diff --git a/.appveyor.yml b/.appveyor.yml deleted file mode 100644 index 41215fe8c..000000000 --- a/.appveyor.yml +++ /dev/null @@ -1,58 +0,0 @@ -version: '{branch}-{build}' - -# Do not build on tags (GitHub only) -skip_tags: true - -image: Visual Studio 2017 - -branches: - except: # blacklist - - coverity_scan - -environment: - REPO_DIR: &REPO_DIR c:\qbittorrent - CACHE_DIR: &CACHE_DIR c:\qbt_cache - - QBT_VER_URL: https://builds.shiki.hu/appveyor/version - QBT_LIB_URL: https://builds.shiki.hu/appveyor/qbt_libraries.7z - -# project directory -clone_folder: *REPO_DIR - -# cache size should < 100MB (after compressing with fastest option): -# see: https://www.appveyor.com/docs/build-cache#save-update-cache-before-build-finishes -cache: - - *CACHE_DIR - -clone_depth: 50 - -install: - # check if library needs update - - appveyor DownloadFile "%QBT_VER_URL%" -FileName "c:\version_new" && SET /P newVersion=<"c:\version_new" - - IF EXIST "%CACHE_DIR%\version" (SET /P oldVersion=<"%CACHE_DIR%\version") - - IF NOT EXIST "%CACHE_DIR%\version" (SET updateCache=1) - - IF NOT "%oldVersion%" == "%newVersion%" (SET updateCache=1) - # update library - - IF "%updateCache%" == "1" (ECHO "--- Will redownload libraries ---" && - RMDIR /S /Q "%CACHE_DIR%" & MKDIR "%CACHE_DIR%" && - appveyor DownloadFile "%QBT_LIB_URL%" -FileName "c:\qbt_lib.7z" && 7z x "c:\qbt_lib.7z" -o"%CACHE_DIR%" > nul && - COPY "c:\version_new" "%CACHE_DIR%\version") - # Qt stay compressed in cache - - 7z x "%CACHE_DIR%\qt5_32.7z" -o"c:\qbt" > nul - -before_build: - # setup env - - CALL "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvars32.bat" - - SET PATH=%PATH%;c:\qbt\qt5_32\bin;%CACHE_DIR%\jom; - # setup project - - COPY /Y "%CACHE_DIR%\winconf.pri" "%REPO_DIR%" - - COPY /Y "%CACHE_DIR%\winconf-msvc.pri" "%REPO_DIR%" - # workarounds - - MKLINK /J "c:\qbt\base" "%CACHE_DIR%\base" - -build_script: - - cd "%REPO_DIR%" - - qmake qbittorrent.pro && cd src && qmake src.pro - - jom -j2 -f Makefile.Release - -test: off diff --git a/.editorconfig b/.editorconfig deleted file mode 100644 index f58613fb0..000000000 --- a/.editorconfig +++ /dev/null @@ -1,12 +0,0 @@ -# EditorConfig is awesome: http://EditorConfig.org - -root = true - -[*] -indent_style = space -indent_size = 4 -insert_final_newline = true -trim_trailing_whitespace = true - -[**.yml] -indent_size = 2 diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md deleted file mode 100644 index c44a90f16..000000000 --- a/.github/ISSUE_TEMPLATE.md +++ /dev/null @@ -1,14 +0,0 @@ -**Please provide the following information** - -### qBittorrent version and Operating System: - -### If on linux, libtorrent and Qt version: - -### What is the problem: - -### What is the expected behavior: - -### Steps to reproduce: - -### Extra info(if any): - diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 48285b2c7..000000000 --- a/.travis.yml +++ /dev/null @@ -1,196 +0,0 @@ -language: cpp - -os: - - linux - - osx -osx_image: xcode7.3 - -env: - matrix: - # Uncomment when Travis upgraded "Ubuntu 12.04 LTS" to a newer version whose repo will have a more up-to-date libtorrent package - #- lt_branch=dist gui=true - #- lt_branch=dist gui=false - - lt_branch=RC_1_0 gui=true build_system=cmake - - lt_branch=RC_1_0 gui=false build_system=cmake - - lt_branch=RC_1_0 gui=true build_system=qmake - - lt_branch=RC_1_0 gui=false build_system=qmake - global: - - secure: "OI9CUjj4lTb0HwwIZU5PbECU3hLlAL6KC8KsbwohG8/O3j5fLcnmDsK4Ad9us5cC39sS11Jcd1kDP2qRcCuST/glVNhLkcjKkiQerOfd5nQ/qL4JYfz/1mfP5mdpz9jHKzpLUIG+TXkbSTjP6VVmsb5KPT+3pKEdRFZB+Pu9+J8=" - - coverity_branch: coverity_scan - -matrix: - allow_failures: - - env: lt_branch=RC_1_0 gui=true build_system=cmake - - env: lt_branch=RC_1_0 gui=false build_system=cmake - -branches: - except: - - search_encoding_windows - - v2_9_x - -notifications: - email: - on_success: change - on_failure: change - -cache: - ccache: true - directories: - - $HOME/hombebrew_cache - -# opt-in Ubuntu Trusty -dist: trusty -# container-based builds -sudo: false - -addons: - coverity_scan: - project: - name: "qbittorrent/qBittorrent" - description: "Build submitted via Travis CI" - build_command_prepend: "./bootstrap.sh && ./configure $qbtconf" - build_command: make - branch_pattern: $coverity_branch - notification_email: sledgehammer999@qbittorrent.org - apt: - sources: - # sources list: https://github.com/travis-ci/apt-source-whitelist/blob/master/ubuntu.json - - ubuntu-toolchain-r-test - #- boost-latest - - sourceline: 'ppa:qbittorrent-team/qbittorrent-stable' - - sourceline: 'ppa:beineri/opt-qt551-trusty' - - sourceline: 'ppa:adrozdoff/cmake' - packages: - # packages list: https://github.com/travis-ci/apt-package-whitelist/blob/master/ubuntu-precise - - [autoconf, automake, colormake] - - [cmake, ninja-build] - - libssl-dev - - [libboost-dev, libboost-system-dev] - - libtorrent-rasterbar-dev - - [qt55base, qt55svg, qt55tools] - - [gcc-6, g++-6] - -before_install: - # only allow specific build for coverity scan, others will stop - - if [ "$TRAVIS_BRANCH" = "$coverity_branch" ] && ! [ "$TRAVIS_OS_NAME" = "linux" -a "$lt_branch" = "RC_1_0" -a "$gui" = true -a "$build_system" = "qmake" ]; then exit ; fi - - - shopt -s expand_aliases - - alias make="colormake -j3" # Using nprocs/2 sometimes may fail (gcc is killed by system) - #- libt_path="$HOME/libt_install" - #- ltconf="$ltconf --prefix="$libt_path" --disable-geoip" - - qbt_path="$HOME/qbt_install" - - qbtconf="$qbtconf --prefix="$qbt_path" PKG_CONFIG_PATH="$libt_path/lib/pkgconfig":/opt/qt55/lib/pkgconfig:$PKG_CONFIG_PATH" - - # options for specific branches - - if [ "$gui" = false ]; then qbtconf="$qbtconf --disable-gui" ; fi - - | - if [ "$TRAVIS_OS_NAME" = "linux" ]; then - # setup virtual display for after_success target - if [ "$gui" = true ]; then 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 ; - - # Qt 5 - PATH=/opt/qt55/bin:${PATH} - - if [ "$build_system" = "cmake" ]; then - COMPILER_VERSION=6 - export CXX="${CXX}-${COMPILER_VERSION}" CC="${CC}-${COMPILER_VERSION}" - fi - fi - - # print settings - - echo $lt_branch - - echo $gui - - echo $build_system - - echo $ltconf - - echo $qbtconf - -install: - #- | - #if [ "$TRAVIS_OS_NAME" = "linux" ]; then - # build libtorrent from source - #if [ "$lt_branch" != "dist" ]; then - #cd "$HOME" && pwd && git clone --depth 1 https://github.com/arvidn/libtorrent.git --branch $lt_branch - #cd libtorrent && ./autotool.sh && ./configure $ltconf && make install - #fi - #fi - - | - if [ "$TRAVIS_OS_NAME" = "osx" ]; then - # dependencies - brew update > /dev/null - brew outdated "pkg-config" || brew upgrade "pkg-config" - brew install colormake ccache zlib qt - PATH="/usr/local/opt/ccache/libexec:$PATH" - brew link --force zlib qt - - wget https://builds.shiki.hu/homebrew/version - if ! cmp --quiet "version" "$HOME/hombebrew_cache/version" ; then - echo "Cached files are different from server. Downloading new ones." - # First delete old files - rm -r "$HOME/hombebrew_cache" - mkdir "$HOME/hombebrew_cache" - cp "version" $HOME/hombebrew_cache - cd "$HOME/hombebrew_cache" - wget https://builds.shiki.hu/homebrew/libtorrent-rasterbar.rb - wget https://builds.shiki.hu/homebrew/libtorrent-rasterbar-1.0.11+git20172003.8736a59adc.el_capitan.bottle.tar.gz - fi - - # Copy custom libtorrent bottle to homebrew's cache so it can find and install it - # Also install our custom libtorrent formula by passing the local path to it - # These 2 files are restored from Travis' cache. - cp "$HOME/hombebrew_cache/libtorrent-rasterbar-1.0.11+git20172003.8736a59adc.el_capitan.bottle.tar.gz" "$(brew --cache)" - brew install "$HOME/hombebrew_cache/libtorrent-rasterbar.rb" - - if [ "$build_system" = "cmake" ]; then - brew outdated cmake || brew upgrade cmake - brew install ninja - - ln -s /usr/local/opt/qt/mkspecs /usr/local/mkspecs - ln -s /usr/local/opt/qt/plugins /usr/local/plugins - fi - - MY_CMAKE_OPENSSL_HINT="-DOPENSSL_ROOT_DIR=/usr/local/opt/openssl/" - fi - - | - if [ "$TRAVIS_BRANCH" != "$coverity_branch" ]; then - export use_ccache=true - ccache -V && ccache --show-stats && ccache --zero-stats - fi - -script: - - if [ "$TRAVIS_BRANCH" = "$coverity_branch" ]; then exit ; fi # skip usual build when running coverity scan - - | - cd "$TRAVIS_BUILD_DIR" - if [ "$build_system" = "cmake" ]; then - mkdir build - cd build - cmake -DGUI=${gui} -DCMAKE_INSTALL_PREFIX="$qbt_path" "$MY_CMAKE_OPENSSL_HINT" \ - -G "Ninja" -DCMAKE_INSTALL_RPATH_USE_LINK_PATH=TRUE .. - BUILD_TOOL="ninja" - fi - if [ "$build_system" = "qmake" ]; then - ./bootstrap.sh && ./configure $qbtconf - if [ "$TRAVIS_OS_NAME" = "osx" ]; then - sed -i "" -e "s/^\(CC.*&&\).*$/\1 $CC/" src/Makefile # workaround for Qt & ccache: https://bugreports.qt.io/browse/QTBUG-31034 - sed -i "" -e "s/^\(CXX.*&&\).*$/\1 $CXX/" src/Makefile - sed -i "" -e 's/^\(CXXFLAGS.*\)$/\1 -Wno-unused-local-typedefs -Wno-inconsistent-missing-override/' src/Makefile - fi - BUILD_TOOL="make" - fi - - $BUILD_TOOL && $BUILD_TOOL install - -after_success: - - if [ "$gui" = true ]; then qbt_exe="qbittorrent" ; else qbt_exe="qbittorrent-nox" ; fi - - if [ "$TRAVIS_OS_NAME" = "linux" ]; then cd "$qbt_path/bin" ; fi - - | - if [ "$TRAVIS_OS_NAME" = "osx" ]; then - if [ "$build_system" = "qmake" ]; then - macdeployqt "$TRAVIS_BUILD_DIR/src/$qbt_exe.app" - cd "$TRAVIS_BUILD_DIR/src/$qbt_exe.app/Contents/MacOS" - else - cd "$qbt_path/$qbt_exe.app/Contents/MacOS" - fi - fi - - ./$qbt_exe --version - -after_script: - - if [ "$use_ccache" = true ]; then ccache --show-stats ; fi diff --git a/.tx/config b/.tx/config deleted file mode 100644 index 42ffa6ffd..000000000 --- a/.tx/config +++ /dev/null @@ -1,19 +0,0 @@ -[main] -host = https://www.transifex.com - -[qbittorrent.qbittorrent_master] -file_filter = src/lang/qbittorrent_.ts -lang_map = pt: pt_PT -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 diff --git a/5B7CC9A2.asc b/5B7CC9A2.asc deleted file mode 100644 index 344f51ccf..000000000 --- a/5B7CC9A2.asc +++ /dev/null @@ -1,92 +0,0 @@ ------BEGIN PGP PUBLIC KEY BLOCK----- -Version: GnuPG v2 - -mQINBFcNIIwBEACpGHvHW9ku7rwCSc2Dv4gh3MO3HPoP7Ba4RiEKwa7SCbPzc0DL -JypV4gNfnrpiO7bWVh5v+otbZTkQeNXWbx6hDUa2e5GCCuJifIu3PxpmMcNJFvvF -nk5QRf6dtz4Sm2x6joYprvsEUjyk+wHC016/0g7yhc/w0sclXlpKK+8Pl5DFrf5C -i5uljy3oJgl54D2yYAvxu3BrdTVKhLVYADUf1Fl3b5pV7VJwr+9wGuTqkORe1rpi -9NGWXUaTmKF8+XAJxlbYIUOZQpQ02clFxz0T7o/+m74N8tK9j7g8H2Q3QwtKi0q1 -gI48LqI/EuZHIaRz/3pEVISlIpWzGqBL/G4I/UtzJLHyvySsqWXAKllKpk97XX77 -XxFy3VL3fR7o4IohAj5fD083X8tuBIP2dxmHzxHTWveKBlEV6C4MdtVRow8ia3lu -RKLz6PF0hBBpebAP4MWAN8cy4ePBCe9BvyI2+3tPgqtlC2tEZLnRru6mtagPi4sj -Yo/iFkSQdTXrxeyrMJh161gsWl16JeAfz4Dq8IBoUA1hXIjfM9FcIv1rCY6Y8JwS -TtWMGYtzIcqE71wZxqnJuyFZkgC14NDTLgUwLf8XJOTWlMW9CY+tStjjw+sNoIPf -p7YQCmss4p5J8flnxH4xJ8ogOHxENidA+Z/J9mtGjxXIXHavPlO3IEg/DwARAQAB -tHFzbGVkZ2VoYW1tZXI5OTkgKFVzZWQgZm9yIHNpZ25pbmcgcUJpdHRvcnJlbnQg -c291cmNlIHRhcmJhbGxzIGFuZCBiaW5hcmllcyB2Mi4pIDxzbGVkZ2VoYW1tZXI5 -OTlAcWJpdHRvcnJlbnQub3JnPokCNwQTAQgAIQUCVw0gjAIbAwULCQgHAgYVCAkK -CwIEFgIDAQIeAQIXgAAKCRBuSi0CW3zJojB2D/0bKlelRDQDtWzfRyxrdhe5pgAt -x1AsN/Cl7h8zlbAw38bL+jQ2/GmtzwzEqPfQc7IFnbeg0PZ58p7Hikj9h6JEhkyA -1qekkriclUmblEwDne3TjPixqgoBfNcDQu74dT08XpM8auFQo31/jJ104903o0O5 -+CPOPn2KTdwpcSpwAVIj/3H96gZWegJDNpdByJUVbzYCt1erJ6I0ZURKhzU1VTJj -ZdEGB2YsvYpt5rsi41IYZZG33jMsPxSDDNJ/MiLXxkn08ZawNET6fnkEJJ37n9Pw -82lTZjFEFU+KTMT7dNjIejWCRgHVLgW8sO2lCPqMiFfWymD/N3sFpBO+UI86y5ds -hfGFAWcgSq9pVjuW4sbX3PntBnoNd+geDD1Ic4rP3jHRe5HuYGhtHO6xv/r7HeY5 -HiShCTSSDBJqFmhfjrCo0nISKnzyxgO/rY9vFlwXsKkTyL7s53ONkjwK34WmGnya -tXdjBWShzAiTfF5hephfBSszmoBG2C8Jcu6P5n4buBY4RCsEa+6jE0R1vCtmpVwx -WrXOeN2kGYMpAkPK1L69Le0FofgUDKlaFMv7KRl4R367xNRukYrsKwVlontJ+Y72 -X5t1BeRn8VSp0IzhssNXM8a4bTE8lvs889DOS2vgWEHIi0iyIesJYWPs4AKUw4rG -EDwWxtTS0a7Rfx3DxLRWc2xlZGdlaGFtbWVyOTk5IChVc2VkIGZvciBzaWduaW5n -IGdpdCBjb21taXRzL3RhZ3MvZXRjLikgPGhhbW1lcmVkOTk5QHFiaXR0b3JyZW50 -Lm9yZz6JAh8EMAEIAAkFAlhie1ICHQAACgkQbkotAlt8yaILIhAAp25o1BbUG2Zk -At3cSrTFnZSCA7nEygbSUv1Uek33JZfY0Apw5qEM8lQCMZk+mhdrSQCYUJcQlruN -zJcJf4CH+VGE23xkI3Kf0nGp9Cjn/q6b1hLIPe5rimvw5pTAejFtebcYY/ZJIB8Z -H1ebuzfqBZ/9k7eYTarZ/ZsgG8YptB0RXBQWOMaSEKwdeo2m7HXHgK3blQiqbuJJ -uyPbid01Wus4AVN47/FKgDNswPs8irYZsu5yakgpi2KLycGDtSiN5XFHI4xbC0zM -srR7Cz0/fC+klhGcuxbw0V0It7UUIitgCcTPHXkukUU8i2+AGMyKa1HjchsXDdLg -DIs6KIurp2ve7znKOz7h1aX8cOBmB/QYeYAx9jRRkePMIRT8V1lRwfvJlJxx1+G3 -e2gJLjqTN8a08KHHjdY/S0ZFERxSlmOym2uf/y6di1ipDPxo8xvDuS5kDbdZLC0t -XijlsH8ONK27KNuWhucG8zHzKQvnPw2qN06SZq4FjbSmAkkuYs56heLEXMzFr75k -SE8rUoQQ+ABG9gU46GEvKlZxqSwXgGnb1X6K7h8svjMh/NlAU358p8Sra4Ru5tz4 -jUu9MoVEw5Lbjcrsnp6/4Kk1Q2ckBNt43nv8/+C7NsC3xi6BrOInuaKHZ4QsTuzJ -m1/A4zlKRnUi6T98DXfIYnNuV9NSmAWJAjkEEwEIACMFAlhiemMCGwMHCwkIBwMC -AQYVCAIJCgsEFgIDAQIeAQIXgAAKCRBuSi0CW3zJor6yD/9N2U0INx0nYpGkmvah -yVG/vw2S6hhKK+03AN+RrtddNRg4aBf/gmOvRWQhAmFnXOBA7fO09wgcljaV5tVb -MYyYZvHhK0o2/sli2p/M5N8ZxchRHypjxUSEyG9ZQ06QG5DVhh4HtM8nIN+UcwTV -C5QjyoWZvHf+tNroyFeh7zT+w4kX1VxgynTQr5LGdYsrVA3CFyT3zsBWV3dMae23 -22CHOirsBBLwairHUsWW+BdThT3MkKYpTEV0jkH4OyAXhJYcS5IjjtKQ8UpZE9dw -f4saJ0TnXNe7goPRZtH7UjPwfVbtYK4y8QklWUTRxgoBxNwSC5X7Flg+3xXxE/VU -U4cehyRkH64i7MJDoFkqh5JtjkgIz+kuTTXb7xR0Wf+JXrGMybZTR8xth2TEMC20 -1FT5L5+0vH1WRzL7bhlaU3EXyCnoH8sDvMEClZbibbew+rf7fC3tFU41ohUT0HDl -zlyfVjRvBHWMTgfpWKBV2m/qP941xTJ9VHxOlAB02XKUZYwFt07CpH+yjMOCOzA4 -cTPBD3mGRuft0V0BJ8bA5bcTly/GBciRX0Y5oIeHZGgq2czb0sywSYT6mPoQMFNM -B+Cwr4pm90r1DMMfW518onF2itwyN/Id0FsWDhsLJHKluBJw52C3OnxCuToVutTm -xntqpPVv62LaeVeWQqxIieTJErRQc2xlZGdlaGFtbWVyXzk5OSAoVXNlZCBmb3Ig -c2lnbmluZyBnaXQgY29tbWl0cy90YWdzL2V0YykgPGhhbW1lcmVkOTk5QGdtYWls -LmNvbT6JAjkEEwEIACMFAlhifeICGwMHCwkIBwMCAQYVCAIJCgsEFgIDAQIeAQIX -gAAKCRBuSi0CW3zJolcCD/9xPBNEkFtnhTW89th0TFZnB5oykCQjyefquvQs8KWT -C92/1VizHi4ZxDehHWP9IKVWT3ZJthj5ZXBSedyl1tHnwkyrUYBW9roQwtDWPncK -pXl/HsE6p3q6EIus+g6YJo4UvYachJFAZATZp1WDBPIswziHGzaL0tndFWZuVM8V -QD0tfPQsS1qCDVv6+B1JWZDnA1JzdSG/uzPhL95q/ff6JmNbfSAVedK2PyqYshnC -KWBx6Yna/0ColBuDFho8+bDuHPQcM35xyjPosVD7moXQiY4yMAJ+VzwEBaCFleI0 -RBWw8/+qyoFqfIKwdq8G+7I9LjWpBiN2+uQBZ+OAvsMWyRShLopxt3JluPTtL6xb -Ca6dglOdlaOS/A6FK7u05k/8kQMDS5Jq2/rpfTPRl1/weCaJZgfRIBosk1Mon/pR -p1zd0abM4t7BcGQpwSkKAmqlKCrWf886EFQT0CJTBo8q7pzgpVraWWPVsmAOdkfU -YcKBgz1A2uMSAxypkSzaDZkIVj6I7gwiGk7IMYx1OK7Ev46h/x4Z7kgT0y3DYYOq -ggVEKQ+15Krn7bZ35s8vbZdfnVKPSXdCC8jkIMBmGmRX6cgZZ3OXZlrrHht5icgJ -5Z2d1M4JUoEZVUr2xNZkkaMk01NAIpGgKvIS6yHuj6vE4GMJ+A/qEW6J60/3YHRe -0bkCDQRXDSCMARAAqMIVJizEJp205c546IN75xeYiFszNXcs3768IY8bOoWj+rTw -t2wIwtL/3O5K2dG79CSt2H5o6BPKmq43tOO60YW3Yk3m9BB/gnAVqk0QOPr5O8+y -eBzdElU8CZh6y6zZMWugSkNmTDm6jZzPhgNjcjrit/dl9+0DGqJQcqoD8WzEWNcW -rMHVz9cDewnLSVkwR758mZMaIiL7R10MZ++tNrC0j69UINqx+9z1r1J07+NNnxqS -TxVRcbjPYtM9E+tUiVFS2HPWN9ShVDkBAEdoWh90qzRaMiFl2NGNGOD1iHx/xr06 -RMeGEEXt2vhSlhfMW2YQW+UD2jzlFbARf53v39MUKKscGuIpBhxGw3JCq4l6qLW/ -bDkgnoXlOhZDmhQm6OpsjAyk9IEdd3ponSc7yYD3mUkJKR9eTaALD5t6TQGyNHak -b4UfoXtE2RR78cbPlLIwag7eQ8GsNA+dfjowmOZdojx3ROsHZdGQwb0YFLjuKAus -A3TY+lCfbS6kzE2iI2DuaW+3dICcLrYuibbVb0CBNHyD+8KEtczdur/wm0lhqyVJ -kGyZKZT8C2cPxywKgy1Rn6F8Yfmj0Lna3nvtaZu0ZUS4/8Lit5PcOso1lSmYBuD6 -yq+GEAMCnUmn1Pm8eZRMlxxQuTPvyJKQrRDhbtAAr472MSnoJKlS4SfaUF0AEQEA -AYkCHwQYAQgACQUCVw0gjAIbDAAKCRBuSi0CW3zJomZDD/9IJmzd5hiEzntlp84p -yIJcfyIRe4KImvldAy6T02OSIbF1HzCNnwmqIPob6MOdMZ+KNwMK0htRkrRr/zM0 -34+lBiWKZt+tVYHu49ioTYXEjAc5qDJE09Sq7HceQnhgE48f1n54XGT5G2w5gw+/ -a8Qn1SceE44VwXafL3E1gKaOrrsb1UH/AJhp+W4VMu+7bLXu7h1tN6v2PhvCYvBt -3zyy8Q8xfJ2x7/D1lbF8ATJAiZ/km9x5bRm7OGRliVYaUe1nyR42fZOj3CBmAR0+ -lZLgjriqdMXrs+qlBbrmAhkn0XPQXAeaPifKoKIGDAUWIsqDHqM7imMGT+MR9APf -Sw8M4enOJWL+HnKpVBEARCEDpaFpJ3u7QRucFybpEhvIymoNftyw+urId2Eg2K33 -NypeZo3M1K2LC65f2Ta7f/sZcIDUTbgW+m334fgVl1KptDA5DX3U9lTci7mi4uPu -AFtbWrB1di4jYrxXYuzFm5g4xTb0Hw3kYIB6WXF+I7i0JaGOTHxPC5X5lIAZrYrk -xh+1n1Y1CY+TC8JcTzwORJIbFFm9tD/BHXa4849k4DVvFYCZkhq+/56FKZfoVByh -B+x+2GaMlsBm1uPniO4lAakFPpIi0kaap4UVayQ/7ak+BhscAIHZUy6NtgZkuvW3 -xdpwp07LYo2ilhMI8RnzmtoRmg== -=UBeB ------END PGP PUBLIC KEY BLOCK----- diff --git a/AUTHORS b/AUTHORS deleted file mode 100644 index 22b9bbea7..000000000 --- a/AUTHORS +++ /dev/null @@ -1,132 +0,0 @@ -Current maintainer: -* Sledgehammer999 - -Original author: -* Christophe Dumez - -Contributors: -* Vladimir Golovnev -* Stefanos Antaris -* Mohammad Dib -* Mirco Chinelli -* Ishan Arora -* Arnaud Demaizière -* Grigis Gaëtan -* Christian Kandeler -* Silvan Scherrer -* Nick Tiskov - -Code from other projects: -* files src/qtsingleapplication/* src/lineedit/* - copyright: Nokia Corporation - license: LGPL - -* files src/ico.cpp src/ico.h - copyright: Malte Starostik - license: LGPL - -* files src/search_engine/socks.py - copyright: Dan Haim - license: BSD - -* file src/stacktrace_win.h - copyright: Quassel Project - license: GPLv2/3 - -Images Authors: -* files: src/icons/*.png - copyright: Gnome Icon Theme - license: GPLv2 - url: http://ftp.acc.umu.se/pub/GNOME/sources/gnome-icon-theme - -* files: src/oxygen/*.png - copyright: Oxygen Icon Theme (KDE) - license: LGPL - url: http://www.oxygen-icons.org - -* files: src/icons/flags/*.png - copyright: Mark James - license: Public Domain - url: http://www.famfamfam.com - -* files: src/icons/skin/*.png - files: src/menuicons/YYxYY/*.png - copyright: Mateusz Tobola - license: GPLv2 - -* file: src/icons/skin/tabs.gif - copyright: Greg Houston - license: MIT - -* file: src/icons/skin/qbittorrent_mono* - copyright: Daniel Eguren - license: LGPL - -* file: src/search_engine/engines/btjunkie.png - copyright: Downloaded from btjunkie.org - -* file: src/search_engine/engines/isohunt.png - copyright: Downloaded from isohunt.com - -* file: src/search_engine/engines/mininova.png - copyright: Downloaded from mininova.org - -* file: src/search_engine/engines/piratebay.png - copyright: Downloaded from thepiratebay.org - -* file: src/search_engine/engines/torrentreactor.png - copyright: Downloaded from torrentreactor.net - -* file: src/icons/oxygen/checked.png - copyright: Victor Buinsky - -* file: src/icons/skin/ratio.png - copyright: Fatcow Web Hosting - license: Creative Commons Attribution 3.0 License - url: http://www.fatcow.com/free-icons - -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) - - 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) - - Croatian: Oliver Mucafir (oliver.untwist@gmail.com) - - Czech: Jirka Vilim (web@tets.cz) and Petr Cernobila abr(Transifex) - - 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) - - French: Christophe Dumez (chris@qbittorrent.org) - - Galician: Marcos Lans (marcoslansgarza@gmail.com) and antiparvos(Transifex) - - Georgian: Beqa Arabuli (arabulibeqa@yahoo.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) - - 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) - - Korean: Jin Woo Sin (jin828sin@users.sourceforge.net) - - Lithuanian: Naglis Jonaitis (njonaitis@gmail.com) - - Norwegian: Tomaso - - Polish: Mariusz Fik (fisiu@opensuse.org) - - Portuguese: Sérgio Marques smarquespt(Transifex) - - Portuguese(Brazil): Nick Marinho (nickmarinho@gmail.com) - - Romanian: Obada Denis (obadadenis@users.sourceforge.net), Adrian Gabor Adriannho(Transifex) and Mihai Coman z0id(Transifex) - - Russian: Nick Khazov (m2k3d0n at users.sourceforge.net), Alexey Morsov (samurai@ricom.ru), Nick Tiskov Dayman(daymansmail (at) gmail (dot) com), Dmitry DmitryKX(Transifex) and kraleksandr kraleksandr(Transifex) - - 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) - - Turkish: Hasan Yilmaz (iletisim@hedefturkce.com) - - Ukrainian: Oleh Prypin (blaxpirit@gmail.com) and zubr139(Transifex) - - Vietnamese: Anh Phan ppanhh(Transifex) - license: GPLv2 diff --git a/CMakeLists.txt b/CMakeLists.txt deleted file mode 100644 index 3cf7687be..000000000 --- a/CMakeLists.txt +++ /dev/null @@ -1,61 +0,0 @@ -cmake_minimum_required(VERSION 3.5) -cmake_policy(VERSION 3.5) - -list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules) -include(FunctionReadVersion) - -read_version("${CMAKE_CURRENT_SOURCE_DIR}/version.pri" VER_MAJOR VER_MINOR VER_BUGFIX VER_BUILD VER_STATUS) -# message(STATUS "Project version is: ${VER_MAJOR}.${VER_MINOR}.${VER_BUGFIX}.${VER_BUILD} (${VER_STATUS})") - -project(qBittorrent VERSION ${VER_MAJOR}.${VER_MINOR}.${VER_BUGFIX}.${VER_BUILD}) - -set(PROJECT_VERSION "${VER_MAJOR}.${VER_MINOR}.${VER_BUGFIX}") - -if (NOT VER_BUILD EQUAL 0) - set(PROJECT_VERSION "${PROJECT_VERSION}.${VER_BUILD}") -endif() - -set(PROJECT_VERSION "${PROJECT_VERSION}${VER_STATUS}") - -add_definitions(-DQBT_VERSION_MAJOR=${VER_MAJOR}) -add_definitions(-DQBT_VERSION_MINOR=${VER_MINOR}) -add_definitions(-DQBT_VERSION_BUGFIX=${VER_BUGFIX}) -add_definitions(-DQBT_VERSION_BUILD=${VER_BUILD}) - -# os2 { -# DEFINES += DQBT_VERSION=\'\"v$${PROJECT_VERSION}\"\' -# DEFINES += DQBT_VERSION_2=\'\"$${PROJECT_VERSION}\"\' -# } else { -add_definitions(-DQBT_VERSION="v${PROJECT_VERSION}") -add_definitions(-DQBT_VERSION_2="${PROJECT_VERSION}") -# } - -if (UNIX AND NOT APPLE) - include(GNUInstallDirs) -endif (UNIX AND NOT APPLE) - -if(WIN32) - include(winconf) -endif(WIN32) - -# we need options here, because they are used not only in "src" subdir, but in the "dist" dir too -include(CMakeDependentOption) - -option(SYSTEM_QTSINGLEAPPLICATION - "Use the system qtsingleapplication library or shipped one otherwise") - -option(GUI "Allows to disable GUI for headless running. Disables QtDBus and the GeoIP Database" ON) - -option(WEBUI "Allows to disable the WebUI." ON) - -if (WIN32) - option(STACKTRACE_WIN "") -else (WIN32) - cmake_dependent_option(SYSTEMD "Install the systemd service file (headless only)" OFF - "NOT GUI" OFF) - cmake_dependent_option(DBUS "Enable use of QtDBus (GUI only)" ON "GUI" OFF) -endif(WIN32) - - -add_subdirectory(src) -add_subdirectory(dist) diff --git a/CODING_GUIDELINES.md b/CODING_GUIDELINES.md deleted file mode 100644 index d17888a3b..000000000 --- a/CODING_GUIDELINES.md +++ /dev/null @@ -1,308 +0,0 @@ -All new code must follow the following coding guidelines. -If you make changes in a file that still uses another coding style, make sure that you follow these guidelines for your changes instead. -**Note 1:** I will not take your head if you forget and use another style. However, most probably the request will be delayed until you fix your coding style. -**Note 2:** You can use the `uncrustify` program/tool to clean up any source file. Use it with the `uncrustify.cfg` configuration file found in the root folder. -**Note 3:** There is also a style for QtCreator but it doesn't cover all cases. In QtCreator `Tools->Options...->C++->Code Style->Import...` and choose the `codingStyleQtCreator.xml` file found in the root folder. - -### 1. Curly braces ### -#### a. Function blocks, class/struct definitions, namespaces #### -```c++ -int myFunction(int a) -{ - //code -} - -void myFunction() {} // empty body - -MyClass::MyClass(int *parent) - : m_parent(parent) -{ - //initialize -} - -int MyClass::myMethod(int a) -{ - //code -} - -class MyOtherClass -{ -public: - //code - -protected: - //code - -private: - //code -}; - -namespace Name -{ - //code -} - -// Lambdas -[](int arg1, int arg2) -> bool { return arg1 < arg2; } - -[this](int arg) -{ - this->acc += arg; -} -``` - -#### b. Other code blocks #### -```c++ -if (condition) { - //code -} - -for (int a = 0; a < b; ++b) { - //code -} - -switch (a) { -case 1: - //blah -case 2: - //blah -default: - //blah -} -``` - -#### c. Blocks in switch's case labels #### -```c++ -switch (var) { -case 1: { - //declare local variables - //code - } - break; -case 2: { - //declare local variables - //code - } - break; -default: - //code -} -``` - -#### d. Brace enclosed initializers #### -Unlike single-line functions, you must not insert spaces between the brackets and concluded expressions.
-But you must insert a space between the variable name and initializer. -```c++ -Class obj {}; // empty -Class obj {expr}; -Class obj {expr1, /*...,*/ exprN}; -QVariantMap map {{"key1", 5}, {"key2", 10}}; -``` - -### 2. If blocks ### -#### a. Multiple tests #### -```c++ -if (condition) { - //code -} -else if (condition) { - //code -} -else { - //code -} -``` -The `else if`/`else` must be on their own lines. - -#### b. Single statement if blocks #### -**Most** single statement if blocks should look like this: -```c++ -if (condition) - a = a + b; -``` - -One acceptable exception to this **can be** `return`, `break` or `continue` statements, provided that the test condition isn't very long. However you can choose to use the first rule instead. -```c++ -a = myFunction(); -b = a * 1500; - -if (b > 0) return; -c = 100 / b; -``` - -#### c. Using curly braces for single statement if blocks #### - -However, there are cases where curly braces for single statement if blocks **should** be used. -* If some branch needs braces then all others should use them. Unless you have multiple `else if` in a row and the one needing the braces is only for a very small sub-block of code. -* Another exception would be when we have nested if blocks or generally multiple levels of code that affect code readability. - -Generally it will depend on the particular piece of code and would be determined on how readable that piece of code is. **If in doubt** always use braces if one of the above exceptions applies. - -### 3. Indentation ### -4 spaces. - -### 4. File encoding and line endings. ### - -UTF-8 and Unix-like line ending (LF). Unless some platform specific files need other encodings/line endings. - -### 5. Initialization lists. ### -Initialization lists should be vertical. This will allow for more easily readable diffs. The initialization colon should be indented and in its own line along with first argument. The rest of the arguments should be indented too and have the comma prepended. -```c++ -myClass::myClass(int a, int b, int c, int d) - : m_a(a) - , m_b(b) - , m_c(c) - , m_d(d) -{ - //code -} -``` - -### 6. Enums. ### -Enums should be vertical. This will allow for more easily readable diffs. The members should be indented. -```c++ -enum Days -{ - Monday, - Tuesday, - Wednesday, - Thursday, - Friday, - Saturday, - Sunday -}; -``` - -### 7. Names. ### -All names should be camelCased. - -#### a. Type names and namespaces #### -Type names and namespaces start with Upper case letter (except POD types). -```c++ -class ClassName {}; - -struct StructName {}; - -enum EnumName {}; - -typedef QList SomeList; - -namespace NamespaceName -{ -} -``` - -#### b. Variable names #### -Variable names start with lower case letter. -```c++ -int myVar; -``` - -#### c. Private member variable names #### -Private member variable names start with lower case letter and should have ```m_``` prefix. -```c++ -class MyClass -{ - int m_myVar; -} -``` - -### 8. Header inclusion order. ### -The headers should be placed in the following order: - 1. Module header (in .cpp) - 2. System/Qt/Boost etc. headers (splitted in subcategories if you have many). - 3. Application headers, starting from *Base* headers. - -The headers should be ordered alphabetically within each group (subgroup).
-
-Example: -```c++ -// examplewidget.cpp - -#include "examplewidget.h" - -#include -#include - -#include -#include -#include -#include - -#include - -#include "base/bittorrent/session.h" -#include "base/bittorrent/infohash.h" -#include "base/utils/fs.h" -#include "base/utils/misc.h" -#include "base/utils/string.h" -#include "ui_examplewidget.h" - -``` - -### 9. Misc. ### - -* Line breaks for long lines with operation: - -```c++ -a += "b" - + "c" - + "d"; -``` - -* **auto** keyword - -We allow the use of the **auto** keyword only where it is strictly necessary -(for example, to declare a lambda object, etc.), or where it **enhances** the readability of the code. -Declarations for which one can gather enough information about the object interface (type) from its name -or the usage pattern (an iterator or a loop variable are good examples of clear patterns) -or the right part of the expression nicely fit here.
-
-When weighing whether to use an auto-typed variable please think about potential reviewers of your code, -who will read it as a plain diff (on github.com, for instance). Please make sure that such reviewers can -understand the code completely and without excessive effort.
-
-Some valid use cases: -```c++ -template -void doSomethingWithList(const List &list) -{ - foreach (const auto &item, list) { - // we don't know item type here so we use 'auto' keyword - // do something with item - } -} - -for (auto it = container.begin(), end = container.end(); it != end; ++it) { - // we don't need to know the exact iterator type, - // because all iterators have the same interface -} - -auto spinBox = static_cast(sender()); -// we know the variable type based on the right-hand expression -``` - -* Space around operations eg `a = b + c` or `a=b+c`: - -Before and after the assignment and other binary (and ternary) operators there should be a space.
-There should not be a space between increment/decrement and its operand.
-Some valid use cases: -```c++ -a += 20; -a = (b <= MAX_B ? b : MAX_B); -++a; -b--; - -for (int a = 0; a < b; ++b) { - // code -} -``` - -* private/public/protected must not be indented - -* Preprocessor commands must go at line start - -* Method definitions aren't allowed in header files - -### 10. Not covered above ### -If something isn't covered above, just follow the same style the file you are editing has. If that particular detail isn't present in the file you are editing, then use whatever the rest of the project uses. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md deleted file mode 100644 index 0f9bbb1fa..000000000 --- a/CONTRIBUTING.md +++ /dev/null @@ -1,35 +0,0 @@ -# Filing an issue - -### Must read -* If you aren't sure, you can ask on the [**forum**](http://forum.qbittorrent.org) or read our [**wiki**](http://wiki.qbittorrent.org) first. -* Do a quick **search**. Others might already reported the issue. -* Write in **English**! -* Provide **version** information: (You can find version numbers at menu `Help -> About -> Libraries`) - ``` - qBittorrent: - Qt: - libtorrent: - boost: - OS version: - ``` -* Provide **steps** to reproduce the problem, it will be easier to pinpoint the fault. -* **Screenshots**! A screenshot is worth a thousand words. just upload it. [(How?)](https://help.github.com/articles/file-attachments-on-issues-and-pull-requests) - -### Good to know -* **Be patient**. The dev team is small and resource limited. Devs finding their free time, analyzing the problem and fixing the issue, it all takes time. :clock3: -* If you can code, why not become a **contributor** by fixing the issue and open a pull request? :wink: -* Harsh words or threats won't help your situation. What's worse, your complain will (very likely) to be **ignored**. :fearful: - - -# Opening a pull request - -### Must read -* Read our [**coding guidelines**](https://github.com/qbittorrent/qBittorrent/blob/master/CODING_GUIDELINES.md). There are some scripts to help you: [uncrustify script](https://raw.githubusercontent.com/qbittorrent/qBittorrent/master/uncrustify.cfg), [astyle script](https://gist.github.com/Chocobo1/539cee860d1eef0acfa6), [(related thread)](https://github.com/qbittorrent/qBittorrent/issues/2192). -* Keep the title **short** and provide a **clear** description about what your pull request does. -* Provide **screenshots** for UI related changes. -* Keep your git commit history **clean** and **precise**. Commits like `xxx fixup` should not appear. -* If your commit fix a reported issue (for example #4134), add the following message to the commit `Closes #4134.`. Example [here](https://github.com/qbittorrent/qBittorrent/commit/a74bac20c4e8de9776bf9bb77fdc7526135d1988). - -### Good to know -* **Search** pull request history! Others might already implemented your idea and is waiting to be merged (or got rejected already). Save your precious time by doing a search first. -* When resolving merge conflicts, do `git rebase `, don't do `git pull`. Then you can start fixing the conflicts. Here is a good explanation: [link](https://www.atlassian.com/git/tutorials/merging-vs-rebasing). diff --git a/COPYING b/COPYING deleted file mode 100644 index 3a486c265..000000000 --- a/COPYING +++ /dev/null @@ -1,294 +0,0 @@ -qBittorrent is licensed under the GNU General Public License version 2 with the -addition of the following special exception: - -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. - ----------- - - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 - - Copyright (C) 1989, 1991 Free Software Foundation, Inc. - 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -License is intended to guarantee your freedom to share and change free -software--to make sure the software is free for all its users. This -General Public License applies to most of the Free Software -Foundation's software and to any other program whose authors commit to -using it. (Some other Free Software Foundation software is covered by -the GNU Library General Public License instead.) You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -this service if you wish), that you receive source code or can get it -if you want it, that you can change the software or use pieces of it -in new free programs; and that you know you can do these things. - - To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if you -distribute copies of the software, or if you modify it. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must give the recipients all the rights that -you have. You must make sure that they, too, receive or can get the -source code. And you must show them these terms so they know their -rights. - - We protect your rights with two steps: (1) copyright the software, and -(2) offer you this license which gives you legal permission to copy, -distribute and/or modify the software. - - Also, for each author's protection and ours, we want to make certain -that everyone understands that there is no warranty for this free -software. If the software is modified by someone else and passed on, we -want its recipients to know that what they have is not the original, so -that any problems introduced by others will not reflect on the original -authors' reputations. - - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that redistributors of a free -program will individually obtain patent licenses, in effect making the -program proprietary. To prevent this, we have made it clear that any -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 - - 0. This License applies to any program or other work which contains -a notice placed by the copyright holder saying it may be distributed -under the terms of this General Public License. The "Program", below, -refers to any such program or work, and a "work based on the Program" -means either the Program or any derivative work under copyright law: -that is to say, a work containing the Program or a portion of it, -either verbatim or with modifications and/or translated into another -language. (Hereinafter, translation is included without limitation in -the term "modification".) Each licensee is addressed as "you". - -Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running the Program is not restricted, and the output from the Program -is covered only if its contents constitute a work based on the -Program (independent of having been made by running the Program). -Whether that is true depends on what the Program does. - - 1. You may copy and distribute verbatim copies of the Program's -source code as you receive it, in any medium, provided that you -conspicuously and appropriately publish on each copy an appropriate -copyright notice and disclaimer of warranty; keep intact all the -notices that refer to this License and to the absence of any warranty; -and give any other recipients of the Program a copy of this License -along with the Program. - -You may charge a fee for the physical act of transferring a copy, and -you may at your option offer warranty protection in exchange for a fee. - - 2. You may modify your copy or copies of the Program or any portion -of it, thus forming a work based on the Program, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) You must cause the modified files to carry prominent notices - stating that you changed the files and the date of any change. - - b) You must cause any work that you distribute or publish, that in - whole or in part contains or is derived from the Program or any - part thereof, to be licensed as a whole at no charge to all third - parties under the terms of this License. - - c) If the modified program normally reads commands interactively - when run, you must cause it, when started running for such - interactive use in the most ordinary way, to print or display an - announcement including an appropriate copyright notice and a - notice that there is no warranty (or else, saying that you provide - a warranty) and that users may redistribute the program under - these conditions, and telling the user how to view a copy of this - 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 -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Program, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Program. - -In addition, mere aggregation of another work not based on the Program -with the Program (or with a work based on the Program) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may copy and distribute the Program (or a work based on it, -under Section 2) in object code or executable form under the terms of -Sections 1 and 2 above provided that you also do one of the following: - - a) Accompany it with the complete corresponding machine-readable - source code, which must be distributed under the terms of Sections - 1 and 2 above on a medium customarily used for software interchange; or, - - b) Accompany it with a written offer, valid for at least three - years, to give any third party, for a charge no more than your - cost of physically performing source distribution, a complete - machine-readable copy of the corresponding source code, to be - distributed under the terms of Sections 1 and 2 above on a medium - customarily used for software interchange; or, - - c) Accompany it with the information you received as to the offer - to distribute corresponding source code. (This alternative is - allowed only for noncommercial distribution and only if you - received the program in object code or executable form with such - an offer, in accord with Subsection b above.) - -The source code for a work means the preferred form of the work for -making modifications to it. For an executable work, complete source -code means all the source code for all modules it contains, plus any -associated interface definition files, plus the scripts used to -control compilation and installation of the executable. However, as a -special exception, the source code distributed need not include -anything that is normally distributed (in either source or binary -form) with the major components (compiler, kernel, and so on) of the -operating system on which the executable runs, unless that component -itself accompanies the executable. - -If distribution of executable or object code is made by offering -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 -void, and will automatically terminate your rights under this License. -However, parties who have received copies, or rights, from you under -this License will not have their licenses terminated so long as such -parties remain in full compliance. - - 5. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Program or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Program (or any work based on the -Program), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Program or works based on it. - - 6. Each time you redistribute the Program (or any work based on the -Program), the recipient automatically receives a license from the -original licensor to copy, distribute or modify the Program subject to -these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties to -this License. - - 7. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Program at all. For example, if a patent -license would not permit royalty-free redistribution of the Program by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Program. - -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply and the section as a whole is intended to apply in other -circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system, which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -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 -may add an explicit geographical distribution limitation excluding -those countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. - - 9. The Free Software Foundation may publish revised and/or new versions -of the General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - -Each version is given a distinguishing version number. If the Program -specifies a version number of this License which applies to it and "any -later version", you have the option of following the terms and conditions -either of that version or of any later version published by the Free -Software Foundation. If the Program does not specify a version number of -this License, you may choose any version ever published by the Free Software -Foundation. - - 10. If you wish to incorporate parts of the Program into other free -programs whose distribution conditions are different, write to the author -to ask for permission. For software which is copyrighted by the Free -Software Foundation, write to the Free Software Foundation; we sometimes -make exceptions for this. Our decision will be guided by the two goals -of preserving the free status of all derivatives of our free software and -of promoting the sharing and reuse of software generally. - - NO WARRANTY - - 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY -FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN -OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES -PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED -OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS -TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE -PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, -REPAIR OR CORRECTION. - - 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR -REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING -OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED -TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER -PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGES. - - END OF TERMS AND CONDITIONS diff --git a/Changelog b/Changelog deleted file mode 100644 index 2d969b432..000000000 --- a/Changelog +++ /dev/null @@ -1,2109 +0,0 @@ -Unreleased - sledgehammer999 - v3.4.0 - - FEATURE: New icon theme with SVG source, so we can scale it appropriately in the future. (Bert Verhelst) - - FEATURE: Drop Qt 4 support. Raise minimum Qt version to 5.5.1 (evsh) - - FEATURE: UI for managing locally banned IP list (dzmat) - - FEATURE: Support for specifying where to save/load config files. Support for portable mode. (evsh) - - FEATURE: It is now possible to pass options via ENV variables instead of cmd options. (evsh) - - FEATURE: Allow to strip subfolder in multifile torrents. (glassez, sledgehammer999) - - FEATURE: Allow cmd args to specify options when adding torrents. (Brian Kendall) - - FEATURE: Widget for showing filesystem paths while typing. Used in the Add New Torrent and Options dialogs. (evsh) - - FEATURE: Trackerlist: Allow to toggle columns (thalieht) - - FEATURE: Add availability column to torrent content model and torrent properties window (evsh) - - FEATURE: Implemented share limit by seeding time (naikel) - - FEATURE: Revamp Torrent creator (Chocobo1) - - FEATURE: Enable drag n drop to create torrent on mainwindow (Chocobo1) - - FEATURE: Add show/hide statusbar option (takiz) - - FEATURE: Show number of pieces. Closes #6774. (Chocobo1) - - FEATURE: Allow to select & delete multiple entries in "Manage Cookies" dialog (Chocobo1) - - FEATURE: Fetch Favicons via google as a final fallback (KingLucius) - - FEATURE: Add a Tags (multi-label) feature to the GUI. Closes #13. (tgregerson) - - FEATURE: Use the system icons for each file type in the Content tab (evsh) - - FEATURE: Use SVG files for monochrome tray icons. Closes #6085. (evsh) - - BUGFIX: Adjust icons names to better fit FDO scheme (evsh) - - BUGFIX: Optimized IP filter parsing, making blazingly fast (sledgehammer999, evsh) - - BUGFIX: Fix dialogs didn't position on the correct screen which qBittorrent window is on. Closes #1690, #2474, #3538. (Chocobo1) - - BUGFIX: Refactor and improve StatusBar (glassez) - - BUGFIX: Set expiration date for newly added cookie to +2 years from now, instead of +99 years. (Chocobo1) - - BUGFIX: Don't create subfolder inside temp folder (glassez) - - BUGFIX: Don't remove shared temp folder (glassez) - - BUGFIX: Don't replace existing files when relocating torrent (glassez) - - COSMETIC: Trackerlist: Set text alignment of columns with numbers to the right (thalieht) - - COSMETIC: Enable alternatingRowColors for "Manage Cookie" dialog (Chocobo1) - - WEBUI: Allow to load/use ECDSA certificate in webUI. (Chocobo1) - - WEBUI: Add copy options to webui context menu (addresses #6815) (#7036) (Tom Piccirello) - - WEBUI: Set torrent location from webui context menu (addresses #6815) (#7062) (Tom Piccirello) - - SEARCH: Use explicit class for search plugin versions (evsh) - - SEARCH: Remove all search plugins from repo. There is another repo named 'search-plugins'. (sledgehammer999) - - SEARCH: Update the backend when a new plugin favicon is downloaded. (sledgehammer999) - - RSS: Redesigned RSS subsystem (glassez) - - RSS: Do not use hardcoded colors in RSS feed view (evsh) - - WINDOWS: Installer detects running process when it is 64-bit (vlakoff) - - MACOS: Various macOS UI improvements (vit9696) - - MACOS: Fix main menu item location on macOS (vit9696) - - OTHER: Use new classes/methods from libtorrent and stop using deprecate ones. (glassez) - - OTHER: Various string fixes (Allan Nordhøy, sledgehammer999) - -* Thu Jun 01 2017 - sledgehammer999 - v3.3.13 - - BUGFIX: Fixed UI glitch about torrent numbers in the sidepanel. Fixes #6454. (evsh) - - BUGFIX: Fix downloaded/uploaded columns were not highlighted properly when selected. (Chocobo1) - - BUGFIX: Always draw background in files list and search result list (Chocobo1) - - BUGFIX: Remove torrent temp folder if it becomes unneeded (glassez) - - BUGFIX: Remove torrent temp folder when torrent is deleted (glassez) - - BUGFIX: Setup DPI at startup (Chocobo1) - - BUGFIX: Do not attempt to show detailed tooltips without torrent metadata. Closes #6768. (evsh) - - BUGFIX: Better detection of already present files when adding a torrent. (fbriere) - - BUGFIX: Fix double click on system tray icon causing program to open and minimize immediately. Closes #5826. (Chocobo1) - - BUGIFX: Fix categories sorting in AddNewTorrentDialog. Partially fixes #6708. (fbriere) - - BUGFIX: Set "category" column as case-insensitive in transfer list. (fbriere) - - BUGFIX: Properly sort categories case-insensitively in filter widget. Closes #6708. (fbriere) - - BUGFIX: Fix renaming files is not case sensitive on Windows platform. Closes #5128. (Chocobo1) - - BUGFIX: Fix crash in download piece bar (evsh) - - BUGFIX: Fix focusing on the previously opened dialog didn't work (Chocobo1) - - WEBUI: Bugfix: `RequestParser::splitMultipartData` drop extra trailing newline. (OpenGG) - - WEBUI: Add `skip_checking` and `paused` to `/command/download` and `/command/upload` (OpenGG) - - WEBUI: Fix checkbox hidden. Closes #6642. (Chocobo1) - - WEBUI: Implement http persistence connection. Max simultaneous connection limit set to 500. This also release allocated memory of Connection instances at runtime instead of at program shutdown. (Chocobo1) - - WEBUI: Always send Content-Length header. (Chocobo1) - - WEBUI: Send Date http header (Chocobo1) - - WEBUI: Fix "Content-Encoding" header is always created. (Chocobo1) - - WEBUI: Implement robust checking for gzip encoding and revise gzip compressing/decompressing code. (Chocobo1) - - WEBUI: Make the context obligatory for translatable strings. Also delete duplicate strings from extra translations. (sledgehammer999) - - WEBUI: Use translatable strings in Statistics dialog. (sledgehammer999) - - WEBUI: Add missing unit sizes in misc.js (sledgehammer999) - - WEBUI: Use the same layout in the Speed tab in preferences as the GUI. (sledgehammer999) - - WEBUI: Return status indicating if at least one torrent was successfully added (Thomas Piccirello) - - WEBUI: Increase the number of digits after the decimal point (thalieht) - - WEBUI: Use less permissive Content Security Policy (Thomas Piccirello) - - WEBUI: Fix connection status icon too large. Closes #6804. (Chocobo1) - - WEBUI: Cosmetic fixes for WebUI upload and download windows (naikel) - - WEBUI: Fix slow filtering in WebUI. (naikel) - - WEBUI: Make cookie parsing robust (Chocobo1) - - WEBUI: New API for getting torrent piece info (Chocobo1) - - WEBUI: Implement Cross-Site Request Forgery defense. Due to this the HTTP referer header is now expected in (almost) all HTTP requests. qBittorrent will drop the request sent without the referer header. That's why we bump the API_VERSION_MIN too. (reported by OpenGG, fixed by Chocobo1) - - SEARCH: Update demonoid, legittorrents plugins (ngosang) - - SEARCH: Remove mininova, ExtraTorrent plugins (ngosang, KingLucius) - - SEARCH: Add btdb plugin (ngosang) - - WINDOWS: Updated Spanish, Ukrainian, German, Chinese languages of the installer. (ngosang, evsh, schnurlos, wevsty) - - LINUX: Rename .desktop and appdata files to match executable name. Fixes #6625. (evsh) - - MACOS: Fix UI responsiveness after AddNewTorrentDialog received metadata. (Brian Kendall) - -* Thu Apr 06 2017 - sledgehammer999 - v3.3.12 - - FEATURE: Indicate bitness in stackstrace and about dialog. Closes #6172. (sledgehammer999) - - BUGFIX: Fix incomplete type compile error with Qt4 (Chocobo1) - - BUGFIX: Fix compile error: ‘escape’ is not a member of ‘Qt’ (Chocobo1) - - BUGFIX: Use system locale to format dates/time/etc (sledgehammer999) - - BUGFIX: Follow http user-agent format (Chocobo1) - - BUGFIX: Fix cancel "Set location" causes files move to installation dir. (Chocobo1) - - WEBUI: Improve performance of updating 'progress' column (buinsky) - - WEBUI: Implement statistics window in web UI (FranciscoPombal) - - WEBUI: fixed "remaining" column in WebUI (FranciscoPombal) - - WEBUI: Set HttpOnly attribute to SID cookie (Chocobo1) - - WEBUI: Fire up the timer to clean inactive sessions (Chocobo1) - - WEBUI: Set cookie SID value to empty on logout (Chocobo1) - - WINDOWS: Make the installer DPI aware (regs01) - - WINDOWS: Set exit code to 0 on install/uninstall success. Fixes problem with silent installations. (Chocobo1) - - WINDOWS: The 64-bit installer refuses to install on 32-bit systems. (sledgehammer999) - - WINDOWS: The 64-bit installer uses the correct "Program Files" now. Detection will not work if you install on top of previous installer. (sledgehammer999) - - WINDOWS: Fix running the uninstaller if the user chose a different path in the installer. Closes #6080. (sledgehammer999) - - LINUX: Add keywords to the .desktop file. (sledgehammer999) - - LINUX: Update stuff in appdata.xml and run 'appstream-utl upgrade' on it. (sledgehammer999) - - OTHER: Replace rand() by a true uniform distribution generator (Chocobo1) - - OTHER: Change our user-agent format as indicated earlier in the news section (Chocobo1) - - OTHER: cmake: fix OSX bundle creation (evsh) - -* Fri Mar 03 2017 - sledgehammer999 - v3.3.11 - - FEATURE: Always show progress and remaining bytes for unselected files. (sledgehammer999) - - FEATURE: Allow to change priority for unselected files through the combobox like it is done via the context menu. (sledgehammer999) - - FEATURE: Remove settings to exchange trackers. It wasn't used by non-libtorrent clients. Also it has a privacy risk and you might be DDoSing someone. (sledgehammer999) - - FEATURE: Put temp files in .qBittorrent directory. Closes #4462. (Chocobo1) - - FEATURE: Use the numbers from tracker scrape response. Closes #5048, #6117. (Chocobo1) - - FEATURE: Implement category filter widget. Show categories in tree mode when subcategories are enabled. (glassez) - - FEATURE: Allow to toggle columns in searchtab (thalieht) - - FEATURE: PeerList: allow to hide zero values for the "uploaded" and "downloaded" columns (thalieht) - - FEATURE: Display more information in tracker tab (ngosang) - - FEATURE: Use Ctrl+F to search torrents. Closes #5797. (Tim Delaney) - - FEATURE: Transferlist: add hotkeys for double click and recheck selected torrents (thalieht) - - FEATURE: Add hotkey for execution log tab, Trackerlist, Peerlist etc (thalieht) - - FEATURE: Seperate seeds from peers for DHT, PeX and LSD (thalieht) - - BUGFIX: Do not remove added files unconditionally. Closes #6248 (Eugene Shalygin) - - BUGFIX: Ignore mouse wheel events in Advanced Settings. Closes #866. (Chocobo1) - - BUGFIX: Add queue repair code. It should fix missing torrents after restarting. (Eugene Shalygin, nxd4) - - BUGFIX: Fetch torrent status when generating final fastresume data. It should fix missing torrents after restarting. (Eugene Shalygin) - - BUGFIX: Fix queue overload for add torrent at session start. It should fix missing torrents after restarting. (falco) - - BUGFIX: After files relocate, don't remove the old folder even if it is empty. (Chocobo1) - - BUGFIX: Fix finding 'English' item in language dropdown menu when an unrecognized locale is requested. Closes #6109. (sledgehammer999) - - BUGIFX: Speedlimitdlg: raise slider default value to 10000. Closes #6150. (Chocobo1) - - BUGFIX: TransferListWidget: keep columns width even if they are hidden on qBittorrent startup (unless something goes wrong) (thalieht) - - BUGFIX: fix index overflow for torrents with invalid meta data or empty progress (Falco) - - BUGFIX: Immediately update torrent_status after manipulating super seeding mode. Partially fixes #6072. (sledgehammer999) - - BUGFIX: Use case-insensitive comparsion for torrent content window. Closes #6327. (Chocobo1) - - BUGFIX: Fixed sort order for datetime columns with empty values (closes #2988) (Vladimir Sinenko) - - BUGFIX: Disable proxy in WebUI HTTP server. Closes #6349. (Eugene Shalygin) - - COSMETIC: Use a disabled progressbar's palette for unselected files. (sledgehammer999) - - COSMETIC: Support fallback when selecting theme icons (Eugene Shalygin) - - COSMETIC: Do not resize SVG icons (Eugene Shalygin) - - COSMETIC: Align text to the right in columns that handle numbers for PeerList and SearchTab (thalieht) - - COSMETIC: Increased number of digits after the decimal point for Gibibytes and above (thalieht) - - COSMETIC: Use non-breaking spaces between numbers and units (thalieht) - - WEBUI: Fix proxy type bug (Oke Atime) - - WEBUI: Use the correct value for KEY_TORRENT_NUM_COMPLETE/KEY_TORRENT_NUM_INCOMPLETE (Chocobo1) - - WEBUI: Make torrents table scrollable horizontally (buinsky) - - WEBUI: Make torrent peers table scrollable horizontally (buinsky) - - WEBUI: Add tooltips to dynamic table header (buinsky) - - WEBUI: Implement dynamic table columns resizing, reordering and hiding (buinsky) - - WEBUI: Add some missing columns to dynamic tables (buinsky) - - WEBUI: Make too tall menus scrollable (buinksy) - - WEBUI: Prevent text wrapping in menus (buinsky) - - WEBUI: Add a vertical separator between columns (buinsky) - - WEBUI: Implement resizable progress bar in "Done" column (buinsky) - - WEBUI: Fix scrollbar covers menu item with long text (buinsky) - - WEBUI: Remove 300px limit of column width (buinsky) - - WEBUI: Avoid lags in firefox on resizing progress column (buinsky) - - WEBUI: Fix category in torrent upload. Closes #6260 (ngosang) - - WEBUI: Turn off port forwarding of WebUI by default for GUI users (Chocobo1) - - WEBUI: Exclude insecure ciphers. Fixes security issues reported by @beardog108 privately. (Chocobo1) - - WEBUI: Avoid clickjacking attacks. Fixes security issues reported by @beardog108 privately. (ngosang) - - WEBUI: Add X-XSS-Protection, X-Content-Type-Options, CSP header. Fixes security issues reported by @beardog108 privately. (Chocobo1) - - WEBUI: Escape various values that might contain injected html. Fixes security issues reported by @beardog108 privately. (Chocobo1) - - WEBUI: Bump API_VERSION to 12. - - SEARCH: Update extratorrent plugin. Closes #6261 (ngosang) - - SEARCH: SearchTab: can now save sorting column changes (thalieht) - - SEARCH: Use case-insensitive sort for Name column in Search tab. Closes #407. (Chocobo1) - - RSS: Fix tab order in RSS downloader. Closes #6164. (Tim Delaney) - - RSS: Move old RSS items to separate config file. Closes #6167. (Tim Delaney) - - RSS: Episode filter code refactoring (Tim Delaney) - - RSS: Allow resetting rule to no category. Closes #5539. (Tim Delaney) - - RSS: Save rule on enable/disable even if not selected. Closes #6163. (Tim Delaney) - - RSS: Allow | in RSS must contain. Closes #6171. (Tim Delaney) - - RSS: RSS use red text to indicate invalid filter. Closes #6165. (Tim Delaney) - - RSS: Allow episode zero (special) and leading zeroes in RSS episode filter. (Tim Delaney) - - RSS: RSS parse torrent episodes like 1x01 as well as S01E01. Closes #2749. (Tim Delaney) - - RSS: RSS allow infinite range to extend beyond current season. Closes #800, #3876, #6170. (Tim Delaney) - - RSS: Improve UI responsiveness during RSS downloading. Closes #873, #1089, #1235, #5423. (Tim Delaney) - - RSS: Show name of feed list and sort rules in editor. Closes #3782, #6281. (Tim Delaney) - - RSS: Fix regex matching. Closes #6337. (Tim Delaney) - - MACOS: Fix qbittorrent-nox build (Oke Atime) - - LINUX: fixes default indicator name (Bilal Elmoussaoui) - - OTHER: Workaround problem with moc from Qt4 and #if (Eugene Shalygin) - - OTHER: Print warning to the user if stacktrace contains no function names (Eugene Shalygin) - - OTHER: Various cmake fixes (Eugene Shalygin) - - OTHER: Fix finding qmake in configure when cross-compiling (Zach Bacon) - -* Sat Dec 17 2016 - sledgehammer999 - v3.3.10 - - BUGFIX: Fix share ratio limiting. Broken by commit 259b5e51c49b744. Closes #6039 #6048. (sledgehammer999) - - BUGFIX: Case insensitive sort for client column. Closes #6054. (Oke Atime) - - BUGFIX: Make resume/pause menu items clickable. Closes #6040. (Oke Atime) - - WINDOWS: Make the updater to look for the x64 installer if running x64 version. (sledgehammer999) - -* Wed Dec 14 2016 - sledgehammer999 - v3.3.9 - - BUGFIX: Fix slider for per torrent speed limits when no global speed limit has been set. Closes #6046. (sledgehammer999) - - BUGFIX: Fix GUI for proxy settings. Closes #6045. (sledgehammer999) - - OSX: Correctly migrate settings/rss/usage stats in macOS. Closes #6041. (sledgehammer999) - -* Wed Dec 14 2016 - sledgehammer999 - v3.3.8 - - FEATURE: Start using new libtorrent 1.1.x APIs (needs at least 1.1.2). Still unofficial support. (glassez, sledgehammer999) - - FEATURE: Add a new DHT bootstrap node run by libtorrent author arvidn. (sledgehammer999) - - FEATURE: Option to disable tracker's favicon download. (sledgehammer999) - - FEATURE: Shift + scroll = horizontal scroll. Closes #5980. Only for TransferListWidget, PeerListWidget. (Chocobo1) - - BUGFIX: Actually set new path as default when checkBox is enabled in Add New Torrent dialog. (erikssm) - - BUGFIX: Properly fix the handling of default save path store/load. (sledgehammer999) - - BUGFIX: Fix crash when restoring from tray. Closes #5854. (Chocobo1) - - BUGFIX: Export torrents added only after the setting was enabled. (sledgehammer999) - - BUGFIX: Delete old rss favicon before assigning new one. (sledgehammer999) - - BUGFIX: Don't revert save path value in the Dialog when metadata are received. Closes #5482. (sledgehammer999) - - BUGFIX: Don't ever stop seeding forced torrents. Closes #5784. (sledgehammer999) - - BUGFIX: Fix potential crash in TransferList widget. Closes #5873. (Chocobo1) - - BUGFIX: Sort torrent names case insensitively. (Yez Ezey) - - BUGFIX: Fix mistake in getting values for sorting in TransferList widget. (Anton Lashkov) - - BUGFIX: Fix memory leaks. (dzmat, Chocobo1) - - WEBUI: Fix webui port overflow. (thalieht) - - WEBUI: Changed meaning of the value of the 'dl_limit', 'up_limit', 'alt_dl_limit' and 'alt_up_limit' tokens. The value is expressed in bytes and not in KiB. (sledgehammer999) - - WEBUI: Don't request client SSL certificate. Closes #3883. (borouhin) - - WEBUI: Bump API_VERSION and API_VERSION_MIN to 11. - - SEARCH: Fixed extratorrent search not working Closes #5736 #5753. (Yez Ezey) - - SEARCH: Update Demonoid plugin. (ngosang) - - SEARCH: Remove TorrentReactor plugin. (ngosang) - - SEARCH: Fix python auto install, deletion of installer and use 3.5.x series for Vista+. Closes #5871. (sledgehammer999) - - SEARCH: Set /usr/local/bin before default PATH on macOS. closes #5639 #5571. This enables finding newer python installs. (Yez Ezey) - - COSMETIC: Log: set embedded Tracker [OFF] msg type as info. (thalieht) - - COSMETIC: Remove (mostly) useless log warnings about tracker's favicon. (sledgehammer999) - - COSMETIC: Change RSS view layout to horizontal. Closes #5920. (Chocobo1) - - OSX: Fix crash on exit using Qt4. (Yez Ezey) - - OSX: Change QSettings to IniFormat on macOS. Closes #5770 #5808. (Yez Ezey) - - LINUX: Workaround a Qt5 bug which results in a flood of network interface change singals. (Eugene Shalygin) - - OTHER: Turkish translation for installer. (Burak Yavuz) - - OTHER: Update portugueseBR for installer. (DaRKSoM) - - OTHER: Update portuguese for installer. (EdwardLinux) - - OTHER: Add --disable-qt-dbus to configure if $host_os is macOS. (Yez Ezey) - - OTHER: New translations: Icelandic, Latvian, Malay, Occitan, Uzbek. - - OTHER: A whole lot of code refactoring by various people. - -* Sun Sep 11 2016 - sledgehammer999 - v3.3.7 - - FEATURE: Delete torrent+files with Shift+Delete (pieniacy) - - BUGFIX: Fix 6-hour speedplot point push rate. Close #5545 (Daniel Segesdi) - - BUGFIX: Avoid spawning a new explorer.exe process when selecting "Open containing folder". Closes #5564. (Chocobo1) - - BUGFIX: Fix loading of new geoip db due to an artificial size limit. (SagePtr) - - BUGFIX: Better error handling and logging with smtp communication. (Brian Kendall) - - SEARCH: Remove KickassTorrents search engine (ngosang) - - SEARCH: Remove BTDigg search engine (ngosang) - - SEARCH: Update Torrentz search engine (ngosang) - -* Wed Jul 20 2016 - sledgehammer999 - v3.3.6 - - BUGFIX: Do not create save folder in advance (glassez) - - BUGFIX: Fix upper-bound limit of command line for "Run External Program" in Windows. Closes #5399. (Chocobo1) - - BUGFIX: Invoke system's cmd.exe directly. (Chocobo1) - - BUGFIX: Workaround space issues in file path for running external program on Windows. (Chocobo1) - - BUGFIX: Fix icons are missing when using RTL languages in Options dialog. Closes #5398. (Chocobo1) - -* Mon Jun 20 2016 - sledgehammer999 - v3.3.5 - - FEATURE: Implement Torrent Management Mode(TMM) (glassez) - - FEATURE: New cookies management dialog and various related fixes (glassez) - - FEATURE: Use unique temp directories (temp_path/). Closes #5154. (glassez) - - FEATURE: Display notifications when a torrent is added. Closes #334 and #915. (sledgehammer999) - - FEATURE: Sort labels with natural sort algorithm in the right-click menu. Closes #3919. (Chocobo1) - - FEATURE: Add option to automatically remove .torrent files upon adding (Eugene Shalygin) - - FEATURE: Add option to bind directly to an IP instead of using a network Interface (Sjoerd van der Berg, sledgehammer999) - - FEATURE: Detailed tooltips on the progress and availability bars in the General button of each torrent. (Eugene Shalygin) - - FEATURE: Let user able to specifiy a filter when choosing an IP filter file (Chocobo1) - - FEATURE: Improve usability of "Run External Program". Users can write (platform dependent) shell scripts now. (Chocobo1) - - PERFORMANCE: Optimize drawing in speed graph (Anton Lashkov, Chocobo1) - - BUGFIX: Fix memory leak. (sledgehammer999) - - BUGFIX: Fix resizing bug in "add torrent dialog". Closes #5036. (Chocobo1) - - BUGFIX: Fix qBittorrent doesn't exit immediately when "all donwloads are done -> exit" option enabled. (glassez, Chocobo1) - - BUGFIX: Display the filepath when a torrent fails to load. Closes #100 and #805. (sledgehammer999) - - BUGFIX: Fix Add tracker dialog empty trackers (ngosang) - - BUGFIX: Fix Add tracker dialog URL download (ngosang) - - BUGFIX: Fix torrent adding with existing data (glassez) - - BUGFIX: Try to find incomplete files for new torrent (glassez) - - BUGFIX: Fix rechecking after torrent is finished (glassez) - - BUGFIX: Fix duplicate network interfaces. Closes #5131 (ngosang) - - BUGFIX: Fix .!qB extension is added when disabled (glassez) - - BUGFIX: Fix "IP Filtering - Apply to trackers" wasn't being applied. Closes #5217. (Chocobo1) - - BUGFIX: Don't resize the Country column needlessly (thalieht) - - BUGFIX: Fix crashing when exiting the program while the Options window was showing. Closes #4871, #5049. (Chocobo1) - - BUGFIX: Fix parsing of eMule .DAT filters. Closes #5281. (thalieht, sledgehammer999) - - WEBUI: Implement in setting/removing/showing categories. (buinsky) - - WEBUI: Add 'Added on' column in Webui. Closes #5145,#1092,#738 (Ibrahim Tachijian) - - WEBUI: Add command to get the logs (pmzqla) - - WEBUI: Expose Add trackers feature (pmzqla) - - WEBUI: Bump API_VERSION and API_VERSION_MIN to 10. (sledgehammer999) - - SEARCH: Implement search filters in the proxy model. (Eugene Shalygin) - - SEARCH: Optimize widgets inside of the search tab (Eugene Shalygin) - - SEARCH: Remove duplicated code from search tab and widget (Eugene Shalygin) - - SEARCH: Use nova2dl.py script instead of DownloadManager. Closes #5026. (glassez) - - SEARCH: Various UI cleanups and optimizations. (Chocobo1, ngosang) - - SEARCH: Fix Torrentz, Mininova, LegitTorrents, PirateBay plugins (ngosang) - - SEARCH: Fix toolbar resizing when m_searchFilter appears/disappears. Closes #5120. (Chocobo1) - - SEARCH: Use QPalette::LinkVisited color for downloaded items in search results (Eugene Shalygin) - - SEARCH: Update Python version requirements (min 2.7.9 / 3.3.0) (ngosang) - - SEARCH: Remove filters from Torrentreactor, BTDigg and Demonoid. It is done in the GUI now. (ngosang) - - RSS: default refresh interval to 30 mins (botmtl) - - COSMETIC: Improve TransferListDelegate::sizeHint (Chocobo1) - - COSMETIC: Fix long text clipping. Closes #5091. (Chocobo1) - - COSMETIC: Minor change in Stats dialog (ngosang) - - COSMETIC: Fix Update all button height in RSS tab (ngosang) - - COSMETIC: Disable `comboHideZero` when `checkHideZero` is unchecked. (Chocobo1) - - COSMETIC: Disable `checkLimituTPConnections` when `checkuTP` is unchecked. (Chocobo1) - - COSMETIC: Enable word wrap for "Run external program" help text (Chocobo1) - - COSMETIC: Fix mutually exclusive radio buttons can be unselected. (Chocobo1) - - COSMETIC: Set About tab font-size to default (zywo) - - COSMETIC: Improve wordings in "Auto download torrent" section (Chocobo1) - - COSMETIC: Change "Auto download torrent" default save path to "default location". (Chocobo1) - - COSMETIC: Change ambiguous text "Copy selected" to "Copy IP:port" (Chocobo1) - - COSMETIC: Improve error messages for "Auto download torrents" (Chocobo1) - - COSMETIC: Slim down 'Downloads' page of options window. (sledgehammer999) - - COSMETIC: Cleanup Connection page in Option dialog. Closes #845. (Chocobo1) - - COSMETIC: Fix reload button size is not the same size as "..." button in options dialog. (Chocobo1) - - WINDOWS: Let Windows handle all widgets scaling. (Chocobo1) - - WINDOWS: Improve stack trace for windows by including source filenames and line numbers (SeigneurSerpent) - - OSX: Fix qt5 bundle on OSX. Closes #4014. (sledgehammer999) - - OTHER: Make AddNewTorrentDialog behavior uniform (glassez) - - OTHER: Optimize the shutdown dialog (Chocobo1) - - OTHER: Enable access to shutdown functions when configured with `--disable-gui` option (Chocobo1) - - OTHER: Delete Import Torrent Dialog. Just use the "add new torrent" dialog. (glassez) - - OTHER: Optimize code for natural sorting (Chocobo1) - - OTHER: Use new alert dispathing API for libtorrent 1.1.x (glassez) - - OTHER: Fix gcc 6 compilation with qmake. See #5237. (sledgehammer999) - -* Tue Mar 29 2016 - sledgehammer999 - v3.3.4 - - FEATURE: Download more pieces in "Download first and last pieces first" feature (ngosang) - - FEATURE: Unlock first column in peerlist too (thalieht) - - FEATURE: Add "Hide zero values" option. Closes #3543. (Chocobo1) - - FEATURE: Add a "remaining" column to the torrent content model (Ben Lau) - - FEATURE: Allow to toggle columns in peerlist (thalieht) - - FEATURE: Add ability to filter log messages by type. (sledgehammer999) - - FEATURE: Add ability to write the log to file. (sledgehammer999) - - FEATURE: Add 'never show again' checkbox/pref to auto-exit confirm dialog (d3fault, sledgehammer999, Chocobo1) - - PERFORMANCE: Perform fastresume data saving in separate thread (glassez) - - PERFORMANCE: Optimize session startup (glassez) - - BUGFIX: Save resume data using QSaveFile (Qt5 only). This reduces chances of corrupt files. (glassez) - - BUGFIX: Check torrent file permissions before opening (birdie-github) - - BUGFIX: Always update native session's announce_ip setting (Jesse Connop) - - BUGFIX: Fix loading *.magnet files from watched folders. Closes #4701. (sledgehammer999) - - BUGFIX: Fix upgrade corrupted fastresume file (glassez) - - BUGFIX: Fix total values for "Seeds" & "Peers" (Chocobo1) - - BUGFIX: Fix potential race condition. Closes #4742. (Chocobo1) - - BUGFIX: Don't merge trackers for private torrents. Closes #2928. (sledgehammer999) - - BUGFIX: Fix double buttons in "Add New Torrent" dialog. (Chocobo1) - - BUGFIX: Fix malformed date header in email. Closes #4828. (Chocobo1) - - BUGFIX: Save "Run external program" input as is. Closes #4830. (Chocobo1) - - BUGFIX: Enable "filename" column in peers list again. Crash is fixed now. (Eugene Shalygin) - - BUGFIX: Don't display warning when folder name stayed the same after rename. (sledgehammer999) - - BUGFIX: Fix selection of Portuguese translation files. (sledgehammer999) - - BUGFIX: Fix selection of Esperanto locale. Closes #4999. (sledgehammer999) - - BUGFIX: Fix "caja" file manager opens the file instead of opens the directory. Closes #5003. (Chocobo1) - - BUGFIX: Fix periodic latency spikes on Windows with WiFi connections. Closes #4209. (sledgehammer999) - - BUGFIX: Potentially fix a random crash coming from the sidepanel (sledgehammer999, ngosang) - - WEBUI: Fix max_ratio precision. Closes #4707 (ngosang) - - WEBUI: Fix JavaScript exception on WebUI load (buinsky) - - WEBUI: Fix translation (buinsky) - - WEBUI: Submit the label in the new label dialog on pressing enter key (buinsky) - - WEBUI: Check WebUI username and password length. Closes #4191 (ngosang) - - WEBUI: Minor changes in CSS styles (ngosang) - - WEBUI: Add "Added on" and "Completion on" fields to query/torrents query response (buinsky) - - WEBUI: Do not try to parse request message when content-length is 0 (Dan Seminara) - - WEBUI: Support SSL certificate bundles. Issue #4896. (UnDifferential) - - WEBUI: Change the order of the values of speed labels (buinsky) - - WEBUI: Bump WebUI API_VERSION - - SEARCH: Update PirateBay plugin. (ngosang) - - SEARCH: Added TorLock search engine (ngosang) - - COSMETIC: Fix splash screen staying on top of all windows. Closes #1391. (sledgehammer999) - - COSMETIC: Rearrange advanced settings (Chocobo1) - - COSMETIC: Cleanup "about" dialog (Chocobo1) - - COSMETIC: Cleanup "Add New Torrent" dialog (Chocobo1) - - COSMETIC: Use short date in addnewtorrentdialog (Chocobo1) - - COSMETIC: Change "Free disk space" to "Free space on disk" (Chocobo1) - - COSMETIC: Let OS handle DPI scaling for now. Should let Qt do the work when it's more mature. (Chocobo1) - - COSMETIC: Put comment_lbl in QScrollArea. Closes #4881. (Chocobo1) - - COSMETIC: Change the order of the values of speed labels (buinsky) - - COSMETIC: Cleanup the Log tab (Chocobo1) - - COSMETIC: Cleanup the RSS tab (Chocobo1) - - OTHER: Set "Show splash screen on start up" option default to off (Chocobo1) - - OTHER: Support for cross-compilation with MXE (Boris Nagaev) - - OTHER: Add basic (and unofficial) cmake support (Eugene Shalygin) - - OTHER: Move some URLs overs to https (funkydude) - - OTHER: Add appveyor support (Chocobo1) - - OTHER: TravisCI: switch to Trusty image. Closes #4953. (Chocobo1) - - OTHER: Many other internal code restructuring, cleaning and fixing. - -* Thu Jan 21 2016 - sledgehammer999 - v3.3.3 - - BUGFIX: Temporarily disable "filename" column of peers view. It has a bug that causes frequent crashes. See issue #4597. - - WEBUI: Move style of dynamic table header to CSS (buinsky) - - WEBUI: Fix unnecessary updates of torrent peers table (buinsky) - -* Tue Jan 19 2016 - sledgehammer999 - v3.3.2 - - FEATURE: Add a new column to peers list that shows list of files which are downloaded right now from a peer. (evsh) - - FEATURE: Improve the "Watch folders" UI. Closes #4300. You'll need to redo your watch folders settings. (sledgehammer999, glassez) - - FEATURE: Support loading multiple magnets/hashes/urls per .magnet file in the watched folder(one per line). Closes #217. (sledgehammer999) - - BUGFIX: Fix resolution of peer host names. Closes #4307. (sledgehammer999) - - BUGFIX: Don't recheck twice after 'Force Recheck' with 'Recheck torrents on completion' enabled. Closes #4274. (sledgehammer999) - - BUGFIX: Don't apply some settings again if they weren't changed. Closes #4278. (sledgehammer999) - - BUGFIX: Update ISO 3166 country codes. Closes #3942. (Chocobo1) - - BUGFIX: Fix moving torrents to Temp after app restart. Closes #4434. (glassez) - - BUGFIX: Fix crash in favicon code due to null pointer dereference. (glassez) - - BUGFIX: Move the 'qBittorrent-resume' file even when no magnets were recovered. Also make sure to rename it with a unique name. Closes #4334. (sledgehammer999) - - BUGFIX: Don't add the watch folder before the user closes the Preferences window. (sledgehammer999) - - BUGFIX: Remove watch folders permanently only if the user accepts the Preferences dialog. (sledgehammer999) - - BUGFIX: Better handling of cookies in the download manager (glassez) - - BUGFIX: Use the download manager for RSS, the program updater and the dns updater. (glassez) - - BUGFIX: Fix reconfigure additional trackers (glassez) - - BUGFIX: Fix loading corrupted .fastresume file (glassez) - - WEBUI: Show filtered torrents number (buinsky) - - WEBUI: Fix paused, active and inactive filters (buinsky) - - WEBUI: Fixed bug when uploading several files and only the last one was considered. (naikel) - - WEBUI: Implemented WebUI interface for the new Watched Folders feature (naikel) - - WEBUI: Fix possible showing "qBittorrent client is not reachable" message on deleting torrents. (buinsky) - - WEBUI: Don't show "Limit download speed" menu item for downloaded torrents. (buinsky) - - WEBUI: Update webui run program parameters (buinsky) - - WEBUI: Allow to remove the label assigned to a torrent (pmzqla) - - WEBUI: Repair translation (buinsky) - - WEBUI: Remember last opened tab (buinsky) - - WEBUI: Bump WebUI API_VERSION and API_VERSION_MIN. - - COSMETIC: Update native names for Chinese locales. Closes #4381. (sledgehammer999) - - COSMETIC: Rename column header in Content view. (Chocobo1) - - COSMETIC: Edit speed limits and upload ratio icons (buinsky) - - SEARCH: Code refactoring. (glassez) - - SEARCH: Fix PirateBay plugin implementation for Python 3 (ngosang) - - SEARCH: Update PirateBay URL. Closes #4470 (ngosang) - - RSS: Code refactoring. (glassez) - - LINUX: Fix build. (sledgehammer999) - - OSX: Set qBittorrent as default torrent app in Mac OS (dmitry.viktorov) - - OTHER: Fix lrelease version due to the default Qt5 build (Fabio Alessandro Locati) - - OTHER: Indicate to the user that he's going to download the new version. Indicate from the installer that the old version was detected and no settings will be deleted. Closes #4320. (sledgehammer999) - - OTHER: Don't require GUI libs for qt4 nox build. Closes #4404. (sledgehammer999) - - OTHER: Fix cross-compilation (bnagaev) - - OTHER: Allow GeoIP in nox builds (glassez) - -* Tue Dec 08 2015 - sledgehammer999 - v3.3.1 - - FEATURE: New "Set as default label" option in Add torrent dialog. (takiz) - - FEATURE: Support wildcards for filtering torrent list and torrent content (vlakoff) - - BUGFIX: Fix -1 is displayed instead of the infinity symbol (Chocobo1) - - BUGFIX: Fix scan dirs settings saving. Closes #4254, #4239, #4187. (glassez) - - BUGFIX: Exported torrents now use name instead of hash. Closes #4205. (glassez) - - BUGFIX: Improve upgrade to v3.3.0. Now undownloaded magnets will be migrated too. Fixes #4195. (glassez) - - BUGFIX: Fix wrong encoding for listen failed error message. (glassez) - - BUGFIX: Fix RSS not automarking articles as read. (glassez) - - BUGFIX: Fix possible deadlock during application exit. (sledgehammer999) - - WEBUI: Cookies support on WebUI when downloading torrent from a URL. (Naikel Aparicio) - - WEBUI: Modified download and upload windows to allow autocompletion of browsers. (Naikel Aparicio) - - WEBUI: Fixed the spinner in the WebUI upload page. (Naikel Aparicio) - - WEBUI: Modified height of the WebUI download page. (Naikel Aparicio) - - WEBUI: Fixed all the JavaScript functions for download and upload pages. (Naikel Aparicio) - - WEBUI: Add seeds tab to WebUI (buinsky) - - WEBUI: Bump WebUI API_VERSION. - - COSMETIC: Cleanup "Trackers", "Peers", "HTTP Sources", "Speed" and "Content" page layout (Chocobo1) - - COSMETIC: Reduce mainwindow border width (Chocobo1) - - COSMETIC: Use QLineEdit built-in ClearButton (Qt5 only) (Chocobo1) - - COSMETIC: Change text description for half-open connection (Chocobo1) - - OTHER: Change update URL to FossHub. Closes #4188. (sledgehammer999) - -* Sun Nov 29 2015 - sledgehammer999 - v3.3.0 - - FEATURE: Huge core code refactoring. Problems with labels, temp folders etc should be eliminated. Smoother UI should be observed too. (glassez) - - FEATURE: Speed graph (Anton Lashkov) - - FEATURE: Add multiple peers in Peers addition dialog. Closes #1563, #2245, #3133, #1419, #3287, #1419 (ngosang) - - FEATURE: Allow to copy all peers with a keyboard shortcut (ngosang) - - FEATURE: Use GeoIP2 database, allows for country resolution of IPv6 peers. It is no longer embedded in the program but downloaded and updated monthly. (glassez) - - FEATURE: Add more "Run External Program" parameters, closes #3053, #238, #1291, #1522. (Chocobo1, glassez) - - FEATURE: Add an option to allow the use of proxies only for torrents. Closes #2701. (pmzqla) - - FEATURE: Detect network interface state changes. It should detect VPN connection resets. (Pawel Polewicz) - - FEATURE: Switch to using c++11 (glassez) - - FEATURE: Automatically add trackers to new downloads. (ngosang) - - FEATURE: You can now choose the path to download for watched folders. (dsimakov, sledgehammer999) - - FEATURE: Switch to Qt5 by default. - - BUGFIX: Fix progress calculation in Content tab. Closes #2639 Closes #2752 (ngosang) - - BUGFIX: Fix label filter. Closes #3429. (glassez) - - BUGFIX: Fix "Run External Program Launches too Early" issue, closes #2107. (Chocobo1) - - BUGFIX: Don't remove torrent contents parent folder, even it is empty. Closes #2244. (Chocobo1) - - BUGFIX: Always apply filter for manually banned IPs. Related #3988. (sledgehammer999) - - BUGFIX: Fix reporting of tracker status. Closes #3101. (sledgehammer999) - - BUGFIX: Don't connect to "any interface" when the configured network interface is missing. Closes #3943, #2741, #1159, #844 and #143. (sledgehammer999) - - BUGFIX: Fix reordering of first column with Qt5. Closes #2835. (sledgehammer999) - - COSMETIC: Add back "qBittorrent" in program updater title, closes #3549. (Chocobo1) - - COSMETIC: Use infinity symbol rather than -1 for nb_connections (pmzqla) - - COSMETIC: Move uTP options to it's own section (Chocobo1) - - COSMETIC: Fix availability bar & progress bar height being too small on high DPI displays (Chocobo1) - - COSMETIC: Fix availability label & progress label clipped on high DPI displays, closes #3237. (Chocobo1) - - COSMETIC: Add tooltips/legend for availability bar & progress bar (Chocobo1) - - COSMETIC: Use theme color for background in PropertiesWidget (Chocobo1) - - COSMETIC: Replace horizontal line with border in bottom panel (Chocobo1) - - COSMETIC: Various visual changes in the side panel. (Chocobo1) - - COSMETIC: Use thin border for transfer list (Chocobo1) - - COSMETIC: Make URL in "Add Torrent File..." clickable. Closes #3928. (Chocobo1) - - COSMETIC: New view for errored torrents. (sledgehammer999) - - WEBUI: Add information in General tab (ngosang) - - WEBUI: Reorder "Super seeding mode" option in right click menu (ngosang) - - WEBUI: Clean up JavaScript code (ngosang) - - WEBUI: Added labels support. #648 (Felipe Barriga Richards, ngosnag) - - WEBUI: Fix accessing the WebUI through IPv6 (ngosang) - - WEBUI: Bump WebUI API_VERSION to 6. - - WEBUI: Change selected color to differentiate from the progressbar. (Daniel Peukert, ngosang) - - SEARCH: Add "Copy description page URL" button in search tab. Closes #2371. (pmzqla) - - SEARCH: Add https_proxy env variable. This forces Python to use the HTTP proxy for HTTPS connections. (pmzqla) - - SEARCH: Detect new plugin URL from clipboard (ngosang) - - SEARCH: Update Torrentz trackers (ngosang) - - WINDOWS: Fix german translation of the installer (netswap) - - NOX: Don't ask the user questions in nox build when in non-interactive mode. Closes #3875. (sledgehammer999) - - OTHER: Fixed typos, spelling correction (dartraiden) - - OTHER: Fix need for restart to enable/disable peer countries resolution. (glassez) - - OTHER: Unload the GeoIP db when disabled. (sledgehammer999) - - OTHER: Reduce max value of "Disk cache size" to 1536MB for 32bit. Closes to #4028. (Chocobo1) - - OTHER: Make "Download in sequential order" and "Download first and last piece first" options independent. (glassez) - -* Sat Oct 31 2015 - sledgehammer999 - v3.2.5 - - BUGFIX: Fix difficult to reproduce crash. (glassez) - - OTHER: Fix Windows' Qt5 build. (Gelmir) - -* Sat Oct 10 2015 - sledgehammer999 - v3.2.4 - - FEATURE: Select the file of single file torrents when opening destination folder (pmzqla) - - BUGFIX: Fix crash with invalid favicon. Closes #3632. (glassez) - - BUGFIX: Try to download favicon.png when the download of favicon.ico fails (pmzqla) - - BUGFIX: Try to avoid loading a corrupted configuration file. Also log errors encountered while saving/loading the configuration. Closes #3503. (sledgehammer999) - - BUGFIX: Allow adding torrent link from Torcache (jsayol) - - BUGFIX: Don't limit the number of torrents that can be announced to the tracker/dht/lsd. Closes #3473. (sledgehammer999) - - BUGFIX: Fix potential crash when memory allocation failed. Closes #3877. (Chocobo1) - - COSMETIC: Change Queue buttons order in the Toolbar (GUI & Web UI) (ngosang) - - COSMETIC: Move option "Ignore transfer limits on local network" to Speed page (Chocobo1) - - COSMETIC: Move option "Confirm torrent deletion" to Behavior page (Chocobo1) - - COSMETIC: Fix typos. Make `μTP` untranslatable. Use American variation of words. Closes #3654. (sledgehammer999) - - COSMETIC: Optimize text color for dark themes. Closes #3633 and #3815. (sledgehammer999) - - COSMETIC: Show current label in the torrent context menu. Closes #3776. (sledgehammer999) - - WEBUI: Add save_path to /query/torrents (Casey Bodley) - - WEBUI: Bump API_VERSION to 5 - - SEARCH: Fix python detection when the 'Anaconda' software is installed. Closes #3731. (sledgehammer999) - - RSS: Handle magnet links as torrents instead of news URLs. Closes #3560 (ngosang) - - RSS: Trim elements text in RSS articles (ngosang) - - RSS: Fix contextual menu in RSS torrents list (ngosang) - - RSS: Improve error handling when a RSS feed doesn't contain torrents (ngosang) - - RSS: More precise message and code simplification in RSS feeds deletion (ngosang) - - RSS: Don't hide the elements in Unread list when clicked (ngosang) - - RSS: Allow multiple selection in RSS torrents list (ngosang) - - RSS: Simplify string translation (ngosang) - - RSS: Handle more types of RSS feeds (ngosang) - - RSS: Fix RSS panel position not saved (ngosang) - - RSS: Fix forgetting label changes to first item in RSS rule list. (Gelmir) - - RSS: Add label to UI when a new one is creating during rule addition. (Gelmir) - - RSS: Removes refresh message when adding a new feed (ngosang) - - RSS: Fix RSS crash when deleting RSS feeds. Closes #997, #2152, #2461, #3718, #3747, #3766, #3806, #3814, #3829 and #3846. (ngosang) - - RSS: Sort labels in RSS Downloader dialog, closes #3140. (Chocobo1) - - WINDOWS: Correctly show german letters in the installer. Closes #3574, #3566. (sledgehammer999) - - WINDOWS: Fix file selection on Explorer when the filename contains weird characters. Closes #3185. (sledgehammer999) - - WINDOWS: Fix wrong default download directory in Windows. Closes #2625. (Chocobo1) - - WINDOWS: Fix German translation of the installer. (netswap) - - LINUX: Fix broken .desktop file icon for some locales. See #3905. (sledgehammer999) - - OTHER: Fix ppc64le detection during configure (sledgehammer999) - - OTHER: Don't use sed in configure. Closes #3169. (pmzqla) - - OTHER: Fix broken donation link. Closes #3771. (sledgehammer999) - - OTHER: Add forum link in README. Closes #3853. (sledgehammer999) - - OTHER: New translation: Esperanto - - OTHER: Fix Qt5 nox build on non-Windows. (sledgehammer999) - -* Sun Aug 02 2015 - sledgehammer999 - v3.2.3 - - BUGFIX: Fix crash when closing a search tab while search is running (pmzqla) - - SEARCH: Other minor search fixes and improvements (pmzqla) - -* Sat Aug 01 2015 - sledgehammer999 - v3.2.2 - - FEATURE: Allow to force reannounce DHT too (Chocobo1) - - FEATURE: Implement an option to disable confirmation of torrent recheck (blaxspirit) - - FEATURE: Allow to copy all the trackers with a keyboard shortcut (pmzqla) - - BUGFIX: Fix torrent renaming. Closes #3398 (ngosang) - - BUGFIX: Fix localhost address (::ffff:127.0.0.1) is not recognized when connecting to WebUI (Chocobo1) - - BUGFIX: Fix '&' character in label name becomes accelerator key, closes #3454. (Chocobo1) - - BUGFIX: Fix HTTP header parsing when torrent filename contains a semicolon. Closes #3511. - - BUGFIX: Fix installing search plugin from local file. (sledgehammer999) - - BUGFIX: Fix installing search plugin by drag-n-dropping file. (sledgehammer999) - - COSMETIC: Update color scheme of completed.png icon. (sledgehammer999) - - COSMETIC: Fix printing of the copyright symbol in the About dialog. (sledgehammer999) - - COSMETIC: Minor changes in Preview File dialog (ngosang) - - COSMETIC: Add Force Resume icon (ngosang) - - COSMETIC: Add count of unread items to RSS tab label (pmzqla) - - WEBUI: Ports between 1 and 65535 as in the GUI. Closes #1602 (ngosang) - - WEBUI: Fix an error in Content tab when the torrent doesn't have metadata (ngosang) - - WEBUI: New option Web UI port UPNP. Closes #3358 (ngosang) - - WEBUI: Fix API Content Types. Closes #3393 (ngosang) - - WEBUI: Fix empty trackers addition (ngosang) - - WEBUI: Torrent download from hash. Closes #1173 (ngosang) - - WEBUI: Fix sort by queue number (ngosang) - - WEBUI: Open external links in a new window/tab (ngosang) - - WEBUI: Massive increase in performance. (ngosang) - - SEARCH: Search status per tab (DoumanAsh) - - SEARCH: Remove the word 'torrent' in ExtraTorrent results (ngosang) - - SEARCH: Prefer python3 over python2 on Linux and OS X (pmzqla) - - SEARCH: Show notification if Python is not found and a search is started (pmzqla) - - SEARCH: Update link to the Windows Python installer (pmzqla) - - SEARCH: Improve checks for python. Print python version and path to log. (sledgehammer999) - - SEARCH: Improve Python detection (ngosang) - - OTHER: Improvements on the build system (Chocobo1) - - OTHER: Bump minimum libtorrent version required to 1.0.6/0.16.19. (sledgehammer999) - - OTHER: New translation: Slovenian - -* Sat Jul 11 2015 - sledgehammer999 - v3.2.1 - - FEATURE: Change default preferences (ngosang) - - FEATURE: Add "Add link to torrent" menu in TrayIconMenu. Closes #2918. (Chocobo1) - - FEATURE: Allow to Open files from the properties pane by pressing "Enter" (pmzqla) - - FEATURE: Add checkbox option for IpFilterTrackers. (Chocobo1) - - FEATURE: Download-from-URL textbox change focus on tab key (Mayank Asthana) - - FEATURE: Increase priority value of "High" (pmzqla) - - FEATURE: Add 16 KiB, 8 MiB and 16 MiB piece sizes in Torrent Creator (ngosang) - - BUGFIX: Disable Auto piece size when creating a new torrent (ngosang) - - BUGFIX: Set default focus to cancel button in delete confirm dlg, closes #3085 (Chocobo1) - - BUGFIX: Set default focus to ok button in add new torrent dlg (Chocobo1) - - BUGFIX: Set default focus to no button in exit confirm box (Chocobo1) - - BUGFIX: Fix Start Minimized checkbox in Options (ngosang) - - BUGFIX: Remove limits on alternative speeds setting (LazyBui) - - BUGFIX: Fix sorting torrents by ETA (pmzqla) - - BUGFIX: Improve ratio calculation formula. Closes #3096. (Chocobo1) - - BUGFIX: Clear missing files flag when resuming or force rechecking. Fixes issues in #2750. (sledgehammer999) - - BUGFIX: Delete tempfile when downloading favicon.ico. Closes #3257. (sledgehammer999) - - BUGFIX: Don't close downloadFromURL dialog when showing empty url warning (Chocobo1) - - BUGFIX: Minimize to tray only if the relevant option is enabled. (sledgehammer999) - - BUGFIX: Update disk space label after changing partition, closes #3309. (Chocobo1) - - BUGFIX: Don't use a default upload limit. Closes #3275. (sledgehammer999) - - BUGFIX: Fix Properties bar size when started minimized to tray. Closes #3206. (sledgehammer999) - - COSMETIC: Change option text "Confirmation on exit when torrents are active" (Chocobo1) - - COSMETIC: Enable to choose dark/light tray icons on all platforms. (Chocobo1) - - COSMETIC: Use AllUppercase for label text (Chocobo1) - - COSMETIC: changes in typography (ngosang) - - COSMETIC: Menu revamp (Chocobo1) - - COSMETIC: Revamp general tab info (Chocobo1) - - COSMETIC: Better update message for users (Chocobo1) - - COSMETIC: Fix ugly 'C++' wrapping in About dialog. (glassez) - - WEBUI: Fix login and logout relative URLs (ngosang) - - WEBUI: Fix resumeAll and pauseAll. Closes #3016 (ngosang) - - WEBUI: Changes in title bar (ngosang) - - WEBUI: Complete translatable strings (ngosang) - - WEBUI: Minor changes in style (ngosang) - - WEBUI: Fix Max connections and Time active in transfer information (ngosang) - - WEBUI: New config - Global maximum number of upload slots (ngosang) - - WEBUI: Display wasted data with friendly units. Closes #2994 (ngosang) - - WEBUI: add delay in shutdown command in order to send out response msg (Chocobo1) - - WEBUI: Option to hide Top Toolbar (ngosang) - - WEBUI: Reorder the tabs/groups in Options window (ngosang) - - WEBUI: Add new options (ngosang) - - WEBUI: Increase API_VERSION due to changes in #3279, #3197, #3226 and #3040 (ngosang) - - WEBUI: Add Web Seeds (HTTP Sources) tab (ngosang) - - WEBUI: Don't update the tabs if tab's panel is collapsed (ngosang) - - WEBUI: Fix alternative global rate limits. (ngosang) - - SEARCH: Fix thepiratebay. Closes #3012 (ngosang) - - SEARCH: Improve torrentz engine to return more results (ngosang) - - SEARCH: Change width of columns in search tab. Closes #764 (ngosang) - - SEARCH: Make strings translatable in seach engine (ngosang) - - SEARCH: Aborting search engine process during closure. Close #2671 (DoumanAsh) - - SEARCH: Perform searches in parallel (DoumanAsh) - - SEARCH: Add Demonoid search engine (ngosang) - - SEARCH: Minor fixes in search engines (ngosang) - - SEARCH: Show the version of search engines (ngosang) - - SEARCH: Update Legit Torrent to remove sgmllib (DoumanAsh) - - SEARCH: Update KickassTorrents (ngosang) - - SEARCH: Update BTDigg (ngosang) - - SEARCH: Update Torrentz (ngosang) - - SEARCH: Update ExtraTorrent (ngosang) - - SEARCH: Update TorrentReactor (ngosang) - - SEARCH: Fix Python 2 implementation of Torrentz (ngosang) - - SEARCH: Cosmetic changes in search engine (ngosang) - - SEARCH: Fix column sort in search engine. Closes #2621 (ngosang) - - RSS: Update matching RSS articles while editing rules (pmzqla) - - WINDOWS: Fix python detection from registry when multiple versions are installed (sledgehammer999) - - LINUX: Fixes Linux issue for when the theme doesn't have a corresponding icon. (sledgehammer999) - - OTHER: Correctly detect FreeBSD when configuring. (sledgehammer999, yurivict) - - OTHER: Add translator to credits. - - OTHER: New translation: Indonesian. - - OTHER: Split Chinese locales into Chinese Simplified, Chinese Traditional(Taiwan), Chinese Traditional(Hong Kong). (sledgehammer999) - -* Sun May 10 2015 - sledgehammer999 - v3.2.0 - - FEATURE: Show actual protocol for listen success/failure in the log. Needs libtorrent v1.0.0 (Gelmir) - - FEATURE: Support per tracker re-announce. Needs libtorrent v1.0.0 (Gelmir) - - FEATURE: Support saving in network locations. (Gelmir) - - FEATURE: Support Qt5 (mostly Glassez) - - FEATURE: Code optimizations resulting in a more CPU efficient and snappier qBittorrent. (sorokin) - - FEATURE: WEBUI code rewritten, refactored and improved. (glassez, pmzqla, buinsky) - - FEATURE: Add option to hibernate computer in Auto-Shutdown menu (Bruno Barbieri) - - FEATURE: Cache preferences in memory. Minimize chance of settings corruption. Closes #1272, #1523, #1694. (sledgehammer999) - - FEATURE: Option to disable connections not supported by proxies. Closes #1894. (sledgehammer999) - - FEATURE: Haiku OS support (diger) - - FEATURE: Add a save resume data interval option(useful for SSD). (john-peterson) - - FEATURE: Add "Last Seen Complete" column (pmzqla) - - FEATURE: Add "Last Activity" column (pmzqla) - - FEATURE: Add "Total Size" column (pmzqla) - - FEATURE: Show current speed limits in the status bar (pmzqla) - - FEATURE: Episode filtering for RSS (Gelmir) - - FEATURE: Highlight files when opening containing folder on Windows and Linux(nautilus, dolphin, konqueror). (Gelmir, pmzqla) - - FEATURE: Setting to ignore RSS rule matches for X days (Gelmir) - - FEATURE: Add hotkeys and buttons for Top and Bottom priorities (alfrix) - - FEATURE: Implement peer relevance column. Closes #1630. (sledgehammer999) - - FEATURE: Show reason why a peer was blocked. Needs libtorrent 1.0.x. (sledgehammer999) - - FEATURE: Use the 'fastest_upload' setting as seed choking algorithm. (sledgehammer999) - - FEATURE: Allow to set text options for the toolbar icons (pmzqla) - - FEATURE: Add 'Resumed' torrent filter (john.s.peterson) - - FEATURE: 'Add New Torrent` dialog has a button for quickly choosing a location (sledgehammer999) - - FEATURE: Copy selected peers as IP:Port format. (ngosang) - - FEATURE: Show info hash in the torrent details in 'Add New Torrent' dialog. (sledgehammer999, chrishirst) - - FEATURE: New feature: Remove empty labels (ngosang) - - FEATURE: Add "Copy name" option in right-click menu of torrent list. Closes #2452 (chrishirst) - - FEATURE: Implement tracker list in the side panel. Closes #170. (sledgehammer999) - - FEATURE: Implement a 'Completed' status. Closes #2326 #2483 #939. (sledgehammer999) - - FEATURE: Columns for session-based download and upload statistics (LazyBui) - - BUGFIX: Use completed time from libtorrent directly. Closes #1726. - - BUGFIX: Speedup and fix a bug in torrent moving. (sorokin) - - BUGFIX: Scan Folder dialog now remembers last location (Bryan Roscoe) - - BUGFIX: Show input box to filter torrent list only when the list is shown (pmzqla) - - BUGFIX: Add placeholder text to the input to filter the torrent list (pmzqla) - - BUGFIX: Put directories first when sorting torrent content by name (pmzqla) - - BUGFIX: Fix missing icon for open action in file list (Gelmir) - - BUGFIX: Set placeholder text to torrent content filter. (sorokin) - - BUGFIX: Fix torrent creation when data is too large (sorokin) - - BUGFIX: Load torrents that have big metadata file. Closes #1889. (sledgehammer999) - - BUGFIX: Use correct separator for "OR" condition in RSS rules (pmzqla) - - BUGFIX: Don't waste UI space in 'Content' window. Closes #2159 (alfrix) - - BUGFIX: Fix the language selection in the combobox when the system locale only has a lang equivalent and not a lang_COUNTRY one. Closes #1786. (sledgehammer999) - - BUGFIX: Don't overwrite the 'Add Paused' setting from the Add New Torrent Dialog (Gelmir) - - BUGFIX: Fix file preview when .!qB extension is used (pmzqla) - - BUGFIX: Ensure that the priority column has enough width when queueing is enabled. Closes #2263. (sledgehammer999) - - BUGFIX: Don't put limits to the alternative speed limits (pmzqla) - - BUGFIX: Make space key change all selected files' checkboxes (sorokin) - - BUGFIX: Don't block peers that use privileged ports. (sledgehammer999) - - BUGFIX: Accept multiple files at once. Closes #2253 (buinsky) - - BUGFIX: Don't touch torrents whose files are missing. Closes #342 #2308 #2469. (sledgehammer999) - - BUGFIX: Save the new save path first in the history. Closes #2382. (sledgehammer999) - - BUGFIX: Fix default tracker in 'Create Torrent' dialog. (ngosang) - - BUGFIX: Let the OS decide the default interface regardless of IPv4/IPv6. Closes #2156. (Chocobo1) - - BUGFIX: Delete the correct selected torrents when the list is filtered. Closes #2729. (sledgehammer999) - - BUGFIX: Don't use HTML in tray icon pop-up on OSX. Closes #2830. (pmzqla) - - BUGFIX: Fix crash when trying to open destination folder on a torrent with no metadata. Closes #2522. (pmzqla) - - BUGFIX: Change torrent name when metadata is retrieved. (ngosang) - - COSMETIC: Removes white bar in the labels list. Closes #1151. (ngosang) - - COSMETIC: Fix speed printing in the tray icon and in the title bar. Closes #2737. (sledgehammer999) - - COSMETIC: Change the color scheme used (sledgehammer999) - - RSS: Display remote images in the preview (Mladen Milinkovic) - - RSS: Format html descriptions in the preview (Mladen Milinkovic) - - RSS: Support overriding global "Add paused" option on per rule basis (Gelmir) - - WINDOWS: Fix automatic python download. Closes #2076. (sledgehammer999) - - WINDOWS: Fix crash when searching the registry for installed python (glassez) - - WINDOWS: Tell Windows to wait during shutdown. (sledgehammer999, paolo-sz) - - OSX: Use the configure script to prepare the build in Mac OSX too. Closes #2295. (sledgehammer999) - - OSX: Fix the build (David Christenson) - - LINUX: Distribute systemd service file for the nox build (sledgehammer999, leigh123linux) - - LINUX: Create qBittorrent.appdata.xml (alxpl) - - SEARCH: Update KickassTorrents plugin (pmzqla) - - SEARCH: Remove vertor engine. Closes #2260. (DoumanAsh) - - SEARCH: Small fix of import in legittorrents engine (DoumanAsh) - - SEARCH: Add combo box for fast search engine switch (DoumanAsh) - - SEARCH: Fix error in mininova search engine (ngosang) - - SEARCH: Fix piratebay. Closes #2270 (DoumanAsh) - - SEARCH: Updated URL in kickasstorrents search engine (ngosang) - - SEARCH: Torrentz search engine added (ngosang) - - OTHER: Drop libtorrent 0.15.x support - - OTHER: Drop Qt < 4.8.0 support - - OTHER: Migrate build system to autotools (sledgehammer999) - - OTHER: Remove deprecated feature of separate DHT port. (sledgehammer999) - - OTHER: Speedup compilation speed (sorokin) - - OTHER: Backtrace generation now works on MinGW. (Gelmir) - - OTHER: New translation: Hindi(India). - -* Wed Feb 22 2015 - sledgehammer999 - 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 - 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 - 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 - v3.1.9.2 - - OTHER: The v3.1.9.1 Windows build was broken - -* Mon Apr 28 2014 - sledgehammer999 - 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 - 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 - v3.1.8 - - BUGFIX: Really fix build of v3.1.6 - -* Sun Feb 02 2014 - sledgehammer999 - v3.1.7 - - BUGFIX: Fix build of v3.1.6 - -* Sun Feb 02 2014 - sledgehammer999 - 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 - 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 - 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 - 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 - 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 - 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 and sledgehammer999 - 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 - -* Mon Jul 29 2013 - sledgehammer999 - v3.0.11 - - FEATURE: Allow more fine tuning of upload slots. It should improve speed (sledgehammer999) - - FEATURE: Enable edit/rename via F2 or double click in various places (Gelmir) - - BUGFIX: Fix Spanish and Basque translations being messed up on Windows (sledgehammer999) - - BUGFIX: Don't allow newlines in rename dialog (Gelmir) - - BUGFIX: Treat unfinished dates as the newest ones when sorting (sledgehammer999) - - BUGFIX: Fix text size problem on Windows with custom DPI (sledgehammer999) - - BUGFIX: Respect UI lock when clicking on tray notification (sledgehammer999) - - BUGFIX: Fix kickass torrents search plugin (Gelmir) - - BUGFIX: Use system language as default language. Closes #780 (sledgehammer999) - - BUGFIX: Move completed files to .unwanted folder when they are unselected by the user (constantined) - - BUGFIX: Show delete action when multiple feeds are selected (Gelmir) - - BUGFIX: Use Unicode for libtorrent alert messages (Gelmir) - - OTHER: Update translations - - WINDOWS: Shave off ~4MB from the binary size (sledgehammer999) - - WINDOWS: Remove wrong dependency on msvc2008 runtime (sledgehammer999) - - WINDOWS: Disable stacktrace when building with mingw (Gelmir) - - WINDOWS: Updated NSIS script to include/delete .pdb file. (sledgehammer999) - -* Tue Jul 9 2013 - Christophe Dumez and sledgehammer999 - v3.0.10 - - BUGFIX: Fix LegitTorrents search plugin - - BUGFIX: Improve peer host name resolution (closes #360) - - BUGFIX: Context menu fix in the Web UI - - BUGFIX: Respect 'don't show' torrent dialog in Search (sledgehammer999) - - BUGFIX: Torrent creator can now use files/folders from disk root (Gelmir) - - BUGFIX: Update free disk space when changing drives in the add new torrent dialog (sledgehammer999) - - BUGFIX: Various fixes relating to RSS drag and drop (Gelmir) - - BUGFIX: Properly rename torrent which changes position in filter model (Gelmir) - - BUGFIX: Actually show tray notifications when a torrent finishes downloading (sledgehammer999) - - BUGFIX: Don't download RSS items based on rules still being edited (Gelmir) - - COSMETIC: Native look for the search boxes (Hyperz) - - IMPROVEMENT: Use natural sorting where possible (Gelmir and sledgehammer999) - - LINUX: Drop Boost.Thread dependency from configure script - - OTHER: Update translations. - - OTHER: Drop obsolete Boost.Thread dependency from configure script on linux (Dumez) - - LIBTORRENT: SOCKS5 fixes (0.16.10) - - LIBTORRENT: Fix hanging issue on Windows when closing files (0.16.10) - - LIBTORRENT: Cache can now be returned to the OS (0.16.10) - - PERFORMANCE: Impove drawing speed of tranferlist when there are many torrents(>100) (sledgehammer999) - - PERFORMANCE: Impove drawing speed of peers list when there are many peers (sledgehammer999) - -* Sat Mar 16 2013 - Christophe Dumez - v3.0.9 - - BUGFIX: Raise qBittorrent windows when another instance is launched - - BUGFIX: Show human readable names for network interfaces in preferences (Windows) - - BUGFIX: Fix torrent creator bug when saving non-latin path (Windows) - - BUGFIX: Enable 'copy magnet uri' for torrents without metadata too - - BUGFIX: Fix a few JSON parser issues (Gelmir) - - BUGFIX: Add support for gzipped encoded HTTP responses (daimor) - - BUGFIX: Fix possibly missing "Add torrent" icon (Driim) - - OTHER: Add search plugin for Legit Torrents - -* Sun Jan 20 2013 - Christophe Dumez - v3.0.8 - - BUGFIX: Fix support for --no-splash command line argument - - BUGFIX: Fix compilation error with libtorrent v0.15 - - BUGFIX: Fix search issues with Python3 - - BUGFIX: Fix dead link about certificates in program preferences - -* Sat Jan 19 2013 - Christophe Dumez - v3.0.7 - - BUGFIX: Update max write cache size to 2048MB and set it to automatic by default (closes #148) - - BUGFIX: Add m4v to the list of previewable file extensions (closes #216) - - BUGFIX: Fix "Couldn't set environment variable..." message on start up (closes #245) - - BUGFIX: Use right path separator in torrent addition dialog on Windows - - BUGFIX: Fix "Set as default save path" setting (closes #254) - - BUGFIX: Reenable disk cache on Windows since the memory issue seems to be gone - - BUGFIX: Fixed several search engine plugins and removed the dead ones - - BUGFIX: Use https links in search plugins when possible - - BUGFIX: Bump Mootools to v1.4.5 (Web UI) - - BUGFIX: Require password to exit qBittorrent from tray icon when locked (closes #311) - - BUGFIX: Fix possible crash in loadPeers() (closes #222) - -* Sun Oct 7 2012 - Christophe Dumez - v3.0.6 - - BUGFIX: Fix unicode support for command-line arguments on Windows (closes #139) - - BUGFIX: Do not store created torrent in memory before writing it to a file (closes #133) - - BUGFIX: No longer fallback to ANY interface if the user-selected interface cannot be found (closes #143) - - BUGFIX: Fix timezone parsing in RSS (closes #136) - - BUGFIX: Fix cookie support for RSS feeds (closes #119) - -* Sun Sep 30 2012 - Christophe Dumez - v3.0.5 - - BUGFIX: Disabling systray icon no longer disables file association settings (closes #114) - - BUGFIX: Import new trackers from magnet link in case of duplicate torrent (closes #111) - - BUGFIX: Fix "Skip hash check" feature in torrent import dialog (closes #128) - - BUGFIX: Several Web UI connection fixes - - BUGFIX: Add Basque locale to Web UI - -* Tue Sep 18 2012 - Christophe Dumez - v3.0.4 - - BUGFIX: Fix issue with downloads starting from scratch on startup if temporary - directory setting is enabled. - -* Sun Sep 16 2012 - Christophe Dumez - v3.0.3 - - BUGFIX: Fix issue with temporary directory not being taken into consideration (closes #94) - - BUGFIX: Address encoding issues when using search engine on Windows (closes #29) - - BUGFIX: Bypass cache when uploading a torrent file in Web UI (closes #68) - - BUGFIX: "Completed On" column is not updated until restart (closes #84) - - BUGFIX: Fix possible build error on some systems - - I18N: Add hebrew translation - -* Sat Sep 1 2012 - Christophe Dumez - v3.0.2 - - FEATURE: Add "clear" functionality to search field (closes #59) - - BUGFIX: Attempt to use qBittorrent icon from theme if available (closes #49) - - BUGFIX: Fix crash when a fastresume file is empty (closes #52) - - BUGFIX: Fix encoding problem for detected XDG Download folder (closes #53) - - BUGFIX: Improve performance when showing torrent content panel (Improves #24) - - BUGFIX: Fix label-based filtering of torrents whose label contains special characters - - BUGFIX: Fix possible crash due to labels (closes #64) - -* Tue Aug 21 2012 - Christophe Dumez - v3.0.1 - - BUGFIX: Fix possible crash when adding a tracker to a magnet torrent without metadata (Closes #1034254) - - BUGFIX: Remember queue position for torrents without metadata (closes #17) - - BUGFIX: Fix crash when using unauthorized characters in label names (closes #19) - - BUGFIX: Fix search plugins updating (closes #25) - - BUGFIX: Make uTP connections rate limited by default - -* Thu Aug 09 2012 - Christophe Dumez - 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 - -* Unreleased - Christophe Dumez - v2.9.12 - - BUGFIX: Fix issue when "Minimize to tray" and "Start minimized" are both enabled - -* Sun Jul 1 2012 - Christophe Dumez - v2.9.11 - - BUGFIX: Fix unreversible "Minimize to tray" on some window managers - - BUGFIX: Fix torrent availability computation (closes #988869) - - BUGFIX: Bring window to front after restoring from systray - - BUGFIX: Fix keyboard focus problems on main window (closes #1019563) - - BUGFIX: Fix ThePirateBay search plugin - -* Sun Jun 24 2012 - Christophe Dumez - v2.9.10 - - BUGFIX: Fix possible crash when showing torrent content (closes #1002586) - - BUGFIX: Add support for RSS feeds using magnet links (closes #1016379) - - BUGFIX: Remove 100kb limit for torrent file size in Web UI - - BUGFIX: Fix ratio limiting bug (closes #835217) - - BUGFIX: Do not display .!qB file extensions in Web UI - - BUGFIX: Stop using absolute URLs in Web UI ajax requests (closes #1011226) - - BUGFIX: Fix torrent association and loading on Mac OS X (closes #1011229) - - BUGFIX: Fix unreversible "Minimize to tray" on some window managers (closes #917825) - -* Sun May 20 2012 - Christophe Dumez - v2.9.9 - - BUGFIX: More reliable RSS feed parsing (closes #1001777) - - BUGFIX: Better support for cookies in RSS - - BUGFIX: Make sure show/hide text in tray icon menu is correct - - COSMETIC: Improve style of left panel - - COSMETIC: Never disable properties panel - - COSMETIC: Make sure first tab is initially selected in options dialog - - COSMETIC: Fix a few focus issues on Mac OS X - -* Sat May 5 2012 - Christophe Dumez - v2.9.8 - - BUGFIX: Various UI style fixes - - BUGFIX: Fix compilation with gcc 4.7 - - BUGFIX: Fix possible compilation error with msvc (Windows) - - BUGFIX: Fix compilation on OS/2 - - I18N: Update Italian translation - -* Sun Mar 18 2012 - Christophe Dumez - v2.9.7 - - BUGFIX: Fix important HTTP request parsing bug (Web UI) - -* Sat Mar 17 2012 - Christophe Dumez - v2.9.6 - - BUGFIX: Fix download first/last pieces state reporting - - BUGFIX: Fix name of progress column in torrent content panel - - BUGFIX: Disable system tray icon on Mac OS X - - BUGFIX: RSS downloader should not ignore "Do not start automatically" rule (closes #946910) - - BUGFIX: Fix DHT port setting in Web UI (Closes #952182) - - BUGFIX: Fix possible Web UI authentication problem when using SSL (closes #941343) - - BUGFIX: Fix possible issues with folder removal when removing a torrent - - I18N: Add Basque translation - -* Sat Feb 18 2012 - Christophe Dumez - v2.9.5 - - BUGFIX: Fix crash when disabling then reenabling RSS - - BUGFIX: Fix duplicate torrent detection when adding a magnet link - - BUGFIX: Fix import of new trackers when adding a torrent with same hash (Closes #747000) - - BUGFIX: Fix possible redownload of torrents marked as read (Closes #927495) - - BUGFIX: Properly remove RSS feed settings/history upon feed removal - -* Sat Feb 18 2012 - Christophe Dumez - v2.9.4 - - BUGFIX: qBittorrent does not handle redirection to relative URLs correctly (Closes #919905) - - BUGFIX: Cmd+M minimizes main window on Mac OS X (Closes #928216) - - BUGFIX: Cmd+Del removes torrents on Mac OS X (Closes #928852) - - BUGFIX: Fix potential bug when moving single file torrents to tmp folder (closes #932861) - - BUGFIX: Fix torrent import dialog layout (Closes #930932) - - BUGFIX: Prevent log window buffer from filling up (Closes #929673) - - I18N: Add Belarusian translation - -* Thu Dec 29 2011 - Christophe Dumez - v2.9.3 - - BUGFIX: Fix btdigg plugin (Python3 support + torrent name in magnet links) - - BUGFIX: Fix banning of IPv6 peers (Closes #885021) - - BUGFIX: Fix torrent addition dialog layout problem (Closes #84650522) - - BUGFIX: Do not report any progress for disabled files (Closes #56731485) - - BUGFIX: Make torrent sorting case insensitive (Closes #857154) - - BUGFIX: Improve Web UI usability of small devices - - BUGFIX: Program updater: More reliable version detection / comparison - - I18N: Add Georgian translation - -* Sat Oct 29 2011 - Christophe Dumez - v2.9.2 - - BUGFIX: Fix mimimum dimensions for torrent addition dialog - - BUGFIX: Remove dependency on boost-datetime - - BUGFIX: Remove dependency on boost-filesystem (libtorrent v0.16.x) - -* Sun Oct 23 2011 - Christophe Dumez - v2.9.1 - - BUGFIX: Add support for speed limits scheduling (Web UI) - - BUGFIX: Fix ratio calculation for purely seeded torrents - - I18N: Update Russian translation - - COSMETIC: Torrent addition dialog layout fixes - -* Sat Oct 08 2011 - Christophe Dumez - 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 - 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 - 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) - -* Sun Jan 9 2011 - Christophe Dumez - v2.6.0 - - FEATURE: Use system icons (Linux, Qt >= 4.6) - - FEATURE: Improved ETA calculation - - FEATURE: Simplify program preferences - - FEATURE: Software update check can now be disabled (Mac OS X / Windows) - - FEATURE: Display pieces size in torrent properties - - FEATURE: Added "Time Active/Seeded" column to transfer list - - FEATURE: Give feedback regarding the IP filter parsing - - FEATURE: Added a button to reload the IP filter - - FEATURE: Search engine results can now be opened in a Web browser - - FEATURE: Added a search engine plugin to extratorrent.com - - FEATURE: Added a search engine plugin for kickasstorrents.com - - FEATURE: Added auto-suspend upon downloads completion feature - - BUGFIX: Hide unwanted files that have to be partly downloaded - - BUGFIX: Do not allocate space for unwanted files (preallocation mode) - - I18N: Added Galician translation - - COSMETIC: Same deletion confirmation dialog in the GUI and Web UI - - COSMETIC: Simplified the top toolbar - - COSMETIC: Display execution log as a tab instead of a modal window - -* Sun Dec 5 2010 - Christophe Dumez - v2.5.0 - - FEATURE: qBittorrent can now act as a tracker - - FEATURE: New and improved RSS feed automated downloader - - FEATURE: Added feature to shutdown qbittorrent on torrents completion - - FEATURE: Added a torrent import assistant to seed or keep downloading outside torrents - - FEATURE: qBittorrent can update itself from Sourceforge (Windows/Mac OS X only) - - FEATURE: Added a transfer list column to display the current tracker - - FEATURE: Remember the last trackers used in the torrent creation tool - - FEATURE: The optimal piece size is now automatically computed in the torrent creation tool - - FEATURE: Bring up the connection settings when clicking on the connection status icon - - FEATURE: Major code refactoring and optimization - - FEATURE: Added "Amount downloaded/left" columns to transfer list - - FEATURE: Simplified proxy settings - - FEATURE: Optimized and improved the peer country resolution code - - FEATURE: Download first/last pieces first when sequential download is - enabled (Thanks Ahmad) - - FEATURE: Download first/last pieces first now applies to all media files - in the torrent (Thanks Ahmad) - - BUGFIX: Fix SOCKS5 proxy authentication in search engine(closes #680072) - - BUGFIX: Fix two advanced settings (ignore limits on LAN and protocol - overhead inclusion in rate limiter) - - BUGFIX: Fix strict super seeding (was not working) - - BUGFIX: Improve magnet save path handling (closes #683395) - - BUGFIX: Disable overwrite confirmation in torrent addition dialog (closes # 685269) - - COSMETIC: Replaced message box by on-screen notification for download errors - - COSMETIC: Improved the torrent creation tool appearance - - COSMETIC: Use country flags by Mark James (Thanks to Dmytro Pukha) - - COSMETIC: Use bigger alternative speed icon - - OTHERS: Dropped support for Qt <= 4.4 - -* Tue Aug 24 2010 - Christophe Dumez - v2.4.0 - - FEATURE: Added actions to "Move to top/bottom" of priority queue - - FEATURE: Auto-Shutdown on downloads completion - - FEATURE: Email notification on download completion - - FEATURE: Added button to password-lock the UI - - FEATURE: Added label-level Pause/Resume/Delete actions - - FEATURE: Torrents can now be filtered by name - - FEATURE: Run external program on torrent completion - - FEATURE: Detect executable updates in order to advise the user to restart - -* Tue Jul 27 2010 - Christophe Dumez - v2.3.0 - - FEATURE: Simplified torrent root folder renaming/truncating (< v2.3.0 is no longer forward compatible) - - FEATURE: Remember previous save paths in torrent addition dialog - - FEATURE: Max number of half-open connections can now be edited - - FEATURE: Added support for strict super seeding - - FEATURE: The user can force listening on a particular network interface - - FEATURE: Added cookie support for RSS feeds - - FEATURE: User can force tracker reannounce - - FEATURE: Added "No action" setting for double-click action - - FEATURE: Several torrents can be moved at once - - FEATURE: Added error state for torrents (error is displayed in a tooltip) - - FEATURE: Added filter for paused/error torrents - - FEATURE: Add Check/Uncheck all feature in Web UI - - FEATURE: Search engine can now be disabled - - FEATURE: Torrents can be automatically paused once they reach a given ratio - - FEATURE: Several files can now be disabled at once - - FEATURE: Added "Select All/None" buttons to files list - - FEATURE: Added support for BitComet links (bc://bt/...) - - BUGFIX: Hide seeding torrents files priorities in Web UI - - BUGFIX: The user can disable permanently recursive torrent download - - BUGFIX: Peer Exchange status is now correctly reported - - BUGFIX: Use an INI file instead of the registry on Windows (More reliable) - - BUGFIX: Removed client spoofing feature to avoid tracker blacklisting - - COSMETIC: Display peers country name in tooltip - - COSMETIC: Display number of torrents in transfers tab label - - COSMETIC: Simplified program preferences - - COSMETIC: Fix naming of actions opening new dialogs (use Name...) - -* Sun Mar 14 2010 - Christophe Dumez - v2.2.0 - - FEATURE: User can set alternative speed limits for fast toggling - - FEATURE: Bandwidth scheduler (automatically use alternative speed limits for a given period) - - FEATURE: Added "Added/Completed On" columns to transfer list - - FEATURE: Added "Upload/Download limit" columns to transfer list - - FEATURE: Torrent files can be exported to a given directory - - FEATURE: Outgoing ports range can be customized (for QoS) - - FEATURE: User can choose to apply transfer limits on LAN too - - FEATURE: User can choose to include the protocol overhead in transfer limits - - FEATURE: Torrents can be automatically rechecked on completion - - FEATURE: If 2 torrents have the same hash, add new trackers/URL seeds to the existing torrent - - FEATURE: Trackers can be added from Web UI - - FEATURE: Global transfer information are displayed in the new Web UI status bar - - FEATURE: Allow to change the priority of several files at once - - FEATURE: Support for multiple scan folders (Patch by Christian Kandeler) - - BUGFIX: Only one log window can be opened at a time - - BUGFIX: Optimized RSS module memory usage - - BUGFIX: Consider HTTP downloads >1MB as invalid .torrent files and abort - - BUGFIX: Fix Web UI authentication with some browsers - - BUGFIX: Set Web UI ban period to 1 hour - - COSMETIC: Improved style management - -* Mon Jan 18 2010 - Christophe Dumez - v2.1.0 - - FEATURE: Graphical User Interface can be disabled at compilation time (headless running) - - FEATURE: Torrents can be labeled/categorized - - FEATURE: Labeled torrent can be downloaded corresponding subfolders - - FEATURE: Disk cache size can be set from preferences - - FEATURE: Peer Exchange (PeX) can be disabled from preferences - - FEATURE: Append !.qB extension to incomplete files option (libtorrent >= v0.15 only) - - FEATURE: Torrent files/folders can be renamed (torrent addition dialog or files properties) - - FEATURE: uTorrent compatible tracker list support (use torrentz.com url as a default) - - FEATURE: Better proxy support and preferences remodeling - - FEATURE: qBittorrent can identify itself as uTorrent, Vuze or KTorrent (Any stable version) - - FEATURE: Torrents can be renamed in transfer list - - FEATURE: Display torrent addition dialog for magnet links too - - FEATURE: Files contained in a torrent are opened on double click (files panel) - - FEATURE: Added support for magnet links in search engine - - FEATURE: Added vertor.com and torrentdownloads.net search plugins - - FEATURE: Search engine can now use a SOCKS5 proxy - - FEATURE: HTTP proxy support for peer communication - - BUGFIX: Search engine loads new proxy settings without program restart - - BUGFIX: Use XDG folders (.cache, .local) instead of .qbittorrent - - BUGFIX: Added legal notice on startup that the user must accept - - BUGFIX: Protect Web UI authentication against brute forcing - - BUGFIX: Use HTTP digest mode for Web UI authentication (instead of Basic) - - BUGFIX: Properly display torrents with one file in subfolder(s) - - BUGFIX: Display Web UI favicon - - BUGFIX: File priority can be set for finished torrents that have filtered files - - COSMETIC: Use checkboxes to filter torrent content instead of comboboxes - - COSMETIC: Use alternating row colors in transfer list (set in program preferences) - - COSMETIC: Added a spin box to speed limiting dialog for manual input - -* Mon Jan 11 2010 - Christophe Dumez - v2.0.7 - - BUGFIX: Fix 'Add in pause' setting in torrent addition dialog - - BUGFIX: Update RSS feed as soon as feed downloader is enabled - - BUGFIX: RSS Feed downloader ignores articles above maximum number of articles - - BUGFIX: Fix possible bug when deleting a RSS folder - - BUGFIX: Remove persistant data when a RSS feed is deleted - - BUGFIX: RSS filters are now alphabetically sorted - - BUGFIX: Fix crash when renaming currently displayed RSS filter - - BUGFIX: Remove overwriting confirmation when exporting RSS filters since Qt takes care of it - -* Tue Jan 5 2010 - Christophe Dumez - v2.0.6 - - BUGFIX: Fix detection of invalid torrent files - - BUGFIX: Stop catching signals once one has been caught to avoid possible infinite loop - - BUGFIX: Force data recheck whenever a torrent is moved - - BUGFIX: Detect existing torrent data even if incomplete torrents are saved to a different folder - - COSMETIC: Improve torrent deletion confirmation dialog so that the text that not get truncated - -* Thu Dec 31 2009 - Christophe Dumez - v2.0.5 - - BUGFIX: Fix crash with downloaded/availability bars when the torrent has too many pieces - -* Wed Dec 30 2009 - Christophe Dumez - v2.0.4 - - BUGFIX: Fix PeerGuardian .p2b binary filter support - - BUGFIX: Fix possible crash when closing a search engine tab - - BUGFIX: Make sure service port does not change - - BUGFIX: Fix possible DHT port saving issue - - BUGFIX: Fix communication between qBittorrent and Web UI (Qt 4.6) - - BUGFIX: Use Wildcard matching instead of full regex in RSS feed downloader - - BUGFIX: Fix code for listening on a random port whenever it failed to listen on the one defined - - BUGFIX: Use global maximum transfer rates as maximum values in per-torrent speed limiting dialogs - - BUGFIX: Fix global download rate limiting from Web UI - - COSMETIC: Display a disconnected icon in status bar whenever qBittorrent failed to listen on the port defined - -* Wed Dec 23 2009 - Christophe Dumez - v2.0.3 - - BUGFIX: Minor cosmetic fix to program preferences - - BUGFIX: Fix "Temp path" button in program preferences - - BUGFIX: Handle paths with [~, ., ..] properly - - BUGFIX: Trackers are now displayed for torrents without metadata - - BUGFIX: Fix issue with speed limiting (unlimited was not handled properly) - - BUGFIX: Use the save path set in program preferences as a default in torrent addition dialog - -* Fri Dec 18 2009 - Christophe Dumez - v2.0.2 - - BUGFIX: Fix .qbittorrent folder not being created (critical bug introduced in v2.0.1 that makes qBittorrent unusuable for new users) - - BUGFIX: Fix RSS Feed downloader for some feeds - - BUGFIX: Do not use home folder as a fallback when the save path is not accessible - - BUGFIX: Fix Mininova, ThePirateBay search engine plugins - - BUGFIX: Read RSS articles are remembered on restart for feeds with no torrents attached - -* Sun Dec 13 2009 - Christophe Dumez - v2.0.1 - - BUGFIX: µTorrent user-agent is now spoofed correctly - - BUGFIX: Fix column hiding behavior when queueing system is disabled - - BUGFIX: Fix link to plugins.qbittorrent.org in plugins dialog - - BUGFIX: ~/qBT_dir is created only when it is actually used - - BUGFIX: Fix possible missing slot message (toggleSelectedTorrentsSuperSeeding) - - BUGFIX: Fix possible crash in torrent properties (files) - - BUGFIX: Added Hex Magnet Links support (Thanks Haypo) - -* Thu Dec 10 2009 - Christophe Dumez - v2.0.0 - - FEATURE: Added program option to disable splash screen - - FEATURE: Dropped dependency on libcurl and libzzip - - FEATURE: Display more information regarding the torrent in its properties - - FEATURE: Various optimizations to save CPU and memory - - FEATURE: Folder scanning now works with CIFS and NFS mounted folders - - FEATURE: Speed up qBittorrent startup and shutdown - - FEATURE: Display per-torrent peer list - - FEATURE: Make sure torrent files are always sorted by name - - FEATURE: Seeds and Peers columns are now sortable - - FEATURE: Torrents can be rechecked from Web UI (Stephanos Antaris) - - FEATURE: New peers can manually be added to the torrents - - FEATURE: Support per-peer rate limiting - - FEATURE: Support peer manual ban - - FEATURE: Display total amounts transferred in status bar - - FEATURE: Display trackers status as well as error/warning messages - - FEATURE: Display the number of peers returned by each tracker & DHT/PeX/LSD - - FEATURE: Global upload/download speeds can be capped from status bar (µTorrent behavior) - - FEATURE: Added option to download first and last piece of a torrent main file first (for preview) - - FEATURE: Graphically display piece availability in torrent properties - - FEATURE: Dropped Qt 4.3 support (Qt >= 4.4 is now required) - - FEATURE: Display close tab button into the tabs in search engine (Qt >= 4.5 only) - - FEATURE: Show official documentation when pressing F1 key - - FEATURE: Search engine plugins now handle HTTP protocol gzip compression - - FEATURE: Enabled lazy bitfield as a counter-measure for ISP speed throttling - - FEATURE: Fall back to a random port if qBittorrent could not listen on the chosen port - - FEATURE: Announce to all trackers specified for a torrent (µTorrent behavior) (libtorrent >= v0.15 only) - - FEATURE: Added per-torrent super seeding mode (libtorrent >= v0.15 only) - - FEATURE: Support for storing symbolic links in .torrent files (libtorrent >= v0.15 only) - - FEATURE: Support for uTorrent interpretation of multi-tracker torrents (libtorrent >= v0.15 only) - - FEATURE: Handle torrents with duplicate filenames (libtorrent >= v0.15 only) - - FEATURE: Support for merkle hash tree torrents (.merkle.torrent) (libtorrent >= v0.15 only) - - FEATURE: Metadata download from swarm is now compatible with µtorrent (libtorrent >= v0.15 only) - - FEATURE: Support tracker exchange between peers (libtorrent >= v0.15 only) - - FEATURE: Better http seed support (libtorrent >= v0.15 only) - - FEATURE: Tracker connections are now also subject to IP filtering (libtorrent >= v0.15 only) - - FEATURE: Include DHT traffic in the rate limiter (libtorrent >= v0.15 only) - - FEATURE: Support for bitcomet padding files (libtorrent >= v0.15 only) - - FEATURE: Option to skip file checking and start seeding immediately in torrent addition dialog (Stephanos Antaris) (libtorrent >= v0.15 only) - - BUGFIX: Made sure qBittorrent does not scrape the tracker too frequently (libtorrent >= 0.15 only) - - BUGFIX: Fix Paste action in search engine field - - BUGFIX: Fix possible double free in search engine destructor - - BUGFIX: Properly handle trackers error messages - - WEB UI: Remodeled Web UI to match new qBittorrent UI (Properties and preferences available) - - WEB UI: Added internationalization support - - WEB UI: Reduced computation in Javascript (do this one server side instead) - - WEB UI: Fixed Transfer list flickering - - WEB UI: Password is now stored as md5 - - I18N: Added Serbian translation (By Anaximandar Milet) - - COSMETIC: Merged download / upload lists - - COSMETIC: Torrents can be filtered based on their status - - COSMETIC: Torrent properties are now displayed in main window - - COSMETIC: Made program preferences scrollable for usability on small screens (e.g. netbooks) - - COSMETIC: Added a "torrent status" column to transfer list - - COSMETIC: Display Seeds and Peers in two separate columns - - COSMETIC: New deletion confirmation dialog (Merged delete/delete permanently actions) - - COSMETIC: Improved status bar layout spacing - - COSMETIC: Display speeds with more user friendly units instead of always using KiB/s - - COSMETIC: New torrent status icons by Mateusz Tolola - - COSMETIC: Make use of libnotify if available for system notifications (Ubuntu, ...) - -* Tue Nov 17 2009 - Christophe Dumez - v1.5.6 - - BUGFIX: RSS feed articles can now be displayed using keyboard arrows - - BUGFIX: RSS feed downloader can only process unread articles now - - BUGFIX: Fixed memory leak in RSS parser - - BUGFIX: Fixed possible crash in search autocompletion - - BUGFIX: Improved ETA calculation for big torrents - - BUGFIX: Fixed per-torrent speed limiting - -* Wed Nov 4 2009 - Christophe Dumez - v1.5.5 - - BUGFIX: Fixed man page - - BUGFIX: Fix crash on torrent addition (if libtorrent-rasterbar has debug enabled) - - BUGFIX: Fix trackers addition to torrents (bug introduced in v1.5.4) - - BUGFIX: Suppress compilation warning regarding sortNewsList() not being used - - BUGFIX: Make sure scan folder is different than qBittorrent backup directory to avoid torrents deletion - - BUGFIX: Added safety mecanism which adds the torrents back to the list in case qbittorrent-resume.conf gets deleted or corrupted. - -* Sun Oct 25 2009 - Christophe Dumez - v1.5.4 - - BUGFIX: Updated man page - - BUGFIX: Fixed possible crash with torrents containing unicode characters - - BUGFIX: Fixed problem when disabling systray integration and starting minimized - - BUGFIX: Fixed PirateBay search plugin - - BUGFIX: Using Download button in search results list now downloads the right torrents - - BUGFIX: The search results list is no longer sorted automatically when a row color is updated - -* Wed Sep 30 2009 - Christophe Dumez - v1.5.3 - - BUGFIX: Fix a possible crash when pausing then deleting a torrent quickly - - BUGFIX: Fix a race condition in folder scanning and torrent downloader - - BUGFIX: Hide download url column in search results - - BUGFIX: Fix a crash when scanned directory does not exist - - BUGFIX: Fix compilation on Mac OS - - BUGFIX: Added a command line parameter to disable splash screen - - BUGFIX: Ignore permanent deletion button when no torrent is selected - - BUGFIX: When a selected torrent is deleted, select next suitable torrent - -* Sun Sep 20 2009 - Christophe Dumez - v1.5.2 - - BUGFIX: Some torrents were pausing for no reason - - I18N: Updated Korean translation - -* Thu Sep 7 2009 - Christophe Dumez - v1.5.1 - - BUGFIX: Fix crash in torrent addition dialog when save path does not exist (closes #425227) - - BUGFIX: Fix downloading from URL (broken in v1.5.0) - - BUGFIX: Pause torrents in error state - -* Thu Sep 3 2009 - Christophe Dumez - v1.5.0 - - FEATURE: Added Magnet URI support - - FEATURE: Search engine supports category-based requests - - FEATURE: Make use of torrent enclosure in RSS feeds for direct download - - FEATURE: Implemented a RSS feed downloader with filter support - - FEATURE: Save old RSS item to hard disk to remember them on start up - - FEATURE: Display free disk space in torrent addition dialog - - FEATURE: In torrent addition from URL, paste clipboard content if it contains an URL - - FEATURE: RSS feeds URLs can now be copied to clipboard - - FEATURE: RSS feeds can now be grouped into folders - - FEATURE: Added "Unread" item to RSS feed list to display all unread news - - FEATURE: If a torrent contains a torrent file, process downloaded torrent file too - - FEATURE: A random listening port can be chosen automatically - - BUGFIX: torrent resume code rewrited - - BUGFIX: Fixed uTorrent spoofing code - - BUGFIX: Greatly improved column sorting code - - BUGFIX: Possibility to create trackerless torrents - - BUGFIX: Better item coloring in torrent content filtering dialog - - COSMETIC: Redesigned search tab to improve usability - - COSMETIC: Redesigned RSS tab to improve usability - - COSMETIC: Improved tracker errors readability - -* Sun Aug 21 2009 - Christophe Dumez - v1.4.1 - - BUGFIX: Fix problems when changing save path (if using temporary download folder) - - BUGFIX: Display real save path instead of the temporary one in torrent properties - - BUGFIX: Catching invalid_handle exception to avoid rare crashes - - BUGFIX: Fixed popup menu position in RSS feeds list - - BUGFIX: Don't save RSS feed state if it could not be updated - -* Thu Aug 13 2009 - Christophe Dumez - v1.4.0 - - FEATURE: Display swarm information in lists - - FEATURE: Allow to define temporary download folder - - FEATURE: Display total amount of uploaded data in finished list - - FEATURE: Resizing a column in a search results tab affects all tabs - - FEATURE: Search results tab columns are now remembered upon startup - - FEATURE: Added right click menu in search engine to clear completion history - - FEATURE: Allow to set a different port for DHT (UDP) than the one used for Bittorrent - - FEATURE: Updated spoofing code to avoid trackers ban - - BUGFIX: Provide more helpful explanation when an I/O error occured - - BUGFIX: Stop enforcing UTF-8 and use system locale instead - - COSMETIC: Redesigned program preferences - - COSMETIC: Updated icons set - -* Fri Jul 24 2009 - Christophe DUMEZ - 1.3.5 - - BUGFIX: Made IP filter parser more robust - - BUGFIX: Fixed torrent creation tool - - BUGFIX: Fixed possible overflow in progress calculation in arborescence.h - - BUGFIX: Save properties window size, position, columns width and restore them - - BUGFIX: Set a minimum default width for NAME column in properties - - BUGFIX: Remember visual indexes of columns in transfer lists - -* Sun Jul 12 2009 - Christophe DUMEZ - v1.3.4 - - BUGFIX: Fixed IP filter file parsing on 64bits - - BUGFIX: Suppressed QLayout: Attempting to add QLayout "" to properties "properties" warning message when opening a properties dialog - - BUGFIX: Fixed a little bug in search engine plugins helper file - - BUGFIX: Fixed compilation problems with Qt 4.3 - - BUGFIX: Percentages no longer disapear with default cleanlooks style - - BUGFIX: Cleanly fixed popup menus position in lists (no more workarounds) - - BUGFIX: Fixed memory leak in search engine - - BUGFIX: Torrents with an infinite ratio are no longer affected by ratio_limit set in program preferences - - BUGFIX: Display a ratio of 0.0 if total_upload and total_download are both 0 - - BUGFIX: Remove last separator in top tool bar - - BUGFIX: Tuned lists properties to make sure display is correct - - COSMETIC: Display date as well as time in log window - -* Sun Apr 5 2009 - Christophe Dumez - v1.3.3 - - BUGFIX: Fixed Web UI torrent upload form - - BUGFIX: Fixed unicode support in search engine - - BUGFIX: Fixed search engine bug that prevented a torrent from appearing more than once among all tabs - - LICENSE: Added an exception to the license regarding OpenSSL. - - I18N: Updated Finnish translation - -* Sat Mar 7 2009 - Christophe Dumez - v1.3.2 - - BUGFIX: Fix top toolbar disabling - - BUGFIX: Fix building with Qt 4.5 - - BUGFIX: RSS items read status is now remembered upon restart - -* Mon Jan 26 2009 - Christophe Dumez - v1.3.1 - - BUGFIX: Torrents paused due to an I/O error were displayed as queued - - BUGFIX: qBittorrent now prints backtrace in terminal when segfaulting - - BUGFIX: Fixed files progress display in torrent properties - - BUGFIX: Improved torrent ratio calculation - - BUGFIX: Fixed possible crash when parsing filter file - - BUGFIX: Made some code optimization - - BUGFIX: Fixed download/upload speed decrease problems - - I18N: Updated Finnish, Bulgarian and Greek translations - -* Fri Jan 9 2009 - Christophe Dumez - v1.3.0 - - FEATURE: Based on libtorrent-rasterbar v0.14.2 - - FEATURE: Improved ratio calculation system - - FEATURE: Torrent creation code cleanup - - FEATURE: Allow to set maximum number of active seeds (queueing) - - FEATURE: Now seeds priorities are handled automatically by libtorrent-rasterbar (queueing) - - FEATURE: Code cleanup and optimization (save memory and cpu) - - FEATURE: ETA calculation now relies on average speed over all sessions - - FEATURE: Allow to force rechecking torrents - - FEATURE: Added support for 2 new extensions (uTorrent metadata and smart ban plugin) - - FEATURE: Allow to change the save path of torrents after addition - - FEATURE: Got rid of libmagick++ dependency - - FEATURE: Updated Web interface to MochaUI v0.9.5 - - FEATURE: Added notification in WebUI when qBittorrent is not reachable - - FEATURE: Rewrote folder scanning code (Now uses a filesystem watcher) - - FEATURE: Added torrent deletion from hard drive function in Web UI - - FEATURE: Added queueing priority actions in Web UI - - FEATURE: Display progress using progress bars in Web UI - - BUGFIX: Made usage of fastresume data more reliable - - BUGFIX: qBittorrent shutdown is now faster - - BUGFIX: Fixed several memory leaks - - BUGFIX: WebUI is now working with IE7 - - BUGFIX: Fixed spacing problem in toolbar when toggling its visibility - - BUGFIX: Fixed some compilation and Qt4 warnings - - BUGFIX: Do not use an addition dialog for torrents from folder scanning - - BUGFIX: Catch SIGTERM to exit cleanly (e.g. computer shutdown) - - BUGFIX: Improved proxy support code - - BUGFIX: Fixed systray icon tooltip on Windows - - BUGFIX: Proxy settings are now saved even if disabled - -* Sun Nov 9 2008 - Christophe Dumez - v1.2.1 - - BUGFIX: Fixed possible crash when deleting a torrent permanently - - BUGFIX: Queued_for_checking torrents were not displayed as checking in seeding list - - BUGFIX: Speed up startup time when having a lot of torrents - -* Wed Oct 29th 2008 - Christophe Dumez - v1.2.0 - - FEATURE: Torrent queueing system (with priorities) - - FEATURE: The number of DHT nodes is displayed - - FEATURE: RSS can now be disabled from program preferences - - FEATURE: Added collapse/expand all buttons in addition and properties dialogs - - FEATURE: Can have different proxies for Bittorrent and search engine - - FEATURE: Allow multiple item selection in Web UI transfer list - - FEATURE: Moved uploads to a separate list in Web UI - - BUGFIX: Totally rewritten Web UI list refresh system (fixed memory leak) - - BUGFIX: Disable ETA calculation when ETA column is hidden - - BUGFIX: Removed "disconnected" connection state, detection was far from perfect - - BUGFIX: Torrents are no longer starting from scratch when changing default save path (when torrent addition dialog is disabled) - - BUGFIX: Single instance code is now more reliable on Qt >= 4.4 - - COSMETIC: Transfer speed, ratio, connection status and DHT nodes are displayed in status bar - - COSMETIC: RSS Tab is now hidden as a default - - COSMETIC: Allow to hide or display top toolbar - - COSMETIC: Log is now in a separate dialog - -* Sun Sept 14 2008 - Christophe Dumez - v1.1.4 - - FEATURE: DHT is no longer used as fallback only - - FEATURE: Ported WebUI to Mootools v1.2 - - BUGFIX: Fixed 'start seeding after torrent creation' feature - - BUGFIX: Fixed compilation with boost v1.36 - - BUGFIX: Some code optimization - - BUGFIX: Fixed memory leak in Web UI - - BUGFIX: Fixed problems with column sorting - - BUGFIX: Improved code for pausing torrents on startup - - BUGFIX: Torrent addition dialog is now disabled for downloads from WebUI - - BUGFIX: Give focus to input field in WebUI download dialog - -* Tue Aug 26 2008 - Christophe Dumez - v1.1.3 - - BUGFIX: Fixed ratio saving for seeding torrents - - I18N: Added czech and traditional chinese translations - -* Sun Aug 17 2008 - Christophe Dumez - v1.1.2 - - BUGFIX: Fixed progress calculation - - BUGFIX: Fixed finished torrent detection - -* Fri Aug 01 2008 - Christophe Dumez - v1.1.1 - - BUGFIX: Fixed bad resource file for icons - -* Fri Aug 01 2008 - Christophe Dumez - v1.1.0 - - FEATURE: Web interface to control qbittorrent (Ishan Arora) - - FEATURE: Can spoof Azureus peer id to avoid ban - - FEATURE: Allow to hide/show some columns in download and seeding lists - - FEATURE: Option to start qBittorrent minimized in systray - - FEATURE: Multi-tab support in search engine (Grigis Gaëtan) - - FEATURE: Allow to define double-click actions in torrents lists - - FEATURE: Allow to open torrent destination folder - - FEATURE: Real progress bar in torrent properties that displays downloaded pieces - - FEATURE: Allow to buy downloads using ShareMonkey - - FEATURE: Display if UPnP/NAT-PMP was successful or not - - FEATURE: Threadified torrent creation - - FEATURE: Improved eMule DAT ip filter parser - - FEATURE: Added support for PeerGuardian p2p filters (text) - - FEATURE: Added support for PeerGuardian p2b filters (binary) - - FEATURE: Allow to customize folder scan interval - - FEATURE: Allow to add several trackers at once - - BUGFIX: Allow to run one instance of qBittorrent per user - - BUGFIX: Do not display seeds number in seeding list (always 0) - - BUGFIX: Threadified IP filter file parser to avoid GUI freeze - - BUGFIX: Ask if we want to redownload if content was deleted from hard drive - - BUGFIX: Added missing copyright/licensing information for some files - - BUGFIX: qBittorrent is no longer conflicting with rTorrent (libtorrent renamed to libtorrent-rasterbar) - - COSMETIC: Do not display progress bar in seeding list (always 100%) - - COSMETIC: Added a progress bar for torrent creation - - COSMETIC: Display tracker errors in a cleaner way - - COSMETIC: Display "unpaused/total_torrent" in download/upload tabs - - COSMETIC: Allow to resize RSS column - - COSMETIC: Global UP/DL speeds and ratio are displayed above tabs - - COSMETIC: Use infinity symbol for ETA when time is infinite - -* Fri Apr 11 2008 - Christophe Dumez - v1.0.0 - - FEATURE: Based on new libtorrent v0.13 - - FEATURE: Added UPnP / NAT-PMP port forwarding support - - FEATURE: Added encryption support (compatible with Azureus) - - FEATURE: Bittorrent FAST extension support - - FEATURE: Added RSS support - - FEATURE: Support files prioritizing in a torrent - - FEATURE: Brand new search engine plugins system - - FEATURE: Filtered files don't appear on hard disk anymore - - FEATURE: Finished torrents are now moved to another tab for seeding - - FEATURE: Display more infos about the torrent in its properties - - FEATURE: Allow the user to edit torrents' trackers - - FEATURE: Allow user to change qBT's style (Plastique, Cleanlooks, Motif, CDE, MacOSX, WinXP) - - FEATURE: Allow the user to disable system tray integration - - FEATURE: Search engine is now using one thread per website for faster results - - FEATURE: Improved a lot the torrent creation module - - FEATURE: Allow to set upload/download limit per torrent (right click) - - FEATURE: Ask for exit confirmation only if download list is not empty - - FEATURE: Allow to use a proxy for trackers / web seeds / peers / DHT connections - - FEATURE: Supports SOCKS5 proxies as well as HTTP ones - - FEATURE: Better systems integration (buttons, dialogs...) - - FEATURE: Filtered files are not allocated on the hard-drive anymore (sparse file support) - - FEATURE: IPs blocked by filter are now logged in GUI - - FEATURE: Added a way to link against static libtorrent (useful for deb packages) - - FEATURE: Allow to set global upload/download limits from tray icon menu - - FEATURE: IPv6 is now fully supported - - FEATURE: Real torrent share ratio is now displayed in transfer list - - FEATURE: Added keyboard shortcuts for main actions (see wiki) - - FEATURE: Added a popup menu to set priority for multiple files at once - - FEATURE: Improved a lot downloading from urls (using libcommoncpp2 instead of libcurl) - - FEATURE: A search request can now be terminated by another - - FEATURE: User is now warned when fast resume data was rejected - - FEATURE: Url seeds are now displayed in torrent properties and are editable - - FEATURE: Allow to drag 'n drop urls on the main window - - FEATURE: Improved search engine (multipage support in all plugins) - - FEATURE: Added BTJunkie search engine plugin - - FEATURE: Added an option to force full disk allocation for all torrents - - FEATURE: Added an option to add torrents in paused state - - FEATURE: Added an option to set the max number of connections per torrent - - FEATURE: Added an option to set the max number of uploads per torrent - - FEATURE: Added an option to automatically delete torrents when they reach a given ratio (>= 1.0) - - FEATURE: Added an option to display current transfer speeds in title bar - - FEATURE: Torrent content is now displayed as a tree - - I18N: Added Hungarian translation - - I18N: Added Brazilian translation - - BUGFIX: Progress of paused torrents is now correct on restart - - BUGFIX: Progress column gets sorted on restart it is was during last execution - - BUGFIX: Made ETA more reliable using stats instead of instant values - - BUGFIX: Remove torrent from hard drive used to delete parent folder if empty - - BUGFIX: Fixed a crash when filtering all the files in a torrent - - BUGFIX: Reload torrent only when necessary (properties) - - BUGFIX: qBittorrent is not exiting anymore when a dialog is closed and main window is hidden - - BUGFIX: Search plugin update is not making the GUI freeze anymore (moved to a thread) - - BUGFIX: DHT settings were not saved correctly - - BUGFIX: Workaround to build on Fedora system (pkg-config problem) - - BUGFIX: search plugin update - do not display only last version changelog - - BUGFIX: Search plugin update - fixed missing new lines in changelog - - BUGFIX: The number of search results was not reset when clicking on 'Clear' button - - BUGFIX: Update torrent progress when its content changed (filtered files) - - BUGFIX: Improved the way menu icons are installed to avoid problems on some systems - - BUGFIX: Improved incremental download - - BUGFIX: Improved unicode support - - BUGFIX: Made torrent deletion from hard-drive safer - - BUGFIX: Prevent downloadFromUrl flooding - - BUGFIX: ETA was wrong for torrents with filtered files - - BUGFIX: Fixed drag'n drop on non-KDE systems - - BUGFIX: Removed build dependency on Python - - BUGFIX: Catching DHT exception in case there is a problem - - COSMETIC: Redesigned torrent properties a little - - COSMETIC: Totally redesigned program preferences - - COSMETIC: Display more logs messages concerning features - - COSMETIC: Improved lists renderers - - COSMETIC: Use a different icon for torrents being checked and for connecting ones - - COSMETIC: Improved some icons - - COSMETIC: Improved systray tooltip style - -* Mon May 07 2007 - Christophe Dumez - v0.9.3 - - BUGFIX: Fixed pause toggle on double-click in download list - - BUGFIX: The torrent size displayed now only takes unfiltered files into account - - BUGFIX: Fixed compiling errors with libtorrent svn (future v0.13 with UPnP enabled) - - BUGFIX: Remember sorted column in download list on restart - - BUGFIX: Small fix in the german translation - - BUGFIX: Some fixes in slovak translation - -* Tue Apr 10 2007 - Christophe Dumez - v0.9.2 - - BUGFIX: Window can now stay maximized on exit - - BUGFIX: Use PKGCONFIG again for configuring libtorrent - - BUGFIX: Allow to compile with libtorrent v0.11 - - BUGFIX: Disabled main window context menu (annoying) - - I18N: Added Japanese translation - - I18N: Updated Turkish translation - -* Wed Apr 04 2007 - Christophe Dumez - v0.9.1 - - BUGFIX: A lot of fixes in configure file - -* Sun Apr 01 2007 - Christophe Dumez - v0.9.0 - - FEATURE: Based on libtorrent v0.12 - - FEATURE: Based on Qt4.2 - - FEATURE: Brand new trayicon from Qt4.2 - - FEATURE: Support uTorrent Peer Exchange (PeX - exchanges peers between clients) - - FEATURE: Added a menu action to visit qBittorrent website - - FEATURE: Added a menu action to report a bug in qBittorrent - - FEATURE: Improved the way parameters are passed between qBT instances (socket) - - FEATURE: User is warned when hard drive becomes full and downloads are paused - - FEATURE: Number of complete/incomplete sources are now displayed in download list for each torrent - - FEATURE: Implemented close to systray - - FEATURE: Added Autocompletion to search engine - - FEATURE: Splitted BT & GUI parts (huge code rewriting & optimization) - - FEATURE: New parameters for configure file to point to custom locations for libtorrent/libcurl - - FEATURE: Update application style according to the system (WindowsXP, MacOS, X11) - - BUGFIX: Two torrents can now have the same name although they are different (use their hash) - - BUGFIX: Fixed download from url that would fail sometimes - - BUGFIX: Save directory was reset to default when filtering files in torrent - - BUGFIX: Force a refresh of download list when the window is shown (avoid delay) - - BUGFIX: Fixed deletion from hard drive (failed for non-empty folders) - - BUGFIX: qBittorrent now identifies its version correctly on the network - - BUGFIX: Preventing GUI from freezing when deleting a download permanently - - BUGFIX: Fixed directory scanning (stop trying to download the same files several times) - - BUGFIX: Fixed bad loading of scan dir in option (widgets still disabled) - - BUGFIX: Threads are now stopped cleanly before their destruction - - BUGFIX: Create Options object only when necessary (to save memory) - - BUGFIX: Let libtorrent store the torrent handles (save memory) - - BUGFIX: Set DHT Port only when DHT is enabled - - BUGFIX: Made ipfilter.dat parser less sensitive to errors - - BUGFIX: Bring main window to foreground when asking for exit confirmation - - I18N: Added Danish translation - - I18N: Better internationalization thanks to dynamic text support - - COSMETIC: Replaced OSD messages by Qt4.2 systray messages - -* Tue Nov 28 2006 - Christophe Dumez - v0.8.0 - - FEATURE: Added a torrent addition dialog - - FEATURE: Allow user to change DHT port - - FEATURE: Added an action to remove files from download list and hard drive too - - FEATURE: Rewritten intensively options code - - FEATURE: Remember GUI settings in a cleaner way on restart - - I18N: Added Finnish translation - - I18N: Improved Italian translation a lot - - BUGFIX: Enabled debug with Qt 4.2.1 too because Trolltech didn't fix their bug yet - - BUGFIX: Fixed layout in torrent properties - - BUGFIX: Made right click menu work for multiple selection in DL list - - BUGFIX: Fixed utf-8 support in paths and filenames - - BUGFIX: Could only listen on the first IP of the given range - - COSMETIC: Connection status in toolBar is not clickable anymore - - COSMETIC: Displaying save path in torrent properties window - - COSMETIC: Reworked options window a little - - COSMETIC: Remember mainwindow position during last execution - -* Mon Oct 16 2006 - Christophe Dumez - v0.7.1 - - I18N: Updated French, Polish, Dutch, Swedish, Slovak translations - - BUGFIX: Fixed Seeds/Leechers display in torrent properties - - BUGFIX: Fixed finished torrent state on restart - - BUGFIX: Fixed trayicon with Qt 4.2 - - BUGFIX: Enabling debug when Qt 4.2.0 is detected (because of a bug in this Qt) - - BUGFIX: Fixed new lines in log widget with Qt 4.2 - - BUGFIX: Display errors to stderr instead of stdout - - BUGFIX: Forgot to catch invalid_handle exception thrown by libtorrent - - BUGFIX: Close torrents properties windows when they are deleted - - BUGFIX: Fixed prefix in Makefile - -* Fri Oct 13 2006 - Christophe Dumez - v0.7.0 - - FEATURE: Based on new libtorrent v0.11 (a lot of bugfixes, new features) - - FEATURE: Added DHT (Trackerless - Decentralized BT) support - - FEATURE: Audio/Video File previewing while downloading - - FEATURE: Added support for incremental download (slower but great for previewing) - - FEATURE: Added Tracker authentication support - - FEATURE: Defined qBittorrent fingerprint so that it doesn't use libtorrent fingerprint anymore - - FEATURE: Display an explicit error message when a download from url fails - - FEATURE: Allow the download multiple torrents from urls at once - - FEATURE: New context menu on main window (Add, Start all, Pause all, Exit...) - - FEATURE: Now supports one new search engines (MegaNova) - - FEATURE: Rewritten search engine plugin (by fab31) - - FEATURE: Rewritten parts of the download/search lists to improve performance - - FEATURE: Individual share ratio is now displayed in each torrent properties. - - FEATURE: Tuned default settings to improve download speed - - FEATURE: Downloading from an URL will retry 10 times if too many users. - - FEATURE: Now remembers filtered pieces in a torrent on restart - - FEATURE: Now updating pieces progress in real time in torrent properties - - I18N: Added Norwegian translation - - BUGFIX: Fixed a memory leak when pressing OK in torrent properties - - BUGFIX: Improved code so that GUI never freeze during downloading from an url - - BUGFIX: Forgot to remove torrent file from scanned directory when "Clear Finished torrents" is enabled - - BUGFIX: Fixed multiple selection in torrent content tab - - BUGFIX: Improved configure file (detects libboost-thread) - - BUGFIX: Fixed trayicon on some window managers (Gnome, XFCE) - - BUGFIX: Always set maximum limit for connection depending on system - - BUGFIX: Fixed Memory leaks in search engine - - BUGFIX: Remove torrent file from scanned directory if it is already in download list - - BUGFIX: Fixed possible segfault on loading due to columns size loading - - BUGFIX: Fixed problems that could happen with delete selection action - - BUGFIX: Fixed an arithmetic exception that could happen in ETA calculation - - BUGFIX: Fixed Isohunt search engine - - BUGFIX: Fixed download from URL function (was buggy) - - BUGFIX: Fixed download button in search engine - - BUGFIX: Fixed selective download - - BUGFIX: Fixed memory leaks in torrent properties - - BUGFIX: Fixed tooltip behaviour for trayicon - - BUGFIX: Fixed Ipfilter.dat loading - - BUGFIX: Not loading options every time we display options anymore - - COSMETIC: Now displaying the number of downloads in tab title - - COSMETIC: Redesigned download from url dialog - - COSMETIC: Added a message to warn user that we started download from an url - - COSMETIC: Renamed main tab from "Downloads" to "Transfers" - - COSMETIC: Improved icons - - COSMETIC: Resized flags in localization settings - - COSMETIC: Improved trayicon image - -* Fri Aug 24 2006 - Christophe Dumez - v0.6.1 - - BUGFIX: Fixed possible segfaults when using context menus - - BUGFIX: Cleanup up context menus code - - BUGFIX: Use best gzip compressing for man page - -* Wed Aug 22 2006 - Christophe Dumez - v0.6.0 - - FEATURE: Rewritten the download list from scratch (more flexible) - - FEATURE: Rewritten the search results list from scratch (more flexible) - - FEATURE: Rewritten the torrent properties list from scratch (more flexible) - - FEATURE: Improved and cleaned up search engine code - - FEATURE: Search results are now displayed in real time (not sequentially) - - FEATURE: Added two command lines parameters (--version, --help) - - FEATURE: Added a popup menu for download list - - FEATURE: Double-click on an item now toggles the paused state of a download - - FEATURE: Improved code to be more portable (Windows & MacOS versions should arrive soon) - - FEATURE: Allow to toggle selected state of a file within a torrent using double-click - - FEATURE: Remember columns width in download and search results lists - - BUGFIX: Don't use pkg-config for libcurl anymore (easier to compile) - - BUGFIX: Fixed ETA calculation when downloading while connecting - - BUGFIX: Download progress is now displayed correctly during first seconds of execution (was 0% before) - - BUGFIX: Code cleanup & optimization - - BUGFIX: Fixed sorting in download list - - BUGFIX: Fixed sorting in search results list - - BUGFIX: Fixed Parameters passing between instances - - BUGFIX: Fixed missing icon for clear action in infoBar popup menu - - BUGFIX: Fixed truncated lines in search results - - BUGFIX: Don't refresh download list when user is in search tab (save CPU) - - BUGFIX: Don't update Progress/DL Speed/ETA for finished downloads (save CPU) - - BUGFIX: Save selected search engines only when they have changed (faster program exit) - - COSMETIC: Increased icon size in toolbar from 24px to 32px - - COSMETIC: Display a progress bar to visualize each download progress - - COSMETIC: Size of each result in search are displayed in user friendly units - - COSMETIC: Display a progress bar to visualize each file progress within a torrent - - COSMETIC: Renamed 'ratio' to 'Session ratio' (makes more sense) - - COSMETIC: Improved layout of torrent properties window when maximized - - COSMETIC: Now number of search results is updated in real time - - COSMETIC: Remember last window size - - COSMETIC: Improved splash screen look - - COSMETIC: Improved default width of columns in download and search results lists - -* Wed Aug 2 2006 - Christophe Dumez - v0.5.0 - - FEATURE: Improved "Download from url" feature (now supports https, ftp & redirections) - - FEATURE: Added a torrent creation tool - - FEATURE: Display progress for each file within a torrent - - FEATURE: Based on new libtorrent v0.10 (lot of improvements) - - FEATURE: Now possible to clear log textbox (popup menu) - - FEATURE: Added two search engines (isohunt, torrentreactor) - - FEATURE: Now Display share ratio on main window - - FEATURE: Use OSD (On Screen Display) when a download or a search is finished - - FEATURE: Allow only one instance of qBittorrent (and add new parameters to download list) - - FEATURE: Remember last selected search engines in search tab - - FEATURE: Improved search engines status output (Aborted, timed out, finished, no results) - - FEATURE: qBittorrent can now update search plugin from qbittorrent.org - - I18N: Added Slovak, Italian, Portuguese, Romanian and Traditional Chinese languages - - BUGFIX: Fixed ThePirateBay parser for search engine (website had changed) - - BUGFIX: Fixed filenames for results from ThePirateBay search engine - - BUGFIX: Fixed unicode support for ThePirateBay search engine - - BUGFIX: Now search results are sorted by seeds - - BUGFIX: Overwrite nova.py search plugin only if it is outdated - - BUGFIX: Fixed possible division by 0 in ETA calculation - - BUGFIX: Improved ETA calculation precision - - BUGFIX: Fixed default tab in options - - BUGFIX: When saving options, reconnect only when listening ports changed - - COSMETIC: qBittorrent has now its own new logo - - COSMETIC: Display status "downloading" if DL Speed > 0 (even when tracker is down) - - COSMETIC: Added a splashscreen - - COSMETIC: qBittorrent has new cute icons - - COSMETIC: Display number of results in search tab - - COSMETIC: Added icons for each item in download list according to its state - - COSMETIC: Redesigned Locale settings - - COSMETIC: Fixed search engines names width (were cut on the right) - - COSMETIC: Moved search engines to the left of the window (better ui) - -* Fri Jun 23 2006 - Christophe Dumez - v0.4.1 - - Not counting "protocol chatter" in UP/DL speed anymore - - Download speed is now 0 when download is finished - - Paused torrents remain paused when qbittorrent is re-started - - Added option "go to systray when minimizing" - - Added option "Clear finished downloads on exit" - - Added option "Ask user for confirmation on exit" - - Added "Stalled" status for downloads (colored in orange, paused are in red and finished in green) - - Fixed Search window layout on maximizing - - Fixed a bug that caused upload limit not to be always applied - - Added Bulgarian translation - - Updated Translations - - Code optimization - -* Tue Jun 13 2006 - Christophe Dumez - v0.4.0 - - Added a search engine (supports Mininova & thepiratebay websites) - - Fixed critical bug: some options were not applied correctly to BT session - - Possibility to download a torrent file from an URL - - Added confirmation dialog on qbittorrent exit - - Enabled sorting in Download list - - Added Ukrainian translation - - Support urls as program parameters - - Added more actions to trayicon menu - - Fixed exception catching when retrieving fastresume data - - use Binary prefix standards from IEC 60027-2 for units (B, KiB, MiB, GiB, TiB) - - Iconification to systray when minimizing - - Code Cleanup & optimization - -* Tue Jun 06 2006 - Christophe Dumez - v0.3.1 - - Fixed toolbar layout (spacing) - - Added Russian translation - - Resume also finished files on startup (for seeding) - - Added colors corresponding to download state - - Fixed a segfault when deleting a download (if no scan dir is set) - -* Mon Jun 05 2006 - Christophe Dumez - v0.3 - - Fixed auto-resume (worked only once) - - Fixed BT_Backup dir creation on first startup (thanks Peter) - - Now min port and max port are inverted if (min port > max port) - - Fixed memory leaks - - Added qbittorrent man page - - Allow to disable max connections limit (default is disabled) - - Disable upload limit by default - - Added Menu Entry with icon (thanks Peter) - - Restructured directory, now Makefile is in main directory (not src/) - - Updated README / INSTALL - -* Fri Jun 02 2006 - Christophe Dumez - v0.2.3 - - Fixed ports checking function (user couldn't type the value he wanted) - - qBittorrent does not remove .torrent file from scanned directory anymore - - Check tracker errors list size and clear it if it becomes too big. - - Small cosmetic change - -* Wed May 31 2006 - Christophe Dumez - v0.2.2 - - Fixed missing icons - -* Thu May 25 2006 - Christophe Dumez - v0.2.1 - - Fixed "make install" rule - - Disabled debug mode - -* Thu May 25 2006 - Christophe Dumez - v0.2 - - Fixed a compatibility problem with some versions of qmake - - Added translations : Greek, Swedish - - Fixed Polish translation selection - - Fixed come warning because of two unexisting slots - - Improved "Apply" button behaviour in options - - Windows are now resizable - -* Tue May 16 2006 - Christophe Dumez - v0.1 - - Initial release (lack features & still need a lot of improvements) diff --git a/INSTALL b/INSTALL deleted file mode 100644 index bc84b7d98..000000000 --- a/INSTALL +++ /dev/null @@ -1,54 +0,0 @@ -qBittorrent - A BitTorrent client in C++ / Qt4 ------------------------------------------- - -1) Compile and install qBittorrent with Qt4 Graphical Interface - - $ ./configure - $ make && make install - $ qbittorrent - - will install and execute qBittorrent hopefully without any problems. - - Dependencies: - - Qt >= 4.6.0 (libqtgui, libqtcore, libqtnetwork, libqtxml, libqtdbus/optional) - - - pkg-config executable - - - libtorrent-rasterbar by Arvid Norberg (>= 1.0.6) - -> http://www.libtorrent.net - Be careful: another library (the one used by rTorrent) uses a similar name. - - - libboost >= 1.35.x (libboost-system) - - - python >= 2.3 (needed by search engine) - * Run time only dependency - - - 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 - -2) Compile and install qBittorrent without Qt4 Graphical interface - - $ ./configure --disable-gui - $ make && make install - $ qbittorrent - - will install and execute qBittorrent hopefully without any problems. - - Dependencies: - - Qt >= 4.4.0 (libqt-devel, libqtcore, libqtnetwork) - - - pkg-config executable - - - libtorrent-rasterbar by Arvid Norberg (>= v1.0.6) - -> http://www.libtorrent.net - Be careful: another library (the one used by rTorrent) uses a similar name. - - - libboost: libboost-filesystem, libboost-date-time, libboost-thread, libboost-serialization - - -DOCUMENTATION: -Please note that there is a documentation with a "compiling howto" at http://wiki.qbittorrent.org. - ------------------------------------------- -Christophe Dumez diff --git a/NEWS b/NEWS deleted file mode 100644 index 96b13e5a6..000000000 --- a/NEWS +++ /dev/null @@ -1,4 +0,0 @@ -See Changelog - -******************************************* -Christophe dumez - chris@qbittorrent.org diff --git a/README.md b/README.md deleted file mode 100644 index 79f7e2a9d..000000000 --- a/README.md +++ /dev/null @@ -1,53 +0,0 @@ -qBittorrent - A BitTorrent client in Qt ------------------------------------------- - -[![TravisCI Status](https://travis-ci.org/qbittorrent/qBittorrent.svg?branch=master)](https://travis-ci.org/qbittorrent/qBittorrent) -[![AppVeyor Status](https://ci.appveyor.com/api/projects/status/github/qbittorrent/qBittorrent?branch=master&svg=true)](https://ci.appveyor.com/project/qbittorrent/qBittorrent) -[![Coverity Status](https://scan.coverity.com/projects/5494/badge.svg)](https://scan.coverity.com/projects/5494) -******************************** -### Description: -qBittorrent is a bittorrent client programmed in C++ / Qt that uses -libtorrent (sometimes called libtorrent-rasterbar) by Arvid Norberg. - -It aims to be a good alternative to all other bittorrent clients -out there. qBittorrent is fast, stable and provides unicode -support as well as many features. - -This product includes GeoLite data created by MaxMind, available from -https://www.maxmind.com/ - -### 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. - -### Public key: -Starting from v3.3.4 all source tarballs and binaries are signed.
-The key currently used is 4096R/[5B7CC9A2](https://pgp.mit.edu/pks/lookup?op=get&search=0x6E4A2D025B7CC9A2) with fingerprint `D8F3DA77AAC6741053599C136E4A2D025B7CC9A2`.
-You can also download it from [here](https://github.com/qbittorrent/qBittorrent/raw/master/5B7CC9A2.asc).
-**PREVIOUSLY** the following key was used to sign the v3.3.4 source tarballs and v3.3.4 Windows installer **only**: 4096R/[520EC6F6](https://pgp.mit.edu/pks/lookup?op=get&search=0xA1ACCAE4520EC6F6) with fingerprint `F4A5FD201B117B1C2AB590E2A1ACCAE4520EC6F6`.
- -### Misc: -For more information please visit: -http://www.qbittorrent.org - -or our wiki here: -http://wiki.qbittorrent.org - -Use the forum for troubleshooting before reporting bugs: -http://forum.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` - ------------------------------------------- -sledgehammer999 diff --git a/README.os2 b/README.os2 deleted file mode 100644 index 13551c93f..000000000 --- a/README.os2 +++ /dev/null @@ -1,74 +0,0 @@ -qBittorrent - A BitTorrent client in Qt4 ------------------------------------------- - -This is the eComStation (OS/2) qBittorrent part of the readme. See also README for more general information. - - -Building qBittorrent -******************** - - -Requirements -============ - -- gcc based build env (recommended gcc v4.4.2 or greater) - -- Qt4 for eCS (OS/2) dev package (see http://svn.netlabs.org/qt4 for more information) - -- libtorrent-rasterbar for eCS (OS/2) port (see http://svn.netlabs.org/ports for more information) - -- boost for eCS (OS/2) port (see http://svn.netlabs.org/ports for more information) - - -How to build -============ - -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 begin ##### -BINDIR = ./bin -INCDIR = ./include -LIBDIR = ./lib -DATADIR = ./share - -CONFIG += staticlib -INCLUDEPATH += x:/trees/libtorrent/trunk/include -LIBS += -Lx:/trees/libtorrent/trunk/src/.libs \ - -Lx:/trees/boost/trunk/stage/lib \ - -Lx:/trees/openssl \ - -Lx:/extras/lib -##### conf.pri content end ##### - -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: - -Simply type: -$ 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: -#netlabs on irc.freenode.net - ------------------------------------------- -Silvan Scherrer - - diff --git a/TODO b/TODO deleted file mode 100644 index c79698771..000000000 --- a/TODO +++ /dev/null @@ -1,2 +0,0 @@ -See https://blueprints.launchpad.net/qbittorrent/ - diff --git a/bootstrap.sh b/bootstrap.sh deleted file mode 100755 index f005e2ec8..000000000 --- a/bootstrap.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/sh - -aclocal -I m4 -autoconf diff --git a/build-aux/compile b/build-aux/compile deleted file mode 100755 index a85b723c7..000000000 --- a/build-aux/compile +++ /dev/null @@ -1,347 +0,0 @@ -#! /bin/sh -# Wrapper for compilers which do not understand '-c -o'. - -scriptversion=2012-10-14.11; # UTC - -# Copyright (C) 1999-2014 Free Software Foundation, Inc. -# Written by Tom Tromey . -# -# 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, 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, see . - -# As a special exception to the GNU General Public License, if you -# distribute this file as part of a program that contains a -# configuration script generated by Autoconf, you may include it under -# the same distribution terms that you use for the rest of that program. - -# This file is maintained in Automake, please report -# bugs to or send patches to -# . - -nl=' -' - -# We need space, tab and new line, in precisely that order. Quoting is -# there to prevent tools from complaining about whitespace usage. -IFS=" "" $nl" - -file_conv= - -# func_file_conv build_file lazy -# Convert a $build file to $host form and store it in $file -# Currently only supports Windows hosts. If the determined conversion -# type is listed in (the comma separated) LAZY, no conversion will -# take place. -func_file_conv () -{ - file=$1 - case $file in - / | /[!/]*) # absolute file, and not a UNC file - if test -z "$file_conv"; then - # lazily determine how to convert abs files - case `uname -s` in - MINGW*) - file_conv=mingw - ;; - CYGWIN*) - file_conv=cygwin - ;; - *) - file_conv=wine - ;; - esac - fi - case $file_conv/,$2, in - *,$file_conv,*) - ;; - mingw/*) - file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'` - ;; - cygwin/*) - file=`cygpath -m "$file" || echo "$file"` - ;; - wine/*) - file=`winepath -w "$file" || echo "$file"` - ;; - esac - ;; - esac -} - -# func_cl_dashL linkdir -# Make cl look for libraries in LINKDIR -func_cl_dashL () -{ - func_file_conv "$1" - if test -z "$lib_path"; then - lib_path=$file - else - lib_path="$lib_path;$file" - fi - linker_opts="$linker_opts -LIBPATH:$file" -} - -# func_cl_dashl library -# Do a library search-path lookup for cl -func_cl_dashl () -{ - lib=$1 - found=no - save_IFS=$IFS - IFS=';' - for dir in $lib_path $LIB - do - IFS=$save_IFS - if $shared && test -f "$dir/$lib.dll.lib"; then - found=yes - lib=$dir/$lib.dll.lib - break - fi - if test -f "$dir/$lib.lib"; then - found=yes - lib=$dir/$lib.lib - break - fi - if test -f "$dir/lib$lib.a"; then - found=yes - lib=$dir/lib$lib.a - break - fi - done - IFS=$save_IFS - - if test "$found" != yes; then - lib=$lib.lib - fi -} - -# func_cl_wrapper cl arg... -# Adjust compile command to suit cl -func_cl_wrapper () -{ - # Assume a capable shell - lib_path= - shared=: - linker_opts= - for arg - do - if test -n "$eat"; then - eat= - else - case $1 in - -o) - # configure might choose to run compile as 'compile cc -o foo foo.c'. - eat=1 - case $2 in - *.o | *.[oO][bB][jJ]) - func_file_conv "$2" - set x "$@" -Fo"$file" - shift - ;; - *) - func_file_conv "$2" - set x "$@" -Fe"$file" - shift - ;; - esac - ;; - -I) - eat=1 - func_file_conv "$2" mingw - set x "$@" -I"$file" - shift - ;; - -I*) - func_file_conv "${1#-I}" mingw - set x "$@" -I"$file" - shift - ;; - -l) - eat=1 - func_cl_dashl "$2" - set x "$@" "$lib" - shift - ;; - -l*) - func_cl_dashl "${1#-l}" - set x "$@" "$lib" - shift - ;; - -L) - eat=1 - func_cl_dashL "$2" - ;; - -L*) - func_cl_dashL "${1#-L}" - ;; - -static) - shared=false - ;; - -Wl,*) - arg=${1#-Wl,} - save_ifs="$IFS"; IFS=',' - for flag in $arg; do - IFS="$save_ifs" - linker_opts="$linker_opts $flag" - done - IFS="$save_ifs" - ;; - -Xlinker) - eat=1 - linker_opts="$linker_opts $2" - ;; - -*) - set x "$@" "$1" - shift - ;; - *.cc | *.CC | *.cxx | *.CXX | *.[cC]++) - func_file_conv "$1" - set x "$@" -Tp"$file" - shift - ;; - *.c | *.cpp | *.CPP | *.lib | *.LIB | *.Lib | *.OBJ | *.obj | *.[oO]) - func_file_conv "$1" mingw - set x "$@" "$file" - shift - ;; - *) - set x "$@" "$1" - shift - ;; - esac - fi - shift - done - if test -n "$linker_opts"; then - linker_opts="-link$linker_opts" - fi - exec "$@" $linker_opts - exit 1 -} - -eat= - -case $1 in - '') - echo "$0: No command. Try '$0 --help' for more information." 1>&2 - exit 1; - ;; - -h | --h*) - cat <<\EOF -Usage: compile [--help] [--version] PROGRAM [ARGS] - -Wrapper for compilers which do not understand '-c -o'. -Remove '-o dest.o' from ARGS, run PROGRAM with the remaining -arguments, and rename the output as expected. - -If you are trying to build a whole package this is not the -right script to run: please start by reading the file 'INSTALL'. - -Report bugs to . -EOF - exit $? - ;; - -v | --v*) - echo "compile $scriptversion" - exit $? - ;; - cl | *[/\\]cl | cl.exe | *[/\\]cl.exe ) - func_cl_wrapper "$@" # Doesn't return... - ;; -esac - -ofile= -cfile= - -for arg -do - if test -n "$eat"; then - eat= - else - case $1 in - -o) - # configure might choose to run compile as 'compile cc -o foo foo.c'. - # So we strip '-o arg' only if arg is an object. - eat=1 - case $2 in - *.o | *.obj) - ofile=$2 - ;; - *) - set x "$@" -o "$2" - shift - ;; - esac - ;; - *.c) - cfile=$1 - set x "$@" "$1" - shift - ;; - *) - set x "$@" "$1" - shift - ;; - esac - fi - shift -done - -if test -z "$ofile" || test -z "$cfile"; then - # If no '-o' option was seen then we might have been invoked from a - # pattern rule where we don't need one. That is ok -- this is a - # normal compilation that the losing compiler can handle. If no - # '.c' file was seen then we are probably linking. That is also - # ok. - exec "$@" -fi - -# Name of file we expect compiler to create. -cofile=`echo "$cfile" | sed 's|^.*[\\/]||; s|^[a-zA-Z]:||; s/\.c$/.o/'` - -# Create the lock directory. -# Note: use '[/\\:.-]' here to ensure that we don't use the same name -# that we are using for the .o file. Also, base the name on the expected -# object file name, since that is what matters with a parallel build. -lockdir=`echo "$cofile" | sed -e 's|[/\\:.-]|_|g'`.d -while true; do - if mkdir "$lockdir" >/dev/null 2>&1; then - break - fi - sleep 1 -done -# FIXME: race condition here if user kills between mkdir and trap. -trap "rmdir '$lockdir'; exit 1" 1 2 15 - -# Run the compile. -"$@" -ret=$? - -if test -f "$cofile"; then - test "$cofile" = "$ofile" || mv "$cofile" "$ofile" -elif test -f "${cofile}bj"; then - test "${cofile}bj" = "$ofile" || mv "${cofile}bj" "$ofile" -fi - -rmdir "$lockdir" -exit $ret - -# Local Variables: -# mode: shell-script -# sh-indentation: 2 -# eval: (add-hook 'write-file-hooks 'time-stamp) -# time-stamp-start: "scriptversion=" -# time-stamp-format: "%:y-%02m-%02d.%02H" -# time-stamp-time-zone: "UTC" -# time-stamp-end: "; # UTC" -# End: diff --git a/build-aux/config.guess b/build-aux/config.guess deleted file mode 100755 index 6c32c8645..000000000 --- a/build-aux/config.guess +++ /dev/null @@ -1,1421 +0,0 @@ -#! /bin/sh -# Attempt to guess a canonical system name. -# Copyright 1992-2014 Free Software Foundation, Inc. - -timestamp='2014-11-04' - -# This file 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 3 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, see . -# -# As a special exception to the GNU General Public License, if you -# distribute this file as part of a program that contains a -# configuration script generated by Autoconf, you may include it under -# the same distribution terms that you use for the rest of that -# program. This Exception is an additional permission under section 7 -# of the GNU General Public License, version 3 ("GPLv3"). -# -# Originally written by Per Bothner; maintained since 2000 by Ben Elliston. -# -# You can get the latest version of this script from: -# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD -# -# Please send patches to . - - -me=`echo "$0" | sed -e 's,.*/,,'` - -usage="\ -Usage: $0 [OPTION] - -Output the configuration name of the system \`$me' is run on. - -Operation modes: - -h, --help print this help, then exit - -t, --time-stamp print date of last modification, then exit - -v, --version print version number, then exit - -Report bugs and patches to ." - -version="\ -GNU config.guess ($timestamp) - -Originally written by Per Bothner. -Copyright 1992-2014 Free Software Foundation, Inc. - -This is free software; see the source for copying conditions. There is NO -warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." - -help=" -Try \`$me --help' for more information." - -# Parse command line -while test $# -gt 0 ; do - case $1 in - --time-stamp | --time* | -t ) - echo "$timestamp" ; exit ;; - --version | -v ) - echo "$version" ; exit ;; - --help | --h* | -h ) - echo "$usage"; exit ;; - -- ) # Stop option processing - shift; break ;; - - ) # Use stdin as input. - break ;; - -* ) - echo "$me: invalid option $1$help" >&2 - exit 1 ;; - * ) - break ;; - esac -done - -if test $# != 0; then - echo "$me: too many arguments$help" >&2 - exit 1 -fi - -trap 'exit 1' 1 2 15 - -# CC_FOR_BUILD -- compiler used by this script. Note that the use of a -# compiler to aid in system detection is discouraged as it requires -# temporary files to be created and, as you can see below, it is a -# headache to deal with in a portable fashion. - -# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still -# use `HOST_CC' if defined, but it is deprecated. - -# Portable tmp directory creation inspired by the Autoconf team. - -set_cc_for_build=' -trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; -trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; -: ${TMPDIR=/tmp} ; - { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || - { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } || - { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || - { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; -dummy=$tmp/dummy ; -tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; -case $CC_FOR_BUILD,$HOST_CC,$CC in - ,,) echo "int x;" > $dummy.c ; - for c in cc gcc c89 c99 ; do - if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then - CC_FOR_BUILD="$c"; break ; - fi ; - done ; - if test x"$CC_FOR_BUILD" = x ; then - CC_FOR_BUILD=no_compiler_found ; - fi - ;; - ,,*) CC_FOR_BUILD=$CC ;; - ,*,*) CC_FOR_BUILD=$HOST_CC ;; -esac ; set_cc_for_build= ;' - -# This is needed to find uname on a Pyramid OSx when run in the BSD universe. -# (ghazi@noc.rutgers.edu 1994-08-24) -if (test -f /.attbin/uname) >/dev/null 2>&1 ; then - PATH=$PATH:/.attbin ; export PATH -fi - -UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown -UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown -UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown -UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown - -case "${UNAME_SYSTEM}" in -Linux|GNU|GNU/*) - # If the system lacks a compiler, then just pick glibc. - # We could probably try harder. - LIBC=gnu - - eval $set_cc_for_build - cat <<-EOF > $dummy.c - #include - #if defined(__UCLIBC__) - LIBC=uclibc - #elif defined(__dietlibc__) - LIBC=dietlibc - #else - LIBC=gnu - #endif - EOF - eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC' | sed 's, ,,g'` - ;; -esac - -# Note: order is significant - the case branches are not exclusive. - -case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in - *:NetBSD:*:*) - # NetBSD (nbsd) targets should (where applicable) match one or - # more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*, - # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently - # switched to ELF, *-*-netbsd* would select the old - # object file format. This provides both forward - # compatibility and a consistent mechanism for selecting the - # object file format. - # - # Note: NetBSD doesn't particularly care about the vendor - # portion of the name. We always set it to "unknown". - sysctl="sysctl -n hw.machine_arch" - UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \ - /usr/sbin/$sysctl 2>/dev/null || echo unknown)` - case "${UNAME_MACHINE_ARCH}" in - armeb) machine=armeb-unknown ;; - arm*) machine=arm-unknown ;; - sh3el) machine=shl-unknown ;; - sh3eb) machine=sh-unknown ;; - sh5el) machine=sh5le-unknown ;; - *) machine=${UNAME_MACHINE_ARCH}-unknown ;; - esac - # The Operating System including object format, if it has switched - # to ELF recently, or will in the future. - case "${UNAME_MACHINE_ARCH}" in - arm*|i386|m68k|ns32k|sh3*|sparc|vax) - eval $set_cc_for_build - if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ - | grep -q __ELF__ - then - # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). - # Return netbsd for either. FIX? - os=netbsd - else - os=netbsdelf - fi - ;; - *) - os=netbsd - ;; - esac - # The OS release - # Debian GNU/NetBSD machines have a different userland, and - # thus, need a distinct triplet. However, they do not need - # kernel version information, so it can be replaced with a - # suitable tag, in the style of linux-gnu. - case "${UNAME_VERSION}" in - Debian*) - release='-gnu' - ;; - *) - release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` - ;; - esac - # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: - # contains redundant information, the shorter form: - # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. - echo "${machine}-${os}${release}" - exit ;; - *:Bitrig:*:*) - UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'` - echo ${UNAME_MACHINE_ARCH}-unknown-bitrig${UNAME_RELEASE} - exit ;; - *:OpenBSD:*:*) - UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` - echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE} - exit ;; - *:ekkoBSD:*:*) - echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE} - exit ;; - *:SolidBSD:*:*) - echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE} - exit ;; - macppc:MirBSD:*:*) - echo powerpc-unknown-mirbsd${UNAME_RELEASE} - exit ;; - *:MirBSD:*:*) - echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE} - exit ;; - alpha:OSF1:*:*) - case $UNAME_RELEASE in - *4.0) - UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` - ;; - *5.*) - UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` - ;; - esac - # According to Compaq, /usr/sbin/psrinfo has been available on - # OSF/1 and Tru64 systems produced since 1995. I hope that - # covers most systems running today. This code pipes the CPU - # types through head -n 1, so we only detect the type of CPU 0. - ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` - case "$ALPHA_CPU_TYPE" in - "EV4 (21064)") - UNAME_MACHINE="alpha" ;; - "EV4.5 (21064)") - UNAME_MACHINE="alpha" ;; - "LCA4 (21066/21068)") - UNAME_MACHINE="alpha" ;; - "EV5 (21164)") - UNAME_MACHINE="alphaev5" ;; - "EV5.6 (21164A)") - UNAME_MACHINE="alphaev56" ;; - "EV5.6 (21164PC)") - UNAME_MACHINE="alphapca56" ;; - "EV5.7 (21164PC)") - UNAME_MACHINE="alphapca57" ;; - "EV6 (21264)") - UNAME_MACHINE="alphaev6" ;; - "EV6.7 (21264A)") - UNAME_MACHINE="alphaev67" ;; - "EV6.8CB (21264C)") - UNAME_MACHINE="alphaev68" ;; - "EV6.8AL (21264B)") - UNAME_MACHINE="alphaev68" ;; - "EV6.8CX (21264D)") - UNAME_MACHINE="alphaev68" ;; - "EV6.9A (21264/EV69A)") - UNAME_MACHINE="alphaev69" ;; - "EV7 (21364)") - UNAME_MACHINE="alphaev7" ;; - "EV7.9 (21364A)") - UNAME_MACHINE="alphaev79" ;; - esac - # A Pn.n version is a patched version. - # A Vn.n version is a released version. - # A Tn.n version is a released field test version. - # A Xn.n version is an unreleased experimental baselevel. - # 1.2 uses "1.2" for uname -r. - echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` - # Reset EXIT trap before exiting to avoid spurious non-zero exit code. - exitcode=$? - trap '' 0 - exit $exitcode ;; - Alpha\ *:Windows_NT*:*) - # How do we know it's Interix rather than the generic POSIX subsystem? - # Should we change UNAME_MACHINE based on the output of uname instead - # of the specific Alpha model? - echo alpha-pc-interix - exit ;; - 21064:Windows_NT:50:3) - echo alpha-dec-winnt3.5 - exit ;; - Amiga*:UNIX_System_V:4.0:*) - echo m68k-unknown-sysv4 - exit ;; - *:[Aa]miga[Oo][Ss]:*:*) - echo ${UNAME_MACHINE}-unknown-amigaos - exit ;; - *:[Mm]orph[Oo][Ss]:*:*) - echo ${UNAME_MACHINE}-unknown-morphos - exit ;; - *:OS/390:*:*) - echo i370-ibm-openedition - exit ;; - *:z/VM:*:*) - echo s390-ibm-zvmoe - exit ;; - *:OS400:*:*) - echo powerpc-ibm-os400 - exit ;; - arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) - echo arm-acorn-riscix${UNAME_RELEASE} - exit ;; - arm*:riscos:*:*|arm*:RISCOS:*:*) - echo arm-unknown-riscos - exit ;; - SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) - echo hppa1.1-hitachi-hiuxmpp - exit ;; - Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) - # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. - if test "`(/bin/universe) 2>/dev/null`" = att ; then - echo pyramid-pyramid-sysv3 - else - echo pyramid-pyramid-bsd - fi - exit ;; - NILE*:*:*:dcosx) - echo pyramid-pyramid-svr4 - exit ;; - DRS?6000:unix:4.0:6*) - echo sparc-icl-nx6 - exit ;; - DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) - case `/usr/bin/uname -p` in - sparc) echo sparc-icl-nx7; exit ;; - esac ;; - s390x:SunOS:*:*) - echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit ;; - sun4H:SunOS:5.*:*) - echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit ;; - sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) - echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit ;; - i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*) - echo i386-pc-auroraux${UNAME_RELEASE} - exit ;; - i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) - eval $set_cc_for_build - SUN_ARCH="i386" - # If there is a compiler, see if it is configured for 64-bit objects. - # Note that the Sun cc does not turn __LP64__ into 1 like gcc does. - # This test works for both compilers. - if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then - if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \ - (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ - grep IS_64BIT_ARCH >/dev/null - then - SUN_ARCH="x86_64" - fi - fi - echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit ;; - sun4*:SunOS:6*:*) - # According to config.sub, this is the proper way to canonicalize - # SunOS6. Hard to guess exactly what SunOS6 will be like, but - # it's likely to be more like Solaris than SunOS4. - echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit ;; - sun4*:SunOS:*:*) - case "`/usr/bin/arch -k`" in - Series*|S4*) - UNAME_RELEASE=`uname -v` - ;; - esac - # Japanese Language versions have a version number like `4.1.3-JL'. - echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` - exit ;; - sun3*:SunOS:*:*) - echo m68k-sun-sunos${UNAME_RELEASE} - exit ;; - sun*:*:4.2BSD:*) - UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` - test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 - case "`/bin/arch`" in - sun3) - echo m68k-sun-sunos${UNAME_RELEASE} - ;; - sun4) - echo sparc-sun-sunos${UNAME_RELEASE} - ;; - esac - exit ;; - aushp:SunOS:*:*) - echo sparc-auspex-sunos${UNAME_RELEASE} - exit ;; - # The situation for MiNT is a little confusing. The machine name - # can be virtually everything (everything which is not - # "atarist" or "atariste" at least should have a processor - # > m68000). The system name ranges from "MiNT" over "FreeMiNT" - # to the lowercase version "mint" (or "freemint"). Finally - # the system name "TOS" denotes a system which is actually not - # MiNT. But MiNT is downward compatible to TOS, so this should - # be no problem. - atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) - echo m68k-atari-mint${UNAME_RELEASE} - exit ;; - atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) - echo m68k-atari-mint${UNAME_RELEASE} - exit ;; - *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) - echo m68k-atari-mint${UNAME_RELEASE} - exit ;; - milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) - echo m68k-milan-mint${UNAME_RELEASE} - exit ;; - hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) - echo m68k-hades-mint${UNAME_RELEASE} - exit ;; - *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) - echo m68k-unknown-mint${UNAME_RELEASE} - exit ;; - m68k:machten:*:*) - echo m68k-apple-machten${UNAME_RELEASE} - exit ;; - powerpc:machten:*:*) - echo powerpc-apple-machten${UNAME_RELEASE} - exit ;; - RISC*:Mach:*:*) - echo mips-dec-mach_bsd4.3 - exit ;; - RISC*:ULTRIX:*:*) - echo mips-dec-ultrix${UNAME_RELEASE} - exit ;; - VAX*:ULTRIX*:*:*) - echo vax-dec-ultrix${UNAME_RELEASE} - exit ;; - 2020:CLIX:*:* | 2430:CLIX:*:*) - echo clipper-intergraph-clix${UNAME_RELEASE} - exit ;; - mips:*:*:UMIPS | mips:*:*:RISCos) - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c -#ifdef __cplusplus -#include /* for printf() prototype */ - int main (int argc, char *argv[]) { -#else - int main (argc, argv) int argc; char *argv[]; { -#endif - #if defined (host_mips) && defined (MIPSEB) - #if defined (SYSTYPE_SYSV) - printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); - #endif - #if defined (SYSTYPE_SVR4) - printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); - #endif - #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) - printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); - #endif - #endif - exit (-1); - } -EOF - $CC_FOR_BUILD -o $dummy $dummy.c && - dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` && - SYSTEM_NAME=`$dummy $dummyarg` && - { echo "$SYSTEM_NAME"; exit; } - echo mips-mips-riscos${UNAME_RELEASE} - exit ;; - Motorola:PowerMAX_OS:*:*) - echo powerpc-motorola-powermax - exit ;; - Motorola:*:4.3:PL8-*) - echo powerpc-harris-powermax - exit ;; - Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) - echo powerpc-harris-powermax - exit ;; - Night_Hawk:Power_UNIX:*:*) - echo powerpc-harris-powerunix - exit ;; - m88k:CX/UX:7*:*) - echo m88k-harris-cxux7 - exit ;; - m88k:*:4*:R4*) - echo m88k-motorola-sysv4 - exit ;; - m88k:*:3*:R3*) - echo m88k-motorola-sysv3 - exit ;; - AViiON:dgux:*:*) - # DG/UX returns AViiON for all architectures - UNAME_PROCESSOR=`/usr/bin/uname -p` - if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] - then - if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ - [ ${TARGET_BINARY_INTERFACE}x = x ] - then - echo m88k-dg-dgux${UNAME_RELEASE} - else - echo m88k-dg-dguxbcs${UNAME_RELEASE} - fi - else - echo i586-dg-dgux${UNAME_RELEASE} - fi - exit ;; - M88*:DolphinOS:*:*) # DolphinOS (SVR3) - echo m88k-dolphin-sysv3 - exit ;; - M88*:*:R3*:*) - # Delta 88k system running SVR3 - echo m88k-motorola-sysv3 - exit ;; - XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) - echo m88k-tektronix-sysv3 - exit ;; - Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) - echo m68k-tektronix-bsd - exit ;; - *:IRIX*:*:*) - echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` - exit ;; - ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. - echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id - exit ;; # Note that: echo "'`uname -s`'" gives 'AIX ' - i*86:AIX:*:*) - echo i386-ibm-aix - exit ;; - ia64:AIX:*:*) - if [ -x /usr/bin/oslevel ] ; then - IBM_REV=`/usr/bin/oslevel` - else - IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} - fi - echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} - exit ;; - *:AIX:2:3) - if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c - #include - - main() - { - if (!__power_pc()) - exit(1); - puts("powerpc-ibm-aix3.2.5"); - exit(0); - } -EOF - if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` - then - echo "$SYSTEM_NAME" - else - echo rs6000-ibm-aix3.2.5 - fi - elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then - echo rs6000-ibm-aix3.2.4 - else - echo rs6000-ibm-aix3.2 - fi - exit ;; - *:AIX:*:[4567]) - IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` - if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then - IBM_ARCH=rs6000 - else - IBM_ARCH=powerpc - fi - if [ -x /usr/bin/lslpp ] ; then - IBM_REV=`/usr/bin/lslpp -Lqc bos.rte.libc | - awk -F: '{ print $3 }' | sed s/[0-9]*$/0/` - else - IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} - fi - echo ${IBM_ARCH}-ibm-aix${IBM_REV} - exit ;; - *:AIX:*:*) - echo rs6000-ibm-aix - exit ;; - ibmrt:4.4BSD:*|romp-ibm:BSD:*) - echo romp-ibm-bsd4.4 - exit ;; - ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and - echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to - exit ;; # report: romp-ibm BSD 4.3 - *:BOSX:*:*) - echo rs6000-bull-bosx - exit ;; - DPX/2?00:B.O.S.:*:*) - echo m68k-bull-sysv3 - exit ;; - 9000/[34]??:4.3bsd:1.*:*) - echo m68k-hp-bsd - exit ;; - hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) - echo m68k-hp-bsd4.4 - exit ;; - 9000/[34678]??:HP-UX:*:*) - HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` - case "${UNAME_MACHINE}" in - 9000/31? ) HP_ARCH=m68000 ;; - 9000/[34]?? ) HP_ARCH=m68k ;; - 9000/[678][0-9][0-9]) - if [ -x /usr/bin/getconf ]; then - sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` - sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` - case "${sc_cpu_version}" in - 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 - 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 - 532) # CPU_PA_RISC2_0 - case "${sc_kernel_bits}" in - 32) HP_ARCH="hppa2.0n" ;; - 64) HP_ARCH="hppa2.0w" ;; - '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20 - esac ;; - esac - fi - if [ "${HP_ARCH}" = "" ]; then - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c - - #define _HPUX_SOURCE - #include - #include - - int main () - { - #if defined(_SC_KERNEL_BITS) - long bits = sysconf(_SC_KERNEL_BITS); - #endif - long cpu = sysconf (_SC_CPU_VERSION); - - switch (cpu) - { - case CPU_PA_RISC1_0: puts ("hppa1.0"); break; - case CPU_PA_RISC1_1: puts ("hppa1.1"); break; - case CPU_PA_RISC2_0: - #if defined(_SC_KERNEL_BITS) - switch (bits) - { - case 64: puts ("hppa2.0w"); break; - case 32: puts ("hppa2.0n"); break; - default: puts ("hppa2.0"); break; - } break; - #else /* !defined(_SC_KERNEL_BITS) */ - puts ("hppa2.0"); break; - #endif - default: puts ("hppa1.0"); break; - } - exit (0); - } -EOF - (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` - test -z "$HP_ARCH" && HP_ARCH=hppa - fi ;; - esac - if [ ${HP_ARCH} = "hppa2.0w" ] - then - eval $set_cc_for_build - - # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating - # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler - # generating 64-bit code. GNU and HP use different nomenclature: - # - # $ CC_FOR_BUILD=cc ./config.guess - # => hppa2.0w-hp-hpux11.23 - # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess - # => hppa64-hp-hpux11.23 - - if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | - grep -q __LP64__ - then - HP_ARCH="hppa2.0w" - else - HP_ARCH="hppa64" - fi - fi - echo ${HP_ARCH}-hp-hpux${HPUX_REV} - exit ;; - ia64:HP-UX:*:*) - HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` - echo ia64-hp-hpux${HPUX_REV} - exit ;; - 3050*:HI-UX:*:*) - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c - #include - int - main () - { - long cpu = sysconf (_SC_CPU_VERSION); - /* The order matters, because CPU_IS_HP_MC68K erroneously returns - true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct - results, however. */ - if (CPU_IS_PA_RISC (cpu)) - { - switch (cpu) - { - case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; - case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; - case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; - default: puts ("hppa-hitachi-hiuxwe2"); break; - } - } - else if (CPU_IS_HP_MC68K (cpu)) - puts ("m68k-hitachi-hiuxwe2"); - else puts ("unknown-hitachi-hiuxwe2"); - exit (0); - } -EOF - $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` && - { echo "$SYSTEM_NAME"; exit; } - echo unknown-hitachi-hiuxwe2 - exit ;; - 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) - echo hppa1.1-hp-bsd - exit ;; - 9000/8??:4.3bsd:*:*) - echo hppa1.0-hp-bsd - exit ;; - *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) - echo hppa1.0-hp-mpeix - exit ;; - hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) - echo hppa1.1-hp-osf - exit ;; - hp8??:OSF1:*:*) - echo hppa1.0-hp-osf - exit ;; - i*86:OSF1:*:*) - if [ -x /usr/sbin/sysversion ] ; then - echo ${UNAME_MACHINE}-unknown-osf1mk - else - echo ${UNAME_MACHINE}-unknown-osf1 - fi - exit ;; - parisc*:Lites*:*:*) - echo hppa1.1-hp-lites - exit ;; - C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) - echo c1-convex-bsd - exit ;; - C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) - if getsysinfo -f scalar_acc - then echo c32-convex-bsd - else echo c2-convex-bsd - fi - exit ;; - C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) - echo c34-convex-bsd - exit ;; - C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) - echo c38-convex-bsd - exit ;; - C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) - echo c4-convex-bsd - exit ;; - CRAY*Y-MP:*:*:*) - echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - exit ;; - CRAY*[A-Z]90:*:*:*) - echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ - | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ - -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ - -e 's/\.[^.]*$/.X/' - exit ;; - CRAY*TS:*:*:*) - echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - exit ;; - CRAY*T3E:*:*:*) - echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - exit ;; - CRAY*SV1:*:*:*) - echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - exit ;; - *:UNICOS/mp:*:*) - echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - exit ;; - F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) - FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` - FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` - FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` - echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" - exit ;; - 5000:UNIX_System_V:4.*:*) - FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` - FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'` - echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" - exit ;; - i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) - echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} - exit ;; - sparc*:BSD/OS:*:*) - echo sparc-unknown-bsdi${UNAME_RELEASE} - exit ;; - *:BSD/OS:*:*) - echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} - exit ;; - *:FreeBSD:*:*) - UNAME_PROCESSOR=`/usr/bin/uname -p` - case ${UNAME_PROCESSOR} in - amd64) - echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; - *) - echo ${UNAME_PROCESSOR}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; - esac - exit ;; - i*:CYGWIN*:*) - echo ${UNAME_MACHINE}-pc-cygwin - exit ;; - *:MINGW64*:*) - echo ${UNAME_MACHINE}-pc-mingw64 - exit ;; - *:MINGW*:*) - echo ${UNAME_MACHINE}-pc-mingw32 - exit ;; - *:MSYS*:*) - echo ${UNAME_MACHINE}-pc-msys - exit ;; - i*:windows32*:*) - # uname -m includes "-pc" on this system. - echo ${UNAME_MACHINE}-mingw32 - exit ;; - i*:PW*:*) - echo ${UNAME_MACHINE}-pc-pw32 - exit ;; - *:Interix*:*) - case ${UNAME_MACHINE} in - x86) - echo i586-pc-interix${UNAME_RELEASE} - exit ;; - authenticamd | genuineintel | EM64T) - echo x86_64-unknown-interix${UNAME_RELEASE} - exit ;; - IA64) - echo ia64-unknown-interix${UNAME_RELEASE} - exit ;; - esac ;; - [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) - echo i${UNAME_MACHINE}-pc-mks - exit ;; - 8664:Windows_NT:*) - echo x86_64-pc-mks - exit ;; - i*:Windows_NT*:* | Pentium*:Windows_NT*:*) - # How do we know it's Interix rather than the generic POSIX subsystem? - # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we - # UNAME_MACHINE based on the output of uname instead of i386? - echo i586-pc-interix - exit ;; - i*:UWIN*:*) - echo ${UNAME_MACHINE}-pc-uwin - exit ;; - amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) - echo x86_64-unknown-cygwin - exit ;; - p*:CYGWIN*:*) - echo powerpcle-unknown-cygwin - exit ;; - prep*:SunOS:5.*:*) - echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit ;; - *:GNU:*:*) - # the GNU system - echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-${LIBC}`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` - exit ;; - *:GNU/*:*:*) - # other systems with GNU libc and userland - echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-${LIBC} - exit ;; - i*86:Minix:*:*) - echo ${UNAME_MACHINE}-pc-minix - exit ;; - aarch64:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} - exit ;; - aarch64_be:Linux:*:*) - UNAME_MACHINE=aarch64_be - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} - exit ;; - alpha:Linux:*:*) - case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in - EV5) UNAME_MACHINE=alphaev5 ;; - EV56) UNAME_MACHINE=alphaev56 ;; - PCA56) UNAME_MACHINE=alphapca56 ;; - PCA57) UNAME_MACHINE=alphapca56 ;; - EV6) UNAME_MACHINE=alphaev6 ;; - EV67) UNAME_MACHINE=alphaev67 ;; - EV68*) UNAME_MACHINE=alphaev68 ;; - esac - objdump --private-headers /bin/sh | grep -q ld.so.1 - if test "$?" = 0 ; then LIBC="gnulibc1" ; fi - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} - exit ;; - arc:Linux:*:* | arceb:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} - exit ;; - arm*:Linux:*:*) - eval $set_cc_for_build - if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ - | grep -q __ARM_EABI__ - then - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} - else - if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ - | grep -q __ARM_PCS_VFP - then - echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabi - else - echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabihf - fi - fi - exit ;; - avr32*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} - exit ;; - cris:Linux:*:*) - echo ${UNAME_MACHINE}-axis-linux-${LIBC} - exit ;; - crisv32:Linux:*:*) - echo ${UNAME_MACHINE}-axis-linux-${LIBC} - exit ;; - frv:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} - exit ;; - hexagon:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} - exit ;; - i*86:Linux:*:*) - echo ${UNAME_MACHINE}-pc-linux-${LIBC} - exit ;; - ia64:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} - exit ;; - m32r*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} - exit ;; - m68*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} - exit ;; - mips:Linux:*:* | mips64:Linux:*:*) - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c - #undef CPU - #undef ${UNAME_MACHINE} - #undef ${UNAME_MACHINE}el - #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) - CPU=${UNAME_MACHINE}el - #else - #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) - CPU=${UNAME_MACHINE} - #else - CPU= - #endif - #endif -EOF - eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'` - test x"${CPU}" != x && { echo "${CPU}-unknown-linux-${LIBC}"; exit; } - ;; - openrisc*:Linux:*:*) - echo or1k-unknown-linux-${LIBC} - exit ;; - or32:Linux:*:* | or1k*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} - exit ;; - padre:Linux:*:*) - echo sparc-unknown-linux-${LIBC} - exit ;; - parisc64:Linux:*:* | hppa64:Linux:*:*) - echo hppa64-unknown-linux-${LIBC} - exit ;; - parisc:Linux:*:* | hppa:Linux:*:*) - # Look for CPU level - case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in - PA7*) echo hppa1.1-unknown-linux-${LIBC} ;; - PA8*) echo hppa2.0-unknown-linux-${LIBC} ;; - *) echo hppa-unknown-linux-${LIBC} ;; - esac - exit ;; - ppc64:Linux:*:*) - echo powerpc64-unknown-linux-${LIBC} - exit ;; - ppc:Linux:*:*) - echo powerpc-unknown-linux-${LIBC} - exit ;; - ppc64le:Linux:*:*) - echo powerpc64le-unknown-linux-${LIBC} - exit ;; - ppcle:Linux:*:*) - echo powerpcle-unknown-linux-${LIBC} - exit ;; - s390:Linux:*:* | s390x:Linux:*:*) - echo ${UNAME_MACHINE}-ibm-linux-${LIBC} - exit ;; - sh64*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} - exit ;; - sh*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} - exit ;; - sparc:Linux:*:* | sparc64:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} - exit ;; - tile*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} - exit ;; - vax:Linux:*:*) - echo ${UNAME_MACHINE}-dec-linux-${LIBC} - exit ;; - x86_64:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} - exit ;; - xtensa*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} - exit ;; - i*86:DYNIX/ptx:4*:*) - # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. - # earlier versions are messed up and put the nodename in both - # sysname and nodename. - echo i386-sequent-sysv4 - exit ;; - i*86:UNIX_SV:4.2MP:2.*) - # Unixware is an offshoot of SVR4, but it has its own version - # number series starting with 2... - # I am not positive that other SVR4 systems won't match this, - # I just have to hope. -- rms. - # Use sysv4.2uw... so that sysv4* matches it. - echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} - exit ;; - i*86:OS/2:*:*) - # If we were able to find `uname', then EMX Unix compatibility - # is probably installed. - echo ${UNAME_MACHINE}-pc-os2-emx - exit ;; - i*86:XTS-300:*:STOP) - echo ${UNAME_MACHINE}-unknown-stop - exit ;; - i*86:atheos:*:*) - echo ${UNAME_MACHINE}-unknown-atheos - exit ;; - i*86:syllable:*:*) - echo ${UNAME_MACHINE}-pc-syllable - exit ;; - i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*) - echo i386-unknown-lynxos${UNAME_RELEASE} - exit ;; - i*86:*DOS:*:*) - echo ${UNAME_MACHINE}-pc-msdosdjgpp - exit ;; - i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) - UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` - if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then - echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} - else - echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} - fi - exit ;; - i*86:*:5:[678]*) - # UnixWare 7.x, OpenUNIX and OpenServer 6. - case `/bin/uname -X | grep "^Machine"` in - *486*) UNAME_MACHINE=i486 ;; - *Pentium) UNAME_MACHINE=i586 ;; - *Pent*|*Celeron) UNAME_MACHINE=i686 ;; - esac - echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} - exit ;; - i*86:*:3.2:*) - if test -f /usr/options/cb.name; then - UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then - UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` - (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 - (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ - && UNAME_MACHINE=i586 - (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ - && UNAME_MACHINE=i686 - (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ - && UNAME_MACHINE=i686 - echo ${UNAME_MACHINE}-pc-sco$UNAME_REL - else - echo ${UNAME_MACHINE}-pc-sysv32 - fi - exit ;; - pc:*:*:*) - # Left here for compatibility: - # uname -m prints for DJGPP always 'pc', but it prints nothing about - # the processor, so we play safe by assuming i586. - # Note: whatever this is, it MUST be the same as what config.sub - # prints for the "djgpp" host, or else GDB configury will decide that - # this is a cross-build. - echo i586-pc-msdosdjgpp - exit ;; - Intel:Mach:3*:*) - echo i386-pc-mach3 - exit ;; - paragon:*:*:*) - echo i860-intel-osf1 - exit ;; - i860:*:4.*:*) # i860-SVR4 - if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then - echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 - else # Add other i860-SVR4 vendors below as they are discovered. - echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 - fi - exit ;; - mini*:CTIX:SYS*5:*) - # "miniframe" - echo m68010-convergent-sysv - exit ;; - mc68k:UNIX:SYSTEM5:3.51m) - echo m68k-convergent-sysv - exit ;; - M680?0:D-NIX:5.3:*) - echo m68k-diab-dnix - exit ;; - M68*:*:R3V[5678]*:*) - test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;; - 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) - OS_REL='' - test -r /etc/.relid \ - && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` - /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ - && { echo i486-ncr-sysv4.3${OS_REL}; exit; } - /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ - && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; - 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) - /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ - && { echo i486-ncr-sysv4; exit; } ;; - NCR*:*:4.2:* | MPRAS*:*:4.2:*) - OS_REL='.3' - test -r /etc/.relid \ - && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` - /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ - && { echo i486-ncr-sysv4.3${OS_REL}; exit; } - /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ - && { echo i586-ncr-sysv4.3${OS_REL}; exit; } - /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \ - && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; - m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) - echo m68k-unknown-lynxos${UNAME_RELEASE} - exit ;; - mc68030:UNIX_System_V:4.*:*) - echo m68k-atari-sysv4 - exit ;; - TSUNAMI:LynxOS:2.*:*) - echo sparc-unknown-lynxos${UNAME_RELEASE} - exit ;; - rs6000:LynxOS:2.*:*) - echo rs6000-unknown-lynxos${UNAME_RELEASE} - exit ;; - PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*) - echo powerpc-unknown-lynxos${UNAME_RELEASE} - exit ;; - SM[BE]S:UNIX_SV:*:*) - echo mips-dde-sysv${UNAME_RELEASE} - exit ;; - RM*:ReliantUNIX-*:*:*) - echo mips-sni-sysv4 - exit ;; - RM*:SINIX-*:*:*) - echo mips-sni-sysv4 - exit ;; - *:SINIX-*:*:*) - if uname -p 2>/dev/null >/dev/null ; then - UNAME_MACHINE=`(uname -p) 2>/dev/null` - echo ${UNAME_MACHINE}-sni-sysv4 - else - echo ns32k-sni-sysv - fi - exit ;; - PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort - # says - echo i586-unisys-sysv4 - exit ;; - *:UNIX_System_V:4*:FTX*) - # From Gerald Hewes . - # How about differentiating between stratus architectures? -djm - echo hppa1.1-stratus-sysv4 - exit ;; - *:*:*:FTX*) - # From seanf@swdc.stratus.com. - echo i860-stratus-sysv4 - exit ;; - i*86:VOS:*:*) - # From Paul.Green@stratus.com. - echo ${UNAME_MACHINE}-stratus-vos - exit ;; - *:VOS:*:*) - # From Paul.Green@stratus.com. - echo hppa1.1-stratus-vos - exit ;; - mc68*:A/UX:*:*) - echo m68k-apple-aux${UNAME_RELEASE} - exit ;; - news*:NEWS-OS:6*:*) - echo mips-sony-newsos6 - exit ;; - R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) - if [ -d /usr/nec ]; then - echo mips-nec-sysv${UNAME_RELEASE} - else - echo mips-unknown-sysv${UNAME_RELEASE} - fi - exit ;; - BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. - echo powerpc-be-beos - exit ;; - BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. - echo powerpc-apple-beos - exit ;; - BePC:BeOS:*:*) # BeOS running on Intel PC compatible. - echo i586-pc-beos - exit ;; - BePC:Haiku:*:*) # Haiku running on Intel PC compatible. - echo i586-pc-haiku - exit ;; - x86_64:Haiku:*:*) - echo x86_64-unknown-haiku - exit ;; - SX-4:SUPER-UX:*:*) - echo sx4-nec-superux${UNAME_RELEASE} - exit ;; - SX-5:SUPER-UX:*:*) - echo sx5-nec-superux${UNAME_RELEASE} - exit ;; - SX-6:SUPER-UX:*:*) - echo sx6-nec-superux${UNAME_RELEASE} - exit ;; - SX-7:SUPER-UX:*:*) - echo sx7-nec-superux${UNAME_RELEASE} - exit ;; - SX-8:SUPER-UX:*:*) - echo sx8-nec-superux${UNAME_RELEASE} - exit ;; - SX-8R:SUPER-UX:*:*) - echo sx8r-nec-superux${UNAME_RELEASE} - exit ;; - Power*:Rhapsody:*:*) - echo powerpc-apple-rhapsody${UNAME_RELEASE} - exit ;; - *:Rhapsody:*:*) - echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} - exit ;; - *:Darwin:*:*) - UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown - eval $set_cc_for_build - if test "$UNAME_PROCESSOR" = unknown ; then - UNAME_PROCESSOR=powerpc - fi - if test `echo "$UNAME_RELEASE" | sed -e 's/\..*//'` -le 10 ; then - if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then - if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ - (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ - grep IS_64BIT_ARCH >/dev/null - then - case $UNAME_PROCESSOR in - i386) UNAME_PROCESSOR=x86_64 ;; - powerpc) UNAME_PROCESSOR=powerpc64 ;; - esac - fi - fi - elif test "$UNAME_PROCESSOR" = i386 ; then - # Avoid executing cc on OS X 10.9, as it ships with a stub - # that puts up a graphical alert prompting to install - # developer tools. Any system running Mac OS X 10.7 or - # later (Darwin 11 and later) is required to have a 64-bit - # processor. This is not true of the ARM version of Darwin - # that Apple uses in portable devices. - UNAME_PROCESSOR=x86_64 - fi - echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} - exit ;; - *:procnto*:*:* | *:QNX:[0123456789]*:*) - UNAME_PROCESSOR=`uname -p` - if test "$UNAME_PROCESSOR" = "x86"; then - UNAME_PROCESSOR=i386 - UNAME_MACHINE=pc - fi - echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} - exit ;; - *:QNX:*:4*) - echo i386-pc-qnx - exit ;; - NEO-?:NONSTOP_KERNEL:*:*) - echo neo-tandem-nsk${UNAME_RELEASE} - exit ;; - NSE-*:NONSTOP_KERNEL:*:*) - echo nse-tandem-nsk${UNAME_RELEASE} - exit ;; - NSR-?:NONSTOP_KERNEL:*:*) - echo nsr-tandem-nsk${UNAME_RELEASE} - exit ;; - *:NonStop-UX:*:*) - echo mips-compaq-nonstopux - exit ;; - BS2000:POSIX*:*:*) - echo bs2000-siemens-sysv - exit ;; - DS/*:UNIX_System_V:*:*) - echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} - exit ;; - *:Plan9:*:*) - # "uname -m" is not consistent, so use $cputype instead. 386 - # is converted to i386 for consistency with other x86 - # operating systems. - if test "$cputype" = "386"; then - UNAME_MACHINE=i386 - else - UNAME_MACHINE="$cputype" - fi - echo ${UNAME_MACHINE}-unknown-plan9 - exit ;; - *:TOPS-10:*:*) - echo pdp10-unknown-tops10 - exit ;; - *:TENEX:*:*) - echo pdp10-unknown-tenex - exit ;; - KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) - echo pdp10-dec-tops20 - exit ;; - XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) - echo pdp10-xkl-tops20 - exit ;; - *:TOPS-20:*:*) - echo pdp10-unknown-tops20 - exit ;; - *:ITS:*:*) - echo pdp10-unknown-its - exit ;; - SEI:*:*:SEIUX) - echo mips-sei-seiux${UNAME_RELEASE} - exit ;; - *:DragonFly:*:*) - echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` - exit ;; - *:*VMS:*:*) - UNAME_MACHINE=`(uname -p) 2>/dev/null` - case "${UNAME_MACHINE}" in - A*) echo alpha-dec-vms ; exit ;; - I*) echo ia64-dec-vms ; exit ;; - V*) echo vax-dec-vms ; exit ;; - esac ;; - *:XENIX:*:SysV) - echo i386-pc-xenix - exit ;; - i*86:skyos:*:*) - echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//' - exit ;; - i*86:rdos:*:*) - echo ${UNAME_MACHINE}-pc-rdos - exit ;; - i*86:AROS:*:*) - echo ${UNAME_MACHINE}-pc-aros - exit ;; - x86_64:VMkernel:*:*) - echo ${UNAME_MACHINE}-unknown-esx - exit ;; -esac - -cat >&2 < in order to provide the needed -information to handle your system. - -config.guess timestamp = $timestamp - -uname -m = `(uname -m) 2>/dev/null || echo unknown` -uname -r = `(uname -r) 2>/dev/null || echo unknown` -uname -s = `(uname -s) 2>/dev/null || echo unknown` -uname -v = `(uname -v) 2>/dev/null || echo unknown` - -/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` -/bin/uname -X = `(/bin/uname -X) 2>/dev/null` - -hostinfo = `(hostinfo) 2>/dev/null` -/bin/universe = `(/bin/universe) 2>/dev/null` -/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` -/bin/arch = `(/bin/arch) 2>/dev/null` -/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` -/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` - -UNAME_MACHINE = ${UNAME_MACHINE} -UNAME_RELEASE = ${UNAME_RELEASE} -UNAME_SYSTEM = ${UNAME_SYSTEM} -UNAME_VERSION = ${UNAME_VERSION} -EOF - -exit 1 - -# Local variables: -# eval: (add-hook 'write-file-hooks 'time-stamp) -# time-stamp-start: "timestamp='" -# time-stamp-format: "%:y-%02m-%02d" -# time-stamp-end: "'" -# End: diff --git a/build-aux/config.sub b/build-aux/config.sub deleted file mode 100755 index 7ffe37378..000000000 --- a/build-aux/config.sub +++ /dev/null @@ -1,1807 +0,0 @@ -#! /bin/sh -# Configuration validation subroutine script. -# Copyright 1992-2014 Free Software Foundation, Inc. - -timestamp='2014-12-03' - -# This file 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 3 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, see . -# -# As a special exception to the GNU General Public License, if you -# distribute this file as part of a program that contains a -# configuration script generated by Autoconf, you may include it under -# the same distribution terms that you use for the rest of that -# program. This Exception is an additional permission under section 7 -# of the GNU General Public License, version 3 ("GPLv3"). - - -# Please send patches to . -# -# Configuration subroutine to validate and canonicalize a configuration type. -# Supply the specified configuration type as an argument. -# If it is invalid, we print an error message on stderr and exit with code 1. -# Otherwise, we print the canonical config type on stdout and succeed. - -# You can get the latest version of this script from: -# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD - -# This file is supposed to be the same for all GNU packages -# and recognize all the CPU types, system types and aliases -# that are meaningful with *any* GNU software. -# Each package is responsible for reporting which valid configurations -# it does not support. The user should be able to distinguish -# a failure to support a valid configuration from a meaningless -# configuration. - -# The goal of this file is to map all the various variations of a given -# machine specification into a single specification in the form: -# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM -# or in some cases, the newer four-part form: -# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM -# It is wrong to echo any other type of specification. - -me=`echo "$0" | sed -e 's,.*/,,'` - -usage="\ -Usage: $0 [OPTION] CPU-MFR-OPSYS - $0 [OPTION] ALIAS - -Canonicalize a configuration name. - -Operation modes: - -h, --help print this help, then exit - -t, --time-stamp print date of last modification, then exit - -v, --version print version number, then exit - -Report bugs and patches to ." - -version="\ -GNU config.sub ($timestamp) - -Copyright 1992-2014 Free Software Foundation, Inc. - -This is free software; see the source for copying conditions. There is NO -warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." - -help=" -Try \`$me --help' for more information." - -# Parse command line -while test $# -gt 0 ; do - case $1 in - --time-stamp | --time* | -t ) - echo "$timestamp" ; exit ;; - --version | -v ) - echo "$version" ; exit ;; - --help | --h* | -h ) - echo "$usage"; exit ;; - -- ) # Stop option processing - shift; break ;; - - ) # Use stdin as input. - break ;; - -* ) - echo "$me: invalid option $1$help" - exit 1 ;; - - *local*) - # First pass through any local machine types. - echo $1 - exit ;; - - * ) - break ;; - esac -done - -case $# in - 0) echo "$me: missing argument$help" >&2 - exit 1;; - 1) ;; - *) echo "$me: too many arguments$help" >&2 - exit 1;; -esac - -# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). -# Here we must recognize all the valid KERNEL-OS combinations. -maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` -case $maybe_os in - nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \ - linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \ - knetbsd*-gnu* | netbsd*-gnu* | \ - kopensolaris*-gnu* | \ - storm-chaos* | os2-emx* | rtmk-nova*) - os=-$maybe_os - basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` - ;; - android-linux) - os=-linux-android - basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown - ;; - *) - basic_machine=`echo $1 | sed 's/-[^-]*$//'` - if [ $basic_machine != $1 ] - then os=`echo $1 | sed 's/.*-/-/'` - else os=; fi - ;; -esac - -### Let's recognize common machines as not being operating systems so -### that things like config.sub decstation-3100 work. We also -### recognize some manufacturers as not being operating systems, so we -### can provide default operating systems below. -case $os in - -sun*os*) - # Prevent following clause from handling this invalid input. - ;; - -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ - -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ - -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ - -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ - -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ - -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ - -apple | -axis | -knuth | -cray | -microblaze*) - os= - basic_machine=$1 - ;; - -bluegene*) - os=-cnk - ;; - -sim | -cisco | -oki | -wec | -winbond) - os= - basic_machine=$1 - ;; - -scout) - ;; - -wrs) - os=-vxworks - basic_machine=$1 - ;; - -chorusos*) - os=-chorusos - basic_machine=$1 - ;; - -chorusrdb) - os=-chorusrdb - basic_machine=$1 - ;; - -hiux*) - os=-hiuxwe2 - ;; - -sco6) - os=-sco5v6 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco5) - os=-sco3.2v5 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco4) - os=-sco3.2v4 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco3.2.[4-9]*) - os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco3.2v[4-9]*) - # Don't forget version if it is 3.2v4 or newer. - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco5v6*) - # Don't forget version if it is 3.2v4 or newer. - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco*) - os=-sco3.2v2 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -udk*) - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -isc) - os=-isc2.2 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -clix*) - basic_machine=clipper-intergraph - ;; - -isc*) - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -lynx*178) - os=-lynxos178 - ;; - -lynx*5) - os=-lynxos5 - ;; - -lynx*) - os=-lynxos - ;; - -ptx*) - basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` - ;; - -windowsnt*) - os=`echo $os | sed -e 's/windowsnt/winnt/'` - ;; - -psos*) - os=-psos - ;; - -mint | -mint[0-9]*) - basic_machine=m68k-atari - os=-mint - ;; -esac - -# Decode aliases for certain CPU-COMPANY combinations. -case $basic_machine in - # Recognize the basic CPU types without company name. - # Some are omitted here because they have special meanings below. - 1750a | 580 \ - | a29k \ - | aarch64 | aarch64_be \ - | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ - | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ - | am33_2.0 \ - | arc | arceb \ - | arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] \ - | avr | avr32 \ - | be32 | be64 \ - | bfin \ - | c4x | c8051 | clipper \ - | d10v | d30v | dlx | dsp16xx \ - | epiphany \ - | fido | fr30 | frv \ - | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ - | hexagon \ - | i370 | i860 | i960 | ia64 \ - | ip2k | iq2000 \ - | k1om \ - | le32 | le64 \ - | lm32 \ - | m32c | m32r | m32rle | m68000 | m68k | m88k \ - | maxq | mb | microblaze | microblazeel | mcore | mep | metag \ - | mips | mipsbe | mipseb | mipsel | mipsle \ - | mips16 \ - | mips64 | mips64el \ - | mips64octeon | mips64octeonel \ - | mips64orion | mips64orionel \ - | mips64r5900 | mips64r5900el \ - | mips64vr | mips64vrel \ - | mips64vr4100 | mips64vr4100el \ - | mips64vr4300 | mips64vr4300el \ - | mips64vr5000 | mips64vr5000el \ - | mips64vr5900 | mips64vr5900el \ - | mipsisa32 | mipsisa32el \ - | mipsisa32r2 | mipsisa32r2el \ - | mipsisa32r6 | mipsisa32r6el \ - | mipsisa64 | mipsisa64el \ - | mipsisa64r2 | mipsisa64r2el \ - | mipsisa64r6 | mipsisa64r6el \ - | mipsisa64sb1 | mipsisa64sb1el \ - | mipsisa64sr71k | mipsisa64sr71kel \ - | mipsr5900 | mipsr5900el \ - | mipstx39 | mipstx39el \ - | mn10200 | mn10300 \ - | moxie \ - | mt \ - | msp430 \ - | nds32 | nds32le | nds32be \ - | nios | nios2 | nios2eb | nios2el \ - | ns16k | ns32k \ - | open8 | or1k | or1knd | or32 \ - | pdp10 | pdp11 | pj | pjl \ - | powerpc | powerpc64 | powerpc64le | powerpcle \ - | pyramid \ - | riscv32 | riscv64 \ - | rl78 | rx \ - | score \ - | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ - | sh64 | sh64le \ - | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ - | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ - | spu \ - | tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \ - | ubicom32 \ - | v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \ - | visium \ - | we32k \ - | x86 | xc16x | xstormy16 | xtensa \ - | z8k | z80) - basic_machine=$basic_machine-unknown - ;; - c54x) - basic_machine=tic54x-unknown - ;; - c55x) - basic_machine=tic55x-unknown - ;; - c6x) - basic_machine=tic6x-unknown - ;; - leon|leon[3-9]) - basic_machine=sparc-$basic_machine - ;; - m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | nvptx | picochip) - basic_machine=$basic_machine-unknown - os=-none - ;; - m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) - ;; - ms1) - basic_machine=mt-unknown - ;; - - strongarm | thumb | xscale) - basic_machine=arm-unknown - ;; - xgate) - basic_machine=$basic_machine-unknown - os=-none - ;; - xscaleeb) - basic_machine=armeb-unknown - ;; - - xscaleel) - basic_machine=armel-unknown - ;; - - # We use `pc' rather than `unknown' - # because (1) that's what they normally are, and - # (2) the word "unknown" tends to confuse beginning users. - i*86 | x86_64) - basic_machine=$basic_machine-pc - ;; - # Object if more than one company name word. - *-*-*) - echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 - exit 1 - ;; - # Recognize the basic CPU types with company name. - 580-* \ - | a29k-* \ - | aarch64-* | aarch64_be-* \ - | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ - | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ - | alphapca5[67]-* | alpha64pca5[67]-* | arc-* | arceb-* \ - | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ - | avr-* | avr32-* \ - | be32-* | be64-* \ - | bfin-* | bs2000-* \ - | c[123]* | c30-* | [cjt]90-* | c4x-* \ - | c8051-* | clipper-* | craynv-* | cydra-* \ - | d10v-* | d30v-* | dlx-* \ - | elxsi-* \ - | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ - | h8300-* | h8500-* \ - | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ - | hexagon-* \ - | i*86-* | i860-* | i960-* | ia64-* \ - | ip2k-* | iq2000-* \ - | k1om-* \ - | le32-* | le64-* \ - | lm32-* \ - | m32c-* | m32r-* | m32rle-* \ - | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ - | m88110-* | m88k-* | maxq-* | mcore-* | metag-* \ - | microblaze-* | microblazeel-* \ - | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ - | mips16-* \ - | mips64-* | mips64el-* \ - | mips64octeon-* | mips64octeonel-* \ - | mips64orion-* | mips64orionel-* \ - | mips64r5900-* | mips64r5900el-* \ - | mips64vr-* | mips64vrel-* \ - | mips64vr4100-* | mips64vr4100el-* \ - | mips64vr4300-* | mips64vr4300el-* \ - | mips64vr5000-* | mips64vr5000el-* \ - | mips64vr5900-* | mips64vr5900el-* \ - | mipsisa32-* | mipsisa32el-* \ - | mipsisa32r2-* | mipsisa32r2el-* \ - | mipsisa32r6-* | mipsisa32r6el-* \ - | mipsisa64-* | mipsisa64el-* \ - | mipsisa64r2-* | mipsisa64r2el-* \ - | mipsisa64r6-* | mipsisa64r6el-* \ - | mipsisa64sb1-* | mipsisa64sb1el-* \ - | mipsisa64sr71k-* | mipsisa64sr71kel-* \ - | mipsr5900-* | mipsr5900el-* \ - | mipstx39-* | mipstx39el-* \ - | mmix-* \ - | mt-* \ - | msp430-* \ - | nds32-* | nds32le-* | nds32be-* \ - | nios-* | nios2-* | nios2eb-* | nios2el-* \ - | none-* | np1-* | ns16k-* | ns32k-* \ - | open8-* \ - | or1k*-* \ - | orion-* \ - | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ - | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \ - | pyramid-* \ - | rl78-* | romp-* | rs6000-* | rx-* \ - | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ - | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ - | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ - | sparclite-* \ - | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx?-* \ - | tahoe-* \ - | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ - | tile*-* \ - | tron-* \ - | ubicom32-* \ - | v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \ - | vax-* \ - | visium-* \ - | we32k-* \ - | x86-* | x86_64-* | xc16x-* | xps100-* \ - | xstormy16-* | xtensa*-* \ - | ymp-* \ - | z8k-* | z80-*) - ;; - # Recognize the basic CPU types without company name, with glob match. - xtensa*) - basic_machine=$basic_machine-unknown - ;; - # Recognize the various machine names and aliases which stand - # for a CPU type and a company and sometimes even an OS. - 386bsd) - basic_machine=i386-unknown - os=-bsd - ;; - 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) - basic_machine=m68000-att - ;; - 3b*) - basic_machine=we32k-att - ;; - a29khif) - basic_machine=a29k-amd - os=-udi - ;; - abacus) - basic_machine=abacus-unknown - ;; - adobe68k) - basic_machine=m68010-adobe - os=-scout - ;; - alliant | fx80) - basic_machine=fx80-alliant - ;; - altos | altos3068) - basic_machine=m68k-altos - ;; - am29k) - basic_machine=a29k-none - os=-bsd - ;; - amd64) - basic_machine=x86_64-pc - ;; - amd64-*) - basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - amdahl) - basic_machine=580-amdahl - os=-sysv - ;; - amiga | amiga-*) - basic_machine=m68k-unknown - ;; - amigaos | amigados) - basic_machine=m68k-unknown - os=-amigaos - ;; - amigaunix | amix) - basic_machine=m68k-unknown - os=-sysv4 - ;; - apollo68) - basic_machine=m68k-apollo - os=-sysv - ;; - apollo68bsd) - basic_machine=m68k-apollo - os=-bsd - ;; - aros) - basic_machine=i386-pc - os=-aros - ;; - aux) - basic_machine=m68k-apple - os=-aux - ;; - balance) - basic_machine=ns32k-sequent - os=-dynix - ;; - blackfin) - basic_machine=bfin-unknown - os=-linux - ;; - blackfin-*) - basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'` - os=-linux - ;; - bluegene*) - basic_machine=powerpc-ibm - os=-cnk - ;; - c54x-*) - basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - c55x-*) - basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - c6x-*) - basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - c90) - basic_machine=c90-cray - os=-unicos - ;; - cegcc) - basic_machine=arm-unknown - os=-cegcc - ;; - convex-c1) - basic_machine=c1-convex - os=-bsd - ;; - convex-c2) - basic_machine=c2-convex - os=-bsd - ;; - convex-c32) - basic_machine=c32-convex - os=-bsd - ;; - convex-c34) - basic_machine=c34-convex - os=-bsd - ;; - convex-c38) - basic_machine=c38-convex - os=-bsd - ;; - cray | j90) - basic_machine=j90-cray - os=-unicos - ;; - craynv) - basic_machine=craynv-cray - os=-unicosmp - ;; - cr16 | cr16-*) - basic_machine=cr16-unknown - os=-elf - ;; - crds | unos) - basic_machine=m68k-crds - ;; - crisv32 | crisv32-* | etraxfs*) - basic_machine=crisv32-axis - ;; - cris | cris-* | etrax*) - basic_machine=cris-axis - ;; - crx) - basic_machine=crx-unknown - os=-elf - ;; - da30 | da30-*) - basic_machine=m68k-da30 - ;; - decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) - basic_machine=mips-dec - ;; - decsystem10* | dec10*) - basic_machine=pdp10-dec - os=-tops10 - ;; - decsystem20* | dec20*) - basic_machine=pdp10-dec - os=-tops20 - ;; - delta | 3300 | motorola-3300 | motorola-delta \ - | 3300-motorola | delta-motorola) - basic_machine=m68k-motorola - ;; - delta88) - basic_machine=m88k-motorola - os=-sysv3 - ;; - dicos) - basic_machine=i686-pc - os=-dicos - ;; - djgpp) - basic_machine=i586-pc - os=-msdosdjgpp - ;; - dpx20 | dpx20-*) - basic_machine=rs6000-bull - os=-bosx - ;; - dpx2* | dpx2*-bull) - basic_machine=m68k-bull - os=-sysv3 - ;; - ebmon29k) - basic_machine=a29k-amd - os=-ebmon - ;; - elxsi) - basic_machine=elxsi-elxsi - os=-bsd - ;; - encore | umax | mmax) - basic_machine=ns32k-encore - ;; - es1800 | OSE68k | ose68k | ose | OSE) - basic_machine=m68k-ericsson - os=-ose - ;; - fx2800) - basic_machine=i860-alliant - ;; - genix) - basic_machine=ns32k-ns - ;; - gmicro) - basic_machine=tron-gmicro - os=-sysv - ;; - go32) - basic_machine=i386-pc - os=-go32 - ;; - h3050r* | hiux*) - basic_machine=hppa1.1-hitachi - os=-hiuxwe2 - ;; - h8300hms) - basic_machine=h8300-hitachi - os=-hms - ;; - h8300xray) - basic_machine=h8300-hitachi - os=-xray - ;; - h8500hms) - basic_machine=h8500-hitachi - os=-hms - ;; - harris) - basic_machine=m88k-harris - os=-sysv3 - ;; - hp300-*) - basic_machine=m68k-hp - ;; - hp300bsd) - basic_machine=m68k-hp - os=-bsd - ;; - hp300hpux) - basic_machine=m68k-hp - os=-hpux - ;; - hp3k9[0-9][0-9] | hp9[0-9][0-9]) - basic_machine=hppa1.0-hp - ;; - hp9k2[0-9][0-9] | hp9k31[0-9]) - basic_machine=m68000-hp - ;; - hp9k3[2-9][0-9]) - basic_machine=m68k-hp - ;; - hp9k6[0-9][0-9] | hp6[0-9][0-9]) - basic_machine=hppa1.0-hp - ;; - hp9k7[0-79][0-9] | hp7[0-79][0-9]) - basic_machine=hppa1.1-hp - ;; - hp9k78[0-9] | hp78[0-9]) - # FIXME: really hppa2.0-hp - basic_machine=hppa1.1-hp - ;; - hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) - # FIXME: really hppa2.0-hp - basic_machine=hppa1.1-hp - ;; - hp9k8[0-9][13679] | hp8[0-9][13679]) - basic_machine=hppa1.1-hp - ;; - hp9k8[0-9][0-9] | hp8[0-9][0-9]) - basic_machine=hppa1.0-hp - ;; - hppa-next) - os=-nextstep3 - ;; - hppaosf) - basic_machine=hppa1.1-hp - os=-osf - ;; - hppro) - basic_machine=hppa1.1-hp - os=-proelf - ;; - i370-ibm* | ibm*) - basic_machine=i370-ibm - ;; - i*86v32) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` - os=-sysv32 - ;; - i*86v4*) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` - os=-sysv4 - ;; - i*86v) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` - os=-sysv - ;; - i*86sol2) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` - os=-solaris2 - ;; - i386mach) - basic_machine=i386-mach - os=-mach - ;; - i386-vsta | vsta) - basic_machine=i386-unknown - os=-vsta - ;; - iris | iris4d) - basic_machine=mips-sgi - case $os in - -irix*) - ;; - *) - os=-irix4 - ;; - esac - ;; - isi68 | isi) - basic_machine=m68k-isi - os=-sysv - ;; - leon-*|leon[3-9]-*) - basic_machine=sparc-`echo $basic_machine | sed 's/-.*//'` - ;; - m68knommu) - basic_machine=m68k-unknown - os=-linux - ;; - m68knommu-*) - basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'` - os=-linux - ;; - m88k-omron*) - basic_machine=m88k-omron - ;; - magnum | m3230) - basic_machine=mips-mips - os=-sysv - ;; - merlin) - basic_machine=ns32k-utek - os=-sysv - ;; - microblaze*) - basic_machine=microblaze-xilinx - ;; - mingw64) - basic_machine=x86_64-pc - os=-mingw64 - ;; - mingw32) - basic_machine=i686-pc - os=-mingw32 - ;; - mingw32ce) - basic_machine=arm-unknown - os=-mingw32ce - ;; - miniframe) - basic_machine=m68000-convergent - ;; - *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) - basic_machine=m68k-atari - os=-mint - ;; - mips3*-*) - basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` - ;; - mips3*) - basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown - ;; - monitor) - basic_machine=m68k-rom68k - os=-coff - ;; - morphos) - basic_machine=powerpc-unknown - os=-morphos - ;; - moxiebox) - basic_machine=moxie-unknown - os=-moxiebox - ;; - msdos) - basic_machine=i386-pc - os=-msdos - ;; - ms1-*) - basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'` - ;; - msys) - basic_machine=i686-pc - os=-msys - ;; - mvs) - basic_machine=i370-ibm - os=-mvs - ;; - nacl) - basic_machine=le32-unknown - os=-nacl - ;; - ncr3000) - basic_machine=i486-ncr - os=-sysv4 - ;; - netbsd386) - basic_machine=i386-unknown - os=-netbsd - ;; - netwinder) - basic_machine=armv4l-rebel - os=-linux - ;; - news | news700 | news800 | news900) - basic_machine=m68k-sony - os=-newsos - ;; - news1000) - basic_machine=m68030-sony - os=-newsos - ;; - news-3600 | risc-news) - basic_machine=mips-sony - os=-newsos - ;; - necv70) - basic_machine=v70-nec - os=-sysv - ;; - next | m*-next ) - basic_machine=m68k-next - case $os in - -nextstep* ) - ;; - -ns2*) - os=-nextstep2 - ;; - *) - os=-nextstep3 - ;; - esac - ;; - nh3000) - basic_machine=m68k-harris - os=-cxux - ;; - nh[45]000) - basic_machine=m88k-harris - os=-cxux - ;; - nindy960) - basic_machine=i960-intel - os=-nindy - ;; - mon960) - basic_machine=i960-intel - os=-mon960 - ;; - nonstopux) - basic_machine=mips-compaq - os=-nonstopux - ;; - np1) - basic_machine=np1-gould - ;; - neo-tandem) - basic_machine=neo-tandem - ;; - nse-tandem) - basic_machine=nse-tandem - ;; - nsr-tandem) - basic_machine=nsr-tandem - ;; - op50n-* | op60c-*) - basic_machine=hppa1.1-oki - os=-proelf - ;; - openrisc | openrisc-*) - basic_machine=or32-unknown - ;; - os400) - basic_machine=powerpc-ibm - os=-os400 - ;; - OSE68000 | ose68000) - basic_machine=m68000-ericsson - os=-ose - ;; - os68k) - basic_machine=m68k-none - os=-os68k - ;; - pa-hitachi) - basic_machine=hppa1.1-hitachi - os=-hiuxwe2 - ;; - paragon) - basic_machine=i860-intel - os=-osf - ;; - parisc) - basic_machine=hppa-unknown - os=-linux - ;; - parisc-*) - basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'` - os=-linux - ;; - pbd) - basic_machine=sparc-tti - ;; - pbb) - basic_machine=m68k-tti - ;; - pc532 | pc532-*) - basic_machine=ns32k-pc532 - ;; - pc98) - basic_machine=i386-pc - ;; - pc98-*) - basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - pentium | p5 | k5 | k6 | nexgen | viac3) - basic_machine=i586-pc - ;; - pentiumpro | p6 | 6x86 | athlon | athlon_*) - basic_machine=i686-pc - ;; - pentiumii | pentium2 | pentiumiii | pentium3) - basic_machine=i686-pc - ;; - pentium4) - basic_machine=i786-pc - ;; - pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) - basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - pentiumpro-* | p6-* | 6x86-* | athlon-*) - basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) - basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - pentium4-*) - basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - pn) - basic_machine=pn-gould - ;; - power) basic_machine=power-ibm - ;; - ppc | ppcbe) basic_machine=powerpc-unknown - ;; - ppc-* | ppcbe-*) - basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - ppcle | powerpclittle | ppc-le | powerpc-little) - basic_machine=powerpcle-unknown - ;; - ppcle-* | powerpclittle-*) - basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - ppc64) basic_machine=powerpc64-unknown - ;; - ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - ppc64le | powerpc64little | ppc64-le | powerpc64-little) - basic_machine=powerpc64le-unknown - ;; - ppc64le-* | powerpc64little-*) - basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - ps2) - basic_machine=i386-ibm - ;; - pw32) - basic_machine=i586-unknown - os=-pw32 - ;; - rdos | rdos64) - basic_machine=x86_64-pc - os=-rdos - ;; - rdos32) - basic_machine=i386-pc - os=-rdos - ;; - rom68k) - basic_machine=m68k-rom68k - os=-coff - ;; - rm[46]00) - basic_machine=mips-siemens - ;; - rtpc | rtpc-*) - basic_machine=romp-ibm - ;; - s390 | s390-*) - basic_machine=s390-ibm - ;; - s390x | s390x-*) - basic_machine=s390x-ibm - ;; - sa29200) - basic_machine=a29k-amd - os=-udi - ;; - sb1) - basic_machine=mipsisa64sb1-unknown - ;; - sb1el) - basic_machine=mipsisa64sb1el-unknown - ;; - sde) - basic_machine=mipsisa32-sde - os=-elf - ;; - sei) - basic_machine=mips-sei - os=-seiux - ;; - sequent) - basic_machine=i386-sequent - ;; - sh) - basic_machine=sh-hitachi - os=-hms - ;; - sh5el) - basic_machine=sh5le-unknown - ;; - sh64) - basic_machine=sh64-unknown - ;; - sparclite-wrs | simso-wrs) - basic_machine=sparclite-wrs - os=-vxworks - ;; - sps7) - basic_machine=m68k-bull - os=-sysv2 - ;; - spur) - basic_machine=spur-unknown - ;; - st2000) - basic_machine=m68k-tandem - ;; - stratus) - basic_machine=i860-stratus - os=-sysv4 - ;; - strongarm-* | thumb-*) - basic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - sun2) - basic_machine=m68000-sun - ;; - sun2os3) - basic_machine=m68000-sun - os=-sunos3 - ;; - sun2os4) - basic_machine=m68000-sun - os=-sunos4 - ;; - sun3os3) - basic_machine=m68k-sun - os=-sunos3 - ;; - sun3os4) - basic_machine=m68k-sun - os=-sunos4 - ;; - sun4os3) - basic_machine=sparc-sun - os=-sunos3 - ;; - sun4os4) - basic_machine=sparc-sun - os=-sunos4 - ;; - sun4sol2) - basic_machine=sparc-sun - os=-solaris2 - ;; - sun3 | sun3-*) - basic_machine=m68k-sun - ;; - sun4) - basic_machine=sparc-sun - ;; - sun386 | sun386i | roadrunner) - basic_machine=i386-sun - ;; - sv1) - basic_machine=sv1-cray - os=-unicos - ;; - symmetry) - basic_machine=i386-sequent - os=-dynix - ;; - t3e) - basic_machine=alphaev5-cray - os=-unicos - ;; - t90) - basic_machine=t90-cray - os=-unicos - ;; - tile*) - basic_machine=$basic_machine-unknown - os=-linux-gnu - ;; - tx39) - basic_machine=mipstx39-unknown - ;; - tx39el) - basic_machine=mipstx39el-unknown - ;; - toad1) - basic_machine=pdp10-xkl - os=-tops20 - ;; - tower | tower-32) - basic_machine=m68k-ncr - ;; - tpf) - basic_machine=s390x-ibm - os=-tpf - ;; - udi29k) - basic_machine=a29k-amd - os=-udi - ;; - ultra3) - basic_machine=a29k-nyu - os=-sym1 - ;; - v810 | necv810) - basic_machine=v810-nec - os=-none - ;; - vaxv) - basic_machine=vax-dec - os=-sysv - ;; - vms) - basic_machine=vax-dec - os=-vms - ;; - vpp*|vx|vx-*) - basic_machine=f301-fujitsu - ;; - vxworks960) - basic_machine=i960-wrs - os=-vxworks - ;; - vxworks68) - basic_machine=m68k-wrs - os=-vxworks - ;; - vxworks29k) - basic_machine=a29k-wrs - os=-vxworks - ;; - w65*) - basic_machine=w65-wdc - os=-none - ;; - w89k-*) - basic_machine=hppa1.1-winbond - os=-proelf - ;; - xbox) - basic_machine=i686-pc - os=-mingw32 - ;; - xps | xps100) - basic_machine=xps100-honeywell - ;; - xscale-* | xscalee[bl]-*) - basic_machine=`echo $basic_machine | sed 's/^xscale/arm/'` - ;; - ymp) - basic_machine=ymp-cray - os=-unicos - ;; - z8k-*-coff) - basic_machine=z8k-unknown - os=-sim - ;; - z80-*-coff) - basic_machine=z80-unknown - os=-sim - ;; - none) - basic_machine=none-none - os=-none - ;; - -# Here we handle the default manufacturer of certain CPU types. It is in -# some cases the only manufacturer, in others, it is the most popular. - w89k) - basic_machine=hppa1.1-winbond - ;; - op50n) - basic_machine=hppa1.1-oki - ;; - op60c) - basic_machine=hppa1.1-oki - ;; - romp) - basic_machine=romp-ibm - ;; - mmix) - basic_machine=mmix-knuth - ;; - rs6000) - basic_machine=rs6000-ibm - ;; - vax) - basic_machine=vax-dec - ;; - pdp10) - # there are many clones, so DEC is not a safe bet - basic_machine=pdp10-unknown - ;; - pdp11) - basic_machine=pdp11-dec - ;; - we32k) - basic_machine=we32k-att - ;; - sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele) - basic_machine=sh-unknown - ;; - sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v) - basic_machine=sparc-sun - ;; - cydra) - basic_machine=cydra-cydrome - ;; - orion) - basic_machine=orion-highlevel - ;; - orion105) - basic_machine=clipper-highlevel - ;; - mac | mpw | mac-mpw) - basic_machine=m68k-apple - ;; - pmac | pmac-mpw) - basic_machine=powerpc-apple - ;; - *-unknown) - # Make sure to match an already-canonicalized machine name. - ;; - *) - echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 - exit 1 - ;; -esac - -# Here we canonicalize certain aliases for manufacturers. -case $basic_machine in - *-digital*) - basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` - ;; - *-commodore*) - basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` - ;; - *) - ;; -esac - -# Decode manufacturer-specific aliases for certain operating systems. - -if [ x"$os" != x"" ] -then -case $os in - # First match some system type aliases - # that might get confused with valid system types. - # -solaris* is a basic system type, with this one exception. - -auroraux) - os=-auroraux - ;; - -solaris1 | -solaris1.*) - os=`echo $os | sed -e 's|solaris1|sunos4|'` - ;; - -solaris) - os=-solaris2 - ;; - -svr4*) - os=-sysv4 - ;; - -unixware*) - os=-sysv4.2uw - ;; - -gnu/linux*) - os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` - ;; - # First accept the basic system types. - # The portable systems comes first. - # Each alternative MUST END IN A *, to match a version number. - # -sysv* is not here because it comes later, after sysvr4. - -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ - | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\ - | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \ - | -sym* | -kopensolaris* | -plan9* \ - | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ - | -aos* | -aros* \ - | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ - | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ - | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ - | -bitrig* | -openbsd* | -solidbsd* \ - | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ - | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ - | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ - | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ - | -chorusos* | -chorusrdb* | -cegcc* \ - | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ - | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \ - | -linux-newlib* | -linux-musl* | -linux-uclibc* \ - | -uxpv* | -beos* | -mpeix* | -udk* | -moxiebox* \ - | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ - | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ - | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ - | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ - | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ - | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ - | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es* | -tirtos*) - # Remember, each alternative MUST END IN *, to match a version number. - ;; - -qnx*) - case $basic_machine in - x86-* | i*86-*) - ;; - *) - os=-nto$os - ;; - esac - ;; - -nto-qnx*) - ;; - -nto*) - os=`echo $os | sed -e 's|nto|nto-qnx|'` - ;; - -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ - | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \ - | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) - ;; - -mac*) - os=`echo $os | sed -e 's|mac|macos|'` - ;; - -linux-dietlibc) - os=-linux-dietlibc - ;; - -linux*) - os=`echo $os | sed -e 's|linux|linux-gnu|'` - ;; - -sunos5*) - os=`echo $os | sed -e 's|sunos5|solaris2|'` - ;; - -sunos6*) - os=`echo $os | sed -e 's|sunos6|solaris3|'` - ;; - -opened*) - os=-openedition - ;; - -os400*) - os=-os400 - ;; - -wince*) - os=-wince - ;; - -osfrose*) - os=-osfrose - ;; - -osf*) - os=-osf - ;; - -utek*) - os=-bsd - ;; - -dynix*) - os=-bsd - ;; - -acis*) - os=-aos - ;; - -atheos*) - os=-atheos - ;; - -syllable*) - os=-syllable - ;; - -386bsd) - os=-bsd - ;; - -ctix* | -uts*) - os=-sysv - ;; - -nova*) - os=-rtmk-nova - ;; - -ns2 ) - os=-nextstep2 - ;; - -nsk*) - os=-nsk - ;; - # Preserve the version number of sinix5. - -sinix5.*) - os=`echo $os | sed -e 's|sinix|sysv|'` - ;; - -sinix*) - os=-sysv4 - ;; - -tpf*) - os=-tpf - ;; - -triton*) - os=-sysv3 - ;; - -oss*) - os=-sysv3 - ;; - -svr4) - os=-sysv4 - ;; - -svr3) - os=-sysv3 - ;; - -sysvr4) - os=-sysv4 - ;; - # This must come after -sysvr4. - -sysv*) - ;; - -ose*) - os=-ose - ;; - -es1800*) - os=-ose - ;; - -xenix) - os=-xenix - ;; - -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) - os=-mint - ;; - -aros*) - os=-aros - ;; - -zvmoe) - os=-zvmoe - ;; - -dicos*) - os=-dicos - ;; - -nacl*) - ;; - -none) - ;; - *) - # Get rid of the `-' at the beginning of $os. - os=`echo $os | sed 's/[^-]*-//'` - echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 - exit 1 - ;; -esac -else - -# Here we handle the default operating systems that come with various machines. -# The value should be what the vendor currently ships out the door with their -# machine or put another way, the most popular os provided with the machine. - -# Note that if you're going to try to match "-MANUFACTURER" here (say, -# "-sun"), then you have to tell the case statement up towards the top -# that MANUFACTURER isn't an operating system. Otherwise, code above -# will signal an error saying that MANUFACTURER isn't an operating -# system, and we'll never get to this point. - -case $basic_machine in - score-*) - os=-elf - ;; - spu-*) - os=-elf - ;; - *-acorn) - os=-riscix1.2 - ;; - arm*-rebel) - os=-linux - ;; - arm*-semi) - os=-aout - ;; - c4x-* | tic4x-*) - os=-coff - ;; - c8051-*) - os=-elf - ;; - hexagon-*) - os=-elf - ;; - tic54x-*) - os=-coff - ;; - tic55x-*) - os=-coff - ;; - tic6x-*) - os=-coff - ;; - # This must come before the *-dec entry. - pdp10-*) - os=-tops20 - ;; - pdp11-*) - os=-none - ;; - *-dec | vax-*) - os=-ultrix4.2 - ;; - m68*-apollo) - os=-domain - ;; - i386-sun) - os=-sunos4.0.2 - ;; - m68000-sun) - os=-sunos3 - ;; - m68*-cisco) - os=-aout - ;; - mep-*) - os=-elf - ;; - mips*-cisco) - os=-elf - ;; - mips*-*) - os=-elf - ;; - or32-*) - os=-coff - ;; - *-tti) # must be before sparc entry or we get the wrong os. - os=-sysv3 - ;; - sparc-* | *-sun) - os=-sunos4.1.1 - ;; - *-be) - os=-beos - ;; - *-haiku) - os=-haiku - ;; - *-ibm) - os=-aix - ;; - *-knuth) - os=-mmixware - ;; - *-wec) - os=-proelf - ;; - *-winbond) - os=-proelf - ;; - *-oki) - os=-proelf - ;; - *-hp) - os=-hpux - ;; - *-hitachi) - os=-hiux - ;; - i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) - os=-sysv - ;; - *-cbm) - os=-amigaos - ;; - *-dg) - os=-dgux - ;; - *-dolphin) - os=-sysv3 - ;; - m68k-ccur) - os=-rtu - ;; - m88k-omron*) - os=-luna - ;; - *-next ) - os=-nextstep - ;; - *-sequent) - os=-ptx - ;; - *-crds) - os=-unos - ;; - *-ns) - os=-genix - ;; - i370-*) - os=-mvs - ;; - *-next) - os=-nextstep3 - ;; - *-gould) - os=-sysv - ;; - *-highlevel) - os=-bsd - ;; - *-encore) - os=-bsd - ;; - *-sgi) - os=-irix - ;; - *-siemens) - os=-sysv4 - ;; - *-masscomp) - os=-rtu - ;; - f30[01]-fujitsu | f700-fujitsu) - os=-uxpv - ;; - *-rom68k) - os=-coff - ;; - *-*bug) - os=-coff - ;; - *-apple) - os=-macos - ;; - *-atari*) - os=-mint - ;; - *) - os=-none - ;; -esac -fi - -# Here we handle the case where we know the os, and the CPU type, but not the -# manufacturer. We pick the logical manufacturer. -vendor=unknown -case $basic_machine in - *-unknown) - case $os in - -riscix*) - vendor=acorn - ;; - -sunos*) - vendor=sun - ;; - -cnk*|-aix*) - vendor=ibm - ;; - -beos*) - vendor=be - ;; - -hpux*) - vendor=hp - ;; - -mpeix*) - vendor=hp - ;; - -hiux*) - vendor=hitachi - ;; - -unos*) - vendor=crds - ;; - -dgux*) - vendor=dg - ;; - -luna*) - vendor=omron - ;; - -genix*) - vendor=ns - ;; - -mvs* | -opened*) - vendor=ibm - ;; - -os400*) - vendor=ibm - ;; - -ptx*) - vendor=sequent - ;; - -tpf*) - vendor=ibm - ;; - -vxsim* | -vxworks* | -windiss*) - vendor=wrs - ;; - -aux*) - vendor=apple - ;; - -hms*) - vendor=hitachi - ;; - -mpw* | -macos*) - vendor=apple - ;; - -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) - vendor=atari - ;; - -vos*) - vendor=stratus - ;; - esac - basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` - ;; -esac - -echo $basic_machine$os -exit - -# Local variables: -# eval: (add-hook 'write-file-hooks 'time-stamp) -# time-stamp-start: "timestamp='" -# time-stamp-format: "%:y-%02m-%02d" -# time-stamp-end: "'" -# End: diff --git a/build-aux/install-sh b/build-aux/install-sh deleted file mode 100755 index 0b0fdcbba..000000000 --- a/build-aux/install-sh +++ /dev/null @@ -1,501 +0,0 @@ -#!/bin/sh -# install - install a program, script, or datafile - -scriptversion=2013-12-25.23; # UTC - -# This originates from X11R5 (mit/util/scripts/install.sh), which was -# later released in X11R6 (xc/config/util/install.sh) with the -# following copyright and license. -# -# Copyright (C) 1994 X Consortium -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to -# deal in the Software without restriction, including without limitation the -# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -# sell copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN -# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- -# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -# -# Except as contained in this notice, the name of the X Consortium shall not -# be used in advertising or otherwise to promote the sale, use or other deal- -# ings in this Software without prior written authorization from the X Consor- -# tium. -# -# -# FSF changes to this file are in the public domain. -# -# Calling this script install-sh is preferred over install.sh, to prevent -# 'make' implicit rules from creating a file called install from it -# when there is no Makefile. -# -# This script is compatible with the BSD install script, but was written -# from scratch. - -tab=' ' -nl=' -' -IFS=" $tab$nl" - -# Set DOITPROG to "echo" to test this script. - -doit=${DOITPROG-} -doit_exec=${doit:-exec} - -# Put in absolute file names if you don't have them in your path; -# or use environment vars. - -chgrpprog=${CHGRPPROG-chgrp} -chmodprog=${CHMODPROG-chmod} -chownprog=${CHOWNPROG-chown} -cmpprog=${CMPPROG-cmp} -cpprog=${CPPROG-cp} -mkdirprog=${MKDIRPROG-mkdir} -mvprog=${MVPROG-mv} -rmprog=${RMPROG-rm} -stripprog=${STRIPPROG-strip} - -posix_mkdir= - -# Desired mode of installed file. -mode=0755 - -chgrpcmd= -chmodcmd=$chmodprog -chowncmd= -mvcmd=$mvprog -rmcmd="$rmprog -f" -stripcmd= - -src= -dst= -dir_arg= -dst_arg= - -copy_on_change=false -is_target_a_directory=possibly - -usage="\ -Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE - or: $0 [OPTION]... SRCFILES... DIRECTORY - or: $0 [OPTION]... -t DIRECTORY SRCFILES... - or: $0 [OPTION]... -d DIRECTORIES... - -In the 1st form, copy SRCFILE to DSTFILE. -In the 2nd and 3rd, copy all SRCFILES to DIRECTORY. -In the 4th, create DIRECTORIES. - -Options: - --help display this help and exit. - --version display version info and exit. - - -c (ignored) - -C install only if different (preserve the last data modification time) - -d create directories instead of installing files. - -g GROUP $chgrpprog installed files to GROUP. - -m MODE $chmodprog installed files to MODE. - -o USER $chownprog installed files to USER. - -s $stripprog installed files. - -t DIRECTORY install into DIRECTORY. - -T report an error if DSTFILE is a directory. - -Environment variables override the default commands: - CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG - RMPROG STRIPPROG -" - -while test $# -ne 0; do - case $1 in - -c) ;; - - -C) copy_on_change=true;; - - -d) dir_arg=true;; - - -g) chgrpcmd="$chgrpprog $2" - shift;; - - --help) echo "$usage"; exit $?;; - - -m) mode=$2 - case $mode in - *' '* | *"$tab"* | *"$nl"* | *'*'* | *'?'* | *'['*) - echo "$0: invalid mode: $mode" >&2 - exit 1;; - esac - shift;; - - -o) chowncmd="$chownprog $2" - shift;; - - -s) stripcmd=$stripprog;; - - -t) - is_target_a_directory=always - dst_arg=$2 - # Protect names problematic for 'test' and other utilities. - case $dst_arg in - -* | [=\(\)!]) dst_arg=./$dst_arg;; - esac - shift;; - - -T) is_target_a_directory=never;; - - --version) echo "$0 $scriptversion"; exit $?;; - - --) shift - break;; - - -*) echo "$0: invalid option: $1" >&2 - exit 1;; - - *) break;; - esac - shift -done - -# We allow the use of options -d and -T together, by making -d -# take the precedence; this is for compatibility with GNU install. - -if test -n "$dir_arg"; then - if test -n "$dst_arg"; then - echo "$0: target directory not allowed when installing a directory." >&2 - exit 1 - fi -fi - -if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then - # When -d is used, all remaining arguments are directories to create. - # When -t is used, the destination is already specified. - # Otherwise, the last argument is the destination. Remove it from $@. - for arg - do - if test -n "$dst_arg"; then - # $@ is not empty: it contains at least $arg. - set fnord "$@" "$dst_arg" - shift # fnord - fi - shift # arg - dst_arg=$arg - # Protect names problematic for 'test' and other utilities. - case $dst_arg in - -* | [=\(\)!]) dst_arg=./$dst_arg;; - esac - done -fi - -if test $# -eq 0; then - if test -z "$dir_arg"; then - echo "$0: no input file specified." >&2 - exit 1 - fi - # It's OK to call 'install-sh -d' without argument. - # This can happen when creating conditional directories. - exit 0 -fi - -if test -z "$dir_arg"; then - if test $# -gt 1 || test "$is_target_a_directory" = always; then - if test ! -d "$dst_arg"; then - echo "$0: $dst_arg: Is not a directory." >&2 - exit 1 - fi - fi -fi - -if test -z "$dir_arg"; then - do_exit='(exit $ret); exit $ret' - trap "ret=129; $do_exit" 1 - trap "ret=130; $do_exit" 2 - trap "ret=141; $do_exit" 13 - trap "ret=143; $do_exit" 15 - - # Set umask so as not to create temps with too-generous modes. - # However, 'strip' requires both read and write access to temps. - case $mode in - # Optimize common cases. - *644) cp_umask=133;; - *755) cp_umask=22;; - - *[0-7]) - if test -z "$stripcmd"; then - u_plus_rw= - else - u_plus_rw='% 200' - fi - cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;; - *) - if test -z "$stripcmd"; then - u_plus_rw= - else - u_plus_rw=,u+rw - fi - cp_umask=$mode$u_plus_rw;; - esac -fi - -for src -do - # Protect names problematic for 'test' and other utilities. - case $src in - -* | [=\(\)!]) src=./$src;; - esac - - if test -n "$dir_arg"; then - dst=$src - dstdir=$dst - test -d "$dstdir" - dstdir_status=$? - else - - # Waiting for this to be detected by the "$cpprog $src $dsttmp" command - # might cause directories to be created, which would be especially bad - # if $src (and thus $dsttmp) contains '*'. - if test ! -f "$src" && test ! -d "$src"; then - echo "$0: $src does not exist." >&2 - exit 1 - fi - - if test -z "$dst_arg"; then - echo "$0: no destination specified." >&2 - exit 1 - fi - dst=$dst_arg - - # If destination is a directory, append the input filename; won't work - # if double slashes aren't ignored. - if test -d "$dst"; then - if test "$is_target_a_directory" = never; then - echo "$0: $dst_arg: Is a directory" >&2 - exit 1 - fi - dstdir=$dst - dst=$dstdir/`basename "$src"` - dstdir_status=0 - else - dstdir=`dirname "$dst"` - test -d "$dstdir" - dstdir_status=$? - fi - fi - - obsolete_mkdir_used=false - - if test $dstdir_status != 0; then - case $posix_mkdir in - '') - # Create intermediate dirs using mode 755 as modified by the umask. - # This is like FreeBSD 'install' as of 1997-10-28. - umask=`umask` - case $stripcmd.$umask in - # Optimize common cases. - *[2367][2367]) mkdir_umask=$umask;; - .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;; - - *[0-7]) - mkdir_umask=`expr $umask + 22 \ - - $umask % 100 % 40 + $umask % 20 \ - - $umask % 10 % 4 + $umask % 2 - `;; - *) mkdir_umask=$umask,go-w;; - esac - - # With -d, create the new directory with the user-specified mode. - # Otherwise, rely on $mkdir_umask. - if test -n "$dir_arg"; then - mkdir_mode=-m$mode - else - mkdir_mode= - fi - - posix_mkdir=false - case $umask in - *[123567][0-7][0-7]) - # POSIX mkdir -p sets u+wx bits regardless of umask, which - # is incompatible with FreeBSD 'install' when (umask & 300) != 0. - ;; - *) - tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ - trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0 - - if (umask $mkdir_umask && - exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1 - then - if test -z "$dir_arg" || { - # Check for POSIX incompatibilities with -m. - # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or - # other-writable bit of parent directory when it shouldn't. - # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. - ls_ld_tmpdir=`ls -ld "$tmpdir"` - case $ls_ld_tmpdir in - d????-?r-*) different_mode=700;; - d????-?--*) different_mode=755;; - *) false;; - esac && - $mkdirprog -m$different_mode -p -- "$tmpdir" && { - ls_ld_tmpdir_1=`ls -ld "$tmpdir"` - test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" - } - } - then posix_mkdir=: - fi - rmdir "$tmpdir/d" "$tmpdir" - else - # Remove any dirs left behind by ancient mkdir implementations. - rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null - fi - trap '' 0;; - esac;; - esac - - if - $posix_mkdir && ( - umask $mkdir_umask && - $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" - ) - then : - else - - # The umask is ridiculous, or mkdir does not conform to POSIX, - # or it failed possibly due to a race condition. Create the - # directory the slow way, step by step, checking for races as we go. - - case $dstdir in - /*) prefix='/';; - [-=\(\)!]*) prefix='./';; - *) prefix='';; - esac - - oIFS=$IFS - IFS=/ - set -f - set fnord $dstdir - shift - set +f - IFS=$oIFS - - prefixes= - - for d - do - test X"$d" = X && continue - - prefix=$prefix$d - if test -d "$prefix"; then - prefixes= - else - if $posix_mkdir; then - (umask=$mkdir_umask && - $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break - # Don't fail if two instances are running concurrently. - test -d "$prefix" || exit 1 - else - case $prefix in - *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;; - *) qprefix=$prefix;; - esac - prefixes="$prefixes '$qprefix'" - fi - fi - prefix=$prefix/ - done - - if test -n "$prefixes"; then - # Don't fail if two instances are running concurrently. - (umask $mkdir_umask && - eval "\$doit_exec \$mkdirprog $prefixes") || - test -d "$dstdir" || exit 1 - obsolete_mkdir_used=true - fi - fi - fi - - if test -n "$dir_arg"; then - { test -z "$chowncmd" || $doit $chowncmd "$dst"; } && - { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } && - { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false || - test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1 - else - - # Make a couple of temp file names in the proper directory. - dsttmp=$dstdir/_inst.$$_ - rmtmp=$dstdir/_rm.$$_ - - # Trap to clean up those temp files at exit. - trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 - - # Copy the file name to the temp name. - (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") && - - # and set any options; do chmod last to preserve setuid bits. - # - # If any of these fail, we abort the whole thing. If we want to - # ignore errors from any of these, just make sure not to ignore - # errors from the above "$doit $cpprog $src $dsttmp" command. - # - { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } && - { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } && - { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } && - { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } && - - # If -C, don't bother to copy if it wouldn't change the file. - if $copy_on_change && - old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` && - new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` && - set -f && - set X $old && old=:$2:$4:$5:$6 && - set X $new && new=:$2:$4:$5:$6 && - set +f && - test "$old" = "$new" && - $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1 - then - rm -f "$dsttmp" - else - # Rename the file to the real destination. - $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null || - - # The rename failed, perhaps because mv can't rename something else - # to itself, or perhaps because mv is so ancient that it does not - # support -f. - { - # Now remove or move aside any old file at destination location. - # We try this two ways since rm can't unlink itself on some - # systems and the destination file might be busy for other - # reasons. In this case, the final cleanup might fail but the new - # file should still install successfully. - { - test ! -f "$dst" || - $doit $rmcmd -f "$dst" 2>/dev/null || - { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null && - { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; } - } || - { echo "$0: cannot unlink or rename $dst" >&2 - (exit 1); exit 1 - } - } && - - # Now rename the file to the real destination. - $doit $mvcmd "$dsttmp" "$dst" - } - fi || exit 1 - - trap '' 0 - fi -done - -# Local variables: -# eval: (add-hook 'write-file-hooks 'time-stamp) -# time-stamp-start: "scriptversion=" -# time-stamp-format: "%:y-%02m-%02d.%02H" -# time-stamp-time-zone: "UTC" -# time-stamp-end: "; # UTC" -# End: diff --git a/build-aux/missing b/build-aux/missing deleted file mode 100755 index f62bbae30..000000000 --- a/build-aux/missing +++ /dev/null @@ -1,215 +0,0 @@ -#! /bin/sh -# Common wrapper for a few potentially missing GNU programs. - -scriptversion=2013-10-28.13; # UTC - -# Copyright (C) 1996-2014 Free Software Foundation, Inc. -# Originally written by Fran,cois Pinard , 1996. - -# 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, 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, see . - -# As a special exception to the GNU General Public License, if you -# distribute this file as part of a program that contains a -# configuration script generated by Autoconf, you may include it under -# the same distribution terms that you use for the rest of that program. - -if test $# -eq 0; then - echo 1>&2 "Try '$0 --help' for more information" - exit 1 -fi - -case $1 in - - --is-lightweight) - # Used by our autoconf macros to check whether the available missing - # script is modern enough. - exit 0 - ;; - - --run) - # Back-compat with the calling convention used by older automake. - shift - ;; - - -h|--h|--he|--hel|--help) - echo "\ -$0 [OPTION]... PROGRAM [ARGUMENT]... - -Run 'PROGRAM [ARGUMENT]...', returning a proper advice when this fails due -to PROGRAM being missing or too old. - -Options: - -h, --help display this help and exit - -v, --version output version information and exit - -Supported PROGRAM values: - aclocal autoconf autoheader autom4te automake makeinfo - bison yacc flex lex help2man - -Version suffixes to PROGRAM as well as the prefixes 'gnu-', 'gnu', and -'g' are ignored when checking the name. - -Send bug reports to ." - exit $? - ;; - - -v|--v|--ve|--ver|--vers|--versi|--versio|--version) - echo "missing $scriptversion (GNU Automake)" - exit $? - ;; - - -*) - echo 1>&2 "$0: unknown '$1' option" - echo 1>&2 "Try '$0 --help' for more information" - exit 1 - ;; - -esac - -# Run the given program, remember its exit status. -"$@"; st=$? - -# If it succeeded, we are done. -test $st -eq 0 && exit 0 - -# Also exit now if we it failed (or wasn't found), and '--version' was -# passed; such an option is passed most likely to detect whether the -# program is present and works. -case $2 in --version|--help) exit $st;; esac - -# Exit code 63 means version mismatch. This often happens when the user -# tries to use an ancient version of a tool on a file that requires a -# minimum version. -if test $st -eq 63; then - msg="probably too old" -elif test $st -eq 127; then - # Program was missing. - msg="missing on your system" -else - # Program was found and executed, but failed. Give up. - exit $st -fi - -perl_URL=http://www.perl.org/ -flex_URL=http://flex.sourceforge.net/ -gnu_software_URL=http://www.gnu.org/software - -program_details () -{ - case $1 in - aclocal|automake) - echo "The '$1' program is part of the GNU Automake package:" - echo "<$gnu_software_URL/automake>" - echo "It also requires GNU Autoconf, GNU m4 and Perl in order to run:" - echo "<$gnu_software_URL/autoconf>" - echo "<$gnu_software_URL/m4/>" - echo "<$perl_URL>" - ;; - autoconf|autom4te|autoheader) - echo "The '$1' program is part of the GNU Autoconf package:" - echo "<$gnu_software_URL/autoconf/>" - echo "It also requires GNU m4 and Perl in order to run:" - echo "<$gnu_software_URL/m4/>" - echo "<$perl_URL>" - ;; - esac -} - -give_advice () -{ - # Normalize program name to check for. - normalized_program=`echo "$1" | sed ' - s/^gnu-//; t - s/^gnu//; t - s/^g//; t'` - - printf '%s\n' "'$1' is $msg." - - configure_deps="'configure.ac' or m4 files included by 'configure.ac'" - case $normalized_program in - autoconf*) - echo "You should only need it if you modified 'configure.ac'," - echo "or m4 files included by it." - program_details 'autoconf' - ;; - autoheader*) - echo "You should only need it if you modified 'acconfig.h' or" - echo "$configure_deps." - program_details 'autoheader' - ;; - automake*) - echo "You should only need it if you modified 'Makefile.am' or" - echo "$configure_deps." - program_details 'automake' - ;; - aclocal*) - echo "You should only need it if you modified 'acinclude.m4' or" - echo "$configure_deps." - program_details 'aclocal' - ;; - autom4te*) - echo "You might have modified some maintainer files that require" - echo "the 'autom4te' program to be rebuilt." - program_details 'autom4te' - ;; - bison*|yacc*) - echo "You should only need it if you modified a '.y' file." - echo "You may want to install the GNU Bison package:" - echo "<$gnu_software_URL/bison/>" - ;; - lex*|flex*) - echo "You should only need it if you modified a '.l' file." - echo "You may want to install the Fast Lexical Analyzer package:" - echo "<$flex_URL>" - ;; - help2man*) - echo "You should only need it if you modified a dependency" \ - "of a man page." - echo "You may want to install the GNU Help2man package:" - echo "<$gnu_software_URL/help2man/>" - ;; - makeinfo*) - echo "You should only need it if you modified a '.texi' file, or" - echo "any other file indirectly affecting the aspect of the manual." - echo "You might want to install the Texinfo package:" - echo "<$gnu_software_URL/texinfo/>" - echo "The spurious makeinfo call might also be the consequence of" - echo "using a buggy 'make' (AIX, DU, IRIX), in which case you might" - echo "want to install GNU make:" - echo "<$gnu_software_URL/make/>" - ;; - *) - echo "You might have modified some files without having the proper" - echo "tools for further handling them. Check the 'README' file, it" - echo "often tells you about the needed prerequisites for installing" - echo "this package. You may also peek at any GNU archive site, in" - echo "case some other package contains this missing '$1' program." - ;; - esac -} - -give_advice "$1" | sed -e '1s/^/WARNING: /' \ - -e '2,$s/^/ /' >&2 - -# Propagate the correct exit status (expected to be 127 for a program -# not found, 63 for a program that failed due to version mismatch). -exit $st - -# Local variables: -# eval: (add-hook 'write-file-hooks 'time-stamp) -# time-stamp-start: "scriptversion=" -# time-stamp-format: "%:y-%02m-%02d.%02H" -# time-stamp-time-zone: "UTC" -# time-stamp-end: "; # UTC" -# End: diff --git a/cmake/Modules/DeployQt5.cmake b/cmake/Modules/DeployQt5.cmake deleted file mode 100644 index f92e7db2f..000000000 --- a/cmake/Modules/DeployQt5.cmake +++ /dev/null @@ -1,355 +0,0 @@ -# Borrowed from Avogadro project (https://github.com/OpenChemistry/avogadroapp) - -#.rst: -# DeployQt5 -# --------- -# -# Functions to help assemble a standalone Qt5 executable. -# -# A collection of CMake utility functions useful for deploying Qt5 -# executables. -# -# The following functions are provided by this module: -# -# :: -# -# write_qt5_conf -# resolve_qt5_paths -# fixup_qt5_executable -# install_qt5_plugin_path -# install_qt5_plugin -# install_qt5_executable -# -# Requires CMake 2.8.9 or greater because Qt 5 does. -# Also depends on BundleUtilities.cmake. -# -# :: -# -# WRITE_QT5_CONF( ) -# -# Writes a qt.conf file with the into . -# -# :: -# -# RESOLVE_QT5_PATHS( []) -# -# Loop through list and if any don't exist resolve them -# relative to the (if supplied) or the -# CMAKE_INSTALL_PREFIX. -# -# :: -# -# FIXUP_QT5_EXECUTABLE( [ ]) -# -# Copies Qt plugins, writes a Qt configuration file (if needed) and -# fixes up a Qt5 executable using BundleUtilities so it is standalone -# and can be drag-and-drop copied to another machine as long as all of -# the system libraries are compatible. -# -# should point to the executable to be fixed-up. -# -# should contain a list of the names or paths of any Qt -# plugins to be installed. -# -# will be passed to BundleUtilities and should be a list of any -# already installed plugins, libraries or executables to also be -# fixed-up. -# -# will be passed to BundleUtilities and should contain and -# directories to be searched to find library dependencies. -# -# allows an custom plugins directory to be used. -# -# will force a qt.conf file to be written even if not -# needed. -# -# :: -# -# INSTALL_QT5_PLUGIN_PATH(plugin executable copy installed_plugin_path_var ) -# -# Install (or copy) a resolved to the default plugins directory -# (or ) relative to and store the result in -# . -# -# If is set to TRUE then the plugins will be copied rather than -# installed. This is to allow this module to be used at CMake time -# rather than install time. -# -# If is set then anything installed will use this COMPONENT. -# -# :: -# -# INSTALL_QT5_PLUGIN(plugin executable copy installed_plugin_path_var ) -# -# Install (or copy) an unresolved to the default plugins -# directory (or ) relative to and store the -# result in . See documentation of -# INSTALL_QT5_PLUGIN_PATH. -# -# :: -# -# INSTALL_QT5_EXECUTABLE( [ ]) -# -# Installs Qt plugins, writes a Qt configuration file (if needed) and -# fixes up a Qt5 executable using BundleUtilities so it is standalone -# and can be drag-and-drop copied to another machine as long as all of -# the system libraries are compatible. The executable will be fixed-up -# at install time. is the COMPONENT used for bundle fixup -# and plugin installation. See documentation of FIXUP_QT5_BUNDLE. - -#============================================================================= -# Copyright 2011 Mike McQuaid -# -# Distributed under the OSI-approved BSD License (the "License"); -# see accompanying file Copyright.txt for details. -# -# This software is distributed WITHOUT ANY WARRANTY; without even the -# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -# See the License for more information. -#============================================================================= -# (To distribute this file outside of CMake, substitute the full -# License text for the above reference.) - -# The functions defined in this file depend on the fixup_bundle function -# (and others) found in BundleUtilities.cmake - -include(BundleUtilities) -set(DeployQt5_cmake_dir "${CMAKE_CURRENT_LIST_DIR}") -set(DeployQt5_apple_plugins_dir "PlugIns") - -function(write_qt5_conf qt_conf_dir qt_conf_contents) - set(qt_conf_path "${qt_conf_dir}/qt.conf") - message(STATUS "Writing ${qt_conf_path}") - file(WRITE "${qt_conf_path}" "${qt_conf_contents}") -endfunction() - -function(resolve_qt5_paths paths_var) - set(executable_path ${ARGV1}) - - set(paths_resolved) - foreach(path ${${paths_var}}) - if(EXISTS "${path}") - list(APPEND paths_resolved "${path}") - else() - if(${executable_path}) - list(APPEND paths_resolved "${executable_path}/${path}") - else() - list(APPEND paths_resolved "\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/${path}") - endif() - endif() - endforeach() - set(${paths_var} ${paths_resolved} PARENT_SCOPE) -endfunction() - -function(fixup_qt5_executable executable) - set(qtplugins ${ARGV1}) - set(libs ${ARGV2}) - set(dirs ${ARGV3}) - set(plugins_dir ${ARGV4}) - set(request_qt_conf ${ARGV5}) - - message(STATUS "fixup_qt5_executable") - message(STATUS " executable='${executable}'") - message(STATUS " qtplugins='${qtplugins}'") - message(STATUS " libs='${libs}'") - message(STATUS " dirs='${dirs}'") - message(STATUS " plugins_dir='${plugins_dir}'") - message(STATUS " request_qt_conf='${request_qt_conf}'") - - if(QT_LIBRARY_DIR) - list(APPEND dirs "${QT_LIBRARY_DIR}") - endif() - if(QT_BINARY_DIR) - list(APPEND dirs "${QT_BINARY_DIR}") - endif() - - if(APPLE) - set(qt_conf_dir "${executable}/Contents/Resources") - set(executable_path "${executable}") - set(write_qt_conf TRUE) - if(NOT plugins_dir) - set(plugins_dir "${DeployQt5_apple_plugins_dir}") - endif() - else() - get_filename_component(executable_path "${executable}" PATH) - if(NOT executable_path) - set(executable_path ".") - endif() - set(qt_conf_dir "${executable_path}") - set(write_qt_conf ${request_qt_conf}) - endif() - - foreach(plugin ${qtplugins}) - set(installed_plugin_path "") - install_qt5_plugin("${plugin}" "${executable}" 1 installed_plugin_path) - list(APPEND libs ${installed_plugin_path}) - endforeach() - - foreach(lib ${libs}) - if(NOT EXISTS "${lib}") - message(FATAL_ERROR "Library does not exist: ${lib}") - endif() - endforeach() - - resolve_qt5_paths(libs "${executable_path}") - - if(write_qt_conf) - set(qt_conf_contents "[Paths]\nPlugins = ${plugins_dir}") - write_qt5_conf("${qt_conf_dir}" "${qt_conf_contents}") - endif() - - fixup_bundle("${executable}" "${libs}" "${dirs}") -endfunction() - -function(install_qt5_plugin_path plugin executable copy installed_plugin_path_var) - set(plugins_dir ${ARGV4}) - set(component ${ARGV5}) - set(configurations ${ARGV6}) - if(EXISTS "${plugin}") - if(APPLE) - if(NOT plugins_dir) - set(plugins_dir "${DeployQt5_apple_plugins_dir}") - endif() - set(plugins_path "${executable}/Contents/${plugins_dir}") - else() - get_filename_component(plugins_path "${executable}" PATH) - if(NOT plugins_path) - set(plugins_path ".") - endif() - if(plugins_dir) - set(plugins_path "${plugins_path}/${plugins_dir}") - endif() - endif() - - set(plugin_group "") - - get_filename_component(plugin_path "${plugin}" PATH) - get_filename_component(plugin_parent_path "${plugin_path}" PATH) - get_filename_component(plugin_parent_dir_name "${plugin_parent_path}" NAME) - get_filename_component(plugin_name "${plugin}" NAME) - string(TOLOWER "${plugin_parent_dir_name}" plugin_parent_dir_name) - - if("${plugin_parent_dir_name}" STREQUAL "plugins") - get_filename_component(plugin_group "${plugin_path}" NAME) - set(${plugin_group_var} "${plugin_group}") - endif() - set(plugins_path "${plugins_path}/${plugin_group}") - - if(${copy}) - file(MAKE_DIRECTORY "${plugins_path}") - file(COPY "${plugin}" DESTINATION "${plugins_path}") - else() - if(configurations AND (CMAKE_CONFIGURATION_TYPES OR CMAKE_BUILD_TYPE)) - set(configurations CONFIGURATIONS ${configurations}) - else() - unset(configurations) - endif() - install(FILES "${plugin}" DESTINATION "${plugins_path}" ${configurations} ${component}) - endif() - set(${installed_plugin_path_var} "${plugins_path}/${plugin_name}" PARENT_SCOPE) - endif() -endfunction() - -function(install_qt5_plugin plugin executable copy installed_plugin_path_var) - set(plugins_dir ${ARGV4}) - set(component ${ARGV5}) - if(EXISTS "${plugin}") - install_qt5_plugin_path("${plugin}" "${executable}" "${copy}" "${installed_plugin_path_var}" "${plugins_dir}" "${component}") - else() - string(TOUPPER "QT_${plugin}_PLUGIN" plugin_var) - set(plugin_release_var "${plugin_var}_RELEASE") - set(plugin_debug_var "${plugin_var}_DEBUG") - set(plugin_release "${${plugin_release_var}}") - set(plugin_debug "${${plugin_debug_var}}") - if(DEFINED "${plugin_release_var}" AND DEFINED "${plugin_debug_var}" AND NOT EXISTS "${plugin_release}" AND NOT EXISTS "${plugin_debug}") - message(WARNING "Qt plugin \"${plugin}\" not recognized or found.") - endif() - if(NOT EXISTS "${${plugin_debug_var}}") - set(plugin_debug "${plugin_release}") - endif() - - if(CMAKE_CONFIGURATION_TYPES OR CMAKE_BUILD_TYPE) - install_qt5_plugin_path("${plugin_release}" "${executable}" "${copy}" "${installed_plugin_path_var}_release" "${plugins_dir}" "${component}" "Release|RelWithDebInfo|MinSizeRel") - install_qt5_plugin_path("${plugin_debug}" "${executable}" "${copy}" "${installed_plugin_path_var}_debug" "${plugins_dir}" "${component}" "Debug") - - if(CMAKE_BUILD_TYPE MATCHES "^Debug$") - set(${installed_plugin_path_var} ${${installed_plugin_path_var}_debug}) - else() - set(${installed_plugin_path_var} ${${installed_plugin_path_var}_release}) - endif() - else() - install_qt5_plugin_path("${plugin_release}" "${executable}" "${copy}" "${installed_plugin_path_var}" "${plugins_dir}" "${component}") - endif() - endif() - set(${installed_plugin_path_var} ${${installed_plugin_path_var}} PARENT_SCOPE) -endfunction() - -function(install_qt5_executable executable) - set(qtplugins ${ARGV1}) - set(libs ${ARGV2}) - set(dirs ${ARGV3}) - set(plugins_dir ${ARGV4}) - set(request_qt_conf ${ARGV5}) - set(component ${ARGV6}) - if(QT_LIBRARY_DIR) - list(APPEND dirs "${QT_LIBRARY_DIR}") - endif() - if(QT_BINARY_DIR) - list(APPEND dirs "${QT_BINARY_DIR}") - endif() - if(TARGET Qt5::Core) - get_property(_locCore TARGET Qt5::Core PROPERTY LOCATION_RELEASE) - get_filename_component(_loc ${_locCore} DIRECTORY) - message(STATUS "Adding Qt 5 directory: ${_loc}") - list(APPEND dirs "${_loc}") - else() - message(FATAL_ERROR "No Qt5::Core target found, ensure it is available") - endif() - if(component) - set(component COMPONENT ${component}) - else() - unset(component) - endif() - - get_filename_component(executable_absolute "${executable}" ABSOLUTE) - if(EXISTS "${QT_QTCORE_LIBRARY_RELEASE}") - gp_file_type("${executable_absolute}" "${QT_QTCORE_LIBRARY_RELEASE}" qtcore_type) - elseif(EXISTS "${QT_QTCORE_LIBRARY_DEBUG}") - gp_file_type("${executable_absolute}" "${QT_QTCORE_LIBRARY_DEBUG}" qtcore_type) - endif() - if(qtcore_type STREQUAL "system") - set(qt_plugins_dir "") - endif() - - if(QT_IS_STATIC) - message(WARNING "Qt built statically: not installing plugins.") - else() - if(APPLE) - get_property(loc TARGET Qt5::QCocoaIntegrationPlugin - PROPERTY LOCATION_RELEASE) - install_qt5_plugin("${loc}" "${executable}" 0 installed_plugin_paths - "PlugIns" "${component}") - list(APPEND libs ${installed_plugin_paths}) - elseif(WIN32) - get_property(loc TARGET Qt5::QWindowsIntegrationPlugin - PROPERTY LOCATION_RELEASE) - install_qt5_plugin("${loc}" "${executable}" 0 installed_plugin_paths - "" "${component}") - list(APPEND libs ${installed_plugin_paths}) - endif() - foreach(plugin ${qtplugins}) - set(installed_plugin_paths "") - install_qt5_plugin("${plugin}" "${executable}" 0 installed_plugin_paths "${plugins_dir}" "${component}") - list(APPEND libs ${installed_plugin_paths}) - endforeach() - endif() - - resolve_qt5_paths(libs "") - - install(CODE - "include(\"${DeployQt5_cmake_dir}/DeployQt5.cmake\") - set(BU_CHMOD_BUNDLE_ITEMS TRUE) - fixup_qt5_executable(\"\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/${executable}\" \"\" \"${libs}\" \"${dirs}\" \"${plugins_dir}\" \"${request_qt_conf}\")" - ${component} - ) -endfunction() diff --git a/cmake/Modules/FindLibtorrentRasterbar.cmake b/cmake/Modules/FindLibtorrentRasterbar.cmake deleted file mode 100644 index 8719b5662..000000000 --- a/cmake/Modules/FindLibtorrentRasterbar.cmake +++ /dev/null @@ -1,127 +0,0 @@ -# - Try to find libtorrent-rasterbar -# -# If not using pkg-config, you can pre-set LibtorrentRasterbar_CUSTOM_DEFINITIONS -# for definitions unrelated to Boost's separate compilation (which are already -# decided by the LibtorrentRasterbar_USE_STATIC_LIBS variable). -# -# Once done this will define -# LibtorrentRasterbar_FOUND - System has libtorrent-rasterbar -# LibtorrentRasterbar_INCLUDE_DIRS - The libtorrent-rasterbar include directories -# LibtorrentRasterbar_LIBRARIES - The libraries needed to use libtorrent-rasterbar -# LibtorrentRasterbar_DEFINITIONS - Compiler switches required for using libtorrent-rasterbar -# LibtorrentRasterbar_OPENSSL_ENABLED - libtorrent-rasterbar uses and links against OpenSSL - -find_package(Threads REQUIRED) -find_package(PkgConfig QUIET) - -macro(_detect_boost_components _outComponets librariesList) - string(REGEX MATCHALL "boost_[a-z_]+[-a-z]*" _boost_libraries "${librariesList}") - string(REGEX REPLACE "boost_([a-z_]+)[-a-z]*" "\\1" ${_outComponets} "${_boost_libraries}") -endmacro() - -if(PKG_CONFIG_FOUND) - pkg_check_modules(PC_LIBTORRENT_RASTERBAR QUIET libtorrent-rasterbar) -endif() - -if(LibtorrentRasterbar_USE_STATIC_LIBS) - set(LibtorrentRasterbar_ORIG_CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES}) - set(CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_STATIC_LIBRARY_SUFFIX}) -endif() - -if(PC_LIBTORRENT_RASTERBAR_FOUND) - set(LibtorrentRasterbar_DEFINITIONS ${PC_LIBTORRENT_RASTERBAR_CFLAGS}) -else() - if(LibtorrentRasterbar_CUSTOM_DEFINITIONS) - set(LibtorrentRasterbar_DEFINITIONS ${LibtorrentRasterbar_CUSTOM_DEFINITIONS}) - else() - # Without pkg-config, we can't possibly figure out the correct build flags. - # libtorrent is very picky about those. Let's take a set of defaults and - # hope that they apply. If not, you the user are on your own. - set(LibtorrentRasterbar_DEFINITIONS - -DTORRENT_USE_OPENSSL - -DTORRENT_DISABLE_GEO_IP - -DBOOST_ASIO_ENABLE_CANCELIO - -DUNICODE -D_UNICODE -D_FILE_OFFSET_BITS=64) - endif() - - if(NOT LibtorrentRasterbar_USE_STATIC_LIBS) - list(APPEND LibtorrentRasterbar_DEFINITIONS - -DTORRENT_LINKING_SHARED - -DBOOST_SYSTEM_DYN_LINK -DBOOST_CHRONO_DYN_LINK) - endif() -endif() - -message(STATUS "libtorrent definitions: ${LibtorrentRasterbar_DEFINITIONS}") - -find_path(LibtorrentRasterbar_INCLUDE_DIR libtorrent - HINTS ${PC_LIBTORRENT_RASTERBAR_INCLUDEDIR} ${PC_LIBTORRENT_RASTERBAR_INCLUDE_DIRS} - PATH_SUFFIXES libtorrent-rasterbar) - -find_library(LibtorrentRasterbar_LIBRARY NAMES torrent-rasterbar libtorrent - HINTS ${PC_LIBTORRENT_RASTERBAR_LIBDIR} ${PC_LIBTORRENT_RASTERBAR_LIBRARY_DIRS}) - -if(LibtorrentRasterbar_USE_STATIC_LIBS) - set(CMAKE_FIND_LIBRARY_SUFFIXES ${LibtorrentRasterbar_ORIG_CMAKE_FIND_LIBRARY_SUFFIXES}) -endif() - -set(LibtorrentRasterbar_LIBRARIES ${LibtorrentRasterbar_LIBRARY} ${CMAKE_THREAD_LIBS_INIT}) -set(LibtorrentRasterbar_INCLUDE_DIRS ${LibtorrentRasterbar_INCLUDE_DIR}) - -# Without pkg-config, we can't possibly figure out the correct boost dependencies -if (LibtorrentRasterbar_CUSTOM_BOOST_DEPENDENCIES) - set(_boost_components "${LibtorrentRasterbar_CUSTOM_BOOST_DEPENDENCIES}") -else(LibtorrentRasterbar_CUSTOM_BOOST_DEPENDENCIES) - if(PC_LIBTORRENT_RASTERBAR_FOUND) - _detect_boost_components(_boost_components "${PC_LIBTORRENT_RASTERBAR_LIBRARIES}") - else() - # all possible boost dependencies - set(_boost_components - date_time - system - chrono - random - thread - ) - endif() -endif(LibtorrentRasterbar_CUSTOM_BOOST_DEPENDENCIES) - -list(SORT _boost_components) -message(STATUS "Libtorrent Boost dependencies: ${_boost_components}") -find_package(Boost REQUIRED COMPONENTS ${_boost_components}) -set(LibtorrentRasterbar_LIBRARIES ${LibtorrentRasterbar_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT}) -foreach(_boost_cmpnt IN LISTS _boost_components) - list(APPEND LibtorrentRasterbar_LIBRARIES "Boost::${_boost_cmpnt}") -endforeach(_boost_cmpnt) - -set(LibtorrentRasterbar_INCLUDE_DIRS ${LibtorrentRasterbar_INCLUDE_DIRS}) - -list(FIND LibtorrentRasterbar_DEFINITIONS -DTORRENT_USE_OPENSSL LibtorrentRasterbar_ENCRYPTION_INDEX) -if(LibtorrentRasterbar_ENCRYPTION_INDEX GREATER -1) - find_package(OpenSSL REQUIRED) - set(LibtorrentRasterbar_LIBRARIES ${LibtorrentRasterbar_LIBRARIES} OpenSSL::SSL OpenSSL::Crypto) - set(LibtorrentRasterbar_OPENSSL_ENABLED ON) -endif() - -include(FindPackageHandleStandardArgs) -# handle the QUIETLY and REQUIRED arguments and set LibtorrentRasterbar_FOUND to TRUE -# if all listed variables are TRUE -find_package_handle_standard_args(LibtorrentRasterbar DEFAULT_MSG - LibtorrentRasterbar_LIBRARY - LibtorrentRasterbar_INCLUDE_DIR) - -mark_as_advanced(LibtorrentRasterbar_INCLUDE_DIR LibtorrentRasterbar_LIBRARY - LibtorrentRasterbar_ORIG_CMAKE_FIND_LIBRARY_SUFFIXES - LibtorrentRasterbar_ENCRYPTION_INDEX) - -if (LibtorrentRasterbar_FOUND AND NOT TARGET LibtorrentRasterbar::LibTorrent) - add_library(LibtorrentRasterbar::LibTorrent UNKNOWN IMPORTED) - - set_target_properties(LibtorrentRasterbar::LibTorrent PROPERTIES - IMPORTED_LINK_INTERFACE_LANGUAGES "CXX" - IMPORTED_LOCATION "${LibtorrentRasterbar_LIBRARY}" - INTERFACE_INCLUDE_DIRECTORIES "${LibtorrentRasterbar_INCLUDE_DIRS}" - INTERFACE_SYSTEM_INCLUDE_DIRECTORIES "${LibtorrentRasterbar_INCLUDE_DIRS}" - INTERFACE_LINK_LIBRARIES "${LibtorrentRasterbar_LIBRARIES}" - INTERFACE_COMPILE_OPTIONS "${LibtorrentRasterbar_DEFINITIONS}" - ) -endif() diff --git a/cmake/Modules/FindQtSingleApplication.cmake b/cmake/Modules/FindQtSingleApplication.cmake deleted file mode 100644 index eb56607e9..000000000 --- a/cmake/Modules/FindQtSingleApplication.cmake +++ /dev/null @@ -1,94 +0,0 @@ -# - Try to find the QtSingleApplication includes and library -# which defines -# -# QTSINGLEAPPLICATION_FOUND - system has QtSingleApplication -# QTSINGLEAPPLICATION_INCLUDE_DIR - where to find header QtSingleApplication -# QTSINGLEAPPLICATION_LIBRARIES - the libraries to link against to use QtSingleApplication -# QTSINGLEAPPLICATION_LIBRARY - where to find the QtSingleApplication library (not for general use) - -# copyright (c) 2013 TI_Eugene ti.eugene@gmail.com -# -# Redistribution and use is allowed according to the terms of the FreeBSD license. - -SET(QTSINGLEAPPLICATION_FOUND FALSE) - -IF(QT4_FOUND) - message(STATUS "Looking for Qt4 single application library") - FIND_PATH(QTSINGLEAPPLICATION_INCLUDE_DIR QtSingleApplication - # standard locations - /usr/include - /usr/include/QtSolutions - # qt4 location except mac's frameworks - "${QT_INCLUDE_DIR}/QtSolutions" - # mac's frameworks - ${FRAMEWORK_INCLUDE_DIR}/QtSolutions - ) - - SET(QTSINGLEAPPLICATION_NAMES ${QTSINGLEAPPLICATION_NAMES} - QtSolutions_SingleApplication-2.6 libQtSolutions_SingleApplication-2.6) - FIND_LIBRARY(QTSINGLEAPPLICATION_LIBRARY - NAMES ${QTSINGLEAPPLICATION_NAMES} - PATHS ${QT_LIBRARY_DIR} - ) -ELSEIF(Qt5Widgets_FOUND) - message(STATUS "Looking for Qt5 single application library") - FOREACH(TOP_INCLUDE_PATH in ${Qt5Widgets_INCLUDE_DIRS} ${FRAMEWORK_INCLUDE_DIR}) - FIND_PATH(QTSINGLEAPPLICATION_INCLUDE_DIR QtSingleApplication ${TOP_INCLUDE_PATH}/QtSolutions) - - IF(QTSINGLEAPPLICATION_INCLUDE_DIR) - BREAK() - ENDIF() - ENDFOREACH() - - SET(QTSINGLEAPPLICATION_NAMES ${QTSINGLEAPPLICATION_NAMES} - Qt5Solutions_SingleApplication-2.6 libQt5Solutions_SingleApplication-2.6 - QtSolutions_SingleApplication-2.6 libQtSolutions_SingleApplication-2.6) - GET_TARGET_PROPERTY(QT5_WIDGETSLIBRARY Qt5::Widgets LOCATION) - GET_FILENAME_COMPONENT(QT5_WIDGETSLIBRARYPATH ${QT5_WIDGETSLIBRARY} PATH) - - FIND_LIBRARY(QTSINGLEAPPLICATION_LIBRARY - NAMES ${QTSINGLEAPPLICATION_NAMES} - PATHS ${QT5_WIDGETSLIBRARYPATH} - ) -ENDIF() - -IF (QTSINGLEAPPLICATION_LIBRARY AND QTSINGLEAPPLICATION_INCLUDE_DIR) - - SET(QTSINGLEAPPLICATION_LIBRARIES ${QTSINGLEAPPLICATION_LIBRARY}) - SET(QTSINGLEAPPLICATION_FOUND TRUE) - - IF (CYGWIN) - IF(BUILD_SHARED_LIBS) - # No need to define QTSINGLEAPPLICATION_USE_DLL here, because it's default for Cygwin. - ELSE(BUILD_SHARED_LIBS) - SET (QTSINGLEAPPLICATION_DEFINITIONS -DQTSINGLEAPPLICATION_STATIC) - ENDIF(BUILD_SHARED_LIBS) - ENDIF (CYGWIN) - -ENDIF (QTSINGLEAPPLICATION_LIBRARY AND QTSINGLEAPPLICATION_INCLUDE_DIR) - -IF (QTSINGLEAPPLICATION_FOUND) - IF (NOT QtSingleApplication_FIND_QUIETLY) - MESSAGE(STATUS "Found QtSingleApplication: ${QTSINGLEAPPLICATION_LIBRARY}") - MESSAGE(STATUS " includes: ${QTSINGLEAPPLICATION_INCLUDE_DIR}") - ENDIF (NOT QtSingleApplication_FIND_QUIETLY) -ELSE (QTSINGLEAPPLICATION_FOUND) - IF (QtSingleApplication_FIND_REQUIRED) - MESSAGE(FATAL_ERROR "Could not find QtSingleApplication library") - ENDIF (QtSingleApplication_FIND_REQUIRED) -ENDIF (QTSINGLEAPPLICATION_FOUND) - -MARK_AS_ADVANCED(QTSINGLEAPPLICATION_INCLUDE_DIR QTSINGLEAPPLICATION_LIBRARY) - -if(NOT TARGET QtSingleApplication::QtSingleApplication) - add_library(QtSingleApplication::QtSingleApplication UNKNOWN IMPORTED) - set_target_properties(QtSingleApplication::QtSingleApplication PROPERTIES - INTERFACE_INCLUDE_DIRECTORIES "${QTSINGLEAPPLICATION_INCLUDE_DIR}" - INTERFACE_SYSTEM_INCLUDE_DIRECTORIES "${QTSINGLEAPPLICATION_INCLUDE_DIR}" - ) - if(EXISTS "${QTSINGLEAPPLICATION_LIBRARY}") - set_target_properties(QtSingleApplication::QtSingleApplication PROPERTIES - IMPORTED_LINK_INTERFACE_LANGUAGES "CXX" - IMPORTED_LOCATION "${QTSINGLEAPPLICATION_LIBRARY}") - endif() -endif(NOT TARGET QtSingleApplication::QtSingleApplication) diff --git a/cmake/Modules/FindSystemd.cmake b/cmake/Modules/FindSystemd.cmake deleted file mode 100644 index 73ebf3693..000000000 --- a/cmake/Modules/FindSystemd.cmake +++ /dev/null @@ -1,26 +0,0 @@ -####### -# Find systemd service dir -# sets variables -# SYSTEMD_FOUND -# SYSTEMD_SERVICES_INSTALL_DIR - -find_package(PkgConfig QUIET REQUIRED) - -if (NOT SYSTEMD_FOUND) - pkg_check_modules(SYSTEMD "systemd") -endif(NOT SYSTEMD_FOUND) - -if (SYSTEMD_FOUND AND "${SYSTEMD_SERVICES_INSTALL_DIR}" STREQUAL "") - execute_process(COMMAND ${PKG_CONFIG_EXECUTABLE} - --variable=systemdsystemunitdir systemd - OUTPUT_VARIABLE SYSTEMD_SERVICES_INSTALL_DIR) - string(REGEX REPLACE "[ \t\n]+" "" SYSTEMD_SERVICES_INSTALL_DIR - "${SYSTEMD_SERVICES_INSTALL_DIR}") -elseif (NOT SYSTEMD_FOUND AND SYSTEMD_SERVICES_INSTALL_DIR) - message (FATAL_ERROR "Variable SYSTEMD_SERVICES_INSTALL_DIR is\ - defined, but we can't find systemd using pkg-config") -endif() - -if (SYSTEMD_FOUND) - message(STATUS "systemd services install dir: ${SYSTEMD_SERVICES_INSTALL_DIR}") -endif(SYSTEMD_FOUND) diff --git a/cmake/Modules/FunctionReadVersion.cmake b/cmake/Modules/FunctionReadVersion.cmake deleted file mode 100644 index 2e51f7d02..000000000 --- a/cmake/Modules/FunctionReadVersion.cmake +++ /dev/null @@ -1,28 +0,0 @@ -# function for parsing version variables that are set in version.pri file -# the version identifiers there are defined as follows: -# VER_MAJOR = 3 -# VER_MINOR = 4 -# VER_BUGFIX = 0 -# VER_BUILD = 0 -# VER_STATUS = alpha - -function(read_version priFile outMajor outMinor outBugfix outBuild outStatus) - file(STRINGS ${priFile} _priFileContents REGEX "^VER_.+") - # message(STATUS "version.pri version contents: ${_priFileContents}") - # the _priFileContents variable contains something like the following: - # VER_MAJOR = 3;VER_MINOR = 4;VER_BUGFIX = 0;VER_BUILD = 0;VER_STATUS = alpha # Should be empty for stable releases! - set(_regex "VER_MAJOR += +([0-9]+);VER_MINOR += +([0-9]+);VER_BUGFIX += +([0-9]+);VER_BUILD += +([0-9]+);VER_STATUS += +([0-9A-Za-z]+)?") - # note quotes around _regex, they are needed because the variable contains semicolons - string(REGEX MATCH "${_regex}" _tmp "${_priFileContents}") - if (NOT _tmp) - message(FATAL_ERROR "Could not detect project version number from ${priFile}") - endif() - - # message(STATUS "Matched version string: ${_tmp}") - - set(${outMajor} ${CMAKE_MATCH_1} PARENT_SCOPE) - set(${outMinor} ${CMAKE_MATCH_2} PARENT_SCOPE) - set(${outBugfix} ${CMAKE_MATCH_3} PARENT_SCOPE) - set(${outBuild} ${CMAKE_MATCH_4} PARENT_SCOPE) - set(${outStatus} ${CMAKE_MATCH_5} PARENT_SCOPE) -endfunction() diff --git a/cmake/Modules/MacroConfigureMSVCRuntime.cmake b/cmake/Modules/MacroConfigureMSVCRuntime.cmake deleted file mode 100644 index b44fd0a64..000000000 --- a/cmake/Modules/MacroConfigureMSVCRuntime.cmake +++ /dev/null @@ -1,38 +0,0 @@ -macro(configure_msvc_runtime) - if(MSVC) - # Default to statically-linked runtime. - if("${MSVC_RUNTIME}" STREQUAL "") - set(MSVC_RUNTIME "static") - endif() - # Set compiler options. - set(variables - CMAKE_C_FLAGS_DEBUG - CMAKE_C_FLAGS_MINSIZEREL - CMAKE_C_FLAGS_RELEASE - CMAKE_C_FLAGS_RELWITHDEBINFO - CMAKE_CXX_FLAGS_DEBUG - CMAKE_CXX_FLAGS_MINSIZEREL - CMAKE_CXX_FLAGS_RELEASE - CMAKE_CXX_FLAGS_RELWITHDEBINFO - ) - if(${MSVC_RUNTIME} STREQUAL "static") - message(STATUS - "MSVC -> forcing use of statically-linked runtime." - ) - foreach(variable ${variables}) - if(${variable} MATCHES "/MD") - string(REGEX REPLACE "/MD" "/MT" ${variable} "${${variable}}") - endif() - endforeach() - else() - message(STATUS - "MSVC -> forcing use of dynamically-linked runtime." - ) - foreach(variable ${variables}) - if(${variable} MATCHES "/MT") - string(REGEX REPLACE "/MT" "/MD" ${variable} "${${variable}}") - endif() - endforeach() - endif() - endif() -endmacro() diff --git a/cmake/Modules/MacroGlibcDetect.cmake b/cmake/Modules/MacroGlibcDetect.cmake deleted file mode 100644 index 7e462e11b..000000000 --- a/cmake/Modules/MacroGlibcDetect.cmake +++ /dev/null @@ -1,49 +0,0 @@ - ############################################################### - # - # Copyright 2011 Red Hat, Inc. - # - # Licensed under the Apache License, Version 2.0 (the "License"); you - # may not use this file except in compliance with the License. You may - # obtain a copy of the License at - # - # http://www.apache.org/licenses/LICENSE-2.0 - # - # Unless required by applicable law or agreed to in writing, software - # distributed under the License is distributed on an "AS IS" BASIS, - # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - # See the License for the specific language governing permissions and - # limitations under the License. - # - ############################################################### - -MACRO (GLIBC_DETECT _VERSION) - -# there are multiple ways to detect glibc, but given nmi's -# cons'd up paths I will trust only gcc. I guess I could also use -# ldd --version to detect. - - set(_GLIB_SOURCE_DETECT " -#include -#include -int main() -{ - printf(\"%d%d\",__GLIBC__, __GLIBC_MINOR__); - return 0; -} -") - -file (WRITE ${CMAKE_CURRENT_BINARY_DIR}/build/cmake/glibc.cpp "${_GLIB_SOURCE_DETECT}\n") - -try_run(POST26_GLIBC_DETECTED - POST26_GLIBC_COMPILE - ${CMAKE_CURRENT_BINARY_DIR}/build/cmake - ${CMAKE_CURRENT_BINARY_DIR}/build/cmake/glibc.cpp - RUN_OUTPUT_VARIABLE GLIBC_VERSION ) - -if (GLIBC_VERSION AND POST26_GLIBC_COMPILE ) - set(${_VERSION} ${GLIBC_VERSION}) -else() - message(STATUS "NOTE: Could not detect GLIBC_VERSION from compiler") -endif() - -ENDMACRO (GLIBC_DETECT) diff --git a/cmake/Modules/MacroLinkQtComponents.cmake b/cmake/Modules/MacroLinkQtComponents.cmake deleted file mode 100644 index c8a1c941f..000000000 --- a/cmake/Modules/MacroLinkQtComponents.cmake +++ /dev/null @@ -1,28 +0,0 @@ -# - macro similar to target_link_libraries, which links Qt components -# names of the components are pased in Qt4/Qt5 agnostic way (Core, DBus, Xml...) -# and the macro links Qt4 ones if QT4_FOUND is set or Qt5 ones if not - -macro (target_link_qt_components target) -if (QT4_FOUND) - foreach(_cmp ${ARGN}) - if ("${_cmp}" STREQUAL "PRIVATE" OR - "${_cmp}" STREQUAL "PUBLIC" OR - "${_cmp}" STREQUAL "INTERFACE") - list(APPEND _QT_CMPNTS "${_cmp}") - else() - list(APPEND _QT_CMPNTS "Qt4::Qt${_cmp}") - endif() - endforeach() -else (QT4_FOUND) - foreach(_cmp ${ARGN}) - if ("${_cmp}" STREQUAL "PRIVATE" OR - "${_cmp}" STREQUAL "PUBLIC" OR - "${_cmp}" STREQUAL "INTERFACE") - list(APPEND _QT_CMPNTS "${_cmp}") - else() - list(APPEND _QT_CMPNTS "Qt5::${_cmp}") - endif() - endforeach() -endif (QT4_FOUND) - target_link_libraries(${target} ${_QT_CMPNTS}) -endmacro() diff --git a/cmake/Modules/MacroQbtCompilerSettings.cmake b/cmake/Modules/MacroQbtCompilerSettings.cmake deleted file mode 100644 index 114681c12..000000000 --- a/cmake/Modules/MacroQbtCompilerSettings.cmake +++ /dev/null @@ -1,89 +0,0 @@ -# Sets cache variable QBT_ADDITONAL_FLAGS and QBT_ADDITONAL_CXX_FLAGS to list of additional -# compiler flags for C and C++ (QBT_ADDITONAL_FLAGS) and for C++ only (QBT_ADDITONAL_CXX_FLAGS) -# and appends them to CMAKE_XXX_FLAGS variables. - -# It could use add_compile_options(), but then it is needed to use generator expressions, -# and most interesting of them are not compatible with Visual Studio :( - -macro(qbt_set_compiler_options) -# if (NOT QBT_ADDITONAL_FLAGS) - if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") - #-Wshadow -Wconversion ? - set(_GCC_COMMON_C_AND_CXX_FLAGS "-Wall -Wextra" - "-Wfloat-equal -Wcast-qual -Wcast-align" - "-Wsign-conversion -Winvalid-pch -Werror=return-type -Wno-long-long" -# -fstack-protector-all - "-Werror -Wno-error=deprecated-declarations" - ) - set (_GCC_COMMON_CXX_FLAGS "-fexceptions -frtti" - "-Woverloaded-virtual -Wold-style-cast -Wstrict-null-sentinel" - "-Wnon-virtual-dtor -Wfloat-equal -Wcast-qual -Wcast-align" - "-Werror=overloaded-virtual" - # "-Weffc++" - "-Werror -Wno-error=cpp" - # we should modify code to make these ones obsolete - "-Wno-error=sign-conversion -Wno-error=float-equal" - ) - - if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.9) - # GCC 4.8 has problems with std::array and its initialization - list(APPEND _GCC_COMMON_CXX_FLAGS "-Wno-error=missing-field-initializers") - endif() - - include(CheckCXXCompilerFlag) - # check for -pedantic - check_cxx_compiler_flag(-pedantic _PEDANTIC_IS_SUPPORTED) - if (_PEDANTIC_IS_SUPPORTED) - list(APPEND _GCC_COMMON_CXX_FLAGS "-pedantic -pedantic-errors") - else (_PEDANTIC_IS_SUPPORTED) - list(APPEND _GCC_COMMON_CXX_FLAGS "-Wpedantic") - endif (_PEDANTIC_IS_SUPPORTED) - - if (CMAKE_SYSTEM_NAME MATCHES Linux) - # if Glibc version is 2.20 or higher, set -D_DEFAULT_SOURCE - include(MacroGlibcDetect) - message(STATUS "Detecting Glibc version...") - glibc_detect(GLIBC_VERSION) - if(${GLIBC_VERSION}) - if(GLIBC_VERSION LESS "220") - message(STATUS "Glibc version is ${GLIBC_VERSION}") - else(GLIBC_VERSION LESS "220") - message(STATUS "Glibc version is ${GLIBC_VERSION}, adding -D_DEFAULT_SOURCE") - add_definitions(-D_DEFAULT_SOURCE) - endif(GLIBC_VERSION LESS "220") - endif(${GLIBC_VERSION}) - endif (CMAKE_SYSTEM_NAME MATCHES Linux) - - string(REPLACE ";" " " _GCC_COMMON_C_AND_CXX_FLAGS_STRING "${_GCC_COMMON_C_AND_CXX_FLAGS}") - string(REPLACE ";" " " _GCC_COMMON_CXX_FLAGS_STRING "${_GCC_COMMON_CXX_FLAGS}") - - string(APPEND CMAKE_C_FLAGS " ${_GCC_COMMON_C_AND_CXX_FLAGS_STRING}") - string(APPEND CMAKE_CXX_FLAGS " ${_GCC_COMMON_C_AND_CXX_FLAGS_STRING} ${_GCC_COMMON_CXX_FLAGS_STRING}") - - set(QBT_ADDITONAL_FLAGS "${_GCC_COMMON_C_AND_CXX_FLAGS_STRING}" CACHE STRING - "Additional qBittorent compile flags" FORCE) - set(QBT_ADDITONAL_CXX_FLAGS "${_GCC_COMMON_CXX_FLAGS_STRING}" CACHE STRING - "Additional qBittorent C++ compile flags" FORCE) - - # check whether we can enable -Og optimization for debug build - # also let's enable -march=native for debug builds - check_cxx_compiler_flag(-Og _DEBUG_OPTIMIZATION_LEVEL_IS_SUPPORTED) - - if (_DEBUG_OPTIMIZATION_LEVEL_IS_SUPPORTED) - string(APPEND CMAKE_C_FLAGS_DEBUG " -Og -g3 -march=native -pipe" ) - string(APPEND CMAKE_CXX_FLAGS_DEBUG " -Og -g3 -march=native -pipe" ) - else(_DEBUG_OPTIMIZATION_LEVEL_IS_SUPPORTED) - string(APPEND CMAKE_C_FLAGS_DEBUG " -O0 -g3 -march=native -pipe" ) - string(APPEND CMAKE_CXX_FLAGS_DEBUG " -O0 -g3 -march=native -pipe" ) - endif (_DEBUG_OPTIMIZATION_LEVEL_IS_SUPPORTED) - endif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") - - if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") - set(QBT_ADDITONAL_FLAGS "-wd4290 -wd4275 -wd4251 /W4" CACHE STRING "Additional qBittorent compile flags") - string(APPEND CMAKE_C_FLAGS " ${QBT_ADDITONAL_FLAGS}") - string(APPEND CMAKE_CXX_FLAGS " ${QBT_ADDITONAL_FLAGS}") - endif () - -# endif (NOT QBT_ADDITONAL_FLAGS) -endmacro(qbt_set_compiler_options) - diff --git a/cmake/Modules/QbtTargetSources.cmake b/cmake/Modules/QbtTargetSources.cmake deleted file mode 100644 index c49fef312..000000000 --- a/cmake/Modules/QbtTargetSources.cmake +++ /dev/null @@ -1,16 +0,0 @@ -# a helper function which appends source to the main qBt target -# sources file names are relative to the the ${qBittorrent_SOURCE_DIR} - -function (qbt_target_sources) - set (_sources_rel "") - foreach (_source IN ITEMS ${ARGN}) - if (IS_ABSOLUTE "${_source}") - set(source_abs "${_source}") - else() - get_filename_component(_source_abs "${_source}" ABSOLUTE) - endif() - file (RELATIVE_PATH _source_rel "${qbt_executable_SOURCE_DIR}" "${_source_abs}") - list (APPEND _sources_rel "${_source_rel}") - endforeach() - target_sources (qBittorrent PRIVATE "${_sources_rel}") -endfunction (qbt_target_sources) diff --git a/cmake/Modules/bundle.cmake b/cmake/Modules/bundle.cmake deleted file mode 100644 index 608dc395d..000000000 --- a/cmake/Modules/bundle.cmake +++ /dev/null @@ -1,21 +0,0 @@ -set(BU_CHMOD_BUNDLE_ITEMS ON) -include(DeployQt5) - -set(plugins "") - -get_property(svgIconPluginLocation TARGET Qt5::QSvgIconPlugin - PROPERTY LOCATION_RELEASE) -list(APPEND plugins "${svgIconPluginLocation}") -get_property(svgPluginLocation TARGET Qt5::QSvgPlugin - PROPERTY LOCATION_RELEASE) -list(APPEND plugins "${svgPluginLocation}") - -set(sfx "") -if(APPLE) - set(sfx ".app") -elseif(WIN32) - set(sfx "${CMAKE_EXECUTABLE_SUFFIX}") -endif() - -get_target_property(exe qBittorrent OUTPUT_NAME) -install_qt5_executable("${exe}${sfx}" "${plugins}" "" "" "") diff --git a/cmake/Modules/winconf-mingw.cmake b/cmake/Modules/winconf-mingw.cmake deleted file mode 100644 index 542fadca5..000000000 --- a/cmake/Modules/winconf-mingw.cmake +++ /dev/null @@ -1,14 +0,0 @@ -if (STACKTRACE_WIN) - if ("${WINXXBITS}" NOT STREQUAL "Win64") - add_compile_options(-fno-omit-frame-pointer) - endif ("${WINXXBITS}" NOT STREQUAL "Win64") - link_libraries(libdbghelp -Wl,--export-all-symbols) -endif (STACKTRACE_WIN) - -if (("${CMAKE_BUILD_TYPE}" STREQUAL "Debug") OR ("${CMAKE_BUILD_TYPE}" STREQUAL "RelWithDebInfo")) - link_libraries(-Wl,--dynamicbase) -endif() - -# LIBS += libadvapi32 libshell32 libuser32 -# LIBS += libcrypto.dll libssl.dll libwsock32 libws2_32 libz libiconv.dll -# LIBS += libpowrprof diff --git a/cmake/Modules/winconf-msvc.cmake b/cmake/Modules/winconf-msvc.cmake deleted file mode 100644 index d678a5b27..000000000 --- a/cmake/Modules/winconf-msvc.cmake +++ /dev/null @@ -1,21 +0,0 @@ -if (STACKTRACE_WIN) - if ("${WINXXBITS}" STREQUAL "Win64") - add_compile_options(-Zi) - else ("${WINXXBITS}" STREQUAL "Win64") - # i686 arch requires frame pointer preservation - add_compile_options(-Oy-) - endif ("${WINXXBITS}" STREQUAL "Win64") - link_libraries(dbghelp.lib) -endif (STACKTRACE_WIN) - -# Enable Wide characters -add_definitions(-DTORRENT_USE_WPATH) - -if (NOT QT5) - # Qt4 does not detect it itself - add_definitions(-DQ_COMPILER_INITIALIZER_LISTS) -endif (NOT QT5) - -include(MacroConfigureMSVCRuntime) -set(MSVC_RUNTIME "dynamic") -configure_msvc_runtime() diff --git a/cmake/Modules/winconf.cmake b/cmake/Modules/winconf.cmake deleted file mode 100644 index 7dc7907bd..000000000 --- a/cmake/Modules/winconf.cmake +++ /dev/null @@ -1,91 +0,0 @@ -# Settings for compiling qBittorrent on Windows - -list(APPEND CMAKE_LIBRARY_PATH "$ENV{LIB}") - -# We want to link with static version of -# libtorrent -set(LibtorrentRasterbar_USE_STATIC_LIBS True) -set(LibtorrentRasterbar_CUSTOM_DEFINITIONS - -DBOOST_ALL_NO_LIB -DBOOST_ASIO_HASH_MAP_BUCKETS=1021 - -DBOOST_ASIO_SEPARATE_COMPILATION - -DBOOST_EXCEPTION_DISABLE - -DBOOST_SYSTEM_STATIC_LINK=1 - -DTORRENT_USE_OPENSSL - -D__USE_W32_SOCKETS - -D_FILE_OFFSET_BITS=64) - -add_definitions(-DUNICODE - -D_UNICODE - -DWIN32 - -D_WIN32 - -DWIN32_LEAN_AND_MEAN - -DNTDDI_VERSION=0x05010000 - -D_WIN32_WINNT=0x0501 - -D_WIN32_IE=0x0501 - -D_CRT_SECURE_NO_DEPRECATE - -D_SCL_SECURE_NO_DEPRECATE -) -# and boost -set(Boost_USE_STATIC_LIBS True) -# set(Boost_USE_STATIC_RUNTIME True) - -# Here we assume that all required libraries are installed into the same prefix -# with usual unix subdirectories (bin, lib, include) -# if so, we just need to set CMAKE_SYSTEM_PREFIX_PATH -# If it is not the case, individual paths need to be specified manually (see below) -set(COMMON_INSTALL_PREFIX "c:/usr" CACHE PATH "Prefix used to install all the required libraries") -list(APPEND CMAKE_SYSTEM_PREFIX_PATH "${COMMON_INSTALL_PREFIX}") - -# If two version of Qt are installed, separate prefixes are needed most likely -set(QT4_INSTALL_PREFIX "${COMMON_INSTALL_PREFIX}/lib/qt4" CACHE PATH "Prefix where Qt4 is installed") -set(QT5_INSTALL_PREFIX "${COMMON_INSTALL_PREFIX}/lib/qt5" CACHE PATH "Prefix where Qt5 is installed") - -# it is safe to set Qt dirs even if their files are directly in the prefix -# Qt4 -if(NOT QT5) - # for qt 4 we need qmake, Qt5 provides cmake config files - LIST(APPEND CMAKE_PROGRAM_PATH "${QT4_INSTALL_PREFIX}/bin/") -endif(NOT QT5) - -# Qt5 -set(Qt5_DIR "${QT5_INSTALL_PREFIX}/lib/cmake/Qt5") - -# And now we can set specific values for the Boost and libtorrent libraries. -# The following values are generated from the paths listed above just for an example -# they have to be set to actual locations - -# Boost -# set(BOOST_ROOT "${COMMON_INSTALL_PREFIX}") -# set(Boost_version_suffix "1_59") -# if a link like boost-version/boost -> boost was created or the boost directory was renamed in the same way, -# the following needs adjustment -# set(BOOST_INCLUDEDIR "${COMMON_INSTALL_PREFIX}/include/boost-${Boost_version_suffix}") -# set(BOOST_LIBRARYDIR "${COMMON_INSTALL_PREFIX}/lib/") - -# libtorrent - -# set(PC_LIBTORRENT_RASTERBAR_INCLUDEDIR "${COMMON_INSTALL_PREFIX}") -# set(PC_LIBTORRENT_RASTERBAR_LIBDIR "${COMMON_INSTALL_PREFIX}/lib") - -set(AUTOGEN_TARGETS_FOLDER "generated") - -set(CMAKE_INSTALL_BINDIR ".") - -# Test 32/64 bits -if("${CMAKE_SIZEOF_VOID_P}" EQUAL "8") - message(STATUS "Target is 64 bits") - if (WIN32) - set(WINXXBITS Win64) - endif(WIN32) -else("${CMAKE_SIZEOF_VOID_P}" EQUAL "8") - message(STATUS "Target is 32 bits") - if (WIN32) - set(WINXXBITS Win32) - endif(WIN32) -endif("${CMAKE_SIZEOF_VOID_P}" EQUAL "8") - -if (MSVC) - include(winconf-msvc) -else (MSVC) - include(winconf-mingw) -endif (MSVC) diff --git a/codingStyleQtCreator.xml b/codingStyleQtCreator.xml deleted file mode 100644 index 0f8ccaae6..000000000 --- a/codingStyleQtCreator.xml +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - CodeStyleData - - true - false - false - true - false - true - false - false - true - false - false - false - true - true - false - true - false - true - false - 4 - true - false - 1 - true - 4 - - - - DisplayName - qBittorrent - - diff --git a/conf.pri.in b/conf.pri.in deleted file mode 100644 index 09ce6d1e5..000000000 --- a/conf.pri.in +++ /dev/null @@ -1,24 +0,0 @@ -# @configure_input@ - -PREFIX = @EXPAND_PREFIX@ -BINDIR = @EXPAND_BINDIR@ -DATADIR = @EXPAND_DATADIR@ -MANPREFIX = @EXPAND_MANDIR@ - -QMAKE_CXXFLAGS += @QBT_CONF_EXTRA_CFLAGS@ - -EXTERNAL_INCLUDES = @QBT_CONF_INCLUDES@ -EXTERNAL_INCLUDES -= $$QMAKE_DEFAULT_INCDIRS -# added /usr/local/include due to Qt 5.7.0 bug on macOS -macx: EXTERNAL_INCLUDES += "/usr/local/include" -INCLUDEPATH += $$EXTERNAL_INCLUDES - -EXTERNAL_LIBS = @LDFLAGS@ @LIBS@ -EXTERNAL_LIBS -= $$QMAKE_DEFAULT_LIBDIRS -LIBS += $$EXTERNAL_LIBS - -CONFIG += @QBT_ADD_CONFIG@ -CONFIG -= @QBT_REMOVE_CONFIG@ - -DEFINES += @QBT_ADD_DEFINES@ -DEFINES -= @QBT_REMOVE_DEFINES@ diff --git a/configure b/configure deleted file mode 100755 index 8b25e3f1a..000000000 --- a/configure +++ /dev/null @@ -1,8027 +0,0 @@ -#! /bin/sh -# Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.69 for qbittorrent v3.2.0alpha. -# -# Report bugs to . -# -# -# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. -# -# -# This configure script is free software; the Free Software Foundation -# gives unlimited permission to copy, distribute and modify it. -## -------------------- ## -## M4sh Initialization. ## -## -------------------- ## - -# Be more Bourne compatible -DUALCASE=1; export DUALCASE # for MKS sh -if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : - emulate sh - NULLCMD=: - # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which - # is contrary to our usage. Disable this feature. - alias -g '${1+"$@"}'='"$@"' - setopt NO_GLOB_SUBST -else - case `(set -o) 2>/dev/null` in #( - *posix*) : - set -o posix ;; #( - *) : - ;; -esac -fi - - -as_nl=' -' -export as_nl -# Printing a long string crashes Solaris 7 /usr/bin/printf. -as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' -as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo -as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo -# Prefer a ksh shell builtin over an external printf program on Solaris, -# but without wasting forks for bash or zsh. -if test -z "$BASH_VERSION$ZSH_VERSION" \ - && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then - as_echo='print -r --' - as_echo_n='print -rn --' -elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then - as_echo='printf %s\n' - as_echo_n='printf %s' -else - if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then - as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' - as_echo_n='/usr/ucb/echo -n' - else - as_echo_body='eval expr "X$1" : "X\\(.*\\)"' - as_echo_n_body='eval - arg=$1; - case $arg in #( - *"$as_nl"*) - expr "X$arg" : "X\\(.*\\)$as_nl"; - arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; - esac; - expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" - ' - export as_echo_n_body - as_echo_n='sh -c $as_echo_n_body as_echo' - fi - export as_echo_body - as_echo='sh -c $as_echo_body as_echo' -fi - -# The user is always right. -if test "${PATH_SEPARATOR+set}" != set; then - PATH_SEPARATOR=: - (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { - (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || - PATH_SEPARATOR=';' - } -fi - - -# IFS -# We need space, tab and new line, in precisely that order. Quoting is -# there to prevent editors from complaining about space-tab. -# (If _AS_PATH_WALK were called with IFS unset, it would disable word -# splitting by setting IFS to empty value.) -IFS=" "" $as_nl" - -# Find who we are. Look in the path if we contain no directory separator. -as_myself= -case $0 in #(( - *[\\/]* ) as_myself=$0 ;; - *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break - done -IFS=$as_save_IFS - - ;; -esac -# We did not find ourselves, most probably we were run as `sh COMMAND' -# in which case we are not to be found in the path. -if test "x$as_myself" = x; then - as_myself=$0 -fi -if test ! -f "$as_myself"; then - $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 - exit 1 -fi - -# Unset variables that we do not need and which cause bugs (e.g. in -# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" -# suppresses any "Segmentation fault" message there. '((' could -# trigger a bug in pdksh 5.2.14. -for as_var in BASH_ENV ENV MAIL MAILPATH -do eval test x\${$as_var+set} = xset \ - && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : -done -PS1='$ ' -PS2='> ' -PS4='+ ' - -# NLS nuisances. -LC_ALL=C -export LC_ALL -LANGUAGE=C -export LANGUAGE - -# CDPATH. -(unset CDPATH) >/dev/null 2>&1 && unset CDPATH - -# Use a proper internal environment variable to ensure we don't fall - # into an infinite loop, continuously re-executing ourselves. - if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then - _as_can_reexec=no; export _as_can_reexec; - # We cannot yet assume a decent shell, so we have to provide a -# neutralization value for shells without unset; and this also -# works around shells that cannot unset nonexistent variables. -# Preserve -v and -x to the replacement shell. -BASH_ENV=/dev/null -ENV=/dev/null -(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV -case $- in # (((( - *v*x* | *x*v* ) as_opts=-vx ;; - *v* ) as_opts=-v ;; - *x* ) as_opts=-x ;; - * ) as_opts= ;; -esac -exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} -# Admittedly, this is quite paranoid, since all the known shells bail -# out after a failed `exec'. -$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 -as_fn_exit 255 - fi - # We don't want this to propagate to other subprocesses. - { _as_can_reexec=; unset _as_can_reexec;} -if test "x$CONFIG_SHELL" = x; then - as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then : - emulate sh - NULLCMD=: - # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which - # is contrary to our usage. Disable this feature. - alias -g '\${1+\"\$@\"}'='\"\$@\"' - setopt NO_GLOB_SUBST -else - case \`(set -o) 2>/dev/null\` in #( - *posix*) : - set -o posix ;; #( - *) : - ;; -esac -fi -" - as_required="as_fn_return () { (exit \$1); } -as_fn_success () { as_fn_return 0; } -as_fn_failure () { as_fn_return 1; } -as_fn_ret_success () { return 0; } -as_fn_ret_failure () { return 1; } - -exitcode=0 -as_fn_success || { exitcode=1; echo as_fn_success failed.; } -as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } -as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } -as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } -if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then : - -else - exitcode=1; echo positional parameters were not saved. -fi -test x\$exitcode = x0 || exit 1 -test -x / || exit 1" - as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO - as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO - eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && - test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1 -test \$(( 1 + 1 )) = 2 || exit 1" - if (eval "$as_required") 2>/dev/null; then : - as_have_required=yes -else - as_have_required=no -fi - if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then : - -else - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -as_found=false -for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - as_found=: - case $as_dir in #( - /*) - for as_base in sh bash ksh sh5; do - # Try only shells that exist, to save several forks. - as_shell=$as_dir/$as_base - if { test -f "$as_shell" || test -f "$as_shell.exe"; } && - { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then : - CONFIG_SHELL=$as_shell as_have_required=yes - if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then : - break 2 -fi -fi - done;; - esac - as_found=false -done -$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } && - { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then : - CONFIG_SHELL=$SHELL as_have_required=yes -fi; } -IFS=$as_save_IFS - - - if test "x$CONFIG_SHELL" != x; then : - export CONFIG_SHELL - # We cannot yet assume a decent shell, so we have to provide a -# neutralization value for shells without unset; and this also -# works around shells that cannot unset nonexistent variables. -# Preserve -v and -x to the replacement shell. -BASH_ENV=/dev/null -ENV=/dev/null -(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV -case $- in # (((( - *v*x* | *x*v* ) as_opts=-vx ;; - *v* ) as_opts=-v ;; - *x* ) as_opts=-x ;; - * ) as_opts= ;; -esac -exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} -# Admittedly, this is quite paranoid, since all the known shells bail -# out after a failed `exec'. -$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 -exit 255 -fi - - if test x$as_have_required = xno; then : - $as_echo "$0: This script requires a shell more modern than all" - $as_echo "$0: the shells that I found on your system." - if test x${ZSH_VERSION+set} = xset ; then - $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should" - $as_echo "$0: be upgraded to zsh 4.3.4 or later." - else - $as_echo "$0: Please tell bug-autoconf@gnu.org and -$0: bugs.qbittorrent.org about your system, including any -$0: error possibly output before this message. Then install -$0: a modern shell, or manually run the script under such a -$0: shell if you do have one." - fi - exit 1 -fi -fi -fi -SHELL=${CONFIG_SHELL-/bin/sh} -export SHELL -# Unset more variables known to interfere with behavior of common tools. -CLICOLOR_FORCE= GREP_OPTIONS= -unset CLICOLOR_FORCE GREP_OPTIONS - -## --------------------- ## -## M4sh Shell Functions. ## -## --------------------- ## -# as_fn_unset VAR -# --------------- -# Portably unset VAR. -as_fn_unset () -{ - { eval $1=; unset $1;} -} -as_unset=as_fn_unset - -# as_fn_set_status STATUS -# ----------------------- -# Set $? to STATUS, without forking. -as_fn_set_status () -{ - return $1 -} # as_fn_set_status - -# as_fn_exit STATUS -# ----------------- -# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. -as_fn_exit () -{ - set +e - as_fn_set_status $1 - exit $1 -} # as_fn_exit - -# as_fn_mkdir_p -# ------------- -# Create "$as_dir" as a directory, including parents if necessary. -as_fn_mkdir_p () -{ - - case $as_dir in #( - -*) as_dir=./$as_dir;; - esac - test -d "$as_dir" || eval $as_mkdir_p || { - as_dirs= - while :; do - case $as_dir in #( - *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( - *) as_qdir=$as_dir;; - esac - as_dirs="'$as_qdir' $as_dirs" - as_dir=`$as_dirname -- "$as_dir" || -$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$as_dir" : 'X\(//\)[^/]' \| \ - X"$as_dir" : 'X\(//\)$' \| \ - X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || -$as_echo X"$as_dir" | - sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ - s//\1/ - q - } - /^X\(\/\/\)[^/].*/{ - s//\1/ - q - } - /^X\(\/\/\)$/{ - s//\1/ - q - } - /^X\(\/\).*/{ - s//\1/ - q - } - s/.*/./; q'` - test -d "$as_dir" && break - done - test -z "$as_dirs" || eval "mkdir $as_dirs" - } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" - - -} # as_fn_mkdir_p - -# as_fn_executable_p FILE -# ----------------------- -# Test if FILE is an executable regular file. -as_fn_executable_p () -{ - test -f "$1" && test -x "$1" -} # as_fn_executable_p -# as_fn_append VAR VALUE -# ---------------------- -# Append the text in VALUE to the end of the definition contained in VAR. Take -# advantage of any shell optimizations that allow amortized linear growth over -# repeated appends, instead of the typical quadratic growth present in naive -# implementations. -if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : - eval 'as_fn_append () - { - eval $1+=\$2 - }' -else - as_fn_append () - { - eval $1=\$$1\$2 - } -fi # as_fn_append - -# as_fn_arith ARG... -# ------------------ -# Perform arithmetic evaluation on the ARGs, and store the result in the -# global $as_val. Take advantage of shells that can avoid forks. The arguments -# must be portable across $(()) and expr. -if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : - eval 'as_fn_arith () - { - as_val=$(( $* )) - }' -else - as_fn_arith () - { - as_val=`expr "$@" || test $? -eq 1` - } -fi # as_fn_arith - - -# as_fn_error STATUS ERROR [LINENO LOG_FD] -# ---------------------------------------- -# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are -# provided, also output the error to LOG_FD, referencing LINENO. Then exit the -# script with STATUS, using 1 if that was 0. -as_fn_error () -{ - as_status=$1; test $as_status -eq 0 && as_status=1 - if test "$4"; then - as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 - fi - $as_echo "$as_me: error: $2" >&2 - as_fn_exit $as_status -} # as_fn_error - -if expr a : '\(a\)' >/dev/null 2>&1 && - test "X`expr 00001 : '.*\(...\)'`" = X001; then - as_expr=expr -else - as_expr=false -fi - -if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then - as_basename=basename -else - as_basename=false -fi - -if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then - as_dirname=dirname -else - as_dirname=false -fi - -as_me=`$as_basename -- "$0" || -$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ - X"$0" : 'X\(//\)$' \| \ - X"$0" : 'X\(/\)' \| . 2>/dev/null || -$as_echo X/"$0" | - sed '/^.*\/\([^/][^/]*\)\/*$/{ - s//\1/ - q - } - /^X\/\(\/\/\)$/{ - s//\1/ - q - } - /^X\/\(\/\).*/{ - s//\1/ - q - } - s/.*/./; q'` - -# Avoid depending upon Character Ranges. -as_cr_letters='abcdefghijklmnopqrstuvwxyz' -as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' -as_cr_Letters=$as_cr_letters$as_cr_LETTERS -as_cr_digits='0123456789' -as_cr_alnum=$as_cr_Letters$as_cr_digits - - - as_lineno_1=$LINENO as_lineno_1a=$LINENO - as_lineno_2=$LINENO as_lineno_2a=$LINENO - eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && - test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { - # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) - sed -n ' - p - /[$]LINENO/= - ' <$as_myself | - sed ' - s/[$]LINENO.*/&-/ - t lineno - b - :lineno - N - :loop - s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ - t loop - s/-\n.*// - ' >$as_me.lineno && - chmod +x "$as_me.lineno" || - { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } - - # If we had to re-execute with $CONFIG_SHELL, we're ensured to have - # already done that, so ensure we don't try to do so again and fall - # in an infinite loop. This has already happened in practice. - _as_can_reexec=no; export _as_can_reexec - # Don't try to exec as it changes $[0], causing all sort of problems - # (the dirname of $[0] is not the place where we might find the - # original and so on. Autoconf is especially sensitive to this). - . "./$as_me.lineno" - # Exit status is that of the last command. - exit -} - -ECHO_C= ECHO_N= ECHO_T= -case `echo -n x` in #((((( --n*) - case `echo 'xy\c'` in - *c*) ECHO_T=' ';; # ECHO_T is single tab character. - xy) ECHO_C='\c';; - *) echo `echo ksh88 bug on AIX 6.1` > /dev/null - ECHO_T=' ';; - esac;; -*) - ECHO_N='-n';; -esac - -rm -f conf$$ conf$$.exe conf$$.file -if test -d conf$$.dir; then - rm -f conf$$.dir/conf$$.file -else - rm -f conf$$.dir - mkdir conf$$.dir 2>/dev/null -fi -if (echo >conf$$.file) 2>/dev/null; then - if ln -s conf$$.file conf$$ 2>/dev/null; then - as_ln_s='ln -s' - # ... but there are two gotchas: - # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. - # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. - # In both cases, we have to default to `cp -pR'. - ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || - as_ln_s='cp -pR' - elif ln conf$$.file conf$$ 2>/dev/null; then - as_ln_s=ln - else - as_ln_s='cp -pR' - fi -else - as_ln_s='cp -pR' -fi -rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file -rmdir conf$$.dir 2>/dev/null - -if mkdir -p . 2>/dev/null; then - as_mkdir_p='mkdir -p "$as_dir"' -else - test -d ./-p && rmdir ./-p - as_mkdir_p=false -fi - -as_test_x='test -x' -as_executable_p=as_fn_executable_p - -# Sed expression to map a string onto a valid CPP name. -as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" - -# Sed expression to map a string onto a valid variable name. -as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" - - -test -n "$DJDIR" || exec 7<&0 &1 - -# Name of the host. -# hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status, -# so uname gets run too. -ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` - -# -# Initializations. -# -ac_default_prefix=/usr/local -ac_clean_files= -ac_config_libobj_dir=. -LIBOBJS= -cross_compiling=no -subdirs= -MFLAGS= -MAKEFLAGS= - -# Identity of this package. -PACKAGE_NAME='qbittorrent' -PACKAGE_TARNAME='qbittorrent' -PACKAGE_VERSION='v3.2.0alpha' -PACKAGE_STRING='qbittorrent v3.2.0alpha' -PACKAGE_BUGREPORT='bugs.qbittorrent.org' -PACKAGE_URL='http://www.qbittorrent.org/' - -ac_subst_vars='am__EXEEXT_FALSE -am__EXEEXT_TRUE -LTLIBOBJS -LIBOBJS -QBT_REMOVE_DEFINES -QBT_ADD_DEFINES -QBT_REMOVE_CONFIG -QBT_ADD_CONFIG -QBT_CONF_EXTRA_CFLAGS -QBT_CONF_INCLUDES -EXPAND_MANDIR -EXPAND_DATADIR -EXPAND_BINDIR -EXPAND_PREFIX -zlib_LIBS -zlib_CFLAGS -libtorrent_LIBS -libtorrent_CFLAGS -BOOST_SYSTEM_LIB -BOOST_LDFLAGS -BOOST_CPPFLAGS -QT_QMAKE -PKG_CONFIG_LIBDIR -PKG_CONFIG_PATH -PKG_CONFIG -AM_BACKSLASH -AM_DEFAULT_VERBOSITY -AM_DEFAULT_V -AM_V -am__fastdepCXX_FALSE -am__fastdepCXX_TRUE -CXXDEPMODE -am__fastdepCC_FALSE -am__fastdepCC_TRUE -CCDEPMODE -am__nodep -AMDEPBACKSLASH -AMDEP_FALSE -AMDEP_TRUE -am__quote -am__include -DEPDIR -am__untar -am__tar -AMTAR -am__leading_dot -SET_MAKE -AWK -mkdir_p -MKDIR_P -INSTALL_STRIP_PROGRAM -STRIP -install_sh -MAKEINFO -AUTOHEADER -AUTOMAKE -AUTOCONF -ACLOCAL -VERSION -PACKAGE -CYGPATH_W -am__isrc -INSTALL_DATA -INSTALL_SCRIPT -INSTALL_PROGRAM -host_os -host_vendor -host_cpu -host -build_os -build_vendor -build_cpu -build -SED -ac_ct_CXX -CXXFLAGS -CXX -OBJEXT -EXEEXT -ac_ct_CC -CPPFLAGS -LDFLAGS -CFLAGS -CC -target_alias -host_alias -build_alias -LIBS -ECHO_T -ECHO_N -ECHO_C -DEFS -mandir -localedir -libdir -psdir -pdfdir -dvidir -htmldir -infodir -docdir -oldincludedir -includedir -localstatedir -sharedstatedir -sysconfdir -datadir -datarootdir -libexecdir -sbindir -bindir -program_transform_name -prefix -exec_prefix -PACKAGE_URL -PACKAGE_BUGREPORT -PACKAGE_STRING -PACKAGE_VERSION -PACKAGE_TARNAME -PACKAGE_NAME -PATH_SEPARATOR -SHELL' -ac_subst_files='' -ac_user_opts=' -enable_option_checking -enable_dependency_tracking -enable_silent_rules -with_qtsingleapplication -enable_debug -enable_gui -enable_systemd -enable_webui -enable_qt_dbus -with_boost -with_boost_libdir -with_boost_system -' - ac_precious_vars='build_alias -host_alias -target_alias -CC -CFLAGS -LDFLAGS -LIBS -CPPFLAGS -CXX -CXXFLAGS -CCC -PKG_CONFIG -PKG_CONFIG_PATH -PKG_CONFIG_LIBDIR -QT_QMAKE -libtorrent_CFLAGS -libtorrent_LIBS -zlib_CFLAGS -zlib_LIBS' - - -# Initialize some variables set by options. -ac_init_help= -ac_init_version=false -ac_unrecognized_opts= -ac_unrecognized_sep= -# The variables have the same names as the options, with -# dashes changed to underlines. -cache_file=/dev/null -exec_prefix=NONE -no_create= -no_recursion= -prefix=NONE -program_prefix=NONE -program_suffix=NONE -program_transform_name=s,x,x, -silent= -site= -srcdir= -verbose= -x_includes=NONE -x_libraries=NONE - -# Installation directory options. -# These are left unexpanded so users can "make install exec_prefix=/foo" -# and all the variables that are supposed to be based on exec_prefix -# by default will actually change. -# Use braces instead of parens because sh, perl, etc. also accept them. -# (The list follows the same order as the GNU Coding Standards.) -bindir='${exec_prefix}/bin' -sbindir='${exec_prefix}/sbin' -libexecdir='${exec_prefix}/libexec' -datarootdir='${prefix}/share' -datadir='${datarootdir}' -sysconfdir='${prefix}/etc' -sharedstatedir='${prefix}/com' -localstatedir='${prefix}/var' -includedir='${prefix}/include' -oldincludedir='/usr/include' -docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' -infodir='${datarootdir}/info' -htmldir='${docdir}' -dvidir='${docdir}' -pdfdir='${docdir}' -psdir='${docdir}' -libdir='${exec_prefix}/lib' -localedir='${datarootdir}/locale' -mandir='${datarootdir}/man' - -ac_prev= -ac_dashdash= -for ac_option -do - # If the previous option needs an argument, assign it. - if test -n "$ac_prev"; then - eval $ac_prev=\$ac_option - ac_prev= - continue - fi - - case $ac_option in - *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; - *=) ac_optarg= ;; - *) ac_optarg=yes ;; - esac - - # Accept the important Cygnus configure options, so we can diagnose typos. - - case $ac_dashdash$ac_option in - --) - ac_dashdash=yes ;; - - -bindir | --bindir | --bindi | --bind | --bin | --bi) - ac_prev=bindir ;; - -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) - bindir=$ac_optarg ;; - - -build | --build | --buil | --bui | --bu) - ac_prev=build_alias ;; - -build=* | --build=* | --buil=* | --bui=* | --bu=*) - build_alias=$ac_optarg ;; - - -cache-file | --cache-file | --cache-fil | --cache-fi \ - | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) - ac_prev=cache_file ;; - -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ - | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) - cache_file=$ac_optarg ;; - - --config-cache | -C) - cache_file=config.cache ;; - - -datadir | --datadir | --datadi | --datad) - ac_prev=datadir ;; - -datadir=* | --datadir=* | --datadi=* | --datad=*) - datadir=$ac_optarg ;; - - -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ - | --dataroo | --dataro | --datar) - ac_prev=datarootdir ;; - -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ - | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) - datarootdir=$ac_optarg ;; - - -disable-* | --disable-*) - ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` - # Reject names that are not valid shell variable names. - expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && - as_fn_error $? "invalid feature name: $ac_useropt" - ac_useropt_orig=$ac_useropt - ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` - case $ac_user_opts in - *" -"enable_$ac_useropt" -"*) ;; - *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" - ac_unrecognized_sep=', ';; - esac - eval enable_$ac_useropt=no ;; - - -docdir | --docdir | --docdi | --doc | --do) - ac_prev=docdir ;; - -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) - docdir=$ac_optarg ;; - - -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) - ac_prev=dvidir ;; - -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) - dvidir=$ac_optarg ;; - - -enable-* | --enable-*) - ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` - # Reject names that are not valid shell variable names. - expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && - as_fn_error $? "invalid feature name: $ac_useropt" - ac_useropt_orig=$ac_useropt - ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` - case $ac_user_opts in - *" -"enable_$ac_useropt" -"*) ;; - *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" - ac_unrecognized_sep=', ';; - esac - eval enable_$ac_useropt=\$ac_optarg ;; - - -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ - | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ - | --exec | --exe | --ex) - ac_prev=exec_prefix ;; - -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ - | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ - | --exec=* | --exe=* | --ex=*) - exec_prefix=$ac_optarg ;; - - -gas | --gas | --ga | --g) - # Obsolete; use --with-gas. - with_gas=yes ;; - - -help | --help | --hel | --he | -h) - ac_init_help=long ;; - -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) - ac_init_help=recursive ;; - -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) - ac_init_help=short ;; - - -host | --host | --hos | --ho) - ac_prev=host_alias ;; - -host=* | --host=* | --hos=* | --ho=*) - host_alias=$ac_optarg ;; - - -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) - ac_prev=htmldir ;; - -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ - | --ht=*) - htmldir=$ac_optarg ;; - - -includedir | --includedir | --includedi | --included | --include \ - | --includ | --inclu | --incl | --inc) - ac_prev=includedir ;; - -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ - | --includ=* | --inclu=* | --incl=* | --inc=*) - includedir=$ac_optarg ;; - - -infodir | --infodir | --infodi | --infod | --info | --inf) - ac_prev=infodir ;; - -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) - infodir=$ac_optarg ;; - - -libdir | --libdir | --libdi | --libd) - ac_prev=libdir ;; - -libdir=* | --libdir=* | --libdi=* | --libd=*) - libdir=$ac_optarg ;; - - -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ - | --libexe | --libex | --libe) - ac_prev=libexecdir ;; - -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ - | --libexe=* | --libex=* | --libe=*) - libexecdir=$ac_optarg ;; - - -localedir | --localedir | --localedi | --localed | --locale) - ac_prev=localedir ;; - -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) - localedir=$ac_optarg ;; - - -localstatedir | --localstatedir | --localstatedi | --localstated \ - | --localstate | --localstat | --localsta | --localst | --locals) - ac_prev=localstatedir ;; - -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ - | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) - localstatedir=$ac_optarg ;; - - -mandir | --mandir | --mandi | --mand | --man | --ma | --m) - ac_prev=mandir ;; - -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) - mandir=$ac_optarg ;; - - -nfp | --nfp | --nf) - # Obsolete; use --without-fp. - with_fp=no ;; - - -no-create | --no-create | --no-creat | --no-crea | --no-cre \ - | --no-cr | --no-c | -n) - no_create=yes ;; - - -no-recursion | --no-recursion | --no-recursio | --no-recursi \ - | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) - no_recursion=yes ;; - - -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ - | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ - | --oldin | --oldi | --old | --ol | --o) - ac_prev=oldincludedir ;; - -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ - | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ - | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) - oldincludedir=$ac_optarg ;; - - -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) - ac_prev=prefix ;; - -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) - prefix=$ac_optarg ;; - - -program-prefix | --program-prefix | --program-prefi | --program-pref \ - | --program-pre | --program-pr | --program-p) - ac_prev=program_prefix ;; - -program-prefix=* | --program-prefix=* | --program-prefi=* \ - | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) - program_prefix=$ac_optarg ;; - - -program-suffix | --program-suffix | --program-suffi | --program-suff \ - | --program-suf | --program-su | --program-s) - ac_prev=program_suffix ;; - -program-suffix=* | --program-suffix=* | --program-suffi=* \ - | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) - program_suffix=$ac_optarg ;; - - -program-transform-name | --program-transform-name \ - | --program-transform-nam | --program-transform-na \ - | --program-transform-n | --program-transform- \ - | --program-transform | --program-transfor \ - | --program-transfo | --program-transf \ - | --program-trans | --program-tran \ - | --progr-tra | --program-tr | --program-t) - ac_prev=program_transform_name ;; - -program-transform-name=* | --program-transform-name=* \ - | --program-transform-nam=* | --program-transform-na=* \ - | --program-transform-n=* | --program-transform-=* \ - | --program-transform=* | --program-transfor=* \ - | --program-transfo=* | --program-transf=* \ - | --program-trans=* | --program-tran=* \ - | --progr-tra=* | --program-tr=* | --program-t=*) - program_transform_name=$ac_optarg ;; - - -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) - ac_prev=pdfdir ;; - -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) - pdfdir=$ac_optarg ;; - - -psdir | --psdir | --psdi | --psd | --ps) - ac_prev=psdir ;; - -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) - psdir=$ac_optarg ;; - - -q | -quiet | --quiet | --quie | --qui | --qu | --q \ - | -silent | --silent | --silen | --sile | --sil) - silent=yes ;; - - -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) - ac_prev=sbindir ;; - -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ - | --sbi=* | --sb=*) - sbindir=$ac_optarg ;; - - -sharedstatedir | --sharedstatedir | --sharedstatedi \ - | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ - | --sharedst | --shareds | --shared | --share | --shar \ - | --sha | --sh) - ac_prev=sharedstatedir ;; - -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ - | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ - | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ - | --sha=* | --sh=*) - sharedstatedir=$ac_optarg ;; - - -site | --site | --sit) - ac_prev=site ;; - -site=* | --site=* | --sit=*) - site=$ac_optarg ;; - - -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) - ac_prev=srcdir ;; - -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) - srcdir=$ac_optarg ;; - - -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ - | --syscon | --sysco | --sysc | --sys | --sy) - ac_prev=sysconfdir ;; - -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ - | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) - sysconfdir=$ac_optarg ;; - - -target | --target | --targe | --targ | --tar | --ta | --t) - ac_prev=target_alias ;; - -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) - target_alias=$ac_optarg ;; - - -v | -verbose | --verbose | --verbos | --verbo | --verb) - verbose=yes ;; - - -version | --version | --versio | --versi | --vers | -V) - ac_init_version=: ;; - - -with-* | --with-*) - ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` - # Reject names that are not valid shell variable names. - expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && - as_fn_error $? "invalid package name: $ac_useropt" - ac_useropt_orig=$ac_useropt - ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` - case $ac_user_opts in - *" -"with_$ac_useropt" -"*) ;; - *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" - ac_unrecognized_sep=', ';; - esac - eval with_$ac_useropt=\$ac_optarg ;; - - -without-* | --without-*) - ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` - # Reject names that are not valid shell variable names. - expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && - as_fn_error $? "invalid package name: $ac_useropt" - ac_useropt_orig=$ac_useropt - ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` - case $ac_user_opts in - *" -"with_$ac_useropt" -"*) ;; - *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" - ac_unrecognized_sep=', ';; - esac - eval with_$ac_useropt=no ;; - - --x) - # Obsolete; use --with-x. - with_x=yes ;; - - -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ - | --x-incl | --x-inc | --x-in | --x-i) - ac_prev=x_includes ;; - -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ - | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) - x_includes=$ac_optarg ;; - - -x-libraries | --x-libraries | --x-librarie | --x-librari \ - | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) - ac_prev=x_libraries ;; - -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ - | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) - x_libraries=$ac_optarg ;; - - -*) as_fn_error $? "unrecognized option: \`$ac_option' -Try \`$0 --help' for more information" - ;; - - *=*) - ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` - # Reject names that are not valid shell variable names. - case $ac_envvar in #( - '' | [0-9]* | *[!_$as_cr_alnum]* ) - as_fn_error $? "invalid variable name: \`$ac_envvar'" ;; - esac - eval $ac_envvar=\$ac_optarg - export $ac_envvar ;; - - *) - # FIXME: should be removed in autoconf 3.0. - $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 - expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && - $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2 - : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}" - ;; - - esac -done - -if test -n "$ac_prev"; then - ac_option=--`echo $ac_prev | sed 's/_/-/g'` - as_fn_error $? "missing argument to $ac_option" -fi - -if test -n "$ac_unrecognized_opts"; then - case $enable_option_checking in - no) ;; - fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;; - *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; - esac -fi - -# Check all directory arguments for consistency. -for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ - datadir sysconfdir sharedstatedir localstatedir includedir \ - oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ - libdir localedir mandir -do - eval ac_val=\$$ac_var - # Remove trailing slashes. - case $ac_val in - */ ) - ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` - eval $ac_var=\$ac_val;; - esac - # Be sure to have absolute directory names. - case $ac_val in - [\\/$]* | ?:[\\/]* ) continue;; - NONE | '' ) case $ac_var in *prefix ) continue;; esac;; - esac - as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val" -done - -# There might be people who depend on the old broken behavior: `$host' -# used to hold the argument of --host etc. -# FIXME: To remove some day. -build=$build_alias -host=$host_alias -target=$target_alias - -# FIXME: To remove some day. -if test "x$host_alias" != x; then - if test "x$build_alias" = x; then - cross_compiling=maybe - elif test "x$build_alias" != "x$host_alias"; then - cross_compiling=yes - fi -fi - -ac_tool_prefix= -test -n "$host_alias" && ac_tool_prefix=$host_alias- - -test "$silent" = yes && exec 6>/dev/null - - -ac_pwd=`pwd` && test -n "$ac_pwd" && -ac_ls_di=`ls -di .` && -ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || - as_fn_error $? "working directory cannot be determined" -test "X$ac_ls_di" = "X$ac_pwd_ls_di" || - as_fn_error $? "pwd does not report name of working directory" - - -# Find the source files, if location was not specified. -if test -z "$srcdir"; then - ac_srcdir_defaulted=yes - # Try the directory containing this script, then the parent directory. - ac_confdir=`$as_dirname -- "$as_myself" || -$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$as_myself" : 'X\(//\)[^/]' \| \ - X"$as_myself" : 'X\(//\)$' \| \ - X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || -$as_echo X"$as_myself" | - sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ - s//\1/ - q - } - /^X\(\/\/\)[^/].*/{ - s//\1/ - q - } - /^X\(\/\/\)$/{ - s//\1/ - q - } - /^X\(\/\).*/{ - s//\1/ - q - } - s/.*/./; q'` - srcdir=$ac_confdir - if test ! -r "$srcdir/$ac_unique_file"; then - srcdir=.. - fi -else - ac_srcdir_defaulted=no -fi -if test ! -r "$srcdir/$ac_unique_file"; then - test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." - as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir" -fi -ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" -ac_abs_confdir=`( - cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg" - pwd)` -# When building in place, set srcdir=. -if test "$ac_abs_confdir" = "$ac_pwd"; then - srcdir=. -fi -# Remove unnecessary trailing slashes from srcdir. -# Double slashes in file names in object file debugging info -# mess up M-x gdb in Emacs. -case $srcdir in -*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; -esac -for ac_var in $ac_precious_vars; do - eval ac_env_${ac_var}_set=\${${ac_var}+set} - eval ac_env_${ac_var}_value=\$${ac_var} - eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} - eval ac_cv_env_${ac_var}_value=\$${ac_var} -done - -# -# Report the --help message. -# -if test "$ac_init_help" = "long"; then - # Omit some internal or obsolete options to make the list less imposing. - # This message is too long to be a string in the A/UX 3.1 sh. - cat <<_ACEOF -\`configure' configures qbittorrent v3.2.0alpha to adapt to many kinds of systems. - -Usage: $0 [OPTION]... [VAR=VALUE]... - -To assign environment variables (e.g., CC, CFLAGS...), specify them as -VAR=VALUE. See below for descriptions of some of the useful variables. - -Defaults for the options are specified in brackets. - -Configuration: - -h, --help display this help and exit - --help=short display options specific to this package - --help=recursive display the short help of all the included packages - -V, --version display version information and exit - -q, --quiet, --silent do not print \`checking ...' messages - --cache-file=FILE cache test results in FILE [disabled] - -C, --config-cache alias for \`--cache-file=config.cache' - -n, --no-create do not create output files - --srcdir=DIR find the sources in DIR [configure dir or \`..'] - -Installation directories: - --prefix=PREFIX install architecture-independent files in PREFIX - [$ac_default_prefix] - --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX - [PREFIX] - -By default, \`make install' will install all the files in -\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify -an installation prefix other than \`$ac_default_prefix' using \`--prefix', -for instance \`--prefix=\$HOME'. - -For better control, use the options below. - -Fine tuning of the installation directories: - --bindir=DIR user executables [EPREFIX/bin] - --sbindir=DIR system admin executables [EPREFIX/sbin] - --libexecdir=DIR program executables [EPREFIX/libexec] - --sysconfdir=DIR read-only single-machine data [PREFIX/etc] - --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] - --localstatedir=DIR modifiable single-machine data [PREFIX/var] - --libdir=DIR object code libraries [EPREFIX/lib] - --includedir=DIR C header files [PREFIX/include] - --oldincludedir=DIR C header files for non-gcc [/usr/include] - --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] - --datadir=DIR read-only architecture-independent data [DATAROOTDIR] - --infodir=DIR info documentation [DATAROOTDIR/info] - --localedir=DIR locale-dependent data [DATAROOTDIR/locale] - --mandir=DIR man documentation [DATAROOTDIR/man] - --docdir=DIR documentation root [DATAROOTDIR/doc/qbittorrent] - --htmldir=DIR html documentation [DOCDIR] - --dvidir=DIR dvi documentation [DOCDIR] - --pdfdir=DIR pdf documentation [DOCDIR] - --psdir=DIR ps documentation [DOCDIR] -_ACEOF - - cat <<\_ACEOF - -Program names: - --program-prefix=PREFIX prepend PREFIX to installed program names - --program-suffix=SUFFIX append SUFFIX to installed program names - --program-transform-name=PROGRAM run sed PROGRAM on installed program names - -System types: - --build=BUILD configure for building on BUILD [guessed] - --host=HOST cross-compile to build programs to run on HOST [BUILD] -_ACEOF -fi - -if test -n "$ac_init_help"; then - case $ac_init_help in - short | recursive ) echo "Configuration of qbittorrent v3.2.0alpha:";; - esac - cat <<\_ACEOF - -Optional Features: - --disable-option-checking ignore unrecognized --enable/--with options - --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) - --enable-FEATURE[=ARG] include FEATURE [ARG=yes] - --enable-dependency-tracking - do not reject slow dependency extractors - --disable-dependency-tracking - speeds up one-time build - --enable-silent-rules less verbose build output (undo: "make V=1") - --disable-silent-rules verbose build output (undo: "make V=0") - --enable-debug Enable debug build - --disable-gui Disable the GUI for headless running. Disables - QtDBus and the GeoIP Database. - --enable-systemd Install the systemd service file (headless only). - --disable-webui Disable the WebUI. - --disable-qt-dbus Disable use of QtDBus (GUI only) - -Optional Packages: - --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] - --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) - --with-qtsingleapplication=[system|shipped] - Use the shipped qtsingleapplication library or the - system one (default=shipped) - --with-boost[=ARG] use Boost library from a standard location - (ARG=yes), from the specified location (ARG=), - or disable it (ARG=no) [ARG=yes] - --with-boost-libdir=LIB_DIR - Force given directory for boost libraries. Note that - this will override library path detection, so use - this parameter only if default library detection - fails and you know exactly where your boost - libraries are located. - --with-boost-system[=special-lib] - use the System library from boost - it is possible - to specify a certain library for the linker e.g. - --with-boost-system=boost_system-gcc-mt - -Some influential environment variables: - CC C compiler command - CFLAGS C compiler flags - LDFLAGS linker flags, e.g. -L if you have libraries in a - nonstandard directory - LIBS libraries to pass to the linker, e.g. -l - CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I if - you have headers in a nonstandard directory - CXX C++ compiler command - CXXFLAGS C++ compiler flags - PKG_CONFIG path to pkg-config utility - PKG_CONFIG_PATH - directories to add to pkg-config's search path - PKG_CONFIG_LIBDIR - path overriding pkg-config's built-in search path - QT_QMAKE value of host_bins for Qt5Core >= 5.5.1, overriding pkg-config - libtorrent_CFLAGS - C compiler flags for libtorrent, overriding pkg-config - libtorrent_LIBS - linker flags for libtorrent, overriding pkg-config - zlib_CFLAGS C compiler flags for zlib, overriding pkg-config - zlib_LIBS linker flags for zlib, overriding pkg-config - -Use these variables to override the choices made by `configure' or to help -it to find libraries and programs with nonstandard names/locations. - -Report bugs to . -qbittorrent home page: . -_ACEOF -ac_status=$? -fi - -if test "$ac_init_help" = "recursive"; then - # If there are subdirs, report their specific --help. - for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue - test -d "$ac_dir" || - { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || - continue - ac_builddir=. - -case "$ac_dir" in -.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; -*) - ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` - # A ".." for each directory in $ac_dir_suffix. - ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` - case $ac_top_builddir_sub in - "") ac_top_builddir_sub=. ac_top_build_prefix= ;; - *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; - esac ;; -esac -ac_abs_top_builddir=$ac_pwd -ac_abs_builddir=$ac_pwd$ac_dir_suffix -# for backward compatibility: -ac_top_builddir=$ac_top_build_prefix - -case $srcdir in - .) # We are building in place. - ac_srcdir=. - ac_top_srcdir=$ac_top_builddir_sub - ac_abs_top_srcdir=$ac_pwd ;; - [\\/]* | ?:[\\/]* ) # Absolute name. - ac_srcdir=$srcdir$ac_dir_suffix; - ac_top_srcdir=$srcdir - ac_abs_top_srcdir=$srcdir ;; - *) # Relative name. - ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix - ac_top_srcdir=$ac_top_build_prefix$srcdir - ac_abs_top_srcdir=$ac_pwd/$srcdir ;; -esac -ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix - - cd "$ac_dir" || { ac_status=$?; continue; } - # Check for guested configure. - if test -f "$ac_srcdir/configure.gnu"; then - echo && - $SHELL "$ac_srcdir/configure.gnu" --help=recursive - elif test -f "$ac_srcdir/configure"; then - echo && - $SHELL "$ac_srcdir/configure" --help=recursive - else - $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 - fi || ac_status=$? - cd "$ac_pwd" || { ac_status=$?; break; } - done -fi - -test -n "$ac_init_help" && exit $ac_status -if $ac_init_version; then - cat <<\_ACEOF -qbittorrent configure v3.2.0alpha -generated by GNU Autoconf 2.69 - -Copyright (C) 2012 Free Software Foundation, Inc. -This configure script is free software; the Free Software Foundation -gives unlimited permission to copy, distribute and modify it. -_ACEOF - exit -fi - -## ------------------------ ## -## Autoconf initialization. ## -## ------------------------ ## - -# ac_fn_c_try_compile LINENO -# -------------------------- -# Try to compile conftest.$ac_ext, and return whether this succeeded. -ac_fn_c_try_compile () -{ - as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - rm -f conftest.$ac_objext - if { { ac_try="$ac_compile" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 - (eval "$ac_compile") 2>conftest.err - ac_status=$? - if test -s conftest.err; then - grep -v '^ *+' conftest.err >conftest.er1 - cat conftest.er1 >&5 - mv -f conftest.er1 conftest.err - fi - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } && { - test -z "$ac_c_werror_flag" || - test ! -s conftest.err - } && test -s conftest.$ac_objext; then : - ac_retval=0 -else - $as_echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_retval=1 -fi - eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno - as_fn_set_status $ac_retval - -} # ac_fn_c_try_compile - -# ac_fn_cxx_try_compile LINENO -# ---------------------------- -# Try to compile conftest.$ac_ext, and return whether this succeeded. -ac_fn_cxx_try_compile () -{ - as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - rm -f conftest.$ac_objext - if { { ac_try="$ac_compile" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 - (eval "$ac_compile") 2>conftest.err - ac_status=$? - if test -s conftest.err; then - grep -v '^ *+' conftest.err >conftest.er1 - cat conftest.er1 >&5 - mv -f conftest.er1 conftest.err - fi - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } && { - test -z "$ac_cxx_werror_flag" || - test ! -s conftest.err - } && test -s conftest.$ac_objext; then : - ac_retval=0 -else - $as_echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_retval=1 -fi - eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno - as_fn_set_status $ac_retval - -} # ac_fn_cxx_try_compile - -# ac_fn_cxx_try_link LINENO -# ------------------------- -# Try to link conftest.$ac_ext, and return whether this succeeded. -ac_fn_cxx_try_link () -{ - as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - rm -f conftest.$ac_objext conftest$ac_exeext - if { { ac_try="$ac_link" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 - (eval "$ac_link") 2>conftest.err - ac_status=$? - if test -s conftest.err; then - grep -v '^ *+' conftest.err >conftest.er1 - cat conftest.er1 >&5 - mv -f conftest.er1 conftest.err - fi - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } && { - test -z "$ac_cxx_werror_flag" || - test ! -s conftest.err - } && test -s conftest$ac_exeext && { - test "$cross_compiling" = yes || - test -x conftest$ac_exeext - }; then : - ac_retval=0 -else - $as_echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_retval=1 -fi - # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information - # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would - # interfere with the next link command; also delete a directory that is - # left behind by Apple's compiler. We do this before executing the actions. - rm -rf conftest.dSYM conftest_ipa8_conftest.oo - eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno - as_fn_set_status $ac_retval - -} # ac_fn_cxx_try_link -cat >config.log <<_ACEOF -This file contains any messages produced by compilers while -running configure, to aid debugging if configure makes a mistake. - -It was created by qbittorrent $as_me v3.2.0alpha, which was -generated by GNU Autoconf 2.69. Invocation command line was - - $ $0 $@ - -_ACEOF -exec 5>>config.log -{ -cat <<_ASUNAME -## --------- ## -## Platform. ## -## --------- ## - -hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` -uname -m = `(uname -m) 2>/dev/null || echo unknown` -uname -r = `(uname -r) 2>/dev/null || echo unknown` -uname -s = `(uname -s) 2>/dev/null || echo unknown` -uname -v = `(uname -v) 2>/dev/null || echo unknown` - -/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` -/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` - -/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` -/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` -/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` -/usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` -/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` -/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` -/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` - -_ASUNAME - -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - $as_echo "PATH: $as_dir" - done -IFS=$as_save_IFS - -} >&5 - -cat >&5 <<_ACEOF - - -## ----------- ## -## Core tests. ## -## ----------- ## - -_ACEOF - - -# Keep a trace of the command line. -# Strip out --no-create and --no-recursion so they do not pile up. -# Strip out --silent because we don't want to record it for future runs. -# Also quote any args containing shell meta-characters. -# Make two passes to allow for proper duplicate-argument suppression. -ac_configure_args= -ac_configure_args0= -ac_configure_args1= -ac_must_keep_next=false -for ac_pass in 1 2 -do - for ac_arg - do - case $ac_arg in - -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; - -q | -quiet | --quiet | --quie | --qui | --qu | --q \ - | -silent | --silent | --silen | --sile | --sil) - continue ;; - *\'*) - ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; - esac - case $ac_pass in - 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; - 2) - as_fn_append ac_configure_args1 " '$ac_arg'" - if test $ac_must_keep_next = true; then - ac_must_keep_next=false # Got value, back to normal. - else - case $ac_arg in - *=* | --config-cache | -C | -disable-* | --disable-* \ - | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ - | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ - | -with-* | --with-* | -without-* | --without-* | --x) - case "$ac_configure_args0 " in - "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; - esac - ;; - -* ) ac_must_keep_next=true ;; - esac - fi - as_fn_append ac_configure_args " '$ac_arg'" - ;; - esac - done -done -{ ac_configure_args0=; unset ac_configure_args0;} -{ ac_configure_args1=; unset ac_configure_args1;} - -# When interrupted or exit'd, cleanup temporary files, and complete -# config.log. We remove comments because anyway the quotes in there -# would cause problems or look ugly. -# WARNING: Use '\'' to represent an apostrophe within the trap. -# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. -trap 'exit_status=$? - # Save into config.log some information that might help in debugging. - { - echo - - $as_echo "## ---------------- ## -## Cache variables. ## -## ---------------- ##" - echo - # The following way of writing the cache mishandles newlines in values, -( - for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do - eval ac_val=\$$ac_var - case $ac_val in #( - *${as_nl}*) - case $ac_var in #( - *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 -$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; - esac - case $ac_var in #( - _ | IFS | as_nl) ;; #( - BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( - *) { eval $ac_var=; unset $ac_var;} ;; - esac ;; - esac - done - (set) 2>&1 | - case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( - *${as_nl}ac_space=\ *) - sed -n \ - "s/'\''/'\''\\\\'\'''\''/g; - s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" - ;; #( - *) - sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" - ;; - esac | - sort -) - echo - - $as_echo "## ----------------- ## -## Output variables. ## -## ----------------- ##" - echo - for ac_var in $ac_subst_vars - do - eval ac_val=\$$ac_var - case $ac_val in - *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; - esac - $as_echo "$ac_var='\''$ac_val'\''" - done | sort - echo - - if test -n "$ac_subst_files"; then - $as_echo "## ------------------- ## -## File substitutions. ## -## ------------------- ##" - echo - for ac_var in $ac_subst_files - do - eval ac_val=\$$ac_var - case $ac_val in - *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; - esac - $as_echo "$ac_var='\''$ac_val'\''" - done | sort - echo - fi - - if test -s confdefs.h; then - $as_echo "## ----------- ## -## confdefs.h. ## -## ----------- ##" - echo - cat confdefs.h - echo - fi - test "$ac_signal" != 0 && - $as_echo "$as_me: caught signal $ac_signal" - $as_echo "$as_me: exit $exit_status" - } >&5 - rm -f core *.core core.conftest.* && - rm -f -r conftest* confdefs* conf$$* $ac_clean_files && - exit $exit_status -' 0 -for ac_signal in 1 2 13 15; do - trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal -done -ac_signal=0 - -# confdefs.h avoids OS command line length limits that DEFS can exceed. -rm -f -r conftest* confdefs.h - -$as_echo "/* confdefs.h */" > confdefs.h - -# Predefined preprocessor variables. - -cat >>confdefs.h <<_ACEOF -#define PACKAGE_NAME "$PACKAGE_NAME" -_ACEOF - -cat >>confdefs.h <<_ACEOF -#define PACKAGE_TARNAME "$PACKAGE_TARNAME" -_ACEOF - -cat >>confdefs.h <<_ACEOF -#define PACKAGE_VERSION "$PACKAGE_VERSION" -_ACEOF - -cat >>confdefs.h <<_ACEOF -#define PACKAGE_STRING "$PACKAGE_STRING" -_ACEOF - -cat >>confdefs.h <<_ACEOF -#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" -_ACEOF - -cat >>confdefs.h <<_ACEOF -#define PACKAGE_URL "$PACKAGE_URL" -_ACEOF - - -# Let the site file select an alternate cache file if it wants to. -# Prefer an explicitly selected file to automatically selected ones. -ac_site_file1=NONE -ac_site_file2=NONE -if test -n "$CONFIG_SITE"; then - # We do not want a PATH search for config.site. - case $CONFIG_SITE in #(( - -*) ac_site_file1=./$CONFIG_SITE;; - */*) ac_site_file1=$CONFIG_SITE;; - *) ac_site_file1=./$CONFIG_SITE;; - esac -elif test "x$prefix" != xNONE; then - ac_site_file1=$prefix/share/config.site - ac_site_file2=$prefix/etc/config.site -else - ac_site_file1=$ac_default_prefix/share/config.site - ac_site_file2=$ac_default_prefix/etc/config.site -fi -for ac_site_file in "$ac_site_file1" "$ac_site_file2" -do - test "x$ac_site_file" = xNONE && continue - if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 -$as_echo "$as_me: loading site script $ac_site_file" >&6;} - sed 's/^/| /' "$ac_site_file" >&5 - . "$ac_site_file" \ - || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 -$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -as_fn_error $? "failed to load site script $ac_site_file -See \`config.log' for more details" "$LINENO" 5; } - fi -done - -if test -r "$cache_file"; then - # Some versions of bash will fail to source /dev/null (special files - # actually), so we avoid doing that. DJGPP emulates it as a regular file. - if test /dev/null != "$cache_file" && test -f "$cache_file"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 -$as_echo "$as_me: loading cache $cache_file" >&6;} - case $cache_file in - [\\/]* | ?:[\\/]* ) . "$cache_file";; - *) . "./$cache_file";; - esac - fi -else - { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 -$as_echo "$as_me: creating cache $cache_file" >&6;} - >$cache_file -fi - -# Check that the precious variables saved in the cache have kept the same -# value. -ac_cache_corrupted=false -for ac_var in $ac_precious_vars; do - eval ac_old_set=\$ac_cv_env_${ac_var}_set - eval ac_new_set=\$ac_env_${ac_var}_set - eval ac_old_val=\$ac_cv_env_${ac_var}_value - eval ac_new_val=\$ac_env_${ac_var}_value - case $ac_old_set,$ac_new_set in - set,) - { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 -$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} - ac_cache_corrupted=: ;; - ,set) - { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 -$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} - ac_cache_corrupted=: ;; - ,);; - *) - if test "x$ac_old_val" != "x$ac_new_val"; then - # differences in whitespace do not lead to failure. - ac_old_val_w=`echo x $ac_old_val` - ac_new_val_w=`echo x $ac_new_val` - if test "$ac_old_val_w" != "$ac_new_val_w"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 -$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} - ac_cache_corrupted=: - else - { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 -$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} - eval $ac_var=\$ac_old_val - fi - { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 -$as_echo "$as_me: former value: \`$ac_old_val'" >&2;} - { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 -$as_echo "$as_me: current value: \`$ac_new_val'" >&2;} - fi;; - esac - # Pass precious variables to config.status. - if test "$ac_new_set" = set; then - case $ac_new_val in - *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; - *) ac_arg=$ac_var=$ac_new_val ;; - esac - case " $ac_configure_args " in - *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. - *) as_fn_append ac_configure_args " '$ac_arg'" ;; - esac - fi -done -if $ac_cache_corrupted; then - { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 -$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} - { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 -$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} - as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 -fi -## -------------------- ## -## Main body of script. ## -## -------------------- ## - -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu - - -ac_aux_dir= -for ac_dir in build-aux "$srcdir"/build-aux; do - if test -f "$ac_dir/install-sh"; then - ac_aux_dir=$ac_dir - ac_install_sh="$ac_aux_dir/install-sh -c" - break - elif test -f "$ac_dir/install.sh"; then - ac_aux_dir=$ac_dir - ac_install_sh="$ac_aux_dir/install.sh -c" - break - elif test -f "$ac_dir/shtool"; then - ac_aux_dir=$ac_dir - ac_install_sh="$ac_aux_dir/shtool install -c" - break - fi -done -if test -z "$ac_aux_dir"; then - as_fn_error $? "cannot find install-sh, install.sh, or shtool in build-aux \"$srcdir\"/build-aux" "$LINENO" 5 -fi - -# These three variables are undocumented and unsupported, -# and are intended to be withdrawn in a future Autoconf release. -# They can cause serious problems if a builder's source tree is in a directory -# whose full name contains unusual characters. -ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var. -ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var. -ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. - - - -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu -if test -n "$ac_tool_prefix"; then - # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. -set dummy ${ac_tool_prefix}gcc; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_CC+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$CC"; then - ac_cv_prog_CC="$CC" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_CC="${ac_tool_prefix}gcc" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -CC=$ac_cv_prog_CC -if test -n "$CC"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 -$as_echo "$CC" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - -fi -if test -z "$ac_cv_prog_CC"; then - ac_ct_CC=$CC - # Extract the first word of "gcc", so it can be a program name with args. -set dummy gcc; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_ac_ct_CC+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$ac_ct_CC"; then - ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_ac_ct_CC="gcc" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -ac_ct_CC=$ac_cv_prog_ac_ct_CC -if test -n "$ac_ct_CC"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 -$as_echo "$ac_ct_CC" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - if test "x$ac_ct_CC" = x; then - CC="" - else - case $cross_compiling:$ac_tool_warned in -yes:) -{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} -ac_tool_warned=yes ;; -esac - CC=$ac_ct_CC - fi -else - CC="$ac_cv_prog_CC" -fi - -if test -z "$CC"; then - if test -n "$ac_tool_prefix"; then - # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. -set dummy ${ac_tool_prefix}cc; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_CC+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$CC"; then - ac_cv_prog_CC="$CC" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_CC="${ac_tool_prefix}cc" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -CC=$ac_cv_prog_CC -if test -n "$CC"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 -$as_echo "$CC" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - - fi -fi -if test -z "$CC"; then - # Extract the first word of "cc", so it can be a program name with args. -set dummy cc; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_CC+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$CC"; then - ac_cv_prog_CC="$CC" # Let the user override the test. -else - ac_prog_rejected=no -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then - ac_prog_rejected=yes - continue - fi - ac_cv_prog_CC="cc" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -if test $ac_prog_rejected = yes; then - # We found a bogon in the path, so make sure we never use it. - set dummy $ac_cv_prog_CC - shift - if test $# != 0; then - # We chose a different compiler from the bogus one. - # However, it has the same basename, so the bogon will be chosen - # first if we set CC to just the basename; use the full file name. - shift - ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" - fi -fi -fi -fi -CC=$ac_cv_prog_CC -if test -n "$CC"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 -$as_echo "$CC" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - -fi -if test -z "$CC"; then - if test -n "$ac_tool_prefix"; then - for ac_prog in cl.exe - do - # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. -set dummy $ac_tool_prefix$ac_prog; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_CC+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$CC"; then - ac_cv_prog_CC="$CC" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_CC="$ac_tool_prefix$ac_prog" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -CC=$ac_cv_prog_CC -if test -n "$CC"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 -$as_echo "$CC" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - - test -n "$CC" && break - done -fi -if test -z "$CC"; then - ac_ct_CC=$CC - for ac_prog in cl.exe -do - # Extract the first word of "$ac_prog", so it can be a program name with args. -set dummy $ac_prog; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_ac_ct_CC+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$ac_ct_CC"; then - ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_ac_ct_CC="$ac_prog" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -ac_ct_CC=$ac_cv_prog_ac_ct_CC -if test -n "$ac_ct_CC"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 -$as_echo "$ac_ct_CC" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - - test -n "$ac_ct_CC" && break -done - - if test "x$ac_ct_CC" = x; then - CC="" - else - case $cross_compiling:$ac_tool_warned in -yes:) -{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} -ac_tool_warned=yes ;; -esac - CC=$ac_ct_CC - fi -fi - -fi - - -test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 -$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -as_fn_error $? "no acceptable C compiler found in \$PATH -See \`config.log' for more details" "$LINENO" 5; } - -# Provide some information about the compiler. -$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 -set X $ac_compile -ac_compiler=$2 -for ac_option in --version -v -V -qversion; do - { { ac_try="$ac_compiler $ac_option >&5" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 - (eval "$ac_compiler $ac_option >&5") 2>conftest.err - ac_status=$? - if test -s conftest.err; then - sed '10a\ -... rest of stderr output deleted ... - 10q' conftest.err >conftest.er1 - cat conftest.er1 >&5 - fi - rm -f conftest.er1 conftest.err - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } -done - -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -ac_clean_files_save=$ac_clean_files -ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out" -# Try to create an executable without -o first, disregard a.out. -# It will help us diagnose broken compilers, and finding out an intuition -# of exeext. -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5 -$as_echo_n "checking whether the C compiler works... " >&6; } -ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` - -# The possible output files: -ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*" - -ac_rmfiles= -for ac_file in $ac_files -do - case $ac_file in - *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; - * ) ac_rmfiles="$ac_rmfiles $ac_file";; - esac -done -rm -f $ac_rmfiles - -if { { ac_try="$ac_link_default" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 - (eval "$ac_link_default") 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; }; then : - # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. -# So ignore a value of `no', otherwise this would lead to `EXEEXT = no' -# in a Makefile. We should not override ac_cv_exeext if it was cached, -# so that the user can short-circuit this test for compilers unknown to -# Autoconf. -for ac_file in $ac_files '' -do - test -f "$ac_file" || continue - case $ac_file in - *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) - ;; - [ab].out ) - # We found the default executable, but exeext='' is most - # certainly right. - break;; - *.* ) - if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; - then :; else - ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` - fi - # We set ac_cv_exeext here because the later test for it is not - # safe: cross compilers may not add the suffix if given an `-o' - # argument, so we may need to know it at that point already. - # Even if this section looks crufty: it has the advantage of - # actually working. - break;; - * ) - break;; - esac -done -test "$ac_cv_exeext" = no && ac_cv_exeext= - -else - ac_file='' -fi -if test -z "$ac_file"; then : - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -$as_echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 -$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -as_fn_error 77 "C compiler cannot create executables -See \`config.log' for more details" "$LINENO" 5; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5 -$as_echo_n "checking for C compiler default output file name... " >&6; } -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 -$as_echo "$ac_file" >&6; } -ac_exeext=$ac_cv_exeext - -rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out -ac_clean_files=$ac_clean_files_save -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 -$as_echo_n "checking for suffix of executables... " >&6; } -if { { ac_try="$ac_link" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 - (eval "$ac_link") 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; }; then : - # If both `conftest.exe' and `conftest' are `present' (well, observable) -# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will -# work properly (i.e., refer to `conftest.exe'), while it won't with -# `rm'. -for ac_file in conftest.exe conftest conftest.*; do - test -f "$ac_file" || continue - case $ac_file in - *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; - *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` - break;; - * ) break;; - esac -done -else - { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 -$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -as_fn_error $? "cannot compute suffix of executables: cannot compile and link -See \`config.log' for more details" "$LINENO" 5; } -fi -rm -f conftest conftest$ac_cv_exeext -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 -$as_echo "$ac_cv_exeext" >&6; } - -rm -f conftest.$ac_ext -EXEEXT=$ac_cv_exeext -ac_exeext=$EXEEXT -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include -int -main () -{ -FILE *f = fopen ("conftest.out", "w"); - return ferror (f) || fclose (f) != 0; - - ; - return 0; -} -_ACEOF -ac_clean_files="$ac_clean_files conftest.out" -# Check that the compiler produces executables we can run. If not, either -# the compiler is broken, or we cross compile. -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 -$as_echo_n "checking whether we are cross compiling... " >&6; } -if test "$cross_compiling" != yes; then - { { ac_try="$ac_link" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 - (eval "$ac_link") 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } - if { ac_try='./conftest$ac_cv_exeext' - { { case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 - (eval "$ac_try") 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; }; }; then - cross_compiling=no - else - if test "$cross_compiling" = maybe; then - cross_compiling=yes - else - { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 -$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -as_fn_error $? "cannot run C compiled programs. -If you meant to cross compile, use \`--host'. -See \`config.log' for more details" "$LINENO" 5; } - fi - fi -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 -$as_echo "$cross_compiling" >&6; } - -rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out -ac_clean_files=$ac_clean_files_save -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 -$as_echo_n "checking for suffix of object files... " >&6; } -if ${ac_cv_objext+:} false; then : - $as_echo_n "(cached) " >&6 -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -rm -f conftest.o conftest.obj -if { { ac_try="$ac_compile" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 - (eval "$ac_compile") 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; }; then : - for ac_file in conftest.o conftest.obj conftest.*; do - test -f "$ac_file" || continue; - case $ac_file in - *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;; - *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` - break;; - esac -done -else - $as_echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 -$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -as_fn_error $? "cannot compute suffix of object files: cannot compile -See \`config.log' for more details" "$LINENO" 5; } -fi -rm -f conftest.$ac_cv_objext conftest.$ac_ext -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 -$as_echo "$ac_cv_objext" >&6; } -OBJEXT=$ac_cv_objext -ac_objext=$OBJEXT -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 -$as_echo_n "checking whether we are using the GNU C compiler... " >&6; } -if ${ac_cv_c_compiler_gnu+:} false; then : - $as_echo_n "(cached) " >&6 -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ -#ifndef __GNUC__ - choke me -#endif - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - ac_compiler_gnu=yes -else - ac_compiler_gnu=no -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -ac_cv_c_compiler_gnu=$ac_compiler_gnu - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 -$as_echo "$ac_cv_c_compiler_gnu" >&6; } -if test $ac_compiler_gnu = yes; then - GCC=yes -else - GCC= -fi -ac_test_CFLAGS=${CFLAGS+set} -ac_save_CFLAGS=$CFLAGS -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 -$as_echo_n "checking whether $CC accepts -g... " >&6; } -if ${ac_cv_prog_cc_g+:} false; then : - $as_echo_n "(cached) " >&6 -else - ac_save_c_werror_flag=$ac_c_werror_flag - ac_c_werror_flag=yes - ac_cv_prog_cc_g=no - CFLAGS="-g" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - ac_cv_prog_cc_g=yes -else - CFLAGS="" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - -else - ac_c_werror_flag=$ac_save_c_werror_flag - CFLAGS="-g" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - ac_cv_prog_cc_g=yes -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - ac_c_werror_flag=$ac_save_c_werror_flag -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 -$as_echo "$ac_cv_prog_cc_g" >&6; } -if test "$ac_test_CFLAGS" = set; then - CFLAGS=$ac_save_CFLAGS -elif test $ac_cv_prog_cc_g = yes; then - if test "$GCC" = yes; then - CFLAGS="-g -O2" - else - CFLAGS="-g" - fi -else - if test "$GCC" = yes; then - CFLAGS="-O2" - else - CFLAGS= - fi -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 -$as_echo_n "checking for $CC option to accept ISO C89... " >&6; } -if ${ac_cv_prog_cc_c89+:} false; then : - $as_echo_n "(cached) " >&6 -else - ac_cv_prog_cc_c89=no -ac_save_CC=$CC -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include -#include -struct stat; -/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ -struct buf { int x; }; -FILE * (*rcsopen) (struct buf *, struct stat *, int); -static char *e (p, i) - char **p; - int i; -{ - return p[i]; -} -static char *f (char * (*g) (char **, int), char **p, ...) -{ - char *s; - va_list v; - va_start (v,p); - s = g (p, va_arg (v,int)); - va_end (v); - return s; -} - -/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has - function prototypes and stuff, but not '\xHH' hex character constants. - These don't provoke an error unfortunately, instead are silently treated - as 'x'. The following induces an error, until -std is added to get - proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an - array size at least. It's necessary to write '\x00'==0 to get something - that's true only with -std. */ -int osf4_cc_array ['\x00' == 0 ? 1 : -1]; - -/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters - inside strings and character constants. */ -#define FOO(x) 'x' -int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; - -int test (int i, double x); -struct s1 {int (*f) (int a);}; -struct s2 {int (*f) (double a);}; -int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); -int argc; -char **argv; -int -main () -{ -return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; - ; - return 0; -} -_ACEOF -for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ - -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" -do - CC="$ac_save_CC $ac_arg" - if ac_fn_c_try_compile "$LINENO"; then : - ac_cv_prog_cc_c89=$ac_arg -fi -rm -f core conftest.err conftest.$ac_objext - test "x$ac_cv_prog_cc_c89" != "xno" && break -done -rm -f conftest.$ac_ext -CC=$ac_save_CC - -fi -# AC_CACHE_VAL -case "x$ac_cv_prog_cc_c89" in - x) - { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 -$as_echo "none needed" >&6; } ;; - xno) - { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 -$as_echo "unsupported" >&6; } ;; - *) - CC="$CC $ac_cv_prog_cc_c89" - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 -$as_echo "$ac_cv_prog_cc_c89" >&6; } ;; -esac -if test "x$ac_cv_prog_cc_c89" != xno; then : - -fi - -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu - -# Expand $ac_aux_dir to an absolute path. -am_aux_dir=`cd "$ac_aux_dir" && pwd` - -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC understands -c and -o together" >&5 -$as_echo_n "checking whether $CC understands -c and -o together... " >&6; } -if ${am_cv_prog_cc_c_o+:} false; then : - $as_echo_n "(cached) " >&6 -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF - # Make sure it works both with $CC and with simple cc. - # Following AC_PROG_CC_C_O, we do the test twice because some - # compilers refuse to overwrite an existing .o file with -o, - # though they will create one. - am_cv_prog_cc_c_o=yes - for am_i in 1 2; do - if { echo "$as_me:$LINENO: $CC -c conftest.$ac_ext -o conftest2.$ac_objext" >&5 - ($CC -c conftest.$ac_ext -o conftest2.$ac_objext) >&5 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } \ - && test -f conftest2.$ac_objext; then - : OK - else - am_cv_prog_cc_c_o=no - break - fi - done - rm -f core conftest* - unset am_i -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_prog_cc_c_o" >&5 -$as_echo "$am_cv_prog_cc_c_o" >&6; } -if test "$am_cv_prog_cc_c_o" != yes; then - # Losing compiler, so override with the script. - # FIXME: It is wrong to rewrite CC. - # But if we don't then we get into trouble of one sort or another. - # A longer-term fix would be to have automake use am__CC in this case, - # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)" - CC="$am_aux_dir/compile $CC" -fi -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu - - -ac_ext=cpp -ac_cpp='$CXXCPP $CPPFLAGS' -ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_cxx_compiler_gnu -if test -z "$CXX"; then - if test -n "$CCC"; then - CXX=$CCC - else - if test -n "$ac_tool_prefix"; then - for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC - do - # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. -set dummy $ac_tool_prefix$ac_prog; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_CXX+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$CXX"; then - ac_cv_prog_CXX="$CXX" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_CXX="$ac_tool_prefix$ac_prog" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -CXX=$ac_cv_prog_CXX -if test -n "$CXX"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CXX" >&5 -$as_echo "$CXX" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - - test -n "$CXX" && break - done -fi -if test -z "$CXX"; then - ac_ct_CXX=$CXX - for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC -do - # Extract the first word of "$ac_prog", so it can be a program name with args. -set dummy $ac_prog; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_ac_ct_CXX+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$ac_ct_CXX"; then - ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_ac_ct_CXX="$ac_prog" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -ac_ct_CXX=$ac_cv_prog_ac_ct_CXX -if test -n "$ac_ct_CXX"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CXX" >&5 -$as_echo "$ac_ct_CXX" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - - test -n "$ac_ct_CXX" && break -done - - if test "x$ac_ct_CXX" = x; then - CXX="g++" - else - case $cross_compiling:$ac_tool_warned in -yes:) -{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} -ac_tool_warned=yes ;; -esac - CXX=$ac_ct_CXX - fi -fi - - fi -fi -# Provide some information about the compiler. -$as_echo "$as_me:${as_lineno-$LINENO}: checking for C++ compiler version" >&5 -set X $ac_compile -ac_compiler=$2 -for ac_option in --version -v -V -qversion; do - { { ac_try="$ac_compiler $ac_option >&5" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 - (eval "$ac_compiler $ac_option >&5") 2>conftest.err - ac_status=$? - if test -s conftest.err; then - sed '10a\ -... rest of stderr output deleted ... - 10q' conftest.err >conftest.er1 - cat conftest.er1 >&5 - fi - rm -f conftest.er1 conftest.err - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } -done - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C++ compiler" >&5 -$as_echo_n "checking whether we are using the GNU C++ compiler... " >&6; } -if ${ac_cv_cxx_compiler_gnu+:} false; then : - $as_echo_n "(cached) " >&6 -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ -#ifndef __GNUC__ - choke me -#endif - - ; - return 0; -} -_ACEOF -if ac_fn_cxx_try_compile "$LINENO"; then : - ac_compiler_gnu=yes -else - ac_compiler_gnu=no -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -ac_cv_cxx_compiler_gnu=$ac_compiler_gnu - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cxx_compiler_gnu" >&5 -$as_echo "$ac_cv_cxx_compiler_gnu" >&6; } -if test $ac_compiler_gnu = yes; then - GXX=yes -else - GXX= -fi -ac_test_CXXFLAGS=${CXXFLAGS+set} -ac_save_CXXFLAGS=$CXXFLAGS -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CXX accepts -g" >&5 -$as_echo_n "checking whether $CXX accepts -g... " >&6; } -if ${ac_cv_prog_cxx_g+:} false; then : - $as_echo_n "(cached) " >&6 -else - ac_save_cxx_werror_flag=$ac_cxx_werror_flag - ac_cxx_werror_flag=yes - ac_cv_prog_cxx_g=no - CXXFLAGS="-g" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -if ac_fn_cxx_try_compile "$LINENO"; then : - ac_cv_prog_cxx_g=yes -else - CXXFLAGS="" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -if ac_fn_cxx_try_compile "$LINENO"; then : - -else - ac_cxx_werror_flag=$ac_save_cxx_werror_flag - CXXFLAGS="-g" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -if ac_fn_cxx_try_compile "$LINENO"; then : - ac_cv_prog_cxx_g=yes -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - ac_cxx_werror_flag=$ac_save_cxx_werror_flag -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cxx_g" >&5 -$as_echo "$ac_cv_prog_cxx_g" >&6; } -if test "$ac_test_CXXFLAGS" = set; then - CXXFLAGS=$ac_save_CXXFLAGS -elif test $ac_cv_prog_cxx_g = yes; then - if test "$GXX" = yes; then - CXXFLAGS="-g -O2" - else - CXXFLAGS="-g" - fi -else - if test "$GXX" = yes; then - CXXFLAGS="-O2" - else - CXXFLAGS= - fi -fi -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a sed that does not truncate output" >&5 -$as_echo_n "checking for a sed that does not truncate output... " >&6; } -if ${ac_cv_path_SED+:} false; then : - $as_echo_n "(cached) " >&6 -else - ac_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/ - for ac_i in 1 2 3 4 5 6 7; do - ac_script="$ac_script$as_nl$ac_script" - done - echo "$ac_script" 2>/dev/null | sed 99q >conftest.sed - { ac_script=; unset ac_script;} - if test -z "$SED"; then - ac_path_SED_found=false - # Loop through the user's path and test for each of PROGNAME-LIST - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_prog in sed gsed; do - for ac_exec_ext in '' $ac_executable_extensions; do - ac_path_SED="$as_dir/$ac_prog$ac_exec_ext" - as_fn_executable_p "$ac_path_SED" || continue -# Check for GNU ac_path_SED and select it if it is found. - # Check for GNU $ac_path_SED -case `"$ac_path_SED" --version 2>&1` in -*GNU*) - ac_cv_path_SED="$ac_path_SED" ac_path_SED_found=:;; -*) - ac_count=0 - $as_echo_n 0123456789 >"conftest.in" - while : - do - cat "conftest.in" "conftest.in" >"conftest.tmp" - mv "conftest.tmp" "conftest.in" - cp "conftest.in" "conftest.nl" - $as_echo '' >> "conftest.nl" - "$ac_path_SED" -f conftest.sed < "conftest.nl" >"conftest.out" 2>/dev/null || break - diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break - as_fn_arith $ac_count + 1 && ac_count=$as_val - if test $ac_count -gt ${ac_path_SED_max-0}; then - # Best one so far, save it but keep looking for a better one - ac_cv_path_SED="$ac_path_SED" - ac_path_SED_max=$ac_count - fi - # 10*(2^10) chars as input seems more than enough - test $ac_count -gt 10 && break - done - rm -f conftest.in conftest.tmp conftest.nl conftest.out;; -esac - - $ac_path_SED_found && break 3 - done - done - done -IFS=$as_save_IFS - if test -z "$ac_cv_path_SED"; then - as_fn_error $? "no acceptable sed could be found in \$PATH" "$LINENO" 5 - fi -else - ac_cv_path_SED=$SED -fi - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_SED" >&5 -$as_echo "$ac_cv_path_SED" >&6; } - SED="$ac_cv_path_SED" - rm -f conftest.sed - -ac_ext=cpp -ac_cpp='$CXXCPP $CPPFLAGS' -ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_cxx_compiler_gnu - -# Make sure we can run config.sub. -$SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 || - as_fn_error $? "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5 - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5 -$as_echo_n "checking build system type... " >&6; } -if ${ac_cv_build+:} false; then : - $as_echo_n "(cached) " >&6 -else - ac_build_alias=$build_alias -test "x$ac_build_alias" = x && - ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"` -test "x$ac_build_alias" = x && - as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5 -ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` || - as_fn_error $? "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5 - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5 -$as_echo "$ac_cv_build" >&6; } -case $ac_cv_build in -*-*-*) ;; -*) as_fn_error $? "invalid value of canonical build" "$LINENO" 5;; -esac -build=$ac_cv_build -ac_save_IFS=$IFS; IFS='-' -set x $ac_cv_build -shift -build_cpu=$1 -build_vendor=$2 -shift; shift -# Remember, the first character of IFS is used to create $*, -# except with old shells: -build_os=$* -IFS=$ac_save_IFS -case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac - - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5 -$as_echo_n "checking host system type... " >&6; } -if ${ac_cv_host+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test "x$host_alias" = x; then - ac_cv_host=$ac_cv_build -else - ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` || - as_fn_error $? "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5 -fi - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5 -$as_echo "$ac_cv_host" >&6; } -case $ac_cv_host in -*-*-*) ;; -*) as_fn_error $? "invalid value of canonical host" "$LINENO" 5;; -esac -host=$ac_cv_host -ac_save_IFS=$IFS; IFS='-' -set x $ac_cv_host -shift -host_cpu=$1 -host_vendor=$2 -shift; shift -# Remember, the first character of IFS is used to create $*, -# except with old shells: -host_os=$* -IFS=$ac_save_IFS -case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac - - -am__api_version='1.15' - -# Find a good install program. We prefer a C program (faster), -# so one script is as good as another. But avoid the broken or -# incompatible versions: -# SysV /etc/install, /usr/sbin/install -# SunOS /usr/etc/install -# IRIX /sbin/install -# AIX /bin/install -# AmigaOS /C/install, which installs bootblocks on floppy discs -# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag -# AFS /usr/afsws/bin/install, which mishandles nonexistent args -# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" -# OS/2's system install, which has a completely different semantic -# ./install, which can be erroneously created by make from ./install.sh. -# Reject install programs that cannot install multiple files. -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5 -$as_echo_n "checking for a BSD-compatible install... " >&6; } -if test -z "$INSTALL"; then -if ${ac_cv_path_install+:} false; then : - $as_echo_n "(cached) " >&6 -else - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - # Account for people who put trailing slashes in PATH elements. -case $as_dir/ in #(( - ./ | .// | /[cC]/* | \ - /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ - ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \ - /usr/ucb/* ) ;; - *) - # OSF1 and SCO ODT 3.0 have their own names for install. - # Don't use installbsd from OSF since it installs stuff as root - # by default. - for ac_prog in ginstall scoinst install; do - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then - if test $ac_prog = install && - grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then - # AIX install. It has an incompatible calling convention. - : - elif test $ac_prog = install && - grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then - # program-specific install script used by HP pwplus--don't use. - : - else - rm -rf conftest.one conftest.two conftest.dir - echo one > conftest.one - echo two > conftest.two - mkdir conftest.dir - if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" && - test -s conftest.one && test -s conftest.two && - test -s conftest.dir/conftest.one && - test -s conftest.dir/conftest.two - then - ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" - break 3 - fi - fi - fi - done - done - ;; -esac - - done -IFS=$as_save_IFS - -rm -rf conftest.one conftest.two conftest.dir - -fi - if test "${ac_cv_path_install+set}" = set; then - INSTALL=$ac_cv_path_install - else - # As a last resort, use the slow shell script. Don't cache a - # value for INSTALL within a source directory, because that will - # break other packages using the cache if that directory is - # removed, or if the value is a relative name. - INSTALL=$ac_install_sh - fi -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5 -$as_echo "$INSTALL" >&6; } - -# Use test -z because SunOS4 sh mishandles braces in ${var-val}. -# It thinks the first close brace ends the variable substitution. -test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' - -test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' - -test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether build environment is sane" >&5 -$as_echo_n "checking whether build environment is sane... " >&6; } -# Reject unsafe characters in $srcdir or the absolute working directory -# name. Accept space and tab only in the latter. -am_lf=' -' -case `pwd` in - *[\\\"\#\$\&\'\`$am_lf]*) - as_fn_error $? "unsafe absolute working directory name" "$LINENO" 5;; -esac -case $srcdir in - *[\\\"\#\$\&\'\`$am_lf\ \ ]*) - as_fn_error $? "unsafe srcdir value: '$srcdir'" "$LINENO" 5;; -esac - -# Do 'set' in a subshell so we don't clobber the current shell's -# arguments. Must try -L first in case configure is actually a -# symlink; some systems play weird games with the mod time of symlinks -# (eg FreeBSD returns the mod time of the symlink's containing -# directory). -if ( - am_has_slept=no - for am_try in 1 2; do - echo "timestamp, slept: $am_has_slept" > conftest.file - set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` - if test "$*" = "X"; then - # -L didn't work. - set X `ls -t "$srcdir/configure" conftest.file` - fi - if test "$*" != "X $srcdir/configure conftest.file" \ - && test "$*" != "X conftest.file $srcdir/configure"; then - - # If neither matched, then we have a broken ls. This can happen - # if, for instance, CONFIG_SHELL is bash and it inherits a - # broken ls alias from the environment. This has actually - # happened. Such a system could not be considered "sane". - as_fn_error $? "ls -t appears to fail. Make sure there is not a broken - alias in your environment" "$LINENO" 5 - fi - if test "$2" = conftest.file || test $am_try -eq 2; then - break - fi - # Just in case. - sleep 1 - am_has_slept=yes - done - test "$2" = conftest.file - ) -then - # Ok. - : -else - as_fn_error $? "newly created file is older than distributed files! -Check your system clock" "$LINENO" 5 -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } -# If we didn't sleep, we still need to ensure time stamps of config.status and -# generated files are strictly newer. -am_sleep_pid= -if grep 'slept: no' conftest.file >/dev/null 2>&1; then - ( sleep 1 ) & - am_sleep_pid=$! -fi - -rm -f conftest.file - -test "$program_prefix" != NONE && - program_transform_name="s&^&$program_prefix&;$program_transform_name" -# Use a double $ so make ignores it. -test "$program_suffix" != NONE && - program_transform_name="s&\$&$program_suffix&;$program_transform_name" -# Double any \ or $. -# By default was `s,x,x', remove it if useless. -ac_script='s/[\\$]/&&/g;s/;s,x,x,$//' -program_transform_name=`$as_echo "$program_transform_name" | sed "$ac_script"` - -if test x"${MISSING+set}" != xset; then - case $am_aux_dir in - *\ * | *\ *) - MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;; - *) - MISSING="\${SHELL} $am_aux_dir/missing" ;; - esac -fi -# Use eval to expand $SHELL -if eval "$MISSING --is-lightweight"; then - am_missing_run="$MISSING " -else - am_missing_run= - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: 'missing' script is too old or missing" >&5 -$as_echo "$as_me: WARNING: 'missing' script is too old or missing" >&2;} -fi - -if test x"${install_sh+set}" != xset; then - case $am_aux_dir in - *\ * | *\ *) - install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; - *) - install_sh="\${SHELL} $am_aux_dir/install-sh" - esac -fi - -# Installed binaries are usually stripped using 'strip' when the user -# run "make install-strip". However 'strip' might not be the right -# tool to use in cross-compilation environments, therefore Automake -# will honor the 'STRIP' environment variable to overrule this program. -if test "$cross_compiling" != no; then - if test -n "$ac_tool_prefix"; then - # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. -set dummy ${ac_tool_prefix}strip; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_STRIP+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$STRIP"; then - ac_cv_prog_STRIP="$STRIP" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_STRIP="${ac_tool_prefix}strip" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -STRIP=$ac_cv_prog_STRIP -if test -n "$STRIP"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 -$as_echo "$STRIP" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - -fi -if test -z "$ac_cv_prog_STRIP"; then - ac_ct_STRIP=$STRIP - # Extract the first word of "strip", so it can be a program name with args. -set dummy strip; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_ac_ct_STRIP+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$ac_ct_STRIP"; then - ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_ac_ct_STRIP="strip" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP -if test -n "$ac_ct_STRIP"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5 -$as_echo "$ac_ct_STRIP" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - if test "x$ac_ct_STRIP" = x; then - STRIP=":" - else - case $cross_compiling:$ac_tool_warned in -yes:) -{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} -ac_tool_warned=yes ;; -esac - STRIP=$ac_ct_STRIP - fi -else - STRIP="$ac_cv_prog_STRIP" -fi - -fi -INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a thread-safe mkdir -p" >&5 -$as_echo_n "checking for a thread-safe mkdir -p... " >&6; } -if test -z "$MKDIR_P"; then - if ${ac_cv_path_mkdir+:} false; then : - $as_echo_n "(cached) " >&6 -else - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH$PATH_SEPARATOR/opt/sfw/bin -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_prog in mkdir gmkdir; do - for ac_exec_ext in '' $ac_executable_extensions; do - as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext" || continue - case `"$as_dir/$ac_prog$ac_exec_ext" --version 2>&1` in #( - 'mkdir (GNU coreutils) '* | \ - 'mkdir (coreutils) '* | \ - 'mkdir (fileutils) '4.1*) - ac_cv_path_mkdir=$as_dir/$ac_prog$ac_exec_ext - break 3;; - esac - done - done - done -IFS=$as_save_IFS - -fi - - test -d ./--version && rmdir ./--version - if test "${ac_cv_path_mkdir+set}" = set; then - MKDIR_P="$ac_cv_path_mkdir -p" - else - # As a last resort, use the slow shell script. Don't cache a - # value for MKDIR_P within a source directory, because that will - # break other packages using the cache if that directory is - # removed, or if the value is a relative name. - MKDIR_P="$ac_install_sh -d" - fi -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $MKDIR_P" >&5 -$as_echo "$MKDIR_P" >&6; } - -for ac_prog in gawk mawk nawk awk -do - # Extract the first word of "$ac_prog", so it can be a program name with args. -set dummy $ac_prog; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_AWK+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$AWK"; then - ac_cv_prog_AWK="$AWK" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_AWK="$ac_prog" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -AWK=$ac_cv_prog_AWK -if test -n "$AWK"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5 -$as_echo "$AWK" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - - test -n "$AWK" && break -done - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5 -$as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; } -set x ${MAKE-make} -ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'` -if eval \${ac_cv_prog_make_${ac_make}_set+:} false; then : - $as_echo_n "(cached) " >&6 -else - cat >conftest.make <<\_ACEOF -SHELL = /bin/sh -all: - @echo '@@@%%%=$(MAKE)=@@@%%%' -_ACEOF -# GNU make sometimes prints "make[1]: Entering ...", which would confuse us. -case `${MAKE-make} -f conftest.make 2>/dev/null` in - *@@@%%%=?*=@@@%%%*) - eval ac_cv_prog_make_${ac_make}_set=yes;; - *) - eval ac_cv_prog_make_${ac_make}_set=no;; -esac -rm -f conftest.make -fi -if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } - SET_MAKE= -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } - SET_MAKE="MAKE=${MAKE-make}" -fi - -rm -rf .tst 2>/dev/null -mkdir .tst 2>/dev/null -if test -d .tst; then - am__leading_dot=. -else - am__leading_dot=_ -fi -rmdir .tst 2>/dev/null - -DEPDIR="${am__leading_dot}deps" - -ac_config_commands="$ac_config_commands depfiles" - - -am_make=${MAKE-make} -cat > confinc << 'END' -am__doit: - @echo this is the am__doit target -.PHONY: am__doit -END -# If we don't find an include directive, just comment out the code. -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for style of include used by $am_make" >&5 -$as_echo_n "checking for style of include used by $am_make... " >&6; } -am__include="#" -am__quote= -_am_result=none -# First try GNU make style include. -echo "include confinc" > confmf -# Ignore all kinds of additional output from 'make'. -case `$am_make -s -f confmf 2> /dev/null` in #( -*the\ am__doit\ target*) - am__include=include - am__quote= - _am_result=GNU - ;; -esac -# Now try BSD make style include. -if test "$am__include" = "#"; then - echo '.include "confinc"' > confmf - case `$am_make -s -f confmf 2> /dev/null` in #( - *the\ am__doit\ target*) - am__include=.include - am__quote="\"" - _am_result=BSD - ;; - esac -fi - - -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $_am_result" >&5 -$as_echo "$_am_result" >&6; } -rm -f confinc confmf - -# Check whether --enable-dependency-tracking was given. -if test "${enable_dependency_tracking+set}" = set; then : - enableval=$enable_dependency_tracking; -fi - -if test "x$enable_dependency_tracking" != xno; then - am_depcomp="$ac_aux_dir/depcomp" - AMDEPBACKSLASH='\' - am__nodep='_no' -fi - if test "x$enable_dependency_tracking" != xno; then - AMDEP_TRUE= - AMDEP_FALSE='#' -else - AMDEP_TRUE='#' - AMDEP_FALSE= -fi - - -# Check whether --enable-silent-rules was given. -if test "${enable_silent_rules+set}" = set; then : - enableval=$enable_silent_rules; -fi - -case $enable_silent_rules in # ((( - yes) AM_DEFAULT_VERBOSITY=0;; - no) AM_DEFAULT_VERBOSITY=1;; - *) AM_DEFAULT_VERBOSITY=1;; -esac -am_make=${MAKE-make} -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $am_make supports nested variables" >&5 -$as_echo_n "checking whether $am_make supports nested variables... " >&6; } -if ${am_cv_make_support_nested_variables+:} false; then : - $as_echo_n "(cached) " >&6 -else - if $as_echo 'TRUE=$(BAR$(V)) -BAR0=false -BAR1=true -V=1 -am__doit: - @$(TRUE) -.PHONY: am__doit' | $am_make -f - >/dev/null 2>&1; then - am_cv_make_support_nested_variables=yes -else - am_cv_make_support_nested_variables=no -fi -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_make_support_nested_variables" >&5 -$as_echo "$am_cv_make_support_nested_variables" >&6; } -if test $am_cv_make_support_nested_variables = yes; then - AM_V='$(V)' - AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' -else - AM_V=$AM_DEFAULT_VERBOSITY - AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY -fi -AM_BACKSLASH='\' - -if test "`cd $srcdir && pwd`" != "`pwd`"; then - # Use -I$(srcdir) only when $(srcdir) != ., so that make's output - # is not polluted with repeated "-I." - am__isrc=' -I$(srcdir)' - # test to see if srcdir already configured - if test -f $srcdir/config.status; then - as_fn_error $? "source directory already configured; run \"make distclean\" there first" "$LINENO" 5 - fi -fi - -# test whether we have cygpath -if test -z "$CYGPATH_W"; then - if (cygpath --version) >/dev/null 2>/dev/null; then - CYGPATH_W='cygpath -w' - else - CYGPATH_W=echo - fi -fi - - -# Define the identity of the package. - PACKAGE='qbittorrent' - VERSION='v3.2.0alpha' - - -cat >>confdefs.h <<_ACEOF -#define PACKAGE "$PACKAGE" -_ACEOF - - -cat >>confdefs.h <<_ACEOF -#define VERSION "$VERSION" -_ACEOF - -# Some tools Automake needs. - -ACLOCAL=${ACLOCAL-"${am_missing_run}aclocal-${am__api_version}"} - - -AUTOCONF=${AUTOCONF-"${am_missing_run}autoconf"} - - -AUTOMAKE=${AUTOMAKE-"${am_missing_run}automake-${am__api_version}"} - - -AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"} - - -MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"} - -# For better backward compatibility. To be removed once Automake 1.9.x -# dies out for good. For more background, see: -# -# -mkdir_p='$(MKDIR_P)' - -# We need awk for the "check" target (and possibly the TAP driver). The -# system "awk" is bad on some platforms. -# Always define AMTAR for backward compatibility. Yes, it's still used -# in the wild :-( We should find a proper way to deprecate it ... -AMTAR='$${TAR-tar}' - - -# We'll loop over all known methods to create a tar archive until one works. -_am_tools='gnutar pax cpio none' - -am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -' - - - - - -depcc="$CC" am_compiler_list= - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5 -$as_echo_n "checking dependency style of $depcc... " >&6; } -if ${am_cv_CC_dependencies_compiler_type+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then - # We make a subdir and do the tests there. Otherwise we can end up - # making bogus files that we don't know about and never remove. For - # instance it was reported that on HP-UX the gcc test will end up - # making a dummy file named 'D' -- because '-MD' means "put the output - # in D". - rm -rf conftest.dir - mkdir conftest.dir - # Copy depcomp to subdir because otherwise we won't find it if we're - # using a relative directory. - cp "$am_depcomp" conftest.dir - cd conftest.dir - # We will build objects and dependencies in a subdirectory because - # it helps to detect inapplicable dependency modes. For instance - # both Tru64's cc and ICC support -MD to output dependencies as a - # side effect of compilation, but ICC will put the dependencies in - # the current directory while Tru64 will put them in the object - # directory. - mkdir sub - - am_cv_CC_dependencies_compiler_type=none - if test "$am_compiler_list" = ""; then - am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` - fi - am__universal=false - case " $depcc " in #( - *\ -arch\ *\ -arch\ *) am__universal=true ;; - esac - - for depmode in $am_compiler_list; do - # Setup a source with many dependencies, because some compilers - # like to wrap large dependency lists on column 80 (with \), and - # we should not choose a depcomp mode which is confused by this. - # - # We need to recreate these files for each test, as the compiler may - # overwrite some of them when testing with obscure command lines. - # This happens at least with the AIX C compiler. - : > sub/conftest.c - for i in 1 2 3 4 5 6; do - echo '#include "conftst'$i'.h"' >> sub/conftest.c - # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with - # Solaris 10 /bin/sh. - echo '/* dummy */' > sub/conftst$i.h - done - echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf - - # We check with '-c' and '-o' for the sake of the "dashmstdout" - # mode. It turns out that the SunPro C++ compiler does not properly - # handle '-M -o', and we need to detect this. Also, some Intel - # versions had trouble with output in subdirs. - am__obj=sub/conftest.${OBJEXT-o} - am__minus_obj="-o $am__obj" - case $depmode in - gcc) - # This depmode causes a compiler race in universal mode. - test "$am__universal" = false || continue - ;; - nosideeffect) - # After this tag, mechanisms are not by side-effect, so they'll - # only be used when explicitly requested. - if test "x$enable_dependency_tracking" = xyes; then - continue - else - break - fi - ;; - msvc7 | msvc7msys | msvisualcpp | msvcmsys) - # This compiler won't grok '-c -o', but also, the minuso test has - # not run yet. These depmodes are late enough in the game, and - # so weak that their functioning should not be impacted. - am__obj=conftest.${OBJEXT-o} - am__minus_obj= - ;; - none) break ;; - esac - if depmode=$depmode \ - source=sub/conftest.c object=$am__obj \ - depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ - $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ - >/dev/null 2>conftest.err && - grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && - grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && - grep $am__obj sub/conftest.Po > /dev/null 2>&1 && - ${MAKE-make} -s -f confmf > /dev/null 2>&1; then - # icc doesn't choke on unknown options, it will just issue warnings - # or remarks (even with -Werror). So we grep stderr for any message - # that says an option was ignored or not supported. - # When given -MP, icc 7.0 and 7.1 complain thusly: - # icc: Command line warning: ignoring option '-M'; no argument required - # The diagnosis changed in icc 8.0: - # icc: Command line remark: option '-MP' not supported - if (grep 'ignoring option' conftest.err || - grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else - am_cv_CC_dependencies_compiler_type=$depmode - break - fi - fi - done - - cd .. - rm -rf conftest.dir -else - am_cv_CC_dependencies_compiler_type=none -fi - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CC_dependencies_compiler_type" >&5 -$as_echo "$am_cv_CC_dependencies_compiler_type" >&6; } -CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type - - if - test "x$enable_dependency_tracking" != xno \ - && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then - am__fastdepCC_TRUE= - am__fastdepCC_FALSE='#' -else - am__fastdepCC_TRUE='#' - am__fastdepCC_FALSE= -fi - - -depcc="$CXX" am_compiler_list= - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5 -$as_echo_n "checking dependency style of $depcc... " >&6; } -if ${am_cv_CXX_dependencies_compiler_type+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then - # We make a subdir and do the tests there. Otherwise we can end up - # making bogus files that we don't know about and never remove. For - # instance it was reported that on HP-UX the gcc test will end up - # making a dummy file named 'D' -- because '-MD' means "put the output - # in D". - rm -rf conftest.dir - mkdir conftest.dir - # Copy depcomp to subdir because otherwise we won't find it if we're - # using a relative directory. - cp "$am_depcomp" conftest.dir - cd conftest.dir - # We will build objects and dependencies in a subdirectory because - # it helps to detect inapplicable dependency modes. For instance - # both Tru64's cc and ICC support -MD to output dependencies as a - # side effect of compilation, but ICC will put the dependencies in - # the current directory while Tru64 will put them in the object - # directory. - mkdir sub - - am_cv_CXX_dependencies_compiler_type=none - if test "$am_compiler_list" = ""; then - am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` - fi - am__universal=false - case " $depcc " in #( - *\ -arch\ *\ -arch\ *) am__universal=true ;; - esac - - for depmode in $am_compiler_list; do - # Setup a source with many dependencies, because some compilers - # like to wrap large dependency lists on column 80 (with \), and - # we should not choose a depcomp mode which is confused by this. - # - # We need to recreate these files for each test, as the compiler may - # overwrite some of them when testing with obscure command lines. - # This happens at least with the AIX C compiler. - : > sub/conftest.c - for i in 1 2 3 4 5 6; do - echo '#include "conftst'$i'.h"' >> sub/conftest.c - # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with - # Solaris 10 /bin/sh. - echo '/* dummy */' > sub/conftst$i.h - done - echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf - - # We check with '-c' and '-o' for the sake of the "dashmstdout" - # mode. It turns out that the SunPro C++ compiler does not properly - # handle '-M -o', and we need to detect this. Also, some Intel - # versions had trouble with output in subdirs. - am__obj=sub/conftest.${OBJEXT-o} - am__minus_obj="-o $am__obj" - case $depmode in - gcc) - # This depmode causes a compiler race in universal mode. - test "$am__universal" = false || continue - ;; - nosideeffect) - # After this tag, mechanisms are not by side-effect, so they'll - # only be used when explicitly requested. - if test "x$enable_dependency_tracking" = xyes; then - continue - else - break - fi - ;; - msvc7 | msvc7msys | msvisualcpp | msvcmsys) - # This compiler won't grok '-c -o', but also, the minuso test has - # not run yet. These depmodes are late enough in the game, and - # so weak that their functioning should not be impacted. - am__obj=conftest.${OBJEXT-o} - am__minus_obj= - ;; - none) break ;; - esac - if depmode=$depmode \ - source=sub/conftest.c object=$am__obj \ - depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ - $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ - >/dev/null 2>conftest.err && - grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && - grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && - grep $am__obj sub/conftest.Po > /dev/null 2>&1 && - ${MAKE-make} -s -f confmf > /dev/null 2>&1; then - # icc doesn't choke on unknown options, it will just issue warnings - # or remarks (even with -Werror). So we grep stderr for any message - # that says an option was ignored or not supported. - # When given -MP, icc 7.0 and 7.1 complain thusly: - # icc: Command line warning: ignoring option '-M'; no argument required - # The diagnosis changed in icc 8.0: - # icc: Command line remark: option '-MP' not supported - if (grep 'ignoring option' conftest.err || - grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else - am_cv_CXX_dependencies_compiler_type=$depmode - break - fi - fi - done - - cd .. - rm -rf conftest.dir -else - am_cv_CXX_dependencies_compiler_type=none -fi - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CXX_dependencies_compiler_type" >&5 -$as_echo "$am_cv_CXX_dependencies_compiler_type" >&6; } -CXXDEPMODE=depmode=$am_cv_CXX_dependencies_compiler_type - - if - test "x$enable_dependency_tracking" != xno \ - && test "$am_cv_CXX_dependencies_compiler_type" = gcc3; then - am__fastdepCXX_TRUE= - am__fastdepCXX_FALSE='#' -else - am__fastdepCXX_TRUE='#' - am__fastdepCXX_FALSE= -fi - - - -# POSIX will say in a future version that running "rm -f" with no argument -# is OK; and we want to be able to make that assumption in our Makefile -# recipes. So use an aggressive probe to check that the usage we want is -# actually supported "in the wild" to an acceptable degree. -# See automake bug#10828. -# To make any issue more visible, cause the running configure to be aborted -# by default if the 'rm' program in use doesn't match our expectations; the -# user can still override this though. -if rm -f && rm -fr && rm -rf; then : OK; else - cat >&2 <<'END' -Oops! - -Your 'rm' program seems unable to run without file operands specified -on the command line, even when the '-f' option is present. This is contrary -to the behaviour of most rm programs out there, and not conforming with -the upcoming POSIX standard: - -Please tell bug-automake@gnu.org about your system, including the value -of your $PATH and any error possibly output before this message. This -can help us improve future automake versions. - -END - if test x"$ACCEPT_INFERIOR_RM_PROGRAM" = x"yes"; then - echo 'Configuration will proceed anyway, since you have set the' >&2 - echo 'ACCEPT_INFERIOR_RM_PROGRAM variable to "yes"' >&2 - echo >&2 - else - cat >&2 <<'END' -Aborting the configuration process, to ensure you take notice of the issue. - -You can download and install GNU coreutils to get an 'rm' implementation -that behaves properly: . - -If you want to complete the configuration process using your problematic -'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM -to "yes", and re-run configure. - -END - as_fn_error $? "Your 'rm' program is bad, sorry." "$LINENO" 5 - fi -fi - - - - -# Define --wth-* and --enable-* arguments - - -# Check whether --with-qtsingleapplication was given. -if test "${with_qtsingleapplication+set}" = set; then : - withval=$with_qtsingleapplication; -else - with_qtsingleapplication=shipped -fi - - -# Check whether --enable-debug was given. -if test "${enable_debug+set}" = set; then : - enableval=$enable_debug; -else - enable_debug=no -fi - - -# Check whether --enable-gui was given. -if test "${enable_gui+set}" = set; then : - enableval=$enable_gui; -else - enable_gui=yes -fi - - -# Check whether --enable-systemd was given. -if test "${enable_systemd+set}" = set; then : - enableval=$enable_systemd; -else - enable_systemd=no -fi - - -# Check whether --enable-webui was given. -if test "${enable_webui+set}" = set; then : - enableval=$enable_webui; -else - enable_webui=yes -fi - - -# Check whether --enable-qt-dbus was given. -if test "${enable_qt_dbus+set}" = set; then : - enableval=$enable_qt_dbus; -else - enable_qt_dbus=yes -fi - - -# Detect OS -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether OS is FreeBSD" >&5 -$as_echo_n "checking whether OS is FreeBSD... " >&6; } -if expr "$host_os" : ".*freebsd.*" > /dev/null; then : - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } - LIBS="-lexecinfo $LIBS" -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether OS is macOS" >&5 -$as_echo_n "checking whether OS is macOS... " >&6; } -if expr "$host_os" : ".*darwin.*" > /dev/null; then : - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } - enable_qt_dbus=no -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - -# Require 0.23 pkg-config - - - - - - - -if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then - if test -n "$ac_tool_prefix"; then - # Extract the first word of "${ac_tool_prefix}pkg-config", so it can be a program name with args. -set dummy ${ac_tool_prefix}pkg-config; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_path_PKG_CONFIG+:} false; then : - $as_echo_n "(cached) " >&6 -else - case $PKG_CONFIG in - [\\/]* | ?:[\\/]*) - ac_cv_path_PKG_CONFIG="$PKG_CONFIG" # Let the user override the test with a path. - ;; - *) - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_path_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - - ;; -esac -fi -PKG_CONFIG=$ac_cv_path_PKG_CONFIG -if test -n "$PKG_CONFIG"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PKG_CONFIG" >&5 -$as_echo "$PKG_CONFIG" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - -fi -if test -z "$ac_cv_path_PKG_CONFIG"; then - ac_pt_PKG_CONFIG=$PKG_CONFIG - # Extract the first word of "pkg-config", so it can be a program name with args. -set dummy pkg-config; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_path_ac_pt_PKG_CONFIG+:} false; then : - $as_echo_n "(cached) " >&6 -else - case $ac_pt_PKG_CONFIG in - [\\/]* | ?:[\\/]*) - ac_cv_path_ac_pt_PKG_CONFIG="$ac_pt_PKG_CONFIG" # Let the user override the test with a path. - ;; - *) - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_path_ac_pt_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - - ;; -esac -fi -ac_pt_PKG_CONFIG=$ac_cv_path_ac_pt_PKG_CONFIG -if test -n "$ac_pt_PKG_CONFIG"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_pt_PKG_CONFIG" >&5 -$as_echo "$ac_pt_PKG_CONFIG" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - if test "x$ac_pt_PKG_CONFIG" = x; then - PKG_CONFIG="" - else - case $cross_compiling:$ac_tool_warned in -yes:) -{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} -ac_tool_warned=yes ;; -esac - PKG_CONFIG=$ac_pt_PKG_CONFIG - fi -else - PKG_CONFIG="$ac_cv_path_PKG_CONFIG" -fi - -fi -if test -n "$PKG_CONFIG"; then - _pkg_min_version=0.23 - { $as_echo "$as_me:${as_lineno-$LINENO}: checking pkg-config is at least version $_pkg_min_version" >&5 -$as_echo_n "checking pkg-config is at least version $_pkg_min_version... " >&6; } - if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } - else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } - PKG_CONFIG="" - fi -fi -if test "x$PKG_CONFIG" = "x"; then : - as_fn_error $? "Could not find pkg-config" "$LINENO" 5 -fi - -# Check which arguments were set and act accordingly -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable the Debug build" >&5 -$as_echo_n "checking whether to enable the Debug build... " >&6; } -case "x$enable_debug" in #( - "xno") : - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } - QBT_ADD_CONFIG="$QBT_ADD_CONFIG release" - QBT_REMOVE_CONFIG="$QBT_REMOVE_CONFIG debug" ;; #( - "xyes") : - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } - QBT_ADD_CONFIG="$QBT_ADD_CONFIG debug" - QBT_REMOVE_CONFIG="$QBT_REMOVE_CONFIG release" ;; #( - *) : - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_debug" >&5 -$as_echo "$enable_debug" >&6; } - as_fn_error $? "Unknown option \"$enable_debug\". Use either \"yes\" or \"no\"." "$LINENO" 5 ;; -esac - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable the GUI" >&5 -$as_echo_n "checking whether to enable the GUI... " >&6; } -case "x$enable_gui" in #( - "xyes") : - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } - enable_systemd=no - QBT_REMOVE_CONFIG="$QBT_REMOVE_CONFIG nogui" ;; #( - "xno") : - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } - enable_qt_dbus=no - QBT_ADD_CONFIG="$QBT_ADD_CONFIG nogui" ;; #( - *) : - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_gui" >&5 -$as_echo "$enable_gui" >&6; } - as_fn_error $? "Unknown option \"$enable_gui\". Use either \"yes\" or \"no\"." "$LINENO" 5 ;; -esac - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to install the systemd service file" >&5 -$as_echo_n "checking whether to install the systemd service file... " >&6; } -case "x$enable_systemd" in #( - "xyes") : - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } - QBT_ADD_CONFIG="$QBT_ADD_CONFIG systemd" ;; #( - "xno") : - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } - QBT_REMOVE_CONFIG="$QBT_REMOVE_CONFIG systemd" ;; #( - *) : - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_systemd" >&5 -$as_echo "$enable_systemd" >&6; } - as_fn_error $? "Unknown option \"$enable_systemd\". Use either \"yes\" or \"no\"." "$LINENO" 5 ;; -esac - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable the WebUI" >&5 -$as_echo_n "checking whether to enable the WebUI... " >&6; } -case "x$enable_webui" in #( - "xyes") : - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } - QBT_REMOVE_CONFIG="$QBT_REMOVE_CONFIG nowebui" ;; #( - "xno") : - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } - QBT_ADD_CONFIG="$QBT_ADD_CONFIG nowebui" ;; #( - *) : - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_webui" >&5 -$as_echo "$enable_webui" >&6; } - as_fn_error $? "Unknown option \"$enable_webui\". Use either \"yes\" or \"no\"." "$LINENO" 5 ;; -esac - -if test -n "$PKG_CONFIG" && \ - { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"Qt5Core >= 5.5.1\""; } >&5 - ($PKG_CONFIG --exists --print-errors "Qt5Core >= 5.5.1") 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; }; then - -if test -n "$QT_QMAKE"; then - pkg_cv_QT_QMAKE="$QT_QMAKE" - elif test -n "$PKG_CONFIG"; then - if test -n "$PKG_CONFIG" && \ - { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"Qt5Core >= 5.5.1\""; } >&5 - ($PKG_CONFIG --exists --print-errors "Qt5Core >= 5.5.1") 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; }; then - pkg_cv_QT_QMAKE=`$PKG_CONFIG --variable="host_bins" "Qt5Core >= 5.5.1" 2>/dev/null` - test "x$?" != "x0" && pkg_failed=yes -else - pkg_failed=yes -fi - else - pkg_failed=untried -fi -QT_QMAKE=$pkg_cv_QT_QMAKE - -if test "x$QT_QMAKE" = x""; then : - -fi - -fi - -if test -f "$QT_QMAKE/qmake"; then : - QT_QMAKE="$QT_QMAKE/qmake" -else - if test -f "$QT_QMAKE/qmake-qt5"; then : - QT_QMAKE="$QT_QMAKE/qmake-qt5" -else - QT_QMAKE="" -fi - -fi - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for Qt5 qmake >= 5.5.1" >&5 -$as_echo_n "checking for Qt5 qmake >= 5.5.1... " >&6; } -if test "x$QT_QMAKE" != "x"; then : - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $QT_QMAKE" >&5 -$as_echo "$QT_QMAKE" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: not found" >&5 -$as_echo "not found" >&6; } - -fi - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether QtDBus should be enabled" >&5 -$as_echo_n "checking whether QtDBus should be enabled... " >&6; } -case "x$enable_qt_dbus" in #( - "xyes") : - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Qt5DBus >= 5.5.1" >&5 -$as_echo_n "checking for Qt5DBus >= 5.5.1... " >&6; } - if test -n "$PKG_CONFIG" && \ - { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"Qt5DBus >= 5.5.1\""; } >&5 - ($PKG_CONFIG --exists --print-errors "Qt5DBus >= 5.5.1") 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; }; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: found" >&5 -$as_echo "found" >&6; } - HAVE_QTDBUS=true -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: not found" >&5 -$as_echo "not found" >&6; } - HAVE_QTDBUS=false -fi - - if test "x$HAVE_QTDBUS" = "xfalse"; then : - as_fn_error $? "Could not find QtDBus" "$LINENO" 5 -else - QBT_ADD_CONFIG="$QBT_ADD_CONFIG dbus" - -fi ;; #( - "xno") : - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } - QBT_REMOVE_CONFIG="$QBT_REMOVE_CONFIG dbus" ;; #( - *) : - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_qt_dbus" >&5 -$as_echo "$enable_qt_dbus" >&6; } - as_fn_error $? "Unknown option \"$enable_qt_dbus\". Use either \"yes\" or \"no\"." "$LINENO" 5 ;; -esac - - - - - -# Check whether --with-boost was given. -if test "${with_boost+set}" = set; then : - withval=$with_boost; - if test "$withval" = "no"; then - want_boost="no" - elif test "$withval" = "yes"; then - want_boost="yes" - ac_boost_path="" - else - want_boost="yes" - ac_boost_path="$withval" - fi - -else - want_boost="yes" -fi - - - - -# Check whether --with-boost-libdir was given. -if test "${with_boost_libdir+set}" = set; then : - withval=$with_boost_libdir; - if test -d "$withval" - then - ac_boost_lib_path="$withval" - else - as_fn_error $? "--with-boost-libdir expected directory name" "$LINENO" 5 - fi - -else - ac_boost_lib_path="" - -fi - - -if test "x$want_boost" = "xyes"; then - boost_lib_version_req=1.35 - boost_lib_version_req_shorten=`expr $boost_lib_version_req : '\([0-9]*\.[0-9]*\)'` - boost_lib_version_req_major=`expr $boost_lib_version_req : '\([0-9]*\)'` - boost_lib_version_req_minor=`expr $boost_lib_version_req : '[0-9]*\.\([0-9]*\)'` - boost_lib_version_req_sub_minor=`expr $boost_lib_version_req : '[0-9]*\.[0-9]*\.\([0-9]*\)'` - if test "x$boost_lib_version_req_sub_minor" = "x" ; then - boost_lib_version_req_sub_minor="0" - fi - WANT_BOOST_VERSION=`expr $boost_lib_version_req_major \* 100000 \+ $boost_lib_version_req_minor \* 100 \+ $boost_lib_version_req_sub_minor` - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for boostlib >= $boost_lib_version_req" >&5 -$as_echo_n "checking for boostlib >= $boost_lib_version_req... " >&6; } - succeeded=no - - libsubdirs="lib" - ax_arch=`uname -m` - case $ax_arch in - x86_64) - libsubdirs="lib64 libx32 lib lib64" - ;; - ppc64|s390x|sparc64|aarch64|ppc64le) - libsubdirs="lib64 lib lib64 ppc64le" - ;; - esac - - - libsubdirs="lib/${host_cpu}-${host_os} $libsubdirs" - - case ${host_cpu} in - i?86) - libsubdirs="lib/i386-${host_os} $libsubdirs" - ;; - esac - - if test "$ac_boost_path" != ""; then - BOOST_CPPFLAGS="-I$ac_boost_path/include" - for ac_boost_path_tmp in $libsubdirs; do - if test -d "$ac_boost_path"/"$ac_boost_path_tmp" ; then - BOOST_LDFLAGS="-L$ac_boost_path/$ac_boost_path_tmp" - break - fi - done - elif test "$cross_compiling" != yes; then - for ac_boost_path_tmp in /usr /usr/local /opt /opt/local ; do - if test -d "$ac_boost_path_tmp/include/boost" && test -r "$ac_boost_path_tmp/include/boost"; then - for libsubdir in $libsubdirs ; do - if ls "$ac_boost_path_tmp/$libsubdir/libboost_"* >/dev/null 2>&1 ; then break; fi - done - BOOST_LDFLAGS="-L$ac_boost_path_tmp/$libsubdir" - BOOST_CPPFLAGS="-I$ac_boost_path_tmp/include" - break; - fi - done - fi - - if test "$ac_boost_lib_path" != ""; then - BOOST_LDFLAGS="-L$ac_boost_lib_path" - fi - - CPPFLAGS_SAVED="$CPPFLAGS" - CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS" - export CPPFLAGS - - LDFLAGS_SAVED="$LDFLAGS" - LDFLAGS="$LDFLAGS $BOOST_LDFLAGS" - export LDFLAGS - - - ac_ext=cpp -ac_cpp='$CXXCPP $CPPFLAGS' -ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_cxx_compiler_gnu - - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - - #include - -int -main () -{ - - #if BOOST_VERSION >= $WANT_BOOST_VERSION - // Everything is okay - #else - # error Boost version is too old - #endif - - ; - return 0; -} -_ACEOF -if ac_fn_cxx_try_compile "$LINENO"; then : - - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } - succeeded=yes - found_system=yes - -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - ac_ext=cpp -ac_cpp='$CXXCPP $CPPFLAGS' -ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_cxx_compiler_gnu - - - - - if test "x$succeeded" != "xyes"; then - CPPFLAGS="$CPPFLAGS_SAVED" - LDFLAGS="$LDFLAGS_SAVED" - BOOST_CPPFLAGS= - BOOST_LDFLAGS= - _version=0 - if test "$ac_boost_path" != ""; then - if test -d "$ac_boost_path" && test -r "$ac_boost_path"; then - for i in `ls -d $ac_boost_path/include/boost-* 2>/dev/null`; do - _version_tmp=`echo $i | sed "s#$ac_boost_path##" | sed 's/\/include\/boost-//' | sed 's/_/./'` - V_CHECK=`expr $_version_tmp \> $_version` - if test "$V_CHECK" = "1" ; then - _version=$_version_tmp - fi - VERSION_UNDERSCORE=`echo $_version | sed 's/\./_/'` - BOOST_CPPFLAGS="-I$ac_boost_path/include/boost-$VERSION_UNDERSCORE" - done - if test -z "$BOOST_CPPFLAGS"; then - if test -d "$ac_boost_path/boost" && test -r "$ac_boost_path/boost"; then - BOOST_CPPFLAGS="-I$ac_boost_path" - fi - fi - fi - else - if test "$cross_compiling" != yes; then - for ac_boost_path in /usr /usr/local /opt /opt/local ; do - if test -d "$ac_boost_path" && test -r "$ac_boost_path"; then - for i in `ls -d $ac_boost_path/include/boost-* 2>/dev/null`; do - _version_tmp=`echo $i | sed "s#$ac_boost_path##" | sed 's/\/include\/boost-//' | sed 's/_/./'` - V_CHECK=`expr $_version_tmp \> $_version` - if test "$V_CHECK" = "1" ; then - _version=$_version_tmp - best_path=$ac_boost_path - fi - done - fi - done - - VERSION_UNDERSCORE=`echo $_version | sed 's/\./_/'` - BOOST_CPPFLAGS="-I$best_path/include/boost-$VERSION_UNDERSCORE" - if test "$ac_boost_lib_path" = ""; then - for libsubdir in $libsubdirs ; do - if ls "$best_path/$libsubdir/libboost_"* >/dev/null 2>&1 ; then break; fi - done - BOOST_LDFLAGS="-L$best_path/$libsubdir" - fi - fi - - if test "x$BOOST_ROOT" != "x"; then - for libsubdir in $libsubdirs ; do - if ls "$BOOST_ROOT/stage/$libsubdir/libboost_"* >/dev/null 2>&1 ; then break; fi - done - if test -d "$BOOST_ROOT" && test -r "$BOOST_ROOT" && test -d "$BOOST_ROOT/stage/$libsubdir" && test -r "$BOOST_ROOT/stage/$libsubdir"; then - version_dir=`expr //$BOOST_ROOT : '.*/\(.*\)'` - stage_version=`echo $version_dir | sed 's/boost_//' | sed 's/_/./g'` - stage_version_shorten=`expr $stage_version : '\([0-9]*\.[0-9]*\)'` - V_CHECK=`expr $stage_version_shorten \>\= $_version` - if test "$V_CHECK" = "1" -a "$ac_boost_lib_path" = "" ; then - { $as_echo "$as_me:${as_lineno-$LINENO}: We will use a staged boost library from $BOOST_ROOT" >&5 -$as_echo "$as_me: We will use a staged boost library from $BOOST_ROOT" >&6;} - BOOST_CPPFLAGS="-I$BOOST_ROOT" - BOOST_LDFLAGS="-L$BOOST_ROOT/stage/$libsubdir" - fi - fi - fi - fi - - CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS" - export CPPFLAGS - LDFLAGS="$LDFLAGS $BOOST_LDFLAGS" - export LDFLAGS - - ac_ext=cpp -ac_cpp='$CXXCPP $CPPFLAGS' -ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_cxx_compiler_gnu - - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - - #include - -int -main () -{ - - #if BOOST_VERSION >= $WANT_BOOST_VERSION - // Everything is okay - #else - # error Boost version is too old - #endif - - ; - return 0; -} -_ACEOF -if ac_fn_cxx_try_compile "$LINENO"; then : - - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } - succeeded=yes - found_system=yes - -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - ac_ext=cpp -ac_cpp='$CXXCPP $CPPFLAGS' -ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_cxx_compiler_gnu - - fi - - if test "$succeeded" != "yes" ; then - if test "$_version" = "0" ; then - { $as_echo "$as_me:${as_lineno-$LINENO}: We could not detect the boost libraries (version $boost_lib_version_req_shorten or higher). If you have a staged boost library (still not installed) please specify \$BOOST_ROOT in your environment and do not give a PATH to --with-boost option. If you are sure you have boost installed, then check your version number looking in . See http://randspringer.de/boost for more documentation." >&5 -$as_echo "$as_me: We could not detect the boost libraries (version $boost_lib_version_req_shorten or higher). If you have a staged boost library (still not installed) please specify \$BOOST_ROOT in your environment and do not give a PATH to --with-boost option. If you are sure you have boost installed, then check your version number looking in . See http://randspringer.de/boost for more documentation." >&6;} - else - { $as_echo "$as_me:${as_lineno-$LINENO}: Your boost libraries seems to old (version $_version)." >&5 -$as_echo "$as_me: Your boost libraries seems to old (version $_version)." >&6;} - fi - # execute ACTION-IF-NOT-FOUND (if present): - : - else - - - -$as_echo "#define HAVE_BOOST /**/" >>confdefs.h - - # execute ACTION-IF-FOUND (if present): - : - fi - - CPPFLAGS="$CPPFLAGS_SAVED" - LDFLAGS="$LDFLAGS_SAVED" -fi - - -# HAVE_BOOST is set to an empty value when Boost is found. I don't know -# how to test for a set vs unset variable. -if test "x$BOOST_CPPFLAGS" = "x"; then : - as_fn_error $? "Could not find Boost" "$LINENO" 5 -else - { $as_echo "$as_me:${as_lineno-$LINENO}: Boost CPPFLAGS: $BOOST_CPPFLAGS" >&5 -$as_echo "$as_me: Boost CPPFLAGS: $BOOST_CPPFLAGS" >&6;} - CPPFLAGS="$BOOST_CPPFLAGS $CPPFLAGS" - LDFLAGS="$BOOST_LDFLAGS $LDFLAGS" -fi - - - -# Check whether --with-boost-system was given. -if test "${with_boost_system+set}" = set; then : - withval=$with_boost_system; - if test "$withval" = "no"; then - want_boost="no" - elif test "$withval" = "yes"; then - want_boost="yes" - ax_boost_user_system_lib="" - else - want_boost="yes" - ax_boost_user_system_lib="$withval" - fi - -else - want_boost="yes" - -fi - - - if test "x$want_boost" = "xyes"; then - - - CPPFLAGS_SAVED="$CPPFLAGS" - CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS" - export CPPFLAGS - - LDFLAGS_SAVED="$LDFLAGS" - LDFLAGS="$LDFLAGS $BOOST_LDFLAGS" - export LDFLAGS - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the Boost::System library is available" >&5 -$as_echo_n "checking whether the Boost::System library is available... " >&6; } -if ${ax_cv_boost_system+:} false; then : - $as_echo_n "(cached) " >&6 -else - ac_ext=cpp -ac_cpp='$CXXCPP $CPPFLAGS' -ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_cxx_compiler_gnu - - CXXFLAGS_SAVE=$CXXFLAGS - CXXFLAGS= - - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include -int -main () -{ -boost::system::error_category *a = 0; - ; - return 0; -} -_ACEOF -if ac_fn_cxx_try_compile "$LINENO"; then : - ax_cv_boost_system=yes -else - ax_cv_boost_system=no -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - CXXFLAGS=$CXXFLAGS_SAVE - ac_ext=cpp -ac_cpp='$CXXCPP $CPPFLAGS' -ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_cxx_compiler_gnu - - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_boost_system" >&5 -$as_echo "$ax_cv_boost_system" >&6; } - if test "x$ax_cv_boost_system" = "xyes"; then - - - -$as_echo "#define HAVE_BOOST_SYSTEM /**/" >>confdefs.h - - BOOSTLIBDIR=`echo $BOOST_LDFLAGS | sed -e 's/[^\/]*//'` - - LDFLAGS_SAVE=$LDFLAGS - if test "x$ax_boost_user_system_lib" = "x"; then - for libextension in `ls -r $BOOSTLIBDIR/libboost_system* 2>/dev/null | sed 's,.*/lib,,' | sed 's,\..*,,'` ; do - ax_lib=${libextension} - as_ac_Lib=`$as_echo "ac_cv_lib_$ax_lib''_exit" | $as_tr_sh` -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for exit in -l$ax_lib" >&5 -$as_echo_n "checking for exit in -l$ax_lib... " >&6; } -if eval \${$as_ac_Lib+:} false; then : - $as_echo_n "(cached) " >&6 -else - ac_check_lib_save_LIBS=$LIBS -LIBS="-l$ax_lib $LIBS" -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -/* Override any GCC internal prototype to avoid an error. - Use char because int might match the return type of a GCC - builtin and then its argument prototype would still apply. */ -#ifdef __cplusplus -extern "C" -#endif -char exit (); -int -main () -{ -return exit (); - ; - return 0; -} -_ACEOF -if ac_fn_cxx_try_link "$LINENO"; then : - eval "$as_ac_Lib=yes" -else - eval "$as_ac_Lib=no" -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -eval ac_res=\$$as_ac_Lib - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 -$as_echo "$ac_res" >&6; } -if eval test \"x\$"$as_ac_Lib"\" = x"yes"; then : - BOOST_SYSTEM_LIB="-l$ax_lib"; link_system="yes"; break -else - link_system="no" -fi - - done - if test "x$link_system" != "xyes"; then - for libextension in `ls -r $BOOSTLIBDIR/boost_system* 2>/dev/null | sed 's,.*/,,' | sed -e 's,\..*,,'` ; do - ax_lib=${libextension} - as_ac_Lib=`$as_echo "ac_cv_lib_$ax_lib''_exit" | $as_tr_sh` -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for exit in -l$ax_lib" >&5 -$as_echo_n "checking for exit in -l$ax_lib... " >&6; } -if eval \${$as_ac_Lib+:} false; then : - $as_echo_n "(cached) " >&6 -else - ac_check_lib_save_LIBS=$LIBS -LIBS="-l$ax_lib $LIBS" -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -/* Override any GCC internal prototype to avoid an error. - Use char because int might match the return type of a GCC - builtin and then its argument prototype would still apply. */ -#ifdef __cplusplus -extern "C" -#endif -char exit (); -int -main () -{ -return exit (); - ; - return 0; -} -_ACEOF -if ac_fn_cxx_try_link "$LINENO"; then : - eval "$as_ac_Lib=yes" -else - eval "$as_ac_Lib=no" -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -eval ac_res=\$$as_ac_Lib - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 -$as_echo "$ac_res" >&6; } -if eval test \"x\$"$as_ac_Lib"\" = x"yes"; then : - BOOST_SYSTEM_LIB="-l$ax_lib"; link_system="yes"; break -else - link_system="no" -fi - - done - fi - - else - for ax_lib in $ax_boost_user_system_lib boost_system-$ax_boost_user_system_lib; do - as_ac_Lib=`$as_echo "ac_cv_lib_$ax_lib''_exit" | $as_tr_sh` -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for exit in -l$ax_lib" >&5 -$as_echo_n "checking for exit in -l$ax_lib... " >&6; } -if eval \${$as_ac_Lib+:} false; then : - $as_echo_n "(cached) " >&6 -else - ac_check_lib_save_LIBS=$LIBS -LIBS="-l$ax_lib $LIBS" -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -/* Override any GCC internal prototype to avoid an error. - Use char because int might match the return type of a GCC - builtin and then its argument prototype would still apply. */ -#ifdef __cplusplus -extern "C" -#endif -char exit (); -int -main () -{ -return exit (); - ; - return 0; -} -_ACEOF -if ac_fn_cxx_try_link "$LINENO"; then : - eval "$as_ac_Lib=yes" -else - eval "$as_ac_Lib=no" -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -eval ac_res=\$$as_ac_Lib - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 -$as_echo "$ac_res" >&6; } -if eval test \"x\$"$as_ac_Lib"\" = x"yes"; then : - BOOST_SYSTEM_LIB="-l$ax_lib"; link_system="yes"; break -else - link_system="no" -fi - - done - - fi - if test "x$ax_lib" = "x"; then - as_fn_error $? "Could not find a version of the library!" "$LINENO" 5 - fi - if test "x$link_system" = "xno"; then - as_fn_error $? "Could not link against $ax_lib !" "$LINENO" 5 - fi - fi - - CPPFLAGS="$CPPFLAGS_SAVED" - LDFLAGS="$LDFLAGS_SAVED" - fi - -# HAVE_BOOST_SYSTEM is set to an empty value when Boost.System is found. -# I don't know how to test for a set vs unset variable. -if test "x$BOOST_SYSTEM_LIB" = "x"; then : - as_fn_error $? "Could not find Boost.System" "$LINENO" 5 -else - { $as_echo "$as_me:${as_lineno-$LINENO}: Boost.System LIB: $BOOST_SYSTEM_LIB" >&5 -$as_echo "$as_me: Boost.System LIB: $BOOST_SYSTEM_LIB" >&6;} - LIBS="$BOOST_SYSTEM_LIB $LIBS" -fi - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking which qtsingleapplication to use" >&5 -$as_echo_n "checking which qtsingleapplication to use... " >&6; } -case "x$with_qtsingleapplication" in #( - "xshipped") : - { $as_echo "$as_me:${as_lineno-$LINENO}: result: shipped" >&5 -$as_echo "shipped" >&6; } - QBT_REMOVE_CONFIG="$QBT_REMOVE_CONFIG usesystemqtsingleapplication" ;; #( - "xsystem") : - { $as_echo "$as_me:${as_lineno-$LINENO}: result: system" >&5 -$as_echo "system" >&6; } - QBT_ADD_CONFIG="$QBT_ADD_CONFIG usesystemqtsingleapplication" ;; #( - *) : - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_qtsingleapplication" >&5 -$as_echo "$with_qtsingleapplication" >&6; } - as_fn_error $? "Unknown option \"$with_qtsingleapplication\". Use either \"system\" or \"shipped\"." "$LINENO" 5 ;; -esac - - -pkg_failed=no -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for libtorrent" >&5 -$as_echo_n "checking for libtorrent... " >&6; } - -if test -n "$libtorrent_CFLAGS"; then - pkg_cv_libtorrent_CFLAGS="$libtorrent_CFLAGS" - elif test -n "$PKG_CONFIG"; then - if test -n "$PKG_CONFIG" && \ - { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libtorrent-rasterbar >= 1.0.6\""; } >&5 - ($PKG_CONFIG --exists --print-errors "libtorrent-rasterbar >= 1.0.6") 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; }; then - pkg_cv_libtorrent_CFLAGS=`$PKG_CONFIG --cflags "libtorrent-rasterbar >= 1.0.6" 2>/dev/null` - test "x$?" != "x0" && pkg_failed=yes -else - pkg_failed=yes -fi - else - pkg_failed=untried -fi -if test -n "$libtorrent_LIBS"; then - pkg_cv_libtorrent_LIBS="$libtorrent_LIBS" - elif test -n "$PKG_CONFIG"; then - if test -n "$PKG_CONFIG" && \ - { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libtorrent-rasterbar >= 1.0.6\""; } >&5 - ($PKG_CONFIG --exists --print-errors "libtorrent-rasterbar >= 1.0.6") 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; }; then - pkg_cv_libtorrent_LIBS=`$PKG_CONFIG --libs "libtorrent-rasterbar >= 1.0.6" 2>/dev/null` - test "x$?" != "x0" && pkg_failed=yes -else - pkg_failed=yes -fi - else - pkg_failed=untried -fi - - - -if test $pkg_failed = yes; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } - -if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then - _pkg_short_errors_supported=yes -else - _pkg_short_errors_supported=no -fi - if test $_pkg_short_errors_supported = yes; then - libtorrent_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libtorrent-rasterbar >= 1.0.6" 2>&1` - else - libtorrent_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libtorrent-rasterbar >= 1.0.6" 2>&1` - fi - # Put the nasty error message in config.log where it belongs - echo "$libtorrent_PKG_ERRORS" >&5 - - as_fn_error $? "Package requirements (libtorrent-rasterbar >= 1.0.6) were not met: - -$libtorrent_PKG_ERRORS - -Consider adjusting the PKG_CONFIG_PATH environment variable if you -installed software in a non-standard prefix. - -Alternatively, you may set the environment variables libtorrent_CFLAGS -and libtorrent_LIBS to avoid the need to call pkg-config. -See the pkg-config man page for more details." "$LINENO" 5 -elif test $pkg_failed = untried; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } - { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 -$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -as_fn_error $? "The pkg-config script could not be found or is too old. Make sure it -is in your PATH or set the PKG_CONFIG environment variable to the full -path to pkg-config. - -Alternatively, you may set the environment variables libtorrent_CFLAGS -and libtorrent_LIBS to avoid the need to call pkg-config. -See the pkg-config man page for more details. - -To get pkg-config, see . -See \`config.log' for more details" "$LINENO" 5; } -else - libtorrent_CFLAGS=$pkg_cv_libtorrent_CFLAGS - libtorrent_LIBS=$pkg_cv_libtorrent_LIBS - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } - CPPFLAGS="$libtorrent_CFLAGS $CPPFLAGS" - LIBS="$libtorrent_LIBS $LIBS" -fi - - -pkg_failed=no -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for zlib" >&5 -$as_echo_n "checking for zlib... " >&6; } - -if test -n "$zlib_CFLAGS"; then - pkg_cv_zlib_CFLAGS="$zlib_CFLAGS" - elif test -n "$PKG_CONFIG"; then - if test -n "$PKG_CONFIG" && \ - { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"zlib >= 1.2.5.2\""; } >&5 - ($PKG_CONFIG --exists --print-errors "zlib >= 1.2.5.2") 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; }; then - pkg_cv_zlib_CFLAGS=`$PKG_CONFIG --cflags "zlib >= 1.2.5.2" 2>/dev/null` - test "x$?" != "x0" && pkg_failed=yes -else - pkg_failed=yes -fi - else - pkg_failed=untried -fi -if test -n "$zlib_LIBS"; then - pkg_cv_zlib_LIBS="$zlib_LIBS" - elif test -n "$PKG_CONFIG"; then - if test -n "$PKG_CONFIG" && \ - { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"zlib >= 1.2.5.2\""; } >&5 - ($PKG_CONFIG --exists --print-errors "zlib >= 1.2.5.2") 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; }; then - pkg_cv_zlib_LIBS=`$PKG_CONFIG --libs "zlib >= 1.2.5.2" 2>/dev/null` - test "x$?" != "x0" && pkg_failed=yes -else - pkg_failed=yes -fi - else - pkg_failed=untried -fi - - - -if test $pkg_failed = yes; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } - -if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then - _pkg_short_errors_supported=yes -else - _pkg_short_errors_supported=no -fi - if test $_pkg_short_errors_supported = yes; then - zlib_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "zlib >= 1.2.5.2" 2>&1` - else - zlib_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "zlib >= 1.2.5.2" 2>&1` - fi - # Put the nasty error message in config.log where it belongs - echo "$zlib_PKG_ERRORS" >&5 - - as_fn_error $? "Package requirements (zlib >= 1.2.5.2) were not met: - -$zlib_PKG_ERRORS - -Consider adjusting the PKG_CONFIG_PATH environment variable if you -installed software in a non-standard prefix. - -Alternatively, you may set the environment variables zlib_CFLAGS -and zlib_LIBS to avoid the need to call pkg-config. -See the pkg-config man page for more details." "$LINENO" 5 -elif test $pkg_failed = untried; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } - { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 -$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -as_fn_error $? "The pkg-config script could not be found or is too old. Make sure it -is in your PATH or set the PKG_CONFIG environment variable to the full -path to pkg-config. - -Alternatively, you may set the environment variables zlib_CFLAGS -and zlib_LIBS to avoid the need to call pkg-config. -See the pkg-config man page for more details. - -To get pkg-config, see . -See \`config.log' for more details" "$LINENO" 5; } -else - zlib_CFLAGS=$pkg_cv_zlib_CFLAGS - zlib_LIBS=$pkg_cv_zlib_LIBS - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } - CPPFLAGS="$zlib_CFLAGS $CPPFLAGS" - LIBS="$zlib_LIBS $LIBS" -fi - -# These are required because autoconf doesn't expand these **particular** -# vars automatically. And qmake cannot autoexpand them. - - prefix_NONE= - exec_prefix_NONE= - test "x$prefix" = xNONE && prefix_NONE=yes && prefix=$ac_default_prefix - test "x$exec_prefix" = xNONE && exec_prefix_NONE=yes && exec_prefix=$prefix - eval ax_define_dir="\"$prefix\"" - eval ax_define_dir="\"$ax_define_dir\"" - EXPAND_PREFIX="$ax_define_dir" - - cat >>confdefs.h <<_ACEOF -#define EXPAND_PREFIX "$ax_define_dir" -_ACEOF - - test "$prefix_NONE" && prefix=NONE - test "$exec_prefix_NONE" && exec_prefix=NONE - - - prefix_NONE= - exec_prefix_NONE= - test "x$prefix" = xNONE && prefix_NONE=yes && prefix=$ac_default_prefix - test "x$exec_prefix" = xNONE && exec_prefix_NONE=yes && exec_prefix=$prefix - eval ax_define_dir="\"$bindir\"" - eval ax_define_dir="\"$ax_define_dir\"" - EXPAND_BINDIR="$ax_define_dir" - - cat >>confdefs.h <<_ACEOF -#define EXPAND_BINDIR "$ax_define_dir" -_ACEOF - - test "$prefix_NONE" && prefix=NONE - test "$exec_prefix_NONE" && exec_prefix=NONE - - - prefix_NONE= - exec_prefix_NONE= - test "x$prefix" = xNONE && prefix_NONE=yes && prefix=$ac_default_prefix - test "x$exec_prefix" = xNONE && exec_prefix_NONE=yes && exec_prefix=$prefix - eval ax_define_dir="\"$datadir\"" - eval ax_define_dir="\"$ax_define_dir\"" - EXPAND_DATADIR="$ax_define_dir" - - cat >>confdefs.h <<_ACEOF -#define EXPAND_DATADIR "$ax_define_dir" -_ACEOF - - test "$prefix_NONE" && prefix=NONE - test "$exec_prefix_NONE" && exec_prefix=NONE - - - prefix_NONE= - exec_prefix_NONE= - test "x$prefix" = xNONE && prefix_NONE=yes && prefix=$ac_default_prefix - test "x$exec_prefix" = xNONE && exec_prefix_NONE=yes && exec_prefix=$prefix - eval ax_define_dir="\"$mandir\"" - eval ax_define_dir="\"$ax_define_dir\"" - EXPAND_MANDIR="$ax_define_dir" - - cat >>confdefs.h <<_ACEOF -#define EXPAND_MANDIR "$ax_define_dir" -_ACEOF - - test "$prefix_NONE" && prefix=NONE - test "$exec_prefix_NONE" && exec_prefix=NONE - - -# Original extract() function contributed by pmzqla -# $*: Strings to parse -# Set $QBT_CONF_DEFINES, $QBT_CONF_INCLUDES, $QBT_CONF_EXTRA_CFLAGS -extract() { - if [ -z "$*" ]; then - echo "Input string required" - return 1 - fi - - # BSD sed needs an actual newline character in the substitute command - new_line=' -' - # Convert " -" to "\n" if not between quotes and remove possible leading white spaces - string=$(echo " $*" | $SED -e "s: -:\\${new_line}:g" -e 's:"\(.*\)\n\(.*\)":\"\1 -\2":g' -e "s:'\(.*\)\n\(.*\)':\'\1 -\2':g" -e 's/^[:space:]*//') - SAVEIFS=$IFS - IFS=$(printf "\n\b") - for i in $string; do - case "$(echo "$i" | cut -c1)" in - '') ;; - D) QBT_CONF_DEFINES="$(echo $i | cut -c2-) $QBT_CONF_DEFINES";; - I) QBT_CONF_INCLUDES="$(echo $i | cut -c2-) $QBT_CONF_INCLUDES";; - *) QBT_CONF_EXTRA_CFLAGS="-$i $QBT_CONF_EXTRA_CFLAGS";; - esac - done - IFS=$SAVEIFS -} - -extract $CPPFLAGS -QBT_ADD_DEFINES="$QBT_ADD_DEFINES $QBT_CONF_DEFINES" -QBT_CONF_EXTRA_CFLAGS="$QBT_CONF_EXTRA_CFLAGS $CXXFLAGS" - -# Substitute the values of these vars in conf.pri.in - - - - - - - -ac_config_files="$ac_config_files conf.pri" - -cat >confcache <<\_ACEOF -# This file is a shell script that caches the results of configure -# tests run on this system so they can be shared between configure -# scripts and configure runs, see configure's option --config-cache. -# It is not useful on other systems. If it contains results you don't -# want to keep, you may remove or edit it. -# -# config.status only pays attention to the cache file if you give it -# the --recheck option to rerun configure. -# -# `ac_cv_env_foo' variables (set or unset) will be overridden when -# loading this file, other *unset* `ac_cv_foo' will be assigned the -# following values. - -_ACEOF - -# The following way of writing the cache mishandles newlines in values, -# but we know of no workaround that is simple, portable, and efficient. -# So, we kill variables containing newlines. -# Ultrix sh set writes to stderr and can't be redirected directly, -# and sets the high bit in the cache file unless we assign to the vars. -( - for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do - eval ac_val=\$$ac_var - case $ac_val in #( - *${as_nl}*) - case $ac_var in #( - *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 -$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; - esac - case $ac_var in #( - _ | IFS | as_nl) ;; #( - BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( - *) { eval $ac_var=; unset $ac_var;} ;; - esac ;; - esac - done - - (set) 2>&1 | - case $as_nl`(ac_space=' '; set) 2>&1` in #( - *${as_nl}ac_space=\ *) - # `set' does not quote correctly, so add quotes: double-quote - # substitution turns \\\\ into \\, and sed turns \\ into \. - sed -n \ - "s/'/'\\\\''/g; - s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" - ;; #( - *) - # `set' quotes correctly as required by POSIX, so do not add quotes. - sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" - ;; - esac | - sort -) | - sed ' - /^ac_cv_env_/b end - t clear - :clear - s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ - t end - s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ - :end' >>confcache -if diff "$cache_file" confcache >/dev/null 2>&1; then :; else - if test -w "$cache_file"; then - if test "x$cache_file" != "x/dev/null"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 -$as_echo "$as_me: updating cache $cache_file" >&6;} - if test ! -f "$cache_file" || test -h "$cache_file"; then - cat confcache >"$cache_file" - else - case $cache_file in #( - */* | ?:*) - mv -f confcache "$cache_file"$$ && - mv -f "$cache_file"$$ "$cache_file" ;; #( - *) - mv -f confcache "$cache_file" ;; - esac - fi - fi - else - { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 -$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} - fi -fi -rm -f confcache - -test "x$prefix" = xNONE && prefix=$ac_default_prefix -# Let make expand exec_prefix. -test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' - -# Transform confdefs.h into DEFS. -# Protect against shell expansion while executing Makefile rules. -# Protect against Makefile macro expansion. -# -# If the first sed substitution is executed (which looks for macros that -# take arguments), then branch to the quote section. Otherwise, -# look for a macro that doesn't take arguments. -ac_script=' -:mline -/\\$/{ - N - s,\\\n,, - b mline -} -t clear -:clear -s/^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*([^)]*)\)[ ]*\(.*\)/-D\1=\2/g -t quote -s/^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\)/-D\1=\2/g -t quote -b any -:quote -s/[ `~#$^&*(){}\\|;'\''"<>?]/\\&/g -s/\[/\\&/g -s/\]/\\&/g -s/\$/$$/g -H -:any -${ - g - s/^\n// - s/\n/ /g - p -} -' -DEFS=`sed -n "$ac_script" confdefs.h` - - -ac_libobjs= -ac_ltlibobjs= -U= -for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue - # 1. Remove the extension, and $U if already installed. - ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' - ac_i=`$as_echo "$ac_i" | sed "$ac_script"` - # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR - # will be set to the directory where LIBOBJS objects are built. - as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" - as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' -done -LIBOBJS=$ac_libobjs - -LTLIBOBJS=$ac_ltlibobjs - - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking that generated files are newer than configure" >&5 -$as_echo_n "checking that generated files are newer than configure... " >&6; } - if test -n "$am_sleep_pid"; then - # Hide warnings about reused PIDs. - wait $am_sleep_pid 2>/dev/null - fi - { $as_echo "$as_me:${as_lineno-$LINENO}: result: done" >&5 -$as_echo "done" >&6; } -if test -z "${AMDEP_TRUE}" && test -z "${AMDEP_FALSE}"; then - as_fn_error $? "conditional \"AMDEP\" was never defined. -Usually this means the macro was only invoked conditionally." "$LINENO" 5 -fi -if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then - as_fn_error $? "conditional \"am__fastdepCC\" was never defined. -Usually this means the macro was only invoked conditionally." "$LINENO" 5 -fi -if test -z "${am__fastdepCXX_TRUE}" && test -z "${am__fastdepCXX_FALSE}"; then - as_fn_error $? "conditional \"am__fastdepCXX\" was never defined. -Usually this means the macro was only invoked conditionally." "$LINENO" 5 -fi - if test -n "$EXEEXT"; then - am__EXEEXT_TRUE= - am__EXEEXT_FALSE='#' -else - am__EXEEXT_TRUE='#' - am__EXEEXT_FALSE= -fi - - -: "${CONFIG_STATUS=./config.status}" -ac_write_fail=0 -ac_clean_files_save=$ac_clean_files -ac_clean_files="$ac_clean_files $CONFIG_STATUS" -{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 -$as_echo "$as_me: creating $CONFIG_STATUS" >&6;} -as_write_fail=0 -cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 -#! $SHELL -# Generated by $as_me. -# Run this file to recreate the current configuration. -# Compiler output produced by configure, useful for debugging -# configure, is in config.log if it exists. - -debug=false -ac_cs_recheck=false -ac_cs_silent=false - -SHELL=\${CONFIG_SHELL-$SHELL} -export SHELL -_ASEOF -cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 -## -------------------- ## -## M4sh Initialization. ## -## -------------------- ## - -# Be more Bourne compatible -DUALCASE=1; export DUALCASE # for MKS sh -if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : - emulate sh - NULLCMD=: - # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which - # is contrary to our usage. Disable this feature. - alias -g '${1+"$@"}'='"$@"' - setopt NO_GLOB_SUBST -else - case `(set -o) 2>/dev/null` in #( - *posix*) : - set -o posix ;; #( - *) : - ;; -esac -fi - - -as_nl=' -' -export as_nl -# Printing a long string crashes Solaris 7 /usr/bin/printf. -as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' -as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo -as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo -# Prefer a ksh shell builtin over an external printf program on Solaris, -# but without wasting forks for bash or zsh. -if test -z "$BASH_VERSION$ZSH_VERSION" \ - && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then - as_echo='print -r --' - as_echo_n='print -rn --' -elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then - as_echo='printf %s\n' - as_echo_n='printf %s' -else - if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then - as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' - as_echo_n='/usr/ucb/echo -n' - else - as_echo_body='eval expr "X$1" : "X\\(.*\\)"' - as_echo_n_body='eval - arg=$1; - case $arg in #( - *"$as_nl"*) - expr "X$arg" : "X\\(.*\\)$as_nl"; - arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; - esac; - expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" - ' - export as_echo_n_body - as_echo_n='sh -c $as_echo_n_body as_echo' - fi - export as_echo_body - as_echo='sh -c $as_echo_body as_echo' -fi - -# The user is always right. -if test "${PATH_SEPARATOR+set}" != set; then - PATH_SEPARATOR=: - (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { - (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || - PATH_SEPARATOR=';' - } -fi - - -# IFS -# We need space, tab and new line, in precisely that order. Quoting is -# there to prevent editors from complaining about space-tab. -# (If _AS_PATH_WALK were called with IFS unset, it would disable word -# splitting by setting IFS to empty value.) -IFS=" "" $as_nl" - -# Find who we are. Look in the path if we contain no directory separator. -as_myself= -case $0 in #(( - *[\\/]* ) as_myself=$0 ;; - *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break - done -IFS=$as_save_IFS - - ;; -esac -# We did not find ourselves, most probably we were run as `sh COMMAND' -# in which case we are not to be found in the path. -if test "x$as_myself" = x; then - as_myself=$0 -fi -if test ! -f "$as_myself"; then - $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 - exit 1 -fi - -# Unset variables that we do not need and which cause bugs (e.g. in -# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" -# suppresses any "Segmentation fault" message there. '((' could -# trigger a bug in pdksh 5.2.14. -for as_var in BASH_ENV ENV MAIL MAILPATH -do eval test x\${$as_var+set} = xset \ - && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : -done -PS1='$ ' -PS2='> ' -PS4='+ ' - -# NLS nuisances. -LC_ALL=C -export LC_ALL -LANGUAGE=C -export LANGUAGE - -# CDPATH. -(unset CDPATH) >/dev/null 2>&1 && unset CDPATH - - -# as_fn_error STATUS ERROR [LINENO LOG_FD] -# ---------------------------------------- -# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are -# provided, also output the error to LOG_FD, referencing LINENO. Then exit the -# script with STATUS, using 1 if that was 0. -as_fn_error () -{ - as_status=$1; test $as_status -eq 0 && as_status=1 - if test "$4"; then - as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 - fi - $as_echo "$as_me: error: $2" >&2 - as_fn_exit $as_status -} # as_fn_error - - -# as_fn_set_status STATUS -# ----------------------- -# Set $? to STATUS, without forking. -as_fn_set_status () -{ - return $1 -} # as_fn_set_status - -# as_fn_exit STATUS -# ----------------- -# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. -as_fn_exit () -{ - set +e - as_fn_set_status $1 - exit $1 -} # as_fn_exit - -# as_fn_unset VAR -# --------------- -# Portably unset VAR. -as_fn_unset () -{ - { eval $1=; unset $1;} -} -as_unset=as_fn_unset -# as_fn_append VAR VALUE -# ---------------------- -# Append the text in VALUE to the end of the definition contained in VAR. Take -# advantage of any shell optimizations that allow amortized linear growth over -# repeated appends, instead of the typical quadratic growth present in naive -# implementations. -if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : - eval 'as_fn_append () - { - eval $1+=\$2 - }' -else - as_fn_append () - { - eval $1=\$$1\$2 - } -fi # as_fn_append - -# as_fn_arith ARG... -# ------------------ -# Perform arithmetic evaluation on the ARGs, and store the result in the -# global $as_val. Take advantage of shells that can avoid forks. The arguments -# must be portable across $(()) and expr. -if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : - eval 'as_fn_arith () - { - as_val=$(( $* )) - }' -else - as_fn_arith () - { - as_val=`expr "$@" || test $? -eq 1` - } -fi # as_fn_arith - - -if expr a : '\(a\)' >/dev/null 2>&1 && - test "X`expr 00001 : '.*\(...\)'`" = X001; then - as_expr=expr -else - as_expr=false -fi - -if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then - as_basename=basename -else - as_basename=false -fi - -if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then - as_dirname=dirname -else - as_dirname=false -fi - -as_me=`$as_basename -- "$0" || -$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ - X"$0" : 'X\(//\)$' \| \ - X"$0" : 'X\(/\)' \| . 2>/dev/null || -$as_echo X/"$0" | - sed '/^.*\/\([^/][^/]*\)\/*$/{ - s//\1/ - q - } - /^X\/\(\/\/\)$/{ - s//\1/ - q - } - /^X\/\(\/\).*/{ - s//\1/ - q - } - s/.*/./; q'` - -# Avoid depending upon Character Ranges. -as_cr_letters='abcdefghijklmnopqrstuvwxyz' -as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' -as_cr_Letters=$as_cr_letters$as_cr_LETTERS -as_cr_digits='0123456789' -as_cr_alnum=$as_cr_Letters$as_cr_digits - -ECHO_C= ECHO_N= ECHO_T= -case `echo -n x` in #((((( --n*) - case `echo 'xy\c'` in - *c*) ECHO_T=' ';; # ECHO_T is single tab character. - xy) ECHO_C='\c';; - *) echo `echo ksh88 bug on AIX 6.1` > /dev/null - ECHO_T=' ';; - esac;; -*) - ECHO_N='-n';; -esac - -rm -f conf$$ conf$$.exe conf$$.file -if test -d conf$$.dir; then - rm -f conf$$.dir/conf$$.file -else - rm -f conf$$.dir - mkdir conf$$.dir 2>/dev/null -fi -if (echo >conf$$.file) 2>/dev/null; then - if ln -s conf$$.file conf$$ 2>/dev/null; then - as_ln_s='ln -s' - # ... but there are two gotchas: - # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. - # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. - # In both cases, we have to default to `cp -pR'. - ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || - as_ln_s='cp -pR' - elif ln conf$$.file conf$$ 2>/dev/null; then - as_ln_s=ln - else - as_ln_s='cp -pR' - fi -else - as_ln_s='cp -pR' -fi -rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file -rmdir conf$$.dir 2>/dev/null - - -# as_fn_mkdir_p -# ------------- -# Create "$as_dir" as a directory, including parents if necessary. -as_fn_mkdir_p () -{ - - case $as_dir in #( - -*) as_dir=./$as_dir;; - esac - test -d "$as_dir" || eval $as_mkdir_p || { - as_dirs= - while :; do - case $as_dir in #( - *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( - *) as_qdir=$as_dir;; - esac - as_dirs="'$as_qdir' $as_dirs" - as_dir=`$as_dirname -- "$as_dir" || -$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$as_dir" : 'X\(//\)[^/]' \| \ - X"$as_dir" : 'X\(//\)$' \| \ - X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || -$as_echo X"$as_dir" | - sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ - s//\1/ - q - } - /^X\(\/\/\)[^/].*/{ - s//\1/ - q - } - /^X\(\/\/\)$/{ - s//\1/ - q - } - /^X\(\/\).*/{ - s//\1/ - q - } - s/.*/./; q'` - test -d "$as_dir" && break - done - test -z "$as_dirs" || eval "mkdir $as_dirs" - } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" - - -} # as_fn_mkdir_p -if mkdir -p . 2>/dev/null; then - as_mkdir_p='mkdir -p "$as_dir"' -else - test -d ./-p && rmdir ./-p - as_mkdir_p=false -fi - - -# as_fn_executable_p FILE -# ----------------------- -# Test if FILE is an executable regular file. -as_fn_executable_p () -{ - test -f "$1" && test -x "$1" -} # as_fn_executable_p -as_test_x='test -x' -as_executable_p=as_fn_executable_p - -# Sed expression to map a string onto a valid CPP name. -as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" - -# Sed expression to map a string onto a valid variable name. -as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" - - -exec 6>&1 -## ----------------------------------- ## -## Main body of $CONFIG_STATUS script. ## -## ----------------------------------- ## -_ASEOF -test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 - -cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 -# Save the log message, to keep $0 and so on meaningful, and to -# report actual input values of CONFIG_FILES etc. instead of their -# values after options handling. -ac_log=" -This file was extended by qbittorrent $as_me v3.2.0alpha, which was -generated by GNU Autoconf 2.69. Invocation command line was - - CONFIG_FILES = $CONFIG_FILES - CONFIG_HEADERS = $CONFIG_HEADERS - CONFIG_LINKS = $CONFIG_LINKS - CONFIG_COMMANDS = $CONFIG_COMMANDS - $ $0 $@ - -on `(hostname || uname -n) 2>/dev/null | sed 1q` -" - -_ACEOF - -case $ac_config_files in *" -"*) set x $ac_config_files; shift; ac_config_files=$*;; -esac - - - -cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 -# Files that config.status was made for. -config_files="$ac_config_files" -config_commands="$ac_config_commands" - -_ACEOF - -cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 -ac_cs_usage="\ -\`$as_me' instantiates files and other configuration actions -from templates according to the current configuration. Unless the files -and actions are specified as TAGs, all are instantiated by default. - -Usage: $0 [OPTION]... [TAG]... - - -h, --help print this help, then exit - -V, --version print version number and configuration settings, then exit - --config print configuration, then exit - -q, --quiet, --silent - do not print progress messages - -d, --debug don't remove temporary files - --recheck update $as_me by reconfiguring in the same conditions - --file=FILE[:TEMPLATE] - instantiate the configuration file FILE - -Configuration files: -$config_files - -Configuration commands: -$config_commands - -Report bugs to . -qbittorrent home page: ." - -_ACEOF -cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 -ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" -ac_cs_version="\\ -qbittorrent config.status v3.2.0alpha -configured by $0, generated by GNU Autoconf 2.69, - with options \\"\$ac_cs_config\\" - -Copyright (C) 2012 Free Software Foundation, Inc. -This config.status script is free software; the Free Software Foundation -gives unlimited permission to copy, distribute and modify it." - -ac_pwd='$ac_pwd' -srcdir='$srcdir' -INSTALL='$INSTALL' -MKDIR_P='$MKDIR_P' -AWK='$AWK' -test -n "\$AWK" || AWK=awk -_ACEOF - -cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 -# The default lists apply if the user does not specify any file. -ac_need_defaults=: -while test $# != 0 -do - case $1 in - --*=?*) - ac_option=`expr "X$1" : 'X\([^=]*\)='` - ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` - ac_shift=: - ;; - --*=) - ac_option=`expr "X$1" : 'X\([^=]*\)='` - ac_optarg= - ac_shift=: - ;; - *) - ac_option=$1 - ac_optarg=$2 - ac_shift=shift - ;; - esac - - case $ac_option in - # Handling of the options. - -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) - ac_cs_recheck=: ;; - --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) - $as_echo "$ac_cs_version"; exit ;; - --config | --confi | --conf | --con | --co | --c ) - $as_echo "$ac_cs_config"; exit ;; - --debug | --debu | --deb | --de | --d | -d ) - debug=: ;; - --file | --fil | --fi | --f ) - $ac_shift - case $ac_optarg in - *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; - '') as_fn_error $? "missing file argument" ;; - esac - as_fn_append CONFIG_FILES " '$ac_optarg'" - ac_need_defaults=false;; - --he | --h | --help | --hel | -h ) - $as_echo "$ac_cs_usage"; exit ;; - -q | -quiet | --quiet | --quie | --qui | --qu | --q \ - | -silent | --silent | --silen | --sile | --sil | --si | --s) - ac_cs_silent=: ;; - - # This is an error. - -*) as_fn_error $? "unrecognized option: \`$1' -Try \`$0 --help' for more information." ;; - - *) as_fn_append ac_config_targets " $1" - ac_need_defaults=false ;; - - esac - shift -done - -ac_configure_extra_args= - -if $ac_cs_silent; then - exec 6>/dev/null - ac_configure_extra_args="$ac_configure_extra_args --silent" -fi - -_ACEOF -cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 -if \$ac_cs_recheck; then - set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion - shift - \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 - CONFIG_SHELL='$SHELL' - export CONFIG_SHELL - exec "\$@" -fi - -_ACEOF -cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 -exec 5>>config.log -{ - echo - sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX -## Running $as_me. ## -_ASBOX - $as_echo "$ac_log" -} >&5 - -_ACEOF -cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 -# -# INIT-COMMANDS -# -AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir" - -_ACEOF - -cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 - -# Handling of arguments. -for ac_config_target in $ac_config_targets -do - case $ac_config_target in - "depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;; - "conf.pri") CONFIG_FILES="$CONFIG_FILES conf.pri" ;; - - *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; - esac -done - - -# If the user did not use the arguments to specify the items to instantiate, -# then the envvar interface is used. Set only those that are not. -# We use the long form for the default assignment because of an extremely -# bizarre bug on SunOS 4.1.3. -if $ac_need_defaults; then - test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files - test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands -fi - -# Have a temporary directory for convenience. Make it in the build tree -# simply because there is no reason against having it here, and in addition, -# creating and moving files from /tmp can sometimes cause problems. -# Hook for its removal unless debugging. -# Note that there is a small window in which the directory will not be cleaned: -# after its creation but before its name has been assigned to `$tmp'. -$debug || -{ - tmp= ac_tmp= - trap 'exit_status=$? - : "${ac_tmp:=$tmp}" - { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status -' 0 - trap 'as_fn_exit 1' 1 2 13 15 -} -# Create a (secure) tmp directory for tmp files. - -{ - tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && - test -d "$tmp" -} || -{ - tmp=./conf$$-$RANDOM - (umask 077 && mkdir "$tmp") -} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 -ac_tmp=$tmp - -# Set up the scripts for CONFIG_FILES section. -# No need to generate them if there are no CONFIG_FILES. -# This happens for instance with `./config.status config.h'. -if test -n "$CONFIG_FILES"; then - - -ac_cr=`echo X | tr X '\015'` -# On cygwin, bash can eat \r inside `` if the user requested igncr. -# But we know of no other shell where ac_cr would be empty at this -# point, so we can use a bashism as a fallback. -if test "x$ac_cr" = x; then - eval ac_cr=\$\'\\r\' -fi -ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` -if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then - ac_cs_awk_cr='\\r' -else - ac_cs_awk_cr=$ac_cr -fi - -echo 'BEGIN {' >"$ac_tmp/subs1.awk" && -_ACEOF - - -{ - echo "cat >conf$$subs.awk <<_ACEOF" && - echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && - echo "_ACEOF" -} >conf$$subs.sh || - as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 -ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'` -ac_delim='%!_!# ' -for ac_last_try in false false false false false :; do - . ./conf$$subs.sh || - as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 - - ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` - if test $ac_delim_n = $ac_delim_num; then - break - elif $ac_last_try; then - as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 - else - ac_delim="$ac_delim!$ac_delim _$ac_delim!! " - fi -done -rm -f conf$$subs.sh - -cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 -cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK && -_ACEOF -sed -n ' -h -s/^/S["/; s/!.*/"]=/ -p -g -s/^[^!]*!// -:repl -t repl -s/'"$ac_delim"'$// -t delim -:nl -h -s/\(.\{148\}\)..*/\1/ -t more1 -s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ -p -n -b repl -:more1 -s/["\\]/\\&/g; s/^/"/; s/$/"\\/ -p -g -s/.\{148\}// -t nl -:delim -h -s/\(.\{148\}\)..*/\1/ -t more2 -s/["\\]/\\&/g; s/^/"/; s/$/"/ -p -b -:more2 -s/["\\]/\\&/g; s/^/"/; s/$/"\\/ -p -g -s/.\{148\}// -t delim -' >$CONFIG_STATUS || ac_write_fail=1 -rm -f conf$$subs.awk -cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 -_ACAWK -cat >>"\$ac_tmp/subs1.awk" <<_ACAWK && - for (key in S) S_is_set[key] = 1 - FS = "" - -} -{ - line = $ 0 - nfields = split(line, field, "@") - substed = 0 - len = length(field[1]) - for (i = 2; i < nfields; i++) { - key = field[i] - keylen = length(key) - if (S_is_set[key]) { - value = S[key] - line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) - len += length(value) + length(field[++i]) - substed = 1 - } else - len += 1 + keylen - } - - print line -} - -_ACAWK -_ACEOF -cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 -if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then - sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" -else - cat -fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \ - || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 -_ACEOF - -# VPATH may cause trouble with some makes, so we remove sole $(srcdir), -# ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and -# trailing colons and then remove the whole line if VPATH becomes empty -# (actually we leave an empty line to preserve line numbers). -if test "x$srcdir" = x.; then - ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{ -h -s/// -s/^/:/ -s/[ ]*$/:/ -s/:\$(srcdir):/:/g -s/:\${srcdir}:/:/g -s/:@srcdir@:/:/g -s/^:*// -s/:*$// -x -s/\(=[ ]*\).*/\1/ -G -s/\n// -s/^[^=]*=[ ]*$// -}' -fi - -cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 -fi # test -n "$CONFIG_FILES" - - -eval set X " :F $CONFIG_FILES :C $CONFIG_COMMANDS" -shift -for ac_tag -do - case $ac_tag in - :[FHLC]) ac_mode=$ac_tag; continue;; - esac - case $ac_mode$ac_tag in - :[FHL]*:*);; - :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;; - :[FH]-) ac_tag=-:-;; - :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; - esac - ac_save_IFS=$IFS - IFS=: - set x $ac_tag - IFS=$ac_save_IFS - shift - ac_file=$1 - shift - - case $ac_mode in - :L) ac_source=$1;; - :[FH]) - ac_file_inputs= - for ac_f - do - case $ac_f in - -) ac_f="$ac_tmp/stdin";; - *) # Look for the file first in the build tree, then in the source tree - # (if the path is not absolute). The absolute path cannot be DOS-style, - # because $ac_f cannot contain `:'. - test -f "$ac_f" || - case $ac_f in - [\\/$]*) false;; - *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; - esac || - as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;; - esac - case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac - as_fn_append ac_file_inputs " '$ac_f'" - done - - # Let's still pretend it is `configure' which instantiates (i.e., don't - # use $as_me), people would be surprised to read: - # /* config.h. Generated by config.status. */ - configure_input='Generated from '` - $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' - `' by configure.' - if test x"$ac_file" != x-; then - configure_input="$ac_file. $configure_input" - { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 -$as_echo "$as_me: creating $ac_file" >&6;} - fi - # Neutralize special characters interpreted by sed in replacement strings. - case $configure_input in #( - *\&* | *\|* | *\\* ) - ac_sed_conf_input=`$as_echo "$configure_input" | - sed 's/[\\\\&|]/\\\\&/g'`;; #( - *) ac_sed_conf_input=$configure_input;; - esac - - case $ac_tag in - *:-:* | *:-) cat >"$ac_tmp/stdin" \ - || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; - esac - ;; - esac - - ac_dir=`$as_dirname -- "$ac_file" || -$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$ac_file" : 'X\(//\)[^/]' \| \ - X"$ac_file" : 'X\(//\)$' \| \ - X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || -$as_echo X"$ac_file" | - sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ - s//\1/ - q - } - /^X\(\/\/\)[^/].*/{ - s//\1/ - q - } - /^X\(\/\/\)$/{ - s//\1/ - q - } - /^X\(\/\).*/{ - s//\1/ - q - } - s/.*/./; q'` - as_dir="$ac_dir"; as_fn_mkdir_p - ac_builddir=. - -case "$ac_dir" in -.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; -*) - ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` - # A ".." for each directory in $ac_dir_suffix. - ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` - case $ac_top_builddir_sub in - "") ac_top_builddir_sub=. ac_top_build_prefix= ;; - *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; - esac ;; -esac -ac_abs_top_builddir=$ac_pwd -ac_abs_builddir=$ac_pwd$ac_dir_suffix -# for backward compatibility: -ac_top_builddir=$ac_top_build_prefix - -case $srcdir in - .) # We are building in place. - ac_srcdir=. - ac_top_srcdir=$ac_top_builddir_sub - ac_abs_top_srcdir=$ac_pwd ;; - [\\/]* | ?:[\\/]* ) # Absolute name. - ac_srcdir=$srcdir$ac_dir_suffix; - ac_top_srcdir=$srcdir - ac_abs_top_srcdir=$srcdir ;; - *) # Relative name. - ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix - ac_top_srcdir=$ac_top_build_prefix$srcdir - ac_abs_top_srcdir=$ac_pwd/$srcdir ;; -esac -ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix - - - case $ac_mode in - :F) - # - # CONFIG_FILE - # - - case $INSTALL in - [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; - *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;; - esac - ac_MKDIR_P=$MKDIR_P - case $MKDIR_P in - [\\/$]* | ?:[\\/]* ) ;; - */*) ac_MKDIR_P=$ac_top_build_prefix$MKDIR_P ;; - esac -_ACEOF - -cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 -# If the template does not know about datarootdir, expand it. -# FIXME: This hack should be removed a few years after 2.60. -ac_datarootdir_hack=; ac_datarootdir_seen= -ac_sed_dataroot=' -/datarootdir/ { - p - q -} -/@datadir@/p -/@docdir@/p -/@infodir@/p -/@localedir@/p -/@mandir@/p' -case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in -*datarootdir*) ac_datarootdir_seen=yes;; -*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 -$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} -_ACEOF -cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 - ac_datarootdir_hack=' - s&@datadir@&$datadir&g - s&@docdir@&$docdir&g - s&@infodir@&$infodir&g - s&@localedir@&$localedir&g - s&@mandir@&$mandir&g - s&\\\${datarootdir}&$datarootdir&g' ;; -esac -_ACEOF - -# Neutralize VPATH when `$srcdir' = `.'. -# Shell code in configure.ac might set extrasub. -# FIXME: do we really want to maintain this feature? -cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 -ac_sed_extra="$ac_vpsub -$extrasub -_ACEOF -cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 -:t -/@[a-zA-Z_][a-zA-Z_0-9]*@/!b -s|@configure_input@|$ac_sed_conf_input|;t t -s&@top_builddir@&$ac_top_builddir_sub&;t t -s&@top_build_prefix@&$ac_top_build_prefix&;t t -s&@srcdir@&$ac_srcdir&;t t -s&@abs_srcdir@&$ac_abs_srcdir&;t t -s&@top_srcdir@&$ac_top_srcdir&;t t -s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t -s&@builddir@&$ac_builddir&;t t -s&@abs_builddir@&$ac_abs_builddir&;t t -s&@abs_top_builddir@&$ac_abs_top_builddir&;t t -s&@INSTALL@&$ac_INSTALL&;t t -s&@MKDIR_P@&$ac_MKDIR_P&;t t -$ac_datarootdir_hack -" -eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \ - >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5 - -test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && - { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && - { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ - "$ac_tmp/out"`; test -z "$ac_out"; } && - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' -which seems to be undefined. Please make sure it is defined" >&5 -$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' -which seems to be undefined. Please make sure it is defined" >&2;} - - rm -f "$ac_tmp/stdin" - case $ac_file in - -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";; - *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";; - esac \ - || as_fn_error $? "could not create $ac_file" "$LINENO" 5 - ;; - - - :C) { $as_echo "$as_me:${as_lineno-$LINENO}: executing $ac_file commands" >&5 -$as_echo "$as_me: executing $ac_file commands" >&6;} - ;; - esac - - - case $ac_file$ac_mode in - "depfiles":C) test x"$AMDEP_TRUE" != x"" || { - # Older Autoconf quotes --file arguments for eval, but not when files - # are listed without --file. Let's play safe and only enable the eval - # if we detect the quoting. - case $CONFIG_FILES in - *\'*) eval set x "$CONFIG_FILES" ;; - *) set x $CONFIG_FILES ;; - esac - shift - for mf - do - # Strip MF so we end up with the name of the file. - mf=`echo "$mf" | sed -e 's/:.*$//'` - # Check whether this is an Automake generated Makefile or not. - # We used to match only the files named 'Makefile.in', but - # some people rename them; so instead we look at the file content. - # Grep'ing the first line is not enough: some people post-process - # each Makefile.in and add a new line on top of each file to say so. - # Grep'ing the whole file is not good either: AIX grep has a line - # limit of 2048, but all sed's we know have understand at least 4000. - if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then - dirpart=`$as_dirname -- "$mf" || -$as_expr X"$mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$mf" : 'X\(//\)[^/]' \| \ - X"$mf" : 'X\(//\)$' \| \ - X"$mf" : 'X\(/\)' \| . 2>/dev/null || -$as_echo X"$mf" | - sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ - s//\1/ - q - } - /^X\(\/\/\)[^/].*/{ - s//\1/ - q - } - /^X\(\/\/\)$/{ - s//\1/ - q - } - /^X\(\/\).*/{ - s//\1/ - q - } - s/.*/./; q'` - else - continue - fi - # Extract the definition of DEPDIR, am__include, and am__quote - # from the Makefile without running 'make'. - DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` - test -z "$DEPDIR" && continue - am__include=`sed -n 's/^am__include = //p' < "$mf"` - test -z "$am__include" && continue - am__quote=`sed -n 's/^am__quote = //p' < "$mf"` - # Find all dependency output files, they are included files with - # $(DEPDIR) in their names. We invoke sed twice because it is the - # simplest approach to changing $(DEPDIR) to its actual value in the - # expansion. - for file in `sed -n " - s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ - sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g'`; do - # Make sure the directory exists. - test -f "$dirpart/$file" && continue - fdir=`$as_dirname -- "$file" || -$as_expr X"$file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$file" : 'X\(//\)[^/]' \| \ - X"$file" : 'X\(//\)$' \| \ - X"$file" : 'X\(/\)' \| . 2>/dev/null || -$as_echo X"$file" | - sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ - s//\1/ - q - } - /^X\(\/\/\)[^/].*/{ - s//\1/ - q - } - /^X\(\/\/\)$/{ - s//\1/ - q - } - /^X\(\/\).*/{ - s//\1/ - q - } - s/.*/./; q'` - as_dir=$dirpart/$fdir; as_fn_mkdir_p - # echo "creating $dirpart/$file" - echo '# dummy' > "$dirpart/$file" - done - done -} - ;; - - esac -done # for ac_tag - - -as_fn_exit 0 -_ACEOF -ac_clean_files=$ac_clean_files_save - -test $ac_write_fail = 0 || - as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5 - - -# configure is writing to config.log, and then calls config.status. -# config.status does its own redirection, appending to config.log. -# Unfortunately, on DOS this fails, as config.log is still kept open -# by configure, so config.status won't be able to write to it; its -# output is simply discarded. So we exec the FD to /dev/null, -# effectively closing config.log, so it can be properly (re)opened and -# appended to by config.status. When coming back to configure, we -# need to make the FD available again. -if test "$no_create" != yes; then - ac_cs_success=: - ac_config_status_args= - test "$silent" = yes && - ac_config_status_args="$ac_config_status_args --quiet" - exec 5>/dev/null - $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false - exec 5>>config.log - # Use ||, not &&, to avoid exiting from the if with $? = 1, which - # would make configure fail if this is the last instruction. - $ac_cs_success || as_fn_exit 1 -fi -if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 -$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} -fi - -if test "x$enable_systemd" = "xyes"; then : - ac_config_files="$ac_config_files dist/unix/systemd/qbittorrent-nox@.service" - -cat >confcache <<\_ACEOF -# This file is a shell script that caches the results of configure -# tests run on this system so they can be shared between configure -# scripts and configure runs, see configure's option --config-cache. -# It is not useful on other systems. If it contains results you don't -# want to keep, you may remove or edit it. -# -# config.status only pays attention to the cache file if you give it -# the --recheck option to rerun configure. -# -# `ac_cv_env_foo' variables (set or unset) will be overridden when -# loading this file, other *unset* `ac_cv_foo' will be assigned the -# following values. - -_ACEOF - -# The following way of writing the cache mishandles newlines in values, -# but we know of no workaround that is simple, portable, and efficient. -# So, we kill variables containing newlines. -# Ultrix sh set writes to stderr and can't be redirected directly, -# and sets the high bit in the cache file unless we assign to the vars. -( - for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do - eval ac_val=\$$ac_var - case $ac_val in #( - *${as_nl}*) - case $ac_var in #( - *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 -$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; - esac - case $ac_var in #( - _ | IFS | as_nl) ;; #( - BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( - *) { eval $ac_var=; unset $ac_var;} ;; - esac ;; - esac - done - - (set) 2>&1 | - case $as_nl`(ac_space=' '; set) 2>&1` in #( - *${as_nl}ac_space=\ *) - # `set' does not quote correctly, so add quotes: double-quote - # substitution turns \\\\ into \\, and sed turns \\ into \. - sed -n \ - "s/'/'\\\\''/g; - s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" - ;; #( - *) - # `set' quotes correctly as required by POSIX, so do not add quotes. - sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" - ;; - esac | - sort -) | - sed ' - /^ac_cv_env_/b end - t clear - :clear - s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ - t end - s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ - :end' >>confcache -if diff "$cache_file" confcache >/dev/null 2>&1; then :; else - if test -w "$cache_file"; then - if test "x$cache_file" != "x/dev/null"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 -$as_echo "$as_me: updating cache $cache_file" >&6;} - if test ! -f "$cache_file" || test -h "$cache_file"; then - cat confcache >"$cache_file" - else - case $cache_file in #( - */* | ?:*) - mv -f confcache "$cache_file"$$ && - mv -f "$cache_file"$$ "$cache_file" ;; #( - *) - mv -f confcache "$cache_file" ;; - esac - fi - fi - else - { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 -$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} - fi -fi -rm -f confcache - -test "x$prefix" = xNONE && prefix=$ac_default_prefix -# Let make expand exec_prefix. -test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' - -# Transform confdefs.h into DEFS. -# Protect against shell expansion while executing Makefile rules. -# Protect against Makefile macro expansion. -# -# If the first sed substitution is executed (which looks for macros that -# take arguments), then branch to the quote section. Otherwise, -# look for a macro that doesn't take arguments. -ac_script=' -:mline -/\\$/{ - N - s,\\\n,, - b mline -} -t clear -:clear -s/^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*([^)]*)\)[ ]*\(.*\)/-D\1=\2/g -t quote -s/^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\)/-D\1=\2/g -t quote -b any -:quote -s/[ `~#$^&*(){}\\|;'\''"<>?]/\\&/g -s/\[/\\&/g -s/\]/\\&/g -s/\$/$$/g -H -:any -${ - g - s/^\n// - s/\n/ /g - p -} -' -DEFS=`sed -n "$ac_script" confdefs.h` - - -ac_libobjs= -ac_ltlibobjs= -U= -for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue - # 1. Remove the extension, and $U if already installed. - ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' - ac_i=`$as_echo "$ac_i" | sed "$ac_script"` - # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR - # will be set to the directory where LIBOBJS objects are built. - as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" - as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' -done -LIBOBJS=$ac_libobjs - -LTLIBOBJS=$ac_ltlibobjs - - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking that generated files are newer than configure" >&5 -$as_echo_n "checking that generated files are newer than configure... " >&6; } - if test -n "$am_sleep_pid"; then - # Hide warnings about reused PIDs. - wait $am_sleep_pid 2>/dev/null - fi - { $as_echo "$as_me:${as_lineno-$LINENO}: result: done" >&5 -$as_echo "done" >&6; } -if test -z "${AMDEP_TRUE}" && test -z "${AMDEP_FALSE}"; then - as_fn_error $? "conditional \"AMDEP\" was never defined. -Usually this means the macro was only invoked conditionally." "$LINENO" 5 -fi -if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then - as_fn_error $? "conditional \"am__fastdepCC\" was never defined. -Usually this means the macro was only invoked conditionally." "$LINENO" 5 -fi -if test -z "${am__fastdepCXX_TRUE}" && test -z "${am__fastdepCXX_FALSE}"; then - as_fn_error $? "conditional \"am__fastdepCXX\" was never defined. -Usually this means the macro was only invoked conditionally." "$LINENO" 5 -fi - if test -n "$EXEEXT"; then - am__EXEEXT_TRUE= - am__EXEEXT_FALSE='#' -else - am__EXEEXT_TRUE='#' - am__EXEEXT_FALSE= -fi - -if test -z "${am__EXEEXT_TRUE}" && test -z "${am__EXEEXT_FALSE}"; then - as_fn_error $? "conditional \"am__EXEEXT\" was never defined. -Usually this means the macro was only invoked conditionally." "$LINENO" 5 -fi - -: "${CONFIG_STATUS=./config.status}" -ac_write_fail=0 -ac_clean_files_save=$ac_clean_files -ac_clean_files="$ac_clean_files $CONFIG_STATUS" -{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 -$as_echo "$as_me: creating $CONFIG_STATUS" >&6;} -as_write_fail=0 -cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 -#! $SHELL -# Generated by $as_me. -# Run this file to recreate the current configuration. -# Compiler output produced by configure, useful for debugging -# configure, is in config.log if it exists. - -debug=false -ac_cs_recheck=false -ac_cs_silent=false - -SHELL=\${CONFIG_SHELL-$SHELL} -export SHELL -_ASEOF -cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 -## -------------------- ## -## M4sh Initialization. ## -## -------------------- ## - -# Be more Bourne compatible -DUALCASE=1; export DUALCASE # for MKS sh -if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : - emulate sh - NULLCMD=: - # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which - # is contrary to our usage. Disable this feature. - alias -g '${1+"$@"}'='"$@"' - setopt NO_GLOB_SUBST -else - case `(set -o) 2>/dev/null` in #( - *posix*) : - set -o posix ;; #( - *) : - ;; -esac -fi - - -as_nl=' -' -export as_nl -# Printing a long string crashes Solaris 7 /usr/bin/printf. -as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' -as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo -as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo -# Prefer a ksh shell builtin over an external printf program on Solaris, -# but without wasting forks for bash or zsh. -if test -z "$BASH_VERSION$ZSH_VERSION" \ - && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then - as_echo='print -r --' - as_echo_n='print -rn --' -elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then - as_echo='printf %s\n' - as_echo_n='printf %s' -else - if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then - as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' - as_echo_n='/usr/ucb/echo -n' - else - as_echo_body='eval expr "X$1" : "X\\(.*\\)"' - as_echo_n_body='eval - arg=$1; - case $arg in #( - *"$as_nl"*) - expr "X$arg" : "X\\(.*\\)$as_nl"; - arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; - esac; - expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" - ' - export as_echo_n_body - as_echo_n='sh -c $as_echo_n_body as_echo' - fi - export as_echo_body - as_echo='sh -c $as_echo_body as_echo' -fi - -# The user is always right. -if test "${PATH_SEPARATOR+set}" != set; then - PATH_SEPARATOR=: - (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { - (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || - PATH_SEPARATOR=';' - } -fi - - -# IFS -# We need space, tab and new line, in precisely that order. Quoting is -# there to prevent editors from complaining about space-tab. -# (If _AS_PATH_WALK were called with IFS unset, it would disable word -# splitting by setting IFS to empty value.) -IFS=" "" $as_nl" - -# Find who we are. Look in the path if we contain no directory separator. -as_myself= -case $0 in #(( - *[\\/]* ) as_myself=$0 ;; - *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break - done -IFS=$as_save_IFS - - ;; -esac -# We did not find ourselves, most probably we were run as `sh COMMAND' -# in which case we are not to be found in the path. -if test "x$as_myself" = x; then - as_myself=$0 -fi -if test ! -f "$as_myself"; then - $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 - exit 1 -fi - -# Unset variables that we do not need and which cause bugs (e.g. in -# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" -# suppresses any "Segmentation fault" message there. '((' could -# trigger a bug in pdksh 5.2.14. -for as_var in BASH_ENV ENV MAIL MAILPATH -do eval test x\${$as_var+set} = xset \ - && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : -done -PS1='$ ' -PS2='> ' -PS4='+ ' - -# NLS nuisances. -LC_ALL=C -export LC_ALL -LANGUAGE=C -export LANGUAGE - -# CDPATH. -(unset CDPATH) >/dev/null 2>&1 && unset CDPATH - - -# as_fn_error STATUS ERROR [LINENO LOG_FD] -# ---------------------------------------- -# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are -# provided, also output the error to LOG_FD, referencing LINENO. Then exit the -# script with STATUS, using 1 if that was 0. -as_fn_error () -{ - as_status=$1; test $as_status -eq 0 && as_status=1 - if test "$4"; then - as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 - fi - $as_echo "$as_me: error: $2" >&2 - as_fn_exit $as_status -} # as_fn_error - - -# as_fn_set_status STATUS -# ----------------------- -# Set $? to STATUS, without forking. -as_fn_set_status () -{ - return $1 -} # as_fn_set_status - -# as_fn_exit STATUS -# ----------------- -# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. -as_fn_exit () -{ - set +e - as_fn_set_status $1 - exit $1 -} # as_fn_exit - -# as_fn_unset VAR -# --------------- -# Portably unset VAR. -as_fn_unset () -{ - { eval $1=; unset $1;} -} -as_unset=as_fn_unset -# as_fn_append VAR VALUE -# ---------------------- -# Append the text in VALUE to the end of the definition contained in VAR. Take -# advantage of any shell optimizations that allow amortized linear growth over -# repeated appends, instead of the typical quadratic growth present in naive -# implementations. -if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : - eval 'as_fn_append () - { - eval $1+=\$2 - }' -else - as_fn_append () - { - eval $1=\$$1\$2 - } -fi # as_fn_append - -# as_fn_arith ARG... -# ------------------ -# Perform arithmetic evaluation on the ARGs, and store the result in the -# global $as_val. Take advantage of shells that can avoid forks. The arguments -# must be portable across $(()) and expr. -if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : - eval 'as_fn_arith () - { - as_val=$(( $* )) - }' -else - as_fn_arith () - { - as_val=`expr "$@" || test $? -eq 1` - } -fi # as_fn_arith - - -if expr a : '\(a\)' >/dev/null 2>&1 && - test "X`expr 00001 : '.*\(...\)'`" = X001; then - as_expr=expr -else - as_expr=false -fi - -if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then - as_basename=basename -else - as_basename=false -fi - -if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then - as_dirname=dirname -else - as_dirname=false -fi - -as_me=`$as_basename -- "$0" || -$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ - X"$0" : 'X\(//\)$' \| \ - X"$0" : 'X\(/\)' \| . 2>/dev/null || -$as_echo X/"$0" | - sed '/^.*\/\([^/][^/]*\)\/*$/{ - s//\1/ - q - } - /^X\/\(\/\/\)$/{ - s//\1/ - q - } - /^X\/\(\/\).*/{ - s//\1/ - q - } - s/.*/./; q'` - -# Avoid depending upon Character Ranges. -as_cr_letters='abcdefghijklmnopqrstuvwxyz' -as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' -as_cr_Letters=$as_cr_letters$as_cr_LETTERS -as_cr_digits='0123456789' -as_cr_alnum=$as_cr_Letters$as_cr_digits - -ECHO_C= ECHO_N= ECHO_T= -case `echo -n x` in #((((( --n*) - case `echo 'xy\c'` in - *c*) ECHO_T=' ';; # ECHO_T is single tab character. - xy) ECHO_C='\c';; - *) echo `echo ksh88 bug on AIX 6.1` > /dev/null - ECHO_T=' ';; - esac;; -*) - ECHO_N='-n';; -esac - -rm -f conf$$ conf$$.exe conf$$.file -if test -d conf$$.dir; then - rm -f conf$$.dir/conf$$.file -else - rm -f conf$$.dir - mkdir conf$$.dir 2>/dev/null -fi -if (echo >conf$$.file) 2>/dev/null; then - if ln -s conf$$.file conf$$ 2>/dev/null; then - as_ln_s='ln -s' - # ... but there are two gotchas: - # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. - # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. - # In both cases, we have to default to `cp -pR'. - ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || - as_ln_s='cp -pR' - elif ln conf$$.file conf$$ 2>/dev/null; then - as_ln_s=ln - else - as_ln_s='cp -pR' - fi -else - as_ln_s='cp -pR' -fi -rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file -rmdir conf$$.dir 2>/dev/null - - -# as_fn_mkdir_p -# ------------- -# Create "$as_dir" as a directory, including parents if necessary. -as_fn_mkdir_p () -{ - - case $as_dir in #( - -*) as_dir=./$as_dir;; - esac - test -d "$as_dir" || eval $as_mkdir_p || { - as_dirs= - while :; do - case $as_dir in #( - *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( - *) as_qdir=$as_dir;; - esac - as_dirs="'$as_qdir' $as_dirs" - as_dir=`$as_dirname -- "$as_dir" || -$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$as_dir" : 'X\(//\)[^/]' \| \ - X"$as_dir" : 'X\(//\)$' \| \ - X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || -$as_echo X"$as_dir" | - sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ - s//\1/ - q - } - /^X\(\/\/\)[^/].*/{ - s//\1/ - q - } - /^X\(\/\/\)$/{ - s//\1/ - q - } - /^X\(\/\).*/{ - s//\1/ - q - } - s/.*/./; q'` - test -d "$as_dir" && break - done - test -z "$as_dirs" || eval "mkdir $as_dirs" - } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" - - -} # as_fn_mkdir_p -if mkdir -p . 2>/dev/null; then - as_mkdir_p='mkdir -p "$as_dir"' -else - test -d ./-p && rmdir ./-p - as_mkdir_p=false -fi - - -# as_fn_executable_p FILE -# ----------------------- -# Test if FILE is an executable regular file. -as_fn_executable_p () -{ - test -f "$1" && test -x "$1" -} # as_fn_executable_p -as_test_x='test -x' -as_executable_p=as_fn_executable_p - -# Sed expression to map a string onto a valid CPP name. -as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" - -# Sed expression to map a string onto a valid variable name. -as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" - - -exec 6>&1 -## ----------------------------------- ## -## Main body of $CONFIG_STATUS script. ## -## ----------------------------------- ## -_ASEOF -test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 - -cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 -# Save the log message, to keep $0 and so on meaningful, and to -# report actual input values of CONFIG_FILES etc. instead of their -# values after options handling. -ac_log=" -This file was extended by qbittorrent $as_me v3.2.0alpha, which was -generated by GNU Autoconf 2.69. Invocation command line was - - CONFIG_FILES = $CONFIG_FILES - CONFIG_HEADERS = $CONFIG_HEADERS - CONFIG_LINKS = $CONFIG_LINKS - CONFIG_COMMANDS = $CONFIG_COMMANDS - $ $0 $@ - -on `(hostname || uname -n) 2>/dev/null | sed 1q` -" - -_ACEOF - -case $ac_config_files in *" -"*) set x $ac_config_files; shift; ac_config_files=$*;; -esac - - - -cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 -# Files that config.status was made for. -config_files="$ac_config_files" -config_commands="$ac_config_commands" - -_ACEOF - -cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 -ac_cs_usage="\ -\`$as_me' instantiates files and other configuration actions -from templates according to the current configuration. Unless the files -and actions are specified as TAGs, all are instantiated by default. - -Usage: $0 [OPTION]... [TAG]... - - -h, --help print this help, then exit - -V, --version print version number and configuration settings, then exit - --config print configuration, then exit - -q, --quiet, --silent - do not print progress messages - -d, --debug don't remove temporary files - --recheck update $as_me by reconfiguring in the same conditions - --file=FILE[:TEMPLATE] - instantiate the configuration file FILE - -Configuration files: -$config_files - -Configuration commands: -$config_commands - -Report bugs to . -qbittorrent home page: ." - -_ACEOF -cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 -ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" -ac_cs_version="\\ -qbittorrent config.status v3.2.0alpha -configured by $0, generated by GNU Autoconf 2.69, - with options \\"\$ac_cs_config\\" - -Copyright (C) 2012 Free Software Foundation, Inc. -This config.status script is free software; the Free Software Foundation -gives unlimited permission to copy, distribute and modify it." - -ac_pwd='$ac_pwd' -srcdir='$srcdir' -INSTALL='$INSTALL' -MKDIR_P='$MKDIR_P' -AWK='$AWK' -test -n "\$AWK" || AWK=awk -_ACEOF - -cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 -# The default lists apply if the user does not specify any file. -ac_need_defaults=: -while test $# != 0 -do - case $1 in - --*=?*) - ac_option=`expr "X$1" : 'X\([^=]*\)='` - ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` - ac_shift=: - ;; - --*=) - ac_option=`expr "X$1" : 'X\([^=]*\)='` - ac_optarg= - ac_shift=: - ;; - *) - ac_option=$1 - ac_optarg=$2 - ac_shift=shift - ;; - esac - - case $ac_option in - # Handling of the options. - -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) - ac_cs_recheck=: ;; - --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) - $as_echo "$ac_cs_version"; exit ;; - --config | --confi | --conf | --con | --co | --c ) - $as_echo "$ac_cs_config"; exit ;; - --debug | --debu | --deb | --de | --d | -d ) - debug=: ;; - --file | --fil | --fi | --f ) - $ac_shift - case $ac_optarg in - *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; - '') as_fn_error $? "missing file argument" ;; - esac - as_fn_append CONFIG_FILES " '$ac_optarg'" - ac_need_defaults=false;; - --he | --h | --help | --hel | -h ) - $as_echo "$ac_cs_usage"; exit ;; - -q | -quiet | --quiet | --quie | --qui | --qu | --q \ - | -silent | --silent | --silen | --sile | --sil | --si | --s) - ac_cs_silent=: ;; - - # This is an error. - -*) as_fn_error $? "unrecognized option: \`$1' -Try \`$0 --help' for more information." ;; - - *) as_fn_append ac_config_targets " $1" - ac_need_defaults=false ;; - - esac - shift -done - -ac_configure_extra_args= - -if $ac_cs_silent; then - exec 6>/dev/null - ac_configure_extra_args="$ac_configure_extra_args --silent" -fi - -_ACEOF -cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 -if \$ac_cs_recheck; then - set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion - shift - \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 - CONFIG_SHELL='$SHELL' - export CONFIG_SHELL - exec "\$@" -fi - -_ACEOF -cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 -exec 5>>config.log -{ - echo - sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX -## Running $as_me. ## -_ASBOX - $as_echo "$ac_log" -} >&5 - -_ACEOF -cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 -# -# INIT-COMMANDS -# -AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir" - -_ACEOF - -cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 - -# Handling of arguments. -for ac_config_target in $ac_config_targets -do - case $ac_config_target in - "depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;; - "conf.pri") CONFIG_FILES="$CONFIG_FILES conf.pri" ;; - "dist/unix/systemd/qbittorrent-nox@.service") CONFIG_FILES="$CONFIG_FILES dist/unix/systemd/qbittorrent-nox@.service" ;; - - *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; - esac -done - - -# If the user did not use the arguments to specify the items to instantiate, -# then the envvar interface is used. Set only those that are not. -# We use the long form for the default assignment because of an extremely -# bizarre bug on SunOS 4.1.3. -if $ac_need_defaults; then - test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files - test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands -fi - -# Have a temporary directory for convenience. Make it in the build tree -# simply because there is no reason against having it here, and in addition, -# creating and moving files from /tmp can sometimes cause problems. -# Hook for its removal unless debugging. -# Note that there is a small window in which the directory will not be cleaned: -# after its creation but before its name has been assigned to `$tmp'. -$debug || -{ - tmp= ac_tmp= - trap 'exit_status=$? - : "${ac_tmp:=$tmp}" - { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status -' 0 - trap 'as_fn_exit 1' 1 2 13 15 -} -# Create a (secure) tmp directory for tmp files. - -{ - tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && - test -d "$tmp" -} || -{ - tmp=./conf$$-$RANDOM - (umask 077 && mkdir "$tmp") -} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 -ac_tmp=$tmp - -# Set up the scripts for CONFIG_FILES section. -# No need to generate them if there are no CONFIG_FILES. -# This happens for instance with `./config.status config.h'. -if test -n "$CONFIG_FILES"; then - - -ac_cr=`echo X | tr X '\015'` -# On cygwin, bash can eat \r inside `` if the user requested igncr. -# But we know of no other shell where ac_cr would be empty at this -# point, so we can use a bashism as a fallback. -if test "x$ac_cr" = x; then - eval ac_cr=\$\'\\r\' -fi -ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` -if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then - ac_cs_awk_cr='\\r' -else - ac_cs_awk_cr=$ac_cr -fi - -echo 'BEGIN {' >"$ac_tmp/subs1.awk" && -_ACEOF - - -{ - echo "cat >conf$$subs.awk <<_ACEOF" && - echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && - echo "_ACEOF" -} >conf$$subs.sh || - as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 -ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'` -ac_delim='%!_!# ' -for ac_last_try in false false false false false :; do - . ./conf$$subs.sh || - as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 - - ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` - if test $ac_delim_n = $ac_delim_num; then - break - elif $ac_last_try; then - as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 - else - ac_delim="$ac_delim!$ac_delim _$ac_delim!! " - fi -done -rm -f conf$$subs.sh - -cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 -cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK && -_ACEOF -sed -n ' -h -s/^/S["/; s/!.*/"]=/ -p -g -s/^[^!]*!// -:repl -t repl -s/'"$ac_delim"'$// -t delim -:nl -h -s/\(.\{148\}\)..*/\1/ -t more1 -s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ -p -n -b repl -:more1 -s/["\\]/\\&/g; s/^/"/; s/$/"\\/ -p -g -s/.\{148\}// -t nl -:delim -h -s/\(.\{148\}\)..*/\1/ -t more2 -s/["\\]/\\&/g; s/^/"/; s/$/"/ -p -b -:more2 -s/["\\]/\\&/g; s/^/"/; s/$/"\\/ -p -g -s/.\{148\}// -t delim -' >$CONFIG_STATUS || ac_write_fail=1 -rm -f conf$$subs.awk -cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 -_ACAWK -cat >>"\$ac_tmp/subs1.awk" <<_ACAWK && - for (key in S) S_is_set[key] = 1 - FS = "" - -} -{ - line = $ 0 - nfields = split(line, field, "@") - substed = 0 - len = length(field[1]) - for (i = 2; i < nfields; i++) { - key = field[i] - keylen = length(key) - if (S_is_set[key]) { - value = S[key] - line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) - len += length(value) + length(field[++i]) - substed = 1 - } else - len += 1 + keylen - } - - print line -} - -_ACAWK -_ACEOF -cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 -if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then - sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" -else - cat -fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \ - || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 -_ACEOF - -# VPATH may cause trouble with some makes, so we remove sole $(srcdir), -# ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and -# trailing colons and then remove the whole line if VPATH becomes empty -# (actually we leave an empty line to preserve line numbers). -if test "x$srcdir" = x.; then - ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{ -h -s/// -s/^/:/ -s/[ ]*$/:/ -s/:\$(srcdir):/:/g -s/:\${srcdir}:/:/g -s/:@srcdir@:/:/g -s/^:*// -s/:*$// -x -s/\(=[ ]*\).*/\1/ -G -s/\n// -s/^[^=]*=[ ]*$// -}' -fi - -cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 -fi # test -n "$CONFIG_FILES" - - -eval set X " :F $CONFIG_FILES :C $CONFIG_COMMANDS" -shift -for ac_tag -do - case $ac_tag in - :[FHLC]) ac_mode=$ac_tag; continue;; - esac - case $ac_mode$ac_tag in - :[FHL]*:*);; - :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;; - :[FH]-) ac_tag=-:-;; - :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; - esac - ac_save_IFS=$IFS - IFS=: - set x $ac_tag - IFS=$ac_save_IFS - shift - ac_file=$1 - shift - - case $ac_mode in - :L) ac_source=$1;; - :[FH]) - ac_file_inputs= - for ac_f - do - case $ac_f in - -) ac_f="$ac_tmp/stdin";; - *) # Look for the file first in the build tree, then in the source tree - # (if the path is not absolute). The absolute path cannot be DOS-style, - # because $ac_f cannot contain `:'. - test -f "$ac_f" || - case $ac_f in - [\\/$]*) false;; - *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; - esac || - as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;; - esac - case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac - as_fn_append ac_file_inputs " '$ac_f'" - done - - # Let's still pretend it is `configure' which instantiates (i.e., don't - # use $as_me), people would be surprised to read: - # /* config.h. Generated by config.status. */ - configure_input='Generated from '` - $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' - `' by configure.' - if test x"$ac_file" != x-; then - configure_input="$ac_file. $configure_input" - { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 -$as_echo "$as_me: creating $ac_file" >&6;} - fi - # Neutralize special characters interpreted by sed in replacement strings. - case $configure_input in #( - *\&* | *\|* | *\\* ) - ac_sed_conf_input=`$as_echo "$configure_input" | - sed 's/[\\\\&|]/\\\\&/g'`;; #( - *) ac_sed_conf_input=$configure_input;; - esac - - case $ac_tag in - *:-:* | *:-) cat >"$ac_tmp/stdin" \ - || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; - esac - ;; - esac - - ac_dir=`$as_dirname -- "$ac_file" || -$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$ac_file" : 'X\(//\)[^/]' \| \ - X"$ac_file" : 'X\(//\)$' \| \ - X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || -$as_echo X"$ac_file" | - sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ - s//\1/ - q - } - /^X\(\/\/\)[^/].*/{ - s//\1/ - q - } - /^X\(\/\/\)$/{ - s//\1/ - q - } - /^X\(\/\).*/{ - s//\1/ - q - } - s/.*/./; q'` - as_dir="$ac_dir"; as_fn_mkdir_p - ac_builddir=. - -case "$ac_dir" in -.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; -*) - ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` - # A ".." for each directory in $ac_dir_suffix. - ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` - case $ac_top_builddir_sub in - "") ac_top_builddir_sub=. ac_top_build_prefix= ;; - *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; - esac ;; -esac -ac_abs_top_builddir=$ac_pwd -ac_abs_builddir=$ac_pwd$ac_dir_suffix -# for backward compatibility: -ac_top_builddir=$ac_top_build_prefix - -case $srcdir in - .) # We are building in place. - ac_srcdir=. - ac_top_srcdir=$ac_top_builddir_sub - ac_abs_top_srcdir=$ac_pwd ;; - [\\/]* | ?:[\\/]* ) # Absolute name. - ac_srcdir=$srcdir$ac_dir_suffix; - ac_top_srcdir=$srcdir - ac_abs_top_srcdir=$srcdir ;; - *) # Relative name. - ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix - ac_top_srcdir=$ac_top_build_prefix$srcdir - ac_abs_top_srcdir=$ac_pwd/$srcdir ;; -esac -ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix - - - case $ac_mode in - :F) - # - # CONFIG_FILE - # - - case $INSTALL in - [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; - *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;; - esac - ac_MKDIR_P=$MKDIR_P - case $MKDIR_P in - [\\/$]* | ?:[\\/]* ) ;; - */*) ac_MKDIR_P=$ac_top_build_prefix$MKDIR_P ;; - esac -_ACEOF - -cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 -# If the template does not know about datarootdir, expand it. -# FIXME: This hack should be removed a few years after 2.60. -ac_datarootdir_hack=; ac_datarootdir_seen= -ac_sed_dataroot=' -/datarootdir/ { - p - q -} -/@datadir@/p -/@docdir@/p -/@infodir@/p -/@localedir@/p -/@mandir@/p' -case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in -*datarootdir*) ac_datarootdir_seen=yes;; -*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 -$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} -_ACEOF -cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 - ac_datarootdir_hack=' - s&@datadir@&$datadir&g - s&@docdir@&$docdir&g - s&@infodir@&$infodir&g - s&@localedir@&$localedir&g - s&@mandir@&$mandir&g - s&\\\${datarootdir}&$datarootdir&g' ;; -esac -_ACEOF - -# Neutralize VPATH when `$srcdir' = `.'. -# Shell code in configure.ac might set extrasub. -# FIXME: do we really want to maintain this feature? -cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 -ac_sed_extra="$ac_vpsub -$extrasub -_ACEOF -cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 -:t -/@[a-zA-Z_][a-zA-Z_0-9]*@/!b -s|@configure_input@|$ac_sed_conf_input|;t t -s&@top_builddir@&$ac_top_builddir_sub&;t t -s&@top_build_prefix@&$ac_top_build_prefix&;t t -s&@srcdir@&$ac_srcdir&;t t -s&@abs_srcdir@&$ac_abs_srcdir&;t t -s&@top_srcdir@&$ac_top_srcdir&;t t -s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t -s&@builddir@&$ac_builddir&;t t -s&@abs_builddir@&$ac_abs_builddir&;t t -s&@abs_top_builddir@&$ac_abs_top_builddir&;t t -s&@INSTALL@&$ac_INSTALL&;t t -s&@MKDIR_P@&$ac_MKDIR_P&;t t -$ac_datarootdir_hack -" -eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \ - >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5 - -test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && - { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && - { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ - "$ac_tmp/out"`; test -z "$ac_out"; } && - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' -which seems to be undefined. Please make sure it is defined" >&5 -$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' -which seems to be undefined. Please make sure it is defined" >&2;} - - rm -f "$ac_tmp/stdin" - case $ac_file in - -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";; - *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";; - esac \ - || as_fn_error $? "could not create $ac_file" "$LINENO" 5 - ;; - - - :C) { $as_echo "$as_me:${as_lineno-$LINENO}: executing $ac_file commands" >&5 -$as_echo "$as_me: executing $ac_file commands" >&6;} - ;; - esac - - - case $ac_file$ac_mode in - "depfiles":C) test x"$AMDEP_TRUE" != x"" || { - # Older Autoconf quotes --file arguments for eval, but not when files - # are listed without --file. Let's play safe and only enable the eval - # if we detect the quoting. - case $CONFIG_FILES in - *\'*) eval set x "$CONFIG_FILES" ;; - *) set x $CONFIG_FILES ;; - esac - shift - for mf - do - # Strip MF so we end up with the name of the file. - mf=`echo "$mf" | sed -e 's/:.*$//'` - # Check whether this is an Automake generated Makefile or not. - # We used to match only the files named 'Makefile.in', but - # some people rename them; so instead we look at the file content. - # Grep'ing the first line is not enough: some people post-process - # each Makefile.in and add a new line on top of each file to say so. - # Grep'ing the whole file is not good either: AIX grep has a line - # limit of 2048, but all sed's we know have understand at least 4000. - if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then - dirpart=`$as_dirname -- "$mf" || -$as_expr X"$mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$mf" : 'X\(//\)[^/]' \| \ - X"$mf" : 'X\(//\)$' \| \ - X"$mf" : 'X\(/\)' \| . 2>/dev/null || -$as_echo X"$mf" | - sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ - s//\1/ - q - } - /^X\(\/\/\)[^/].*/{ - s//\1/ - q - } - /^X\(\/\/\)$/{ - s//\1/ - q - } - /^X\(\/\).*/{ - s//\1/ - q - } - s/.*/./; q'` - else - continue - fi - # Extract the definition of DEPDIR, am__include, and am__quote - # from the Makefile without running 'make'. - DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` - test -z "$DEPDIR" && continue - am__include=`sed -n 's/^am__include = //p' < "$mf"` - test -z "$am__include" && continue - am__quote=`sed -n 's/^am__quote = //p' < "$mf"` - # Find all dependency output files, they are included files with - # $(DEPDIR) in their names. We invoke sed twice because it is the - # simplest approach to changing $(DEPDIR) to its actual value in the - # expansion. - for file in `sed -n " - s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ - sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g'`; do - # Make sure the directory exists. - test -f "$dirpart/$file" && continue - fdir=`$as_dirname -- "$file" || -$as_expr X"$file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$file" : 'X\(//\)[^/]' \| \ - X"$file" : 'X\(//\)$' \| \ - X"$file" : 'X\(/\)' \| . 2>/dev/null || -$as_echo X"$file" | - sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ - s//\1/ - q - } - /^X\(\/\/\)[^/].*/{ - s//\1/ - q - } - /^X\(\/\/\)$/{ - s//\1/ - q - } - /^X\(\/\).*/{ - s//\1/ - q - } - s/.*/./; q'` - as_dir=$dirpart/$fdir; as_fn_mkdir_p - # echo "creating $dirpart/$file" - echo '# dummy' > "$dirpart/$file" - done - done -} - ;; - - esac -done # for ac_tag - - -as_fn_exit 0 -_ACEOF -ac_clean_files=$ac_clean_files_save - -test $ac_write_fail = 0 || - as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5 - - -# configure is writing to config.log, and then calls config.status. -# config.status does its own redirection, appending to config.log. -# Unfortunately, on DOS this fails, as config.log is still kept open -# by configure, so config.status won't be able to write to it; its -# output is simply discarded. So we exec the FD to /dev/null, -# effectively closing config.log, so it can be properly (re)opened and -# appended to by config.status. When coming back to configure, we -# need to make the FD available again. -if test "$no_create" != yes; then - ac_cs_success=: - ac_config_status_args= - test "$silent" = yes && - ac_config_status_args="$ac_config_status_args --quiet" - exec 5>/dev/null - $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false - exec 5>>config.log - # Use ||, not &&, to avoid exiting from the if with $? = 1, which - # would make configure fail if this is the last instruction. - $ac_cs_success || as_fn_exit 1 -fi -if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 -$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} -fi - -fi - - - -{ $as_echo "$as_me:${as_lineno-$LINENO}: Running qmake to generate the makefile..." >&5 -$as_echo "$as_me: Running qmake to generate the makefile..." >&6;} -CONFDIR="$( cd "$( dirname "$0" )" && pwd )" - -$QT_QMAKE -r $CONFDIR/qbittorrent.pro "QMAKE_LRELEASE=$QMAKE_LRELEASE" - -ret="$?" - -$as_echo -if test "x$ret" = "x0"; then : - { $as_echo "$as_me:${as_lineno-$LINENO}: Good, your configure finished." >&5 -$as_echo "$as_me: Good, your configure finished." >&6;} -else - as_fn_error $? "Failed running $QT_QMAKE to generate the makefile" "$LINENO" 5 -fi -$as_echo - diff --git a/configure.ac b/configure.ac deleted file mode 100644 index 872dfe3ff..000000000 --- a/configure.ac +++ /dev/null @@ -1,237 +0,0 @@ -AC_INIT([qbittorrent], [v3.2.0alpha], [bugs.qbittorrent.org], [], [http://www.qbittorrent.org/]) -AC_CONFIG_AUX_DIR([build-aux]) -AC_CONFIG_MACRO_DIR([m4]) -AC_PROG_CC -AC_PROG_CXX -AC_PROG_SED -AC_LANG(C++) -AC_CANONICAL_HOST -AM_INIT_AUTOMAKE - - - -# Define --wth-* and --enable-* arguments - -AC_ARG_WITH(qtsingleapplication, - [AS_HELP_STRING([--with-qtsingleapplication=@<:@system|shipped@:>@], - [Use the shipped qtsingleapplication library or the system one (default=shipped)])], - [], - [with_qtsingleapplication=shipped]) - -AC_ARG_ENABLE(debug, - [AS_HELP_STRING([--enable-debug], - [Enable debug build])], - [], - [enable_debug=no]) - -AC_ARG_ENABLE(gui, - [AS_HELP_STRING([--disable-gui], - [Disable the GUI for headless running. Disables QtDBus and the GeoIP Database.])], - [], - [enable_gui=yes]) - -AC_ARG_ENABLE(systemd, - [AS_HELP_STRING([--enable-systemd], - [Install the systemd service file (headless only).])], - [], - [enable_systemd=no]) - -AC_ARG_ENABLE(webui, - [AS_HELP_STRING([--disable-webui], - [Disable the WebUI.])], - [], - [enable_webui=yes]) - -AC_ARG_ENABLE(qt-dbus, - [AS_HELP_STRING([--disable-qt-dbus], - [Disable use of QtDBus (GUI only)])], - [], - [enable_qt_dbus=yes]) - -# Detect OS -AC_MSG_CHECKING([whether OS is FreeBSD]) -AS_IF([expr "$host_os" : ".*freebsd.*" > /dev/null], - [AC_MSG_RESULT([yes]) - LIBS="-lexecinfo $LIBS"], - [AC_MSG_RESULT([no])]) - -AC_MSG_CHECKING([whether OS is macOS]) -AS_IF([expr "$host_os" : ".*darwin.*" > /dev/null], - [AC_MSG_RESULT([yes]) - enable_qt_dbus=no], - [AC_MSG_RESULT([no])]) - -# Require 0.23 pkg-config -PKG_PROG_PKG_CONFIG([0.23]) -AS_IF([test "x$PKG_CONFIG" = "x"], - [AC_MSG_ERROR([Could not find pkg-config])]) - -# Check which arguments were set and act accordingly -AC_MSG_CHECKING([whether to enable the Debug build]) -AS_CASE(["x$enable_debug"], - ["xno"], - [AC_MSG_RESULT([no]) - QBT_ADD_CONFIG="$QBT_ADD_CONFIG release" - QBT_REMOVE_CONFIG="$QBT_REMOVE_CONFIG debug"], - ["xyes"], - [AC_MSG_RESULT([yes]) - QBT_ADD_CONFIG="$QBT_ADD_CONFIG debug" - QBT_REMOVE_CONFIG="$QBT_REMOVE_CONFIG release"], - [AC_MSG_RESULT([$enable_debug]) - AC_MSG_ERROR([Unknown option "$enable_debug". Use either "yes" or "no".])]) - -AC_MSG_CHECKING([whether to enable the GUI]) -AS_CASE(["x$enable_gui"], - ["xyes"], - [AC_MSG_RESULT([yes]) - enable_systemd=[no] - QBT_REMOVE_CONFIG="$QBT_REMOVE_CONFIG nogui"], - ["xno"], - [AC_MSG_RESULT([no]) - enable_qt_dbus=[no] - QBT_ADD_CONFIG="$QBT_ADD_CONFIG nogui"], - [AC_MSG_RESULT([$enable_gui]) - AC_MSG_ERROR([Unknown option "$enable_gui". Use either "yes" or "no".])]) - -AC_MSG_CHECKING([whether to install the systemd service file]) -AS_CASE(["x$enable_systemd"], - ["xyes"], - [AC_MSG_RESULT([yes]) - QBT_ADD_CONFIG="$QBT_ADD_CONFIG systemd"], - ["xno"], - [AC_MSG_RESULT([no]) - QBT_REMOVE_CONFIG="$QBT_REMOVE_CONFIG systemd"], - [AC_MSG_RESULT([$enable_systemd]) - AC_MSG_ERROR([Unknown option "$enable_systemd". Use either "yes" or "no".])]) - -AC_MSG_CHECKING([whether to enable the WebUI]) -AS_CASE(["x$enable_webui"], - ["xyes"], - [AC_MSG_RESULT([yes]) - QBT_REMOVE_CONFIG="$QBT_REMOVE_CONFIG nowebui"], - ["xno"], - [AC_MSG_RESULT([no]) - QBT_ADD_CONFIG="$QBT_ADD_CONFIG nowebui"], - [AC_MSG_RESULT([$enable_webui]) - AC_MSG_ERROR([Unknown option "$enable_webui". Use either "yes" or "no".])]) - -FIND_QT5() -AC_MSG_CHECKING([whether QtDBus should be enabled]) -AS_CASE(["x$enable_qt_dbus"], - ["xyes"], - [AC_MSG_RESULT([yes]) - FIND_QTDBUS() - AS_IF([test "x$HAVE_QTDBUS" = "xfalse"], - [AC_MSG_ERROR([Could not find QtDBus])], - [QBT_ADD_CONFIG="$QBT_ADD_CONFIG dbus"] - )], - ["xno"], - [AC_MSG_RESULT([no]) - QBT_REMOVE_CONFIG="$QBT_REMOVE_CONFIG dbus"], - [AC_MSG_RESULT([$enable_qt_dbus]) - AC_MSG_ERROR([Unknown option "$enable_qt_dbus". Use either "yes" or "no".])]) - - -AX_BOOST_BASE([1.35]) -# HAVE_BOOST is set to an empty value when Boost is found. I don't know -# how to test for a set vs unset variable. -AS_IF([test "x$BOOST_CPPFLAGS" = "x"], - [AC_MSG_ERROR([Could not find Boost])], - [AC_MSG_NOTICE([Boost CPPFLAGS: $BOOST_CPPFLAGS]) - CPPFLAGS="$BOOST_CPPFLAGS $CPPFLAGS" - LDFLAGS="$BOOST_LDFLAGS $LDFLAGS"]) - -AX_BOOST_SYSTEM() -# HAVE_BOOST_SYSTEM is set to an empty value when Boost.System is found. -# I don't know how to test for a set vs unset variable. -AS_IF([test "x$BOOST_SYSTEM_LIB" = "x"], - [AC_MSG_ERROR([Could not find Boost.System])], - [AC_MSG_NOTICE([Boost.System LIB: $BOOST_SYSTEM_LIB]) - LIBS="$BOOST_SYSTEM_LIB $LIBS"]) - -AC_MSG_CHECKING([which qtsingleapplication to use]) -AS_CASE(["x$with_qtsingleapplication"], - ["xshipped"], - [AC_MSG_RESULT([shipped]) - QBT_REMOVE_CONFIG="$QBT_REMOVE_CONFIG usesystemqtsingleapplication"], - ["xsystem"], - [AC_MSG_RESULT([system]) - QBT_ADD_CONFIG="$QBT_ADD_CONFIG usesystemqtsingleapplication"], - [AC_MSG_RESULT([$with_qtsingleapplication]) - AC_MSG_ERROR([Unknown option "$with_qtsingleapplication". Use either "system" or "shipped".])]) - -PKG_CHECK_MODULES(libtorrent, - [libtorrent-rasterbar >= 1.0.6], - [CPPFLAGS="$libtorrent_CFLAGS $CPPFLAGS" - LIBS="$libtorrent_LIBS $LIBS"]) - -PKG_CHECK_MODULES(zlib, - [zlib >= 1.2.5.2], - [CPPFLAGS="$zlib_CFLAGS $CPPFLAGS" - LIBS="$zlib_LIBS $LIBS"]) - -# These are required because autoconf doesn't expand these **particular** -# vars automatically. And qmake cannot autoexpand them. -AX_DEFINE_DIR([EXPAND_PREFIX], [prefix]) -AX_DEFINE_DIR([EXPAND_BINDIR], [bindir]) -AX_DEFINE_DIR([EXPAND_DATADIR], [datadir]) -AX_DEFINE_DIR([EXPAND_MANDIR], [mandir]) - -# Original extract() function contributed by pmzqla -# $*: Strings to parse -# Set $QBT_CONF_DEFINES, $QBT_CONF_INCLUDES, $QBT_CONF_EXTRA_CFLAGS -extract() { - if [[ -z "$*" ]]; then - echo "Input string required" - return 1 - fi - - # BSD sed needs an actual newline character in the substitute command - new_line=' -' - # Convert " -" to "\n" if not between quotes and remove possible leading white spaces - string=$(echo " $*" | $SED -e "s: -:\\${new_line}:g" -e 's:"\(.*\)\n\(.*\)":\"\1 -\2":g' -e "s:'\(.*\)\n\(.*\)':\'\1 -\2':g" -e 's/^[[:space:]]*//') - SAVEIFS=$IFS - IFS=$(printf "\n\b") - for i in $string; do - case "$(echo "$i" | cut -c1)" in - '') ;; - D) QBT_CONF_DEFINES="$(echo $i | cut -c2-) $QBT_CONF_DEFINES";; - I) QBT_CONF_INCLUDES="$(echo $i | cut -c2-) $QBT_CONF_INCLUDES";; - *) QBT_CONF_EXTRA_CFLAGS="-$i $QBT_CONF_EXTRA_CFLAGS";; - esac - done - IFS=$SAVEIFS -} - -extract $CPPFLAGS -QBT_ADD_DEFINES="$QBT_ADD_DEFINES $QBT_CONF_DEFINES" -QBT_CONF_EXTRA_CFLAGS="$QBT_CONF_EXTRA_CFLAGS $CXXFLAGS" - -# Substitute the values of these vars in conf.pri.in -AC_SUBST(QBT_CONF_INCLUDES) -AC_SUBST(QBT_CONF_EXTRA_CFLAGS) -AC_SUBST(QBT_ADD_CONFIG) -AC_SUBST(QBT_REMOVE_CONFIG) -AC_SUBST(QBT_ADD_DEFINES) -AC_SUBST(QBT_REMOVE_DEFINES) - -AC_OUTPUT(conf.pri) -AS_IF([test "x$enable_systemd" = "xyes"], - [AC_OUTPUT(dist/unix/systemd/qbittorrent-nox@.service)]) - - - -AC_MSG_NOTICE([Running qmake to generate the makefile...]) -CONFDIR="$( cd "$( dirname "$0" )" && pwd )" - -$QT_QMAKE -r [$CONFDIR]/qbittorrent.pro "QMAKE_LRELEASE=$QMAKE_LRELEASE" - -ret="$?" - -AS_ECHO() -AS_IF([test "x$ret" = "x0"], - [AC_MSG_NOTICE([Good, your configure finished.])], - [AC_MSG_ERROR([Failed running $QT_QMAKE to generate the makefile])]) -AS_ECHO() - diff --git a/dist/CMakeLists.txt b/dist/CMakeLists.txt deleted file mode 100644 index 0eeb49dc0..000000000 --- a/dist/CMakeLists.txt +++ /dev/null @@ -1,10 +0,0 @@ -if (APPLE) - add_subdirectory(mac) -else (APPLE) - if (UNIX) - add_subdirectory(unix) - endif (UNIX) - if (WIN32) - add_subdirectory(windows) - endif (WIN32) -endif (APPLE) diff --git a/dist/mac/CMakeLists.txt b/dist/mac/CMakeLists.txt deleted file mode 100644 index e69de29bb..000000000 diff --git a/dist/mac/Info.plist b/dist/mac/Info.plist deleted file mode 100644 index c7e42fa9c..000000000 --- a/dist/mac/Info.plist +++ /dev/null @@ -1,94 +0,0 @@ - - - - - CFBundleDocumentTypes - - - CFBundleTypeExtensions - - torrent - - CFBundleTypeIconFile - qBitTorrentDocument - CFBundleTypeName - BitTorrent Document - CFBundleTypeRole - Viewer - LSHandlerRank - Owner - LSItemContentTypes - - org.bittorrent.torrent - - LSIsAppleDefaultForType - - - - CFBundleURLTypes - - - CFBundleURLSchemes - - magnet - - CFBundleURLName - BitTorrent Magnet URL - - - CFBundleName - @EXECUTABLE@ - CFBundleIconFile - qbittorrent_mac.icns - CFBundleInfoDictionaryVersion - 6.0 - CFBundlePackageType - APPL - CFBundleShortVersionString - 3.4.0 - CFBundleSignature - qBit - CFBundleExecutable - @EXECUTABLE@ - CFBundleIdentifier - org.qbittorrent - NSPrincipalClass - NSApplication - NSHighResolutionCapable - True - NSAppleScriptEnabled - YES - NSHumanReadableCopyright - Copyright © 2006-2017 The qBittorrent project - UTExportedTypeDeclarations - - - UTTypeConformsTo - - public.data - public.item - com.bittorrent.torrent - - UTTypeDescription - BitTorrent Document - UTTypeIconFile - qBitTorrentDocument - UTTypeIdentifier - org.bittorrent.torrent - UTTypeReferenceURL - http://www.bittorrent.org/beps/bep_0000.html - UTTypeTagSpecification - - com.apple.ostype - TORR - public.filename-extension - - torrent - - public.mime-type - application/x-bittorrent - - - - - diff --git a/dist/mac/qBitTorrentDocument.icns b/dist/mac/qBitTorrentDocument.icns deleted file mode 100644 index 4132085e7..000000000 Binary files a/dist/mac/qBitTorrentDocument.icns and /dev/null differ diff --git a/dist/mac/qbittorrent_mac.icns b/dist/mac/qbittorrent_mac.icns deleted file mode 100644 index bcfffe69b..000000000 Binary files a/dist/mac/qbittorrent_mac.icns and /dev/null differ diff --git a/dist/mac/qt.conf b/dist/mac/qt.conf deleted file mode 100644 index 4c8277466..000000000 --- a/dist/mac/qt.conf +++ /dev/null @@ -1,3 +0,0 @@ -[Paths] - Translations = translations - Plugins = PlugIns diff --git a/dist/qt-translations/qt_ar.qm b/dist/qt-translations/qt_ar.qm deleted file mode 100644 index 372c1ab8f..000000000 Binary files a/dist/qt-translations/qt_ar.qm and /dev/null differ diff --git a/dist/qt-translations/qt_bg.qm b/dist/qt-translations/qt_bg.qm deleted file mode 100644 index 2cab8a1bf..000000000 Binary files a/dist/qt-translations/qt_bg.qm and /dev/null differ diff --git a/dist/qt-translations/qt_ca.qm b/dist/qt-translations/qt_ca.qm deleted file mode 100644 index b9d29a1e0..000000000 Binary files a/dist/qt-translations/qt_ca.qm and /dev/null differ diff --git a/dist/qt-translations/qt_cs.qm b/dist/qt-translations/qt_cs.qm deleted file mode 100644 index b04e24c6d..000000000 Binary files a/dist/qt-translations/qt_cs.qm and /dev/null differ diff --git a/dist/qt-translations/qt_da.qm b/dist/qt-translations/qt_da.qm deleted file mode 100644 index d198c7fd0..000000000 Binary files a/dist/qt-translations/qt_da.qm and /dev/null differ diff --git a/dist/qt-translations/qt_de.qm b/dist/qt-translations/qt_de.qm deleted file mode 100644 index 3650eec59..000000000 Binary files a/dist/qt-translations/qt_de.qm and /dev/null differ diff --git a/dist/qt-translations/qt_es.qm b/dist/qt-translations/qt_es.qm deleted file mode 100644 index 7f721faca..000000000 Binary files a/dist/qt-translations/qt_es.qm and /dev/null differ diff --git a/dist/qt-translations/qt_eu.qm b/dist/qt-translations/qt_eu.qm deleted file mode 100644 index 44beb4338..000000000 Binary files a/dist/qt-translations/qt_eu.qm and /dev/null differ diff --git a/dist/qt-translations/qt_fa.qm b/dist/qt-translations/qt_fa.qm deleted file mode 100644 index 0968c5d4e..000000000 Binary files a/dist/qt-translations/qt_fa.qm and /dev/null differ diff --git a/dist/qt-translations/qt_fi.qm b/dist/qt-translations/qt_fi.qm deleted file mode 100644 index c78467648..000000000 Binary files a/dist/qt-translations/qt_fi.qm and /dev/null differ diff --git a/dist/qt-translations/qt_fr.qm b/dist/qt-translations/qt_fr.qm deleted file mode 100644 index d40706bfa..000000000 Binary files a/dist/qt-translations/qt_fr.qm and /dev/null differ diff --git a/dist/qt-translations/qt_gl.qm b/dist/qt-translations/qt_gl.qm deleted file mode 100644 index 4f7e3c433..000000000 Binary files a/dist/qt-translations/qt_gl.qm and /dev/null differ diff --git a/dist/qt-translations/qt_he.qm b/dist/qt-translations/qt_he.qm deleted file mode 100644 index 04da4c9fa..000000000 Binary files a/dist/qt-translations/qt_he.qm and /dev/null differ diff --git a/dist/qt-translations/qt_hu.qm b/dist/qt-translations/qt_hu.qm deleted file mode 100644 index 048744323..000000000 Binary files a/dist/qt-translations/qt_hu.qm and /dev/null differ diff --git a/dist/qt-translations/qt_it.qm b/dist/qt-translations/qt_it.qm deleted file mode 100644 index a4b9f2559..000000000 Binary files a/dist/qt-translations/qt_it.qm and /dev/null differ diff --git a/dist/qt-translations/qt_ja.qm b/dist/qt-translations/qt_ja.qm deleted file mode 100644 index 99648eaa5..000000000 Binary files a/dist/qt-translations/qt_ja.qm and /dev/null differ diff --git a/dist/qt-translations/qt_ko.qm b/dist/qt-translations/qt_ko.qm deleted file mode 100644 index c01c33b73..000000000 Binary files a/dist/qt-translations/qt_ko.qm and /dev/null differ diff --git a/dist/qt-translations/qt_lt.qm b/dist/qt-translations/qt_lt.qm deleted file mode 100644 index 8a2255325..000000000 Binary files a/dist/qt-translations/qt_lt.qm and /dev/null differ diff --git a/dist/qt-translations/qt_nl.qm b/dist/qt-translations/qt_nl.qm deleted file mode 100644 index ce9f56f47..000000000 Binary files a/dist/qt-translations/qt_nl.qm and /dev/null differ diff --git a/dist/qt-translations/qt_pl.qm b/dist/qt-translations/qt_pl.qm deleted file mode 100644 index c2ea0947b..000000000 Binary files a/dist/qt-translations/qt_pl.qm and /dev/null differ diff --git a/dist/qt-translations/qt_pt.qm b/dist/qt-translations/qt_pt.qm deleted file mode 100644 index 9ac3b08d9..000000000 Binary files a/dist/qt-translations/qt_pt.qm and /dev/null differ diff --git a/dist/qt-translations/qt_pt_BR.qm b/dist/qt-translations/qt_pt_BR.qm deleted file mode 100644 index 4bafaad2e..000000000 Binary files a/dist/qt-translations/qt_pt_BR.qm and /dev/null differ diff --git a/dist/qt-translations/qt_ru.qm b/dist/qt-translations/qt_ru.qm deleted file mode 100644 index d54bae8eb..000000000 Binary files a/dist/qt-translations/qt_ru.qm and /dev/null differ diff --git a/dist/qt-translations/qt_sk.qm b/dist/qt-translations/qt_sk.qm deleted file mode 100644 index 9e8f8622d..000000000 Binary files a/dist/qt-translations/qt_sk.qm and /dev/null differ diff --git a/dist/qt-translations/qt_sl.qm b/dist/qt-translations/qt_sl.qm deleted file mode 100644 index 2575b3fab..000000000 Binary files a/dist/qt-translations/qt_sl.qm and /dev/null differ diff --git a/dist/qt-translations/qt_sv.qm b/dist/qt-translations/qt_sv.qm deleted file mode 100644 index 294ae141c..000000000 Binary files a/dist/qt-translations/qt_sv.qm and /dev/null differ diff --git a/dist/qt-translations/qt_tr.qm b/dist/qt-translations/qt_tr.qm deleted file mode 100644 index b0d14e9ff..000000000 Binary files a/dist/qt-translations/qt_tr.qm and /dev/null differ diff --git a/dist/qt-translations/qt_uk.qm b/dist/qt-translations/qt_uk.qm deleted file mode 100644 index 2d9dabc61..000000000 Binary files a/dist/qt-translations/qt_uk.qm and /dev/null differ diff --git a/dist/qt-translations/qt_zh_CN.qm b/dist/qt-translations/qt_zh_CN.qm deleted file mode 100644 index d6f3648ff..000000000 Binary files a/dist/qt-translations/qt_zh_CN.qm and /dev/null differ diff --git a/dist/qt-translations/qt_zh_TW.qm b/dist/qt-translations/qt_zh_TW.qm deleted file mode 100644 index b391a6b69..000000000 Binary files a/dist/qt-translations/qt_zh_TW.qm and /dev/null differ diff --git a/dist/qt-translations/qtbase_ca.qm b/dist/qt-translations/qtbase_ca.qm deleted file mode 100644 index 7c7cf0b82..000000000 Binary files a/dist/qt-translations/qtbase_ca.qm and /dev/null differ diff --git a/dist/qt-translations/qtbase_cs.qm b/dist/qt-translations/qtbase_cs.qm deleted file mode 100644 index 1dca943f3..000000000 Binary files a/dist/qt-translations/qtbase_cs.qm and /dev/null differ diff --git a/dist/qt-translations/qtbase_de.qm b/dist/qt-translations/qtbase_de.qm deleted file mode 100644 index d73d22032..000000000 Binary files a/dist/qt-translations/qtbase_de.qm and /dev/null differ diff --git a/dist/qt-translations/qtbase_fi.qm b/dist/qt-translations/qtbase_fi.qm deleted file mode 100644 index 980e087c3..000000000 Binary files a/dist/qt-translations/qtbase_fi.qm and /dev/null differ diff --git a/dist/qt-translations/qtbase_fr.qm b/dist/qt-translations/qtbase_fr.qm deleted file mode 100644 index 8353f0a93..000000000 Binary files a/dist/qt-translations/qtbase_fr.qm and /dev/null differ diff --git a/dist/qt-translations/qtbase_he.qm b/dist/qt-translations/qtbase_he.qm deleted file mode 100644 index 0ac1ed220..000000000 Binary files a/dist/qt-translations/qtbase_he.qm and /dev/null differ diff --git a/dist/qt-translations/qtbase_hu.qm b/dist/qt-translations/qtbase_hu.qm deleted file mode 100644 index 4b67de34e..000000000 Binary files a/dist/qt-translations/qtbase_hu.qm and /dev/null differ diff --git a/dist/qt-translations/qtbase_it.qm b/dist/qt-translations/qtbase_it.qm deleted file mode 100644 index 4c76a0b15..000000000 Binary files a/dist/qt-translations/qtbase_it.qm and /dev/null differ diff --git a/dist/qt-translations/qtbase_ja.qm b/dist/qt-translations/qtbase_ja.qm deleted file mode 100644 index 74409b1a5..000000000 Binary files a/dist/qt-translations/qtbase_ja.qm and /dev/null differ diff --git a/dist/qt-translations/qtbase_ko.qm b/dist/qt-translations/qtbase_ko.qm deleted file mode 100644 index f960d8ac4..000000000 Binary files a/dist/qt-translations/qtbase_ko.qm and /dev/null differ diff --git a/dist/qt-translations/qtbase_lv.qm b/dist/qt-translations/qtbase_lv.qm deleted file mode 100644 index c1dbfbd2e..000000000 Binary files a/dist/qt-translations/qtbase_lv.qm and /dev/null differ diff --git a/dist/qt-translations/qtbase_pl.qm b/dist/qt-translations/qtbase_pl.qm deleted file mode 100644 index 021088e4f..000000000 Binary files a/dist/qt-translations/qtbase_pl.qm and /dev/null differ diff --git a/dist/qt-translations/qtbase_ru.qm b/dist/qt-translations/qtbase_ru.qm deleted file mode 100644 index a11b7c75a..000000000 Binary files a/dist/qt-translations/qtbase_ru.qm and /dev/null differ diff --git a/dist/qt-translations/qtbase_sk.qm b/dist/qt-translations/qtbase_sk.qm deleted file mode 100644 index 5f6b2f33c..000000000 Binary files a/dist/qt-translations/qtbase_sk.qm and /dev/null differ diff --git a/dist/qt-translations/qtbase_uk.qm b/dist/qt-translations/qtbase_uk.qm deleted file mode 100644 index 7d588e99f..000000000 Binary files a/dist/qt-translations/qtbase_uk.qm and /dev/null differ diff --git a/dist/unix/CMakeLists.txt b/dist/unix/CMakeLists.txt deleted file mode 100644 index 2dfb3f4fa..000000000 --- a/dist/unix/CMakeLists.txt +++ /dev/null @@ -1,45 +0,0 @@ -if (SYSTEMD) - find_package(Systemd) - if (SYSTEMD_FOUND) - set(EXPAND_BINDIR ${CMAKE_INSTALL_FULL_BINDIR}) - configure_file(systemd/qbittorrent-nox@.service.in ${CMAKE_CURRENT_BINARY_DIR}/qbittorrent-nox@.service @ONLY) - install(FILES ${CMAKE_CURRENT_BINARY_DIR}/qbittorrent-nox@.service - DESTINATION ${SYSTEMD_SERVICES_INSTALL_DIR} - COMPONENT data) - endif(SYSTEMD_FOUND) -endif(SYSTEMD) - - -if (GUI) - list(APPEND MAN_FILES ${qBittorrent_SOURCE_DIR}/doc/qbittorrent.1) -else (GUI) - list(APPEND MAN_FILES ${qBittorrent_SOURCE_DIR}/doc/qbittorrent-nox.1) -endif (GUI) - -install(FILES ${MAN_FILES} - DESTINATION ${CMAKE_INSTALL_MANDIR}/man1 - COMPONENT doc) - -if (GUI) - install(DIRECTORY menuicons/ - DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor - FILES_MATCHING PATTERN "*.png") - - install(FILES ${qBittorrent_SOURCE_DIR}/src/icons/qbittorrent.png - DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/pixmaps/ - COMPONENT data) - - install(FILES ${qBittorrent_SOURCE_DIR}/src/icons/qbittorrent.desktop - DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/applications/ - COMPONENT data) - - install(FILES qbittorrent.appdata.xml - DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/appdata/ - COMPONENT data) - - install(FILES - ${qBittorrent_SOURCE_DIR}/src/icons/skin/qbittorrent-tray-dark.svg - ${qBittorrent_SOURCE_DIR}/src/icons/skin/qbittorrent-tray-light.svg - DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/scalable/status - COMPONENT data) -endif() diff --git a/dist/unix/menuicons/128x128/apps/qbittorrent.png b/dist/unix/menuicons/128x128/apps/qbittorrent.png deleted file mode 100644 index d66343bac..000000000 Binary files a/dist/unix/menuicons/128x128/apps/qbittorrent.png and /dev/null differ diff --git a/dist/unix/menuicons/128x128/status/qbittorrent-tray.png b/dist/unix/menuicons/128x128/status/qbittorrent-tray.png deleted file mode 100644 index d66343bac..000000000 Binary files a/dist/unix/menuicons/128x128/status/qbittorrent-tray.png and /dev/null differ diff --git a/dist/unix/menuicons/16x16/apps/qbittorrent.png b/dist/unix/menuicons/16x16/apps/qbittorrent.png deleted file mode 100644 index 440f254fa..000000000 Binary files a/dist/unix/menuicons/16x16/apps/qbittorrent.png and /dev/null differ diff --git a/dist/unix/menuicons/16x16/status/qbittorrent-tray.png b/dist/unix/menuicons/16x16/status/qbittorrent-tray.png deleted file mode 100644 index 440f254fa..000000000 Binary files a/dist/unix/menuicons/16x16/status/qbittorrent-tray.png and /dev/null differ diff --git a/dist/unix/menuicons/192x192/apps/qbittorrent.png b/dist/unix/menuicons/192x192/apps/qbittorrent.png deleted file mode 100644 index 9ec69b38a..000000000 Binary files a/dist/unix/menuicons/192x192/apps/qbittorrent.png and /dev/null differ diff --git a/dist/unix/menuicons/192x192/status/qbittorrent-tray.png b/dist/unix/menuicons/192x192/status/qbittorrent-tray.png deleted file mode 100644 index 9ec69b38a..000000000 Binary files a/dist/unix/menuicons/192x192/status/qbittorrent-tray.png and /dev/null differ diff --git a/dist/unix/menuicons/22x22/apps/qbittorrent.png b/dist/unix/menuicons/22x22/apps/qbittorrent.png deleted file mode 100644 index 6da1543cd..000000000 Binary files a/dist/unix/menuicons/22x22/apps/qbittorrent.png and /dev/null differ diff --git a/dist/unix/menuicons/22x22/status/qbittorrent-tray.png b/dist/unix/menuicons/22x22/status/qbittorrent-tray.png deleted file mode 100644 index 6da1543cd..000000000 Binary files a/dist/unix/menuicons/22x22/status/qbittorrent-tray.png and /dev/null differ diff --git a/dist/unix/menuicons/24x24/apps/qbittorrent.png b/dist/unix/menuicons/24x24/apps/qbittorrent.png deleted file mode 100644 index 32267058c..000000000 Binary files a/dist/unix/menuicons/24x24/apps/qbittorrent.png and /dev/null differ diff --git a/dist/unix/menuicons/24x24/status/qbittorrent-tray.png b/dist/unix/menuicons/24x24/status/qbittorrent-tray.png deleted file mode 100644 index 32267058c..000000000 Binary files a/dist/unix/menuicons/24x24/status/qbittorrent-tray.png and /dev/null differ diff --git a/dist/unix/menuicons/32x32/apps/qbittorrent.png b/dist/unix/menuicons/32x32/apps/qbittorrent.png deleted file mode 100644 index ba838a3d3..000000000 Binary files a/dist/unix/menuicons/32x32/apps/qbittorrent.png and /dev/null differ diff --git a/dist/unix/menuicons/32x32/status/qbittorrent-tray.png b/dist/unix/menuicons/32x32/status/qbittorrent-tray.png deleted file mode 100644 index ba838a3d3..000000000 Binary files a/dist/unix/menuicons/32x32/status/qbittorrent-tray.png and /dev/null differ diff --git a/dist/unix/menuicons/36x36/apps/qbittorrent.png b/dist/unix/menuicons/36x36/apps/qbittorrent.png deleted file mode 100644 index ba3d44999..000000000 Binary files a/dist/unix/menuicons/36x36/apps/qbittorrent.png and /dev/null differ diff --git a/dist/unix/menuicons/36x36/status/qbittorrent-tray.png b/dist/unix/menuicons/36x36/status/qbittorrent-tray.png deleted file mode 100644 index ba3d44999..000000000 Binary files a/dist/unix/menuicons/36x36/status/qbittorrent-tray.png and /dev/null differ diff --git a/dist/unix/menuicons/48x48/apps/qbittorrent.png b/dist/unix/menuicons/48x48/apps/qbittorrent.png deleted file mode 100644 index 2c49158cd..000000000 Binary files a/dist/unix/menuicons/48x48/apps/qbittorrent.png and /dev/null differ diff --git a/dist/unix/menuicons/48x48/status/qbittorrent-tray.png b/dist/unix/menuicons/48x48/status/qbittorrent-tray.png deleted file mode 100644 index 2c49158cd..000000000 Binary files a/dist/unix/menuicons/48x48/status/qbittorrent-tray.png and /dev/null differ diff --git a/dist/unix/menuicons/64x64/apps/qbittorrent.png b/dist/unix/menuicons/64x64/apps/qbittorrent.png deleted file mode 100644 index edfe65866..000000000 Binary files a/dist/unix/menuicons/64x64/apps/qbittorrent.png and /dev/null differ diff --git a/dist/unix/menuicons/64x64/status/qbittorrent-tray.png b/dist/unix/menuicons/64x64/status/qbittorrent-tray.png deleted file mode 100644 index edfe65866..000000000 Binary files a/dist/unix/menuicons/64x64/status/qbittorrent-tray.png and /dev/null differ diff --git a/dist/unix/menuicons/72x72/apps/qbittorrent.png b/dist/unix/menuicons/72x72/apps/qbittorrent.png deleted file mode 100644 index 8958cfb45..000000000 Binary files a/dist/unix/menuicons/72x72/apps/qbittorrent.png and /dev/null differ diff --git a/dist/unix/menuicons/72x72/status/qbittorrent-tray.png b/dist/unix/menuicons/72x72/status/qbittorrent-tray.png deleted file mode 100644 index 8958cfb45..000000000 Binary files a/dist/unix/menuicons/72x72/status/qbittorrent-tray.png and /dev/null differ diff --git a/dist/unix/menuicons/96x96/apps/qbittorrent.png b/dist/unix/menuicons/96x96/apps/qbittorrent.png deleted file mode 100644 index a7e8f781e..000000000 Binary files a/dist/unix/menuicons/96x96/apps/qbittorrent.png and /dev/null differ diff --git a/dist/unix/menuicons/96x96/status/qbittorrent-tray.png b/dist/unix/menuicons/96x96/status/qbittorrent-tray.png deleted file mode 100644 index a7e8f781e..000000000 Binary files a/dist/unix/menuicons/96x96/status/qbittorrent-tray.png and /dev/null differ diff --git a/dist/unix/qbittorrent.appdata.xml b/dist/unix/qbittorrent.appdata.xml deleted file mode 100644 index 8d3214ad0..000000000 --- a/dist/unix/qbittorrent.appdata.xml +++ /dev/null @@ -1,66 +0,0 @@ - - - - qbittorrent.desktop - CC0-1.0 - GPL-2.0 and OpenSSL - qBittorrent - A Bittorrent Client - -

- Aiming to be a good alternative to all other bittorrent clients out - there, qBittorrent is fast, stable and provides unicode support as well - as many other features. Additionally, qBittorrent runs and provides those - same features on all major platforms (Linux, Mac OS X, Windows, OS/2, FreeBSD). -

-

- It is programmed in C++ / Qt and uses libtorrent (sometimes called - libtorrent-rasterbar) by Arvid Norberg. GeoLite data, created by MaxMind, - are included in qBittorrent. Its features include: -

-
    -
  • Polished µTorrent-like User Interface
  • -
  • Well-integrated and extensible Search Engine
  • -
  • All Bittorrent extensions (DHT, Peer Exchange, Full encryption, Magnet/BitComet URIs, ...)
  • -
  • Remote control through a Web user interface
  • -
  • Advanced control over trackers, peers and torrents
  • -
  • UPnP / NAT-PMP port forwarding support
  • -
  • Available in ~25 languages (Unicode support)
  • -
  • Torrent creation tool
  • -
  • Advanced RSS support with download filters (inc. regex)
  • -
  • Bandwidth scheduler
  • -
  • IP Filtering (eMule and PeerGuardian compatible)
  • -
  • IPv6 compliant
  • -
  • Sequential downloading (aka "Download in order")
  • -
-
- - - - https://alexpl.fedorapeople.org/AppData/qbittorrent/screens/qbittorrent_01.png - - - - - https://alexpl.fedorapeople.org/AppData/qbittorrent/screens/qbittorrent_02.png - - - - - https://alexpl.fedorapeople.org/AppData/qbittorrent/screens/qbittorrent_03.png - - - - - https://alexpl.fedorapeople.org/AppData/qbittorrent/screens/qbittorrent_04.png - - - - http://www.qbittorrent.org/ - sledgehammer999@qbittorrent.org - The qBittorrent Project - http://bugs.qbittorrent.org/ - https://www.qbittorrent.org/donate - http://forum.qbittorrent.org/ - https://github.com/qbittorrent/qBittorrent/wiki/How-to-translate-qBittorrent -
diff --git a/dist/unix/systemd/qbittorrent-nox@.service.in b/dist/unix/systemd/qbittorrent-nox@.service.in deleted file mode 100644 index 59396a844..000000000 --- a/dist/unix/systemd/qbittorrent-nox@.service.in +++ /dev/null @@ -1,14 +0,0 @@ -[Unit] -Description=qBittorrenti-nox service for user %I - -Documentation=man:qbittorrent-nox(1) -After=network.target - -[Service] -Type=simple -PrivateTmp=false -User=%i -ExecStart=@EXPAND_BINDIR@/qbittorrent-nox - -[Install] -WantedBy=multi-user.target diff --git a/dist/windows/CMakeLists.txt b/dist/windows/CMakeLists.txt deleted file mode 100644 index f1a8169b9..000000000 --- a/dist/windows/CMakeLists.txt +++ /dev/null @@ -1 +0,0 @@ -install(FILES qt.conf DESTINATION ${CMAKE_INSTALL_BINDIR}) diff --git a/dist/windows/README.txt b/dist/windows/README.txt deleted file mode 100644 index fa8b745ad..000000000 --- a/dist/windows/README.txt +++ /dev/null @@ -1,67 +0,0 @@ -TRANSLATORS: - -1. Use an editor that has NSIS syntax highlighting(eg Notepad++/Geany). This will - make your life easier. -2. Open the relevant .nsi file that exists in the folder named - "installer-translations" -3. Lines starting with ";" are considered comments. These include the - english message to help you with the translation. -4. Edit only the part inside the quotation marks(""). Unless you know - what you are doing. -5. Save the files with utf8 encoding and BOM. -6. Submit your changes: 1) as a pull request to the official git repo or - 2) open an issue to the bugtracker and attach them or 3) via email or - 4)the same way you provide the translations for qbt itself - -PACKAGERS: - -You will need NSIS and upx to make the installer. You need a unicode version of NSIS. -I tested with NSIS 3.0 (final). - -1. Open the options.nsi file in an editor and change line that contains - "!define PROG_VERSION "3.0.3"" to the version of qbittorrent you just built. -2. Extract the plugins found in the folder "nsis plugins" into your - NSIS's unicode Plugin directory(usually C:\Program Files\NSIS\Plugins\x86-unicode). - Only the *.dll files are needed. Use the unicode version of the dlls. -3. The script you need to compile is "qbittorrent.nsi". It includes all other necessary scripts. -4. The script expects the following file tree: - -The installer script expects the following file tree: - -Root: -installer-translations - afrikaans.nsi - .... - (all the .nsi files found here in every source release) - welsh.nsi -translations - qt_ar.qm - ... - (all the .qm files found in the 'translations' folder of your Qt install. Those files differ between Qt4 and Qt5. - If you want to distribute Qt4 translations it is better to use the ones found in this repo under the path "dist/qt-translations". - They contain extra languages not distributed via the official qt4 sources. - Don't forget to edit the filelist in installer.nsi + uninstaller.nsi to include all your .qm files.) - qt_zh_TW.qm -installer.nsi -license.txt -options.nsi -qbittorrent.exe -qbittorrent.nsi -qt.conf -translations.nsi -UAC.nsh -uninstaller.nsi - - -5. "license.txt" is a text file that contains the text rendered - from src\gui\gpl.html or the text contained in COPYING -6. "qbittorrent.exe" is the compiled binary file. - -SCRIPT HACKERS: - -If you add any new LangString variable to the scripts you NEED to provide -"translations" of it to all the .nsi files inside "installer-translations. -You can always leave the english string but you have to use all the LANG_ -for the given variable. Otherwise, if the user chooses a language that you -haven't provided a LANG_ for your variable then your string will be empty. -Don't worry though, NSIS throws warnings for this when compiling the scripts. diff --git a/dist/windows/UAC.nsh b/dist/windows/UAC.nsh deleted file mode 100644 index 08979aba9..000000000 --- a/dist/windows/UAC.nsh +++ /dev/null @@ -1,299 +0,0 @@ -/*** UAC Plug-in *** - -Interactive User (MediumIL) Admin user (HighIL) -***[Setup.exe]************* ***[Setup.exe]************** -* * * * -* +++[.OnInit]+++++++++++ * * +++[.OnInit]++++++++++++ * -* + UAC_RunElevated >---+-+----> * + + * -* + NSIS.Quit + * * + + * -* +++++++++++++++++++++++ * * ++++++++++++++++++++++++ * -* * * * -* * * * -* +++[Section]+++++++++++ * * +++[Section]++++++++++++ * -* + + * /--+-+- -** -** Get integrity level of current process -** -**/ -!macro UAC_GetIntegrityLevel outvar -UAC::_ 6 -!if "${outvar}" != "s" - Pop ${outvar} -!endif -!macroend - - - -/* UAC_IsAdmin -** -** Is the current process running with administrator privileges? Result in $0 -** -** ${If} ${UAC_IsAdmin} ... -** -**/ -!macro UAC_IsAdmin -UAC::_ 2 -!macroend -!define UAC_IsAdmin `"" UAC_IsAdmin ""` -!macro _UAC_IsAdmin _a _b _t _f -!insertmacro _UAC_MakeLL_Cmp _!= 0 2s -!macroend - - - -/* UAC_IsInnerInstance -** -** Does the current process have a NSIS/UAC parent process that is part of the elevation operation? -** -** ${If} ${UAC_IsInnerInstance} ... -** -**/ -!macro UAC_IsInnerInstance -UAC::_ 3 -!macroend -!define UAC_IsInnerInstance `"" UAC_IsInnerInstance ""` -!macro _UAC_IsInnerInstance _a _b _t _f -!insertmacro _UAC_MakeLL_Cmp _!= 0 3s -!macroend - - - -/* UAC_PageElevation_OnInit, UAC_PageElevation_OnGuiInit, -** -** Helper macros for elevation on a custom elevation page, see the DualMode example for more information. -** -**/ -!macro UAC_Notify_OnGuiInit -UAC::_ 4 -!macroend -!macro UAC_PageElevation_OnGuiInit -!insertmacro UAC_Notify_OnGuiInit -!macroend -!macro UAC_PageElevation_OnInit -UAC::_ 5 -${IfThen} ${Errors} ${|} Quit ${|} -!macroend - - - -/* UAC_AsUser_Call -** -** Calls a function or label in the user process instance. -** All the UAC_AsUser_* macros use this helper macro. -** -**/ -!define UAC_SYNCREGISTERS 0x1 -;define UAC_SYNCSTACK 0x2 -!define UAC_SYNCOUTDIR 0x4 -!define UAC_SYNCINSTDIR 0x8 -;define UAC_CLEARERRFLAG 0x10 -!macro UAC_AsUser_Call type name flags -push $0 -Get${type}Address $0 ${name} -!verbose push -!verbose ${UAC_VERBOSE} -!insertmacro _UAC_ParseDefineFlagsToInt _UAC_AsUser_Call__flags ${flags} -!verbose pop -StrCpy $0 "1$0:${_UAC_AsUser_Call__flags}" -!undef _UAC_AsUser_Call__flags -Exch $0 -UAC::_ -!macroend - - - -/* -** UAC_AsUser_GetSection -*/ -!macro UAC_AsUser_GetSection secprop secidx outvar -!insertmacro _UAC_AsUser_GenOp ${outvar} SectionGet${secprop} ${secidx} "" -!macroend - - - -/* -** UAC_AsUser_GetGlobalVar -** UAC_AsUser_GetGlobal -*/ -!macro UAC_AsUser_GetGlobalVar var -!insertmacro _UAC_AsUser_GenOp ${var} StrCpy "" ${var} -!macroend -!macro UAC_AsUser_GetGlobal outvar srcvar -!insertmacro _UAC_AsUser_GenOp ${outvar} StrCpy "" ${srcvar} -!macroend - - - -/* -** UAC_AsUser_ExecShell -** -** Call ExecShell in the user process instance. -** -*/ -!macro UAC_AsUser_ExecShell verb command params workdir show -!insertmacro _UAC_IncL -goto _UAC_L_E_${__UAC_L} -_UAC_L_F_${__UAC_L}: -ExecShell "${verb}" "${command}" '${params}' ${show} -return -_UAC_L_E_${__UAC_L}: -!if "${workdir}" != "" - push $outdir - SetOutPath "${workdir}" -!endif -!insertmacro UAC_AsUser_Call Label _UAC_L_F_${__UAC_L} ${UAC_SYNCREGISTERS}|${UAC_SYNCOUTDIR}|${UAC_SYNCINSTDIR} #|${UAC_CLEARERRFLAG} -!if "${workdir}" != "" - pop $outdir - SetOutPath $outdir -!endif -!macroend - - - -!macro _UAC_MakeLL_Cmp cmpop cmp pluginparams -!insertmacro _LOGICLIB_TEMP -UAC::_ ${pluginparams} -pop $_LOGICLIB_TEMP -!insertmacro ${cmpop} $_LOGICLIB_TEMP ${cmp} `${_t}` `${_f}` -!macroend -!macro _UAC_definemath def val1 op val2 -!define /math _UAC_definemath "${val1}" ${op} ${val2} -!ifdef ${def} - !undef ${def} -!endif -!define ${def} "${_UAC_definemath}" -!undef _UAC_definemath -!macroend -!macro _UAC_ParseDefineFlags_orin parse outflags -!searchparse /noerrors ${${parse}} "" _UAC_ParseDefineFlags_orin_f1 "|" _UAC_ParseDefineFlags_orin_f2 -!define _UAC_ParseDefineFlags_orin_this ${_UAC_ParseDefineFlags_orin_f1} -!undef ${parse} -!define ${parse} ${_UAC_ParseDefineFlags_orin_f2} -!define _UAC_ParseDefineFlags_orin_saveout ${${outflags}} -!undef ${outflags} -!define /math ${outflags} "${_UAC_ParseDefineFlags_orin_saveout}" | "${_UAC_ParseDefineFlags_orin_this}" -!undef _UAC_ParseDefineFlags_orin_saveout -!undef _UAC_ParseDefineFlags_orin_this -!ifdef _UAC_ParseDefineFlags_orin_f1 - !undef _UAC_ParseDefineFlags_orin_f1 -!endif -!ifdef _UAC_ParseDefineFlags_orin_f2 - !undef _UAC_ParseDefineFlags_orin_f2 -!endif -!macroend -!macro _UAC_ParseDefineFlags_Begin _outdef _in -!define _UAC_PDF${_outdef}_parse "${_in}" -!define _UAC_PDF${_outdef}_flags "" -!define _UAC_PDF${_outdef}_r 0 -!insertmacro _UAC_ParseDefineFlags_orin _UAC_PDF${_outdef}_parse _UAC_PDF${_outdef}_flags ;0x1 -!insertmacro _UAC_ParseDefineFlags_orin _UAC_PDF${_outdef}_parse _UAC_PDF${_outdef}_flags ;0x2 -!insertmacro _UAC_ParseDefineFlags_orin _UAC_PDF${_outdef}_parse _UAC_PDF${_outdef}_flags ;0x4 -!insertmacro _UAC_ParseDefineFlags_orin _UAC_PDF${_outdef}_parse _UAC_PDF${_outdef}_flags ;0x8 -!insertmacro _UAC_ParseDefineFlags_orin _UAC_PDF${_outdef}_parse _UAC_PDF${_outdef}_flags ;0x10 -!macroend -!macro _UAC_ParseDefineFlags_End _outdef -!define ${_outdef} ${_UAC_PDF${_outdef}_r} -!undef _UAC_PDF${_outdef}_r -!undef _UAC_PDF${_outdef}_flags -!undef _UAC_PDF${_outdef}_parse -!macroend -!macro _UAC_ParseDefineFlags_IncludeFlag _outdef flag -!if ${_UAC_PDF${_outdef}_flags} & ${flag} - !insertmacro _UAC_definemath _UAC_PDF${_outdef}_r ${_UAC_PDF${_outdef}_r} | ${flag} -!endif -!macroend -!macro _UAC_ParseDefineFlagsToInt _outdef _in -!insertmacro _UAC_ParseDefineFlags_Begin _UAC_ParseDefineFlagsToInt_tmp "${_in}" -!define ${_outdef} ${_UAC_PDF_UAC_ParseDefineFlagsToInt_tmp_flags} -!insertmacro _UAC_ParseDefineFlags_End _UAC_ParseDefineFlagsToInt_tmp -!undef _UAC_ParseDefineFlagsToInt_tmp -!macroend -!macro _UAC_IncL -!insertmacro _UAC_definemath __UAC_L "${__UAC_L}" + 1 -!macroend -!macro _UAC_AsUser_GenOp outvar op opparam1 opparam2 -!define _UAC_AUGOGR_ID _UAC_AUGOGR_OP${outvar}${op}${opparam1}${opparam2} -!ifndef ${_UAC_AUGOGR_ID} ;Has this exact action been done before? - !if ${outvar} == $0 - !define ${_UAC_AUGOGR_ID} $1 - !else - !define ${_UAC_AUGOGR_ID} $0 - !endif - !if "${opparam1}" == "" - !define _UAC_AUGOGR_OPP1 ${${_UAC_AUGOGR_ID}} - !define _UAC_AUGOGR_OPP2 ${opparam2} - !else - !define _UAC_AUGOGR_OPP1 ${opparam1} - !define _UAC_AUGOGR_OPP2 ${${_UAC_AUGOGR_ID}} - !endif - goto ${_UAC_AUGOGR_ID}_C - ${_UAC_AUGOGR_ID}_F: - ${op} ${_UAC_AUGOGR_OPP1} ${_UAC_AUGOGR_OPP2} - return - ${_UAC_AUGOGR_ID}_C: - !undef _UAC_AUGOGR_OPP1 - !undef _UAC_AUGOGR_OPP2 -!endif -push ${${_UAC_AUGOGR_ID}} -!insertmacro UAC_AsUser_Call Label ${_UAC_AUGOGR_ID}_F ${UAC_SYNCREGISTERS} -StrCpy ${outvar} ${${_UAC_AUGOGR_ID}} -pop ${${_UAC_AUGOGR_ID}} -!undef _UAC_AUGOGR_ID -!macroend - - - -!verbose pop -!endif /* UAC_HDR__INC */ \ No newline at end of file diff --git a/dist/windows/installer-translations/afrikaans.nsi b/dist/windows/installer-translations/afrikaans.nsi deleted file mode 100644 index 54f0fb3f6..000000000 --- a/dist/windows/installer-translations/afrikaans.nsi +++ /dev/null @@ -1,53 +0,0 @@ -;Installer strings - -;LangString inst_qbt_req ${LANG_ENGLISH} "qBittorrent (required)" -LangString inst_qbt_req ${LANG_AFRIKAANS} "qBittorrent (required)" -;LangString inst_dekstop ${LANG_ENGLISH} "Create Desktop Shortcut" -LangString inst_dekstop ${LANG_AFRIKAANS} "Create Desktop Shortcut" -;LangString inst_startmenu ${LANG_ENGLISH} "Create Start Menu Shortcut" -LangString inst_startmenu ${LANG_AFRIKAANS} "Create Start Menu Shortcut" -;LangString inst_torrent ${LANG_ENGLISH} "Open .torrent files with qBittorrent" -LangString inst_torrent ${LANG_AFRIKAANS} "Open .torrent files with qBittorrent" -;LangString inst_magnet ${LANG_ENGLISH} "Open magnet links with qBittorrent" -LangString inst_magnet ${LANG_AFRIKAANS} "Open magnet links with qBittorrent" -;LangString inst_firewall ${LANG_ENGLISH} "Add Windows Firewall rule" -LangString inst_firewall ${LANG_AFRIKAANS} "Add Windows Firewall rule" -;LangString inst_firewallinfo ${LANG_ENGLISH} "Adding Windows Firewall rule" -LangString inst_firewallinfo ${LANG_AFRIKAANS} "Adding Windows Firewall rule" -;LangString inst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before installing." -LangString inst_warning ${LANG_AFRIKAANS} "qBittorrent is running. Please close the application before installing." -;LangString inst_uninstall_question ${LANG_ENGLISH} "A previous installation was detected. It will be uninstalled without deleting user settings." -LangString inst_uninstall_question ${LANG_AFRIKAANS} "A previous installation was detected. It will be uninstalled without deleting user settings." -;LangString inst_unist ${LANG_ENGLISH} "Uninstalling previous version." -LangString inst_unist ${LANG_AFRIKAANS} "Uninstalling previous version." -;LangString launch_qbt ${LANG_ENGLISH} "Launch qBittorrent." -LangString launch_qbt ${LANG_AFRIKAANS} "Launch qBittorrent." -;LangString inst_requires_64bit ${LANG_ENGLISH} "This installer works only in 64-bit Windows versions." -LangString inst_requires_64bit ${LANG_AFRIKAANS} "This installer works only in 64-bit Windows versions." - - -;------------------------------------ -;Uninstaller strings - -;LangString remove_files ${LANG_ENGLISH} "Remove files" -LangString remove_files ${LANG_AFRIKAANS} "Remove files" -;LangString remove_shortcuts ${LANG_ENGLISH} "Remove shortcuts" -LangString remove_shortcuts ${LANG_AFRIKAANS} "Remove shortcuts" -;LangString remove_associations ${LANG_ENGLISH} "Remove file associations" -LangString remove_associations ${LANG_AFRIKAANS} "Remove file associations" -;LangString remove_registry ${LANG_ENGLISH} "Remove registry keys" -LangString remove_registry ${LANG_AFRIKAANS} "Remove registry keys" -;LangString remove_conf ${LANG_ENGLISH} "Remove configuration files" -LangString remove_conf ${LANG_AFRIKAANS} "Remove configuration files" -;LangString remove_firewall ${LANG_ENGLISH} "Remove Windows Firewall rule" -LangString remove_firewall ${LANG_AFRIKAANS} "Remove Windows Firewall rule" -;LangString remove_firewallinfo ${LANG_ENGLISH} "Removing Windows Firewall rule" -LangString remove_firewallinfo ${LANG_AFRIKAANS} "Removing Windows Firewall rule" -;LangString remove_cache ${LANG_ENGLISH} "Remove torrents and cached data" -LangString remove_cache ${LANG_AFRIKAANS} "Remove torrents and cached data" -;LangString uninst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before uninstalling." -LangString uninst_warning ${LANG_AFRIKAANS} "qBittorrent is running. Please close the application before uninstalling." -;LangString uninst_tor_warn ${LANG_ENGLISH} "Not removing .torrent association. It is associated with:" -LangString uninst_tor_warn ${LANG_AFRIKAANS} "Not removing .torrent association. It is associated with:" -;LangString uninst_mag_warn ${LANG_ENGLISH} "Not removing magnet association. It is associated with:" -LangString uninst_mag_warn ${LANG_AFRIKAANS} "Not removing magnet association. It is associated with:" diff --git a/dist/windows/installer-translations/albanian.nsi b/dist/windows/installer-translations/albanian.nsi deleted file mode 100644 index 89fb95782..000000000 --- a/dist/windows/installer-translations/albanian.nsi +++ /dev/null @@ -1,53 +0,0 @@ -;Installer strings - -;LangString inst_qbt_req ${LANG_ENGLISH} "qBittorrent (required)" -LangString inst_qbt_req ${LANG_ALBANIAN} "qBittorrent (required)" -;LangString inst_dekstop ${LANG_ENGLISH} "Create Desktop Shortcut" -LangString inst_dekstop ${LANG_ALBANIAN} "Create Desktop Shortcut" -;LangString inst_startmenu ${LANG_ENGLISH} "Create Start Menu Shortcut" -LangString inst_startmenu ${LANG_ALBANIAN} "Create Start Menu Shortcut" -;LangString inst_torrent ${LANG_ENGLISH} "Open .torrent files with qBittorrent" -LangString inst_torrent ${LANG_ALBANIAN} "Open .torrent files with qBittorrent" -;LangString inst_magnet ${LANG_ENGLISH} "Open magnet links with qBittorrent" -LangString inst_magnet ${LANG_ALBANIAN} "Open magnet links with qBittorrent" -;LangString inst_firewall ${LANG_ENGLISH} "Add Windows Firewall rule" -LangString inst_firewall ${LANG_ALBANIAN} "Add Windows Firewall rule" -;LangString inst_firewallinfo ${LANG_ENGLISH} "Adding Windows Firewall rule" -LangString inst_firewallinfo ${LANG_ALBANIAN} "Adding Windows Firewall rule" -;LangString inst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before installing." -LangString inst_warning ${LANG_ALBANIAN} "qBittorrent is running. Please close the application before installing." -;LangString inst_uninstall_question ${LANG_ENGLISH} "A previous installation was detected. It will be uninstalled without deleting user settings." -LangString inst_uninstall_question ${LANG_ALBANIAN} "A previous installation was detected. It will be uninstalled without deleting user settings." -;LangString inst_unist ${LANG_ENGLISH} "Uninstalling previous version." -LangString inst_unist ${LANG_ALBANIAN} "Uninstalling previous version." -;LangString launch_qbt ${LANG_ENGLISH} "Launch qBittorrent." -LangString launch_qbt ${LANG_ALBANIAN} "Launch qBittorrent." -;LangString inst_requires_64bit ${LANG_ENGLISH} "This installer works only in 64-bit Windows versions." -LangString inst_requires_64bit ${LANG_ALBANIAN} "This installer works only in 64-bit Windows versions." - - -;------------------------------------ -;Uninstaller strings - -;LangString remove_files ${LANG_ENGLISH} "Remove files" -LangString remove_files ${LANG_ALBANIAN} "Remove files" -;LangString remove_shortcuts ${LANG_ENGLISH} "Remove shortcuts" -LangString remove_shortcuts ${LANG_ALBANIAN} "Remove shortcuts" -;LangString remove_associations ${LANG_ENGLISH} "Remove file associations" -LangString remove_associations ${LANG_ALBANIAN} "Remove file associations" -;LangString remove_registry ${LANG_ENGLISH} "Remove registry keys" -LangString remove_registry ${LANG_ALBANIAN} "Remove registry keys" -;LangString remove_conf ${LANG_ENGLISH} "Remove configuration files" -LangString remove_conf ${LANG_ALBANIAN} "Remove configuration files" -;LangString remove_firewall ${LANG_ENGLISH} "Remove Windows Firewall rule" -LangString remove_firewall ${LANG_ALBANIAN} "Remove Windows Firewall rule" -;LangString remove_firewallinfo ${LANG_ENGLISH} "Removing Windows Firewall rule" -LangString remove_firewallinfo ${LANG_ALBANIAN} "Removing Windows Firewall rule" -;LangString remove_cache ${LANG_ENGLISH} "Remove torrents and cached data" -LangString remove_cache ${LANG_ALBANIAN} "Remove torrents and cached data" -;LangString uninst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before uninstalling." -LangString uninst_warning ${LANG_ALBANIAN} "qBittorrent is running. Please close the application before uninstalling." -;LangString uninst_tor_warn ${LANG_ENGLISH} "Not removing .torrent association. It is associated with:" -LangString uninst_tor_warn ${LANG_ALBANIAN} "Not removing .torrent association. It is associated with:" -;LangString uninst_mag_warn ${LANG_ENGLISH} "Not removing magnet association. It is associated with:" -LangString uninst_mag_warn ${LANG_ALBANIAN} "Not removing magnet association. It is associated with:" diff --git a/dist/windows/installer-translations/arabic.nsi b/dist/windows/installer-translations/arabic.nsi deleted file mode 100644 index a54bd9890..000000000 --- a/dist/windows/installer-translations/arabic.nsi +++ /dev/null @@ -1,53 +0,0 @@ -;Installer strings - -;LangString inst_qbt_req ${LANG_ENGLISH} "qBittorrent (required)" -LangString inst_qbt_req ${LANG_ARABIC} "qBittorrent (مطلوب)" -;LangString inst_dekstop ${LANG_ENGLISH} "Create Desktop Shortcut" -LangString inst_dekstop ${LANG_ARABIC} "وضع اختصار على سطح المكتب" -;LangString inst_startmenu ${LANG_ENGLISH} "Create Start Menu Shortcut" -LangString inst_startmenu ${LANG_ARABIC} "وضع اختصار في قائمة البداية" -;LangString inst_torrent ${LANG_ENGLISH} "Open .torrent files with qBittorrent" -LangString inst_torrent ${LANG_ARABIC} "فتح ملفات التورنت باستخدام qBittorrent" -;LangString inst_magnet ${LANG_ENGLISH} "Open magnet links with qBittorrent" -LangString inst_magnet ${LANG_ARABIC} "فتح الروابط المغناطيسية باستخدام qBittorrent" -;LangString inst_firewall ${LANG_ENGLISH} "Add Windows Firewall rule" -LangString inst_firewall ${LANG_ARABIC} "اضافة قاعدة للجدار الناري لويندوز" -;LangString inst_firewallinfo ${LANG_ENGLISH} "Adding Windows Firewall rule" -LangString inst_firewallinfo ${LANG_ARABIC} "جاري اضافة القاعدة للجدار الناري" -;LangString inst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before installing." -LangString inst_warning ${LANG_ARABIC} "البرنامج يعمل. يرجى اغلاقه قبل البدء في التنصيب" -;LangString inst_uninstall_question ${LANG_ENGLISH} "A previous installation was detected. It will be uninstalled without deleting user settings." -LangString inst_uninstall_question ${LANG_ARABIC} "يوجد نسخة سابقة من البرنامج. سيتم إزالتها دون حذف إعدادات المستخدم" -;LangString inst_unist ${LANG_ENGLISH} "Uninstalling previous version." -LangString inst_unist ${LANG_ARABIC} "جاري ازالة النسخة السابقة من البرنامج" -;LangString launch_qbt ${LANG_ENGLISH} "Launch qBittorrent." -LangString launch_qbt ${LANG_ARABIC} "تشغيل البرنامج" -;LangString inst_requires_64bit ${LANG_ENGLISH} "This installer works only in 64-bit Windows versions." -LangString inst_requires_64bit ${LANG_ARABIC} "هذا المثبت يعمل فقط في نسخ ويندوز 64 بت" - - -;------------------------------------ -;Uninstaller strings - -;LangString remove_files ${LANG_ENGLISH} "Remove files" -LangString remove_files ${LANG_ARABIC} "ازالة الملفات" -;LangString remove_shortcuts ${LANG_ENGLISH} "Remove shortcuts" -LangString remove_shortcuts ${LANG_ARABIC} "ازالة الاختصارات" -;LangString remove_associations ${LANG_ENGLISH} "Remove file associations" -LangString remove_associations ${LANG_ARABIC} "ازالة ارتباطات البرنامج بالملفات" -;LangString remove_registry ${LANG_ENGLISH} "Remove registry keys" -LangString remove_registry ${LANG_ARABIC} "ازالة المفاتيح الموجودة في الريجستري" -;LangString remove_conf ${LANG_ENGLISH} "Remove configuration files" -LangString remove_conf ${LANG_ARABIC} "ازالة اعدادات البرنامج" -;LangString remove_firewall ${LANG_ENGLISH} "Remove Windows Firewall rule" -LangString remove_firewall ${LANG_ARABIC} "حذف قاعدة الجدار الناري" -;LangString remove_firewallinfo ${LANG_ENGLISH} "Removing Windows Firewall rule" -LangString remove_firewallinfo ${LANG_ARABIC} "جاري حذف قاعدة الجدار الناري" -;LangString remove_cache ${LANG_ENGLISH} "Remove torrents and cached data" -LangString remove_cache ${LANG_ARABIC} "ازالة التورنتات و الملفات المحفوظة مسبقا" -;LangString uninst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before uninstalling." -LangString uninst_warning ${LANG_ARABIC} "البرنامج يعمل. يرجى اغلاقه قبل البدء في ازالة التنصيب" -;LangString uninst_tor_warn ${LANG_ENGLISH} "Not removing .torrent association. It is associated with:" -LangString uninst_tor_warn ${LANG_ARABIC} "لا يمكن ازالة الارتباط بالملفات . لأنها مرتبطة مع:" -;LangString uninst_mag_warn ${LANG_ENGLISH} "Not removing magnet association. It is associated with:" -LangString uninst_mag_warn ${LANG_ARABIC} "لا يمكن ازالة الارتباط بالملفات المغناطيسية لأنها مرتبطة مع:" diff --git a/dist/windows/installer-translations/basque.nsi b/dist/windows/installer-translations/basque.nsi deleted file mode 100644 index 5a0e0c49c..000000000 --- a/dist/windows/installer-translations/basque.nsi +++ /dev/null @@ -1,53 +0,0 @@ -;Installer strings - -;LangString inst_qbt_req ${LANG_ENGLISH} "qBittorrent (required)" -LangString inst_qbt_req ${LANG_BASQUE} "qBittorrent (beharrezkoa)" -;LangString inst_dekstop ${LANG_ENGLISH} "Create Desktop Shortcut" -LangString inst_dekstop ${LANG_BASQUE} "Sortu Mahaigaineko Lasterbidea" -;LangString inst_startmenu ${LANG_ENGLISH} "Create Start Menu Shortcut" -LangString inst_startmenu ${LANG_BASQUE} "Sortu Hasierako Lasterbidea" -;LangString inst_torrent ${LANG_ENGLISH} "Open .torrent files with qBittorrent" -LangString inst_torrent ${LANG_BASQUE} "Ireki .torrent agiriak qBittorrent-rekin" -;LangString inst_magnet ${LANG_ENGLISH} "Open magnet links with qBittorrent" -LangString inst_magnet ${LANG_BASQUE} "Ireki magnet loturak qBittorrent-rekin" -;LangString inst_firewall ${LANG_ENGLISH} "Add Windows Firewall rule" -LangString inst_firewall ${LANG_BASQUE} "Gehitu Windows Suhesi araua" -;LangString inst_firewallinfo ${LANG_ENGLISH} "Adding Windows Firewall rule" -LangString inst_firewallinfo ${LANG_BASQUE} "Windows Suhesi araua gehitzen" -;LangString inst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before installing." -LangString inst_warning ${LANG_BASQUE} "qBittorrent ekinean dago. Mesedez itxi aplikazioa ezarri aurretik." -;LangString inst_uninstall_question ${LANG_ENGLISH} "A previous installation was detected. It will be uninstalled without deleting user settings." -LangString inst_uninstall_question ${LANG_BASQUE} "A previous installation was detected. It will be uninstalled without deleting user settings." -;LangString inst_unist ${LANG_ENGLISH} "Uninstalling previous version." -LangString inst_unist ${LANG_BASQUE} "Aurreko bertsioa kentzen." -;LangString launch_qbt ${LANG_ENGLISH} "Launch qBittorrent." -LangString launch_qbt ${LANG_BASQUE} "Abiarazi qBittorrent." -;LangString inst_requires_64bit ${LANG_ENGLISH} "This installer works only in 64-bit Windows versions." -LangString inst_requires_64bit ${LANG_BASQUE} "This installer works only in 64-bit Windows versions." - - -;------------------------------------ -;Uninstaller strings - -;LangString remove_files ${LANG_ENGLISH} "Remove files" -LangString remove_files ${LANG_BASQUE} "Kendu agiriak" -;LangString remove_shortcuts ${LANG_ENGLISH} "Remove shortcuts" -LangString remove_shortcuts ${LANG_BASQUE} "Kendu lasterbideak" -;LangString remove_associations ${LANG_ENGLISH} "Remove file associations" -LangString remove_associations ${LANG_BASQUE} "Kendu agiri elkarketak" -;LangString remove_registry ${LANG_ENGLISH} "Remove registry keys" -LangString remove_registry ${LANG_BASQUE} "Kendu erregistro giltzak" -;LangString remove_conf ${LANG_ENGLISH} "Remove configuration files" -LangString remove_conf ${LANG_BASQUE} "Kendu itxurapen agiriak" -;LangString remove_firewall ${LANG_ENGLISH} "Remove Windows Firewall rule" -LangString remove_firewall ${LANG_BASQUE} "Kendu Windows Suhesi araua" -;LangString remove_firewallinfo ${LANG_ENGLISH} "Removing Windows Firewall rule" -LangString remove_firewallinfo ${LANG_BASQUE} "Windows Suhesi araua kentzen" -;LangString remove_cache ${LANG_ENGLISH} "Remove torrents and cached data" -LangString remove_cache ${LANG_BASQUE} "Kendu torrentak eta katxeaturiko datuak" -;LangString uninst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before uninstalling." -LangString uninst_warning ${LANG_BASQUE} "qBittorrent ekinean dago. Mesedez itxi aplikazioa kendu aurretik." -;LangString uninst_tor_warn ${LANG_ENGLISH} "Not removing .torrent association. It is associated with:" -LangString uninst_tor_warn ${LANG_BASQUE} "Ez kentzen .torrent elkarketa. Honekin elkarturik dago:" -;LangString uninst_mag_warn ${LANG_ENGLISH} "Not removing magnet association. It is associated with:" -LangString uninst_mag_warn ${LANG_BASQUE} "Ez kentzen magnet elkarketa. Honekin elkarturik dago:" diff --git a/dist/windows/installer-translations/belarusian.nsi b/dist/windows/installer-translations/belarusian.nsi deleted file mode 100644 index 69bc132a2..000000000 --- a/dist/windows/installer-translations/belarusian.nsi +++ /dev/null @@ -1,53 +0,0 @@ -;Installer strings - -;LangString inst_qbt_req ${LANG_ENGLISH} "qBittorrent (required)" -LangString inst_qbt_req ${LANG_BELARUSIAN} "qBittorrent (required)" -;LangString inst_dekstop ${LANG_ENGLISH} "Create Desktop Shortcut" -LangString inst_dekstop ${LANG_BELARUSIAN} "Create Desktop Shortcut" -;LangString inst_startmenu ${LANG_ENGLISH} "Create Start Menu Shortcut" -LangString inst_startmenu ${LANG_BELARUSIAN} "Create Start Menu Shortcut" -;LangString inst_torrent ${LANG_ENGLISH} "Open .torrent files with qBittorrent" -LangString inst_torrent ${LANG_BELARUSIAN} "Open .torrent files with qBittorrent" -;LangString inst_magnet ${LANG_ENGLISH} "Open magnet links with qBittorrent" -LangString inst_magnet ${LANG_BELARUSIAN} "Open magnet links with qBittorrent" -;LangString inst_firewall ${LANG_ENGLISH} "Add Windows Firewall rule" -LangString inst_firewall ${LANG_BELARUSIAN} "Add Windows Firewall rule" -;LangString inst_firewallinfo ${LANG_ENGLISH} "Adding Windows Firewall rule" -LangString inst_firewallinfo ${LANG_BELARUSIAN} "Adding Windows Firewall rule" -;LangString inst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before installing." -LangString inst_warning ${LANG_BELARUSIAN} "qBittorrent is running. Please close the application before installing." -;LangString inst_uninstall_question ${LANG_ENGLISH} "A previous installation was detected. It will be uninstalled without deleting user settings." -LangString inst_uninstall_question ${LANG_BELARUSIAN} "A previous installation was detected. It will be uninstalled without deleting user settings." -;LangString inst_unist ${LANG_ENGLISH} "Uninstalling previous version." -LangString inst_unist ${LANG_BELARUSIAN} "Uninstalling previous version." -;LangString launch_qbt ${LANG_ENGLISH} "Launch qBittorrent." -LangString launch_qbt ${LANG_BELARUSIAN} "Launch qBittorrent." -;LangString inst_requires_64bit ${LANG_ENGLISH} "This installer works only in 64-bit Windows versions." -LangString inst_requires_64bit ${LANG_BELARUSIAN} "This installer works only in 64-bit Windows versions." - - -;------------------------------------ -;Uninstaller strings - -;LangString remove_files ${LANG_ENGLISH} "Remove files" -LangString remove_files ${LANG_BELARUSIAN} "Remove files" -;LangString remove_shortcuts ${LANG_ENGLISH} "Remove shortcuts" -LangString remove_shortcuts ${LANG_BELARUSIAN} "Remove shortcuts" -;LangString remove_associations ${LANG_ENGLISH} "Remove file associations" -LangString remove_associations ${LANG_BELARUSIAN} "Remove file associations" -;LangString remove_registry ${LANG_ENGLISH} "Remove registry keys" -LangString remove_registry ${LANG_BELARUSIAN} "Remove registry keys" -;LangString remove_conf ${LANG_ENGLISH} "Remove configuration files" -LangString remove_conf ${LANG_BELARUSIAN} "Remove configuration files" -;LangString remove_firewall ${LANG_ENGLISH} "Remove Windows Firewall rule" -LangString remove_firewall ${LANG_BELARUSIAN} "Remove Windows Firewall rule" -;LangString remove_firewallinfo ${LANG_ENGLISH} "Removing Windows Firewall rule" -LangString remove_firewallinfo ${LANG_BELARUSIAN} "Removing Windows Firewall rule" -;LangString remove_cache ${LANG_ENGLISH} "Remove torrents and cached data" -LangString remove_cache ${LANG_BELARUSIAN} "Remove torrents and cached data" -;LangString uninst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before uninstalling." -LangString uninst_warning ${LANG_BELARUSIAN} "qBittorrent is running. Please close the application before uninstalling." -;LangString uninst_tor_warn ${LANG_ENGLISH} "Not removing .torrent association. It is associated with:" -LangString uninst_tor_warn ${LANG_BELARUSIAN} "Not removing .torrent association. It is associated with:" -;LangString uninst_mag_warn ${LANG_ENGLISH} "Not removing magnet association. It is associated with:" -LangString uninst_mag_warn ${LANG_BELARUSIAN} "Not removing magnet association. It is associated with:" diff --git a/dist/windows/installer-translations/bosnian.nsi b/dist/windows/installer-translations/bosnian.nsi deleted file mode 100644 index cbc0d4d75..000000000 --- a/dist/windows/installer-translations/bosnian.nsi +++ /dev/null @@ -1,53 +0,0 @@ -;Installer strings - -;LangString inst_qbt_req ${LANG_ENGLISH} "qBittorrent (required)" -LangString inst_qbt_req ${LANG_BOSNIAN} "qBittorrent (required)" -;LangString inst_dekstop ${LANG_ENGLISH} "Create Desktop Shortcut" -LangString inst_dekstop ${LANG_BOSNIAN} "Create Desktop Shortcut" -;LangString inst_startmenu ${LANG_ENGLISH} "Create Start Menu Shortcut" -LangString inst_startmenu ${LANG_BOSNIAN} "Create Start Menu Shortcut" -;LangString inst_torrent ${LANG_ENGLISH} "Open .torrent files with qBittorrent" -LangString inst_torrent ${LANG_BOSNIAN} "Open .torrent files with qBittorrent" -;LangString inst_magnet ${LANG_ENGLISH} "Open magnet links with qBittorrent" -LangString inst_magnet ${LANG_BOSNIAN} "Open magnet links with qBittorrent" -;LangString inst_firewall ${LANG_ENGLISH} "Add Windows Firewall rule" -LangString inst_firewall ${LANG_BOSNIAN} "Add Windows Firewall rule" -;LangString inst_firewallinfo ${LANG_ENGLISH} "Adding Windows Firewall rule" -LangString inst_firewallinfo ${LANG_BOSNIAN} "Adding Windows Firewall rule" -;LangString inst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before installing." -LangString inst_warning ${LANG_BOSNIAN} "qBittorrent is running. Please close the application before installing." -;LangString inst_uninstall_question ${LANG_ENGLISH} "A previous installation was detected. It will be uninstalled without deleting user settings." -LangString inst_uninstall_question ${LANG_BOSNIAN} "A previous installation was detected. It will be uninstalled without deleting user settings." -;LangString inst_unist ${LANG_ENGLISH} "Uninstalling previous version." -LangString inst_unist ${LANG_BOSNIAN} "Uninstalling previous version." -;LangString launch_qbt ${LANG_ENGLISH} "Launch qBittorrent." -LangString launch_qbt ${LANG_BOSNIAN} "Launch qBittorrent." -;LangString inst_requires_64bit ${LANG_ENGLISH} "This installer works only in 64-bit Windows versions." -LangString inst_requires_64bit ${LANG_BOSNIAN} "This installer works only in 64-bit Windows versions." - - -;------------------------------------ -;Uninstaller strings - -;LangString remove_files ${LANG_ENGLISH} "Remove files" -LangString remove_files ${LANG_BOSNIAN} "Remove files" -;LangString remove_shortcuts ${LANG_ENGLISH} "Remove shortcuts" -LangString remove_shortcuts ${LANG_BOSNIAN} "Remove shortcuts" -;LangString remove_associations ${LANG_ENGLISH} "Remove file associations" -LangString remove_associations ${LANG_BOSNIAN} "Remove file associations" -;LangString remove_registry ${LANG_ENGLISH} "Remove registry keys" -LangString remove_registry ${LANG_BOSNIAN} "Remove registry keys" -;LangString remove_conf ${LANG_ENGLISH} "Remove configuration files" -LangString remove_conf ${LANG_BOSNIAN} "Remove configuration files" -;LangString remove_firewall ${LANG_ENGLISH} "Remove Windows Firewall rule" -LangString remove_firewall ${LANG_BOSNIAN} "Remove Windows Firewall rule" -;LangString remove_firewallinfo ${LANG_ENGLISH} "Removing Windows Firewall rule" -LangString remove_firewallinfo ${LANG_BOSNIAN} "Removing Windows Firewall rule" -;LangString remove_cache ${LANG_ENGLISH} "Remove torrents and cached data" -LangString remove_cache ${LANG_BOSNIAN} "Remove torrents and cached data" -;LangString uninst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before uninstalling." -LangString uninst_warning ${LANG_BOSNIAN} "qBittorrent is running. Please close the application before uninstalling." -;LangString uninst_tor_warn ${LANG_ENGLISH} "Not removing .torrent association. It is associated with:" -LangString uninst_tor_warn ${LANG_BOSNIAN} "Not removing .torrent association. It is associated with:" -;LangString uninst_mag_warn ${LANG_ENGLISH} "Not removing magnet association. It is associated with:" -LangString uninst_mag_warn ${LANG_BOSNIAN} "Not removing magnet association. It is associated with:" diff --git a/dist/windows/installer-translations/breton.nsi b/dist/windows/installer-translations/breton.nsi deleted file mode 100644 index 641f9db94..000000000 --- a/dist/windows/installer-translations/breton.nsi +++ /dev/null @@ -1,53 +0,0 @@ -;Installer strings - -;LangString inst_qbt_req ${LANG_ENGLISH} "qBittorrent (required)" -LangString inst_qbt_req ${LANG_BRETON} "qBittorrent (required)" -;LangString inst_dekstop ${LANG_ENGLISH} "Create Desktop Shortcut" -LangString inst_dekstop ${LANG_BRETON} "Create Desktop Shortcut" -;LangString inst_startmenu ${LANG_ENGLISH} "Create Start Menu Shortcut" -LangString inst_startmenu ${LANG_BRETON} "Create Start Menu Shortcut" -;LangString inst_torrent ${LANG_ENGLISH} "Open .torrent files with qBittorrent" -LangString inst_torrent ${LANG_BRETON} "Open .torrent files with qBittorrent" -;LangString inst_magnet ${LANG_ENGLISH} "Open magnet links with qBittorrent" -LangString inst_magnet ${LANG_BRETON} "Open magnet links with qBittorrent" -;LangString inst_firewall ${LANG_ENGLISH} "Add Windows Firewall rule" -LangString inst_firewall ${LANG_BRETON} "Add Windows Firewall rule" -;LangString inst_firewallinfo ${LANG_ENGLISH} "Adding Windows Firewall rule" -LangString inst_firewallinfo ${LANG_BRETON} "Adding Windows Firewall rule" -;LangString inst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before installing." -LangString inst_warning ${LANG_BRETON} "qBittorrent is running. Please close the application before installing." -;LangString inst_uninstall_question ${LANG_ENGLISH} "A previous installation was detected. It will be uninstalled without deleting user settings." -LangString inst_uninstall_question ${LANG_BRETON} "A previous installation was detected. It will be uninstalled without deleting user settings." -;LangString inst_unist ${LANG_ENGLISH} "Uninstalling previous version." -LangString inst_unist ${LANG_BRETON} "Uninstalling previous version." -;LangString launch_qbt ${LANG_ENGLISH} "Launch qBittorrent." -LangString launch_qbt ${LANG_BRETON} "Launch qBittorrent." -;LangString inst_requires_64bit ${LANG_ENGLISH} "This installer works only in 64-bit Windows versions." -LangString inst_requires_64bit ${LANG_BRETON} "This installer works only in 64-bit Windows versions." - - -;------------------------------------ -;Uninstaller strings - -;LangString remove_files ${LANG_ENGLISH} "Remove files" -LangString remove_files ${LANG_BRETON} "Remove files" -;LangString remove_shortcuts ${LANG_ENGLISH} "Remove shortcuts" -LangString remove_shortcuts ${LANG_BRETON} "Remove shortcuts" -;LangString remove_associations ${LANG_ENGLISH} "Remove file associations" -LangString remove_associations ${LANG_BRETON} "Remove file associations" -;LangString remove_registry ${LANG_ENGLISH} "Remove registry keys" -LangString remove_registry ${LANG_BRETON} "Remove registry keys" -;LangString remove_conf ${LANG_ENGLISH} "Remove configuration files" -LangString remove_conf ${LANG_BRETON} "Remove configuration files" -;LangString remove_firewall ${LANG_ENGLISH} "Remove Windows Firewall rule" -LangString remove_firewall ${LANG_BRETON} "Remove Windows Firewall rule" -;LangString remove_firewallinfo ${LANG_ENGLISH} "Removing Windows Firewall rule" -LangString remove_firewallinfo ${LANG_BRETON} "Removing Windows Firewall rule" -;LangString remove_cache ${LANG_ENGLISH} "Remove torrents and cached data" -LangString remove_cache ${LANG_BRETON} "Remove torrents and cached data" -;LangString uninst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before uninstalling." -LangString uninst_warning ${LANG_BRETON} "qBittorrent is running. Please close the application before uninstalling." -;LangString uninst_tor_warn ${LANG_ENGLISH} "Not removing .torrent association. It is associated with:" -LangString uninst_tor_warn ${LANG_BRETON} "Not removing .torrent association. It is associated with:" -;LangString uninst_mag_warn ${LANG_ENGLISH} "Not removing magnet association. It is associated with:" -LangString uninst_mag_warn ${LANG_BRETON} "Not removing magnet association. It is associated with:" diff --git a/dist/windows/installer-translations/bulgarian.nsi b/dist/windows/installer-translations/bulgarian.nsi deleted file mode 100644 index 481c0bde3..000000000 --- a/dist/windows/installer-translations/bulgarian.nsi +++ /dev/null @@ -1,53 +0,0 @@ -;Installer strings - -;LangString inst_qbt_req ${LANG_ENGLISH} "qBittorrent (required)" -LangString inst_qbt_req ${LANG_BULGARIAN} "qBittorrent (required)" -;LangString inst_dekstop ${LANG_ENGLISH} "Create Desktop Shortcut" -LangString inst_dekstop ${LANG_BULGARIAN} "Create Desktop Shortcut" -;LangString inst_startmenu ${LANG_ENGLISH} "Create Start Menu Shortcut" -LangString inst_startmenu ${LANG_BULGARIAN} "Create Start Menu Shortcut" -;LangString inst_torrent ${LANG_ENGLISH} "Open .torrent files with qBittorrent" -LangString inst_torrent ${LANG_BULGARIAN} "Open .torrent files with qBittorrent" -;LangString inst_magnet ${LANG_ENGLISH} "Open magnet links with qBittorrent" -LangString inst_magnet ${LANG_BULGARIAN} "Open magnet links with qBittorrent" -;LangString inst_firewall ${LANG_ENGLISH} "Add Windows Firewall rule" -LangString inst_firewall ${LANG_BULGARIAN} "Add Windows Firewall rule" -;LangString inst_firewallinfo ${LANG_ENGLISH} "Adding Windows Firewall rule" -LangString inst_firewallinfo ${LANG_BULGARIAN} "Adding Windows Firewall rule" -;LangString inst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before installing." -LangString inst_warning ${LANG_BULGARIAN} "qBittorrent is running. Please close the application before installing." -;LangString inst_uninstall_question ${LANG_ENGLISH} "A previous installation was detected. It will be uninstalled without deleting user settings." -LangString inst_uninstall_question ${LANG_BULGARIAN} "A previous installation was detected. It will be uninstalled without deleting user settings." -;LangString inst_unist ${LANG_ENGLISH} "Uninstalling previous version." -LangString inst_unist ${LANG_BULGARIAN} "Uninstalling previous version." -;LangString launch_qbt ${LANG_ENGLISH} "Launch qBittorrent." -LangString launch_qbt ${LANG_BULGARIAN} "Launch qBittorrent." -;LangString inst_requires_64bit ${LANG_ENGLISH} "This installer works only in 64-bit Windows versions." -LangString inst_requires_64bit ${LANG_BULGARIAN} "This installer works only in 64-bit Windows versions." - - -;------------------------------------ -;Uninstaller strings - -;LangString remove_files ${LANG_ENGLISH} "Remove files" -LangString remove_files ${LANG_BULGARIAN} "Remove files" -;LangString remove_shortcuts ${LANG_ENGLISH} "Remove shortcuts" -LangString remove_shortcuts ${LANG_BULGARIAN} "Remove shortcuts" -;LangString remove_associations ${LANG_ENGLISH} "Remove file associations" -LangString remove_associations ${LANG_BULGARIAN} "Remove file associations" -;LangString remove_registry ${LANG_ENGLISH} "Remove registry keys" -LangString remove_registry ${LANG_BULGARIAN} "Remove registry keys" -;LangString remove_conf ${LANG_ENGLISH} "Remove configuration files" -LangString remove_conf ${LANG_BULGARIAN} "Remove configuration files" -;LangString remove_firewall ${LANG_ENGLISH} "Remove Windows Firewall rule" -LangString remove_firewall ${LANG_BULGARIAN} "Remove Windows Firewall rule" -;LangString remove_firewallinfo ${LANG_ENGLISH} "Removing Windows Firewall rule" -LangString remove_firewallinfo ${LANG_BULGARIAN} "Removing Windows Firewall rule" -;LangString remove_cache ${LANG_ENGLISH} "Remove torrents and cached data" -LangString remove_cache ${LANG_BULGARIAN} "Remove torrents and cached data" -;LangString uninst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before uninstalling." -LangString uninst_warning ${LANG_BULGARIAN} "qBittorrent is running. Please close the application before uninstalling." -;LangString uninst_tor_warn ${LANG_ENGLISH} "Not removing .torrent association. It is associated with:" -LangString uninst_tor_warn ${LANG_BULGARIAN} "Not removing .torrent association. It is associated with:" -;LangString uninst_mag_warn ${LANG_ENGLISH} "Not removing magnet association. It is associated with:" -LangString uninst_mag_warn ${LANG_BULGARIAN} "Not removing magnet association. It is associated with:" diff --git a/dist/windows/installer-translations/catalan.nsi b/dist/windows/installer-translations/catalan.nsi deleted file mode 100644 index e277beb35..000000000 --- a/dist/windows/installer-translations/catalan.nsi +++ /dev/null @@ -1,53 +0,0 @@ -;Installer strings - -;LangString inst_qbt_req ${LANG_ENGLISH} "qBittorrent (required)" -LangString inst_qbt_req ${LANG_CATALAN} "qBittorrent (required)" -;LangString inst_dekstop ${LANG_ENGLISH} "Create Desktop Shortcut" -LangString inst_dekstop ${LANG_CATALAN} "Create Desktop Shortcut" -;LangString inst_startmenu ${LANG_ENGLISH} "Create Start Menu Shortcut" -LangString inst_startmenu ${LANG_CATALAN} "Create Start Menu Shortcut" -;LangString inst_torrent ${LANG_ENGLISH} "Open .torrent files with qBittorrent" -LangString inst_torrent ${LANG_CATALAN} "Open .torrent files with qBittorrent" -;LangString inst_magnet ${LANG_ENGLISH} "Open magnet links with qBittorrent" -LangString inst_magnet ${LANG_CATALAN} "Open magnet links with qBittorrent" -;LangString inst_firewall ${LANG_ENGLISH} "Add Windows Firewall rule" -LangString inst_firewall ${LANG_CATALAN} "Add Windows Firewall rule" -;LangString inst_firewallinfo ${LANG_ENGLISH} "Adding Windows Firewall rule" -LangString inst_firewallinfo ${LANG_CATALAN} "Adding Windows Firewall rule" -;LangString inst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before installing." -LangString inst_warning ${LANG_CATALAN} "qBittorrent is running. Please close the application before installing." -;LangString inst_uninstall_question ${LANG_ENGLISH} "A previous installation was detected. It will be uninstalled without deleting user settings." -LangString inst_uninstall_question ${LANG_CATALAN} "A previous installation was detected. It will be uninstalled without deleting user settings." -;LangString inst_unist ${LANG_ENGLISH} "Uninstalling previous version." -LangString inst_unist ${LANG_CATALAN} "Uninstalling previous version." -;LangString launch_qbt ${LANG_ENGLISH} "Launch qBittorrent." -LangString launch_qbt ${LANG_CATALAN} "Launch qBittorrent." -;LangString inst_requires_64bit ${LANG_ENGLISH} "This installer works only in 64-bit Windows versions." -LangString inst_requires_64bit ${LANG_CATALAN} "This installer works only in 64-bit Windows versions." - - -;------------------------------------ -;Uninstaller strings - -;LangString remove_files ${LANG_ENGLISH} "Remove files" -LangString remove_files ${LANG_CATALAN} "Remove files" -;LangString remove_shortcuts ${LANG_ENGLISH} "Remove shortcuts" -LangString remove_shortcuts ${LANG_CATALAN} "Remove shortcuts" -;LangString remove_associations ${LANG_ENGLISH} "Remove file associations" -LangString remove_associations ${LANG_CATALAN} "Remove file associations" -;LangString remove_registry ${LANG_ENGLISH} "Remove registry keys" -LangString remove_registry ${LANG_CATALAN} "Remove registry keys" -;LangString remove_conf ${LANG_ENGLISH} "Remove configuration files" -LangString remove_conf ${LANG_CATALAN} "Remove configuration files" -;LangString remove_firewall ${LANG_ENGLISH} "Remove Windows Firewall rule" -LangString remove_firewall ${LANG_CATALAN} "Remove Windows Firewall rule" -;LangString remove_firewallinfo ${LANG_ENGLISH} "Removing Windows Firewall rule" -LangString remove_firewallinfo ${LANG_CATALAN} "Removing Windows Firewall rule" -;LangString remove_cache ${LANG_ENGLISH} "Remove torrents and cached data" -LangString remove_cache ${LANG_CATALAN} "Remove torrents and cached data" -;LangString uninst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before uninstalling." -LangString uninst_warning ${LANG_CATALAN} "qBittorrent is running. Please close the application before uninstalling." -;LangString uninst_tor_warn ${LANG_ENGLISH} "Not removing .torrent association. It is associated with:" -LangString uninst_tor_warn ${LANG_CATALAN} "Not removing .torrent association. It is associated with:" -;LangString uninst_mag_warn ${LANG_ENGLISH} "Not removing magnet association. It is associated with:" -LangString uninst_mag_warn ${LANG_CATALAN} "Not removing magnet association. It is associated with:" diff --git a/dist/windows/installer-translations/croatian.nsi b/dist/windows/installer-translations/croatian.nsi deleted file mode 100644 index 8b604792f..000000000 --- a/dist/windows/installer-translations/croatian.nsi +++ /dev/null @@ -1,53 +0,0 @@ -;Installer strings - -;LangString inst_qbt_req ${LANG_ENGLISH} "qBittorrent (required)" -LangString inst_qbt_req ${LANG_CROATIAN} "qBittorrent (neophodno)" -;LangString inst_dekstop ${LANG_ENGLISH} "Create Desktop Shortcut" -LangString inst_dekstop ${LANG_CROATIAN} "Kreiraj prečac na radnoj površini" -;LangString inst_startmenu ${LANG_ENGLISH} "Create Start Menu Shortcut" -LangString inst_startmenu ${LANG_CROATIAN} "Kreiraj prečac u početnom meniju" -;LangString inst_torrent ${LANG_ENGLISH} "Open .torrent files with qBittorrent" -LangString inst_torrent ${LANG_CROATIAN} "Otvori .torrent datoteke s qBittorrentom" -;LangString inst_magnet ${LANG_ENGLISH} "Open magnet links with qBittorrent" -LangString inst_magnet ${LANG_CROATIAN} "Otvori magnet linkove s qBittorrentom" -;LangString inst_firewall ${LANG_ENGLISH} "Add Windows Firewall rule" -LangString inst_firewall ${LANG_CROATIAN} "Dodaj Windows Firewall pravilo" -;LangString inst_firewallinfo ${LANG_ENGLISH} "Adding Windows Firewall rule" -LangString inst_firewallinfo ${LANG_CROATIAN} "Dodavanje Windows Firewall rule" -;LangString inst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before installing." -LangString inst_warning ${LANG_CROATIAN} "qBittorrent je pokrenut. Zatvorite ga prije instalacije." -;LangString inst_uninstall_question ${LANG_ENGLISH} "A previous installation was detected. It will be uninstalled without deleting user settings." -LangString inst_uninstall_question ${LANG_CROATIAN} "A previous installation was detected. It will be uninstalled without deleting user settings." -;LangString inst_unist ${LANG_ENGLISH} "Uninstalling previous version." -LangString inst_unist ${LANG_CROATIAN} "Deinstaliraj prethodnu verziju." -;LangString launch_qbt ${LANG_ENGLISH} "Launch qBittorrent." -LangString launch_qbt ${LANG_CROATIAN} "Pokreni qBittorrent." -;LangString inst_requires_64bit ${LANG_ENGLISH} "This installer works only in 64-bit Windows versions." -LangString inst_requires_64bit ${LANG_CROATIAN} "This installer works only in 64-bit Windows versions." - - -;------------------------------------ -;Uninstaller strings - -;LangString remove_files ${LANG_ENGLISH} "Remove files" -LangString remove_files ${LANG_CROATIAN} "Ukloni datoteke" -;LangString remove_shortcuts ${LANG_ENGLISH} "Remove shortcuts" -LangString remove_shortcuts ${LANG_CROATIAN} "Ukloni prečace" -;LangString remove_associations ${LANG_ENGLISH} "Remove file associations" -LangString remove_associations ${LANG_CROATIAN} "Ukloni datotečne asocijacije" -;LangString remove_registry ${LANG_ENGLISH} "Remove registry keys" -LangString remove_registry ${LANG_CROATIAN} "Ukloni ključeva registra" -;LangString remove_conf ${LANG_ENGLISH} "Remove configuration files" -LangString remove_conf ${LANG_CROATIAN} "Ukloni konfiguracijske datoteke" -;LangString remove_firewall ${LANG_ENGLISH} "Remove Windows Firewall rule" -LangString remove_firewall ${LANG_CROATIAN} "Ukloni Windows Firewall pravilo" -;LangString remove_firewallinfo ${LANG_ENGLISH} "Removing Windows Firewall rule" -LangString remove_firewallinfo ${LANG_CROATIAN} "Uklanjanje Windows Firewall pravila" -;LangString remove_cache ${LANG_ENGLISH} "Remove torrents and cached data" -LangString remove_cache ${LANG_CROATIAN} "Ukloni torrente i isprazni međumemoriju" -;LangString uninst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before uninstalling." -LangString uninst_warning ${LANG_CROATIAN} "qBittorrent je pokrenut. Zatvorite ga prije deinstalacije." -;LangString uninst_tor_warn ${LANG_ENGLISH} "Not removing .torrent association. It is associated with:" -LangString uninst_tor_warn ${LANG_CROATIAN} "Nije moguće ukloniti .torrent asocijaciju. Asocirana je s:" -;LangString uninst_mag_warn ${LANG_ENGLISH} "Not removing magnet association. It is associated with:" -LangString uninst_mag_warn ${LANG_CROATIAN} "Nije moguće ukloniti magnet asocijaciju. Asociran je s:" diff --git a/dist/windows/installer-translations/czech.nsi b/dist/windows/installer-translations/czech.nsi deleted file mode 100644 index b48378b0e..000000000 --- a/dist/windows/installer-translations/czech.nsi +++ /dev/null @@ -1,53 +0,0 @@ -;Installer strings - -;LangString inst_qbt_req ${LANG_ENGLISH} "qBittorrent (required)" -LangString inst_qbt_req ${LANG_CZECH} "qBittorrent (vyžadováno)" -;LangString inst_dekstop ${LANG_ENGLISH} "Create Desktop Shortcut" -LangString inst_dekstop ${LANG_CZECH} "Vytvořit zástupce na ploše" -;LangString inst_startmenu ${LANG_ENGLISH} "Create Start Menu Shortcut" -LangString inst_startmenu ${LANG_CZECH} "Vytvořit zástupce v nabídce Start" -;LangString inst_torrent ${LANG_ENGLISH} "Open .torrent files with qBittorrent" -LangString inst_torrent ${LANG_CZECH} "Otevírat .torrent soubory pomocí qBittorrent" -;LangString inst_magnet ${LANG_ENGLISH} "Open magnet links with qBittorrent" -LangString inst_magnet ${LANG_CZECH} "Otevírat odkazy Magnet pomocí qBittorrent" -;LangString inst_firewall ${LANG_ENGLISH} "Add Windows Firewall rule" -LangString inst_firewall ${LANG_CZECH} "Vytvořit pravidlo ve Windows Firewall" -;LangString inst_firewallinfo ${LANG_ENGLISH} "Adding Windows Firewall rule" -LangString inst_firewallinfo ${LANG_CZECH} "Vytváření pravidla ve Windows Firewall" -;LangString inst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before installing." -LangString inst_warning ${LANG_CZECH} "qBittorrent je spuštěn. Před instalací aplikaci ukončete, prosím." -;LangString inst_uninstall_question ${LANG_ENGLISH} "A previous installation was detected. It will be uninstalled without deleting user settings." -LangString inst_uninstall_question ${LANG_CZECH} "A previous installation was detected. It will be uninstalled without deleting user settings." -;LangString inst_unist ${LANG_ENGLISH} "Uninstalling previous version." -LangString inst_unist ${LANG_CZECH} "Odebírání předchozí verze." -;LangString launch_qbt ${LANG_ENGLISH} "Launch qBittorrent." -LangString launch_qbt ${LANG_CZECH} "Spustit qBittorrent." -;LangString inst_requires_64bit ${LANG_ENGLISH} "This installer works only in 64-bit Windows versions." -LangString inst_requires_64bit ${LANG_CZECH} "This installer works only in 64-bit Windows versions." - - -;------------------------------------ -;Uninstaller strings - -;LangString remove_files ${LANG_ENGLISH} "Remove files" -LangString remove_files ${LANG_CZECH} "Odstranit soubory" -;LangString remove_shortcuts ${LANG_ENGLISH} "Remove shortcuts" -LangString remove_shortcuts ${LANG_CZECH} "Odstranit zástupce" -;LangString remove_associations ${LANG_ENGLISH} "Remove file associations" -LangString remove_associations ${LANG_CZECH} "Odstranit přidružení souborů" -;LangString remove_registry ${LANG_ENGLISH} "Remove registry keys" -LangString remove_registry ${LANG_CZECH} "Odstranit klíče registru" -;LangString remove_conf ${LANG_ENGLISH} "Remove configuration files" -LangString remove_conf ${LANG_CZECH} "Odstranit konfigurační soubory" -;LangString remove_firewall ${LANG_ENGLISH} "Remove Windows Firewall rule" -LangString remove_firewall ${LANG_CZECH} "Odstranit pravidlo ve Windows Firewall" -;LangString remove_firewallinfo ${LANG_ENGLISH} "Removing Windows Firewall rule" -LangString remove_firewallinfo ${LANG_CZECH} "Odebírání pravidla ve Windows Firewall" -;LangString remove_cache ${LANG_ENGLISH} "Remove torrents and cached data" -LangString remove_cache ${LANG_CZECH} "Odstranit torrenty a data v cache" -;LangString uninst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before uninstalling." -LangString uninst_warning ${LANG_CZECH} "qBittorrent je spuštěn. Před odinstalací aplikaci ukončete, prosím." -;LangString uninst_tor_warn ${LANG_ENGLISH} "Not removing .torrent association. It is associated with:" -LangString uninst_tor_warn ${LANG_CZECH} "Neodebírám přidružení souboru .torrent. Je asociován s:" -;LangString uninst_mag_warn ${LANG_ENGLISH} "Not removing magnet association. It is associated with:" -LangString uninst_mag_warn ${LANG_CZECH} "Neodebírám přidružení odkazu Magnet. Je asociován s:" diff --git a/dist/windows/installer-translations/danish.nsi b/dist/windows/installer-translations/danish.nsi deleted file mode 100644 index c04d7b709..000000000 --- a/dist/windows/installer-translations/danish.nsi +++ /dev/null @@ -1,53 +0,0 @@ -;Installer strings - -;LangString inst_qbt_req ${LANG_ENGLISH} "qBittorrent (required)" -LangString inst_qbt_req ${LANG_DANISH} "qBittorrent (påkrævet)" -;LangString inst_dekstop ${LANG_ENGLISH} "Create Desktop Shortcut" -LangString inst_dekstop ${LANG_DANISH} "Opret skrivebordsgenvej" -;LangString inst_startmenu ${LANG_ENGLISH} "Create Start Menu Shortcut" -LangString inst_startmenu ${LANG_DANISH} "Opret genvej i menuen Start" -;LangString inst_torrent ${LANG_ENGLISH} "Open .torrent files with qBittorrent" -LangString inst_torrent ${LANG_DANISH} "Åbn .torrent-filer med qBittorrent" -;LangString inst_magnet ${LANG_ENGLISH} "Open magnet links with qBittorrent" -LangString inst_magnet ${LANG_DANISH} "Åbn magnet-links med qBittorrent" -;LangString inst_firewall ${LANG_ENGLISH} "Add Windows Firewall rule" -LangString inst_firewall ${LANG_DANISH} "Tilføj Windows Firewall-regel" -;LangString inst_firewallinfo ${LANG_ENGLISH} "Adding Windows Firewall rule" -LangString inst_firewallinfo ${LANG_DANISH} "Tilføjer Windows Firewall-regel" -;LangString inst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before installing." -LangString inst_warning ${LANG_DANISH} "qBittorrent kører. Luk venligst programmet inden installation." -;LangString inst_uninstall_question ${LANG_ENGLISH} "A previous installation was detected. It will be uninstalled without deleting user settings." -LangString inst_uninstall_question ${LANG_DANISH} "En tidligere installation blev registreret. Den vil blive afinstalleret uden at brugerindstillingerne slettes." -;LangString inst_unist ${LANG_ENGLISH} "Uninstalling previous version." -LangString inst_unist ${LANG_DANISH} "Afinstallerer tidligere version." -;LangString launch_qbt ${LANG_ENGLISH} "Launch qBittorrent." -LangString launch_qbt ${LANG_DANISH} "Start qBittorrent." -;LangString inst_requires_64bit ${LANG_ENGLISH} "This installer works only in 64-bit Windows versions." -LangString inst_requires_64bit ${LANG_DANISH} "Dette installationsprogram virker kun i 64-bit Windows versioner." - - -;------------------------------------ -;Uninstaller strings - -;LangString remove_files ${LANG_ENGLISH} "Remove files" -LangString remove_files ${LANG_DANISH} "Fjern filer" -;LangString remove_shortcuts ${LANG_ENGLISH} "Remove shortcuts" -LangString remove_shortcuts ${LANG_DANISH} "Fjern genveje" -;LangString remove_associations ${LANG_ENGLISH} "Remove file associations" -LangString remove_associations ${LANG_DANISH} "Fjern filtilknytninger" -;LangString remove_registry ${LANG_ENGLISH} "Remove registry keys" -LangString remove_registry ${LANG_DANISH} "Fjern registreringsnøgler" -;LangString remove_conf ${LANG_ENGLISH} "Remove configuration files" -LangString remove_conf ${LANG_DANISH} "Fjern konfigurationsfiler" -;LangString remove_firewall ${LANG_ENGLISH} "Remove Windows Firewall rule" -LangString remove_firewall ${LANG_DANISH} "Fjern Windows Firewall-regel" -;LangString remove_firewallinfo ${LANG_ENGLISH} "Removing Windows Firewall rule" -LangString remove_firewallinfo ${LANG_DANISH} "Fjerner Windows Firewall-regel" -;LangString remove_cache ${LANG_ENGLISH} "Remove torrents and cached data" -LangString remove_cache ${LANG_DANISH} "Fjern torrents og mellemlagret data" -;LangString uninst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before uninstalling." -LangString uninst_warning ${LANG_DANISH} "qBittorrent kører. Luk venligst programmet inden afinstallation." -;LangString uninst_tor_warn ${LANG_ENGLISH} "Not removing .torrent association. It is associated with:" -LangString uninst_tor_warn ${LANG_DANISH} "Fjerner ikke .torrent-tilknytning. Det er tilknyttet:" -;LangString uninst_mag_warn ${LANG_ENGLISH} "Not removing magnet association. It is associated with:" -LangString uninst_mag_warn ${LANG_DANISH} "Fjerner ikke magnet-tilknytning. Det er tilknyttet:" diff --git a/dist/windows/installer-translations/dutch.nsi b/dist/windows/installer-translations/dutch.nsi deleted file mode 100644 index 62042a4be..000000000 --- a/dist/windows/installer-translations/dutch.nsi +++ /dev/null @@ -1,53 +0,0 @@ -;Installer strings - -;LangString inst_qbt_req ${LANG_ENGLISH} "qBittorrent (required)" -LangString inst_qbt_req ${LANG_DUTCH} "qBittorrent (required)" -;LangString inst_dekstop ${LANG_ENGLISH} "Create Desktop Shortcut" -LangString inst_dekstop ${LANG_DUTCH} "Create Desktop Shortcut" -;LangString inst_startmenu ${LANG_ENGLISH} "Create Start Menu Shortcut" -LangString inst_startmenu ${LANG_DUTCH} "Create Start Menu Shortcut" -;LangString inst_torrent ${LANG_ENGLISH} "Open .torrent files with qBittorrent" -LangString inst_torrent ${LANG_DUTCH} "Open .torrent files with qBittorrent" -;LangString inst_magnet ${LANG_ENGLISH} "Open magnet links with qBittorrent" -LangString inst_magnet ${LANG_DUTCH} "Open magnet links with qBittorrent" -;LangString inst_firewall ${LANG_ENGLISH} "Add Windows Firewall rule" -LangString inst_firewall ${LANG_DUTCH} "Add Windows Firewall rule" -;LangString inst_firewallinfo ${LANG_ENGLISH} "Adding Windows Firewall rule" -LangString inst_firewallinfo ${LANG_DUTCH} "Adding Windows Firewall rule" -;LangString inst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before installing." -LangString inst_warning ${LANG_DUTCH} "qBittorrent is running. Please close the application before installing." -;LangString inst_uninstall_question ${LANG_ENGLISH} "A previous installation was detected. It will be uninstalled without deleting user settings." -LangString inst_uninstall_question ${LANG_DUTCH} "A previous installation was detected. It will be uninstalled without deleting user settings." -;LangString inst_unist ${LANG_ENGLISH} "Uninstalling previous version." -LangString inst_unist ${LANG_DUTCH} "Uninstalling previous version." -;LangString launch_qbt ${LANG_ENGLISH} "Launch qBittorrent." -LangString launch_qbt ${LANG_DUTCH} "Launch qBittorrent." -;LangString inst_requires_64bit ${LANG_ENGLISH} "This installer works only in 64-bit Windows versions." -LangString inst_requires_64bit ${LANG_DUTCH} "This installer works only in 64-bit Windows versions." - - -;------------------------------------ -;Uninstaller strings - -;LangString remove_files ${LANG_ENGLISH} "Remove files" -LangString remove_files ${LANG_DUTCH} "Remove files" -;LangString remove_shortcuts ${LANG_ENGLISH} "Remove shortcuts" -LangString remove_shortcuts ${LANG_DUTCH} "Remove shortcuts" -;LangString remove_associations ${LANG_ENGLISH} "Remove file associations" -LangString remove_associations ${LANG_DUTCH} "Remove file associations" -;LangString remove_registry ${LANG_ENGLISH} "Remove registry keys" -LangString remove_registry ${LANG_DUTCH} "Remove registry keys" -;LangString remove_conf ${LANG_ENGLISH} "Remove configuration files" -LangString remove_conf ${LANG_DUTCH} "Remove configuration files" -;LangString remove_firewall ${LANG_ENGLISH} "Remove Windows Firewall rule" -LangString remove_firewall ${LANG_DUTCH} "Remove Windows Firewall rule" -;LangString remove_firewallinfo ${LANG_ENGLISH} "Removing Windows Firewall rule" -LangString remove_firewallinfo ${LANG_DUTCH} "Removing Windows Firewall rule" -;LangString remove_cache ${LANG_ENGLISH} "Remove torrents and cached data" -LangString remove_cache ${LANG_DUTCH} "Remove torrents and cached data" -;LangString uninst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before uninstalling." -LangString uninst_warning ${LANG_DUTCH} "qBittorrent is running. Please close the application before uninstalling." -;LangString uninst_tor_warn ${LANG_ENGLISH} "Not removing .torrent association. It is associated with:" -LangString uninst_tor_warn ${LANG_DUTCH} "Not removing .torrent association. It is associated with:" -;LangString uninst_mag_warn ${LANG_ENGLISH} "Not removing magnet association. It is associated with:" -LangString uninst_mag_warn ${LANG_DUTCH} "Not removing magnet association. It is associated with:" diff --git a/dist/windows/installer-translations/english.nsi b/dist/windows/installer-translations/english.nsi deleted file mode 100644 index 05b77ef59..000000000 --- a/dist/windows/installer-translations/english.nsi +++ /dev/null @@ -1,53 +0,0 @@ -;Installer strings - -;LangString inst_qbt_req ${LANG_ENGLISH} "qBittorrent (required)" -LangString inst_qbt_req ${LANG_ENGLISH} "qBittorrent (required)" -;LangString inst_dekstop ${LANG_ENGLISH} "Create Desktop Shortcut" -LangString inst_dekstop ${LANG_ENGLISH} "Create Desktop Shortcut" -;LangString inst_startmenu ${LANG_ENGLISH} "Create Start Menu Shortcut" -LangString inst_startmenu ${LANG_ENGLISH} "Create Start Menu Shortcut" -;LangString inst_torrent ${LANG_ENGLISH} "Open .torrent files with qBittorrent" -LangString inst_torrent ${LANG_ENGLISH} "Open .torrent files with qBittorrent" -;LangString inst_magnet ${LANG_ENGLISH} "Open magnet links with qBittorrent" -LangString inst_magnet ${LANG_ENGLISH} "Open magnet links with qBittorrent" -;LangString inst_firewall ${LANG_ENGLISH} "Add Windows Firewall rule" -LangString inst_firewall ${LANG_ENGLISH} "Add Windows Firewall rule" -;LangString inst_firewallinfo ${LANG_ENGLISH} "Adding Windows Firewall rule" -LangString inst_firewallinfo ${LANG_ENGLISH} "Adding Windows Firewall rule" -;LangString inst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before installing." -LangString inst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before installing." -;LangString inst_uninstall_question ${LANG_ENGLISH} "A previous installation was detected. It will be uninstalled without deleting user settings." -LangString inst_uninstall_question ${LANG_ENGLISH} "A previous installation was detected. It will be uninstalled without deleting user settings." -;LangString inst_unist ${LANG_ENGLISH} "Uninstalling previous version." -LangString inst_unist ${LANG_ENGLISH} "Uninstalling previous version." -;LangString launch_qbt ${LANG_ENGLISH} "Launch qBittorrent." -LangString launch_qbt ${LANG_ENGLISH} "Launch qBittorrent." -;LangString inst_requires_64bit ${LANG_ENGLISH} "This installer works only in 64-bit Windows versions." -LangString inst_requires_64bit ${LANG_ENGLISH} "This installer works only in 64-bit Windows versions." - - -;------------------------------------ -;Uninstaller strings - -;LangString remove_files ${LANG_ENGLISH} "Remove files" -LangString remove_files ${LANG_ENGLISH} "Remove files" -;LangString remove_shortcuts ${LANG_ENGLISH} "Remove shortcuts" -LangString remove_shortcuts ${LANG_ENGLISH} "Remove shortcuts" -;LangString remove_associations ${LANG_ENGLISH} "Remove file associations" -LangString remove_associations ${LANG_ENGLISH} "Remove file associations" -;LangString remove_registry ${LANG_ENGLISH} "Remove registry keys" -LangString remove_registry ${LANG_ENGLISH} "Remove registry keys" -;LangString remove_conf ${LANG_ENGLISH} "Remove configuration files" -LangString remove_conf ${LANG_ENGLISH} "Remove configuration files" -;LangString remove_firewall ${LANG_ENGLISH} "Remove Windows Firewall rule" -LangString remove_firewall ${LANG_ENGLISH} "Remove Windows Firewall rule" -;LangString remove_firewallinfo ${LANG_ENGLISH} "Removing Windows Firewall rule" -LangString remove_firewallinfo ${LANG_ENGLISH} "Removing Windows Firewall rule" -;LangString remove_cache ${LANG_ENGLISH} "Remove torrents and cached data" -LangString remove_cache ${LANG_ENGLISH} "Remove torrents and cached data" -;LangString uninst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before uninstalling." -LangString uninst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before uninstalling." -;LangString uninst_tor_warn ${LANG_ENGLISH} "Not removing .torrent association. It is associated with:" -LangString uninst_tor_warn ${LANG_ENGLISH} "Not removing .torrent association. It is associated with:" -;LangString uninst_mag_warn ${LANG_ENGLISH} "Not removing magnet association. It is associated with:" -LangString uninst_mag_warn ${LANG_ENGLISH} "Not removing magnet association. It is associated with:" diff --git a/dist/windows/installer-translations/esperanto.nsi b/dist/windows/installer-translations/esperanto.nsi deleted file mode 100644 index bf79d7ddf..000000000 --- a/dist/windows/installer-translations/esperanto.nsi +++ /dev/null @@ -1,53 +0,0 @@ -;Installer strings - -;LangString inst_qbt_req ${LANG_ENGLISH} "qBittorrent (required)" -LangString inst_qbt_req ${LANG_ESPERANTO} "qBittorrent (required)" -;LangString inst_dekstop ${LANG_ENGLISH} "Create Desktop Shortcut" -LangString inst_dekstop ${LANG_ESPERANTO} "Create Desktop Shortcut" -;LangString inst_startmenu ${LANG_ENGLISH} "Create Start Menu Shortcut" -LangString inst_startmenu ${LANG_ESPERANTO} "Create Start Menu Shortcut" -;LangString inst_torrent ${LANG_ENGLISH} "Open .torrent files with qBittorrent" -LangString inst_torrent ${LANG_ESPERANTO} "Open .torrent files with qBittorrent" -;LangString inst_magnet ${LANG_ENGLISH} "Open magnet links with qBittorrent" -LangString inst_magnet ${LANG_ESPERANTO} "Open magnet links with qBittorrent" -;LangString inst_firewall ${LANG_ENGLISH} "Add Windows Firewall rule" -LangString inst_firewall ${LANG_ESPERANTO} "Add Windows Firewall rule" -;LangString inst_firewallinfo ${LANG_ENGLISH} "Adding Windows Firewall rule" -LangString inst_firewallinfo ${LANG_ESPERANTO} "Adding Windows Firewall rule" -;LangString inst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before installing." -LangString inst_warning ${LANG_ESPERANTO} "qBittorrent is running. Please close the application before installing." -;LangString inst_uninstall_question ${LANG_ENGLISH} "A previous installation was detected. It will be uninstalled without deleting user settings." -LangString inst_uninstall_question ${LANG_ESPERANTO} "A previous installation was detected. It will be uninstalled without deleting user settings." -;LangString inst_unist ${LANG_ENGLISH} "Uninstalling previous version." -LangString inst_unist ${LANG_ESPERANTO} "Uninstalling previous version." -;LangString launch_qbt ${LANG_ENGLISH} "Launch qBittorrent." -LangString launch_qbt ${LANG_ESPERANTO} "Launch qBittorrent." -;LangString inst_requires_64bit ${LANG_ENGLISH} "This installer works only in 64-bit Windows versions." -LangString inst_requires_64bit ${LANG_ESPERANTO} "This installer works only in 64-bit Windows versions." - - -;------------------------------------ -;Uninstaller strings - -;LangString remove_files ${LANG_ENGLISH} "Remove files" -LangString remove_files ${LANG_ESPERANTO} "Remove files" -;LangString remove_shortcuts ${LANG_ENGLISH} "Remove shortcuts" -LangString remove_shortcuts ${LANG_ESPERANTO} "Remove shortcuts" -;LangString remove_associations ${LANG_ENGLISH} "Remove file associations" -LangString remove_associations ${LANG_ESPERANTO} "Remove file associations" -;LangString remove_registry ${LANG_ENGLISH} "Remove registry keys" -LangString remove_registry ${LANG_ESPERANTO} "Remove registry keys" -;LangString remove_conf ${LANG_ENGLISH} "Remove configuration files" -LangString remove_conf ${LANG_ESPERANTO} "Remove configuration files" -;LangString remove_firewall ${LANG_ENGLISH} "Remove Windows Firewall rule" -LangString remove_firewall ${LANG_ESPERANTO} "Remove Windows Firewall rule" -;LangString remove_firewallinfo ${LANG_ENGLISH} "Removing Windows Firewall rule" -LangString remove_firewallinfo ${LANG_ESPERANTO} "Removing Windows Firewall rule" -;LangString remove_cache ${LANG_ENGLISH} "Remove torrents and cached data" -LangString remove_cache ${LANG_ESPERANTO} "Remove torrents and cached data" -;LangString uninst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before uninstalling." -LangString uninst_warning ${LANG_ESPERANTO} "qBittorrent is running. Please close the application before uninstalling." -;LangString uninst_tor_warn ${LANG_ENGLISH} "Not removing .torrent association. It is associated with:" -LangString uninst_tor_warn ${LANG_ESPERANTO} "Not removing .torrent association. It is associated with:" -;LangString uninst_mag_warn ${LANG_ENGLISH} "Not removing magnet association. It is associated with:" -LangString uninst_mag_warn ${LANG_ESPERANTO} "Not removing magnet association. It is associated with:" diff --git a/dist/windows/installer-translations/estonian.nsi b/dist/windows/installer-translations/estonian.nsi deleted file mode 100644 index 7fda8c6ba..000000000 --- a/dist/windows/installer-translations/estonian.nsi +++ /dev/null @@ -1,53 +0,0 @@ -;Installer strings - -;LangString inst_qbt_req ${LANG_ENGLISH} "qBittorrent (required)" -LangString inst_qbt_req ${LANG_ESTONIAN} "qBittorrent (required)" -;LangString inst_dekstop ${LANG_ENGLISH} "Create Desktop Shortcut" -LangString inst_dekstop ${LANG_ESTONIAN} "Create Desktop Shortcut" -;LangString inst_startmenu ${LANG_ENGLISH} "Create Start Menu Shortcut" -LangString inst_startmenu ${LANG_ESTONIAN} "Create Start Menu Shortcut" -;LangString inst_torrent ${LANG_ENGLISH} "Open .torrent files with qBittorrent" -LangString inst_torrent ${LANG_ESTONIAN} "Open .torrent files with qBittorrent" -;LangString inst_magnet ${LANG_ENGLISH} "Open magnet links with qBittorrent" -LangString inst_magnet ${LANG_ESTONIAN} "Open magnet links with qBittorrent" -;LangString inst_firewall ${LANG_ENGLISH} "Add Windows Firewall rule" -LangString inst_firewall ${LANG_ESTONIAN} "Add Windows Firewall rule" -;LangString inst_firewallinfo ${LANG_ENGLISH} "Adding Windows Firewall rule" -LangString inst_firewallinfo ${LANG_ESTONIAN} "Adding Windows Firewall rule" -;LangString inst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before installing." -LangString inst_warning ${LANG_ESTONIAN} "qBittorrent is running. Please close the application before installing." -;LangString inst_uninstall_question ${LANG_ENGLISH} "A previous installation was detected. It will be uninstalled without deleting user settings." -LangString inst_uninstall_question ${LANG_ESTONIAN} "A previous installation was detected. It will be uninstalled without deleting user settings." -;LangString inst_unist ${LANG_ENGLISH} "Uninstalling previous version." -LangString inst_unist ${LANG_ESTONIAN} "Uninstalling previous version." -;LangString launch_qbt ${LANG_ENGLISH} "Launch qBittorrent." -LangString launch_qbt ${LANG_ESTONIAN} "Launch qBittorrent." -;LangString inst_requires_64bit ${LANG_ENGLISH} "This installer works only in 64-bit Windows versions." -LangString inst_requires_64bit ${LANG_ESTONIAN} "This installer works only in 64-bit Windows versions." - - -;------------------------------------ -;Uninstaller strings - -;LangString remove_files ${LANG_ENGLISH} "Remove files" -LangString remove_files ${LANG_ESTONIAN} "Remove files" -;LangString remove_shortcuts ${LANG_ENGLISH} "Remove shortcuts" -LangString remove_shortcuts ${LANG_ESTONIAN} "Remove shortcuts" -;LangString remove_associations ${LANG_ENGLISH} "Remove file associations" -LangString remove_associations ${LANG_ESTONIAN} "Remove file associations" -;LangString remove_registry ${LANG_ENGLISH} "Remove registry keys" -LangString remove_registry ${LANG_ESTONIAN} "Remove registry keys" -;LangString remove_conf ${LANG_ENGLISH} "Remove configuration files" -LangString remove_conf ${LANG_ESTONIAN} "Remove configuration files" -;LangString remove_firewall ${LANG_ENGLISH} "Remove Windows Firewall rule" -LangString remove_firewall ${LANG_ESTONIAN} "Remove Windows Firewall rule" -;LangString remove_firewallinfo ${LANG_ENGLISH} "Removing Windows Firewall rule" -LangString remove_firewallinfo ${LANG_ESTONIAN} "Removing Windows Firewall rule" -;LangString remove_cache ${LANG_ENGLISH} "Remove torrents and cached data" -LangString remove_cache ${LANG_ESTONIAN} "Remove torrents and cached data" -;LangString uninst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before uninstalling." -LangString uninst_warning ${LANG_ESTONIAN} "qBittorrent is running. Please close the application before uninstalling." -;LangString uninst_tor_warn ${LANG_ENGLISH} "Not removing .torrent association. It is associated with:" -LangString uninst_tor_warn ${LANG_ESTONIAN} "Not removing .torrent association. It is associated with:" -;LangString uninst_mag_warn ${LANG_ENGLISH} "Not removing magnet association. It is associated with:" -LangString uninst_mag_warn ${LANG_ESTONIAN} "Not removing magnet association. It is associated with:" diff --git a/dist/windows/installer-translations/farsi.nsi b/dist/windows/installer-translations/farsi.nsi deleted file mode 100644 index ca5f0e0dc..000000000 --- a/dist/windows/installer-translations/farsi.nsi +++ /dev/null @@ -1,53 +0,0 @@ -;Installer strings - -;LangString inst_qbt_req ${LANG_ENGLISH} "qBittorrent (required)" -LangString inst_qbt_req ${LANG_FARSI} "qBittorrent (required)" -;LangString inst_dekstop ${LANG_ENGLISH} "Create Desktop Shortcut" -LangString inst_dekstop ${LANG_FARSI} "Create Desktop Shortcut" -;LangString inst_startmenu ${LANG_ENGLISH} "Create Start Menu Shortcut" -LangString inst_startmenu ${LANG_FARSI} "Create Start Menu Shortcut" -;LangString inst_torrent ${LANG_ENGLISH} "Open .torrent files with qBittorrent" -LangString inst_torrent ${LANG_FARSI} "Open .torrent files with qBittorrent" -;LangString inst_magnet ${LANG_ENGLISH} "Open magnet links with qBittorrent" -LangString inst_magnet ${LANG_FARSI} "Open magnet links with qBittorrent" -;LangString inst_firewall ${LANG_ENGLISH} "Add Windows Firewall rule" -LangString inst_firewall ${LANG_FARSI} "Add Windows Firewall rule" -;LangString inst_firewallinfo ${LANG_ENGLISH} "Adding Windows Firewall rule" -LangString inst_firewallinfo ${LANG_FARSI} "Adding Windows Firewall rule" -;LangString inst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before installing." -LangString inst_warning ${LANG_FARSI} "qBittorrent is running. Please close the application before installing." -;LangString inst_uninstall_question ${LANG_ENGLISH} "A previous installation was detected. It will be uninstalled without deleting user settings." -LangString inst_uninstall_question ${LANG_FARSI} "A previous installation was detected. It will be uninstalled without deleting user settings." -;LangString inst_unist ${LANG_ENGLISH} "Uninstalling previous version." -LangString inst_unist ${LANG_FARSI} "Uninstalling previous version." -;LangString launch_qbt ${LANG_ENGLISH} "Launch qBittorrent." -LangString launch_qbt ${LANG_FARSI} "Launch qBittorrent." -;LangString inst_requires_64bit ${LANG_ENGLISH} "This installer works only in 64-bit Windows versions." -LangString inst_requires_64bit ${LANG_FARSI} "This installer works only in 64-bit Windows versions." - - -;------------------------------------ -;Uninstaller strings - -;LangString remove_files ${LANG_ENGLISH} "Remove files" -LangString remove_files ${LANG_FARSI} "Remove files" -;LangString remove_shortcuts ${LANG_ENGLISH} "Remove shortcuts" -LangString remove_shortcuts ${LANG_FARSI} "Remove shortcuts" -;LangString remove_associations ${LANG_ENGLISH} "Remove file associations" -LangString remove_associations ${LANG_FARSI} "Remove file associations" -;LangString remove_registry ${LANG_ENGLISH} "Remove registry keys" -LangString remove_registry ${LANG_FARSI} "Remove registry keys" -;LangString remove_conf ${LANG_ENGLISH} "Remove configuration files" -LangString remove_conf ${LANG_FARSI} "Remove configuration files" -;LangString remove_firewall ${LANG_ENGLISH} "Remove Windows Firewall rule" -LangString remove_firewall ${LANG_FARSI} "Remove Windows Firewall rule" -;LangString remove_firewallinfo ${LANG_ENGLISH} "Removing Windows Firewall rule" -LangString remove_firewallinfo ${LANG_FARSI} "Removing Windows Firewall rule" -;LangString remove_cache ${LANG_ENGLISH} "Remove torrents and cached data" -LangString remove_cache ${LANG_FARSI} "Remove torrents and cached data" -;LangString uninst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before uninstalling." -LangString uninst_warning ${LANG_FARSI} "qBittorrent is running. Please close the application before uninstalling." -;LangString uninst_tor_warn ${LANG_ENGLISH} "Not removing .torrent association. It is associated with:" -LangString uninst_tor_warn ${LANG_FARSI} "Not removing .torrent association. It is associated with:" -;LangString uninst_mag_warn ${LANG_ENGLISH} "Not removing magnet association. It is associated with:" -LangString uninst_mag_warn ${LANG_FARSI} "Not removing magnet association. It is associated with:" diff --git a/dist/windows/installer-translations/finnish.nsi b/dist/windows/installer-translations/finnish.nsi deleted file mode 100644 index 932946a54..000000000 --- a/dist/windows/installer-translations/finnish.nsi +++ /dev/null @@ -1,53 +0,0 @@ -;Installer strings - -;LangString inst_qbt_req ${LANG_ENGLISH} "qBittorrent (required)" -LangString inst_qbt_req ${LANG_FINNISH} "qBittorrent (required)" -;LangString inst_dekstop ${LANG_ENGLISH} "Create Desktop Shortcut" -LangString inst_dekstop ${LANG_FINNISH} "Create Desktop Shortcut" -;LangString inst_startmenu ${LANG_ENGLISH} "Create Start Menu Shortcut" -LangString inst_startmenu ${LANG_FINNISH} "Create Start Menu Shortcut" -;LangString inst_torrent ${LANG_ENGLISH} "Open .torrent files with qBittorrent" -LangString inst_torrent ${LANG_FINNISH} "Open .torrent files with qBittorrent" -;LangString inst_magnet ${LANG_ENGLISH} "Open magnet links with qBittorrent" -LangString inst_magnet ${LANG_FINNISH} "Open magnet links with qBittorrent" -;LangString inst_firewall ${LANG_ENGLISH} "Add Windows Firewall rule" -LangString inst_firewall ${LANG_FINNISH} "Add Windows Firewall rule" -;LangString inst_firewallinfo ${LANG_ENGLISH} "Adding Windows Firewall rule" -LangString inst_firewallinfo ${LANG_FINNISH} "Adding Windows Firewall rule" -;LangString inst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before installing." -LangString inst_warning ${LANG_FINNISH} "qBittorrent is running. Please close the application before installing." -;LangString inst_uninstall_question ${LANG_ENGLISH} "A previous installation was detected. It will be uninstalled without deleting user settings." -LangString inst_uninstall_question ${LANG_FINNISH} "A previous installation was detected. It will be uninstalled without deleting user settings." -;LangString inst_unist ${LANG_ENGLISH} "Uninstalling previous version." -LangString inst_unist ${LANG_FINNISH} "Uninstalling previous version." -;LangString launch_qbt ${LANG_ENGLISH} "Launch qBittorrent." -LangString launch_qbt ${LANG_FINNISH} "Launch qBittorrent." -;LangString inst_requires_64bit ${LANG_ENGLISH} "This installer works only in 64-bit Windows versions." -LangString inst_requires_64bit ${LANG_FINNISH} "This installer works only in 64-bit Windows versions." - - -;------------------------------------ -;Uninstaller strings - -;LangString remove_files ${LANG_ENGLISH} "Remove files" -LangString remove_files ${LANG_FINNISH} "Remove files" -;LangString remove_shortcuts ${LANG_ENGLISH} "Remove shortcuts" -LangString remove_shortcuts ${LANG_FINNISH} "Remove shortcuts" -;LangString remove_associations ${LANG_ENGLISH} "Remove file associations" -LangString remove_associations ${LANG_FINNISH} "Remove file associations" -;LangString remove_registry ${LANG_ENGLISH} "Remove registry keys" -LangString remove_registry ${LANG_FINNISH} "Remove registry keys" -;LangString remove_conf ${LANG_ENGLISH} "Remove configuration files" -LangString remove_conf ${LANG_FINNISH} "Remove configuration files" -;LangString remove_firewall ${LANG_ENGLISH} "Remove Windows Firewall rule" -LangString remove_firewall ${LANG_FINNISH} "Remove Windows Firewall rule" -;LangString remove_firewallinfo ${LANG_ENGLISH} "Removing Windows Firewall rule" -LangString remove_firewallinfo ${LANG_FINNISH} "Removing Windows Firewall rule" -;LangString remove_cache ${LANG_ENGLISH} "Remove torrents and cached data" -LangString remove_cache ${LANG_FINNISH} "Remove torrents and cached data" -;LangString uninst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before uninstalling." -LangString uninst_warning ${LANG_FINNISH} "qBittorrent is running. Please close the application before uninstalling." -;LangString uninst_tor_warn ${LANG_ENGLISH} "Not removing .torrent association. It is associated with:" -LangString uninst_tor_warn ${LANG_FINNISH} "Not removing .torrent association. It is associated with:" -;LangString uninst_mag_warn ${LANG_ENGLISH} "Not removing magnet association. It is associated with:" -LangString uninst_mag_warn ${LANG_FINNISH} "Not removing magnet association. It is associated with:" diff --git a/dist/windows/installer-translations/french.nsi b/dist/windows/installer-translations/french.nsi deleted file mode 100644 index 72203c552..000000000 --- a/dist/windows/installer-translations/french.nsi +++ /dev/null @@ -1,53 +0,0 @@ -;Installer strings - -;LangString inst_qbt_req ${LANG_ENGLISH} "qBittorrent (required)" -LangString inst_qbt_req ${LANG_FRENCH} "qBittorrent (requis)" -;LangString inst_dekstop ${LANG_ENGLISH} "Create Desktop Shortcut" -LangString inst_dekstop ${LANG_FRENCH} "Créer Raccourci Bureau" -;LangString inst_startmenu ${LANG_ENGLISH} "Create Start Menu Shortcut" -LangString inst_startmenu ${LANG_FRENCH} "Créer Raccourci dans le Menu Démarrer" -;LangString inst_torrent ${LANG_ENGLISH} "Open .torrent files with qBittorrent" -LangString inst_torrent ${LANG_FRENCH} "Ouvrir fichiers .torrent avec qBittorrent" -;LangString inst_magnet ${LANG_ENGLISH} "Open magnet links with qBittorrent" -LangString inst_magnet ${LANG_FRENCH} "Ouvrir liens magnet avec qBittorrent" -;LangString inst_firewall ${LANG_ENGLISH} "Add Windows Firewall rule" -LangString inst_firewall ${LANG_FRENCH} "Ajouter règle Pare-Feu Windows" -;LangString inst_firewallinfo ${LANG_ENGLISH} "Adding Windows Firewall rule" -LangString inst_firewallinfo ${LANG_FRENCH} "Ajout règle Pare-Feu Windows" -;LangString inst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before installing." -LangString inst_warning ${LANG_FRENCH} "qBittorrent est en cours d'exécution. Veuillez fermer l'application avant l'installation." -;LangString inst_uninstall_question ${LANG_ENGLISH} "A previous installation was detected. It will be uninstalled without deleting user settings." -LangString inst_uninstall_question ${LANG_FRENCH} "Une installation précédente a été détectée. Elle sera désinstallée sans supprimer les réglages utilisateur." -;LangString inst_unist ${LANG_ENGLISH} "Uninstalling previous version." -LangString inst_unist ${LANG_FRENCH} "Désinstallation de la version précédente." -;LangString launch_qbt ${LANG_ENGLISH} "Launch qBittorrent." -LangString launch_qbt ${LANG_FRENCH} "Lancer qBittorrent." -;LangString inst_requires_64bit ${LANG_ENGLISH} "This installer works only in 64-bit Windows versions." -LangString inst_requires_64bit ${LANG_FRENCH} "Cet installateur ne fonctionne que dans les versions 64 bits de Windows." - - -;------------------------------------ -;Uninstaller strings - -;LangString remove_files ${LANG_ENGLISH} "Remove files" -LangString remove_files ${LANG_FRENCH} "Supprimer fichiers" -;LangString remove_shortcuts ${LANG_ENGLISH} "Remove shortcuts" -LangString remove_shortcuts ${LANG_FRENCH} "Supprimer raccourcis" -;LangString remove_associations ${LANG_ENGLISH} "Remove file associations" -LangString remove_associations ${LANG_FRENCH} "Supprimer associations de fichiers" -;LangString remove_registry ${LANG_ENGLISH} "Remove registry keys" -LangString remove_registry ${LANG_FRENCH} "Supprimer clés de registre" -;LangString remove_conf ${LANG_ENGLISH} "Remove configuration files" -LangString remove_conf ${LANG_FRENCH} "Supprimer fichiers de configuration" -;LangString remove_firewall ${LANG_ENGLISH} "Remove Windows Firewall rule" -LangString remove_firewall ${LANG_FRENCH} "Supprimer règle Pare-Feu Windows" -;LangString remove_firewallinfo ${LANG_ENGLISH} "Removing Windows Firewall rule" -LangString remove_firewallinfo ${LANG_FRENCH} "Suppression règle Pare-Feu Windows" -;LangString remove_cache ${LANG_ENGLISH} "Remove torrents and cached data" -LangString remove_cache ${LANG_FRENCH} "Supprimer torrents et données cachées" -;LangString uninst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before uninstalling." -LangString uninst_warning ${LANG_FRENCH} "qBittorrent est en cours d'exécution. Veuillez fermer l'application avant la désinstallation." -;LangString uninst_tor_warn ${LANG_ENGLISH} "Not removing .torrent association. It is associated with:" -LangString uninst_tor_warn ${LANG_FRENCH} "Ne peut pas supprimer l'association du .torrent. Elle est associée avec :" -;LangString uninst_mag_warn ${LANG_ENGLISH} "Not removing magnet association. It is associated with:" -LangString uninst_mag_warn ${LANG_FRENCH} "Ne peut pas supprimer l'association du magnet. Elle est associée avec :" diff --git a/dist/windows/installer-translations/galician.nsi b/dist/windows/installer-translations/galician.nsi deleted file mode 100644 index f63c51d2b..000000000 --- a/dist/windows/installer-translations/galician.nsi +++ /dev/null @@ -1,53 +0,0 @@ -;Installer strings - -;LangString inst_qbt_req ${LANG_ENGLISH} "qBittorrent (required)" -LangString inst_qbt_req ${LANG_GALICIAN} "qBittorrent (necesario)" -;LangString inst_dekstop ${LANG_ENGLISH} "Create Desktop Shortcut" -LangString inst_dekstop ${LANG_GALICIAN} "Crear atallo no escritorio" -;LangString inst_startmenu ${LANG_ENGLISH} "Create Start Menu Shortcut" -LangString inst_startmenu ${LANG_GALICIAN} "Crear atallo no menú de inicio" -;LangString inst_torrent ${LANG_ENGLISH} "Open .torrent files with qBittorrent" -LangString inst_torrent ${LANG_GALICIAN} "Abrir os ficheiros .torrent co qBittorrent" -;LangString inst_magnet ${LANG_ENGLISH} "Open magnet links with qBittorrent" -LangString inst_magnet ${LANG_GALICIAN} "Abrir as ligazóns magnet co qBittorrent" -;LangString inst_firewall ${LANG_ENGLISH} "Add Windows Firewall rule" -LangString inst_firewall ${LANG_GALICIAN} "Engadir unha regra á devasa (firewall) de Windows" -;LangString inst_firewallinfo ${LANG_ENGLISH} "Adding Windows Firewall rule" -LangString inst_firewallinfo ${LANG_GALICIAN} "Engadindo unha regra á devasa de Windows" -;LangString inst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before installing." -LangString inst_warning ${LANG_GALICIAN} "qBittorrent está en execución. Peche o aplicativo antes da instalación." -;LangString inst_uninstall_question ${LANG_ENGLISH} "A previous installation was detected. It will be uninstalled without deleting user settings." -LangString inst_uninstall_question ${LANG_GALICIAN} "A previous installation was detected. It will be uninstalled without deleting user settings." -;LangString inst_unist ${LANG_ENGLISH} "Uninstalling previous version." -LangString inst_unist ${LANG_GALICIAN} "Desinstalando a versión anterior." -;LangString launch_qbt ${LANG_ENGLISH} "Launch qBittorrent." -LangString launch_qbt ${LANG_GALICIAN} "Iniciar qBittorrent." -;LangString inst_requires_64bit ${LANG_ENGLISH} "This installer works only in 64-bit Windows versions." -LangString inst_requires_64bit ${LANG_GALICIAN} "This installer works only in 64-bit Windows versions." - - -;------------------------------------ -;Uninstaller strings - -;LangString remove_files ${LANG_ENGLISH} "Remove files" -LangString remove_files ${LANG_GALICIAN} "Retirar ficheiros" -;LangString remove_shortcuts ${LANG_ENGLISH} "Remove shortcuts" -LangString remove_shortcuts ${LANG_GALICIAN} "Retirar atallos" -;LangString remove_associations ${LANG_ENGLISH} "Remove file associations" -LangString remove_associations ${LANG_GALICIAN} "Retirando as asociacións de ficheiros" -;LangString remove_registry ${LANG_ENGLISH} "Remove registry keys" -LangString remove_registry ${LANG_GALICIAN} "Retirar as chaves do rexistro" -;LangString remove_conf ${LANG_ENGLISH} "Remove configuration files" -LangString remove_conf ${LANG_GALICIAN} "Retirar os ficheiros de configuración" -;LangString remove_firewall ${LANG_ENGLISH} "Remove Windows Firewall rule" -LangString remove_firewall ${LANG_GALICIAN} "Retirar a regra da devasa (firewall) de Windows" -;LangString remove_firewallinfo ${LANG_ENGLISH} "Removing Windows Firewall rule" -LangString remove_firewallinfo ${LANG_GALICIAN} "Retirando a regra da devasa de Windows" -;LangString remove_cache ${LANG_ENGLISH} "Remove torrents and cached data" -LangString remove_cache ${LANG_GALICIAN} "Retirar os torrents e os datos da caché" -;LangString uninst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before uninstalling." -LangString uninst_warning ${LANG_GALICIAN} "qBittorrent está en execución. Peche o aplicativo antes da desinstalación." -;LangString uninst_tor_warn ${LANG_ENGLISH} "Not removing .torrent association. It is associated with:" -LangString uninst_tor_warn ${LANG_GALICIAN} "Non se retirou a asociación .torrent. Está asociado a:" -;LangString uninst_mag_warn ${LANG_ENGLISH} "Not removing magnet association. It is associated with:" -LangString uninst_mag_warn ${LANG_GALICIAN} "Non se retirou a asociación magnet. Está asociada a:" diff --git a/dist/windows/installer-translations/german.nsi b/dist/windows/installer-translations/german.nsi deleted file mode 100644 index e49a5268a..000000000 --- a/dist/windows/installer-translations/german.nsi +++ /dev/null @@ -1,53 +0,0 @@ -;Installer strings - -;LangString inst_qbt_req ${LANG_ENGLISH} "qBittorrent (required)" -LangString inst_qbt_req ${LANG_GERMAN} "qBittorrent (erforderlich)" -;LangString inst_dekstop ${LANG_ENGLISH} "Create Desktop Shortcut" -LangString inst_dekstop ${LANG_GERMAN} "Verknüpfung auf dem Desktop erstellen" -;LangString inst_startmenu ${LANG_ENGLISH} "Create Start Menu Shortcut" -LangString inst_startmenu ${LANG_GERMAN} "Eintrag im Startmenü erstellen" -;LangString inst_torrent ${LANG_ENGLISH} "Open .torrent files with qBittorrent" -LangString inst_torrent ${LANG_GERMAN} "Öffne .torrent-Dateien mit qBittorrent" -;LangString inst_magnet ${LANG_ENGLISH} "Open magnet links with qBittorrent" -LangString inst_magnet ${LANG_GERMAN} "Öffne Magnet-Links mit qBittorrent" -;LangString inst_firewall ${LANG_ENGLISH} "Add Windows Firewall rule" -LangString inst_firewall ${LANG_GERMAN} "Regel in der Windows Firewall hinzufügen" -;LangString inst_firewallinfo ${LANG_ENGLISH} "Adding Windows Firewall rule" -LangString inst_firewallinfo ${LANG_GERMAN} "Füge Regel in der Windows Firewall hinzu" -;LangString inst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before installing." -LangString inst_warning ${LANG_GERMAN} "qBittorrent läuft gerade. Bitte das Programm vor der Installation beenden." -;LangString inst_uninstall_question ${LANG_ENGLISH} "A previous installation was detected. It will be uninstalled without deleting user settings." -LangString inst_uninstall_question ${LANG_GERMAN} "Eine ältere Installation wurde festgestellt. Diese wird deinstalliert ohne die Benutzereinstellungen zu löschen." -;LangString inst_unist ${LANG_ENGLISH} "Uninstalling previous version." -LangString inst_unist ${LANG_GERMAN} "Vorherige Version wird deinstalliert." -;LangString launch_qbt ${LANG_ENGLISH} "Launch qBittorrent." -LangString launch_qbt ${LANG_GERMAN} "Starte qBittorrent." -;LangString inst_requires_64bit ${LANG_ENGLISH} "This installer works only in 64-bit Windows versions." -LangString inst_requires_64bit ${LANG_GERMAN} "Diese Installation funktioniert nur mit einer 64-bit Version von Windows." - - -;------------------------------------ -;Uninstaller strings - -;LangString remove_files ${LANG_ENGLISH} "Remove files" -LangString remove_files ${LANG_GERMAN} "Dateien entfernen" -;LangString remove_shortcuts ${LANG_ENGLISH} "Remove shortcuts" -LangString remove_shortcuts ${LANG_GERMAN} "Verknüpfungen entfernen" -;LangString remove_associations ${LANG_ENGLISH} "Remove file associations" -LangString remove_associations ${LANG_GERMAN} "Datei-Verknüpfungen entfernen" -;LangString remove_registry ${LANG_ENGLISH} "Remove registry keys" -LangString remove_registry ${LANG_GERMAN} "Registry-Einträge entfernen" -;LangString remove_conf ${LANG_ENGLISH} "Remove configuration files" -LangString remove_conf ${LANG_GERMAN} "Einstellungsdateien entfernen" -;LangString remove_firewall ${LANG_ENGLISH} "Remove Windows Firewall rule" -LangString remove_firewall ${LANG_GERMAN} "Regel in der Windows Firewall entfernen" -;LangString remove_firewallinfo ${LANG_ENGLISH} "Removing Windows Firewall rule" -LangString remove_firewallinfo ${LANG_GERMAN} "Entferne Regel aus der Windows Firewall" -;LangString remove_cache ${LANG_ENGLISH} "Remove torrents and cached data" -LangString remove_cache ${LANG_GERMAN} "Torrents und zwischengespeicherte Daten entfernen" -;LangString uninst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before uninstalling." -LangString uninst_warning ${LANG_GERMAN} "qBittorrent läuft gerade. Bitte das Programm vor der Deinstallation beenden." -;LangString uninst_tor_warn ${LANG_ENGLISH} "Not removing .torrent association. It is associated with:" -LangString uninst_tor_warn ${LANG_GERMAN} "Dateiverknüpfung mit .torrent-Dateien konnte nicht entfernt werden, da dieser Typ mit diesem Programm verknüpft ist:" -;LangString uninst_mag_warn ${LANG_ENGLISH} "Not removing magnet association. It is associated with:" -LangString uninst_mag_warn ${LANG_GERMAN} "Dateiverknüpfung mit Magnet-Links konnte nicht entfernt werden, da dieser Typ mit diesem Programm verknüpft ist:" diff --git a/dist/windows/installer-translations/greek.nsi b/dist/windows/installer-translations/greek.nsi deleted file mode 100644 index b658b1dbf..000000000 --- a/dist/windows/installer-translations/greek.nsi +++ /dev/null @@ -1,53 +0,0 @@ -;Installer strings - -;LangString inst_qbt_req ${LANG_ENGLISH} "qBittorrent (required)" -LangString inst_qbt_req ${LANG_GREEK} "qBittorrent (απαιτείται)" -;LangString inst_dekstop ${LANG_ENGLISH} "Create Desktop Shortcut" -LangString inst_dekstop ${LANG_GREEK} "Δημιουργία συντόμευσης στην Επιφάνεια Εργασίας" -;LangString inst_startmenu ${LANG_ENGLISH} "Create Start Menu Shortcut" -LangString inst_startmenu ${LANG_GREEK} "Δημιουργία συντόμευσης στο Μενού Έναρξης" -;LangString inst_torrent ${LANG_ENGLISH} "Open .torrent files with qBittorrent" -LangString inst_torrent ${LANG_GREEK} "Άνοιγμα των αρχείων .torrent με το qBittorrent" -;LangString inst_magnet ${LANG_ENGLISH} "Open magnet links with qBittorrent" -LangString inst_magnet ${LANG_GREEK} "Άνοιγμα των μαγνητικών συνδέσμων με το qBittorrent" -;LangString inst_firewall ${LANG_ENGLISH} "Add Windows Firewall rule" -LangString inst_firewall ${LANG_GREEK} "Προσθήκη κανόνα εξαίρεσης στο Τείχος Προστασίας των Windows" -;LangString inst_firewallinfo ${LANG_ENGLISH} "Adding Windows Firewall rule" -LangString inst_firewallinfo ${LANG_GREEK} "Προστίθεται κανόνας εξαίρεσης στο Τείχος Προστασίας των Windows" -;LangString inst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before installing." -LangString inst_warning ${LANG_GREEK} "Το qBittorrent βρίσκεται σε εκτέλεση. Παρακαλούμε κλείστε την εφαρμογή πριν την εγκατάσταση." -;LangString inst_uninstall_question ${LANG_ENGLISH} "A previous installation was detected. It will be uninstalled without deleting user settings." -LangString inst_uninstall_question ${LANG_GREEK} "Ανιχνεύθηκε προηγούμενη εγκατάσταση. Θα απεγκατασταθεί χωρίς να διαγραφούν οι ρυθμίσεις του χρήστη." -;LangString inst_unist ${LANG_ENGLISH} "Uninstalling previous version." -LangString inst_unist ${LANG_GREEK} "Γίνεται απεγκατάσταση της προηγούμενης έκδοσης." -;LangString launch_qbt ${LANG_ENGLISH} "Launch qBittorrent." -LangString launch_qbt ${LANG_GREEK} "Εκκίνηση του qBittorrent." -;LangString inst_requires_64bit ${LANG_ENGLISH} "This installer works only in 64-bit Windows versions." -LangString inst_requires_64bit ${LANG_GREEK} "Αυτό το αρχείο εγκατάστασης λειτουργεί μόνο σε 64-bit εκδόσεις των Windows." - - -;------------------------------------ -;Uninstaller strings - -;LangString remove_files ${LANG_ENGLISH} "Remove files" -LangString remove_files ${LANG_GREEK} "Να διαγραφούν τα αρχεία" -;LangString remove_shortcuts ${LANG_ENGLISH} "Remove shortcuts" -LangString remove_shortcuts ${LANG_GREEK} "Να διαγραφούν οι συντομεύσεις" -;LangString remove_associations ${LANG_ENGLISH} "Remove file associations" -LangString remove_associations ${LANG_GREEK} "Να καταργηθούν οι συσχετίσεις αρχείων" -;LangString remove_registry ${LANG_ENGLISH} "Remove registry keys" -LangString remove_registry ${LANG_GREEK} "Να διαγραφούν τα κλειδιά μητρώου" -;LangString remove_conf ${LANG_ENGLISH} "Remove configuration files" -LangString remove_conf ${LANG_GREEK} "Να διαγραφούν τα αρχεία ρυθμίσεων" -;LangString remove_firewall ${LANG_ENGLISH} "Remove Windows Firewall rule" -LangString remove_firewall ${LANG_GREEK} "Να διαγραφεί ο κανόνας εξαίρεσης στο Τείχος Προστασίας των Windows" -;LangString remove_firewallinfo ${LANG_ENGLISH} "Removing Windows Firewall rule" -LangString remove_firewallinfo ${LANG_GREEK} "Γίνεται διαγραφή του κανόνα εξαίρεσης στο Τείχος Προστασίας των Windows" -;LangString remove_cache ${LANG_ENGLISH} "Remove torrents and cached data" -LangString remove_cache ${LANG_GREEK} "Να διαγραφούν τα torrents και τα δεδομένα προσωρινής αποθήκευσης" -;LangString uninst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before uninstalling." -LangString uninst_warning ${LANG_GREEK} "Το qBittorrent βρίσκεται σε εκτέλεση. Παρακαλούμε κλείστε την εφαρμογή πριν την απεγκατάσταση." -;LangString uninst_tor_warn ${LANG_ENGLISH} "Not removing .torrent association. It is associated with:" -LangString uninst_tor_warn ${LANG_GREEK} "Δεν θα καταργηθεί η συσχέτιση με τα αρχεία .torrent. Είναι συσχετισμένα με το:" -;LangString uninst_mag_warn ${LANG_ENGLISH} "Not removing magnet association. It is associated with:" -LangString uninst_mag_warn ${LANG_GREEK} "Δεν θα καταργηθεί η συσχέτιση με τους μαγνητικούς συνδέσμους. Είναι συσχετισμένοι με το:" diff --git a/dist/windows/installer-translations/hebrew.nsi b/dist/windows/installer-translations/hebrew.nsi deleted file mode 100644 index c8b8a89e0..000000000 --- a/dist/windows/installer-translations/hebrew.nsi +++ /dev/null @@ -1,53 +0,0 @@ -;Installer strings - -;LangString inst_qbt_req ${LANG_ENGLISH} "qBittorrent (required)" -LangString inst_qbt_req ${LANG_HEBREW} "qBittorrent (required)" -;LangString inst_dekstop ${LANG_ENGLISH} "Create Desktop Shortcut" -LangString inst_dekstop ${LANG_HEBREW} "Create Desktop Shortcut" -;LangString inst_startmenu ${LANG_ENGLISH} "Create Start Menu Shortcut" -LangString inst_startmenu ${LANG_HEBREW} "Create Start Menu Shortcut" -;LangString inst_torrent ${LANG_ENGLISH} "Open .torrent files with qBittorrent" -LangString inst_torrent ${LANG_HEBREW} "Open .torrent files with qBittorrent" -;LangString inst_magnet ${LANG_ENGLISH} "Open magnet links with qBittorrent" -LangString inst_magnet ${LANG_HEBREW} "Open magnet links with qBittorrent" -;LangString inst_firewall ${LANG_ENGLISH} "Add Windows Firewall rule" -LangString inst_firewall ${LANG_HEBREW} "Add Windows Firewall rule" -;LangString inst_firewallinfo ${LANG_ENGLISH} "Adding Windows Firewall rule" -LangString inst_firewallinfo ${LANG_HEBREW} "Adding Windows Firewall rule" -;LangString inst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before installing." -LangString inst_warning ${LANG_HEBREW} "qBittorrent is running. Please close the application before installing." -;LangString inst_uninstall_question ${LANG_ENGLISH} "A previous installation was detected. It will be uninstalled without deleting user settings." -LangString inst_uninstall_question ${LANG_HEBREW} "A previous installation was detected. It will be uninstalled without deleting user settings." -;LangString inst_unist ${LANG_ENGLISH} "Uninstalling previous version." -LangString inst_unist ${LANG_HEBREW} "Uninstalling previous version." -;LangString launch_qbt ${LANG_ENGLISH} "Launch qBittorrent." -LangString launch_qbt ${LANG_HEBREW} "Launch qBittorrent." -;LangString inst_requires_64bit ${LANG_ENGLISH} "This installer works only in 64-bit Windows versions." -LangString inst_requires_64bit ${LANG_HEBREW} "This installer works only in 64-bit Windows versions." - - -;------------------------------------ -;Uninstaller strings - -;LangString remove_files ${LANG_ENGLISH} "Remove files" -LangString remove_files ${LANG_HEBREW} "Remove files" -;LangString remove_shortcuts ${LANG_ENGLISH} "Remove shortcuts" -LangString remove_shortcuts ${LANG_HEBREW} "Remove shortcuts" -;LangString remove_associations ${LANG_ENGLISH} "Remove file associations" -LangString remove_associations ${LANG_HEBREW} "Remove file associations" -;LangString remove_registry ${LANG_ENGLISH} "Remove registry keys" -LangString remove_registry ${LANG_HEBREW} "Remove registry keys" -;LangString remove_conf ${LANG_ENGLISH} "Remove configuration files" -LangString remove_conf ${LANG_HEBREW} "Remove configuration files" -;LangString remove_firewall ${LANG_ENGLISH} "Remove Windows Firewall rule" -LangString remove_firewall ${LANG_HEBREW} "Remove Windows Firewall rule" -;LangString remove_firewallinfo ${LANG_ENGLISH} "Removing Windows Firewall rule" -LangString remove_firewallinfo ${LANG_HEBREW} "Removing Windows Firewall rule" -;LangString remove_cache ${LANG_ENGLISH} "Remove torrents and cached data" -LangString remove_cache ${LANG_HEBREW} "Remove torrents and cached data" -;LangString uninst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before uninstalling." -LangString uninst_warning ${LANG_HEBREW} "qBittorrent is running. Please close the application before uninstalling." -;LangString uninst_tor_warn ${LANG_ENGLISH} "Not removing .torrent association. It is associated with:" -LangString uninst_tor_warn ${LANG_HEBREW} "Not removing .torrent association. It is associated with:" -;LangString uninst_mag_warn ${LANG_ENGLISH} "Not removing magnet association. It is associated with:" -LangString uninst_mag_warn ${LANG_HEBREW} "Not removing magnet association. It is associated with:" diff --git a/dist/windows/installer-translations/hungarian.nsi b/dist/windows/installer-translations/hungarian.nsi deleted file mode 100644 index fdd80894e..000000000 --- a/dist/windows/installer-translations/hungarian.nsi +++ /dev/null @@ -1,53 +0,0 @@ -;Installer strings - -;LangString inst_qbt_req ${LANG_ENGLISH} "qBittorrent (required)" -LangString inst_qbt_req ${LANG_HUNGARIAN} "qBittorrent (required)" -;LangString inst_dekstop ${LANG_ENGLISH} "Create Desktop Shortcut" -LangString inst_dekstop ${LANG_HUNGARIAN} "Create Desktop Shortcut" -;LangString inst_startmenu ${LANG_ENGLISH} "Create Start Menu Shortcut" -LangString inst_startmenu ${LANG_HUNGARIAN} "Create Start Menu Shortcut" -;LangString inst_torrent ${LANG_ENGLISH} "Open .torrent files with qBittorrent" -LangString inst_torrent ${LANG_HUNGARIAN} "Open .torrent files with qBittorrent" -;LangString inst_magnet ${LANG_ENGLISH} "Open magnet links with qBittorrent" -LangString inst_magnet ${LANG_HUNGARIAN} "Open magnet links with qBittorrent" -;LangString inst_firewall ${LANG_ENGLISH} "Add Windows Firewall rule" -LangString inst_firewall ${LANG_HUNGARIAN} "Add Windows Firewall rule" -;LangString inst_firewallinfo ${LANG_ENGLISH} "Adding Windows Firewall rule" -LangString inst_firewallinfo ${LANG_HUNGARIAN} "Adding Windows Firewall rule" -;LangString inst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before installing." -LangString inst_warning ${LANG_HUNGARIAN} "qBittorrent is running. Please close the application before installing." -;LangString inst_uninstall_question ${LANG_ENGLISH} "A previous installation was detected. It will be uninstalled without deleting user settings." -LangString inst_uninstall_question ${LANG_HUNGARIAN} "A previous installation was detected. It will be uninstalled without deleting user settings." -;LangString inst_unist ${LANG_ENGLISH} "Uninstalling previous version." -LangString inst_unist ${LANG_HUNGARIAN} "Uninstalling previous version." -;LangString launch_qbt ${LANG_ENGLISH} "Launch qBittorrent." -LangString launch_qbt ${LANG_HUNGARIAN} "Launch qBittorrent." -;LangString inst_requires_64bit ${LANG_ENGLISH} "This installer works only in 64-bit Windows versions." -LangString inst_requires_64bit ${LANG_HUNGARIAN} "This installer works only in 64-bit Windows versions." - - -;------------------------------------ -;Uninstaller strings - -;LangString remove_files ${LANG_ENGLISH} "Remove files" -LangString remove_files ${LANG_HUNGARIAN} "Remove files" -;LangString remove_shortcuts ${LANG_ENGLISH} "Remove shortcuts" -LangString remove_shortcuts ${LANG_HUNGARIAN} "Remove shortcuts" -;LangString remove_associations ${LANG_ENGLISH} "Remove file associations" -LangString remove_associations ${LANG_HUNGARIAN} "Remove file associations" -;LangString remove_registry ${LANG_ENGLISH} "Remove registry keys" -LangString remove_registry ${LANG_HUNGARIAN} "Remove registry keys" -;LangString remove_conf ${LANG_ENGLISH} "Remove configuration files" -LangString remove_conf ${LANG_HUNGARIAN} "Remove configuration files" -;LangString remove_firewall ${LANG_ENGLISH} "Remove Windows Firewall rule" -LangString remove_firewall ${LANG_HUNGARIAN} "Remove Windows Firewall rule" -;LangString remove_firewallinfo ${LANG_ENGLISH} "Removing Windows Firewall rule" -LangString remove_firewallinfo ${LANG_HUNGARIAN} "Removing Windows Firewall rule" -;LangString remove_cache ${LANG_ENGLISH} "Remove torrents and cached data" -LangString remove_cache ${LANG_HUNGARIAN} "Remove torrents and cached data" -;LangString uninst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before uninstalling." -LangString uninst_warning ${LANG_HUNGARIAN} "qBittorrent is running. Please close the application before uninstalling." -;LangString uninst_tor_warn ${LANG_ENGLISH} "Not removing .torrent association. It is associated with:" -LangString uninst_tor_warn ${LANG_HUNGARIAN} "Not removing .torrent association. It is associated with:" -;LangString uninst_mag_warn ${LANG_ENGLISH} "Not removing magnet association. It is associated with:" -LangString uninst_mag_warn ${LANG_HUNGARIAN} "Not removing magnet association. It is associated with:" diff --git a/dist/windows/installer-translations/icelandic.nsi b/dist/windows/installer-translations/icelandic.nsi deleted file mode 100644 index 2dd263e0c..000000000 --- a/dist/windows/installer-translations/icelandic.nsi +++ /dev/null @@ -1,53 +0,0 @@ -;Installer strings - -;LangString inst_qbt_req ${LANG_ENGLISH} "qBittorrent (required)" -LangString inst_qbt_req ${LANG_ICELANDIC} "qBittorrent (required)" -;LangString inst_dekstop ${LANG_ENGLISH} "Create Desktop Shortcut" -LangString inst_dekstop ${LANG_ICELANDIC} "Create Desktop Shortcut" -;LangString inst_startmenu ${LANG_ENGLISH} "Create Start Menu Shortcut" -LangString inst_startmenu ${LANG_ICELANDIC} "Create Start Menu Shortcut" -;LangString inst_torrent ${LANG_ENGLISH} "Open .torrent files with qBittorrent" -LangString inst_torrent ${LANG_ICELANDIC} "Open .torrent files with qBittorrent" -;LangString inst_magnet ${LANG_ENGLISH} "Open magnet links with qBittorrent" -LangString inst_magnet ${LANG_ICELANDIC} "Open magnet links with qBittorrent" -;LangString inst_firewall ${LANG_ENGLISH} "Add Windows Firewall rule" -LangString inst_firewall ${LANG_ICELANDIC} "Add Windows Firewall rule" -;LangString inst_firewallinfo ${LANG_ENGLISH} "Adding Windows Firewall rule" -LangString inst_firewallinfo ${LANG_ICELANDIC} "Adding Windows Firewall rule" -;LangString inst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before installing." -LangString inst_warning ${LANG_ICELANDIC} "qBittorrent is running. Please close the application before installing." -;LangString inst_uninstall_question ${LANG_ENGLISH} "A previous installation was detected. It will be uninstalled without deleting user settings." -LangString inst_uninstall_question ${LANG_ICELANDIC} "A previous installation was detected. It will be uninstalled without deleting user settings." -;LangString inst_unist ${LANG_ENGLISH} "Uninstalling previous version." -LangString inst_unist ${LANG_ICELANDIC} "Uninstalling previous version." -;LangString launch_qbt ${LANG_ENGLISH} "Launch qBittorrent." -LangString launch_qbt ${LANG_ICELANDIC} "Launch qBittorrent." -;LangString inst_requires_64bit ${LANG_ENGLISH} "This installer works only in 64-bit Windows versions." -LangString inst_requires_64bit ${LANG_ICELANDIC} "This installer works only in 64-bit Windows versions." - - -;------------------------------------ -;Uninstaller strings - -;LangString remove_files ${LANG_ENGLISH} "Remove files" -LangString remove_files ${LANG_ICELANDIC} "Remove files" -;LangString remove_shortcuts ${LANG_ENGLISH} "Remove shortcuts" -LangString remove_shortcuts ${LANG_ICELANDIC} "Remove shortcuts" -;LangString remove_associations ${LANG_ENGLISH} "Remove file associations" -LangString remove_associations ${LANG_ICELANDIC} "Remove file associations" -;LangString remove_registry ${LANG_ENGLISH} "Remove registry keys" -LangString remove_registry ${LANG_ICELANDIC} "Remove registry keys" -;LangString remove_conf ${LANG_ENGLISH} "Remove configuration files" -LangString remove_conf ${LANG_ICELANDIC} "Remove configuration files" -;LangString remove_firewall ${LANG_ENGLISH} "Remove Windows Firewall rule" -LangString remove_firewall ${LANG_ICELANDIC} "Remove Windows Firewall rule" -;LangString remove_firewallinfo ${LANG_ENGLISH} "Removing Windows Firewall rule" -LangString remove_firewallinfo ${LANG_ICELANDIC} "Removing Windows Firewall rule" -;LangString remove_cache ${LANG_ENGLISH} "Remove torrents and cached data" -LangString remove_cache ${LANG_ICELANDIC} "Remove torrents and cached data" -;LangString uninst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before uninstalling." -LangString uninst_warning ${LANG_ICELANDIC} "qBittorrent is running. Please close the application before uninstalling." -;LangString uninst_tor_warn ${LANG_ENGLISH} "Not removing .torrent association. It is associated with:" -LangString uninst_tor_warn ${LANG_ICELANDIC} "Not removing .torrent association. It is associated with:" -;LangString uninst_mag_warn ${LANG_ENGLISH} "Not removing magnet association. It is associated with:" -LangString uninst_mag_warn ${LANG_ICELANDIC} "Not removing magnet association. It is associated with:" diff --git a/dist/windows/installer-translations/indonesian.nsi b/dist/windows/installer-translations/indonesian.nsi deleted file mode 100644 index 98fa10c4d..000000000 --- a/dist/windows/installer-translations/indonesian.nsi +++ /dev/null @@ -1,53 +0,0 @@ -;Installer strings - -;LangString inst_qbt_req ${LANG_ENGLISH} "qBittorrent (required)" -LangString inst_qbt_req ${LANG_INDONESIAN} "qBittorrent (required)" -;LangString inst_dekstop ${LANG_ENGLISH} "Create Desktop Shortcut" -LangString inst_dekstop ${LANG_INDONESIAN} "Create Desktop Shortcut" -;LangString inst_startmenu ${LANG_ENGLISH} "Create Start Menu Shortcut" -LangString inst_startmenu ${LANG_INDONESIAN} "Create Start Menu Shortcut" -;LangString inst_torrent ${LANG_ENGLISH} "Open .torrent files with qBittorrent" -LangString inst_torrent ${LANG_INDONESIAN} "Open .torrent files with qBittorrent" -;LangString inst_magnet ${LANG_ENGLISH} "Open magnet links with qBittorrent" -LangString inst_magnet ${LANG_INDONESIAN} "Open magnet links with qBittorrent" -;LangString inst_firewall ${LANG_ENGLISH} "Add Windows Firewall rule" -LangString inst_firewall ${LANG_INDONESIAN} "Add Windows Firewall rule" -;LangString inst_firewallinfo ${LANG_ENGLISH} "Adding Windows Firewall rule" -LangString inst_firewallinfo ${LANG_INDONESIAN} "Adding Windows Firewall rule" -;LangString inst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before installing." -LangString inst_warning ${LANG_INDONESIAN} "qBittorrent is running. Please close the application before installing." -;LangString inst_uninstall_question ${LANG_ENGLISH} "A previous installation was detected. It will be uninstalled without deleting user settings." -LangString inst_uninstall_question ${LANG_INDONESIAN} "A previous installation was detected. It will be uninstalled without deleting user settings." -;LangString inst_unist ${LANG_ENGLISH} "Uninstalling previous version." -LangString inst_unist ${LANG_INDONESIAN} "Uninstalling previous version." -;LangString launch_qbt ${LANG_ENGLISH} "Launch qBittorrent." -LangString launch_qbt ${LANG_INDONESIAN} "Launch qBittorrent." -;LangString inst_requires_64bit ${LANG_ENGLISH} "This installer works only in 64-bit Windows versions." -LangString inst_requires_64bit ${LANG_INDONESIAN} "This installer works only in 64-bit Windows versions." - - -;------------------------------------ -;Uninstaller strings - -;LangString remove_files ${LANG_ENGLISH} "Remove files" -LangString remove_files ${LANG_INDONESIAN} "Remove files" -;LangString remove_shortcuts ${LANG_ENGLISH} "Remove shortcuts" -LangString remove_shortcuts ${LANG_INDONESIAN} "Remove shortcuts" -;LangString remove_associations ${LANG_ENGLISH} "Remove file associations" -LangString remove_associations ${LANG_INDONESIAN} "Remove file associations" -;LangString remove_registry ${LANG_ENGLISH} "Remove registry keys" -LangString remove_registry ${LANG_INDONESIAN} "Remove registry keys" -;LangString remove_conf ${LANG_ENGLISH} "Remove configuration files" -LangString remove_conf ${LANG_INDONESIAN} "Remove configuration files" -;LangString remove_firewall ${LANG_ENGLISH} "Remove Windows Firewall rule" -LangString remove_firewall ${LANG_INDONESIAN} "Remove Windows Firewall rule" -;LangString remove_firewallinfo ${LANG_ENGLISH} "Removing Windows Firewall rule" -LangString remove_firewallinfo ${LANG_INDONESIAN} "Removing Windows Firewall rule" -;LangString remove_cache ${LANG_ENGLISH} "Remove torrents and cached data" -LangString remove_cache ${LANG_INDONESIAN} "Remove torrents and cached data" -;LangString uninst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before uninstalling." -LangString uninst_warning ${LANG_INDONESIAN} "qBittorrent is running. Please close the application before uninstalling." -;LangString uninst_tor_warn ${LANG_ENGLISH} "Not removing .torrent association. It is associated with:" -LangString uninst_tor_warn ${LANG_INDONESIAN} "Not removing .torrent association. It is associated with:" -;LangString uninst_mag_warn ${LANG_ENGLISH} "Not removing magnet association. It is associated with:" -LangString uninst_mag_warn ${LANG_INDONESIAN} "Not removing magnet association. It is associated with:" diff --git a/dist/windows/installer-translations/irish.nsi b/dist/windows/installer-translations/irish.nsi deleted file mode 100644 index 983d0cbdd..000000000 --- a/dist/windows/installer-translations/irish.nsi +++ /dev/null @@ -1,53 +0,0 @@ -;Installer strings - -;LangString inst_qbt_req ${LANG_ENGLISH} "qBittorrent (required)" -LangString inst_qbt_req ${LANG_IRISH} "qBittorrent (required)" -;LangString inst_dekstop ${LANG_ENGLISH} "Create Desktop Shortcut" -LangString inst_dekstop ${LANG_IRISH} "Create Desktop Shortcut" -;LangString inst_startmenu ${LANG_ENGLISH} "Create Start Menu Shortcut" -LangString inst_startmenu ${LANG_IRISH} "Create Start Menu Shortcut" -;LangString inst_torrent ${LANG_ENGLISH} "Open .torrent files with qBittorrent" -LangString inst_torrent ${LANG_IRISH} "Open .torrent files with qBittorrent" -;LangString inst_magnet ${LANG_ENGLISH} "Open magnet links with qBittorrent" -LangString inst_magnet ${LANG_IRISH} "Open magnet links with qBittorrent" -;LangString inst_firewall ${LANG_ENGLISH} "Add Windows Firewall rule" -LangString inst_firewall ${LANG_IRISH} "Add Windows Firewall rule" -;LangString inst_firewallinfo ${LANG_ENGLISH} "Adding Windows Firewall rule" -LangString inst_firewallinfo ${LANG_IRISH} "Adding Windows Firewall rule" -;LangString inst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before installing." -LangString inst_warning ${LANG_IRISH} "qBittorrent is running. Please close the application before installing." -;LangString inst_uninstall_question ${LANG_ENGLISH} "A previous installation was detected. It will be uninstalled without deleting user settings." -LangString inst_uninstall_question ${LANG_IRISH} "A previous installation was detected. It will be uninstalled without deleting user settings." -;LangString inst_unist ${LANG_ENGLISH} "Uninstalling previous version." -LangString inst_unist ${LANG_IRISH} "Uninstalling previous version." -;LangString launch_qbt ${LANG_ENGLISH} "Launch qBittorrent." -LangString launch_qbt ${LANG_IRISH} "Launch qBittorrent." -;LangString inst_requires_64bit ${LANG_ENGLISH} "This installer works only in 64-bit Windows versions." -LangString inst_requires_64bit ${LANG_IRISH} "This installer works only in 64-bit Windows versions." - - -;------------------------------------ -;Uninstaller strings - -;LangString remove_files ${LANG_ENGLISH} "Remove files" -LangString remove_files ${LANG_IRISH} "Remove files" -;LangString remove_shortcuts ${LANG_ENGLISH} "Remove shortcuts" -LangString remove_shortcuts ${LANG_IRISH} "Remove shortcuts" -;LangString remove_associations ${LANG_ENGLISH} "Remove file associations" -LangString remove_associations ${LANG_IRISH} "Remove file associations" -;LangString remove_registry ${LANG_ENGLISH} "Remove registry keys" -LangString remove_registry ${LANG_IRISH} "Remove registry keys" -;LangString remove_conf ${LANG_ENGLISH} "Remove configuration files" -LangString remove_conf ${LANG_IRISH} "Remove configuration files" -;LangString remove_firewall ${LANG_ENGLISH} "Remove Windows Firewall rule" -LangString remove_firewall ${LANG_IRISH} "Remove Windows Firewall rule" -;LangString remove_firewallinfo ${LANG_ENGLISH} "Removing Windows Firewall rule" -LangString remove_firewallinfo ${LANG_IRISH} "Removing Windows Firewall rule" -;LangString remove_cache ${LANG_ENGLISH} "Remove torrents and cached data" -LangString remove_cache ${LANG_IRISH} "Remove torrents and cached data" -;LangString uninst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before uninstalling." -LangString uninst_warning ${LANG_IRISH} "qBittorrent is running. Please close the application before uninstalling." -;LangString uninst_tor_warn ${LANG_ENGLISH} "Not removing .torrent association. It is associated with:" -LangString uninst_tor_warn ${LANG_IRISH} "Not removing .torrent association. It is associated with:" -;LangString uninst_mag_warn ${LANG_ENGLISH} "Not removing magnet association. It is associated with:" -LangString uninst_mag_warn ${LANG_IRISH} "Not removing magnet association. It is associated with:" diff --git a/dist/windows/installer-translations/italian.nsi b/dist/windows/installer-translations/italian.nsi deleted file mode 100644 index 1dd9a033a..000000000 --- a/dist/windows/installer-translations/italian.nsi +++ /dev/null @@ -1,53 +0,0 @@ -;Installer strings - -;LangString inst_qbt_req ${LANG_ENGLISH} "qBittorrent (required)" -LangString inst_qbt_req ${LANG_ITALIAN} "qBittorrent (necessario)" -;LangString inst_dekstop ${LANG_ENGLISH} "Create Desktop Shortcut" -LangString inst_dekstop ${LANG_ITALIAN} "Crea icone sul desktop" -;LangString inst_startmenu ${LANG_ENGLISH} "Create Start Menu Shortcut" -LangString inst_startmenu ${LANG_ITALIAN} "Crea gruppo programmi" -;LangString inst_torrent ${LANG_ENGLISH} "Open .torrent files with qBittorrent" -LangString inst_torrent ${LANG_ITALIAN} "Apri file .torrent con qBittorrent" -;LangString inst_magnet ${LANG_ENGLISH} "Open magnet links with qBittorrent" -LangString inst_magnet ${LANG_ITALIAN} "Apri collegamenti magnet con qBittorrent" -;LangString inst_firewall ${LANG_ENGLISH} "Add Windows Firewall rule" -LangString inst_firewall ${LANG_ITALIAN} "Aggiungi regola al firewall di Windows" -;LangString inst_firewallinfo ${LANG_ENGLISH} "Adding Windows Firewall rule" -LangString inst_firewallinfo ${LANG_ITALIAN} "Aggiunta regola al firewall di Windows" -;LangString inst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before installing." -LangString inst_warning ${LANG_ITALIAN} "qBittorrent è in esecuzione. Chiudi l'applicazione prima dell'installazione." -;LangString inst_uninstall_question ${LANG_ENGLISH} "A previous installation was detected. It will be uninstalled without deleting user settings." -LangString inst_uninstall_question ${LANG_ITALIAN} "A previous installation was detected. It will be uninstalled without deleting user settings." -;LangString inst_unist ${LANG_ENGLISH} "Uninstalling previous version." -LangString inst_unist ${LANG_ITALIAN} "Disinstallazione versione precedente." -;LangString launch_qbt ${LANG_ENGLISH} "Launch qBittorrent." -LangString launch_qbt ${LANG_ITALIAN} "Esegui qBittorrent." -;LangString inst_requires_64bit ${LANG_ENGLISH} "This installer works only in 64-bit Windows versions." -LangString inst_requires_64bit ${LANG_ITALIAN} "This installer works only in 64-bit Windows versions." - - -;------------------------------------ -;Uninstaller strings - -;LangString remove_files ${LANG_ENGLISH} "Remove files" -LangString remove_files ${LANG_ITALIAN} "Rimuovi file" -;LangString remove_shortcuts ${LANG_ENGLISH} "Remove shortcuts" -LangString remove_shortcuts ${LANG_ITALIAN} "Rimuovi collegamenti" -;LangString remove_associations ${LANG_ENGLISH} "Remove file associations" -LangString remove_associations ${LANG_ITALIAN} "Rimuovi associazione file" -;LangString remove_registry ${LANG_ENGLISH} "Remove registry keys" -LangString remove_registry ${LANG_ITALIAN} "Rimuovi chiavi registro" -;LangString remove_conf ${LANG_ENGLISH} "Remove configuration files" -LangString remove_conf ${LANG_ITALIAN} "Rimuovi file di configurazione" -;LangString remove_firewall ${LANG_ENGLISH} "Remove Windows Firewall rule" -LangString remove_firewall ${LANG_ITALIAN} "Rimuovi regola dal firewall di Windows" -;LangString remove_firewallinfo ${LANG_ENGLISH} "Removing Windows Firewall rule" -LangString remove_firewallinfo ${LANG_ITALIAN} "Rimozione regola dal firewall di Windows" -;LangString remove_cache ${LANG_ENGLISH} "Remove torrents and cached data" -LangString remove_cache ${LANG_ITALIAN} "Rimuovi torrent e dati nella cache" -;LangString uninst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before uninstalling." -LangString uninst_warning ${LANG_ITALIAN} "qBittorrent è in esecuzione. Chiudi l'applicazione prima della disinstallazione." -;LangString uninst_tor_warn ${LANG_ENGLISH} "Not removing .torrent association. It is associated with:" -LangString uninst_tor_warn ${LANG_ITALIAN} "Associazione file .torrent non rimossa. File associati con:" -;LangString uninst_mag_warn ${LANG_ENGLISH} "Not removing magnet association. It is associated with:" -LangString uninst_mag_warn ${LANG_ITALIAN} "Associazione file magnet non rimossa. File associati con:" diff --git a/dist/windows/installer-translations/japanese.nsi b/dist/windows/installer-translations/japanese.nsi deleted file mode 100644 index 58d0302a6..000000000 --- a/dist/windows/installer-translations/japanese.nsi +++ /dev/null @@ -1,53 +0,0 @@ -;Installer strings - -;LangString inst_qbt_req ${LANG_ENGLISH} "qBittorrent (required)" -LangString inst_qbt_req ${LANG_JAPANESE} "qBittorrent (必須)" -;LangString inst_dekstop ${LANG_ENGLISH} "Create Desktop Shortcut" -LangString inst_dekstop ${LANG_JAPANESE} "デスクトップにショートカットを作成する" -;LangString inst_startmenu ${LANG_ENGLISH} "Create Start Menu Shortcut" -LangString inst_startmenu ${LANG_JAPANESE} "スタートメニューにショートカットを登録する" -;LangString inst_torrent ${LANG_ENGLISH} "Open .torrent files with qBittorrent" -LangString inst_torrent ${LANG_JAPANESE} ".torrent ファイルは qBittorrent で開く" -;LangString inst_magnet ${LANG_ENGLISH} "Open magnet links with qBittorrent" -LangString inst_magnet ${LANG_JAPANESE} "マグネットリンクは qBittorrent で開く" -;LangString inst_firewall ${LANG_ENGLISH} "Add Windows Firewall rule" -LangString inst_firewall ${LANG_JAPANESE} "Windows ファイアウォールのルールを追加する" -;LangString inst_firewallinfo ${LANG_ENGLISH} "Adding Windows Firewall rule" -LangString inst_firewallinfo ${LANG_JAPANESE} "Windows ファイアウォールのルールを追加しています" -;LangString inst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before installing." -LangString inst_warning ${LANG_JAPANESE} "qBittorrent が起動されています。インストールの前にアプリケーションを終了してください。" -;LangString inst_uninstall_question ${LANG_ENGLISH} "A previous installation was detected. It will be uninstalled without deleting user settings." -LangString inst_uninstall_question ${LANG_JAPANESE} "A previous installation was detected. It will be uninstalled without deleting user settings." -;LangString inst_unist ${LANG_ENGLISH} "Uninstalling previous version." -LangString inst_unist ${LANG_JAPANESE} "以前のバージョンをアンインストールしています。" -;LangString launch_qbt ${LANG_ENGLISH} "Launch qBittorrent." -LangString launch_qbt ${LANG_JAPANESE} "qBittorrent を起動する" -;LangString inst_requires_64bit ${LANG_ENGLISH} "This installer works only in 64-bit Windows versions." -LangString inst_requires_64bit ${LANG_JAPANESE} "This installer works only in 64-bit Windows versions." - - -;------------------------------------ -;Uninstaller strings - -;LangString remove_files ${LANG_ENGLISH} "Remove files" -LangString remove_files ${LANG_JAPANESE} "ファイルを削除する" -;LangString remove_shortcuts ${LANG_ENGLISH} "Remove shortcuts" -LangString remove_shortcuts ${LANG_JAPANESE} "ショートカットを削除する" -;LangString remove_associations ${LANG_ENGLISH} "Remove file associations" -LangString remove_associations ${LANG_JAPANESE} "ファイルの関連付けを削除する" -;LangString remove_registry ${LANG_ENGLISH} "Remove registry keys" -LangString remove_registry ${LANG_JAPANESE} "レジストリキーを削除する" -;LangString remove_conf ${LANG_ENGLISH} "Remove configuration files" -LangString remove_conf ${LANG_JAPANESE} "設定ファイルを削除する" -;LangString remove_firewall ${LANG_ENGLISH} "Remove Windows Firewall rule" -LangString remove_firewall ${LANG_JAPANESE} "Windows ファイアウォールのルールを削除する" -;LangString remove_firewallinfo ${LANG_ENGLISH} "Removing Windows Firewall rule" -LangString remove_firewallinfo ${LANG_JAPANESE} "Windows ファイアウォールのルールを削除しています" -;LangString remove_cache ${LANG_ENGLISH} "Remove torrents and cached data" -LangString remove_cache ${LANG_JAPANESE} "Torrent およびキャッシュデータを削除する" -;LangString uninst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before uninstalling." -LangString uninst_warning ${LANG_JAPANESE} "qBittorrent が起動されています。アンインストールの前にアプリケーションを終了してください。" -;LangString uninst_tor_warn ${LANG_ENGLISH} "Not removing .torrent association. It is associated with:" -LangString uninst_tor_warn ${LANG_JAPANESE} ".torrent ファイルへの関連付けは削除しません。現在他のアプリケーションが関連付けられています:" -;LangString uninst_mag_warn ${LANG_ENGLISH} "Not removing magnet association. It is associated with:" -LangString uninst_mag_warn ${LANG_JAPANESE} "マグネットリンクへの関連付けは削除しません。現在他のアプリケーションが関連付けられています:" diff --git a/dist/windows/installer-translations/korean.nsi b/dist/windows/installer-translations/korean.nsi deleted file mode 100644 index ff40491e2..000000000 --- a/dist/windows/installer-translations/korean.nsi +++ /dev/null @@ -1,53 +0,0 @@ -;Installer strings - -;LangString inst_qbt_req ${LANG_ENGLISH} "qBittorrent (required)" -LangString inst_qbt_req ${LANG_KOREAN} "qBittorrent (required)" -;LangString inst_dekstop ${LANG_ENGLISH} "Create Desktop Shortcut" -LangString inst_dekstop ${LANG_KOREAN} "Create Desktop Shortcut" -;LangString inst_startmenu ${LANG_ENGLISH} "Create Start Menu Shortcut" -LangString inst_startmenu ${LANG_KOREAN} "Create Start Menu Shortcut" -;LangString inst_torrent ${LANG_ENGLISH} "Open .torrent files with qBittorrent" -LangString inst_torrent ${LANG_KOREAN} "Open .torrent files with qBittorrent" -;LangString inst_magnet ${LANG_ENGLISH} "Open magnet links with qBittorrent" -LangString inst_magnet ${LANG_KOREAN} "Open magnet links with qBittorrent" -;LangString inst_firewall ${LANG_ENGLISH} "Add Windows Firewall rule" -LangString inst_firewall ${LANG_KOREAN} "Add Windows Firewall rule" -;LangString inst_firewallinfo ${LANG_ENGLISH} "Adding Windows Firewall rule" -LangString inst_firewallinfo ${LANG_KOREAN} "Adding Windows Firewall rule" -;LangString inst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before installing." -LangString inst_warning ${LANG_KOREAN} "qBittorrent is running. Please close the application before installing." -;LangString inst_uninstall_question ${LANG_ENGLISH} "A previous installation was detected. It will be uninstalled without deleting user settings." -LangString inst_uninstall_question ${LANG_KOREAN} "A previous installation was detected. It will be uninstalled without deleting user settings." -;LangString inst_unist ${LANG_ENGLISH} "Uninstalling previous version." -LangString inst_unist ${LANG_KOREAN} "Uninstalling previous version." -;LangString launch_qbt ${LANG_ENGLISH} "Launch qBittorrent." -LangString launch_qbt ${LANG_KOREAN} "Launch qBittorrent." -;LangString inst_requires_64bit ${LANG_ENGLISH} "This installer works only in 64-bit Windows versions." -LangString inst_requires_64bit ${LANG_KOREAN} "This installer works only in 64-bit Windows versions." - - -;------------------------------------ -;Uninstaller strings - -;LangString remove_files ${LANG_ENGLISH} "Remove files" -LangString remove_files ${LANG_KOREAN} "Remove files" -;LangString remove_shortcuts ${LANG_ENGLISH} "Remove shortcuts" -LangString remove_shortcuts ${LANG_KOREAN} "Remove shortcuts" -;LangString remove_associations ${LANG_ENGLISH} "Remove file associations" -LangString remove_associations ${LANG_KOREAN} "Remove file associations" -;LangString remove_registry ${LANG_ENGLISH} "Remove registry keys" -LangString remove_registry ${LANG_KOREAN} "Remove registry keys" -;LangString remove_conf ${LANG_ENGLISH} "Remove configuration files" -LangString remove_conf ${LANG_KOREAN} "Remove configuration files" -;LangString remove_firewall ${LANG_ENGLISH} "Remove Windows Firewall rule" -LangString remove_firewall ${LANG_KOREAN} "Remove Windows Firewall rule" -;LangString remove_firewallinfo ${LANG_ENGLISH} "Removing Windows Firewall rule" -LangString remove_firewallinfo ${LANG_KOREAN} "Removing Windows Firewall rule" -;LangString remove_cache ${LANG_ENGLISH} "Remove torrents and cached data" -LangString remove_cache ${LANG_KOREAN} "Remove torrents and cached data" -;LangString uninst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before uninstalling." -LangString uninst_warning ${LANG_KOREAN} "qBittorrent is running. Please close the application before uninstalling." -;LangString uninst_tor_warn ${LANG_ENGLISH} "Not removing .torrent association. It is associated with:" -LangString uninst_tor_warn ${LANG_KOREAN} "Not removing .torrent association. It is associated with:" -;LangString uninst_mag_warn ${LANG_ENGLISH} "Not removing magnet association. It is associated with:" -LangString uninst_mag_warn ${LANG_KOREAN} "Not removing magnet association. It is associated with:" diff --git a/dist/windows/installer-translations/kurdish.nsi b/dist/windows/installer-translations/kurdish.nsi deleted file mode 100644 index c3c74c3a5..000000000 --- a/dist/windows/installer-translations/kurdish.nsi +++ /dev/null @@ -1,53 +0,0 @@ -;Installer strings - -;LangString inst_qbt_req ${LANG_ENGLISH} "qBittorrent (required)" -LangString inst_qbt_req ${LANG_KURDISH} "qBittorrent (required)" -;LangString inst_dekstop ${LANG_ENGLISH} "Create Desktop Shortcut" -LangString inst_dekstop ${LANG_KURDISH} "Create Desktop Shortcut" -;LangString inst_startmenu ${LANG_ENGLISH} "Create Start Menu Shortcut" -LangString inst_startmenu ${LANG_KURDISH} "Create Start Menu Shortcut" -;LangString inst_torrent ${LANG_ENGLISH} "Open .torrent files with qBittorrent" -LangString inst_torrent ${LANG_KURDISH} "Open .torrent files with qBittorrent" -;LangString inst_magnet ${LANG_ENGLISH} "Open magnet links with qBittorrent" -LangString inst_magnet ${LANG_KURDISH} "Open magnet links with qBittorrent" -;LangString inst_firewall ${LANG_ENGLISH} "Add Windows Firewall rule" -LangString inst_firewall ${LANG_KURDISH} "Add Windows Firewall rule" -;LangString inst_firewallinfo ${LANG_ENGLISH} "Adding Windows Firewall rule" -LangString inst_firewallinfo ${LANG_KURDISH} "Adding Windows Firewall rule" -;LangString inst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before installing." -LangString inst_warning ${LANG_KURDISH} "qBittorrent is running. Please close the application before installing." -;LangString inst_uninstall_question ${LANG_ENGLISH} "A previous installation was detected. It will be uninstalled without deleting user settings." -LangString inst_uninstall_question ${LANG_KURDISH} "A previous installation was detected. It will be uninstalled without deleting user settings." -;LangString inst_unist ${LANG_ENGLISH} "Uninstalling previous version." -LangString inst_unist ${LANG_KURDISH} "Uninstalling previous version." -;LangString launch_qbt ${LANG_ENGLISH} "Launch qBittorrent." -LangString launch_qbt ${LANG_KURDISH} "Launch qBittorrent." -;LangString inst_requires_64bit ${LANG_ENGLISH} "This installer works only in 64-bit Windows versions." -LangString inst_requires_64bit ${LANG_KURDISH} "This installer works only in 64-bit Windows versions." - - -;------------------------------------ -;Uninstaller strings - -;LangString remove_files ${LANG_ENGLISH} "Remove files" -LangString remove_files ${LANG_KURDISH} "Remove files" -;LangString remove_shortcuts ${LANG_ENGLISH} "Remove shortcuts" -LangString remove_shortcuts ${LANG_KURDISH} "Remove shortcuts" -;LangString remove_associations ${LANG_ENGLISH} "Remove file associations" -LangString remove_associations ${LANG_KURDISH} "Remove file associations" -;LangString remove_registry ${LANG_ENGLISH} "Remove registry keys" -LangString remove_registry ${LANG_KURDISH} "Remove registry keys" -;LangString remove_conf ${LANG_ENGLISH} "Remove configuration files" -LangString remove_conf ${LANG_KURDISH} "Remove configuration files" -;LangString remove_firewall ${LANG_ENGLISH} "Remove Windows Firewall rule" -LangString remove_firewall ${LANG_KURDISH} "Remove Windows Firewall rule" -;LangString remove_firewallinfo ${LANG_ENGLISH} "Removing Windows Firewall rule" -LangString remove_firewallinfo ${LANG_KURDISH} "Removing Windows Firewall rule" -;LangString remove_cache ${LANG_ENGLISH} "Remove torrents and cached data" -LangString remove_cache ${LANG_KURDISH} "Remove torrents and cached data" -;LangString uninst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before uninstalling." -LangString uninst_warning ${LANG_KURDISH} "qBittorrent is running. Please close the application before uninstalling." -;LangString uninst_tor_warn ${LANG_ENGLISH} "Not removing .torrent association. It is associated with:" -LangString uninst_tor_warn ${LANG_KURDISH} "Not removing .torrent association. It is associated with:" -;LangString uninst_mag_warn ${LANG_ENGLISH} "Not removing magnet association. It is associated with:" -LangString uninst_mag_warn ${LANG_KURDISH} "Not removing magnet association. It is associated with:" diff --git a/dist/windows/installer-translations/latvian.nsi b/dist/windows/installer-translations/latvian.nsi deleted file mode 100644 index d2bb03174..000000000 --- a/dist/windows/installer-translations/latvian.nsi +++ /dev/null @@ -1,53 +0,0 @@ -;Installer strings - -;LangString inst_qbt_req ${LANG_ENGLISH} "qBittorrent (required)" -LangString inst_qbt_req ${LANG_LATVIAN} "qBittorrent (required)" -;LangString inst_dekstop ${LANG_ENGLISH} "Create Desktop Shortcut" -LangString inst_dekstop ${LANG_LATVIAN} "Create Desktop Shortcut" -;LangString inst_startmenu ${LANG_ENGLISH} "Create Start Menu Shortcut" -LangString inst_startmenu ${LANG_LATVIAN} "Create Start Menu Shortcut" -;LangString inst_torrent ${LANG_ENGLISH} "Open .torrent files with qBittorrent" -LangString inst_torrent ${LANG_LATVIAN} "Open .torrent files with qBittorrent" -;LangString inst_magnet ${LANG_ENGLISH} "Open magnet links with qBittorrent" -LangString inst_magnet ${LANG_LATVIAN} "Open magnet links with qBittorrent" -;LangString inst_firewall ${LANG_ENGLISH} "Add Windows Firewall rule" -LangString inst_firewall ${LANG_LATVIAN} "Add Windows Firewall rule" -;LangString inst_firewallinfo ${LANG_ENGLISH} "Adding Windows Firewall rule" -LangString inst_firewallinfo ${LANG_LATVIAN} "Adding Windows Firewall rule" -;LangString inst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before installing." -LangString inst_warning ${LANG_LATVIAN} "qBittorrent is running. Please close the application before installing." -;LangString inst_uninstall_question ${LANG_ENGLISH} "A previous installation was detected. It will be uninstalled without deleting user settings." -LangString inst_uninstall_question ${LANG_LATVIAN} "A previous installation was detected. It will be uninstalled without deleting user settings." -;LangString inst_unist ${LANG_ENGLISH} "Uninstalling previous version." -LangString inst_unist ${LANG_LATVIAN} "Uninstalling previous version." -;LangString launch_qbt ${LANG_ENGLISH} "Launch qBittorrent." -LangString launch_qbt ${LANG_LATVIAN} "Launch qBittorrent." -;LangString inst_requires_64bit ${LANG_ENGLISH} "This installer works only in 64-bit Windows versions." -LangString inst_requires_64bit ${LANG_LATVIAN} "This installer works only in 64-bit Windows versions." - - -;------------------------------------ -;Uninstaller strings - -;LangString remove_files ${LANG_ENGLISH} "Remove files" -LangString remove_files ${LANG_LATVIAN} "Remove files" -;LangString remove_shortcuts ${LANG_ENGLISH} "Remove shortcuts" -LangString remove_shortcuts ${LANG_LATVIAN} "Remove shortcuts" -;LangString remove_associations ${LANG_ENGLISH} "Remove file associations" -LangString remove_associations ${LANG_LATVIAN} "Remove file associations" -;LangString remove_registry ${LANG_ENGLISH} "Remove registry keys" -LangString remove_registry ${LANG_LATVIAN} "Remove registry keys" -;LangString remove_conf ${LANG_ENGLISH} "Remove configuration files" -LangString remove_conf ${LANG_LATVIAN} "Remove configuration files" -;LangString remove_firewall ${LANG_ENGLISH} "Remove Windows Firewall rule" -LangString remove_firewall ${LANG_LATVIAN} "Remove Windows Firewall rule" -;LangString remove_firewallinfo ${LANG_ENGLISH} "Removing Windows Firewall rule" -LangString remove_firewallinfo ${LANG_LATVIAN} "Removing Windows Firewall rule" -;LangString remove_cache ${LANG_ENGLISH} "Remove torrents and cached data" -LangString remove_cache ${LANG_LATVIAN} "Remove torrents and cached data" -;LangString uninst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before uninstalling." -LangString uninst_warning ${LANG_LATVIAN} "qBittorrent is running. Please close the application before uninstalling." -;LangString uninst_tor_warn ${LANG_ENGLISH} "Not removing .torrent association. It is associated with:" -LangString uninst_tor_warn ${LANG_LATVIAN} "Not removing .torrent association. It is associated with:" -;LangString uninst_mag_warn ${LANG_ENGLISH} "Not removing magnet association. It is associated with:" -LangString uninst_mag_warn ${LANG_LATVIAN} "Not removing magnet association. It is associated with:" diff --git a/dist/windows/installer-translations/lithuanian.nsi b/dist/windows/installer-translations/lithuanian.nsi deleted file mode 100644 index 8fef9159c..000000000 --- a/dist/windows/installer-translations/lithuanian.nsi +++ /dev/null @@ -1,53 +0,0 @@ -;Installer strings - -;LangString inst_qbt_req ${LANG_ENGLISH} "qBittorrent (required)" -LangString inst_qbt_req ${LANG_LITHUANIAN} "qBittorrent (reikalingas)" -;LangString inst_dekstop ${LANG_ENGLISH} "Create Desktop Shortcut" -LangString inst_dekstop ${LANG_LITHUANIAN} "Sukurti darbalaukyje nuorodą" -;LangString inst_startmenu ${LANG_ENGLISH} "Create Start Menu Shortcut" -LangString inst_startmenu ${LANG_LITHUANIAN} "Sukurti Pradėti meniu nuorodą" -;LangString inst_torrent ${LANG_ENGLISH} "Open .torrent files with qBittorrent" -LangString inst_torrent ${LANG_LITHUANIAN} "Atidaryti .torrent failus su qBittorrent" -;LangString inst_magnet ${LANG_ENGLISH} "Open magnet links with qBittorrent" -LangString inst_magnet ${LANG_LITHUANIAN} "Atidaryti magneto nuorodas su qBittorrent" -;LangString inst_firewall ${LANG_ENGLISH} "Add Windows Firewall rule" -LangString inst_firewall ${LANG_LITHUANIAN} "Sukurti Windows užkardos leidimą" -;LangString inst_firewallinfo ${LANG_ENGLISH} "Adding Windows Firewall rule" -LangString inst_firewallinfo ${LANG_LITHUANIAN} "Pridedu Windows užkardos leidimą" -;LangString inst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before installing." -LangString inst_warning ${LANG_LITHUANIAN} "qBittorrent yra paleistas. Prašau uždaryti programą prieš įdiegiant." -;LangString inst_uninstall_question ${LANG_ENGLISH} "A previous installation was detected. It will be uninstalled without deleting user settings." -LangString inst_uninstall_question ${LANG_LITHUANIAN} "A previous installation was detected. It will be uninstalled without deleting user settings." -;LangString inst_unist ${LANG_ENGLISH} "Uninstalling previous version." -LangString inst_unist ${LANG_LITHUANIAN} "Šalinu ankstesnę versiją." -;LangString launch_qbt ${LANG_ENGLISH} "Launch qBittorrent." -LangString launch_qbt ${LANG_LITHUANIAN} "Paleisti qBittorrent." -;LangString inst_requires_64bit ${LANG_ENGLISH} "This installer works only in 64-bit Windows versions." -LangString inst_requires_64bit ${LANG_LITHUANIAN} "This installer works only in 64-bit Windows versions." - - -;------------------------------------ -;Uninstaller strings - -;LangString remove_files ${LANG_ENGLISH} "Remove files" -LangString remove_files ${LANG_LITHUANIAN} "Pašalinti failus" -;LangString remove_shortcuts ${LANG_ENGLISH} "Remove shortcuts" -LangString remove_shortcuts ${LANG_LITHUANIAN} "Pašalinti nuorodas" -;LangString remove_associations ${LANG_ENGLISH} "Remove file associations" -LangString remove_associations ${LANG_LITHUANIAN} "Pašalinti failų asociacijas" -;LangString remove_registry ${LANG_ENGLISH} "Remove registry keys" -LangString remove_registry ${LANG_LITHUANIAN} "Pašalinti registro raktus" -;LangString remove_conf ${LANG_ENGLISH} "Remove configuration files" -LangString remove_conf ${LANG_LITHUANIAN} "Pašalinti nustatymų failus" -;LangString remove_firewall ${LANG_ENGLISH} "Remove Windows Firewall rule" -LangString remove_firewall ${LANG_LITHUANIAN} "Pašalinti Windows užkardos leidimą" -;LangString remove_firewallinfo ${LANG_ENGLISH} "Removing Windows Firewall rule" -LangString remove_firewallinfo ${LANG_LITHUANIAN} "Šalinu Windows užkardos leidimą" -;LangString remove_cache ${LANG_ENGLISH} "Remove torrents and cached data" -LangString remove_cache ${LANG_LITHUANIAN} "Pašalinti torentus ir podėlio duomenis" -;LangString uninst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before uninstalling." -LangString uninst_warning ${LANG_LITHUANIAN} "qBittorrent yra paleistas. Prašau uždarykite programą prieš išdiegiant." -;LangString uninst_tor_warn ${LANG_ENGLISH} "Not removing .torrent association. It is associated with:" -LangString uninst_tor_warn ${LANG_LITHUANIAN} "Negaliu pašalinti .torrent asociacijos. Ji yra susieti su:" -;LangString uninst_mag_warn ${LANG_ENGLISH} "Not removing magnet association. It is associated with:" -LangString uninst_mag_warn ${LANG_LITHUANIAN} "Negaliu pašalinti magneto asociacijos. Jis susietas su:" diff --git a/dist/windows/installer-translations/luxembourgish.nsi b/dist/windows/installer-translations/luxembourgish.nsi deleted file mode 100644 index b1adf2870..000000000 --- a/dist/windows/installer-translations/luxembourgish.nsi +++ /dev/null @@ -1,53 +0,0 @@ -;Installer strings - -;LangString inst_qbt_req ${LANG_ENGLISH} "qBittorrent (required)" -LangString inst_qbt_req ${LANG_LUXEMBOURGISH} "qBittorrent (required)" -;LangString inst_dekstop ${LANG_ENGLISH} "Create Desktop Shortcut" -LangString inst_dekstop ${LANG_LUXEMBOURGISH} "Create Desktop Shortcut" -;LangString inst_startmenu ${LANG_ENGLISH} "Create Start Menu Shortcut" -LangString inst_startmenu ${LANG_LUXEMBOURGISH} "Create Start Menu Shortcut" -;LangString inst_torrent ${LANG_ENGLISH} "Open .torrent files with qBittorrent" -LangString inst_torrent ${LANG_LUXEMBOURGISH} "Open .torrent files with qBittorrent" -;LangString inst_magnet ${LANG_ENGLISH} "Open magnet links with qBittorrent" -LangString inst_magnet ${LANG_LUXEMBOURGISH} "Open magnet links with qBittorrent" -;LangString inst_firewall ${LANG_ENGLISH} "Add Windows Firewall rule" -LangString inst_firewall ${LANG_LUXEMBOURGISH} "Add Windows Firewall rule" -;LangString inst_firewallinfo ${LANG_ENGLISH} "Adding Windows Firewall rule" -LangString inst_firewallinfo ${LANG_LUXEMBOURGISH} "Adding Windows Firewall rule" -;LangString inst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before installing." -LangString inst_warning ${LANG_LUXEMBOURGISH} "qBittorrent is running. Please close the application before installing." -;LangString inst_uninstall_question ${LANG_ENGLISH} "A previous installation was detected. It will be uninstalled without deleting user settings." -LangString inst_uninstall_question ${LANG_LUXEMBOURGISH} "A previous installation was detected. It will be uninstalled without deleting user settings." -;LangString inst_unist ${LANG_ENGLISH} "Uninstalling previous version." -LangString inst_unist ${LANG_LUXEMBOURGISH} "Uninstalling previous version." -;LangString launch_qbt ${LANG_ENGLISH} "Launch qBittorrent." -LangString launch_qbt ${LANG_LUXEMBOURGISH} "Launch qBittorrent." -;LangString inst_requires_64bit ${LANG_ENGLISH} "This installer works only in 64-bit Windows versions." -LangString inst_requires_64bit ${LANG_LUXEMBOURGISH} "This installer works only in 64-bit Windows versions." - - -;------------------------------------ -;Uninstaller strings - -;LangString remove_files ${LANG_ENGLISH} "Remove files" -LangString remove_files ${LANG_LUXEMBOURGISH} "Remove files" -;LangString remove_shortcuts ${LANG_ENGLISH} "Remove shortcuts" -LangString remove_shortcuts ${LANG_LUXEMBOURGISH} "Remove shortcuts" -;LangString remove_associations ${LANG_ENGLISH} "Remove file associations" -LangString remove_associations ${LANG_LUXEMBOURGISH} "Remove file associations" -;LangString remove_registry ${LANG_ENGLISH} "Remove registry keys" -LangString remove_registry ${LANG_LUXEMBOURGISH} "Remove registry keys" -;LangString remove_conf ${LANG_ENGLISH} "Remove configuration files" -LangString remove_conf ${LANG_LUXEMBOURGISH} "Remove configuration files" -;LangString remove_firewall ${LANG_ENGLISH} "Remove Windows Firewall rule" -LangString remove_firewall ${LANG_LUXEMBOURGISH} "Remove Windows Firewall rule" -;LangString remove_firewallinfo ${LANG_ENGLISH} "Removing Windows Firewall rule" -LangString remove_firewallinfo ${LANG_LUXEMBOURGISH} "Removing Windows Firewall rule" -;LangString remove_cache ${LANG_ENGLISH} "Remove torrents and cached data" -LangString remove_cache ${LANG_LUXEMBOURGISH} "Remove torrents and cached data" -;LangString uninst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before uninstalling." -LangString uninst_warning ${LANG_LUXEMBOURGISH} "qBittorrent is running. Please close the application before uninstalling." -;LangString uninst_tor_warn ${LANG_ENGLISH} "Not removing .torrent association. It is associated with:" -LangString uninst_tor_warn ${LANG_LUXEMBOURGISH} "Not removing .torrent association. It is associated with:" -;LangString uninst_mag_warn ${LANG_ENGLISH} "Not removing magnet association. It is associated with:" -LangString uninst_mag_warn ${LANG_LUXEMBOURGISH} "Not removing magnet association. It is associated with:" diff --git a/dist/windows/installer-translations/macedonian.nsi b/dist/windows/installer-translations/macedonian.nsi deleted file mode 100644 index 36dda8150..000000000 --- a/dist/windows/installer-translations/macedonian.nsi +++ /dev/null @@ -1,53 +0,0 @@ -;Installer strings - -;LangString inst_qbt_req ${LANG_ENGLISH} "qBittorrent (required)" -LangString inst_qbt_req ${LANG_MACEDONIAN} "qBittorrent (required)" -;LangString inst_dekstop ${LANG_ENGLISH} "Create Desktop Shortcut" -LangString inst_dekstop ${LANG_MACEDONIAN} "Create Desktop Shortcut" -;LangString inst_startmenu ${LANG_ENGLISH} "Create Start Menu Shortcut" -LangString inst_startmenu ${LANG_MACEDONIAN} "Create Start Menu Shortcut" -;LangString inst_torrent ${LANG_ENGLISH} "Open .torrent files with qBittorrent" -LangString inst_torrent ${LANG_MACEDONIAN} "Open .torrent files with qBittorrent" -;LangString inst_magnet ${LANG_ENGLISH} "Open magnet links with qBittorrent" -LangString inst_magnet ${LANG_MACEDONIAN} "Open magnet links with qBittorrent" -;LangString inst_firewall ${LANG_ENGLISH} "Add Windows Firewall rule" -LangString inst_firewall ${LANG_MACEDONIAN} "Add Windows Firewall rule" -;LangString inst_firewallinfo ${LANG_ENGLISH} "Adding Windows Firewall rule" -LangString inst_firewallinfo ${LANG_MACEDONIAN} "Adding Windows Firewall rule" -;LangString inst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before installing." -LangString inst_warning ${LANG_MACEDONIAN} "qBittorrent is running. Please close the application before installing." -;LangString inst_uninstall_question ${LANG_ENGLISH} "A previous installation was detected. It will be uninstalled without deleting user settings." -LangString inst_uninstall_question ${LANG_MACEDONIAN} "A previous installation was detected. It will be uninstalled without deleting user settings." -;LangString inst_unist ${LANG_ENGLISH} "Uninstalling previous version." -LangString inst_unist ${LANG_MACEDONIAN} "Uninstalling previous version." -;LangString launch_qbt ${LANG_ENGLISH} "Launch qBittorrent." -LangString launch_qbt ${LANG_MACEDONIAN} "Launch qBittorrent." -;LangString inst_requires_64bit ${LANG_ENGLISH} "This installer works only in 64-bit Windows versions." -LangString inst_requires_64bit ${LANG_MACEDONIAN} "This installer works only in 64-bit Windows versions." - - -;------------------------------------ -;Uninstaller strings - -;LangString remove_files ${LANG_ENGLISH} "Remove files" -LangString remove_files ${LANG_MACEDONIAN} "Remove files" -;LangString remove_shortcuts ${LANG_ENGLISH} "Remove shortcuts" -LangString remove_shortcuts ${LANG_MACEDONIAN} "Remove shortcuts" -;LangString remove_associations ${LANG_ENGLISH} "Remove file associations" -LangString remove_associations ${LANG_MACEDONIAN} "Remove file associations" -;LangString remove_registry ${LANG_ENGLISH} "Remove registry keys" -LangString remove_registry ${LANG_MACEDONIAN} "Remove registry keys" -;LangString remove_conf ${LANG_ENGLISH} "Remove configuration files" -LangString remove_conf ${LANG_MACEDONIAN} "Remove configuration files" -;LangString remove_firewall ${LANG_ENGLISH} "Remove Windows Firewall rule" -LangString remove_firewall ${LANG_MACEDONIAN} "Remove Windows Firewall rule" -;LangString remove_firewallinfo ${LANG_ENGLISH} "Removing Windows Firewall rule" -LangString remove_firewallinfo ${LANG_MACEDONIAN} "Removing Windows Firewall rule" -;LangString remove_cache ${LANG_ENGLISH} "Remove torrents and cached data" -LangString remove_cache ${LANG_MACEDONIAN} "Remove torrents and cached data" -;LangString uninst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before uninstalling." -LangString uninst_warning ${LANG_MACEDONIAN} "qBittorrent is running. Please close the application before uninstalling." -;LangString uninst_tor_warn ${LANG_ENGLISH} "Not removing .torrent association. It is associated with:" -LangString uninst_tor_warn ${LANG_MACEDONIAN} "Not removing .torrent association. It is associated with:" -;LangString uninst_mag_warn ${LANG_ENGLISH} "Not removing magnet association. It is associated with:" -LangString uninst_mag_warn ${LANG_MACEDONIAN} "Not removing magnet association. It is associated with:" diff --git a/dist/windows/installer-translations/malay.nsi b/dist/windows/installer-translations/malay.nsi deleted file mode 100644 index acbabc653..000000000 --- a/dist/windows/installer-translations/malay.nsi +++ /dev/null @@ -1,53 +0,0 @@ -;Installer strings - -;LangString inst_qbt_req ${LANG_ENGLISH} "qBittorrent (required)" -LangString inst_qbt_req ${LANG_MALAY} "qBittorrent (required)" -;LangString inst_dekstop ${LANG_ENGLISH} "Create Desktop Shortcut" -LangString inst_dekstop ${LANG_MALAY} "Create Desktop Shortcut" -;LangString inst_startmenu ${LANG_ENGLISH} "Create Start Menu Shortcut" -LangString inst_startmenu ${LANG_MALAY} "Create Start Menu Shortcut" -;LangString inst_torrent ${LANG_ENGLISH} "Open .torrent files with qBittorrent" -LangString inst_torrent ${LANG_MALAY} "Open .torrent files with qBittorrent" -;LangString inst_magnet ${LANG_ENGLISH} "Open magnet links with qBittorrent" -LangString inst_magnet ${LANG_MALAY} "Open magnet links with qBittorrent" -;LangString inst_firewall ${LANG_ENGLISH} "Add Windows Firewall rule" -LangString inst_firewall ${LANG_MALAY} "Add Windows Firewall rule" -;LangString inst_firewallinfo ${LANG_ENGLISH} "Adding Windows Firewall rule" -LangString inst_firewallinfo ${LANG_MALAY} "Adding Windows Firewall rule" -;LangString inst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before installing." -LangString inst_warning ${LANG_MALAY} "qBittorrent is running. Please close the application before installing." -;LangString inst_uninstall_question ${LANG_ENGLISH} "A previous installation was detected. It will be uninstalled without deleting user settings." -LangString inst_uninstall_question ${LANG_MALAY} "A previous installation was detected. It will be uninstalled without deleting user settings." -;LangString inst_unist ${LANG_ENGLISH} "Uninstalling previous version." -LangString inst_unist ${LANG_MALAY} "Uninstalling previous version." -;LangString launch_qbt ${LANG_ENGLISH} "Launch qBittorrent." -LangString launch_qbt ${LANG_MALAY} "Launch qBittorrent." -;LangString inst_requires_64bit ${LANG_ENGLISH} "This installer works only in 64-bit Windows versions." -LangString inst_requires_64bit ${LANG_MALAY} "This installer works only in 64-bit Windows versions." - - -;------------------------------------ -;Uninstaller strings - -;LangString remove_files ${LANG_ENGLISH} "Remove files" -LangString remove_files ${LANG_MALAY} "Remove files" -;LangString remove_shortcuts ${LANG_ENGLISH} "Remove shortcuts" -LangString remove_shortcuts ${LANG_MALAY} "Remove shortcuts" -;LangString remove_associations ${LANG_ENGLISH} "Remove file associations" -LangString remove_associations ${LANG_MALAY} "Remove file associations" -;LangString remove_registry ${LANG_ENGLISH} "Remove registry keys" -LangString remove_registry ${LANG_MALAY} "Remove registry keys" -;LangString remove_conf ${LANG_ENGLISH} "Remove configuration files" -LangString remove_conf ${LANG_MALAY} "Remove configuration files" -;LangString remove_firewall ${LANG_ENGLISH} "Remove Windows Firewall rule" -LangString remove_firewall ${LANG_MALAY} "Remove Windows Firewall rule" -;LangString remove_firewallinfo ${LANG_ENGLISH} "Removing Windows Firewall rule" -LangString remove_firewallinfo ${LANG_MALAY} "Removing Windows Firewall rule" -;LangString remove_cache ${LANG_ENGLISH} "Remove torrents and cached data" -LangString remove_cache ${LANG_MALAY} "Remove torrents and cached data" -;LangString uninst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before uninstalling." -LangString uninst_warning ${LANG_MALAY} "qBittorrent is running. Please close the application before uninstalling." -;LangString uninst_tor_warn ${LANG_ENGLISH} "Not removing .torrent association. It is associated with:" -LangString uninst_tor_warn ${LANG_MALAY} "Not removing .torrent association. It is associated with:" -;LangString uninst_mag_warn ${LANG_ENGLISH} "Not removing magnet association. It is associated with:" -LangString uninst_mag_warn ${LANG_MALAY} "Not removing magnet association. It is associated with:" diff --git a/dist/windows/installer-translations/mongolian.nsi b/dist/windows/installer-translations/mongolian.nsi deleted file mode 100644 index 6e0e9d57f..000000000 --- a/dist/windows/installer-translations/mongolian.nsi +++ /dev/null @@ -1,53 +0,0 @@ -;Installer strings - -;LangString inst_qbt_req ${LANG_ENGLISH} "qBittorrent (required)" -LangString inst_qbt_req ${LANG_MONGOLIAN} "qBittorrent (required)" -;LangString inst_dekstop ${LANG_ENGLISH} "Create Desktop Shortcut" -LangString inst_dekstop ${LANG_MONGOLIAN} "Create Desktop Shortcut" -;LangString inst_startmenu ${LANG_ENGLISH} "Create Start Menu Shortcut" -LangString inst_startmenu ${LANG_MONGOLIAN} "Create Start Menu Shortcut" -;LangString inst_torrent ${LANG_ENGLISH} "Open .torrent files with qBittorrent" -LangString inst_torrent ${LANG_MONGOLIAN} "Open .torrent files with qBittorrent" -;LangString inst_magnet ${LANG_ENGLISH} "Open magnet links with qBittorrent" -LangString inst_magnet ${LANG_MONGOLIAN} "Open magnet links with qBittorrent" -;LangString inst_firewall ${LANG_ENGLISH} "Add Windows Firewall rule" -LangString inst_firewall ${LANG_MONGOLIAN} "Add Windows Firewall rule" -;LangString inst_firewallinfo ${LANG_ENGLISH} "Adding Windows Firewall rule" -LangString inst_firewallinfo ${LANG_MONGOLIAN} "Adding Windows Firewall rule" -;LangString inst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before installing." -LangString inst_warning ${LANG_MONGOLIAN} "qBittorrent is running. Please close the application before installing." -;LangString inst_uninstall_question ${LANG_ENGLISH} "A previous installation was detected. It will be uninstalled without deleting user settings." -LangString inst_uninstall_question ${LANG_MONGOLIAN} "A previous installation was detected. It will be uninstalled without deleting user settings." -;LangString inst_unist ${LANG_ENGLISH} "Uninstalling previous version." -LangString inst_unist ${LANG_MONGOLIAN} "Uninstalling previous version." -;LangString launch_qbt ${LANG_ENGLISH} "Launch qBittorrent." -LangString launch_qbt ${LANG_MONGOLIAN} "Launch qBittorrent." -;LangString inst_requires_64bit ${LANG_ENGLISH} "This installer works only in 64-bit Windows versions." -LangString inst_requires_64bit ${LANG_MONGOLIAN} "This installer works only in 64-bit Windows versions." - - -;------------------------------------ -;Uninstaller strings - -;LangString remove_files ${LANG_ENGLISH} "Remove files" -LangString remove_files ${LANG_MONGOLIAN} "Remove files" -;LangString remove_shortcuts ${LANG_ENGLISH} "Remove shortcuts" -LangString remove_shortcuts ${LANG_MONGOLIAN} "Remove shortcuts" -;LangString remove_associations ${LANG_ENGLISH} "Remove file associations" -LangString remove_associations ${LANG_MONGOLIAN} "Remove file associations" -;LangString remove_registry ${LANG_ENGLISH} "Remove registry keys" -LangString remove_registry ${LANG_MONGOLIAN} "Remove registry keys" -;LangString remove_conf ${LANG_ENGLISH} "Remove configuration files" -LangString remove_conf ${LANG_MONGOLIAN} "Remove configuration files" -;LangString remove_firewall ${LANG_ENGLISH} "Remove Windows Firewall rule" -LangString remove_firewall ${LANG_MONGOLIAN} "Remove Windows Firewall rule" -;LangString remove_firewallinfo ${LANG_ENGLISH} "Removing Windows Firewall rule" -LangString remove_firewallinfo ${LANG_MONGOLIAN} "Removing Windows Firewall rule" -;LangString remove_cache ${LANG_ENGLISH} "Remove torrents and cached data" -LangString remove_cache ${LANG_MONGOLIAN} "Remove torrents and cached data" -;LangString uninst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before uninstalling." -LangString uninst_warning ${LANG_MONGOLIAN} "qBittorrent is running. Please close the application before uninstalling." -;LangString uninst_tor_warn ${LANG_ENGLISH} "Not removing .torrent association. It is associated with:" -LangString uninst_tor_warn ${LANG_MONGOLIAN} "Not removing .torrent association. It is associated with:" -;LangString uninst_mag_warn ${LANG_ENGLISH} "Not removing magnet association. It is associated with:" -LangString uninst_mag_warn ${LANG_MONGOLIAN} "Not removing magnet association. It is associated with:" diff --git a/dist/windows/installer-translations/norwegian.nsi b/dist/windows/installer-translations/norwegian.nsi deleted file mode 100644 index 18a8cc080..000000000 --- a/dist/windows/installer-translations/norwegian.nsi +++ /dev/null @@ -1,53 +0,0 @@ -;Installer strings - -;LangString inst_qbt_req ${LANG_ENGLISH} "qBittorrent (required)" -LangString inst_qbt_req ${LANG_NORWEGIAN} "qBittorrent (kreves)" -;LangString inst_dekstop ${LANG_ENGLISH} "Create Desktop Shortcut" -LangString inst_dekstop ${LANG_NORWEGIAN} "Opprett Skrivebordssnarvei" -;LangString inst_startmenu ${LANG_ENGLISH} "Create Start Menu Shortcut" -LangString inst_startmenu ${LANG_NORWEGIAN} "Opprett Startmeny-snarvei" -;LangString inst_torrent ${LANG_ENGLISH} "Open .torrent files with qBittorrent" -LangString inst_torrent ${LANG_NORWEGIAN} "Åpne .torrent filer med qBittorrent" -;LangString inst_magnet ${LANG_ENGLISH} "Open magnet links with qBittorrent" -LangString inst_magnet ${LANG_NORWEGIAN} "Åpne magnetlenker med qBittorrent" -;LangString inst_firewall ${LANG_ENGLISH} "Add Windows Firewall rule" -LangString inst_firewall ${LANG_NORWEGIAN} "Legg til Windows-brannmursregel" -;LangString inst_firewallinfo ${LANG_ENGLISH} "Adding Windows Firewall rule" -LangString inst_firewallinfo ${LANG_NORWEGIAN} "Legger til Windows-brannmursregel" -;LangString inst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before installing." -LangString inst_warning ${LANG_NORWEGIAN} "qBittorrent kjører. Vennligst steng applikasjonen før installering." -;LangString inst_uninstall_question ${LANG_ENGLISH} "A previous installation was detected. It will be uninstalled without deleting user settings." -LangString inst_uninstall_question ${LANG_NORWEGIAN} "A previous installation was detected. It will be uninstalled without deleting user settings." -;LangString inst_unist ${LANG_ENGLISH} "Uninstalling previous version." -LangString inst_unist ${LANG_NORWEGIAN} "Avinstallerer forrige versjon." -;LangString launch_qbt ${LANG_ENGLISH} "Launch qBittorrent." -LangString launch_qbt ${LANG_NORWEGIAN} "Sett i gang qBittorrent." -;LangString inst_requires_64bit ${LANG_ENGLISH} "This installer works only in 64-bit Windows versions." -LangString inst_requires_64bit ${LANG_NORWEGIAN} "This installer works only in 64-bit Windows versions." - - -;------------------------------------ -;Uninstaller strings - -;LangString remove_files ${LANG_ENGLISH} "Remove files" -LangString remove_files ${LANG_NORWEGIAN} "Fjern filer" -;LangString remove_shortcuts ${LANG_ENGLISH} "Remove shortcuts" -LangString remove_shortcuts ${LANG_NORWEGIAN} "Fjern snarveier" -;LangString remove_associations ${LANG_ENGLISH} "Remove file associations" -LangString remove_associations ${LANG_NORWEGIAN} "Fjern filassosiasjoner" -;LangString remove_registry ${LANG_ENGLISH} "Remove registry keys" -LangString remove_registry ${LANG_NORWEGIAN} "Fjern registernøkler" -;LangString remove_conf ${LANG_ENGLISH} "Remove configuration files" -LangString remove_conf ${LANG_NORWEGIAN} "Fjern konfigurasjonsfiler" -;LangString remove_firewall ${LANG_ENGLISH} "Remove Windows Firewall rule" -LangString remove_firewall ${LANG_NORWEGIAN} "Fjern Windows-brannmursregel" -;LangString remove_firewallinfo ${LANG_ENGLISH} "Removing Windows Firewall rule" -LangString remove_firewallinfo ${LANG_NORWEGIAN} "Fjerner Windows-brannmursregel" -;LangString remove_cache ${LANG_ENGLISH} "Remove torrents and cached data" -LangString remove_cache ${LANG_NORWEGIAN} "Fjern torrenter og hurtiglagret data" -;LangString uninst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before uninstalling." -LangString uninst_warning ${LANG_NORWEGIAN} "qBittorrent kjører. Vennligst steng applikasjonen før avinstallering." -;LangString uninst_tor_warn ${LANG_ENGLISH} "Not removing .torrent association. It is associated with:" -LangString uninst_tor_warn ${LANG_NORWEGIAN} "Fjerner ikke .torrent assosiasjon. Det er assosiert med:" -;LangString uninst_mag_warn ${LANG_ENGLISH} "Not removing magnet association. It is associated with:" -LangString uninst_mag_warn ${LANG_NORWEGIAN} "Fjerner ikke magnet-assosiasjon. Det er assosiert med:" diff --git a/dist/windows/installer-translations/norwegiannynorsk.nsi b/dist/windows/installer-translations/norwegiannynorsk.nsi deleted file mode 100644 index cc27e43fb..000000000 --- a/dist/windows/installer-translations/norwegiannynorsk.nsi +++ /dev/null @@ -1,53 +0,0 @@ -;Installer strings - -;LangString inst_qbt_req ${LANG_ENGLISH} "qBittorrent (required)" -LangString inst_qbt_req ${LANG_NORWEGIANNYNORSK} "qBittorrent (required)" -;LangString inst_dekstop ${LANG_ENGLISH} "Create Desktop Shortcut" -LangString inst_dekstop ${LANG_NORWEGIANNYNORSK} "Create Desktop Shortcut" -;LangString inst_startmenu ${LANG_ENGLISH} "Create Start Menu Shortcut" -LangString inst_startmenu ${LANG_NORWEGIANNYNORSK} "Create Start Menu Shortcut" -;LangString inst_torrent ${LANG_ENGLISH} "Open .torrent files with qBittorrent" -LangString inst_torrent ${LANG_NORWEGIANNYNORSK} "Open .torrent files with qBittorrent" -;LangString inst_magnet ${LANG_ENGLISH} "Open magnet links with qBittorrent" -LangString inst_magnet ${LANG_NORWEGIANNYNORSK} "Open magnet links with qBittorrent" -;LangString inst_firewall ${LANG_ENGLISH} "Add Windows Firewall rule" -LangString inst_firewall ${LANG_NORWEGIANNYNORSK} "Add Windows Firewall rule" -;LangString inst_firewallinfo ${LANG_ENGLISH} "Adding Windows Firewall rule" -LangString inst_firewallinfo ${LANG_NORWEGIANNYNORSK} "Adding Windows Firewall rule" -;LangString inst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before installing." -LangString inst_warning ${LANG_NORWEGIANNYNORSK} "qBittorrent is running. Please close the application before installing." -;LangString inst_uninstall_question ${LANG_ENGLISH} "A previous installation was detected. It will be uninstalled without deleting user settings." -LangString inst_uninstall_question ${LANG_NORWEGIANNYNORSK} "A previous installation was detected. It will be uninstalled without deleting user settings." -;LangString inst_unist ${LANG_ENGLISH} "Uninstalling previous version." -LangString inst_unist ${LANG_NORWEGIANNYNORSK} "Uninstalling previous version." -;LangString launch_qbt ${LANG_ENGLISH} "Launch qBittorrent." -LangString launch_qbt ${LANG_NORWEGIANNYNORSK} "Launch qBittorrent." -;LangString inst_requires_64bit ${LANG_ENGLISH} "This installer works only in 64-bit Windows versions." -LangString inst_requires_64bit ${LANG_NORWEGIANNYNORSK} "This installer works only in 64-bit Windows versions." - - -;------------------------------------ -;Uninstaller strings - -;LangString remove_files ${LANG_ENGLISH} "Remove files" -LangString remove_files ${LANG_NORWEGIANNYNORSK} "Remove files" -;LangString remove_shortcuts ${LANG_ENGLISH} "Remove shortcuts" -LangString remove_shortcuts ${LANG_NORWEGIANNYNORSK} "Remove shortcuts" -;LangString remove_associations ${LANG_ENGLISH} "Remove file associations" -LangString remove_associations ${LANG_NORWEGIANNYNORSK} "Remove file associations" -;LangString remove_registry ${LANG_ENGLISH} "Remove registry keys" -LangString remove_registry ${LANG_NORWEGIANNYNORSK} "Remove registry keys" -;LangString remove_conf ${LANG_ENGLISH} "Remove configuration files" -LangString remove_conf ${LANG_NORWEGIANNYNORSK} "Remove configuration files" -;LangString remove_firewall ${LANG_ENGLISH} "Remove Windows Firewall rule" -LangString remove_firewall ${LANG_NORWEGIANNYNORSK} "Remove Windows Firewall rule" -;LangString remove_firewallinfo ${LANG_ENGLISH} "Removing Windows Firewall rule" -LangString remove_firewallinfo ${LANG_NORWEGIANNYNORSK} "Removing Windows Firewall rule" -;LangString remove_cache ${LANG_ENGLISH} "Remove torrents and cached data" -LangString remove_cache ${LANG_NORWEGIANNYNORSK} "Remove torrents and cached data" -;LangString uninst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before uninstalling." -LangString uninst_warning ${LANG_NORWEGIANNYNORSK} "qBittorrent is running. Please close the application before uninstalling." -;LangString uninst_tor_warn ${LANG_ENGLISH} "Not removing .torrent association. It is associated with:" -LangString uninst_tor_warn ${LANG_NORWEGIANNYNORSK} "Not removing .torrent association. It is associated with:" -;LangString uninst_mag_warn ${LANG_ENGLISH} "Not removing magnet association. It is associated with:" -LangString uninst_mag_warn ${LANG_NORWEGIANNYNORSK} "Not removing magnet association. It is associated with:" diff --git a/dist/windows/installer-translations/polish.nsi b/dist/windows/installer-translations/polish.nsi deleted file mode 100644 index 171738c18..000000000 --- a/dist/windows/installer-translations/polish.nsi +++ /dev/null @@ -1,53 +0,0 @@ -;Installer strings - -;LangString inst_qbt_req ${LANG_ENGLISH} "qBittorrent (required)" -LangString inst_qbt_req ${LANG_POLISH} "qBittorrent (required)" -;LangString inst_dekstop ${LANG_ENGLISH} "Create Desktop Shortcut" -LangString inst_dekstop ${LANG_POLISH} "Create Desktop Shortcut" -;LangString inst_startmenu ${LANG_ENGLISH} "Create Start Menu Shortcut" -LangString inst_startmenu ${LANG_POLISH} "Create Start Menu Shortcut" -;LangString inst_torrent ${LANG_ENGLISH} "Open .torrent files with qBittorrent" -LangString inst_torrent ${LANG_POLISH} "Open .torrent files with qBittorrent" -;LangString inst_magnet ${LANG_ENGLISH} "Open magnet links with qBittorrent" -LangString inst_magnet ${LANG_POLISH} "Open magnet links with qBittorrent" -;LangString inst_firewall ${LANG_ENGLISH} "Add Windows Firewall rule" -LangString inst_firewall ${LANG_POLISH} "Add Windows Firewall rule" -;LangString inst_firewallinfo ${LANG_ENGLISH} "Adding Windows Firewall rule" -LangString inst_firewallinfo ${LANG_POLISH} "Adding Windows Firewall rule" -;LangString inst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before installing." -LangString inst_warning ${LANG_POLISH} "qBittorrent is running. Please close the application before installing." -;LangString inst_uninstall_question ${LANG_ENGLISH} "A previous installation was detected. It will be uninstalled without deleting user settings." -LangString inst_uninstall_question ${LANG_POLISH} "A previous installation was detected. It will be uninstalled without deleting user settings." -;LangString inst_unist ${LANG_ENGLISH} "Uninstalling previous version." -LangString inst_unist ${LANG_POLISH} "Uninstalling previous version." -;LangString launch_qbt ${LANG_ENGLISH} "Launch qBittorrent." -LangString launch_qbt ${LANG_POLISH} "Launch qBittorrent." -;LangString inst_requires_64bit ${LANG_ENGLISH} "This installer works only in 64-bit Windows versions." -LangString inst_requires_64bit ${LANG_POLISH} "This installer works only in 64-bit Windows versions." - - -;------------------------------------ -;Uninstaller strings - -;LangString remove_files ${LANG_ENGLISH} "Remove files" -LangString remove_files ${LANG_POLISH} "Remove files" -;LangString remove_shortcuts ${LANG_ENGLISH} "Remove shortcuts" -LangString remove_shortcuts ${LANG_POLISH} "Remove shortcuts" -;LangString remove_associations ${LANG_ENGLISH} "Remove file associations" -LangString remove_associations ${LANG_POLISH} "Remove file associations" -;LangString remove_registry ${LANG_ENGLISH} "Remove registry keys" -LangString remove_registry ${LANG_POLISH} "Remove registry keys" -;LangString remove_conf ${LANG_ENGLISH} "Remove configuration files" -LangString remove_conf ${LANG_POLISH} "Remove configuration files" -;LangString remove_firewall ${LANG_ENGLISH} "Remove Windows Firewall rule" -LangString remove_firewall ${LANG_POLISH} "Remove Windows Firewall rule" -;LangString remove_firewallinfo ${LANG_ENGLISH} "Removing Windows Firewall rule" -LangString remove_firewallinfo ${LANG_POLISH} "Removing Windows Firewall rule" -;LangString remove_cache ${LANG_ENGLISH} "Remove torrents and cached data" -LangString remove_cache ${LANG_POLISH} "Remove torrents and cached data" -;LangString uninst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before uninstalling." -LangString uninst_warning ${LANG_POLISH} "qBittorrent is running. Please close the application before uninstalling." -;LangString uninst_tor_warn ${LANG_ENGLISH} "Not removing .torrent association. It is associated with:" -LangString uninst_tor_warn ${LANG_POLISH} "Not removing .torrent association. It is associated with:" -;LangString uninst_mag_warn ${LANG_ENGLISH} "Not removing magnet association. It is associated with:" -LangString uninst_mag_warn ${LANG_POLISH} "Not removing magnet association. It is associated with:" diff --git a/dist/windows/installer-translations/portuguese.nsi b/dist/windows/installer-translations/portuguese.nsi deleted file mode 100644 index f6e7ab394..000000000 --- a/dist/windows/installer-translations/portuguese.nsi +++ /dev/null @@ -1,53 +0,0 @@ -;Installer strings - -;LangString inst_qbt_req ${LANG_ENGLISH} "qBittorrent (required)" -LangString inst_qbt_req ${LANG_PORTUGUESE} "qBittorrent (obrigatório)" -;LangString inst_dekstop ${LANG_ENGLISH} "Create Desktop Shortcut" -LangString inst_dekstop ${LANG_PORTUGUESE} "Criar atalho no ambiente de trabalho" -;LangString inst_startmenu ${LANG_ENGLISH} "Create Start Menu Shortcut" -LangString inst_startmenu ${LANG_PORTUGUESE} "Criar atalho no menu Iniciar" -;LangString inst_torrent ${LANG_ENGLISH} "Open .torrent files with qBittorrent" -LangString inst_torrent ${LANG_PORTUGUESE} "Abrir ficheiros .torrent com o qBittorrent" -;LangString inst_magnet ${LANG_ENGLISH} "Open magnet links with qBittorrent" -LangString inst_magnet ${LANG_PORTUGUESE} "Abrir ligações magnet com o qBittorrent" -;LangString inst_firewall ${LANG_ENGLISH} "Add Windows Firewall rule" -LangString inst_firewall ${LANG_PORTUGUESE} "Adicionar regra à firewall do Windows" -;LangString inst_firewallinfo ${LANG_ENGLISH} "Adding Windows Firewall rule" -LangString inst_firewallinfo ${LANG_PORTUGUESE} "Adicionando regra à firewall do Windows" -;LangString inst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before installing." -LangString inst_warning ${LANG_PORTUGUESE} "O qBittorrent está a ser executado. Feche a aplicação antes de instalar esta versão." -;LangString inst_uninstall_question ${LANG_ENGLISH} "A previous installation was detected. It will be uninstalled without deleting user settings." -LangString inst_uninstall_question ${LANG_PORTUGUESE} "Uma antiga instalação foi encontrada.Essa mesma será desinstalada sem apagar as definições do usuário." -;LangString inst_unist ${LANG_ENGLISH} "Uninstalling previous version." -LangString inst_unist ${LANG_PORTUGUESE} "A desinstalar versão anterior." -;LangString launch_qbt ${LANG_ENGLISH} "Launch qBittorrent." -LangString launch_qbt ${LANG_PORTUGUESE} "Iniciar qBittorrent." -;LangString inst_requires_64bit ${LANG_ENGLISH} "This installer works only in 64-bit Windows versions." -LangString inst_requires_64bit ${LANG_PORTUGUESE} "This installer works only in 64-bit Windows versions." - - -;------------------------------------ -;Uninstaller strings - -;LangString remove_files ${LANG_ENGLISH} "Remove files" -LangString remove_files ${LANG_PORTUGUESE} "Remover ficheiros" -;LangString remove_shortcuts ${LANG_ENGLISH} "Remove shortcuts" -LangString remove_shortcuts ${LANG_PORTUGUESE} "Remover atalhos" -;LangString remove_associations ${LANG_ENGLISH} "Remove file associations" -LangString remove_associations ${LANG_PORTUGUESE} "Remove associação de ficheiros" -;LangString remove_registry ${LANG_ENGLISH} "Remove registry keys" -LangString remove_registry ${LANG_PORTUGUESE} "Remover chaves de registo" -;LangString remove_conf ${LANG_ENGLISH} "Remove configuration files" -LangString remove_conf ${LANG_PORTUGUESE} "Remover ficheiros de configuração" -;LangString remove_firewall ${LANG_ENGLISH} "Remove Windows Firewall rule" -LangString remove_firewall ${LANG_PORTUGUESE} "Remover regra da firewall do Windows" -;LangString remove_firewallinfo ${LANG_ENGLISH} "Removing Windows Firewall rule" -LangString remove_firewallinfo ${LANG_PORTUGUESE} "Removendo regra da firewall do Windows" -;LangString remove_cache ${LANG_ENGLISH} "Remove torrents and cached data" -LangString remove_cache ${LANG_PORTUGUESE} "Remover torrents e dados guardados" -;LangString uninst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before uninstalling." -LangString uninst_warning ${LANG_PORTUGUESE} "O qBittorrent está a ser executado. Feche a aplicação antes de desinstalar esta versão." -;LangString uninst_tor_warn ${LANG_ENGLISH} "Not removing .torrent association. It is associated with:" -LangString uninst_tor_warn ${LANG_PORTUGUESE} "Associação .torrent não removida. Ficheiros associados a:" -;LangString uninst_mag_warn ${LANG_ENGLISH} "Not removing magnet association. It is associated with:" -LangString uninst_mag_warn ${LANG_PORTUGUESE} "Associação magnet nã removida. Ligações associadas a:" diff --git a/dist/windows/installer-translations/portugueseBR.nsi b/dist/windows/installer-translations/portugueseBR.nsi deleted file mode 100644 index 083aba26c..000000000 --- a/dist/windows/installer-translations/portugueseBR.nsi +++ /dev/null @@ -1,53 +0,0 @@ -;Installer strings - -;LangString inst_qbt_req ${LANG_ENGLISH} "qBittorrent (required)" -LangString inst_qbt_req ${LANG_PORTUGUESEBR} "qBittorrent (requerido)" -;LangString inst_dekstop ${LANG_ENGLISH} "Create Desktop Shortcut" -LangString inst_dekstop ${LANG_PORTUGUESEBR} "Criar Atalho no Desktop" -;LangString inst_startmenu ${LANG_ENGLISH} "Create Start Menu Shortcut" -LangString inst_startmenu ${LANG_PORTUGUESEBR} "Criar Atalho no Menu" -;LangString inst_torrent ${LANG_ENGLISH} "Open .torrent files with qBittorrent" -LangString inst_torrent ${LANG_PORTUGUESEBR} "Abrir arquivos .torrent com qBittorrent" -;LangString inst_magnet ${LANG_ENGLISH} "Open magnet links with qBittorrent" -LangString inst_magnet ${LANG_PORTUGUESEBR} "Abrir links magnéticos com qBittorrent" -;LangString inst_firewall ${LANG_ENGLISH} "Add Windows Firewall rule" -LangString inst_firewall ${LANG_PORTUGUESEBR} "Adicionar regra no firewall do Windows" -;LangString inst_firewallinfo ${LANG_ENGLISH} "Adding Windows Firewall rule" -LangString inst_firewallinfo ${LANG_PORTUGUESEBR} "Adicionando regra no firewall do Windows" -;LangString inst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before installing." -LangString inst_warning ${LANG_PORTUGUESEBR} "qBittorrent está rodando. Por favor feche a aplicação antes de instalar." -;LangString inst_uninstall_question ${LANG_ENGLISH} "A previous installation was detected. It will be uninstalled without deleting user settings." -LangString inst_uninstall_question ${LANG_PORTUGUESEBR} "Uma instalação anterior foi detectada. Ela será desistalada sem deletar as configurações de usuário." -;LangString inst_unist ${LANG_ENGLISH} "Uninstalling previous version." -LangString inst_unist ${LANG_PORTUGUESEBR} "Desinstalando versão anterior." -;LangString launch_qbt ${LANG_ENGLISH} "Launch qBittorrent." -LangString launch_qbt ${LANG_PORTUGUESEBR} "Executar qBittorrent." -;LangString inst_requires_64bit ${LANG_ENGLISH} "This installer works only in 64-bit Windows versions." -LangString inst_requires_64bit ${LANG_PORTUGUESEBR} "This installer works only in 64-bit Windows versions." - - -;------------------------------------ -;Uninstaller strings - -;LangString remove_files ${LANG_ENGLISH} "Remove files" -LangString remove_files ${LANG_PORTUGUESEBR} "Remover arquivos" -;LangString remove_shortcuts ${LANG_ENGLISH} "Remove shortcuts" -LangString remove_shortcuts ${LANG_PORTUGUESEBR} "Remover atalhos" -;LangString remove_associations ${LANG_ENGLISH} "Remove file associations" -LangString remove_associations ${LANG_PORTUGUESEBR} "Remover associação de arquivos" -;LangString remove_registry ${LANG_ENGLISH} "Remove registry keys" -LangString remove_registry ${LANG_PORTUGUESEBR} "Remover registros" -;LangString remove_conf ${LANG_ENGLISH} "Remove configuration files" -LangString remove_conf ${LANG_PORTUGUESEBR} "Remover configurações" -;LangString remove_firewall ${LANG_ENGLISH} "Remove Windows Firewall rule" -LangString remove_firewall ${LANG_PORTUGUESEBR} "Remover regras do firewall do Windows" -;LangString remove_firewallinfo ${LANG_ENGLISH} "Removing Windows Firewall rule" -LangString remove_firewallinfo ${LANG_PORTUGUESEBR} "Removendo regras do firewall do Windows" -;LangString remove_cache ${LANG_ENGLISH} "Remove torrents and cached data" -LangString remove_cache ${LANG_PORTUGUESEBR} "Remover torrents e dados em cache" -;LangString uninst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before uninstalling." -LangString uninst_warning ${LANG_PORTUGUESEBR} "qBittorrent está rodando. Por favor feche a aplicação antes de desinstalar." -;LangString uninst_tor_warn ${LANG_ENGLISH} "Not removing .torrent association. It is associated with:" -LangString uninst_tor_warn ${LANG_PORTUGUESEBR} "Não removendo associação com .torrent. Está associado com:" -;LangString uninst_mag_warn ${LANG_ENGLISH} "Not removing magnet association. It is associated with:" -LangString uninst_mag_warn ${LANG_PORTUGUESEBR} "Não removendo associação com links magnéticos. Está associado com:" diff --git a/dist/windows/installer-translations/romanian.nsi b/dist/windows/installer-translations/romanian.nsi deleted file mode 100644 index a0ec4cd54..000000000 --- a/dist/windows/installer-translations/romanian.nsi +++ /dev/null @@ -1,53 +0,0 @@ -;Installer strings - -;LangString inst_qbt_req ${LANG_ENGLISH} "qBittorrent (required)" -LangString inst_qbt_req ${LANG_ROMANIAN} "qBittorrent (required)" -;LangString inst_dekstop ${LANG_ENGLISH} "Create Desktop Shortcut" -LangString inst_dekstop ${LANG_ROMANIAN} "Create Desktop Shortcut" -;LangString inst_startmenu ${LANG_ENGLISH} "Create Start Menu Shortcut" -LangString inst_startmenu ${LANG_ROMANIAN} "Create Start Menu Shortcut" -;LangString inst_torrent ${LANG_ENGLISH} "Open .torrent files with qBittorrent" -LangString inst_torrent ${LANG_ROMANIAN} "Open .torrent files with qBittorrent" -;LangString inst_magnet ${LANG_ENGLISH} "Open magnet links with qBittorrent" -LangString inst_magnet ${LANG_ROMANIAN} "Open magnet links with qBittorrent" -;LangString inst_firewall ${LANG_ENGLISH} "Add Windows Firewall rule" -LangString inst_firewall ${LANG_ROMANIAN} "Add Windows Firewall rule" -;LangString inst_firewallinfo ${LANG_ENGLISH} "Adding Windows Firewall rule" -LangString inst_firewallinfo ${LANG_ROMANIAN} "Adding Windows Firewall rule" -;LangString inst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before installing." -LangString inst_warning ${LANG_ROMANIAN} "qBittorrent is running. Please close the application before installing." -;LangString inst_uninstall_question ${LANG_ENGLISH} "A previous installation was detected. It will be uninstalled without deleting user settings." -LangString inst_uninstall_question ${LANG_ROMANIAN} "A previous installation was detected. It will be uninstalled without deleting user settings." -;LangString inst_unist ${LANG_ENGLISH} "Uninstalling previous version." -LangString inst_unist ${LANG_ROMANIAN} "Uninstalling previous version." -;LangString launch_qbt ${LANG_ENGLISH} "Launch qBittorrent." -LangString launch_qbt ${LANG_ROMANIAN} "Launch qBittorrent." -;LangString inst_requires_64bit ${LANG_ENGLISH} "This installer works only in 64-bit Windows versions." -LangString inst_requires_64bit ${LANG_ROMANIAN} "This installer works only in 64-bit Windows versions." - - -;------------------------------------ -;Uninstaller strings - -;LangString remove_files ${LANG_ENGLISH} "Remove files" -LangString remove_files ${LANG_ROMANIAN} "Remove files" -;LangString remove_shortcuts ${LANG_ENGLISH} "Remove shortcuts" -LangString remove_shortcuts ${LANG_ROMANIAN} "Remove shortcuts" -;LangString remove_associations ${LANG_ENGLISH} "Remove file associations" -LangString remove_associations ${LANG_ROMANIAN} "Remove file associations" -;LangString remove_registry ${LANG_ENGLISH} "Remove registry keys" -LangString remove_registry ${LANG_ROMANIAN} "Remove registry keys" -;LangString remove_conf ${LANG_ENGLISH} "Remove configuration files" -LangString remove_conf ${LANG_ROMANIAN} "Remove configuration files" -;LangString remove_firewall ${LANG_ENGLISH} "Remove Windows Firewall rule" -LangString remove_firewall ${LANG_ROMANIAN} "Remove Windows Firewall rule" -;LangString remove_firewallinfo ${LANG_ENGLISH} "Removing Windows Firewall rule" -LangString remove_firewallinfo ${LANG_ROMANIAN} "Removing Windows Firewall rule" -;LangString remove_cache ${LANG_ENGLISH} "Remove torrents and cached data" -LangString remove_cache ${LANG_ROMANIAN} "Remove torrents and cached data" -;LangString uninst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before uninstalling." -LangString uninst_warning ${LANG_ROMANIAN} "qBittorrent is running. Please close the application before uninstalling." -;LangString uninst_tor_warn ${LANG_ENGLISH} "Not removing .torrent association. It is associated with:" -LangString uninst_tor_warn ${LANG_ROMANIAN} "Not removing .torrent association. It is associated with:" -;LangString uninst_mag_warn ${LANG_ENGLISH} "Not removing magnet association. It is associated with:" -LangString uninst_mag_warn ${LANG_ROMANIAN} "Not removing magnet association. It is associated with:" diff --git a/dist/windows/installer-translations/russian.nsi b/dist/windows/installer-translations/russian.nsi deleted file mode 100644 index a265e432f..000000000 --- a/dist/windows/installer-translations/russian.nsi +++ /dev/null @@ -1,53 +0,0 @@ -;Installer strings - -;LangString inst_qbt_req ${LANG_ENGLISH} "qBittorrent (required)" -LangString inst_qbt_req ${LANG_RUSSIAN} "qBittorrent (обязательно)" -;LangString inst_dekstop ${LANG_ENGLISH} "Create Desktop Shortcut" -LangString inst_dekstop ${LANG_RUSSIAN} "Создать ярлык на рабочем столе" -;LangString inst_startmenu ${LANG_ENGLISH} "Create Start Menu Shortcut" -LangString inst_startmenu ${LANG_RUSSIAN} "Создать ярлык в меню Пуск" -;LangString inst_torrent ${LANG_ENGLISH} "Open .torrent files with qBittorrent" -LangString inst_torrent ${LANG_RUSSIAN} "Открывать торрент-файлы с помощью qBittorrent" -;LangString inst_magnet ${LANG_ENGLISH} "Open magnet links with qBittorrent" -LangString inst_magnet ${LANG_RUSSIAN} "Открывать magnet-ссылки с помощью qBittorrent" -;LangString inst_firewall ${LANG_ENGLISH} "Add Windows Firewall rule" -LangString inst_firewall ${LANG_RUSSIAN} "Добавить в список исключений брандмауера" -;LangString inst_firewallinfo ${LANG_ENGLISH} "Adding Windows Firewall rule" -LangString inst_firewallinfo ${LANG_RUSSIAN} "Добавление в список исключений брандмауера" -;LangString inst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before installing." -LangString inst_warning ${LANG_RUSSIAN} "qBittorrent запущен. Пожалуйста, закройте qBittorrent и перезапустите программу установки." -;LangString inst_uninstall_question ${LANG_ENGLISH} "A previous installation was detected. It will be uninstalled without deleting user settings." -LangString inst_uninstall_question ${LANG_RUSSIAN} "Обнаружена предыдущая установка. Она будет деинсталлирована без удаления пользовательских настроек." -;LangString inst_unist ${LANG_ENGLISH} "Uninstalling previous version." -LangString inst_unist ${LANG_RUSSIAN} "Деинсталлируем старую версию." -;LangString launch_qbt ${LANG_ENGLISH} "Launch qBittorrent." -LangString launch_qbt ${LANG_RUSSIAN} "Запустить qBittorrent." -;LangString inst_requires_64bit ${LANG_ENGLISH} "This installer works only in 64-bit Windows versions." -LangString inst_requires_64bit ${LANG_RUSSIAN} "Этот установщик работает только на 64-битных версиях Windows." - - -;------------------------------------ -;Uninstaller strings - -;LangString remove_files ${LANG_ENGLISH} "Remove files" -LangString remove_files ${LANG_RUSSIAN} "Удалить файлы" -;LangString remove_shortcuts ${LANG_ENGLISH} "Remove shortcuts" -LangString remove_shortcuts ${LANG_RUSSIAN} "Удалить ярлыки" -;LangString remove_associations ${LANG_ENGLISH} "Remove file associations" -LangString remove_associations ${LANG_RUSSIAN} "Сбросить ассоциации файлов" -;LangString remove_registry ${LANG_ENGLISH} "Remove registry keys" -LangString remove_registry ${LANG_RUSSIAN} "Удалить данные из реестра" -;LangString remove_conf ${LANG_ENGLISH} "Remove configuration files" -LangString remove_conf ${LANG_RUSSIAN} "Удалить пользовательские настройки" -;LangString remove_firewall ${LANG_ENGLISH} "Remove Windows Firewall rule" -LangString remove_firewall ${LANG_RUSSIAN} "Удалить из списка исключений брандмауера" -;LangString remove_firewallinfo ${LANG_ENGLISH} "Removing Windows Firewall rule" -LangString remove_firewallinfo ${LANG_RUSSIAN} "Удаление из списка исключений брандмауера" -;LangString remove_cache ${LANG_ENGLISH} "Remove torrents and cached data" -LangString remove_cache ${LANG_RUSSIAN} "Удалить сохранённые торрент-файлы" -;LangString uninst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before uninstalling." -LangString uninst_warning ${LANG_RUSSIAN} "qBittorrent запущен. Пожалуйста, закройте qBittorrent и перезапустите программу удаления." -;LangString uninst_tor_warn ${LANG_ENGLISH} "Not removing .torrent association. It is associated with:" -LangString uninst_tor_warn ${LANG_RUSSIAN} "Ассоциации торрент-файлов не сброшены. Уже ассоциированы с:" -;LangString uninst_mag_warn ${LANG_ENGLISH} "Not removing magnet association. It is associated with:" -LangString uninst_mag_warn ${LANG_RUSSIAN} "Ассоциации magnet-ссылок не сброшены. Уже ассоциированы с:" diff --git a/dist/windows/installer-translations/serbian.nsi b/dist/windows/installer-translations/serbian.nsi deleted file mode 100644 index 6e2f5e4e6..000000000 --- a/dist/windows/installer-translations/serbian.nsi +++ /dev/null @@ -1,53 +0,0 @@ -;Installer strings - -;LangString inst_qbt_req ${LANG_ENGLISH} "qBittorrent (required)" -LangString inst_qbt_req ${LANG_SERBIAN} "qBittorrent (required)" -;LangString inst_dekstop ${LANG_ENGLISH} "Create Desktop Shortcut" -LangString inst_dekstop ${LANG_SERBIAN} "Create Desktop Shortcut" -;LangString inst_startmenu ${LANG_ENGLISH} "Create Start Menu Shortcut" -LangString inst_startmenu ${LANG_SERBIAN} "Create Start Menu Shortcut" -;LangString inst_torrent ${LANG_ENGLISH} "Open .torrent files with qBittorrent" -LangString inst_torrent ${LANG_SERBIAN} "Open .torrent files with qBittorrent" -;LangString inst_magnet ${LANG_ENGLISH} "Open magnet links with qBittorrent" -LangString inst_magnet ${LANG_SERBIAN} "Open magnet links with qBittorrent" -;LangString inst_firewall ${LANG_ENGLISH} "Add Windows Firewall rule" -LangString inst_firewall ${LANG_SERBIAN} "Add Windows Firewall rule" -;LangString inst_firewallinfo ${LANG_ENGLISH} "Adding Windows Firewall rule" -LangString inst_firewallinfo ${LANG_SERBIAN} "Adding Windows Firewall rule" -;LangString inst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before installing." -LangString inst_warning ${LANG_SERBIAN} "qBittorrent is running. Please close the application before installing." -;LangString inst_uninstall_question ${LANG_ENGLISH} "A previous installation was detected. It will be uninstalled without deleting user settings." -LangString inst_uninstall_question ${LANG_SERBIAN} "A previous installation was detected. It will be uninstalled without deleting user settings." -;LangString inst_unist ${LANG_ENGLISH} "Uninstalling previous version." -LangString inst_unist ${LANG_SERBIAN} "Uninstalling previous version." -;LangString launch_qbt ${LANG_ENGLISH} "Launch qBittorrent." -LangString launch_qbt ${LANG_SERBIAN} "Launch qBittorrent." -;LangString inst_requires_64bit ${LANG_ENGLISH} "This installer works only in 64-bit Windows versions." -LangString inst_requires_64bit ${LANG_SERBIAN} "This installer works only in 64-bit Windows versions." - - -;------------------------------------ -;Uninstaller strings - -;LangString remove_files ${LANG_ENGLISH} "Remove files" -LangString remove_files ${LANG_SERBIAN} "Remove files" -;LangString remove_shortcuts ${LANG_ENGLISH} "Remove shortcuts" -LangString remove_shortcuts ${LANG_SERBIAN} "Remove shortcuts" -;LangString remove_associations ${LANG_ENGLISH} "Remove file associations" -LangString remove_associations ${LANG_SERBIAN} "Remove file associations" -;LangString remove_registry ${LANG_ENGLISH} "Remove registry keys" -LangString remove_registry ${LANG_SERBIAN} "Remove registry keys" -;LangString remove_conf ${LANG_ENGLISH} "Remove configuration files" -LangString remove_conf ${LANG_SERBIAN} "Remove configuration files" -;LangString remove_firewall ${LANG_ENGLISH} "Remove Windows Firewall rule" -LangString remove_firewall ${LANG_SERBIAN} "Remove Windows Firewall rule" -;LangString remove_firewallinfo ${LANG_ENGLISH} "Removing Windows Firewall rule" -LangString remove_firewallinfo ${LANG_SERBIAN} "Removing Windows Firewall rule" -;LangString remove_cache ${LANG_ENGLISH} "Remove torrents and cached data" -LangString remove_cache ${LANG_SERBIAN} "Remove torrents and cached data" -;LangString uninst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before uninstalling." -LangString uninst_warning ${LANG_SERBIAN} "qBittorrent is running. Please close the application before uninstalling." -;LangString uninst_tor_warn ${LANG_ENGLISH} "Not removing .torrent association. It is associated with:" -LangString uninst_tor_warn ${LANG_SERBIAN} "Not removing .torrent association. It is associated with:" -;LangString uninst_mag_warn ${LANG_ENGLISH} "Not removing magnet association. It is associated with:" -LangString uninst_mag_warn ${LANG_SERBIAN} "Not removing magnet association. It is associated with:" diff --git a/dist/windows/installer-translations/serbianlatin.nsi b/dist/windows/installer-translations/serbianlatin.nsi deleted file mode 100644 index 637a69c82..000000000 --- a/dist/windows/installer-translations/serbianlatin.nsi +++ /dev/null @@ -1,53 +0,0 @@ -;Installer strings - -;LangString inst_qbt_req ${LANG_ENGLISH} "qBittorrent (required)" -LangString inst_qbt_req ${LANG_SERBIANLATIN} "qBittorrent (required)" -;LangString inst_dekstop ${LANG_ENGLISH} "Create Desktop Shortcut" -LangString inst_dekstop ${LANG_SERBIANLATIN} "Create Desktop Shortcut" -;LangString inst_startmenu ${LANG_ENGLISH} "Create Start Menu Shortcut" -LangString inst_startmenu ${LANG_SERBIANLATIN} "Create Start Menu Shortcut" -;LangString inst_torrent ${LANG_ENGLISH} "Open .torrent files with qBittorrent" -LangString inst_torrent ${LANG_SERBIANLATIN} "Open .torrent files with qBittorrent" -;LangString inst_magnet ${LANG_ENGLISH} "Open magnet links with qBittorrent" -LangString inst_magnet ${LANG_SERBIANLATIN} "Open magnet links with qBittorrent" -;LangString inst_firewall ${LANG_ENGLISH} "Add Windows Firewall rule" -LangString inst_firewall ${LANG_SERBIANLATIN} "Add Windows Firewall rule" -;LangString inst_firewallinfo ${LANG_ENGLISH} "Adding Windows Firewall rule" -LangString inst_firewallinfo ${LANG_SERBIANLATIN} "Adding Windows Firewall rule" -;LangString inst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before installing." -LangString inst_warning ${LANG_SERBIANLATIN} "qBittorrent is running. Please close the application before installing." -;LangString inst_uninstall_question ${LANG_ENGLISH} "A previous installation was detected. It will be uninstalled without deleting user settings." -LangString inst_uninstall_question ${LANG_SERBIANLATIN} "A previous installation was detected. It will be uninstalled without deleting user settings." -;LangString inst_unist ${LANG_ENGLISH} "Uninstalling previous version." -LangString inst_unist ${LANG_SERBIANLATIN} "Uninstalling previous version." -;LangString launch_qbt ${LANG_ENGLISH} "Launch qBittorrent." -LangString launch_qbt ${LANG_SERBIANLATIN} "Launch qBittorrent." -;LangString inst_requires_64bit ${LANG_ENGLISH} "This installer works only in 64-bit Windows versions." -LangString inst_requires_64bit ${LANG_SERBIANLATIN} "This installer works only in 64-bit Windows versions." - - -;------------------------------------ -;Uninstaller strings - -;LangString remove_files ${LANG_ENGLISH} "Remove files" -LangString remove_files ${LANG_SERBIANLATIN} "Remove files" -;LangString remove_shortcuts ${LANG_ENGLISH} "Remove shortcuts" -LangString remove_shortcuts ${LANG_SERBIANLATIN} "Remove shortcuts" -;LangString remove_associations ${LANG_ENGLISH} "Remove file associations" -LangString remove_associations ${LANG_SERBIANLATIN} "Remove file associations" -;LangString remove_registry ${LANG_ENGLISH} "Remove registry keys" -LangString remove_registry ${LANG_SERBIANLATIN} "Remove registry keys" -;LangString remove_conf ${LANG_ENGLISH} "Remove configuration files" -LangString remove_conf ${LANG_SERBIANLATIN} "Remove configuration files" -;LangString remove_firewall ${LANG_ENGLISH} "Remove Windows Firewall rule" -LangString remove_firewall ${LANG_SERBIANLATIN} "Remove Windows Firewall rule" -;LangString remove_firewallinfo ${LANG_ENGLISH} "Removing Windows Firewall rule" -LangString remove_firewallinfo ${LANG_SERBIANLATIN} "Removing Windows Firewall rule" -;LangString remove_cache ${LANG_ENGLISH} "Remove torrents and cached data" -LangString remove_cache ${LANG_SERBIANLATIN} "Remove torrents and cached data" -;LangString uninst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before uninstalling." -LangString uninst_warning ${LANG_SERBIANLATIN} "qBittorrent is running. Please close the application before uninstalling." -;LangString uninst_tor_warn ${LANG_ENGLISH} "Not removing .torrent association. It is associated with:" -LangString uninst_tor_warn ${LANG_SERBIANLATIN} "Not removing .torrent association. It is associated with:" -;LangString uninst_mag_warn ${LANG_ENGLISH} "Not removing magnet association. It is associated with:" -LangString uninst_mag_warn ${LANG_SERBIANLATIN} "Not removing magnet association. It is associated with:" diff --git a/dist/windows/installer-translations/simpchinese.nsi b/dist/windows/installer-translations/simpchinese.nsi deleted file mode 100644 index d5f6f6f1b..000000000 --- a/dist/windows/installer-translations/simpchinese.nsi +++ /dev/null @@ -1,53 +0,0 @@ -;Installer strings - -;LangString inst_qbt_req ${LANG_ENGLISH} "qBittorrent (required)" -LangString inst_qbt_req ${LANG_SIMPCHINESE} "qBittorrent (必要)" -;LangString inst_dekstop ${LANG_ENGLISH} "Create Desktop Shortcut" -LangString inst_dekstop ${LANG_SIMPCHINESE} "创建桌面快捷方式" -;LangString inst_startmenu ${LANG_ENGLISH} "Create Start Menu Shortcut" -LangString inst_startmenu ${LANG_SIMPCHINESE} "创建开始菜单快捷方式" -;LangString inst_torrent ${LANG_ENGLISH} "Open .torrent files with qBittorrent" -LangString inst_torrent ${LANG_SIMPCHINESE} "用 qBittorrent 打开.torrent文件" -;LangString inst_magnet ${LANG_ENGLISH} "Open magnet links with qBittorrent" -LangString inst_magnet ${LANG_SIMPCHINESE} "用 qBittorrent 打开磁力链接" -;LangString inst_firewall ${LANG_ENGLISH} "Add Windows Firewall rule" -LangString inst_firewall ${LANG_SIMPCHINESE} "添加Windows防火墙规则" -;LangString inst_firewallinfo ${LANG_ENGLISH} "Adding Windows Firewall rule" -LangString inst_firewallinfo ${LANG_SIMPCHINESE} "正在添加Windows防火墙规则" -;LangString inst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before installing." -LangString inst_warning ${LANG_SIMPCHINESE} "qBittorrent 正在运行。 安装前请关闭应用程序。" -;LangString inst_uninstall_question ${LANG_ENGLISH} "A previous installation was detected. It will be uninstalled without deleting user settings." -LangString inst_uninstall_question ${LANG_SIMPCHINESE} "检测到以前的安装。 它将被卸载但不删除用户设置。" -;LangString inst_unist ${LANG_ENGLISH} "Uninstalling previous version." -LangString inst_unist ${LANG_SIMPCHINESE} "卸载以前的版本。" -;LangString launch_qbt ${LANG_ENGLISH} "Launch qBittorrent." -LangString launch_qbt ${LANG_SIMPCHINESE} "启动 qBittorrent." -;LangString inst_requires_64bit ${LANG_ENGLISH} "This installer works only in 64-bit Windows versions." -LangString inst_requires_64bit ${LANG_SIMPCHINESE} "此安装程序只能在64位的Windows上工作。" - - -;------------------------------------ -;Uninstaller strings - -;LangString remove_files ${LANG_ENGLISH} "Remove files" -LangString remove_files ${LANG_SIMPCHINESE} "删除文件" -;LangString remove_shortcuts ${LANG_ENGLISH} "Remove shortcuts" -LangString remove_shortcuts ${LANG_SIMPCHINESE} "删除快捷方式" -;LangString remove_associations ${LANG_ENGLISH} "Remove file associations" -LangString remove_associations ${LANG_SIMPCHINESE} "删除文件关联" -;LangString remove_registry ${LANG_ENGLISH} "Remove registry keys" -LangString remove_registry ${LANG_SIMPCHINESE} "删除注册表键" -;LangString remove_conf ${LANG_ENGLISH} "Remove configuration files" -LangString remove_conf ${LANG_SIMPCHINESE} "删除配置文件" -;LangString remove_firewall ${LANG_ENGLISH} "Remove Windows Firewall rule" -LangString remove_firewall ${LANG_SIMPCHINESE} "删除Windows防火墙规则" -;LangString remove_firewallinfo ${LANG_ENGLISH} "Removing Windows Firewall rule" -LangString remove_firewallinfo ${LANG_SIMPCHINESE} "正在删除Windows防火墙规则" -;LangString remove_cache ${LANG_ENGLISH} "Remove torrents and cached data" -LangString remove_cache ${LANG_SIMPCHINESE} "删除种子和缓存数据" -;LangString uninst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before uninstalling." -LangString uninst_warning ${LANG_SIMPCHINESE} "qBittorrent 正在运行。 卸载前请关闭程序。" -;LangString uninst_tor_warn ${LANG_ENGLISH} "Not removing .torrent association. It is associated with:" -LangString uninst_tor_warn ${LANG_SIMPCHINESE} "不删除 .torrent 关联。 关联的是:" -;LangString uninst_mag_warn ${LANG_ENGLISH} "Not removing magnet association. It is associated with:" -LangString uninst_mag_warn ${LANG_SIMPCHINESE} "不删除磁力关联。 关联的是:" diff --git a/dist/windows/installer-translations/slovak.nsi b/dist/windows/installer-translations/slovak.nsi deleted file mode 100644 index 9e43420ae..000000000 --- a/dist/windows/installer-translations/slovak.nsi +++ /dev/null @@ -1,53 +0,0 @@ -;Installer strings - -;LangString inst_qbt_req ${LANG_ENGLISH} "qBittorrent (required)" -LangString inst_qbt_req ${LANG_SLOVAK} "qBittorrent (required)" -;LangString inst_dekstop ${LANG_ENGLISH} "Create Desktop Shortcut" -LangString inst_dekstop ${LANG_SLOVAK} "Create Desktop Shortcut" -;LangString inst_startmenu ${LANG_ENGLISH} "Create Start Menu Shortcut" -LangString inst_startmenu ${LANG_SLOVAK} "Create Start Menu Shortcut" -;LangString inst_torrent ${LANG_ENGLISH} "Open .torrent files with qBittorrent" -LangString inst_torrent ${LANG_SLOVAK} "Open .torrent files with qBittorrent" -;LangString inst_magnet ${LANG_ENGLISH} "Open magnet links with qBittorrent" -LangString inst_magnet ${LANG_SLOVAK} "Open magnet links with qBittorrent" -;LangString inst_firewall ${LANG_ENGLISH} "Add Windows Firewall rule" -LangString inst_firewall ${LANG_SLOVAK} "Add Windows Firewall rule" -;LangString inst_firewallinfo ${LANG_ENGLISH} "Adding Windows Firewall rule" -LangString inst_firewallinfo ${LANG_SLOVAK} "Adding Windows Firewall rule" -;LangString inst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before installing." -LangString inst_warning ${LANG_SLOVAK} "qBittorrent is running. Please close the application before installing." -;LangString inst_uninstall_question ${LANG_ENGLISH} "A previous installation was detected. It will be uninstalled without deleting user settings." -LangString inst_uninstall_question ${LANG_SLOVAK} "A previous installation was detected. It will be uninstalled without deleting user settings." -;LangString inst_unist ${LANG_ENGLISH} "Uninstalling previous version." -LangString inst_unist ${LANG_SLOVAK} "Uninstalling previous version." -;LangString launch_qbt ${LANG_ENGLISH} "Launch qBittorrent." -LangString launch_qbt ${LANG_SLOVAK} "Launch qBittorrent." -;LangString inst_requires_64bit ${LANG_ENGLISH} "This installer works only in 64-bit Windows versions." -LangString inst_requires_64bit ${LANG_SLOVAK} "This installer works only in 64-bit Windows versions." - - -;------------------------------------ -;Uninstaller strings - -;LangString remove_files ${LANG_ENGLISH} "Remove files" -LangString remove_files ${LANG_SLOVAK} "Remove files" -;LangString remove_shortcuts ${LANG_ENGLISH} "Remove shortcuts" -LangString remove_shortcuts ${LANG_SLOVAK} "Remove shortcuts" -;LangString remove_associations ${LANG_ENGLISH} "Remove file associations" -LangString remove_associations ${LANG_SLOVAK} "Remove file associations" -;LangString remove_registry ${LANG_ENGLISH} "Remove registry keys" -LangString remove_registry ${LANG_SLOVAK} "Remove registry keys" -;LangString remove_conf ${LANG_ENGLISH} "Remove configuration files" -LangString remove_conf ${LANG_SLOVAK} "Remove configuration files" -;LangString remove_firewall ${LANG_ENGLISH} "Remove Windows Firewall rule" -LangString remove_firewall ${LANG_SLOVAK} "Remove Windows Firewall rule" -;LangString remove_firewallinfo ${LANG_ENGLISH} "Removing Windows Firewall rule" -LangString remove_firewallinfo ${LANG_SLOVAK} "Removing Windows Firewall rule" -;LangString remove_cache ${LANG_ENGLISH} "Remove torrents and cached data" -LangString remove_cache ${LANG_SLOVAK} "Remove torrents and cached data" -;LangString uninst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before uninstalling." -LangString uninst_warning ${LANG_SLOVAK} "qBittorrent is running. Please close the application before uninstalling." -;LangString uninst_tor_warn ${LANG_ENGLISH} "Not removing .torrent association. It is associated with:" -LangString uninst_tor_warn ${LANG_SLOVAK} "Not removing .torrent association. It is associated with:" -;LangString uninst_mag_warn ${LANG_ENGLISH} "Not removing magnet association. It is associated with:" -LangString uninst_mag_warn ${LANG_SLOVAK} "Not removing magnet association. It is associated with:" diff --git a/dist/windows/installer-translations/slovenian.nsi b/dist/windows/installer-translations/slovenian.nsi deleted file mode 100644 index 824afd33b..000000000 --- a/dist/windows/installer-translations/slovenian.nsi +++ /dev/null @@ -1,53 +0,0 @@ -;Installer strings - -;LangString inst_qbt_req ${LANG_ENGLISH} "qBittorrent (required)" -LangString inst_qbt_req ${LANG_SLOVENIAN} "qBittorrent (required)" -;LangString inst_dekstop ${LANG_ENGLISH} "Create Desktop Shortcut" -LangString inst_dekstop ${LANG_SLOVENIAN} "Create Desktop Shortcut" -;LangString inst_startmenu ${LANG_ENGLISH} "Create Start Menu Shortcut" -LangString inst_startmenu ${LANG_SLOVENIAN} "Create Start Menu Shortcut" -;LangString inst_torrent ${LANG_ENGLISH} "Open .torrent files with qBittorrent" -LangString inst_torrent ${LANG_SLOVENIAN} "Open .torrent files with qBittorrent" -;LangString inst_magnet ${LANG_ENGLISH} "Open magnet links with qBittorrent" -LangString inst_magnet ${LANG_SLOVENIAN} "Open magnet links with qBittorrent" -;LangString inst_firewall ${LANG_ENGLISH} "Add Windows Firewall rule" -LangString inst_firewall ${LANG_SLOVENIAN} "Add Windows Firewall rule" -;LangString inst_firewallinfo ${LANG_ENGLISH} "Adding Windows Firewall rule" -LangString inst_firewallinfo ${LANG_SLOVENIAN} "Adding Windows Firewall rule" -;LangString inst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before installing." -LangString inst_warning ${LANG_SLOVENIAN} "qBittorrent is running. Please close the application before installing." -;LangString inst_uninstall_question ${LANG_ENGLISH} "A previous installation was detected. It will be uninstalled without deleting user settings." -LangString inst_uninstall_question ${LANG_SLOVENIAN} "A previous installation was detected. It will be uninstalled without deleting user settings." -;LangString inst_unist ${LANG_ENGLISH} "Uninstalling previous version." -LangString inst_unist ${LANG_SLOVENIAN} "Uninstalling previous version." -;LangString launch_qbt ${LANG_ENGLISH} "Launch qBittorrent." -LangString launch_qbt ${LANG_SLOVENIAN} "Launch qBittorrent." -;LangString inst_requires_64bit ${LANG_ENGLISH} "This installer works only in 64-bit Windows versions." -LangString inst_requires_64bit ${LANG_SLOVENIAN} "This installer works only in 64-bit Windows versions." - - -;------------------------------------ -;Uninstaller strings - -;LangString remove_files ${LANG_ENGLISH} "Remove files" -LangString remove_files ${LANG_SLOVENIAN} "Remove files" -;LangString remove_shortcuts ${LANG_ENGLISH} "Remove shortcuts" -LangString remove_shortcuts ${LANG_SLOVENIAN} "Remove shortcuts" -;LangString remove_associations ${LANG_ENGLISH} "Remove file associations" -LangString remove_associations ${LANG_SLOVENIAN} "Remove file associations" -;LangString remove_registry ${LANG_ENGLISH} "Remove registry keys" -LangString remove_registry ${LANG_SLOVENIAN} "Remove registry keys" -;LangString remove_conf ${LANG_ENGLISH} "Remove configuration files" -LangString remove_conf ${LANG_SLOVENIAN} "Remove configuration files" -;LangString remove_firewall ${LANG_ENGLISH} "Remove Windows Firewall rule" -LangString remove_firewall ${LANG_SLOVENIAN} "Remove Windows Firewall rule" -;LangString remove_firewallinfo ${LANG_ENGLISH} "Removing Windows Firewall rule" -LangString remove_firewallinfo ${LANG_SLOVENIAN} "Removing Windows Firewall rule" -;LangString remove_cache ${LANG_ENGLISH} "Remove torrents and cached data" -LangString remove_cache ${LANG_SLOVENIAN} "Remove torrents and cached data" -;LangString uninst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before uninstalling." -LangString uninst_warning ${LANG_SLOVENIAN} "qBittorrent is running. Please close the application before uninstalling." -;LangString uninst_tor_warn ${LANG_ENGLISH} "Not removing .torrent association. It is associated with:" -LangString uninst_tor_warn ${LANG_SLOVENIAN} "Not removing .torrent association. It is associated with:" -;LangString uninst_mag_warn ${LANG_ENGLISH} "Not removing magnet association. It is associated with:" -LangString uninst_mag_warn ${LANG_SLOVENIAN} "Not removing magnet association. It is associated with:" diff --git a/dist/windows/installer-translations/spanish.nsi b/dist/windows/installer-translations/spanish.nsi deleted file mode 100644 index 7681e30f4..000000000 --- a/dist/windows/installer-translations/spanish.nsi +++ /dev/null @@ -1,53 +0,0 @@ -;Installer strings - -;LangString inst_qbt_req ${LANG_ENGLISH} "qBittorrent (required)" -LangString inst_qbt_req ${LANG_SPANISH} "qBittorrent (necesario)" -;LangString inst_dekstop ${LANG_ENGLISH} "Create Desktop Shortcut" -LangString inst_dekstop ${LANG_SPANISH} "Crear un acceso directo en el escritorio" -;LangString inst_startmenu ${LANG_ENGLISH} "Create Start Menu Shortcut" -LangString inst_startmenu ${LANG_SPANISH} "Crear un acceso directo en el menú inicio" -;LangString inst_torrent ${LANG_ENGLISH} "Open .torrent files with qBittorrent" -LangString inst_torrent ${LANG_SPANISH} "Abrir archivos .torrent con qBittorrent" -;LangString inst_magnet ${LANG_ENGLISH} "Open magnet links with qBittorrent" -LangString inst_magnet ${LANG_SPANISH} "Abrir enlaces magnet con qBittorrent" -;LangString inst_firewall ${LANG_ENGLISH} "Add Windows Firewall rule" -LangString inst_firewall ${LANG_SPANISH} "Añadir regla al Firewall de Windows" -;LangString inst_firewallinfo ${LANG_ENGLISH} "Adding Windows Firewall rule" -LangString inst_firewallinfo ${LANG_SPANISH} "Añadiendo regla al Firewall de Windows" -;LangString inst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before installing." -LangString inst_warning ${LANG_SPANISH} "qBittorrent se está ejecutando. Ciérrelo antes de continuar." -;LangString inst_uninstall_question ${LANG_ENGLISH} "A previous installation was detected. It will be uninstalled without deleting user settings." -LangString inst_uninstall_question ${LANG_SPANISH} "Se detectó una instalación anterior. Será desinstalada sin eliminar la configuración del usuario." -;LangString inst_unist ${LANG_ENGLISH} "Uninstalling previous version." -LangString inst_unist ${LANG_SPANISH} "Desinstalando la versión anterior." -;LangString launch_qbt ${LANG_ENGLISH} "Launch qBittorrent." -LangString launch_qbt ${LANG_SPANISH} "Iniciar qBittorrent." -;LangString inst_requires_64bit ${LANG_ENGLISH} "This installer works only in 64-bit Windows versions." -LangString inst_requires_64bit ${LANG_SPANISH} "Este instalador solo funciona en versiones de 64-bit de Windows." - - -;------------------------------------ -;Uninstaller strings - -;LangString remove_files ${LANG_ENGLISH} "Remove files" -LangString remove_files ${LANG_SPANISH} "Quitar archivos" -;LangString remove_shortcuts ${LANG_ENGLISH} "Remove shortcuts" -LangString remove_shortcuts ${LANG_SPANISH} "Quitar accesos directos" -;LangString remove_associations ${LANG_ENGLISH} "Remove file associations" -LangString remove_associations ${LANG_SPANISH} "Deshacer asociaciones" -;LangString remove_registry ${LANG_ENGLISH} "Remove registry keys" -LangString remove_registry ${LANG_SPANISH} "Eliminar claves del registro" -;LangString remove_conf ${LANG_ENGLISH} "Remove configuration files" -LangString remove_conf ${LANG_SPANISH} "Eliminar archivos de configuración" -;LangString remove_firewall ${LANG_ENGLISH} "Remove Windows Firewall rule" -LangString remove_firewall ${LANG_SPANISH} "Quitar regla del Firewall de Windows" -;LangString remove_firewallinfo ${LANG_ENGLISH} "Removing Windows Firewall rule" -LangString remove_firewallinfo ${LANG_SPANISH} "Quitando regla del firewall de Windows" -;LangString remove_cache ${LANG_ENGLISH} "Remove torrents and cached data" -LangString remove_cache ${LANG_SPANISH} "Eliminar torrents y datos en cache" -;LangString uninst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before uninstalling." -LangString uninst_warning ${LANG_SPANISH} "qBittorrent se está ejecutando. Ciérrelo antes de continuar." -;LangString uninst_tor_warn ${LANG_ENGLISH} "Not removing .torrent association. It is associated with:" -LangString uninst_tor_warn ${LANG_SPANISH} "Manteniendo asociación de archivos .torrent. Estan asociados con:" -;LangString uninst_mag_warn ${LANG_ENGLISH} "Not removing magnet association. It is associated with:" -LangString uninst_mag_warn ${LANG_SPANISH} "Manteniendo asociación de enlaces magnet. Estan asociados con:" diff --git a/dist/windows/installer-translations/spanishinternational.nsi b/dist/windows/installer-translations/spanishinternational.nsi deleted file mode 100644 index ddc05a6ad..000000000 --- a/dist/windows/installer-translations/spanishinternational.nsi +++ /dev/null @@ -1,53 +0,0 @@ -;Installer strings - -;LangString inst_qbt_req ${LANG_ENGLISH} "qBittorrent (required)" -LangString inst_qbt_req ${LANG_SPANISHINTERNATIONAL} "qBittorrent (necesario)" -;LangString inst_dekstop ${LANG_ENGLISH} "Create Desktop Shortcut" -LangString inst_dekstop ${LANG_SPANISHINTERNATIONAL} "Crear un acceso directo en el escritorio" -;LangString inst_startmenu ${LANG_ENGLISH} "Create Start Menu Shortcut" -LangString inst_startmenu ${LANG_SPANISHINTERNATIONAL} "Crear un acceso directo en el menú inicio" -;LangString inst_torrent ${LANG_ENGLISH} "Open .torrent files with qBittorrent" -LangString inst_torrent ${LANG_SPANISHINTERNATIONAL} "Abrir archivos .torrent con qBittorrent" -;LangString inst_magnet ${LANG_ENGLISH} "Open magnet links with qBittorrent" -LangString inst_magnet ${LANG_SPANISHINTERNATIONAL} "Abrir enlaces magnet con qBittorrent" -;LangString inst_firewall ${LANG_ENGLISH} "Add Windows Firewall rule" -LangString inst_firewall ${LANG_SPANISHINTERNATIONAL} "Añadir regla al Firewall de Windows" -;LangString inst_firewallinfo ${LANG_ENGLISH} "Adding Windows Firewall rule" -LangString inst_firewallinfo ${LANG_SPANISHINTERNATIONAL} "Añadiendo regla al Firewall de Windows" -;LangString inst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before installing." -LangString inst_warning ${LANG_SPANISHINTERNATIONAL} "qBittorrent se está ejecutando. Ciérrelo antes de continuar." -;LangString inst_uninstall_question ${LANG_ENGLISH} "A previous installation was detected. It will be uninstalled without deleting user settings." -LangString inst_uninstall_question ${LANG_SPANISHINTERNATIONAL} "Se detectó una instalación anterior. Será desinstalada sin eliminar la configuración del usuario." -;LangString inst_unist ${LANG_ENGLISH} "Uninstalling previous version." -LangString inst_unist ${LANG_SPANISHINTERNATIONAL} "Desinstalando la versión anterior." -;LangString launch_qbt ${LANG_ENGLISH} "Launch qBittorrent." -LangString launch_qbt ${LANG_SPANISHINTERNATIONAL} "Iniciar qBittorrent." -;LangString inst_requires_64bit ${LANG_ENGLISH} "This installer works only in 64-bit Windows versions." -LangString inst_requires_64bit ${LANG_SPANISHINTERNATIONAL} "Este instalador solo funciona en versiones de 64-bit de Windows." - - -;------------------------------------ -;Uninstaller strings - -;LangString remove_files ${LANG_ENGLISH} "Remove files" -LangString remove_files ${LANG_SPANISHINTERNATIONAL} "Quitar archivos" -;LangString remove_shortcuts ${LANG_ENGLISH} "Remove shortcuts" -LangString remove_shortcuts ${LANG_SPANISHINTERNATIONAL} "Quitar accesos directos" -;LangString remove_associations ${LANG_ENGLISH} "Remove file associations" -LangString remove_associations ${LANG_SPANISHINTERNATIONAL} "Deshacer asociaciones" -;LangString remove_registry ${LANG_ENGLISH} "Remove registry keys" -LangString remove_registry ${LANG_SPANISHINTERNATIONAL} "Eliminar claves del registro" -;LangString remove_conf ${LANG_ENGLISH} "Remove configuration files" -LangString remove_conf ${LANG_SPANISHINTERNATIONAL} "Eliminar archivos de configuración" -;LangString remove_firewall ${LANG_ENGLISH} "Remove Windows Firewall rule" -LangString remove_firewall ${LANG_SPANISHINTERNATIONAL} "Quitar regla del Firewall de Windows" -;LangString remove_firewallinfo ${LANG_ENGLISH} "Removing Windows Firewall rule" -LangString remove_firewallinfo ${LANG_SPANISHINTERNATIONAL} "Quitando regla del firewall de Windows" -;LangString remove_cache ${LANG_ENGLISH} "Remove torrents and cached data" -LangString remove_cache ${LANG_SPANISHINTERNATIONAL} "Eliminar torrents y datos en cache" -;LangString uninst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before uninstalling." -LangString uninst_warning ${LANG_SPANISHINTERNATIONAL} "qBittorrent se está ejecutando. Ciérrelo antes de continuar." -;LangString uninst_tor_warn ${LANG_ENGLISH} "Not removing .torrent association. It is associated with:" -LangString uninst_tor_warn ${LANG_SPANISHINTERNATIONAL} "Manteniendo asociación de archivos .torrent. Estan asociados con:" -;LangString uninst_mag_warn ${LANG_ENGLISH} "Not removing magnet association. It is associated with:" -LangString uninst_mag_warn ${LANG_SPANISHINTERNATIONAL} "Manteniendo asociación de enlaces magnet. Estan asociados con:" diff --git a/dist/windows/installer-translations/swedish.nsi b/dist/windows/installer-translations/swedish.nsi deleted file mode 100644 index 1be763f98..000000000 --- a/dist/windows/installer-translations/swedish.nsi +++ /dev/null @@ -1,53 +0,0 @@ -;Installer strings - -;LangString inst_qbt_req ${LANG_ENGLISH} "qBittorrent (required)" -LangString inst_qbt_req ${LANG_SWEDISH} "qBittorrent (required)" -;LangString inst_dekstop ${LANG_ENGLISH} "Create Desktop Shortcut" -LangString inst_dekstop ${LANG_SWEDISH} "Create Desktop Shortcut" -;LangString inst_startmenu ${LANG_ENGLISH} "Create Start Menu Shortcut" -LangString inst_startmenu ${LANG_SWEDISH} "Create Start Menu Shortcut" -;LangString inst_torrent ${LANG_ENGLISH} "Open .torrent files with qBittorrent" -LangString inst_torrent ${LANG_SWEDISH} "Open .torrent files with qBittorrent" -;LangString inst_magnet ${LANG_ENGLISH} "Open magnet links with qBittorrent" -LangString inst_magnet ${LANG_SWEDISH} "Open magnet links with qBittorrent" -;LangString inst_firewall ${LANG_ENGLISH} "Add Windows Firewall rule" -LangString inst_firewall ${LANG_SWEDISH} "Add Windows Firewall rule" -;LangString inst_firewallinfo ${LANG_ENGLISH} "Adding Windows Firewall rule" -LangString inst_firewallinfo ${LANG_SWEDISH} "Adding Windows Firewall rule" -;LangString inst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before installing." -LangString inst_warning ${LANG_SWEDISH} "qBittorrent is running. Please close the application before installing." -;LangString inst_uninstall_question ${LANG_ENGLISH} "A previous installation was detected. It will be uninstalled without deleting user settings." -LangString inst_uninstall_question ${LANG_SWEDISH} "A previous installation was detected. It will be uninstalled without deleting user settings." -;LangString inst_unist ${LANG_ENGLISH} "Uninstalling previous version." -LangString inst_unist ${LANG_SWEDISH} "Uninstalling previous version." -;LangString launch_qbt ${LANG_ENGLISH} "Launch qBittorrent." -LangString launch_qbt ${LANG_SWEDISH} "Launch qBittorrent." -;LangString inst_requires_64bit ${LANG_ENGLISH} "This installer works only in 64-bit Windows versions." -LangString inst_requires_64bit ${LANG_SWEDISH} "This installer works only in 64-bit Windows versions." - - -;------------------------------------ -;Uninstaller strings - -;LangString remove_files ${LANG_ENGLISH} "Remove files" -LangString remove_files ${LANG_SWEDISH} "Remove files" -;LangString remove_shortcuts ${LANG_ENGLISH} "Remove shortcuts" -LangString remove_shortcuts ${LANG_SWEDISH} "Remove shortcuts" -;LangString remove_associations ${LANG_ENGLISH} "Remove file associations" -LangString remove_associations ${LANG_SWEDISH} "Remove file associations" -;LangString remove_registry ${LANG_ENGLISH} "Remove registry keys" -LangString remove_registry ${LANG_SWEDISH} "Remove registry keys" -;LangString remove_conf ${LANG_ENGLISH} "Remove configuration files" -LangString remove_conf ${LANG_SWEDISH} "Remove configuration files" -;LangString remove_firewall ${LANG_ENGLISH} "Remove Windows Firewall rule" -LangString remove_firewall ${LANG_SWEDISH} "Remove Windows Firewall rule" -;LangString remove_firewallinfo ${LANG_ENGLISH} "Removing Windows Firewall rule" -LangString remove_firewallinfo ${LANG_SWEDISH} "Removing Windows Firewall rule" -;LangString remove_cache ${LANG_ENGLISH} "Remove torrents and cached data" -LangString remove_cache ${LANG_SWEDISH} "Remove torrents and cached data" -;LangString uninst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before uninstalling." -LangString uninst_warning ${LANG_SWEDISH} "qBittorrent is running. Please close the application before uninstalling." -;LangString uninst_tor_warn ${LANG_ENGLISH} "Not removing .torrent association. It is associated with:" -LangString uninst_tor_warn ${LANG_SWEDISH} "Not removing .torrent association. It is associated with:" -;LangString uninst_mag_warn ${LANG_ENGLISH} "Not removing magnet association. It is associated with:" -LangString uninst_mag_warn ${LANG_SWEDISH} "Not removing magnet association. It is associated with:" diff --git a/dist/windows/installer-translations/thai.nsi b/dist/windows/installer-translations/thai.nsi deleted file mode 100644 index 0b42d9d8b..000000000 --- a/dist/windows/installer-translations/thai.nsi +++ /dev/null @@ -1,53 +0,0 @@ -;Installer strings - -;LangString inst_qbt_req ${LANG_ENGLISH} "qBittorrent (required)" -LangString inst_qbt_req ${LANG_THAI} "qBittorrent (required)" -;LangString inst_dekstop ${LANG_ENGLISH} "Create Desktop Shortcut" -LangString inst_dekstop ${LANG_THAI} "Create Desktop Shortcut" -;LangString inst_startmenu ${LANG_ENGLISH} "Create Start Menu Shortcut" -LangString inst_startmenu ${LANG_THAI} "Create Start Menu Shortcut" -;LangString inst_torrent ${LANG_ENGLISH} "Open .torrent files with qBittorrent" -LangString inst_torrent ${LANG_THAI} "Open .torrent files with qBittorrent" -;LangString inst_magnet ${LANG_ENGLISH} "Open magnet links with qBittorrent" -LangString inst_magnet ${LANG_THAI} "Open magnet links with qBittorrent" -;LangString inst_firewall ${LANG_ENGLISH} "Add Windows Firewall rule" -LangString inst_firewall ${LANG_THAI} "Add Windows Firewall rule" -;LangString inst_firewallinfo ${LANG_ENGLISH} "Adding Windows Firewall rule" -LangString inst_firewallinfo ${LANG_THAI} "Adding Windows Firewall rule" -;LangString inst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before installing." -LangString inst_warning ${LANG_THAI} "qBittorrent is running. Please close the application before installing." -;LangString inst_uninstall_question ${LANG_ENGLISH} "A previous installation was detected. It will be uninstalled without deleting user settings." -LangString inst_uninstall_question ${LANG_THAI} "A previous installation was detected. It will be uninstalled without deleting user settings." -;LangString inst_unist ${LANG_ENGLISH} "Uninstalling previous version." -LangString inst_unist ${LANG_THAI} "Uninstalling previous version." -;LangString launch_qbt ${LANG_ENGLISH} "Launch qBittorrent." -LangString launch_qbt ${LANG_THAI} "Launch qBittorrent." -;LangString inst_requires_64bit ${LANG_ENGLISH} "This installer works only in 64-bit Windows versions." -LangString inst_requires_64bit ${LANG_THAI} "This installer works only in 64-bit Windows versions." - - -;------------------------------------ -;Uninstaller strings - -;LangString remove_files ${LANG_ENGLISH} "Remove files" -LangString remove_files ${LANG_THAI} "Remove files" -;LangString remove_shortcuts ${LANG_ENGLISH} "Remove shortcuts" -LangString remove_shortcuts ${LANG_THAI} "Remove shortcuts" -;LangString remove_associations ${LANG_ENGLISH} "Remove file associations" -LangString remove_associations ${LANG_THAI} "Remove file associations" -;LangString remove_registry ${LANG_ENGLISH} "Remove registry keys" -LangString remove_registry ${LANG_THAI} "Remove registry keys" -;LangString remove_conf ${LANG_ENGLISH} "Remove configuration files" -LangString remove_conf ${LANG_THAI} "Remove configuration files" -;LangString remove_firewall ${LANG_ENGLISH} "Remove Windows Firewall rule" -LangString remove_firewall ${LANG_THAI} "Remove Windows Firewall rule" -;LangString remove_firewallinfo ${LANG_ENGLISH} "Removing Windows Firewall rule" -LangString remove_firewallinfo ${LANG_THAI} "Removing Windows Firewall rule" -;LangString remove_cache ${LANG_ENGLISH} "Remove torrents and cached data" -LangString remove_cache ${LANG_THAI} "Remove torrents and cached data" -;LangString uninst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before uninstalling." -LangString uninst_warning ${LANG_THAI} "qBittorrent is running. Please close the application before uninstalling." -;LangString uninst_tor_warn ${LANG_ENGLISH} "Not removing .torrent association. It is associated with:" -LangString uninst_tor_warn ${LANG_THAI} "Not removing .torrent association. It is associated with:" -;LangString uninst_mag_warn ${LANG_ENGLISH} "Not removing magnet association. It is associated with:" -LangString uninst_mag_warn ${LANG_THAI} "Not removing magnet association. It is associated with:" diff --git a/dist/windows/installer-translations/tradchinese.nsi b/dist/windows/installer-translations/tradchinese.nsi deleted file mode 100644 index fd10a6dab..000000000 --- a/dist/windows/installer-translations/tradchinese.nsi +++ /dev/null @@ -1,53 +0,0 @@ -;Installer strings - -;LangString inst_qbt_req ${LANG_ENGLISH} "qBittorrent (required)" -LangString inst_qbt_req ${LANG_TRADCHINESE} "qBittorrent (必要)" -;LangString inst_dekstop ${LANG_ENGLISH} "Create Desktop Shortcut" -LangString inst_dekstop ${LANG_TRADCHINESE} "建立桌面捷徑" -;LangString inst_startmenu ${LANG_ENGLISH} "Create Start Menu Shortcut" -LangString inst_startmenu ${LANG_TRADCHINESE} "建立開始功能表捷徑" -;LangString inst_torrent ${LANG_ENGLISH} "Open .torrent files with qBittorrent" -LangString inst_torrent ${LANG_TRADCHINESE} "使用 qBittorrent 開啟 .torrent 檔案" -;LangString inst_magnet ${LANG_ENGLISH} "Open magnet links with qBittorrent" -LangString inst_magnet ${LANG_TRADCHINESE} "使用 qBittorrent 開啟 magnet 連結" -;LangString inst_firewall ${LANG_ENGLISH} "Add Windows Firewall rule" -LangString inst_firewall ${LANG_TRADCHINESE} "建立 Windows 防火牆規則" -;LangString inst_firewallinfo ${LANG_ENGLISH} "Adding Windows Firewall rule" -LangString inst_firewallinfo ${LANG_TRADCHINESE} "正在建立 Windows 防火牆規則" -;LangString inst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before installing." -LangString inst_warning ${LANG_TRADCHINESE} "qBittorrent 正在執行中,請先關閉後再進行安裝。" -;LangString inst_uninstall_question ${LANG_ENGLISH} "A previous installation was detected. It will be uninstalled without deleting user settings." -LangString inst_uninstall_question ${LANG_TRADCHINESE} "A previous installation was detected. It will be uninstalled without deleting user settings." -;LangString inst_unist ${LANG_ENGLISH} "Uninstalling previous version." -LangString inst_unist ${LANG_TRADCHINESE} "正在移除先前版本" -;LangString launch_qbt ${LANG_ENGLISH} "Launch qBittorrent." -LangString launch_qbt ${LANG_TRADCHINESE} "啟動 qBittorrent" -;LangString inst_requires_64bit ${LANG_ENGLISH} "This installer works only in 64-bit Windows versions." -LangString inst_requires_64bit ${LANG_TRADCHINESE} "This installer works only in 64-bit Windows versions." - - -;------------------------------------ -;Uninstaller strings - -;LangString remove_files ${LANG_ENGLISH} "Remove files" -LangString remove_files ${LANG_TRADCHINESE} "移除程式" -;LangString remove_shortcuts ${LANG_ENGLISH} "Remove shortcuts" -LangString remove_shortcuts ${LANG_TRADCHINESE} "移除捷徑" -;LangString remove_associations ${LANG_ENGLISH} "Remove file associations" -LangString remove_associations ${LANG_TRADCHINESE} "移除檔案關聯" -;LangString remove_registry ${LANG_ENGLISH} "Remove registry keys" -LangString remove_registry ${LANG_TRADCHINESE} "移除登錄檔機碼" -;LangString remove_conf ${LANG_ENGLISH} "Remove configuration files" -LangString remove_conf ${LANG_TRADCHINESE} "移除程式設定" -;LangString remove_firewall ${LANG_ENGLISH} "Remove Windows Firewall rule" -LangString remove_firewall ${LANG_TRADCHINESE} "移除 Windows 防火牆規則" -;LangString remove_firewallinfo ${LANG_ENGLISH} "Removing Windows Firewall rule" -LangString remove_firewallinfo ${LANG_TRADCHINESE} "正在移除 Windows 防火牆規則" -;LangString remove_cache ${LANG_ENGLISH} "Remove torrents and cached data" -LangString remove_cache ${LANG_TRADCHINESE} "移除 torrent 檔案及快取" -;LangString uninst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before uninstalling." -LangString uninst_warning ${LANG_TRADCHINESE} "qBittorrent 正在執行中,請先關閉後再進行移除。" -;LangString uninst_tor_warn ${LANG_ENGLISH} "Not removing .torrent association. It is associated with:" -LangString uninst_tor_warn ${LANG_TRADCHINESE} "無法移除 .torrent 關聯,目前連結於:" -;LangString uninst_mag_warn ${LANG_ENGLISH} "Not removing magnet association. It is associated with:" -LangString uninst_mag_warn ${LANG_TRADCHINESE} "無法移除 magnet 關聯,目前連結於:" diff --git a/dist/windows/installer-translations/turkish.nsi b/dist/windows/installer-translations/turkish.nsi deleted file mode 100644 index 6e87d5065..000000000 --- a/dist/windows/installer-translations/turkish.nsi +++ /dev/null @@ -1,53 +0,0 @@ -;Installer strings - -;LangString inst_qbt_req ${LANG_ENGLISH} "qBittorrent (required)" -LangString inst_qbt_req ${LANG_TURKISH} "qBittorrent (zorunlu)" -;LangString inst_dekstop ${LANG_ENGLISH} "Create Desktop Shortcut" -LangString inst_dekstop ${LANG_TURKISH} "Masaüstü Kısayolu oluştur" -;LangString inst_startmenu ${LANG_ENGLISH} "Create Start Menu Shortcut" -LangString inst_startmenu ${LANG_TURKISH} "Başlangıç Menüsü Kısayolu oluştur" -;LangString inst_torrent ${LANG_ENGLISH} "Open .torrent files with qBittorrent" -LangString inst_torrent ${LANG_TURKISH} ".torrent dosyalarını qBittorrent ile aç" -;LangString inst_magnet ${LANG_ENGLISH} "Open magnet links with qBittorrent" -LangString inst_magnet ${LANG_TURKISH} "Magnet bağlantılarını qBittorrent ile aç" -;LangString inst_firewall ${LANG_ENGLISH} "Add Windows Firewall rule" -LangString inst_firewall ${LANG_TURKISH} "Windows Güvenlik Duvarı kuralı ekle" -;LangString inst_firewallinfo ${LANG_ENGLISH} "Adding Windows Firewall rule" -LangString inst_firewallinfo ${LANG_TURKISH} "Windows Güvenlik Duvarı kuralı ekleniyor" -;LangString inst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before installing." -LangString inst_warning ${LANG_TURKISH} "qBittorrent çalışıyor. Lütfen yüklemeden önce uygulamayı kapatın." -;LangString inst_uninstall_question ${LANG_ENGLISH} "A previous installation was detected. It will be uninstalled without deleting user settings." -LangString inst_uninstall_question ${LANG_TURKISH} "Önceki bir kurulum algılandı. Kullanıcı ayarları silinmeden kaldırılacaktır." -;LangString inst_unist ${LANG_ENGLISH} "Uninstalling previous version." -LangString inst_unist ${LANG_TURKISH} "Önceki sürüm kaldırılıyor." -;LangString launch_qbt ${LANG_ENGLISH} "Launch qBittorrent." -LangString launch_qbt ${LANG_TURKISH} "qBittorrent'i çalıştır." -;LangString inst_requires_64bit ${LANG_ENGLISH} "This installer works only in 64-bit Windows versions." -LangString inst_requires_64bit ${LANG_TURKISH} "Bu yükleyici sadece 64-bit Windows sürümlerinde çalışır." - - -;------------------------------------ -;Uninstaller strings - -;LangString remove_files ${LANG_ENGLISH} "Remove files" -LangString remove_files ${LANG_TURKISH} "Dosyaları kaldır" -;LangString remove_shortcuts ${LANG_ENGLISH} "Remove shortcuts" -LangString remove_shortcuts ${LANG_TURKISH} "Kısayolları kaldır" -;LangString remove_associations ${LANG_ENGLISH} "Remove file associations" -LangString remove_associations ${LANG_TURKISH} "Dosya ilişkilendirmelerini kaldır" -;LangString remove_registry ${LANG_ENGLISH} "Remove registry keys" -LangString remove_registry ${LANG_TURKISH} "Kayıt defteri anahtarlarını kaldır" -;LangString remove_conf ${LANG_ENGLISH} "Remove configuration files" -LangString remove_conf ${LANG_TURKISH} "Yapılandırma dosyalarını kaldır" -;LangString remove_firewall ${LANG_ENGLISH} "Remove Windows Firewall rule" -LangString remove_firewall ${LANG_TURKISH} "Windows Güvenlik Duvarı kuralını kaldır" -;LangString remove_firewallinfo ${LANG_ENGLISH} "Removing Windows Firewall rule" -LangString remove_firewallinfo ${LANG_TURKISH} "Windows Güvenlik Duvarı kuralı kaldırılıyor" -;LangString remove_cache ${LANG_ENGLISH} "Remove torrents and cached data" -LangString remove_cache ${LANG_TURKISH} "Torrentleri ve önbelleklenen verileri kaldır" -;LangString uninst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before uninstalling." -LangString uninst_warning ${LANG_TURKISH} "qBittorrent çalışıyor. Lütfen kaldırmadan önce uygulamayı kapatın." -;LangString uninst_tor_warn ${LANG_ENGLISH} "Not removing .torrent association. It is associated with:" -LangString uninst_tor_warn ${LANG_TURKISH} ".torrent ilişkilendirmesi kaldırılmıyor. Şununla ilişkilendirildi:" -;LangString uninst_mag_warn ${LANG_ENGLISH} "Not removing magnet association. It is associated with:" -LangString uninst_mag_warn ${LANG_TURKISH} "Magnet ilişkilendirmesi kaldırılmıyor. Şununla ilişkilendirildi:" diff --git a/dist/windows/installer-translations/ukrainian.nsi b/dist/windows/installer-translations/ukrainian.nsi deleted file mode 100644 index 3aa090690..000000000 --- a/dist/windows/installer-translations/ukrainian.nsi +++ /dev/null @@ -1,53 +0,0 @@ -;Installer strings - -;LangString inst_qbt_req ${LANG_ENGLISH} "qBittorrent (required)" -LangString inst_qbt_req ${LANG_UKRAINIAN} "qBittorrent (необхідний)" -;LangString inst_dekstop ${LANG_ENGLISH} "Create Desktop Shortcut" -LangString inst_dekstop ${LANG_UKRAINIAN} "Створити ярлик на стільниці" -;LangString inst_startmenu ${LANG_ENGLISH} "Create Start Menu Shortcut" -LangString inst_startmenu ${LANG_UKRAINIAN} "Створити ярлик в меню Пуск" -;LangString inst_torrent ${LANG_ENGLISH} "Open .torrent files with qBittorrent" -LangString inst_torrent ${LANG_UKRAINIAN} "Відкривати .torrent файли за допомогою qBittorrent" -;LangString inst_magnet ${LANG_ENGLISH} "Open magnet links with qBittorrent" -LangString inst_magnet ${LANG_UKRAINIAN} "Відкривати посилання magnet за допомогою qBittorrent" -;LangString inst_firewall ${LANG_ENGLISH} "Add Windows Firewall rule" -LangString inst_firewall ${LANG_UKRAINIAN} "Додати правило в Windows брандмауер" -;LangString inst_firewallinfo ${LANG_ENGLISH} "Adding Windows Firewall rule" -LangString inst_firewallinfo ${LANG_UKRAINIAN} "Додаємо правило до брандмауера" -;LangString inst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before installing." -LangString inst_warning ${LANG_UKRAINIAN} "qBittorrent вже виконується. Будь ласка, закрийте застосунок перед запуском інсталятору." -;LangString inst_uninstall_question ${LANG_ENGLISH} "A previous installation was detected. It will be uninstalled without deleting user settings." -LangString inst_uninstall_question ${LANG_UKRAINIAN} "Виявлено попередню інсталяцію. Її буде видалено за виключенням користувацьких налаштувань." -;LangString inst_unist ${LANG_ENGLISH} "Uninstalling previous version." -LangString inst_unist ${LANG_UKRAINIAN} "Видалення попередньої версії." -;LangString launch_qbt ${LANG_ENGLISH} "Launch qBittorrent." -LangString launch_qbt ${LANG_UKRAINIAN} "Запустити qBittorrent." -;LangString inst_requires_64bit ${LANG_ENGLISH} "This installer works only in 64-bit Windows versions." -LangString inst_requires_64bit ${LANG_UKRAINIAN} "Ця програма установки працює тільки в 64-розрядних версіях Windows." - - -;------------------------------------ -;Uninstaller strings - -;LangString remove_files ${LANG_ENGLISH} "Remove files" -LangString remove_files ${LANG_UKRAINIAN} "Видалити файли" -;LangString remove_shortcuts ${LANG_ENGLISH} "Remove shortcuts" -LangString remove_shortcuts ${LANG_UKRAINIAN} "Видалити ярлики" -;LangString remove_associations ${LANG_ENGLISH} "Remove file associations" -LangString remove_associations ${LANG_UKRAINIAN} "Видалити файлові асоціації" -;LangString remove_registry ${LANG_ENGLISH} "Remove registry keys" -LangString remove_registry ${LANG_UKRAINIAN} "Видалити ключі реєстру" -;LangString remove_conf ${LANG_ENGLISH} "Remove configuration files" -LangString remove_conf ${LANG_UKRAINIAN} "Видалити користувацькі налаштування" -;LangString remove_firewall ${LANG_ENGLISH} "Remove Windows Firewall rule" -LangString remove_firewall ${LANG_UKRAINIAN} "Видалити правило брандмауера Windows" -;LangString remove_firewallinfo ${LANG_ENGLISH} "Removing Windows Firewall rule" -LangString remove_firewallinfo ${LANG_UKRAINIAN} "Видаляємо правило брандмауера Windows" -;LangString remove_cache ${LANG_ENGLISH} "Remove torrents and cached data" -LangString remove_cache ${LANG_UKRAINIAN} "Видалити торренти та кешовані дані" -;LangString uninst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before uninstalling." -LangString uninst_warning ${LANG_UKRAINIAN} "qBittorrent виконується. Будь ласка, закрийте застосунок перед деінсталляцією." -;LangString uninst_tor_warn ${LANG_ENGLISH} "Not removing .torrent association. It is associated with:" -LangString uninst_tor_warn ${LANG_UKRAINIAN} "Не видаляємо асоціацію .torrent файлів. Вони асоційовані з:" -;LangString uninst_mag_warn ${LANG_ENGLISH} "Not removing magnet association. It is associated with:" -LangString uninst_mag_warn ${LANG_UKRAINIAN} "Не видаляємо асоціацію magnet-посилань. Вони асоційовані з:" diff --git a/dist/windows/installer-translations/uzbek.nsi b/dist/windows/installer-translations/uzbek.nsi deleted file mode 100644 index 807bf88b6..000000000 --- a/dist/windows/installer-translations/uzbek.nsi +++ /dev/null @@ -1,53 +0,0 @@ -;Installer strings - -;LangString inst_qbt_req ${LANG_ENGLISH} "qBittorrent (required)" -LangString inst_qbt_req ${LANG_UZBEK} "qBittorrent (required)" -;LangString inst_dekstop ${LANG_ENGLISH} "Create Desktop Shortcut" -LangString inst_dekstop ${LANG_UZBEK} "Create Desktop Shortcut" -;LangString inst_startmenu ${LANG_ENGLISH} "Create Start Menu Shortcut" -LangString inst_startmenu ${LANG_UZBEK} "Create Start Menu Shortcut" -;LangString inst_torrent ${LANG_ENGLISH} "Open .torrent files with qBittorrent" -LangString inst_torrent ${LANG_UZBEK} "Open .torrent files with qBittorrent" -;LangString inst_magnet ${LANG_ENGLISH} "Open magnet links with qBittorrent" -LangString inst_magnet ${LANG_UZBEK} "Open magnet links with qBittorrent" -;LangString inst_firewall ${LANG_ENGLISH} "Add Windows Firewall rule" -LangString inst_firewall ${LANG_UZBEK} "Add Windows Firewall rule" -;LangString inst_firewallinfo ${LANG_ENGLISH} "Adding Windows Firewall rule" -LangString inst_firewallinfo ${LANG_UZBEK} "Adding Windows Firewall rule" -;LangString inst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before installing." -LangString inst_warning ${LANG_UZBEK} "qBittorrent is running. Please close the application before installing." -;LangString inst_uninstall_question ${LANG_ENGLISH} "A previous installation was detected. It will be uninstalled without deleting user settings." -LangString inst_uninstall_question ${LANG_UZBEK} "A previous installation was detected. It will be uninstalled without deleting user settings." -;LangString inst_unist ${LANG_ENGLISH} "Uninstalling previous version." -LangString inst_unist ${LANG_UZBEK} "Uninstalling previous version." -;LangString launch_qbt ${LANG_ENGLISH} "Launch qBittorrent." -LangString launch_qbt ${LANG_UZBEK} "Launch qBittorrent." -;LangString inst_requires_64bit ${LANG_ENGLISH} "This installer works only in 64-bit Windows versions." -LangString inst_requires_64bit ${LANG_UZBEK} "This installer works only in 64-bit Windows versions." - - -;------------------------------------ -;Uninstaller strings - -;LangString remove_files ${LANG_ENGLISH} "Remove files" -LangString remove_files ${LANG_UZBEK} "Remove files" -;LangString remove_shortcuts ${LANG_ENGLISH} "Remove shortcuts" -LangString remove_shortcuts ${LANG_UZBEK} "Remove shortcuts" -;LangString remove_associations ${LANG_ENGLISH} "Remove file associations" -LangString remove_associations ${LANG_UZBEK} "Remove file associations" -;LangString remove_registry ${LANG_ENGLISH} "Remove registry keys" -LangString remove_registry ${LANG_UZBEK} "Remove registry keys" -;LangString remove_conf ${LANG_ENGLISH} "Remove configuration files" -LangString remove_conf ${LANG_UZBEK} "Remove configuration files" -;LangString remove_firewall ${LANG_ENGLISH} "Remove Windows Firewall rule" -LangString remove_firewall ${LANG_UZBEK} "Remove Windows Firewall rule" -;LangString remove_firewallinfo ${LANG_ENGLISH} "Removing Windows Firewall rule" -LangString remove_firewallinfo ${LANG_UZBEK} "Removing Windows Firewall rule" -;LangString remove_cache ${LANG_ENGLISH} "Remove torrents and cached data" -LangString remove_cache ${LANG_UZBEK} "Remove torrents and cached data" -;LangString uninst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before uninstalling." -LangString uninst_warning ${LANG_UZBEK} "qBittorrent is running. Please close the application before uninstalling." -;LangString uninst_tor_warn ${LANG_ENGLISH} "Not removing .torrent association. It is associated with:" -LangString uninst_tor_warn ${LANG_UZBEK} "Not removing .torrent association. It is associated with:" -;LangString uninst_mag_warn ${LANG_ENGLISH} "Not removing magnet association. It is associated with:" -LangString uninst_mag_warn ${LANG_UZBEK} "Not removing magnet association. It is associated with:" diff --git a/dist/windows/installer-translations/welsh.nsi b/dist/windows/installer-translations/welsh.nsi deleted file mode 100644 index 3b09b1b60..000000000 --- a/dist/windows/installer-translations/welsh.nsi +++ /dev/null @@ -1,53 +0,0 @@ -;Installer strings - -;LangString inst_qbt_req ${LANG_ENGLISH} "qBittorrent (required)" -LangString inst_qbt_req ${LANG_WELSH} "qBittorrent (required)" -;LangString inst_dekstop ${LANG_ENGLISH} "Create Desktop Shortcut" -LangString inst_dekstop ${LANG_WELSH} "Create Desktop Shortcut" -;LangString inst_startmenu ${LANG_ENGLISH} "Create Start Menu Shortcut" -LangString inst_startmenu ${LANG_WELSH} "Create Start Menu Shortcut" -;LangString inst_torrent ${LANG_ENGLISH} "Open .torrent files with qBittorrent" -LangString inst_torrent ${LANG_WELSH} "Open .torrent files with qBittorrent" -;LangString inst_magnet ${LANG_ENGLISH} "Open magnet links with qBittorrent" -LangString inst_magnet ${LANG_WELSH} "Open magnet links with qBittorrent" -;LangString inst_firewall ${LANG_ENGLISH} "Add Windows Firewall rule" -LangString inst_firewall ${LANG_WELSH} "Add Windows Firewall rule" -;LangString inst_firewallinfo ${LANG_ENGLISH} "Adding Windows Firewall rule" -LangString inst_firewallinfo ${LANG_WELSH} "Adding Windows Firewall rule" -;LangString inst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before installing." -LangString inst_warning ${LANG_WELSH} "qBittorrent is running. Please close the application before installing." -;LangString inst_uninstall_question ${LANG_ENGLISH} "A previous installation was detected. It will be uninstalled without deleting user settings." -LangString inst_uninstall_question ${LANG_WELSH} "A previous installation was detected. It will be uninstalled without deleting user settings." -;LangString inst_unist ${LANG_ENGLISH} "Uninstalling previous version." -LangString inst_unist ${LANG_WELSH} "Uninstalling previous version." -;LangString launch_qbt ${LANG_ENGLISH} "Launch qBittorrent." -LangString launch_qbt ${LANG_WELSH} "Launch qBittorrent." -;LangString inst_requires_64bit ${LANG_ENGLISH} "This installer works only in 64-bit Windows versions." -LangString inst_requires_64bit ${LANG_WELSH} "This installer works only in 64-bit Windows versions." - - -;------------------------------------ -;Uninstaller strings - -;LangString remove_files ${LANG_ENGLISH} "Remove files" -LangString remove_files ${LANG_WELSH} "Remove files" -;LangString remove_shortcuts ${LANG_ENGLISH} "Remove shortcuts" -LangString remove_shortcuts ${LANG_WELSH} "Remove shortcuts" -;LangString remove_associations ${LANG_ENGLISH} "Remove file associations" -LangString remove_associations ${LANG_WELSH} "Remove file associations" -;LangString remove_registry ${LANG_ENGLISH} "Remove registry keys" -LangString remove_registry ${LANG_WELSH} "Remove registry keys" -;LangString remove_conf ${LANG_ENGLISH} "Remove configuration files" -LangString remove_conf ${LANG_WELSH} "Remove configuration files" -;LangString remove_firewall ${LANG_ENGLISH} "Remove Windows Firewall rule" -LangString remove_firewall ${LANG_WELSH} "Remove Windows Firewall rule" -;LangString remove_firewallinfo ${LANG_ENGLISH} "Removing Windows Firewall rule" -LangString remove_firewallinfo ${LANG_WELSH} "Removing Windows Firewall rule" -;LangString remove_cache ${LANG_ENGLISH} "Remove torrents and cached data" -LangString remove_cache ${LANG_WELSH} "Remove torrents and cached data" -;LangString uninst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before uninstalling." -LangString uninst_warning ${LANG_WELSH} "qBittorrent is running. Please close the application before uninstalling." -;LangString uninst_tor_warn ${LANG_ENGLISH} "Not removing .torrent association. It is associated with:" -LangString uninst_tor_warn ${LANG_WELSH} "Not removing .torrent association. It is associated with:" -;LangString uninst_mag_warn ${LANG_ENGLISH} "Not removing magnet association. It is associated with:" -LangString uninst_mag_warn ${LANG_WELSH} "Not removing magnet association. It is associated with:" diff --git a/dist/windows/installer.nsi b/dist/windows/installer.nsi deleted file mode 100644 index 2651112e4..000000000 --- a/dist/windows/installer.nsi +++ /dev/null @@ -1,247 +0,0 @@ -Var uninstallerPath - -Section "-hidden" - - ;Search if qBittorrent is already installed. - FindFirst $0 $1 "$uninstallerPath\uninst.exe" - FindClose $0 - StrCmp $1 "" done - - ;Run the uninstaller of the previous install. - DetailPrint $(inst_unist) - ExecWait '"$uninstallerPath\uninst.exe" /S _?=$uninstallerPath' - Delete "$uninstallerPath\uninst.exe" - RMDir "$uninstallerPath" - - done: - -SectionEnd - - -Section $(inst_qbt_req) ;"qBittorrent (required)" - - SectionIn RO - - ; Set output path to the installation directory. - SetOutPath $INSTDIR - - ;Create 'translations' directory - CreateDirectory $INSTDIR\translations - - ; Put file there - File "qbittorrent.exe" - File "qbittorrent.pdb" - File "qt.conf" - File /oname=translations\qt_ar.qm "translations\qt_ar.qm" - File /oname=translations\qt_bg.qm "translations\qt_bg.qm" - File /oname=translations\qt_ca.qm "translations\qt_ca.qm" - File /oname=translations\qt_cs.qm "translations\qt_cs.qm" - File /oname=translations\qt_da.qm "translations\qt_da.qm" - File /oname=translations\qt_de.qm "translations\qt_de.qm" - File /oname=translations\qt_es.qm "translations\qt_es.qm" - File /oname=translations\qt_eu.qm "translations\qt_eu.qm" - File /oname=translations\qt_fa.qm "translations\qt_fa.qm" - File /oname=translations\qt_fi.qm "translations\qt_fi.qm" - File /oname=translations\qt_fr.qm "translations\qt_fr.qm" - File /oname=translations\qt_gl.qm "translations\qt_gl.qm" - File /oname=translations\qt_he.qm "translations\qt_he.qm" - File /oname=translations\qt_hu.qm "translations\qt_hu.qm" - File /oname=translations\qt_it.qm "translations\qt_it.qm" - File /oname=translations\qt_ja.qm "translations\qt_ja.qm" - File /oname=translations\qt_ko.qm "translations\qt_ko.qm" - File /oname=translations\qt_lt.qm "translations\qt_lt.qm" - File /oname=translations\qt_nl.qm "translations\qt_nl.qm" - File /oname=translations\qt_pl.qm "translations\qt_pl.qm" - File /oname=translations\qt_pt.qm "translations\qt_pt.qm" - File /oname=translations\qt_pt_BR.qm "translations\qt_pt_BR.qm" - File /oname=translations\qt_ru.qm "translations\qt_ru.qm" - File /oname=translations\qt_sk.qm "translations\qt_sk.qm" - File /oname=translations\qt_sl.qm "translations\qt_sl.qm" - File /oname=translations\qt_sv.qm "translations\qt_sv.qm" - File /oname=translations\qt_tr.qm "translations\qt_tr.qm" - File /oname=translations\qt_uk.qm "translations\qt_uk.qm" - File /oname=translations\qt_zh_CN.qm "translations\qt_zh_CN.qm" - File /oname=translations\qt_zh_TW.qm "translations\qt_zh_TW.qm" - File /oname=translations\qtbase_ca.qm "translations\qtbase_ca.qm" - File /oname=translations\qtbase_cs.qm "translations\qtbase_cs.qm" - File /oname=translations\qtbase_de.qm "translations\qtbase_de.qm" - File /oname=translations\qtbase_fi.qm "translations\qtbase_fi.qm" - File /oname=translations\qtbase_fr.qm "translations\qtbase_fr.qm" - File /oname=translations\qtbase_he.qm "translations\qtbase_he.qm" - File /oname=translations\qtbase_hu.qm "translations\qtbase_hu.qm" - File /oname=translations\qtbase_it.qm "translations\qtbase_it.qm" - File /oname=translations\qtbase_ja.qm "translations\qtbase_ja.qm" - File /oname=translations\qtbase_ko.qm "translations\qtbase_ko.qm" - File /oname=translations\qtbase_lv.qm "translations\qtbase_lv.qm" - File /oname=translations\qtbase_pl.qm "translations\qtbase_pl.qm" - File /oname=translations\qtbase_ru.qm "translations\qtbase_ru.qm" - File /oname=translations\qtbase_sk.qm "translations\qtbase_sk.qm" - File /oname=translations\qtbase_uk.qm "translations\qtbase_uk.qm" - - ; Write the installation path into the registry - WriteRegStr HKLM "Software\qBittorrent" "InstallLocation" "$INSTDIR" - - ; Write the uninstall keys for Windows - WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\qBittorrent" "DisplayName" "qBittorrent ${PROG_VERSION}" - WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\qBittorrent" "UninstallString" '"$INSTDIR\uninst.exe"' - WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\qBittorrent" "DisplayIcon" '"$INSTDIR\qbittorrent.exe",0' - WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\qBittorrent" "Publisher" "The qBittorrent project" - WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\qBittorrent" "URLInfoAbout" "http://www.qbittorrent.org" - WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\qBittorrent" "DisplayVersion" "${PROG_VERSION}" - WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\qBittorrent" "NoModify" 1 - WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\qBittorrent" "NoRepair" 1 - WriteUninstaller "uninst.exe" - ${GetSize} "$INSTDIR" "/S=0K" $0 $1 $2 - IntFmt $0 "0x%08X" $0 - WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\qBittorrent" "EstimatedSize" "$0" - - ; qBittorrent ProgID - WriteRegStr HKLM "Software\Classes\qBittorrent" "" "qBittorrent Torrent File" - WriteRegStr HKLM "Software\Classes\qBittorrent" "FriendlyTypeName" "qBittorrent Torrent File" - WriteRegStr HKLM "Software\Classes\qBittorrent\shell" "" "open" - WriteRegStr HKLM "Software\Classes\qBittorrent\shell\open\command" "" '"$INSTDIR\qbittorrent.exe" "%1"' - WriteRegStr HKLM "Software\Classes\qBittorrent\DefaultIcon" "" '"$INSTDIR\qbittorrent.exe",1' - -SectionEnd - -; Optional section (can be disabled by the user) -Section /o $(inst_dekstop) ;"Create Desktop Shortcut" - - CreateShortCut "$DESKTOP\qBittorrent.lnk" "$INSTDIR\qbittorrent.exe" - -SectionEnd - -Section $(inst_startmenu) ;"Create Start Menu Shortcut" - - CreateDirectory "$SMPROGRAMS\qBittorrent" - CreateShortCut "$SMPROGRAMS\qBittorrent\qBittorrent.lnk" "$INSTDIR\qbittorrent.exe" - CreateShortCut "$SMPROGRAMS\qBittorrent\Uninstall.lnk" "$INSTDIR\uninst.exe" - -SectionEnd - -Section $(inst_torrent) ;"Open .torrent files with qBittorrent" - - ReadRegStr $0 HKLM "Software\Classes\.torrent" "" - - StrCmp $0 "qBittorrent" clear_errors 0 - ;Check if empty string - StrCmp $0 "" clear_errors 0 - ;Write old value to OpenWithProgIds - WriteRegStr HKLM "Software\Classes\.torrent\OpenWithProgIds" $0 "" - - clear_errors: - ClearErrors - - WriteRegStr HKLM "Software\Classes\.torrent" "" "qBittorrent" - WriteRegStr HKLM "Software\Classes\.torrent" "Content Type" "application/x-bittorrent" - - !insertmacro UAC_AsUser_Call Function inst_torrent_user ${UAC_SYNCREGISTERS}|${UAC_SYNCOUTDIR}|${UAC_SYNCINSTDIR} - - System::Call 'Shell32::SHChangeNotify(i ${SHCNE_ASSOCCHANGED}, i ${SHCNF_IDLIST}, i 0, i 0)' - -SectionEnd - -Function inst_torrent_user - - ReadRegStr $0 HKCU "Software\Classes\.torrent" "" - - StrCmp $0 "qBittorrent" clear_errors 0 - ;Check if empty string - StrCmp $0 "" clear_errors 0 - ;Write old value to OpenWithProgIds - WriteRegStr HKCU "Software\Classes\.torrent\OpenWithProgIds" $0 "" - - clear_errors: - ClearErrors - - WriteRegStr HKCU "Software\Classes\.torrent" "" "qBittorrent" - WriteRegStr HKCU "Software\Classes\.torrent" "Content Type" "application/x-bittorrent" - -FunctionEnd - -Section $(inst_magnet) ;"Open magnet links with qBittorrent" - - WriteRegStr HKLM "Software\Classes\magnet" "" "URL:Magnet link" - WriteRegStr HKLM "Software\Classes\magnet" "Content Type" "application/x-magnet" - WriteRegStr HKLM "Software\Classes\magnet" "URL Protocol" "" - WriteRegStr HKLM "Software\Classes\magnet\DefaultIcon" "" '"$INSTDIR\qbittorrent.exe",1' - WriteRegStr HKLM "Software\Classes\magnet\shell" "" "open" - WriteRegStr HKLM "Software\Classes\magnet\shell\open\command" "" '"$INSTDIR\qbittorrent.exe" "%1"' - - !insertmacro UAC_AsUser_Call Function inst_magnet_user ${UAC_SYNCREGISTERS}|${UAC_SYNCOUTDIR}|${UAC_SYNCINSTDIR} - - System::Call 'Shell32::SHChangeNotify(i ${SHCNE_ASSOCCHANGED}, i ${SHCNF_IDLIST}, i 0, i 0)' - -SectionEnd - -Function inst_magnet_user - - WriteRegStr HKCU "Software\Classes\magnet" "" "URL:Magnet link" - WriteRegStr HKCU "Software\Classes\magnet" "Content Type" "application/x-magnet" - WriteRegStr HKCU "Software\Classes\magnet" "URL Protocol" "" - WriteRegStr HKCU "Software\Classes\magnet\DefaultIcon" "" '"$INSTDIR\qbittorrent.exe",1' - WriteRegStr HKCU "Software\Classes\magnet\shell" "" "open" - WriteRegStr HKCU "Software\Classes\magnet\shell\open\command" "" '"$INSTDIR\qbittorrent.exe" "%1"' - -FunctionEnd - -Section $(inst_firewall) - - DetailPrint $(inst_firewallinfo) - nsisFirewallW::AddAuthorizedApplication "$INSTDIR\qbittorrent.exe" "qBittorrent" - -SectionEnd - -;-------------------------------- - -Function .onInit - - !insertmacro Init "installer" - !insertmacro MUI_LANGDLL_DISPLAY - - !ifdef APP64BIT - ${IfNot} ${RunningX64} - MessageBox MB_OK|MB_ICONEXCLAMATION $(inst_requires_64bit) - Abort - ${EndIf} - !endif - - ;Search if qBittorrent is already installed. - FindFirst $0 $1 "$INSTDIR\uninst.exe" - FindClose $0 - StrCmp $1 "" done - - ;Copy old value to var so we can call the correct uninstaller - StrCpy $uninstallerPath $INSTDIR - - ;Inform the user - MessageBox MB_OKCANCEL|MB_ICONINFORMATION $(inst_uninstall_question) /SD IDOK IDOK done - Quit - - done: - -FunctionEnd - -Function check_instance - - check: - FindProcDLL::FindProc "qbittorrent.exe" - StrCmp $R0 "1" 0 notfound - MessageBox MB_RETRYCANCEL|MB_ICONEXCLAMATION $(inst_warning) IDRETRY check IDCANCEL done - - done: - Abort - - notfound: - -FunctionEnd - -Function PageFinishRun - - !insertmacro UAC_AsUser_ExecShell "" "$INSTDIR\qbittorrent.exe" "" "" "" - -FunctionEnd - -Function .onInstSuccess - SetErrorLevel 0 -FunctionEnd diff --git a/dist/windows/nsis plugins/FindProcDLL_mod_by_hnedka.7z b/dist/windows/nsis plugins/FindProcDLL_mod_by_hnedka.7z deleted file mode 100644 index 01cc54de6..000000000 Binary files a/dist/windows/nsis plugins/FindProcDLL_mod_by_hnedka.7z and /dev/null differ diff --git a/dist/windows/nsis plugins/UAC.zip b/dist/windows/nsis plugins/UAC.zip deleted file mode 100644 index 66489aacd..000000000 Binary files a/dist/windows/nsis plugins/UAC.zip and /dev/null differ diff --git a/dist/windows/nsis plugins/nsisFirewall.zip b/dist/windows/nsis plugins/nsisFirewall.zip deleted file mode 100644 index 3d34ac4e7..000000000 Binary files a/dist/windows/nsis plugins/nsisFirewall.zip and /dev/null differ diff --git a/dist/windows/options.nsi b/dist/windows/options.nsi deleted file mode 100644 index e036d0c74..000000000 --- a/dist/windows/options.nsi +++ /dev/null @@ -1,135 +0,0 @@ -Unicode true -ManifestDPIAware true -;Compress the header too -!packhdr "$%TEMP%\exehead.tmp" 'upx.exe -9 --best --ultra-brute "$%TEMP%\exehead.tmp"' - -;Setting the compression -SetCompressor /SOLID LZMA -SetCompressorDictSize 64 -XPStyle on - -;Uncomment when packaging 64bit qbittorrent -;!define APP64BIT - -!include "MUI.nsh" -!include "UAC.nsh" -!include "FileFunc.nsh" -!ifdef APP64BIT -!include "x64.nsh" -!endif - -;For the file association -!define SHCNE_ASSOCCHANGED 0x8000000 -!define SHCNF_IDLIST 0 - -;For special folder detection -!define CSIDL_APPDATA '0x1A' ;Application Data path -!define CSIDL_LOCALAPPDATA '0x1C' ;Local Application Data path - -; Program specific -!define PROG_VERSION "3.4.0" - -!define MUI_FINISHPAGE_RUN -!define MUI_FINISHPAGE_RUN_FUNCTION PageFinishRun -!define MUI_FINISHPAGE_RUN_TEXT $(launch_qbt) - -!ifndef APP64BIT - ; The name of the installer - Name "qBittorrent ${PROG_VERSION}" - - ; The file to write - OutFile "qbittorrent_${PROG_VERSION}_setup.exe" -!else - ; The name of the installer - Name "qBittorrent ${PROG_VERSION} x64" - - ; The file to write - OutFile "qbittorrent_${PROG_VERSION}_x64_setup.exe" -!endif - -;Installer Version Information -VIAddVersionKey "ProductName" "qBittorrent" -VIAddVersionKey "CompanyName" "The qBittorrent project" -VIAddVersionKey "LegalCopyright" "Copyright ©2006-2017 The qBittorrent project" -VIAddVersionKey "FileDescription" "qBittorrent - A Bittorrent Client" -VIAddVersionKey "FileVersion" "${PROG_VERSION}" - -VIProductVersion "${PROG_VERSION}.0" - -; The default installation directory. It changes depending if we install in the 64bit dir or not. -; A caveat of this is if a user has installed a 32bit version and then runs the 64bit installer -; (which in turn launches the 32bit uninstaller first) the value will still point to the 32bit location. -; The user has to manually uninstall the old version and THEN run the 64bit installer -!ifndef APP64BIT - InstallDir $PROGRAMFILES32\qBittorrent -!else - InstallDir $PROGRAMFILES64\qBittorrent -!endif - -; Registry key to check for directory (so if you install again, it will -; overwrite the old one automatically) -InstallDirRegKey HKLM Software\qbittorrent InstallLocation - -; Request application privileges for Windows Vista -RequestExecutionLevel user - -;-------------------------------- -;General Settings -!define MUI_ABORTWARNING -!define MUI_HEADERIMAGE -!define MUI_COMPONENTSPAGE_NODESC -;!define MUI_ICON "qbittorrent.ico" -!define MUI_LICENSEPAGE_CHECKBOX -!define MUI_LANGDLL_ALLLANGUAGES - -;-------------------------------- -;Remember the unistaller/installer language -!define MUI_LANGDLL_REGISTRY_ROOT "HKLM" -!define MUI_LANGDLL_REGISTRY_KEY "Software\qbittorrent" -!define MUI_LANGDLL_REGISTRY_VALUENAME "Installer Language" - -;-------------------------------- -;Installer Pages -!insertmacro MUI_PAGE_WELCOME -!insertmacro MUI_PAGE_LICENSE "license.txt" -!insertmacro MUI_PAGE_COMPONENTS -!define MUI_PAGE_CUSTOMFUNCTION_LEAVE check_instance -!insertmacro MUI_PAGE_DIRECTORY -!insertmacro MUI_PAGE_INSTFILES -!insertmacro MUI_PAGE_FINISH - -;-------------------------------- -;Uninstaller Pages -!insertmacro MUI_UNPAGE_CONFIRM -!define MUI_PAGE_CUSTOMFUNCTION_LEAVE un.check_instance -!insertmacro MUI_UNPAGE_COMPONENTS -!insertmacro MUI_UNPAGE_INSTFILES - -!insertmacro MUI_RESERVEFILE_LANGDLL -ReserveFile "${NSISDIR}\Plugins\x86-unicode\FindProcDLL.dll" -ReserveFile "${NSISDIR}\Plugins\x86-unicode\UAC.dll" - -!macro Init thing -uac_tryagain: -!insertmacro UAC_RunElevated -${Switch} $0 -${Case} 0 - ${IfThen} $1 = 1 ${|} Quit ${|} ;we are the outer process, the inner process has done its work, we are done - ${IfThen} $3 <> 0 ${|} ${Break} ${|} ;we are admin, let the show go on - ${If} $1 = 3 ;RunAs completed successfully, but with a non-admin user - MessageBox mb_YesNo|mb_IconExclamation|mb_TopMost|mb_SetForeground "This ${thing} requires admin privileges, try again" /SD IDNO IDYES uac_tryagain IDNO 0 - ${EndIf} - ;fall-through and die -${Case} 1223 - MessageBox mb_IconStop|mb_TopMost|mb_SetForeground "This ${thing} requires admin privileges, aborting!" - Quit -${Case} 1062 - MessageBox mb_IconStop|mb_TopMost|mb_SetForeground "Logon service not running, aborting!" - Quit -${Default} - MessageBox mb_IconStop|mb_TopMost|mb_SetForeground "Unable to elevate , error $0" - Quit -${EndSwitch} - -SetShellVarContext all -!macroend diff --git a/dist/windows/qbittorrent.nsi b/dist/windows/qbittorrent.nsi deleted file mode 100644 index a5b9509ce..000000000 --- a/dist/windows/qbittorrent.nsi +++ /dev/null @@ -1,4 +0,0 @@ -!include options.nsi -!include translations.nsi -!include installer.nsi -!include uninstaller.nsi diff --git a/dist/windows/qt.conf b/dist/windows/qt.conf deleted file mode 100644 index 5041e27db..000000000 --- a/dist/windows/qt.conf +++ /dev/null @@ -1,5 +0,0 @@ -[Paths] -Translations = translations - -[Platforms] -WindowsArguments = dpiawareness=0 diff --git a/dist/windows/translations.nsi b/dist/windows/translations.nsi deleted file mode 100644 index ef3bd58c6..000000000 --- a/dist/windows/translations.nsi +++ /dev/null @@ -1,123 +0,0 @@ -;Nsis translations - -!insertmacro MUI_LANGUAGE "English" -!insertmacro MUI_LANGUAGE "Afrikaans" -!insertmacro MUI_LANGUAGE "Albanian" -!insertmacro MUI_LANGUAGE "Arabic" -!insertmacro MUI_LANGUAGE "Basque" -!insertmacro MUI_LANGUAGE "Belarusian" -!insertmacro MUI_LANGUAGE "Bosnian" -!insertmacro MUI_LANGUAGE "Breton" -!insertmacro MUI_LANGUAGE "Bulgarian" -!insertmacro MUI_LANGUAGE "Catalan" -!insertmacro MUI_LANGUAGE "Croatian" -!insertmacro MUI_LANGUAGE "Czech" -!insertmacro MUI_LANGUAGE "Danish" -!insertmacro MUI_LANGUAGE "Dutch" -!insertmacro MUI_LANGUAGE "Esperanto" -!insertmacro MUI_LANGUAGE "Estonian" -!insertmacro MUI_LANGUAGE "Farsi" -!insertmacro MUI_LANGUAGE "Finnish" -!insertmacro MUI_LANGUAGE "French" -!insertmacro MUI_LANGUAGE "Galician" -!insertmacro MUI_LANGUAGE "German" -!insertmacro MUI_LANGUAGE "Greek" -!insertmacro MUI_LANGUAGE "Hebrew" -!insertmacro MUI_LANGUAGE "Hungarian" -!insertmacro MUI_LANGUAGE "Icelandic" -!insertmacro MUI_LANGUAGE "Indonesian" -!insertmacro MUI_LANGUAGE "Irish" -!insertmacro MUI_LANGUAGE "Italian" -!insertmacro MUI_LANGUAGE "Japanese" -!insertmacro MUI_LANGUAGE "Korean" -!insertmacro MUI_LANGUAGE "Kurdish" -!insertmacro MUI_LANGUAGE "Latvian" -!insertmacro MUI_LANGUAGE "Lithuanian" -!insertmacro MUI_LANGUAGE "Luxembourgish" -!insertmacro MUI_LANGUAGE "Macedonian" -!insertmacro MUI_LANGUAGE "Malay" -!insertmacro MUI_LANGUAGE "Mongolian" -!insertmacro MUI_LANGUAGE "Norwegian" -!insertmacro MUI_LANGUAGE "NorwegianNynorsk" -!insertmacro MUI_LANGUAGE "Polish" -!insertmacro MUI_LANGUAGE "Portuguese" -!insertmacro MUI_LANGUAGE "PortugueseBR" -!insertmacro MUI_LANGUAGE "Romanian" -!insertmacro MUI_LANGUAGE "Russian" -!insertmacro MUI_LANGUAGE "Serbian" -!insertmacro MUI_LANGUAGE "SerbianLatin" -!insertmacro MUI_LANGUAGE "SimpChinese" -!insertmacro MUI_LANGUAGE "Slovak" -!insertmacro MUI_LANGUAGE "Slovenian" -!insertmacro MUI_LANGUAGE "Spanish" -!insertmacro MUI_LANGUAGE "SpanishInternational" -!insertmacro MUI_LANGUAGE "Swedish" -!insertmacro MUI_LANGUAGE "Thai" -!insertmacro MUI_LANGUAGE "TradChinese" -!insertmacro MUI_LANGUAGE "Turkish" -!insertmacro MUI_LANGUAGE "Ukrainian" -!insertmacro MUI_LANGUAGE "Uzbek" -!insertmacro MUI_LANGUAGE "Welsh" - -;Installer/Uninstaller translations -!addincludedir installer-translations - -;The languages should be in alphabetical order -!include afrikaans.nsi -!include albanian.nsi -!include arabic.nsi -!include basque.nsi -!include belarusian.nsi -!include bosnian.nsi -!include breton.nsi -!include bulgarian.nsi -!include catalan.nsi -!include croatian.nsi -!include czech.nsi -!include danish.nsi -!include dutch.nsi -!include english.nsi -!include esperanto.nsi -!include estonian.nsi -!include farsi.nsi -!include finnish.nsi -!include french.nsi -!include galician.nsi -!include german.nsi -!include greek.nsi -!include hebrew.nsi -!include hungarian.nsi -!include icelandic.nsi -!include indonesian.nsi -!include irish.nsi -!include italian.nsi -!include japanese.nsi -!include korean.nsi -!include kurdish.nsi -!include latvian.nsi -!include lithuanian.nsi -!include luxembourgish.nsi -!include macedonian.nsi -!include malay.nsi -!include mongolian.nsi -!include norwegian.nsi -!include norwegiannynorsk.nsi -!include polish.nsi -!include portuguese.nsi -!include portuguesebr.nsi -!include romanian.nsi -!include russian.nsi -!include serbian.nsi -!include serbianlatin.nsi -!include simpchinese.nsi -!include slovak.nsi -!include slovenian.nsi -!include spanish.nsi -!include spanishinternational.nsi -!include swedish.nsi -!include thai.nsi -!include tradchinese.nsi -!include turkish.nsi -!include ukrainian.nsi -!include uzbek.nsi -!include welsh.nsi diff --git a/dist/windows/uninstaller.nsi b/dist/windows/uninstaller.nsi deleted file mode 100644 index b5e4cde19..000000000 --- a/dist/windows/uninstaller.nsi +++ /dev/null @@ -1,172 +0,0 @@ -Section "un.$(remove_files)" ;"un.Remove files" - SectionIn RO - -; Remove files and uninstaller - Delete "$INSTDIR\qbittorrent.exe" - Delete "$INSTDIR\qbittorrent.pdb" - Delete "$INSTDIR\qt.conf" - Delete "$INSTDIR\translations\qt_ar.qm" - Delete "$INSTDIR\translations\qt_bg.qm" - Delete "$INSTDIR\translations\qt_ca.qm" - Delete "$INSTDIR\translations\qt_cs.qm" - Delete "$INSTDIR\translations\qt_da.qm" - Delete "$INSTDIR\translations\qt_de.qm" - Delete "$INSTDIR\translations\qt_es.qm" - Delete "$INSTDIR\translations\qt_eu.qm" - Delete "$INSTDIR\translations\qt_fa.qm" - Delete "$INSTDIR\translations\qt_fi.qm" - Delete "$INSTDIR\translations\qt_fr.qm" - Delete "$INSTDIR\translations\qt_gl.qm" - Delete "$INSTDIR\translations\qt_he.qm" - Delete "$INSTDIR\translations\qt_hu.qm" - Delete "$INSTDIR\translations\qt_it.qm" - Delete "$INSTDIR\translations\qt_ja.qm" - Delete "$INSTDIR\translations\qt_ko.qm" - Delete "$INSTDIR\translations\qt_lt.qm" - Delete "$INSTDIR\translations\qt_nl.qm" - Delete "$INSTDIR\translations\qt_pl.qm" - Delete "$INSTDIR\translations\qt_pt_BR.qm" - Delete "$INSTDIR\translations\qt_pt.qm" - Delete "$INSTDIR\translations\qt_ru.qm" - Delete "$INSTDIR\translations\qt_sk.qm" - Delete "$INSTDIR\translations\qt_sl.qm" - Delete "$INSTDIR\translations\qt_sv.qm" - Delete "$INSTDIR\translations\qt_tr.qm" - Delete "$INSTDIR\translations\qt_uk.qm" - Delete "$INSTDIR\translations\qt_zh_CN.qm" - Delete "$INSTDIR\translations\qt_zh_TW.qm" - Delete "$INSTDIR\translations\qtbase_ca.qm" - Delete "$INSTDIR\translations\qtbase_cs.qm" - Delete "$INSTDIR\translations\qtbase_de.qm" - Delete "$INSTDIR\translations\qtbase_fi.qm" - Delete "$INSTDIR\translations\qtbase_fr.qm" - Delete "$INSTDIR\translations\qtbase_he.qm" - Delete "$INSTDIR\translations\qtbase_hu.qm" - Delete "$INSTDIR\translations\qtbase_it.qm" - Delete "$INSTDIR\translations\qtbase_ja.qm" - Delete "$INSTDIR\translations\qtbase_ko.qm" - Delete "$INSTDIR\translations\qtbase_lv.qm" - Delete "$INSTDIR\translations\qtbase_pl.qm" - Delete "$INSTDIR\translations\qtbase_ru.qm" - Delete "$INSTDIR\translations\qtbase_sk.qm" - Delete "$INSTDIR\translations\qtbase_uk.qm" - Delete "$INSTDIR\uninst.exe" - - ; Remove directories used - RMDir /r "$INSTDIR\translations" - RMDir "$INSTDIR" -SectionEnd - -Section "un.$(remove_shortcuts)" ;"un.Remove shortcuts" - SectionIn RO -; Remove shortcuts, if any - RMDir /r "$SMPROGRAMS\qBittorrent" - Delete "$DESKTOP\qBittorrent.lnk" -SectionEnd - -Section "un.$(remove_associations)" ;"un.Remove file associations" - SectionIn RO - ReadRegStr $0 HKLM "Software\Classes\.torrent" "" - StrCmp $0 "qBittorrent" 0 torrent_end - DetailPrint "$(uninst_tor_warn) $0" - DeleteRegValue HKLM "Software\Classes\.torrent" "" - DeleteRegKey /ifempty HKLM "Software\Classes\.torrent" - - torrent_end: - ReadRegStr $0 HKLM "Software\Classes\magnet\shell\open\command" "" - StrCmp $0 '"$INSTDIR\qbittorrent.exe" "%1"' 0 magnet_end - DetailPrint "$(uninst_mag_warn) $0" - DeleteRegKey HKLM "Software\Classes\magnet" - - magnet_end: - !insertmacro UAC_AsUser_Call Function un.remove_associations_user ${UAC_SYNCREGISTERS}|${UAC_SYNCOUTDIR}|${UAC_SYNCINSTDIR} - - System::Call 'Shell32::SHChangeNotify(i ${SHCNE_ASSOCCHANGED}, i ${SHCNF_IDLIST}, i 0, i 0)' -SectionEnd - -Function un.remove_associations_user - ReadRegStr $0 HKCU "Software\Classes\.torrent" "" - StrCmp $0 "qBittorrent" 0 torrent_end - DetailPrint "$(uninst_tor_warn) $0" - DeleteRegValue HKCU "Software\Classes\.torrent" "" - DeleteRegKey /ifempty HKCU "Software\Classes\.torrent" - - torrent_end: - ReadRegStr $0 HKCU "Software\Classes\magnet\shell\open\command" "" - StrCmp $0 '"$INSTDIR\qbittorrent.exe" "%1"' 0 magnet_end - DetailPrint "$(uninst_mag_warn) $0" - DeleteRegKey HKCU "Software\Classes\magnet" - - magnet_end: -FunctionEnd - -Section "un.$(remove_registry)" ;"un.Remove registry keys" - SectionIn RO - ; Remove registry keys - DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\qBittorrent" - DeleteRegKey HKLM "Software\qBittorrent" - DeleteRegKey HKLM "Software\Classes\qBittorrent" - - System::Call 'Shell32::SHChangeNotify(i ${SHCNE_ASSOCCHANGED}, i ${SHCNF_IDLIST}, i 0, i 0)' -SectionEnd - -Section "un.$(remove_firewall)" ; - - DetailPrint $(remove_firewallinfo) - nsisFirewallW::RemoveAuthorizedApplication "$INSTDIR\qbittorrent.exe" - -SectionEnd - -Section /o "un.$(remove_conf)" ;"un.Remove configuration files" - - !insertmacro UAC_AsUser_Call Function un.remove_conf_user ${UAC_SYNCREGISTERS}|${UAC_SYNCOUTDIR}|${UAC_SYNCINSTDIR} - -SectionEnd - -Function un.remove_conf_user - - System::Call 'shell32::SHGetSpecialFolderPath(i $HWNDPARENT, t .r1, i ${CSIDL_APPDATA}, i0)i.r0' - RMDir /r "$1\qBittorrent" - -FunctionEnd - -Section /o "un.$(remove_cache)" - - !insertmacro UAC_AsUser_Call Function un.remove_cache_user ${UAC_SYNCREGISTERS}|${UAC_SYNCOUTDIR}|${UAC_SYNCINSTDIR} - -SectionEnd - -Function un.remove_cache_user - - System::Call 'shell32::SHGetSpecialFolderPath(i $HWNDPARENT, t .r1, i ${CSIDL_LOCALAPPDATA}, i0)i.r0' - RMDir /r "$1\qBittorrent\" - -FunctionEnd - -;-------------------------------- -;Uninstaller Functions - -Function un.onInit - - !insertmacro Init "uninstaller" - !insertmacro MUI_UNGETLANGUAGE - -FunctionEnd - -Function un.check_instance - - check: - FindProcDLL::FindProc "qbittorrent.exe" - StrCmp $R0 "1" 0 notfound - MessageBox MB_RETRYCANCEL|MB_ICONEXCLAMATION $(uninst_warning) IDRETRY check IDCANCEL done - - done: - Abort - - notfound: - -FunctionEnd - -Function un.onUninstSuccess - SetErrorLevel 0 -FunctionEnd diff --git a/doc/qbittorrent-nox.1 b/doc/qbittorrent-nox.1 deleted file mode 100644 index 96c1eb5f1..000000000 --- a/doc/qbittorrent-nox.1 +++ /dev/null @@ -1,44 +0,0 @@ -.\" This manpage has been automatically generated by docbook2man -.\" from a DocBook document. This tool can be found at: -.\" . -.TH "QBITTORRENT\-NOX" "1" "January 16th 2010" "Command line Bittorrent client written in C++ / Qt" "" - -.SH "NAME" -qBittorrent\-nox \- a command line Bittorrent client written in C++ / Qt - -.SH "SYNOPSIS" - -\fBqbittorrent\-nox\fR [\-\-d|\-\-daemon] [\-\-webui-port=x] [TORRENT_FILE | URL]... - -\fBqbittorrent\-nox\fR \-\-help - -\fBqbittorrent\-nox\fR \-\-version - -.PP -.SH "DESCRIPTION" - -\fBqBittorrent-nox\fR is an advanced command-line Bittorrent client written in C++ / Qt -using the \fBlibtorrent-rasterbar\fR library by Arvid Norberg. qBittorrent\-nox aims -to be a good alternative to other command line bittorrent clients and provides features similar to popular graphical clients. - -qBittorrent\-nox is fast, stable, light and it supports unicode. -It also comes with UPnP port forwarding / NAT-PMP, encryption (Vuze compatible), -FAST extension (mainline) and PeX support (utorrent compatible). - -qBittorrent\-nox is meant to be controlled via its feature-rich Web UI which is accessible as a default on http://localhost:8080. The Web UI access is secured and the default account user name is "admin" with "adminadmin" as a password. - -.SH "OPTIONS" - -\fB--help\fR Prints the command line options. - -\fB--version\fR Prints qbittorrent program version number. - -\fB--webui-port=x\fR Changes Web UI port to x (default: 8080). - -.SH "BUGS" - -If you find a bug, please report it at http://bugs.qbittorrent.org - -.SH "AUTHOR" - -Christophe Dumez diff --git a/doc/qbittorrent.1 b/doc/qbittorrent.1 deleted file mode 100644 index ff95e5c25..000000000 --- a/doc/qbittorrent.1 +++ /dev/null @@ -1,42 +0,0 @@ -.\" This manpage has been automatically generated by docbook2man -.\" from a DocBook document. This tool can be found at: -.\" . -.TH "QBITTORRENT" "1" "January 16th 2010" "Bittorrent client written in C++ / Qt" "" - -.SH "NAME" -qBittorrent \- a Bittorrent client written in C++ / Qt - -.SH "SYNOPSIS" - -\fBqbittorrent\fR [\-\-no-splash] [\-\-webui-port=x] [TORRENT_FILE | URL]... - -\fBqbittorrent\fR \-\-help - -\fBqbittorrent\fR \-\-version - -.PP -.SH "DESCRIPTION" - -\fBqBittorrent\fR is an advanced Bittorrent client written in C++ / Qt, -using the \fBlibtorrent-rasterbar\fR library by Arvid Norberg. qBittorrent is similar to uTorrent. qBittorrent -is fast, stable, light, it supports unicode and it provides a good integrated search engine. -It also comes with UPnP port forwarding / NAT-PMP, encryption (Vuze compatible), -FAST extension (mainline) and PeX support (utorrent compatible). - -.SH "OPTIONS" - -\fB--help\fR Prints the command line options. - -\fB--version\fR Prints qbittorrent program version number. - -\fB--no-splash\fR Disables splash screen on startup. - -\fB--webui-port=x\fR Changes Web UI port to x (default: 8080). - -.SH "BUGS" - -If you find a bug, please report it at http://bugs.qbittorrent.org - -.SH "AUTHOR" - -Christophe Dumez diff --git a/install.os2 b/install.os2 deleted file mode 100644 index 17737b26a..000000000 --- a/install.os2 +++ /dev/null @@ -1,187 +0,0 @@ -QBittorrent installation - - - -0. CONTENTS OF THIS FILE -======================== - -1. INTRODUCTION - -2. REQUIREMENTS - -3. INSTALLATION - -4. BUGREPORTS - -5. CREDITS - -6. SUPPORT AND DONATIONS - -7. HISTORY - - -1. INTRODUCTION -=============== - -Welcome to QBittorrent port for OS/2 and eComStation. - - -2. REQUIREMENTS -=============== - -The following requirements can be installed either by rpm or by zip files. - -RPM Installation: - -klibc ------ - - 1. yum install libc - -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 - - -3. INSTALLATION -=============== - -To install QBittorrent, do the following: - - 1. Create a directory for QBittorrent. - 2. Extract the QBittorrent package to the new directory. - 3. Create a WPS object for QBittorrent.exe. - 4. Start QBittorrent - 5. Happy torrenting - - -4. BUGREPORTS -============= - -Please create bugreports at http://svn.netlabs.org/qtapps -Only bug reports with a reproducible bug are accepted. :-) - - -5. CREDITS -========== - -The port was done by: - -Silvan Scherrer aka _diver - -Thanks go to: - - * Dmitry A. Kuminov - -They either helped me when I had some nasty questions or did some testing for -me. - - -6. SUPPORT AND DONATIONS -======================== - -QBittorrent port is based on volunteer work. If you would like to support further -development, you can do so in one of the following ways: - - - * Donate to the Qt4 project: see qt.netlabs.org for more information - - * Contribute to the project: Besides actual development, this also includes - maintaining the documentation and the project web site as well as help - for users. - - -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 - -2010-11-22 - - * updated to 2.4.11 code level of QBittorrent - -2010-xx-xx - - * initial port - diff --git a/m4/ax_boost_base.m4 b/m4/ax_boost_base.m4 deleted file mode 100644 index f3279f2b7..000000000 --- a/m4/ax_boost_base.m4 +++ /dev/null @@ -1,285 +0,0 @@ -# =========================================================================== -# http://www.gnu.org/software/autoconf-archive/ax_boost_base.html -# =========================================================================== -# -# SYNOPSIS -# -# AX_BOOST_BASE([MINIMUM-VERSION], [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) -# -# DESCRIPTION -# -# Test for the Boost C++ libraries of a particular version (or newer) -# -# If no path to the installed boost library is given the macro searchs -# under /usr, /usr/local, /opt and /opt/local and evaluates the -# $BOOST_ROOT environment variable. Further documentation is available at -# . -# -# This macro calls: -# -# AC_SUBST(BOOST_CPPFLAGS) / AC_SUBST(BOOST_LDFLAGS) -# -# And sets: -# -# HAVE_BOOST -# -# LICENSE -# -# Copyright (c) 2008 Thomas Porschberg -# Copyright (c) 2009 Peter Adolphs -# -# Copying and distribution of this file, with or without modification, are -# permitted in any medium without royalty provided the copyright notice -# and this notice are preserved. This file is offered as-is, without any -# warranty. - -#serial 26 - -AC_DEFUN([AX_BOOST_BASE], -[ -AC_ARG_WITH([boost], - [AS_HELP_STRING([--with-boost@<:@=ARG@:>@], - [use Boost library from a standard location (ARG=yes), - from the specified location (ARG=), - or disable it (ARG=no) - @<:@ARG=yes@:>@ ])], - [ - if test "$withval" = "no"; then - want_boost="no" - elif test "$withval" = "yes"; then - want_boost="yes" - ac_boost_path="" - else - want_boost="yes" - ac_boost_path="$withval" - fi - ], - [want_boost="yes"]) - - -AC_ARG_WITH([boost-libdir], - AS_HELP_STRING([--with-boost-libdir=LIB_DIR], - [Force given directory for boost libraries. Note that this will override library path detection, so use this parameter only if default library detection fails and you know exactly where your boost libraries are located.]), - [ - if test -d "$withval" - then - ac_boost_lib_path="$withval" - else - AC_MSG_ERROR(--with-boost-libdir expected directory name) - fi - ], - [ac_boost_lib_path=""] -) - -if test "x$want_boost" = "xyes"; then - boost_lib_version_req=ifelse([$1], ,1.20.0,$1) - boost_lib_version_req_shorten=`expr $boost_lib_version_req : '\([[0-9]]*\.[[0-9]]*\)'` - boost_lib_version_req_major=`expr $boost_lib_version_req : '\([[0-9]]*\)'` - boost_lib_version_req_minor=`expr $boost_lib_version_req : '[[0-9]]*\.\([[0-9]]*\)'` - boost_lib_version_req_sub_minor=`expr $boost_lib_version_req : '[[0-9]]*\.[[0-9]]*\.\([[0-9]]*\)'` - if test "x$boost_lib_version_req_sub_minor" = "x" ; then - boost_lib_version_req_sub_minor="0" - fi - WANT_BOOST_VERSION=`expr $boost_lib_version_req_major \* 100000 \+ $boost_lib_version_req_minor \* 100 \+ $boost_lib_version_req_sub_minor` - AC_MSG_CHECKING(for boostlib >= $boost_lib_version_req) - succeeded=no - - dnl On 64-bit systems check for system libraries in both lib64 and lib. - dnl The former is specified by FHS, but e.g. Debian does not adhere to - dnl this (as it rises problems for generic multi-arch support). - dnl The last entry in the list is chosen by default when no libraries - dnl are found, e.g. when only header-only libraries are installed! - libsubdirs="lib" - ax_arch=`uname -m` - case $ax_arch in - x86_64) - libsubdirs="lib64 libx32 lib lib64" - ;; - ppc64|s390x|sparc64|aarch64|ppc64le) - libsubdirs="lib64 lib lib64 ppc64le" - ;; - esac - - dnl allow for real multi-arch paths e.g. /usr/lib/x86_64-linux-gnu. Give - dnl them priority over the other paths since, if libs are found there, they - dnl are almost assuredly the ones desired. - AC_REQUIRE([AC_CANONICAL_HOST]) - libsubdirs="lib/${host_cpu}-${host_os} $libsubdirs" - - case ${host_cpu} in - i?86) - libsubdirs="lib/i386-${host_os} $libsubdirs" - ;; - esac - - dnl first we check the system location for boost libraries - dnl this location ist chosen if boost libraries are installed with the --layout=system option - dnl or if you install boost with RPM - if test "$ac_boost_path" != ""; then - BOOST_CPPFLAGS="-I$ac_boost_path/include" - for ac_boost_path_tmp in $libsubdirs; do - if test -d "$ac_boost_path"/"$ac_boost_path_tmp" ; then - BOOST_LDFLAGS="-L$ac_boost_path/$ac_boost_path_tmp" - break - fi - done - elif test "$cross_compiling" != yes; then - for ac_boost_path_tmp in /usr /usr/local /opt /opt/local ; do - if test -d "$ac_boost_path_tmp/include/boost" && test -r "$ac_boost_path_tmp/include/boost"; then - for libsubdir in $libsubdirs ; do - if ls "$ac_boost_path_tmp/$libsubdir/libboost_"* >/dev/null 2>&1 ; then break; fi - done - BOOST_LDFLAGS="-L$ac_boost_path_tmp/$libsubdir" - BOOST_CPPFLAGS="-I$ac_boost_path_tmp/include" - break; - fi - done - fi - - dnl overwrite ld flags if we have required special directory with - dnl --with-boost-libdir parameter - if test "$ac_boost_lib_path" != ""; then - BOOST_LDFLAGS="-L$ac_boost_lib_path" - fi - - CPPFLAGS_SAVED="$CPPFLAGS" - CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS" - export CPPFLAGS - - LDFLAGS_SAVED="$LDFLAGS" - LDFLAGS="$LDFLAGS $BOOST_LDFLAGS" - export LDFLAGS - - AC_REQUIRE([AC_PROG_CXX]) - AC_LANG_PUSH(C++) - AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ - @%:@include - ]], [[ - #if BOOST_VERSION >= $WANT_BOOST_VERSION - // Everything is okay - #else - # error Boost version is too old - #endif - ]])],[ - AC_MSG_RESULT(yes) - succeeded=yes - found_system=yes - ],[ - ]) - AC_LANG_POP([C++]) - - - - dnl if we found no boost with system layout we search for boost libraries - dnl built and installed without the --layout=system option or for a staged(not installed) version - if test "x$succeeded" != "xyes"; then - CPPFLAGS="$CPPFLAGS_SAVED" - LDFLAGS="$LDFLAGS_SAVED" - BOOST_CPPFLAGS= - BOOST_LDFLAGS= - _version=0 - if test "$ac_boost_path" != ""; then - if test -d "$ac_boost_path" && test -r "$ac_boost_path"; then - for i in `ls -d $ac_boost_path/include/boost-* 2>/dev/null`; do - _version_tmp=`echo $i | sed "s#$ac_boost_path##" | sed 's/\/include\/boost-//' | sed 's/_/./'` - V_CHECK=`expr $_version_tmp \> $_version` - if test "$V_CHECK" = "1" ; then - _version=$_version_tmp - fi - VERSION_UNDERSCORE=`echo $_version | sed 's/\./_/'` - BOOST_CPPFLAGS="-I$ac_boost_path/include/boost-$VERSION_UNDERSCORE" - done - dnl if nothing found search for layout used in Windows distributions - if test -z "$BOOST_CPPFLAGS"; then - if test -d "$ac_boost_path/boost" && test -r "$ac_boost_path/boost"; then - BOOST_CPPFLAGS="-I$ac_boost_path" - fi - fi - fi - else - if test "$cross_compiling" != yes; then - for ac_boost_path in /usr /usr/local /opt /opt/local ; do - if test -d "$ac_boost_path" && test -r "$ac_boost_path"; then - for i in `ls -d $ac_boost_path/include/boost-* 2>/dev/null`; do - _version_tmp=`echo $i | sed "s#$ac_boost_path##" | sed 's/\/include\/boost-//' | sed 's/_/./'` - V_CHECK=`expr $_version_tmp \> $_version` - if test "$V_CHECK" = "1" ; then - _version=$_version_tmp - best_path=$ac_boost_path - fi - done - fi - done - - VERSION_UNDERSCORE=`echo $_version | sed 's/\./_/'` - BOOST_CPPFLAGS="-I$best_path/include/boost-$VERSION_UNDERSCORE" - if test "$ac_boost_lib_path" = ""; then - for libsubdir in $libsubdirs ; do - if ls "$best_path/$libsubdir/libboost_"* >/dev/null 2>&1 ; then break; fi - done - BOOST_LDFLAGS="-L$best_path/$libsubdir" - fi - fi - - if test "x$BOOST_ROOT" != "x"; then - for libsubdir in $libsubdirs ; do - if ls "$BOOST_ROOT/stage/$libsubdir/libboost_"* >/dev/null 2>&1 ; then break; fi - done - if test -d "$BOOST_ROOT" && test -r "$BOOST_ROOT" && test -d "$BOOST_ROOT/stage/$libsubdir" && test -r "$BOOST_ROOT/stage/$libsubdir"; then - version_dir=`expr //$BOOST_ROOT : '.*/\(.*\)'` - stage_version=`echo $version_dir | sed 's/boost_//' | sed 's/_/./g'` - stage_version_shorten=`expr $stage_version : '\([[0-9]]*\.[[0-9]]*\)'` - V_CHECK=`expr $stage_version_shorten \>\= $_version` - if test "$V_CHECK" = "1" -a "$ac_boost_lib_path" = "" ; then - AC_MSG_NOTICE(We will use a staged boost library from $BOOST_ROOT) - BOOST_CPPFLAGS="-I$BOOST_ROOT" - BOOST_LDFLAGS="-L$BOOST_ROOT/stage/$libsubdir" - fi - fi - fi - fi - - CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS" - export CPPFLAGS - LDFLAGS="$LDFLAGS $BOOST_LDFLAGS" - export LDFLAGS - - AC_LANG_PUSH(C++) - AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ - @%:@include - ]], [[ - #if BOOST_VERSION >= $WANT_BOOST_VERSION - // Everything is okay - #else - # error Boost version is too old - #endif - ]])],[ - AC_MSG_RESULT(yes) - succeeded=yes - found_system=yes - ],[ - ]) - AC_LANG_POP([C++]) - fi - - if test "$succeeded" != "yes" ; then - if test "$_version" = "0" ; then - AC_MSG_NOTICE([[We could not detect the boost libraries (version $boost_lib_version_req_shorten or higher). If you have a staged boost library (still not installed) please specify \$BOOST_ROOT in your environment and do not give a PATH to --with-boost option. If you are sure you have boost installed, then check your version number looking in . See http://randspringer.de/boost for more documentation.]]) - else - AC_MSG_NOTICE([Your boost libraries seems to old (version $_version).]) - fi - # execute ACTION-IF-NOT-FOUND (if present): - ifelse([$3], , :, [$3]) - else - AC_SUBST(BOOST_CPPFLAGS) - AC_SUBST(BOOST_LDFLAGS) - AC_DEFINE(HAVE_BOOST,,[define if the Boost library is available]) - # execute ACTION-IF-FOUND (if present): - ifelse([$2], , :, [$2]) - fi - - CPPFLAGS="$CPPFLAGS_SAVED" - LDFLAGS="$LDFLAGS_SAVED" -fi - -]) diff --git a/m4/ax_boost_system.m4 b/m4/ax_boost_system.m4 deleted file mode 100644 index 43570a513..000000000 --- a/m4/ax_boost_system.m4 +++ /dev/null @@ -1,121 +0,0 @@ -# =========================================================================== -# http://www.gnu.org/software/autoconf-archive/ax_boost_system.html -# =========================================================================== -# -# SYNOPSIS -# -# AX_BOOST_SYSTEM -# -# DESCRIPTION -# -# Test for System library from the Boost C++ libraries. The macro requires -# a preceding call to AX_BOOST_BASE. Further documentation is available at -# . -# -# This macro calls: -# -# AC_SUBST(BOOST_SYSTEM_LIB) -# -# And sets: -# -# HAVE_BOOST_SYSTEM -# -# LICENSE -# -# Copyright (c) 2008 Thomas Porschberg -# Copyright (c) 2008 Michael Tindal -# Copyright (c) 2008 Daniel Casimiro -# -# Copying and distribution of this file, with or without modification, are -# permitted in any medium without royalty provided the copyright notice -# and this notice are preserved. This file is offered as-is, without any -# warranty. - -#serial 18 - -AC_DEFUN([AX_BOOST_SYSTEM], -[ - AC_ARG_WITH([boost-system], - AS_HELP_STRING([--with-boost-system@<:@=special-lib@:>@], - [use the System library from boost - it is possible to specify a certain library for the linker - e.g. --with-boost-system=boost_system-gcc-mt ]), - [ - if test "$withval" = "no"; then - want_boost="no" - elif test "$withval" = "yes"; then - want_boost="yes" - ax_boost_user_system_lib="" - else - want_boost="yes" - ax_boost_user_system_lib="$withval" - fi - ], - [want_boost="yes"] - ) - - if test "x$want_boost" = "xyes"; then - AC_REQUIRE([AC_PROG_CC]) - AC_REQUIRE([AC_CANONICAL_BUILD]) - CPPFLAGS_SAVED="$CPPFLAGS" - CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS" - export CPPFLAGS - - LDFLAGS_SAVED="$LDFLAGS" - LDFLAGS="$LDFLAGS $BOOST_LDFLAGS" - export LDFLAGS - - AC_CACHE_CHECK(whether the Boost::System library is available, - ax_cv_boost_system, - [AC_LANG_PUSH([C++]) - CXXFLAGS_SAVE=$CXXFLAGS - CXXFLAGS= - - AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[@%:@include ]], - [[boost::system::error_category *a = 0;]])], - ax_cv_boost_system=yes, ax_cv_boost_system=no) - CXXFLAGS=$CXXFLAGS_SAVE - AC_LANG_POP([C++]) - ]) - if test "x$ax_cv_boost_system" = "xyes"; then - AC_SUBST(BOOST_CPPFLAGS) - - AC_DEFINE(HAVE_BOOST_SYSTEM,,[define if the Boost::System library is available]) - BOOSTLIBDIR=`echo $BOOST_LDFLAGS | sed -e 's/@<:@^\/@:>@*//'` - - LDFLAGS_SAVE=$LDFLAGS - if test "x$ax_boost_user_system_lib" = "x"; then - for libextension in `ls -r $BOOSTLIBDIR/libboost_system* 2>/dev/null | sed 's,.*/lib,,' | sed 's,\..*,,'` ; do - ax_lib=${libextension} - AC_CHECK_LIB($ax_lib, exit, - [BOOST_SYSTEM_LIB="-l$ax_lib"; AC_SUBST(BOOST_SYSTEM_LIB) link_system="yes"; break], - [link_system="no"]) - done - if test "x$link_system" != "xyes"; then - for libextension in `ls -r $BOOSTLIBDIR/boost_system* 2>/dev/null | sed 's,.*/,,' | sed -e 's,\..*,,'` ; do - ax_lib=${libextension} - AC_CHECK_LIB($ax_lib, exit, - [BOOST_SYSTEM_LIB="-l$ax_lib"; AC_SUBST(BOOST_SYSTEM_LIB) link_system="yes"; break], - [link_system="no"]) - done - fi - - else - for ax_lib in $ax_boost_user_system_lib boost_system-$ax_boost_user_system_lib; do - AC_CHECK_LIB($ax_lib, exit, - [BOOST_SYSTEM_LIB="-l$ax_lib"; AC_SUBST(BOOST_SYSTEM_LIB) link_system="yes"; break], - [link_system="no"]) - done - - fi - if test "x$ax_lib" = "x"; then - AC_MSG_ERROR(Could not find a version of the library!) - fi - if test "x$link_system" = "xno"; then - AC_MSG_ERROR(Could not link against $ax_lib !) - fi - fi - - CPPFLAGS="$CPPFLAGS_SAVED" - LDFLAGS="$LDFLAGS_SAVED" - fi -]) diff --git a/m4/ax_define_dir.m4 b/m4/ax_define_dir.m4 deleted file mode 100644 index b74d155fd..000000000 --- a/m4/ax_define_dir.m4 +++ /dev/null @@ -1,49 +0,0 @@ -# =========================================================================== -# http://www.gnu.org/software/autoconf-archive/ax_define_dir.html -# =========================================================================== -# -# SYNOPSIS -# -# AX_DEFINE_DIR(VARNAME, DIR [, DESCRIPTION]) -# -# DESCRIPTION -# -# This macro sets VARNAME to the expansion of the DIR variable, taking -# care of fixing up ${prefix} and such. -# -# VARNAME is then offered as both an output variable and a C preprocessor -# symbol. -# -# Example: -# -# AX_DEFINE_DIR([DATADIR], [datadir], [Where data are placed to.]) -# -# LICENSE -# -# Copyright (c) 2008 Stepan Kasal -# Copyright (c) 2008 Andreas Schwab -# Copyright (c) 2008 Guido U. Draheim -# Copyright (c) 2008 Alexandre Oliva -# -# Copying and distribution of this file, with or without modification, are -# permitted in any medium without royalty provided the copyright notice -# and this notice are preserved. This file is offered as-is, without any -# warranty. - -#serial 6 - -AU_ALIAS([AC_DEFINE_DIR], [AX_DEFINE_DIR]) -AC_DEFUN([AX_DEFINE_DIR], [ - prefix_NONE= - exec_prefix_NONE= - test "x$prefix" = xNONE && prefix_NONE=yes && prefix=$ac_default_prefix - test "x$exec_prefix" = xNONE && exec_prefix_NONE=yes && exec_prefix=$prefix -dnl In Autoconf 2.60, ${datadir} refers to ${datarootdir}, which in turn -dnl refers to ${prefix}. Thus we have to use `eval' twice. - eval ax_define_dir="\"[$]$2\"" - eval ax_define_dir="\"$ax_define_dir\"" - AC_SUBST($1, "$ax_define_dir") - AC_DEFINE_UNQUOTED($1, "$ax_define_dir", [$3]) - test "$prefix_NONE" && prefix=NONE - test "$exec_prefix_NONE" && exec_prefix=NONE -]) diff --git a/m4/pkg.m4 b/m4/pkg.m4 deleted file mode 100644 index c5b26b52e..000000000 --- a/m4/pkg.m4 +++ /dev/null @@ -1,214 +0,0 @@ -# pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*- -# serial 1 (pkg-config-0.24) -# -# Copyright © 2004 Scott James Remnant . -# -# 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -# -# As a special exception to the GNU General Public License, if you -# distribute this file as part of a program that contains a -# configuration script generated by Autoconf, you may include it under -# the same distribution terms that you use for the rest of that program. - -# PKG_PROG_PKG_CONFIG([MIN-VERSION]) -# ---------------------------------- -AC_DEFUN([PKG_PROG_PKG_CONFIG], -[m4_pattern_forbid([^_?PKG_[A-Z_]+$]) -m4_pattern_allow([^PKG_CONFIG(_(PATH|LIBDIR|SYSROOT_DIR|ALLOW_SYSTEM_(CFLAGS|LIBS)))?$]) -m4_pattern_allow([^PKG_CONFIG_(DISABLE_UNINSTALLED|TOP_BUILD_DIR|DEBUG_SPEW)$]) -AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility]) -AC_ARG_VAR([PKG_CONFIG_PATH], [directories to add to pkg-config's search path]) -AC_ARG_VAR([PKG_CONFIG_LIBDIR], [path overriding pkg-config's built-in search path]) - -if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then - AC_PATH_TOOL([PKG_CONFIG], [pkg-config]) -fi -if test -n "$PKG_CONFIG"; then - _pkg_min_version=m4_default([$1], [0.9.0]) - AC_MSG_CHECKING([pkg-config is at least version $_pkg_min_version]) - if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then - AC_MSG_RESULT([yes]) - else - AC_MSG_RESULT([no]) - PKG_CONFIG="" - fi -fi[]dnl -])# PKG_PROG_PKG_CONFIG - -# PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) -# -# Check to see whether a particular set of modules exists. Similar -# to PKG_CHECK_MODULES(), but does not set variables or print errors. -# -# Please remember that m4 expands AC_REQUIRE([PKG_PROG_PKG_CONFIG]) -# only at the first occurence in configure.ac, so if the first place -# it's called might be skipped (such as if it is within an "if", you -# have to call PKG_CHECK_EXISTS manually -# -------------------------------------------------------------- -AC_DEFUN([PKG_CHECK_EXISTS], -[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl -if test -n "$PKG_CONFIG" && \ - AC_RUN_LOG([$PKG_CONFIG --exists --print-errors "$1"]); then - m4_default([$2], [:]) -m4_ifvaln([$3], [else - $3])dnl -fi]) - -# _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES]) -# --------------------------------------------- -m4_define([_PKG_CONFIG], -[if test -n "$$1"; then - pkg_cv_[]$1="$$1" - elif test -n "$PKG_CONFIG"; then - PKG_CHECK_EXISTS([$3], - [pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null` - test "x$?" != "x0" && pkg_failed=yes ], - [pkg_failed=yes]) - else - pkg_failed=untried -fi[]dnl -])# _PKG_CONFIG - -# _PKG_SHORT_ERRORS_SUPPORTED -# ----------------------------- -AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED], -[AC_REQUIRE([PKG_PROG_PKG_CONFIG]) -if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then - _pkg_short_errors_supported=yes -else - _pkg_short_errors_supported=no -fi[]dnl -])# _PKG_SHORT_ERRORS_SUPPORTED - - -# PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND], -# [ACTION-IF-NOT-FOUND]) -# -# -# Note that if there is a possibility the first call to -# PKG_CHECK_MODULES might not happen, you should be sure to include an -# explicit call to PKG_PROG_PKG_CONFIG in your configure.ac -# -# -# -------------------------------------------------------------- -AC_DEFUN([PKG_CHECK_MODULES], -[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl -AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl -AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl - -pkg_failed=no -AC_MSG_CHECKING([for $1]) - -_PKG_CONFIG([$1][_CFLAGS], [cflags], [$2]) -_PKG_CONFIG([$1][_LIBS], [libs], [$2]) - -m4_define([_PKG_TEXT], [Alternatively, you may set the environment variables $1[]_CFLAGS -and $1[]_LIBS to avoid the need to call pkg-config. -See the pkg-config man page for more details.]) - -if test $pkg_failed = yes; then - AC_MSG_RESULT([no]) - _PKG_SHORT_ERRORS_SUPPORTED - if test $_pkg_short_errors_supported = yes; then - $1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$2" 2>&1` - else - $1[]_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$2" 2>&1` - fi - # Put the nasty error message in config.log where it belongs - echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD - - m4_default([$4], [AC_MSG_ERROR( -[Package requirements ($2) were not met: - -$$1_PKG_ERRORS - -Consider adjusting the PKG_CONFIG_PATH environment variable if you -installed software in a non-standard prefix. - -_PKG_TEXT])[]dnl - ]) -elif test $pkg_failed = untried; then - AC_MSG_RESULT([no]) - m4_default([$4], [AC_MSG_FAILURE( -[The pkg-config script could not be found or is too old. Make sure it -is in your PATH or set the PKG_CONFIG environment variable to the full -path to pkg-config. - -_PKG_TEXT - -To get pkg-config, see .])[]dnl - ]) -else - $1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS - $1[]_LIBS=$pkg_cv_[]$1[]_LIBS - AC_MSG_RESULT([yes]) - $3 -fi[]dnl -])# PKG_CHECK_MODULES - - -# PKG_INSTALLDIR(DIRECTORY) -# ------------------------- -# Substitutes the variable pkgconfigdir as the location where a module -# should install pkg-config .pc files. By default the directory is -# $libdir/pkgconfig, but the default can be changed by passing -# DIRECTORY. The user can override through the --with-pkgconfigdir -# parameter. -AC_DEFUN([PKG_INSTALLDIR], -[m4_pushdef([pkg_default], [m4_default([$1], ['${libdir}/pkgconfig'])]) -m4_pushdef([pkg_description], - [pkg-config installation directory @<:@]pkg_default[@:>@]) -AC_ARG_WITH([pkgconfigdir], - [AS_HELP_STRING([--with-pkgconfigdir], pkg_description)],, - [with_pkgconfigdir=]pkg_default) -AC_SUBST([pkgconfigdir], [$with_pkgconfigdir]) -m4_popdef([pkg_default]) -m4_popdef([pkg_description]) -]) dnl PKG_INSTALLDIR - - -# PKG_NOARCH_INSTALLDIR(DIRECTORY) -# ------------------------- -# Substitutes the variable noarch_pkgconfigdir as the location where a -# module should install arch-independent pkg-config .pc files. By -# default the directory is $datadir/pkgconfig, but the default can be -# changed by passing DIRECTORY. The user can override through the -# --with-noarch-pkgconfigdir parameter. -AC_DEFUN([PKG_NOARCH_INSTALLDIR], -[m4_pushdef([pkg_default], [m4_default([$1], ['${datadir}/pkgconfig'])]) -m4_pushdef([pkg_description], - [pkg-config arch-independent installation directory @<:@]pkg_default[@:>@]) -AC_ARG_WITH([noarch-pkgconfigdir], - [AS_HELP_STRING([--with-noarch-pkgconfigdir], pkg_description)],, - [with_noarch_pkgconfigdir=]pkg_default) -AC_SUBST([noarch_pkgconfigdir], [$with_noarch_pkgconfigdir]) -m4_popdef([pkg_default]) -m4_popdef([pkg_description]) -]) dnl PKG_NOARCH_INSTALLDIR - - -# PKG_CHECK_VAR(VARIABLE, MODULE, CONFIG-VARIABLE, -# [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) -# ------------------------------------------- -# Retrieves the value of the pkg-config variable for the given module. -AC_DEFUN([PKG_CHECK_VAR], -[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl -AC_ARG_VAR([$1], [value of $3 for $2, overriding pkg-config])dnl - -_PKG_CONFIG([$1], [variable="][$3]["], [$2]) -AS_VAR_COPY([$1], [pkg_cv_][$1]) - -AS_VAR_IF([$1], [""], [$5], [$4])dnl -])# PKG_CHECK_VAR diff --git a/m4/qbittorrent.m4 b/m4/qbittorrent.m4 deleted file mode 100644 index e0696e630..000000000 --- a/m4/qbittorrent.m4 +++ /dev/null @@ -1,38 +0,0 @@ -# Checking for pkg-config. If found, check for QtCore and query pkg-config -# for its exec-prefix variable. - -# FIND_QT5() -# Sets the QT_QMAKE variable to the path of Qt5 qmake if found. -# -------------------------------------- -AC_DEFUN([FIND_QT5], -[PKG_CHECK_EXISTS([Qt5Core >= 5.5.1], - [PKG_CHECK_VAR(QT_QMAKE, - [Qt5Core >= 5.5.1], - [host_bins]) - ]) - -AS_IF([test -f "$QT_QMAKE/qmake"], - [QT_QMAKE="$QT_QMAKE/qmake"], - [AS_IF([test -f "$QT_QMAKE/qmake-qt5"], - [QT_QMAKE="$QT_QMAKE/qmake-qt5"], - [QT_QMAKE=""]) - ]) - -AC_MSG_CHECKING([for Qt5 qmake >= 5.5.1]) -AS_IF([test "x$QT_QMAKE" != "x"], - [AC_MSG_RESULT([$QT_QMAKE])], - [AC_MSG_RESULT([not found])] - ) -]) - -# FIND_QTDBUS() -# Sets the HAVE_QTDBUS variable to true or false. -# -------------------------------------- -AC_DEFUN([FIND_QTDBUS], - [AC_MSG_CHECKING([for Qt5DBus >= 5.5.1]) - PKG_CHECK_EXISTS([Qt5DBus >= 5.5.1], - [AC_MSG_RESULT([found]) - HAVE_QTDBUS=[true]], - [AC_MSG_RESULT([not found]) - HAVE_QTDBUS=[false]]) -]) diff --git a/macxconf.pri b/macxconf.pri deleted file mode 100644 index 09dd13a82..000000000 --- a/macxconf.pri +++ /dev/null @@ -1,75 +0,0 @@ -# Generated by the configure file -# Ignore any WARNING about 'conf.pri' missing during configure. The file should be found during make. -# If not there will be a WARNING again. -# The first path is used when the source is being build by packagers (pbuilder/sbuild/etc) -# The second path is used when you manually run the configure script in the root folder (eg when using qt creator) -exists($$OUT_PWD/../conf.pri) { - include($$OUT_PWD/../conf.pri) -} else { - include(conf.pri) -} - -LIBS += -framework Carbon -framework IOKit - -QT_LANG_PATH = ../dist/qt-translations -DIST_PATH = ../dist/mac - -document_icon.path = Contents/Resources -document_icon.files = $$DIST_PATH/qBitTorrentDocument.icns -QMAKE_BUNDLE_DATA += document_icon - -qt_conf.path = Contents/Resources -qt_conf.files = $$DIST_PATH/qt.conf -QMAKE_BUNDLE_DATA += qt_conf - -qt_translations.path = Contents/translations -qt_translations.files = \ - $$QT_LANG_PATH/qt_ar.qm \ - $$QT_LANG_PATH/qt_bg.qm \ - $$QT_LANG_PATH/qt_ca.qm \ - $$QT_LANG_PATH/qt_cs.qm \ - $$QT_LANG_PATH/qt_da.qm \ - $$QT_LANG_PATH/qt_de.qm \ - $$QT_LANG_PATH/qt_es.qm \ - $$QT_LANG_PATH/qt_eu.qm \ - $$QT_LANG_PATH/qt_fa.qm \ - $$QT_LANG_PATH/qt_fi.qm \ - $$QT_LANG_PATH/qt_fr.qm \ - $$QT_LANG_PATH/qt_gl.qm \ - $$QT_LANG_PATH/qt_he.qm \ - $$QT_LANG_PATH/qt_hu.qm \ - $$QT_LANG_PATH/qt_it.qm \ - $$QT_LANG_PATH/qt_ja.qm \ - $$QT_LANG_PATH/qt_ko.qm \ - $$QT_LANG_PATH/qt_lt.qm \ - $$QT_LANG_PATH/qt_nl.qm \ - $$QT_LANG_PATH/qt_pl.qm \ - $$QT_LANG_PATH/qt_pt.qm \ - $$QT_LANG_PATH/qt_pt_BR.qm \ - $$QT_LANG_PATH/qt_ru.qm \ - $$QT_LANG_PATH/qt_sk.qm \ - $$QT_LANG_PATH/qt_sl.qm \ - $$QT_LANG_PATH/qt_sv.qm \ - $$QT_LANG_PATH/qt_tr.qm \ - $$QT_LANG_PATH/qt_uk.qm \ - $$QT_LANG_PATH/qt_zh_CN.qm \ - $$QT_LANG_PATH/qt_zh_TW.qm \ - $$QT_LANG_PATH/qtbase_ca.qm \ - $$QT_LANG_PATH/qtbase_cs.qm \ - $$QT_LANG_PATH/qtbase_de.qm \ - $$QT_LANG_PATH/qtbase_fi.qm \ - $$QT_LANG_PATH/qtbase_fr.qm \ - $$QT_LANG_PATH/qtbase_he.qm \ - $$QT_LANG_PATH/qtbase_hu.qm \ - $$QT_LANG_PATH/qtbase_it.qm \ - $$QT_LANG_PATH/qtbase_ja.qm \ - $$QT_LANG_PATH/qtbase_ko.qm \ - $$QT_LANG_PATH/qtbase_lv.qm \ - $$QT_LANG_PATH/qtbase_pl.qm \ - $$QT_LANG_PATH/qtbase_ru.qm \ - $$QT_LANG_PATH/qtbase_sk.qm \ - $$QT_LANG_PATH/qtbase_uk.qm -QMAKE_BUNDLE_DATA += qt_translations - -ICON = $$DIST_PATH/qbittorrent_mac.icns -QMAKE_INFO_PLIST = $$DIST_PATH/Info.plist diff --git a/os2conf.pri b/os2conf.pri deleted file mode 100644 index c27a9e77e..000000000 --- a/os2conf.pri +++ /dev/null @@ -1,16 +0,0 @@ -exists(conf.pri) { - # to the conf.pri goes all system dependent stuff - include(conf.pri) -} - -LIBS += \ - -ltorrent-rasterbar \ - -lboost_thread \ - -lboost_system \ - -lboost_filesystem \ - -lssl -lcrypto -lidn -lpthread -lz - -RC_FILE = qbittorrent_os2.rc - -# LIBTORRENT DEFINES -DEFINES += BOOST_ASIO_DYN_LINK diff --git a/qbittorrent.pro b/qbittorrent.pro deleted file mode 100644 index c2791bfe0..000000000 --- a/qbittorrent.pro +++ /dev/null @@ -1,19 +0,0 @@ -TEMPLATE = subdirs - -SUBDIRS += src - -include(version.pri) -include(qm_gen.pri) - -# Make target to create release tarball. Use 'make tarball' -tarball.commands += rm -fR ../$${PROJECT_NAME}-$${PROJECT_VERSION}/ && -tarball.commands += git clone . ../$${PROJECT_NAME}-$${PROJECT_VERSION} && -tarball.commands += rm -fR ../$${PROJECT_NAME}-$${PROJECT_VERSION}/.git && -tarball.commands += rm -f ../$${PROJECT_NAME}-$${PROJECT_VERSION}/.gitignore && -tarball.commands += cd .. && -tarball.commands += tar czf $${PROJECT_NAME}-$${PROJECT_VERSION}.tar.gz $${PROJECT_NAME}-$${PROJECT_VERSION} && -tarball.commands += tar cf $${PROJECT_NAME}-$${PROJECT_VERSION}.tar $${PROJECT_NAME}-$${PROJECT_VERSION} && -tarball.commands += xz -f $${PROJECT_NAME}-$${PROJECT_VERSION}.tar && -tarball.commands += rm -fR $${PROJECT_NAME}-$${PROJECT_VERSION} - -QMAKE_EXTRA_TARGETS += tarball diff --git a/qm_gen.pri b/qm_gen.pri deleted file mode 100644 index ae9d73e86..000000000 --- a/qm_gen.pri +++ /dev/null @@ -1,21 +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 { - equals(QT_MAJOR_VERSION, 5) { - !exists($$QMAKE_LRELEASE) { QMAKE_LRELEASE = lrelease-qt5 } - } - } 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") -} diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt deleted file mode 100644 index 3137057ca..000000000 --- a/src/CMakeLists.txt +++ /dev/null @@ -1,103 +0,0 @@ -set(CMAKE_CXX_STANDARD_REQUIRED True) -set(CMAKE_CXX_STANDARD "11") -add_definitions(-DBOOST_NO_CXX11_RVALUE_REFERENCES) - -include(MacroQbtCompilerSettings) -qbt_set_compiler_options() - -include(MacroLinkQtComponents) -include(QbtTargetSources) - -find_package(LibtorrentRasterbar REQUIRED) - -# Qt -list(APPEND QBT_QT_COMPONENTS Core Network Xml) -if (GUI) - list (APPEND QBT_QT_COMPONENTS Concurrent Gui Svg Widgets) - if (WIN32) - list (APPEND QBT_QT_COMPONENTS WinExtras) - endif(WIN32) - if (APPLE) - list (APPEND QBT_GUI_OPTIONAL_LINK_LIBRARIES objc) - list (APPEND QBT_QT_COMPONENTS MacExtras) - endif (APPLE) -endif (GUI) -if (DBUS) - list (APPEND QBT_QT_COMPONENTS DBus) -endif (DBUS) -find_package(Qt5 5.5.1 COMPONENTS ${QBT_QT_COMPONENTS} REQUIRED) - -if (GUI AND APPLE) - # Fix MOC inability to detect macOS. This seems to only affect cmake. - # Relevant issue: https://bugreports.qt.io/browse/QTBUG-58325 - set(CMAKE_AUTOMOC_MOC_OPTIONS ${CMAKE_AUTOMOC_MOC_OPTIONS} -DQ_OS_MAC) -endif () - -set(CMAKE_AUTOMOC True) -list(APPEND CMAKE_AUTORCC_OPTIONS -compress 9 -threshold 5) - -include_directories(${CMAKE_CURRENT_SOURCE_DIR}) - -# defines -add_definitions(-DQT_NO_CAST_TO_ASCII) -# Fast concatenation (Qt >= 4.6) -add_definitions(-DQT_USE_FAST_CONCATENATION -DQT_USE_FAST_OPERATOR_PLUS) -if (WIN32) - add_definitions(-DNOMINMAX) -endif (WIN32) - -if (NOT GUI) - add_definitions(-DDISABLE_GUI -DDISABLE_COUNTRIES_RESOLUTION) -endif (NOT GUI) - -if (NOT WEBUI) - add_definitions(-DDISABLE_WEBUI) -endif (NOT WEBUI) - -if (STACKTRACE_WIN) - add_definitions(-DSTACKTRACE_WIN) -endif(STACKTRACE_WIN) -# nogui { -# TARGET = qbittorrent-nox -# } else { -# CONFIG(static) { -# DEFINES += QBT_STATIC_QT -# QTPLUGIN += qico -# } -# TARGET = qbittorrent -# } - -if (UNIX AND NOT APPLE) - add_compile_options(-Wformat -Wformat-security) -endif () - -if (CMAKE_BUILD_TYPE STREQUAL "Debug") - message(STATUS "Project is built in DEBUG mode.") -else (CMAKE_BUILD_TYPE STREQUAL "Debug") - message(STATUS "Project is built in RELEASE mode.") - message(STATUS "Disabling debug output.") - add_definitions(-DQT_NO_DEBUG_OUTPUT) -endif (CMAKE_BUILD_TYPE STREQUAL "Debug") - -set(QBT_USE_GUI ${GUI}) -set(QBT_USE_WEBUI ${WEBUI}) - -configure_file(config.h.cmakein ${CMAKE_CURRENT_BINARY_DIR}/config.h) - -if (SYSTEM_QTSINGLEAPPLICATION) - find_package(QtSingleApplication REQUIRED) -else (SYSTEM_QTSINGLEAPPLICATION) - add_subdirectory(app/qtsingleapplication) -endif (SYSTEM_QTSINGLEAPPLICATION) - -add_subdirectory(app) -add_subdirectory(base) - -if (GUI) - add_subdirectory(gui) -endif (GUI) - -if (WEBUI) - add_subdirectory(webui) -endif (WEBUI) - diff --git a/src/app/CMakeLists.txt b/src/app/CMakeLists.txt deleted file mode 100644 index bb5ea43e3..000000000 --- a/src/app/CMakeLists.txt +++ /dev/null @@ -1,191 +0,0 @@ -project(qbt_executable) -include_directories(${CMAKE_CURRENT_BINARY_DIR}) - -set(QBT_APP_HEADERS -application.h -cmdoptions.h -filelogger.h -) - -set(QBT_APP_SOURCES -application.cpp -cmdoptions.cpp -filelogger.cpp -main.cpp -) - -# translations -file(GLOB QBT_TS_FILES ../lang/*.ts) -get_filename_component(QBT_QM_FILES_BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/../lang" ABSOLUTE) -set_source_files_properties(${QBT_TS_FILES} PROPERTIES OUTPUT_LOCATION "${QBT_QM_FILES_BINARY_DIR}") - -find_package(Qt5 COMPONENTS LinguistTools REQUIRED) -qt5_add_translation(QBT_QM_FILES ${QBT_TS_FILES}) - -get_filename_component(_lang_qrc_src "${CMAKE_CURRENT_SOURCE_DIR}/../lang.qrc" ABSOLUTE) -get_filename_component(_lang_qrc_dst "${CMAKE_CURRENT_BINARY_DIR}/../lang.qrc" ABSOLUTE) -get_filename_component(_lang_qrc_dst_dir "${CMAKE_CURRENT_BINARY_DIR}/../" ABSOLUTE) - -message(STATUS "copying ${_lang_qrc_src} -> ${_lang_qrc_dst}") -file(COPY ${_lang_qrc_src} DESTINATION ${_lang_qrc_dst_dir}) - -set_source_files_properties("${_lang_qrc_dst}" PROPERTIES GENERATED True) -foreach(qm_file ${QBT_QM_FILES}) - set_source_files_properties("${_lang_qrc_dst}" PROPERTIES OBJECT_DEPENDS ${qm_file}) -endforeach() - -set(QBT_APP_RESOURCES -../icons.qrc -../searchengine.qrc -"${_lang_qrc_dst}" -) - -# With AUTORCC rcc is ran by cmake before language files are generated, -# and thus we call rcc explicitly -qt5_add_resources(QBT_APP_RESOURCE_SOURCE ${QBT_APP_RESOURCES}) - -if (WIN32) - if (MINGW) - list (APPEND QBT_APP_SOURCES ../qbittorrent_mingw.rc) - else (MINGW) - list (APPEND QBT_APP_SOURCES ../qbittorrent.rc) - endif (MINGW) - list(APPEND QBT_APP_SOURCES ../qbittorrent.exe.manifest) -endif (WIN32) - -if (UNIX) - list(APPEND QBT_APP_HEADERS stacktrace.h) -endif (UNIX) - -if (STACKTRACE_WIN) - list(APPEND QBT_APP_HEADERS stacktrace_win.h) - if (GUI) - list(APPEND QBT_APP_HEADERS stacktrace_win_dlg.h) - endif (GUI) -endif (STACKTRACE_WIN) - -# usesystemqtsingleapplication { -# nogui { -# CONFIG += qtsinglecoreapplication -# } else { -# CONFIG += qtsingleapplication -# } -# } else { -# nogui { -# include(qtsingleapplication/qtsinglecoreapplication.pri) -# } else { -# include(qtsingleapplication/qtsingleapplication.pri) -# } -# } - -# upgrade code -list(APPEND QBT_APP_HEADERS upgrade.h) -list(APPEND QBT_TARGET_LIBRARIES qbt_base) - -if (GUI) - list(APPEND QBT_TARGET_LIBRARIES qbt_searchengine qbt_gui) - include_directories(../gui - ${CMAKE_CURRENT_BINARY_DIR}/../gui - ) -endif (GUI) - -if (WEBUI) - list(APPEND QBT_TARGET_LIBRARIES qbt_webui) -endif (WEBUI) - -# we have to include resources into the bundle -if (APPLE) - set(OSX_RES_SRC_DIR "${qBittorrent_SOURCE_DIR}/dist/mac") - list(APPEND QBT_APP_RESOURCE_SOURCE - "${OSX_RES_SRC_DIR}/qt.conf" - "${OSX_RES_SRC_DIR}/qBitTorrentDocument.icns" - "${OSX_RES_SRC_DIR}/qbittorrent_mac.icns") - set_source_files_properties( - "${OSX_RES_SRC_DIR}/qt.conf" - "${OSX_RES_SRC_DIR}/qBitTorrentDocument.icns" - "${OSX_RES_SRC_DIR}/qbittorrent_mac.icns" - PROPERTIES - MACOSX_PACKAGE_LOCATION Resources) - set(QT_TR_DIR "${qBittorrent_SOURCE_DIR}/dist/qt-translations") - set(QT_TRANSLATIONS - ${QT_TR_DIR}/qt_ar.qm - ${QT_TR_DIR}/qt_bg.qm - ${QT_TR_DIR}/qt_ca.qm - ${QT_TR_DIR}/qt_cs.qm - ${QT_TR_DIR}/qt_da.qm - ${QT_TR_DIR}/qt_de.qm - ${QT_TR_DIR}/qt_es.qm - ${QT_TR_DIR}/qt_eu.qm - ${QT_TR_DIR}/qt_fi.qm - ${QT_TR_DIR}/qt_fr.qm - ${QT_TR_DIR}/qt_gl.qm - ${QT_TR_DIR}/qt_he.qm - ${QT_TR_DIR}/qt_hu.qm - ${QT_TR_DIR}/qt_it.qm - ${QT_TR_DIR}/qt_ja.qm - ${QT_TR_DIR}/qt_ko.qm - ${QT_TR_DIR}/qt_lt.qm - ${QT_TR_DIR}/qt_nl.qm - ${QT_TR_DIR}/qt_pl.qm - ${QT_TR_DIR}/qt_pt.qm - ${QT_TR_DIR}/qt_pt_BR.qm - ${QT_TR_DIR}/qt_ru.qm - ${QT_TR_DIR}/qt_sk.qm - ${QT_TR_DIR}/qt_sv.qm - ${QT_TR_DIR}/qt_tr.qm - ${QT_TR_DIR}/qt_uk.qm - ${QT_TR_DIR}/qt_zh_CN.qm - ${QT_TR_DIR}/qt_zh_TW.qm - ) - list(APPEND QBT_APP_RESOURCE_SOURCE ${QT_TRANSLATIONS}) - set_source_files_properties(${QT_TRANSLATIONS} - PROPERTIES MACOSX_PACKAGE_LOCATION translations) -endif (APPLE) - -add_executable(qBittorrent ${QBT_APP_HEADERS} ${QBT_APP_SOURCES} ${QBT_QM_FILES} ${QBT_APP_RESOURCE_SOURCE}) -if (GUI) - set_target_properties(qBittorrent - PROPERTIES - OUTPUT_NAME qbittorrent - WIN32_EXECUTABLE True - ) -else (GUI) - set_target_properties(qBittorrent - PROPERTIES - OUTPUT_NAME qbittorrent-nox - ) -endif (GUI) - -set_target_properties(qBittorrent - PROPERTIES - AUTOUIC True - AUTORCC True - MACOSX_BUNDLE True -) - -get_target_property(QBT_EXECUTABLE_NAME qBittorrent OUTPUT_NAME) - -target_link_libraries(qBittorrent ${QBT_TARGET_LIBRARIES} QtSingleApplication::QtSingleApplication) - -if (APPLE) - set(qbt_BUNDLE_NAME ${QBT_EXECUTABLE_NAME}) - -# substitute @EXECUTABLE@ in dist/mac/Info.plist - set(EXECUTABLE ${qbt_BUNDLE_NAME}) - configure_file(${qBittorrent_SOURCE_DIR}/dist/mac/Info.plist ${qBittorrent_BINARY_DIR}/dist/mac/Info.plist @ONLY) - - set_target_properties(qBittorrent PROPERTIES - MACOSX_BUNDLE_BUNDLE_NAME "${qbt_BUNDLE_NAME}" - MACOSX_BUNDLE_INFO_PLIST ${qBittorrent_BINARY_DIR}/dist/mac/Info.plist - ) -endif (APPLE) - -# installation -install(TARGETS qBittorrent - RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} - BUNDLE DESTINATION . - COMPONENT runtime) - -if (GUI AND APPLE) - include(bundle) -endif (GUI AND APPLE) diff --git a/src/app/app.pri b/src/app/app.pri deleted file mode 100644 index 8c8c7d870..000000000 --- a/src/app/app.pri +++ /dev/null @@ -1,38 +0,0 @@ -INCLUDEPATH += $$PWD - -usesystemqtsingleapplication { - nogui { - CONFIG += qtsinglecoreapplication - } else { - CONFIG += qtsingleapplication - } -} else { - nogui { - include(qtsingleapplication/qtsinglecoreapplication.pri) - } else { - include(qtsingleapplication/qtsingleapplication.pri) - } -} - -HEADERS += \ - $$PWD/application.h \ - $$PWD/cmdoptions.h \ - $$PWD/filelogger.h - -SOURCES += \ - $$PWD/application.cpp \ - $$PWD/cmdoptions.cpp \ - $$PWD/filelogger.cpp \ - $$PWD/main.cpp - -unix: HEADERS += $$PWD/stacktrace.h -strace_win { - HEADERS += $$PWD/stacktrace_win.h - !nogui { - HEADERS += $$PWD/stacktrace_win_dlg.h - FORMS += $$PWD/stacktrace_win_dlg.ui - } -} - -# upgrade code -HEADERS += $$PWD/upgrade.h diff --git a/src/app/application.cpp b/src/app/application.cpp deleted file mode 100644 index 7052051ff..000000000 --- a/src/app/application.cpp +++ /dev/null @@ -1,723 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2015 Vladimir Golovnev - * Copyright (C) 2006 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. - */ - -#include -#include -#include -#include -#include -#include -#include - -#ifndef DISABLE_GUI -#include "gui/guiiconprovider.h" -#ifdef Q_OS_WIN -#include -#include -#include -#endif // Q_OS_WIN -#ifdef Q_OS_MAC -#include -#include -#include -#endif // Q_OS_MAC -#include "mainwindow.h" -#include "addnewtorrentdialog.h" -#include "shutdownconfirmdlg.h" -#else // DISABLE_GUI -#include -#endif // DISABLE_GUI - -#ifndef DISABLE_WEBUI -#include "webui/webui.h" -#endif - -#include "application.h" -#include "filelogger.h" -#include "base/logger.h" -#include "base/preferences.h" -#include "base/settingsstorage.h" -#include "base/profile.h" -#include "base/utils/fs.h" -#include "base/utils/misc.h" -#include "base/iconprovider.h" -#include "base/scanfoldersmodel.h" -#include "base/net/smtp.h" -#include "base/net/downloadmanager.h" -#include "base/net/geoipmanager.h" -#include "base/net/proxyconfigurationmanager.h" -#include "base/bittorrent/session.h" -#include "base/bittorrent/torrenthandle.h" -#include "base/rss/rss_autodownloader.h" -#include "base/rss/rss_session.h" - -namespace -{ -#define SETTINGS_KEY(name) "Application/" name - - // FileLogger properties keys -#define FILELOGGER_SETTINGS_KEY(name) SETTINGS_KEY("FileLogger/") name - const QString KEY_FILELOGGER_ENABLED = FILELOGGER_SETTINGS_KEY("Enabled"); - const QString KEY_FILELOGGER_PATH = FILELOGGER_SETTINGS_KEY("Path"); - const QString KEY_FILELOGGER_BACKUP = FILELOGGER_SETTINGS_KEY("Backup"); - const QString KEY_FILELOGGER_DELETEOLD = FILELOGGER_SETTINGS_KEY("DeleteOld"); - const QString KEY_FILELOGGER_MAXSIZE = FILELOGGER_SETTINGS_KEY("MaxSize"); - const QString KEY_FILELOGGER_AGE = FILELOGGER_SETTINGS_KEY("Age"); - const QString KEY_FILELOGGER_AGETYPE = FILELOGGER_SETTINGS_KEY("AgeType"); - - //just a shortcut - inline SettingsStorage *settings() { return SettingsStorage::instance(); } - - const QString LOG_FOLDER("logs"); - const char PARAMS_SEPARATOR[] = "|"; - - const QString DEFAULT_PORTABLE_MODE_PROFILE_DIR = QLatin1String("profile"); -} - -Application::Application(const QString &id, int &argc, char **argv) - : BaseApplication(id, argc, argv) - , m_running(false) - , m_shutdownAct(ShutdownDialogAction::Exit) - , m_commandLineArgs(parseCommandLine(this->arguments())) -{ - qRegisterMetaType("Log::Msg"); - - setApplicationName("qBittorrent"); - validateCommandLineParameters(); - - QString profileDir = m_commandLineArgs.portableMode - ? QDir(QCoreApplication::applicationDirPath()).absoluteFilePath(DEFAULT_PORTABLE_MODE_PROFILE_DIR) - : m_commandLineArgs.profileDir; - - Profile::initialize(profileDir, m_commandLineArgs.configurationName, - m_commandLineArgs.relativeFastresumePaths || m_commandLineArgs.portableMode); - - Logger::initInstance(); - SettingsStorage::initInstance(); - Preferences::initInstance(); - - if (m_commandLineArgs.webUiPort > 0) // it will be -1 when user did not set any value - Preferences::instance()->setWebUiPort(m_commandLineArgs.webUiPort); - - setApplicationName("qBittorrent"); - initializeTranslation(); - -#if !defined(DISABLE_GUI) - setAttribute(Qt::AA_UseHighDpiPixmaps, true); // opt-in to the high DPI pixmap support - setQuitOnLastWindowClosed(false); -#endif - -#if defined(Q_OS_WIN) && !defined(DISABLE_GUI) - connect(this, SIGNAL(commitDataRequest(QSessionManager &)), this, SLOT(shutdownCleanup(QSessionManager &)), Qt::DirectConnection); -#endif - - connect(this, SIGNAL(messageReceived(const QString &)), SLOT(processMessage(const QString &))); - connect(this, SIGNAL(aboutToQuit()), SLOT(cleanup())); - - if (isFileLoggerEnabled()) - m_fileLogger = new FileLogger(fileLoggerPath(), isFileLoggerBackup(), fileLoggerMaxSize(), isFileLoggerDeleteOld(), fileLoggerAge(), static_cast(fileLoggerAgeType())); - - Logger::instance()->addMessage(tr("qBittorrent %1 started", "qBittorrent v3.2.0alpha started").arg(QBT_VERSION)); -} - -#ifndef DISABLE_GUI -QPointer Application::mainWindow() -{ - return m_window; -} -#endif - -const QBtCommandLineParameters &Application::commandLineArgs() const -{ - return m_commandLineArgs; -} - -bool Application::isFileLoggerEnabled() const -{ - return settings()->loadValue(KEY_FILELOGGER_ENABLED, true).toBool(); -} - -void Application::setFileLoggerEnabled(bool value) -{ - if (value && !m_fileLogger) - m_fileLogger = new FileLogger(fileLoggerPath(), isFileLoggerBackup(), fileLoggerMaxSize(), isFileLoggerDeleteOld(), fileLoggerAge(), static_cast(fileLoggerAgeType())); - else if (!value) - delete m_fileLogger; - settings()->storeValue(KEY_FILELOGGER_ENABLED, value); -} - -QString Application::fileLoggerPath() const -{ - return settings()->loadValue(KEY_FILELOGGER_PATH, - QVariant(specialFolderLocation(SpecialFolder::Data) + LOG_FOLDER)).toString(); -} - -void Application::setFileLoggerPath(const QString &path) -{ - if (m_fileLogger) - m_fileLogger->changePath(path); - settings()->storeValue(KEY_FILELOGGER_PATH, path); -} - -bool Application::isFileLoggerBackup() const -{ - return settings()->loadValue(KEY_FILELOGGER_BACKUP, true).toBool(); -} - -void Application::setFileLoggerBackup(bool value) -{ - if (m_fileLogger) - m_fileLogger->setBackup(value); - settings()->storeValue(KEY_FILELOGGER_BACKUP, value); -} - -bool Application::isFileLoggerDeleteOld() const -{ - return settings()->loadValue(KEY_FILELOGGER_DELETEOLD, true).toBool(); -} - -void Application::setFileLoggerDeleteOld(bool value) -{ - if (value && m_fileLogger) - m_fileLogger->deleteOld(fileLoggerAge(), static_cast(fileLoggerAgeType())); - settings()->storeValue(KEY_FILELOGGER_DELETEOLD, value); -} - -int Application::fileLoggerMaxSize() const -{ - int val = settings()->loadValue(KEY_FILELOGGER_MAXSIZE, 10).toInt(); - if (val < 1) - return 1; - if (val > 1000) - return 1000; - return val; -} - -void Application::setFileLoggerMaxSize(const int value) -{ - if (m_fileLogger) - m_fileLogger->setMaxSize(value); - settings()->storeValue(KEY_FILELOGGER_MAXSIZE, std::min(std::max(value, 1), 1000)); -} - -int Application::fileLoggerAge() const -{ - int val = settings()->loadValue(KEY_FILELOGGER_AGE, 6).toInt(); - if (val < 1) - return 1; - if (val > 365) - return 365; - return val; -} - -void Application::setFileLoggerAge(const int value) -{ - settings()->storeValue(KEY_FILELOGGER_AGE, std::min(std::max(value, 1), 365)); -} - -int Application::fileLoggerAgeType() const -{ - int val = settings()->loadValue(KEY_FILELOGGER_AGETYPE, 1).toInt(); - return (val < 0 || val > 2) ? 1 : val; -} - -void Application::setFileLoggerAgeType(const int value) -{ - settings()->storeValue(KEY_FILELOGGER_AGETYPE, (value < 0 || value > 2) ? 1 : value); -} - -void Application::processMessage(const QString &message) -{ - QStringList params = message.split(QLatin1String(PARAMS_SEPARATOR), QString::SkipEmptyParts); - // If Application is not running (i.e., other - // components are not ready) store params - if (m_running) - processParams(params); - else - m_paramsQueue.append(params); -} - -void Application::runExternalProgram(BitTorrent::TorrentHandle *const torrent) const -{ - QString program = Preferences::instance()->getAutoRunProgram(); - program.replace("%N", torrent->name()); - program.replace("%L", torrent->category()); - program.replace("%F", Utils::Fs::toNativePath(torrent->contentPath())); - program.replace("%R", Utils::Fs::toNativePath(torrent->rootPath())); - program.replace("%D", Utils::Fs::toNativePath(torrent->savePath())); - program.replace("%C", QString::number(torrent->filesCount())); - program.replace("%Z", QString::number(torrent->totalSize())); - program.replace("%T", torrent->currentTracker()); - program.replace("%I", torrent->hash()); - - Logger *logger = Logger::instance(); - logger->addMessage(tr("Torrent: %1, running external program, command: %2").arg(torrent->name()).arg(program)); - -#if defined(Q_OS_UNIX) - QProcess::startDetached(QLatin1String("/bin/sh"), {QLatin1String("-c"), program}); -#elif defined(Q_OS_WIN) // test cmd: `echo "%F" > "c:\ab ba.txt"` - program.prepend(QLatin1String("\"")).append(QLatin1String("\"")); - program.prepend(Utils::Misc::windowsSystemPath() + QLatin1String("\\cmd.exe /C ")); - const int cmdMaxLength = 32768; // max length (incl. terminate char) for `lpCommandLine` in `CreateProcessW()` - if ((program.size() + 1) > cmdMaxLength) { - logger->addMessage(tr("Torrent: %1, run external program command too long (length > %2), execution failed.").arg(torrent->name()).arg(cmdMaxLength), Log::CRITICAL); - return; - } - - STARTUPINFOW si = {0}; - si.cb = sizeof(si); - PROCESS_INFORMATION pi = {0}; - - WCHAR *arg = new WCHAR[program.size() + 1]; - program.toWCharArray(arg); - arg[program.size()] = L'\0'; - if (CreateProcessW(NULL, arg, NULL, NULL, FALSE, CREATE_NO_WINDOW, NULL, NULL, &si, &pi)) { - CloseHandle(pi.hProcess); - CloseHandle(pi.hThread); - } - delete[] arg; -#else - QProcess::startDetached(program); -#endif -} - -void Application::sendNotificationEmail(BitTorrent::TorrentHandle *const torrent) -{ - // Prepare mail content - QString content = QObject::tr("Torrent name: %1").arg(torrent->name()) + "\n"; - content += QObject::tr("Torrent size: %1").arg(Utils::Misc::friendlyUnit(torrent->wantedSize())) + "\n"; - content += QObject::tr("Save path: %1").arg(torrent->savePath()) + "\n\n"; - content += QObject::tr("The torrent was downloaded in %1.", - "The torrent was downloaded in 1 hour and 20 seconds") - .arg(Utils::Misc::userFriendlyDuration(torrent->activeTime())) + "\n\n\n"; - content += QObject::tr("Thank you for using qBittorrent.") + "\n"; - - // Send the notification email - Net::Smtp *sender = new Net::Smtp; - sender->sendMail("notification@qbittorrent.org", - Preferences::instance()->getMailNotificationEmail(), - QObject::tr("[qBittorrent] '%1' has finished downloading").arg(torrent->name()), - content); -} - -void Application::torrentFinished(BitTorrent::TorrentHandle *const torrent) -{ - Preferences *const pref = Preferences::instance(); - - // AutoRun program - if (pref->isAutoRunEnabled()) - runExternalProgram(torrent); - - // Mail notification - if (pref->isMailNotificationEnabled()) { - Logger::instance()->addMessage(tr("Torrent: %1, sending mail notification").arg(torrent->name())); - sendNotificationEmail(torrent); - } -} - -void Application::allTorrentsFinished() -{ - Preferences *const pref = Preferences::instance(); - bool isExit = pref->shutdownqBTWhenDownloadsComplete(); - bool isShutdown = pref->shutdownWhenDownloadsComplete(); - bool isSuspend = pref->suspendWhenDownloadsComplete(); - bool isHibernate = pref->hibernateWhenDownloadsComplete(); - - bool haveAction = isExit || isShutdown || isSuspend || isHibernate; - if (!haveAction) return; - - ShutdownDialogAction action = ShutdownDialogAction::Exit; - if (isSuspend) - action = ShutdownDialogAction::Suspend; - else if (isHibernate) - action = ShutdownDialogAction::Hibernate; - else if (isShutdown) - action = ShutdownDialogAction::Shutdown; - -#ifndef DISABLE_GUI - // ask confirm - if ((action == ShutdownDialogAction::Exit) && (pref->dontConfirmAutoExit())) { - // do nothing & skip confirm - } - else { - if (!ShutdownConfirmDlg::askForConfirmation(m_window, action)) return; - } -#endif // DISABLE_GUI - - // Actually shut down - if (action != ShutdownDialogAction::Exit) { - qDebug("Preparing for auto-shutdown because all downloads are complete!"); - // Disabling it for next time - pref->setShutdownWhenDownloadsComplete(false); - pref->setSuspendWhenDownloadsComplete(false); - pref->setHibernateWhenDownloadsComplete(false); - // Make sure preferences are synced before exiting - m_shutdownAct = action; - } - - qDebug("Exiting the application"); - exit(); -} - -bool Application::sendParams(const QStringList ¶ms) -{ - return sendMessage(params.join(QLatin1String(PARAMS_SEPARATOR))); -} - -// As program parameters, we can get paths or urls. -// This function parse the parameters and call -// the right addTorrent function, considering -// the parameter type. -void Application::processParams(const QStringList ¶ms) -{ -#ifndef DISABLE_GUI - if (params.isEmpty()) { - m_window->activate(); // show UI - return; - } -#endif - BitTorrent::AddTorrentParams torrentParams; - TriStateBool skipTorrentDialog; - - foreach (QString param, params) { - param = param.trimmed(); - - // Process strings indicating options specified by the user. - - if (param.startsWith(QLatin1String("@savePath="))) { - torrentParams.savePath = param.mid(10); - continue; - } - - if (param.startsWith(QLatin1String("@addPaused="))) { - torrentParams.addPaused = param.mid(11).toInt() ? TriStateBool::True : TriStateBool::False; - continue; - } - - if (param == QLatin1String("@skipChecking")) { - torrentParams.skipChecking = true; - continue; - } - - if (param.startsWith(QLatin1String("@category="))) { - torrentParams.category = param.mid(10); - continue; - } - - if (param == QLatin1String("@sequential")) { - torrentParams.sequential = true; - continue; - } - - if (param == QLatin1String("@firstLastPiecePriority")) { - torrentParams.firstLastPiecePriority = true; - continue; - } - - if (param.startsWith(QLatin1String("@skipDialog="))) { - skipTorrentDialog = param.mid(12).toInt() ? TriStateBool::True : TriStateBool::False; - continue; - } - -#ifndef DISABLE_GUI - // There are two circumstances in which we want to show the torrent - // dialog. One is when the application settings specify that it should - // be shown and skipTorrentDialog is undefined. The other is when - // skipTorrentDialog is false, meaning that the application setting - // should be overridden. - const bool showDialogForThisTorrent = - ((AddNewTorrentDialog::isEnabled() && skipTorrentDialog == TriStateBool::Undefined) - || skipTorrentDialog == TriStateBool::False); - if (showDialogForThisTorrent) - AddNewTorrentDialog::show(param, torrentParams, m_window); - else -#endif - BitTorrent::Session::instance()->addTorrent(param, torrentParams); - } -} - -int Application::exec(const QStringList ¶ms) -{ - Net::ProxyConfigurationManager::initInstance(); - Net::DownloadManager::initInstance(); -#ifdef DISABLE_GUI - IconProvider::initInstance(); -#else - GuiIconProvider::initInstance(); -#endif - - BitTorrent::Session::initInstance(); - connect(BitTorrent::Session::instance(), SIGNAL(torrentFinished(BitTorrent::TorrentHandle *const)), SLOT(torrentFinished(BitTorrent::TorrentHandle *const))); - connect(BitTorrent::Session::instance(), SIGNAL(allTorrentsFinished()), SLOT(allTorrentsFinished()), Qt::QueuedConnection); - -#ifndef DISABLE_COUNTRIES_RESOLUTION - Net::GeoIPManager::initInstance(); -#endif - ScanFoldersModel::initInstance(this); - -#ifndef DISABLE_WEBUI - m_webui = new WebUI; -#endif - - new RSS::Session; // create RSS::Session singleton - new RSS::AutoDownloader; // create RSS::AutoDownloader singleton - -#ifdef DISABLE_GUI -#ifndef DISABLE_WEBUI - Preferences* const pref = Preferences::instance(); - // Display some information to the user - std::cout << std::endl << "******** " << qPrintable(tr("Information")) << " ********" << std::endl; - 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() == "f6fdffe48c908deb0f4c3bd36c032e72") { - 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; - } -#endif // DISABLE_WEBUI -#else - m_window = new MainWindow; -#endif // DISABLE_GUI - - m_running = true; - m_paramsQueue = params + m_paramsQueue; - if (!m_paramsQueue.isEmpty()) { - processParams(m_paramsQueue); - m_paramsQueue.clear(); - } - - // Now UI is ready to process signals from Session - BitTorrent::Session::instance()->startUpTorrents(); - - return BaseApplication::exec(); -} - -#ifndef DISABLE_GUI -#ifdef Q_OS_WIN -bool Application::isRunning() -{ - bool running = BaseApplication::isRunning(); - QSharedMemory *sharedMem = new QSharedMemory(id() + QLatin1String("-shared-memory-key"), this); - if (!running) { - // First instance creates shared memory and store PID - if (sharedMem->create(sizeof(DWORD)) && sharedMem->lock()) { - *(static_cast(sharedMem->data())) = ::GetCurrentProcessId(); - sharedMem->unlock(); - } - } - else { - // Later instances attach to shared memory and retrieve PID - if (sharedMem->attach() && sharedMem->lock()) { - ::AllowSetForegroundWindow(*(static_cast(sharedMem->data()))); - sharedMem->unlock(); - } - } - - if (!sharedMem->isAttached()) - qWarning() << "Failed to initialize shared memory: " << sharedMem->errorString(); - - return running; -} -#endif // Q_OS_WIN - -#ifdef Q_OS_MAC -bool Application::event(QEvent *ev) -{ - if (ev->type() == QEvent::FileOpen) { - QString path = static_cast(ev)->file(); - if (path.isEmpty()) - // Get the url instead - path = static_cast(ev)->url().toString(); - qDebug("Received a mac file open event: %s", qPrintable(path)); - if (m_running) - processParams(QStringList(path)); - else - m_paramsQueue.append(path); - return true; - } - else { - return BaseApplication::event(ev); - } -} -#endif // Q_OS_MAC - -bool Application::notify(QObject *receiver, QEvent *event) -{ - try { - return QApplication::notify(receiver, event); - } - catch (const std::exception &e) { - qCritical() << "Exception thrown:" << e.what() << ", receiver: " << receiver->objectName(); - receiver->dumpObjectInfo(); - } - - return false; -} -#endif // DISABLE_GUI - -void Application::initializeTranslation() -{ - Preferences* const pref = Preferences::instance(); - // Load translation - QString localeStr = pref->getLocale(); - - if (m_qtTranslator.load(QString::fromUtf8("qtbase_") + localeStr, QLibraryInfo::location(QLibraryInfo::TranslationsPath)) || - m_qtTranslator.load(QString::fromUtf8("qt_") + localeStr, QLibraryInfo::location(QLibraryInfo::TranslationsPath))) - qDebug("Qt %s locale recognized, using translation.", qPrintable(localeStr)); - else - qDebug("Qt %s locale unrecognized, using default (en).", qPrintable(localeStr)); - - installTranslator(&m_qtTranslator); - - if (m_translator.load(QString::fromUtf8(":/lang/qbittorrent_") + localeStr)) - qDebug("%s locale recognized, using translation.", qPrintable(localeStr)); - else - qDebug("%s locale unrecognized, using default (en).", qPrintable(localeStr)); - installTranslator(&m_translator); - -#ifndef DISABLE_GUI - if (localeStr.startsWith("ar") || localeStr.startsWith("he")) { - qDebug("Right to Left mode"); - setLayoutDirection(Qt::RightToLeft); - } - else { - setLayoutDirection(Qt::LeftToRight); - } -#endif -} - -#if (!defined(DISABLE_GUI) && defined(Q_OS_WIN)) -void Application::shutdownCleanup(QSessionManager &manager) -{ - Q_UNUSED(manager); - - // This is only needed for a special case on Windows XP. - // (but is called for every Windows version) - // If a process takes too much time to exit during OS - // shutdown, the OS presents a dialog to the user. - // That dialog tells the user that qbt is blocking the - // shutdown, it shows a progress bar and it offers - // a "Terminate Now" button for the user. However, - // after the progress bar has reached 100% another button - // is offered to the user reading "Cancel". With this the - // user can cancel the **OS** shutdown. If we don't do - // the cleanup by handling the commitDataRequest() signal - // and the user clicks "Cancel", it will result in qbt being - // killed and the shutdown proceeding instead. Apparently - // aboutToQuit() is emitted too late in the shutdown process. - cleanup(); - - // According to the qt docs we shouldn't call quit() inside a slot. - // aboutToQuit() is never emitted if the user hits "Cancel" in - // the above dialog. - QTimer::singleShot(0, qApp, SLOT(quit())); -} -#endif - -void Application::cleanup() -{ -#ifndef DISABLE_GUI -#ifdef Q_OS_WIN - // cleanup() can be called multiple times during shutdown. We only need it once. - static QAtomicInt alreadyDone; - if (!alreadyDone.testAndSetAcquire(0, 1)) - return; -#endif // Q_OS_WIN - - // Hide the window and not leave it on screen as - // unresponsive. Also for Windows take the WinId - // after it's hidden, because hide() may cause a - // WinId change. - m_window->hide(); - -#ifdef Q_OS_WIN - typedef BOOL (WINAPI *PSHUTDOWNBRCREATE)(HWND, LPCWSTR); - PSHUTDOWNBRCREATE shutdownBRCreate = (PSHUTDOWNBRCREATE)::GetProcAddress(::GetModuleHandleW(L"User32.dll"), "ShutdownBlockReasonCreate"); - // Only available on Vista+ - if (shutdownBRCreate) - shutdownBRCreate((HWND)m_window->effectiveWinId(), tr("Saving torrent progress...").toStdWString().c_str()); -#endif // Q_OS_WIN - - // Do manual cleanup in MainWindow to force widgets - // to save their Preferences, stop all timers and - // delete as many widgets as possible to leave only - // a 'shell' MainWindow. - // We need a valid window handle for Windows Vista+ - // otherwise the system shutdown will continue even - // though we created a ShutdownBlockReason - m_window->cleanup(); - -#endif // DISABLE_GUI - -#ifndef DISABLE_WEBUI - delete m_webui; -#endif - - delete RSS::AutoDownloader::instance(); - delete RSS::Session::instance(); - - ScanFoldersModel::freeInstance(); - BitTorrent::Session::freeInstance(); -#ifndef DISABLE_COUNTRIES_RESOLUTION - Net::GeoIPManager::freeInstance(); -#endif - Net::DownloadManager::freeInstance(); - Net::ProxyConfigurationManager::freeInstance(); - Preferences::freeInstance(); - SettingsStorage::freeInstance(); - delete m_fileLogger; - Logger::freeInstance(); - IconProvider::freeInstance(); - Utils::Fs::removeDirRecursive(Utils::Fs::tempPath()); - -#ifndef DISABLE_GUI -#ifdef Q_OS_WIN - typedef BOOL (WINAPI *PSHUTDOWNBRDESTROY)(HWND); - PSHUTDOWNBRDESTROY shutdownBRDestroy = (PSHUTDOWNBRDESTROY)::GetProcAddress(::GetModuleHandleW(L"User32.dll"), "ShutdownBlockReasonDestroy"); - // Only available on Vista+ - if (shutdownBRDestroy) - shutdownBRDestroy((HWND)m_window->effectiveWinId()); -#endif // Q_OS_WIN - delete m_window; -#endif // DISABLE_GUI - - if (m_shutdownAct != ShutdownDialogAction::Exit) { - qDebug() << "Sending computer shutdown/suspend/hibernate signal..."; - Utils::Misc::shutdownComputer(m_shutdownAct); - } -} - -void Application::validateCommandLineParameters() -{ - if (m_commandLineArgs.portableMode && !m_commandLineArgs.profileDir.isEmpty()) - throw CommandLineParameterError(tr("Portable mode and explicit profile directory options are mutually exclusive")); - - if (m_commandLineArgs.portableMode && m_commandLineArgs.relativeFastresumePaths) - Logger::instance()->addMessage(tr("Portable mode implies relative fastresume"), Log::WARNING); -} diff --git a/src/app/application.h b/src/app/application.h deleted file mode 100644 index f698a5e54..000000000 --- a/src/app/application.h +++ /dev/null @@ -1,152 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2015 Vladimir Golovnev - * Copyright (C) 2006 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. - */ - -#ifndef APPLICATION_H -#define APPLICATION_H - -#include -#include -#include - -#ifndef DISABLE_GUI -#include "qtsingleapplication.h" -typedef QtSingleApplication BaseApplication; -class MainWindow; - -#ifdef Q_OS_WIN -QT_BEGIN_NAMESPACE -class QSessionManager; -QT_END_NAMESPACE -#endif // Q_OS_WIN - -#else -#include "qtsinglecoreapplication.h" -typedef QtSingleCoreApplication BaseApplication; -#endif - -#include "base/utils/misc.h" -#include "cmdoptions.h" - -#ifndef DISABLE_WEBUI -class WebUI; -#endif - -class FileLogger; - -namespace BitTorrent -{ - class TorrentHandle; -} - -namespace RSS -{ - class Session; - class AutoDownloader; -} - -class Application : public BaseApplication -{ - Q_OBJECT - -public: - Application(const QString &id, int &argc, char **argv); - - #if (defined(Q_OS_WIN) && !defined(DISABLE_GUI)) - bool isRunning(); -#endif - int exec(const QStringList ¶ms); - bool sendParams(const QStringList ¶ms); - -#ifndef DISABLE_GUI - QPointer mainWindow(); -#endif - - const QBtCommandLineParameters &commandLineArgs() const; - - // FileLogger properties - bool isFileLoggerEnabled() const; - void setFileLoggerEnabled(bool value); - QString fileLoggerPath() const; - void setFileLoggerPath(const QString &path); - bool isFileLoggerBackup() const; - void setFileLoggerBackup(bool value); - bool isFileLoggerDeleteOld() const; - void setFileLoggerDeleteOld(bool value); - int fileLoggerMaxSize() const; - void setFileLoggerMaxSize(const int value); - int fileLoggerAge() const; - void setFileLoggerAge(const int value); - int fileLoggerAgeType() const; - void setFileLoggerAgeType(const int value); - -protected: -#ifndef DISABLE_GUI -#ifdef Q_OS_MAC - bool event(QEvent *); -#endif - bool notify(QObject* receiver, QEvent* event); -#endif - -private slots: - void processMessage(const QString &message); - void torrentFinished(BitTorrent::TorrentHandle *const torrent); - void allTorrentsFinished(); - void cleanup(); -#if (!defined(DISABLE_GUI) && defined(Q_OS_WIN)) - void shutdownCleanup(QSessionManager &manager); -#endif - -private: - bool m_running; - ShutdownDialogAction m_shutdownAct; - QBtCommandLineParameters m_commandLineArgs; - -#ifndef DISABLE_GUI - QPointer m_window; -#endif - -#ifndef DISABLE_WEBUI - QPointer m_webui; -#endif - - // FileLog - QPointer m_fileLogger; - - QTranslator m_qtTranslator; - QTranslator m_translator; - QStringList m_paramsQueue; - - void initializeTranslation(); - void processParams(const QStringList ¶ms); - void runExternalProgram(BitTorrent::TorrentHandle *const torrent) const; - void sendNotificationEmail(BitTorrent::TorrentHandle *const torrent); - void validateCommandLineParameters(); -}; - -#endif // APPLICATION_H diff --git a/src/app/cmdoptions.cpp b/src/app/cmdoptions.cpp deleted file mode 100644 index 87d46f821..000000000 --- a/src/app/cmdoptions.cpp +++ /dev/null @@ -1,587 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2016 Eugene Shalygin - * Copyright (C) 2014 Vladimir Golovnev - * Copyright (C) 2006 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 "cmdoptions.h" - -#include - -#include -#include -#include -#include - -#ifdef Q_OS_WIN -#include -#endif - -#include "base/utils/misc.h" -#include "base/utils/string.h" - -namespace -{ - const int USAGE_INDENTATION = 4; - const int USAGE_TEXT_COLUMN = 31; - const int WRAP_AT_COLUMN = 80; - - // Base option class. Encapsulates name operations. - class Option - { - protected: - constexpr Option(const char *name, char shortcut = 0) - : m_name {name} - , m_shortcut {shortcut} - { - } - - QString fullParameter() const - { - return QLatin1String("--") + QLatin1String(m_name); - } - - QString shortcutParameter() const - { - return QLatin1String("-") + QLatin1Char(m_shortcut); - } - - bool hasShortcut() const - { - return m_shortcut != 0; - } - - QString envVarName() const - { - return QLatin1String("QBT_") - + QString(QLatin1String(m_name)).toUpper().replace(QLatin1Char('-'), QLatin1Char('_')); - } - - public: - static QString padUsageText(const QString &usage) - { - QString res = QString(USAGE_INDENTATION, ' ') + usage; - - if ((USAGE_TEXT_COLUMN - usage.length() - 4) > 0) - return res + QString(USAGE_TEXT_COLUMN - usage.length() - 4, ' '); - else - return res; - } - - private: - const char *m_name; - const char m_shortcut; - }; - - // Boolean option. - class BoolOption: protected Option - { - public: - constexpr BoolOption(const char *name, char shortcut = 0) - : Option {name, shortcut} - { - } - - bool operator==(const QString &arg) const - { - return (hasShortcut() && ((arg.size() == 2) && (arg == shortcutParameter()))) - || (arg == fullParameter()); - } - - bool value(const QProcessEnvironment &env) const - { - QString val = env.value(envVarName()); - // we accept "1" and "true" (upper or lower cased) as boolean 'true' values - return (val == QLatin1String("1") || val.toUpper() == QLatin1String("TRUE")); - } - - QString usage() const - { - QString res; - if (hasShortcut()) - res += shortcutParameter() + QLatin1String(" | "); - res += fullParameter(); - return padUsageText(res); - } - }; - - bool operator==(const QString &s, const BoolOption &o) - { - return o == s; - } - - // Option with string value. May not have a shortcut - struct StringOption: protected Option - { - public: - constexpr StringOption(const char *name) - : Option {name, 0} - { - } - - bool operator==(const QString &arg) const - { - return arg.startsWith(parameterAssignment()); - } - - QString value(const QString &arg) const - { - QStringList parts = arg.split(QLatin1Char('=')); - if (parts.size() == 2) - return Utils::String::unquote(parts[1], QLatin1String("'\"")); - throw CommandLineParameterError(QObject::tr("Parameter '%1' must follow syntax '%1=%2'", - "e.g. Parameter '--webui-port' must follow syntax '--webui-port=value'") - .arg(fullParameter()).arg(QLatin1String(""))); - } - - QString value(const QProcessEnvironment &env, const QString &defaultValue = QString()) const - { - QString val = env.value(envVarName()); - return val.isEmpty() ? defaultValue : Utils::String::unquote(val, QLatin1String("'\"")); - } - - QString usage(const QString &valueName) const - { - return padUsageText(parameterAssignment() + QLatin1Char('<') + valueName + QLatin1Char('>')); - } - - private: - QString parameterAssignment() const - { - return fullParameter() + QLatin1Char('='); - } - }; - - bool operator==(const QString &s, const StringOption &o) - { - return o == s; - } - - // Option with integer value. May not have a shortcut - class IntOption: protected StringOption - { - public: - constexpr IntOption(const char *name) - : StringOption {name} - { - } - - using StringOption::operator==; - using StringOption::usage; - - int value(const QString &arg) const - { - QString val = StringOption::value(arg); - bool ok = false; - int res = val.toInt(&ok); - if (!ok) - throw CommandLineParameterError(QObject::tr("Parameter '%1' must follow syntax '%1=%2'", - "e.g. Parameter '--webui-port' must follow syntax '--webui-port='") - .arg(fullParameter()).arg(QLatin1String(""))); - return res; - } - - int value(const QProcessEnvironment &env, int defaultValue) const - { - QString val = env.value(envVarName()); - if (val.isEmpty()) return defaultValue; - - bool ok; - int res = val.toInt(&ok); - if (!ok) { - qDebug() << QObject::tr("Expected integer number in environment variable '%1', but got '%2'") - .arg(envVarName()).arg(val); - return defaultValue; - } - return res; - } - }; - - bool operator==(const QString &s, const IntOption &o) - { - return o == s; - } - - // Option that is explicitly set to true or false, and whose value is undefined when unspecified. - // May not have a shortcut. - class TriStateBoolOption: protected Option - { - public: - constexpr TriStateBoolOption(const char *name, bool defaultValue) - : Option {name, 0} - , m_defaultValue(defaultValue) - { - } - - bool operator==(const QString &arg) const - { - QStringList parts = arg.split(QLatin1Char('=')); - return parts[0] == fullParameter(); - } - - QString usage() const - { - return padUsageText(fullParameter() + QLatin1String("=")); - } - - TriStateBool value(const QString &arg) const - { - QStringList parts = arg.split(QLatin1Char('=')); - - if (parts.size() == 1) { - return TriStateBool(m_defaultValue); - } - else if (parts.size() == 2) { - QString val = parts[1]; - - if (val.toUpper() == QLatin1String("TRUE") || val == QLatin1String("1")) { - return TriStateBool::True; - } - else if (val.toUpper() == QLatin1String("FALSE") || val == QLatin1String("0")) { - return TriStateBool::False; - } - } - - throw CommandLineParameterError(QObject::tr("Parameter '%1' must follow syntax '%1=%2'", - "e.g. Parameter '--add-paused' must follow syntax " - "'--add-paused='") - .arg(fullParameter()) - .arg(QLatin1String(""))); - } - - TriStateBool value(const QProcessEnvironment &env) const - { - QString val = env.value(envVarName(), "-1"); - - if (val.isEmpty()) { - return TriStateBool(m_defaultValue); - } - else if (val == QLatin1String("-1")) { - return TriStateBool::Undefined; - } - else if (val.toUpper() == QLatin1String("TRUE") || val == QLatin1String("1")) { - return TriStateBool::True; - } - else if (val.toUpper() == QLatin1String("FALSE") || val == QLatin1String("0")) { - return TriStateBool::False; - } - else { - qDebug() << QObject::tr("Expected %1 in environment variable '%2', but got '%3'") - .arg(QLatin1String("true|false")).arg(envVarName()).arg(val); - return TriStateBool::Undefined; - } - } - - bool m_defaultValue; - }; - - bool operator==(const QString &s, const TriStateBoolOption &o) - { - return o == s; - } - - constexpr const BoolOption SHOW_HELP_OPTION = {"help", 'h'}; - constexpr const BoolOption SHOW_VERSION_OPTION = {"version", 'v'}; -#ifdef DISABLE_GUI - constexpr const BoolOption DAEMON_OPTION = {"daemon", 'd'}; -#else - constexpr const BoolOption NO_SPLASH_OPTION = {"no-splash"}; -#endif - constexpr const IntOption WEBUI_PORT_OPTION = {"webui-port"}; - constexpr const StringOption PROFILE_OPTION = {"profile"}; - constexpr const StringOption CONFIGURATION_OPTION = {"configuration"}; - constexpr const BoolOption PORTABLE_OPTION = {"portable"}; - constexpr const BoolOption RELATIVE_FASTRESUME = {"relative-fastresume"}; - constexpr const StringOption SAVE_PATH_OPTION = {"save-path"}; - constexpr const TriStateBoolOption PAUSED_OPTION = {"add-paused", true}; - constexpr const BoolOption SKIP_HASH_CHECK_OPTION = {"skip-hash-check"}; - constexpr const StringOption CATEGORY_OPTION = {"category"}; - constexpr const BoolOption SEQUENTIAL_OPTION = {"sequential"}; - constexpr const BoolOption FIRST_AND_LAST_OPTION = {"first-and-last"}; - constexpr const TriStateBoolOption SKIP_DIALOG_OPTION = {"skip-dialog", true}; -} - -QBtCommandLineParameters::QBtCommandLineParameters(const QProcessEnvironment &env) - : showHelp(false) - , relativeFastresumePaths(RELATIVE_FASTRESUME.value(env)) - , portableMode(PORTABLE_OPTION.value(env)) - , skipChecking(SKIP_HASH_CHECK_OPTION.value(env)) - , sequential(SEQUENTIAL_OPTION.value(env)) - , firstLastPiecePriority(FIRST_AND_LAST_OPTION.value(env)) -#ifndef Q_OS_WIN - , showVersion(false) -#endif -#ifndef DISABLE_GUI - , noSplash(NO_SPLASH_OPTION.value(env)) -#else - , shouldDaemonize(DAEMON_OPTION.value(env)) -#endif - , webUiPort(WEBUI_PORT_OPTION.value(env, -1)) - , addPaused(PAUSED_OPTION.value(env)) - , skipDialog(SKIP_DIALOG_OPTION.value(env)) - , profileDir(PROFILE_OPTION.value(env)) - , configurationName(CONFIGURATION_OPTION.value(env)) - , savePath(SAVE_PATH_OPTION.value(env)) - , category(CATEGORY_OPTION.value(env)) -{ -} - -QStringList QBtCommandLineParameters::paramList() const -{ - QStringList result; - // Because we're passing a string list to the currently running - // qBittorrent process, we need some way of passing along the options - // the user has specified. Here we place special strings that are - // almost certainly not going to collide with a file path or URL - // specified by the user, and placing them at the beginning of the - // string listr so that they will be processed before the list of - // torrent paths or URLs. - - if (!savePath.isEmpty()) - result.append(QString("@savePath=%1").arg(savePath)); - - if (addPaused == TriStateBool::True) { - result.append(QLatin1String("@addPaused=1")); - } - else if (addPaused == TriStateBool::False) { - result.append(QLatin1String("@addPaused=0")); - } - - if (skipChecking) - result.append(QLatin1String("@skipChecking")); - - if (!category.isEmpty()) - result.append(QString("@category=%1").arg(category)); - - if (sequential) - result.append(QLatin1String("@sequential")); - - if (firstLastPiecePriority) - result.append(QLatin1String("@firstLastPiecePriority")); - - if (skipDialog == TriStateBool::True) { - result.append(QLatin1String("@skipDialog=1")); - } - else if (skipDialog == TriStateBool::False) { - result.append(QLatin1String("@skipDialog=0")); - } - - result += torrents; - return result; -} - -QBtCommandLineParameters parseCommandLine(const QStringList &args) -{ - QBtCommandLineParameters result {QProcessEnvironment::systemEnvironment()}; - - for (int i = 1; i < args.count(); ++i) { - const QString &arg = args[i]; - - if ((arg.startsWith("--") && !arg.endsWith(".torrent")) - || (arg.startsWith("-") && (arg.size() == 2))) { - // Parse known parameters - if ((arg == SHOW_HELP_OPTION)) { - result.showHelp = true; - } -#ifndef Q_OS_WIN - else if (arg == SHOW_VERSION_OPTION) { - result.showVersion = true; - } -#endif - else if (arg == WEBUI_PORT_OPTION) { - result.webUiPort = WEBUI_PORT_OPTION.value(arg); - if ((result.webUiPort < 1) || (result.webUiPort > 65535)) - throw CommandLineParameterError(QObject::tr("%1 must specify a valid port (1 to 65535).") - .arg(QLatin1String("--webui-port"))); - } -#ifndef DISABLE_GUI - else if (arg == NO_SPLASH_OPTION) { - result.noSplash = true; - } -#else - else if (arg == DAEMON_OPTION) { - result.shouldDaemonize = true; - } -#endif - else if (arg == PROFILE_OPTION) { - result.profileDir = PROFILE_OPTION.value(arg); - } - else if (arg == RELATIVE_FASTRESUME) { - result.relativeFastresumePaths = true; - } - else if (arg == PORTABLE_OPTION) { - result.portableMode = true; - } - else if (arg == CONFIGURATION_OPTION) { - result.configurationName = CONFIGURATION_OPTION.value(arg); - } - else if (arg == SAVE_PATH_OPTION) { - result.savePath = SAVE_PATH_OPTION.value(arg); - } - else if (arg == PAUSED_OPTION) { - result.addPaused = PAUSED_OPTION.value(arg); - } - else if (arg == SKIP_HASH_CHECK_OPTION) { - result.skipChecking = true; - } - else if (arg == CATEGORY_OPTION) { - result.category = CATEGORY_OPTION.value(arg); - } - else if (arg == SEQUENTIAL_OPTION) { - result.sequential = true; - } - else if (arg == FIRST_AND_LAST_OPTION) { - result.firstLastPiecePriority = true; - } - else if (arg == SKIP_DIALOG_OPTION) { - result.skipDialog = SKIP_DIALOG_OPTION.value(arg); - } - else { - // Unknown argument - result.unknownParameter = arg; - break; - } - } - else { - QFileInfo torrentPath; - torrentPath.setFile(arg); - - if (torrentPath.exists()) - result.torrents += torrentPath.absoluteFilePath(); - else - result.torrents += arg; - } - } - - return result; -} - -CommandLineParameterError::CommandLineParameterError(const QString &messageForUser) - : std::runtime_error(messageForUser.toLocal8Bit().data()) - , m_messageForUser(messageForUser) -{ -} - -const QString& CommandLineParameterError::messageForUser() const -{ - return m_messageForUser; -} - -QString wrapText(const QString &text, int initialIndentation = USAGE_TEXT_COLUMN, int wrapAtColumn = WRAP_AT_COLUMN) -{ - QStringList words = text.split(' '); - QStringList lines = {words.first()}; - int currentLineMaxLength = wrapAtColumn - initialIndentation; - - foreach (const QString &word, words.mid(1)) { - if (lines.last().length() + word.length() + 1 < currentLineMaxLength) { - lines.last().append(" " + word); - } - else { - lines.append(QString(initialIndentation, ' ') + word); - currentLineMaxLength = wrapAtColumn; - } - } - - return lines.join("\n"); -} - -QString makeUsage(const QString &prgName) -{ - QString text; - QTextStream stream(&text, QIODevice::WriteOnly); - QString indentation = QString(USAGE_INDENTATION, ' '); - - stream << QObject::tr("Usage:") << '\n'; - stream << indentation << prgName << QLatin1String(" [options] [( | )...]") << '\n'; - - stream << QObject::tr("Options:") << '\n'; -#ifndef Q_OS_WIN - stream << SHOW_VERSION_OPTION.usage() << wrapText(QObject::tr("Display program version and exit")) << '\n'; -#endif - stream << SHOW_HELP_OPTION.usage() << wrapText(QObject::tr("Display this help message and exit")) << '\n'; - stream << WEBUI_PORT_OPTION.usage(QObject::tr("port")) - << wrapText(QObject::tr("Change the Web UI port")) - << '\n'; -#ifndef DISABLE_GUI - stream << NO_SPLASH_OPTION.usage() << wrapText(QObject::tr("Disable splash screen")) << '\n'; -#else - stream << DAEMON_OPTION.usage() << wrapText(QObject::tr("Run in daemon-mode (background)")) << '\n'; -#endif - //: Use appropriate short form or abbreviation of "directory" - stream << PROFILE_OPTION.usage(QObject::tr("dir")) - << wrapText(QObject::tr("Store configuration files in ")) << '\n'; - stream << CONFIGURATION_OPTION.usage(QObject::tr("name")) - << wrapText(QObject::tr("Store configuration files in directories qBittorrent_")) << '\n'; - stream << RELATIVE_FASTRESUME.usage() - << wrapText(QObject::tr("Hack into libtorrent fastresume files and make file paths relative " - "to the profile directory")) << '\n'; - stream << PORTABLE_OPTION.usage() - << wrapText(QObject::tr("Shortcut for --profile=/profile --relative-fastresume")) << '\n'; - stream << Option::padUsageText(QObject::tr("files or URLs")) - << wrapText(QObject::tr("Download the torrents passed by the user")) << '\n' - << '\n'; - - stream << wrapText(QObject::tr("Options when adding new torrents:"), 0) << '\n'; - stream << SAVE_PATH_OPTION.usage(QObject::tr("path")) << wrapText(QObject::tr("Torrent save path")) << '\n'; - stream << PAUSED_OPTION.usage() << wrapText(QObject::tr("Add torrents as started or paused")) << '\n'; - stream << SKIP_HASH_CHECK_OPTION.usage() << wrapText(QObject::tr("Skip hash check")) << '\n'; - stream << CATEGORY_OPTION.usage(QObject::tr("name")) - << wrapText(QObject::tr("Assign torrents to category. If the category doesn't exist, it will be " - "created.")) << '\n'; - stream << SEQUENTIAL_OPTION.usage() << wrapText(QObject::tr("Download files in sequential order")) << '\n'; - stream << FIRST_AND_LAST_OPTION.usage() - << wrapText(QObject::tr("Download first and last pieces first")) << '\n'; - stream << SKIP_DIALOG_OPTION.usage() - << wrapText(QObject::tr("Specify whether the \"Add New Torrent\" dialog opens when adding a " - "torrent.")) << '\n'; - stream << '\n'; - - stream << wrapText(QObject::tr("Option values may be supplied via environment variables. For option named " - "'parameter-name', environment variable name is 'QBT_PARAMETER_NAME' (in upper " - "case, '-' replaced with '_'). To pass flag values, set the variable to '1' or " - "'TRUE'. For example, to disable the splash screen: "), 0) << "\n" - << QLatin1String("QBT_NO_SPLASH=1 ") << prgName << '\n' - << wrapText(QObject::tr("Command line parameters take precedence over environment variables"), 0) << '\n'; - - stream << flush; - return text; -} - -void displayUsage(const QString &prgName) -{ -#ifndef Q_OS_WIN - std::cout << qPrintable(makeUsage(prgName)) << std::endl; -#else - QMessageBox msgBox(QMessageBox::Information, QObject::tr("Help"), makeUsage(prgName), QMessageBox::Ok); - msgBox.show(); // Need to be shown or to moveToCenter does not work - msgBox.move(Utils::Misc::screenCenter(&msgBox)); - msgBox.exec(); -#endif -} diff --git a/src/app/cmdoptions.h b/src/app/cmdoptions.h deleted file mode 100644 index 0a406cb6c..000000000 --- a/src/app/cmdoptions.h +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2016 Eugene Shalygin - * Copyright (C) 2014 Vladimir Golovnev - * Copyright (C) 2006 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 APP_OPTIONS_H -#define APP_OPTIONS_H - -#include - -#include -#include - -#include "base/tristatebool.h" - -class QProcessEnvironment; - -struct QBtCommandLineParameters -{ - bool showHelp, relativeFastresumePaths, portableMode, skipChecking, sequential, firstLastPiecePriority; -#ifndef Q_OS_WIN - bool showVersion; -#endif -#ifndef DISABLE_GUI - bool noSplash; -#else - bool shouldDaemonize; -#endif - int webUiPort; - TriStateBool addPaused, skipDialog; - QStringList torrents; - QString profileDir, configurationName, savePath, category, unknownParameter; - - QBtCommandLineParameters(const QProcessEnvironment&); - QStringList paramList() const; -}; - -class CommandLineParameterError: public std::runtime_error -{ -public: - CommandLineParameterError(const QString &messageForUser); - const QString& messageForUser() const; - -private: - const QString m_messageForUser; -}; - -QBtCommandLineParameters parseCommandLine(const QStringList &args); -void displayUsage(const QString &prgName); - -#endif // APP_OPTIONS_H diff --git a/src/app/filelogger.cpp b/src/app/filelogger.cpp deleted file mode 100644 index 0c8426bc6..000000000 --- a/src/app/filelogger.cpp +++ /dev/null @@ -1,176 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2016 sledgehammer999 - * - * 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. - */ - -#include -#include -#include -#include -#include "filelogger.h" -#include "base/logger.h" -#include "base/utils/fs.h" - -FileLogger::FileLogger(const QString &path, const bool backup, const int maxSize, const bool deleteOld, const int age, const FileLogAgeType ageType) - : m_backup(backup) - , m_maxSize(maxSize) - , m_logFile(nullptr) -{ - m_flusher.setInterval(0); - m_flusher.setSingleShot(true); - connect(&m_flusher, SIGNAL(timeout()), SLOT(flushLog())); - - changePath(path); - if (deleteOld) - this->deleteOld(age, ageType); - - const Logger* const logger = Logger::instance(); - foreach (const Log::Msg& msg, logger->getMessages()) - addLogMessage(msg); - - connect(logger, SIGNAL(newLogMessage(const Log::Msg &)), SLOT(addLogMessage(const Log::Msg &))); -} - -FileLogger::~FileLogger() -{ - if (!m_logFile) return; - closeLogFile(); - delete m_logFile; -} - -void FileLogger::changePath(const QString& newPath) -{ - QString tmpPath = Utils::Fs::fromNativePath(newPath); - QDir dir(tmpPath); - dir.mkpath(tmpPath); - tmpPath = dir.absoluteFilePath("qbittorrent.log"); - - if (tmpPath != m_path) { - m_path = tmpPath; - - if (m_logFile) { - closeLogFile(); - delete m_logFile; - } - m_logFile = new QFile(m_path); - openLogFile(); - } -} - -void FileLogger::deleteOld(const int age, const FileLogAgeType ageType) -{ - QDateTime date = QDateTime::currentDateTime(); - QDir dir(m_path); - - switch (ageType) { - case DAYS: - date = date.addDays(age); - break; - case MONTHS: - date = date.addMonths(age); - break; - default: - date = date.addYears(age); - } - - foreach (const QFileInfo file, dir.entryInfoList(QStringList("qbittorrent.log.bak*"), QDir::Files | QDir::Writable, QDir::Time | QDir::Reversed)) { - if (file.lastModified() < date) - break; - Utils::Fs::forceRemove(file.absoluteFilePath()); - } -} - -void FileLogger::setBackup(bool value) -{ - m_backup = value; -} - -void FileLogger::setMaxSize(int value) -{ - m_maxSize = value; -} - -void FileLogger::addLogMessage(const Log::Msg &msg) -{ - if (!m_logFile) return; - - QTextStream str(m_logFile); - - switch (msg.type) { - case Log::INFO: - str << "(I) "; - break; - case Log::WARNING: - str << "(W) "; - break; - case Log::CRITICAL: - str << "(C) "; - break; - default: - str << "(N) "; - } - - str << QDateTime::fromMSecsSinceEpoch(msg.timestamp).toString(Qt::ISODate) << " - " << msg.message << endl; - - if (m_backup && (m_logFile->size() >= (m_maxSize * 1024 * 1024))) { - closeLogFile(); - int counter = 0; - QString backupLogFilename = m_path + ".bak"; - - while (QFile::exists(backupLogFilename)) { - ++counter; - backupLogFilename = m_path + ".bak" + QString::number(counter); - } - - QFile::rename(m_path, backupLogFilename); - openLogFile(); - } - else { - m_flusher.start(); - } -} - -void FileLogger::flushLog() -{ - if (m_logFile) - m_logFile->flush(); -} - -void FileLogger::openLogFile() -{ - if (!m_logFile->open(QIODevice::WriteOnly | QIODevice::Append | QIODevice::Text) - || !m_logFile->setPermissions(QFile::ReadOwner | QFile::WriteOwner)) { - delete m_logFile; - m_logFile = nullptr; - Logger::instance()->addMessage(tr("An error occured while trying to open the log file. Logging to file is disabled."), Log::CRITICAL); - } -} - -void FileLogger::closeLogFile() -{ - m_flusher.stop(); - m_logFile->close(); -} diff --git a/src/app/filelogger.h b/src/app/filelogger.h deleted file mode 100644 index 423b7a625..000000000 --- a/src/app/filelogger.h +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2016 sledgehammer999 - * - * 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. - */ - -#ifndef FILELOGGER_H -#define FILELOGGER_H - -#include -#include - -class QFile; - -namespace Log -{ - struct Msg; -} - -class FileLogger : public QObject -{ - Q_OBJECT - Q_DISABLE_COPY(FileLogger) - -public: - enum FileLogAgeType - { - DAYS, - MONTHS, - YEARS - }; - - FileLogger(const QString &path, const bool backup, const int maxSize, const bool deleteOld, const int age, const FileLogAgeType ageType); - ~FileLogger(); - - void changePath(const QString &newPath); - void deleteOld(const int age, const FileLogAgeType ageType); - void setBackup(bool value); - void setMaxSize(int value); - -private slots: - void addLogMessage(const Log::Msg &msg); - void flushLog(); - -private: - void openLogFile(); - void closeLogFile(); - - QString m_path; - bool m_backup; - int m_maxSize; - QFile *m_logFile; - QTimer m_flusher; -}; - -#endif // FILELOGGER_H - diff --git a/src/app/main.cpp b/src/app/main.cpp deleted file mode 100644 index b42fec742..000000000 --- a/src/app/main.cpp +++ /dev/null @@ -1,390 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2014 Vladimir Golovnev - * Copyright (C) 2006 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 -#include -#include - -#ifndef DISABLE_GUI -// GUI-only includes -#include -#include -#include -#include -#include -#include - -#ifdef QBT_STATIC_QT -#include -Q_IMPORT_PLUGIN(QICOPlugin) -#endif // QBT_STATIC_QT - -#else -// NoGUI-only includes -#include -#ifdef Q_OS_UNIX -#include "unistd.h" -#endif -#endif // DISABLE_GUI - -#ifdef Q_OS_UNIX -#include -#include -#include "stacktrace.h" -#endif // Q_OS_UNIX - -#ifdef STACKTRACE_WIN -#include -#include "stacktrace_win.h" -#include "stacktrace_win_dlg.h" -#endif //STACKTRACE_WIN - -#include -#include - -#include "application.h" -#include "base/profile.h" -#include "base/utils/misc.h" -#include "base/preferences.h" -#include "cmdoptions.h" - -#include "upgrade.h" - -// Signal handlers -#if defined(Q_OS_UNIX) || defined(STACKTRACE_WIN) -void sigNormalHandler(int signum); -void sigAbnormalHandler(int signum); -// sys_signame[] is only defined in BSD -const char *sysSigName[] = { - "", "SIGHUP", "SIGINT", "SIGQUIT", "SIGILL", "SIGTRAP", "SIGABRT", "SIGBUS", "SIGFPE", "SIGKILL", - "SIGUSR1", "SIGSEGV", "SIGUSR2", "SIGPIPE", "SIGALRM", "SIGTERM", "SIGSTKFLT", "SIGCHLD", "SIGCONT", "SIGSTOP", - "SIGTSTP", "SIGTTIN", "SIGTTOU", "SIGURG", "SIGXCPU", "SIGXFSZ", "SIGVTALRM", "SIGPROF", "SIGWINCH", "SIGIO", - "SIGPWR", "SIGUNUSED" -}; -#endif - -#if !defined Q_OS_WIN && !defined Q_OS_HAIKU -void reportToUser(const char* str); -#endif - -void displayVersion(); -bool userAgreesWithLegalNotice(); -void displayBadArgMessage(const QString &message); - -#if !defined(DISABLE_GUI) -void showSplashScreen(); - -#if defined(Q_OS_UNIX) -void setupDpi(); -#endif // Q_OS_UNIX -#endif // DISABLE_GUI - -// Main -int main(int argc, char *argv[]) -{ - // We must save it here because QApplication constructor may change it - bool isOneArg = (argc == 2); - -#ifdef Q_OS_MAC - // On macOS 10.12 Sierra, Apple changed the behaviour of CFPreferencesSetValue() https://bugreports.qt.io/browse/QTBUG-56344 - // Due to this, we have to move from native plist to IniFormat - macMigratePlists(); -#endif - -#if !defined(DISABLE_GUI) && defined(Q_OS_UNIX) - setupDpi(); -#endif - - try { - // Create Application - QString appId = QLatin1String("qBittorrent-") + Utils::Misc::getUserIDString(); - QScopedPointer app(new Application(appId, argc, argv)); - -#ifndef DISABLE_GUI - // after the application object creation because we need a profile to be set already - // for the migration - migrateRSS(); -#endif - - const QBtCommandLineParameters params = app->commandLineArgs(); - - if (!params.unknownParameter.isEmpty()) { - throw CommandLineParameterError(QObject::tr("%1 is an unknown command line parameter.", - "--random-parameter is an unknown command line parameter.") - .arg(params.unknownParameter)); - } -#ifndef Q_OS_WIN - if (params.showVersion) { - if (isOneArg) { - displayVersion(); - return EXIT_SUCCESS; - } - throw CommandLineParameterError(QObject::tr("%1 must be the single command line parameter.") - .arg(QLatin1String("-v (or --version)"))); - } -#endif - if (params.showHelp) { - if (isOneArg) { - displayUsage(argv[0]); - return EXIT_SUCCESS; - } - throw CommandLineParameterError(QObject::tr("%1 must be the single command line parameter.") - .arg(QLatin1String("-h (or --help)"))); - } - - // Set environment variable - if (!qputenv("QBITTORRENT", QBT_VERSION)) - std::cerr << "Couldn't set environment variable...\n"; - -#ifndef DISABLE_GUI - if (!userAgreesWithLegalNotice()) - return EXIT_SUCCESS; -#else - if (!params.shouldDaemonize - && isatty(fileno(stdin)) - && isatty(fileno(stdout)) - && !userAgreesWithLegalNotice()) - return EXIT_SUCCESS; -#endif - - // Check if qBittorrent is already running for this user - if (app->isRunning()) { -#ifdef DISABLE_GUI - if (params.shouldDaemonize) { - throw CommandLineParameterError(QObject::tr("You cannot use %1: qBittorrent is already running for this user.") - .arg(QLatin1String("-d (or --daemon)"))); - } - else -#endif - qDebug("qBittorrent is already running for this user."); - - QThread::msleep(300); - app->sendParams(params.paramList()); - - return EXIT_SUCCESS; - } - -#if defined(Q_OS_WIN) - // This affects only Windows apparently and Qt5. - // When QNetworkAccessManager is instantiated it regularly starts polling - // the network interfaces to see what's available and their status. - // This polling creates jitter and high ping with wifi interfaces. - // So here we disable it for lack of better measure. - // It will also spew this message in the console: QObject::startTimer: Timers cannot have negative intervals - // For more info see: - // 1. https://github.com/qbittorrent/qBittorrent/issues/4209 - // 2. https://bugreports.qt.io/browse/QTBUG-40332 - // 3. https://bugreports.qt.io/browse/QTBUG-46015 - - qputenv("QT_BEARER_POLL_TIMEOUT", QByteArray::number(-1)); -#endif - -#if defined(Q_OS_MAC) - // Since Apple made difficult for users to set PATH, we set here for convenience. - // Users are supposed to install Homebrew Python for search function. - // For more info see issue #5571. - QByteArray path = "/usr/local/bin:"; - path += qgetenv("PATH"); - qputenv("PATH", path.constData()); - - // On OS X the standard is to not show icons in the menus - app->setAttribute(Qt::AA_DontShowIconsInMenus); -#endif - -#ifndef DISABLE_GUI - if (!upgrade()) return EXIT_FAILURE; -#else - if (!upgrade(!params.shouldDaemonize - && isatty(fileno(stdin)) - && isatty(fileno(stdout)))) return EXIT_FAILURE; -#endif -#ifdef DISABLE_GUI - if (params.shouldDaemonize) { - app.reset(); // Destroy current application - if ((daemon(1, 0) == 0)) { - app.reset(new Application(appId, argc, argv)); - if (app->isRunning()) { - // Another instance had time to start. - return EXIT_FAILURE; - } - } - else { - qCritical("Something went wrong while daemonizing, exiting..."); - return EXIT_FAILURE; - } - } -#else - if (!(params.noSplash || Preferences::instance()->isSplashScreenDisabled())) - showSplashScreen(); -#endif - -#if defined(Q_OS_UNIX) || defined(STACKTRACE_WIN) - signal(SIGINT, sigNormalHandler); - signal(SIGTERM, sigNormalHandler); - signal(SIGABRT, sigAbnormalHandler); - signal(SIGSEGV, sigAbnormalHandler); -#endif - - return app->exec(params.paramList()); - } - catch (CommandLineParameterError &er) { - displayBadArgMessage(er.messageForUser()); - return EXIT_FAILURE; - } -} - -#if !defined Q_OS_WIN && !defined Q_OS_HAIKU -void reportToUser(const char* str) -{ - const size_t strLen = strlen(str); - if (write(STDERR_FILENO, str, strLen) < static_cast(strLen)) { - auto dummy = write(STDOUT_FILENO, str, strLen); - Q_UNUSED(dummy); - } -} -#endif - -#if defined(Q_OS_UNIX) || defined(STACKTRACE_WIN) -void sigNormalHandler(int signum) -{ -#if !defined Q_OS_WIN && !defined Q_OS_HAIKU - const char str1[] = "Catching signal: "; - const char *sigName = sysSigName[signum]; - const char str2[] = "\nExiting cleanly\n"; - reportToUser(str1); - reportToUser(sigName); - reportToUser(str2); -#endif // !defined Q_OS_WIN && !defined Q_OS_HAIKU - signal(signum, SIG_DFL); - qApp->exit(); // unsafe, but exit anyway -} - -void sigAbnormalHandler(int signum) -{ -#if !defined Q_OS_WIN && !defined Q_OS_HAIKU - const char str1[] = "\n\n*************************************************************\nCatching signal: "; - const char *sigName = sysSigName[signum]; - const char str2[] = "\nPlease file a bug report at http://bug.qbittorrent.org and provide the following information:\n\n" - "qBittorrent version: " QBT_VERSION "\n"; - reportToUser(str1); - reportToUser(sigName); - reportToUser(str2); - print_stacktrace(); // unsafe -#endif // !defined Q_OS_WIN && !defined Q_OS_HAIKU -#ifdef STACKTRACE_WIN - StraceDlg dlg; // unsafe - dlg.setStacktraceString(straceWin::getBacktrace()); - dlg.exec(); -#endif // STACKTRACE_WIN - signal(signum, SIG_DFL); - raise(signum); -} -#endif // defined(Q_OS_UNIX) || defined(STACKTRACE_WIN) - -#if !defined(DISABLE_GUI) -void showSplashScreen() -{ - QPixmap splash_img(":/icons/skin/splash.png"); - QPainter painter(&splash_img); - QString version = QBT_VERSION; - painter.setPen(QPen(Qt::white)); - painter.setFont(QFont("Arial", 22, QFont::Black)); - painter.drawText(224 - painter.fontMetrics().width(version), 270, version); - QSplashScreen *splash = new QSplashScreen(splash_img); - splash->show(); - QTimer::singleShot(1500, splash, SLOT(deleteLater())); - qApp->processEvents(); -} - -#if defined(Q_OS_UNIX) -void setupDpi() -{ - if (qgetenv("QT_AUTO_SCREEN_SCALE_FACTOR").isEmpty()) - qputenv("QT_AUTO_SCREEN_SCALE_FACTOR", "1"); -} -#endif // Q_OS_UNIX -#endif // DISABLE_GUI - -void displayVersion() -{ - std::cout << qPrintable(qApp->applicationName()) << " " << QBT_VERSION << std::endl; -} - -void displayBadArgMessage(const QString& message) -{ - QString help = QObject::tr("Run application with -h option to read about command line parameters."); -#ifdef Q_OS_WIN - QMessageBox msgBox(QMessageBox::Critical, QObject::tr("Bad command line"), - message + QLatin1Char('\n') + help, QMessageBox::Ok); - msgBox.show(); // Need to be shown or to moveToCenter does not work - msgBox.move(Utils::Misc::screenCenter(&msgBox)); - msgBox.exec(); -#else - std::cerr << qPrintable(QObject::tr("Bad command line: ")); - std::cerr << qPrintable(message) << std::endl; - std::cerr << qPrintable(help) << std::endl; -#endif -} - -bool userAgreesWithLegalNotice() -{ - Preferences* const pref = Preferences::instance(); - if (pref->getAcceptedLegal()) // Already accepted once - return true; - -#ifdef DISABLE_GUI - std::cout << std::endl << "*** " << qPrintable(QObject::tr("Legal Notice")) << " ***" << std::endl; - std::cout << qPrintable(QObject::tr("qBittorrent is a file sharing program. When you run a torrent, its data will be made available to others by means of upload. Any content you share is your sole responsibility.\n\nNo further notices will be issued.")) << std::endl << std::endl; - std::cout << qPrintable(QObject::tr("Press %1 key to accept and continue...").arg("'y'")) << std::endl; - char ret = getchar(); // Read pressed key - if (ret == 'y' || ret == 'Y') { - // Save the answer - pref->setAcceptedLegal(true); - return true; - } -#else - QMessageBox msgBox; - msgBox.setText(QObject::tr("qBittorrent is a file sharing program. When you run a torrent, its data will be made available to others by means of upload. Any content you share is your sole responsibility.\n\nNo further notices will be issued.")); - msgBox.setWindowTitle(QObject::tr("Legal notice")); - msgBox.addButton(QObject::tr("Cancel"), QMessageBox::RejectRole); - QAbstractButton *agree_button = msgBox.addButton(QObject::tr("I Agree"), QMessageBox::AcceptRole); - msgBox.show(); // Need to be shown or to moveToCenter does not work - msgBox.move(Utils::Misc::screenCenter(&msgBox)); - msgBox.exec(); - if (msgBox.clickedButton() == agree_button) { - // Save the answer - pref->setAcceptedLegal(true); - return true; - } -#endif - - return false; -} diff --git a/src/app/qtsingleapplication/CMakeLists.txt b/src/app/qtsingleapplication/CMakeLists.txt deleted file mode 100644 index 6571c1f8e..000000000 --- a/src/app/qtsingleapplication/CMakeLists.txt +++ /dev/null @@ -1,31 +0,0 @@ -project(qtsingleapplication) - -set(QBT_QTSINGLEAPPLICATION_HEADERS -qtlocalpeer.h -) - -set(QBT_QTSINGLEAPPLICATION_SOURCES -qtlocalpeer.cpp -) - -if (GUI) - list(APPEND QBT_QTSINGLEAPPLICATION_HEADERS qtsingleapplication.h) - list(APPEND QBT_QTSINGLEAPPLICATION_SOURCES qtsingleapplication.cpp) -else (GUI) - list(APPEND QBT_QTSINGLEAPPLICATION_HEADERS qtsinglecoreapplication.h) - list(APPEND QBT_QTSINGLEAPPLICATION_SOURCES qtsinglecoreapplication.cpp) -endif (GUI) - -add_library(qtsingleapplication ${QBT_QTSINGLEAPPLICATION_HEADERS} ${QBT_QTSINGLEAPPLICATION_SOURCES}) -target_include_directories(qtsingleapplication INTERFACE "${qtsingleapplication_SOURCE_DIR}") -target_link_qt_components(qtsingleapplication Network) - -if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") - target_compile_options(qtsingleapplication PRIVATE "-w") # disable warning for 3rdparty code -endif() - -if (GUI) - target_link_qt_components(qtsingleapplication Widgets) -endif (GUI) - -add_library(QtSingleApplication::QtSingleApplication ALIAS qtsingleapplication) diff --git a/src/app/qtsingleapplication/QtLockedFile b/src/app/qtsingleapplication/QtLockedFile deleted file mode 100644 index 16b48ba9d..000000000 --- a/src/app/qtsingleapplication/QtLockedFile +++ /dev/null @@ -1 +0,0 @@ -#include "qtlockedfile.h" diff --git a/src/app/qtsingleapplication/QtSingleApplication b/src/app/qtsingleapplication/QtSingleApplication deleted file mode 100644 index d111bf72d..000000000 --- a/src/app/qtsingleapplication/QtSingleApplication +++ /dev/null @@ -1 +0,0 @@ -#include "qtsingleapplication.h" diff --git a/src/app/qtsingleapplication/qtlocalpeer.cpp b/src/app/qtsingleapplication/qtlocalpeer.cpp deleted file mode 100644 index c7ce52762..000000000 --- a/src/app/qtsingleapplication/qtlocalpeer.cpp +++ /dev/null @@ -1,204 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the Qt Solutions component. -** -** $QT_BEGIN_LICENSE:BSD$ -** You may use this file under the terms of the BSD license as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names -** of its contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - - -#include "qtlocalpeer.h" -#include -#include -#include - -#if defined(Q_OS_WIN) -#include -#include -typedef BOOL(WINAPI*PProcessIdToSessionId)(DWORD,DWORD*); -static PProcessIdToSessionId pProcessIdToSessionId = 0; -#endif -#if defined(Q_OS_UNIX) -#include -#include -#include -#endif - -namespace QtLP_Private { -#include "qtlockedfile.cpp" -#if defined(Q_OS_WIN) -#include "qtlockedfile_win.cpp" -#else -#include "qtlockedfile_unix.cpp" -#endif -} - -const char* QtLocalPeer::ack = "ack"; - -QtLocalPeer::QtLocalPeer(QObject* parent, const QString &appId) - : QObject(parent), id(appId) -{ - QString prefix = id; - if (id.isEmpty()) { - id = QCoreApplication::applicationFilePath(); -#if defined(Q_OS_WIN) - id = id.toLower(); -#endif - prefix = id.section(QLatin1Char('/'), -1); - } - prefix.remove(QRegExp("[^a-zA-Z]")); - prefix.truncate(6); - - QByteArray idc = id.toUtf8(); - quint16 idNum = qChecksum(idc.constData(), idc.size()); - socketName = QLatin1String("qtsingleapp-") + prefix - + QLatin1Char('-') + QString::number(idNum, 16); - -#if defined(Q_OS_WIN) - if (!pProcessIdToSessionId) { - QLibrary lib("kernel32"); - pProcessIdToSessionId = (PProcessIdToSessionId)lib.resolve("ProcessIdToSessionId"); - } - if (pProcessIdToSessionId) { - DWORD sessionId = 0; - pProcessIdToSessionId(GetCurrentProcessId(), &sessionId); - socketName += QLatin1Char('-') + QString::number(sessionId, 16); - } -#else - socketName += QLatin1Char('-') + QString::number(::getuid(), 16); -#endif - - server = new QLocalServer(this); - QString lockName = QDir(QDir::tempPath()).absolutePath() - + QLatin1Char('/') + socketName - + QLatin1String("-lockfile"); - lockFile.setFileName(lockName); - lockFile.open(QIODevice::ReadWrite); -} - - - -bool QtLocalPeer::isClient() -{ - if (lockFile.isLocked()) - return false; - - if (!lockFile.lock(QtLP_Private::QtLockedFile::WriteLock, false)) - return true; - - bool res = server->listen(socketName); -#if defined(Q_OS_UNIX) && (QT_VERSION >= QT_VERSION_CHECK(4,5,0)) - // ### Workaround - if (!res && server->serverError() == QAbstractSocket::AddressInUseError) { - QFile::remove(QDir::cleanPath(QDir::tempPath())+QLatin1Char('/')+socketName); - res = server->listen(socketName); - } -#endif - if (!res) - qWarning("QtSingleCoreApplication: listen on local socket failed, %s", qPrintable(server->errorString())); - QObject::connect(server, SIGNAL(newConnection()), SLOT(receiveConnection())); - return false; -} - - -bool QtLocalPeer::sendMessage(const QString &message, int timeout) -{ - if (!isClient()) - return false; - - QLocalSocket socket; - bool connOk = false; - for(int i = 0; i < 2; i++) { - // Try twice, in case the other instance is just starting up - socket.connectToServer(socketName); - connOk = socket.waitForConnected(timeout/2); - if (connOk || i) - break; - int ms = 250; -#if defined(Q_OS_WIN) - Sleep(DWORD(ms)); -#else - struct timespec ts = { ms / 1000, (ms % 1000) * 1000 * 1000 }; - nanosleep(&ts, NULL); -#endif - } - if (!connOk) - return false; - - QByteArray uMsg(message.toUtf8()); - QDataStream ds(&socket); - ds.writeBytes(uMsg.constData(), uMsg.size()); - bool res = socket.waitForBytesWritten(timeout); - if (res) { - res &= socket.waitForReadyRead(timeout); // wait for ack - if (res) - res &= (socket.read(qstrlen(ack)) == ack); - } - return res; -} - - -void QtLocalPeer::receiveConnection() -{ - QLocalSocket* socket = server->nextPendingConnection(); - if (!socket) - return; - - while (socket->bytesAvailable() < (int)sizeof(quint32)) - socket->waitForReadyRead(); - QDataStream ds(socket); - QByteArray uMsg; - quint32 remaining; - ds >> remaining; - uMsg.resize(remaining); - int got = 0; - char* uMsgBuf = uMsg.data(); - do { - got = ds.readRawData(uMsgBuf, remaining); - remaining -= got; - uMsgBuf += got; - } while (remaining && got >= 0 && socket->waitForReadyRead(2000)); - if (got < 0) { - qWarning("QtLocalPeer: Message reception failed %s", socket->errorString().toLatin1().constData()); - delete socket; - return; - } - QString message(QString::fromUtf8(uMsg)); - socket->write(ack, qstrlen(ack)); - socket->waitForBytesWritten(1000); - socket->waitForDisconnected(1000); // make sure client reads ack - delete socket; - emit messageReceived(message); //### (might take a long time to return) -} diff --git a/src/app/qtsingleapplication/qtlocalpeer.h b/src/app/qtsingleapplication/qtlocalpeer.h deleted file mode 100644 index 1b533b1ab..000000000 --- a/src/app/qtsingleapplication/qtlocalpeer.h +++ /dev/null @@ -1,77 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the Qt Solutions component. -** -** $QT_BEGIN_LICENSE:BSD$ -** You may use this file under the terms of the BSD license as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names -** of its contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QTLOCALPEER_H -#define QTLOCALPEER_H - -#include -#include -#include - -#include "qtlockedfile.h" - -class QtLocalPeer : public QObject -{ - Q_OBJECT - -public: - QtLocalPeer(QObject *parent = 0, const QString &appId = QString()); - bool isClient(); - bool sendMessage(const QString &message, int timeout); - QString applicationId() const - { return id; } - -Q_SIGNALS: - void messageReceived(const QString &message); - -protected Q_SLOTS: - void receiveConnection(); - -protected: - QString id; - QString socketName; - QLocalServer* server; - QtLP_Private::QtLockedFile lockFile; - -private: - static const char* ack; -}; - -#endif // QTLOCALPEER_H diff --git a/src/app/qtsingleapplication/qtlockedfile.cpp b/src/app/qtsingleapplication/qtlockedfile.cpp deleted file mode 100644 index c142a863a..000000000 --- a/src/app/qtsingleapplication/qtlockedfile.cpp +++ /dev/null @@ -1,193 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the Qt Solutions component. -** -** $QT_BEGIN_LICENSE:BSD$ -** You may use this file under the terms of the BSD license as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names -** of its contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qtlockedfile.h" - -/*! - \class QtLockedFile - - \brief The QtLockedFile class extends QFile with advisory locking - functions. - - A file may be locked in read or write mode. Multiple instances of - \e QtLockedFile, created in multiple processes running on the same - machine, may have a file locked in read mode. Exactly one instance - may have it locked in write mode. A read and a write lock cannot - exist simultaneously on the same file. - - The file locks are advisory. This means that nothing prevents - another process from manipulating a locked file using QFile or - file system functions offered by the OS. Serialization is only - guaranteed if all processes that access the file use - QLockedFile. Also, while holding a lock on a file, a process - must not open the same file again (through any API), or locks - can be unexpectedly lost. - - The lock provided by an instance of \e QtLockedFile is released - whenever the program terminates. This is true even when the - program crashes and no destructors are called. -*/ - -/*! \enum QtLockedFile::LockMode - - This enum describes the available lock modes. - - \value ReadLock A read lock. - \value WriteLock A write lock. - \value NoLock Neither a read lock nor a write lock. -*/ - -/*! - Constructs an unlocked \e QtLockedFile object. This constructor - behaves in the same way as \e QFile::QFile(). - - \sa QFile::QFile() -*/ -QtLockedFile::QtLockedFile() - : QFile() -{ -#ifdef Q_OS_WIN - wmutex = 0; - rmutex = 0; -#endif - m_lock_mode = NoLock; -} - -/*! - Constructs an unlocked QtLockedFile object with file \a name. This - constructor behaves in the same way as \e QFile::QFile(const - QString&). - - \sa QFile::QFile() -*/ -QtLockedFile::QtLockedFile(const QString &name) - : QFile(name) -{ -#ifdef Q_OS_WIN - wmutex = 0; - rmutex = 0; -#endif - m_lock_mode = NoLock; -} - -/*! - Opens the file in OpenMode \a mode. - - This is identical to QFile::open(), with the one exception that the - Truncate mode flag is disallowed. Truncation would conflict with the - advisory file locking, since the file would be modified before the - write lock is obtained. If truncation is required, use resize(0) - after obtaining the write lock. - - Returns true if successful; otherwise false. - - \sa QFile::open(), QFile::resize() -*/ -bool QtLockedFile::open(OpenMode mode) -{ - if (mode & QIODevice::Truncate) { - qWarning("QtLockedFile::open(): Truncate mode not allowed."); - return false; - } - return QFile::open(mode); -} - -/*! - Returns \e true if this object has a in read or write lock; - otherwise returns \e false. - - \sa lockMode() -*/ -bool QtLockedFile::isLocked() const -{ - return m_lock_mode != NoLock; -} - -/*! - Returns the type of lock currently held by this object, or \e - QtLockedFile::NoLock. - - \sa isLocked() -*/ -QtLockedFile::LockMode QtLockedFile::lockMode() const -{ - return m_lock_mode; -} - -/*! - \fn bool QtLockedFile::lock(LockMode mode, bool block = true) - - Obtains a lock of type \a mode. The file must be opened before it - can be locked. - - If \a block is true, this function will block until the lock is - aquired. If \a block is false, this function returns \e false - immediately if the lock cannot be aquired. - - If this object already has a lock of type \a mode, this function - returns \e true immediately. If this object has a lock of a - different type than \a mode, the lock is first released and then a - new lock is obtained. - - This function returns \e true if, after it executes, the file is - locked by this object, and \e false otherwise. - - \sa unlock(), isLocked(), lockMode() -*/ - -/*! - \fn bool QtLockedFile::unlock() - - Releases a lock. - - If the object has no lock, this function returns immediately. - - This function returns \e true if, after it executes, the file is - not locked by this object, and \e false otherwise. - - \sa lock(), isLocked(), lockMode() -*/ - -/*! - \fn QtLockedFile::~QtLockedFile() - - Destroys the \e QtLockedFile object. If any locks were held, they - are released. -*/ diff --git a/src/app/qtsingleapplication/qtlockedfile.h b/src/app/qtsingleapplication/qtlockedfile.h deleted file mode 100644 index 84c18e5c9..000000000 --- a/src/app/qtsingleapplication/qtlockedfile.h +++ /dev/null @@ -1,97 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the Qt Solutions component. -** -** $QT_BEGIN_LICENSE:BSD$ -** You may use this file under the terms of the BSD license as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names -** of its contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QTLOCKEDFILE_H -#define QTLOCKEDFILE_H - -#include -#ifdef Q_OS_WIN -#include -#endif - -#if defined(Q_OS_WIN) -# if !defined(QT_QTLOCKEDFILE_EXPORT) && !defined(QT_QTLOCKEDFILE_IMPORT) -# define QT_QTLOCKEDFILE_EXPORT -# elif defined(QT_QTLOCKEDFILE_IMPORT) -# if defined(QT_QTLOCKEDFILE_EXPORT) -# undef QT_QTLOCKEDFILE_EXPORT -# endif -# define QT_QTLOCKEDFILE_EXPORT __declspec(dllimport) -# elif defined(QT_QTLOCKEDFILE_EXPORT) -# undef QT_QTLOCKEDFILE_EXPORT -# define QT_QTLOCKEDFILE_EXPORT __declspec(dllexport) -# endif -#else -# define QT_QTLOCKEDFILE_EXPORT -#endif - -namespace QtLP_Private { - -class QT_QTLOCKEDFILE_EXPORT QtLockedFile : public QFile -{ -public: - enum LockMode { NoLock = 0, ReadLock, WriteLock }; - - QtLockedFile(); - QtLockedFile(const QString &name); - ~QtLockedFile(); - - bool open(OpenMode mode); - - bool lock(LockMode mode, bool block = true); - bool unlock(); - bool isLocked() const; - LockMode lockMode() const; - -private: -#ifdef Q_OS_WIN - Qt::HANDLE wmutex; - Qt::HANDLE rmutex; - QVector rmutexes; - QString mutexname; - - Qt::HANDLE getMutexHandle(int idx, bool doCreate); - bool waitMutex(Qt::HANDLE mutex, bool doBlock); - -#endif - LockMode m_lock_mode; -}; -} -#endif diff --git a/src/app/qtsingleapplication/qtlockedfile_unix.cpp b/src/app/qtsingleapplication/qtlockedfile_unix.cpp deleted file mode 100644 index 976c1b9ee..000000000 --- a/src/app/qtsingleapplication/qtlockedfile_unix.cpp +++ /dev/null @@ -1,115 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the Qt Solutions component. -** -** $QT_BEGIN_LICENSE:BSD$ -** You may use this file under the terms of the BSD license as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names -** of its contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include -#include -#include -#include - -#include "qtlockedfile.h" - -bool QtLockedFile::lock(LockMode mode, bool block) -{ - if (!isOpen()) { - qWarning("QtLockedFile::lock(): file is not opened"); - return false; - } - - if (mode == NoLock) - return unlock(); - - if (mode == m_lock_mode) - return true; - - if (m_lock_mode != NoLock) - unlock(); - - struct flock fl; - fl.l_whence = SEEK_SET; - fl.l_start = 0; - fl.l_len = 0; - fl.l_type = (mode == ReadLock) ? F_RDLCK : F_WRLCK; - int cmd = block ? F_SETLKW : F_SETLK; - int ret = fcntl(handle(), cmd, &fl); - - if (ret == -1) { - if (errno != EINTR && errno != EAGAIN) - qWarning("QtLockedFile::lock(): fcntl: %s", strerror(errno)); - return false; - } - - - m_lock_mode = mode; - return true; -} - - -bool QtLockedFile::unlock() -{ - if (!isOpen()) { - qWarning("QtLockedFile::unlock(): file is not opened"); - return false; - } - - if (!isLocked()) - return true; - - struct flock fl; - fl.l_whence = SEEK_SET; - fl.l_start = 0; - fl.l_len = 0; - fl.l_type = F_UNLCK; - int ret = fcntl(handle(), F_SETLKW, &fl); - - if (ret == -1) { - qWarning("QtLockedFile::lock(): fcntl: %s", strerror(errno)); - return false; - } - - m_lock_mode = NoLock; - return true; -} - -QtLockedFile::~QtLockedFile() -{ - if (isOpen()) - unlock(); -} - diff --git a/src/app/qtsingleapplication/qtlockedfile_win.cpp b/src/app/qtsingleapplication/qtlockedfile_win.cpp deleted file mode 100644 index 5e2126204..000000000 --- a/src/app/qtsingleapplication/qtlockedfile_win.cpp +++ /dev/null @@ -1,211 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the Qt Solutions component. -** -** $QT_BEGIN_LICENSE:BSD$ -** You may use this file under the terms of the BSD license as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names -** of its contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qtlockedfile.h" -#include -#include - -#define MUTEX_PREFIX "QtLockedFile mutex " -// Maximum number of concurrent read locks. Must not be greater than MAXIMUM_WAIT_OBJECTS -#define MAX_READERS MAXIMUM_WAIT_OBJECTS - -#if QT_VERSION >= 0x050000 -#define QT_WA(unicode, ansi) unicode -#endif - -Qt::HANDLE QtLockedFile::getMutexHandle(int idx, bool doCreate) -{ - if (mutexname.isEmpty()) { - QFileInfo fi(*this); - mutexname = QString::fromLatin1(MUTEX_PREFIX) - + fi.absoluteFilePath().toLower(); - } - QString mname(mutexname); - if (idx >= 0) - mname += QString::number(idx); - - Qt::HANDLE mutex; - if (doCreate) { - QT_WA( { mutex = CreateMutexW(NULL, FALSE, (TCHAR*)mname.utf16()); }, - { mutex = CreateMutexA(NULL, FALSE, mname.toLocal8Bit().constData()); } ); - if (!mutex) { - qErrnoWarning("QtLockedFile::lock(): CreateMutex failed"); - return 0; - } - } - else { - QT_WA( { mutex = OpenMutexW(SYNCHRONIZE | MUTEX_MODIFY_STATE, FALSE, (TCHAR*)mname.utf16()); }, - { mutex = OpenMutexA(SYNCHRONIZE | MUTEX_MODIFY_STATE, FALSE, mname.toLocal8Bit().constData()); } ); - if (!mutex) { - if (GetLastError() != ERROR_FILE_NOT_FOUND) - qErrnoWarning("QtLockedFile::lock(): OpenMutex failed"); - return 0; - } - } - return mutex; -} - -bool QtLockedFile::waitMutex(Qt::HANDLE mutex, bool doBlock) -{ - Q_ASSERT(mutex); - DWORD res = WaitForSingleObject(mutex, doBlock ? INFINITE : 0); - switch (res) { - case WAIT_OBJECT_0: - case WAIT_ABANDONED: - return true; - break; - case WAIT_TIMEOUT: - break; - default: - qErrnoWarning("QtLockedFile::lock(): WaitForSingleObject failed"); - } - return false; -} - - - -bool QtLockedFile::lock(LockMode mode, bool block) -{ - if (!isOpen()) { - qWarning("QtLockedFile::lock(): file is not opened"); - return false; - } - - if (mode == NoLock) - return unlock(); - - if (mode == m_lock_mode) - return true; - - if (m_lock_mode != NoLock) - unlock(); - - if (!wmutex && !(wmutex = getMutexHandle(-1, true))) - return false; - - if (!waitMutex(wmutex, block)) - return false; - - if (mode == ReadLock) { - int idx = 0; - for (; idx < MAX_READERS; idx++) { - rmutex = getMutexHandle(idx, false); - if (!rmutex || waitMutex(rmutex, false)) - break; - CloseHandle(rmutex); - } - bool ok = true; - if (idx >= MAX_READERS) { - qWarning("QtLockedFile::lock(): too many readers"); - rmutex = 0; - ok = false; - } - else if (!rmutex) { - rmutex = getMutexHandle(idx, true); - if (!rmutex || !waitMutex(rmutex, false)) - ok = false; - } - if (!ok && rmutex) { - CloseHandle(rmutex); - rmutex = 0; - } - ReleaseMutex(wmutex); - if (!ok) - return false; - } - else { - Q_ASSERT(rmutexes.isEmpty()); - for (int i = 0; i < MAX_READERS; i++) { - Qt::HANDLE mutex = getMutexHandle(i, false); - if (mutex) - rmutexes.append(mutex); - } - if (rmutexes.size()) { - DWORD res = WaitForMultipleObjects(rmutexes.size(), rmutexes.constData(), - TRUE, block ? INFINITE : 0); - if (res != WAIT_OBJECT_0 && res != WAIT_ABANDONED) { - if (res != WAIT_TIMEOUT) - qErrnoWarning("QtLockedFile::lock(): WaitForMultipleObjects failed"); - m_lock_mode = WriteLock; // trick unlock() to clean up - semiyucky - unlock(); - return false; - } - } - } - - m_lock_mode = mode; - return true; -} - -bool QtLockedFile::unlock() -{ - if (!isOpen()) { - qWarning("QtLockedFile::unlock(): file is not opened"); - return false; - } - - if (!isLocked()) - return true; - - if (m_lock_mode == ReadLock) { - ReleaseMutex(rmutex); - CloseHandle(rmutex); - rmutex = 0; - } - else { - foreach(Qt::HANDLE mutex, rmutexes) { - ReleaseMutex(mutex); - CloseHandle(mutex); - } - rmutexes.clear(); - ReleaseMutex(wmutex); - } - - m_lock_mode = QtLockedFile::NoLock; - return true; -} - -QtLockedFile::~QtLockedFile() -{ - if (isOpen()) - unlock(); - if (wmutex) - CloseHandle(wmutex); -} diff --git a/src/app/qtsingleapplication/qtsingleapplication.cpp b/src/app/qtsingleapplication/qtsingleapplication.cpp deleted file mode 100644 index d0fb15d76..000000000 --- a/src/app/qtsingleapplication/qtsingleapplication.cpp +++ /dev/null @@ -1,347 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the Qt Solutions component. -** -** $QT_BEGIN_LICENSE:BSD$ -** You may use this file under the terms of the BSD license as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names -** of its contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - - -#include "qtsingleapplication.h" -#include "qtlocalpeer.h" -#include - - -/*! - \class QtSingleApplication qtsingleapplication.h - \brief The QtSingleApplication class provides an API to detect and - communicate with running instances of an application. - - This class allows you to create applications where only one - instance should be running at a time. I.e., if the user tries to - launch another instance, the already running instance will be - activated instead. Another usecase is a client-server system, - where the first started instance will assume the role of server, - and the later instances will act as clients of that server. - - By default, the full path of the executable file is used to - determine whether two processes are instances of the same - application. You can also provide an explicit identifier string - that will be compared instead. - - The application should create the QtSingleApplication object early - in the startup phase, and call isRunning() to find out if another - instance of this application is already running. If isRunning() - returns false, it means that no other instance is running, and - this instance has assumed the role as the running instance. In - this case, the application should continue with the initialization - of the application user interface before entering the event loop - with exec(), as normal. - - The messageReceived() signal will be emitted when the running - application receives messages from another instance of the same - application. When a message is received it might be helpful to the - user to raise the application so that it becomes visible. To - facilitate this, QtSingleApplication provides the - setActivationWindow() function and the activateWindow() slot. - - If isRunning() returns true, another instance is already - running. It may be alerted to the fact that another instance has - started by using the sendMessage() function. Also data such as - startup parameters (e.g. the name of the file the user wanted this - new instance to open) can be passed to the running instance with - this function. Then, the application should terminate (or enter - client mode). - - If isRunning() returns true, but sendMessage() fails, that is an - indication that the running instance is frozen. - - Here's an example that shows how to convert an existing - application to use QtSingleApplication. It is very simple and does - not make use of all QtSingleApplication's functionality (see the - examples for that). - - \code - // Original - int main(int argc, char **argv) - { - QApplication app(argc, argv); - - MyMainWidget mmw; - mmw.show(); - return app.exec(); - } - - // Single instance - int main(int argc, char **argv) - { - QtSingleApplication app(argc, argv); - - if (app.isRunning()) - return !app.sendMessage(someDataString); - - MyMainWidget mmw; - app.setActivationWindow(&mmw); - mmw.show(); - return app.exec(); - } - \endcode - - Once this QtSingleApplication instance is destroyed (normally when - the process exits or crashes), when the user next attempts to run the - application this instance will not, of course, be encountered. The - next instance to call isRunning() or sendMessage() will assume the - role as the new running instance. - - For console (non-GUI) applications, QtSingleCoreApplication may be - used instead of this class, to avoid the dependency on the QtGui - library. - - \sa QtSingleCoreApplication -*/ - - -void QtSingleApplication::sysInit(const QString &appId) -{ - actWin = 0; - peer = new QtLocalPeer(this, appId); - connect(peer, SIGNAL(messageReceived(const QString&)), SIGNAL(messageReceived(const QString&))); -} - - -/*! - Creates a QtSingleApplication object. The application identifier - will be QCoreApplication::applicationFilePath(). \a argc, \a - argv, and \a GUIenabled are passed on to the QAppliation constructor. - - If you are creating a console application (i.e. setting \a - GUIenabled to false), you may consider using - QtSingleCoreApplication instead. -*/ - -QtSingleApplication::QtSingleApplication(int &argc, char **argv, bool GUIenabled) - : QApplication(argc, argv, GUIenabled) -{ - sysInit(); -} - - -/*! - Creates a QtSingleApplication object with the application - identifier \a appId. \a argc and \a argv are passed on to the - QAppliation constructor. -*/ - -QtSingleApplication::QtSingleApplication(const QString &appId, int &argc, char **argv) - : QApplication(argc, argv) -{ - sysInit(appId); -} - -#if QT_VERSION < 0x050000 - -/*! - Creates a QtSingleApplication object. The application identifier - will be QCoreApplication::applicationFilePath(). \a argc, \a - argv, and \a type are passed on to the QAppliation constructor. -*/ -QtSingleApplication::QtSingleApplication(int &argc, char **argv, Type type) - : QApplication(argc, argv, type) -{ - sysInit(); -} - - -# if defined(Q_WS_X11) -/*! - Special constructor for X11, ref. the documentation of - QApplication's corresponding constructor. The application identifier - will be QCoreApplication::applicationFilePath(). \a dpy, \a visual, - and \a cmap are passed on to the QApplication constructor. -*/ -QtSingleApplication::QtSingleApplication(Display* dpy, Qt::HANDLE visual, Qt::HANDLE cmap) - : QApplication(dpy, visual, cmap) -{ - sysInit(); -} - -/*! - Special constructor for X11, ref. the documentation of - QApplication's corresponding constructor. The application identifier - will be QCoreApplication::applicationFilePath(). \a dpy, \a argc, \a - argv, \a visual, and \a cmap are passed on to the QApplication - constructor. -*/ -QtSingleApplication::QtSingleApplication(Display *dpy, int &argc, char **argv, Qt::HANDLE visual, Qt::HANDLE cmap) - : QApplication(dpy, argc, argv, visual, cmap) -{ - sysInit(); -} - -/*! - Special constructor for X11, ref. the documentation of - QApplication's corresponding constructor. The application identifier - will be \a appId. \a dpy, \a argc, \a - argv, \a visual, and \a cmap are passed on to the QApplication - constructor. -*/ -QtSingleApplication::QtSingleApplication(Display* dpy, const QString &appId, int argc, char **argv, Qt::HANDLE visual, Qt::HANDLE cmap) - : QApplication(dpy, argc, argv, visual, cmap) -{ - sysInit(appId); -} -# endif // Q_WS_X11 -#endif // QT_VERSION < 0x050000 - - -/*! - Returns true if another instance of this application is running; - otherwise false. - - This function does not find instances of this application that are - being run by a different user (on Windows: that are running in - another session). - - \sa sendMessage() -*/ - -bool QtSingleApplication::isRunning() -{ - return peer->isClient(); -} - - -/*! - Tries to send the text \a message to the currently running - instance. The QtSingleApplication object in the running instance - will emit the messageReceived() signal when it receives the - message. - - This function returns true if the message has been sent to, and - processed by, the current instance. If there is no instance - currently running, or if the running instance fails to process the - message within \a timeout milliseconds, this function return false. - - \sa isRunning(), messageReceived() -*/ -bool QtSingleApplication::sendMessage(const QString &message, int timeout) -{ - return peer->sendMessage(message, timeout); -} - - -/*! - Returns the application identifier. Two processes with the same - identifier will be regarded as instances of the same application. -*/ -QString QtSingleApplication::id() const -{ - return peer->applicationId(); -} - - -/*! - Sets the activation window of this application to \a aw. The - activation window is the widget that will be activated by - activateWindow(). This is typically the application's main window. - - If \a activateOnMessage is true (the default), the window will be - activated automatically every time a message is received, just prior - to the messageReceived() signal being emitted. - - \sa activateWindow(), messageReceived() -*/ - -void QtSingleApplication::setActivationWindow(QWidget* aw, bool activateOnMessage) -{ - actWin = aw; - if (activateOnMessage) - connect(peer, SIGNAL(messageReceived(const QString&)), this, SLOT(activateWindow())); - else - disconnect(peer, SIGNAL(messageReceived(const QString&)), this, SLOT(activateWindow())); -} - - -/*! - Returns the applications activation window if one has been set by - calling setActivationWindow(), otherwise returns 0. - - \sa setActivationWindow() -*/ -QWidget* QtSingleApplication::activationWindow() const -{ - return actWin; -} - - -/*! - De-minimizes, raises, and activates this application's activation window. - This function does nothing if no activation window has been set. - - This is a convenience function to show the user that this - application instance has been activated when he has tried to start - another instance. - - This function should typically be called in response to the - messageReceived() signal. By default, that will happen - automatically, if an activation window has been set. - - \sa setActivationWindow(), messageReceived(), initialize() -*/ -void QtSingleApplication::activateWindow() -{ - if (actWin) { - actWin->setWindowState(actWin->windowState() & ~Qt::WindowMinimized); - actWin->raise(); - actWin->activateWindow(); - } -} - - -/*! - \fn void QtSingleApplication::messageReceived(const QString& message) - - This signal is emitted when the current instance receives a \a - message from another instance of this application. - - \sa sendMessage(), setActivationWindow(), activateWindow() -*/ - - -/*! - \fn void QtSingleApplication::initialize(bool dummy = true) - - \obsolete -*/ diff --git a/src/app/qtsingleapplication/qtsingleapplication.h b/src/app/qtsingleapplication/qtsingleapplication.h deleted file mode 100644 index 049406f72..000000000 --- a/src/app/qtsingleapplication/qtsingleapplication.h +++ /dev/null @@ -1,105 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the Qt Solutions component. -** -** $QT_BEGIN_LICENSE:BSD$ -** You may use this file under the terms of the BSD license as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names -** of its contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QTSINGLEAPPLICATION_H -#define QTSINGLEAPPLICATION_H - -#include - -class QtLocalPeer; - -#if defined(Q_OS_WIN) -# if !defined(QT_QTSINGLEAPPLICATION_EXPORT) && !defined(QT_QTSINGLEAPPLICATION_IMPORT) -# define QT_QTSINGLEAPPLICATION_EXPORT -# elif defined(QT_QTSINGLEAPPLICATION_IMPORT) -# if defined(QT_QTSINGLEAPPLICATION_EXPORT) -# undef QT_QTSINGLEAPPLICATION_EXPORT -# endif -# define QT_QTSINGLEAPPLICATION_EXPORT __declspec(dllimport) -# elif defined(QT_QTSINGLEAPPLICATION_EXPORT) -# undef QT_QTSINGLEAPPLICATION_EXPORT -# define QT_QTSINGLEAPPLICATION_EXPORT __declspec(dllexport) -# endif -#else -# define QT_QTSINGLEAPPLICATION_EXPORT -#endif - -class QT_QTSINGLEAPPLICATION_EXPORT QtSingleApplication : public QApplication -{ - Q_OBJECT - -public: - QtSingleApplication(int &argc, char **argv, bool GUIenabled = true); - QtSingleApplication(const QString &id, int &argc, char **argv); -#if QT_VERSION < 0x050000 - QtSingleApplication(int &argc, char **argv, Type type); -# if defined(Q_WS_X11) - QtSingleApplication(Display* dpy, Qt::HANDLE visual = 0, Qt::HANDLE colormap = 0); - QtSingleApplication(Display *dpy, int &argc, char **argv, Qt::HANDLE visual = 0, Qt::HANDLE cmap= 0); - QtSingleApplication(Display* dpy, const QString &appId, int argc, char **argv, Qt::HANDLE visual = 0, Qt::HANDLE colormap = 0); -# endif // Q_WS_X11 -#endif // QT_VERSION < 0x050000 - - bool isRunning(); - QString id() const; - - void setActivationWindow(QWidget* aw, bool activateOnMessage = true); - QWidget* activationWindow() const; - - // Obsolete: - void initialize(bool dummy = true) - { isRunning(); Q_UNUSED(dummy) } - -public Q_SLOTS: - bool sendMessage(const QString &message, int timeout = 5000); - void activateWindow(); - - -Q_SIGNALS: - void messageReceived(const QString &message); - - -private: - void sysInit(const QString &appId = QString()); - QtLocalPeer *peer; - QWidget *actWin; -}; - -#endif // QTSINGLEAPPLICATION_H diff --git a/src/app/qtsingleapplication/qtsingleapplication.pri b/src/app/qtsingleapplication/qtsingleapplication.pri deleted file mode 100644 index 1d852858a..000000000 --- a/src/app/qtsingleapplication/qtsingleapplication.pri +++ /dev/null @@ -1,16 +0,0 @@ -INCLUDEPATH += $$PWD -DEPENDPATH += $$PWD -QT *= network -greaterThan(QT_MAJOR_VERSION, 4): QT *= widgets - -qtsingleapplication-uselib:!qtsingleapplication-buildlib { - LIBS += -L$$QTSINGLEAPPLICATION_LIBDIR -l$$QTSINGLEAPPLICATION_LIBNAME -} else { - SOURCES += $$PWD/qtsingleapplication.cpp $$PWD/qtlocalpeer.cpp - HEADERS += $$PWD/qtsingleapplication.h $$PWD/qtlocalpeer.h -} - -win32 { - contains(TEMPLATE, lib):contains(CONFIG, shared):DEFINES += QT_QTSINGLEAPPLICATION_EXPORT - else:qtsingleapplication-uselib:DEFINES += QT_QTSINGLEAPPLICATION_IMPORT -} diff --git a/src/app/qtsingleapplication/qtsinglecoreapplication.cpp b/src/app/qtsingleapplication/qtsinglecoreapplication.cpp deleted file mode 100644 index 563453732..000000000 --- a/src/app/qtsingleapplication/qtsinglecoreapplication.cpp +++ /dev/null @@ -1,149 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the Qt Solutions component. -** -** $QT_BEGIN_LICENSE:BSD$ -** You may use this file under the terms of the BSD license as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names -** of its contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - - -#include "qtsinglecoreapplication.h" -#include "qtlocalpeer.h" - -/*! - \class QtSingleCoreApplication qtsinglecoreapplication.h - \brief A variant of the QtSingleApplication class for non-GUI applications. - - This class is a variant of QtSingleApplication suited for use in - console (non-GUI) applications. It is an extension of - QCoreApplication (instead of QApplication). It does not require - the QtGui library. - - The API and usage is identical to QtSingleApplication, except that - functions relating to the "activation window" are not present, for - obvious reasons. Please refer to the QtSingleApplication - documentation for explanation of the usage. - - A QtSingleCoreApplication instance can communicate to a - QtSingleApplication instance if they share the same application - id. Hence, this class can be used to create a light-weight - command-line tool that sends commands to a GUI application. - - \sa QtSingleApplication -*/ - -/*! - Creates a QtSingleCoreApplication object. The application identifier - will be QCoreApplication::applicationFilePath(). \a argc and \a - argv are passed on to the QCoreAppliation constructor. -*/ - -QtSingleCoreApplication::QtSingleCoreApplication(int &argc, char **argv) - : QCoreApplication(argc, argv) -{ - peer = new QtLocalPeer(this); - connect(peer, SIGNAL(messageReceived(const QString&)), SIGNAL(messageReceived(const QString&))); -} - - -/*! - Creates a QtSingleCoreApplication object with the application - identifier \a appId. \a argc and \a argv are passed on to the - QCoreAppliation constructor. -*/ -QtSingleCoreApplication::QtSingleCoreApplication(const QString &appId, int &argc, char **argv) - : QCoreApplication(argc, argv) -{ - peer = new QtLocalPeer(this, appId); - connect(peer, SIGNAL(messageReceived(const QString&)), SIGNAL(messageReceived(const QString&))); -} - - -/*! - Returns true if another instance of this application is running; - otherwise false. - - This function does not find instances of this application that are - being run by a different user (on Windows: that are running in - another session). - - \sa sendMessage() -*/ - -bool QtSingleCoreApplication::isRunning() -{ - return peer->isClient(); -} - - -/*! - Tries to send the text \a message to the currently running - instance. The QtSingleCoreApplication object in the running instance - will emit the messageReceived() signal when it receives the - message. - - This function returns true if the message has been sent to, and - processed by, the current instance. If there is no instance - currently running, or if the running instance fails to process the - message within \a timeout milliseconds, this function return false. - - \sa isRunning(), messageReceived() -*/ - -bool QtSingleCoreApplication::sendMessage(const QString &message, int timeout) -{ - return peer->sendMessage(message, timeout); -} - - -/*! - Returns the application identifier. Two processes with the same - identifier will be regarded as instances of the same application. -*/ - -QString QtSingleCoreApplication::id() const -{ - return peer->applicationId(); -} - - -/*! - \fn void QtSingleCoreApplication::messageReceived(const QString& message) - - This signal is emitted when the current instance receives a \a - message from another instance of this application. - - \sa sendMessage() -*/ diff --git a/src/app/qtsingleapplication/qtsinglecoreapplication.h b/src/app/qtsingleapplication/qtsinglecoreapplication.h deleted file mode 100644 index b87fffe41..000000000 --- a/src/app/qtsingleapplication/qtsinglecoreapplication.h +++ /dev/null @@ -1,71 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the Qt Solutions component. -** -** $QT_BEGIN_LICENSE:BSD$ -** You may use this file under the terms of the BSD license as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names -** of its contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QTSINGLECOREAPPLICATION_H -#define QTSINGLECOREAPPLICATION_H - -#include - -class QtLocalPeer; - -class QtSingleCoreApplication : public QCoreApplication -{ - Q_OBJECT - -public: - QtSingleCoreApplication(int &argc, char **argv); - QtSingleCoreApplication(const QString &id, int &argc, char **argv); - - bool isRunning(); - QString id() const; - -public Q_SLOTS: - bool sendMessage(const QString &message, int timeout = 5000); - - -Q_SIGNALS: - void messageReceived(const QString &message); - - -private: - QtLocalPeer* peer; -}; - -#endif // QTSINGLECOREAPPLICATION_H diff --git a/src/app/qtsingleapplication/qtsinglecoreapplication.pri b/src/app/qtsingleapplication/qtsinglecoreapplication.pri deleted file mode 100644 index d2d6cc3e1..000000000 --- a/src/app/qtsingleapplication/qtsinglecoreapplication.pri +++ /dev/null @@ -1,10 +0,0 @@ -INCLUDEPATH += $$PWD -DEPENDPATH += $$PWD -HEADERS += $$PWD/qtsinglecoreapplication.h $$PWD/qtlocalpeer.h -SOURCES += $$PWD/qtsinglecoreapplication.cpp $$PWD/qtlocalpeer.cpp - -QT *= network - -win32:contains(TEMPLATE, lib):contains(CONFIG, shared) { - DEFINES += QT_QTSINGLECOREAPPLICATION_EXPORT=__declspec(dllexport) -} diff --git a/src/app/stacktrace.h b/src/app/stacktrace.h deleted file mode 100644 index 4bcccf859..000000000 --- a/src/app/stacktrace.h +++ /dev/null @@ -1,104 +0,0 @@ -// stacktrace.h (c) 2008, Timo Bingmann from http://idlebox.net/ -// published under the WTFPL v2.0 - -#ifndef _STACKTRACE_H_ -#define _STACKTRACE_H_ - -#include -#include -#include -#include - -#include - -/** Print a demangled stack backtrace of the caller function to FILE* out. */ -static inline void print_stacktrace(FILE *out = stderr, unsigned int max_frames = 63) -{ - fprintf(out, "stack trace:\n"); - - // storage array for stack trace address data - std::vector addrlist(max_frames + 1); - - // retrieve current stack addresses - int addrlen = backtrace(addrlist.data(), addrlist.size()); - - if (addrlen == 0) { - fprintf(out, " \n"); - return; - } - - // resolve addresses into strings containing "filename(function+address)", - // this array must be free()-ed - char * *symbollist = backtrace_symbols(addrlist.data(), addrlen); - - // allocate string which will be filled with the demangled function name - size_t funcnamesize = 256; - char *funcname = static_cast(malloc(funcnamesize)); - - int functionNamesFound = 0; - // iterate over the returned symbol lines. skip the first, it is the - // address of this function. - for (int i = 2; i < addrlen; i++) { - char *begin_name = 0, *begin_offset = 0, *end_offset = 0; - - // find parentheses and +address offset surrounding the mangled name: - // ./module(function+0x15c) [0x8048a6d] - // fprintf(out, "%s TT\n", symbollist[i]); - for (char *p = symbollist[i]; *p; ++p) { - if (*p == '(') { - begin_name = p; - } - else if (*p == '+') { - begin_offset = p; - } - else if ((*p == ')') && begin_offset) { - end_offset = p; - break; - } - } - - if (begin_name && begin_offset && end_offset - && (begin_name < begin_offset)) { - *begin_name++ = '\0'; - *begin_offset++ = '\0'; - *end_offset = '\0'; - - // mangled name is now in [begin_name, begin_offset) and caller - // offset in [begin_offset, end_offset). now apply - // __cxa_demangle(): - - int status; - char *ret = abi::__cxa_demangle(begin_name, - funcname, &funcnamesize, &status); - if (status == 0) { - funcname = ret; // use possibly realloc()-ed string - fprintf(out, " %s : %s+%s %s\n", - symbollist[i], funcname, begin_offset, ++end_offset); - } - else { - // demangling failed. Output function name as a C function with - // no arguments. - fprintf(out, " %s : %s()+%s %s\n", - symbollist[i], begin_name, begin_offset, ++end_offset); - } - ++functionNamesFound; - } - else { - // couldn't parse the line? print the whole line. - fprintf(out, " %s\n", symbollist[i]); - } - } - - if (!functionNamesFound) { - fprintf(out, "There were no function names found in the stack trace\n." - "Seems like debug symbols are not installed, and the stack trace is useless.\n"); - } - if (functionNamesFound < addrlen - 2) { - fprintf(out, "Consider installing debug symbols for packages containing files with empty" - " function names (i.e. empty braces \"()\") to make your stack trace more useful\n"); - } - free(funcname); - free(symbollist); -} - -#endif // _STACKTRACE_H_ diff --git a/src/app/stacktrace_win.h b/src/app/stacktrace_win.h deleted file mode 100644 index ca86ebd9d..000000000 --- a/src/app/stacktrace_win.h +++ /dev/null @@ -1,346 +0,0 @@ -/*************************************************************************** -* Copyright (C) 2005-09 by the Quassel Project * -* devel@quassel-irc.org * -* * -* 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) version 3. * -* * -* 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., * -* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * -***************************************************************************/ - -#ifndef STACKTRACE_WIN_H -#define STACKTRACE_WIN_H - -#include -#include -#include - -#include -#include -#ifdef __MINGW32__ -#include -#endif - -namespace straceWin -{ - void loadHelpStackFrame(IMAGEHLP_STACK_FRAME&, const STACKFRAME64&); - BOOL CALLBACK EnumSymbolsCB(PSYMBOL_INFO, ULONG, PVOID); - BOOL CALLBACK EnumModulesCB(LPCSTR, DWORD64, PVOID); - const QString getBacktrace(); - struct EnumModulesContext; - // Also works for MinGW64 -#ifdef __MINGW32__ - void demangle(QString& str); -#endif - - QString getSourcePathAndLineNumber(HANDLE hProcess, DWORD64 addr); - bool makeRelativePath(const QString& dir, QString& file); -} - -#ifdef __MINGW32__ -void straceWin::demangle(QString& str) -{ - char const* inStr = qPrintable("_" + str); // Really need that underline or demangling will fail - int status = 0; - size_t outSz = 0; - char* demangled_name = abi::__cxa_demangle(inStr, 0, &outSz, &status); - if (status == 0) { - str = QString::fromLocal8Bit(demangled_name); - if (outSz > 0) - free(demangled_name); - } -} -#endif - -void straceWin::loadHelpStackFrame(IMAGEHLP_STACK_FRAME& ihsf, const STACKFRAME64& stackFrame) -{ - ZeroMemory(&ihsf, sizeof(IMAGEHLP_STACK_FRAME)); - ihsf.InstructionOffset = stackFrame.AddrPC.Offset; - ihsf.FrameOffset = stackFrame.AddrFrame.Offset; -} - -BOOL CALLBACK straceWin::EnumSymbolsCB(PSYMBOL_INFO symInfo, ULONG size, PVOID user) -{ - Q_UNUSED(size) - QStringList* params = (QStringList*)user; - if (symInfo->Flags & SYMFLAG_PARAMETER) - params->append(symInfo->Name); - return TRUE; -} - - -struct straceWin::EnumModulesContext -{ - HANDLE hProcess; - QTextStream& stream; - EnumModulesContext(HANDLE hProcess, QTextStream& stream): hProcess(hProcess), stream(stream) {} -}; - -BOOL CALLBACK straceWin::EnumModulesCB(LPCSTR ModuleName, DWORD64 BaseOfDll, PVOID UserContext) -{ - Q_UNUSED(ModuleName) - IMAGEHLP_MODULE64 mod; - EnumModulesContext* context = (EnumModulesContext*)UserContext; - mod.SizeOfStruct = sizeof(IMAGEHLP_MODULE64); - if(SymGetModuleInfo64(context->hProcess, BaseOfDll, &mod)) { - QString moduleBase = QString("0x%1").arg(BaseOfDll, 16, 16, QLatin1Char('0')); - QString line = QString("%1 %2 Image: %3") - .arg(mod.ModuleName, -25) - .arg(moduleBase, -13) - .arg(mod.LoadedImageName); - context->stream << line << '\n'; - - QString pdbName(mod.LoadedPdbName); - if(!pdbName.isEmpty()) { - QString line2 = QString("%1 %2") - .arg("", 35) - .arg(pdbName); - context->stream << line2 << '\n'; - } - } - return TRUE; -} - - -/** -* Cuts off leading 'dir' path from 'file' path, otherwise leaves it unchanged -* returns true if 'dir' is an ancestor of 'file', otherwise - false -*/ -bool straceWin::makeRelativePath(const QString& dir, QString& file) -{ - QString d = QDir::toNativeSeparators(QDir(dir).absolutePath()); - QString f = QDir::toNativeSeparators(QFileInfo(file).absoluteFilePath()); - - // append separator at the end of dir - QChar separator = QDir::separator(); - if (!d.isEmpty() && (d[d.length() - 1] != separator)) - d += separator; - - if (f.startsWith(d, Qt::CaseInsensitive)) { - f.remove(0, d.length()); - file.swap(f); - - return true; - } - - return false; -} - -QString straceWin::getSourcePathAndLineNumber(HANDLE hProcess, DWORD64 addr) -{ - IMAGEHLP_LINE64 line = {0}; - line.SizeOfStruct = sizeof(IMAGEHLP_LINE64); - DWORD dwDisplacement = 0; - - if (SymGetLineFromAddr64(hProcess, addr, &dwDisplacement, &line)) { - QString path(line.FileName); - -#if defined STACKTRACE_WIN_PROJECT_PATH || defined STACKTRACE_WIN_MAKEFILE_PATH - -#define STACKTRACE_WIN_QUOTE(x) #x -#define STACKTRACE_WIN_STRING(x) STACKTRACE_WIN_QUOTE(x) - - //prune leading project directory path or build target directory path - - bool success = false; -#ifdef STACKTRACE_WIN_PROJECT_PATH - QString projectPath(STACKTRACE_WIN_STRING(STACKTRACE_WIN_PROJECT_PATH)); - success = makeRelativePath(projectPath, path); -#endif - -#ifdef STACKTRACE_WIN_MAKEFILE_PATH - if (!success) { - QString targetPath(STACKTRACE_WIN_STRING(STACKTRACE_WIN_MAKEFILE_PATH)); - makeRelativePath(targetPath, path); - } -#endif -#endif - return QString("%1 : %2").arg(path).arg(line.LineNumber); - } - - return QString(); -} - - -#if defined( _M_IX86 ) && defined(Q_CC_MSVC) -// Disable global optimization and ignore /GS waning caused by -// inline assembly. -// not needed with mingw cause we can tell mingw which registers we use -#pragma optimize("g", off) -#pragma warning(push) -#pragma warning(disable : 4748) -#endif -const QString straceWin::getBacktrace() -{ - DWORD MachineType; - CONTEXT Context; - STACKFRAME64 StackFrame; - -#ifdef _M_IX86 - ZeroMemory(&Context, sizeof(CONTEXT)); - Context.ContextFlags = CONTEXT_CONTROL; - - -#ifdef __MINGW32__ - asm ("Label:\n\t" - "movl %%ebp,%0;\n\t" - "movl %%esp,%1;\n\t" - "movl $Label,%%eax;\n\t" - "movl %%eax,%2;\n\t" - : "=r" (Context.Ebp),"=r" (Context.Esp),"=r" (Context.Eip) - : //no input - : "eax"); -#else - _asm { - Label: - mov [Context.Ebp], ebp; - mov [Context.Esp], esp; - mov eax, [Label]; - mov [Context.Eip], eax; - } -#endif -#else - RtlCaptureContext(&Context); -#endif - - ZeroMemory(&StackFrame, sizeof(STACKFRAME64)); -#ifdef _M_IX86 - MachineType = IMAGE_FILE_MACHINE_I386; - StackFrame.AddrPC.Offset = Context.Eip; - StackFrame.AddrPC.Mode = AddrModeFlat; - StackFrame.AddrFrame.Offset = Context.Ebp; - StackFrame.AddrFrame.Mode = AddrModeFlat; - StackFrame.AddrStack.Offset = Context.Esp; - StackFrame.AddrStack.Mode = AddrModeFlat; -#elif _M_X64 - MachineType = IMAGE_FILE_MACHINE_AMD64; - StackFrame.AddrPC.Offset = Context.Rip; - StackFrame.AddrPC.Mode = AddrModeFlat; - StackFrame.AddrFrame.Offset = Context.Rsp; - StackFrame.AddrFrame.Mode = AddrModeFlat; - StackFrame.AddrStack.Offset = Context.Rsp; - StackFrame.AddrStack.Mode = AddrModeFlat; -#elif _M_IA64 - MachineType = IMAGE_FILE_MACHINE_IA64; - StackFrame.AddrPC.Offset = Context.StIIP; - StackFrame.AddrPC.Mode = AddrModeFlat; - StackFrame.AddrFrame.Offset = Context.IntSp; - StackFrame.AddrFrame.Mode = AddrModeFlat; - StackFrame.AddrBStore.Offset = Context.RsBSP; - StackFrame.AddrBStore.Mode = AddrModeFlat; - StackFrame.AddrStack.Offset = Context.IntSp; - StackFrame.AddrStack.Mode = AddrModeFlat; -#else -#error "Unsupported platform" -#endif - - QString log; - QTextStream logStream(&log); - logStream << "```\n"; - - HANDLE hProcess = GetCurrentProcess(); - HANDLE hThread = GetCurrentThread(); - SymInitialize(hProcess, NULL, TRUE); - - DWORD64 dwDisplacement; - - ULONG64 buffer[(sizeof(SYMBOL_INFO) + - MAX_SYM_NAME * sizeof(TCHAR) + - sizeof(ULONG64) - 1) / sizeof(ULONG64)]; - PSYMBOL_INFO pSymbol = (PSYMBOL_INFO)buffer; - pSymbol->SizeOfStruct = sizeof(SYMBOL_INFO); - pSymbol->MaxNameLen = MAX_SYM_NAME; - - IMAGEHLP_MODULE64 mod; - mod.SizeOfStruct = sizeof(IMAGEHLP_MODULE64); - - IMAGEHLP_STACK_FRAME ihsf; - ZeroMemory(&ihsf, sizeof(IMAGEHLP_STACK_FRAME)); - - int i = 0; - - while(StackWalk64(MachineType, hProcess, hThread, &StackFrame, &Context, NULL, NULL, NULL, NULL)) { - if(i == 128) - break; - - loadHelpStackFrame(ihsf, StackFrame); - if(StackFrame.AddrPC.Offset != 0) { // Valid frame. - - QString fileName("???"); - if(SymGetModuleInfo64(hProcess, ihsf.InstructionOffset, &mod)) { - fileName = QString(mod.ImageName); - int slashPos = fileName.lastIndexOf('\\'); - if(slashPos != -1) - fileName = fileName.mid(slashPos + 1); - } - QString funcName; - QString sourceFile; - if(SymFromAddr(hProcess, ihsf.InstructionOffset, &dwDisplacement, pSymbol)) { - funcName = QString(pSymbol->Name); -#ifdef __MINGW32__ - demangle(funcName); -#endif - - // now ihsf.InstructionOffset points to the instruction that follows CALL instuction - // decrease the query address by one byte to point somewhere in the CALL instruction byte sequence - sourceFile = getSourcePathAndLineNumber(hProcess, ihsf.InstructionOffset - 1); - } - else { - funcName = QString("0x%1").arg(ihsf.InstructionOffset, 8, 16, QLatin1Char('0')); - } - SymSetContext(hProcess, &ihsf, NULL); -#ifndef __MINGW32__ - QStringList params; - SymEnumSymbols(hProcess, 0, NULL, EnumSymbolsCB, (PVOID)¶ms); -#endif - - QString insOffset = QString("0x%1").arg(ihsf.InstructionOffset, 16, 16, QLatin1Char('0')); - QString formatLine = "#%1 %2 %3 %4"; -#ifndef __MINGW32__ - formatLine += "(%5)"; -#endif - QString debugLine = formatLine - .arg(i, 3, 10) - .arg(fileName, -20) - .arg(insOffset, -11) - .arg(funcName) -#ifndef __MINGW32__ - .arg(params.join(", ")); - - if (!sourceFile.isEmpty()) - debugLine += QString("[ %1 ]").arg(sourceFile); -#else - ; -#endif - logStream << debugLine << '\n'; - i++; - } - else { - break; // we're at the end. - } - } - - //logStream << "\n\nList of linked Modules:\n"; - //EnumModulesContext modulesContext(hProcess, logStream); - //SymEnumerateModules64(hProcess, EnumModulesCB, (PVOID)&modulesContext); - SymCleanup(hProcess); - - logStream << "```"; - return log; -} -#if defined(_M_IX86) && defined(Q_CC_MSVC) -#pragma warning(pop) -#pragma optimize("g", on) -#endif - -#endif // STACKTRACE_WIN_H diff --git a/src/app/stacktrace_win_dlg.h b/src/app/stacktrace_win_dlg.h deleted file mode 100644 index e9e7ff307..000000000 --- a/src/app/stacktrace_win_dlg.h +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2015 The qBittorrent project - * - * 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. - * - */ - -#ifndef STACKTRACE_WIN_DLG_H -#define STACKTRACE_WIN_DLG_H - -#include -#include -#include "base/utils/misc.h" -#include "ui_stacktrace_win_dlg.h" - -class StraceDlg : public QDialog, private Ui::errorDialog -{ - Q_OBJECT - -public: - StraceDlg(QWidget* parent = 0) - : QDialog(parent) - { - setupUi(this); - } - - void setStacktraceString(const QString& trace) - { - // try to call Qt function as less as possible - QString htmlStr = QString( - "

" - "qBittorrent has crashed" - "

" - "

" - "Please file a bug report at " - "http://bugs.qbittorrent.org " - "and provide the following information:" - "

" - "


" - "

" -#if defined(__x86_64__) || defined(_M_X64) - "qBittorrent version: " QBT_VERSION " (64-bit)
" -#else - "qBittorrent version: " QBT_VERSION " (32-bit)
" -#endif - "Libtorrent version: %1
" - "Qt version: " QT_VERSION_STR "
" - "Boost version: %2
" - "OS version: %3" - "


" - "
%4
" - "



") - .arg(Utils::Misc::libtorrentVersionString()) - .arg(Utils::Misc::boostVersionString()) - .arg(Utils::Misc::osName()) - .arg(trace); - - errorText->setHtml(htmlStr); - } -}; - -#endif diff --git a/src/app/stacktrace_win_dlg.ui b/src/app/stacktrace_win_dlg.ui deleted file mode 100644 index 41f1fc7f9..000000000 --- a/src/app/stacktrace_win_dlg.ui +++ /dev/null @@ -1,35 +0,0 @@ - - - errorDialog - - - - 0 - 0 - 640 - 480 - - - - Crash info - - - - - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><br /></p></body></html> - - - true - - - - - - - - diff --git a/src/app/upgrade.h b/src/app/upgrade.h deleted file mode 100644 index 40c720f4d..000000000 --- a/src/app/upgrade.h +++ /dev/null @@ -1,275 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2015 Vladimir Golovnev - * - * 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. - */ - -#ifndef UPGRADE_H -#define UPGRADE_H - -#include -#if LIBTORRENT_VERSION_NUM >= 10100 -#include -#endif -#include -#include -#if LIBTORRENT_VERSION_NUM < 10100 -#include -#endif - - -#include -#include -#ifndef DISABLE_GUI -#include -#endif -#include -#include -#ifdef Q_OS_MAC -#include -#endif - -#include "base/logger.h" -#include "base/profile.h" -#include "base/utils/fs.h" -#include "base/utils/misc.h" -#include "base/utils/string.h" -#include "base/preferences.h" - -bool userAcceptsUpgrade() -{ -#ifdef DISABLE_GUI - std::cout << std::endl << "*** " << qPrintable(QObject::tr("Upgrade")) << " ***" << std::endl; - char ret = '\0'; - do { - std::cout << qPrintable(QObject::tr("You updated from an older version that saved things differently. You must migrate to the new saving system. You will not be able to use an older version than v3.3.0 again. Continue? [y/n]")) << std::endl; - ret = getchar(); // Read pressed key - } - while ((ret != 'y') && (ret != 'Y') && (ret != 'n') && (ret != 'N')); - - if ((ret == 'y') || (ret == 'Y')) - return true; -#else - QMessageBox msgBox; - msgBox.setText(QObject::tr("You updated from an older version that saved things differently. You must migrate to the new saving system. If you continue, you will not be able to use an older version than v3.3.0 again.")); - msgBox.setWindowTitle(QObject::tr("Upgrade")); - msgBox.addButton(QMessageBox::Abort); - msgBox.addButton(QMessageBox::Ok); - msgBox.setDefaultButton(QMessageBox::Abort); - msgBox.show(); // Need to be shown or to moveToCenter does not work - msgBox.move(Utils::Misc::screenCenter(&msgBox)); - if (msgBox.exec() == QMessageBox::Ok) - return true; -#endif - - return false; -} - -bool upgradeResumeFile(const QString &filepath, const QVariantHash &oldTorrent = QVariantHash()) -{ - QFile file1(filepath); - if (!file1.open(QIODevice::ReadOnly)) - return false; - - QByteArray data = file1.readAll(); - file1.close(); - - libtorrent::error_code ec; -#if LIBTORRENT_VERSION_NUM < 10100 - libtorrent::lazy_entry fastOld; - libtorrent::lazy_bdecode(data.constData(), data.constData() + data.size(), fastOld, ec); - if (ec || (fastOld.type() != libtorrent::lazy_entry::dict_t)) return false; -#else - libtorrent::bdecode_node fastOld; - libtorrent::bdecode(data.constData(), data.constData() + data.size(), fastOld, ec); - if (ec || (fastOld.type() != libtorrent::bdecode_node::dict_t)) return false; -#endif - - libtorrent::entry fastNew; - fastNew = fastOld; - - bool v3_3 = false; - int queuePosition = 0; - QString outFilePath = filepath; - QRegExp rx(QLatin1String("([A-Fa-f0-9]{40})\\.fastresume\\.(\\d+)$")); - if (rx.indexIn(filepath) != -1) { - // old v3.3.x format - queuePosition = rx.cap(2).toInt(); - v3_3 = true; - outFilePath.replace(QRegExp("\\.\\d+$"), ""); - } - else { - queuePosition = fastOld.dict_find_int_value("qBt-queuePosition", 0); - fastNew["qBt-name"] = oldTorrent.value("name").toString().toStdString(); - fastNew["qBt-tempPathDisabled"] = false; - } - - // in versions < 3.3 we have -1 for seeding torrents, so we convert it to 0 - fastNew["qBt-queuePosition"] = (queuePosition >= 0 ? queuePosition : 0); - - QFile file2(outFilePath); - QVector out; - libtorrent::bencode(std::back_inserter(out), fastNew); - if (file2.open(QIODevice::WriteOnly)) { - if (file2.write(&out[0], out.size()) == out.size()) { - if (v3_3) - Utils::Fs::forceRemove(filepath); - return true; - } - } - - return false; -} - -bool upgrade(bool ask = true) -{ - // Upgrade preferences - Preferences::instance()->upgrade(); - - QString backupFolderPath = Utils::Fs::expandPathAbs(specialFolderLocation(SpecialFolder::Data) + "BT_backup"); - QDir backupFolderDir(backupFolderPath); - - // **************************************************************************************** - // Silently converts old v3.3.x .fastresume files - QStringList backupFiles_3_3 = backupFolderDir.entryList( - QStringList(QLatin1String("*.fastresume.*")), QDir::Files, QDir::Unsorted); - foreach (const QString &backupFile, backupFiles_3_3) - upgradeResumeFile(backupFolderDir.absoluteFilePath(backupFile)); - // **************************************************************************************** - - SettingsPtr oldResumeSettings = Profile::instance().applicationSettings(QLatin1String("qBittorrent-resume")); - QString oldResumeFilename = oldResumeSettings->fileName(); - QVariantHash oldResumeData = oldResumeSettings->value("torrents").toHash(); - oldResumeSettings.reset(); - - if (oldResumeData.isEmpty()) { - Utils::Fs::forceRemove(oldResumeFilename); - return true; - } - - if (ask && !userAcceptsUpgrade()) return false; - - QStringList backupFiles = backupFolderDir.entryList( - QStringList(QLatin1String("*.fastresume")), QDir::Files, QDir::Unsorted); - QRegExp rx(QLatin1String("^([A-Fa-f0-9]{40})\\.fastresume$")); - foreach (QString backupFile, backupFiles) { - if (rx.indexIn(backupFile) != -1) { - if (upgradeResumeFile(backupFolderDir.absoluteFilePath(backupFile), oldResumeData[rx.cap(1)].toHash())) - oldResumeData.remove(rx.cap(1)); - else - Logger::instance()->addMessage(QObject::tr("Couldn't migrate torrent with hash: %1").arg(rx.cap(1)), Log::WARNING); - } - else { - Logger::instance()->addMessage(QObject::tr("Couldn't migrate torrent. Invalid fastresume file name: %1").arg(backupFile), Log::WARNING); - } - } - - foreach (const QString &hash, oldResumeData.keys()) { - QVariantHash oldTorrent = oldResumeData[hash].toHash(); - if (oldTorrent.value("is_magnet", false).toBool()) { - libtorrent::entry resumeData; - resumeData["qBt-magnetUri"] = oldTorrent.value("magnet_uri").toString().toStdString(); - resumeData["qBt-paused"] = false; - resumeData["qBt-forced"] = false; - - resumeData["qBt-savePath"] = oldTorrent.value("save_path").toString().toStdString(); - resumeData["qBt-ratioLimit"] = QString::number(oldTorrent.value("max_ratio", -2).toReal()).toStdString(); - resumeData["qBt-label"] = oldTorrent.value("label").toString().toStdString(); - resumeData["qBt-name"] = oldTorrent.value("name").toString().toStdString(); - resumeData["qBt-seedStatus"] = oldTorrent.value("seed").toBool(); - resumeData["qBt-tempPathDisabled"] = false; - - int queuePosition = oldTorrent.value("priority", 0).toInt(); - resumeData["qBt-queuePosition"] = (queuePosition >= 0 ? queuePosition : 0); - - QString filename = QString("%1.fastresume").arg(hash); - QString filepath = backupFolderDir.absoluteFilePath(filename); - - QFile resumeFile(filepath); - QVector out; - libtorrent::bencode(std::back_inserter(out), resumeData); - if (resumeFile.open(QIODevice::WriteOnly)) - resumeFile.write(&out[0], out.size()); - } - } - - int counter = 0; - QString backupResumeFilename = oldResumeFilename + ".bak"; - while (QFile::exists(backupResumeFilename)) { - ++counter; - backupResumeFilename = oldResumeFilename + ".bak" + QString::number(counter); - } - QFile::rename(oldResumeFilename, backupResumeFilename); - - return true; -} - -#ifdef Q_OS_MAC -void migratePlistToIni(const QString &application) -{ - QSettings iniFile(QSettings::IniFormat, QSettings::UserScope, "qBittorrent", application); - if (!iniFile.allKeys().isEmpty()) return; // We copy the contents of plist, only if inifile does not exist(is empty). - - QSettings *plistFile = new QSettings("qBittorrent", application); - plistFile->setFallbacksEnabled(false); - const QStringList plist = plistFile->allKeys(); - if (!plist.isEmpty()) { - foreach (const QString &key, plist) - iniFile.setValue(key, plistFile->value(key)); - plistFile->clear(); - } - - QString plistPath = plistFile->fileName(); - delete plistFile; - Utils::Fs::forceRemove(plistPath); -} - -void macMigratePlists() -{ - migratePlistToIni("qBittorrent-data"); - migratePlistToIni("qBittorrent-rss"); - migratePlistToIni("qBittorrent"); -} -#endif // Q_OS_MAC - -#ifndef DISABLE_GUI -void migrateRSS() -{ - // Copy old feed items to new file if needed - SettingsPtr qBTRSS = Profile::instance().applicationSettings(QLatin1String("qBittorrent-rss-feeds")); - if (!qBTRSS->allKeys().isEmpty()) return; // We move the contents of RSS old_items only if inifile does not exist (is empty). - - SettingsPtr qBTRSSLegacy = Profile::instance().applicationSettings(QLatin1String("qBittorrent-rss")); - QHash allOldItems = qBTRSSLegacy->value("old_items", QHash()).toHash(); - - if (!allOldItems.empty()) { - qDebug("Moving %d old items for feeds to qBittorrent-rss-feeds", allOldItems.size()); - qBTRSS->setValue("old_items", allOldItems); - qBTRSSLegacy->remove("old_items"); - } -} -#endif - -#endif // UPGRADE_H diff --git a/src/base/CMakeLists.txt b/src/base/CMakeLists.txt deleted file mode 100644 index 9ff9521ed..000000000 --- a/src/base/CMakeLists.txt +++ /dev/null @@ -1,145 +0,0 @@ -find_package(ZLIB 1.2.5.2 REQUIRED) - -set(QBT_BASE_HEADERS -bittorrent/addtorrentparams.h -bittorrent/cachestatus.h -bittorrent/infohash.h -bittorrent/magneturi.h -bittorrent/peerinfo.h -bittorrent/private/bandwidthscheduler.h -bittorrent/private/filterparserthread.h -bittorrent/private/resumedatasavingmanager.h -bittorrent/private/speedmonitor.h -bittorrent/private/statistics.h -bittorrent/session.h -bittorrent/sessionstatus.h -bittorrent/torrentcreatorthread.h -bittorrent/torrenthandle.h -bittorrent/torrentinfo.h -bittorrent/tracker.h -bittorrent/trackerentry.h -http/connection.h -http/irequesthandler.h -http/requestparser.h -http/responsebuilder.h -http/responsegenerator.h -http/server.h -http/types.h -net/dnsupdater.h -net/downloadhandler.h -net/downloadmanager.h -net/geoipmanager.h -net/portforwarder.h -net/private/geoipdatabase.h -net/proxyconfigurationmanager.h -net/reverseresolution.h -net/smtp.h -private/profile_p.h -rss/private/rss_parser.h -rss/rss_article.h -rss/rss_autodownloader.h -rss/rss_autodownloadrule.h -rss/rss_feed.h -rss/rss_folder.h -rss/rss_item.h -rss/rss_session.h -utils/fs.h -utils/gzip.h -utils/misc.h -utils/net.h -utils/random.h -utils/string.h -utils/version.h -asyncfilestorage.h -filesystemwatcher.h -global.h -iconprovider.h -indexrange.h -logger.h -preferences.h -profile.h -scanfoldersmodel.h -searchengine.h -settingsstorage.h -torrentfileguard.h -torrentfilter.h -tristatebool.h -types.h -unicodestrings.h -) - -set(QBT_BASE_SOURCES -bittorrent/infohash.cpp -bittorrent/magneturi.cpp -bittorrent/peerinfo.cpp -bittorrent/private/bandwidthscheduler.cpp -bittorrent/private/filterparserthread.cpp -bittorrent/private/resumedatasavingmanager.cpp -bittorrent/private/speedmonitor.cpp -bittorrent/private/statistics.cpp -bittorrent/session.cpp -bittorrent/torrentcreatorthread.cpp -bittorrent/torrenthandle.cpp -bittorrent/torrentinfo.cpp -bittorrent/tracker.cpp -bittorrent/trackerentry.cpp -http/connection.cpp -http/requestparser.cpp -http/responsebuilder.cpp -http/responsegenerator.cpp -http/server.cpp -net/dnsupdater.cpp -net/downloadhandler.cpp -net/downloadmanager.cpp -net/geoipmanager.cpp -net/portforwarder.cpp -net/private/geoipdatabase.cpp -net/proxyconfigurationmanager.cpp -net/reverseresolution.cpp -net/smtp.cpp -private/profile_p.cpp -rss/private/rss_parser.cpp -rss/rss_article.cpp -rss/rss_autodownloader.cpp -rss/rss_autodownloadrule.cpp -rss/rss_feed.cpp -rss/rss_folder.cpp -rss/rss_item.cpp -rss/rss_session.cpp -utils/fs.cpp -utils/gzip.cpp -utils/misc.cpp -utils/net.cpp -utils/random.cpp -utils/string.cpp -asyncfilestorage.cpp -filesystemwatcher.cpp -iconprovider.cpp -logger.cpp -preferences.cpp -profile.cpp -scanfoldersmodel.cpp -searchengine.cpp -settingsstorage.cpp -torrentfileguard.cpp -torrentfilter.cpp -tristatebool.cpp -) - -add_library(qbt_base STATIC ${QBT_BASE_HEADERS} ${QBT_BASE_SOURCES}) -target_link_libraries(qbt_base PRIVATE ZLIB::ZLIB PUBLIC LibtorrentRasterbar::LibTorrent) -target_link_qt_components(qbt_base PUBLIC Core Network Xml) - -if (GUI) - target_link_libraries(qbt_base PUBLIC Qt5::Gui Qt5::Widgets) -endif (GUI) - -if (DBUS) - target_link_qt_components(qbt_base PRIVATE DBus) -endif () - -if (APPLE) - find_library(IOKit_LIBRARY IOKit) - find_library(Carbon_LIBRARY Carbon) - target_link_libraries(qbt_base PRIVATE ${Carbon_LIBRARY} ${IOKit_LIBRARY}) -endif (APPLE) diff --git a/src/base/asyncfilestorage.cpp b/src/base/asyncfilestorage.cpp deleted file mode 100644 index 94402b924..000000000 --- a/src/base/asyncfilestorage.cpp +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2017 Vladimir Golovnev - * - * 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. - */ - -#include "asyncfilestorage.h" - -#include -#include -#include - -AsyncFileStorage::AsyncFileStorage(const QString &storageFolderPath, QObject *parent) - : QObject(parent) - , m_storageDir(storageFolderPath) - , m_lockFile(m_storageDir.absoluteFilePath(QStringLiteral("storage.lock"))) -{ - if (!m_storageDir.mkpath(m_storageDir.absolutePath())) - throw AsyncFileStorageError( - QString("Could not create directory '%1'.").arg(m_storageDir.absolutePath())); - - // TODO: This folder locking approach does not work for UNIX systems. Implement it. - if (!m_lockFile.open(QFile::WriteOnly)) - throw AsyncFileStorageError(m_lockFile.errorString()); -} - -AsyncFileStorage::~AsyncFileStorage() -{ - m_lockFile.close(); - m_lockFile.remove(); -} - -void AsyncFileStorage::store(const QString &fileName, const QByteArray &data) -{ - QMetaObject::invokeMethod(this, "store_impl", Qt::QueuedConnection - , Q_ARG(QString, fileName), Q_ARG(QByteArray, data)); -} - -QDir AsyncFileStorage::storageDir() const -{ - return m_storageDir; -} - -void AsyncFileStorage::store_impl(const QString &fileName, const QByteArray &data) -{ - const QString filePath = m_storageDir.absoluteFilePath(fileName); - QSaveFile file(filePath); - qDebug() << "AsyncFileStorage: Saving data to" << filePath; - if (file.open(QIODevice::WriteOnly)) { - file.write(data); - if (!file.commit()) { - qDebug() << "AsyncFileStorage: Failed to save data"; - emit failed(filePath, file.errorString()); - } - } -} - -AsyncFileStorageError::AsyncFileStorageError(const QString &message) - : std::runtime_error(message.toUtf8().data()) -{ -} - -QString AsyncFileStorageError::message() const -{ - return what(); -} diff --git a/src/base/asyncfilestorage.h b/src/base/asyncfilestorage.h deleted file mode 100644 index 79e53faf7..000000000 --- a/src/base/asyncfilestorage.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2017 Vladimir Golovnev - * - * 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. - */ - -#pragma once - -#include - -#include -#include -#include - -class AsyncFileStorageError: public std::runtime_error -{ -public: - explicit AsyncFileStorageError(const QString &message); - QString message() const; -}; - -class AsyncFileStorage: public QObject -{ - Q_OBJECT - -public: - explicit AsyncFileStorage(const QString &storageFolderPath, QObject *parent = nullptr); - ~AsyncFileStorage() override; - - void store(const QString &fileName, const QByteArray &data); - - QDir storageDir() const; - -signals: - void failed(const QString &fileName, const QString &errorString); - -private: - Q_INVOKABLE void store_impl(const QString &fileName, const QByteArray &data); - - QDir m_storageDir; - QFile m_lockFile; -}; diff --git a/src/base/base.pri b/src/base/base.pri deleted file mode 100644 index b302c9436..000000000 --- a/src/base/base.pri +++ /dev/null @@ -1,124 +0,0 @@ -HEADERS += \ - $$PWD/asyncfilestorage.h \ - $$PWD/types.h \ - $$PWD/tristatebool.h \ - $$PWD/filesystemwatcher.h \ - $$PWD/logger.h \ - $$PWD/settingsstorage.h \ - $$PWD/settingvalue.h \ - $$PWD/preferences.h \ - $$PWD/indexrange.h \ - $$PWD/iconprovider.h \ - $$PWD/http/irequesthandler.h \ - $$PWD/http/connection.h \ - $$PWD/http/requestparser.h \ - $$PWD/http/responsegenerator.h \ - $$PWD/http/server.h \ - $$PWD/http/types.h \ - $$PWD/http/responsebuilder.h \ - $$PWD/net/dnsupdater.h \ - $$PWD/net/downloadmanager.h \ - $$PWD/net/downloadhandler.h \ - $$PWD/net/geoipmanager.h \ - $$PWD/net/portforwarder.h \ - $$PWD/net/proxyconfigurationmanager.h \ - $$PWD/net/reverseresolution.h \ - $$PWD/net/smtp.h \ - $$PWD/net/private/geoipdatabase.h \ - $$PWD/bittorrent/addtorrentparams.h \ - $$PWD/bittorrent/infohash.h \ - $$PWD/bittorrent/session.h \ - $$PWD/bittorrent/sessionstatus.h \ - $$PWD/bittorrent/cachestatus.h \ - $$PWD/bittorrent/magneturi.h \ - $$PWD/bittorrent/torrentinfo.h \ - $$PWD/bittorrent/torrenthandle.h \ - $$PWD/bittorrent/peerinfo.h \ - $$PWD/bittorrent/trackerentry.h \ - $$PWD/bittorrent/tracker.h \ - $$PWD/bittorrent/torrentcreatorthread.h \ - $$PWD/bittorrent/private/speedmonitor.h \ - $$PWD/bittorrent/private/bandwidthscheduler.h \ - $$PWD/bittorrent/private/filterparserthread.h \ - $$PWD/bittorrent/private/statistics.h \ - $$PWD/bittorrent/private/resumedatasavingmanager.h \ - $$PWD/rss/rss_article.h \ - $$PWD/rss/rss_item.h \ - $$PWD/rss/rss_feed.h \ - $$PWD/rss/rss_folder.h \ - $$PWD/rss/rss_session.h \ - $$PWD/rss/rss_autodownloader.h \ - $$PWD/rss/rss_autodownloadrule.h \ - $$PWD/rss/private/rss_parser.h \ - $$PWD/utils/fs.h \ - $$PWD/utils/gzip.h \ - $$PWD/utils/misc.h \ - $$PWD/utils/net.h \ - $$PWD/utils/random.h \ - $$PWD/utils/string.h \ - $$PWD/utils/version.h \ - $$PWD/profile.h \ - $$PWD/private/profile_p.h \ - $$PWD/unicodestrings.h \ - $$PWD/torrentfileguard.h \ - $$PWD/torrentfilter.h \ - $$PWD/scanfoldersmodel.h \ - $$PWD/searchengine.h \ - $$PWD/global.h - -SOURCES += \ - $$PWD/asyncfilestorage.cpp \ - $$PWD/tristatebool.cpp \ - $$PWD/filesystemwatcher.cpp \ - $$PWD/logger.cpp \ - $$PWD/settingsstorage.cpp \ - $$PWD/preferences.cpp \ - $$PWD/iconprovider.cpp \ - $$PWD/http/connection.cpp \ - $$PWD/http/requestparser.cpp \ - $$PWD/http/responsegenerator.cpp \ - $$PWD/http/server.cpp \ - $$PWD/http/responsebuilder.cpp \ - $$PWD/net/dnsupdater.cpp \ - $$PWD/net/downloadmanager.cpp \ - $$PWD/net/downloadhandler.cpp \ - $$PWD/net/geoipmanager.cpp \ - $$PWD/net/portforwarder.cpp \ - $$PWD/net/proxyconfigurationmanager.cpp \ - $$PWD/net/reverseresolution.cpp \ - $$PWD/net/smtp.cpp \ - $$PWD/net/private/geoipdatabase.cpp \ - $$PWD/bittorrent/infohash.cpp \ - $$PWD/bittorrent/session.cpp \ - $$PWD/bittorrent/magneturi.cpp \ - $$PWD/bittorrent/torrentinfo.cpp \ - $$PWD/bittorrent/torrenthandle.cpp \ - $$PWD/bittorrent/peerinfo.cpp \ - $$PWD/bittorrent/trackerentry.cpp \ - $$PWD/bittorrent/tracker.cpp \ - $$PWD/bittorrent/torrentcreatorthread.cpp \ - $$PWD/bittorrent/private/speedmonitor.cpp \ - $$PWD/bittorrent/private/bandwidthscheduler.cpp \ - $$PWD/bittorrent/private/filterparserthread.cpp \ - $$PWD/bittorrent/private/statistics.cpp \ - $$PWD/bittorrent/private/resumedatasavingmanager.cpp \ - $$PWD/rss/rss_article.cpp \ - $$PWD/rss/rss_item.cpp \ - $$PWD/rss/rss_feed.cpp \ - $$PWD/rss/rss_folder.cpp \ - $$PWD/rss/rss_session.cpp \ - $$PWD/rss/rss_autodownloader.cpp \ - $$PWD/rss/rss_autodownloadrule.cpp \ - $$PWD/rss/private/rss_parser.cpp \ - $$PWD/utils/fs.cpp \ - $$PWD/utils/gzip.cpp \ - $$PWD/utils/misc.cpp \ - $$PWD/utils/net.cpp \ - $$PWD/utils/random.cpp \ - $$PWD/utils/string.cpp \ - $$PWD/profile.cpp \ - $$PWD/private/profile_p.cpp \ - $$PWD/torrentfileguard.cpp \ - $$PWD/torrentfilter.cpp \ - $$PWD/scanfoldersmodel.cpp \ - $$PWD/searchengine.cpp diff --git a/src/base/bittorrent/addtorrentparams.h b/src/base/bittorrent/addtorrentparams.h deleted file mode 100644 index 6976746f5..000000000 --- a/src/base/bittorrent/addtorrentparams.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2015 Vladimir Golovnev - * - * 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. - */ - -#pragma once - -#include -#include -#include - -#include "../tristatebool.h" - -namespace BitTorrent -{ - struct AddTorrentParams - { - QString name; - QString category; - QSet tags; - QString savePath; - bool disableTempPath = false; // e.g. for imported torrents - bool sequential = false; - bool firstLastPiecePriority = false; - TriStateBool addForced; - TriStateBool addPaused; - QVector filePriorities; // used if TorrentInfo is set - bool ignoreShareLimits = false; - bool skipChecking = false; - TriStateBool createSubfolder; - TriStateBool useAutoTMM; - }; -} diff --git a/src/base/bittorrent/cachestatus.h b/src/base/bittorrent/cachestatus.h deleted file mode 100644 index d5282c9d4..000000000 --- a/src/base/bittorrent/cachestatus.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2015, 2017 Vladimir Golovnev - * - * 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. - */ - -#ifndef BITTORRENT_CACHESTATUS_H -#define BITTORRENT_CACHESTATUS_H - -#include - -namespace BitTorrent -{ - struct CacheStatus - { - quint64 totalUsedBuffers = 0; - quint64 jobQueueLength = 0; - quint64 averageJobTime = 0; - quint64 queuedBytes = 0; - qreal readRatio = 0.0; - }; -} - -#endif // BITTORRENT_CACHESTATUS_H diff --git a/src/base/bittorrent/infohash.cpp b/src/base/bittorrent/infohash.cpp deleted file mode 100644 index 0e37c7509..000000000 --- a/src/base/bittorrent/infohash.cpp +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2015 Vladimir Golovnev - * - * 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. - */ - -#include -#include "infohash.h" - -using namespace BitTorrent; - -InfoHash::InfoHash() - : m_valid(false) -{ -} - -InfoHash::InfoHash(const libtorrent::sha1_hash &nativeHash) - : m_valid(true) - , m_nativeHash(nativeHash) -{ - char out[(libtorrent::sha1_hash::size * 2) + 1]; - libtorrent::to_hex(reinterpret_cast(&m_nativeHash[0]), libtorrent::sha1_hash::size, out); - m_hashString = QString(out); -} - -InfoHash::InfoHash(const QString &hashString) - : m_valid(false) - , m_hashString(hashString) -{ - QByteArray raw = m_hashString.toLatin1(); - if (raw.size() == 40) - m_valid = libtorrent::from_hex(raw.constData(), 40, reinterpret_cast(&m_nativeHash[0])); -} - - -InfoHash::InfoHash(const InfoHash &other) - : m_valid(other.m_valid) - , m_nativeHash(other.m_nativeHash) - , m_hashString(other.m_hashString) -{ -} - - -bool InfoHash::isValid() const -{ - return m_valid; -} - -InfoHash::operator libtorrent::sha1_hash() const -{ - return m_nativeHash; -} - - -InfoHash::operator QString() const -{ - return m_hashString; -} - - -bool InfoHash::operator==(const InfoHash &other) const -{ - return (m_nativeHash == other.m_nativeHash); -} - - -bool InfoHash::operator!=(const InfoHash &other) const -{ - return (m_nativeHash != other.m_nativeHash); -} - -uint qHash(const InfoHash &key, uint seed) -{ - return qHash(static_cast(key), seed); -} diff --git a/src/base/bittorrent/infohash.h b/src/base/bittorrent/infohash.h deleted file mode 100644 index 7a1a49150..000000000 --- a/src/base/bittorrent/infohash.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2015 Vladimir Golovnev - * - * 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. - */ - -#ifndef BITTORRENT_INFOHASH_H -#define BITTORRENT_INFOHASH_H - -#include -#include - -namespace BitTorrent -{ - class InfoHash - { - public: - InfoHash(); - InfoHash(const libtorrent::sha1_hash &nativeHash); - InfoHash(const QString &hashString); - InfoHash(const InfoHash &other); - - bool isValid() const; - - operator libtorrent::sha1_hash() const; - operator QString() const; - bool operator==(const InfoHash &other) const; - bool operator!=(const InfoHash &other) const; - - private: - bool m_valid; - libtorrent::sha1_hash m_nativeHash; - QString m_hashString; - }; -} - -uint qHash(const BitTorrent::InfoHash &key, uint seed); - -#endif // BITTORRENT_INFOHASH_H diff --git a/src/base/bittorrent/magneturi.cpp b/src/base/bittorrent/magneturi.cpp deleted file mode 100644 index a3a7c8325..000000000 --- a/src/base/bittorrent/magneturi.cpp +++ /dev/null @@ -1,125 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2015 Vladimir Golovnev - * - * 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. - */ - -#include -#include -#include - -#include -#include -#include - -#include "base/utils/string.h" -#include "magneturi.h" - -namespace -{ - QString bcLinkToMagnet(QString bcLink) - { - QByteArray rawBc = bcLink.toUtf8(); - rawBc = rawBc.mid(8); // skip bc://bt/ - rawBc = QByteArray::fromBase64(rawBc); // Decode base64 - // Format is now AA/url_encoded_filename/size_bytes/info_hash/ZZ - QStringList parts = QString(rawBc).split("/"); - if (parts.size() != 5) return QString(); - - QString filename = parts.at(1); - QString hash = parts.at(3); - QString magnet = "magnet:?xt=urn:btih:" + hash; - magnet += "&dn=" + filename; - return magnet; - } -} - -namespace libt = libtorrent; -using namespace BitTorrent; - -MagnetUri::MagnetUri(const QString &source) - : m_valid(false) - , m_url(source) -{ - if (source.isEmpty()) return; - - if (source.startsWith("bc://bt/", Qt::CaseInsensitive)) { - qDebug("Creating magnet link from bc link"); - m_url = bcLinkToMagnet(source); - } - else if (((source.size() == 40) && !source.contains(QRegExp("[^0-9A-Fa-f]"))) - || ((source.size() == 32) && !source.contains(QRegExp("[^2-7A-Za-z]")))) { - m_url = "magnet:?xt=urn:btih:" + source; - } - - libt::error_code ec; - libt::parse_magnet_uri(m_url.toUtf8().constData(), m_addTorrentParams, ec); - if (ec) return; - - m_valid = true; - m_hash = m_addTorrentParams.info_hash; - m_name = QString::fromStdString(m_addTorrentParams.name); - - foreach (const std::string &tracker, m_addTorrentParams.trackers) - m_trackers.append(QString::fromStdString(tracker)); - - foreach (const std::string &urlSeed, m_addTorrentParams.url_seeds) - m_urlSeeds.append(QUrl(urlSeed.c_str())); -} - -bool MagnetUri::isValid() const -{ - return m_valid; -} - -InfoHash MagnetUri::hash() const -{ - return m_hash; -} - -QString MagnetUri::name() const -{ - return m_name; -} - -QList MagnetUri::trackers() const -{ - return m_trackers; -} - -QList MagnetUri::urlSeeds() const -{ - return m_urlSeeds; -} - -QString MagnetUri::url() const -{ - return m_url; -} - -libtorrent::add_torrent_params MagnetUri::addTorrentParams() const -{ - return m_addTorrentParams; -} diff --git a/src/base/bittorrent/magneturi.h b/src/base/bittorrent/magneturi.h deleted file mode 100644 index e7e23becf..000000000 --- a/src/base/bittorrent/magneturi.h +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2015 Vladimir Golovnev - * - * 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. - */ - -#ifndef BITTORRENT_MAGNETURI_H -#define BITTORRENT_MAGNETURI_H - -#include -#include -#include - -#include - -#include "infohash.h" -#include "trackerentry.h" - -namespace BitTorrent -{ - class MagnetUri - { - public: - explicit MagnetUri(const QString &source = QString()); - - bool isValid() const; - InfoHash hash() const; - QString name() const; - QList trackers() const; - QList urlSeeds() const; - QString url() const; - - libtorrent::add_torrent_params addTorrentParams() const; - - private: - bool m_valid; - QString m_url; - InfoHash m_hash; - QString m_name; - QList m_trackers; - QList m_urlSeeds; - libtorrent::add_torrent_params m_addTorrentParams; - }; -} - -#endif // BITTORRENT_MAGNETURI_H diff --git a/src/base/bittorrent/peerinfo.cpp b/src/base/bittorrent/peerinfo.cpp deleted file mode 100644 index d054e38d7..000000000 --- a/src/base/bittorrent/peerinfo.cpp +++ /dev/null @@ -1,409 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2015 Vladimir Golovnev - * - * 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. - */ - -#include "base/net/geoipmanager.h" -#include "base/utils/string.h" -#include "base/unicodestrings.h" -#include "base/bittorrent/torrenthandle.h" -#include "peerinfo.h" - -namespace libt = libtorrent; -using namespace BitTorrent; - -// PeerAddress - -PeerAddress::PeerAddress() - : port(0) -{ -} - -PeerAddress::PeerAddress(QHostAddress ip, ushort port) - : ip(ip) - , port(port) -{ -} - -// PeerInfo - -PeerInfo::PeerInfo(const TorrentHandle *torrent, const libt::peer_info &nativeInfo) - : m_nativeInfo(nativeInfo) -{ - calcRelevance(torrent); - determineFlags(); -} - -bool PeerInfo::fromDHT() const -{ - return (m_nativeInfo.source & libt::peer_info::dht); -} - -bool PeerInfo::fromPeX() const -{ - return (m_nativeInfo.source & libt::peer_info::pex); -} - -bool PeerInfo::fromLSD() const -{ - return (m_nativeInfo.source & libt::peer_info::lsd); -} - -#ifndef DISABLE_COUNTRIES_RESOLUTION -QString PeerInfo::country() const -{ - return Net::GeoIPManager::instance()->lookup(address().ip); -} -#endif - -bool PeerInfo::isInteresting() const -{ - return (m_nativeInfo.flags & libt::peer_info::interesting); -} - -bool PeerInfo::isChocked() const -{ - return (m_nativeInfo.flags & libt::peer_info::choked); -} - -bool PeerInfo::isRemoteInterested() const -{ - return (m_nativeInfo.flags & libt::peer_info::remote_interested); -} - -bool PeerInfo::isRemoteChocked() const -{ - return (m_nativeInfo.flags & libt::peer_info::remote_choked); -} - - -bool PeerInfo::isSupportsExtensions() const -{ - return (m_nativeInfo.flags & libt::peer_info::supports_extensions); -} - -bool PeerInfo::isLocalConnection() const -{ - return (m_nativeInfo.flags & libt::peer_info::local_connection); -} - -bool PeerInfo::isHandshake() const -{ - return (m_nativeInfo.flags & libt::peer_info::handshake); -} - - -bool PeerInfo::isConnecting() const -{ - return (m_nativeInfo.flags & libt::peer_info::connecting); -} - -bool PeerInfo::isOnParole() const -{ - return (m_nativeInfo.flags & libt::peer_info::on_parole); -} - -bool PeerInfo::isSeed() const -{ - return (m_nativeInfo.flags & libt::peer_info::seed); -} - -bool PeerInfo::optimisticUnchoke() const -{ - return (m_nativeInfo.flags & libt::peer_info::optimistic_unchoke); -} - - -bool PeerInfo::isSnubbed() const -{ - return (m_nativeInfo.flags & libt::peer_info::snubbed); -} - -bool PeerInfo::isUploadOnly() const -{ - return (m_nativeInfo.flags & libt::peer_info::upload_only); -} - -bool PeerInfo::isEndgameMode() const -{ - return (m_nativeInfo.flags & libt::peer_info::endgame_mode); -} - - -bool PeerInfo::isHolepunched() const -{ - return (m_nativeInfo.flags & libt::peer_info::holepunched); -} - -bool PeerInfo::useI2PSocket() const -{ - return (m_nativeInfo.flags & libt::peer_info::i2p_socket); -} - -bool PeerInfo::useUTPSocket() const -{ - return (m_nativeInfo.flags & libt::peer_info::utp_socket); -} - -bool PeerInfo::useSSLSocket() const -{ - return (m_nativeInfo.flags & libt::peer_info::ssl_socket); -} - -bool PeerInfo::isRC4Encrypted() const -{ - return (m_nativeInfo.flags & libt::peer_info::rc4_encrypted); -} - -bool PeerInfo::isPlaintextEncrypted() const -{ - return (m_nativeInfo.flags & libt::peer_info::plaintext_encrypted); -} - - -PeerAddress PeerInfo::address() const -{ - return PeerAddress(QHostAddress(QString::fromStdString(m_nativeInfo.ip.address().to_string())), - m_nativeInfo.ip.port()); -} - -QString PeerInfo::client() const -{ - return QString::fromStdString(m_nativeInfo.client); -} - - -qreal PeerInfo::progress() const -{ - return m_nativeInfo.progress; -} - -int PeerInfo::payloadUpSpeed() const -{ - return m_nativeInfo.payload_up_speed; -} - - -int PeerInfo::payloadDownSpeed() const -{ - return m_nativeInfo.payload_down_speed; -} - -qlonglong PeerInfo::totalUpload() const -{ - return m_nativeInfo.total_upload; -} - - -qlonglong PeerInfo::totalDownload() const -{ - return m_nativeInfo.total_download; -} - -QBitArray PeerInfo::pieces() const -{ - QBitArray result(m_nativeInfo.pieces.size()); - - for (int i = 0; i < m_nativeInfo.pieces.size(); ++i) - result.setBit(i, m_nativeInfo.pieces.get_bit(i)); - - return result; -} - -QString PeerInfo::connectionType() const -{ - if (m_nativeInfo.flags & libt::peer_info::utp_socket) - return QString::fromUtf8(C_UTP); - - QString connection; - switch(m_nativeInfo.connection_type) { - case libt::peer_info::http_seed: - case libt::peer_info::web_seed: - connection = "Web"; - break; - default: - connection = "BT"; - } - - return connection; -} - -void PeerInfo::calcRelevance(const TorrentHandle *torrent) -{ - const QBitArray &allPieces = torrent->pieces(); - const QBitArray &peerPieces = pieces(); - - int localMissing = 0; - int remoteHaves = 0; - - for (int i = 0; i < allPieces.size(); ++i) { - if (!allPieces[i]) { - ++localMissing; - if (peerPieces[i]) - ++remoteHaves; - } - } - - if (localMissing == 0) - m_relevance = 0.0; - else - m_relevance = static_cast(remoteHaves) / localMissing; -} - -qreal PeerInfo::relevance() const -{ - return m_relevance; -} - -void PeerInfo::determineFlags() -{ - if (isInteresting()) { - //d = Your client wants to download, but peer doesn't want to send (interested and choked) - if (isRemoteChocked()) { - m_flags += "d "; - m_flagsDescription += tr("interested(local) and choked(peer)"); - m_flagsDescription += ", "; - } - else { - //D = Currently downloading (interested and not choked) - m_flags += "D "; - m_flagsDescription += tr("interested(local) and unchoked(peer)"); - m_flagsDescription += ", "; - } - } - - if (isRemoteInterested()) { - //u = Peer wants your client to upload, but your client doesn't want to (interested and choked) - if (isChocked()) { - m_flags += "u "; - m_flagsDescription += tr("interested(peer) and choked(local)"); - m_flagsDescription += ", "; - } - else { - //U = Currently uploading (interested and not choked) - m_flags += "U "; - m_flagsDescription += tr("interested(peer) and unchoked(local)"); - m_flagsDescription += ", "; - } - } - - //O = Optimistic unchoke - if (optimisticUnchoke()) { - m_flags += "O "; - m_flagsDescription += tr("optimistic unchoke"); - m_flagsDescription += ", "; - } - - //S = Peer is snubbed - if (isSnubbed()) { - m_flags += "S "; - m_flagsDescription += tr("peer snubbed"); - m_flagsDescription += ", "; - } - - //I = Peer is an incoming connection - if (!isLocalConnection()) { - m_flags += "I "; - m_flagsDescription += tr("incoming connection"); - m_flagsDescription += ", "; - } - - //K = Peer is unchoking your client, but your client is not interested - if (!isRemoteChocked() && !isInteresting()) { - m_flags += "K "; - m_flagsDescription += tr("not interested(local) and unchoked(peer)"); - m_flagsDescription += ", "; - } - - //? = Your client unchoked the peer but the peer is not interested - if (!isChocked() && !isRemoteInterested()) { - m_flags += "? "; - m_flagsDescription += tr("not interested(peer) and unchoked(local)"); - m_flagsDescription += ", "; - } - - //X = Peer was included in peerlists obtained through Peer Exchange (PEX) - if (fromPeX()) { - m_flags += "X "; - m_flagsDescription += tr("peer from PEX"); - m_flagsDescription += ", "; - } - - //H = Peer was obtained through DHT - if (fromDHT()) { - m_flags += "H "; - m_flagsDescription += tr("peer from DHT"); - m_flagsDescription += ", "; - } - - //E = Peer is using Protocol Encryption (all traffic) - if (isRC4Encrypted()) { - m_flags += "E "; - m_flagsDescription += tr("encrypted traffic"); - m_flagsDescription += ", "; - } - - //e = Peer is using Protocol Encryption (handshake) - if (isPlaintextEncrypted()) { - m_flags += "e "; - m_flagsDescription += tr("encrypted handshake"); - m_flagsDescription += ", "; - } - - //P = Peer is using uTorrent uTP - - if (useUTPSocket()) { - m_flags += "P "; - m_flagsDescription += QString::fromUtf8(C_UTP); - m_flagsDescription += ", "; - } - - //L = Peer is local - if (fromLSD()) { - m_flags += "L"; - m_flagsDescription += tr("peer from LSD"); - } - - m_flags = m_flags.trimmed(); - m_flagsDescription = m_flagsDescription.trimmed(); - if (m_flagsDescription.endsWith(',', Qt::CaseInsensitive)) - m_flagsDescription.chop(1); -} - -QString PeerInfo::flags() const -{ - return m_flags; -} - -QString PeerInfo::flagsDescription() const -{ - return m_flagsDescription; -} - -int PeerInfo::downloadingPieceIndex() const -{ - return m_nativeInfo.downloading_piece_index; -} diff --git a/src/base/bittorrent/peerinfo.h b/src/base/bittorrent/peerinfo.h deleted file mode 100644 index 0d096c493..000000000 --- a/src/base/bittorrent/peerinfo.h +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2015 Vladimir Golovnev - * - * 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. - */ - -#ifndef BITTORRENT_PEERINFO_H -#define BITTORRENT_PEERINFO_H - -#include - -#include -#include -#include - -namespace BitTorrent -{ - class TorrentHandle; - - struct PeerAddress - { - QHostAddress ip; - ushort port; - - PeerAddress(); - PeerAddress(QHostAddress ip, ushort port); - }; - - class PeerInfo - { - Q_DECLARE_TR_FUNCTIONS(PeerInfo) - - public: - PeerInfo(const TorrentHandle *torrent, const libtorrent::peer_info &nativeInfo); - - bool fromDHT() const; - bool fromPeX() const; - bool fromLSD() const; - - bool isInteresting() const; - bool isChocked() const; - bool isRemoteInterested() const; - bool isRemoteChocked() const; - bool isSupportsExtensions() const; - bool isLocalConnection() const; - - bool isHandshake() const; - bool isConnecting() const; - bool isOnParole() const; - bool isSeed() const; - - bool optimisticUnchoke() const; - bool isSnubbed() const; - bool isUploadOnly() const; - bool isEndgameMode() const; - bool isHolepunched() const; - - bool useI2PSocket() const; - bool useUTPSocket() const; - bool useSSLSocket() const; - - bool isRC4Encrypted() const; - bool isPlaintextEncrypted() const; - - PeerAddress address() const; - QString client() const; - qreal progress() const; - int payloadUpSpeed() const; - int payloadDownSpeed() const; - qlonglong totalUpload() const; - qlonglong totalDownload() const; - QBitArray pieces() const; - QString connectionType() const; - qreal relevance() const; - QString flags() const; - QString flagsDescription() const; -#ifndef DISABLE_COUNTRIES_RESOLUTION - QString country() const; -#endif - int downloadingPieceIndex() const; - - private: - void calcRelevance(const TorrentHandle *torrent); - void determineFlags(); - - libtorrent::peer_info m_nativeInfo; - qreal m_relevance; - QString m_flags; - QString m_flagsDescription; - }; -} - -#endif // BITTORRENT_PEERINFO_H diff --git a/src/base/bittorrent/private/bandwidthscheduler.cpp b/src/base/bittorrent/private/bandwidthscheduler.cpp deleted file mode 100644 index ee009ac55..000000000 --- a/src/base/bittorrent/private/bandwidthscheduler.cpp +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2010 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 -#include - -#include "base/bittorrent/session.h" -#include "base/preferences.h" -#include "bandwidthscheduler.h" - -BandwidthScheduler::BandwidthScheduler(QObject *parent) - : QTimer(parent) -{ - // Single shot, we call start() again manually - setSingleShot(true); - // Connect Signals/Slots - connect(this, SIGNAL(timeout()), this, SLOT(start())); -} - -void BandwidthScheduler::start() -{ - const Preferences* const pref = Preferences::instance(); - bool alt_bw_enabled = BitTorrent::Session::instance()->isAltGlobalSpeedLimitEnabled(); - - QTime start = pref->getSchedulerStartTime(); - QTime end = pref->getSchedulerEndTime(); - QTime now = QTime::currentTime(); - int sched_days = pref->getSchedulerDays(); - int day = QDateTime::currentDateTime().toLocalTime().date().dayOfWeek(); - bool new_mode = false; - bool reverse = false; - - if (start > end) { - QTime temp = start; - start = end; - end = temp; - reverse = true; - } - - if ((start <= now) && (end >= now)) { - switch(sched_days) { - case EVERY_DAY: - new_mode = true; - break; - case WEEK_ENDS: - if ((day == 6) || (day == 7)) - new_mode = true; - break; - case WEEK_DAYS: - if ((day != 6) && (day != 7)) - new_mode = true; - break; - default: - if (day == (sched_days - 2)) - new_mode = true; - } - } - - if (reverse) - new_mode = !new_mode; - - if (new_mode != alt_bw_enabled) - emit switchToAlternativeMode(new_mode); - - // Timeout regularly to accommodate for external system clock changes - // eg from the user or from a timesync utility - QTimer::start(1500); -} diff --git a/src/base/bittorrent/private/bandwidthscheduler.h b/src/base/bittorrent/private/bandwidthscheduler.h deleted file mode 100644 index 5b68f82b6..000000000 --- a/src/base/bittorrent/private/bandwidthscheduler.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2010 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 BANDWIDTHSCHEDULER_H -#define BANDWIDTHSCHEDULER_H - -#include - -class BandwidthScheduler : public QTimer -{ - Q_OBJECT - -public: - BandwidthScheduler(QObject *parent = 0); - -public slots: - void start(); - -signals: - void switchToAlternativeMode(bool alternative); -}; - -#endif // BANDWIDTHSCHEDULER_H diff --git a/src/base/bittorrent/private/filterparserthread.cpp b/src/base/bittorrent/private/filterparserthread.cpp deleted file mode 100644 index a3304815e..000000000 --- a/src/base/bittorrent/private/filterparserthread.cpp +++ /dev/null @@ -1,608 +0,0 @@ -/* - * Bittorrent Client using Qt and libt. - * Copyright (C) 2006 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 "filterparserthread.h" - -#include -#include - -#include - -#include "base/logger.h" - -namespace libt = libtorrent; - -namespace -{ - class IPv4Parser - { - public: - bool tryParse(const char *str) - { - unsigned char octetIndex = 0; - - const char *octetStart = str; - char *endptr; - for (; *str; ++str) { - if (*str == '.') { - long int extractedNum = strtol(octetStart, &endptr, 10); - if ((extractedNum >= 0L) && (extractedNum <= 255L)) - m_buf[octetIndex++] = static_cast(extractedNum); - else - return false; - - if (endptr != str) - return false; - if (octetIndex == 4) - return true; - - octetStart = str + 1; - } - } - - if (str != octetStart) { - long int extractedNum = strtol(octetStart, &endptr, 10); - if ((extractedNum >= 0L) && (extractedNum <= 255L)) - m_buf[octetIndex] = static_cast(strtol(octetStart, &endptr, 10)); - else - return false; - - if ((endptr == str) && (octetIndex == 3)) - return true; - } - - return false; - } - - libt::address_v4::bytes_type parsed() const - { - return m_buf; - } - - private: - libt::address_v4::bytes_type m_buf; - }; - - bool parseIPAddress(const char *data, libt::address &address) - { - IPv4Parser parser; - boost::system::error_code ec; - - if (parser.tryParse(data)) - address = libt::address_v4(parser.parsed()); - else - address = libt::address_v6::from_string(data, ec); - - return !ec; - } - - const int BUFFER_SIZE = 2 * 1024 * 1024; // 2 MiB -} - -FilterParserThread::FilterParserThread(QObject *parent) - : QThread(parent) - , m_abort(false) -{ -} - -FilterParserThread::~FilterParserThread() -{ - m_abort = true; - wait(); -} - -// Parser for eMule ip filter in DAT format -int FilterParserThread::parseDATFilterFile() -{ - int ruleCount = 0; - QFile file(m_filePath); - if (!file.exists()) return ruleCount; - - if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { - LogMsg(tr("I/O Error: Could not open ip filter file in read mode."), Log::CRITICAL); - return ruleCount; - } - - std::vector buffer(BUFFER_SIZE, 0); // seems a bit faster than QVector - qint64 bytesRead = 0; - int offset = 0; - int start = 0; - int endOfLine = -1; - int nbLine = 0; - - while (true) { - bytesRead = file.read(buffer.data() + offset, BUFFER_SIZE - offset - 1); - if (bytesRead < 0) - break; - int dataSize = bytesRead + offset; - if (bytesRead == 0 && dataSize == 0) - break; - - for (start = 0; start < dataSize; ++start) { - endOfLine = -1; - // The file might have ended without the last line having a newline - if (!(bytesRead == 0 && dataSize > 0)) { - for (int i = start; i < dataSize; ++i) { - if (buffer[i] == '\n') { - endOfLine = i; - // We need to NULL the newline in case the line has only an IP range. - // In that case the parser won't work for the end IP, because it ends - // with the newline and not with a number. - buffer[i] = '\0'; - break; - } - } - } - else { - endOfLine = dataSize; - buffer[dataSize] = '\0'; - } - - if (endOfLine == -1) { - // read the next chunk from file - // but first move(copy) the leftover data to the front of the buffer - offset = dataSize - start; - memmove(buffer.data(), buffer.data() + start, offset); - break; - } - else { - ++nbLine; - } - - if ((buffer[start] == '#') - || ((buffer[start] == '/') && ((start + 1 < dataSize) && (buffer[start + 1] == '/')))) { - start = endOfLine; - continue; - } - - // Each line should follow this format: - // 001.009.096.105 - 001.009.096.105 , 000 , Some organization - // The 3rd entry is access level and if above 127 the IP range isn't blocked. - int firstComma = findAndNullDelimiter(buffer.data(), ',', start, endOfLine); - if (firstComma != -1) - findAndNullDelimiter(buffer.data(), ',', firstComma + 1, endOfLine); - - // Check if there is an access value (apparently not mandatory) - if (firstComma != -1) { - // There is possibly one - const long int nbAccess = strtol(buffer.data() + firstComma + 1, nullptr, 10); - // Ignoring this rule because access value is too high - if (nbAccess > 127L) { - start = endOfLine; - continue; - } - } - - // IP Range should be split by a dash - int endOfIPRange = ((firstComma == -1) ? (endOfLine - 1) : (firstComma - 1)); - int delimIP = findAndNullDelimiter(buffer.data(), '-', start, endOfIPRange); - if (delimIP == -1) { - LogMsg(tr("IP filter line %1 is malformed.").arg(nbLine), Log::CRITICAL); - start = endOfLine; - continue; - } - - libt::address startAddr; - int newStart = trim(buffer.data(), start, delimIP - 1); - if (!parseIPAddress(buffer.data() + newStart, startAddr)) { - LogMsg(tr("IP filter line %1 is malformed. Start IP of the range is malformed.").arg(nbLine), Log::CRITICAL); - start = endOfLine; - continue; - } - - libt::address endAddr; - newStart = trim(buffer.data(), delimIP + 1, endOfIPRange); - if (!parseIPAddress(buffer.data() + newStart, endAddr)) { - LogMsg(tr("IP filter line %1 is malformed. End IP of the range is malformed.").arg(nbLine), Log::CRITICAL); - start = endOfLine; - continue; - } - - if ((startAddr.is_v4() != endAddr.is_v4()) - || (startAddr.is_v6() != endAddr.is_v6())) { - LogMsg(tr("IP filter line %1 is malformed. One IP is IPv4 and the other is IPv6!").arg(nbLine), Log::CRITICAL); - start = endOfLine; - continue; - } - - start = endOfLine; - - // Now Add to the filter - try { - m_filter.add_rule(startAddr, endAddr, libt::ip_filter::blocked); - ++ruleCount; - } - catch (std::exception &e) { - LogMsg(tr("IP filter exception thrown for line %1. Exception is: %2").arg(nbLine) - .arg(QString::fromLocal8Bit(e.what())), Log::CRITICAL); - } - } - - if (start >= dataSize) - offset = 0; - } - - return ruleCount; -} - -// Parser for PeerGuardian ip filter in p2p format -int FilterParserThread::parseP2PFilterFile() -{ - int ruleCount = 0; - QFile file(m_filePath); - if (!file.exists()) return ruleCount; - - if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { - LogMsg(tr("I/O Error: Could not open ip filter file in read mode."), Log::CRITICAL); - return ruleCount; - } - - std::vector buffer(BUFFER_SIZE, 0); // seems a bit faster than QVector - qint64 bytesRead = 0; - int offset = 0; - int start = 0; - int endOfLine = -1; - int nbLine = 0; - - while (true) { - bytesRead = file.read(buffer.data() + offset, BUFFER_SIZE - offset - 1); - if (bytesRead < 0) - break; - int dataSize = bytesRead + offset; - if (bytesRead == 0 && dataSize == 0) - break; - - for (start = 0; start < dataSize; ++start) { - endOfLine = -1; - // The file might have ended without the last line having a newline - if (!(bytesRead == 0 && dataSize > 0)) { - for (int i = start; i < dataSize; ++i) { - if (buffer[i] == '\n') { - endOfLine = i; - // We need to NULL the newline in case the line has only an IP range. - // In that case the parser won't work for the end IP, because it ends - // with the newline and not with a number. - buffer[i] = '\0'; - break; - } - } - } - else { - endOfLine = dataSize; - buffer[dataSize] = '\0'; - } - - if (endOfLine == -1) { - // read the next chunk from file - // but first move(copy) the leftover data to the front of the buffer - offset = dataSize - start; - memmove(buffer.data(), buffer.data() + start, offset); - break; - } - else { - ++nbLine; - } - - if ((buffer[start] == '#') - || ((buffer[start] == '/') && ((start + 1 < dataSize) && (buffer[start + 1] == '/')))) { - start = endOfLine; - continue; - } - - // Each line should follow this format: - // Some organization:1.0.0.0-1.255.255.255 - // The "Some organization" part might contain a ':' char itself so we find the last occurrence - int partsDelimiter = findAndNullDelimiter(buffer.data(), ':', start, endOfLine, true); - if (partsDelimiter == -1) { - LogMsg(tr("IP filter line %1 is malformed.").arg(nbLine), Log::CRITICAL); - start = endOfLine; - continue; - } - - // IP Range should be split by a dash - int delimIP = findAndNullDelimiter(buffer.data(), '-', partsDelimiter + 1, endOfLine); - if (delimIP == -1) { - LogMsg(tr("IP filter line %1 is malformed.").arg(nbLine), Log::CRITICAL); - start = endOfLine; - continue; - } - - libt::address startAddr; - int newStart = trim(buffer.data(), partsDelimiter + 1, delimIP - 1); - if (!parseIPAddress(buffer.data() + newStart, startAddr)) { - LogMsg(tr("IP filter line %1 is malformed. Start IP of the range is malformed.").arg(nbLine), Log::CRITICAL); - start = endOfLine; - continue; - } - - libt::address endAddr; - newStart = trim(buffer.data(), delimIP + 1, endOfLine); - if (!parseIPAddress(buffer.data() + newStart, endAddr)) { - LogMsg(tr("IP filter line %1 is malformed. End IP of the range is malformed.").arg(nbLine), Log::CRITICAL); - start = endOfLine; - continue; - } - - if ((startAddr.is_v4() != endAddr.is_v4()) - || (startAddr.is_v6() != endAddr.is_v6())) { - LogMsg(tr("IP filter line %1 is malformed. One IP is IPv4 and the other is IPv6!").arg(nbLine), Log::CRITICAL); - start = endOfLine; - continue; - } - - start = endOfLine; - - try { - m_filter.add_rule(startAddr, endAddr, libt::ip_filter::blocked); - ++ruleCount; - } - catch (std::exception &e) { - LogMsg(tr("IP filter exception thrown for line %1. Exception is: %2").arg(nbLine) - .arg(QString::fromLocal8Bit(e.what())), Log::CRITICAL); - } - } - - if (start >= dataSize) - offset = 0; - } - - return ruleCount; -} - -int FilterParserThread::getlineInStream(QDataStream &stream, std::string &name, char delim) -{ - char c; - int total_read = 0; - int read; - do { - read = stream.readRawData(&c, 1); - total_read += read; - if (read > 0) { - if (c != delim) { - name += c; - } - else { - // Delim found - return total_read; - } - } - } - while(read > 0); - - return total_read; -} - -// Parser for PeerGuardian ip filter in p2p format -int FilterParserThread::parseP2BFilterFile() -{ - int ruleCount = 0; - QFile file(m_filePath); - if (!file.exists()) return ruleCount; - - if (!file.open(QIODevice::ReadOnly)) { - LogMsg(tr("I/O Error: Could not open ip filter file in read mode."), Log::CRITICAL); - return ruleCount; - } - - QDataStream stream(&file); - // Read header - char buf[7]; - unsigned char version; - if (!stream.readRawData(buf, sizeof(buf)) - || memcmp(buf, "\xFF\xFF\xFF\xFFP2B", 7) - || !stream.readRawData(reinterpret_cast(&version), sizeof(version))) { - LogMsg(tr("Parsing Error: The filter file is not a valid PeerGuardian P2B file."), Log::CRITICAL); - return ruleCount; - } - - if ((version == 1) || (version == 2)) { - qDebug ("p2b version 1 or 2"); - unsigned int start, end; - - std::string name; - while(getlineInStream(stream, name, '\0') && !m_abort) { - if (!stream.readRawData(reinterpret_cast(&start), sizeof(start)) - || !stream.readRawData(reinterpret_cast(&end), sizeof(end))) { - LogMsg(tr("Parsing Error: The filter file is not a valid PeerGuardian P2B file."), Log::CRITICAL); - return ruleCount; - } - - // Network byte order to Host byte order - // asio address_v4 constructor expects it - // that way - libt::address_v4 first(ntohl(start)); - libt::address_v4 last(ntohl(end)); - // Apply to bittorrent session - try { - m_filter.add_rule(first, last, libt::ip_filter::blocked); - ++ruleCount; - } - catch(std::exception &) {} - } - } - else if (version == 3) { - qDebug ("p2b version 3"); - unsigned int namecount; - if (!stream.readRawData(reinterpret_cast(&namecount), sizeof(namecount))) { - LogMsg(tr("Parsing Error: The filter file is not a valid PeerGuardian P2B file."), Log::CRITICAL); - return ruleCount; - } - - namecount = ntohl(namecount); - // Reading names although, we don't really care about them - for (unsigned int i = 0; i < namecount; ++i) { - std::string name; - if (!getlineInStream(stream, name, '\0')) { - LogMsg(tr("Parsing Error: The filter file is not a valid PeerGuardian P2B file."), Log::CRITICAL); - return ruleCount; - } - - if (m_abort) return ruleCount; - } - - // Reading the ranges - unsigned int rangecount; - if (!stream.readRawData(reinterpret_cast(&rangecount), sizeof(rangecount))) { - LogMsg(tr("Parsing Error: The filter file is not a valid PeerGuardian P2B file."), Log::CRITICAL); - return ruleCount; - } - - rangecount = ntohl(rangecount); - unsigned int name, start, end; - for (unsigned int i = 0; i < rangecount; ++i) { - if (!stream.readRawData(reinterpret_cast(&name), sizeof(name)) - || !stream.readRawData(reinterpret_cast(&start), sizeof(start)) - || !stream.readRawData(reinterpret_cast(&end), sizeof(end))) { - LogMsg(tr("Parsing Error: The filter file is not a valid PeerGuardian P2B file."), Log::CRITICAL); - return ruleCount; - } - - // Network byte order to Host byte order - // asio address_v4 constructor expects it - // that way - libt::address_v4 first(ntohl(start)); - libt::address_v4 last(ntohl(end)); - // Apply to bittorrent session - try { - m_filter.add_rule(first, last, libt::ip_filter::blocked); - ++ruleCount; - } - catch(std::exception &) {} - - if (m_abort) return ruleCount; - } - } - else { - LogMsg(tr("Parsing Error: The filter file is not a valid PeerGuardian P2B file."), Log::CRITICAL); - } - - return ruleCount; -} - -// Process ip filter file -// Supported formats: -// * eMule IP list (DAT): http://wiki.phoenixlabs.org/wiki/DAT_Format -// * PeerGuardian Text (P2P): http://wiki.phoenixlabs.org/wiki/P2P_Format -// * PeerGuardian Binary (P2B): http://wiki.phoenixlabs.org/wiki/P2B_Format -void FilterParserThread::processFilterFile(const QString &filePath) -{ - if (isRunning()) { - // Already parsing a filter, m_abort first - m_abort = true; - wait(); - } - - m_abort = false; - m_filePath = filePath; - m_filter = libt::ip_filter(); - // Run it - start(); -} - -libt::ip_filter FilterParserThread::IPfilter() -{ - return m_filter; -} - -void FilterParserThread::run() -{ - qDebug("Processing filter file"); - int ruleCount = 0; - if (m_filePath.endsWith(".p2p", Qt::CaseInsensitive)) { - // PeerGuardian p2p file - ruleCount = parseP2PFilterFile(); - } - else if (m_filePath.endsWith(".p2b", Qt::CaseInsensitive)) { - // PeerGuardian p2b file - ruleCount = parseP2BFilterFile(); - } - else if (m_filePath.endsWith(".dat", Qt::CaseInsensitive)) { - // eMule DAT format - ruleCount = parseDATFilterFile(); - } - - if (m_abort) return; - - try { - emit IPFilterParsed(ruleCount); - } - catch(std::exception &) { - emit IPFilterError(); - } - - qDebug("IP Filter thread: finished parsing, filter applied"); -} - -int FilterParserThread::findAndNullDelimiter(char *const data, char delimiter, int start, int end, bool reverse) -{ - if (!reverse) { - for (int i = start; i <= end; ++i) { - if (data[i] == delimiter) { - data[i] = '\0'; - return i; - } - } - } - else { - for (int i = end; i >= start; --i) { - if (data[i] == delimiter) { - data[i] = '\0'; - return i; - } - } - } - - return -1; -} - -int FilterParserThread::trim(char* const data, int start, int end) -{ - if (start >= end) return start; - int newStart = start; - - for (int i = start; i <= end; ++i) { - if (isspace(data[i]) != 0) { - data[i] = '\0'; - } - else { - newStart = i; - break; - } - } - - for (int i = end; i >= start; --i) { - if (isspace(data[i]) != 0) - data[i] = '\0'; - else - break; - } - - return newStart; -} diff --git a/src/base/bittorrent/private/filterparserthread.h b/src/base/bittorrent/private/filterparserthread.h deleted file mode 100644 index 5db6fce73..000000000 --- a/src/base/bittorrent/private/filterparserthread.h +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2006 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 FILTERPARSERTHREAD_H -#define FILTERPARSERTHREAD_H - -#include - -#include - -class QDataStream; - -class FilterParserThread : public QThread -{ - Q_OBJECT - -public: - FilterParserThread(QObject *parent = 0); - ~FilterParserThread(); - void processFilterFile(const QString &filePath); - libtorrent::ip_filter IPfilter(); - -signals: - void IPFilterParsed(int ruleCount); - void IPFilterError(); - -protected: - void run(); - -private: - int findAndNullDelimiter(char *const data, char delimiter, int start, int end, bool reverse = false); - int trim(char *const data, int start, int end); - int parseDATFilterFile(); - int parseP2PFilterFile(); - int getlineInStream(QDataStream &stream, std::string &name, char delim); - int parseP2BFilterFile(); - - bool m_abort; - QString m_filePath; - libtorrent::ip_filter m_filter; -}; - -#endif // BITTORRENT_FILTERPARSERTHREAD_H diff --git a/src/base/bittorrent/private/resumedatasavingmanager.cpp b/src/base/bittorrent/private/resumedatasavingmanager.cpp deleted file mode 100644 index bb86b9958..000000000 --- a/src/base/bittorrent/private/resumedatasavingmanager.cpp +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2015 Vladimir Golovnev - * - * 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. - */ - -#include -#include - -#include "base/logger.h" -#include "base/utils/fs.h" -#include "resumedatasavingmanager.h" - -ResumeDataSavingManager::ResumeDataSavingManager(const QString &resumeFolderPath) - : m_resumeDataDir(resumeFolderPath) -{ -} - -void ResumeDataSavingManager::saveResumeData(QString infoHash, QByteArray data) const -{ - QString filename = QString("%1.fastresume").arg(infoHash); - QString filepath = m_resumeDataDir.absoluteFilePath(filename); - - qDebug() << "Saving resume data in" << filepath; - QSaveFile resumeFile(filepath); - if (resumeFile.open(QIODevice::WriteOnly)) { - resumeFile.write(data); - if (!resumeFile.commit()) { - Logger::instance()->addMessage(QString("Couldn't save resume data in %1. Error: %2") - .arg(filepath).arg(resumeFile.errorString()), Log::WARNING); - } - } -} diff --git a/src/base/bittorrent/private/resumedatasavingmanager.h b/src/base/bittorrent/private/resumedatasavingmanager.h deleted file mode 100644 index 08bcfb0e2..000000000 --- a/src/base/bittorrent/private/resumedatasavingmanager.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2015 Vladimir Golovnev - * - * 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. - */ - -#ifndef RESUMEDATASAVINGMANAGER_H -#define RESUMEDATASAVINGMANAGER_H - -#include -#include -#include - -class ResumeDataSavingManager: public QObject -{ - Q_OBJECT - -public: - explicit ResumeDataSavingManager(const QString &resumeFolderPath); - -public slots: - void saveResumeData(QString infoHash, QByteArray data) const; - -private: - QDir m_resumeDataDir; -}; - -#endif // RESUMEDATASAVINGMANAGER_H diff --git a/src/base/bittorrent/private/speedmonitor.cpp b/src/base/bittorrent/private/speedmonitor.cpp deleted file mode 100644 index 096f9b883..000000000 --- a/src/base/bittorrent/private/speedmonitor.cpp +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2015 Vladimir Golovnev - * 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. - */ - -#include "speedmonitor.h" - -SpeedMonitor::SpeedMonitor() - : m_speedSamples(MAX_SAMPLES) -{ -} - -void SpeedMonitor::addSample(const SpeedSample &sample) -{ - if (m_speedSamples.size() >= MAX_SAMPLES) { - m_sum -= m_speedSamples.front(); - } - - m_speedSamples.push_back(sample); - m_sum += sample; -} - -SpeedSampleAvg SpeedMonitor::average() const -{ - if (m_speedSamples.empty()) - return SpeedSampleAvg(); - - qreal k = qreal(1.) / m_speedSamples.size(); - return SpeedSampleAvg(m_sum.download * k, m_sum.upload * k); -} - -void SpeedMonitor::reset() -{ - m_sum = SpeedSample(); - m_speedSamples.clear(); -} diff --git a/src/base/bittorrent/private/speedmonitor.h b/src/base/bittorrent/private/speedmonitor.h deleted file mode 100644 index 4bbc90c4e..000000000 --- a/src/base/bittorrent/private/speedmonitor.h +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2015 Vladimir Golovnev - * 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. - */ - -#ifndef SPEEDMONITOR_H -#define SPEEDMONITOR_H - -#ifndef Q_MOC_RUN -#include -#endif - -#include - -template -struct Sample -{ - Sample() - : download() - , upload() - { - } - - Sample(T dl, T ul) - : download(dl) - , upload(ul) - { - } - - Sample &operator+=(const Sample &other) - { - download += other.download; - upload += other.upload; - return *this; - } - - Sample &operator-=(const Sample &other) - { - download -= other.download; - upload -= other.upload; - return *this; - } - - T download; - T upload; -}; - -typedef Sample SpeedSample; -typedef Sample SpeedSampleAvg; - -class SpeedMonitor -{ -public: - SpeedMonitor(); - - void addSample(const SpeedSample &sample); - SpeedSampleAvg average() const; - void reset(); - -private: - static const int MAX_SAMPLES = 30; - boost::circular_buffer m_speedSamples; - SpeedSample m_sum; -}; - -#endif // SPEEDMONITOR_H diff --git a/src/base/bittorrent/private/statistics.cpp b/src/base/bittorrent/private/statistics.cpp deleted file mode 100644 index 97e3f0424..000000000 --- a/src/base/bittorrent/private/statistics.cpp +++ /dev/null @@ -1,84 +0,0 @@ -#include "statistics.h" - -#include - -#include - -#include "base/bittorrent/sessionstatus.h" -#include "base/profile.h" -#include "base/bittorrent/session.h" - -static const qint64 SAVE_INTERVAL = 15 * 60 * 1000; - -namespace libt = libtorrent; -using namespace BitTorrent; - -Statistics::Statistics(Session *session) - : QObject(session) - , m_session(session) - , m_sessionUL(0) - , m_sessionDL(0) - , m_lastWrite(0) - , m_dirty(false) -{ - load(); - connect(&m_timer, SIGNAL(timeout()), this, SLOT(gather())); - m_timer.start(60 * 1000); -} - -Statistics::~Statistics() -{ - if (m_dirty) - m_lastWrite = 0; - save(); -} - -quint64 Statistics::getAlltimeDL() const -{ - return m_alltimeDL + m_sessionDL; -} - -quint64 Statistics::getAlltimeUL() const -{ - return m_alltimeUL + m_sessionUL; -} - -void Statistics::gather() -{ - const SessionStatus &ss = m_session->status(); - if (ss.totalDownload > m_sessionDL) { - m_sessionDL = ss.totalDownload; - m_dirty = true; - } - if (ss.totalUpload > m_sessionUL) { - m_sessionUL = ss.totalUpload; - m_dirty = true; - } - - save(); -} - -void Statistics::save() const -{ - qint64 now = QDateTime::currentMSecsSinceEpoch(); - - if (!m_dirty || ((now - m_lastWrite) < SAVE_INTERVAL)) - return; - - SettingsPtr s = Profile::instance().applicationSettings(QLatin1String("qBittorrent-data")); - QVariantHash v; - v.insert("AlltimeDL", m_alltimeDL + m_sessionDL); - v.insert("AlltimeUL", m_alltimeUL + m_sessionUL); - s->setValue("Stats/AllStats", v); - m_dirty = false; - m_lastWrite = now; -} - -void Statistics::load() -{ - SettingsPtr s = Profile::instance().applicationSettings(QLatin1String("qBittorrent-data")); - QVariantHash v = s->value("Stats/AllStats").toHash(); - - m_alltimeDL = v["AlltimeDL"].toULongLong(); - m_alltimeUL = v["AlltimeUL"].toULongLong(); -} diff --git a/src/base/bittorrent/private/statistics.h b/src/base/bittorrent/private/statistics.h deleted file mode 100644 index c012c409e..000000000 --- a/src/base/bittorrent/private/statistics.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef STATISTICS_H -#define STATISTICS_H - -#include -#include - -namespace BitTorrent { class Session; } - -class Statistics : QObject -{ - Q_OBJECT - Q_DISABLE_COPY(Statistics) - -public: - Statistics(BitTorrent::Session *session); - ~Statistics(); - - quint64 getAlltimeDL() const; - quint64 getAlltimeUL() const; - -private slots: - void gather(); - -private: - void save() const; - void load(); - -private: - BitTorrent::Session *m_session; - // Will overflow at 15.9 EiB - quint64 m_alltimeUL; - quint64 m_alltimeDL; - quint64 m_sessionUL; - quint64 m_sessionDL; - mutable qint64 m_lastWrite; - mutable bool m_dirty; - - QTimer m_timer; -}; - -#endif // STATISTICS_H diff --git a/src/base/bittorrent/session.cpp b/src/base/bittorrent/session.cpp deleted file mode 100644 index 616de4500..000000000 --- a/src/base/bittorrent/session.cpp +++ /dev/null @@ -1,4082 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2015 Vladimir Golovnev - * Copyright (C) 2006 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. - */ - -#include "session.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#if LIBTORRENT_VERSION_NUM >= 10100 -#include -#endif -#include -#include -#include -#include -#include -#include -#include -#include -#if LIBTORRENT_VERSION_NUM < 10100 -#include -#endif -#include -#include -#if LIBTORRENT_VERSION_NUM >= 10100 -#include -#endif -#include -#include - -#include "base/logger.h" -#include "base/profile.h" -#include "base/net/downloadhandler.h" -#include "base/net/downloadmanager.h" -#include "base/net/portforwarder.h" -#include "base/net/proxyconfigurationmanager.h" -#include "base/torrentfileguard.h" -#include "base/torrentfilter.h" -#include "base/unicodestrings.h" -#include "base/utils/net.h" -#include "base/utils/misc.h" -#include "base/utils/fs.h" -#include "base/utils/random.h" -#include "base/utils/string.h" -#include "magneturi.h" -#include "private/filterparserthread.h" -#include "private/statistics.h" -#include "private/bandwidthscheduler.h" -#include "private/resumedatasavingmanager.h" -#include "torrenthandle.h" -#include "tracker.h" -#include "trackerentry.h" - -static const char PEER_ID[] = "qB"; -static const char RESUME_FOLDER[] = "BT_backup"; -static const char USER_AGENT[] = "qBittorrent/" QBT_VERSION_2; - -namespace libt = libtorrent; -using namespace BitTorrent; - -namespace -{ - bool readFile(const QString &path, QByteArray &buf); - bool loadTorrentResumeData(const QByteArray &data, AddTorrentData &torrentData, int &prio, MagnetUri &magnetUri); - - void torrentQueuePositionUp(const libt::torrent_handle &handle); - void torrentQueuePositionDown(const libt::torrent_handle &handle); - void torrentQueuePositionTop(const libt::torrent_handle &handle); - void torrentQueuePositionBottom(const libt::torrent_handle &handle); - - inline SettingsStorage *settings() { return SettingsStorage::instance(); } - - QStringMap map_cast(const QVariantMap &map) - { - QStringMap result; - foreach (const QString &key, map.keys()) - result[key] = map.value(key).toString(); - return result; - } - - QVariantMap map_cast(const QStringMap &map) - { - QVariantMap result; - foreach (const QString &key, map.keys()) - result[key] = map.value(key); - return result; - } - - template - QSet entryListToSetImpl(const Entry &entry) - { - Q_ASSERT(entry.type() == Entry::list_t); - QSet output; - for (int i = 0; i < entry.list_size(); ++i) { - const QString tag = QString::fromStdString(entry.list_string_value_at(i)); - if (Session::isValidTag(tag)) - output.insert(tag); - else - qWarning() << QString("Dropping invalid stored tag: %1").arg(tag); - } - return output; - } - -#if LIBTORRENT_VERSION_NUM < 10100 - bool isList(const libt::lazy_entry *entry) - { - return entry && (entry->type() == libt::lazy_entry::list_t); - } - - QSet entryListToSet(const libt::lazy_entry *entry) - { - return entry ? entryListToSetImpl(*entry) : QSet(); - } -#else - bool isList(const libt::bdecode_node &entry) - { - return entry.type() == libt::bdecode_node::list_t; - } - - QSet entryListToSet(const libt::bdecode_node &entry) - { - return entryListToSetImpl(entry); - } -#endif - - QString normalizePath(const QString &path) - { - QString tmp = Utils::Fs::fromNativePath(path.trimmed()); - if (!tmp.isEmpty() && !tmp.endsWith('/')) - return tmp + '/'; - return tmp; - } - - QString normalizeSavePath(QString path, const QString &defaultPath = specialFolderLocation(SpecialFolder::Downloads)) - { - path = path.trimmed(); - if (path.isEmpty()) - path = Utils::Fs::fromNativePath(defaultPath.trimmed()); - - return normalizePath(path); - } - - QStringMap expandCategories(const QStringMap &categories) - { - QStringMap expanded = categories; - - foreach (const QString &category, categories.keys()) { - foreach (const QString &subcat, Session::expandCategory(category)) { - if (!expanded.contains(subcat)) - expanded[subcat] = ""; - } - } - - return expanded; - } - - template - struct LowerLimited - { - LowerLimited(T limit, T ret) - : m_limit(limit) - , m_ret(ret) - { - } - - explicit LowerLimited(T limit) - : LowerLimited(limit, limit) - { - } - - T operator()(T val) const - { - return val <= m_limit ? m_ret : val; - } - - private: - const T m_limit; - const T m_ret; - }; - - template - LowerLimited lowerLimited(T limit) { return LowerLimited(limit); } - - template - LowerLimited lowerLimited(T limit, T ret) { return LowerLimited(limit, ret); } -} - -// Session - -Session *Session::m_instance = nullptr; - -#define BITTORRENT_KEY(name) "BitTorrent/" name -#define BITTORRENT_SESSION_KEY(name) BITTORRENT_KEY("Session/") name - -Session::Session(QObject *parent) - : QObject(parent) - , m_deferredConfigureScheduled(false) - , m_IPFilteringChanged(false) -#if LIBTORRENT_VERSION_NUM >= 10100 - , m_listenInterfaceChanged(true) -#endif - , m_isDHTEnabled(BITTORRENT_SESSION_KEY("DHTEnabled"), true) - , m_isLSDEnabled(BITTORRENT_SESSION_KEY("LSDEnabled"), true) - , m_isPeXEnabled(BITTORRENT_SESSION_KEY("PeXEnabled"), true) - , m_isIPFilteringEnabled(BITTORRENT_SESSION_KEY("IPFilteringEnabled"), false) - , m_isTrackerFilteringEnabled(BITTORRENT_SESSION_KEY("TrackerFilteringEnabled"), false) - , m_IPFilterFile(BITTORRENT_SESSION_KEY("IPFilter")) - , m_announceToAllTrackers(BITTORRENT_SESSION_KEY("AnnounceToAllTrackers"), true) - , m_diskCacheSize(BITTORRENT_SESSION_KEY("DiskCacheSize"), 0) - , m_diskCacheTTL(BITTORRENT_SESSION_KEY("DiskCacheTTL"), 60) - , m_useOSCache(BITTORRENT_SESSION_KEY("UseOSCache"), true) - , m_isAnonymousModeEnabled(BITTORRENT_SESSION_KEY("AnonymousModeEnabled"), false) - , m_isQueueingEnabled(BITTORRENT_SESSION_KEY("QueueingSystemEnabled"), true) - , m_maxActiveDownloads(BITTORRENT_SESSION_KEY("MaxActiveDownloads"), 3, lowerLimited(-1)) - , m_maxActiveUploads(BITTORRENT_SESSION_KEY("MaxActiveUploads"), 3, lowerLimited(-1)) - , m_maxActiveTorrents(BITTORRENT_SESSION_KEY("MaxActiveTorrents"), 5, lowerLimited(-1)) - , m_ignoreSlowTorrentsForQueueing(BITTORRENT_SESSION_KEY("IgnoreSlowTorrentsForQueueing"), false) - , m_outgoingPortsMin(BITTORRENT_SESSION_KEY("OutgoingPortsMin"), 0) - , m_outgoingPortsMax(BITTORRENT_SESSION_KEY("OutgoingPortsMax"), 0) - , m_ignoreLimitsOnLAN(BITTORRENT_SESSION_KEY("IgnoreLimitsOnLAN"), true) - , m_includeOverheadInLimits(BITTORRENT_SESSION_KEY("IncludeOverheadInLimits"), false) - , m_announceIP(BITTORRENT_SESSION_KEY("AnnounceIP")) - , m_isSuperSeedingEnabled(BITTORRENT_SESSION_KEY("SuperSeedingEnabled"), false) - , m_maxConnections(BITTORRENT_SESSION_KEY("MaxConnections"), 500, lowerLimited(0, -1)) - , m_maxHalfOpenConnections(BITTORRENT_SESSION_KEY("MaxHalfOpenConnections"), 20, lowerLimited(0, -1)) - , m_maxUploads(BITTORRENT_SESSION_KEY("MaxUploads"), -1, lowerLimited(0, -1)) - , m_maxConnectionsPerTorrent(BITTORRENT_SESSION_KEY("MaxConnectionsPerTorrent"), 100, lowerLimited(0, -1)) - , m_maxUploadsPerTorrent(BITTORRENT_SESSION_KEY("MaxUploadsPerTorrent"), -1, lowerLimited(0, -1)) - , m_isUTPEnabled(BITTORRENT_SESSION_KEY("uTPEnabled"), true) - , m_isUTPRateLimited(BITTORRENT_SESSION_KEY("uTPRateLimited"), true) - , m_isAddTrackersEnabled(BITTORRENT_SESSION_KEY("AddTrackersEnabled"), false) - , m_additionalTrackers(BITTORRENT_SESSION_KEY("AdditionalTrackers")) - , m_globalMaxRatio(BITTORRENT_SESSION_KEY("GlobalMaxRatio"), -1, [](qreal r) { return r < 0 ? -1. : r;}) - , m_globalMaxSeedingMinutes(BITTORRENT_SESSION_KEY("GlobalMaxSeedingMinutes"), -1, lowerLimited(-1)) - , m_isAddTorrentPaused(BITTORRENT_SESSION_KEY("AddTorrentPaused"), false) - , m_isCreateTorrentSubfolder(BITTORRENT_SESSION_KEY("CreateTorrentSubfolder"), true) - , m_isAppendExtensionEnabled(BITTORRENT_SESSION_KEY("AddExtensionToIncompleteFiles"), false) - , m_refreshInterval(BITTORRENT_SESSION_KEY("RefreshInterval"), 1500) - , m_isPreallocationEnabled(BITTORRENT_SESSION_KEY("Preallocation"), false) - , m_torrentExportDirectory(BITTORRENT_SESSION_KEY("TorrentExportDirectory")) - , m_finishedTorrentExportDirectory(BITTORRENT_SESSION_KEY("FinishedTorrentExportDirectory")) - , m_globalDownloadSpeedLimit(BITTORRENT_SESSION_KEY("GlobalDLSpeedLimit"), 0, lowerLimited(0)) - , m_globalUploadSpeedLimit(BITTORRENT_SESSION_KEY("GlobalUPSpeedLimit"), 0, lowerLimited(0)) - , m_altGlobalDownloadSpeedLimit(BITTORRENT_SESSION_KEY("AlternativeGlobalDLSpeedLimit"), 10, lowerLimited(0)) - , m_altGlobalUploadSpeedLimit(BITTORRENT_SESSION_KEY("AlternativeGlobalUPSpeedLimit"), 10, lowerLimited(0)) - , m_isAltGlobalSpeedLimitEnabled(BITTORRENT_SESSION_KEY("UseAlternativeGlobalSpeedLimit"), false) - , m_isBandwidthSchedulerEnabled(BITTORRENT_SESSION_KEY("BandwidthSchedulerEnabled"), false) - , m_saveResumeDataInterval(BITTORRENT_SESSION_KEY("SaveResumeDataInterval"), 3) - , m_port(BITTORRENT_SESSION_KEY("Port"), 8999) - , m_useRandomPort(BITTORRENT_SESSION_KEY("UseRandomPort"), false) - , m_networkInterface(BITTORRENT_SESSION_KEY("Interface")) - , m_networkInterfaceName(BITTORRENT_SESSION_KEY("InterfaceName")) - , m_networkInterfaceAddress(BITTORRENT_SESSION_KEY("InterfaceAddress")) - , m_isIPv6Enabled(BITTORRENT_SESSION_KEY("IPv6Enabled"), false) - , m_encryption(BITTORRENT_SESSION_KEY("Encryption"), 0) - , m_isForceProxyEnabled(BITTORRENT_SESSION_KEY("ForceProxy"), true) - , m_isProxyPeerConnectionsEnabled(BITTORRENT_SESSION_KEY("ProxyPeerConnections"), false) - , m_storedCategories(BITTORRENT_SESSION_KEY("Categories")) - , m_storedTags(BITTORRENT_SESSION_KEY("Tags")) - , m_maxRatioAction(BITTORRENT_SESSION_KEY("MaxRatioAction"), Pause) - , m_defaultSavePath(BITTORRENT_SESSION_KEY("DefaultSavePath"), specialFolderLocation(SpecialFolder::Downloads), normalizePath) - , m_tempPath(BITTORRENT_SESSION_KEY("TempPath"), defaultSavePath() + "temp/", normalizePath) - , m_isSubcategoriesEnabled(BITTORRENT_SESSION_KEY("SubcategoriesEnabled"), false) - , m_isTempPathEnabled(BITTORRENT_SESSION_KEY("TempPathEnabled"), false) - , m_isAutoTMMDisabledByDefault(BITTORRENT_SESSION_KEY("DisableAutoTMMByDefault"), true) - , m_isDisableAutoTMMWhenCategoryChanged(BITTORRENT_SESSION_KEY("DisableAutoTMMTriggers/CategoryChanged"), false) - , m_isDisableAutoTMMWhenDefaultSavePathChanged(BITTORRENT_SESSION_KEY("DisableAutoTMMTriggers/DefaultSavePathChanged"), true) - , m_isDisableAutoTMMWhenCategorySavePathChanged(BITTORRENT_SESSION_KEY("DisableAutoTMMTriggers/CategorySavePathChanged"), true) - , m_isTrackerEnabled(BITTORRENT_KEY("TrackerEnabled"), false) - , m_bannedIPs("State/BannedIPs" - , QStringList() - , [](const QStringList &value) - { - QStringList tmp = value; - tmp.sort(); - return tmp; - } - ) - , m_wasPexEnabled(m_isPeXEnabled) - , m_numResumeData(0) - , m_extraLimit(0) - , m_useProxy(false) -{ - Logger* const logger = Logger::instance(); - - initResumeFolder(); - - m_seedingLimitTimer = new QTimer(this); - m_seedingLimitTimer->setInterval(10000); - connect(m_seedingLimitTimer, SIGNAL(timeout()), SLOT(processShareLimits())); - - // Set severity level of libtorrent session - int alertMask = libt::alert::error_notification - | libt::alert::peer_notification - | libt::alert::port_mapping_notification - | libt::alert::storage_notification - | libt::alert::tracker_notification - | libt::alert::status_notification - | libt::alert::ip_block_notification - | libt::alert::progress_notification - | libt::alert::stats_notification - ; - -#if LIBTORRENT_VERSION_NUM < 10100 - libt::fingerprint fingerprint(PEER_ID, QBT_VERSION_MAJOR, QBT_VERSION_MINOR, QBT_VERSION_BUGFIX, QBT_VERSION_BUILD); - std::string peerId = fingerprint.to_string(); - const ushort port = this->port(); - std::pair ports(port, port); - const QString ip = getListeningIPs().first(); - m_nativeSession = new libt::session(fingerprint, ports, ip.isEmpty() ? 0 : ip.toLatin1().constData(), 0, alertMask); - - libt::session_settings sessionSettings = m_nativeSession->settings(); - sessionSettings.user_agent = USER_AGENT; - sessionSettings.upnp_ignore_nonrouters = true; - sessionSettings.use_dht_as_fallback = false; - // Disable support for SSL torrents for now - sessionSettings.ssl_listen = 0; - // To prevent ISPs from blocking seeding - sessionSettings.lazy_bitfields = true; - // Speed up exit - sessionSettings.stop_tracker_timeout = 1; - sessionSettings.auto_scrape_interval = 1200; // 20 minutes - sessionSettings.auto_scrape_min_interval = 900; // 15 minutes - sessionSettings.connection_speed = 20; // default is 10 - sessionSettings.no_connect_privileged_ports = false; - sessionSettings.seed_choking_algorithm = libt::session_settings::fastest_upload; - configure(sessionSettings); - m_nativeSession->set_settings(sessionSettings); - configureListeningInterface(); - m_nativeSession->set_alert_dispatch([this](std::auto_ptr alertPtr) - { - dispatchAlerts(alertPtr.release()); - }); -#else - std::string peerId = libt::generate_fingerprint(PEER_ID, QBT_VERSION_MAJOR, QBT_VERSION_MINOR, QBT_VERSION_BUGFIX, QBT_VERSION_BUILD); - libt::settings_pack pack; - pack.set_int(libt::settings_pack::alert_mask, alertMask); - pack.set_str(libt::settings_pack::peer_fingerprint, peerId); - pack.set_bool(libt::settings_pack::listen_system_port_fallback, false); - pack.set_str(libt::settings_pack::user_agent, USER_AGENT); - pack.set_bool(libt::settings_pack::upnp_ignore_nonrouters, true); - pack.set_bool(libt::settings_pack::use_dht_as_fallback, false); - // Disable support for SSL torrents for now - pack.set_int(libt::settings_pack::ssl_listen, 0); - // To prevent ISPs from blocking seeding - pack.set_bool(libt::settings_pack::lazy_bitfields, true); - // Speed up exit - pack.set_int(libt::settings_pack::stop_tracker_timeout, 1); - pack.set_int(libt::settings_pack::auto_scrape_interval, 1200); // 20 minutes - pack.set_int(libt::settings_pack::auto_scrape_min_interval, 900); // 15 minutes - pack.set_int(libt::settings_pack::connection_speed, 20); // default is 10 - pack.set_bool(libt::settings_pack::no_connect_privileged_ports, false); - pack.set_int(libt::settings_pack::seed_choking_algorithm, libt::settings_pack::fastest_upload); - configure(pack); - - m_nativeSession = new libt::session(pack, 0); - m_nativeSession->set_alert_notify([this]() - { - QMetaObject::invokeMethod(this, "readAlerts", Qt::QueuedConnection); - }); - - configurePeerClasses(); -#endif - - // Enabling plugins - //m_nativeSession->add_extension(&libt::create_metadata_plugin); - m_nativeSession->add_extension(&libt::create_ut_metadata_plugin); - if (isPeXEnabled()) - m_nativeSession->add_extension(&libt::create_ut_pex_plugin); - m_nativeSession->add_extension(&libt::create_smart_ban_plugin); - - logger->addMessage(tr("Peer ID: ") + QString::fromStdString(peerId)); - logger->addMessage(tr("HTTP User-Agent is '%1'").arg(USER_AGENT)); - logger->addMessage(tr("DHT support [%1]").arg(isDHTEnabled() ? tr("ON") : tr("OFF")), Log::INFO); - logger->addMessage(tr("Local Peer Discovery support [%1]").arg(isLSDEnabled() ? tr("ON") : tr("OFF")), Log::INFO); - logger->addMessage(tr("PeX support [%1]").arg(isPeXEnabled() ? tr("ON") : tr("OFF")), Log::INFO); - logger->addMessage(tr("Anonymous mode [%1]").arg(isAnonymousModeEnabled() ? tr("ON") : tr("OFF")), Log::INFO); - logger->addMessage(tr("Encryption support [%1]") - .arg(encryption() == 0 ? tr("ON") : encryption() == 1 ? tr("FORCED") : tr("OFF")) - , Log::INFO); - - if (isIPFilteringEnabled()) { - // Manually banned IPs are handled in that function too(in the slots) - enableIPFilter(); - } - else { - // Add the banned IPs - libt::ip_filter filter; - processBannedIPs(filter); - m_nativeSession->set_ip_filter(filter); - } - - m_categories = map_cast(m_storedCategories); - if (isSubcategoriesEnabled()) { - // if subcategories support changed manually - m_categories = expandCategories(m_categories); - m_storedCategories = map_cast(m_categories); - } - - m_tags = QSet::fromList(m_storedTags.value()); - - m_refreshTimer = new QTimer(this); - m_refreshTimer->setInterval(refreshInterval()); - connect(m_refreshTimer, SIGNAL(timeout()), SLOT(refresh())); - m_refreshTimer->start(); - - // Regular saving of fastresume data - m_resumeDataTimer = new QTimer(this); - m_resumeDataTimer->setInterval(saveResumeDataInterval() * 60 * 1000); - connect(m_resumeDataTimer, SIGNAL(timeout()), SLOT(generateResumeData())); - - m_statistics = new Statistics(this); - - updateSeedingLimitTimer(); - populateAdditionalTrackers(); - - enableTracker(isTrackerEnabled()); - - connect(Net::ProxyConfigurationManager::instance(), SIGNAL(proxyConfigurationChanged()), SLOT(configureDeferred())); - - // Network configuration monitor - connect(&m_networkManager, SIGNAL(onlineStateChanged(bool)), SLOT(networkOnlineStateChanged(bool))); - connect(&m_networkManager, SIGNAL(configurationAdded(const QNetworkConfiguration&)), SLOT(networkConfigurationChange(const QNetworkConfiguration&))); - connect(&m_networkManager, SIGNAL(configurationRemoved(const QNetworkConfiguration&)), SLOT(networkConfigurationChange(const QNetworkConfiguration&))); - connect(&m_networkManager, SIGNAL(configurationChanged(const QNetworkConfiguration&)), SLOT(networkConfigurationChange(const QNetworkConfiguration&))); - - m_ioThread = new QThread(this); - m_resumeDataSavingManager = new ResumeDataSavingManager(m_resumeFolderPath); - m_resumeDataSavingManager->moveToThread(m_ioThread); - connect(m_ioThread, SIGNAL(finished()), m_resumeDataSavingManager, SLOT(deleteLater())); - m_ioThread->start(); - m_resumeDataTimer->start(); - - // initialize PortForwarder instance - Net::PortForwarder::initInstance(m_nativeSession); - -#if LIBTORRENT_VERSION_NUM >= 10100 - initMetrics(); - m_statsUpdateTimer.start(); -#endif - - qDebug("* BitTorrent Session constructed"); -} - -bool Session::isDHTEnabled() const -{ - return m_isDHTEnabled; -} - -void Session::setDHTEnabled(bool enabled) -{ - if (enabled != m_isDHTEnabled) { - m_isDHTEnabled = enabled; - configureDeferred(); - Logger::instance()->addMessage( - tr("DHT support [%1]").arg(enabled ? tr("ON") : tr("OFF")), Log::INFO); - } -} - -bool Session::isLSDEnabled() const -{ - return m_isLSDEnabled; -} - -void Session::setLSDEnabled(bool enabled) -{ - if (enabled != m_isLSDEnabled) { - m_isLSDEnabled = enabled; - configureDeferred(); - Logger::instance()->addMessage( - tr("Local Peer Discovery support [%1]").arg(enabled ? tr("ON") : tr("OFF")) - , Log::INFO); - } -} - -bool Session::isPeXEnabled() const -{ - return m_isPeXEnabled; -} - -void Session::setPeXEnabled(bool enabled) -{ - m_isPeXEnabled = enabled; - if (m_wasPexEnabled != enabled) - Logger::instance()->addMessage(tr("Restart is required to toggle PeX support"), Log::WARNING); -} - -bool Session::isTempPathEnabled() const -{ - return m_isTempPathEnabled; -} - -void Session::setTempPathEnabled(bool enabled) -{ - if (enabled != isTempPathEnabled()) { - m_isTempPathEnabled = enabled; - foreach (TorrentHandle *const torrent, m_torrents) - torrent->handleTempPathChanged(); - } -} - -bool Session::isAppendExtensionEnabled() const -{ - return m_isAppendExtensionEnabled; -} - -void Session::setAppendExtensionEnabled(bool enabled) -{ - if (isAppendExtensionEnabled() != enabled) { - // append or remove .!qB extension for incomplete files - foreach (TorrentHandle *const torrent, m_torrents) - torrent->handleAppendExtensionToggled(); - - m_isAppendExtensionEnabled = enabled; - } -} - -uint Session::refreshInterval() const -{ - return m_refreshInterval; -} - -void Session::setRefreshInterval(uint value) -{ - if (value != refreshInterval()) { - m_refreshTimer->setInterval(value); - m_refreshInterval = value; - } -} - -bool Session::isPreallocationEnabled() const -{ - return m_isPreallocationEnabled; -} - -void Session::setPreallocationEnabled(bool enabled) -{ - m_isPreallocationEnabled = enabled; -} - -QString Session::torrentExportDirectory() const -{ - return Utils::Fs::fromNativePath(m_torrentExportDirectory); -} - -void Session::setTorrentExportDirectory(QString path) -{ - path = Utils::Fs::fromNativePath(path); - if (path != torrentExportDirectory()) - m_torrentExportDirectory = path; -} - -QString Session::finishedTorrentExportDirectory() const -{ - return Utils::Fs::fromNativePath(m_finishedTorrentExportDirectory); -} - -void Session::setFinishedTorrentExportDirectory(QString path) -{ - path = Utils::Fs::fromNativePath(path); - if (path != finishedTorrentExportDirectory()) - m_finishedTorrentExportDirectory = path; -} - -QString Session::defaultSavePath() const -{ - return Utils::Fs::fromNativePath(m_defaultSavePath); -} - -QString Session::tempPath() const -{ - return Utils::Fs::fromNativePath(m_tempPath); -} - -QString Session::torrentTempPath(const TorrentInfo &torrentInfo) const -{ - if ((torrentInfo.filesCount() > 1) && !torrentInfo.hasRootFolder()) - return tempPath() - + QString::fromStdString(torrentInfo.nativeInfo()->orig_files().name()) - + "/"; - - return tempPath(); -} - -bool Session::isValidCategoryName(const QString &name) -{ - QRegExp re(R"(^([^\\\/]|[^\\\/]([^\\\/]|\/(?=[^\/]))*[^\\\/])$)"); - if (!name.isEmpty() && (re.indexIn(name) != 0)) { - qDebug() << "Incorrect category name:" << name; - return false; - } - - return true; -} - -QStringList Session::expandCategory(const QString &category) -{ - QStringList result; - if (!isValidCategoryName(category)) - return result; - - int index = 0; - while ((index = category.indexOf('/', index)) >= 0) { - result << category.left(index); - ++index; - } - result << category; - - return result; -} - -QStringList Session::categories() const -{ - return m_categories.keys(); -} - -QString Session::categorySavePath(const QString &categoryName) const -{ - QString basePath = m_defaultSavePath; - if (categoryName.isEmpty()) return basePath; - - QString path = m_categories.value(categoryName); - if (path.isEmpty()) // use implicit save path - path = Utils::Fs::toValidFileSystemName(categoryName, true); - - if (!QDir::isAbsolutePath(path)) - path.prepend(basePath); - - return normalizeSavePath(path); -} - -bool Session::addCategory(const QString &name, const QString &savePath) -{ - if (name.isEmpty()) return false; - if (!isValidCategoryName(name) || m_categories.contains(name)) - return false; - - if (isSubcategoriesEnabled()) { - foreach (const QString &parent, expandCategory(name)) { - if ((parent != name) && !m_categories.contains(parent)) { - m_categories[parent] = ""; - emit categoryAdded(parent); - } - } - } - - m_categories[name] = savePath; - m_storedCategories = map_cast(m_categories); - emit categoryAdded(name); - - return true; -} - -bool Session::editCategory(const QString &name, const QString &savePath) -{ - if (!m_categories.contains(name)) return false; - if (categorySavePath(name) == savePath) return false; - - m_categories[name] = savePath; - if (isDisableAutoTMMWhenCategorySavePathChanged()) { - foreach (TorrentHandle *const torrent, torrents()) - if (torrent->category() == name) - torrent->setAutoTMMEnabled(false); - } - else { - foreach (TorrentHandle *const torrent, torrents()) - if (torrent->category() == name) - torrent->handleCategorySavePathChanged(); - } - - return true; -} - -bool Session::removeCategory(const QString &name) -{ - foreach (TorrentHandle *const torrent, torrents()) - if (torrent->belongsToCategory(name)) - torrent->setCategory(""); - - // remove stored category and its subcategories if exist - bool result = false; - if (isSubcategoriesEnabled()) { - // remove subcategories - QString test = name + "/"; - foreach (const QString &category, m_categories.keys()) { - if (category.startsWith(test)) { - m_categories.remove(category); - result = true; - emit categoryRemoved(category); - } - } - } - - result = (m_categories.remove(name) > 0) || result; - - if (result) { - // update stored categories - m_storedCategories = map_cast(m_categories); - emit categoryRemoved(name); - } - - return result; -} - -bool Session::isSubcategoriesEnabled() const -{ - return m_isSubcategoriesEnabled; -} - -void Session::setSubcategoriesEnabled(bool value) -{ - if (isSubcategoriesEnabled() == value) return; - - if (value) { - // expand categories to include all parent categories - m_categories = expandCategories(m_categories); - // update stored categories - m_storedCategories = map_cast(m_categories); - } - else { - // reload categories - m_categories = map_cast(m_storedCategories); - } - - m_isSubcategoriesEnabled = value; - emit subcategoriesSupportChanged(); -} - -QSet Session::tags() const -{ - return m_tags; -} - -bool Session::isValidTag(const QString &tag) -{ - return (!tag.trimmed().isEmpty() && !tag.contains(',')); -} - -bool Session::hasTag(const QString &tag) const -{ - return m_tags.contains(tag); -} - -bool Session::addTag(const QString &tag) -{ - if (!isValidTag(tag)) - return false; - - if (!hasTag(tag)) { - m_tags.insert(tag); - m_storedTags = m_tags.toList(); - emit tagAdded(tag); - return true; - } - return false; -} - -bool Session::removeTag(const QString &tag) -{ - if (m_tags.remove(tag)) { - foreach (TorrentHandle *const torrent, torrents()) - torrent->removeTag(tag); - m_storedTags = m_tags.toList(); - emit tagRemoved(tag); - return true; - } - return false; -} - -bool Session::isAutoTMMDisabledByDefault() const -{ - return m_isAutoTMMDisabledByDefault; -} - -void Session::setAutoTMMDisabledByDefault(bool value) -{ - m_isAutoTMMDisabledByDefault = value; -} - -bool Session::isDisableAutoTMMWhenCategoryChanged() const -{ - return m_isDisableAutoTMMWhenCategoryChanged; -} - -void Session::setDisableAutoTMMWhenCategoryChanged(bool value) -{ - m_isDisableAutoTMMWhenCategoryChanged = value; -} - -bool Session::isDisableAutoTMMWhenDefaultSavePathChanged() const -{ - return m_isDisableAutoTMMWhenDefaultSavePathChanged; -} - -void Session::setDisableAutoTMMWhenDefaultSavePathChanged(bool value) -{ - m_isDisableAutoTMMWhenDefaultSavePathChanged = value; -} - -bool Session::isDisableAutoTMMWhenCategorySavePathChanged() const -{ - return m_isDisableAutoTMMWhenCategorySavePathChanged; -} - -void Session::setDisableAutoTMMWhenCategorySavePathChanged(bool value) -{ - m_isDisableAutoTMMWhenCategorySavePathChanged = value; -} - -bool Session::isAddTorrentPaused() const -{ - return m_isAddTorrentPaused; -} - -void Session::setAddTorrentPaused(bool value) -{ - m_isAddTorrentPaused = value; -} - -bool Session::isTrackerEnabled() const -{ - return m_isTrackerEnabled; -} - -void Session::setTrackerEnabled(bool enabled) -{ - if (isTrackerEnabled() != enabled) { - enableTracker(enabled); - m_isTrackerEnabled = enabled; - } -} - -qreal Session::globalMaxRatio() const -{ - return m_globalMaxRatio; -} - -// Torrents will a ratio superior to the given value will -// be automatically deleted -void Session::setGlobalMaxRatio(qreal ratio) -{ - if (ratio < 0) - ratio = -1.; - - if (ratio != globalMaxRatio()) { - m_globalMaxRatio = ratio; - updateSeedingLimitTimer(); - } -} - -int Session::globalMaxSeedingMinutes() const -{ - return m_globalMaxSeedingMinutes; -} - -void Session::setGlobalMaxSeedingMinutes(int minutes) -{ - if (minutes < 0) - minutes = -1; - - if (minutes != globalMaxSeedingMinutes()) { - m_globalMaxSeedingMinutes = minutes; - updateSeedingLimitTimer(); - } -} - -// Main destructor -Session::~Session() -{ - // Do some BT related saving - saveResumeData(); - - // We must delete FilterParserThread - // before we delete libtorrent::session - if (m_filterParser) - delete m_filterParser; - - // We must delete PortForwarderImpl before - // we delete libtorrent::session - Net::PortForwarder::freeInstance(); - - qDebug("Deleting the session"); - delete m_nativeSession; - - m_ioThread->quit(); - m_ioThread->wait(); - - m_resumeFolderLock.close(); - m_resumeFolderLock.remove(); -} - -void Session::initInstance() -{ - if (!m_instance) { - m_instance = new Session; - - // BandwidthScheduler::start() depends on Session being fully constructed - if (m_instance->isBandwidthSchedulerEnabled()) - m_instance->enableBandwidthScheduler(); - } -} - -void Session::freeInstance() -{ - if (m_instance) { - delete m_instance; - m_instance = 0; - } -} - -Session *Session::instance() -{ - return m_instance; -} - -void Session::adjustLimits() -{ - if (isQueueingSystemEnabled()) { -#if LIBTORRENT_VERSION_NUM < 10100 - libt::session_settings sessionSettings(m_nativeSession->settings()); - adjustLimits(sessionSettings); - m_nativeSession->set_settings(sessionSettings); -#else - libt::settings_pack settingsPack = m_nativeSession->get_settings(); - adjustLimits(settingsPack); - m_nativeSession->apply_settings(settingsPack); -#endif - } -} - -// Set BitTorrent session configuration -void Session::configure() -{ - qDebug("Configuring session"); -#if LIBTORRENT_VERSION_NUM < 10100 - libt::session_settings sessionSettings = m_nativeSession->settings(); - configure(sessionSettings); - m_nativeSession->set_settings(sessionSettings); -#else - libt::settings_pack settingsPack = m_nativeSession->get_settings(); - configure(settingsPack); - m_nativeSession->apply_settings(settingsPack); - configurePeerClasses(); -#endif - - if (m_IPFilteringChanged) { - if (isIPFilteringEnabled()) - enableIPFilter(); - else - disableIPFilter(); - m_IPFilteringChanged = false; - } - - m_deferredConfigureScheduled = false; - qDebug("Session configured"); -} - -void Session::processBannedIPs(libt::ip_filter &filter) -{ - // First, import current filter - foreach (const QString &ip, m_bannedIPs.value()) { - boost::system::error_code ec; - libt::address addr = libt::address::from_string(ip.toLatin1().constData(), ec); - Q_ASSERT(!ec); - if (!ec) - filter.add_rule(addr, addr, libt::ip_filter::blocked); - } -} - -#if LIBTORRENT_VERSION_NUM >= 10100 -void Session::adjustLimits(libt::settings_pack &settingsPack) -{ - //Internally increase the queue limits to ensure that the magnet is started - int maxDownloads = maxActiveDownloads(); - int maxActive = maxActiveTorrents(); - - settingsPack.set_int(libt::settings_pack::active_downloads - , maxDownloads > -1 ? maxDownloads + m_extraLimit : maxDownloads); - settingsPack.set_int(libt::settings_pack::active_limit - , maxActive > -1 ? maxActive + m_extraLimit : maxActive); -} - -void Session::initMetrics() -{ - m_metricIndices.net.hasIncomingConnections = libt::find_metric_idx("net.has_incoming_connections"); - Q_ASSERT(m_metricIndices.net.hasIncomingConnections >= 0); - - m_metricIndices.net.sentPayloadBytes = libt::find_metric_idx("net.sent_payload_bytes"); - Q_ASSERT(m_metricIndices.net.sentPayloadBytes >= 0); - - m_metricIndices.net.recvPayloadBytes = libt::find_metric_idx("net.recv_payload_bytes"); - Q_ASSERT(m_metricIndices.net.recvPayloadBytes >= 0); - - m_metricIndices.net.sentBytes = libt::find_metric_idx("net.sent_bytes"); - Q_ASSERT(m_metricIndices.net.sentBytes >= 0); - - m_metricIndices.net.recvBytes = libt::find_metric_idx("net.recv_bytes"); - Q_ASSERT(m_metricIndices.net.recvBytes >= 0); - - m_metricIndices.net.sentIPOverheadBytes = libt::find_metric_idx("net.sent_ip_overhead_bytes"); - Q_ASSERT(m_metricIndices.net.sentIPOverheadBytes >= 0); - - m_metricIndices.net.recvIPOverheadBytes = libt::find_metric_idx("net.recv_ip_overhead_bytes"); - Q_ASSERT(m_metricIndices.net.recvIPOverheadBytes >= 0); - - m_metricIndices.net.sentTrackerBytes = libt::find_metric_idx("net.sent_tracker_bytes"); - Q_ASSERT(m_metricIndices.net.sentTrackerBytes >= 0); - - m_metricIndices.net.recvTrackerBytes = libt::find_metric_idx("net.recv_tracker_bytes"); - Q_ASSERT(m_metricIndices.net.recvTrackerBytes >= 0); - - m_metricIndices.net.recvRedundantBytes = libt::find_metric_idx("net.recv_redundant_bytes"); - Q_ASSERT(m_metricIndices.net.recvRedundantBytes >= 0); - - m_metricIndices.net.recvFailedBytes = libt::find_metric_idx("net.recv_failed_bytes"); - Q_ASSERT(m_metricIndices.net.recvFailedBytes >= 0); - - m_metricIndices.peer.numPeersConnected = libt::find_metric_idx("peer.num_peers_connected"); - Q_ASSERT(m_metricIndices.peer.numPeersConnected >= 0); - - m_metricIndices.peer.numPeersDownDisk = libt::find_metric_idx("peer.num_peers_down_disk"); - Q_ASSERT(m_metricIndices.peer.numPeersDownDisk >= 0); - - m_metricIndices.peer.numPeersUpDisk = libt::find_metric_idx("peer.num_peers_up_disk"); - Q_ASSERT(m_metricIndices.peer.numPeersUpDisk >= 0); - - m_metricIndices.dht.dhtBytesIn = libt::find_metric_idx("dht.dht_bytes_in"); - Q_ASSERT(m_metricIndices.dht.dhtBytesIn >= 0); - - m_metricIndices.dht.dhtBytesOut = libt::find_metric_idx("dht.dht_bytes_out"); - Q_ASSERT(m_metricIndices.dht.dhtBytesOut >= 0); - - m_metricIndices.dht.dhtNodes = libt::find_metric_idx("dht.dht_nodes"); - Q_ASSERT(m_metricIndices.dht.dhtNodes >= 0); - - m_metricIndices.disk.diskBlocksInUse = libt::find_metric_idx("disk.disk_blocks_in_use"); - Q_ASSERT(m_metricIndices.disk.diskBlocksInUse >= 0); - - m_metricIndices.disk.numBlocksRead = libt::find_metric_idx("disk.num_blocks_read"); - Q_ASSERT(m_metricIndices.disk.numBlocksRead >= 0); - - m_metricIndices.disk.numBlocksCacheHits = libt::find_metric_idx("disk.num_blocks_cache_hits"); - Q_ASSERT(m_metricIndices.disk.numBlocksCacheHits >= 0); - - m_metricIndices.disk.queuedDiskJobs = libt::find_metric_idx("disk.queued_disk_jobs"); - Q_ASSERT(m_metricIndices.disk.queuedDiskJobs >= 0); - - m_metricIndices.disk.diskJobTime = libt::find_metric_idx("disk.disk_job_time"); - Q_ASSERT(m_metricIndices.disk.diskJobTime >= 0); -} - -void Session::configure(libtorrent::settings_pack &settingsPack) -{ - Logger* const logger = Logger::instance(); - - if (m_listenInterfaceChanged) { - const ushort port = this->port(); - std::pair ports(port, port); - settingsPack.set_int(libt::settings_pack::max_retry_port_bind, ports.second - ports.first); - foreach (QString ip, getListeningIPs()) { - libt::error_code ec; - std::string interfacesStr; - - if (ip.isEmpty()) { - ip = QLatin1String("0.0.0.0"); - interfacesStr = std::string((QString("%1:%2").arg(ip).arg(port)).toLatin1().constData()); - logger->addMessage(tr("qBittorrent is trying to listen on any interface port: %1" - , "e.g: qBittorrent is trying to listen on any interface port: TCP/6881") - .arg(QString::number(port)) - , Log::INFO); - - settingsPack.set_str(libt::settings_pack::listen_interfaces, interfacesStr); - break; - } - - libt::address addr = libt::address::from_string(ip.toLatin1().constData(), ec); - if (!ec) { - interfacesStr = std::string((addr.is_v6() ? QString("[%1]:%2") : QString("%1:%2")) - .arg(ip).arg(port).toLatin1().constData()); - logger->addMessage(tr("qBittorrent is trying to listen on interface %1 port: %2" - , "e.g: qBittorrent is trying to listen on interface 192.168.0.1 port: TCP/6881") - .arg(ip).arg(port) - , Log::INFO); - settingsPack.set_str(libt::settings_pack::listen_interfaces, interfacesStr); - break; - } - } - - settingsPack.set_str(libt::settings_pack::outgoing_interfaces, networkInterface().toStdString()); - m_listenInterfaceChanged = false; - } - - const bool altSpeedLimitEnabled = isAltGlobalSpeedLimitEnabled(); - settingsPack.set_int(libt::settings_pack::download_rate_limit, altSpeedLimitEnabled ? altGlobalDownloadSpeedLimit() : globalDownloadSpeedLimit()); - settingsPack.set_int(libt::settings_pack::upload_rate_limit, altSpeedLimitEnabled ? altGlobalUploadSpeedLimit() : globalUploadSpeedLimit()); - - // The most secure, rc4 only so that all streams are encrypted - settingsPack.set_int(libt::settings_pack::allowed_enc_level, libt::settings_pack::pe_rc4); - settingsPack.set_bool(libt::settings_pack::prefer_rc4, true); - switch (encryption()) { - case 0: //Enabled - settingsPack.set_int(libt::settings_pack::out_enc_policy, libt::settings_pack::pe_enabled); - settingsPack.set_int(libt::settings_pack::in_enc_policy, libt::settings_pack::pe_enabled); - break; - case 1: // Forced - settingsPack.set_int(libt::settings_pack::out_enc_policy, libt::settings_pack::pe_forced); - settingsPack.set_int(libt::settings_pack::in_enc_policy, libt::settings_pack::pe_forced); - break; - default: // Disabled - settingsPack.set_int(libt::settings_pack::out_enc_policy, libt::settings_pack::pe_disabled); - settingsPack.set_int(libt::settings_pack::in_enc_policy, libt::settings_pack::pe_disabled); - } - - auto proxyManager = Net::ProxyConfigurationManager::instance(); - Net::ProxyConfiguration proxyConfig = proxyManager->proxyConfiguration(); - if (m_useProxy || (proxyConfig.type != Net::ProxyType::None)) { - if (proxyConfig.type != Net::ProxyType::None) { - settingsPack.set_str(libt::settings_pack::proxy_hostname, proxyConfig.ip.toStdString()); - settingsPack.set_int(libt::settings_pack::proxy_port, proxyConfig.port); - if (proxyManager->isAuthenticationRequired()) { - settingsPack.set_str(libt::settings_pack::proxy_username, proxyConfig.username.toStdString()); - settingsPack.set_str(libt::settings_pack::proxy_password, proxyConfig.password.toStdString()); - } - settingsPack.set_bool(libt::settings_pack::proxy_peer_connections, isProxyPeerConnectionsEnabled()); - } - - switch (proxyConfig.type) { - case Net::ProxyType::HTTP: - settingsPack.set_int(libt::settings_pack::proxy_type, libt::settings_pack::http); - break; - case Net::ProxyType::HTTP_PW: - settingsPack.set_int(libt::settings_pack::proxy_type, libt::settings_pack::http_pw); - break; - case Net::ProxyType::SOCKS4: - settingsPack.set_int(libt::settings_pack::proxy_type, libt::settings_pack::socks4); - break; - case Net::ProxyType::SOCKS5: - settingsPack.set_int(libt::settings_pack::proxy_type, libt::settings_pack::socks5); - break; - case Net::ProxyType::SOCKS5_PW: - settingsPack.set_int(libt::settings_pack::proxy_type, libt::settings_pack::socks5_pw); - break; - default: - settingsPack.set_int(libt::settings_pack::proxy_type, libt::settings_pack::none); - } - - m_useProxy = (proxyConfig.type != Net::ProxyType::None); - } - settingsPack.set_bool(libt::settings_pack::force_proxy, m_useProxy ? isForceProxyEnabled() : false); - - const bool announceToAll = announceToAllTrackers(); - settingsPack.set_bool(libt::settings_pack::announce_to_all_trackers, announceToAll); - settingsPack.set_bool(libt::settings_pack::announce_to_all_tiers, announceToAll); - - const int cacheSize = diskCacheSize(); - settingsPack.set_int(libt::settings_pack::cache_size, (cacheSize > 0) ? cacheSize * 64 : -1); - settingsPack.set_int(libt::settings_pack::cache_expiry, diskCacheTTL()); - qDebug() << "Using a disk cache size of" << cacheSize << "MiB"; - - libt::settings_pack::io_buffer_mode_t mode = useOSCache() ? libt::settings_pack::enable_os_cache - : libt::settings_pack::disable_os_cache; - settingsPack.set_int(libt::settings_pack::disk_io_read_mode, mode); - settingsPack.set_int(libt::settings_pack::disk_io_write_mode, mode); - - settingsPack.set_bool(libt::settings_pack::anonymous_mode, isAnonymousModeEnabled()); - - // Queueing System - if (isQueueingSystemEnabled()) { - adjustLimits(settingsPack); - - settingsPack.set_int(libt::settings_pack::active_seeds, maxActiveUploads()); - settingsPack.set_bool(libt::settings_pack::dont_count_slow_torrents, ignoreSlowTorrentsForQueueing()); - } - else { - settingsPack.set_int(libt::settings_pack::active_downloads, -1); - settingsPack.set_int(libt::settings_pack::active_seeds, -1); - settingsPack.set_int(libt::settings_pack::active_limit, -1); - } - settingsPack.set_int(libt::settings_pack::active_tracker_limit, -1); - settingsPack.set_int(libt::settings_pack::active_dht_limit, -1); - settingsPack.set_int(libt::settings_pack::active_lsd_limit, -1); - // 1 active torrent force 2 connections. If you have more active torrents * 2 than connection limit, - // connection limit will get extended. Multiply max connections or active torrents by 10 for queue. - // Ignore -1 values because we don't want to set a max int message queue - settingsPack.set_int(libt::settings_pack::alert_queue_size, std::max(1000, - 10 * std::max(maxActiveTorrents() * 2, maxConnections()))); - - // Outgoing ports - settingsPack.set_int(libt::settings_pack::outgoing_port, outgoingPortsMin()); - settingsPack.set_int(libt::settings_pack::num_outgoing_ports, outgoingPortsMax() - outgoingPortsMin() + 1); - - // Include overhead in transfer limits - settingsPack.set_bool(libt::settings_pack::rate_limit_ip_overhead, includeOverheadInLimits()); - // IP address to announce to trackers - settingsPack.set_str(libt::settings_pack::announce_ip, announceIP().toStdString()); - // Super seeding - settingsPack.set_bool(libt::settings_pack::strict_super_seeding, isSuperSeedingEnabled()); - // * Max connections limit - settingsPack.set_int(libt::settings_pack::connections_limit, maxConnections()); - // * Global max upload slots - settingsPack.set_int(libt::settings_pack::unchoke_slots_limit, maxUploads()); - // uTP - settingsPack.set_bool(libt::settings_pack::enable_incoming_utp, isUTPEnabled()); - settingsPack.set_bool(libt::settings_pack::enable_outgoing_utp, isUTPEnabled()); - settingsPack.set_int(libt::settings_pack::mixed_mode_algorithm, isUTPRateLimited() - ? libt::settings_pack::prefer_tcp - : libt::settings_pack::peer_proportional); - - settingsPack.set_bool(libt::settings_pack::apply_ip_filter_to_trackers, isTrackerFilteringEnabled()); - - settingsPack.set_bool(libt::settings_pack::enable_dht, isDHTEnabled()); - if (isDHTEnabled()) - settingsPack.set_str(libt::settings_pack::dht_bootstrap_nodes, "dht.libtorrent.org:25401,router.bittorrent.com:6881,router.utorrent.com:6881,dht.transmissionbt.com:6881,dht.aelitis.com:6881"); - settingsPack.set_bool(libt::settings_pack::enable_lsd, isLSDEnabled()); -} - -void Session::configurePeerClasses() -{ - libt::ip_filter f; - f.add_rule(libt::address_v4::from_string("0.0.0.0") - , libt::address_v4::from_string("255.255.255.255") - , 1 << libt::session::global_peer_class_id); -#if TORRENT_USE_IPV6 - f.add_rule(libt::address_v6::from_string("::0") - , libt::address_v6::from_string("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff") - , 1 << libt::session::global_peer_class_id); -#endif - if (ignoreLimitsOnLAN()) { - // local networks - f.add_rule(libt::address_v4::from_string("10.0.0.0") - , libt::address_v4::from_string("10.255.255.255") - , 1 << libt::session::local_peer_class_id); - f.add_rule(libt::address_v4::from_string("172.16.0.0") - , libt::address_v4::from_string("172.31.255.255") - , 1 << libt::session::local_peer_class_id); - f.add_rule(libt::address_v4::from_string("192.168.0.0") - , libt::address_v4::from_string("192.168.255.255") - , 1 << libt::session::local_peer_class_id); - // link local - f.add_rule(libt::address_v4::from_string("169.254.0.0") - , libt::address_v4::from_string("169.254.255.255") - , 1 << libt::session::local_peer_class_id); - // loopback - f.add_rule(libt::address_v4::from_string("127.0.0.0") - , libt::address_v4::from_string("127.255.255.255") - , 1 << libt::session::local_peer_class_id); -#if TORRENT_USE_IPV6 - // link local - f.add_rule(libt::address_v6::from_string("fe80::") - , libt::address_v6::from_string("febf:ffff:ffff:ffff:ffff:ffff:ffff:ffff") - , 1 << libt::session::local_peer_class_id); - // unique local addresses - f.add_rule(libt::address_v6::from_string("fc00::") - , libt::address_v6::from_string("fdff:ffff:ffff:ffff:ffff:ffff:ffff:ffff") - , 1 << libt::session::local_peer_class_id); - // loopback - f.add_rule(libt::address_v6::from_string("::1") - , libt::address_v6::from_string("::1") - , 1 << libt::session::local_peer_class_id); -#endif - } - m_nativeSession->set_peer_class_filter(f); - - libt::peer_class_type_filter peerClassTypeFilter; - peerClassTypeFilter.add(libt::peer_class_type_filter::tcp_socket, libt::session::tcp_peer_class_id); - peerClassTypeFilter.add(libt::peer_class_type_filter::ssl_tcp_socket, libt::session::tcp_peer_class_id); - peerClassTypeFilter.add(libt::peer_class_type_filter::i2p_socket, libt::session::tcp_peer_class_id); - if (isUTPRateLimited()) { - peerClassTypeFilter.add(libt::peer_class_type_filter::utp_socket - , libt::session::local_peer_class_id); - peerClassTypeFilter.add(libt::peer_class_type_filter::utp_socket - , libt::session::global_peer_class_id); - peerClassTypeFilter.add(libt::peer_class_type_filter::ssl_utp_socket - , libt::session::local_peer_class_id); - peerClassTypeFilter.add(libt::peer_class_type_filter::ssl_utp_socket - , libt::session::global_peer_class_id); - } - m_nativeSession->set_peer_class_type_filter(peerClassTypeFilter); -} - -#else - -void Session::adjustLimits(libt::session_settings &sessionSettings) -{ - //Internally increase the queue limits to ensure that the magnet is started - int maxDownloads = maxActiveDownloads(); - int maxActive = maxActiveTorrents(); - - sessionSettings.active_downloads = maxDownloads > -1 ? maxDownloads + m_extraLimit : maxDownloads; - sessionSettings.active_limit = maxActive > -1 ? maxActive + m_extraLimit : maxActive; -} - -void Session::configure(libtorrent::session_settings &sessionSettings) -{ - const bool altSpeedLimitEnabled = isAltGlobalSpeedLimitEnabled(); - sessionSettings.download_rate_limit = altSpeedLimitEnabled ? altGlobalDownloadSpeedLimit() : globalDownloadSpeedLimit(); - sessionSettings.upload_rate_limit = altSpeedLimitEnabled ? altGlobalUploadSpeedLimit() : globalUploadSpeedLimit(); - - // The most secure, rc4 only so that all streams are encrypted - libt::pe_settings encryptionSettings; - encryptionSettings.allowed_enc_level = libt::pe_settings::rc4; - encryptionSettings.prefer_rc4 = true; - switch (encryption()) { - case 0: //Enabled - encryptionSettings.out_enc_policy = libt::pe_settings::enabled; - encryptionSettings.in_enc_policy = libt::pe_settings::enabled; - break; - case 1: // Forced - encryptionSettings.out_enc_policy = libt::pe_settings::forced; - encryptionSettings.in_enc_policy = libt::pe_settings::forced; - break; - default: // Disabled - encryptionSettings.out_enc_policy = libt::pe_settings::disabled; - encryptionSettings.in_enc_policy = libt::pe_settings::disabled; - } - m_nativeSession->set_pe_settings(encryptionSettings); - - auto proxyManager = Net::ProxyConfigurationManager::instance(); - Net::ProxyConfiguration proxyConfig = proxyManager->proxyConfiguration(); - if (m_useProxy || (proxyConfig.type != Net::ProxyType::None)) { - libt::proxy_settings proxySettings; - if (proxyConfig.type != Net::ProxyType::None) { - proxySettings.hostname = proxyConfig.ip.toStdString(); - proxySettings.port = proxyConfig.port; - if (proxyManager->isAuthenticationRequired()) { - proxySettings.username = proxyConfig.username.toStdString(); - proxySettings.password = proxyConfig.password.toStdString(); - } - proxySettings.proxy_peer_connections = isProxyPeerConnectionsEnabled(); - } - - switch (proxyConfig.type) { - case Net::ProxyType::HTTP: - proxySettings.type = libt::proxy_settings::http; - break; - case Net::ProxyType::HTTP_PW: - proxySettings.type = libt::proxy_settings::http_pw; - break; - case Net::ProxyType::SOCKS4: - proxySettings.type = libt::proxy_settings::socks4; - break; - case Net::ProxyType::SOCKS5: - proxySettings.type = libt::proxy_settings::socks5; - break; - case Net::ProxyType::SOCKS5_PW: - proxySettings.type = libt::proxy_settings::socks5_pw; - break; - default: - proxySettings.type = libt::proxy_settings::none; - } - - m_nativeSession->set_proxy(proxySettings); - m_useProxy = (proxyConfig.type != Net::ProxyType::None); - } - sessionSettings.force_proxy = m_useProxy ? isForceProxyEnabled() : false; - - bool announceToAll = announceToAllTrackers(); - sessionSettings.announce_to_all_trackers = announceToAll; - sessionSettings.announce_to_all_tiers = announceToAll; - int cacheSize = diskCacheSize(); - sessionSettings.cache_size = (cacheSize > 0) ? cacheSize * 64 : -1; - sessionSettings.cache_expiry = diskCacheTTL(); - qDebug() << "Using a disk cache size of" << cacheSize << "MiB"; - libt::session_settings::io_buffer_mode_t mode = useOSCache() ? libt::session_settings::enable_os_cache - : libt::session_settings::disable_os_cache; - sessionSettings.disk_io_read_mode = mode; - sessionSettings.disk_io_write_mode = mode; - - sessionSettings.anonymous_mode = isAnonymousModeEnabled(); - - // Queueing System - if (isQueueingSystemEnabled()) { - adjustLimits(sessionSettings); - - sessionSettings.active_seeds = maxActiveUploads(); - sessionSettings.dont_count_slow_torrents = ignoreSlowTorrentsForQueueing(); - } - else { - sessionSettings.active_downloads = -1; - sessionSettings.active_seeds = -1; - sessionSettings.active_limit = -1; - } - sessionSettings.active_tracker_limit = -1; - sessionSettings.active_dht_limit = -1; - sessionSettings.active_lsd_limit = -1; - // 1 active torrent force 2 connections. If you have more active torrents * 2 than connection limit, - // connection limit will get extended. Multiply max connections or active torrents by 10 for queue. - // Ignore -1 values because we don't want to set a max int message queue - sessionSettings.alert_queue_size = std::max(1000, - 10 * std::max(maxActiveTorrents() * 2, maxConnections())); - - // Outgoing ports - sessionSettings.outgoing_ports = std::make_pair(outgoingPortsMin(), outgoingPortsMax()); - - // Ignore limits on LAN - sessionSettings.ignore_limits_on_local_network = ignoreLimitsOnLAN(); - // Include overhead in transfer limits - sessionSettings.rate_limit_ip_overhead = includeOverheadInLimits(); - // IP address to announce to trackers - sessionSettings.announce_ip = announceIP().toStdString(); - // Super seeding - sessionSettings.strict_super_seeding = isSuperSeedingEnabled(); - // * Max Half-open connections - sessionSettings.half_open_limit = maxHalfOpenConnections(); - // * Max connections limit - sessionSettings.connections_limit = maxConnections(); - // * Global max upload slots - sessionSettings.unchoke_slots_limit = maxUploads(); - // uTP - sessionSettings.enable_incoming_utp = isUTPEnabled(); - sessionSettings.enable_outgoing_utp = isUTPEnabled(); - // uTP rate limiting - sessionSettings.rate_limit_utp = isUTPRateLimited(); - sessionSettings.mixed_mode_algorithm = isUTPRateLimited() - ? libt::session_settings::prefer_tcp - : libt::session_settings::peer_proportional; - - sessionSettings.apply_ip_filter_to_trackers = isTrackerFilteringEnabled(); - - if (isDHTEnabled()) { - // Add first the routers and then start DHT. - m_nativeSession->add_dht_router(std::make_pair(std::string("dht.libtorrent.org"), 25401)); - m_nativeSession->add_dht_router(std::make_pair(std::string("router.bittorrent.com"), 6881)); - m_nativeSession->add_dht_router(std::make_pair(std::string("router.utorrent.com"), 6881)); - m_nativeSession->add_dht_router(std::make_pair(std::string("dht.transmissionbt.com"), 6881)); - m_nativeSession->add_dht_router(std::make_pair(std::string("dht.aelitis.com"), 6881)); // Vuze - m_nativeSession->start_dht(); - } - else { - m_nativeSession->stop_dht(); - } - - if (isLSDEnabled()) - m_nativeSession->start_lsd(); - else - m_nativeSession->stop_lsd(); -} -#endif - -void Session::enableTracker(bool enable) -{ - Logger *const logger = Logger::instance(); - - if (enable) { - if (!m_tracker) - m_tracker = new Tracker(this); - - if (m_tracker->start()) - logger->addMessage(tr("Embedded Tracker [ON]"), Log::INFO); - else - logger->addMessage(tr("Failed to start the embedded tracker!"), Log::CRITICAL); - } - else { - logger->addMessage(tr("Embedded Tracker [OFF]"), Log::INFO); - if (m_tracker) - delete m_tracker; - } -} - -void Session::enableBandwidthScheduler() -{ - if (!m_bwScheduler) { - m_bwScheduler = new BandwidthScheduler(this); - connect(m_bwScheduler.data(), SIGNAL(switchToAlternativeMode(bool)), this, SLOT(switchToAlternativeMode(bool))); - } - m_bwScheduler->start(); -} - -void Session::populateAdditionalTrackers() -{ - m_additionalTrackerList.clear(); - foreach (QString tracker, additionalTrackers().split("\n")) { - tracker = tracker.trimmed(); - if (!tracker.isEmpty()) - m_additionalTrackerList << tracker; - } -} - -void Session::processShareLimits() -{ - qDebug("Processing share limits..."); - - foreach (TorrentHandle *const torrent, m_torrents) { - if (torrent->isSeed() && !torrent->isForced()) { - if (torrent->ratioLimit() != TorrentHandle::NO_RATIO_LIMIT) { - const qreal ratio = torrent->realRatio(); - qreal ratioLimit = torrent->ratioLimit(); - if (ratioLimit == TorrentHandle::USE_GLOBAL_RATIO) - // If Global Max Ratio is really set... - ratioLimit = globalMaxRatio(); - - if (ratioLimit >= 0) { - qDebug("Ratio: %f (limit: %f)", ratio, ratioLimit); - - if ((ratio <= TorrentHandle::MAX_RATIO) && (ratio >= ratioLimit)) { - Logger* const logger = Logger::instance(); - if (m_maxRatioAction == Remove) { - deleteTorrent(torrent->hash()); - logger->addMessage(tr("'%1' reached the maximum ratio you set. Removed.").arg(torrent->name())); - } - else if (!torrent->isPaused()) { - torrent->pause(); - logger->addMessage(tr("'%1' reached the maximum ratio you set. Paused.").arg(torrent->name())); - } - } - } - } - - if (torrent->seedingTimeLimit() != TorrentHandle::NO_SEEDING_TIME_LIMIT) { - const int seedingTimeInMinutes = torrent->seedingTime() / 60; - int seedingTimeLimit = torrent->seedingTimeLimit(); - if (seedingTimeLimit == TorrentHandle::USE_GLOBAL_SEEDING_TIME) - // If Global Seeding Time Limit is really set... - seedingTimeLimit = globalMaxSeedingMinutes(); - - if (seedingTimeLimit >= 0) { - qDebug("Seeding Time: %d (limit: %d)", seedingTimeInMinutes, seedingTimeLimit); - - if ((seedingTimeInMinutes <= TorrentHandle::MAX_SEEDING_TIME) && (seedingTimeInMinutes >= seedingTimeLimit)) { - Logger* const logger = Logger::instance(); - if (m_maxRatioAction == Remove) { - deleteTorrent(torrent->hash()); - logger->addMessage(tr("'%1' reached the maximum seeding time you set. Removed.").arg(torrent->name())); - } - else if (!torrent->isPaused()) { - torrent->pause(); - logger->addMessage(tr("'%1' reached the maximum seeding time you set. Paused.").arg(torrent->name())); - } - } - } - } - } - } -} - -void Session::handleDownloadFailed(const QString &url, const QString &reason) -{ - emit downloadFromUrlFailed(url, reason); -} - -void Session::handleRedirectedToMagnet(const QString &url, const QString &magnetUri) -{ - addTorrent_impl(m_downloadedTorrents.take(url), MagnetUri(magnetUri)); -} - -void Session::switchToAlternativeMode(bool alternative) -{ - changeSpeedLimitMode_impl(alternative); -} - -// Add to BitTorrent session the downloaded torrent file -void Session::handleDownloadFinished(const QString &url, const QString &filePath) -{ - emit downloadFromUrlFinished(url); - addTorrent_impl(m_downloadedTorrents.take(url), MagnetUri(), TorrentInfo::loadFromFile(filePath)); - Utils::Fs::forceRemove(filePath); // remove temporary file -} - -// Return the torrent handle, given its hash -TorrentHandle *Session::findTorrent(const InfoHash &hash) const -{ - return m_torrents.value(hash); -} - -bool Session::hasActiveTorrents() const -{ - foreach (TorrentHandle *const torrent, m_torrents) - if (TorrentFilter::ActiveTorrent.match(torrent)) - return true; - - return false; -} - -bool Session::hasUnfinishedTorrents() const -{ - foreach (TorrentHandle *const torrent, m_torrents) - if (!torrent->isSeed() && !torrent->isPaused()) - return true; - - return false; -} - -void Session::banIP(const QString &ip) -{ - QStringList bannedIPs = m_bannedIPs; - if (!bannedIPs.contains(ip)) { - libt::ip_filter filter = m_nativeSession->get_ip_filter(); - boost::system::error_code ec; - libt::address addr = libt::address::from_string(ip.toLatin1().constData(), ec); - Q_ASSERT(!ec); - if (ec) return; - filter.add_rule(addr, addr, libt::ip_filter::blocked); - m_nativeSession->set_ip_filter(filter); - - bannedIPs << ip; - bannedIPs.sort(); - m_bannedIPs = bannedIPs; - } -} - -// Delete a torrent from the session, given its hash -// deleteLocalFiles = true means that the torrent will be removed from the hard-drive too -bool Session::deleteTorrent(const QString &hash, bool deleteLocalFiles) -{ - TorrentHandle *const torrent = m_torrents.take(hash); - if (!torrent) return false; - - qDebug("Deleting torrent with hash: %s", qPrintable(torrent->hash())); - emit torrentAboutToBeRemoved(torrent); - - // Remove it from session - if (deleteLocalFiles) { - QString rootPath = torrent->rootPath(true); - if (!rootPath.isEmpty()) - // torrent with root folder - m_savePathsToRemove[torrent->hash()] = rootPath; - else if (torrent->useTempPath()) - // torrent without root folder still has it in its temporary save path - m_savePathsToRemove[torrent->hash()] = torrent->savePath(true); - m_nativeSession->remove_torrent(torrent->nativeHandle(), libt::session::delete_files); - } - else { - QStringList unwantedFiles; - if (torrent->hasMetadata()) - unwantedFiles = torrent->absoluteFilePathsUnwanted(); -#if LIBTORRENT_VERSION_NUM < 10100 - m_nativeSession->remove_torrent(torrent->nativeHandle()); -#else - m_nativeSession->remove_torrent(torrent->nativeHandle(), libt::session::delete_partfile); -#endif - // Remove unwanted and incomplete files - foreach (const QString &unwantedFile, unwantedFiles) { - qDebug("Removing unwanted file: %s", qPrintable(unwantedFile)); - Utils::Fs::forceRemove(unwantedFile); - const QString parentFolder = Utils::Fs::branchPath(unwantedFile); - qDebug("Attempt to remove parent folder (if empty): %s", qPrintable(parentFolder)); - QDir().rmpath(parentFolder); - } - } - - // Remove it from torrent resume directory - QDir resumeDataDir(m_resumeFolderPath); - QStringList filters; - filters << QString("%1.*").arg(torrent->hash()); - const QStringList files = resumeDataDir.entryList(filters, QDir::Files, QDir::Unsorted); - foreach (const QString &file, files) - Utils::Fs::forceRemove(resumeDataDir.absoluteFilePath(file)); - - if (deleteLocalFiles) - Logger::instance()->addMessage(tr("'%1' was removed from transfer list and hard disk.", "'xxx.avi' was removed...").arg(torrent->name())); - else - Logger::instance()->addMessage(tr("'%1' was removed from transfer list.", "'xxx.avi' was removed...").arg(torrent->name())); - - delete torrent; - qDebug("Torrent deleted."); - return true; -} - -bool Session::cancelLoadMetadata(const InfoHash &hash) -{ - if (!m_loadedMetadata.contains(hash)) return false; - - m_loadedMetadata.remove(hash); - libt::torrent_handle torrent = m_nativeSession->find_torrent(hash); - if (!torrent.is_valid()) return false; - - if (!torrent.status(0).has_metadata) { - // if hidden torrent is still loading metadata... - --m_extraLimit; - adjustLimits(); - } - - // Remove it from session - m_nativeSession->remove_torrent(torrent, libt::session::delete_files); - qDebug("Preloaded torrent deleted."); - return true; -} - -void Session::increaseTorrentsPriority(const QStringList &hashes) -{ - std::priority_queue, - std::vector >, - std::greater > > torrentQueue; - - // Sort torrents by priority - foreach (const InfoHash &hash, hashes) { - TorrentHandle *const torrent = m_torrents.value(hash); - if (torrent && !torrent->isSeed()) - torrentQueue.push(qMakePair(torrent->queuePosition(), torrent)); - } - - // Increase torrents priority (starting with the ones with highest priority) - while (!torrentQueue.empty()) { - TorrentHandle *const torrent = torrentQueue.top().second; - torrentQueuePositionUp(torrent->nativeHandle()); - torrentQueue.pop(); - } -} - -void Session::decreaseTorrentsPriority(const QStringList &hashes) -{ - std::priority_queue, - std::vector >, - std::less > > torrentQueue; - - // Sort torrents by priority - foreach (const InfoHash &hash, hashes) { - TorrentHandle *const torrent = m_torrents.value(hash); - if (torrent && !torrent->isSeed()) - torrentQueue.push(qMakePair(torrent->queuePosition(), torrent)); - } - - // Decrease torrents priority (starting with the ones with lowest priority) - while (!torrentQueue.empty()) { - TorrentHandle *const torrent = torrentQueue.top().second; - torrentQueuePositionDown(torrent->nativeHandle()); - torrentQueue.pop(); - } - - foreach (const InfoHash &hash, m_loadedMetadata.keys()) - torrentQueuePositionBottom(m_nativeSession->find_torrent(hash)); -} - -void Session::topTorrentsPriority(const QStringList &hashes) -{ - std::priority_queue, - std::vector >, - std::greater > > torrentQueue; - - // Sort torrents by priority - foreach (const InfoHash &hash, hashes) { - TorrentHandle *const torrent = m_torrents.value(hash); - if (torrent && !torrent->isSeed()) - torrentQueue.push(qMakePair(torrent->queuePosition(), torrent)); - } - - // Top torrents priority (starting with the ones with highest priority) - while (!torrentQueue.empty()) { - TorrentHandle *const torrent = torrentQueue.top().second; - torrentQueuePositionTop(torrent->nativeHandle()); - torrentQueue.pop(); - } -} - -void Session::bottomTorrentsPriority(const QStringList &hashes) -{ - std::priority_queue, - std::vector >, - std::less > > torrentQueue; - - // Sort torrents by priority - foreach (const InfoHash &hash, hashes) { - TorrentHandle *const torrent = m_torrents.value(hash); - if (torrent && !torrent->isSeed()) - torrentQueue.push(qMakePair(torrent->queuePosition(), torrent)); - } - - // Bottom torrents priority (starting with the ones with lowest priority) - while (!torrentQueue.empty()) { - TorrentHandle *const torrent = torrentQueue.top().second; - torrentQueuePositionBottom(torrent->nativeHandle()); - torrentQueue.pop(); - } - - foreach (const InfoHash &hash, m_loadedMetadata.keys()) - torrentQueuePositionBottom(m_nativeSession->find_torrent(hash)); -} - -QHash Session::torrents() const -{ - return m_torrents; -} - -TorrentStatusReport Session::torrentStatusReport() const -{ - return m_torrentStatusReport; -} - -// source - .torrent file path/url or magnet uri -bool Session::addTorrent(QString source, const AddTorrentParams ¶ms) -{ - MagnetUri magnetUri(source); - if (magnetUri.isValid()) { - return addTorrent_impl(params, magnetUri); - } - else if (Utils::Misc::isUrl(source)) { - Logger::instance()->addMessage(tr("Downloading '%1', please wait...", "e.g: Downloading 'xxx.torrent', please wait...").arg(source)); - // Launch downloader - Net::DownloadHandler *handler = Net::DownloadManager::instance()->downloadUrl(source, true, 10485760 /* 10MB */, true); - connect(handler, SIGNAL(downloadFinished(QString, QString)), this, SLOT(handleDownloadFinished(QString, QString))); - connect(handler, SIGNAL(downloadFailed(QString, QString)), this, SLOT(handleDownloadFailed(QString, QString))); - connect(handler, SIGNAL(redirectedToMagnet(QString, QString)), this, SLOT(handleRedirectedToMagnet(QString, QString))); - m_downloadedTorrents[handler->url()] = params; - } - else { - TorrentFileGuard guard(source); - if (addTorrent_impl(params, MagnetUri(), TorrentInfo::loadFromFile(source))) { - guard.markAsAddedToSession(); - return true; - } - } - - return false; -} - -bool Session::addTorrent(const TorrentInfo &torrentInfo, const AddTorrentParams ¶ms) -{ - if (!torrentInfo.isValid()) return false; - - return addTorrent_impl(params, MagnetUri(), torrentInfo); -} - -// Add a torrent to the BitTorrent session -bool Session::addTorrent_impl(AddTorrentData addData, const MagnetUri &magnetUri, - TorrentInfo torrentInfo, const QByteArray &fastresumeData) -{ - addData.savePath = normalizeSavePath(addData.savePath, ""); - - if (!addData.category.isEmpty()) { - if (!m_categories.contains(addData.category) && !addCategory(addData.category)) { - qWarning() << "Couldn't create category" << addData.category; - addData.category = ""; - } - } - - libt::add_torrent_params p; - InfoHash hash; - std::vector filePriorities; - - QString savePath; - if (addData.savePath.isEmpty()) // using Automatic mode - savePath = categorySavePath(addData.category); - else // using Manual mode - savePath = addData.savePath; - - bool fromMagnetUri = magnetUri.isValid(); - if (fromMagnetUri) { - hash = magnetUri.hash(); - - if (m_loadedMetadata.contains(hash)) { - // Adding preloaded torrent - m_loadedMetadata.remove(hash); - libt::torrent_handle handle = m_nativeSession->find_torrent(hash); - --m_extraLimit; - - try { - handle.auto_managed(false); - handle.pause(); - } - catch (std::exception &) {} - - adjustLimits(); - - // use common 2nd step of torrent addition - m_addingTorrents.insert(hash, addData); - createTorrentHandle(handle); - return true; - } - - p = magnetUri.addTorrentParams(); - } - else if (torrentInfo.isValid()) { - if (!addData.resumed && !addData.hasRootFolder) - torrentInfo.stripRootFolder(); - - // Metadata - if (!addData.resumed && !addData.hasSeedStatus) - findIncompleteFiles(torrentInfo, savePath); - p.ti = torrentInfo.nativeInfo(); - hash = torrentInfo.hash(); - } - else { - // We can have an invalid torrentInfo when there isn't a matching - // .torrent file to the .fastresume we loaded. Possibly from a - // failed upgrade. - return false; - } - - if (addData.resumed && !fromMagnetUri) { - // Set torrent fast resume data - p.resume_data = {fastresumeData.constData(), fastresumeData.constData() + fastresumeData.size()}; - p.flags |= libt::add_torrent_params::flag_use_resume_save_path; - } - else { - foreach (int prio, addData.filePriorities) - filePriorities.push_back(prio); - p.file_priorities = filePriorities; - } - - // We should not add torrent if it already - // processed or adding to session - if (m_addingTorrents.contains(hash) || m_loadedMetadata.contains(hash)) return false; - - if (m_torrents.contains(hash)) { - TorrentHandle *const torrent = m_torrents.value(hash); - if (torrent->isPrivate() || (!fromMagnetUri && torrentInfo.isPrivate())) - return false; - torrent->addTrackers(fromMagnetUri ? magnetUri.trackers() : torrentInfo.trackers()); - torrent->addUrlSeeds(fromMagnetUri ? magnetUri.urlSeeds() : torrentInfo.urlSeeds()); - return true; - } - - qDebug("Adding torrent..."); - qDebug(" -> Hash: %s", qPrintable(hash)); - - // Preallocation mode - if (isPreallocationEnabled()) - p.storage_mode = libt::storage_mode_allocate; - else - p.storage_mode = libt::storage_mode_sparse; - - p.flags |= libt::add_torrent_params::flag_paused; // Start in pause - p.flags &= ~libt::add_torrent_params::flag_auto_managed; // Because it is added in paused state - p.flags &= ~libt::add_torrent_params::flag_duplicate_is_error; // Already checked - - // Seeding mode - // Skip checking and directly start seeding (new in libtorrent v0.15) - if (addData.skipChecking) - p.flags |= libt::add_torrent_params::flag_seed_mode; - else - p.flags &= ~libt::add_torrent_params::flag_seed_mode; - - // Limits - p.max_connections = maxConnectionsPerTorrent(); - p.max_uploads = maxUploadsPerTorrent(); - p.save_path = Utils::Fs::toNativePath(savePath).toStdString(); - - m_addingTorrents.insert(hash, addData); - // Adding torrent to BitTorrent session - m_nativeSession->async_add_torrent(p); - return true; -} - -bool Session::findIncompleteFiles(TorrentInfo &torrentInfo, QString &savePath) const -{ - auto findInDir = [](const QString &dirPath, TorrentInfo &torrentInfo) -> bool - { - const QDir dir(dirPath); - bool found = false; - for (int i = 0; i < torrentInfo.filesCount(); ++i) { - const QString filePath = torrentInfo.filePath(i); - if (dir.exists(filePath)) { - found = true; - } - else if (dir.exists(filePath + QB_EXT)) { - found = true; - torrentInfo.renameFile(i, filePath + QB_EXT); - } - if ((i % 100) == 0) - qApp->processEvents(); - } - - return found; - }; - - bool found = findInDir(savePath, torrentInfo); - if (!found && isTempPathEnabled()) { - savePath = torrentTempPath(torrentInfo); - found = findInDir(savePath, torrentInfo); - } - - return found; -} - -// Add a torrent to the BitTorrent session in hidden mode -// and force it to load its metadata -bool Session::loadMetadata(const MagnetUri &magnetUri) -{ - if (!magnetUri.isValid()) return false; - - InfoHash hash = magnetUri.hash(); - QString name = magnetUri.name(); - - // We should not add torrent if it already - // processed or adding to session - if (m_torrents.contains(hash)) return false; - if (m_addingTorrents.contains(hash)) return false; - if (m_loadedMetadata.contains(hash)) return false; - - qDebug("Adding torrent to preload metadata..."); - qDebug(" -> Hash: %s", qPrintable(hash)); - qDebug(" -> Name: %s", qPrintable(name)); - - libt::add_torrent_params p = magnetUri.addTorrentParams(); - - // Flags - // Preallocation mode - if (isPreallocationEnabled()) - p.storage_mode = libt::storage_mode_allocate; - else - p.storage_mode = libt::storage_mode_sparse; - - // Limits - p.max_connections = maxConnectionsPerTorrent(); - p.max_uploads = maxUploadsPerTorrent(); - - QString savePath = QString("%1/%2").arg(QDir::tempPath()).arg(hash); - p.save_path = Utils::Fs::toNativePath(savePath).toStdString(); - - // Forced start - p.flags &= ~libt::add_torrent_params::flag_paused; - p.flags &= ~libt::add_torrent_params::flag_auto_managed; - // Solution to avoid accidental file writes - p.flags |= libt::add_torrent_params::flag_upload_mode; - - // Adding torrent to BitTorrent session - libt::error_code ec; - libt::torrent_handle h = m_nativeSession->add_torrent(p, ec); - if (ec) return false; - - // waiting for metadata... - m_loadedMetadata.insert(h.info_hash(), TorrentInfo()); - ++m_extraLimit; - adjustLimits(); - - return true; -} - -void Session::exportTorrentFile(TorrentHandle *const torrent, TorrentExportFolder folder) -{ - Q_ASSERT(((folder == TorrentExportFolder::Regular) && !torrentExportDirectory().isEmpty()) || - ((folder == TorrentExportFolder::Finished) && !finishedTorrentExportDirectory().isEmpty())); - - QString validName = Utils::Fs::toValidFileSystemName(torrent->name()); - QString torrentFilename = QString("%1.torrent").arg(torrent->hash()); - QString torrentExportFilename = QString("%1.torrent").arg(validName); - QString torrentPath = QDir(m_resumeFolderPath).absoluteFilePath(torrentFilename); - QDir exportPath(folder == TorrentExportFolder::Regular ? torrentExportDirectory() : finishedTorrentExportDirectory()); - if (exportPath.exists() || exportPath.mkpath(exportPath.absolutePath())) { - QString newTorrentPath = exportPath.absoluteFilePath(torrentExportFilename); - int counter = 0; - while (QFile::exists(newTorrentPath) && !Utils::Fs::sameFiles(torrentPath, newTorrentPath)) { - // Append number to torrent name to make it unique - torrentExportFilename = QString("%1 %2.torrent").arg(validName).arg(++counter); - newTorrentPath = exportPath.absoluteFilePath(torrentExportFilename); - } - - if (!QFile::exists(newTorrentPath)) - QFile::copy(torrentPath, newTorrentPath); - } -} - -void Session::changeSpeedLimitMode_impl(bool alternative) -{ - qDebug() << Q_FUNC_INFO << alternative; - if (alternative == isAltGlobalSpeedLimitEnabled()) return; - - // Save new state to remember it on startup - m_isAltGlobalSpeedLimitEnabled = alternative; - configureDeferred(); - // Notify - emit speedLimitModeChanged(alternative); -} - -void Session::generateResumeData(bool final) -{ - foreach (TorrentHandle *const torrent, m_torrents) { - if (!torrent->isValid()) continue; - if (torrent->hasMissingFiles()) continue; - if (torrent->isChecking() || torrent->hasError()) continue; - if (!final && !torrent->needSaveResumeData()) continue; - - saveTorrentResumeData(torrent, final); - qDebug("Saving fastresume data for %s", qPrintable(torrent->name())); - } -} - -// Called on exit -void Session::saveResumeData() -{ - qDebug("Saving fast resume data..."); - - // Pause session - m_nativeSession->pause(); - - generateResumeData(true); - - while (m_numResumeData > 0) { - std::vector alerts; - getPendingAlerts(alerts, 30 * 1000); - if (alerts.empty()) { - std::cerr << " aborting with " << m_numResumeData - << " outstanding torrents to save resume data for" - << std::endl; - break; - } - - for (const auto a: alerts) { - switch (a->type()) { - case libt::save_resume_data_failed_alert::alert_type: - case libt::save_resume_data_alert::alert_type: - dispatchTorrentAlert(a); - break; - } -#if LIBTORRENT_VERSION_NUM < 10100 - delete a; -#endif - } - } -} - -void Session::setDefaultSavePath(QString path) -{ - path = normalizeSavePath(path); - if (path == m_defaultSavePath) return; - - m_defaultSavePath = path; - - if (isDisableAutoTMMWhenDefaultSavePathChanged()) - foreach (TorrentHandle *const torrent, torrents()) - torrent->setAutoTMMEnabled(false); - else - foreach (TorrentHandle *const torrent, torrents()) - torrent->handleCategorySavePathChanged(); -} - -void Session::setTempPath(QString path) -{ - path = normalizeSavePath(path, defaultSavePath() + "temp/"); - if (path == m_tempPath) return; - - m_tempPath = path; - - foreach (TorrentHandle *const torrent, m_torrents) - torrent->handleTempPathChanged(); -} - -void Session::networkOnlineStateChanged(const bool online) -{ - Logger::instance()->addMessage(tr("System network status changed to %1", "e.g: System network status changed to ONLINE").arg(online ? tr("ONLINE") : tr("OFFLINE")), Log::INFO); -} - -void Session::networkConfigurationChange(const QNetworkConfiguration& cfg) -{ - const QString configuredInterfaceName = networkInterface(); - // Empty means "Any Interface". In this case libtorrent has binded to 0.0.0.0 so any change to any interface will - // be automatically picked up. Otherwise we would rebinding here to 0.0.0.0 again. - if (configuredInterfaceName.isEmpty()) return; - - const QString changedInterface = cfg.name(); - - // workaround for QTBUG-52633: check interface IPs, react only if the IPs have changed - // seems to be present only with NetworkManager, hence Q_OS_LINUX -#if defined Q_OS_LINUX && QT_VERSION >= QT_VERSION_CHECK(5, 0, 0) && QT_VERSION < QT_VERSION_CHECK(5, 7, 1) - static QStringList boundIPs = getListeningIPs(); - const QStringList newBoundIPs = getListeningIPs(); - if ((configuredInterfaceName == changedInterface) && (boundIPs != newBoundIPs)) { - boundIPs = newBoundIPs; -#else - if (configuredInterfaceName == changedInterface) { -#endif - Logger::instance()->addMessage(tr("Network configuration of %1 has changed, refreshing session binding", "e.g: Network configuration of tun0 has changed, refreshing session binding").arg(changedInterface), Log::INFO); - configureListeningInterface(); - } -} - -const QStringList Session::getListeningIPs() -{ - Logger* const logger = Logger::instance(); - QStringList IPs; - - const QString ifaceName = networkInterface(); - const QString ifaceAddr = networkInterfaceAddress(); - const bool listenIPv6 = isIPv6Enabled(); - - if (!ifaceAddr.isEmpty()) { - QHostAddress addr(ifaceAddr); - if (addr.isNull()) { - logger->addMessage(tr("Configured network interface address %1 isn't valid.", "Configured network interface address 124.5.1568.1 isn't valid.").arg(ifaceAddr), Log::CRITICAL); - IPs.append("127.0.0.1"); // Force listening to localhost and avoid accidental connection that will expose user data. - return IPs; - } - } - - if (ifaceName.isEmpty()) { - if (!ifaceAddr.isEmpty()) - IPs.append(ifaceAddr); - else - IPs.append(QString()); - - return IPs; - } - - // Attempt to listen on provided interface - const QNetworkInterface networkIFace = QNetworkInterface::interfaceFromName(ifaceName); - if (!networkIFace.isValid()) { - qDebug("Invalid network interface: %s", qPrintable(ifaceName)); - logger->addMessage(tr("The network interface defined is invalid: %1").arg(ifaceName), Log::CRITICAL); - IPs.append("127.0.0.1"); // Force listening to localhost and avoid accidental connection that will expose user data. - return IPs; - } - - const QList addresses = networkIFace.addressEntries(); - qDebug("This network interface has %d IP addresses", addresses.size()); - QHostAddress ip; - QString ipString; - QAbstractSocket::NetworkLayerProtocol protocol; - foreach (const QNetworkAddressEntry &entry, addresses) { - ip = entry.ip(); - ipString = ip.toString(); - protocol = ip.protocol(); - Q_ASSERT(protocol == QAbstractSocket::IPv4Protocol || protocol == QAbstractSocket::IPv6Protocol); - if ((!listenIPv6 && (protocol == QAbstractSocket::IPv6Protocol)) - || (listenIPv6 && (protocol == QAbstractSocket::IPv4Protocol))) - continue; - - //If an iface address has been defined only allow ip's that match it to go through - if (!ifaceAddr.isEmpty()) { - if (ifaceAddr == ipString) { - IPs.append(ipString); - break; - } - } - else { - IPs.append(ipString); - } - } - - // Make sure there is at least one IP - // At this point there was a valid network interface, with no suitable IP. - if (IPs.size() == 0) { - logger->addMessage(tr("qBittorrent didn't find an %1 local address to listen on", "qBittorrent didn't find an IPv4 local address to listen on").arg(listenIPv6 ? "IPv6" : "IPv4"), Log::CRITICAL); - IPs.append("127.0.0.1"); // Force listening to localhost and avoid accidental connection that will expose user data. - return IPs; - } - - return IPs; -} - -// Set the ports range in which is chosen the port -// the BitTorrent session will listen to -void Session::configureListeningInterface() -{ -#if LIBTORRENT_VERSION_NUM < 10100 - const ushort port = this->port(); - qDebug() << Q_FUNC_INFO << port; - - Logger* const logger = Logger::instance(); - - std::pair ports(port, port); - libt::error_code ec; - const QStringList IPs = getListeningIPs(); - - foreach (const QString ip, IPs) { - if (ip.isEmpty()) { - logger->addMessage(tr("qBittorrent is trying to listen on any interface port: %1", "e.g: qBittorrent is trying to listen on any interface port: TCP/6881").arg(QString::number(port)), Log::INFO); - m_nativeSession->listen_on(ports, ec, 0, libt::session::listen_no_system_port); - - if (ec) - logger->addMessage(tr("qBittorrent failed to listen on any interface port: %1. Reason: %2.", "e.g: qBittorrent failed to listen on any interface port: TCP/6881. Reason: no such interface" ).arg(QString::number(port)).arg(QString::fromLocal8Bit(ec.message().c_str())), Log::CRITICAL); - - return; - } - - m_nativeSession->listen_on(ports, ec, ip.toLatin1().constData(), libt::session::listen_no_system_port); - if (!ec) { - logger->addMessage(tr("qBittorrent is trying to listen on interface %1 port: %2", "e.g: qBittorrent is trying to listen on interface 192.168.0.1 port: TCP/6881").arg(ip).arg(port), Log::INFO); - return; - } - } -#else - m_listenInterfaceChanged = true; - configureDeferred(); -#endif -} - -int Session::globalDownloadSpeedLimit() const -{ - // Unfortunately the value was saved as KiB instead of B. - // But it is better to pass it around internally(+ webui) as Bytes. - return m_globalDownloadSpeedLimit * 1024; -} - -void Session::setGlobalDownloadSpeedLimit(int limit) -{ - // Unfortunately the value was saved as KiB instead of B. - // But it is better to pass it around internally(+ webui) as Bytes. - limit /= 1024; - if (limit < 0) limit = 0; - if (limit == globalDownloadSpeedLimit()) return; - - m_globalDownloadSpeedLimit = limit; - if (!isAltGlobalSpeedLimitEnabled()) - configureDeferred(); -} - -int Session::globalUploadSpeedLimit() const -{ - // Unfortunately the value was saved as KiB instead of B. - // But it is better to pass it around internally(+ webui) as Bytes. - return m_globalUploadSpeedLimit * 1024; -} - -void Session::setGlobalUploadSpeedLimit(int limit) -{ - // Unfortunately the value was saved as KiB instead of B. - // But it is better to pass it around internally(+ webui) as Bytes. - limit /= 1024; - if (limit < 0) limit = 0; - if (limit == globalUploadSpeedLimit()) return; - - m_globalUploadSpeedLimit = limit; - if (!isAltGlobalSpeedLimitEnabled()) - configureDeferred(); -} - -int Session::altGlobalDownloadSpeedLimit() const -{ - // Unfortunately the value was saved as KiB instead of B. - // But it is better to pass it around internally(+ webui) as Bytes. - return m_altGlobalDownloadSpeedLimit * 1024; -} - -void Session::setAltGlobalDownloadSpeedLimit(int limit) -{ - // Unfortunately the value was saved as KiB instead of B. - // But it is better to pass it around internally(+ webui) as Bytes. - limit /= 1024; - if (limit < 0) limit = 0; - if (limit == altGlobalDownloadSpeedLimit()) return; - - m_altGlobalDownloadSpeedLimit = limit; - if (isAltGlobalSpeedLimitEnabled()) - configureDeferred(); -} - -int Session::altGlobalUploadSpeedLimit() const -{ - // Unfortunately the value was saved as KiB instead of B. - // But it is better to pass it around internally(+ webui) as Bytes. - return m_altGlobalUploadSpeedLimit * 1024; -} - -void Session::setAltGlobalUploadSpeedLimit(int limit) -{ - // Unfortunately the value was saved as KiB instead of B. - // But it is better to pass it around internally(+ webui) as Bytes. - limit /= 1024; - if (limit < 0) limit = 0; - if (limit == altGlobalUploadSpeedLimit()) return; - - m_altGlobalUploadSpeedLimit = limit; - if (isAltGlobalSpeedLimitEnabled()) - configureDeferred(); -} - -int Session::downloadSpeedLimit() const -{ - return isAltGlobalSpeedLimitEnabled() - ? altGlobalDownloadSpeedLimit() - : globalDownloadSpeedLimit(); -} - -void Session::setDownloadSpeedLimit(int limit) -{ - if (isAltGlobalSpeedLimitEnabled()) - setAltGlobalDownloadSpeedLimit(limit); - else - setGlobalDownloadSpeedLimit(limit); -} - -int Session::uploadSpeedLimit() const -{ - return isAltGlobalSpeedLimitEnabled() - ? altGlobalUploadSpeedLimit() - : globalUploadSpeedLimit(); -} - -void Session::setUploadSpeedLimit(int limit) -{ - if (isAltGlobalSpeedLimitEnabled()) - setAltGlobalUploadSpeedLimit(limit); - else - setGlobalUploadSpeedLimit(limit); -} - -bool Session::isAltGlobalSpeedLimitEnabled() const -{ - return m_isAltGlobalSpeedLimitEnabled; -} - -void Session::setAltGlobalSpeedLimitEnabled(bool enabled) -{ - // Stop the scheduler when the user has manually changed the bandwidth mode - if (isBandwidthSchedulerEnabled()) - setBandwidthSchedulerEnabled(false); - - changeSpeedLimitMode_impl(enabled); -} - -bool Session::isBandwidthSchedulerEnabled() const -{ - return m_isBandwidthSchedulerEnabled; -} - -void Session::setBandwidthSchedulerEnabled(bool enabled) -{ - if (enabled != isBandwidthSchedulerEnabled()) { - m_isBandwidthSchedulerEnabled = enabled; - if (enabled) - enableBandwidthScheduler(); - else - delete m_bwScheduler; - } -} - -uint Session::saveResumeDataInterval() const -{ - return m_saveResumeDataInterval; -} - -void Session::setSaveResumeDataInterval(uint value) -{ - if (value != saveResumeDataInterval()) { - m_saveResumeDataInterval = value; - m_resumeDataTimer->setInterval(value * 60 * 1000); - } -} - -int Session::port() const -{ - static int randomPort = Utils::Random::rand(1024, 65535); - if (useRandomPort()) - return randomPort; - return m_port; -} - -void Session::setPort(int port) -{ - if (port != this->port()) { - m_port = port; - configureListeningInterface(); - } -} - -bool Session::useRandomPort() const -{ - return m_useRandomPort; -} - -void Session::setUseRandomPort(bool value) -{ - m_useRandomPort = value; -} - -QString Session::networkInterface() const -{ - return m_networkInterface; -} - -void Session::setNetworkInterface(const QString &interface) -{ - if (interface != networkInterface()) { - m_networkInterface = interface; - configureListeningInterface(); - } -} - -QString Session::networkInterfaceName() const -{ - return m_networkInterfaceName; -} - -void Session::setNetworkInterfaceName(const QString &name) -{ - m_networkInterfaceName = name; -} - -QString Session::networkInterfaceAddress() const -{ - return m_networkInterfaceAddress; -} - -void Session::setNetworkInterfaceAddress(const QString &address) -{ - if (address != networkInterfaceAddress()) { - m_networkInterfaceAddress = address; - configureListeningInterface(); - } -} - -bool Session::isIPv6Enabled() const -{ - return m_isIPv6Enabled; -} - -void Session::setIPv6Enabled(bool enabled) -{ - if (enabled != isIPv6Enabled()) { - m_isIPv6Enabled = enabled; - configureListeningInterface(); - } -} - -int Session::encryption() const -{ - return m_encryption; -} - -void Session::setEncryption(int state) -{ - if (state != encryption()) { - m_encryption = state; - configureDeferred(); - Logger::instance()->addMessage( - tr("Encryption support [%1]") - .arg(state == 0 ? tr("ON") : state == 1 ? tr("FORCED") : tr("OFF")) - , Log::INFO); - } -} - -bool Session::isForceProxyEnabled() const -{ - return m_isForceProxyEnabled; -} - -void Session::setForceProxyEnabled(bool enabled) -{ - if (enabled != isForceProxyEnabled()) { - m_isForceProxyEnabled = enabled; - configureDeferred(); - } -} - -bool Session::isProxyPeerConnectionsEnabled() const -{ - return m_isProxyPeerConnectionsEnabled; -} - -void Session::setProxyPeerConnectionsEnabled(bool enabled) -{ - if (enabled != isProxyPeerConnectionsEnabled()) { - m_isProxyPeerConnectionsEnabled = enabled; - configureDeferred(); - } -} - -bool Session::isAddTrackersEnabled() const -{ - return m_isAddTrackersEnabled; -} - -void Session::setAddTrackersEnabled(bool enabled) -{ - m_isAddTrackersEnabled = enabled; -} - -QString Session::additionalTrackers() const -{ - return m_additionalTrackers; -} - -void Session::setAdditionalTrackers(const QString &trackers) -{ - if (trackers != additionalTrackers()) { - m_additionalTrackers = trackers; - populateAdditionalTrackers(); - } -} - -bool Session::isIPFilteringEnabled() const -{ - return m_isIPFilteringEnabled; -} - -void Session::setIPFilteringEnabled(bool enabled) -{ - if (enabled != m_isIPFilteringEnabled) { - m_isIPFilteringEnabled = enabled; - m_IPFilteringChanged = true; - configureDeferred(); - } -} - -QString Session::IPFilterFile() const -{ - return Utils::Fs::fromNativePath(m_IPFilterFile); -} - -void Session::setIPFilterFile(QString path) -{ - path = Utils::Fs::fromNativePath(path); - if (path != IPFilterFile()) { - m_IPFilterFile = path; - m_IPFilteringChanged = true; - configureDeferred(); - } -} - -void Session::setBannedIPs(const QStringList &newList) -{ - if (newList == m_bannedIPs) - return; // do nothing - // here filter out incorrect IP - QStringList filteredList; - for (const QString &ip : newList) { - if (Utils::Net::isValidIP(ip)) { - // the same IPv6 addresses could be written in different forms; - // QHostAddress::toString() result format follows RFC5952; - // thus we avoid duplicate entries pointing to the same address - filteredList << QHostAddress(ip).toString(); - } - else { - Logger::instance()->addMessage( - tr("%1 is not a valid IP address and was rejected while applying the list of banned addresses.") - .arg(ip) - , Log::WARNING); - } - } - // now we have to sort IPs and make them unique - filteredList.sort(); - filteredList.removeDuplicates(); - // Again ensure that the new list is different from the stored one. - if (filteredList == m_bannedIPs) - return; // do nothing - // store to session settings - // also here we have to recreate filter list including 3rd party ban file - // and install it again into m_session - m_bannedIPs = filteredList; - m_IPFilteringChanged = true; - configureDeferred(); -} - -QStringList Session::bannedIPs() const -{ - return m_bannedIPs; -} - -int Session::maxConnectionsPerTorrent() const -{ - return m_maxConnectionsPerTorrent; -} - -void Session::setMaxConnectionsPerTorrent(int max) -{ - max = (max > 0) ? max : -1; - if (max != maxConnectionsPerTorrent()) { - m_maxConnectionsPerTorrent = max; - - // Apply this to all session torrents - for (const auto &handle: m_nativeSession->get_torrents()) { - if (!handle.is_valid()) continue; - try { - handle.set_max_connections(max); - } - catch(std::exception) {} - } - } -} - -int Session::maxUploadsPerTorrent() const -{ - return m_maxUploadsPerTorrent; -} - -void Session::setMaxUploadsPerTorrent(int max) -{ - max = (max > 0) ? max : -1; - if (max != maxUploadsPerTorrent()) { - m_maxUploadsPerTorrent = max; - - // Apply this to all session torrents - for (const auto &handle: m_nativeSession->get_torrents()) { - if (!handle.is_valid()) continue; - try { - handle.set_max_uploads(max); - } - catch(std::exception) {} - } - } -} - -bool Session::announceToAllTrackers() const -{ - return m_announceToAllTrackers; -} - -void Session::setAnnounceToAllTrackers(bool val) -{ - if (val != m_announceToAllTrackers) { - m_announceToAllTrackers = val; - configureDeferred(); - } -} - -uint Session::diskCacheSize() const -{ - uint size = m_diskCacheSize; - // These macros may not be available on compilers other than MSVC and GCC -#if defined(__x86_64__) || defined(_M_X64) - size = qMin(size, 4096u); // 4GiB -#else - // When build as 32bit binary, set the maximum at less than 2GB to prevent crashes - // allocate 1536MiB and leave 512MiB to the rest of program data in RAM - size = qMin(size, 1536u); -#endif - return size; -} - -void Session::setDiskCacheSize(uint size) -{ -#if defined(__x86_64__) || defined(_M_X64) - size = qMin(size, 4096u); // 4GiB -#else - // allocate 1536MiB and leave 512MiB to the rest of program data in RAM - size = qMin(size, 1536u); -#endif - if (size != m_diskCacheSize) { - m_diskCacheSize = size; - configureDeferred(); - } -} - -uint Session::diskCacheTTL() const -{ - return m_diskCacheTTL; -} - -void Session::setDiskCacheTTL(uint ttl) -{ - if (ttl != m_diskCacheTTL) { - m_diskCacheTTL = ttl; - configureDeferred(); - } -} - -bool Session::useOSCache() const -{ - return m_useOSCache; -} - -void Session::setUseOSCache(bool use) -{ - if (use != m_useOSCache) { - m_useOSCache = use; - configureDeferred(); - } -} - -bool Session::isAnonymousModeEnabled() const -{ - return m_isAnonymousModeEnabled; -} - -void Session::setAnonymousModeEnabled(bool enabled) -{ - if (enabled != m_isAnonymousModeEnabled) { - m_isAnonymousModeEnabled = enabled; - configureDeferred(); - Logger::instance()->addMessage( - tr("Anonymous mode [%1]").arg(isAnonymousModeEnabled() ? tr("ON") : tr("OFF")) - , Log::INFO); - } -} - -bool Session::isQueueingSystemEnabled() const -{ - return m_isQueueingEnabled; -} - -void Session::setQueueingSystemEnabled(bool enabled) -{ - if (enabled != m_isQueueingEnabled) { - m_isQueueingEnabled = enabled; - configureDeferred(); - } -} - -int Session::maxActiveDownloads() const -{ - return m_maxActiveDownloads; -} - -void Session::setMaxActiveDownloads(int max) -{ - max = std::max(max, -1); - if (max != m_maxActiveDownloads) { - m_maxActiveDownloads = max; - configureDeferred(); - } -} - -int Session::maxActiveUploads() const -{ - return m_maxActiveUploads; -} - -void Session::setMaxActiveUploads(int max) -{ - max = std::max(max, -1); - if (max != m_maxActiveUploads) { - m_maxActiveUploads = max; - configureDeferred(); - } -} - -int Session::maxActiveTorrents() const -{ - return m_maxActiveTorrents; -} - -void Session::setMaxActiveTorrents(int max) -{ - max = std::max(max, -1); - if (max != m_maxActiveTorrents) { - m_maxActiveTorrents = max; - configureDeferred(); - } -} - -bool Session::ignoreSlowTorrentsForQueueing() const -{ - return m_ignoreSlowTorrentsForQueueing; -} - -void Session::setIgnoreSlowTorrentsForQueueing(bool ignore) -{ - if (ignore != m_ignoreSlowTorrentsForQueueing) { - m_ignoreSlowTorrentsForQueueing = ignore; - configureDeferred(); - } -} - -uint Session::outgoingPortsMin() const -{ - return m_outgoingPortsMin; -} - -void Session::setOutgoingPortsMin(uint min) -{ - if (min != m_outgoingPortsMin) { - m_outgoingPortsMin = min; - configureDeferred(); - } -} - -uint Session::outgoingPortsMax() const -{ - return m_outgoingPortsMax; -} - -void Session::setOutgoingPortsMax(uint max) -{ - if (max != m_outgoingPortsMax) { - m_outgoingPortsMax = max; - configureDeferred(); - } -} - -bool Session::ignoreLimitsOnLAN() const -{ - return m_ignoreLimitsOnLAN; -} - -void Session::setIgnoreLimitsOnLAN(bool ignore) -{ - if (ignore != m_ignoreLimitsOnLAN) { - m_ignoreLimitsOnLAN = ignore; - configureDeferred(); - } -} - -bool Session::includeOverheadInLimits() const -{ - return m_includeOverheadInLimits; -} - -void Session::setIncludeOverheadInLimits(bool include) -{ - if (include != m_includeOverheadInLimits) { - m_includeOverheadInLimits = include; - configureDeferred(); - } -} - -QString Session::announceIP() const -{ - return m_announceIP; -} - -void Session::setAnnounceIP(const QString &ip) -{ - if (ip != m_announceIP) { - m_announceIP = ip; - configureDeferred(); - } -} - -bool Session::isSuperSeedingEnabled() const -{ - return m_isSuperSeedingEnabled; -} - -void Session::setSuperSeedingEnabled(bool enabled) -{ - if (enabled != m_isSuperSeedingEnabled) { - m_isSuperSeedingEnabled = enabled; - configureDeferred(); - } -} - -int Session::maxConnections() const -{ - return m_maxConnections; -} - -void Session::setMaxConnections(int max) -{ - max = (max > 0) ? max : -1; - if (max != m_maxConnections) { - m_maxConnections = max; - configureDeferred(); - } -} - -int Session::maxHalfOpenConnections() const -{ - return m_maxHalfOpenConnections; -} - -void Session::setMaxHalfOpenConnections(int max) -{ - max = (max > 0) ? max : -1; - if (max != m_maxHalfOpenConnections) { - m_maxHalfOpenConnections = max; - configureDeferred(); - } -} - -int Session::maxUploads() const -{ - return m_maxUploads; -} - -void Session::setMaxUploads(int max) -{ - max = (max > 0) ? max : -1; - if (max != m_maxUploads) { - m_maxUploads = max; - configureDeferred(); - } -} - -bool Session::isUTPEnabled() const -{ - return m_isUTPEnabled; -} - -void Session::setUTPEnabled(bool enabled) -{ - if (enabled != m_isUTPEnabled) { - m_isUTPEnabled = enabled; - configureDeferred(); - } -} - -bool Session::isUTPRateLimited() const -{ - return m_isUTPRateLimited; -} - -void Session::setUTPRateLimited(bool limited) -{ - if (limited != m_isUTPRateLimited) { - m_isUTPRateLimited = limited; - configureDeferred(); - } -} - -bool Session::isTrackerFilteringEnabled() const -{ - return m_isTrackerFilteringEnabled; -} - -void Session::setTrackerFilteringEnabled(bool enabled) -{ - if (enabled != m_isTrackerFilteringEnabled) { - m_isTrackerFilteringEnabled = enabled; - configureDeferred(); - } -} - -bool Session::isListening() const -{ - return m_nativeSession->is_listening(); -} - -MaxRatioAction Session::maxRatioAction() const -{ - return static_cast(m_maxRatioAction.value()); -} - -void Session::setMaxRatioAction(MaxRatioAction act) -{ - m_maxRatioAction = static_cast(act); -} - -// If this functions returns true, we cannot add torrent to session, -// but it is still possible to merge trackers in some case -bool Session::isKnownTorrent(const InfoHash &hash) const -{ - return (m_torrents.contains(hash) - || m_addingTorrents.contains(hash) - || m_loadedMetadata.contains(hash)); -} - -void Session::updateSeedingLimitTimer() -{ - if ((globalMaxRatio() == -1) && !hasPerTorrentRatioLimit() - && (globalMaxSeedingMinutes() == TorrentHandle::NO_SEEDING_TIME_LIMIT) && !hasPerTorrentSeedingTimeLimit()) { - if (m_seedingLimitTimer->isActive()) - m_seedingLimitTimer->stop(); - } - else if (!m_seedingLimitTimer->isActive()) { - m_seedingLimitTimer->start(); - } -} - -void Session::handleTorrentShareLimitChanged(TorrentHandle *const torrent) -{ - Q_UNUSED(torrent); - updateSeedingLimitTimer(); -} - -void Session::saveTorrentResumeData(TorrentHandle *const torrent, bool finalSave) -{ - torrent->saveResumeData(finalSave); - ++m_numResumeData; -} - -void Session::handleTorrentSavePathChanged(TorrentHandle *const torrent) -{ - emit torrentSavePathChanged(torrent); -} - -void Session::handleTorrentCategoryChanged(TorrentHandle *const torrent, const QString &oldCategory) -{ - emit torrentCategoryChanged(torrent, oldCategory); -} - -void Session::handleTorrentTagAdded(TorrentHandle *const torrent, const QString &tag) -{ - emit torrentTagAdded(torrent, tag); -} - -void Session::handleTorrentTagRemoved(TorrentHandle *const torrent, const QString &tag) -{ - emit torrentTagRemoved(torrent, tag); -} - -void Session::handleTorrentSavingModeChanged(TorrentHandle * const torrent) -{ - emit torrentSavingModeChanged(torrent); -} - -void Session::handleTorrentTrackersAdded(TorrentHandle *const torrent, const QList &newTrackers) -{ - foreach (const TrackerEntry &newTracker, newTrackers) - Logger::instance()->addMessage(tr("Tracker '%1' was added to torrent '%2'").arg(newTracker.url()).arg(torrent->name())); - emit trackersAdded(torrent, newTrackers); - if (torrent->trackers().size() == newTrackers.size()) - emit trackerlessStateChanged(torrent, false); - emit trackersChanged(torrent); -} - -void Session::handleTorrentTrackersRemoved(TorrentHandle *const torrent, const QList &deletedTrackers) -{ - foreach (const TrackerEntry &deletedTracker, deletedTrackers) - Logger::instance()->addMessage(tr("Tracker '%1' was deleted from torrent '%2'").arg(deletedTracker.url()).arg(torrent->name())); - emit trackersRemoved(torrent, deletedTrackers); - if (torrent->trackers().size() == 0) - emit trackerlessStateChanged(torrent, true); - emit trackersChanged(torrent); -} - -void Session::handleTorrentTrackersChanged(TorrentHandle *const torrent) -{ - emit trackersChanged(torrent); -} - -void Session::handleTorrentUrlSeedsAdded(TorrentHandle *const torrent, const QList &newUrlSeeds) -{ - foreach (const QUrl &newUrlSeed, newUrlSeeds) - Logger::instance()->addMessage(tr("URL seed '%1' was added to torrent '%2'").arg(newUrlSeed.toString()).arg(torrent->name())); -} - -void Session::handleTorrentUrlSeedsRemoved(TorrentHandle *const torrent, const QList &urlSeeds) -{ - foreach (const QUrl &urlSeed, urlSeeds) - Logger::instance()->addMessage(tr("URL seed '%1' was removed from torrent '%2'").arg(urlSeed.toString()).arg(torrent->name())); -} - -void Session::handleTorrentMetadataReceived(TorrentHandle *const torrent) -{ - saveTorrentResumeData(torrent); - - // Save metadata - const QDir resumeDataDir(m_resumeFolderPath); - QString torrentFile = resumeDataDir.absoluteFilePath(QString("%1.torrent").arg(torrent->hash())); - if (torrent->saveTorrentFile(torrentFile)) { - // Copy the torrent file to the export folder - if (!torrentExportDirectory().isEmpty()) - exportTorrentFile(torrent); - } - - emit torrentMetadataLoaded(torrent); -} - -void Session::handleTorrentPaused(TorrentHandle *const torrent) -{ - if (!torrent->hasError() && !torrent->hasMissingFiles()) - saveTorrentResumeData(torrent); - emit torrentPaused(torrent); -} - -void Session::handleTorrentResumed(TorrentHandle *const torrent) -{ - emit torrentResumed(torrent); -} - -void Session::handleTorrentChecked(TorrentHandle *const torrent) -{ - emit torrentFinishedChecking(torrent); -} - -void Session::handleTorrentFinished(TorrentHandle *const torrent) -{ - if (!torrent->hasError() && !torrent->hasMissingFiles()) - saveTorrentResumeData(torrent); - emit torrentFinished(torrent); - - qDebug("Checking if the torrent contains torrent files to download"); - // Check if there are torrent files inside - for (int i = 0; i < torrent->filesCount(); ++i) { - const QString torrentRelpath = torrent->filePath(i); - if (torrentRelpath.endsWith(".torrent", Qt::CaseInsensitive)) { - qDebug("Found possible recursive torrent download."); - const QString torrentFullpath = torrent->savePath(true) + "/" + torrentRelpath; - qDebug("Full subtorrent path is %s", qPrintable(torrentFullpath)); - TorrentInfo torrentInfo = TorrentInfo::loadFromFile(torrentFullpath); - if (torrentInfo.isValid()) { - qDebug("emitting recursiveTorrentDownloadPossible()"); - emit recursiveTorrentDownloadPossible(torrent); - break; - } - else { - qDebug("Caught error loading torrent"); - Logger::instance()->addMessage(tr("Unable to decode '%1' torrent file.").arg(Utils::Fs::toNativePath(torrentFullpath)), Log::CRITICAL); - } - } - } - - // Move .torrent file to another folder - if (!finishedTorrentExportDirectory().isEmpty()) - exportTorrentFile(torrent, TorrentExportFolder::Finished); - - if (!hasUnfinishedTorrents()) - emit allTorrentsFinished(); -} - -void Session::handleTorrentResumeDataReady(TorrentHandle *const torrent, const libtorrent::entry &data) -{ - --m_numResumeData; - - // Separated thread is used for the blocking IO which results in slow processing of many torrents. - // Encoding data in parallel while doing IO saves time. Copying libtorrent::entry objects around - // isn't cheap too. - - QByteArray out; - libt::bencode(std::back_inserter(out), data); - - QMetaObject::invokeMethod(m_resumeDataSavingManager, "saveResumeData", - Q_ARG(QString, torrent->hash()), Q_ARG(QByteArray, out)); -} - -void Session::handleTorrentResumeDataFailed(TorrentHandle *const torrent) -{ - Q_UNUSED(torrent) - --m_numResumeData; -} - -void Session::handleTorrentTrackerReply(TorrentHandle *const torrent, const QString &trackerUrl) -{ - emit trackerSuccess(torrent, trackerUrl); -} - -void Session::handleTorrentTrackerError(TorrentHandle *const torrent, const QString &trackerUrl) -{ - emit trackerError(torrent, trackerUrl); -} - -void Session::handleTorrentTrackerAuthenticationRequired(TorrentHandle *const torrent, const QString &trackerUrl) -{ - Q_UNUSED(trackerUrl); - emit trackerAuthenticationRequired(torrent); -} - -void Session::handleTorrentTrackerWarning(TorrentHandle *const torrent, const QString &trackerUrl) -{ - emit trackerWarning(torrent, trackerUrl); -} - -bool Session::hasPerTorrentRatioLimit() const -{ - foreach (TorrentHandle *const torrent, m_torrents) - if (torrent->ratioLimit() >= 0) return true; - - return false; -} - -bool Session::hasPerTorrentSeedingTimeLimit() const -{ - foreach (TorrentHandle *const torrent, m_torrents) - if (torrent->seedingTimeLimit() >= 0) return true; - - return false; -} - -void Session::initResumeFolder() -{ - m_resumeFolderPath = Utils::Fs::expandPathAbs(specialFolderLocation(SpecialFolder::Data) + RESUME_FOLDER); - QDir resumeFolderDir(m_resumeFolderPath); - if (resumeFolderDir.exists() || resumeFolderDir.mkpath(resumeFolderDir.absolutePath())) { - m_resumeFolderLock.setFileName(resumeFolderDir.absoluteFilePath("session.lock")); - if (!m_resumeFolderLock.open(QFile::WriteOnly)) { - throw std::runtime_error("Cannot write to torrent resume folder."); - } - } - else { - throw std::runtime_error("Cannot create torrent resume folder."); - } -} - -void Session::configureDeferred() -{ - if (!m_deferredConfigureScheduled) { - QMetaObject::invokeMethod(this, "configure", Qt::QueuedConnection); - m_deferredConfigureScheduled = true; - } -} - -// Enable IP Filtering -// this method creates ban list from scratch combining user ban list and 3rd party ban list file -void Session::enableIPFilter() -{ - qDebug("Enabling IPFilter"); - // 1. Parse the IP filter - // 2. In the slot add the manually banned IPs to the provided libtorrent::ip_filter - // 3. Set the ip_filter in one go so there isn't a time window where there isn't an ip_filter - // set between clearing the old one and setting the new one. - if (!m_filterParser) { - m_filterParser = new FilterParserThread(this); - connect(m_filterParser.data(), SIGNAL(IPFilterParsed(int)), SLOT(handleIPFilterParsed(int))); - connect(m_filterParser.data(), SIGNAL(IPFilterError()), SLOT(handleIPFilterError())); - } - m_filterParser->processFilterFile(IPFilterFile()); -} - -// Disable IP Filtering -void Session::disableIPFilter() -{ - qDebug("Disabling IPFilter"); - if (m_filterParser) { - disconnect(m_filterParser.data(), 0, this, 0); - delete m_filterParser; - } - - // Add the banned IPs after the IPFilter disabling - // which creates an empty filter and overrides all previously - // applied bans. - libt::ip_filter filter; - processBannedIPs(filter); - m_nativeSession->set_ip_filter(filter); -} - -void Session::recursiveTorrentDownload(const InfoHash &hash) -{ - TorrentHandle *const torrent = m_torrents.value(hash); - if (!torrent) return; - - for (int i = 0; i < torrent->filesCount(); ++i) { - const QString torrentRelpath = torrent->filePath(i); - if (torrentRelpath.endsWith(".torrent")) { - Logger::instance()->addMessage( - tr("Recursive download of file '%1' embedded in torrent '%2'" - , "Recursive download of 'test.torrent' embedded in torrent 'test2'") - .arg(Utils::Fs::toNativePath(torrentRelpath)).arg(torrent->name())); - const QString torrentFullpath = torrent->savePath() + "/" + torrentRelpath; - - AddTorrentParams params; - // Passing the save path along to the sub torrent file - params.savePath = torrent->savePath(); - addTorrent(TorrentInfo::loadFromFile(torrentFullpath), params); - } - } -} - -const SessionStatus &Session::status() const -{ - return m_status; -} - -const CacheStatus &Session::cacheStatus() const -{ - return m_cacheStatus; -} - -// Will resume torrents in backup directory -void Session::startUpTorrents() -{ - qDebug("Resuming torrents..."); - - const QDir resumeDataDir(m_resumeFolderPath); - QStringList fastresumes = resumeDataDir.entryList( - QStringList(QLatin1String("*.fastresume")), QDir::Files, QDir::Unsorted); - - Logger *const logger = Logger::instance(); - - typedef struct - { - QString hash; - MagnetUri magnetUri; - AddTorrentData addTorrentData; - QByteArray data; - } TorrentResumeData; - - int resumedTorrentsCount = 0; - const auto startupTorrent = [this, logger, &resumeDataDir, &resumedTorrentsCount](const TorrentResumeData ¶ms) - { - QString filePath = resumeDataDir.filePath(QString("%1.torrent").arg(params.hash)); - qDebug() << "Starting up torrent" << params.hash << "..."; - if (!addTorrent_impl(params.addTorrentData, params.magnetUri, TorrentInfo::loadFromFile(filePath), params.data)) - logger->addMessage(tr("Unable to resume torrent '%1'.", "e.g: Unable to resume torrent 'hash'.") - .arg(params.hash), Log::CRITICAL); - - // process add torrent messages before message queue overflow - if (resumedTorrentsCount % 100 == 0) readAlerts(); - - ++resumedTorrentsCount; - }; - - qDebug("Starting up torrents"); - qDebug("Queue size: %d", fastresumes.size()); - // Resume downloads - QMap queuedResumeData; - int nextQueuePosition = 1; - int numOfRemappedFiles = 0; - QRegExp rx(QLatin1String("^([A-Fa-f0-9]{40})\\.fastresume$")); - foreach (const QString &fastresumeName, fastresumes) { - if (rx.indexIn(fastresumeName) == -1) continue; - - QString hash = rx.cap(1); - QString fastresumePath = resumeDataDir.absoluteFilePath(fastresumeName); - QByteArray data; - AddTorrentData resumeData; - MagnetUri magnetUri; - int queuePosition; - if (readFile(fastresumePath, data) && loadTorrentResumeData(data, resumeData, queuePosition, magnetUri)) { - if (queuePosition <= nextQueuePosition) { - startupTorrent({ hash, magnetUri, resumeData, data }); - - if (queuePosition == nextQueuePosition) { - ++nextQueuePosition; - while (queuedResumeData.contains(nextQueuePosition)) { - startupTorrent(queuedResumeData.take(nextQueuePosition)); - ++nextQueuePosition; - } - } - } - else { - int q = queuePosition; - for(; queuedResumeData.contains(q); ++q) { - } - if (q != queuePosition) { - ++numOfRemappedFiles; - } - queuedResumeData[q] = { hash, magnetUri, resumeData, data }; - } - } - } - - if (numOfRemappedFiles > 0) { - logger->addMessage( - QString(tr("Queue positions were corrected in %1 resume files")).arg(numOfRemappedFiles), - Log::CRITICAL); - } - - // starting up downloading torrents (queue position > 0) - foreach (const TorrentResumeData &torrentResumeData, queuedResumeData) - startupTorrent(torrentResumeData); -} - -quint64 Session::getAlltimeDL() const -{ - return m_statistics->getAlltimeDL(); -} - -quint64 Session::getAlltimeUL() const -{ - return m_statistics->getAlltimeUL(); -} - -void Session::refresh() -{ - m_nativeSession->post_torrent_updates(); -#if LIBTORRENT_VERSION_NUM >= 10100 - m_nativeSession->post_session_stats(); -#endif -} - -void Session::handleIPFilterParsed(int ruleCount) -{ - if (m_filterParser) { - libt::ip_filter filter = m_filterParser->IPfilter(); - processBannedIPs(filter); - m_nativeSession->set_ip_filter(filter); - } - Logger::instance()->addMessage(tr("Successfully parsed the provided IP filter: %1 rules were applied.", "%1 is a number").arg(ruleCount)); - emit IPFilterParsed(false, ruleCount); -} - -void Session::handleIPFilterError() -{ - libt::ip_filter filter; - processBannedIPs(filter); - m_nativeSession->set_ip_filter(filter); - - Logger::instance()->addMessage(tr("Error: Failed to parse the provided IP filter."), Log::CRITICAL); - emit IPFilterParsed(true, 0); -} - -#if LIBTORRENT_VERSION_NUM < 10100 -void Session::dispatchAlerts(libt::alert *alertPtr) -{ - QMutexLocker lock(&m_alertsMutex); - - bool wasEmpty = m_alerts.empty(); - - m_alerts.push_back(alertPtr); - - if (wasEmpty) { - m_alertsWaitCondition.wakeAll(); - QMetaObject::invokeMethod(this, "readAlerts", Qt::QueuedConnection); - } -} -#endif - -void Session::getPendingAlerts(std::vector &out, ulong time) -{ - Q_ASSERT(out.empty()); - -#if LIBTORRENT_VERSION_NUM < 10100 - QMutexLocker lock(&m_alertsMutex); - - if (m_alerts.empty()) - m_alertsWaitCondition.wait(&m_alertsMutex, time); - - m_alerts.swap(out); -#else - if (time > 0) - m_nativeSession->wait_for_alert(libt::milliseconds(time)); - m_nativeSession->pop_alerts(&out); -#endif -} - -bool Session::isCreateTorrentSubfolder() const -{ - return m_isCreateTorrentSubfolder; -} - -void Session::setCreateTorrentSubfolder(bool value) -{ - m_isCreateTorrentSubfolder = value; -} - -// Read alerts sent by the BitTorrent session -void Session::readAlerts() -{ - std::vector alerts; - getPendingAlerts(alerts); - - for (const auto a: alerts) { - handleAlert(a); -#if LIBTORRENT_VERSION_NUM < 10100 - delete a; -#endif - } -} - -void Session::handleAlert(libt::alert *a) -{ - try { - switch (a->type()) { - case libt::stats_alert::alert_type: - case libt::file_renamed_alert::alert_type: - case libt::file_completed_alert::alert_type: - case libt::torrent_finished_alert::alert_type: - case libt::save_resume_data_alert::alert_type: - case libt::save_resume_data_failed_alert::alert_type: - case libt::storage_moved_alert::alert_type: - case libt::storage_moved_failed_alert::alert_type: - case libt::torrent_paused_alert::alert_type: - case libt::tracker_error_alert::alert_type: - case libt::tracker_reply_alert::alert_type: - case libt::tracker_warning_alert::alert_type: - case libt::fastresume_rejected_alert::alert_type: - case libt::torrent_checked_alert::alert_type: - dispatchTorrentAlert(a); - break; - case libt::metadata_received_alert::alert_type: - handleMetadataReceivedAlert(static_cast(a)); - dispatchTorrentAlert(a); - break; - case libt::state_update_alert::alert_type: - handleStateUpdateAlert(static_cast(a)); - break; -#if LIBTORRENT_VERSION_NUM >= 10100 - case libt::session_stats_alert::alert_type: - handleSessionStatsAlert(static_cast(a)); - break; -#endif - case libt::file_error_alert::alert_type: - handleFileErrorAlert(static_cast(a)); - break; - case libt::add_torrent_alert::alert_type: - handleAddTorrentAlert(static_cast(a)); - break; - case libt::torrent_removed_alert::alert_type: - handleTorrentRemovedAlert(static_cast(a)); - break; - case libt::torrent_deleted_alert::alert_type: - handleTorrentDeletedAlert(static_cast(a)); - break; - case libt::torrent_delete_failed_alert::alert_type: - handleTorrentDeleteFailedAlert(static_cast(a)); - break; - case libt::portmap_error_alert::alert_type: - handlePortmapWarningAlert(static_cast(a)); - break; - case libt::portmap_alert::alert_type: - handlePortmapAlert(static_cast(a)); - break; - case libt::peer_blocked_alert::alert_type: - handlePeerBlockedAlert(static_cast(a)); - break; - case libt::peer_ban_alert::alert_type: - handlePeerBanAlert(static_cast(a)); - break; - case libt::url_seed_alert::alert_type: - handleUrlSeedAlert(static_cast(a)); - break; - case libt::listen_succeeded_alert::alert_type: - handleListenSucceededAlert(static_cast(a)); - break; - case libt::listen_failed_alert::alert_type: - handleListenFailedAlert(static_cast(a)); - break; - case libt::external_ip_alert::alert_type: - handleExternalIPAlert(static_cast(a)); - break; - } - } - catch (std::exception &exc) { - qWarning() << "Caught exception in " << Q_FUNC_INFO << ": " << QString::fromStdString(exc.what()); - } -} - -void Session::dispatchTorrentAlert(libt::alert *a) -{ - TorrentHandle *const torrent = m_torrents.value(static_cast(a)->handle.info_hash()); - if (torrent) - torrent->handleAlert(a); -} - -void Session::createTorrentHandle(const libt::torrent_handle &nativeHandle) -{ - // Magnet added for preload its metadata - if (!m_addingTorrents.contains(nativeHandle.info_hash())) return; - - AddTorrentData data = m_addingTorrents.take(nativeHandle.info_hash()); - - TorrentHandle *const torrent = new TorrentHandle(this, nativeHandle, data); - m_torrents.insert(torrent->hash(), torrent); - - Logger *const logger = Logger::instance(); - - bool fromMagnetUri = !torrent->hasMetadata(); - - if (data.resumed) { - if (fromMagnetUri && !data.addPaused) - torrent->resume(data.addForced); - - logger->addMessage(tr("'%1' resumed. (fast resume)", "'torrent name' was resumed. (fast resume)") - .arg(torrent->name())); - } - else { - qDebug("This is a NEW torrent (first time)..."); - - // The following is useless for newly added magnet - if (!fromMagnetUri) { - // Backup torrent file - const QDir resumeDataDir(m_resumeFolderPath); - const QString newFile = resumeDataDir.absoluteFilePath(QString("%1.torrent").arg(torrent->hash())); - if (torrent->saveTorrentFile(newFile)) { - // Copy the torrent file to the export folder - if (!torrentExportDirectory().isEmpty()) - exportTorrentFile(torrent); - } - else { - logger->addMessage(tr("Couldn't save '%1.torrent'").arg(torrent->hash()), Log::CRITICAL); - } - } - - if (isAddTrackersEnabled() && !torrent->isPrivate()) - torrent->addTrackers(m_additionalTrackerList); - - // Start torrent because it was added in paused state - if (!data.addPaused) - torrent->resume(); - logger->addMessage(tr("'%1' added to download list.", "'torrent name' was added to download list.") - .arg(torrent->name())); - - // In case of crash before the scheduled generation - // of the fastresumes. - saveTorrentResumeData(torrent); - } - - if (((torrent->ratioLimit() >= 0) || (torrent->seedingTimeLimit() >= 0)) - && !m_seedingLimitTimer->isActive()) - m_seedingLimitTimer->start(); - - // Send torrent addition signal - emit torrentAdded(torrent); - // Send new torrent signal - if (!data.resumed) - emit torrentNew(torrent); -} - -void Session::handleAddTorrentAlert(libt::add_torrent_alert *p) -{ - if (p->error) { - qDebug("/!\\ Error: Failed to add torrent!"); - QString msg = QString::fromStdString(p->message()); - Logger::instance()->addMessage(tr("Couldn't add torrent. Reason: %1").arg(msg), Log::WARNING); - emit addTorrentFailed(msg); - } - else { - createTorrentHandle(p->handle); - } -} - -void Session::handleTorrentRemovedAlert(libt::torrent_removed_alert *p) -{ - if (m_loadedMetadata.contains(p->info_hash)) - emit metadataLoaded(m_loadedMetadata.take(p->info_hash)); -} - -void Session::handleTorrentDeletedAlert(libt::torrent_deleted_alert *p) -{ - Utils::Fs::smartRemoveEmptyFolderTree(m_savePathsToRemove.take(p->info_hash)); -} - -void Session::handleTorrentDeleteFailedAlert(libt::torrent_delete_failed_alert *p) -{ - // libtorrent won't delete the directory if it contains files not listed in the torrent, - // so we remove the directory ourselves - Utils::Fs::smartRemoveEmptyFolderTree(m_savePathsToRemove.take(p->info_hash)); -} - -void Session::handleMetadataReceivedAlert(libt::metadata_received_alert *p) -{ - InfoHash hash = p->handle.info_hash(); - - if (m_loadedMetadata.contains(hash)) { - --m_extraLimit; - adjustLimits(); - m_loadedMetadata[hash] = TorrentInfo(p->handle.torrent_file()); - m_nativeSession->remove_torrent(p->handle, libt::session::delete_files); - } -} - -void Session::handleFileErrorAlert(libt::file_error_alert *p) -{ - qDebug() << Q_FUNC_INFO; - // NOTE: Check this function! - TorrentHandle *const torrent = m_torrents.value(p->handle.info_hash()); - if (torrent) { - QString msg = QString::fromStdString(p->message()); - Logger::instance()->addMessage(tr("An I/O error occurred, '%1' paused. %2") - .arg(torrent->name()).arg(msg)); - emit fullDiskError(torrent, msg); - } -} - -void Session::handlePortmapWarningAlert(libt::portmap_error_alert *p) -{ - Logger::instance()->addMessage(tr("UPnP/NAT-PMP: Port mapping failure, message: %1").arg(QString::fromStdString(p->message())), Log::CRITICAL); -} - -void Session::handlePortmapAlert(libt::portmap_alert *p) -{ - qDebug("UPnP Success, msg: %s", p->message().c_str()); - Logger::instance()->addMessage(tr("UPnP/NAT-PMP: Port mapping successful, message: %1").arg(QString::fromStdString(p->message())), Log::INFO); -} - -void Session::handlePeerBlockedAlert(libt::peer_blocked_alert *p) -{ - boost::system::error_code ec; - std::string ip = p->ip.to_string(ec); - QString reason; - switch (p->reason) { - case libt::peer_blocked_alert::ip_filter: - reason = tr("due to IP filter.", "this peer was blocked due to ip filter."); - break; - case libt::peer_blocked_alert::port_filter: - reason = tr("due to port filter.", "this peer was blocked due to port filter."); - break; - case libt::peer_blocked_alert::i2p_mixed: - reason = tr("due to i2p mixed mode restrictions.", "this peer was blocked due to i2p mixed mode restrictions."); - break; - case libt::peer_blocked_alert::privileged_ports: - reason = tr("because it has a low port.", "this peer was blocked because it has a low port."); - break; - case libt::peer_blocked_alert::utp_disabled: - reason = trUtf8("because %1 is disabled.", "this peer was blocked because uTP is disabled.").arg(QString::fromUtf8(C_UTP)); // don't translate μTP - break; - case libt::peer_blocked_alert::tcp_disabled: - reason = tr("because %1 is disabled.", "this peer was blocked because TCP is disabled.").arg("TCP"); // don't translate TCP - break; - } - - if (!ec) - Logger::instance()->addPeer(QString::fromLatin1(ip.c_str()), true, reason); -} - -void Session::handlePeerBanAlert(libt::peer_ban_alert *p) -{ - boost::system::error_code ec; - std::string ip = p->ip.address().to_string(ec); - if (!ec) - Logger::instance()->addPeer(QString::fromLatin1(ip.c_str()), false); -} - -void Session::handleUrlSeedAlert(libt::url_seed_alert *p) -{ - Logger::instance()->addMessage(tr("URL seed lookup failed for URL: '%1', message: %2") -#if LIBTORRENT_VERSION_NUM >= 10100 - .arg(QString::fromStdString(p->server_url())) -#else - .arg(QString::fromStdString(p->url)) -#endif - .arg(QString::fromStdString(p->message())), Log::CRITICAL); -} - -void Session::handleListenSucceededAlert(libt::listen_succeeded_alert *p) -{ - boost::system::error_code ec; - QString proto = "TCP"; - if (p->sock_type == libt::listen_succeeded_alert::udp) - proto = "UDP"; - else if (p->sock_type == libt::listen_succeeded_alert::tcp) - proto = "TCP"; - else if (p->sock_type == libt::listen_succeeded_alert::tcp_ssl) - proto = "TCP_SSL"; - qDebug() << "Successfully listening on " << proto << p->endpoint.address().to_string(ec).c_str() << "/" << p->endpoint.port(); - Logger::instance()->addMessage(tr("qBittorrent is successfully listening on interface %1 port: %2/%3", "e.g: qBittorrent is successfully listening on interface 192.168.0.1 port: TCP/6881").arg(p->endpoint.address().to_string(ec).c_str()).arg(proto).arg(QString::number(p->endpoint.port())), Log::INFO); - - // Force reannounce on all torrents because some trackers blacklist some ports - std::vector torrents = m_nativeSession->get_torrents(); - std::vector::iterator it = torrents.begin(); - std::vector::iterator itend = torrents.end(); - for ( ; it != itend; ++it) - it->force_reannounce(); -} - -void Session::handleListenFailedAlert(libt::listen_failed_alert *p) -{ - boost::system::error_code ec; - QString proto = "TCP"; - if (p->sock_type == libt::listen_failed_alert::udp) - proto = "UDP"; - else if (p->sock_type == libt::listen_failed_alert::tcp) - proto = "TCP"; - else if (p->sock_type == libt::listen_failed_alert::tcp_ssl) - proto = "TCP_SSL"; - else if (p->sock_type == libt::listen_failed_alert::i2p) - proto = "I2P"; - else if (p->sock_type == libt::listen_failed_alert::socks5) - proto = "SOCKS5"; - qDebug() << "Failed listening on " << proto << p->endpoint.address().to_string(ec).c_str() << "/" << p->endpoint.port(); - Logger::instance()->addMessage( - tr("qBittorrent failed listening on interface %1 port: %2/%3. Reason: %4.", - "e.g: qBittorrent failed listening on interface 192.168.0.1 port: TCP/6881. Reason: already in use.") - .arg(p->endpoint.address().to_string(ec).c_str()).arg(proto).arg(QString::number(p->endpoint.port())) - .arg(QString::fromLocal8Bit(p->error.message().c_str())), Log::CRITICAL); -} - -void Session::handleExternalIPAlert(libt::external_ip_alert *p) -{ - boost::system::error_code ec; - Logger::instance()->addMessage(tr("External IP: %1", "e.g. External IP: 192.168.0.1").arg(p->external_address.to_string(ec).c_str()), Log::INFO); -} - -#if LIBTORRENT_VERSION_NUM >= 10100 -void Session::handleSessionStatsAlert(libt::session_stats_alert *p) -{ - qreal interval = m_statsUpdateTimer.restart() / 1000.; - - m_status.hasIncomingConnections = static_cast(p->values[m_metricIndices.net.hasIncomingConnections]); - - const auto ipOverheadDownload = p->values[m_metricIndices.net.recvIPOverheadBytes]; - const auto ipOverheadUpload = p->values[m_metricIndices.net.sentIPOverheadBytes]; - const auto totalDownload = p->values[m_metricIndices.net.recvBytes] + ipOverheadDownload; - const auto totalUpload = p->values[m_metricIndices.net.sentBytes] + ipOverheadUpload; - const auto totalPayloadDownload = p->values[m_metricIndices.net.recvPayloadBytes]; - const auto totalPayloadUpload = p->values[m_metricIndices.net.sentPayloadBytes]; - const auto trackerDownload = p->values[m_metricIndices.net.recvTrackerBytes]; - const auto trackerUpload = p->values[m_metricIndices.net.sentTrackerBytes]; - const auto dhtDownload = p->values[m_metricIndices.dht.dhtBytesIn]; - const auto dhtUpload = p->values[m_metricIndices.dht.dhtBytesOut]; - - auto calcRate = [interval](quint64 previous, quint64 current) - { - Q_ASSERT(current >= previous); - return static_cast((current - previous) / interval); - }; - - m_status.payloadDownloadRate = calcRate(m_status.totalPayloadDownload, totalPayloadDownload); - m_status.payloadUploadRate = calcRate(m_status.totalPayloadUpload, totalPayloadUpload); - m_status.downloadRate = calcRate(m_status.totalDownload, totalDownload); - m_status.uploadRate = calcRate(m_status.totalUpload, totalUpload); - m_status.ipOverheadDownloadRate = calcRate(m_status.ipOverheadDownload, ipOverheadDownload); - m_status.ipOverheadUploadRate = calcRate(m_status.ipOverheadUpload, ipOverheadUpload); - m_status.dhtDownloadRate = calcRate(m_status.dhtDownload, dhtDownload); - m_status.dhtUploadRate = calcRate(m_status.dhtUpload, dhtUpload); - m_status.trackerDownloadRate = calcRate(m_status.trackerDownload, trackerDownload); - m_status.trackerUploadRate = calcRate(m_status.trackerUpload, trackerUpload); - - m_status.totalDownload = totalDownload; - m_status.totalUpload = totalUpload; - m_status.totalPayloadDownload = totalPayloadDownload; - m_status.totalPayloadUpload = totalPayloadUpload; - m_status.ipOverheadDownload = ipOverheadDownload; - m_status.ipOverheadUpload = ipOverheadUpload; - m_status.trackerDownload = trackerDownload; - m_status.trackerUpload = trackerUpload; - m_status.dhtDownload = dhtDownload; - m_status.dhtUpload = dhtUpload; - m_status.totalWasted = p->values[m_metricIndices.net.recvRedundantBytes] - + p->values[m_metricIndices.net.recvFailedBytes]; - m_status.dhtNodes = p->values[m_metricIndices.dht.dhtNodes]; - m_status.diskReadQueue = p->values[m_metricIndices.peer.numPeersUpDisk]; - m_status.diskWriteQueue = p->values[m_metricIndices.peer.numPeersDownDisk]; - m_status.peersCount = p->values[m_metricIndices.peer.numPeersConnected]; - - const auto numBlocksRead = p->values[m_metricIndices.disk.numBlocksRead]; - m_cacheStatus.totalUsedBuffers = p->values[m_metricIndices.disk.diskBlocksInUse]; - m_cacheStatus.readRatio = numBlocksRead > 0 - ? static_cast(p->values[m_metricIndices.disk.numBlocksCacheHits]) / numBlocksRead - : -1; - m_cacheStatus.jobQueueLength = p->values[m_metricIndices.disk.queuedDiskJobs]; - m_cacheStatus.averageJobTime = p->values[m_metricIndices.disk.diskJobTime]; - - emit statsUpdated(); -} -#else -void Session::updateStats() -{ - libt::session_status ss = m_nativeSession->status(); - m_status.hasIncomingConnections = ss.has_incoming_connections; - m_status.payloadDownloadRate = ss.payload_download_rate; - m_status.payloadUploadRate = ss.payload_upload_rate; - m_status.downloadRate = ss.download_rate; - m_status.uploadRate = ss.upload_rate; - m_status.ipOverheadDownloadRate = ss.ip_overhead_download_rate; - m_status.ipOverheadUploadRate = ss.ip_overhead_upload_rate; - m_status.dhtDownloadRate = ss.dht_download_rate; - m_status.dhtUploadRate = ss.dht_upload_rate; - m_status.trackerDownloadRate = ss.tracker_download_rate; - m_status.trackerUploadRate = ss.tracker_upload_rate; - - m_status.totalDownload = ss.total_download; - m_status.totalUpload = ss.total_upload; - m_status.totalPayloadDownload = ss.total_payload_download; - m_status.totalPayloadUpload = ss.total_payload_upload; - m_status.totalWasted = ss.total_redundant_bytes + ss.total_failed_bytes; - m_status.diskReadQueue = ss.disk_read_queue; - m_status.diskWriteQueue = ss.disk_write_queue; - m_status.dhtNodes = ss.dht_nodes; - m_status.peersCount = ss.num_peers; - - libt::cache_status cs = m_nativeSession->get_cache_status(); - m_cacheStatus.totalUsedBuffers = cs.total_used_buffers; - m_cacheStatus.readRatio = cs.blocks_read > 0 - ? static_cast(cs.blocks_read_hit) / cs.blocks_read - : -1; - m_cacheStatus.jobQueueLength = cs.job_queue_length; - m_cacheStatus.averageJobTime = cs.average_job_time; - m_cacheStatus.queuedBytes = cs.queued_bytes; // it seems that it is constantly equal to zero - - emit statsUpdated(); -} -#endif - -void Session::handleStateUpdateAlert(libt::state_update_alert *p) -{ -#if LIBTORRENT_VERSION_NUM < 10100 - updateStats(); -#endif - - foreach (const libt::torrent_status &status, p->status) { - TorrentHandle *const torrent = m_torrents.value(status.info_hash); - if (torrent) - torrent->handleStateUpdate(status); - } - - m_torrentStatusReport = TorrentStatusReport(); - foreach (TorrentHandle *const torrent, m_torrents) { - if (torrent->isDownloading()) - ++m_torrentStatusReport.nbDownloading; - if (torrent->isUploading()) - ++m_torrentStatusReport.nbSeeding; - if (torrent->isCompleted()) - ++m_torrentStatusReport.nbCompleted; - if (torrent->isPaused()) - ++m_torrentStatusReport.nbPaused; - if (torrent->isResumed()) - ++m_torrentStatusReport.nbResumed; - if (torrent->isActive()) - ++m_torrentStatusReport.nbActive; - if (torrent->isInactive()) - ++m_torrentStatusReport.nbInactive; - if (torrent->isErrored()) - ++m_torrentStatusReport.nbErrored; - } - - emit torrentsUpdated(); -} - -namespace -{ - bool readFile(const QString &path, QByteArray &buf) - { - QFile file(path); - if (!file.open(QIODevice::ReadOnly)) { - qDebug("Cannot read file %s: %s", qPrintable(path), qPrintable(file.errorString())); - return false; - } - - buf = file.readAll(); - return true; - } - - bool loadTorrentResumeData(const QByteArray &data, AddTorrentData &torrentData, int &prio, MagnetUri &magnetUri) - { - torrentData = AddTorrentData(); - torrentData.resumed = true; - torrentData.skipChecking = false; - - libt::error_code ec; -#if LIBTORRENT_VERSION_NUM < 10100 - libt::lazy_entry fast; - libt::lazy_bdecode(data.constData(), data.constData() + data.size(), fast, ec); - if (ec || (fast.type() != libt::lazy_entry::dict_t)) return false; -#else - libt::bdecode_node fast; - libt::bdecode(data.constData(), data.constData() + data.size(), fast, ec); - if (ec || (fast.type() != libt::bdecode_node::dict_t)) return false; -#endif - - torrentData.savePath = Profile::instance().fromPortablePath( - Utils::Fs::fromNativePath(QString::fromStdString(fast.dict_find_string_value("qBt-savePath")))); - torrentData.ratioLimit = QString::fromStdString(fast.dict_find_string_value("qBt-ratioLimit")).toDouble(); - torrentData.seedingTimeLimit = fast.dict_find_int_value("qBt-seedingTimeLimit", TorrentHandle::USE_GLOBAL_SEEDING_TIME); - // ************************************************************************************** - // Workaround to convert legacy label to category - // TODO: Should be removed in future - torrentData.category = QString::fromStdString(fast.dict_find_string_value("qBt-label")); - if (torrentData.category.isEmpty()) - // ************************************************************************************** - torrentData.category = QString::fromStdString(fast.dict_find_string_value("qBt-category")); - // auto because the return type depends on the #if above. - const auto tagsEntry = fast.dict_find_list("qBt-tags"); - if (isList(tagsEntry)) - torrentData.tags = entryListToSet(tagsEntry); - torrentData.name = QString::fromStdString(fast.dict_find_string_value("qBt-name")); - torrentData.hasSeedStatus = fast.dict_find_int_value("qBt-seedStatus"); - torrentData.disableTempPath = fast.dict_find_int_value("qBt-tempPathDisabled"); - torrentData.hasRootFolder = fast.dict_find_int_value("qBt-hasRootFolder"); - - magnetUri = MagnetUri(QString::fromStdString(fast.dict_find_string_value("qBt-magnetUri"))); - torrentData.addPaused = fast.dict_find_int_value("qBt-paused"); - torrentData.addForced = fast.dict_find_int_value("qBt-forced"); - torrentData.firstLastPiecePriority = fast.dict_find_int_value("qBt-firstLastPiecePriority"); - torrentData.sequential = fast.dict_find_int_value("qBt-sequential"); - - prio = fast.dict_find_int_value("qBt-queuePosition"); - - return true; - } - - void torrentQueuePositionUp(const libt::torrent_handle &handle) - { - try { - handle.queue_position_up(); - } - catch (std::exception &exc) { - qDebug() << Q_FUNC_INFO << " fails: " << exc.what(); - } - } - - void torrentQueuePositionDown(const libt::torrent_handle &handle) - { - try { - handle.queue_position_down(); - } - catch (std::exception &exc) { - qDebug() << Q_FUNC_INFO << " fails: " << exc.what(); - } - } - - void torrentQueuePositionTop(const libt::torrent_handle &handle) - { - try { - handle.queue_position_top(); - } - catch (std::exception &exc) { - qDebug() << Q_FUNC_INFO << " fails: " << exc.what(); - } - } - - void torrentQueuePositionBottom(const libt::torrent_handle &handle) - { - try { - handle.queue_position_bottom(); - } - catch (std::exception &exc) { - qDebug() << Q_FUNC_INFO << " fails: " << exc.what(); - } - } -} diff --git a/src/base/bittorrent/session.h b/src/base/bittorrent/session.h deleted file mode 100644 index 01422b620..000000000 --- a/src/base/bittorrent/session.h +++ /dev/null @@ -1,687 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2015 Vladimir Golovnev - * Copyright (C) 2006 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. - */ - -#ifndef BITTORRENT_SESSION_H -#define BITTORRENT_SESSION_H - -#include -#include - -#if LIBTORRENT_VERSION_NUM >= 10100 -#include -#endif -#include -#include -#include -#if LIBTORRENT_VERSION_NUM < 10100 -#include -#endif -#include -#include -#include -#include -#include -#include - -#include "base/settingvalue.h" -#include "base/tristatebool.h" -#include "base/types.h" -#include "addtorrentparams.h" -#include "cachestatus.h" -#include "sessionstatus.h" -#include "torrentinfo.h" - -namespace libtorrent -{ - class session; - struct torrent_handle; - class entry; - struct ip_filter; -#if LIBTORRENT_VERSION_NUM < 10100 - struct session_settings; -#else - struct settings_pack; -#endif - - class alert; - struct torrent_alert; - struct state_update_alert; - struct stats_alert; - struct add_torrent_alert; - struct torrent_checked_alert; - struct torrent_finished_alert; - struct torrent_removed_alert; - struct torrent_deleted_alert; - struct torrent_delete_failed_alert; - struct torrent_paused_alert; - struct torrent_resumed_alert; - struct save_resume_data_alert; - struct save_resume_data_failed_alert; - struct file_renamed_alert; - struct storage_moved_alert; - struct storage_moved_failed_alert; - struct metadata_received_alert; - struct file_error_alert; - struct file_completed_alert; - struct tracker_error_alert; - struct tracker_reply_alert; - struct tracker_warning_alert; - struct portmap_error_alert; - struct portmap_alert; - struct peer_blocked_alert; - struct peer_ban_alert; - struct fastresume_rejected_alert; - struct url_seed_alert; - struct listen_succeeded_alert; - struct listen_failed_alert; - struct external_ip_alert; -#if LIBTORRENT_VERSION_NUM >= 10100 - struct session_stats_alert; -#endif -} - -class QThread; -class QTimer; -class QStringList; -class QString; -class QUrl; -template class QList; - -class FilterParserThread; -class BandwidthScheduler; -class Statistics; -class ResumeDataSavingManager; - -enum MaxRatioAction -{ - Pause, - Remove -}; - -enum TorrentExportFolder -{ - Regular, - Finished -}; - -namespace BitTorrent -{ - class InfoHash; - class TorrentHandle; - class Tracker; - class MagnetUri; - class TrackerEntry; - struct AddTorrentData; - - struct TorrentStatusReport - { - uint nbDownloading = 0; - uint nbSeeding = 0; - uint nbCompleted = 0; - uint nbActive = 0; - uint nbInactive = 0; - uint nbPaused = 0; - uint nbResumed = 0; - uint nbErrored = 0; - }; - -#if LIBTORRENT_VERSION_NUM >= 10100 - struct SessionMetricIndices - { - struct - { - int hasIncomingConnections = 0; - int sentPayloadBytes = 0; - int recvPayloadBytes = 0; - int sentBytes = 0; - int recvBytes = 0; - int sentIPOverheadBytes = 0; - int recvIPOverheadBytes = 0; - int sentTrackerBytes = 0; - int recvTrackerBytes = 0; - int recvRedundantBytes = 0; - int recvFailedBytes = 0; - } net; - - struct - { - int numPeersConnected = 0; - int numPeersUpDisk = 0; - int numPeersDownDisk = 0; - } peer; - - struct - { - int dhtBytesIn = 0; - int dhtBytesOut = 0; - int dhtNodes = 0; - } dht; - - struct - { - int diskBlocksInUse = 0; - int numBlocksRead = 0; - int numBlocksCacheHits = 0; - int queuedDiskJobs = 0; - int diskJobTime = 0; - } disk; - }; -#endif - - class Session : public QObject - { - Q_OBJECT - Q_DISABLE_COPY(Session) - - public: - static void initInstance(); - static void freeInstance(); - static Session *instance(); - - QString defaultSavePath() const; - void setDefaultSavePath(QString path); - QString tempPath() const; - void setTempPath(QString path); - bool isTempPathEnabled() const; - void setTempPathEnabled(bool enabled); - QString torrentTempPath(const TorrentInfo &torrentInfo) const; - - static bool isValidCategoryName(const QString &name); - // returns category itself and all top level categories - static QStringList expandCategory(const QString &category); - - QStringList categories() const; - QString categorySavePath(const QString &categoryName) const; - bool addCategory(const QString &name, const QString &savePath = ""); - bool editCategory(const QString &name, const QString &savePath); - bool removeCategory(const QString &name); - bool isSubcategoriesEnabled() const; - void setSubcategoriesEnabled(bool value); - - static bool isValidTag(const QString &tag); - QSet tags() const; - bool hasTag(const QString &tag) const; - bool addTag(const QString &tag); - bool removeTag(const QString &tag); - - // Torrent Management Mode subsystem (TMM) - // - // Each torrent can be either in Manual mode or in Automatic mode - // In Manual Mode various torrent properties are set explicitly(eg save path) - // In Automatic Mode various torrent properties are set implicitly(eg save path) - // based on the associated category. - // In Automatic Mode torrent save path can be changed in following cases: - // 1. Default save path changed - // 2. Torrent category save path changed - // 3. Torrent category changed - // (unless otherwise is specified) - bool isAutoTMMDisabledByDefault() const; - void setAutoTMMDisabledByDefault(bool value); - bool isDisableAutoTMMWhenCategoryChanged() const; - void setDisableAutoTMMWhenCategoryChanged(bool value); - bool isDisableAutoTMMWhenDefaultSavePathChanged() const; - void setDisableAutoTMMWhenDefaultSavePathChanged(bool value); - bool isDisableAutoTMMWhenCategorySavePathChanged() const; - void setDisableAutoTMMWhenCategorySavePathChanged(bool value); - - qreal globalMaxRatio() const; - void setGlobalMaxRatio(qreal ratio); - int globalMaxSeedingMinutes() const; - void setGlobalMaxSeedingMinutes(int minutes); - bool isDHTEnabled() const; - void setDHTEnabled(bool enabled); - bool isLSDEnabled() const; - void setLSDEnabled(bool enabled); - bool isPeXEnabled() const; - void setPeXEnabled(bool enabled); - bool isAddTorrentPaused() const; - void setAddTorrentPaused(bool value); - bool isCreateTorrentSubfolder() const; - void setCreateTorrentSubfolder(bool value); - bool isTrackerEnabled() const; - void setTrackerEnabled(bool enabled); - bool isAppendExtensionEnabled() const; - void setAppendExtensionEnabled(bool enabled); - uint refreshInterval() const; - void setRefreshInterval(uint value); - bool isPreallocationEnabled() const; - void setPreallocationEnabled(bool enabled); - QString torrentExportDirectory() const; - void setTorrentExportDirectory(QString path); - QString finishedTorrentExportDirectory() const; - void setFinishedTorrentExportDirectory(QString path); - - int globalDownloadSpeedLimit() const; - void setGlobalDownloadSpeedLimit(int limit); - int globalUploadSpeedLimit() const; - void setGlobalUploadSpeedLimit(int limit); - int altGlobalDownloadSpeedLimit() const; - void setAltGlobalDownloadSpeedLimit(int limit); - int altGlobalUploadSpeedLimit() const; - void setAltGlobalUploadSpeedLimit(int limit); - int downloadSpeedLimit() const; - void setDownloadSpeedLimit(int limit); - int uploadSpeedLimit() const; - void setUploadSpeedLimit(int limit); - bool isAltGlobalSpeedLimitEnabled() const; - void setAltGlobalSpeedLimitEnabled(bool enabled); - bool isBandwidthSchedulerEnabled() const; - void setBandwidthSchedulerEnabled(bool enabled); - - uint saveResumeDataInterval() const; - void setSaveResumeDataInterval(uint value); - int port() const; - void setPort(int port); - bool useRandomPort() const; - void setUseRandomPort(bool value); - QString networkInterface() const; - void setNetworkInterface(const QString &interface); - QString networkInterfaceName() const; - void setNetworkInterfaceName(const QString &name); - QString networkInterfaceAddress() const; - void setNetworkInterfaceAddress(const QString &address); - bool isIPv6Enabled() const; - void setIPv6Enabled(bool enabled); - int encryption() const; - void setEncryption(int state); - bool isForceProxyEnabled() const; - void setForceProxyEnabled(bool enabled); - bool isProxyPeerConnectionsEnabled() const; - void setProxyPeerConnectionsEnabled(bool enabled); - bool isAddTrackersEnabled() const; - void setAddTrackersEnabled(bool enabled); - QString additionalTrackers() const; - void setAdditionalTrackers(const QString &trackers); - bool isIPFilteringEnabled() const; - void setIPFilteringEnabled(bool enabled); - QString IPFilterFile() const; - void setIPFilterFile(QString path); - bool announceToAllTrackers() const; - void setAnnounceToAllTrackers(bool val); - uint diskCacheSize() const; - void setDiskCacheSize(uint size); - uint diskCacheTTL() const; - void setDiskCacheTTL(uint ttl); - bool useOSCache() const; - void setUseOSCache(bool use); - bool isAnonymousModeEnabled() const; - void setAnonymousModeEnabled(bool enabled); - bool isQueueingSystemEnabled() const; - void setQueueingSystemEnabled(bool enabled); - bool ignoreSlowTorrentsForQueueing() const; - void setIgnoreSlowTorrentsForQueueing(bool ignore); - uint outgoingPortsMin() const; - void setOutgoingPortsMin(uint min); - uint outgoingPortsMax() const; - void setOutgoingPortsMax(uint max); - bool ignoreLimitsOnLAN() const; - void setIgnoreLimitsOnLAN(bool ignore); - bool includeOverheadInLimits() const; - void setIncludeOverheadInLimits(bool include); - QString announceIP() const; - void setAnnounceIP(const QString &ip); - bool isSuperSeedingEnabled() const; - void setSuperSeedingEnabled(bool enabled); - int maxConnections() const; - void setMaxConnections(int max); - int maxHalfOpenConnections() const; - void setMaxHalfOpenConnections(int max); - int maxConnectionsPerTorrent() const; - void setMaxConnectionsPerTorrent(int max); - int maxUploads() const; - void setMaxUploads(int max); - int maxUploadsPerTorrent() const; - void setMaxUploadsPerTorrent(int max); - int maxActiveDownloads() const; - void setMaxActiveDownloads(int max); - int maxActiveUploads() const; - void setMaxActiveUploads(int max); - int maxActiveTorrents() const; - void setMaxActiveTorrents(int max); - bool isUTPEnabled() const; - void setUTPEnabled(bool enabled); - bool isUTPRateLimited() const; - void setUTPRateLimited(bool limited); - bool isTrackerFilteringEnabled() const; - void setTrackerFilteringEnabled(bool enabled); - QStringList bannedIPs() const; - void setBannedIPs(const QStringList &newList); - - void startUpTorrents(); - TorrentHandle *findTorrent(const InfoHash &hash) const; - QHash torrents() const; - TorrentStatusReport torrentStatusReport() const; - bool hasActiveTorrents() const; - bool hasUnfinishedTorrents() const; - const SessionStatus &status() const; - const CacheStatus &cacheStatus() const; - quint64 getAlltimeDL() const; - quint64 getAlltimeUL() const; - bool isListening() const; - - MaxRatioAction maxRatioAction() const; - void setMaxRatioAction(MaxRatioAction act); - - void banIP(const QString &ip); - - bool isKnownTorrent(const InfoHash &hash) const; - bool addTorrent(QString source, const AddTorrentParams ¶ms = AddTorrentParams()); - bool addTorrent(const TorrentInfo &torrentInfo, const AddTorrentParams ¶ms = AddTorrentParams()); - bool deleteTorrent(const QString &hash, bool deleteLocalFiles = false); - bool loadMetadata(const MagnetUri &magnetUri); - bool cancelLoadMetadata(const InfoHash &hash); - - void recursiveTorrentDownload(const InfoHash &hash); - void increaseTorrentsPriority(const QStringList &hashes); - void decreaseTorrentsPriority(const QStringList &hashes); - void topTorrentsPriority(const QStringList &hashes); - void bottomTorrentsPriority(const QStringList &hashes); - - // TorrentHandle interface - void handleTorrentShareLimitChanged(TorrentHandle *const torrent); - void handleTorrentSavePathChanged(TorrentHandle *const torrent); - void handleTorrentCategoryChanged(TorrentHandle *const torrent, const QString &oldCategory); - void handleTorrentTagAdded(TorrentHandle *const torrent, const QString &tag); - void handleTorrentTagRemoved(TorrentHandle *const torrent, const QString &tag); - void handleTorrentSavingModeChanged(TorrentHandle *const torrent); - void handleTorrentMetadataReceived(TorrentHandle *const torrent); - void handleTorrentPaused(TorrentHandle *const torrent); - void handleTorrentResumed(TorrentHandle *const torrent); - void handleTorrentChecked(TorrentHandle *const torrent); - void handleTorrentFinished(TorrentHandle *const torrent); - void handleTorrentTrackersAdded(TorrentHandle *const torrent, const QList &newTrackers); - void handleTorrentTrackersRemoved(TorrentHandle *const torrent, const QList &deletedTrackers); - void handleTorrentTrackersChanged(TorrentHandle *const torrent); - void handleTorrentUrlSeedsAdded(TorrentHandle *const torrent, const QList &newUrlSeeds); - void handleTorrentUrlSeedsRemoved(TorrentHandle *const torrent, const QList &urlSeeds); - void handleTorrentResumeDataReady(TorrentHandle *const torrent, const libtorrent::entry &data); - void handleTorrentResumeDataFailed(TorrentHandle *const torrent); - void handleTorrentTrackerReply(TorrentHandle *const torrent, const QString &trackerUrl); - void handleTorrentTrackerWarning(TorrentHandle *const torrent, const QString &trackerUrl); - void handleTorrentTrackerError(TorrentHandle *const torrent, const QString &trackerUrl); - void handleTorrentTrackerAuthenticationRequired(TorrentHandle *const torrent, const QString &trackerUrl); - - signals: - void statsUpdated(); - void torrentsUpdated(); - void addTorrentFailed(const QString &error); - void torrentAdded(BitTorrent::TorrentHandle *const torrent); - void torrentNew(BitTorrent::TorrentHandle *const torrent); - void torrentAboutToBeRemoved(BitTorrent::TorrentHandle *const torrent); - void torrentPaused(BitTorrent::TorrentHandle *const torrent); - void torrentResumed(BitTorrent::TorrentHandle *const torrent); - void torrentFinished(BitTorrent::TorrentHandle *const torrent); - void torrentFinishedChecking(BitTorrent::TorrentHandle *const torrent); - void torrentSavePathChanged(BitTorrent::TorrentHandle *const torrent); - void torrentCategoryChanged(BitTorrent::TorrentHandle *const torrent, const QString &oldCategory); - void torrentTagAdded(TorrentHandle *const torrent, const QString &tag); - void torrentTagRemoved(TorrentHandle *const torrent, const QString &tag); - void torrentSavingModeChanged(BitTorrent::TorrentHandle *const torrent); - void allTorrentsFinished(); - void metadataLoaded(const BitTorrent::TorrentInfo &info); - void torrentMetadataLoaded(BitTorrent::TorrentHandle *const torrent); - void fullDiskError(BitTorrent::TorrentHandle *const torrent, const QString &msg); - void trackerSuccess(BitTorrent::TorrentHandle *const torrent, const QString &tracker); - void trackerWarning(BitTorrent::TorrentHandle *const torrent, const QString &tracker); - void trackerError(BitTorrent::TorrentHandle *const torrent, const QString &tracker); - void trackerAuthenticationRequired(BitTorrent::TorrentHandle *const torrent); - void recursiveTorrentDownloadPossible(BitTorrent::TorrentHandle *const torrent); - void speedLimitModeChanged(bool alternative); - void IPFilterParsed(bool error, int ruleCount); - void trackersAdded(BitTorrent::TorrentHandle *const torrent, const QList &trackers); - void trackersRemoved(BitTorrent::TorrentHandle *const torrent, const QList &trackers); - void trackersChanged(BitTorrent::TorrentHandle *const torrent); - void trackerlessStateChanged(BitTorrent::TorrentHandle *const torrent, bool trackerless); - void downloadFromUrlFailed(const QString &url, const QString &reason); - void downloadFromUrlFinished(const QString &url); - void categoryAdded(const QString &categoryName); - void categoryRemoved(const QString &categoryName); - void subcategoriesSupportChanged(); - void tagAdded(const QString &tag); - void tagRemoved(const QString &tag); - - private slots: - void configureDeferred(); - void readAlerts(); - void refresh(); - void processShareLimits(); - void generateResumeData(bool final = false); - void handleIPFilterParsed(int ruleCount); - void handleIPFilterError(); - void handleDownloadFinished(const QString &url, const QString &filePath); - void handleDownloadFailed(const QString &url, const QString &reason); - void handleRedirectedToMagnet(const QString &url, const QString &magnetUri); - void switchToAlternativeMode(bool alternative); - - // Session reconfiguration triggers - void networkOnlineStateChanged(const bool online); - void networkConfigurationChange(const QNetworkConfiguration&); - - private: - explicit Session(QObject *parent = 0); - ~Session(); - - bool hasPerTorrentRatioLimit() const; - bool hasPerTorrentSeedingTimeLimit() const; - - void initResumeFolder(); - - // Session configuration - Q_INVOKABLE void configure(); -#if LIBTORRENT_VERSION_NUM < 10100 - void configure(libtorrent::session_settings &sessionSettings); - void adjustLimits(libtorrent::session_settings &sessionSettings); -#else - void configure(libtorrent::settings_pack &settingsPack); - void configurePeerClasses(); - void adjustLimits(libtorrent::settings_pack &settingsPack); - void initMetrics(); -#endif - void adjustLimits(); - void processBannedIPs(libtorrent::ip_filter &filter); - const QStringList getListeningIPs(); - void configureListeningInterface(); - void changeSpeedLimitMode_impl(bool alternative); - void enableTracker(bool enable); - void enableBandwidthScheduler(); - void populateAdditionalTrackers(); - void enableIPFilter(); - void disableIPFilter(); - - bool addTorrent_impl(AddTorrentData addData, const MagnetUri &magnetUri, - TorrentInfo torrentInfo = TorrentInfo(), - const QByteArray &fastresumeData = QByteArray()); - bool findIncompleteFiles(TorrentInfo &torrentInfo, QString &savePath) const; - - void updateSeedingLimitTimer(); - void exportTorrentFile(TorrentHandle *const torrent, TorrentExportFolder folder = TorrentExportFolder::Regular); - void saveTorrentResumeData(TorrentHandle *const torrent, bool finalSave = false); - - void handleAlert(libtorrent::alert *a); - void dispatchTorrentAlert(libtorrent::alert *a); - void handleAddTorrentAlert(libtorrent::add_torrent_alert *p); - void handleStateUpdateAlert(libtorrent::state_update_alert *p); - void handleMetadataReceivedAlert(libtorrent::metadata_received_alert *p); - void handleFileErrorAlert(libtorrent::file_error_alert *p); - void handleTorrentRemovedAlert(libtorrent::torrent_removed_alert *p); - void handleTorrentDeletedAlert(libtorrent::torrent_deleted_alert *p); - void handleTorrentDeleteFailedAlert(libtorrent::torrent_delete_failed_alert *p); - void handlePortmapWarningAlert(libtorrent::portmap_error_alert *p); - void handlePortmapAlert(libtorrent::portmap_alert *p); - void handlePeerBlockedAlert(libtorrent::peer_blocked_alert *p); - void handlePeerBanAlert(libtorrent::peer_ban_alert *p); - void handleUrlSeedAlert(libtorrent::url_seed_alert *p); - void handleListenSucceededAlert(libtorrent::listen_succeeded_alert *p); - void handleListenFailedAlert(libtorrent::listen_failed_alert *p); - void handleExternalIPAlert(libtorrent::external_ip_alert *p); -#if LIBTORRENT_VERSION_NUM >= 10100 - void handleSessionStatsAlert(libtorrent::session_stats_alert *p); -#endif - - void createTorrentHandle(const libtorrent::torrent_handle &nativeHandle); - - void saveResumeData(); - -#if LIBTORRENT_VERSION_NUM < 10100 - void dispatchAlerts(libtorrent::alert *alertPtr); - void updateStats(); -#endif - void getPendingAlerts(std::vector &out, ulong time = 0); - - // BitTorrent - libtorrent::session *m_nativeSession; - - bool m_deferredConfigureScheduled; - bool m_IPFilteringChanged; -#if LIBTORRENT_VERSION_NUM >= 10100 - bool m_listenInterfaceChanged; // optimization -#endif - CachedSettingValue m_isDHTEnabled; - CachedSettingValue m_isLSDEnabled; - CachedSettingValue m_isPeXEnabled; - CachedSettingValue m_isIPFilteringEnabled; - CachedSettingValue m_isTrackerFilteringEnabled; - CachedSettingValue m_IPFilterFile; - CachedSettingValue m_announceToAllTrackers; - CachedSettingValue m_diskCacheSize; - CachedSettingValue m_diskCacheTTL; - CachedSettingValue m_useOSCache; - CachedSettingValue m_isAnonymousModeEnabled; - CachedSettingValue m_isQueueingEnabled; - CachedSettingValue m_maxActiveDownloads; - CachedSettingValue m_maxActiveUploads; - CachedSettingValue m_maxActiveTorrents; - CachedSettingValue m_ignoreSlowTorrentsForQueueing; - CachedSettingValue m_outgoingPortsMin; - CachedSettingValue m_outgoingPortsMax; - CachedSettingValue m_ignoreLimitsOnLAN; - CachedSettingValue m_includeOverheadInLimits; - CachedSettingValue m_announceIP; - CachedSettingValue m_isSuperSeedingEnabled; - CachedSettingValue m_maxConnections; - CachedSettingValue m_maxHalfOpenConnections; - CachedSettingValue m_maxUploads; - CachedSettingValue m_maxConnectionsPerTorrent; - CachedSettingValue m_maxUploadsPerTorrent; - CachedSettingValue m_isUTPEnabled; - CachedSettingValue m_isUTPRateLimited; - CachedSettingValue m_isAddTrackersEnabled; - CachedSettingValue m_additionalTrackers; - CachedSettingValue m_globalMaxRatio; - CachedSettingValue m_globalMaxSeedingMinutes; - CachedSettingValue m_isAddTorrentPaused; - CachedSettingValue m_isCreateTorrentSubfolder; - CachedSettingValue m_isAppendExtensionEnabled; - CachedSettingValue m_refreshInterval; - CachedSettingValue m_isPreallocationEnabled; - CachedSettingValue m_torrentExportDirectory; - CachedSettingValue m_finishedTorrentExportDirectory; - CachedSettingValue m_globalDownloadSpeedLimit; - CachedSettingValue m_globalUploadSpeedLimit; - CachedSettingValue m_altGlobalDownloadSpeedLimit; - CachedSettingValue m_altGlobalUploadSpeedLimit; - CachedSettingValue m_isAltGlobalSpeedLimitEnabled; - CachedSettingValue m_isBandwidthSchedulerEnabled; - CachedSettingValue m_saveResumeDataInterval; - CachedSettingValue m_port; - CachedSettingValue m_useRandomPort; - CachedSettingValue m_networkInterface; - CachedSettingValue m_networkInterfaceName; - CachedSettingValue m_networkInterfaceAddress; - CachedSettingValue m_isIPv6Enabled; - CachedSettingValue m_encryption; - CachedSettingValue m_isForceProxyEnabled; - CachedSettingValue m_isProxyPeerConnectionsEnabled; - CachedSettingValue m_storedCategories; - CachedSettingValue m_storedTags; - CachedSettingValue m_maxRatioAction; - CachedSettingValue m_defaultSavePath; - CachedSettingValue m_tempPath; - CachedSettingValue m_isSubcategoriesEnabled; - CachedSettingValue m_isTempPathEnabled; - CachedSettingValue m_isAutoTMMDisabledByDefault; - CachedSettingValue m_isDisableAutoTMMWhenCategoryChanged; - CachedSettingValue m_isDisableAutoTMMWhenDefaultSavePathChanged; - CachedSettingValue m_isDisableAutoTMMWhenCategorySavePathChanged; - CachedSettingValue m_isTrackerEnabled; - CachedSettingValue m_bannedIPs; - - // Order is important. This needs to be declared after its CachedSettingsValue - // counterpart, because it uses it for initialization in the constructor - // initialization list. - const bool m_wasPexEnabled; - - int m_numResumeData; - int m_extraLimit; - QList m_additionalTrackerList; - QString m_resumeFolderPath; - QFile m_resumeFolderLock; - QHash m_savePathsToRemove; - bool m_useProxy; - - QTimer *m_refreshTimer; - QTimer *m_seedingLimitTimer; - QTimer *m_resumeDataTimer; - Statistics *m_statistics; - // IP filtering - QPointer m_filterParser; - QPointer m_bwScheduler; - // Tracker - QPointer m_tracker; - // fastresume data writing thread - QThread *m_ioThread; - ResumeDataSavingManager *m_resumeDataSavingManager; - - QHash m_loadedMetadata; - QHash m_torrents; - QHash m_addingTorrents; - QHash m_downloadedTorrents; - TorrentStatusReport m_torrentStatusReport; - QStringMap m_categories; - QSet m_tags; - -#if LIBTORRENT_VERSION_NUM < 10100 - QMutex m_alertsMutex; - QWaitCondition m_alertsWaitCondition; - std::vector m_alerts; -#else - SessionMetricIndices m_metricIndices; - QElapsedTimer m_statsUpdateTimer; -#endif - - SessionStatus m_status; - CacheStatus m_cacheStatus; - - QNetworkConfigurationManager m_networkManager; - - static Session *m_instance; - }; -} - -#endif // BITTORRENT_SESSION_H diff --git a/src/base/bittorrent/sessionstatus.h b/src/base/bittorrent/sessionstatus.h deleted file mode 100644 index 1426786ba..000000000 --- a/src/base/bittorrent/sessionstatus.h +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2015, 2017 Vladimir Golovnev - * - * 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. - */ - -#ifndef BITTORRENT_SESSIONSTATUS_H -#define BITTORRENT_SESSIONSTATUS_H - -#include - -namespace BitTorrent -{ - struct SessionStatus - { - bool hasIncomingConnections = false; - - // Current download rate for the BT - // session. Payload means that it only take into - // account "useful" part of the rate - quint64 payloadDownloadRate = 0; - - // Current upload rate for the BT - // session. Payload means that it only take into - // account "useful" part of the rate - quint64 payloadUploadRate = 0; - - // Additional download/upload rates - quint64 uploadRate = 0; - quint64 downloadRate = 0; - quint64 ipOverheadUploadRate = 0; - quint64 ipOverheadDownloadRate = 0; - quint64 dhtUploadRate = 0; - quint64 dhtDownloadRate = 0; - quint64 trackerUploadRate = 0; - quint64 trackerDownloadRate = 0; - - quint64 totalDownload = 0; - quint64 totalUpload = 0; - quint64 totalPayloadDownload = 0; - quint64 totalPayloadUpload = 0; - quint64 ipOverheadUpload = 0; - quint64 ipOverheadDownload = 0; - quint64 dhtUpload = 0; - quint64 dhtDownload = 0; - quint64 trackerUpload = 0; - quint64 trackerDownload = 0; - quint64 totalWasted = 0; - quint64 diskReadQueue = 0; - quint64 diskWriteQueue = 0; - quint64 dhtNodes = 0; - quint64 peersCount = 0; - }; -} - -#endif // BITTORRENT_SESSIONSTATUS_H diff --git a/src/base/bittorrent/torrentcreatorthread.cpp b/src/base/bittorrent/torrentcreatorthread.cpp deleted file mode 100644 index 38643235b..000000000 --- a/src/base/bittorrent/torrentcreatorthread.cpp +++ /dev/null @@ -1,172 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2010 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 "torrentcreatorthread.h" - -#include - -#include -#include -#include -#include -#include - -#include - -#include "base/utils/fs.h" -#include "base/utils/misc.h" -#include "base/utils/string.h" - -namespace libt = libtorrent; -using namespace BitTorrent; - -// do not include files and folders whose -// name starts with a . -bool fileFilter(const std::string &f) -{ - return !Utils::Fs::fileName(QString::fromStdString(f)).startsWith('.'); -} - -TorrentCreatorThread::TorrentCreatorThread(QObject *parent) - : QThread(parent) - , m_private(false) - , m_pieceSize(0) -{ -} - -TorrentCreatorThread::~TorrentCreatorThread() -{ - requestInterruption(); - wait(1000); -} - -void TorrentCreatorThread::create(const QString &inputPath, const QString &savePath, const QStringList &trackers, - const QStringList &urlSeeds, const QString &comment, bool isPrivate, int pieceSize) -{ - m_inputPath = Utils::Fs::fromNativePath(inputPath); - m_savePath = Utils::Fs::fromNativePath(savePath); - if (QFile(m_savePath).exists()) - Utils::Fs::forceRemove(m_savePath); - m_trackers = trackers; - m_urlSeeds = urlSeeds; - m_comment = comment; - m_private = isPrivate; - m_pieceSize = pieceSize; - - start(); -} - -void TorrentCreatorThread::sendProgressSignal(int numHashes, int numPieces) -{ - emit updateProgress(static_cast((numHashes * 100.) / numPieces)); -} - -void TorrentCreatorThread::run() -{ - emit updateProgress(0); - - QString creator_str("qBittorrent " QBT_VERSION); - try { - libt::file_storage fs; - // Adding files to the torrent - libt::add_files(fs, Utils::Fs::toNativePath(m_inputPath).toStdString(), fileFilter); - - if (isInterruptionRequested()) return; - - libt::create_torrent t(fs, m_pieceSize); - - // Add url seeds - foreach (const QString &seed, m_urlSeeds) - t.add_url_seed(seed.trimmed().toStdString()); - - int tier = 0; - bool newline = false; - foreach (const QString &tracker, m_trackers) { - if (tracker.isEmpty()) { - if (newline) - continue; - ++tier; - newline = true; - continue; - } - t.add_tracker(tracker.trimmed().toStdString(), tier); - newline = false; - } - - if (isInterruptionRequested()) return; - - // calculate the hash for all pieces - const QString parentPath = Utils::Fs::branchPath(m_inputPath) + "/"; - libt::set_piece_hashes(t, Utils::Fs::toNativePath(parentPath).toStdString(), boost::bind(&TorrentCreatorThread::sendProgressSignal, this, _1, t.num_pieces())); - // Set qBittorrent as creator and add user comment to - // torrent_info structure - t.set_creator(creator_str.toUtf8().constData()); - t.set_comment(m_comment.toUtf8().constData()); - // Is private ? - t.set_priv(m_private); - - if (isInterruptionRequested()) return; - - // create the torrent and print it to out - qDebug("Saving to %s", qPrintable(m_savePath)); -#ifdef _MSC_VER - wchar_t *savePathW = new wchar_t[m_savePath.length() + 1]; - int len = Utils::Fs::toNativePath(m_savePath).toWCharArray(savePathW); - savePathW[len] = L'\0'; - std::ofstream outfile(savePathW, std::ios_base::out | std::ios_base::binary); - delete[] savePathW; -#else - std::ofstream outfile(Utils::Fs::toNativePath(m_savePath).toLocal8Bit().constData(), std::ios_base::out | std::ios_base::binary); -#endif - if (outfile.fail()) - throw std::exception(); - - if (isInterruptionRequested()) return; - - libt::bencode(std::ostream_iterator(outfile), t.generate()); - outfile.close(); - - emit updateProgress(100); - emit creationSuccess(m_savePath, parentPath); - } - catch (std::exception& e) { - emit creationFailure(QString::fromStdString(e.what())); - } -} - -int TorrentCreatorThread::calculateTotalPieces(const QString &inputPath, const int pieceSize) -{ - if (inputPath.isEmpty()) - return 0; - - libt::file_storage fs; - libt::add_files(fs, Utils::Fs::toNativePath(inputPath).toStdString(), fileFilter); - return libt::create_torrent(fs, pieceSize).num_pieces(); -} diff --git a/src/base/bittorrent/torrentcreatorthread.h b/src/base/bittorrent/torrentcreatorthread.h deleted file mode 100644 index 25d8d83ed..000000000 --- a/src/base/bittorrent/torrentcreatorthread.h +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2010 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 BITTORRENT_TORRENTCREATORTHREAD_H -#define BITTORRENT_TORRENTCREATORTHREAD_H - -#include -#include - -namespace BitTorrent -{ - class TorrentCreatorThread : public QThread - { - Q_OBJECT - - public: - TorrentCreatorThread(QObject *parent = 0); - ~TorrentCreatorThread(); - - void create(const QString &inputPath, const QString &savePath, const QStringList &trackers, - const QStringList &urlSeeds, const QString &comment, bool isPrivate, int pieceSize); - - static int calculateTotalPieces(const QString &inputPath, const int pieceSize); - - protected: - void run(); - - signals: - void creationFailure(const QString &msg); - void creationSuccess(const QString &path, const QString &branchPath); - void updateProgress(int progress); - - private: - void sendProgressSignal(int numHashes, int numPieces); - - QString m_inputPath; - QString m_savePath; - QStringList m_trackers; - QStringList m_urlSeeds; - QString m_comment; - bool m_private; - int m_pieceSize; - }; -} - -#endif // BITTORRENT_TORRENTCREATORTHREAD_H diff --git a/src/base/bittorrent/torrenthandle.cpp b/src/base/bittorrent/torrenthandle.cpp deleted file mode 100644 index 4a95ee9ea..000000000 --- a/src/base/bittorrent/torrenthandle.cpp +++ /dev/null @@ -1,2144 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2015 Vladimir Golovnev - * Copyright (C) 2006 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. - */ - -#include - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#if LIBTORRENT_VERSION_NUM >= 10100 -#include -#endif - -#include - -#ifdef Q_OS_WIN -#include -#endif - -#include "base/logger.h" -#include "base/preferences.h" -#include "base/profile.h" -#include "base/utils/string.h" -#include "base/utils/fs.h" -#include "base/utils/misc.h" -#include "session.h" -#include "peerinfo.h" -#include "trackerentry.h" -#include "torrenthandle.h" - -const QString QB_EXT {".!qB"}; - -namespace libt = libtorrent; -using namespace BitTorrent; - -namespace -{ - using ListType = libt::entry::list_type; - - ListType setToEntryList(const QSet &input) - { - ListType entryList; - foreach (const QString &setValue, input) - entryList.emplace_back(setValue.toStdString()); - return entryList; - } -} - -// AddTorrentData - -AddTorrentData::AddTorrentData() - : resumed(false) - , disableTempPath(false) - , sequential(false) - , firstLastPiecePriority(false) - , hasSeedStatus(false) - , skipChecking(false) - , hasRootFolder(true) - , addForced(false) - , addPaused(false) - , ratioLimit(TorrentHandle::USE_GLOBAL_RATIO) - , seedingTimeLimit(TorrentHandle::USE_GLOBAL_SEEDING_TIME) -{ -} - -AddTorrentData::AddTorrentData(const AddTorrentParams ¶ms) - : resumed(false) - , name(params.name) - , category(params.category) - , tags(params.tags) - , savePath(params.savePath) - , disableTempPath(params.disableTempPath) - , sequential(params.sequential) - , firstLastPiecePriority(params.firstLastPiecePriority) - , hasSeedStatus(params.skipChecking) // do not react on 'torrent_finished_alert' when skipping - , skipChecking(params.skipChecking) - , hasRootFolder(params.createSubfolder == TriStateBool::Undefined - ? Session::instance()->isCreateTorrentSubfolder() - : params.createSubfolder == TriStateBool::True) - , addForced(params.addForced == TriStateBool::True) - , addPaused(params.addPaused == TriStateBool::Undefined - ? Session::instance()->isAddTorrentPaused() - : params.addPaused == TriStateBool::True) - , filePriorities(params.filePriorities) - , ratioLimit(params.ignoreShareLimits ? TorrentHandle::NO_RATIO_LIMIT : TorrentHandle::USE_GLOBAL_RATIO) - , seedingTimeLimit(params.ignoreShareLimits ? TorrentHandle::NO_SEEDING_TIME_LIMIT : TorrentHandle::USE_GLOBAL_SEEDING_TIME) -{ - bool useAutoTMM = (params.useAutoTMM == TriStateBool::Undefined - ? !Session::instance()->isAutoTMMDisabledByDefault() - : params.useAutoTMM == TriStateBool::True); - if (useAutoTMM) - savePath = ""; - else if (savePath.trimmed().isEmpty()) - savePath = Session::instance()->defaultSavePath(); -} - -// TorrentState - -TorrentState::TorrentState(int value) - : m_value(value) -{ -} - -QString TorrentState::toString() const -{ - switch (m_value) { - case Error: - return QLatin1String("error"); - case MissingFiles: - return QLatin1String("missingFiles"); - case Uploading: - return QLatin1String("uploading"); - case PausedUploading: - return QLatin1String("pausedUP"); - case QueuedUploading: - return QLatin1String("queuedUP"); - case StalledUploading: - return QLatin1String("stalledUP"); - case CheckingUploading: - return QLatin1String("checkingUP"); - case ForcedUploading: - return QLatin1String("forcedUP"); - case Allocating: - return QLatin1String("allocating"); - case Downloading: - return QLatin1String("downloading"); - case DownloadingMetadata: - return QLatin1String("metaDL"); - case PausedDownloading: - return QLatin1String("pausedDL"); - case QueuedDownloading: - return QLatin1String("queuedDL"); - case StalledDownloading: - return QLatin1String("stalledDL"); - case CheckingDownloading: - return QLatin1String("checkingDL"); - case ForcedDownloading: - return QLatin1String("forcedDL"); -#if LIBTORRENT_VERSION_NUM < 10100 - case QueuedForChecking: - return QLatin1String("queuedForChecking"); -#endif - case CheckingResumeData: - return QLatin1String("checkingResumeData"); - default: - return QLatin1String("unknown"); - } -} - -TorrentState::operator int() const -{ - return m_value; -} - -// TorrentHandle - -const qreal TorrentHandle::USE_GLOBAL_RATIO = -2.; -const qreal TorrentHandle::NO_RATIO_LIMIT = -1.; - -const int TorrentHandle::USE_GLOBAL_SEEDING_TIME = -2; -const int TorrentHandle::NO_SEEDING_TIME_LIMIT = -1; - -const qreal TorrentHandle::MAX_RATIO = 9999.; -const int TorrentHandle::MAX_SEEDING_TIME = 525600; - -// The new libtorrent::create_torrent constructor appeared after 1.0.11 in RC_1_0 -// and after 1.1.1 in RC_1_1. Since it fixed an ABI incompatibility with previous versions -// distros might choose to backport it onto 1.0.11 and 1.1.1 respectively. -// So we need a way to detect its presence without relying solely on the LIBTORRENT_VERSION_NUM. -// Relevant links: -// 1. https://github.com/arvidn/libtorrent/issues/1696 -// 2. https://github.com/qbittorrent/qBittorrent/issues/6406 -// The following can be removed after one or two libtorrent releases on each branch. -namespace -{ - // new constructor is available - template::value, int>::type = 0> - T makeTorrentCreator(const libtorrent::torrent_info & ti) - { - return T(ti, true); - } - - // new constructor isn't available - template::value, int>::type = 0> - T makeTorrentCreator(const libtorrent::torrent_info & ti) - { - return T(ti); - } -} - -TorrentHandle::TorrentHandle(Session *session, const libtorrent::torrent_handle &nativeHandle, - const AddTorrentData &data) - : QObject(session) - , m_session(session) - , m_nativeHandle(nativeHandle) - , m_state(TorrentState::Unknown) - , m_renameCount(0) - , m_useAutoTMM(data.savePath.isEmpty()) - , m_name(data.name) - , m_savePath(Utils::Fs::toNativePath(data.savePath)) - , m_category(data.category) - , m_tags(data.tags) - , m_hasSeedStatus(data.hasSeedStatus) - , m_ratioLimit(data.ratioLimit) - , m_seedingTimeLimit(data.seedingTimeLimit) - , m_tempPathDisabled(data.disableTempPath) - , m_hasMissingFiles(false) - , m_hasRootFolder(data.hasRootFolder) - , m_needsToSetFirstLastPiecePriority(false) - , m_pauseAfterRecheck(false) - , m_needSaveResumeData(false) -{ - if (m_useAutoTMM) - m_savePath = Utils::Fs::toNativePath(m_session->categorySavePath(m_category)); - - updateStatus(); - m_hash = InfoHash(m_nativeStatus.info_hash); - - // NB: the following two if statements are present because we don't want - // to set either sequential download or first/last piece priority to false - // if their respective flags in data are false when a torrent is being - // resumed. This is because, in that circumstance, this constructor is - // called with those flags set to false, even if the torrent was set to - // download sequentially or have first/last piece priority enabled when - // its resume data was saved. These two settings are restored later. But - // if we set them to false now, both will erroneously not be restored. - if (!data.resumed || data.sequential) - setSequentialDownload(data.sequential); - if (!data.resumed || data.firstLastPiecePriority) - setFirstLastPiecePriority(data.firstLastPiecePriority); - - if (!data.resumed && hasMetadata()) { - if (filesCount() == 1) - m_hasRootFolder = false; - } -} - -TorrentHandle::~TorrentHandle() {} - -bool TorrentHandle::isValid() const -{ - return m_nativeHandle.is_valid(); -} - -InfoHash TorrentHandle::hash() const -{ - return m_hash; -} - -QString TorrentHandle::name() const -{ - QString name = m_name; - if (name.isEmpty()) - name = QString::fromStdString(m_nativeStatus.name); - - if (name.isEmpty() && hasMetadata()) - name = QString::fromStdString(m_torrentInfo.nativeInfo()->orig_files().name()); - - if (name.isEmpty()) - name = m_hash; - - return name; -} - -QDateTime TorrentHandle::creationDate() const -{ - return m_torrentInfo.creationDate(); -} - -QString TorrentHandle::creator() const -{ - return m_torrentInfo.creator(); -} - -QString TorrentHandle::comment() const -{ - return m_torrentInfo.comment(); -} - -bool TorrentHandle::isPrivate() const -{ - return m_torrentInfo.isPrivate(); -} - -qlonglong TorrentHandle::totalSize() const -{ - return m_torrentInfo.totalSize(); -} - -// get the size of the torrent without the filtered files -qlonglong TorrentHandle::wantedSize() const -{ - return m_nativeStatus.total_wanted; -} - -qlonglong TorrentHandle::completedSize() const -{ - return m_nativeStatus.total_wanted_done; -} - -qlonglong TorrentHandle::incompletedSize() const -{ - return (m_nativeStatus.total_wanted - m_nativeStatus.total_wanted_done); -} - -qlonglong TorrentHandle::pieceLength() const -{ - return m_torrentInfo.pieceLength(); -} - -qlonglong TorrentHandle::wastedSize() const -{ - return (m_nativeStatus.total_failed_bytes + m_nativeStatus.total_redundant_bytes); -} - -QString TorrentHandle::currentTracker() const -{ - return QString::fromStdString(m_nativeStatus.current_tracker); -} - -QString TorrentHandle::savePath(bool actual) const -{ - if (actual) - return Utils::Fs::fromNativePath(nativeActualSavePath()); - else - return Utils::Fs::fromNativePath(m_savePath); -} - -QString TorrentHandle::rootPath(bool actual) const -{ - if ((filesCount() > 1) && !hasRootFolder()) - return QString(); - - QString firstFilePath = filePath(0); - const int slashIndex = firstFilePath.indexOf("/"); - if (slashIndex >= 0) - return QDir(savePath(actual)).absoluteFilePath(firstFilePath.left(slashIndex)); - else - return QDir(savePath(actual)).absoluteFilePath(firstFilePath); -} - -QString TorrentHandle::contentPath(bool actual) const -{ - if (filesCount() == 1) - return QDir(savePath(actual)).absoluteFilePath(filePath(0)); - else if (hasRootFolder()) - return rootPath(actual); - else - return savePath(actual); -} - -bool TorrentHandle::isAutoTMMEnabled() const -{ - return m_useAutoTMM; -} - -void TorrentHandle::setAutoTMMEnabled(bool enabled) -{ - if (m_useAutoTMM == enabled) return; - - m_useAutoTMM = enabled; - m_session->handleTorrentSavingModeChanged(this); - - if (m_useAutoTMM) - move_impl(m_session->categorySavePath(m_category), true); -} - -bool TorrentHandle::hasRootFolder() const -{ - return m_hasRootFolder; -} - -QString TorrentHandle::nativeActualSavePath() const -{ - return QString::fromStdString(m_nativeStatus.save_path); -} - -QList TorrentHandle::trackers() const -{ - QList entries; - std::vector announces; - - announces = m_nativeHandle.trackers(); - foreach (const libt::announce_entry &tracker, announces) - entries << tracker; - - return entries; -} - -QHash TorrentHandle::trackerInfos() const -{ - return m_trackerInfos; -} - -void TorrentHandle::addTrackers(const QList &trackers) -{ - QList addedTrackers; - foreach (const TrackerEntry &tracker, trackers) { - if (addTracker(tracker)) - addedTrackers << tracker; - } - - if (!addedTrackers.isEmpty()) - m_session->handleTorrentTrackersAdded(this, addedTrackers); -} - -void TorrentHandle::replaceTrackers(QList trackers) -{ - QList existingTrackers = this->trackers(); - QList addedTrackers; - - std::vector announces; - foreach (const TrackerEntry &tracker, trackers) { - announces.push_back(tracker.nativeEntry()); - if (!existingTrackers.contains(tracker)) - addedTrackers << tracker; - else - existingTrackers.removeOne(tracker); - } - - m_nativeHandle.replace_trackers(announces); - if (addedTrackers.isEmpty() && existingTrackers.isEmpty()) { - m_session->handleTorrentTrackersChanged(this); - } - else { - if (!existingTrackers.isEmpty()) - m_session->handleTorrentTrackersRemoved(this, existingTrackers); - if (!addedTrackers.isEmpty()) - m_session->handleTorrentTrackersAdded(this, addedTrackers); - } -} - -bool TorrentHandle::addTracker(const TrackerEntry &tracker) -{ - if (trackers().contains(tracker)) - return false; - - m_nativeHandle.add_tracker(tracker.nativeEntry()); - return true; -} - -QList TorrentHandle::urlSeeds() const -{ - QList urlSeeds; - std::set seeds = m_nativeHandle.url_seeds(); - - foreach (const std::string &urlSeed, seeds) - urlSeeds.append(QUrl(urlSeed.c_str())); - - return urlSeeds; -} - -void TorrentHandle::addUrlSeeds(const QList &urlSeeds) -{ - QList addedUrlSeeds; - foreach (const QUrl &urlSeed, urlSeeds) { - if (addUrlSeed(urlSeed)) - addedUrlSeeds << urlSeed; - } - - if (!addedUrlSeeds.isEmpty()) - m_session->handleTorrentUrlSeedsAdded(this, addedUrlSeeds); -} - -void TorrentHandle::removeUrlSeeds(const QList &urlSeeds) -{ - QList removedUrlSeeds; - foreach (const QUrl &urlSeed, urlSeeds) { - if (removeUrlSeed(urlSeed)) - removedUrlSeeds << urlSeed; - } - - if (!removedUrlSeeds.isEmpty()) - m_session->handleTorrentUrlSeedsRemoved(this, removedUrlSeeds); -} - -bool TorrentHandle::addUrlSeed(const QUrl &urlSeed) -{ - QList seeds = urlSeeds(); - if (seeds.contains(urlSeed)) return false; - - m_nativeHandle.add_url_seed(urlSeed.toString().toStdString()); - return true; -} - -bool TorrentHandle::removeUrlSeed(const QUrl &urlSeed) -{ - QList seeds = urlSeeds(); - if (!seeds.contains(urlSeed)) return false; - - m_nativeHandle.remove_url_seed(urlSeed.toString().toStdString()); - return true; -} - -bool TorrentHandle::connectPeer(const PeerAddress &peerAddress) -{ - libt::error_code ec; - libt::address addr = libt::address::from_string(peerAddress.ip.toString().toStdString(), ec); - if (ec) return false; - - boost::asio::ip::tcp::endpoint ep(addr, peerAddress.port); - m_nativeHandle.connect_peer(ep); - return true; -} - -bool TorrentHandle::needSaveResumeData() const -{ - if (m_needSaveResumeData) return true; - - return m_nativeHandle.need_save_resume_data(); -} - -void TorrentHandle::saveResumeData(bool updateStatus) -{ - if (updateStatus) // to update queue_position, see discussion in PR #6154 - this->updateStatus(); - - m_nativeHandle.save_resume_data(); - m_needSaveResumeData = false; -} - -int TorrentHandle::filesCount() const -{ - return m_torrentInfo.filesCount(); -} - -int TorrentHandle::piecesCount() const -{ - return m_torrentInfo.piecesCount(); -} - -int TorrentHandle::piecesHave() const -{ - return m_nativeStatus.num_pieces; -} - -qreal TorrentHandle::progress() const -{ - if (!m_nativeStatus.total_wanted) - return 0.; - - if (m_nativeStatus.total_wanted_done == m_nativeStatus.total_wanted) - return 1.; - - float progress = static_cast(m_nativeStatus.total_wanted_done) / m_nativeStatus.total_wanted; - Q_ASSERT((progress >= 0.f) && (progress <= 1.f)); - return progress; -} - -QString TorrentHandle::category() const -{ - return m_category; -} - -bool TorrentHandle::belongsToCategory(const QString &category) const -{ - if (m_category.isEmpty()) return category.isEmpty(); - if (!Session::isValidCategoryName(category)) return false; - - if (m_category == category) return true; - - if (m_session->isSubcategoriesEnabled() && m_category.startsWith(category + "/")) - return true; - - return false; -} - -QSet TorrentHandle::tags() const -{ - return m_tags; -} - -bool TorrentHandle::hasTag(const QString &tag) const -{ - return m_tags.contains(tag); -} - -bool TorrentHandle::addTag(const QString &tag) -{ - if (!Session::isValidTag(tag)) - return false; - - if (!hasTag(tag)) { - if (!m_session->hasTag(tag)) - if (!m_session->addTag(tag)) - return false; - m_tags.insert(tag); - m_session->handleTorrentTagAdded(this, tag); - m_needSaveResumeData = true; - return true; - } - return false; -} - -bool TorrentHandle::removeTag(const QString &tag) -{ - if (m_tags.remove(tag)) { - m_session->handleTorrentTagRemoved(this, tag); - m_needSaveResumeData = true; - return true; - } - return false; -} - -void TorrentHandle::removeAllTags() -{ - // QT automatically copies the container in foreach, so it's safe to mutate it. - foreach (const QString &tag, m_tags) - removeTag(tag); -} - -QDateTime TorrentHandle::addedTime() const -{ - return QDateTime::fromTime_t(m_nativeStatus.added_time); -} - -qreal TorrentHandle::ratioLimit() const -{ - return m_ratioLimit; -} - -int TorrentHandle::seedingTimeLimit() const -{ - return m_seedingTimeLimit; -} - -QString TorrentHandle::filePath(int index) const -{ - return m_torrentInfo.filePath(index); -} - -QString TorrentHandle::fileName(int index) const -{ - if (!hasMetadata()) return QString(); - return Utils::Fs::fileName(filePath(index)); -} - -qlonglong TorrentHandle::fileSize(int index) const -{ - return m_torrentInfo.fileSize(index); -} - -// Return a list of absolute paths corresponding -// to all files in a torrent -QStringList TorrentHandle::absoluteFilePaths() const -{ - if (!hasMetadata()) return QStringList(); - - QDir saveDir(savePath(true)); - QStringList res; - for (int i = 0; i < filesCount(); ++i) - res << Utils::Fs::expandPathAbs(saveDir.absoluteFilePath(filePath(i))); - return res; -} - -QStringList TorrentHandle::absoluteFilePathsUnwanted() const -{ - if (!hasMetadata()) return QStringList(); - - QDir saveDir(savePath(true)); - QStringList res; - std::vector fp; - fp = m_nativeHandle.file_priorities(); - - int count = static_cast(fp.size()); - for (int i = 0; i < count; ++i) { - if (fp[i] == 0) { - const QString path = Utils::Fs::expandPathAbs(saveDir.absoluteFilePath(filePath(i))); - if (path.contains(".unwanted")) - res << path; - } - } - - return res; -} - -QVector TorrentHandle::filePriorities() const -{ - std::vector fp; - fp = m_nativeHandle.file_priorities(); - - return QVector::fromStdVector(fp); -} - -TorrentInfo TorrentHandle::info() const -{ - return m_torrentInfo; -} - -bool TorrentHandle::isPaused() const -{ - return (m_nativeStatus.paused && !m_nativeStatus.auto_managed); -} - -bool TorrentHandle::isResumed() const -{ - return !isPaused(); -} - -bool TorrentHandle::isQueued() const -{ - return (m_nativeStatus.paused && m_nativeStatus.auto_managed); -} - -bool TorrentHandle::isChecking() const -{ - return ((m_nativeStatus.state == libt::torrent_status::checking_files) - || (m_nativeStatus.state == libt::torrent_status::checking_resume_data) -#if LIBTORRENT_VERSION_NUM < 10100 - || (m_nativeStatus.state == libt::torrent_status::queued_for_checking) -#endif - ); -} - -bool TorrentHandle::isDownloading() const -{ - return m_state == TorrentState::Downloading - || m_state == TorrentState::DownloadingMetadata - || m_state == TorrentState::StalledDownloading - || m_state == TorrentState::CheckingDownloading - || m_state == TorrentState::PausedDownloading - || m_state == TorrentState::QueuedDownloading - || m_state == TorrentState::ForcedDownloading; -} - -bool TorrentHandle::isUploading() const -{ - return m_state == TorrentState::Uploading - || m_state == TorrentState::StalledUploading - || m_state == TorrentState::CheckingUploading - || m_state == TorrentState::QueuedUploading - || m_state == TorrentState::ForcedUploading; -} - -bool TorrentHandle::isCompleted() const -{ - return m_state == TorrentState::Uploading - || m_state == TorrentState::StalledUploading - || m_state == TorrentState::CheckingUploading - || m_state == TorrentState::PausedUploading - || m_state == TorrentState::QueuedUploading - || m_state == TorrentState::ForcedUploading; -} - -bool TorrentHandle::isActive() const -{ - if (m_state == TorrentState::StalledDownloading) - return (uploadPayloadRate() > 0); - - return m_state == TorrentState::DownloadingMetadata - || m_state == TorrentState::Downloading - || m_state == TorrentState::ForcedDownloading - || m_state == TorrentState::Uploading - || m_state == TorrentState::ForcedUploading; -} - -bool TorrentHandle::isInactive() const -{ - return !isActive(); -} - -bool TorrentHandle::isErrored() const -{ - return m_state == TorrentState::MissingFiles - || m_state == TorrentState::Error; -} - -bool TorrentHandle::isSeed() const -{ - // Affected by bug http://code.rasterbar.com/libtorrent/ticket/402 - //bool result; - //result = m_nativeHandle.is_seed()); - //return result; - // May suffer from approximation problems - //return (progress() == 1.); - // This looks safe - return ((m_nativeStatus.state == libt::torrent_status::finished) - || (m_nativeStatus.state == libt::torrent_status::seeding)); -} - -bool TorrentHandle::isForced() const -{ - return (!m_nativeStatus.paused && !m_nativeStatus.auto_managed); -} - -bool TorrentHandle::isSequentialDownload() const -{ - return m_nativeStatus.sequential_download; -} - -bool TorrentHandle::hasFirstLastPiecePriority() const -{ - if (!hasMetadata()) - return m_needsToSetFirstLastPiecePriority; - - // Get int first media file - std::vector fp; - fp = m_nativeHandle.file_priorities(); - - TorrentInfo::PieceRange extremities; - bool found = false; - int count = static_cast(fp.size()); - for (int i = 0; i < count; ++i) { - const QString ext = Utils::Fs::fileExtension(filePath(i)); - if (Utils::Misc::isPreviewable(ext) && (fp[i] > 0)) { - extremities = info().filePieces(i); - found = true; - break; - } - } - - if (!found) return false; // No media file - - int first = m_nativeHandle.piece_priority(extremities.first()); - int last = m_nativeHandle.piece_priority(extremities.last()); - - return ((first == 7) && (last == 7)); -} - -TorrentState TorrentHandle::state() const -{ - return m_state; -} - -void TorrentHandle::updateState() -{ - if (isPaused()) { - if (hasMissingFiles()) - m_state = TorrentState::MissingFiles; - else if (hasError()) - m_state = TorrentState::Error; - else - m_state = isSeed() ? TorrentState::PausedUploading : TorrentState::PausedDownloading; - } - else { - if (m_session->isQueueingSystemEnabled() && isQueued() && !isChecking()) { - m_state = isSeed() ? TorrentState::QueuedUploading : TorrentState::QueuedDownloading; - } - else { - switch (m_nativeStatus.state) { - case libt::torrent_status::finished: - case libt::torrent_status::seeding: - if (isForced()) - m_state = TorrentState::ForcedUploading; - else - m_state = m_nativeStatus.upload_payload_rate > 0 ? TorrentState::Uploading : TorrentState::StalledUploading; - break; - case libt::torrent_status::allocating: - m_state = TorrentState::Allocating; - break; -#if LIBTORRENT_VERSION_NUM < 10100 - case libt::torrent_status::queued_for_checking: - m_state = TorrentState::QueuedForChecking; - break; -#endif - case libt::torrent_status::checking_resume_data: - m_state = TorrentState::CheckingResumeData; - break; - case libt::torrent_status::checking_files: - m_state = m_hasSeedStatus ? TorrentState::CheckingUploading : TorrentState::CheckingDownloading; - break; - case libt::torrent_status::downloading_metadata: - m_state = TorrentState::DownloadingMetadata; - break; - case libt::torrent_status::downloading: - if (isForced()) - m_state = TorrentState::ForcedDownloading; - else - m_state = m_nativeStatus.download_payload_rate > 0 ? TorrentState::Downloading : TorrentState::StalledDownloading; - break; - default: - qWarning("Unrecognized torrent status, should not happen!!! status was %d", m_nativeStatus.state); - m_state = TorrentState::Unknown; - } - } - } -} - -bool TorrentHandle::hasMetadata() const -{ - return m_nativeStatus.has_metadata; -} - -bool TorrentHandle::hasMissingFiles() const -{ - return m_hasMissingFiles; -} - -bool TorrentHandle::hasError() const -{ -#if LIBTORRENT_VERSION_NUM < 10100 - return (m_nativeStatus.paused && !m_nativeStatus.error.empty()); -#else - return (m_nativeStatus.paused && m_nativeStatus.errc); -#endif -} - -bool TorrentHandle::hasFilteredPieces() const -{ - std::vector pp = m_nativeHandle.piece_priorities(); - - foreach (const int priority, pp) - if (priority == 0) return true; - - return false; -} - -int TorrentHandle::queuePosition() const -{ - if (m_nativeStatus.queue_position < 0) return 0; - - return m_nativeStatus.queue_position + 1; -} - -QString TorrentHandle::error() const -{ -#if LIBTORRENT_VERSION_NUM < 10100 - return QString::fromStdString(m_nativeStatus.error); -#else - return QString::fromStdString(m_nativeStatus.errc.message()); -#endif -} - -qlonglong TorrentHandle::totalDownload() const -{ - return m_nativeStatus.all_time_download; -} - -qlonglong TorrentHandle::totalUpload() const -{ - return m_nativeStatus.all_time_upload; -} - -int TorrentHandle::activeTime() const -{ - return m_nativeStatus.active_time; -} - -int TorrentHandle::finishedTime() const -{ - return m_nativeStatus.finished_time; -} - -int TorrentHandle::seedingTime() const -{ - return m_nativeStatus.seeding_time; -} - -qulonglong TorrentHandle::eta() const -{ - if (isPaused()) return MAX_ETA; - - const SpeedSampleAvg speedAverage = m_speedMonitor.average(); - - if (isSeed()) { - qreal maxRatioValue = maxRatio(); - int maxSeedingTimeValue = maxSeedingTime(); - if ((maxRatioValue < 0) && (maxSeedingTimeValue < 0)) return MAX_ETA; - - qlonglong ratioEta = MAX_ETA; - - if ((speedAverage.upload > 0) && (maxRatioValue >= 0)) { - - qlonglong realDL = totalDownload(); - if (realDL <= 0) - realDL = wantedSize(); - - ratioEta = ((realDL * maxRatioValue) - totalUpload()) / speedAverage.upload; - } - - qlonglong seedingTimeEta = MAX_ETA; - - if (maxSeedingTimeValue >= 0) { - seedingTimeEta = (maxSeedingTimeValue * 60) - seedingTime(); - if (seedingTimeEta < 0) - seedingTimeEta = 0; - } - - return qMin(ratioEta, seedingTimeEta); - } - - if (!speedAverage.download) return MAX_ETA; - - return (wantedSize() - completedSize()) / speedAverage.download; -} - -QVector TorrentHandle::filesProgress() const -{ - std::vector fp; - QVector result; - m_nativeHandle.file_progress(fp, libt::torrent_handle::piece_granularity); - - int count = static_cast(fp.size()); - for (int i = 0; i < count; ++i) { - qlonglong size = fileSize(i); - if ((size <= 0) || (fp[i] == size)) - result << 1; - else - result << (fp[i] / static_cast(size)); - } - - return result; -} - -int TorrentHandle::seedsCount() const -{ - return m_nativeStatus.num_seeds; -} - -int TorrentHandle::peersCount() const -{ - return m_nativeStatus.num_peers; -} - -int TorrentHandle::leechsCount() const -{ - return (m_nativeStatus.num_peers - m_nativeStatus.num_seeds); -} - -int TorrentHandle::totalSeedsCount() const -{ - return (m_nativeStatus.num_complete > 0) ? m_nativeStatus.num_complete : m_nativeStatus.list_seeds; -} - -int TorrentHandle::totalPeersCount() const -{ - int peers = m_nativeStatus.num_complete + m_nativeStatus.num_incomplete; - return (peers > 0) ? peers : m_nativeStatus.list_peers; -} - -int TorrentHandle::totalLeechersCount() const -{ - return (m_nativeStatus.num_incomplete > 0) ? m_nativeStatus.num_incomplete : (m_nativeStatus.list_peers - m_nativeStatus.list_seeds); -} - -int TorrentHandle::completeCount() const -{ - // additional info: https://github.com/qbittorrent/qBittorrent/pull/5300#issuecomment-267783646 - return m_nativeStatus.num_complete; -} - -int TorrentHandle::incompleteCount() const -{ - // additional info: https://github.com/qbittorrent/qBittorrent/pull/5300#issuecomment-267783646 - return m_nativeStatus.num_incomplete; -} - -QDateTime TorrentHandle::lastSeenComplete() const -{ - if (m_nativeStatus.last_seen_complete > 0) - return QDateTime::fromTime_t(m_nativeStatus.last_seen_complete); - else - return QDateTime(); -} - -QDateTime TorrentHandle::completedTime() const -{ - if (m_nativeStatus.completed_time > 0) - return QDateTime::fromTime_t(m_nativeStatus.completed_time); - else - return QDateTime(); -} - -int TorrentHandle::timeSinceUpload() const -{ - return m_nativeStatus.time_since_upload; -} - -int TorrentHandle::timeSinceDownload() const -{ - return m_nativeStatus.time_since_download; -} - -int TorrentHandle::timeSinceActivity() const -{ - if (m_nativeStatus.time_since_upload < m_nativeStatus.time_since_download) - return m_nativeStatus.time_since_upload; - else - return m_nativeStatus.time_since_download; -} - -int TorrentHandle::downloadLimit() const -{ - return m_nativeHandle.download_limit(); -} - -int TorrentHandle::uploadLimit() const -{ - return m_nativeHandle.upload_limit(); -} - -bool TorrentHandle::superSeeding() const -{ - return m_nativeStatus.super_seeding; -} - -QList TorrentHandle::peers() const -{ - QList peers; - std::vector nativePeers; - - m_nativeHandle.get_peer_info(nativePeers); - - foreach (const libt::peer_info &peer, nativePeers) - peers << PeerInfo(this, peer); - - return peers; -} - -QBitArray TorrentHandle::pieces() const -{ - QBitArray result(m_nativeStatus.pieces.size()); - - for (int i = 0; i < m_nativeStatus.pieces.size(); ++i) - result.setBit(i, m_nativeStatus.pieces.get_bit(i)); - - return result; -} - -QBitArray TorrentHandle::downloadingPieces() const -{ - QBitArray result(piecesCount()); - - std::vector queue; - m_nativeHandle.get_download_queue(queue); - - std::vector::const_iterator it = queue.begin(); - std::vector::const_iterator itend = queue.end(); - for (; it != itend; ++it) - result.setBit(it->piece_index); - - return result; -} - -QVector TorrentHandle::pieceAvailability() const -{ - std::vector avail; - m_nativeHandle.piece_availability(avail); - - return QVector::fromStdVector(avail); -} - -qreal TorrentHandle::distributedCopies() const -{ - return m_nativeStatus.distributed_copies; -} - -qreal TorrentHandle::maxRatio(bool *usesGlobalRatio) const -{ - qreal ratioLimit = m_ratioLimit; - - if (ratioLimit == USE_GLOBAL_RATIO) { - ratioLimit = m_session->globalMaxRatio(); - if (usesGlobalRatio) - *usesGlobalRatio = true; - } - else { - if (usesGlobalRatio) - *usesGlobalRatio = false; - } - - return ratioLimit; -} - -int TorrentHandle::maxSeedingTime(bool *usesGlobalSeedingTime) const -{ - int seedingTimeLimit = m_seedingTimeLimit; - - if (seedingTimeLimit == USE_GLOBAL_SEEDING_TIME) { - seedingTimeLimit = m_session->globalMaxSeedingMinutes(); - if (usesGlobalSeedingTime) - *usesGlobalSeedingTime = true; - } - else { - if (usesGlobalSeedingTime) - *usesGlobalSeedingTime = false; - } - - return seedingTimeLimit; -} - -qreal TorrentHandle::realRatio() const -{ - boost::int64_t upload = m_nativeStatus.all_time_upload; - // special case for a seeder who lost its stats, also assume nobody will import a 99% done torrent - boost::int64_t download = (m_nativeStatus.all_time_download < m_nativeStatus.total_done * 0.01) ? m_nativeStatus.total_done : m_nativeStatus.all_time_download; - - if (download == 0) - return (upload == 0) ? 0.0 : MAX_RATIO; - - qreal ratio = upload / static_cast(download); - Q_ASSERT(ratio >= 0.0); - return (ratio > MAX_RATIO) ? MAX_RATIO : ratio; -} - -int TorrentHandle::uploadPayloadRate() const -{ - return m_nativeStatus.upload_payload_rate; -} - -int TorrentHandle::downloadPayloadRate() const -{ - return m_nativeStatus.download_payload_rate; -} - -qlonglong TorrentHandle::totalPayloadUpload() const -{ - return m_nativeStatus.total_payload_upload; -} - -qlonglong TorrentHandle::totalPayloadDownload() const -{ - return m_nativeStatus.total_payload_download; -} - -int TorrentHandle::connectionsCount() const -{ - return m_nativeStatus.num_connections; -} - -int TorrentHandle::connectionsLimit() const -{ - return m_nativeStatus.connections_limit; -} - -qlonglong TorrentHandle::nextAnnounce() const -{ -#if LIBTORRENT_VERSION_NUM < 10100 - return m_nativeStatus.next_announce.total_seconds(); -#else - return libt::duration_cast(m_nativeStatus.next_announce).count(); -#endif -} - -void TorrentHandle::setName(const QString &name) -{ - if (m_name != name) { - m_name = name; - m_needSaveResumeData = true; - } -} - -bool TorrentHandle::setCategory(const QString &category) -{ - if (m_category != category) { - if (!category.isEmpty()) { - if (!Session::isValidCategoryName(category)) return false; - if (!m_session->categories().contains(category)) - if (!m_session->addCategory(category)) - return false; - } - - QString oldCategory = m_category; - m_category = category; - m_needSaveResumeData = true; - m_session->handleTorrentCategoryChanged(this, oldCategory); - - if (m_useAutoTMM) { - if (!m_session->isDisableAutoTMMWhenCategoryChanged()) - move_impl(m_session->categorySavePath(m_category), true); - else - setAutoTMMEnabled(false); - } - } - - return true; -} - -void TorrentHandle::move(QString path) -{ - m_useAutoTMM = false; - m_session->handleTorrentSavingModeChanged(this); - - path = Utils::Fs::fromNativePath(path.trimmed()); - if (path.isEmpty()) - path = m_session->defaultSavePath(); - if (!path.endsWith('/')) - path += '/'; - - move_impl(path, false); -} - -void TorrentHandle::move_impl(QString path, bool overwrite) -{ - if (path == savePath()) return; - path = Utils::Fs::toNativePath(path); - - if (!useTempPath()) { - moveStorage(path, overwrite); - } - else { - m_savePath = path; - m_needSaveResumeData = true; - m_session->handleTorrentSavePathChanged(this); - } -} - -void TorrentHandle::forceReannounce(int index) -{ - m_nativeHandle.force_reannounce(0, index); -} - -void TorrentHandle::forceDHTAnnounce() -{ - m_nativeHandle.force_dht_announce(); -} - -void TorrentHandle::forceRecheck() -{ - if (!hasMetadata()) return; - - if (isPaused()) { - m_pauseAfterRecheck = true; - resume(); - } - - m_nativeHandle.force_recheck(); -} - -void TorrentHandle::setSequentialDownload(bool b) -{ - if (b != isSequentialDownload()) { - m_nativeHandle.set_sequential_download(b); - m_nativeStatus.sequential_download = b; // prevent return cached value - } -} - -void TorrentHandle::toggleSequentialDownload() -{ - setSequentialDownload(!isSequentialDownload()); -} - -void TorrentHandle::setFirstLastPiecePriority(bool b) -{ - if (!hasMetadata()) { - m_needsToSetFirstLastPiecePriority = b; - return; - } - - std::vector fp = m_nativeHandle.file_priorities(); - std::vector pp = m_nativeHandle.piece_priorities(); - - // Download first and last pieces first for all media files in the torrent - int nbfiles = static_cast(fp.size()); - for (int index = 0; index < nbfiles; ++index) { - const QString path = filePath(index); - const QString ext = Utils::Fs::fileExtension(path); - if (Utils::Misc::isPreviewable(ext) && (fp[index] > 0)) { - qDebug() << "File" << path << "is previewable, toggle downloading of first/last pieces first"; - - // Determine the priority to set - int prio = b ? 7 : fp[index]; - - TorrentInfo::PieceRange extremities = info().filePieces(index); - - // worst case: AVI index = 1% of total file size (at the end of the file) - int nNumPieces = ceil(fileSize(index) * 0.01 / pieceLength()); - for (int i = 0; i < nNumPieces; ++i) { - pp[extremities.first() + i] = prio; - pp[extremities.last() - i] = prio; - } - } - } - - m_nativeHandle.prioritize_pieces(pp); -} - -void TorrentHandle::toggleFirstLastPiecePriority() -{ - setFirstLastPiecePriority(!hasFirstLastPiecePriority()); -} - -void TorrentHandle::pause() -{ - if (isPaused()) return; - - m_nativeHandle.auto_managed(false); - m_nativeHandle.pause(); -} - -void TorrentHandle::resume(bool forced) -{ - if (hasError()) - m_nativeHandle.clear_error(); - m_hasMissingFiles = false; - m_nativeHandle.set_upload_mode(false); - m_nativeHandle.auto_managed(!forced); - m_nativeHandle.resume(); -} - -void TorrentHandle::moveStorage(const QString &newPath, bool overwrite) -{ - if (isMoveInProgress()) { - qDebug("enqueue move storage to %s", qPrintable(newPath)); - m_moveStorageInfo.queuedPath = newPath; - m_moveStorageInfo.queuedOverwrite = overwrite; - } - else { - const QString oldPath = nativeActualSavePath(); - if (QDir(oldPath) == QDir(newPath)) return; - - qDebug("move storage: %s to %s", qPrintable(oldPath), qPrintable(newPath)); - // Actually move the storage - m_nativeHandle.move_storage(newPath.toUtf8().constData() - , (overwrite ? libt::always_replace_files : libt::dont_replace)); - m_moveStorageInfo.oldPath = oldPath; - m_moveStorageInfo.newPath = newPath; - } -} - -#if LIBTORRENT_VERSION_NUM < 10100 -void TorrentHandle::setTrackerLogin(const QString &username, const QString &password) -{ - m_nativeHandle.set_tracker_login(std::string(username.toLocal8Bit().constData()) - , std::string(password.toLocal8Bit().constData())); -} -#endif - -void TorrentHandle::renameFile(int index, const QString &name) -{ - ++m_renameCount; - qDebug() << Q_FUNC_INFO << index << name; - m_nativeHandle.rename_file(index, Utils::Fs::toNativePath(name).toStdString()); -} - -bool TorrentHandle::saveTorrentFile(const QString &path) -{ - if (!m_torrentInfo.isValid()) return false; - - libt::create_torrent torrentCreator = makeTorrentCreator(*(m_torrentInfo.nativeInfo())); - libt::entry torrentEntry = torrentCreator.generate(); - - QVector out; - libt::bencode(std::back_inserter(out), torrentEntry); - QFile torrentFile(path); - if (!out.empty() && torrentFile.open(QIODevice::WriteOnly)) - return (torrentFile.write(&out[0], out.size()) == out.size()); - - return false; -} - -void TorrentHandle::setFilePriority(int index, int priority) -{ - std::vector priorities = m_nativeHandle.file_priorities(); - - if ((priorities.size() > static_cast(index)) && (priorities[index] != priority)) { - priorities[index] = priority; - prioritizeFiles(QVector::fromStdVector(priorities)); - } -} - -void TorrentHandle::handleStateUpdate(const libt::torrent_status &nativeStatus) -{ - updateStatus(nativeStatus); -} - -void TorrentHandle::handleStorageMovedAlert(libtorrent::storage_moved_alert *p) -{ - if (!isMoveInProgress()) { - qWarning() << "Unexpected " << Q_FUNC_INFO << " call."; - return; - } - -#if LIBTORRENT_VERSION_NUM < 10100 - const QString newPath = QString::fromStdString(p->path); -#else - const QString newPath(p->storage_path()); -#endif - if (newPath != m_moveStorageInfo.newPath) { - qWarning() << Q_FUNC_INFO << ": New path doesn't match a path in a queue."; - return; - } - - qDebug("Torrent is successfully moved from %s to %s", qPrintable(m_moveStorageInfo.oldPath), qPrintable(m_moveStorageInfo.newPath)); - if (QDir(m_moveStorageInfo.oldPath) == QDir(m_session->torrentTempPath(info()))) { - qDebug() << "Removing torrent temp folder:" << m_moveStorageInfo.oldPath; - Utils::Fs::smartRemoveEmptyFolderTree(m_moveStorageInfo.oldPath); - } - updateStatus(); - - m_moveStorageInfo.newPath.clear(); - if (!m_moveStorageInfo.queuedPath.isEmpty()) { - moveStorage(m_moveStorageInfo.queuedPath, m_moveStorageInfo.queuedOverwrite); - m_moveStorageInfo.queuedPath.clear(); - } - - if (!useTempPath()) { - m_savePath = newPath; - m_session->handleTorrentSavePathChanged(this); - } - - while (!isMoveInProgress() && (m_renameCount == 0) && !m_moveFinishedTriggers.isEmpty()) - m_moveFinishedTriggers.takeFirst()(); -} - -void TorrentHandle::handleStorageMovedFailedAlert(libtorrent::storage_moved_failed_alert *p) -{ - if (!isMoveInProgress()) { - qWarning() << "Unexpected " << Q_FUNC_INFO << " call."; - return; - } - - Logger::instance()->addMessage(tr("Could not move torrent: '%1'. Reason: %2") - .arg(name()).arg(QString::fromStdString(p->message())), Log::CRITICAL); - - m_moveStorageInfo.newPath.clear(); - if (!m_moveStorageInfo.queuedPath.isEmpty()) { - moveStorage(m_moveStorageInfo.queuedPath, m_moveStorageInfo.queuedOverwrite); - m_moveStorageInfo.queuedPath.clear(); - } - - while (!isMoveInProgress() && (m_renameCount == 0) && !m_moveFinishedTriggers.isEmpty()) - m_moveFinishedTriggers.takeFirst()(); -} - -void TorrentHandle::handleTrackerReplyAlert(libtorrent::tracker_reply_alert *p) -{ -#if LIBTORRENT_VERSION_NUM < 10100 - QString trackerUrl = QString::fromStdString(p->url); -#else - QString trackerUrl(p->tracker_url()); -#endif - qDebug("Received a tracker reply from %s (Num_peers = %d)", qPrintable(trackerUrl), p->num_peers); - // Connection was successful now. Remove possible old errors - m_trackerInfos[trackerUrl].lastMessage.clear(); // Reset error/warning message - m_trackerInfos[trackerUrl].numPeers = p->num_peers; - - m_session->handleTorrentTrackerReply(this, trackerUrl); -} - -void TorrentHandle::handleTrackerWarningAlert(libtorrent::tracker_warning_alert *p) -{ -#if LIBTORRENT_VERSION_NUM < 10100 - QString trackerUrl = QString::fromStdString(p->url); - QString message = QString::fromStdString(p->msg); -#else - QString trackerUrl(p->tracker_url()); - QString message = QString::fromStdString(p->message()); -#endif - qDebug("Received a tracker warning for %s: %s", qPrintable(trackerUrl), qPrintable(message)); - // Connection was successful now but there is a warning message - m_trackerInfos[trackerUrl].lastMessage = message; // Store warning message - - m_session->handleTorrentTrackerWarning(this, trackerUrl); -} - -void TorrentHandle::handleTrackerErrorAlert(libtorrent::tracker_error_alert *p) -{ -#if LIBTORRENT_VERSION_NUM < 10100 - QString trackerUrl = QString::fromStdString(p->url); - QString message = QString::fromStdString(p->msg); -#else - QString trackerUrl(p->tracker_url()); - QString message = QString::fromStdString(p->message()); -#endif - qDebug("Received a tracker error for %s: %s", qPrintable(trackerUrl), qPrintable(message)); - m_trackerInfos[trackerUrl].lastMessage = message; - - if (p->status_code == 401) - m_session->handleTorrentTrackerAuthenticationRequired(this, trackerUrl); - - m_session->handleTorrentTrackerError(this, trackerUrl); -} - -void TorrentHandle::handleTorrentCheckedAlert(libtorrent::torrent_checked_alert *p) -{ - Q_UNUSED(p); - qDebug("%s have just finished checking", qPrintable(hash())); - - updateStatus(); - - if ((progress() < 1.0) && (wantedSize() > 0)) - m_hasSeedStatus = false; - else if (progress() == 1.0) - m_hasSeedStatus = true; - - adjustActualSavePath(); - manageIncompleteFiles(); - - if (m_pauseAfterRecheck) { - m_pauseAfterRecheck = false; - pause(); - } - - m_session->handleTorrentChecked(this); -} - -void TorrentHandle::handleTorrentFinishedAlert(libtorrent::torrent_finished_alert *p) -{ - Q_UNUSED(p); - qDebug("Got a torrent finished alert for %s", qPrintable(name())); - qDebug("Torrent has seed status: %s", m_hasSeedStatus ? "yes" : "no"); - if (m_hasSeedStatus) return; - - updateStatus(); - m_hasMissingFiles = false; - m_hasSeedStatus = true; - - adjustActualSavePath(); - manageIncompleteFiles(); - - const bool recheckTorrentsOnCompletion = Preferences::instance()->recheckTorrentsOnCompletion(); - if (isMoveInProgress() || m_renameCount > 0) { - if (recheckTorrentsOnCompletion) - m_moveFinishedTriggers.append(boost::bind(&TorrentHandle::forceRecheck, this)); - m_moveFinishedTriggers.append(boost::bind(&Session::handleTorrentFinished, m_session, this)); - } - else { - if (recheckTorrentsOnCompletion) - forceRecheck(); - m_session->handleTorrentFinished(this); - } -} - -void TorrentHandle::handleTorrentPausedAlert(libtorrent::torrent_paused_alert *p) -{ - Q_UNUSED(p); - updateStatus(); - m_speedMonitor.reset(); - m_session->handleTorrentPaused(this); -} - -void TorrentHandle::handleTorrentResumedAlert(libtorrent::torrent_resumed_alert *p) -{ - Q_UNUSED(p); - m_session->handleTorrentResumed(this); -} - -void TorrentHandle::handleSaveResumeDataAlert(libtorrent::save_resume_data_alert *p) -{ - const bool useDummyResumeData = !(p && p->resume_data); - libtorrent::entry dummyEntry; - - libtorrent::entry &resumeData = useDummyResumeData ? dummyEntry : *(p->resume_data); - if (useDummyResumeData) { - resumeData["qBt-magnetUri"] = toMagnetUri().toStdString(); - resumeData["qBt-paused"] = isPaused(); - resumeData["qBt-forced"] = isForced(); - // Both firstLastPiecePriority and sequential need to be stored in the - // resume data if there is no metadata, otherwise they won't be - // restored if qBittorrent quits before the metadata are retrieved: - resumeData["qBt-firstLastPiecePriority"] = hasFirstLastPiecePriority(); - resumeData["qBt-sequential"] = isSequentialDownload(); - } - else { - auto savePath = resumeData.find_key("save_path")->string(); - resumeData["save_path"] = Profile::instance().toPortablePath(QString::fromStdString(savePath)).toStdString(); - } - resumeData["qBt-savePath"] = m_useAutoTMM ? "" : Profile::instance().toPortablePath(m_savePath).toStdString(); - resumeData["qBt-ratioLimit"] = QString::number(m_ratioLimit).toStdString(); - resumeData["qBt-seedingTimeLimit"] = QString::number(m_seedingTimeLimit).toStdString(); - resumeData["qBt-category"] = m_category.toStdString(); - resumeData["qBt-tags"] = setToEntryList(m_tags); - resumeData["qBt-name"] = m_name.toStdString(); - resumeData["qBt-seedStatus"] = m_hasSeedStatus; - resumeData["qBt-tempPathDisabled"] = m_tempPathDisabled; - resumeData["qBt-queuePosition"] = queuePosition(); - resumeData["qBt-hasRootFolder"] = m_hasRootFolder; - - m_session->handleTorrentResumeDataReady(this, resumeData); -} - -void TorrentHandle::handleSaveResumeDataFailedAlert(libtorrent::save_resume_data_failed_alert *p) -{ - // if torrent has no metadata we should save dummy fastresume data - // containing Magnet URI and qBittorrent own resume data only - if (p->error.value() == libt::errors::no_metadata) - handleSaveResumeDataAlert(0); - else - m_session->handleTorrentResumeDataFailed(this); -} - -void TorrentHandle::handleFastResumeRejectedAlert(libtorrent::fastresume_rejected_alert *p) -{ - qDebug("/!\\ Fast resume failed for %s, reason: %s", qPrintable(name()), p->message().c_str()); - Logger *const logger = Logger::instance(); - - updateStatus(); - if (p->error.value() == libt::errors::mismatching_file_size) { - // Mismatching file size (files were probably moved) - logger->addMessage(tr("File sizes mismatch for torrent '%1', pausing it.").arg(name()), Log::CRITICAL); - m_hasMissingFiles = true; - if (!isPaused()) - pause(); - } - else { - logger->addMessage(tr("Fast resume data was rejected for torrent '%1'. Reason: %2. Checking again...") - .arg(name()).arg(QString::fromStdString(p->message())), Log::CRITICAL); - } -} - -void TorrentHandle::handleFileRenamedAlert(libtorrent::file_renamed_alert *p) -{ -#if LIBTORRENT_VERSION_NUM < 10100 - QString newName = Utils::Fs::fromNativePath(QString::fromStdString(p->name)); -#else - QString newName = Utils::Fs::fromNativePath(p->new_name()); -#endif - - // TODO: Check this! - if (filesCount() > 1) { - // Check if folders were renamed - QStringList oldPathParts = m_torrentInfo.origFilePath(p->index).split("/"); - oldPathParts.removeLast(); - QString oldPath = oldPathParts.join("/"); - QStringList newPathParts = newName.split("/"); - newPathParts.removeLast(); - QString newPath = newPathParts.join("/"); - if (!newPathParts.isEmpty() && (oldPath != newPath)) { - qDebug("oldPath(%s) != newPath(%s)", qPrintable(oldPath), qPrintable(newPath)); - oldPath = QString("%1/%2").arg(savePath(true)).arg(oldPath); - qDebug("Detected folder renaming, attempt to delete old folder: %s", qPrintable(oldPath)); - QDir().rmpath(oldPath); - } - } - - updateStatus(); - - --m_renameCount; - while (!isMoveInProgress() && (m_renameCount == 0) && !m_moveFinishedTriggers.isEmpty()) - m_moveFinishedTriggers.takeFirst()(); -} - -void TorrentHandle::handleFileRenameFailedAlert(libtorrent::file_rename_failed_alert *p) -{ - Q_UNUSED(p); - - --m_renameCount; - while (!isMoveInProgress() && (m_renameCount == 0) && !m_moveFinishedTriggers.isEmpty()) - m_moveFinishedTriggers.takeFirst()(); -} - -void TorrentHandle::handleFileCompletedAlert(libtorrent::file_completed_alert *p) -{ - updateStatus(); - - qDebug("A file completed download in torrent \"%s\"", qPrintable(name())); - if (m_session->isAppendExtensionEnabled()) { - QString name = filePath(p->index); - if (name.endsWith(QB_EXT)) { - const QString oldName = name; - name.chop(QB_EXT.size()); - qDebug("Renaming %s to %s", qPrintable(oldName), qPrintable(name)); - renameFile(p->index, name); - } - } -} - -void TorrentHandle::handleStatsAlert(libtorrent::stats_alert *p) -{ - Q_ASSERT(p->interval >= 1000); - SpeedSample transferred(p->transferred[libt::stats_alert::download_payload] * 1000LL / p->interval, - p->transferred[libt::stats_alert::upload_payload] * 1000LL / p->interval); - m_speedMonitor.addSample(transferred); -} - -void TorrentHandle::handleMetadataReceivedAlert(libt::metadata_received_alert *p) -{ - Q_UNUSED(p); - qDebug("Metadata received for torrent %s.", qPrintable(name())); - updateStatus(); - if (m_session->isAppendExtensionEnabled()) - manageIncompleteFiles(); - if (!m_hasRootFolder) - m_torrentInfo.stripRootFolder(); - if (filesCount() == 1) - m_hasRootFolder = false; - m_session->handleTorrentMetadataReceived(this); - - if (isPaused()) { - // XXX: Unfortunately libtorrent-rasterbar does not send a torrent_paused_alert - // and the torrent can be paused when metadata is received - m_speedMonitor.reset(); - m_session->handleTorrentPaused(this); - } - - // If first/last piece priority was specified when adding this torrent, we can set it - // now that we have metadata: - if (m_needsToSetFirstLastPiecePriority) { - setFirstLastPiecePriority(true); - m_needsToSetFirstLastPiecePriority = false; - } -} - -void TorrentHandle::handleTempPathChanged() -{ - adjustActualSavePath(); -} - -void TorrentHandle::handleCategorySavePathChanged() -{ - if (m_useAutoTMM) - move_impl(m_session->categorySavePath(m_category), true); -} - -void TorrentHandle::handleAppendExtensionToggled() -{ - if (!hasMetadata()) return; - - manageIncompleteFiles(); -} - -void TorrentHandle::handleAlert(libtorrent::alert *a) -{ - switch (a->type()) { - case libt::stats_alert::alert_type: - handleStatsAlert(static_cast(a)); - break; - case libt::file_renamed_alert::alert_type: - handleFileRenamedAlert(static_cast(a)); - break; - case libt::file_rename_failed_alert::alert_type: - handleFileRenameFailedAlert(static_cast(a)); - break; - case libt::file_completed_alert::alert_type: - handleFileCompletedAlert(static_cast(a)); - break; - case libt::torrent_finished_alert::alert_type: - handleTorrentFinishedAlert(static_cast(a)); - break; - case libt::save_resume_data_alert::alert_type: - handleSaveResumeDataAlert(static_cast(a)); - break; - case libt::save_resume_data_failed_alert::alert_type: - handleSaveResumeDataFailedAlert(static_cast(a)); - break; - case libt::storage_moved_alert::alert_type: - handleStorageMovedAlert(static_cast(a)); - break; - case libt::storage_moved_failed_alert::alert_type: - handleStorageMovedFailedAlert(static_cast(a)); - break; - case libt::torrent_paused_alert::alert_type: - handleTorrentPausedAlert(static_cast(a)); - break; - case libt::tracker_error_alert::alert_type: - handleTrackerErrorAlert(static_cast(a)); - break; - case libt::tracker_reply_alert::alert_type: - handleTrackerReplyAlert(static_cast(a)); - break; - case libt::tracker_warning_alert::alert_type: - handleTrackerWarningAlert(static_cast(a)); - break; - case libt::metadata_received_alert::alert_type: - handleMetadataReceivedAlert(static_cast(a)); - break; - case libt::fastresume_rejected_alert::alert_type: - handleFastResumeRejectedAlert(static_cast(a)); - break; - case libt::torrent_checked_alert::alert_type: - handleTorrentCheckedAlert(static_cast(a)); - break; - } -} - -void TorrentHandle::manageIncompleteFiles() -{ - const bool isAppendExtensionEnabled = m_session->isAppendExtensionEnabled(); - QVector fp = filesProgress(); - if( fp.size() != filesCount() ) { - qDebug() << "skip manageIncompleteFiles because of invalid torrent meta-data or empty file-progress"; - return; - } - - for (int i = 0; i < filesCount(); ++i) { - QString name = filePath(i); - if (isAppendExtensionEnabled && (fileSize(i) > 0) && (fp[i] < 1)) { - if (!name.endsWith(QB_EXT)) { - const QString newName = name + QB_EXT; - qDebug() << "Renaming" << name << "to" << newName; - renameFile(i, newName); - } - } - else { - if (name.endsWith(QB_EXT)) { - const QString oldName = name; - name.chop(QB_EXT.size()); - qDebug() << "Renaming" << oldName << "to" << name; - renameFile(i, name); - } - } - } -} - -void TorrentHandle::adjustActualSavePath() -{ - if (!isMoveInProgress()) - adjustActualSavePath_impl(); - else - m_moveFinishedTriggers.append(boost::bind(&TorrentHandle::adjustActualSavePath_impl, this)); -} - -void TorrentHandle::adjustActualSavePath_impl() -{ - QString path; - if (!useTempPath()) { - // Disabling temp dir - // Moving all torrents to their destination folder - path = savePath(); - } - else { - // Moving all downloading torrents to temporary folder - path = m_session->torrentTempPath(info()); - qDebug() << "Moving torrent to its temporary folder:" << path; - } - - moveStorage(Utils::Fs::toNativePath(path), true); -} - -libtorrent::torrent_handle TorrentHandle::nativeHandle() const -{ - return m_nativeHandle; -} - -void TorrentHandle::updateTorrentInfo() -{ - if (!hasMetadata()) return; -#if LIBTORRENT_VERSION_NUM < 10100 - m_torrentInfo = TorrentInfo(m_nativeStatus.torrent_file); -#else - m_torrentInfo = TorrentInfo(m_nativeStatus.torrent_file.lock()); -#endif -} - -bool TorrentHandle::isMoveInProgress() const -{ - return !m_moveStorageInfo.newPath.isEmpty(); -} - -bool TorrentHandle::useTempPath() const -{ - return !m_tempPathDisabled && m_session->isTempPathEnabled() && !(isSeed() || m_hasSeedStatus); -} - -void TorrentHandle::updateStatus() -{ - updateStatus(m_nativeHandle.status()); -} - -void TorrentHandle::updateStatus(const libtorrent::torrent_status &nativeStatus) -{ - m_nativeStatus = nativeStatus; - - updateState(); - updateTorrentInfo(); -} - -void TorrentHandle::setRatioLimit(qreal limit) -{ - if (limit < USE_GLOBAL_RATIO) - limit = NO_RATIO_LIMIT; - else if (limit > MAX_RATIO) - limit = MAX_RATIO; - - if (m_ratioLimit != limit) { - m_ratioLimit = limit; - m_needSaveResumeData = true; - m_session->handleTorrentShareLimitChanged(this); - } -} - -void TorrentHandle::setSeedingTimeLimit(int limit) -{ - if (limit < USE_GLOBAL_SEEDING_TIME) - limit = NO_SEEDING_TIME_LIMIT; - else if (limit > MAX_SEEDING_TIME) - limit = MAX_SEEDING_TIME; - - if (m_seedingTimeLimit != limit) { - m_seedingTimeLimit = limit; - m_needSaveResumeData = true; - m_session->handleTorrentShareLimitChanged(this); - } -} - -void TorrentHandle::setUploadLimit(int limit) -{ - m_nativeHandle.set_upload_limit(limit); -} - -void TorrentHandle::setDownloadLimit(int limit) -{ - m_nativeHandle.set_download_limit(limit); -} - -void TorrentHandle::setSuperSeeding(bool enable) -{ - m_nativeHandle.super_seeding(enable); - if (superSeeding() != enable) - updateStatus(); -} - -void TorrentHandle::flushCache() -{ - m_nativeHandle.flush_cache(); -} - -QString TorrentHandle::toMagnetUri() const -{ - return QString::fromStdString(libt::make_magnet_uri(m_nativeHandle)); -} - -void TorrentHandle::prioritizeFiles(const QVector &priorities) -{ - if (!hasMetadata()) return; - if (priorities.size() != filesCount()) return; - - // Save first/last piece first option state - bool firstLastPieceFirst = hasFirstLastPiecePriority(); - - // Reset 'm_hasSeedStatus' if needed in order to react again to - // 'torrent_finished_alert' and eg show tray notifications - QVector progress = filesProgress(); - QVector oldPriorities = filePriorities(); - for (int i = 0; i < oldPriorities.size(); ++i) { - if ((oldPriorities[i] == 0) && (priorities[i] > 0) && (progress[i] < 1.0)) { - m_hasSeedStatus = false; - break; - } - } - - qDebug() << Q_FUNC_INFO << "Changing files priorities..."; - m_nativeHandle.prioritize_files(priorities.toStdVector()); - - qDebug() << Q_FUNC_INFO << "Moving unwanted files to .unwanted folder and conversely..."; - QString spath = savePath(true); - for (int i = 0; i < priorities.size(); ++i) { - QString filepath = filePath(i); - // Move unwanted files to a .unwanted subfolder - if (priorities[i] == 0) { - QString oldAbsPath = QDir(spath).absoluteFilePath(filepath); - QString parentAbsPath = Utils::Fs::branchPath(oldAbsPath); - // Make sure the file does not already exists - if (QDir(parentAbsPath).dirName() != ".unwanted") { - QString unwantedAbsPath = parentAbsPath + "/.unwanted"; - QString newAbsPath = unwantedAbsPath + "/" + Utils::Fs::fileName(filepath); - qDebug() << "Unwanted path is" << unwantedAbsPath; - if (QFile::exists(newAbsPath)) { - qWarning() << "File" << newAbsPath << "already exists at destination."; - continue; - } - - bool created = QDir().mkpath(unwantedAbsPath); - qDebug() << "unwanted folder was created:" << created; -#ifdef Q_OS_WIN - if (created) { - // Hide the folder on Windows - qDebug() << "Hiding folder (Windows)"; - std::wstring winPath = Utils::Fs::toNativePath(unwantedAbsPath).toStdWString(); - DWORD dwAttrs = ::GetFileAttributesW(winPath.c_str()); - bool ret = ::SetFileAttributesW(winPath.c_str(), dwAttrs | FILE_ATTRIBUTE_HIDDEN); - Q_ASSERT(ret != 0); Q_UNUSED(ret); - } -#endif - QString parentPath = Utils::Fs::branchPath(filepath); - if (!parentPath.isEmpty() && !parentPath.endsWith("/")) - parentPath += "/"; - renameFile(i, parentPath + ".unwanted/" + Utils::Fs::fileName(filepath)); - } - } - - // Move wanted files back to their original folder - if (priorities[i] > 0) { - QString parentRelPath = Utils::Fs::branchPath(filepath); - if (QDir(parentRelPath).dirName() == ".unwanted") { - QString oldName = Utils::Fs::fileName(filepath); - QString newRelPath = Utils::Fs::branchPath(parentRelPath); - if (newRelPath.isEmpty()) - renameFile(i, oldName); - else - renameFile(i, QDir(newRelPath).filePath(oldName)); - - // Remove .unwanted directory if empty - qDebug() << "Attempting to remove .unwanted folder at " << QDir(spath + "/" + newRelPath).absoluteFilePath(".unwanted"); - QDir(spath + "/" + newRelPath).rmdir(".unwanted"); - } - } - } - - // Restore first/last piece first option if necessary - if (firstLastPieceFirst) - setFirstLastPiecePriority(true); - - updateStatus(); -} - -QVector TorrentHandle::availableFileFractions() const -{ - const auto filesCount = this->filesCount(); - if (filesCount < 0) return {}; - - const QVector piecesAvailability = pieceAvailability(); - // libtorrent returns empty array for seeding only torrents - if (piecesAvailability.empty()) return QVector(filesCount, -1.); - - QVector res; - res.reserve(filesCount); - TorrentInfo info = this->info(); - for (int file = 0; file < filesCount; ++file) { - TorrentInfo::PieceRange filePieces = info.filePieces(file); - int availablePieces = 0; - for (int piece = filePieces.first(); piece <= filePieces.last(); ++piece) { - availablePieces += piecesAvailability[piece] > 0 ? 1 : 0; - } - res.push_back(static_cast(availablePieces) / filePieces.size()); - } - return res; -} diff --git a/src/base/bittorrent/torrenthandle.h b/src/base/bittorrent/torrenthandle.h deleted file mode 100644 index b6aa59c86..000000000 --- a/src/base/bittorrent/torrenthandle.h +++ /dev/null @@ -1,477 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2015 Vladimir Golovnev - * Copyright (C) 2006 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. - */ - -#ifndef BITTORRENT_TORRENTHANDLE_H -#define BITTORRENT_TORRENTHANDLE_H - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#if LIBTORRENT_VERSION_NUM >= 10100 -#include -#endif - -#include - -#include "base/tristatebool.h" -#include "private/speedmonitor.h" -#include "infohash.h" -#include "torrentinfo.h" - -class QBitArray; -class QStringList; -template struct QPair; - -extern const QString QB_EXT; - -namespace libtorrent -{ - class alert; - struct stats_alert; - struct torrent_checked_alert; - struct torrent_finished_alert; - struct torrent_paused_alert; - struct torrent_resumed_alert; - struct save_resume_data_alert; - struct save_resume_data_failed_alert; - struct file_renamed_alert; - struct file_rename_failed_alert; - struct storage_moved_alert; - struct storage_moved_failed_alert; - struct metadata_received_alert; - struct file_completed_alert; - struct tracker_error_alert; - struct tracker_reply_alert; - struct tracker_warning_alert; - struct fastresume_rejected_alert; - struct torrent_status; -} - -namespace BitTorrent -{ - struct PeerAddress; - class Session; - class PeerInfo; - class TrackerEntry; - struct AddTorrentParams; - - struct AddTorrentData - { - bool resumed; - // for both new and resumed torrents - QString name; - QString category; - QSet tags; - QString savePath; - bool disableTempPath; - bool sequential; - bool firstLastPiecePriority; - bool hasSeedStatus; - bool skipChecking; - bool hasRootFolder; - bool addForced; - bool addPaused; - // for new torrents - QVector filePriorities; - // for resumed torrents - qreal ratioLimit; - int seedingTimeLimit; - - AddTorrentData(); - AddTorrentData(const AddTorrentParams ¶ms); - }; - - struct TrackerInfo - { - QString lastMessage; - quint32 numPeers = 0; - }; - - class TorrentState - { - public: - enum - { - Unknown = -1, - - ForcedDownloading, - Downloading, - DownloadingMetadata, - Allocating, - StalledDownloading, - - ForcedUploading, - Uploading, - StalledUploading, - - QueuedDownloading, - QueuedUploading, - - CheckingUploading, - CheckingDownloading, - -#if LIBTORRENT_VERSION_NUM < 10100 - QueuedForChecking, -#endif - CheckingResumeData, - - PausedDownloading, - PausedUploading, - - MissingFiles, - Error - }; - - TorrentState(int value); - - operator int() const; - QString toString() const; - - private: - int m_value; - }; - - class TorrentHandle : public QObject - { - Q_DISABLE_COPY(TorrentHandle) - - public: - static const qreal USE_GLOBAL_RATIO; - static const qreal NO_RATIO_LIMIT; - - static const int USE_GLOBAL_SEEDING_TIME; - static const int NO_SEEDING_TIME_LIMIT; - - static const qreal MAX_RATIO; - static const int MAX_SEEDING_TIME; - - TorrentHandle(Session *session, const libtorrent::torrent_handle &nativeHandle, - const AddTorrentData &data); - ~TorrentHandle(); - - bool isValid() const; - InfoHash hash() const; - QString name() const; - QDateTime creationDate() const; - QString creator() const; - QString comment() const; - bool isPrivate() const; - qlonglong totalSize() const; - qlonglong wantedSize() const; - qlonglong completedSize() const; - qlonglong incompletedSize() const; - qlonglong pieceLength() const; - qlonglong wastedSize() const; - QString currentTracker() const; - - // 1. savePath() - the path where all the files and subfolders of torrent are stored (as always). - // 2. rootPath() - absolute path of torrent file tree (save path + first item from 1st torrent file path). - // 3. contentPath() - absolute path of torrent content (root path for multifile torrents, absolute file path for singlefile torrents). - // - // These methods have 'actual' parameter (defaults to false) which allow to get actual or final path variant. - // - // Examples. - // Suppose we have three torrent with following structures and save path `/home/user/torrents`: - // - // Torrent A (multifile) - // - // torrentA/ - // subdir1/ - // subdir2/ - // file1 - // file2 - // file3 - // file4 - // - // - // Torrent A* (Torrent A in "strip root folder" mode) - // - // - // Torrent B (singlefile) - // - // torrentB/ - // subdir1/ - // file1 - // - // - // Torrent C (singlefile) - // - // file1 - // - // - // Results: - // | | rootPath | contentPath | - // |---|------------------------------|--------------------------------------------| - // | A | /home/user/torrents/torrentA | /home/user/torrents/torrentA | - // | A*| | /home/user/torrents | - // | B | /home/user/torrents/torrentB | /home/user/torrents/torrentB/subdir1/file1 | - // | C | /home/user/torrents/file1 | /home/user/torrents/file1 | - - QString savePath(bool actual = false) const; - QString rootPath(bool actual = false) const; - QString contentPath(bool actual = false) const; - - bool useTempPath() const; - - bool isAutoTMMEnabled() const; - void setAutoTMMEnabled(bool enabled); - QString category() const; - bool belongsToCategory(const QString &category) const; - bool setCategory(const QString &category); - - QSet tags() const; - bool hasTag(const QString &tag) const; - bool addTag(const QString &tag); - bool removeTag(const QString &tag); - void removeAllTags(); - - bool hasRootFolder() const; - - int filesCount() const; - int piecesCount() const; - int piecesHave() const; - qreal progress() const; - QDateTime addedTime() const; - qreal ratioLimit() const; - int seedingTimeLimit() const; - - QString filePath(int index) const; - QString fileName(int index) const; - qlonglong fileSize(int index) const; - QStringList absoluteFilePaths() const; - QStringList absoluteFilePathsUnwanted() const; - QVector filePriorities() const; - - TorrentInfo info() const; - bool isSeed() const; - bool isPaused() const; - bool isResumed() const; - bool isQueued() const; - bool isForced() const; - bool isChecking() const; - bool isDownloading() const; - bool isUploading() const; - bool isCompleted() const; - bool isActive() const; - bool isInactive() const; - bool isErrored() const; - bool isSequentialDownload() const; - bool hasFirstLastPiecePriority() const; - TorrentState state() const; - bool hasMetadata() const; - bool hasMissingFiles() const; - bool hasError() const; - bool hasFilteredPieces() const; - int queuePosition() const; - QList trackers() const; - QHash trackerInfos() const; - QList urlSeeds() const; - QString error() const; - qlonglong totalDownload() const; - qlonglong totalUpload() const; - int activeTime() const; - int finishedTime() const; - int seedingTime() const; - qulonglong eta() const; - QVector filesProgress() const; - int seedsCount() const; - int peersCount() const; - int leechsCount() const; - int totalSeedsCount() const; - int totalPeersCount() const; - int totalLeechersCount() const; - int completeCount() const; - int incompleteCount() const; - QDateTime lastSeenComplete() const; - QDateTime completedTime() const; - int timeSinceUpload() const; - int timeSinceDownload() const; - int timeSinceActivity() const; - int downloadLimit() const; - int uploadLimit() const; - bool superSeeding() const; - QList peers() const; - QBitArray pieces() const; - QBitArray downloadingPieces() const; - QVector pieceAvailability() const; - qreal distributedCopies() const; - qreal maxRatio(bool *usesGlobalRatio = 0) const; - int maxSeedingTime(bool *usesGlobalSeedingTime = 0) const; - qreal realRatio() const; - int uploadPayloadRate() const; - int downloadPayloadRate() const; - qlonglong totalPayloadUpload() const; - qlonglong totalPayloadDownload() const; - int connectionsCount() const; - int connectionsLimit() const; - qlonglong nextAnnounce() const; - - void setName(const QString &name); - void setSequentialDownload(bool b); - void toggleSequentialDownload(); - void setFirstLastPiecePriority(bool b); - void toggleFirstLastPiecePriority(); - void pause(); - void resume(bool forced = false); - void move(QString path); - void forceReannounce(int index = -1); - void forceDHTAnnounce(); - void forceRecheck(); -#if LIBTORRENT_VERSION_NUM < 10100 - void setTrackerLogin(const QString &username, const QString &password); -#endif - void renameFile(int index, const QString &name); - bool saveTorrentFile(const QString &path); - void prioritizeFiles(const QVector &priorities); - void setFilePriority(int index, int priority); - void setRatioLimit(qreal limit); - void setSeedingTimeLimit(int limit); - void setUploadLimit(int limit); - void setDownloadLimit(int limit); - void setSuperSeeding(bool enable); - void flushCache(); - void addTrackers(const QList &trackers); - void replaceTrackers(QList trackers); - void addUrlSeeds(const QList &urlSeeds); - void removeUrlSeeds(const QList &urlSeeds); - bool connectPeer(const PeerAddress &peerAddress); - - QString toMagnetUri() const; - - bool needSaveResumeData() const; - - // Session interface - libtorrent::torrent_handle nativeHandle() const; - - void handleAlert(libtorrent::alert *a); - void handleStateUpdate(const libtorrent::torrent_status &nativeStatus); - void handleTempPathChanged(); - void handleCategorySavePathChanged(); - void handleAppendExtensionToggled(); - void saveResumeData(bool updateStatus = false); - - /** - * @brief fraction of file pieces that are available at least from one peer - * - * This is not the same as torrrent availability, it is just a fraction of pieces - * that can be downloaded right now. It varies between 0 to 1. - */ - QVector availableFileFractions() const; - - private: - typedef boost::function EventTrigger; - - void updateStatus(); - void updateStatus(const libtorrent::torrent_status &nativeStatus); - void updateState(); - void updateTorrentInfo(); - - void handleStorageMovedAlert(libtorrent::storage_moved_alert *p); - void handleStorageMovedFailedAlert(libtorrent::storage_moved_failed_alert *p); - void handleTrackerReplyAlert(libtorrent::tracker_reply_alert *p); - void handleTrackerWarningAlert(libtorrent::tracker_warning_alert *p); - void handleTrackerErrorAlert(libtorrent::tracker_error_alert *p); - void handleTorrentCheckedAlert(libtorrent::torrent_checked_alert *p); - void handleTorrentFinishedAlert(libtorrent::torrent_finished_alert *p); - void handleTorrentPausedAlert(libtorrent::torrent_paused_alert *p); - void handleTorrentResumedAlert(libtorrent::torrent_resumed_alert *p); - void handleSaveResumeDataAlert(libtorrent::save_resume_data_alert *p); - void handleSaveResumeDataFailedAlert(libtorrent::save_resume_data_failed_alert *p); - void handleFastResumeRejectedAlert(libtorrent::fastresume_rejected_alert *p); - void handleFileRenamedAlert(libtorrent::file_renamed_alert *p); - void handleFileRenameFailedAlert(libtorrent::file_rename_failed_alert *p); - void handleFileCompletedAlert(libtorrent::file_completed_alert *p); - void handleMetadataReceivedAlert(libtorrent::metadata_received_alert *p); - void handleStatsAlert(libtorrent::stats_alert *p); - - bool isMoveInProgress() const; - QString nativeActualSavePath() const; - - void adjustActualSavePath(); - void adjustActualSavePath_impl(); - void move_impl(QString path, bool overwrite); - void moveStorage(const QString &newPath, bool overwrite); - void manageIncompleteFiles(); - bool addTracker(const TrackerEntry &tracker); - bool addUrlSeed(const QUrl &urlSeed); - bool removeUrlSeed(const QUrl &urlSeed); - - Session *const m_session; - libtorrent::torrent_handle m_nativeHandle; - libtorrent::torrent_status m_nativeStatus; - TorrentState m_state; - TorrentInfo m_torrentInfo; - SpeedMonitor m_speedMonitor; - - InfoHash m_hash; - - struct - { - QString oldPath; - QString newPath; - // queuedPath is where files should be moved to, - // when current moving is completed - QString queuedPath; - bool queuedOverwrite = true; - } m_moveStorageInfo; - - // m_moveFinishedTriggers is activated only when the following conditions are met: - // all file rename jobs complete, all file move jobs complete - QQueue m_moveFinishedTriggers; - int m_renameCount; - - bool m_useAutoTMM; - - // Persistent data - QString m_name; - QString m_savePath; - QString m_category; - QSet m_tags; - bool m_hasSeedStatus; - qreal m_ratioLimit; - int m_seedingTimeLimit; - bool m_tempPathDisabled; - bool m_hasMissingFiles; - bool m_hasRootFolder; - bool m_needsToSetFirstLastPiecePriority; - - bool m_pauseAfterRecheck; - bool m_needSaveResumeData; - QHash m_trackerInfos; - }; -} - -#endif // BITTORRENT_TORRENTHANDLE_H diff --git a/src/base/bittorrent/torrentinfo.cpp b/src/base/bittorrent/torrentinfo.cpp deleted file mode 100644 index 03eabe8c8..000000000 --- a/src/base/bittorrent/torrentinfo.cpp +++ /dev/null @@ -1,352 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2015 Vladimir Golovnev - * - * 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. - */ - -#include -#include -#include -#include -#include - -#include - -#include "base/utils/misc.h" -#include "base/utils/fs.h" -#include "base/utils/string.h" -#include "infohash.h" -#include "trackerentry.h" -#include "torrentinfo.h" - -namespace libt = libtorrent; -using namespace BitTorrent; - -TorrentInfo::TorrentInfo(NativeConstPtr nativeInfo) -{ - m_nativeInfo = boost::const_pointer_cast(nativeInfo); -} - -TorrentInfo::TorrentInfo(const TorrentInfo &other) - : m_nativeInfo(other.m_nativeInfo) -{ -} - -TorrentInfo &TorrentInfo::operator=(const TorrentInfo &other) -{ - m_nativeInfo = other.m_nativeInfo; - return *this; -} - -TorrentInfo TorrentInfo::loadFromFile(const QString &path, QString &error) -{ - error.clear(); - libt::error_code ec; - TorrentInfo info(NativePtr(new libt::torrent_info(Utils::Fs::toNativePath(path).toStdString(), ec))); - if (ec) { - error = QString::fromUtf8(ec.message().c_str()); - qDebug("Cannot load .torrent file: %s", qPrintable(error)); - } - - return info; -} - -TorrentInfo TorrentInfo::loadFromFile(const QString &path) -{ - QString error; - return loadFromFile(path, error); -} - -bool TorrentInfo::isValid() const -{ - return (m_nativeInfo && m_nativeInfo->is_valid() && (m_nativeInfo->num_files() > 0)); -} - -InfoHash TorrentInfo::hash() const -{ - if (!isValid()) return InfoHash(); - return m_nativeInfo->info_hash(); -} - -QString TorrentInfo::name() const -{ - if (!isValid()) return QString(); - return QString::fromStdString(m_nativeInfo->name()); -} - -QDateTime TorrentInfo::creationDate() const -{ - if (!isValid()) return QDateTime(); - boost::optional t = m_nativeInfo->creation_date(); - return t ? QDateTime::fromTime_t(*t) : QDateTime(); -} - -QString TorrentInfo::creator() const -{ - if (!isValid()) return QString(); - return QString::fromStdString(m_nativeInfo->creator()); -} - -QString TorrentInfo::comment() const -{ - if (!isValid()) return QString(); - return QString::fromStdString(m_nativeInfo->comment()); -} - -bool TorrentInfo::isPrivate() const -{ - if (!isValid()) return false; - return m_nativeInfo->priv(); -} - -qlonglong TorrentInfo::totalSize() const -{ - if (!isValid()) return -1; - return m_nativeInfo->total_size(); -} - -int TorrentInfo::filesCount() const -{ - if (!isValid()) return -1; - return m_nativeInfo->num_files(); -} - -int TorrentInfo::pieceLength() const -{ - if (!isValid()) return -1; - return m_nativeInfo->piece_length(); -} - -int TorrentInfo::pieceLength(int index) const -{ - if (!isValid()) return -1; - return m_nativeInfo->piece_size(index); -} - -int TorrentInfo::piecesCount() const -{ - if (!isValid()) return -1; - return m_nativeInfo->num_pieces(); -} - -QString TorrentInfo::filePath(int index) const -{ - if (!isValid()) return QString(); - return Utils::Fs::fromNativePath(QString::fromStdString(m_nativeInfo->files().file_path(index))); -} - -QStringList TorrentInfo::filePaths() const -{ - QStringList list; - for (int i = 0; i < filesCount(); ++i) - list << filePath(i); - - return list; -} - -QString TorrentInfo::fileName(int index) const -{ - return Utils::Fs::fileName(filePath(index)); -} - -QString TorrentInfo::origFilePath(int index) const -{ - if (!isValid()) return QString(); - return Utils::Fs::fromNativePath(QString::fromStdString(m_nativeInfo->orig_files().file_path(index))); -} - -qlonglong TorrentInfo::fileSize(int index) const -{ - if (!isValid()) return -1; - return m_nativeInfo->files().file_size(index); -} - -qlonglong TorrentInfo::fileOffset(int index) const -{ - if (!isValid()) return -1; - return m_nativeInfo->files().file_offset(index); -} - -QList TorrentInfo::trackers() const -{ - if (!isValid()) return QList(); - - QList trackers; - foreach (const libt::announce_entry &tracker, m_nativeInfo->trackers()) - trackers.append(tracker); - - return trackers; -} - -QList TorrentInfo::urlSeeds() const -{ - if (!isValid()) return QList(); - - QList urlSeeds; - foreach (const libt::web_seed_entry &webSeed, m_nativeInfo->web_seeds()) - if (webSeed.type == libt::web_seed_entry::url_seed) - urlSeeds.append(QUrl(webSeed.url.c_str())); - - return urlSeeds; -} - -QByteArray TorrentInfo::metadata() const -{ - if (!isValid()) return QByteArray(); - return QByteArray(m_nativeInfo->metadata().get(), m_nativeInfo->metadata_size()); -} - -QStringList TorrentInfo::filesForPiece(int pieceIndex) const -{ - // no checks here because fileIndicesForPiece() will return an empty list - QVector fileIndices = fileIndicesForPiece(pieceIndex); - - QStringList res; - res.reserve(fileIndices.size()); - std::transform(fileIndices.begin(), fileIndices.end(), std::back_inserter(res), - [this](int i) { return filePath(i); }); - - return res; -} - -QVector TorrentInfo::fileIndicesForPiece(int pieceIndex) const -{ - if (!isValid() || (pieceIndex < 0) || (pieceIndex >= piecesCount())) - return QVector(); - - std::vector files( - nativeInfo()->map_block(pieceIndex, 0, nativeInfo()->piece_size(pieceIndex))); - QVector res; - res.reserve(int(files.size())); - std::transform(files.begin(), files.end(), std::back_inserter(res), - [](const libt::file_slice &s) { return s.file_index; }); - - return res; -} - -QVector TorrentInfo::pieceHashes() const -{ - if (!isValid()) - return {}; - - const int count = piecesCount(); - QVector hashes; - hashes.reserve(count); - - for (int i = 0; i < count; ++i) - hashes += { m_nativeInfo->hash_for_piece_ptr(i), libtorrent::sha1_hash::size }; - - return hashes; -} - -TorrentInfo::PieceRange TorrentInfo::filePieces(const QString& file) const -{ - if (!isValid()) // if we do not check here the debug message will be printed, which would be not correct - return {}; - - int index = fileIndex(file); - if (index == -1) { - qDebug() << "Filename" << file << "was not found in torrent" << name(); - return {}; - } - return filePieces(index); -} - -TorrentInfo::PieceRange TorrentInfo::filePieces(int fileIndex) const -{ - if (!isValid()) - return {}; - - if ((fileIndex < 0) || (fileIndex >= filesCount())) { - qDebug() << "File index (" << fileIndex << ") is out of range for torrent" << name(); - return {}; - } - - const libt::file_storage &files = nativeInfo()->files(); - const auto fileSize = files.file_size(fileIndex); - const auto firstOffset = files.file_offset(fileIndex); - return makeInterval(static_cast(firstOffset / pieceLength()), - static_cast((firstOffset + fileSize - 1) / pieceLength())); -} - -void TorrentInfo::renameFile(uint index, const QString &newPath) -{ - if (!isValid()) return; - nativeInfo()->rename_file(index, Utils::Fs::toNativePath(newPath).toStdString()); -} - -int BitTorrent::TorrentInfo::fileIndex(const QString& fileName) const -{ - // the check whether the object valid is not needed here - // because filesCount() returns -1 in that case and the loop exits immediately - for (int i = 0; i < filesCount(); ++i) - if (fileName == filePath(i)) - return i; - - return -1; -} - -bool TorrentInfo::hasRootFolder() const -{ - QString testRootFolder; - for (int i = 0; i < filesCount(); ++i) { - const QString filePath = this->filePath(i); - if (QDir::isAbsolutePath(filePath)) continue; - - const auto filePathElements = filePath.splitRef('/'); - // if at least one file has no root folder, no common root folder exists - if (filePathElements.count() <= 1) return false; - - if (testRootFolder.isEmpty()) - testRootFolder = filePathElements.at(0).toString(); - else if (testRootFolder != filePathElements.at(0)) - return false; - } - - return true; -} - -void TorrentInfo::stripRootFolder() -{ - if (!hasRootFolder()) return; - - libtorrent::file_storage files = m_nativeInfo->files(); - - // Solution for case of renamed root folder - std::string testName = filePath(0).split('/').value(0).toStdString(); - if (files.name() != testName) { - files.set_name(testName); - for (int i = 0; i < files.num_files(); ++i) - files.rename_file(i, files.file_path(i)); - } - - files.set_name(""); - m_nativeInfo->remap_files(files); -} - -TorrentInfo::NativePtr TorrentInfo::nativeInfo() const -{ - return m_nativeInfo; -} diff --git a/src/base/bittorrent/torrentinfo.h b/src/base/bittorrent/torrentinfo.h deleted file mode 100644 index 6730d2f11..000000000 --- a/src/base/bittorrent/torrentinfo.h +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2015 Vladimir Golovnev - * - * 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. - */ - -#ifndef BITTORRENT_TORRENTINFO_H -#define BITTORRENT_TORRENTINFO_H - -#include - -#include -#include - -#include "base/indexrange.h" - -class QString; -class QUrl; -class QDateTime; -class QStringList; -class QByteArray; -template class QList; -template class QVector; - -namespace BitTorrent -{ - class InfoHash; - class TrackerEntry; - - class TorrentInfo - { - public: -#if LIBTORRENT_VERSION_NUM < 10100 - typedef boost::intrusive_ptr NativeConstPtr; - typedef boost::intrusive_ptr NativePtr; -#else - typedef boost::shared_ptr NativeConstPtr; - typedef boost::shared_ptr NativePtr; -#endif - - explicit TorrentInfo(NativeConstPtr nativeInfo = NativeConstPtr()); - TorrentInfo(const TorrentInfo &other); - - static TorrentInfo loadFromFile(const QString &path, QString &error); - static TorrentInfo loadFromFile(const QString &path); - - TorrentInfo &operator=(const TorrentInfo &other); - - bool isValid() const; - InfoHash hash() const; - QString name() const; - QDateTime creationDate() const; - QString creator() const; - QString comment() const; - bool isPrivate() const; - qlonglong totalSize() const; - int filesCount() const; - int pieceLength() const; - int pieceLength(int index) const; - int piecesCount() const; - QString filePath(int index) const; - QStringList filePaths() const; - QString fileName(int index) const; - QString origFilePath(int index) const; - qlonglong fileSize(int index) const; - qlonglong fileOffset(int index) const; - QList trackers() const; - QList urlSeeds() const; - QByteArray metadata() const; - QStringList filesForPiece(int pieceIndex) const; - QVector fileIndicesForPiece(int pieceIndex) const; - QVector pieceHashes() const; - - using PieceRange = IndexRange; - // returns pair of the first and the last pieces into which - // the given file extends (maybe partially). - PieceRange filePieces(const QString &file) const; - PieceRange filePieces(int fileIndex) const; - - void renameFile(uint index, const QString &newPath); - - bool hasRootFolder() const; - void stripRootFolder(); - - NativePtr nativeInfo() const; - - private: - // returns file index or -1 if fileName is not found - int fileIndex(const QString &fileName) const; - NativePtr m_nativeInfo; - }; -} - -#endif // BITTORRENT_TORRENTINFO_H diff --git a/src/base/bittorrent/tracker.cpp b/src/base/bittorrent/tracker.cpp deleted file mode 100644 index 88a464582..000000000 --- a/src/base/bittorrent/tracker.cpp +++ /dev/null @@ -1,257 +0,0 @@ -/* - * Bittorrent Client using Qt4 and libtorrent. - * Copyright (C) 2015 Vladimir Golovnev - * Copyright (C) 2006 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 -#include -#include - -#include "base/preferences.h" -#include "base/http/server.h" -#include "base/utils/string.h" -#include "tracker.h" - -// static limits -static const int MAX_TORRENTS = 100; -static const int MAX_PEERS_PER_TORRENT = 1000; -static const int ANNOUNCE_INTERVAL = 1800; // 30min - -using namespace BitTorrent; - -// Peer -bool Peer::operator!=(const Peer &other) const -{ - return uid() != other.uid(); -} - -bool Peer::operator==(const Peer &other) const -{ - return uid() == other.uid(); -} - -QString Peer::uid() const -{ - return ip + ":" + QString::number(port); -} - -libtorrent::entry Peer::toEntry(bool noPeerId) const -{ - libtorrent::entry::dictionary_type peerMap; - if (!noPeerId) - peerMap["id"] = libtorrent::entry(peerId.toStdString()); - peerMap["ip"] = libtorrent::entry(ip.toStdString()); - peerMap["port"] = libtorrent::entry(port); - - return libtorrent::entry(peerMap); -} - -// Tracker - -Tracker::Tracker(QObject *parent) - : Http::ResponseBuilder(parent) - , m_server(new Http::Server(this, this)) -{ -} - -Tracker::~Tracker() -{ - if (m_server->isListening()) - qDebug("Shutting down the embedded tracker..."); - // TODO: Store the torrent list -} - -bool Tracker::start() -{ - const int listenPort = Preferences::instance()->getTrackerPort(); - - if (m_server->isListening()) { - if (m_server->serverPort() == listenPort) { - // Already listening on the right port, just return - return true; - } - // Wrong port, closing the server - m_server->close(); - } - - qDebug("Starting the embedded tracker..."); - // Listen on the predefined port - return m_server->listen(QHostAddress::Any, listenPort); -} - -Http::Response Tracker::processRequest(const Http::Request &request, const Http::Environment &env) -{ - clear(); // clear response - - //qDebug("Tracker received the following request:\n%s", qPrintable(parser.toString())); - // Is request a GET request? - if (request.method != "GET") { - qDebug("Tracker: Unsupported HTTP request: %s", qPrintable(request.method)); - status(100, "Invalid request type"); - } - else if (!request.path.startsWith("/announce", Qt::CaseInsensitive)) { - qDebug("Tracker: Unrecognized path: %s", qPrintable(request.path)); - status(100, "Invalid request type"); - } - else { - // OK, this is a GET request - m_request = request; - m_env = env; - respondToAnnounceRequest(); - } - - return response(); -} - -void Tracker::respondToAnnounceRequest() -{ - const QStringMap &gets = m_request.gets; - TrackerAnnounceRequest annonceReq; - - // IP - annonceReq.peer.ip = m_env.clientAddress.toString(); - - // 1. Get info_hash - if (!gets.contains("info_hash")) { - qDebug("Tracker: Missing info_hash"); - status(101, "Missing info_hash"); - return; - } - annonceReq.infoHash = gets.value("info_hash"); - // info_hash cannot be longer than 20 bytes - /*if (annonce_req.info_hash.toLatin1().length() > 20) { - qDebug("Tracker: Info_hash is not 20 byte long: %s (%d)", qPrintable(annonce_req.info_hash), annonce_req.info_hash.toLatin1().length()); - status(150, "Invalid infohash"); - return; - }*/ - - // 2. Get peer ID - if (!gets.contains("peer_id")) { - qDebug("Tracker: Missing peer_id"); - status(102, "Missing peer_id"); - return; - } - annonceReq.peer.peerId = gets.value("peer_id"); - // peer_id cannot be longer than 20 bytes - /*if (annonce_req.peer.peer_id.length() > 20) { - qDebug("Tracker: peer_id is not 20 byte long: %s", qPrintable(annonce_req.peer.peer_id)); - status(151, "Invalid peerid"); - return; - }*/ - - // 3. Get port - if (!gets.contains("port")) { - qDebug("Tracker: Missing port"); - status(103, "Missing port"); - return; - } - bool ok = false; - annonceReq.peer.port = gets.value("port").toInt(&ok); - if (!ok || annonceReq.peer.port < 1 || annonceReq.peer.port > 65535) { - qDebug("Tracker: Invalid port number (%d)", annonceReq.peer.port); - status(103, "Missing port"); - return; - } - - // 4. Get event - annonceReq.event = ""; - if (gets.contains("event")) { - annonceReq.event = gets.value("event"); - qDebug("Tracker: event is %s", qPrintable(annonceReq.event)); - } - - // 5. Get numwant - annonceReq.numwant = 50; - if (gets.contains("numwant")) { - int tmp = gets.value("numwant").toInt(); - if (tmp > 0) { - qDebug("Tracker: numwant = %d", tmp); - annonceReq.numwant = tmp; - } - } - - // 6. no_peer_id (extension) - annonceReq.noPeerId = false; - if (gets.contains("no_peer_id")) - annonceReq.noPeerId = true; - - // 7. TODO: support "compact" extension - - // Done parsing, now let's reply - if (m_torrents.contains(annonceReq.infoHash)) { - if (annonceReq.event == "stopped") { - qDebug("Tracker: Peer stopped downloading, deleting it from the list"); - m_torrents[annonceReq.infoHash].remove(annonceReq.peer.uid()); - return; - } - } - else { - // Unknown torrent - if (m_torrents.size() == MAX_TORRENTS) { - // Reached max size, remove a random torrent - m_torrents.erase(m_torrents.begin()); - } - } - // Register the user - PeerList peers = m_torrents.value(annonceReq.infoHash); - if (peers.size() == MAX_PEERS_PER_TORRENT) { - // Too many peers, remove a random one - peers.erase(peers.begin()); - } - peers[annonceReq.peer.uid()] = annonceReq.peer; - m_torrents[annonceReq.infoHash] = peers; - - // Reply - replyWithPeerList(annonceReq); -} - -void Tracker::replyWithPeerList(const TrackerAnnounceRequest &annonceReq) -{ - // Prepare the entry for bencoding - libtorrent::entry::dictionary_type replyDict; - replyDict["interval"] = libtorrent::entry(ANNOUNCE_INTERVAL); - QList peers = m_torrents.value(annonceReq.infoHash).values(); - libtorrent::entry::list_type peerList; - foreach (const Peer &p, peers) { - //if (p != annonce_req.peer) - peerList.push_back(p.toEntry(annonceReq.noPeerId)); - } - replyDict["peers"] = libtorrent::entry(peerList); - libtorrent::entry replyEntry(replyDict); - // bencode - std::vector buf; - libtorrent::bencode(std::back_inserter(buf), replyEntry); - QByteArray reply(&buf[0], static_cast(buf.size())); - qDebug("Tracker: reply with the following bencoded data:\n %s", reply.constData()); - - // HTTP reply - print(reply, Http::CONTENT_TYPE_TXT); -} - - diff --git a/src/base/bittorrent/tracker.h b/src/base/bittorrent/tracker.h deleted file mode 100644 index 7e8f9f318..000000000 --- a/src/base/bittorrent/tracker.h +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2015 Vladimir Golovnev - * Copyright (C) 2010 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 BITTORRENT_TRACKER_H -#define BITTORRENT_TRACKER_H - -#include -#include "base/http/types.h" -#include "base/http/responsebuilder.h" -#include "base/http/irequesthandler.h" - -namespace libtorrent -{ - class entry; -} - -namespace Http -{ - class Server; -} - -namespace BitTorrent -{ - struct Peer - { - QString ip; - QString peerId; - int port; - - bool operator!=(const Peer &other) const; - bool operator==(const Peer &other) const; - QString uid() const; - libtorrent::entry toEntry(bool noPeerId) const; - }; - - struct TrackerAnnounceRequest - { - QString infoHash; - QString event; - int numwant; - Peer peer; - // Extensions - bool noPeerId; - }; - - typedef QHash PeerList; - typedef QHash TorrentList; - - /* Basic Bittorrent tracker implementation in Qt */ - /* Following http://wiki.theory.org/BitTorrent_Tracker_Protocol */ - class Tracker : public Http::ResponseBuilder, public Http::IRequestHandler - { - Q_OBJECT - Q_DISABLE_COPY(Tracker) - - public: - explicit Tracker(QObject *parent = 0); - ~Tracker(); - - bool start(); - Http::Response processRequest(const Http::Request &request, const Http::Environment &env); - - private: - void respondToAnnounceRequest(); - void replyWithPeerList(const TrackerAnnounceRequest &annonceReq); - - Http::Server *m_server; - TorrentList m_torrents; - - Http::Request m_request; - Http::Environment m_env; - }; -} - -#endif // BITTORRENT_TRACKER_H diff --git a/src/base/bittorrent/trackerentry.cpp b/src/base/bittorrent/trackerentry.cpp deleted file mode 100644 index 824f8f1ba..000000000 --- a/src/base/bittorrent/trackerentry.cpp +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2015 Vladimir Golovnev - * - * 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. - */ - -#include - -#include "base/utils/misc.h" -#include "base/utils/string.h" -#include "trackerentry.h" - -using namespace BitTorrent; - -TrackerEntry::TrackerEntry(const QString &url) - : m_nativeEntry(libtorrent::announce_entry(url.toStdString())) -{ -} - -TrackerEntry::TrackerEntry(const libtorrent::announce_entry &nativeEntry) - : m_nativeEntry(nativeEntry) -{ -} - -TrackerEntry::TrackerEntry(const TrackerEntry &other) - : m_nativeEntry(other.m_nativeEntry) -{ -} - -QString TrackerEntry::url() const -{ - return QString::fromStdString(m_nativeEntry.url); -} - -int TrackerEntry::tier() const -{ - return m_nativeEntry.tier; -} - -TrackerEntry::Status TrackerEntry::status() const -{ - // libtorrent::announce_entry::is_working() returns - // true when the tracker hasn't been tried yet. - if (m_nativeEntry.verified && m_nativeEntry.is_working()) - return Working; - else if ((m_nativeEntry.fails == 0) && m_nativeEntry.updating) - return Updating; - else if (m_nativeEntry.fails == 0) - return NotContacted; - else - return NotWorking; -} - -void TrackerEntry::setTier(int value) -{ - m_nativeEntry.tier = value; -} - -TrackerEntry &TrackerEntry::operator=(const TrackerEntry &other) -{ - this->m_nativeEntry = other.m_nativeEntry; - return *this; -} - -bool TrackerEntry::operator==(const TrackerEntry &other) const -{ - return (QUrl(url()) == QUrl(other.url())); -} - -libtorrent::announce_entry TrackerEntry::nativeEntry() const -{ - return m_nativeEntry; -} diff --git a/src/base/bittorrent/trackerentry.h b/src/base/bittorrent/trackerentry.h deleted file mode 100644 index fcaf9af7d..000000000 --- a/src/base/bittorrent/trackerentry.h +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2015 Vladimir Golovnev - * - * 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. - */ - -#ifndef BITTORRENT_TRACKERENTRY_H -#define BITTORRENT_TRACKERENTRY_H - -#include -#include -#if LIBTORRENT_VERSION_NUM >= 10100 -#include -#endif - -class QString; - -namespace BitTorrent -{ - class TrackerEntry - { - public: - enum Status - { - NotContacted, - Working, - Updating, - NotWorking - }; - - TrackerEntry(const QString &url); - TrackerEntry(const libtorrent::announce_entry &nativeEntry); - TrackerEntry(const TrackerEntry &other); - - QString url() const; - int tier() const; - Status status() const; - - void setTier(int value); - TrackerEntry &operator=(const TrackerEntry &other); - bool operator==(const TrackerEntry &other) const; - - libtorrent::announce_entry nativeEntry() const; - - private: - libtorrent::announce_entry m_nativeEntry; - }; -} - -#endif // BITTORRENT_TRACKERENTRY_H diff --git a/src/base/filesystemwatcher.cpp b/src/base/filesystemwatcher.cpp deleted file mode 100644 index c4877ee08..000000000 --- a/src/base/filesystemwatcher.cpp +++ /dev/null @@ -1,276 +0,0 @@ -#include -#ifndef Q_OS_WIN -#include -#include -#include -#if defined(Q_OS_MAC) || defined(Q_OS_FREEBSD) -#include -#include -#include -#elif !defined Q_OS_HAIKU -#include -#endif -#endif - -#include "base/preferences.h" -#include "base/bittorrent/torrentinfo.h" -#include "base/bittorrent/magneturi.h" -#include "filesystemwatcher.h" - -#ifndef CIFS_MAGIC_NUMBER -#define CIFS_MAGIC_NUMBER 0xFF534D42 -#endif - -#ifndef NFS_SUPER_MAGIC -#define NFS_SUPER_MAGIC 0x6969 -#endif - -#ifndef SMB_SUPER_MAGIC -#define SMB_SUPER_MAGIC 0x517B -#endif - -const int WATCH_INTERVAL = 10000; // 10 sec -const int MAX_PARTIAL_RETRIES = 5; - -FileSystemWatcher::FileSystemWatcher(QObject *parent) - : QFileSystemWatcher(parent) -{ - m_filters << "*.torrent" << "*.magnet"; - connect(this, SIGNAL(directoryChanged(QString)), SLOT(scanLocalFolder(QString))); -} - -FileSystemWatcher::~FileSystemWatcher() -{ -#ifndef Q_OS_WIN - if (m_watchTimer) - delete m_watchTimer; -#endif - if (m_partialTorrentTimer) - delete m_partialTorrentTimer; -} - -QStringList FileSystemWatcher::directories() const -{ - QStringList dirs; -#ifndef Q_OS_WIN - if (m_watchTimer) { - foreach (const QDir &dir, m_watchedFolders) - dirs << dir.canonicalPath(); - } -#endif - dirs << QFileSystemWatcher::directories(); - return dirs; -} - -void FileSystemWatcher::addPath(const QString &path) -{ -#if !defined Q_OS_WIN && !defined Q_OS_HAIKU - QDir dir(path); - if (!dir.exists()) return; - - // Check if the path points to a network file system or not - if (isNetworkFileSystem(path)) { - // Network mode - qDebug("Network folder detected: %s", qPrintable(path)); - qDebug("Using file polling mode instead of inotify..."); - m_watchedFolders << dir; - // Set up the watch timer - if (!m_watchTimer) { - m_watchTimer = new QTimer(this); - connect(m_watchTimer, SIGNAL(timeout()), SLOT(scanNetworkFolders())); - m_watchTimer->start(WATCH_INTERVAL); // 5 sec - } - } - else { -#endif - // Normal mode - qDebug("FS Watching is watching %s in normal mode", qPrintable(path)); - QFileSystemWatcher::addPath(path); - scanLocalFolder(path); -#if !defined Q_OS_WIN && !defined Q_OS_HAIKU - } -#endif -} - -void FileSystemWatcher::removePath(const QString &path) -{ -#ifndef Q_OS_WIN - QDir dir(path); - for (int i = 0; i < m_watchedFolders.count(); ++i) { - if (QDir(m_watchedFolders.at(i)) == dir) { - m_watchedFolders.removeAt(i); - if (m_watchedFolders.isEmpty()) - delete m_watchTimer; - return; - } - } -#endif - // Normal mode - QFileSystemWatcher::removePath(path); -} - -void FileSystemWatcher::scanLocalFolder(QString path) -{ - qDebug("scanLocalFolder(%s) called", qPrintable(path)); - QStringList torrents; - // Local folders scan - addTorrentsFromDir(QDir(path), torrents); - // Report detected torrent files - if (!torrents.empty()) { - qDebug("The following files are being reported: %s", qPrintable(torrents.join("\n"))); - emit torrentsAdded(torrents); - } -} - -void FileSystemWatcher::scanNetworkFolders() -{ -#ifndef Q_OS_WIN - qDebug("scanNetworkFolders() called"); - QStringList torrents; - // Network folders scan - foreach (const QDir &dir, m_watchedFolders) { - //qDebug("FSWatcher: Polling manually folder %s", qPrintable(dir.path())); - addTorrentsFromDir(dir, torrents); - } - // Report detected torrent files - if (!torrents.empty()) { - qDebug("The following files are being reported: %s", qPrintable(torrents.join("\n"))); - emit torrentsAdded(torrents); - } -#endif -} - -void FileSystemWatcher::processPartialTorrents() -{ - QStringList noLongerPartial; - - // Check which torrents are still partial - foreach (const QString &torrentPath, m_partialTorrents.keys()) { - if (!QFile::exists(torrentPath)) { - m_partialTorrents.remove(torrentPath); - } - else if (BitTorrent::TorrentInfo::loadFromFile(torrentPath).isValid()) { - noLongerPartial << torrentPath; - m_partialTorrents.remove(torrentPath); - } - else if (m_partialTorrents[torrentPath] >= MAX_PARTIAL_RETRIES) { - m_partialTorrents.remove(torrentPath); - QFile::rename(torrentPath, torrentPath + ".invalid"); - } - else { - ++m_partialTorrents[torrentPath]; - } - } - - // Stop the partial timer if necessary - if (m_partialTorrents.empty()) { - m_partialTorrentTimer->stop(); - m_partialTorrentTimer->deleteLater(); - qDebug("No longer any partial torrent."); - } - else { - qDebug("Still %d partial torrents after delayed processing.", m_partialTorrents.count()); - m_partialTorrentTimer->start(WATCH_INTERVAL); - } - - // Notify of new torrents - if (!noLongerPartial.isEmpty()) - emit torrentsAdded(noLongerPartial); -} - -void FileSystemWatcher::startPartialTorrentTimer() -{ - Q_ASSERT(!m_partialTorrents.isEmpty()); - if (!m_partialTorrentTimer) { - m_partialTorrentTimer = new QTimer(); - connect(m_partialTorrentTimer, SIGNAL(timeout()), SLOT(processPartialTorrents())); - m_partialTorrentTimer->setSingleShot(true); - m_partialTorrentTimer->start(WATCH_INTERVAL); - } -} - -void FileSystemWatcher::addTorrentsFromDir(const QDir &dir, QStringList &torrents) -{ - const QStringList files = dir.entryList(m_filters, QDir::Files, QDir::Unsorted); - foreach (const QString &file, files) { - const QString fileAbsPath = dir.absoluteFilePath(file); - if (fileAbsPath.endsWith(".magnet")) { - torrents << fileAbsPath; - } - else if (BitTorrent::TorrentInfo::loadFromFile(fileAbsPath).isValid()) { - torrents << fileAbsPath; - } - else if (!m_partialTorrents.contains(fileAbsPath)) { - qDebug("Partial torrent detected at: %s", qPrintable(fileAbsPath)); - qDebug("Delay the file's processing..."); - m_partialTorrents.insert(fileAbsPath, 0); - } - } - - if (!m_partialTorrents.empty()) - startPartialTorrentTimer(); -} - -#if !defined Q_OS_WIN && !defined Q_OS_HAIKU -bool FileSystemWatcher::isNetworkFileSystem(QString path) -{ - QString file = path; - if (!file.endsWith("/")) - file += "/"; - file += "."; - struct statfs buf; - if (!statfs(file.toLocal8Bit().constData(), &buf)) { -#ifdef Q_OS_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)); -#else - return ((buf.f_type == static_cast(CIFS_MAGIC_NUMBER)) - || (buf.f_type == static_cast(NFS_SUPER_MAGIC)) - || (buf.f_type == static_cast(SMB_SUPER_MAGIC))); -#endif - } - else { - std::cerr << "Error: statfs() call failed for " << qPrintable(file) << ". Supposing it is a local folder..." << std::endl; - switch(errno) { - case EACCES: - std::cerr << "Search permission is denied for a component of the path prefix of the path" << std::endl; - break; - case EFAULT: - std::cerr << "Buf or path points to an invalid address" << std::endl; - break; - case EINTR: - std::cerr << "This call was interrupted by a signal" << std::endl; - break; - case EIO: - std::cerr << "I/O Error" << std::endl; - break; - case ELOOP: - std::cerr << "Too many symlinks" << std::endl; - break; - case ENAMETOOLONG: - std::cerr << "path is too long" << std::endl; - break; - case ENOENT: - std::cerr << "The file referred by path does not exist" << std::endl; - break; - case ENOMEM: - std::cerr << "Insufficient kernel memory" << std::endl; - break; - case ENOSYS: - std::cerr << "The file system does not detect this call" << std::endl; - break; - case ENOTDIR: - std::cerr << "A component of the path is not a directory" << std::endl; - break; - case EOVERFLOW: - std::cerr << "Some values were too large to be represented in the struct" << std::endl; - break; - default: - std::cerr << "Unknown error" << std::endl; - } - - std::cerr << "Errno: " << errno << std::endl; - return false; - } -} -#endif diff --git a/src/base/filesystemwatcher.h b/src/base/filesystemwatcher.h deleted file mode 100644 index 9e71958ef..000000000 --- a/src/base/filesystemwatcher.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef FILESYSTEMWATCHER_H -#define FILESYSTEMWATCHER_H - -#include -#include -#include -#include -#include -#include - -/* - * Subclassing QFileSystemWatcher in order to support Network File - * System watching (NFS, CIFS) on Linux and Mac OS. - */ -class FileSystemWatcher : public QFileSystemWatcher -{ - Q_OBJECT - -public: - explicit FileSystemWatcher(QObject *parent = 0); - ~FileSystemWatcher(); - - QStringList directories() const; - void addPath(const QString &path); - void removePath(const QString &path); - -signals: - void torrentsAdded(const QStringList &pathList); - -protected slots: - void scanLocalFolder(QString path); - void scanNetworkFolders(); - void processPartialTorrents(); - -private: - void startPartialTorrentTimer(); - void addTorrentsFromDir(const QDir &dir, QStringList &torrents); -#if !defined Q_OS_WIN && !defined Q_OS_HAIKU - static bool isNetworkFileSystem(QString path); -#endif - -#ifndef Q_OS_WIN - QList m_watchedFolders; - QPointer m_watchTimer; -#endif - QStringList m_filters; - // Partial torrents - QHash m_partialTorrents; - QPointer m_partialTorrentTimer; -}; - -#endif // FILESYSTEMWATCHER_H diff --git a/src/base/global.h b/src/base/global.h deleted file mode 100644 index 2bfeda9cb..000000000 --- a/src/base/global.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2016 Mike Tzou - * - * 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. - */ - -const char C_TORRENT_FILE_EXTENSION[] = ".torrent"; - diff --git a/src/base/http/connection.cpp b/src/base/http/connection.cpp deleted file mode 100644 index bb63093e6..000000000 --- a/src/base/http/connection.cpp +++ /dev/null @@ -1,144 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2014 Vladimir Golovnev - * Copyright (C) 2006 Ishan Arora and 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 "connection.h" - -#include -#include - -#include "irequesthandler.h" -#include "requestparser.h" -#include "responsegenerator.h" - -using namespace Http; - -Connection::Connection(QTcpSocket *socket, IRequestHandler *requestHandler, QObject *parent) - : QObject(parent) - , m_socket(socket) - , m_requestHandler(requestHandler) -{ - m_socket->setParent(this); - m_idleTimer.start(); - connect(m_socket, SIGNAL(readyRead()), SLOT(read())); -} - -Connection::~Connection() -{ - m_socket->close(); -} - -void Connection::read() -{ - m_idleTimer.restart(); - - m_receivedData.append(m_socket->readAll()); - Request request; - RequestParser::ErrorCode err = RequestParser::parse(m_receivedData, request); // TODO: transform request headers to lowercase - - switch (err) { - case RequestParser::IncompleteRequest: - // Partial request waiting for the rest - break; - - case RequestParser::BadRequest: - sendResponse(Response(400, "Bad Request")); - m_receivedData.clear(); - break; - - case RequestParser::NoError: - const Environment env {m_socket->localAddress(), m_socket->localPort(), m_socket->peerAddress(), m_socket->peerPort()}; - - Response response = m_requestHandler->processRequest(request, env); - if (acceptsGzipEncoding(request.headers["accept-encoding"])) - response.headers[HEADER_CONTENT_ENCODING] = "gzip"; - sendResponse(response); - m_receivedData.clear(); - break; - } -} - -void Connection::sendResponse(const Response &response) -{ - m_socket->write(toByteArray(response)); - m_socket->close(); // TODO: remove when HTTP pipelining is supported -} - -bool Connection::hasExpired(const qint64 timeout) const -{ - return m_idleTimer.hasExpired(timeout); -} - -bool Connection::isClosed() const -{ - return (m_socket->state() == QAbstractSocket::UnconnectedState); -} - -bool Connection::acceptsGzipEncoding(QString codings) -{ - // [rfc7231] 5.3.4. Accept-Encoding - - const auto isCodingAvailable = [](const QStringList &list, const QString &encoding) -> bool - { - foreach (const QString &str, list) { - if (!str.startsWith(encoding)) - continue; - - // without quality values - if (str == encoding) - return true; - - // [rfc7231] 5.3.1. Quality Values - const QStringRef substr = str.midRef(encoding.size() + 3); // ex. skip over "gzip;q=" - - bool ok = false; - const double qvalue = substr.toDouble(&ok); - if (!ok || (qvalue <= 0.0)) - return false; - - return true; - } - return false; - }; - - const QStringList list = codings.remove(' ').remove('\t').split(',', QString::SkipEmptyParts); - if (list.isEmpty()) - return false; - - const bool canGzip = isCodingAvailable(list, QLatin1String("gzip")); - if (canGzip) - return true; - - const bool canAny = isCodingAvailable(list, QLatin1String("*")); - if (canAny) - return true; - - return false; -} diff --git a/src/base/http/connection.h b/src/base/http/connection.h deleted file mode 100644 index 81ec3ab80..000000000 --- a/src/base/http/connection.h +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2014 Vladimir Golovnev - * Copyright (C) 2006 Ishan Arora and 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 HTTP_CONNECTION_H -#define HTTP_CONNECTION_H - -#include -#include - -#include "types.h" - -class QTcpSocket; - -namespace Http -{ - class IRequestHandler; - - class Connection : public QObject - { - Q_OBJECT - Q_DISABLE_COPY(Connection) - - public: - Connection(QTcpSocket *socket, IRequestHandler *requestHandler, QObject *parent = 0); - ~Connection(); - - bool hasExpired(qint64 timeout) const; - bool isClosed() const; - - private slots: - void read(); - - private: - static bool acceptsGzipEncoding(QString codings); - void sendResponse(const Response &response); - - QTcpSocket *m_socket; - IRequestHandler *m_requestHandler; - QByteArray m_receivedData; - QElapsedTimer m_idleTimer; - }; -} - -#endif // HTTP_CONNECTION_H diff --git a/src/base/http/irequesthandler.h b/src/base/http/irequesthandler.h deleted file mode 100644 index 0d2cf9a5c..000000000 --- a/src/base/http/irequesthandler.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2015 Vladimir Golovnev - * - * 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. - */ - -#ifndef HTTP_IREQUESTHANDLER_H -#define HTTP_IREQUESTHANDLER_H - -#include "types.h" - -namespace Http -{ - class IRequestHandler - { - public: - virtual ~IRequestHandler() {} - virtual Response processRequest(const Request &request, const Environment &env) = 0; - }; -} - -#endif // HTTP_IREQUESTHANDLER_H - diff --git a/src/base/http/requestparser.cpp b/src/base/http/requestparser.cpp deleted file mode 100644 index ca85f49bf..000000000 --- a/src/base/http/requestparser.cpp +++ /dev/null @@ -1,344 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2014 Vladimir Golovnev - * Copyright (C) 2006 Ishan Arora and 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 -#include -#include -#include -#include -#include "requestparser.h" - -const QByteArray EOL("\r\n"); -const QByteArray EOH("\r\n\r\n"); - -inline QString unquoted(const QString& str) -{ - if ((str[0] == '\"') && (str[str.length() - 1] == '\"')) - return str.mid(1, str.length() - 2); - - return str; -} - -using namespace Http; - -RequestParser::ErrorCode RequestParser::parse(const QByteArray& data, Request& request, uint maxContentLength) -{ - return RequestParser(maxContentLength).parseHttpRequest(data, request); -} - -RequestParser::RequestParser(uint maxContentLength) - : m_maxContentLength(maxContentLength) -{ -} - -RequestParser::ErrorCode RequestParser::parseHttpRequest(const QByteArray& data, Request& request) -{ - m_request = Request(); - - // Parse HTTP request header - const int header_end = data.indexOf(EOH); - if (header_end < 0) { - qDebug() << Q_FUNC_INFO << "incomplete request"; - return IncompleteRequest; - } - - if (!parseHttpHeader(data.left(header_end))) { - qWarning() << Q_FUNC_INFO << "header parsing error"; - return BadRequest; - } - - // Parse HTTP request message - if (m_request.headers.contains("content-length")) { - int content_length = m_request.headers["content-length"].toInt(); - if (content_length < 0) { - qWarning() << Q_FUNC_INFO << "bad request: content-length negative"; - return BadRequest; - } - - if (content_length > static_cast(m_maxContentLength)) { - qWarning() << Q_FUNC_INFO << "bad request: message too long"; - return BadRequest; - } - - QByteArray content = data.mid(header_end + EOH.length(), content_length); - if (content.length() < content_length) { - qDebug() << Q_FUNC_INFO << "incomplete request"; - return IncompleteRequest; - } - - if ((content_length > 0) && !parseContent(content)) { - qWarning() << Q_FUNC_INFO << "message parsing error"; - return BadRequest; - } - } - - // qDebug() << Q_FUNC_INFO; - // qDebug() << "HTTP Request header:"; - // qDebug() << data.left(header_end) << "\n"; - - request = m_request; - return NoError; -} - -bool RequestParser::parseStartingLine(const QString &line) -{ - const QRegExp rx("^([A-Z]+)\\s+(\\S+)\\s+HTTP/\\d\\.\\d$"); - - if (rx.indexIn(line.trimmed()) >= 0) { - m_request.method = rx.cap(1); - - QUrl url = QUrl::fromEncoded(rx.cap(2).toLatin1()); - m_request.path = url.path(); // Path - - // Parse GET parameters - QListIterator > i(QUrlQuery(url).queryItems()); - while (i.hasNext()) { - QPair pair = i.next(); - m_request.gets[pair.first] = pair.second; - } - - return true; - } - - qWarning() << Q_FUNC_INFO << "invalid http header:" << line; - return false; -} - -bool RequestParser::parseHeaderLine(const QString &line, QPair& out) -{ - int i = line.indexOf(QLatin1Char(':')); - if (i == -1) { - qWarning() << Q_FUNC_INFO << "invalid http header:" << line; - return false; - } - - out = qMakePair(line.left(i).trimmed().toLower(), line.mid(i + 1).trimmed()); - return true; -} - -bool RequestParser::parseHttpHeader(const QByteArray &data) -{ - QString str = QString::fromUtf8(data); - QStringList lines = str.trimmed().split(EOL); - - QStringList headerLines; - foreach (const QString& line, lines) { - if (line[0].isSpace()) { // header line continuation - if (!headerLines.isEmpty()) { // really continuation - headerLines.last() += QLatin1Char(' '); - headerLines.last() += line.trimmed(); - } - } - else { - headerLines.append(line); - } - } - - if (headerLines.isEmpty()) - return false; // Empty header - - QStringList::Iterator it = headerLines.begin(); - if (!parseStartingLine(*it)) - return false; - - ++it; - for (; it != headerLines.end(); ++it) { - QPair header; - if (!parseHeaderLine(*it, header)) - return false; - - m_request.headers[header.first] = header.second; - } - - return true; -} - -QList RequestParser::splitMultipartData(const QByteArray& data, const QByteArray& boundary) -{ - QList ret; - QByteArray sep = boundary + EOL; - const int sepLength = sep.size(); - - int start = 0, end = 0; - if ((end = data.indexOf(sep, start)) >= 0) { - start = end + sepLength; // skip first boundary - - while ((end = data.indexOf(sep, start)) >= 0) { - ret << data.mid(start, end - EOL.length() - start); - start = end + sepLength; - } - - // last or single part - sep = boundary + "--" + EOL; - if ((end = data.indexOf(sep, start)) >= 0) - ret << data.mid(start, end - EOL.length() - start); - } - - return ret; -} - -bool RequestParser::parseContent(const QByteArray& data) -{ - // Parse message content - qDebug() << Q_FUNC_INFO << "Content-Length: " << m_request.headers["content-length"]; - qDebug() << Q_FUNC_INFO << "data.size(): " << data.size(); - - // Parse url-encoded POST data - if (m_request.headers["content-type"].startsWith("application/x-www-form-urlencoded")) { - QUrl url; - url.setQuery(data); - QListIterator > i(QUrlQuery(url).queryItems(QUrl::FullyDecoded)); - while (i.hasNext()) { - QPair pair = i.next(); - m_request.posts[pair.first.toLower()] = pair.second; - } - - return true; - } - - // Parse multipart/form data (torrent file) - /** - data has the following format (if boundary is "cH2ae0GI3KM7GI3Ij5ae0ei4Ij5Ij5") - ---cH2ae0GI3KM7GI3Ij5ae0ei4Ij5Ij5 -Content-Disposition: form-data; name=\"Filename\" - -PB020344.torrent ---cH2ae0GI3KM7GI3Ij5ae0ei4Ij5Ij5 -Content-Disposition: form-data; name=\"torrentfile"; filename=\"PB020344.torrent\" -Content-Type: application/x-bittorrent - -BINARY DATA IS HERE ---cH2ae0GI3KM7GI3Ij5ae0ei4Ij5Ij5 -Content-Disposition: form-data; name=\"Upload\" - -Submit Query ---cH2ae0GI3KM7GI3Ij5ae0ei4Ij5Ij5-- -**/ - QString content_type = m_request.headers["content-type"]; - if (content_type.startsWith("multipart/form-data")) { - const QRegExp boundaryRegexQuoted("boundary=\"([ \\w'()+,-\\./:=\\?]+)\""); - const QRegExp boundaryRegexNotQuoted("boundary=([\\w'()+,-\\./:=\\?]+)"); - - QByteArray boundary; - if (boundaryRegexQuoted.indexIn(content_type) < 0) { - if (boundaryRegexNotQuoted.indexIn(content_type) < 0) { - qWarning() << "Could not find boundary in multipart/form-data header!"; - return false; - } - else { - boundary = "--" + boundaryRegexNotQuoted.cap(1).toLatin1(); - } - } - else { - boundary = "--" + boundaryRegexQuoted.cap(1).toLatin1(); - } - - qDebug() << "Boundary is " << boundary; - QList parts = splitMultipartData(data, boundary); - qDebug() << parts.size() << "parts in data"; - - foreach (const QByteArray& part, parts) { - if (!parseFormData(part)) - return false; - } - - return true; - } - - qWarning() << Q_FUNC_INFO << "unknown content type:" << qPrintable(content_type); - return false; -} - -bool RequestParser::parseFormData(const QByteArray& data) -{ - // Parse form data header - const int header_end = data.indexOf(EOH); - if (header_end < 0) { - qDebug() << "Invalid form data: \n" << data; - return false; - } - - QString header_str = QString::fromUtf8(data.left(header_end)); - QStringList lines = header_str.trimmed().split(EOL); - QStringMap headers; - foreach (const QString& line, lines) { - QPair header; - if (!parseHeaderLine(line, header)) - return false; - - headers[header.first] = header.second; - } - - QStringMap disposition; - if (!headers.contains("content-disposition") - || !parseHeaderValue(headers["content-disposition"], disposition) - || !disposition.contains("name")) { - qDebug() << "Invalid form data header: \n" << header_str; - return false; - } - - if (disposition.contains("filename")) { - UploadedFile ufile; - ufile.filename = disposition["filename"]; - ufile.type = disposition["content-type"]; - ufile.data = data.mid(header_end + EOH.length()); - - m_request.files.append(ufile); - } - else { - m_request.posts[disposition["name"]] = QString::fromUtf8(data.mid(header_end + EOH.length())); - } - - return true; -} - -bool RequestParser::parseHeaderValue(const QString& value, QStringMap& out) -{ - int pos = value.indexOf(QLatin1Char(';')); - if (pos == -1) { - out[""] = value.trimmed(); - return true; - } - - out[""] = value.left(pos).trimmed(); - - QRegExp rx(";\\s*([^=;\"]+)\\s*=\\s*(\"[^\"]*\"|[^\";\\s]+)\\s*"); - while (rx.indexIn(value, pos) == pos) { - out[rx.cap(1).trimmed()] = unquoted(rx.cap(2)); - pos += rx.cap(0).length(); - } - - if (pos != value.length()) - return false; - - return true; -} diff --git a/src/base/http/requestparser.h b/src/base/http/requestparser.h deleted file mode 100644 index 5ea8e05e4..000000000 --- a/src/base/http/requestparser.h +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2014 Vladimir Golovnev - * Copyright (C) 2006 Ishan Arora and 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 HTTP_REQUESTPARSER_H -#define HTTP_REQUESTPARSER_H - -#include "types.h" - -namespace Http -{ - class RequestParser - { - public: - enum ErrorCode - { - NoError = 0, - IncompleteRequest, - BadRequest - }; - - // when result != NoError parsed request is undefined - // Warning! Header names are converted to lower-case. - static ErrorCode parse(const QByteArray &data, Request &request, uint maxContentLength = 10000000 /* ~10MB */); - - private: - RequestParser(uint maxContentLength); - - ErrorCode parseHttpRequest(const QByteArray &data, Request &request); - - bool parseHttpHeader(const QByteArray &data); - bool parseStartingLine(const QString &line); - bool parseContent(const QByteArray &data); - bool parseFormData(const QByteArray &data); - QList splitMultipartData(const QByteArray &data, const QByteArray &boundary); - - static bool parseHeaderLine(const QString &line, QPair &out); - static bool parseHeaderValue(const QString &value, QStringMap &out); - - const uint m_maxContentLength; - Request m_request; - }; -} - -#endif // HTTP_REQUESTPARSER_H diff --git a/src/base/http/responsebuilder.cpp b/src/base/http/responsebuilder.cpp deleted file mode 100644 index 954ed05b5..000000000 --- a/src/base/http/responsebuilder.cpp +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2015 Vladimir Golovnev - * - * 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. - */ - -#include "responsebuilder.h" - -using namespace Http; - -ResponseBuilder::ResponseBuilder(QObject *parent) - : QObject(parent) -{ -} - -void ResponseBuilder::status(uint code, const QString &text) -{ - m_response.status = ResponseStatus(code, text); -} - -void ResponseBuilder::header(const QString &name, const QString &value) -{ - m_response.headers[name] = value; -} - -void ResponseBuilder::print(const QString &text, const QString &type) -{ - print_impl(text.toUtf8(), type); -} - -void ResponseBuilder::print(const QByteArray &data, const QString &type) -{ - print_impl(data, type); -} - -void ResponseBuilder::clear() -{ - m_response = Response(); -} - -Response ResponseBuilder::response() const -{ - return m_response; -} - -void ResponseBuilder::print_impl(const QByteArray &data, const QString &type) -{ - if (!m_response.headers.contains(HEADER_CONTENT_TYPE)) - m_response.headers[HEADER_CONTENT_TYPE] = type; - - m_response.content += data; -} diff --git a/src/base/http/responsebuilder.h b/src/base/http/responsebuilder.h deleted file mode 100644 index 53e92c418..000000000 --- a/src/base/http/responsebuilder.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2015 Vladimir Golovnev - * - * 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. - */ - -#ifndef HTTP_RESPONSEBUILDER_H -#define HTTP_RESPONSEBUILDER_H - -#include -#include "types.h" - -namespace Http -{ - class ResponseBuilder : public QObject - { - public: - explicit ResponseBuilder(QObject *parent = 0); - - protected: - void status(uint code = 200, const QString &text = QLatin1String("OK")); - void header(const QString &name, const QString &value); - void print(const QString &text, const QString &type = CONTENT_TYPE_HTML); - void print(const QByteArray &data, const QString &type = CONTENT_TYPE_HTML); - void clear(); - - Response response() const; - - private: - void print_impl(const QByteArray &data, const QString &type); - - Response m_response; - }; -} - -#endif // HTTP_RESPONSEBUILDER_H diff --git a/src/base/http/responsegenerator.cpp b/src/base/http/responsegenerator.cpp deleted file mode 100644 index 4ac6cba61..000000000 --- a/src/base/http/responsegenerator.cpp +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2014 Vladimir Golovnev - * Copyright (C) 2006 Ishan Arora and 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 "responsegenerator.h" - -#include - -#include "base/utils/gzip.h" - -QByteArray Http::toByteArray(Response response) -{ - compressContent(response); - - response.headers[HEADER_CONTENT_LENGTH] = QString::number(response.content.length()); - response.headers[HEADER_DATE] = httpDate(); - - QByteArray buf; - buf.reserve(10 * 1024); - - // Status Line - buf += QString("HTTP/%1 %2 %3") - .arg("1.1", // TODO: depends on request - QString::number(response.status.code), - response.status.text) - .toLatin1() - .append(CRLF); - - // Header Fields - for (auto i = response.headers.constBegin(); i != response.headers.constEnd(); ++i) - buf += QString("%1: %2").arg(i.key(), i.value()).toLatin1().append(CRLF); - - // the first empty line - buf += CRLF; - - // message body // TODO: support HEAD request - buf += response.content; - - return buf; -} - -QString Http::httpDate() -{ - // [RFC 7231] 7.1.1.1. Date/Time Formats - // example: "Sun, 06 Nov 1994 08:49:37 GMT" - - return QLocale::c().toString(QDateTime::currentDateTimeUtc(), QLatin1String("ddd, dd MMM yyyy HH:mm:ss")) - .append(QLatin1String(" GMT")); -} - -void Http::compressContent(Response &response) -{ - if (response.headers.value(HEADER_CONTENT_ENCODING) != QLatin1String("gzip")) - return; - - response.headers.remove(HEADER_CONTENT_ENCODING); - - // for very small files, compressing them only wastes cpu cycles - const int contentSize = response.content.size(); - if (contentSize <= 1024) // 1 kb - return; - - // filter out known hard-to-compress types - const QString contentType = response.headers[HEADER_CONTENT_TYPE]; - if ((contentType == CONTENT_TYPE_GIF) || (contentType == CONTENT_TYPE_PNG)) - return; - - // try compressing - bool ok = false; - const QByteArray compressedData = Utils::Gzip::compress(response.content, 6, &ok); - if (!ok) - return; - - // "Content-Encoding: gzip\r\n" is 24 bytes long - if ((compressedData.size() + 24) >= contentSize) - return; - - response.content = compressedData; - response.headers[HEADER_CONTENT_ENCODING] = QLatin1String("gzip"); -} diff --git a/src/base/http/responsegenerator.h b/src/base/http/responsegenerator.h deleted file mode 100644 index 7c714e050..000000000 --- a/src/base/http/responsegenerator.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2014 Vladimir Golovnev - * Copyright (C) 2006 Ishan Arora and 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 HTTP_RESPONSEGENERATOR_H -#define HTTP_RESPONSEGENERATOR_H - -#include "types.h" - -namespace Http -{ - QByteArray toByteArray(Response response); - QString httpDate(); - void compressContent(Response &response); -} - -#endif // HTTP_RESPONSEGENERATOR_H diff --git a/src/base/http/server.cpp b/src/base/http/server.cpp deleted file mode 100644 index 5bd96ad56..000000000 --- a/src/base/http/server.cpp +++ /dev/null @@ -1,167 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2014 Vladimir Golovnev - * Copyright (C) 2006 Christophe Dumez - * Copyright (C) 2006 Ishan Arora - * - * 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. - */ - -#include "server.h" - -#include -#include -#include -#include - -#ifndef QT_NO_OPENSSL -#include -#else -#include -#endif - -#include "connection.h" - -static const int KEEP_ALIVE_DURATION = 7 * 1000; // milliseconds -static const int CONNECTIONS_LIMIT = 500; -static const int CONNECTIONS_SCAN_INTERVAL = 2; // seconds - -using namespace Http; - -Server::Server(IRequestHandler *requestHandler, QObject *parent) - : QTcpServer(parent) - , m_requestHandler(requestHandler) -#ifndef QT_NO_OPENSSL - , m_https(false) -#endif -{ - setProxy(QNetworkProxy::NoProxy); -#ifndef QT_NO_OPENSSL - QSslSocket::setDefaultCiphers(safeCipherList()); -#endif - - QTimer *dropConnectionTimer = new QTimer(this); - connect(dropConnectionTimer, &QTimer::timeout, this, &Server::dropTimedOutConnection); - dropConnectionTimer->start(CONNECTIONS_SCAN_INTERVAL * 1000); -} - -Server::~Server() -{ -} - -void Server::incomingConnection(qintptr socketDescriptor) -{ - if (m_connections.size() >= CONNECTIONS_LIMIT) return; - - QTcpSocket *serverSocket; -#ifndef QT_NO_OPENSSL - if (m_https) - serverSocket = new QSslSocket(this); - else -#endif - serverSocket = new QTcpSocket(this); - - if (!serverSocket->setSocketDescriptor(socketDescriptor)) { - delete serverSocket; - return; - } - -#ifndef QT_NO_OPENSSL - if (m_https) { - static_cast(serverSocket)->setProtocol(QSsl::SecureProtocols); - static_cast(serverSocket)->setPrivateKey(m_key); - static_cast(serverSocket)->setLocalCertificateChain(m_certificates); - static_cast(serverSocket)->setPeerVerifyMode(QSslSocket::VerifyNone); - static_cast(serverSocket)->startServerEncryption(); - } -#endif - - Connection *c = new Connection(serverSocket, m_requestHandler, this); - m_connections.append(c); -} - -void Server::dropTimedOutConnection() -{ - QMutableListIterator i(m_connections); - while (i.hasNext()) { - auto connection = i.next(); - if (connection->isClosed() || connection->hasExpired(KEEP_ALIVE_DURATION)) { - delete connection; - i.remove(); - } - } -} - -#ifndef QT_NO_OPENSSL -bool Server::setupHttps(const QByteArray &certificates, const QByteArray &key) -{ - QSslKey sslKey(key, QSsl::Rsa); - if (sslKey.isNull()) - sslKey = QSslKey(key, QSsl::Ec); - - const QList certs = QSslCertificate::fromData(certificates); - const bool areCertsValid = !certs.empty() && std::all_of(certs.begin(), certs.end(), [](const QSslCertificate &c) { return !c.isNull(); }); - - if (!sslKey.isNull() && areCertsValid) - { - m_key = sslKey; - m_certificates = certs; - m_https = true; - return true; - } - else - { - disableHttps(); - return false; - } -} - -void Server::disableHttps() -{ - m_https = false; - m_certificates.clear(); - m_key.clear(); -} - -QList Server::safeCipherList() const -{ - const QStringList badCiphers = {"idea", "rc4"}; - const QList allCiphers = QSslSocket::supportedCiphers(); - QList safeCiphers; - foreach (const QSslCipher &cipher, allCiphers) { - bool isSafe = true; - foreach (const QString &badCipher, badCiphers) { - if (cipher.name().contains(badCipher, Qt::CaseInsensitive)) { - isSafe = false; - break; - } - } - - if (isSafe) - safeCiphers += cipher; - } - - return safeCiphers; -} -#endif diff --git a/src/base/http/server.h b/src/base/http/server.h deleted file mode 100644 index d9b9ae19e..000000000 --- a/src/base/http/server.h +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2014 Vladimir Golovnev - * Copyright (C) 2006 Ishan Arora and 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 HTTP_SERVER_H -#define HTTP_SERVER_H - -#include - -#ifndef QT_NO_OPENSSL -#include -#include -#include -#endif - -namespace Http -{ - class IRequestHandler; - class Connection; - - class Server: public QTcpServer - { - Q_OBJECT - Q_DISABLE_COPY(Server) - - public: - Server(IRequestHandler *requestHandler, QObject *parent = 0); - ~Server(); - -#ifndef QT_NO_OPENSSL - bool setupHttps(const QByteArray &certificates, const QByteArray &key); - void disableHttps(); -#endif - - private slots: - void dropTimedOutConnection(); - - private: - void incomingConnection(qintptr socketDescriptor); - - IRequestHandler *m_requestHandler; - QList m_connections; // for tracking persistence connections - -#ifndef QT_NO_OPENSSL - QList safeCipherList() const; - - bool m_https; - QList m_certificates; - QSslKey m_key; -#endif - }; -} - -#endif // HTTP_SERVER_H diff --git a/src/base/http/types.h b/src/base/http/types.h deleted file mode 100644 index 488edf9e3..000000000 --- a/src/base/http/types.h +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2014 Vladimir Golovnev - * - * 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. - */ - -#ifndef HTTP_TYPES_H -#define HTTP_TYPES_H - -#include -#include -#include - -#include "base/types.h" - -namespace Http -{ - const char HEADER_CACHE_CONTROL[] = "cache-control"; - const char HEADER_CONTENT_ENCODING[] = "content-encoding"; - const char HEADER_CONTENT_LENGTH[] = "content-length"; - const char HEADER_CONTENT_SECURITY_POLICY[] = "content-security-policy"; - const char HEADER_CONTENT_TYPE[] = "content-type"; - const char HEADER_DATE[] = "date"; - const char HEADER_HOST[] = "host"; - const char HEADER_ORIGIN[] = "origin"; - const char HEADER_REFERER[] = "referer"; - const char HEADER_SET_COOKIE[] = "set-cookie"; - const char HEADER_X_CONTENT_TYPE_OPTIONS[] = "x-content-type-options"; - const char HEADER_X_FORWARDED_HOST[] = "x-forwarded-host"; - const char HEADER_X_FRAME_OPTIONS[] = "x-frame-options"; - const char HEADER_X_XSS_PROTECTION[] = "x-xss-protection"; - - const char CONTENT_TYPE_CSS[] = "text/css; charset=UTF-8"; - const char CONTENT_TYPE_GIF[] = "image/gif"; - const char CONTENT_TYPE_HTML[] = "text/html; charset=UTF-8"; - const char CONTENT_TYPE_JS[] = "application/javascript; charset=UTF-8"; - const char CONTENT_TYPE_JSON[] = "application/json"; - const char CONTENT_TYPE_PNG[] = "image/png"; - const char CONTENT_TYPE_TXT[] = "text/plain; charset=UTF-8"; - - // portability: "\r\n" doesn't guarantee mapping to the correct value - const char CRLF[] = {0x0D, 0x0A, '\0'}; - - struct Environment - { - QHostAddress localAddress; - quint16 localPort; - - QHostAddress clientAddress; - quint16 clientPort; - }; - - struct UploadedFile - { - QString filename; // original filename - QString type; // MIME type - QByteArray data; // File data - }; - - struct Request - { - QString method; - QString path; - QStringMap headers; - QStringMap gets; - QStringMap posts; - QVector files; - }; - - struct ResponseStatus - { - uint code; - QString text; - - ResponseStatus(uint code = 200, const QString& text = "OK"): code(code), text(text) {} - }; - - struct Response - { - ResponseStatus status; - QStringMap headers; - QByteArray content; - - Response(uint code = 200, const QString& text = "OK"): status(code, text) {} - }; -} - -#endif // HTTP_TYPES_H diff --git a/src/base/iconprovider.cpp b/src/base/iconprovider.cpp deleted file mode 100644 index 8d137556d..000000000 --- a/src/base/iconprovider.cpp +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2015 Vladimir Golovnev - * 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. - */ - -#include -#include "iconprovider.h" - -IconProvider::IconProvider(QObject *parent) - : QObject(parent) -{ -} - -IconProvider::~IconProvider() {} - -void IconProvider::initInstance() -{ - if (!m_instance) - m_instance = new IconProvider; -} - -void IconProvider::freeInstance() -{ - if (m_instance) { - delete m_instance; - m_instance = 0; - } -} - -IconProvider *IconProvider::instance() -{ - return m_instance; -} - -QString IconProvider::getIconPath(const QString &iconId) -{ - return ":/icons/qbt-theme/" + iconId + ".png"; -} - -IconProvider *IconProvider::m_instance = 0; diff --git a/src/base/iconprovider.h b/src/base/iconprovider.h deleted file mode 100644 index f9c00d63c..000000000 --- a/src/base/iconprovider.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2015 Vladimir Golovnev - * 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. - */ - -#ifndef ICONPROVIDER_H -#define ICONPROVIDER_H - -#include - -class QString; - -class IconProvider : public QObject -{ - Q_DISABLE_COPY(IconProvider) - -public: - static void initInstance(); - static void freeInstance(); - static IconProvider *instance(); - - virtual QString getIconPath(const QString &iconId); - -protected: - explicit IconProvider(QObject *parent = 0); - ~IconProvider(); - - static IconProvider *m_instance; -}; - -#endif // ICONPROVIDER_H diff --git a/src/base/indexrange.h b/src/base/indexrange.h deleted file mode 100644 index 77384d89f..000000000 --- a/src/base/indexrange.h +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2016 Eugene Shalygin - * - * 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. - */ - -#ifndef QBT_INDEXRANGE_H -#define QBT_INDEXRANGE_H - -#include - -// Interval is defined via [first;last] -template -class IndexInterval -{ -public: - using IndexType = Index; - - IndexInterval(IndexType first, IndexType last) - : m_first {first} - , m_last {last} - { - Q_ASSERT(first <= last); - } - - IndexType first() const - { - return m_first; - } - - IndexType last() const - { - return m_last; - } - -private: - IndexType m_first; - IndexType m_last; -}; - -template -inline IndexInterval makeInterval(T first, T last) -{ - return {first, last}; -} - -// range is defined via first index and size -template -class IndexRange -{ -public: - using IndexType = Index; - using IndexDiffType = IndexDiff; - - constexpr IndexRange() - : m_first {0} - , m_size {0} - { - } - - constexpr IndexRange(IndexType first, IndexDiffType size) - : m_first {first} - , m_size {size} - { - } - - constexpr IndexRange(const IndexInterval &interval) - : m_first {interval.first()} - , m_size {interval.last() - interval.first() + 1} - { - } - - constexpr IndexType begin() const - { - return m_first; - } - - constexpr IndexType end() const - { - return m_first + m_size; - } - - constexpr IndexDiffType size() const - { - return m_size; - } - - constexpr IndexType first() const - { - return m_first; - } - - constexpr IndexType last() const - { - return m_first + m_size - 1; - } - - constexpr bool isEmpty() const - { - return m_size == 0; - } - -private: - IndexType m_first; - IndexDiffType m_size; -}; - -#endif // QBT_INDEXRANGE_H diff --git a/src/base/logger.cpp b/src/base/logger.cpp deleted file mode 100644 index 53855fb10..000000000 --- a/src/base/logger.cpp +++ /dev/null @@ -1,97 +0,0 @@ -#include "logger.h" - -#include -#include "base/utils/string.h" - -Logger* Logger::m_instance = 0; - -Logger::Logger() - : lock(QReadWriteLock::Recursive) - , msgCounter(0) - , peerCounter(0) -{ -} - -Logger::~Logger() {} - -Logger *Logger::instance() -{ - return m_instance; -} - -void Logger::initInstance() -{ - if (!m_instance) - m_instance = new Logger; -} - -void Logger::freeInstance() -{ - if (m_instance) { - delete m_instance; - m_instance = 0; - } -} - -void Logger::addMessage(const QString &message, const Log::MsgType &type) -{ - QWriteLocker locker(&lock); - - Log::Msg temp = { msgCounter++, QDateTime::currentMSecsSinceEpoch(), type, message.toHtmlEscaped() }; - m_messages.push_back(temp); - - if (m_messages.size() >= MAX_LOG_MESSAGES) - m_messages.pop_front(); - - emit newLogMessage(temp); -} - -void Logger::addPeer(const QString &ip, bool blocked, const QString &reason) -{ - QWriteLocker locker(&lock); - - Log::Peer temp = { peerCounter++, QDateTime::currentMSecsSinceEpoch(), ip.toHtmlEscaped(), blocked, reason.toHtmlEscaped() }; - m_peers.push_back(temp); - - if (m_peers.size() >= MAX_LOG_MESSAGES) - m_peers.pop_front(); - - emit newLogPeer(temp); -} - -QVector Logger::getMessages(int lastKnownId) const -{ - QReadLocker locker(&lock); - - int diff = msgCounter - lastKnownId - 1; - int size = m_messages.size(); - - if ((lastKnownId == -1) || (diff >= size)) - return m_messages; - - if (diff <= 0) - return QVector(); - - return m_messages.mid(size - diff); -} - -QVector Logger::getPeers(int lastKnownId) const -{ - QReadLocker locker(&lock); - - int diff = peerCounter - lastKnownId - 1; - int size = m_peers.size(); - - if ((lastKnownId == -1) || (diff >= size)) - return m_peers; - - if (diff <= 0) - return QVector(); - - return m_peers.mid(size - diff); -} - -void LogMsg(const QString &message, const Log::MsgType &type) -{ - Logger::instance()->addMessage(message, type); -} diff --git a/src/base/logger.h b/src/base/logger.h deleted file mode 100644 index 441a7408b..000000000 --- a/src/base/logger.h +++ /dev/null @@ -1,77 +0,0 @@ -#ifndef LOGGER_H -#define LOGGER_H - -#include -#include -#include -#include - -const int MAX_LOG_MESSAGES = 20000; - -namespace Log -{ - enum MsgType - { - ALL = -1, - NORMAL = 0x1, - INFO = 0x2, - WARNING = 0x4, - CRITICAL = 0x8 //ERROR is defined by libtorrent and results in compiler error - }; - Q_DECLARE_FLAGS(MsgTypes, MsgType) - - struct Msg - { - int id; - qint64 timestamp; - MsgType type; - QString message; - }; - - struct Peer - { - int id; - qint64 timestamp; - QString ip; - bool blocked; - QString reason; - }; -} - -Q_DECLARE_OPERATORS_FOR_FLAGS(Log::MsgTypes) - -class Logger : public QObject -{ - Q_OBJECT - Q_DISABLE_COPY(Logger) - -public: - static void initInstance(); - static void freeInstance(); - static Logger *instance(); - - void addMessage(const QString &message, const Log::MsgType &type = Log::NORMAL); - void addPeer(const QString &ip, bool blocked, const QString &reason = QString()); - QVector getMessages(int lastKnownId = -1) const; - QVector getPeers(int lastKnownId = -1) const; - -signals: - void newLogMessage(const Log::Msg &message); - void newLogPeer(const Log::Peer &peer); - -private: - Logger(); - ~Logger(); - - static Logger* m_instance; - QVector m_messages; - QVector m_peers; - mutable QReadWriteLock lock; - int msgCounter; - int peerCounter; -}; - -// Helper function -void LogMsg(const QString &message, const Log::MsgType &type = Log::NORMAL); - -#endif // LOGGER_H diff --git a/src/base/net/dnsupdater.cpp b/src/base/net/dnsupdater.cpp deleted file mode 100644 index 2a57e1e99..000000000 --- a/src/base/net/dnsupdater.cpp +++ /dev/null @@ -1,301 +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 -#include -#include -#include - -#include "base/logger.h" -#include "base/net/downloadmanager.h" -#include "base/net/downloadhandler.h" -#include "dnsupdater.h" - -using namespace Net; - -DNSUpdater::DNSUpdater(QObject *parent) - : QObject(parent) - , m_state(OK) - , m_service(DNS::NONE) -{ - updateCredentials(); - - // Load saved settings from previous session - const Preferences *const pref = Preferences::instance(); - m_lastIPCheckTime = pref->getDNSLastUpd(); - m_lastIP = QHostAddress(pref->getDNSLastIP()); - - // 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 - Preferences *const pref = Preferences::instance(); - pref->setDNSLastUpd(m_lastIPCheckTime); - pref->setDNSLastIP(m_lastIP.toString()); -} - -void DNSUpdater::checkPublicIP() -{ - Q_ASSERT(m_state == OK); - - DownloadHandler *handler = DownloadManager::instance()->downloadUrl( - "http://checkip.dyndns.org", false, 0, false, - "qBittorrent/" QBT_VERSION_2); - connect(handler, SIGNAL(downloadFinished(QString, QByteArray)), SLOT(ipRequestFinished(QString, QByteArray))); - connect(handler, SIGNAL(downloadFailed(QString, QString)), SLOT(ipRequestFailed(QString, QString))); - - m_lastIPCheckTime = QDateTime::currentDateTime(); -} - -void DNSUpdater::ipRequestFinished(const QString &url, const QByteArray &data) -{ - Q_UNUSED(url); - - // Parse response - QRegExp ipregex("Current IP Address:\\s+([^<]+)"); - if (ipregex.indexIn(data) >= 0) { - QString ipStr = ipregex.cap(1); - qDebug() << Q_FUNC_INFO << "Regular expression captured the following IP:" << ipStr; - QHostAddress newIp(ipStr); - if (!newIp.isNull()) { - if (m_lastIP != newIp) { - qDebug() << Q_FUNC_INFO << "The IP address changed, report the change to DynDNS..."; - qDebug() << m_lastIP.toString() << "->" << newIp.toString(); - m_lastIP = newIp; - updateDNSService(); - } - } - else { - qWarning() << Q_FUNC_INFO << "Failed to construct a QHostAddress from the IP string"; - } - } - else { - qWarning() << Q_FUNC_INFO << "Regular expression failed to capture the IP address"; - } -} - -void DNSUpdater::ipRequestFailed(const QString &url, const QString &error) -{ - Q_UNUSED(url); - qWarning() << "IP request failed:" << error; -} - -void DNSUpdater::updateDNSService() -{ - qDebug() << Q_FUNC_INFO; - - m_lastIPCheckTime = QDateTime::currentDateTime(); - DownloadHandler *handler = DownloadManager::instance()->downloadUrl( - getUpdateUrl(), false, 0, false, - "qBittorrent/" QBT_VERSION_2); - connect(handler, SIGNAL(downloadFinished(QString, QByteArray)), SLOT(ipUpdateFinished(QString, QByteArray))); - connect(handler, SIGNAL(downloadFailed(QString, QString)), SLOT(ipUpdateFailed(QString, QString))); -} - -QString 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"); - - QUrlQuery urlQuery(url); - urlQuery.addQueryItem("hostname", m_domain); - urlQuery.addQueryItem("myip", m_lastIP.toString()); - url.setQuery(urlQuery); - Q_ASSERT(url.isValid()); - - qDebug() << Q_FUNC_INFO << url.toString(); - return url.toString(); -} - -void DNSUpdater::ipUpdateFinished(const QString &url, const QByteArray &data) -{ - Q_UNUSED(url); - // Parse reply - processIPUpdateReply(data); -} - -void DNSUpdater::ipUpdateFailed(const QString &url, const QString &error) -{ - Q_UNUSED(url); - qWarning() << "IP update failed:" << error; -} - -void DNSUpdater::processIPUpdateReply(const QString &reply) -{ - Logger *const logger = Logger::instance(); - qDebug() << Q_FUNC_INFO << reply; - QString code = reply.split(" ").first(); - qDebug() << Q_FUNC_INFO << "Code:" << code; - - if ((code == "good") || (code == "nochg")) { - logger->addMessage(tr("Your dynamic DNS was successfully updated."), Log::INFO); - return; - } - - if ((code == "911") || (code == "dnserr")) { - logger->addMessage(tr("Dynamic DNS error: The service is temporarily unavailable, it will be retried in 30 minutes."), Log::CRITICAL); - 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") { - logger->addMessage(tr("Dynamic DNS error: hostname supplied does not exist under specified account."), Log::CRITICAL); - m_state = INVALID_CREDS; - return; - } - - if (code == "badauth") { - logger->addMessage(tr("Dynamic DNS error: Invalid username/password."), Log::CRITICAL); - m_state = INVALID_CREDS; - return; - } - - if (code == "badagent") { - logger->addMessage(tr("Dynamic DNS error: qBittorrent was blacklisted by the service, please report a bug at http://bugs.qbittorrent.org."), - Log::CRITICAL); - m_state = FATAL; - return; - } - - if (code == "!donator") { - logger->addMessage(tr("Dynamic DNS error: %1 was returned by the service, please report a bug at http://bugs.qbittorrent.org.").arg("!donator"), - Log::CRITICAL); - m_state = FATAL; - return; - } - - if (code == "abuse") { - logger->addMessage(tr("Dynamic DNS error: Your username was blocked due to abuse."), Log::CRITICAL); - m_state = FATAL; - return; - } -} - -void DNSUpdater::updateCredentials() -{ - if (m_state == FATAL) return; - Preferences *const pref = Preferences::instance(); - Logger *const logger = Logger::instance(); - 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) { - logger->addMessage(tr("Dynamic DNS error: supplied domain name is invalid."), Log::CRITICAL); - 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) { - logger->addMessage(tr("Dynamic DNS error: supplied username is too short."), Log::CRITICAL); - 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) { - logger->addMessage(tr("Dynamic DNS error: supplied password is too short."), Log::CRITICAL); - 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("https://www.noip.com/remote-access"); - default: - Q_ASSERT(0); - } - return QUrl(); -} diff --git a/src/base/net/dnsupdater.h b/src/base/net/dnsupdater.h deleted file mode 100644 index 2c3cb6c38..000000000 --- a/src/base/net/dnsupdater.h +++ /dev/null @@ -1,90 +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 -#include -#include -#include - -#include "base/preferences.h" - -namespace Net -{ - // 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(const QString &url, const QByteArray &data); - void ipRequestFailed(const QString &url, const QString &error); - void updateDNSService(); - void ipUpdateFinished(const QString &url, const QByteArray &data); - void ipUpdateFailed(const QString &url, const QString &error); - - private: - enum State - { - OK, - INVALID_CREDS, - FATAL - }; - - static const int IP_CHECK_INTERVAL_MS = 1800000; // 30 min - - QString getUpdateUrl() const; - void processIPUpdateReply(const QString &reply); - - 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; - }; -} - -#endif // DNSUPDATER_H diff --git a/src/base/net/downloadhandler.cpp b/src/base/net/downloadhandler.cpp deleted file mode 100644 index 96a5068bf..000000000 --- a/src/base/net/downloadhandler.cpp +++ /dev/null @@ -1,248 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2015 Vladimir Golovnev - * Copyright (C) 2006 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. - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "base/utils/fs.h" -#include "base/utils/gzip.h" -#include "base/utils/misc.h" -#include "downloadmanager.h" -#include "downloadhandler.h" - -static QString errorCodeToString(QNetworkReply::NetworkError status); - -using namespace Net; - -DownloadHandler::DownloadHandler(QNetworkReply *reply, DownloadManager *manager, bool saveToFile, qint64 limit, bool handleRedirectToMagnet) - : QObject(manager) - , m_reply(reply) - , m_manager(manager) - , m_saveToFile(saveToFile) - , m_sizeLimit(limit) - , m_handleRedirectToMagnet(handleRedirectToMagnet) - , m_url(reply->url().toString()) -{ - init(); -} - -DownloadHandler::~DownloadHandler() -{ - if (m_reply) - delete m_reply; -} - -// Returns original url -QString DownloadHandler::url() const -{ - return m_url; -} - -void DownloadHandler::processFinishedDownload() -{ - QString url = m_reply->url().toString(); - qDebug("Download finished: %s", qPrintable(url)); - // Check if the request was successful - if (m_reply->error() != QNetworkReply::NoError) { - // Failure - qDebug("Download failure (%s), reason: %s", qPrintable(url), qPrintable(errorCodeToString(m_reply->error()))); - emit downloadFailed(m_url, errorCodeToString(m_reply->error())); - this->deleteLater(); - } - else { - // Check if the server ask us to redirect somewhere else - const QVariant redirection = m_reply->attribute(QNetworkRequest::RedirectionTargetAttribute); - if (redirection.isValid()) { - // We should redirect - handleRedirection(redirection.toUrl()); - } - else { - // Success - QByteArray replyData = m_reply->readAll(); - if (m_reply->rawHeader("Content-Encoding") == "gzip") { - // decompress gzip reply - replyData = Utils::Gzip::decompress(replyData); - } - - if (m_saveToFile) { - QString filePath; - if (saveToFile(replyData, filePath)) - emit downloadFinished(m_url, filePath); - else - emit downloadFailed(m_url, tr("I/O Error")); - } - else { - emit downloadFinished(m_url, replyData); - } - - this->deleteLater(); - } - } -} - -void DownloadHandler::checkDownloadSize(qint64 bytesReceived, qint64 bytesTotal) -{ - QString msg = tr("The file size is %1. It exceeds the download limit of %2."); - - if (bytesTotal > 0) { - // Total number of bytes is available - if (bytesTotal > m_sizeLimit) { - m_reply->abort(); - emit downloadFailed(m_url, msg.arg(Utils::Misc::friendlyUnit(bytesTotal)).arg(Utils::Misc::friendlyUnit(m_sizeLimit))); - } - else { - disconnect(m_reply, SIGNAL(downloadProgress(qint64, qint64)), this, SLOT(checkDownloadSize(qint64, qint64))); - } - } - else if (bytesReceived > m_sizeLimit) { - m_reply->abort(); - emit downloadFailed(m_url, msg.arg(Utils::Misc::friendlyUnit(bytesReceived)).arg(Utils::Misc::friendlyUnit(m_sizeLimit))); - } -} - -void DownloadHandler::init() -{ - m_reply->setParent(this); - if (m_sizeLimit > 0) - connect(m_reply, SIGNAL(downloadProgress(qint64, qint64)), this, SLOT(checkDownloadSize(qint64, qint64))); - connect(m_reply, SIGNAL(finished()), this, SLOT(processFinishedDownload())); -} - -bool DownloadHandler::saveToFile(const QByteArray &replyData, QString &filePath) -{ - QTemporaryFile *tmpfile = new QTemporaryFile(Utils::Fs::tempPath() + "XXXXXX"); - if (!tmpfile->open()) { - delete tmpfile; - return false; - } - - tmpfile->setAutoRemove(false); - filePath = tmpfile->fileName(); - qDebug("Temporary filename is: %s", qPrintable(filePath)); - if (m_reply->isOpen() || m_reply->open(QIODevice::ReadOnly)) { - 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; - return true; - } - else { - delete tmpfile; - Utils::Fs::forceRemove(filePath); - } - - return false; -} - -void DownloadHandler::handleRedirection(QUrl newUrl) -{ - // Resolve relative urls - if (newUrl.isRelative()) - newUrl = m_reply->url().resolved(newUrl); - - const QString newUrlString = newUrl.toString(); - qDebug("Redirecting from %s to %s", qPrintable(m_reply->url().toString()), qPrintable(newUrlString)); - - // Redirect to magnet workaround - if (newUrlString.startsWith("magnet:", Qt::CaseInsensitive)) { - qDebug("Magnet redirect detected."); - m_reply->abort(); - if (m_handleRedirectToMagnet) - emit redirectedToMagnet(m_url, newUrlString); - else - emit downloadFailed(m_url, tr("Unexpected redirect to magnet URI.")); - - this->deleteLater(); - } - else { - DownloadHandler *tmp = m_manager->downloadUrl(newUrlString, m_saveToFile, m_sizeLimit, m_handleRedirectToMagnet); - m_reply->deleteLater(); - m_reply = tmp->m_reply; - init(); - tmp->m_reply = 0; - delete tmp; - } -} - -QString errorCodeToString(QNetworkReply::NetworkError status) -{ - switch(status) { - case QNetworkReply::HostNotFoundError: - return QObject::tr("The remote host name was not found (invalid hostname)"); - case QNetworkReply::OperationCanceledError: - return QObject::tr("The operation was canceled"); - case QNetworkReply::RemoteHostClosedError: - return QObject::tr("The remote server closed the connection prematurely, before the entire reply was received and processed"); - case QNetworkReply::TimeoutError: - return QObject::tr("The connection to the remote server timed out"); - case QNetworkReply::SslHandshakeFailedError: - return QObject::tr("SSL/TLS handshake failed"); - case QNetworkReply::ConnectionRefusedError: - return QObject::tr("The remote server refused the connection"); - case QNetworkReply::ProxyConnectionRefusedError: - return QObject::tr("The connection to the proxy server was refused"); - case QNetworkReply::ProxyConnectionClosedError: - return QObject::tr("The proxy server closed the connection prematurely"); - case QNetworkReply::ProxyNotFoundError: - return QObject::tr("The proxy host name was not found"); - case QNetworkReply::ProxyTimeoutError: - return QObject::tr("The connection to the proxy timed out or the proxy did not reply in time to the request sent"); - case QNetworkReply::ProxyAuthenticationRequiredError: - return QObject::tr("The proxy requires authentication in order to honor the request but did not accept any credentials offered"); - case QNetworkReply::ContentAccessDenied: - return QObject::tr("The access to the remote content was denied (401)"); - case QNetworkReply::ContentOperationNotPermittedError: - return QObject::tr("The operation requested on the remote content is not permitted"); - case QNetworkReply::ContentNotFoundError: - return QObject::tr("The remote content was not found at the server (404)"); - case QNetworkReply::AuthenticationRequiredError: - return QObject::tr("The remote server requires authentication to serve the content but the credentials provided were not accepted"); - case QNetworkReply::ProtocolUnknownError: - return QObject::tr("The Network Access API cannot honor the request because the protocol is not known"); - case QNetworkReply::ProtocolInvalidOperationError: - return QObject::tr("The requested operation is invalid for this protocol"); - case QNetworkReply::UnknownNetworkError: - return QObject::tr("An unknown network-related error was detected"); - case QNetworkReply::UnknownProxyError: - return QObject::tr("An unknown proxy-related error was detected"); - case QNetworkReply::UnknownContentError: - return QObject::tr("An unknown error related to the remote content was detected"); - case QNetworkReply::ProtocolFailure: - return QObject::tr("A breakdown in protocol was detected"); - default: - return QObject::tr("Unknown error"); - } -} diff --git a/src/base/net/downloadhandler.h b/src/base/net/downloadhandler.h deleted file mode 100644 index f4afa7491..000000000 --- a/src/base/net/downloadhandler.h +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2015 Vladimir Golovnev - * Copyright (C) 2006 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. - */ - -#ifndef NET_DOWNLOADHANDLER_H -#define NET_DOWNLOADHANDLER_H - -#include - -QT_BEGIN_NAMESPACE -class QNetworkAccessManager; -class QNetworkReply; -class QUrl; -QT_END_NAMESPACE - -namespace Net -{ - class DownloadManager; - - class DownloadHandler : public QObject - { - Q_OBJECT - - public: - DownloadHandler(QNetworkReply *reply, DownloadManager *manager, bool saveToFile = false, qint64 limit = 0, bool handleRedirectToMagnet = false); - ~DownloadHandler(); - - QString url() const; - - signals: - void downloadFinished(const QString &url, const QByteArray &data); - void downloadFinished(const QString &url, const QString &filePath); - void downloadFailed(const QString &url, const QString &reason); - void redirectedToMagnet(const QString &url, const QString &magnetUri); - - private slots: - void processFinishedDownload(); - void checkDownloadSize(qint64 bytesReceived, qint64 bytesTotal); - - private: - void init(); - bool saveToFile(const QByteArray &replyData, QString &filePath); - void handleRedirection(QUrl newUrl); - - QNetworkReply *m_reply; - DownloadManager *m_manager; - bool m_saveToFile; - qint64 m_sizeLimit; - bool m_handleRedirectToMagnet; - QString m_url; - }; -} - -#endif // NET_DOWNLOADHANDLER_H diff --git a/src/base/net/downloadmanager.cpp b/src/base/net/downloadmanager.cpp deleted file mode 100644 index 547c30807..000000000 --- a/src/base/net/downloadmanager.cpp +++ /dev/null @@ -1,230 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2015 Vladimir Golovnev - * Copyright (C) 2006 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. - */ - -#include "downloadmanager.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "base/preferences.h" -#include "downloadhandler.h" -#include "proxyconfigurationmanager.h" - -// Spoof Firefox 38 user agent to avoid web server banning -const char DEFAULT_USER_AGENT[] = "Mozilla/5.0 (X11; Linux i686; rv:38.0) Gecko/20100101 Firefox/38.0"; - -namespace -{ - class NetworkCookieJar: public QNetworkCookieJar - { - public: - explicit NetworkCookieJar(QObject *parent = 0) - : QNetworkCookieJar(parent) - { - QDateTime now = QDateTime::currentDateTime(); - QList cookies = Preferences::instance()->getNetworkCookies(); - foreach (const QNetworkCookie &cookie, Preferences::instance()->getNetworkCookies()) { - if (cookie.isSessionCookie() || (cookie.expirationDate() <= now)) - cookies.removeAll(cookie); - } - - setAllCookies(cookies); - } - - ~NetworkCookieJar() - { - QDateTime now = QDateTime::currentDateTime(); - QList cookies = allCookies(); - foreach (const QNetworkCookie &cookie, allCookies()) { - if (cookie.isSessionCookie() || (cookie.expirationDate() <= now)) - cookies.removeAll(cookie); - } - - Preferences::instance()->setNetworkCookies(cookies); - } - - using QNetworkCookieJar::allCookies; - using QNetworkCookieJar::setAllCookies; - - QList cookiesForUrl(const QUrl &url) const override - { - QDateTime now = QDateTime::currentDateTime(); - QList cookies = QNetworkCookieJar::cookiesForUrl(url); - foreach (const QNetworkCookie &cookie, QNetworkCookieJar::cookiesForUrl(url)) { - if (!cookie.isSessionCookie() && (cookie.expirationDate() <= now)) - cookies.removeAll(cookie); - } - - return cookies; - } - - bool setCookiesFromUrl(const QList &cookieList, const QUrl &url) override - { - QDateTime now = QDateTime::currentDateTime(); - QList cookies = cookieList; - foreach (const QNetworkCookie &cookie, cookieList) { - if (!cookie.isSessionCookie() && (cookie.expirationDate() <= now)) - cookies.removeAll(cookie); - } - - return QNetworkCookieJar::setCookiesFromUrl(cookies, url); - } - }; -} - -using namespace Net; - -DownloadManager *DownloadManager::m_instance = 0; - -DownloadManager::DownloadManager(QObject *parent) - : QObject(parent) -{ -#ifndef QT_NO_OPENSSL - connect(&m_networkManager, SIGNAL(sslErrors(QNetworkReply *, QList)), this, SLOT(ignoreSslErrors(QNetworkReply *, QList))); -#endif - m_networkManager.setCookieJar(new NetworkCookieJar(this)); -} - -void DownloadManager::initInstance() -{ - if (!m_instance) - m_instance = new DownloadManager; -} - -void DownloadManager::freeInstance() -{ - if (m_instance) { - delete m_instance; - m_instance = 0; - } -} - -DownloadManager *DownloadManager::instance() -{ - return m_instance; -} - -DownloadHandler *DownloadManager::downloadUrl(const QString &url, bool saveToFile, qint64 limit, bool handleRedirectToMagnet, const QString &userAgent) -{ - // Update proxy settings - applyProxySettings(); - - // Process download request - qDebug("url is %s", qPrintable(url)); - const QUrl qurl = QUrl(url); - QNetworkRequest request(qurl); - - if (userAgent.isEmpty()) - request.setRawHeader("User-Agent", DEFAULT_USER_AGENT); - else - request.setRawHeader("User-Agent", userAgent.toUtf8()); - - // Spoof HTTP Referer to allow adding torrent link from Torcache/KickAssTorrents - request.setRawHeader("Referer", request.url().toEncoded().data()); - - qDebug("Downloading %s...", request.url().toEncoded().data()); - qDebug() << "Cookies:" << m_networkManager.cookieJar()->cookiesForUrl(request.url()); - // accept gzip - request.setRawHeader("Accept-Encoding", "gzip"); - return new DownloadHandler(m_networkManager.get(request), this, saveToFile, limit, handleRedirectToMagnet); -} - -QList DownloadManager::cookiesForUrl(const QUrl &url) const -{ - return m_networkManager.cookieJar()->cookiesForUrl(url); -} - -bool DownloadManager::setCookiesFromUrl(const QList &cookieList, const QUrl &url) -{ - return m_networkManager.cookieJar()->setCookiesFromUrl(cookieList, url); -} - -QList DownloadManager::allCookies() const -{ - return static_cast(m_networkManager.cookieJar())->allCookies(); -} - -void DownloadManager::setAllCookies(const QList &cookieList) -{ - static_cast(m_networkManager.cookieJar())->setAllCookies(cookieList); -} - -bool DownloadManager::deleteCookie(const QNetworkCookie &cookie) -{ - return static_cast(m_networkManager.cookieJar())->deleteCookie(cookie); -} - -void DownloadManager::applyProxySettings() -{ - auto proxyManager = ProxyConfigurationManager::instance(); - ProxyConfiguration proxyConfig = proxyManager->proxyConfiguration(); - QNetworkProxy proxy; - - if (!proxyManager->isProxyOnlyForTorrents() && (proxyConfig.type != ProxyType::None)) { - // Proxy enabled - proxy.setHostName(proxyConfig.ip); - proxy.setPort(proxyConfig.port); - // Default proxy type is HTTP, we must change if it is SOCKS5 - if ((proxyConfig.type == ProxyType::SOCKS5) || (proxyConfig.type == ProxyType::SOCKS5_PW)) { - qDebug() << Q_FUNC_INFO << "using SOCKS proxy"; - proxy.setType(QNetworkProxy::Socks5Proxy); - } - else { - qDebug() << Q_FUNC_INFO << "using HTTP proxy"; - proxy.setType(QNetworkProxy::HttpProxy); - } - // Authentication? - if (proxyManager->isAuthenticationRequired()) { - qDebug("Proxy requires authentication, authenticating"); - proxy.setUser(proxyConfig.username); - proxy.setPassword(proxyConfig.password); - } - } - else { - proxy.setType(QNetworkProxy::NoProxy); - } - - m_networkManager.setProxy(proxy); -} - -#ifndef QT_NO_OPENSSL -void DownloadManager::ignoreSslErrors(QNetworkReply *reply, const QList &errors) -{ - Q_UNUSED(errors) - // Ignore all SSL errors - reply->ignoreSslErrors(); -} -#endif diff --git a/src/base/net/downloadmanager.h b/src/base/net/downloadmanager.h deleted file mode 100644 index 35acc4777..000000000 --- a/src/base/net/downloadmanager.h +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2015 Vladimir Golovnev - * Copyright (C) 2006 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. - */ - -#ifndef NET_DOWNLOADMANAGER_H -#define NET_DOWNLOADMANAGER_H - -#include -#include - -class QNetworkReply; -class QNetworkCookie; -class QSslError; -class QUrl; - -namespace Net -{ - class DownloadHandler; - - class DownloadManager : public QObject - { - Q_OBJECT - - public: - static void initInstance(); - static void freeInstance(); - static DownloadManager *instance(); - - DownloadHandler *downloadUrl(const QString &url, bool saveToFile = false, qint64 limit = 0, bool handleRedirectToMagnet = false, const QString &userAgent = ""); - QList cookiesForUrl(const QUrl &url) const; - bool setCookiesFromUrl(const QList &cookieList, const QUrl &url); - QList allCookies() const; - void setAllCookies(const QList &cookieList); - bool deleteCookie(const QNetworkCookie &cookie); - - private slots: - #ifndef QT_NO_OPENSSL - void ignoreSslErrors(QNetworkReply *,const QList &); - #endif - - private: - explicit DownloadManager(QObject *parent = 0); - - void applyProxySettings(); - - static DownloadManager *m_instance; - QNetworkAccessManager m_networkManager; - }; -} - -#endif // NET_DOWNLOADMANAGER_H diff --git a/src/base/net/geoipmanager.cpp b/src/base/net/geoipmanager.cpp deleted file mode 100644 index efa150de9..000000000 --- a/src/base/net/geoipmanager.cpp +++ /dev/null @@ -1,462 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2015 Vladimir Golovnev - * Copyright (C) 2010 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. - */ - -#include -#include -#include -#include -#include - -#include "base/logger.h" -#include "base/preferences.h" -#include "base/profile.h" -#include "base/utils/fs.h" -#include "base/utils/gzip.h" -#include "downloadmanager.h" -#include "downloadhandler.h" -#include "private/geoipdatabase.h" -#include "geoipmanager.h" - -static const char DATABASE_URL[] = "https://geolite.maxmind.com/download/geoip/database/GeoLite2-Country.mmdb.gz"; -static const char GEOIP_FOLDER[] = "GeoIP"; -static const char GEOIP_FILENAME[] = "GeoLite2-Country.mmdb"; -static const int UPDATE_INTERVAL = 30; // Days between database updates - -using namespace Net; - -// GeoIPManager - -GeoIPManager *GeoIPManager::m_instance = 0; - -GeoIPManager::GeoIPManager() - : m_enabled(false) - , m_geoIPDatabase(0) -{ - configure(); - connect(Preferences::instance(), SIGNAL(changed()), SLOT(configure())); -} - -GeoIPManager::~GeoIPManager() -{ - if (m_geoIPDatabase) - delete m_geoIPDatabase; -} - -void GeoIPManager::initInstance() -{ - if (!m_instance) - m_instance = new GeoIPManager; -} - -void GeoIPManager::freeInstance() -{ - if (m_instance) { - delete m_instance; - m_instance = 0; - } -} - -GeoIPManager *GeoIPManager::instance() -{ - return m_instance; -} - -void GeoIPManager::loadDatabase() -{ - if (m_geoIPDatabase) { - delete m_geoIPDatabase; - m_geoIPDatabase = 0; - } - - QString filepath = Utils::Fs::expandPathAbs( - QString("%1%2/%3").arg(specialFolderLocation(SpecialFolder::Data)) - .arg(GEOIP_FOLDER).arg(GEOIP_FILENAME)); - - QString error; - m_geoIPDatabase = GeoIPDatabase::load(filepath, error); - if (m_geoIPDatabase) - Logger::instance()->addMessage(tr("GeoIP database loaded. Type: %1. Build time: %2.") - .arg(m_geoIPDatabase->type()).arg(m_geoIPDatabase->buildEpoch().toString()), - Log::INFO); - else - Logger::instance()->addMessage(tr("Couldn't load GeoIP database. Reason: %1").arg(error), Log::WARNING); - - manageDatabaseUpdate(); -} - -void GeoIPManager::manageDatabaseUpdate() -{ - if (!m_geoIPDatabase || (m_geoIPDatabase->buildEpoch().daysTo(QDateTime::currentDateTimeUtc()) >= UPDATE_INTERVAL)) - downloadDatabaseFile(); -} - -void GeoIPManager::downloadDatabaseFile() -{ - DownloadHandler *handler = DownloadManager::instance()->downloadUrl(DATABASE_URL); - connect(handler, SIGNAL(downloadFinished(QString, QByteArray)), SLOT(downloadFinished(QString, QByteArray))); - connect(handler, SIGNAL(downloadFailed(QString, QString)), SLOT(downloadFailed(QString, QString))); -} - -QString GeoIPManager::lookup(const QHostAddress &hostAddr) const -{ - if (m_enabled && m_geoIPDatabase) - return m_geoIPDatabase->lookup(hostAddr); - - return QString(); -} - -QString GeoIPManager::CountryName(const QString &countryISOCode) -{ - static QHash countries; - static bool initialized = false; - - // ISO 3166-1 alpha-2 codes - // http://www.iso.org/iso/home/standards/country_codes/country_names_and_code_elements_txt-temp.htm - if (!initialized) { - // Officially assigned - countries["AD"] = tr("Andorra"); - countries["AE"] = tr("United Arab Emirates"); - countries["AF"] = tr("Afghanistan"); - countries["AG"] = tr("Antigua and Barbuda"); - countries["AI"] = tr("Anguilla"); - countries["AL"] = tr("Albania"); - countries["AM"] = tr("Armenia"); - countries["AO"] = tr("Angola"); - countries["AQ"] = tr("Antarctica"); - countries["AR"] = tr("Argentina"); - countries["AS"] = tr("American Samoa"); - countries["AT"] = tr("Austria"); - countries["AU"] = tr("Australia"); - countries["AW"] = tr("Aruba"); - countries["AX"] = tr("Aland Islands"); - countries["AZ"] = tr("Azerbaijan"); - countries["BA"] = tr("Bosnia and Herzegovina"); - countries["BB"] = tr("Barbados"); - countries["BD"] = tr("Bangladesh"); - countries["BE"] = tr("Belgium"); - countries["BF"] = tr("Burkina Faso"); - countries["BG"] = tr("Bulgaria"); - countries["BH"] = tr("Bahrain"); - countries["BI"] = tr("Burundi"); - countries["BJ"] = tr("Benin"); - countries["BL"] = tr("Saint Barthelemy"); - countries["BM"] = tr("Bermuda"); - countries["BN"] = tr("Brunei Darussalam"); - countries["BO"] = tr("Bolivia, Plurinational State of"); - countries["BQ"] = tr("Bonaire, Sint Eustatius and Saba"); - countries["BR"] = tr("Brazil"); - countries["BS"] = tr("Bahamas"); - countries["BT"] = tr("Bhutan"); - countries["BV"] = tr("Bouvet Island"); - countries["BW"] = tr("Botswana"); - countries["BY"] = tr("Belarus"); - countries["BZ"] = tr("Belize"); - countries["CA"] = tr("Canada"); - countries["CC"] = tr("Cocos (Keeling) Islands"); - countries["CD"] = tr("Congo, The Democratic Republic of the"); - countries["CF"] = tr("Central African Republic"); - countries["CG"] = tr("Congo"); - countries["CH"] = tr("Switzerland"); - countries["CI"] = tr("Cote d'Ivoire"); - countries["CK"] = tr("Cook Islands"); - countries["CL"] = tr("Chile"); - countries["CM"] = tr("Cameroon"); - countries["CN"] = tr("China"); - countries["CO"] = tr("Colombia"); - countries["CR"] = tr("Costa Rica"); - countries["CU"] = tr("Cuba"); - countries["CV"] = tr("Cape Verde"); - countries["CW"] = tr("Curacao"); - countries["CX"] = tr("Christmas Island"); - countries["CY"] = tr("Cyprus"); - countries["CZ"] = tr("Czech Republic"); - countries["DE"] = tr("Germany"); - countries["DJ"] = tr("Djibouti"); - countries["DK"] = tr("Denmark"); - countries["DM"] = tr("Dominica"); - countries["DO"] = tr("Dominican Republic"); - countries["DZ"] = tr("Algeria"); - countries["EC"] = tr("Ecuador"); - countries["EE"] = tr("Estonia"); - countries["EG"] = tr("Egypt"); - countries["EH"] = tr("Western Sahara"); - countries["ER"] = tr("Eritrea"); - countries["ES"] = tr("Spain"); - countries["ET"] = tr("Ethiopia"); - countries["FI"] = tr("Finland"); - countries["FJ"] = tr("Fiji"); - countries["FK"] = tr("Falkland Islands (Malvinas)"); - countries["FM"] = tr("Micronesia, Federated States of"); - countries["FO"] = tr("Faroe Islands"); - countries["FR"] = tr("France"); - countries["GA"] = tr("Gabon"); - countries["GB"] = tr("United Kingdom"); - countries["GD"] = tr("Grenada"); - countries["GE"] = tr("Georgia"); - countries["GF"] = tr("French Guiana"); - countries["GG"] = tr("Guernsey"); - countries["GH"] = tr("Ghana"); - countries["GI"] = tr("Gibraltar"); - countries["GL"] = tr("Greenland"); - countries["GM"] = tr("Gambia"); - countries["GN"] = tr("Guinea"); - countries["GP"] = tr("Guadeloupe"); - countries["GQ"] = tr("Equatorial Guinea"); - countries["GR"] = tr("Greece"); - countries["GS"] = tr("South Georgia and the South Sandwich Islands"); - countries["GT"] = tr("Guatemala"); - countries["GU"] = tr("Guam"); - countries["GW"] = tr("Guinea-Bissau"); - countries["GY"] = tr("Guyana"); - countries["HK"] = tr("Hong Kong"); - countries["HM"] = tr("Heard Island and McDonald Islands"); - countries["HN"] = tr("Honduras"); - countries["HR"] = tr("Croatia"); - countries["HT"] = tr("Haiti"); - countries["HU"] = tr("Hungary"); - countries["ID"] = tr("Indonesia"); - countries["IE"] = tr("Ireland"); - countries["IL"] = tr("Israel"); - countries["IM"] = tr("Isle of Man"); - countries["IN"] = tr("India"); - countries["IO"] = tr("British Indian Ocean Territory"); - countries["IQ"] = tr("Iraq"); - countries["IR"] = tr("Iran, Islamic Republic of"); - countries["IS"] = tr("Iceland"); - countries["IT"] = tr("Italy"); - countries["JE"] = tr("Jersey"); - countries["JM"] = tr("Jamaica"); - countries["JO"] = tr("Jordan"); - countries["JP"] = tr("Japan"); - countries["KE"] = tr("Kenya"); - countries["KG"] = tr("Kyrgyzstan"); - countries["KH"] = tr("Cambodia"); - countries["KI"] = tr("Kiribati"); - countries["KM"] = tr("Comoros"); - countries["KN"] = tr("Saint Kitts and Nevis"); - countries["KP"] = tr("Korea, Democratic People's Republic of"); - countries["KR"] = tr("Korea, Republic of"); - countries["KW"] = tr("Kuwait"); - countries["KY"] = tr("Cayman Islands"); - countries["KZ"] = tr("Kazakhstan"); - countries["LA"] = tr("Lao People's Democratic Republic"); - countries["LB"] = tr("Lebanon"); - countries["LC"] = tr("Saint Lucia"); - countries["LI"] = tr("Liechtenstein"); - countries["LK"] = tr("Sri Lanka"); - countries["LR"] = tr("Liberia"); - countries["LS"] = tr("Lesotho"); - countries["LT"] = tr("Lithuania"); - countries["LU"] = tr("Luxembourg"); - countries["LV"] = tr("Latvia"); - countries["LY"] = tr("Libya"); - countries["MA"] = tr("Morocco"); - countries["MC"] = tr("Monaco"); - countries["MD"] = tr("Moldova, Republic of"); - countries["ME"] = tr("Montenegro"); - countries["MF"] = tr("Saint Martin (French part)"); - countries["MG"] = tr("Madagascar"); - countries["MH"] = tr("Marshall Islands"); - countries["MK"] = tr("Macedonia, The Former Yugoslav Republic of"); - countries["ML"] = tr("Mali"); - countries["MM"] = tr("Myanmar"); - countries["MN"] = tr("Mongolia"); - countries["MO"] = tr("Macao"); - countries["MP"] = tr("Northern Mariana Islands"); - countries["MQ"] = tr("Martinique"); - countries["MR"] = tr("Mauritania"); - countries["MS"] = tr("Montserrat"); - countries["MT"] = tr("Malta"); - countries["MU"] = tr("Mauritius"); - countries["MV"] = tr("Maldives"); - countries["MW"] = tr("Malawi"); - countries["MX"] = tr("Mexico"); - countries["MY"] = tr("Malaysia"); - countries["MZ"] = tr("Mozambique"); - countries["NA"] = tr("Namibia"); - countries["NC"] = tr("New Caledonia"); - countries["NE"] = tr("Niger"); - countries["NF"] = tr("Norfolk Island"); - countries["NG"] = tr("Nigeria"); - countries["NI"] = tr("Nicaragua"); - countries["NL"] = tr("Netherlands"); - countries["NO"] = tr("Norway"); - countries["NP"] = tr("Nepal"); - countries["NR"] = tr("Nauru"); - countries["NU"] = tr("Niue"); - countries["NZ"] = tr("New Zealand"); - countries["OM"] = tr("Oman"); - countries["PA"] = tr("Panama"); - countries["PE"] = tr("Peru"); - countries["PF"] = tr("French Polynesia"); - countries["PG"] = tr("Papua New Guinea"); - countries["PH"] = tr("Philippines"); - countries["PK"] = tr("Pakistan"); - countries["PL"] = tr("Poland"); - countries["PM"] = tr("Saint Pierre and Miquelon"); - countries["PN"] = tr("Pitcairn"); - countries["PR"] = tr("Puerto Rico"); - countries["PS"] = tr("Palestine, State of"); - countries["PT"] = tr("Portugal"); - countries["PW"] = tr("Palau"); - countries["PY"] = tr("Paraguay"); - countries["QA"] = tr("Qatar"); - countries["RE"] = tr("Reunion"); - countries["RO"] = tr("Romania"); - countries["RS"] = tr("Serbia"); - countries["RU"] = tr("Russian Federation"); - countries["RW"] = tr("Rwanda"); - countries["SA"] = tr("Saudi Arabia"); - countries["SB"] = tr("Solomon Islands"); - countries["SC"] = tr("Seychelles"); - countries["SD"] = tr("Sudan"); - countries["SE"] = tr("Sweden"); - countries["SG"] = tr("Singapore"); - countries["SH"] = tr("Saint Helena, Ascension and Tristan da Cunha"); - countries["SI"] = tr("Slovenia"); - countries["SJ"] = tr("Svalbard and Jan Mayen"); - countries["SK"] = tr("Slovakia"); - countries["SL"] = tr("Sierra Leone"); - countries["SM"] = tr("San Marino"); - countries["SN"] = tr("Senegal"); - countries["SO"] = tr("Somalia"); - countries["SR"] = tr("Suriname"); - countries["SS"] = tr("South Sudan"); - countries["ST"] = tr("Sao Tome and Principe"); - countries["SV"] = tr("El Salvador"); - countries["SX"] = tr("Sint Maarten (Dutch part)"); - countries["SY"] = tr("Syrian Arab Republic"); - countries["SZ"] = tr("Swaziland"); - countries["TC"] = tr("Turks and Caicos Islands"); - countries["TD"] = tr("Chad"); - countries["TF"] = tr("French Southern Territories"); - countries["TG"] = tr("Togo"); - countries["TH"] = tr("Thailand"); - countries["TJ"] = tr("Tajikistan"); - countries["TK"] = tr("Tokelau"); - countries["TL"] = tr("Timor-Leste"); - countries["TM"] = tr("Turkmenistan"); - countries["TN"] = tr("Tunisia"); - countries["TO"] = tr("Tonga"); - countries["TR"] = tr("Turkey"); - countries["TT"] = tr("Trinidad and Tobago"); - countries["TV"] = tr("Tuvalu"); - countries["TW"] = tr("Taiwan"); - countries["TZ"] = tr("Tanzania, United Republic of"); - countries["UA"] = tr("Ukraine"); - countries["UG"] = tr("Uganda"); - countries["UM"] = tr("United States Minor Outlying Islands"); - countries["US"] = tr("United States"); - countries["UY"] = tr("Uruguay"); - countries["UZ"] = tr("Uzbekistan"); - countries["VA"] = tr("Holy See (Vatican City State)"); - countries["VC"] = tr("Saint Vincent and the Grenadines"); - countries["VE"] = tr("Venezuela, Bolivarian Republic of"); - countries["VG"] = tr("Virgin Islands, British"); - countries["VI"] = tr("Virgin Islands, U.S."); - countries["VN"] = tr("Viet Nam"); - countries["VU"] = tr("Vanuatu"); - countries["WF"] = tr("Wallis and Futuna"); - countries["WS"] = tr("Samoa"); - countries["YE"] = tr("Yemen"); - countries["YT"] = tr("Mayotte"); - countries["ZA"] = tr("South Africa"); - countries["ZM"] = tr("Zambia"); - countries["ZW"] = tr("Zimbabwe"); - - countries[QString()] = tr("N/A"); - initialized = true; - } - - return countries.value(countryISOCode, tr("N/A")); -} - -void GeoIPManager::configure() -{ - const bool enabled = Preferences::instance()->resolvePeerCountries(); - if (m_enabled != enabled) { - m_enabled = enabled; - if (m_enabled && !m_geoIPDatabase) { - loadDatabase(); - } - else if (!m_enabled && m_geoIPDatabase) { - delete m_geoIPDatabase; - m_geoIPDatabase = 0; - } - } -} - -void GeoIPManager::downloadFinished(const QString &url, QByteArray data) -{ - Q_UNUSED(url); - - bool ok = false; - data = Utils::Gzip::decompress(data, &ok); - if (!ok) { - Logger::instance()->addMessage(tr("Could not decompress GeoIP database file."), Log::WARNING); - return; - } - - QString error; - GeoIPDatabase *geoIPDatabase = GeoIPDatabase::load(data, error); - if (geoIPDatabase) { - if (!m_geoIPDatabase || (geoIPDatabase->buildEpoch() > m_geoIPDatabase->buildEpoch())) { - if (m_geoIPDatabase) - delete m_geoIPDatabase; - m_geoIPDatabase = geoIPDatabase; - Logger::instance()->addMessage(tr("GeoIP database loaded. Type: %1. Build time: %2.") - .arg(m_geoIPDatabase->type()).arg(m_geoIPDatabase->buildEpoch().toString()), - Log::INFO); - QString targetPath = Utils::Fs::expandPathAbs( - specialFolderLocation(SpecialFolder::Data) + GEOIP_FOLDER); - if (!QDir(targetPath).exists()) - QDir().mkpath(targetPath); - QFile targetFile(QString("%1/%2").arg(targetPath).arg(GEOIP_FILENAME)); - if (!targetFile.open(QFile::WriteOnly) || (targetFile.write(data) == -1)) { - Logger::instance()->addMessage( - tr("Couldn't save downloaded GeoIP database file."), Log::WARNING); - } - else { - Logger::instance()->addMessage(tr("Successfully updated GeoIP database."), Log::INFO); - } - } - else { - delete geoIPDatabase; - } - } - else { - Logger::instance()->addMessage(tr("Couldn't load GeoIP database. Reason: %1").arg(error), Log::WARNING); - } -} - -void GeoIPManager::downloadFailed(const QString &url, const QString &reason) -{ - Q_UNUSED(url); - Logger::instance()->addMessage(tr("Couldn't download GeoIP database file. Reason: %1").arg(reason), Log::WARNING); -} diff --git a/src/base/net/geoipmanager.h b/src/base/net/geoipmanager.h deleted file mode 100644 index ddfb7d25a..000000000 --- a/src/base/net/geoipmanager.h +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2015 Vladimir Golovnev - * Copyright (C) 2010 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. - */ - -#ifndef NET_GEOIPMANAGER_H -#define NET_GEOIPMANAGER_H - -#include -#include - -class QHostAddress; -class QString; - -class GeoIPDatabase; - -namespace Net -{ - class GeoIPManager : public QObject - { - Q_OBJECT - - public: - static void initInstance(); - static void freeInstance(); - static GeoIPManager *instance(); - - QString lookup(const QHostAddress &hostAddr) const; - - static QString CountryName(const QString &countryISOCode); - - private slots: - void configure(); - void downloadFinished(const QString &url, QByteArray data); - void downloadFailed(const QString &url, const QString &reason); - - private: - GeoIPManager(); - ~GeoIPManager(); - - void loadDatabase(); - void manageDatabaseUpdate(); - void downloadDatabaseFile(); - - bool m_enabled; - GeoIPDatabase *m_geoIPDatabase; - - static GeoIPManager *m_instance; - }; -} - -#endif // NET_GEOIPMANAGER_H diff --git a/src/base/net/portforwarder.cpp b/src/base/net/portforwarder.cpp deleted file mode 100644 index 3b7dd5ebc..000000000 --- a/src/base/net/portforwarder.cpp +++ /dev/null @@ -1,146 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2015 Vladimir Golovnev - * - * 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. - */ - -#include "portforwarder.h" - -#include - -#include -#include - -#include "base/logger.h" -#include "base/settingsstorage.h" - -static const QString KEY_ENABLED = QLatin1String("Network/PortForwardingEnabled"); - -namespace libt = libtorrent; -using namespace Net; - -PortForwarder::PortForwarder(libtorrent::session *provider, QObject *parent) - : QObject(parent) - , m_active(false) - , m_provider(provider) -{ - if (SettingsStorage::instance()->loadValue(KEY_ENABLED, true).toBool()) - start(); -} - -PortForwarder::~PortForwarder() -{ - stop(); -} - -void PortForwarder::initInstance(libtorrent::session *const provider) -{ - if (!m_instance) - m_instance = new PortForwarder(provider); -} - -void PortForwarder::freeInstance() -{ - if (m_instance) { - delete m_instance; - m_instance = 0; - } -} - -PortForwarder *PortForwarder::instance() -{ - return m_instance; -} - -bool PortForwarder::isEnabled() const -{ - return m_active; -} - -void PortForwarder::setEnabled(bool enabled) -{ - if (m_active != enabled) { - if (enabled) - start(); - else - stop(); - - SettingsStorage::instance()->storeValue(KEY_ENABLED, enabled); - } -} - -void PortForwarder::addPort(quint16 port) -{ - if (!m_mappedPorts.contains(port)) { - m_mappedPorts.insert(port, 0); - if (m_active) - m_mappedPorts[port] = m_provider->add_port_mapping(libt::session::tcp, port, port); - } -} - -void PortForwarder::deletePort(quint16 port) -{ - if (m_mappedPorts.contains(port)) { - if (m_active) - m_provider->delete_port_mapping(m_mappedPorts[port]); - m_mappedPorts.remove(port); - } -} - -void PortForwarder::start() -{ - qDebug("Enabling UPnP / NAT-PMP"); -#if LIBTORRENT_VERSION_NUM < 10100 - m_provider->start_upnp(); - m_provider->start_natpmp(); -#else - libt::settings_pack settingsPack = m_provider->get_settings(); - settingsPack.set_bool(libt::settings_pack::enable_upnp, true); - settingsPack.set_bool(libt::settings_pack::enable_natpmp, true); - m_provider->apply_settings(settingsPack); -#endif - foreach (quint16 port, m_mappedPorts.keys()) - m_mappedPorts[port] = m_provider->add_port_mapping(libt::session::tcp, port, port); - m_active = true; - Logger::instance()->addMessage(tr("UPnP / NAT-PMP support [ON]"), Log::INFO); -} - -void PortForwarder::stop() -{ - qDebug("Disabling UPnP / NAT-PMP"); -#if LIBTORRENT_VERSION_NUM < 10100 - m_provider->stop_upnp(); - m_provider->stop_natpmp(); -#else - libt::settings_pack settingsPack = m_provider->get_settings(); - settingsPack.set_bool(libt::settings_pack::enable_upnp, false); - settingsPack.set_bool(libt::settings_pack::enable_natpmp, false); - m_provider->apply_settings(settingsPack); -#endif - m_active = false; - Logger::instance()->addMessage(tr("UPnP / NAT-PMP support [OFF]"), Log::INFO); -} - -PortForwarder *PortForwarder::m_instance = 0; diff --git a/src/base/net/portforwarder.h b/src/base/net/portforwarder.h deleted file mode 100644 index 7044e006b..000000000 --- a/src/base/net/portforwarder.h +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2015 Vladimir Golovnev - * - * 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. - */ - -#ifndef NET_PORTFORWARDER_H -#define NET_PORTFORWARDER_H - -#include -#include - -namespace libtorrent -{ - class session; -} - -namespace Net -{ - class PortForwarder : public QObject - { - Q_OBJECT - Q_DISABLE_COPY(PortForwarder) - - public: - static void initInstance(libtorrent::session *const provider); - static void freeInstance(); - static PortForwarder *instance(); - - bool isEnabled() const; - void setEnabled(bool enabled); - - void addPort(quint16 port); - void deletePort(quint16 port); - - private: - explicit PortForwarder(libtorrent::session *const provider, QObject *parent = 0); - ~PortForwarder(); - - void start(); - void stop(); - - bool m_active; - libtorrent::session *m_provider; - QHash m_mappedPorts; - - static PortForwarder *m_instance; - }; -} - -#endif // NET_PORTFORWARDER_H diff --git a/src/base/net/private/geoipdatabase.cpp b/src/base/net/private/geoipdatabase.cpp deleted file mode 100644 index 9594ac929..000000000 --- a/src/base/net/private/geoipdatabase.cpp +++ /dev/null @@ -1,488 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2015 Vladimir Golovnev - * - * 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. - */ - -#include -#include -#include -#include -#include -#include - -#include "base/types.h" -#include "geoipdatabase.h" - -namespace -{ - const quint32 __ENDIAN_TEST__ = 0x00000001; - const bool __IS_LITTLE_ENDIAN__ = (reinterpret_cast(&__ENDIAN_TEST__)[0] == 0x01); - const qint32 MAX_FILE_SIZE = 67108864; // 64MB - const char DB_TYPE[] = "GeoLite2-Country"; - const quint32 MAX_METADATA_SIZE = 131072; // 128KB - const char METADATA_BEGIN_MARK[] = "\xab\xcd\xefMaxMind.com"; - const char DATA_SECTION_SEPARATOR[16] = { 0 }; - - enum class DataType - { - Unknown = 0, - Pointer = 1, - String = 2, - Double = 3, - Bytes = 4, - Integer16 = 5, - Integer32 = 6, - Map = 7, - SignedInteger32 = 8, - Integer64 = 9, - Integer128 = 10, - Array = 11, - DataCacheContainer = 12, - EndMarker = 13, - Boolean = 14, - Float = 15 - }; -} - -struct DataFieldDescriptor -{ - DataType fieldType; - union - { - quint32 fieldSize; - quint32 offset; // Pointer - }; -}; - -GeoIPDatabase::GeoIPDatabase(quint32 size) - : m_ipVersion(0) - , m_recordSize(0) - , m_nodeCount(0) - , m_nodeSize(0) - , m_indexSize(0) - , m_recordBytes(0) - , m_size(size) - , m_data(new uchar[size]) -{ -} - -GeoIPDatabase *GeoIPDatabase::load(const QString &filename, QString &error) -{ - GeoIPDatabase *db = 0; - QFile file(filename); - if (file.size() > MAX_FILE_SIZE) { - error = tr("Unsupported database file size."); - return 0; - } - - if (!file.open(QFile::ReadOnly)) { - error = file.errorString(); - return 0; - } - - db = new GeoIPDatabase(file.size()); - - if (file.read(reinterpret_cast(db->m_data), db->m_size) != db->m_size) { - error = file.errorString(); - delete db; - return 0; - } - - - if (!db->parseMetadata(db->readMetadata(), error) || !db->loadDB(error)) { - delete db; - return 0; - } - - return db; -} - -GeoIPDatabase *GeoIPDatabase::load(const QByteArray &data, QString &error) -{ - GeoIPDatabase *db = 0; - if (data.size() > MAX_FILE_SIZE) { - error = tr("Unsupported database file size."); - return 0; - } - - db = new GeoIPDatabase(data.size()); - - memcpy(reinterpret_cast(db->m_data), data.constData(), db->m_size); - - if (!db->parseMetadata(db->readMetadata(), error) || !db->loadDB(error)) { - delete db; - return 0; - } - - return db; -} - -GeoIPDatabase::~GeoIPDatabase() -{ - delete [] m_data; -} - -QString GeoIPDatabase::type() const -{ - return DB_TYPE; -} - -quint16 GeoIPDatabase::ipVersion() const -{ - return m_ipVersion; -} - -QDateTime GeoIPDatabase::buildEpoch() const -{ - return m_buildEpoch; -} - -QString GeoIPDatabase::lookup(const QHostAddress &hostAddr) const -{ - Q_IPV6ADDR addr = hostAddr.toIPv6Address(); - - const uchar *ptr = m_data; - - for (int i = 0; i < 16; ++i) { - for (int j = 0; j < 8; ++j) { - bool right = static_cast((addr[i] >> (7 - j)) & 1); - // Interpret the left/right record as number - if (right) - ptr += m_recordBytes; - - quint32 id = 0; - uchar *idPtr = reinterpret_cast(&id); - memcpy(&idPtr[4 - m_recordBytes], ptr, m_recordBytes); - fromBigEndian(idPtr, 4); - - if (id == m_nodeCount) { - return QString(); - } - else if (id > m_nodeCount) { - QString country = m_countries.value(id); - if (country.isEmpty()) { - const quint32 offset = id - m_nodeCount - sizeof(DATA_SECTION_SEPARATOR); - quint32 tmp = offset + m_indexSize + sizeof(DATA_SECTION_SEPARATOR); - QVariant val = readDataField(tmp); - if (val.userType() == QMetaType::QVariantHash) { - country = val.toHash()["country"].toHash()["iso_code"].toString(); - m_countries[id] = country; - } - } - return country; - } - else { - ptr = m_data + (id * m_nodeSize); - } - } - } - - return QString(); -} - -#define CHECK_METADATA_REQ(key, type) \ -if (!metadata.contains(#key)) { \ - error = errMsgNotFound.arg(#key); \ - return false; \ -} \ -else if (metadata.value(#key).userType() != QMetaType::type) { \ - error = errMsgInvalid.arg(#key); \ - return false; \ -} - -#define CHECK_METADATA_OPT(key, type) \ -if (metadata.contains(#key)) { \ - if (metadata.value(#key).userType() != QMetaType::type) { \ - error = errMsgInvalid.arg(#key); \ - return false; \ - } \ -} - -bool GeoIPDatabase::parseMetadata(const QVariantHash &metadata, QString &error) -{ - const QString errMsgNotFound = tr("Metadata error: '%1' entry not found."); - const QString errMsgInvalid = tr("Metadata error: '%1' entry has invalid type."); - - qDebug() << "Parsing MaxMindDB metadata..."; - - CHECK_METADATA_REQ(binary_format_major_version, UShort); - CHECK_METADATA_REQ(binary_format_minor_version, UShort); - uint versionMajor = metadata.value("binary_format_major_version").toUInt(); - uint versionMinor = metadata.value("binary_format_minor_version").toUInt(); - if (versionMajor != 2) { - error = tr("Unsupported database version: %1.%2").arg(versionMajor).arg(versionMinor); - return false; - } - - CHECK_METADATA_REQ(ip_version, UShort); - m_ipVersion = metadata.value("ip_version").value(); - if (m_ipVersion != 6) { - error = tr("Unsupported IP version: %1").arg(m_ipVersion); - return false; - } - - CHECK_METADATA_REQ(record_size, UShort); - m_recordSize = metadata.value("record_size").value(); - if (m_recordSize != 24) { - error = tr("Unsupported record size: %1").arg(m_recordSize); - return false; - } - m_nodeSize = m_recordSize / 4; - m_recordBytes = m_nodeSize / 2; - - CHECK_METADATA_REQ(node_count, UInt); - m_nodeCount = metadata.value("node_count").value(); - m_indexSize = m_nodeCount * m_nodeSize; - - CHECK_METADATA_REQ(database_type, QString); - QString dbType = metadata.value("database_type").toString(); - if (dbType != DB_TYPE) { - error = tr("Invalid database type: %1").arg(dbType); - return false; - } - - CHECK_METADATA_REQ(build_epoch, ULongLong); - m_buildEpoch = QDateTime::fromTime_t(metadata.value("build_epoch").toULongLong()); - - CHECK_METADATA_OPT(languages, QVariantList); - CHECK_METADATA_OPT(description, QVariantHash); - - return true; -} - -bool GeoIPDatabase::loadDB(QString &error) const -{ - qDebug() << "Parsing MaxMindDB index tree..."; - - const int nodeSize = m_recordSize / 4; // in bytes - const int indexSize = m_nodeCount * nodeSize; - if ((m_size < (indexSize + sizeof(DATA_SECTION_SEPARATOR))) - || (memcmp(m_data + indexSize, DATA_SECTION_SEPARATOR, sizeof(DATA_SECTION_SEPARATOR)) != 0)) { - error = tr("Database corrupted: no data section found."); - return false; - } - - return true; -} - -QVariantHash GeoIPDatabase::readMetadata() const -{ - const char *ptr = reinterpret_cast(m_data); - quint32 size = m_size; - if (m_size > MAX_METADATA_SIZE) { - ptr += m_size - MAX_METADATA_SIZE; - size = MAX_METADATA_SIZE; - } - - const QByteArray data = QByteArray::fromRawData(ptr, size); - int index = data.lastIndexOf(METADATA_BEGIN_MARK); - if (index >= 0) { - if (m_size > MAX_METADATA_SIZE) - index += (m_size - MAX_METADATA_SIZE); // from begin of all data - quint32 offset = static_cast(index + strlen(METADATA_BEGIN_MARK)); - QVariant metadata = readDataField(offset); - if (metadata.userType() == QMetaType::QVariantHash) - return metadata.toHash(); - } - - return QVariantHash(); -} - -QVariant GeoIPDatabase::readDataField(quint32 &offset) const -{ - DataFieldDescriptor descr; - if (!readDataFieldDescriptor(offset, descr)) - return QVariant(); - - quint32 locOffset = offset; - bool usePointer = false; - if (descr.fieldType == DataType::Pointer) { - usePointer = true; - // convert offset from data section to global - locOffset = descr.offset + (m_nodeCount * m_recordSize / 4) + sizeof(DATA_SECTION_SEPARATOR); - if (!readDataFieldDescriptor(locOffset, descr)) - return QVariant(); - } - - QVariant fieldValue; - switch (descr.fieldType) { - case DataType::Pointer: - qDebug() << "* Illegal Pointer using"; - break; - case DataType::String: - fieldValue = QString::fromUtf8(reinterpret_cast(m_data + locOffset), descr.fieldSize); - locOffset += descr.fieldSize; - break; - case DataType::Double: - if (descr.fieldSize == 8) - fieldValue = readPlainValue(locOffset, descr.fieldSize); - else - qDebug() << "* Invalid field size for type: Double"; - break; - case DataType::Bytes: - fieldValue = QByteArray(reinterpret_cast(m_data + locOffset), descr.fieldSize); - locOffset += descr.fieldSize; - break; - case DataType::Integer16: - fieldValue = readPlainValue(locOffset, descr.fieldSize); - break; - case DataType::Integer32: - fieldValue = readPlainValue(locOffset, descr.fieldSize); - break; - case DataType::Map: - fieldValue = readMapValue(locOffset, descr.fieldSize); - break; - case DataType::SignedInteger32: - fieldValue = readPlainValue(locOffset, descr.fieldSize); - break; - case DataType::Integer64: - fieldValue = readPlainValue(locOffset, descr.fieldSize); - break; - case DataType::Integer128: - qDebug() << "* Unsupported data type: Integer128"; - break; - case DataType::Array: - fieldValue = readArrayValue(locOffset, descr.fieldSize); - break; - case DataType::DataCacheContainer: - qDebug() << "* Unsupported data type: DataCacheContainer"; - break; - case DataType::EndMarker: - qDebug() << "* Unsupported data type: EndMarker"; - break; - case DataType::Boolean: - fieldValue = QVariant::fromValue(static_cast(descr.fieldSize)); - break; - case DataType::Float: - if (descr.fieldSize == 4) - fieldValue = readPlainValue(locOffset, descr.fieldSize); - else - qDebug() << "* Invalid field size for type: Float"; - break; - default: - qDebug() << "* Unsupported data type: Unknown"; - } - - if (!usePointer) - offset = locOffset; - return fieldValue; -} - -bool GeoIPDatabase::readDataFieldDescriptor(quint32 &offset, DataFieldDescriptor &out) const -{ - const uchar *dataPtr = m_data + offset; - int availSize = m_size - offset; - if (availSize < 1) return false; - - out.fieldType = static_cast((dataPtr[0] & 0xE0) >> 5); - if (out.fieldType == DataType::Pointer) { - int size = ((dataPtr[0] & 0x18) >> 3); - if (availSize < (size + 2)) return false; - - if (size == 0) - out.offset = ((dataPtr[0] & 0x07) << 8) + dataPtr[1]; - else if (size == 1) - out.offset = ((dataPtr[0] & 0x07) << 16) + (dataPtr[1] << 8) + dataPtr[2] + 2048; - else if (size == 2) - out.offset = ((dataPtr[0] & 0x07) << 24) + (dataPtr[1] << 16) + (dataPtr[2] << 8) + dataPtr[3] + 526336; - else if (size == 3) - out.offset = (dataPtr[1] << 24) + (dataPtr[2] << 16) + (dataPtr[3] << 8) + dataPtr[4]; - - offset += size + 2; - return true; - } - - out.fieldSize = dataPtr[0] & 0x1F; - if (out.fieldSize <= 28) { - if (out.fieldType == DataType::Unknown) { - out.fieldType = static_cast(dataPtr[1] + 7); - if ((out.fieldType <= DataType::Map) || (out.fieldType > DataType::Float) || (availSize < 3)) - return false; - offset += 2; - } - else { - offset += 1; - } - } - else if (out.fieldSize == 29) { - if (availSize < 2) return false; - out.fieldSize = dataPtr[1] + 29; - offset += 2; - } - else if (out.fieldSize == 30) { - if (availSize < 3) return false; - out.fieldSize = (dataPtr[1] << 8) + dataPtr[2] + 285; - offset += 3; - } - else if (out.fieldSize == 31) { - if (availSize < 4) return false; - out.fieldSize = (dataPtr[1] << 16) + (dataPtr[2] << 8) + dataPtr[3] + 65821; - offset += 4; - } - - return true; -} - -void GeoIPDatabase::fromBigEndian(uchar *buf, quint32 len) const -{ - if (__IS_LITTLE_ENDIAN__) - std::reverse(buf, buf + len); -} - -QVariant GeoIPDatabase::readMapValue(quint32 &offset, quint32 count) const -{ - QVariantHash map; - - for (quint32 i = 0; i < count; ++i) { - QVariant field = readDataField(offset); - if (field.userType() != QMetaType::QString) - return QVariant(); - - QString key = field.toString(); - field = readDataField(offset); - if (field.userType() == QVariant::Invalid) - return QVariant(); - - map[key] = field; - } - - return map; -} - -QVariant GeoIPDatabase::readArrayValue(quint32 &offset, quint32 count) const -{ - QVariantList array; - - for (quint32 i = 0; i < count; ++i) { - QVariant field = readDataField(offset); - if (field.userType() == QVariant::Invalid) - return QVariant(); - - array.append(field); - } - - return array; -} diff --git a/src/base/net/private/geoipdatabase.h b/src/base/net/private/geoipdatabase.h deleted file mode 100644 index 329e28453..000000000 --- a/src/base/net/private/geoipdatabase.h +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2015 Vladimir Golovnev - * - * 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. - */ - -#ifndef GEOIPDATABASE_H -#define GEOIPDATABASE_H - -#include -#include - -class QHostAddress; -class QString; -class QByteArray; -class QDateTime; - -struct DataFieldDescriptor; - -class GeoIPDatabase -{ - Q_DECLARE_TR_FUNCTIONS(GeoIPDatabase) - -public: - static GeoIPDatabase *load(const QString &filename, QString &error); - static GeoIPDatabase *load(const QByteArray &data, QString &error); - - ~GeoIPDatabase(); - - QString type() const; - quint16 ipVersion() const; - QDateTime buildEpoch() const; - QString lookup(const QHostAddress &hostAddr) const; - -private: - GeoIPDatabase(quint32 size); - - bool parseMetadata(const QVariantHash &metadata, QString &error); - bool loadDB(QString &error) const; - QVariantHash readMetadata() const; - - QVariant readDataField(quint32 &offset) const; - bool readDataFieldDescriptor(quint32 &offset, DataFieldDescriptor &out) const; - void fromBigEndian(uchar *buf, quint32 len) const; - QVariant readMapValue(quint32 &offset, quint32 count) const; - QVariant readArrayValue(quint32 &offset, quint32 count) const; - - template - QVariant readPlainValue(quint32 &offset, quint8 len) const - { - T value = 0; - const uchar *const data = m_data + offset; - const quint32 availSize = m_size - offset; - - if ((len > 0) && (len <= sizeof(T) && (availSize >= len))) { - // copy input data to last 'len' bytes of 'value' - uchar *dst = reinterpret_cast(&value) + (sizeof(T) - len); - memcpy(dst, data, len); - fromBigEndian(reinterpret_cast(&value), sizeof(T)); - offset += len; - } - - return QVariant::fromValue(value); - } - - // Metadata - quint16 m_ipVersion; - quint16 m_recordSize; - quint32 m_nodeCount; - int m_nodeSize; - int m_indexSize; - int m_recordBytes; - QDateTime m_buildEpoch; - // Search data - mutable QHash m_countries; - quint32 m_size; - uchar *m_data; -}; - -#endif // GEOIPDATABASE_H diff --git a/src/base/net/proxyconfigurationmanager.cpp b/src/base/net/proxyconfigurationmanager.cpp deleted file mode 100644 index a91331bba..000000000 --- a/src/base/net/proxyconfigurationmanager.cpp +++ /dev/null @@ -1,163 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2016 Vladimir Golovnev - * - * 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. - */ - -#include "proxyconfigurationmanager.h" -#include "base/settingsstorage.h" - -#define SETTINGS_KEY(name) "Network/Proxy/" name -const QString KEY_ONLY_FOR_TORRENTS = SETTINGS_KEY("OnlyForTorrents"); -const QString KEY_TYPE = SETTINGS_KEY("Type"); -const QString KEY_IP = SETTINGS_KEY("IP"); -const QString KEY_PORT = SETTINGS_KEY("Port"); -const QString KEY_USERNAME = SETTINGS_KEY("Username"); -const QString KEY_PASSWORD = SETTINGS_KEY("Password"); - -namespace -{ - inline SettingsStorage *settings() { return SettingsStorage::instance(); } - - inline bool isSameConfig(const Net::ProxyConfiguration &conf1, const Net::ProxyConfiguration &conf2) - { - return conf1.type == conf2.type - && conf1.ip == conf2.ip - && conf1.port == conf2.port - && conf1.username == conf2.username - && conf1.password == conf2.password; - } -} - -using namespace Net; - -ProxyConfigurationManager *ProxyConfigurationManager::m_instance = nullptr; - -ProxyConfigurationManager::ProxyConfigurationManager(QObject *parent) - : QObject(parent) -{ - m_isProxyOnlyForTorrents = settings()->loadValue(KEY_ONLY_FOR_TORRENTS, false).toBool(); - m_config.type = static_cast( - settings()->loadValue(KEY_TYPE, static_cast(ProxyType::None)).toInt()); - if ((m_config.type < ProxyType::None) || (m_config.type > ProxyType::SOCKS4)) - m_config.type = ProxyType::None; - m_config.ip = settings()->loadValue(KEY_IP, "0.0.0.0").toString(); - m_config.port = static_cast(settings()->loadValue(KEY_PORT, 8080).toUInt()); - m_config.username = settings()->loadValue(KEY_USERNAME).toString(); - m_config.password = settings()->loadValue(KEY_PASSWORD).toString(); - configureProxy(); -} - -void ProxyConfigurationManager::initInstance() -{ - if (!m_instance) - m_instance = new ProxyConfigurationManager; -} - -void ProxyConfigurationManager::freeInstance() -{ - if (m_instance) { - delete m_instance; - m_instance = 0; - } -} - -ProxyConfigurationManager *ProxyConfigurationManager::instance() -{ - return m_instance; -} - -ProxyConfiguration ProxyConfigurationManager::proxyConfiguration() const -{ - return m_config; -} - -void ProxyConfigurationManager::setProxyConfiguration(const ProxyConfiguration &config) -{ - if (!isSameConfig(config, m_config)) { - m_config = config; - settings()->storeValue(KEY_TYPE, static_cast(config.type)); - settings()->storeValue(KEY_IP, config.ip); - settings()->storeValue(KEY_PORT, config.port); - settings()->storeValue(KEY_USERNAME, config.username); - settings()->storeValue(KEY_PASSWORD, config.password); - configureProxy(); - - emit proxyConfigurationChanged(); - } -} - -bool ProxyConfigurationManager::isProxyOnlyForTorrents() const -{ - return m_isProxyOnlyForTorrents || (m_config.type == ProxyType::SOCKS4); -} - -void ProxyConfigurationManager::setProxyOnlyForTorrents(bool onlyForTorrents) -{ - if (m_isProxyOnlyForTorrents != onlyForTorrents) { - settings()->storeValue(KEY_ONLY_FOR_TORRENTS, onlyForTorrents); - m_isProxyOnlyForTorrents = onlyForTorrents; - } -} - -bool ProxyConfigurationManager::isAuthenticationRequired() const -{ - return m_config.type == ProxyType::SOCKS5_PW - || m_config.type == ProxyType::HTTP_PW; -} - -void ProxyConfigurationManager::configureProxy() -{ - // Define environment variables for urllib in search engine plugins - QString proxyStrHTTP, proxyStrSOCK; - if (!m_isProxyOnlyForTorrents) { - switch (m_config.type) { - case ProxyType::HTTP_PW: - proxyStrHTTP = QString("http://%1:%2@%3:%4").arg(m_config.username) - .arg(m_config.password).arg(m_config.ip).arg(m_config.port); - break; - case ProxyType::HTTP: - proxyStrHTTP = QString("http://%1:%2").arg(m_config.ip).arg(m_config.port); - break; - case ProxyType::SOCKS5: - proxyStrSOCK = QString("%1:%2").arg(m_config.ip).arg(m_config.port); - break; - case ProxyType::SOCKS5_PW: - proxyStrSOCK = QString("%1:%2@%3:%4").arg(m_config.username) - .arg(m_config.password).arg(m_config.ip).arg(m_config.port); - break; - default: - qDebug("Disabling HTTP communications proxy"); - } - - qDebug("HTTP communications proxy string: %s" - , qPrintable((m_config.type == ProxyType::SOCKS5) || (m_config.type == ProxyType::SOCKS5_PW) - ? proxyStrSOCK : proxyStrHTTP)); - } - - qputenv("http_proxy", proxyStrHTTP.toLocal8Bit()); - qputenv("https_proxy", proxyStrHTTP.toLocal8Bit()); - qputenv("sock_proxy", proxyStrSOCK.toLocal8Bit()); -} diff --git a/src/base/net/proxyconfigurationmanager.h b/src/base/net/proxyconfigurationmanager.h deleted file mode 100644 index 3f21632c1..000000000 --- a/src/base/net/proxyconfigurationmanager.h +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2016 Vladimir Golovnev - * - * 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. - */ - -#ifndef NET_PROXYCONFIGURATIONMANAGER_H -#define NET_PROXYCONFIGURATIONMANAGER_H - -#include - -namespace Net -{ - enum class ProxyType - { - None = 0, - HTTP = 1, - SOCKS5 = 2, - HTTP_PW = 3, - SOCKS5_PW = 4, - SOCKS4 = 5 - }; - - struct ProxyConfiguration - { - ProxyType type = ProxyType::None; - QString ip = "0.0.0.0"; - ushort port = 8080; - QString username; - QString password; - }; - - class ProxyConfigurationManager: public QObject - { - Q_OBJECT - Q_DISABLE_COPY(ProxyConfigurationManager) - - explicit ProxyConfigurationManager(QObject *parent = nullptr); - ~ProxyConfigurationManager() = default; - - public: - static void initInstance(); - static void freeInstance(); - static ProxyConfigurationManager *instance(); - - ProxyConfiguration proxyConfiguration() const; - void setProxyConfiguration(const ProxyConfiguration &config); - bool isProxyOnlyForTorrents() const; - void setProxyOnlyForTorrents(bool onlyForTorrents); - - bool isAuthenticationRequired() const; - - signals: - void proxyConfigurationChanged(); - - private: - void configureProxy(); - - static ProxyConfigurationManager *m_instance; - ProxyConfiguration m_config; - bool m_isProxyOnlyForTorrents; - }; -} - -#endif // NET_PROXYCONFIGURATIONMANAGER_H diff --git a/src/base/net/reverseresolution.cpp b/src/base/net/reverseresolution.cpp deleted file mode 100644 index e3b9b706d..000000000 --- a/src/base/net/reverseresolution.cpp +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2006 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 -#include -#include - -#include -#include - -#include "reverseresolution.h" - -const int CACHE_SIZE = 500; - -using namespace Net; - -static inline bool isUsefulHostName(const QString &hostname, const QString &ip) -{ - return (!hostname.isEmpty() && hostname != ip); -} - -ReverseResolution::ReverseResolution(QObject *parent) - : QObject(parent) -{ - m_cache.setMaxCost(CACHE_SIZE); -} - -ReverseResolution::~ReverseResolution() -{ - qDebug("Deleting host name resolver..."); -} - -void ReverseResolution::resolve(const QString &ip) -{ - if (m_cache.contains(ip)) { - const QString &hostname = *m_cache.object(ip); - qDebug() << "Resolved host name using cache: " << ip << " -> " << hostname; - if (isUsefulHostName(hostname, ip)) - emit ipResolved(ip, hostname); - } - else { - // Actually resolve the ip - m_lookups.insert(QHostInfo::lookupHost(ip, this, SLOT(hostResolved(QHostInfo))), ip); - } -} - -void ReverseResolution::hostResolved(const QHostInfo &host) -{ - const QString &ip = m_lookups.take(host.lookupId()); - Q_ASSERT(!ip.isNull()); - - if (host.error() != QHostInfo::NoError) { - qDebug() << "DNS Reverse resolution error: " << host.errorString(); - return; - } - - const QString &hostname = host.hostName(); - - qDebug() << Q_FUNC_INFO << ip << QString("->") << hostname; - m_cache.insert(ip, new QString(hostname)); - if (isUsefulHostName(hostname, ip)) - emit ipResolved(ip, hostname); -} diff --git a/src/base/net/reverseresolution.h b/src/base/net/reverseresolution.h deleted file mode 100644 index ef181762a..000000000 --- a/src/base/net/reverseresolution.h +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2006 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 NET_REVERSERESOLUTION_H -#define NET_REVERSERESOLUTION_H - -#include -#include - -QT_BEGIN_NAMESPACE -class QHostInfo; -class QString; -QT_END_NAMESPACE - -namespace Net -{ - class ReverseResolution : public QObject - { - Q_OBJECT - Q_DISABLE_COPY(ReverseResolution) - - public: - explicit ReverseResolution(QObject *parent = 0); - ~ReverseResolution(); - - void resolve(const QString &ip); - - signals: - void ipResolved(const QString &ip, const QString &hostname); - - private slots: - void hostResolved(const QHostInfo &host); - - private: - QHash m_lookups; - QCache m_cache; - }; -} - -#endif // NET_REVERSERESOLUTION_H diff --git a/src/base/net/smtp.cpp b/src/base/net/smtp.cpp deleted file mode 100644 index fcc35b2e3..000000000 --- a/src/base/net/smtp.cpp +++ /dev/null @@ -1,546 +0,0 @@ -/* - * Bittorrent Client using Qt 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 - */ - -/* - * This code is based on QxtSmtp from libqxt (http://libqxt.org) - */ - -#include "smtp.h" -#include "base/preferences.h" -#include "base/logger.h" - -#include -#ifndef QT_NO_OPENSSL -#include -#else -#include -#endif -#include -#include -#include -#include -#include -#include -#include - -namespace -{ - const short DEFAULT_PORT = 25; -#ifndef QT_NO_OPENSSL - const short DEFAULT_PORT_SSL = 465; -#endif - - QByteArray hmacMD5(QByteArray key, const QByteArray &msg) - { - const int blockSize = 64; // HMAC-MD5 block size - if (key.length() > blockSize) // if key is longer than block size (64), reduce key length with MD5 compression - key = QCryptographicHash::hash(key, QCryptographicHash::Md5); - - QByteArray innerPadding(blockSize, char(0x36)); // initialize inner padding with char "6" - QByteArray outerPadding(blockSize, char(0x5c)); // initialize outer padding with char "\" - // ascii characters 0x36 ("6") and 0x5c ("\") are selected because they have large - // Hamming distance (http://en.wikipedia.org/wiki/Hamming_distance) - - for (int i = 0; i < key.length(); i++) { - innerPadding[i] = innerPadding[i] ^ key.at(i); // XOR operation between every byte in key and innerpadding, of key length - outerPadding[i] = outerPadding[i] ^ key.at(i); // XOR operation between every byte in key and outerpadding, of key length - } - - // result = hash ( outerPadding CONCAT hash ( innerPadding CONCAT baseString ) ).toBase64 - QByteArray total = outerPadding; - QByteArray part = innerPadding; - part.append(msg); - total.append(QCryptographicHash::hash(part, QCryptographicHash::Md5)); - return QCryptographicHash::hash(total, QCryptographicHash::Md5); - } - - QByteArray determineFQDN() - { - QString hostname = QHostInfo::localHostName(); - if (hostname.isEmpty()) - hostname = "localhost"; - - return hostname.toLocal8Bit(); - } -} // namespace - -using namespace Net; - -Smtp::Smtp(QObject *parent) - : QObject(parent) - , m_state(Init) - , m_useSsl(false) - , m_authType(AuthPlain) -{ - static bool needToRegisterMetaType = true; - - if (needToRegisterMetaType) { - qRegisterMetaType(); - needToRegisterMetaType = false; - } - -#ifndef QT_NO_OPENSSL - m_socket = new QSslSocket(this); -#else - m_socket = new QTcpSocket(this); -#endif - - connect(m_socket, SIGNAL(readyRead()), SLOT(readyRead())); - connect(m_socket, SIGNAL(disconnected()), SLOT(deleteLater())); - connect(m_socket, SIGNAL(error(QAbstractSocket::SocketError)), SLOT(error(QAbstractSocket::SocketError))); - - // Test hmacMD5 function (http://www.faqs.org/rfcs/rfc2202.html) - Q_ASSERT(hmacMD5("Jefe", "what do ya want for nothing?").toHex() - == "750c783e6ab0b503eaa86e310a5db738"); - Q_ASSERT(hmacMD5(QByteArray::fromHex("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b"), "Hi There").toHex() - == "9294727a3638bb1c13f48ef8158bfc9d"); -} - -Smtp::~Smtp() -{ - qDebug() << Q_FUNC_INFO; -} - -void Smtp::sendMail(const QString &from, const QString &to, const QString &subject, const QString &body) -{ - const Preferences* const pref = Preferences::instance(); - QTextCodec* latin1 = QTextCodec::codecForName("latin1"); - m_message = "Date: " + getCurrentDateTime().toLatin1() + "\r\n" - + encodeMimeHeader("From", from, latin1) - + encodeMimeHeader("Subject", subject, latin1) - + encodeMimeHeader("To", to, latin1) - + "MIME-Version: 1.0\r\n" - + "Content-Type: text/plain; charset=UTF-8\r\n" - + "Content-Transfer-Encoding: base64\r\n" - + "\r\n"; - // Encode the body in base64 - QString crlf_body = body; - QByteArray b = crlf_body.replace("\n", "\r\n").toUtf8().toBase64(); - int ct = b.length(); - for (int i = 0; i < ct; i += 78) - m_message += b.mid(i, 78); - m_from = from; - m_rcpt = to; - // Authentication - if (pref->getMailNotificationSMTPAuth()) { - m_username = pref->getMailNotificationSMTPUsername(); - m_password = pref->getMailNotificationSMTPPassword(); - } - - // Connect to SMTP server -#ifndef QT_NO_OPENSSL - if (pref->getMailNotificationSMTPSSL()) { - m_socket->connectToHostEncrypted(pref->getMailNotificationSMTP(), DEFAULT_PORT_SSL); - m_useSsl = true; - } - else { -#endif - m_socket->connectToHost(pref->getMailNotificationSMTP(), DEFAULT_PORT); - m_useSsl = false; -#ifndef QT_NO_OPENSSL -} -#endif -} - -void Smtp::readyRead() -{ - qDebug() << Q_FUNC_INFO; - // SMTP is line-oriented - m_buffer += m_socket->readAll(); - while (true) { - int pos = m_buffer.indexOf("\r\n"); - if (pos < 0) return; // Loop exit condition - QByteArray line = m_buffer.left(pos); - m_buffer = m_buffer.mid(pos + 2); - qDebug() << "Response line:" << line; - // Extract response code - QByteArray code = line.left(3); - - switch (m_state) { - case Init: { - if (code[0] == '2') { - // The server may send a multiline greeting/INIT/220 response. - // We wait until it finishes. - if (line[3] != ' ') - break; - // Connection was successful - ehlo(); - } - else { - logError("Connection failed, unrecognized reply: " + line); - m_state = Close; - } - break; - } - case EhloSent: - case HeloSent: - case EhloGreetReceived: - parseEhloResponse(code, line[3] != ' ', line.mid(4)); - break; -#ifndef QT_NO_OPENSSL - case StartTLSSent: - if (code == "220") { - m_socket->startClientEncryption(); - ehlo(); - } - else { - authenticate(); - } - break; -#endif - case AuthRequestSent: - case AuthUsernameSent: - if (m_authType == AuthPlain) authPlain(); - else if (m_authType == AuthLogin) authLogin(); - else authCramMD5(line.mid(4)); - break; - case AuthSent: - case Authenticated: - if (code[0] == '2') { - qDebug() << "Sending ..."; - m_socket->write("mail from:<" + m_from.toLatin1() + ">\r\n"); - m_socket->flush(); - m_state = Rcpt; - } - else { - // Authentication failed! - logError("Authentication failed, msg: " + line); - m_state = Close; - } - break; - case Rcpt: - if (code[0] == '2') { - m_socket->write("rcpt to:<" + m_rcpt.toLatin1() + ">\r\n"); - m_socket->flush(); - m_state = Data; - } - else { - logError(" was rejected by server, msg: " + line); - m_state = Close; - } - break; - case Data: - if (code[0] == '2') { - m_socket->write("data\r\n"); - m_socket->flush(); - m_state = Body; - } - else { - logError(" was rejected by server, msg: " + line); - m_state = Close; - } - break; - case Body: - if (code[0] == '3') { - m_socket->write(m_message + "\r\n.\r\n"); - m_socket->flush(); - m_state = Quit; - } - else { - logError(" was rejected by server, msg: " + line); - m_state = Close; - } - break; - case Quit: - if (code[0] == '2') { - m_socket->write("QUIT\r\n"); - m_socket->flush(); - // here, we just close. - m_state = Close; - } - else { - logError("Message was rejected by the server, error: " + line); - m_state = Close; - } - break; - default: - qDebug() << "Disconnecting from host"; - m_socket->disconnectFromHost(); - return; - } - } -} - -QByteArray Smtp::encodeMimeHeader(const QString &key, const QString &value, QTextCodec *latin1, const QByteArray &prefix) -{ - QByteArray rv = ""; - QByteArray line = key.toLatin1() + ": "; - if (!prefix.isEmpty()) line += prefix; - if (!value.contains("=?") && latin1->canEncode(value)) { - bool firstWord = true; - foreach (const QByteArray& word, value.toLatin1().split(' ')) { - if (line.size() > 78) { - rv = rv + line + "\r\n"; - line.clear(); - } - if (firstWord) - line += word; - else - line += " " + word; - firstWord = false; - } - } - else { - // The text cannot be losslessly encoded as Latin-1. Therefore, we - // must use base64 encoding. - QByteArray utf8 = value.toUtf8(); - // Use base64 encoding - QByteArray base64 = utf8.toBase64(); - int ct = base64.length(); - line += "=?utf-8?b?"; - for (int i = 0; i < ct; i += 4) { - /*if (line.length() > 72) { - rv += line + "?\n\r"; - line = " =?utf-8?b?"; - }*/ - line = line + base64.mid(i, 4); - } - line += "?="; // end encoded-word atom - } - return rv + line + "\r\n"; -} - -void Smtp::ehlo() -{ - QByteArray address = determineFQDN(); - m_socket->write("ehlo " + address + "\r\n"); - m_socket->flush(); - m_state = EhloSent; -} - -void Smtp::helo() -{ - QByteArray address = determineFQDN(); - m_socket->write("helo " + address + "\r\n"); - m_socket->flush(); - m_state = HeloSent; -} - -void Smtp::parseEhloResponse(const QByteArray &code, bool continued, const QString &line) -{ - if (code != "250") { - // Error - if (m_state == EhloSent) { - // try to send HELO instead of EHLO - qDebug() << "EHLO failed, trying HELO instead..."; - helo(); - } - else { - // Both EHLO and HELO failed, chances are this is NOT - // a SMTP server - logError("Both EHLO and HELO failed, msg: " + line); - m_state = Close; - } - return; - } - - if (m_state != EhloGreetReceived) { - if (!continued) { - // greeting only, no extensions - qDebug() << "No extension"; - m_state = EhloDone; - } - else { - // greeting followed by extensions - m_state = EhloGreetReceived; - qDebug() << "EHLO greet received"; - return; - } - } - else { - qDebug() << Q_FUNC_INFO << "Supported extension: " << line.section(' ', 0, 0).toUpper() - << line.section(' ', 1); - m_extensions[line.section(' ', 0, 0).toUpper()] = line.section(' ', 1); - if (!continued) - m_state = EhloDone; - } - - if (m_state != EhloDone) return; - - if (m_extensions.contains("STARTTLS") && m_useSsl) { - qDebug() << "STARTTLS"; - startTLS(); - } - else { - authenticate(); - } -} - -void Smtp::authenticate() -{ - qDebug() << Q_FUNC_INFO; - if (!m_extensions.contains("AUTH") || - m_username.isEmpty() || m_password.isEmpty()) { - // Skip authentication - qDebug() << "Skipping authentication..."; - m_state = Authenticated; - // At this point the server will not send any response - // So fill the buffer with a fake one to pass the tests - // in readyRead() - m_buffer.push_front("250 QBT FAKE RESPONSE\r\n"); - return; - } - // AUTH extension is supported, check which - // authentication modes are supported by - // the server - QStringList auth = m_extensions["AUTH"].toUpper().split(' ', QString::SkipEmptyParts); - if (auth.contains("CRAM-MD5")) { - qDebug() << "Using CRAM-MD5 authentication..."; - authCramMD5(); - } - else if (auth.contains("PLAIN")) { - qDebug() << "Using PLAIN authentication..."; - authPlain(); - } - else if (auth.contains("LOGIN")) { - qDebug() << "Using LOGIN authentication..."; - authLogin(); - } - else { - // Skip authentication - logError("The SMTP server does not seem to support any of the authentications modes " - "we support [CRAM-MD5|PLAIN|LOGIN], skipping authentication, " - "knowing it is likely to fail... Server Auth Modes: " + auth.join("|")); - m_state = Authenticated; - // At this point the server will not send any response - // So fill the buffer with a fake one to pass the tests - // in readyRead() - m_buffer.push_front("250 QBT FAKE RESPONSE\r\n"); - } -} - -void Smtp::startTLS() -{ - qDebug() << Q_FUNC_INFO; -#ifndef QT_NO_OPENSSL - m_socket->write("starttls\r\n"); - m_socket->flush(); - m_state = StartTLSSent; -#else - authenticate(); -#endif -} - -void Smtp::authCramMD5(const QByteArray& challenge) -{ - if (m_state != AuthRequestSent) { - m_socket->write("auth cram-md5\r\n"); - m_socket->flush(); - m_authType = AuthCramMD5; - m_state = AuthRequestSent; - } - else { - QByteArray response = m_username.toLatin1() + ' ' - + hmacMD5(m_password.toLatin1(), QByteArray::fromBase64(challenge)).toHex(); - m_socket->write(response.toBase64() + "\r\n"); - m_socket->flush(); - m_state = AuthSent; - } -} - -void Smtp::authPlain() -{ - if (m_state != AuthRequestSent) { - m_authType = AuthPlain; - // Prepare Auth string - QByteArray auth; - auth += '\0'; - auth += m_username.toLatin1(); - qDebug() << "username: " << m_username.toLatin1(); - auth += '\0'; - auth += m_password.toLatin1(); - qDebug() << "password: " << m_password.toLatin1(); - // Send it - m_socket->write("auth plain " + auth.toBase64() + "\r\n"); - m_socket->flush(); - m_state = AuthSent; - } -} - -void Smtp::authLogin() -{ - if ((m_state != AuthRequestSent) && (m_state != AuthUsernameSent)) { - m_socket->write("auth login\r\n"); - m_socket->flush(); - m_authType = AuthLogin; - m_state = AuthRequestSent; - } - else if (m_state == AuthRequestSent) { - m_socket->write(m_username.toLatin1().toBase64() + "\r\n"); - m_socket->flush(); - m_state = AuthUsernameSent; - } - else { - m_socket->write(m_password.toLatin1().toBase64() + "\r\n"); - m_socket->flush(); - m_state = AuthSent; - } -} - -void Smtp::logError(const QString &msg) -{ - qDebug() << "Email Notification Error:" << msg; - Logger::instance()->addMessage(tr("Email Notification Error:") + " " + msg, Log::CRITICAL); -} - -QString Smtp::getCurrentDateTime() const -{ - // return date & time in the format specified in RFC 2822, section 3.3 - const QDateTime nowDateTime = QDateTime::currentDateTime(); - const QDate nowDate = nowDateTime.date(); - const QLocale eng(QLocale::English); - - QString timeStr = nowDateTime.time().toString("HH:mm:ss"); - QString weekDayStr = eng.dayName(nowDate.dayOfWeek(), QLocale::ShortFormat); - QString dayStr = QString::number(nowDate.day()); - QString monthStr = eng.monthName(nowDate.month(), QLocale::ShortFormat); - QString yearStr = QString::number(nowDate.year()); - - QDateTime tmp = nowDateTime; - tmp.setTimeSpec(Qt::UTC); - int timeOffsetHour = nowDateTime.secsTo(tmp) / 3600; - int timeOffsetMin = nowDateTime.secsTo(tmp) / 60 - (60 * timeOffsetHour); - int timeOffset = timeOffsetHour * 100 + timeOffsetMin; - // buf size = 11 to avoid format truncation warnings from snprintf - char buf[11] = {0}; - std::snprintf(buf, sizeof(buf), "%+05d", timeOffset); - QString timeOffsetStr = buf; - - QString ret = weekDayStr + ", " + dayStr + " " + monthStr + " " + yearStr + " " + timeStr + " " + timeOffsetStr; - return ret; -} - -void Smtp::error(QAbstractSocket::SocketError socketError) -{ - // Getting a remote host closed error is apparently normal, even when successfully sending - // an email - if (socketError != QAbstractSocket::RemoteHostClosedError) - logError(m_socket->errorString()); -} diff --git a/src/base/net/smtp.h b/src/base/net/smtp.h deleted file mode 100644 index 6c1b9b9ee..000000000 --- a/src/base/net/smtp.h +++ /dev/null @@ -1,129 +0,0 @@ -/* - * Bittorrent Client using Qt 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 - */ - -/* - * This code is based on QxtSmtp from libqxt (http://libqxt.org) - */ - -#ifndef SMTP_H -#define SMTP_H - -#include -#include -#include -#include -#include -#include - -QT_BEGIN_NAMESPACE -class QTextStream; -#ifndef QT_NO_OPENSSL -class QSslSocket; -#else -class QTcpSocket; -#endif -class QTextCodec; -QT_END_NAMESPACE - -namespace Net -{ - class Smtp : public QObject - { - Q_OBJECT - - public: - Smtp(QObject *parent = 0); - ~Smtp(); - - void sendMail(const QString &from, const QString &to, const QString &subject, const QString &body); - - private slots: - void readyRead(); - void error(QAbstractSocket::SocketError socketError); - - private: - enum States - { - Rcpt, - EhloSent, - HeloSent, - EhloDone, - EhloGreetReceived, - AuthRequestSent, - AuthSent, - AuthUsernameSent, - Authenticated, - StartTLSSent, - Data, - Init, - Body, - Quit, - Close - }; - - enum AuthType - { - AuthPlain, - AuthLogin, - AuthCramMD5 - }; - - QByteArray encodeMimeHeader(const QString &key, const QString &value, QTextCodec *latin1, const QByteArray &prefix = QByteArray()); - void ehlo(); - void helo(); - void parseEhloResponse(const QByteArray &code, bool continued, const QString &line); - void authenticate(); - void startTLS(); - void authCramMD5(const QByteArray &challenge = QByteArray()); - void authPlain(); - void authLogin(); - void logError(const QString &msg); - QString getCurrentDateTime() const; - - QByteArray m_message; -#ifndef QT_NO_OPENSSL - QSslSocket *m_socket; -#else - QTcpSocket *m_socket; -#endif - QString m_from; - QString m_rcpt; - QString m_response; - int m_state; - QHash m_extensions; - QByteArray m_buffer; - bool m_useSsl; - AuthType m_authType; - QString m_username; - QString m_password; - }; -} - -#endif diff --git a/src/base/preferences.cpp b/src/base/preferences.cpp deleted file mode 100644 index 6de309161..000000000 --- a/src/base/preferences.cpp +++ /dev/null @@ -1,1477 +0,0 @@ -/* - * Bittorrent Client using Qt4 and libtorrent. - * Copyright (C) 2006 Christophe Dumez - * Copyright (C) 2014 sledgehammer999 - * - * 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 - * Contact : hammered999@gmail.com - */ - -#include -#include -#include -#include -#include - -#ifndef DISABLE_GUI -#include -#else -#include -#endif - -#ifdef Q_OS_WIN -#include -#include -#endif - -#ifdef Q_OS_MAC -#include -#endif - -#include "utils/fs.h" -#include "utils/misc.h" -#include "settingsstorage.h" -#include "logger.h" -#include "preferences.h" - -Preferences* Preferences::m_instance = 0; - -Preferences::Preferences() {} - -Preferences *Preferences::instance() -{ - return m_instance; -} - -void Preferences::initInstance() -{ - if (!m_instance) - m_instance = new Preferences; -} - -void Preferences::freeInstance() -{ - if (m_instance) { - delete m_instance; - m_instance = 0; - } -} - -const QVariant Preferences::value(const QString &key, const QVariant &defaultValue) const -{ - return SettingsStorage::instance()->loadValue(key, defaultValue); -} - -void Preferences::setValue(const QString &key, const QVariant &value) -{ - SettingsStorage::instance()->storeValue(key, value); -} - -// General options -QString Preferences::getLocale() const -{ - return value("Preferences/General/Locale", QLocale::system().name()).toString(); -} - -void Preferences::setLocale(const QString &locale) -{ - setValue("Preferences/General/Locale", locale); -} - -bool Preferences::deleteTorrentFilesAsDefault() const -{ - return value("Preferences/General/DeleteTorrentsFilesAsDefault", false).toBool(); -} - -void Preferences::setDeleteTorrentFilesAsDefault(bool del) -{ - setValue("Preferences/General/DeleteTorrentsFilesAsDefault", del); -} - -bool Preferences::confirmOnExit() const -{ - return value("Preferences/General/ExitConfirm", true).toBool(); -} - -void Preferences::setConfirmOnExit(bool confirm) -{ - setValue("Preferences/General/ExitConfirm", confirm); -} - -bool Preferences::speedInTitleBar() const -{ - return value("Preferences/General/SpeedInTitleBar", false).toBool(); -} - -void Preferences::showSpeedInTitleBar(bool show) -{ - setValue("Preferences/General/SpeedInTitleBar", show); -} - -bool Preferences::useAlternatingRowColors() const -{ - return value("Preferences/General/AlternatingRowColors", true).toBool(); -} - -void Preferences::setAlternatingRowColors(bool b) -{ - setValue("Preferences/General/AlternatingRowColors", b); -} - -bool Preferences::getHideZeroValues() const -{ - return value("Preferences/General/HideZeroValues", false).toBool(); -} - -void Preferences::setHideZeroValues(bool b) -{ - setValue("Preferences/General/HideZeroValues", b); -} - -int Preferences::getHideZeroComboValues() const -{ - return value("Preferences/General/HideZeroComboValues", 0).toInt(); -} - -void Preferences::setHideZeroComboValues(int n) -{ - setValue("Preferences/General/HideZeroComboValues", n); -} - -// In Mac OS X the dock is sufficient for our needs so we disable the sys tray functionality. -// See extensive discussion in https://github.com/qbittorrent/qBittorrent/pull/3018 -#ifndef Q_OS_MAC -bool Preferences::systrayIntegration() const -{ - return value("Preferences/General/SystrayEnabled", true).toBool(); -} - -void Preferences::setSystrayIntegration(bool enabled) -{ - setValue("Preferences/General/SystrayEnabled", enabled); -} - -bool Preferences::minimizeToTray() const -{ - return value("Preferences/General/MinimizeToTray", false).toBool(); -} - -void Preferences::setMinimizeToTray(bool b) -{ - setValue("Preferences/General/MinimizeToTray", b); -} - -bool Preferences::closeToTray() const -{ - return value("Preferences/General/CloseToTray", true).toBool(); -} - -void Preferences::setCloseToTray(bool b) -{ - setValue("Preferences/General/CloseToTray", b); -} -#endif - -bool Preferences::isToolbarDisplayed() const -{ - return value("Preferences/General/ToolbarDisplayed", true).toBool(); -} - -void Preferences::setToolbarDisplayed(bool displayed) -{ - setValue("Preferences/General/ToolbarDisplayed", displayed); -} - -bool Preferences::isStatusbarDisplayed() const -{ - return value("Preferences/General/StatusbarDisplayed", true).toBool(); -} - -void Preferences::setStatusbarDisplayed(bool displayed) -{ - setValue("Preferences/General/StatusbarDisplayed", displayed); -} - -bool Preferences::startMinimized() const -{ - return value("Preferences/General/StartMinimized", false).toBool(); -} - -void Preferences::setStartMinimized(bool b) -{ - setValue("Preferences/General/StartMinimized", b); -} - -bool Preferences::isSplashScreenDisabled() const -{ - return value("Preferences/General/NoSplashScreen", true).toBool(); -} - -void Preferences::setSplashScreenDisabled(bool b) -{ - setValue("Preferences/General/NoSplashScreen", b); -} - -// Preventing from system suspend while active torrents are presented. -bool Preferences::preventFromSuspend() const -{ - return value("Preferences/General/PreventFromSuspend", false).toBool(); -} - -void Preferences::setPreventFromSuspend(bool b) -{ - setValue("Preferences/General/PreventFromSuspend", b); -} - -#ifdef Q_OS_WIN -bool Preferences::WinStartup() const -{ - QSettings settings("HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Run", QSettings::NativeFormat); - return settings.contains("qBittorrent"); -} - -void Preferences::setWinStartup(bool b) -{ - QSettings settings("HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Run", QSettings::NativeFormat); - if (b) { - const QString bin_path = "\"" + Utils::Fs::toNativePath(qApp->applicationFilePath()) + "\""; - settings.setValue("qBittorrent", bin_path); - } - else { - settings.remove("qBittorrent"); - } -} -#endif - -// Downloads -QString Preferences::lastLocationPath() const -{ - return Utils::Fs::fromNativePath(value("Preferences/Downloads/LastLocationPath").toString()); -} - -void Preferences::setLastLocationPath(const QString &path) -{ - setValue("Preferences/Downloads/LastLocationPath", Utils::Fs::fromNativePath(path)); -} - -QVariantHash Preferences::getScanDirs() const -{ - return value("Preferences/Downloads/ScanDirsV2").toHash(); -} - -// This must be called somewhere with data from the model -void Preferences::setScanDirs(const QVariantHash &dirs) -{ - setValue("Preferences/Downloads/ScanDirsV2", dirs); -} - -QString Preferences::getScanDirsLastPath() const -{ - return Utils::Fs::fromNativePath(value("Preferences/Downloads/ScanDirsLastPath").toString()); -} - -void Preferences::setScanDirsLastPath(const QString &path) -{ - setValue("Preferences/Downloads/ScanDirsLastPath", Utils::Fs::fromNativePath(path)); -} - -bool Preferences::isMailNotificationEnabled() const -{ - return value("Preferences/MailNotification/enabled", false).toBool(); -} - -void Preferences::setMailNotificationEnabled(bool enabled) -{ - setValue("Preferences/MailNotification/enabled", enabled); -} - -QString Preferences::getMailNotificationEmail() const -{ - return value("Preferences/MailNotification/email").toString(); -} - -void Preferences::setMailNotificationEmail(const QString &mail) -{ - setValue("Preferences/MailNotification/email", mail); -} - -QString Preferences::getMailNotificationSMTP() const -{ - return value("Preferences/MailNotification/smtp_server", "smtp.changeme.com").toString(); -} - -void Preferences::setMailNotificationSMTP(const QString &smtp_server) -{ - setValue("Preferences/MailNotification/smtp_server", smtp_server); -} - -bool Preferences::getMailNotificationSMTPSSL() const -{ - return value("Preferences/MailNotification/req_ssl", false).toBool(); -} - -void Preferences::setMailNotificationSMTPSSL(bool use) -{ - setValue("Preferences/MailNotification/req_ssl", use); -} - -bool Preferences::getMailNotificationSMTPAuth() const -{ - return value("Preferences/MailNotification/req_auth", false).toBool(); -} - -void Preferences::setMailNotificationSMTPAuth(bool use) -{ - setValue("Preferences/MailNotification/req_auth", use); -} - -QString Preferences::getMailNotificationSMTPUsername() const -{ - return value("Preferences/MailNotification/username").toString(); -} - -void Preferences::setMailNotificationSMTPUsername(const QString &username) -{ - setValue("Preferences/MailNotification/username", username); -} - -QString Preferences::getMailNotificationSMTPPassword() const -{ - return value("Preferences/MailNotification/password").toString(); -} - -void Preferences::setMailNotificationSMTPPassword(const QString &password) -{ - setValue("Preferences/MailNotification/password", password); -} - -int Preferences::getActionOnDblClOnTorrentDl() const -{ - return value("Preferences/Downloads/DblClOnTorDl", 0).toInt(); -} - -void Preferences::setActionOnDblClOnTorrentDl(int act) -{ - setValue("Preferences/Downloads/DblClOnTorDl", act); -} - -int Preferences::getActionOnDblClOnTorrentFn() const -{ - return value("Preferences/Downloads/DblClOnTorFn", 1).toInt(); -} - -void Preferences::setActionOnDblClOnTorrentFn(int act) -{ - setValue("Preferences/Downloads/DblClOnTorFn", act); -} - -QTime Preferences::getSchedulerStartTime() const -{ - return value("Preferences/Scheduler/start_time", QTime(8,0)).toTime(); -} - -void Preferences::setSchedulerStartTime(const QTime &time) -{ - setValue("Preferences/Scheduler/start_time", time); -} - -QTime Preferences::getSchedulerEndTime() const -{ - return value("Preferences/Scheduler/end_time", QTime(20,0)).toTime(); -} - -void Preferences::setSchedulerEndTime(const QTime &time) -{ - setValue("Preferences/Scheduler/end_time", time); -} - -scheduler_days Preferences::getSchedulerDays() const -{ - return static_cast(value("Preferences/Scheduler/days", EVERY_DAY).toInt()); -} - -void Preferences::setSchedulerDays(scheduler_days days) -{ - setValue("Preferences/Scheduler/days", static_cast(days)); -} - -// Search -bool Preferences::isSearchEnabled() const -{ - return value("Preferences/Search/SearchEnabled", false).toBool(); -} - -void Preferences::setSearchEnabled(bool enabled) -{ - setValue("Preferences/Search/SearchEnabled", enabled); -} - -bool Preferences::isWebUiEnabled() const -{ -#ifdef DISABLE_GUI - return true; -#else - return value("Preferences/WebUI/Enabled", false).toBool(); -#endif -} - -void Preferences::setWebUiEnabled(bool enabled) -{ - setValue("Preferences/WebUI/Enabled", enabled); -} - -bool Preferences::isWebUiLocalAuthEnabled() const -{ - return value("Preferences/WebUI/LocalHostAuth", true).toBool(); -} - -void Preferences::setWebUiLocalAuthEnabled(bool enabled) -{ - setValue("Preferences/WebUI/LocalHostAuth", enabled); -} - -QString Preferences::getServerDomains() const -{ - return value("Preferences/WebUI/ServerDomains", "*").toString(); -} - -void Preferences::setServerDomains(const QString &str) -{ - setValue("Preferences/WebUI/ServerDomains", str); -} - -quint16 Preferences::getWebUiPort() const -{ - return value("Preferences/WebUI/Port", 8080).toInt(); -} - -void Preferences::setWebUiPort(quint16 port) -{ - setValue("Preferences/WebUI/Port", port); -} - -bool Preferences::useUPnPForWebUIPort() const -{ -#ifdef DISABLE_GUI - return value("Preferences/WebUI/UseUPnP", true).toBool(); -#else - return value("Preferences/WebUI/UseUPnP", false).toBool(); -#endif -} - -void Preferences::setUPnPForWebUIPort(bool enabled) -{ - setValue("Preferences/WebUI/UseUPnP", enabled); -} - -QString Preferences::getWebUiUsername() const -{ - return value("Preferences/WebUI/Username", "admin").toString(); -} - -void Preferences::setWebUiUsername(const QString &username) -{ - setValue("Preferences/WebUI/Username", username); -} - -QString Preferences::getWebUiPassword() const -{ - QString pass_ha1 = value("Preferences/WebUI/Password_ha1").toString(); - if (pass_ha1.isEmpty()) { - QCryptographicHash md5(QCryptographicHash::Md5); - md5.addData("adminadmin"); - pass_ha1 = md5.result().toHex(); - } - return pass_ha1; -} - -void Preferences::setWebUiPassword(const QString &new_password) -{ - // Do not overwrite current password with its hash - if (new_password == getWebUiPassword()) - return; - - // Encode to md5 and save - QCryptographicHash md5(QCryptographicHash::Md5); - md5.addData(new_password.toLocal8Bit()); - - setValue("Preferences/WebUI/Password_ha1", md5.result().toHex()); -} - -bool Preferences::isWebUiHttpsEnabled() const -{ - return value("Preferences/WebUI/HTTPS/Enabled", false).toBool(); -} - -void Preferences::setWebUiHttpsEnabled(bool enabled) -{ - setValue("Preferences/WebUI/HTTPS/Enabled", enabled); -} - -QByteArray Preferences::getWebUiHttpsCertificate() const -{ - return value("Preferences/WebUI/HTTPS/Certificate").toByteArray(); -} - -void Preferences::setWebUiHttpsCertificate(const QByteArray &data) -{ - setValue("Preferences/WebUI/HTTPS/Certificate", data); -} - -QByteArray Preferences::getWebUiHttpsKey() const -{ - return value("Preferences/WebUI/HTTPS/Key").toByteArray(); -} - -void Preferences::setWebUiHttpsKey(const QByteArray &data) -{ - setValue("Preferences/WebUI/HTTPS/Key", data); -} - -bool Preferences::isDynDNSEnabled() const -{ - return value("Preferences/DynDNS/Enabled", false).toBool(); -} - -void Preferences::setDynDNSEnabled(bool enabled) -{ - setValue("Preferences/DynDNS/Enabled", enabled); -} - -DNS::Service Preferences::getDynDNSService() const -{ - return DNS::Service(value("Preferences/DynDNS/Service", DNS::DYNDNS).toInt()); -} - -void Preferences::setDynDNSService(int service) -{ - setValue("Preferences/DynDNS/Service", service); -} - -QString Preferences::getDynDomainName() const -{ - return value("Preferences/DynDNS/DomainName", "changeme.dyndns.org").toString(); -} - -void Preferences::setDynDomainName(const QString &name) -{ - setValue("Preferences/DynDNS/DomainName", name); -} - -QString Preferences::getDynDNSUsername() const -{ - return value("Preferences/DynDNS/Username").toString(); -} - -void Preferences::setDynDNSUsername(const QString &username) -{ - setValue("Preferences/DynDNS/Username", username); -} - -QString Preferences::getDynDNSPassword() const -{ - return value("Preferences/DynDNS/Password").toString(); -} - -void Preferences::setDynDNSPassword(const QString &password) -{ - setValue("Preferences/DynDNS/Password", password); -} - -// Advanced settings -void Preferences::clearUILockPassword() -{ - setValue("Locking/password", QString()); -} - -QString Preferences::getUILockPasswordMD5() const -{ - return value("Locking/password").toString(); -} - -void Preferences::setUILockPassword(const QString &clear_password) -{ - QCryptographicHash md5(QCryptographicHash::Md5); - md5.addData(clear_password.toLocal8Bit()); - QString md5_password = md5.result().toHex(); - setValue("Locking/password", md5_password); -} - -bool Preferences::isUILocked() const -{ - return value("Locking/locked", false).toBool(); -} - -void Preferences::setUILocked(bool locked) -{ - return setValue("Locking/locked", locked); -} - -bool Preferences::isAutoRunEnabled() const -{ - return value("AutoRun/enabled", false).toBool(); -} - -void Preferences::setAutoRunEnabled(bool enabled) -{ - return setValue("AutoRun/enabled", enabled); -} - -QString Preferences::getAutoRunProgram() const -{ - return value("AutoRun/program").toString(); -} - -void Preferences::setAutoRunProgram(const QString &program) -{ - setValue("AutoRun/program", program); -} - -bool Preferences::shutdownWhenDownloadsComplete() const -{ - return value("Preferences/Downloads/AutoShutDownOnCompletion", false).toBool(); -} - -void Preferences::setShutdownWhenDownloadsComplete(bool shutdown) -{ - setValue("Preferences/Downloads/AutoShutDownOnCompletion", shutdown); -} - -bool Preferences::suspendWhenDownloadsComplete() const -{ - return value("Preferences/Downloads/AutoSuspendOnCompletion", false).toBool(); -} - -void Preferences::setSuspendWhenDownloadsComplete(bool suspend) -{ - setValue("Preferences/Downloads/AutoSuspendOnCompletion", suspend); -} - -bool Preferences::hibernateWhenDownloadsComplete() const -{ - return value("Preferences/Downloads/AutoHibernateOnCompletion", false).toBool(); -} - -void Preferences::setHibernateWhenDownloadsComplete(bool hibernate) -{ - setValue("Preferences/Downloads/AutoHibernateOnCompletion", hibernate); -} - -bool Preferences::shutdownqBTWhenDownloadsComplete() const -{ - return value("Preferences/Downloads/AutoShutDownqBTOnCompletion", false).toBool(); -} - -void Preferences::setShutdownqBTWhenDownloadsComplete(bool shutdown) -{ - setValue("Preferences/Downloads/AutoShutDownqBTOnCompletion", shutdown); -} - -bool Preferences::dontConfirmAutoExit() const -{ - return value("ShutdownConfirmDlg/DontConfirmAutoExit", false).toBool(); -} - -void Preferences::setDontConfirmAutoExit(bool dontConfirmAutoExit) -{ - setValue("ShutdownConfirmDlg/DontConfirmAutoExit", dontConfirmAutoExit); -} - -bool Preferences::recheckTorrentsOnCompletion() const -{ - return value("Preferences/Advanced/RecheckOnCompletion", false).toBool(); -} - -void Preferences::recheckTorrentsOnCompletion(bool recheck) -{ - setValue("Preferences/Advanced/RecheckOnCompletion", recheck); -} - -bool Preferences::resolvePeerCountries() const -{ - return value("Preferences/Connection/ResolvePeerCountries", true).toBool(); -} - -void Preferences::resolvePeerCountries(bool resolve) -{ - setValue("Preferences/Connection/ResolvePeerCountries", resolve); -} - -bool Preferences::resolvePeerHostNames() const -{ - return value("Preferences/Connection/ResolvePeerHostNames", false).toBool(); -} - -void Preferences::resolvePeerHostNames(bool resolve) -{ - setValue("Preferences/Connection/ResolvePeerHostNames", resolve); -} - -#if (defined(Q_OS_UNIX) && !defined(Q_OS_MAC)) -bool Preferences::useSystemIconTheme() const -{ - return value("Preferences/Advanced/useSystemIconTheme", true).toBool(); -} - -void Preferences::useSystemIconTheme(bool enabled) -{ - setValue("Preferences/Advanced/useSystemIconTheme", enabled); -} -#endif - -bool Preferences::recursiveDownloadDisabled() const -{ - return value("Preferences/Advanced/DisableRecursiveDownload", false).toBool(); -} - -void Preferences::disableRecursiveDownload(bool disable) -{ - setValue("Preferences/Advanced/DisableRecursiveDownload", disable); -} - -#ifdef Q_OS_WIN -namespace { - enum REG_SEARCH_TYPE - { - USER, - SYSTEM_32BIT, - SYSTEM_64BIT - }; - - QStringList getRegSubkeys(HKEY handle) - { - QStringList keys; - - DWORD cSubKeys = 0; - DWORD cMaxSubKeyLen = 0; - LONG res = ::RegQueryInfoKeyW(handle, NULL, NULL, NULL, &cSubKeys, &cMaxSubKeyLen, NULL, NULL, NULL, NULL, NULL, NULL); - - if (res == ERROR_SUCCESS) { - cMaxSubKeyLen++; // For null character - LPWSTR lpName = new WCHAR[cMaxSubKeyLen]; - DWORD cName; - - for (DWORD i = 0; i < cSubKeys; ++i) { - cName = cMaxSubKeyLen; - res = ::RegEnumKeyExW(handle, i, lpName, &cName, NULL, NULL, NULL, NULL); - if (res == ERROR_SUCCESS) - keys.push_back(QString::fromWCharArray(lpName)); - } - - delete[] lpName; - } - - return keys; - } - - QString getRegValue(HKEY handle, const QString &name = QString()) - { - QString result; - - DWORD type = 0; - DWORD cbData = 0; - LPWSTR lpValueName = NULL; - if (!name.isEmpty()) { - lpValueName = new WCHAR[name.size() + 1]; - name.toWCharArray(lpValueName); - lpValueName[name.size()] = 0; - } - - // Discover the size of the value - ::RegQueryValueExW(handle, lpValueName, NULL, &type, NULL, &cbData); - DWORD cBuffer = (cbData / sizeof(WCHAR)) + 1; - LPWSTR lpData = new WCHAR[cBuffer]; - LONG res = ::RegQueryValueExW(handle, lpValueName, NULL, &type, (LPBYTE)lpData, &cbData); - if (lpValueName) - delete[] lpValueName; - - if (res == ERROR_SUCCESS) { - lpData[cBuffer - 1] = 0; - result = QString::fromWCharArray(lpData); - } - delete[] lpData; - - return result; - } - - QString pythonSearchReg(const REG_SEARCH_TYPE type) - { - HKEY hkRoot; - if (type == USER) - hkRoot = HKEY_CURRENT_USER; - else - hkRoot = HKEY_LOCAL_MACHINE; - - REGSAM samDesired = KEY_READ; - if (type == SYSTEM_32BIT) - samDesired |= KEY_WOW64_32KEY; - else if (type == SYSTEM_64BIT) - samDesired |= KEY_WOW64_64KEY; - - QString path; - LONG res = 0; - HKEY hkPythonCore; - res = ::RegOpenKeyExW(hkRoot, L"SOFTWARE\\Python\\PythonCore", 0, samDesired, &hkPythonCore); - - if (res == ERROR_SUCCESS) { - QStringList versions = getRegSubkeys(hkPythonCore); - qDebug("Python versions nb: %d", versions.size()); - versions.sort(); - - bool found = false; - while(!found && !versions.empty()) { - const QString version = versions.takeLast() + "\\InstallPath"; - LPWSTR lpSubkey = new WCHAR[version.size() + 1]; - version.toWCharArray(lpSubkey); - lpSubkey[version.size()] = 0; - - HKEY hkInstallPath; - res = ::RegOpenKeyExW(hkPythonCore, lpSubkey, 0, samDesired, &hkInstallPath); - delete[] lpSubkey; - - if (res == ERROR_SUCCESS) { - qDebug("Detected possible Python v%s location", qPrintable(version)); - path = getRegValue(hkInstallPath); - ::RegCloseKey(hkInstallPath); - - if (!path.isEmpty() && QDir(path).exists("python.exe")) { - qDebug("Found python.exe at %s", qPrintable(path)); - found = true; - } - } - } - - if (!found) - path = QString(); - - ::RegCloseKey(hkPythonCore); - } - - return path; - } - -} - -QString Preferences::getPythonPath() -{ - QString path = pythonSearchReg(USER); - if (!path.isEmpty()) - return path; - - path = pythonSearchReg(SYSTEM_32BIT); - if (!path.isEmpty()) - return path; - - path = pythonSearchReg(SYSTEM_64BIT); - if (!path.isEmpty()) - return path; - - // Fallback: Detect python from default locations - const QStringList dirs = QDir("C:/").entryList(QStringList("Python*"), QDir::Dirs, QDir::Name | QDir::Reversed); - foreach (const QString &dir, dirs) { - const QString path("C:/" + dir + "/"); - if (QFile::exists(path + "python.exe")) - return path; - } - - return QString(); -} - -bool Preferences::neverCheckFileAssoc() const -{ - return value("Preferences/Win32/NeverCheckFileAssocation", false).toBool(); -} - -void Preferences::setNeverCheckFileAssoc(bool check) -{ - setValue("Preferences/Win32/NeverCheckFileAssocation", check); -} - -bool Preferences::isTorrentFileAssocSet() -{ - QSettings settings("HKEY_CURRENT_USER\\Software\\Classes", QSettings::NativeFormat); - if (settings.value(".torrent/Default").toString() != "qBittorrent") { - qDebug(".torrent != qBittorrent"); - return false; - } - - return true; -} - -bool Preferences::isMagnetLinkAssocSet() -{ - QSettings settings("HKEY_CURRENT_USER\\Software\\Classes", QSettings::NativeFormat); - - // Check magnet link assoc - QRegExp exe_reg("\"([^\"]+)\".*"); - QString shell_command = Utils::Fs::toNativePath(settings.value("magnet/shell/open/command/Default", "").toString()); - if (exe_reg.indexIn(shell_command) < 0) - return false; - QString assoc_exe = exe_reg.cap(1); - qDebug("exe: %s", qPrintable(assoc_exe)); - if (assoc_exe.compare(Utils::Fs::toNativePath(qApp->applicationFilePath()), Qt::CaseInsensitive) != 0) - return false; - - return true; -} - -void Preferences::setTorrentFileAssoc(bool set) -{ - QSettings settings("HKEY_CURRENT_USER\\Software\\Classes", QSettings::NativeFormat); - - // .Torrent association - if (set) { - QString old_progid = settings.value(".torrent/Default").toString(); - if (!old_progid.isEmpty() && (old_progid != "qBittorrent")) - settings.setValue(".torrent/OpenWithProgids/" + old_progid, ""); - settings.setValue(".torrent/Default", "qBittorrent"); - } - else if (isTorrentFileAssocSet()) { - settings.setValue(".torrent/Default", ""); - } - - SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, 0, 0); -} - -void Preferences::setMagnetLinkAssoc(bool set) -{ - QSettings settings("HKEY_CURRENT_USER\\Software\\Classes", QSettings::NativeFormat); - - // Magnet association - if (set) { - const QString command_str = "\"" + qApp->applicationFilePath() + "\" \"%1\""; - const QString icon_str = "\"" + qApp->applicationFilePath() + "\",1"; - - settings.setValue("magnet/Default", "URL:Magnet link"); - settings.setValue("magnet/Content Type", "application/x-magnet"); - settings.setValue("magnet/URL Protocol", ""); - settings.setValue("magnet/DefaultIcon/Default", Utils::Fs::toNativePath(icon_str)); - settings.setValue("magnet/shell/Default", "open"); - settings.setValue("magnet/shell/open/command/Default", Utils::Fs::toNativePath(command_str)); - } - else if (isMagnetLinkAssocSet()) { - settings.remove("magnet"); - } - - SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, 0, 0); -} -#endif - -#ifdef Q_OS_MAC -namespace -{ - CFStringRef torrentExtension = CFSTR("torrent"); - CFStringRef magnetUrlScheme = CFSTR("magnet"); -} - -bool Preferences::isTorrentFileAssocSet() -{ - bool isSet = false; - CFStringRef torrentId = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, torrentExtension, NULL); - if (torrentId != NULL) { - CFStringRef defaultHandlerId = LSCopyDefaultRoleHandlerForContentType(torrentId, kLSRolesViewer); - if (defaultHandlerId != NULL) { - CFStringRef myBundleId = CFBundleGetIdentifier(CFBundleGetMainBundle()); - isSet = CFStringCompare(myBundleId, defaultHandlerId, 0) == kCFCompareEqualTo; - CFRelease(defaultHandlerId); - } - CFRelease(torrentId); - } - return isSet; -} - -bool Preferences::isMagnetLinkAssocSet() -{ - bool isSet = false; - CFStringRef defaultHandlerId = LSCopyDefaultHandlerForURLScheme(magnetUrlScheme); - if (defaultHandlerId != NULL) { - CFStringRef myBundleId = CFBundleGetIdentifier(CFBundleGetMainBundle()); - isSet = CFStringCompare(myBundleId, defaultHandlerId, 0) == kCFCompareEqualTo; - CFRelease(defaultHandlerId); - } - return isSet; -} - -void Preferences::setTorrentFileAssoc() -{ - if (isTorrentFileAssocSet()) - return; - CFStringRef torrentId = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, torrentExtension, NULL); - if (torrentId != NULL) { - CFStringRef myBundleId = CFBundleGetIdentifier(CFBundleGetMainBundle()); - LSSetDefaultRoleHandlerForContentType(torrentId, kLSRolesViewer, myBundleId); - CFRelease(torrentId); - } -} - -void Preferences::setMagnetLinkAssoc() -{ - if (isMagnetLinkAssocSet()) - return; - CFStringRef myBundleId = CFBundleGetIdentifier(CFBundleGetMainBundle()); - LSSetDefaultHandlerForURLScheme(magnetUrlScheme, myBundleId); -} -#endif - -int Preferences::getTrackerPort() const -{ - return value("Preferences/Advanced/trackerPort", 9000).toInt(); -} - -void Preferences::setTrackerPort(int port) -{ - setValue("Preferences/Advanced/trackerPort", port); -} - -#if defined(Q_OS_WIN) || defined(Q_OS_MAC) -bool Preferences::isUpdateCheckEnabled() const -{ - return value("Preferences/Advanced/updateCheck", true).toBool(); -} - -void Preferences::setUpdateCheckEnabled(bool enabled) -{ - setValue("Preferences/Advanced/updateCheck", enabled); -} -#endif - -bool Preferences::confirmTorrentDeletion() const -{ - return value("Preferences/Advanced/confirmTorrentDeletion", true).toBool(); -} - -void Preferences::setConfirmTorrentDeletion(bool enabled) -{ - setValue("Preferences/Advanced/confirmTorrentDeletion", enabled); -} - -bool Preferences::confirmTorrentRecheck() const -{ - return value("Preferences/Advanced/confirmTorrentRecheck", true).toBool(); -} - -void Preferences::setConfirmTorrentRecheck(bool enabled) -{ - setValue("Preferences/Advanced/confirmTorrentRecheck", enabled); -} - -bool Preferences::confirmRemoveAllTags() const -{ - return value("Preferences/Advanced/confirmRemoveAllTags", true).toBool(); -} - -void Preferences::setConfirmRemoveAllTags(bool enabled) -{ - setValue("Preferences/Advanced/confirmRemoveAllTags", enabled); -} - -#ifndef Q_OS_MAC -TrayIcon::Style Preferences::trayIconStyle() const -{ - return TrayIcon::Style(value("Preferences/Advanced/TrayIconStyle", TrayIcon::NORMAL).toInt()); -} - -void Preferences::setTrayIconStyle(TrayIcon::Style style) -{ - setValue("Preferences/Advanced/TrayIconStyle", style); -} -#endif - -// Stuff that don't appear in the Options GUI but are saved -// in the same file. - -QDateTime Preferences::getDNSLastUpd() const -{ - return value("DNSUpdater/lastUpdateTime").toDateTime(); -} - -void Preferences::setDNSLastUpd(const QDateTime &date) -{ - setValue("DNSUpdater/lastUpdateTime", date); -} - -QString Preferences::getDNSLastIP() const -{ - return value("DNSUpdater/lastIP").toString(); -} - -void Preferences::setDNSLastIP(const QString &ip) -{ - setValue("DNSUpdater/lastIP", ip); -} - -bool Preferences::getAcceptedLegal() const -{ - return value("LegalNotice/Accepted", false).toBool(); -} - -void Preferences::setAcceptedLegal(const bool accepted) -{ - setValue("LegalNotice/Accepted", accepted); -} - -QByteArray Preferences::getMainGeometry() const -{ - return value("MainWindow/geometry").toByteArray(); -} - -void Preferences::setMainGeometry(const QByteArray &geometry) -{ - setValue("MainWindow/geometry", geometry); -} - -QByteArray Preferences::getMainVSplitterState() const -{ - return value("MainWindow/qt5/vsplitterState").toByteArray(); -} - -void Preferences::setMainVSplitterState(const QByteArray &state) -{ - setValue("MainWindow/qt5/vsplitterState", state); -} - -QString Preferences::getMainLastDir() const -{ - return value("MainWindowLastDir", QDir::homePath()).toString(); -} - -void Preferences::setMainLastDir(const QString &path) -{ - setValue("MainWindowLastDir", path); -} - -QSize Preferences::getPrefSize(const QSize& defaultSize) const -{ - return value("Preferences/State/size", defaultSize).toSize(); -} - -void Preferences::setPrefSize(const QSize &size) -{ - setValue("Preferences/State/size", size); -} - -QStringList Preferences::getPrefHSplitterSizes() const -{ - return value("Preferences/State/hSplitterSizes").toStringList(); -} - -void Preferences::setPrefHSplitterSizes(const QStringList &sizes) -{ - setValue("Preferences/State/hSplitterSizes", sizes); -} - -QByteArray Preferences::getPeerListState() const -{ - return value("TorrentProperties/Peers/qt5/PeerListState").toByteArray(); -} - -void Preferences::setPeerListState(const QByteArray &state) -{ - setValue("TorrentProperties/Peers/qt5/PeerListState", state); -} - -QString Preferences::getPropSplitterSizes() const -{ - return value("TorrentProperties/SplitterSizes").toString(); -} - -void Preferences::setPropSplitterSizes(const QString &sizes) -{ - setValue("TorrentProperties/SplitterSizes", sizes); -} - -QByteArray Preferences::getPropFileListState() const -{ - return value("TorrentProperties/qt5/FilesListState").toByteArray(); -} - -void Preferences::setPropFileListState(const QByteArray &state) -{ - setValue("TorrentProperties/qt5/FilesListState", state); -} - -int Preferences::getPropCurTab() const -{ - return value("TorrentProperties/CurrentTab", -1).toInt(); -} - -void Preferences::setPropCurTab(const int &tab) -{ - setValue("TorrentProperties/CurrentTab", tab); -} - -bool Preferences::getPropVisible() const -{ - return value("TorrentProperties/Visible", false).toBool(); -} - -void Preferences::setPropVisible(const bool visible) -{ - setValue("TorrentProperties/Visible", visible); -} - -QByteArray Preferences::getPropTrackerListState() const -{ - return value("TorrentProperties/Trackers/qt5/TrackerListState").toByteArray(); -} - -void Preferences::setPropTrackerListState(const QByteArray &state) -{ - setValue("TorrentProperties/Trackers/qt5/TrackerListState", state); -} - -QSize Preferences::getRssGeometrySize(const QSize &defaultSize) const -{ - return value("RssFeedDownloader/geometrySize", defaultSize).toSize(); -} - -void Preferences::setRssGeometrySize(const QSize &geometry) -{ - setValue("RssFeedDownloader/geometrySize", geometry); -} - -QByteArray Preferences::getRssHSplitterSizes() const -{ - return value("RssFeedDownloader/qt5/hsplitterSizes").toByteArray(); -} - -void Preferences::setRssHSplitterSizes(const QByteArray &sizes) -{ - setValue("RssFeedDownloader/qt5/hsplitterSizes", sizes); -} - -QStringList Preferences::getRssOpenFolders() const -{ - return value("GUI/RSSWidget/OpenedFolders").toStringList(); -} - -void Preferences::setRssOpenFolders(const QStringList &folders) -{ - setValue("GUI/RSSWidget/OpenedFolders", folders); -} - -QByteArray Preferences::getRssSideSplitterState() const -{ - return value("GUI/RSSWidget/qt5/splitter_h").toByteArray(); -} - -void Preferences::setRssSideSplitterState(const QByteArray &state) -{ - setValue("GUI/RSSWidget/qt5/splitter_h", state); -} - -QByteArray Preferences::getRssMainSplitterState() const -{ - return value("GUI/RSSWidget/qt5/splitterMain").toByteArray(); -} - -void Preferences::setRssMainSplitterState(const QByteArray &state) -{ - setValue("GUI/RSSWidget/qt5/splitterMain", state); -} - -QByteArray Preferences::getSearchTabHeaderState() const -{ - return value("SearchTab/qt5/HeaderState").toByteArray(); -} - -void Preferences::setSearchTabHeaderState(const QByteArray &state) -{ - setValue("SearchTab/qt5/HeaderState", state); -} - -QStringList Preferences::getSearchEngDisabled() const -{ - return value("SearchEngines/disabledEngines").toStringList(); -} - -void Preferences::setSearchEngDisabled(const QStringList &engines) -{ - setValue("SearchEngines/disabledEngines", engines); -} - -QString Preferences::getTorImportLastContentDir() const -{ - return value("TorrentImport/LastContentDir", QDir::homePath()).toString(); -} - -void Preferences::setTorImportLastContentDir(const QString &path) -{ - setValue("TorrentImport/LastContentDir", path); -} - -QByteArray Preferences::getTorImportGeometry() const -{ - return value("TorrentImportDlg/dimensions").toByteArray(); -} - -void Preferences::setTorImportGeometry(const QByteArray &geometry) -{ - setValue("TorrentImportDlg/dimensions", geometry); -} - -bool Preferences::getStatusFilterState() const -{ - return value("TransferListFilters/statusFilterState", true).toBool(); -} - -void Preferences::setStatusFilterState(const bool checked) -{ - setValue("TransferListFilters/statusFilterState", checked); -} - -bool Preferences::getCategoryFilterState() const -{ - return value("TransferListFilters/CategoryFilterState", true).toBool(); -} - -void Preferences::setCategoryFilterState(const bool checked) -{ - setValue("TransferListFilters/CategoryFilterState", checked); -} - -bool Preferences::getTagFilterState() const -{ - return value("TransferListFilters/TagFilterState", true).toBool(); -} - -void Preferences::setTagFilterState(const bool checked) -{ - setValue("TransferListFilters/TagFilterState", checked); -} - -bool Preferences::getTrackerFilterState() const -{ - return value("TransferListFilters/trackerFilterState", true).toBool(); -} - -void Preferences::setTrackerFilterState(const bool checked) -{ - setValue("TransferListFilters/trackerFilterState", checked); -} - -int Preferences::getTransSelFilter() const -{ - return value("TransferListFilters/selectedFilterIndex", 0).toInt(); -} - -void Preferences::setTransSelFilter(const int &index) -{ - setValue("TransferListFilters/selectedFilterIndex", index); -} - -QByteArray Preferences::getTransHeaderState() const -{ - return value("TransferList/qt5/HeaderState").toByteArray(); -} - -void Preferences::setTransHeaderState(const QByteArray &state) -{ - setValue("TransferList/qt5/HeaderState", state); -} - -//From old RssSettings class -bool Preferences::isRSSWidgetEnabled() const -{ - return value("GUI/RSSWidget/Enabled", false).toBool(); -} - -void Preferences::setRSSWidgetVisible(const bool enabled) -{ - setValue("GUI/RSSWidget/Enabled", enabled); -} - -int Preferences::getToolbarTextPosition() const -{ - return value("Toolbar/textPosition", -1).toInt(); -} - -void Preferences::setToolbarTextPosition(const int position) -{ - setValue("Toolbar/textPosition", position); -} - -QList Preferences::getNetworkCookies() const -{ - QList cookies; - QStringList rawCookies = value("Network/Cookies").toStringList(); - foreach (const QString &rawCookie, rawCookies) - cookies << QNetworkCookie::parseCookies(rawCookie.toUtf8()); - - return cookies; -} - -void Preferences::setNetworkCookies(const QList &cookies) -{ - QStringList rawCookies; - foreach (const QNetworkCookie &cookie, cookies) - rawCookies << cookie.toRawForm(); - - setValue("Network/Cookies", rawCookies); -} - -int Preferences::getSpeedWidgetPeriod() const -{ - return value("SpeedWidget/period", 1).toInt(); -} - -void Preferences::setSpeedWidgetPeriod(const int period) -{ - setValue("SpeedWidget/period", period); -} - -bool Preferences::getSpeedWidgetGraphEnable(int id) const -{ - // UP and DOWN graphs enabled by default - return value("SpeedWidget/graph_enable_" + QString::number(id), (id == 0 || id == 1)).toBool(); -} - -void Preferences::setSpeedWidgetGraphEnable(int id, const bool enable) -{ - setValue("SpeedWidget/graph_enable_" + QString::number(id), enable); -} - -void Preferences::upgrade() -{ - QStringList labels = value("TransferListFilters/customLabels").toStringList(); - if (!labels.isEmpty()) { - QVariantMap categories = value("BitTorrent/Session/Categories").toMap(); - foreach (const QString &label, labels) { - if (!categories.contains(label)) - categories[label] = ""; - } - setValue("BitTorrent/Session/Categories", categories); - SettingsStorage::instance()->removeValue("TransferListFilters/customLabels"); - } - - SettingsStorage::instance()->removeValue("Preferences/Downloads/AppendLabel"); -} - -void Preferences::apply() -{ - if (SettingsStorage::instance()->save()) - emit changed(); -} diff --git a/src/base/preferences.h b/src/base/preferences.h deleted file mode 100644 index fe021bc78..000000000 --- a/src/base/preferences.h +++ /dev/null @@ -1,356 +0,0 @@ -/* - * Bittorrent Client using Qt4 and libtorrent. - * Copyright (C) 2006 Christophe Dumez - * Copyright (C) 2014 sledgehammer999 - * - * 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 - * Contact : hammered999@gmail.com - */ - -#ifndef PREFERENCES_H -#define PREFERENCES_H - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "types.h" - -enum scheduler_days -{ - EVERY_DAY, - WEEK_DAYS, - WEEK_ENDS, - MON, - TUE, - WED, - THU, - FRI, - SAT, - SUN -}; - -namespace TrayIcon -{ - enum Style - { - NORMAL = 0, - MONO_DARK, - MONO_LIGHT - }; -} - -namespace DNS -{ - enum Service - { - DYNDNS, - NOIP, - NONE = -1 - }; -} - -class SettingsStorage; - -class Preferences: public QObject -{ - Q_OBJECT - Q_DISABLE_COPY(Preferences) - - Preferences(); - - const QVariant value(const QString &key, const QVariant &defaultValue = QVariant()) const; - void setValue(const QString &key, const QVariant &value); - - static Preferences* m_instance; - -signals: - void changed(); - -public: - static void initInstance(); - static void freeInstance(); - static Preferences* instance(); - - // General options - QString getLocale() const; - void setLocale(const QString &locale); - bool deleteTorrentFilesAsDefault() const; - void setDeleteTorrentFilesAsDefault(bool del); - bool confirmOnExit() const; - void setConfirmOnExit(bool confirm); - bool speedInTitleBar() const; - void showSpeedInTitleBar(bool show); - bool useAlternatingRowColors() const; - void setAlternatingRowColors(bool b); - bool getHideZeroValues() const; - void setHideZeroValues(bool b); - int getHideZeroComboValues() const; - void setHideZeroComboValues(int n); - bool isStatusbarDisplayed() const; - void setStatusbarDisplayed(bool displayed); - bool isToolbarDisplayed() const; - void setToolbarDisplayed(bool displayed); - bool startMinimized() const; - void setStartMinimized(bool b); - bool isSplashScreenDisabled() const; - void setSplashScreenDisabled(bool b); - bool preventFromSuspend() const; - void setPreventFromSuspend(bool b); -#ifdef Q_OS_WIN - bool WinStartup() const; - void setWinStartup(bool b); -#endif - - // Downloads - QString lastLocationPath() const; - void setLastLocationPath(const QString &path); - QVariantHash getScanDirs() const; - void setScanDirs(const QVariantHash &dirs); - QString getScanDirsLastPath() const; - void setScanDirsLastPath(const QString &path); - bool isMailNotificationEnabled() const; - void setMailNotificationEnabled(bool enabled); - QString getMailNotificationEmail() const; - void setMailNotificationEmail(const QString &mail); - QString getMailNotificationSMTP() const; - void setMailNotificationSMTP(const QString &smtp_server); - bool getMailNotificationSMTPSSL() const; - void setMailNotificationSMTPSSL(bool use); - bool getMailNotificationSMTPAuth() const; - void setMailNotificationSMTPAuth(bool use); - QString getMailNotificationSMTPUsername() const; - void setMailNotificationSMTPUsername(const QString &username); - QString getMailNotificationSMTPPassword() const; - void setMailNotificationSMTPPassword(const QString &password); - int getActionOnDblClOnTorrentDl() const; - void setActionOnDblClOnTorrentDl(int act); - int getActionOnDblClOnTorrentFn() const; - void setActionOnDblClOnTorrentFn(int act); - - // Connection options - QTime getSchedulerStartTime() const; - void setSchedulerStartTime(const QTime &time); - QTime getSchedulerEndTime() const; - void setSchedulerEndTime(const QTime &time); - scheduler_days getSchedulerDays() const; - void setSchedulerDays(scheduler_days days); - - // Search - bool isSearchEnabled() const; - void setSearchEnabled(bool enabled); - - bool isWebUiEnabled() const; - void setWebUiEnabled(bool enabled); - bool isWebUiLocalAuthEnabled() const; - void setWebUiLocalAuthEnabled(bool enabled); - QString getServerDomains() const; - void setServerDomains(const QString &str); - quint16 getWebUiPort() const; - void setWebUiPort(quint16 port); - bool useUPnPForWebUIPort() const; - void setUPnPForWebUIPort(bool enabled); - QString getWebUiUsername() const; - void setWebUiUsername(const QString &username); - QString getWebUiPassword() const; - void setWebUiPassword(const QString &new_password); - bool isWebUiHttpsEnabled() const; - void setWebUiHttpsEnabled(bool enabled); - QByteArray getWebUiHttpsCertificate() const; - void setWebUiHttpsCertificate(const QByteArray &data); - QByteArray getWebUiHttpsKey() const; - void setWebUiHttpsKey(const QByteArray &data); - bool isDynDNSEnabled() const; - void setDynDNSEnabled(bool enabled); - DNS::Service getDynDNSService() const; - void setDynDNSService(int service); - QString getDynDomainName() const; - void setDynDomainName(const QString &name); - QString getDynDNSUsername() const; - void setDynDNSUsername(const QString &username); - QString getDynDNSPassword() const; - void setDynDNSPassword(const QString &password); - - // Advanced settings - void setUILockPassword(const QString &clear_password); - void clearUILockPassword(); - QString getUILockPasswordMD5() const; - bool isUILocked() const; - void setUILocked(bool locked); - bool isAutoRunEnabled() const; - void setAutoRunEnabled(bool enabled); - QString getAutoRunProgram() const; - void setAutoRunProgram(const QString &program); - bool shutdownWhenDownloadsComplete() const; - void setShutdownWhenDownloadsComplete(bool shutdown); - bool suspendWhenDownloadsComplete() const; - void setSuspendWhenDownloadsComplete(bool suspend); - bool hibernateWhenDownloadsComplete() const; - void setHibernateWhenDownloadsComplete(bool hibernate); - bool shutdownqBTWhenDownloadsComplete() const; - void setShutdownqBTWhenDownloadsComplete(bool shutdown); - bool dontConfirmAutoExit() const; - void setDontConfirmAutoExit(bool dontConfirmAutoExit); - bool recheckTorrentsOnCompletion() const; - void recheckTorrentsOnCompletion(bool recheck); - bool resolvePeerCountries() const; - void resolvePeerCountries(bool resolve); - bool resolvePeerHostNames() const; - void resolvePeerHostNames(bool resolve); -#if (defined(Q_OS_UNIX) && !defined(Q_OS_MAC)) - bool useSystemIconTheme() const; - void useSystemIconTheme(bool enabled); -#endif - bool recursiveDownloadDisabled() const; - void disableRecursiveDownload(bool disable = true); -#ifdef Q_OS_WIN - static QString getPythonPath(); - bool neverCheckFileAssoc() const; - void setNeverCheckFileAssoc(bool check = true); - static bool isTorrentFileAssocSet(); - static bool isMagnetLinkAssocSet(); - static void setTorrentFileAssoc(bool set); - static void setMagnetLinkAssoc(bool set); -#endif -#ifdef Q_OS_MAC - static bool isTorrentFileAssocSet(); - static bool isMagnetLinkAssocSet(); - static void setTorrentFileAssoc(); - static void setMagnetLinkAssoc(); -#endif - int getTrackerPort() const; - void setTrackerPort(int port); -#if defined(Q_OS_WIN) || defined(Q_OS_MAC) - bool isUpdateCheckEnabled() const; - void setUpdateCheckEnabled(bool enabled); -#endif - bool confirmTorrentDeletion() const; - void setConfirmTorrentDeletion(bool enabled); - bool confirmTorrentRecheck() const; - void setConfirmTorrentRecheck(bool enabled); - bool confirmRemoveAllTags() const; - void setConfirmRemoveAllTags(bool enabled); -#ifndef Q_OS_MAC - bool systrayIntegration() const; - void setSystrayIntegration(bool enabled); - bool minimizeToTray() const; - void setMinimizeToTray(bool b); - bool closeToTray() const; - void setCloseToTray(bool b); - TrayIcon::Style trayIconStyle() const; - void setTrayIconStyle(TrayIcon::Style style); -#endif - - // Stuff that don't appear in the Options GUI but are saved - // in the same file. - QDateTime getDNSLastUpd() const; - void setDNSLastUpd(const QDateTime &date); - QString getDNSLastIP() const; - void setDNSLastIP(const QString &ip); - bool getAcceptedLegal() const; - void setAcceptedLegal(const bool accepted); - QByteArray getMainGeometry() const; - void setMainGeometry(const QByteArray &geometry); - QByteArray getMainVSplitterState() const; - void setMainVSplitterState(const QByteArray &state); - QString getMainLastDir() const; - void setMainLastDir(const QString &path); - QSize getPrefSize(const QSize &defaultSize) const; - void setPrefSize(const QSize &size); - QStringList getPrefHSplitterSizes() const; - void setPrefHSplitterSizes(const QStringList &sizes); - QByteArray getPeerListState() const; - void setPeerListState(const QByteArray &state); - QString getPropSplitterSizes() const; - void setPropSplitterSizes(const QString &sizes); - QByteArray getPropFileListState() const; - void setPropFileListState(const QByteArray &state); - int getPropCurTab() const; - void setPropCurTab(const int &tab); - bool getPropVisible() const; - void setPropVisible(const bool visible); - QByteArray getPropTrackerListState() const; - void setPropTrackerListState(const QByteArray &state); - QSize getRssGeometrySize(const QSize &defaultSize) const; - void setRssGeometrySize(const QSize &geometry); - QByteArray getRssHSplitterSizes() const; - void setRssHSplitterSizes(const QByteArray &sizes); - QStringList getRssOpenFolders() const; - void setRssOpenFolders(const QStringList &folders); - QByteArray getRssSideSplitterState() const; - void setRssSideSplitterState(const QByteArray &state); - QByteArray getRssMainSplitterState() const; - void setRssMainSplitterState(const QByteArray &state); - QByteArray getSearchTabHeaderState() const; - void setSearchTabHeaderState(const QByteArray &state); - QStringList getSearchEngDisabled() const; - void setSearchEngDisabled(const QStringList &engines); - QString getTorImportLastContentDir() const; - void setTorImportLastContentDir(const QString &path); - QByteArray getTorImportGeometry() const; - void setTorImportGeometry(const QByteArray &geometry); - bool getStatusFilterState() const; - bool getCategoryFilterState() const; - bool getTagFilterState() const; - bool getTrackerFilterState() const; - int getTransSelFilter() const; - void setTransSelFilter(const int &index); - QByteArray getTransHeaderState() const; - void setTransHeaderState(const QByteArray &state); - int getToolbarTextPosition() const; - void setToolbarTextPosition(const int position); - - //From old RssSettings class - bool isRSSWidgetEnabled() const; - void setRSSWidgetVisible(const bool enabled); - - // Network - QList getNetworkCookies() const; - void setNetworkCookies(const QList &cookies); - - // SpeedWidget - int getSpeedWidgetPeriod() const; - void setSpeedWidgetPeriod(const int period); - bool getSpeedWidgetGraphEnable(int id) const; - void setSpeedWidgetGraphEnable(int id, const bool enable); - - void upgrade(); - -public slots: - void setStatusFilterState(bool checked); - void setCategoryFilterState(bool checked); - void setTagFilterState(bool checked); - void setTrackerFilterState(bool checked); - - void apply(); -}; - -#endif // PREFERENCES_H diff --git a/src/base/private/profile_p.cpp b/src/base/private/profile_p.cpp deleted file mode 100644 index 156ac1148..000000000 --- a/src/base/private/profile_p.cpp +++ /dev/null @@ -1,194 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2016 Eugene Shalygin - * 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. - * - */ - -#include "profile_p.h" - -#include - -#include "base/utils/fs.h" - -Private::Profile::Profile(const QString &configurationName) - : m_configurationSuffix {configurationName.isEmpty() ? QString() : QLatin1Char('_') + configurationName} -{ -} - -QString Private::Profile::configurationSuffix() const -{ - return m_configurationSuffix; -} - -QString Private::Profile::profileName() const -{ - return QCoreApplication::applicationName() + configurationSuffix(); -} - -Private::DefaultProfile::DefaultProfile(const QString &configurationName) - : Profile(configurationName) -{ -} - -QString Private::DefaultProfile::baseDirectory() const -{ - return QDir::homePath(); -} - -QString Private::DefaultProfile::cacheLocation() const -{ - return locationWithConfigurationName(QStandardPaths::CacheLocation); -} - -QString Private::DefaultProfile::configLocation() const -{ -#if defined(Q_OS_WIN) - // On Windows QSettings stores files in FOLDERID_RoamingAppData\AppName - return locationWithConfigurationName(QStandardPaths::AppDataLocation); -#else - return locationWithConfigurationName(QStandardPaths::AppConfigLocation); -#endif -} - -QString Private::DefaultProfile::dataLocation() const -{ -#if defined(Q_OS_WIN) || defined (Q_OS_MAC) - return locationWithConfigurationName(QStandardPaths::AppLocalDataLocation); -#else - // on Linux gods know why qBittorrent creates 'data' subdirectory in ~/.local/share/ - return QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) - + QLatin1String("/data/") + profileName() + QLatin1Char('/'); -#endif -} - -QString Private::DefaultProfile::downloadLocation() const -{ -#if defined(Q_OS_WIN) - if (QSysInfo::windowsVersion() <= QSysInfo::WV_XP) // Windows XP - return QDir(QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation)).absoluteFilePath( - QCoreApplication::translate("fsutils", "Downloads")); -#endif - return QStandardPaths::writableLocation(QStandardPaths::DownloadLocation); -} - -SettingsPtr Private::DefaultProfile::applicationSettings(const QString &name) const -{ -#if defined(Q_OS_WIN) || defined(Q_OS_MAC) - return SettingsPtr(new QSettings(QSettings::IniFormat, QSettings::UserScope, profileName(), name)); -#else - return SettingsPtr(new QSettings(profileName(), name)); -#endif -} - -QString Private::DefaultProfile::locationWithConfigurationName(QStandardPaths::StandardLocation location) const -{ - return QStandardPaths::writableLocation(location) + configurationSuffix(); -} - -Private::CustomProfile::CustomProfile(const QString &rootPath, const QString &configurationName) - : Profile {configurationName} - , m_rootDirectory {QDir(rootPath).absoluteFilePath(this->profileName())} -{ -} - -QString Private::CustomProfile::baseDirectory() const -{ - return m_rootDirectory.canonicalPath(); -} - -QString Private::CustomProfile::cacheLocation() const -{ - return m_rootDirectory.absoluteFilePath(QLatin1String(cacheDirName)); -} - -QString Private::CustomProfile::configLocation() const -{ - return m_rootDirectory.absoluteFilePath(QLatin1String(configDirName)); -} - -QString Private::CustomProfile::dataLocation() const -{ - return m_rootDirectory.absoluteFilePath(QLatin1String(dataDirName)); -} - -QString Private::CustomProfile::downloadLocation() const -{ - return m_rootDirectory.absoluteFilePath(QLatin1String(downloadsDirName)); -} - -SettingsPtr Private::CustomProfile::applicationSettings(const QString &name) const -{ - // here we force QSettings::IniFormat format always because we need it to be portable across platforms -#if defined(Q_OS_WIN) || defined(Q_OS_MAC) - constexpr const char *CONF_FILE_EXTENSION = ".ini"; -#else - constexpr const char *CONF_FILE_EXTENSION = ".conf"; -#endif - const QString settingsFileName {QDir(configLocation()).absoluteFilePath(name + QLatin1String(CONF_FILE_EXTENSION))}; - return SettingsPtr(new QSettings(settingsFileName, QSettings::IniFormat)); -} - -QString Private::NoConvertConverter::fromPortablePath(const QString &portablePath) const -{ - return portablePath; -} - -QString Private::NoConvertConverter::toPortablePath(const QString &path) const -{ - return path; -} - -Private::Converter::Converter(const QString &basePath) - : m_baseDir {basePath} -{ - m_baseDir.makeAbsolute(); -} - -QString Private::Converter::toPortablePath(const QString &path) const -{ - if (path.isEmpty() || m_baseDir.path().isEmpty()) - return path; - -#ifdef Q_OS_WIN - if (QDir::isAbsolutePath(path)) { - QChar driveLeter = path[0].toUpper(); - QChar baseDriveLetter = m_baseDir.path()[0].toUpper(); - bool onSameDrive = (driveLeter.category() == QChar::Letter_Uppercase) && (driveLeter == baseDriveLetter); - if (!onSameDrive) - return path; - } -#endif - return m_baseDir.relativeFilePath(path); -} - -QString Private::Converter::fromPortablePath(const QString &portablePath) const -{ - if (QDir::isAbsolutePath(portablePath)) - return portablePath; - - return QDir::cleanPath(m_baseDir.absoluteFilePath(portablePath)); -} diff --git a/src/base/private/profile_p.h b/src/base/private/profile_p.h deleted file mode 100644 index 7e6d9a7ea..000000000 --- a/src/base/private/profile_p.h +++ /dev/null @@ -1,135 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2016 Eugene Shalygin - * 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. - * - */ - -#ifndef QBT_PROFILE_P_H -#define QBT_PROFILE_P_H - -#include -#include -#include "base/profile.h" - -namespace Private -{ - class Profile - { - public: - virtual QString baseDirectory() const = 0; - virtual QString cacheLocation() const = 0; - virtual QString configLocation() const = 0; - virtual QString dataLocation() const = 0; - virtual QString downloadLocation() const = 0; - virtual SettingsPtr applicationSettings(const QString &name) const = 0; - - virtual ~Profile() = default; - - /** - * @brief QCoreApplication::applicationName() with optional configuration name appended - */ - QString profileName() const; - - protected: - Profile(const QString &configurationName); - - QString configurationSuffix() const; - private: - QString m_configurationSuffix; - }; - - /// Default implementation. Takes paths from system - class DefaultProfile: public Profile - { - public: - DefaultProfile(const QString &configurationName); - - QString baseDirectory() const override; - QString cacheLocation() const override; - QString configLocation() const override; - QString dataLocation() const override; - QString downloadLocation() const override; - SettingsPtr applicationSettings(const QString &name) const override; - - private: - /** - * @brief Standard path writable location for profile files - * - * @param location location kind - * @return QStandardPaths::writableLocation(location) / configurationName() - */ - QString locationWithConfigurationName(QStandardPaths::StandardLocation location) const; - }; - - /// Custom tree: creates directories under the specified root directory - class CustomProfile: public Profile - { - public: - CustomProfile(const QString &rootPath, const QString &configurationName); - - QString baseDirectory() const override; - QString cacheLocation() const override; - QString configLocation() const override; - QString dataLocation() const override; - QString downloadLocation() const override; - SettingsPtr applicationSettings(const QString &name) const override; - - private: - QDir m_rootDirectory; - static constexpr const char *cacheDirName = "cache"; - static constexpr const char *configDirName = "config"; - static constexpr const char *dataDirName = "data"; - static constexpr const char *downloadsDirName = "downloads"; - }; - - class PathConverter - { - public: - virtual QString toPortablePath(const QString &path) const = 0; - virtual QString fromPortablePath(const QString &portablePath) const = 0; - virtual ~PathConverter() = default; - }; - - class NoConvertConverter: public PathConverter - { - public: - QString toPortablePath(const QString &path) const override; - QString fromPortablePath(const QString &portablePath) const override; - }; - - class Converter: public PathConverter - { - public: - Converter(const QString &basePath); - QString toPortablePath(const QString &path) const override; - QString fromPortablePath(const QString &portablePath) const override; - - private: - QDir m_baseDir; - }; -} -#endif // QBT_PROFILE_P_H diff --git a/src/base/profile.cpp b/src/base/profile.cpp deleted file mode 100644 index d2fd9c310..000000000 --- a/src/base/profile.cpp +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2016 Eugene Shalygin - * 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. - * - */ - -#include "profile.h" - -#include - -#include "private/profile_p.h" - -Profile *Profile::m_instance = nullptr; - -Profile::Profile(Private::Profile *impl, Private::PathConverter *pathConverter) - : m_profileImpl(impl) - , m_pathConverterImpl(pathConverter) -{ - ensureDirectoryExists(SpecialFolder::Cache); - ensureDirectoryExists(SpecialFolder::Config); - ensureDirectoryExists(SpecialFolder::Data); - ensureDirectoryExists(SpecialFolder::Downloads); -} - -// to generate correct call to ProfilePrivate::~ProfileImpl() -Profile::~Profile() = default; - -void Profile::initialize(const QString &rootProfilePath, const QString &configurationName, - bool convertPathsToProfileRelative) -{ - QScopedPointer profile(rootProfilePath.isEmpty() - ? static_cast(new Private::DefaultProfile(configurationName)) - : static_cast(new Private::CustomProfile(rootProfilePath, configurationName))); - - QScopedPointer converter(convertPathsToProfileRelative - ? static_cast(new Private::Converter(profile->baseDirectory())) - : static_cast(new Private::NoConvertConverter())); - m_instance = new Profile(profile.take(), converter.take()); -} - -const Profile &Profile::instance() -{ - return *m_instance; -} - -QString Profile::location(SpecialFolder folder) const -{ - QString result; - switch (folder) { - case SpecialFolder::Cache: - result = m_profileImpl->cacheLocation(); - break; - case SpecialFolder::Config: - result = m_profileImpl->configLocation(); - break; - case SpecialFolder::Data: - result = m_profileImpl->dataLocation(); - break; - case SpecialFolder::Downloads: - result = m_profileImpl->downloadLocation(); - break; - } - - if (!result.endsWith(QLatin1Char('/'))) - result += QLatin1Char('/'); - return result; -} - -QString Profile::profileName() const -{ - return m_profileImpl->profileName(); -} - -SettingsPtr Profile::applicationSettings(const QString &name) const -{ - return m_profileImpl->applicationSettings(name); -} - -void Profile::ensureDirectoryExists(SpecialFolder folder) -{ - QString locationPath = location(folder); - if (!locationPath.isEmpty() && !QDir().mkpath(locationPath)) - qFatal("Could not create required directory '%s'", qPrintable(locationPath)); -} - -QString Profile::toPortablePath(const QString &absolutePath) const -{ - return m_pathConverterImpl->toPortablePath(absolutePath); -} - -QString Profile::fromPortablePath(const QString &portablePath) const -{ - return m_pathConverterImpl->fromPortablePath(portablePath); -} diff --git a/src/base/profile.h b/src/base/profile.h deleted file mode 100644 index 85557633a..000000000 --- a/src/base/profile.h +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2016 Eugene Shalygin - * 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. - * - */ - -#ifndef QBT_PROFILE_H -#define QBT_PROFILE_H - -#include - -#include -#include -#include - -class Application; - -namespace Private -{ - class Profile; - class PathConverter; -} - -using SettingsPtr = std::unique_ptr; - -enum class SpecialFolder -{ - Cache, - Config, - Data, - Downloads -}; - -class Profile -{ -public: - QString location(SpecialFolder folder) const; - SettingsPtr applicationSettings(const QString &name) const; - - /// Returns either default name for configuration file (QCoreApplication::applicationName()) - /// or the value, supplied via parameters - QString profileName() const; - - QString toPortablePath(const QString &absolutePath) const; - QString fromPortablePath(const QString &portablePath) const; - - static const Profile &instance(); - -private: - Profile(Private::Profile *impl, Private::PathConverter *pathConverter); - ~Profile(); - - friend class ::Application; - static void initialize(const QString &rootProfilePath, const QString &configurationName, - bool convertPathsToProfileRelative); - void ensureDirectoryExists(SpecialFolder folder); - - QScopedPointer m_profileImpl; - QScopedPointer m_pathConverterImpl; - static Profile *m_instance; -}; - -inline QString specialFolderLocation(SpecialFolder folder) -{ - return Profile::instance().location(folder); -} - -#endif // QBT_PROFILE_H diff --git a/src/base/rss/private/rss_parser.cpp b/src/base/rss/private/rss_parser.cpp deleted file mode 100644 index f1b45d837..000000000 --- a/src/base/rss/private/rss_parser.cpp +++ /dev/null @@ -1,460 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2015 Vladimir Golovnev - * 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 "rss_parser.h" - -#include -#include -#include -#include -#include -#include -#include - -#include "../rss_article.h" - -namespace -{ - const char shortDay[][4] = { - "Mon", "Tue", "Wed", - "Thu", "Fri", "Sat", - "Sun" - }; - - const char longDay[][10] = { - "Monday", "Tuesday", "Wednesday", - "Thursday", "Friday", "Saturday", - "Sunday" - }; - - const char shortMonth[][4] = { - "Jan", "Feb", "Mar", "Apr", - "May", "Jun", "Jul", "Aug", - "Sep", "Oct", "Nov", "Dec" - }; - - // Ported to Qt from KDElibs4 - QDateTime parseDate(const QString &string) - { - const QString str = string.trimmed(); - if (str.isEmpty()) - return QDateTime::currentDateTime(); - - int nyear = 6; // indexes within string to values - int nmonth = 4; - int nday = 2; - int nwday = 1; - int nhour = 7; - int nmin = 8; - int nsec = 9; - // Also accept obsolete form "Weekday, DD-Mon-YY HH:MM:SS ±hhmm" - QRegExp rx("^(?:([A-Z][a-z]+),\\s*)?(\\d{1,2})(\\s+|-)([^-\\s]+)(\\s+|-)(\\d{2,4})\\s+(\\d\\d):(\\d\\d)(?::(\\d\\d))?\\s+(\\S+)$"); - QStringList parts; - if (!str.indexOf(rx)) { - // Check that if date has '-' separators, both separators are '-'. - parts = rx.capturedTexts(); - bool h1 = (parts[3] == QLatin1String("-")); - bool h2 = (parts[5] == QLatin1String("-")); - if (h1 != h2) - return QDateTime::currentDateTime(); - } - else { - // Check for the obsolete form "Wdy Mon DD HH:MM:SS YYYY" - rx = QRegExp("^([A-Z][a-z]+)\\s+(\\S+)\\s+(\\d\\d)\\s+(\\d\\d):(\\d\\d):(\\d\\d)\\s+(\\d\\d\\d\\d)$"); - if (str.indexOf(rx)) - return QDateTime::currentDateTime(); - nyear = 7; - nmonth = 2; - nday = 3; - nwday = 1; - nhour = 4; - nmin = 5; - nsec = 6; - parts = rx.capturedTexts(); - } - - bool ok[4]; - const int day = parts[nday].toInt(&ok[0]); - int year = parts[nyear].toInt(&ok[1]); - const int hour = parts[nhour].toInt(&ok[2]); - const int minute = parts[nmin].toInt(&ok[3]); - if (!ok[0] || !ok[1] || !ok[2] || !ok[3]) - return QDateTime::currentDateTime(); - - int second = 0; - if (!parts[nsec].isEmpty()) { - second = parts[nsec].toInt(&ok[0]); - if (!ok[0]) - return QDateTime::currentDateTime(); - } - - bool leapSecond = (second == 60); - if (leapSecond) - second = 59; // apparently a leap second - validate below, once time zone is known - int month = 0; - for ( ; (month < 12) && (parts[nmonth] != shortMonth[month]); ++month); - int dayOfWeek = -1; - if (!parts[nwday].isEmpty()) { - // Look up the weekday name - while (++dayOfWeek < 7 && (shortDay[dayOfWeek] != parts[nwday])); - if (dayOfWeek >= 7) - for (dayOfWeek = 0; dayOfWeek < 7 && (longDay[dayOfWeek] != parts[nwday]); ++dayOfWeek); - } - - // if (month >= 12 || dayOfWeek >= 7 - // || (dayOfWeek < 0 && format == RFCDateDay)) - // return QDateTime; - int i = parts[nyear].size(); - if (i < 4) { - // It's an obsolete year specification with less than 4 digits - year += (i == 2 && year < 50) ? 2000 : 1900; - } - - // Parse the UTC offset part - int offset = 0; // set default to '-0000' - bool negOffset = false; - if (parts.count() > 10) { - rx = QRegExp("^([+-])(\\d\\d)(\\d\\d)$"); - if (!parts[10].indexOf(rx)) { - // It's a UTC offset ±hhmm - parts = rx.capturedTexts(); - offset = parts[2].toInt(&ok[0]) * 3600; - int offsetMin = parts[3].toInt(&ok[1]); - if (!ok[0] || !ok[1] || offsetMin > 59) - return QDateTime(); - offset += offsetMin * 60; - negOffset = (parts[1] == QLatin1String("-")); - if (negOffset) - offset = -offset; - } - else { - // Check for an obsolete time zone name - QByteArray zone = parts[10].toLatin1(); - if (zone.length() == 1 && isalpha(zone[0]) && toupper(zone[0]) != 'J') { - negOffset = true; // military zone: RFC 2822 treats as '-0000' - } - else if (zone != "UT" && zone != "GMT") { // treated as '+0000' - offset = (zone == "EDT") - ? -4 * 3600 - : ((zone == "EST") || (zone == "CDT")) - ? -5 * 3600 - : ((zone == "CST") || (zone == "MDT")) - ? -6 * 3600 - : (zone == "MST" || zone == "PDT") - ? -7 * 3600 - : (zone == "PST") - ? -8 * 3600 - : 0; - if (!offset) { - // Check for any other alphabetic time zone - bool nonalpha = false; - for (int i = 0, end = zone.size(); (i < end) && !nonalpha; ++i) - nonalpha = !isalpha(zone[i]); - if (nonalpha) - return QDateTime(); - // TODO: Attempt to recognize the time zone abbreviation? - negOffset = true; // unknown time zone: RFC 2822 treats as '-0000' - } - } - } - } - - QDate qdate(year, month + 1, day); // convert date, and check for out-of-range - if (!qdate.isValid()) - return QDateTime::currentDateTime(); - - QTime qTime(hour, minute, second); - QDateTime result(qdate, qTime, Qt::UTC); - if (offset) - result = result.addSecs(-offset); - if (!result.isValid()) - return QDateTime::currentDateTime(); // invalid date/time - - if (leapSecond) { - // Validate a leap second time. Leap seconds are inserted after 23:59:59 UTC. - // Convert the time to UTC and check that it is 00:00:00. - if ((hour*3600 + minute*60 + 60 - offset + 86400*5) % 86400) // (max abs(offset) is 100 hours) - return QDateTime::currentDateTime(); // the time isn't the last second of the day - } - - return result; - } -} - -using namespace RSS::Private; - -const int ParsingResultTypeId = qRegisterMetaType(); - -Parser::Parser(QString lastBuildDate) -{ - m_result.lastBuildDate = lastBuildDate; -} - -void Parser::parse(const QByteArray &feedData) -{ - QMetaObject::invokeMethod(this, "parse_impl", Qt::QueuedConnection - , Q_ARG(QByteArray, feedData)); -} - -// read and create items from a rss document -void Parser::parse_impl(const QByteArray &feedData) -{ - qDebug() << Q_FUNC_INFO; - - QXmlStreamReader xml(feedData); - bool foundChannel = false; - while (xml.readNextStartElement()) { - if (xml.name() == "rss") { - // Find channels - while (xml.readNextStartElement()) { - if (xml.name() == "channel") { - parseRSSChannel(xml); - foundChannel = true; - break; - } - else { - qDebug() << "Skip rss item: " << xml.name(); - xml.skipCurrentElement(); - } - } - break; - } - else if (xml.name() == "feed") { // Atom feed - parseAtomChannel(xml); - foundChannel = true; - break; - } - else { - qDebug() << "Skip root item: " << xml.name(); - xml.skipCurrentElement(); - } - } - - if (xml.hasError()) - m_result.error = xml.errorString(); - else if (!foundChannel) - m_result.error = tr("Invalid RSS feed."); - else - // Sort article list chronologically - // NOTE: We don't need to sort it here if articles are always - // sorted in fetched XML in reverse chronological order - std::sort(m_result.articles.begin(), m_result.articles.end() - , [](const QVariantHash &a1, const QVariantHash &a2) - { - return a1["date"].toDateTime() < a2["date"].toDateTime(); - }); - - emit finished(m_result); - m_result.articles.clear(); // clear articles only -} - -void Parser::parseRssArticle(QXmlStreamReader &xml) -{ - QVariantHash article; - - while (!xml.atEnd()) { - xml.readNext(); - const QString name(xml.name().toString()); - - if (xml.isEndElement() && (name == QLatin1String("item"))) - break; - - if (xml.isStartElement()) { - const QString text(xml.readElementText().trimmed()); - - if (name == QLatin1String("title")) { - article[Article::KeyTitle] = text; - } - else if (name == QLatin1String("enclosure")) { - if (xml.attributes().value("type") == QLatin1String("application/x-bittorrent")) - article[Article::KeyTorrentURL] = xml.attributes().value(QLatin1String("url")).toString(); - } - else if (name == QLatin1String("link")) { - if (text.startsWith(QLatin1String("magnet:"), Qt::CaseInsensitive)) - article[Article::KeyTorrentURL] = text; // magnet link instead of a news URL - else - article[Article::KeyLink] = text; - } - else if (name == QLatin1String("description")) { - article[Article::KeyDescription] = text; - } - else if (name == QLatin1String("pubDate")) { - article[Article::KeyDate] = parseDate(text); - } - else if (name == QLatin1String("author")) { - article[Article::KeyAuthor] = text; - } - else if (name == QLatin1String("guid")) { - article[Article::KeyId] = text; - } - else { - article[name] = text; - } - } - } - - m_result.articles.prepend(article); -} - -void Parser::parseRSSChannel(QXmlStreamReader &xml) -{ - qDebug() << Q_FUNC_INFO; - Q_ASSERT(xml.isStartElement() && xml.name() == "channel"); - - while (!xml.atEnd()) { - xml.readNext(); - - if (xml.isStartElement()) { - if (xml.name() == "title") { - m_result.title = xml.readElementText(); - } - else if (xml.name() == "lastBuildDate") { - QString lastBuildDate = xml.readElementText(); - if (!lastBuildDate.isEmpty()) { - if (m_result.lastBuildDate == lastBuildDate) { - qDebug() << "The RSS feed has not changed since last time, aborting parsing."; - return; - } - m_result.lastBuildDate = lastBuildDate; - } - } - else if (xml.name() == "item") { - parseRssArticle(xml); - } - } - } -} - -void Parser::parseAtomArticle(QXmlStreamReader &xml) -{ - QVariantHash article; - bool doubleContent = false; - - while (!xml.atEnd()) { - xml.readNext(); - const QString name(xml.name().toString()); - - if (xml.isEndElement() && (name == QLatin1String("entry"))) - break; - - if (xml.isStartElement()) { - const QString text(xml.readElementText().trimmed()); - - if (name == QLatin1String("title")) { - article[Article::KeyTitle] = text; - } - else if (name == QLatin1String("link")) { - QString link = (xml.attributes().isEmpty() - ? text - : xml.attributes().value(QLatin1String("href")).toString()); - - if (link.startsWith(QLatin1String("magnet:"), Qt::CaseInsensitive)) - article[Article::KeyTorrentURL] = link; // magnet link instead of a news URL - else - // Atom feeds can have relative links, work around this and - // take the stress of figuring article full URI from UI - // Assemble full URI - article[Article::KeyLink] = (m_baseUrl.isEmpty() ? link : m_baseUrl + link); - - } - else if ((name == QLatin1String("summary")) || (name == QLatin1String("content"))){ - if (doubleContent) { // Duplicate content -> ignore - xml.readNext(); - - while ((xml.name() != QLatin1String("summary")) && (xml.name() != QLatin1String("content"))) - xml.readNext(); - - continue; - } - - // Try to also parse broken articles, which don't use html '&' escapes - // Actually works great for non-broken content too - QString feedText = xml.readElementText(QXmlStreamReader::IncludeChildElements); - if (!feedText.isEmpty()) - article[Article::KeyDescription] = feedText.trimmed(); - - doubleContent = true; - } - else if (name == QLatin1String("updated")) { - // ATOM uses standard compliant date, don't do fancy stuff - QDateTime articleDate = QDateTime::fromString(text, Qt::ISODate); - article[Article::KeyDate] = (articleDate.isValid() ? articleDate : QDateTime::currentDateTime()); - } - else if (name == QLatin1String("author")) { - xml.readNext(); - while (xml.name() != QLatin1String("author")) { - if (xml.name() == QLatin1String("name")) - article[Article::KeyAuthor] = xml.readElementText().trimmed(); - xml.readNext(); - } - } - else if (name == QLatin1String("id")) { - article[Article::KeyId] = text; - } - else { - article[name] = text; - } - } - } - - m_result.articles.prepend(article); -} - -void Parser::parseAtomChannel(QXmlStreamReader &xml) -{ - qDebug() << Q_FUNC_INFO; - Q_ASSERT(xml.isStartElement() && xml.name() == "feed"); - - m_baseUrl = xml.attributes().value("xml:base").toString(); - - while (!xml.atEnd()) { - xml.readNext(); - - if (xml.isStartElement()) { - if (xml.name() == "title") { - m_result.title = xml.readElementText(); - } - else if (xml.name() == "updated") { - QString lastBuildDate = xml.readElementText(); - if (!lastBuildDate.isEmpty()) { - if (m_result.lastBuildDate == lastBuildDate) { - qDebug() << "The RSS feed has not changed since last time, aborting parsing."; - return; - } - m_result.lastBuildDate = lastBuildDate; - } - } - else if (xml.name() == "entry") { - parseAtomArticle(xml); - } - } - } -} diff --git a/src/base/rss/private/rss_parser.h b/src/base/rss/private/rss_parser.h deleted file mode 100644 index 8d2c705e2..000000000 --- a/src/base/rss/private/rss_parser.h +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2015 Vladimir Golovnev - * 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 - */ - -#pragma once - -#include -#include -#include -#include - -class QXmlStreamReader; - -namespace RSS -{ - namespace Private - { - struct ParsingResult - { - QString error; - QString lastBuildDate; - QString title; - QList articles; - }; - - class Parser: public QObject - { - Q_OBJECT - - public: - explicit Parser(QString lastBuildDate); - void parse(const QByteArray &feedData); - - signals: - void finished(const RSS::Private::ParsingResult &result); - - private: - Q_INVOKABLE void parse_impl(const QByteArray &feedData); - void parseRssArticle(QXmlStreamReader &xml); - void parseRSSChannel(QXmlStreamReader &xml); - void parseAtomArticle(QXmlStreamReader &xml); - void parseAtomChannel(QXmlStreamReader &xml); - - QString m_baseUrl; - ParsingResult m_result; - }; - } -} - -Q_DECLARE_METATYPE(RSS::Private::ParsingResult) diff --git a/src/base/rss/rss_article.cpp b/src/base/rss/rss_article.cpp deleted file mode 100644 index c53d3bfca..000000000 --- a/src/base/rss/rss_article.cpp +++ /dev/null @@ -1,158 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2017 Vladimir Golovnev - * Copyright (C) 2010 Christophe Dumez - * Copyright (C) 2010 Arnaud Demaiziere - * - * 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. - */ - -#include "rss_article.h" - -#include -#include -#include - -#include "rss_feed.h" - -using namespace RSS; - -const QString Article::KeyId(QStringLiteral("id")); -const QString Article::KeyDate(QStringLiteral("date")); -const QString Article::KeyTitle(QStringLiteral("title")); -const QString Article::KeyAuthor(QStringLiteral("author")); -const QString Article::KeyDescription(QStringLiteral("description")); -const QString Article::KeyTorrentURL(QStringLiteral("torrentURL")); -const QString Article::KeyLink(QStringLiteral("link")); -const QString Article::KeyIsRead(QStringLiteral("isRead")); - -Article::Article(Feed *feed, const QVariantHash &varHash) - : QObject(feed) - , m_feed(feed) - , m_guid(varHash.value(KeyId).toString()) - , m_date(varHash.value(KeyDate).toDateTime()) - , m_title(varHash.value(KeyTitle).toString()) - , m_author(varHash.value(KeyAuthor).toString()) - , m_description(varHash.value(KeyDescription).toString()) - , m_torrentURL(varHash.value(KeyTorrentURL).toString()) - , m_link(varHash.value(KeyLink).toString()) - , m_isRead(varHash.value(KeyIsRead, false).toBool()) - , m_data(varHash) -{ - // If item does not have a guid, fall back to some other identifier - if (m_guid.isEmpty()) - m_guid = varHash.value(KeyTorrentURL).toString(); - if (m_guid.isEmpty()) - m_guid = varHash.value(KeyTitle).toString(); - if (m_guid.isEmpty()) - throw std::runtime_error("Bad RSS Article data"); - - m_data[KeyId] = m_guid; - - if (m_torrentURL.isEmpty()) { - m_torrentURL = m_link; - m_data[KeyTorrentURL] = m_torrentURL; - } -} - -Article::Article(Feed *feed, const QJsonObject &jsonObj) - : Article(feed, jsonObj.toVariantHash()) -{ - // JSON object store DateTime as string so we need to convert it - m_date = QDateTime::fromString(jsonObj.value(KeyDate).toString(), Qt::RFC2822Date); - m_data[KeyDate] = m_date; -} - -QString Article::guid() const -{ - return m_guid; -} - -QDateTime Article::date() const -{ - return m_date; -} - -QString Article::title() const -{ - return m_title; -} - -QString Article::author() const -{ - return m_author; -} - -QString Article::description() const -{ - return m_description; -} - -QString Article::torrentUrl() const -{ - return (m_torrentURL.isEmpty() ? m_link : m_torrentURL); -} - -QString Article::link() const -{ - return m_link; -} - -bool Article::isRead() const -{ - return m_isRead; -} - -QVariantHash Article::data() const -{ - return m_data; -} - -void Article::markAsRead() -{ - if (!m_isRead) { - m_isRead = true; - m_data[KeyIsRead] = m_isRead; - emit read(this); - } -} - -QJsonObject Article::toJsonObject() const -{ - auto jsonObj = QJsonObject::fromVariantHash(m_data); - // JSON object doesn't support DateTime so we need to convert it - jsonObj[KeyDate] = m_date.toString(Qt::RFC2822Date); - - return jsonObj; -} - -bool Article::articleDateRecentThan(Article *article, const QDateTime &date) -{ - return article->date() > date; -} - -Feed *Article::feed() const -{ - return m_feed; -} diff --git a/src/base/rss/rss_article.h b/src/base/rss/rss_article.h deleted file mode 100644 index a77967551..000000000 --- a/src/base/rss/rss_article.h +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2017 Vladimir Golovnev - * Copyright (C) 2010 Christophe Dumez - * Copyright (C) 2010 Arnaud Demaiziere - * - * 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. - */ - -#pragma once - -#include -#include -#include -#include - -namespace RSS -{ - class Feed; - - class Article: public QObject - { - Q_OBJECT - Q_DISABLE_COPY(Article) - - friend class Feed; - - Article(Feed *feed, const QVariantHash &varHash); - Article(Feed *feed, const QJsonObject &jsonObj); - - public: - static const QString KeyId; - static const QString KeyDate; - static const QString KeyTitle; - static const QString KeyAuthor; - static const QString KeyDescription; - static const QString KeyTorrentURL; - static const QString KeyLink; - static const QString KeyIsRead; - - Feed *feed() const; - QString guid() const; - QDateTime date() const; - QString title() const; - QString author() const; - QString description() const; - QString torrentUrl() const; - QString link() const; - bool isRead() const; - QVariantHash data() const; - - void markAsRead(); - - QJsonObject toJsonObject() const; - - static bool articleDateRecentThan(Article *article, const QDateTime &date); - - signals: - void read(Article *article = nullptr); - - private: - Feed *m_feed = nullptr; - QString m_guid; - QDateTime m_date; - QString m_title; - QString m_author; - QString m_description; - QString m_torrentURL; - QString m_link; - bool m_isRead = false; - QVariantHash m_data; - }; -} diff --git a/src/base/rss/rss_autodownloader.cpp b/src/base/rss/rss_autodownloader.cpp deleted file mode 100644 index 7707983de..000000000 --- a/src/base/rss/rss_autodownloader.cpp +++ /dev/null @@ -1,387 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2017 Vladimir Golovnev - * - * 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. - */ - -#include "rss_autodownloader.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "../bittorrent/magneturi.h" -#include "../bittorrent/session.h" -#include "../asyncfilestorage.h" -#include "../logger.h" -#include "../profile.h" -#include "../settingsstorage.h" -#include "../tristatebool.h" -#include "../utils/fs.h" -#include "rss_article.h" -#include "rss_autodownloadrule.h" -#include "rss_feed.h" -#include "rss_folder.h" -#include "rss_session.h" - -struct ProcessingJob -{ - QString feedURL; - QVariantHash articleData; -}; - -const QString ConfFolderName(QStringLiteral("rss")); -const QString RulesFileName(QStringLiteral("download_rules.json")); - -const QString SettingsKey_ProcessingEnabled(QStringLiteral("RSS/AutoDownloader/EnableProcessing")); - -using namespace RSS; - -QPointer AutoDownloader::m_instance = nullptr; - -AutoDownloader::AutoDownloader() - : m_processingEnabled(SettingsStorage::instance()->loadValue(SettingsKey_ProcessingEnabled, false).toBool()) - , m_processingTimer(new QTimer(this)) - , m_ioThread(new QThread(this)) -{ - Q_ASSERT(!m_instance); // only one instance is allowed - m_instance = this; - - m_fileStorage = new AsyncFileStorage( - Utils::Fs::expandPathAbs(specialFolderLocation(SpecialFolder::Config) + ConfFolderName)); - if (!m_fileStorage) - throw std::runtime_error("Directory for RSS AutoDownloader data is unavailable."); - - m_fileStorage->moveToThread(m_ioThread); - connect(m_ioThread, &QThread::finished, m_fileStorage, &AsyncFileStorage::deleteLater); - connect(m_fileStorage, &AsyncFileStorage::failed, [](const QString &fileName, const QString &errorString) - { - Logger::instance()->addMessage(QString("Couldn't save RSS AutoDownloader data in %1. Error: %2") - .arg(fileName).arg(errorString), Log::WARNING); - }); - - m_ioThread->start(); - - connect(BitTorrent::Session::instance(), &BitTorrent::Session::downloadFromUrlFinished - , this, &AutoDownloader::handleTorrentDownloadFinished); - connect(BitTorrent::Session::instance(), &BitTorrent::Session::downloadFromUrlFailed - , this, &AutoDownloader::handleTorrentDownloadFailed); - - load(); - - m_processingTimer->setSingleShot(true); - connect(m_processingTimer, &QTimer::timeout, this, &AutoDownloader::process); - - if (m_processingEnabled) - startProcessing(); -} - -AutoDownloader::~AutoDownloader() -{ - store(); - - m_ioThread->quit(); - m_ioThread->wait(); -} - -AutoDownloader *AutoDownloader::instance() -{ - return m_instance; -} - -bool AutoDownloader::hasRule(const QString &ruleName) const -{ - return m_rules.contains(ruleName); -} - -AutoDownloadRule AutoDownloader::ruleByName(const QString &ruleName) const -{ - return m_rules.value(ruleName, AutoDownloadRule("Unknown Rule")); -} - -QList AutoDownloader::rules() const -{ - return m_rules.values(); -} - -void AutoDownloader::insertRule(const AutoDownloadRule &rule) -{ - if (!hasRule(rule.name())) { - // Insert new rule - setRule_impl(rule); - m_dirty = true; - store(); - emit ruleAdded(rule.name()); - resetProcessingQueue(); - } - else if (ruleByName(rule.name()) != rule) { - // Update existing rule - setRule_impl(rule); - m_dirty = true; - storeDeferred(); - emit ruleChanged(rule.name()); - resetProcessingQueue(); - } -} - -bool AutoDownloader::renameRule(const QString &ruleName, const QString &newRuleName) -{ - if (!hasRule(ruleName)) return false; - if (hasRule(newRuleName)) return false; - - m_rules.insert(newRuleName, m_rules.take(ruleName)); - m_dirty = true; - store(); - emit ruleRenamed(newRuleName, ruleName); - return true; -} - -void AutoDownloader::removeRule(const QString &ruleName) -{ - if (m_rules.contains(ruleName)) { - emit ruleAboutToBeRemoved(ruleName); - m_rules.remove(ruleName); - m_dirty = true; - store(); - } -} - -void AutoDownloader::process() -{ - if (m_processingQueue.isEmpty()) return; // processing was disabled - - processJob(m_processingQueue.takeFirst()); - if (!m_processingQueue.isEmpty()) - // Schedule to process the next torrent (if any) - m_processingTimer->start(); -} - -void AutoDownloader::handleTorrentDownloadFinished(const QString &url) -{ - auto job = m_waitingJobs.take(url); - if (!job) return; - - if (Feed *feed = Session::instance()->feedByURL(job->feedURL)) - if (Article *article = feed->articleByGUID(job->articleData.value(Article::KeyId).toString())) - article->markAsRead(); -} - -void AutoDownloader::handleTorrentDownloadFailed(const QString &url) -{ - m_waitingJobs.remove(url); - // TODO: Re-schedule job here. -} - -void AutoDownloader::handleNewArticle(Article *article) -{ - if (!article->isRead() && !article->torrentUrl().isEmpty()) - addJobForArticle(article); -} - -void AutoDownloader::setRule_impl(const AutoDownloadRule &rule) -{ - m_rules.insert(rule.name(), rule); -} - -void AutoDownloader::addJobForArticle(Article *article) -{ - const QString torrentURL = article->torrentUrl(); - if (m_waitingJobs.contains(torrentURL)) return; - - QSharedPointer job(new ProcessingJob); - job->feedURL = article->feed()->url(); - job->articleData = article->data(); - m_processingQueue.append(job); - if (!m_processingTimer->isActive()) - m_processingTimer->start(); -} - -void AutoDownloader::processJob(const QSharedPointer &job) -{ - for (AutoDownloadRule &rule: m_rules) { - if (!rule.isEnabled()) continue; - if (!rule.feedURLs().contains(job->feedURL)) continue; - if (!rule.matches(job->articleData.value(Article::KeyTitle).toString())) continue; - - auto articleDate = job->articleData.value(Article::KeyDate).toDateTime(); - // if rule is in ignoring state do nothing with matched torrent - if (rule.ignoreDays() > 0) { - if (rule.lastMatch().isValid()) { - if (articleDate < rule.lastMatch().addDays(rule.ignoreDays())) - return; - } - } - - rule.setLastMatch(articleDate); - m_dirty = true; - storeDeferred(); - - BitTorrent::AddTorrentParams params; - params.savePath = rule.savePath(); - params.category = rule.assignedCategory(); - params.addPaused = rule.addPaused(); - auto torrentURL = job->articleData.value(Article::KeyTorrentURL).toString(); - BitTorrent::Session::instance()->addTorrent(torrentURL, params); - - if (BitTorrent::MagnetUri(torrentURL).isValid()) { - if (Feed *feed = Session::instance()->feedByURL(job->feedURL)) { - if (Article *article = feed->articleByGUID(job->articleData.value(Article::KeyId).toString())) - article->markAsRead(); - } - } - else { - // waiting for torrent file downloading - // normalize URL string via QUrl since DownloadManager do it - m_waitingJobs.insert(QUrl(torrentURL).toString(), job); - } - - return; - } -} - -void AutoDownloader::load() -{ - QFile rulesFile(m_fileStorage->storageDir().absoluteFilePath(RulesFileName)); - - if (!rulesFile.exists()) - loadRulesLegacy(); - else if (rulesFile.open(QFile::ReadOnly)) - loadRules(rulesFile.readAll()); - else - Logger::instance()->addMessage( - QString("Couldn't read RSS AutoDownloader rules from %1. Error: %2") - .arg(rulesFile.fileName()).arg(rulesFile.errorString()), Log::WARNING); -} - -void AutoDownloader::loadRules(const QByteArray &data) -{ - QJsonParseError jsonError; - QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &jsonError); - if (jsonError.error != QJsonParseError::NoError) { - Logger::instance()->addMessage( - QString("Couldn't parse RSS AutoDownloader rules. Error: %1") - .arg(jsonError.errorString()), Log::WARNING); - return; - } - - if (!jsonDoc.isObject()) { - Logger::instance()->addMessage( - QString("Couldn't load RSS AutoDownloader rules. Invalid data format."), Log::WARNING); - return; - } - - QJsonObject jsonObj = jsonDoc.object(); - foreach (const QString &key, jsonObj.keys()) { - const QJsonValue jsonVal = jsonObj.value(key); - if (!jsonVal.isObject()) { - Logger::instance()->addMessage( - QString("Couldn't load RSS AutoDownloader rule '%1'. Invalid data format.") - .arg(key), Log::WARNING); - continue; - } - - setRule_impl(AutoDownloadRule::fromJsonObject(jsonVal.toObject(), key)); - } -} - -void AutoDownloader::loadRulesLegacy() -{ - SettingsPtr settings = Profile::instance().applicationSettings(QStringLiteral("qBittorrent-rss")); - QVariantHash rules = settings->value(QStringLiteral("download_rules")).toHash(); - foreach (const QVariant &ruleVar, rules) { - auto rule = AutoDownloadRule::fromVariantHash(ruleVar.toHash()); - if (!rule.name().isEmpty()) - insertRule(rule); - } -} - -void AutoDownloader::store() -{ - if (!m_dirty) return; - - m_dirty = false; - m_savingTimer.stop(); - - QJsonObject jsonObj; - foreach (auto rule, m_rules) - jsonObj.insert(rule.name(), rule.toJsonObject()); - - m_fileStorage->store(RulesFileName, QJsonDocument(jsonObj).toJson()); -} - -void AutoDownloader::storeDeferred() -{ - if (!m_savingTimer.isActive()) - m_savingTimer.start(5 * 1000, this); -} - -bool AutoDownloader::isProcessingEnabled() const -{ - return m_processingEnabled; -} - -void AutoDownloader::resetProcessingQueue() -{ - m_processingQueue.clear(); - foreach (Article *article, Session::instance()->rootFolder()->articles()) { - if (!article->isRead() && !article->torrentUrl().isEmpty()) - addJobForArticle(article); - } -} - -void AutoDownloader::startProcessing() -{ - resetProcessingQueue(); - connect(Session::instance()->rootFolder(), &Folder::newArticle, this, &AutoDownloader::handleNewArticle); -} - -void AutoDownloader::setProcessingEnabled(bool enabled) -{ - if (m_processingEnabled != enabled) { - m_processingEnabled = enabled; - SettingsStorage::instance()->storeValue(SettingsKey_ProcessingEnabled, m_processingEnabled); - if (m_processingEnabled) { - startProcessing(); - } - else { - m_processingQueue.clear(); - disconnect(Session::instance()->rootFolder(), &Folder::newArticle, this, &AutoDownloader::handleNewArticle); - } - - emit processingStateChanged(m_processingEnabled); - } -} - -void AutoDownloader::timerEvent(QTimerEvent *event) -{ - Q_UNUSED(event); - store(); -} diff --git a/src/base/rss/rss_autodownloader.h b/src/base/rss/rss_autodownloader.h deleted file mode 100644 index 50919f978..000000000 --- a/src/base/rss/rss_autodownloader.h +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2017 Vladimir Golovnev - * - * 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. - */ - -#pragma once - -#include -#include -#include -#include -#include -#include - -class QThread; -class QTimer; -class Application; -class AsyncFileStorage; -struct ProcessingJob; - -namespace RSS -{ - class Article; - class Feed; - class Item; - - class AutoDownloadRule; - - class AutoDownloader final: public QObject - { - Q_OBJECT - Q_DISABLE_COPY(AutoDownloader) - - friend class ::Application; - - AutoDownloader(); - ~AutoDownloader() override; - - public: - static AutoDownloader *instance(); - - bool isProcessingEnabled() const; - void setProcessingEnabled(bool enabled); - - bool hasRule(const QString &ruleName) const; - AutoDownloadRule ruleByName(const QString &ruleName) const; - QList rules() const; - - void insertRule(const AutoDownloadRule &rule); - bool renameRule(const QString &ruleName, const QString &newRuleName); - void removeRule(const QString &ruleName); - - signals: - void processingStateChanged(bool enabled); - void ruleAdded(const QString &ruleName); - void ruleChanged(const QString &ruleName); - void ruleRenamed(const QString &ruleName, const QString &oldRuleName); - void ruleAboutToBeRemoved(const QString &ruleName); - - private slots: - void process(); - void handleTorrentDownloadFinished(const QString &url); - void handleTorrentDownloadFailed(const QString &url); - void handleNewArticle(Article *article); - - private: - void timerEvent(QTimerEvent *event) override; - void setRule_impl(const AutoDownloadRule &rule); - void resetProcessingQueue(); - void startProcessing(); - void addJobForArticle(Article *article); - void processJob(const QSharedPointer &job); - void load(); - void loadRules(const QByteArray &data); - void loadRulesLegacy(); - void store(); - void storeDeferred(); - - static QPointer m_instance; - - bool m_processingEnabled; - QTimer *m_processingTimer; - QThread *m_ioThread; - AsyncFileStorage *m_fileStorage; - QHash m_rules; - QList> m_processingQueue; - QHash> m_waitingJobs; - bool m_dirty = false; - QBasicTimer m_savingTimer; - }; -} diff --git a/src/base/rss/rss_autodownloadrule.cpp b/src/base/rss/rss_autodownloadrule.cpp deleted file mode 100644 index 48c194621..000000000 --- a/src/base/rss/rss_autodownloadrule.cpp +++ /dev/null @@ -1,538 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2017 Vladimir Golovnev - * Copyright (C) 2010 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. - */ - -#include "rss_autodownloadrule.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "../preferences.h" -#include "../tristatebool.h" -#include "../utils/fs.h" -#include "../utils/string.h" -#include "rss_feed.h" -#include "rss_article.h" - -namespace -{ - TriStateBool jsonValueToTriStateBool(const QJsonValue &jsonVal) - { - if (jsonVal.isBool()) - return TriStateBool(jsonVal.toBool()); - - if (!jsonVal.isNull()) - qDebug() << Q_FUNC_INFO << "Incorrect value" << jsonVal.toVariant(); - - return TriStateBool::Undefined; - } - - QJsonValue triStateBoolToJsonValue(const TriStateBool &triStateBool) - { - switch (static_cast(triStateBool)) { - case 0: return false; break; - case 1: return true; break; - default: return QJsonValue(); - } - } -} - -const QString Str_Name(QStringLiteral("name")); -const QString Str_Enabled(QStringLiteral("enabled")); -const QString Str_UseRegex(QStringLiteral("useRegex")); -const QString Str_MustContain(QStringLiteral("mustContain")); -const QString Str_MustNotContain(QStringLiteral("mustNotContain")); -const QString Str_EpisodeFilter(QStringLiteral("episodeFilter")); -const QString Str_AffectedFeeds(QStringLiteral("affectedFeeds")); -const QString Str_SavePath(QStringLiteral("savePath")); -const QString Str_AssignedCategory(QStringLiteral("assignedCategory")); -const QString Str_LastMatch(QStringLiteral("lastMatch")); -const QString Str_IgnoreDays(QStringLiteral("ignoreDays")); -const QString Str_AddPaused(QStringLiteral("addPaused")); - -namespace RSS -{ - struct AutoDownloadRuleData: public QSharedData - { - QString name; - bool enabled = true; - - QStringList mustContain; - QStringList mustNotContain; - QString episodeFilter; - QStringList feedURLs; - bool useRegex = false; - int ignoreDays = 0; - QDateTime lastMatch; - - QString savePath; - QString category; - TriStateBool addPaused = TriStateBool::Undefined; - - mutable QHash cachedRegexes; - - bool operator==(const AutoDownloadRuleData &other) const - { - return (name == other.name) - && (enabled == other.enabled) - && (mustContain == other.mustContain) - && (mustNotContain == other.mustNotContain) - && (episodeFilter == other.episodeFilter) - && (feedURLs == other.feedURLs) - && (useRegex == other.useRegex) - && (ignoreDays == other.ignoreDays) - && (lastMatch == other.lastMatch) - && (savePath == other.savePath) - && (category == other.category) - && (addPaused == other.addPaused); - } - }; -} - -using namespace RSS; - -AutoDownloadRule::AutoDownloadRule(const QString &name) - : m_dataPtr(new AutoDownloadRuleData) -{ - setName(name); -} - -AutoDownloadRule::AutoDownloadRule(const AutoDownloadRule &other) - : m_dataPtr(other.m_dataPtr) -{ -} - -AutoDownloadRule::~AutoDownloadRule() {} - -QRegularExpression AutoDownloadRule::cachedRegex(const QString &expression, bool isRegex) const -{ - // Use a cache of regexes so we don't have to continually recompile - big performance increase. - // The cache is cleared whenever the regex/wildcard, must or must not contain fields or - // episode filter are modified. - Q_ASSERT(!expression.isEmpty()); - QRegularExpression regex(m_dataPtr->cachedRegexes[expression]); - - if (!regex.pattern().isEmpty()) - return regex; - - return m_dataPtr->cachedRegexes[expression] = QRegularExpression(isRegex ? expression : Utils::String::wildcardToRegex(expression), QRegularExpression::CaseInsensitiveOption); -} - -bool AutoDownloadRule::matches(const QString &articleTitle, const QString &expression) const -{ - static QRegularExpression whitespace("\\s+"); - - if (expression.isEmpty()) { - // A regex of the form "expr|" will always match, so do the same for wildcards - return true; - } - else if (m_dataPtr->useRegex) { - QRegularExpression reg(cachedRegex(expression)); - return reg.match(articleTitle).hasMatch(); - } - else { - // Only match if every wildcard token (separated by spaces) is present in the article name. - // Order of wildcard tokens is unimportant (if order is important, they should have used *). - foreach (const QString &wildcard, expression.split(whitespace, QString::SplitBehavior::SkipEmptyParts)) { - QRegularExpression reg(cachedRegex(wildcard, false)); - - if (!reg.match(articleTitle).hasMatch()) - return false; - } - } - - return true; -} - -bool AutoDownloadRule::matches(const QString &articleTitle) const -{ - if (!m_dataPtr->mustContain.empty()) { - bool logged = false; - bool foundMustContain = false; - - // Each expression is either a regex, or a set of wildcards separated by whitespace. - // Accept if any complete expression matches. - foreach (const QString &expression, m_dataPtr->mustContain) { - if (!logged) { -// qDebug() << "Checking matching" << (m_dataPtr->useRegex ? "regex:" : "wildcard expressions:") << m_dataPtr->mustContain.join("|"); - logged = true; - } - - // A regex of the form "expr|" will always match, so do the same for wildcards - foundMustContain = matches(articleTitle, expression); - - if (foundMustContain) { -// qDebug() << "Found matching" << (m_dataPtr->useRegex ? "regex:" : "wildcard expression:") << expression; - break; - } - } - - if (!foundMustContain) - return false; - } - - if (!m_dataPtr->mustNotContain.empty()) { - bool logged = false; - - // Each expression is either a regex, or a set of wildcards separated by whitespace. - // Reject if any complete expression matches. - foreach (const QString &expression, m_dataPtr->mustNotContain) { - if (!logged) { -// qDebug() << "Checking not matching" << (m_dataPtr->useRegex ? "regex:" : "wildcard expressions:") << m_dataPtr->mustNotContain.join("|"); - logged = true; - } - - // A regex of the form "expr|" will always match, so do the same for wildcards - if (matches(articleTitle, expression)) { -// qDebug() << "Found not matching" << (m_dataPtr->useRegex ? "regex:" : "wildcard expression:") << expression; - return false; - } - } - } - - if (!m_dataPtr->episodeFilter.isEmpty()) { -// qDebug() << "Checking episode filter:" << m_dataPtr->episodeFilter; - QRegularExpression f(cachedRegex("(^\\d{1,4})x(.*;$)")); - QRegularExpressionMatch matcher = f.match(m_dataPtr->episodeFilter); - bool matched = matcher.hasMatch(); - - if (!matched) - return false; - - QString s = matcher.captured(1); - QStringList eps = matcher.captured(2).split(";"); - int sOurs = s.toInt(); - - foreach (QString ep, eps) { - if (ep.isEmpty()) - continue; - - // We need to trim leading zeroes, but if it's all zeros then we want episode zero. - while (ep.size() > 1 && ep.startsWith("0")) - ep = ep.right(ep.size() - 1); - - if (ep.indexOf('-') != -1) { // Range detected - QString partialPattern1 = "\\bs0?(\\d{1,4})[ -_\\.]?e(0?\\d{1,4})(?:\\D|\\b)"; - QString partialPattern2 = "\\b(\\d{1,4})x(0?\\d{1,4})(?:\\D|\\b)"; - QRegularExpression reg(cachedRegex(partialPattern1)); - - if (ep.endsWith('-')) { // Infinite range - int epOurs = ep.left(ep.size() - 1).toInt(); - - // Extract partial match from article and compare as digits - matcher = reg.match(articleTitle); - matched = matcher.hasMatch(); - - if (!matched) { - reg = QRegularExpression(cachedRegex(partialPattern2)); - matcher = reg.match(articleTitle); - matched = matcher.hasMatch(); - } - - if (matched) { - int sTheirs = matcher.captured(1).toInt(); - int epTheirs = matcher.captured(2).toInt(); - if (((sTheirs == sOurs) && (epTheirs >= epOurs)) || (sTheirs > sOurs)) { -// qDebug() << "Matched episode:" << ep; -// qDebug() << "Matched article:" << articleTitle; - return true; - } - } - } - else { // Normal range - QStringList range = ep.split('-'); - Q_ASSERT(range.size() == 2); - if (range.first().toInt() > range.last().toInt()) - continue; // Ignore this subrule completely - - int epOursFirst = range.first().toInt(); - int epOursLast = range.last().toInt(); - - // Extract partial match from article and compare as digits - matcher = reg.match(articleTitle); - matched = matcher.hasMatch(); - - if (!matched) { - reg = QRegularExpression(cachedRegex(partialPattern2)); - matcher = reg.match(articleTitle); - matched = matcher.hasMatch(); - } - - if (matched) { - int sTheirs = matcher.captured(1).toInt(); - int epTheirs = matcher.captured(2).toInt(); - if ((sTheirs == sOurs) && ((epOursFirst <= epTheirs) && (epOursLast >= epTheirs))) { -// qDebug() << "Matched episode:" << ep; -// qDebug() << "Matched article:" << articleTitle; - return true; - } - } - } - } - else { // Single number - QString expStr("\\b(?:s0?" + s + "[ -_\\.]?" + "e0?" + ep + "|" + s + "x" + "0?" + ep + ")(?:\\D|\\b)"); - QRegularExpression reg(cachedRegex(expStr)); - if (reg.match(articleTitle).hasMatch()) { -// qDebug() << "Matched episode:" << ep; -// qDebug() << "Matched article:" << articleTitle; - return true; - } - } - } - - return false; - } - -// qDebug() << "Matched article:" << articleTitle; - return true; -} - -AutoDownloadRule &AutoDownloadRule::operator=(const AutoDownloadRule &other) -{ - m_dataPtr = other.m_dataPtr; - return *this; -} - -bool AutoDownloadRule::operator==(const AutoDownloadRule &other) const -{ - return (m_dataPtr == other.m_dataPtr) // optimization - || (*m_dataPtr == *other.m_dataPtr); -} - -bool AutoDownloadRule::operator!=(const AutoDownloadRule &other) const -{ - return !operator==(other); -} - -QJsonObject AutoDownloadRule::toJsonObject() const -{ - return {{Str_Enabled, isEnabled()} - , {Str_UseRegex, useRegex()} - , {Str_MustContain, mustContain()} - , {Str_MustNotContain, mustNotContain()} - , {Str_EpisodeFilter, episodeFilter()} - , {Str_AffectedFeeds, QJsonArray::fromStringList(feedURLs())} - , {Str_SavePath, savePath()} - , {Str_AssignedCategory, assignedCategory()} - , {Str_LastMatch, lastMatch().toString(Qt::RFC2822Date)} - , {Str_IgnoreDays, ignoreDays()} - , {Str_AddPaused, triStateBoolToJsonValue(addPaused())}}; -} - -AutoDownloadRule AutoDownloadRule::fromJsonObject(const QJsonObject &jsonObj, const QString &name) -{ - AutoDownloadRule rule(name.isEmpty() ? jsonObj.value(Str_Name).toString() : name); - - rule.setUseRegex(jsonObj.value(Str_UseRegex).toBool(false)); - rule.setMustContain(jsonObj.value(Str_MustContain).toString()); - rule.setMustNotContain(jsonObj.value(Str_MustNotContain).toString()); - rule.setEpisodeFilter(jsonObj.value(Str_EpisodeFilter).toString()); - rule.setEnabled(jsonObj.value(Str_Enabled).toBool(true)); - rule.setSavePath(jsonObj.value(Str_SavePath).toString()); - rule.setCategory(jsonObj.value(Str_AssignedCategory).toString()); - rule.setAddPaused(jsonValueToTriStateBool(jsonObj.value(Str_AddPaused))); - rule.setLastMatch(QDateTime::fromString(jsonObj.value(Str_LastMatch).toString(), Qt::RFC2822Date)); - rule.setIgnoreDays(jsonObj.value(Str_IgnoreDays).toInt()); - - const QJsonValue feedsVal = jsonObj.value(Str_AffectedFeeds); - QStringList feedURLs; - if (feedsVal.isString()) - feedURLs << feedsVal.toString(); - else foreach (const QJsonValue &urlVal, feedsVal.toArray()) - feedURLs << urlVal.toString(); - rule.setFeedURLs(feedURLs); - - return rule; -} - -AutoDownloadRule AutoDownloadRule::fromVariantHash(const QVariantHash &varHash) -{ - AutoDownloadRule rule(varHash.value("name").toString()); - - rule.setUseRegex(varHash.value("use_regex", false).toBool()); - rule.setMustContain(varHash.value("must_contain").toString()); - rule.setMustNotContain(varHash.value("must_not_contain").toString()); - rule.setEpisodeFilter(varHash.value("episode_filter").toString()); - rule.setFeedURLs(varHash.value("affected_feeds").toStringList()); - rule.setEnabled(varHash.value("enabled", false).toBool()); - rule.setSavePath(varHash.value("save_path").toString()); - rule.setCategory(varHash.value("category_assigned").toString()); - rule.setAddPaused(TriStateBool(varHash.value("add_paused").toInt() - 1)); - rule.setLastMatch(varHash.value("last_match").toDateTime()); - rule.setIgnoreDays(varHash.value("ignore_days").toInt()); - - return rule; -} - -void AutoDownloadRule::setMustContain(const QString &tokens) -{ - m_dataPtr->cachedRegexes.clear(); - - if (m_dataPtr->useRegex) - m_dataPtr->mustContain = QStringList() << tokens; - else - m_dataPtr->mustContain = tokens.split("|"); - - // Check for single empty string - if so, no condition - if ((m_dataPtr->mustContain.size() == 1) && m_dataPtr->mustContain[0].isEmpty()) - m_dataPtr->mustContain.clear(); -} - -void AutoDownloadRule::setMustNotContain(const QString &tokens) -{ - m_dataPtr->cachedRegexes.clear(); - - if (m_dataPtr->useRegex) - m_dataPtr->mustNotContain = QStringList() << tokens; - else - m_dataPtr->mustNotContain = tokens.split("|"); - - // Check for single empty string - if so, no condition - if ((m_dataPtr->mustNotContain.size() == 1) && m_dataPtr->mustNotContain[0].isEmpty()) - m_dataPtr->mustNotContain.clear(); -} - -QStringList AutoDownloadRule::feedURLs() const -{ - return m_dataPtr->feedURLs; -} - -void AutoDownloadRule::setFeedURLs(const QStringList &urls) -{ - m_dataPtr->feedURLs = urls; -} - -QString AutoDownloadRule::name() const -{ - return m_dataPtr->name; -} - -void AutoDownloadRule::setName(const QString &name) -{ - m_dataPtr->name = name; -} - -QString AutoDownloadRule::savePath() const -{ - return m_dataPtr->savePath; -} - -void AutoDownloadRule::setSavePath(const QString &savePath) -{ - m_dataPtr->savePath = Utils::Fs::fromNativePath(savePath); -} - -TriStateBool AutoDownloadRule::addPaused() const -{ - return m_dataPtr->addPaused; -} - -void AutoDownloadRule::setAddPaused(const TriStateBool &addPaused) -{ - m_dataPtr->addPaused = addPaused; -} - -QString AutoDownloadRule::assignedCategory() const -{ - return m_dataPtr->category; -} - -void AutoDownloadRule::setCategory(const QString &category) -{ - m_dataPtr->category = category; -} - -bool AutoDownloadRule::isEnabled() const -{ - return m_dataPtr->enabled; -} - -void AutoDownloadRule::setEnabled(bool enable) -{ - m_dataPtr->enabled = enable; -} - -QDateTime AutoDownloadRule::lastMatch() const -{ - return m_dataPtr->lastMatch; -} - -void AutoDownloadRule::setLastMatch(const QDateTime &lastMatch) -{ - m_dataPtr->lastMatch = lastMatch; -} - -void AutoDownloadRule::setIgnoreDays(int d) -{ - m_dataPtr->ignoreDays = d; -} - -int AutoDownloadRule::ignoreDays() const -{ - return m_dataPtr->ignoreDays; -} - -QString AutoDownloadRule::mustContain() const -{ - return m_dataPtr->mustContain.join("|"); -} - -QString AutoDownloadRule::mustNotContain() const -{ - return m_dataPtr->mustNotContain.join("|"); -} - -bool AutoDownloadRule::useRegex() const -{ - return m_dataPtr->useRegex; -} - -void AutoDownloadRule::setUseRegex(bool enabled) -{ - m_dataPtr->useRegex = enabled; - m_dataPtr->cachedRegexes.clear(); -} - -QString AutoDownloadRule::episodeFilter() const -{ - return m_dataPtr->episodeFilter; -} - -void AutoDownloadRule::setEpisodeFilter(const QString &e) -{ - m_dataPtr->episodeFilter = e; - m_dataPtr->cachedRegexes.clear(); -} diff --git a/src/base/rss/rss_autodownloadrule.h b/src/base/rss/rss_autodownloadrule.h deleted file mode 100644 index 6b79fe3a5..000000000 --- a/src/base/rss/rss_autodownloadrule.h +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2017 Vladimir Golovnev - * Copyright (C) 2010 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. - */ - -#pragma once - -#include -#include -#include - -class QJsonObject; -class QRegularExpression; -class TriStateBool; - -namespace RSS -{ - struct AutoDownloadRuleData; - - class AutoDownloadRule - { - public: - explicit AutoDownloadRule(const QString &name = ""); - AutoDownloadRule(const AutoDownloadRule &other); - ~AutoDownloadRule(); - - QString name() const; - void setName(const QString &name); - - bool isEnabled() const; - void setEnabled(bool enable); - - QString mustContain() const; - void setMustContain(const QString &tokens); - QString mustNotContain() const; - void setMustNotContain(const QString &tokens); - QStringList feedURLs() const; - void setFeedURLs(const QStringList &urls); - int ignoreDays() const; - void setIgnoreDays(int d); - QDateTime lastMatch() const; - void setLastMatch(const QDateTime &lastMatch); - bool useRegex() const; - void setUseRegex(bool enabled); - QString episodeFilter() const; - void setEpisodeFilter(const QString &e); - - QString savePath() const; - void setSavePath(const QString &savePath); - TriStateBool addPaused() const; - void setAddPaused(const TriStateBool &addPaused); - QString assignedCategory() const; - void setCategory(const QString &category); - - bool matches(const QString &articleTitle) const; - - AutoDownloadRule &operator=(const AutoDownloadRule &other); - bool operator==(const AutoDownloadRule &other) const; - bool operator!=(const AutoDownloadRule &other) const; - - QJsonObject toJsonObject() const; - static AutoDownloadRule fromJsonObject(const QJsonObject &jsonObj, const QString &name = ""); - static AutoDownloadRule fromVariantHash(const QVariantHash &varHash); - - private: - bool matches(const QString &articleTitle, const QString &expression) const; - QRegularExpression cachedRegex(const QString &expression, bool isRegex = true) const; - - QSharedDataPointer m_dataPtr; - }; -} diff --git a/src/base/rss/rss_feed.cpp b/src/base/rss/rss_feed.cpp deleted file mode 100644 index 7ceac9cef..000000000 --- a/src/base/rss/rss_feed.cpp +++ /dev/null @@ -1,451 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2015, 2017 Vladimir Golovnev - * Copyright (C) 2010 Christophe Dumez - * Copyright (C) 2010 Arnaud Demaiziere - * - * 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. - */ - -#include "rss_feed.h" - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "../asyncfilestorage.h" -#include "../logger.h" -#include "../net/downloadhandler.h" -#include "../net/downloadmanager.h" -#include "../profile.h" -#include "../utils/fs.h" -#include "private/rss_parser.h" -#include "rss_article.h" -#include "rss_session.h" - -const QString Str_Url(QStringLiteral("url")); -const QString Str_Title(QStringLiteral("title")); -const QString Str_LastBuildDate(QStringLiteral("lastBuildDate")); -const QString Str_IsLoading(QStringLiteral("isLoading")); -const QString Str_HasError(QStringLiteral("hasError")); -const QString Str_Articles(QStringLiteral("articles")); - -using namespace RSS; - -Feed::Feed(const QString &url, const QString &path, Session *session) - : Item(path) - , m_session(session) - , m_url(url) -{ - m_dataFileName = QString("%1.json").arg(Utils::Fs::toValidFileSystemName(m_url, false, QLatin1String("_"))); - - m_parser = new Private::Parser(m_lastBuildDate); - m_parser->moveToThread(m_session->workingThread()); - connect(this, &Feed::destroyed, m_parser, &Private::Parser::deleteLater); - connect(m_parser, &Private::Parser::finished, this, &Feed::handleParsingFinished); - - connect(m_session, &Session::maxArticlesPerFeedChanged, this, &Feed::handleMaxArticlesPerFeedChanged); - - if (m_session->isProcessingEnabled()) - downloadIcon(); - else - connect(m_session, &Session::processingStateChanged, this, &Feed::handleSessionProcessingEnabledChanged); - - load(); -} - -Feed::~Feed() -{ - emit aboutToBeDestroyed(this); - Utils::Fs::forceRemove(m_iconPath); -} - -QList
Feed::articles() const -{ - return m_articlesByDate; -} - -void Feed::markAsRead() -{ - auto oldUnreadCount = m_unreadCount; - foreach (Article *article, m_articles) { - if (!article->isRead()) { - article->disconnect(this); - article->markAsRead(); - --m_unreadCount; - emit articleRead(article); - } - } - - if (m_unreadCount != oldUnreadCount) { - m_dirty = true; - store(); - emit unreadCountChanged(this); - } -} - -void Feed::refresh() -{ - if (isLoading()) return; - - // NOTE: Should we allow manually refreshing for disabled session? - - Net::DownloadHandler *handler = Net::DownloadManager::instance()->downloadUrl(m_url); - connect(handler - , static_cast(&Net::DownloadHandler::downloadFinished) - , this, &Feed::handleDownloadFinished); - connect(handler, &Net::DownloadHandler::downloadFailed, this, &Feed::handleDownloadFailed); - - m_isLoading = true; - emit stateChanged(this); -} - -QString Feed::url() const -{ - return m_url; -} - -QString Feed::title() const -{ - return m_title; -} - -bool Feed::isLoading() const -{ - return m_isLoading; -} - -QString Feed::lastBuildDate() const -{ - return m_lastBuildDate; -} - -int Feed::unreadCount() const -{ - return m_unreadCount; -} - -Article *Feed::articleByGUID(const QString &guid) const -{ - return m_articles.value(guid); -} - -void Feed::handleMaxArticlesPerFeedChanged(int n) -{ - while (m_articlesByDate.size() > n) - removeOldestArticle(); - // We don't need store articles here -} - -void Feed::handleIconDownloadFinished(const QString &url, const QString &filePath) -{ - Q_UNUSED(url); - - m_iconPath = Utils::Fs::fromNativePath(filePath); - emit iconLoaded(this); -} - -bool Feed::hasError() const -{ - return m_hasError; -} - -void Feed::handleDownloadFinished(const QString &url, const QByteArray &data) -{ - qDebug() << "Successfully downloaded RSS feed at" << url; - // Parse the download RSS - m_parser->parse(data); -} - -void Feed::handleDownloadFailed(const QString &url, const QString &error) -{ - m_isLoading = false; - m_hasError = true; - emit stateChanged(this); - qWarning() << "Failed to download RSS feed at" << url; - qWarning() << "Reason:" << error; -} - -void Feed::handleParsingFinished(const RSS::Private::ParsingResult &result) -{ - if (!result.error.isEmpty()) { - qWarning() << "Failed to parse RSS feed at" << m_url; - qWarning() << "Reason:" << result.error; - } - else { - if (title() != result.title) { - m_title = result.title; - emit titleChanged(this); - } - - m_lastBuildDate = result.lastBuildDate; - - foreach (const QVariantHash &varHash, result.articles) { - try { - auto article = new Article(this, varHash); - if (!addArticle(article)) - delete article; - else - m_dirty = true; - } - catch (const std::runtime_error&) {} - } - - store(); - } - - m_isLoading = false; - m_hasError = false; - emit stateChanged(this); -} - -void Feed::load() -{ - QFile file(m_session->dataFileStorage()->storageDir().absoluteFilePath(m_dataFileName)); - - if (!file.exists()) { - loadArticlesLegacy(); - m_dirty = true; - store(); // convert to new format - } - else if (file.open(QFile::ReadOnly)) { - loadArticles(file.readAll()); - file.close(); - } - else { - Logger::instance()->addMessage( - QString("Couldn't read RSS AutoDownloader rules from %1. Error: %2") - .arg(m_dataFileName).arg(file.errorString()), Log::WARNING); - } -} - -void Feed::loadArticles(const QByteArray &data) -{ - QJsonParseError jsonError; - QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &jsonError); - if (jsonError.error != QJsonParseError::NoError) { - Logger::instance()->addMessage( - QString("Couldn't parse RSS Session data. Error: %1") - .arg(jsonError.errorString()), Log::WARNING); - return; - } - - if (!jsonDoc.isArray()) { - Logger::instance()->addMessage( - QString("Couldn't load RSS Session data. Invalid data format."), Log::WARNING); - return; - } - - QJsonArray jsonArr = jsonDoc.array(); - int i = -1; - foreach (const QJsonValue &jsonVal, jsonArr) { - ++i; - if (!jsonVal.isObject()) { - Logger::instance()->addMessage( - QString("Couldn't load RSS article '%1#%2'. Invalid data format.").arg(m_url).arg(i) - , Log::WARNING); - continue; - } - - try { - auto article = new Article(this, jsonVal.toObject()); - if (!addArticle(article)) - delete article; - } - catch (const std::runtime_error&) {} - } -} - -void Feed::loadArticlesLegacy() -{ - SettingsPtr qBTRSSFeeds = Profile::instance().applicationSettings(QStringLiteral("qBittorrent-rss-feeds")); - QVariantHash allOldItems = qBTRSSFeeds->value("old_items").toHash(); - - foreach (const QVariant &var, allOldItems.value(m_url).toList()) { - auto hash = var.toHash(); - // update legacy keys - hash[Article::KeyLink] = hash.take(QLatin1String("news_link")); - hash[Article::KeyTorrentURL] = hash.take(QLatin1String("torrent_url")); - hash[Article::KeyIsRead] = hash.take(QLatin1String("read")); - try { - auto article = new Article(this, hash); - if (!addArticle(article)) - delete article; - } - catch (const std::runtime_error&) {} - } -} - -void Feed::store() -{ - if (!m_dirty) return; - - m_dirty = false; - m_savingTimer.stop(); - - QJsonArray jsonArr; - foreach (Article *article, m_articles) - jsonArr << article->toJsonObject(); - - m_session->dataFileStorage()->store(m_dataFileName, QJsonDocument(jsonArr).toJson()); -} - -void Feed::storeDeferred() -{ - if (!m_savingTimer.isActive()) - m_savingTimer.start(5 * 1000, this); -} - -bool Feed::addArticle(Article *article) -{ - Q_ASSERT(article); - - if (m_articles.contains(article->guid())) - return false; - - // Insertion sort - const int maxArticles = m_session->maxArticlesPerFeed(); - auto lowerBound = std::lower_bound(m_articlesByDate.begin(), m_articlesByDate.end() - , article->date(), Article::articleDateRecentThan); - if ((lowerBound - m_articlesByDate.begin()) >= maxArticles) - return false; // we reach max articles - - m_articles[article->guid()] = article; - m_articlesByDate.insert(lowerBound, article); - if (!article->isRead()) { - increaseUnreadCount(); - connect(article, &Article::read, this, &Feed::handleArticleRead); - } - emit newArticle(article); - - if (m_articlesByDate.size() > maxArticles) - removeOldestArticle(); - - return true; -} - -void Feed::removeOldestArticle() -{ - auto oldestArticle = m_articlesByDate.last(); - emit articleAboutToBeRemoved(oldestArticle); - - m_articles.remove(oldestArticle->guid()); - m_articlesByDate.removeLast(); - bool isRead = oldestArticle->isRead(); - delete oldestArticle; - - if (!isRead) - decreaseUnreadCount(); -} - -void Feed::increaseUnreadCount() -{ - ++m_unreadCount; - emit unreadCountChanged(this); -} - -void Feed::decreaseUnreadCount() -{ - Q_ASSERT(m_unreadCount > 0); - - --m_unreadCount; - emit unreadCountChanged(this); -} - -void Feed::downloadIcon() -{ - // Download the RSS Feed icon - // XXX: This works for most sites but it is not perfect - const QUrl url(m_url); - auto iconUrl = QString("%1://%2/favicon.ico").arg(url.scheme()).arg(url.host()); - Net::DownloadHandler *handler = Net::DownloadManager::instance()->downloadUrl(iconUrl, true); - connect(handler - , static_cast(&Net::DownloadHandler::downloadFinished) - , this, &Feed::handleIconDownloadFinished); -} - -QString Feed::iconPath() const -{ - return m_iconPath; -} - -QJsonValue Feed::toJsonValue(bool withData) const -{ - if (!withData) { - // if feed alias is empty we create "reduced" JSON - // value for it since its name is equal to its URL - return (name() == url() ? "" : url()); - // if we'll need storing some more properties we should check - // for its default values and produce JSON object instead of (if it's required) - } - - QJsonArray jsonArr; - foreach (Article *article, m_articles) - jsonArr << article->toJsonObject(); - - QJsonObject jsonObj; - jsonObj.insert(Str_Url, url()); - jsonObj.insert(Str_Title, title()); - jsonObj.insert(Str_LastBuildDate, lastBuildDate()); - jsonObj.insert(Str_IsLoading, isLoading()); - jsonObj.insert(Str_HasError, hasError()); - jsonObj.insert(Str_Articles, jsonArr); - - return jsonObj; -} - -void Feed::handleSessionProcessingEnabledChanged(bool enabled) -{ - if (enabled) { - downloadIcon(); - disconnect(m_session, &Session::processingStateChanged - , this, &Feed::handleSessionProcessingEnabledChanged); - } -} - -void Feed::handleArticleRead(Article *article) -{ - article->disconnect(this); - decreaseUnreadCount(); - emit articleRead(article); - // will be stored deferred - m_dirty = true; - storeDeferred(); -} - -void Feed::cleanup() -{ - Utils::Fs::forceRemove(m_session->dataFileStorage()->storageDir().absoluteFilePath(m_dataFileName)); -} - -void Feed::timerEvent(QTimerEvent *event) -{ - Q_UNUSED(event); - store(); -} diff --git a/src/base/rss/rss_feed.h b/src/base/rss/rss_feed.h deleted file mode 100644 index 248095d9d..000000000 --- a/src/base/rss/rss_feed.h +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2015, 2017 Vladimir Golovnev - * Copyright (C) 2010 Christophe Dumez - * Copyright (C) 2010 Arnaud Demaiziere - * - * 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. - */ - -#pragma once - -#include -#include -#include - -#include "rss_item.h" - -class AsyncFileStorage; - -namespace RSS -{ - class Article; - class Session; - - namespace Private - { - class Parser; - struct ParsingResult; - } - - class Feed final: public Item - { - Q_OBJECT - Q_DISABLE_COPY(Feed) - - friend class Session; - - Feed(const QString &url, const QString &path, Session *session); - ~Feed() override; - - public: - QList
articles() const override; - int unreadCount() const override; - void markAsRead() override; - void refresh() override; - - QString url() const; - QString title() const; - QString lastBuildDate() const; - bool hasError() const; - bool isLoading() const; - Article *articleByGUID(const QString &guid) const; - QString iconPath() const; - - QJsonValue toJsonValue(bool withData = false) const override; - - signals: - void iconLoaded(Feed *feed = nullptr); - void titleChanged(Feed *feed = nullptr); - void stateChanged(Feed *feed = nullptr); - - private slots: - void handleSessionProcessingEnabledChanged(bool enabled); - void handleMaxArticlesPerFeedChanged(int n); - void handleIconDownloadFinished(const QString &url, const QString &filePath); - void handleDownloadFinished(const QString &url, const QByteArray &data); - void handleDownloadFailed(const QString &url, const QString &error); - void handleParsingFinished(const Private::ParsingResult &result); - void handleArticleRead(Article *article); - - private: - void timerEvent(QTimerEvent *event) override; - void cleanup() override; - void load(); - void loadArticles(const QByteArray &data); - void loadArticlesLegacy(); - void store(); - void storeDeferred(); - bool addArticle(Article *article); - void removeOldestArticle(); - void increaseUnreadCount(); - void decreaseUnreadCount(); - void downloadIcon(); - - Session *m_session; - Private::Parser *m_parser; - const QString m_url; - QString m_title; - QString m_lastBuildDate; - bool m_hasError = false; - bool m_isLoading = false; - QHash m_articles; - QList
m_articlesByDate; - int m_unreadCount = 0; - QString m_iconPath; - QString m_dataFileName; - QBasicTimer m_savingTimer; - bool m_dirty = false; - }; -} diff --git a/src/base/rss/rss_folder.cpp b/src/base/rss/rss_folder.cpp deleted file mode 100644 index 2d05f3573..000000000 --- a/src/base/rss/rss_folder.cpp +++ /dev/null @@ -1,143 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2017 Vladimir Golovnev - * Copyright (C) 2010 Christophe Dumez - * Copyright (C) 2010 Arnaud Demaiziere - * - * 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. - */ - -#include "rss_folder.h" - -#include -#include - -#include "rss_article.h" - -using namespace RSS; - -Folder::Folder(const QString &path) - : Item(path) -{ -} - -Folder::~Folder() -{ - emit aboutToBeDestroyed(this); - - foreach (auto item, items()) - delete item; -} - -QList
Folder::articles() const -{ - QList
news; - - foreach (Item *item, items()) { - int n = news.size(); - news << item->articles(); - std::inplace_merge(news.begin(), news.begin() + n, news.end() - , [](Article *a1, Article *a2) - { - return Article::articleDateRecentThan(a1, a2->date()); - }); - } - return news; -} - -int Folder::unreadCount() const -{ - int count = 0; - foreach (Item *item, items()) - count += item->unreadCount(); - return count; -} - -void Folder::markAsRead() -{ - foreach (Item *item, items()) - item->markAsRead(); -} - -void Folder::refresh() -{ - foreach (Item *item, items()) - item->refresh(); -} - -QList Folder::items() const -{ - return m_items; -} - -QJsonValue Folder::toJsonValue(bool withData) const -{ - QJsonObject jsonObj; - foreach (Item *item, items()) - jsonObj.insert(item->name(), item->toJsonValue(withData)); - - return jsonObj; -} - -void Folder::handleItemUnreadCountChanged() -{ - emit unreadCountChanged(this); -} - -void Folder::cleanup() -{ - foreach (Item *item, items()) - item->cleanup(); -} - -void Folder::addItem(Item *item) -{ - Q_ASSERT(item); - Q_ASSERT(!m_items.contains(item)); - - m_items.append(item); - connect(item, &Item::newArticle, this, &Item::newArticle); - connect(item, &Item::articleRead, this, &Item::articleRead); - connect(item, &Item::articleAboutToBeRemoved, this, &Item::articleAboutToBeRemoved); - connect(item, &Item::unreadCountChanged, this, &Folder::handleItemUnreadCountChanged); - - for (auto article: item->articles()) - emit newArticle(article); - - if (item->unreadCount() > 0) - emit unreadCountChanged(this); -} - -void Folder::removeItem(Item *item) -{ - Q_ASSERT(m_items.contains(item)); - - for (auto article: item->articles()) - emit articleAboutToBeRemoved(article); - - item->disconnect(this); - m_items.removeOne(item); - if (item->unreadCount() > 0) - emit unreadCountChanged(this); -} diff --git a/src/base/rss/rss_folder.h b/src/base/rss/rss_folder.h deleted file mode 100644 index 6317f4ea5..000000000 --- a/src/base/rss/rss_folder.h +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2017 Vladimir Golovnev - * Copyright (C) 2010 Christophe Dumez - * Copyright (C) 2010 Arnaud Demaiziere - * - * 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. - */ - -#pragma once - -#include -#include "rss_item.h" - -namespace RSS -{ - class Session; - - class Folder final: public Item - { - Q_OBJECT - Q_DISABLE_COPY(Folder) - - friend class Session; - - explicit Folder(const QString &path = ""); - ~Folder() override; - - public: - QList
articles() const override; - int unreadCount() const override; - void markAsRead() override; - void refresh() override; - - QList items() const; - - QJsonValue toJsonValue(bool withData = false) const override; - - private slots: - void handleItemUnreadCountChanged(); - - private: - void cleanup() override; - void addItem(Item *item); - void removeItem(Item *item); - - QList m_items; - }; -} diff --git a/src/base/rss/rss_item.cpp b/src/base/rss/rss_item.cpp deleted file mode 100644 index 7c0917438..000000000 --- a/src/base/rss/rss_item.cpp +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2017 Vladimir Golovnev - * Copyright (C) 2010 Christophe Dumez - * Copyright (C) 2010 Arnaud Demaiziere - * - * 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. - */ - -#include "rss_item.h" - -#include -#include -#include - -using namespace RSS; - -const QString Item::PathSeparator("\\"); - -Item::Item(const QString &path) - : m_path(path) -{ -} - -Item::~Item() {} - -void Item::setPath(const QString &path) -{ - if (path != m_path) { - m_path = path; - emit pathChanged(this); - } -} - -QString Item::path() const -{ - return m_path; -} - -QString Item::name() const -{ - return relativeName(path()); -} - -bool Item::isValidPath(const QString &path) -{ - static const QRegularExpression re( - QString(R"(\A[^\%1]+(\%1[^\%1]+)*\z)").arg(Item::PathSeparator) - , QRegularExpression::DontCaptureOption | QRegularExpression::OptimizeOnFirstUsageOption); - - if (path.isEmpty() || !re.match(path).hasMatch()) { - qDebug() << "Incorrect RSS Item path:" << path; - return false; - } - - return true; -} - -QString Item::joinPath(const QString &path1, const QString &path2) -{ - if (path1.isEmpty()) - return path2; - else - return path1 + Item::PathSeparator + path2; -} - -QStringList Item::expandPath(const QString &path) -{ - QStringList result; - if (path.isEmpty()) return result; - // if (!isValidRSSFolderName(folder)) - // return result; - - int index = 0; - while ((index = path.indexOf(Item::PathSeparator, index)) >= 0) { - result << path.left(index); - ++index; - } - result << path; - - return result; -} - -QString Item::parentPath(const QString &path) -{ - int pos; - return ((pos = path.lastIndexOf(Item::PathSeparator)) >= 0 ? path.left(pos) : ""); -} - -QString Item::relativeName(const QString &path) -{ - int pos; - return ((pos = path.lastIndexOf(Item::PathSeparator)) >= 0 ? path.right(path.size() - (pos + 1)) : path); -} diff --git a/src/base/rss/rss_item.h b/src/base/rss/rss_item.h deleted file mode 100644 index 9ba1db692..000000000 --- a/src/base/rss/rss_item.h +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2017 Vladimir Golovnev - * Copyright (C) 2010 Christophe Dumez - * Copyright (C) 2010 Arnaud Demaiziere - * - * 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. - */ - -#pragma once - -#include -#include - -namespace RSS -{ - class Article; - class Folder; - class Session; - - class Item: public QObject - { - Q_OBJECT - Q_DISABLE_COPY(Item) - - friend class Folder; - friend class Session; - - public: - virtual QList
articles() const = 0; - virtual int unreadCount() const = 0; - virtual void markAsRead() = 0; - virtual void refresh() = 0; - - QString path() const; - QString name() const; - - virtual QJsonValue toJsonValue(bool withData = false) const = 0; - - static const QString PathSeparator; - - static bool isValidPath(const QString &path); - static QString joinPath(const QString &path1, const QString &path2); - static QStringList expandPath(const QString &path); - static QString parentPath(const QString &path); - static QString relativeName(const QString &path); - - signals: - void pathChanged(Item *item = nullptr); - void unreadCountChanged(Item *item = nullptr); - void aboutToBeDestroyed(Item *item = nullptr); - void newArticle(Article *article); - void articleRead(Article *article); - void articleAboutToBeRemoved(Article *article); - - protected: - explicit Item(const QString &path); - ~Item() override; - - virtual void cleanup() = 0; - - private: - void setPath(const QString &path); - - QString m_path; - }; -} diff --git a/src/base/rss/rss_session.cpp b/src/base/rss/rss_session.cpp deleted file mode 100644 index d9a1329da..000000000 --- a/src/base/rss/rss_session.cpp +++ /dev/null @@ -1,485 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2017 Vladimir Golovnev - * Copyright (C) 2010 Christophe Dumez - * Copyright (C) 2010 Arnaud Demaiziere - * - * 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. - */ - -#include "rss_session.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "../asyncfilestorage.h" -#include "../logger.h" -#include "../profile.h" -#include "../settingsstorage.h" -#include "../utils/fs.h" -#include "rss_article.h" -#include "rss_feed.h" -#include "rss_item.h" -#include "rss_folder.h" - -const int MsecsPerMin = 60000; -const QString ConfFolderName(QStringLiteral("rss")); -const QString DataFolderName(QStringLiteral("rss/articles")); -const QString FeedsFileName(QStringLiteral("feeds.json")); - -const QString SettingsKey_ProcessingEnabled(QStringLiteral("RSS/Session/EnableProcessing")); -const QString SettingsKey_RefreshInterval(QStringLiteral("RSS/Session/RefreshInterval")); -const QString SettingsKey_MaxArticlesPerFeed(QStringLiteral("RSS/Session/MaxArticlesPerFeed")); - -using namespace RSS; - -QPointer Session::m_instance = nullptr; - -Session::Session() - : m_processingEnabled(SettingsStorage::instance()->loadValue(SettingsKey_ProcessingEnabled, false).toBool()) - , m_workingThread(new QThread(this)) - , m_refreshInterval(SettingsStorage::instance()->loadValue(SettingsKey_RefreshInterval, 30).toUInt()) - , m_maxArticlesPerFeed(SettingsStorage::instance()->loadValue(SettingsKey_MaxArticlesPerFeed, 50).toInt()) -{ - Q_ASSERT(!m_instance); // only one instance is allowed - m_instance = this; - - m_confFileStorage = new AsyncFileStorage( - Utils::Fs::expandPathAbs(specialFolderLocation(SpecialFolder::Config) + ConfFolderName)); - m_confFileStorage->moveToThread(m_workingThread); - connect(m_workingThread, &QThread::finished, m_confFileStorage, &AsyncFileStorage::deleteLater); - connect(m_confFileStorage, &AsyncFileStorage::failed, [](const QString &fileName, const QString &errorString) - { - Logger::instance()->addMessage(QString("Couldn't save RSS Session configuration in %1. Error: %2") - .arg(fileName).arg(errorString), Log::WARNING); - }); - - m_dataFileStorage = new AsyncFileStorage( - Utils::Fs::expandPathAbs(specialFolderLocation(SpecialFolder::Data) + DataFolderName)); - m_dataFileStorage->moveToThread(m_workingThread); - connect(m_workingThread, &QThread::finished, m_dataFileStorage, &AsyncFileStorage::deleteLater); - connect(m_dataFileStorage, &AsyncFileStorage::failed, [](const QString &fileName, const QString &errorString) - { - Logger::instance()->addMessage(QString("Couldn't save RSS Session data in %1. Error: %2") - .arg(fileName).arg(errorString), Log::WARNING); - }); - - m_itemsByPath.insert("", new Folder); // root folder - - m_workingThread->start(); - load(); - - connect(&m_refreshTimer, &QTimer::timeout, this, &Session::refresh); - if (m_processingEnabled) { - m_refreshTimer.start(m_refreshInterval * MsecsPerMin); - refresh(); - } -} - -Session::~Session() -{ - qDebug() << "Deleting RSS Session..."; - - m_workingThread->quit(); - m_workingThread->wait(); - - //store(); - delete m_itemsByPath[""]; // deleting root folder - - qDebug() << "RSS Session deleted."; -} - -Session *Session::instance() -{ - return m_instance; -} - -bool Session::addFolder(const QString &path, QString *error) -{ - Folder *destFolder = prepareItemDest(path, error); - if (!destFolder) - return false; - - addItem(new Folder(path), destFolder); - store(); - return true; -} - -bool Session::addFeed(const QString &url, const QString &path, QString *error) -{ - if (m_feedsByURL.contains(url)) { - if (error) - *error = tr("RSS feed with given URL already exists: %1.").arg(url); - return false; - } - - Folder *destFolder = prepareItemDest(path, error); - if (!destFolder) - return false; - - addItem(new Feed(url, path, this), destFolder); - store(); - if (m_processingEnabled) - feedByURL(url)->refresh(); - return true; -} - -bool Session::moveItem(const QString &itemPath, const QString &destPath, QString *error) -{ - if (itemPath.isEmpty()) { - if (error) - *error = tr("Cannot move root folder."); - return false; - } - - auto item = m_itemsByPath.value(itemPath); - if (!item) { - if (error) - *error = tr("Item doesn't exists: %1.").arg(itemPath); - return false; - } - - return moveItem(item, destPath, error); -} - -bool Session::moveItem(Item *item, const QString &destPath, QString *error) -{ - Q_ASSERT(item); - Q_ASSERT(item != rootFolder()); - - Folder *destFolder = prepareItemDest(destPath, error); - if (!destFolder) - return false; - - auto srcFolder = static_cast(m_itemsByPath.value(Item::parentPath(item->path()))); - if (srcFolder != destFolder) { - srcFolder->removeItem(item); - destFolder->addItem(item); - } - m_itemsByPath.insert(destPath, m_itemsByPath.take(item->path())); - item->setPath(destPath); - store(); - return true; -} - -bool Session::removeItem(const QString &itemPath, QString *error) -{ - if (itemPath.isEmpty()) { - if (error) - *error = tr("Cannot delete root folder."); - return false; - } - - auto item = m_itemsByPath.value(itemPath); - if (!item) { - if (error) - *error = tr("Item doesn't exists: %1.").arg(itemPath); - return false; - } - - emit itemAboutToBeRemoved(item); - item->cleanup(); - - auto folder = static_cast(m_itemsByPath.value(Item::parentPath(item->path()))); - folder->removeItem(item); - delete item; - store(); - return true; -} - -QList Session::items() const -{ - return m_itemsByPath.values(); -} - -Item *Session::itemByPath(const QString &path) const -{ - return m_itemsByPath.value(path); -} - -void Session::load() -{ - QFile itemsFile(m_confFileStorage->storageDir().absoluteFilePath(FeedsFileName)); - if (!itemsFile.exists()) { - loadLegacy(); - return; - } - - if (!itemsFile.open(QFile::ReadOnly)) { - Logger::instance()->addMessage( - QString("Couldn't read RSS Session data from %1. Error: %2") - .arg(itemsFile.fileName()).arg(itemsFile.errorString()), Log::WARNING); - return; - } - - QJsonParseError jsonError; - QJsonDocument jsonDoc = QJsonDocument::fromJson(itemsFile.readAll(), &jsonError); - if (jsonError.error != QJsonParseError::NoError) { - Logger::instance()->addMessage( - QString("Couldn't parse RSS Session data from %1. Error: %2") - .arg(itemsFile.fileName()).arg(jsonError.errorString()), Log::WARNING); - return; - } - - if (!jsonDoc.isObject()) { - Logger::instance()->addMessage( - QString("Couldn't load RSS Session data from %1. Invalid data format.") - .arg(itemsFile.fileName()), Log::WARNING); - return; - } - - loadFolder(jsonDoc.object(), rootFolder()); -} - -void Session::loadFolder(const QJsonObject &jsonObj, Folder *folder) -{ - foreach (const QString &key, jsonObj.keys()) { - QJsonValue val = jsonObj[key]; - if (val.isString()) { - QString url = val.toString(); - if (url.isEmpty()) - url = key; - addFeedToFolder(url, key, folder); - } - else if (!val.isObject()) { - Logger::instance()->addMessage( - QString("Couldn't load RSS Item '%1'. Invalid data format.") - .arg(QString("%1\\%2").arg(folder->path()).arg(key)), Log::WARNING); - } - else { - QJsonObject valObj = val.toObject(); - if (valObj.contains("url")) { - if (!valObj["url"].isString()) { - Logger::instance()->addMessage( - QString("Couldn't load RSS Feed '%1'. URL is required.") - .arg(QString("%1\\%2").arg(folder->path()).arg(key)), Log::WARNING); - continue; - } - - addFeedToFolder(valObj["url"].toString(), key, folder); - } - else { - loadFolder(valObj, addSubfolder(key, folder)); - } - } - } -} - -void Session::loadLegacy() -{ - const QStringList legacyFeedPaths = SettingsStorage::instance()->loadValue("Rss/streamList").toStringList(); - const QStringList feedAliases = SettingsStorage::instance()->loadValue("Rss/streamAlias").toStringList(); - if (legacyFeedPaths.size() != feedAliases.size()) { - Logger::instance()->addMessage("Corrupted RSS list, not loading it.", Log::WARNING); - return; - } - - uint i = 0; - foreach (QString legacyPath, legacyFeedPaths) { - if (Item::PathSeparator == QString(legacyPath[0])) - legacyPath.remove(0, 1); - const QString parentFolderPath = Item::parentPath(legacyPath); - const QString feedUrl = Item::relativeName(legacyPath); - - foreach (const QString &folderPath, Item::expandPath(parentFolderPath)) - addFolder(folderPath); - - const QString feedPath = feedAliases[i].isEmpty() - ? legacyPath - : Item::joinPath(parentFolderPath, feedAliases[i]); - addFeed(feedUrl, feedPath); - ++i; - } - - store(); // convert to new format -} - -void Session::store() -{ - m_confFileStorage->store(FeedsFileName, QJsonDocument(rootFolder()->toJsonValue().toObject()).toJson()); -} - -Folder *Session::prepareItemDest(const QString &path, QString *error) -{ - if (!Item::isValidPath(path)) { - if (error) - *error = tr("Incorrect RSS Item path: %1.").arg(path); - return nullptr; - } - - if (m_itemsByPath.contains(path)) { - if (error) - *error = tr("RSS item with given path already exists: %1.").arg(path); - return nullptr; - } - - const QString destFolderPath = Item::parentPath(path); - auto destFolder = qobject_cast(m_itemsByPath.value(destFolderPath)); - if (!destFolder) { - if (error) - *error = tr("Parent folder doesn't exist: %1.").arg(destFolderPath); - return nullptr; - } - - return destFolder; -} - -Folder *Session::addSubfolder(const QString &name, Folder *parentFolder) -{ - auto folder = new Folder(Item::joinPath(parentFolder->path(), name)); - addItem(folder, parentFolder); - return folder; -} - -Feed *Session::addFeedToFolder(const QString &url, const QString &name, Folder *parentFolder) -{ - auto feed = new Feed(url, Item::joinPath(parentFolder->path(), name), this); - addItem(feed, parentFolder); - return feed; -} - -void Session::addItem(Item *item, Folder *destFolder) -{ - if (auto feed = qobject_cast(item)) { - connect(feed, &Feed::titleChanged, this, &Session::handleFeedTitleChanged); - connect(feed, &Feed::iconLoaded, this, &Session::feedIconLoaded); - connect(feed, &Feed::stateChanged, this, &Session::feedStateChanged); - m_feedsByURL[feed->url()] = feed; - } - - connect(item, &Item::pathChanged, this, &Session::itemPathChanged); - connect(item, &Item::aboutToBeDestroyed, this, &Session::handleItemAboutToBeDestroyed); - m_itemsByPath[item->path()] = item; - destFolder->addItem(item); - emit itemAdded(item); -} - -bool Session::isProcessingEnabled() const -{ - return m_processingEnabled; -} - -void Session::setProcessingEnabled(bool enabled) -{ - if (m_processingEnabled != enabled) { - m_processingEnabled = enabled; - SettingsStorage::instance()->storeValue(SettingsKey_ProcessingEnabled, m_processingEnabled); - if (m_processingEnabled) { - m_refreshTimer.start(m_refreshInterval * MsecsPerMin); - refresh(); - } - else { - m_refreshTimer.stop(); - } - - emit processingStateChanged(m_processingEnabled); - } -} - -AsyncFileStorage *Session::confFileStorage() const -{ - return m_confFileStorage; -} - -AsyncFileStorage *Session::dataFileStorage() const -{ - return m_dataFileStorage; -} - -Folder *Session::rootFolder() const -{ - return static_cast(m_itemsByPath.value("")); -} - -QList Session::feeds() const -{ - return m_feedsByURL.values(); -} - -Feed *Session::feedByURL(const QString &url) const -{ - return m_feedsByURL.value(url); -} - -uint Session::refreshInterval() const -{ - return m_refreshInterval; -} - -void Session::setRefreshInterval(uint refreshInterval) -{ - if (m_refreshInterval != refreshInterval) { - SettingsStorage::instance()->storeValue(SettingsKey_RefreshInterval, refreshInterval); - m_refreshInterval = refreshInterval; - m_refreshTimer.start(m_refreshInterval * MsecsPerMin); - } -} - -QThread *Session::workingThread() const -{ - return m_workingThread; -} - -void Session::handleItemAboutToBeDestroyed(Item *item) -{ - m_itemsByPath.remove(item->path()); - auto feed = qobject_cast(item); - if (feed) - m_feedsByURL.remove(feed->url()); -} - -void Session::handleFeedTitleChanged(Feed *feed) -{ - if (feed->name() == feed->url()) - // Now we have something better than a URL. - // Trying to rename feed... - moveItem(feed, Item::joinPath(Item::parentPath(feed->path()), feed->title())); -} - -int Session::maxArticlesPerFeed() const -{ - return m_maxArticlesPerFeed; -} - -void Session::setMaxArticlesPerFeed(int n) -{ - if (m_maxArticlesPerFeed != n) { - m_maxArticlesPerFeed = n; - SettingsStorage::instance()->storeValue(SettingsKey_MaxArticlesPerFeed, n); - emit maxArticlesPerFeedChanged(n); - } -} - -void Session::refresh() -{ - // NOTE: Should we allow manually refreshing for disabled session? - rootFolder()->refresh(); -} diff --git a/src/base/rss/rss_session.h b/src/base/rss/rss_session.h deleted file mode 100644 index 648e167bf..000000000 --- a/src/base/rss/rss_session.h +++ /dev/null @@ -1,154 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2017 Vladimir Golovnev - * Copyright (C) 2010 Christophe Dumez - * Copyright (C) 2010 Arnaud Demaiziere - * - * 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. - */ - -#pragma once - -/* - * RSS Session configuration file format (JSON): - * - * =============== BEGIN =============== - * { - * "folder1": { - * "subfolder1": { - * "Feed name (Alias)": "http://some-feed-url1", - * "http://some-feed-url2": "" - * }, - * "subfolder2": {}, - * "http://some-feed-url3": "", - * "Feed name (Alias)": { - * "url": "http://some-feed-url4", - * } - * }, - * "folder2": {}, - * "folder3": {} - * } - * ================ END ================ - * - * 1. Document is JSON object (the same as Folder) - * 2. Folder is JSON object (keys are Item names, values are Items) - * 3.1. Feed is JSON object (keys are property names, values are property values; 'url' is required) - * 3.2. (Reduced format) Feed is JSON string (string is URL unless it's empty, otherwise we take Feed URL from name) - */ - -#include -#include -#include -#include -#include - -class QThread; -class Application; -class AsyncFileStorage; - -namespace RSS -{ - class Item; - class Feed; - class Folder; - - class Session: public QObject - { - Q_OBJECT - Q_DISABLE_COPY(Session) - - friend class ::Application; - - Session(); - ~Session() override; - - public: - static Session *instance(); - - bool isProcessingEnabled() const; - void setProcessingEnabled(bool enabled); - - QThread *workingThread() const; - AsyncFileStorage *confFileStorage() const; - AsyncFileStorage *dataFileStorage() const; - - int maxArticlesPerFeed() const; - void setMaxArticlesPerFeed(int n); - - uint refreshInterval() const; - void setRefreshInterval(uint refreshInterval); - - bool addFolder(const QString &path, QString *error = nullptr); - bool addFeed(const QString &url, const QString &path, QString *error = nullptr); - bool moveItem(const QString &itemPath, const QString &destPath - , QString *error = nullptr); - bool moveItem(Item *item, const QString &destPath, QString *error = nullptr); - bool removeItem(const QString &itemPath, QString *error = nullptr); - - QList items() const; - Item *itemByPath(const QString &path) const; - QList feeds() const; - Feed *feedByURL(const QString &url) const; - - Folder *rootFolder() const; - - public slots: - void refresh(); - - signals: - void processingStateChanged(bool enabled); - void maxArticlesPerFeedChanged(int n); - void itemAdded(Item *item); - void itemPathChanged(Item *item); - void itemAboutToBeRemoved(Item *item); - void feedIconLoaded(Feed *feed); - void feedStateChanged(Feed *feed); - - private slots: - void handleItemAboutToBeDestroyed(Item *item); - void handleFeedTitleChanged(Feed *feed); - - private: - void load(); - void loadFolder(const QJsonObject &jsonObj, Folder *folder); - void loadLegacy(); - void store(); - Folder *prepareItemDest(const QString &path, QString *error); - Folder *addSubfolder(const QString &name, Folder *parentFolder); - Feed *addFeedToFolder(const QString &url, const QString &name, Folder *parentFolder); - void addItem(Item *item, Folder *destFolder); - - static QPointer m_instance; - - bool m_processingEnabled; - QThread *m_workingThread; - AsyncFileStorage *m_confFileStorage; - AsyncFileStorage *m_dataFileStorage; - QTimer m_refreshTimer; - uint m_refreshInterval; - int m_maxArticlesPerFeed; - QHash m_itemsByPath; - QHash m_feedsByURL; - }; -} diff --git a/src/base/scanfoldersmodel.cpp b/src/base/scanfoldersmodel.cpp deleted file mode 100644 index ea1bc6335..000000000 --- a/src/base/scanfoldersmodel.cpp +++ /dev/null @@ -1,404 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2010 Christian Kandeler, 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 "scanfoldersmodel.h" - -#include -#include -#include -#include - -#include "bittorrent/session.h" -#include "filesystemwatcher.h" -#include "preferences.h" -#include "utils/fs.h" - -struct ScanFoldersModel::PathData -{ - PathData(const QString &watchPath, const PathType &type, const QString &downloadPath) - : watchPath(watchPath) - , downloadType(type) - , downloadPath(downloadPath) - { - if (this->downloadPath.isEmpty() && downloadType == CUSTOM_LOCATION) - downloadType = DEFAULT_LOCATION; - } - - QString watchPath; - PathType downloadType; - QString downloadPath; // valid for CUSTOM_LOCATION -}; - -ScanFoldersModel *ScanFoldersModel::m_instance = 0; - -bool ScanFoldersModel::initInstance(QObject *parent) -{ - if (!m_instance) { - m_instance = new ScanFoldersModel(parent); - return true; - } - - return false; -} - -void ScanFoldersModel::freeInstance() -{ - if (m_instance) { - delete m_instance; - m_instance = 0; - } -} - -ScanFoldersModel *ScanFoldersModel::instance() -{ - return m_instance; -} - -ScanFoldersModel::ScanFoldersModel(QObject *parent) - : QAbstractListModel(parent) - , m_fsWatcher(0) -{ - configure(); - connect(Preferences::instance(), SIGNAL(changed()), SLOT(configure())); -} - -ScanFoldersModel::~ScanFoldersModel() -{ - qDeleteAll(m_pathList); -} - -int ScanFoldersModel::rowCount(const QModelIndex &parent) const -{ - return parent.isValid() ? 0 : m_pathList.count(); -} - -int ScanFoldersModel::columnCount(const QModelIndex &parent) const -{ - Q_UNUSED(parent); - return NB_COLUMNS; -} - -QVariant ScanFoldersModel::data(const QModelIndex &index, int role) const -{ - if (!index.isValid() || (index.row() >= rowCount())) - return QVariant(); - - const PathData *pathData = m_pathList.at(index.row()); - QVariant value; - - switch (index.column()) { - case WATCH: - if (role == Qt::DisplayRole) - value = Utils::Fs::toNativePath(pathData->watchPath); - break; - case DOWNLOAD: - if (role == Qt::UserRole) { - value = pathData->downloadType; - } - else if (role == Qt::DisplayRole) { - switch (pathData->downloadType) { - case DOWNLOAD_IN_WATCH_FOLDER: - case DEFAULT_LOCATION: - value = pathTypeDisplayName(pathData->downloadType); - break; - case CUSTOM_LOCATION: - value = pathData->downloadPath; - break; - } - } - break; - } - - return value; -} - -QVariant ScanFoldersModel::headerData(int section, Qt::Orientation orientation, int role) const -{ - if ((orientation != Qt::Horizontal) || (role != Qt::DisplayRole) || (section < 0) || (section >= columnCount())) - return QVariant(); - - QVariant title; - - switch (section) { - case WATCH: - title = tr("Monitored Folder"); - break; - case DOWNLOAD: - title = tr("Override Save Location"); - break; - } - - return title; -} - -Qt::ItemFlags ScanFoldersModel::flags(const QModelIndex &index) const -{ - if (!index.isValid() || (index.row() >= rowCount())) - return QAbstractListModel::flags(index); - - Qt::ItemFlags flags; - - switch (index.column()) { - case WATCH: - flags = QAbstractListModel::flags(index); - break; - case DOWNLOAD: - flags = QAbstractListModel::flags(index) | Qt::ItemIsEditable; - break; - } - - return flags; -} - -bool ScanFoldersModel::setData(const QModelIndex &index, const QVariant &value, int role) -{ - if (!index.isValid() || (index.row() >= rowCount()) || (index.column() >= columnCount()) - || (index.column() != DOWNLOAD)) - return false; - - if (role == Qt::UserRole) { - PathType type = static_cast(value.toInt()); - if (type == CUSTOM_LOCATION) - return false; - - m_pathList[index.row()]->downloadType = type; - m_pathList[index.row()]->downloadPath.clear(); - emit dataChanged(index, index); - } - else if (role == Qt::DisplayRole) { - QString path = value.toString(); - if (path.isEmpty()) // means we didn't pass CUSTOM_LOCATION type - return false; - - m_pathList[index.row()]->downloadType = CUSTOM_LOCATION; - m_pathList[index.row()]->downloadPath = Utils::Fs::toNativePath(path); - emit dataChanged(index, index); - } - else { - return false; - } - - return true; -} - -ScanFoldersModel::PathStatus ScanFoldersModel::addPath(const QString &watchPath, const PathType &downloadType, const QString &downloadPath, bool addToFSWatcher) -{ - QDir watchDir(watchPath); - if (!watchDir.exists()) return DoesNotExist; - if (!watchDir.isReadable()) return CannotRead; - - const QString &canonicalWatchPath = watchDir.canonicalPath(); - if (findPathData(canonicalWatchPath) != -1) return AlreadyInList; - - QDir downloadDir(downloadPath); - const QString &canonicalDownloadPath = downloadDir.canonicalPath(); - - if (!m_fsWatcher) { - m_fsWatcher = new FileSystemWatcher(this); - connect(m_fsWatcher, SIGNAL(torrentsAdded(const QStringList &)), this, SLOT(addTorrentsToSession(const QStringList &))); - } - - beginInsertRows(QModelIndex(), rowCount(), rowCount()); - m_pathList << new PathData(Utils::Fs::toNativePath(canonicalWatchPath), downloadType, Utils::Fs::toNativePath(canonicalDownloadPath)); - endInsertRows(); - - // Start scanning - if (addToFSWatcher) - m_fsWatcher->addPath(canonicalWatchPath); - return Ok; -} - -ScanFoldersModel::PathStatus ScanFoldersModel::updatePath(const QString &watchPath, const PathType& downloadType, const QString &downloadPath) -{ - QDir watchDir(watchPath); - const QString &canonicalWatchPath = watchDir.canonicalPath(); - int row = findPathData(canonicalWatchPath); - if (row == -1) return DoesNotExist; - - QDir downloadDir(downloadPath); - const QString &canonicalDownloadPath = downloadDir.canonicalPath(); - - m_pathList.at(row)->downloadType = downloadType; - m_pathList.at(row)->downloadPath = Utils::Fs::toNativePath(canonicalDownloadPath); - - return Ok; -} - -void ScanFoldersModel::addToFSWatcher(const QStringList &watchPaths) -{ - if (!m_fsWatcher) - return; // addPath() wasn't called before this - - foreach (const QString &path, watchPaths) { - QDir watchDir(path); - const QString &canonicalWatchPath = watchDir.canonicalPath(); - m_fsWatcher->addPath(canonicalWatchPath); - } -} - -void ScanFoldersModel::removePath(int row, bool removeFromFSWatcher) -{ - Q_ASSERT((row >= 0) && (row < rowCount())); - beginRemoveRows(QModelIndex(), row, row); - if (removeFromFSWatcher) - m_fsWatcher->removePath(m_pathList.at(row)->watchPath); - delete m_pathList.takeAt(row); - endRemoveRows(); -} - -bool ScanFoldersModel::removePath(const QString &path, bool removeFromFSWatcher) -{ - const int row = findPathData(path); - if (row == -1) return false; - - removePath(row, removeFromFSWatcher); - return true; -} - -void ScanFoldersModel::removeFromFSWatcher(const QStringList &watchPaths) -{ - foreach (const QString &path, watchPaths) - m_fsWatcher->removePath(path); -} - -bool ScanFoldersModel::downloadInWatchFolder(const QString &filePath) const -{ - const int row = findPathData(QFileInfo(filePath).dir().path()); - Q_ASSERT(row != -1); - PathData *data = m_pathList.at(row); - return (data->downloadType == DOWNLOAD_IN_WATCH_FOLDER); -} - -bool ScanFoldersModel::downloadInDefaultFolder(const QString &filePath) const -{ - const int row = findPathData(QFileInfo(filePath).dir().path()); - Q_ASSERT(row != -1); - PathData *data = m_pathList.at(row); - return (data->downloadType == DEFAULT_LOCATION); -} - -QString ScanFoldersModel::downloadPathTorrentFolder(const QString &filePath) const -{ - const int row = findPathData(QFileInfo(filePath).dir().path()); - Q_ASSERT(row != -1); - PathData *data = m_pathList.at(row); - if (data->downloadType == CUSTOM_LOCATION) - return data->downloadPath; - - return QString(); -} - -int ScanFoldersModel::findPathData(const QString &path) const -{ - for (int i = 0; i < m_pathList.count(); ++i) - if (m_pathList.at(i)->watchPath == Utils::Fs::toNativePath(path)) - return i; - - return -1; -} - -void ScanFoldersModel::makePersistent() -{ - QVariantHash dirs; - - foreach (const PathData *pathData, m_pathList) { - if (pathData->downloadType == CUSTOM_LOCATION) - dirs.insert(Utils::Fs::fromNativePath(pathData->watchPath), Utils::Fs::fromNativePath(pathData->downloadPath)); - else - dirs.insert(Utils::Fs::fromNativePath(pathData->watchPath), pathData->downloadType); - } - - Preferences::instance()->setScanDirs(dirs); -} - -void ScanFoldersModel::configure() -{ - QVariantHash dirs = Preferences::instance()->getScanDirs(); - - for (QVariantHash::const_iterator i = dirs.begin(), e = dirs.end(); i != e; ++i) { - if (i.value().type() == QVariant::Int) - addPath(i.key(), static_cast(i.value().toInt()), QString()); - else - addPath(i.key(), CUSTOM_LOCATION, i.value().toString()); - } -} - -void ScanFoldersModel::addTorrentsToSession(const QStringList &pathList) -{ - foreach (const QString &file, pathList) { - qDebug("File %s added", qPrintable(file)); - - BitTorrent::AddTorrentParams params; - if (downloadInWatchFolder(file)) - params.savePath = QFileInfo(file).dir().path(); - else if (!downloadInDefaultFolder(file)) - params.savePath = downloadPathTorrentFolder(file); - - if (file.endsWith(".magnet")) { - QFile f(file); - if (f.open(QIODevice::ReadOnly | QIODevice::Text)) { - QTextStream str(&f); - while (!str.atEnd()) - BitTorrent::Session::instance()->addTorrent(str.readLine(), params); - - f.close(); - Utils::Fs::forceRemove(file); - } - else { - qDebug("Failed to open magnet file: %s", qPrintable(f.errorString())); - } - } - else { - BitTorrent::TorrentInfo torrentInfo = BitTorrent::TorrentInfo::loadFromFile(file); - if (torrentInfo.isValid()) { - BitTorrent::Session::instance()->addTorrent(torrentInfo, params); - Utils::Fs::forceRemove(file); - } - else { - qDebug("Ignoring incomplete torrent file: %s", qPrintable(file)); - } - } - } -} - -QString ScanFoldersModel::pathTypeDisplayName(const PathType type) -{ - switch(type) { - case DOWNLOAD_IN_WATCH_FOLDER: - return tr("Monitored folder"); - case DEFAULT_LOCATION: - return tr("Default save location"); - case CUSTOM_LOCATION: - return tr("Browse..."); - default: - qDebug("Invalid PathType: %d", type); - }; - return QString(); -} diff --git a/src/base/scanfoldersmodel.h b/src/base/scanfoldersmodel.h deleted file mode 100644 index 41fd3a288..000000000 --- a/src/base/scanfoldersmodel.h +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2010 Christian Kandeler, 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 SCANFOLDERSMODEL_H -#define SCANFOLDERSMODEL_H - -#include -#include - -class QStringList; -class FileSystemWatcher; - -class ScanFoldersModel: public QAbstractListModel -{ - Q_OBJECT - Q_DISABLE_COPY(ScanFoldersModel) - -public: - enum PathStatus - { - Ok, - DoesNotExist, - CannotRead, - CannotWrite, - AlreadyInList - }; - - enum Column - { - WATCH, - DOWNLOAD, - NB_COLUMNS - }; - - enum PathType - { - DOWNLOAD_IN_WATCH_FOLDER, - DEFAULT_LOCATION, - CUSTOM_LOCATION - }; - - static bool initInstance(QObject *parent = 0); - static void freeInstance(); - static ScanFoldersModel* instance(); - - static QString pathTypeDisplayName(const PathType type); - - int rowCount(const QModelIndex &parent = QModelIndex()) const; - int columnCount(const QModelIndex &parent = QModelIndex()) const; - QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; - QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; - Qt::ItemFlags flags(const QModelIndex &index) const; - - // TODO: removePaths(); singular version becomes private helper functions; - // also: remove functions should take modelindexes - PathStatus addPath(const QString &watchPath, const PathType &downloadType, const QString &downloadPath, bool addToFSWatcher = true); - PathStatus updatePath(const QString &watchPath, const PathType &downloadType, const QString &downloadPath); - // PRECONDITION: The paths must have been added with addPath() first. - void addToFSWatcher(const QStringList &watchPaths); - void removePath(int row, bool removeFromFSWatcher = true); - bool removePath(const QString &path, bool removeFromFSWatcher = true); - void removeFromFSWatcher(const QStringList &watchPaths); - - void makePersistent(); - -public slots: - void configure(); - -private slots: - void addTorrentsToSession(const QStringList &pathList); - -private: - explicit ScanFoldersModel(QObject *parent = 0); - ~ScanFoldersModel(); - - virtual bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole); - bool downloadInWatchFolder(const QString &filePath) const; - bool downloadInDefaultFolder(const QString &filePath) const; - QString downloadPathTorrentFolder(const QString &filePath) const; - int findPathData(const QString &path) const; - -private: - static ScanFoldersModel *m_instance; - struct PathData; - - QList m_pathList; - FileSystemWatcher *m_fsWatcher; -}; - -#endif // SCANFOLDERSMODEL_H diff --git a/src/base/searchengine.cpp b/src/base/searchengine.cpp deleted file mode 100644 index cfb83d206..000000000 --- a/src/base/searchengine.cpp +++ /dev/null @@ -1,683 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2015 Vladimir Golovnev - * Copyright (C) 2006 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. - */ - -#include -#include -#include -#include -#include -#include - -#include "base/utils/fs.h" -#include "base/utils/misc.h" -#include "base/preferences.h" -#include "base/profile.h" -#include "base/net/downloadmanager.h" -#include "base/net/downloadhandler.h" -#include "searchengine.h" - -enum SearchResultColumn -{ - PL_DL_LINK, - PL_NAME, - PL_SIZE, - PL_SEEDS, - PL_LEECHS, - PL_ENGINE_URL, - PL_DESC_LINK, - NB_PLUGIN_COLUMNS -}; - -static inline void removePythonScriptIfExists(const QString &scriptPath) -{ - Utils::Fs::forceRemove(scriptPath); - Utils::Fs::forceRemove(scriptPath + "c"); -} - -const QHash SearchEngine::m_categoryNames = SearchEngine::initializeCategoryNames(); - -SearchEngine::SearchEngine() - : m_updateUrl(QString("http://searchplugins.qbittorrent.org/%1/engines/").arg(Utils::Misc::pythonVersion() >= 3 ? "nova3" : "nova")) - , m_searchStopped(false) -{ - updateNova(); - - m_searchProcess = new QProcess(this); - m_searchProcess->setEnvironment(QProcess::systemEnvironment()); - connect(m_searchProcess, &QProcess::started, this, &SearchEngine::searchStarted); - connect(m_searchProcess, &QProcess::readyReadStandardOutput, this, &SearchEngine::readSearchOutput); - connect(m_searchProcess, static_cast(&QProcess::finished), this, &SearchEngine::processFinished); - - m_searchTimeout = new QTimer(this); - m_searchTimeout->setSingleShot(true); - connect(m_searchTimeout, &QTimer::timeout, this, &SearchEngine::onTimeout); - - update(); -} - -SearchEngine::~SearchEngine() -{ - qDeleteAll(m_plugins.values()); - cancelSearch(); -} - -QStringList SearchEngine::allPlugins() const -{ - return m_plugins.keys(); -} - -QStringList SearchEngine::enabledPlugins() const -{ - QStringList plugins; - foreach (const PluginInfo *plugin, m_plugins.values()) { - if (plugin->enabled) - plugins << plugin->name; - } - - return plugins; -} - -QStringList SearchEngine::supportedCategories() const -{ - QStringList result; - foreach (const PluginInfo *plugin, m_plugins.values()) { - if (plugin->enabled) { - foreach (QString cat, plugin->supportedCategories) { - if (!result.contains(cat)) - result << cat; - } - } - } - - return result; -} - -PluginInfo *SearchEngine::pluginInfo(const QString &name) const -{ - return m_plugins.value(name, 0); -} - -bool SearchEngine::isActive() const -{ - return (m_searchProcess->state() != QProcess::NotRunning); -} - -void SearchEngine::enablePlugin(const QString &name, bool enabled) -{ - PluginInfo *plugin = m_plugins.value(name, 0); - if (plugin) { - plugin->enabled = enabled; - // Save to Hard disk - Preferences *const pref = Preferences::instance(); - QStringList disabledPlugins = pref->getSearchEngDisabled(); - if (enabled) - disabledPlugins.removeAll(name); - else if (!disabledPlugins.contains(name)) - disabledPlugins.append(name); - pref->setSearchEngDisabled(disabledPlugins); - - emit pluginEnabled(name, enabled); - } -} - -// Updates shipped plugin -void SearchEngine::updatePlugin(const QString &name) -{ - installPlugin(QString("%1%2.py").arg(m_updateUrl).arg(name)); -} - -// Install or update plugin from file or url -void SearchEngine::installPlugin(const QString &source) -{ - qDebug("Asked to install plugin at %s", qPrintable(source)); - - if (Utils::Misc::isUrl(source)) { - using namespace Net; - DownloadHandler *handler = DownloadManager::instance()->downloadUrl(source, true); - connect(handler, static_cast(&DownloadHandler::downloadFinished) - , this, &SearchEngine::pluginDownloaded); - connect(handler, &DownloadHandler::downloadFailed, this, &SearchEngine::pluginDownloadFailed); - } - else { - QString path = source; - if (path.startsWith("file:", Qt::CaseInsensitive)) - path = QUrl(path).toLocalFile(); - - QString pluginName = Utils::Fs::fileName(path); - pluginName.chop(pluginName.size() - pluginName.lastIndexOf(".")); - - if (!path.endsWith(".py", Qt::CaseInsensitive)) - emit pluginInstallationFailed(pluginName, tr("Unknown search engine plugin file format.")); - else - installPlugin_impl(pluginName, path); - } -} - -void SearchEngine::installPlugin_impl(const QString &name, const QString &path) -{ - PluginVersion newVersion = getPluginVersion(path); - qDebug() << "Version to be installed:" << newVersion; - - PluginInfo *plugin = pluginInfo(name); - if (plugin && !(plugin->version < newVersion)) { - qDebug("Apparently update is not needed, we have a more recent version"); - emit pluginUpdateFailed(name, tr("A more recent version of this plugin is already installed.")); - return; - } - - // Process with install - QString destPath = pluginPath(name); - bool updated = false; - if (QFile::exists(destPath)) { - // Backup in case install fails - QFile::copy(destPath, destPath + ".bak"); - Utils::Fs::forceRemove(destPath); - Utils::Fs::forceRemove(destPath + "c"); - updated = true; - } - // Copy the plugin - QFile::copy(path, destPath); - // Update supported plugins - update(); - // Check if this was correctly installed - if (!m_plugins.contains(name)) { - // Remove broken file - Utils::Fs::forceRemove(destPath); - if (updated) { - // restore backup - QFile::copy(destPath + ".bak", destPath); - Utils::Fs::forceRemove(destPath + ".bak"); - // Update supported plugins - update(); - emit pluginUpdateFailed(name, tr("Plugin is not supported.")); - } - else { - emit pluginInstallationFailed(name, tr("Plugin is not supported.")); - } - } - else { - // Install was successful, remove backup - if (updated) - Utils::Fs::forceRemove(destPath + ".bak"); - } -} - -bool SearchEngine::uninstallPlugin(const QString &name) -{ - // remove it from hard drive - QDir pluginsFolder(pluginsLocation()); - QStringList filters; - filters << name + ".*"; - QStringList files = pluginsFolder.entryList(filters, QDir::Files, QDir::Unsorted); - QString file; - foreach (file, files) - Utils::Fs::forceRemove(pluginsFolder.absoluteFilePath(file)); - // Remove it from supported engines - delete m_plugins.take(name); - - emit pluginUninstalled(name); - return true; -} - -void SearchEngine::updateIconPath(PluginInfo * const plugin) -{ - if (!plugin) return; - QString iconPath = QString("%1/%2.png").arg(pluginsLocation()).arg(plugin->name); - if (QFile::exists(iconPath)) { - plugin->iconPath = iconPath; - } - else { - iconPath = QString("%1/%2.ico").arg(pluginsLocation()).arg(plugin->name); - if (QFile::exists(iconPath)) - plugin->iconPath = iconPath; - } -} - -void SearchEngine::checkForUpdates() -{ - // Download version file from update server - using namespace Net; - DownloadHandler *handler = DownloadManager::instance()->downloadUrl(m_updateUrl + "versions.txt"); - connect(handler, static_cast(&DownloadHandler::downloadFinished) - , this, &SearchEngine::versionInfoDownloaded); - connect(handler, &DownloadHandler::downloadFailed, this, &SearchEngine::versionInfoDownloadFailed); -} - -void SearchEngine::cancelSearch() -{ - if (m_searchProcess->state() != QProcess::NotRunning) { -#ifdef Q_OS_WIN - m_searchProcess->kill(); -#else - m_searchProcess->terminate(); -#endif - m_searchStopped = true; - m_searchTimeout->stop(); - - m_searchProcess->waitForFinished(1000); - } -} - -void SearchEngine::downloadTorrent(const QString &siteUrl, const QString &url) -{ - QProcess *downloadProcess = new QProcess(this); - downloadProcess->setEnvironment(QProcess::systemEnvironment()); - connect(downloadProcess, static_cast(&QProcess::finished), this, &SearchEngine::torrentFileDownloadFinished); - m_downloaders << downloadProcess; - QStringList params { - Utils::Fs::toNativePath(engineLocation() + "/nova2dl.py"), - siteUrl, - url - }; - // Launch search - downloadProcess->start(Utils::Misc::pythonExecutable(), params, QIODevice::ReadOnly); -} - -void SearchEngine::startSearch(const QString &pattern, const QString &category, const QStringList &usedPlugins) -{ - // Search process already running or - // No search pattern entered - if ((m_searchProcess->state() != QProcess::NotRunning) || pattern.isEmpty()) { - emit searchFailed(); - return; - } - - // Reload environment variables (proxy) - m_searchProcess->setEnvironment(QProcess::systemEnvironment()); - - QStringList params; - m_searchStopped = false; - params << Utils::Fs::toNativePath(engineLocation() + "/nova2.py"); - params << usedPlugins.join(","); - params << category; - params << pattern.split(" "); - - // Launch search - m_searchProcess->start(Utils::Misc::pythonExecutable(), params, QIODevice::ReadOnly); - m_searchTimeout->start(180000); // 3min -} - -QString SearchEngine::categoryFullName(const QString &categoryName) -{ - return tr(m_categoryNames.value(categoryName).toUtf8().constData()); -} - -QString SearchEngine::pluginFullName(const QString &pluginName) -{ - return pluginInfo(pluginName) ? pluginInfo(pluginName)->fullName : QString(); -} - -QString SearchEngine::pluginsLocation() -{ - return QString("%1/engines").arg(engineLocation()); -} - -QString SearchEngine::engineLocation() -{ - QString folder = "nova"; - if (Utils::Misc::pythonVersion() >= 3) - folder = "nova3"; - const QString location = Utils::Fs::expandPathAbs(specialFolderLocation(SpecialFolder::Data) + folder); - QDir locationDir(location); - if (!locationDir.exists()) - locationDir.mkpath(locationDir.absolutePath()); - return location; -} - -// Slot called when QProcess is Finished -// QProcess can be finished for 3 reasons : -// Error | Stopped by user | Finished normally -void SearchEngine::processFinished(int exitcode) -{ - m_searchTimeout->stop(); - - if (exitcode == 0) - emit searchFinished(m_searchStopped); - else - emit searchFailed(); -} - -void SearchEngine::versionInfoDownloaded(const QString &url, const QByteArray &data) -{ - Q_UNUSED(url) - parseVersionInfo(data); -} - -void SearchEngine::versionInfoDownloadFailed(const QString &url, const QString &reason) -{ - Q_UNUSED(url) - emit checkForUpdatesFailed(tr("Update server is temporarily unavailable. %1").arg(reason)); -} - -void SearchEngine::pluginDownloaded(const QString &url, QString filePath) -{ - filePath = Utils::Fs::fromNativePath(filePath); - - QString pluginName = Utils::Fs::fileName(url); - pluginName.chop(pluginName.size() - pluginName.lastIndexOf(".")); // Remove extension - installPlugin_impl(pluginName, filePath); - Utils::Fs::forceRemove(filePath); -} - -void SearchEngine::pluginDownloadFailed(const QString &url, const QString &reason) -{ - QString pluginName = url.split('/').last(); - pluginName.replace(".py", "", Qt::CaseInsensitive); - if (pluginInfo(pluginName)) - emit pluginUpdateFailed(pluginName, tr("Failed to download the plugin file. %1").arg(reason)); - else - emit pluginInstallationFailed(pluginName, tr("Failed to download the plugin file. %1").arg(reason)); -} - -void SearchEngine::torrentFileDownloadFinished(int exitcode) -{ - QProcess *downloadProcess = static_cast(sender()); - if (exitcode == 0) { - QString line = QString::fromUtf8(downloadProcess->readAllStandardOutput()).trimmed(); - QStringList parts = line.split(' '); - if (parts.size() == 2) - emit torrentFileDownloaded(parts[0]); - } - - qDebug() << "Deleting downloadProcess"; - m_downloaders.removeOne(downloadProcess); - downloadProcess->deleteLater(); -} - -// Update nova.py search plugin if necessary -void SearchEngine::updateNova() -{ - qDebug("Updating nova"); - - // create nova directory if necessary - QDir searchDir(engineLocation()); - QString novaFolder = Utils::Misc::pythonVersion() >= 3 ? "searchengine/nova3" : "searchengine/nova"; - QFile packageFile(searchDir.absoluteFilePath("__init__.py")); - packageFile.open(QIODevice::WriteOnly | QIODevice::Text); - packageFile.close(); - if (!searchDir.exists("engines")) - searchDir.mkdir("engines"); - Utils::Fs::removeDirRecursive(searchDir.absoluteFilePath("__pycache__")); - - QFile packageFile2(searchDir.absolutePath() + "/engines/__init__.py"); - packageFile2.open(QIODevice::WriteOnly | QIODevice::Text); - packageFile2.close(); - - // Copy search plugin files (if necessary) - QString filePath = searchDir.absoluteFilePath("nova2.py"); - if (getPluginVersion(":/" + novaFolder + "/nova2.py") > getPluginVersion(filePath)) { - removePythonScriptIfExists(filePath); - QFile::copy(":/" + novaFolder + "/nova2.py", filePath); - } - - filePath = searchDir.absoluteFilePath("nova2dl.py"); - if (getPluginVersion(":/" + novaFolder + "/nova2dl.py") > getPluginVersion(filePath)) { - removePythonScriptIfExists(filePath); - QFile::copy(":/" + novaFolder + "/nova2dl.py", filePath); - } - - filePath = searchDir.absoluteFilePath("fix_encoding.py"); - QFile::copy(":/" + novaFolder + "/fix_encoding.py", filePath); - - filePath = searchDir.absoluteFilePath("novaprinter.py"); - if (getPluginVersion(":/" + novaFolder + "/novaprinter.py") > getPluginVersion(filePath)) { - removePythonScriptIfExists(filePath); - QFile::copy(":/" + novaFolder + "/novaprinter.py", filePath); - } - - filePath = searchDir.absoluteFilePath("helpers.py"); - if (getPluginVersion(":/" + novaFolder + "/helpers.py") > getPluginVersion(filePath)) { - removePythonScriptIfExists(filePath); - QFile::copy(":/" + novaFolder + "/helpers.py", filePath); - } - - filePath = searchDir.absoluteFilePath("socks.py"); - removePythonScriptIfExists(filePath); - QFile::copy(":/" + novaFolder + "/socks.py", filePath); - - if (novaFolder.endsWith("nova")) { - filePath = searchDir.absoluteFilePath("fix_encoding.py"); - removePythonScriptIfExists(filePath); - QFile::copy(":/" + novaFolder + "/fix_encoding.py", filePath); - } - else if (novaFolder.endsWith("nova3")) { - filePath = searchDir.absoluteFilePath("sgmllib3.py"); - removePythonScriptIfExists(filePath); - QFile::copy(":/" + novaFolder + "/sgmllib3.py", filePath); - } - - QDir destDir(pluginsLocation()); - Utils::Fs::removeDirRecursive(destDir.absoluteFilePath("__pycache__")); -} - -void SearchEngine::onTimeout() -{ - cancelSearch(); -} - -// search QProcess return output as soon as it gets new -// stuff to read. We split it into lines and parse each -// line to SearchResult calling parseSearchResult(). -void SearchEngine::readSearchOutput() -{ - QByteArray output = m_searchProcess->readAllStandardOutput(); - output.replace("\r", ""); - QList lines = output.split('\n'); - if (!m_searchResultLineTruncated.isEmpty()) - lines.prepend(m_searchResultLineTruncated + lines.takeFirst()); - m_searchResultLineTruncated = lines.takeLast().trimmed(); - - QList searchResultList; - foreach (const QByteArray &line, lines) { - SearchResult searchResult; - if (parseSearchResult(QString::fromUtf8(line), searchResult)) - searchResultList << searchResult; - } - - if (!searchResultList.isEmpty()) - emit newSearchResults(searchResultList); -} - -void SearchEngine::update() -{ - QProcess nova; - nova.setEnvironment(QProcess::systemEnvironment()); - QStringList params; - params << Utils::Fs::toNativePath(engineLocation() + "/nova2.py"); - params << "--capabilities"; - nova.start(Utils::Misc::pythonExecutable(), params, QIODevice::ReadOnly); - nova.waitForStarted(); - nova.waitForFinished(); - - QString capabilities = QString(nova.readAll()); - QDomDocument xmlDoc; - if (!xmlDoc.setContent(capabilities)) { - qWarning() << "Could not parse Nova search engine capabilities, msg: " << capabilities.toLocal8Bit().data(); - qWarning() << "Error: " << nova.readAllStandardError().constData(); - return; - } - - QDomElement root = xmlDoc.documentElement(); - if (root.tagName() != "capabilities") { - qWarning() << "Invalid XML file for Nova search engine capabilities, msg: " << capabilities.toLocal8Bit().data(); - return; - } - - for (QDomNode engineNode = root.firstChild(); !engineNode.isNull(); engineNode = engineNode.nextSibling()) { - QDomElement engineElem = engineNode.toElement(); - if (!engineElem.isNull()) { - QString pluginName = engineElem.tagName(); - - PluginInfo *plugin = new PluginInfo; - plugin->name = pluginName; - plugin->version = getPluginVersion(pluginPath(pluginName)); - plugin->fullName = engineElem.elementsByTagName("name").at(0).toElement().text(); - plugin->url = engineElem.elementsByTagName("url").at(0).toElement().text(); - - foreach (QString cat, engineElem.elementsByTagName("categories").at(0).toElement().text().split(" ")) { - cat = cat.trimmed(); - if (!cat.isEmpty()) - plugin->supportedCategories << cat; - } - - QStringList disabledEngines = Preferences::instance()->getSearchEngDisabled(); - plugin->enabled = !disabledEngines.contains(pluginName); - - updateIconPath(plugin); - - if (!m_plugins.contains(pluginName)) { - m_plugins[pluginName] = plugin; - emit pluginInstalled(pluginName); - } - else if (m_plugins[pluginName]->version != plugin->version) { - delete m_plugins.take(pluginName); - m_plugins[pluginName] = plugin; - emit pluginUpdated(pluginName); - } - } - } -} - -// Parse one line of search results list -// Line is in the following form: -// file url | file name | file size | nb seeds | nb leechers | Search engine url -bool SearchEngine::parseSearchResult(const QString &line, SearchResult &searchResult) -{ - const QStringList parts = line.split("|"); - const int nbFields = parts.size(); - if (nbFields < (NB_PLUGIN_COLUMNS - 1)) return false; // -1 because desc_link is optional - - searchResult = SearchResult(); - searchResult.fileUrl = parts.at(PL_DL_LINK).trimmed(); // download URL - searchResult.fileName = parts.at(PL_NAME).trimmed(); // Name - searchResult.fileSize = parts.at(PL_SIZE).trimmed().toLongLong(); // Size - bool ok = false; - searchResult.nbSeeders = parts.at(PL_SEEDS).trimmed().toLongLong(&ok); // Seeders - if (!ok || (searchResult.nbSeeders < 0)) - searchResult.nbSeeders = -1; - searchResult.nbLeechers = parts.at(PL_LEECHS).trimmed().toLongLong(&ok); // Leechers - if (!ok || (searchResult.nbLeechers < 0)) - searchResult.nbLeechers = -1; - searchResult.siteUrl = parts.at(PL_ENGINE_URL).trimmed(); // Search site URL - if (nbFields == NB_PLUGIN_COLUMNS) - searchResult.descrLink = parts.at(PL_DESC_LINK).trimmed(); // Description Link - - return true; -} - -void SearchEngine::parseVersionInfo(const QByteArray &info) -{ - qDebug("Checking if update is needed"); - - QHash updateInfo; - bool dataCorrect = false; - QList lines = info.split('\n'); - foreach (QByteArray line, lines) { - line = line.trimmed(); - if (line.isEmpty()) continue; - if (line.startsWith("#")) continue; - - QList list = line.split(' '); - if (list.size() != 2) continue; - - QString pluginName = QString(list.first()); - if (!pluginName.endsWith(":")) continue; - - pluginName.chop(1); // remove trailing ':' - PluginVersion version = PluginVersion::tryParse(list.last(), {}); - if (version == PluginVersion()) continue; - - dataCorrect = true; - if (isUpdateNeeded(pluginName, version)) { - qDebug("Plugin: %s is outdated", qPrintable(pluginName)); - updateInfo[pluginName] = version; - } - } - - if (!dataCorrect) - emit checkForUpdatesFailed(tr("An incorrect update info received.")); - else - emit checkForUpdatesFinished(updateInfo); -} - -bool SearchEngine::isUpdateNeeded(QString pluginName, PluginVersion newVersion) const -{ - PluginInfo *plugin = pluginInfo(pluginName); - if (!plugin) return true; - - PluginVersion oldVersion = plugin->version; - qDebug() << "IsUpdate needed? to be installed:" << newVersion << ", already installed:" << oldVersion; - return (newVersion > oldVersion); -} - -QString SearchEngine::pluginPath(const QString &name) -{ - return QString("%1/%2.py").arg(pluginsLocation()).arg(name); -} - -QHash SearchEngine::initializeCategoryNames() -{ - QHash result; - - result["all"] = QT_TRANSLATE_NOOP("SearchEngine", "All categories"); - result["movies"] = QT_TRANSLATE_NOOP("SearchEngine", "Movies"); - result["tv"] = QT_TRANSLATE_NOOP("SearchEngine", "TV shows"); - result["music"] = QT_TRANSLATE_NOOP("SearchEngine", "Music"); - result["games"] = QT_TRANSLATE_NOOP("SearchEngine", "Games"); - result["anime"] = QT_TRANSLATE_NOOP("SearchEngine", "Anime"); - result["software"] = QT_TRANSLATE_NOOP("SearchEngine", "Software"); - result["pictures"] = QT_TRANSLATE_NOOP("SearchEngine", "Pictures"); - result["books"] = QT_TRANSLATE_NOOP("SearchEngine", "Books"); - - return result; -} - -PluginVersion SearchEngine::getPluginVersion(QString filePath) -{ - QFile plugin(filePath); - if (!plugin.exists()) { - qDebug("%s plugin does not exist, returning 0.0", qPrintable(filePath)); - return {}; - } - - if (!plugin.open(QIODevice::ReadOnly | QIODevice::Text)) - return {}; - - PluginVersion version; - while (!plugin.atEnd()) { - QByteArray line = plugin.readLine(); - if (line.startsWith("#VERSION: ")) { - line = line.split(' ').last().trimmed(); - version = PluginVersion::tryParse(line, {}); - qDebug() << "plugin" << filePath << "version: " << version; - break; - } - } - return version; -} diff --git a/src/base/searchengine.h b/src/base/searchengine.h deleted file mode 100644 index 191b5f1f5..000000000 --- a/src/base/searchengine.h +++ /dev/null @@ -1,152 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2015 Vladimir Golovnev - * Copyright (C) 2006 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. - */ - -#ifndef SEARCHENGINE_H -#define SEARCHENGINE_H - -#include -#include -#include -#include - -#include "base/utils/version.h" - -class QProcess; -class QTimer; - -using PluginVersion = Utils::Version; -Q_DECLARE_METATYPE(PluginVersion) - -struct PluginInfo -{ - QString name; - PluginVersion version; - QString fullName; - QString url; - QStringList supportedCategories; - QString iconPath; - bool enabled; -}; - -struct SearchResult -{ - QString fileName; - QString fileUrl; - qlonglong fileSize; - qlonglong nbSeeders; - qlonglong nbLeechers; - QString siteUrl; - QString descrLink; -}; - -class SearchEngine: public QObject -{ - Q_OBJECT - -public: - SearchEngine(); - ~SearchEngine(); - - QStringList allPlugins() const; - QStringList enabledPlugins() const; - QStringList supportedCategories() const; - PluginInfo *pluginInfo(const QString &name) const; - - bool isActive() const; - - void enablePlugin(const QString &name, bool enabled = true); - void updatePlugin(const QString &name); - void installPlugin(const QString &source); - bool uninstallPlugin(const QString &name); - static void updateIconPath(PluginInfo * const plugin); - void checkForUpdates(); - - void startSearch(const QString &pattern, const QString &category, const QStringList &usedPlugins); - void cancelSearch(); - - void downloadTorrent(const QString &siteUrl, const QString &url); - - static PluginVersion getPluginVersion(QString filePath); - static QString categoryFullName(const QString &categoryName); - QString pluginFullName(const QString &pluginName); - static QString pluginsLocation(); - -signals: - void searchStarted(); - void searchFinished(bool cancelled); - void searchFailed(); - void newSearchResults(const QList &results); - - void pluginEnabled(const QString &name, bool enabled); - void pluginInstalled(const QString &name); - void pluginInstallationFailed(const QString &name, const QString &reason); - void pluginUninstalled(const QString &name); - void pluginUpdated(const QString &name); - void pluginUpdateFailed(const QString &name, const QString &reason); - - void checkForUpdatesFinished(const QHash &updateInfo); - void checkForUpdatesFailed(const QString &reason); - - void torrentFileDownloaded(const QString &path); - -private slots: - void onTimeout(); - void readSearchOutput(); - void processFinished(int exitcode); - void versionInfoDownloaded(const QString &url, const QByteArray &data); - void versionInfoDownloadFailed(const QString &url, const QString &reason); - void pluginDownloaded(const QString &url, QString filePath); - void pluginDownloadFailed(const QString &url, const QString &reason); - void torrentFileDownloadFinished(int exitcode); - -private: - void update(); - void updateNova(); - bool parseSearchResult(const QString &line, SearchResult &searchResult); - void parseVersionInfo(const QByteArray &info); - void installPlugin_impl(const QString &name, const QString &path); - bool isUpdateNeeded(QString pluginName, PluginVersion newVersion) const; - - static QString engineLocation(); - static QString pluginPath(const QString &name); - static QHash initializeCategoryNames(); - - static const QHash m_categoryNames; - - const QString m_updateUrl; - - QHash m_plugins; - QProcess *m_searchProcess; - bool m_searchStopped; - QTimer *m_searchTimeout; - QByteArray m_searchResultLineTruncated; - QList m_downloaders; -}; - -#endif // SEARCHENGINE_H diff --git a/src/base/settingsstorage.cpp b/src/base/settingsstorage.cpp deleted file mode 100644 index e7323c2ef..000000000 --- a/src/base/settingsstorage.cpp +++ /dev/null @@ -1,313 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2016 Vladimir Golovnev - * Copyright (C) 2014 sledgehammer999 - * - * 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. - */ - -#include "settingsstorage.h" - -#include -#include -#include -#include - -#include "logger.h" -#include "profile.h" -#include "utils/fs.h" - -namespace -{ - // Encapsulates serialization of settings in "atomic" way. - // write() does not leave half-written files, - // read() has a workaround for a case of power loss during a previous serialization - class TransactionalSettings - { - public: - TransactionalSettings(const QString &name) - : m_name(name) - { - } - - QVariantHash read(); - bool write(const QVariantHash &data); - - private: - // we return actual file names used by QSettings because - // there is no other way to get that name except - // actually create a QSettings object. - // if serialization operation was not successful we return empty string - QString deserialize(const QString &name, QVariantHash &data); - QString serialize(const QString &name, const QVariantHash &data); - - QString m_name; - }; - - typedef QHash MappingTable; - - QString mapKey(const QString &key) - { - static const MappingTable keyMapping = { - - {"BitTorrent/Session/MaxRatioAction", "Preferences/Bittorrent/MaxRatioAction"}, - {"BitTorrent/Session/DefaultSavePath", "Preferences/Downloads/SavePath"}, - {"BitTorrent/Session/TempPath", "Preferences/Downloads/TempPath"}, - {"BitTorrent/Session/TempPathEnabled", "Preferences/Downloads/TempPathEnabled"}, - {"BitTorrent/Session/AddTorrentPaused", "Preferences/Downloads/StartInPause"}, - {"BitTorrent/Session/RefreshInterval", "Preferences/General/RefreshInterval"}, - {"BitTorrent/Session/Preallocation", "Preferences/Downloads/PreAllocation"}, - {"BitTorrent/Session/AddExtensionToIncompleteFiles", "Preferences/Downloads/UseIncompleteExtension"}, - {"BitTorrent/Session/TorrentExportDirectory", "Preferences/Downloads/TorrentExportDir"}, - {"BitTorrent/Session/FinishedTorrentExportDirectory", "Preferences/Downloads/FinishedTorrentExportDir"}, - {"BitTorrent/Session/GlobalUPSpeedLimit", "Preferences/Connection/GlobalUPLimit"}, - {"BitTorrent/Session/GlobalDLSpeedLimit", "Preferences/Connection/GlobalDLLimit"}, - {"BitTorrent/Session/AlternativeGlobalUPSpeedLimit", "Preferences/Connection/GlobalUPLimitAlt"}, - {"BitTorrent/Session/AlternativeGlobalDLSpeedLimit", "Preferences/Connection/GlobalDLLimitAlt"}, - {"BitTorrent/Session/UseAlternativeGlobalSpeedLimit", "Preferences/Connection/alt_speeds_on"}, - {"BitTorrent/Session/BandwidthSchedulerEnabled", "Preferences/Scheduler/Enabled"}, - {"BitTorrent/Session/Port", "Preferences/Connection/PortRangeMin"}, - {"BitTorrent/Session/UseRandomPort", "Preferences/General/UseRandomPort"}, - {"BitTorrent/Session/IPv6Enabled", "Preferences/Connection/InterfaceListenIPv6"}, - {"BitTorrent/Session/Interface", "Preferences/Connection/Interface"}, - {"BitTorrent/Session/InterfaceName", "Preferences/Connection/InterfaceName"}, - {"BitTorrent/Session/InterfaceAddress", "Preferences/Connection/InterfaceAddress"}, - {"BitTorrent/Session/SaveResumeDataInterval", "Preferences/Downloads/SaveResumeDataInterval"}, - {"BitTorrent/Session/Encryption", "Preferences/Bittorrent/Encryption"}, - {"BitTorrent/Session/ForceProxy", "Preferences/Connection/ProxyForce"}, - {"BitTorrent/Session/ProxyPeerConnections", "Preferences/Connection/ProxyPeerConnections"}, - {"BitTorrent/Session/MaxConnections", "Preferences/Bittorrent/MaxConnecs"}, - {"BitTorrent/Session/MaxUploads", "Preferences/Bittorrent/MaxUploads"}, - {"BitTorrent/Session/MaxConnectionsPerTorrent", "Preferences/Bittorrent/MaxConnecsPerTorrent"}, - {"BitTorrent/Session/MaxUploadsPerTorrent", "Preferences/Bittorrent/MaxUploadsPerTorrent"}, - {"BitTorrent/Session/DHTEnabled", "Preferences/Bittorrent/DHT"}, - {"BitTorrent/Session/LSDEnabled", "Preferences/Bittorrent/LSD"}, - {"BitTorrent/Session/PeXEnabled", "Preferences/Bittorrent/PeX"}, - {"BitTorrent/Session/AddTrackersEnabled", "Preferences/Bittorrent/AddTrackers"}, - {"BitTorrent/Session/AdditionalTrackers", "Preferences/Bittorrent/TrackersList"}, - {"BitTorrent/Session/IPFilteringEnabled", "Preferences/IPFilter/Enabled"}, - {"BitTorrent/Session/TrackerFilteringEnabled", "Preferences/IPFilter/FilterTracker"}, - {"BitTorrent/Session/IPFilter", "Preferences/IPFilter/File"}, - {"BitTorrent/Session/GlobalMaxRatio", "Preferences/Bittorrent/MaxRatio"}, - {"BitTorrent/Session/AnnounceToAllTrackers", "Preferences/Advanced/AnnounceToAllTrackers"}, - {"BitTorrent/Session/DiskCacheSize", "Preferences/Downloads/DiskWriteCacheSize"}, - {"BitTorrent/Session/DiskCacheTTL", "Preferences/Downloads/DiskWriteCacheTTL"}, - {"BitTorrent/Session/UseOSCache", "Preferences/Advanced/osCache"}, - {"BitTorrent/Session/AnonymousModeEnabled", "Preferences/Advanced/AnonymousMode"}, - {"BitTorrent/Session/QueueingSystemEnabled", "Preferences/Queueing/QueueingEnabled"}, - {"BitTorrent/Session/MaxActiveDownloads", "Preferences/Queueing/MaxActiveDownloads"}, - {"BitTorrent/Session/MaxActiveUploads", "Preferences/Queueing/MaxActiveUploads"}, - {"BitTorrent/Session/MaxActiveTorrents", "Preferences/Queueing/MaxActiveTorrents"}, - {"BitTorrent/Session/IgnoreSlowTorrentsForQueueing", "Preferences/Queueing/IgnoreSlowTorrents"}, - {"BitTorrent/Session/OutgoingPortsMin", "Preferences/Advanced/OutgoingPortsMin"}, - {"BitTorrent/Session/OutgoingPortsMax", "Preferences/Advanced/OutgoingPortsMax"}, - {"BitTorrent/Session/IgnoreLimitsOnLAN", "Preferences/Advanced/IgnoreLimitsLAN"}, - {"BitTorrent/Session/IncludeOverheadInLimits", "Preferences/Advanced/IncludeOverhead"}, - {"BitTorrent/Session/AnnounceIP", "Preferences/Connection/InetAddress"}, - {"BitTorrent/Session/SuperSeedingEnabled", "Preferences/Advanced/SuperSeeding"}, - {"BitTorrent/Session/MaxHalfOpenConnections", "Preferences/Connection/MaxHalfOpenConnec"}, - {"BitTorrent/Session/uTPEnabled", "Preferences/Bittorrent/uTP"}, - {"BitTorrent/Session/uTPRateLimited", "Preferences/Bittorrent/uTP_rate_limited"}, - {"BitTorrent/TrackerEnabled", "Preferences/Advanced/trackerEnabled"}, - {"Network/Proxy/OnlyForTorrents", "Preferences/Connection/ProxyOnlyForTorrents"}, - {"Network/Proxy/Type", "Preferences/Connection/ProxyType"}, - {"Network/Proxy/Authentication", "Preferences/Connection/Proxy/Authentication"}, - {"Network/Proxy/Username", "Preferences/Connection/Proxy/Username"}, - {"Network/Proxy/Password", "Preferences/Connection/Proxy/Password"}, - {"Network/Proxy/IP", "Preferences/Connection/Proxy/IP"}, - {"Network/Proxy/Port", "Preferences/Connection/Proxy/Port"}, - {"Network/PortForwardingEnabled", "Preferences/Connection/UPnP"}, - {"AddNewTorrentDialog/TreeHeaderState", "AddNewTorrentDialog/qt5/treeHeaderState"}, - {"AddNewTorrentDialog/Width", "AddNewTorrentDialog/width"}, - {"AddNewTorrentDialog/Position", "AddNewTorrentDialog/y"}, - {"AddNewTorrentDialog/Expanded", "AddNewTorrentDialog/expanded"}, - {"AddNewTorrentDialog/SavePathHistory", "TorrentAdditionDlg/save_path_history"}, - {"AddNewTorrentDialog/Enabled", "Preferences/Downloads/NewAdditionDialog"}, - {"AddNewTorrentDialog/TopLevel", "Preferences/Downloads/NewAdditionDialogFront"}, - - {"State/BannedIPs", "Preferences/IPFilter/BannedIPs"} - - }; - - return keyMapping.value(key, key); - } -} - -SettingsStorage *SettingsStorage::m_instance = nullptr; - -SettingsStorage::SettingsStorage() - : m_data{TransactionalSettings(QLatin1String("qBittorrent")).read()} - , m_dirty(false) - , m_lock(QReadWriteLock::Recursive) -{ - m_timer.setSingleShot(true); - m_timer.setInterval(5 * 1000); - connect(&m_timer, SIGNAL(timeout()), SLOT(save())); -} - -SettingsStorage::~SettingsStorage() -{ - save(); -} - -void SettingsStorage::initInstance() -{ - if (!m_instance) - m_instance = new SettingsStorage; -} - -void SettingsStorage::freeInstance() -{ - delete m_instance; - m_instance = nullptr; -} - -SettingsStorage *SettingsStorage::instance() -{ - return m_instance; -} - -bool SettingsStorage::save() -{ - if (!m_dirty) return false; // Obtaining the lock is expensive, let's check early - QWriteLocker locker(&m_lock); - if (!m_dirty) return false; // something might have changed while we were getting the lock - - TransactionalSettings settings(QLatin1String("qBittorrent")); - if (settings.write(m_data)) { - m_dirty = false; - return true; - } - - return false; -} - -QVariant SettingsStorage::loadValue(const QString &key, const QVariant &defaultValue) const -{ - QReadLocker locker(&m_lock); - return m_data.value(mapKey(key), defaultValue); -} - -void SettingsStorage::storeValue(const QString &key, const QVariant &value) -{ - QString realKey = mapKey(key); - QWriteLocker locker(&m_lock); - if (m_data.value(realKey) != value) { - m_dirty = true; - m_data.insert(realKey, value); - m_timer.start(); - } -} - -void SettingsStorage::removeValue(const QString &key) -{ - QString realKey = mapKey(key); - QWriteLocker locker(&m_lock); - if (m_data.contains(realKey)) { - m_dirty = true; - m_data.remove(realKey); - m_timer.start(); - } -} - -QVariantHash TransactionalSettings::read() -{ - QVariantHash res; - bool writeBackNeeded = false; - QString newPath = deserialize(m_name + QLatin1String("_new"), res); - if (!newPath.isEmpty()) { // "_new" file is NOT empty - // This means that the PC closed either due to power outage - // or because the disk was full. In any case the settings weren't transfered - // in their final position. So assume that qbittorrent_new.ini/qbittorrent_new.conf - // contains the most recent settings. - Logger::instance()->addMessage(QObject::tr("Detected unclean program exit. Using fallback file to restore settings."), Log::WARNING); - writeBackNeeded = true; - } - else { - deserialize(m_name, res); - } - - Utils::Fs::forceRemove(newPath); - - if (writeBackNeeded) - write(res); - - return res; -} - -bool TransactionalSettings::write(const QVariantHash &data) -{ - // QSettings delete the file before writing it out. This can result in problems - // if the disk is full or a power outage occurs. Those events might occur - // between deleting the file and recreating it. This is a safety measure. - // Write everything to qBittorrent_new.ini/qBittorrent_new.conf and if it succeeds - // replace qBittorrent.ini/qBittorrent.conf with it. - QString newPath = serialize(m_name + QLatin1String("_new"), data); - if (newPath.isEmpty()) { - Utils::Fs::forceRemove(newPath); - return false; - } - - QString finalPath = newPath; - int index = finalPath.lastIndexOf("_new", -1, Qt::CaseInsensitive); - finalPath.remove(index, 4); - Utils::Fs::forceRemove(finalPath); - QFile::rename(newPath, finalPath); - - return true; -} - -QString TransactionalSettings::deserialize(const QString &name, QVariantHash &data) -{ - SettingsPtr settings = Profile::instance().applicationSettings(name); - - if (settings->allKeys().isEmpty()) - return QString(); - - // Copy everything into memory. This means even keys inserted in the file manually - // or that we don't touch directly in this code (eg disabled by ifdef). This ensures - // that they will be copied over when save our settings to disk. - foreach (const QString &key, settings->allKeys()) - data.insert(key, settings->value(key)); - - return settings->fileName(); -} - -QString TransactionalSettings::serialize(const QString &name, const QVariantHash &data) -{ - SettingsPtr settings = Profile::instance().applicationSettings(name); - for (auto i = data.begin(); i != data.end(); ++i) - settings->setValue(i.key(), i.value()); - - settings->sync(); // Important to get error status - QSettings::Status status = settings->status(); - if (status != QSettings::NoError) { - if (status == QSettings::AccessError) - Logger::instance()->addMessage(QObject::tr("An access error occurred while trying to write the configuration file."), Log::CRITICAL); - else - Logger::instance()->addMessage(QObject::tr("A format error occurred while trying to write the configuration file."), Log::CRITICAL); - return QString(); - } - return settings->fileName(); -} diff --git a/src/base/settingsstorage.h b/src/base/settingsstorage.h deleted file mode 100644 index 1f035fad4..000000000 --- a/src/base/settingsstorage.h +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2016 Vladimir Golovnev - * Copyright (C) 2014 sledgehammer999 - * - * 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. - */ - -#ifndef SETTINGSSTORAGE_H -#define SETTINGSSTORAGE_H - -#include -#include -#include -#include - -class SettingsStorage: public QObject -{ - Q_OBJECT - SettingsStorage(); - ~SettingsStorage(); - -public: - static void initInstance(); - static void freeInstance(); - static SettingsStorage* instance(); - - QVariant loadValue(const QString &key, const QVariant &defaultValue = QVariant()) const; - void storeValue(const QString &key, const QVariant &value); - void removeValue(const QString &key); - -public slots: - bool save(); - -private: - static SettingsStorage *m_instance; - - QVariantHash m_data; - bool m_dirty; - QTimer m_timer; - mutable QReadWriteLock m_lock; -}; - -#endif // SETTINGSSTORAGE_H diff --git a/src/base/settingvalue.h b/src/base/settingvalue.h deleted file mode 100644 index ec0ba71a1..000000000 --- a/src/base/settingvalue.h +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2016 Vladimir Golovnev - * - * 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. - */ - -#ifndef SETTINGVALUE_H -#define SETTINGVALUE_H - -#include -#include -#include -#include -#include - -#include "settingsstorage.h" - -template -class CachedSettingValue -{ - using ProxyFunc = std::function; - -public: - explicit CachedSettingValue(const char *keyName, const T &defaultValue = T()) - : m_keyName(QLatin1String(keyName)) - , m_value(loadValue(defaultValue)) - { - } - - explicit CachedSettingValue(const char *keyName, const T &defaultValue - , const ProxyFunc &proxyFunc) - : m_keyName(QLatin1String(keyName)) - , m_value(proxyFunc(loadValue(defaultValue))) - { - } - - T value() const - { - return m_value; - } - - operator T() const - { - return value(); - } - - CachedSettingValue &operator=(const T &newValue) - { - m_value = newValue; - storeValue(m_value); - return *this; - } - -private: - // regular load/save pair - template ::value, int>::type = 0> - U loadValue(const U &defaultValue) - { - return SettingsStorage::instance()->loadValue(m_keyName, defaultValue).template value(); - } - - template ::value, int>::type = 0> - void storeValue(const U &value) - { - SettingsStorage::instance()->storeValue(m_keyName, value); - } - - // load/save pair for an enum - // saves literal value of the enum constant, obtained from QMetaEnum - template ::value, int>::type = 0> - U loadValue(const U &defaultValue) - { - static_assert(std::is_same::type>::value, - "Enumeration underlying type has to be int"); - - bool ok = false; - const U res = static_cast(QMetaEnum::fromType().keyToValue( - SettingsStorage::instance()->loadValue(m_keyName).toString().toLatin1().constData(), &ok)); - return ok ? res : defaultValue; - } - - template ::value, int>::type = 0> - void storeValue(const U &value) - { - SettingsStorage::instance()->storeValue(m_keyName, - QString::fromLatin1(QMetaEnum::fromType().valueToKey(static_cast(value)))); - } - - const QString m_keyName; - T m_value; -}; - -#endif // SETTINGVALUE_H diff --git a/src/base/torrentfileguard.cpp b/src/base/torrentfileguard.cpp deleted file mode 100644 index 1a39196e5..000000000 --- a/src/base/torrentfileguard.cpp +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2016 Eugene Shalygin - * - * 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. - */ - -#include "torrentfileguard.h" - -#include "settingvalue.h" -#include "utils/fs.h" - -FileGuard::FileGuard(const QString &path) - : m_path {path} - , m_remove {true} -{ -} - -void FileGuard::setAutoRemove(bool remove) noexcept -{ - m_remove = remove; -} - -FileGuard::~FileGuard() -{ - if (m_remove && !m_path.isEmpty()) - Utils::Fs::forceRemove(m_path); // forceRemove() checks for file existence -} - -TorrentFileGuard::TorrentFileGuard(const QString &path, TorrentFileGuard::AutoDeleteMode mode) - : FileGuard {mode != Never ? path : QString()} - , m_mode {mode} - , m_wasAdded {false} -{ -} - -TorrentFileGuard::TorrentFileGuard(const QString &path) - : TorrentFileGuard {path, autoDeleteMode()} -{ -} - -TorrentFileGuard::~TorrentFileGuard() -{ - if (!m_wasAdded && (m_mode != Always)) - setAutoRemove(false); -} - -void TorrentFileGuard::markAsAddedToSession() -{ - m_wasAdded = true; -} - -TorrentFileGuard::AutoDeleteMode TorrentFileGuard::autoDeleteMode() -{ - return autoDeleteModeSetting(); -} - -void TorrentFileGuard::setAutoDeleteMode(TorrentFileGuard::AutoDeleteMode mode) -{ - autoDeleteModeSetting() = mode; -} - -CachedSettingValue &TorrentFileGuard::autoDeleteModeSetting() -{ - static CachedSettingValue setting("Core/AutoDeleteAddedTorrentFile", AutoDeleteMode::Never); - return setting; -} - diff --git a/src/base/torrentfileguard.h b/src/base/torrentfileguard.h deleted file mode 100644 index 30ec3138d..000000000 --- a/src/base/torrentfileguard.h +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2016 Eugene Shalygin - * - * 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. - */ - -#ifndef TOFFENTFILEGURAD_H -#define TOFFENTFILEGURAD_H - -#include -#include - -template class CachedSettingValue; - -/// Utility class to defer file deletion -class FileGuard -{ -public: - FileGuard(const QString &path = QString()); - ~FileGuard(); - - /// Cancels or re-enables deferred file deletion - void setAutoRemove(bool remove) noexcept; - -private: - QString m_path; - bool m_remove; -}; - -/// Reads settings for .torrent files from preferences -/// and sets the file guard up accordingly -class TorrentFileGuard: private FileGuard -{ - Q_GADGET - -public: - TorrentFileGuard(const QString &path = QString()); - ~TorrentFileGuard(); - - /// marks the torrent file as loaded (added) into the BitTorrent::Session - void markAsAddedToSession(); - using FileGuard::setAutoRemove; - - enum AutoDeleteMode: int // do not change these names: they are stored in config file - { - Never, - IfAdded, - Always - }; - - // static interface to get/set preferences - static AutoDeleteMode autoDeleteMode(); - static void setAutoDeleteMode(AutoDeleteMode mode); - -private: - TorrentFileGuard(const QString &path, AutoDeleteMode mode); - static CachedSettingValue &autoDeleteModeSetting(); - - Q_ENUM(AutoDeleteMode) - AutoDeleteMode m_mode; - bool m_wasAdded; -}; - -#endif // TOFFENTFILEGURAD_H diff --git a/src/base/torrentfilter.cpp b/src/base/torrentfilter.cpp deleted file mode 100644 index 716f93041..000000000 --- a/src/base/torrentfilter.cpp +++ /dev/null @@ -1,191 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2014 Vladimir Golovnev - * - * 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. - */ - -#include "bittorrent/torrenthandle.h" -#include "torrentfilter.h" - -const QString TorrentFilter::AnyCategory; -const QStringSet TorrentFilter::AnyHash = (QStringSet() << QString()); -const QString TorrentFilter::AnyTag; - -const TorrentFilter TorrentFilter::DownloadingTorrent(TorrentFilter::Downloading); -const TorrentFilter TorrentFilter::SeedingTorrent(TorrentFilter::Seeding); -const TorrentFilter TorrentFilter::CompletedTorrent(TorrentFilter::Completed); -const TorrentFilter TorrentFilter::PausedTorrent(TorrentFilter::Paused); -const TorrentFilter TorrentFilter::ResumedTorrent(TorrentFilter::Resumed); -const TorrentFilter TorrentFilter::ActiveTorrent(TorrentFilter::Active); -const TorrentFilter TorrentFilter::InactiveTorrent(TorrentFilter::Inactive); -const TorrentFilter TorrentFilter::ErroredTorrent(TorrentFilter::Errored); - -using BitTorrent::TorrentHandle; -using BitTorrent::TorrentState; - -TorrentFilter::TorrentFilter() - : m_type(All) -{ -} - -TorrentFilter::TorrentFilter(const Type type, const QStringSet &hashSet, const QString &category, const QString &tag) - : m_type(type) - , m_category(category) - , m_tag(tag) - , m_hashSet(hashSet) -{ -} - -TorrentFilter::TorrentFilter(const QString &filter, const QStringSet &hashSet, const QString &category, const QString &tag) - : m_type(All) - , m_category(category) - , m_tag(tag) - , m_hashSet(hashSet) -{ - setTypeByName(filter); -} - -bool TorrentFilter::setType(Type type) -{ - if (m_type != type) { - m_type = type; - return true; - } - - return false; -} - -bool TorrentFilter::setTypeByName(const QString &filter) -{ - Type type = All; - - if (filter == "downloading") - type = Downloading; - else if (filter == "seeding") - type = Seeding; - else if (filter == "completed") - type = Completed; - else if (filter == "paused") - type = Paused; - else if (filter == "resumed") - type = Resumed; - else if (filter == "active") - type = Active; - else if (filter == "inactive") - type = Inactive; - else if (filter == "errored") - type = Errored; - - return setType(type); -} - -bool TorrentFilter::setHashSet(const QStringSet &hashSet) -{ - if (m_hashSet != hashSet) { - m_hashSet = hashSet; - return true; - } - - return false; -} - -bool TorrentFilter::setCategory(const QString &category) -{ - // QString::operator==() doesn't distinguish between empty and null strings. - if ((m_category != category) - || (m_category.isNull() && !category.isNull()) - || (!m_category.isNull() && category.isNull())) { - m_category = category; - return true; - } - - return false; -} - -bool TorrentFilter::setTag(const QString &tag) -{ - // QString::operator==() doesn't distinguish between empty and null strings. - if ((m_tag != tag) - || (m_tag.isNull() && !tag.isNull()) - || (!m_tag.isNull() && tag.isNull())) { - m_tag = tag; - return true; - } - - return false; -} - -bool TorrentFilter::match(TorrentHandle *const torrent) const -{ - if (!torrent) return false; - - return (matchState(torrent) && matchHash(torrent) && matchCategory(torrent) && matchTag(torrent)); -} - -bool TorrentFilter::matchState(BitTorrent::TorrentHandle *const torrent) const -{ - switch (m_type) { - case All: - return true; - case Downloading: - return torrent->isDownloading(); - case Seeding: - return torrent->isUploading(); - case Completed: - return torrent->isCompleted(); - case Paused: - return torrent->isPaused(); - case Resumed: - return torrent->isResumed(); - case Active: - return torrent->isActive(); - case Inactive: - return torrent->isInactive(); - case Errored: - return torrent->isErrored(); - default: // All - return true; - } -} - -bool TorrentFilter::matchHash(BitTorrent::TorrentHandle *const torrent) const -{ - if (m_hashSet == AnyHash) return true; - else return m_hashSet.contains(torrent->hash()); -} - -bool TorrentFilter::matchCategory(BitTorrent::TorrentHandle *const torrent) const -{ - if (m_category.isNull()) return true; - else return (torrent->belongsToCategory(m_category)); -} - -bool TorrentFilter::matchTag(BitTorrent::TorrentHandle *const torrent) const -{ - // Empty tag is a special value to indicate we're filtering for untagged torrents. - if (m_tag.isNull()) return true; - else if (m_tag.isEmpty()) return torrent->tags().isEmpty(); - else return (torrent->hasTag(m_tag)); -} diff --git a/src/base/torrentfilter.h b/src/base/torrentfilter.h deleted file mode 100644 index cb2c150ad..000000000 --- a/src/base/torrentfilter.h +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2014 Vladimir Golovnev - * - * 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. - */ - -#ifndef TORRENTFILTER_H -#define TORRENTFILTER_H - -#include -#include - -typedef QSet QStringSet; - -namespace BitTorrent -{ - -class TorrentHandle; -class TorrentState; - -} - -class TorrentFilter -{ -public: - enum Type - { - All, - Downloading, - Seeding, - Completed, - Resumed, - Paused, - Active, - Inactive, - Errored - }; - - // These mean any permutation, including no category / tag. - static const QString AnyCategory; - static const QStringSet AnyHash; - static const QString AnyTag; - - static const TorrentFilter DownloadingTorrent; - static const TorrentFilter SeedingTorrent; - static const TorrentFilter CompletedTorrent; - static const TorrentFilter PausedTorrent; - static const TorrentFilter ResumedTorrent; - static const TorrentFilter ActiveTorrent; - static const TorrentFilter InactiveTorrent; - static const TorrentFilter ErroredTorrent; - - TorrentFilter(); - // category & tags: pass empty string for uncategorized / untagged torrents. - // Pass null string (QString()) to disable filtering (i.e. all torrents). - TorrentFilter(const Type type, const QStringSet &hashSet = AnyHash, const QString &category = AnyCategory, const QString &tag = AnyTag); - TorrentFilter(const QString &filter, const QStringSet &hashSet = AnyHash, const QString &category = AnyCategory, const QString &tags = AnyTag); - - bool setType(Type type); - bool setTypeByName(const QString &filter); - bool setHashSet(const QStringSet &hashSet); - bool setCategory(const QString &category); - bool setTag(const QString &tag); - - bool match(BitTorrent::TorrentHandle *const torrent) const; - -private: - bool matchState(BitTorrent::TorrentHandle *const torrent) const; - bool matchHash(BitTorrent::TorrentHandle *const torrent) const; - bool matchCategory(BitTorrent::TorrentHandle *const torrent) const; - bool matchTag(BitTorrent::TorrentHandle *const torrent) const; - - Type m_type; - QString m_category; - QString m_tag; - QStringSet m_hashSet; -}; - -#endif // TORRENTFILTER_H diff --git a/src/base/tristatebool.cpp b/src/base/tristatebool.cpp deleted file mode 100644 index 1de7efc7f..000000000 --- a/src/base/tristatebool.cpp +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2015 Vladimir Golovnev - * - * 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. - */ - -#include "tristatebool.h" - -const TriStateBool TriStateBool::Undefined(-1); -const TriStateBool TriStateBool::False(0); -const TriStateBool TriStateBool::True(1); - -TriStateBool::operator int() const -{ - return m_value; -} - -TriStateBool::TriStateBool(int value) -{ - if (value < 0) - m_value = -1; - else if (value > 0) - m_value = 1; - else - m_value = 0; -} - -bool TriStateBool::operator==(const TriStateBool &other) const -{ - return (m_value == other.m_value); -} - -bool TriStateBool::operator!=(const TriStateBool &other) const -{ - return !operator==(other); -} diff --git a/src/base/tristatebool.h b/src/base/tristatebool.h deleted file mode 100644 index a75d1d09c..000000000 --- a/src/base/tristatebool.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2015 Vladimir Golovnev - * - * 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. - */ - -#ifndef TRISTATEBOOL_H -#define TRISTATEBOOL_H - -class TriStateBool -{ -public: - static const TriStateBool Undefined; - static const TriStateBool False; - static const TriStateBool True; - - TriStateBool() = default; - TriStateBool(const TriStateBool &other) = default; - - explicit TriStateBool(int value); - explicit operator int() const; - - TriStateBool &operator=(const TriStateBool &other) = default; - bool operator==(const TriStateBool &other) const; - bool operator!=(const TriStateBool &other) const; - -private: - int m_value = -1; // Undefined by default -}; - -#endif // TRISTATEBOOL_H diff --git a/src/base/types.h b/src/base/types.h deleted file mode 100644 index bd18b1a40..000000000 --- a/src/base/types.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2015 Vladimir Golovnev - * - * 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. - */ - -#ifndef TYPES_H -#define TYPES_H - -#include - -const qlonglong MAX_ETA = 8640000; - -enum class ShutdownDialogAction -{ - Exit, - Shutdown, - Suspend, - Hibernate -}; - -typedef QMap QStringMap; - -#endif // TYPES_H diff --git a/src/base/unicodestrings.h b/src/base/unicodestrings.h deleted file mode 100644 index 88ffe7782..000000000 --- a/src/base/unicodestrings.h +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2015 Mike Tzou - * - * 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. - */ - -// This file must be encoded in "UTF-8 with BOM" -#ifdef _MSC_VER -#pragma execution_character_set("utf-8") -#endif - -// Because of the poor handling of UTF-8 characters in MSVC (emits warning C4819), -// we put all problematic UTF-8 chars/strings in this file. -// See issue #3059 for more details (https://github.com/qbittorrent/qBittorrent/issues/3059). -const char C_INFINITY[] = "∞"; -const char C_NON_BREAKING_SPACE[] = " "; -const char C_UP[] = "▲"; -const char C_DOWN[] = "▼"; -const char C_COPYRIGHT[] = "©"; -const char C_THIN_SPACE[] = " "; -const char C_UTP[] = "μTP"; -const char C_LOCALE_ENGLISH[] = "English"; -const char C_LOCALE_ENGLISH_AUSTRALIA[] = "English(Australia)"; -const char C_LOCALE_ENGLISH_UNITEDKINGDOM[] = "English(United Kingdom)"; -const char C_LOCALE_ESPERANTO[] = "Esperanto"; -const char C_LOCALE_FRENCH[] = "Français"; -const char C_LOCALE_GERMAN[] = "Deutsch"; -const char C_LOCALE_HUNGARIAN[] = "Magyar"; -const char C_LOCALE_ICELANDIC[] = "Íslenska"; -const char C_LOCALE_INDONESIAN[] = "Bahasa Indonesia"; -const char C_LOCALE_ITALIAN[] = "Italiano"; -const char C_LOCALE_DUTCH[] = "Nederlands"; -const char C_LOCALE_SPANISH[] = "Español"; -const char C_LOCALE_CATALAN[] = "Català"; -const char C_LOCALE_GALICIAN[] = "Galego"; -const char C_LOCALE_OCCITAN[] = "lenga d'òc"; -const char C_LOCALE_PORTUGUESE[] = "Português"; -const char C_LOCALE_PORTUGUESE_BRAZIL[] = "Português brasileiro"; -const char C_LOCALE_POLISH[] = "Polski"; -const char C_LOCALE_LATVIAN[] = "latviešu valoda"; -const char C_LOCALE_LITHUANIAN[] = "Lietuvių"; -const char C_LOCALE_MALAY[] = "بهاس ملايو"; -const char C_LOCALE_CZECH[] = "Čeština"; -const char C_LOCALE_SLOVAK[] = "Slovenčina"; -const char C_LOCALE_SLOVENIAN[] = "Slovenščina"; -const char C_LOCALE_SERBIAN[] = "Српски"; -const char C_LOCALE_CROATIAN[] = "Hrvatski"; -const char C_LOCALE_ARMENIAN[] = "Հայերեն"; -const char C_LOCALE_ROMANIAN[] = "Română"; -const char C_LOCALE_TURKISH[] = "Türkçe"; -const char C_LOCALE_GREEK[] = "Ελληνικά"; -const char C_LOCALE_SWEDISH[] = "Svenska"; -const char C_LOCALE_FINNISH[] = "Suomi"; -const char C_LOCALE_NORWEGIAN[] = "Norsk"; -const char C_LOCALE_DANISH[] = "Dansk"; -const char C_LOCALE_BULGARIAN[] = "Български"; -const char C_LOCALE_UKRAINIAN[] = "Українська"; -const char C_LOCALE_UZBEK[] = "أۇزبېك‎"; -const char C_LOCALE_RUSSIAN[] = "Русский"; -const char C_LOCALE_JAPANESE[] = "日本語"; -const char C_LOCALE_HEBREW[] = "עברית"; -const char C_LOCALE_HINDI[] = "हिन्दी, हिंदी"; -const char C_LOCALE_ARABIC[] = "عربي"; -const char C_LOCALE_GEORGIAN[] = "ქართული"; -const char C_LOCALE_BYELORUSSIAN[] = "Беларуская"; -const char C_LOCALE_BASQUE[] = "Euskara"; -const char C_LOCALE_VIETNAMESE[] = "tiếng Việt"; -const char C_LOCALE_CHINESE_TRADITIONAL_TW[] = "正體中文"; -const char C_LOCALE_CHINESE_TRADITIONAL_HK[] = "香港正體字"; -const char C_LOCALE_CHINESE_SIMPLIFIED[] = "简体中文"; -const char C_LOCALE_KOREAN[] = "한글"; diff --git a/src/base/utils/fs.cpp b/src/base/utils/fs.cpp deleted file mode 100644 index b10edc241..000000000 --- a/src/base/utils/fs.cpp +++ /dev/null @@ -1,286 +0,0 @@ -/* - * Bittorrent Client using Qt 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.h" - -#include -#include -#include -#include -#include -#include -#include - -#if defined(Q_OS_WIN) -#include -#elif defined(Q_OS_MAC) || defined(Q_OS_FREEBSD) -#include -#include -#elif defined(Q_OS_HAIKU) -#include -#else -#include -#endif - -#include "base/bittorrent/torrenthandle.h" - -/** - * 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 Utils::Fs::toNativePath(const QString& path) -{ - return QDir::toNativeSeparators(path); -} - -QString Utils::Fs::fromNativePath(const QString &path) -{ - return QDir::fromNativeSeparators(path); -} - -/** - * Returns the file extension part of a file name. - */ -QString Utils::Fs::fileExtension(const QString &filename) -{ - QString ext = QString(filename).remove(QB_EXT); - const int point_index = ext.lastIndexOf("."); - return (point_index >= 0) ? ext.mid(point_index + 1) : QString(); -} - -QString Utils::Fs::fileName(const QString& file_path) -{ - QString path = fromNativePath(file_path); - const int slash_index = path.lastIndexOf("/"); - if (slash_index == -1) - return path; - return path.mid(slash_index + 1); -} - -QString Utils::Fs::folderName(const QString& file_path) -{ - QString path = fromNativePath(file_path); - const int slash_index = path.lastIndexOf("/"); - if (slash_index == -1) - return path; - return path.left(slash_index); -} - -/** - * This function will first remove system cache files, e.g. `Thumbs.db`, - * `.DS_Store`. Then will try to remove the whole tree if the tree consist - * only of folders - */ -bool Utils::Fs::smartRemoveEmptyFolderTree(const QString& path) -{ - if (path.isEmpty() || !QDir(path).exists()) - return false; - - static const QStringList deleteFilesList = { - // Windows - "Thumbs.db", - "desktop.ini", - // Linux - ".directory", - // Mac OS - ".DS_Store" - }; - - // travel from the deepest folder and remove anything unwanted on the way out. - QStringList dirList(path + "/"); // get all sub directories paths - QDirIterator iter(path, (QDir::AllDirs | QDir::NoDotAndDotDot), QDirIterator::Subdirectories); - while (iter.hasNext()) - dirList << iter.next() + "/"; - std::sort(dirList.begin(), dirList.end(), [](const QString &l, const QString &r) { return l.count("/") > r.count("/"); }); // sort descending by directory depth - - for (const QString &p : dirList) { - // remove unwanted files - for (const QString &f : deleteFilesList) { - forceRemove(p + f); - } - - // remove temp files on linux (file ends with '~'), e.g. `filename~` - QDir dir(p); - QStringList tmpFileList = dir.entryList(QDir::Files); - for (const QString &f : tmpFileList) { - if (f.endsWith("~")) - forceRemove(p + f); - } - - // remove directory if empty - dir.rmdir(p); - } - - return QDir(path).exists(); -} - -/** - * Removes the file with the given file_path. - * - * This function will try to fix the file permissions before removing it. - */ -bool Utils::Fs::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(); -} - -/** - * Removes directory and its content recursively. - * - */ -void Utils::Fs::removeDirRecursive(const QString &path) -{ - if (!path.isEmpty()) - QDir(path).removeRecursively(); -} - -/** - * 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 Utils::Fs::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; - QDirIterator iter(path, QDir::Files | QDir::Hidden | QDir::NoSymLinks, QDirIterator::Subdirectories); - while (iter.hasNext()) { - iter.next(); - size += iter.fileInfo().size(); - } - return size; -} - -/** - * Makes deep comparison of two files to make sure they are identical. - */ -bool Utils::Fs::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)) return false; - - const int readSize = 1024 * 1024; // 1 MiB - while(!f1.atEnd() && !f2.atEnd()) { - if (f1.read(readSize) != f2.read(readSize)) - return false; - } - return true; -} - -QString Utils::Fs::toValidFileSystemName(const QString &name, bool allowSeparators, const QString &pad) -{ - QRegExp regex(allowSeparators ? "[:?\"*<>|]+" : "[\\\\/:?\"*<>|]+"); - - QString validName = name.trimmed(); - validName.replace(regex, pad); - qDebug() << "toValidFileSystemName:" << name << "=>" << validName; - - return validName; -} - -bool Utils::Fs::isValidFileSystemName(const QString &name, bool allowSeparators) -{ - if (name.isEmpty()) return false; - - QRegExp regex(allowSeparators ? "[:?\"*<>|]" : "[\\\\/:?\"*<>|]"); - return !name.contains(regex); -} - -qint64 Utils::Fs::freeDiskSpaceOnPath(const QString &path) -{ - if (path.isEmpty()) return -1; - - return QStorageInfo(path).bytesAvailable(); -} - -QString Utils::Fs::branchPath(const QString& file_path, QString* removed) -{ - QString ret = fromNativePath(file_path); - if (ret.endsWith("/")) - ret.chop(1); - const int slashIndex = ret.lastIndexOf("/"); - if (slashIndex >= 0) { - if (removed) - *removed = ret.mid(slashIndex + 1); - ret = ret.left(slashIndex); - } - return ret; -} - -bool Utils::Fs::sameFileNames(const QString &first, const QString &second) -{ -#if defined(Q_OS_UNIX) || defined(Q_WS_QWS) - return QString::compare(first, second, Qt::CaseSensitive) == 0; -#else - return QString::compare(first, second, Qt::CaseInsensitive) == 0; -#endif -} - -QString Utils::Fs::expandPath(const QString &path) -{ - QString ret = fromNativePath(path.trimmed()); - if (ret.isEmpty()) - return ret; - - return QDir::cleanPath(ret); -} - -QString Utils::Fs::expandPathAbs(const QString& path) -{ - QString ret = expandPath(path); - - if (!QDir::isAbsolutePath(ret)) - ret = QDir(ret).absolutePath(); - - return ret; -} - -QString Utils::Fs::tempPath() -{ - static const QString path = QDir::tempPath() + "/.qBittorrent/"; - QDir().mkdir(path); - return path; -} diff --git a/src/base/utils/fs.h b/src/base/utils/fs.h deleted file mode 100644 index 59e532c68..000000000 --- a/src/base/utils/fs.h +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Bittorrent Client using Qt 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 UTILS_FS_H -#define UTILS_FS_H - -/** - * Utility functions related to file system. - */ - -#include - -namespace Utils -{ - namespace Fs - { - QString toNativePath(const QString& path); - QString fromNativePath(const QString& path); - QString fileExtension(const QString& filename); - QString fileName(const QString& file_path); - QString folderName(const QString& file_path); - qint64 computePathSize(const QString& path); - bool sameFiles(const QString& path1, const QString& path2); - QString toValidFileSystemName(const QString &name, bool allowSeparators = false - , const QString &pad = QLatin1String(" ")); - bool isValidFileSystemName(const QString& name, bool allowSeparators = false); - qint64 freeDiskSpaceOnPath(const QString &path); - QString branchPath(const QString& file_path, QString* removed = 0); - bool sameFileNames(const QString& first, const QString& second); - QString expandPath(const QString& path); - QString expandPathAbs(const QString& path); - - bool smartRemoveEmptyFolderTree(const QString& path); - bool forceRemove(const QString& file_path); - void removeDirRecursive(const QString& path); - - QString tempPath(); - } -} - -#endif // UTILS_FS_H diff --git a/src/base/utils/gzip.cpp b/src/base/utils/gzip.cpp deleted file mode 100644 index b9f3eba26..000000000 --- a/src/base/utils/gzip.cpp +++ /dev/null @@ -1,151 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2015 Vladimir Golovnev - * Copyright (C) 2006 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. - */ - -#include "gzip.h" - -#include - -#include - -#ifndef ZLIB_CONST -#define ZLIB_CONST // make z_stream.next_in const -#endif -#include - -QByteArray Utils::Gzip::compress(const QByteArray &data, const int level, bool *ok) -{ - if (ok) *ok = false; - - if (data.isEmpty()) - return {}; - - const int BUFSIZE = 128 * 1024; - std::vector tmpBuf(BUFSIZE); - - z_stream strm; - strm.zalloc = Z_NULL; - strm.zfree = Z_NULL; - strm.opaque = Z_NULL; - strm.next_in = reinterpret_cast(data.constData()); - strm.avail_in = uInt(data.size()); - strm.next_out = reinterpret_cast(tmpBuf.data()); - strm.avail_out = BUFSIZE; - - // windowBits = 15 + 16 to enable gzip - // From the zlib manual: windowBits can also be greater than 15 for optional gzip encoding. Add 16 to windowBits - // to write a simple gzip header and trailer around the compressed data instead of a zlib wrapper. - int result = deflateInit2(&strm, level, Z_DEFLATED, (15 + 16), 9, Z_DEFAULT_STRATEGY); - if (result != Z_OK) - return {}; - - QByteArray output; - output.reserve(deflateBound(&strm, data.size())); - - // feed to deflate - while (strm.avail_in > 0) { - result = deflate(&strm, Z_NO_FLUSH); - - if (result != Z_OK) { - deflateEnd(&strm); - return {}; - } - - output.append(tmpBuf.data(), (BUFSIZE - strm.avail_out)); - strm.next_out = reinterpret_cast(tmpBuf.data()); - strm.avail_out = BUFSIZE; - } - - // flush the rest from deflate - while (result != Z_STREAM_END) { - result = deflate(&strm, Z_FINISH); - - output.append(tmpBuf.data(), (BUFSIZE - strm.avail_out)); - strm.next_out = reinterpret_cast(tmpBuf.data()); - strm.avail_out = BUFSIZE; - } - - deflateEnd(&strm); - - if (ok) *ok = true; - return output; -} - -QByteArray Utils::Gzip::decompress(const QByteArray &data, bool *ok) -{ - if (ok) *ok = false; - - if (data.isEmpty()) - return {}; - - const int BUFSIZE = 1024 * 1024; - std::vector tmpBuf(BUFSIZE); - - z_stream strm; - strm.zalloc = Z_NULL; - strm.zfree = Z_NULL; - strm.opaque = Z_NULL; - strm.next_in = reinterpret_cast(data.constData()); - strm.avail_in = uInt(data.size()); - strm.next_out = reinterpret_cast(tmpBuf.data()); - strm.avail_out = BUFSIZE; - - // windowBits must be greater than or equal to the windowBits value provided to deflateInit2() while compressing - // Add 32 to windowBits to enable zlib and gzip decoding with automatic header detection - int result = inflateInit2(&strm, (15 + 32)); - if (result != Z_OK) - return {}; - - QByteArray output; - // from lzbench, level 9 average compression ratio is: 31.92%, which decompression ratio is: 1 / 0.3192 = 3.13 - output.reserve(data.size() * 3); - - // run inflate - while (true) { - result = inflate(&strm, Z_NO_FLUSH); - - if (result == Z_STREAM_END) { - output.append(tmpBuf.data(), (BUFSIZE - strm.avail_out)); - break; - } - - if (result != Z_OK) { - inflateEnd(&strm); - return {}; - } - - output.append(tmpBuf.data(), (BUFSIZE - strm.avail_out)); - strm.next_out = reinterpret_cast(tmpBuf.data()); - strm.avail_out = BUFSIZE; - } - - inflateEnd(&strm); - - if (ok) *ok = true; - return output; -} diff --git a/src/base/utils/gzip.h b/src/base/utils/gzip.h deleted file mode 100644 index 4954a4023..000000000 --- a/src/base/utils/gzip.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2015 Vladimir Golovnev - * Copyright (C) 2006 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. - */ - -#ifndef UTILS_GZIP_H -#define UTILS_GZIP_H - -class QByteArray; - -namespace Utils -{ - namespace Gzip - { - QByteArray compress(const QByteArray &data, int level = 6, bool *ok = nullptr); - QByteArray decompress(const QByteArray &data, bool *ok = nullptr); - } -} - -#endif // UTILS_GZIP_H diff --git a/src/base/utils/misc.cpp b/src/base/utils/misc.cpp deleted file mode 100644 index 65d4ea85a..000000000 --- a/src/base/utils/misc.cpp +++ /dev/null @@ -1,688 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2006 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef DISABLE_GUI -#include -#else -#include -#include -#include -#endif - -#ifdef Q_OS_WIN -#include -#include -#include -const int UNLEN = 256; -#else -#include -#include -#endif - -#ifdef Q_OS_MAC -#include -#include -#endif - -#ifndef DISABLE_GUI -#if (defined(Q_OS_UNIX) && !defined(Q_OS_MAC)) && defined(QT_DBUS_LIB) -#include -#include -#endif -#endif // DISABLE_GUI - -#ifndef DISABLE_GUI -#include -#include -#endif - -#include "base/utils/string.h" -#include "base/unicodestrings.h" -#include "base/logger.h" -#include "misc.h" -#include "fs.h" - -static struct { const char *source; const char *comment; } units[] = { - QT_TRANSLATE_NOOP3("misc", "B", "bytes"), - QT_TRANSLATE_NOOP3("misc", "KiB", "kibibytes (1024 bytes)"), - QT_TRANSLATE_NOOP3("misc", "MiB", "mebibytes (1024 kibibytes)"), - QT_TRANSLATE_NOOP3("misc", "GiB", "gibibytes (1024 mibibytes)"), - QT_TRANSLATE_NOOP3("misc", "TiB", "tebibytes (1024 gibibytes)"), - QT_TRANSLATE_NOOP3("misc", "PiB", "pebibytes (1024 tebibytes)"), - QT_TRANSLATE_NOOP3("misc", "EiB", "exbibytes (1024 pebibytes)") -}; - -void Utils::Misc::shutdownComputer(const ShutdownDialogAction &action) -{ -#if defined(Q_OS_WIN) - HANDLE hToken; // handle to process token - TOKEN_PRIVILEGES tkp; // pointer to token structure - if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) - return; - // Get the LUID for shutdown privilege. - LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME, - &tkp.Privileges[0].Luid); - - tkp.PrivilegeCount = 1; // one privilege to set - tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; - - // Get shutdown privilege for this process. - - AdjustTokenPrivileges(hToken, FALSE, &tkp, 0, - (PTOKEN_PRIVILEGES) NULL, 0); - - // Cannot test the return value of AdjustTokenPrivileges. - - if (GetLastError() != ERROR_SUCCESS) - return; - - if (action == ShutdownDialogAction::Suspend) - SetSuspendState(false, false, false); - else if (action == ShutdownDialogAction::Hibernate) - SetSuspendState(true, false, false); - else - InitiateSystemShutdownA(0, QCoreApplication::translate("misc", "qBittorrent will shutdown the computer now because all downloads are complete.").toLocal8Bit().data(), 10, true, false); - - // Disable shutdown privilege. - tkp.Privileges[0].Attributes = 0; - AdjustTokenPrivileges(hToken, FALSE, &tkp, 0, (PTOKEN_PRIVILEGES) NULL, 0); - -#elif defined(Q_OS_MAC) - AEEventID EventToSend; - if (action != ShutdownDialogAction::Shutdown) - EventToSend = kAESleep; - else - EventToSend = kAEShutDown; - AEAddressDesc targetDesc; - static const ProcessSerialNumber kPSNOfSystemProcess = { 0, kSystemProcess }; - AppleEvent eventReply = {typeNull, NULL}; - AppleEvent appleEventToSend = {typeNull, NULL}; - - OSStatus error = AECreateDesc(typeProcessSerialNumber, &kPSNOfSystemProcess, - sizeof(kPSNOfSystemProcess), &targetDesc); - - if (error != noErr) - return; - - error = AECreateAppleEvent(kCoreEventClass, EventToSend, &targetDesc, - kAutoGenerateReturnID, kAnyTransactionID, &appleEventToSend); - - AEDisposeDesc(&targetDesc); - if (error != noErr) - return; - - error = AESend(&appleEventToSend, &eventReply, kAENoReply, - kAENormalPriority, kAEDefaultTimeout, NULL, NULL); - - AEDisposeDesc(&appleEventToSend); - if (error != noErr) - return; - - AEDisposeDesc(&eventReply); - -#elif (defined(Q_OS_UNIX) && defined(QT_DBUS_LIB)) - // Use dbus to power off / suspend the system - if (action != ShutdownDialogAction::Shutdown) { - // Some recent systems use systemd's logind - QDBusInterface login1Iface("org.freedesktop.login1", "/org/freedesktop/login1", - "org.freedesktop.login1.Manager", QDBusConnection::systemBus()); - if (login1Iface.isValid()) { - if (action == ShutdownDialogAction::Suspend) - login1Iface.call("Suspend", false); - else - login1Iface.call("Hibernate", false); - return; - } - // Else, other recent systems use UPower - QDBusInterface upowerIface("org.freedesktop.UPower", "/org/freedesktop/UPower", - "org.freedesktop.UPower", QDBusConnection::systemBus()); - if (upowerIface.isValid()) { - if (action == ShutdownDialogAction::Suspend) - upowerIface.call("Suspend"); - else - upowerIface.call("Hibernate"); - return; - } - // HAL (older systems) - QDBusInterface halIface("org.freedesktop.Hal", "/org/freedesktop/Hal/devices/computer", - "org.freedesktop.Hal.Device.SystemPowerManagement", - QDBusConnection::systemBus()); - if (action == ShutdownDialogAction::Suspend) - halIface.call("Suspend", 5); - else - halIface.call("Hibernate"); - } - else { - // Some recent systems use systemd's logind - QDBusInterface login1Iface("org.freedesktop.login1", "/org/freedesktop/login1", - "org.freedesktop.login1.Manager", QDBusConnection::systemBus()); - if (login1Iface.isValid()) { - login1Iface.call("PowerOff", false); - return; - } - // Else, other recent systems use ConsoleKit - QDBusInterface consolekitIface("org.freedesktop.ConsoleKit", "/org/freedesktop/ConsoleKit/Manager", - "org.freedesktop.ConsoleKit.Manager", QDBusConnection::systemBus()); - if (consolekitIface.isValid()) { - consolekitIface.call("Stop"); - return; - } - // HAL (older systems) - QDBusInterface halIface("org.freedesktop.Hal", "/org/freedesktop/Hal/devices/computer", - "org.freedesktop.Hal.Device.SystemPowerManagement", - QDBusConnection::systemBus()); - halIface.call("Shutdown"); - } - -#else - Q_UNUSED(action); -#endif -} - -#ifndef DISABLE_GUI -QPoint Utils::Misc::screenCenter(const QWidget *w) -{ - // Returns the QPoint which the widget will be placed center on screen (where parent resides) - - QWidget *parent = w->parentWidget(); - QDesktopWidget *desktop = QApplication::desktop(); - int scrn = desktop->screenNumber(parent); // fallback to `primaryScreen` when parent is invalid - QRect r = desktop->availableGeometry(scrn); - return QPoint(r.x() + (r.width() - w->frameSize().width()) / 2, r.y() + (r.height() - w->frameSize().height()) / 2); -} - -#endif - -/** - * Detects the python version. - */ -int Utils::Misc::pythonVersion() -{ - static int version = -1; - if (version < 0) { - QString versionComplete = pythonVersionComplete().trimmed(); - QStringList splitted = versionComplete.split('.'); - if (splitted.size() > 1) { - int highVer = splitted.at(0).toInt(); - if ((highVer == 2) || (highVer == 3)) - version = highVer; - } - } - return version; -} - -/** - * Detects the python executable by calling "python --version". - */ -QString Utils::Misc::pythonExecutable() -{ - static QString executable; - if (executable.isEmpty()) { - QProcess pythonProc; -#if defined(Q_OS_UNIX) - /* - * On Unix-Like Systems python2 and python3 should always exist - * http://legacy.python.org/dev/peps/pep-0394/ - */ - pythonProc.start("python3", QStringList() << "--version", QIODevice::ReadOnly); - if (pythonProc.waitForFinished() && (pythonProc.exitCode() == 0)) { - executable = "python3"; - return executable; - } - pythonProc.start("python2", QStringList() << "--version", QIODevice::ReadOnly); - if (pythonProc.waitForFinished() && (pythonProc.exitCode() == 0)) { - executable = "python2"; - return executable; - } -#endif - // Look for "python" in Windows and in UNIX if "python2" and "python3" are - // not detected. - pythonProc.start("python", QStringList() << "--version", QIODevice::ReadOnly); - if (pythonProc.waitForFinished() && (pythonProc.exitCode() == 0)) - executable = "python"; - else - Logger::instance()->addMessage(QCoreApplication::translate("misc", "Python not detected"), Log::INFO); - } - return executable; -} - -/** - * Returns the complete python version - * eg 2.7.9 - * Make sure to have setup python first - */ -QString Utils::Misc::pythonVersionComplete() -{ - static QString version; - if (version.isEmpty()) { - if (pythonExecutable().isEmpty()) - return version; - QProcess pythonProc; - pythonProc.start(pythonExecutable(), QStringList() << "--version", QIODevice::ReadOnly); - if (pythonProc.waitForFinished() && (pythonProc.exitCode() == 0)) { - QByteArray output = pythonProc.readAllStandardOutput(); - if (output.isEmpty()) - output = pythonProc.readAllStandardError(); - - // Software 'Anaconda' installs its own python interpreter - // and `python --version` returns a string like this: - // `Python 3.4.3 :: Anaconda 2.3.0 (64-bit)` - const QList outSplit = output.split(' '); - if (outSplit.size() > 1) { - version = outSplit.at(1).trimmed(); - Logger::instance()->addMessage(QCoreApplication::translate("misc", "Python version: %1").arg(version), Log::INFO); - } - - // If python doesn't report a 3-piece version e.g. 3.6.1 - // then fill the missing pieces with zero - const QStringList verSplit = version.split('.', QString::SkipEmptyParts); - if (verSplit.size() < 3) { - for (int i = verSplit.size(); i < 3; ++i) { - if (version.endsWith('.')) - version.append('0'); - else - version.append(".0"); - } - Logger::instance()->addMessage(QCoreApplication::translate("misc", "Normalized Python version: %1").arg(version), Log::INFO); - } - } - } - return version; -} - -QString Utils::Misc::unitString(Utils::Misc::SizeUnit unit) -{ - return QCoreApplication::translate("misc", - units[static_cast(unit)].source, units[static_cast(unit)].comment); -} - -// return best userfriendly storage unit (B, KiB, MiB, GiB, TiB, ...) -// use Binary prefix standards from IEC 60027-2 -// see http://en.wikipedia.org/wiki/Kilobyte -// value must be given in bytes -// to send numbers instead of strings with suffixes -bool Utils::Misc::friendlyUnit(qint64 sizeInBytes, qreal &val, Utils::Misc::SizeUnit &unit) -{ - if (sizeInBytes < 0) return false; - - int i = 0; - qreal rawVal = static_cast(sizeInBytes); - - while ((rawVal >= 1024.) && (i <= static_cast(SizeUnit::ExbiByte))) { - rawVal /= 1024.; - ++i; - } - val = rawVal; - unit = static_cast(i); - return true; -} - -QString Utils::Misc::friendlyUnit(qint64 bytesValue, bool isSpeed) -{ - SizeUnit unit; - qreal friendlyVal; - if (!friendlyUnit(bytesValue, friendlyVal, unit)) - return QCoreApplication::translate("misc", "Unknown", "Unknown (size)"); - QString ret; - if (unit == SizeUnit::Byte) - ret = QString::number(bytesValue) + QString::fromUtf8(C_NON_BREAKING_SPACE) + unitString(unit); - else - ret = Utils::String::fromDouble(friendlyVal, friendlyUnitPrecision(unit)) + QString::fromUtf8(C_NON_BREAKING_SPACE) + unitString(unit); - if (isSpeed) - ret += QCoreApplication::translate("misc", "/s", "per second"); - return ret; -} - -int Utils::Misc::friendlyUnitPrecision(SizeUnit unit) -{ - // friendlyUnit's number of digits after the decimal point - if (unit <= SizeUnit::MebiByte) return 1; - else if (unit == SizeUnit::GibiByte) return 2; - else return 3; -} - -qlonglong Utils::Misc::sizeInBytes(qreal size, Utils::Misc::SizeUnit unit) -{ - for (int i = 0; i < static_cast(unit); ++i) - size *= 1024; - return size; -} - -bool Utils::Misc::isPreviewable(const QString &extension) -{ - static QSet multimedia_extensions; - if (multimedia_extensions.empty()) { - multimedia_extensions.insert("3GP"); - multimedia_extensions.insert("AAC"); - multimedia_extensions.insert("AC3"); - multimedia_extensions.insert("AIF"); - multimedia_extensions.insert("AIFC"); - multimedia_extensions.insert("AIFF"); - multimedia_extensions.insert("ASF"); - multimedia_extensions.insert("AU"); - multimedia_extensions.insert("AVI"); - multimedia_extensions.insert("FLAC"); - multimedia_extensions.insert("FLV"); - multimedia_extensions.insert("M3U"); - multimedia_extensions.insert("M4A"); - multimedia_extensions.insert("M4P"); - multimedia_extensions.insert("M4V"); - multimedia_extensions.insert("MID"); - multimedia_extensions.insert("MKV"); - multimedia_extensions.insert("MOV"); - multimedia_extensions.insert("MP2"); - multimedia_extensions.insert("MP3"); - multimedia_extensions.insert("MP4"); - multimedia_extensions.insert("MPC"); - multimedia_extensions.insert("MPE"); - multimedia_extensions.insert("MPEG"); - multimedia_extensions.insert("MPG"); - multimedia_extensions.insert("MPP"); - multimedia_extensions.insert("OGG"); - multimedia_extensions.insert("OGM"); - multimedia_extensions.insert("OGV"); - multimedia_extensions.insert("QT"); - multimedia_extensions.insert("RA"); - multimedia_extensions.insert("RAM"); - multimedia_extensions.insert("RM"); - multimedia_extensions.insert("RMV"); - multimedia_extensions.insert("RMVB"); - multimedia_extensions.insert("SWA"); - multimedia_extensions.insert("SWF"); - multimedia_extensions.insert("VOB"); - multimedia_extensions.insert("WAV"); - multimedia_extensions.insert("WMA"); - multimedia_extensions.insert("WMV"); - } - - if (extension.isEmpty()) - return false; - - return multimedia_extensions.contains(extension.toUpper()); -} - -// Take a number of seconds and return an user-friendly -// time duration like "1d 2h 10m". -QString Utils::Misc::userFriendlyDuration(qlonglong seconds) -{ - if ((seconds < 0) || (seconds >= MAX_ETA)) - return QString::fromUtf8(C_INFINITY); - - if (seconds == 0) - return "0"; - - if (seconds < 60) - return QCoreApplication::translate("misc", "< 1m", "< 1 minute"); - - qlonglong minutes = seconds / 60; - if (minutes < 60) - return QCoreApplication::translate("misc", "%1m", "e.g: 10minutes").arg(QString::number(minutes)); - - qlonglong hours = minutes / 60; - minutes -= hours * 60; - if (hours < 24) - return QCoreApplication::translate("misc", "%1h %2m", "e.g: 3hours 5minutes").arg(QString::number(hours)).arg(QString::number(minutes)); - - qlonglong days = hours / 24; - hours -= days * 24; - if (days < 100) - return QCoreApplication::translate("misc", "%1d %2h", "e.g: 2days 10hours").arg(QString::number(days)).arg(QString::number(hours)); - - return QString::fromUtf8(C_INFINITY); -} - -QString Utils::Misc::getUserIDString() -{ - QString uid = "0"; -#ifdef Q_OS_WIN - WCHAR buffer[UNLEN + 1] = {0}; - DWORD buffer_len = sizeof(buffer) / sizeof(*buffer); - if (GetUserNameW(buffer, &buffer_len)) - uid = QString::fromWCharArray(buffer); -#else - uid = QString::number(getuid()); -#endif - return uid; -} - -QStringList Utils::Misc::toStringList(const QList &l) -{ - QStringList ret; - foreach (const bool &b, l) - ret << (b ? "1" : "0"); - return ret; -} - -QList Utils::Misc::intListfromStringList(const QStringList &l) -{ - QList ret; - foreach (const QString &s, l) - ret << s.toInt(); - return ret; -} - -QList Utils::Misc::boolListfromStringList(const QStringList &l) -{ - QList ret; - foreach (const QString &s, l) - ret << (s == "1"); - return ret; -} - -bool Utils::Misc::isUrl(const QString &s) -{ - static const QRegularExpression reURLScheme( - "http[s]?|ftp", QRegularExpression::CaseInsensitiveOption); - - return reURLScheme.match(QUrl(s).scheme()).hasMatch(); -} - -QString Utils::Misc::parseHtmlLinks(const QString &raw_text) -{ - QString result = raw_text; - static QRegExp reURL( - "(\\s|^)" // start with whitespace or beginning of line - "(" - "(" // case 1 -- URL with scheme - "(http(s?))\\://" // start with scheme - "([a-zA-Z0-9_-]+\\.)+" // domainpart. at least one of these must exist - "([a-zA-Z0-9\\?%=&/_\\.:#;-]+)" // everything to 1st non-URI char, must be at least one char after the previous dot (cannot use ".*" because it can be too greedy) - ")" - "|" - "(" // case 2a -- no scheme, contains common TLD example.com - "([a-zA-Z0-9_-]+\\.)+" // domainpart. at least one of these must exist - "(?=" // must be followed by TLD - "AERO|aero|" // N.B. assertions are non-capturing - "ARPA|arpa|" - "ASIA|asia|" - "BIZ|biz|" - "CAT|cat|" - "COM|com|" - "COOP|coop|" - "EDU|edu|" - "GOV|gov|" - "INFO|info|" - "INT|int|" - "JOBS|jobs|" - "MIL|mil|" - "MOBI|mobi|" - "MUSEUM|museum|" - "NAME|name|" - "NET|net|" - "ORG|org|" - "PRO|pro|" - "RO|ro|" - "RU|ru|" - "TEL|tel|" - "TRAVEL|travel" - ")" - "([a-zA-Z0-9\\?%=&/_\\.:#;-]+)" // everything to 1st non-URI char, must be at least one char after the previous dot (cannot use ".*" because it can be too greedy) - ")" - "|" - "(" // case 2b no scheme, no TLD, must have at least 2 alphanum strings plus uncommon TLD string --> del.icio.us - "([a-zA-Z0-9_-]+\\.) {2,}" // 2 or more domainpart. --> del.icio. - "[a-zA-Z]{2,}" // one ab (2 char or longer) --> us - "([a-zA-Z0-9\\?%=&/_\\.:#;-]*)" // everything to 1st non-URI char, maybe nothing in case of del.icio.us/path - ")" - ")" - ); - - - // Capture links - result.replace(reURL, "\\1\\2"); - - // Capture links without scheme - static QRegExp reNoScheme(""); - result.replace(reNoScheme, ""); - - // to preserve plain text formatting - result = "

" + result + "

"; - return result; -} - -#ifndef DISABLE_GUI -// Open the given path with an appropriate application -void Utils::Misc::openPath(const QString &absolutePath) -{ - const QString path = Utils::Fs::fromNativePath(absolutePath); - // Hack to access samba shares with QDesktopServices::openUrl - if (path.startsWith("//")) - QDesktopServices::openUrl(Utils::Fs::toNativePath("file:" + path)); - else - QDesktopServices::openUrl(QUrl::fromLocalFile(path)); -} - -// Open the parent directory of the given path with a file manager and select -// (if possible) the item at the given path -void Utils::Misc::openFolderSelect(const QString &absolutePath) -{ - const QString path = Utils::Fs::fromNativePath(absolutePath); - // If the item to select doesn't exist, try to open its parent - if (!QFileInfo(path).exists()) { - openPath(path.left(path.lastIndexOf("/"))); - return; - } -#ifdef Q_OS_WIN - HRESULT hresult = ::CoInitializeEx(nullptr, COINIT_MULTITHREADED); - PIDLIST_ABSOLUTE pidl = ::ILCreateFromPathW(reinterpret_cast(Utils::Fs::toNativePath(path).utf16())); - if (pidl) { - ::SHOpenFolderAndSelectItems(pidl, 0, nullptr, 0); - ::ILFree(pidl); - } - if ((hresult == S_OK) || (hresult == S_FALSE)) - ::CoUninitialize(); -#elif defined(Q_OS_UNIX) && !defined(Q_OS_MAC) - QProcess proc; - proc.start("xdg-mime", QStringList() << "query" << "default" << "inode/directory"); - proc.waitForFinished(); - QString output = proc.readLine().simplified(); - if ((output == "dolphin.desktop") || (output == "org.kde.dolphin.desktop")) - proc.startDetached("dolphin", QStringList() << "--select" << Utils::Fs::toNativePath(path)); - else if ((output == "nautilus.desktop") || (output == "org.gnome.Nautilus.desktop") - || (output == "nautilus-folder-handler.desktop")) - proc.startDetached("nautilus", QStringList() << "--no-desktop" << Utils::Fs::toNativePath(path)); - else if (output == "nemo.desktop") - proc.startDetached("nemo", QStringList() << "--no-desktop" << Utils::Fs::toNativePath(path)); - else if ((output == "konqueror.desktop") || (output == "kfmclient_dir.desktop")) - proc.startDetached("konqueror", QStringList() << "--select" << Utils::Fs::toNativePath(path)); - else - // "caja" manager can't pinpoint the file, see: https://github.com/qbittorrent/qBittorrent/issues/5003 - openPath(path.left(path.lastIndexOf("/"))); -#else - openPath(path.left(path.lastIndexOf("/"))); -#endif -} - -QSize Utils::Misc::smallIconSize() -{ - // Get DPI scaled icon size (device-dependent), see QT source - int s = QApplication::style()->pixelMetric(QStyle::PM_SmallIconSize); - return QSize(s, s); -} - -QSize Utils::Misc::largeIconSize() -{ - // Get DPI scaled icon size (device-dependent), see QT source - int s = QApplication::style()->pixelMetric(QStyle::PM_LargeIconSize); - return QSize(s, s); -} -#endif // DISABLE_GUI - -QString Utils::Misc::osName() -{ - // static initialization for usage in signal handler - static const QString name = - QString("%1 %2 %3") - .arg(QSysInfo::prettyProductName()) - .arg(QSysInfo::kernelVersion()) - .arg(QSysInfo::currentCpuArchitecture()); - return name; -} - -QString Utils::Misc::boostVersionString() -{ - // static initialization for usage in signal handler - static const QString ver = QString("%1.%2.%3") - .arg(BOOST_VERSION / 100000) - .arg((BOOST_VERSION / 100) % 1000) - .arg(BOOST_VERSION % 100); - return ver; -} - -QString Utils::Misc::libtorrentVersionString() -{ - // static initialization for usage in signal handler - static const QString ver = LIBTORRENT_VERSION; - return ver; -} - -#ifdef Q_OS_WIN -QString Utils::Misc::windowsSystemPath() -{ - static const QString path = []() -> QString { - WCHAR systemPath[64] = {0}; - GetSystemDirectoryW(systemPath, sizeof(systemPath) / sizeof(WCHAR)); - return QString::fromWCharArray(systemPath); - }(); - return path; -} -#endif diff --git a/src/base/utils/misc.h b/src/base/utils/misc.h deleted file mode 100644 index cf733e9a7..000000000 --- a/src/base/utils/misc.h +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2006 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 UTILS_MISC_H -#define UTILS_MISC_H - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "base/types.h" - -/* Miscellaneous functions that can be useful */ - -namespace Utils -{ - namespace Misc - { - // use binary prefix standards from IEC 60027-2 - // see http://en.wikipedia.org/wiki/Kilobyte - enum class SizeUnit - { - Byte, // 1024^0, - KibiByte, // 1024^1, - MebiByte, // 1024^2, - GibiByte, // 1024^3, - TebiByte, // 1024^4, - PebiByte, // 1024^5, - ExbiByte // 1024^6, - // int64 is used for sizes and thus the next units can not be handled - // ZebiByte, // 1024^7, - // YobiByte, // 1024^8 - }; - - QString parseHtmlLinks(const QString &raw_text); - bool isUrl(const QString &s); - - void shutdownComputer(const ShutdownDialogAction &action); - - QString osName(); - QString boostVersionString(); - QString libtorrentVersionString(); - - int pythonVersion(); - QString pythonExecutable(); - QString pythonVersionComplete(); - - QString unitString(SizeUnit unit); - - // return best user friendly storage unit (B, KiB, MiB, GiB, TiB) - // value must be given in bytes - bool friendlyUnit(qint64 sizeInBytes, qreal& val, SizeUnit& unit); - QString friendlyUnit(qint64 bytesValue, bool isSpeed = false); - int friendlyUnitPrecision(SizeUnit unit); - qint64 sizeInBytes(qreal size, SizeUnit unit); - - bool isPreviewable(const QString& extension); - - // Take a number of seconds and return an user-friendly - // time duration like "1d 2h 10m". - QString userFriendlyDuration(qlonglong seconds); - QString getUserIDString(); - - // Convert functions - QStringList toStringList(const QList &l); - QList intListfromStringList(const QStringList &l); - QList boolListfromStringList(const QStringList &l); - -#ifndef DISABLE_GUI - void openPath(const QString& absolutePath); - void openFolderSelect(const QString& absolutePath); - - QPoint screenCenter(const QWidget *w); - QSize smallIconSize(); - QSize largeIconSize(); -#endif - -#ifdef Q_OS_WIN - QString windowsSystemPath(); -#endif - } -} - -#endif diff --git a/src/base/utils/net.cpp b/src/base/utils/net.cpp deleted file mode 100644 index 564c4d29c..000000000 --- a/src/base/utils/net.cpp +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2016 Alexandr Milovantsev - * - * 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. - */ - -#include "net.h" -#include -#include - -namespace Utils -{ - namespace Net - { - bool isValidIP(const QString &ip) - { - return !QHostAddress(ip).isNull(); - } - } -} diff --git a/src/base/utils/net.h b/src/base/utils/net.h deleted file mode 100644 index 65b17b0e7..000000000 --- a/src/base/utils/net.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2016 Alexandr Milovantsev - * - * 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. - */ - -#ifndef BASE_UTILS_NET_H -#define BASE_UTILS_NET_H -class QString; - -namespace Utils -{ - namespace Net - { - bool isValidIP(const QString &ip); - } -} - -#endif // BASE_UTILS_NET_H diff --git a/src/base/utils/random.cpp b/src/base/utils/random.cpp deleted file mode 100644 index add0b4e16..000000000 --- a/src/base/utils/random.cpp +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2017 Mike Tzou - * - * 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. - * - */ - -#include "random.h" - -#include -#include -#include - -#include - -#ifdef Q_OS_MAC -#include -#endif - -// on some platform `std::random_device` may generate the same number sequence -static bool hasTrueRandomDevice{ std::random_device{}() != std::random_device{}() }; - -uint32_t Utils::Random::rand(const uint32_t min, const uint32_t max) -{ -#ifdef Q_OS_MAC // workaround for Apple xcode: https://stackoverflow.com/a/29929949 - static QThreadStorage generator; - if (!generator.hasLocalData()) - generator.localData().seed( - hasTrueRandomDevice - ? std::random_device{}() - : (std::random_device::result_type) std::chrono::system_clock::now().time_since_epoch().count() - ); -#else - static thread_local std::mt19937 generator{ - hasTrueRandomDevice - ? std::random_device{}() - : static_cast(std::chrono::system_clock::now().time_since_epoch().count()) - }; -#endif - - // better replacement for `std::rand`, don't use this for real cryptography application - // min <= returned_value <= max - assert(min <= max); - - // new distribution is cheap: http://stackoverflow.com/a/19036349 - std::uniform_int_distribution uniform(min, max); - -#ifdef Q_OS_MAC - return uniform(generator.localData()); -#else - return uniform(generator); -#endif -} diff --git a/src/base/utils/random.h b/src/base/utils/random.h deleted file mode 100644 index d4198deca..000000000 --- a/src/base/utils/random.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2017 Mike Tzou - * - * 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. - * - */ - -#ifndef UTILS_RANDOM_H -#define UTILS_RANDOM_H - -#include -#include - -namespace Utils -{ - namespace Random - { - uint32_t rand(uint32_t min = 0, uint32_t max = UINT32_MAX); - } -} - -#endif // UTILS_FS_H diff --git a/src/base/utils/string.cpp b/src/base/utils/string.cpp deleted file mode 100644 index 302186753..000000000 --- a/src/base/utils/string.cpp +++ /dev/null @@ -1,191 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2015 Vladimir Golovnev - * Copyright (C) 2006 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. - */ - -#include "string.h" - -#include - -#include -#include -#include -#include -#include -#ifdef Q_OS_MAC -#include -#endif - -namespace -{ - class NaturalCompare - { - public: - explicit NaturalCompare(const bool caseSensitive = true) - : m_caseSensitive(caseSensitive) - { -#if defined(Q_OS_WIN) - // Without ICU library, QCollator uses the native API on Windows 7+. But that API - // sorts older versions of μTorrent differently than the newer ones because the - // 'μ' character is encoded differently and the native API can't cope with that. - // So default to using our custom natural sorting algorithm instead. - // See #5238 and #5240 - // Without ICU library, QCollator doesn't support `setNumericMode(true)` on OS older than Win7 - // if (QSysInfo::windowsVersion() < QSysInfo::WV_WINDOWS7) - return; -#endif - m_collator.setNumericMode(true); - m_collator.setCaseSensitivity(caseSensitive ? Qt::CaseSensitive : Qt::CaseInsensitive); - } - - bool operator()(const QString &left, const QString &right) const - { -#if defined(Q_OS_WIN) - // Without ICU library, QCollator uses the native API on Windows 7+. But that API - // sorts older versions of μTorrent differently than the newer ones because the - // 'μ' character is encoded differently and the native API can't cope with that. - // So default to using our custom natural sorting algorithm instead. - // See #5238 and #5240 - // Without ICU library, QCollator doesn't support `setNumericMode(true)` on OS older than Win7 - // if (QSysInfo::windowsVersion() < QSysInfo::WV_WINDOWS7) - return lessThan(left, right); -#endif - return (m_collator.compare(left, right) < 0); - } - - bool lessThan(const QString &left, const QString &right) const - { - // Return value `false` indicates `right` should go before `left`, otherwise, after - int posL = 0; - int posR = 0; - while (true) { - while (true) { - if ((posL == left.size()) || (posR == right.size())) - return (left.size() < right.size()); // when a shorter string is another string's prefix, shorter string place before longer string - - QChar leftChar = m_caseSensitive ? left[posL] : left[posL].toLower(); - QChar rightChar = m_caseSensitive ? right[posR] : right[posR].toLower(); - if (leftChar == rightChar) - ; // compare next character - else if (leftChar.isDigit() && rightChar.isDigit()) - break; // Both are digits, break this loop and compare numbers - else - return leftChar < rightChar; - - ++posL; - ++posR; - } - - int startL = posL; - while ((posL < left.size()) && left[posL].isDigit()) - ++posL; - int numL = left.midRef(startL, posL - startL).toInt(); - - int startR = posR; - while ((posR < right.size()) && right[posR].isDigit()) - ++posR; - int numR = right.midRef(startR, posR - startR).toInt(); - - if (numL != numR) - return (numL < numR); - - // Strings + digits do match and we haven't hit string end - // Do another round - } - return false; - } - - private: - QCollator m_collator; - const bool m_caseSensitive; - }; -} - -bool Utils::String::naturalCompareCaseSensitive(const QString &left, const QString &right) -{ - // provide a single `NaturalCompare` instance for easy use - // https://doc.qt.io/qt-5/threads-reentrancy.html -#ifdef Q_OS_MAC // workaround for Apple xcode: https://stackoverflow.com/a/29929949 - static QThreadStorage nCmp; - if (!nCmp.hasLocalData()) nCmp.setLocalData(NaturalCompare(true)); - return (nCmp.localData())(left, right); -#else - thread_local NaturalCompare nCmp(true); - return nCmp(left, right); -#endif -} - -bool Utils::String::naturalCompareCaseInsensitive(const QString &left, const QString &right) -{ - // provide a single `NaturalCompare` instance for easy use - // https://doc.qt.io/qt-5/threads-reentrancy.html -#ifdef Q_OS_MAC // workaround for Apple xcode: https://stackoverflow.com/a/29929949 - static QThreadStorage nCmp; - if (!nCmp.hasLocalData()) nCmp.setLocalData(NaturalCompare(false)); - return (nCmp.localData())(left, right); -#else - thread_local NaturalCompare nCmp(false); - return nCmp(left, right); -#endif -} - -// to send numbers instead of strings with suffixes -QString Utils::String::fromDouble(double n, int precision) -{ - /* HACK because QString rounds up. Eg QString::number(0.999*100.0, 'f' ,1) == 99.9 - ** but QString::number(0.9999*100.0, 'f' ,1) == 100.0 The problem manifests when - ** the number has more digits after the decimal than we want AND the digit after - ** our 'wanted' is >= 5. In this case our last digit gets rounded up. So for each - ** precision we add an extra 0 behind 1 in the below algorithm. */ - - double prec = std::pow(10.0, precision); - return QLocale::system().toString(std::floor(n * prec) / prec, 'f', precision); -} - -// Implements constant-time comparison to protect against timing attacks -// Taken from https://crackstation.net/hashing-security.htm -bool Utils::String::slowEquals(const QByteArray &a, const QByteArray &b) -{ - int lengthA = a.length(); - int lengthB = b.length(); - - int diff = lengthA ^ lengthB; - for (int i = 0; (i < lengthA) && (i < lengthB); i++) - diff |= a[i] ^ b[i]; - - return (diff == 0); -} - -// This is marked as internal in QRegExp.cpp, but is exported. The alternative would be to -// copy the code from QRegExp::wc2rx(). -QString qt_regexp_toCanonical(const QString &pattern, QRegExp::PatternSyntax patternSyntax); - -QString Utils::String::wildcardToRegex(const QString &pattern) -{ - return qt_regexp_toCanonical(pattern, QRegExp::Wildcard); -} - diff --git a/src/base/utils/string.h b/src/base/utils/string.h deleted file mode 100644 index e5257de14..000000000 --- a/src/base/utils/string.h +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2015 Vladimir Golovnev - * Copyright (C) 2006 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. - */ - -#ifndef UTILS_STRING_H -#define UTILS_STRING_H - -#include - -class QByteArray; -class QLatin1String; - -namespace Utils -{ - namespace String - { - QString fromDouble(double n, int precision); - - // Implements constant-time comparison to protect against timing attacks - // Taken from https://crackstation.net/hashing-security.htm - bool slowEquals(const QByteArray &a, const QByteArray &b); - - bool naturalCompareCaseSensitive(const QString &left, const QString &right); - bool naturalCompareCaseInsensitive(const QString &left, const QString &right); - - QString wildcardToRegex(const QString &pattern); - - template - T unquote(const T &str, const QString "es = QLatin1String("\"")) - { - if (str.length() < 2) return str; - - for (auto const quote : quotes) { - if (str.startsWith(quote) && str.endsWith(quote)) - return str.mid(1, str.length() - 2); - } - - return str; - } - } -} - -#endif // UTILS_STRING_H diff --git a/src/base/utils/version.h b/src/base/utils/version.h deleted file mode 100644 index aa1be88d1..000000000 --- a/src/base/utils/version.h +++ /dev/null @@ -1,195 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2016 Eugene Shalygin - * - * 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. - */ - -#ifndef QBITTORRENT_UTILS_VERSION_H -#define QBITTORRENT_UTILS_VERSION_H - -#include -#include - -#include -#include -#include - -namespace Utils -{ - template - class Version - { - static_assert(N > 0, "The number of version components may not be smaller than 1"); - static_assert(N >= Mandatory, - "The number of mandatory components may not be larger than the total number of components"); - - public: - typedef T ComponentType; - typedef Version ThisType; - - constexpr Version() - : m_components {} - { - } - - constexpr Version(const ThisType &other) = default; - - template - constexpr Version(Other ... components) - : m_components {{components ...}} - { - } - - /** - * @brief Creates version from string in format "x.y.z" - * - * @param version Version string in format "x.y.z" - * @throws std::runtime_error if parsing fails - */ - Version(const QString &version) - : Version {version.split(QLatin1Char('.'))} - { - } - - /** - * @brief Creates version from byte array in format "x.y.z" - * - * @param version Version string in format "x.y.z" - * @throws std::runtime_error if parsing fails - */ - Version(const QByteArray &version) - : Version {version.split('.')} - { - } - - ComponentType majorNumber() const - { - static_assert(N >= 1, "The number of version components is too small"); - return (*this)[0]; - } - - ComponentType minorNumber() const - { - static_assert(N >= 2, "The number of version components is too small"); - return (*this)[1]; - } - - ComponentType revisionNumber() const - { - static_assert(N >= 3, "The number of version components is too small"); - return (*this)[2]; - } - - ComponentType patchNumber() const - { - static_assert(N >= 4, "The number of version components is too small"); - return (*this)[3]; - } - - ComponentType operator[](std::size_t i) const - { - return m_components.at(i); - } - - operator QString() const - { - // find the last one non-zero component - std::size_t lastSignificantIndex = N - 1; - while (lastSignificantIndex >= 0 && (*this)[lastSignificantIndex] == 0) - --lastSignificantIndex; - - if (lastSignificantIndex + 1 < Mandatory) // lastSignificantIndex >= 0 - lastSignificantIndex = Mandatory - 1; // and Mandatory >= 1 - - QString res = QString::number((*this)[0]); - for (std::size_t i = 1; i <= lastSignificantIndex; ++i) - res += QLatin1Char('.') + QString::number((*this)[i]); - return res; - } - - bool operator==(const ThisType &other) const - { - return m_components == other.m_components; - } - - bool operator<(const ThisType &other) const - { - return m_components < other.m_components; - } - - bool operator>(const ThisType &other) const - { - return m_components > other.m_components; - } - - template - static Version tryParse(const StringClassWithSplitMethod &s, const Version &defaultVersion) - { - try { - return Version(s); - } - catch (std::runtime_error &er) { - qDebug() << "Error parsing version:" << er.what(); - return defaultVersion; - } - } - - private: - using ComponentsArray = std::array; - - template - static ComponentsArray parseList(const StringsList &versionParts) - { - if ((static_cast(versionParts.size()) > N) - || (static_cast(versionParts.size()) < Mandatory)) - throw std::runtime_error ("Incorrect number of version components"); - - bool ok = false; - ComponentsArray res{}; - for (std::size_t i = 0; i < static_cast(versionParts.size()); ++i) { - res[i] = static_cast(versionParts[i].toInt(&ok)); - if (!ok) - throw std::runtime_error("Can not parse version component"); - } - return res; - } - - template - Version(const StringsList &versionParts) - : m_components (parseList(versionParts)) // GCC 4.8.4 has problems with the uniform initializer here - { - } - - ComponentsArray m_components; - }; - - template - inline bool operator!=(const Version &left, const Version &right) - { - return !(left == right); - } -} - -#endif // QBITTORRENT_UTILS_VERSION_H diff --git a/src/config.h.cmakein b/src/config.h.cmakein deleted file mode 100644 index 5d6a30c32..000000000 --- a/src/config.h.cmakein +++ /dev/null @@ -1,14 +0,0 @@ -#cmakedefine QBT_USE_GUI - -#ifndef QBT_USE_GUI -#define DISABLE_GUI -#define DISABLE_COUNTRIES_RESOLUTION -#endif - -#cmakedefine QBT_USE_WEBUI - -#ifndef QBT_USE_WEBUI -#define DISABLE_WEBUI -#endif - -#cmakedefine STACKTRACE_WIN diff --git a/src/gui/CMakeLists.txt b/src/gui/CMakeLists.txt deleted file mode 100644 index 3b9f18838..000000000 --- a/src/gui/CMakeLists.txt +++ /dev/null @@ -1,159 +0,0 @@ -set(CMAKE_AUTORCC True) -set(CMAKE_AUTOUIC True) - -include_directories(${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}) - -add_subdirectory(lineedit) -add_subdirectory(properties) -add_subdirectory(powermanagement) -add_subdirectory(rss) -add_subdirectory(search) - -if (UNIX AND NOT APPLE AND DBUS) - add_subdirectory(qtnotify) - include_directories(qtnotify) - list(APPEND QBT_GUI_OPTIONAL_LINK_LIBRARIES qbt_qtnotify) -endif (UNIX AND NOT APPLE AND DBUS) - -include_directories( -${CMAKE_CURRENT_BINARY_DIR}/properties -${CMAKE_CURRENT_BINARY_DIR}/rss -${CMAKE_CURRENT_BINARY_DIR}/search -lineedit/src -powermanagement -properties -rss -../app -) - -set(QBT_GUI_HEADERS -about_imp.h -addnewtorrentdialog.h -advancedsettings.h -advancedsettings.h -autoexpandabledialog.h -banlistoptions.h -categoryfiltermodel.h -categoryfilterproxymodel.h -categoryfilterwidget.h -cookiesdialog.h -cookiesmodel.h -deletionconfirmationdlg.h -downloadfromurldlg.h -executionlog.h -fspathedit.h -fspathedit_p.h -guiiconprovider.h -hidabletabwidget.h -loglistwidget.h -mainwindow.h -messageboxraised.h -optionsdlg.h -previewlistdelegate.h -previewselect.h -scanfoldersdelegate.h -shutdownconfirmdlg.h -speedlimitdlg.h -statsdialog.h -statusbar.h -tagfiltermodel.h -tagfilterproxymodel.h -tagfilterwidget.h -torrentcontentfiltermodel.h -torrentcontentmodel.h -torrentcontentmodelfile.h -torrentcontentmodelfolder.h -torrentcontentmodelitem.h -torrentcontenttreeview.h -torrentcreatordlg.h -torrentmodel.h -trackerlogin.h -transferlistdelegate.h -transferlistfilterswidget.h -transferlistsortmodel.h -transferlistwidget.h -updownratiodlg.h -) - -set(QBT_GUI_SOURCES -addnewtorrentdialog.cpp -advancedsettings.cpp -autoexpandabledialog.cpp -banlistoptions.cpp -categoryfiltermodel.cpp -categoryfilterproxymodel.cpp -categoryfilterwidget.cpp -cookiesdialog.cpp -cookiesmodel.cpp -executionlog.cpp -fspathedit.cpp -fspathedit_p.cpp -guiiconprovider.cpp -loglistwidget.cpp -mainwindow.cpp -messageboxraised.cpp -optionsdlg.cpp -previewselect.cpp -scanfoldersdelegate.cpp -shutdownconfirmdlg.cpp -speedlimitdlg.cpp -statsdialog.cpp -statusbar.cpp -tagfiltermodel.cpp -tagfilterproxymodel.cpp -tagfilterwidget.cpp -torrentcontentfiltermodel.cpp -torrentcontentmodel.cpp -torrentcontentmodelfile.cpp -torrentcontentmodelfolder.cpp -torrentcontentmodelitem.cpp -torrentcontenttreeview.cpp -torrentcreatordlg.cpp -torrentmodel.cpp -trackerlogin.cpp -transferlistdelegate.cpp -transferlistfilterswidget.cpp -transferlistsortmodel.cpp -transferlistwidget.cpp -updownratiodlg.cpp -) - -if (WIN32 OR APPLE) - list(APPEND QBT_GUI_HEADERS programupdater.h) - list(APPEND QBT_GUI_SOURCES programupdater.cpp) -endif (WIN32 OR APPLE) - -set(QBT_GUI_FORMS -mainwindow.ui -about.ui -banlistoptions.ui -cookiesdialog.ui -preview.ui -login.ui -downloadfromurldlg.ui -bandwidth_limit.ui -updownratiodlg.ui -confirmdeletiondlg.ui -executionlog.ui -addnewtorrentdialog.ui -autoexpandabledialog.ui -statsdialog.ui -optionsdlg.ui -torrentcreatordlg.ui -shutdownconfirmdlg.ui -) - -qbt_target_sources(about.qrc) - -add_library(qbt_gui STATIC ${QBT_GUI_HEADERS} ${QBT_GUI_SOURCES} ${QBT_GUI_FORMS}) -target_link_libraries(qbt_gui qbt_lineedit qbt_powermanagement qbt_rss qbt_properties qbt_searchengine - ${QBT_GUI_OPTIONAL_LINK_LIBRARIES} qbt_base - QtSingleApplication::QtSingleApplication -) -if(WIN32) - target_link_libraries(qbt_gui Qt5::WinExtras) -endif(WIN32) - -if (APPLE) - target_link_libraries(qbt_gui Qt5::MacExtras) -endif() diff --git a/src/gui/about.qrc b/src/gui/about.qrc deleted file mode 100644 index da886b454..000000000 --- a/src/gui/about.qrc +++ /dev/null @@ -1,7 +0,0 @@ - - - gpl.html - thanks.html - translators.html - - diff --git a/src/gui/about.ui b/src/gui/about.ui deleted file mode 100644 index 41028ba5d..000000000 --- a/src/gui/about.ui +++ /dev/null @@ -1,461 +0,0 @@ - - - Christophe Dumez - AboutDlg - - - - 0 - 0 - 545 - 295 - - - - About qBittorrent - - - - - - - - :/icons/skin/qbittorrent32.png - - - - - - - qBittorrent - - - - - - - Qt::Horizontal - - - - 0 - 0 - - - - - - - - - - 0 - - - - About - - - - - - :/icons/skin/mascot.png - - - - - - - - 0 - 0 - - - - Qt::RichText - - - true - - - true - - - - - - - - Author - - - - - - Current maintainer - - - - - - Greece - - - - - - - <a href="mailto:sledgehammer999@qbittorrent.org">sledgehammer999@qbittorrent.org</a> - - - true - - - Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse - - - - - - - Nationality: - - - - - - - E-mail: - - - - - - - Name: - - - - - - - Sledgehammer999 - - - - - - - Qt::Horizontal - - - - 0 - 0 - - - - - - - - - - - Original author - - - - - - France - - - - - - - Christophe Dumez - - - - - - - <a href="mailto:chris@qbittorrent.org">chris@qbittorrent.org</a> - - - true - - - Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse - - - - - - - Name: - - - - - - - E-mail: - - - - - - - Nationality: - - - - - - - Qt::Horizontal - - - - 0 - 0 - - - - - - - - - - - Qt::Vertical - - - - 0 - 0 - - - - - - - - - Special Thanks - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - true - - - - - - - - Translators - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - QTextEdit::NoWrap - - - - - - - - License - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - - - - - Libraries - - - - - - qBittorrent was built with the following libraries: - - - - - - - Qt::Horizontal - - - - - - - - - Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse - - - - - - - Qt::Horizontal - - - - 0 - 0 - - - - - - - - Qt: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse - - - - - - - Libtorrent: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse - - - - - - - Boost: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse - - - - - - - Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse - - - - - - - Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse - - - - - - - Qt::Horizontal - - - - 0 - 0 - - - - - - - - - - Qt::Horizontal - - - - - - - Qt::Vertical - - - - 0 - 0 - - - - - - - - - - - - - - - - diff --git a/src/gui/about_imp.h b/src/gui/about_imp.h deleted file mode 100644 index 2ff663edc..000000000 --- a/src/gui/about_imp.h +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Bittorrent Client using Qt4 and libtorrent. - * Copyright (C) 2006 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 ABOUT_H -#define ABOUT_H - -#include "ui_about.h" -#include -#include "base/utils/misc.h" -#include "base/unicodestrings.h" - -class about: public QDialog, private Ui::AboutDlg -{ - Q_OBJECT - -public: - about(QWidget *parent) : QDialog(parent) - { - setupUi(this); - setAttribute(Qt::WA_DeleteOnClose); - - // Title -#if defined(__x86_64__) || defined(_M_X64) - lb_name->setText("

qBittorrent " QBT_VERSION " (64-bit)

"); -#else - lb_name->setText("

qBittorrent " QBT_VERSION " (32-bit)

"); -#endif - - // About - QString aboutText = QString( - "

" - "%1\n\n" - "%2\n\n" - "" - "" - "" - "" - "
%3http://www.qbittorrent.org
%4http://forum.qbittorrent.org
%5http://bugs.qbittorrent.org
" - "

") - .arg(tr("An advanced BitTorrent client programmed in C++, based on Qt toolkit and libtorrent-rasterbar.")) - .arg(tr("Copyright %1 2006-2017 The qBittorrent project").arg(QString::fromUtf8(C_COPYRIGHT))) - .arg(tr("Home Page:")) - .arg(tr("Forum:")) - .arg(tr("Bug Tracker:")); - lb_about->setText(aboutText); - - // Thanks - QFile thanksfile(":/thanks.html"); - if (thanksfile.open(QIODevice::ReadOnly | QIODevice::Text)) { - te_thanks->setHtml(QString::fromUtf8(thanksfile.readAll().constData())); - thanksfile.close(); - } - - // Translation - QFile translatorsfile(":/translators.html"); - if (translatorsfile.open(QIODevice::ReadOnly | QIODevice::Text)) { - te_translation->setHtml(QString::fromUtf8(translatorsfile.readAll().constData())); - translatorsfile.close(); - } - - // License - QFile licensefile(":/gpl.html"); - if (licensefile.open(QIODevice::ReadOnly | QIODevice::Text)) { - te_license->setHtml(QString::fromUtf8(licensefile.readAll().constData())); - licensefile.close(); - } - - // Libraries - label_11->setText(QT_VERSION_STR); - label_12->setText(Utils::Misc::libtorrentVersionString()); - label_13->setText(Utils::Misc::boostVersionString()); - - show(); - } -}; - -#endif diff --git a/src/gui/addnewtorrentdialog.cpp b/src/gui/addnewtorrentdialog.cpp deleted file mode 100644 index bcbfb6537..000000000 --- a/src/gui/addnewtorrentdialog.cpp +++ /dev/null @@ -1,790 +0,0 @@ -/* - * Bittorrent Client using Qt 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 -#include -#include -#include -#include -#include -#include - -#include "base/preferences.h" -#include "base/settingsstorage.h" -#include "base/net/downloadmanager.h" -#include "base/net/downloadhandler.h" -#include "base/bittorrent/session.h" -#include "base/bittorrent/magneturi.h" -#include "base/bittorrent/torrentinfo.h" -#include "base/bittorrent/torrenthandle.h" -#include "base/utils/fs.h" -#include "base/utils/misc.h" -#include "base/utils/string.h" -#include "base/torrentfileguard.h" -#include "base/unicodestrings.h" -#include "guiiconprovider.h" -#include "autoexpandabledialog.h" -#include "messageboxraised.h" -#include "proplistdelegate.h" -#include "torrentcontentmodel.h" -#include "torrentcontentfiltermodel.h" -#include "ui_addnewtorrentdialog.h" -#include "addnewtorrentdialog.h" - -#define SETTINGS_KEY(name) "AddNewTorrentDialog/" name -const QString KEY_ENABLED = SETTINGS_KEY("Enabled"); -const QString KEY_DEFAULTCATEGORY = SETTINGS_KEY("DefaultCategory"); -const QString KEY_TREEHEADERSTATE = SETTINGS_KEY("TreeHeaderState"); -const QString KEY_WIDTH = SETTINGS_KEY("Width"); -const QString KEY_EXPANDED = SETTINGS_KEY("Expanded"); -const QString KEY_TOPLEVEL = SETTINGS_KEY("TopLevel"); -const QString KEY_SAVEPATHHISTORY = SETTINGS_KEY("SavePathHistory"); - -namespace -{ - // just a shortcut - inline SettingsStorage *settings() - { - return SettingsStorage::instance(); - } -} - -AddNewTorrentDialog::AddNewTorrentDialog(const BitTorrent::AddTorrentParams &inParams, QWidget *parent) - : QDialog(parent) - , ui(new Ui::AddNewTorrentDialog) - , m_contentModel(nullptr) - , m_contentDelegate(nullptr) - , m_hasMetadata(false) - , m_oldIndex(0) - , m_torrentParams(inParams) -{ - // TODO: set dialog file properties using m_torrentParams.filePriorities - ui->setupUi(this); - setAttribute(Qt::WA_DeleteOnClose); - ui->lblMetaLoading->setVisible(false); - ui->progMetaLoading->setVisible(false); - - ui->savePath->setMode(FileSystemPathEdit::Mode::DirectorySave); - ui->savePath->setDialogCaption(tr("Choose save path")); - - auto session = BitTorrent::Session::instance(); - - if (m_torrentParams.addPaused == TriStateBool::True) - ui->startTorrentCheckBox->setChecked(false); - else if (m_torrentParams.addPaused == TriStateBool::False) - ui->startTorrentCheckBox->setChecked(true); - else - ui->startTorrentCheckBox->setChecked(!session->isAddTorrentPaused()); - - ui->comboTTM->blockSignals(true); // the TreeView size isn't correct if the slot does it job at this point - ui->comboTTM->setCurrentIndex(!session->isAutoTMMDisabledByDefault()); - ui->comboTTM->blockSignals(false); - populateSavePathComboBox(); - connect(ui->savePath, &FileSystemPathEdit::selectedPathChanged, this, &AddNewTorrentDialog::onSavePathChanged); - ui->defaultSavePathCheckBox->setVisible(false); // Default path is selected by default - - if (m_torrentParams.createSubfolder == TriStateBool::True) - ui->createSubfolderCheckBox->setChecked(true); - else if (m_torrentParams.createSubfolder == TriStateBool::False) - ui->createSubfolderCheckBox->setChecked(false); - else - ui->createSubfolderCheckBox->setChecked(session->isCreateTorrentSubfolder()); - - ui->skipCheckingCheckBox->setChecked(m_torrentParams.skipChecking); - ui->doNotDeleteTorrentCheckBox->setVisible(TorrentFileGuard::autoDeleteMode() != TorrentFileGuard::Never); - - // Load categories - QStringList categories = session->categories(); - std::sort(categories.begin(), categories.end(), Utils::String::naturalCompareCaseInsensitive); - QString defaultCategory = settings()->loadValue(KEY_DEFAULTCATEGORY).toString(); - - if (!m_torrentParams.category.isEmpty()) - ui->categoryComboBox->addItem(m_torrentParams.category); - if (!defaultCategory.isEmpty()) - ui->categoryComboBox->addItem(defaultCategory); - ui->categoryComboBox->addItem(""); - - foreach (const QString &category, categories) - if (category != defaultCategory && category != m_torrentParams.category) - ui->categoryComboBox->addItem(category); - - ui->contentTreeView->header()->setSortIndicator(0, Qt::AscendingOrder); - loadState(); - // Signal / slots - connect(ui->adv_button, SIGNAL(clicked(bool)), SLOT(showAdvancedSettings(bool))); - connect(ui->doNotDeleteTorrentCheckBox, SIGNAL(clicked(bool)), SLOT(doNotDeleteTorrentClicked(bool))); - QShortcut *editHotkey = new QShortcut(Qt::Key_F2, ui->contentTreeView, 0, 0, Qt::WidgetShortcut); - connect(editHotkey, SIGNAL(activated()), SLOT(renameSelectedFile())); - connect(ui->contentTreeView, SIGNAL(doubleClicked(QModelIndex)), SLOT(renameSelectedFile())); - - ui->buttonBox->button(QDialogButtonBox::Ok)->setFocus(); -} - -AddNewTorrentDialog::~AddNewTorrentDialog() -{ - saveState(); - - delete m_contentDelegate; - delete ui; -} - -bool AddNewTorrentDialog::isEnabled() -{ - return SettingsStorage::instance()->loadValue(KEY_ENABLED, true).toBool(); -} - -void AddNewTorrentDialog::setEnabled(bool value) -{ - SettingsStorage::instance()->storeValue(KEY_ENABLED, value); -} - -bool AddNewTorrentDialog::isTopLevel() -{ - return SettingsStorage::instance()->loadValue(KEY_TOPLEVEL, true).toBool(); -} - -void AddNewTorrentDialog::setTopLevel(bool value) -{ - SettingsStorage::instance()->storeValue(KEY_TOPLEVEL, value); -} - -void AddNewTorrentDialog::loadState() -{ - m_headerState = settings()->loadValue(KEY_TREEHEADERSTATE).toByteArray(); - int width = settings()->loadValue(KEY_WIDTH, -1).toInt(); - QSize geo = size(); - geo.setWidth(width); - resize(geo); - - ui->adv_button->setChecked(settings()->loadValue(KEY_EXPANDED).toBool()); -} - -void AddNewTorrentDialog::saveState() -{ - if (m_contentModel) - settings()->storeValue(KEY_TREEHEADERSTATE, ui->contentTreeView->header()->saveState()); - settings()->storeValue(KEY_WIDTH, width()); - settings()->storeValue(KEY_EXPANDED, ui->adv_button->isChecked()); -} - -void AddNewTorrentDialog::show(QString source, const BitTorrent::AddTorrentParams &inParams, QWidget *parent) -{ - AddNewTorrentDialog *dlg = new AddNewTorrentDialog(inParams, parent); - - if (Utils::Misc::isUrl(source)) { - // Launch downloader - Net::DownloadHandler *handler = Net::DownloadManager::instance()->downloadUrl(source, true, 10485760 /* 10MB */, true); - connect(handler, SIGNAL(downloadFinished(QString,QString)), dlg, SLOT(handleDownloadFinished(QString,QString))); - connect(handler, SIGNAL(downloadFailed(QString,QString)), dlg, SLOT(handleDownloadFailed(QString,QString))); - connect(handler, SIGNAL(redirectedToMagnet(QString,QString)), dlg, SLOT(handleRedirectedToMagnet(QString,QString))); - } - else { - bool ok = false; - BitTorrent::MagnetUri magnetUri(source); - if (magnetUri.isValid()) - ok = dlg->loadMagnet(magnetUri); - else - ok = dlg->loadTorrent(source); - - if (ok) -#ifdef Q_OS_MAC - dlg->exec(); -#else - dlg->open(); -#endif - else - delete dlg; - } -} - -void AddNewTorrentDialog::show(QString source, QWidget *parent) -{ - show(source, BitTorrent::AddTorrentParams(), parent); -} - -bool AddNewTorrentDialog::loadTorrent(const QString &torrentPath) -{ - if (torrentPath.startsWith("file://", Qt::CaseInsensitive)) - m_filePath = QUrl::fromEncoded(torrentPath.toLocal8Bit()).toLocalFile(); - else - m_filePath = torrentPath; - - if (!QFile::exists(m_filePath)) { - MessageBoxRaised::critical(this, tr("I/O Error"), tr("The torrent file '%1' does not exist.").arg(Utils::Fs::toNativePath(m_filePath))); - return false; - } - - QFileInfo fileinfo(m_filePath); - if (!fileinfo.isReadable()) { - MessageBoxRaised::critical(this, tr("I/O Error"), tr("The torrent file '%1' cannot be read from the disk. Probably you don't have enough permissions.").arg(Utils::Fs::toNativePath(m_filePath))); - return false; - } - - m_hasMetadata = true; - QString error; - m_torrentInfo = BitTorrent::TorrentInfo::loadFromFile(m_filePath, error); - if (!m_torrentInfo.isValid()) { - MessageBoxRaised::critical(this, tr("Invalid torrent"), tr("Failed to load the torrent: %1.\nError: %2", "Don't remove the '\n' characters. They insert a newline.").arg(Utils::Fs::toNativePath(m_filePath)).arg(error)); - return false; - } - - m_torrentGuard.reset(new TorrentFileGuard(m_filePath)); - m_hash = m_torrentInfo.hash(); - - // Prevent showing the dialog if download is already present - if (BitTorrent::Session::instance()->isKnownTorrent(m_hash)) { - BitTorrent::TorrentHandle *const torrent = BitTorrent::Session::instance()->findTorrent(m_hash); - if (torrent) { - if (torrent->isPrivate() || m_torrentInfo.isPrivate()) { - MessageBoxRaised::critical(this, tr("Already in download list"), tr("Torrent is already in download list. Trackers weren't merged because it is a private torrent."), QMessageBox::Ok); - } - else { - torrent->addTrackers(m_torrentInfo.trackers()); - torrent->addUrlSeeds(m_torrentInfo.urlSeeds()); - MessageBoxRaised::information(this, tr("Already in download list"), tr("Torrent is already in download list. Trackers were merged."), QMessageBox::Ok); - } - } - else { - MessageBoxRaised::critical(this, tr("Cannot add torrent"), tr("Cannot add this torrent. Perhaps it is already in adding state."), QMessageBox::Ok); - } - return false; - } - - ui->lblhash->setText(m_hash); - setupTreeview(); - TMMChanged(ui->comboTTM->currentIndex()); - return true; -} - -bool AddNewTorrentDialog::loadMagnet(const BitTorrent::MagnetUri &magnetUri) -{ - if (!magnetUri.isValid()) { - MessageBoxRaised::critical(this, tr("Invalid magnet link"), tr("This magnet link was not recognized")); - return false; - } - - m_torrentGuard.reset(new TorrentFileGuard(QString())); - m_hash = magnetUri.hash(); - // Prevent showing the dialog if download is already present - if (BitTorrent::Session::instance()->isKnownTorrent(m_hash)) { - BitTorrent::TorrentHandle *const torrent = BitTorrent::Session::instance()->findTorrent(m_hash); - if (torrent) { - if (torrent->isPrivate()) { - MessageBoxRaised::critical(this, tr("Already in download list"), tr("Torrent is already in download list. Trackers weren't merged because it is a private torrent."), QMessageBox::Ok); - } - else { - torrent->addTrackers(magnetUri.trackers()); - torrent->addUrlSeeds(magnetUri.urlSeeds()); - MessageBoxRaised::information(this, tr("Already in download list"), tr("Magnet link is already in download list. Trackers were merged."), QMessageBox::Ok); - } - } - else { - MessageBoxRaised::critical(this, tr("Cannot add torrent"), tr("Cannot add this torrent. Perhaps it is already in adding."), QMessageBox::Ok); - } - return false; - } - - connect(BitTorrent::Session::instance(), SIGNAL(metadataLoaded(BitTorrent::TorrentInfo)), SLOT(updateMetadata(BitTorrent::TorrentInfo))); - - // Set dialog title - QString torrent_name = magnetUri.name(); - setWindowTitle(torrent_name.isEmpty() ? tr("Magnet link") : torrent_name); - - setupTreeview(); - TMMChanged(ui->comboTTM->currentIndex()); - - BitTorrent::Session::instance()->loadMetadata(magnetUri); - setMetadataProgressIndicator(true, tr("Retrieving metadata...")); - ui->lblhash->setText(m_hash); - - return true; -} - -void AddNewTorrentDialog::showEvent(QShowEvent *event) -{ - QDialog::showEvent(event); - if (!isTopLevel()) return; - - activateWindow(); - raise(); -} - -void AddNewTorrentDialog::showAdvancedSettings(bool show) -{ - const int minimumW = minimumWidth(); - setMinimumWidth(width()); // to remain the same width - if (show) { - ui->adv_button->setText(QString::fromUtf8(C_UP)); - ui->settings_group->setVisible(true); - ui->infoGroup->setVisible(true); - ui->contentTreeView->setVisible(m_hasMetadata); - static_cast(layout())->insertWidget(layout()->indexOf(ui->never_show_cb) + 1, ui->adv_button); - } - else { - ui->adv_button->setText(QString::fromUtf8(C_DOWN)); - ui->settings_group->setVisible(false); - ui->infoGroup->setVisible(false); - ui->buttonsHLayout->insertWidget(0, layout()->takeAt(layout()->indexOf(ui->never_show_cb) + 1)->widget()); - } - adjustSize(); - setMinimumWidth(minimumW); -} - -void AddNewTorrentDialog::saveSavePathHistory() const -{ - QDir selectedSavePath(ui->savePath->selectedPath()); - // Get current history - QStringList history = settings()->loadValue(KEY_SAVEPATHHISTORY).toStringList(); - QList historyDirs; - foreach (const QString dir, history) - historyDirs << QDir(dir); - if (!historyDirs.contains(selectedSavePath)) { - // Add save path to history - history.push_front(selectedSavePath.absolutePath()); - // Limit list size - if (history.size() > 8) - history.pop_back(); - // Save history - settings()->storeValue(KEY_SAVEPATHHISTORY, 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->savePath->count(); ++i) - if (QDir(ui->savePath->item(i)) == saveDir) - return i; - return -1; -} - -void AddNewTorrentDialog::updateDiskSpaceLabel() -{ - // Determine torrent size - qulonglong torrent_size = 0; - - if (m_hasMetadata) { - if (m_contentModel) { - const QVector priorities = m_contentModel->model()->getFilePriorities(); - Q_ASSERT(priorities.size() == m_torrentInfo.filesCount()); - for (int i = 0; i < priorities.size(); ++i) - if (priorities[i] > 0) - torrent_size += m_torrentInfo.fileSize(i); - } - else { - torrent_size = m_torrentInfo.totalSize(); - } - } - - QString size_string = torrent_size ? Utils::Misc::friendlyUnit(torrent_size) : QString(tr("Not Available", "This size is unavailable.")); - size_string += " ("; - size_string += tr("Free space on disk: %1").arg(Utils::Misc::friendlyUnit(Utils::Fs::freeDiskSpaceOnPath( - ui->savePath->selectedPath()))); - size_string += ")"; - ui->size_lbl->setText(size_string); -} - -void AddNewTorrentDialog::onSavePathChanged(const QString &newPath) -{ - // Toggle default save path setting checkbox visibility - ui->defaultSavePathCheckBox->setChecked(false); - ui->defaultSavePathCheckBox->setVisible(QDir(newPath) != QDir(BitTorrent::Session::instance()->defaultSavePath())); - // Remember index - m_oldIndex = ui->savePath->currentIndex(); - updateDiskSpaceLabel(); -} - -void AddNewTorrentDialog::categoryChanged(int index) -{ - Q_UNUSED(index); - - if (ui->comboTTM->currentIndex() == 1) { - QString savePath = BitTorrent::Session::instance()->categorySavePath(ui->categoryComboBox->currentText()); - ui->savePath->setSelectedPath(Utils::Fs::toNativePath(savePath)); - } -} - -void AddNewTorrentDialog::setSavePath(const QString &newPath) -{ - int existingIndex = indexOfSavePath(newPath); - if (existingIndex < 0) { - // New path, prepend to combo box - ui->savePath->insertItem(0, newPath); - existingIndex = 0; - } - ui->savePath->setCurrentIndex(existingIndex); - onSavePathChanged(newPath); -} - -void AddNewTorrentDialog::renameSelectedFile() -{ - const QModelIndexList selectedIndexes = ui->contentTreeView->selectionModel()->selectedRows(0); - if (selectedIndexes.size() != 1) return; - - const QModelIndex modelIndex = selectedIndexes.first(); - if (!modelIndex.isValid()) return; - - // Ask for new name - bool ok = false; - QString newName = AutoExpandableDialog::getText(this, tr("Renaming"), tr("New name:"), QLineEdit::Normal, modelIndex.data().toString(), &ok) - .trimmed(); - if (!ok) return; - - if (newName.isEmpty() || !Utils::Fs::isValidFileSystemName(newName)) { - MessageBoxRaised::warning(this, tr("Rename error"), - tr("The name is empty or contains forbidden characters, please choose a different one."), - QMessageBox::Ok); - return; - } - - if (m_contentModel->itemType(modelIndex) == TorrentContentModelItem::FileType) { - // renaming a file - const int fileIndex = m_contentModel->getFileIndex(modelIndex); - - if (newName.endsWith(QB_EXT)) - newName.chop(QB_EXT.size()); - const QString oldFileName = m_torrentInfo.fileName(fileIndex); - const QString oldFilePath = m_torrentInfo.filePath(fileIndex); - const QString newFilePath = oldFilePath.leftRef(oldFilePath.size() - oldFileName.size()) + newName; - - if (oldFileName == newName) { - qDebug("Name did not change: %s", qPrintable(oldFileName)); - return; - } - - // check if that name is already used - for (int i = 0; i < m_torrentInfo.filesCount(); ++i) { - if (i == fileIndex) continue; - if (Utils::Fs::sameFileNames(m_torrentInfo.filePath(i), newFilePath)) { - MessageBoxRaised::warning(this, tr("Rename error"), - tr("This name is already in use in this folder. Please use a different name."), - QMessageBox::Ok); - return; - } - } - - qDebug("Renaming %s to %s", qPrintable(oldFilePath), qPrintable(newFilePath)); - m_torrentInfo.renameFile(fileIndex, newFilePath); - - m_contentModel->setData(modelIndex, newName); - } - else { - // renaming a folder - QStringList pathItems; - pathItems << modelIndex.data().toString(); - QModelIndex parent = m_contentModel->parent(modelIndex); - while (parent.isValid()) { - pathItems.prepend(parent.data().toString()); - parent = m_contentModel->parent(parent); - } - const QString oldPath = pathItems.join("/"); - pathItems.removeLast(); - pathItems << newName; - QString newPath = pathItems.join("/"); - if (Utils::Fs::sameFileNames(oldPath, newPath)) { - qDebug("Name did not change"); - return; - } - if (!newPath.endsWith("/")) newPath += "/"; - // Check for overwriting - for (int i = 0; i < m_torrentInfo.filesCount(); ++i) { - const QString ¤tName = m_torrentInfo.filePath(i); -#if defined(Q_OS_UNIX) || defined(Q_WS_QWS) - if (currentName.startsWith(newPath, Qt::CaseSensitive)) { -#else - if (currentName.startsWith(newPath, 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.filesCount(); ++i) { - const QString ¤tName = m_torrentInfo.filePath(i); - if (currentName.startsWith(oldPath)) { - QString newName = currentName; - newName.replace(0, oldPath.length(), newPath); - newName = Utils::Fs::expandPath(newName); - qDebug("Rename %s to %s", qPrintable(currentName), qPrintable(newName)); - m_torrentInfo.renameFile(i, newName); - } - } - - // Rename folder in torrent files model too - m_contentModel->setData(modelIndex, newName); - } -} - -void AddNewTorrentDialog::populateSavePathComboBox() -{ - QString defSavePath = BitTorrent::Session::instance()->defaultSavePath(); - - ui->savePath->clear(); - ui->savePath->addItem(defSavePath); - QDir defaultSaveDir(defSavePath); - // Load save path history - foreach (const QString &savePath, settings()->loadValue(KEY_SAVEPATHHISTORY).toStringList()) - if (QDir(savePath) != defaultSaveDir) - ui->savePath->addItem(savePath); - - if (!m_torrentParams.savePath.isEmpty()) - setSavePath(m_torrentParams.savePath); -} - -void AddNewTorrentDialog::displayContentTreeMenu(const QPoint &) -{ - QMenu myFilesLlistMenu; - const QModelIndexList selectedRows = ui->contentTreeView->selectionModel()->selectedRows(0); - QAction *actRename = 0; - if (selectedRows.size() == 1) { - actRename = myFilesLlistMenu.addAction(GuiIconProvider::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_hasMetadata) - disconnect(this, SLOT(updateMetadata(const BitTorrent::TorrentInfo&))); - - // TODO: Check if destination actually exists - m_torrentParams.skipChecking = ui->skipCheckingCheckBox->isChecked(); - - // Category - m_torrentParams.category = ui->categoryComboBox->currentText(); - - if (ui->defaultCategoryCheckbox->isChecked()) - settings()->storeValue(KEY_DEFAULTCATEGORY, m_torrentParams.category); - - // Save file priorities - if (m_contentModel) - m_torrentParams.filePriorities = m_contentModel->model()->getFilePriorities(); - - m_torrentParams.addPaused = TriStateBool(!ui->startTorrentCheckBox->isChecked()); - m_torrentParams.createSubfolder = TriStateBool(ui->createSubfolderCheckBox->isChecked()); - - QString savePath = ui->savePath->selectedPath(); - if (ui->comboTTM->currentIndex() != 1) { // 0 is Manual mode and 1 is Automatic mode. Handle all non 1 values as manual mode. - m_torrentParams.useAutoTMM = TriStateBool::False; - m_torrentParams.savePath = savePath; - saveSavePathHistory(); - if (ui->defaultSavePathCheckBox->isChecked()) - BitTorrent::Session::instance()->setDefaultSavePath(savePath); - } - else { - m_torrentParams.useAutoTMM = TriStateBool::True; - } - - setEnabled(!ui->never_show_cb->isChecked()); - - // Add torrent - if (!m_hasMetadata) - BitTorrent::Session::instance()->addTorrent(m_hash, m_torrentParams); - else - BitTorrent::Session::instance()->addTorrent(m_torrentInfo, m_torrentParams); - - m_torrentGuard->markAsAddedToSession(); - QDialog::accept(); -} - -void AddNewTorrentDialog::reject() -{ - if (!m_hasMetadata) { - disconnect(this, SLOT(updateMetadata(BitTorrent::TorrentInfo))); - setMetadataProgressIndicator(false); - BitTorrent::Session::instance()->cancelLoadMetadata(m_hash); - } - - QDialog::reject(); -} - -void AddNewTorrentDialog::updateMetadata(const BitTorrent::TorrentInfo &info) -{ - if (info.hash() != m_hash) return; - - disconnect(this, SLOT(updateMetadata(BitTorrent::TorrentInfo))); - if (!info.isValid()) { - MessageBoxRaised::critical(this, tr("I/O Error"), ("Invalid metadata.")); - setMetadataProgressIndicator(false, tr("Invalid metadata")); - return; - } - - // Good to go - m_torrentInfo = info; - m_hasMetadata = true; - setMetadataProgressIndicator(true, tr("Parsing metadata...")); - - // Update UI - setupTreeview(); - setMetadataProgressIndicator(false, tr("Metadata retrieval complete")); -} - -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) { - setCommentText(tr("Not Available", "This comment is unavailable")); - ui->date_lbl->setText(tr("Not Available", "This date is unavailable")); - } - else { - // Set dialog title - setWindowTitle(m_torrentInfo.name()); - - // Set torrent information - setCommentText(Utils::Misc::parseHtmlLinks(m_torrentInfo.comment())); - ui->date_lbl->setText(!m_torrentInfo.creationDate().isNull() ? m_torrentInfo.creationDate().toString(Qt::DefaultLocaleShortDate) : tr("Not available")); - - // Prepare content tree - m_contentModel = new TorrentContentFilterModel(this); - connect(m_contentModel->model(), SIGNAL(filteredFilesChanged()), SLOT(updateDiskSpaceLabel())); - ui->contentTreeView->setModel(m_contentModel); - m_contentDelegate = new PropListDelegate(nullptr); - ui->contentTreeView->setItemDelegate(m_contentDelegate); - connect(ui->contentTreeView, SIGNAL(clicked(const QModelIndex&)), ui->contentTreeView, SLOT(edit(const QModelIndex&))); - connect(ui->contentTreeView, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(displayContentTreeMenu(const QPoint&))); - - // List files in torrent - m_contentModel->model()->setupModelData(m_torrentInfo); - if (!m_headerState.isEmpty()) - ui->contentTreeView->header()->restoreState(m_headerState); - - // Hide useless columns after loading the header state - ui->contentTreeView->hideColumn(PROGRESS); - ui->contentTreeView->hideColumn(REMAINING); - ui->contentTreeView->hideColumn(AVAILABILITY); - - // Expand root folder - ui->contentTreeView->setExpanded(m_contentModel->index(0, 0), true); - } - - updateDiskSpaceLabel(); - showAdvancedSettings(settings()->loadValue(KEY_EXPANDED, false).toBool()); -} - -void AddNewTorrentDialog::handleDownloadFailed(const QString &url, const QString &reason) -{ - MessageBoxRaised::critical(this, tr("Download Error"), QString("Cannot download '%1': %2").arg(url).arg(reason)); - this->deleteLater(); -} - -void AddNewTorrentDialog::handleRedirectedToMagnet(const QString &url, const QString &magnetUri) -{ - Q_UNUSED(url) - if (loadMagnet(BitTorrent::MagnetUri(magnetUri))) - open(); - else - this->deleteLater(); -} - -void AddNewTorrentDialog::handleDownloadFinished(const QString &url, const QString &filePath) -{ - Q_UNUSED(url) - if (loadTorrent(filePath)) - open(); - else - this->deleteLater(); -} - -void AddNewTorrentDialog::TMMChanged(int index) -{ - if (index != 1) { // 0 is Manual mode and 1 is Automatic mode. Handle all non 1 values as manual mode. - populateSavePathComboBox(); - ui->groupBoxSavePath->setEnabled(true); - ui->savePath->blockSignals(false); - ui->savePath->setCurrentIndex(m_oldIndex < ui->savePath->count() ? m_oldIndex : ui->savePath->count() - 1); - ui->adv_button->setEnabled(true); - } - else { - ui->groupBoxSavePath->setEnabled(false); - ui->savePath->blockSignals(true); - ui->savePath->clear(); - QString savePath = BitTorrent::Session::instance()->categorySavePath(ui->categoryComboBox->currentText()); - ui->savePath->addItem(savePath); - ui->defaultSavePathCheckBox->setVisible(false); - ui->adv_button->setChecked(true); - ui->adv_button->setEnabled(false); - showAdvancedSettings(true); - } -} - -void AddNewTorrentDialog::setCommentText(const QString &str) const -{ - ui->commentLabel->setText(str); - - // workaround for the additional space introduced by QScrollArea - int lineHeight = ui->commentLabel->fontMetrics().lineSpacing(); - int lines = 1 + str.count("\n"); - int height = lineHeight * lines; - ui->scrollArea->setMaximumHeight(height); -} - -void AddNewTorrentDialog::doNotDeleteTorrentClicked(bool checked) -{ - m_torrentGuard->setAutoRemove(!checked); -} diff --git a/src/gui/addnewtorrentdialog.h b/src/gui/addnewtorrentdialog.h deleted file mode 100644 index 668c29754..000000000 --- a/src/gui/addnewtorrentdialog.h +++ /dev/null @@ -1,118 +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 -#include -#include -#include - -#include "base/bittorrent/infohash.h" -#include "base/bittorrent/torrentinfo.h" -#include "base/bittorrent/addtorrentparams.h" - -namespace BitTorrent -{ - class MagnetUri; -} - -namespace Ui -{ - class AddNewTorrentDialog; -} - -class TorrentContentFilterModel; -class TorrentFileGuard; -class PropListDelegate; - -class AddNewTorrentDialog: public QDialog -{ - Q_OBJECT - -public: - ~AddNewTorrentDialog(); - - static bool isEnabled(); - static void setEnabled(bool value); - static bool isTopLevel(); - static void setTopLevel(bool value); - - static void show(QString source, const BitTorrent::AddTorrentParams &inParams, QWidget *parent); - static void show(QString source, QWidget *parent); - -private slots: - void showAdvancedSettings(bool show); - void displayContentTreeMenu(const QPoint &); - void updateDiskSpaceLabel(); - void onSavePathChanged(const QString &newPath); - void renameSelectedFile(); - void updateMetadata(const BitTorrent::TorrentInfo &info); - void handleDownloadFailed(const QString &url, const QString &reason); - void handleRedirectedToMagnet(const QString &url, const QString &magnetUri); - void handleDownloadFinished(const QString &url, const QString &filePath); - void TMMChanged(int index); - void categoryChanged(int index); - void doNotDeleteTorrentClicked(bool checked); - - void accept() override; - void reject() override; - -private: - explicit AddNewTorrentDialog(const BitTorrent::AddTorrentParams &inParams, QWidget *parent); - bool loadTorrent(const QString &torrentPath); - bool loadMagnet(const BitTorrent::MagnetUri &magnetUri); - void populateSavePathComboBox(); - void saveSavePathHistory() const; - int indexOfSavePath(const QString &save_path); - void loadState(); - void saveState(); - void setMetadataProgressIndicator(bool visibleIndicator, const QString &labelText = QString()); - void setupTreeview(); - void setCommentText(const QString &str) const; - void setSavePath(const QString &newPath); - - void showEvent(QShowEvent *event) override; - - Ui::AddNewTorrentDialog *ui; - TorrentContentFilterModel *m_contentModel; - PropListDelegate *m_contentDelegate; - bool m_hasMetadata; - QString m_filePath; - BitTorrent::InfoHash m_hash; - BitTorrent::TorrentInfo m_torrentInfo; - QByteArray m_headerState; - int m_oldIndex; - QScopedPointer m_torrentGuard; - BitTorrent::AddTorrentParams m_torrentParams; -}; - -#endif // ADDNEWTORRENTDIALOG_H diff --git a/src/gui/addnewtorrentdialog.ui b/src/gui/addnewtorrentdialog.ui deleted file mode 100644 index 9f8747101..000000000 --- a/src/gui/addnewtorrentdialog.ui +++ /dev/null @@ -1,478 +0,0 @@ - - - AddNewTorrentDialog - - - - 0 - 0 - 414 - 630 - - - - - - - - - Torrent Management Mode: - - - - - - - Automatic mode means that various torrent properties(eg save path) will be decided by the associated category - - - - Manual - - - - - Automatic - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - Save at - - - - - - - - - Set as default save path - - - - - - - - - - When checked, the .torrent file will not be deleted despite the settings at the "Download" page of the options dialog - - - Do not delete .torrent file - - - - - - - Never show again - - - - - - - - - - true - - - - - - - Torrent settings - - - - - - Set as default category - - - - - - - - - Category: - - - - - - - - 0 - 0 - - - - true - - - QComboBox::InsertAtTop - - - - - - - - - Start torrent - - - true - - - - - - - Skip hash check - - - - - - - Qt::Horizontal - - - QSizePolicy::Fixed - - - - 35 - 0 - - - - - - - - Create subfolder - - - true - - - - - - - - - - Torrent information - - - - - - - - - Qt::PlainText - - - Qt::TextSelectableByMouse - - - - - - - Hash: - - - - - - - Qt::CustomContextMenu - - - QAbstractItemView::ExtendedSelection - - - true - - - - - - - - - - - - - - Date: - - - - - - - Size: - - - - - - - - - - - - - - Comment: - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop - - - - - - - QFrame::NoFrame - - - true - - - - - 0 - 0 - 321 - 69 - - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - - - - Qt::RichText - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop - - - true - - - true - - - Qt::TextBrowserInteraction - - - - - - - - - - - - - - - - - 0 - 0 - - - - 0 - - - -1 - - - false - - - %p% - - - - - - - - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - - - - - - - Normal - - - - - High - - - - - Maximum - - - - - Do not download - - - - - - TorrentContentTreeView - QTreeView -
torrentcontenttreeview.h
-
- - FileSystemPathComboEdit - QWidget -
fspathedit.h
- 1 -
-
- - savePath - defaultSavePathCheckBox - never_show_cb - adv_button - startTorrentCheckBox - skipCheckingCheckBox - categoryComboBox - defaultCategoryCheckbox - scrollArea - contentTreeView - - - - - buttonBox - accepted() - AddNewTorrentDialog - accept() - - - 403 - 579 - - - 157 - 274 - - - - - buttonBox - rejected() - AddNewTorrentDialog - reject() - - - 403 - 579 - - - 286 - 274 - - - - - categoryComboBox - currentIndexChanged(int) - AddNewTorrentDialog - categoryChanged(int) - - - 337 - 205 - - - 403 - 160 - - - - - comboTTM - currentIndexChanged(int) - AddNewTorrentDialog - TMMChanged(int) - - - 200 - 19 - - - 206 - 294 - - - - - - savingModeChanged(bool) - categoryChanged(int) - TMMChanged(int) - -
diff --git a/src/gui/advancedsettings.cpp b/src/gui/advancedsettings.cpp deleted file mode 100644 index 6d5926cd3..000000000 --- a/src/gui/advancedsettings.cpp +++ /dev/null @@ -1,412 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2016 qBittorrent project - * - * 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. - */ - -#include "advancedsettings.h" - -#include -#include -#include -#include - -#include "app/application.h" -#include "base/bittorrent/session.h" -#include "base/preferences.h" -#include "gui/mainwindow.h" - -enum AdvSettingsCols -{ - PROPERTY, - VALUE, - COL_COUNT -}; -enum AdvSettingsRows -{ - // qBittorrent section - QBITTORRENT_HEADER, - // network interface - NETWORK_IFACE, - //Optional network address - NETWORK_IFACE_ADDRESS, - NETWORK_LISTEN_IPV6, - // behavior - SAVE_RESUME_DATA_INTERVAL, - CONFIRM_RECHECK_TORRENT, - RECHECK_COMPLETED, -#if defined(Q_OS_WIN) || defined(Q_OS_MAC) - UPDATE_CHECK, -#endif - // UI related - LIST_REFRESH, - RESOLVE_HOSTS, - RESOLVE_COUNTRIES, - PROGRAM_NOTIFICATIONS, - TORRENT_ADDED_NOTIFICATIONS, - CONFIRM_REMOVE_ALL_TAGS, - DOWNLOAD_TRACKER_FAVICON, -#if (defined(Q_OS_UNIX) && !defined(Q_OS_MAC)) - USE_ICON_THEME, -#endif - - // libtorrent section - LIBTORRENT_HEADER, - // cache - DISK_CACHE, - DISK_CACHE_TTL, - OS_CACHE, - // ports - MAX_HALF_OPEN, - OUTGOING_PORT_MIN, - OUTGOING_PORT_MAX, - // embedded tracker - TRACKER_STATUS, - TRACKER_PORT, - // seeding - SUPER_SEEDING, - // tracker - ANNOUNCE_ALL_TRACKERS, - ANNOUNCE_IP, - - ROW_COUNT -}; - -AdvancedSettings::AdvancedSettings(QWidget *parent) - : QTableWidget(parent) -{ - // column - setColumnCount(COL_COUNT); - QStringList header = { tr("Setting"), tr("Value", "Value set for this setting") }; - setHorizontalHeaderLabels(header); - // row - setRowCount(ROW_COUNT); - verticalHeader()->setVisible(false); - // etc. - setAlternatingRowColors(true); - setSelectionMode(QAbstractItemView::NoSelection); - setEditTriggers(QAbstractItemView::NoEditTriggers); - // Signals - connect(&spin_cache, SIGNAL(valueChanged(int)), SLOT(updateCacheSpinSuffix(int))); - connect(&combo_iface, SIGNAL(currentIndexChanged(int)), SLOT(updateInterfaceAddressCombo())); - // Load settings - loadAdvancedSettings(); - resizeColumnToContents(0); - horizontalHeader()->setStretchLastSection(true); -} - -void AdvancedSettings::saveAdvancedSettings() -{ - Preferences* const pref = Preferences::instance(); - BitTorrent::Session *const session = BitTorrent::Session::instance(); - - // Disk write cache - session->setDiskCacheSize(spin_cache.value()); - session->setDiskCacheTTL(spin_cache_ttl.value()); - // Enable OS cache - session->setUseOSCache(cb_os_cache.isChecked()); - // Save resume data interval - session->setSaveResumeDataInterval(spin_save_resume_data_interval.value()); - // Outgoing ports - session->setOutgoingPortsMin(outgoing_ports_min.value()); - session->setOutgoingPortsMax(outgoing_ports_max.value()); - // Recheck torrents on completion - pref->recheckTorrentsOnCompletion(cb_recheck_completed.isChecked()); - // Transfer list refresh interval - session->setRefreshInterval(spin_list_refresh.value()); - // Peer resolution - pref->resolvePeerCountries(cb_resolve_countries.isChecked()); - pref->resolvePeerHostNames(cb_resolve_hosts.isChecked()); - // Max Half-Open connections - session->setMaxHalfOpenConnections(spin_maxhalfopen.value()); - // Super seeding - session->setSuperSeedingEnabled(cb_super_seeding.isChecked()); - // Network interface - if (combo_iface.currentIndex() == 0) { - // All interfaces (default) - session->setNetworkInterface(QString()); - session->setNetworkInterfaceName(QString()); - } - else { - session->setNetworkInterface(combo_iface.itemData(combo_iface.currentIndex()).toString()); - session->setNetworkInterfaceName(combo_iface.currentText()); - } - - // Interface address - if (combo_iface_address.currentIndex() == 0) { - // All addresses (default) - session->setNetworkInterfaceAddress(QString::null); - } - else { - QHostAddress ifaceAddr(combo_iface_address.currentText().trimmed()); - ifaceAddr.isNull() ? session->setNetworkInterfaceAddress(QString::null) : session->setNetworkInterfaceAddress(ifaceAddr.toString()); - } - session->setIPv6Enabled(cb_listen_ipv6.isChecked()); - // Announce IP - QHostAddress addr(txtAnnounceIP.text().trimmed()); - session->setAnnounceIP(addr.isNull() ? "" : addr.toString()); - - // Program notification - MainWindow * const mainWindow = static_cast(QCoreApplication::instance())->mainWindow(); - mainWindow->setNotificationsEnabled(cb_program_notifications.isChecked()); - mainWindow->setTorrentAddedNotificationsEnabled(cb_torrent_added_notifications.isChecked()); - // Misc GUI properties - mainWindow->setDownloadTrackerFavicon(cb_tracker_favicon.isChecked()); - - // Tracker - session->setTrackerEnabled(cb_tracker_status.isChecked()); - pref->setTrackerPort(spin_tracker_port.value()); -#if defined(Q_OS_WIN) || defined(Q_OS_MAC) - pref->setUpdateCheckEnabled(cb_update_check.isChecked()); -#endif - // Icon theme -#if (defined(Q_OS_UNIX) && !defined(Q_OS_MAC)) - pref->useSystemIconTheme(cb_use_icon_theme.isChecked()); -#endif - pref->setConfirmTorrentRecheck(cb_confirm_torrent_recheck.isChecked()); - - pref->setConfirmRemoveAllTags(cb_confirm_remove_all_tags.isChecked()); - - session->setAnnounceToAllTrackers(cb_announce_all_trackers.isChecked()); -} - -void AdvancedSettings::updateCacheSpinSuffix(int value) -{ - if (value <= 0) - spin_cache.setSuffix(tr(" (auto)")); - else - spin_cache.setSuffix(tr(" MiB")); -} - -void AdvancedSettings::updateInterfaceAddressCombo() -{ - // Try to get the currently selected interface name - const QString ifaceName = combo_iface.itemData(combo_iface.currentIndex()).toString(); // Empty string for the first element - const QString currentAddress = BitTorrent::Session::instance()->networkInterfaceAddress(); - - //Clear all items and reinsert them, default to all - combo_iface_address.clear(); - combo_iface_address.addItem(tr("All addresses")); - combo_iface_address.setCurrentIndex(0); - - auto populateCombo = [this, ¤tAddress](const QString &ip, const QAbstractSocket::NetworkLayerProtocol &protocol) - { - Q_ASSERT(protocol == QAbstractSocket::IPv4Protocol || protocol == QAbstractSocket::IPv6Protocol); - //Only take ipv4 for now? - if (protocol != QAbstractSocket::IPv4Protocol && protocol != QAbstractSocket::IPv6Protocol) - return; - combo_iface_address.addItem(ip); - //Try to select the last added one - if (ip == currentAddress) - combo_iface_address.setCurrentIndex(combo_iface_address.count() - 1); - }; - - if (ifaceName.isEmpty()) { - foreach (const QHostAddress &ip, QNetworkInterface::allAddresses()) - populateCombo(ip.toString(), ip.protocol()); - } - else { - const QNetworkInterface iface = QNetworkInterface::interfaceFromName(ifaceName); - const QList addresses = iface.addressEntries(); - foreach (const QNetworkAddressEntry &entry, addresses) { - const QHostAddress ip = entry.ip(); - populateCombo(ip.toString(), ip.protocol()); - } - } -} - -void AdvancedSettings::loadAdvancedSettings() -{ - const Preferences* const pref = Preferences::instance(); - const BitTorrent::Session *const session = BitTorrent::Session::instance(); - - // add section headers - QFont boldFont; - boldFont.setBold(true); - addRow(QBITTORRENT_HEADER, tr("qBittorrent Section"), &labelQbtLink); - item(QBITTORRENT_HEADER, PROPERTY)->setFont(boldFont); - labelQbtLink.setText(QString("
%2").arg("https://github.com/qbittorrent/qBittorrent/wiki/Explanation-of-Options-in-qBittorrent#Advanced").arg(tr("Open documentation"))); - labelQbtLink.setOpenExternalLinks(true); - - addRow(LIBTORRENT_HEADER, tr("libtorrent Section"), &labelLibtorrentLink); - item(LIBTORRENT_HEADER, PROPERTY)->setFont(boldFont); - labelLibtorrentLink.setText(QString("%2").arg("http://www.libtorrent.org/reference.html").arg(tr("Open documentation"))); - labelLibtorrentLink.setOpenExternalLinks(true); - // Disk write cache - spin_cache.setMinimum(0); - // When build as 32bit binary, set the maximum at less than 2GB to prevent crashes. - // These macros may not be available on compilers other than MSVC and GCC -#if defined(__x86_64__) || defined(_M_X64) - spin_cache.setMaximum(4096); -#else - // allocate 1536MiB and leave 512MiB to the rest of program data in RAM - spin_cache.setMaximum(1536); -#endif - spin_cache.setValue(session->diskCacheSize()); - updateCacheSpinSuffix(spin_cache.value()); - addRow(DISK_CACHE, tr("Disk write cache size"), &spin_cache); - // Disk cache expiry - spin_cache_ttl.setMinimum(15); - spin_cache_ttl.setMaximum(600); - spin_cache_ttl.setValue(session->diskCacheTTL()); - spin_cache_ttl.setSuffix(tr(" s", " seconds")); - addRow(DISK_CACHE_TTL, tr("Disk cache expiry interval"), &spin_cache_ttl); - // Enable OS cache - cb_os_cache.setChecked(session->useOSCache()); - addRow(OS_CACHE, tr("Enable OS cache"), &cb_os_cache); - // Save resume data interval - spin_save_resume_data_interval.setMinimum(1); - spin_save_resume_data_interval.setMaximum(1440); - spin_save_resume_data_interval.setValue(session->saveResumeDataInterval()); - spin_save_resume_data_interval.setSuffix(tr(" m", " minutes")); - addRow(SAVE_RESUME_DATA_INTERVAL, tr("Save resume data interval", "How often the fastresume file is saved."), &spin_save_resume_data_interval); - // Outgoing port Min - outgoing_ports_min.setMinimum(0); - outgoing_ports_min.setMaximum(65535); - outgoing_ports_min.setValue(session->outgoingPortsMin()); - addRow(OUTGOING_PORT_MIN, tr("Outgoing ports (Min) [0: Disabled]"), &outgoing_ports_min); - // Outgoing port Min - outgoing_ports_max.setMinimum(0); - outgoing_ports_max.setMaximum(65535); - outgoing_ports_max.setValue(session->outgoingPortsMax()); - addRow(OUTGOING_PORT_MAX, tr("Outgoing ports (Max) [0: Disabled]"), &outgoing_ports_max); - // Recheck completed torrents - cb_recheck_completed.setChecked(pref->recheckTorrentsOnCompletion()); - addRow(RECHECK_COMPLETED, tr("Recheck torrents on completion"), &cb_recheck_completed); - // Transfer list refresh interval - spin_list_refresh.setMinimum(30); - spin_list_refresh.setMaximum(99999); - spin_list_refresh.setValue(session->refreshInterval()); - spin_list_refresh.setSuffix(tr(" ms", " milliseconds")); - addRow(LIST_REFRESH, tr("Transfer list refresh interval"), &spin_list_refresh); - // Resolve Peer countries - cb_resolve_countries.setChecked(pref->resolvePeerCountries()); - addRow(RESOLVE_COUNTRIES, tr("Resolve peer countries (GeoIP)"), &cb_resolve_countries); - // Resolve peer hosts - cb_resolve_hosts.setChecked(pref->resolvePeerHostNames()); - addRow(RESOLVE_HOSTS, tr("Resolve peer host names"), &cb_resolve_hosts); - // Max Half Open connections - spin_maxhalfopen.setMinimum(0); - spin_maxhalfopen.setMaximum(99999); - spin_maxhalfopen.setValue(session->maxHalfOpenConnections()); - addRow(MAX_HALF_OPEN, tr("Maximum number of half-open connections [0: Unlimited]"), &spin_maxhalfopen); - // Super seeding - cb_super_seeding.setChecked(session->isSuperSeedingEnabled()); - addRow(SUPER_SEEDING, tr("Strict super seeding"), &cb_super_seeding); - // Network interface - combo_iface.addItem(tr("Any interface", "i.e. Any network interface")); - const QString current_iface = session->networkInterface(); - bool interface_exists = current_iface.isEmpty(); - int i = 1; - foreach (const QNetworkInterface& iface, QNetworkInterface::allInterfaces()) { - // This line fixes a Qt bug => https://bugreports.qt.io/browse/QTBUG-52633 - // Tested in Qt 5.6.0. For more info see: - // https://github.com/qbittorrent/qBittorrent/issues/5131 - // https://github.com/qbittorrent/qBittorrent/pull/5135 - if (iface.addressEntries().isEmpty()) continue; - - if (iface.flags() & QNetworkInterface::IsLoopBack) continue; - combo_iface.addItem(iface.humanReadableName(), iface.name()); - if (!current_iface.isEmpty() && (iface.name() == current_iface)) { - combo_iface.setCurrentIndex(i); - interface_exists = true; - } - ++i; - } - // Saved interface does not exist, show it anyway - if (!interface_exists) { - combo_iface.addItem(session->networkInterfaceName(), current_iface); - combo_iface.setCurrentIndex(i); - } - addRow(NETWORK_IFACE, tr("Network Interface (requires restart)"), &combo_iface); - // Network interface address - updateInterfaceAddressCombo(); - addRow(NETWORK_IFACE_ADDRESS, tr("Optional IP Address to bind to (requires restart)"), &combo_iface_address); - // Listen on IPv6 address - cb_listen_ipv6.setChecked(session->isIPv6Enabled()); - addRow(NETWORK_LISTEN_IPV6, tr("Listen on IPv6 address (requires restart)"), &cb_listen_ipv6); - // Announce IP - txtAnnounceIP.setText(session->announceIP()); - addRow(ANNOUNCE_IP, tr("IP Address to report to trackers (requires restart)"), &txtAnnounceIP); - - // Program notifications - const MainWindow * const mainWindow = static_cast(QCoreApplication::instance())->mainWindow(); - cb_program_notifications.setChecked(mainWindow->isNotificationsEnabled()); - addRow(PROGRAM_NOTIFICATIONS, tr("Display notifications"), &cb_program_notifications); - // Torrent added notifications - cb_torrent_added_notifications.setChecked(mainWindow->isTorrentAddedNotificationsEnabled()); - addRow(TORRENT_ADDED_NOTIFICATIONS, tr("Display notifications for added torrents"), &cb_torrent_added_notifications); - // Download tracker's favicon - cb_tracker_favicon.setChecked(mainWindow->isDownloadTrackerFavicon()); - addRow(DOWNLOAD_TRACKER_FAVICON, tr("Download tracker's favicon"), &cb_tracker_favicon); - - // Tracker State - cb_tracker_status.setChecked(session->isTrackerEnabled()); - addRow(TRACKER_STATUS, tr("Enable embedded tracker"), &cb_tracker_status); - // Tracker port - spin_tracker_port.setMinimum(1); - spin_tracker_port.setMaximum(65535); - spin_tracker_port.setValue(pref->getTrackerPort()); - addRow(TRACKER_PORT, tr("Embedded tracker port"), &spin_tracker_port); -#if defined(Q_OS_WIN) || defined(Q_OS_MAC) - cb_update_check.setChecked(pref->isUpdateCheckEnabled()); - addRow(UPDATE_CHECK, tr("Check for software updates"), &cb_update_check); -#endif -#if (defined(Q_OS_UNIX) && !defined(Q_OS_MAC)) - cb_use_icon_theme.setChecked(pref->useSystemIconTheme()); - addRow(USE_ICON_THEME, tr("Use system icon theme"), &cb_use_icon_theme); -#endif - // Torrent recheck confirmation - cb_confirm_torrent_recheck.setChecked(pref->confirmTorrentRecheck()); - addRow(CONFIRM_RECHECK_TORRENT, tr("Confirm torrent recheck"), &cb_confirm_torrent_recheck); - - // Remove all tags confirmation - cb_confirm_remove_all_tags.setChecked(pref->confirmRemoveAllTags()); - addRow(CONFIRM_REMOVE_ALL_TAGS, tr("Confirm remove all tags"), &cb_confirm_remove_all_tags); - - // Announce to all trackers - cb_announce_all_trackers.setChecked(session->announceToAllTrackers()); - addRow(ANNOUNCE_ALL_TRACKERS, tr("Always announce to all trackers"), &cb_announce_all_trackers); -} - -template -void AdvancedSettings::addRow(int row, const QString &rowText, T* widget) -{ - // ignore mouse wheel event - static WheelEventEater filter; - widget->installEventFilter(&filter); - - setItem(row, PROPERTY, new QTableWidgetItem(rowText)); - setCellWidget(row, VALUE, widget); - - if (std::is_same::value) - connect(widget, SIGNAL(stateChanged(int)), SIGNAL(settingsChanged())); - else if (std::is_same::value) - connect(widget, SIGNAL(valueChanged(int)), SIGNAL(settingsChanged())); - else if (std::is_same::value) - connect(widget, SIGNAL(currentIndexChanged(int)), SIGNAL(settingsChanged())); - else if (std::is_same::value) - connect(widget, SIGNAL(textChanged(QString)), SIGNAL(settingsChanged())); -} diff --git a/src/gui/advancedsettings.h b/src/gui/advancedsettings.h deleted file mode 100644 index 57ae1b643..000000000 --- a/src/gui/advancedsettings.h +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2015 - * - * 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. - */ - -#ifndef ADVANCEDSETTINGS_H -#define ADVANCEDSETTINGS_H - -#include -#include -#include -#include -#include -#include -#include - - -class WheelEventEater: public QObject -{ - Q_OBJECT - -private: - bool eventFilter(QObject *obj, QEvent *event) - { - switch (event->type()) { - case QEvent::Wheel: - return true; - default: - return QObject::eventFilter(obj, event); - } - } -}; - -class AdvancedSettings: public QTableWidget -{ - Q_OBJECT - -public: - AdvancedSettings(QWidget *parent); - -public slots: - void saveAdvancedSettings(); - -signals: - void settingsChanged(); - -private slots: - void updateCacheSpinSuffix(int value); - void updateInterfaceAddressCombo(); - -private: - void loadAdvancedSettings(); - template void addRow(int row, const QString &rowText, T* widget); - - QLabel labelQbtLink, labelLibtorrentLink; - QSpinBox spin_cache, spin_save_resume_data_interval, outgoing_ports_min, outgoing_ports_max, spin_list_refresh, spin_maxhalfopen, spin_tracker_port, spin_cache_ttl; - QCheckBox cb_os_cache, cb_recheck_completed, cb_resolve_countries, cb_resolve_hosts, cb_super_seeding, - cb_program_notifications, cb_torrent_added_notifications, cb_tracker_favicon, cb_tracker_status, - cb_confirm_torrent_recheck, cb_confirm_remove_all_tags, cb_listen_ipv6, cb_announce_all_trackers; - QComboBox combo_iface, combo_iface_address; - QLineEdit txtAnnounceIP; - - // OS dependent settings -#if defined(Q_OS_WIN) || defined(Q_OS_MAC) - QCheckBox cb_update_check; -#endif - -#if (defined(Q_OS_UNIX) && !defined(Q_OS_MAC)) - QCheckBox cb_use_icon_theme; -#endif -}; - -#endif // ADVANCEDSETTINGS_H diff --git a/src/gui/autoexpandabledialog.cpp b/src/gui/autoexpandabledialog.cpp deleted file mode 100644 index 590989326..000000000 --- a/src/gui/autoexpandabledialog.cpp +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Bittorrent Client using Qt 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. - */ - -#include "autoexpandabledialog.h" - -#include - -#include "mainwindow.h" -#include "ui_autoexpandabledialog.h" - -AutoExpandableDialog::AutoExpandableDialog(QWidget *parent) - : QDialog(parent) - , m_ui(new Ui::AutoExpandableDialog) -{ - m_ui->setupUi(this); -} - -AutoExpandableDialog::~AutoExpandableDialog() -{ - delete m_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.m_ui->textLabel->setText(label); - d.m_ui->textEdit->setText(text); - d.m_ui->textEdit->setEchoMode(mode); - d.m_ui->textEdit->setInputMethodHints(inputMethodHints); - - bool res = d.exec(); - if (ok) - *ok = res; - - if (!res) return QString(); - - return d.m_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 = m_ui->textEdit->fontMetrics().width(m_ui->textEdit->text()) + 4; - int wd = textW; - - if (!windowTitle().isEmpty()) { - int w = fontMetrics().width(windowTitle()); - if (w > wd) - wd = w; - } - - if (!m_ui->textLabel->text().isEmpty()) { - int w = m_ui->textLabel->fontMetrics().width(m_ui->textLabel->text()); - if (w > wd) - wd = w; - } - - // Now resize the dialog to fit the contents - // max width of text from either of: label, title, textedit - // If the value is less than dialog default size, default size is used - if (wd > width()) - resize(width() - m_ui->verticalLayout->sizeHint().width() + wd, height()); -} diff --git a/src/gui/autoexpandabledialog.h b/src/gui/autoexpandabledialog.h deleted file mode 100644 index f3e5d0666..000000000 --- a/src/gui/autoexpandabledialog.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Bittorrent Client using Qt 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. - */ - -#ifndef AUTOEXPANDABLEDIALOG_H -#define AUTOEXPANDABLEDIALOG_H - -#include -#include -#include - -namespace Ui -{ - class AutoExpandableDialog; -} - -class AutoExpandableDialog: public QDialog -{ - Q_OBJECT - -public: - explicit AutoExpandableDialog(QWidget *parent); - ~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 *m_ui; -}; - -#endif // AUTOEXPANDABLEDIALOG_H diff --git a/src/gui/autoexpandabledialog.ui b/src/gui/autoexpandabledialog.ui deleted file mode 100644 index 43d7daa09..000000000 --- a/src/gui/autoexpandabledialog.ui +++ /dev/null @@ -1,64 +0,0 @@ - - - AutoExpandableDialog - - - - 0 - 0 - 222 - 105 - - - - - - - - - - - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - - - - - - - buttonBox - accepted() - AutoExpandableDialog - accept() - - - 248 - 254 - - - 157 - 274 - - - - - buttonBox - rejected() - AutoExpandableDialog - reject() - - - 316 - 260 - - - 286 - 274 - - - - - diff --git a/src/gui/bandwidth_limit.ui b/src/gui/bandwidth_limit.ui deleted file mode 100644 index b10bee62d..000000000 --- a/src/gui/bandwidth_limit.ui +++ /dev/null @@ -1,79 +0,0 @@ - - - bandwidth_dlg - - - - 0 - 0 - 338 - 83 - - - - - - - - - Qt::Horizontal - - - - - - - 65535 - - - 0 - - - - - - - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - - - - - - - buttonBox - rejected() - bandwidth_dlg - reject() - - - 221 - 73 - - - 221 - 82 - - - - - buttonBox - accepted() - bandwidth_dlg - accept() - - - 277 - 59 - - - 343 - 80 - - - - - diff --git a/src/gui/banlistoptions.cpp b/src/gui/banlistoptions.cpp deleted file mode 100644 index 0c4a70657..000000000 --- a/src/gui/banlistoptions.cpp +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2016 Alexandr Milovantsev - * - * 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. - */ - -#include "banlistoptions.h" -#include "ui_banlistoptions.h" - -#include -#include -#include -#include - -#include "base/bittorrent/session.h" -#include "base/utils/net.h" - -BanListOptions::BanListOptions(QWidget *parent) - : QDialog(parent) - , m_ui(new Ui::BanListOptions) - , m_modified(false) -{ - m_ui->setupUi(this); - m_model = new QStringListModel(BitTorrent::Session::instance()->bannedIPs(), this); - - m_sortFilter = new QSortFilterProxyModel(this); - m_sortFilter->setDynamicSortFilter(true); - m_sortFilter->setSourceModel(m_model); - - m_ui->bannedIPList->setModel(m_sortFilter); - m_ui->bannedIPList->sortByColumn(0, Qt::AscendingOrder); - m_ui->buttonBanIP->setEnabled(false); -} - -BanListOptions::~BanListOptions() -{ - delete m_ui; -} - -void BanListOptions::on_buttonBox_accepted() -{ - if (m_modified) { - // save to session - QStringList IPList; - // Operate on the m_sortFilter to grab the strings in sorted order - for (int i = 0; i < m_sortFilter->rowCount(); ++i) { - QModelIndex index = m_sortFilter->index(i, 0); - IPList << index.data().toString(); - } - BitTorrent::Session::instance()->setBannedIPs(IPList); - } - QDialog::accept(); -} - -void BanListOptions::on_buttonBanIP_clicked() -{ - QString ip = m_ui->txtIP->text(); - if (!Utils::Net::isValidIP(ip)) { - QMessageBox::warning(this, tr("Warning"), tr("The entered IP address is invalid.")); - return; - } - // the same IPv6 addresses could be written in different forms; - // QHostAddress::toString() result format follows RFC5952; - // thus we avoid duplicate entries pointing to the same address - ip = QHostAddress(ip).toString(); - for (int i = 0; i < m_sortFilter->rowCount(); ++i) { - QModelIndex index = m_sortFilter->index(i, 0); - if (ip == index.data().toString()) { - QMessageBox::warning(this, tr("Warning"), tr("The entered IP is already banned.")); - return; - } - } - - m_model->insertRow(m_model->rowCount()); - m_model->setData(m_model->index(m_model->rowCount() - 1, 0), ip); - m_ui->txtIP->clear(); - m_modified = true; -} - -void BanListOptions::on_buttonDeleteIP_clicked() -{ - QModelIndexList selection = m_ui->bannedIPList->selectionModel()->selectedIndexes(); - for (auto &i : selection) - m_sortFilter->removeRow(i.row()); - - m_modified = true; -} - -void BanListOptions::on_txtIP_textChanged(const QString &ip) -{ - m_ui->buttonBanIP->setEnabled(Utils::Net::isValidIP(ip)); -} diff --git a/src/gui/banlistoptions.h b/src/gui/banlistoptions.h deleted file mode 100644 index 5c6b10220..000000000 --- a/src/gui/banlistoptions.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2016 Alexandr Milovantsev - * - * 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. - */ - -#ifndef OPTIONS_BANLIST_H -#define OPTIONS_BANLIST_H - -#include - -class QSortFilterProxyModel; -class QStringListModel; - -namespace Ui -{ - class BanListOptions; -} - -class BanListOptions: public QDialog -{ - Q_OBJECT - -public: - explicit BanListOptions(QWidget *parent = 0); - ~BanListOptions(); - -private slots: - void on_buttonBox_accepted(); - void on_buttonBanIP_clicked(); - void on_buttonDeleteIP_clicked(); - void on_txtIP_textChanged(const QString &ip); - -private: - Ui::BanListOptions *m_ui; - QStringListModel *m_model; - QSortFilterProxyModel *m_sortFilter; - bool m_modified; -}; - -#endif // OPTIONS_BANLIST_H diff --git a/src/gui/banlistoptions.ui b/src/gui/banlistoptions.ui deleted file mode 100644 index 24a2ef7ae..000000000 --- a/src/gui/banlistoptions.ui +++ /dev/null @@ -1,127 +0,0 @@ - - - BanListOptions - - - - 0 - 0 - 360 - 450 - - - - List of banned IP addresses - - - - - - true - - - - 0 - 0 - - - - true - - - QFrame::Panel - - - QFrame::Raised - - - 1 - - - 0 - - - - - - - 0 - 0 - - - - false - - - true - - - false - - - true - - - false - - - - - - - - - - - - Ban IP - - - - - - - Delete - - - - - - - - - - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - - - - - bannedIPList - txtIP - buttonBanIP - buttonDeleteIP - - - - - buttonBox - rejected() - BanListOptions - reject() - - - 179 - 427 - - - 179 - 224 - - - - - diff --git a/src/gui/categoryfiltermodel.cpp b/src/gui/categoryfiltermodel.cpp deleted file mode 100644 index ca6048d83..000000000 --- a/src/gui/categoryfiltermodel.cpp +++ /dev/null @@ -1,447 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2016 Vladimir Golovnev - * - * 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. - */ - -#include "categoryfiltermodel.h" - -#include -#include - -#include "base/bittorrent/torrenthandle.h" -#include "base/bittorrent/session.h" -#include "guiiconprovider.h" - -class CategoryModelItem -{ -public: - CategoryModelItem() - : m_parent(nullptr) - , m_torrentsCount(0) - { - } - - CategoryModelItem(CategoryModelItem *parent, QString categoryName, int torrentsCount = 0) - : m_parent(nullptr) - , m_name(categoryName) - , m_torrentsCount(torrentsCount) - { - if (parent) - parent->addChild(m_name, this); - } - - ~CategoryModelItem() - { - clear(); - if (m_parent) { - m_parent->m_torrentsCount -= m_torrentsCount; - const QString uid = m_parent->m_children.key(this); - m_parent->m_children.remove(uid); - m_parent->m_childUids.removeOne(uid); - } - } - - QString name() const - { - return m_name; - } - - QString fullName() const - { - if (!m_parent || m_parent->name().isEmpty()) - return m_name; - - return QString("%1/%2").arg(m_parent->fullName()).arg(m_name); - } - - CategoryModelItem *parent() const - { - return m_parent; - } - - int torrentsCount() const - { - return m_torrentsCount; - } - - void increaseTorrentsCount() - { - ++m_torrentsCount; - if (m_parent) - m_parent->increaseTorrentsCount(); - } - - void decreaseTorrentsCount() - { - --m_torrentsCount; - if (m_parent) - m_parent->decreaseTorrentsCount(); - } - - int pos() const - { - if (!m_parent) return -1; - - return m_parent->m_childUids.indexOf(m_name); - } - - bool hasChild(const QString &name) const - { - return m_children.contains(name); - } - - int childCount() const - { - return m_children.count(); - } - - CategoryModelItem *child(const QString &uid) const - { - return m_children.value(uid); - } - - CategoryModelItem *childAt(int index) const - { - if ((index < 0) || (index >= m_childUids.count())) - return nullptr; - - return m_children[m_childUids[index]]; - } - - void addChild(const QString &uid, CategoryModelItem *item) - { - Q_ASSERT(item); - Q_ASSERT(!item->parent()); - Q_ASSERT(!m_children.contains(uid)); - - item->m_parent = this; - m_children[uid] = item; - m_childUids.append(uid); - m_torrentsCount += item->torrentsCount(); - } - - void clear() - { - // use copy of m_children for qDeleteAll - // to avoid collision when child removes - // itself from parent children - qDeleteAll(decltype(m_children)(m_children)); - } - -private: - CategoryModelItem *m_parent; - QString m_name; - int m_torrentsCount; - QHash m_children; - QStringList m_childUids; -}; - -namespace -{ - QString shortName(const QString &fullName) - { - int pos = fullName.lastIndexOf(QLatin1Char('/')); - if (pos >= 0) - return fullName.mid(pos + 1); - return fullName; - } -} - -CategoryFilterModel::CategoryFilterModel(QObject *parent) - : QAbstractItemModel(parent) - , m_rootItem(new CategoryModelItem) -{ - auto session = BitTorrent::Session::instance(); - - connect(session, SIGNAL(categoryAdded(QString)), SLOT(categoryAdded(QString))); - connect(session, SIGNAL(categoryRemoved(QString)), SLOT(categoryRemoved(QString))); - connect(session, SIGNAL(torrentCategoryChanged(BitTorrent::TorrentHandle *const, QString)) - , SLOT(torrentCategoryChanged(BitTorrent::TorrentHandle *const, QString))); - connect(session, SIGNAL(subcategoriesSupportChanged()), SLOT(subcategoriesSupportChanged())); - connect(session, SIGNAL(torrentAdded(BitTorrent::TorrentHandle *const)) - , SLOT(torrentAdded(BitTorrent::TorrentHandle *const))); - connect(session, SIGNAL(torrentAboutToBeRemoved(BitTorrent::TorrentHandle *const)) - , SLOT(torrentAboutToBeRemoved(BitTorrent::TorrentHandle *const))); - - populate(); -} - -CategoryFilterModel::~CategoryFilterModel() -{ - delete m_rootItem; -} - -bool CategoryFilterModel::isSpecialItem(const QModelIndex &index) -{ - // the first two items at first level are special items: - // 'All' and 'Uncategorized' - return (!index.parent().isValid() && (index.row() <= 1)); -} - -int CategoryFilterModel::columnCount(const QModelIndex &) const -{ - return 1; -} - -QVariant CategoryFilterModel::data(const QModelIndex &index, int role) const -{ - if (!index.isValid()) return QVariant(); - - auto item = static_cast(index.internalPointer()); - - if ((index.column() == 0) && (role == Qt::DecorationRole)) { - return GuiIconProvider::instance()->getIcon("inode-directory"); - } - - if ((index.column() == 0) && (role == Qt::DisplayRole)) { - return QString(QStringLiteral("%1 (%2)")) - .arg(item->name()).arg(item->torrentsCount()); - } - - if ((index.column() == 0) && (role == Qt::UserRole)) { - return item->torrentsCount(); - } - - return QVariant(); -} - -Qt::ItemFlags CategoryFilterModel::flags(const QModelIndex &index) const -{ - if (!index.isValid()) return 0; - - return Qt::ItemIsEnabled | Qt::ItemIsSelectable; -} - -QVariant CategoryFilterModel::headerData(int section, Qt::Orientation orientation, int role) const -{ - if ((orientation == Qt::Horizontal) && (role == Qt::DisplayRole)) - if (section == 0) - return tr("Categories"); - - return QVariant(); -} - -QModelIndex CategoryFilterModel::index(int row, int column, const QModelIndex &parent) const -{ - if (column > 0) - return QModelIndex(); - - if (parent.isValid() && (parent.column() != 0)) - return QModelIndex(); - - auto parentItem = parent.isValid() ? static_cast(parent.internalPointer()) - : m_rootItem; - if (row < parentItem->childCount()) - return createIndex(row, column, parentItem->childAt(row)); - - return QModelIndex(); -} - -QModelIndex CategoryFilterModel::parent(const QModelIndex &index) const -{ - if (!index.isValid()) - return QModelIndex(); - - auto item = static_cast(index.internalPointer()); - if (!item) return QModelIndex(); - - return this->index(item->parent()); -} - -int CategoryFilterModel::rowCount(const QModelIndex &parent) const -{ - if (parent.column() > 0) - return 0; - - if (!parent.isValid()) - return m_rootItem->childCount(); - - auto item = static_cast(parent.internalPointer()); - if (!item) return 0; - - return item->childCount(); -} - -QModelIndex CategoryFilterModel::index(const QString &categoryName) const -{ - return index(findItem(categoryName)); -} - -QString CategoryFilterModel::categoryName(const QModelIndex &index) const -{ - if (!index.isValid()) return QString(); - return static_cast(index.internalPointer())->fullName(); -} - -QModelIndex CategoryFilterModel::index(CategoryModelItem *item) const -{ - if (!item || !item->parent()) return QModelIndex(); - - return index(item->pos(), 0, index(item->parent())); -} - -void CategoryFilterModel::categoryAdded(const QString &categoryName) -{ - CategoryModelItem *parent = m_rootItem; - - if (m_isSubcategoriesEnabled) { - QStringList expanded = BitTorrent::Session::expandCategory(categoryName); - if (expanded.count() > 1) - parent = findItem(expanded[expanded.count() - 2]); - } - - int row = parent->childCount(); - beginInsertRows(index(parent), row, row); - new CategoryModelItem( - parent, m_isSubcategoriesEnabled ? shortName(categoryName) : categoryName); - endInsertRows(); -} - -void CategoryFilterModel::categoryRemoved(const QString &categoryName) -{ - auto item = findItem(categoryName); - if (item) { - QModelIndex i = index(item); - beginRemoveRows(i.parent(), i.row(), i.row()); - delete item; - endRemoveRows(); - } -} - -void CategoryFilterModel::torrentAdded(BitTorrent::TorrentHandle *const torrent) -{ - CategoryModelItem *item = findItem(torrent->category()); - Q_ASSERT(item); - - item->increaseTorrentsCount(); - m_rootItem->childAt(0)->increaseTorrentsCount(); -} - -void CategoryFilterModel::torrentAboutToBeRemoved(BitTorrent::TorrentHandle *const torrent) -{ - CategoryModelItem *item = findItem(torrent->category()); - Q_ASSERT(item); - - item->decreaseTorrentsCount(); - m_rootItem->childAt(0)->decreaseTorrentsCount(); -} - -void CategoryFilterModel::torrentCategoryChanged(BitTorrent::TorrentHandle *const torrent, const QString &oldCategory) -{ - QModelIndex i; - - auto item = findItem(oldCategory); - Q_ASSERT(item); - - item->decreaseTorrentsCount(); - i = index(item); - while (i.isValid()) { - emit dataChanged(i, i); - i = parent(i); - } - - item = findItem(torrent->category()); - Q_ASSERT(item); - - item->increaseTorrentsCount(); - i = index(item); - while (i.isValid()) { - emit dataChanged(i, i); - i = parent(i); - } -} - -void CategoryFilterModel::subcategoriesSupportChanged() -{ - beginResetModel(); - populate(); - endResetModel(); -} - -void CategoryFilterModel::populate() -{ - m_rootItem->clear(); - - auto session = BitTorrent::Session::instance(); - auto torrents = session->torrents(); - m_isSubcategoriesEnabled = session->isSubcategoriesEnabled(); - - const QString UID_ALL; - const QString UID_UNCATEGORIZED(QChar(1)); - - // All torrents - m_rootItem->addChild(UID_ALL, new CategoryModelItem(nullptr, tr("All"), torrents.count())); - - // Uncategorized torrents - using Torrent = BitTorrent::TorrentHandle; - m_rootItem->addChild( - UID_UNCATEGORIZED - , new CategoryModelItem( - nullptr, tr("Uncategorized") - , std::count_if(torrents.begin(), torrents.end() - , [](Torrent *torrent) { return torrent->category().isEmpty(); }))); - - using Torrent = BitTorrent::TorrentHandle; - foreach (const QString &category, session->categories()) { - if (m_isSubcategoriesEnabled) { - CategoryModelItem *parent = m_rootItem; - foreach (const QString &subcat, session->expandCategory(category)) { - const QString subcatName = shortName(subcat); - if (!parent->hasChild(subcatName)) { - new CategoryModelItem( - parent, subcatName - , std::count_if(torrents.begin(), torrents.end() - , [subcat](Torrent *torrent) { return torrent->category() == subcat; })); - } - parent = parent->child(subcatName); - } - } - else { - new CategoryModelItem( - m_rootItem, category - , std::count_if(torrents.begin(), torrents.end() - , [category](Torrent *torrent) { return torrent->belongsToCategory(category); })); - } - } -} - -CategoryModelItem *CategoryFilterModel::findItem(const QString &fullName) const -{ - if (fullName.isEmpty()) - return m_rootItem->childAt(1); // "Uncategorized" item - - if (!m_isSubcategoriesEnabled) - return m_rootItem->child(fullName); - - CategoryModelItem *item = m_rootItem; - foreach (const QString &subcat, BitTorrent::Session::expandCategory(fullName)) { - const QString subcatName = shortName(subcat); - if (!item->hasChild(subcatName)) return nullptr; - item = item->child(subcatName); - } - - return item; -} diff --git a/src/gui/categoryfiltermodel.h b/src/gui/categoryfiltermodel.h deleted file mode 100644 index bf186faae..000000000 --- a/src/gui/categoryfiltermodel.h +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2016 Vladimir Golovnev - * - * 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. - */ - -#ifndef CATEGORYFILTERMODEL_H -#define CATEGORYFILTERMODEL_H - -#include -#include -#include - -namespace BitTorrent -{ - class TorrentHandle; -} - -class CategoryModelItem; - -class CategoryFilterModel: public QAbstractItemModel -{ - Q_OBJECT - -public: - explicit CategoryFilterModel(QObject *parent = nullptr); - ~CategoryFilterModel(); - - static bool isSpecialItem(const QModelIndex &index); - - int columnCount(const QModelIndex &parent = QModelIndex()) const override; - QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; - Qt::ItemFlags flags(const QModelIndex &index) const override; - QVariant headerData(int section, Qt::Orientation orientation, int role) const override; - QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override; - QModelIndex parent(const QModelIndex &index) const override; - int rowCount(const QModelIndex &parent = QModelIndex()) const override; - - QModelIndex index(const QString &categoryName) const; - QString categoryName(const QModelIndex &index) const; - -private slots: - void categoryAdded(const QString &categoryName); - void categoryRemoved(const QString &categoryName); - void torrentAdded(BitTorrent::TorrentHandle *const torrent); - void torrentAboutToBeRemoved(BitTorrent::TorrentHandle *const torrent); - void torrentCategoryChanged(BitTorrent::TorrentHandle *const torrent, const QString &oldCategory); - void subcategoriesSupportChanged(); - -private: - void populate(); - QModelIndex index(CategoryModelItem *item) const; - CategoryModelItem *findItem(const QString &fullName) const; - - bool m_isSubcategoriesEnabled; - CategoryModelItem *m_rootItem; -}; - -#endif // CATEGORYFILTERMODEL_H diff --git a/src/gui/categoryfilterproxymodel.cpp b/src/gui/categoryfilterproxymodel.cpp deleted file mode 100644 index 4862aa238..000000000 --- a/src/gui/categoryfilterproxymodel.cpp +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2017 Frédéric Brière - * - * 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. - */ - -#include "categoryfilterproxymodel.h" - -#include "base/utils/string.h" -#include "categoryfiltermodel.h" - -CategoryFilterProxyModel::CategoryFilterProxyModel(QObject *parent) - : QSortFilterProxyModel(parent) -{ -} - -QModelIndex CategoryFilterProxyModel::index(const QString &categoryName) const -{ - return mapFromSource(static_cast(sourceModel())->index(categoryName)); -} - -QString CategoryFilterProxyModel::categoryName(const QModelIndex &index) const -{ - return static_cast(sourceModel())->categoryName(mapToSource(index)); -} - -bool CategoryFilterProxyModel::lessThan(const QModelIndex &left, const QModelIndex &right) const -{ - // "All" and "Uncategorized" must be left in place - if (CategoryFilterModel::isSpecialItem(left) || CategoryFilterModel::isSpecialItem(right)) - return left.row() < right.row(); - else - return Utils::String::naturalCompareCaseInsensitive( - left.data().toString(), right.data().toString()); -} diff --git a/src/gui/categoryfilterproxymodel.h b/src/gui/categoryfilterproxymodel.h deleted file mode 100644 index 2bdeb95e1..000000000 --- a/src/gui/categoryfilterproxymodel.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2017 Frédéric Brière - * - * 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. - */ - -#ifndef CATEGORYFILTERPROXYMODEL_H -#define CATEGORYFILTERPROXYMODEL_H - -#include -#include - -class CategoryFilterProxyModel: public QSortFilterProxyModel -{ -public: - explicit CategoryFilterProxyModel(QObject *parent = nullptr); - - // CategoryFilterModel methods which we need to relay - QModelIndex index(const QString &categoryName) const; - QString categoryName(const QModelIndex &index) const; - -protected: - bool lessThan(const QModelIndex &left, const QModelIndex &right) const override; - -private: - // we added another overload of index(), hence this using directive: - using QSortFilterProxyModel::index; -}; - -#endif // CATEGORYFILTERPROXYMODEL_H diff --git a/src/gui/categoryfilterwidget.cpp b/src/gui/categoryfilterwidget.cpp deleted file mode 100644 index 5422388b6..000000000 --- a/src/gui/categoryfilterwidget.cpp +++ /dev/null @@ -1,262 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2016 Vladimir Golovnev - * - * 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. - */ - -#include "categoryfilterwidget.h" - -#include -#include -#include -#include -#include - -#include "base/bittorrent/session.h" -#include "base/utils/misc.h" -#include "autoexpandabledialog.h" -#include "categoryfiltermodel.h" -#include "categoryfilterproxymodel.h" -#include "guiiconprovider.h" - -namespace -{ - QString getCategoryFilter(const CategoryFilterProxyModel *const model, const QModelIndex &index) - { - QString categoryFilter; // Defaults to All - if (index.isValid()) { - if (!index.parent().isValid() && (index.row() == 1)) - categoryFilter = ""; // Uncategorized - else if (index.parent().isValid() || (index.row() > 1)) - categoryFilter = model->categoryName(index); - } - - return categoryFilter; - } -} - -CategoryFilterWidget::CategoryFilterWidget(QWidget *parent) - : QTreeView(parent) -{ - CategoryFilterProxyModel *proxyModel = new CategoryFilterProxyModel(this); - proxyModel->setSortCaseSensitivity(Qt::CaseInsensitive); - proxyModel->setSourceModel(new CategoryFilterModel(this)); - setModel(proxyModel); - setFrameShape(QFrame::NoFrame); - setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); - setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); - setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); - setUniformRowHeights(true); - setHeaderHidden(true); - setIconSize(Utils::Misc::smallIconSize()); -#ifdef Q_OS_MAC - setAttribute(Qt::WA_MacShowFocusRect, false); - m_defaultIndentation = indentation(); - if (!BitTorrent::Session::instance()->isSubcategoriesEnabled()) - setIndentation(0); -#endif - setContextMenuPolicy(Qt::CustomContextMenu); - sortByColumn(0, Qt::AscendingOrder); - setCurrentIndex(model()->index(0, 0)); - - connect(this, SIGNAL(collapsed(QModelIndex)), SLOT(callUpdateGeometry())); - connect(this, SIGNAL(expanded(QModelIndex)), SLOT(callUpdateGeometry())); - connect(this, SIGNAL(customContextMenuRequested(QPoint)), SLOT(showMenu(QPoint))); - connect(selectionModel(), SIGNAL(currentRowChanged(QModelIndex,QModelIndex)) - , SLOT(onCurrentRowChanged(QModelIndex,QModelIndex))); - connect(model(), SIGNAL(modelReset()), SLOT(callUpdateGeometry())); -} - -QString CategoryFilterWidget::currentCategory() const -{ - QModelIndex current; - auto selectedRows = selectionModel()->selectedRows(); - if (!selectedRows.isEmpty()) - current = selectedRows.first(); - - return getCategoryFilter(static_cast(model()), current); -} - -void CategoryFilterWidget::onCurrentRowChanged(const QModelIndex ¤t, const QModelIndex &previous) -{ - Q_UNUSED(previous); - - emit categoryChanged(getCategoryFilter(static_cast(model()), current)); -} - -void CategoryFilterWidget::showMenu(QPoint) -{ - QMenu menu(this); - - QAction *addAct = menu.addAction( - GuiIconProvider::instance()->getIcon("list-add") - , tr("Add category...")); - connect(addAct, SIGNAL(triggered()), SLOT(addCategory())); - - auto selectedRows = selectionModel()->selectedRows(); - if (!selectedRows.empty() && !CategoryFilterModel::isSpecialItem(selectedRows.first())) { - if (BitTorrent::Session::instance()->isSubcategoriesEnabled()) { - QAction *addSubAct = menu.addAction( - GuiIconProvider::instance()->getIcon("list-add") - , tr("Add subcategory...")); - connect(addSubAct, SIGNAL(triggered()), SLOT(addSubcategory())); - } - - QAction *removeAct = menu.addAction( - GuiIconProvider::instance()->getIcon("list-remove") - , tr("Remove category")); - connect(removeAct, SIGNAL(triggered()), SLOT(removeCategory())); - } - - QAction *removeUnusedAct = menu.addAction( - GuiIconProvider::instance()->getIcon("list-remove") - , tr("Remove unused categories")); - connect(removeUnusedAct, SIGNAL(triggered()), SLOT(removeUnusedCategories())); - - menu.addSeparator(); - - QAction *startAct = menu.addAction( - GuiIconProvider::instance()->getIcon("media-playback-start") - , tr("Resume torrents")); - connect(startAct, SIGNAL(triggered()), SIGNAL(actionResumeTorrentsTriggered())); - - QAction *pauseAct = menu.addAction( - GuiIconProvider::instance()->getIcon("media-playback-pause") - , tr("Pause torrents")); - connect(pauseAct, SIGNAL(triggered()), SIGNAL(actionPauseTorrentsTriggered())); - - QAction *deleteTorrentsAct = menu.addAction( - GuiIconProvider::instance()->getIcon("edit-delete") - , tr("Delete torrents")); - connect(deleteTorrentsAct, SIGNAL(triggered()), SIGNAL(actionDeleteTorrentsTriggered())); - - menu.exec(QCursor::pos()); -} - -void CategoryFilterWidget::callUpdateGeometry() -{ -#ifdef Q_OS_MAC - if (!BitTorrent::Session::instance()->isSubcategoriesEnabled()) - setIndentation(0); - else - setIndentation(m_defaultIndentation); -#endif - updateGeometry(); -} - -QSize CategoryFilterWidget::sizeHint() const -{ - return viewportSizeHint(); -} - -QSize CategoryFilterWidget::minimumSizeHint() const -{ - QSize size = sizeHint(); - size.setWidth(6); - return size; -} - -void CategoryFilterWidget::rowsInserted(const QModelIndex &parent, int start, int end) -{ - QTreeView::rowsInserted(parent, start, end); - - // Expand all parents if the parent(s) of the node are not expanded. - QModelIndex p = parent; - while (p.isValid()) { - if (!isExpanded(p)) - expand(p); - p = model()->parent(p); - } - - updateGeometry(); -} - -QString CategoryFilterWidget::askCategoryName() -{ - bool ok; - QString category = ""; - bool invalid; - do { - invalid = false; - category = AutoExpandableDialog::getText( - this, tr("New Category"), tr("Category:"), QLineEdit::Normal, category, &ok); - if (ok && !category.isEmpty()) { - if (!BitTorrent::Session::isValidCategoryName(category)) { - QMessageBox::warning( - this, tr("Invalid category name") - , tr("Category name must not contain '\\'.\n" - "Category name must not start/end with '/'.\n" - "Category name must not contain '//' sequence.")); - invalid = true; - } - } - } while (invalid); - - return ok ? category : QString(); -} - -void CategoryFilterWidget::addCategory() -{ - const QString category = askCategoryName(); - if (category.isEmpty()) return; - - if (BitTorrent::Session::instance()->categories().contains(category)) - QMessageBox::warning(this, tr("Category exists"), tr("Category name already exists.")); - else - BitTorrent::Session::instance()->addCategory(category); -} - -void CategoryFilterWidget::addSubcategory() -{ - const QString subcat = askCategoryName(); - if (subcat.isEmpty()) return; - - const QString category = QString(QStringLiteral("%1/%2")).arg(currentCategory()).arg(subcat); - - if (BitTorrent::Session::instance()->categories().contains(category)) - QMessageBox::warning(this, tr("Category exists") - , tr("Subcategory name already exists in selected category.")); - else - BitTorrent::Session::instance()->addCategory(category); -} - -void CategoryFilterWidget::removeCategory() -{ - auto selectedRows = selectionModel()->selectedRows(); - if (!selectedRows.empty() && !CategoryFilterModel::isSpecialItem(selectedRows.first())) { - BitTorrent::Session::instance()->removeCategory( - static_cast(model())->categoryName(selectedRows.first())); - updateGeometry(); - } -} - -void CategoryFilterWidget::removeUnusedCategories() -{ - auto session = BitTorrent::Session::instance(); - foreach (const QString &category, session->categories()) - if (model()->data(static_cast(model())->index(category), Qt::UserRole) == 0) - session->removeCategory(category); - updateGeometry(); -} diff --git a/src/gui/categoryfilterwidget.h b/src/gui/categoryfilterwidget.h deleted file mode 100644 index 9c6df0e59..000000000 --- a/src/gui/categoryfilterwidget.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2016 Vladimir Golovnev - * - * 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. - */ - - #include - -class CategoryFilterWidget: public QTreeView -{ - Q_OBJECT - -public: - explicit CategoryFilterWidget(QWidget *parent = nullptr); - - QString currentCategory() const; - -signals: - void categoryChanged(const QString &categoryName); - void actionResumeTorrentsTriggered(); - void actionPauseTorrentsTriggered(); - void actionDeleteTorrentsTriggered(); - -private slots: - void onCurrentRowChanged(const QModelIndex ¤t, const QModelIndex &previous); - void showMenu(QPoint); - void callUpdateGeometry(); - void addCategory(); - void addSubcategory(); - void removeCategory(); - void removeUnusedCategories(); - -private: - QSize sizeHint() const override; - QSize minimumSizeHint() const override; - void rowsInserted(const QModelIndex &parent, int start, int end) override; - QString askCategoryName(); - -#ifdef Q_OS_MAC - int m_defaultIndentation; -#endif -}; diff --git a/src/gui/confirmdeletiondlg.ui b/src/gui/confirmdeletiondlg.ui deleted file mode 100644 index acb55a35a..000000000 --- a/src/gui/confirmdeletiondlg.ui +++ /dev/null @@ -1,153 +0,0 @@ - - - confirmDeletionDlg - - - - 0 - 0 - 463 - 128 - - - - - 0 - 0 - - - - Deletion confirmation - - - - - - - - - 0 - 0 - - - - - - - - - - - - 0 - 0 - - - - deletion message goes here - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter - - - true - - - - - - - - - - - false - - - Remember choice - - - - - - - 24 - 24 - - - - - - - - - 0 - 0 - - - - - true - - - - Also delete the files on the hard disk - - - - - - - - - - 0 - 0 - - - - Qt::Horizontal - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - - - - - - - buttonBox - accepted() - confirmDeletionDlg - accept() - - - 248 - 254 - - - 157 - 274 - - - - - buttonBox - rejected() - confirmDeletionDlg - reject() - - - 316 - 260 - - - 286 - 274 - - - - - diff --git a/src/gui/cookiesdialog.cpp b/src/gui/cookiesdialog.cpp deleted file mode 100644 index f030a52b6..000000000 --- a/src/gui/cookiesdialog.cpp +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2016 Vladimir Golovnev - * - * 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. - */ - -#include "cookiesdialog.h" - -#include - -#include "base/settingsstorage.h" -#include "base/net/downloadmanager.h" -#include "guiiconprovider.h" -#include "cookiesmodel.h" -#include "ui_cookiesdialog.h" - -#define SETTINGS_KEY(name) "CookiesDialog/" name -const QString KEY_SIZE = SETTINGS_KEY("Size"); -const QString KEY_COOKIESVIEWSTATE = SETTINGS_KEY("CookiesViewState"); - -CookiesDialog::CookiesDialog(QWidget *parent) - : QDialog(parent) - , m_ui(new Ui::CookiesDialog) - , m_cookiesModel(new CookiesModel(Net::DownloadManager::instance()->allCookies(), this)) -{ - m_ui->setupUi(this); - - setWindowIcon(GuiIconProvider::instance()->getIcon("preferences-web-browser-cookies")); - m_ui->buttonAdd->setIcon(GuiIconProvider::instance()->getIcon("list-add")); - m_ui->buttonDelete->setIcon(GuiIconProvider::instance()->getIcon("list-remove")); - - m_ui->treeView->setModel(m_cookiesModel); - if (m_cookiesModel->rowCount() > 0) - m_ui->treeView->selectionModel()->setCurrentIndex( - m_cookiesModel->index(0, 0), - QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows); - - resize(SettingsStorage::instance()->loadValue(KEY_SIZE, size()).toSize()); - m_ui->treeView->header()->restoreState( - SettingsStorage::instance()->loadValue(KEY_COOKIESVIEWSTATE).toByteArray()); -} - -CookiesDialog::~CookiesDialog() -{ - SettingsStorage::instance()->storeValue(KEY_SIZE, size()); - SettingsStorage::instance()->storeValue( - KEY_COOKIESVIEWSTATE, m_ui->treeView->header()->saveState()); - delete m_ui; -} - -void CookiesDialog::accept() -{ - Net::DownloadManager::instance()->setAllCookies(m_cookiesModel->cookies()); - QDialog::accept(); -} - -void CookiesDialog::onButtonAddClicked() -{ - int row = m_ui->treeView->selectionModel()->currentIndex().row() + 1; - - m_cookiesModel->insertRow(row); - m_ui->treeView->selectionModel()->setCurrentIndex( - m_cookiesModel->index(row, 0), QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows); -} - -void CookiesDialog::onButtonDeleteClicked() -{ - QModelIndexList idxs = m_ui->treeView->selectionModel()->selectedRows(); - - // sort in descending order - std::sort(idxs.begin(), idxs.end(), - [](const QModelIndex &l, const QModelIndex &r) - { - return (l.row() > r.row()); - } - ); - - for (const QModelIndex &idx : idxs) - m_cookiesModel->removeRow(idx.row()); -} diff --git a/src/gui/cookiesdialog.h b/src/gui/cookiesdialog.h deleted file mode 100644 index 39cdf77cf..000000000 --- a/src/gui/cookiesdialog.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2016 Vladimir Golovnev - * - * 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. - */ - -#ifndef COOKIESDIALOG_H -#define COOKIESDIALOG_H - -#include - -namespace Ui -{ - class CookiesDialog; -} - -class CookiesModel; - -class CookiesDialog : public QDialog -{ - Q_OBJECT - -public: - explicit CookiesDialog(QWidget *parent = 0); - ~CookiesDialog(); - -public slots: - void accept() override; - -private slots: - void onButtonAddClicked(); - void onButtonDeleteClicked(); - -private: - Ui::CookiesDialog *m_ui; - CookiesModel *m_cookiesModel; -}; - -#endif // COOKIESDIALOG_H diff --git a/src/gui/cookiesdialog.ui b/src/gui/cookiesdialog.ui deleted file mode 100644 index 0f08a69d9..000000000 --- a/src/gui/cookiesdialog.ui +++ /dev/null @@ -1,189 +0,0 @@ - - - CookiesDialog - - - - 0 - 0 - 618 - 369 - - - - Manage Cookies - - - - - - - - QAbstractItemView::AllEditTriggers - - - true - - - QAbstractItemView::ExtendedSelection - - - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - - - - 20 - 20 - - - - - - - - Qt::Vertical - - - QSizePolicy::Fixed - - - - 20 - 5 - - - - - - - - - - - - 20 - 20 - - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - - - - Qt::Horizontal - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - - - - - - - buttonBox - accepted() - CookiesDialog - accept() - - - 257 - 406 - - - 157 - 274 - - - - - buttonBox - rejected() - CookiesDialog - reject() - - - 325 - 406 - - - 286 - 274 - - - - - buttonAdd - clicked() - CookiesDialog - onButtonAddClicked() - - - 484 - 174 - - - 486 - 93 - - - - - buttonDelete - clicked() - CookiesDialog - onButtonDeleteClicked() - - - 483 - 226 - - - 485 - 296 - - - - - - onButtonAddClicked() - onButtonDeleteClicked() - - diff --git a/src/gui/cookiesmodel.cpp b/src/gui/cookiesmodel.cpp deleted file mode 100644 index 7c283a66f..000000000 --- a/src/gui/cookiesmodel.cpp +++ /dev/null @@ -1,178 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2016 Vladimir Golovnev - * - * 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. - */ - -#include -#include "cookiesmodel.h" - -CookiesModel::CookiesModel(const QList &cookies, QObject *parent) - : QAbstractItemModel(parent) - , m_cookies(cookies) -{ -} - -QList CookiesModel::cookies() const -{ - return m_cookies; -} - -QVariant CookiesModel::headerData(int section, Qt::Orientation orientation, int role) const -{ - if ((role == Qt::DisplayRole) && (orientation == Qt::Horizontal)) { - switch (section) - { - case COL_DOMAIN: - return tr("Domain"); - case COL_PATH: - return tr("Path"); - case COL_NAME: - return tr("Name"); - case COL_VALUE: - return tr("Value"); - case COL_EXPDATE: - return tr("Expiration Date"); - } - } - - return QVariant(); -} - -QModelIndex CookiesModel::index(int row, int column, const QModelIndex &parent) const -{ - if (parent.isValid() // no items with valid parent - || (row < 0) || (row >= m_cookies.size()) - || (column < 0) || (column >= NB_COLUMNS)) - return QModelIndex(); - - return createIndex(row, column, &m_cookies[row]); -} - -QModelIndex CookiesModel::parent(const QModelIndex &index) const -{ - Q_UNUSED(index); - return QModelIndex(); -} - -int CookiesModel::rowCount(const QModelIndex &parent) const -{ - if (parent.isValid()) return 0; - - return m_cookies.size(); -} - -int CookiesModel::columnCount(const QModelIndex &parent) const -{ - Q_UNUSED(parent); - return NB_COLUMNS; -} - -QVariant CookiesModel::data(const QModelIndex &index, int role) const -{ - if (!index.isValid() || (index.row() >= m_cookies.size()) - || ((role != Qt::DisplayRole) && (role != Qt::EditRole))) - return QVariant(); - - switch (index.column()) { - case COL_DOMAIN: - return m_cookies[index.row()].domain(); - case COL_PATH: - return m_cookies[index.row()].path(); - case COL_NAME: - return QString::fromLatin1(m_cookies[index.row()].name()); - case COL_VALUE: - return QString::fromLatin1(m_cookies[index.row()].value()); - case COL_EXPDATE: - return m_cookies[index.row()].expirationDate(); - } - - return QVariant(); -} - -bool CookiesModel::setData(const QModelIndex &index, const QVariant &value, int role) -{ - if (role != Qt::EditRole) return false; - - switch (index.column()) { - case COL_DOMAIN: - m_cookies[index.row()].setDomain(value.toString()); - break; - case COL_PATH: - m_cookies[index.row()].setPath(value.toString()); - break; - case COL_NAME: - m_cookies[index.row()].setName(value.toString().toLatin1()); - break; - case COL_VALUE: - m_cookies[index.row()].setValue(value.toString().toLatin1()); - break; - case COL_EXPDATE: - m_cookies[index.row()].setExpirationDate(value.toDateTime()); - break; - default: - return false; - } - - emit dataChanged(index, index); - return true; -} - -bool CookiesModel::insertRows(int row, int count, const QModelIndex &parent) -{ - if ((row < 0) || (row > m_cookies.size())) return false; - - QNetworkCookie newCookie; - newCookie.setExpirationDate(QDateTime::currentDateTime().addYears(2)); - - beginInsertRows(parent, row, row + count - 1); - while (count-- > 0) - m_cookies.insert(row, newCookie); - endInsertRows(); - - return true; -} - -bool CookiesModel::removeRows(int row, int count, const QModelIndex &parent) -{ - if ((m_cookies.size() == 0) - || (row >= m_cookies.size()) - || ((row + count) > m_cookies.size())) - return false; - - beginRemoveRows(parent, row, row + count - 1); - while (count-- > 0) - m_cookies.removeAt(row); - endRemoveRows(); - - return true; -} - -Qt::ItemFlags CookiesModel::flags(const QModelIndex &index) const -{ - if (!index.isValid()) return 0; - - return Qt::ItemIsEditable | QAbstractItemModel::flags(index); -} diff --git a/src/gui/cookiesmodel.h b/src/gui/cookiesmodel.h deleted file mode 100644 index 098596b4e..000000000 --- a/src/gui/cookiesmodel.h +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2016 Vladimir Golovnev - * - * 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. - */ - -#ifndef COOKIESMODEL_H -#define COOKIESMODEL_H - -#include -#include -#include - -class CookiesModel : public QAbstractItemModel -{ - Q_OBJECT - -public: - enum Column - { - COL_DOMAIN, - COL_PATH, - COL_NAME, - COL_VALUE, - COL_EXPDATE, - - NB_COLUMNS - }; - - explicit CookiesModel(const QList &cookies, QObject *parent = 0); - - QList cookies() const; - - QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; - QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override; - QModelIndex parent(const QModelIndex &index) const override; - - int rowCount(const QModelIndex &parent = QModelIndex()) const override; - int columnCount(const QModelIndex &parent = QModelIndex()) const override; - - Qt::ItemFlags flags(const QModelIndex &index) const override; - QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; - - bool setData(const QModelIndex &index, const QVariant &value, int role) override; - bool insertRows(int row, int count, const QModelIndex &parent = QModelIndex()) override; - bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex()) override; - -private: - mutable QList m_cookies; -}; - -#endif // COOKIESMODEL_H diff --git a/src/gui/deletionconfirmationdlg.h b/src/gui/deletionconfirmationdlg.h deleted file mode 100644 index 37e7acde1..000000000 --- a/src/gui/deletionconfirmationdlg.h +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Bittorrent Client using Qt4 and libtorrent. - * Copyright (C) 2006 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 DELETIONCONFIRMATIONDLG_H -#define DELETIONCONFIRMATIONDLG_H - -#include -#include -#include "ui_confirmdeletiondlg.h" -#include "base/preferences.h" -#include "base/utils/misc.h" -#include "base/utils/string.h" -#include "guiiconprovider.h" - -class DeletionConfirmationDlg : public QDialog, private Ui::confirmDeletionDlg { - Q_OBJECT - - public: - DeletionConfirmationDlg(QWidget *parent, const int &size, const QString &name, bool defaultDeleteFiles): 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.toHtmlEscaped())); - 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(GuiIconProvider::instance()->getIcon("dialog-warning").pixmap(lbl_warn->height())); - lbl_warn->setFixedWidth(lbl_warn->height()); - rememberBtn->setIcon(GuiIconProvider::instance()->getIcon("object-locked")); - - checkPermDelete->setChecked(defaultDeleteFiles || Preferences::instance()->deleteTorrentFilesAsDefault()); - connect(checkPermDelete, SIGNAL(clicked()), this, SLOT(updateRememberButtonState())); - buttonBox->button(QDialogButtonBox::Cancel)->setFocus(); - } - - bool shouldDeleteLocalFiles() const { - return checkPermDelete->isChecked(); - } - - static bool askForDeletionConfirmation(QWidget *parent, bool& deleteLocalFiles, const int& size, const QString& name) { - DeletionConfirmationDlg dlg(parent, size, name, deleteLocalFiles); - if (dlg.exec() == QDialog::Accepted) { - deleteLocalFiles = dlg.shouldDeleteLocalFiles(); - return true; - } - return false; - } - -private slots: - void updateRememberButtonState() { - rememberBtn->setEnabled(checkPermDelete->isChecked() != Preferences::instance()->deleteTorrentFilesAsDefault()); - } - - void on_rememberBtn_clicked() { - Preferences::instance()->setDeleteTorrentFilesAsDefault(checkPermDelete->isChecked()); - rememberBtn->setEnabled(false); - } -}; - -#endif // DELETIONCONFIRMATIONDLG_H diff --git a/src/gui/downloadfromurldlg.h b/src/gui/downloadfromurldlg.h deleted file mode 100644 index cd05aeb17..000000000 --- a/src/gui/downloadfromurldlg.h +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Bittorrent Client using Qt4 and libtorrent. - * Copyright (C) 2006 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 DOWNLOADFROMURL_H -#define DOWNLOADFROMURL_H - -#include -#include -#include -#include -#include -#include -#include "ui_downloadfromurldlg.h" - -class downloadFromURL : public QDialog, private Ui::downloadFromURL{ - Q_OBJECT - - public: - downloadFromURL(QWidget *parent): QDialog(parent) { - setupUi(this); - setAttribute(Qt::WA_DeleteOnClose); - setModal(true); - - // 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_list_cleaned.size() > 0) - textUrls->setText(clip_txt_list_cleaned.join("\n")); - - show(); - } - - ~downloadFromURL() {} - - signals: - void urlsReadyToBeDownloaded(const QStringList& torrent_urls); - - public slots: - 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) { - url = url.trimmed(); - if (!url.isEmpty()) { - if (url_list_cleaned.indexOf(QRegExp(url, Qt::CaseInsensitive, QRegExp::FixedString)) < 0) { - url_list_cleaned << url; - } - } - } - if (!url_list_cleaned.size()) { - QMessageBox::warning(this, 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() { - close(); - } -}; - -#endif diff --git a/src/gui/downloadfromurldlg.ui b/src/gui/downloadfromurldlg.ui deleted file mode 100644 index a701e7f99..000000000 --- a/src/gui/downloadfromurldlg.ui +++ /dev/null @@ -1,100 +0,0 @@ - - - downloadFromURL - - - - 0 - 0 - 482 - 220 - - - - Download from URLs - - - - - - - 75 - true - - - - Add torrent links - - - - - - - true - - - false - - - - - - - - true - - - - One link per line (HTTP links, Magnet links and info-hashes are supported) - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - Download - - - - - - - Cancel - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - - diff --git a/src/gui/executionlog.cpp b/src/gui/executionlog.cpp deleted file mode 100644 index b286f0ed4..000000000 --- a/src/gui/executionlog.cpp +++ /dev/null @@ -1,113 +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 -#include -#include -#include -#include -#include "executionlog.h" -#include "ui_executionlog.h" -#include "guiiconprovider.h" -#include "loglistwidget.h" - -ExecutionLog::ExecutionLog(QWidget *parent, const Log::MsgTypes &types) - : QWidget(parent) - , ui(new Ui::ExecutionLog) - , m_peerList(new LogListWidget(MAX_LOG_MESSAGES)) -{ - ui->setupUi(this); - - m_msgList = new LogListWidget(MAX_LOG_MESSAGES, Log::MsgTypes(types)); - -#ifndef Q_OS_MAC - ui->tabConsole->setTabIcon(0, GuiIconProvider::instance()->getIcon("view-calendar-journal")); - ui->tabConsole->setTabIcon(1, GuiIconProvider::instance()->getIcon("view-filter")); -#endif - ui->tabGeneral->layout()->addWidget(m_msgList); - ui->tabBan->layout()->addWidget(m_peerList); - - const Logger* const logger = Logger::instance(); - foreach (const Log::Msg& msg, logger->getMessages()) - addLogMessage(msg); - foreach (const Log::Peer& peer, logger->getPeers()) - addPeerMessage(peer); - connect(logger, SIGNAL(newLogMessage(const Log::Msg &)), SLOT(addLogMessage(const Log::Msg &))); - connect(logger, SIGNAL(newLogPeer(const Log::Peer &)), SLOT(addPeerMessage(const Log::Peer &))); -} - -ExecutionLog::~ExecutionLog() -{ - delete m_msgList; - delete m_peerList; - delete ui; -} - -void ExecutionLog::showMsgTypes(const Log::MsgTypes &types) -{ - m_msgList->showMsgTypes(types); -} - -void ExecutionLog::addLogMessage(const Log::Msg &msg) -{ - QString text; - QDateTime time = QDateTime::fromMSecsSinceEpoch(msg.timestamp); - QColor color; - - switch (msg.type) { - case Log::INFO: - color.setNamedColor("blue"); - break; - case Log::WARNING: - color.setNamedColor("orange"); - break; - case Log::CRITICAL: - color.setNamedColor("red"); - break; - default: - color = QApplication::palette().color(QPalette::WindowText); - } - - text = "" + time.toString(Qt::SystemLocaleShortDate) + " - " + msg.message + ""; - m_msgList->appendLine(text, msg.type); -} - -void ExecutionLog::addPeerMessage(const Log::Peer& peer) -{ - QString text; - QDateTime time = QDateTime::fromMSecsSinceEpoch(peer.timestamp); - - if (peer.blocked) - text = "" + time.toString(Qt::SystemLocaleShortDate) + " - " + tr("%1 was blocked %2", "x.y.z.w was blocked").arg(peer.ip).arg(peer.reason); - else - text = "" + time.toString(Qt::SystemLocaleShortDate) + " - " + tr("%1 was banned", "x.y.z.w was banned").arg(peer.ip); - - m_peerList->appendLine(text, Log::NORMAL); -} diff --git a/src/gui/executionlog.h b/src/gui/executionlog.h deleted file mode 100644 index 7422398f8..000000000 --- a/src/gui/executionlog.h +++ /dev/null @@ -1,64 +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 EXECUTIONLOG_H -#define EXECUTIONLOG_H - -#include -#include "base/logger.h" - -QT_BEGIN_NAMESPACE -namespace Ui { - class ExecutionLog; -} -QT_END_NAMESPACE -class LogListWidget; - -class ExecutionLog: public QWidget -{ - Q_OBJECT - -public: - ExecutionLog(QWidget *parent, const Log::MsgTypes &types); - void showMsgTypes(const Log::MsgTypes &types); - ~ExecutionLog(); - -private slots: - void addLogMessage(const Log::Msg &msg); - void addPeerMessage(const Log::Peer &peer); - -private: - Ui::ExecutionLog *ui; - - LogListWidget *m_msgList; - LogListWidget *m_peerList; -}; - -#endif // EXECUTIONLOG_H diff --git a/src/gui/executionlog.ui b/src/gui/executionlog.ui deleted file mode 100644 index 1f12063fd..000000000 --- a/src/gui/executionlog.ui +++ /dev/null @@ -1,55 +0,0 @@ - - - ExecutionLog - - - - 0 - 0 - 400 - 300 - - - - Form - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - QTabWidget::East - - - 0 - - - - General - - - - - - Blocked IPs - - - - - - - - - - diff --git a/src/gui/fspathedit.cpp b/src/gui/fspathedit.cpp deleted file mode 100644 index 66d3ed314..000000000 --- a/src/gui/fspathedit.cpp +++ /dev/null @@ -1,372 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2016 Eugene Shalygin - * - * 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. - */ - -#include "fspathedit.h" - -#include -#include -#include -#include -#include -#include - -#include "base/utils/fs.h" -#include "fspathedit_p.h" - -namespace -{ - struct TrStringWithComment - { - const char *source; - const char *comment; - - QString tr() const - { - return QObject::tr(source, comment); - } - }; - - constexpr TrStringWithComment browseButtonBriefText = - QT_TRANSLATE_NOOP3("FileSystemPathEdit", "...", "Launch file dialog button text (brief)"); - constexpr TrStringWithComment browseButtonFullText = - QT_TRANSLATE_NOOP3("FileSystemPathEdit", "&Browse...", "Launch file dialog button text (full)"); - constexpr TrStringWithComment defaultDialogCaptionForFile = - QT_TRANSLATE_NOOP3("FileSystemPathEdit", "Choose a file", "Caption for file open/save dialog"); - constexpr TrStringWithComment defaultDialogCaptionForDirectory = - QT_TRANSLATE_NOOP3("FileSystemPathEdit", "Choose a folder", "Caption for directory open dialog"); -} - -class FileSystemPathEdit::FileSystemPathEditPrivate -{ - Q_DECLARE_PUBLIC(FileSystemPathEdit) - Q_DISABLE_COPY(FileSystemPathEditPrivate) - - FileSystemPathEditPrivate(FileSystemPathEdit *q, Private::FileEditorWithCompletion *editor); - - void modeChanged(); - void browseActionTriggered(); - QString dialogCaptionOrDefault() const; - - FileSystemPathEdit *q_ptr; - QScopedPointer m_editor; - QAction *m_browseAction; - QToolButton *m_browseBtn; - QString m_fileNameFilter; - Mode m_mode; - QString m_lastSignaledPath; - QString m_dialogCaption; - Private::FileSystemPathValidator *m_validator; -}; - -FileSystemPathEdit::FileSystemPathEditPrivate::FileSystemPathEditPrivate( - FileSystemPathEdit *q, Private::FileEditorWithCompletion *editor) - : q_ptr {q} - , m_editor {editor} - , m_browseAction {new QAction(q)} - , m_browseBtn {new QToolButton(q)} - , m_mode {FileSystemPathEdit::Mode::FileOpen} - , m_validator {new Private::FileSystemPathValidator(q)} -{ - m_browseAction->setIconText(browseButtonBriefText.tr()); - m_browseAction->setText(browseButtonFullText.tr()); - m_browseAction->setToolTip(browseButtonFullText.tr().remove(QLatin1Char('&'))); - m_browseAction->setShortcut(Qt::CTRL + Qt::Key_B); - m_browseBtn->setDefaultAction(m_browseAction); - m_fileNameFilter = tr("Any file") + QLatin1String(" (*)"); - m_editor->setBrowseAction(m_browseAction); - m_validator->setStrictMode(false); - m_editor->setValidator(m_validator); - modeChanged(); -} - -void FileSystemPathEdit::FileSystemPathEditPrivate::browseActionTriggered() -{ - Q_Q(FileSystemPathEdit); - QString filter = q->fileNameFilter(); - QString directory = q->currentDirectory().isEmpty() ? QDir::homePath() : q->currentDirectory(); - - QString selectedPath; - switch (m_mode) { - case FileSystemPathEdit::Mode::FileOpen: - selectedPath = QFileDialog::getOpenFileName(q, dialogCaptionOrDefault(), directory, filter); - break; - case FileSystemPathEdit::Mode::FileSave: - selectedPath = QFileDialog::getSaveFileName(q, dialogCaptionOrDefault(), directory, filter, &filter); - break; - case FileSystemPathEdit::Mode::DirectoryOpen: - case FileSystemPathEdit::Mode::DirectorySave: - selectedPath = QFileDialog::getExistingDirectory(q, dialogCaptionOrDefault(), - directory, QFileDialog::DontResolveSymlinks | QFileDialog::ShowDirsOnly); - break; - default: - throw std::logic_error("Unknown FileSystemPathEdit mode"); - } - if (!selectedPath.isEmpty()) - q->setEditWidgetText(selectedPath); -} - -QString FileSystemPathEdit::FileSystemPathEditPrivate::dialogCaptionOrDefault() const -{ - if (!m_dialogCaption.isEmpty()) - return m_dialogCaption; - - switch (m_mode) { - case FileSystemPathEdit::Mode::FileOpen: - case FileSystemPathEdit::Mode::FileSave: - return defaultDialogCaptionForFile.tr(); - case FileSystemPathEdit::Mode::DirectoryOpen: - case FileSystemPathEdit::Mode::DirectorySave: - return defaultDialogCaptionForDirectory.tr(); - default: - throw std::logic_error("Unknown FileSystemPathEdit mode"); - } -} - -void FileSystemPathEdit::FileSystemPathEditPrivate::modeChanged() -{ - QStyle::StandardPixmap pixmap = QStyle::SP_DialogOpenButton; - bool showDirsOnly = false; - switch (m_mode) { - case FileSystemPathEdit::Mode::FileOpen: - case FileSystemPathEdit::Mode::FileSave: - pixmap = QStyle::SP_DialogOpenButton; - showDirsOnly = false; - break; - case FileSystemPathEdit::Mode::DirectoryOpen: - case FileSystemPathEdit::Mode::DirectorySave: - pixmap = QStyle::SP_DirOpenIcon; - showDirsOnly = true; - break; - default: - throw std::logic_error("Unknown FileSystemPathEdit mode"); - } - m_browseAction->setIcon(QApplication::style()->standardIcon(pixmap)); - m_editor->completeDirectoriesOnly(showDirsOnly); - - m_validator->setExistingOnly(m_mode != FileSystemPathEdit::Mode::FileSave); - m_validator->setDirectoriesOnly((m_mode == FileSystemPathEdit::Mode::DirectoryOpen) || (m_mode == FileSystemPathEdit::Mode::DirectorySave)); - m_validator->setCheckReadPermission((m_mode == FileSystemPathEdit::Mode::FileOpen) || (m_mode == FileSystemPathEdit::Mode::DirectoryOpen)); - m_validator->setCheckWritePermission((m_mode == FileSystemPathEdit::Mode::FileSave) || (m_mode == FileSystemPathEdit::Mode::DirectorySave)); -} - -FileSystemPathEdit::FileSystemPathEdit(Private::FileEditorWithCompletion *editor, QWidget *parent) - : QWidget(parent) - , d_ptr(new FileSystemPathEditPrivate(this, editor)) -{ - Q_D(FileSystemPathEdit); - editor->widget()->setParent(this); - - QHBoxLayout *layout = new QHBoxLayout(this); - layout->addWidget(editor->widget()); - layout->addWidget(d->m_browseBtn); - - connect(d->m_browseAction, &QAction::triggered, [this]() {this->d_func()->browseActionTriggered();}); -} - -FileSystemPathEdit::~FileSystemPathEdit() = default; - -QString FileSystemPathEdit::selectedPath() const -{ - return Utils::Fs::fromNativePath(editWidgetText()); -} - -void FileSystemPathEdit::setSelectedPath(const QString &val) -{ - Q_D(FileSystemPathEdit); - setEditWidgetText(Utils::Fs::toNativePath(val)); - d->m_editor->widget()->setToolTip(val); -} - -QString FileSystemPathEdit::fileNameFilter() const -{ - Q_D(const FileSystemPathEdit); - return d->m_fileNameFilter; -} - -void FileSystemPathEdit::setFileNameFilter(const QString &val) -{ - Q_D(FileSystemPathEdit); - d->m_fileNameFilter = val; - -#if 0 - // QFileSystemModel applies name filters to directories too. - // To use the filters we have to subclass QFileSystemModel and skip directories while filtering - // extract file masks - const int openBracePos = val.indexOf(QLatin1Char('('), 0); - const int closeBracePos = val.indexOf(QLatin1Char(')'), openBracePos + 1); - if ((openBracePos > 0) && (closeBracePos > 0) && (closeBracePos > openBracePos + 2)) { - QString filterString = val.mid(openBracePos + 1, closeBracePos - openBracePos - 1); - if (filterString == QLatin1String("*")) { // no filters - d->m_editor->setFilenameFilters({}); - } - else { - QStringList filters = filterString.split(QLatin1Char(' '), QString::SkipEmptyParts); - d->m_editor->setFilenameFilters(filters); - } - } - else { - d->m_editor->setFilenameFilters({}); - } -#endif -} - -bool FileSystemPathEdit::briefBrowseButtonCaption() const -{ - Q_D(const FileSystemPathEdit); - return d->m_browseBtn->text() == browseButtonBriefText.tr(); -} - -void FileSystemPathEdit::setBriefBrowseButtonCaption(bool brief) -{ - Q_D(FileSystemPathEdit); - d->m_browseBtn->setText(brief ? browseButtonBriefText.tr() : browseButtonFullText.tr()); -} - -void FileSystemPathEdit::onPathEdited() -{ - Q_D(FileSystemPathEdit); - QString newPath = selectedPath(); - if (newPath != d->m_lastSignaledPath) { - emit selectedPathChanged(newPath); - d->m_lastSignaledPath = newPath; - d->m_editor->widget()->setToolTip(editWidgetText()); - } -} - -FileSystemPathEdit::Mode FileSystemPathEdit::mode() const -{ - Q_D(const FileSystemPathEdit); - return d->m_mode; -} - -void FileSystemPathEdit::setMode(FileSystemPathEdit::Mode theMode) -{ - Q_D(FileSystemPathEdit); - d->m_mode = theMode; - d->modeChanged(); -} - -QString FileSystemPathEdit::dialogCaption() const -{ - Q_D(const FileSystemPathEdit); - return d->m_dialogCaption; -} - -void FileSystemPathEdit::setDialogCaption(const QString &caption) -{ - Q_D(FileSystemPathEdit); - d->m_dialogCaption = caption; -} - -QString FileSystemPathEdit::currentDirectory() const -{ - return QFileInfo(selectedPath()).absoluteDir().absolutePath(); -} - -QWidget *FileSystemPathEdit::editWidgetImpl() const -{ - Q_D(const FileSystemPathEdit); - return d->m_editor->widget(); -} - -// ------------------------- FileSystemPathLineEdit ---------------------- -FileSystemPathLineEdit::FileSystemPathLineEdit(QWidget *parent) - : FileSystemPathEdit(new WidgetType(), parent) -{ - connect(editWidget(), &QLineEdit::editingFinished, this, &FileSystemPathLineEdit::onPathEdited); - connect(editWidget(), &QLineEdit::textChanged, this, &FileSystemPathLineEdit::onPathEdited); -} - -QString FileSystemPathLineEdit::editWidgetText() const -{ - return editWidget()->text(); -} - -void FileSystemPathLineEdit::clear() -{ - editWidget()->clear(); -} - -void FileSystemPathLineEdit::setEditWidgetText(const QString &text) -{ - editWidget()->setText(text); -} - -// ----------------------- FileSystemPathComboEdit ----------------------- -FileSystemPathComboEdit::FileSystemPathComboEdit(QWidget *parent) - : FileSystemPathEdit(new WidgetType(), parent) -{ - editWidget()->setEditable(true); - connect(editWidget(), &QComboBox::currentTextChanged, this, &FileSystemPathComboEdit::onPathEdited); - connect(editWidget()->lineEdit(), &QLineEdit::editingFinished, this, &FileSystemPathComboEdit::onPathEdited); -} - -void FileSystemPathComboEdit::clear() -{ - editWidget()->clear(); -} - -int FileSystemPathComboEdit::count() const -{ - return editWidget()->count(); -} - -QString FileSystemPathComboEdit::item(int index) const -{ - return Utils::Fs::fromNativePath(editWidget()->itemText(index)); -} - -void FileSystemPathComboEdit::addItem(const QString &text) -{ - editWidget()->addItem(Utils::Fs::toNativePath(text)); -} - -void FileSystemPathComboEdit::insertItem(int index, const QString& text) -{ - editWidget()->insertItem(index, Utils::Fs::toNativePath(text)); -} - -int FileSystemPathComboEdit::currentIndex() const -{ - return editWidget()->currentIndex(); -} - -void FileSystemPathComboEdit::setCurrentIndex(int index) -{ - editWidget()->setCurrentIndex(index); -} - -QString FileSystemPathComboEdit::editWidgetText() const -{ - return editWidget()->currentText(); -} - -void FileSystemPathComboEdit::setEditWidgetText(const QString &text) -{ - editWidget()->setCurrentText(text); -} diff --git a/src/gui/fspathedit.h b/src/gui/fspathedit.h deleted file mode 100644 index e7bf496ab..000000000 --- a/src/gui/fspathedit.h +++ /dev/null @@ -1,151 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2016 Eugene Shalygin - * - * 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. - */ - -#ifndef QBT_FSPATHEDIT_H -#define QBT_FSPATHEDIT_H - -#include -#include - -namespace Private -{ - class FileEditorWithCompletion; - class FileLineEdit; - class FileComboEdit; -} - -/*! - * \brief - * Widget for editing strings which are paths in filesystem - */ -class FileSystemPathEdit: public QWidget -{ - Q_OBJECT - Q_ENUMS(Mode) - Q_PROPERTY(Mode mode READ mode WRITE setMode) - Q_PROPERTY(QString selectedPath READ selectedPath WRITE setSelectedPath NOTIFY selectedPathChanged) - Q_PROPERTY(QString fileNameFilter READ fileNameFilter WRITE setFileNameFilter) - Q_PROPERTY(QString dialogCaption READ dialogCaption WRITE setDialogCaption) - -public: - ~FileSystemPathEdit() override; - - enum class Mode - { - FileOpen, //!< opening files, shows open file dialog - FileSave, //!< saving files, shows save file dialog - DirectoryOpen, //!< selecting existing directories - DirectorySave //!< selecting directories for saving - }; - - Mode mode() const; - void setMode(Mode mode); - - QString currentDirectory() const; - QString selectedPath() const; - void setSelectedPath(const QString &val); - - QString fileNameFilter() const; - void setFileNameFilter(const QString &val); - - /// The browse button caption is "..." if true, and "Browse" otherwise - bool briefBrowseButtonCaption() const; - void setBriefBrowseButtonCaption(bool brief); - - QString dialogCaption() const; - void setDialogCaption(const QString &caption); - - virtual void clear() = 0; - -signals: - void selectedPathChanged(const QString &path); - -protected: - explicit FileSystemPathEdit(Private::FileEditorWithCompletion *editor, QWidget *parent); - - template - Widget *editWidget() const - { - return static_cast(editWidgetImpl()); - } - -protected slots: - void onPathEdited(); - -private: - virtual QString editWidgetText() const = 0; - virtual void setEditWidgetText(const QString &text) = 0; - - QWidget *editWidgetImpl() const; - Q_DISABLE_COPY(FileSystemPathEdit) - class FileSystemPathEditPrivate; - Q_DECLARE_PRIVATE(FileSystemPathEdit) - QScopedPointer const d_ptr; -}; - -/// Widget which uses QLineEdit for path editing -class FileSystemPathLineEdit: public FileSystemPathEdit -{ - using base = FileSystemPathEdit; - using WidgetType = Private::FileLineEdit; - -public: - explicit FileSystemPathLineEdit(QWidget *parent = nullptr); - - void clear() override; - -private: - QString editWidgetText() const override; - void setEditWidgetText(const QString &text) override; -}; - -/// Widget which uses QComboBox for path editing -class FileSystemPathComboEdit: public FileSystemPathEdit -{ - using base = FileSystemPathEdit; - using WidgetType = Private::FileComboEdit; - -public: - explicit FileSystemPathComboEdit(QWidget *parent = nullptr); - - void clear() override; - - int count() const; - QString item(int index) const; - void addItem(const QString &text); - void insertItem(int index, const QString &text); - - int currentIndex() const; - void setCurrentIndex(int index); - -private: - QString editWidgetText() const override; - void setEditWidgetText(const QString &text) override; -}; - -#endif // QBT_FSPATHEDIT_H diff --git a/src/gui/fspathedit_p.cpp b/src/gui/fspathedit_p.cpp deleted file mode 100644 index f03194d13..000000000 --- a/src/gui/fspathedit_p.cpp +++ /dev/null @@ -1,352 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2016 Eugene Shalygin - * - * 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. - */ - -#include "fspathedit_p.h" - -#include -#include -#include -#include -#include - -// -------------------- FileSystemPathValidator ---------------------------------------- -Private::FileSystemPathValidator::FileSystemPathValidator(QObject *parent) - : QValidator(parent) - , m_strictMode(false) - , m_existingOnly(false) - , m_directoriesOnly(false) - , m_checkReadPermission(false) - , m_checkWritePermission(false) -{ -} - -bool Private::FileSystemPathValidator::strictMode() const -{ - return m_strictMode; -} - -void Private::FileSystemPathValidator::setStrictMode(bool v) -{ - m_strictMode = v; -} - -bool Private::FileSystemPathValidator::existingOnly() const -{ - return m_existingOnly; -} - -void Private::FileSystemPathValidator::setExistingOnly(bool v) -{ - m_existingOnly = v; -} - -bool Private::FileSystemPathValidator::directoriesOnly() const -{ - return m_directoriesOnly; -} - -void Private::FileSystemPathValidator::setDirectoriesOnly(bool v) -{ - m_directoriesOnly = v; -} - -bool Private::FileSystemPathValidator::checkReadPermission() const -{ - return m_checkReadPermission; -} - -void Private::FileSystemPathValidator::setCheckReadPermission(bool v) -{ - m_checkReadPermission = v; -} - -bool Private::FileSystemPathValidator::checkWritePermission() const -{ - return m_checkWritePermission; -} - -void Private::FileSystemPathValidator::setCheckWritePermission(bool v) -{ - m_checkWritePermission = v; -} - -QValidator::State Private::FileSystemPathValidator::validate(QString &input, int &pos) const -{ - if (input.isEmpty()) - return m_strictMode ? QValidator::Invalid : QValidator::Intermediate; - - // we test path components from beginning to the one with cursor location in strict mode - // and the one with cursor and beyond in non-strict mode - QVector components = input.splitRef(QDir::separator(), QString::KeepEmptyParts); - // find index of the component that contains pos - int componentWithCursorIndex = 0; - int pathLength = 0; - - // components.size() - 1 because when path ends with QDir::separator(), we will not see the last - // character in the components array, yet everything past the one before the last delimiter - // belongs to the last component - for (; (componentWithCursorIndex < components.size() - 1) && (pathLength < pos); ++componentWithCursorIndex) { - pathLength = components[componentWithCursorIndex].position() + components[componentWithCursorIndex].size(); - } - - Q_ASSERT(componentWithCursorIndex < components.size()); - - m_lastValidationState = QValidator::Acceptable; - if (componentWithCursorIndex > 0) - m_lastValidationState = validate(input, components, m_strictMode, 0, componentWithCursorIndex - 1); - if ((m_lastValidationState == QValidator::Acceptable) && (componentWithCursorIndex < components.size())) - m_lastValidationState = validate(input, components, false, componentWithCursorIndex, components.size() - 1); - return m_lastValidationState; -} - -QValidator::State Private::FileSystemPathValidator::validate(const QString &path, const QVector &pathComponents, bool strict, - int firstComponentToTest, int lastComponentToTest) const -{ - Q_ASSERT(firstComponentToTest >= 0); - Q_ASSERT(lastComponentToTest >= firstComponentToTest); - Q_ASSERT(lastComponentToTest < pathComponents.size()); - - m_lastTestResult = TestResult::DoesNotExist; - if (pathComponents.empty()) - return strict ? QValidator::Invalid : QValidator::Intermediate; - - for (int i = firstComponentToTest; i < lastComponentToTest; ++i) { - if (pathComponents[i].isEmpty()) continue; - - QStringRef componentPath(&path, 0, pathComponents[i].position() + pathComponents[i].size()); - m_lastTestResult = testPath(componentPath, false); - if (m_lastTestResult != TestResult::OK) { - m_lastTestedPath = componentPath.toString(); - return strict ? QValidator::Invalid : QValidator::Intermediate; - } - } - - const bool finalPath = (lastComponentToTest == (pathComponents.size() - 1)); - QStringRef componentPath(&path, 0, pathComponents[lastComponentToTest].position() - + pathComponents[lastComponentToTest].size()); - m_lastTestResult = testPath(componentPath, finalPath); - if (m_lastTestResult != TestResult::OK) { - m_lastTestedPath = componentPath.toString(); - return strict ? QValidator::Invalid : QValidator::Intermediate; - } - return QValidator::Acceptable; -} - -Private::FileSystemPathValidator::TestResult -Private::FileSystemPathValidator::testPath(const QStringRef &path, bool pathIsComplete) const -{ - QFileInfo fi(path.toString()); - if (m_existingOnly && !fi.exists()) - return TestResult::DoesNotExist; - - if ((!pathIsComplete || m_directoriesOnly) && !fi.isDir()) - return TestResult::NotADir; - - if (pathIsComplete) { - if (!m_directoriesOnly && fi.isDir()) - return TestResult::NotAFile; - - if (m_checkWritePermission && (fi.exists() && !fi.isWritable())) - return TestResult::CantWrite; - if (m_checkReadPermission && !fi.isReadable()) - return TestResult::CantRead; - } - - return TestResult::OK; -} - -Private::FileSystemPathValidator::TestResult Private::FileSystemPathValidator::lastTestResult() const -{ - return m_lastTestResult; -} - -QValidator::State Private::FileSystemPathValidator::lastValidationState() const -{ - return m_lastValidationState; -} - -QString Private::FileSystemPathValidator::lastTestedPath() const -{ - return m_lastTestedPath; -} - -Private::FileLineEdit::FileLineEdit(QWidget *parent) - : QLineEdit {parent} - , m_completerModel {new QFileSystemModel(this)} - , m_completer {new QCompleter(this)} - , m_browseAction {nullptr} - , m_warningAction {nullptr} -{ - m_completerModel->setRootPath(""); - m_completerModel->setIconProvider(&m_iconProvider); - m_completer->setModel(m_completerModel); - m_completer->setCompletionMode(QCompleter::PopupCompletion); - setCompleter(m_completer); -} - -Private::FileLineEdit::~FileLineEdit() -{ - delete m_completerModel; // has to be deleted before deleting the m_iconProvider object -} - -void Private::FileLineEdit::completeDirectoriesOnly(bool completeDirsOnly) -{ - QDir::Filters filters = completeDirsOnly ? QDir::Dirs : QDir::AllEntries; - filters |= QDir::NoDotAndDotDot; - m_completerModel->setFilter(filters); -} - -void Private::FileLineEdit::setFilenameFilters(const QStringList &filters) -{ - m_completerModel->setNameFilters(filters); -} - -void Private::FileLineEdit::setBrowseAction(QAction *action) -{ - m_browseAction = action; -} - -void Private::FileLineEdit::setValidator(QValidator *validator) -{ - QLineEdit::setValidator(validator); -} - -QWidget *Private::FileLineEdit::widget() -{ - return this; -} - -void Private::FileLineEdit::keyPressEvent(QKeyEvent *e) -{ - QLineEdit::keyPressEvent(e); - if ((e->key() == Qt::Key_Space) && (e->modifiers() == Qt::CTRL)) { - m_completerModel->setRootPath(QFileInfo(text()).absoluteDir().absolutePath()); - showCompletionPopup(); - } - - const FileSystemPathValidator *validator = - qobject_cast(this->validator()); - if (validator) { - FileSystemPathValidator::TestResult lastTestResult = validator->lastTestResult(); - QValidator::State lastState = validator->lastValidationState(); - if (lastTestResult == FileSystemPathValidator::TestResult::OK) { - if (m_warningAction) { - delete m_warningAction; - m_warningAction = nullptr; - } - } - else { - if (!m_warningAction) { - m_warningAction = new QAction(this); - addAction(m_warningAction, QLineEdit::TrailingPosition); - } - } - - if (m_warningAction) { - if (lastState == QValidator::Invalid) - m_warningAction->setIcon(style()->standardIcon(QStyle::SP_MessageBoxCritical)); - else if (lastState == QValidator::Intermediate) - m_warningAction->setIcon(style()->standardIcon(QStyle::SP_MessageBoxWarning)); - m_warningAction->setToolTip(warningText(lastTestResult).arg(validator->lastTestedPath())); - } - } -} - -void Private::FileLineEdit::contextMenuEvent(QContextMenuEvent *event) -{ - QMenu *menu = createStandardContextMenu(); - menu->addSeparator(); - if (m_browseAction) { - menu->addSeparator(); - menu->addAction(m_browseAction); - } - menu->exec(event->globalPos()); - delete menu; -} - -void Private::FileLineEdit::showCompletionPopup() -{ - m_completer->setCompletionPrefix(text()); - m_completer->complete(); -} - -QString Private::FileLineEdit::warningText(FileSystemPathValidator::TestResult r) -{ - using TestResult = FileSystemPathValidator::TestResult; - switch (r) { - case TestResult::DoesNotExist: - return tr("'%1' does not exist"); - case TestResult::NotADir: - return tr("'%1' does not point to a directory"); - case TestResult::NotAFile: - return tr("'%1' does not point to a file"); - case TestResult::CantRead: - return tr("Does not have read permission in '%1'"); - case TestResult::CantWrite: - return tr("Does not have write permission in '%1'"); - default: - return QString(); - } -} - -Private::FileComboEdit::FileComboEdit(QWidget *parent) - : QComboBox {parent} -{ - setEditable(true); - setLineEdit(new FileLineEdit(this)); -} - -void Private::FileComboEdit::completeDirectoriesOnly(bool completeDirsOnly) -{ - static_cast(lineEdit())->completeDirectoriesOnly(completeDirsOnly); -} - -void Private::FileComboEdit::setBrowseAction(QAction *action) -{ - static_cast(lineEdit())->setBrowseAction(action); -} - -void Private::FileComboEdit::setValidator(QValidator *validator) -{ - lineEdit()->setValidator(validator); -} - -void Private::FileComboEdit::setFilenameFilters(const QStringList &filters) -{ - static_cast(lineEdit())->setFilenameFilters(filters); -} - -QWidget *Private::FileComboEdit::widget() -{ - return this; -} - -QString Private::FileComboEdit::text() const -{ - return currentText(); -} diff --git a/src/gui/fspathedit_p.h b/src/gui/fspathedit_p.h deleted file mode 100644 index 7edf9455a..000000000 --- a/src/gui/fspathedit_p.h +++ /dev/null @@ -1,164 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2016 Eugene Shalygin - * - * 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. - */ - -#ifndef QBT_GUI_FSPATHEDIT_P_H -#define QBT_GUI_FSPATHEDIT_P_H - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -class QStringList; - -namespace Private -{ - class FileSystemPathValidator: public QValidator - { - Q_OBJECT - - public: - FileSystemPathValidator(QObject *parent = nullptr); - - bool strictMode() const; - void setStrictMode(bool v); - - bool existingOnly() const; - void setExistingOnly(bool v); - - bool directoriesOnly() const; - void setDirectoriesOnly(bool v); - - bool checkReadPermission() const; - void setCheckReadPermission(bool v); - - bool checkWritePermission() const; - void setCheckWritePermission(bool v); - - QValidator::State validate(QString &input, int &pos) const override; - - enum class TestResult - { - OK, - DoesNotExist, - NotADir, - NotAFile, - CantRead, - CantWrite - }; - - TestResult lastTestResult() const; - QValidator::State lastValidationState() const; - QString lastTestedPath() const; - - private: - QValidator::State validate(const QString &path, const QVector &pathComponents, bool strict, - int firstComponentToTest, int lastComponentToTest) const; - - TestResult testPath(const QStringRef &path, bool pathIsComplete) const; - - bool m_strictMode; - bool m_existingOnly; - bool m_directoriesOnly; - bool m_checkReadPermission; - bool m_checkWritePermission; - - mutable TestResult m_lastTestResult; - mutable QValidator::State m_lastValidationState; - mutable QString m_lastTestedPath; - }; - - class FileEditorWithCompletion - { - public: - virtual ~FileEditorWithCompletion() = default; - virtual void completeDirectoriesOnly(bool completeDirsOnly) = 0; - virtual void setFilenameFilters(const QStringList &filters) = 0; - virtual void setBrowseAction(QAction *action) = 0; - virtual void setValidator(QValidator *validator) = 0; - virtual QWidget *widget() = 0; - }; - - class FileLineEdit: public QLineEdit, public FileEditorWithCompletion - { - Q_OBJECT - Q_DISABLE_COPY(FileLineEdit) - - public: - FileLineEdit(QWidget *parent = nullptr); - ~FileLineEdit(); - - void completeDirectoriesOnly(bool completeDirsOnly) override; - void setFilenameFilters(const QStringList &filters) override; - void setBrowseAction(QAction *action) override; - void setValidator(QValidator *validator) override; - QWidget *widget() override; - - protected: - void keyPressEvent(QKeyEvent *event) override; - void contextMenuEvent(QContextMenuEvent *event) override; - - private: - static QString warningText(FileSystemPathValidator::TestResult r); - void showCompletionPopup(); - - QFileSystemModel *m_completerModel; - QCompleter *m_completer; - QAction *m_browseAction; - QFileIconProvider m_iconProvider; - QAction *m_warningAction; - }; - - class FileComboEdit: public QComboBox, public FileEditorWithCompletion - { - Q_OBJECT - - public: - FileComboEdit(QWidget *parent = nullptr); - - void completeDirectoriesOnly(bool completeDirsOnly) override; - void setFilenameFilters(const QStringList &filters) override; - void setBrowseAction(QAction *action) override; - void setValidator(QValidator *validator) override; - QWidget *widget() override; - - protected: - QString text() const; - }; -} - -#endif // QBT_GUI_FSPATHEDIT_P_H diff --git a/src/gui/gpl.html b/src/gui/gpl.html deleted file mode 100644 index cec3fa8b9..000000000 --- a/src/gui/gpl.html +++ /dev/null @@ -1,517 +0,0 @@ - - - - - License - - -

qBittorrent is licensed under the GNU General Public License version 2 with the -addition of the following special exception:

-

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

----------- -

GNU General Public License, version 2

-
- -

Table of Contents

- - -
- -

GNU GENERAL PUBLIC LICENSE

-

-Version 2, June 1991 -

- -
 
-Copyright (C) 1989, 1991 Free Software Foundation, Inc.  
-51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
- 
-Everyone is permitted to copy and distribute verbatim copies
-of this license document, but changing it is not allowed.
-
- -

Preamble

- -

- The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -License is intended to guarantee your freedom to share and change free -software--to make sure the software is free for all its users. This -General Public License applies to most of the Free Software -Foundation's software and to any other program whose authors commit to -using it. (Some other Free Software Foundation software is covered by -the GNU Lesser General Public License instead.) You can apply it to -your programs, too. -

- -

- When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -this service if you wish), that you receive source code or can get it -if you want it, that you can change the software or use pieces of it -in new free programs; and that you know you can do these things. -

- -

- To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if you -distribute copies of the software, or if you modify it. -

- -

- For example, if you distribute copies of such a program, whether -gratis or for a fee, you must give the recipients all the rights that -you have. You must make sure that they, too, receive or can get the -source code. And you must show them these terms so they know their -rights. -

- -

- We protect your rights with two steps: (1) copyright the software, and -(2) offer you this license which gives you legal permission to copy, -distribute and/or modify the software. -

- -

- Also, for each author's protection and ours, we want to make certain -that everyone understands that there is no warranty for this free -software. If the software is modified by someone else and passed on, we -want its recipients to know that what they have is not the original, so -that any problems introduced by others will not reflect on the original -authors' reputations. -

- -

- Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that redistributors of a free -program will individually obtain patent licenses, in effect making the -program proprietary. To prevent this, we have made it clear that any -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. -

- - -

TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION

- - -

-0. - This License applies to any program or other work which contains -a notice placed by the copyright holder saying it may be distributed -under the terms of this General Public License. The "Program", below, -refers to any such program or work, and a "work based on the Program" -means either the Program or any derivative work under copyright law: -that is to say, a work containing the Program or a portion of it, -either verbatim or with modifications and/or translated into another -language. (Hereinafter, translation is included without limitation in -the term "modification".) Each licensee is addressed as "you". -

- -

-Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running the Program is not restricted, and the output from the Program -is covered only if its contents constitute a work based on the -Program (independent of having been made by running the Program). -Whether that is true depends on what the Program does. -

- -

-1. - You may copy and distribute verbatim copies of the Program's -source code as you receive it, in any medium, provided that you -conspicuously and appropriately publish on each copy an appropriate -copyright notice and disclaimer of warranty; keep intact all the -notices that refer to this License and to the absence of any warranty; -and give any other recipients of the Program a copy of this License -along with the Program. -

- -

-You may charge a fee for the physical act of transferring a copy, and -you may at your option offer warranty protection in exchange for a fee. -

- -

-2. - You may modify your copy or copies of the Program or any portion -of it, thus forming a work based on the Program, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: -

- -
-
-
- a) - You must cause the modified files to carry prominent notices - stating that you changed the files and the date of any change. -
-
-
- b) - You must cause any work that you distribute or publish, that in - whole or in part contains or is derived from the Program or any - part thereof, to be licensed as a whole at no charge to all third - parties under the terms of this License. -
-
-
- c) - If the modified program normally reads commands interactively - when run, you must cause it, when started running for such - interactive use in the most ordinary way, to print or display an - announcement including an appropriate copyright notice and a - notice that there is no warranty (or else, saying that you provide - a warranty) and that users may redistribute the program under - these conditions, and telling the user how to view a copy of this - 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 -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Program, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote it. -

- -

-Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Program. -

- -

-In addition, mere aggregation of another work not based on the Program -with the Program (or with a work based on the Program) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. -

- -

-3. - You may copy and distribute the Program (or a work based on it, -under Section 2) in object code or executable form under the terms of -Sections 1 and 2 above provided that you also do one of the following: -

- - - - -
-
-
- a) - Accompany it with the complete corresponding machine-readable - source code, which must be distributed under the terms of Sections - 1 and 2 above on a medium customarily used for software interchange; or, -
-
-
- b) - Accompany it with a written offer, valid for at least three - years, to give any third party, for a charge no more than your - cost of physically performing source distribution, a complete - machine-readable copy of the corresponding source code, to be - distributed under the terms of Sections 1 and 2 above on a medium - customarily used for software interchange; or, -
-
-
- c) - Accompany it with the information you received as to the offer - to distribute corresponding source code. (This alternative is - allowed only for noncommercial distribution and only if you - received the program in object code or executable form with such - an offer, in accord with Subsection b above.) -
-
- -

-The source code for a work means the preferred form of the work for -making modifications to it. For an executable work, complete source -code means all the source code for all modules it contains, plus any -associated interface definition files, plus the scripts used to -control compilation and installation of the executable. However, as a -special exception, the source code distributed need not include -anything that is normally distributed (in either source or binary -form) with the major components (compiler, kernel, and so on) of the -operating system on which the executable runs, unless that component -itself accompanies the executable. -

- -

-If distribution of executable or object code is made by offering -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 -void, and will automatically terminate your rights under this License. -However, parties who have received copies, or rights, from you under -this License will not have their licenses terminated so long as such -parties remain in full compliance. -

- -

-5. - You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Program or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Program (or any work based on the -Program), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Program or works based on it. -

- -

-6. - Each time you redistribute the Program (or any work based on the -Program), the recipient automatically receives a license from the -original licensor to copy, distribute or modify the Program subject to -these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties to -this License. -

- -

-7. - If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Program at all. For example, if a patent -license would not permit royalty-free redistribution of the Program by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Program. -

- -

-If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply and the section as a whole is intended to apply in other -circumstances. -

- -

-It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system, which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -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 -may add an explicit geographical distribution limitation excluding -those countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. -

- -

-9. - The Free Software Foundation may publish revised and/or new versions -of the General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. -

- -

-Each version is given a distinguishing version number. If the Program -specifies a version number of this License which applies to it and "any -later version", you have the option of following the terms and conditions -either of that version or of any later version published by the Free -Software Foundation. If the Program does not specify a version number of -this License, you may choose any version ever published by the Free Software -Foundation. -

- -

-10. - If you wish to incorporate parts of the Program into other free -programs whose distribution conditions are different, write to the author -to ask for permission. For software which is copyrighted by the Free -Software Foundation, write to the Free Software Foundation; we sometimes -make exceptions for this. Our decision will be guided by the two goals -of preserving the free status of all derivatives of our free software and -of promoting the sharing and reuse of software generally. -

- -

NO WARRANTY

- -

-11. - BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY -FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN -OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES -PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED -OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS -TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE -PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, -REPAIR OR CORRECTION. -

- -

-12. - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR -REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING -OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED -TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER -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 -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. -

- -

- To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. -

- -
 
-one line to give the program's name and an idea of what it does. 
-Copyright (C) yyyy  name of author 
- 
-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.
-
- -

-Also add information on how to contact you by electronic and paper mail. -

- -

-If the program is interactive, make it output a short notice like this -when it starts in an interactive mode: -

- -
 
-Gnomovision version 69, Copyright (C) year name of author 
-Gnomovision comes with ABSOLUTELY NO WARRANTY; for details
-type `show w'.  This is free software, and you are welcome
-to redistribute it under certain conditions; type `show c' 
-for details.
-
- -

-The hypothetical commands `show w' and `show c' should show -the appropriate parts of the General Public License. Of course, the -commands you use may be called something other than `show w' and -`show c'; they could even be mouse-clicks or menu items--whatever -suits your program. -

- -

-You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the program, if -necessary. Here is a sample; alter the names: -

- - -
 
-Yoyodyne, Inc., hereby disclaims all copyright
-interest in the program `Gnomovision'
-(which makes passes at compilers) written 
-by James Hacker.
- 
-signature of Ty Coon, 1 April 1989
-Ty Coon, President of Vice
-
- -

-This General Public License does not permit incorporating your program into -proprietary programs. If your program is a subroutine library, you may -consider it more useful to permit linking proprietary applications with the -library. If this is what you want to do, use the -GNU Lesser General Public License -instead of this License. -

- - diff --git a/src/gui/gui.pri b/src/gui/gui.pri deleted file mode 100644 index 889a076c8..000000000 --- a/src/gui/gui.pri +++ /dev/null @@ -1,149 +0,0 @@ -INCLUDEPATH += $$PWD - -include(lineedit/lineedit.pri) -include(properties/properties.pri) -include(powermanagement/powermanagement.pri) -unix:!macx:dbus: include(qtnotify/qtnotify.pri) - -HEADERS += \ - $$PWD/mainwindow.h \ - $$PWD/transferlistwidget.h \ - $$PWD/transferlistdelegate.h \ - $$PWD/transferlistfilterswidget.h \ - $$PWD/transferlistsortmodel.h \ - $$PWD/torrentcontentmodel.h \ - $$PWD/torrentcontentmodelitem.h \ - $$PWD/torrentcontentmodelfolder.h \ - $$PWD/torrentcontentmodelfile.h \ - $$PWD/torrentcontentfiltermodel.h \ - $$PWD/torrentcontenttreeview.h \ - $$PWD/deletionconfirmationdlg.h \ - $$PWD/statusbar.h \ - $$PWD/speedlimitdlg.h \ - $$PWD/about_imp.h \ - $$PWD/previewselect.h \ - $$PWD/previewlistdelegate.h \ - $$PWD/downloadfromurldlg.h \ - $$PWD/trackerlogin.h \ - $$PWD/hidabletabwidget.h \ - $$PWD/executionlog.h \ - $$PWD/guiiconprovider.h \ - $$PWD/updownratiodlg.h \ - $$PWD/loglistwidget.h \ - $$PWD/addnewtorrentdialog.h \ - $$PWD/autoexpandabledialog.h \ - $$PWD/statsdialog.h \ - $$PWD/messageboxraised.h \ - $$PWD/optionsdlg.h \ - $$PWD/advancedsettings.h \ - $$PWD/shutdownconfirmdlg.h \ - $$PWD/torrentmodel.h \ - $$PWD/torrentcreatordlg.h \ - $$PWD/scanfoldersdelegate.h \ - $$PWD/search/searchwidget.h \ - $$PWD/search/searchtab.h \ - $$PWD/search/pluginselectdlg.h \ - $$PWD/search/pluginsourcedlg.h \ - $$PWD/search/searchlistdelegate.h \ - $$PWD/search/searchsortmodel.h \ - $$PWD/cookiesmodel.h \ - $$PWD/cookiesdialog.h \ - $$PWD/categoryfiltermodel.h \ - $$PWD/categoryfilterproxymodel.h \ - $$PWD/categoryfilterwidget.h \ - $$PWD/tagfiltermodel.h \ - $$PWD/tagfilterproxymodel.h \ - $$PWD/tagfilterwidget.h \ - $$PWD/banlistoptions.h \ - $$PWD/rss/rsswidget.h \ - $$PWD/rss/articlelistwidget.h \ - $$PWD/rss/feedlistwidget.h \ - $$PWD/rss/automatedrssdownloader.h \ - $$PWD/rss/htmlbrowser.h \ - $$PWD/fspathedit.h \ - $$PWD/fspathedit_p.h \ - -SOURCES += \ - $$PWD/mainwindow.cpp \ - $$PWD/transferlistwidget.cpp \ - $$PWD/transferlistsortmodel.cpp \ - $$PWD/transferlistdelegate.cpp \ - $$PWD/transferlistfilterswidget.cpp \ - $$PWD/torrentcontentmodel.cpp \ - $$PWD/torrentcontentmodelitem.cpp \ - $$PWD/torrentcontentmodelfolder.cpp \ - $$PWD/torrentcontentmodelfile.cpp \ - $$PWD/torrentcontentfiltermodel.cpp \ - $$PWD/torrentcontenttreeview.cpp \ - $$PWD/executionlog.cpp \ - $$PWD/speedlimitdlg.cpp \ - $$PWD/previewselect.cpp \ - $$PWD/guiiconprovider.cpp \ - $$PWD/updownratiodlg.cpp \ - $$PWD/loglistwidget.cpp \ - $$PWD/addnewtorrentdialog.cpp \ - $$PWD/autoexpandabledialog.cpp \ - $$PWD/statsdialog.cpp \ - $$PWD/messageboxraised.cpp \ - $$PWD/statusbar.cpp \ - $$PWD/advancedsettings.cpp \ - $$PWD/trackerlogin.cpp \ - $$PWD/optionsdlg.cpp \ - $$PWD/shutdownconfirmdlg.cpp \ - $$PWD/torrentmodel.cpp \ - $$PWD/torrentcreatordlg.cpp \ - $$PWD/scanfoldersdelegate.cpp \ - $$PWD/search/searchwidget.cpp \ - $$PWD/search/searchtab.cpp \ - $$PWD/search/pluginselectdlg.cpp \ - $$PWD/search/pluginsourcedlg.cpp \ - $$PWD/search/searchlistdelegate.cpp \ - $$PWD/search/searchsortmodel.cpp \ - $$PWD/cookiesmodel.cpp \ - $$PWD/cookiesdialog.cpp \ - $$PWD/categoryfiltermodel.cpp \ - $$PWD/categoryfilterproxymodel.cpp \ - $$PWD/categoryfilterwidget.cpp \ - $$PWD/tagfiltermodel.cpp \ - $$PWD/tagfilterproxymodel.cpp \ - $$PWD/tagfilterwidget.cpp \ - $$PWD/banlistoptions.cpp \ - $$PWD/rss/rsswidget.cpp \ - $$PWD/rss/articlelistwidget.cpp \ - $$PWD/rss/feedlistwidget.cpp \ - $$PWD/rss/automatedrssdownloader.cpp \ - $$PWD/rss/htmlbrowser.cpp \ - $$PWD/fspathedit.cpp \ - $$PWD/fspathedit_p.cpp - -win32|macx { - HEADERS += $$PWD/programupdater.h - SOURCES += $$PWD/programupdater.cpp -} - -FORMS += \ - $$PWD/mainwindow.ui \ - $$PWD/about.ui \ - $$PWD/preview.ui \ - $$PWD/login.ui \ - $$PWD/downloadfromurldlg.ui \ - $$PWD/bandwidth_limit.ui \ - $$PWD/updownratiodlg.ui \ - $$PWD/confirmdeletiondlg.ui \ - $$PWD/shutdownconfirmdlg.ui \ - $$PWD/executionlog.ui \ - $$PWD/addnewtorrentdialog.ui \ - $$PWD/autoexpandabledialog.ui \ - $$PWD/statsdialog.ui \ - $$PWD/optionsdlg.ui \ - $$PWD/torrentcreatordlg.ui \ - $$PWD/search/searchwidget.ui \ - $$PWD/search/pluginselectdlg.ui \ - $$PWD/search/pluginsourcedlg.ui \ - $$PWD/search/searchtab.ui \ - $$PWD/cookiesdialog.ui \ - $$PWD/banlistoptions.ui \ - $$PWD/rss/rsswidget.ui \ - $$PWD/rss/automatedrssdownloader.ui - -RESOURCES += $$PWD/about.qrc diff --git a/src/gui/guiiconprovider.cpp b/src/gui/guiiconprovider.cpp deleted file mode 100644 index 1c58dd03c..000000000 --- a/src/gui/guiiconprovider.cpp +++ /dev/null @@ -1,147 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2015 Vladimir Golovnev - * 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. - */ - -#include "guiiconprovider.h" -#include "base/preferences.h" - -#include -#if (defined(Q_OS_UNIX) && !defined(Q_OS_MAC)) -#include -#include -#endif - -GuiIconProvider::GuiIconProvider(QObject *parent) - : IconProvider(parent) -{ - configure(); - connect(Preferences::instance(), SIGNAL(changed()), SLOT(configure())); -} - -GuiIconProvider::~GuiIconProvider() {} - -void GuiIconProvider::initInstance() -{ - if (!m_instance) - m_instance = new GuiIconProvider; -} - -GuiIconProvider *GuiIconProvider::instance() -{ - return static_cast(m_instance); -} - -QIcon GuiIconProvider::getIcon(const QString &iconId) -{ - return getIcon(iconId, iconId); -} - -QIcon GuiIconProvider::getIcon(const QString &iconId, const QString &fallback) -{ -#if (defined(Q_OS_UNIX) && !defined(Q_OS_MAC)) - if (m_useSystemTheme) { - QIcon icon = QIcon::fromTheme(iconId); - if (icon.name() != iconId) - icon = QIcon::fromTheme(fallback, QIcon(IconProvider::getIconPath(iconId))); - icon = generateDifferentSizes(icon); - return icon; - } -#else - Q_UNUSED(fallback) -#endif - return QIcon(IconProvider::getIconPath(iconId)); -} - -QIcon GuiIconProvider::getFlagIcon(const QString &countryIsoCode) -{ - if (countryIsoCode.isEmpty()) return QIcon(); - return QIcon(":/icons/flags/" + countryIsoCode.toLower() + ".png"); -} - -// 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. -#if (defined(Q_OS_UNIX) && !defined(Q_OS_MAC)) -QIcon GuiIconProvider::generateDifferentSizes(const QIcon &icon) -{ - // if icon is loaded from SVG format, it already contains all the required sizes and we shall not resize it - // In that case it will be available in the following sizes: - // (QSize(16, 16), QSize(22, 22), QSize(32, 32), QSize(48, 48), QSize(64, 64), QSize(128, 128), QSize(256, 256)) - - if (icon.availableSizes(QIcon::Normal, QIcon::On).size() > 6) - return icon; - - QIcon newIcon; - QList requiredSizes; - requiredSizes << QSize(16, 16) << QSize(24, 24) << QSize(32, 32); - QList modes; - modes << QIcon::Normal << QIcon::Active << QIcon::Selected << QIcon::Disabled; - foreach (const QSize &size, requiredSizes) { - 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); - newIcon.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); - newIcon.addPixmap(pixon, mode, QIcon::On); - } - } - - return newIcon; -} -#endif - -QString GuiIconProvider::getIconPath(const QString &iconId) -{ -#if (defined(Q_OS_UNIX) && !defined(Q_OS_MAC)) - if (m_useSystemTheme) { - QString path = QDir::temp().absoluteFilePath(iconId + ".png"); - if (!QFile::exists(path)) { - const QIcon icon = QIcon::fromTheme(iconId); - if (!icon.isNull()) - icon.pixmap(32).save(path); - else - path = IconProvider::getIconPath(iconId); - } - - return path; - } -#endif - return IconProvider::getIconPath(iconId); -} - - -void GuiIconProvider::configure() -{ -#if (defined(Q_OS_UNIX) && !defined(Q_OS_MAC)) - m_useSystemTheme = Preferences::instance()->useSystemIconTheme(); -#endif -} diff --git a/src/gui/guiiconprovider.h b/src/gui/guiiconprovider.h deleted file mode 100644 index 665a7fabe..000000000 --- a/src/gui/guiiconprovider.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2015 Vladimir Golovnev - * 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. - */ - -#ifndef GUIICONPROVIDER_H -#define GUIICONPROVIDER_H - -#include "base/iconprovider.h" - -class QIcon; - -class GuiIconProvider : public IconProvider -{ - Q_DISABLE_COPY(GuiIconProvider) - Q_OBJECT - -public: - static void initInstance(); - static GuiIconProvider *instance(); - - QIcon getIcon(const QString &iconId); - QIcon getIcon(const QString &iconId, const QString &fallback); - QIcon getFlagIcon(const QString &countryIsoCode); - QString getIconPath(const QString &iconId); - -private slots: - void configure(); - -private: - explicit GuiIconProvider(QObject *parent = 0); - ~GuiIconProvider(); -#if (defined(Q_OS_UNIX) && !defined(Q_OS_MAC)) - QIcon generateDifferentSizes(const QIcon &icon); - - bool m_useSystemTheme; -#endif -}; - -#endif // GUIICONPROVIDER_H diff --git a/src/gui/hidabletabwidget.h b/src/gui/hidabletabwidget.h deleted file mode 100644 index 9263fac46..000000000 --- a/src/gui/hidabletabwidget.h +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2006 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 HIDABLETABWIDGET_H -#define HIDABLETABWIDGET_H - -#include -#include - -class HidableTabWidget : public QTabWidget -{ -public: - explicit HidableTabWidget(QWidget *parent = 0) - : QTabWidget(parent) - { - } - -protected: -#ifdef Q_OS_MAC - void paintEvent(QPaintEvent* event) override - { - // Hide the pane for macintosh style - if (!style()->inherits("QMacStyle")) - QTabWidget::paintEvent(event); - } -#endif - - void tabInserted(int index) override - { - QTabWidget::tabInserted(index); - tabBar()->setVisible(count() != 1); - } - - void tabRemoved(int index) override - { - //QTabWidget::tabInserted(index); - QTabWidget::tabRemoved(index); - tabBar()->setVisible(count() != 1); - } -}; - -#endif // HIDABLETABWIDGET_H diff --git a/src/gui/lineedit/CMakeLists.txt b/src/gui/lineedit/CMakeLists.txt deleted file mode 100644 index ee1f46c2f..000000000 --- a/src/gui/lineedit/CMakeLists.txt +++ /dev/null @@ -1,16 +0,0 @@ -set(QBT_LINEEDIT_SOURCES -src/lineedit.cpp -) - -set(QBT_LINEEDIT_HEADERS -src/lineedit.h -) - -set(QBT_LINEEDIT_RESOURCES -resources/lineeditimages.qrc -) - -add_library(qbt_lineedit STATIC ${QBT_LINEEDIT_SOURCES} ${QBT_LINEEDIT_HEADERS}) -target_link_libraries(qbt_lineedit Qt5::Widgets) - -qbt_target_sources(${QBT_LINEEDIT_RESOURCES}) diff --git a/src/gui/lineedit/lineedit.pri b/src/gui/lineedit/lineedit.pri deleted file mode 100644 index 19c09395a..000000000 --- a/src/gui/lineedit/lineedit.pri +++ /dev/null @@ -1,4 +0,0 @@ -INCLUDEPATH += $$PWD/src -HEADERS += $$PWD/src/lineedit.h -SOURCES += $$PWD/src/lineedit.cpp -RESOURCES += $$PWD/resources/lineeditimages.qrc diff --git a/src/gui/lineedit/resources/lineeditimages.qrc b/src/gui/lineedit/resources/lineeditimages.qrc deleted file mode 100644 index 122e8cbd6..000000000 --- a/src/gui/lineedit/resources/lineeditimages.qrc +++ /dev/null @@ -1,6 +0,0 @@ - - - lineeditimages/clear_left.png - lineeditimages/search.png - - diff --git a/src/gui/lineedit/resources/lineeditimages/clear_left.png b/src/gui/lineedit/resources/lineeditimages/clear_left.png deleted file mode 100644 index 18a541fc3..000000000 Binary files a/src/gui/lineedit/resources/lineeditimages/clear_left.png and /dev/null differ diff --git a/src/gui/lineedit/resources/lineeditimages/search.png b/src/gui/lineedit/resources/lineeditimages/search.png deleted file mode 100644 index fb8df709e..000000000 Binary files a/src/gui/lineedit/resources/lineeditimages/search.png and /dev/null differ diff --git a/src/gui/lineedit/src/lineedit.cpp b/src/gui/lineedit/src/lineedit.cpp deleted file mode 100644 index f3f978e26..000000000 --- a/src/gui/lineedit/src/lineedit.cpp +++ /dev/null @@ -1,44 +0,0 @@ -/**************************************************************************** -** -** Copyright (c) 2007 Trolltech ASA -** -** Use, modification and distribution is allowed without limitation, -** warranty, liability or support of any kind. -** -****************************************************************************/ - -#include "lineedit.h" -#include -#include -#include -#include - -LineEdit::LineEdit(QWidget *parent) - : QLineEdit(parent) -{ - QPixmap pixmap1(":/lineeditimages/search.png"); - searchButton = new QToolButton(this); - searchButton->setIcon(QIcon(pixmap1)); - searchButton->setIconSize(pixmap1.size()); - searchButton->setCursor(Qt::ArrowCursor); - searchButton->setStyleSheet("QToolButton { border: none; padding: 2px; }"); - QSize searchButtonHint = searchButton->sizeHint(); - - QSize clearButtonHint(0, 0); - setClearButtonEnabled(true); - setStyleSheet(QString("QLineEdit { padding-left: %1px; }").arg(searchButtonHint.width())); // padding between text and widget borders - - QSize widgetHint = sizeHint(); - int frameWidth = style()->pixelMetric(QStyle::PM_DefaultFrameWidth); - setMaximumHeight(std::max({ widgetHint.height(), searchButtonHint.height(), clearButtonHint.height() }) + frameWidth * 2); - setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); -} - -void LineEdit::resizeEvent(QResizeEvent *e) -{ - int frameWidth = style()->pixelMetric(QStyle::PM_DefaultFrameWidth); - - QSize sz = searchButton->sizeHint(); - searchButton->move(frameWidth, (e->size().height() - sz.height()) / 2); -} - diff --git a/src/gui/lineedit/src/lineedit.h b/src/gui/lineedit/src/lineedit.h deleted file mode 100644 index 5922ce209..000000000 --- a/src/gui/lineedit/src/lineedit.h +++ /dev/null @@ -1,31 +0,0 @@ -/**************************************************************************** -** -** Copyright (c) 2007 Trolltech ASA -** -** Use, modification and distribution is allowed without limitation, -** warranty, liability or support of any kind. -** -****************************************************************************/ - -#ifndef LINEEDIT_H -#define LINEEDIT_H - -#include - -class QToolButton; - -class LineEdit : public QLineEdit -{ - Q_OBJECT - -public: - LineEdit(QWidget *parent); - -protected: - void resizeEvent(QResizeEvent *e); - -private: - QToolButton *searchButton; -}; - -#endif // LIENEDIT_H diff --git a/src/gui/login.ui b/src/gui/login.ui deleted file mode 100644 index 63a9125d2..000000000 --- a/src/gui/login.ui +++ /dev/null @@ -1,233 +0,0 @@ - - - authentication - - - - 0 - 0 - 311 - 231 - - - - Tracker authentication - - - - - - - - - 39 - 39 - - - - - - - - - - - - 16777215 - 39 - - - - - 75 - true - - - - Tracker authentication - - - - - - - - - - - - 75 - true - - - - Tracker: - - - - - - - - 220 - 0 - - - - - - - - - - - - - Login - - - - - - - - Username: - - - lineUsername - - - - - - - - - - - - - - - 68 - 0 - - - - Password: - - - linePasswd - - - - - - - QLineEdit::Password - - - - - - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - Log in - - - - - - - Cancel - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - - - cancelButton - clicked() - authentication - reject() - - - 245 - 195 - - - 179 - 230 - - - - - linePasswd - returnPressed() - loginButton - click() - - - 139 - 158 - - - 122 - 199 - - - - - lineUsername - returnPressed() - linePasswd - setFocus() - - - 199 - 130 - - - 198 - 157 - - - - - diff --git a/src/gui/loglistwidget.cpp b/src/gui/loglistwidget.cpp deleted file mode 100644 index c6a71f65c..000000000 --- a/src/gui/loglistwidget.cpp +++ /dev/null @@ -1,103 +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 -#include -#include -#include -#include -#include -#include -#include "loglistwidget.h" -#include "guiiconprovider.h" - -LogListWidget::LogListWidget(int maxLines, const Log::MsgTypes &types, QWidget *parent) - : QListWidget(parent) - , m_maxLines(maxLines) - , m_types(types) -{ - // Allow multiple selections - setSelectionMode(QAbstractItemView::ExtendedSelection); - // Context menu - QAction *copyAct = new QAction(GuiIconProvider::instance()->getIcon("edit-copy"), tr("Copy"), this); - QAction *clearAct = new QAction(GuiIconProvider::instance()->getIcon("edit-clear"), tr("Clear"), this); - connect(copyAct, SIGNAL(triggered()), SLOT(copySelection())); - connect(clearAct, SIGNAL(triggered()), SLOT(clear())); - addAction(copyAct); - addAction(clearAct); - setContextMenuPolicy(Qt::ActionsContextMenu); -} - -void LogListWidget::showMsgTypes(const Log::MsgTypes &types) -{ - m_types = types; - for (int i = 0; i < count(); ++i) { - QListWidgetItem *tempItem = item(i); - if (!tempItem) continue; - - Log::MsgType itemType = static_cast(tempItem->data(Qt::UserRole).toInt()); - setRowHidden(i, !(m_types & itemType)); - } -} - -void LogListWidget::keyPressEvent(QKeyEvent *event) -{ - if (event->matches(QKeySequence::Copy)) - copySelection(); - else if (event->matches(QKeySequence::SelectAll)) - selectAll(); -} - -void LogListWidget::appendLine(const QString &line, const Log::MsgType &type) -{ - QListWidgetItem *item = new QListWidgetItem; - // We need to use QLabel here to support rich text - QLabel *lbl = new QLabel(line); - lbl->setContentsMargins(4, 2, 4, 2); - item->setSizeHint(lbl->sizeHint()); - item->setData(Qt::UserRole, type); - insertItem(0, item); - setItemWidget(item, lbl); - setRowHidden(0, !(m_types & type)); - - const int nbLines = count(); - // Limit log size - if (nbLines > m_maxLines) - delete takeItem(nbLines - 1); -} - -void LogListWidget::copySelection() -{ - static QRegExp htmlTag("<[^>]+>"); - QStringList strings; - foreach (QListWidgetItem* it, selectedItems()) - strings << static_cast(itemWidget(it))->text().replace(htmlTag, ""); - - QApplication::clipboard()->setText(strings.join("\n")); -} diff --git a/src/gui/loglistwidget.h b/src/gui/loglistwidget.h deleted file mode 100644 index 46147f204..000000000 --- a/src/gui/loglistwidget.h +++ /dev/null @@ -1,63 +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 LOGLISTWIDGET_H -#define LOGLISTWIDGET_H - -#include -#include "base/logger.h" - -QT_BEGIN_NAMESPACE -class QKeyEvent; -QT_END_NAMESPACE - -class LogListWidget: public QListWidget -{ - Q_OBJECT - -public: - // -1 is the portable way to have all the bits set - explicit LogListWidget(int maxLines, const Log::MsgTypes &types = Log::ALL, QWidget *parent = 0); - void showMsgTypes(const Log::MsgTypes &types); - -public slots: - void appendLine(const QString &line, const Log::MsgType &type); - -protected slots: - void copySelection(); - -protected: - void keyPressEvent(QKeyEvent *event); - -private: - int m_maxLines; - Log::MsgTypes m_types; -}; - -#endif // LOGLISTWIDGET_H diff --git a/src/gui/mainwindow.cpp b/src/gui/mainwindow.cpp deleted file mode 100644 index 4bad8746b..000000000 --- a/src/gui/mainwindow.cpp +++ /dev/null @@ -1,2096 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2006 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 "mainwindow.h" - -#ifdef Q_OS_MAC -#include -#include -#include -#include -#endif - -#include -#if (defined(Q_OS_UNIX) && !defined(Q_OS_MAC)) && defined(QT_DBUS_LIB) -#include -#include "notifications.h" -#endif -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "base/preferences.h" -#include "base/settingsstorage.h" -#include "base/logger.h" -#include "base/utils/misc.h" -#include "base/utils/fs.h" -#ifdef Q_OS_WIN -#include "base/net/downloadmanager.h" -#include "base/net/downloadhandler.h" -#endif -#include "base/bittorrent/session.h" -#include "base/bittorrent/sessionstatus.h" -#include "base/bittorrent/torrenthandle.h" -#include "base/global.h" -#include "base/rss/rss_folder.h" -#include "base/rss/rss_session.h" - -#include "application.h" -#if defined(Q_OS_WIN) || defined(Q_OS_MAC) -#include "programupdater.h" -#endif -#include "powermanagement.h" -#include "guiiconprovider.h" -#include "torrentmodel.h" -#include "autoexpandabledialog.h" -#include "torrentcreatordlg.h" -#include "downloadfromurldlg.h" -#include "addnewtorrentdialog.h" -#include "statsdialog.h" -#include "cookiesdialog.h" -#include "speedlimitdlg.h" -#include "transferlistwidget.h" -#include "search/searchwidget.h" -#include "trackerlist.h" -#include "peerlistwidget.h" -#include "transferlistfilterswidget.h" -#include "propertieswidget.h" -#include "statusbar.h" -#include "rss/rsswidget.h" -#include "about_imp.h" -#include "optionsdlg.h" -#if LIBTORRENT_VERSION_NUM < 10100 -#include "trackerlogin.h" -#endif -#include "lineedit.h" -#include "executionlog.h" -#include "hidabletabwidget.h" -#include "ui_mainwindow.h" - -#ifdef Q_OS_MAC -void qt_mac_set_dock_menu(QMenu *menu); -#endif - -#define TIME_TRAY_BALLOON 5000 -#define PREVENT_SUSPEND_INTERVAL 60000 - -namespace -{ -#define SETTINGS_KEY(name) "GUI/" name - - // ExecutionLog properties keys -#define EXECUTIONLOG_SETTINGS_KEY(name) SETTINGS_KEY("Log/") name - const QString KEY_EXECUTIONLOG_ENABLED = EXECUTIONLOG_SETTINGS_KEY("Enabled"); - const QString KEY_EXECUTIONLOG_TYPES = EXECUTIONLOG_SETTINGS_KEY("Types"); - - // Notifications properties keys -#define NOTIFICATIONS_SETTINGS_KEY(name) SETTINGS_KEY("Notifications/") name - const QString KEY_NOTIFICATIONS_ENABLED = NOTIFICATIONS_SETTINGS_KEY("Enabled"); - const QString KEY_NOTIFICATIONS_TORRENTADDED = NOTIFICATIONS_SETTINGS_KEY("TorrentAdded"); - - // Misc - const QString KEY_DOWNLOAD_TRACKER_FAVICON = NOTIFICATIONS_SETTINGS_KEY("DownloadTrackerFavicon"); - - // just a shortcut - inline SettingsStorage *settings() - { - return SettingsStorage::instance(); - } -} - -MainWindow::MainWindow(QWidget *parent) - : QMainWindow(parent) - , m_ui(new Ui::MainWindow) - , m_posInitialized(false) - , m_forceExit(false) - , m_unlockDlgShowing(false) -#if defined(Q_OS_WIN) || defined(Q_OS_MAC) - , m_wasUpdateCheckEnabled(false) -#endif - , m_hasPython(false) -{ - m_ui->setupUi(this); - - Preferences *const pref = Preferences::instance(); - m_uiLocked = pref->isUILocked(); - setWindowTitle("qBittorrent " QBT_VERSION); - m_displaySpeedInTitle = pref->speedInTitleBar(); - // Setting icons -#ifndef Q_OS_MAC -#ifdef Q_OS_UNIX - if (Preferences::instance()->useSystemIconTheme()) - setWindowIcon(QIcon::fromTheme("qbittorrent", QIcon(":/icons/skin/qbittorrent32.png"))); - else -#endif // Q_OS_UNIX - setWindowIcon(QIcon(":/icons/skin/qbittorrent32.png")); -#endif // Q_OS_MAC - -#if (defined(Q_OS_UNIX)) - m_ui->actionOptions->setText(tr("Preferences")); -#endif - - addToolbarContextMenu(); - - m_ui->actionOpen->setIcon(GuiIconProvider::instance()->getIcon("list-add")); - m_ui->actionDownloadFromURL->setIcon(GuiIconProvider::instance()->getIcon("insert-link")); - m_ui->actionSetUploadLimit->setIcon(GuiIconProvider::instance()->getIcon("kt-set-max-upload-speed")); - m_ui->actionSetDownloadLimit->setIcon(GuiIconProvider::instance()->getIcon("kt-set-max-download-speed")); - m_ui->actionSetGlobalUploadLimit->setIcon(GuiIconProvider::instance()->getIcon("kt-set-max-upload-speed")); - m_ui->actionSetGlobalDownloadLimit->setIcon(GuiIconProvider::instance()->getIcon("kt-set-max-download-speed")); - m_ui->actionCreateTorrent->setIcon(GuiIconProvider::instance()->getIcon("document-edit")); - m_ui->actionAbout->setIcon(GuiIconProvider::instance()->getIcon("help-about")); - m_ui->actionStatistics->setIcon(GuiIconProvider::instance()->getIcon("view-statistics")); - m_ui->actionDecreasePriority->setIcon(GuiIconProvider::instance()->getIcon("go-down")); - m_ui->actionBottomPriority->setIcon(GuiIconProvider::instance()->getIcon("go-bottom")); - m_ui->actionDelete->setIcon(GuiIconProvider::instance()->getIcon("list-remove")); - m_ui->actionDocumentation->setIcon(GuiIconProvider::instance()->getIcon("help-contents")); - m_ui->actionDonateMoney->setIcon(GuiIconProvider::instance()->getIcon("wallet-open")); - m_ui->actionExit->setIcon(GuiIconProvider::instance()->getIcon("application-exit")); - m_ui->actionIncreasePriority->setIcon(GuiIconProvider::instance()->getIcon("go-up")); - m_ui->actionTopPriority->setIcon(GuiIconProvider::instance()->getIcon("go-top")); - m_ui->actionLock->setIcon(GuiIconProvider::instance()->getIcon("object-locked")); - m_ui->actionOptions->setIcon(GuiIconProvider::instance()->getIcon("configure", "preferences-system")); - m_ui->actionPause->setIcon(GuiIconProvider::instance()->getIcon("media-playback-pause")); - m_ui->actionPauseAll->setIcon(GuiIconProvider::instance()->getIcon("media-playback-pause")); - m_ui->actionStart->setIcon(GuiIconProvider::instance()->getIcon("media-playback-start")); - m_ui->actionStartAll->setIcon(GuiIconProvider::instance()->getIcon("media-playback-start")); - m_ui->menuAutoShutdownOnDownloadsCompletion->setIcon(GuiIconProvider::instance()->getIcon("application-exit")); - m_ui->actionManageCookies->setIcon(GuiIconProvider::instance()->getIcon("preferences-web-browser-cookies")); - - QMenu *lockMenu = new QMenu(this); - QAction *defineUiLockPasswdAct = lockMenu->addAction(tr("&Set Password")); - connect(defineUiLockPasswdAct, &QAction::triggered, this, &MainWindow::defineUILockPassword); - QAction *clearUiLockPasswdAct = lockMenu->addAction(tr("&Clear Password")); - connect(clearUiLockPasswdAct, &QAction::triggered, this, &MainWindow::clearUILockPassword); - m_ui->actionLock->setMenu(lockMenu); - - // Creating Bittorrent session - connect(BitTorrent::Session::instance(), &BitTorrent::Session::fullDiskError, this, &MainWindow::fullDiskError); - connect(BitTorrent::Session::instance(), &BitTorrent::Session::addTorrentFailed, this, &MainWindow::addTorrentFailed); - connect(BitTorrent::Session::instance(), &BitTorrent::Session::torrentNew,this, &MainWindow::torrentNew); - connect(BitTorrent::Session::instance(), &BitTorrent::Session::torrentFinished, this, &MainWindow::finishedTorrent); - connect(BitTorrent::Session::instance(), &BitTorrent::Session::trackerAuthenticationRequired, this, &MainWindow::trackerAuthenticationRequired); - connect(BitTorrent::Session::instance(), &BitTorrent::Session::downloadFromUrlFailed, this, &MainWindow::handleDownloadFromUrlFailure); - connect(BitTorrent::Session::instance(), &BitTorrent::Session::speedLimitModeChanged, this, &MainWindow::updateAltSpeedsBtn); - connect(BitTorrent::Session::instance(), &BitTorrent::Session::recursiveTorrentDownloadPossible, this, &MainWindow::askRecursiveTorrentDownloadConfirmation); - - qDebug("create tabWidget"); - m_tabs = new HidableTabWidget(this); - connect(m_tabs.data(), &QTabWidget::currentChanged, this, &MainWindow::tabChanged); - - m_splitter = new QSplitter(Qt::Horizontal, this); - // vSplitter->setChildrenCollapsible(false); - - QSplitter *hSplitter = new QSplitter(Qt::Vertical, this); - hSplitter->setChildrenCollapsible(false); - hSplitter->setFrameShape(QFrame::NoFrame); - - // Name filter - m_searchFilter = new LineEdit(this); - m_searchFilterAction = m_ui->toolBar->insertWidget(m_ui->actionLock, m_searchFilter); - m_searchFilter->setPlaceholderText(tr("Filter torrent list...")); - m_searchFilter->setFixedWidth(200); - - QWidget *spacer = new QWidget(this); - spacer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); - m_ui->toolBar->insertWidget(m_searchFilterAction, spacer); - - // Transfer List tab - m_transferListWidget = new TransferListWidget(hSplitter, this); - // transferList->setStyleSheet("QTreeView {border: none;}"); // borderless - m_propertiesWidget = new PropertiesWidget(hSplitter, this, m_transferListWidget); - m_transferListFiltersWidget = new TransferListFiltersWidget(m_splitter, m_transferListWidget); - m_transferListFiltersWidget->setDownloadTrackerFavicon(isDownloadTrackerFavicon()); - hSplitter->addWidget(m_transferListWidget); - hSplitter->addWidget(m_propertiesWidget); - m_splitter->addWidget(m_transferListFiltersWidget); - m_splitter->addWidget(hSplitter); - m_splitter->setCollapsible(0, true); - m_splitter->setCollapsible(1, false); - m_tabs->addTab(m_splitter, -#ifndef Q_OS_MAC - GuiIconProvider::instance()->getIcon("folder-remote"), -#endif - tr("Transfers")); - - connect(m_searchFilter, &LineEdit::textChanged, m_transferListWidget, &TransferListWidget::applyNameFilter); - connect(hSplitter, &QSplitter::splitterMoved, this, &MainWindow::writeSettings); - connect(m_splitter, &QSplitter::splitterMoved, this, &MainWindow::writeSettings); - connect(BitTorrent::Session::instance(), &BitTorrent::Session::trackersChanged, m_propertiesWidget, &PropertiesWidget::loadTrackers); - connect(BitTorrent::Session::instance(), &BitTorrent::Session::trackersAdded, m_transferListFiltersWidget, &TransferListFiltersWidget::addTrackers); - connect(BitTorrent::Session::instance(), &BitTorrent::Session::trackersRemoved, m_transferListFiltersWidget, &TransferListFiltersWidget::removeTrackers); - connect(BitTorrent::Session::instance(), &BitTorrent::Session::trackerlessStateChanged, m_transferListFiltersWidget, &TransferListFiltersWidget::changeTrackerless); - - using Func = void (TransferListFiltersWidget::*)(BitTorrent::TorrentHandle * const, const QString &); - connect(BitTorrent::Session::instance(), &BitTorrent::Session::trackerSuccess, m_transferListFiltersWidget, static_cast(&TransferListFiltersWidget::trackerSuccess)); - connect(BitTorrent::Session::instance(), &BitTorrent::Session::trackerError, m_transferListFiltersWidget, static_cast(&TransferListFiltersWidget::trackerError)); - connect(BitTorrent::Session::instance(), &BitTorrent::Session::trackerWarning, m_transferListFiltersWidget, static_cast(&TransferListFiltersWidget::trackerWarning)); - -#ifdef Q_OS_MAC - // Increase top spacing to avoid tab overlapping - m_ui->centralWidgetLayout->addSpacing(8); -#endif - - m_ui->centralWidgetLayout->addWidget(m_tabs); - - m_prioSeparator = m_ui->toolBar->insertSeparator(m_ui->actionTopPriority); - m_prioSeparatorMenu = m_ui->menuEdit->insertSeparator(m_ui->actionTopPriority); - -#ifdef Q_OS_MAC - foreach (QAction *action, m_ui->toolBar->actions()) { - if (action->isSeparator()) { - QWidget *spacer = new QWidget(this); - spacer->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); - spacer->setMinimumWidth(16); - m_ui->toolBar->insertWidget(action, spacer); - m_ui->toolBar->removeAction(action); - } - } - { - QWidget *spacer = new QWidget(this); - spacer->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); - spacer->setMinimumWidth(8); - m_ui->toolBar->insertWidget(m_ui->actionDownloadFromURL, spacer); - } - { - QWidget *spacer = new QWidget(this); - spacer->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); - spacer->setMinimumWidth(8); - m_ui->toolBar->addWidget(spacer); - } -#endif - - // Transfer list slots - connect(m_ui->actionStart, &QAction::triggered, m_transferListWidget, &TransferListWidget::startSelectedTorrents); - connect(m_ui->actionStartAll, &QAction::triggered, m_transferListWidget, &TransferListWidget::resumeAllTorrents); - connect(m_ui->actionPause, &QAction::triggered, m_transferListWidget, &TransferListWidget::pauseSelectedTorrents); - connect(m_ui->actionPauseAll, &QAction::triggered, m_transferListWidget, &TransferListWidget::pauseAllTorrents); - connect(m_ui->actionDelete, &QAction::triggered, m_transferListWidget, &TransferListWidget::softDeleteSelectedTorrents); - connect(m_ui->actionTopPriority, &QAction::triggered, m_transferListWidget, &TransferListWidget::topPrioSelectedTorrents); - connect(m_ui->actionIncreasePriority, &QAction::triggered, m_transferListWidget, &TransferListWidget::increasePrioSelectedTorrents); - connect(m_ui->actionDecreasePriority, &QAction::triggered, m_transferListWidget, &TransferListWidget::decreasePrioSelectedTorrents); - connect(m_ui->actionBottomPriority, &QAction::triggered, m_transferListWidget, &TransferListWidget::bottomPrioSelectedTorrents); -#ifndef Q_OS_MAC - connect(m_ui->actionToggleVisibility, &QAction::triggered, this, [this]() { toggleVisibility(); }); -#endif - connect(m_ui->actionMinimize, &QAction::triggered, this, &MainWindow::minimizeWindow); - connect(m_ui->actionUseAlternativeSpeedLimits, &QAction::triggered, this, &MainWindow::toggleAlternativeSpeeds); - -#if defined(Q_OS_WIN) || defined(Q_OS_MAC) - m_programUpdateTimer = new QTimer(this); - m_programUpdateTimer->setInterval(60 * 60 * 1000); - m_programUpdateTimer->setSingleShot(true); - connect(m_programUpdateTimer, &QTimer::timeout, this, &MainWindow::checkProgramUpdate); - connect(m_ui->actionCheckForUpdates, &QAction::triggered, this, &MainWindow::checkProgramUpdate); -#else - m_ui->actionCheckForUpdates->setVisible(false); -#endif - - // Certain menu items should reside at specific places on macOS. - // Qt partially does it on its own, but updates and different languages require tuning. - m_ui->actionExit->setMenuRole(QAction::QuitRole); - m_ui->actionAbout->setMenuRole(QAction::AboutRole); - m_ui->actionCheckForUpdates->setMenuRole(QAction::ApplicationSpecificRole); - m_ui->actionOptions->setMenuRole(QAction::PreferencesRole); - - connect(m_ui->actionManageCookies, &QAction::triggered, this, &MainWindow::manageCookies); - - m_pwr = new PowerManagement(this); - m_preventTimer = new QTimer(this); - connect(m_preventTimer, &QTimer::timeout, this, &MainWindow::checkForActiveTorrents); - - // Configure BT session according to options - loadPreferences(false); - - connect(BitTorrent::Session::instance(), &BitTorrent::Session::torrentsUpdated, this, &MainWindow::updateGUI); - - // Accept drag 'n drops - setAcceptDrops(true); - createKeyboardShortcuts(); - -#ifdef Q_OS_MAC - setUnifiedTitleAndToolBarOnMac(true); -#endif - - // View settings - m_ui->actionTopToolBar->setChecked(pref->isToolbarDisplayed()); - m_ui->actionShowStatusbar->setChecked(pref->isStatusbarDisplayed()); - m_ui->actionSpeedInTitleBar->setChecked(pref->speedInTitleBar()); - m_ui->actionRSSReader->setChecked(pref->isRSSWidgetEnabled()); - m_ui->actionSearchWidget->setChecked(pref->isSearchEnabled()); - m_ui->actionExecutionLogs->setChecked(isExecutionLogEnabled()); - - Log::MsgTypes flags(executionLogMsgTypes()); - m_ui->actionNormalMessages->setChecked(flags & Log::NORMAL); - m_ui->actionInformationMessages->setChecked(flags & Log::INFO); - m_ui->actionWarningMessages->setChecked(flags & Log::WARNING); - m_ui->actionCriticalMessages->setChecked(flags & Log::CRITICAL); - - displayRSSTab(m_ui->actionRSSReader->isChecked()); - on_actionExecutionLogs_triggered(m_ui->actionExecutionLogs->isChecked()); - on_actionNormalMessages_triggered(m_ui->actionNormalMessages->isChecked()); - on_actionInformationMessages_triggered(m_ui->actionInformationMessages->isChecked()); - on_actionWarningMessages_triggered(m_ui->actionWarningMessages->isChecked()); - on_actionCriticalMessages_triggered(m_ui->actionCriticalMessages->isChecked()); - if (m_ui->actionSearchWidget->isChecked()) - QTimer::singleShot(0, this, SLOT(on_actionSearchWidget_triggered())); - - // Auto shutdown actions - QActionGroup *autoShutdownGroup = new QActionGroup(this); - autoShutdownGroup->setExclusive(true); - autoShutdownGroup->addAction(m_ui->actionAutoShutdownDisabled); - autoShutdownGroup->addAction(m_ui->actionAutoExit); - autoShutdownGroup->addAction(m_ui->actionAutoShutdown); - autoShutdownGroup->addAction(m_ui->actionAutoSuspend); - autoShutdownGroup->addAction(m_ui->actionAutoHibernate); -#if (!defined(Q_OS_UNIX) || defined(Q_OS_MAC)) || defined(QT_DBUS_LIB) - m_ui->actionAutoShutdown->setChecked(pref->shutdownWhenDownloadsComplete()); - m_ui->actionAutoSuspend->setChecked(pref->suspendWhenDownloadsComplete()); - m_ui->actionAutoHibernate->setChecked(pref->hibernateWhenDownloadsComplete()); -#else - m_ui->actionAutoShutdown->setDisabled(true); - m_ui->actionAutoSuspend->setDisabled(true); - m_ui->actionAutoHibernate->setDisabled(true); -#endif - m_ui->actionAutoExit->setChecked(pref->shutdownqBTWhenDownloadsComplete()); - - if (!autoShutdownGroup->checkedAction()) - m_ui->actionAutoShutdownDisabled->setChecked(true); - - // Load Window state and sizes - readSettings(); - -#ifndef Q_OS_MAC - if (m_systrayIcon) { - if (!(pref->startMinimized() || m_uiLocked)) { - show(); - activateWindow(); - raise(); - } - else if (pref->startMinimized()) { - showMinimized(); - if (pref->minimizeToTray()) - hide(); - } - } - else { -#endif - // Make sure the Window is visible if we don't have a tray icon - if (pref->startMinimized()) { - showMinimized(); - } - else { - show(); - activateWindow(); - raise(); - } -#ifndef Q_OS_MAC - } -#endif - - m_propertiesWidget->readSettings(); - - // Start watching the executable for updates - m_executableWatcher = new QFileSystemWatcher(this); - connect(m_executableWatcher, &QFileSystemWatcher::fileChanged, this, &MainWindow::notifyOfUpdate); - m_executableWatcher->addPath(qApp->applicationFilePath()); - - m_transferListWidget->setFocus(); - - // Update the number of torrents (tab) - updateNbTorrents(); - connect(m_transferListWidget->getSourceModel(), &QAbstractItemModel::rowsInserted, this, &MainWindow::updateNbTorrents); - connect(m_transferListWidget->getSourceModel(), &QAbstractItemModel::rowsRemoved, this, &MainWindow::updateNbTorrents); - - connect(pref, &Preferences::changed, this, &MainWindow::optionsSaved); - - qDebug("GUI Built"); -#ifdef Q_OS_WIN - if (!pref->neverCheckFileAssoc() && (!Preferences::isTorrentFileAssocSet() || !Preferences::isMagnetLinkAssocSet())) { - if (QMessageBox::question(this, tr("Torrent file association"), - tr("qBittorrent is not the default application to open torrent files or Magnet links.\nDo you want to associate qBittorrent to torrent files and Magnet links?"), - QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes) == QMessageBox::Yes) { - Preferences::setTorrentFileAssoc(true); - Preferences::setMagnetLinkAssoc(true); - } - else { - pref->setNeverCheckFileAssoc(); - } - } -#endif -#ifdef Q_OS_MAC - setupDockClickHandler(); - qt_mac_set_dock_menu(trayIconMenu()); -#endif -} - -MainWindow::~MainWindow() -{ - delete m_ui; -} - -bool MainWindow::isExecutionLogEnabled() const -{ - return settings()->loadValue(KEY_EXECUTIONLOG_ENABLED, false).toBool(); -} - -void MainWindow::setExecutionLogEnabled(bool value) -{ - settings()->storeValue(KEY_EXECUTIONLOG_ENABLED, value); -} - -int MainWindow::executionLogMsgTypes() const -{ - // as default value we need all the bits set - // -1 is considered the portable way to achieve that - return settings()->loadValue(KEY_EXECUTIONLOG_TYPES, -1).toInt(); -} - -void MainWindow::setExecutionLogMsgTypes(const int value) -{ - m_executionLog->showMsgTypes(static_cast(value)); - settings()->storeValue(KEY_EXECUTIONLOG_TYPES, value); -} - -bool MainWindow::isNotificationsEnabled() const -{ - return settings()->loadValue(KEY_NOTIFICATIONS_ENABLED, true).toBool(); -} - -void MainWindow::setNotificationsEnabled(bool value) -{ - settings()->storeValue(KEY_NOTIFICATIONS_ENABLED, value); -} - -bool MainWindow::isTorrentAddedNotificationsEnabled() const -{ - return settings()->loadValue(KEY_NOTIFICATIONS_TORRENTADDED, false).toBool(); -} - -void MainWindow::setTorrentAddedNotificationsEnabled(bool value) -{ - settings()->storeValue(KEY_NOTIFICATIONS_TORRENTADDED, value); -} - -bool MainWindow::isDownloadTrackerFavicon() const -{ - return settings()->loadValue(KEY_DOWNLOAD_TRACKER_FAVICON, true).toBool(); -} - -void MainWindow::setDownloadTrackerFavicon(bool value) -{ - m_transferListFiltersWidget->setDownloadTrackerFavicon(value); - settings()->storeValue(KEY_DOWNLOAD_TRACKER_FAVICON, value); -} - -void MainWindow::addToolbarContextMenu() -{ - const Preferences *const pref = Preferences::instance(); - m_toolbarMenu = new QMenu(this); - - m_ui->toolBar->setContextMenuPolicy(Qt::CustomContextMenu); - connect(m_ui->toolBar, &QWidget::customContextMenuRequested, this, &MainWindow::toolbarMenuRequested); - - QAction *iconsOnly = new QAction(tr("Icons Only"), m_toolbarMenu); - connect(iconsOnly, &QAction::triggered, this, &MainWindow::toolbarIconsOnly); - QAction *textOnly = new QAction(tr("Text Only"), m_toolbarMenu); - connect(textOnly, &QAction::triggered, this, &MainWindow::toolbarTextOnly); - QAction *textBesideIcons = new QAction(tr("Text Alongside Icons"), m_toolbarMenu); - connect(textBesideIcons, &QAction::triggered, this, &MainWindow::toolbarTextBeside); - QAction *textUnderIcons = new QAction(tr("Text Under Icons"), m_toolbarMenu); - connect(textUnderIcons, &QAction::triggered, this, &MainWindow::toolbarTextUnder); - QAction *followSystemStyle = new QAction(tr("Follow System Style"), m_toolbarMenu); - connect(followSystemStyle, &QAction::triggered, this, &MainWindow::toolbarFollowSystem); - m_toolbarMenu->addAction(iconsOnly); - m_toolbarMenu->addAction(textOnly); - m_toolbarMenu->addAction(textBesideIcons); - m_toolbarMenu->addAction(textUnderIcons); - m_toolbarMenu->addAction(followSystemStyle); - QActionGroup *textPositionGroup = new QActionGroup(m_toolbarMenu); - textPositionGroup->addAction(iconsOnly); - iconsOnly->setCheckable(true); - textPositionGroup->addAction(textOnly); - textOnly->setCheckable(true); - textPositionGroup->addAction(textBesideIcons); - textBesideIcons->setCheckable(true); - textPositionGroup->addAction(textUnderIcons); - textUnderIcons->setCheckable(true); - textPositionGroup->addAction(followSystemStyle); - followSystemStyle->setCheckable(true); - - const Qt::ToolButtonStyle buttonStyle = static_cast(pref->getToolbarTextPosition()); - if ((buttonStyle >= Qt::ToolButtonIconOnly) && (buttonStyle <= Qt::ToolButtonFollowStyle)) - m_ui->toolBar->setToolButtonStyle(buttonStyle); - switch (buttonStyle) { - case Qt::ToolButtonIconOnly: - iconsOnly->setChecked(true); - break; - case Qt::ToolButtonTextOnly: - textOnly->setChecked(true); - break; - case Qt::ToolButtonTextBesideIcon: - textBesideIcons->setChecked(true); - break; - case Qt::ToolButtonTextUnderIcon: - textUnderIcons->setChecked(true); - break; - default: - followSystemStyle->setChecked(true); - } -} - -void MainWindow::manageCookies() -{ - CookiesDialog(this).exec(); -} - -void MainWindow::toolbarMenuRequested(QPoint point) -{ - m_toolbarMenu->exec(m_ui->toolBar->mapToGlobal(point)); -} - -void MainWindow::toolbarIconsOnly() -{ - m_ui->toolBar->setToolButtonStyle(Qt::ToolButtonIconOnly); - Preferences::instance()->setToolbarTextPosition(Qt::ToolButtonIconOnly); -} - -void MainWindow::toolbarTextOnly() -{ - m_ui->toolBar->setToolButtonStyle(Qt::ToolButtonTextOnly); - Preferences::instance()->setToolbarTextPosition(Qt::ToolButtonTextOnly); -} - -void MainWindow::toolbarTextBeside() -{ - m_ui->toolBar->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); - Preferences::instance()->setToolbarTextPosition(Qt::ToolButtonTextBesideIcon); -} - -void MainWindow::toolbarTextUnder() -{ - m_ui->toolBar->setToolButtonStyle(Qt::ToolButtonTextUnderIcon); - Preferences::instance()->setToolbarTextPosition(Qt::ToolButtonTextUnderIcon); -} - -void MainWindow::toolbarFollowSystem() -{ - m_ui->toolBar->setToolButtonStyle(Qt::ToolButtonFollowStyle); - Preferences::instance()->setToolbarTextPosition(Qt::ToolButtonFollowStyle); -} - -void MainWindow::defineUILockPassword() -{ - QString oldPassMd5 = Preferences::instance()->getUILockPasswordMD5(); - if (oldPassMd5.isNull()) - oldPassMd5 = ""; - - bool ok = false; - QString newClearPassword = AutoExpandableDialog::getText(this, tr("UI lock password"), tr("Please type the UI lock password:"), QLineEdit::Password, oldPassMd5, &ok); - if (ok) { - newClearPassword = newClearPassword.trimmed(); - if (newClearPassword.size() < 3) { - QMessageBox::warning(this, tr("Invalid password"), tr("The password should contain at least 3 characters")); - } - else { - if (newClearPassword != oldPassMd5) - Preferences::instance()->setUILockPassword(newClearPassword); - QMessageBox::information(this, tr("Password update"), tr("The UI lock password has been successfully updated")); - } - } -} - -void MainWindow::clearUILockPassword() -{ - QMessageBox::StandardButton answer = QMessageBox::question(this, tr("Clear the password"), tr("Are you sure you want to clear the password?"), QMessageBox::Yes | QMessageBox::No, QMessageBox::No); - if (answer == QMessageBox::Yes) - Preferences::instance()->clearUILockPassword(); -} - -void MainWindow::on_actionLock_triggered() -{ - Preferences *const pref = Preferences::instance(); - // Check if there is a password - if (pref->getUILockPasswordMD5().isEmpty()) { - // Ask for a password - bool ok = false; - QString clearPassword = AutoExpandableDialog::getText(this, tr("UI lock password"), tr("Please type the UI lock password:"), QLineEdit::Password, "", &ok); - if (!ok) return; - pref->setUILockPassword(clearPassword); - } - // Lock the interface - m_uiLocked = true; - pref->setUILocked(true); - m_trayIconMenu->setEnabled(false); - hide(); -} - -void MainWindow::handleRSSUnreadCountUpdated(int count) -{ - m_tabs->setTabText(m_tabs->indexOf(m_rssWidget), tr("RSS (%1)").arg(count)); -} - -void MainWindow::displayRSSTab(bool enable) -{ - if (enable) { - // RSS tab - if (!m_rssWidget) { - m_rssWidget = new RSSWidget(m_tabs); - connect(m_rssWidget.data(), &RSSWidget::unreadCountUpdated, this, &MainWindow::handleRSSUnreadCountUpdated); - int indexTab = m_tabs->addTab(m_rssWidget, tr("RSS (%1)").arg(RSS::Session::instance()->rootFolder()->unreadCount())); -#ifndef Q_OS_MAC - m_tabs->setTabIcon(indexTab, GuiIconProvider::instance()->getIcon("application-rss+xml")); -#endif - } - } - else if (m_rssWidget) { - delete m_rssWidget; - } -} - -void MainWindow::displaySearchTab(bool enable) -{ - Preferences::instance()->setSearchEnabled(enable); - if (enable) { - // RSS tab - if (!m_searchWidget) { - m_searchWidget = new SearchWidget(this); - m_tabs->insertTab(1, m_searchWidget, -#ifndef Q_OS_MAC - GuiIconProvider::instance()->getIcon("edit-find"), -#endif - tr("Search")); - } - } - else if (m_searchWidget) { - delete m_searchWidget; - } -} - -void MainWindow::focusSearchFilter() -{ - m_searchFilter->setFocus(); - m_searchFilter->selectAll(); -} - -void MainWindow::updateNbTorrents() -{ - m_tabs->setTabText(0, tr("Transfers (%1)").arg(m_transferListWidget->getSourceModel()->rowCount())); -} - -void MainWindow::on_actionDocumentation_triggered() const -{ - QDesktopServices::openUrl(QUrl("http://doc.qbittorrent.org")); -} - -void MainWindow::tabChanged(int newTab) -{ - Q_UNUSED(newTab); - // We cannot rely on the index newTab - // because the tab order is undetermined now - if (m_tabs->currentWidget() == m_splitter) { - qDebug("Changed tab to transfer list, refreshing the list"); - m_propertiesWidget->loadDynamicData(); - m_searchFilterAction->setVisible(true); - return; - } - else { - m_searchFilterAction->setVisible(false); - } - if (m_tabs->currentWidget() == m_searchWidget) { - qDebug("Changed tab to search engine, giving focus to search input"); - m_searchWidget->giveFocusToSearchInput(); - } -} - -void MainWindow::writeSettings() -{ - Preferences *const pref = Preferences::instance(); - pref->setMainGeometry(saveGeometry()); - // Splitter size - pref->setMainVSplitterState(m_splitter->saveState()); - m_propertiesWidget->saveSettings(); -} - -void MainWindow::cleanup() -{ - writeSettings(); - - // delete RSSWidget explicitly to avoid crash in - // handleRSSUnreadCountUpdated() at application shutdown - delete m_rssWidget; - - delete m_executableWatcher; -#ifndef Q_OS_MAC - if (m_systrayCreator) - m_systrayCreator->stop(); -#endif - if (m_preventTimer) - m_preventTimer->stop(); -#if (defined(Q_OS_WIN) || defined(Q_OS_MAC)) - m_programUpdateTimer->stop(); -#endif - - delete m_searchFilterAction; - - // remove all child widgets - while (QWidget *w = findChild()) - delete w; -} - -void MainWindow::readSettings() -{ - const Preferences *const pref = Preferences::instance(); - const QByteArray mainGeo = pref->getMainGeometry(); - if (!mainGeo.isEmpty() && restoreGeometry(mainGeo)) - m_posInitialized = true; - const QByteArray splitterState = pref->getMainVSplitterState(); - if (splitterState.isEmpty()) - // Default sizes - m_splitter->setSizes({ 120, m_splitter->width() - 120 }); - else - m_splitter->restoreState(splitterState); -} - -void MainWindow::balloonClicked() -{ - if (isHidden()) { - if (m_uiLocked) { - // Ask for UI lock password - if (!unlockUI()) - return; - } - show(); - if (isMinimized()) - showNormal(); - } - - raise(); - activateWindow(); -} - -void MainWindow::addTorrentFailed(const QString &error) const -{ - showNotificationBaloon(tr("Error"), tr("Failed to add torrent: %1").arg(error)); -} - -// called when a torrent was added -void MainWindow::torrentNew(BitTorrent::TorrentHandle *const torrent) const -{ - if (isTorrentAddedNotificationsEnabled()) - showNotificationBaloon(tr("Torrent added"), tr("'%1' was added.", "e.g: xxx.avi was added.").arg(torrent->name())); -} - -// called when a torrent has finished -void MainWindow::finishedTorrent(BitTorrent::TorrentHandle *const torrent) const -{ - showNotificationBaloon(tr("Download completion"), tr("'%1' has finished downloading.", "e.g: xxx.avi has finished downloading.").arg(torrent->name())); -} - -// Notification when disk is full -void MainWindow::fullDiskError(BitTorrent::TorrentHandle *const torrent, QString msg) const -{ - showNotificationBaloon(tr("I/O Error", "i.e: Input/Output Error"), tr("An I/O error occurred for torrent '%1'.\n Reason: %2", "e.g: An error occurred for torrent 'xxx.avi'.\n Reason: disk is full.").arg(torrent->name()).arg(msg)); -} - -void MainWindow::createKeyboardShortcuts() -{ - m_ui->actionCreateTorrent->setShortcut(QKeySequence::New); - m_ui->actionOpen->setShortcut(QKeySequence::Open); - m_ui->actionDownloadFromURL->setShortcut(Qt::CTRL + Qt::SHIFT + Qt::Key_O); - m_ui->actionExit->setShortcut(Qt::CTRL + Qt::Key_Q); - - QShortcut *switchTransferShortcut = new QShortcut(Qt::ALT + Qt::Key_1, this); - connect(switchTransferShortcut, &QShortcut::activated, this, &MainWindow::displayTransferTab); - - using Func = void (MainWindow::*)(); - QShortcut *switchSearchShortcut = new QShortcut(Qt::ALT + Qt::Key_2, this); - connect(switchSearchShortcut, &QShortcut::activated, this, static_cast(&MainWindow::displaySearchTab)); - QShortcut *switchRSSShortcut = new QShortcut(Qt::ALT + Qt::Key_3, this); - connect(switchRSSShortcut, &QShortcut::activated, this, static_cast(&MainWindow::displayRSSTab)); - QShortcut *switchExecutionLogShortcut = new QShortcut(Qt::ALT + Qt::Key_4, this); - connect(switchExecutionLogShortcut, &QShortcut::activated, this, &MainWindow::displayExecutionLogTab); - QShortcut *switchSearchFilterShortcut = new QShortcut(QKeySequence::Find, this); - connect(switchSearchFilterShortcut, &QShortcut::activated, this, &MainWindow::focusSearchFilter); - - m_ui->actionDocumentation->setShortcut(QKeySequence::HelpContents); - m_ui->actionOptions->setShortcut(Qt::ALT + Qt::Key_O); - m_ui->actionStart->setShortcut(Qt::CTRL + Qt::Key_S); - m_ui->actionStartAll->setShortcut(Qt::CTRL + Qt::SHIFT +Qt::Key_S); - m_ui->actionPause->setShortcut(Qt::CTRL + Qt::Key_P); - m_ui->actionPauseAll->setShortcut(Qt::CTRL + Qt::SHIFT + Qt::Key_P); - m_ui->actionBottomPriority->setShortcut(Qt::CTRL + Qt::SHIFT + Qt::Key_Minus); - m_ui->actionDecreasePriority->setShortcut(Qt::CTRL + Qt::Key_Minus); - m_ui->actionIncreasePriority->setShortcut(Qt::CTRL + Qt::Key_Plus); - m_ui->actionTopPriority->setShortcut(Qt::CTRL + Qt::SHIFT + Qt::Key_Plus); -#ifdef Q_OS_MAC - m_ui->actionMinimize->setShortcut(Qt::CTRL + Qt::Key_M); - addAction(m_ui->actionMinimize); -#endif -} - -// Keyboard shortcuts slots -void MainWindow::displayTransferTab() const -{ - m_tabs->setCurrentWidget(m_transferListWidget); -} - -void MainWindow::displaySearchTab() -{ - if (!m_searchWidget) { - m_ui->actionSearchWidget->setChecked(true); - displaySearchTab(true); - } - - m_tabs->setCurrentWidget(m_searchWidget); -} - -void MainWindow::displayRSSTab() -{ - if (!m_rssWidget) { - m_ui->actionRSSReader->setChecked(true); - displayRSSTab(true); - } - - m_tabs->setCurrentWidget(m_rssWidget); -} - -void MainWindow::displayExecutionLogTab() -{ - if (!m_executionLog) { - m_ui->actionExecutionLogs->setChecked(true); - on_actionExecutionLogs_triggered(true); - } - - m_tabs->setCurrentWidget(m_executionLog); -} - -// End of keyboard shortcuts slots - -void MainWindow::askRecursiveTorrentDownloadConfirmation(BitTorrent::TorrentHandle *const torrent) -{ - Preferences *const pref = Preferences::instance(); - if (pref->recursiveDownloadDisabled()) return; - // Get Torrent name - QString torrentName = torrent->name(); - QMessageBox confirmBox(QMessageBox::Question, tr("Recursive download confirmation"), tr("The torrent '%1' contains torrent files, do you want to proceed with their download?").arg(torrentName), QMessageBox::NoButton, this); - QPushButton *yes = confirmBox.addButton(tr("Yes"), QMessageBox::YesRole); - /*QPushButton *no = */ confirmBox.addButton(tr("No"), QMessageBox::NoRole); - QPushButton *never = confirmBox.addButton(tr("Never"), QMessageBox::NoRole); - confirmBox.exec(); - - if (confirmBox.clickedButton() == yes) - BitTorrent::Session::instance()->recursiveTorrentDownload(torrent->hash()); - else if (confirmBox.clickedButton() == never) - pref->disableRecursiveDownload(); -} - -void MainWindow::handleDownloadFromUrlFailure(QString url, QString reason) const -{ - // Display a message box - showNotificationBaloon(tr("URL download error"), tr("Couldn't download file at URL '%1', reason: %2.").arg(url).arg(reason)); -} - -void MainWindow::on_actionSetGlobalUploadLimit_triggered() -{ - qDebug() << Q_FUNC_INFO; - - BitTorrent::Session *const session = BitTorrent::Session::instance(); - bool ok = false; - const long newLimit = SpeedLimitDialog::askSpeedLimit( - this, &ok, tr("Global Upload Speed Limit"), session->uploadSpeedLimit()); - - if (ok) { - qDebug("Setting global upload rate limit to %.1fKb/s", newLimit / 1024.); - session->setUploadSpeedLimit(newLimit); - } -} - -void MainWindow::on_actionSetGlobalDownloadLimit_triggered() -{ - qDebug() << Q_FUNC_INFO; - - BitTorrent::Session *const session = BitTorrent::Session::instance(); - bool ok = false; - const long newLimit = SpeedLimitDialog::askSpeedLimit( - this, &ok, tr("Global Download Speed Limit"), session->downloadSpeedLimit()); - - if (ok) { - qDebug("Setting global download rate limit to %.1fKb/s", newLimit / 1024.); - session->setDownloadSpeedLimit(newLimit); - } -} - -// Necessary if we want to close the window -// in one time if "close to systray" is enabled -void MainWindow::on_actionExit_triggered() -{ - // UI locking enforcement. - if (isHidden() && m_uiLocked) - // Ask for UI lock password - if (!unlockUI()) return; - - m_forceExit = true; - close(); -} - -QWidget *MainWindow::currentTabWidget() const -{ - if (isMinimized() || !isVisible()) - return 0; - if (m_tabs->currentIndex() == 0) - return m_transferListWidget; - return m_tabs->currentWidget(); -} - -TransferListWidget *MainWindow::transferListWidget() const -{ - return m_transferListWidget; -} - -bool MainWindow::unlockUI() -{ - if (m_unlockDlgShowing) - return false; - else - m_unlockDlgShowing = true; - - bool ok = false; - QString clearPassword = AutoExpandableDialog::getText(this, tr("UI lock password"), tr("Please type the UI lock password:"), QLineEdit::Password, "", &ok); - m_unlockDlgShowing = false; - if (!ok) return false; - - Preferences *const pref = Preferences::instance(); - QString realPassMd5 = pref->getUILockPasswordMD5(); - QCryptographicHash md5(QCryptographicHash::Md5); - md5.addData(clearPassword.toLocal8Bit()); - QString passwordMd5 = md5.result().toHex(); - if (realPassMd5 == passwordMd5) { - m_uiLocked = false; - pref->setUILocked(false); - m_trayIconMenu->setEnabled(true); - return true; - } - QMessageBox::warning(this, tr("Invalid password"), tr("The password is invalid")); - return false; -} - -void MainWindow::notifyOfUpdate(QString) -{ - // Show restart message - m_statusBar->showRestartRequired(); - Logger::instance()->addMessage(tr("qBittorrent was just updated and needs to be restarted for the changes to be effective.") - , Log::CRITICAL); - // Delete the executable watcher - delete m_executableWatcher; - m_executableWatcher = 0; -} - -#ifndef Q_OS_MAC -// Toggle Main window visibility -void MainWindow::toggleVisibility(const QSystemTrayIcon::ActivationReason reason) -{ - switch (reason) { - case QSystemTrayIcon::Trigger: { - if (isHidden()) { - if (m_uiLocked && !unlockUI()) // Ask for UI lock password - return; - - // Make sure the window is not minimized - setWindowState((windowState() & ~Qt::WindowMinimized) | Qt::WindowActive); - - // Then show it - show(); - raise(); - activateWindow(); - } - else { - hide(); - } - - break; - } - - default: - break; - } -} -#endif - -// Display About Dialog -void MainWindow::on_actionAbout_triggered() -{ - // About dialog - if (m_aboutDlg) - m_aboutDlg->activateWindow(); - else - m_aboutDlg = new about(this); -} - -void MainWindow::on_actionStatistics_triggered() -{ - if (m_statsDlg) - m_statsDlg->activateWindow(); - else - m_statsDlg = new StatsDialog(this); -} - -void MainWindow::showEvent(QShowEvent *e) -{ - qDebug("** Show Event **"); - - if (currentTabWidget() == m_transferListWidget) - m_propertiesWidget->loadDynamicData(); - - e->accept(); - - // Make sure the window is initially centered - if (!m_posInitialized) { - move(Utils::Misc::screenCenter(this)); - m_posInitialized = true; - } -} - -// Called when we close the program -void MainWindow::closeEvent(QCloseEvent *e) -{ - Preferences *const pref = Preferences::instance(); -#ifdef Q_OS_MAC - if (!m_forceExit) { - hide(); - e->accept(); - return; - } -#else - const bool goToSystrayOnExit = pref->closeToTray(); - if (!m_forceExit && m_systrayIcon && goToSystrayOnExit && !this->isHidden()) { - hide(); - e->accept(); - return; - } -#endif - - if (pref->confirmOnExit() && BitTorrent::Session::instance()->hasActiveTorrents()) { - if (e->spontaneous() || m_forceExit) { - if (!isVisible()) - show(); - QMessageBox confirmBox(QMessageBox::Question, tr("Exiting qBittorrent"), - // Split it because the last sentence is used in the Web UI - tr("Some files are currently transferring.") + "\n" + tr("Are you sure you want to quit qBittorrent?"), - QMessageBox::NoButton, this); - QPushButton *noBtn = confirmBox.addButton(tr("&No"), QMessageBox::NoRole); - confirmBox.addButton(tr("&Yes"), QMessageBox::YesRole); - QPushButton *alwaysBtn = confirmBox.addButton(tr("&Always Yes"), QMessageBox::YesRole); - confirmBox.setDefaultButton(noBtn); - confirmBox.exec(); - if (!confirmBox.clickedButton() || (confirmBox.clickedButton() == noBtn)) { - // Cancel exit - e->ignore(); - m_forceExit = false; - return; - } - if (confirmBox.clickedButton() == alwaysBtn) - // Remember choice - Preferences::instance()->setConfirmOnExit(false); - } - } - - // abort search if any - if (m_searchWidget) - delete m_searchWidget; - - hide(); -#ifndef Q_OS_MAC - // Hide tray icon - if (m_systrayIcon) - m_systrayIcon->hide(); -#endif - // Accept exit - e->accept(); - qApp->exit(); -} - -// Display window to create a torrent -void MainWindow::on_actionCreateTorrent_triggered() -{ - createTorrentTriggered(); -} - -void MainWindow::createTorrentTriggered(const QString &path) -{ - if (m_createTorrentDlg) { - m_createTorrentDlg->updateInputPath(path); - m_createTorrentDlg->activateWindow(); - } - else - m_createTorrentDlg = new TorrentCreatorDlg(this, path); -} - -bool MainWindow::event(QEvent *e) -{ -#ifndef Q_OS_MAC - switch (e->type()) { - case QEvent::WindowStateChange: { - qDebug("Window change event"); - // Now check to see if the window is minimised - if (isMinimized()) { - qDebug("minimisation"); - if (m_systrayIcon && Preferences::instance()->minimizeToTray()) { - qDebug() << "Has active window:" << (qApp->activeWindow() != nullptr); - // Check if there is a modal window - bool hasModalWindow = false; - foreach (QWidget *widget, QApplication::allWidgets()) { - if (widget->isModal()) { - hasModalWindow = true; - break; - } - } - // Iconify if there is no modal window - if (!hasModalWindow) { - qDebug("Minimize to Tray enabled, hiding!"); - e->ignore(); - QTimer::singleShot(0, this, SLOT(hide())); - return true; - } - } - } - break; - } - case QEvent::ToolBarChange: { - qDebug("MAC: Received a toolbar change event!"); - bool ret = QMainWindow::event(e); - - qDebug("MAC: new toolbar visibility is %d", !m_ui->actionTopToolBar->isChecked()); - m_ui->actionTopToolBar->toggle(); - Preferences::instance()->setToolbarDisplayed(m_ui->actionTopToolBar->isChecked()); - return ret; - } - default: - break; - } -#endif - - return QMainWindow::event(e); -} - -// action executed when a file is dropped -void MainWindow::dropEvent(QDropEvent *event) -{ - event->acceptProposedAction(); - - // remove scheme - QStringList files; - if (event->mimeData()->hasUrls()) { - const QList urls = event->mimeData()->urls(); - foreach (const QUrl &url, urls) { - if (!url.isEmpty()) { - if (url.scheme().compare("file", Qt::CaseInsensitive) == 0) - files << url.toLocalFile(); - else - files << url.toString(); - } - } - } - else { - files = event->mimeData()->text().split('\n'); - } - - // differentiate ".torrent" files and others - QStringList torrentFiles, otherFiles; - foreach (const QString &file, files) { - if (file.endsWith(C_TORRENT_FILE_EXTENSION, Qt::CaseInsensitive)) - torrentFiles << file; - else - otherFiles << file; - } - - // Download torrents - const bool useTorrentAdditionDialog = AddNewTorrentDialog::isEnabled(); - foreach (const QString &file, torrentFiles) { - qDebug("Dropped file %s on download list", qPrintable(file)); - if (useTorrentAdditionDialog) - AddNewTorrentDialog::show(file, this); - else - BitTorrent::Session::instance()->addTorrent(file); - } - if (!torrentFiles.isEmpty()) return; - - // Create torrent - foreach (const QString &file, otherFiles) { - createTorrentTriggered(file); - - // currently only hande the first entry - // this is a stub that can be expanded later to create many torrents at once - break; - } -} - -// Decode if we accept drag 'n drop or not -void MainWindow::dragEnterEvent(QDragEnterEvent *event) -{ - foreach (const QString &mime, event->mimeData()->formats()) - qDebug("mimeData: %s", mime.toLocal8Bit().data()); - if (event->mimeData()->hasFormat("text/plain") || event->mimeData()->hasFormat("text/uri-list")) - event->acceptProposedAction(); -} - -#ifdef Q_OS_MAC - -static MainWindow *dockMainWindowHandle; - -static bool dockClickHandler(id self, SEL cmd, ...) -{ - Q_UNUSED(self) - Q_UNUSED(cmd) - - qDebug("Dock icon clicked!"); - - if (dockMainWindowHandle && !dockMainWindowHandle->isVisible()) { - dockMainWindowHandle->activate(); - } - - // Return NO (false) to suppress the default OS X actions - return false; -} - -void MainWindow::setupDockClickHandler() -{ - Class cls = objc_getClass("NSApplication"); - objc_object *appInst = objc_msgSend(reinterpret_cast(cls), sel_registerName("sharedApplication")); - - if (!appInst) - return; - - dockMainWindowHandle = this; - objc_object* delegate = objc_msgSend(appInst, sel_registerName("delegate")); - Class delClass = reinterpret_cast(objc_msgSend(delegate, sel_registerName("class"))); - SEL shouldHandle = sel_registerName("applicationShouldHandleReopen:hasVisibleWindows:"); - if (class_getInstanceMethod(delClass, shouldHandle)) { - if (class_replaceMethod(delClass, shouldHandle, reinterpret_cast(dockClickHandler), "B@:")) - qDebug("Registered dock click handler (replaced original method)"); - else - qWarning("Failed to replace method for dock click handler"); - } - else { - if (class_addMethod(delClass, shouldHandle, reinterpret_cast(dockClickHandler), "B@:")) - qDebug("Registered dock click handler"); - else - qWarning("Failed to register dock click handler"); - } -} - -#endif - -/***************************************************** -* * -* Torrent * -* * -*****************************************************/ - -// Display a dialog to allow user to add -// torrents to download list -void MainWindow::on_actionOpen_triggered() -{ - Preferences *const pref = Preferences::instance(); - // Open File Open Dialog - // Note: it is possible to select more than one file - const QStringList pathsList = - QFileDialog::getOpenFileNames(this, tr("Open Torrent Files"), pref->getMainLastDir(), - tr("Torrent Files") + " (*" + C_TORRENT_FILE_EXTENSION + ')'); - - const bool useTorrentAdditionDialog = AddNewTorrentDialog::isEnabled(); - if (!pathsList.isEmpty()) { - foreach (QString file, pathsList) { - qDebug("Dropped file %s on download list", qPrintable(file)); - if (useTorrentAdditionDialog) - AddNewTorrentDialog::show(file, this); - else - BitTorrent::Session::instance()->addTorrent(file); - } - - // Save last dir to remember it - QStringList topDir = Utils::Fs::fromNativePath(pathsList.at(0)).split("/"); - topDir.removeLast(); - pref->setMainLastDir(Utils::Fs::fromNativePath(topDir.join("/"))); - } -} - -void MainWindow::activate() -{ - if (!m_uiLocked || unlockUI()) { - show(); - activateWindow(); - raise(); - } -} - -void MainWindow::optionsSaved() -{ - loadPreferences(); -} - -void MainWindow::showStatusBar(bool show) -{ - if (!show) { - // Remove status bar - setStatusBar(nullptr); - } - else if (!m_statusBar) { - // Create status bar - m_statusBar = new StatusBar; - connect(m_statusBar.data(), &StatusBar::connectionButtonClicked, this, &MainWindow::showConnectionSettings); - connect(m_statusBar.data(), &StatusBar::alternativeSpeedsButtonClicked, this, &MainWindow::toggleAlternativeSpeeds); - setStatusBar(m_statusBar); - } -} - -void MainWindow::loadPreferences(bool configureSession) -{ - Logger::instance()->addMessage(tr("Options were saved successfully.")); - const Preferences *const pref = Preferences::instance(); -#ifndef Q_OS_MAC - const bool newSystrayIntegration = pref->systrayIntegration(); - m_ui->actionLock->setVisible(newSystrayIntegration); - if (newSystrayIntegration != (m_systrayIcon != 0)) { - if (newSystrayIntegration) { - // create the trayicon - if (!QSystemTrayIcon::isSystemTrayAvailable()) { - if (!configureSession) { // Program startup - m_systrayCreator = new QTimer(this); - connect(m_systrayCreator.data(), &QTimer::timeout, this, &MainWindow::createSystrayDelayed); - m_systrayCreator->setSingleShot(true); - m_systrayCreator->start(2000); - qDebug("Info: System tray is unavailable, trying again later."); - } - else { - qDebug("Warning: System tray is unavailable."); - } - } - else { - createTrayIcon(); - } - } - else { - // Destroy trayicon - delete m_systrayIcon; - delete m_trayIconMenu; - } - } - // Reload systray icon - if (newSystrayIntegration && m_systrayIcon) - m_systrayIcon->setIcon(getSystrayIcon()); -#endif - // General - if (pref->isToolbarDisplayed()) { - m_ui->toolBar->setVisible(true); - } - else { - // Clear search filter before hiding the top toolbar - m_searchFilter->clear(); - m_ui->toolBar->setVisible(false); - } - - showStatusBar(pref->isStatusbarDisplayed()); - - if (pref->preventFromSuspend() && !m_preventTimer->isActive()) { - m_preventTimer->start(PREVENT_SUSPEND_INTERVAL); - } - else { - m_preventTimer->stop(); - m_pwr->setActivityState(false); - } - - m_transferListWidget->setAlternatingRowColors(pref->useAlternatingRowColors()); - m_propertiesWidget->getFilesList()->setAlternatingRowColors(pref->useAlternatingRowColors()); - m_propertiesWidget->getTrackerList()->setAlternatingRowColors(pref->useAlternatingRowColors()); - m_propertiesWidget->getPeerList()->setAlternatingRowColors(pref->useAlternatingRowColors()); - - // Queueing System - if (BitTorrent::Session::instance()->isQueueingSystemEnabled()) { - if (!m_ui->actionDecreasePriority->isVisible()) { - m_transferListWidget->hidePriorityColumn(false); - m_ui->actionDecreasePriority->setVisible(true); - m_ui->actionIncreasePriority->setVisible(true); - m_ui->actionTopPriority->setVisible(true); - m_ui->actionBottomPriority->setVisible(true); -#ifndef Q_OS_MAC - m_prioSeparator->setVisible(true); -#endif - m_prioSeparatorMenu->setVisible(true); - } - } - else { - if (m_ui->actionDecreasePriority->isVisible()) { - m_transferListWidget->hidePriorityColumn(true); - m_ui->actionDecreasePriority->setVisible(false); - m_ui->actionIncreasePriority->setVisible(false); - m_ui->actionTopPriority->setVisible(false); - m_ui->actionBottomPriority->setVisible(false); -#ifndef Q_OS_MAC - m_prioSeparator->setVisible(false); -#endif - m_prioSeparatorMenu->setVisible(false); - } - } - - // Torrent properties - m_propertiesWidget->reloadPreferences(); - -#if defined(Q_OS_WIN) || defined(Q_OS_MAC) - if (pref->isUpdateCheckEnabled() && !m_wasUpdateCheckEnabled) { - m_wasUpdateCheckEnabled = true; - checkProgramUpdate(); - } - else if (!pref->isUpdateCheckEnabled() && m_wasUpdateCheckEnabled) { - m_wasUpdateCheckEnabled = false; - m_programUpdateTimer->stop(); - } -#endif - - qDebug("GUI settings loaded"); -} - -void MainWindow::addUnauthenticatedTracker(const QPair &tracker) -{ - // Trackers whose authentication was cancelled - if (m_unauthenticatedTrackers.indexOf(tracker) < 0) - m_unauthenticatedTrackers << tracker; -} - -// Called when a tracker requires authentication -void MainWindow::trackerAuthenticationRequired(BitTorrent::TorrentHandle *const torrent) -{ -#if LIBTORRENT_VERSION_NUM < 10100 - if (m_unauthenticatedTrackers.indexOf(qMakePair(torrent, torrent->currentTracker())) < 0) - // Tracker login - new trackerLogin(this, torrent); -#else - Q_UNUSED(torrent); -#endif -} - -// Check connection status and display right icon -void MainWindow::updateGUI() -{ - const BitTorrent::SessionStatus &status = BitTorrent::Session::instance()->status(); - - // update global informations -#ifndef Q_OS_MAC - if (m_systrayIcon) { -#ifdef Q_OS_UNIX - QString html = "
"; - html += "qBittorrent"; - html += "
"; - html += "
"; - html += " " + tr("DL speed: %1", "e.g: Download speed: 10 KiB/s").arg(Utils::Misc::friendlyUnit(status.payloadDownloadRate, true)); - html += "
"; - html += "
"; - html += " " + tr("UP speed: %1", "e.g: Upload speed: 10 KiB/s").arg(Utils::Misc::friendlyUnit(status.payloadUploadRate, true)); - html += "
"; -#else - // OSes such as Windows do not support html here - QString html = tr("DL speed: %1", "e.g: Download speed: 10 KiB/s").arg(Utils::Misc::friendlyUnit(status.payloadDownloadRate, true)); - html += "\n"; - html += tr("UP speed: %1", "e.g: Upload speed: 10 KiB/s").arg(Utils::Misc::friendlyUnit(status.payloadUploadRate, true)); -#endif // Q_OS_UNIX - m_systrayIcon->setToolTip(html); // tray icon - } -#else - if (status.payloadDownloadRate > 0) - QtMac::setBadgeLabelText(tr("%1/s", "s is a shorthand for seconds") - .arg(Utils::Misc::friendlyUnit(status.payloadDownloadRate))); - else if (!QtMac::badgeLabelText().isEmpty()) - QtMac::setBadgeLabelText(""); -#endif // Q_OS_MAC - - if (m_displaySpeedInTitle) { - setWindowTitle(tr("[D: %1, U: %2] qBittorrent %3", "D = Download; U = Upload; %3 is qBittorrent version") - .arg(Utils::Misc::friendlyUnit(status.payloadDownloadRate, true)) - .arg(Utils::Misc::friendlyUnit(status.payloadUploadRate, true)) - .arg(QBT_VERSION)); - } -} - -void MainWindow::showNotificationBaloon(QString title, QString msg) const -{ - if (!isNotificationsEnabled()) return; -#if (defined(Q_OS_UNIX) && !defined(Q_OS_MAC)) && defined(QT_DBUS_LIB) - org::freedesktop::Notifications notifications("org.freedesktop.Notifications", - "/org/freedesktop/Notifications", - QDBusConnection::sessionBus()); - // Testing for 'notifications.isValid()' isn't helpful here. - // If the notification daemon is configured to run 'as needed' - // the above check can be false if the daemon wasn't started - // by another application. In this case DBus will be able to - // start the notification daemon and complete our request. Such - // a daemon is xfce4-notifyd, DBus autostarts it and after - // some inactivity shuts it down. Other DEs, like GNOME, choose - // to start their daemons at the session startup and have it sit - // idling for the whole session. - QVariantMap hints; - hints["desktop-entry"] = "qBittorrent"; - QDBusPendingReply reply = notifications.Notify("qBittorrent", 0, "qbittorrent", title, - msg, QStringList(), hints, -1); - reply.waitForFinished(); - if (!reply.isError()) - return; -#elif (!defined(Q_OS_MAC)) - if (m_systrayIcon && QSystemTrayIcon::supportsMessages()) - m_systrayIcon->showMessage(title, msg, QSystemTrayIcon::Information, TIME_TRAY_BALLOON); -#endif -} - -/***************************************************** -* * -* Utils * -* * -*****************************************************/ - -void MainWindow::downloadFromURLList(const QStringList &urlList) -{ - const bool useTorrentAdditionDialog = AddNewTorrentDialog::isEnabled(); - foreach (QString url, urlList) { - if (((url.size() == 40) && !url.contains(QRegExp("[^0-9A-Fa-f]"))) - || ((url.size() == 32) && !url.contains(QRegExp("[^2-7A-Za-z]")))) - url = "magnet:?xt=urn:btih:" + url; - - if (useTorrentAdditionDialog) - AddNewTorrentDialog::show(url, this); - else - BitTorrent::Session::instance()->addTorrent(url); - } -} - -/***************************************************** -* * -* Options * -* * -*****************************************************/ - -#ifndef Q_OS_MAC -void MainWindow::createSystrayDelayed() -{ - static int timeout = 20; - if (QSystemTrayIcon::isSystemTrayAvailable()) { - // Ok, systray integration is now supported - // Create systray icon - createTrayIcon(); - delete m_systrayCreator; - } - else { - if (timeout) { - // Retry a bit later - m_systrayCreator->start(2000); - --timeout; - } - else { - // Timed out, apparently system really does not - // support systray icon - delete m_systrayCreator; - // Disable it in program preferences to - // avoid trying at each startup - Preferences::instance()->setSystrayIntegration(false); - } - } -} - -void MainWindow::updateTrayIconMenu() -{ - m_ui->actionToggleVisibility->setText(isVisible() ? tr("Hide") : tr("Show")); -} - -void MainWindow::createTrayIcon() -{ - // Tray icon - m_systrayIcon = new QSystemTrayIcon(getSystrayIcon(), this); - - m_systrayIcon->setContextMenu(trayIconMenu()); - connect(m_systrayIcon.data(), &QSystemTrayIcon::messageClicked, this, &MainWindow::balloonClicked); - // End of Icon Menu - connect(m_systrayIcon.data(), &QSystemTrayIcon::activated, this, &MainWindow::toggleVisibility); - m_systrayIcon->show(); -} -#endif - -QMenu *MainWindow::trayIconMenu() -{ - if (m_trayIconMenu) return m_trayIconMenu; - - m_trayIconMenu = new QMenu(this); -#ifndef Q_OS_MAC - connect(m_trayIconMenu.data(), &QMenu::aboutToShow, this, &MainWindow::updateTrayIconMenu); - m_trayIconMenu->addAction(m_ui->actionToggleVisibility); - m_trayIconMenu->addSeparator(); -#endif - m_trayIconMenu->addAction(m_ui->actionOpen); - m_trayIconMenu->addAction(m_ui->actionDownloadFromURL); - m_trayIconMenu->addSeparator(); - const bool isAltBWEnabled = BitTorrent::Session::instance()->isAltGlobalSpeedLimitEnabled(); - updateAltSpeedsBtn(isAltBWEnabled); - m_ui->actionUseAlternativeSpeedLimits->setChecked(isAltBWEnabled); - m_trayIconMenu->addAction(m_ui->actionUseAlternativeSpeedLimits); - m_trayIconMenu->addAction(m_ui->actionSetGlobalDownloadLimit); - m_trayIconMenu->addAction(m_ui->actionSetGlobalUploadLimit); - m_trayIconMenu->addSeparator(); - m_trayIconMenu->addAction(m_ui->actionStartAll); - m_trayIconMenu->addAction(m_ui->actionPauseAll); -#ifndef Q_OS_MAC - m_trayIconMenu->addSeparator(); - m_trayIconMenu->addAction(m_ui->actionExit); -#endif - if (m_uiLocked) - m_trayIconMenu->setEnabled(false); - - return m_trayIconMenu; -} - -void MainWindow::updateAltSpeedsBtn(bool alternative) -{ - m_ui->actionUseAlternativeSpeedLimits->setChecked(alternative); -} - -PropertiesWidget *MainWindow::propertiesWidget() const -{ - return m_propertiesWidget; -} - -// Display Program Options -void MainWindow::on_actionOptions_triggered() -{ - if (m_options) - m_options->activateWindow(); - else - m_options = new OptionsDialog(this); -} - -void MainWindow::on_actionTopToolBar_triggered() -{ - const bool isVisible = static_cast(sender())->isChecked(); - m_ui->toolBar->setVisible(isVisible); - Preferences::instance()->setToolbarDisplayed(isVisible); -} - -void MainWindow::on_actionShowStatusbar_triggered() -{ - const bool isVisible = static_cast(sender())->isChecked(); - Preferences::instance()->setStatusbarDisplayed(isVisible); - showStatusBar(isVisible); -} - -void MainWindow::on_actionSpeedInTitleBar_triggered() -{ - m_displaySpeedInTitle = static_cast(sender())->isChecked(); - Preferences::instance()->showSpeedInTitleBar(m_displaySpeedInTitle); - if (m_displaySpeedInTitle) - updateGUI(); - else - setWindowTitle("qBittorrent " QBT_VERSION); -} - -void MainWindow::on_actionRSSReader_triggered() -{ - Preferences::instance()->setRSSWidgetVisible(m_ui->actionRSSReader->isChecked()); - displayRSSTab(m_ui->actionRSSReader->isChecked()); -} - -void MainWindow::on_actionSearchWidget_triggered() -{ - if (!m_hasPython && m_ui->actionSearchWidget->isChecked()) { - int pythonVersion = Utils::Misc::pythonVersion(); - - // Check if python is already in PATH - if (pythonVersion > 0) - // Prevent translators from messing with PATH - Logger::instance()->addMessage(tr("Python found in %1: %2", "Python found in PATH: /usr/local/bin:/usr/bin:/etc/bin").arg("PATH").arg(qgetenv("PATH").constData()), Log::INFO); -#ifdef Q_OS_WIN - else if (addPythonPathToEnv()) - pythonVersion = Utils::Misc::pythonVersion(); -#endif - - bool res = false; - - if ((pythonVersion == 2) || (pythonVersion == 3)) { - // Check Python minimum requirement: 2.7.9 / 3.3.0 - QString version = Utils::Misc::pythonVersionComplete(); - QStringList splitted = version.split('.'); - if (splitted.size() > 2) { - int middleVer = splitted.at(1).toInt(); - int lowerVer = splitted.at(2).toInt(); - if (((pythonVersion == 2) && (middleVer < 7)) - || ((pythonVersion == 2) && (middleVer == 7) && (lowerVer < 9)) - || ((pythonVersion == 3) && (middleVer < 3))) { - QMessageBox::information(this, tr("Old Python Interpreter"), tr("Your Python version (%1) is outdated. Please upgrade to latest version for search engines to work.\nMinimum requirement: 2.7.9 / 3.3.0.").arg(version)); - m_ui->actionSearchWidget->setChecked(false); - Preferences::instance()->setSearchEnabled(false); - return; - } - else { - res = true; - } - } - else { - QMessageBox::information(this, tr("Undetermined Python version"), tr("Couldn't determine your Python version (%1). Search engine disabled.").arg(version)); - m_ui->actionSearchWidget->setChecked(false); - Preferences::instance()->setSearchEnabled(false); - return; - } - } - - if (res) { - m_hasPython = true; - } -#ifdef Q_OS_WIN - else if (QMessageBox::question(this, tr("Missing Python Interpreter"), - tr("Python is required to use the search engine but it does not seem to be installed.\nDo you want to install it now?"), - QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes) == QMessageBox::Yes) { - // Download and Install Python - installPython(); - m_ui->actionSearchWidget->setChecked(false); - Preferences::instance()->setSearchEnabled(false); - return; - } -#endif - else { -#ifndef Q_OS_WIN - QMessageBox::information(this, tr("Missing Python Interpreter"), tr("Python is required to use the search engine but it does not seem to be installed.")); -#endif - m_ui->actionSearchWidget->setChecked(false); - Preferences::instance()->setSearchEnabled(false); - return; - } - } - displaySearchTab(m_ui->actionSearchWidget->isChecked()); -} - -/***************************************************** -* * -* HTTP Downloader * -* * -*****************************************************/ - -// Display an input dialog to prompt user for -// an url -void MainWindow::on_actionDownloadFromURL_triggered() -{ - if (!m_downloadFromURLDialog) { - m_downloadFromURLDialog = new downloadFromURL(this); - connect(m_downloadFromURLDialog.data(), &downloadFromURL::urlsReadyToBeDownloaded, this, &MainWindow::downloadFromURLList); - } -} - -#if defined(Q_OS_WIN) || defined(Q_OS_MAC) - -void MainWindow::handleUpdateCheckFinished(bool updateAvailable, QString newVersion, bool invokedByUser) -{ - QMessageBox::StandardButton answer = QMessageBox::Yes; - if (updateAvailable) { - answer = QMessageBox::question(this, tr("qBittorrent Update Available"), - tr("A new version is available.\nDo you want to download %1?").arg(newVersion), - QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes); - if (answer == QMessageBox::Yes) { - // The user want to update, let's download the update - ProgramUpdater *updater = dynamic_cast(sender()); - updater->updateProgram(); - } - } - else if (invokedByUser) { - QMessageBox::information(this, tr("Already Using the Latest qBittorrent Version"), - tr("No updates available.\nYou are already using the latest version.")); - } - sender()->deleteLater(); - m_ui->actionCheckForUpdates->setEnabled(true); - m_ui->actionCheckForUpdates->setText(tr("&Check for Updates")); - m_ui->actionCheckForUpdates->setToolTip(tr("Check for program updates")); - // Don't bother the user again in this session if he chose to ignore the update - if (Preferences::instance()->isUpdateCheckEnabled() && (answer == QMessageBox::Yes)) - m_programUpdateTimer->start(); -} -#endif - -void MainWindow::toggleAlternativeSpeeds() -{ - BitTorrent::Session *const session = BitTorrent::Session::instance(); - if (session->isBandwidthSchedulerEnabled()) - m_statusBar->showMessage(tr("Manual change of rate limits mode. The scheduler is disabled."), 5000); - session->setAltGlobalSpeedLimitEnabled(!session->isAltGlobalSpeedLimitEnabled()); -} - -void MainWindow::on_actionDonateMoney_triggered() -{ - QDesktopServices::openUrl(QUrl("http://www.qbittorrent.org/donate")); -} - -void MainWindow::showConnectionSettings() -{ - on_actionOptions_triggered(); - m_options->showConnectionTab(); -} - -void MainWindow::minimizeWindow() -{ - setWindowState(windowState() | Qt::WindowMinimized); -} - -void MainWindow::on_actionExecutionLogs_triggered(bool checked) -{ - if (checked) { - Q_ASSERT(!m_executionLog); - m_executionLog = new ExecutionLog(m_tabs, static_cast(executionLogMsgTypes())); - int indexTab = m_tabs->addTab(m_executionLog, tr("Execution Log")); -#ifndef Q_OS_MAC - m_tabs->setTabIcon(indexTab, GuiIconProvider::instance()->getIcon("view-calendar-journal")); -#endif - } - else if (m_executionLog) { - delete m_executionLog; - } - - m_ui->actionNormalMessages->setEnabled(checked); - m_ui->actionInformationMessages->setEnabled(checked); - m_ui->actionWarningMessages->setEnabled(checked); - m_ui->actionCriticalMessages->setEnabled(checked); - setExecutionLogEnabled(checked); -} - -void MainWindow::on_actionNormalMessages_triggered(bool checked) -{ - if (!m_executionLog) - return; - - Log::MsgTypes flags(executionLogMsgTypes()); - checked ? (flags |= Log::NORMAL) : (flags &= ~Log::NORMAL); - setExecutionLogMsgTypes(flags); -} - -void MainWindow::on_actionInformationMessages_triggered(bool checked) -{ - if (!m_executionLog) - return; - - Log::MsgTypes flags(executionLogMsgTypes()); - checked ? (flags |= Log::INFO) : (flags &= ~Log::INFO); - setExecutionLogMsgTypes(flags); -} - -void MainWindow::on_actionWarningMessages_triggered(bool checked) -{ - if (!m_executionLog) - return; - - Log::MsgTypes flags(executionLogMsgTypes()); - checked ? (flags |= Log::WARNING) : (flags &= ~Log::WARNING); - setExecutionLogMsgTypes(flags); -} - -void MainWindow::on_actionCriticalMessages_triggered(bool checked) -{ - if (!m_executionLog) - return; - - Log::MsgTypes flags(executionLogMsgTypes()); - checked ? (flags |= Log::CRITICAL) : (flags &= ~Log::CRITICAL); - setExecutionLogMsgTypes(flags); -} - -void MainWindow::on_actionAutoExit_toggled(bool enabled) -{ - qDebug() << Q_FUNC_INFO << enabled; - Preferences::instance()->setShutdownqBTWhenDownloadsComplete(enabled); -} - -void MainWindow::on_actionAutoSuspend_toggled(bool enabled) -{ - qDebug() << Q_FUNC_INFO << enabled; - Preferences::instance()->setSuspendWhenDownloadsComplete(enabled); -} - -void MainWindow::on_actionAutoHibernate_toggled(bool enabled) -{ - qDebug() << Q_FUNC_INFO << enabled; - Preferences::instance()->setHibernateWhenDownloadsComplete(enabled); -} - -void MainWindow::on_actionAutoShutdown_toggled(bool enabled) -{ - qDebug() << Q_FUNC_INFO << enabled; - Preferences::instance()->setShutdownWhenDownloadsComplete(enabled); -} - -void MainWindow::checkForActiveTorrents() -{ - m_pwr->setActivityState(BitTorrent::Session::instance()->hasActiveTorrents()); -} - -#ifndef Q_OS_MAC -QIcon MainWindow::getSystrayIcon() const -{ -#if (defined(Q_OS_UNIX) && !defined(Q_OS_MAC)) - if (Preferences::instance()->useSystemIconTheme()) - return QIcon::fromTheme("qbittorrent-tray"); -#endif - - const TrayIcon::Style style = Preferences::instance()->trayIconStyle(); - // on Linux we use theme icons, and icons from resources everywhere else -#if (defined(Q_OS_UNIX) && !defined(Q_OS_MAC)) - switch (style) { - case TrayIcon::MONO_DARK: - return QIcon::fromTheme(QLatin1String("qbittorrent-tray-dark")); - case TrayIcon::MONO_LIGHT: - return QIcon::fromTheme(QLatin1String("qbittorrent-tray-light")); - default: - break; - } -#else - switch (style) { - case TrayIcon::MONO_DARK: - return QIcon(QLatin1String(":/icons/skin/qbittorrent-tray-dark.svg")); - case TrayIcon::MONO_LIGHT: - return QIcon(QLatin1String(":/icons/skin/qbittorrent-tray-light.svg")); - default: - break; - } -#endif - - QIcon icon; - icon.addFile(":/icons/skin/qbittorrent22.png", QSize(22, 22)); - icon.addFile(":/icons/skin/qbittorrent16.png", QSize(16, 16)); - icon.addFile(":/icons/skin/qbittorrent32.png", QSize(32, 32)); - return icon; -} -#endif - -#if defined(Q_OS_WIN) || defined(Q_OS_MAC) -void MainWindow::checkProgramUpdate() -{ - m_programUpdateTimer->stop(); // If the user had clicked the menu item - m_ui->actionCheckForUpdates->setEnabled(false); - m_ui->actionCheckForUpdates->setText(tr("Checking for Updates...")); - m_ui->actionCheckForUpdates->setToolTip(tr("Already checking for program updates in the background")); - bool invokedByUser = m_ui->actionCheckForUpdates == qobject_cast(sender()); - ProgramUpdater *updater = new ProgramUpdater(this, invokedByUser); - connect(updater, &ProgramUpdater::updateCheckFinished, this, &MainWindow::handleUpdateCheckFinished); - updater->checkForUpdates(); -} - -#endif - -#ifdef Q_OS_WIN -bool MainWindow::addPythonPathToEnv() -{ - if (m_hasPython) return true; - - QString pythonPath = Preferences::getPythonPath(); - if (!pythonPath.isEmpty()) { - Logger::instance()->addMessage(tr("Python found in '%1'").arg(Utils::Fs::toNativePath(pythonPath)), Log::INFO); - // Add it to PATH envvar - QString pathEnvar = QString::fromLocal8Bit(qgetenv("PATH").constData()); - if (pathEnvar.isNull()) - pathEnvar = ""; - pathEnvar = pythonPath + ";" + pathEnvar; - qDebug("New PATH envvar is: %s", qPrintable(pathEnvar)); - qputenv("PATH", Utils::Fs::toNativePath(pathEnvar).toLocal8Bit()); - return true; - } - return false; -} - -void MainWindow::installPython() -{ - setCursor(QCursor(Qt::WaitCursor)); - // Download python - Net::DownloadHandler *handler = nullptr; - if (QSysInfo::windowsVersion() >= QSysInfo::WV_VISTA) - handler = Net::DownloadManager::instance()->downloadUrl("https://www.python.org/ftp/python/3.5.2/python-3.5.2.exe", true); - else - handler = Net::DownloadManager::instance()->downloadUrl("https://www.python.org/ftp/python/3.4.4/python-3.4.4.msi", true); - - using Func = void (Net::DownloadHandler::*)(const QString &, const QString &); - connect(handler, static_cast(&Net::DownloadHandler::downloadFinished), this, &MainWindow::pythonDownloadSuccess); - connect(handler, static_cast(&Net::DownloadHandler::downloadFailed), this, &MainWindow::pythonDownloadFailure); -} - -void MainWindow::pythonDownloadSuccess(const QString &url, const QString &filePath) -{ - Q_UNUSED(url) - setCursor(QCursor(Qt::ArrowCursor)); - QProcess installer; - qDebug("Launching Python installer in passive mode..."); - - if (QSysInfo::windowsVersion() >= QSysInfo::WV_VISTA) { - QFile::rename(filePath, filePath + ".exe"); - installer.start("\"" + Utils::Fs::toNativePath(filePath) + ".exe\" /passive"); - } - else { - QFile::rename(filePath, filePath + ".msi"); - installer.start(Utils::Misc::windowsSystemPath() + "\\msiexec.exe /passive /i \"" + Utils::Fs::toNativePath(filePath) + ".msi\""); - } - - // Wait for setup to complete - installer.waitForFinished(10 * 60 * 1000); - - qDebug("Installer stdout: %s", installer.readAllStandardOutput().data()); - qDebug("Installer stderr: %s", installer.readAllStandardError().data()); - qDebug("Setup should be complete!"); - // Delete temp file - if (QSysInfo::windowsVersion() >= QSysInfo::WV_VISTA) - Utils::Fs::forceRemove(filePath + ".exe"); - else - Utils::Fs::forceRemove(filePath + ".msi"); - // Reload search engine - m_hasPython = addPythonPathToEnv(); - if (m_hasPython) { - // Make it print the version to Log - Utils::Misc::pythonVersion(); - m_ui->actionSearchWidget->setChecked(true); - displaySearchTab(true); - } -} - -void MainWindow::pythonDownloadFailure(const QString &url, const QString &error) -{ - Q_UNUSED(url) - setCursor(QCursor(Qt::ArrowCursor)); - QMessageBox::warning(this, tr("Download error"), tr("Python setup could not be downloaded, reason: %1.\nPlease install it manually.").arg(error)); -} - -#endif diff --git a/src/gui/mainwindow.h b/src/gui/mainwindow.h deleted file mode 100644 index f3e1b2a93..000000000 --- a/src/gui/mainwindow.h +++ /dev/null @@ -1,264 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2006 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 MAINWINDOW_H -#define MAINWINDOW_H - -#include -#include - -#ifndef Q_OS_MAC -#include -#endif - -class QCloseEvent; -class QFileSystemWatcher; -class QShortcut; -class QSplitter; -class QTabWidget; -class QTimer; - -class downloadFromURL; -class SearchWidget; -class RSSWidget; -class about; -class OptionsDialog; -class TransferListWidget; -class TransferListFiltersWidget; -class PropertiesWidget; -class StatusBar; -class TorrentCreatorDlg; -class LineEdit; -class ExecutionLog; -class PowerManagement; -class StatsDialog; - -namespace BitTorrent -{ - class TorrentHandle; -} - -namespace Ui -{ - class MainWindow; -} - -class MainWindow: public QMainWindow -{ - Q_OBJECT - -public: - explicit MainWindow(QWidget *parent = 0); - ~MainWindow() override; - - QWidget *currentTabWidget() const; - TransferListWidget *transferListWidget() const; - PropertiesWidget *propertiesWidget() const; - QMenu *trayIconMenu(); - - // ExecutionLog properties - bool isExecutionLogEnabled() const; - void setExecutionLogEnabled(bool value); - int executionLogMsgTypes() const; - void setExecutionLogMsgTypes(const int value); - - // Notifications properties - bool isNotificationsEnabled() const; - void setNotificationsEnabled(bool value); - bool isTorrentAddedNotificationsEnabled() const; - void setTorrentAddedNotificationsEnabled(bool value); - - // Misc properties - bool isDownloadTrackerFavicon() const; - void setDownloadTrackerFavicon(bool value); - - void activate(); - void cleanup(); - - void showNotificationBaloon(QString title, QString msg) const; - -private slots: - void balloonClicked(); - void writeSettings(); - void readSettings(); - void fullDiskError(BitTorrent::TorrentHandle *const torrent, QString msg) const; - void handleDownloadFromUrlFailure(QString, QString) const; - void tabChanged(int newTab); - void defineUILockPassword(); - void clearUILockPassword(); - bool unlockUI(); - void notifyOfUpdate(QString); - void showConnectionSettings(); - void minimizeWindow(); - // Keyboard shortcuts - void createKeyboardShortcuts(); - void displayTransferTab() const; - void displaySearchTab(); - void displayRSSTab(); - void displayExecutionLogTab(); - void focusSearchFilter(); - void updateGUI(); - void loadPreferences(bool configureSession = true); - void addUnauthenticatedTracker(const QPair &tracker); - void addTorrentFailed(const QString &error) const; - void torrentNew(BitTorrent::TorrentHandle *const torrent) const; - void finishedTorrent(BitTorrent::TorrentHandle *const torrent) const; - void askRecursiveTorrentDownloadConfirmation(BitTorrent::TorrentHandle *const torrent); - void optionsSaved(); -#if defined(Q_OS_WIN) || defined(Q_OS_MAC) - void handleUpdateCheckFinished(bool updateAvailable, QString newVersion, bool invokedByUser); -#endif - void toggleAlternativeSpeeds(); - -#ifdef Q_OS_WIN - void pythonDownloadSuccess(const QString &url, const QString &filePath); - void pythonDownloadFailure(const QString &url, const QString &error); -#endif - void addToolbarContextMenu(); - void manageCookies(); - - void trackerAuthenticationRequired(BitTorrent::TorrentHandle *const torrent); - void downloadFromURLList(const QStringList &urlList); - void updateAltSpeedsBtn(bool alternative); - void updateNbTorrents(); - void handleRSSUnreadCountUpdated(int count); - - void on_actionSearchWidget_triggered(); - void on_actionRSSReader_triggered(); - void on_actionSpeedInTitleBar_triggered(); - void on_actionTopToolBar_triggered(); - void on_actionShowStatusbar_triggered(); - void on_actionDonateMoney_triggered(); - void on_actionExecutionLogs_triggered(bool checked); - void on_actionNormalMessages_triggered(bool checked); - void on_actionInformationMessages_triggered(bool checked); - void on_actionWarningMessages_triggered(bool checked); - void on_actionCriticalMessages_triggered(bool checked); - void on_actionAutoExit_toggled(bool); - void on_actionAutoSuspend_toggled(bool); - void on_actionAutoHibernate_toggled(bool); - void on_actionAutoShutdown_toggled(bool); - void on_actionAbout_triggered(); - void on_actionStatistics_triggered(); - void on_actionCreateTorrent_triggered(); - void on_actionOptions_triggered(); - void on_actionSetGlobalUploadLimit_triggered(); - void on_actionSetGlobalDownloadLimit_triggered(); - void on_actionDocumentation_triggered() const; - void on_actionOpen_triggered(); - void on_actionDownloadFromURL_triggered(); - void on_actionExit_triggered(); - void on_actionLock_triggered(); - // Check for active torrents and set preventing from suspend state - void checkForActiveTorrents(); -#if defined(Q_OS_WIN) || defined(Q_OS_MAC) - void checkProgramUpdate(); -#endif - void toolbarMenuRequested(QPoint); - void toolbarIconsOnly(); - void toolbarTextOnly(); - void toolbarTextBeside(); - void toolbarTextUnder(); - void toolbarFollowSystem(); -#ifndef Q_OS_MAC - void toggleVisibility(const QSystemTrayIcon::ActivationReason reason = QSystemTrayIcon::Trigger); - void createSystrayDelayed(); - void updateTrayIconMenu(); -#endif - -private: -#ifdef Q_OS_MAC - void setupDockClickHandler(); -#else - void createTrayIcon(); - QIcon getSystrayIcon() const; -#endif -#ifdef Q_OS_WIN - bool addPythonPathToEnv(); - void installPython(); -#endif - - void dropEvent(QDropEvent *event) override; - void dragEnterEvent(QDragEnterEvent *event) override; - void closeEvent(QCloseEvent *) override; - void showEvent(QShowEvent *) override; - bool event(QEvent *e) override; - void displayRSSTab(bool enable); - void displaySearchTab(bool enable); - void createTorrentTriggered(const QString &path = QString()); - void showStatusBar(bool show); - - Ui::MainWindow *m_ui; - - QFileSystemWatcher *m_executableWatcher; - // Bittorrent - QList> m_unauthenticatedTrackers; // Still needed? - // GUI related - bool m_posInitialized; - QPointer m_tabs; - QPointer m_statusBar; - QPointer m_options; - QPointer m_aboutDlg; - QPointer m_statsDlg; - QPointer m_createTorrentDlg; - QPointer m_downloadFromURLDialog; -#ifndef Q_OS_MAC - QPointer m_systrayIcon; - QPointer m_systrayCreator; -#endif - QPointer m_trayIconMenu; - TransferListWidget *m_transferListWidget; - TransferListFiltersWidget *m_transferListFiltersWidget; - PropertiesWidget *m_propertiesWidget; - bool m_displaySpeedInTitle; - bool m_forceExit; - bool m_uiLocked; - bool m_unlockDlgShowing; - LineEdit *m_searchFilter; - QAction *m_searchFilterAction; - // Widgets - QAction *m_prioSeparator; - QAction *m_prioSeparatorMenu; - QSplitter *m_splitter; - QPointer m_searchWidget; - QPointer m_rssWidget; - QPointer m_executionLog; - // Power Management - PowerManagement *m_pwr; - QTimer *m_preventTimer; -#if defined(Q_OS_WIN) || defined(Q_OS_MAC) - QTimer *m_programUpdateTimer; - bool m_wasUpdateCheckEnabled; -#endif - bool m_hasPython; - QMenu *m_toolbarMenu; -}; - -#endif // MAINWINDOW_H diff --git a/src/gui/mainwindow.ui b/src/gui/mainwindow.ui deleted file mode 100644 index 85003cb85..000000000 --- a/src/gui/mainwindow.ui +++ /dev/null @@ -1,472 +0,0 @@ - - - MainWindow - - - - 0 - 0 - 914 - 563 - - - - Qt::CustomContextMenu - - - - - 7 - - - 3 - - - 5 - - - 0 - - - - - - - 0 - 0 - 914 - 22 - - - - - &Edit - - - - - - - - - - - - - - - &Help - - - - - - - - - - &Tools - - - - On Downloads &Done - - - - - - - - - - - - - - - - - &File - - - - - - - - - &View - - - - &Log - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - false - - - Qt::Horizontal - - - Qt::ToolButtonFollowStyle - - - false - - - TopToolBarArea - - - false - - - - - - - - - - - - - - - - - - - &Add Torrent File... - - - Open - - - - - E&xit - - - - - &Options... - - - - - &About - - - - - &Resume - - - - - &Pause - - - - - R&esume All - - - - - P&ause All - - - - - &Delete - - - - - Add Torrent &Link... - - - Open URL - - - - - Torrent &Creator - - - - - Set Upload Limit... - - - - - Set Download Limit... - - - - - &Documentation - - - - - Set Global Download Limit... - - - - - Set Global Upload Limit... - - - - - Minimum Priority - - - true - - - - - Top Priority - - - true - - - - - Decrease Priority - - - true - - - - - Increase Priority - - - true - - - - - true - - - Alternative Speed Limits - - - Alternative Speed Limits - - - - - true - - - &Top Toolbar - - - Display Top Toolbar - - - - - true - - - Status &Bar - - - - - true - - - S&peed in Title Bar - - - Show Transfer Speed in Title Bar - - - - - true - - - &RSS Reader - - - - - true - - - Search &Engine - - - - - L&ock qBittorrent - - - Lock - - - Ctrl+L - - - - - Do&nate! - - - If you like qBittorrent, please donate! - - - - - true - - - &Exit qBittorrent - - - - - true - - - &Suspend System - - - - - true - - - &Hibernate System - - - - - true - - - S&hutdown System - - - - - true - - - &Disabled - - - - - Show - - - - - Minimize - - - - - &Statistics - - - - - Check for Updates - - - Check for Program Updates - - - - - Manage Cookies... - - - Manage stored network cookies - - - - - true - - - Show - - - - - true - - - Normal Messages - - - - - true - - - Information Messages - - - - - true - - - Warning Messages - - - - - true - - - Critical Messages - - - - - - diff --git a/src/gui/messageboxraised.cpp b/src/gui/messageboxraised.cpp deleted file mode 100644 index 902697628..000000000 --- a/src/gui/messageboxraised.cpp +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Bittorrent Client using Qt4 and libtorrent. - * Copyright (C) 2014 sledgehammer999 - * - * 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 : hammered999@gmail.com - */ - -#include "messageboxraised.h" - -MessageBoxRaised::MessageBoxRaised(QMessageBox::Icon icon, const QString &title, const QString &text, - QMessageBox::StandardButtons buttons, QWidget *parent, Qt::WindowFlags f) - : QMessageBox(icon, title, text, buttons, parent, f) {} - -QMessageBox::StandardButton MessageBoxRaised::impl(const QMessageBox::Icon &icon, QWidget *parent, const QString &title, const QString &text, QMessageBox::StandardButtons buttons, QMessageBox::StandardButton defaultButton) { - MessageBoxRaised dlg(icon, title, text, buttons, parent); - dlg.setDefaultButton(defaultButton); - return static_cast(dlg.exec()); -} - -QMessageBox::StandardButton MessageBoxRaised::critical(QWidget *parent, const QString &title, const QString &text, QMessageBox::StandardButtons buttons, QMessageBox::StandardButton defaultButton) { - return impl(Critical, parent, title, text, buttons, defaultButton); -} - -QMessageBox::StandardButton MessageBoxRaised::information(QWidget *parent, const QString &title, const QString &text, QMessageBox::StandardButtons buttons, QMessageBox::StandardButton defaultButton) { - return impl(Information, parent, title, text, buttons, defaultButton); -} - -QMessageBox::StandardButton MessageBoxRaised::question(QWidget *parent, const QString &title, const QString &text, QMessageBox::StandardButtons buttons, QMessageBox::StandardButton defaultButton) { - return impl(Question, parent, title, text, buttons, defaultButton); -} - -QMessageBox::StandardButton MessageBoxRaised::warning(QWidget *parent, const QString &title, const QString &text, QMessageBox::StandardButtons buttons, QMessageBox::StandardButton defaultButton) { - return impl(Warning, parent, title, text, buttons, defaultButton); -} - -void MessageBoxRaised::showEvent(QShowEvent *event) { - QMessageBox::showEvent(event); - activateWindow(); - raise(); -} diff --git a/src/gui/messageboxraised.h b/src/gui/messageboxraised.h deleted file mode 100644 index d9be5ffbd..000000000 --- a/src/gui/messageboxraised.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Bittorrent Client using Qt4 and libtorrent. - * Copyright (C) 2014 sledgehammer999 - * - * 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 : hammered999@gmail.com - */ - -#ifndef MESSAGEBOXRAISED_H -#define MESSAGEBOXRAISED_H - -#include - -class MessageBoxRaised : public QMessageBox -{ - Q_OBJECT - -private: - MessageBoxRaised(QMessageBox::Icon icon, const QString &title, const QString &text, QMessageBox::StandardButtons buttons = NoButton, QWidget *parent = 0, Qt::WindowFlags f = Qt::Dialog|Qt::MSWindowsFixedSizeDialogHint); - MessageBoxRaised(); - MessageBoxRaised(MessageBoxRaised const&); - void operator=(MessageBoxRaised const&); - -public: - static QMessageBox::StandardButton critical(QWidget *parent, const QString &title, const QString &text, QMessageBox::StandardButtons buttons = QMessageBox::Ok, QMessageBox::StandardButton defaultButton = QMessageBox::NoButton); - static QMessageBox::StandardButton information(QWidget *parent, const QString &title, const QString &text, QMessageBox::StandardButtons buttons = QMessageBox::Ok, QMessageBox::StandardButton defaultButton = QMessageBox::NoButton); - static QMessageBox::StandardButton question(QWidget *parent, const QString &title, const QString &text, QMessageBox::StandardButtons buttons = QMessageBox::Ok, QMessageBox::StandardButton defaultButton = QMessageBox::NoButton); - static QMessageBox::StandardButton warning(QWidget *parent, const QString &title, const QString &text, QMessageBox::StandardButtons buttons = QMessageBox::Ok, QMessageBox::StandardButton defaultButton = QMessageBox::NoButton); - -protected: - void showEvent(QShowEvent *event); - -private: - static QMessageBox::StandardButton impl(const QMessageBox::Icon &icon, QWidget *parent, const QString &title, const QString &text, QMessageBox::StandardButtons buttons = QMessageBox::Ok, QMessageBox::StandardButton defaultButton = QMessageBox::NoButton); -}; - -#endif // MESSAGEBOXRAISED_H diff --git a/src/gui/optionsdlg.cpp b/src/gui/optionsdlg.cpp deleted file mode 100644 index cd6ba1225..000000000 --- a/src/gui/optionsdlg.cpp +++ /dev/null @@ -1,1721 +0,0 @@ -/* - * Bittorrent Client using Qt4 and libtorrent. - * Copyright (C) 2006 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 "optionsdlg.h" - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifndef QT_NO_OPENSSL -#include -#include -#endif - -#include "app/application.h" -#include "base/bittorrent/session.h" -#include "base/net/dnsupdater.h" -#include "base/net/portforwarder.h" -#include "base/net/proxyconfigurationmanager.h" -#include "base/preferences.h" -#include "base/rss/rss_autodownloader.h" -#include "base/rss/rss_session.h" -#include "base/scanfoldersmodel.h" -#include "base/torrentfileguard.h" -#include "base/unicodestrings.h" -#include "base/utils/fs.h" -#include "base/utils/random.h" -#include "addnewtorrentdialog.h" -#include "advancedsettings.h" -#include "rss/automatedrssdownloader.h" -#include "banlistoptions.h" -#include "guiiconprovider.h" -#include "scanfoldersdelegate.h" - -#include "ui_optionsdlg.h" - -// Constructor -OptionsDialog::OptionsDialog(QWidget *parent) - : QDialog(parent) - , m_refreshingIpFilter(false) - , m_ui(new Ui::OptionsDialog) -{ - qDebug("-> Constructing Options"); - m_ui->setupUi(this); - setAttribute(Qt::WA_DeleteOnClose); - setModal(true); - -#if (defined(Q_OS_UNIX)) - setWindowTitle(tr("Preferences")); -#endif - - // Icons - m_ui->tabSelection->item(TAB_UI)->setIcon(GuiIconProvider::instance()->getIcon("preferences-desktop")); - m_ui->tabSelection->item(TAB_BITTORRENT)->setIcon(GuiIconProvider::instance()->getIcon("preferences-system-network")); - m_ui->tabSelection->item(TAB_CONNECTION)->setIcon(GuiIconProvider::instance()->getIcon("network-wired")); - m_ui->tabSelection->item(TAB_DOWNLOADS)->setIcon(GuiIconProvider::instance()->getIcon("folder-download")); - m_ui->tabSelection->item(TAB_SPEED)->setIcon(GuiIconProvider::instance()->getIcon("speedometer", "chronometer")); - m_ui->tabSelection->item(TAB_RSS)->setIcon(GuiIconProvider::instance()->getIcon("rss-config", "application-rss+xml")); -#ifndef DISABLE_WEBUI - m_ui->tabSelection->item(TAB_WEBUI)->setIcon(GuiIconProvider::instance()->getIcon("network-server")); -#else - m_ui->tabSelection->item(TAB_WEBUI)->setHidden(true); -#endif - m_ui->tabSelection->item(TAB_ADVANCED)->setIcon(GuiIconProvider::instance()->getIcon("preferences-other")); - for (int i = 0; i < m_ui->tabSelection->count(); ++i) { - // uniform size for all icons - m_ui->tabSelection->item(i)->setSizeHint(QSize(std::numeric_limits::max(), 62)); - } - - m_ui->IpFilterRefreshBtn->setIcon(GuiIconProvider::instance()->getIcon("view-refresh")); - - m_ui->deleteTorrentWarningIcon->setPixmap(QApplication::style()->standardIcon(QStyle::SP_MessageBoxCritical).pixmap(16, 16)); - m_ui->deleteTorrentWarningIcon->hide(); - m_ui->deleteTorrentWarningLabel->hide(); - m_ui->deleteTorrentWarningLabel->setToolTip(QLatin1String("

") + - tr("By enabling these options, you can irrevocably lose your .torrent files!") + - QLatin1String("

") + - tr("When these options are enabled, qBittorent will delete .torrent files " - "after they were successfully (the first option) or not (the second option) added to its " - "download queue. This will be applied not only to the files opened via " - "“Add torrent” menu action but to those opened via file type association as well") + - QLatin1String("

") + - tr("If you enable the second option (“Also when addition is cancelled”) the " - ".torrent file will be deleted even if you press “Cancel” in " - "the “Add torrent” dialog") + - QLatin1String("

")); - - m_ui->hsplitter->setCollapsible(0, false); - m_ui->hsplitter->setCollapsible(1, false); - // Get apply button in button box - QList buttons = m_ui->buttonBox->buttons(); - foreach (QAbstractButton *button, buttons) { - if (m_ui->buttonBox->buttonRole(button) == QDialogButtonBox::ApplyRole) { - applyButton = button; - break; - } - } - - m_ui->scanFoldersView->header()->setSectionResizeMode(QHeaderView::ResizeToContents); - m_ui->scanFoldersView->setModel(ScanFoldersModel::instance()); - m_ui->scanFoldersView->setItemDelegate(new ScanFoldersDelegate(this, m_ui->scanFoldersView)); - connect(ScanFoldersModel::instance(), &QAbstractListModel::dataChanged, this, &ThisType::enableApplyButton); - connect(m_ui->scanFoldersView->selectionModel(), &QItemSelectionModel::selectionChanged, this, &ThisType::handleScanFolderViewSelectionChanged); - - connect(m_ui->buttonBox, SIGNAL(clicked(QAbstractButton*)), this, SLOT(applySettings(QAbstractButton*))); - // Languages supported - initializeLanguageCombo(); - - // Load week days (scheduler) - for (uint i = 1; i <= 7; ++i) - m_ui->schedule_days->addItem(QDate::longDayName(i, QDate::StandaloneFormat)); - - // Load options - loadOptions(); -#ifdef Q_OS_MAC - m_ui->checkShowSystray->setVisible(false); -#else - // Disable systray integration if it is not supported by the system - if (!QSystemTrayIcon::isSystemTrayAvailable()) { - m_ui->checkShowSystray->setChecked(false); - m_ui->checkShowSystray->setEnabled(false); - m_ui->label_trayIconStyle->setVisible(false); - m_ui->comboTrayIcon->setVisible(false); - } -#endif - -#if defined(QT_NO_OPENSSL) - m_ui->checkWebUiHttps->setVisible(false); - m_ui->checkSmtpSSL->setVisible(false); -#endif - -#ifndef Q_OS_WIN - m_ui->checkStartup->setVisible(false); -#endif - -#if !(defined(Q_OS_WIN) || defined(Q_OS_MAC)) - m_ui->groupFileAssociation->setVisible(false); -#endif - - // Connect signals / slots - // Shortcuts for frequently used signals that have more than one overload. They would require - // type casts and that is why we declare required member pointer here instead. - void (QComboBox::*qComboBoxCurrentIndexChanged)(int) = &QComboBox::currentIndexChanged; - void (QSpinBox::*qSpinBoxValueChanged)(int) = &QSpinBox::valueChanged; - - connect(m_ui->comboProxyType, qComboBoxCurrentIndexChanged, this, &ThisType::enableProxy); - connect(m_ui->checkRandomPort, &QAbstractButton::toggled, m_ui->spinPort, &ThisType::setDisabled); - - // Apply button is activated when a value is changed - // General tab - connect(m_ui->comboI18n, qComboBoxCurrentIndexChanged, this, &ThisType::enableApplyButton); - connect(m_ui->confirmDeletion, &QAbstractButton::toggled, this, &ThisType::enableApplyButton); - connect(m_ui->checkAltRowColors, &QAbstractButton::toggled, this, &ThisType::enableApplyButton); - connect(m_ui->checkHideZero, &QAbstractButton::toggled, this, &ThisType::enableApplyButton); - connect(m_ui->checkHideZero, &QAbstractButton::toggled, m_ui->comboHideZero, &QWidget::setEnabled); - connect(m_ui->comboHideZero, qComboBoxCurrentIndexChanged, this, &ThisType::enableApplyButton); - connect(m_ui->checkShowSystray, &QGroupBox::toggled, this, &ThisType::enableApplyButton); - connect(m_ui->checkCloseToSystray, &QAbstractButton::toggled, this, &ThisType::enableApplyButton); - connect(m_ui->checkMinimizeToSysTray, &QAbstractButton::toggled, this, &ThisType::enableApplyButton); - connect(m_ui->checkStartMinimized, &QAbstractButton::toggled, this, &ThisType::enableApplyButton); -#ifdef Q_OS_WIN - connect(m_ui->checkStartup, &QAbstractButton::toggled, this, &ThisType::enableApplyButton); -#endif - connect(m_ui->checkShowSplash, &QAbstractButton::toggled, this, &ThisType::enableApplyButton); - connect(m_ui->checkProgramExitConfirm, &QAbstractButton::toggled, this, &ThisType::enableApplyButton); - connect(m_ui->checkProgramAutoExitConfirm, &QAbstractButton::toggled, this, &ThisType::enableApplyButton); - connect(m_ui->checkPreventFromSuspend, &QAbstractButton::toggled, this, &ThisType::enableApplyButton); - connect(m_ui->comboTrayIcon, qComboBoxCurrentIndexChanged, this, &ThisType::enableApplyButton); -#if (defined(Q_OS_UNIX) && !defined(Q_OS_MAC)) && !defined(QT_DBUS_LIB) - m_ui->checkPreventFromSuspend->setDisabled(true); -#endif -#if defined(Q_OS_WIN) || defined(Q_OS_MAC) - connect(m_ui->checkAssociateTorrents, &QAbstractButton::toggled, this, &ThisType::enableApplyButton); - connect(m_ui->checkAssociateMagnetLinks, &QAbstractButton::toggled, this, &ThisType::enableApplyButton); -#endif - connect(m_ui->checkFileLog, &QGroupBox::toggled, this, &ThisType::enableApplyButton); - connect(m_ui->textFileLogPath, &FileSystemPathEdit::selectedPathChanged, this, &ThisType::enableApplyButton); - connect(m_ui->checkFileLogBackup, &QAbstractButton::toggled, this, &ThisType::enableApplyButton); - connect(m_ui->checkFileLogBackup, &QAbstractButton::toggled, m_ui->spinFileLogSize, &QWidget::setEnabled); - connect(m_ui->checkFileLogDelete, &QAbstractButton::toggled, this, &ThisType::enableApplyButton); - connect(m_ui->checkFileLogDelete, &QAbstractButton::toggled, m_ui->spinFileLogAge, &QWidget::setEnabled); - connect(m_ui->checkFileLogDelete, &QAbstractButton::toggled, m_ui->comboFileLogAgeType, &QWidget::setEnabled); - connect(m_ui->spinFileLogSize, qSpinBoxValueChanged, this, &ThisType::enableApplyButton); - connect(m_ui->spinFileLogAge, qSpinBoxValueChanged, this, &ThisType::enableApplyButton); - connect(m_ui->comboFileLogAgeType, qComboBoxCurrentIndexChanged, this, &ThisType::enableApplyButton); - // Downloads tab - connect(m_ui->textSavePath, &FileSystemPathEdit::selectedPathChanged, this, &ThisType::enableApplyButton); - connect(m_ui->checkUseSubcategories, &QAbstractButton::toggled, this, &ThisType::enableApplyButton); - connect(m_ui->comboSavingMode, qComboBoxCurrentIndexChanged, this, &ThisType::enableApplyButton); - connect(m_ui->comboTorrentCategoryChanged, qComboBoxCurrentIndexChanged, this, &ThisType::enableApplyButton); - connect(m_ui->comboCategoryDefaultPathChanged, qComboBoxCurrentIndexChanged, this, &ThisType::enableApplyButton); - connect(m_ui->comboCategoryChanged, qComboBoxCurrentIndexChanged, this, &ThisType::enableApplyButton); - connect(m_ui->textTempPath, &FileSystemPathEdit::selectedPathChanged, this, &ThisType::enableApplyButton); - connect(m_ui->checkAppendqB, &QAbstractButton::toggled, this, &ThisType::enableApplyButton); - connect(m_ui->checkPreallocateAll, &QAbstractButton::toggled, this, &ThisType::enableApplyButton); - connect(m_ui->checkAdditionDialog, &QGroupBox::toggled, this, &ThisType::enableApplyButton); - connect(m_ui->checkAdditionDialogFront, &QAbstractButton::toggled, this, &ThisType::enableApplyButton); - connect(m_ui->checkStartPaused, &QAbstractButton::toggled, this, &ThisType::enableApplyButton); - connect(m_ui->checkCreateSubfolder, &QAbstractButton::toggled, this, &ThisType::enableApplyButton); - connect(m_ui->deleteTorrentBox, &QGroupBox::toggled, this, &ThisType::enableApplyButton); - connect(m_ui->deleteCancelledTorrentBox, &QAbstractButton::toggled, this, &ThisType::enableApplyButton); - connect(m_ui->checkExportDir, &QAbstractButton::toggled, this, &ThisType::enableApplyButton); - connect(m_ui->checkExportDir, &QAbstractButton::toggled, m_ui->textExportDir, &QWidget::setEnabled); - connect(m_ui->checkExportDirFin, &QAbstractButton::toggled, this, &ThisType::enableApplyButton); - connect(m_ui->checkExportDirFin, &QAbstractButton::toggled, m_ui->textExportDirFin, &QWidget::setEnabled); - connect(m_ui->textExportDir, &FileSystemPathEdit::selectedPathChanged, this, &ThisType::enableApplyButton); - connect(m_ui->textExportDirFin, &FileSystemPathEdit::selectedPathChanged, this, &ThisType::enableApplyButton); - connect(m_ui->actionTorrentDlOnDblClBox, qComboBoxCurrentIndexChanged, this, &ThisType::enableApplyButton); - connect(m_ui->actionTorrentFnOnDblClBox, qComboBoxCurrentIndexChanged, this, &ThisType::enableApplyButton); - connect(m_ui->checkTempFolder, &QAbstractButton::toggled, this, &ThisType::enableApplyButton); - connect(m_ui->checkTempFolder, &QAbstractButton::toggled, m_ui->textTempPath, &QWidget::setEnabled); - connect(m_ui->addScanFolderButton, &QAbstractButton::clicked, this, &ThisType::enableApplyButton); - connect(m_ui->removeScanFolderButton, &QAbstractButton::clicked, this, &ThisType::enableApplyButton); - connect(m_ui->groupMailNotification, &QGroupBox::toggled, this, &ThisType::enableApplyButton); - connect(m_ui->dest_email_txt, &QLineEdit::textChanged, this, &ThisType::enableApplyButton); - connect(m_ui->smtp_server_txt, &QLineEdit::textChanged, this, &ThisType::enableApplyButton); - connect(m_ui->checkSmtpSSL, &QAbstractButton::toggled, this, &ThisType::enableApplyButton); - connect(m_ui->groupMailNotifAuth, &QGroupBox::toggled, this, &ThisType::enableApplyButton); - connect(m_ui->mailNotifUsername, &QLineEdit::textChanged, this, &ThisType::enableApplyButton); - connect(m_ui->mailNotifPassword, &QLineEdit::textChanged, this, &ThisType::enableApplyButton); - connect(m_ui->autoRunBox, &QGroupBox::toggled, this, &ThisType::enableApplyButton); - connect(m_ui->autoRun_txt, &FileSystemPathEdit::selectedPathChanged, this, &ThisType::enableApplyButton); - - const QString autoRunStr = QString::fromUtf8("%1\n %2\n %3\n %4\n %5\n %6\n %7\n %8\n %9\n %10\n%11") - .arg(tr("Supported parameters (case sensitive):")) - .arg(tr("%N: Torrent name")) - .arg(tr("%L: Category")) - .arg(tr("%F: Content path (same as root path for multifile torrent)")) - .arg(tr("%R: Root path (first torrent subdirectory path)")) - .arg(tr("%D: Save path")) - .arg(tr("%C: Number of files")) - .arg(tr("%Z: Torrent size (bytes)")) - .arg(tr("%T: Current tracker")) - .arg(tr("%I: Info hash")) - .arg(tr("Tip: Encapsulate parameter with quotation marks to avoid text being cut off at whitespace (e.g., \"%N\")")); - m_ui->autoRun_param->setText(autoRunStr); - - // Connection tab - connect(m_ui->spinPort, qSpinBoxValueChanged, this, &ThisType::enableApplyButton); - connect(m_ui->checkRandomPort, &QAbstractButton::toggled, this, &ThisType::enableApplyButton); - connect(m_ui->checkUPnP, &QAbstractButton::toggled, this, &ThisType::enableApplyButton); - connect(m_ui->checkUploadLimit, &QAbstractButton::toggled, this, &ThisType::enableApplyButton); - connect(m_ui->checkDownloadLimit, &QAbstractButton::toggled, this, &ThisType::enableApplyButton); - connect(m_ui->checkUploadLimitAlt, &QAbstractButton::toggled, this, &ThisType::enableApplyButton); - connect(m_ui->checkDownloadLimitAlt, &QAbstractButton::toggled, this, &ThisType::enableApplyButton); - connect(m_ui->spinUploadLimit, qSpinBoxValueChanged, this, &ThisType::enableApplyButton); - connect(m_ui->spinDownloadLimit, qSpinBoxValueChanged, this, &ThisType::enableApplyButton); - connect(m_ui->spinUploadLimitAlt, qSpinBoxValueChanged, this, &ThisType::enableApplyButton); - connect(m_ui->spinDownloadLimitAlt, qSpinBoxValueChanged, this, &ThisType::enableApplyButton); - connect(m_ui->check_schedule, &QGroupBox::toggled, this, &ThisType::enableApplyButton); - connect(m_ui->schedule_from, &QDateTimeEdit::timeChanged, this, &ThisType::enableApplyButton); - connect(m_ui->schedule_to, &QDateTimeEdit::timeChanged, this, &ThisType::enableApplyButton); - connect(m_ui->schedule_days, qComboBoxCurrentIndexChanged, this, &ThisType::enableApplyButton); - connect(m_ui->checkuTP, &QAbstractButton::toggled, this, &ThisType::enableApplyButton); - connect(m_ui->checkuTP, &QAbstractButton::toggled, m_ui->checkLimituTPConnections, &QWidget::setEnabled); - connect(m_ui->checkLimituTPConnections, &QAbstractButton::toggled, this, &ThisType::enableApplyButton); - connect(m_ui->checkLimitTransportOverhead, &QAbstractButton::toggled, this, &ThisType::enableApplyButton); - connect(m_ui->checkLimitLocalPeerRate, &QAbstractButton::toggled, this, &ThisType::enableApplyButton); - // Bittorrent tab - connect(m_ui->checkMaxConnecs, &QAbstractButton::toggled, this, &ThisType::enableApplyButton); - connect(m_ui->checkMaxConnecsPerTorrent, &QAbstractButton::toggled, this, &ThisType::enableApplyButton); - connect(m_ui->checkMaxUploads, &QAbstractButton::toggled, this, &ThisType::enableApplyButton); - connect(m_ui->checkMaxUploadsPerTorrent, &QAbstractButton::toggled, this, &ThisType::enableApplyButton); - connect(m_ui->spinMaxConnec, qSpinBoxValueChanged, this, &ThisType::enableApplyButton); - connect(m_ui->spinMaxConnecPerTorrent, qSpinBoxValueChanged, this, &ThisType::enableApplyButton); - connect(m_ui->spinMaxUploads, qSpinBoxValueChanged, this, &ThisType::enableApplyButton); - connect(m_ui->spinMaxUploadsPerTorrent, qSpinBoxValueChanged, this, &ThisType::enableApplyButton); - connect(m_ui->checkDHT, &QAbstractButton::toggled, this, &ThisType::enableApplyButton); - connect(m_ui->checkAnonymousMode, &QAbstractButton::toggled, this, &ThisType::enableApplyButton); - connect(m_ui->checkPeX, &QAbstractButton::toggled, this, &ThisType::enableApplyButton); - connect(m_ui->checkLSD, &QAbstractButton::toggled, this, &ThisType::enableApplyButton); - connect(m_ui->comboEncryption, qComboBoxCurrentIndexChanged, this, &ThisType::enableApplyButton); - connect(m_ui->checkMaxRatio, &QAbstractButton::toggled, this, &ThisType::enableApplyButton); - connect(m_ui->checkMaxRatio, &QAbstractButton::toggled, this, &ThisType::toggleComboRatioLimitAct); - connect(m_ui->spinMaxRatio, static_cast(&QDoubleSpinBox::valueChanged), - this, &ThisType::enableApplyButton); - connect(m_ui->comboRatioLimitAct, qComboBoxCurrentIndexChanged, this, &ThisType::enableApplyButton); - connect(m_ui->checkMaxSeedingMinutes, &QAbstractButton::toggled, this, &ThisType::enableApplyButton); - connect(m_ui->checkMaxSeedingMinutes, &QAbstractButton::toggled, this, &ThisType::toggleComboRatioLimitAct); - connect(m_ui->spinMaxSeedingMinutes, static_cast(&QSpinBox::valueChanged), - this, &ThisType::enableApplyButton); - // Proxy tab - connect(m_ui->comboProxyType, qComboBoxCurrentIndexChanged, this, &ThisType::enableApplyButton); - connect(m_ui->textProxyIP, &QLineEdit::textChanged, this, &ThisType::enableApplyButton); - connect(m_ui->spinProxyPort, qSpinBoxValueChanged, this, &ThisType::enableApplyButton); - connect(m_ui->checkProxyPeerConnecs, &QAbstractButton::toggled, this, &ThisType::enableApplyButton); - connect(m_ui->checkForceProxy, &QAbstractButton::toggled, this, &ThisType::enableApplyButton); - connect(m_ui->isProxyOnlyForTorrents, &QAbstractButton::toggled, this, &ThisType::enableApplyButton); - connect(m_ui->checkProxyAuth, &QGroupBox::toggled, this, &ThisType::enableApplyButton); - connect(m_ui->textProxyUsername, &QLineEdit::textChanged, this, &ThisType::enableApplyButton); - connect(m_ui->textProxyPassword, &QLineEdit::textChanged, this, &ThisType::enableApplyButton); - // Misc tab - connect(m_ui->checkIPFilter, &QAbstractButton::toggled, this, &ThisType::enableApplyButton); - connect(m_ui->checkIPFilter, &QAbstractButton::toggled, m_ui->textFilterPath, &QWidget::setEnabled); - connect(m_ui->checkIPFilter, &QAbstractButton::toggled, m_ui->IpFilterRefreshBtn, &QWidget::setEnabled); - connect(m_ui->checkIpFilterTrackers, &QAbstractButton::toggled, this, &ThisType::enableApplyButton); - connect(m_ui->textFilterPath, &FileSystemPathEdit::selectedPathChanged, this, &ThisType::enableApplyButton); - connect(m_ui->checkEnableQueueing, &QGroupBox::toggled, this, &ThisType::enableApplyButton); - connect(m_ui->spinMaxActiveDownloads, qSpinBoxValueChanged, this, &ThisType::enableApplyButton); - connect(m_ui->spinMaxActiveUploads, qSpinBoxValueChanged, this, &ThisType::enableApplyButton); - connect(m_ui->spinMaxActiveTorrents, qSpinBoxValueChanged, this, &ThisType::enableApplyButton); - connect(m_ui->checkIgnoreSlowTorrentsForQueueing, &QAbstractButton::toggled, this, &ThisType::enableApplyButton); - connect(m_ui->checkEnableAddTrackers, &QGroupBox::toggled, this, &ThisType::enableApplyButton); - connect(m_ui->textTrackers, &QPlainTextEdit::textChanged, this, &ThisType::enableApplyButton); -#ifndef DISABLE_WEBUI - // Web UI tab - connect(m_ui->textServerDomains, &QLineEdit::textChanged, this, &ThisType::enableApplyButton); - connect(m_ui->checkWebUi, &QGroupBox::toggled, this, &ThisType::enableApplyButton); - connect(m_ui->spinWebUiPort, qSpinBoxValueChanged, this, &ThisType::enableApplyButton); - connect(m_ui->checkWebUIUPnP, &QAbstractButton::toggled, this, &ThisType::enableApplyButton); - connect(m_ui->checkWebUiHttps, &QGroupBox::toggled, this, &ThisType::enableApplyButton); - connect(m_ui->btnWebUiKey, &QAbstractButton::clicked, this, &ThisType::enableApplyButton); - connect(m_ui->btnWebUiCrt, &QAbstractButton::clicked, this, &ThisType::enableApplyButton); - connect(m_ui->textWebUiUsername, &QLineEdit::textChanged, this, &ThisType::enableApplyButton); - connect(m_ui->textWebUiPassword, &QLineEdit::textChanged, this, &ThisType::enableApplyButton); - connect(m_ui->checkBypassLocalAuth, &QAbstractButton::toggled, this, &ThisType::enableApplyButton); - connect(m_ui->checkDynDNS, &QGroupBox::toggled, this, &ThisType::enableApplyButton); - connect(m_ui->comboDNSService, qComboBoxCurrentIndexChanged, this, &ThisType::enableApplyButton); - connect(m_ui->domainNameTxt, &QLineEdit::textChanged, this, &ThisType::enableApplyButton); - connect(m_ui->DNSUsernameTxt, &QLineEdit::textChanged, this, &ThisType::enableApplyButton); - connect(m_ui->DNSPasswordTxt, &QLineEdit::textChanged, this, &ThisType::enableApplyButton); -#endif - - // RSS tab - connect(m_ui->checkRSSEnable, &QCheckBox::toggled, this, &OptionsDialog::enableApplyButton); - connect(m_ui->checkRSSAutoDownloaderEnable, &QCheckBox::toggled, this, &OptionsDialog::enableApplyButton); - connect(m_ui->spinRSSRefreshInterval, qSpinBoxValueChanged, this, &OptionsDialog::enableApplyButton); - connect(m_ui->spinRSSMaxArticlesPerFeed, qSpinBoxValueChanged, this, &OptionsDialog::enableApplyButton); - connect(m_ui->btnEditRules, &QPushButton::clicked, [this]() { AutomatedRssDownloader(this).exec(); }); - - // Disable apply Button - applyButton->setEnabled(false); - // Tab selection mechanism - connect(m_ui->tabSelection, &QListWidget::currentItemChanged, this, &ThisType::changePage); - // Load Advanced settings - advancedSettings = new AdvancedSettings(m_ui->tabAdvancedPage); - m_ui->advPageLayout->addWidget(advancedSettings); - connect(advancedSettings, &AdvancedSettings::settingsChanged, this, &ThisType::enableApplyButton); - - m_ui->textFileLogPath->setDialogCaption(tr("Choose a save directory")); - m_ui->textFileLogPath->setMode(FileSystemPathEdit::Mode::DirectorySave); - - m_ui->textExportDir->setDialogCaption(tr("Choose export directory")); - m_ui->textExportDir->setMode(FileSystemPathEdit::Mode::DirectorySave); - - m_ui->textExportDirFin->setDialogCaption(tr("Choose export directory")); - m_ui->textExportDirFin->setMode(FileSystemPathEdit::Mode::DirectorySave); - - m_ui->textFilterPath->setDialogCaption(tr("Choose an IP filter file")); - m_ui->textFilterPath->setFileNameFilter(tr("All supported filters") - + QLatin1String(" (*.dat *.p2p *.p2b);;.dat (*.dat);;.p2p (*.p2p);;.p2b (*.p2b)")); - - m_ui->textSavePath->setDialogCaption(tr("Choose a save directory")); - m_ui->textSavePath->setMode(FileSystemPathEdit::Mode::DirectorySave); - - m_ui->textTempPath->setDialogCaption(tr("Choose a save directory")); - m_ui->textTempPath->setMode(FileSystemPathEdit::Mode::DirectorySave); - - show(); - loadWindowState(); -} - -void OptionsDialog::initializeLanguageCombo() -{ - // List language files - const QDir langDir(":/lang"); - const QStringList langFiles = langDir.entryList(QStringList("qbittorrent_*.qm"), QDir::Files); - foreach (const QString langFile, langFiles) { - QString localeStr = langFile.mid(12); // remove "qbittorrent_" - localeStr.chop(3); // Remove ".qm" - QString languageName; - if (localeStr.startsWith("eo", Qt::CaseInsensitive)) { - // QLocale doesn't work with that locale. Esperanto isn't a "real" language. - languageName = QString::fromUtf8(C_LOCALE_ESPERANTO); - } - else { - QLocale locale(localeStr); - languageName = languageToLocalizedString(locale); - } - m_ui->comboI18n->addItem(/*QIcon(":/icons/flags/"+country+".png"), */ languageName, localeStr); - qDebug() << "Supported locale:" << localeStr; - } -} - -// Main destructor -OptionsDialog::~OptionsDialog() -{ - qDebug("-> destructing Options"); - foreach (const QString &path, addedScanDirs) - ScanFoldersModel::instance()->removePath(path); - ScanFoldersModel::instance()->configure(); // reloads "removed" paths - delete m_ui; -} - -void OptionsDialog::changePage(QListWidgetItem *current, QListWidgetItem *previous) -{ - if (!current) - current = previous; - m_ui->tabOption->setCurrentIndex(m_ui->tabSelection->row(current)); -} - -void OptionsDialog::loadWindowState() -{ - const Preferences* const pref = Preferences::instance(); - - resize(pref->getPrefSize(this->size())); - const QStringList sizes_str = pref->getPrefHSplitterSizes(); - QList sizes; - if (sizes_str.size() == 2) { - sizes << sizes_str.first().toInt(); - sizes << sizes_str.last().toInt(); - } - else { - sizes << 116; - sizes << m_ui->hsplitter->width() - 116; - } - m_ui->hsplitter->setSizes(sizes); -} - -void OptionsDialog::saveWindowState() const -{ - Preferences* const pref = Preferences::instance(); - - // window size - pref->setPrefSize(size()); - - // Splitter size - QStringList sizes_str; - sizes_str << QString::number(m_ui->hsplitter->sizes().first()); - sizes_str << QString::number(m_ui->hsplitter->sizes().last()); - pref->setPrefHSplitterSizes(sizes_str); -} - -void OptionsDialog::saveOptions() -{ - applyButton->setEnabled(false); - Preferences* const pref = Preferences::instance(); - // Load the translation - QString locale = getLocale(); - if (pref->getLocale() != locale) { - QTranslator *translator = new QTranslator; - if (translator->load(QString::fromUtf8(":/lang/qbittorrent_") + locale)) - qDebug("%s locale recognized, using translation.", qPrintable(locale)); - else - qDebug("%s locale unrecognized, using default (en).", qPrintable(locale)); - qApp->installTranslator(translator); - } - - // General preferences - pref->setLocale(locale); - pref->setConfirmTorrentDeletion(m_ui->confirmDeletion->isChecked()); - pref->setAlternatingRowColors(m_ui->checkAltRowColors->isChecked()); - pref->setHideZeroValues(m_ui->checkHideZero->isChecked()); - pref->setHideZeroComboValues(m_ui->comboHideZero->currentIndex()); -#ifndef Q_OS_MAC - pref->setSystrayIntegration(systrayIntegration()); - pref->setTrayIconStyle(TrayIcon::Style(m_ui->comboTrayIcon->currentIndex())); - pref->setCloseToTray(closeToTray()); - pref->setMinimizeToTray(minimizeToTray()); - pref->setStartMinimized(startMinimized()); -#endif - pref->setSplashScreenDisabled(isSlashScreenDisabled()); - pref->setConfirmOnExit(m_ui->checkProgramExitConfirm->isChecked()); - pref->setDontConfirmAutoExit(!m_ui->checkProgramAutoExitConfirm->isChecked()); - pref->setPreventFromSuspend(preventFromSuspend()); -#ifdef Q_OS_WIN - pref->setWinStartup(WinStartup()); - // Windows: file association settings - Preferences::setTorrentFileAssoc(m_ui->checkAssociateTorrents->isChecked()); - Preferences::setMagnetLinkAssoc(m_ui->checkAssociateMagnetLinks->isChecked()); -#endif -#ifdef Q_OS_MAC - if (m_ui->checkAssociateTorrents->isChecked()) { - Preferences::setTorrentFileAssoc(); - m_ui->checkAssociateTorrents->setChecked(Preferences::isTorrentFileAssocSet()); - m_ui->checkAssociateTorrents->setEnabled(!m_ui->checkAssociateTorrents->isChecked()); - } - if (m_ui->checkAssociateMagnetLinks->isChecked()) { - Preferences::setMagnetLinkAssoc(); - m_ui->checkAssociateMagnetLinks->setChecked(Preferences::isMagnetLinkAssocSet()); - m_ui->checkAssociateMagnetLinks->setEnabled(!m_ui->checkAssociateMagnetLinks->isChecked()); - } -#endif - Application * const app = static_cast(QCoreApplication::instance()); - app->setFileLoggerPath(m_ui->textFileLogPath->selectedPath()); - app->setFileLoggerBackup(m_ui->checkFileLogBackup->isChecked()); - app->setFileLoggerMaxSize(m_ui->spinFileLogSize->value()); - app->setFileLoggerAge(m_ui->spinFileLogAge->value()); - app->setFileLoggerAgeType(m_ui->comboFileLogAgeType->currentIndex()); - app->setFileLoggerDeleteOld(m_ui->checkFileLogDelete->isChecked()); - app->setFileLoggerEnabled(m_ui->checkFileLog->isChecked()); - // End General preferences - - RSS::Session::instance()->setRefreshInterval(m_ui->spinRSSRefreshInterval->value()); - RSS::Session::instance()->setMaxArticlesPerFeed(m_ui->spinRSSMaxArticlesPerFeed->value()); - RSS::Session::instance()->setProcessingEnabled(m_ui->checkRSSEnable->isChecked()); - RSS::AutoDownloader::instance()->setProcessingEnabled(m_ui->checkRSSAutoDownloaderEnable->isChecked()); - - auto session = BitTorrent::Session::instance(); - - // Downloads preferences - session->setDefaultSavePath(Utils::Fs::expandPathAbs(m_ui->textSavePath->selectedPath())); - session->setSubcategoriesEnabled(m_ui->checkUseSubcategories->isChecked()); - session->setAutoTMMDisabledByDefault(m_ui->comboSavingMode->currentIndex() == 0); - session->setDisableAutoTMMWhenCategoryChanged(m_ui->comboTorrentCategoryChanged->currentIndex() == 1); - session->setDisableAutoTMMWhenCategorySavePathChanged(m_ui->comboCategoryChanged->currentIndex() == 1); - session->setDisableAutoTMMWhenDefaultSavePathChanged(m_ui->comboCategoryDefaultPathChanged->currentIndex() == 1); - session->setTempPathEnabled(m_ui->checkTempFolder->isChecked()); - session->setTempPath(Utils::Fs::expandPathAbs(m_ui->textTempPath->selectedPath())); - session->setAppendExtensionEnabled(m_ui->checkAppendqB->isChecked()); - session->setPreallocationEnabled(preAllocateAllFiles()); - AddNewTorrentDialog::setEnabled(useAdditionDialog()); - AddNewTorrentDialog::setTopLevel(m_ui->checkAdditionDialogFront->isChecked()); - session->setAddTorrentPaused(addTorrentsInPause()); - session->setCreateTorrentSubfolder(m_ui->checkCreateSubfolder->isChecked()); - ScanFoldersModel::instance()->removeFromFSWatcher(removedScanDirs); - ScanFoldersModel::instance()->addToFSWatcher(addedScanDirs); - ScanFoldersModel::instance()->makePersistent(); - removedScanDirs.clear(); - addedScanDirs.clear(); - session->setTorrentExportDirectory(getTorrentExportDir()); - session->setFinishedTorrentExportDirectory(getFinishedTorrentExportDir()); - pref->setMailNotificationEnabled(m_ui->groupMailNotification->isChecked()); - pref->setMailNotificationEmail(m_ui->dest_email_txt->text()); - pref->setMailNotificationSMTP(m_ui->smtp_server_txt->text()); - pref->setMailNotificationSMTPSSL(m_ui->checkSmtpSSL->isChecked()); - pref->setMailNotificationSMTPAuth(m_ui->groupMailNotifAuth->isChecked()); - pref->setMailNotificationSMTPUsername(m_ui->mailNotifUsername->text()); - pref->setMailNotificationSMTPPassword(m_ui->mailNotifPassword->text()); - pref->setAutoRunEnabled(m_ui->autoRunBox->isChecked()); - pref->setAutoRunProgram(m_ui->autoRun_txt->selectedPath().trimmed()); - pref->setActionOnDblClOnTorrentDl(getActionOnDblClOnTorrentDl()); - pref->setActionOnDblClOnTorrentFn(getActionOnDblClOnTorrentFn()); - TorrentFileGuard::setAutoDeleteMode(!m_ui->deleteTorrentBox->isChecked() ? TorrentFileGuard::Never - : !m_ui->deleteCancelledTorrentBox->isChecked() ? TorrentFileGuard::IfAdded - : TorrentFileGuard::Always); - // End Downloads preferences - - // Connection preferences - session->setPort(getPort()); - session->setUseRandomPort(m_ui->checkRandomPort->isChecked()); - Net::PortForwarder::instance()->setEnabled(isUPnPEnabled()); - const QPair down_up_limit = getGlobalBandwidthLimits(); - session->setGlobalDownloadSpeedLimit(down_up_limit.first); - session->setGlobalUploadSpeedLimit(down_up_limit.second); - session->setUTPEnabled(m_ui->checkuTP->isChecked()); - session->setUTPRateLimited(m_ui->checkLimituTPConnections->isChecked()); - session->setIncludeOverheadInLimits(m_ui->checkLimitTransportOverhead->isChecked()); - session->setIgnoreLimitsOnLAN(!m_ui->checkLimitLocalPeerRate->isChecked()); - const QPair alt_down_up_limit = getAltGlobalBandwidthLimits(); - session->setAltGlobalDownloadSpeedLimit(alt_down_up_limit.first); - session->setAltGlobalUploadSpeedLimit(alt_down_up_limit.second); - session->setBandwidthSchedulerEnabled(m_ui->check_schedule->isChecked()); - pref->setSchedulerStartTime(m_ui->schedule_from->time()); - pref->setSchedulerEndTime(m_ui->schedule_to->time()); - pref->setSchedulerDays(static_cast(m_ui->schedule_days->currentIndex())); - - auto proxyConfigManager = Net::ProxyConfigurationManager::instance(); - Net::ProxyConfiguration proxyConf; - proxyConf.type = getProxyType(); - proxyConf.ip = getProxyIp(); - proxyConf.port = getProxyPort(); - proxyConf.username = getProxyUsername(); - proxyConf.password = getProxyPassword(); - proxyConfigManager->setProxyOnlyForTorrents(m_ui->isProxyOnlyForTorrents->isChecked()); - proxyConfigManager->setProxyConfiguration(proxyConf); - - session->setProxyPeerConnectionsEnabled(m_ui->checkProxyPeerConnecs->isChecked()); - session->setForceProxyEnabled(m_ui->checkForceProxy->isChecked()); - // End Connection preferences - - // Bittorrent preferences - session->setMaxConnections(getMaxConnecs()); - session->setMaxConnectionsPerTorrent(getMaxConnecsPerTorrent()); - session->setMaxUploads(getMaxUploads()); - session->setMaxUploadsPerTorrent(getMaxUploadsPerTorrent()); - session->setDHTEnabled(isDHTEnabled()); - session->setPeXEnabled(m_ui->checkPeX->isChecked()); - session->setLSDEnabled(isLSDEnabled()); - session->setEncryption(getEncryptionSetting()); - session->setAnonymousModeEnabled(m_ui->checkAnonymousMode->isChecked()); - session->setAddTrackersEnabled(m_ui->checkEnableAddTrackers->isChecked()); - session->setAdditionalTrackers(m_ui->textTrackers->toPlainText()); - session->setGlobalMaxRatio(getMaxRatio()); - session->setGlobalMaxSeedingMinutes(getMaxSeedingMinutes()); - session->setMaxRatioAction(static_cast(m_ui->comboRatioLimitAct->currentIndex())); - // End Bittorrent preferences - - // Misc preferences - // * IPFilter - session->setIPFilteringEnabled(isIPFilteringEnabled()); - session->setTrackerFilteringEnabled(m_ui->checkIpFilterTrackers->isChecked()); - session->setIPFilterFile(m_ui->textFilterPath->selectedPath()); - // End IPFilter preferences - // Queueing system - session->setQueueingSystemEnabled(isQueueingSystemEnabled()); - session->setMaxActiveDownloads(m_ui->spinMaxActiveDownloads->value()); - session->setMaxActiveUploads(m_ui->spinMaxActiveUploads->value()); - session->setMaxActiveTorrents(m_ui->spinMaxActiveTorrents->value()); - session->setIgnoreSlowTorrentsForQueueing(m_ui->checkIgnoreSlowTorrentsForQueueing->isChecked()); - // End Queueing system preferences - // Web UI - pref->setWebUiEnabled(isWebUiEnabled()); - if (isWebUiEnabled()) { - pref->setServerDomains(m_ui->textServerDomains->text()); - pref->setWebUiPort(webUiPort()); - pref->setUPnPForWebUIPort(m_ui->checkWebUIUPnP->isChecked()); - pref->setWebUiHttpsEnabled(m_ui->checkWebUiHttps->isChecked()); - if (m_ui->checkWebUiHttps->isChecked()) { - pref->setWebUiHttpsCertificate(m_sslCert); - pref->setWebUiHttpsKey(m_sslKey); - } - pref->setWebUiUsername(webUiUsername()); - pref->setWebUiPassword(webUiPassword()); - pref->setWebUiLocalAuthEnabled(!m_ui->checkBypassLocalAuth->isChecked()); - // DynDNS - pref->setDynDNSEnabled(m_ui->checkDynDNS->isChecked()); - pref->setDynDNSService(m_ui->comboDNSService->currentIndex()); - pref->setDynDomainName(m_ui->domainNameTxt->text()); - pref->setDynDNSUsername(m_ui->DNSUsernameTxt->text()); - pref->setDynDNSPassword(m_ui->DNSPasswordTxt->text()); - } - // End Web UI - // End preferences - // Save advanced settings - advancedSettings->saveAdvancedSettings(); - // Assume that user changed multiple settings - // so it's best to save immediately - pref->apply(); -} - -bool OptionsDialog::isIPFilteringEnabled() const -{ - return m_ui->checkIPFilter->isChecked(); -} - -Net::ProxyType OptionsDialog::getProxyType() const -{ - switch (m_ui->comboProxyType->currentIndex()) { - case 1: - return Net::ProxyType::SOCKS4; - break; - case 2: - if (isProxyAuthEnabled()) - return Net::ProxyType::SOCKS5_PW; - return Net::ProxyType::SOCKS5; - case 3: - if (isProxyAuthEnabled()) - return Net::ProxyType::HTTP_PW; - return Net::ProxyType::HTTP; - default: - return Net::ProxyType::None; - } -} - -void OptionsDialog::loadOptions() -{ - int intValue; - QString strValue; - bool fileLogBackup = true; - bool fileLogDelete = true; - const Preferences* const pref = Preferences::instance(); - - // General preferences - setLocale(pref->getLocale()); - m_ui->confirmDeletion->setChecked(pref->confirmTorrentDeletion()); - m_ui->checkAltRowColors->setChecked(pref->useAlternatingRowColors()); - m_ui->checkHideZero->setChecked(pref->getHideZeroValues()); - m_ui->comboHideZero->setEnabled(m_ui->checkHideZero->isChecked()); - m_ui->comboHideZero->setCurrentIndex(pref->getHideZeroComboValues()); - - m_ui->checkShowSplash->setChecked(!pref->isSplashScreenDisabled()); - m_ui->checkStartMinimized->setChecked(pref->startMinimized()); - m_ui->checkProgramExitConfirm->setChecked(pref->confirmOnExit()); - m_ui->checkProgramAutoExitConfirm->setChecked(!pref->dontConfirmAutoExit()); - -#ifndef Q_OS_MAC - m_ui->checkShowSystray->setChecked(pref->systrayIntegration()); - if (m_ui->checkShowSystray->isChecked()) { - m_ui->checkMinimizeToSysTray->setChecked(pref->minimizeToTray()); - m_ui->checkCloseToSystray->setChecked(pref->closeToTray()); - m_ui->comboTrayIcon->setCurrentIndex(pref->trayIconStyle()); - } -#endif - - m_ui->checkPreventFromSuspend->setChecked(pref->preventFromSuspend()); - -#ifdef Q_OS_WIN - m_ui->checkStartup->setChecked(pref->WinStartup()); - m_ui->checkAssociateTorrents->setChecked(Preferences::isTorrentFileAssocSet()); - m_ui->checkAssociateMagnetLinks->setChecked(Preferences::isMagnetLinkAssocSet()); -#endif -#ifdef Q_OS_MAC - m_ui->checkAssociateTorrents->setChecked(Preferences::isTorrentFileAssocSet()); - m_ui->checkAssociateTorrents->setEnabled(!m_ui->checkAssociateTorrents->isChecked()); - m_ui->checkAssociateMagnetLinks->setChecked(Preferences::isMagnetLinkAssocSet()); - m_ui->checkAssociateMagnetLinks->setEnabled(!m_ui->checkAssociateMagnetLinks->isChecked()); -#endif - - const Application * const app = static_cast(QCoreApplication::instance()); - m_ui->checkFileLog->setChecked(app->isFileLoggerEnabled()); - m_ui->textFileLogPath->setSelectedPath(app->fileLoggerPath()); - fileLogBackup = app->isFileLoggerBackup(); - m_ui->checkFileLogBackup->setChecked(fileLogBackup); - m_ui->spinFileLogSize->setEnabled(fileLogBackup); - fileLogDelete = app->isFileLoggerDeleteOld(); - m_ui->checkFileLogDelete->setChecked(fileLogDelete); - m_ui->spinFileLogAge->setEnabled(fileLogDelete); - m_ui->comboFileLogAgeType->setEnabled(fileLogDelete); - m_ui->spinFileLogSize->setValue(app->fileLoggerMaxSize()); - m_ui->spinFileLogAge->setValue(app->fileLoggerAge()); - m_ui->comboFileLogAgeType->setCurrentIndex(app->fileLoggerAgeType()); - // End General preferences - - m_ui->checkRSSEnable->setChecked(RSS::Session::instance()->isProcessingEnabled()); - m_ui->checkRSSAutoDownloaderEnable->setChecked(RSS::AutoDownloader::instance()->isProcessingEnabled()); - m_ui->spinRSSRefreshInterval->setValue(RSS::Session::instance()->refreshInterval()); - m_ui->spinRSSMaxArticlesPerFeed->setValue(RSS::Session::instance()->maxArticlesPerFeed()); - - auto session = BitTorrent::Session::instance(); - - // Downloads preferences - m_ui->checkAdditionDialog->setChecked(AddNewTorrentDialog::isEnabled()); - m_ui->checkAdditionDialogFront->setChecked(AddNewTorrentDialog::isTopLevel()); - m_ui->checkStartPaused->setChecked(session->isAddTorrentPaused()); - m_ui->checkCreateSubfolder->setChecked(session->isCreateTorrentSubfolder()); - const TorrentFileGuard::AutoDeleteMode autoDeleteMode = TorrentFileGuard::autoDeleteMode(); - m_ui->deleteTorrentBox->setChecked(autoDeleteMode != TorrentFileGuard::Never); - m_ui->deleteCancelledTorrentBox->setChecked(autoDeleteMode == TorrentFileGuard::Always); - - m_ui->textSavePath->setSelectedPath(session->defaultSavePath()); - m_ui->checkUseSubcategories->setChecked(session->isSubcategoriesEnabled()); - m_ui->comboSavingMode->setCurrentIndex(!session->isAutoTMMDisabledByDefault()); - m_ui->comboTorrentCategoryChanged->setCurrentIndex(session->isDisableAutoTMMWhenCategoryChanged()); - m_ui->comboCategoryChanged->setCurrentIndex(session->isDisableAutoTMMWhenCategorySavePathChanged()); - m_ui->comboCategoryDefaultPathChanged->setCurrentIndex(session->isDisableAutoTMMWhenDefaultSavePathChanged()); - m_ui->checkTempFolder->setChecked(session->isTempPathEnabled()); - m_ui->textTempPath->setEnabled(m_ui->checkTempFolder->isChecked()); - m_ui->textTempPath->setEnabled(m_ui->checkTempFolder->isChecked()); - m_ui->textTempPath->setSelectedPath(Utils::Fs::toNativePath(session->tempPath())); - m_ui->checkAppendqB->setChecked(session->isAppendExtensionEnabled()); - m_ui->checkPreallocateAll->setChecked(session->isPreallocationEnabled()); - - strValue = session->torrentExportDirectory(); - if (strValue.isEmpty()) { - // Disable - m_ui->checkExportDir->setChecked(false); - m_ui->textExportDir->setEnabled(false); - } - else { - // Enable - m_ui->checkExportDir->setChecked(true); - m_ui->textExportDir->setEnabled(true); - m_ui->textExportDir->setSelectedPath(strValue); - } - - strValue = session->finishedTorrentExportDirectory(); - if (strValue.isEmpty()) { - // Disable - m_ui->checkExportDirFin->setChecked(false); - m_ui->textExportDirFin->setEnabled(false); - } - else { - // Enable - m_ui->checkExportDirFin->setChecked(true); - m_ui->textExportDirFin->setEnabled(true); - m_ui->textExportDirFin->setSelectedPath(strValue); - } - - m_ui->groupMailNotification->setChecked(pref->isMailNotificationEnabled()); - m_ui->dest_email_txt->setText(pref->getMailNotificationEmail()); - m_ui->smtp_server_txt->setText(pref->getMailNotificationSMTP()); - m_ui->checkSmtpSSL->setChecked(pref->getMailNotificationSMTPSSL()); - m_ui->groupMailNotifAuth->setChecked(pref->getMailNotificationSMTPAuth()); - m_ui->mailNotifUsername->setText(pref->getMailNotificationSMTPUsername()); - m_ui->mailNotifPassword->setText(pref->getMailNotificationSMTPPassword()); - - m_ui->autoRunBox->setChecked(pref->isAutoRunEnabled()); - m_ui->autoRun_txt->setSelectedPath(pref->getAutoRunProgram()); - intValue = pref->getActionOnDblClOnTorrentDl(); - if (intValue >= m_ui->actionTorrentDlOnDblClBox->count()) - intValue = 0; - m_ui->actionTorrentDlOnDblClBox->setCurrentIndex(intValue); - intValue = pref->getActionOnDblClOnTorrentFn(); - if (intValue >= m_ui->actionTorrentFnOnDblClBox->count()) - intValue = 1; - m_ui->actionTorrentFnOnDblClBox->setCurrentIndex(intValue); - // End Downloads preferences - - // Connection preferences - m_ui->checkUPnP->setChecked(Net::PortForwarder::instance()->isEnabled()); - m_ui->checkRandomPort->setChecked(session->useRandomPort()); - m_ui->spinPort->setValue(session->port()); - m_ui->spinPort->setDisabled(m_ui->checkRandomPort->isChecked()); - - intValue = session->maxConnections(); - if (intValue > 0) { - // enable - m_ui->checkMaxConnecs->setChecked(true); - m_ui->spinMaxConnec->setEnabled(true); - m_ui->spinMaxConnec->setValue(intValue); - } - else { - // disable - m_ui->checkMaxConnecs->setChecked(false); - m_ui->spinMaxConnec->setEnabled(false); - } - intValue = session->maxConnectionsPerTorrent(); - if (intValue > 0) { - // enable - m_ui->checkMaxConnecsPerTorrent->setChecked(true); - m_ui->spinMaxConnecPerTorrent->setEnabled(true); - m_ui->spinMaxConnecPerTorrent->setValue(intValue); - } - else { - // disable - m_ui->checkMaxConnecsPerTorrent->setChecked(false); - m_ui->spinMaxConnecPerTorrent->setEnabled(false); - } - intValue = session->maxUploads(); - if (intValue > 0) { - // enable - m_ui->checkMaxUploads->setChecked(true); - m_ui->spinMaxUploads->setEnabled(true); - m_ui->spinMaxUploads->setValue(intValue); - } - else { - // disable - m_ui->checkMaxUploads->setChecked(false); - m_ui->spinMaxUploads->setEnabled(false); - } - intValue = session->maxUploadsPerTorrent(); - if (intValue > 0) { - // enable - m_ui->checkMaxUploadsPerTorrent->setChecked(true); - m_ui->spinMaxUploadsPerTorrent->setEnabled(true); - m_ui->spinMaxUploadsPerTorrent->setValue(intValue); - } - else { - // disable - m_ui->checkMaxUploadsPerTorrent->setChecked(false); - m_ui->spinMaxUploadsPerTorrent->setEnabled(false); - } - - auto proxyConfigManager = Net::ProxyConfigurationManager::instance(); - Net::ProxyConfiguration proxyConf = proxyConfigManager->proxyConfiguration(); - using Net::ProxyType; - bool useProxyAuth = false; - switch (proxyConf.type) { - case ProxyType::SOCKS4: - m_ui->comboProxyType->setCurrentIndex(1); - break; - - case ProxyType::SOCKS5_PW: - useProxyAuth = true; - // fallthrough - case ProxyType::SOCKS5: - m_ui->comboProxyType->setCurrentIndex(2); - break; - - case ProxyType::HTTP_PW: - useProxyAuth = true; - // fallthrough - case ProxyType::HTTP: - m_ui->comboProxyType->setCurrentIndex(3); - break; - - default: - m_ui->comboProxyType->setCurrentIndex(0); - } - m_ui->textProxyIP->setText(proxyConf.ip); - m_ui->spinProxyPort->setValue(proxyConf.port); - m_ui->checkProxyAuth->setChecked(useProxyAuth); - m_ui->textProxyUsername->setText(proxyConf.username); - m_ui->textProxyPassword->setText(proxyConf.password); - - m_ui->checkProxyPeerConnecs->setChecked(session->isProxyPeerConnectionsEnabled()); - m_ui->checkForceProxy->setChecked(session->isForceProxyEnabled()); - m_ui->isProxyOnlyForTorrents->setChecked(proxyConfigManager->isProxyOnlyForTorrents()); - enableProxy(m_ui->comboProxyType->currentIndex()); - - m_ui->checkIPFilter->setChecked(session->isIPFilteringEnabled()); - m_ui->textFilterPath->setEnabled(m_ui->checkIPFilter->isChecked()); - m_ui->textFilterPath->setSelectedPath(session->IPFilterFile()); - m_ui->IpFilterRefreshBtn->setEnabled(m_ui->checkIPFilter->isChecked()); - m_ui->checkIpFilterTrackers->setChecked(session->isTrackerFilteringEnabled()); - // End Connection preferences - - // Speed preferences - intValue = session->globalDownloadSpeedLimit() / 1024; - if (intValue > 0) { - // Enabled - m_ui->checkDownloadLimit->setChecked(true); - m_ui->spinDownloadLimit->setEnabled(true); - m_ui->spinDownloadLimit->setValue(intValue); - } - else { - // Disabled - m_ui->checkDownloadLimit->setChecked(false); - m_ui->spinDownloadLimit->setEnabled(false); - } - intValue = session->globalUploadSpeedLimit() / 1024; - if (intValue > 0) { - // Enabled - m_ui->checkUploadLimit->setChecked(true); - m_ui->spinUploadLimit->setEnabled(true); - m_ui->spinUploadLimit->setValue(intValue); - } - else { - // Disabled - m_ui->checkUploadLimit->setChecked(false); - m_ui->spinUploadLimit->setEnabled(false); - } - - intValue = session->altGlobalDownloadSpeedLimit() / 1024; - if (intValue > 0) { - // Enabled - m_ui->checkDownloadLimitAlt->setChecked(true); - m_ui->spinDownloadLimitAlt->setEnabled(true); - m_ui->spinDownloadLimitAlt->setValue(intValue); - } - else { - // Disabled - m_ui->checkDownloadLimitAlt->setChecked(false); - m_ui->spinDownloadLimitAlt->setEnabled(false); - } - intValue = session->altGlobalUploadSpeedLimit() / 1024; - if (intValue > 0) { - // Enabled - m_ui->checkUploadLimitAlt->setChecked(true); - m_ui->spinUploadLimitAlt->setEnabled(true); - m_ui->spinUploadLimitAlt->setValue(intValue); - } - else { - // Disabled - m_ui->checkUploadLimitAlt->setChecked(false); - m_ui->spinUploadLimitAlt->setEnabled(false); - } - - m_ui->checkuTP->setChecked(session->isUTPEnabled()); - m_ui->checkLimituTPConnections->setEnabled(m_ui->checkuTP->isChecked()); - m_ui->checkLimituTPConnections->setChecked(session->isUTPRateLimited()); - m_ui->checkLimitTransportOverhead->setChecked(session->includeOverheadInLimits()); - m_ui->checkLimitLocalPeerRate->setChecked(!session->ignoreLimitsOnLAN()); - - m_ui->check_schedule->setChecked(session->isBandwidthSchedulerEnabled()); - m_ui->schedule_from->setTime(pref->getSchedulerStartTime()); - m_ui->schedule_to->setTime(pref->getSchedulerEndTime()); - m_ui->schedule_days->setCurrentIndex(static_cast(pref->getSchedulerDays())); - // End Speed preferences - - // Bittorrent preferences - m_ui->checkDHT->setChecked(session->isDHTEnabled()); - m_ui->checkPeX->setChecked(session->isPeXEnabled()); - m_ui->checkLSD->setChecked(session->isLSDEnabled()); - m_ui->comboEncryption->setCurrentIndex(session->encryption()); - m_ui->checkAnonymousMode->setChecked(session->isAnonymousModeEnabled()); - m_ui->checkEnableAddTrackers->setChecked(session->isAddTrackersEnabled()); - m_ui->textTrackers->setPlainText(session->additionalTrackers()); - - m_ui->checkEnableQueueing->setChecked(session->isQueueingSystemEnabled()); - m_ui->spinMaxActiveDownloads->setValue(session->maxActiveDownloads()); - m_ui->spinMaxActiveUploads->setValue(session->maxActiveUploads()); - m_ui->spinMaxActiveTorrents->setValue(session->maxActiveTorrents()); - m_ui->checkIgnoreSlowTorrentsForQueueing->setChecked(session->ignoreSlowTorrentsForQueueing()); - - if (session->globalMaxRatio() >= 0.) { - // Enable - m_ui->checkMaxRatio->setChecked(true); - m_ui->spinMaxRatio->setEnabled(true); - m_ui->comboRatioLimitAct->setEnabled(true); - m_ui->spinMaxRatio->setValue(session->globalMaxRatio()); - } - else { - // Disable - m_ui->checkMaxRatio->setChecked(false); - m_ui->spinMaxRatio->setEnabled(false); - } - if (session->globalMaxSeedingMinutes() >= 0) { - // Enable - m_ui->checkMaxSeedingMinutes->setChecked(true); - m_ui->spinMaxSeedingMinutes->setEnabled(true); - m_ui->spinMaxSeedingMinutes->setValue(session->globalMaxSeedingMinutes()); - } - else { - // Disable - m_ui->checkMaxSeedingMinutes->setChecked(false); - m_ui->spinMaxSeedingMinutes->setEnabled(false); - } - m_ui->comboRatioLimitAct->setEnabled((session->globalMaxSeedingMinutes() >= 0) || (session->globalMaxRatio() >= 0.)); - m_ui->comboRatioLimitAct->setCurrentIndex(session->maxRatioAction()); - // End Bittorrent preferences - - // Web UI preferences - m_ui->textServerDomains->setText(pref->getServerDomains()); - m_ui->checkWebUi->setChecked(pref->isWebUiEnabled()); - m_ui->spinWebUiPort->setValue(pref->getWebUiPort()); - m_ui->checkWebUIUPnP->setChecked(pref->useUPnPForWebUIPort()); - m_ui->checkWebUiHttps->setChecked(pref->isWebUiHttpsEnabled()); - setSslCertificate(pref->getWebUiHttpsCertificate()); - setSslKey(pref->getWebUiHttpsKey()); - m_ui->textWebUiUsername->setText(pref->getWebUiUsername()); - m_ui->textWebUiPassword->setText(pref->getWebUiPassword()); - m_ui->checkBypassLocalAuth->setChecked(!pref->isWebUiLocalAuthEnabled()); - - m_ui->checkDynDNS->setChecked(pref->isDynDNSEnabled()); - m_ui->comboDNSService->setCurrentIndex(static_cast(pref->getDynDNSService())); - m_ui->domainNameTxt->setText(pref->getDynDomainName()); - m_ui->DNSUsernameTxt->setText(pref->getDynDNSUsername()); - m_ui->DNSPasswordTxt->setText(pref->getDynDNSPassword()); - // End Web UI preferences -} - -// return min & max ports -// [min, max] -int OptionsDialog::getPort() const -{ - return m_ui->spinPort->value(); -} - -void OptionsDialog::on_randomButton_clicked() -{ - // Range [1024: 65535] - m_ui->spinPort->setValue(Utils::Random::rand(1024, 65535)); -} - -int OptionsDialog::getEncryptionSetting() const -{ - return m_ui->comboEncryption->currentIndex(); -} - -int OptionsDialog::getMaxActiveDownloads() const -{ - return m_ui->spinMaxActiveDownloads->value(); -} - -int OptionsDialog::getMaxActiveUploads() const -{ - return m_ui->spinMaxActiveUploads->value(); -} - -int OptionsDialog::getMaxActiveTorrents() const -{ - return m_ui->spinMaxActiveTorrents->value(); -} - -bool OptionsDialog::isQueueingSystemEnabled() const -{ - return m_ui->checkEnableQueueing->isChecked(); -} - -bool OptionsDialog::isDHTEnabled() const -{ - return m_ui->checkDHT->isChecked(); -} - -bool OptionsDialog::isLSDEnabled() const -{ - return m_ui->checkLSD->isChecked(); -} - -bool OptionsDialog::isUPnPEnabled() const -{ - return m_ui->checkUPnP->isChecked(); -} - -// Return Download & Upload limits in kbps -// [download,upload] -QPair OptionsDialog::getGlobalBandwidthLimits() const -{ - int DL = 0, UP = 0; - if (m_ui->checkDownloadLimit->isChecked()) - DL = m_ui->spinDownloadLimit->value() * 1024; - if (m_ui->checkUploadLimit->isChecked()) - UP = m_ui->spinUploadLimit->value() * 1024; - return qMakePair(DL, UP); -} - -// Return alternate Download & Upload limits in kbps -// [download,upload] -QPair OptionsDialog::getAltGlobalBandwidthLimits() const -{ - int DL = 0, UP = 0; - if (m_ui->checkDownloadLimitAlt->isChecked()) - DL = m_ui->spinDownloadLimitAlt->value() * 1024; - if (m_ui->checkUploadLimitAlt->isChecked()) - UP = m_ui->spinUploadLimitAlt->value() * 1024; - return qMakePair(DL, UP); -} - -bool OptionsDialog::startMinimized() const -{ - return m_ui->checkStartMinimized->isChecked(); -} - -#ifndef Q_OS_MAC -bool OptionsDialog::systrayIntegration() const -{ - if (!QSystemTrayIcon::isSystemTrayAvailable()) return false; - return m_ui->checkShowSystray->isChecked(); -} - -bool OptionsDialog::minimizeToTray() const -{ - if (!m_ui->checkShowSystray->isChecked()) return false; - return m_ui->checkMinimizeToSysTray->isChecked(); -} - -bool OptionsDialog::closeToTray() const -{ - if (!m_ui->checkShowSystray->isChecked()) return false; - return m_ui->checkCloseToSystray->isChecked(); -} -#endif - -// Return Share ratio -qreal OptionsDialog::getMaxRatio() const -{ - if (m_ui->checkMaxRatio->isChecked()) - return m_ui->spinMaxRatio->value(); - return -1; -} - -// Return Seeding Minutes -int OptionsDialog::getMaxSeedingMinutes() const -{ - if (m_ui->checkMaxSeedingMinutes->isChecked()) - return m_ui->spinMaxSeedingMinutes->value(); - return -1; -} - -// Return max connections number -int OptionsDialog::getMaxConnecs() const -{ - if (!m_ui->checkMaxConnecs->isChecked()) - return -1; - else - return m_ui->spinMaxConnec->value(); -} - -int OptionsDialog::getMaxConnecsPerTorrent() const -{ - if (!m_ui->checkMaxConnecsPerTorrent->isChecked()) - return -1; - else - return m_ui->spinMaxConnecPerTorrent->value(); -} - -int OptionsDialog::getMaxUploads() const -{ - if (!m_ui->checkMaxUploads->isChecked()) - return -1; - else - return m_ui->spinMaxUploads->value(); -} - -int OptionsDialog::getMaxUploadsPerTorrent() const -{ - if (!m_ui->checkMaxUploadsPerTorrent->isChecked()) - return -1; - else - return m_ui->spinMaxUploadsPerTorrent->value(); -} - -void OptionsDialog::on_buttonBox_accepted() -{ - if (applyButton->isEnabled()) { - if (!schedTimesOk()) { - m_ui->tabSelection->setCurrentRow(TAB_SPEED); - return; - } - if (!webUIAuthenticationOk()) { - m_ui->tabSelection->setCurrentRow(TAB_WEBUI); - return; - } - applyButton->setEnabled(false); - this->hide(); - saveOptions(); - } - saveWindowState(); - accept(); -} - -void OptionsDialog::applySettings(QAbstractButton* button) -{ - if (button == applyButton) { - if (!schedTimesOk()) { - m_ui->tabSelection->setCurrentRow(TAB_SPEED); - return; - } - if (!webUIAuthenticationOk()) { - m_ui->tabSelection->setCurrentRow(TAB_WEBUI); - return; - } - saveOptions(); - } -} - -void OptionsDialog::closeEvent(QCloseEvent *e) -{ - setAttribute(Qt::WA_DeleteOnClose); - e->accept(); -} - -void OptionsDialog::on_buttonBox_rejected() -{ - setAttribute(Qt::WA_DeleteOnClose); - reject(); -} - -bool OptionsDialog::useAdditionDialog() const -{ - return m_ui->checkAdditionDialog->isChecked(); -} - -void OptionsDialog::enableApplyButton() -{ - applyButton->setEnabled(true); -} - -void OptionsDialog::toggleComboRatioLimitAct() -{ - // Verify if the share action button must be enabled - m_ui->comboRatioLimitAct->setEnabled(m_ui->checkMaxRatio->isChecked() || m_ui->checkMaxSeedingMinutes->isChecked()); -} - -void OptionsDialog::enableProxy(int index) -{ - if (index) { - //enable - m_ui->lblProxyIP->setEnabled(true); - m_ui->textProxyIP->setEnabled(true); - m_ui->lblProxyPort->setEnabled(true); - m_ui->spinProxyPort->setEnabled(true); - m_ui->checkProxyPeerConnecs->setEnabled(true); - m_ui->checkForceProxy->setEnabled(true); - if (index > 1) { - m_ui->checkProxyAuth->setEnabled(true); - m_ui->isProxyOnlyForTorrents->setEnabled(true); - } - else { - m_ui->checkProxyAuth->setEnabled(false); - m_ui->checkProxyAuth->setChecked(false); - m_ui->isProxyOnlyForTorrents->setEnabled(false); - m_ui->isProxyOnlyForTorrents->setChecked(true); - } - } - else { - //disable - m_ui->lblProxyIP->setEnabled(false); - m_ui->textProxyIP->setEnabled(false); - m_ui->lblProxyPort->setEnabled(false); - m_ui->spinProxyPort->setEnabled(false); - m_ui->checkProxyPeerConnecs->setEnabled(false); - m_ui->checkForceProxy->setEnabled(false); - m_ui->isProxyOnlyForTorrents->setEnabled(false); - m_ui->checkProxyAuth->setEnabled(false); - m_ui->checkProxyAuth->setChecked(false); - } -} - -bool OptionsDialog::isSlashScreenDisabled() const -{ - return !m_ui->checkShowSplash->isChecked(); -} - -#ifdef Q_OS_WIN -bool OptionsDialog::WinStartup() const -{ - return m_ui->checkStartup->isChecked(); -} -#endif - -bool OptionsDialog::preventFromSuspend() const -{ - return m_ui->checkPreventFromSuspend->isChecked(); -} - -bool OptionsDialog::preAllocateAllFiles() const -{ - return m_ui->checkPreallocateAll->isChecked(); -} - -bool OptionsDialog::addTorrentsInPause() const -{ - return m_ui->checkStartPaused->isChecked(); -} - -// Proxy settings -bool OptionsDialog::isProxyEnabled() const -{ - return m_ui->comboProxyType->currentIndex(); -} - -bool OptionsDialog::isProxyAuthEnabled() const -{ - return m_ui->checkProxyAuth->isChecked(); -} - -QString OptionsDialog::getProxyIp() const -{ - return m_ui->textProxyIP->text().trimmed(); -} - -unsigned short OptionsDialog::getProxyPort() const -{ - return m_ui->spinProxyPort->value(); -} - -QString OptionsDialog::getProxyUsername() const -{ - QString username = m_ui->textProxyUsername->text().trimmed(); - return username; -} - -QString OptionsDialog::getProxyPassword() const -{ - QString password = m_ui->textProxyPassword->text(); - password = password.trimmed(); - return password; -} - -// Locale Settings -QString OptionsDialog::getLocale() const -{ - return m_ui->comboI18n->itemData(m_ui->comboI18n->currentIndex(), Qt::UserRole).toString(); -} - -void OptionsDialog::setLocale(const QString &localeStr) -{ - QString name; - if (localeStr.startsWith("eo", Qt::CaseInsensitive)) { - name = "eo"; - } - else { - QLocale locale(localeStr); - if (locale.language() == QLocale::Uzbek) - name = "uz@Latn"; - else - name = locale.name(); - } - // Attempt to find exact match - int index = m_ui->comboI18n->findData(name, Qt::UserRole); - if (index < 0) { - //Attempt to find a language match without a country - int pos = name.indexOf('_'); - if (pos > -1) { - QString lang = name.left(pos); - index = m_ui->comboI18n->findData(lang, Qt::UserRole); - } - } - if (index < 0) { - // Unrecognized, use US English - index = m_ui->comboI18n->findData("en", Qt::UserRole); - Q_ASSERT(index >= 0); - } - m_ui->comboI18n->setCurrentIndex(index); -} - -QString OptionsDialog::getTorrentExportDir() const -{ - if (m_ui->checkExportDir->isChecked()) - return Utils::Fs::expandPathAbs(m_ui->textExportDir->selectedPath()); - return QString(); -} - -QString OptionsDialog::getFinishedTorrentExportDir() const -{ - if (m_ui->checkExportDirFin->isChecked()) - return Utils::Fs::expandPathAbs(m_ui->textExportDirFin->selectedPath()); - return QString(); -} - -// Return action on double-click on a downloading torrent set in options -int OptionsDialog::getActionOnDblClOnTorrentDl() const -{ - if (m_ui->actionTorrentDlOnDblClBox->currentIndex() < 1) - return 0; - return m_ui->actionTorrentDlOnDblClBox->currentIndex(); -} - -// Return action on double-click on a finished torrent set in options -int OptionsDialog::getActionOnDblClOnTorrentFn() const -{ - if (m_ui->actionTorrentFnOnDblClBox->currentIndex() < 1) - return 0; - return m_ui->actionTorrentFnOnDblClBox->currentIndex(); -} - -void OptionsDialog::on_addScanFolderButton_clicked() -{ - Preferences* const pref = Preferences::instance(); - const QString dir = QFileDialog::getExistingDirectory(this, tr("Select folder to monitor"), - Utils::Fs::toNativePath(Utils::Fs::folderName(pref->getScanDirsLastPath()))); - if (!dir.isEmpty()) { - const ScanFoldersModel::PathStatus status = ScanFoldersModel::instance()->addPath(dir, ScanFoldersModel::DEFAULT_LOCATION, QString(), false); - QString error; - switch (status) { - case ScanFoldersModel::AlreadyInList: - error = tr("Folder is already being monitored:"); - break; - case ScanFoldersModel::DoesNotExist: - error = tr("Folder does not exist:"); - break; - case ScanFoldersModel::CannotRead: - error = tr("Folder is not readable:"); - break; - default: - pref->setScanDirsLastPath(dir); - addedScanDirs << dir; - for (int i = 0; i < ScanFoldersModel::instance()->columnCount(); ++i) - m_ui->scanFoldersView->resizeColumnToContents(i); - enableApplyButton(); - } - - if (!error.isEmpty()) - QMessageBox::critical(this, tr("Adding entry failed"), QString("%1\n%2").arg(error).arg(dir)); - } -} - -void OptionsDialog::on_removeScanFolderButton_clicked() -{ - const QModelIndexList selected - = m_ui->scanFoldersView->selectionModel()->selectedIndexes(); - if (selected.isEmpty()) - return; - Q_ASSERT(selected.count() == ScanFoldersModel::instance()->columnCount()); - foreach (const QModelIndex &index, selected) { - if (index.column() == ScanFoldersModel::WATCH) - removedScanDirs << index.data().toString(); - } - ScanFoldersModel::instance()->removePath(selected.first().row(), false); -} - -void OptionsDialog::handleScanFolderViewSelectionChanged() -{ - m_ui->removeScanFolderButton->setEnabled(!m_ui->scanFoldersView->selectionModel()->selectedIndexes().isEmpty()); -} - -QString OptionsDialog::askForExportDir(const QString& currentExportPath) -{ - QDir currentExportDir(Utils::Fs::expandPathAbs(currentExportPath)); - QString dir; - if (!currentExportPath.isEmpty() && currentExportDir.exists()) - dir = QFileDialog::getExistingDirectory(this, tr("Choose export directory"), currentExportDir.absolutePath()); - else - dir = QFileDialog::getExistingDirectory(this, tr("Choose export directory"), QDir::homePath()); - return dir; -} - -// Return Filter object to apply to BT session -QString OptionsDialog::getFilter() const -{ - return m_ui->textFilterPath->selectedPath(); -} - -// Web UI - -bool OptionsDialog::isWebUiEnabled() const -{ - return m_ui->checkWebUi->isChecked(); -} - -quint16 OptionsDialog::webUiPort() const -{ - return m_ui->spinWebUiPort->value(); -} - -QString OptionsDialog::webUiUsername() const -{ - return m_ui->textWebUiUsername->text(); -} - -QString OptionsDialog::webUiPassword() const -{ - return m_ui->textWebUiPassword->text(); -} - -void OptionsDialog::showConnectionTab() -{ - m_ui->tabSelection->setCurrentRow(TAB_CONNECTION); -} - -void OptionsDialog::on_btnWebUiCrt_clicked() -{ - const QString filename = QFileDialog::getOpenFileName(this, tr("Import SSL certificate"), QString(), tr("SSL Certificate") + QLatin1String(" (*.crt *.pem)")); - if (filename.isEmpty()) - return; - - QFile cert(filename); - if (!cert.open(QIODevice::ReadOnly)) - return; - - bool success = setSslCertificate(cert.read(1024 * 1024)); - if (!success) - QMessageBox::warning(this, tr("Invalid certificate"), tr("This is not a valid SSL certificate.")); -} - -void OptionsDialog::on_btnWebUiKey_clicked() -{ - const QString filename = QFileDialog::getOpenFileName(this, tr("Import SSL key"), QString(), tr("SSL key") + QLatin1String(" (*.key *.pem)")); - if (filename.isEmpty()) - return; - - QFile key(filename); - if (!key.open(QIODevice::ReadOnly)) - return; - - bool success = setSslKey(key.read(1024 * 1024)); - if (!success) - QMessageBox::warning(this, tr("Invalid key"), tr("This is not a valid SSL key.")); -} - -void OptionsDialog::on_registerDNSBtn_clicked() -{ - QDesktopServices::openUrl(Net::DNSUpdater::getRegistrationUrl(m_ui->comboDNSService->currentIndex())); -} - -void OptionsDialog::on_IpFilterRefreshBtn_clicked() -{ - if (m_refreshingIpFilter) return; - m_refreshingIpFilter = true; - // Updating program preferences - BitTorrent::Session *const session = BitTorrent::Session::instance(); - session->setIPFilteringEnabled(true); - session->setIPFilterFile(""); // forcing Session reload filter file - session->setIPFilterFile(getFilter()); - connect(session, SIGNAL(IPFilterParsed(bool, int)), SLOT(handleIPFilterParsed(bool, int))); - setCursor(QCursor(Qt::WaitCursor)); -} - -void OptionsDialog::handleIPFilterParsed(bool error, int ruleCount) -{ - setCursor(QCursor(Qt::ArrowCursor)); - if (error) - QMessageBox::warning(this, tr("Parsing error"), tr("Failed to parse the provided IP filter")); - else - QMessageBox::information(this, tr("Successfully refreshed"), tr("Successfully parsed the provided IP filter: %1 rules were applied.", "%1 is a number").arg(ruleCount)); - m_refreshingIpFilter = false; - disconnect(BitTorrent::Session::instance(), SIGNAL(IPFilterParsed(bool, int)), this, SLOT(handleIPFilterParsed(bool, int))); -} - -QString OptionsDialog::languageToLocalizedString(const QLocale &locale) -{ - switch (locale.language()) { - case QLocale::English: { - if (locale.country() == QLocale::Australia) - return QString::fromUtf8(C_LOCALE_ENGLISH_AUSTRALIA); - else if (locale.country() == QLocale::UnitedKingdom) - return QString::fromUtf8(C_LOCALE_ENGLISH_UNITEDKINGDOM); - return QString::fromUtf8(C_LOCALE_ENGLISH); - } - case QLocale::French: return QString::fromUtf8(C_LOCALE_FRENCH); - case QLocale::German: return QString::fromUtf8(C_LOCALE_GERMAN); - case QLocale::Hungarian: return QString::fromUtf8(C_LOCALE_HUNGARIAN); - case QLocale::Icelandic: return QString::fromUtf8(C_LOCALE_ICELANDIC); - case QLocale::Indonesian: return QString::fromUtf8(C_LOCALE_INDONESIAN); - case QLocale::Italian: return QString::fromUtf8(C_LOCALE_ITALIAN); - case QLocale::Dutch: return QString::fromUtf8(C_LOCALE_DUTCH); - case QLocale::Spanish: return QString::fromUtf8(C_LOCALE_SPANISH); - case QLocale::Catalan: return QString::fromUtf8(C_LOCALE_CATALAN); - case QLocale::Galician: return QString::fromUtf8(C_LOCALE_GALICIAN); - case QLocale::Occitan: return QString::fromUtf8(C_LOCALE_OCCITAN); - case QLocale::Portuguese: { - if (locale.country() == QLocale::Brazil) - return QString::fromUtf8(C_LOCALE_PORTUGUESE_BRAZIL); - return QString::fromUtf8(C_LOCALE_PORTUGUESE); - } - case QLocale::Polish: return QString::fromUtf8(C_LOCALE_POLISH); - case QLocale::Latvian: return QString::fromUtf8(C_LOCALE_LATVIAN); - case QLocale::Lithuanian: return QString::fromUtf8(C_LOCALE_LITHUANIAN); - case QLocale::Malay: return QString::fromUtf8(C_LOCALE_MALAY); - case QLocale::Czech: return QString::fromUtf8(C_LOCALE_CZECH); - case QLocale::Slovak: return QString::fromUtf8(C_LOCALE_SLOVAK); - case QLocale::Slovenian: return QString::fromUtf8(C_LOCALE_SLOVENIAN); - case QLocale::Serbian: return QString::fromUtf8(C_LOCALE_SERBIAN); - case QLocale::Croatian: return QString::fromUtf8(C_LOCALE_CROATIAN); - case QLocale::Armenian: return QString::fromUtf8(C_LOCALE_ARMENIAN); - case QLocale::Romanian: return QString::fromUtf8(C_LOCALE_ROMANIAN); - case QLocale::Turkish: return QString::fromUtf8(C_LOCALE_TURKISH); - case QLocale::Greek: return QString::fromUtf8(C_LOCALE_GREEK); - case QLocale::Swedish: return QString::fromUtf8(C_LOCALE_SWEDISH); - case QLocale::Finnish: return QString::fromUtf8(C_LOCALE_FINNISH); - case QLocale::Norwegian: return QString::fromUtf8(C_LOCALE_NORWEGIAN); - case QLocale::Danish: return QString::fromUtf8(C_LOCALE_DANISH); - case QLocale::Bulgarian: return QString::fromUtf8(C_LOCALE_BULGARIAN); - case QLocale::Ukrainian: return QString::fromUtf8(C_LOCALE_UKRAINIAN); - case QLocale::Uzbek: return QString::fromUtf8(C_LOCALE_UZBEK); - case QLocale::Russian: return QString::fromUtf8(C_LOCALE_RUSSIAN); - case QLocale::Japanese: return QString::fromUtf8(C_LOCALE_JAPANESE); - case QLocale::Hebrew: return QString::fromUtf8(C_LOCALE_HEBREW); - case QLocale::Hindi: return QString::fromUtf8(C_LOCALE_HINDI); - case QLocale::Arabic: return QString::fromUtf8(C_LOCALE_ARABIC); - case QLocale::Georgian: return QString::fromUtf8(C_LOCALE_GEORGIAN); - case QLocale::Byelorussian: return QString::fromUtf8(C_LOCALE_BYELORUSSIAN); - case QLocale::Basque: return QString::fromUtf8(C_LOCALE_BASQUE); - case QLocale::Vietnamese: return QString::fromUtf8(C_LOCALE_VIETNAMESE); - case QLocale::Chinese: { - switch (locale.country()) { - case QLocale::China: - return QString::fromUtf8(C_LOCALE_CHINESE_SIMPLIFIED); - case QLocale::HongKong: - return QString::fromUtf8(C_LOCALE_CHINESE_TRADITIONAL_HK); - default: - return QString::fromUtf8(C_LOCALE_CHINESE_TRADITIONAL_TW); - - } - } - case QLocale::Korean: return QString::fromUtf8(C_LOCALE_KOREAN); - default: { - // Fallback to English - const QString eng_lang = QLocale::languageToString(locale.language()); - qWarning() << "Unrecognized language name: " << eng_lang; - return eng_lang; - } - } -} - -bool OptionsDialog::setSslKey(const QByteArray &key) -{ -#ifndef QT_NO_OPENSSL - // try different formats - const bool isKeyValid = (!QSslKey(key, QSsl::Rsa).isNull() || !QSslKey(key, QSsl::Ec).isNull()); - if (isKeyValid) { - m_ui->lblSslKeyStatus->setPixmap(QPixmap(":/icons/qbt-theme/security-high.png").scaledToHeight(20, Qt::SmoothTransformation)); - m_sslKey = key; - } - else { - m_ui->lblSslKeyStatus->setPixmap(QPixmap(":/icons/qbt-theme/security-low.png").scaledToHeight(20, Qt::SmoothTransformation)); - m_sslKey.clear(); - } - return isKeyValid; -#else - Q_UNUSED(key); - return false; -#endif -} - -bool OptionsDialog::setSslCertificate(const QByteArray &cert) -{ -#ifndef QT_NO_OPENSSL - const bool isCertValid = !QSslCertificate(cert).isNull(); - if (isCertValid) { - m_ui->lblSslCertStatus->setPixmap(QPixmap(":/icons/qbt-theme/security-high.png").scaledToHeight(20, Qt::SmoothTransformation)); - m_sslCert = cert; - } - else { - m_ui->lblSslCertStatus->setPixmap(QPixmap(":/icons/qbt-theme/security-low.png").scaledToHeight(20, Qt::SmoothTransformation)); - m_sslCert.clear(); - } - return isCertValid; -#else - Q_UNUSED(cert); - return false; -#endif -} - -bool OptionsDialog::schedTimesOk() -{ - if (m_ui->schedule_from->time() == m_ui->schedule_to->time()) { - QMessageBox::warning(this, tr("Time Error"), tr("The start time and the end time can't be the same.")); - return false; - } - return true; -} - -bool OptionsDialog::webUIAuthenticationOk() -{ - if (webUiUsername().length() < 3) { - QMessageBox::warning(this, tr("Length Error"), tr("The Web UI username must be at least 3 characters long.")); - return false; - } - if (webUiPassword().length() < 6) { - QMessageBox::warning(this, tr("Length Error"), tr("The Web UI password must be at least 6 characters long.")); - return false; - } - return true; -} - -void OptionsDialog::on_banListButton_clicked() -{ - //have to call dialog window - BanListOptions bl(this); - bl.exec(); -} diff --git a/src/gui/optionsdlg.h b/src/gui/optionsdlg.h deleted file mode 100644 index dc0cf9a59..000000000 --- a/src/gui/optionsdlg.h +++ /dev/null @@ -1,191 +0,0 @@ -/* - * Bittorrent Client using Qt4 and libtorrent. - * Copyright (C) 2006 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 OPTIONSDLG_H -#define OPTIONSDLG_H - -#include -#include - -class QAbstractButton; -class QCloseEvent; -class QListWidgetItem; -class AdvancedSettings; - -// actions on double-click on torrents -enum DoubleClickAction -{ - TOGGLE_PAUSE, - OPEN_DEST, - NO_ACTION -}; - -namespace Net -{ - enum class ProxyType; -} - -namespace Ui -{ - class OptionsDialog; -} - -class OptionsDialog: public QDialog -{ - Q_OBJECT - using ThisType = OptionsDialog; - -private: - enum Tabs - { - TAB_UI, - TAB_DOWNLOADS, - TAB_CONNECTION, - TAB_SPEED, - TAB_BITTORRENT, - TAB_RSS, - TAB_WEBUI, - TAB_ADVANCED - }; - -public: - // Constructor / Destructor - OptionsDialog(QWidget *parent = 0); - ~OptionsDialog(); - -public slots: - void showConnectionTab(); - -private slots: - void enableProxy(int index); - void on_buttonBox_accepted(); - void closeEvent(QCloseEvent *e); - void on_buttonBox_rejected(); - void applySettings(QAbstractButton* button); - void enableApplyButton(); - void toggleComboRatioLimitAct(); - void changePage(QListWidgetItem*, QListWidgetItem*); - void loadWindowState(); - void saveWindowState() const; - void handleScanFolderViewSelectionChanged(); - void on_IpFilterRefreshBtn_clicked(); - void handleIPFilterParsed(bool error, int ruleCount); - void on_banListButton_clicked(); - void on_randomButton_clicked(); - void on_addScanFolderButton_clicked(); - void on_removeScanFolderButton_clicked(); - void on_btnWebUiCrt_clicked(); - void on_btnWebUiKey_clicked(); - void on_registerDNSBtn_clicked(); - void setLocale(const QString &localeStr); - -private: - // Methods - void saveOptions(); - void loadOptions(); - void initializeLanguageCombo(); - static QString languageToLocalizedString(const QLocale &locale); - // General options - QString getLocale() const; -#ifndef Q_OS_MAC - bool systrayIntegration() const; - bool minimizeToTray() const; - bool closeToTray() const; -#endif - bool startMinimized() const; - bool isSlashScreenDisabled() const; - bool preventFromSuspend() const; -#ifdef Q_OS_WIN - bool WinStartup() const; -#endif - // Downloads - bool preAllocateAllFiles() const; - bool useAdditionDialog() const; - bool addTorrentsInPause() const; - QString getTorrentExportDir() const; - QString getFinishedTorrentExportDir() const; - QString askForExportDir(const QString& currentExportPath); - int getActionOnDblClOnTorrentDl() const; - int getActionOnDblClOnTorrentFn() const; - // Connection options - int getPort() const; - bool isUPnPEnabled() const; - QPair getGlobalBandwidthLimits() const; - QPair getAltGlobalBandwidthLimits() const; - // Bittorrent options - int getMaxConnecs() const; - int getMaxConnecsPerTorrent() const; - int getMaxUploads() const; - int getMaxUploadsPerTorrent() const; - bool isDHTEnabled() const; - bool isLSDEnabled() const; - int getEncryptionSetting() const; - qreal getMaxRatio() const; - int getMaxSeedingMinutes() const; - // Proxy options - bool isProxyEnabled() const; - bool isProxyAuthEnabled() const; - QString getProxyIp() const; - unsigned short getProxyPort() const; - QString getProxyUsername() const; - QString getProxyPassword() const; - Net::ProxyType getProxyType() const; - // IP Filter - bool isIPFilteringEnabled() const; - QString getFilter() const; - bool m_refreshingIpFilter; - // Queueing system - bool isQueueingSystemEnabled() const; - int getMaxActiveDownloads() const; - int getMaxActiveUploads() const; - int getMaxActiveTorrents() const; - bool isWebUiEnabled() const; - quint16 webUiPort() const; - QString webUiUsername() const; - QString webUiPassword() const; - -private: - bool setSslKey(const QByteArray &key); - bool setSslCertificate(const QByteArray &cert); - bool schedTimesOk(); - bool webUIAuthenticationOk(); - -private: - Ui::OptionsDialog *m_ui; - QButtonGroup choiceLanguage; - QAbstractButton *applyButton; - AdvancedSettings *advancedSettings; - QList addedScanDirs; - QList removedScanDirs; - // SSL Cert / key - QByteArray m_sslCert, m_sslKey; -}; - -#endif diff --git a/src/gui/optionsdlg.ui b/src/gui/optionsdlg.ui deleted file mode 100644 index 6cc0ff763..000000000 --- a/src/gui/optionsdlg.ui +++ /dev/null @@ -1,3438 +0,0 @@ - - - OptionsDialog - - - - 0 - 0 - 779 - 591 - - - - Options - - - - - - Qt::Horizontal - - - false - - - - Qt::LeftToRight - - - Qt::ScrollBarAlwaysOff - - - QListView::Static - - - QListView::TopToBottom - - - false - - - QListView::Adjust - - - QListView::IconMode - - - -1 - - - - Behavior - - - - - Downloads - - - - - Connection - - - - - Speed - - - - - BitTorrent - - - - - RSS - - - - - Web UI - - - - - Advanced - - - - - - 0 - - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - - 0 - 0 - - - - true - - - - - 0 - 0 - 430 - 972 - - - - - - - Language - - - - - - - - User Interface Language: - - - - - - - - 0 - 0 - - - - QComboBox::AdjustToContents - - - 0 - - - - - - - - true - - - - (Requires restart) - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - - - - Transfer List - - - - - - Confirm when deleting torrents - - - true - - - - - - - Use alternating row colors - - - true - - - - - - - - - Hide zero and infinity values - - - - - - - - Always - - - - - Paused torrents only - - - - - - - - Qt::Horizontal - - - - 0 - 0 - - - - - - - - - - - 50 - false - - - - Action on double-click - - - true - - - - - - Downloading torrents: - - - - - - - - 0 - 0 - - - - 0 - - - - Start / Stop Torrent - - - - - Open destination folder - - - - - No action - - - - - - - - Completed torrents: - - - - - - - - Start / Stop Torrent - - - - - Open destination folder - - - - - No action - - - - - - - - - - - - - - Desktop - - - - - - Start qBittorrent on Windows start up - - - - - - - Show splash screen on start up - - - true - - - - - - - Start qBittorrent minimized - - - - - - - Confirmation on exit when torrents are active - - - true - - - - - - - Confirmation on auto-exit when downloads finish - - - true - - - - - - - Show &qBittorrent in notification area - - - true - - - - - - Minimize qBittorrent to notification area - - - false - - - - - - - Close qBittorrent to notification area - - - - - - - - - Tray icon style: - - - - - - - - Normal - - - - - Monochrome (Dark theme) - - - - - Monochrome (Light theme) - - - - - - - - - - - - - File association - - - - - - Use qBittorrent for .torrent files - - - - - - - Use qBittorrent for magnet links - - - - - - - - - - - - - Power Management - - - - - - Inhibit system sleep when torrents are active - - - - - - - - - - &Log file - - - true - - - true - - - - - - - - - 0 - 0 - - - - Save path: - - - - - - - - - - - - 0 - - - - - Backup the log file after: - - - - - - - MB - - - 1 - - - 1000 - - - 10 - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - 0 - - - - - Delete backup logs older than: - - - - - - - 1 - - - 365 - - - 6 - - - - - - - 1 - - - - days - - - - - months - - - - - years - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - - - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - true - - - - - 0 - 0 - 585 - 1179 - - - - - - - When adding a torrent - - - - - - Display &torrent content and some options - - - true - - - - 0 - - - - - Bring torrent dialog to the front - - - true - - - - - - - - - - Create subfolder for torrents with multiple files - - - true - - - - - - - Do not start the download automatically - - - - - - - Should the .torrent file be deleted after adding it - - - De&lete .torrent files afterwards - - - true - - - false - - - - - - Also delete .torrent files whose addition was cancelled - - - Also when addition is cancelled - - - - - - - - - - 0 - 0 - - - - <> - - - - - - - Warning! Data loss possible! - - - - - - - - - - - - - - - Saving Management - - - - - - - - Default Torrent Management Mode: - - - - - - - 10 - - - - - Automatic mode means that various torrent properties (e.g. save path) will be decided by the associated category - - - - Manual - - - - - Automatic - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - When Torrent Category changed: - - - - - - - - - - Relocate torrent - - - - - Switch torrent to Manual Mode - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - When Default Save Path changed: - - - - - - - - - 1 - - - - Relocate affected torrents - - - - - Switch affected torrents to Manual Mode - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - When Category changed: - - - - - - - - - 1 - - - - Relocate affected torrents - - - - - Switch affected torrents to Manual Mode - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - - - Use Subcategories - - - - - - - - - - - - Copy .torrent files for finished downloads to: - - - - - - - Default Save Path: - - - - - - - Copy .torrent files to: - - - - - - - Keep incomplete torrents in: - - - - - - - - - - - - - - - - - - Pre-allocate disk space for all files - - - - - - - Append .!qB extension to incomplete files - - - - - - - - - - Automatically add torrents from: - - - - - - - - - 0 - 1 - - - - - 250 - 150 - - - - QAbstractItemView::AllEditTriggers - - - QAbstractItemView::SingleSelection - - - QAbstractItemView::SelectRows - - - Qt::ElideNone - - - false - - - 80 - - - false - - - - - - - - - Add entry - - - - - - - false - - - Remove entry - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - - - - - - - Email notification &upon download completion - - - true - - - false - - - - - - - - - - - Destination email: - - - - - - - SMTP server: - - - - - - - - - - - - This server requires a secure connection (SSL) - - - - - - - Authentication - - - true - - - false - - - - - - Username: - - - - - - - - - - Password: - - - - - - - QLineEdit::Password - - - - - - - - - - - - - Run e&xternal program on torrent completion - - - true - - - false - - - - - - - - - true - - - - - - - - - - - - - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - true - - - - - 0 - 0 - 450 - 759 - - - - - - - Listening Port - - - - - - - - Port used for incoming connections: - - - - - - - 1 - - - 65535 - - - 8999 - - - - - - - Random - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - Use UPnP / NAT-PMP port forwarding from my router - - - true - - - - - - - Use different port on each startup - - - - - - - - - - Connections Limits - - - - - - 500 - - - 4 - - - - - - - Maximum number of connections per torrent: - - - true - - - - - - - Global maximum number of connections: - - - true - - - - - - - true - - - 2 - - - 2000 - - - 500 - - - - - - - 2 - - - 2000 - - - 100 - - - - - - - Maximum number of upload slots per torrent: - - - false - - - - - - - Global maximum number of upload slots: - - - false - - - - - - - 2000 - - - 8 - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - - true - - - Proxy Server - - - - - - - - Type: - - - - - - - - (None) - - - - - SOCKS4 - - - - - SOCKS5 - - - - - HTTP - - - - - - - - false - - - Host: - - - - - - - false - - - - - - - - - - false - - - Port: - - - - - - - false - - - 1 - - - 65535 - - - 8080 - - - - - - - - - false - - - Otherwise, the proxy server is only used for tracker connections - - - Use proxy for peer connections - - - - - - - Disable connections not supported by proxies - - - true - - - - - - - RSS feeds, search engine, software updates or anything else other than torrent transfers and related operations (such as peer exchanges) will use a direct connection - - - Use proxy only for torrents - - - false - - - - - - - false - - - A&uthentication - - - true - - - false - - - - - - - - Username: - - - - - - - - - - Password: - - - - - - - QLineEdit::Password - - - - - - - - - Info: The password is saved unencrypted - - - - - - - - - - - - - IP Fi&ltering - - - - - - - - Filter path (.dat, .p2p, .p2b): - - - - - - - - - - - 0 - 25 - - - - Reload the filter - - - - - - - - - - 0 - 0 - - - - Manually banned IP addresses... - - - - - - - Apply to trackers - - - - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - - - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - true - - - - - 0 - 0 - 376 - 501 - - - - - - - Global Rate Limits - - - - - - false - - - 1 - - - 1000000 - - - 100 - - - - - - - Upload: - - - - - - - KiB/s - - - - - - - false - - - 1 - - - 1000000 - - - 100 - - - - - - - KiB/s - - - - - - - :/icons/slow_off.png - - - - - - - Download: - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - - Alternative Rate Limits - - - - - - Schedule &the use of alternative rate limits - - - true - - - false - - - - - - From: - - - - - - - true - - - - - - hh:mm - - - - - - - To: - - - - - - - true - - - - - - hh:mm - - - false - - - - - - - When: - - - - - - - - 0 - 0 - - - - - Every day - - - - - Weekdays - - - - - Weekends - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - - :/icons/slow.png - - - - - - - Upload: - - - - - - - Download: - - - - - - - false - - - 1 - - - 1000000 - - - 10 - - - - - - - false - - - 1 - - - 1000000 - - - 10 - - - - - - - KiB/s - - - - - - - KiB/s - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - - Rate Limits Settings - - - - - - Apply rate limit to peers on LAN - - - - - - - Apply rate limit to transport overhead - - - - - - - Enable µTP protocol - - - - - - - Apply rate limit to µTP protocol - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - - - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - true - - - - - 0 - 0 - 528 - 664 - - - - - - - Privacy - - - - - - Enable DHT (decentralized network) to find more peers - - - true - - - - - - - Exchange peers with compatible Bittorrent clients (µTorrent, Vuze, ...) - - - Enable Peer Exchange (PeX) to find more peers - - - true - - - - - - - Look for peers on your local network - - - Enable Local Peer Discovery to find more peers - - - true - - - - - - - - - Encryption mode: - - - - - - - - Prefer encryption - - - - - Require encryption - - - - - Disable encryption - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - - - Enable when using a proxy or a VPN connection - - - Enable anonymous mode - - - - - - - (<a href="https://github.com/qbittorrent/qBittorrent/wiki/Anonymous-Mode">More information</a>) - - - true - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - - - - &Torrent Queueing - - - true - - - false - - - - 9 - - - - - Maximum active downloads: - - - - - - - -1 - - - 999 - - - 3 - - - - - - - Maximum active uploads: - - - - - - - -1 - - - 999 - - - 3 - - - - - - - Maximum active torrents: - - - - - - - -1 - - - 999 - - - 5 - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - Do not count slow torrents in these limits - - - - - - - - - - Share Ratio Limiting - - - - - - Seed torrents until their ratio reaches - - - - - - - Qt::Horizontal - - - - 109 - 20 - - - - - - - - then - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - false - - - - Pause them - - - - - Remove them - - - - - - - - Qt::Horizontal - - - - 121 - 28 - - - - - - - - Qt::Horizontal - - - - 100 - 42 - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - false - - - Qt::AlignCenter - - - 9999999 - - - 1440 - - - - - - - false - - - Qt::AlignHCenter - - - 0.000000000000000 - - - 9998.000000000000000 - - - 0.050000000000000 - - - 1.000000000000000 - - - - - - - minutes - - - - - - - Seed torrents until their seeding time reaches - - - - - - - - - - - 0 - 0 - - - - A&utomatically add these trackers to new downloads: - - - true - - - false - - - - - - true - - - Qt::StrongFocus - - - - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - - - - - - - - RSS Reader - - - - - - Enable fetching RSS feeds - - - - - - - - - Feeds refresh interval: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - Maximum number of articles per feed: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - min - - - 1 - - - 999999 - - - 5 - - - - - - - 9999 - - - 100 - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - - - - RSS Torrent Auto Downloader - - - - - - Enable auto downloading of RSS torrents - - - - - - - Edit auto downloading rules... - - - - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - true - - - - - 0 - 0 - 518 - 602 - - - - - - - Web User Interface (Remote control) - - - true - - - false - - - - - - - - Server domains: - - - - - - - Whitelist for filtering HTTP Host header values. -In order to defend against DNS rebinding attack, -you should put in domain names used by WebUI server. - -Use ';' to split multiple entries. Can use wildcard '*'. - - - - - - - - - - - Port: - - - - - - - 1 - - - 65535 - - - 8080 - - - - - - - Qt::Horizontal - - - - 21 - 29 - - - - - - - - - - Use UPnP / NAT-PMP to forward the port from my router - - - true - - - - - - - &Use HTTPS instead of HTTP - - - true - - - false - - - - - - - 22 - 22 - - - - - 22 - 22 - - - - - - - - - - - Certificate: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - - Import SSL Certificate - - - - - - - Qt::Horizontal - - - - 138 - 28 - - - - - - - - - - - 22 - 22 - - - - - 22 - 22 - - - - - - - - - - - Key: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - - Import SSL Key - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - <a href=https://httpd.apache.org/docs/current/ssl/ssl_faq.html#aboutcerts>Information about certificates</a> - - - true - - - - - - - - - - Authentication - - - - - - - - - 1000 - - - QLineEdit::Normal - - - - - - - - - - 1000 - - - QLineEdit::Password - - - - - - - Bypass authentication for localhost - - - - - - - Username: - - - - - - - Password: - - - - - - - - - - Upda&te my dynamic domain name - - - true - - - false - - - - - - Service: - - - - - - - - - - DynDNS - - - - - No-IP - - - - - - - - Register - - - - - - - - - Domain name: - - - - - - - changeme.dyndns.org - - - - - - - Username: - - - - - - - 50 - - - - - - - Password: - - - - - - - 50 - - - QLineEdit::Password - - - - - - - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - - - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - - - - - - QDialogButtonBox::Apply|QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - - - - - - FileSystemPathLineEdit - QWidget -
fspathedit.h
- 1 -
-
- - tabOption - comboI18n - checkStartPaused - spinPort - checkUPnP - textWebUiUsername - checkWebUi - textSavePath - scrollArea_7 - scrollArea_2 - spinWebUiPort - textWebUiPassword - buttonBox - tabSelection - scrollArea - confirmDeletion - checkAltRowColors - actionTorrentDlOnDblClBox - actionTorrentFnOnDblClBox - checkStartup - checkShowSplash - checkStartMinimized - checkProgramExitConfirm - checkShowSystray - checkMinimizeToSysTray - checkCloseToSystray - comboTrayIcon - checkAssociateTorrents - checkAssociateMagnetLinks - checkPreventFromSuspend - checkAdditionDialog - checkAdditionDialogFront - checkPreallocateAll - checkTempFolder - textTempPath - checkAppendqB - scanFoldersView - addScanFolderButton - removeScanFolderButton - checkExportDir - textExportDir - checkExportDirFin - textExportDirFin - groupMailNotification - dest_email_txt - smtp_server_txt - groupMailNotifAuth - mailNotifUsername - mailNotifPassword - checkSmtpSSL - autoRunBox - autoRun_txt - scrollArea_3 - randomButton - checkRandomPort - checkMaxConnecs - spinMaxConnec - checkMaxConnecsPerTorrent - spinMaxConnecPerTorrent - checkMaxUploadsPerTorrent - spinMaxUploadsPerTorrent - checkMaxUploads - spinMaxUploads - comboProxyType - textProxyIP - spinProxyPort - checkProxyPeerConnecs - checkForceProxy - isProxyOnlyForTorrents - checkProxyAuth - textProxyUsername - textProxyPassword - checkIPFilter - textFilterPath - IpFilterRefreshBtn - checkIpFilterTrackers - scrollArea_9 - spinUploadLimit - checkUploadLimit - spinDownloadLimit - checkDownloadLimit - check_schedule - schedule_to - schedule_from - schedule_days - checkUploadLimitAlt - checkDownloadLimitAlt - spinUploadLimitAlt - spinDownloadLimitAlt - checkLimitLocalPeerRate - checkLimitTransportOverhead - checkuTP - checkLimituTPConnections - scrollArea_4 - checkDHT - checkPeX - checkLSD - comboEncryption - checkAnonymousMode - checkEnableQueueing - spinMaxActiveDownloads - spinMaxActiveUploads - spinMaxActiveTorrents - checkIgnoreSlowTorrentsForQueueing - checkMaxRatio - spinMaxRatio - checkMaxSeedingMinutes - spinMaxSeedingMinutes - comboRatioLimitAct - checkWebUIUPnP - checkWebUiHttps - btnWebUiCrt - btnWebUiKey - checkBypassLocalAuth - checkDynDNS - comboDNSService - registerDNSBtn - domainNameTxt - DNSUsernameTxt - DNSPasswordTxt - - - - - - - checkUploadLimit - toggled(bool) - spinUploadLimit - setEnabled(bool) - - - 367 - 61 - - - 448 - 62 - - - - - checkDownloadLimit - toggled(bool) - spinDownloadLimit - setEnabled(bool) - - - 377 - 81 - - - 430 - 87 - - - - - checkMaxConnecs - toggled(bool) - spinMaxConnec - setEnabled(bool) - - - 604 - 205 - - - 677 - 206 - - - - - checkMaxConnecsPerTorrent - toggled(bool) - spinMaxConnecPerTorrent - setEnabled(bool) - - - 604 - 238 - - - 677 - 239 - - - - - checkMaxUploadsPerTorrent - toggled(bool) - spinMaxUploadsPerTorrent - setEnabled(bool) - - - 604 - 304 - - - 677 - 305 - - - - - checkMaxUploads - toggled(bool) - spinMaxUploads - setEnabled(bool) - - - 547 - 415 - - - 642 - 414 - - - - - checkDownloadLimitAlt - toggled(bool) - spinDownloadLimitAlt - setEnabled(bool) - - - 547 - 415 - - - 815 - 413 - - - - - checkUploadLimitAlt - toggled(bool) - spinUploadLimitAlt - setEnabled(bool) - - - 604 - 271 - - - 677 - 272 - - - - - checkMaxRatio - toggled(bool) - spinMaxRatio - setEnabled(bool) - - - 395 - 203 - - - 496 - 204 - - - - - checkMaxSeedingMinutes - toggled(bool) - spinMaxSeedingMinutes - setEnabled(bool) - - - 395 - 170 - - - 496 - 171 - - - - - deleteTorrentBox - toggled(bool) - deleteTorrentWarningIcon - setVisible(bool) - - - 554 - 153 - - - 324 - 214 - - - - - deleteTorrentBox - toggled(bool) - deleteTorrentWarningLabel - setVisible(bool) - - - 646 - 158 - - - 629 - 207 - - - - -
diff --git a/src/gui/powermanagement/CMakeLists.txt b/src/gui/powermanagement/CMakeLists.txt deleted file mode 100644 index 6baee2947..000000000 --- a/src/gui/powermanagement/CMakeLists.txt +++ /dev/null @@ -1,25 +0,0 @@ -set(QBT_POWERMANAGEMENT_HEADERS -powermanagement.h -) - -set(QBT_POWERMANAGEMENT_SOURCES -powermanagement.cpp -) - -if (UNIX AND DBUS) - find_package(X11) - if (X11_FOUND) - list(APPEND QBT_POWERMANAGEMENT_HEADERS powermanagement_x11.h) - list(APPEND QBT_POWERMANAGEMENT_SOURCES powermanagement_x11.cpp) - endif (X11_FOUND) -endif (UNIX AND DBUS) - -add_library(qbt_powermanagement STATIC ${QBT_POWERMANAGEMENT_SOURCES} ${QBT_POWERMANAGEMENT_HEADERS}) -set_target_properties(qbt_powermanagement PROPERTIES AUTOUIC False AUTORCC False) -target_link_qt_components(qbt_powermanagement Core) -if (X11_FOUND) - target_link_qt_components(qbt_powermanagement DBus) -endif (X11_FOUND) -if (WIN32) - target_link_libraries(qbt_powermanagement PowrProf) -endif (WIN32) diff --git a/src/gui/powermanagement/powermanagement.cpp b/src/gui/powermanagement/powermanagement.cpp deleted file mode 100644 index c51b22974..000000000 --- a/src/gui/powermanagement/powermanagement.cpp +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Bittorrent Client using Qt4 and libtorrent. - * Copyright (C) 2011 Vladimir Golovnev - * - * 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 - -#if (defined(Q_OS_UNIX) && !defined(Q_OS_MAC)) && defined(QT_DBUS_LIB) -#include "powermanagement_x11.h" -#endif -#include "powermanagement.h" - -#ifdef Q_OS_MAC -#include -#endif - -#ifdef Q_OS_WIN -#include -#endif - -PowerManagement::PowerManagement(QObject *parent) : QObject(parent), m_busy(false) -{ -#if (defined(Q_OS_UNIX) && !defined(Q_OS_MAC)) && defined(QT_DBUS_LIB) - m_inhibitor = new PowerManagementInhibitor(this); -#endif -} - -PowerManagement::~PowerManagement() -{ -} - -void PowerManagement::setActivityState(bool busy) -{ - if (busy) setBusy(); - else setIdle(); -} - -void PowerManagement::setBusy() -{ - if (m_busy) return; - m_busy = true; - -#ifdef Q_OS_WIN - SetThreadExecutionState(ES_CONTINUOUS | ES_SYSTEM_REQUIRED); -#elif (defined(Q_OS_UNIX) && !defined(Q_OS_MAC)) && defined(QT_DBUS_LIB) - m_inhibitor->RequestBusy(); -#elif defined(Q_OS_MAC) - IOReturn success = IOPMAssertionCreate(kIOPMAssertionTypeNoIdleSleep, kIOPMAssertionLevelOn, &m_assertionID); - if (success != kIOReturnSuccess) m_busy = false; -#endif -} - -void PowerManagement::setIdle() -{ - if (!m_busy) return; - m_busy = false; - -#ifdef Q_OS_WIN - SetThreadExecutionState(ES_CONTINUOUS); -#elif (defined(Q_OS_UNIX) && !defined(Q_OS_MAC)) && defined(QT_DBUS_LIB) - m_inhibitor->RequestIdle(); -#elif defined(Q_OS_MAC) - IOPMAssertionRelease(m_assertionID); -#endif -} diff --git a/src/gui/powermanagement/powermanagement.h b/src/gui/powermanagement/powermanagement.h deleted file mode 100644 index 435f76a2f..000000000 --- a/src/gui/powermanagement/powermanagement.h +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Bittorrent Client using Qt4 and libtorrent. - * Copyright (C) 2011 Vladimir Golovnev - * - * 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 POWERMANAGEMENT_H -#define POWERMANAGEMENT_H - -#include - -#ifdef Q_OS_MAC -// Require Mac OS X >= 10.5 -#include -#endif - -#if (defined(Q_OS_UNIX) && !defined(Q_OS_MAC)) && defined(QT_DBUS_LIB) -// Require DBus -class PowerManagementInhibitor; -#endif - -class PowerManagement : public QObject -{ - Q_OBJECT - -public: - PowerManagement(QObject *parent = 0); - virtual ~PowerManagement(); - - void setActivityState(bool busy); - -private: - bool m_busy; - - void setBusy(); - void setIdle(); - -#if (defined(Q_OS_UNIX) && !defined(Q_OS_MAC)) && defined(QT_DBUS_LIB) - PowerManagementInhibitor *m_inhibitor; -#endif -#ifdef Q_OS_MAC - IOPMAssertionID m_assertionID; -#endif -}; - -#endif // POWERMANAGEMENT_H diff --git a/src/gui/powermanagement/powermanagement.pri b/src/gui/powermanagement/powermanagement.pri deleted file mode 100644 index d5834d935..000000000 --- a/src/gui/powermanagement/powermanagement.pri +++ /dev/null @@ -1,9 +0,0 @@ -INCLUDEPATH += $$PWD - -HEADERS += $$PWD/powermanagement.h -SOURCES += $$PWD/powermanagement.cpp - -unix:!macx:dbus { - HEADERS += $$PWD/powermanagement_x11.h - SOURCES += $$PWD/powermanagement_x11.cpp -} diff --git a/src/gui/powermanagement/powermanagement_x11.cpp b/src/gui/powermanagement/powermanagement_x11.cpp deleted file mode 100644 index 14958a62f..000000000 --- a/src/gui/powermanagement/powermanagement_x11.cpp +++ /dev/null @@ -1,185 +0,0 @@ -/* - * Bittorrent Client using Qt4 and libtorrent. - * Copyright (C) 2011 Vladimir Golovnev - * - * 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 -#include -#include -#include - -#include "powermanagement_x11.h" - -PowerManagementInhibitor::PowerManagementInhibitor(QObject *parent) : QObject(parent) -{ - if (!QDBusConnection::sessionBus().isConnected()) - { - qDebug("D-Bus: Could not connect to session bus"); - m_state = error; - } - else - { - m_state = idle; - } - - m_intended_state = idle; - m_cookie = 0; - m_use_gsm = false; -} - -PowerManagementInhibitor::~PowerManagementInhibitor() -{ -} - -void PowerManagementInhibitor::RequestIdle() -{ - m_intended_state = idle; - if (m_state == error || m_state == idle || m_state == request_idle || m_state == request_busy) - return; - - qDebug("D-Bus: PowerManagementInhibitor: Requesting idle"); - - QDBusMessage call; - if (!m_use_gsm) - call = QDBusMessage::createMethodCall( - "org.freedesktop.PowerManagement", - "/org/freedesktop/PowerManagement/Inhibit", - "org.freedesktop.PowerManagement.Inhibit", - "UnInhibit"); - else - call = QDBusMessage::createMethodCall( - "org.gnome.SessionManager", - "/org/gnome/SessionManager", - "org.gnome.SessionManager", - "Uninhibit"); - - m_state = request_idle; - - QList args; - args << m_cookie; - call.setArguments(args); - - QDBusPendingCall pcall = QDBusConnection::sessionBus().asyncCall(call, 1000); - QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pcall, this); - connect(watcher, SIGNAL(finished(QDBusPendingCallWatcher*)), - this, SLOT(OnAsyncReply(QDBusPendingCallWatcher*))); -} - - -void PowerManagementInhibitor::RequestBusy() -{ - m_intended_state = busy; - if (m_state == error || m_state == busy || m_state == request_busy || m_state == request_idle) - return; - - qDebug("D-Bus: PowerManagementInhibitor: Requesting busy"); - - QDBusMessage call; - if (!m_use_gsm) - call = QDBusMessage::createMethodCall( - "org.freedesktop.PowerManagement", - "/org/freedesktop/PowerManagement/Inhibit", - "org.freedesktop.PowerManagement.Inhibit", - "Inhibit"); - else - call = QDBusMessage::createMethodCall( - "org.gnome.SessionManager", - "/org/gnome/SessionManager", - "org.gnome.SessionManager", - "Inhibit"); - - m_state = request_busy; - - QList args; - args << "qBittorrent"; - if (m_use_gsm) args << 0u; - args << "Active torrents are presented"; - if (m_use_gsm) args << 8u; - call.setArguments(args); - - QDBusPendingCall pcall = QDBusConnection::sessionBus().asyncCall(call, 1000); - QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pcall, this); - connect(watcher, SIGNAL(finished(QDBusPendingCallWatcher*)), - this, SLOT(OnAsyncReply(QDBusPendingCallWatcher*))); -} - -void PowerManagementInhibitor::OnAsyncReply(QDBusPendingCallWatcher *call) -{ - if (m_state == request_idle) - { - QDBusPendingReply<> reply = *call; - - if (reply.isError()) - { - qDebug("D-Bus: Reply: Error: %s", qPrintable(reply.error().message())); - m_state = error; - } - else - { - m_state = idle; - qDebug("D-Bus: PowerManagementInhibitor: Request successful"); - if (m_intended_state == busy) RequestBusy(); - } - } - else if (m_state == request_busy) - { - QDBusPendingReply reply = *call; - - if (reply.isError()) - { - qDebug("D-Bus: Reply: Error: %s", qPrintable(reply.error().message())); - - if (!m_use_gsm) - { - qDebug("D-Bus: Falling back to org.gnome.SessionManager"); - m_use_gsm = true; - m_state = idle; - if (m_intended_state == busy) - RequestBusy(); - } - else - { - m_state = error; - } - } - else - { - m_state = busy; - m_cookie = reply.value(); - qDebug("D-Bus: PowerManagementInhibitor: Request successful, cookie is %d", m_cookie); - if (m_intended_state == idle) RequestIdle(); - } - } - else - { - qDebug("D-Bus: Unexpected reply in state %d", m_state); - m_state = error; - } - - call->deleteLater(); -} diff --git a/src/gui/powermanagement/powermanagement_x11.h b/src/gui/powermanagement/powermanagement_x11.h deleted file mode 100644 index 963d57581..000000000 --- a/src/gui/powermanagement/powermanagement_x11.h +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Bittorrent Client using Qt4 and libtorrent. - * Copyright (C) 2011 Vladimir Golovnev - * - * 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 POWERMANAGEMENTINHIBITOR_H -#define POWERMANAGEMENTINHIBITOR_H - -#include - -QT_BEGIN_NAMESPACE -class QDBusPendingCallWatcher; -QT_END_NAMESPACE - -class PowerManagementInhibitor : public QObject -{ - Q_OBJECT - -public: - PowerManagementInhibitor(QObject *parent = 0); - virtual ~PowerManagementInhibitor(); - - void RequestIdle(); - void RequestBusy(); - -private slots: - void OnAsyncReply(QDBusPendingCallWatcher *call); - -private: - enum _state - { - error, - idle, - request_busy, - busy, - request_idle - }; - - enum _state m_state; - enum _state m_intended_state; - unsigned int m_cookie; - - bool m_use_gsm; -}; - -#endif // POWERMANAGEMENTINHIBITOR_H diff --git a/src/gui/preview.ui b/src/gui/preview.ui deleted file mode 100644 index 7405b3e0f..000000000 --- a/src/gui/preview.ui +++ /dev/null @@ -1,99 +0,0 @@ - - - preview - - - - 0 - 0 - 462 - 256 - - - - Preview selection - - - - - - The following files support previewing, please select one of them: - - - true - - - - - - - true - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - Preview - - - - - - - Cancel - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - - - cancelButton - clicked() - preview - reject() - - - 296 - 245 - - - 179 - 282 - - - - - diff --git a/src/gui/previewlistdelegate.h b/src/gui/previewlistdelegate.h deleted file mode 100644 index 6dfb085ce..000000000 --- a/src/gui/previewlistdelegate.h +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Bittorrent Client using Qt4 and libtorrent. - * Copyright (C) 2006 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 PREVIEWLISTDELEGATE_H -#define PREVIEWLISTDELEGATE_H - -#include -#include -#include -#include -#include -#include -#include "base/utils/misc.h" -#include "base/utils/string.h" -#include "previewselect.h" - -#ifdef Q_OS_WIN -#include -#endif - -class PreviewListDelegate: public QItemDelegate { - Q_OBJECT - - public: - PreviewListDelegate(QObject *parent=0) : QItemDelegate(parent) {} - - ~PreviewListDelegate() {} - - void paint(QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index) const { - painter->save(); - QStyleOptionViewItem opt = QItemDelegate::setOptions(index, option); - - switch(index.column()) { - case PreviewSelect::SIZE: - QItemDelegate::drawBackground(painter, opt, index); - QItemDelegate::drawDisplay(painter, opt, option.rect, Utils::Misc::friendlyUnit(index.data().toLongLong())); - break; - case PreviewSelect::PROGRESS:{ - QStyleOptionProgressBar newopt; - qreal progress = index.data().toDouble()*100.; - newopt.rect = opt.rect; - newopt.text = ((progress == 100.0) ? QString("100%") : Utils::String::fromDouble(progress, 1) + "%"); - newopt.progress = static_cast(progress); - newopt.maximum = 100; - newopt.minimum = 0; - newopt.state |= QStyle::State_Enabled; - newopt.textVisible = true; -#ifndef Q_OS_WIN - QApplication::style()->drawControl(QStyle::CE_ProgressBar, &newopt, painter); -#else - // XXX: To avoid having the progress text on the right of the bar - QProxyStyle st("fusion"); - st.drawControl(QStyle::CE_ProgressBar, &newopt, painter, 0); -#endif - break; - } - default: - QItemDelegate::paint(painter, option, index); - } - painter->restore(); - } - - QWidget* createEditor(QWidget*, const QStyleOptionViewItem &, const QModelIndex &) const { - // No editor here - return 0; - } -}; - -#endif diff --git a/src/gui/previewselect.cpp b/src/gui/previewselect.cpp deleted file mode 100644 index e9cf03be4..000000000 --- a/src/gui/previewselect.cpp +++ /dev/null @@ -1,136 +0,0 @@ -/* - * Bittorrent Client using Qt 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. - */ - -#include "previewselect.h" - -#include -#include -#include -#include -#include - -#include "base/preferences.h" -#include "base/utils/fs.h" -#include "base/utils/misc.h" -#include "previewlistdelegate.h" - -PreviewSelect::PreviewSelect(QWidget* parent, BitTorrent::TorrentHandle *const torrent) - : QDialog(parent) - , m_torrent(torrent) -{ - setupUi(this); - setAttribute(Qt::WA_DeleteOnClose); - Preferences *const pref = Preferences::instance(); - // Preview list - m_previewListModel = new QStandardItemModel(0, NB_COLUMNS); - m_previewListModel->setHeaderData(NAME, Qt::Horizontal, tr("Name")); - m_previewListModel->setHeaderData(SIZE, Qt::Horizontal, tr("Size")); - m_previewListModel->setHeaderData(PROGRESS, Qt::Horizontal, tr("Progress")); - - // This hack fixes reordering of first column with Qt5. - // https://github.com/qtproject/qtbase/commit/e0fc088c0c8bc61dbcaf5928b24986cd61a22777 - QTableView unused; - unused.setVerticalHeader(previewList->header()); - previewList->header()->setParent(previewList); - unused.setVerticalHeader(new QHeaderView(Qt::Horizontal)); - - previewList->setModel(m_previewListModel); - previewList->hideColumn(FILE_INDEX); - m_listDelegate = new PreviewListDelegate(this); - previewList->setItemDelegate(m_listDelegate); - previewList->header()->resizeSection(0, 200); - previewList->setAlternatingRowColors(pref->useAlternatingRowColors()); - // Fill list in - QVector fp = torrent->filesProgress(); - int nbFiles = torrent->filesCount(); - for (int i = 0; i < nbFiles; ++i) { - QString fileName = torrent->fileName(i); - if (fileName.endsWith(QB_EXT)) - fileName.chop(4); - QString extension = Utils::Fs::fileExtension(fileName).toUpper(); - if (Utils::Misc::isPreviewable(extension)) { - int row = m_previewListModel->rowCount(); - m_previewListModel->insertRow(row); - m_previewListModel->setData(m_previewListModel->index(row, NAME), QVariant(fileName)); - m_previewListModel->setData(m_previewListModel->index(row, SIZE), QVariant(torrent->fileSize(i))); - m_previewListModel->setData(m_previewListModel->index(row, PROGRESS), QVariant(fp[i])); - m_previewListModel->setData(m_previewListModel->index(row, FILE_INDEX), QVariant(i)); - } - } - - if (m_previewListModel->rowCount() == 0) { - QMessageBox::critical(this->parentWidget(), tr("Preview impossible"), tr("Sorry, we can't preview this file")); - close(); - } - connect(this, SIGNAL(readyToPreviewFile(QString)), parent, SLOT(previewFile(QString))); - m_previewListModel->sort(NAME); - previewList->header()->setSortIndicator(0, Qt::AscendingOrder); - previewList->selectionModel()->select(m_previewListModel->index(0, NAME), QItemSelectionModel::Select | QItemSelectionModel::Rows); - - if (m_previewListModel->rowCount() == 1) { - qDebug("Torrent file only contains one file, no need to display selection dialog before preview"); - // Only one file : no choice - on_previewButton_clicked(); - } - else { - qDebug("Displaying media file selection dialog for preview"); - show(); - } -} - -PreviewSelect::~PreviewSelect() -{ - delete m_previewListModel; - delete m_listDelegate; -} - - -void PreviewSelect::on_previewButton_clicked() -{ - QModelIndexList selectedIndexes = previewList->selectionModel()->selectedRows(FILE_INDEX); - if (selectedIndexes.size() == 0) return; - - // Flush data - m_torrent->flushCache(); - - QStringList absolutePaths(m_torrent->absoluteFilePaths()); - // Only one file should be selected - QString path = absolutePaths.at(selectedIndexes.at(0).data().toInt()); - // File - if (QFile::exists(path)) - emit readyToPreviewFile(path); - else - QMessageBox::critical(this->parentWidget(), tr("Preview impossible"), tr("Sorry, we can't preview this file")); - - close(); -} - -void PreviewSelect::on_cancelButton_clicked() -{ - close(); -} diff --git a/src/gui/previewselect.h b/src/gui/previewselect.h deleted file mode 100644 index 0f1db209c..000000000 --- a/src/gui/previewselect.h +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Bittorrent Client using Qt 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. - */ - -#ifndef PREVIEWSELECT_H -#define PREVIEWSELECT_H - -#include -#include - -#include "base/bittorrent/torrenthandle.h" -#include "ui_preview.h" - -class QStandardItemModel; - -class PreviewListDelegate; - -class PreviewSelect: public QDialog, private Ui::preview -{ - Q_OBJECT - -public: - enum PreviewColumn - { - NAME, - SIZE, - PROGRESS, - FILE_INDEX, - - NB_COLUMNS - }; - - PreviewSelect(QWidget* parent, BitTorrent::TorrentHandle *const torrent); - ~PreviewSelect(); - -signals: - void readyToPreviewFile(QString) const; - -protected slots: - void on_previewButton_clicked(); - void on_cancelButton_clicked(); - -private: - QStandardItemModel *m_previewListModel; - PreviewListDelegate *m_listDelegate; - BitTorrent::TorrentHandle *const m_torrent; -}; - -#endif // PREVIEWSELECT_H diff --git a/src/gui/programupdater.cpp b/src/gui/programupdater.cpp deleted file mode 100644 index e4ce2597e..000000000 --- a/src/gui/programupdater.cpp +++ /dev/null @@ -1,172 +0,0 @@ -/* - * Bittorrent Client using Qt4 and libtorrent. - * Copyright (C) 2010 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 -#include -#include -#include -#include - -#include "base/utils/fs.h" -#include "base/net/downloadmanager.h" -#include "base/net/downloadhandler.h" -#include "programupdater.h" - -namespace -{ - const QString RSS_URL("https://www.fosshub.com/software/feedqBittorent"); - -#ifdef Q_OS_MAC - const QString OS_TYPE("Mac OS X"); -#elif defined(Q_OS_WIN) && (defined(__x86_64__) || defined(_M_X64)) - const QString OS_TYPE("Windows x64"); -#else - const QString OS_TYPE("Windows"); -#endif - - QString getStringValue(QXmlStreamReader &xml); -} - -ProgramUpdater::ProgramUpdater(QObject *parent, bool invokedByUser) - : QObject(parent) - , m_invokedByUser(invokedByUser) -{ -} - -void ProgramUpdater::checkForUpdates() -{ - Net::DownloadHandler *handler = Net::DownloadManager::instance()->downloadUrl( - RSS_URL, false, 0, false, - // Don't change this User-Agent. In case our updater goes haywire, - // the filehost can identify it and contact us. - "qBittorrent/" QBT_VERSION_2 " ProgramUpdater (www.qbittorrent.org)"); - connect(handler, SIGNAL(downloadFinished(QString,QByteArray)), SLOT(rssDownloadFinished(QString,QByteArray))); - connect(handler, SIGNAL(downloadFailed(QString,QString)), SLOT(rssDownloadFailed(QString,QString))); -} - -void ProgramUpdater::rssDownloadFinished(const QString &url, const QByteArray &data) -{ - Q_UNUSED(url); - - qDebug("Finished downloading the new qBittorrent updates RSS"); - QString version; - - QXmlStreamReader xml(data); - bool inItem = false; - QString updateLink; - QString type; - - while (!xml.atEnd()) { - xml.readNext(); - - if (xml.isStartElement()) { - if (xml.name() == "item") - inItem = true; - else if (inItem && xml.name() == "link") - updateLink = getStringValue(xml); - else if (inItem && xml.name() == "type") - type = getStringValue(xml); - else if (inItem && xml.name() == "version") - version = getStringValue(xml); - } - else if (xml.isEndElement()) { - if (inItem && xml.name() == "item") { - if (type.compare(OS_TYPE, Qt::CaseInsensitive) == 0) { - qDebug("The last update available is %s", qPrintable(version)); - if (!version.isEmpty()) { - qDebug("Detected version is %s", qPrintable(version)); - if (isVersionMoreRecent(version)) - m_updateUrl = updateLink; - } - break; - } - - inItem = false; - updateLink.clear(); - type.clear(); - version.clear(); - } - } - } - - emit updateCheckFinished(!m_updateUrl.isEmpty(), version, m_invokedByUser); -} - -void ProgramUpdater::rssDownloadFailed(const QString &url, const QString &error) -{ - Q_UNUSED(url); - - qDebug() << "Downloading the new qBittorrent updates RSS failed:" << error; - emit updateCheckFinished(false, QString(), m_invokedByUser); -} - -void ProgramUpdater::updateProgram() -{ - Q_ASSERT(!m_updateUrl.isEmpty()); - QDesktopServices::openUrl(m_updateUrl); - return; -} - -bool ProgramUpdater::isVersionMoreRecent(const QString &remoteVersion) const -{ - QRegExp regVer("([0-9.]+)"); - if (regVer.indexIn(QBT_VERSION) >= 0) { - QString localVersion = regVer.cap(1); - qDebug() << Q_FUNC_INFO << "local version:" << localVersion << "/" << QBT_VERSION; - QStringList remoteParts = remoteVersion.split('.'); - QStringList localParts = localVersion.split('.'); - for (int i = 0; i localParts[i].toInt()) - return true; - if (remoteParts[i].toInt() < localParts[i].toInt()) - return false; - } - // Compared parts were equal, if remote version is longer, then it's more recent (2.9.2.1 > 2.9.2) - if (remoteParts.size() > localParts.size()) - return true; - // versions are equal, check if the local version is a development release, in which case it is older (2.9.2beta < 2.9.2) - QRegExp regDevel("(alpha|beta|rc)"); - if (regDevel.indexIn(QBT_VERSION) >= 0) - return true; - } - return false; -} - -namespace -{ - QString getStringValue(QXmlStreamReader &xml) - { - xml.readNext(); - if (xml.isCharacters() && !xml.isWhitespace()) - return xml.text().toString(); - - return QString(); - } -} diff --git a/src/gui/programupdater.h b/src/gui/programupdater.h deleted file mode 100644 index cda228bbb..000000000 --- a/src/gui/programupdater.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Bittorrent Client using Qt4 and libtorrent. - * Copyright (C) 2010 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 PROGRAMUPDATER_H -#define PROGRAMUPDATER_H - -#include -#include - -class ProgramUpdater: public QObject -{ - Q_OBJECT - -public: - explicit ProgramUpdater(QObject *parent = 0, bool invokedByUser = false); - - void checkForUpdates(); - void updateProgram(); - -signals: - void updateCheckFinished(bool updateAvailable, QString version, bool invokedByUser); - -private slots: - void rssDownloadFinished(const QString &url, const QByteArray &data); - void rssDownloadFailed(const QString &url, const QString &error); - -private: - bool isVersionMoreRecent(const QString &remoteVersion) const; - - QString m_updateUrl; - bool m_invokedByUser; -}; - -#endif // PROGRAMUPDATER_H diff --git a/src/gui/properties/CMakeLists.txt b/src/gui/properties/CMakeLists.txt deleted file mode 100644 index b5c134951..000000000 --- a/src/gui/properties/CMakeLists.txt +++ /dev/null @@ -1,47 +0,0 @@ -include_directories( -${CMAKE_CURRENT_BINARY_DIR} -${CMAKE_CURRENT_SOURCE_DIR} -../lineedit/src/ -) - -set(QBT_PROPERTIES_FORMS -propertieswidget.ui -trackersadditiondlg.ui -peersadditiondlg.ui -) - -set(QBT_PROPERTIES_HEADERS -propertieswidget.h -peerlistwidget.h -proplistdelegate.h -trackerlist.h -downloadedpiecesbar.h -piecesbar.h -peerlistdelegate.h -peerlistsortmodel.h -peersadditiondlg.h -trackersadditiondlg.h -pieceavailabilitybar.h -proptabbar.h -speedwidget.h -speedplotview.h -) - -set(QBT_PROPERTIES_SOURCES -propertieswidget.cpp -proplistdelegate.cpp -peerlistwidget.cpp -trackerlist.cpp -peersadditiondlg.cpp -downloadedpiecesbar.cpp -piecesbar.cpp -trackersadditiondlg.cpp -pieceavailabilitybar.cpp -proptabbar.cpp -speedwidget.cpp -speedplotview.cpp -) - -add_library(qbt_properties STATIC ${QBT_PROPERTIES_HEADERS} ${QBT_PROPERTIES_SOURCES} ${QBT_PROPERTIES_FORMS}) -target_link_libraries(qbt_properties qbt_base) -target_link_libraries(qbt_properties Qt5::Widgets Qt5::Concurrent) diff --git a/src/gui/properties/downloadedpiecesbar.cpp b/src/gui/properties/downloadedpiecesbar.cpp deleted file mode 100644 index 4ecdb82f9..000000000 --- a/src/gui/properties/downloadedpiecesbar.cpp +++ /dev/null @@ -1,180 +0,0 @@ -/* - * Bittorrent Client using Qt4 and libtorrent. - * Copyright (C) 2006 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 "downloadedpiecesbar.h" - -#include - -#include - -DownloadedPiecesBar::DownloadedPiecesBar(QWidget *parent) - : base {parent} - , m_dlPieceColor {0, 0xd0, 0} -{ -} - -QVector DownloadedPiecesBar::bitfieldToFloatVector(const QBitArray &vecin, int reqSize) -{ - QVector result(reqSize, 0.0); - if (vecin.isEmpty()) return result; - - const float ratio = vecin.size() / static_cast(reqSize); - - // simple linear transformation algorithm - // for example: - // image.x(0) = pieces.x(0.0 >= x < 1.7) - // image.x(1) = pieces.x(1.7 >= x < 3.4) - - for (int x = 0; x < reqSize; ++x) { - // R - real - const float fromR = x * ratio; - const float toR = (x + 1) * ratio; - - // C - integer - int fromC = fromR; // std::floor not needed - int toC = std::ceil(toR); - if (toC > vecin.size()) - --toC; - - // position in pieces table - int x2 = fromC; - - // little speed up for really big pieces table, 10K+ size - const int toCMinusOne = toC - 1; - - // value in returned vector - float value = 0; - - // case when calculated range is (15.2 >= x < 15.7) - if (x2 == toCMinusOne) { - if (vecin[x2]) - value += ratio; - ++x2; - } - // case when (15.2 >= x < 17.8) - else { - // subcase (15.2 >= x < 16) - if (x2 != fromR) { - if (vecin[x2]) - value += 1.0 - (fromR - fromC); - ++x2; - } - - // subcase (16 >= x < 17) - for (; x2 < toCMinusOne; ++x2) - if (vecin[x2]) - value += 1.0; - - // subcase (17 >= x < 17.8) - if (x2 == toCMinusOne) { - if (vecin[x2]) - value += 1.0 - (toC - toR); - ++x2; - } - } - - // normalization <0, 1> - value /= ratio; - - // float precision sometimes gives > 1, because in not possible to store irrational numbers - value = qMin(value, 1.0f); - - result[x] = value; - } - - return result; -} - -bool DownloadedPiecesBar::updateImage(QImage &image) -{ - // qDebug() << "updateImage"; - QImage image2(width() - 2 * borderWidth, 1, QImage::Format_RGB888); - if (image2.isNull()) { - qDebug() << "QImage image2() allocation failed, width():" << width(); - return false; - } - - if (m_pieces.isEmpty()) { - image2.fill(Qt::white); - image = image2; - return true; - } - - QVector scaled_pieces = bitfieldToFloatVector(m_pieces, image2.width()); - QVector scaled_pieces_dl = bitfieldToFloatVector(m_downloadedPieces, image2.width()); - - // filling image - for (int x = 0; x < scaled_pieces.size(); ++x) { - float pieces2_val = scaled_pieces.at(x); - float pieces2_val_dl = scaled_pieces_dl.at(x); - if (pieces2_val_dl != 0) { - float fill_ratio = pieces2_val + pieces2_val_dl; - float ratio = pieces2_val_dl / fill_ratio; - - QRgb mixedColor = mixTwoColors(pieceColor().rgb(), m_dlPieceColor.rgb(), ratio); - mixedColor = mixTwoColors(backgroundColor().rgb(), mixedColor, fill_ratio); - - image2.setPixel(x, 0, mixedColor); - } - else { - image2.setPixel(x, 0, pieceColors()[pieces2_val * 255]); - } - } - image = image2; - return true; -} - -void DownloadedPiecesBar::setProgress(const QBitArray &pieces, const QBitArray &downloadedPieces) -{ - m_pieces = pieces; - m_downloadedPieces = downloadedPieces; - - requestImageUpdate(); -} - -void DownloadedPiecesBar::setColors(const QColor &background, const QColor &border, const QColor &complete, const QColor &incomplete) -{ - m_dlPieceColor = incomplete; - base::setColors(background, border, complete); -} - -void DownloadedPiecesBar::clear() -{ - m_pieces.clear(); - m_downloadedPieces.clear(); - base::clear(); -} - -QString DownloadedPiecesBar::simpleToolTipText() const -{ - return tr("White: Missing pieces") + '\n' - + tr("Green: Partial pieces") + '\n' - + tr("Blue: Completed pieces") + '\n'; -} diff --git a/src/gui/properties/downloadedpiecesbar.h b/src/gui/properties/downloadedpiecesbar.h deleted file mode 100644 index 137c0723d..000000000 --- a/src/gui/properties/downloadedpiecesbar.h +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Bittorrent Client using Qt4 and libtorrent. - * Copyright (C) 2006 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 DOWNLOADEDPIECESBAR_H -#define DOWNLOADEDPIECESBAR_H - -#include -#include -#include - -#include "piecesbar.h" - -class DownloadedPiecesBar: public PiecesBar -{ - using base = PiecesBar; - Q_OBJECT - Q_DISABLE_COPY(DownloadedPiecesBar) - -public: - DownloadedPiecesBar(QWidget *parent); - - void setProgress(const QBitArray &pieces, const QBitArray &downloadedPieces); - - void setColors(const QColor &background, const QColor &border, const QColor &complete, const QColor &incomplete); - - // PiecesBar interface - void clear() override; - -private: - // scale bitfield vector to float vector - QVector bitfieldToFloatVector(const QBitArray &vecin, int reqSize); - virtual bool updateImage(QImage &image) override; - QString simpleToolTipText() const override; - - // incomplete piece color - QColor m_dlPieceColor; - // last used bitfields, uses to better resize redraw - // TODO: make a diff pieces to new pieces and update only changed pixels, speedup when update > 20x faster - QBitArray m_pieces; - QBitArray m_downloadedPieces; -}; - -#endif // DOWNLOADEDPIECESBAR_H diff --git a/src/gui/properties/peerlistdelegate.h b/src/gui/properties/peerlistdelegate.h deleted file mode 100644 index bfd79bcbc..000000000 --- a/src/gui/properties/peerlistdelegate.h +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Bittorrent Client using Qt4 and libtorrent. - * Copyright (C) 2006 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 PEERLISTDELEGATE_H -#define PEERLISTDELEGATE_H - -#include -#include - -#include "base/preferences.h" -#include "base/utils/misc.h" -#include "base/utils/string.h" - -class PeerListDelegate: public QItemDelegate -{ - Q_OBJECT - -public: - enum PeerListColumns - { - COUNTRY, - IP, - PORT, - CONNECTION, - FLAGS, - CLIENT, - PROGRESS, - DOWN_SPEED, - UP_SPEED, - TOT_DOWN, - TOT_UP, - RELEVANCE, - DOWNLOADING_PIECE, - IP_HIDDEN, - - COL_COUNT - }; - -public: - PeerListDelegate(QObject *parent) : QItemDelegate(parent) {} - - ~PeerListDelegate() {} - - void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override - { - painter->save(); - - const bool hideValues = Preferences::instance()->getHideZeroValues(); - QStyleOptionViewItem opt = QItemDelegate::setOptions(index, option); - QItemDelegate::drawBackground(painter, opt, index); - - switch (index.column()) { - case PORT: { - opt.displayAlignment = Qt::AlignRight | Qt::AlignVCenter; - QItemDelegate::drawDisplay(painter, opt, option.rect, index.data().toString()); - } - break; - case TOT_DOWN: - case TOT_UP: { - qlonglong size = index.data().toLongLong(); - if (hideValues && (size <= 0)) - break; - opt.displayAlignment = Qt::AlignRight | Qt::AlignVCenter; - QItemDelegate::drawDisplay(painter, opt, option.rect, Utils::Misc::friendlyUnit(size)); - } - break; - case DOWN_SPEED: - case UP_SPEED: { - qreal speed = index.data().toDouble(); - if (speed <= 0.0) - break; - opt.displayAlignment = Qt::AlignRight | Qt::AlignVCenter; - QItemDelegate::drawDisplay(painter, opt, opt.rect, Utils::Misc::friendlyUnit(speed, true)); - } - break; - case PROGRESS: - case RELEVANCE: { - qreal progress = index.data().toDouble(); - opt.displayAlignment = Qt::AlignRight | Qt::AlignVCenter; - QItemDelegate::drawDisplay(painter, opt, opt.rect, Utils::String::fromDouble(progress * 100.0, 1) + "%"); - } - break; - default: - QItemDelegate::paint(painter, option, index); - } - - painter->restore(); - } - - QWidget *createEditor(QWidget *, const QStyleOptionViewItem &, const QModelIndex &) const override - { - // No editor here - return nullptr; - } -}; - -#endif // PEERLISTDELEGATE_H diff --git a/src/gui/properties/peerlistsortmodel.h b/src/gui/properties/peerlistsortmodel.h deleted file mode 100644 index a19d9f958..000000000 --- a/src/gui/properties/peerlistsortmodel.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Bittorrent Client using Qt 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. - */ - -#ifndef PEERLISTSORTMODEL_H -#define PEERLISTSORTMODEL_H - -#include -#include - -#include "peerlistdelegate.h" - -class PeerListSortModel: public QSortFilterProxyModel -{ - Q_OBJECT - -public: - PeerListSortModel(QObject *parent = 0) - : QSortFilterProxyModel(parent) - { - } - -protected: - bool lessThan(const QModelIndex &left, const QModelIndex &right) const - { - switch (sortColumn()) { - case PeerListDelegate::IP: - case PeerListDelegate::CLIENT: { - QString vL = left.data().toString(); - QString vR = right.data().toString(); - return Utils::String::naturalCompareCaseInsensitive(vL, vR); - } - }; - - return QSortFilterProxyModel::lessThan(left, right); - } -}; - -#endif // PEERLISTSORTMODEL_H diff --git a/src/gui/properties/peerlistwidget.cpp b/src/gui/properties/peerlistwidget.cpp deleted file mode 100644 index 1a3ad29a0..000000000 --- a/src/gui/properties/peerlistwidget.cpp +++ /dev/null @@ -1,473 +0,0 @@ -/* - * Bittorrent Client using Qt4 and libtorrent. - * Copyright (C) 2006 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 "peerlistwidget.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "base/net/reverseresolution.h" -#include "base/bittorrent/torrenthandle.h" -#include "base/bittorrent/peerinfo.h" -#include "base/preferences.h" -#include "base/logger.h" -#include "base/unicodestrings.h" -#include "propertieswidget.h" -#include "base/net/geoipmanager.h" -#include "peersadditiondlg.h" -#include "speedlimitdlg.h" -#include "guiiconprovider.h" -#include "peerlistdelegate.h" -#include "peerlistsortmodel.h" - -PeerListWidget::PeerListWidget(PropertiesWidget *parent) - : QTreeView(parent) - , m_properties(parent) -{ - // Load settings - loadSettings(); - // Visual settings - setUniformRowHeights(true); - setRootIsDecorated(false); - setItemsExpandable(false); - setAllColumnsShowFocus(true); - setSelectionMode(QAbstractItemView::ExtendedSelection); - header()->setStretchLastSection(false); - // List Model - m_listModel = new QStandardItemModel(0, PeerListDelegate::COL_COUNT, this); - m_listModel->setHeaderData(PeerListDelegate::COUNTRY, Qt::Horizontal, tr("Country")); // Country flag column - m_listModel->setHeaderData(PeerListDelegate::IP, Qt::Horizontal, tr("IP")); - m_listModel->setHeaderData(PeerListDelegate::PORT, Qt::Horizontal, tr("Port")); - m_listModel->setHeaderData(PeerListDelegate::FLAGS, Qt::Horizontal, tr("Flags")); - m_listModel->setHeaderData(PeerListDelegate::CONNECTION, Qt::Horizontal, tr("Connection")); - m_listModel->setHeaderData(PeerListDelegate::CLIENT, Qt::Horizontal, tr("Client", "i.e.: Client application")); - m_listModel->setHeaderData(PeerListDelegate::PROGRESS, Qt::Horizontal, tr("Progress", "i.e: % downloaded")); - m_listModel->setHeaderData(PeerListDelegate::DOWN_SPEED, Qt::Horizontal, tr("Down Speed", "i.e: Download speed")); - m_listModel->setHeaderData(PeerListDelegate::UP_SPEED, Qt::Horizontal, tr("Up Speed", "i.e: Upload speed")); - m_listModel->setHeaderData(PeerListDelegate::TOT_DOWN, Qt::Horizontal, tr("Downloaded", "i.e: total data downloaded")); - m_listModel->setHeaderData(PeerListDelegate::TOT_UP, Qt::Horizontal, tr("Uploaded", "i.e: total data uploaded")); - m_listModel->setHeaderData(PeerListDelegate::RELEVANCE, Qt::Horizontal, tr("Relevance", "i.e: How relevant this peer is to us. How many pieces it has that we don't.")); - m_listModel->setHeaderData(PeerListDelegate::DOWNLOADING_PIECE, Qt::Horizontal, tr("Files", "i.e. files that are being downloaded right now")); - // Set header text alignment - m_listModel->setHeaderData(PeerListDelegate::PORT, Qt::Horizontal, QVariant(Qt::AlignRight | Qt::AlignVCenter), Qt::TextAlignmentRole); - m_listModel->setHeaderData(PeerListDelegate::PROGRESS, Qt::Horizontal, QVariant(Qt::AlignRight | Qt::AlignVCenter), Qt::TextAlignmentRole); - m_listModel->setHeaderData(PeerListDelegate::DOWN_SPEED, Qt::Horizontal, QVariant(Qt::AlignRight | Qt::AlignVCenter), Qt::TextAlignmentRole); - m_listModel->setHeaderData(PeerListDelegate::UP_SPEED, Qt::Horizontal, QVariant(Qt::AlignRight | Qt::AlignVCenter), Qt::TextAlignmentRole); - m_listModel->setHeaderData(PeerListDelegate::TOT_DOWN, Qt::Horizontal, QVariant(Qt::AlignRight | Qt::AlignVCenter), Qt::TextAlignmentRole); - m_listModel->setHeaderData(PeerListDelegate::TOT_UP, Qt::Horizontal, QVariant(Qt::AlignRight | Qt::AlignVCenter), Qt::TextAlignmentRole); - m_listModel->setHeaderData(PeerListDelegate::RELEVANCE, Qt::Horizontal, QVariant(Qt::AlignRight | Qt::AlignVCenter), Qt::TextAlignmentRole); - // Proxy model to support sorting without actually altering the underlying model - m_proxyModel = new PeerListSortModel(this); - m_proxyModel->setDynamicSortFilter(true); - m_proxyModel->setSourceModel(m_listModel); - m_proxyModel->setSortCaseSensitivity(Qt::CaseInsensitive); - setModel(m_proxyModel); - hideColumn(PeerListDelegate::IP_HIDDEN); - hideColumn(PeerListDelegate::COL_COUNT); - m_resolveCountries = Preferences::instance()->resolvePeerCountries(); - if (!m_resolveCountries) - hideColumn(PeerListDelegate::COUNTRY); - // Ensure that at least one column is visible at all times - bool atLeastOne = false; - for (unsigned int i = 0; i < PeerListDelegate::IP_HIDDEN; i++) { - if (!isColumnHidden(i)) { - atLeastOne = true; - break; - } - } - if (!atLeastOne) - setColumnHidden(PeerListDelegate::IP, false); - // To also mitigate the above issue, we have to resize each column when - // its size is 0, because explicitly 'showing' the column isn't enough - // in the above scenario. - for (unsigned int i = 0; i < PeerListDelegate::IP_HIDDEN; i++) - if ((columnWidth(i) <= 0) && !isColumnHidden(i)) - resizeColumnToContents(i); - // Context menu - setContextMenuPolicy(Qt::CustomContextMenu); - connect(this, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(showPeerListMenu(QPoint))); - // List delegate - m_listDelegate = new PeerListDelegate(this); - setItemDelegate(m_listDelegate); - // Enable sorting - setSortingEnabled(true); - // IP to Hostname resolver - updatePeerHostNameResolutionState(); - // SIGNAL/SLOT - header()->setContextMenuPolicy(Qt::CustomContextMenu); - connect(header(), SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(displayToggleColumnsMenu(const QPoint&))); - connect(header(), SIGNAL(sectionClicked(int)), SLOT(handleSortColumnChanged(int))); - handleSortColumnChanged(header()->sortIndicatorSection()); - m_copyHotkey = new QShortcut(QKeySequence::Copy, this, SLOT(copySelectedPeers()), 0, Qt::WidgetShortcut); - - // This hack fixes reordering of first column with Qt5. - // https://github.com/qtproject/qtbase/commit/e0fc088c0c8bc61dbcaf5928b24986cd61a22777 - QTableView unused; - unused.setVerticalHeader(this->header()); - this->header()->setParent(this); - unused.setVerticalHeader(new QHeaderView(Qt::Horizontal)); -} - -PeerListWidget::~PeerListWidget() -{ - saveSettings(); - if (m_resolver) - delete m_resolver; -} - -void PeerListWidget::displayToggleColumnsMenu(const QPoint &) -{ - QMenu hideshowColumn(this); - hideshowColumn.setTitle(tr("Column visibility")); - QList actions; - for (int i = 0; i < PeerListDelegate::IP_HIDDEN; ++i) { - if ((i == PeerListDelegate::COUNTRY) && !Preferences::instance()->resolvePeerCountries()) { - actions.append(nullptr); // keep the index in sync - continue; - } - QAction *myAct = hideshowColumn.addAction(m_listModel->headerData(i, Qt::Horizontal, Qt::DisplayRole).toString()); - myAct->setCheckable(true); - myAct->setChecked(!isColumnHidden(i)); - actions.append(myAct); - } - int visibleCols = 0; - for (unsigned int i = 0; i < PeerListDelegate::IP_HIDDEN; i++) { - if (!isColumnHidden(i)) - visibleCols++; - - if (visibleCols > 1) - break; - } - - // Call menu - QAction *act = hideshowColumn.exec(QCursor::pos()); - if (act) { - int col = actions.indexOf(act); - Q_ASSERT(col >= 0); - Q_ASSERT(visibleCols > 0); - if (!isColumnHidden(col) && (visibleCols == 1)) - return; - qDebug("Toggling column %d visibility", col); - setColumnHidden(col, !isColumnHidden(col)); - if (!isColumnHidden(col) && (columnWidth(col) <= 5)) - setColumnWidth(col, 100); - saveSettings(); - } -} - -void PeerListWidget::updatePeerHostNameResolutionState() -{ - if (Preferences::instance()->resolvePeerHostNames()) { - if (!m_resolver) { - m_resolver = new Net::ReverseResolution(this); - connect(m_resolver, SIGNAL(ipResolved(QString,QString)), SLOT(handleResolved(QString,QString))); - loadPeers(m_properties->getCurrentTorrent(), true); - } - } - else if (m_resolver) { - delete m_resolver; - } -} - -void PeerListWidget::updatePeerCountryResolutionState() -{ - if (Preferences::instance()->resolvePeerCountries() != m_resolveCountries) { - m_resolveCountries = !m_resolveCountries; - if (m_resolveCountries) { - loadPeers(m_properties->getCurrentTorrent()); - showColumn(PeerListDelegate::COUNTRY); - if (columnWidth(PeerListDelegate::COUNTRY) <= 0) - resizeColumnToContents(PeerListDelegate::COUNTRY); - } - else { - hideColumn(PeerListDelegate::COUNTRY); - } - } -} - -void PeerListWidget::showPeerListMenu(const QPoint &) -{ - QMenu menu; - bool emptyMenu = true; - BitTorrent::TorrentHandle *const torrent = m_properties->getCurrentTorrent(); - if (!torrent) return; - - // Add Peer Action - QAction *addPeerAct = 0; - if (!torrent->isQueued() && !torrent->isChecking()) { - addPeerAct = menu.addAction(GuiIconProvider::instance()->getIcon("user-group-new"), tr("Add a new peer...")); - emptyMenu = false; - } - QAction *banAct = 0; - QAction *copyPeerAct = 0; - if (!selectionModel()->selectedRows().isEmpty()) { - copyPeerAct = menu.addAction(GuiIconProvider::instance()->getIcon("edit-copy"), tr("Copy IP:port")); - menu.addSeparator(); - banAct = menu.addAction(GuiIconProvider::instance()->getIcon("user-group-delete"), tr("Ban peer permanently")); - emptyMenu = false; - } - if (emptyMenu) return; - QAction *act = menu.exec(QCursor::pos()); - if (act == 0) return; - if (act == addPeerAct) { - QList peersList = PeersAdditionDlg::askForPeers(this); - int peerCount = 0; - foreach (const BitTorrent::PeerAddress &addr, peersList) { - if (torrent->connectPeer(addr)) { - qDebug("Adding peer %s...", qPrintable(addr.ip.toString())); - Logger::instance()->addMessage(tr("Manually adding peer '%1'...").arg(addr.ip.toString())); - peerCount++; - } - else { - Logger::instance()->addMessage(tr("The peer '%1' could not be added to this torrent.").arg(addr.ip.toString()), Log::WARNING); - } - } - if (peerCount < peersList.length()) - QMessageBox::information(this, tr("Peer addition"), tr("Some peers could not be added. Check the Log for details.")); - else if (peerCount > 0) - QMessageBox::information(this, tr("Peer addition"), tr("The peers were added to this torrent.")); - return; - } - if (act == banAct) { - banSelectedPeers(); - return; - } - if (act == copyPeerAct) { - copySelectedPeers(); - return; - } -} - -void PeerListWidget::banSelectedPeers() -{ - // Confirm first - int ret = QMessageBox::question(this, tr("Ban peer permanently"), tr("Are you sure you want to ban permanently the selected peers?"), - tr("&Yes"), tr("&No"), - QString(), 0, 1); - if (ret) - return; - - QModelIndexList selectedIndexes = selectionModel()->selectedRows(); - foreach (const QModelIndex &index, selectedIndexes) { - int row = m_proxyModel->mapToSource(index).row(); - QString ip = m_listModel->data(m_listModel->index(row, PeerListDelegate::IP_HIDDEN)).toString(); - qDebug("Banning peer %s...", ip.toLocal8Bit().data()); - Logger::instance()->addMessage(tr("Manually banning peer '%1'...").arg(ip)); - BitTorrent::Session::instance()->banIP(ip); - } - // Refresh list - loadPeers(m_properties->getCurrentTorrent()); -} - -void PeerListWidget::copySelectedPeers() -{ - QModelIndexList selectedIndexes = selectionModel()->selectedRows(); - QStringList selectedPeers; - foreach (const QModelIndex &index, selectedIndexes) { - int row = m_proxyModel->mapToSource(index).row(); - QString ip = m_listModel->data(m_listModel->index(row, PeerListDelegate::IP_HIDDEN)).toString(); - QString myport = m_listModel->data(m_listModel->index(row, PeerListDelegate::PORT)).toString(); - if (ip.indexOf(".") == -1) // IPv6 - selectedPeers << "[" + ip + "]:" + myport; - else // IPv4 - selectedPeers << ip + ":" + myport; - } - QApplication::clipboard()->setText(selectedPeers.join("\n")); -} - -void PeerListWidget::clear() -{ - qDebug("clearing peer list"); - m_peerItems.clear(); - m_peerAddresses.clear(); - m_missingFlags.clear(); - int nbrows = m_listModel->rowCount(); - if (nbrows > 0) { - qDebug("Cleared %d peers", nbrows); - m_listModel->removeRows(0, nbrows); - } -} - -void PeerListWidget::loadSettings() -{ - header()->restoreState(Preferences::instance()->getPeerListState()); -} - -void PeerListWidget::saveSettings() const -{ - Preferences::instance()->setPeerListState(header()->saveState()); -} - -void PeerListWidget::loadPeers(BitTorrent::TorrentHandle *const torrent, bool forceHostnameResolution) -{ - if (!torrent) return; - - QList peers = torrent->peers(); - QSet oldeersSet = m_peerItems.keys().toSet(); - - foreach (const BitTorrent::PeerInfo &peer, peers) { - BitTorrent::PeerAddress addr = peer.address(); - if (addr.ip.isNull()) continue; - - QString peerIp = addr.ip.toString(); - if (m_peerItems.contains(peerIp)) { - // Update existing peer - updatePeer(peerIp, torrent, peer); - oldeersSet.remove(peerIp); - if (forceHostnameResolution && m_resolver) - m_resolver->resolve(peerIp); - } - else { - // Add new peer - m_peerItems[peerIp] = addPeer(peerIp, torrent, peer); - m_peerAddresses[peerIp] = addr; - // Resolve peer host name is asked - if (m_resolver) - m_resolver->resolve(peerIp); - } - } - // Delete peers that are gone - QSetIterator it(oldeersSet); - while (it.hasNext()) { - const QString &ip = it.next(); - m_missingFlags.remove(ip); - m_peerAddresses.remove(ip); - QStandardItem *item = m_peerItems.take(ip); - m_listModel->removeRow(item->row()); - } -} - -QStandardItem *PeerListWidget::addPeer(const QString &ip, BitTorrent::TorrentHandle *const torrent, const BitTorrent::PeerInfo &peer) -{ - int row = m_listModel->rowCount(); - // Adding Peer to peer list - m_listModel->insertRow(row); - m_listModel->setData(m_listModel->index(row, PeerListDelegate::IP), ip); - m_listModel->setData(m_listModel->index(row, PeerListDelegate::IP), ip, Qt::ToolTipRole); - m_listModel->setData(m_listModel->index(row, PeerListDelegate::PORT), peer.address().port); - m_listModel->setData(m_listModel->index(row, PeerListDelegate::IP_HIDDEN), ip); - if (m_resolveCountries) { - const QIcon ico = GuiIconProvider::instance()->getFlagIcon(peer.country()); - if (!ico.isNull()) { - m_listModel->setData(m_listModel->index(row, PeerListDelegate::COUNTRY), ico, Qt::DecorationRole); - const QString countryName = Net::GeoIPManager::CountryName(peer.country()); - m_listModel->setData(m_listModel->index(row, PeerListDelegate::COUNTRY), countryName, Qt::ToolTipRole); - } - else { - m_missingFlags.insert(ip); - } - } - m_listModel->setData(m_listModel->index(row, PeerListDelegate::CONNECTION), peer.connectionType()); - m_listModel->setData(m_listModel->index(row, PeerListDelegate::FLAGS), peer.flags()); - m_listModel->setData(m_listModel->index(row, PeerListDelegate::FLAGS), peer.flagsDescription(), Qt::ToolTipRole); - m_listModel->setData(m_listModel->index(row, PeerListDelegate::CLIENT), peer.client().toHtmlEscaped()); - m_listModel->setData(m_listModel->index(row, PeerListDelegate::PROGRESS), peer.progress()); - m_listModel->setData(m_listModel->index(row, PeerListDelegate::DOWN_SPEED), peer.payloadDownSpeed()); - m_listModel->setData(m_listModel->index(row, PeerListDelegate::UP_SPEED), peer.payloadUpSpeed()); - m_listModel->setData(m_listModel->index(row, PeerListDelegate::TOT_DOWN), peer.totalDownload()); - m_listModel->setData(m_listModel->index(row, PeerListDelegate::TOT_UP), peer.totalUpload()); - m_listModel->setData(m_listModel->index(row, PeerListDelegate::RELEVANCE), peer.relevance()); - QStringList downloadingFiles(torrent->info().filesForPiece(peer.downloadingPieceIndex())); - m_listModel->setData(m_listModel->index(row, PeerListDelegate::DOWNLOADING_PIECE), downloadingFiles.join(QLatin1String(";"))); - m_listModel->setData(m_listModel->index(row, PeerListDelegate::DOWNLOADING_PIECE), downloadingFiles.join(QLatin1String("\n")), Qt::ToolTipRole); - - return m_listModel->item(row, PeerListDelegate::IP); -} - -void PeerListWidget::updatePeer(const QString &ip, BitTorrent::TorrentHandle *const torrent, const BitTorrent::PeerInfo &peer) -{ - QStandardItem *item = m_peerItems.value(ip); - int row = item->row(); - if (m_resolveCountries) { - const QIcon ico = GuiIconProvider::instance()->getFlagIcon(peer.country()); - if (!ico.isNull()) { - m_listModel->setData(m_listModel->index(row, PeerListDelegate::COUNTRY), ico, Qt::DecorationRole); - const QString countryName = Net::GeoIPManager::CountryName(peer.country()); - m_listModel->setData(m_listModel->index(row, PeerListDelegate::COUNTRY), countryName, Qt::ToolTipRole); - m_missingFlags.remove(ip); - } - } - m_listModel->setData(m_listModel->index(row, PeerListDelegate::CONNECTION), peer.connectionType()); - m_listModel->setData(m_listModel->index(row, PeerListDelegate::PORT), peer.address().port); - m_listModel->setData(m_listModel->index(row, PeerListDelegate::FLAGS), peer.flags()); - m_listModel->setData(m_listModel->index(row, PeerListDelegate::FLAGS), peer.flagsDescription(), Qt::ToolTipRole); - m_listModel->setData(m_listModel->index(row, PeerListDelegate::CLIENT), peer.client().toHtmlEscaped()); - m_listModel->setData(m_listModel->index(row, PeerListDelegate::PROGRESS), peer.progress()); - m_listModel->setData(m_listModel->index(row, PeerListDelegate::DOWN_SPEED), peer.payloadDownSpeed()); - m_listModel->setData(m_listModel->index(row, PeerListDelegate::UP_SPEED), peer.payloadUpSpeed()); - m_listModel->setData(m_listModel->index(row, PeerListDelegate::TOT_DOWN), peer.totalDownload()); - m_listModel->setData(m_listModel->index(row, PeerListDelegate::TOT_UP), peer.totalUpload()); - m_listModel->setData(m_listModel->index(row, PeerListDelegate::RELEVANCE), peer.relevance()); - QStringList downloadingFiles(torrent->info().filesForPiece(peer.downloadingPieceIndex())); - m_listModel->setData(m_listModel->index(row, PeerListDelegate::DOWNLOADING_PIECE), downloadingFiles.join(QLatin1String(";"))); - m_listModel->setData(m_listModel->index(row, PeerListDelegate::DOWNLOADING_PIECE), downloadingFiles.join(QLatin1String("\n")), Qt::ToolTipRole); -} - -void PeerListWidget::handleResolved(const QString &ip, const QString &hostname) -{ - QStandardItem *item = m_peerItems.value(ip, 0); - if (item) { - qDebug("Resolved %s -> %s", qPrintable(ip), qPrintable(hostname)); - item->setData(hostname, Qt::DisplayRole); - } -} - -void PeerListWidget::handleSortColumnChanged(int col) -{ - if (col == PeerListDelegate::COUNTRY) { - qDebug("Sorting by decoration"); - m_proxyModel->setSortRole(Qt::ToolTipRole); - } - else { - m_proxyModel->setSortRole(Qt::DisplayRole); - } -} - -void PeerListWidget::wheelEvent(QWheelEvent *event) -{ - event->accept(); - - if (event->modifiers() & Qt::ShiftModifier) { - // Shift + scroll = horizontal scroll - QWheelEvent scrollHEvent(event->pos(), event->globalPos(), event->delta(), event->buttons(), event->modifiers(), Qt::Horizontal); - QTreeView::wheelEvent(&scrollHEvent); - return; - } - - QTreeView::wheelEvent(event); // event delegated to base class -} diff --git a/src/gui/properties/peerlistwidget.h b/src/gui/properties/peerlistwidget.h deleted file mode 100644 index 3d4a8483b..000000000 --- a/src/gui/properties/peerlistwidget.h +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Bittorrent Client using Qt4 and libtorrent. - * Copyright (C) 2006 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 PEERLISTWIDGET_H -#define PEERLISTWIDGET_H - -#include -#include -#include -#include -#include - -namespace Net -{ - class ReverseResolution; -} - -class PeerListDelegate; -class PeerListSortModel; -class PropertiesWidget; - -QT_BEGIN_NAMESPACE -class QSortFilterProxyModel; -class QStandardItem; -class QStandardItemModel; -QT_END_NAMESPACE - -namespace BitTorrent -{ - class TorrentHandle; - class PeerInfo; - struct PeerAddress; -} - -class PeerListWidget: public QTreeView -{ - Q_OBJECT - -public: - explicit PeerListWidget(PropertiesWidget *parent); - ~PeerListWidget(); - - void loadPeers(BitTorrent::TorrentHandle *const torrent, bool forceHostnameResolution = false); - QStandardItem *addPeer(const QString &ip, BitTorrent::TorrentHandle *const torrent, const BitTorrent::PeerInfo &peer); - void updatePeer(const QString &ip, BitTorrent::TorrentHandle *const torrent, const BitTorrent::PeerInfo &peer); - void updatePeerHostNameResolutionState(); - void updatePeerCountryResolutionState(); - void clear(); - -private slots: - void loadSettings(); - void saveSettings() const; - void displayToggleColumnsMenu(const QPoint &); - void showPeerListMenu(const QPoint &); - void banSelectedPeers(); - void copySelectedPeers(); - void handleSortColumnChanged(int col); - void handleResolved(const QString &ip, const QString &hostname); - -private: - void wheelEvent(QWheelEvent *event) override; - - QStandardItemModel *m_listModel; - PeerListDelegate *m_listDelegate; - PeerListSortModel *m_proxyModel; - QHash m_peerItems; - QHash m_peerAddresses; - QSet m_missingFlags; - QPointer m_resolver; - PropertiesWidget *m_properties; - bool m_resolveCountries; - QShortcut *m_copyHotkey; -}; - -#endif // PEERLISTWIDGET_H diff --git a/src/gui/properties/peersadditiondlg.cpp b/src/gui/properties/peersadditiondlg.cpp deleted file mode 100644 index ab20674aa..000000000 --- a/src/gui/properties/peersadditiondlg.cpp +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Bittorrent Client using Qt4 and libtorrent. - * Copyright (C) 2006 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 "peersadditiondlg.h" - -#include -#include - -#include "ui_peersadditiondlg.h" - -PeersAdditionDlg::PeersAdditionDlg(QWidget *parent) - : QDialog(parent) - , m_ui(new Ui::addPeersDialog()) -{ - m_ui->setupUi(this); - connect(m_ui->buttonBox, SIGNAL(accepted()), this, SLOT(validateInput())); - - m_ui->label_format->hide(); - m_ui->peers_txt->setPlaceholderText("Format: IPv4:port / [IPv6]:port"); -} - -PeersAdditionDlg::~PeersAdditionDlg() -{ - delete m_ui; -} - -QList PeersAdditionDlg::askForPeers(QWidget *parent) -{ - PeersAdditionDlg dlg(parent); - dlg.exec(); - return dlg.m_peersList; -} - -void PeersAdditionDlg::validateInput() -{ - if (m_ui->peers_txt->toPlainText().trimmed().isEmpty()) { - QMessageBox::warning(this, tr("No peer entered"), - tr("Please type at least one peer."), - QMessageBox::Ok); - return; - } - foreach (const QString &peer, m_ui->peers_txt->toPlainText().trimmed().split("\n")) { - BitTorrent::PeerAddress addr = parsePeer(peer); - if (!addr.ip.isNull()) { - m_peersList.append(addr); - } - else { - QMessageBox::warning(this, tr("Invalid peer"), - tr("The peer '%1' is invalid.").arg(peer), - QMessageBox::Ok); - m_peersList.clear(); - return; - } - } - accept(); -} - -BitTorrent::PeerAddress PeersAdditionDlg::parsePeer(QString peer) -{ - BitTorrent::PeerAddress addr; - QStringList ipPort; - - if (peer[0] == '[' && peer.indexOf("]:") != -1) // IPv6 - ipPort = peer.remove(QChar('[')).split("]:"); - else if (peer.indexOf(":") != -1) // IPv4 - ipPort = peer.split(":"); - else - return addr; - - QHostAddress ip(ipPort[0]); - if (ip.isNull()) - return addr; - - bool ok; - int port = ipPort[1].toInt(&ok); - if (!ok || port < 1 || port > 65535) - return addr; - - addr.ip = ip; - addr.port = port; - return addr; -} diff --git a/src/gui/properties/peersadditiondlg.h b/src/gui/properties/peersadditiondlg.h deleted file mode 100644 index 8f09c907c..000000000 --- a/src/gui/properties/peersadditiondlg.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2006 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 PEERADDITION_H -#define PEERADDITION_H - -#include - -#include "base/bittorrent/peerinfo.h" - -template class QList; - -namespace Ui -{ - class addPeersDialog; -} - -class PeersAdditionDlg: public QDialog -{ - Q_OBJECT - -public: - PeersAdditionDlg(QWidget *parent); - ~PeersAdditionDlg(); - - static QList askForPeers(QWidget *parent); - -protected slots: - void validateInput(); - -private: - BitTorrent::PeerAddress parsePeer(QString peer); - - Ui::addPeersDialog *m_ui; - QList m_peersList; - -}; - -#endif // PEERADDITION_H diff --git a/src/gui/properties/peersadditiondlg.ui b/src/gui/properties/peersadditiondlg.ui deleted file mode 100644 index b2c056513..000000000 --- a/src/gui/properties/peersadditiondlg.ui +++ /dev/null @@ -1,72 +0,0 @@ - - - addPeersDialog - - - - 0 - 0 - 367 - 274 - - - - Add Peers - - - - - - List of peers to add (one IP per line): - - - - - - - QTextEdit::NoWrap - - - false - - - - - - - Format: IPv4:port / [IPv6]:port - - - - - - - Qt::Horizontal - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - - - - - - - buttonBox - rejected() - addPeersDialog - reject() - - - 183 - 251 - - - 183 - 136 - - - - - diff --git a/src/gui/properties/pieceavailabilitybar.cpp b/src/gui/properties/pieceavailabilitybar.cpp deleted file mode 100644 index 0ce3f2618..000000000 --- a/src/gui/properties/pieceavailabilitybar.cpp +++ /dev/null @@ -1,170 +0,0 @@ -/* - * Bittorrent Client using Qt4 and libtorrent. - * Copyright (C) 2006 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 "pieceavailabilitybar.h" - -#include - -#include - -PieceAvailabilityBar::PieceAvailabilityBar(QWidget *parent) - : base {parent} -{ -} - -QVector PieceAvailabilityBar::intToFloatVector(const QVector &vecin, int reqSize) -{ - QVector result(reqSize, 0.0); - if (vecin.isEmpty()) return result; - - const float ratio = static_cast(vecin.size()) / reqSize; - - const int maxElement = *std::max_element(vecin.begin(), vecin.end()); - - // qMax because in normalization we don't want divide by 0 - // if maxElement == 0 check will be disabled please enable this line: - // const int maxElement = qMax(*std::max_element(avail.begin(), avail.end()), 1); - - if (maxElement == 0) - return result; - - // simple linear transformation algorithm - // for example: - // image.x(0) = pieces.x(0.0 >= x < 1.7) - // image.x(1) = pieces.x(1.7 >= x < 3.4) - - for (int x = 0; x < reqSize; ++x) { - // R - real - const float fromR = x * ratio; - const float toR = (x + 1) * ratio; - - // C - integer - int fromC = fromR;// std::floor not needed - int toC = std::ceil(toR); - if (toC > vecin.size()) - --toC; - - // position in pieces table - int x2 = fromC; - - // little speed up for really big pieces table, 10K+ size - const int toCMinusOne = toC - 1; - - // value in returned vector - float value = 0; - - // case when calculated range is (15.2 >= x < 15.7) - if (x2 == toCMinusOne) { - if (vecin[x2]) - value += ratio * vecin[x2]; - ++x2; - } - // case when (15.2 >= x < 17.8) - else { - // subcase (15.2 >= x < 16) - if (x2 != fromR) { - if (vecin[x2]) - value += (1.0 - (fromR - fromC)) * vecin[x2]; - ++x2; - } - - // subcase (16 >= x < 17) - for (; x2 < toCMinusOne; ++x2) - if (vecin[x2]) - value += vecin[x2]; - - // subcase (17 >= x < 17.8) - if (x2 == toCMinusOne) { - if (vecin[x2]) - value += (1.0 - (toC - toR)) * vecin[x2]; - ++x2; - } - } - - // normalization <0, 1> - value /= ratio * maxElement; - - // float precision sometimes gives > 1, because in not possible to store irrational numbers - value = qMin(value, 1.0f); - - result[x] = value; - } - - return result; -} - -bool PieceAvailabilityBar::updateImage(QImage &image) -{ - QImage image2(width() - 2 * borderWidth, 1, QImage::Format_RGB888); - if (image2.isNull()) { - qDebug() << "QImage image2() allocation failed, width():" << width(); - return false; - } - - if (m_pieces.empty()) { - image2.fill(Qt::white); - image = image2; - return true; - } - - QVector scaled_pieces = intToFloatVector(m_pieces, image2.width()); - - // filling image - for (int x = 0; x < scaled_pieces.size(); ++x) { - float pieces2_val = scaled_pieces.at(x); - image2.setPixel(x, 0, pieceColors()[pieces2_val * 255]); - } - image = image2; - return true; -} - -void PieceAvailabilityBar::setAvailability(const QVector &avail) -{ - m_pieces = avail; - - requestImageUpdate(); -} - -void PieceAvailabilityBar::clear() -{ - m_pieces.clear(); - base::clear(); -} - -QString PieceAvailabilityBar::simpleToolTipText() const -{ - return tr("White: Unavailable pieces") + '\n' - + tr("Blue: Available pieces") + '\n'; -} - -bool PieceAvailabilityBar::isFileNameCorrectionNeeded() const -{ - return true; -} diff --git a/src/gui/properties/pieceavailabilitybar.h b/src/gui/properties/pieceavailabilitybar.h deleted file mode 100644 index 98d98a31a..000000000 --- a/src/gui/properties/pieceavailabilitybar.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Bittorrent Client using Qt4 and libtorrent. - * Copyright (C) 2006 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 PIECEAVAILABILITYBAR_H -#define PIECEAVAILABILITYBAR_H - -#include "piecesbar.h" - -class PieceAvailabilityBar: public PiecesBar -{ - using base = PiecesBar; - Q_OBJECT - Q_DISABLE_COPY(PieceAvailabilityBar) - -public: - PieceAvailabilityBar(QWidget *parent); - - void setAvailability(const QVector &avail); - - // PiecesBar interface - void clear() override; - -private: - bool updateImage(QImage &image) override; - QString simpleToolTipText() const override; - bool isFileNameCorrectionNeeded() const override; - - // last used int vector, uses to better resize redraw - // TODO: make a diff pieces to new pieces and update only changed pixels, speedup when update > 20x faster - QVector m_pieces; - - // scale int vector to float vector - QVector intToFloatVector(const QVector &vecin, int reqSize); -}; - -#endif // PIECEAVAILABILITYBAR_H diff --git a/src/gui/properties/piecesbar.cpp b/src/gui/properties/piecesbar.cpp deleted file mode 100644 index f495f82c1..000000000 --- a/src/gui/properties/piecesbar.cpp +++ /dev/null @@ -1,338 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2016 Eugene Shalygin - * Copyright (C) 2006 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. - */ - -#include "piecesbar.h" - -#include -#include -#include -#include -#include -#include - -#include "base/bittorrent/torrenthandle.h" -#include "base/utils/misc.h" - -namespace -{ - using ImageRange = IndexRange; - - // Computes approximate mapping from image scale (measured in pixels) onto the torrent contents scale (in pieces) - // However, taking the size of a screen to be ~ 1000 px and the torrent size larger than 10 MiB, the pointing error - // is well below 0.5 px and thus is negligible. - class PieceIndexToImagePos - { - public: - PieceIndexToImagePos(const BitTorrent::TorrentInfo &torrentInfo, const QImage &image) - : m_bytesPerPixel {(image.width() > 0 && torrentInfo.totalSize() >= image.width()) - ? torrentInfo.totalSize() / image.width() : -1} - , m_torrentInfo {torrentInfo} - { - if ((m_bytesPerPixel > 0) && (m_bytesPerPixel < 10)) - qDebug() << "PieceIndexToImagePos: torrent size is too small for correct computaions." - << "Torrent size =" << torrentInfo.totalSize() << "Image width = " << image.width(); - } - - ImageRange imagePos(const BitTorrent::TorrentInfo::PieceRange &pieces) const - { - if (m_bytesPerPixel < 0) - return {0, 0}; - - // the type conversion is used to prevent integer overflow with torrents of 2+ GiB size - const qlonglong pieceLength = m_torrentInfo.pieceLength(); - return makeInterval( - (pieces.first() * pieceLength) / m_bytesPerPixel, - (pieces.last() * pieceLength + m_torrentInfo.pieceLength(pieces.last()) - 1) / m_bytesPerPixel); - } - - int pieceIndex(int imagePos) const - { - return m_bytesPerPixel < 0 ? 0 : (imagePos * m_bytesPerPixel + m_bytesPerPixel / 2) / m_torrentInfo.pieceLength(); - } - - private: - const qlonglong m_bytesPerPixel; // how many bytes of the torrent are squeezed into a bar's pixel - const BitTorrent::TorrentInfo m_torrentInfo; - }; - - class DetailedTooltipRenderer - { - public: - DetailedTooltipRenderer(QTextStream &stream, const QString &header) - : m_stream(stream) - { - m_stream << header - << R"()"; - } - - ~DetailedTooltipRenderer() - { - m_stream << "
"; - } - - void operator()(const QString &size, const QString &path) - { - m_stream << R"()" << size << "" << path << ""; - } - - private: - QTextStream &m_stream; - }; -} - -PiecesBar::PiecesBar(QWidget *parent) - : QWidget {parent} - , m_torrent {nullptr} - , m_borderColor {palette().color(QPalette::Dark)} - , m_bgColor {Qt::white} - , m_pieceColor {Qt::blue} - , m_hovered {false} -{ - updatePieceColors(); - setMouseTracking(true); -} - -void PiecesBar::setTorrent(BitTorrent::TorrentHandle *torrent) -{ - m_torrent = torrent; - if (!m_torrent) - clear(); -} - -void PiecesBar::clear() -{ - m_image = QImage(); - update(); -} - -void PiecesBar::setColors(const QColor &background, const QColor &border, const QColor &complete) -{ - m_bgColor = background; - m_borderColor = border; - m_pieceColor = complete; - - updatePieceColors(); - requestImageUpdate(); -} - -bool PiecesBar::event(QEvent *e) -{ - if (e->type() == QEvent::ToolTip) { - showToolTip(static_cast(e)); - return true; - } - else { - return base::event(e); - } -} - -void PiecesBar::enterEvent(QEvent *e) -{ - m_hovered = true; - base::enterEvent(e); -} - -void PiecesBar::leaveEvent(QEvent *e) -{ - m_hovered = false; - m_highlitedRegion = QRect(); - requestImageUpdate(); - base::leaveEvent(e); -} - -void PiecesBar::mouseMoveEvent(QMouseEvent *e) -{ - // if user pointed to a piece which is a part of a single large file, - // we highlight the space, occupied by this file - highlightFile(e->pos().x() - borderWidth); - base::mouseMoveEvent(e); -} - -void PiecesBar::paintEvent(QPaintEvent *) -{ - QPainter painter(this); - QRect imageRect(borderWidth, borderWidth, width() - 2 * borderWidth, height() - 2 * borderWidth); - if (m_image.isNull()) { - painter.setBrush(Qt::white); - painter.drawRect(imageRect); - } - else { - if (m_image.width() != imageRect.width()) - updateImage(m_image); - painter.drawImage(imageRect, m_image); - } - - if (!m_highlitedRegion.isNull()) { - QColor highlightColor {this->palette().color(QPalette::Active, QPalette::Highlight)}; - highlightColor.setAlphaF(0.35); - QRect targetHighlightRect {m_highlitedRegion.adjusted(borderWidth, borderWidth, borderWidth, height() - 2 * borderWidth)}; - painter.fillRect(targetHighlightRect, highlightColor); - } - - QPainterPath border; - border.addRect(0, 0, width(), height()); - painter.setPen(m_borderColor); - painter.drawPath(border); -} - -void PiecesBar::requestImageUpdate() -{ - if (updateImage(m_image)) - update(); -} - -QColor PiecesBar::backgroundColor() const -{ - return m_bgColor; -} - -QColor PiecesBar::borderColor() const -{ - return m_borderColor; -} - -QColor PiecesBar::pieceColor() const -{ - return m_pieceColor; -} - -const QVector &PiecesBar::pieceColors() const -{ - return m_pieceColors; -} - -QRgb PiecesBar::mixTwoColors(QRgb rgb1, QRgb rgb2, float ratio) -{ - int r1 = qRed(rgb1); - int g1 = qGreen(rgb1); - int b1 = qBlue(rgb1); - - int r2 = qRed(rgb2); - int g2 = qGreen(rgb2); - int b2 = qBlue(rgb2); - - float ratioN = 1.0f - ratio; - int r = (r1 * ratioN) + (r2 * ratio); - int g = (g1 * ratioN) + (g2 * ratio); - int b = (b1 * ratioN) + (b2 * ratio); - - return qRgb(r, g, b); -} - -void PiecesBar::showToolTip(const QHelpEvent *e) -{ - if (!m_torrent) - return; - - QString toolTipText; - QTextStream stream(&toolTipText, QIODevice::WriteOnly); - const bool showDetailedInformation = QApplication::keyboardModifiers().testFlag(Qt::ShiftModifier); - if (showDetailedInformation && m_torrent->hasMetadata()) { - const int imagePos = e->pos().x() - borderWidth; - if ((imagePos >=0) && (imagePos < m_image.width())) { - stream << ""; - PieceIndexToImagePos transform {m_torrent->info(), m_image}; - int pieceIndex = transform.pieceIndex(imagePos); - QVector files {m_torrent->info().fileIndicesForPiece(pieceIndex)}; - - QString tooltipTitle; - if (files.count() > 1) { - tooltipTitle = tr("Files in this piece:"); - } - else { - if (m_torrent->info().fileSize(files.front()) == m_torrent->info().pieceLength(pieceIndex)) - tooltipTitle = tr("File in this piece"); - else - tooltipTitle = tr("File in these pieces"); - } - - DetailedTooltipRenderer renderer(stream, tooltipTitle); - - const bool isFileNameCorrectionNeeded = this->isFileNameCorrectionNeeded(); - for (int f: files) { - QString filePath {m_torrent->info().filePath(f)}; - if (isFileNameCorrectionNeeded) - filePath.replace(QLatin1String("/.unwanted"), QString()); - - renderer(Utils::Misc::friendlyUnit(m_torrent->info().fileSize(f)), filePath); - } - stream << ""; - } - } - else { - stream << simpleToolTipText(); - if (showDetailedInformation) // metadata are not available at this point - stream << '\n' << tr("Wait until metadata become available to see detailed information"); - else - stream << '\n' << tr("Hold Shift key for detailed information"); - } - - stream.flush(); - - QToolTip::showText(e->globalPos(), toolTipText, this); -} - -void PiecesBar::highlightFile(int imagePos) -{ - if (!m_torrent || !m_torrent->hasMetadata() || (imagePos < 0) || (imagePos >= m_image.width())) - return; - - PieceIndexToImagePos transform {m_torrent->info(), m_image}; - - int pieceIndex = transform.pieceIndex(imagePos); - QVector fileIndices {m_torrent->info().fileIndicesForPiece(pieceIndex)}; - if (fileIndices.count() == 1) { - BitTorrent::TorrentInfo::PieceRange filePieces = m_torrent->info().filePieces(fileIndices.first()); - - ImageRange imageRange = transform.imagePos(filePieces); - QRect newHighlitedRegion {imageRange.first(), 0, imageRange.size(), m_image.height()}; - if (newHighlitedRegion != m_highlitedRegion) { - m_highlitedRegion = newHighlitedRegion; - update(); - } - } - else if (!m_highlitedRegion.isEmpty()) { - m_highlitedRegion = QRect(); - update(); - } -} - -void PiecesBar::updatePieceColors() -{ - m_pieceColors = QVector(256); - for (int i = 0; i < 256; ++i) { - float ratio = (i / 255.0); - m_pieceColors[i] = mixTwoColors(backgroundColor().rgb(), m_pieceColor.rgb(), ratio); - } -} - -bool PiecesBar::isFileNameCorrectionNeeded() const -{ - return false; -} diff --git a/src/gui/properties/piecesbar.h b/src/gui/properties/piecesbar.h deleted file mode 100644 index 92f81a80e..000000000 --- a/src/gui/properties/piecesbar.h +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2016 Eugene Shalygin - * Copyright (C) 2006 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. - */ - -#ifndef PIECESBAR_H -#define PIECESBAR_H - -#include -#include -#include - -class QHelpEvent; - -namespace BitTorrent -{ - class TorrentHandle; -} - -class PiecesBar: public QWidget -{ - using base = QWidget; - Q_OBJECT - Q_DISABLE_COPY(PiecesBar) - -public: - explicit PiecesBar(QWidget *parent = nullptr); - - void setTorrent(BitTorrent::TorrentHandle *torrent); - void setColors(const QColor &background, const QColor &border, const QColor &complete); - - virtual void clear(); - - // QObject interface - virtual bool event(QEvent*) override; - -protected: - // QWidget interface - void enterEvent(QEvent*) override; - void leaveEvent(QEvent*) override; - void mouseMoveEvent(QMouseEvent*) override; - - void paintEvent(QPaintEvent*) override; - void requestImageUpdate(); - - QColor backgroundColor() const; - QColor borderColor() const; - QColor pieceColor() const; - const QVector &pieceColors() const; - - // mix two colors by light model, ratio <0, 1> - static QRgb mixTwoColors(QRgb rgb1, QRgb rgb2, float ratio); - - static constexpr int borderWidth = 1; - -private: - void showToolTip(const QHelpEvent*); - void highlightFile(int imagePos); - - virtual QString simpleToolTipText() const = 0; - - /// whether to perform removing of ".unwanted" directory from paths - virtual bool isFileNameCorrectionNeeded() const; - - // draw new image to replace the actual image - // returns true if image was successfully updated - virtual bool updateImage(QImage &image) = 0; - void updatePieceColors(); - - const BitTorrent::TorrentHandle *m_torrent; - QImage m_image; - // I used values, because it should be possible to change colors at run time - // border color - QColor m_borderColor; - // background color - QColor m_bgColor; - // complete piece color - QColor m_pieceColor; - // buffered 256 levels gradient from bg_color to piece_color - QVector m_pieceColors; - bool m_hovered; - QRect m_highlitedRegion; //!< part of the bar can be highlighted; this rectangle is in the same frame as m_image -}; - -#endif // PIECESBAR_H diff --git a/src/gui/properties/properties.pri b/src/gui/properties/properties.pri deleted file mode 100644 index da380922a..000000000 --- a/src/gui/properties/properties.pri +++ /dev/null @@ -1,33 +0,0 @@ -INCLUDEPATH += $$PWD - -FORMS += $$PWD/propertieswidget.ui \ - $$PWD/trackersadditiondlg.ui \ - $$PWD/peersadditiondlg.ui - -HEADERS += $$PWD/propertieswidget.h \ - $$PWD/peerlistwidget.h \ - $$PWD/proplistdelegate.h \ - $$PWD/trackerlist.h \ - $$PWD/downloadedpiecesbar.h \ - $$PWD/peerlistdelegate.h \ - $$PWD/peerlistsortmodel.h \ - $$PWD/peersadditiondlg.h \ - $$PWD/trackersadditiondlg.h \ - $$PWD/pieceavailabilitybar.h \ - $$PWD/proptabbar.h \ - $$PWD/speedwidget.h \ - $$PWD/speedplotview.h \ - $$PWD/piecesbar.h - -SOURCES += $$PWD/propertieswidget.cpp \ - $$PWD/proplistdelegate.cpp \ - $$PWD/peerlistwidget.cpp \ - $$PWD/trackerlist.cpp \ - $$PWD/peersadditiondlg.cpp \ - $$PWD/downloadedpiecesbar.cpp \ - $$PWD/trackersadditiondlg.cpp \ - $$PWD/pieceavailabilitybar.cpp \ - $$PWD/proptabbar.cpp \ - $$PWD/speedwidget.cpp \ - $$PWD/speedplotview.cpp \ - $$PWD/piecesbar.cpp diff --git a/src/gui/properties/propertieswidget.cpp b/src/gui/properties/propertieswidget.cpp deleted file mode 100644 index b38b0da0a..000000000 --- a/src/gui/properties/propertieswidget.cpp +++ /dev/null @@ -1,897 +0,0 @@ -/* - * Bittorrent Client using Qt4 and libtorrent. - * Copyright (C) 2006 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 "propertieswidget.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "base/bittorrent/session.h" -#include "base/preferences.h" -#include "base/unicodestrings.h" -#include "base/utils/fs.h" -#include "base/utils/misc.h" -#include "base/utils/string.h" -#include "autoexpandabledialog.h" -#include "downloadedpiecesbar.h" -#include "guiiconprovider.h" -#include "lineedit.h" -#include "mainwindow.h" -#include "messageboxraised.h" -#include "peerlistwidget.h" -#include "pieceavailabilitybar.h" -#include "proplistdelegate.h" -#include "proptabbar.h" -#include "speedwidget.h" -#include "torrentcontentfiltermodel.h" -#include "torrentcontentmodel.h" -#include "trackerlist.h" -#include "transferlistwidget.h" - -#include "ui_propertieswidget.h" - -PropertiesWidget::PropertiesWidget(QWidget *parent, MainWindow *main_window, TransferListWidget *transferList) - : QWidget(parent) - , m_ui(new Ui::PropertiesWidget()) - , transferList(transferList) - , main_window(main_window) - , m_torrent(nullptr) -{ - m_ui->setupUi(this); - setAutoFillBackground(true); - - state = VISIBLE; - - // Set Properties list model - PropListModel = new TorrentContentFilterModel(); - m_ui->filesList->setModel(PropListModel); - PropDelegate = new PropListDelegate(this); - m_ui->filesList->setItemDelegate(PropDelegate); - m_ui->filesList->setSortingEnabled(true); - // Torrent content filtering - m_contentFilterLine = new LineEdit(this); - m_contentFilterLine->setPlaceholderText(tr("Filter files...")); - m_contentFilterLine->setMaximumSize(300, m_contentFilterLine->size().height()); - connect(m_contentFilterLine, SIGNAL(textChanged(QString)), this, SLOT(filterText(QString))); - m_ui->contentFilterLayout->insertWidget(3, m_contentFilterLine); - - // SIGNAL/SLOTS - connect(m_ui->filesList, SIGNAL(clicked(const QModelIndex&)), m_ui->filesList, SLOT(edit(const QModelIndex&))); - connect(m_ui->selectAllButton, SIGNAL(clicked()), PropListModel, SLOT(selectAll())); - connect(m_ui->selectNoneButton, SIGNAL(clicked()), PropListModel, SLOT(selectNone())); - connect(m_ui->filesList, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(displayFilesListMenu(const QPoint&))); - connect(m_ui->filesList, SIGNAL(doubleClicked(const QModelIndex&)), this, SLOT(openDoubleClickedFile(const QModelIndex&))); - connect(PropListModel, SIGNAL(filteredFilesChanged()), this, SLOT(filteredFilesChanged())); - connect(m_ui->listWebSeeds, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(displayWebSeedListMenu(const QPoint&))); - connect(transferList, SIGNAL(currentTorrentChanged(BitTorrent::TorrentHandle * const)), this, SLOT(loadTorrentInfos(BitTorrent::TorrentHandle * const))); - connect(PropDelegate, SIGNAL(filteredFilesChanged()), this, SLOT(filteredFilesChanged())); - connect(m_ui->stackedProperties, SIGNAL(currentChanged(int)), this, SLOT(loadDynamicData())); - connect(BitTorrent::Session::instance(), SIGNAL(torrentSavePathChanged(BitTorrent::TorrentHandle * const)), this, SLOT(updateSavePath(BitTorrent::TorrentHandle * const))); - connect(BitTorrent::Session::instance(), SIGNAL(torrentMetadataLoaded(BitTorrent::TorrentHandle * const)), this, SLOT(updateTorrentInfos(BitTorrent::TorrentHandle * const))); - connect(m_ui->filesList->header(), SIGNAL(sectionMoved(int,int,int)), this, SLOT(saveSettings())); - connect(m_ui->filesList->header(), SIGNAL(sectionResized(int,int,int)), this, SLOT(saveSettings())); - connect(m_ui->filesList->header(), SIGNAL(sortIndicatorChanged(int,Qt::SortOrder)), this, SLOT(saveSettings())); - - // set bar height relative to screen dpi - int barHeight = devicePixelRatio() * 18; - - // Downloaded pieces progress bar - m_ui->tempProgressBarArea->setVisible(false); - downloaded_pieces = new DownloadedPiecesBar(this); - m_ui->groupBarLayout->addWidget(downloaded_pieces, 0, 1); - downloaded_pieces->setFixedHeight(barHeight); - downloaded_pieces->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); - - // Pieces availability bar - m_ui->tempAvailabilityBarArea->setVisible(false); - pieces_availability = new PieceAvailabilityBar(this); - m_ui->groupBarLayout->addWidget(pieces_availability, 1, 1); - pieces_availability->setFixedHeight(barHeight); - pieces_availability->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); - - // Tracker list - trackerList = new TrackerList(this); - m_ui->trackerUpButton->setIcon(GuiIconProvider::instance()->getIcon("go-up")); - m_ui->trackerUpButton->setIconSize(Utils::Misc::smallIconSize()); - m_ui->trackerDownButton->setIcon(GuiIconProvider::instance()->getIcon("go-down")); - m_ui->trackerDownButton->setIconSize(Utils::Misc::smallIconSize()); - connect(m_ui->trackerUpButton, SIGNAL(clicked()), trackerList, SLOT(moveSelectionUp())); - connect(m_ui->trackerDownButton, SIGNAL(clicked()), trackerList, SLOT(moveSelectionDown())); - m_ui->horizontalLayout_trackers->insertWidget(0, trackerList); - connect(trackerList->header(), SIGNAL(sectionMoved(int,int,int)), trackerList, SLOT(saveSettings())); - connect(trackerList->header(), SIGNAL(sectionResized(int,int,int)), trackerList, SLOT(saveSettings())); - connect(trackerList->header(), SIGNAL(sortIndicatorChanged(int,Qt::SortOrder)), trackerList, SLOT(saveSettings())); - // Peers list - peersList = new PeerListWidget(this); - m_ui->peerpage_layout->addWidget(peersList); - connect(peersList->header(), SIGNAL(sectionMoved(int,int,int)), peersList, SLOT(saveSettings())); - connect(peersList->header(), SIGNAL(sectionResized(int,int,int)), peersList, SLOT(saveSettings())); - connect(peersList->header(), SIGNAL(sortIndicatorChanged(int,Qt::SortOrder)), peersList, SLOT(saveSettings())); - // Speed widget - speedWidget = new SpeedWidget(this); - m_ui->speed_layout->addWidget(speedWidget); - // Tab bar - m_tabBar = new PropTabBar(); - m_tabBar->setContentsMargins(0, 5, 0, 0); - m_ui->verticalLayout->addLayout(m_tabBar); - connect(m_tabBar, SIGNAL(tabChanged(int)), m_ui->stackedProperties, SLOT(setCurrentIndex(int))); - connect(m_tabBar, SIGNAL(tabChanged(int)), this, SLOT(saveSettings())); - connect(m_tabBar, SIGNAL(visibilityToggled(bool)), SLOT(setVisibility(bool))); - connect(m_tabBar, SIGNAL(visibilityToggled(bool)), this, SLOT(saveSettings())); - // Dynamic data refresher - refreshTimer = new QTimer(this); - connect(refreshTimer, SIGNAL(timeout()), this, SLOT(loadDynamicData())); - refreshTimer->start(3000); // 3sec - editHotkeyFile = new QShortcut(Qt::Key_F2, m_ui->filesList, 0, 0, Qt::WidgetShortcut); - connect(editHotkeyFile, SIGNAL(activated()), SLOT(renameSelectedFile())); - editHotkeyWeb = new QShortcut(Qt::Key_F2, m_ui->listWebSeeds, 0, 0, Qt::WidgetShortcut); - connect(editHotkeyWeb, SIGNAL(activated()), SLOT(editWebSeed())); - connect(m_ui->listWebSeeds, SIGNAL(doubleClicked(QModelIndex)), SLOT(editWebSeed())); - deleteHotkeyWeb = new QShortcut(QKeySequence::Delete, m_ui->listWebSeeds, 0, 0, Qt::WidgetShortcut); - connect(deleteHotkeyWeb, SIGNAL(activated()), SLOT(deleteSelectedUrlSeeds())); - openHotkeyFile = new QShortcut(Qt::Key_Return, m_ui->filesList, 0, 0, Qt::WidgetShortcut); - connect(openHotkeyFile, SIGNAL(activated()), SLOT(openSelectedFile())); -} - -PropertiesWidget::~PropertiesWidget() -{ - qDebug() << Q_FUNC_INFO << "ENTER"; - delete refreshTimer; - delete trackerList; - delete peersList; - delete speedWidget; - delete downloaded_pieces; - delete pieces_availability; - delete PropListModel; - delete PropDelegate; - delete m_tabBar; - delete editHotkeyFile; - delete editHotkeyWeb; - delete deleteHotkeyWeb; - delete openHotkeyFile; - delete m_ui; - qDebug() << Q_FUNC_INFO << "EXIT"; -} - -void PropertiesWidget::showPiecesAvailability(bool show) -{ - m_ui->avail_pieces_lbl->setVisible(show); - pieces_availability->setVisible(show); - m_ui->avail_average_lbl->setVisible(show); - if (show || !downloaded_pieces->isVisible()) - m_ui->line_2->setVisible(show); -} - -void PropertiesWidget::showPiecesDownloaded(bool show) -{ - m_ui->downloaded_pieces_lbl->setVisible(show); - downloaded_pieces->setVisible(show); - m_ui->progress_lbl->setVisible(show); - if (show || !pieces_availability->isVisible()) - m_ui->line_2->setVisible(show); -} - -void PropertiesWidget::setVisibility(bool visible) -{ - if (!visible && (state == VISIBLE)) { - QSplitter *hSplitter = static_cast(parentWidget()); - m_ui->stackedProperties->setVisible(false); - slideSizes = hSplitter->sizes(); - hSplitter->handle(1)->setVisible(false); - hSplitter->handle(1)->setDisabled(true); - QList sizes = QList() << hSplitter->geometry().height() - 30 << 30; - hSplitter->setSizes(sizes); - state = REDUCED; - return; - } - - if (visible && (state == REDUCED)) { - m_ui->stackedProperties->setVisible(true); - QSplitter *hSplitter = static_cast(parentWidget()); - hSplitter->handle(1)->setDisabled(false); - hSplitter->handle(1)->setVisible(true); - hSplitter->setSizes(slideSizes); - state = VISIBLE; - // Force refresh - loadDynamicData(); - } -} - -void PropertiesWidget::clear() -{ - qDebug("Clearing torrent properties"); - m_ui->save_path->clear(); - m_ui->lbl_creationDate->clear(); - m_ui->label_total_pieces_val->clear(); - m_ui->hash_lbl->clear(); - m_ui->comment_text->clear(); - m_ui->progress_lbl->clear(); - trackerList->clear(); - downloaded_pieces->clear(); - pieces_availability->clear(); - m_ui->avail_average_lbl->clear(); - m_ui->wasted->clear(); - m_ui->upTotal->clear(); - m_ui->dlTotal->clear(); - peersList->clear(); - m_ui->lbl_uplimit->clear(); - m_ui->lbl_dllimit->clear(); - m_ui->lbl_elapsed->clear(); - m_ui->lbl_connections->clear(); - m_ui->reannounce_lbl->clear(); - m_ui->shareRatio->clear(); - m_ui->listWebSeeds->clear(); - m_contentFilterLine->clear(); - PropListModel->model()->clear(); - m_ui->label_eta_val->clear(); - m_ui->label_seeds_val->clear(); - m_ui->label_peers_val->clear(); - m_ui->label_dl_speed_val->clear(); - m_ui->label_upload_speed_val->clear(); - m_ui->label_total_size_val->clear(); - m_ui->label_completed_on_val->clear(); - m_ui->label_last_complete_val->clear(); - m_ui->label_created_by_val->clear(); - m_ui->label_added_on_val->clear(); -} - -BitTorrent::TorrentHandle *PropertiesWidget::getCurrentTorrent() const -{ - return m_torrent; -} - -QTreeView *PropertiesWidget::getFilesList() const -{ - return m_ui->filesList; -} - -void PropertiesWidget::updateSavePath(BitTorrent::TorrentHandle *const torrent) -{ - if (m_torrent == torrent) - m_ui->save_path->setText(Utils::Fs::toNativePath(m_torrent->savePath())); -} - -void PropertiesWidget::loadTrackers(BitTorrent::TorrentHandle *const torrent) -{ - if (torrent == m_torrent) - trackerList->loadTrackers(); -} - -void PropertiesWidget::updateTorrentInfos(BitTorrent::TorrentHandle *const torrent) -{ - if (m_torrent == torrent) - loadTorrentInfos(m_torrent); -} - -void PropertiesWidget::loadTorrentInfos(BitTorrent::TorrentHandle *const torrent) -{ - clear(); - m_torrent = torrent; - downloaded_pieces->setTorrent(m_torrent); - pieces_availability->setTorrent(m_torrent); - if (!m_torrent) return; - - // Save path - updateSavePath(m_torrent); - // Hash - m_ui->hash_lbl->setText(m_torrent->hash()); - PropListModel->model()->clear(); - if (m_torrent->hasMetadata()) { - // Creation date - m_ui->lbl_creationDate->setText(m_torrent->creationDate().toString(Qt::DefaultLocaleShortDate)); - - m_ui->label_total_size_val->setText(Utils::Misc::friendlyUnit(m_torrent->totalSize())); - - // Comment - m_ui->comment_text->setText(Utils::Misc::parseHtmlLinks(m_torrent->comment().toHtmlEscaped())); - - // URL seeds - loadUrlSeeds(); - - m_ui->label_created_by_val->setText(m_torrent->creator().toHtmlEscaped()); - - // List files in torrent - PropListModel->model()->setupModelData(m_torrent->info()); - if ((m_torrent->filesCount() > 1) && (PropListModel->model()->rowCount() == 1)) - m_ui->filesList->setExpanded(PropListModel->index(0, 0), true); - - // Load file priorities - PropListModel->model()->updateFilesPriorities(m_torrent->filePriorities()); - } - // Load dynamic data - loadDynamicData(); -} - -void PropertiesWidget::readSettings() -{ - const Preferences *const pref = Preferences::instance(); - // Restore splitter sizes - QStringList sizes_str = pref->getPropSplitterSizes().split(","); - if (sizes_str.size() == 2) { - slideSizes << sizes_str.first().toInt(); - slideSizes << sizes_str.last().toInt(); - QSplitter *hSplitter = static_cast(parentWidget()); - hSplitter->setSizes(slideSizes); - } - const int current_tab = pref->getPropCurTab(); - const bool visible = pref->getPropVisible(); - // the following will call saveSettings but shouldn't change any state - if (!m_ui->filesList->header()->restoreState(pref->getPropFileListState())) - m_ui->filesList->header()->resizeSection(0, 400); // Default - m_tabBar->setCurrentIndex(current_tab); - if (!visible) - setVisibility(false); -} - -void PropertiesWidget::saveSettings() -{ - Preferences *const pref = Preferences::instance(); - pref->setPropVisible(state == VISIBLE); - // Splitter sizes - QSplitter *hSplitter = static_cast(parentWidget()); - QList sizes; - if (state == VISIBLE) - sizes = hSplitter->sizes(); - else - sizes = slideSizes; - qDebug("Sizes: %d", sizes.size()); - if (sizes.size() == 2) - pref->setPropSplitterSizes(QString::number(sizes.first()) + ',' + QString::number(sizes.last())); - pref->setPropFileListState(m_ui->filesList->header()->saveState()); - // Remember current tab - pref->setPropCurTab(m_tabBar->currentIndex()); -} - -void PropertiesWidget::reloadPreferences() -{ - // Take program preferences into consideration - peersList->updatePeerHostNameResolutionState(); - peersList->updatePeerCountryResolutionState(); -} - -void PropertiesWidget::loadDynamicData() -{ - // Refresh only if the torrent handle is valid and if visible - if (!m_torrent || (main_window->currentTabWidget() != transferList) || (state != VISIBLE)) return; - - // Transfer infos - switch (m_ui->stackedProperties->currentIndex()) { - case PropTabBar::MAIN_TAB: { - m_ui->wasted->setText(Utils::Misc::friendlyUnit(m_torrent->wastedSize())); - - m_ui->upTotal->setText(tr("%1 (%2 this session)").arg(Utils::Misc::friendlyUnit(m_torrent->totalUpload())) - .arg(Utils::Misc::friendlyUnit(m_torrent->totalPayloadUpload()))); - - m_ui->dlTotal->setText(tr("%1 (%2 this session)").arg(Utils::Misc::friendlyUnit(m_torrent->totalDownload())) - .arg(Utils::Misc::friendlyUnit(m_torrent->totalPayloadDownload()))); - - m_ui->lbl_uplimit->setText(m_torrent->uploadLimit() <= 0 ? QString::fromUtf8(C_INFINITY) : Utils::Misc::friendlyUnit(m_torrent->uploadLimit(), true)); - - m_ui->lbl_dllimit->setText(m_torrent->downloadLimit() <= 0 ? QString::fromUtf8(C_INFINITY) : Utils::Misc::friendlyUnit(m_torrent->downloadLimit(), true)); - - QString elapsed_txt; - if (m_torrent->isSeed()) - elapsed_txt = tr("%1 (seeded for %2)", "e.g. 4m39s (seeded for 3m10s)") - .arg(Utils::Misc::userFriendlyDuration(m_torrent->activeTime())) - .arg(Utils::Misc::userFriendlyDuration(m_torrent->seedingTime())); - else - elapsed_txt = Utils::Misc::userFriendlyDuration(m_torrent->activeTime()); - m_ui->lbl_elapsed->setText(elapsed_txt); - - m_ui->lbl_connections->setText(tr("%1 (%2 max)", "%1 and %2 are numbers, e.g. 3 (10 max)") - .arg(m_torrent->connectionsCount()) - .arg(m_torrent->connectionsLimit() < 0 ? QString::fromUtf8(C_INFINITY) : QString::number(m_torrent->connectionsLimit()))); - - m_ui->label_eta_val->setText(Utils::Misc::userFriendlyDuration(m_torrent->eta())); - - // Update next announce time - m_ui->reannounce_lbl->setText(Utils::Misc::userFriendlyDuration(m_torrent->nextAnnounce())); - - // Update ratio info - const qreal ratio = m_torrent->realRatio(); - m_ui->shareRatio->setText(ratio > BitTorrent::TorrentHandle::MAX_RATIO ? QString::fromUtf8(C_INFINITY) : Utils::String::fromDouble(ratio, 2)); - - m_ui->label_seeds_val->setText(tr("%1 (%2 total)", "%1 and %2 are numbers, e.g. 3 (10 total)") - .arg(QString::number(m_torrent->seedsCount())) - .arg(QString::number(m_torrent->totalSeedsCount()))); - - m_ui->label_peers_val->setText(tr("%1 (%2 total)", "%1 and %2 are numbers, e.g. 3 (10 total)") - .arg(QString::number(m_torrent->leechsCount())) - .arg(QString::number(m_torrent->totalLeechersCount()))); - - m_ui->label_dl_speed_val->setText(tr("%1 (%2 avg.)", "%1 and %2 are speed rates, e.g. 200KiB/s (100KiB/s avg.)") - .arg(Utils::Misc::friendlyUnit(m_torrent->downloadPayloadRate(), true)) - .arg(Utils::Misc::friendlyUnit(m_torrent->totalDownload() / (1 + m_torrent->activeTime() - m_torrent->finishedTime()), true))); - - m_ui->label_upload_speed_val->setText(tr("%1 (%2 avg.)", "%1 and %2 are speed rates, e.g. 200KiB/s (100KiB/s avg.)") - .arg(Utils::Misc::friendlyUnit(m_torrent->uploadPayloadRate(), true)) - .arg(Utils::Misc::friendlyUnit(m_torrent->totalUpload() / (1 + m_torrent->activeTime()), true))); - - m_ui->label_last_complete_val->setText(m_torrent->lastSeenComplete().isValid() ? m_torrent->lastSeenComplete().toString(Qt::DefaultLocaleShortDate) : tr("Never")); - - m_ui->label_completed_on_val->setText(m_torrent->completedTime().isValid() ? m_torrent->completedTime().toString(Qt::DefaultLocaleShortDate) : ""); - - m_ui->label_added_on_val->setText(m_torrent->addedTime().toString(Qt::DefaultLocaleShortDate)); - - if (m_torrent->hasMetadata()) { - m_ui->label_total_pieces_val->setText(tr("%1 x %2 (have %3)", "(torrent pieces) eg 152 x 4MB (have 25)").arg(m_torrent->piecesCount()).arg(Utils::Misc::friendlyUnit(m_torrent->pieceLength())).arg(m_torrent->piecesHave())); - - if (!m_torrent->isSeed() && !m_torrent->isPaused() && !m_torrent->isQueued() && !m_torrent->isChecking()) { - // Pieces availability - showPiecesAvailability(true); - pieces_availability->setAvailability(m_torrent->pieceAvailability()); - m_ui->avail_average_lbl->setText(Utils::String::fromDouble(m_torrent->distributedCopies(), 3)); - } - else { - showPiecesAvailability(false); - } - - // Progress - qreal progress = m_torrent->progress() * 100.; - m_ui->progress_lbl->setText(Utils::String::fromDouble(progress, 1) + "%"); - downloaded_pieces->setProgress(m_torrent->pieces(), m_torrent->downloadingPieces()); - } - else { - showPiecesAvailability(false); - } - - break; - } - - case PropTabBar::TRACKERS_TAB: { - // Trackers - trackerList->loadTrackers(); - break; - } - - case PropTabBar::PEERS_TAB: { - // Load peers - peersList->loadPeers(m_torrent); - break; - } - - case PropTabBar::FILES_TAB: { - // Files progress - if (m_torrent->hasMetadata()) { - qDebug("Updating priorities in files tab"); - m_ui->filesList->setUpdatesEnabled(false); - PropListModel->model()->updateFilesProgress(m_torrent->filesProgress()); - PropListModel->model()->updateFilesAvailability(m_torrent->availableFileFractions()); - // XXX: We don't update file priorities regularly for performance - // reasons. This means that priorities will not be updated if - // set from the Web UI. - // PropListModel->model()->updateFilesPriorities(h.file_priorities()); - m_ui->filesList->setUpdatesEnabled(true); - } - break; - } - - default:; - } -} - -void PropertiesWidget::loadUrlSeeds() -{ - m_ui->listWebSeeds->clear(); - qDebug("Loading URL seeds"); - const QList hc_seeds = m_torrent->urlSeeds(); - // Add url seeds - foreach (const QUrl &hc_seed, hc_seeds) { - qDebug("Loading URL seed: %s", qPrintable(hc_seed.toString())); - new QListWidgetItem(hc_seed.toString(), m_ui->listWebSeeds); - } -} - -void PropertiesWidget::openDoubleClickedFile(const QModelIndex &index) -{ - if (!index.isValid()) return; - if (!m_torrent || !m_torrent->hasMetadata()) return; - if (PropListModel->itemType(index) == TorrentContentModelItem::FileType) - openFile(index); - else - openFolder(index, false); -} - -void PropertiesWidget::openFile(const QModelIndex &index) -{ - int i = PropListModel->getFileIndex(index); - const QDir saveDir(m_torrent->savePath(true)); - const QString filename = m_torrent->filePath(i); - const QString file_path = Utils::Fs::expandPath(saveDir.absoluteFilePath(filename)); - qDebug("Trying to open file at %s", qPrintable(file_path)); - // Flush data - m_torrent->flushCache(); - Utils::Misc::openPath(file_path); -} - -void PropertiesWidget::openFolder(const QModelIndex &index, bool containing_folder) -{ - QString absolute_path; - // FOLDER - if (PropListModel->itemType(index) == TorrentContentModelItem::FolderType) { - // Generate relative path to selected folder - QStringList path_items; - path_items << index.data().toString(); - QModelIndex parent = PropListModel->parent(index); - while (parent.isValid()) { - path_items.prepend(parent.data().toString()); - parent = PropListModel->parent(parent); - } - if (path_items.isEmpty()) - return; - const QDir saveDir(m_torrent->savePath(true)); - const QString relative_path = path_items.join("/"); - absolute_path = Utils::Fs::expandPath(saveDir.absoluteFilePath(relative_path)); - } - else { - int i = PropListModel->getFileIndex(index); - const QDir saveDir(m_torrent->savePath(true)); - const QString relative_path = m_torrent->filePath(i); - absolute_path = Utils::Fs::expandPath(saveDir.absoluteFilePath(relative_path)); - } - - // Flush data - m_torrent->flushCache(); - if (containing_folder) - Utils::Misc::openFolderSelect(absolute_path); - else - Utils::Misc::openPath(absolute_path); -} - -void PropertiesWidget::displayFilesListMenu(const QPoint &) -{ - if (!m_torrent) return; - - QModelIndexList selectedRows = m_ui->filesList->selectionModel()->selectedRows(0); - if (selectedRows.empty()) - return; - QMenu myFilesLlistMenu; - QAction *actOpen = nullptr; - QAction *actOpenContainingFolder = nullptr; - QAction *actRename = nullptr; - if (selectedRows.size() == 1) { - actOpen = myFilesLlistMenu.addAction(GuiIconProvider::instance()->getIcon("folder-documents"), tr("Open")); - actOpenContainingFolder = myFilesLlistMenu.addAction(GuiIconProvider::instance()->getIcon("inode-directory"), tr("Open Containing Folder")); - actRename = myFilesLlistMenu.addAction(GuiIconProvider::instance()->getIcon("edit-rename"), tr("Rename...")); - myFilesLlistMenu.addSeparator(); - } - QMenu subMenu; - if (!m_torrent->isSeed()) { - subMenu.setTitle(tr("Priority")); - subMenu.addAction(m_ui->actionNot_downloaded); - subMenu.addAction(m_ui->actionNormal); - subMenu.addAction(m_ui->actionHigh); - subMenu.addAction(m_ui->actionMaximum); - myFilesLlistMenu.addMenu(&subMenu); - } - // Call menu - const QAction *act = myFilesLlistMenu.exec(QCursor::pos()); - // The selected torrent might have disappeared during exec() - // from the current view thus leaving invalid indices. - const QModelIndex index = *(selectedRows.begin()); - if (!index.isValid()) - return; - if (act) { - if (act == actOpen) { - openDoubleClickedFile(index); - } - else if (act == actOpenContainingFolder) { - openFolder(index, true); - } - else if (act == actRename) { - renameSelectedFile(); - } - else { - int prio = prio::NORMAL; - if (act == m_ui->actionHigh) - prio = prio::HIGH; - else if (act == m_ui->actionMaximum) - prio = prio::MAXIMUM; - else if (act == m_ui->actionNot_downloaded) - prio = prio::IGNORED; - - qDebug("Setting files priority"); - foreach (QModelIndex index, selectedRows) { - qDebug("Setting priority(%d) for file at row %d", prio, index.row()); - PropListModel->setData(PropListModel->index(index.row(), PRIORITY, index.parent()), prio); - } - // Save changes - filteredFilesChanged(); - } - } -} - -void PropertiesWidget::displayWebSeedListMenu(const QPoint &) -{ - if (!m_torrent) return; - - QMenu seedMenu; - QModelIndexList rows = m_ui->listWebSeeds->selectionModel()->selectedRows(); - QAction *actAdd = seedMenu.addAction(GuiIconProvider::instance()->getIcon("list-add"), tr("New Web seed")); - QAction *actDel = nullptr; - QAction *actCpy = nullptr; - QAction *actEdit = nullptr; - - if (rows.size()) { - actDel = seedMenu.addAction(GuiIconProvider::instance()->getIcon("list-remove"), tr("Remove Web seed")); - seedMenu.addSeparator(); - actCpy = seedMenu.addAction(GuiIconProvider::instance()->getIcon("edit-copy"), tr("Copy Web seed URL")); - actEdit = seedMenu.addAction(GuiIconProvider::instance()->getIcon("edit-rename"), tr("Edit Web seed URL")); - } - - const QAction *act = seedMenu.exec(QCursor::pos()); - if (act) { - if (act == actAdd) - askWebSeed(); - else if (act == actDel) - deleteSelectedUrlSeeds(); - else if (act == actCpy) - copySelectedWebSeedsToClipboard(); - else if (act == actEdit) - editWebSeed(); - } -} - -void PropertiesWidget::renameSelectedFile() -{ - if (!m_torrent) return; - - const QModelIndexList selectedIndexes = m_ui->filesList->selectionModel()->selectedRows(0); - if (selectedIndexes.size() != 1) return; - - const QModelIndex modelIndex = selectedIndexes.first(); - if (!modelIndex.isValid()) return; - - // Ask for new name - bool ok = false; - QString newName = AutoExpandableDialog::getText(this, tr("Renaming"), tr("New name:"), QLineEdit::Normal, modelIndex.data().toString(), &ok) - .trimmed(); - if (!ok) return; - - if (newName.isEmpty() || !Utils::Fs::isValidFileSystemName(newName)) { - MessageBoxRaised::warning(this, tr("Rename error"), - tr("The name is empty or contains forbidden characters, please choose a different one."), - QMessageBox::Ok); - return; - } - - if (PropListModel->itemType(modelIndex) == TorrentContentModelItem::FileType) { - // renaming a file - const int fileIndex = PropListModel->getFileIndex(modelIndex); - - if (newName.endsWith(QB_EXT)) - newName.chop(QB_EXT.size()); - const QString oldFileName = m_torrent->fileName(fileIndex); - const QString oldFilePath = m_torrent->filePath(fileIndex); - const QString newFileName = newName + (BitTorrent::Session::instance()->isAppendExtensionEnabled() ? QB_EXT : QString()); - const QString newFilePath = oldFilePath.leftRef(oldFilePath.size() - oldFileName.size()) + newFileName; - - if (oldFileName == newFileName) { - qDebug("Name did not change: %s", qPrintable(oldFileName)); - return; - } - - // check if that name is already used - for (int i = 0; i < m_torrent->filesCount(); ++i) { - if (i == fileIndex) continue; - if (Utils::Fs::sameFileNames(m_torrent->filePath(i), newFilePath)) { - MessageBoxRaised::warning(this, tr("Rename error"), - tr("This name is already in use in this folder. Please use a different name."), - QMessageBox::Ok); - return; - } - } - - qDebug("Renaming %s to %s", qPrintable(oldFilePath), qPrintable(newFilePath)); - m_torrent->renameFile(fileIndex, newFilePath); - - PropListModel->setData(modelIndex, newName); - } - else { - // renaming a folder - QStringList pathItems; - pathItems << modelIndex.data().toString(); - QModelIndex parent = PropListModel->parent(modelIndex); - while (parent.isValid()) { - pathItems.prepend(parent.data().toString()); - parent = PropListModel->parent(parent); - } - const QString oldPath = pathItems.join("/"); - pathItems.removeLast(); - pathItems << newName; - QString newPath = pathItems.join("/"); - if (Utils::Fs::sameFileNames(oldPath, newPath)) { - qDebug("Name did not change"); - return; - } - if (!newPath.endsWith("/")) newPath += "/"; - // Check for overwriting - for (int i = 0; i < m_torrent->filesCount(); ++i) { - const QString ¤tName = m_torrent->filePath(i); -#if defined(Q_OS_UNIX) || defined(Q_WS_QWS) - if (currentName.startsWith(newPath, Qt::CaseSensitive)) { -#else - if (currentName.startsWith(newPath, Qt::CaseInsensitive)) { -#endif - QMessageBox::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; - } - } - bool forceRecheck = false; - // Replace path in all files - for (int i = 0; i < m_torrent->filesCount(); ++i) { - const QString currentName = m_torrent->filePath(i); - if (currentName.startsWith(oldPath)) { - QString newName = currentName; - newName.replace(0, oldPath.length(), newPath); - if (!forceRecheck && QDir(m_torrent->savePath(true)).exists(newName)) - forceRecheck = true; - newName = Utils::Fs::expandPath(newName); - qDebug("Rename %s to %s", qPrintable(currentName), qPrintable(newName)); - m_torrent->renameFile(i, newName); - } - } - // Force recheck - if (forceRecheck) m_torrent->forceRecheck(); - // Rename folder in torrent files model too - PropListModel->setData(modelIndex, newName); - // Remove old folder - const QDir oldFolder(m_torrent->savePath(true) + "/" + oldPath); - int timeout = 10; - while (!QDir().rmpath(oldFolder.absolutePath()) && timeout > 0) { - // FIXME: We should not sleep here (freezes the UI for 1 second) - QThread::msleep(100); - --timeout; - } - } -} - -void PropertiesWidget::openSelectedFile() -{ - const QModelIndexList selectedIndexes = m_ui->filesList->selectionModel()->selectedRows(0); - if (selectedIndexes.size() != 1) - return; - openDoubleClickedFile(selectedIndexes.first()); -} - -void PropertiesWidget::askWebSeed() -{ - bool ok; - // Ask user for a new url seed - const QString url_seed = AutoExpandableDialog::getText(this, tr("New URL seed", "New HTTP source"), - tr("New URL seed:"), QLineEdit::Normal, - QString::fromUtf8("http://www."), &ok); - if (!ok) return; - qDebug("Adding %s web seed", qPrintable(url_seed)); - if (!m_ui->listWebSeeds->findItems(url_seed, Qt::MatchFixedString).empty()) { - QMessageBox::warning(this, "qBittorrent", - tr("This URL seed is already in the list."), - QMessageBox::Ok); - return; - } - if (m_torrent) - m_torrent->addUrlSeeds(QList() << url_seed); - // Refresh the seeds list - loadUrlSeeds(); -} - -void PropertiesWidget::deleteSelectedUrlSeeds() -{ - const QList selectedItems = m_ui->listWebSeeds->selectedItems(); - if (selectedItems.isEmpty()) return; - - QList urlSeeds; - foreach (const QListWidgetItem *item, selectedItems) - urlSeeds << item->text(); - - m_torrent->removeUrlSeeds(urlSeeds); - // Refresh list - loadUrlSeeds(); -} - -void PropertiesWidget::copySelectedWebSeedsToClipboard() const -{ - const QList selected_items = m_ui->listWebSeeds->selectedItems(); - if (selected_items.isEmpty()) - return; - - QStringList urls_to_copy; - foreach (QListWidgetItem *item, selected_items) - urls_to_copy << item->text(); - - QApplication::clipboard()->setText(urls_to_copy.join("\n")); -} - -void PropertiesWidget::editWebSeed() -{ - const QList selected_items = m_ui->listWebSeeds->selectedItems(); - if (selected_items.size() != 1) - return; - - const QListWidgetItem *selected_item = selected_items.last(); - const QString old_seed = selected_item->text(); - bool result; - const QString new_seed = AutoExpandableDialog::getText(this, tr("Web seed editing"), - tr("Web seed URL:"), QLineEdit::Normal, - old_seed, &result); - if (!result) - return; - - if (!m_ui->listWebSeeds->findItems(new_seed, Qt::MatchFixedString).empty()) { - QMessageBox::warning(this, tr("qBittorrent"), - tr("This URL seed is already in the list."), - QMessageBox::Ok); - return; - } - - m_torrent->removeUrlSeeds(QList() << old_seed); - m_torrent->addUrlSeeds(QList() << new_seed); - loadUrlSeeds(); -} - -bool PropertiesWidget::applyPriorities() -{ - qDebug("Saving files priorities"); - const QVector priorities = PropListModel->model()->getFilePriorities(); - // Prioritize the files - qDebug("prioritize files: %d", priorities[0]); - m_torrent->prioritizeFiles(priorities); - return true; -} - -void PropertiesWidget::filteredFilesChanged() -{ - if (m_torrent) - applyPriorities(); -} - -void PropertiesWidget::filterText(const QString &filter) -{ - PropListModel->setFilterRegExp(QRegExp(filter, Qt::CaseInsensitive, QRegExp::WildcardUnix)); - if (filter.isEmpty()) { - m_ui->filesList->collapseAll(); - m_ui->filesList->expand(PropListModel->index(0, 0)); - } - else { - m_ui->filesList->expandAll(); - } -} diff --git a/src/gui/properties/propertieswidget.h b/src/gui/properties/propertieswidget.h deleted file mode 100644 index 9bfefe10c..000000000 --- a/src/gui/properties/propertieswidget.h +++ /dev/null @@ -1,144 +0,0 @@ -/* - * Bittorrent Client using Qt4 and libtorrent. - * Copyright (C) 2006 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 PROPERTIESWIDGET_H -#define PROPERTIESWIDGET_H - -#include -#include - -#include "base/bittorrent/torrenthandle.h" - -class TransferListWidget; -class TorrentContentFilterModel; -class PropListDelegate; -class torrent_file; -class PeerListWidget; -class TrackerList; -class SpeedWidget; -class MainWindow; -class DownloadedPiecesBar; -class PieceAvailabilityBar; -class PropTabBar; -class LineEdit; - -QT_BEGIN_NAMESPACE -class QAction; -class QPushButton; -class QTimer; -class QTreeView; -QT_END_NAMESPACE - -namespace Ui -{ - class PropertiesWidget; -} - -class PropertiesWidget: public QWidget -{ - Q_OBJECT - Q_DISABLE_COPY(PropertiesWidget) - -public: - enum SlideState - { - REDUCED, - VISIBLE - }; - - PropertiesWidget(QWidget *parent, MainWindow *main_window, TransferListWidget *transferList); - ~PropertiesWidget(); - BitTorrent::TorrentHandle *getCurrentTorrent() const; - TrackerList *getTrackerList() const { return trackerList; } - PeerListWidget *getPeerList() const { return peersList; } - QTreeView *getFilesList() const; - SpeedWidget *getSpeedWidget() const { return speedWidget; } - -public slots: - void setVisibility(bool visible); - void loadDynamicData(); - void clear(); - void readSettings(); - void saveSettings(); - void reloadPreferences(); - void openDoubleClickedFile(const QModelIndex &); - void loadTrackers(BitTorrent::TorrentHandle *const torrent); - -protected: - QPushButton *getButtonFromIndex(int index); - bool applyPriorities(); - -protected slots: - void loadTorrentInfos(BitTorrent::TorrentHandle *const torrent); - void updateTorrentInfos(BitTorrent::TorrentHandle *const torrent); - void loadUrlSeeds(); - void askWebSeed(); - void deleteSelectedUrlSeeds(); - void copySelectedWebSeedsToClipboard() const; - void editWebSeed(); - void displayFilesListMenu(const QPoint &pos); - void displayWebSeedListMenu(const QPoint &pos); - void filteredFilesChanged(); - void showPiecesDownloaded(bool show); - void showPiecesAvailability(bool show); - void renameSelectedFile(); - void openSelectedFile(); - -private: - void openFile(const QModelIndex &index); - void openFolder(const QModelIndex &index, bool containing_folder); - - Ui::PropertiesWidget *m_ui; - TransferListWidget *transferList; - MainWindow *main_window; - BitTorrent::TorrentHandle *m_torrent; - QTimer *refreshTimer; - SlideState state; - TorrentContentFilterModel *PropListModel; - PropListDelegate *PropDelegate; - PeerListWidget *peersList; - TrackerList *trackerList; - SpeedWidget *speedWidget; - QList slideSizes; - DownloadedPiecesBar *downloaded_pieces; - PieceAvailabilityBar *pieces_availability; - PropTabBar *m_tabBar; - LineEdit *m_contentFilterLine; - QShortcut *editHotkeyFile; - QShortcut *editHotkeyWeb; - QShortcut *deleteHotkeyWeb; - QShortcut *openHotkeyFile; - -private slots: - void filterText(const QString &filter); - void updateSavePath(BitTorrent::TorrentHandle *const torrent); -}; - -#endif // PROPERTIESWIDGET_H diff --git a/src/gui/properties/propertieswidget.ui b/src/gui/properties/propertieswidget.ui deleted file mode 100644 index 01d4e2faf..000000000 --- a/src/gui/properties/propertieswidget.ui +++ /dev/null @@ -1,1116 +0,0 @@ - - - PropertiesWidget - - - - 0 - 0 - 551 - 452 - - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - 0 - - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - true - - - - - 0 - 0 - 549 - 450 - - - - - - - - 4 - - - 4 - - - - - - 0 - 0 - - - - Progress: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - 0 - 0 - - - - Qt::PlainText - - - - - - - - 0 - 0 - - - - Availability: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - 0 - 0 - - - - Qt::PlainText - - - - - - - Qt::PlainText - - - - - - - Qt::PlainText - - - - - - - - - - Qt::Horizontal - - - - - - - Transfer - - - - 4 - - - 4 - - - - - - 0 - 0 - - - - Qt::PlainText - - - - - - - - 0 - 0 - - - - Upload Speed: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - 0 - 0 - - - - Qt::PlainText - - - - - - - - 0 - 0 - - - - Peers: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - 0 - 0 - - - - Connections: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - 0 - 0 - - - - Qt::PlainText - - - - - - - - 0 - 0 - - - - Qt::PlainText - - - - - - - - 0 - 0 - - - - Download Limit: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - 0 - 0 - - - - Share Ratio: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - 0 - 0 - - - - Qt::PlainText - - - - - - - - 0 - 0 - - - - Qt::PlainText - - - - - - - - 0 - 0 - - - - Downloaded: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - 0 - 0 - - - - Upload Limit: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - 0 - 0 - - - - Last Seen Complete: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - 0 - 0 - - - - Qt::PlainText - - - - - - - - 0 - 0 - - - - Qt::PlainText - - - - - - - - 0 - 0 - - - - Reannounce In: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - 0 - 0 - - - - Qt::PlainText - - - - - - - - 0 - 0 - - - - Seeds: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - 0 - 0 - - - - Download Speed: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - 0 - 0 - - - - Qt::PlainText - - - - - - - - 0 - 0 - - - - Qt::PlainText - - - - - - - - 0 - 0 - - - - Qt::PlainText - - - - - - - - 0 - 0 - - - - Uploaded: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - 0 - 0 - - - - Qt::PlainText - - - - - - - - 0 - 0 - - - - Qt::PlainText - - - - - - - - 0 - 0 - - - - Time Active: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - 0 - 0 - - - - Qt::PlainText - - - - - - - - 0 - 0 - - - - ETA: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - 0 - 0 - - - - Wasted: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - - - Information - - - - 4 - - - 2 - - - - - - 0 - 0 - - - - Total Size: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - 0 - 0 - - - - Qt::PlainText - - - - - - - - 0 - 0 - - - - Pieces: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - 0 - 0 - - - - Qt::PlainText - - - - - - - - 0 - 0 - - - - Created By: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - 0 - 0 - - - - Qt::PlainText - - - - - - - - 0 - 0 - - - - Added On: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - 0 - 0 - - - - Qt::PlainText - - - - - - - - 0 - 0 - - - - Completed On: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - 0 - 0 - - - - Qt::PlainText - - - - - - - - 0 - 0 - - - - Created On: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - 0 - 0 - - - - Qt::PlainText - - - - - - - - 0 - 0 - - - - Torrent Hash: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - 0 - 0 - - - - Qt::PlainText - - - Qt::TextSelectableByMouse - - - - - - - - 0 - 0 - - - - Save Path: - - - Qt::AlignRight|Qt::AlignTop|Qt::AlignTrailing - - - - - - - - 0 - 0 - - - - Qt::PlainText - - - true - - - Qt::TextSelectableByMouse - - - - - - - - 0 - 0 - - - - Comment: - - - Qt::AlignRight|Qt::AlignTop|Qt::AlignTrailing - - - - - - - - 0 - 0 - - - - Qt::RichText - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop - - - true - - - true - - - Qt::TextBrowserInteraction - - - true - - - - - - - - - - - - - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - Qt::CustomContextMenu - - - QAbstractItemView::ExtendedSelection - - - - - - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - - - Select All - - - - - - - Select None - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - Qt::CustomContextMenu - - - QAbstractItemView::AllEditTriggers - - - QAbstractItemView::ExtendedSelection - - - true - - - - - - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - - - - - Do not download - - - Do not download - - - - - Maximum - - - - - High - - - - - Normal - - - - - - TorrentContentTreeView - QTreeView -
torrentcontenttreeview.h
-
-
- - -
diff --git a/src/gui/properties/proplistdelegate.cpp b/src/gui/properties/proplistdelegate.cpp deleted file mode 100644 index b1b1b3645..000000000 --- a/src/gui/properties/proplistdelegate.cpp +++ /dev/null @@ -1,224 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2006 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 "proplistdelegate.h" - -#include -#include -#include -#include -#include -#include -#include - -#ifdef Q_OS_WIN -#include -#endif - -#include "base/unicodestrings.h" -#include "base/utils/misc.h" -#include "base/utils/string.h" -#include "propertieswidget.h" -#include "torrentcontentmodelitem.h" - -namespace -{ - - QPalette progressBarDisabledPalette() - { - auto getPalette = []() { - QProgressBar bar; - bar.setEnabled(false); - QStyleOptionProgressBar opt; - opt.initFrom(&bar); - return opt.palette; - }; - static QPalette palette = getPalette(); - return palette; - } -} - -PropListDelegate::PropListDelegate(PropertiesWidget *properties) - : QItemDelegate(properties) - , m_properties(properties) -{ -} - -void PropListDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const -{ - painter->save(); - QStyleOptionViewItem opt = QItemDelegate::setOptions(index, option); - QItemDelegate::drawBackground(painter, opt, index); - - switch (index.column()) { - case PCSIZE: - case REMAINING: - QItemDelegate::drawDisplay(painter, opt, option.rect, Utils::Misc::friendlyUnit(index.data().toLongLong())); - break; - case PROGRESS: { - if (index.data().toDouble() < 0) - break; - - QStyleOptionProgressBar newopt; - qreal progress = index.data().toDouble() * 100.; - newopt.rect = opt.rect; - newopt.text = ((progress == 100.0) ? QString("100%") : Utils::String::fromDouble(progress, 1) + "%"); - newopt.progress = int(progress); - newopt.maximum = 100; - newopt.minimum = 0; - newopt.textVisible = true; - if (index.sibling(index.row(), PRIORITY).data().toInt() == prio::IGNORED) { - newopt.state &= ~QStyle::State_Enabled; - newopt.palette = progressBarDisabledPalette(); - } - else { - newopt.state |= QStyle::State_Enabled; - } - -#ifndef Q_OS_WIN - QApplication::style()->drawControl(QStyle::CE_ProgressBar, &newopt, painter); -#else - // XXX: To avoid having the progress text on the right of the bar - QProxyStyle("fusion").drawControl(QStyle::CE_ProgressBar, &newopt, painter, 0); -#endif - } - break; - case PRIORITY: { - QString text = ""; - switch (index.data().toInt()) { - case prio::MIXED: - text = tr("Mixed", "Mixed (priorities"); - break; - case prio::IGNORED: - text = tr("Not downloaded"); - break; - case prio::HIGH: - text = tr("High", "High (priority)"); - break; - case prio::MAXIMUM: - text = tr("Maximum", "Maximum (priority)"); - break; - default: - text = tr("Normal", "Normal (priority)"); - break; - } - QItemDelegate::drawDisplay(painter, opt, option.rect, text); - } - break; - case AVAILABILITY: { - const qreal availability = index.data().toDouble(); - if (availability < 0) { - QItemDelegate::drawDisplay(painter, opt, option.rect, tr("N/A")); - } - else { - const QString value = (availability >= 1.0) - ? QLatin1String("100") - : Utils::String::fromDouble(availability * 100., 1); - QItemDelegate::drawDisplay(painter, opt, option.rect, value + C_THIN_SPACE + QLatin1Char('%')); - } - } - break; - default: - QItemDelegate::paint(painter, option, index); - break; - } - painter->restore(); -} - -void PropListDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const -{ - QComboBox *combobox = static_cast(editor); - // Set combobox index - switch (index.data().toInt()) { - case prio::IGNORED: - combobox->setCurrentIndex(0); - break; - case prio::HIGH: - combobox->setCurrentIndex(2); - break; - case prio::MAXIMUM: - combobox->setCurrentIndex(3); - break; - default: - combobox->setCurrentIndex(1); - break; - } -} - -QWidget *PropListDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &, const QModelIndex &index) const -{ - if (index.column() != PRIORITY) return 0; - - if (m_properties) { - BitTorrent::TorrentHandle *const torrent = m_properties->getCurrentTorrent(); - if (!torrent || !torrent->hasMetadata() || torrent->isSeed()) - return 0; - } - - if (index.data().toInt() == prio::MIXED) - return 0; - - QComboBox *editor = new QComboBox(parent); - editor->setFocusPolicy(Qt::StrongFocus); - editor->addItem(tr("Do not download", "Do not download (priority)")); - editor->addItem(tr("Normal", "Normal (priority)")); - editor->addItem(tr("High", "High (priority)")); - editor->addItem(tr("Maximum", "Maximum (priority)")); - return editor; -} - -void PropListDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const -{ - QComboBox *combobox = static_cast(editor); - int value = combobox->currentIndex(); - qDebug("PropListDelegate: setModelData(%d)", value); - - switch (value) { - case 0: - model->setData(index, prio::IGNORED); // IGNORED - break; - case 2: - model->setData(index, prio::HIGH); // HIGH - break; - case 3: - model->setData(index, prio::MAXIMUM); // MAX - break; - default: - model->setData(index, prio::NORMAL); // NORMAL - } - - emit filteredFilesChanged(); -} - -void PropListDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &) const -{ - qDebug("UpdateEditor Geometry called"); - editor->setGeometry(option.rect); -} diff --git a/src/gui/properties/proplistdelegate.h b/src/gui/properties/proplistdelegate.h deleted file mode 100644 index ed9035349..000000000 --- a/src/gui/properties/proplistdelegate.h +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2006 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 PROPLISTDELEGATE_H -#define PROPLISTDELEGATE_H - -#include - -class QPainter; -class QModelIndex; -class QStyleOptionViewItem; -class QAbstractItemModel; -class PropertiesWidget; - -// Defines for properties list columns -enum PropColumn -{ - NAME, - PCSIZE, - PROGRESS, - PRIORITY, - REMAINING, - AVAILABILITY -}; - -class PropListDelegate: public QItemDelegate -{ - Q_OBJECT - -public: - PropListDelegate(PropertiesWidget *properties); - - void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override; - void setEditorData(QWidget *editor, const QModelIndex &index) const override; - QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem & /* option */, const QModelIndex &index) const override; - -public slots: - void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const override; - void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex & /* index */) const override; - -signals: - void filteredFilesChanged() const; - -private: - PropertiesWidget *m_properties; -}; - -#endif - diff --git a/src/gui/properties/proptabbar.cpp b/src/gui/properties/proptabbar.cpp deleted file mode 100644 index b2edf10f3..000000000 --- a/src/gui/properties/proptabbar.cpp +++ /dev/null @@ -1,143 +0,0 @@ -/* - * Bittorrent Client using Qt4 and libtorrent. - * Copyright (C) 2010 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 -#include -#include -#include - -#include "proptabbar.h" -#include "guiiconprovider.h" - -PropTabBar::PropTabBar(QWidget *parent) : - QHBoxLayout(parent), m_currentIndex(-1) -{ - setAlignment(Qt::AlignLeft | Qt::AlignCenter); - setSpacing(3); - m_btnGroup = new QButtonGroup(this); - // General tab - QPushButton *main_infos_button = new QPushButton( -#ifndef Q_OS_MAC - GuiIconProvider::instance()->getIcon("document-properties"), -#endif - tr("General"), parent); - main_infos_button->setShortcut(Qt::ALT + Qt::Key_G); - addWidget(main_infos_button); - m_btnGroup->addButton(main_infos_button, MAIN_TAB); - // Trackers tab - QPushButton *trackers_button = new QPushButton( -#ifndef Q_OS_MAC - GuiIconProvider::instance()->getIcon("network-server"), -#endif - tr("Trackers"), parent); - trackers_button->setShortcut(Qt::ALT + Qt::Key_C); - addWidget(trackers_button); - m_btnGroup->addButton(trackers_button, TRACKERS_TAB); - // Peers tab - QPushButton *peers_button = new QPushButton( -#ifndef Q_OS_MAC - GuiIconProvider::instance()->getIcon("edit-find-user"), -#endif - tr("Peers"), parent); - peers_button->setShortcut(Qt::ALT + Qt::Key_R); - addWidget(peers_button); - m_btnGroup->addButton(peers_button, PEERS_TAB); - // URL seeds tab - QPushButton *urlseeds_button = new QPushButton( -#ifndef Q_OS_MAC - GuiIconProvider::instance()->getIcon("network-server"), -#endif - tr("HTTP Sources"), parent); - urlseeds_button->setShortcut(Qt::ALT + Qt::Key_B); - addWidget(urlseeds_button); - m_btnGroup->addButton(urlseeds_button, URLSEEDS_TAB); - // Files tab - QPushButton *files_button = new QPushButton( -#ifndef Q_OS_MAC - GuiIconProvider::instance()->getIcon("inode-directory"), -#endif - tr("Content"), parent); - files_button->setShortcut(Qt::ALT + Qt::Key_Z); - addWidget(files_button); - m_btnGroup->addButton(files_button, FILES_TAB); - // Spacer - addItem(new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Fixed)); - // Speed tab - QPushButton *speed_button = new QPushButton( -#ifndef Q_OS_MAC - GuiIconProvider::instance()->getIcon("office-chart-line"), -#endif - tr("Speed"), parent); - speed_button->setShortcut(Qt::ALT + Qt::Key_D); - addWidget(speed_button); - m_btnGroup->addButton(speed_button, SPEED_TAB); - // SIGNAL/SLOT - connect(m_btnGroup, SIGNAL(buttonClicked(int)), SLOT(setCurrentIndex(int))); - // Disable buttons focus - foreach (QAbstractButton *btn, m_btnGroup->buttons()) { - btn->setFocusPolicy(Qt::NoFocus); - } -} - -PropTabBar::~PropTabBar() { - delete m_btnGroup; -} - -int PropTabBar::currentIndex() const -{ - return m_currentIndex; -} - -void PropTabBar::setCurrentIndex(int index) -{ - if (index >= m_btnGroup->buttons().size()) - index = 0; - // If asked to hide or if the currently selected tab is clicked - if (index < 0 || m_currentIndex == index) { - if (m_currentIndex >= 0) { - m_btnGroup->button(m_currentIndex)->setDown(false); - m_currentIndex = -1; - emit visibilityToggled(false); - } - return; - } - // Unselect previous tab - if (m_currentIndex >= 0) { - m_btnGroup->button(m_currentIndex)->setDown(false); - } else { - // Nothing was selected, show! - emit visibilityToggled(true); - } - // Select the new button - m_btnGroup->button(index)->setDown(true); - m_currentIndex = index; - // Emit the signal - emit tabChanged(index); -} diff --git a/src/gui/properties/proptabbar.h b/src/gui/properties/proptabbar.h deleted file mode 100644 index 85fffe9d2..000000000 --- a/src/gui/properties/proptabbar.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Bittorrent Client using Qt4 and libtorrent. - * Copyright (C) 2010 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 PROPTABBAR_H -#define PROPTABBAR_H - -#include - -QT_BEGIN_NAMESPACE -class QButtonGroup; -QT_END_NAMESPACE - -class PropTabBar : public QHBoxLayout -{ - Q_OBJECT - Q_DISABLE_COPY(PropTabBar) - -public: - enum PropertyTab {MAIN_TAB, TRACKERS_TAB, PEERS_TAB, URLSEEDS_TAB, FILES_TAB, SPEED_TAB}; - -public: - explicit PropTabBar(QWidget *parent = 0); - ~PropTabBar(); - int currentIndex() const; - -signals: - void tabChanged(int index); - void visibilityToggled(bool visible); - -public slots: - void setCurrentIndex(int index); - -private: - QButtonGroup *m_btnGroup; - int m_currentIndex; - -}; - -#endif // PROPTABBAR_H diff --git a/src/gui/properties/speedplotview.cpp b/src/gui/properties/speedplotview.cpp deleted file mode 100644 index d22ae99a0..000000000 --- a/src/gui/properties/speedplotview.cpp +++ /dev/null @@ -1,302 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2015 Anton Lashkov - * - * 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. - */ - -#include "speedplotview.h" - -#include -#include -#include "base/utils/misc.h" - -SpeedPlotView::SpeedPlotView(QWidget *parent) - : QGraphicsView(parent) - , m_data5Min(MIN5_BUF_SIZE) - , m_data30Min(MIN30_BUF_SIZE) - , m_data6Hour(HOUR6_BUF_SIZE) - , m_period(MIN5) - , m_viewablePointsCount(MIN5_SEC) - , m_counter30Min(-1) - , m_counter6Hour(-1) -{ - QPen greenPen; - greenPen.setWidthF(1.5); - greenPen.setColor(QColor(134, 196, 63)); - QPen bluePen; - bluePen.setWidthF(1.5); - bluePen.setColor(QColor(50, 153, 255)); - - m_properties[UP] = GraphProperties(tr("Total Upload"), bluePen); - m_properties[DOWN] = GraphProperties(tr("Total Download"), greenPen); - - bluePen.setStyle(Qt::DashLine); - greenPen.setStyle(Qt::DashLine); - m_properties[PAYLOAD_UP] = GraphProperties(tr("Payload Upload"), bluePen); - m_properties[PAYLOAD_DOWN] = GraphProperties(tr("Payload Download"), greenPen); - - bluePen.setStyle(Qt::DashDotLine); - greenPen.setStyle(Qt::DashDotLine); - m_properties[OVERHEAD_UP] = GraphProperties(tr("Overhead Upload"), bluePen); - m_properties[OVERHEAD_DOWN] = GraphProperties(tr("Overhead Download"), greenPen); - - bluePen.setStyle(Qt::DashDotDotLine); - greenPen.setStyle(Qt::DashDotDotLine); - m_properties[DHT_UP] = GraphProperties(tr("DHT Upload"), bluePen); - m_properties[DHT_DOWN] = GraphProperties(tr("DHT Download"), greenPen); - - bluePen.setStyle(Qt::DotLine); - greenPen.setStyle(Qt::DotLine); - m_properties[TRACKER_UP] = GraphProperties(tr("Tracker Upload"), bluePen); - m_properties[TRACKER_DOWN] = GraphProperties(tr("Tracker Download"), greenPen); -} - -void SpeedPlotView::setGraphEnable(GraphID id, bool enable) -{ - m_properties[id].enable = enable; - viewport()->update(); -} - -void SpeedPlotView::pushPoint(SpeedPlotView::PointData point) -{ - m_counter30Min = (m_counter30Min + 1) % 3; - m_counter6Hour = (m_counter6Hour + 1) % 18; - - m_data5Min.push_back(point); - - if (m_counter30Min == 0) { - m_data30Min.push_back(point); - } - else { - m_data30Min.back().x = (m_data30Min.back().x * m_counter30Min + point.x) / (m_counter30Min + 1); - for (int id = UP; id < NB_GRAPHS; ++id) - m_data30Min.back().y[id] = (m_data30Min.back().y[id] * m_counter30Min + point.y[id]) / (m_counter30Min + 1); - } - - if (m_counter6Hour == 0) { - m_data6Hour.push_back(point); - } - else { - m_data6Hour.back().x = (m_data6Hour.back().x * m_counter6Hour + point.x) / (m_counter6Hour + 1); - for (int id = UP; id < NB_GRAPHS; ++id) - m_data6Hour.back().y[id] = (m_data6Hour.back().y[id] * m_counter6Hour + point.y[id]) / (m_counter6Hour + 1); - } -} - -void SpeedPlotView::setViewableLastPoints(TimePeriod period) -{ - m_period = period; - - switch (period) { - case SpeedPlotView::MIN1: - m_viewablePointsCount = MIN1_SEC; - break; - case SpeedPlotView::MIN5: - m_viewablePointsCount = MIN5_SEC; - break; - case SpeedPlotView::MIN30: - m_viewablePointsCount = MIN30_BUF_SIZE; - break; - case SpeedPlotView::HOUR6: - m_viewablePointsCount = HOUR6_BUF_SIZE; - break; - } - - viewport()->update(); -} - -void SpeedPlotView::replot() -{ - if ((m_period == MIN1) - || (m_period == MIN5) - || ((m_period == MIN30) && (m_counter30Min == 2)) - || ((m_period == HOUR6) && (m_counter6Hour == 17))) - viewport()->update(); -} - -boost::circular_buffer &SpeedPlotView::getCurrentData() -{ - switch (m_period) { - case SpeedPlotView::MIN1: - case SpeedPlotView::MIN5: - default: - return m_data5Min; - case SpeedPlotView::MIN30: - return m_data30Min; - case SpeedPlotView::HOUR6: - return m_data6Hour; - } -} - -int SpeedPlotView::maxYValue() -{ - boost::circular_buffer &queue = getCurrentData(); - - int maxYValue = 0; - for (int id = UP; id < NB_GRAPHS; ++id) { - - if (!m_properties[static_cast(id)].enable) - continue; - - for (int i = int(queue.size()) - 1, j = 0; i >= 0 && j <= m_viewablePointsCount; --i, ++j) - if (queue[i].y[id] > maxYValue) - maxYValue = queue[i].y[id]; - } - - return maxYValue; -} - -void SpeedPlotView::paintEvent(QPaintEvent *) -{ - QPainter painter(viewport()); - - QRect fullRect = viewport()->rect(); - QRect rect = viewport()->rect(); - QFontMetrics fontMetrics = painter.fontMetrics(); - - rect.adjust(4, 4, 0, -4); // Add padding - - int maxY = maxYValue(); - - rect.adjust(0, fontMetrics.height(), 0, 0); // Add top padding for top speed text - - // draw Y axis speed labels - QVector speedLabels = { - Utils::Misc::friendlyUnit(maxY, true), - Utils::Misc::friendlyUnit(0.75 * maxY, true), - Utils::Misc::friendlyUnit(0.5 * maxY, true), - Utils::Misc::friendlyUnit(0.25 * maxY, true), - Utils::Misc::friendlyUnit(0, true) - }; - - int yAxeWidth = 0; - for (const QString &label : speedLabels) - if (fontMetrics.width(label) > yAxeWidth) - yAxeWidth = fontMetrics.width(label); - - int i = 0; - for (const QString &label : speedLabels) { - QRectF labelRect(rect.topLeft() + QPointF(-yAxeWidth, (i++) * 0.25 * rect.height() - fontMetrics.height()), - QSizeF(2 * yAxeWidth, fontMetrics.height())); - painter.drawText(labelRect, label, Qt::AlignRight | Qt::AlignTop); - } - - // draw grid lines - rect.adjust(yAxeWidth + 4, 0, 0, 0); - - QPen gridPen; - gridPen.setStyle(Qt::DashLine); - gridPen.setWidthF(1); - gridPen.setColor(QColor(128, 128, 128, 128)); - painter.setPen(gridPen); - - painter.drawLine(fullRect.left(), rect.top(), rect.right(), rect.top()); - painter.drawLine(fullRect.left(), rect.top() + 0.25 * rect.height(), rect.right(), rect.top() + 0.25 * rect.height()); - painter.drawLine(fullRect.left(), rect.top() + 0.50 * rect.height(), rect.right(), rect.top() + 0.50 * rect.height()); - painter.drawLine(fullRect.left(), rect.top() + 0.75 * rect.height(), rect.right(), rect.top() + 0.75 * rect.height()); - painter.drawLine(fullRect.left(), rect.bottom(), rect.right(), rect.bottom()); - - painter.drawLine(rect.left(), fullRect.top(), rect.left(), fullRect.bottom()); - painter.drawLine(rect.left() + 0.2 * rect.width(), fullRect.top(), rect.left() + 0.2 * rect.width(), fullRect.bottom()); - painter.drawLine(rect.left() + 0.4 * rect.width(), fullRect.top(), rect.left() + 0.4 * rect.width(), fullRect.bottom()); - painter.drawLine(rect.left() + 0.6 * rect.width(), fullRect.top(), rect.left() + 0.6 * rect.width(), fullRect.bottom()); - painter.drawLine(rect.left() + 0.8 * rect.width(), fullRect.top(), rect.left() + 0.8 * rect.width(), fullRect.bottom()); - - // Set antialiasing for graphs - painter.setRenderHints(QPainter::Antialiasing | QPainter::HighQualityAntialiasing); - - // draw graphs - rect.adjust(3, 0, 0, 0); // Need, else graphs cross left gridline - - double yMultiplier = (maxY == 0) ? 0.0 : static_cast(rect.height()) / maxY; - double xTickSize = static_cast(rect.width()) / m_viewablePointsCount; - - boost::circular_buffer &queue = getCurrentData(); - - for (int id = UP; id < NB_GRAPHS; ++id) { - - if (!m_properties[static_cast(id)].enable) - continue; - - QVector points; - - for (int i = int(queue.size()) - 1, j = 0; i >= 0 && j <= m_viewablePointsCount; --i, ++j) { - - int new_x = rect.right() - j * xTickSize; - int new_y = rect.bottom() - queue[i].y[id] * yMultiplier; - - points.push_back(QPoint(new_x, new_y)); - } - - painter.setPen(m_properties[static_cast(id)].pen); - painter.drawPolyline(points.data(), points.size()); - } - - // draw legend - QPoint legendTopLeft(rect.left() + 4, fullRect.top() + 4); - - double legendHeight = 0; - int legendWidth = 0; - for (const auto &property : m_properties) { - - if (!property.enable) - continue; - - if (fontMetrics.width(property.name) > legendWidth) - legendWidth = fontMetrics.width(property.name); - legendHeight += 1.5 * fontMetrics.height(); - } - - QRectF legendBackgroundRect(QPoint(legendTopLeft.x() - 4, legendTopLeft.y() - 4), QSizeF(legendWidth + 8, legendHeight + 8)); - QColor legendBackgroundColor = QWidget::palette().color(QWidget::backgroundRole()); - legendBackgroundColor.setAlpha(128); // 50% transparent - painter.fillRect(legendBackgroundRect, legendBackgroundColor); - - i = 0; - for (const auto &property : m_properties) { - - if (!property.enable) - continue; - - int nameSize = fontMetrics.width(property.name); - double indent = 1.5 * (i++) * fontMetrics.height(); - - painter.setPen(property.pen); - painter.drawLine(legendTopLeft + QPointF(0, indent + fontMetrics.height()), - legendTopLeft + QPointF(nameSize, indent + fontMetrics.height())); - painter.drawText(QRectF(legendTopLeft + QPointF(0, indent), QSizeF(2 * nameSize, fontMetrics.height())), - property.name, QTextOption(Qt::AlignVCenter)); - } -} - -SpeedPlotView::GraphProperties::GraphProperties() - : enable(false) -{} - -SpeedPlotView::GraphProperties::GraphProperties(const QString &name, const QPen &pen, bool enable) - : name(name) - , pen(pen) - , enable(enable) -{} diff --git a/src/gui/properties/speedplotview.h b/src/gui/properties/speedplotview.h deleted file mode 100644 index 2165110b6..000000000 --- a/src/gui/properties/speedplotview.h +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2015 Anton Lashkov - * - * 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. - */ - -#ifndef SPEEDPLOTVIEW_H -#define SPEEDPLOTVIEW_H - -#ifndef Q_MOC_RUN -#include -#endif - -#include -#include -class QPen; - -class SpeedPlotView: public QGraphicsView -{ - Q_OBJECT - -public: - enum GraphID - { - UP = 0, - DOWN, - PAYLOAD_UP, - PAYLOAD_DOWN, - OVERHEAD_UP, - OVERHEAD_DOWN, - DHT_UP, - DHT_DOWN, - TRACKER_UP, - TRACKER_DOWN, - NB_GRAPHS - }; - - enum TimePeriod - { - MIN1 = 0, - MIN5, - MIN30, - HOUR6 - }; - - struct PointData - { - uint x; - int y[NB_GRAPHS]; - }; - - explicit SpeedPlotView(QWidget *parent = 0); - - void setGraphEnable(GraphID id, bool enable); - void setViewableLastPoints(TimePeriod period); - - void pushPoint(PointData point); - - void replot(); - -protected: - virtual void paintEvent(QPaintEvent *event); - -private: - enum PeriodInSeconds - { - MIN1_SEC = 60, - MIN5_SEC = 5 * 60, - MIN30_SEC = 30 * 60, - HOUR6_SEC = 6 * 60 * 60 - }; - - enum PointsToSave - { - MIN5_BUF_SIZE = 5 * 60, - MIN30_BUF_SIZE = 10 * 60, - HOUR6_BUF_SIZE = 20 * 60 - }; - - struct GraphProperties - { - GraphProperties(); - GraphProperties(const QString &name, const QPen &pen, bool enable = false); - - QString name; - QPen pen; - bool enable; - }; - - boost::circular_buffer m_data5Min; - boost::circular_buffer m_data30Min; - boost::circular_buffer m_data6Hour; - QMap m_properties; - - TimePeriod m_period; - int m_viewablePointsCount; - - int m_counter30Min; - int m_counter6Hour; - - int maxYValue(); - - boost::circular_buffer &getCurrentData(); -}; - -#endif // SPEEDPLOTVIEW_H diff --git a/src/gui/properties/speedwidget.cpp b/src/gui/properties/speedwidget.cpp deleted file mode 100644 index daba84043..000000000 --- a/src/gui/properties/speedwidget.cpp +++ /dev/null @@ -1,203 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2015 Anton Lashkov - * - * 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. - */ - -#include "speedwidget.h" - -#include -#include -#include -#include -#include -#include - -#include - -#include "propertieswidget.h" -#include "base/bittorrent/session.h" -#include "base/bittorrent/sessionstatus.h" -#include "base/preferences.h" - -ComboBoxMenuButton::ComboBoxMenuButton(QWidget *parent, QMenu *menu) - : QComboBox(parent) - , m_menu(menu) -{ -} - -void ComboBoxMenuButton::showPopup() -{ - QPoint p = mapToGlobal(QPoint(0, height())); - m_menu->exec(p); - QComboBox::hidePopup(); -} - -SpeedWidget::SpeedWidget(PropertiesWidget *parent) - : QWidget(parent) -{ - m_layout = new QVBoxLayout(this); - m_layout->setContentsMargins(0, 0, 0, 0); - - m_hlayout = new QHBoxLayout(); - m_hlayout->setContentsMargins(0, 0, 0, 0); - - m_periodLabel = new QLabel("" + tr("Period:") + ""); - - m_periodCombobox = new QComboBox(); - m_periodCombobox->addItem(tr("1 Minute")); - m_periodCombobox->addItem(tr("5 Minutes")); - m_periodCombobox->addItem(tr("30 Minutes")); - m_periodCombobox->addItem(tr("6 Hours")); - - connect(m_periodCombobox, SIGNAL(currentIndexChanged(int)), this, SLOT(onPeriodChange(int))); - - m_graphsMenu = new QMenu(this); - m_graphsMenu->addAction(tr("Total Upload")); - m_graphsMenu->addAction(tr("Total Download")); - m_graphsMenu->addAction(tr("Payload Upload")); - m_graphsMenu->addAction(tr("Payload Download")); - m_graphsMenu->addAction(tr("Overhead Upload")); - m_graphsMenu->addAction(tr("Overhead Download")); - m_graphsMenu->addAction(tr("DHT Upload")); - m_graphsMenu->addAction(tr("DHT Download")); - m_graphsMenu->addAction(tr("Tracker Upload")); - m_graphsMenu->addAction(tr("Tracker Download")); - - m_graphsMenuActions = m_graphsMenu->actions(); - m_graphsSignalMapper = new QSignalMapper(); - - for (int id = SpeedPlotView::UP; id < SpeedPlotView::NB_GRAPHS; ++id) { - QAction *action = m_graphsMenuActions.at(id); - action->setCheckable(true); - action->setChecked(true); - connect(action, SIGNAL(changed()), m_graphsSignalMapper, SLOT(map())); - m_graphsSignalMapper->setMapping(action, id); - } - connect(m_graphsSignalMapper, SIGNAL(mapped(int)), this, SLOT(onGraphChange(int))); - - m_graphsButton = new ComboBoxMenuButton(this, m_graphsMenu); - m_graphsButton->addItem(tr("Select Graphs")); - - m_hlayout->addWidget(m_periodLabel); - m_hlayout->addWidget(m_periodCombobox); - m_hlayout->addStretch(); - m_hlayout->addWidget(m_graphsButton); - - m_plot = new SpeedPlotView(this); - - m_layout->addLayout(m_hlayout); - m_layout->addWidget(m_plot); - - loadSettings(); - - m_isUpdating = true; - m_updateFuture = QtConcurrent::run(this, &SpeedWidget::update); - - m_plot->show(); -} - -SpeedWidget::~SpeedWidget() -{ - qDebug("SpeedWidget::~SpeedWidget() ENTER"); - - m_isUpdating = false; - m_updateFuture.waitForFinished(); - - saveSettings(); - - qDebug("SpeedWidget::~SpeedWidget() EXIT"); -} - -void SpeedWidget::update() -{ - while (m_isUpdating) { - - const BitTorrent::SessionStatus &btStatus = BitTorrent::Session::instance()->status(); - - SpeedPlotView::PointData point; - point.x = QDateTime::currentDateTime().toTime_t(); - point.y[SpeedPlotView::UP] = btStatus.uploadRate; - point.y[SpeedPlotView::DOWN] = btStatus.downloadRate; - point.y[SpeedPlotView::PAYLOAD_UP] = btStatus.payloadUploadRate; - point.y[SpeedPlotView::PAYLOAD_DOWN] = btStatus.payloadDownloadRate; - point.y[SpeedPlotView::OVERHEAD_UP] = btStatus.ipOverheadUploadRate; - point.y[SpeedPlotView::OVERHEAD_DOWN] = btStatus.ipOverheadDownloadRate; - point.y[SpeedPlotView::DHT_UP] = btStatus.dhtUploadRate; - point.y[SpeedPlotView::DHT_DOWN] = btStatus.dhtDownloadRate; - point.y[SpeedPlotView::TRACKER_UP] = btStatus.trackerUploadRate; - point.y[SpeedPlotView::TRACKER_DOWN] = btStatus.trackerDownloadRate; - - m_plot->pushPoint(point); - - QMetaObject::invokeMethod(this, "graphUpdate", Qt::QueuedConnection); - QThread::msleep(1000); - } -} - -void SpeedWidget::graphUpdate() -{ - m_plot->replot(); -} - -void SpeedWidget::onPeriodChange(int period) -{ - m_plot->setViewableLastPoints(static_cast(period)); -} - -void SpeedWidget::onGraphChange(int id) -{ - QAction *action = m_graphsMenuActions.at(id); - m_plot->setGraphEnable(static_cast(id), action->isChecked()); -} - -void SpeedWidget::loadSettings() -{ - Preferences *preferences = Preferences::instance(); - - int periodIndex = preferences->getSpeedWidgetPeriod(); - m_periodCombobox->setCurrentIndex(periodIndex); - onPeriodChange(static_cast(periodIndex)); - - for (int id = SpeedPlotView::UP; id < SpeedPlotView::NB_GRAPHS; ++id) { - QAction *action = m_graphsMenuActions.at(id); - bool enable = preferences->getSpeedWidgetGraphEnable(id); - - action->setChecked(enable); - m_plot->setGraphEnable(static_cast(id), enable); - } -} - -void SpeedWidget::saveSettings() const -{ - Preferences *preferences = Preferences::instance(); - - preferences->setSpeedWidgetPeriod(m_periodCombobox->currentIndex()); - - for (int id = SpeedPlotView::UP; id < SpeedPlotView::NB_GRAPHS; ++id) { - QAction *action = m_graphsMenuActions.at(id); - preferences->setSpeedWidgetGraphEnable(id, action->isChecked()); - } -} diff --git a/src/gui/properties/speedwidget.h b/src/gui/properties/speedwidget.h deleted file mode 100644 index c4d366819..000000000 --- a/src/gui/properties/speedwidget.h +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2015 Anton Lashkov - * - * 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. - */ - -#ifndef SPEEDWIDGET_H -#define SPEEDWIDGET_H - -#include -#include -#include - -#include "speedplotview.h" - -class QVBoxLayout; -class QHBoxLayout; -class QLabel; -class QMenu; -class QSignalMapper; -class PropertiesWidget; - -class ComboBoxMenuButton : public QComboBox -{ - Q_OBJECT -public: - ComboBoxMenuButton(QWidget *parent, QMenu *menu); - virtual void showPopup(); - -private: - QMenu *m_menu; -}; - - -class SpeedWidget : public QWidget -{ - Q_OBJECT -public: - SpeedWidget(PropertiesWidget *parent); - ~SpeedWidget(); - -private slots: - void onPeriodChange(int period); - void onGraphChange(int id); - -private: - void update(); - void loadSettings(); - void saveSettings() const; - Q_INVOKABLE void graphUpdate(); - - QVBoxLayout *m_layout; - QHBoxLayout *m_hlayout; - QLabel *m_periodLabel; - QComboBox *m_periodCombobox; - SpeedPlotView *m_plot; - - ComboBoxMenuButton *m_graphsButton; - QMenu *m_graphsMenu; - QList m_graphsMenuActions; - QSignalMapper *m_graphsSignalMapper; - - QFuture m_updateFuture; - bool m_isUpdating; -}; - -#endif // SPEEDWIDGET_H diff --git a/src/gui/properties/trackerlist.cpp b/src/gui/properties/trackerlist.cpp deleted file mode 100644 index 3110a103e..000000000 --- a/src/gui/properties/trackerlist.cpp +++ /dev/null @@ -1,635 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2006 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. - */ - -#include "trackerlist.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "base/bittorrent/peerinfo.h" -#include "base/bittorrent/session.h" -#include "base/bittorrent/torrenthandle.h" -#include "base/bittorrent/trackerentry.h" -#include "base/preferences.h" -#include "base/utils/misc.h" -#include "autoexpandabledialog.h" -#include "guiiconprovider.h" -#include "propertieswidget.h" -#include "trackersadditiondlg.h" - -TrackerList::TrackerList(PropertiesWidget *properties) - : QTreeWidget() - , m_properties(properties) -{ - // Set header - // Must be set before calling loadSettings() otherwise the header is reset on restart - setHeaderLabels(headerLabels()); - // Load settings - loadSettings(); - // Graphical settings - setRootIsDecorated(false); - setAllColumnsShowFocus(true); - setItemsExpandable(false); - setSelectionMode(QAbstractItemView::ExtendedSelection); - header()->setStretchLastSection(false); // Must be set after loadSettings() in order to work - // Ensure that at least one column is visible at all times - if (visibleColumnsCount() == 0) - setColumnHidden(COL_URL, false); - // To also mitigate the above issue, we have to resize each column when - // its size is 0, because explicitly 'showing' the column isn't enough - // in the above scenario. - for (unsigned int i = 0; i < COL_COUNT; ++i) - if ((columnWidth(i) <= 0) && !isColumnHidden(i)) - resizeColumnToContents(i); - // Context menu - setContextMenuPolicy(Qt::CustomContextMenu); - connect(this, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(showTrackerListMenu(QPoint))); - // Header context menu - header()->setContextMenuPolicy(Qt::CustomContextMenu); - connect(header(), SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(displayToggleColumnsMenu(const QPoint&))); - // Set DHT, PeX, LSD items - m_DHTItem = new QTreeWidgetItem({ "", "** [DHT] **", "", "0", "", "", "0" }); - insertTopLevelItem(0, m_DHTItem); - setRowColor(0, QColor("grey")); - m_PEXItem = new QTreeWidgetItem({ "", "** [PeX] **", "", "0", "", "", "0" }); - insertTopLevelItem(1, m_PEXItem); - setRowColor(1, QColor("grey")); - m_LSDItem = new QTreeWidgetItem({ "", "** [LSD] **", "", "0", "", "", "0" }); - insertTopLevelItem(2, m_LSDItem); - setRowColor(2, QColor("grey")); - // Set static items alignment - m_DHTItem->setTextAlignment(COL_RECEIVED, (Qt::AlignRight | Qt::AlignVCenter)); - m_PEXItem->setTextAlignment(COL_RECEIVED, (Qt::AlignRight | Qt::AlignVCenter)); - m_LSDItem->setTextAlignment(COL_RECEIVED, (Qt::AlignRight | Qt::AlignVCenter)); - m_DHTItem->setTextAlignment(COL_SEEDS, (Qt::AlignRight | Qt::AlignVCenter)); - m_PEXItem->setTextAlignment(COL_SEEDS, (Qt::AlignRight | Qt::AlignVCenter)); - m_LSDItem->setTextAlignment(COL_SEEDS, (Qt::AlignRight | Qt::AlignVCenter)); - m_DHTItem->setTextAlignment(COL_PEERS, (Qt::AlignRight | Qt::AlignVCenter)); - m_PEXItem->setTextAlignment(COL_PEERS, (Qt::AlignRight | Qt::AlignVCenter)); - m_LSDItem->setTextAlignment(COL_PEERS, (Qt::AlignRight | Qt::AlignVCenter)); - m_DHTItem->setTextAlignment(COL_DOWNLOADED, (Qt::AlignRight | Qt::AlignVCenter)); - m_PEXItem->setTextAlignment(COL_DOWNLOADED, (Qt::AlignRight | Qt::AlignVCenter)); - m_LSDItem->setTextAlignment(COL_DOWNLOADED, (Qt::AlignRight | Qt::AlignVCenter)); - // Set header alignment - headerItem()->setTextAlignment(COL_TIER, (Qt::AlignRight | Qt::AlignVCenter)); - headerItem()->setTextAlignment(COL_RECEIVED, (Qt::AlignRight | Qt::AlignVCenter)); - headerItem()->setTextAlignment(COL_SEEDS, (Qt::AlignRight | Qt::AlignVCenter)); - headerItem()->setTextAlignment(COL_PEERS, (Qt::AlignRight | Qt::AlignVCenter)); - headerItem()->setTextAlignment(COL_DOWNLOADED, (Qt::AlignRight | Qt::AlignVCenter)); - // Set hotkeys - m_editHotkey = new QShortcut(Qt::Key_F2, this, SLOT(editSelectedTracker()), 0, Qt::WidgetShortcut); - connect(this, SIGNAL(doubleClicked(QModelIndex)), SLOT(editSelectedTracker())); - m_deleteHotkey = new QShortcut(QKeySequence::Delete, this, SLOT(deleteSelectedTrackers()), 0, Qt::WidgetShortcut); - m_copyHotkey = new QShortcut(QKeySequence::Copy, this, SLOT(copyTrackerUrl()), 0, Qt::WidgetShortcut); - - // This hack fixes reordering of first column with Qt5. - // https://github.com/qtproject/qtbase/commit/e0fc088c0c8bc61dbcaf5928b24986cd61a22777 - QTableView unused; - unused.setVerticalHeader(header()); - header()->setParent(this); - unused.setVerticalHeader(new QHeaderView(Qt::Horizontal)); -} - -TrackerList::~TrackerList() -{ - saveSettings(); -} - -QList TrackerList::getSelectedTrackerItems() const -{ - const QList selectedTrackerItems = selectedItems(); - QList selectedTrackers; - foreach (QTreeWidgetItem *item, selectedTrackerItems) { - if (indexOfTopLevelItem(item) >= NB_STICKY_ITEM) // Ignore STICKY ITEMS - selectedTrackers << item; - } - - return selectedTrackers; -} - -void TrackerList::setRowColor(int row, QColor color) -{ - unsigned int nbColumns = columnCount(); - QTreeWidgetItem *item = topLevelItem(row); - for (unsigned int i = 0; i < nbColumns; ++i) - item->setData(i, Qt::ForegroundRole, color); -} - -void TrackerList::moveSelectionUp() -{ - BitTorrent::TorrentHandle *const torrent = m_properties->getCurrentTorrent(); - if (!torrent) { - clear(); - return; - } - QList selectedTrackerItems = getSelectedTrackerItems(); - if (selectedTrackerItems.isEmpty()) return; - - bool change = false; - foreach (QTreeWidgetItem *item, selectedTrackerItems) { - int index = indexOfTopLevelItem(item); - if (index > NB_STICKY_ITEM) { - insertTopLevelItem(index - 1, takeTopLevelItem(index)); - change = true; - } - } - if (!change) return; - - // Restore selection - QItemSelectionModel *selection = selectionModel(); - foreach (QTreeWidgetItem *item, selectedTrackerItems) - selection->select(indexFromItem(item), (QItemSelectionModel::Rows | QItemSelectionModel::Select)); - - setSelectionModel(selection); - // Update torrent trackers - QList trackers; - for (int i = NB_STICKY_ITEM; i < topLevelItemCount(); ++i) { - QString trackerURL = topLevelItem(i)->data(COL_URL, Qt::DisplayRole).toString(); - BitTorrent::TrackerEntry e(trackerURL); - e.setTier(i - NB_STICKY_ITEM); - trackers.append(e); - } - - torrent->replaceTrackers(trackers); - // Reannounce - if (!torrent->isPaused()) - torrent->forceReannounce(); -} - -void TrackerList::moveSelectionDown() -{ - BitTorrent::TorrentHandle *const torrent = m_properties->getCurrentTorrent(); - if (!torrent) { - clear(); - return; - } - QList selectedTrackerItems = getSelectedTrackerItems(); - if (selectedTrackerItems.isEmpty()) return; - - bool change = false; - for (int i = selectedItems().size() - 1; i >= 0; --i) { - int index = indexOfTopLevelItem(selectedTrackerItems.at(i)); - if (index < (topLevelItemCount() - 1)) { - insertTopLevelItem(index + 1, takeTopLevelItem(index)); - change = true; - } - } - if (!change) return; - - // Restore selection - QItemSelectionModel *selection = selectionModel(); - foreach (QTreeWidgetItem *item, selectedTrackerItems) - selection->select(indexFromItem(item), (QItemSelectionModel::Rows | QItemSelectionModel::Select)); - - setSelectionModel(selection); - // Update torrent trackers - QList trackers; - for (int i = NB_STICKY_ITEM; i < topLevelItemCount(); ++i) { - QString trackerURL = topLevelItem(i)->data(COL_URL, Qt::DisplayRole).toString(); - BitTorrent::TrackerEntry e(trackerURL); - e.setTier(i - NB_STICKY_ITEM); - trackers.append(e); - } - - torrent->replaceTrackers(trackers); - // Reannounce - if (!torrent->isPaused()) - torrent->forceReannounce(); -} - -void TrackerList::clear() -{ - qDeleteAll(m_trackerItems.values()); - m_trackerItems.clear(); - m_DHTItem->setText(COL_STATUS, ""); - m_DHTItem->setText(COL_SEEDS, ""); - m_DHTItem->setText(COL_PEERS, ""); - m_DHTItem->setText(COL_MSG, ""); - m_PEXItem->setText(COL_STATUS, ""); - m_PEXItem->setText(COL_SEEDS, ""); - m_PEXItem->setText(COL_PEERS, ""); - m_PEXItem->setText(COL_MSG, ""); - m_LSDItem->setText(COL_STATUS, ""); - m_LSDItem->setText(COL_SEEDS, ""); - m_LSDItem->setText(COL_PEERS, ""); - m_LSDItem->setText(COL_MSG, ""); -} - -void TrackerList::loadStickyItems(BitTorrent::TorrentHandle *const torrent) -{ - QString working = tr("Working"); - QString disabled = tr("Disabled"); - - // load DHT information - if (BitTorrent::Session::instance()->isDHTEnabled() && !torrent->isPrivate()) - m_DHTItem->setText(COL_STATUS, working); - else - m_DHTItem->setText(COL_STATUS, disabled); - - // Load PeX Information - if (BitTorrent::Session::instance()->isPeXEnabled() && !torrent->isPrivate()) - m_PEXItem->setText(COL_STATUS, working); - else - m_PEXItem->setText(COL_STATUS, disabled); - - // Load LSD Information - if (BitTorrent::Session::instance()->isLSDEnabled() && !torrent->isPrivate()) - m_LSDItem->setText(COL_STATUS, working); - else - m_LSDItem->setText(COL_STATUS, disabled); - - if (torrent->isPrivate()) { - QString privateMsg = tr("This torrent is private"); - m_DHTItem->setText(COL_MSG, privateMsg); - m_PEXItem->setText(COL_MSG, privateMsg); - m_LSDItem->setText(COL_MSG, privateMsg); - } - - // XXX: libtorrent should provide this info... - // Count peers from DHT, PeX, LSD - uint seedsDHT = 0, seedsPeX = 0, seedsLSD = 0, peersDHT = 0, peersPeX = 0, peersLSD = 0; - foreach (const BitTorrent::PeerInfo &peer, torrent->peers()) { - if (peer.isConnecting()) continue; - - if (peer.fromDHT()) { - if (peer.isSeed()) - ++seedsDHT; - else - ++peersDHT; - } - if (peer.fromPeX()) { - if (peer.isSeed()) - ++seedsPeX; - else - ++peersPeX; - } - if (peer.fromLSD()) { - if (peer.isSeed()) - ++seedsLSD; - else - ++peersLSD; - } - } - - m_DHTItem->setText(COL_SEEDS, QString::number(seedsDHT)); - m_DHTItem->setText(COL_PEERS, QString::number(peersDHT)); - m_PEXItem->setText(COL_SEEDS, QString::number(seedsPeX)); - m_PEXItem->setText(COL_PEERS, QString::number(peersPeX)); - m_LSDItem->setText(COL_SEEDS, QString::number(seedsLSD)); - m_LSDItem->setText(COL_PEERS, QString::number(peersLSD)); -} - -void TrackerList::loadTrackers() -{ - // Load trackers from torrent handle - BitTorrent::TorrentHandle *const torrent = m_properties->getCurrentTorrent(); - if (!torrent) return; - - loadStickyItems(torrent); - - // Load actual trackers information - QHash trackerData = torrent->trackerInfos(); - QStringList oldTrackerURLs = m_trackerItems.keys(); - foreach (const BitTorrent::TrackerEntry &entry, torrent->trackers()) { - QString trackerURL = entry.url(); - QTreeWidgetItem *item = m_trackerItems.value(trackerURL, 0); - if (!item) { - item = new QTreeWidgetItem(); - item->setText(COL_URL, trackerURL); - addTopLevelItem(item); - m_trackerItems[trackerURL] = item; - } - else { - oldTrackerURLs.removeOne(trackerURL); - } - item->setText(COL_TIER, QString::number(entry.tier())); - BitTorrent::TrackerInfo data = trackerData.value(trackerURL); - QString errorMessage = data.lastMessage.trimmed(); - switch (entry.status()) { - case BitTorrent::TrackerEntry::Working: - item->setText(COL_STATUS, tr("Working")); - item->setText(COL_MSG, ""); - break; - case BitTorrent::TrackerEntry::Updating: - item->setText(COL_STATUS, tr("Updating...")); - item->setText(COL_MSG, ""); - break; - case BitTorrent::TrackerEntry::NotWorking: - item->setText(COL_STATUS, tr("Not working")); - item->setText(COL_MSG, errorMessage); - break; - case BitTorrent::TrackerEntry::NotContacted: - item->setText(COL_STATUS, tr("Not contacted yet")); - item->setText(COL_MSG, ""); - break; - } - - item->setText(COL_RECEIVED, QString::number(data.numPeers)); -#if LIBTORRENT_VERSION_NUM >= 10000 - item->setText(COL_SEEDS, QString::number(entry.nativeEntry().scrape_complete > 0 ? entry.nativeEntry().scrape_complete : 0)); - item->setText(COL_PEERS, QString::number(entry.nativeEntry().scrape_incomplete > 0 ? entry.nativeEntry().scrape_incomplete : 0)); - item->setText(COL_DOWNLOADED, QString::number(entry.nativeEntry().scrape_downloaded > 0 ? entry.nativeEntry().scrape_downloaded : 0)); -#else - item->setText(COL_SEEDS, "0"); - item->setText(COL_PEERS, "0"); - item->setText(COL_DOWNLOADED, "0"); -#endif - - item->setTextAlignment(COL_TIER, (Qt::AlignRight | Qt::AlignVCenter)); - item->setTextAlignment(COL_RECEIVED, (Qt::AlignRight | Qt::AlignVCenter)); - item->setTextAlignment(COL_SEEDS, (Qt::AlignRight | Qt::AlignVCenter)); - item->setTextAlignment(COL_PEERS, (Qt::AlignRight | Qt::AlignVCenter)); - item->setTextAlignment(COL_DOWNLOADED, (Qt::AlignRight | Qt::AlignVCenter)); - } - // Remove old trackers - foreach (const QString &tracker, oldTrackerURLs) - delete m_trackerItems.take(tracker); -} - -// Ask the user for new trackers and add them to the torrent -void TrackerList::askForTrackers() -{ - BitTorrent::TorrentHandle *const torrent = m_properties->getCurrentTorrent(); - if (!torrent) return; - - QList trackers; - foreach (const QString &tracker, TrackersAdditionDlg::askForTrackers(this, torrent)) - trackers << tracker; - - torrent->addTrackers(trackers); -} - -void TrackerList::copyTrackerUrl() -{ - QList selectedTrackerItems = getSelectedTrackerItems(); - if (selectedTrackerItems.isEmpty()) return; - - QStringList URLsToCopy; - foreach (QTreeWidgetItem *item, selectedTrackerItems) { - QString trackerURL = item->data(COL_URL, Qt::DisplayRole).toString(); - qDebug() << QString("Copy: ") + trackerURL; - URLsToCopy << trackerURL; - } - QApplication::clipboard()->setText(URLsToCopy.join("\n")); -} - - -void TrackerList::deleteSelectedTrackers() -{ - BitTorrent::TorrentHandle *const torrent = m_properties->getCurrentTorrent(); - if (!torrent) { - clear(); - return; - } - - QList selectedTrackerItems = getSelectedTrackerItems(); - if (selectedTrackerItems.isEmpty()) return; - - QStringList URLsToRemove; - foreach (QTreeWidgetItem *item, selectedTrackerItems) { - QString trackerURL = item->data(COL_URL, Qt::DisplayRole).toString(); - URLsToRemove << trackerURL; - m_trackerItems.remove(trackerURL); - delete item; - } - - // Iterate over the trackers and remove the selected ones - QList remainingTrackers; - QList trackers = torrent->trackers(); - foreach (const BitTorrent::TrackerEntry &entry, trackers) { - if (!URLsToRemove.contains(entry.url())) - remainingTrackers.push_back(entry); - } - - torrent->replaceTrackers(remainingTrackers); - if (!torrent->isPaused()) - torrent->forceReannounce(); -} - -void TrackerList::editSelectedTracker() -{ - BitTorrent::TorrentHandle *const torrent = m_properties->getCurrentTorrent(); - if (!torrent) return; - - QString hash = torrent->hash(); - - QList selectedTrackerItems = getSelectedTrackerItems(); - if (selectedTrackerItems.isEmpty()) return; - - // During multi-select only process item selected last - QUrl trackerURL = selectedTrackerItems.last()->text(COL_URL); - - bool ok; - QUrl newTrackerURL = AutoExpandableDialog::getText(this, tr("Tracker editing"), tr("Tracker URL:"), - QLineEdit::Normal, trackerURL.toString(), &ok).trimmed(); - if (!ok) return; - - if (!newTrackerURL.isValid()) { - QMessageBox::warning(this, tr("Tracker editing failed"), tr("The tracker URL entered is invalid.")); - return; - } - if (newTrackerURL == trackerURL) return; - - QList trackers = torrent->trackers(); - bool match = false; - for (int i = 0; i < trackers.size(); ++i) { - BitTorrent::TrackerEntry &entry = trackers[i]; - if (newTrackerURL == QUrl(entry.url())) { - QMessageBox::warning(this, tr("Tracker editing failed"), tr("The tracker URL already exists.")); - return; - } - - if (trackerURL == QUrl(entry.url()) && !match) { - BitTorrent::TrackerEntry newEntry(newTrackerURL.toString()); - newEntry.setTier(entry.tier()); - match = true; - entry = newEntry; - } - } - - torrent->replaceTrackers(trackers); - if (!torrent->isPaused()) - torrent->forceReannounce(); -} - -void TrackerList::reannounceSelected() -{ - QList selItems = selectedItems(); - if (selItems.isEmpty()) return; - - BitTorrent::TorrentHandle *const torrent = m_properties->getCurrentTorrent(); - if (!torrent) return; - - QList trackers = torrent->trackers(); - - foreach (QTreeWidgetItem* item, selItems) { - // DHT case - if (item == m_DHTItem) { - torrent->forceDHTAnnounce(); - continue; - } - - // Trackers case - for (int i = 0; i < trackers.size(); ++i) { - if (item->text(COL_URL) == trackers[i].url()) { - torrent->forceReannounce(i); - break; - } - } - } - - loadTrackers(); -} - -void TrackerList::showTrackerListMenu(QPoint) -{ - BitTorrent::TorrentHandle *const torrent = m_properties->getCurrentTorrent(); - if (!torrent) return; - - //QList selected_items = getSelectedTrackerItems(); - QMenu menu; - // Add actions - QAction *addAct = menu.addAction(GuiIconProvider::instance()->getIcon("list-add"), tr("Add a new tracker...")); - QAction *copyAct = nullptr; - QAction *delAct = nullptr; - QAction *editAct = nullptr; - if (!getSelectedTrackerItems().isEmpty()) { - delAct = menu.addAction(GuiIconProvider::instance()->getIcon("list-remove"), tr("Remove tracker")); - copyAct = menu.addAction(GuiIconProvider::instance()->getIcon("edit-copy"), tr("Copy tracker URL")); - editAct = menu.addAction(GuiIconProvider::instance()->getIcon("edit-rename"),tr("Edit selected tracker URL")); - } - QAction *reannounceSelAct = nullptr; - QAction *reannounceAllAct = nullptr; - if (!torrent->isPaused()) { - reannounceSelAct = menu.addAction(GuiIconProvider::instance()->getIcon("view-refresh"), tr("Force reannounce to selected trackers")); - menu.addSeparator(); - reannounceAllAct = menu.addAction(GuiIconProvider::instance()->getIcon("view-refresh"), tr("Force reannounce to all trackers")); - } - QAction *act = menu.exec(QCursor::pos()); - if (act == nullptr) return; - - if (act == addAct) { - askForTrackers(); - return; - } - if (act == copyAct) { - copyTrackerUrl(); - return; - } - if (act == delAct) { - deleteSelectedTrackers(); - return; - } - if (act == reannounceSelAct) { - reannounceSelected(); - return; - } - if (act == reannounceAllAct) { - BitTorrent::TorrentHandle *h = m_properties->getCurrentTorrent(); - h->forceReannounce(); - h->forceDHTAnnounce(); - return; - } - if (act == editAct) { - editSelectedTracker(); - return; - } -} - -void TrackerList::loadSettings() -{ - header()->restoreState(Preferences::instance()->getPropTrackerListState()); -} - -void TrackerList::saveSettings() const -{ - Preferences::instance()->setPropTrackerListState(header()->saveState()); -} - -QStringList TrackerList::headerLabels() -{ - static const QStringList header { - "#" - , tr("URL") - , tr("Status") - , tr("Received") - , tr("Seeds") - , tr("Peers") - , tr("Downloaded") - , tr("Message") - }; - - return header; -} - -int TrackerList::visibleColumnsCount() const -{ - int visibleCols = 0; - for (unsigned int i = 0; i < COL_COUNT; ++i) { - if (!isColumnHidden(i)) - ++visibleCols; - } - - return visibleCols; -} - -void TrackerList::displayToggleColumnsMenu(const QPoint &) -{ - QMenu hideshowColumn(this); - hideshowColumn.setTitle(tr("Column visibility")); - for (int i = 0; i < COL_COUNT; ++i) { - QAction *myAct = hideshowColumn.addAction(headerLabels().at(i)); - myAct->setCheckable(true); - myAct->setChecked(!isColumnHidden(i)); - myAct->setData(i); - } - - // Call menu - QAction *act = hideshowColumn.exec(QCursor::pos()); - if (!act) return; - - int col = act->data().toInt(); - Q_ASSERT(visibleColumnsCount() > 0); - if (!isColumnHidden(col) && (visibleColumnsCount() == 1)) - return; - qDebug("Toggling column %d visibility", col); - setColumnHidden(col, !isColumnHidden(col)); - if (!isColumnHidden(col) && (columnWidth(col) <= 5)) - setColumnWidth(col, 100); - saveSettings(); -} diff --git a/src/gui/properties/trackerlist.h b/src/gui/properties/trackerlist.h deleted file mode 100644 index 5271918d8..000000000 --- a/src/gui/properties/trackerlist.h +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2006 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. - */ - -#ifndef TRACKERLIST_H -#define TRACKERLIST_H - -#include -#include -#include -#include - -#include "propertieswidget.h" - -#define NB_STICKY_ITEM 3 - -namespace BitTorrent -{ - class TorrentHandle; -} - -class TrackerList: public QTreeWidget -{ - Q_OBJECT - Q_DISABLE_COPY(TrackerList) - -public: - enum TrackerListColumn - { - COL_TIER, - COL_URL, - COL_STATUS, - COL_RECEIVED, - COL_SEEDS, - COL_PEERS, - COL_DOWNLOADED, - COL_MSG, - - COL_COUNT - }; - - TrackerList(PropertiesWidget *properties); - ~TrackerList(); - - int visibleColumnsCount() const; - -public slots: - void setRowColor(int row, QColor color); - - void moveSelectionUp(); - void moveSelectionDown(); - - void clear(); - void loadStickyItems(BitTorrent::TorrentHandle *const torrent); - void loadTrackers(); - void askForTrackers(); - void copyTrackerUrl(); - void reannounceSelected(); - void deleteSelectedTrackers(); - void editSelectedTracker(); - void showTrackerListMenu(QPoint); - void displayToggleColumnsMenu(const QPoint &); - void loadSettings(); - void saveSettings() const; - -protected: - QList getSelectedTrackerItems() const; - -private: - PropertiesWidget *m_properties; - QHash m_trackerItems; - QTreeWidgetItem *m_DHTItem; - QTreeWidgetItem *m_PEXItem; - QTreeWidgetItem *m_LSDItem; - QShortcut *m_editHotkey; - QShortcut *m_deleteHotkey; - QShortcut *m_copyHotkey; - - static QStringList headerLabels(); -}; - -#endif // TRACKERLIST_H diff --git a/src/gui/properties/trackersadditiondlg.cpp b/src/gui/properties/trackersadditiondlg.cpp deleted file mode 100644 index cf98eea63..000000000 --- a/src/gui/properties/trackersadditiondlg.cpp +++ /dev/null @@ -1,143 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2006 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 "trackersadditiondlg.h" - -#include -#include -#include -#include - -#include "base/utils/misc.h" -#include "base/utils/fs.h" -#include "base/net/downloadmanager.h" -#include "base/net/downloadhandler.h" -#include "base/bittorrent/trackerentry.h" -#include "base/bittorrent/torrenthandle.h" -#include "guiiconprovider.h" -#include "ui_trackersadditiondlg.h" - -TrackersAdditionDlg::TrackersAdditionDlg(QWidget *parent, BitTorrent::TorrentHandle *const torrent) - : QDialog(parent) - , m_ui(new Ui::TrackersAdditionDlg()) - , m_torrent(torrent) -{ - m_ui->setupUi(this); - // Icons - m_ui->uTorrentListButton->setIcon(GuiIconProvider::instance()->getIcon("download")); -} - -TrackersAdditionDlg::~TrackersAdditionDlg() -{ - delete m_ui; -} - -QStringList TrackersAdditionDlg::newTrackers() const -{ - QStringList cleanTrackers; - foreach (QString url, m_ui->trackers_list->toPlainText().split("\n")) { - url = url.trimmed(); - if (!url.isEmpty()) - cleanTrackers << url; - } - return cleanTrackers; -} - -void TrackersAdditionDlg::on_uTorrentListButton_clicked() -{ - m_ui->uTorrentListButton->setEnabled(false); - Net::DownloadHandler *handler = Net::DownloadManager::instance()->downloadUrl(m_ui->list_url->text(), true); - connect(handler, SIGNAL(downloadFinished(QString, QString)), this, SLOT(parseUTorrentList(QString, QString))); - connect(handler, SIGNAL(downloadFailed(QString, QString)), this, SLOT(getTrackerError(QString, QString))); - //Just to show that it takes times - setCursor(Qt::WaitCursor); -} - -void TrackersAdditionDlg::parseUTorrentList(const QString &, const QString &path) -{ - QFile list_file(path); - if (!list_file.open(QFile::ReadOnly)) { - QMessageBox::warning(this, tr("I/O Error"), tr("Error while trying to open the downloaded file."), QMessageBox::Ok); - setCursor(Qt::ArrowCursor); - m_ui->uTorrentListButton->setEnabled(true); - Utils::Fs::forceRemove(path); - return; - } - - // Load from torrent handle - QList existingTrackers = m_torrent->trackers(); - // Load from current user list - QStringList tmp = m_ui->trackers_list->toPlainText().split("\n"); - foreach (const QString &user_url, tmp) { - BitTorrent::TrackerEntry userTracker(user_url); - if (!existingTrackers.contains(userTracker)) - existingTrackers << userTracker; - } - - // Add new trackers to the list - if (!m_ui->trackers_list->toPlainText().isEmpty() && !m_ui->trackers_list->toPlainText().endsWith("\n")) - m_ui->trackers_list->insertPlainText("\n"); - int nb = 0; - while (!list_file.atEnd()) { - const QByteArray line = list_file.readLine().trimmed(); - if (line.isEmpty()) continue; - BitTorrent::TrackerEntry newTracker(line); - if (!existingTrackers.contains(newTracker)) { - m_ui->trackers_list->insertPlainText(line + "\n"); - ++nb; - } - } - // Clean up - list_file.close(); - Utils::Fs::forceRemove(path); - //To restore the cursor ... - setCursor(Qt::ArrowCursor); - m_ui->uTorrentListButton->setEnabled(true); - // Display information message if necessary - if (nb == 0) - QMessageBox::information(this, tr("No change"), tr("No additional trackers were found."), QMessageBox::Ok); -} - -void TrackersAdditionDlg::getTrackerError(const QString &, const QString &error) -{ - //To restore the cursor ... - setCursor(Qt::ArrowCursor); - m_ui->uTorrentListButton->setEnabled(true); - QMessageBox::warning(this, tr("Download error"), tr("The trackers list could not be downloaded, reason: %1").arg(error), QMessageBox::Ok); -} - -QStringList TrackersAdditionDlg::askForTrackers(QWidget *parent, BitTorrent::TorrentHandle *const torrent) -{ - QStringList trackers; - TrackersAdditionDlg dlg(parent, torrent); - if (dlg.exec() == QDialog::Accepted) - return dlg.newTrackers(); - - return trackers; -} diff --git a/src/gui/properties/trackersadditiondlg.h b/src/gui/properties/trackersadditiondlg.h deleted file mode 100644 index fc355acea..000000000 --- a/src/gui/properties/trackersadditiondlg.h +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2006 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 TRACKERSADDITION_H -#define TRACKERSADDITION_H - -#include - -class QString; -class QStringList; - -namespace BitTorrent -{ - class TorrentHandle; -} - -namespace Ui -{ - class TrackersAdditionDlg; -} - -class TrackersAdditionDlg : public QDialog -{ - Q_OBJECT - -public: - TrackersAdditionDlg(QWidget *parent, BitTorrent::TorrentHandle *const torrent); - ~TrackersAdditionDlg(); - - QStringList newTrackers() const; - static QStringList askForTrackers(QWidget *parent, BitTorrent::TorrentHandle *const torrent); - -public slots: - void on_uTorrentListButton_clicked(); - void parseUTorrentList(const QString &, const QString &path); - void getTrackerError(const QString &, const QString &error); - -private: - Ui::TrackersAdditionDlg *m_ui; - BitTorrent::TorrentHandle *const m_torrent; -}; - -#endif diff --git a/src/gui/properties/trackersadditiondlg.ui b/src/gui/properties/trackersadditiondlg.ui deleted file mode 100644 index bee0e607a..000000000 --- a/src/gui/properties/trackersadditiondlg.ui +++ /dev/null @@ -1,98 +0,0 @@ - - - TrackersAdditionDlg - - - - 0 - 0 - 367 - 274 - - - - Trackers addition dialog - - - - - - List of trackers to add (one per line): - - - - - - - QTextEdit::NoWrap - - - false - - - - - - - µTorrent compatible list URL: - - - - - - - - - - - - - - - - - Qt::Horizontal - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - - - - - - - buttonBox - accepted() - TrackersAdditionDlg - accept() - - - 248 - 254 - - - 157 - 274 - - - - - buttonBox - rejected() - TrackersAdditionDlg - reject() - - - 316 - 260 - - - 286 - 274 - - - - - diff --git a/src/gui/qtnotify/CMakeLists.txt b/src/gui/qtnotify/CMakeLists.txt deleted file mode 100644 index fb97b97e2..000000000 --- a/src/gui/qtnotify/CMakeLists.txt +++ /dev/null @@ -1,11 +0,0 @@ -set(QBT_QTNOTIFY_SOURCES -notifications.cpp -) - -set(QBT_QTNOTIFY_HEADERS -notifications.h -) - -add_library(qbt_qtnotify STATIC ${QBT_QTNOTIFY_SOURCES} ${QBT_QTNOTIFY_HEADERS}) -set_target_properties(qbt_qtnotify PROPERTIES AUTOUIC False AUTORCC False) -target_link_qt_components(qbt_qtnotify DBus) diff --git a/src/gui/qtnotify/notifications.cpp b/src/gui/qtnotify/notifications.cpp deleted file mode 100644 index 57722dd91..000000000 --- a/src/gui/qtnotify/notifications.cpp +++ /dev/null @@ -1,26 +0,0 @@ -/* - * This file was generated by qdbusxml2cpp version 0.7 - * Command line was: qdbusxml2cpp -p notifications.h:notifications.cpp notifications.xml - * - * qdbusxml2cpp is Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). - * - * This is an auto-generated file. - * This file may have been hand-edited. Look for HAND-EDIT comments - * before re-generating it. - */ - -#include "notifications.h" - -/* - * Implementation of interface class OrgFreedesktopNotificationsInterface - */ - -OrgFreedesktopNotificationsInterface::OrgFreedesktopNotificationsInterface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent) - : QDBusAbstractInterface(service, path, staticInterfaceName(), connection, parent) -{ -} - -OrgFreedesktopNotificationsInterface::~OrgFreedesktopNotificationsInterface() -{ -} - diff --git a/src/gui/qtnotify/notifications.h b/src/gui/qtnotify/notifications.h deleted file mode 100644 index fe975fd27..000000000 --- a/src/gui/qtnotify/notifications.h +++ /dev/null @@ -1,84 +0,0 @@ -/* - * This file was generated by qdbusxml2cpp version 0.7 - * Command line was: qdbusxml2cpp -p notifications.h:notifications.cpp notifications.xml - * - * qdbusxml2cpp is Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). - * - * This is an auto-generated file. - * Do not edit! All changes made to it will be lost. - */ - -#ifndef NOTIFICATIONS_H_1301681398 -#define NOTIFICATIONS_H_1301681398 - -#include -#include -#include -#include -#include -#include -#include -#include - -/* - * Proxy class for interface org.freedesktop.Notifications - */ -class OrgFreedesktopNotificationsInterface: public QDBusAbstractInterface -{ - Q_OBJECT -public: - static inline const char *staticInterfaceName() - { return "org.freedesktop.Notifications"; } - -public: - OrgFreedesktopNotificationsInterface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = 0); - - ~OrgFreedesktopNotificationsInterface(); - -public Q_SLOTS: // METHODS - inline QDBusPendingReply<> CloseNotification(uint id) - { - QList argumentList; - argumentList << qVariantFromValue(id); - return asyncCallWithArgumentList(QLatin1String("CloseNotification"), argumentList); - } - - inline QDBusPendingReply GetCapabilities() - { - QList argumentList; - return asyncCallWithArgumentList(QLatin1String("GetCapabilities"), argumentList); - } - - inline QDBusPendingReply GetServerInformation() - { - QList argumentList; - return asyncCallWithArgumentList(QLatin1String("GetServerInformation"), argumentList); - } - inline QDBusReply GetServerInformation(QString &return_vendor, QString &return_version, QString &return_spec_version) - { - QList argumentList; - QDBusMessage reply = callWithArgumentList(QDBus::Block, QLatin1String("GetServerInformation"), argumentList); - if (reply.type() == QDBusMessage::ReplyMessage && reply.arguments().count() == 4) { - return_vendor = qdbus_cast(reply.arguments().at(1)); - return_version = qdbus_cast(reply.arguments().at(2)); - return_spec_version = qdbus_cast(reply.arguments().at(3)); - } - return reply; - } - - inline QDBusPendingReply Notify(const QString &app_name, uint id, const QString &icon, const QString &summary, const QString &body, const QStringList &actions, const QVariantMap &hints, int timeout) - { - QList argumentList; - argumentList << qVariantFromValue(app_name) << qVariantFromValue(id) << qVariantFromValue(icon) << qVariantFromValue(summary) << qVariantFromValue(body) << qVariantFromValue(actions) << qVariantFromValue(hints) << qVariantFromValue(timeout); - return asyncCallWithArgumentList(QLatin1String("Notify"), argumentList); - } - -Q_SIGNALS: // SIGNALS -}; - -namespace org { - namespace freedesktop { - typedef ::OrgFreedesktopNotificationsInterface Notifications; - } -} -#endif diff --git a/src/gui/qtnotify/notifications.xml b/src/gui/qtnotify/notifications.xml deleted file mode 100644 index 7c1d2e7ad..000000000 --- a/src/gui/qtnotify/notifications.xml +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/gui/qtnotify/qtnotify.pri b/src/gui/qtnotify/qtnotify.pri deleted file mode 100644 index 84d288a4a..000000000 --- a/src/gui/qtnotify/qtnotify.pri +++ /dev/null @@ -1,5 +0,0 @@ -INCLUDEPATH += $$PWD - -HEADERS += $$PWD/notifications.h - -SOURCES += $$PWD/notifications.cpp diff --git a/src/gui/rss/CMakeLists.txt b/src/gui/rss/CMakeLists.txt deleted file mode 100644 index c7d03408c..000000000 --- a/src/gui/rss/CMakeLists.txt +++ /dev/null @@ -1,26 +0,0 @@ -include_directories(${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}) - -set(QBT_RSS_HEADERS -articlelistwidget.h -automatedrssdownloader.h -feedlistwidget.h -htmlbrowser.h -rsswidget.h -) - -set(QBT_RSS_SOURCE -articlelistwidget.cpp -automatedrssdownloader.cpp -feedlistwidget.cpp -htmlbrowser.cpp -rsswidget.cpp -) - -set(QBT_RSS_FORMS -automatedrssdownloader.ui -rsswidget.ui -) - -add_library(qbt_rss STATIC ${QBT_RSS_HEADERS} ${QBT_RSS_SOURCE} ${QBT_RSS_FORMS}) -target_link_libraries(qbt_rss qbt_base) -target_link_libraries(qbt_rss Qt5::Gui Qt5::Widgets Qt5::Network) diff --git a/src/gui/rss/articlelistwidget.cpp b/src/gui/rss/articlelistwidget.cpp deleted file mode 100644 index cef67b943..000000000 --- a/src/gui/rss/articlelistwidget.cpp +++ /dev/null @@ -1,133 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2017 Vladimir Golovnev - * - * 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. - */ - -#include "articlelistwidget.h" - -#include - -#include "base/rss/rss_article.h" -#include "base/rss/rss_item.h" - -ArticleListWidget::ArticleListWidget(QWidget *parent) - : QListWidget(parent) -{ - setContextMenuPolicy(Qt::CustomContextMenu); - setSelectionMode(QAbstractItemView::ExtendedSelection); - - checkInvariant(); -} - -RSS::Article *ArticleListWidget::getRSSArticle(QListWidgetItem *item) const -{ - Q_ASSERT(item); - return reinterpret_cast(item->data(Qt::UserRole).value()); -} - -QListWidgetItem *ArticleListWidget::mapRSSArticle(RSS::Article *rssArticle) const -{ - return m_rssArticleToListItemMapping.value(rssArticle); -} - -void ArticleListWidget::setRSSItem(RSS::Item *rssItem, bool unreadOnly) -{ - // Clear the list first - clear(); - m_rssArticleToListItemMapping.clear(); - if (m_rssItem) - m_rssItem->disconnect(this); - - m_unreadOnly = unreadOnly; - m_rssItem = rssItem; - if (m_rssItem) { - connect(m_rssItem, &RSS::Item::newArticle, this, &ArticleListWidget::handleArticleAdded); - connect(m_rssItem, &RSS::Item::articleRead, this, &ArticleListWidget::handleArticleRead); - connect(m_rssItem, &RSS::Item::articleAboutToBeRemoved, this, &ArticleListWidget::handleArticleAboutToBeRemoved); - - foreach (auto article, rssItem->articles()) { - if (!(m_unreadOnly && article->isRead())) { - auto item = createItem(article); - addItem(item); - m_rssArticleToListItemMapping.insert(article, item); - } - } - } - - checkInvariant(); -} - -void ArticleListWidget::handleArticleAdded(RSS::Article *rssArticle) -{ - if (!(m_unreadOnly && rssArticle->isRead())) { - auto item = createItem(rssArticle); - insertItem(0, item); - m_rssArticleToListItemMapping.insert(rssArticle, item); - } - - checkInvariant(); -} - -void ArticleListWidget::handleArticleRead(RSS::Article *rssArticle) -{ - auto item = mapRSSArticle(rssArticle); - if (!item) return; - - item->setData(Qt::ForegroundRole, QPalette().color(QPalette::Inactive, QPalette::WindowText)); - item->setData(Qt::DecorationRole, QIcon(":/icons/sphere.png")); - - checkInvariant(); -} - -void ArticleListWidget::handleArticleAboutToBeRemoved(RSS::Article *rssArticle) -{ - delete m_rssArticleToListItemMapping.take(rssArticle); - checkInvariant(); -} - -void ArticleListWidget::checkInvariant() const -{ - Q_ASSERT(count() == m_rssArticleToListItemMapping.count()); -} - -QListWidgetItem *ArticleListWidget::createItem(RSS::Article *article) const -{ - Q_ASSERT(article); - QListWidgetItem *item = new QListWidgetItem; - - item->setData(Qt::DisplayRole, article->title()); - item->setData(Qt::UserRole, reinterpret_cast(article)); - if (article->isRead()) { - item->setData(Qt::ForegroundRole, QPalette().color(QPalette::Inactive, QPalette::WindowText)); - item->setData(Qt::DecorationRole, QIcon(":/icons/sphere.png")); - } - else { - item->setData(Qt::ForegroundRole, QPalette().color(QPalette::Active, QPalette::Link)); - item->setData(Qt::DecorationRole, QIcon(":/icons/sphere2.png")); - } - - return item; -} diff --git a/src/gui/rss/articlelistwidget.h b/src/gui/rss/articlelistwidget.h deleted file mode 100644 index 6c35892b0..000000000 --- a/src/gui/rss/articlelistwidget.h +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2017 Vladimir Golovnev - * - * 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. - */ - -#ifndef ARTICLELISTWIDGET_H -#define ARTICLELISTWIDGET_H - -#include -#include - -namespace RSS -{ - class Article; - class Item; -} - -class ArticleListWidget: public QListWidget -{ - Q_OBJECT - -public: - explicit ArticleListWidget(QWidget *parent); - - RSS::Article *getRSSArticle(QListWidgetItem *item) const; - QListWidgetItem *mapRSSArticle(RSS::Article *rssArticle) const; - - void setRSSItem(RSS::Item *rssItem, bool unreadOnly = false); - -private slots: - void handleArticleAdded(RSS::Article *rssArticle); - void handleArticleRead(RSS::Article *rssArticle); - void handleArticleAboutToBeRemoved(RSS::Article *rssArticle); - -private: - void checkInvariant() const; - QListWidgetItem *createItem(RSS::Article *article) const; - - RSS::Item *m_rssItem = nullptr; - bool m_unreadOnly = false; - QHash m_rssArticleToListItemMapping; -}; - -#endif // ARTICLELISTWIDGET_H diff --git a/src/gui/rss/automatedrssdownloader.cpp b/src/gui/rss/automatedrssdownloader.cpp deleted file mode 100644 index 4b54cb96d..000000000 --- a/src/gui/rss/automatedrssdownloader.cpp +++ /dev/null @@ -1,715 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2017 Vladimir Golovnev - * Copyright (C) 2010 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. - */ - -#include "automatedrssdownloader.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "base/bittorrent/session.h" -#include "base/preferences.h" -#include "base/rss/rss_article.h" -#include "base/rss/rss_autodownloader.h" -#include "base/rss/rss_feed.h" -#include "base/rss/rss_folder.h" -#include "base/rss/rss_session.h" -#include "base/utils/fs.h" -#include "base/utils/string.h" -#include "guiiconprovider.h" -#include "autoexpandabledialog.h" -#include "ui_automatedrssdownloader.h" - -AutomatedRssDownloader::AutomatedRssDownloader(QWidget *parent) - : QDialog(parent) - , m_ui(new Ui::AutomatedRssDownloader) - , m_currentRuleItem(nullptr) -{ - m_ui->setupUi(this); - // Icons - m_ui->removeRuleBtn->setIcon(GuiIconProvider::instance()->getIcon("list-remove")); - m_ui->addRuleBtn->setIcon(GuiIconProvider::instance()->getIcon("list-add")); - - // Ui Settings - m_ui->listRules->setSortingEnabled(true); - m_ui->listRules->setSelectionMode(QAbstractItemView::ExtendedSelection); - m_ui->treeMatchingArticles->setSortingEnabled(true); - m_ui->treeMatchingArticles->sortByColumn(0, Qt::AscendingOrder); - m_ui->hsplitter->setCollapsible(0, false); - m_ui->hsplitter->setCollapsible(1, false); - m_ui->hsplitter->setCollapsible(2, true); // Only the preview list is collapsible - - connect(m_ui->checkRegex, &QAbstractButton::toggled, this, &AutomatedRssDownloader::updateFieldsToolTips); - connect(m_ui->listRules, &QWidget::customContextMenuRequested, this, &AutomatedRssDownloader::displayRulesListMenu); - - m_episodeRegex = new QRegularExpression("^(^\\d{1,4}x(\\d{1,4}(-(\\d{1,4})?)?;){1,}){1,1}" - , QRegularExpression::CaseInsensitiveOption); - QString tip = "

" + tr("Matches articles based on episode filter.") + "

" + tr("Example: ") - + "1x2;8-15;5;30-;" + tr(" will match 2, 5, 8 through 15, 30 and onward episodes of season one", "example X will match") + "

"; - tip += "

" + tr("Episode filter rules: ") + "

  • " + tr("Season number is a mandatory non-zero value") + "
  • " - + "
  • " + tr("Episode number is a mandatory positive value") + "
  • " - + "
  • " + tr("Filter must end with semicolon") + "
  • " - + "
  • " + tr("Three range types for episodes are supported: ") + "
  • " + "
    • " - + "
    • " + tr("Single number: 1x25; matches episode 25 of season one") + "
    • " - + "
    • " + tr("Normal range: 1x25-40; matches episodes 25 through 40 of season one") + "
    • " - + "
    • " + tr("Infinite range: 1x25-; matches episodes 25 and upward of season one, and all episodes of later seasons") + "
    • " + "
"; - m_ui->lineEFilter->setToolTip(tip); - - initCategoryCombobox(); - loadSettings(); - - connect(RSS::AutoDownloader::instance(), &RSS::AutoDownloader::ruleAdded, this, &AutomatedRssDownloader::handleRuleAdded); - connect(RSS::AutoDownloader::instance(), &RSS::AutoDownloader::ruleRenamed, this, &AutomatedRssDownloader::handleRuleRenamed); - connect(RSS::AutoDownloader::instance(), &RSS::AutoDownloader::ruleChanged, this, &AutomatedRssDownloader::handleRuleChanged); - connect(RSS::AutoDownloader::instance(), &RSS::AutoDownloader::ruleAboutToBeRemoved, this, &AutomatedRssDownloader::handleRuleAboutToBeRemoved); - - // Update matching articles when necessary - connect(m_ui->lineContains, &QLineEdit::textEdited, this, &AutomatedRssDownloader::handleRuleDefinitionChanged); - connect(m_ui->lineContains, &QLineEdit::textEdited, this, &AutomatedRssDownloader::updateMustLineValidity); - connect(m_ui->lineNotContains, &QLineEdit::textEdited, this, &AutomatedRssDownloader::handleRuleDefinitionChanged); - connect(m_ui->lineNotContains, &QLineEdit::textEdited, this, &AutomatedRssDownloader::updateMustNotLineValidity); - connect(m_ui->lineEFilter, &QLineEdit::textEdited, this, &AutomatedRssDownloader::handleRuleDefinitionChanged); - connect(m_ui->lineEFilter, &QLineEdit::textEdited, this, &AutomatedRssDownloader::updateEpisodeFilterValidity); - connect(m_ui->checkRegex, &QCheckBox::stateChanged, this, &AutomatedRssDownloader::handleRuleDefinitionChanged); - connect(m_ui->checkRegex, &QCheckBox::stateChanged, this, &AutomatedRssDownloader::updateMustLineValidity); - connect(m_ui->checkRegex, &QCheckBox::stateChanged, this, &AutomatedRssDownloader::updateMustNotLineValidity); - - connect(m_ui->listFeeds, &QListWidget::itemChanged, this, &AutomatedRssDownloader::handleFeedCheckStateChange); - - connect(m_ui->listRules, &QListWidget::itemSelectionChanged, this, &AutomatedRssDownloader::updateRuleDefinitionBox); - connect(m_ui->listRules, &QListWidget::itemChanged, this, &AutomatedRssDownloader::handleRuleCheckStateChange); - - m_editHotkey = new QShortcut(Qt::Key_F2, m_ui->listRules, 0, 0, Qt::WidgetShortcut); - connect(m_editHotkey, &QShortcut::activated, this, &AutomatedRssDownloader::renameSelectedRule); - connect(m_ui->listRules, &QAbstractItemView::doubleClicked, this, &AutomatedRssDownloader::renameSelectedRule); - - m_deleteHotkey = new QShortcut(QKeySequence::Delete, m_ui->listRules, 0, 0, Qt::WidgetShortcut); - connect(m_deleteHotkey, &QShortcut::activated, this, &AutomatedRssDownloader::on_removeRuleBtn_clicked); - - loadFeedList(); - - m_ui->listRules->blockSignals(true); - foreach (const RSS::AutoDownloadRule &rule, RSS::AutoDownloader::instance()->rules()) - createRuleItem(rule); - m_ui->listRules->blockSignals(false); - - updateRuleDefinitionBox(); - - if (RSS::AutoDownloader::instance()->isProcessingEnabled()) - m_ui->labelWarn->hide(); - connect(RSS::AutoDownloader::instance(), &RSS::AutoDownloader::processingStateChanged - , this, &AutomatedRssDownloader::handleProcessingStateChanged); -} - -AutomatedRssDownloader::~AutomatedRssDownloader() -{ - // Save current item on exit - saveEditedRule(); - saveSettings(); - - delete m_editHotkey; - delete m_deleteHotkey; - delete m_ui; - delete m_episodeRegex; -} - -void AutomatedRssDownloader::loadSettings() -{ - const Preferences *const pref = Preferences::instance(); - resize(pref->getRssGeometrySize(this->size())); - m_ui->hsplitter->restoreState(pref->getRssHSplitterSizes()); -} - -void AutomatedRssDownloader::saveSettings() -{ - Preferences *const pref = Preferences::instance(); - pref->setRssGeometrySize(this->size()); - pref->setRssHSplitterSizes(m_ui->hsplitter->saveState()); -} - -void AutomatedRssDownloader::createRuleItem(const RSS::AutoDownloadRule &rule) -{ - QListWidgetItem *item = new QListWidgetItem(rule.name(), m_ui->listRules); - m_itemsByRuleName.insert(rule.name(), item); - item->setFlags(item->flags() | Qt::ItemIsUserCheckable); - item->setCheckState(rule.isEnabled() ? Qt::Checked : Qt::Unchecked); -} - -void AutomatedRssDownloader::loadFeedList() -{ - const QSignalBlocker feedListSignalBlocker(m_ui->listFeeds); - - foreach (auto feed, RSS::Session::instance()->feeds()) { - QListWidgetItem *item = new QListWidgetItem(feed->name(), m_ui->listFeeds); - item->setData(Qt::UserRole, feed->url()); - item->setFlags(item->flags() | Qt::ItemIsUserCheckable | Qt::ItemIsTristate); - } - - updateFeedList(); -} - -void AutomatedRssDownloader::updateFeedList() -{ - const QSignalBlocker feedListSignalBlocker(m_ui->listFeeds); - - QList selection; - - if (m_currentRuleItem) - selection << m_currentRuleItem; - else - selection = m_ui->listRules->selectedItems(); - - bool enable = !selection.isEmpty(); - - for (int i = 0; i < m_ui->listFeeds->count(); ++i) { - QListWidgetItem *item = m_ui->listFeeds->item(i); - const QString feedURL = item->data(Qt::UserRole).toString(); - item->setHidden(!enable); - - bool allEnabled = true; - bool anyEnabled = false; - - foreach (const QListWidgetItem *ruleItem, selection) { - auto rule = RSS::AutoDownloader::instance()->ruleByName(ruleItem->text()); - if (rule.feedURLs().contains(feedURL)) - anyEnabled = true; - else - allEnabled = false; - } - - if (anyEnabled && allEnabled) - item->setCheckState(Qt::Checked); - else if (anyEnabled) - item->setCheckState(Qt::PartiallyChecked); - else - item->setCheckState(Qt::Unchecked); - } - - m_ui->listFeeds->sortItems(); - m_ui->lblListFeeds->setEnabled(enable); - m_ui->listFeeds->setEnabled(enable); -} - -void AutomatedRssDownloader::updateRuleDefinitionBox() -{ - const QList selection = m_ui->listRules->selectedItems(); - QListWidgetItem *currentRuleItem = ((selection.count() == 1) ? selection.first() : nullptr); - if (m_currentRuleItem != currentRuleItem) { - saveEditedRule(); // Save previous rule first - m_currentRuleItem = currentRuleItem; - //m_ui->listRules->setCurrentItem(m_currentRuleItem); - } - - // Update rule definition box - if (m_currentRuleItem) { - m_currentRule = RSS::AutoDownloader::instance()->ruleByName(m_currentRuleItem->text()); - - m_ui->lineContains->setText(m_currentRule.mustContain()); - m_ui->lineNotContains->setText(m_currentRule.mustNotContain()); - if (!m_currentRule.episodeFilter().isEmpty()) - m_ui->lineEFilter->setText(m_currentRule.episodeFilter()); - else - m_ui->lineEFilter->clear(); - m_ui->saveDiffDir_check->setChecked(!m_currentRule.savePath().isEmpty()); - m_ui->lineSavePath->setText(Utils::Fs::toNativePath(m_currentRule.savePath())); - m_ui->checkRegex->blockSignals(true); - m_ui->checkRegex->setChecked(m_currentRule.useRegex()); - m_ui->checkRegex->blockSignals(false); - m_ui->comboCategory->setCurrentIndex(m_ui->comboCategory->findText(m_currentRule.assignedCategory())); - if (m_currentRule.assignedCategory().isEmpty()) - m_ui->comboCategory->clearEditText(); - int index = 0; - if (m_currentRule.addPaused() == TriStateBool::True) - index = 1; - else if (m_currentRule.addPaused() == TriStateBool::False) - index = 2; - m_ui->comboAddPaused->setCurrentIndex(index); - m_ui->spinIgnorePeriod->setValue(m_currentRule.ignoreDays()); - QDateTime dateTime = m_currentRule.lastMatch(); - QString lMatch; - if (dateTime.isValid()) - lMatch = tr("Last Match: %1 days ago").arg(dateTime.daysTo(QDateTime::currentDateTime())); - else - lMatch = tr("Last Match: Unknown"); - m_ui->lblLastMatch->setText(lMatch); - updateMustLineValidity(); - updateMustNotLineValidity(); - updateEpisodeFilterValidity(); - - updateFieldsToolTips(m_ui->checkRegex->isChecked()); - m_ui->ruleDefBox->setEnabled(true); - } - else { - m_currentRule = RSS::AutoDownloadRule(); - clearRuleDefinitionBox(); - m_ui->ruleDefBox->setEnabled(false); - } - - updateFeedList(); - updateMatchingArticles(); -} - -void AutomatedRssDownloader::clearRuleDefinitionBox() -{ - m_ui->lineContains->clear(); - m_ui->lineNotContains->clear(); - m_ui->lineEFilter->clear(); - m_ui->saveDiffDir_check->setChecked(false); - m_ui->lineSavePath->clear(); - m_ui->comboCategory->clearEditText(); - m_ui->comboCategory->setCurrentIndex(-1); - m_ui->checkRegex->setChecked(false); - m_ui->spinIgnorePeriod->setValue(0); - m_ui->comboAddPaused->clearEditText(); - m_ui->comboAddPaused->setCurrentIndex(-1); - updateFieldsToolTips(m_ui->checkRegex->isChecked()); - updateMustLineValidity(); - updateMustNotLineValidity(); - updateEpisodeFilterValidity(); -} - -void AutomatedRssDownloader::initCategoryCombobox() -{ - // Load torrent categories - QStringList categories = BitTorrent::Session::instance()->categories(); - std::sort(categories.begin(), categories.end(), Utils::String::naturalCompareCaseInsensitive); - m_ui->comboCategory->addItem(""); - m_ui->comboCategory->addItems(categories); -} - -void AutomatedRssDownloader::updateEditedRule() -{ - if (!m_currentRuleItem || !m_ui->ruleDefBox->isEnabled()) return; - - m_currentRule.setEnabled(m_currentRuleItem->checkState() != Qt::Unchecked); - m_currentRule.setUseRegex(m_ui->checkRegex->isChecked()); - m_currentRule.setMustContain(m_ui->lineContains->text()); - m_currentRule.setMustNotContain(m_ui->lineNotContains->text()); - m_currentRule.setEpisodeFilter(m_ui->lineEFilter->text()); - m_currentRule.setSavePath(m_ui->saveDiffDir_check->isChecked() ? m_ui->lineSavePath->text() : ""); - m_currentRule.setCategory(m_ui->comboCategory->currentText()); - TriStateBool addPaused; // Undefined by default - if (m_ui->comboAddPaused->currentIndex() == 1) - addPaused = TriStateBool::True; - else if (m_ui->comboAddPaused->currentIndex() == 2) - addPaused = TriStateBool::False; - m_currentRule.setAddPaused(addPaused); - m_currentRule.setIgnoreDays(m_ui->spinIgnorePeriod->value()); -} - -void AutomatedRssDownloader::saveEditedRule() -{ - if (!m_currentRuleItem || !m_ui->ruleDefBox->isEnabled()) return; - - updateEditedRule(); - RSS::AutoDownloader::instance()->insertRule(m_currentRule); -} - -void AutomatedRssDownloader::on_addRuleBtn_clicked() -{ -// saveEditedRule(); - - // Ask for a rule name - const QString ruleName = AutoExpandableDialog::getText( - this, tr("New rule name"), tr("Please type the name of the new download rule.")); - if (ruleName.isEmpty()) return; - - // Check if this rule name already exists - if (RSS::AutoDownloader::instance()->hasRule(ruleName)) { - QMessageBox::warning(this, tr("Rule name conflict") - , tr("A rule with this name already exists, please choose another name.")); - return; - } - - RSS::AutoDownloader::instance()->insertRule(RSS::AutoDownloadRule(ruleName)); -} - -void AutomatedRssDownloader::on_removeRuleBtn_clicked() -{ - const QList selection = m_ui->listRules->selectedItems(); - if (selection.isEmpty()) return; - - // Ask for confirmation - const QString confirmText = ((selection.count() == 1) - ? tr("Are you sure you want to remove the download rule named '%1'?") - .arg(selection.first()->text()) - : tr("Are you sure you want to remove the selected download rules?")); - if (QMessageBox::question(this, tr("Rule deletion confirmation"), confirmText, QMessageBox::Yes, QMessageBox::No) != QMessageBox::Yes) - return; - - foreach (QListWidgetItem *item, selection) - RSS::AutoDownloader::instance()->removeRule(item->text()); -} - -void AutomatedRssDownloader::on_browseSP_clicked() -{ - QString savePath = QFileDialog::getExistingDirectory(this, tr("Destination directory"), QDir::homePath()); - if (!savePath.isEmpty()) - m_ui->lineSavePath->setText(Utils::Fs::toNativePath(savePath)); -} - -void AutomatedRssDownloader::on_exportBtn_clicked() -{ -// if (m_editableRuleList->isEmpty()) { -// QMessageBox::warning(this, tr("Invalid action"), tr("The list is empty, there is nothing to export.")); -// return; -// } -// // Ask for a save path -// QString save_path = QFileDialog::getSaveFileName(this, tr("Where would you like to save the list?"), QDir::homePath(), tr("Rules list (*.rssrules)")); -// if (save_path.isEmpty()) return; -// if (!save_path.endsWith(".rssrules", Qt::CaseInsensitive)) -// save_path += ".rssrules"; -// if (!m_editableRuleList->serialize(save_path)) { -// QMessageBox::warning(this, tr("I/O Error"), tr("Failed to create the destination file")); -// return; -// } -} - -void AutomatedRssDownloader::on_importBtn_clicked() -{ -// // Ask for filter path -// QString load_path = QFileDialog::getOpenFileName(this, tr("Please point to the RSS download rules file"), QDir::homePath(), tr("Rules list") + QString(" (*.rssrules *.filters)")); -// if (load_path.isEmpty() || !QFile::exists(load_path)) return; -// // Load it -// if (!m_editableRuleList->unserialize(load_path)) { -// QMessageBox::warning(this, tr("Import Error"), tr("Failed to import the selected rules file")); -// return; -// } -} - -void AutomatedRssDownloader::displayRulesListMenu() -{ - QMenu menu; - QAction *addAct = menu.addAction(GuiIconProvider::instance()->getIcon("list-add"), tr("Add new rule...")); - QAction *delAct = nullptr; - QAction *renameAct = nullptr; - const QList selection = m_ui->listRules->selectedItems(); - if (!selection.isEmpty()) { - if (selection.count() == 1) { - delAct = menu.addAction(GuiIconProvider::instance()->getIcon("list-remove"), tr("Delete rule")); - menu.addSeparator(); - renameAct = menu.addAction(GuiIconProvider::instance()->getIcon("edit-rename"), tr("Rename rule...")); - } - else { - delAct = menu.addAction(GuiIconProvider::instance()->getIcon("list-remove"), tr("Delete selected rules")); - } - } - - QAction *act = menu.exec(QCursor::pos()); - if (!act) return; - - if (act == addAct) - on_addRuleBtn_clicked(); - else if (act == delAct) - on_removeRuleBtn_clicked(); - else if (act == renameAct) - renameSelectedRule(); -} - -void AutomatedRssDownloader::renameSelectedRule() -{ - const QList selection = m_ui->listRules->selectedItems(); - if (selection.isEmpty()) return; - - QListWidgetItem *item = selection.first(); - forever { - QString newName = AutoExpandableDialog::getText( - this, tr("Rule renaming"), tr("Please type the new rule name") - , QLineEdit::Normal, item->text()); - newName = newName.trimmed(); - if (newName.isEmpty()) return; - - if (RSS::AutoDownloader::instance()->hasRule(newName)) { - QMessageBox::warning(this, tr("Rule name conflict") - , tr("A rule with this name already exists, please choose another name.")); - } - else { - // Rename the rule - RSS::AutoDownloader::instance()->renameRule(item->text(), newName); - return; - } - } -} - -void AutomatedRssDownloader::handleRuleCheckStateChange(QListWidgetItem *ruleItem) -{ - m_ui->listRules->setCurrentItem(ruleItem); -} - -void AutomatedRssDownloader::handleFeedCheckStateChange(QListWidgetItem *feedItem) -{ - const QString feedURL = feedItem->data(Qt::UserRole).toString(); - foreach (QListWidgetItem *ruleItem, m_ui->listRules->selectedItems()) { - RSS::AutoDownloadRule rule = (ruleItem == m_currentRuleItem - ? m_currentRule - : RSS::AutoDownloader::instance()->ruleByName(ruleItem->text())); - QStringList affectedFeeds = rule.feedURLs(); - if ((feedItem->checkState() == Qt::Checked) && !affectedFeeds.contains(feedURL)) - affectedFeeds << feedURL; - else if ((feedItem->checkState() == Qt::Unchecked) && affectedFeeds.contains(feedURL)) - affectedFeeds.removeOne(feedURL); - - rule.setFeedURLs(affectedFeeds); - if (ruleItem != m_currentRuleItem) - RSS::AutoDownloader::instance()->insertRule(rule); - else - m_currentRule = rule; - } - - handleRuleDefinitionChanged(); -} - -void AutomatedRssDownloader::updateMatchingArticles() -{ - m_ui->treeMatchingArticles->clear(); - - foreach (const QListWidgetItem *ruleItem, m_ui->listRules->selectedItems()) { - RSS::AutoDownloadRule rule = (ruleItem == m_currentRuleItem - ? m_currentRule - : RSS::AutoDownloader::instance()->ruleByName(ruleItem->text())); - foreach (const QString &feedURL, rule.feedURLs()) { - auto feed = RSS::Session::instance()->feedByURL(feedURL); - if (!feed) continue; // feed doesn't exists - - QStringList matchingArticles; - foreach (auto article, feed->articles()) - if (rule.matches(article->title())) - matchingArticles << article->title(); - if (!matchingArticles.isEmpty()) - addFeedArticlesToTree(feed, matchingArticles); - } - } - - m_treeListEntries.clear(); -} - -void AutomatedRssDownloader::addFeedArticlesToTree(RSS::Feed *feed, const QStringList &articles) -{ - // Turn off sorting while inserting - m_ui->treeMatchingArticles->setSortingEnabled(false); - - // Check if this feed is already in the tree - QTreeWidgetItem *treeFeedItem = nullptr; - for (int i = 0; i < m_ui->treeMatchingArticles->topLevelItemCount(); ++i) { - QTreeWidgetItem *item = m_ui->treeMatchingArticles->topLevelItem(i); - if (item->data(0, Qt::UserRole).toString() == feed->url()) { - treeFeedItem = item; - break; - } - } - - // If there is none, create it - if (!treeFeedItem) { - treeFeedItem = new QTreeWidgetItem(QStringList() << feed->name()); - treeFeedItem->setToolTip(0, feed->name()); - QFont f = treeFeedItem->font(0); - f.setBold(true); - treeFeedItem->setFont(0, f); - treeFeedItem->setData(0, Qt::DecorationRole, GuiIconProvider::instance()->getIcon("inode-directory")); - treeFeedItem->setData(0, Qt::UserRole, feed->url()); - m_ui->treeMatchingArticles->addTopLevelItem(treeFeedItem); - } - - // Insert the articles - foreach (const QString &article, articles) { - QPair key(feed->name(), article); - - if (!m_treeListEntries.contains(key)) { - m_treeListEntries << key; - QTreeWidgetItem *item = new QTreeWidgetItem(QStringList() << article); - item->setToolTip(0, article); - treeFeedItem->addChild(item); - } - } - - m_ui->treeMatchingArticles->expandItem(treeFeedItem); - m_ui->treeMatchingArticles->sortItems(0, Qt::AscendingOrder); - m_ui->treeMatchingArticles->setSortingEnabled(true); -} - -void AutomatedRssDownloader::updateFieldsToolTips(bool regex) -{ - QString tip; - if (regex) { - tip = "

" + tr("Regex mode: use Perl-compatible regular expressions") + "

"; - } - else { - tip = "

" + tr("Wildcard mode: you can use") + "

    " - + "
  • " + tr("? to match any single character") + "
  • " - + "
  • " + tr("* to match zero or more of any characters") + "
  • " - + "
  • " + tr("Whitespaces count as AND operators (all words, any order)") + "
  • " - + "
  • " + tr("| is used as OR operator") + "

" - + "

" + tr("If word order is important use * instead of whitespace.") + "

"; - } - - // Whether regex or wildcard, warn about a potential gotcha for users. - // Explanatory string broken over multiple lines for readability (and multiple - // statements to prevent uncrustify indenting excessively. - tip += "

"; - tip += tr("An expression with an empty %1 clause (e.g. %2)", - "We talk about regex/wildcards in the RSS filters section here." - " So a valid sentence would be: An expression with an empty | clause (e.g. expr|)" - ).arg("|").arg("expr|"); - m_ui->lineContains->setToolTip(tip + tr(" will match all articles.") + "

"); - m_ui->lineNotContains->setToolTip(tip + tr(" will exclude all articles.") + "

"); -} - -void AutomatedRssDownloader::updateMustLineValidity() -{ - const QString text = m_ui->lineContains->text(); - bool isRegex = m_ui->checkRegex->isChecked(); - bool valid = true; - QString error; - - if (!text.isEmpty()) { - QStringList tokens; - if (isRegex) - tokens << text; - else - foreach (const QString &token, text.split("|")) - tokens << Utils::String::wildcardToRegex(token); - - foreach (const QString &token, tokens) { - QRegularExpression reg(token, QRegularExpression::CaseInsensitiveOption); - if (!reg.isValid()) { - if (isRegex) - error = tr("Position %1: %2").arg(reg.patternErrorOffset()).arg(reg.errorString()); - valid = false; - break; - } - } - } - - if (valid) { - m_ui->lineContains->setStyleSheet(""); - m_ui->lbl_must_stat->setPixmap(QPixmap()); - m_ui->lbl_must_stat->setToolTip(""); - } - else { - m_ui->lineContains->setStyleSheet("QLineEdit { color: #ff0000; }"); - m_ui->lbl_must_stat->setPixmap(GuiIconProvider::instance()->getIcon("task-attention").pixmap(16, 16)); - m_ui->lbl_must_stat->setToolTip(error); - } -} - -void AutomatedRssDownloader::updateMustNotLineValidity() -{ - const QString text = m_ui->lineNotContains->text(); - bool isRegex = m_ui->checkRegex->isChecked(); - bool valid = true; - QString error; - - if (!text.isEmpty()) { - QStringList tokens; - if (isRegex) - tokens << text; - else - foreach (const QString &token, text.split("|")) - tokens << Utils::String::wildcardToRegex(token); - - foreach (const QString &token, tokens) { - QRegularExpression reg(token, QRegularExpression::CaseInsensitiveOption); - if (!reg.isValid()) { - if (isRegex) - error = tr("Position %1: %2").arg(reg.patternErrorOffset()).arg(reg.errorString()); - valid = false; - break; - } - } - } - - if (valid) { - m_ui->lineNotContains->setStyleSheet(""); - m_ui->lbl_mustnot_stat->setPixmap(QPixmap()); - m_ui->lbl_mustnot_stat->setToolTip(""); - } - else { - m_ui->lineNotContains->setStyleSheet("QLineEdit { color: #ff0000; }"); - m_ui->lbl_mustnot_stat->setPixmap(GuiIconProvider::instance()->getIcon("task-attention").pixmap(16, 16)); - m_ui->lbl_mustnot_stat->setToolTip(error); - } -} - -void AutomatedRssDownloader::updateEpisodeFilterValidity() -{ - const QString text = m_ui->lineEFilter->text(); - bool valid = text.isEmpty() || m_episodeRegex->match(text).hasMatch(); - - if (valid) { - m_ui->lineEFilter->setStyleSheet(""); - m_ui->lbl_epfilter_stat->setPixmap(QPixmap()); - } - else { - m_ui->lineEFilter->setStyleSheet("QLineEdit { color: #ff0000; }"); - m_ui->lbl_epfilter_stat->setPixmap(GuiIconProvider::instance()->getIcon("task-attention").pixmap(16, 16)); - } -} - -void AutomatedRssDownloader::handleRuleDefinitionChanged() -{ - updateEditedRule(); - updateMatchingArticles(); -} - -void AutomatedRssDownloader::handleRuleAdded(const QString &ruleName) -{ - createRuleItem(RSS::AutoDownloadRule(ruleName)); -} - -void AutomatedRssDownloader::handleRuleRenamed(const QString &ruleName, const QString &oldRuleName) -{ - auto item = m_itemsByRuleName.value(oldRuleName); - m_itemsByRuleName.insert(ruleName, item); - item->setText(ruleName); -} - -void AutomatedRssDownloader::handleRuleChanged(const QString &ruleName) -{ - auto item = m_itemsByRuleName.value(ruleName); - if (item != m_currentRuleItem) - item->setCheckState(RSS::AutoDownloader::instance()->ruleByName(ruleName).isEnabled() ? Qt::Checked : Qt::Unchecked); -} - -void AutomatedRssDownloader::handleRuleAboutToBeRemoved(const QString &ruleName) -{ - delete m_itemsByRuleName.take(ruleName); -} - -void AutomatedRssDownloader::handleProcessingStateChanged(bool enabled) -{ - m_ui->labelWarn->setVisible(!enabled); -} diff --git a/src/gui/rss/automatedrssdownloader.h b/src/gui/rss/automatedrssdownloader.h deleted file mode 100644 index acbd9b955..000000000 --- a/src/gui/rss/automatedrssdownloader.h +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2017 Vladimir Golovnev - * Copyright (C) 2010 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. - */ - -#ifndef AUTOMATEDRSSDOWNLOADER_H -#define AUTOMATEDRSSDOWNLOADER_H - -#include -#include -#include -#include - -#include "base/rss/rss_autodownloadrule.h" - -namespace Ui -{ - class AutomatedRssDownloader; -} - -class QListWidgetItem; -class QRegularExpression; -class QShortcut; - -namespace RSS -{ - class Feed; -} - -class AutomatedRssDownloader: public QDialog -{ - Q_OBJECT - -public: - explicit AutomatedRssDownloader(QWidget *parent = nullptr); - ~AutomatedRssDownloader() override; - -private slots: - void on_addRuleBtn_clicked(); - void on_removeRuleBtn_clicked(); - void on_browseSP_clicked(); - void on_exportBtn_clicked(); - void on_importBtn_clicked(); - - void handleRuleCheckStateChange(QListWidgetItem *ruleItem); - void handleFeedCheckStateChange(QListWidgetItem *feedItem); - void displayRulesListMenu(); - void renameSelectedRule(); - void updateRuleDefinitionBox(); - void updateFieldsToolTips(bool regex); - void updateMustLineValidity(); - void updateMustNotLineValidity(); - void updateEpisodeFilterValidity(); - void handleRuleDefinitionChanged(); - void handleRuleAdded(const QString &ruleName); - void handleRuleRenamed(const QString &ruleName, const QString &oldRuleName); - void handleRuleChanged(const QString &ruleName); - void handleRuleAboutToBeRemoved(const QString &ruleName); - - void handleProcessingStateChanged(bool enabled); - -private: - void loadSettings(); - void saveSettings(); - void createRuleItem(const RSS::AutoDownloadRule &rule); - void initCategoryCombobox(); - void clearRuleDefinitionBox(); - void updateEditedRule(); - void updateMatchingArticles(); - void saveEditedRule(); - void loadFeedList(); - void updateFeedList(); - void addFeedArticlesToTree(RSS::Feed *feed, const QStringList &articles); - - Ui::AutomatedRssDownloader *m_ui; - QListWidgetItem *m_currentRuleItem; - QShortcut *m_editHotkey; - QShortcut *m_deleteHotkey; - QSet> m_treeListEntries; - RSS::AutoDownloadRule m_currentRule; - QHash m_itemsByRuleName; - QRegularExpression *m_episodeRegex; -}; - -#endif // AUTOMATEDRSSDOWNLOADER_H diff --git a/src/gui/rss/automatedrssdownloader.ui b/src/gui/rss/automatedrssdownloader.ui deleted file mode 100644 index 6c9db0cdf..000000000 --- a/src/gui/rss/automatedrssdownloader.ui +++ /dev/null @@ -1,500 +0,0 @@ - - - AutomatedRssDownloader - - - - 0 - 0 - 816 - 523 - - - - RSS Downloader - - - - - - - true - - - - color: red; - - - Auto downloading of RSS torrents is disabled now! You can enable it in application settings. - - - true - - - - - - - - 0 - 0 - - - - Qt::Horizontal - - - - - - - - - - 75 - true - - - - Download Rules - - - - - - - - 24 - 20 - - - - - - - - - 24 - 20 - - - - - - - - - - Qt::CustomContextMenu - - - - - - - - - - - Rule Definition - - - - - - Use Regular Expressions - - - - - - - - - Must Contain: - - - - - - - Must Not Contain: - - - - - - - Episode Filter: - - - - - - - - 18 - 18 - - - - - - - - - 18 - 18 - - - - - - - - - - - - 18 - 18 - - - - - - - - - 18 - 18 - - - - - - - - - - - - - - - - Qt::Horizontal - - - - - - - - - - 0 - 0 - - - - Assign Category: - - - - - - - false - - - - - - - - - Save to a Different Directory - - - - - - - - - false - - - Save to: - - - - - - - false - - - - - - - false - - - ... - - - - - - - - - - - Ignore Subsequent Matches for (0 to Disable) - - - - - - - true - - - Disabled - - - days - - - 0 - - - 365 - - - - - - - - - true - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - - - 0 - 0 - - - - Add Paused: - - - - - - - - Use global settings - - - - - Always - - - - - Never - - - - - - - - - - - - - - - - 50 - false - - - - Apply Rule to Feeds: - - - - - - - - - - - - - - - - - 75 - true - - - - Matching RSS Articles - - - - - - - false - - - - 1 - - - - - - - - - - - - - - false - - - &Import... - - - - - - - false - - - &Export... - - - - - - - QDialogButtonBox::Close - - - - - - - - - - - buttonBox - accepted() - AutomatedRssDownloader - accept() - - - 750 - 483 - - - 157 - 274 - - - - - buttonBox - rejected() - AutomatedRssDownloader - reject() - - - 805 - 483 - - - 286 - 274 - - - - - saveDiffDir_check - toggled(bool) - label_6 - setEnabled(bool) - - - 304 - 171 - - - 377 - 205 - - - - - saveDiffDir_check - toggled(bool) - lineSavePath - setEnabled(bool) - - - 474 - 174 - - - 476 - 204 - - - - - saveDiffDir_check - toggled(bool) - browseSP - setEnabled(bool) - - - 544 - 166 - - - 549 - 209 - - - - - diff --git a/src/gui/rss/feedlistwidget.cpp b/src/gui/rss/feedlistwidget.cpp deleted file mode 100644 index 40754a8a2..000000000 --- a/src/gui/rss/feedlistwidget.cpp +++ /dev/null @@ -1,273 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2017 Vladimir Golovnev - * Copyright (C) 2010 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. - */ - -#include "feedlistwidget.h" - -#include -#include -#include - -#include "base/rss/rss_article.h" -#include "base/rss/rss_feed.h" -#include "base/rss/rss_folder.h" -#include "base/rss/rss_session.h" -#include "guiiconprovider.h" - -FeedListWidget::FeedListWidget(QWidget *parent) - : QTreeWidget(parent) -{ - setContextMenuPolicy(Qt::CustomContextMenu); - setDragDropMode(QAbstractItemView::InternalMove); - setSelectionMode(QAbstractItemView::ExtendedSelection); - setColumnCount(1); - headerItem()->setText(0, tr("RSS feeds")); - - connect(RSS::Session::instance(), &RSS::Session::itemAdded, this, &FeedListWidget::handleItemAdded); - connect(RSS::Session::instance(), &RSS::Session::feedStateChanged, this, &FeedListWidget::handleFeedStateChanged); - connect(RSS::Session::instance(), &RSS::Session::feedIconLoaded, this, &FeedListWidget::handleFeedIconLoaded); - connect(RSS::Session::instance(), &RSS::Session::itemPathChanged, this, &FeedListWidget::handleItemPathChanged); - connect(RSS::Session::instance(), &RSS::Session::itemAboutToBeRemoved, this, &FeedListWidget::handleItemAboutToBeRemoved); - - m_rssToTreeItemMapping[RSS::Session::instance()->rootFolder()] = invisibleRootItem(); - - m_unreadStickyItem = new QTreeWidgetItem(this); - m_unreadStickyItem->setData(0, Qt::UserRole, reinterpret_cast(RSS::Session::instance()->rootFolder())); - m_unreadStickyItem->setText(0, tr("Unread (%1)").arg(RSS::Session::instance()->rootFolder()->unreadCount())); - m_unreadStickyItem->setData(0, Qt::DecorationRole, GuiIconProvider::instance()->getIcon("mail-folder-inbox")); - - connect(RSS::Session::instance()->rootFolder(), &RSS::Item::unreadCountChanged, this, &FeedListWidget::handleItemUnreadCountChanged); - - setSortingEnabled(false); - fill(nullptr, RSS::Session::instance()->rootFolder()); - setSortingEnabled(true); - -// setCurrentItem(m_unreadStickyItem); -} - -FeedListWidget::~FeedListWidget() -{ - delete m_unreadStickyItem; -} - -void FeedListWidget::handleItemAdded(RSS::Item *rssItem) -{ - auto parentItem = m_rssToTreeItemMapping.value( - RSS::Session::instance()->itemByPath(RSS::Item::parentPath(rssItem->path()))); - createItem(rssItem, parentItem); -} - -void FeedListWidget::handleFeedStateChanged(RSS::Feed *feed) -{ - QTreeWidgetItem *item = m_rssToTreeItemMapping.value(feed); - Q_ASSERT(item); - - QIcon icon; - if (feed->isLoading()) - icon = QIcon(QStringLiteral(":/icons/loading.png")); - else if (feed->hasError()) - icon = GuiIconProvider::instance()->getIcon(QStringLiteral("unavailable")); - else if (!feed->iconPath().isEmpty()) - icon = QIcon(feed->iconPath()); - else - icon = GuiIconProvider::instance()->getIcon(QStringLiteral("application-rss+xml")); - item->setData(0, Qt::DecorationRole, icon); -} - -void FeedListWidget::handleFeedIconLoaded(RSS::Feed *feed) -{ - if (!feed->isLoading() && !feed->hasError()) { - QTreeWidgetItem *item = m_rssToTreeItemMapping.value(feed); - Q_ASSERT(item); - - item->setData(0, Qt::DecorationRole, QIcon(feed->iconPath())); - } -} - -void FeedListWidget::handleItemUnreadCountChanged(RSS::Item *rssItem) -{ - if (rssItem == RSS::Session::instance()->rootFolder()) { - m_unreadStickyItem->setText(0, tr("Unread (%1)").arg(RSS::Session::instance()->rootFolder()->unreadCount())); - } - else { - QTreeWidgetItem *item = mapRSSItem(rssItem); - Q_ASSERT(item); - item->setData(0, Qt::DisplayRole, QString("%1 (%2)").arg(rssItem->name()).arg(rssItem->unreadCount())); - } -} - -void FeedListWidget::handleItemPathChanged(RSS::Item *rssItem) -{ - QTreeWidgetItem *item = mapRSSItem(rssItem); - Q_ASSERT(item); - - item->setData(0, Qt::DisplayRole, QString("%1 (%2)").arg(rssItem->name()).arg(rssItem->unreadCount())); - - RSS::Item *parentRssItem = RSS::Session::instance()->itemByPath(RSS::Item::parentPath(rssItem->path())); - QTreeWidgetItem *parentItem = mapRSSItem(parentRssItem); - Q_ASSERT(parentItem); - - parentItem->addChild(item); -} - -void FeedListWidget::handleItemAboutToBeRemoved(RSS::Item *rssItem) -{ - rssItem->disconnect(this); - delete m_rssToTreeItemMapping.take(rssItem); - - // RSS Item is still valid in this slot so if it is the last - // item we should prevent Unread list populating - if (m_rssToTreeItemMapping.size() == 1) - setCurrentItem(nullptr); -} - -QTreeWidgetItem *FeedListWidget::stickyUnreadItem() const -{ - return m_unreadStickyItem; -} - -QList FeedListWidget::getAllOpenedFolders(QTreeWidgetItem *parent) const -{ - QList openedFolders; - int nbChildren = (parent ? parent->childCount() : topLevelItemCount()); - for (int i = 0; i < nbChildren; ++i) { - QTreeWidgetItem *item (parent ? parent->child(i) : topLevelItem(i)); - if (isFolder(item) && item->isExpanded()) { - QList openedSubfolders = getAllOpenedFolders(item); - if (!openedSubfolders.empty()) - openedFolders << openedSubfolders; - else - openedFolders << item; - } - } - return openedFolders; -} - -RSS::Item *FeedListWidget::getRSSItem(QTreeWidgetItem *item) const -{ - if (!item) return nullptr; - - return reinterpret_cast(item->data(0, Qt::UserRole).value()); -} - -QTreeWidgetItem *FeedListWidget::mapRSSItem(RSS::Item *rssItem) const -{ - return m_rssToTreeItemMapping.value(rssItem); -} - -QString FeedListWidget::itemPath(QTreeWidgetItem *item) const -{ - return getRSSItem(item)->path(); -} - -bool FeedListWidget::isFeed(QTreeWidgetItem *item) const -{ - return qobject_cast(getRSSItem(item)); -} - -bool FeedListWidget::isFolder(QTreeWidgetItem *item) const -{ - return qobject_cast(getRSSItem(item)); -} - -void FeedListWidget::dragMoveEvent(QDragMoveEvent *event) -{ - QTreeWidget::dragMoveEvent(event); - - QTreeWidgetItem *item = itemAt(event->pos()); - // Prohibit dropping onto global unread counter - if (item == m_unreadStickyItem) - event->ignore(); - // Prohibit dragging of global unread counter - else if (selectedItems().contains(m_unreadStickyItem)) - event->ignore(); - // Prohibit dropping onto feeds - else if (item && isFeed(item)) - event->ignore(); -} - -void FeedListWidget::dropEvent(QDropEvent *event) -{ - QTreeWidgetItem *destFolderItem = itemAt(event->pos()); - RSS::Folder *destFolder = (destFolderItem - ? static_cast(getRSSItem(destFolderItem)) - : RSS::Session::instance()->rootFolder()); - - // move as much items as possible - foreach (QTreeWidgetItem *srcItem, selectedItems()) { - auto rssItem = getRSSItem(srcItem); - RSS::Session::instance()->moveItem(rssItem, RSS::Item::joinPath(destFolder->path(), rssItem->name())); - } - - QTreeWidget::dropEvent(event); - if (destFolderItem) - destFolderItem->setExpanded(true); -} - -QTreeWidgetItem *FeedListWidget::createItem(RSS::Item *rssItem, QTreeWidgetItem *parentItem) -{ - QTreeWidgetItem *item = new QTreeWidgetItem; - item->setData(0, Qt::DisplayRole, QString("%1 (%2)").arg(rssItem->name()).arg(rssItem->unreadCount())); - item->setData(0, Qt::UserRole, reinterpret_cast(rssItem)); - m_rssToTreeItemMapping[rssItem] = item; - - QIcon icon; - if (auto feed = qobject_cast(rssItem)) { - if (feed->isLoading()) - icon = QIcon(QStringLiteral(":/icons/loading.png")); - else if (feed->hasError()) - icon = GuiIconProvider::instance()->getIcon(QStringLiteral("unavailable")); - else if (!feed->iconPath().isEmpty()) - icon = QIcon(feed->iconPath()); - else - icon = GuiIconProvider::instance()->getIcon(QStringLiteral("application-rss+xml")); - } - else { - icon = GuiIconProvider::instance()->getIcon("inode-directory"); - } - item->setData(0, Qt::DecorationRole, icon); - - connect(rssItem, &RSS::Item::unreadCountChanged, this, &FeedListWidget::handleItemUnreadCountChanged); - - if (!parentItem || (parentItem == m_unreadStickyItem)) - addTopLevelItem(item); - else - parentItem->addChild(item); - - return item; -} - -void FeedListWidget::fill(QTreeWidgetItem *parent, RSS::Folder *rssParent) -{ - foreach (auto rssItem, rssParent->items()) { - QTreeWidgetItem *item = createItem(rssItem, parent); - // Recursive call if this is a folder. - if (auto folder = qobject_cast(rssItem)) - fill(item, folder); - } -} diff --git a/src/gui/rss/feedlistwidget.h b/src/gui/rss/feedlistwidget.h deleted file mode 100644 index f7667a275..000000000 --- a/src/gui/rss/feedlistwidget.h +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2017 Vladimir Golovnev - * Copyright (C) 2010 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. - */ - -#ifndef FEEDLISTWIDGET_H -#define FEEDLISTWIDGET_H - -#include -#include - -namespace RSS -{ - class Article; - class Feed; - class Folder; - class Item; -} - -class FeedListWidget: public QTreeWidget -{ - Q_OBJECT - -public: - explicit FeedListWidget(QWidget *parent); - ~FeedListWidget(); - - QTreeWidgetItem *stickyUnreadItem() const; - QList getAllOpenedFolders(QTreeWidgetItem *parent = nullptr) const; - RSS::Item *getRSSItem(QTreeWidgetItem *item) const; - QTreeWidgetItem *mapRSSItem(RSS::Item *rssItem) const; - QString itemPath(QTreeWidgetItem *item) const; - bool isFeed(QTreeWidgetItem *item) const; - bool isFolder(QTreeWidgetItem *item) const; - -private slots: - void handleItemAdded(RSS::Item *rssItem); - void handleFeedStateChanged(RSS::Feed *feed); - void handleFeedIconLoaded(RSS::Feed *feed); - void handleItemUnreadCountChanged(RSS::Item *rssItem); - void handleItemPathChanged(RSS::Item *rssItem); - void handleItemAboutToBeRemoved(RSS::Item *rssItem); - -private: - void dragMoveEvent(QDragMoveEvent *event); - void dropEvent(QDropEvent *event); - QTreeWidgetItem *createItem(RSS::Item *rssItem, QTreeWidgetItem *parentItem = nullptr); - void fill(QTreeWidgetItem *parent, RSS::Folder *rssParent); - - QHash m_rssToTreeItemMapping; - QTreeWidgetItem *m_unreadStickyItem; -}; - -#endif // FEEDLISTWIDGET_H diff --git a/src/gui/rss/htmlbrowser.cpp b/src/gui/rss/htmlbrowser.cpp deleted file mode 100644 index e378b0405..000000000 --- a/src/gui/rss/htmlbrowser.cpp +++ /dev/null @@ -1,93 +0,0 @@ -#include "htmlbrowser.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "base/profile.h" - -HtmlBrowser::HtmlBrowser(QWidget* parent) - : QTextBrowser(parent) -{ - m_netManager = new QNetworkAccessManager(this); - m_diskCache = new QNetworkDiskCache(this); - m_diskCache->setCacheDirectory(QDir::cleanPath(specialFolderLocation(SpecialFolder::Cache) + "/rss")); - m_diskCache->setMaximumCacheSize(50 * 1024 * 1024); - qDebug() << "HtmlBrowser cache path:" << m_diskCache->cacheDirectory() << " max size:" << m_diskCache->maximumCacheSize() / 1024 / 1024 << "MB"; - m_netManager->setCache(m_diskCache); - - connect(m_netManager, SIGNAL(finished(QNetworkReply *)), this, SLOT(resourceLoaded(QNetworkReply*))); -} - -HtmlBrowser::~HtmlBrowser() -{ -} - -QVariant HtmlBrowser::loadResource(int type, const QUrl &name) -{ - if(type == QTextDocument::ImageResource) { - QUrl url(name); - if(url.scheme().isEmpty()) - url.setScheme("http"); - - QIODevice *dev = m_diskCache->data(url); - if(dev != 0) { - qDebug() << "HtmlBrowser::loadResource() cache " << url.toString(); - QByteArray res = dev->readAll(); - delete dev; - return res; - } - - if(!m_activeRequests.contains(url)) { - m_activeRequests.insert(url, true); - qDebug() << "HtmlBrowser::loadResource() get " << url.toString(); - QNetworkRequest req(url); - req.setAttribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferCache); - m_netManager->get(req); - } - - return QVariant(); - } - - return QTextBrowser::loadResource(type, name); -} - -void HtmlBrowser::resourceLoaded(QNetworkReply *reply) -{ - m_activeRequests.remove(reply->request().url()); - - if(reply->error() == QNetworkReply::NoError && reply->size() > 0) { - qDebug() << "HtmlBrowser::resourceLoaded() save " << reply->request().url().toString(); - } - else { - // If resource failed to load, replace it with warning icon and store it in cache for 1 day. - // Otherwise HTMLBrowser will keep trying to download it every time article is displayed, - // since it's not possible to cache error responses. - QNetworkCacheMetaData metaData; - QNetworkCacheMetaData::AttributesMap atts; - metaData.setUrl(reply->request().url()); - metaData.setSaveToDisk(true); - atts[QNetworkRequest::HttpStatusCodeAttribute] = 200; - atts[QNetworkRequest::HttpReasonPhraseAttribute] = "Ok"; - metaData.setAttributes(atts); - metaData.setLastModified(QDateTime::currentDateTime()); - metaData.setExpirationDate(QDateTime::currentDateTime().addDays(1)); - QIODevice *dev = m_diskCache->prepare(metaData); - if(!dev) - return; - QApplication::style()->standardIcon(QStyle::SP_MessageBoxWarning).pixmap(32, 32).save(dev, "PNG"); - m_diskCache->insert(dev); - } - // Refresh the document display and keep scrollbars where they are - int sx = horizontalScrollBar()->value(); - int sy = verticalScrollBar()->value(); - document()->setHtml(document()->toHtml()); - horizontalScrollBar()->setValue(sx); - verticalScrollBar()->setValue(sy); -} diff --git a/src/gui/rss/htmlbrowser.h b/src/gui/rss/htmlbrowser.h deleted file mode 100644 index 8be699552..000000000 --- a/src/gui/rss/htmlbrowser.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef HTMLBROWSER_H -#define HTMLBROWSER_H - -#include -#include - -class QNetworkAccessManager; -class QNetworkDiskCache; -class QNetworkReply; - -class HtmlBrowser: public QTextBrowser -{ - Q_OBJECT - -public: - explicit HtmlBrowser(QWidget* parent = 0); - ~HtmlBrowser(); - - virtual QVariant loadResource(int type, const QUrl &name); - -protected: - QNetworkAccessManager *m_netManager; - QNetworkDiskCache *m_diskCache; - QHash m_activeRequests; - -protected slots: - void resourceLoaded(QNetworkReply *reply); -}; - -#endif // HTMLBROWSER_H diff --git a/src/gui/rss/rsswidget.cpp b/src/gui/rss/rsswidget.cpp deleted file mode 100644 index ef6dec28a..000000000 --- a/src/gui/rss/rsswidget.cpp +++ /dev/null @@ -1,530 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2017 Vladimir Golovnev - * Copyright (C) 2006 Christophe Dumez - * Copyright (C) 2006 Arnaud Demaiziere - * - * 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. - */ - -#include "rsswidget.h" - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "base/bittorrent/session.h" -#include "base/net/downloadmanager.h" -#include "base/preferences.h" -#include "base/rss/rss_article.h" -#include "base/rss/rss_feed.h" -#include "base/rss/rss_folder.h" -#include "base/rss/rss_session.h" -#include "base/utils/misc.h" -#include "addnewtorrentdialog.h" -#include "articlelistwidget.h" -#include "autoexpandabledialog.h" -#include "automatedrssdownloader.h" -#include "feedlistwidget.h" -#include "guiiconprovider.h" -#include "ui_rsswidget.h" - -RSSWidget::RSSWidget(QWidget *parent) - : QWidget(parent) - , m_ui(new Ui::RSSWidget) -{ - m_ui->setupUi(this); - - // Icons - m_ui->actionCopyFeedURL->setIcon(GuiIconProvider::instance()->getIcon("edit-copy")); - m_ui->actionDelete->setIcon(GuiIconProvider::instance()->getIcon("edit-delete")); - m_ui->actionDownloadTorrent->setIcon(GuiIconProvider::instance()->getIcon("download")); - m_ui->actionMarkItemsRead->setIcon(GuiIconProvider::instance()->getIcon("mail-mark-read")); - m_ui->actionNewFolder->setIcon(GuiIconProvider::instance()->getIcon("folder-new")); - m_ui->actionNewSubscription->setIcon(GuiIconProvider::instance()->getIcon("list-add")); - m_ui->actionOpenNewsURL->setIcon(GuiIconProvider::instance()->getIcon("application-x-mswinurl")); - m_ui->actionRename->setIcon(GuiIconProvider::instance()->getIcon("edit-rename")); - m_ui->actionUpdate->setIcon(GuiIconProvider::instance()->getIcon("view-refresh")); - m_ui->actionUpdateAllFeeds->setIcon(GuiIconProvider::instance()->getIcon("view-refresh")); -#ifndef Q_OS_MAC - m_ui->newFeedButton->setIcon(GuiIconProvider::instance()->getIcon("list-add")); - m_ui->markReadButton->setIcon(GuiIconProvider::instance()->getIcon("mail-mark-read")); - m_ui->updateAllButton->setIcon(GuiIconProvider::instance()->getIcon("view-refresh")); - m_ui->rssDownloaderBtn->setIcon(GuiIconProvider::instance()->getIcon("download")); -#endif - - m_articleListWidget = new ArticleListWidget(m_ui->splitterMain); - m_ui->splitterMain->insertWidget(0, m_articleListWidget); - connect(m_articleListWidget, &ArticleListWidget::customContextMenuRequested, this, &RSSWidget::displayItemsListMenu); - connect(m_articleListWidget, &ArticleListWidget::currentItemChanged, this, &RSSWidget::handleCurrentArticleItemChanged); - connect(m_articleListWidget, &ArticleListWidget::itemDoubleClicked, this, &RSSWidget::downloadSelectedTorrents); - - m_feedListWidget = new FeedListWidget(m_ui->splitterSide); - m_ui->splitterSide->insertWidget(0, m_feedListWidget); - connect(m_feedListWidget, &QAbstractItemView::doubleClicked, this, &RSSWidget::renameSelectedRSSItem); - connect(m_feedListWidget, &QTreeWidget::currentItemChanged, this, &RSSWidget::handleCurrentFeedItemChanged); - connect(m_feedListWidget, &QWidget::customContextMenuRequested, this, &RSSWidget::displayRSSListMenu); - loadFoldersOpenState(); - m_feedListWidget->setCurrentItem(m_feedListWidget->stickyUnreadItem()); - - m_editHotkey = new QShortcut(Qt::Key_F2, m_feedListWidget, 0, 0, Qt::WidgetShortcut); - connect(m_editHotkey, &QShortcut::activated, this, &RSSWidget::renameSelectedRSSItem); - m_deleteHotkey = new QShortcut(QKeySequence::Delete, m_feedListWidget, 0, 0, Qt::WidgetShortcut); - connect(m_deleteHotkey, &QShortcut::activated, this, &RSSWidget::deleteSelectedItems); - - // Feeds list actions - connect(m_ui->actionDelete, &QAction::triggered, this, &RSSWidget::deleteSelectedItems); - connect(m_ui->actionRename, &QAction::triggered, this, &RSSWidget::renameSelectedRSSItem); - connect(m_ui->actionUpdate, &QAction::triggered, this, &RSSWidget::refreshSelectedItems); - connect(m_ui->actionNewFolder, &QAction::triggered, this, &RSSWidget::askNewFolder); - connect(m_ui->actionNewSubscription, &QAction::triggered, this, &RSSWidget::on_newFeedButton_clicked); - connect(m_ui->actionUpdateAllFeeds, &QAction::triggered, this, &RSSWidget::refreshAllFeeds); - connect(m_ui->updateAllButton, &QAbstractButton::clicked, this, &RSSWidget::refreshAllFeeds); - connect(m_ui->actionCopyFeedURL, &QAction::triggered, this, &RSSWidget::copySelectedFeedsURL); - connect(m_ui->actionMarkItemsRead, &QAction::triggered, this, &RSSWidget::on_markReadButton_clicked); - - // News list actions - connect(m_ui->actionOpenNewsURL, &QAction::triggered, this, &RSSWidget::openSelectedArticlesUrls); - connect(m_ui->actionDownloadTorrent, &QAction::triggered, this, &RSSWidget::downloadSelectedTorrents); - - // Restore sliders position - restoreSlidersPosition(); - // Bind saveSliders slots - connect(m_ui->splitterMain, &QSplitter::splitterMoved, this, &RSSWidget::saveSlidersPosition); - connect(m_ui->splitterSide, &QSplitter::splitterMoved, this, &RSSWidget::saveSlidersPosition); - - if (RSS::Session::instance()->isProcessingEnabled()) - m_ui->labelWarn->hide(); - connect(RSS::Session::instance(), &RSS::Session::processingStateChanged - , this, &RSSWidget::handleSessionProcessingStateChanged); - connect(RSS::Session::instance()->rootFolder(), &RSS::Folder::unreadCountChanged - , this, &RSSWidget::handleUnreadCountChanged); -} - -RSSWidget::~RSSWidget() -{ - // we need it here to properly mark latest article - // as read without having additional code - m_articleListWidget->clear(); - - saveFoldersOpenState(); - - delete m_editHotkey; - delete m_deleteHotkey; - delete m_feedListWidget; - delete m_ui; -} - -// display a right-click menu -void RSSWidget::displayRSSListMenu(const QPoint &pos) -{ - if (!m_feedListWidget->indexAt(pos).isValid()) - // No item under the mouse, clear selection - m_feedListWidget->clearSelection(); - QMenu myRSSListMenu(this); - QList selectedItems = m_feedListWidget->selectedItems(); - if (selectedItems.size() > 0) { - myRSSListMenu.addAction(m_ui->actionUpdate); - myRSSListMenu.addAction(m_ui->actionMarkItemsRead); - myRSSListMenu.addSeparator(); - if (selectedItems.size() == 1) { - if (selectedItems.first() != m_feedListWidget->stickyUnreadItem()) { - myRSSListMenu.addAction(m_ui->actionRename); - myRSSListMenu.addAction(m_ui->actionDelete); - myRSSListMenu.addSeparator(); - if (m_feedListWidget->isFolder(selectedItems.first())) - myRSSListMenu.addAction(m_ui->actionNewFolder); - } - } - else { - myRSSListMenu.addAction(m_ui->actionDelete); - myRSSListMenu.addSeparator(); - } - myRSSListMenu.addAction(m_ui->actionNewSubscription); - if (m_feedListWidget->isFeed(selectedItems.first())) { - myRSSListMenu.addSeparator(); - myRSSListMenu.addAction(m_ui->actionCopyFeedURL); - } - } - else { - myRSSListMenu.addAction(m_ui->actionNewSubscription); - myRSSListMenu.addAction(m_ui->actionNewFolder); - myRSSListMenu.addSeparator(); - myRSSListMenu.addAction(m_ui->actionUpdateAllFeeds); - } - myRSSListMenu.exec(QCursor::pos()); -} - -void RSSWidget::displayItemsListMenu(const QPoint &) -{ - bool hasTorrent = false; - bool hasLink = false; - foreach (const QListWidgetItem *item, m_articleListWidget->selectedItems()) { - auto article = reinterpret_cast(item->data(Qt::UserRole).value()); - Q_ASSERT(article); - - if (!article->torrentUrl().isEmpty()) - hasTorrent = true; - if (!article->link().isEmpty()) - hasLink = true; - if (hasTorrent && hasLink) - break; - } - - QMenu myItemListMenu(this); - if (hasTorrent) - myItemListMenu.addAction(m_ui->actionDownloadTorrent); - if (hasLink) - myItemListMenu.addAction(m_ui->actionOpenNewsURL); - if (hasTorrent || hasLink) - myItemListMenu.exec(QCursor::pos()); -} - -void RSSWidget::askNewFolder() -{ - bool ok; - QString newName = AutoExpandableDialog::getText( - this, tr("Please choose a folder name"), tr("Folder name:"), QLineEdit::Normal - , tr("New folder"), &ok); - if (!ok) return; - - newName = newName.trimmed(); - if (newName.isEmpty()) return; - - // Determine destination folder for new item - QTreeWidgetItem *destItem = nullptr; - QList selectedItems = m_feedListWidget->selectedItems(); - if (!selectedItems.empty()) { - destItem = selectedItems.first(); - if (!m_feedListWidget->isFolder(destItem)) - destItem = destItem->parent(); - } - // Consider the case where the user clicked on Unread item - RSS::Folder *rssDestFolder = ((!destItem || (destItem == m_feedListWidget->stickyUnreadItem())) - ? RSS::Session::instance()->rootFolder() - : qobject_cast(m_feedListWidget->getRSSItem(destItem))); - - QString error; - const QString newFolderPath = RSS::Item::joinPath(rssDestFolder->path(), newName); - if (!RSS::Session::instance()->addFolder(newFolderPath, &error)) - QMessageBox::warning(this, "qBittorrent", error, QMessageBox::Ok); - - // Expand destination folder to display new feed - if (destItem && (destItem != m_feedListWidget->stickyUnreadItem())) - destItem->setExpanded(true); - // As new RSS items are added synchronously, we can do the following here. - m_feedListWidget->setCurrentItem(m_feedListWidget->mapRSSItem(RSS::Session::instance()->itemByPath(newFolderPath))); -} - -// add a stream by a button -void RSSWidget::on_newFeedButton_clicked() -{ - // Ask for feed URL - const QString clipText = qApp->clipboard()->text(); - const QString defaultURL = (Utils::Misc::isUrl(clipText) ? clipText : "http://"); - - bool ok; - QString newURL = AutoExpandableDialog::getText( - this, tr("Please type a RSS feed URL"), tr("Feed URL:"), QLineEdit::Normal, defaultURL, &ok); - if (!ok) return; - - newURL = newURL.trimmed(); - if (newURL.isEmpty()) return; - - // Determine destination folder for new item - QTreeWidgetItem *destItem = nullptr; - QList selectedItems = m_feedListWidget->selectedItems(); - if (!selectedItems.empty()) { - destItem = selectedItems.first(); - if (!m_feedListWidget->isFolder(destItem)) - destItem = destItem->parent(); - } - // Consider the case where the user clicked on Unread item - RSS::Folder *rssDestFolder = ((!destItem || (destItem == m_feedListWidget->stickyUnreadItem())) - ? RSS::Session::instance()->rootFolder() - : qobject_cast(m_feedListWidget->getRSSItem(destItem))); - - QString error; - // NOTE: We still add feed using legacy way (with URL as feed name) - const QString newFeedPath = RSS::Item::joinPath(rssDestFolder->path(), newURL); - if (!RSS::Session::instance()->addFeed(newURL, newFeedPath, &error)) - QMessageBox::warning(this, "qBittorrent", error, QMessageBox::Ok); - - // Expand destination folder to display new feed - if (destItem && (destItem != m_feedListWidget->stickyUnreadItem())) - destItem->setExpanded(true); - // As new RSS items are added synchronously, we can do the following here. - m_feedListWidget->setCurrentItem(m_feedListWidget->mapRSSItem(RSS::Session::instance()->itemByPath(newFeedPath))); -} - -void RSSWidget::deleteSelectedItems() -{ - QList selectedItems = m_feedListWidget->selectedItems(); - if (selectedItems.isEmpty()) - return; - if ((selectedItems.size() == 1) && (selectedItems.first() == m_feedListWidget->stickyUnreadItem())) - return; - - QMessageBox::StandardButton answer = QMessageBox::question( - this, tr("Deletion confirmation"), tr("Are you sure you want to delete the selected RSS feeds?") - , QMessageBox::Yes | QMessageBox::No, QMessageBox::No); - if (answer == QMessageBox::No) - return; - - foreach (QTreeWidgetItem *item, selectedItems) - if (item != m_feedListWidget->stickyUnreadItem()) - RSS::Session::instance()->removeItem(m_feedListWidget->itemPath(item)); -} - -void RSSWidget::loadFoldersOpenState() -{ - const QStringList openedFolders = Preferences::instance()->getRssOpenFolders(); - foreach (const QString &varPath, openedFolders) { - QTreeWidgetItem *parent = nullptr; - foreach (const QString &name, varPath.split("\\")) { - int nbChildren = (parent ? parent->childCount() : m_feedListWidget->topLevelItemCount()); - for (int i = 0; i < nbChildren; ++i) { - QTreeWidgetItem *child = (parent ? parent->child(i) : m_feedListWidget->topLevelItem(i)); - if (m_feedListWidget->getRSSItem(child)->name() == name) { - parent = child; - parent->setExpanded(true); - break; - } - } - } - } -} - -void RSSWidget::saveFoldersOpenState() -{ - QStringList openedFolders; - foreach (QTreeWidgetItem *item, m_feedListWidget->getAllOpenedFolders()) - openedFolders << m_feedListWidget->itemPath(item); - Preferences::instance()->setRssOpenFolders(openedFolders); -} - -void RSSWidget::refreshAllFeeds() -{ - RSS::Session::instance()->refresh(); -} - -void RSSWidget::downloadSelectedTorrents() -{ - foreach (QListWidgetItem *item, m_articleListWidget->selectedItems()) { - auto article = reinterpret_cast(item->data(Qt::UserRole).value()); - Q_ASSERT(article); - - // Mark as read - article->markAsRead(); - - if (!article->torrentUrl().isEmpty()) { - if (AddNewTorrentDialog::isEnabled()) - AddNewTorrentDialog::show(article->torrentUrl(), window()); - else - BitTorrent::Session::instance()->addTorrent(article->torrentUrl()); - } - } -} - -// open the url of the selected RSS articles in the Web browser -void RSSWidget::openSelectedArticlesUrls() -{ - foreach (QListWidgetItem *item, m_articleListWidget->selectedItems()) { - auto article = reinterpret_cast(item->data(Qt::UserRole).value()); - Q_ASSERT(article); - - // Mark as read - article->markAsRead(); - - if (!article->link().isEmpty()) - QDesktopServices::openUrl(QUrl(article->link())); - } -} - -void RSSWidget::renameSelectedRSSItem() -{ - QList selectedItems = m_feedListWidget->selectedItems(); - if (selectedItems.size() != 1) return; - - QTreeWidgetItem *item = selectedItems.first(); - if (item == m_feedListWidget->stickyUnreadItem()) - return; - - RSS::Item *rssItem = m_feedListWidget->getRSSItem(item); - const QString parentPath = RSS::Item::parentPath(rssItem->path()); - bool ok; - do { - QString newName = AutoExpandableDialog::getText( - this, tr("Please choose a new name for this RSS feed"), tr("New feed name:") - , QLineEdit::Normal, rssItem->name(), &ok); - // Check if name is already taken - if (!ok) return; - - QString error; - if (!RSS::Session::instance()->moveItem(rssItem, RSS::Item::joinPath(parentPath, newName), &error)) { - QMessageBox::warning(0, tr("Rename failed"), error); - ok = false; - } - } while (!ok); -} - -void RSSWidget::refreshSelectedItems() -{ - foreach (QTreeWidgetItem *item, m_feedListWidget->selectedItems()) { - if (item == m_feedListWidget->stickyUnreadItem()) { - refreshAllFeeds(); - return; - } - - m_feedListWidget->getRSSItem(item)->refresh(); - } -} - -void RSSWidget::copySelectedFeedsURL() -{ - QStringList URLs; - foreach (QTreeWidgetItem *item, m_feedListWidget->selectedItems()) { - if (auto feed = qobject_cast(m_feedListWidget->getRSSItem(item))) - URLs << feed->url(); - } - qApp->clipboard()->setText(URLs.join("\n")); -} - -void RSSWidget::handleCurrentFeedItemChanged(QTreeWidgetItem *currentItem) -{ - m_articleListWidget->setRSSItem(m_feedListWidget->getRSSItem(currentItem) - , (currentItem == m_feedListWidget->stickyUnreadItem())); -} - -void RSSWidget::on_markReadButton_clicked() -{ - foreach (QTreeWidgetItem *item, m_feedListWidget->selectedItems()) { - m_feedListWidget->getRSSItem(item)->markAsRead(); - if (item == m_feedListWidget->stickyUnreadItem()) - break; // all items was read - } -} - -// display a news -void RSSWidget::handleCurrentArticleItemChanged(QListWidgetItem *currentItem, QListWidgetItem *previousItem) -{ - m_ui->textBrowser->clear(); - - if (previousItem) { - auto article = m_articleListWidget->getRSSArticle(previousItem); - Q_ASSERT(article); - article->markAsRead(); - } - - if (!currentItem) return; - - auto article = m_articleListWidget->getRSSArticle(currentItem); - Q_ASSERT(article); - - QString html; - html += "
"; - html += "
" + article->title() + "
"; - if (article->date().isValid()) - html += "
" + tr("Date: ") + "" + article->date().toLocalTime().toString(Qt::SystemLocaleLongDate) + "
"; - if (!article->author().isEmpty()) - html += "
" + tr("Author: ") + "" + article->author() + "
"; - html += "
"; - html += "
"; - if (Qt::mightBeRichText(article->description())) { - html += article->description(); - } - else { - QString description = article->description(); - QRegExp rx; - // If description is plain text, replace BBCode tags with HTML and wrap everything in
 so it looks nice
-        rx.setMinimal(true);
-        rx.setCaseSensitivity(Qt::CaseInsensitive);
-
-        rx.setPattern("\\[img\\](.+)\\[/img\\]");
-        description = description.replace(rx, "");
-
-        rx.setPattern("\\[url=(\")?(.+)\\1\\]");
-        description = description.replace(rx, "");
-        description = description.replace("[/url]", "", Qt::CaseInsensitive);
-
-        rx.setPattern("\\[(/)?([bius])\\]");
-        description = description.replace(rx, "<\\1\\2>");
-
-        rx.setPattern("\\[color=(\")?(.+)\\1\\]");
-        description = description.replace(rx, "");
-        description = description.replace("[/color]", "", Qt::CaseInsensitive);
-
-        rx.setPattern("\\[size=(\")?(.+)\\d\\1\\]");
-        description = description.replace(rx, "");
-        description = description.replace("[/size]", "", Qt::CaseInsensitive);
-
-        html += "
" + description + "
"; - } - html += "
"; - m_ui->textBrowser->setHtml(html); -} - -void RSSWidget::saveSlidersPosition() -{ - // Remember sliders positions - Preferences *const pref = Preferences::instance(); - pref->setRssSideSplitterState(m_ui->splitterSide->saveState()); - pref->setRssMainSplitterState(m_ui->splitterMain->saveState()); -} - -void RSSWidget::restoreSlidersPosition() -{ - const Preferences *const pref = Preferences::instance(); - const QByteArray stateSide = pref->getRssSideSplitterState(); - if (!stateSide.isEmpty()) - m_ui->splitterSide->restoreState(stateSide); - const QByteArray stateMain = pref->getRssMainSplitterState(); - if (!stateMain.isEmpty()) - m_ui->splitterMain->restoreState(stateMain); -} - -void RSSWidget::updateRefreshInterval(uint val) -{ - RSS::Session::instance()->setRefreshInterval(val); -} - -void RSSWidget::on_rssDownloaderBtn_clicked() -{ - AutomatedRssDownloader(this).exec(); -} - -void RSSWidget::handleSessionProcessingStateChanged(bool enabled) -{ - m_ui->labelWarn->setVisible(!enabled); -} - -void RSSWidget::handleUnreadCountChanged() -{ - emit unreadCountUpdated(RSS::Session::instance()->rootFolder()->unreadCount()); -} diff --git a/src/gui/rss/rsswidget.h b/src/gui/rss/rsswidget.h deleted file mode 100644 index 6c88e1cc3..000000000 --- a/src/gui/rss/rsswidget.h +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2017 Vladimir Golovnev - * Copyright (C) 2006 Christophe Dumez - * Copyright (C) 2006 Arnaud Demaiziere - * - * 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. - */ - -#ifndef RSSWIDGET_H -#define RSSWIDGET_H - -#include -#include - -class ArticleListWidget; -class FeedListWidget; -class QListWidgetItem; -class QTreeWidgetItem; - -namespace Ui -{ - class RSSWidget; -} - -class RSSWidget: public QWidget -{ - Q_OBJECT - -public: - RSSWidget(QWidget *parent); - ~RSSWidget(); - -public slots: - void deleteSelectedItems(); - void updateRefreshInterval(uint val); - -signals: - void unreadCountUpdated(int count); - -private slots: - void on_newFeedButton_clicked(); - void refreshAllFeeds(); - void on_markReadButton_clicked(); - void displayRSSListMenu(const QPoint &); - void displayItemsListMenu(const QPoint &); - void renameSelectedRSSItem(); - void refreshSelectedItems(); - void copySelectedFeedsURL(); - void handleCurrentFeedItemChanged(QTreeWidgetItem *currentItem); - void handleCurrentArticleItemChanged(QListWidgetItem *currentItem, QListWidgetItem *previousItem); - void openSelectedArticlesUrls(); - void downloadSelectedTorrents(); - void saveSlidersPosition(); - void restoreSlidersPosition(); - void askNewFolder(); - void saveFoldersOpenState(); - void loadFoldersOpenState(); - void on_rssDownloaderBtn_clicked(); - void handleSessionProcessingStateChanged(bool enabled); - void handleUnreadCountChanged(); - -private: - Ui::RSSWidget *m_ui; - ArticleListWidget *m_articleListWidget; - FeedListWidget *m_feedListWidget; - QShortcut *m_editHotkey; - QShortcut *m_deleteHotkey; -}; - -#endif // RSSWIDGET_H diff --git a/src/gui/rss/rsswidget.ui b/src/gui/rss/rsswidget.ui deleted file mode 100644 index 74fb81130..000000000 --- a/src/gui/rss/rsswidget.ui +++ /dev/null @@ -1,210 +0,0 @@ - - - RSSWidget - - - - 0 - 0 - 811 - 447 - - - - false - - - Search - - - - - - - true - - - - color: red; - - - Fetching of RSS feeds is disabled now! You can enable it in application settings. - - - true - - - - - - - - - New subscription - - - - - - - Mark items read - - - - - - - Refresh RSS streams - - - Update all - - - - - - - Qt::Horizontal - - - - 0 - 0 - - - - - - - - RSS Downloader... - - - - - - - - - - 0 - 0 - - - - Qt::Horizontal - - - - - - - - 75 - true - - - - Torrents: (double-click to download) - - - - - - - - 0 - 0 - - - - Qt::Horizontal - - - - true - - - - - - - - - - - - Delete - - - Delete - - - - - Rename... - - - Rename - - - - - Update - - - Update - - - - - New subscription... - - - - - Update all feeds - - - Update all feeds - - - - - Mark items read - - - Mark items read - - - - - Download torrent - - - - - Open news URL - - - - - Copy feed URL - - - - - New folder... - - - - - - HtmlBrowser - QTextBrowser -
gui/rss/htmlbrowser.h
-
-
- - -
diff --git a/src/gui/scanfoldersdelegate.cpp b/src/gui/scanfoldersdelegate.cpp deleted file mode 100644 index 56fa993fc..000000000 --- a/src/gui/scanfoldersdelegate.cpp +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2015 sledgehammer999 - * - * 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 : hammered999@gmail.com - */ - -#include -#include -#include -#include -#include -#include - -#include "base/scanfoldersmodel.h" -#include "base/bittorrent/session.h" -#include "scanfoldersdelegate.h" - - -ScanFoldersDelegate::ScanFoldersDelegate(QObject *parent, QTreeView *foldersView) - : QItemDelegate(parent) - , m_folderView(foldersView) -{ -} - -void ScanFoldersDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const -{ - QComboBox *combobox = static_cast(editor); - // Set combobox index - if (index.data(Qt::UserRole).toInt() == ScanFoldersModel::CUSTOM_LOCATION) - combobox->setCurrentIndex(4); // '4' is the index of the item after the separator in the QComboBox menu - else - combobox->setCurrentIndex(index.data(Qt::UserRole).toInt()); -} - -QWidget *ScanFoldersDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &, const QModelIndex &index) const -{ - if (index.column() != ScanFoldersModel::DOWNLOAD) return 0; - - QComboBox* editor = new QComboBox(parent); - - editor->setFocusPolicy(Qt::StrongFocus); - editor->addItem(ScanFoldersModel::pathTypeDisplayName(ScanFoldersModel::DOWNLOAD_IN_WATCH_FOLDER)); - editor->addItem(ScanFoldersModel::pathTypeDisplayName(ScanFoldersModel::DEFAULT_LOCATION)); - editor->addItem(ScanFoldersModel::pathTypeDisplayName(ScanFoldersModel::CUSTOM_LOCATION)); - if (index.data(Qt::UserRole).toInt() == ScanFoldersModel::CUSTOM_LOCATION) { - editor->insertSeparator(3); - editor->addItem(index.data().toString()); - } - - connect(editor, SIGNAL(currentIndexChanged(int)), this, SLOT(comboboxIndexChanged(int))); - return editor; -} - -void ScanFoldersDelegate::comboboxIndexChanged(int index) -{ - if (index == ScanFoldersModel::CUSTOM_LOCATION) { - QWidget *w = static_cast(sender()); - if (w && w->parentWidget()) - w->parentWidget()->setFocus(); - } -} - -void ScanFoldersDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const -{ - QComboBox *combobox = static_cast(editor); - int value = combobox->currentIndex(); - - switch (value) { - case ScanFoldersModel::DOWNLOAD_IN_WATCH_FOLDER: - case ScanFoldersModel::DEFAULT_LOCATION: - model->setData(index, value, Qt::UserRole); - break; - - case ScanFoldersModel::CUSTOM_LOCATION: - model->setData( - index, - QFileDialog::getExistingDirectory( - 0, tr("Select save location"), - index.data(Qt::UserRole).toInt() == ScanFoldersModel::CUSTOM_LOCATION ? - index.data().toString() : - BitTorrent::Session::instance()->defaultSavePath()), - Qt::DisplayRole); - break; - - default: - break; - } -} - -void ScanFoldersDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &) const -{ - qDebug("UpdateEditor Geometry called"); - editor->setGeometry(option.rect); -} diff --git a/src/gui/scanfoldersdelegate.h b/src/gui/scanfoldersdelegate.h deleted file mode 100644 index c9b1af98b..000000000 --- a/src/gui/scanfoldersdelegate.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2015 sledgehammer999 - * - * 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 : hammered999@gmail.com - */ - -#ifndef SCANFOLDERSDELEGATE_H -#define SCANFOLDERSDELEGATE_H - -#include - -class QPainter; -class QModelIndex; -class QStyleOptionViewItem; -class QAbstractItemModel; -class PropertiesWidget; -class QTreeView; - -class ScanFoldersDelegate : public QItemDelegate -{ - Q_OBJECT - -public: - ScanFoldersDelegate(QObject *parent, QTreeView *foldersView); - -private slots: - void comboboxIndexChanged(int index); - -private: - void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const; - void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &) const; - void setEditorData(QWidget *editor, const QModelIndex &index) const; - QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &, const QModelIndex &index) const; - - QTreeView *m_folderView; -}; - -#endif // SCANFOLDERSDELEGATE_H - diff --git a/src/gui/search/CMakeLists.txt b/src/gui/search/CMakeLists.txt deleted file mode 100644 index ca27861a7..000000000 --- a/src/gui/search/CMakeLists.txt +++ /dev/null @@ -1,37 +0,0 @@ -include_directories( -${CMAKE_CURRENT_BINARY_DIR} -${CMAKE_CURRENT_SOURCE_DIR}/.. -${CMAKE_CURRENT_SOURCE_DIR}/../lineedit/src -) - -set(QBT_SEARCHENGINE_FORMS -pluginselectdlg.ui -pluginsourcedlg.ui -searchwidget.ui -) - -set(QBT_SEARCHENGINE_HEADERS -pluginselectdlg.h -pluginsourcedlg.h -searchlistdelegate.h -searchsortmodel.h -searchtab.h -searchwidget.h -) - -set(QBT_SEARCHENGINE_SOURCES -pluginselectdlg.cpp -pluginsourcedlg.cpp -searchlistdelegate.cpp -searchsortmodel.cpp -searchtab.cpp -searchwidget.cpp -) - -set(QBT_SEARCHENGINE_RESOURCES -# search.qrc -) - -add_library(qbt_searchengine STATIC ${QBT_SEARCHENGINE_HEADERS} ${QBT_SEARCHENGINE_SOURCES} ${QBT_SEARCHENGINE_RESOURCES} ${QBT_SEARCHENGINE_FORMS}) -target_link_libraries(qbt_searchengine qbt_base) - diff --git a/src/gui/search/pluginselectdlg.cpp b/src/gui/search/pluginselectdlg.cpp deleted file mode 100644 index a3f74e4e7..000000000 --- a/src/gui/search/pluginselectdlg.cpp +++ /dev/null @@ -1,470 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2015 Vladimir Golovnev - * Copyright (C) 2006 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 "pluginselectdlg.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "base/utils/fs.h" -#include "base/utils/misc.h" -#include "base/net/downloadmanager.h" -#include "base/net/downloadhandler.h" -#include "searchwidget.h" -#include "pluginsourcedlg.h" -#include "guiiconprovider.h" -#include "autoexpandabledialog.h" -#include "ui_pluginselectdlg.h" - -enum PluginColumns -{ - PLUGIN_NAME, - PLUGIN_VERSION, - PLUGIN_URL, - PLUGIN_STATE, - PLUGIN_ID -}; - -PluginSelectDlg::PluginSelectDlg(SearchEngine *pluginManager, QWidget *parent) - : QDialog(parent) - , m_ui(new Ui::PluginSelectDlg()) - , m_pluginManager(pluginManager) - , m_asyncOps(0) - , m_pendingUpdates(0) -{ - m_ui->setupUi(this); - setAttribute(Qt::WA_DeleteOnClose); - - // This hack fixes reordering of first column with Qt5. - // https://github.com/qtproject/qtbase/commit/e0fc088c0c8bc61dbcaf5928b24986cd61a22777 - QTableView unused; - unused.setVerticalHeader(m_ui->pluginsTree->header()); - m_ui->pluginsTree->header()->setParent(m_ui->pluginsTree); - unused.setVerticalHeader(new QHeaderView(Qt::Horizontal)); - - m_ui->pluginsTree->setRootIsDecorated(false); - m_ui->pluginsTree->header()->resizeSection(0, 160); - m_ui->pluginsTree->header()->resizeSection(1, 80); - m_ui->pluginsTree->header()->resizeSection(2, 200); - m_ui->pluginsTree->hideColumn(PLUGIN_ID); - - m_ui->actionUninstall->setIcon(GuiIconProvider::instance()->getIcon("list-remove")); - - connect(m_ui->actionEnable, &QAction::toggled, this, &PluginSelectDlg::enableSelection); - connect(m_ui->pluginsTree, &QTreeWidget::customContextMenuRequested, this, &PluginSelectDlg::displayContextMenu); - connect(m_ui->pluginsTree, &QTreeWidget::itemDoubleClicked, this, &PluginSelectDlg::togglePluginState); - - loadSupportedSearchPlugins(); - - connect(m_pluginManager, &SearchEngine::pluginInstalled, this, &PluginSelectDlg::pluginInstalled); - connect(m_pluginManager, &SearchEngine::pluginInstallationFailed, this, &PluginSelectDlg::pluginInstallationFailed); - connect(m_pluginManager, &SearchEngine::pluginUpdated, this, &PluginSelectDlg::pluginUpdated); - connect(m_pluginManager, &SearchEngine::pluginUpdateFailed, this, &PluginSelectDlg::pluginUpdateFailed); - connect(m_pluginManager, &SearchEngine::checkForUpdatesFinished, this, &PluginSelectDlg::checkForUpdatesFinished); - connect(m_pluginManager, &SearchEngine::checkForUpdatesFailed, this, &PluginSelectDlg::checkForUpdatesFailed); - - show(); -} - -PluginSelectDlg::~PluginSelectDlg() -{ - delete m_ui; -} - -void PluginSelectDlg::dropEvent(QDropEvent *event) -{ - event->acceptProposedAction(); - - QStringList files; - if (event->mimeData()->hasUrls()) { - foreach (const QUrl &url, event->mimeData()->urls()) { - if (!url.isEmpty()) { - if (url.scheme().compare("file", Qt::CaseInsensitive) == 0) - files << url.toLocalFile(); - else - files << url.toString(); - } - } - } - else { - files = event->mimeData()->text().split(QLatin1String("\n")); - } - - if (files.isEmpty()) return; - - foreach (QString file, files) { - qDebug("dropped %s", qPrintable(file)); - startAsyncOp(); - m_pluginManager->installPlugin(file); - } -} - -// Decode if we accept drag 'n drop or not -void PluginSelectDlg::dragEnterEvent(QDragEnterEvent *event) -{ - QString mime; - foreach (mime, event->mimeData()->formats()) { - qDebug("mimeData: %s", qPrintable(mime)); - } - - if (event->mimeData()->hasFormat(QLatin1String("text/plain")) || event->mimeData()->hasFormat(QLatin1String("text/uri-list"))) { - event->acceptProposedAction(); - } -} - -void PluginSelectDlg::on_updateButton_clicked() -{ - startAsyncOp(); - m_pluginManager->checkForUpdates(); -} - -void PluginSelectDlg::togglePluginState(QTreeWidgetItem *item, int) -{ - PluginInfo *plugin = m_pluginManager->pluginInfo(item->text(PLUGIN_ID)); - m_pluginManager->enablePlugin(plugin->name, !plugin->enabled); - if (plugin->enabled) { - item->setText(PLUGIN_STATE, tr("Yes")); - setRowColor(m_ui->pluginsTree->indexOfTopLevelItem(item), "green"); - } - else { - item->setText(PLUGIN_STATE, tr("No")); - setRowColor(m_ui->pluginsTree->indexOfTopLevelItem(item), "red"); - } -} - -void PluginSelectDlg::displayContextMenu(const QPoint&) -{ - QMenu myContextMenu(this); - // Enable/disable pause/start action given the DL state - QList items = m_ui->pluginsTree->selectedItems(); - if (items.isEmpty()) return; - - QString first_id = items.first()->text(PLUGIN_ID); - m_ui->actionEnable->setChecked(m_pluginManager->pluginInfo(first_id)->enabled); - myContextMenu.addAction(m_ui->actionEnable); - myContextMenu.addSeparator(); - myContextMenu.addAction(m_ui->actionUninstall); - myContextMenu.exec(QCursor::pos()); -} - -void PluginSelectDlg::on_closeButton_clicked() -{ - close(); -} - -void PluginSelectDlg::on_actionUninstall_triggered() -{ - bool error = false; - foreach (QTreeWidgetItem *item, m_ui->pluginsTree->selectedItems()) { - int index = m_ui->pluginsTree->indexOfTopLevelItem(item); - Q_ASSERT(index != -1); - QString id = item->text(PLUGIN_ID); - if (m_pluginManager->uninstallPlugin(id)) { - delete item; - } - else { - error = true; - // Disable it instead - m_pluginManager->enablePlugin(id, false); - item->setText(PLUGIN_STATE, tr("No")); - setRowColor(index, "red"); - } - } - - if (error) - QMessageBox::warning(this, tr("Uninstall warning"), tr("Some plugins could not be uninstalled because they are included in qBittorrent. Only the ones you added yourself can be uninstalled.\nThose plugins were disabled.")); - else - QMessageBox::information(this, tr("Uninstall success"), tr("All selected plugins were uninstalled successfully")); -} - -void PluginSelectDlg::enableSelection(bool enable) -{ - foreach (QTreeWidgetItem *item, m_ui->pluginsTree->selectedItems()) { - int index = m_ui->pluginsTree->indexOfTopLevelItem(item); - Q_ASSERT(index != -1); - QString id = item->text(PLUGIN_ID); - m_pluginManager->enablePlugin(id, enable); - if (enable) { - item->setText(PLUGIN_STATE, tr("Yes")); - setRowColor(index, "green"); - } - else { - item->setText(PLUGIN_STATE, tr("No")); - setRowColor(index, "red"); - } - } -} - -// Set the color of a row in data model -void PluginSelectDlg::setRowColor(int row, QString color) -{ - QTreeWidgetItem *item = m_ui->pluginsTree->topLevelItem(row); - for (int i = 0; i < m_ui->pluginsTree->columnCount(); ++i) { - item->setData(i, Qt::ForegroundRole, QVariant(QColor(color))); - } -} - -QList PluginSelectDlg::findItemsWithUrl(QString url) -{ - QList res; - - for (int i = 0; i < m_ui->pluginsTree->topLevelItemCount(); ++i) { - QTreeWidgetItem *item = m_ui->pluginsTree->topLevelItem(i); - if (url.startsWith(item->text(PLUGIN_URL), Qt::CaseInsensitive)) - res << item; - } - - return res; -} - -QTreeWidgetItem* PluginSelectDlg::findItemWithID(QString id) -{ - for (int i = 0; i < m_ui->pluginsTree->topLevelItemCount(); ++i) { - QTreeWidgetItem *item = m_ui->pluginsTree->topLevelItem(i); - if (id == item->text(PLUGIN_ID)) - return item; - } - - return 0; -} - -void PluginSelectDlg::loadSupportedSearchPlugins() -{ - // Some clean up first - m_ui->pluginsTree->clear(); - foreach (QString name, m_pluginManager->allPlugins()) - addNewPlugin(name); -} - -void PluginSelectDlg::addNewPlugin(QString pluginName) -{ - QTreeWidgetItem *item = new QTreeWidgetItem(m_ui->pluginsTree); - PluginInfo *plugin = m_pluginManager->pluginInfo(pluginName); - item->setText(PLUGIN_NAME, plugin->fullName); - item->setText(PLUGIN_URL, plugin->url); - item->setText(PLUGIN_ID, plugin->name); - if (plugin->enabled) { - item->setText(PLUGIN_STATE, tr("Yes")); - setRowColor(m_ui->pluginsTree->indexOfTopLevelItem(item), "green"); - } - else { - item->setText(PLUGIN_STATE, tr("No")); - setRowColor(m_ui->pluginsTree->indexOfTopLevelItem(item), "red"); - } - // Handle icon - if (QFile::exists(plugin->iconPath)) { - // Good, we already have the icon - item->setData(PLUGIN_NAME, Qt::DecorationRole, QVariant(QIcon(plugin->iconPath))); - } - else { - // Icon is missing, we must download it - using namespace Net; - DownloadHandler *handler = DownloadManager::instance()->downloadUrl(plugin->url + "/favicon.ico", true); - connect(handler, static_cast(&DownloadHandler::downloadFinished) - , this, &PluginSelectDlg::iconDownloaded); - connect(handler, &DownloadHandler::downloadFailed, this, &PluginSelectDlg::iconDownloadFailed); - } - item->setText(PLUGIN_VERSION, plugin->version); -} - -void PluginSelectDlg::startAsyncOp() -{ - ++m_asyncOps; - if (m_asyncOps == 1) - setCursor(QCursor(Qt::WaitCursor)); -} - -void PluginSelectDlg::finishAsyncOp() -{ - --m_asyncOps; - if (m_asyncOps == 0) - setCursor(QCursor(Qt::ArrowCursor)); -} - -void PluginSelectDlg::finishPluginUpdate() -{ - --m_pendingUpdates; - if (m_pendingUpdates == 0 && !m_updatedPlugins.isEmpty()) { - m_updatedPlugins.sort(Qt::CaseInsensitive); - QMessageBox::information(this, tr("Search plugin update"), tr("Plugins installed or updated: %1").arg(m_updatedPlugins.join(", "))); - m_updatedPlugins.clear(); - } -} - -void PluginSelectDlg::on_installButton_clicked() -{ - PluginSourceDlg *dlg = new PluginSourceDlg(this); - connect(dlg, &PluginSourceDlg::askForLocalFile, this, &PluginSelectDlg::askForLocalPlugin); - connect(dlg, &PluginSourceDlg::askForUrl, this, &PluginSelectDlg::askForPluginUrl); -} - -void PluginSelectDlg::askForPluginUrl() -{ - bool ok = false; - QString clipTxt = qApp->clipboard()->text(); - QString defaultUrl = "http://"; - if (Utils::Misc::isUrl(clipTxt) && clipTxt.endsWith(".py")) - defaultUrl = clipTxt; - QString url = AutoExpandableDialog::getText( - this, tr("New search engine plugin URL"), - tr("URL:"), QLineEdit::Normal, defaultUrl, &ok - ); - - while (ok && !url.isEmpty() && !url.endsWith(".py")) { - QMessageBox::warning(this, tr("Invalid link"), tr("The link doesn't seem to point to a search engine plugin.")); - url = AutoExpandableDialog::getText( - this, tr("New search engine plugin URL"), - tr("URL:"), QLineEdit::Normal, url, &ok - ); - } - - if (ok && !url.isEmpty()) { - startAsyncOp(); - m_pluginManager->installPlugin(url); - } -} - -void PluginSelectDlg::askForLocalPlugin() -{ - QStringList pathsList = QFileDialog::getOpenFileNames( - 0, tr("Select search plugins"), QDir::homePath(), - tr("qBittorrent search plugin") + QLatin1String(" (*.py)") - ); - foreach (QString path, pathsList) { - startAsyncOp(); - m_pluginManager->installPlugin(path); - } -} - -void PluginSelectDlg::iconDownloaded(const QString &url, QString filePath) -{ - filePath = Utils::Fs::fromNativePath(filePath); - - // Icon downloaded - QIcon icon(filePath); - // Detect a non-decodable icon - QList sizes = icon.availableSizes(); - bool invalid = (sizes.isEmpty() || icon.pixmap(sizes.first()).isNull()); - if (!invalid) { - foreach (QTreeWidgetItem *item, findItemsWithUrl(url)) { - QString id = item->text(PLUGIN_ID); - PluginInfo *plugin = m_pluginManager->pluginInfo(id); - if (!plugin) continue; - - QString iconPath = QString("%1/%2.%3") - .arg(SearchEngine::pluginsLocation()) - .arg(id) - .arg(url.endsWith(".ico", Qt::CaseInsensitive) ? "ico" : "png"); - if (QFile::copy(filePath, iconPath)) { - // This 2nd check is necessary. Some favicons (eg from piratebay) - // decode fine without an ext, but fail to do so when appending the ext - // from the url. Probably a Qt bug. - QIcon iconWithExt(iconPath); - QList sizesExt = iconWithExt.availableSizes(); - bool invalidExt = (sizesExt.isEmpty() || iconWithExt.pixmap(sizesExt.first()).isNull()); - if (invalidExt) { - Utils::Fs::forceRemove(iconPath); - continue; - } - - item->setData(PLUGIN_NAME, Qt::DecorationRole, iconWithExt); - m_pluginManager->updateIconPath(plugin); - } - } - } - // Delete tmp file - Utils::Fs::forceRemove(filePath); -} - -void PluginSelectDlg::iconDownloadFailed(const QString &url, const QString &reason) -{ - qDebug("Could not download favicon: %s, reason: %s", qPrintable(url), qPrintable(reason)); -} - -void PluginSelectDlg::checkForUpdatesFinished(const QHash &updateInfo) -{ - finishAsyncOp(); - if (updateInfo.isEmpty()) { - QMessageBox::information(this, tr("Search plugin update"), tr("All your plugins are already up to date.")); - return; - } - - foreach (const QString &pluginName, updateInfo.keys()) { - startAsyncOp(); - m_pendingUpdates++; - m_pluginManager->updatePlugin(pluginName); - } -} - -void PluginSelectDlg::checkForUpdatesFailed(const QString &reason) -{ - finishAsyncOp(); - QMessageBox::warning(this, tr("Search plugin update"), tr("Sorry, couldn't check for plugin updates. %1").arg(reason)); -} - -void PluginSelectDlg::pluginInstalled(const QString &name) -{ - addNewPlugin(name); - finishAsyncOp(); - m_updatedPlugins.append(name); - finishPluginUpdate(); -} - -void PluginSelectDlg::pluginInstallationFailed(const QString &name, const QString &reason) -{ - finishAsyncOp(); - QMessageBox::information(this, tr("Search plugin install"), tr("Couldn't install \"%1\" search engine plugin. %2").arg(name).arg(reason)); - finishPluginUpdate(); -} - -void PluginSelectDlg::pluginUpdated(const QString &name) -{ - finishAsyncOp(); - PluginVersion version = m_pluginManager->pluginInfo(name)->version; - QTreeWidgetItem *item = findItemWithID(name); - item->setText(PLUGIN_VERSION, version); - m_updatedPlugins.append(name); - finishPluginUpdate(); -} - -void PluginSelectDlg::pluginUpdateFailed(const QString &name, const QString &reason) -{ - finishAsyncOp(); - QMessageBox::information(this, tr("Search plugin update"), tr("Couldn't update \"%1\" search engine plugin. %2").arg(name).arg(reason)); - finishPluginUpdate(); -} diff --git a/src/gui/search/pluginselectdlg.h b/src/gui/search/pluginselectdlg.h deleted file mode 100644 index c07c3dd4e..000000000 --- a/src/gui/search/pluginselectdlg.h +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2015 Vladimir Golovnev - * Copyright (C) 2006 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 PLUGINSELECTDLG_H -#define PLUGINSELECTDLG_H - -#include - -#include "base/searchengine.h" - -class QDropEvent; -class QStringList; -class QTreeWidgetItem; - -namespace Ui -{ - class PluginSelectDlg; -} - -class PluginSelectDlg: public QDialog -{ - Q_OBJECT - -public: - explicit PluginSelectDlg(SearchEngine *pluginManager, QWidget *parent = 0); - ~PluginSelectDlg(); - - QList findItemsWithUrl(QString url); - QTreeWidgetItem* findItemWithID(QString id); - -protected: - void dropEvent(QDropEvent *event); - void dragEnterEvent(QDragEnterEvent *event); - -private slots: - void on_actionUninstall_triggered(); - void on_updateButton_clicked(); - void on_installButton_clicked(); - void on_closeButton_clicked(); - void togglePluginState(QTreeWidgetItem*, int); - void setRowColor(int row, QString color); - void displayContextMenu(const QPoint& pos); - void enableSelection(bool enable); - void askForLocalPlugin(); - void askForPluginUrl(); - void iconDownloaded(const QString &url, QString filePath); - void iconDownloadFailed(const QString &url, const QString &reason); - - void checkForUpdatesFinished(const QHash &updateInfo); - void checkForUpdatesFailed(const QString &reason); - void pluginInstalled(const QString &name); - void pluginInstallationFailed(const QString &name, const QString &reason); - void pluginUpdated(const QString &name); - void pluginUpdateFailed(const QString &name, const QString &reason); - -private: - void loadSupportedSearchPlugins(); - void addNewPlugin(QString pluginName); - void startAsyncOp(); - void finishAsyncOp(); - void finishPluginUpdate(); - - Ui::PluginSelectDlg *m_ui; - SearchEngine *m_pluginManager; - QStringList m_updatedPlugins; - int m_asyncOps; - int m_pendingUpdates; -}; - -#endif // PLUGINSELECTDLG_H diff --git a/src/gui/search/pluginselectdlg.ui b/src/gui/search/pluginselectdlg.ui deleted file mode 100644 index 696a90173..000000000 --- a/src/gui/search/pluginselectdlg.ui +++ /dev/null @@ -1,142 +0,0 @@ - - - PluginSelectDlg - - - - 0 - 0 - 600 - 345 - - - - true - - - Search plugins - - - - - - - 75 - true - true - - - - Installed search plugins: - - - - - - - Qt::CustomContextMenu - - - QAbstractItemView::ExtendedSelection - - - true - - - false - - - - Name - - - - - Version - - - - - Url - - - - - Enabled - - - - - - - - - - - - - Warning: Be sure to comply with your country's copyright laws when downloading torrents from any of these search engines. - - - true - - - - - - - - true - - - - You can get new search engine plugins here: <a href="http://plugins.qbittorrent.org">http://plugins.qbittorrent.org</a> - - - true - - - - - - - - - Install a new one - - - - - - - Check for updates - - - - - - - Close - - - - - - - - - true - - - Enabled - - - - - Uninstall - - - - - - diff --git a/src/gui/search/pluginsourcedlg.cpp b/src/gui/search/pluginsourcedlg.cpp deleted file mode 100644 index 1d5844bd3..000000000 --- a/src/gui/search/pluginsourcedlg.cpp +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2006 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 "pluginsourcedlg.h" - -#include "ui_pluginsourcedlg.h" - -PluginSourceDlg::PluginSourceDlg(QWidget *parent) - : QDialog(parent) - , m_ui(new Ui::PluginSourceDlg()) -{ - m_ui->setupUi(this); - setAttribute(Qt::WA_DeleteOnClose); - show(); -} - -PluginSourceDlg::~PluginSourceDlg() -{ - delete m_ui; -} - -void PluginSourceDlg::on_localButton_clicked() -{ - emit askForLocalFile(); - close(); -} - -void PluginSourceDlg::on_urlButton_clicked() -{ - emit askForUrl(); - close(); -} diff --git a/src/gui/search/pluginsourcedlg.h b/src/gui/search/pluginsourcedlg.h deleted file mode 100644 index f600e90f1..000000000 --- a/src/gui/search/pluginsourcedlg.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2006 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 PLUGINSOURCEDLG_H -#define PLUGINSOURCEDLG_H - -#include - -namespace Ui -{ - class PluginSourceDlg; -} - -class PluginSourceDlg: public QDialog -{ - Q_OBJECT - -public: - explicit PluginSourceDlg(QWidget *parent = 0); - ~PluginSourceDlg(); - -signals: - void askForUrl(); - void askForLocalFile(); - -private slots: - void on_localButton_clicked(); - void on_urlButton_clicked(); - -private: - Ui::PluginSourceDlg *m_ui; -}; - -#endif // PLUGINSOURCEDLG_H diff --git a/src/gui/search/pluginsourcedlg.ui b/src/gui/search/pluginsourcedlg.ui deleted file mode 100644 index 9b0411e1d..000000000 --- a/src/gui/search/pluginsourcedlg.ui +++ /dev/null @@ -1,53 +0,0 @@ - - - PluginSourceDlg - - - - 0 - 0 - 207 - 76 - - - - Plugin source - - - - - - - 75 - true - true - - - - Search plugin source: - - - - - - - - - Local file - - - - - - - Web link - - - - - - - - - - diff --git a/src/gui/search/searchlistdelegate.cpp b/src/gui/search/searchlistdelegate.cpp deleted file mode 100644 index 04d030d3e..000000000 --- a/src/gui/search/searchlistdelegate.cpp +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2006 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 -#include -#include -#include - -#include "base/utils/misc.h" -#include "searchsortmodel.h" -#include "searchlistdelegate.h" - -SearchListDelegate::SearchListDelegate(QObject *parent) - : QItemDelegate(parent) -{ -} - -void SearchListDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const -{ - painter->save(); - - QStyleOptionViewItem opt = QItemDelegate::setOptions(index, option); - QItemDelegate::drawBackground(painter, opt, index); - - switch (index.column()) { - case SearchSortModel::SIZE: - opt.displayAlignment = Qt::AlignRight | Qt::AlignVCenter; - QItemDelegate::drawDisplay(painter, opt, option.rect, Utils::Misc::friendlyUnit(index.data().toLongLong())); - break; - case SearchSortModel::SEEDS: - case SearchSortModel::LEECHES: - opt.displayAlignment = Qt::AlignRight | Qt::AlignVCenter; - QItemDelegate::drawDisplay(painter, opt, option.rect, (index.data().toLongLong() >= 0) ? index.data().toString() : tr("Unknown")); - break; - default: - QItemDelegate::paint(painter, option, index); - } - - painter->restore(); -} - -QWidget *SearchListDelegate::createEditor(QWidget *, const QStyleOptionViewItem &, const QModelIndex &) const -{ - // No editor here - return nullptr; -} diff --git a/src/gui/search/searchlistdelegate.h b/src/gui/search/searchlistdelegate.h deleted file mode 100644 index 1af6e19ce..000000000 --- a/src/gui/search/searchlistdelegate.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2006 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 SEARCHLISTDELEGATE_H -#define SEARCHLISTDELEGATE_H - -#include - -class SearchListDelegate: public QItemDelegate -{ -public: - explicit SearchListDelegate(QObject *parent); - - void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override; - QWidget *createEditor(QWidget *, const QStyleOptionViewItem &, const QModelIndex &) const override; -}; - -#endif diff --git a/src/gui/search/searchsortmodel.cpp b/src/gui/search/searchsortmodel.cpp deleted file mode 100644 index f5d24ff45..000000000 --- a/src/gui/search/searchsortmodel.cpp +++ /dev/null @@ -1,161 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2013 sledgehammer999 - * - * 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. - */ - -#include "searchsortmodel.h" - -SearchSortModel::SearchSortModel(QObject *parent) - : base(parent) - , m_isNameFilterEnabled(false) - , m_minSeeds(0) - , m_maxSeeds(-1) - , m_minLeeches(0) - , m_maxLeeches(-1) - , m_minSize(0) - , m_maxSize(-1) -{ -} - -void SearchSortModel::enableNameFilter(bool enabled) -{ - m_isNameFilterEnabled = enabled; -} - -void SearchSortModel::setNameFilter(const QString &searchTerm) -{ - m_searchTerm = searchTerm; - if (searchTerm.length() > 2 - && searchTerm.startsWith(QLatin1Char('"')) && searchTerm.endsWith(QLatin1Char('"'))) { - m_searchTermWords = QStringList(m_searchTerm.mid(1, m_searchTerm.length() - 2)); - } - else { - m_searchTermWords = searchTerm.split(QLatin1Char(' '), QString::SkipEmptyParts); - } -} - -void SearchSortModel::setSizeFilter(qint64 minSize, qint64 maxSize) -{ - m_minSize = std::max(static_cast(0), minSize); - m_maxSize = std::max(static_cast(-1), maxSize); -} - -void SearchSortModel::setSeedsFilter(int minSeeds, int maxSeeds) -{ - m_minSeeds = std::max(0, minSeeds); - m_maxSeeds = std::max(-1, maxSeeds); -} - -void SearchSortModel::setLeechesFilter(int minLeeches, int maxLeeches) -{ - m_minLeeches = std::max(0, minLeeches); - m_maxLeeches = std::max(-1, maxLeeches); -} - -bool SearchSortModel::isNameFilterEnabled() const -{ - return m_isNameFilterEnabled; -} - -QString SearchSortModel::searchTerm() const -{ - return m_searchTerm; -} - -int SearchSortModel::minSeeds() const -{ - return m_minSeeds; -} - -int SearchSortModel::maxSeeds() const -{ - return m_maxSeeds; -} - -qint64 SearchSortModel::minSize() const -{ - return m_minSize; -} - -qint64 SearchSortModel::maxSize() const -{ - return m_maxSize; -} - -bool SearchSortModel::lessThan(const QModelIndex &left, const QModelIndex &right) const -{ - switch (sortColumn()) { - case NAME: - case ENGINE_URL: { - QString vL = left.data().toString(); - QString vR = right.data().toString(); - return Utils::String::naturalCompareCaseInsensitive(vL, vR); - } - - default: - return base::lessThan(left, right); - }; -} - -bool SearchSortModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const -{ - const QAbstractItemModel* const sourceModel = this->sourceModel(); - if (m_isNameFilterEnabled && !m_searchTerm.isEmpty()) { - QString name = sourceModel->data(sourceModel->index(sourceRow, NAME, sourceParent)).toString(); - for (const QString& word: m_searchTermWords) { - int i = name.indexOf(word, 0, Qt::CaseInsensitive); - if (i == -1) { - return false; - } - } - } - - if (m_minSize > 0 || m_maxSize >= 0) { - qlonglong size = sourceModel->data(sourceModel->index(sourceRow, SIZE, sourceParent)).toLongLong(); - if ((m_minSize > 0 && size < m_minSize) - || (m_maxSize > 0 && size > m_maxSize)) { - return false; - } - } - - if (m_minSeeds > 0 || m_maxSeeds >= 0) { - int seeds = sourceModel->data(sourceModel->index(sourceRow, SEEDS, sourceParent)).toInt(); - if ((m_minSeeds > 0 && seeds < m_minSeeds) - || (m_maxSeeds > 0 && seeds > m_maxSeeds)) { - return false; - } - } - - if (m_minLeeches > 0 || m_maxLeeches >= 0) { - int leeches = sourceModel->data(sourceModel->index(sourceRow, LEECHES, sourceParent)).toInt(); - if ((m_minLeeches > 0 && leeches < m_minLeeches) - || (m_maxLeeches > 0 && leeches > m_maxLeeches)) { - return false; - } - } - - return base::filterAcceptsRow(sourceRow, sourceParent); -} diff --git a/src/gui/search/searchsortmodel.h b/src/gui/search/searchsortmodel.h deleted file mode 100644 index e3da49de8..000000000 --- a/src/gui/search/searchsortmodel.h +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2013 sledgehammer999 - * - * 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. - */ - -#ifndef SEARCHSORTMODEL_H -#define SEARCHSORTMODEL_H - -#include -#include -#include "base/utils/string.h" - -class SearchSortModel: public QSortFilterProxyModel -{ - using base = QSortFilterProxyModel; - -public: - enum SearchColumn - { - NAME, - SIZE, - SEEDS, - LEECHES, - ENGINE_URL, - DL_LINK, - DESC_LINK, - NB_SEARCH_COLUMNS - }; - - explicit SearchSortModel(QObject *parent = 0); - - void enableNameFilter(bool enabled); - void setNameFilter(const QString& searchTerm = QString()); - - //! \brief Sets parameters for filtering by size - //! \param minSize minimal size in bytes - //! \param maxSize maximal size in bytes, negative value to disable filtering - void setSizeFilter(qint64 minSize, qint64 maxSize); - - //! \brief Sets parameters for filtering by seeds number - //! \param minSeeds minimal number of seeders - //! \param maxSeeds maximal number of seeders, negative value to disable filtering - void setSeedsFilter(int minSeeds, int maxSeeds); - - //! \brief Sets parameters for filtering by leeches number - //! \param minLeeches minimal number of leechers - //! \param maxLeeches maximal number of leechers, negative value to disable filtering - void setLeechesFilter(int minLeeches, int maxLeeches); - - bool isNameFilterEnabled() const; - - QString searchTerm() const; - - int minSeeds() const; - int maxSeeds() const; - - qint64 minSize() const; - qint64 maxSize() const; - -protected: - bool lessThan(const QModelIndex &left, const QModelIndex &right) const override; - bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const override; - -private: - bool m_isNameFilterEnabled; - QString m_searchTerm; - QStringList m_searchTermWords; - int m_minSeeds, m_maxSeeds; - int m_minLeeches, m_maxLeeches; - qint64 m_minSize, m_maxSize; -}; - -#endif // SEARCHSORTMODEL_H diff --git a/src/gui/search/searchtab.cpp b/src/gui/search/searchtab.cpp deleted file mode 100644 index f4dfebc6a..000000000 --- a/src/gui/search/searchtab.cpp +++ /dev/null @@ -1,348 +0,0 @@ -/* - * Bittorrent Client using Qt4 and libtorrent. - * Copyright (C) 2006 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "base/utils/misc.h" -#include "base/preferences.h" -#include "base/settingvalue.h" -#include "guiiconprovider.h" -#include "searchsortmodel.h" -#include "searchlistdelegate.h" -#include "searchwidget.h" -#include "searchtab.h" -#include "ui_searchtab.h" - -SearchTab::SearchTab(SearchWidget *parent) - : QWidget(parent) - , m_ui(new Ui::SearchTab()) - , m_parent(parent) -{ - m_ui->setupUi(this); - - // This hack fixes reordering of first column with Qt5. - // https://github.com/qtproject/qtbase/commit/e0fc088c0c8bc61dbcaf5928b24986cd61a22777 - QTableView unused; - unused.setVerticalHeader(m_ui->resultsBrowser->header()); - m_ui->resultsBrowser->header()->setParent(m_ui->resultsBrowser); - unused.setVerticalHeader(new QHeaderView(Qt::Horizontal)); - - loadSettings(); - m_ui->resultsBrowser->setSelectionMode(QAbstractItemView::ExtendedSelection); - header()->setStretchLastSection(false); - - // Set Search results list model - m_searchListModel = new QStandardItemModel(0, SearchSortModel::NB_SEARCH_COLUMNS, this); - m_searchListModel->setHeaderData(SearchSortModel::NAME, Qt::Horizontal, tr("Name", "i.e: file name")); - m_searchListModel->setHeaderData(SearchSortModel::SIZE, Qt::Horizontal, tr("Size", "i.e: file size")); - m_searchListModel->setHeaderData(SearchSortModel::SEEDS, Qt::Horizontal, tr("Seeders", "i.e: Number of full sources")); - m_searchListModel->setHeaderData(SearchSortModel::LEECHES, Qt::Horizontal, tr("Leechers", "i.e: Number of partial sources")); - m_searchListModel->setHeaderData(SearchSortModel::ENGINE_URL, Qt::Horizontal, tr("Search engine")); - // Set columns text alignment - m_searchListModel->setHeaderData(SearchSortModel::SIZE, Qt::Horizontal, QVariant(Qt::AlignRight | Qt::AlignVCenter), Qt::TextAlignmentRole); - m_searchListModel->setHeaderData(SearchSortModel::SEEDS, Qt::Horizontal, QVariant(Qt::AlignRight | Qt::AlignVCenter), Qt::TextAlignmentRole); - m_searchListModel->setHeaderData(SearchSortModel::LEECHES, Qt::Horizontal, QVariant(Qt::AlignRight | Qt::AlignVCenter), Qt::TextAlignmentRole); - - m_proxyModel = new SearchSortModel(this); - m_proxyModel->setDynamicSortFilter(true); - m_proxyModel->setSourceModel(m_searchListModel); - m_ui->resultsBrowser->setModel(m_proxyModel); - - m_searchDelegate = new SearchListDelegate(this); - m_ui->resultsBrowser->setItemDelegate(m_searchDelegate); - - m_ui->resultsBrowser->hideColumn(SearchSortModel::DL_LINK); // Hide url column - m_ui->resultsBrowser->hideColumn(SearchSortModel::DESC_LINK); - - m_ui->resultsBrowser->setRootIsDecorated(false); - m_ui->resultsBrowser->setAllColumnsShowFocus(true); - m_ui->resultsBrowser->setSortingEnabled(true); - - //Ensure that at least one column is visible at all times - bool atLeastOne = false; - for (unsigned int i = 0; i < SearchSortModel::DL_LINK; i++) { - if (!m_ui->resultsBrowser->isColumnHidden(i)) { - atLeastOne = true; - break; - } - } - if (!atLeastOne) - m_ui->resultsBrowser->setColumnHidden(SearchSortModel::NAME, false); - //To also mitigate the above issue, we have to resize each column when - //its size is 0, because explicitly 'showing' the column isn't enough - //in the above scenario. - for (unsigned int i = 0; i < SearchSortModel::DL_LINK; i++) - if ((m_ui->resultsBrowser->columnWidth(i) <= 0) && !m_ui->resultsBrowser->isColumnHidden(i)) - m_ui->resultsBrowser->resizeColumnToContents(i); - - // Connect signals to slots (search part) - connect(m_ui->resultsBrowser, SIGNAL(doubleClicked(const QModelIndex&)), this, SLOT(downloadItem(const QModelIndex&))); - - header()->setContextMenuPolicy(Qt::CustomContextMenu); - connect(header(), SIGNAL(customContextMenuRequested(const QPoint &)), this, SLOT(displayToggleColumnsMenu(const QPoint &))); - connect(header(), SIGNAL(sectionResized(int, int, int)), this, SLOT(saveSettings())); - connect(header(), SIGNAL(sectionMoved(int, int, int)), this, SLOT(saveSettings())); - connect(header(), SIGNAL(sortIndicatorChanged(int, Qt::SortOrder)), this, SLOT(saveSettings())); - - fillFilterComboBoxes(); - - updateFilter(); - - connect(m_ui->filterMode, SIGNAL(currentIndexChanged(int)), this, SLOT(updateFilter())); - connect(m_ui->minSeeds, SIGNAL(editingFinished()), this, SLOT(updateFilter())); - connect(m_ui->minSeeds, SIGNAL(valueChanged(int)), this, SLOT(updateFilter())); - connect(m_ui->maxSeeds, SIGNAL(editingFinished()), this, SLOT(updateFilter())); - connect(m_ui->maxSeeds, SIGNAL(valueChanged(int)), this, SLOT(updateFilter())); - connect(m_ui->minSize, SIGNAL(editingFinished()), this, SLOT(updateFilter())); - connect(m_ui->minSize, SIGNAL(valueChanged(double)), this, SLOT(updateFilter())); - connect(m_ui->maxSize, SIGNAL(editingFinished()), this, SLOT(updateFilter())); - connect(m_ui->maxSize, SIGNAL(valueChanged(double)), this, SLOT(updateFilter())); - connect(m_ui->minSizeUnit, SIGNAL(currentIndexChanged(int)), this, SLOT(updateFilter())); - connect(m_ui->maxSizeUnit, SIGNAL(currentIndexChanged(int)), this, SLOT(updateFilter())); -} - -SearchTab::~SearchTab() -{ - saveSettings(); - delete m_ui; -} - -void SearchTab::downloadItem(const QModelIndex &index) -{ - QString torrentUrl = m_proxyModel->data(m_proxyModel->index(index.row(), SearchSortModel::DL_LINK)).toString(); - QString siteUrl = m_proxyModel->data(m_proxyModel->index(index.row(), SearchSortModel::ENGINE_URL)).toString(); - setRowColor(index.row(), QApplication::palette().color(QPalette::LinkVisited)); - m_parent->downloadTorrent(siteUrl, torrentUrl); -} - -QHeaderView* SearchTab::header() const -{ - return m_ui->resultsBrowser->header(); -} - -QTreeView* SearchTab::getCurrentTreeView() const -{ - return m_ui->resultsBrowser; -} - -SearchSortModel* SearchTab::getCurrentSearchListProxy() const -{ - return m_proxyModel; -} - -QStandardItemModel* SearchTab::getCurrentSearchListModel() const -{ - return m_searchListModel; -} - -// Set the color of a row in data model -void SearchTab::setRowColor(int row, const QColor &color) -{ - m_proxyModel->setDynamicSortFilter(false); - for (int i = 0; i < m_proxyModel->columnCount(); ++i) - m_proxyModel->setData(m_proxyModel->index(row, i), color, Qt::ForegroundRole); - - m_proxyModel->setDynamicSortFilter(true); -} - -SearchTab::Status SearchTab::status() const -{ - return m_status; -} - -void SearchTab::setStatus(Status value) -{ - m_status = value; - setStatusTip(statusText(value)); - const int thisTabIndex = m_parent->searchTabs()->indexOf(this); - m_parent->searchTabs()->setTabToolTip(thisTabIndex, statusTip()); - m_parent->searchTabs()->setTabIcon(thisTabIndex, GuiIconProvider::instance()->getIcon(statusIconName(value))); -} - -void SearchTab::updateResultsCount() -{ - const int totalResults = getCurrentSearchListModel() ? getCurrentSearchListModel()->rowCount(QModelIndex()) : 0; - const int filteredResults = getCurrentSearchListProxy() ? getCurrentSearchListProxy()->rowCount(QModelIndex()) : totalResults; - m_ui->resultsLbl->setText(tr("Results (showing %1 out of %2):", "i.e: Search results") - .arg(filteredResults).arg(totalResults)); -} - -void SearchTab::updateFilter() -{ - using Utils::Misc::SizeUnit; - SearchSortModel* filterModel = getCurrentSearchListProxy(); - filterModel->enableNameFilter(filteringMode() == NameFilteringMode::OnlyNames); - // we update size and seeds filter parameters in the model even if they are disabled - filterModel->setSeedsFilter(m_ui->minSeeds->value(), m_ui->maxSeeds->value()); - filterModel->setSizeFilter( - sizeInBytes(m_ui->minSize->value(), static_cast(m_ui->minSizeUnit->currentIndex())), - sizeInBytes(m_ui->maxSize->value(), static_cast(m_ui->maxSizeUnit->currentIndex()))); - - nameFilteringModeSetting() = filteringMode(); - - filterModel->invalidate(); - updateResultsCount(); -} - -void SearchTab::fillFilterComboBoxes() -{ - using Utils::Misc::SizeUnit; - QStringList unitStrings; - unitStrings.append(unitString(SizeUnit::Byte)); - unitStrings.append(unitString(SizeUnit::KibiByte)); - unitStrings.append(unitString(SizeUnit::MebiByte)); - unitStrings.append(unitString(SizeUnit::GibiByte)); - unitStrings.append(unitString(SizeUnit::TebiByte)); - unitStrings.append(unitString(SizeUnit::PebiByte)); - unitStrings.append(unitString(SizeUnit::ExbiByte)); - - m_ui->minSizeUnit->clear(); - m_ui->maxSizeUnit->clear(); - m_ui->minSizeUnit->addItems(unitStrings); - m_ui->maxSizeUnit->addItems(unitStrings); - - m_ui->minSize->setValue(0); - m_ui->minSizeUnit->setCurrentIndex(static_cast(SizeUnit::MebiByte)); - - m_ui->maxSize->setValue(-1); - m_ui->maxSizeUnit->setCurrentIndex(static_cast(SizeUnit::GibiByte)); - - m_ui->filterMode->clear(); - - m_ui->filterMode->addItem(tr("Torrent names only"), static_cast(NameFilteringMode::OnlyNames)); - m_ui->filterMode->addItem(tr("Everywhere"), static_cast(NameFilteringMode::Everywhere)); - - QVariant selectedMode = static_cast(nameFilteringModeSetting().value()); - int index = m_ui->filterMode->findData(selectedMode); - m_ui->filterMode->setCurrentIndex(index == -1 ? 0 : index); -} - -QString SearchTab::statusText(SearchTab::Status st) -{ - switch (st) { - case Status::Ongoing: - return tr("Searching..."); - case Status::Finished: - return tr("Search has finished"); - case Status::Aborted: - return tr("Search aborted"); - case Status::Error: - return tr("An error occurred during search..."); - case Status::NoResults: - return tr("Search returned no results"); - default: - return QString(); - } -} - -QString SearchTab::statusIconName(SearchTab::Status st) -{ - switch (st) { - case Status::Ongoing: - return QLatin1String("task-ongoing"); - case Status::Finished: - return QLatin1String("task-complete"); - case Status::Aborted: - return QLatin1String("task-reject"); - case Status::Error: - return QLatin1String("task-attention"); - case Status::NoResults: - return QLatin1String("task-attention"); - default: - return QString(); - } -} - -SearchTab::NameFilteringMode SearchTab::filteringMode() const -{ - return static_cast(m_ui->filterMode->itemData(m_ui->filterMode->currentIndex()).toInt()); -} - -void SearchTab::loadSettings() -{ - header()->restoreState(Preferences::instance()->getSearchTabHeaderState()); -} - -void SearchTab::saveSettings() const -{ - Preferences::instance()->setSearchTabHeaderState(header()->saveState()); -} - -void SearchTab::displayToggleColumnsMenu(const QPoint&) -{ - QMenu hideshowColumn(this); - hideshowColumn.setTitle(tr("Column visibility")); - QList actions; - for (int i = 0; i < SearchSortModel::DL_LINK; ++i) { - QAction *myAct = hideshowColumn.addAction(m_searchListModel->headerData(i, Qt::Horizontal, Qt::DisplayRole).toString()); - myAct->setCheckable(true); - myAct->setChecked(!m_ui->resultsBrowser->isColumnHidden(i)); - actions.append(myAct); - } - int visibleCols = 0; - for (unsigned int i = 0; i < SearchSortModel::DL_LINK; i++) { - if (!m_ui->resultsBrowser->isColumnHidden(i)) - visibleCols++; - - if (visibleCols > 1) - break; - } - - // Call menu - QAction *act = hideshowColumn.exec(QCursor::pos()); - if (act) { - int col = actions.indexOf(act); - Q_ASSERT(col >= 0); - Q_ASSERT(visibleCols > 0); - if ((!m_ui->resultsBrowser->isColumnHidden(col)) && (visibleCols == 1)) - return; - qDebug("Toggling column %d visibility", col); - m_ui->resultsBrowser->setColumnHidden(col, !m_ui->resultsBrowser->isColumnHidden(col)); - if ((!m_ui->resultsBrowser->isColumnHidden(col)) && (m_ui->resultsBrowser->columnWidth(col) <= 5)) - m_ui->resultsBrowser->setColumnWidth(col, 100); - saveSettings(); - } -} - -CachedSettingValue &SearchTab::nameFilteringModeSetting() -{ - static CachedSettingValue setting("Search/FilteringMode", NameFilteringMode::OnlyNames); - return setting; -} diff --git a/src/gui/search/searchtab.h b/src/gui/search/searchtab.h deleted file mode 100644 index c573deef3..000000000 --- a/src/gui/search/searchtab.h +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Bittorrent Client using Qt4 and libtorrent. - * Copyright (C) 2006 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 SEARCHTAB_H -#define SEARCHTAB_H - -#include - -#define ENGINE_URL_COLUMN 4 -#define URL_COLUMN 5 - -class QLabel; -class QModelIndex; -class QTreeView; -class QHeaderView; -class QStandardItemModel; -class QVBoxLayout; - -template class CachedSettingValue; - -class SearchSortModel; -class SearchListDelegate; -class SearchWidget; - -namespace Ui -{ - class SearchTab; -} - -class SearchTab: public QWidget -{ - Q_OBJECT - -public: - - enum class NameFilteringMode - { - Everywhere, - OnlyNames - }; - - Q_ENUM(NameFilteringMode) - - explicit SearchTab(SearchWidget *parent); - ~SearchTab(); - - QStandardItemModel* getCurrentSearchListModel() const; - SearchSortModel* getCurrentSearchListProxy() const; - QTreeView* getCurrentTreeView() const; - QHeaderView* header() const; - - void setRowColor(int row, const QColor &color); - - enum class Status - { - Ongoing, - Finished, - Error, - Aborted, - NoResults - }; - - void setStatus(Status value); - Status status() const; - - void updateResultsCount(); - -public slots: - void downloadItem(const QModelIndex &index); - -private slots: - void loadSettings(); - void saveSettings() const; - void updateFilter(); - void displayToggleColumnsMenu(const QPoint&); - -private: - void fillFilterComboBoxes(); - NameFilteringMode filteringMode() const; - static QString statusText(Status st); - static QString statusIconName(Status st); - - static CachedSettingValue& nameFilteringModeSetting(); - - Ui::SearchTab *m_ui; - QTreeView *m_resultsBrowser; - QStandardItemModel *m_searchListModel; - SearchSortModel *m_proxyModel; - SearchListDelegate *m_searchDelegate; - SearchWidget *m_parent; - Status m_status; -}; - -Q_DECLARE_METATYPE(SearchTab::NameFilteringMode) - -#endif // SEARCHTAB_H diff --git a/src/gui/search/searchtab.ui b/src/gui/search/searchtab.ui deleted file mode 100644 index d2ec133d6..000000000 --- a/src/gui/search/searchtab.ui +++ /dev/null @@ -1,250 +0,0 @@ - - - SearchTab - - - - 0 - 0 - 1216 - 364 - - - - Form - - - - - - - - Results(xxx) - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - Qt::NoFocus - - - Search in: - - - filterMode - - - - - - - <html><head/><body><p>Some search engines search in torrent description and in torrent file names too. Whether such results will be shown in the list below is controlled by this mode.</p><p><span style=" font-weight:600;">Everywhere </span>disables filtering and shows everyhing returned by the search engines.</p><p><span style=" font-weight:600;">Torrent names only</span> shows only torrents whose names match the search query.</p></body></html> - - - - - - - Qt::Horizontal - - - QSizePolicy::Minimum - - - - 12 - 20 - - - - - - - - - 0 - 0 - - - - <html><head/><body><p>Set minimal and maximal allowed number of seeders</p></body></html> - - - Seeds: - - - - - - - <html><head/><body><p>Minimal number of seeds</p></body></html> - - - 0 - - - 1000 - - - 0 - - - - - - - - 0 - 0 - - - - to - - - - - - - <html><head/><body><p>Maximal number of seeds</p></body></html> - - - - - - - - - -1 - - - 1000 - - - -1 - - - - - - - Qt::Horizontal - - - QSizePolicy::Minimum - - - - 12 - 20 - - - - - - - - - 0 - 0 - - - - <html><head/><body><p>Set minimal and maximal allowed size of a torrent</p></body></html> - - - Size: - - - - - - - - - <html><head/><body><p>Minimal torrent size</p></body></html> - - - 0.000000000000000 - - - 1000.000000000000000 - - - 0.000000000000000 - - - - - - - QComboBox::AdjustToContents - - - - - - - - - to - - - - - - - - - <html><head/><body><p>Maximal torrent size</p></body></html> - - - - - - -1.000000000000000 - - - 1000.000000000000000 - - - 1000.000000000000000 - - - - - - - -1 - - - QComboBox::AdjustToContents - - - - - - - - - - - - - - - diff --git a/src/gui/search/searchwidget.cpp b/src/gui/search/searchwidget.cpp deleted file mode 100644 index 623713e03..000000000 --- a/src/gui/search/searchwidget.cpp +++ /dev/null @@ -1,474 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2015 Vladimir Golovnev - * Copyright (C) 2006 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 "searchwidget.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#ifdef Q_OS_WIN -#include -#endif - -#include "base/bittorrent/session.h" -#include "base/utils/fs.h" -#include "base/utils/misc.h" -#include "base/preferences.h" -#include "base/searchengine.h" -#include "searchlistdelegate.h" -#include "mainwindow.h" -#include "addnewtorrentdialog.h" -#include "guiiconprovider.h" -#include "pluginselectdlg.h" -#include "searchsortmodel.h" -#include "searchtab.h" - -#include "ui_searchwidget.h" - -#define SEARCHHISTORY_MAXSIZE 50 -#define URL_COLUMN 5 - -SearchWidget::SearchWidget(MainWindow *mainWindow) - : QWidget(mainWindow) - , m_ui(new Ui::SearchWidget()) - , m_mainWindow(mainWindow) - , m_isNewQueryString(false) - , m_noSearchResults(true) -{ - m_ui->setupUi(this); - - QString searchPatternHint; - QTextStream stream(&searchPatternHint, QIODevice::WriteOnly); - stream << "

" - << tr("A phrase to search for.") << "
" - << tr("Spaces in a search term may be protected by double quotes.") - << "

" - << tr("Example:", "Search phrase example") - << "
" - << tr("foo bar: search for foo and bar", - "Search phrase example, illustrates quotes usage, a pair of " - "space delimited words, individal words are highlighted") - << "
" - << tr(""foo bar": search for foo bar", - "Search phrase example, illustrates quotes usage, double quoted" - "pair of space delimited words, the whole pair is highlighted") - << "

" << flush; - m_ui->m_searchPattern->setToolTip(searchPatternHint); - -#ifndef Q_OS_MAC - // Icons - m_ui->searchButton->setIcon(GuiIconProvider::instance()->getIcon("edit-find")); - m_ui->downloadButton->setIcon(GuiIconProvider::instance()->getIcon("download")); - m_ui->goToDescBtn->setIcon(GuiIconProvider::instance()->getIcon("application-x-mswinurl")); - m_ui->pluginsButton->setIcon(GuiIconProvider::instance()->getIcon("preferences-system-network")); - m_ui->copyURLBtn->setIcon(GuiIconProvider::instance()->getIcon("edit-copy")); -#else - // On macOS the icons overlap the text otherwise - QSize iconSize = m_ui->tabWidget->iconSize(); - iconSize.setWidth(iconSize.width() + 16); - m_ui->tabWidget->setIconSize(iconSize); -#endif - connect(m_ui->tabWidget, &QTabWidget::tabCloseRequested, this, &SearchWidget::closeTab); - - m_searchEngine = new SearchEngine; - connect(m_searchEngine, &SearchEngine::searchStarted, this, &SearchWidget::searchStarted); - connect(m_searchEngine, &SearchEngine::newSearchResults, this, &SearchWidget::appendSearchResults); - connect(m_searchEngine, &SearchEngine::searchFinished, this, &SearchWidget::searchFinished); - connect(m_searchEngine, &SearchEngine::searchFailed, this, &SearchWidget::searchFailed); - connect(m_searchEngine, &SearchEngine::torrentFileDownloaded, this, &SearchWidget::addTorrentToSession); - - const auto onPluginChanged = [this]() - { - fillCatCombobox(); - fillPluginComboBox(); - selectActivePage(); - }; - connect(m_searchEngine, &SearchEngine::pluginInstalled, this, onPluginChanged); - connect(m_searchEngine, &SearchEngine::pluginUninstalled, this, onPluginChanged); - connect(m_searchEngine, &SearchEngine::pluginUpdated, this, onPluginChanged); - connect(m_searchEngine, &SearchEngine::pluginEnabled, this, onPluginChanged); - - // Fill in category combobox - onPluginChanged(); - - connect(m_ui->m_searchPattern, &LineEdit::returnPressed, m_ui->searchButton, &QPushButton::click); - connect(m_ui->m_searchPattern, &LineEdit::textEdited, this, &SearchWidget::searchTextEdited); - connect(m_ui->selectPlugin, static_cast(&QComboBox::currentIndexChanged), this, &SearchWidget::selectMultipleBox); -} - -void SearchWidget::fillCatCombobox() -{ - m_ui->comboCategory->clear(); - m_ui->comboCategory->addItem(SearchEngine::categoryFullName("all"), QVariant("all")); - m_ui->comboCategory->insertSeparator(1); - - using QStrPair = QPair; - QList tmpList; - foreach (const QString &cat, m_searchEngine->supportedCategories()) - tmpList << qMakePair(SearchEngine::categoryFullName(cat), cat); - std::sort(tmpList.begin(), tmpList.end(), [](const QStrPair &l, const QStrPair &r) { return (QString::localeAwareCompare(l.first, r.first) < 0); }); - - foreach (const QStrPair &p, tmpList) { - qDebug("Supported category: %s", qPrintable(p.second)); - m_ui->comboCategory->addItem(p.first, QVariant(p.second)); - } -} - -void SearchWidget::fillPluginComboBox() -{ - m_ui->selectPlugin->clear(); - m_ui->selectPlugin->addItem(tr("Only enabled"), QVariant("enabled")); - m_ui->selectPlugin->addItem(tr("All plugins"), QVariant("all")); - m_ui->selectPlugin->addItem(tr("Select..."), QVariant("multi")); - m_ui->selectPlugin->insertSeparator(3); - - using QStrPair = QPair; - QList tmpList; - foreach (const QString &name, m_searchEngine->enabledPlugins()) - tmpList << qMakePair(m_searchEngine->pluginFullName(name), name); - std::sort(tmpList.begin(), tmpList.end(), [](const QStrPair &l, const QStrPair &r) { return (l.first < r.first); } ); - - foreach (const QStrPair &p, tmpList) - m_ui->selectPlugin->addItem(p.first, QVariant(p.second)); -} - -QString SearchWidget::selectedCategory() const -{ - return m_ui->comboCategory->itemData(m_ui->comboCategory->currentIndex()).toString(); -} - -QString SearchWidget::selectedPlugin() const -{ - return m_ui->selectPlugin->itemData(m_ui->selectPlugin->currentIndex()).toString(); -} - -void SearchWidget::selectActivePage() -{ - if (m_searchEngine->allPlugins().isEmpty()) { - m_ui->stackedPages->setCurrentWidget(m_ui->emptyPage); - m_ui->m_searchPattern->setEnabled(false); - m_ui->comboCategory->setEnabled(false); - m_ui->selectPlugin->setEnabled(false); - m_ui->searchButton->setEnabled(false); - } - else { - m_ui->stackedPages->setCurrentWidget(m_ui->searchPage); - m_ui->m_searchPattern->setEnabled(true); - m_ui->comboCategory->setEnabled(true); - m_ui->selectPlugin->setEnabled(true); - m_ui->searchButton->setEnabled(true); - } -} - -SearchWidget::~SearchWidget() -{ - qDebug("Search destruction"); - delete m_searchEngine; - delete m_ui; -} - -void SearchWidget::downloadTorrent(const QString &siteUrl, const QString &url) -{ - if (url.startsWith("bc://bt/", Qt::CaseInsensitive) || url.startsWith("magnet:", Qt::CaseInsensitive)) - addTorrentToSession(url); - else - m_searchEngine->downloadTorrent(siteUrl, url); -} - -void SearchWidget::tab_changed(int t) -{ - //when we switch from a tab that is not empty to another that is empty the download button - //doesn't have to be available - if (t > -1) { - //-1 = no more tab - m_currentSearchTab = m_allTabs.at(m_ui->tabWidget->currentIndex()); - if (m_currentSearchTab->getCurrentSearchListModel()->rowCount()) { - m_ui->downloadButton->setEnabled(true); - m_ui->goToDescBtn->setEnabled(true); - m_ui->copyURLBtn->setEnabled(true); - } - else { - m_ui->downloadButton->setEnabled(false); - m_ui->goToDescBtn->setEnabled(false); - m_ui->copyURLBtn->setEnabled(false); - } - } -} - -void SearchWidget::selectMultipleBox(int index) -{ - Q_UNUSED(index); - if (selectedPlugin() == "multi") - on_pluginsButton_clicked(); -} - -void SearchWidget::addTorrentToSession(const QString &source) -{ - if (AddNewTorrentDialog::isEnabled()) - AddNewTorrentDialog::show(source, this); - else - BitTorrent::Session::instance()->addTorrent(source); -} - -void SearchWidget::on_pluginsButton_clicked() -{ - new PluginSelectDlg(m_searchEngine, this); -} - -void SearchWidget::searchTextEdited(QString) -{ - // Enable search button - m_ui->searchButton->setText(tr("Search")); - m_isNewQueryString = true; -} - -void SearchWidget::giveFocusToSearchInput() -{ - m_ui->m_searchPattern->setFocus(); -} - -QTabWidget *SearchWidget::searchTabs() const -{ - return m_ui->tabWidget; -} - -// Function called when we click on search button -void SearchWidget::on_searchButton_clicked() -{ - if (Utils::Misc::pythonVersion() < 0) { - m_mainWindow->showNotificationBaloon(tr("Search Engine"), tr("Please install Python to use the Search Engine.")); - return; - } - - if (m_searchEngine->isActive()) { - m_searchEngine->cancelSearch(); - - if (!m_isNewQueryString) { - m_ui->searchButton->setText(tr("Search")); - return; - } - } - - m_isNewQueryString = false; - - const QString pattern = m_ui->m_searchPattern->text().trimmed(); - // No search pattern entered - if (pattern.isEmpty()) { - QMessageBox::critical(this, tr("Empty search pattern"), tr("Please type a search pattern first")); - return; - } - - // Tab Addition - m_currentSearchTab = new SearchTab(this); - m_activeSearchTab = m_currentSearchTab; - m_allTabs.append(m_currentSearchTab); - QString tabName = pattern; - tabName.replace(QRegExp("&{1}"), "&&"); - m_ui->tabWidget->addTab(m_currentSearchTab, tabName); - m_ui->tabWidget->setCurrentWidget(m_currentSearchTab); - m_currentSearchTab->getCurrentSearchListProxy()->setNameFilter(pattern); - - QStringList plugins; - if (selectedPlugin() == "all") plugins = m_searchEngine->allPlugins(); - else if (selectedPlugin() == "enabled") plugins = m_searchEngine->enabledPlugins(); - else if (selectedPlugin() == "multi") plugins = m_searchEngine->enabledPlugins(); - else plugins << selectedPlugin(); - - qDebug("Search with category: %s", qPrintable(selectedCategory())); - - // Update SearchEngine widgets - m_noSearchResults = true; - - // Changing the text of the current label - m_activeSearchTab->updateResultsCount(); - - // Launch search - m_searchEngine->startSearch(pattern, selectedCategory(), plugins); -} - -void SearchWidget::searchStarted() -{ - // Update SearchEngine widgets - m_activeSearchTab->setStatus(SearchTab::Status::Ongoing); - m_ui->searchButton->setText(tr("Stop")); -} - -// Slot called when search is Finished -// Search can be finished for 3 reasons : -// Error | Stopped by user | Finished normally -void SearchWidget::searchFinished(bool cancelled) -{ - if (m_mainWindow->isNotificationsEnabled() && (m_mainWindow->currentTabWidget() != this)) - m_mainWindow->showNotificationBaloon(tr("Search Engine"), tr("Search has finished")); - - if (m_activeSearchTab.isNull()) return; // The active tab was closed - - if (cancelled) - m_activeSearchTab->setStatus(SearchTab::Status::Aborted); - else if (m_noSearchResults) - m_activeSearchTab->setStatus(SearchTab::Status::NoResults); - else - m_activeSearchTab->setStatus(SearchTab::Status::Finished); - - m_activeSearchTab = 0; - m_ui->searchButton->setText(tr("Search")); -} - -void SearchWidget::searchFailed() -{ - if (m_mainWindow->isNotificationsEnabled() && (m_mainWindow->currentTabWidget() != this)) - m_mainWindow->showNotificationBaloon(tr("Search Engine"), tr("Search has failed")); - - if (m_activeSearchTab.isNull()) return; // The active tab was closed - -#ifdef Q_OS_WIN - m_activeSearchTab->setStatus(SearchTab::Status::Aborted); -#else - m_activeSearchTab->setStatus(SearchTab::Status::Error); -#endif -} - -void SearchWidget::appendSearchResults(const QList &results) -{ - if (m_activeSearchTab.isNull()) { - m_searchEngine->cancelSearch(); - return; - } - - Q_ASSERT(m_activeSearchTab); - - QStandardItemModel *curModel = m_activeSearchTab->getCurrentSearchListModel(); - Q_ASSERT(curModel); - - foreach (const SearchResult &result, results) { - // Add item to search result list - int row = curModel->rowCount(); - curModel->insertRow(row); - - curModel->setData(curModel->index(row, SearchSortModel::DL_LINK), result.fileUrl); // download URL - curModel->setData(curModel->index(row, SearchSortModel::NAME), result.fileName); // Name - curModel->setData(curModel->index(row, SearchSortModel::SIZE), result.fileSize); // Size - curModel->setData(curModel->index(row, SearchSortModel::SEEDS), result.nbSeeders); // Seeders - curModel->setData(curModel->index(row, SearchSortModel::LEECHES), result.nbLeechers); // Leechers - curModel->setData(curModel->index(row, SearchSortModel::ENGINE_URL), result.siteUrl); // Search site URL - curModel->setData(curModel->index(row, SearchSortModel::DESC_LINK), result.descrLink); // Description Link - } - - m_noSearchResults = false; - m_activeSearchTab->updateResultsCount(); - - // Enable clear & download buttons - m_ui->downloadButton->setEnabled(true); - m_ui->goToDescBtn->setEnabled(true); - m_ui->copyURLBtn->setEnabled(true); -} - -void SearchWidget::closeTab(int index) -{ - // Search is run for active tab so if user decided to close it, then stop search - if (!m_activeSearchTab.isNull() && index == m_ui->tabWidget->indexOf(m_activeSearchTab)) { - qDebug("Closed active search Tab"); - if (m_searchEngine->isActive()) - m_searchEngine->cancelSearch(); - m_activeSearchTab = 0; - } - - delete m_allTabs.takeAt(index); - - if (!m_allTabs.size()) { - m_ui->downloadButton->setEnabled(false); - m_ui->goToDescBtn->setEnabled(false); - m_ui->copyURLBtn->setEnabled(false); - } -} - -// Download selected items in search results list -void SearchWidget::on_downloadButton_clicked() -{ - //QModelIndexList selectedIndexes = currentSearchTab->getCurrentTreeView()->selectionModel()->selectedIndexes(); - QModelIndexList selectedIndexes = - m_allTabs.at(m_ui->tabWidget->currentIndex())->getCurrentTreeView()->selectionModel()->selectedIndexes(); - foreach (const QModelIndex &index, selectedIndexes) { - if (index.column() == SearchSortModel::NAME) - m_allTabs.at(m_ui->tabWidget->currentIndex())->downloadItem(index); - } -} - -void SearchWidget::on_goToDescBtn_clicked() -{ - QModelIndexList selectedIndexes = - m_allTabs.at(m_ui->tabWidget->currentIndex())->getCurrentTreeView()->selectionModel()->selectedIndexes(); - foreach (const QModelIndex &index, selectedIndexes) { - if (index.column() == SearchSortModel::NAME) { - QSortFilterProxyModel *model = m_allTabs.at(m_ui->tabWidget->currentIndex())->getCurrentSearchListProxy(); - const QString descUrl = model->data(model->index(index.row(), SearchSortModel::DESC_LINK)).toString(); - if (!descUrl.isEmpty()) - QDesktopServices::openUrl(QUrl::fromEncoded(descUrl.toUtf8())); - } - } -} - -void SearchWidget::on_copyURLBtn_clicked() -{ - QStringList urls; - QModelIndexList selectedIndexes = - m_allTabs.at(m_ui->tabWidget->currentIndex())->getCurrentTreeView()->selectionModel()->selectedIndexes(); - - foreach (const QModelIndex &index, selectedIndexes) { - if (index.column() == SearchSortModel::NAME) { - QSortFilterProxyModel *model = m_allTabs.at(m_ui->tabWidget->currentIndex())->getCurrentSearchListProxy(); - const QString descUrl = model->data(model->index(index.row(), SearchSortModel::DESC_LINK)).toString(); - if (!descUrl.isEmpty()) - urls << descUrl.toUtf8(); - } - } - - if (!urls.empty()) { - QClipboard *clipboard = QApplication::clipboard(); - clipboard->setText(urls.join("\n")); - } -} diff --git a/src/gui/search/searchwidget.h b/src/gui/search/searchwidget.h deleted file mode 100644 index 1f582ae70..000000000 --- a/src/gui/search/searchwidget.h +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2015 Vladimir Golovnev - * Copyright (C) 2006 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 SEARCHWIDGET_H -#define SEARCHWIDGET_H - -#include -#include -#include - -class QTabWidget; - -class MainWindow; -class SearchEngine; -struct SearchResult; -class SearchTab; - -namespace Ui -{ - class SearchWidget; -} - -class SearchWidget: public QWidget -{ - Q_OBJECT - Q_DISABLE_COPY(SearchWidget) - -public: - explicit SearchWidget(MainWindow *mainWindow); - ~SearchWidget(); - - void downloadTorrent(const QString &siteUrl, const QString &url); - void giveFocusToSearchInput(); - - QTabWidget* searchTabs() const; - -private slots: - // Search slots - void tab_changed(int); //to prevent the use of the download button when the tab is empty - void on_searchButton_clicked(); - void on_downloadButton_clicked(); - void on_goToDescBtn_clicked(); - void on_copyURLBtn_clicked(); - void on_pluginsButton_clicked(); - - void closeTab(int index); - void appendSearchResults(const QList &results); - void searchStarted(); - void searchFinished(bool cancelled); - void searchFailed(); - void selectMultipleBox(int index); - - void addTorrentToSession(const QString &source); - - void fillCatCombobox(); - void fillPluginComboBox(); - void selectActivePage(); - void searchTextEdited(QString); - -private: - QString selectedCategory() const; - QString selectedPlugin() const; - - Ui::SearchWidget *m_ui; - SearchEngine *m_searchEngine; - QPointer m_currentSearchTab; // Selected tab - QPointer m_activeSearchTab; // Tab with running search - QList> m_allTabs; // To store all tabs - MainWindow *m_mainWindow; - bool m_isNewQueryString; - bool m_noSearchResults; - QByteArray m_searchResultLineTruncated; -}; - -#endif // SEARCHWIDGET_H diff --git a/src/gui/search/searchwidget.ui b/src/gui/search/searchwidget.ui deleted file mode 100644 index c8b86ddf9..000000000 --- a/src/gui/search/searchwidget.ui +++ /dev/null @@ -1,179 +0,0 @@ - - - SearchWidget - - - - 0 - 0 - 843 - 669 - - - - Search - - - - - - - - - - - - 0 - 0 - - - - - - - - - 0 - 0 - - - - - - - - - 0 - 0 - - - - Search - - - - - - - - - 1 - - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - There aren't any search plugins installed. -Click the "Search plugins..." button at the bottom right of the window to install some. - - - Qt::AlignCenter - - - - - - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - true - - - - - - - - - - - - - false - - - Download - - - - - - - false - - - Go to description page - - - - - - - false - - - Copy description page URL - - - - - - - Qt::Horizontal - - - - 0 - 0 - - - - - - - - Search plugins... - - - - - - - - - - LineEdit - QLineEdit -
lineedit.h
-
-
- - -
diff --git a/src/gui/shutdownconfirmdlg.cpp b/src/gui/shutdownconfirmdlg.cpp deleted file mode 100644 index 63446e752..000000000 --- a/src/gui/shutdownconfirmdlg.cpp +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2014 sledgehammer999 - * 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. - */ - -#include "shutdownconfirmdlg.h" - -#include -#include -#include -#include - -#include "base/preferences.h" -#include "base/utils/misc.h" -#include "ui_shutdownconfirmdlg.h" - -ShutdownConfirmDlg::ShutdownConfirmDlg(QWidget *parent, const ShutdownDialogAction &action) - : QDialog(parent) - , m_ui(new Ui::confirmShutdownDlg) - , m_timeout(15) - , m_action(action) -{ - m_ui->setupUi(this); - - initText(); - QIcon warningIcon(style()->standardIcon(QStyle::SP_MessageBoxWarning)); - m_ui->warningLabel->setPixmap(warningIcon.pixmap(32)); - - if (m_action == ShutdownDialogAction::Exit) - m_ui->neverShowAgainCheckbox->setVisible(true); - else - m_ui->neverShowAgainCheckbox->setVisible(false); - - // Cancel Button - QPushButton *cancelButton = m_ui->buttonBox->button(QDialogButtonBox::Cancel); - cancelButton->setFocus(); - cancelButton->setDefault(true); - - // Always on top - setWindowFlags(windowFlags() | Qt::WindowStaysOnTopHint); - move(Utils::Misc::screenCenter(this)); - - m_timer.setInterval(1000); // 1sec - connect(&m_timer, SIGNAL(timeout()), this, SLOT(updateSeconds())); -} - -ShutdownConfirmDlg::~ShutdownConfirmDlg() -{ - delete m_ui; -} - -void ShutdownConfirmDlg::showEvent(QShowEvent *event) -{ - QDialog::showEvent(event); - m_timer.start(); -} - -bool ShutdownConfirmDlg::askForConfirmation(QWidget *parent, const ShutdownDialogAction &action) -{ - ShutdownConfirmDlg dlg(parent, action); - return (dlg.exec() == QDialog::Accepted); -} - -void ShutdownConfirmDlg::updateSeconds() -{ - --m_timeout; - updateText(); - if (m_timeout == 0) { - m_timer.stop(); - accept(); - } -} - -void ShutdownConfirmDlg::accept() -{ - Preferences::instance()->setDontConfirmAutoExit(m_ui->neverShowAgainCheckbox->isChecked()); - QDialog::accept(); -} - -void ShutdownConfirmDlg::initText() -{ - QPushButton *okButton = m_ui->buttonBox->button(QDialogButtonBox::Ok); - - switch (m_action) { - case ShutdownDialogAction::Exit: - m_msg = tr("qBittorrent will now exit."); - okButton->setText(tr("E&xit Now")); - setWindowTitle(tr("Exit confirmation")); - break; - case ShutdownDialogAction::Shutdown: - m_msg = tr("The computer is going to shutdown."); - okButton->setText(tr("&Shutdown Now")); - setWindowTitle(tr("Shutdown confirmation")); - break; - case ShutdownDialogAction::Suspend: - m_msg = tr("The computer is going to enter suspend mode."); - okButton->setText(tr("&Suspend Now")); - setWindowTitle(tr("Suspend confirmation")); - break; - case ShutdownDialogAction::Hibernate: - m_msg = tr("The computer is going to enter hibernation mode."); - okButton->setText(tr("&Hibernate Now")); - setWindowTitle(tr("Hibernate confirmation")); - break; - } - - m_msg += "\n"; - updateText(); -} - -void ShutdownConfirmDlg::updateText() -{ - QString t = tr("You can cancel the action within %1 seconds.").arg(QString::number(m_timeout)) + "\n"; - m_ui->shutdownText->setText(m_msg + t); -} diff --git a/src/gui/shutdownconfirmdlg.h b/src/gui/shutdownconfirmdlg.h deleted file mode 100644 index 1c9b70fe1..000000000 --- a/src/gui/shutdownconfirmdlg.h +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Bittorrent Client using Qt 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. - */ - -#ifndef SHUTDOWNCONFIRMDLG_H -#define SHUTDOWNCONFIRMDLG_H - -#include -#include - -#include "base/types.h" - -namespace Ui -{ - class confirmShutdownDlg; -} - -class ShutdownConfirmDlg: public QDialog -{ - Q_OBJECT - -public: - ShutdownConfirmDlg(QWidget *parent, const ShutdownDialogAction &action); - ~ShutdownConfirmDlg(); - - static bool askForConfirmation(QWidget *parent, const ShutdownDialogAction &action); - -protected: - void showEvent(QShowEvent *event) override; - -private slots: - void updateSeconds(); - void accept() override; - -private: - // Methods - void initText(); - void updateText(); - - // Vars - Ui::confirmShutdownDlg *m_ui; - QTimer m_timer; - int m_timeout; - ShutdownDialogAction m_action; - QString m_msg; -}; - -#endif // SHUTDOWNCONFIRM_H diff --git a/src/gui/shutdownconfirmdlg.ui b/src/gui/shutdownconfirmdlg.ui deleted file mode 100644 index 5c46f40a4..000000000 --- a/src/gui/shutdownconfirmdlg.ui +++ /dev/null @@ -1,127 +0,0 @@ - - - confirmShutdownDlg - - - - 0 - 0 - 410 - 140 - - - - - 15 - - - - - - - warning icon - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop - - - - - - - Qt::Horizontal - - - QSizePolicy::Fixed - - - - 20 - 0 - - - - - - - - - 0 - 0 - - - - shutdown message goes here - - - true - - - - - - - Don't show again - - - - - - - - - Qt::Vertical - - - - 0 - 0 - - - - - - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - - - - - - - buttonBox - accepted() - confirmShutdownDlg - accept() - - - 248 - 254 - - - 157 - 274 - - - - - buttonBox - rejected() - confirmShutdownDlg - reject() - - - 316 - 260 - - - 286 - 274 - - - - - diff --git a/src/gui/speedlimitdlg.cpp b/src/gui/speedlimitdlg.cpp deleted file mode 100644 index ef14b152c..000000000 --- a/src/gui/speedlimitdlg.cpp +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Bittorrent Client using Qt4 and libtorrent. - * Copyright (C) 2006 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 "speedlimitdlg.h" - -#include "ui_bandwidth_limit.h" -#include "base/unicodestrings.h" - -SpeedLimitDialog::SpeedLimitDialog(QWidget *parent) - : QDialog(parent) - , m_ui(new Ui::bandwidth_dlg()) -{ - m_ui->setupUi(this); - qDebug("Bandwidth allocation dialog creation"); - - // Connect to slots - connect(m_ui->bandwidthSlider, SIGNAL(valueChanged(int)), this, SLOT(updateSpinValue(int))); - connect(m_ui->spinBandwidth, SIGNAL(valueChanged(int)), this, SLOT(updateSliderValue(int))); -} - -SpeedLimitDialog::~SpeedLimitDialog() -{ - qDebug("Deleting bandwidth allocation dialog"); - delete m_ui; -} - -// -2: if cancel -long SpeedLimitDialog::askSpeedLimit(QWidget *parent, bool *ok, QString title, long default_value, long max_value) -{ - SpeedLimitDialog dlg(parent); - dlg.setWindowTitle(title); - dlg.setupDialog(max_value / 1024., default_value / 1024.); - if (dlg.exec() == QDialog::Accepted) { - *ok = true; - int val = dlg.getSpeedLimit(); - if (val <= 0) - return 0; - return val * 1024; - } - else { - *ok = false; - return -2; - } -} - -void SpeedLimitDialog::updateSpinValue(int val) const -{ - qDebug("Called updateSpinValue with %d", val); - if (val <= 0) { - m_ui->spinBandwidth->setValue(0); - m_ui->spinBandwidth->setSpecialValueText(QString::fromUtf8(C_INFINITY)); - m_ui->spinBandwidth->setSuffix(QString::fromUtf8("")); - } - else { - m_ui->spinBandwidth->setValue(val); - m_ui->spinBandwidth->setSuffix(" " + tr("KiB/s")); - } -} - -void SpeedLimitDialog::updateSliderValue(int val) const -{ - if (val <= 0) { - m_ui->spinBandwidth->setValue(0); - m_ui->spinBandwidth->setSpecialValueText(QString::fromUtf8(C_INFINITY)); - m_ui->spinBandwidth->setSuffix(QString::fromUtf8("")); - } - if (val > m_ui->bandwidthSlider->maximum()) - m_ui->bandwidthSlider->setMaximum(val); - m_ui->bandwidthSlider->setValue(val); -} - -long SpeedLimitDialog::getSpeedLimit() const -{ - long val = m_ui->bandwidthSlider->value(); - if (val > 0) - return val; - return -1; -} - -void SpeedLimitDialog::setupDialog(long max_slider, long val) const -{ - if (val < 0) - val = 0; - if (max_slider <= 0) - max_slider = 10000; - // This can happen for example if global rate limit is lower - // than torrent rate limit. - if (val > max_slider) - max_slider = val; - m_ui->bandwidthSlider->setMaximum(max_slider); - m_ui->bandwidthSlider->setValue(val); - updateSpinValue(val); -} diff --git a/src/gui/speedlimitdlg.h b/src/gui/speedlimitdlg.h deleted file mode 100644 index 45f62b144..000000000 --- a/src/gui/speedlimitdlg.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Bittorrent Client using Qt4 and libtorrent. - * Copyright (C) 2006 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 BANDWIDTH_ALLOCATION_H -#define BANDWIDTH_ALLOCATION_H - -#include -#include -#include "base/utils/misc.h" -#include "base/bittorrent/session.h" - -namespace Ui -{ - class bandwidth_dlg; -} - -class SpeedLimitDialog : public QDialog { - Q_OBJECT -public: - explicit SpeedLimitDialog(QWidget *parent); - ~SpeedLimitDialog(); - static long askSpeedLimit(QWidget *parent, bool *ok, QString title, long default_value, long max_value=10240000); - -protected slots: - void updateSpinValue(int val) const; - void updateSliderValue(int val) const; - long getSpeedLimit() const; - void setupDialog(long max_slider, long val) const; - -private: - Ui::bandwidth_dlg *m_ui; -}; - -#endif diff --git a/src/gui/statsdialog.cpp b/src/gui/statsdialog.cpp deleted file mode 100644 index f73d61164..000000000 --- a/src/gui/statsdialog.cpp +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Bittorrent Client using Qt 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. - */ - -#include "statsdialog.h" - -#include "base/bittorrent/cachestatus.h" -#include "base/bittorrent/session.h" -#include "base/bittorrent/sessionstatus.h" -#include "base/bittorrent/torrenthandle.h" -#include "base/utils/misc.h" -#include "base/utils/string.h" -#include "ui_statsdialog.h" - -StatsDialog::StatsDialog(QWidget *parent) - : QDialog(parent) - , m_ui(new Ui::StatsDialog) -{ - m_ui->setupUi(this); - setAttribute(Qt::WA_DeleteOnClose); - connect(m_ui->buttonBox, &QDialogButtonBox::accepted, this, &StatsDialog::close); - - update(); - connect(BitTorrent::Session::instance(), &BitTorrent::Session::statsUpdated - , this, &StatsDialog::update); - - show(); -} - -StatsDialog::~StatsDialog() -{ - delete m_ui; -} - -void StatsDialog::update() -{ - const BitTorrent::SessionStatus &ss = BitTorrent::Session::instance()->status(); - const BitTorrent::CacheStatus &cs = BitTorrent::Session::instance()->cacheStatus(); - - // Alltime DL/UL - quint64 atd = BitTorrent::Session::instance()->getAlltimeDL(); - quint64 atu = BitTorrent::Session::instance()->getAlltimeUL(); - m_ui->labelAlltimeDL->setText(Utils::Misc::friendlyUnit(atd)); - m_ui->labelAlltimeUL->setText(Utils::Misc::friendlyUnit(atu)); - // Total waste (this session) - m_ui->labelWaste->setText(Utils::Misc::friendlyUnit(ss.totalWasted)); - // Global ratio - m_ui->labelGlobalRatio->setText( - ((atd > 0) && (atu > 0)) - ? Utils::String::fromDouble(static_cast(atu) / atd, 2) - : "-"); - // Cache hits - qreal readRatio = cs.readRatio; - m_ui->labelCacheHits->setText((readRatio >= 0) ? Utils::String::fromDouble(100 * readRatio, 2) : "-"); - // Buffers size - m_ui->labelTotalBuf->setText(Utils::Misc::friendlyUnit(cs.totalUsedBuffers * 16 * 1024)); - // Disk overload (100%) equivalent - // From lt manual: disk_write_queue and disk_read_queue are the number of peers currently waiting on a disk write or disk read - // to complete before it receives or sends any more data on the socket. It's a metric of how disk bound you are. - - // num_peers is not reliable (adds up peers, which didn't even overcome tcp handshake) - quint32 peers = 0; - foreach (BitTorrent::TorrentHandle *const torrent, BitTorrent::Session::instance()->torrents()) - peers += torrent->peersCount(); - - m_ui->labelWriteStarve->setText(QString("%1%") - .arg(((ss.diskWriteQueue > 0) && (peers > 0)) - ? Utils::String::fromDouble((100. * ss.diskWriteQueue) / peers, 2) - : "0")); - m_ui->labelReadStarve->setText(QString("%1%") - .arg(((ss.diskReadQueue > 0) && (peers > 0)) - ? Utils::String::fromDouble((100. * ss.diskReadQueue) / peers, 2) - : "0")); - // Disk queues - m_ui->labelQueuedJobs->setText(QString::number(cs.jobQueueLength)); - m_ui->labelJobsTime->setText(tr("%1 ms", "18 milliseconds").arg(cs.averageJobTime)); - m_ui->labelQueuedBytes->setText(Utils::Misc::friendlyUnit(cs.queuedBytes)); - - // Total connected peers - m_ui->labelPeers->setText(QString::number(ss.peersCount)); -} diff --git a/src/gui/statsdialog.h b/src/gui/statsdialog.h deleted file mode 100644 index 22652ebda..000000000 --- a/src/gui/statsdialog.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Bittorrent Client using Qt 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. - */ - -#ifndef STATSDIALOG_H -#define STATSDIALOG_H - -#include - -namespace Ui -{ - class StatsDialog; -} - -class StatsDialog: public QDialog -{ - Q_OBJECT - -public: - explicit StatsDialog(QWidget *parent); - ~StatsDialog() override; - -private slots: - void update(); - -private: - Ui::StatsDialog *m_ui; -}; - -#endif // STATSDIALOG_H diff --git a/src/gui/statsdialog.ui b/src/gui/statsdialog.ui deleted file mode 100644 index ef2ebbf08..000000000 --- a/src/gui/statsdialog.ui +++ /dev/null @@ -1,236 +0,0 @@ - - - StatsDialog - - - - 0 - 0 - 286 - 401 - - - - Statistics - - - - - - User statistics - - - - - - Total peer connections: - - - - - - - Global ratio: - - - - - - - TextLabel - - - - - - - Alltime download: - - - - - - - TextLabel - - - - - - - TextLabel - - - - - - - Alltime upload: - - - - - - - TextLabel - - - - - - - Total waste (this session): - - - - - - - TextLabel - - - - - - - - - - Cache statistics - - - - - - Read cache hits: - - - - - - - TextLabel - - - - - - - TextLabel - - - - - - - Total buffers size: - - - - - - - - - - Performance statistics - - - - - - TextLabel - - - - - - - TextLabel - - - - - - - TextLabel - - - - - - - TextLabel - - - - - - - Queued I/O jobs: - - - - - - - Write cache overload: - - - - - - - Average time in queue: - - - - - - - Read cache overload: - - - - - - - Total queued size: - - - - - - - TextLabel - - - - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - QDialogButtonBox::Ok - - - - - - - - diff --git a/src/gui/statusbar.cpp b/src/gui/statusbar.cpp deleted file mode 100644 index 20927f928..000000000 --- a/src/gui/statusbar.cpp +++ /dev/null @@ -1,271 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2006 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. - */ - -#include "statusbar.h" - -#include -#include -#include -#include -#include -#include -#include - -#include "base/bittorrent/session.h" -#include "base/bittorrent/sessionstatus.h" -#include "base/utils/misc.h" -#include "guiiconprovider.h" -#include "speedlimitdlg.h" - -StatusBar::StatusBar(QWidget *parent) - : QStatusBar(parent) -{ -#ifndef Q_OS_MAC - // Redefining global stylesheet breaks certain elements on mac like tabs. - // Qt checks whether the stylesheet class inherts("QMacStyle") and this becomes false. - qApp->setStyleSheet("QStatusBar::item { border-width: 0; }"); -#endif - - BitTorrent::Session *const session = BitTorrent::Session::instance(); - connect(session, &BitTorrent::Session::speedLimitModeChanged, this, &StatusBar::updateAltSpeedsBtn); - QWidget *container = new QWidget(this); - QHBoxLayout *layout = new QHBoxLayout(container); - layout->setContentsMargins(0,0,0,0); - - container->setLayout(layout); - m_connecStatusLblIcon = new QPushButton(this); - m_connecStatusLblIcon->setFlat(true); - m_connecStatusLblIcon->setFocusPolicy(Qt::NoFocus); - m_connecStatusLblIcon->setCursor(Qt::PointingHandCursor); - m_connecStatusLblIcon->setIcon(QIcon(":/icons/skin/firewalled.png")); - m_connecStatusLblIcon->setToolTip( - QString(QLatin1String("%1
%2")) - .arg(tr("Connection status:")) - .arg(tr("No direct connections. This may indicate network configuration problems."))); - connect(m_connecStatusLblIcon, &QAbstractButton::clicked, this, &StatusBar::connectionButtonClicked); - - m_dlSpeedLbl = new QPushButton(this); - m_dlSpeedLbl->setIcon(QIcon(":/icons/skin/download.png")); - connect(m_dlSpeedLbl, &QAbstractButton::clicked, this, &StatusBar::capDownloadSpeed); - m_dlSpeedLbl->setFlat(true); - m_dlSpeedLbl->setFocusPolicy(Qt::NoFocus); - m_dlSpeedLbl->setCursor(Qt::PointingHandCursor); - m_dlSpeedLbl->setStyleSheet("text-align:left;"); - m_dlSpeedLbl->setMinimumWidth(200); - - m_upSpeedLbl = new QPushButton(this); - m_upSpeedLbl->setIcon(QIcon(":/icons/skin/seeding.png")); - connect(m_upSpeedLbl, &QAbstractButton::clicked, this, &StatusBar::capUploadSpeed); - m_upSpeedLbl->setFlat(true); - m_upSpeedLbl->setFocusPolicy(Qt::NoFocus); - m_upSpeedLbl->setCursor(Qt::PointingHandCursor); - m_upSpeedLbl->setStyleSheet("text-align:left;"); - m_upSpeedLbl->setMinimumWidth(200); - - m_DHTLbl = new QLabel(tr("DHT: %1 nodes").arg(0), this); - m_DHTLbl->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Preferred); - - m_altSpeedsBtn = new QPushButton(this); - m_altSpeedsBtn->setFlat(true); - m_altSpeedsBtn->setFocusPolicy(Qt::NoFocus); - m_altSpeedsBtn->setCursor(Qt::PointingHandCursor); - updateAltSpeedsBtn(session->isAltGlobalSpeedLimitEnabled()); - connect(m_altSpeedsBtn, &QAbstractButton::clicked, this, &StatusBar::alternativeSpeedsButtonClicked); - - // Because on some platforms the default icon size is bigger - // and it will result in taller/fatter statusbar, even if the - // icons are actually 16x16 - m_connecStatusLblIcon->setIconSize(QSize(16, 16)); - m_dlSpeedLbl->setIconSize(QSize(16, 16)); - m_upSpeedLbl->setIconSize(QSize(16, 16)); - m_altSpeedsBtn->setIconSize(QSize(28, 16)); - - // Set to the known maximum width(plus some padding) - // so the speed widgets will take the rest of the space - m_connecStatusLblIcon->setMaximumWidth(16 + 6); - m_altSpeedsBtn->setMaximumWidth(28 + 6); - - QFrame *statusSep1 = new QFrame(this); - statusSep1->setFrameStyle(QFrame::VLine); -#ifndef Q_OS_MAC - statusSep1->setFrameShadow(QFrame::Raised); -#endif - QFrame *statusSep2 = new QFrame(this); - statusSep2->setFrameStyle(QFrame::VLine); -#ifndef Q_OS_MAC - statusSep2->setFrameShadow(QFrame::Raised); -#endif - QFrame *statusSep3 = new QFrame(this); - statusSep3->setFrameStyle(QFrame::VLine); -#ifndef Q_OS_MAC - statusSep3->setFrameShadow(QFrame::Raised); -#endif - QFrame *statusSep4 = new QFrame(this); - statusSep4->setFrameStyle(QFrame::VLine); -#ifndef Q_OS_MAC - statusSep4->setFrameShadow(QFrame::Raised); -#endif - layout->addWidget(m_DHTLbl); - layout->addWidget(statusSep1); - layout->addWidget(m_connecStatusLblIcon); - layout->addWidget(statusSep2); - layout->addWidget(m_altSpeedsBtn); - layout->addWidget(statusSep4); - layout->addWidget(m_dlSpeedLbl); - layout->addWidget(statusSep3); - layout->addWidget(m_upSpeedLbl); - - addPermanentWidget(container); - setStyleSheet("QWidget {margin: 0;}"); - container->adjustSize(); - adjustSize(); - // Is DHT enabled - m_DHTLbl->setVisible(session->isDHTEnabled()); - refresh(); - connect(session, &BitTorrent::Session::statsUpdated, this, &StatusBar::refresh); -} - -StatusBar::~StatusBar() -{ - qDebug() << Q_FUNC_INFO; -} - -void StatusBar::showRestartRequired() -{ - // Restart required notification - const QString restartText = tr("qBittorrent needs to be restarted!"); - QLabel *restartIconLbl = new QLabel(this); - restartIconLbl->setPixmap(style()->standardPixmap(QStyle::SP_MessageBoxWarning)); - restartIconLbl->setToolTip(restartText); - insertWidget(0, restartIconLbl); - - QLabel *restartLbl = new QLabel(this); - restartLbl->setText(restartText); - insertWidget(1, restartLbl); -} - -void StatusBar::updateConnectionStatus() -{ - const BitTorrent::SessionStatus &sessionStatus = BitTorrent::Session::instance()->status(); - - if (!BitTorrent::Session::instance()->isListening()) { - m_connecStatusLblIcon->setIcon(QIcon(QLatin1String(":/icons/skin/disconnected.png"))); - m_connecStatusLblIcon->setToolTip(QLatin1String("") + tr("Connection Status:") + QLatin1String("
") + tr("Offline. This usually means that qBittorrent failed to listen on the selected port for incoming connections.")); - } - else { - if (sessionStatus.hasIncomingConnections) { - // Connection OK - m_connecStatusLblIcon->setIcon(QIcon(QLatin1String(":/icons/skin/connected.png"))); - m_connecStatusLblIcon->setToolTip(QLatin1String("") + tr("Connection Status:") + QLatin1String("
") + tr("Online")); - } - else { - m_connecStatusLblIcon->setIcon(QIcon(QLatin1String(":/icons/skin/firewalled.png"))); - m_connecStatusLblIcon->setToolTip(QLatin1String("") + tr("Connection status:") + QLatin1String("
") + QLatin1String("") + tr("No direct connections. This may indicate network configuration problems.") + QLatin1String("")); - } - } -} - -void StatusBar::updateDHTNodesNumber() -{ - if (BitTorrent::Session::instance()->isDHTEnabled()) { - m_DHTLbl->setVisible(true); - m_DHTLbl->setText(tr("DHT: %1 nodes") - .arg(BitTorrent::Session::instance()->status().dhtNodes)); - } - else { - m_DHTLbl->setVisible(false); - } -} - -void StatusBar::updateSpeedLabels() -{ - const BitTorrent::SessionStatus &sessionStatus = BitTorrent::Session::instance()->status(); - - QString speedLbl = Utils::Misc::friendlyUnit(sessionStatus.payloadDownloadRate, true); - int speedLimit = BitTorrent::Session::instance()->downloadSpeedLimit(); - if (speedLimit) - speedLbl += " [" + Utils::Misc::friendlyUnit(speedLimit, true) + "]"; - speedLbl += " (" + Utils::Misc::friendlyUnit(sessionStatus.totalPayloadDownload) + ")"; - m_dlSpeedLbl->setText(speedLbl); - speedLimit = BitTorrent::Session::instance()->uploadSpeedLimit(); - speedLbl = Utils::Misc::friendlyUnit(sessionStatus.payloadUploadRate, true); - if (speedLimit) - speedLbl += " [" + Utils::Misc::friendlyUnit(speedLimit, true) + "]"; - speedLbl += " (" + Utils::Misc::friendlyUnit(sessionStatus.totalPayloadUpload) + ")"; - m_upSpeedLbl->setText(speedLbl); -} - -void StatusBar::refresh() -{ - updateConnectionStatus(); - updateDHTNodesNumber(); - updateSpeedLabels(); -} - -void StatusBar::updateAltSpeedsBtn(bool alternative) -{ - if (alternative) { - m_altSpeedsBtn->setIcon(QIcon(":/icons/slow.png")); - m_altSpeedsBtn->setToolTip(tr("Click to switch to regular speed limits")); - m_altSpeedsBtn->setDown(true); - } - else { - m_altSpeedsBtn->setIcon(QIcon(":/icons/slow_off.png")); - m_altSpeedsBtn->setToolTip(tr("Click to switch to alternative speed limits")); - m_altSpeedsBtn->setDown(false); - } - refresh(); -} - -void StatusBar::capDownloadSpeed() -{ - BitTorrent::Session *const session = BitTorrent::Session::instance(); - - bool ok = false; - const long newLimit = SpeedLimitDialog::askSpeedLimit( - parentWidget(), &ok, tr("Global Download Speed Limit"), session->downloadSpeedLimit()); - if (ok) { - qDebug("Setting global download rate limit to %.1fKb/s", newLimit / 1024.); - session->setDownloadSpeedLimit(newLimit); - refresh(); - } -} - -void StatusBar::capUploadSpeed() -{ - BitTorrent::Session *const session = BitTorrent::Session::instance(); - - bool ok = false; - const long newLimit = SpeedLimitDialog::askSpeedLimit( - parentWidget(), &ok, tr("Global Upload Speed Limit"), session->uploadSpeedLimit()); - if (ok) { - qDebug("Setting global upload rate limit to %.1fKb/s", newLimit / 1024.); - session->setUploadSpeedLimit(newLimit); - refresh(); - } -} diff --git a/src/gui/statusbar.h b/src/gui/statusbar.h deleted file mode 100644 index 5fe8db8bc..000000000 --- a/src/gui/statusbar.h +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2006 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. - */ - -#ifndef STATUSBAR_H -#define STATUSBAR_H - -#include - -class QLabel; -class QPushButton; - -namespace BitTorrent -{ - struct SessionStatus; -} - -class StatusBar: public QStatusBar -{ - Q_OBJECT - Q_DISABLE_COPY(StatusBar) - -public: - StatusBar(QWidget *parent = nullptr); - ~StatusBar() override; - -signals: - void alternativeSpeedsButtonClicked(); - void connectionButtonClicked(); - -public slots: - void showRestartRequired(); - -private slots: - void refresh(); - void updateAltSpeedsBtn(bool alternative); - void capDownloadSpeed(); - void capUploadSpeed(); - -private: - void updateConnectionStatus(); - void updateDHTNodesNumber(); - void updateSpeedLabels(); - - QPushButton *m_dlSpeedLbl; - QPushButton *m_upSpeedLbl; - QLabel *m_DHTLbl; - QPushButton *m_connecStatusLblIcon; - QPushButton *m_altSpeedsBtn; -}; - -#endif // STATUSBAR_H diff --git a/src/gui/tagfiltermodel.cpp b/src/gui/tagfiltermodel.cpp deleted file mode 100644 index 5d9f81bd3..000000000 --- a/src/gui/tagfiltermodel.cpp +++ /dev/null @@ -1,337 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2017 Tony Gregerson - * - * 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. - */ - -#include "tagfiltermodel.h" - -#include -#include -#include - -#include "base/bittorrent/session.h" -#include "base/bittorrent/torrenthandle.h" -#include "guiiconprovider.h" - -namespace -{ - QString getSpecialAllTag() - { - static const QString *const ALL_TAG = new QString(" "); - Q_ASSERT(!BitTorrent::Session::isValidTag(*ALL_TAG)); - return *ALL_TAG; - } - - QString getSpecialUntaggedTag() - { - static const QString *const UNTAGGED_TAG = new QString(" "); - Q_ASSERT(!BitTorrent::Session::isValidTag(*UNTAGGED_TAG)); - return *UNTAGGED_TAG; - } -} - -class TagModelItem -{ -public: - TagModelItem(const QString &tag, int torrentsCount = 0) - : m_tag(tag) - , m_torrentsCount(torrentsCount) - { - } - - QString tag() const - { - return m_tag; - } - - int torrentsCount() const - { - return m_torrentsCount; - } - - void increaseTorrentsCount() - { - ++m_torrentsCount; - } - - void decreaseTorrentsCount() - { - Q_ASSERT(m_torrentsCount > 0); - --m_torrentsCount; - } - -private: - QString m_tag; - int m_torrentsCount; -}; - -TagFilterModel::TagFilterModel(QObject *parent) - : QAbstractListModel(parent) -{ - using Session = BitTorrent::Session; - auto session = Session::instance(); - - connect(session, &Session::tagAdded, this, &TagFilterModel::tagAdded); - connect(session, &Session::tagRemoved, this, &TagFilterModel::tagRemoved); - connect(session, &Session::torrentTagAdded, this, &TagFilterModel::torrentTagAdded); - connect(session, &Session::torrentTagRemoved, this, &TagFilterModel::torrentTagRemoved); - connect(session, &Session::torrentAdded, this, &TagFilterModel::torrentAdded); - connect(session, &Session::torrentAboutToBeRemoved, this, &TagFilterModel::torrentAboutToBeRemoved); - populate(); -} - -TagFilterModel::~TagFilterModel() = default; - -bool TagFilterModel::isSpecialItem(const QModelIndex &index) -{ - // the first two items are special items: 'All' and 'Untagged' - return (!index.parent().isValid() && (index.row() <= 1)); -} - -QVariant TagFilterModel::data(const QModelIndex &index, int role) const -{ - if (!index.isValid() || index.column() != 0) - return QVariant(); - - const int row = index.internalId(); - Q_ASSERT(isValidRow(row)); - const TagModelItem &item = m_tagItems[row]; - - switch (role) { - case Qt::DecorationRole: - return GuiIconProvider::instance()->getIcon("inode-directory"); - case Qt::DisplayRole: - return QString(QLatin1String("%1 (%2)")) - .arg(tagDisplayName(item.tag())).arg(item.torrentsCount()); - case Qt::UserRole: - return item.torrentsCount(); - default: - return QVariant(); - } -} - -Qt::ItemFlags TagFilterModel::flags(const QModelIndex &index) const -{ - if (!index.isValid()) - return 0; - return Qt::ItemIsEnabled | Qt::ItemIsSelectable; -} - -QVariant TagFilterModel::headerData(int section, Qt::Orientation orientation, int role) const -{ - if ((orientation == Qt::Horizontal) && (role == Qt::DisplayRole)) - if (section == 0) - return tr("Tags"); - return QVariant(); -} - -QModelIndex TagFilterModel::index(int row, int, const QModelIndex &) const -{ - if (!isValidRow(row)) - return QModelIndex(); - return createIndex(row, 0, row); -} - -int TagFilterModel::rowCount(const QModelIndex &parent) const -{ - if (!parent.isValid()) - return m_tagItems.count(); - return 0; -} - -bool TagFilterModel::isValidRow(int row) const -{ - return (row >= 0) && (row < m_tagItems.size()); -} - -QModelIndex TagFilterModel::index(const QString &tag) const -{ - const int row = findRow(tag); - if (!isValidRow(row)) - return QModelIndex(); - return index(row, 0, QModelIndex()); -} - -QString TagFilterModel::tag(const QModelIndex &index) const -{ - if (!index.isValid()) - return QString(); - const int row = index.internalId(); - Q_ASSERT(isValidRow(row)); - return m_tagItems[row].tag(); -} - -void TagFilterModel::tagAdded(const QString &tag) -{ - const int row = m_tagItems.count(); - beginInsertRows(QModelIndex(), row, row); - addToModel(tag, 0); - endInsertRows(); -} - -void TagFilterModel::tagRemoved(const QString &tag) -{ - QModelIndex i = index(tag); - beginRemoveRows(i.parent(), i.row(), i.row()); - removeFromModel(i.row()); - endRemoveRows(); -} - -void TagFilterModel::torrentTagAdded(BitTorrent::TorrentHandle *const torrent, const QString &tag) -{ - if (torrent->tags().count() == 1) - untaggedItem()->decreaseTorrentsCount(); - - const int row = findRow(tag); - Q_ASSERT(isValidRow(row)); - TagModelItem &item = m_tagItems[row]; - - item.increaseTorrentsCount(); - const QModelIndex i = index(row, 0, QModelIndex()); - emit dataChanged(i, i); -} - -void TagFilterModel::torrentTagRemoved(BitTorrent::TorrentHandle* const torrent, const QString &tag) -{ - Q_ASSERT(torrent->tags().count() >= 0); - if (torrent->tags().count() == 0) - untaggedItem()->increaseTorrentsCount(); - - const int row = findRow(tag); - Q_ASSERT(isValidRow(row)); - TagModelItem &item = m_tagItems[row]; - - item.decreaseTorrentsCount(); - const QModelIndex i = index(row, 0, QModelIndex()); - emit dataChanged(i, i); -} - -void TagFilterModel::torrentAdded(BitTorrent::TorrentHandle *const torrent) -{ - allTagsItem()->increaseTorrentsCount(); - - const QVector items = findItems(torrent->tags()); - if (items.isEmpty()) - untaggedItem()->increaseTorrentsCount(); - - foreach (TagModelItem *item, items) - item->increaseTorrentsCount(); -} - -void TagFilterModel::torrentAboutToBeRemoved(BitTorrent::TorrentHandle *const torrent) -{ - allTagsItem()->decreaseTorrentsCount(); - - if (torrent->tags().isEmpty()) - untaggedItem()->decreaseTorrentsCount(); - - foreach (TagModelItem *item, findItems(torrent->tags())) - item->decreaseTorrentsCount(); -} - -QString TagFilterModel::tagDisplayName(const QString &tag) -{ - if (tag == getSpecialAllTag()) - return tr("All"); - if (tag == getSpecialUntaggedTag()) - return tr("Untagged"); - return tag; -} - -void TagFilterModel::populate() -{ - using Torrent = BitTorrent::TorrentHandle; - - auto session = BitTorrent::Session::instance(); - auto torrents = session->torrents(); - - // All torrents - addToModel(getSpecialAllTag(), torrents.count()); - - const int untaggedCount = std::count_if(torrents.begin(), torrents.end(), - [](Torrent *torrent) { return torrent->tags().isEmpty(); }); - addToModel(getSpecialUntaggedTag(), untaggedCount); - - foreach (const QString &tag, session->tags()) { - const int count = std::count_if(torrents.begin(), torrents.end(), - [tag](Torrent *torrent) { return torrent->hasTag(tag); }); - addToModel(tag, count); - } -} - -void TagFilterModel::addToModel(const QString &tag, int count) -{ - m_tagItems.append(TagModelItem(tag, count)); -} - -void TagFilterModel::removeFromModel(int row) -{ - Q_ASSERT(isValidRow(row)); - m_tagItems.removeAt(row); -} - -int TagFilterModel::findRow(const QString &tag) const -{ - for (int i = 0; i < m_tagItems.size(); ++i) { - if (m_tagItems[i].tag() == tag) - return i; - } - return -1; -} - -TagModelItem *TagFilterModel::findItem(const QString &tag) -{ - const int row = findRow(tag); - if (!isValidRow(row)) - return nullptr; - return &m_tagItems[row]; -} - -QVector TagFilterModel::findItems(const QSet &tags) -{ - QVector items; - items.reserve(tags.size()); - foreach (const QString &tag, tags) { - TagModelItem *item = findItem(tag); - if (item) - items.push_back(item); - else - qWarning() << QString("Requested tag '%1' missing from the model.").arg(tag); - } - return items; -} - -TagModelItem *TagFilterModel::allTagsItem() -{ - Q_ASSERT(m_tagItems.size() > 0); - return &m_tagItems[0]; -} - -TagModelItem *TagFilterModel::untaggedItem() -{ - Q_ASSERT(m_tagItems.size() > 1); - return &m_tagItems[1]; -} diff --git a/src/gui/tagfiltermodel.h b/src/gui/tagfiltermodel.h deleted file mode 100644 index f2f3cc67a..000000000 --- a/src/gui/tagfiltermodel.h +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2017 Tony Gregerson - * - * 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. - */ - -#ifndef TAGFILTERMODEL_H -#define TAGFILTERMODEL_H - -#include -#include -#include -#include -#include - -namespace BitTorrent -{ - class TorrentHandle; -} - -class TagModelItem; - -class TagFilterModel: public QAbstractListModel -{ - Q_OBJECT - -public: - explicit TagFilterModel(QObject *parent = nullptr); - ~TagFilterModel(); - - static bool isSpecialItem(const QModelIndex &index); - - QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; - Qt::ItemFlags flags(const QModelIndex &index) const override; - QVariant headerData(int section, Qt::Orientation orientation, int role) const override; - QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override; - int rowCount(const QModelIndex &parent = QModelIndex()) const override; - - QModelIndex index(const QString &tag) const; - QString tag(const QModelIndex &index) const; - -private slots: - void tagAdded(const QString &tag); - void tagRemoved(const QString &tag); - void torrentTagAdded(BitTorrent::TorrentHandle *const torrent, const QString &tag); - void torrentTagRemoved(BitTorrent::TorrentHandle *const, const QString &tag); - void torrentAdded(BitTorrent::TorrentHandle *const torrent); - void torrentAboutToBeRemoved(BitTorrent::TorrentHandle *const torrent); - -private: - static QString tagDisplayName(const QString &tag); - - void populate(); - void addToModel(const QString &tag, int count); - void removeFromModel(int row); - bool isValidRow(int row) const; - int findRow(const QString &tag) const; - TagModelItem *findItem(const QString &tag); - QVector findItems(const QSet &tags); - TagModelItem *allTagsItem(); - TagModelItem *untaggedItem(); - - QList m_tagItems; // Index corresponds to its row -}; - -#endif // TAGFILTERMODEL_H diff --git a/src/gui/tagfilterproxymodel.cpp b/src/gui/tagfilterproxymodel.cpp deleted file mode 100644 index 5bfb9036f..000000000 --- a/src/gui/tagfilterproxymodel.cpp +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2017 Tony Gregerson - * - * 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. - */ - -#include "tagfilterproxymodel.h" - -#include "base/utils/string.h" -#include "tagfiltermodel.h" - -TagFilterProxyModel::TagFilterProxyModel(QObject *parent) - : QSortFilterProxyModel(parent) -{ -} - -QModelIndex TagFilterProxyModel::index(const QString &tag) const -{ - return mapFromSource(static_cast(sourceModel())->index(tag)); -} - -QString TagFilterProxyModel::tag(const QModelIndex &index) const -{ - return static_cast(sourceModel())->tag(mapToSource(index)); -} - -bool TagFilterProxyModel::lessThan(const QModelIndex &left, const QModelIndex &right) const -{ - // "All" and "Untagged" must be left in place - if (TagFilterModel::isSpecialItem(left) || TagFilterModel::isSpecialItem(right)) - return left.row() < right.row(); - return Utils::String::naturalCompareCaseInsensitive( - left.data().toString(), right.data().toString()); -} diff --git a/src/gui/tagfilterproxymodel.h b/src/gui/tagfilterproxymodel.h deleted file mode 100644 index 60e4174df..000000000 --- a/src/gui/tagfilterproxymodel.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2017 Tony Gregerson - * - * 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. - */ - -#ifndef TAGFILTERPROXYMODEL_H -#define TAGFILTERPROXYMODEL_H - -#include -#include - -class TagFilterProxyModel: public QSortFilterProxyModel -{ -public: - explicit TagFilterProxyModel(QObject *parent = nullptr); - - // TagFilterModel methods which we need to relay - QModelIndex index(const QString &tag) const; - QString tag(const QModelIndex &index) const; - -protected: - bool lessThan(const QModelIndex &left, const QModelIndex &right) const override; - -private: - // we added another overload of index(), hence this using directive: - using QSortFilterProxyModel::index; -}; - -#endif // TAGFILTERPROXYMODEL_H diff --git a/src/gui/tagfilterwidget.cpp b/src/gui/tagfilterwidget.cpp deleted file mode 100644 index 591d8b427..000000000 --- a/src/gui/tagfilterwidget.cpp +++ /dev/null @@ -1,225 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2017 Tony Gregerson - * - * 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. - */ - -#include "tagfilterwidget.h" - -#include -#include -#include -#include -#include -#include - -#include "base/bittorrent/session.h" -#include "base/utils/misc.h" -#include "autoexpandabledialog.h" -#include "guiiconprovider.h" -#include "tagfiltermodel.h" -#include "tagfilterproxymodel.h" - -namespace -{ - QString getTagFilter(const TagFilterProxyModel *const model, const QModelIndex &index) - { - QString tagFilter; // Defaults to All - if (index.isValid()) { - if (index.row() == 1) - tagFilter = ""; // Untagged - else if (index.row() > 1) - tagFilter = model->tag(index); - } - return tagFilter; - } -} - -TagFilterWidget::TagFilterWidget(QWidget *parent) - : QTreeView(parent) -{ - TagFilterProxyModel *proxyModel = new TagFilterProxyModel(this); - proxyModel->setSortCaseSensitivity(Qt::CaseInsensitive); - proxyModel->setSourceModel(new TagFilterModel(this)); - setModel(proxyModel); - setFrameShape(QFrame::NoFrame); - setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); - setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); - setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); - setUniformRowHeights(true); - setHeaderHidden(true); - setIconSize(Utils::Misc::smallIconSize()); -#if defined(Q_OS_MAC) - setAttribute(Qt::WA_MacShowFocusRect, false); - setIndentation(0); -#endif - setContextMenuPolicy(Qt::CustomContextMenu); - sortByColumn(0, Qt::AscendingOrder); - setCurrentIndex(model()->index(0, 0)); - - connect(this, &TagFilterWidget::collapsed, this, &TagFilterWidget::callUpdateGeometry); - connect(this, &TagFilterWidget::expanded, this, &TagFilterWidget::callUpdateGeometry); - connect(this, &TagFilterWidget::customContextMenuRequested, this, &TagFilterWidget::showMenu); - connect(selectionModel(), &QItemSelectionModel::currentRowChanged, this - , &TagFilterWidget::onCurrentRowChanged); - connect(model(), &QAbstractItemModel::modelReset, this, &TagFilterWidget::callUpdateGeometry); -} - -QString TagFilterWidget::currentTag() const -{ - QModelIndex current; - auto selectedRows = selectionModel()->selectedRows(); - if (!selectedRows.isEmpty()) - current = selectedRows.first(); - - return getTagFilter(static_cast(model()), current); -} - -void TagFilterWidget::onCurrentRowChanged(const QModelIndex ¤t, const QModelIndex &previous) -{ - Q_UNUSED(previous); - - emit tagChanged(getTagFilter(static_cast(model()), current)); -} - -void TagFilterWidget::showMenu(QPoint) -{ - QMenu menu(this); - - QAction *addAct = menu.addAction( - GuiIconProvider::instance()->getIcon("list-add") - , tr("Add tag...")); - connect(addAct, &QAction::triggered, this, &TagFilterWidget::addTag); - - auto selectedRows = selectionModel()->selectedRows(); - if (!selectedRows.empty() && !TagFilterModel::isSpecialItem(selectedRows.first())) { - QAction *removeAct = menu.addAction( - GuiIconProvider::instance()->getIcon("list-remove") - , tr("Remove tag")); - connect(removeAct, &QAction::triggered, this, &TagFilterWidget::removeTag); - } - - QAction *removeUnusedAct = menu.addAction( - GuiIconProvider::instance()->getIcon("list-remove") - , tr("Remove unused tags")); - connect(removeUnusedAct, &QAction::triggered, this, &TagFilterWidget::removeUnusedTags); - - menu.addSeparator(); - - QAction *startAct = menu.addAction( - GuiIconProvider::instance()->getIcon("media-playback-start") - , tr("Resume torrents")); - connect(startAct, &QAction::triggered - , this, &TagFilterWidget::actionResumeTorrentsTriggered); - - QAction *pauseAct = menu.addAction( - GuiIconProvider::instance()->getIcon("media-playback-pause") - , tr("Pause torrents")); - connect(pauseAct, &QAction::triggered, this - , &TagFilterWidget::actionPauseTorrentsTriggered); - - QAction *deleteTorrentsAct = menu.addAction( - GuiIconProvider::instance()->getIcon("edit-delete") - , tr("Delete torrents")); - connect(deleteTorrentsAct, &QAction::triggered, this - , &TagFilterWidget::actionDeleteTorrentsTriggered); - - menu.exec(QCursor::pos()); -} - -void TagFilterWidget::callUpdateGeometry() -{ - updateGeometry(); -} - -QSize TagFilterWidget::sizeHint() const -{ - return viewportSizeHint(); -} - -QSize TagFilterWidget::minimumSizeHint() const -{ - QSize size = sizeHint(); - size.setWidth(6); - return size; -} - -void TagFilterWidget::rowsInserted(const QModelIndex &parent, int start, int end) -{ - QTreeView::rowsInserted(parent, start, end); - updateGeometry(); -} - -QString TagFilterWidget::askTagName() -{ - bool ok = false; - QString tag = ""; - bool invalid = true; - while (invalid) { - invalid = false; - tag = AutoExpandableDialog::getText( - this, tr("New Tag"), tr("Tag:"), QLineEdit::Normal, tag, &ok).trimmed(); - if (ok && !tag.isEmpty()) { - if (!BitTorrent::Session::isValidTag(tag)) { - QMessageBox::warning( - this, tr("Invalid tag name") - , tr("Tag name '%1' is invalid").arg(tag)); - invalid = true; - } - } - } - - return ok ? tag : QString(); -} - -void TagFilterWidget::addTag() -{ - const QString tag = askTagName(); - if (tag.isEmpty()) return; - - if (BitTorrent::Session::instance()->tags().contains(tag)) - QMessageBox::warning(this, tr("Tag exists"), tr("Tag name already exists.")); - else - BitTorrent::Session::instance()->addTag(tag); -} - -void TagFilterWidget::removeTag() -{ - auto selectedRows = selectionModel()->selectedRows(); - if (!selectedRows.empty() && !TagFilterModel::isSpecialItem(selectedRows.first())) { - BitTorrent::Session::instance()->removeTag( - static_cast(model())->tag(selectedRows.first())); - updateGeometry(); - } -} - -void TagFilterWidget::removeUnusedTags() -{ - auto session = BitTorrent::Session::instance(); - foreach (const QString &tag, session->tags()) - if (model()->data(static_cast(model())->index(tag), Qt::UserRole) == 0) - session->removeTag(tag); - updateGeometry(); -} diff --git a/src/gui/tagfilterwidget.h b/src/gui/tagfilterwidget.h deleted file mode 100644 index c24b0d34f..000000000 --- a/src/gui/tagfilterwidget.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2017 Tony Gregerson - * - * 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. - */ - -#ifndef TAGFILTERWIDGET_H -#define TAGFILTERWIDGET_H - -#include - -class TagFilterWidget: public QTreeView -{ - Q_OBJECT - -public: - explicit TagFilterWidget(QWidget *parent = nullptr); - - QString currentTag() const; - -signals: - void tagChanged(const QString &tag); - void actionResumeTorrentsTriggered(); - void actionPauseTorrentsTriggered(); - void actionDeleteTorrentsTriggered(); - -private slots: - void onCurrentRowChanged(const QModelIndex ¤t, const QModelIndex &previous); - void showMenu(QPoint); - void callUpdateGeometry(); - void addTag(); - void removeTag(); - void removeUnusedTags(); - -private: - QSize sizeHint() const override; - QSize minimumSizeHint() const override; - void rowsInserted(const QModelIndex &parent, int start, int end) override; - QString askTagName(); -}; - -#endif // TAGFILTERWIDGET_H diff --git a/src/gui/thanks.html b/src/gui/thanks.html deleted file mode 100644 index 6a3b9fb31..000000000 --- a/src/gui/thanks.html +++ /dev/null @@ -1,15 +0,0 @@ - - - - - Thanks - - -

I would first like to thank sourceforge.net for hosting qBittorrent project and for their support.

-

I am pleased that people from all over the world are contributing to qBittorrent: Ishan Arora (India), Arnaud Demaizière (France) and Stephanos Antaris (Greece). Their help is greatly appreciated

-

I also want to thank Στέφανος Αντάρης (santaris@csd.auth.gr) and Mirco Chinelli (infinity89@fastwebmail.it) for working on Mac OS X packaging.

-

I am grateful to Peter Koeleman (peter@qbittorrent.org) and Mohammad Dib (mdib@qbittorrent.org) for working on qBittorrent port to Windows.

-

Thanks a lot to our graphist Mateusz Toboła (tobejodok@qbittorrent.org) for his great work.

-

Thanks to all contributors on GitHub.

- - diff --git a/src/gui/torrentcontentfiltermodel.cpp b/src/gui/torrentcontentfiltermodel.cpp deleted file mode 100644 index c765f2bd6..000000000 --- a/src/gui/torrentcontentfiltermodel.cpp +++ /dev/null @@ -1,145 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2006-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. - */ - -#include "torrentcontentfiltermodel.h" - -#include "base/utils/string.h" -#include "torrentcontentmodel.h" - -TorrentContentFilterModel::TorrentContentFilterModel(QObject *parent) - : QSortFilterProxyModel(parent) - , m_model(new TorrentContentModel(this)) -{ - connect(m_model, SIGNAL(filteredFilesChanged()), this, SIGNAL(filteredFilesChanged())); - setSourceModel(m_model); - // Filter settings - setFilterKeyColumn(TorrentContentModelItem::COL_NAME); - setFilterRole(Qt::DisplayRole); - setDynamicSortFilter(true); - setSortCaseSensitivity(Qt::CaseInsensitive); -} - -TorrentContentFilterModel::~TorrentContentFilterModel() -{ - delete m_model; -} - -TorrentContentModel *TorrentContentFilterModel::model() const -{ - return m_model; -} - -TorrentContentModelItem::ItemType TorrentContentFilterModel::itemType(const QModelIndex &index) const -{ - return m_model->itemType(mapToSource(index)); -} - -int TorrentContentFilterModel::getFileIndex(const QModelIndex &index) const -{ - return m_model->getFileIndex(mapToSource(index)); -} - -QModelIndex TorrentContentFilterModel::parent(const QModelIndex &child) const -{ - if (!child.isValid()) return QModelIndex(); - - QModelIndex sourceParent = m_model->parent(mapToSource(child)); - if (!sourceParent.isValid()) return QModelIndex(); - - return mapFromSource(sourceParent); -} - -bool TorrentContentFilterModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const -{ - if (m_model->itemType(m_model->index(sourceRow, 0, sourceParent)) == TorrentContentModelItem::FolderType) { - // accept folders if they have at least one filtered item - return hasFiltered(m_model->index(sourceRow, 0, sourceParent)); - } - - return QSortFilterProxyModel::filterAcceptsRow(sourceRow, sourceParent); -} - -bool TorrentContentFilterModel::lessThan(const QModelIndex &left, const QModelIndex &right) const -{ - switch (sortColumn()) { - case TorrentContentModelItem::COL_NAME: { - QString vL = left.data().toString(); - QString vR = right.data().toString(); - TorrentContentModelItem::ItemType leftType = m_model->itemType(m_model->index(left.row(), 0, left.parent())); - TorrentContentModelItem::ItemType rightType = m_model->itemType(m_model->index(right.row(), 0, right.parent())); - - if (leftType == rightType) - return Utils::String::naturalCompareCaseInsensitive(vL, vR); - else if ((leftType == TorrentContentModelItem::FolderType) && (sortOrder() == Qt::AscendingOrder)) - return true; - else - return false; - } - }; - - return QSortFilterProxyModel::lessThan(left, right); -} - -void TorrentContentFilterModel::selectAll() -{ - for (int i = 0; i < rowCount(); ++i) - setData(index(i, 0), Qt::Checked, Qt::CheckStateRole); - - emit dataChanged(index(0,0), index(rowCount(), columnCount())); -} - -void TorrentContentFilterModel::selectNone() -{ - for (int i = 0; i < rowCount(); ++i) - setData(index(i, 0), Qt::Unchecked, Qt::CheckStateRole); - - emit dataChanged(index(0,0), index(rowCount(), columnCount())); -} - -bool TorrentContentFilterModel::hasFiltered(const QModelIndex &folder) const -{ - // this should be called only with folders - // check if the folder name itself matches the filter string - QString name = folder.data().toString(); - if (name.contains(filterRegExp())) - return true; - for (int child = 0; child < m_model->rowCount(folder); child++) { - QModelIndex childIndex = m_model->index(child, 0, folder); - if (m_model->hasChildren(childIndex)) { - if (hasFiltered(childIndex)) - return true; - else - continue; - } - name = childIndex.data().toString(); - if (name.contains(filterRegExp())) - return true; - } - - return false; -} diff --git a/src/gui/torrentcontentfiltermodel.h b/src/gui/torrentcontentfiltermodel.h deleted file mode 100644 index ab9bd10d0..000000000 --- a/src/gui/torrentcontentfiltermodel.h +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2006-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. - */ - -#ifndef TORRENTCONTENTFILTERMODEL_H -#define TORRENTCONTENTFILTERMODEL_H - -#include - -#include "torrentcontentmodelitem.h" - -class TorrentContentModel; - -class TorrentContentFilterModel: public QSortFilterProxyModel -{ - Q_OBJECT - -public: - TorrentContentFilterModel(QObject *parent = 0); - virtual ~TorrentContentFilterModel(); - - TorrentContentModel *model() const; - TorrentContentModelItem::ItemType itemType(const QModelIndex &index) const; - int getFileIndex(const QModelIndex &index) const; - virtual QModelIndex parent(const QModelIndex &child) const; - -public slots: - void selectAll(); - void selectNone(); - -signals: - void filteredFilesChanged(); - -protected: - virtual bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const; - virtual bool lessThan(const QModelIndex &left, const QModelIndex &right) const; - -private: - TorrentContentModel *m_model; - bool hasFiltered(const QModelIndex &folder) const; -}; - -#endif // TORRENTCONTENTFILTERMODEL_H diff --git a/src/gui/torrentcontentmodel.cpp b/src/gui/torrentcontentmodel.cpp deleted file mode 100644 index e203701c7..000000000 --- a/src/gui/torrentcontentmodel.cpp +++ /dev/null @@ -1,498 +0,0 @@ -/* - * Bittorrent Client using Qt4 and libtorrent. - * Copyright (C) 2006-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 -#include -#include -#include - -#if defined(Q_OS_WIN) -#include -#include -#include -#elif defined(Q_OS_MAC) -#include -#include -#else -#include -#include -#endif - -#include "guiiconprovider.h" -#include "base/utils/misc.h" -#include "base/utils/fs.h" -#include "torrentcontentmodel.h" -#include "torrentcontentmodelitem.h" -#include "torrentcontentmodelfolder.h" -#include "torrentcontentmodelfile.h" - -#ifdef Q_OS_MAC -struct NSImage; -// This function is a private QtGui library export on macOS -// See src/gui/painting/qcoregraphics_p.h for more details -// QtMac::fromCGImageRef takes a CGImageRef and thus requires a double conversion -QPixmap qt_mac_toQPixmap(const NSImage *image, const QSizeF &size); -#endif - -namespace -{ - QIcon getDirectoryIcon() - { - static QIcon cached = GuiIconProvider::instance()->getIcon("inode-directory"); - return cached; - } - - class UnifiedFileIconProvider: public QFileIconProvider - { - public: - using QFileIconProvider::icon; - - QIcon icon(const QFileInfo &info) const override - { - Q_UNUSED(info); - static QIcon cached = GuiIconProvider::instance()->getIcon("text-plain"); - return cached; - } - }; -#if defined(Q_OS_WIN) - // See QTBUG-25319 for explanation why this is required - class WinShellFileIconProvider: public UnifiedFileIconProvider - { - public: - using QFileIconProvider::icon; - - QIcon icon(const QFileInfo &info) const override - { - SHFILEINFO sfi = { 0 }; - HRESULT hr = ::SHGetFileInfoW(info.absoluteFilePath().toStdWString().c_str(), - FILE_ATTRIBUTE_NORMAL, &sfi, sizeof(sfi), SHGFI_ICON | SHGFI_USEFILEATTRIBUTES); - if (FAILED(hr)) - return UnifiedFileIconProvider::icon(info); - - QPixmap iconPixmap = QtWin::fromHICON(sfi.hIcon); - ::DestroyIcon(sfi.hIcon); - return QIcon(iconPixmap); - } - }; -#elif defined(Q_OS_MAC) - // There is a similar bug on macOS, to be reported to Qt - // https://github.com/qbittorrent/qBittorrent/pull/6156#issuecomment-316302615 - class MacFileIconProvider: public UnifiedFileIconProvider - { - public: - using QFileIconProvider::icon; - - QIcon icon(const QFileInfo &info) const override - { - const QString ext = info.suffix(); - if (!ext.isEmpty()) { - const QPixmap pixmap = pixmapForExtension(ext, QSize(32, 32)); - if (!pixmap.isNull()) - return QIcon(pixmap); - } - - return UnifiedFileIconProvider::icon(info); - } - - private: - QPixmap pixmapForExtension(const QString &ext, const QSize &size) const - { - QMacAutoReleasePool pool; - objc_object *woskspaceCls = reinterpret_cast(objc_getClass("NSWorkspace")); - SEL sharedWorkspaceSel = sel_registerName("sharedWorkspace"); - SEL iconForFileTypeSel = sel_registerName("iconForFileType:"); - - objc_object *sharedWorkspace = objc_msgSend(woskspaceCls, sharedWorkspaceSel); - if (sharedWorkspace) { - objc_object *image = objc_msgSend(sharedWorkspace, iconForFileTypeSel, ext.toNSString()); - if (image) - return qt_mac_toQPixmap(reinterpret_cast(image), size); - } - - return QPixmap(); - } - }; -#else - /** - * @brief Tests whether QFileIconProvider actually works - * - * Some QPA plugins do not implement QPlatformTheme::fileIcon(), and - * QFileIconProvider::icon() returns empty icons as the result. Here we ask it for - * two icons for probably absent files and when both icons are null, we assume that - * the current QPA plugin does not implement QPlatformTheme::fileIcon(). - */ - bool doesQFileIconProviderWork() - { - QFileIconProvider provider; - const char PSEUDO_UNIQUE_FILE_NAME[] = "/tmp/qBittorrent-test-QFileIconProvider-845eb448-7ad5-4cdb-b764-b3f322a266a9"; - QIcon testIcon1 = provider.icon(QFileInfo( - QLatin1String(PSEUDO_UNIQUE_FILE_NAME) + QLatin1String(".pdf"))); - QIcon testIcon2 = provider.icon(QFileInfo( - QLatin1String(PSEUDO_UNIQUE_FILE_NAME) + QLatin1String(".png"))); - - return (!testIcon1.isNull() || !testIcon2.isNull()); - } - - class MimeFileIconProvider: public UnifiedFileIconProvider - { - using QFileIconProvider::icon; - - QIcon icon(const QFileInfo &info) const override - { - const QMimeType mimeType = m_db.mimeTypeForFile(info, QMimeDatabase::MatchExtension); - QIcon res = QIcon::fromTheme(mimeType.iconName()); - if (!res.isNull()) { - return res; - } - - res = QIcon::fromTheme(mimeType.genericIconName()); - if (!res.isNull()) { - return res; - } - - return UnifiedFileIconProvider::icon(info); - } - - private: - QMimeDatabase m_db; - }; -#endif -} - -TorrentContentModel::TorrentContentModel(QObject *parent) - : QAbstractItemModel(parent) - , m_rootItem(new TorrentContentModelFolder(QList({ tr("Name"), tr("Size"), tr("Progress"), tr("Download Priority"), tr("Remaining"), tr("Availability") }))) -{ -#if defined(Q_OS_WIN) - m_fileIconProvider = new WinShellFileIconProvider(); -#elif defined(Q_OS_MAC) - m_fileIconProvider = new MacFileIconProvider(); -#else - static bool doesBuiltInProviderWork = doesQFileIconProviderWork(); - m_fileIconProvider = doesBuiltInProviderWork ? new QFileIconProvider() : new MimeFileIconProvider(); -#endif -} - -TorrentContentModel::~TorrentContentModel() -{ - delete m_fileIconProvider; - delete m_rootItem; -} - -void TorrentContentModel::updateFilesProgress(const QVector &fp) -{ - Q_ASSERT(m_filesIndex.size() == fp.size()); - // XXX: Why is this necessary? - if (m_filesIndex.size() != fp.size()) return; - - emit layoutAboutToBeChanged(); - for (int i = 0; i < fp.size(); ++i) - m_filesIndex[i]->setProgress(fp[i]); - // Update folders progress in the tree - m_rootItem->recalculateProgress(); - m_rootItem->recalculateAvailability(); - emit dataChanged(index(0, 0), index(rowCount(), columnCount())); -} - -void TorrentContentModel::updateFilesPriorities(const QVector &fprio) -{ - Q_ASSERT(m_filesIndex.size() == fprio.size()); - // XXX: Why is this necessary? - if (m_filesIndex.size() != fprio.size()) - return; - - emit layoutAboutToBeChanged(); - for (int i = 0; i < fprio.size(); ++i) - m_filesIndex[i]->setPriority(fprio[i]); - emit dataChanged(index(0, 0), index(rowCount(), columnCount())); -} - -void TorrentContentModel::updateFilesAvailability(const QVector &fa) -{ - Q_ASSERT(m_filesIndex.size() == fa.size()); - // XXX: Why is this necessary? - if (m_filesIndex.size() != fa.size()) return; - - emit layoutAboutToBeChanged(); - for (int i = 0; i < fa.size(); ++i) - m_filesIndex[i]->setAvailability(fa[i]); - // Update folders progress in the tree - m_rootItem->recalculateProgress(); - emit dataChanged(index(0, 0), index(rowCount(), columnCount())); -} - -QVector TorrentContentModel::getFilePriorities() const -{ - QVector prio; - prio.reserve(m_filesIndex.size()); - foreach (const TorrentContentModelFile* file, m_filesIndex) - prio.push_back(file->priority()); - return prio; -} - -bool TorrentContentModel::allFiltered() const -{ - foreach (const TorrentContentModelFile* fileItem, m_filesIndex) - if (fileItem->priority() != prio::IGNORED) - return false; - return true; -} - -int TorrentContentModel::columnCount(const QModelIndex& parent) const -{ - if (parent.isValid()) - return static_cast(parent.internalPointer())->columnCount(); - else - return m_rootItem->columnCount(); -} - -bool TorrentContentModel::setData(const QModelIndex& index, const QVariant& value, int role) -{ - if (!index.isValid()) - return false; - - if ((index.column() == TorrentContentModelItem::COL_NAME) && (role == Qt::CheckStateRole)) { - TorrentContentModelItem *item = static_cast(index.internalPointer()); - qDebug("setData(%s, %d", qPrintable(item->name()), value.toInt()); - if (item->priority() != value.toInt()) { - if (value.toInt() == Qt::PartiallyChecked) - item->setPriority(prio::MIXED); - else if (value.toInt() == Qt::Unchecked) - item->setPriority(prio::IGNORED); - else - item->setPriority(prio::NORMAL); - // Update folders progress in the tree - m_rootItem->recalculateProgress(); - m_rootItem->recalculateAvailability(); - emit dataChanged(this->index(0, 0), this->index(rowCount() - 1, columnCount() - 1)); - emit filteredFilesChanged(); - } - return true; - } - - if (role == Qt::EditRole) { - Q_ASSERT(index.isValid()); - TorrentContentModelItem* item = static_cast(index.internalPointer()); - switch (index.column()) { - case TorrentContentModelItem::COL_NAME: - item->setName(value.toString()); - break; - case TorrentContentModelItem::COL_PRIO: - item->setPriority(value.toInt()); - break; - default: - return false; - } - emit dataChanged(index, index); - return true; - } - - return false; -} - -TorrentContentModelItem::ItemType TorrentContentModel::itemType(const QModelIndex& index) const -{ - return static_cast(index.internalPointer())->itemType(); -} - -int TorrentContentModel::getFileIndex(const QModelIndex& index) -{ - TorrentContentModelItem *item = static_cast(index.internalPointer()); - if (item->itemType() == TorrentContentModelItem::FileType) - return static_cast(item)->fileIndex(); - - Q_ASSERT(item->itemType() == TorrentContentModelItem::FileType); - return -1; -} - -QVariant TorrentContentModel::data(const QModelIndex& index, int role) const -{ - if (!index.isValid()) - return QVariant(); - - TorrentContentModelItem* item = static_cast(index.internalPointer()); - - if ((index.column() == TorrentContentModelItem::COL_NAME) && (role == Qt::DecorationRole)) { - if (item->itemType() == TorrentContentModelItem::FolderType) - return getDirectoryIcon(); - else - return m_fileIconProvider->icon(QFileInfo(item->name())); - } - - if ((index.column() == TorrentContentModelItem::COL_NAME) && (role == Qt::CheckStateRole)) { - if (item->data(TorrentContentModelItem::COL_PRIO).toInt() == prio::IGNORED) - return Qt::Unchecked; - if (item->data(TorrentContentModelItem::COL_PRIO).toInt() == prio::MIXED) - return Qt::PartiallyChecked; - return Qt::Checked; - } - - if (role == Qt::DisplayRole) - return item->data(index.column()); - - return QVariant(); -} - -Qt::ItemFlags TorrentContentModel::flags(const QModelIndex& index) const -{ - if (!index.isValid()) - return 0; - - if (itemType(index) == TorrentContentModelItem::FolderType) - return Qt::ItemIsEditable | Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsUserCheckable | Qt::ItemIsTristate; - - return Qt::ItemIsEditable | Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsUserCheckable; -} - -QVariant TorrentContentModel::headerData(int section, Qt::Orientation orientation, int role) const -{ - if ((orientation == Qt::Horizontal) && (role == Qt::DisplayRole)) - return m_rootItem->data(section); - - return QVariant(); -} - -QModelIndex TorrentContentModel::index(int row, int column, const QModelIndex& parent) const -{ - if (parent.isValid() && (parent.column() != 0)) - return QModelIndex(); - - if (column >= TorrentContentModelItem::NB_COL) - return QModelIndex(); - - TorrentContentModelFolder* parentItem; - if (!parent.isValid()) - parentItem = m_rootItem; - else - parentItem = static_cast(parent.internalPointer()); - Q_ASSERT(parentItem); - - if (row >= parentItem->childCount()) - return QModelIndex(); - - TorrentContentModelItem* childItem = parentItem->child(row); - if (childItem) - return createIndex(row, column, childItem); - return QModelIndex(); -} - -QModelIndex TorrentContentModel::parent(const QModelIndex& index) const -{ - if (!index.isValid()) - return QModelIndex(); - - TorrentContentModelItem* childItem = static_cast(index.internalPointer()); - if (!childItem) - return QModelIndex(); - - TorrentContentModelItem *parentItem = childItem->parent(); - if (parentItem == m_rootItem) - return QModelIndex(); - - return createIndex(parentItem->row(), 0, parentItem); -} - -int TorrentContentModel::rowCount(const QModelIndex& parent) const -{ - if (parent.column() > 0) - return 0; - - TorrentContentModelFolder* parentItem; - if (!parent.isValid()) - parentItem = m_rootItem; - else - parentItem = dynamic_cast(static_cast(parent.internalPointer())); - - return parentItem ? parentItem->childCount() : 0; -} - -void TorrentContentModel::clear() -{ - qDebug("clear called"); - beginResetModel(); - m_filesIndex.clear(); - m_rootItem->deleteAllChildren(); - endResetModel(); -} - -void TorrentContentModel::setupModelData(const BitTorrent::TorrentInfo &info) -{ - qDebug("setup model data called"); - const int filesCount = info.filesCount(); - if (filesCount <= 0) - return; - - emit layoutAboutToBeChanged(); - // Initialize files_index array - qDebug("Torrent contains %d files", filesCount); - m_filesIndex.reserve(filesCount); - - TorrentContentModelFolder* currentParent; - // Iterate over files - for (int i = 0; i < filesCount; ++i) { - currentParent = m_rootItem; - QString path = Utils::Fs::fromNativePath(info.filePath(i)); - // Iterate of parts of the path to create necessary folders - QStringList pathFolders = path.split("/", QString::SkipEmptyParts); - pathFolders.removeLast(); - foreach (const QString& pathPart, pathFolders) { - if (pathPart == ".unwanted") - continue; - TorrentContentModelFolder* newParent = currentParent->childFolderWithName(pathPart); - if (!newParent) { - newParent = new TorrentContentModelFolder(pathPart, currentParent); - currentParent->appendChild(newParent); - } - currentParent = newParent; - } - // Actually create the file - TorrentContentModelFile* fileItem = new TorrentContentModelFile(info.fileName(i), info.fileSize(i), currentParent, i); - currentParent->appendChild(fileItem); - m_filesIndex.push_back(fileItem); - } - emit layoutChanged(); -} - -void TorrentContentModel::selectAll() -{ - for (int i = 0; i < m_rootItem->childCount(); ++i) { - TorrentContentModelItem* child = m_rootItem->child(i); - if (child->priority() == prio::IGNORED) - child->setPriority(prio::NORMAL); - } - emit dataChanged(index(0, 0), index(rowCount(), columnCount())); -} - -void TorrentContentModel::selectNone() -{ - for (int i = 0; i < m_rootItem->childCount(); ++i) - m_rootItem->child(i)->setPriority(prio::IGNORED); - emit dataChanged(index(0, 0), index(rowCount(), columnCount())); -} diff --git a/src/gui/torrentcontentmodel.h b/src/gui/torrentcontentmodel.h deleted file mode 100644 index cd6ef3966..000000000 --- a/src/gui/torrentcontentmodel.h +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Bittorrent Client using Qt4 and libtorrent. - * Copyright (C) 2006-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 TORRENTCONTENTMODEL_H -#define TORRENTCONTENTMODEL_H - -#include -#include -#include -#include - -#include "base/bittorrent/torrentinfo.h" -#include "torrentcontentmodelitem.h" - -class QFileIconProvider; -class TorrentContentModelFile; - -class TorrentContentModel: public QAbstractItemModel -{ - Q_OBJECT - -public: - TorrentContentModel(QObject *parent = 0); - ~TorrentContentModel(); - - void updateFilesProgress(const QVector &fp); - void updateFilesPriorities(const QVector &fprio); - void updateFilesAvailability(const QVector &fa); - QVector getFilePriorities() const; - bool allFiltered() const; - int columnCount(const QModelIndex &parent = QModelIndex()) const override; - bool setData(const QModelIndex& index, const QVariant& value, int role = Qt::EditRole) override; - TorrentContentModelItem::ItemType itemType(const QModelIndex& index) const; - int getFileIndex(const QModelIndex& index); - QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; - Qt::ItemFlags flags(const QModelIndex& index) const override; - QVariant headerData(int section, Qt::Orientation orientation, int role) const override; - QModelIndex index(int row, int column, const QModelIndex& parent = QModelIndex()) const override; - QModelIndex parent(const QModelIndex& index) const override; - int rowCount(const QModelIndex& parent = QModelIndex()) const override; - void clear(); - void setupModelData(const BitTorrent::TorrentInfo &info); - -signals: - void filteredFilesChanged(); - -public slots: - void selectAll(); - void selectNone(); - -private: - TorrentContentModelFolder *m_rootItem; - QVector m_filesIndex; - QFileIconProvider *m_fileIconProvider; -}; - -#endif // TORRENTCONTENTMODEL_H diff --git a/src/gui/torrentcontentmodelfile.cpp b/src/gui/torrentcontentmodelfile.cpp deleted file mode 100644 index 62c925428..000000000 --- a/src/gui/torrentcontentmodelfile.cpp +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Bittorrent Client using Qt4 and libtorrent. - * Copyright (C) 2006-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 "torrentcontentmodelfile.h" - -#include "base/bittorrent/torrenthandle.h" -#include "torrentcontentmodelfolder.h" - -TorrentContentModelFile::TorrentContentModelFile(const QString &fileName, qulonglong fileSize, - TorrentContentModelFolder *parent, int fileIndex) - : TorrentContentModelItem(parent) - , m_fileIndex(fileIndex) -{ - Q_ASSERT(parent); - - m_name = fileName; - - // Do not display incomplete extensions - if (m_name.endsWith(QB_EXT)) - m_name.chop(4); - - m_size = fileSize; -} - -int TorrentContentModelFile::fileIndex() const -{ - return m_fileIndex; -} - -void TorrentContentModelFile::setPriority(int newPriority, bool updateParent) -{ - Q_ASSERT(newPriority != prio::MIXED); - - if (m_priority == newPriority) - return; - - m_priority = newPriority; - - // Update parent - if (updateParent) - m_parentItem->updatePriority(); -} - -void TorrentContentModelFile::setProgress(qreal progress) -{ - m_progress = progress; - m_remaining = static_cast(m_size * (1.0 - m_progress)); - Q_ASSERT(m_progress <= 1.); -} - -void TorrentContentModelFile::setAvailability(qreal availability) -{ - m_availability = availability; - Q_ASSERT(m_availability <= 1.); -} - -TorrentContentModelItem::ItemType TorrentContentModelFile::itemType() const -{ - return FileType; -} diff --git a/src/gui/torrentcontentmodelfile.h b/src/gui/torrentcontentmodelfile.h deleted file mode 100644 index f6d73e51a..000000000 --- a/src/gui/torrentcontentmodelfile.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Bittorrent Client using Qt4 and libtorrent. - * Copyright (C) 2006-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 TORRENTCONTENTMODELFILE_H -#define TORRENTCONTENTMODELFILE_H - -#include "torrentcontentmodelitem.h" - -class TorrentContentModelFile: public TorrentContentModelItem -{ -public: - TorrentContentModelFile(const QString &fileName, qulonglong fileSize, - TorrentContentModelFolder *parent, int fileIndex); - - int fileIndex() const; - void setPriority(int newPriority, bool updateParent = true) override; - void setProgress(qreal progress); - void setAvailability(qreal availability); - ItemType itemType() const override; - -private: - int m_fileIndex; -}; - -#endif // TORRENTCONTENTMODELFILE_H diff --git a/src/gui/torrentcontentmodelfolder.cpp b/src/gui/torrentcontentmodelfolder.cpp deleted file mode 100644 index b74f89ded..000000000 --- a/src/gui/torrentcontentmodelfolder.cpp +++ /dev/null @@ -1,198 +0,0 @@ -/* - * Bittorrent Client using Qt4 and libtorrent. - * Copyright (C) 2006-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 "torrentcontentmodelfolder.h" - -#include "base/bittorrent/torrenthandle.h" - -TorrentContentModelFolder::TorrentContentModelFolder(const QString &name, TorrentContentModelFolder *parent) - : TorrentContentModelItem(parent) -{ - Q_ASSERT(parent); - m_name = name; - // Do not display incomplete extensions - if (m_name.endsWith(QB_EXT)) - m_name.chop(4); -} - -TorrentContentModelFolder::TorrentContentModelFolder(const QList &data) - : TorrentContentModelItem(0) -{ - Q_ASSERT(data.size() == NB_COL); - m_itemData = data; -} - -TorrentContentModelFolder::~TorrentContentModelFolder() -{ - qDeleteAll(m_childItems); -} - -TorrentContentModelItem::ItemType TorrentContentModelFolder::itemType() const -{ - return FolderType; -} - -void TorrentContentModelFolder::deleteAllChildren() -{ - Q_ASSERT(isRootItem()); - qDeleteAll(m_childItems); - m_childItems.clear(); -} - -const QList &TorrentContentModelFolder::children() const -{ - return m_childItems; -} - -void TorrentContentModelFolder::appendChild(TorrentContentModelItem *item) -{ - Q_ASSERT(item); - m_childItems.append(item); - // Update own size - if (item->itemType() == FileType) - increaseSize(item->size()); -} - -TorrentContentModelItem *TorrentContentModelFolder::child(int row) const -{ - return m_childItems.value(row, 0); -} - -TorrentContentModelFolder *TorrentContentModelFolder::childFolderWithName(const QString &name) const -{ - foreach (TorrentContentModelItem *child, m_childItems) - if ((child->itemType() == FolderType) && (child->name() == name)) - return static_cast(child); - return 0; -} - -int TorrentContentModelFolder::childCount() const -{ - return m_childItems.count(); -} - -// Only non-root folders use this function -void TorrentContentModelFolder::updatePriority() -{ - if (isRootItem()) - return; - - Q_ASSERT(!m_childItems.isEmpty()); - - // If all children have the same priority - // then the folder should have the same - // priority - const int prio = m_childItems.first()->priority(); - for (int i = 1; i < m_childItems.size(); ++i) { - if (m_childItems.at(i)->priority() != prio) { - setPriority(prio::MIXED); - return; - } - } - // All child items have the same priority - // Update own if necessary - setPriority(prio); -} - -void TorrentContentModelFolder::setPriority(int newPriority, bool updateParent) -{ - if (m_priority == newPriority) - return; - - m_priority = newPriority; - - // Update parent priority - if (updateParent) - m_parentItem->updatePriority(); - - // Update children - if (m_priority != prio::MIXED) - foreach (TorrentContentModelItem *child, m_childItems) - child->setPriority(m_priority, false); -} - -void TorrentContentModelFolder::recalculateProgress() -{ - qreal tProgress = 0; - qulonglong tSize = 0; - qulonglong tRemaining = 0; - foreach (TorrentContentModelItem *child, m_childItems) { - if (child->priority() != prio::IGNORED) { - if (child->itemType() == FolderType) - static_cast(child)->recalculateProgress(); - tProgress += child->progress() * child->size(); - tSize += child->size(); - tRemaining += child->remaining(); - } - } - - if (!isRootItem() && (tSize > 0)) { - m_progress = tProgress / tSize; - m_remaining = tRemaining; - Q_ASSERT(m_progress <= 1.); - } -} - -void TorrentContentModelFolder::recalculateAvailability() -{ - qreal tAvailability = 0; - qulonglong tSize = 0; - bool foundAnyData = false; - foreach (TorrentContentModelItem* child, m_childItems) { - if (child->priority() == prio::IGNORED) - continue; - - if (child->itemType() == FolderType) - static_cast(child)->recalculateAvailability(); - const qreal childAvailability = child->availability(); - if (childAvailability >= 0) { // -1 means "no data" - tAvailability += childAvailability * child->size(); - foundAnyData = true; - } - tSize += child->size(); - } - - if (!isRootItem() && (tSize > 0) && foundAnyData) { - m_availability = tAvailability / tSize; - Q_ASSERT(m_availability <= 1.); - } - else { - m_availability = -1.; - } -} - -void TorrentContentModelFolder::increaseSize(qulonglong delta) -{ - if (isRootItem()) - return; - - m_size += delta; - m_parentItem->increaseSize(delta); -} diff --git a/src/gui/torrentcontentmodelfolder.h b/src/gui/torrentcontentmodelfolder.h deleted file mode 100644 index e136c9a2e..000000000 --- a/src/gui/torrentcontentmodelfolder.h +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Bittorrent Client using Qt4 and libtorrent. - * Copyright (C) 2006-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 TORRENTCONTENTMODELFOLDER_H -#define TORRENTCONTENTMODELFOLDER_H - -#include "torrentcontentmodelitem.h" - -class TorrentContentModelFolder: public TorrentContentModelItem -{ -public: - // Folder constructor - TorrentContentModelFolder(const QString& name, TorrentContentModelFolder* parent); - - // Invisible root item constructor - TorrentContentModelFolder(const QList& data); - - ~TorrentContentModelFolder(); - - ItemType itemType() const override; - - void increaseSize(qulonglong delta); - void recalculateProgress(); - void recalculateAvailability(); - void updatePriority(); - - void setPriority(int newPriority, bool updateParent = true) override; - - void deleteAllChildren(); - const QList& children() const; - void appendChild(TorrentContentModelItem* item); - TorrentContentModelItem* child(int row) const; - TorrentContentModelFolder* childFolderWithName(const QString& name) const; - int childCount() const; - -private: - QList m_childItems; -}; - -#endif // TORRENTCONTENTMODELFOLDER_H diff --git a/src/gui/torrentcontentmodelitem.cpp b/src/gui/torrentcontentmodelitem.cpp deleted file mode 100644 index 15a1988db..000000000 --- a/src/gui/torrentcontentmodelitem.cpp +++ /dev/null @@ -1,141 +0,0 @@ -/* - * Bittorrent Client using Qt4 and libtorrent. - * Copyright (C) 2006-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 "base/utils/misc.h" -#include "base/utils/fs.h" -#include "torrentcontentmodelitem.h" -#include "torrentcontentmodelfolder.h" -#include - -TorrentContentModelItem::TorrentContentModelItem(TorrentContentModelFolder *parent) - : m_parentItem(parent) - , m_size(0) - , m_remaining(0) - , m_priority(prio::NORMAL) - , m_progress(0) - , m_availability(-1.) -{ -} - -TorrentContentModelItem::~TorrentContentModelItem() = default; - -bool TorrentContentModelItem::isRootItem() const -{ - return !m_parentItem; -} - -QString TorrentContentModelItem::name() const -{ - Q_ASSERT(!isRootItem()); - return m_name; -} - -void TorrentContentModelItem::setName(const QString &name) -{ - Q_ASSERT(!isRootItem()); - m_name = name; -} - -qulonglong TorrentContentModelItem::size() const -{ - Q_ASSERT(!isRootItem()); - - return m_size; -} - -qreal TorrentContentModelItem::progress() const -{ - Q_ASSERT(!isRootItem()); - - if (m_size > 0) return m_progress; - - return 1; -} - -qulonglong TorrentContentModelItem::remaining() const -{ - Q_ASSERT(!isRootItem()); - return m_remaining; -} - -qreal TorrentContentModelItem::availability() const -{ - Q_ASSERT(!isRootItem()); - - return m_size > 0 ? m_availability : 0.; -} - -int TorrentContentModelItem::priority() const -{ - Q_ASSERT(!isRootItem()); - return m_priority; -} - -int TorrentContentModelItem::columnCount() const -{ - return NB_COL; -} - -QVariant TorrentContentModelItem::data(int column) const -{ - if (isRootItem()) - return m_itemData.value(column); - - switch (column) { - case COL_NAME: - return m_name; - case COL_PRIO: - return m_priority; - case COL_PROGRESS: - return progress(); - case COL_SIZE: - return m_size; - case COL_REMAINING: - return remaining(); - case COL_AVAILABILITY: - return availability(); - default: - Q_ASSERT(false); - return QVariant(); - } -} - -int TorrentContentModelItem::row() const -{ - if (m_parentItem) - return m_parentItem->children().indexOf(const_cast(this)); - return 0; -} - -TorrentContentModelFolder *TorrentContentModelItem::parent() const -{ - return m_parentItem; -} - diff --git a/src/gui/torrentcontentmodelitem.h b/src/gui/torrentcontentmodelitem.h deleted file mode 100644 index 115dd76c2..000000000 --- a/src/gui/torrentcontentmodelitem.h +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Bittorrent Client using Qt4 and libtorrent. - * Copyright (C) 2006-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 TORRENTCONTENTMODELITEM_H -#define TORRENTCONTENTMODELITEM_H - -#include -#include - -namespace prio -{ - enum FilePriority - { - IGNORED=0, - NORMAL=1, - HIGH=6, - MAXIMUM=7, - MIXED=-1 - }; -} - -class TorrentContentModelFolder; - -class TorrentContentModelItem -{ -public: - enum TreeItemColumns - { - COL_NAME, - COL_SIZE, - COL_PROGRESS, - COL_PRIO, - COL_REMAINING, - COL_AVAILABILITY, - NB_COL - }; - - enum ItemType - { - FileType, - FolderType - }; - - TorrentContentModelItem(TorrentContentModelFolder *parent); - virtual ~TorrentContentModelItem(); - - bool isRootItem() const; - TorrentContentModelFolder *parent() const; - virtual ItemType itemType() const = 0; - - QString name() const; - void setName(const QString &name); - - qulonglong size() const; - qreal progress() const; - qulonglong remaining() const; - - qreal availability() const; - - int priority() const; - virtual void setPriority(int newPriority, bool updateParent = true) = 0; - - int columnCount() const; - QVariant data(int column) const; - int row() const; - -protected: - TorrentContentModelFolder *m_parentItem; - // Root item members - QList m_itemData; - // Non-root item members - QString m_name; - qulonglong m_size; - qulonglong m_remaining; - int m_priority; - qreal m_progress; - qreal m_availability; -}; - -#endif // TORRENTCONTENTMODELITEM_H diff --git a/src/gui/torrentcontenttreeview.cpp b/src/gui/torrentcontenttreeview.cpp deleted file mode 100644 index 574ab7bf7..000000000 --- a/src/gui/torrentcontenttreeview.cpp +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2014 Ivan Sorokin - * - * 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. - */ - -#include "torrentcontenttreeview.h" - -#include -#include -#include -#include - -#include "torrentcontentmodelitem.h" - -TorrentContentTreeView::TorrentContentTreeView(QWidget *parent) - : QTreeView(parent) -{ - // This hack fixes reordering of first column with Qt5. - // https://github.com/qtproject/qtbase/commit/e0fc088c0c8bc61dbcaf5928b24986cd61a22777 - QTableView unused; - unused.setVerticalHeader(header()); - header()->setParent(this); - unused.setVerticalHeader(new QHeaderView(Qt::Horizontal)); -} - -void TorrentContentTreeView::keyPressEvent(QKeyEvent *event) -{ - if ((event->key() != Qt::Key_Space) && (event->key() != Qt::Key_Select)) { - QTreeView::keyPressEvent(event); - return; - } - - event->accept(); - - QModelIndex current = currentNameCell(); - - QVariant value = current.data(Qt::CheckStateRole); - if (!value.isValid()) { - Q_ASSERT(false); - return; - } - - Qt::CheckState state = (static_cast(value.toInt()) == Qt::Checked - ? Qt::Unchecked : Qt::Checked); - - QModelIndexList selection = selectionModel()->selectedRows(TorrentContentModelItem::COL_NAME); - - for (QModelIndexList::const_iterator i = selection.begin(); i != selection.end(); ++i) { - QModelIndex index = *i; - Q_ASSERT(i->column() == TorrentContentModelItem::COL_NAME); - model()->setData(index, state, Qt::CheckStateRole); - } -} - -QModelIndex TorrentContentTreeView::currentNameCell() -{ - QModelIndex current = currentIndex(); - if (!current.isValid()) { - Q_ASSERT(false); - return QModelIndex(); - } - - return model()->index(current.row(), TorrentContentModelItem::COL_NAME, current.parent()); -} diff --git a/src/gui/torrentcontenttreeview.h b/src/gui/torrentcontenttreeview.h deleted file mode 100644 index 0da6614fc..000000000 --- a/src/gui/torrentcontenttreeview.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2014 Ivan Sorokin - * - * 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. - */ - -#ifndef TORRENTCONTENTTREEVIEW_H -#define TORRENTCONTENTTREEVIEW_H - -#include - -class TorrentContentTreeView: public QTreeView -{ - Q_OBJECT - -public: - explicit TorrentContentTreeView(QWidget *parent = 0); - void keyPressEvent(QKeyEvent *event); - -private: - QModelIndex currentNameCell(); -}; - -#endif // TORRENTCONTENTTREEVIEW_H diff --git a/src/gui/torrentcreatordlg.cpp b/src/gui/torrentcreatordlg.cpp deleted file mode 100644 index 5f26c1aeb..000000000 --- a/src/gui/torrentcreatordlg.cpp +++ /dev/null @@ -1,266 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2017 Mike Tzou (Chocobo1) - * Copyright (C) 2010 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. - */ - -#include "torrentcreatordlg.h" - -#include -#include -#include -#include -#include -#include - -#include "base/bittorrent/session.h" -#include "base/bittorrent/torrentcreatorthread.h" -#include "base/bittorrent/torrentinfo.h" -#include "base/global.h" -#include "base/utils/fs.h" - -#include "ui_torrentcreatordlg.h" - -#define SETTINGS_KEY(name) "TorrentCreator/" name - -TorrentCreatorDlg::TorrentCreatorDlg(QWidget *parent, const QString &defaultPath) - : QDialog(parent) - , m_ui(new Ui::TorrentCreatorDlg) - , m_creatorThread(new BitTorrent::TorrentCreatorThread(this)) - , m_storeDialogSize(SETTINGS_KEY("Dimension")) - , m_storePieceSize(SETTINGS_KEY("PieceSize")) - , m_storePrivateTorrent(SETTINGS_KEY("PrivateTorrent")) - , m_storeStartSeeding(SETTINGS_KEY("StartSeeding")) - , m_storeIgnoreRatio(SETTINGS_KEY("IgnoreRatio")) - , m_storeLastAddPath(SETTINGS_KEY("LastAddPath"), QDir::homePath()) - , m_storeTrackerList(SETTINGS_KEY("TrackerList")) - , m_storeWebSeedList(SETTINGS_KEY("WebSeedList")) - , m_storeComments(SETTINGS_KEY("Comments")) - , m_storeLastSavePath(SETTINGS_KEY("LastSavePath"), QDir::homePath()) -{ - m_ui->setupUi(this); - setAttribute(Qt::WA_DeleteOnClose); - setModal(false); - - m_ui->buttonBox->button(QDialogButtonBox::Ok)->setText(tr("Create Torrent")); - - connect(m_ui->addFileButton, SIGNAL(clicked(bool)), SLOT(onAddFileButtonClicked())); - connect(m_ui->addFolderButton, SIGNAL(clicked(bool)), SLOT(onAddFolderButtonClicked())); - connect(m_ui->buttonBox, SIGNAL(accepted()), SLOT(onCreateButtonClicked())); - connect(m_ui->buttonCalcTotalPieces, &QAbstractButton::clicked, this, &TorrentCreatorDlg::updatePiecesCount); - - connect(m_creatorThread, SIGNAL(creationSuccess(QString, QString)), this, SLOT(handleCreationSuccess(QString, QString))); - connect(m_creatorThread, SIGNAL(creationFailure(QString)), this, SLOT(handleCreationFailure(QString))); - connect(m_creatorThread, SIGNAL(updateProgress(int)), this, SLOT(updateProgressBar(int))); - - loadSettings(); - updateInputPath(defaultPath); - - show(); -} - -TorrentCreatorDlg::~TorrentCreatorDlg() -{ - saveSettings(); - - if (m_creatorThread) - delete m_creatorThread; - - delete m_ui; -} - -void TorrentCreatorDlg::updateInputPath(const QString &path) -{ - if (path.isEmpty()) return; - m_ui->textInputPath->setText(Utils::Fs::toNativePath(path)); - updateProgressBar(0); -} - -void TorrentCreatorDlg::onAddFolderButtonClicked() -{ - QString oldPath = m_ui->textInputPath->text(); - QString path = QFileDialog::getExistingDirectory(this, tr("Select folder"), oldPath); - updateInputPath(path); -} - -void TorrentCreatorDlg::onAddFileButtonClicked() -{ - QString oldPath = m_ui->textInputPath->text(); - QString path = QFileDialog::getOpenFileName(this, tr("Select file"), oldPath); - updateInputPath(path); -} - -int TorrentCreatorDlg::getPieceSize() const -{ - const int pieceSizes[] = {0, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384}; // base unit in KiB - return pieceSizes[m_ui->comboPieceSize->currentIndex()] * 1024; -} - -void TorrentCreatorDlg::dropEvent(QDropEvent *event) -{ - event->acceptProposedAction(); - - if (event->mimeData()->hasUrls()) { - // only take the first one - QUrl firstItem = event->mimeData()->urls().first(); - QString path = (firstItem.scheme().compare("file", Qt::CaseInsensitive) == 0) - ? firstItem.toLocalFile() : firstItem.toString(); - updateInputPath(path); - } -} - -void TorrentCreatorDlg::dragEnterEvent(QDragEnterEvent *event) -{ - if (event->mimeData()->hasFormat("text/plain") || event->mimeData()->hasFormat("text/uri-list")) - event->acceptProposedAction(); -} - -// Main function that create a .torrent file -void TorrentCreatorDlg::onCreateButtonClicked() -{ - QString input = Utils::Fs::fromNativePath(m_ui->textInputPath->text()).trimmed(); - - // test if readable - const QFileInfo fi(input); - if (!fi.isReadable()) { - QMessageBox::critical(this, tr("Torrent creator failed"), tr("Reason: Path to file/folder is not readable.")); - return; - } - input = fi.canonicalFilePath(); - - // get save path - const QString savePath = QString(m_storeLastSavePath) + QLatin1Char('/') + fi.fileName() + QLatin1String(".torrent"); - QString destination = QFileDialog::getSaveFileName(this, tr("Select where to save the new torrent"), savePath, tr("Torrent Files (*.torrent)")); - if (destination.isEmpty()) - return; - if (!destination.endsWith(C_TORRENT_FILE_EXTENSION, Qt::CaseInsensitive)) - destination += C_TORRENT_FILE_EXTENSION; - m_storeLastSavePath = Utils::Fs::branchPath(destination); - - // Disable dialog & set busy cursor - setInteractionEnabled(false); - setCursor(QCursor(Qt::WaitCursor)); - - QStringList trackers = m_ui->trackersList->toPlainText().split("\n"); - QStringList urlSeeds = m_ui->URLSeedsList->toPlainText().split("\n"); - QString comment = m_ui->txtComment->toPlainText(); - - // run the creator thread - m_creatorThread->create(input, destination, trackers, urlSeeds, comment, m_ui->checkPrivate->isChecked(), getPieceSize()); -} - -void TorrentCreatorDlg::handleCreationFailure(const QString &msg) -{ - // Remove busy cursor - setCursor(QCursor(Qt::ArrowCursor)); - QMessageBox::information(this, tr("Torrent creator failed"), tr("Reason: %1").arg(msg)); - setInteractionEnabled(true); -} - -void TorrentCreatorDlg::handleCreationSuccess(const QString &path, const QString &branchPath) -{ - // Remove busy cursor - setCursor(QCursor(Qt::ArrowCursor)); - if (m_ui->checkStartSeeding->isChecked()) { - // Create save path temp data - BitTorrent::TorrentInfo t = BitTorrent::TorrentInfo::loadFromFile(Utils::Fs::toNativePath(path)); - if (!t.isValid()) { - QMessageBox::critical(this, tr("Torrent creator failed"), tr("Reason: Created torrent is invalid. It won't be added to download list.")); - return; - } - - BitTorrent::AddTorrentParams params; - params.savePath = branchPath; - params.skipChecking = true; - params.ignoreShareLimits = m_ui->checkIgnoreShareLimits->isChecked(); - - BitTorrent::Session::instance()->addTorrent(t, params); - } - QMessageBox::information(this, tr("Torrent creator"), QString("%1\n%2").arg(tr("Create torrent success:")).arg(Utils::Fs::toNativePath(path))); - setInteractionEnabled(true); -} - -void TorrentCreatorDlg::updateProgressBar(int progress) -{ - m_ui->progressBar->setValue(progress); -} - -void TorrentCreatorDlg::updatePiecesCount() -{ - const QString path = m_ui->textInputPath->text().trimmed(); - - const int count = BitTorrent::TorrentCreatorThread::calculateTotalPieces(path, getPieceSize()); - m_ui->labelTotalPieces->setText(QString::number(count)); -} - -void TorrentCreatorDlg::setInteractionEnabled(bool enabled) -{ - m_ui->textInputPath->setEnabled(enabled); - m_ui->addFileButton->setEnabled(enabled); - m_ui->addFolderButton->setEnabled(enabled); - m_ui->trackersList->setEnabled(enabled); - m_ui->URLSeedsList->setEnabled(enabled); - m_ui->txtComment->setEnabled(enabled); - m_ui->comboPieceSize->setEnabled(enabled); - m_ui->checkPrivate->setEnabled(enabled); - m_ui->checkStartSeeding->setEnabled(enabled); - m_ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(enabled); - m_ui->checkIgnoreShareLimits->setEnabled(enabled && m_ui->checkStartSeeding->isChecked()); -} - -void TorrentCreatorDlg::saveSettings() -{ - m_storeLastAddPath = m_ui->textInputPath->text().trimmed(); - - m_storePieceSize = m_ui->comboPieceSize->currentIndex(); - m_storePrivateTorrent = m_ui->checkPrivate->isChecked(); - m_storeStartSeeding = m_ui->checkStartSeeding->isChecked(); - m_storeIgnoreRatio = m_ui->checkIgnoreShareLimits->isChecked(); - - m_storeTrackerList = m_ui->trackersList->toPlainText(); - m_storeWebSeedList = m_ui->URLSeedsList->toPlainText(); - m_storeComments = m_ui->txtComment->toPlainText(); - - m_storeDialogSize = size(); -} - -void TorrentCreatorDlg::loadSettings() -{ - m_ui->textInputPath->setText(m_storeLastAddPath); - - m_ui->comboPieceSize->setCurrentIndex(m_storePieceSize); - m_ui->checkPrivate->setChecked(m_storePrivateTorrent); - m_ui->checkStartSeeding->setChecked(m_storeStartSeeding); - m_ui->checkIgnoreShareLimits->setChecked(m_storeIgnoreRatio); - m_ui->checkIgnoreShareLimits->setEnabled(m_ui->checkStartSeeding->isChecked()); - - m_ui->trackersList->setPlainText(m_storeTrackerList); - m_ui->URLSeedsList->setPlainText(m_storeWebSeedList); - m_ui->txtComment->setPlainText(m_storeComments); - - if (m_storeDialogSize.value().isValid()) - resize(m_storeDialogSize); -} diff --git a/src/gui/torrentcreatordlg.h b/src/gui/torrentcreatordlg.h deleted file mode 100644 index f8235fe67..000000000 --- a/src/gui/torrentcreatordlg.h +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2017 Mike Tzou (Chocobo1) - * Copyright (C) 2010 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. - */ - -#ifndef TORRENTCREATORDLG_H -#define TORRENTCREATORDLG_H - -#include - -#include "base/settingvalue.h" - -namespace Ui -{ - class TorrentCreatorDlg; -} - -namespace BitTorrent -{ - class TorrentCreatorThread; -} - -class TorrentCreatorDlg: public QDialog -{ - Q_OBJECT - -public: - TorrentCreatorDlg(QWidget *parent = 0, const QString &defaultPath = QString()); - ~TorrentCreatorDlg(); - void updateInputPath(const QString &path); - -private slots: - void updateProgressBar(int progress); - void updatePiecesCount(); - void onCreateButtonClicked(); - void onAddFileButtonClicked(); - void onAddFolderButtonClicked(); - void handleCreationFailure(const QString &msg); - void handleCreationSuccess(const QString &path, const QString &branchPath); - -private: - void dropEvent(QDropEvent *event) override; - void dragEnterEvent(QDragEnterEvent *event) override; - - void saveSettings(); - void loadSettings(); - int getPieceSize() const; - void setInteractionEnabled(bool enabled); - - Ui::TorrentCreatorDlg *m_ui; - BitTorrent::TorrentCreatorThread *m_creatorThread; - - // settings - CachedSettingValue m_storeDialogSize; - CachedSettingValue m_storePieceSize; - CachedSettingValue m_storePrivateTorrent; - CachedSettingValue m_storeStartSeeding; - CachedSettingValue m_storeIgnoreRatio; - CachedSettingValue m_storeLastAddPath; - CachedSettingValue m_storeTrackerList; - CachedSettingValue m_storeWebSeedList; - CachedSettingValue m_storeComments; - CachedSettingValue m_storeLastSavePath; -}; - -#endif diff --git a/src/gui/torrentcreatordlg.ui b/src/gui/torrentcreatordlg.ui deleted file mode 100644 index 29b6162ee..000000000 --- a/src/gui/torrentcreatordlg.ui +++ /dev/null @@ -1,356 +0,0 @@ - - - TorrentCreatorDlg - - - - 0 - 0 - 592 - 658 - - - - true - - - Torrent Creator - - - - - - Select file/folder to share - - - - - - - - Path: - - - - - - - false - - - - - - - - - - - false - - - - 0 - 0 - - - - [Drag and drop area] - - - Qt::AlignCenter - - - - - - - Select file - - - - - - - Select folder - - - - - - - - - - - - Settings - - - - - - - - Piece size: - - - - - - - 0 - - - 7 - - - - Auto - - - - - 16 KiB - - - - - 32 KiB - - - - - 64 KiB - - - - - 128 KiB - - - - - 256 KiB - - - - - 512 KiB - - - - - 1 MiB - - - - - 2 MiB - - - - - 4 MiB - - - - - 8 MiB - - - - - 16 MiB - - - - - - - - Calculate total pieces: - - - - - - - 0 - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - Private torrent (Won't distribute on DHT network) - - - - - - - Start seeding immediately - - - true - - - - - - - Ignore share ratio limits for this torrent - - - - - - - - - - Fields - - - - - - You can separate tracker tiers / groups with an empty line. - - - false - - - - - - - Web seed URLs: - - - - - - - false - - - - - - - false - - - - - - - Tracker URLs: - - - - - - - Comments: - - - - - - - - - - - - Progress: - - - - - - - 0 - - - - - - - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - true - - - - - - - textInputPath - addFileButton - addFolderButton - comboPieceSize - checkPrivate - checkStartSeeding - checkIgnoreShareLimits - trackersList - URLSeedsList - txtComment - - - - - checkStartSeeding - clicked(bool) - checkIgnoreShareLimits - setEnabled(bool) - - - 295 - 532 - - - 295 - 555 - - - - - buttonBox - rejected() - TorrentCreatorDlg - reject() - - - 295 - 635 - - - 295 - 328 - - - - - diff --git a/src/gui/torrentmodel.cpp b/src/gui/torrentmodel.cpp deleted file mode 100644 index 4feef0897..000000000 --- a/src/gui/torrentmodel.cpp +++ /dev/null @@ -1,478 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2015 Vladimir Golovnev - * Copyright (C) 2010 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 -#include -#include -#include - -#include "base/bittorrent/session.h" -#include "base/bittorrent/torrenthandle.h" -#include "base/torrentfilter.h" -#include "base/utils/fs.h" -#include "torrentmodel.h" - -static QIcon getIconByState(BitTorrent::TorrentState state); -static QColor getColorByState(BitTorrent::TorrentState state); - -static QIcon getPausedIcon(); -static QIcon getQueuedIcon(); -static QIcon getDownloadingIcon(); -static QIcon getStalledDownloadingIcon(); -static QIcon getUploadingIcon(); -static QIcon getStalledUploadingIcon(); -static QIcon getCompletedIcon(); -static QIcon getCheckingIcon(); -static QIcon getErrorIcon(); - -static bool isDarkTheme(); - -// TorrentModel - -TorrentModel::TorrentModel(QObject *parent) - : QAbstractListModel(parent) -{ - // Load the torrents - foreach (BitTorrent::TorrentHandle *const torrent, BitTorrent::Session::instance()->torrents()) - addTorrent(torrent); - - // Listen for torrent changes - connect(BitTorrent::Session::instance(), SIGNAL(torrentAdded(BitTorrent::TorrentHandle * const)), SLOT(addTorrent(BitTorrent::TorrentHandle * const))); - connect(BitTorrent::Session::instance(), SIGNAL(torrentAboutToBeRemoved(BitTorrent::TorrentHandle * const)), SLOT(handleTorrentAboutToBeRemoved(BitTorrent::TorrentHandle * const))); - connect(BitTorrent::Session::instance(), SIGNAL(torrentsUpdated()), SLOT(handleTorrentsUpdated())); - - connect(BitTorrent::Session::instance(), SIGNAL(torrentFinished(BitTorrent::TorrentHandle * const)), SLOT(handleTorrentStatusUpdated(BitTorrent::TorrentHandle * const))); - connect(BitTorrent::Session::instance(), SIGNAL(torrentMetadataLoaded(BitTorrent::TorrentHandle * const)), SLOT(handleTorrentStatusUpdated(BitTorrent::TorrentHandle * const))); - connect(BitTorrent::Session::instance(), SIGNAL(torrentResumed(BitTorrent::TorrentHandle * const)), SLOT(handleTorrentStatusUpdated(BitTorrent::TorrentHandle * const))); - connect(BitTorrent::Session::instance(), SIGNAL(torrentPaused(BitTorrent::TorrentHandle * const)), SLOT(handleTorrentStatusUpdated(BitTorrent::TorrentHandle * const))); - connect(BitTorrent::Session::instance(), SIGNAL(torrentFinishedChecking(BitTorrent::TorrentHandle * const)), SLOT(handleTorrentStatusUpdated(BitTorrent::TorrentHandle * const))); -} - -int TorrentModel::rowCount(const QModelIndex &index) const -{ - Q_UNUSED(index); - return m_torrents.size(); -} - -int TorrentModel::columnCount(const QModelIndex &parent) const -{ - Q_UNUSED(parent); - return NB_COLUMNS; -} - -QVariant TorrentModel::headerData(int section, Qt::Orientation orientation, int role) const -{ - if (orientation == Qt::Horizontal) { - if (role == Qt::DisplayRole) { - switch (section) { - case TR_PRIORITY: return "#"; - case TR_NAME: return tr("Name", "i.e: torrent name"); - case TR_SIZE: return tr("Size", "i.e: torrent size"); - case TR_PROGRESS: return tr("Done", "% Done"); - case TR_STATUS: return tr("Status", "Torrent status (e.g. downloading, seeding, paused)"); - case TR_SEEDS: return tr("Seeds", "i.e. full sources (often untranslated)"); - case TR_PEERS: return tr("Peers", "i.e. partial sources (often untranslated)"); - case TR_DLSPEED: return tr("Down Speed", "i.e: Download speed"); - case TR_UPSPEED: return tr("Up Speed", "i.e: Upload speed"); - case TR_RATIO: return tr("Ratio", "Share ratio"); - case TR_ETA: return tr("ETA", "i.e: Estimated Time of Arrival / Time left"); - case TR_CATEGORY: return tr("Category"); - case TR_TAGS: return tr("Tags"); - case TR_ADD_DATE: return tr("Added On", "Torrent was added to transfer list on 01/01/2010 08:00"); - case TR_SEED_DATE: return tr("Completed On", "Torrent was completed on 01/01/2010 08:00"); - case TR_TRACKER: return tr("Tracker"); - case TR_DLLIMIT: return tr("Down Limit", "i.e: Download limit"); - case TR_UPLIMIT: return tr("Up Limit", "i.e: Upload limit"); - case TR_AMOUNT_DOWNLOADED: return tr("Downloaded", "Amount of data downloaded (e.g. in MB)"); - case TR_AMOUNT_UPLOADED: return tr("Uploaded", "Amount of data uploaded (e.g. in MB)"); - case TR_AMOUNT_DOWNLOADED_SESSION: return tr("Session Download", "Amount of data downloaded since program open (e.g. in MB)"); - case TR_AMOUNT_UPLOADED_SESSION: return tr("Session Upload", "Amount of data uploaded since program open (e.g. in MB)"); - case TR_AMOUNT_LEFT: return tr("Remaining", "Amount of data left to download (e.g. in MB)"); - case TR_TIME_ELAPSED: return tr("Time Active", "Time (duration) the torrent is active (not paused)"); - case TR_SAVE_PATH: return tr("Save path", "Torrent save path"); - case TR_COMPLETED: return tr("Completed", "Amount of data completed (e.g. in MB)"); - case TR_RATIO_LIMIT: return tr("Ratio Limit", "Upload share ratio limit"); - case TR_SEEN_COMPLETE_DATE: return tr("Last Seen Complete", "Indicates the time when the torrent was last seen complete/whole"); - case TR_LAST_ACTIVITY: return tr("Last Activity", "Time passed since a chunk was downloaded/uploaded"); - case TR_TOTAL_SIZE: return tr("Total Size", "i.e. Size including unwanted data"); - default: - return QVariant(); - } - } - else if (role == Qt::TextAlignmentRole) { - switch (section) { - case TR_AMOUNT_DOWNLOADED: - case TR_AMOUNT_UPLOADED: - case TR_AMOUNT_DOWNLOADED_SESSION: - case TR_AMOUNT_UPLOADED_SESSION: - case TR_AMOUNT_LEFT: - case TR_COMPLETED: - case TR_SIZE: - case TR_TOTAL_SIZE: - case TR_ETA: - case TR_SEEDS: - case TR_PEERS: - case TR_UPSPEED: - case TR_DLSPEED: - case TR_UPLIMIT: - case TR_DLLIMIT: - case TR_RATIO_LIMIT: - case TR_RATIO: - case TR_PRIORITY: - case TR_LAST_ACTIVITY: - return QVariant(Qt::AlignRight | Qt::AlignVCenter); - default: - return QAbstractListModel::headerData(section, orientation, role); - } - } - } - - return QVariant(); -} - -QVariant TorrentModel::data(const QModelIndex &index, int role) const -{ - if (!index.isValid()) return QVariant(); - - BitTorrent::TorrentHandle *const torrent = m_torrents.value(index.row()); - if (!torrent) return QVariant(); - - if ((role == Qt::DecorationRole) && (index.column() == TR_NAME)) - return getIconByState(torrent->state()); - - if (role == Qt::ForegroundRole) - return getColorByState(torrent->state()); - - if ((role != Qt::DisplayRole) && (role != Qt::UserRole)) - return QVariant(); - - switch (index.column()) { - case TR_NAME: - return torrent->name(); - case TR_PRIORITY: - return torrent->queuePosition(); - case TR_SIZE: - return torrent->wantedSize(); - case TR_PROGRESS: - return torrent->progress(); - case TR_STATUS: - return static_cast(torrent->state()); - case TR_SEEDS: - return (role == Qt::DisplayRole) ? torrent->seedsCount() : torrent->totalSeedsCount(); - case TR_PEERS: - return (role == Qt::DisplayRole) ? torrent->leechsCount() : torrent->totalLeechersCount(); - case TR_DLSPEED: - return torrent->downloadPayloadRate(); - case TR_UPSPEED: - return torrent->uploadPayloadRate(); - case TR_ETA: - return torrent->eta(); - case TR_RATIO: - return torrent->realRatio(); - case TR_CATEGORY: - return torrent->category(); - case TR_TAGS: { - QStringList tagsList = torrent->tags().toList(); - tagsList.sort(); - return tagsList.join(", "); - } - case TR_ADD_DATE: - return torrent->addedTime(); - case TR_SEED_DATE: - return torrent->completedTime(); - case TR_TRACKER: - return torrent->currentTracker(); - case TR_DLLIMIT: - return torrent->downloadLimit(); - case TR_UPLIMIT: - return torrent->uploadLimit(); - case TR_AMOUNT_DOWNLOADED: - return torrent->totalDownload(); - case TR_AMOUNT_UPLOADED: - return torrent->totalUpload(); - case TR_AMOUNT_DOWNLOADED_SESSION: - return torrent->totalPayloadDownload(); - case TR_AMOUNT_UPLOADED_SESSION: - return torrent->totalPayloadUpload(); - case TR_AMOUNT_LEFT: - return torrent->incompletedSize(); - case TR_TIME_ELAPSED: - return (role == Qt::DisplayRole) ? torrent->activeTime() : torrent->seedingTime(); - case TR_SAVE_PATH: - return Utils::Fs::toNativePath(torrent->savePath()); - case TR_COMPLETED: - return torrent->completedSize(); - case TR_RATIO_LIMIT: - return torrent->maxRatio(); - case TR_SEEN_COMPLETE_DATE: - return torrent->lastSeenComplete(); - case TR_LAST_ACTIVITY: - if (torrent->isPaused() || torrent->isChecking()) - return -1; - return torrent->timeSinceActivity(); - case TR_TOTAL_SIZE: - return torrent->totalSize(); - default: - return QVariant(); - } - - return QVariant(); -} - -bool TorrentModel::setData(const QModelIndex &index, const QVariant &value, int role) -{ - qDebug() << Q_FUNC_INFO << value; - if (!index.isValid() || (role != Qt::DisplayRole)) return false; - - qDebug("Index is valid and role is DisplayRole"); - BitTorrent::TorrentHandle *const torrent = m_torrents.value(index.row()); - if (!torrent) return false; - - // Category, seed date and Name columns can be edited - switch (index.column()) { - case TR_NAME: - torrent->setName(value.toString()); - break; - case TR_CATEGORY: - torrent->setCategory(value.toString()); - break; - default: - return false; - } - - return true; -} - -void TorrentModel::addTorrent(BitTorrent::TorrentHandle *const torrent) -{ - if (m_torrents.indexOf(torrent) == -1) { - const int row = m_torrents.size(); - beginInsertRows(QModelIndex(), row, row); - m_torrents << torrent; - endInsertRows(); - } -} - -Qt::ItemFlags TorrentModel::flags(const QModelIndex &index) const -{ - if (!index.isValid()) return 0; - - // Explicitly mark as editable - return QAbstractListModel::flags(index) | Qt::ItemIsEditable; -} - -BitTorrent::TorrentHandle *TorrentModel::torrentHandle(const QModelIndex &index) const -{ - if (!index.isValid()) return 0; - - return m_torrents.value(index.row()); -} - -void TorrentModel::handleTorrentAboutToBeRemoved(BitTorrent::TorrentHandle *const torrent) -{ - const int row = m_torrents.indexOf(torrent); - if (row >= 0) { - beginRemoveRows(QModelIndex(), row, row); - m_torrents.removeAt(row); - endRemoveRows(); - } -} - -void TorrentModel::handleTorrentStatusUpdated(BitTorrent::TorrentHandle *const torrent) -{ - const int row = m_torrents.indexOf(torrent); - if (row >= 0) - emit dataChanged(index(row, 0), index(row, columnCount() - 1)); -} - -void TorrentModel::handleTorrentsUpdated() -{ - emit dataChanged(index(0, 0), index(rowCount() - 1, columnCount() - 1)); -} - -// Static functions - -QIcon getIconByState(BitTorrent::TorrentState state) -{ - switch (state) { - case BitTorrent::TorrentState::Downloading: - case BitTorrent::TorrentState::ForcedDownloading: - case BitTorrent::TorrentState::DownloadingMetadata: - return getDownloadingIcon(); - case BitTorrent::TorrentState::Allocating: - case BitTorrent::TorrentState::StalledDownloading: - return getStalledDownloadingIcon(); - case BitTorrent::TorrentState::StalledUploading: - return getStalledUploadingIcon(); - case BitTorrent::TorrentState::Uploading: - case BitTorrent::TorrentState::ForcedUploading: - return getUploadingIcon(); - case BitTorrent::TorrentState::PausedDownloading: - return getPausedIcon(); - case BitTorrent::TorrentState::PausedUploading: - return getCompletedIcon(); - case BitTorrent::TorrentState::QueuedDownloading: - case BitTorrent::TorrentState::QueuedUploading: - return getQueuedIcon(); - case BitTorrent::TorrentState::CheckingDownloading: - case BitTorrent::TorrentState::CheckingUploading: -#if LIBTORRENT_VERSION_NUM < 10100 - case BitTorrent::TorrentState::QueuedForChecking: -#endif - case BitTorrent::TorrentState::CheckingResumeData: - return getCheckingIcon(); - case BitTorrent::TorrentState::Unknown: - case BitTorrent::TorrentState::MissingFiles: - case BitTorrent::TorrentState::Error: - return getErrorIcon(); - default: - Q_ASSERT(false); - return getErrorIcon(); - } -} - -QColor getColorByState(BitTorrent::TorrentState state) -{ - // Color names taken from http://cloford.com/resources/colours/500col.htm - bool dark = isDarkTheme(); - - switch (state) { - case BitTorrent::TorrentState::Downloading: - case BitTorrent::TorrentState::ForcedDownloading: - case BitTorrent::TorrentState::DownloadingMetadata: - if (!dark) - return QColor(34, 139, 34); // Forest Green - else - return QColor(50, 205, 50); // Lime Green - case BitTorrent::TorrentState::Allocating: - case BitTorrent::TorrentState::StalledDownloading: - case BitTorrent::TorrentState::StalledUploading: - if (!dark) - return QColor(0, 0, 0); // Black - else - return QColor(204, 204, 204); // Gray 80 - case BitTorrent::TorrentState::Uploading: - case BitTorrent::TorrentState::ForcedUploading: - if (!dark) - return QColor(65, 105, 225); // Royal Blue - else - return QColor(99, 184, 255); // Steel Blue 1 - case BitTorrent::TorrentState::PausedDownloading: - return QColor(250, 128, 114); // Salmon - case BitTorrent::TorrentState::PausedUploading: - if (!dark) - return QColor(0, 0, 139); // Dark Blue - else - return QColor(79, 148, 205); // Steel Blue 3 - case BitTorrent::TorrentState::Error: - case BitTorrent::TorrentState::MissingFiles: - return QColor(255, 0, 0); // red - case BitTorrent::TorrentState::QueuedDownloading: - case BitTorrent::TorrentState::QueuedUploading: - case BitTorrent::TorrentState::CheckingDownloading: - case BitTorrent::TorrentState::CheckingUploading: -#if LIBTORRENT_VERSION_NUM < 10100 - case BitTorrent::TorrentState::QueuedForChecking: -#endif - case BitTorrent::TorrentState::CheckingResumeData: - if (!dark) - return QColor(0, 128, 128); // Teal - else - return QColor(0, 205, 205); // Cyan 3 - case BitTorrent::TorrentState::Unknown: - return QColor(255, 0, 0); // red - default: - Q_ASSERT(false); - return QColor(255, 0, 0); // red - } -} - -QIcon getPausedIcon() -{ - static QIcon cached = QIcon(":/icons/skin/paused.png"); - return cached; -} - -QIcon getQueuedIcon() -{ - static QIcon cached = QIcon(":/icons/skin/queued.png"); - return cached; -} - -QIcon getDownloadingIcon() -{ - static QIcon cached = QIcon(":/icons/skin/downloading.png"); - return cached; -} - -QIcon getStalledDownloadingIcon() -{ - static QIcon cached = QIcon(":/icons/skin/stalledDL.png"); - return cached; -} - -QIcon getUploadingIcon() -{ - static QIcon cached = QIcon(":/icons/skin/uploading.png"); - return cached; -} - -QIcon getStalledUploadingIcon() -{ - static QIcon cached = QIcon(":/icons/skin/stalledUP.png"); - return cached; -} - -QIcon getCompletedIcon() -{ - static QIcon cached = QIcon(":/icons/skin/completed.png"); - return cached; -} - -QIcon getCheckingIcon() -{ - static QIcon cached = QIcon(":/icons/skin/checking.png"); - return cached; -} - -QIcon getErrorIcon() -{ - static QIcon cached = QIcon(":/icons/skin/error.png"); - return cached; -} - -bool isDarkTheme() -{ - QPalette pal = QApplication::palette(); - // QPalette::Base is used for the background of the Treeview - QColor color = pal.color(QPalette::Active, QPalette::Base); - return (color.lightness() < 127); -} diff --git a/src/gui/torrentmodel.h b/src/gui/torrentmodel.h deleted file mode 100644 index fd9161ec8..000000000 --- a/src/gui/torrentmodel.h +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2015 Vladimir Golovnev - * Copyright (C) 2010 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 TORRENTMODEL_H -#define TORRENTMODEL_H - -#include -#include - -namespace BitTorrent -{ - class InfoHash; - class TorrentHandle; -} - -class TorrentModel : public QAbstractListModel -{ - Q_OBJECT - Q_DISABLE_COPY(TorrentModel) - -public: - enum Column - { - TR_PRIORITY, - TR_NAME, - TR_SIZE, - TR_TOTAL_SIZE, - TR_PROGRESS, - TR_STATUS, - TR_SEEDS, - TR_PEERS, - TR_DLSPEED, - TR_UPSPEED, - TR_ETA, - TR_RATIO, - TR_CATEGORY, - TR_TAGS, - TR_ADD_DATE, - TR_SEED_DATE, - TR_TRACKER, - TR_DLLIMIT, - TR_UPLIMIT, - TR_AMOUNT_DOWNLOADED, - TR_AMOUNT_UPLOADED, - TR_AMOUNT_DOWNLOADED_SESSION, - TR_AMOUNT_UPLOADED_SESSION, - TR_AMOUNT_LEFT, - TR_TIME_ELAPSED, - TR_SAVE_PATH, - TR_COMPLETED, - TR_RATIO_LIMIT, - TR_SEEN_COMPLETE_DATE, - TR_LAST_ACTIVITY, - - NB_COLUMNS - }; - - explicit TorrentModel(QObject *parent = 0); - - int rowCount(const QModelIndex& index = QModelIndex()) const; - int columnCount(const QModelIndex &parent=QModelIndex()) const; - QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; - bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::DisplayRole); - QVariant headerData(int section, Qt::Orientation orientation, int role) const; - Qt::ItemFlags flags(const QModelIndex &index) const; - - BitTorrent::TorrentHandle *torrentHandle(const QModelIndex &index) const; - -private slots: - void addTorrent(BitTorrent::TorrentHandle *const torrent); - void handleTorrentAboutToBeRemoved(BitTorrent::TorrentHandle *const torrent); - void handleTorrentStatusUpdated(BitTorrent::TorrentHandle *const torrent); - void handleTorrentsUpdated(); - -private: - QList m_torrents; -}; - -#endif // TORRENTMODEL_H diff --git a/src/gui/trackerlogin.cpp b/src/gui/trackerlogin.cpp deleted file mode 100644 index 74abf1dae..000000000 --- a/src/gui/trackerlogin.cpp +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Bittorrent Client using Qt4 and libtorrent. - * Copyright (C) 2006 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 "trackerlogin.h" - -#include -#include "base/bittorrent/torrenthandle.h" - -trackerLogin::trackerLogin(QWidget *parent, BitTorrent::TorrentHandle *const torrent) - : QDialog(parent) - , m_torrent(torrent) -{ - setupUi(this); - setAttribute(Qt::WA_DeleteOnClose); - login_logo->setPixmap(QPixmap(QString::fromUtf8(":/icons/qbt-theme/encrypted.png"))); - tracker_url->setText(torrent->currentTracker()); - connect(this, SIGNAL(trackerLoginCancelled(QPair)), parent, SLOT(addUnauthenticatedTracker(QPair))); - show(); -} - -trackerLogin::~trackerLogin() {} - -void trackerLogin::on_loginButton_clicked() { - // login -#if LIBTORRENT_VERSION_NUM < 10100 - m_torrent->setTrackerLogin(lineUsername->text(), linePasswd->text()); -#endif - close(); -} - -void trackerLogin::on_cancelButton_clicked() { - // Emit a signal to GUI to stop asking for authentication - emit trackerLoginCancelled(qMakePair(m_torrent, m_torrent->currentTracker())); - close(); -} diff --git a/src/gui/trackerlogin.h b/src/gui/trackerlogin.h deleted file mode 100644 index 780162dca..000000000 --- a/src/gui/trackerlogin.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Bittorrent Client using Qt4 and libtorrent. - * Copyright (C) 2006 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 TRACKERLOGIN_H -#define TRACKERLOGIN_H - -#include - -#include "ui_login.h" - -namespace BitTorrent -{ - class TorrentHandle; -} - -class trackerLogin : public QDialog, private Ui::authentication{ - Q_OBJECT - - private: - BitTorrent::TorrentHandle *const m_torrent; - - public: - trackerLogin(QWidget *parent, BitTorrent::TorrentHandle *const torrent); - ~trackerLogin(); - - signals: - void trackerLoginCancelled(QPair tracker); - - public slots: - void on_loginButton_clicked(); - void on_cancelButton_clicked(); -}; - -#endif diff --git a/src/gui/transferlistdelegate.cpp b/src/gui/transferlistdelegate.cpp deleted file mode 100644 index 6187cc245..000000000 --- a/src/gui/transferlistdelegate.cpp +++ /dev/null @@ -1,286 +0,0 @@ -/* - * Bittorrent Client using Qt4 and libtorrent. - * Copyright (C) 2006 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 "transferlistdelegate.h" - -#include -#include -#include -#include -#include "base/utils/misc.h" -#include "base/utils/string.h" -#include "torrentmodel.h" -#include "base/bittorrent/session.h" -#include "base/bittorrent/torrenthandle.h" -#include "base/types.h" -#include "base/preferences.h" -#include "base/unicodestrings.h" - -#ifdef Q_OS_WIN -#include -#endif - -TransferListDelegate::TransferListDelegate(QObject *parent) - : QItemDelegate(parent) -{ -} - -void TransferListDelegate::paint(QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index) const -{ - painter->save(); - bool isHideState = true; - if (Preferences::instance()->getHideZeroComboValues() == 1) { // paused torrents only - QModelIndex stateIndex = index.sibling(index.row(), TorrentModel::TR_STATUS); - if (stateIndex.data().toInt() != BitTorrent::TorrentState::PausedDownloading) - isHideState = false; - } - const bool hideValues = Preferences::instance()->getHideZeroValues() & isHideState; - - QStyleOptionViewItem opt = QItemDelegate::setOptions(index, option); - QItemDelegate::drawBackground(painter, opt, index); - switch (index.column()) { - case TorrentModel::TR_AMOUNT_DOWNLOADED: - case TorrentModel::TR_AMOUNT_UPLOADED: - case TorrentModel::TR_AMOUNT_DOWNLOADED_SESSION: - case TorrentModel::TR_AMOUNT_UPLOADED_SESSION: - case TorrentModel::TR_AMOUNT_LEFT: - case TorrentModel::TR_COMPLETED: - case TorrentModel::TR_SIZE: - case TorrentModel::TR_TOTAL_SIZE: { - qlonglong size = index.data().toLongLong(); - if (hideValues && !size) - break; - opt.displayAlignment = Qt::AlignRight | Qt::AlignVCenter; - QItemDelegate::drawDisplay(painter, opt, option.rect, Utils::Misc::friendlyUnit(size)); - break; - } - case TorrentModel::TR_ETA: { - opt.displayAlignment = Qt::AlignRight | Qt::AlignVCenter; - QItemDelegate::drawDisplay(painter, opt, option.rect, Utils::Misc::userFriendlyDuration(index.data().toLongLong())); - break; - } - case TorrentModel::TR_SEEDS: - case TorrentModel::TR_PEERS: { - qlonglong value = index.data().toLongLong(); - qlonglong total = index.data(Qt::UserRole).toLongLong(); - if (hideValues && (!value && !total)) - break; - QString display = QString::number(value) + " (" + QString::number(total) + ")"; - opt.displayAlignment = Qt::AlignRight | Qt::AlignVCenter; - QItemDelegate::drawDisplay(painter, opt, opt.rect, display); - break; - } - case TorrentModel::TR_STATUS: { - const int state = index.data().toInt(); - QString display = getStatusString(state); - QItemDelegate::drawDisplay(painter, opt, opt.rect, display); - break; - } - case TorrentModel::TR_UPSPEED: - case TorrentModel::TR_DLSPEED: { - const qulonglong speed = index.data().toULongLong(); - if (hideValues && !speed) - break; - opt.displayAlignment = Qt::AlignRight | Qt::AlignVCenter; - QItemDelegate::drawDisplay(painter, opt, opt.rect, Utils::Misc::friendlyUnit(speed, true)); - break; - } - case TorrentModel::TR_UPLIMIT: - case TorrentModel::TR_DLLIMIT: { - const qlonglong limit = index.data().toLongLong(); - if (hideValues && !limit) - break; - opt.displayAlignment = Qt::AlignRight | Qt::AlignVCenter; - QItemDelegate::drawDisplay(painter, opt, opt.rect, limit > 0 ? Utils::Misc::friendlyUnit(limit, true) : QString::fromUtf8(C_INFINITY)); - break; - } - case TorrentModel::TR_TIME_ELAPSED: { - qlonglong elapsedTime = index.data().toLongLong(); - qlonglong seedingTime = index.data(Qt::UserRole).toLongLong(); - QString txt; - if (seedingTime > 0) - txt += tr("%1 (seeded for %2)", "e.g. 4m39s (seeded for 3m10s)") - .arg(Utils::Misc::userFriendlyDuration(elapsedTime)) - .arg(Utils::Misc::userFriendlyDuration(seedingTime)); - QItemDelegate::drawDisplay(painter, opt, opt.rect, txt); - break; - } - case TorrentModel::TR_ADD_DATE: - case TorrentModel::TR_SEED_DATE: - QItemDelegate::drawDisplay(painter, opt, opt.rect, index.data().toDateTime().toLocalTime().toString(Qt::DefaultLocaleShortDate)); - break; - case TorrentModel::TR_RATIO_LIMIT: - case TorrentModel::TR_RATIO: { - const qreal ratio = index.data().toDouble(); - if (hideValues && (ratio <= 0)) - break; - QString str = ((ratio == -1) || (ratio > BitTorrent::TorrentHandle::MAX_RATIO)) ? QString::fromUtf8(C_INFINITY) : Utils::String::fromDouble(ratio, 2); - opt.displayAlignment = Qt::AlignRight | Qt::AlignVCenter; - QItemDelegate::drawDisplay(painter, opt, opt.rect, str); - break; - } - case TorrentModel::TR_PRIORITY: { - const int priority = index.data().toInt(); - opt.displayAlignment = Qt::AlignRight | Qt::AlignVCenter; - if (priority > 0) { - QItemDelegate::paint(painter, opt, index); - } - else { - QItemDelegate::drawDisplay(painter, opt, opt.rect, "*"); - } - break; - } - case TorrentModel::TR_PROGRESS: { - QStyleOptionProgressBar newopt; - qreal progress = index.data().toDouble() * 100.; - newopt.rect = opt.rect; - newopt.text = ((progress == 100.0) ? QString("100%") : Utils::String::fromDouble(progress, 1) + "%"); - newopt.progress = static_cast(progress); - newopt.maximum = 100; - newopt.minimum = 0; - newopt.state |= QStyle::State_Enabled; - newopt.textVisible = true; -#ifndef Q_OS_WIN - QApplication::style()->drawControl(QStyle::CE_ProgressBar, &newopt, painter); -#else - // XXX: To avoid having the progress text on the right of the bar - QProxyStyle st("fusion"); - st.drawControl(QStyle::CE_ProgressBar, &newopt, painter, 0); -#endif - break; - } - case TorrentModel::TR_LAST_ACTIVITY: { - qlonglong elapsed = index.data().toLongLong(); - if (hideValues && ((elapsed < 0) || (elapsed >= MAX_ETA))) - break; - - QString elapsedString; - if (elapsed == 0) - // Show '< 1m ago' when elapsed time is 0 - elapsed = 1; - else if (elapsed < 0) - elapsedString = Utils::Misc::userFriendlyDuration(elapsed); - else - elapsedString = tr("%1 ago", "e.g.: 1h 20m ago").arg(Utils::Misc::userFriendlyDuration(elapsed)); - opt.displayAlignment = Qt::AlignRight | Qt::AlignVCenter; - QItemDelegate::drawDisplay(painter, opt, option.rect, elapsedString); - break; - } - default: - QItemDelegate::paint(painter, option, index); - } - painter->restore(); -} - -QWidget* TransferListDelegate::createEditor(QWidget*, const QStyleOptionViewItem &, const QModelIndex &) const -{ - // No editor here - return 0; -} - -QSize TransferListDelegate::sizeHint(const QStyleOptionViewItem & option, const QModelIndex & index) const -{ - // Reimplementing sizeHint() because the 'name' column contains text+icon. - // When that WHOLE column goes out of view(eg user scrolls horizontally) - // the rows shrink if the text's height is smaller than the icon's height. - // This happens because icon from the 'name' column is no longer drawn. - - static int nameColHeight = -1; - if (nameColHeight == -1) { - QModelIndex nameColumn = index.sibling(index.row(), TorrentModel::TR_NAME); - nameColHeight = QItemDelegate::sizeHint(option, nameColumn).height(); - } - - QSize size = QItemDelegate::sizeHint(option, index); - size.setHeight(std::max(nameColHeight, size.height())); - return size; -} - -QString TransferListDelegate::getStatusString(const int state) const -{ - QString str; - - switch (state) { - case BitTorrent::TorrentState::Downloading: - str = tr("Downloading"); - break; - case BitTorrent::TorrentState::StalledDownloading: - str = tr("Stalled", "Torrent is waiting for download to begin"); - break; - case BitTorrent::TorrentState::DownloadingMetadata: - str = tr("Downloading metadata", "used when loading a magnet link"); - break; - case BitTorrent::TorrentState::ForcedDownloading: - str = tr("[F] Downloading", "used when the torrent is forced started. You probably shouldn't translate the F."); - break; - case BitTorrent::TorrentState::Allocating: - str = tr("Allocating", "qBittorrent is allocating the files on disk"); - break; - case BitTorrent::TorrentState::Uploading: - case BitTorrent::TorrentState::StalledUploading: - str = tr("Seeding", "Torrent is complete and in upload-only mode"); - break; - case BitTorrent::TorrentState::ForcedUploading: - str = tr("[F] Seeding", "used when the torrent is forced started. You probably shouldn't translate the F."); - break; - case BitTorrent::TorrentState::QueuedDownloading: - case BitTorrent::TorrentState::QueuedUploading: - str = tr("Queued", "i.e. torrent is queued"); - break; - case BitTorrent::TorrentState::CheckingDownloading: - case BitTorrent::TorrentState::CheckingUploading: - str = tr("Checking", "Torrent local data is being checked"); - break; -#if LIBTORRENT_VERSION_NUM < 10100 - case BitTorrent::TorrentState::QueuedForChecking: - str = tr("Queued for checking", "i.e. torrent is queued for hash checking"); - break; -#endif - case BitTorrent::TorrentState::CheckingResumeData: - str = tr("Checking resume data", "used when loading the torrents from disk after qbt is launched. It checks the correctness of the .fastresume file. Normally it is completed in a fraction of a second, unless loading many many torrents."); - break; - case BitTorrent::TorrentState::PausedDownloading: - str = tr("Paused"); - break; - case BitTorrent::TorrentState::PausedUploading: - str = tr("Completed"); - break; - case BitTorrent::TorrentState::MissingFiles: - str = tr("Missing Files"); - break; - case BitTorrent::TorrentState::Error: - str = tr("Errored", "torrent status, the torrent has an error"); - break; - default: - str = ""; - } - - return str; -} diff --git a/src/gui/transferlistdelegate.h b/src/gui/transferlistdelegate.h deleted file mode 100644 index 577dd1b32..000000000 --- a/src/gui/transferlistdelegate.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Bittorrent Client using Qt4 and libtorrent. - * Copyright (C) 2006 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 TRANSFERLISTDELEGATE_H -#define TRANSFERLISTDELEGATE_H - -#include - -QT_BEGIN_NAMESPACE -class QPainter; -class QStyleOptionViewItem; -class QModelIndex; -QT_END_NAMESPACE - -// Defines for download list list columns - -class TransferListDelegate: public QItemDelegate -{ - Q_OBJECT - -public: - TransferListDelegate(QObject *parent); - void paint(QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index) const; - QWidget* createEditor(QWidget*, const QStyleOptionViewItem &, const QModelIndex &) const; - QSize sizeHint(const QStyleOptionViewItem & option, const QModelIndex & index) const; - -private: - QString getStatusString(const int state) const; -}; - -#endif // TRANSFERLISTDELEGATE_H diff --git a/src/gui/transferlistfilterswidget.cpp b/src/gui/transferlistfilterswidget.cpp deleted file mode 100644 index 05188ac41..000000000 --- a/src/gui/transferlistfilterswidget.cpp +++ /dev/null @@ -1,702 +0,0 @@ -/* - * Bittorrent Client using Qt4 and libtorrent. - * Copyright (C) 2006 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 "transferlistfilterswidget.h" - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "base/bittorrent/session.h" -#include "base/bittorrent/torrenthandle.h" -#include "base/bittorrent/trackerentry.h" -#include "base/logger.h" -#include "base/net/downloadmanager.h" -#include "base/net/downloadhandler.h" -#include "base/preferences.h" -#include "base/torrentfilter.h" -#include "base/utils/fs.h" -#include "base/utils/misc.h" -#include "base/utils/string.h" -#include "autoexpandabledialog.h" -#include "categoryfilterwidget.h" -#include "guiiconprovider.h" -#include "tagfilterwidget.h" -#include "torrentmodel.h" -#include "transferlistdelegate.h" -#include "transferlistwidget.h" - -const QLatin1String GOOGLE_FAVICON_URL("https://www.google.com/s2/favicons?domain="); - -FiltersBase::FiltersBase(QWidget *parent, TransferListWidget *transferList) - : QListWidget(parent) - , transferList(transferList) -{ - setFrameShape(QFrame::NoFrame); - setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); - setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); - setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); - setUniformItemSizes(true); - setSpacing(0); - - setIconSize(Utils::Misc::smallIconSize()); - -#if defined(Q_OS_MAC) - setAttribute(Qt::WA_MacShowFocusRect, false); -#endif - - setContextMenuPolicy(Qt::CustomContextMenu); - connect(this, &FiltersBase::customContextMenuRequested, this, &FiltersBase::showMenu); - connect(this, &FiltersBase::currentRowChanged, this, &FiltersBase::applyFilter); - - connect(BitTorrent::Session::instance(), &BitTorrent::Session::torrentAdded - , this, &FiltersBase::handleNewTorrent); - connect(BitTorrent::Session::instance(), &BitTorrent::Session::torrentAboutToBeRemoved - , this, &FiltersBase::torrentAboutToBeDeleted); -} - -QSize FiltersBase::sizeHint() const -{ - QSize size; - // Height should be exactly the height of the content - size.setHeight(((sizeHintForRow(0) + 2 * spacing()) * (count() + 0.5))); - // Width should be exactly the width of the content - size.setWidth(sizeHintForColumn(0)); - return size; -} - -QSize FiltersBase::minimumSizeHint() const -{ - QSize size = sizeHint(); - size.setWidth(6); - return size; -} - -void FiltersBase::toggleFilter(bool checked) -{ - setVisible(checked); - if (checked) - applyFilter(currentRow()); - else - applyFilter(0); -} - -StatusFiltersWidget::StatusFiltersWidget(QWidget *parent, TransferListWidget *transferList) - : FiltersBase(parent, transferList) -{ - connect(BitTorrent::Session::instance(), &BitTorrent::Session::torrentsUpdated - , this, &StatusFiltersWidget::updateTorrentNumbers); - - // Add status filters - QListWidgetItem *all = new QListWidgetItem(this); - all->setData(Qt::DisplayRole, QVariant(tr("All (0)", "this is for the status filter"))); - all->setData(Qt::DecorationRole, QIcon(":/icons/skin/filterall.png")); - QListWidgetItem *downloading = new QListWidgetItem(this); - downloading->setData(Qt::DisplayRole, QVariant(tr("Downloading (0)"))); - downloading->setData(Qt::DecorationRole, QIcon(":/icons/skin/downloading.png")); - QListWidgetItem *seeding = new QListWidgetItem(this); - seeding->setData(Qt::DisplayRole, QVariant(tr("Seeding (0)"))); - seeding->setData(Qt::DecorationRole, QIcon(":/icons/skin/uploading.png")); - QListWidgetItem *completed = new QListWidgetItem(this); - completed->setData(Qt::DisplayRole, QVariant(tr("Completed (0)"))); - completed->setData(Qt::DecorationRole, QIcon(":/icons/skin/completed.png")); - QListWidgetItem *resumed = new QListWidgetItem(this); - resumed->setData(Qt::DisplayRole, QVariant(tr("Resumed (0)"))); - resumed->setData(Qt::DecorationRole, QIcon(":/icons/skin/resumed.png")); - QListWidgetItem *paused = new QListWidgetItem(this); - paused->setData(Qt::DisplayRole, QVariant(tr("Paused (0)"))); - paused->setData(Qt::DecorationRole, QIcon(":/icons/skin/paused.png")); - QListWidgetItem *active = new QListWidgetItem(this); - active->setData(Qt::DisplayRole, QVariant(tr("Active (0)"))); - active->setData(Qt::DecorationRole, QIcon(":/icons/skin/filteractive.png")); - QListWidgetItem *inactive = new QListWidgetItem(this); - inactive->setData(Qt::DisplayRole, QVariant(tr("Inactive (0)"))); - inactive->setData(Qt::DecorationRole, QIcon(":/icons/skin/filterinactive.png")); - QListWidgetItem *errored = new QListWidgetItem(this); - errored->setData(Qt::DisplayRole, QVariant(tr("Errored (0)"))); - errored->setData(Qt::DecorationRole, QIcon(":/icons/skin/error.png")); - - const Preferences* const pref = Preferences::instance(); - setCurrentRow(pref->getTransSelFilter(), QItemSelectionModel::SelectCurrent); - toggleFilter(pref->getStatusFilterState()); -} - -StatusFiltersWidget::~StatusFiltersWidget() -{ - Preferences::instance()->setTransSelFilter(currentRow()); -} - -void StatusFiltersWidget::updateTorrentNumbers() -{ - auto report = BitTorrent::Session::instance()->torrentStatusReport(); - - item(TorrentFilter::All)->setData(Qt::DisplayRole, QVariant(tr("All (%1)").arg(report.nbActive + report.nbInactive))); - item(TorrentFilter::Downloading)->setData(Qt::DisplayRole, QVariant(tr("Downloading (%1)").arg(report.nbDownloading))); - item(TorrentFilter::Seeding)->setData(Qt::DisplayRole, QVariant(tr("Seeding (%1)").arg(report.nbSeeding))); - item(TorrentFilter::Completed)->setData(Qt::DisplayRole, QVariant(tr("Completed (%1)").arg(report.nbCompleted))); - item(TorrentFilter::Paused)->setData(Qt::DisplayRole, QVariant(tr("Paused (%1)").arg(report.nbPaused))); - item(TorrentFilter::Resumed)->setData(Qt::DisplayRole, QVariant(tr("Resumed (%1)").arg(report.nbResumed))); - item(TorrentFilter::Active)->setData(Qt::DisplayRole, QVariant(tr("Active (%1)").arg(report.nbActive))); - item(TorrentFilter::Inactive)->setData(Qt::DisplayRole, QVariant(tr("Inactive (%1)").arg(report.nbInactive))); - item(TorrentFilter::Errored)->setData(Qt::DisplayRole, QVariant(tr("Errored (%1)").arg(report.nbErrored))); -} - -void StatusFiltersWidget::showMenu(QPoint) {} - -void StatusFiltersWidget::applyFilter(int row) -{ - transferList->applyStatusFilter(row); -} - -void StatusFiltersWidget::handleNewTorrent(BitTorrent::TorrentHandle *const) {} - -void StatusFiltersWidget::torrentAboutToBeDeleted(BitTorrent::TorrentHandle *const) {} - -TrackerFiltersList::TrackerFiltersList(QWidget *parent, TransferListWidget *transferList) - : FiltersBase(parent, transferList) - , m_totalTorrents(0) - , m_downloadTrackerFavicon(true) -{ - QListWidgetItem *allTrackers = new QListWidgetItem(this); - allTrackers->setData(Qt::DisplayRole, QVariant(tr("All (0)", "this is for the tracker filter"))); - allTrackers->setData(Qt::DecorationRole, GuiIconProvider::instance()->getIcon("network-server")); - QListWidgetItem *noTracker = new QListWidgetItem(this); - noTracker->setData(Qt::DisplayRole, QVariant(tr("Trackerless (0)"))); - noTracker->setData(Qt::DecorationRole, GuiIconProvider::instance()->getIcon("network-server")); - QListWidgetItem *errorTracker = new QListWidgetItem(this); - errorTracker->setData(Qt::DisplayRole, QVariant(tr("Error (0)"))); - errorTracker->setData(Qt::DecorationRole, style()->standardIcon(QStyle::SP_MessageBoxCritical)); - QListWidgetItem *warningTracker = new QListWidgetItem(this); - warningTracker->setData(Qt::DisplayRole, QVariant(tr("Warning (0)"))); - warningTracker->setData(Qt::DecorationRole, style()->standardIcon(QStyle::SP_MessageBoxWarning)); - m_trackers.insert("", QStringList()); - - setCurrentRow(0, QItemSelectionModel::SelectCurrent); - toggleFilter(Preferences::instance()->getTrackerFilterState()); -} - -TrackerFiltersList::~TrackerFiltersList() -{ - foreach (const QString &iconPath, m_iconPaths) - Utils::Fs::forceRemove(iconPath); -} - -void TrackerFiltersList::addItem(const QString &tracker, const QString &hash) -{ - QStringList tmp; - QListWidgetItem *trackerItem = 0; - QString host = getHost(tracker); - bool exists = m_trackers.contains(host); - - if (exists) { - tmp = m_trackers.value(host); - if (tmp.contains(hash)) - return; - - if (host != "") { - trackerItem = item(rowFromTracker(host)); - } - else { - trackerItem = item(1); - } - } - else { - trackerItem = new QListWidgetItem(); - trackerItem->setData(Qt::DecorationRole, GuiIconProvider::instance()->getIcon("network-server")); - - downloadFavicon(QString("http://%1/favicon.ico").arg(host)); - } - if (!trackerItem) return; - - tmp.append(hash); - m_trackers.insert(host, tmp); - if (host == "") { - trackerItem->setText(tr("Trackerless (%1)").arg(tmp.size())); - if (currentRow() == 1) - applyFilter(1); - return; - } - - trackerItem->setText(QString("%1 (%2)").arg(host).arg(tmp.size())); - if (exists) { - if (currentRow() == rowFromTracker(host)) - applyFilter(currentRow()); - return; - } - - Q_ASSERT(count() >= 4); - int insPos = count(); - for (int i = 4; i < count(); ++i) { - if (Utils::String::naturalCompareCaseSensitive(host, item(i)->text())) { - insPos = i; - break; - } - } - QListWidget::insertItem(insPos, trackerItem); - updateGeometry(); -} - -void TrackerFiltersList::removeItem(const QString &tracker, const QString &hash) -{ - QString host = getHost(tracker); - QListWidgetItem *trackerItem = nullptr; - QStringList tmp = m_trackers.value(host); - int row = 0; - - if (tmp.empty()) - return; - tmp.removeAll(hash); - - if (!host.isEmpty()) { - // Remove from 'Error' and 'Warning' view - trackerSuccess(hash, tracker); - row = rowFromTracker(host); - trackerItem = item(row); - if (tmp.empty()) { - if (currentRow() == row) - setCurrentRow(0, QItemSelectionModel::SelectCurrent); - delete trackerItem; - m_trackers.remove(host); - updateGeometry(); - return; - } - if (trackerItem != nullptr) - trackerItem->setText(QString("%1 (%2)").arg(host).arg(tmp.size())); - } - else { - row = 1; - trackerItem = item(1); - trackerItem->setText(tr("Trackerless (%1)").arg(tmp.size())); - } - - m_trackers.insert(host, tmp); - if (currentRow() == row) - applyFilter(row); -} - -void TrackerFiltersList::changeTrackerless(bool trackerless, const QString &hash) -{ - if (trackerless) - addItem("", hash); - else - removeItem("", hash); -} - -void TrackerFiltersList::setDownloadTrackerFavicon(bool value) -{ - if (value == m_downloadTrackerFavicon) return; - m_downloadTrackerFavicon = value; - - if (m_downloadTrackerFavicon) { - foreach (const QString &tracker, m_trackers.keys()) { - if (!tracker.isEmpty()) - downloadFavicon(QString("http://%1/favicon.ico").arg(tracker)); - } - } -} - -void TrackerFiltersList::trackerSuccess(const QString &hash, const QString &tracker) -{ - QStringList errored = m_errors.value(hash); - QStringList warned = m_warnings.value(hash); - - if (errored.contains(tracker)) { - errored.removeAll(tracker); - if (errored.empty()) { - m_errors.remove(hash); - item(2)->setText(tr("Error (%1)").arg(m_errors.size())); - if (currentRow() == 2) - applyFilter(2); - } - else { - m_errors.insert(hash, errored); - } - } - - if (warned.contains(tracker)) { - warned.removeAll(tracker); - if (warned.empty()) { - m_warnings.remove(hash); - item(3)->setText(tr("Warning (%1)").arg(m_warnings.size())); - if (currentRow() == 3) - applyFilter(3); - } - else { - m_warnings.insert(hash, warned); - } - } -} - -void TrackerFiltersList::trackerError(const QString &hash, const QString &tracker) -{ - QStringList trackers = m_errors.value(hash); - - if (trackers.contains(tracker)) - return; - - trackers.append(tracker); - m_errors.insert(hash, trackers); - item(2)->setText(tr("Error (%1)").arg(m_errors.size())); - - if (currentRow() == 2) - applyFilter(2); -} - -void TrackerFiltersList::trackerWarning(const QString &hash, const QString &tracker) -{ - QStringList trackers = m_warnings.value(hash); - - if (trackers.contains(tracker)) - return; - - trackers.append(tracker); - m_warnings.insert(hash, trackers); - item(3)->setText(tr("Warning (%1)").arg(m_warnings.size())); - - if (currentRow() == 3) - applyFilter(3); -} - -void TrackerFiltersList::downloadFavicon(const QString& url) -{ - if (!m_downloadTrackerFavicon) return; - Net::DownloadHandler *h = Net::DownloadManager::instance()->downloadUrl(url, true); - using Func = void (Net::DownloadHandler::*)(const QString &, const QString &); - connect(h, static_cast(&Net::DownloadHandler::downloadFinished), this - , &TrackerFiltersList::handleFavicoDownload); - connect(h, static_cast(&Net::DownloadHandler::downloadFailed), this - , &TrackerFiltersList::handleFavicoFailure); -} - -void TrackerFiltersList::handleFavicoDownload(const QString& url, const QString& filePath) -{ - QString host = url.startsWith(GOOGLE_FAVICON_URL) - ? url.mid(GOOGLE_FAVICON_URL.size()) - : getHost(url); - - if (!m_trackers.contains(host)) { - Utils::Fs::forceRemove(filePath); - return; - } - - QListWidgetItem *trackerItem = item(rowFromTracker(host)); - if (!trackerItem) return; - - QIcon icon(filePath); - //Detect a non-decodable icon - QList sizes = icon.availableSizes(); - bool invalid = (sizes.isEmpty() || icon.pixmap(sizes.first()).isNull()); - if (invalid) { - if (url.endsWith(".ico", Qt::CaseInsensitive)) - downloadFavicon(url.left(url.size() - 4) + ".png"); - Utils::Fs::forceRemove(filePath); - } - else { - trackerItem->setData(Qt::DecorationRole, QVariant(QIcon(filePath))); - m_iconPaths.append(filePath); - } -} - -void TrackerFiltersList::handleFavicoFailure(const QString& url, const QString& error) -{ - Q_UNUSED(error) - if (url.endsWith(".ico", Qt::CaseInsensitive)) { - downloadFavicon(url.left(url.size() - 4) + ".png"); - } - else if (!url.startsWith(GOOGLE_FAVICON_URL)) { - downloadFavicon(GOOGLE_FAVICON_URL + getHost(url)); - } -} - -void TrackerFiltersList::showMenu(QPoint) -{ - QMenu menu(this); - QAction *startAct = menu.addAction(GuiIconProvider::instance()->getIcon("media-playback-start"), tr("Resume torrents")); - QAction *pauseAct = menu.addAction(GuiIconProvider::instance()->getIcon("media-playback-pause"), tr("Pause torrents")); - QAction *deleteTorrentsAct = menu.addAction(GuiIconProvider::instance()->getIcon("edit-delete"), tr("Delete torrents")); - QAction *act = 0; - act = menu.exec(QCursor::pos()); - - if (!act) - return; - - if (act == startAct) - transferList->startVisibleTorrents(); - else if (act == pauseAct) - transferList->pauseVisibleTorrents(); - else if (act == deleteTorrentsAct) - transferList->deleteVisibleTorrents(); -} - -void TrackerFiltersList::applyFilter(int row) -{ - if (row == 0) - transferList->applyTrackerFilterAll(); - else if (isVisible()) - transferList->applyTrackerFilter(getHashes(row)); -} - -void TrackerFiltersList::handleNewTorrent(BitTorrent::TorrentHandle *const torrent) -{ - QString hash = torrent->hash(); - QList trackers = torrent->trackers(); - foreach (const BitTorrent::TrackerEntry &tracker, trackers) - addItem(tracker.url(), hash); - - //Check for trackerless torrent - if (trackers.size() == 0) - addItem("", hash); - - item(0)->setText(tr("All (%1)", "this is for the tracker filter").arg(++m_totalTorrents)); -} - -void TrackerFiltersList::torrentAboutToBeDeleted(BitTorrent::TorrentHandle *const torrent) -{ - QString hash = torrent->hash(); - QList trackers = torrent->trackers(); - foreach (const BitTorrent::TrackerEntry &tracker, trackers) - removeItem(tracker.url(), hash); - - //Check for trackerless torrent - if (trackers.size() == 0) - removeItem("", hash); - - item(0)->setText(tr("All (%1)", "this is for the tracker filter").arg(--m_totalTorrents)); -} - -QString TrackerFiltersList::trackerFromRow(int row) const -{ - Q_ASSERT(row > 1); - const QString &tracker = item(row)->text(); - QStringList parts = tracker.split(" "); - Q_ASSERT(parts.size() >= 2); - parts.removeLast(); // Remove trailing number - return parts.join(" "); -} - -int TrackerFiltersList::rowFromTracker(const QString &tracker) const -{ - Q_ASSERT(!tracker.isEmpty()); - for (int i = 4; isetWidgetResizable(true); - scroll->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); - - setStyleSheet("QFrame {background: transparent;}"); - scroll->setStyleSheet("QFrame {border: none;}"); - vLayout->setContentsMargins(0, 0, 0, 0); - frameLayout->setContentsMargins(0, 2, 0, 0); - frameLayout->setSpacing(2); - frameLayout->setAlignment(Qt::AlignLeft | Qt::AlignTop); - - frame->setLayout(frameLayout); - scroll->setWidget(frame); - vLayout->addWidget(scroll); - setLayout(vLayout); - - QCheckBox * statusLabel = new QCheckBox(tr("Status"), this); - statusLabel->setChecked(pref->getStatusFilterState()); - statusLabel->setFont(font); - frameLayout->addWidget(statusLabel); - - StatusFiltersWidget *statusFilters = new StatusFiltersWidget(this, transferList); - frameLayout->addWidget(statusFilters); - - QCheckBox *categoryLabel = new QCheckBox(tr("Categories"), this); - categoryLabel->setChecked(pref->getCategoryFilterState()); - categoryLabel->setFont(font); - connect(categoryLabel, &QCheckBox::toggled, this - , &TransferListFiltersWidget::onCategoryFilterStateChanged); - frameLayout->addWidget(categoryLabel); - - m_categoryFilterWidget = new CategoryFilterWidget(this); - connect(m_categoryFilterWidget, &CategoryFilterWidget::actionDeleteTorrentsTriggered - , transferList, &TransferListWidget::deleteVisibleTorrents); - connect(m_categoryFilterWidget, &CategoryFilterWidget::actionPauseTorrentsTriggered - , transferList, &TransferListWidget::pauseVisibleTorrents); - connect(m_categoryFilterWidget, &CategoryFilterWidget::actionResumeTorrentsTriggered - , transferList, &TransferListWidget::startVisibleTorrents); - connect(m_categoryFilterWidget, &CategoryFilterWidget::categoryChanged - , transferList, &TransferListWidget::applyCategoryFilter); - toggleCategoryFilter(pref->getCategoryFilterState()); - frameLayout->addWidget(m_categoryFilterWidget); - - QCheckBox *tagsLabel = new QCheckBox(tr("Tags"), this); - tagsLabel->setChecked(pref->getTagFilterState()); - tagsLabel->setFont(font); - connect(tagsLabel, &QCheckBox::toggled, this, &TransferListFiltersWidget::onTagFilterStateChanged); - frameLayout->addWidget(tagsLabel); - - m_tagFilterWidget = new TagFilterWidget(this); - connect(m_tagFilterWidget, &TagFilterWidget::actionDeleteTorrentsTriggered - , transferList, &TransferListWidget::deleteVisibleTorrents); - connect(m_tagFilterWidget, &TagFilterWidget::actionPauseTorrentsTriggered - , transferList, &TransferListWidget::pauseVisibleTorrents); - connect(m_tagFilterWidget, &TagFilterWidget::actionResumeTorrentsTriggered - , transferList, &TransferListWidget::startVisibleTorrents); - connect(m_tagFilterWidget, &TagFilterWidget::tagChanged - , transferList, &TransferListWidget::applyTagFilter); - toggleTagFilter(pref->getTagFilterState()); - frameLayout->addWidget(m_tagFilterWidget); - - QCheckBox *trackerLabel = new QCheckBox(tr("Trackers"), this); - trackerLabel->setChecked(pref->getTrackerFilterState()); - trackerLabel->setFont(font); - frameLayout->addWidget(trackerLabel); - - m_trackerFilters = new TrackerFiltersList(this, transferList); - frameLayout->addWidget(m_trackerFilters); - - connect(statusLabel, &QCheckBox::toggled, statusFilters, &StatusFiltersWidget::toggleFilter); - connect(statusLabel, &QCheckBox::toggled, pref, &Preferences::setStatusFilterState); - connect(trackerLabel, &QCheckBox::toggled, m_trackerFilters, &TrackerFiltersList::toggleFilter); - connect(trackerLabel, &QCheckBox::toggled, pref, &Preferences::setTrackerFilterState); - - using Func = void (TransferListFiltersWidget::*)(const QString&, const QString&); - connect(this, static_cast(&TransferListFiltersWidget::trackerSuccess) - , m_trackerFilters, &TrackerFiltersList::trackerSuccess); - connect(this, static_cast(&TransferListFiltersWidget::trackerError) - , m_trackerFilters, &TrackerFiltersList::trackerError); - connect(this, static_cast(&TransferListFiltersWidget::trackerWarning) - , m_trackerFilters, &TrackerFiltersList::trackerWarning); -} - -void TransferListFiltersWidget::setDownloadTrackerFavicon(bool value) -{ - m_trackerFilters->setDownloadTrackerFavicon(value); -} - -void TransferListFiltersWidget::addTrackers(BitTorrent::TorrentHandle *const torrent, const QList &trackers) -{ - foreach (const BitTorrent::TrackerEntry &tracker, trackers) - m_trackerFilters->addItem(tracker.url(), torrent->hash()); -} - -void TransferListFiltersWidget::removeTrackers(BitTorrent::TorrentHandle *const torrent, const QList &trackers) -{ - foreach (const BitTorrent::TrackerEntry &tracker, trackers) - m_trackerFilters->removeItem(tracker.url(), torrent->hash()); -} - -void TransferListFiltersWidget::changeTrackerless(BitTorrent::TorrentHandle *const torrent, bool trackerless) -{ - m_trackerFilters->changeTrackerless(trackerless, torrent->hash()); -} - -void TransferListFiltersWidget::trackerSuccess(BitTorrent::TorrentHandle *const torrent, const QString &tracker) -{ - emit trackerSuccess(torrent->hash(), tracker); -} - -void TransferListFiltersWidget::trackerWarning(BitTorrent::TorrentHandle *const torrent, const QString &tracker) -{ - emit trackerWarning(torrent->hash(), tracker); -} - -void TransferListFiltersWidget::trackerError(BitTorrent::TorrentHandle *const torrent, const QString &tracker) -{ - emit trackerError(torrent->hash(), tracker); -} - -void TransferListFiltersWidget::onCategoryFilterStateChanged(bool enabled) -{ - toggleCategoryFilter(enabled); - Preferences::instance()->setCategoryFilterState(enabled); -} - -void TransferListFiltersWidget::toggleCategoryFilter(bool enabled) -{ - m_categoryFilterWidget->setVisible(enabled); - m_transferList->applyCategoryFilter(enabled ? m_categoryFilterWidget->currentCategory() : QString()); -} - -void TransferListFiltersWidget::onTagFilterStateChanged(bool enabled) -{ - toggleTagFilter(enabled); - Preferences::instance()->setTagFilterState(enabled); -} - -void TransferListFiltersWidget::toggleTagFilter(bool enabled) -{ - m_tagFilterWidget->setVisible(enabled); - m_transferList->applyTagFilter(enabled ? m_tagFilterWidget->currentTag() : QString()); -} diff --git a/src/gui/transferlistfilterswidget.h b/src/gui/transferlistfilterswidget.h deleted file mode 100644 index 98b1d6e9f..000000000 --- a/src/gui/transferlistfilterswidget.h +++ /dev/null @@ -1,176 +0,0 @@ -/* - * Bittorrent Client using Qt4 and libtorrent. - * Copyright (C) 2006 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 TRANSFERLISTFILTERSWIDGET_H -#define TRANSFERLISTFILTERSWIDGET_H - -#include -#include - -QT_BEGIN_NAMESPACE -class QResizeEvent; -class QCheckBox; -QT_END_NAMESPACE - -class TransferListWidget; - -namespace BitTorrent -{ - class TorrentHandle; - class TrackerEntry; -} - -class FiltersBase: public QListWidget -{ - Q_OBJECT - -public: - FiltersBase(QWidget *parent, TransferListWidget *transferList); - - virtual QSize sizeHint() const; - virtual QSize minimumSizeHint() const; - -public slots: - void toggleFilter(bool checked); - -protected: - TransferListWidget *transferList; - -private slots: - virtual void showMenu(QPoint) = 0; - virtual void applyFilter(int row) = 0; - virtual void handleNewTorrent(BitTorrent::TorrentHandle *const) = 0; - virtual void torrentAboutToBeDeleted(BitTorrent::TorrentHandle *const) = 0; -}; - -class StatusFiltersWidget: public FiltersBase -{ - Q_OBJECT - -public: - StatusFiltersWidget(QWidget *parent, TransferListWidget *transferList); - ~StatusFiltersWidget(); - -private slots: - void updateTorrentNumbers(); - -private: - // These 4 methods are virtual slots in the base class. - // No need to redeclare them here as slots. - virtual void showMenu(QPoint); - virtual void applyFilter(int row); - virtual void handleNewTorrent(BitTorrent::TorrentHandle *const); - virtual void torrentAboutToBeDeleted(BitTorrent::TorrentHandle *const); -}; - -class TrackerFiltersList: public FiltersBase -{ - Q_OBJECT - -public: - TrackerFiltersList(QWidget *parent, TransferListWidget *transferList); - ~TrackerFiltersList(); - - // Redefine addItem() to make sure the list stays sorted - void addItem(const QString &tracker, const QString &hash); - void removeItem(const QString &tracker, const QString &hash); - void changeTrackerless(bool trackerless, const QString &hash); - void setDownloadTrackerFavicon(bool value); - -public slots: - void trackerSuccess(const QString &hash, const QString &tracker); - void trackerError(const QString &hash, const QString &tracker); - void trackerWarning(const QString &hash, const QString &tracker); - -private slots: - void handleFavicoDownload(const QString &url, const QString &filePath); - void handleFavicoFailure(const QString &url, const QString &error); - -private: - // These 4 methods are virtual slots in the base class. - // No need to redeclare them here as slots. - virtual void showMenu(QPoint); - virtual void applyFilter(int row); - virtual void handleNewTorrent(BitTorrent::TorrentHandle *const torrent); - virtual void torrentAboutToBeDeleted(BitTorrent::TorrentHandle *const torrent); - QString trackerFromRow(int row) const; - int rowFromTracker(const QString &tracker) const; - QString getHost(const QString &tracker) const; - QStringList getHashes(int row); - void downloadFavicon(const QString &url); - -private: - QHash m_trackers; - QHash m_errors; - QHash m_warnings; - QStringList m_iconPaths; - int m_totalTorrents; - bool m_downloadTrackerFavicon; -}; - -class CategoryFilterWidget; -class TagFilterWidget; - -class TransferListFiltersWidget: public QFrame -{ - Q_OBJECT - -public: - TransferListFiltersWidget(QWidget *parent, TransferListWidget *transferList); - void setDownloadTrackerFavicon(bool value); - -public slots: - void addTrackers(BitTorrent::TorrentHandle *const torrent, const QList &trackers); - void removeTrackers(BitTorrent::TorrentHandle *const torrent, const QList &trackers); - void changeTrackerless(BitTorrent::TorrentHandle *const torrent, bool trackerless); - void trackerSuccess(BitTorrent::TorrentHandle *const torrent, const QString &tracker); - void trackerWarning(BitTorrent::TorrentHandle *const torrent, const QString &tracker); - void trackerError(BitTorrent::TorrentHandle *const torrent, const QString &tracker); - -signals: - void trackerSuccess(const QString &hash, const QString &tracker); - void trackerError(const QString &hash, const QString &tracker); - void trackerWarning(const QString &hash, const QString &tracker); - -private slots: - void onCategoryFilterStateChanged(bool enabled); - void onTagFilterStateChanged(bool enabled); - -private: - void toggleCategoryFilter(bool enabled); - void toggleTagFilter(bool enabled); - - TransferListWidget *m_transferList; - TrackerFiltersList *m_trackerFilters; - CategoryFilterWidget *m_categoryFilterWidget; - TagFilterWidget *m_tagFilterWidget; -}; - -#endif // TRANSFERLISTFILTERSWIDGET_H diff --git a/src/gui/transferlistsortmodel.cpp b/src/gui/transferlistsortmodel.cpp deleted file mode 100644 index 2bf3051e9..000000000 --- a/src/gui/transferlistsortmodel.cpp +++ /dev/null @@ -1,254 +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 - -#include "base/types.h" -#include "base/utils/string.h" -#include "base/bittorrent/torrenthandle.h" -#include "torrentmodel.h" -#include "transferlistsortmodel.h" - -TransferListSortModel::TransferListSortModel(QObject *parent) - : QSortFilterProxyModel(parent) -{ -} - -void TransferListSortModel::setStatusFilter(TorrentFilter::Type filter) -{ - if (m_filter.setType(filter)) - invalidateFilter(); -} - -void TransferListSortModel::setCategoryFilter(const QString &category) -{ - if (m_filter.setCategory(category)) - invalidateFilter(); -} - -void TransferListSortModel::disableCategoryFilter() -{ - if (m_filter.setCategory(TorrentFilter::AnyCategory)) - invalidateFilter(); -} - -void TransferListSortModel::setTagFilter(const QString &tag) -{ - if (m_filter.setTag(tag)) - invalidateFilter(); -} - -void TransferListSortModel::disableTagFilter() -{ - if (m_filter.setTag(TorrentFilter::AnyTag)) - invalidateFilter(); -} - -void TransferListSortModel::setTrackerFilter(const QStringList &hashes) -{ - if (m_filter.setHashSet(hashes.toSet())) - invalidateFilter(); -} - -void TransferListSortModel::disableTrackerFilter() -{ - if (m_filter.setHashSet(TorrentFilter::AnyHash)) - invalidateFilter(); -} - -bool TransferListSortModel::lessThan(const QModelIndex &left, const QModelIndex &right) const -{ - switch (sortColumn()) { - case TorrentModel::TR_CATEGORY: - case TorrentModel::TR_TAGS: - case TorrentModel::TR_NAME: { - QVariant vL = left.data(); - QVariant vR = right.data(); - if (!vL.isValid() || !vR.isValid() || (vL == vR)) - return lowerPositionThan(left, right); - - return Utils::String::naturalCompareCaseInsensitive(vL.toString(), vR.toString()); - } - - case TorrentModel::TR_ADD_DATE: - case TorrentModel::TR_SEED_DATE: - case TorrentModel::TR_SEEN_COMPLETE_DATE: { - return dateLessThan(sortColumn(), left, right, true); - } - - case TorrentModel::TR_PRIORITY: { - return lowerPositionThan(left, right); - } - - case TorrentModel::TR_SEEDS: - case TorrentModel::TR_PEERS: { - int left_active = left.data().toInt(); - int left_total = left.data(Qt::UserRole).toInt(); - int right_active = right.data().toInt(); - int right_total = right.data(Qt::UserRole).toInt(); - - // Active peers/seeds take precedence over total peers/seeds. - if (left_active == right_active) { - if (left_total == right_total) - return lowerPositionThan(left, right); - return (left_total < right_total); - } - else { - return (left_active < right_active); - } - } - - case TorrentModel::TR_ETA: { - TorrentModel *model = qobject_cast(sourceModel()); - const int prioL = model->data(model->index(left.row(), TorrentModel::TR_PRIORITY)).toInt(); - const int prioR = model->data(model->index(right.row(), TorrentModel::TR_PRIORITY)).toInt(); - const qlonglong etaL = left.data().toLongLong(); - const qlonglong etaR = right.data().toLongLong(); - const bool ascend = (sortOrder() == Qt::AscendingOrder); - const bool invalidL = (etaL < 0 || etaL >= MAX_ETA); - const bool invalidR = (etaR < 0 || etaR >= MAX_ETA); - const bool seedingL = (prioL < 0); - const bool seedingR = (prioR < 0); - - bool activeR = TorrentFilter::ActiveTorrent.match(model->torrentHandle(model->index(right.row()))); - bool activeL = TorrentFilter::ActiveTorrent.match(model->torrentHandle(model->index(left.row()))); - - // Sorting rules prioritized. - // 1. Active torrents at the top - // 2. Seeding torrents at the bottom - // 3. Torrents with invalid ETAs at the bottom - - if (activeL != activeR) return activeL; - if (seedingL != seedingR) { - if (seedingL) return !ascend; - else return ascend; - } - - if (invalidL && invalidR) { - if (seedingL) // Both seeding - return dateLessThan(TorrentModel::TR_SEED_DATE, left, right, true); - else - return prioL < prioR; - } - else if (!invalidL && !invalidR) { - return etaL < etaR; - } - else { - return !invalidL; - } - } - - case TorrentModel::TR_LAST_ACTIVITY: { - const qlonglong vL = left.data().toLongLong(); - const qlonglong vR = right.data().toLongLong(); - - if (vL == -1) return false; - if (vR == -1) return true; - - return vL < vR; - } - - case TorrentModel::TR_RATIO_LIMIT: { - const qreal vL = left.data().toDouble(); - const qreal vR = right.data().toDouble(); - - if (vL == -1) return false; - if (vR == -1) return true; - - return vL < vR; - } - - default: { - if (left.data() == right.data()) - return lowerPositionThan(left, right); - return QSortFilterProxyModel::lessThan(left, right); - } - } -} - -bool TransferListSortModel::lowerPositionThan(const QModelIndex &left, const QModelIndex &right) const -{ - const TorrentModel *model = qobject_cast(sourceModel()); - - // Sort according to TR_PRIORITY - const int queueL = model->data(model->index(left.row(), TorrentModel::TR_PRIORITY)).toInt(); - const int queueR = model->data(model->index(right.row(), TorrentModel::TR_PRIORITY)).toInt(); - if ((queueL > 0) || (queueR > 0)) { - if ((queueL > 0) && (queueR > 0)) - return queueL < queueR; - else - return queueL != 0; - } - - // Sort according to TR_SEED_DATE - return dateLessThan(TorrentModel::TR_SEED_DATE, left, right, false); -} - -// Every time we compare QDateTimes we need a fallback comparison in case both -// values are empty. This is a workaround for unstable sort in QSortFilterProxyModel -// (detailed discussion in #2526 and #2158). -bool TransferListSortModel::dateLessThan(const int dateColumn, const QModelIndex &left, const QModelIndex &right, bool sortInvalidInBottom) const -{ - const TorrentModel *model = qobject_cast(sourceModel()); - const QDateTime dateL = model->data(model->index(left.row(), dateColumn)).toDateTime(); - const QDateTime dateR = model->data(model->index(right.row(), dateColumn)).toDateTime(); - if (dateL.isValid() && dateR.isValid()) { - if (dateL != dateR) - return dateL < dateR; - } - else if (dateL.isValid()) { - return sortInvalidInBottom; - } - else if (dateR.isValid()) { - return !sortInvalidInBottom; - } - - // Finally, sort by hash - const QString hashL(model->torrentHandle(model->index(left.row()))->hash()); - const QString hashR(model->torrentHandle(model->index(right.row()))->hash()); - return hashL < hashR; -} - -bool TransferListSortModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const -{ - return matchFilter(sourceRow, sourceParent) - && QSortFilterProxyModel::filterAcceptsRow(sourceRow, sourceParent); -} - -bool TransferListSortModel::matchFilter(int sourceRow, const QModelIndex &sourceParent) const -{ - TorrentModel *model = qobject_cast(sourceModel()); - if (!model) return false; - - BitTorrent::TorrentHandle *const torrent = model->torrentHandle(model->index(sourceRow, 0, sourceParent)); - if (!torrent) return false; - - return m_filter.match(torrent); -} diff --git a/src/gui/transferlistsortmodel.h b/src/gui/transferlistsortmodel.h deleted file mode 100644 index 1e092340d..000000000 --- a/src/gui/transferlistsortmodel.h +++ /dev/null @@ -1,65 +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 TRANSFERLISTSORTMODEL_H -#define TRANSFERLISTSORTMODEL_H - -#include -#include "base/torrentfilter.h" - -class QStringList; - -class TransferListSortModel: public QSortFilterProxyModel -{ - Q_OBJECT - -public: - TransferListSortModel(QObject *parent = 0); - - void setStatusFilter(TorrentFilter::Type filter); - void setCategoryFilter(const QString &category); - void disableCategoryFilter(); - void setTagFilter(const QString &tag); - void disableTagFilter(); - void setTrackerFilter(const QStringList &hashes); - void disableTrackerFilter(); - -private: - bool lessThan(const QModelIndex &left, const QModelIndex &right) const; - bool lowerPositionThan(const QModelIndex &left, const QModelIndex &right) const; - bool dateLessThan(const int dateColumn, const QModelIndex &left, const QModelIndex &right, bool sortInvalidInBottom) const; - bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const; - bool matchFilter(int sourceRow, const QModelIndex &sourceParent) const; - -private: - TorrentFilter m_filter; -}; - -#endif // TRANSFERLISTSORTMODEL_H diff --git a/src/gui/transferlistwidget.cpp b/src/gui/transferlistwidget.cpp deleted file mode 100644 index b45c6e184..000000000 --- a/src/gui/transferlistwidget.cpp +++ /dev/null @@ -1,1207 +0,0 @@ -/* - * Bittorrent Client using Qt4 and libtorrent. - * Copyright (C) 2006 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 "transferlistwidget.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "autoexpandabledialog.h" -#include "base/bittorrent/session.h" -#include "base/bittorrent/torrenthandle.h" -#include "base/logger.h" -#include "base/preferences.h" -#include "base/torrentfilter.h" -#include "base/utils/fs.h" -#include "base/utils/string.h" -#include "deletionconfirmationdlg.h" -#include "guiiconprovider.h" -#include "mainwindow.h" -#include "optionsdlg.h" -#include "previewselect.h" -#include "speedlimitdlg.h" -#include "torrentmodel.h" -#include "transferlistdelegate.h" -#include "transferlistsortmodel.h" -#include "updownratiodlg.h" - -namespace -{ - using ToggleFn = std::function; - - QStringList extractHashes(const QList &torrents) - { - QStringList hashes; - foreach (BitTorrent::TorrentHandle *const torrent, torrents) - hashes << torrent->hash(); - - return hashes; - } - - // Helper for setting style parameters when painting check box primitives. - class CheckBoxIconHelper: public QCheckBox - { - public: - explicit CheckBoxIconHelper(QWidget *parent); - QSize sizeHint() const override; - void initStyleOption(QStyleOptionButton *opt) const; - - protected: - void paintEvent(QPaintEvent *) override {} - }; - - CheckBoxIconHelper::CheckBoxIconHelper(QWidget *parent) - : QCheckBox(parent) - { - setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); - } - - QSize CheckBoxIconHelper::sizeHint() const - { - const int dim = QCheckBox::sizeHint().height(); - return QSize(dim, dim); - } - - void CheckBoxIconHelper::initStyleOption(QStyleOptionButton *opt) const - { - QCheckBox::initStyleOption(opt); - } - - // Tristate checkbox styled for use in menus. - class MenuCheckBox: public QWidget - { - public: - MenuCheckBox(const QString &text, const ToggleFn &onToggle, Qt::CheckState initialState); - QSize sizeHint() const override; - - protected: - void paintEvent(QPaintEvent *e) override; - void mousePressEvent(QMouseEvent *) override; - - private: - CheckBoxIconHelper *const m_checkBox; - const QString m_text; - QSize m_sizeHint; - QSize m_checkBoxOffset; - }; - - MenuCheckBox::MenuCheckBox(const QString &text, const ToggleFn &onToggle, Qt::CheckState initialState) - : m_checkBox(new CheckBoxIconHelper(this)) - , m_text(text) - , m_sizeHint(QCheckBox(m_text).sizeHint()) - { - m_checkBox->setCheckState(initialState); - connect(m_checkBox, &QCheckBox::stateChanged, [this, onToggle](int newState) - { - m_checkBox->setTristate(false); - onToggle(static_cast(newState)); - }); - setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); - setMouseTracking(true); - - // We attempt to mimic the amount of vertical whitespace padding around a QCheckBox. - QSize layoutPadding(3, 0); - const int sizeHintMargin = (m_sizeHint.height() - m_checkBox->sizeHint().height()) / 2; - if (sizeHintMargin > 0) { - m_checkBoxOffset.setHeight(sizeHintMargin); - } - else { - layoutPadding.setHeight(1); - m_checkBoxOffset.setHeight(1); - } - m_checkBoxOffset.setWidth(layoutPadding.width()); - - QHBoxLayout *layout = new QHBoxLayout(this); - layout->addWidget(m_checkBox); - layout->addStretch(); - layout->setContentsMargins(layoutPadding.width(), layoutPadding.height(), layoutPadding.width(), layoutPadding.height()); - setLayout(layout); - } - - QSize MenuCheckBox::sizeHint() const - { - return m_sizeHint; - } - - void MenuCheckBox::paintEvent(QPaintEvent *e) - { - if (!rect().intersects(e->rect())) - return; - QStylePainter painter(this); - QStyleOptionMenuItem menuOpt; - menuOpt.initFrom(this); - menuOpt.menuItemType = QStyleOptionMenuItem::Normal; - menuOpt.text = m_text; - QStyleOptionButton checkBoxOpt; - m_checkBox->initStyleOption(&checkBoxOpt); - checkBoxOpt.rect.translate(m_checkBoxOffset.width(), m_checkBoxOffset.height()); - if (rect().contains(mapFromGlobal(QCursor::pos()))) { - menuOpt.state |= QStyle::State_Selected; - checkBoxOpt.state |= QStyle::State_MouseOver; - } - painter.drawControl(QStyle::CE_MenuItem, menuOpt); - painter.drawPrimitive(QStyle::PE_IndicatorCheckBox, checkBoxOpt); - } - - void MenuCheckBox::mousePressEvent(QMouseEvent *) - { - m_checkBox->click(); - } - - class CheckBoxMenuItem: public QWidgetAction - { - public: - CheckBoxMenuItem(const QString &text, const ToggleFn &onToggle, Qt::CheckState initialState, QObject *parent) - : QWidgetAction(parent) - { - setDefaultWidget(new MenuCheckBox(text, onToggle, initialState)); - } - }; -} - -TransferListWidget::TransferListWidget(QWidget *parent, MainWindow *main_window) - : QTreeView(parent) - , main_window(main_window) -{ - - setUniformRowHeights(true); - // Load settings - bool column_loaded = loadSettings(); - - // Create and apply delegate - listDelegate = new TransferListDelegate(this); - setItemDelegate(listDelegate); - - // Create transfer list model - listModel = new TorrentModel(this); - - nameFilterModel = new TransferListSortModel(); - nameFilterModel->setDynamicSortFilter(true); - nameFilterModel->setSourceModel(listModel); - nameFilterModel->setFilterKeyColumn(TorrentModel::TR_NAME); - nameFilterModel->setFilterRole(Qt::DisplayRole); - nameFilterModel->setSortCaseSensitivity(Qt::CaseInsensitive); - - setModel(nameFilterModel); - - // Visual settings - setRootIsDecorated(false); - setAllColumnsShowFocus(true); - setSortingEnabled(true); - setSelectionMode(QAbstractItemView::ExtendedSelection); - setItemsExpandable(false); - setAutoScroll(true); - setDragDropMode(QAbstractItemView::DragOnly); -#if defined(Q_OS_MAC) - setAttribute(Qt::WA_MacShowFocusRect, false); -#endif - header()->setStretchLastSection(false); - - // Default hidden columns - if (!column_loaded) { - setColumnHidden(TorrentModel::TR_ADD_DATE, true); - setColumnHidden(TorrentModel::TR_SEED_DATE, true); - setColumnHidden(TorrentModel::TR_UPLIMIT, true); - setColumnHidden(TorrentModel::TR_DLLIMIT, true); - setColumnHidden(TorrentModel::TR_TRACKER, true); - setColumnHidden(TorrentModel::TR_AMOUNT_DOWNLOADED, true); - setColumnHidden(TorrentModel::TR_AMOUNT_UPLOADED, true); - setColumnHidden(TorrentModel::TR_AMOUNT_DOWNLOADED_SESSION, true); - setColumnHidden(TorrentModel::TR_AMOUNT_UPLOADED_SESSION, true); - setColumnHidden(TorrentModel::TR_AMOUNT_LEFT, true); - setColumnHidden(TorrentModel::TR_TIME_ELAPSED, true); - setColumnHidden(TorrentModel::TR_SAVE_PATH, true); - setColumnHidden(TorrentModel::TR_COMPLETED, true); - setColumnHidden(TorrentModel::TR_RATIO_LIMIT, true); - setColumnHidden(TorrentModel::TR_SEEN_COMPLETE_DATE, true); - setColumnHidden(TorrentModel::TR_LAST_ACTIVITY, true); - setColumnHidden(TorrentModel::TR_TOTAL_SIZE, true); - } - - //Ensure that at least one column is visible at all times - bool atLeastOne = false; - for (unsigned int i = 0; isetContextMenuPolicy(Qt::CustomContextMenu); - connect(header(), SIGNAL(customContextMenuRequested(const QPoint &)), this, SLOT(displayDLHoSMenu(const QPoint &))); - connect(header(), SIGNAL(sectionMoved(int, int, int)), this, SLOT(saveSettings())); - connect(header(), SIGNAL(sectionResized(int, int, int)), this, SLOT(saveSettings())); - connect(header(), SIGNAL(sortIndicatorChanged(int, Qt::SortOrder)), this, SLOT(saveSettings())); - - editHotkey = new QShortcut(Qt::Key_F2, this, SLOT(renameSelectedTorrent()), 0, Qt::WidgetShortcut); - deleteHotkey = new QShortcut(QKeySequence::Delete, this, SLOT(softDeleteSelectedTorrents()), 0, Qt::WidgetShortcut); - permDeleteHotkey = new QShortcut(Qt::SHIFT + Qt::Key_Delete, this, SLOT(permDeleteSelectedTorrents()), 0, Qt::WidgetShortcut); - doubleClickHotkey = new QShortcut(Qt::Key_Return, this, SLOT(torrentDoubleClicked()), 0, Qt::WidgetShortcut); - recheckHotkey = new QShortcut(Qt::CTRL + Qt::Key_R, this, SLOT(recheckSelectedTorrents()), 0, Qt::WidgetShortcut); - - // This hack fixes reordering of first column with Qt5. - // https://github.com/qtproject/qtbase/commit/e0fc088c0c8bc61dbcaf5928b24986cd61a22777 - QTableView unused; - unused.setVerticalHeader(header()); - header()->setParent(this); - unused.setVerticalHeader(new QHeaderView(Qt::Horizontal)); -} - -TransferListWidget::~TransferListWidget() -{ - qDebug() << Q_FUNC_INFO << "ENTER"; - // Save settings - saveSettings(); - // Clean up - delete nameFilterModel; - delete listModel; - delete listDelegate; - qDebug() << Q_FUNC_INFO << "EXIT"; -} - -TorrentModel* TransferListWidget::getSourceModel() const -{ - return listModel; -} - -void TransferListWidget::previewFile(QString filePath) -{ - Utils::Misc::openPath(filePath); -} - -inline QModelIndex TransferListWidget::mapToSource(const QModelIndex &index) const -{ - Q_ASSERT(index.isValid()); - if (index.model() == nameFilterModel) - return nameFilterModel->mapToSource(index); - return index; -} - -inline QModelIndex TransferListWidget::mapFromSource(const QModelIndex &index) const -{ - Q_ASSERT(index.isValid()); - Q_ASSERT(index.model() == nameFilterModel); - return nameFilterModel->mapFromSource(index); -} - -void TransferListWidget::torrentDoubleClicked() -{ - const QModelIndexList selectedIndexes = selectionModel()->selectedRows(); - if ((selectedIndexes.size() != 1) || !selectedIndexes.first().isValid()) return; - - const QModelIndex index = listModel->index(mapToSource(selectedIndexes.first()).row()); - BitTorrent::TorrentHandle *const torrent = listModel->torrentHandle(index); - if (!torrent) return; - - int action; - if (torrent->isSeed()) - action = Preferences::instance()->getActionOnDblClOnTorrentFn(); - else - action = Preferences::instance()->getActionOnDblClOnTorrentDl(); - - switch(action) { - case TOGGLE_PAUSE: - if (torrent->isPaused()) - torrent->resume(); - else - torrent->pause(); - break; - case OPEN_DEST: - if (torrent->filesCount() == 1) - Utils::Misc::openFolderSelect(torrent->contentPath(true)); - else - Utils::Misc::openPath(torrent->contentPath(true)); - break; - } -} - -QList TransferListWidget::getSelectedTorrents() const -{ - QList torrents; - foreach (const QModelIndex &index, selectionModel()->selectedRows()) - torrents << listModel->torrentHandle(mapToSource(index)); - - return torrents; -} - -void TransferListWidget::setSelectedTorrentsLocation() -{ - const QList torrents = getSelectedTorrents(); - if (torrents.isEmpty()) return; - - const QString oldLocation = torrents[0]->savePath(); - qDebug("Old location is %s", qPrintable(oldLocation)); - - const QString newLocation = QFileDialog::getExistingDirectory(this, tr("Choose save path"), oldLocation, - QFileDialog::DontConfirmOverwrite | QFileDialog::ShowDirsOnly | QFileDialog::HideNameFilterDetails); - if (newLocation.isEmpty() || !QDir(newLocation).exists()) return; - qDebug("New location is %s", qPrintable(newLocation)); - - // Actually move storage - foreach (BitTorrent::TorrentHandle *const torrent, torrents) { - Logger::instance()->addMessage(tr("Set location: moving \"%1\", from \"%2\" to \"%3\"", "Set location: moving \"ubuntu_16_04.iso\", from \"/home/dir1\" to \"/home/dir2\"").arg(torrent->name()).arg(torrent->savePath()).arg(newLocation)); - torrent->move(Utils::Fs::expandPathAbs(newLocation)); - } -} - -void TransferListWidget::pauseAllTorrents() -{ - foreach (BitTorrent::TorrentHandle *const torrent, BitTorrent::Session::instance()->torrents()) - torrent->pause(); -} - -void TransferListWidget::resumeAllTorrents() -{ - foreach (BitTorrent::TorrentHandle *const torrent, BitTorrent::Session::instance()->torrents()) - torrent->resume(); -} - -void TransferListWidget::startSelectedTorrents() -{ - foreach (BitTorrent::TorrentHandle *const torrent, getSelectedTorrents()) - torrent->resume(); -} - -void TransferListWidget::forceStartSelectedTorrents() -{ - foreach (BitTorrent::TorrentHandle *const torrent, getSelectedTorrents()) - torrent->resume(true); -} - -void TransferListWidget::startVisibleTorrents() -{ - for (int i = 0; i < nameFilterModel->rowCount(); ++i) { - BitTorrent::TorrentHandle *const torrent = listModel->torrentHandle(mapToSource(nameFilterModel->index(i, 0))); - if (torrent) - torrent->resume(); - } -} - -void TransferListWidget::pauseSelectedTorrents() -{ - foreach (BitTorrent::TorrentHandle *const torrent, getSelectedTorrents()) - torrent->pause(); -} - -void TransferListWidget::pauseVisibleTorrents() -{ - for (int i = 0; i < nameFilterModel->rowCount(); ++i) { - BitTorrent::TorrentHandle *const torrent = listModel->torrentHandle(mapToSource(nameFilterModel->index(i, 0))); - if (torrent) - torrent->pause(); - } -} - -void TransferListWidget::softDeleteSelectedTorrents() -{ - deleteSelectedTorrents(false); -} - -void TransferListWidget::permDeleteSelectedTorrents() -{ - deleteSelectedTorrents(true); -} - -void TransferListWidget::deleteSelectedTorrents(bool deleteLocalFiles) -{ - if (main_window->currentTabWidget() != this) return; - - const QList torrents = getSelectedTorrents(); - if (torrents.empty()) return; - - if (Preferences::instance()->confirmTorrentDeletion() - && !DeletionConfirmationDlg::askForDeletionConfirmation(this, deleteLocalFiles, torrents.size(), torrents[0]->name())) - return; - foreach (BitTorrent::TorrentHandle *const torrent, torrents) - BitTorrent::Session::instance()->deleteTorrent(torrent->hash(), deleteLocalFiles); -} - -void TransferListWidget::deleteVisibleTorrents() -{ - if (nameFilterModel->rowCount() <= 0) return; - - QList torrents; - for (int i = 0; i < nameFilterModel->rowCount(); ++i) - torrents << listModel->torrentHandle(mapToSource(nameFilterModel->index(i, 0))); - - bool deleteLocalFiles = false; - if (Preferences::instance()->confirmTorrentDeletion() - && !DeletionConfirmationDlg::askForDeletionConfirmation(this, deleteLocalFiles, torrents.size(), torrents[0]->name())) - return; - - foreach (BitTorrent::TorrentHandle *const torrent, torrents) - BitTorrent::Session::instance()->deleteTorrent(torrent->hash(), deleteLocalFiles); -} - -void TransferListWidget::increasePrioSelectedTorrents() -{ - qDebug() << Q_FUNC_INFO; - if (main_window->currentTabWidget() == this) - BitTorrent::Session::instance()->increaseTorrentsPriority(extractHashes(getSelectedTorrents())); -} - -void TransferListWidget::decreasePrioSelectedTorrents() -{ - qDebug() << Q_FUNC_INFO; - if (main_window->currentTabWidget() == this) - BitTorrent::Session::instance()->decreaseTorrentsPriority(extractHashes(getSelectedTorrents())); -} - -void TransferListWidget::topPrioSelectedTorrents() -{ - if (main_window->currentTabWidget() == this) - BitTorrent::Session::instance()->topTorrentsPriority(extractHashes(getSelectedTorrents())); -} - -void TransferListWidget::bottomPrioSelectedTorrents() -{ - if (main_window->currentTabWidget() == this) - BitTorrent::Session::instance()->bottomTorrentsPriority(extractHashes(getSelectedTorrents())); -} - -void TransferListWidget::copySelectedMagnetURIs() const -{ - QStringList magnet_uris; - foreach (BitTorrent::TorrentHandle *const torrent, getSelectedTorrents()) - magnet_uris << torrent->toMagnetUri(); - - qApp->clipboard()->setText(magnet_uris.join("\n")); -} - -void TransferListWidget::copySelectedNames() const -{ - QStringList torrent_names; - foreach (BitTorrent::TorrentHandle *const torrent, getSelectedTorrents()) - torrent_names << torrent->name(); - - qApp->clipboard()->setText(torrent_names.join("\n")); -} - -void TransferListWidget::copySelectedHashes() const -{ - QStringList torrentHashes; - foreach (BitTorrent::TorrentHandle *const torrent, getSelectedTorrents()) - torrentHashes << torrent->hash(); - - qApp->clipboard()->setText(torrentHashes.join('\n')); -} - -void TransferListWidget::hidePriorityColumn(bool hide) -{ - qDebug("hidePriorityColumn(%d)", hide); - setColumnHidden(TorrentModel::TR_PRIORITY, hide); - if (!hide && !columnWidth(TorrentModel::TR_PRIORITY)) - resizeColumnToContents(TorrentModel::TR_PRIORITY); -} - -void TransferListWidget::openSelectedTorrentsFolder() const -{ - QSet pathsList; - foreach (BitTorrent::TorrentHandle *const torrent, getSelectedTorrents()) { - QString path = torrent->contentPath(true); - if (!pathsList.contains(path)) { - if (torrent->filesCount() == 1) - Utils::Misc::openFolderSelect(path); - else - Utils::Misc::openPath(path); - } - pathsList.insert(path); - } -} - -void TransferListWidget::previewSelectedTorrents() -{ - foreach (BitTorrent::TorrentHandle *const torrent, getSelectedTorrents()) { - if (torrent->hasMetadata()) - new PreviewSelect(this, torrent); - } -} - -void TransferListWidget::setDlLimitSelectedTorrents() -{ - QList TorrentsList; - foreach (BitTorrent::TorrentHandle *const torrent, getSelectedTorrents()) { - if (torrent->isSeed()) - continue; - TorrentsList += torrent; - } - if (TorrentsList.empty()) return; - - int oldLimit = TorrentsList.first()->downloadLimit(); - foreach (BitTorrent::TorrentHandle *const torrent, TorrentsList) { - if (torrent->downloadLimit() != oldLimit) { - oldLimit = -1; - break; - } - } - - bool ok = false; - const long newLimit = SpeedLimitDialog::askSpeedLimit( - this, &ok, tr("Torrent Download Speed Limiting"), oldLimit - , BitTorrent::Session::instance()->globalDownloadSpeedLimit()); - if (!ok) return; - - foreach (BitTorrent::TorrentHandle *const torrent, TorrentsList) { - qDebug("Applying download speed limit of %ld Kb/s to torrent %s", (newLimit / 1024l), qPrintable(torrent->hash())); - torrent->setDownloadLimit(newLimit); - } -} - -void TransferListWidget::setUpLimitSelectedTorrents() -{ - QList TorrentsList = getSelectedTorrents(); - if (TorrentsList.empty()) return; - - int oldLimit = TorrentsList.first()->uploadLimit(); - foreach (BitTorrent::TorrentHandle *const torrent, TorrentsList) { - if (torrent->uploadLimit() != oldLimit) { - oldLimit = -1; - break; - } - } - - bool ok = false; - const long newLimit = SpeedLimitDialog::askSpeedLimit( - this, &ok, tr("Torrent Upload Speed Limiting"), oldLimit - , BitTorrent::Session::instance()->globalUploadSpeedLimit()); - if (!ok) return; - - foreach (BitTorrent::TorrentHandle *const torrent, TorrentsList) { - qDebug("Applying upload speed limit of %ld Kb/s to torrent %s", (newLimit / 1024l), qPrintable(torrent->hash())); - torrent->setUploadLimit(newLimit); - } -} - -void TransferListWidget::setMaxRatioSelectedTorrents() -{ - const QList torrents = getSelectedTorrents(); - if (torrents.isEmpty()) return; - - bool useGlobalValue = true; - qreal currentMaxRatio = BitTorrent::Session::instance()->globalMaxRatio(); - if (torrents.count() == 1) - currentMaxRatio = torrents[0]->maxRatio(&useGlobalValue); - - int currentMaxSeedingTime = BitTorrent::Session::instance()->globalMaxSeedingMinutes(); - if (torrents.count() == 1) - currentMaxSeedingTime = torrents[0]->maxSeedingTime(&useGlobalValue); - - UpDownRatioDlg dlg(useGlobalValue, currentMaxRatio, BitTorrent::TorrentHandle::MAX_RATIO, - currentMaxSeedingTime, BitTorrent::TorrentHandle::MAX_SEEDING_TIME, this); - if (dlg.exec() != QDialog::Accepted) return; - - foreach (BitTorrent::TorrentHandle *const torrent, torrents) { - qreal ratio = (dlg.useDefault() ? BitTorrent::TorrentHandle::USE_GLOBAL_RATIO : dlg.ratio()); - torrent->setRatioLimit(ratio); - - int seedingTime = (dlg.useDefault() ? BitTorrent::TorrentHandle::USE_GLOBAL_SEEDING_TIME : dlg.seedingTime()); - torrent->setSeedingTimeLimit(seedingTime); - } -} - -void TransferListWidget::recheckSelectedTorrents() -{ - if (Preferences::instance()->confirmTorrentRecheck()) { - QMessageBox::StandardButton ret = QMessageBox::question(this, tr("Recheck confirmation"), tr("Are you sure you want to recheck the selected torrent(s)?"), QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes); - if (ret != QMessageBox::Yes) return; - } - - foreach (BitTorrent::TorrentHandle *const torrent, getSelectedTorrents()) - torrent->forceRecheck(); -} - -// hide/show columns menu -void TransferListWidget::displayDLHoSMenu(const QPoint&) -{ - QMenu hideshowColumn(this); - hideshowColumn.setTitle(tr("Column visibility")); - QList actions; - for (int i = 0; i < listModel->columnCount(); ++i) { - if (!BitTorrent::Session::instance()->isQueueingSystemEnabled() && i == TorrentModel::TR_PRIORITY) { - actions.append(0); - continue; - } - QAction *myAct = hideshowColumn.addAction(listModel->headerData(i, Qt::Horizontal, Qt::DisplayRole).toString()); - myAct->setCheckable(true); - myAct->setChecked(!isColumnHidden(i)); - actions.append(myAct); - } - int visibleCols = 0; - for (unsigned int i = 0; i 1) - break; - } - - // Call menu - QAction *act = hideshowColumn.exec(QCursor::pos()); - if (act) { - int col = actions.indexOf(act); - Q_ASSERT(col >= 0); - Q_ASSERT(visibleCols > 0); - if (!isColumnHidden(col) && visibleCols == 1) - return; - qDebug("Toggling column %d visibility", col); - setColumnHidden(col, !isColumnHidden(col)); - if (!isColumnHidden(col) && columnWidth(col) <= 5) - setColumnWidth(col, 100); - saveSettings(); - } -} - -void TransferListWidget::toggleSelectedTorrentsSuperSeeding() const -{ - foreach (BitTorrent::TorrentHandle *const torrent, getSelectedTorrents()) { - if (torrent->hasMetadata()) - torrent->setSuperSeeding(!torrent->superSeeding()); - } -} - -void TransferListWidget::toggleSelectedTorrentsSequentialDownload() const -{ - foreach (BitTorrent::TorrentHandle *const torrent, getSelectedTorrents()) - torrent->toggleSequentialDownload(); -} - -void TransferListWidget::toggleSelectedFirstLastPiecePrio() const -{ - foreach (BitTorrent::TorrentHandle *const torrent, getSelectedTorrents()) - torrent->toggleFirstLastPiecePriority(); -} - -void TransferListWidget::setSelectedAutoTMMEnabled(bool enabled) const -{ - foreach (BitTorrent::TorrentHandle *const torrent, getSelectedTorrents()) - torrent->setAutoTMMEnabled(enabled); -} - -void TransferListWidget::askNewCategoryForSelection() -{ - // Ask for category - bool ok; - bool invalid; - do { - invalid = false; - const QString category = AutoExpandableDialog::getText(this, tr("New Category"), tr("Category:"), QLineEdit::Normal, "", &ok).trimmed(); - if (ok && !category.isEmpty()) { - if (!BitTorrent::Session::isValidCategoryName(category)) { - QMessageBox::warning(this, tr("Invalid category name"), - tr("Category name must not contain '\\'.\n" - "Category name must not start/end with '/'.\n" - "Category name must not contain '//' sequence.")); - invalid = true; - } - else { - setSelectionCategory(category); - } - } - } while(invalid); -} - -void TransferListWidget::askAddTagsForSelection() -{ - const QStringList tags = askTagsForSelection(tr("Add Tags")); - foreach (const QString &tag, tags) - addSelectionTag(tag); -} - -void TransferListWidget::confirmRemoveAllTagsForSelection() -{ - QMessageBox::StandardButton response = QMessageBox::question( - this, tr("Remove All Tags"), tr("Remove all tags from selected torrents?"), - QMessageBox::Yes | QMessageBox::No); - if (response == QMessageBox::Yes) - clearSelectionTags(); -} - -QStringList TransferListWidget::askTagsForSelection(const QString &dialogTitle) -{ - QStringList tags; - bool invalid = true; - while (invalid) { - bool ok = false; - invalid = false; - const QString tagsInput = AutoExpandableDialog::getText( - this, dialogTitle, tr("Comma-separated tags:"), QLineEdit::Normal, "", &ok).trimmed(); - if (!ok || tagsInput.isEmpty()) - return QStringList(); - tags = tagsInput.split(',', QString::SkipEmptyParts); - for (QString &tag : tags) { - tag = tag.trimmed(); - if (!BitTorrent::Session::isValidTag(tag)) { - QMessageBox::warning(this, tr("Invalid tag") - , tr("Tag name: '%1' is invalid").arg(tag)); - invalid = true; - } - } - } - return tags; -} - -void TransferListWidget::applyToSelectedTorrents(const std::function &fn) -{ - foreach (const QModelIndex &index, selectionModel()->selectedRows()) { - BitTorrent::TorrentHandle *const torrent = listModel->torrentHandle(mapToSource(index)); - Q_ASSERT(torrent); - fn(torrent); - } -} - -void TransferListWidget::renameSelectedTorrent() -{ - const QModelIndexList selectedIndexes = selectionModel()->selectedRows(); - if ((selectedIndexes.size() != 1) || !selectedIndexes.first().isValid()) return; - - const QModelIndex mi = listModel->index(mapToSource(selectedIndexes.first()).row(), TorrentModel::TR_NAME); - BitTorrent::TorrentHandle *const torrent = listModel->torrentHandle(mi); - if (!torrent) return; - - // Ask for a new Name - bool ok; - QString name = AutoExpandableDialog::getText(this, tr("Rename"), tr("New name:"), QLineEdit::Normal, torrent->name(), &ok); - if (ok && !name.isEmpty()) { - name.replace(QRegExp("\r?\n|\r"), " "); - // Rename the torrent - listModel->setData(mi, name, Qt::DisplayRole); - } -} - -void TransferListWidget::setSelectionCategory(QString category) -{ - foreach (const QModelIndex &index, selectionModel()->selectedRows()) - listModel->setData(listModel->index(mapToSource(index).row(), TorrentModel::TR_CATEGORY), category, Qt::DisplayRole); -} - -void TransferListWidget::addSelectionTag(const QString &tag) -{ - applyToSelectedTorrents([&tag](BitTorrent::TorrentHandle *const torrent) { torrent->addTag(tag); }); -} - -void TransferListWidget::removeSelectionTag(const QString &tag) -{ - applyToSelectedTorrents([&tag](BitTorrent::TorrentHandle *const torrent) { torrent->removeTag(tag); }); -} - -void TransferListWidget::clearSelectionTags() -{ - applyToSelectedTorrents([](BitTorrent::TorrentHandle *const torrent) { torrent->removeAllTags(); }); -} - -void TransferListWidget::displayListMenu(const QPoint&) -{ - QModelIndexList selectedIndexes = selectionModel()->selectedRows(); - if (selectedIndexes.size() == 0) return; - - // Create actions - QAction actionStart(GuiIconProvider::instance()->getIcon("media-playback-start"), tr("Resume", "Resume/start the torrent"), 0); - connect(&actionStart, SIGNAL(triggered()), this, SLOT(startSelectedTorrents())); - QAction actionPause(GuiIconProvider::instance()->getIcon("media-playback-pause"), tr("Pause", "Pause the torrent"), 0); - connect(&actionPause, SIGNAL(triggered()), this, SLOT(pauseSelectedTorrents())); - QAction actionForceStart(GuiIconProvider::instance()->getIcon("media-seek-forward"), tr("Force Resume", "Force Resume/start the torrent"), 0); - connect(&actionForceStart, SIGNAL(triggered()), this, SLOT(forceStartSelectedTorrents())); - QAction actionDelete(GuiIconProvider::instance()->getIcon("edit-delete"), tr("Delete", "Delete the torrent"), 0); - connect(&actionDelete, SIGNAL(triggered()), this, SLOT(softDeleteSelectedTorrents())); - QAction actionPreview_file(GuiIconProvider::instance()->getIcon("view-preview"), tr("Preview file..."), 0); - connect(&actionPreview_file, SIGNAL(triggered()), this, SLOT(previewSelectedTorrents())); - QAction actionSet_max_ratio(QIcon(QString::fromUtf8(":/icons/skin/ratio.png")), tr("Limit share ratio..."), 0); - connect(&actionSet_max_ratio, SIGNAL(triggered()), this, SLOT(setMaxRatioSelectedTorrents())); - QAction actionSet_upload_limit(GuiIconProvider::instance()->getIcon("kt-set-max-upload-speed"), tr("Limit upload rate..."), 0); - connect(&actionSet_upload_limit, SIGNAL(triggered()), this, SLOT(setUpLimitSelectedTorrents())); - QAction actionSet_download_limit(GuiIconProvider::instance()->getIcon("kt-set-max-download-speed"), tr("Limit download rate..."), 0); - connect(&actionSet_download_limit, SIGNAL(triggered()), this, SLOT(setDlLimitSelectedTorrents())); - QAction actionOpen_destination_folder(GuiIconProvider::instance()->getIcon("inode-directory"), tr("Open destination folder"), 0); - connect(&actionOpen_destination_folder, SIGNAL(triggered()), this, SLOT(openSelectedTorrentsFolder())); - QAction actionIncreasePriority(GuiIconProvider::instance()->getIcon("go-up"), tr("Move up", "i.e. move up in the queue"), 0); - connect(&actionIncreasePriority, SIGNAL(triggered()), this, SLOT(increasePrioSelectedTorrents())); - QAction actionDecreasePriority(GuiIconProvider::instance()->getIcon("go-down"), tr("Move down", "i.e. Move down in the queue"), 0); - connect(&actionDecreasePriority, SIGNAL(triggered()), this, SLOT(decreasePrioSelectedTorrents())); - QAction actionTopPriority(GuiIconProvider::instance()->getIcon("go-top"), tr("Move to top", "i.e. Move to top of the queue"), 0); - connect(&actionTopPriority, SIGNAL(triggered()), this, SLOT(topPrioSelectedTorrents())); - QAction actionBottomPriority(GuiIconProvider::instance()->getIcon("go-bottom"), tr("Move to bottom", "i.e. Move to bottom of the queue"), 0); - connect(&actionBottomPriority, SIGNAL(triggered()), this, SLOT(bottomPrioSelectedTorrents())); - QAction actionSetTorrentPath(GuiIconProvider::instance()->getIcon("inode-directory"), tr("Set location..."), 0); - connect(&actionSetTorrentPath, SIGNAL(triggered()), this, SLOT(setSelectedTorrentsLocation())); - QAction actionForce_recheck(GuiIconProvider::instance()->getIcon("document-edit-verify"), tr("Force recheck"), 0); - connect(&actionForce_recheck, SIGNAL(triggered()), this, SLOT(recheckSelectedTorrents())); - QAction actionCopy_magnet_link(GuiIconProvider::instance()->getIcon("kt-magnet"), tr("Copy magnet link"), 0); - connect(&actionCopy_magnet_link, SIGNAL(triggered()), this, SLOT(copySelectedMagnetURIs())); - QAction actionCopy_name(GuiIconProvider::instance()->getIcon("edit-copy"), tr("Copy name"), 0); - connect(&actionCopy_name, SIGNAL(triggered()), this, SLOT(copySelectedNames())); - QAction actionCopyHash(GuiIconProvider::instance()->getIcon("edit-copy"), tr("Copy hash"), 0); - connect(&actionCopyHash, &QAction::triggered, this, &TransferListWidget::copySelectedHashes); - QAction actionSuper_seeding_mode(tr("Super seeding mode"), 0); - actionSuper_seeding_mode.setCheckable(true); - connect(&actionSuper_seeding_mode, SIGNAL(triggered()), this, SLOT(toggleSelectedTorrentsSuperSeeding())); - QAction actionRename(GuiIconProvider::instance()->getIcon("edit-rename"), tr("Rename..."), 0); - connect(&actionRename, SIGNAL(triggered()), this, SLOT(renameSelectedTorrent())); - QAction actionSequential_download(tr("Download in sequential order"), 0); - actionSequential_download.setCheckable(true); - connect(&actionSequential_download, SIGNAL(triggered()), this, SLOT(toggleSelectedTorrentsSequentialDownload())); - QAction actionFirstLastPiece_prio(tr("Download first and last pieces first"), 0); - actionFirstLastPiece_prio.setCheckable(true); - connect(&actionFirstLastPiece_prio, SIGNAL(triggered()), this, SLOT(toggleSelectedFirstLastPiecePrio())); - QAction actionAutoTMM(tr("Automatic Torrent Management"), 0); - actionAutoTMM.setCheckable(true); - actionAutoTMM.setToolTip(tr("Automatic mode means that various torrent properties(eg save path) will be decided by the associated category")); - connect(&actionAutoTMM, SIGNAL(triggered(bool)), this, SLOT(setSelectedAutoTMMEnabled(bool))); - // End of actions - - // Enable/disable pause/start action given the DL state - bool needs_pause = false, needs_start = false, needs_force = false, needs_preview = false; - bool all_same_super_seeding = true; - bool super_seeding_mode = false; - bool all_same_sequential_download_mode = true, all_same_prio_firstlast = true; - bool sequential_download_mode = false, prioritize_first_last = false; - bool one_has_metadata = false, one_not_seed = false; - bool allSameCategory = true; - bool allSameAutoTMM = true; - bool firstAutoTMM = false; - QString firstCategory; - bool first = true; - QSet tagsInAny; - QSet tagsInAll; - - BitTorrent::TorrentHandle *torrent; - qDebug("Displaying menu"); - foreach (const QModelIndex &index, selectedIndexes) { - // Get the file name - // Get handle and pause the torrent - torrent = listModel->torrentHandle(mapToSource(index)); - if (!torrent) continue; - - if (firstCategory.isEmpty() && first) - firstCategory = torrent->category(); - if (firstCategory != torrent->category()) - allSameCategory = false; - - tagsInAny.unite(torrent->tags()); - - if (first) { - firstAutoTMM = torrent->isAutoTMMEnabled(); - tagsInAll = torrent->tags(); - } - else { - tagsInAll.intersect(torrent->tags()); - } - if (firstAutoTMM != torrent->isAutoTMMEnabled()) - allSameAutoTMM = false; - - if (torrent->hasMetadata()) - one_has_metadata = true; - if (!torrent->isSeed()) { - one_not_seed = true; - if (torrent->hasMetadata()) { - if (first) { - sequential_download_mode = torrent->isSequentialDownload(); - prioritize_first_last = torrent->hasFirstLastPiecePriority(); - } - else { - if (sequential_download_mode != torrent->isSequentialDownload()) - all_same_sequential_download_mode = false; - if (prioritize_first_last != torrent->hasFirstLastPiecePriority()) - all_same_prio_firstlast = false; - } - } - } - else { - if (!one_not_seed && all_same_super_seeding && torrent->hasMetadata()) { - if (first) { - super_seeding_mode = torrent->superSeeding(); - } - else if (super_seeding_mode != torrent->superSeeding()) - all_same_super_seeding = false; - - } - } - if (!torrent->isForced()) - needs_force = true; - else - needs_start = true; - if (torrent->isPaused()) - needs_start = true; - else - needs_pause = true; - if (torrent->hasMetadata()) - needs_preview = true; - - first = false; - - if (one_has_metadata && one_not_seed && !all_same_sequential_download_mode - && !all_same_prio_firstlast && !all_same_super_seeding && !allSameCategory - && needs_start && needs_force && needs_pause && needs_preview && !allSameAutoTMM) { - break; - } - } - QMenu listMenu(this); - if (needs_start) - listMenu.addAction(&actionStart); - if (needs_pause) - listMenu.addAction(&actionPause); - if (needs_force) - listMenu.addAction(&actionForceStart); - listMenu.addSeparator(); - listMenu.addAction(&actionDelete); - listMenu.addSeparator(); - listMenu.addAction(&actionSetTorrentPath); - if (selectedIndexes.size() == 1) - listMenu.addAction(&actionRename); - // Category Menu - QStringList categories = BitTorrent::Session::instance()->categories(); - std::sort(categories.begin(), categories.end(), Utils::String::naturalCompareCaseInsensitive); - QList categoryActions; - QMenu *categoryMenu = listMenu.addMenu(GuiIconProvider::instance()->getIcon("view-categories"), tr("Category")); - categoryActions << categoryMenu->addAction(GuiIconProvider::instance()->getIcon("list-add"), tr("New...", "New category...")); - categoryActions << categoryMenu->addAction(GuiIconProvider::instance()->getIcon("edit-clear"), tr("Reset", "Reset category")); - categoryMenu->addSeparator(); - foreach (QString category, categories) { - category.replace('&', "&&"); // avoid '&' becomes accelerator key - QAction *cat = new QAction(GuiIconProvider::instance()->getIcon("inode-directory"), category, categoryMenu); - if (allSameCategory && (category == firstCategory)) { - cat->setCheckable(true); - cat->setChecked(true); - } - categoryMenu->addAction(cat); - categoryActions << cat; - } - - // Tag Menu - QStringList tags(BitTorrent::Session::instance()->tags().toList()); - std::sort(tags.begin(), tags.end(), Utils::String::naturalCompareCaseInsensitive); - QList tagsActions; - QMenu *tagsMenu = listMenu.addMenu(GuiIconProvider::instance()->getIcon("view-categories"), tr("Tags")); - tagsActions << tagsMenu->addAction(GuiIconProvider::instance()->getIcon("list-add"), tr("Add...", "Add / assign multiple tags...")); - tagsActions << tagsMenu->addAction(GuiIconProvider::instance()->getIcon("edit-clear"), tr("Remove All", "Remove all tags")); - tagsMenu->addSeparator(); - foreach (QString tag, tags) { - const Qt::CheckState initialState = tagsInAll.contains(tag) ? Qt::Checked - : tagsInAny.contains(tag) ? Qt::PartiallyChecked - : Qt::Unchecked; - - const ToggleFn onToggle = [this, tag](Qt::CheckState newState) - { - Q_ASSERT(newState == Qt::CheckState::Checked || newState == Qt::CheckState::Unchecked); - if (newState == Qt::CheckState::Checked) - addSelectionTag(tag); - else - removeSelectionTag(tag); - }; - - tagsMenu->addAction(new CheckBoxMenuItem(tag, onToggle, initialState, tagsMenu)); - } - - if (allSameAutoTMM) { - actionAutoTMM.setChecked(firstAutoTMM); - listMenu.addAction(&actionAutoTMM); - } - - listMenu.addSeparator(); - if (one_not_seed) - listMenu.addAction(&actionSet_download_limit); - listMenu.addAction(&actionSet_upload_limit); - listMenu.addAction(&actionSet_max_ratio); - if (!one_not_seed && all_same_super_seeding && one_has_metadata) { - actionSuper_seeding_mode.setChecked(super_seeding_mode); - listMenu.addAction(&actionSuper_seeding_mode); - } - listMenu.addSeparator(); - bool added_preview_action = false; - if (needs_preview) { - listMenu.addAction(&actionPreview_file); - added_preview_action = true; - } - if (one_not_seed && one_has_metadata) { - if (all_same_sequential_download_mode) { - actionSequential_download.setChecked(sequential_download_mode); - listMenu.addAction(&actionSequential_download); - added_preview_action = true; - } - if (all_same_prio_firstlast) { - actionFirstLastPiece_prio.setChecked(prioritize_first_last); - listMenu.addAction(&actionFirstLastPiece_prio); - added_preview_action = true; - } - } - - if (added_preview_action) - listMenu.addSeparator(); - if (one_has_metadata) { - listMenu.addAction(&actionForce_recheck); - listMenu.addSeparator(); - } - listMenu.addAction(&actionOpen_destination_folder); - if (BitTorrent::Session::instance()->isQueueingSystemEnabled() && one_not_seed) { - listMenu.addSeparator(); - QMenu *prioMenu = listMenu.addMenu(tr("Priority")); - prioMenu->addAction(&actionTopPriority); - prioMenu->addAction(&actionIncreasePriority); - prioMenu->addAction(&actionDecreasePriority); - prioMenu->addAction(&actionBottomPriority); - } - listMenu.addSeparator(); - listMenu.addAction(&actionCopy_name); - listMenu.addAction(&actionCopyHash); - listMenu.addAction(&actionCopy_magnet_link); - // Call menu - QAction *act = 0; - act = listMenu.exec(QCursor::pos()); - if (act) { - // Parse category & tag actions only (others have slots assigned) - int i = categoryActions.indexOf(act); - if (i >= 0) { - // Category action - if (i == 0) { - // New Category - askNewCategoryForSelection(); - } - else { - QString category = ""; - if (i > 1) - category = categories.at(i - 2); - // Update Category - setSelectionCategory(category); - } - } - i = tagsActions.indexOf(act); - if (i == 0) { - askAddTagsForSelection(); - } - else if (i == 1) { - if (Preferences::instance()->confirmRemoveAllTags()) - confirmRemoveAllTagsForSelection(); - else - clearSelectionTags(); - } - } -} - -void TransferListWidget::currentChanged(const QModelIndex& current, const QModelIndex&) -{ - qDebug("CURRENT CHANGED"); - BitTorrent::TorrentHandle *torrent = 0; - if (current.isValid()) { - torrent = listModel->torrentHandle(mapToSource(current)); - // Scroll Fix - scrollTo(current); - } - emit currentTorrentChanged(torrent); -} - -void TransferListWidget::applyCategoryFilter(QString category) -{ - if (category.isNull()) - nameFilterModel->disableCategoryFilter(); - else - nameFilterModel->setCategoryFilter(category); -} - -void TransferListWidget::applyTagFilter(const QString &tag) -{ - if (tag.isNull()) - nameFilterModel->disableTagFilter(); - else - nameFilterModel->setTagFilter(tag); -} - -void TransferListWidget::applyTrackerFilterAll() -{ - nameFilterModel->disableTrackerFilter(); -} - -void TransferListWidget::applyTrackerFilter(const QStringList &hashes) -{ - nameFilterModel->setTrackerFilter(hashes); -} - -void TransferListWidget::applyNameFilter(const QString& name) -{ - nameFilterModel->setFilterRegExp(QRegExp(name, Qt::CaseInsensitive, QRegExp::WildcardUnix)); -} - -void TransferListWidget::applyStatusFilter(int f) -{ - nameFilterModel->setStatusFilter(static_cast(f)); - // Select first item if nothing is selected - if (selectionModel()->selectedRows(0).empty() && nameFilterModel->rowCount() > 0) { - qDebug("Nothing is selected, selecting first row: %s", qPrintable(nameFilterModel->index(0, TorrentModel::TR_NAME).data().toString())); - selectionModel()->setCurrentIndex(nameFilterModel->index(0, TorrentModel::TR_NAME), QItemSelectionModel::SelectCurrent | QItemSelectionModel::Rows); - } -} - -void TransferListWidget::saveSettings() -{ - Preferences::instance()->setTransHeaderState(header()->saveState()); -} - -bool TransferListWidget::loadSettings() -{ - bool ok = header()->restoreState(Preferences::instance()->getTransHeaderState()); - if (!ok) - header()->resizeSection(0, 200); // Default - return ok; -} - -void TransferListWidget::wheelEvent(QWheelEvent *event) -{ - event->accept(); - - if (event->modifiers() & Qt::ShiftModifier) { - // Shift + scroll = horizontal scroll - QWheelEvent scrollHEvent(event->pos(), event->globalPos(), event->delta(), event->buttons(), event->modifiers(), Qt::Horizontal); - QTreeView::wheelEvent(&scrollHEvent); - return; - } - - QTreeView::wheelEvent(event); // event delegated to base class -} diff --git a/src/gui/transferlistwidget.h b/src/gui/transferlistwidget.h deleted file mode 100644 index 0686f4466..000000000 --- a/src/gui/transferlistwidget.h +++ /dev/null @@ -1,141 +0,0 @@ -/* - * Bittorrent Client using Qt4 and libtorrent. - * Copyright (C) 2006 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 TRANSFERLISTWIDGET_H -#define TRANSFERLISTWIDGET_H - -#include -#include - -namespace BitTorrent -{ - class TorrentHandle; -} - -class MainWindow; -class TransferListDelegate; -class TransferListSortModel; -class TorrentModel; - -QT_BEGIN_NAMESPACE -class QShortcut; -class QSortFilterProxyModel; -class QStandardItemModel; -QT_END_NAMESPACE - -class TransferListWidget: public QTreeView -{ - Q_OBJECT - -public: - TransferListWidget(QWidget *parent, MainWindow *main_window); - ~TransferListWidget(); - TorrentModel* getSourceModel() const; - -public slots: - void setSelectionCategory(QString category); - void addSelectionTag(const QString &tag); - void removeSelectionTag(const QString &tag); - void clearSelectionTags(); - void setSelectedTorrentsLocation(); - void pauseAllTorrents(); - void resumeAllTorrents(); - void startSelectedTorrents(); - void forceStartSelectedTorrents(); - void startVisibleTorrents(); - void pauseSelectedTorrents(); - void pauseVisibleTorrents(); - void softDeleteSelectedTorrents(); - void permDeleteSelectedTorrents(); - void deleteSelectedTorrents(bool deleteLocalFiles); - void deleteVisibleTorrents(); - void increasePrioSelectedTorrents(); - void decreasePrioSelectedTorrents(); - void topPrioSelectedTorrents(); - void bottomPrioSelectedTorrents(); - void copySelectedMagnetURIs() const; - void copySelectedNames() const; - void copySelectedHashes() const; - void openSelectedTorrentsFolder() const; - void recheckSelectedTorrents(); - void setDlLimitSelectedTorrents(); - void setUpLimitSelectedTorrents(); - void setMaxRatioSelectedTorrents(); - void previewSelectedTorrents(); - void hidePriorityColumn(bool hide); - void displayDLHoSMenu(const QPoint&); - void applyNameFilter(const QString& name); - void applyStatusFilter(int f); - void applyCategoryFilter(QString category); - void applyTagFilter(const QString &tag); - void applyTrackerFilterAll(); - void applyTrackerFilter(const QStringList &hashes); - void previewFile(QString filePath); - void renameSelectedTorrent(); - -protected: - QModelIndex mapToSource(const QModelIndex &index) const; - QModelIndex mapFromSource(const QModelIndex &index) const; - bool loadSettings(); - QList getSelectedTorrents() const; - -protected slots: - void torrentDoubleClicked(); - void displayListMenu(const QPoint&); - void currentChanged(const QModelIndex& current, const QModelIndex&); - void toggleSelectedTorrentsSuperSeeding() const; - void toggleSelectedTorrentsSequentialDownload() const; - void toggleSelectedFirstLastPiecePrio() const; - void setSelectedAutoTMMEnabled(bool enabled) const; - void askNewCategoryForSelection(); - void saveSettings(); - -signals: - void currentTorrentChanged(BitTorrent::TorrentHandle *const torrent); - -private: - void wheelEvent(QWheelEvent *event) override; - void askAddTagsForSelection(); - void confirmRemoveAllTagsForSelection(); - QStringList askTagsForSelection(const QString &dialogTitle); - void applyToSelectedTorrents(const std::function &fn); - - TransferListDelegate *listDelegate; - TorrentModel *listModel; - TransferListSortModel *nameFilterModel; - MainWindow *main_window; - QShortcut *editHotkey; - QShortcut *deleteHotkey; - QShortcut *permDeleteHotkey; - QShortcut *doubleClickHotkey; - QShortcut *recheckHotkey; -}; - -#endif // TRANSFERLISTWIDGET_H diff --git a/src/gui/translators.html b/src/gui/translators.html deleted file mode 100644 index 38aa69f1b..000000000 --- a/src/gui/translators.html +++ /dev/null @@ -1,51 +0,0 @@ - - - - - Translators - - -

I would like to thank the following people who volunteered to translate qBittorrent:

-
    -
  • 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)
  • -
  • 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)
  • -
  • Croatian: Oliver Mucafir (oliver.untwist@gmail.com)
  • -
  • Czech: Jirka Vilim (web@tets.cz) and Petr Cernobila abr(Transifex)
  • -
  • Danish: Mathias Nielsen (comoneo@gmail.com)
  • -
  • Dutch: Pieter Heyvaert (pieter_heyvaert@hotmail.com)
  • -
  • 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)
  • -
  • Galician: Marcos Lans (marcoslansgarza@gmail.com) and antiparvos(Transifex)
  • -
  • Georgian: Beqa Arabuli (arabulibeqa@yahoo.com)
  • -
  • German: Niels Hoffmann (zentralmaschine@users.sourceforge.net), schnurlos (schnurlos@gmail.com)
  • -
  • Greek: Tsvetan Bankov (emerge_life@users.sourceforge.net), Stephanos Antaris (santaris@csd.auth.gr), sledgehammer999(hammered999@gmail.com), Γιάννης Ανθυμίδης Evropi(Transifex) and Panagiotis Tabakis(tabakisp@gmail.com)
  • -
  • Hebrew: David Deutsch (d.deffo@gmail.com)
  • -
  • Hungarian: Majoros Péter (majoros.peterj@gmail.com)
  • -
  • Italian: bovirus (bovirus@live.it) and Matteo Sechi (bu17714@gmail.com)
  • -
  • Japanese: Masato Hashimoto (cabezon.hashimoto@gmail.com)
  • -
  • Korean: Jin Woo Sin (jin828sin@users.sourceforge.net)
  • -
  • Lithuanian: Naglis Jonaitis (njonaitis@gmail.com)
  • -
  • Norwegian: Tomaso
  • -
  • Polish: Mariusz Fik (fisiu@opensuse.org)
  • -
  • Portuguese: Sérgio Marques smarquespt(Transifex)
  • -
  • Portuguese(Brazil): Nick Marinho (nickmarinho@gmail.com)
  • -
  • Romanian: Obada Denis (obadadenis@users.sourceforge.net), Adrian Gabor Adriannho(Transifex) and Mihai Coman z0id(Transifex)
  • -
  • Russian: Nick Khazov (m2k3d0n at users.sourceforge.net), Alexey Morsov (samurai@ricom.ru), Nick Tiskov Dayman(daymansmail (at) gmail (dot) com), Dmitry DmitryKX(Transifex) and kraleksandr kraleksandr(Transifex)
  • -
  • Serbian: Anaximandar Milet (anaximandar@operamail.com)
  • -
  • Slovak: helix84
  • -
  • Spanish: Alfredo Monclús (alfrix), Francisco Luque Contreras (frannoe@ya.com), José Antonio Moray moray33(Transifex) and Diego de las Heras(Transifex)
  • -
  • Swedish: Daniel Nylander (po@danielnylander.se) and Emil Hammarberg Ooglogput(Transifex)
  • -
  • Turkish: Hasan YILMAZ (iletisim@hedefturkce.com) and Erdem Bingöl (erdem84@gmail.com)
  • -
  • Ukrainian: Oleh Prypin (blaxpirit@gmail.com)
  • -
  • Vietnamese: Anh Phan ppanhh(Transifex)
  • -
-

Please contact me if you would like to translate qBittorrent into your own language.

- - diff --git a/src/gui/updownratiodlg.cpp b/src/gui/updownratiodlg.cpp deleted file mode 100644 index efd14f523..000000000 --- a/src/gui/updownratiodlg.cpp +++ /dev/null @@ -1,127 +0,0 @@ -/* - * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2011 Christian Kandeler, 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 "updownratiodlg.h" - -#include - -#include "base/bittorrent/session.h" - -#include "ui_updownratiodlg.h" - -UpDownRatioDlg::UpDownRatioDlg(bool useDefault, qreal initialRatioValue, - qreal maxRatioValue, int initialTimeValue, - int maxTimeValue, QWidget *parent) - : QDialog(parent) - , ui(new Ui::UpDownRatioDlg) -{ - ui->setupUi(this); - - if (useDefault) { - ui->useDefaultButton->setChecked(true); - } - else if ((initialRatioValue == -1) && (initialTimeValue == -1)) { - ui->noLimitButton->setChecked(true); - initialRatioValue = BitTorrent::Session::instance()->globalMaxRatio(); - initialTimeValue = BitTorrent::Session::instance()->globalMaxSeedingMinutes(); - } - else { - ui->torrentLimitButton->setChecked(true); - - if (initialRatioValue >= 0) - ui->checkMaxRatio->setChecked(true); - - if (initialTimeValue >= 0) - ui->checkMaxTime->setChecked(true); - } - - ui->ratioSpinBox->setMinimum(0); - ui->ratioSpinBox->setMaximum(maxRatioValue); - ui->ratioSpinBox->setValue(initialRatioValue); - - ui->timeSpinBox->setMinimum(0); - ui->timeSpinBox->setMaximum(maxTimeValue); - ui->timeSpinBox->setValue(initialTimeValue); - - connect(ui->buttonGroup, SIGNAL(buttonClicked(int)), SLOT(handleRatioTypeChanged())); - connect(ui->checkMaxRatio, SIGNAL(toggled(bool)), this, SLOT(enableRatioSpin())); - connect(ui->checkMaxTime, SIGNAL(toggled(bool)), this, SLOT(enableTimeSpin())); - - handleRatioTypeChanged(); -} - -void UpDownRatioDlg::accept() -{ - if (ui->torrentLimitButton->isChecked() && !ui->checkMaxRatio->isChecked() && !ui->checkMaxTime->isChecked()) - QMessageBox::critical(this, tr("No share limit method selected"), - tr("Please select a limit method first")); - else - QDialog::accept(); -} - -bool UpDownRatioDlg::useDefault() const -{ - return ui->useDefaultButton->isChecked(); -} - -qreal UpDownRatioDlg::ratio() const -{ - return (ui->noLimitButton->isChecked() || !ui->checkMaxRatio->isChecked()) ? -1 : ui->ratioSpinBox->value(); -} - -int UpDownRatioDlg::seedingTime() const -{ - return (ui->noLimitButton->isChecked() || !ui->checkMaxTime->isChecked()) ? -1 : ui->timeSpinBox->value(); -} - -void UpDownRatioDlg::handleRatioTypeChanged() -{ - // ui->ratioSpinBox->setEnabled(ui->torrentLimitButton->isChecked()); - ui->checkMaxRatio->setEnabled(ui->torrentLimitButton->isChecked()); - ui->checkMaxTime->setEnabled(ui->torrentLimitButton->isChecked()); - - ui->ratioSpinBox->setEnabled(ui->torrentLimitButton->isChecked() && ui->checkMaxRatio->isChecked()); - ui->timeSpinBox->setEnabled(ui->torrentLimitButton->isChecked() && ui->checkMaxTime->isChecked()); -} - -void UpDownRatioDlg::enableRatioSpin() -{ - ui->ratioSpinBox->setEnabled(ui->checkMaxRatio->isChecked()); -} - -void UpDownRatioDlg::enableTimeSpin() -{ - ui->timeSpinBox->setEnabled(ui->checkMaxTime->isChecked()); -} - -UpDownRatioDlg::~UpDownRatioDlg() -{ - delete ui; -} diff --git a/src/gui/updownratiodlg.h b/src/gui/updownratiodlg.h deleted file mode 100644 index b7a59de81..000000000 --- a/src/gui/updownratiodlg.h +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Bittorrent Client using Qt4 and libtorrent. - * Copyright (C) 2011 Christian Kandeler, 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 UPDOWNRATIODLG_H -#define UPDOWNRATIODLG_H - -#include - -QT_BEGIN_NAMESPACE -namespace Ui { - class UpDownRatioDlg; -} -QT_END_NAMESPACE - -class UpDownRatioDlg : public QDialog -{ - Q_OBJECT - -public: - explicit UpDownRatioDlg(bool useDefault, qreal initialValue, qreal maxValue, - int initialTimeValue, int maxTimeValue, - QWidget *parent = 0); - ~UpDownRatioDlg(); - - bool useDefault() const; - qreal ratio() const; - int seedingTime() const; - -public slots: - void accept(); - -private slots: - void handleRatioTypeChanged(); - void enableRatioSpin(); - void enableTimeSpin(); - -private: - Ui::UpDownRatioDlg *ui; -}; - -#endif // UPDOWNRATIODLG_H diff --git a/src/gui/updownratiodlg.ui b/src/gui/updownratiodlg.ui deleted file mode 100644 index 6774d8a0d..000000000 --- a/src/gui/updownratiodlg.ui +++ /dev/null @@ -1,177 +0,0 @@ - - - UpDownRatioDlg - - - - 0 - 0 - 399 - 195 - - - - Torrent Upload/Download Ratio Limiting - - - - - - Use global share limit - - - buttonGroup - - - - - - - Set no share limit - - - buttonGroup - - - - - - - - - Set share limit to - - - buttonGroup - - - - - - - 9998.000000000000000 - - - 0.050000000000000 - - - 1.000000000000000 - - - - - - - - 0 - 0 - - - - 0 - - - 525600.000000000000000 - - - 1.000000000000000 - - - 1440.000000000000000 - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - ratio - - - - - - - minutes - - - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - Qt::Horizontal - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - - - - - - - buttonBox - accepted() - UpDownRatioDlg - accept() - - - 248 - 254 - - - 157 - 274 - - - - - buttonBox - rejected() - UpDownRatioDlg - reject() - - - 316 - 260 - - - 286 - 274 - - - - - - - - - diff --git a/src/icons.qrc b/src/icons.qrc deleted file mode 100644 index b3247798f..000000000 --- a/src/icons.qrc +++ /dev/null @@ -1,381 +0,0 @@ - - - icons/qbittorrent.png - icons/3-state-checkbox.gif - icons/L.gif - icons/loading.png - icons/slow.png - icons/slow_off.png - icons/sphere.png - icons/sphere2.png - icons/url.png - icons/flags/ad.png - icons/flags/ae.png - icons/flags/af.png - icons/flags/ag.png - icons/flags/ai.png - icons/flags/al.png - icons/flags/am.png - icons/flags/an.png - icons/flags/ao.png - icons/flags/ar.png - icons/flags/as.png - icons/flags/at.png - icons/flags/au.png - icons/flags/aw.png - icons/flags/ax.png - icons/flags/az.png - icons/flags/ba.png - icons/flags/bb.png - icons/flags/bd.png - icons/flags/be.png - icons/flags/bf.png - icons/flags/bg.png - icons/flags/bh.png - icons/flags/bi.png - icons/flags/bj.png - icons/flags/bm.png - icons/flags/bn.png - icons/flags/bo.png - icons/flags/br.png - icons/flags/bs.png - icons/flags/bt.png - icons/flags/bv.png - icons/flags/bw.png - icons/flags/by.png - icons/flags/bz.png - icons/flags/ca.png - icons/flags/cc.png - icons/flags/cd.png - icons/flags/cf.png - icons/flags/cg.png - icons/flags/ch.png - icons/flags/ci.png - icons/flags/ck.png - icons/flags/cl.png - icons/flags/cm.png - icons/flags/cn.png - icons/flags/co.png - icons/flags/cr.png - icons/flags/cs.png - icons/flags/cu.png - icons/flags/cv.png - icons/flags/cx.png - icons/flags/cy.png - icons/flags/cz.png - icons/flags/de.png - icons/flags/dj.png - icons/flags/dk.png - icons/flags/dm.png - icons/flags/do.png - icons/flags/dz.png - icons/flags/ec.png - icons/flags/ee.png - icons/flags/eg.png - icons/flags/eh.png - icons/flags/er.png - icons/flags/es.png - icons/flags/et.png - icons/flags/fi.png - icons/flags/fj.png - icons/flags/fk.png - icons/flags/fm.png - icons/flags/fo.png - icons/flags/fr.png - icons/flags/ga.png - icons/flags/gb.png - icons/flags/gd.png - icons/flags/ge.png - icons/flags/gf.png - icons/flags/gh.png - icons/flags/gi.png - icons/flags/gl.png - icons/flags/gm.png - icons/flags/gn.png - icons/flags/gp.png - icons/flags/gq.png - icons/flags/gr.png - icons/flags/gs.png - icons/flags/gt.png - icons/flags/gu.png - icons/flags/gw.png - icons/flags/gy.png - icons/flags/hk.png - icons/flags/hm.png - icons/flags/hn.png - icons/flags/hr.png - icons/flags/ht.png - icons/flags/hu.png - icons/flags/id.png - icons/flags/ie.png - icons/flags/il.png - icons/flags/in.png - icons/flags/io.png - icons/flags/iq.png - icons/flags/ir.png - icons/flags/is.png - icons/flags/it.png - icons/flags/jm.png - icons/flags/jo.png - icons/flags/jp.png - icons/flags/ke.png - icons/flags/kg.png - icons/flags/kh.png - icons/flags/ki.png - icons/flags/km.png - icons/flags/kn.png - icons/flags/kp.png - icons/flags/kr.png - icons/flags/kw.png - icons/flags/ky.png - icons/flags/kz.png - icons/flags/la.png - icons/flags/lb.png - icons/flags/lc.png - icons/flags/li.png - icons/flags/lk.png - icons/flags/lr.png - icons/flags/ls.png - icons/flags/lt.png - icons/flags/lu.png - icons/flags/lv.png - icons/flags/ly.png - icons/flags/ma.png - icons/flags/mc.png - icons/flags/md.png - icons/flags/me.png - icons/flags/mg.png - icons/flags/mh.png - icons/flags/mk.png - icons/flags/ml.png - icons/flags/mm.png - icons/flags/mn.png - icons/flags/mo.png - icons/flags/mp.png - icons/flags/mq.png - icons/flags/mr.png - icons/flags/ms.png - icons/flags/mt.png - icons/flags/mu.png - icons/flags/mv.png - icons/flags/mw.png - icons/flags/mx.png - icons/flags/my.png - icons/flags/mz.png - icons/flags/na.png - icons/flags/nc.png - icons/flags/ne.png - icons/flags/nf.png - icons/flags/ng.png - icons/flags/ni.png - icons/flags/nl.png - icons/flags/no.png - icons/flags/np.png - icons/flags/nr.png - icons/flags/nu.png - icons/flags/nz.png - icons/flags/om.png - icons/flags/pa.png - icons/flags/pe.png - icons/flags/pf.png - icons/flags/pg.png - icons/flags/ph.png - icons/flags/pk.png - icons/flags/pl.png - icons/flags/pm.png - icons/flags/pn.png - icons/flags/pr.png - icons/flags/ps.png - icons/flags/pt.png - icons/flags/pw.png - icons/flags/py.png - icons/flags/qa.png - icons/flags/re.png - icons/flags/ro.png - icons/flags/rs.png - icons/flags/ru.png - icons/flags/rw.png - icons/flags/sa.png - icons/flags/sb.png - icons/flags/sc.png - icons/flags/sd.png - icons/flags/se.png - icons/flags/sg.png - icons/flags/sh.png - icons/flags/si.png - icons/flags/sj.png - icons/flags/sk.png - icons/flags/sl.png - icons/flags/sm.png - icons/flags/sn.png - icons/flags/so.png - icons/flags/sr.png - icons/flags/st.png - icons/flags/sv.png - icons/flags/sy.png - icons/flags/sz.png - icons/flags/tc.png - icons/flags/td.png - icons/flags/tf.png - icons/flags/tg.png - icons/flags/th.png - icons/flags/tj.png - icons/flags/tk.png - icons/flags/tl.png - icons/flags/tm.png - icons/flags/tn.png - icons/flags/to.png - icons/flags/tr.png - icons/flags/tt.png - icons/flags/tv.png - icons/flags/tw.png - icons/flags/tz.png - icons/flags/ua.png - icons/flags/ug.png - icons/flags/um.png - icons/flags/us.png - icons/flags/uy.png - icons/flags/uz.png - icons/flags/va.png - icons/flags/vc.png - icons/flags/ve.png - icons/flags/vg.png - icons/flags/vi.png - icons/flags/vn.png - icons/flags/vu.png - icons/flags/wf.png - icons/flags/ws.png - icons/flags/ye.png - icons/flags/yt.png - icons/flags/za.png - icons/flags/zm.png - icons/flags/zw.png - icons/qbt-theme/application-exit.png - icons/qbt-theme/application-rss+xml.png - icons/qbt-theme/application-x-mswinurl.png - icons/qbt-theme/configure.png - icons/qbt-theme/dialog-cancel.png - icons/qbt-theme/dialog-information.png - icons/qbt-theme/dialog-warning.png - icons/qbt-theme/document-edit-verify.png - icons/qbt-theme/document-edit.png - icons/qbt-theme/document-encrypt.png - icons/qbt-theme/document-import.png - icons/qbt-theme/document-new.png - icons/qbt-theme/document-properties.png - icons/qbt-theme/document-save.png - icons/qbt-theme/download.png - icons/qbt-theme/edit-clear-history.png - icons/qbt-theme/edit-clear.png - icons/qbt-theme/edit-copy.png - icons/qbt-theme/edit-cut.png - icons/qbt-theme/edit-delete.png - icons/qbt-theme/edit-find-user.png - icons/qbt-theme/edit-find.png - icons/qbt-theme/edit-paste.png - icons/qbt-theme/edit-rename.png - icons/qbt-theme/folder-documents.png - icons/qbt-theme/folder-download.png - icons/qbt-theme/folder-new.png - icons/qbt-theme/folder-remote.png - icons/qbt-theme/gear.png - icons/qbt-theme/gear32.png - icons/qbt-theme/go-down.png - icons/qbt-theme/go-up.png - icons/qbt-theme/help-about.png - icons/qbt-theme/help-contents.png - icons/qbt-theme/inode-directory.png - icons/qbt-theme/insert-link.png - icons/qbt-theme/kt-magnet.png - icons/qbt-theme/kt-set-max-download-speed.png - icons/qbt-theme/kt-set-max-upload-speed.png - icons/qbt-theme/list-add.png - icons/qbt-theme/list-remove.png - icons/qbt-theme/mail-folder-inbox.png - icons/qbt-theme/mail-mark-read.png - icons/qbt-theme/media-playback-pause.png - icons/qbt-theme/media-playback-start.png - icons/qbt-theme/media-seek-forward.png - icons/qbt-theme/network-server.png - icons/qbt-theme/network-wired.png - icons/qbt-theme/object-locked.png - icons/qbt-theme/preferences-desktop.png - icons/qbt-theme/preferences-other.png - icons/qbt-theme/preferences-system-network.png - icons/qbt-theme/preferences-web-browser-cookies.png - icons/qbt-theme/security-high.png - icons/qbt-theme/security-low.png - icons/qbt-theme/services.png - icons/qbt-theme/speedometer.png - icons/qbt-theme/tab-close.png - icons/qbt-theme/task-attention.png - icons/qbt-theme/task-complete.png - icons/qbt-theme/task-ongoing.png - icons/qbt-theme/task-reject.png - icons/qbt-theme/text-plain.png - icons/qbt-theme/tools-report-bug.png - icons/qbt-theme/unavailable.png - icons/qbt-theme/user-group-delete.png - icons/qbt-theme/user-group-new.png - icons/qbt-theme/view-calendar-journal.png - icons/qbt-theme/view-categories.png - icons/qbt-theme/view-filter.png - icons/qbt-theme/view-preview.png - icons/qbt-theme/view-refresh.png - icons/qbt-theme/view-statistics.png - icons/qbt-theme/wallet-open.png - icons/qbt-theme/webui.png - icons/skin/arrow-right.gif - icons/skin/bg-dropdown.gif - icons/skin/bg-handle-horizontal.gif - icons/skin/bg-header.gif - icons/skin/bg-panel-header.gif - icons/skin/checking.png - icons/skin/collapse-expand.gif - icons/skin/connected.png - icons/skin/disconnected.png - icons/skin/dock-tabs.gif - icons/skin/download.png - icons/skin/downloading.png - icons/skin/error.png - icons/skin/filteractive.png - icons/skin/filterall.png - icons/skin/filterinactive.png - icons/skin/firewalled.png - icons/skin/handle-icon-horizontal.gif - icons/skin/handle-icon.gif - icons/skin/knob.gif - icons/skin/logo-blank.gif - icons/skin/logo.gif - icons/skin/logo2.gif - icons/skin/mascot.png - icons/skin/paused.png - icons/skin/qbittorrent16.png - icons/skin/qbittorrent22.png - icons/skin/qbittorrent32.png - icons/skin/qbittorrent-tray-dark.svg - icons/skin/qbittorrent-tray-light.svg - icons/skin/queued.png - icons/skin/ratio.png - icons/skin/seeding.png - icons/skin/slider-area.gif - icons/skin/spacer.gif - icons/skin/spinner-placeholder.gif - icons/skin/spinner.gif - icons/skin/splash.png - icons/skin/stalledDL.png - icons/skin/stalledUP.png - icons/skin/tabs.gif - icons/skin/toolbox-divider.gif - icons/skin/toolbox-divider2.gif - icons/skin/resumed.png - icons/skin/uploading.png - icons/skin/completed.png - icons/qbt-theme/system-log-out.png - icons/qbt-theme/go-bottom.png - icons/qbt-theme/go-top.png - icons/qbt-theme/checked.png - icons/qbt-theme/office-chart-line.png - icons/qbt-theme/rss-config.png - - diff --git a/src/icons/3-state-checkbox.gif b/src/icons/3-state-checkbox.gif deleted file mode 100644 index f7918e84c..000000000 Binary files a/src/icons/3-state-checkbox.gif and /dev/null differ diff --git a/src/icons/L.gif b/src/icons/L.gif deleted file mode 100644 index 48b81c80a..000000000 Binary files a/src/icons/L.gif and /dev/null differ diff --git a/src/icons/flags/ad.png b/src/icons/flags/ad.png deleted file mode 100755 index dd4adcdd7..000000000 Binary files a/src/icons/flags/ad.png and /dev/null differ diff --git a/src/icons/flags/ae.png b/src/icons/flags/ae.png deleted file mode 100755 index 3aaf20d84..000000000 Binary files a/src/icons/flags/ae.png and /dev/null differ diff --git a/src/icons/flags/af.png b/src/icons/flags/af.png deleted file mode 100755 index 51e1933a9..000000000 Binary files a/src/icons/flags/af.png and /dev/null differ diff --git a/src/icons/flags/ag.png b/src/icons/flags/ag.png deleted file mode 100755 index da53be824..000000000 Binary files a/src/icons/flags/ag.png and /dev/null differ diff --git a/src/icons/flags/ai.png b/src/icons/flags/ai.png deleted file mode 100755 index 9bde3ce70..000000000 Binary files a/src/icons/flags/ai.png and /dev/null differ diff --git a/src/icons/flags/al.png b/src/icons/flags/al.png deleted file mode 100755 index a38a7307a..000000000 Binary files a/src/icons/flags/al.png and /dev/null differ diff --git a/src/icons/flags/am.png b/src/icons/flags/am.png deleted file mode 100755 index 763478ffe..000000000 Binary files a/src/icons/flags/am.png and /dev/null differ diff --git a/src/icons/flags/an.png b/src/icons/flags/an.png deleted file mode 100755 index 4e2a57c39..000000000 Binary files a/src/icons/flags/an.png and /dev/null differ diff --git a/src/icons/flags/ao.png b/src/icons/flags/ao.png deleted file mode 100644 index 33827bb7a..000000000 Binary files a/src/icons/flags/ao.png and /dev/null differ diff --git a/src/icons/flags/ar.png b/src/icons/flags/ar.png deleted file mode 100755 index 86e8dbed4..000000000 Binary files a/src/icons/flags/ar.png and /dev/null differ diff --git a/src/icons/flags/as.png b/src/icons/flags/as.png deleted file mode 100755 index c0729de33..000000000 Binary files a/src/icons/flags/as.png and /dev/null differ diff --git a/src/icons/flags/at.png b/src/icons/flags/at.png deleted file mode 100755 index 700a65667..000000000 Binary files a/src/icons/flags/at.png and /dev/null differ diff --git a/src/icons/flags/au.png b/src/icons/flags/au.png deleted file mode 100755 index 27c4d0a7b..000000000 Binary files a/src/icons/flags/au.png and /dev/null differ diff --git a/src/icons/flags/aw.png b/src/icons/flags/aw.png deleted file mode 100755 index 7b7d01c10..000000000 Binary files a/src/icons/flags/aw.png and /dev/null differ diff --git a/src/icons/flags/ax.png b/src/icons/flags/ax.png deleted file mode 100755 index 2c7c7f44e..000000000 Binary files a/src/icons/flags/ax.png and /dev/null differ diff --git a/src/icons/flags/az.png b/src/icons/flags/az.png deleted file mode 100755 index ba4d61fed..000000000 Binary files a/src/icons/flags/az.png and /dev/null differ diff --git a/src/icons/flags/ba.png b/src/icons/flags/ba.png deleted file mode 100755 index 688c1af9a..000000000 Binary files a/src/icons/flags/ba.png and /dev/null differ diff --git a/src/icons/flags/bb.png b/src/icons/flags/bb.png deleted file mode 100755 index 61557ba50..000000000 Binary files a/src/icons/flags/bb.png and /dev/null differ diff --git a/src/icons/flags/bd.png b/src/icons/flags/bd.png deleted file mode 100755 index 347601c6c..000000000 Binary files a/src/icons/flags/bd.png and /dev/null differ diff --git a/src/icons/flags/be.png b/src/icons/flags/be.png deleted file mode 100755 index 12c10f46e..000000000 Binary files a/src/icons/flags/be.png and /dev/null differ diff --git a/src/icons/flags/bf.png b/src/icons/flags/bf.png deleted file mode 100755 index 34416757c..000000000 Binary files a/src/icons/flags/bf.png and /dev/null differ diff --git a/src/icons/flags/bg.png b/src/icons/flags/bg.png deleted file mode 100755 index 41f34d856..000000000 Binary files a/src/icons/flags/bg.png and /dev/null differ diff --git a/src/icons/flags/bh.png b/src/icons/flags/bh.png deleted file mode 100755 index 651934f05..000000000 Binary files a/src/icons/flags/bh.png and /dev/null differ diff --git a/src/icons/flags/bi.png b/src/icons/flags/bi.png deleted file mode 100755 index 5ff589b8b..000000000 Binary files a/src/icons/flags/bi.png and /dev/null differ diff --git a/src/icons/flags/bj.png b/src/icons/flags/bj.png deleted file mode 100755 index 5fd1a5a18..000000000 Binary files a/src/icons/flags/bj.png and /dev/null differ diff --git a/src/icons/flags/bm.png b/src/icons/flags/bm.png deleted file mode 100755 index 3cb880315..000000000 Binary files a/src/icons/flags/bm.png and /dev/null differ diff --git a/src/icons/flags/bn.png b/src/icons/flags/bn.png deleted file mode 100755 index 2a3d934e7..000000000 Binary files a/src/icons/flags/bn.png and /dev/null differ diff --git a/src/icons/flags/bo.png b/src/icons/flags/bo.png deleted file mode 100755 index 46b519eae..000000000 Binary files a/src/icons/flags/bo.png and /dev/null differ diff --git a/src/icons/flags/br.png b/src/icons/flags/br.png deleted file mode 100755 index a011b1dd1..000000000 Binary files a/src/icons/flags/br.png and /dev/null differ diff --git a/src/icons/flags/bs.png b/src/icons/flags/bs.png deleted file mode 100755 index 1030207a1..000000000 Binary files a/src/icons/flags/bs.png and /dev/null differ diff --git a/src/icons/flags/bt.png b/src/icons/flags/bt.png deleted file mode 100755 index dd3bb1c2c..000000000 Binary files a/src/icons/flags/bt.png and /dev/null differ diff --git a/src/icons/flags/bv.png b/src/icons/flags/bv.png deleted file mode 100755 index 74264c586..000000000 Binary files a/src/icons/flags/bv.png and /dev/null differ diff --git a/src/icons/flags/bw.png b/src/icons/flags/bw.png deleted file mode 100755 index 4a840d381..000000000 Binary files a/src/icons/flags/bw.png and /dev/null differ diff --git a/src/icons/flags/by.png b/src/icons/flags/by.png deleted file mode 100755 index e9f9c3486..000000000 Binary files a/src/icons/flags/by.png and /dev/null differ diff --git a/src/icons/flags/bz.png b/src/icons/flags/bz.png deleted file mode 100755 index 3b13813dc..000000000 Binary files a/src/icons/flags/bz.png and /dev/null differ diff --git a/src/icons/flags/ca.png b/src/icons/flags/ca.png deleted file mode 100755 index c4df905ce..000000000 Binary files a/src/icons/flags/ca.png and /dev/null differ diff --git a/src/icons/flags/cc.png b/src/icons/flags/cc.png deleted file mode 100755 index bf5dcf176..000000000 Binary files a/src/icons/flags/cc.png and /dev/null differ diff --git a/src/icons/flags/cd.png b/src/icons/flags/cd.png deleted file mode 100644 index 932e403f0..000000000 Binary files a/src/icons/flags/cd.png and /dev/null differ diff --git a/src/icons/flags/cf.png b/src/icons/flags/cf.png deleted file mode 100755 index 7fcb56149..000000000 Binary files a/src/icons/flags/cf.png and /dev/null differ diff --git a/src/icons/flags/cg.png b/src/icons/flags/cg.png deleted file mode 100755 index a6e0490fc..000000000 Binary files a/src/icons/flags/cg.png and /dev/null differ diff --git a/src/icons/flags/ch.png b/src/icons/flags/ch.png deleted file mode 100755 index ca4d9be65..000000000 Binary files a/src/icons/flags/ch.png and /dev/null differ diff --git a/src/icons/flags/ci.png b/src/icons/flags/ci.png deleted file mode 100755 index 2ee79a364..000000000 Binary files a/src/icons/flags/ci.png and /dev/null differ diff --git a/src/icons/flags/ck.png b/src/icons/flags/ck.png deleted file mode 100755 index 45254db42..000000000 Binary files a/src/icons/flags/ck.png and /dev/null differ diff --git a/src/icons/flags/cl.png b/src/icons/flags/cl.png deleted file mode 100755 index 74a69dc8e..000000000 Binary files a/src/icons/flags/cl.png and /dev/null differ diff --git a/src/icons/flags/cm.png b/src/icons/flags/cm.png deleted file mode 100755 index 7add66be0..000000000 Binary files a/src/icons/flags/cm.png and /dev/null differ diff --git a/src/icons/flags/cn.png b/src/icons/flags/cn.png deleted file mode 100755 index 9f1b31090..000000000 Binary files a/src/icons/flags/cn.png and /dev/null differ diff --git a/src/icons/flags/co.png b/src/icons/flags/co.png deleted file mode 100755 index a2fb47693..000000000 Binary files a/src/icons/flags/co.png and /dev/null differ diff --git a/src/icons/flags/cr.png b/src/icons/flags/cr.png deleted file mode 100755 index 413797bfe..000000000 Binary files a/src/icons/flags/cr.png and /dev/null differ diff --git a/src/icons/flags/cs.png b/src/icons/flags/cs.png deleted file mode 100755 index 23f716dc4..000000000 Binary files a/src/icons/flags/cs.png and /dev/null differ diff --git a/src/icons/flags/cu.png b/src/icons/flags/cu.png deleted file mode 100755 index 8ad51d2e2..000000000 Binary files a/src/icons/flags/cu.png and /dev/null differ diff --git a/src/icons/flags/cv.png b/src/icons/flags/cv.png deleted file mode 100755 index eb96f9ca6..000000000 Binary files a/src/icons/flags/cv.png and /dev/null differ diff --git a/src/icons/flags/cx.png b/src/icons/flags/cx.png deleted file mode 100755 index 35ca80cf8..000000000 Binary files a/src/icons/flags/cx.png and /dev/null differ diff --git a/src/icons/flags/cy.png b/src/icons/flags/cy.png deleted file mode 100755 index cd9253d6c..000000000 Binary files a/src/icons/flags/cy.png and /dev/null differ diff --git a/src/icons/flags/cz.png b/src/icons/flags/cz.png deleted file mode 100755 index 113c87374..000000000 Binary files a/src/icons/flags/cz.png and /dev/null differ diff --git a/src/icons/flags/de.png b/src/icons/flags/de.png deleted file mode 100755 index 5cf32c744..000000000 Binary files a/src/icons/flags/de.png and /dev/null differ diff --git a/src/icons/flags/dj.png b/src/icons/flags/dj.png deleted file mode 100755 index de0faaa0d..000000000 Binary files a/src/icons/flags/dj.png and /dev/null differ diff --git a/src/icons/flags/dk.png b/src/icons/flags/dk.png deleted file mode 100755 index 622cebd2c..000000000 Binary files a/src/icons/flags/dk.png and /dev/null differ diff --git a/src/icons/flags/dm.png b/src/icons/flags/dm.png deleted file mode 100755 index 9f6a3dd5f..000000000 Binary files a/src/icons/flags/dm.png and /dev/null differ diff --git a/src/icons/flags/do.png b/src/icons/flags/do.png deleted file mode 100755 index 46230992f..000000000 Binary files a/src/icons/flags/do.png and /dev/null differ diff --git a/src/icons/flags/dz.png b/src/icons/flags/dz.png deleted file mode 100755 index cc6b0149c..000000000 Binary files a/src/icons/flags/dz.png and /dev/null differ diff --git a/src/icons/flags/ec.png b/src/icons/flags/ec.png deleted file mode 100755 index 4ca13865f..000000000 Binary files a/src/icons/flags/ec.png and /dev/null differ diff --git a/src/icons/flags/ee.png b/src/icons/flags/ee.png deleted file mode 100755 index 4bd818044..000000000 Binary files a/src/icons/flags/ee.png and /dev/null differ diff --git a/src/icons/flags/eg.png b/src/icons/flags/eg.png deleted file mode 100755 index a7131a3a7..000000000 Binary files a/src/icons/flags/eg.png and /dev/null differ diff --git a/src/icons/flags/eh.png b/src/icons/flags/eh.png deleted file mode 100755 index e6566ce20..000000000 Binary files a/src/icons/flags/eh.png and /dev/null differ diff --git a/src/icons/flags/er.png b/src/icons/flags/er.png deleted file mode 100755 index 8223dbfcb..000000000 Binary files a/src/icons/flags/er.png and /dev/null differ diff --git a/src/icons/flags/es.png b/src/icons/flags/es.png deleted file mode 100755 index ef156815f..000000000 Binary files a/src/icons/flags/es.png and /dev/null differ diff --git a/src/icons/flags/et.png b/src/icons/flags/et.png deleted file mode 100755 index 11f79b002..000000000 Binary files a/src/icons/flags/et.png and /dev/null differ diff --git a/src/icons/flags/fi.png b/src/icons/flags/fi.png deleted file mode 100755 index 541a87271..000000000 Binary files a/src/icons/flags/fi.png and /dev/null differ diff --git a/src/icons/flags/fj.png b/src/icons/flags/fj.png deleted file mode 100755 index 4e8d07340..000000000 Binary files a/src/icons/flags/fj.png and /dev/null differ diff --git a/src/icons/flags/fk.png b/src/icons/flags/fk.png deleted file mode 100755 index 0c80c6e5c..000000000 Binary files a/src/icons/flags/fk.png and /dev/null differ diff --git a/src/icons/flags/fm.png b/src/icons/flags/fm.png deleted file mode 100755 index a77a777a6..000000000 Binary files a/src/icons/flags/fm.png and /dev/null differ diff --git a/src/icons/flags/fo.png b/src/icons/flags/fo.png deleted file mode 100755 index 957b0df66..000000000 Binary files a/src/icons/flags/fo.png and /dev/null differ diff --git a/src/icons/flags/fr.png b/src/icons/flags/fr.png deleted file mode 100755 index 25cbe709b..000000000 Binary files a/src/icons/flags/fr.png and /dev/null differ diff --git a/src/icons/flags/ga.png b/src/icons/flags/ga.png deleted file mode 100755 index 476fcf7da..000000000 Binary files a/src/icons/flags/ga.png and /dev/null differ diff --git a/src/icons/flags/gb.png b/src/icons/flags/gb.png deleted file mode 100644 index 405e897c5..000000000 Binary files a/src/icons/flags/gb.png and /dev/null differ diff --git a/src/icons/flags/gd.png b/src/icons/flags/gd.png deleted file mode 100755 index e533b304a..000000000 Binary files a/src/icons/flags/gd.png and /dev/null differ diff --git a/src/icons/flags/ge.png b/src/icons/flags/ge.png deleted file mode 100755 index 38a2a8b12..000000000 Binary files a/src/icons/flags/ge.png and /dev/null differ diff --git a/src/icons/flags/gf.png b/src/icons/flags/gf.png deleted file mode 100755 index 25cbe709b..000000000 Binary files a/src/icons/flags/gf.png and /dev/null differ diff --git a/src/icons/flags/gh.png b/src/icons/flags/gh.png deleted file mode 100755 index 952b1620a..000000000 Binary files a/src/icons/flags/gh.png and /dev/null differ diff --git a/src/icons/flags/gi.png b/src/icons/flags/gi.png deleted file mode 100755 index dbf58f99e..000000000 Binary files a/src/icons/flags/gi.png and /dev/null differ diff --git a/src/icons/flags/gl.png b/src/icons/flags/gl.png deleted file mode 100755 index 1a429de1b..000000000 Binary files a/src/icons/flags/gl.png and /dev/null differ diff --git a/src/icons/flags/gm.png b/src/icons/flags/gm.png deleted file mode 100755 index 483e0dd75..000000000 Binary files a/src/icons/flags/gm.png and /dev/null differ diff --git a/src/icons/flags/gn.png b/src/icons/flags/gn.png deleted file mode 100755 index 72e879adf..000000000 Binary files a/src/icons/flags/gn.png and /dev/null differ diff --git a/src/icons/flags/gp.png b/src/icons/flags/gp.png deleted file mode 100755 index 160dae80c..000000000 Binary files a/src/icons/flags/gp.png and /dev/null differ diff --git a/src/icons/flags/gq.png b/src/icons/flags/gq.png deleted file mode 100755 index 2cf6cf2a3..000000000 Binary files a/src/icons/flags/gq.png and /dev/null differ diff --git a/src/icons/flags/gr.png b/src/icons/flags/gr.png deleted file mode 100755 index e2864b920..000000000 Binary files a/src/icons/flags/gr.png and /dev/null differ diff --git a/src/icons/flags/gs.png b/src/icons/flags/gs.png deleted file mode 100755 index e37521f63..000000000 Binary files a/src/icons/flags/gs.png and /dev/null differ diff --git a/src/icons/flags/gt.png b/src/icons/flags/gt.png deleted file mode 100755 index abeaa1986..000000000 Binary files a/src/icons/flags/gt.png and /dev/null differ diff --git a/src/icons/flags/gu.png b/src/icons/flags/gu.png deleted file mode 100755 index f1248c5d4..000000000 Binary files a/src/icons/flags/gu.png and /dev/null differ diff --git a/src/icons/flags/gw.png b/src/icons/flags/gw.png deleted file mode 100755 index 2ad970b20..000000000 Binary files a/src/icons/flags/gw.png and /dev/null differ diff --git a/src/icons/flags/gy.png b/src/icons/flags/gy.png deleted file mode 100755 index b8f6a0442..000000000 Binary files a/src/icons/flags/gy.png and /dev/null differ diff --git a/src/icons/flags/hk.png b/src/icons/flags/hk.png deleted file mode 100755 index 5a3663a87..000000000 Binary files a/src/icons/flags/hk.png and /dev/null differ diff --git a/src/icons/flags/hm.png b/src/icons/flags/hm.png deleted file mode 100755 index 27c4d0a7b..000000000 Binary files a/src/icons/flags/hm.png and /dev/null differ diff --git a/src/icons/flags/hn.png b/src/icons/flags/hn.png deleted file mode 100755 index 97630a336..000000000 Binary files a/src/icons/flags/hn.png and /dev/null differ diff --git a/src/icons/flags/hr.png b/src/icons/flags/hr.png deleted file mode 100755 index 42d6f0727..000000000 Binary files a/src/icons/flags/hr.png and /dev/null differ diff --git a/src/icons/flags/ht.png b/src/icons/flags/ht.png deleted file mode 100755 index 674ec29f3..000000000 Binary files a/src/icons/flags/ht.png and /dev/null differ diff --git a/src/icons/flags/hu.png b/src/icons/flags/hu.png deleted file mode 100755 index 2d0181831..000000000 Binary files a/src/icons/flags/hu.png and /dev/null differ diff --git a/src/icons/flags/icons-set-readme.txt b/src/icons/flags/icons-set-readme.txt deleted file mode 100755 index 2e5ad529a..000000000 --- a/src/icons/flags/icons-set-readme.txt +++ /dev/null @@ -1,9 +0,0 @@ -Flag icons - http://www.famfamfam.com - -These icons are public domain, and as such are free for any use (attribution appreciated but not required). - -Note that these flags are named using the ISO3166-1 alpha-2 country codes where appropriate. A list of codes can be found at http://en.wikipedia.org/wiki/ISO_3166-1_alpha-2 - -If you find these icons useful, please donate via paypal to mjames@gmail.com (or click the donate button available at http://www.famfamfam.com/lab/icons/silk) - -Contact: mjames@gmail.com \ No newline at end of file diff --git a/src/icons/flags/id.png b/src/icons/flags/id.png deleted file mode 100755 index ba72a73f2..000000000 Binary files a/src/icons/flags/id.png and /dev/null differ diff --git a/src/icons/flags/ie.png b/src/icons/flags/ie.png deleted file mode 100755 index fc3a45586..000000000 Binary files a/src/icons/flags/ie.png and /dev/null differ diff --git a/src/icons/flags/il.png b/src/icons/flags/il.png deleted file mode 100755 index a6a4331d2..000000000 Binary files a/src/icons/flags/il.png and /dev/null differ diff --git a/src/icons/flags/in.png b/src/icons/flags/in.png deleted file mode 100755 index 6be798c16..000000000 Binary files a/src/icons/flags/in.png and /dev/null differ diff --git a/src/icons/flags/io.png b/src/icons/flags/io.png deleted file mode 100755 index d87ed5f93..000000000 Binary files a/src/icons/flags/io.png and /dev/null differ diff --git a/src/icons/flags/iq.png b/src/icons/flags/iq.png deleted file mode 100755 index 9ac7f01c3..000000000 Binary files a/src/icons/flags/iq.png and /dev/null differ diff --git a/src/icons/flags/ir.png b/src/icons/flags/ir.png deleted file mode 100755 index f038dc9ae..000000000 Binary files a/src/icons/flags/ir.png and /dev/null differ diff --git a/src/icons/flags/is.png b/src/icons/flags/is.png deleted file mode 100755 index a4f546273..000000000 Binary files a/src/icons/flags/is.png and /dev/null differ diff --git a/src/icons/flags/it.png b/src/icons/flags/it.png deleted file mode 100755 index 8f248c52c..000000000 Binary files a/src/icons/flags/it.png and /dev/null differ diff --git a/src/icons/flags/jm.png b/src/icons/flags/jm.png deleted file mode 100755 index 7a301fb69..000000000 Binary files a/src/icons/flags/jm.png and /dev/null differ diff --git a/src/icons/flags/jo.png b/src/icons/flags/jo.png deleted file mode 100755 index f7beba7ea..000000000 Binary files a/src/icons/flags/jo.png and /dev/null differ diff --git a/src/icons/flags/jp.png b/src/icons/flags/jp.png deleted file mode 100755 index fcb41a131..000000000 Binary files a/src/icons/flags/jp.png and /dev/null differ diff --git a/src/icons/flags/ke.png b/src/icons/flags/ke.png deleted file mode 100755 index dde4b7a5c..000000000 Binary files a/src/icons/flags/ke.png and /dev/null differ diff --git a/src/icons/flags/kg.png b/src/icons/flags/kg.png deleted file mode 100755 index 6ded1b102..000000000 Binary files a/src/icons/flags/kg.png and /dev/null differ diff --git a/src/icons/flags/kh.png b/src/icons/flags/kh.png deleted file mode 100755 index d8a0f0448..000000000 Binary files a/src/icons/flags/kh.png and /dev/null differ diff --git a/src/icons/flags/ki.png b/src/icons/flags/ki.png deleted file mode 100755 index 36bc72838..000000000 Binary files a/src/icons/flags/ki.png and /dev/null differ diff --git a/src/icons/flags/km.png b/src/icons/flags/km.png deleted file mode 100755 index a2e1c6244..000000000 Binary files a/src/icons/flags/km.png and /dev/null differ diff --git a/src/icons/flags/kn.png b/src/icons/flags/kn.png deleted file mode 100755 index 4570fc612..000000000 Binary files a/src/icons/flags/kn.png and /dev/null differ diff --git a/src/icons/flags/kp.png b/src/icons/flags/kp.png deleted file mode 100755 index 0a01c5e00..000000000 Binary files a/src/icons/flags/kp.png and /dev/null differ diff --git a/src/icons/flags/kr.png b/src/icons/flags/kr.png deleted file mode 100755 index cdffba1db..000000000 Binary files a/src/icons/flags/kr.png and /dev/null differ diff --git a/src/icons/flags/kw.png b/src/icons/flags/kw.png deleted file mode 100755 index 00e1c892b..000000000 Binary files a/src/icons/flags/kw.png and /dev/null differ diff --git a/src/icons/flags/ky.png b/src/icons/flags/ky.png deleted file mode 100755 index 13de72efa..000000000 Binary files a/src/icons/flags/ky.png and /dev/null differ diff --git a/src/icons/flags/kz.png b/src/icons/flags/kz.png deleted file mode 100755 index 947e721ab..000000000 Binary files a/src/icons/flags/kz.png and /dev/null differ diff --git a/src/icons/flags/la.png b/src/icons/flags/la.png deleted file mode 100755 index 257d2bc3c..000000000 Binary files a/src/icons/flags/la.png and /dev/null differ diff --git a/src/icons/flags/lb.png b/src/icons/flags/lb.png deleted file mode 100755 index 8affe4a81..000000000 Binary files a/src/icons/flags/lb.png and /dev/null differ diff --git a/src/icons/flags/lc.png b/src/icons/flags/lc.png deleted file mode 100644 index e610fe713..000000000 Binary files a/src/icons/flags/lc.png and /dev/null differ diff --git a/src/icons/flags/li.png b/src/icons/flags/li.png deleted file mode 100755 index 0d7ad9717..000000000 Binary files a/src/icons/flags/li.png and /dev/null differ diff --git a/src/icons/flags/lk.png b/src/icons/flags/lk.png deleted file mode 100755 index 165bcd2cc..000000000 Binary files a/src/icons/flags/lk.png and /dev/null differ diff --git a/src/icons/flags/lr.png b/src/icons/flags/lr.png deleted file mode 100755 index 111aae80e..000000000 Binary files a/src/icons/flags/lr.png and /dev/null differ diff --git a/src/icons/flags/ls.png b/src/icons/flags/ls.png deleted file mode 100755 index e9c653aa8..000000000 Binary files a/src/icons/flags/ls.png and /dev/null differ diff --git a/src/icons/flags/lt.png b/src/icons/flags/lt.png deleted file mode 100755 index 2e3b86f78..000000000 Binary files a/src/icons/flags/lt.png and /dev/null differ diff --git a/src/icons/flags/lu.png b/src/icons/flags/lu.png deleted file mode 100755 index 8e400a852..000000000 Binary files a/src/icons/flags/lu.png and /dev/null differ diff --git a/src/icons/flags/lv.png b/src/icons/flags/lv.png deleted file mode 100755 index d9236f966..000000000 Binary files a/src/icons/flags/lv.png and /dev/null differ diff --git a/src/icons/flags/ly.png b/src/icons/flags/ly.png deleted file mode 100755 index 4277cc376..000000000 Binary files a/src/icons/flags/ly.png and /dev/null differ diff --git a/src/icons/flags/ma.png b/src/icons/flags/ma.png deleted file mode 100755 index 44f2961c1..000000000 Binary files a/src/icons/flags/ma.png and /dev/null differ diff --git a/src/icons/flags/mc.png b/src/icons/flags/mc.png deleted file mode 100755 index 6647ff98b..000000000 Binary files a/src/icons/flags/mc.png and /dev/null differ diff --git a/src/icons/flags/md.png b/src/icons/flags/md.png deleted file mode 100755 index 7601ee5d5..000000000 Binary files a/src/icons/flags/md.png and /dev/null differ diff --git a/src/icons/flags/me.png b/src/icons/flags/me.png deleted file mode 100644 index 9b316f169..000000000 Binary files a/src/icons/flags/me.png and /dev/null differ diff --git a/src/icons/flags/mg.png b/src/icons/flags/mg.png deleted file mode 100755 index b8740f880..000000000 Binary files a/src/icons/flags/mg.png and /dev/null differ diff --git a/src/icons/flags/mh.png b/src/icons/flags/mh.png deleted file mode 100755 index ae1ca1da1..000000000 Binary files a/src/icons/flags/mh.png and /dev/null differ diff --git a/src/icons/flags/mk.png b/src/icons/flags/mk.png deleted file mode 100755 index c2b84b790..000000000 Binary files a/src/icons/flags/mk.png and /dev/null differ diff --git a/src/icons/flags/ml.png b/src/icons/flags/ml.png deleted file mode 100755 index 0796eaa5c..000000000 Binary files a/src/icons/flags/ml.png and /dev/null differ diff --git a/src/icons/flags/mm.png b/src/icons/flags/mm.png deleted file mode 100755 index d931b1dbe..000000000 Binary files a/src/icons/flags/mm.png and /dev/null differ diff --git a/src/icons/flags/mn.png b/src/icons/flags/mn.png deleted file mode 100755 index 8efe371b0..000000000 Binary files a/src/icons/flags/mn.png and /dev/null differ diff --git a/src/icons/flags/mo.png b/src/icons/flags/mo.png deleted file mode 100755 index fc49f581e..000000000 Binary files a/src/icons/flags/mo.png and /dev/null differ diff --git a/src/icons/flags/mp.png b/src/icons/flags/mp.png deleted file mode 100755 index df0c4b8c1..000000000 Binary files a/src/icons/flags/mp.png and /dev/null differ diff --git a/src/icons/flags/mq.png b/src/icons/flags/mq.png deleted file mode 100755 index 05452001f..000000000 Binary files a/src/icons/flags/mq.png and /dev/null differ diff --git a/src/icons/flags/mr.png b/src/icons/flags/mr.png deleted file mode 100755 index 6700d1ce9..000000000 Binary files a/src/icons/flags/mr.png and /dev/null differ diff --git a/src/icons/flags/ms.png b/src/icons/flags/ms.png deleted file mode 100755 index aef23fc51..000000000 Binary files a/src/icons/flags/ms.png and /dev/null differ diff --git a/src/icons/flags/mt.png b/src/icons/flags/mt.png deleted file mode 100755 index a3703194a..000000000 Binary files a/src/icons/flags/mt.png and /dev/null differ diff --git a/src/icons/flags/mu.png b/src/icons/flags/mu.png deleted file mode 100755 index c1e8b909d..000000000 Binary files a/src/icons/flags/mu.png and /dev/null differ diff --git a/src/icons/flags/mv.png b/src/icons/flags/mv.png deleted file mode 100755 index f03f90ac6..000000000 Binary files a/src/icons/flags/mv.png and /dev/null differ diff --git a/src/icons/flags/mw.png b/src/icons/flags/mw.png deleted file mode 100755 index 1ee6485ed..000000000 Binary files a/src/icons/flags/mw.png and /dev/null differ diff --git a/src/icons/flags/mx.png b/src/icons/flags/mx.png deleted file mode 100755 index 755f3be4d..000000000 Binary files a/src/icons/flags/mx.png and /dev/null differ diff --git a/src/icons/flags/my.png b/src/icons/flags/my.png deleted file mode 100755 index 1680e0f33..000000000 Binary files a/src/icons/flags/my.png and /dev/null differ diff --git a/src/icons/flags/mz.png b/src/icons/flags/mz.png deleted file mode 100755 index 9128db2a1..000000000 Binary files a/src/icons/flags/mz.png and /dev/null differ diff --git a/src/icons/flags/na.png b/src/icons/flags/na.png deleted file mode 100755 index a94c230cc..000000000 Binary files a/src/icons/flags/na.png and /dev/null differ diff --git a/src/icons/flags/nc.png b/src/icons/flags/nc.png deleted file mode 100755 index b8f86548b..000000000 Binary files a/src/icons/flags/nc.png and /dev/null differ diff --git a/src/icons/flags/ne.png b/src/icons/flags/ne.png deleted file mode 100755 index 60c893451..000000000 Binary files a/src/icons/flags/ne.png and /dev/null differ diff --git a/src/icons/flags/nf.png b/src/icons/flags/nf.png deleted file mode 100755 index 659bc0f0a..000000000 Binary files a/src/icons/flags/nf.png and /dev/null differ diff --git a/src/icons/flags/ng.png b/src/icons/flags/ng.png deleted file mode 100755 index 6a1e6ee67..000000000 Binary files a/src/icons/flags/ng.png and /dev/null differ diff --git a/src/icons/flags/ni.png b/src/icons/flags/ni.png deleted file mode 100755 index 6aab83f07..000000000 Binary files a/src/icons/flags/ni.png and /dev/null differ diff --git a/src/icons/flags/nl.png b/src/icons/flags/nl.png deleted file mode 100755 index 3d09d5e93..000000000 Binary files a/src/icons/flags/nl.png and /dev/null differ diff --git a/src/icons/flags/no.png b/src/icons/flags/no.png deleted file mode 100755 index 74264c586..000000000 Binary files a/src/icons/flags/no.png and /dev/null differ diff --git a/src/icons/flags/np.png b/src/icons/flags/np.png deleted file mode 100755 index 58d266605..000000000 Binary files a/src/icons/flags/np.png and /dev/null differ diff --git a/src/icons/flags/nr.png b/src/icons/flags/nr.png deleted file mode 100755 index 2c319caec..000000000 Binary files a/src/icons/flags/nr.png and /dev/null differ diff --git a/src/icons/flags/nu.png b/src/icons/flags/nu.png deleted file mode 100755 index 5e365e124..000000000 Binary files a/src/icons/flags/nu.png and /dev/null differ diff --git a/src/icons/flags/nz.png b/src/icons/flags/nz.png deleted file mode 100755 index be935de87..000000000 Binary files a/src/icons/flags/nz.png and /dev/null differ diff --git a/src/icons/flags/om.png b/src/icons/flags/om.png deleted file mode 100755 index dce4f36ea..000000000 Binary files a/src/icons/flags/om.png and /dev/null differ diff --git a/src/icons/flags/pa.png b/src/icons/flags/pa.png deleted file mode 100755 index 59a45a1b2..000000000 Binary files a/src/icons/flags/pa.png and /dev/null differ diff --git a/src/icons/flags/pe.png b/src/icons/flags/pe.png deleted file mode 100755 index b14d04d8b..000000000 Binary files a/src/icons/flags/pe.png and /dev/null differ diff --git a/src/icons/flags/pf.png b/src/icons/flags/pf.png deleted file mode 100755 index 0da2b6c3d..000000000 Binary files a/src/icons/flags/pf.png and /dev/null differ diff --git a/src/icons/flags/pg.png b/src/icons/flags/pg.png deleted file mode 100755 index bcd1ea2eb..000000000 Binary files a/src/icons/flags/pg.png and /dev/null differ diff --git a/src/icons/flags/ph.png b/src/icons/flags/ph.png deleted file mode 100755 index 89083e942..000000000 Binary files a/src/icons/flags/ph.png and /dev/null differ diff --git a/src/icons/flags/pk.png b/src/icons/flags/pk.png deleted file mode 100755 index fc036d270..000000000 Binary files a/src/icons/flags/pk.png and /dev/null differ diff --git a/src/icons/flags/pl.png b/src/icons/flags/pl.png deleted file mode 100755 index 52c7a9d55..000000000 Binary files a/src/icons/flags/pl.png and /dev/null differ diff --git a/src/icons/flags/pm.png b/src/icons/flags/pm.png deleted file mode 100755 index 0eea37cd7..000000000 Binary files a/src/icons/flags/pm.png and /dev/null differ diff --git a/src/icons/flags/pn.png b/src/icons/flags/pn.png deleted file mode 100755 index edf6e5722..000000000 Binary files a/src/icons/flags/pn.png and /dev/null differ diff --git a/src/icons/flags/pr.png b/src/icons/flags/pr.png deleted file mode 100755 index 5eb084ea5..000000000 Binary files a/src/icons/flags/pr.png and /dev/null differ diff --git a/src/icons/flags/ps.png b/src/icons/flags/ps.png deleted file mode 100755 index 12a338a26..000000000 Binary files a/src/icons/flags/ps.png and /dev/null differ diff --git a/src/icons/flags/pt.png b/src/icons/flags/pt.png deleted file mode 100755 index dfe00c44c..000000000 Binary files a/src/icons/flags/pt.png and /dev/null differ diff --git a/src/icons/flags/pw.png b/src/icons/flags/pw.png deleted file mode 100755 index 0581288c7..000000000 Binary files a/src/icons/flags/pw.png and /dev/null differ diff --git a/src/icons/flags/py.png b/src/icons/flags/py.png deleted file mode 100755 index 7010556b6..000000000 Binary files a/src/icons/flags/py.png and /dev/null differ diff --git a/src/icons/flags/qa.png b/src/icons/flags/qa.png deleted file mode 100755 index b8dab3314..000000000 Binary files a/src/icons/flags/qa.png and /dev/null differ diff --git a/src/icons/flags/re.png b/src/icons/flags/re.png deleted file mode 100755 index 25cbe709b..000000000 Binary files a/src/icons/flags/re.png and /dev/null differ diff --git a/src/icons/flags/ro.png b/src/icons/flags/ro.png deleted file mode 100755 index 2535bc81f..000000000 Binary files a/src/icons/flags/ro.png and /dev/null differ diff --git a/src/icons/flags/rs.png b/src/icons/flags/rs.png deleted file mode 100644 index 23f716dc4..000000000 Binary files a/src/icons/flags/rs.png and /dev/null differ diff --git a/src/icons/flags/ru.png b/src/icons/flags/ru.png deleted file mode 100755 index 17641a673..000000000 Binary files a/src/icons/flags/ru.png and /dev/null differ diff --git a/src/icons/flags/rw.png b/src/icons/flags/rw.png deleted file mode 100755 index f4b0136ea..000000000 Binary files a/src/icons/flags/rw.png and /dev/null differ diff --git a/src/icons/flags/sa.png b/src/icons/flags/sa.png deleted file mode 100755 index 36ebcb7cf..000000000 Binary files a/src/icons/flags/sa.png and /dev/null differ diff --git a/src/icons/flags/sb.png b/src/icons/flags/sb.png deleted file mode 100755 index 9293fa454..000000000 Binary files a/src/icons/flags/sb.png and /dev/null differ diff --git a/src/icons/flags/sc.png b/src/icons/flags/sc.png deleted file mode 100755 index 8ad512b7e..000000000 Binary files a/src/icons/flags/sc.png and /dev/null differ diff --git a/src/icons/flags/sd.png b/src/icons/flags/sd.png deleted file mode 100755 index eba0a2079..000000000 Binary files a/src/icons/flags/sd.png and /dev/null differ diff --git a/src/icons/flags/se.png b/src/icons/flags/se.png deleted file mode 100755 index e2b347c78..000000000 Binary files a/src/icons/flags/se.png and /dev/null differ diff --git a/src/icons/flags/sg.png b/src/icons/flags/sg.png deleted file mode 100755 index 975d6bb08..000000000 Binary files a/src/icons/flags/sg.png and /dev/null differ diff --git a/src/icons/flags/sh.png b/src/icons/flags/sh.png deleted file mode 100755 index 9b6d05e3b..000000000 Binary files a/src/icons/flags/sh.png and /dev/null differ diff --git a/src/icons/flags/si.png b/src/icons/flags/si.png deleted file mode 100755 index 266b9df29..000000000 Binary files a/src/icons/flags/si.png and /dev/null differ diff --git a/src/icons/flags/sj.png b/src/icons/flags/sj.png deleted file mode 100755 index 74264c586..000000000 Binary files a/src/icons/flags/sj.png and /dev/null differ diff --git a/src/icons/flags/sk.png b/src/icons/flags/sk.png deleted file mode 100755 index 3d96e0bb5..000000000 Binary files a/src/icons/flags/sk.png and /dev/null differ diff --git a/src/icons/flags/sl.png b/src/icons/flags/sl.png deleted file mode 100755 index c59445bc5..000000000 Binary files a/src/icons/flags/sl.png and /dev/null differ diff --git a/src/icons/flags/sm.png b/src/icons/flags/sm.png deleted file mode 100755 index 07282bb55..000000000 Binary files a/src/icons/flags/sm.png and /dev/null differ diff --git a/src/icons/flags/sn.png b/src/icons/flags/sn.png deleted file mode 100755 index 89961cb89..000000000 Binary files a/src/icons/flags/sn.png and /dev/null differ diff --git a/src/icons/flags/so.png b/src/icons/flags/so.png deleted file mode 100755 index ee5d955e5..000000000 Binary files a/src/icons/flags/so.png and /dev/null differ diff --git a/src/icons/flags/sr.png b/src/icons/flags/sr.png deleted file mode 100755 index a217ac418..000000000 Binary files a/src/icons/flags/sr.png and /dev/null differ diff --git a/src/icons/flags/st.png b/src/icons/flags/st.png deleted file mode 100755 index fb781300c..000000000 Binary files a/src/icons/flags/st.png and /dev/null differ diff --git a/src/icons/flags/sv.png b/src/icons/flags/sv.png deleted file mode 100755 index bed69b9ab..000000000 Binary files a/src/icons/flags/sv.png and /dev/null differ diff --git a/src/icons/flags/sy.png b/src/icons/flags/sy.png deleted file mode 100755 index 6b9e5358e..000000000 Binary files a/src/icons/flags/sy.png and /dev/null differ diff --git a/src/icons/flags/sz.png b/src/icons/flags/sz.png deleted file mode 100755 index aadce5227..000000000 Binary files a/src/icons/flags/sz.png and /dev/null differ diff --git a/src/icons/flags/tc.png b/src/icons/flags/tc.png deleted file mode 100755 index 729ce5a63..000000000 Binary files a/src/icons/flags/tc.png and /dev/null differ diff --git a/src/icons/flags/td.png b/src/icons/flags/td.png deleted file mode 100755 index 24421ad3d..000000000 Binary files a/src/icons/flags/td.png and /dev/null differ diff --git a/src/icons/flags/tf.png b/src/icons/flags/tf.png deleted file mode 100755 index faf0e2009..000000000 Binary files a/src/icons/flags/tf.png and /dev/null differ diff --git a/src/icons/flags/tg.png b/src/icons/flags/tg.png deleted file mode 100755 index 6f7094783..000000000 Binary files a/src/icons/flags/tg.png and /dev/null differ diff --git a/src/icons/flags/th.png b/src/icons/flags/th.png deleted file mode 100755 index c1817ebc9..000000000 Binary files a/src/icons/flags/th.png and /dev/null differ diff --git a/src/icons/flags/tj.png b/src/icons/flags/tj.png deleted file mode 100755 index 68dba1abe..000000000 Binary files a/src/icons/flags/tj.png and /dev/null differ diff --git a/src/icons/flags/tk.png b/src/icons/flags/tk.png deleted file mode 100755 index f3aa0f77f..000000000 Binary files a/src/icons/flags/tk.png and /dev/null differ diff --git a/src/icons/flags/tl.png b/src/icons/flags/tl.png deleted file mode 100755 index 0fa1b5979..000000000 Binary files a/src/icons/flags/tl.png and /dev/null differ diff --git a/src/icons/flags/tm.png b/src/icons/flags/tm.png deleted file mode 100755 index cb1b24dd1..000000000 Binary files a/src/icons/flags/tm.png and /dev/null differ diff --git a/src/icons/flags/tn.png b/src/icons/flags/tn.png deleted file mode 100755 index 35215a539..000000000 Binary files a/src/icons/flags/tn.png and /dev/null differ diff --git a/src/icons/flags/to.png b/src/icons/flags/to.png deleted file mode 100755 index 4a208a5e9..000000000 Binary files a/src/icons/flags/to.png and /dev/null differ diff --git a/src/icons/flags/tr.png b/src/icons/flags/tr.png deleted file mode 100755 index 97c147b88..000000000 Binary files a/src/icons/flags/tr.png and /dev/null differ diff --git a/src/icons/flags/tt.png b/src/icons/flags/tt.png deleted file mode 100755 index add5c9a8e..000000000 Binary files a/src/icons/flags/tt.png and /dev/null differ diff --git a/src/icons/flags/tv.png b/src/icons/flags/tv.png deleted file mode 100755 index f439e47a6..000000000 Binary files a/src/icons/flags/tv.png and /dev/null differ diff --git a/src/icons/flags/tw.png b/src/icons/flags/tw.png deleted file mode 100755 index 242fa9ee2..000000000 Binary files a/src/icons/flags/tw.png and /dev/null differ diff --git a/src/icons/flags/tz.png b/src/icons/flags/tz.png deleted file mode 100755 index 80f0bda04..000000000 Binary files a/src/icons/flags/tz.png and /dev/null differ diff --git a/src/icons/flags/ua.png b/src/icons/flags/ua.png deleted file mode 100755 index 7182cb387..000000000 Binary files a/src/icons/flags/ua.png and /dev/null differ diff --git a/src/icons/flags/ug.png b/src/icons/flags/ug.png deleted file mode 100755 index 339774547..000000000 Binary files a/src/icons/flags/ug.png and /dev/null differ diff --git a/src/icons/flags/um.png b/src/icons/flags/um.png deleted file mode 100755 index 714556bfa..000000000 Binary files a/src/icons/flags/um.png and /dev/null differ diff --git a/src/icons/flags/us.png b/src/icons/flags/us.png deleted file mode 100755 index e1a588054..000000000 Binary files a/src/icons/flags/us.png and /dev/null differ diff --git a/src/icons/flags/uy.png b/src/icons/flags/uy.png deleted file mode 100755 index 52d04308f..000000000 Binary files a/src/icons/flags/uy.png and /dev/null differ diff --git a/src/icons/flags/uz.png b/src/icons/flags/uz.png deleted file mode 100755 index e387bea75..000000000 Binary files a/src/icons/flags/uz.png and /dev/null differ diff --git a/src/icons/flags/va.png b/src/icons/flags/va.png deleted file mode 100755 index 557f514f4..000000000 Binary files a/src/icons/flags/va.png and /dev/null differ diff --git a/src/icons/flags/vc.png b/src/icons/flags/vc.png deleted file mode 100755 index 22d5eaa36..000000000 Binary files a/src/icons/flags/vc.png and /dev/null differ diff --git a/src/icons/flags/ve.png b/src/icons/flags/ve.png deleted file mode 100755 index 3b59ee680..000000000 Binary files a/src/icons/flags/ve.png and /dev/null differ diff --git a/src/icons/flags/vg.png b/src/icons/flags/vg.png deleted file mode 100755 index da34b84cf..000000000 Binary files a/src/icons/flags/vg.png and /dev/null differ diff --git a/src/icons/flags/vi.png b/src/icons/flags/vi.png deleted file mode 100755 index 581cb924e..000000000 Binary files a/src/icons/flags/vi.png and /dev/null differ diff --git a/src/icons/flags/vn.png b/src/icons/flags/vn.png deleted file mode 100755 index a2cd8a151..000000000 Binary files a/src/icons/flags/vn.png and /dev/null differ diff --git a/src/icons/flags/vu.png b/src/icons/flags/vu.png deleted file mode 100755 index 32d7756d3..000000000 Binary files a/src/icons/flags/vu.png and /dev/null differ diff --git a/src/icons/flags/wf.png b/src/icons/flags/wf.png deleted file mode 100755 index d60c5b4b2..000000000 Binary files a/src/icons/flags/wf.png and /dev/null differ diff --git a/src/icons/flags/ws.png b/src/icons/flags/ws.png deleted file mode 100755 index 8b40fdd22..000000000 Binary files a/src/icons/flags/ws.png and /dev/null differ diff --git a/src/icons/flags/ye.png b/src/icons/flags/ye.png deleted file mode 100755 index 9279e7e02..000000000 Binary files a/src/icons/flags/ye.png and /dev/null differ diff --git a/src/icons/flags/yt.png b/src/icons/flags/yt.png deleted file mode 100755 index a12f24d01..000000000 Binary files a/src/icons/flags/yt.png and /dev/null differ diff --git a/src/icons/flags/za.png b/src/icons/flags/za.png deleted file mode 100755 index 489545f88..000000000 Binary files a/src/icons/flags/za.png and /dev/null differ diff --git a/src/icons/flags/zm.png b/src/icons/flags/zm.png deleted file mode 100755 index 69dddb861..000000000 Binary files a/src/icons/flags/zm.png and /dev/null differ diff --git a/src/icons/flags/zw.png b/src/icons/flags/zw.png deleted file mode 100755 index a795223b7..000000000 Binary files a/src/icons/flags/zw.png and /dev/null differ diff --git a/src/icons/loading.png b/src/icons/loading.png deleted file mode 100644 index 09376599d..000000000 Binary files a/src/icons/loading.png and /dev/null differ diff --git a/src/icons/qbittorrent.desktop b/src/icons/qbittorrent.desktop deleted file mode 100644 index 09b8a8790..000000000 --- a/src/icons/qbittorrent.desktop +++ /dev/null @@ -1,190 +0,0 @@ -[Desktop Entry] -Categories=Network;FileTransfer;P2P;Qt; -Exec=qbittorrent %U -GenericName=BitTorrent client -Comment=Download and share files over BitTorrent -Icon=qbittorrent -MimeType=application/x-bittorrent;x-scheme-handler/magnet; -Name=qBittorrent -Terminal=false -Type=Application -StartupNotify=false -StartupWMClass=qbittorrent -Keywords=bittorrent;torrent;magnet;download;p2p; - -# Translations -Comment[oc]=Telecargar e partejar de fichièrs amb BitTorrent -GenericName[oc]=Client BitTorrent -Name[oc]=qBittorrent -Comment[af]=Aflaai en deel lêers oor BitTorrent -GenericName[af]=BitTorrent kliënt -Name[af]=qBittorrent -Comment[ar]=نزّل وشارك الملفات عبر كيوبت‎تورنت -GenericName[ar]=عميل بت‎تورنت -Name[ar]=كيوبت‎تورنت -Comment[be]=Сцягванне і раздача файлаў праз пратакол BitTorrent -GenericName[be]=BitTorrent-кліент -Name[be]=qBittorrent -Comment[bg]=Сваляне и споделяне на файлове чрез BitTorrent -GenericName[bg]=BitTorrent клиент -Name[bg]=qBittorrent -Comment[bn]=বিটটরেন্টে ফাইল ডাউনলোড এবং শেয়ার করুন -GenericName[bn]=বিটটরেন্ট ক্লায়েন্ট -Name[bn]=কিউবি্টটরেন্ট -Comment[bs]=Preuzmi i dijeli datoteke preko BitTorrent-a -GenericName[bs]=BitTorrent klijent -Name[bs]=qBittorrent -Comment[ca]=Baixeu i compartiu fitxers mitjançant BitTorrent -GenericName[ca]=Client de BitTorrent -Name[ca]=qBittorrent -Comment[cs]=Stahování a sdílení souborů přes síť BitTorrent -GenericName[cs]=BitTorrent klient -Name[cs]=qBittorrent -Comment[da]=Download og del filer over BitTorrent -GenericName[da]=BitTorrent klient -Name[da]=qBittorrent -Comment[de]=Über BitTorrent Dateien herunterladen und teilen -GenericName[de]=BitTorrent Client -Name[de]=qBittorrent -Comment[el]=Κάντε λήψη και ανταλάξτε αρχεία μέσω BitTorrent -GenericName[el]=Πελάτης BitTorrent -Name[el]=qBittorrent -Comment[en_GB]=Download and share files over BitTorrent -GenericName[en_GB]=BitTorrent client -Name[en_GB]=qBittorrent -Comment[es]=Descargue y comparta archivos por BitTorrent -GenericName[es]=Cliente BitTorrent -Name[es]=qBittorrent -Comment[eu]=Jeitsi eta elkarbanatu agiriak BitTorrent-en -GenericName[eu]=BitTorrent bezeroa -Name[eu]=qBittorrent -Comment[fa]=دانلود و به اشتراک گذاری فایل های بوسیله بیت تورنت -GenericName[fa]=بیت تورنت نسخه کلاینت -Name[fa]=کیو بیت تورنت -Comment[fi]=Lataa ja jaa tiedostoja BitTorrentia käyttäen -GenericName[fi]=BitTorrent-asiakasohjelma -Name[fi]=qBittorrent -Comment[fr]=Télécharger et partager des fichiers avec BitTorrent -GenericName[fr]=Client BitTorrent -Name[fr]=qBittorrent -Comment[gl]=Descargar e compartir ficheiros co protocolo BitTorrent -GenericName[gl]=Cliente BitTorrent -Name[gl]=qBittorrent -Comment[gu]=બિટ્ટોરેંટ પર ફાઈલો ડાઉનલોડ અને શેર કરો -GenericName[gu]=બિટ્ટોરેંટ ક્લાયન્ટ -Name[gu]=ક્યૂ-બિટ્ટોરેંટ -Comment[he]=הורד ושתף קבצים על גבי ביטורנט -GenericName[he]=לקוח ביטורנט -Name[he]=qBittorrent -Comment[hr]=Preuzmite i dijelite datoteke putem BitTorrenta -GenericName[hr]=BitTorrent klijent -Name[hr]=qBittorrent -Comment[hu]=Fájlok letöltése és megosztása a BitTorrent hálózaton keresztül -GenericName[hu]=BitTorrent kliens -Name[hu]=qBittorrent -Comment[id]=Unduh dan berbagi berkas melalui BitTorrent -GenericName[id]=Klien BitTorrent -Name[id]=qBittorrent -Comment[is]=Sækja og deila skrám yfir BitTorrent -GenericName[is]=BitTorrent biðlarar -Name[is]=qBittorrent -Comment[it]=Client BitTorrent per il download di file via internet -GenericName[it]=Client BitTorrent -Name[it]=qBittorrent -Comment[ja]=BitTorrent でファイルをダウンロードおよび共有します -GenericName[ja]=BitTorrent クライアント -Name[ja]=qBittorrent -Comment[ka]=ჩამოტვირთე და გააზიარე ფაილები Bittorrent-ის საშუალებით -GenericName[ka]=BitTorrent კლიენტი -Name[ka]=qBittorrent -Comment[ko]=비트토런트를 통해 파일을 다운로드하고 공유합니다 -GenericName[ko]=비트토런트 클라이언트 -Name[ko]=큐빗토런트 -Comment[zh]=通过 BitTorrent 下载和分享文件 -GenericName[zh]=BitTorrent 客户端 -Name[zh]=qBittorrent -Comment[lt]=Atsisiųskite bei dalinkitės failais BitTorrent tinkle -GenericName[lt]=BitTorrent klientas -Name[lt]=qBittorrent -Comment[nb]=Last ned og del filer over BitTorrent -GenericName[nb]=BitTorrent-klient -Name[nb]=qBittorrent -Comment[nqo]=ߞߐߕߐ߯ߘߐ ߟߎ߬ ߟߊߖߌ߰ ߞߊ߬ ߓߊ߲߫ ߞߵߊ߬ߟߎ߬ ߘߐߕߟߊ߫ ߓߌߙߏߙߍ߲ߕ ߞߊ߲߬ -GenericName[nqo]=ߓߌߙߏߙߍ߲ߕ ߕߣߐ߬ߓߐ߬ߟߊ -Name[nqo]=ߞߎ߳ߓߌߕߏߙߍ߲ߕ -Comment[nl]=Bestanden downloaden en delen via BitTorrent -GenericName[nl]=BitTorrent-cliënt -Name[nl]=qBittorrent -Comment[pl]=Pobieraj i dziel się plikami przez BitTorrent -GenericName[pl]=Klient BitTorrent -Name[pl]=qBittorrent -Comment[pt]=Transferir e partilhar ficheiros por BitTorrent -GenericName[pt]=Cliente BitTorrent -Name[pt]=qBittorrent -Comment[pt_BR]=Baixe e compartilhe arquivos por BitTorrent -GenericName[pt_BR]=Cliente BitTorrent -Name[pt_BR]=qBittorrent -Comment[ro]=Descărcați și partajați fișiere prin BitTorrent -GenericName[ro]=Client BitTorrent -Name[ro]=qBittorrent -Comment[ru]=Скачивайте и делитесь файлами с помощью BitTorrent -GenericName[ru]=BitTorrent-клиент -Name[ru]=qBittorrent -Comment[sk]=Sťahovanie a zdieľanie súborov prostredníctvom siete BitTorrent -GenericName[sk]=Klient siete BitTorrent -Name[sk]=qBittorrent -Comment[sl]=Prenesite in delite datoteke preko BitTorrenta -GenericName[sl]=BitTorrent odjemalec -Name[sl]=qBittorrent -GenericName[sr]=BitTorrent-клијент -Comment[sr@latin]=Preuzimanje i deljenje fajlova preko BitTorrent-a -GenericName[sr@latin]=BitTorrent klijent -Name[sr@latin]=qBittorrent -Comment[sv]=Hämta och dela filer över BitTorrent -GenericName[sv]=BitTorrent-klient -Name[sv]=qBittorrent -Comment[uz@Latn]=BitTorrent orqali fayllarni yuklab olish va baham ko‘rish -GenericName[uz@Latn]=BitTorrent mijozi -Name[uz@Latn]=qBittorrent -Comment[te]=క్యు బిట్ టొరెంట్ తో ఫైల్స్ దిగుమతి చేసుకోండి , పంచుకోండి -GenericName[te]=క్యు బిట్ టొరెంట్ క్లయింట్ -Name[te]=క్యు బిట్ టొరెంట్ -Comment[hi_IN]= अपनी फाइलें BitTorrent के माध्यम से डाउनलोड आैर साॅझा करें -GenericName[hi_IN]=BitTorrent उपभोक्ता -Name[hi_IN]=qBittorrent -Comment[tr]=Dosyaları BitTorrent üzerinden indirin ve paylaşın -GenericName[tr]=BitTorrent istemcisi -Name[tr]=qBittorrent -Comment[uk]=Завантажувати і обмінюватися файлами через BitTorrent -GenericName[uk]=BitTorrent-клієнт -Name[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 -Comment[zh_HK]=經由BitTorrent下載並分享檔案 -GenericName[zh_HK]=BitTorrent用戶端 -Name[zh_HK]=qBittorrent -Comment[zh_TW]=經由 BitTorrent 下載並分享檔案 -GenericName[zh_TW]=BitTorrent 客戶端 -Name[zh_TW]=qBittorrent -Comment[lv_LV]=Lejupielādēt un koplietot failus ar BitTorrent -GenericName[lv_LV]=BitTorrent klients -Name[lv_LV]=qBittorrent -Comment[ms_MY]=Muat turun dan kongsi fail melalui BitTorrent -GenericName[ms_MY]=Klien BitTorrent -Name[ms_MY]=qBittorrent -Comment[eo]=Elŝutu kaj kunhavigu dosierojn per BitTorrent -GenericName[eo]=BitTorrent-kliento -Name[eo]=qBittorrent -Comment[mn_MN]=BitTorrent ашиглан файлуудыг татаж түгээх -GenericName[mn_MN]=BitTorrent үйлчлүүлэгч -Name[mn_MN]=qBittorrent -Comment[ne_NP]=फाइलहरू डाउनलोड गर्नुहोस् र BitTorrent मा साझा गर्नुहोस् -GenericName[ne_NP]=BitTorrent क्लाइन्ट -Name[ne_NP]=qBittorrent -Comment[en_AU]=Download and share files over BitTorrent -GenericName[en_AU]=BitTorrent client -Name[en_AU]=qBittorrent -Comment[th]=ดาว์นโหลดและแชร์ไฟล์ด้วยบิททอเร้น -GenericName[th]=โปรแกรมบิททอเร้น -Name[th]=qBittorrent diff --git a/src/icons/qbittorrent.png b/src/icons/qbittorrent.png deleted file mode 100644 index 9ec69b38a..000000000 Binary files a/src/icons/qbittorrent.png and /dev/null differ diff --git a/src/icons/qbt-theme/README.md b/src/icons/qbt-theme/README.md deleted file mode 100644 index 7a636b5f8..000000000 --- a/src/icons/qbt-theme/README.md +++ /dev/null @@ -1,7 +0,0 @@ -qBittorrent Theme Icons ------------------------------------------- -Initial `qbt-theme` icons created by Bert Verhelst (). - -Icons are based on the `Font-Awesome` icon-set: [link](http://fontawesome.io/icons/). - -If you need to add an icon that qBittorrent does not already use, you can take an icon from the SVG fork of `Font-Awesome`: [link](https://github.com/encharm/Font-Awesome-SVG-PNG). diff --git a/src/icons/qbt-theme/application-exit.png b/src/icons/qbt-theme/application-exit.png deleted file mode 100644 index 04e772ab6..000000000 Binary files a/src/icons/qbt-theme/application-exit.png and /dev/null differ diff --git a/src/icons/qbt-theme/application-rss+xml.png b/src/icons/qbt-theme/application-rss+xml.png deleted file mode 100644 index 9b6bc538e..000000000 Binary files a/src/icons/qbt-theme/application-rss+xml.png and /dev/null differ diff --git a/src/icons/qbt-theme/application-x-mswinurl.png b/src/icons/qbt-theme/application-x-mswinurl.png deleted file mode 100644 index c13683d40..000000000 Binary files a/src/icons/qbt-theme/application-x-mswinurl.png and /dev/null differ diff --git a/src/icons/qbt-theme/build-icons/Gruntfile.js b/src/icons/qbt-theme/build-icons/Gruntfile.js deleted file mode 100644 index 2a88a4639..000000000 --- a/src/icons/qbt-theme/build-icons/Gruntfile.js +++ /dev/null @@ -1,22 +0,0 @@ -module.exports = function(grunt) { - - grunt.initConfig({ - svg2png: { - all: { - options:{ - size: 256 - }, - files: [ - { - src: ['icons/*.svg'] - } - ] - } - } - }); - - grunt.loadNpmTasks('grunt-svg2png'); - - grunt.registerTask('default', ['svg2png']); - -} \ No newline at end of file diff --git a/src/icons/qbt-theme/build-icons/icons/application-exit.svg b/src/icons/qbt-theme/build-icons/icons/application-exit.svg deleted file mode 100644 index 3c8870ed6..000000000 --- a/src/icons/qbt-theme/build-icons/icons/application-exit.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - diff --git a/src/icons/qbt-theme/build-icons/icons/application-rss+xml.svg b/src/icons/qbt-theme/build-icons/icons/application-rss+xml.svg deleted file mode 100644 index 9865d9d62..000000000 --- a/src/icons/qbt-theme/build-icons/icons/application-rss+xml.svg +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - diff --git a/src/icons/qbt-theme/build-icons/icons/application-x-mswinurl.svg b/src/icons/qbt-theme/build-icons/icons/application-x-mswinurl.svg deleted file mode 100644 index 0e77f1f49..000000000 --- a/src/icons/qbt-theme/build-icons/icons/application-x-mswinurl.svg +++ /dev/null @@ -1,74 +0,0 @@ - - - - - - - - diff --git a/src/icons/qbt-theme/build-icons/icons/checked.svg b/src/icons/qbt-theme/build-icons/icons/checked.svg deleted file mode 100644 index 0e18ffc5b..000000000 --- a/src/icons/qbt-theme/build-icons/icons/checked.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - diff --git a/src/icons/qbt-theme/build-icons/icons/configure.svg b/src/icons/qbt-theme/build-icons/icons/configure.svg deleted file mode 100644 index 604af0e8a..000000000 --- a/src/icons/qbt-theme/build-icons/icons/configure.svg +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/src/icons/qbt-theme/build-icons/icons/dialog-cancel.svg b/src/icons/qbt-theme/build-icons/icons/dialog-cancel.svg deleted file mode 100644 index cd5b08475..000000000 --- a/src/icons/qbt-theme/build-icons/icons/dialog-cancel.svg +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - diff --git a/src/icons/qbt-theme/build-icons/icons/dialog-information.svg b/src/icons/qbt-theme/build-icons/icons/dialog-information.svg deleted file mode 100644 index afca90d12..000000000 --- a/src/icons/qbt-theme/build-icons/icons/dialog-information.svg +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - diff --git a/src/icons/qbt-theme/build-icons/icons/dialog-warning.svg b/src/icons/qbt-theme/build-icons/icons/dialog-warning.svg deleted file mode 100644 index 01014b1e5..000000000 --- a/src/icons/qbt-theme/build-icons/icons/dialog-warning.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - diff --git a/src/icons/qbt-theme/build-icons/icons/document-edit-verify.svg b/src/icons/qbt-theme/build-icons/icons/document-edit-verify.svg deleted file mode 100644 index 7431906b6..000000000 --- a/src/icons/qbt-theme/build-icons/icons/document-edit-verify.svg +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - - - - diff --git a/src/icons/qbt-theme/build-icons/icons/document-edit.svg b/src/icons/qbt-theme/build-icons/icons/document-edit.svg deleted file mode 100644 index c9557f269..000000000 --- a/src/icons/qbt-theme/build-icons/icons/document-edit.svg +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - - - - - - diff --git a/src/icons/qbt-theme/build-icons/icons/document-encrypt.svg b/src/icons/qbt-theme/build-icons/icons/document-encrypt.svg deleted file mode 100644 index 238cb4428..000000000 --- a/src/icons/qbt-theme/build-icons/icons/document-encrypt.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - diff --git a/src/icons/qbt-theme/build-icons/icons/document-import.svg b/src/icons/qbt-theme/build-icons/icons/document-import.svg deleted file mode 100644 index 9d3675f2b..000000000 --- a/src/icons/qbt-theme/build-icons/icons/document-import.svg +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - - - - - - - - diff --git a/src/icons/qbt-theme/build-icons/icons/document-new.svg b/src/icons/qbt-theme/build-icons/icons/document-new.svg deleted file mode 100644 index 5b8c014a4..000000000 --- a/src/icons/qbt-theme/build-icons/icons/document-new.svg +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - - - - - - - diff --git a/src/icons/qbt-theme/build-icons/icons/document-properties.svg b/src/icons/qbt-theme/build-icons/icons/document-properties.svg deleted file mode 100644 index dd57a3485..000000000 --- a/src/icons/qbt-theme/build-icons/icons/document-properties.svg +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - - - - - - - diff --git a/src/icons/qbt-theme/build-icons/icons/document-save.svg b/src/icons/qbt-theme/build-icons/icons/document-save.svg deleted file mode 100644 index 28dc9eb0c..000000000 --- a/src/icons/qbt-theme/build-icons/icons/document-save.svg +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - diff --git a/src/icons/qbt-theme/build-icons/icons/download.svg b/src/icons/qbt-theme/build-icons/icons/download.svg deleted file mode 100644 index f966e9921..000000000 --- a/src/icons/qbt-theme/build-icons/icons/download.svg +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - diff --git a/src/icons/qbt-theme/build-icons/icons/edit-clear-history.svg b/src/icons/qbt-theme/build-icons/icons/edit-clear-history.svg deleted file mode 100644 index 7cec56fdb..000000000 --- a/src/icons/qbt-theme/build-icons/icons/edit-clear-history.svg +++ /dev/null @@ -1,43 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/icons/qbt-theme/build-icons/icons/edit-clear.svg b/src/icons/qbt-theme/build-icons/icons/edit-clear.svg deleted file mode 100644 index 243700e47..000000000 --- a/src/icons/qbt-theme/build-icons/icons/edit-clear.svg +++ /dev/null @@ -1,40 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/icons/qbt-theme/build-icons/icons/edit-copy.svg b/src/icons/qbt-theme/build-icons/icons/edit-copy.svg deleted file mode 100644 index 1da15fdd2..000000000 --- a/src/icons/qbt-theme/build-icons/icons/edit-copy.svg +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/src/icons/qbt-theme/build-icons/icons/edit-cut.svg b/src/icons/qbt-theme/build-icons/icons/edit-cut.svg deleted file mode 100644 index be1405700..000000000 --- a/src/icons/qbt-theme/build-icons/icons/edit-cut.svg +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/src/icons/qbt-theme/build-icons/icons/edit-delete.svg b/src/icons/qbt-theme/build-icons/icons/edit-delete.svg deleted file mode 100644 index 3c8870ed6..000000000 --- a/src/icons/qbt-theme/build-icons/icons/edit-delete.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - diff --git a/src/icons/qbt-theme/build-icons/icons/edit-find-user.svg b/src/icons/qbt-theme/build-icons/icons/edit-find-user.svg deleted file mode 100644 index 3f81a568e..000000000 --- a/src/icons/qbt-theme/build-icons/icons/edit-find-user.svg +++ /dev/null @@ -1,45 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/icons/qbt-theme/build-icons/icons/edit-find.svg b/src/icons/qbt-theme/build-icons/icons/edit-find.svg deleted file mode 100644 index a363d164e..000000000 --- a/src/icons/qbt-theme/build-icons/icons/edit-find.svg +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/src/icons/qbt-theme/build-icons/icons/edit-paste.svg b/src/icons/qbt-theme/build-icons/icons/edit-paste.svg deleted file mode 100644 index bc7a58d0e..000000000 --- a/src/icons/qbt-theme/build-icons/icons/edit-paste.svg +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/src/icons/qbt-theme/build-icons/icons/edit-rename.svg b/src/icons/qbt-theme/build-icons/icons/edit-rename.svg deleted file mode 100644 index 211f513db..000000000 --- a/src/icons/qbt-theme/build-icons/icons/edit-rename.svg +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/src/icons/qbt-theme/build-icons/icons/folder-documents.svg b/src/icons/qbt-theme/build-icons/icons/folder-documents.svg deleted file mode 100644 index 97399e432..000000000 --- a/src/icons/qbt-theme/build-icons/icons/folder-documents.svg +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/src/icons/qbt-theme/build-icons/icons/folder-download.svg b/src/icons/qbt-theme/build-icons/icons/folder-download.svg deleted file mode 100644 index f966e9921..000000000 --- a/src/icons/qbt-theme/build-icons/icons/folder-download.svg +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - diff --git a/src/icons/qbt-theme/build-icons/icons/folder-new.svg b/src/icons/qbt-theme/build-icons/icons/folder-new.svg deleted file mode 100644 index fb60f1191..000000000 --- a/src/icons/qbt-theme/build-icons/icons/folder-new.svg +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - - - - - - - - - - - - - - - diff --git a/src/icons/qbt-theme/build-icons/icons/folder-remote.svg b/src/icons/qbt-theme/build-icons/icons/folder-remote.svg deleted file mode 100644 index ba8832d41..000000000 --- a/src/icons/qbt-theme/build-icons/icons/folder-remote.svg +++ /dev/null @@ -1,141 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - diff --git a/src/icons/qbt-theme/build-icons/icons/gear.svg b/src/icons/qbt-theme/build-icons/icons/gear.svg deleted file mode 100644 index 604af0e8a..000000000 --- a/src/icons/qbt-theme/build-icons/icons/gear.svg +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/src/icons/qbt-theme/build-icons/icons/gear32.svg b/src/icons/qbt-theme/build-icons/icons/gear32.svg deleted file mode 100644 index 604af0e8a..000000000 --- a/src/icons/qbt-theme/build-icons/icons/gear32.svg +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/src/icons/qbt-theme/build-icons/icons/go-bottom.svg b/src/icons/qbt-theme/build-icons/icons/go-bottom.svg deleted file mode 100644 index 9ef856f24..000000000 --- a/src/icons/qbt-theme/build-icons/icons/go-bottom.svg +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - - - - - diff --git a/src/icons/qbt-theme/build-icons/icons/go-down.svg b/src/icons/qbt-theme/build-icons/icons/go-down.svg deleted file mode 100644 index 40c25ff9e..000000000 --- a/src/icons/qbt-theme/build-icons/icons/go-down.svg +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - - - - - diff --git a/src/icons/qbt-theme/build-icons/icons/go-top.svg b/src/icons/qbt-theme/build-icons/icons/go-top.svg deleted file mode 100644 index ccb01c5cb..000000000 --- a/src/icons/qbt-theme/build-icons/icons/go-top.svg +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - - - - - diff --git a/src/icons/qbt-theme/build-icons/icons/go-up.svg b/src/icons/qbt-theme/build-icons/icons/go-up.svg deleted file mode 100644 index e1d6dd9eb..000000000 --- a/src/icons/qbt-theme/build-icons/icons/go-up.svg +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - - - - - diff --git a/src/icons/qbt-theme/build-icons/icons/help-about.svg b/src/icons/qbt-theme/build-icons/icons/help-about.svg deleted file mode 100644 index afca90d12..000000000 --- a/src/icons/qbt-theme/build-icons/icons/help-about.svg +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - diff --git a/src/icons/qbt-theme/build-icons/icons/help-contents.svg b/src/icons/qbt-theme/build-icons/icons/help-contents.svg deleted file mode 100644 index 82273eb1b..000000000 --- a/src/icons/qbt-theme/build-icons/icons/help-contents.svg +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - - - - - - - diff --git a/src/icons/qbt-theme/build-icons/icons/inode-directory.svg b/src/icons/qbt-theme/build-icons/icons/inode-directory.svg deleted file mode 100644 index 97399e432..000000000 --- a/src/icons/qbt-theme/build-icons/icons/inode-directory.svg +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/src/icons/qbt-theme/build-icons/icons/insert-link.svg b/src/icons/qbt-theme/build-icons/icons/insert-link.svg deleted file mode 100644 index a69a53e9d..000000000 --- a/src/icons/qbt-theme/build-icons/icons/insert-link.svg +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/src/icons/qbt-theme/build-icons/icons/list-add.svg b/src/icons/qbt-theme/build-icons/icons/list-add.svg deleted file mode 100644 index 5b8c014a4..000000000 --- a/src/icons/qbt-theme/build-icons/icons/list-add.svg +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - - - - - - - diff --git a/src/icons/qbt-theme/build-icons/icons/list-remove.svg b/src/icons/qbt-theme/build-icons/icons/list-remove.svg deleted file mode 100644 index 22d9d8ccb..000000000 --- a/src/icons/qbt-theme/build-icons/icons/list-remove.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - diff --git a/src/icons/qbt-theme/build-icons/icons/mail-folder-inbox.svg b/src/icons/qbt-theme/build-icons/icons/mail-folder-inbox.svg deleted file mode 100644 index 3cde193bf..000000000 --- a/src/icons/qbt-theme/build-icons/icons/mail-folder-inbox.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - diff --git a/src/icons/qbt-theme/build-icons/icons/mail-mark-read.svg b/src/icons/qbt-theme/build-icons/icons/mail-mark-read.svg deleted file mode 100644 index 16bf991a4..000000000 --- a/src/icons/qbt-theme/build-icons/icons/mail-mark-read.svg +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - - - - diff --git a/src/icons/qbt-theme/build-icons/icons/media-playback-pause.svg b/src/icons/qbt-theme/build-icons/icons/media-playback-pause.svg deleted file mode 100644 index 79abdeeb4..000000000 --- a/src/icons/qbt-theme/build-icons/icons/media-playback-pause.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - diff --git a/src/icons/qbt-theme/build-icons/icons/media-playback-start.svg b/src/icons/qbt-theme/build-icons/icons/media-playback-start.svg deleted file mode 100644 index dca0dce51..000000000 --- a/src/icons/qbt-theme/build-icons/icons/media-playback-start.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - diff --git a/src/icons/qbt-theme/build-icons/icons/media-seek-forward.svg b/src/icons/qbt-theme/build-icons/icons/media-seek-forward.svg deleted file mode 100644 index b6ee66e0e..000000000 --- a/src/icons/qbt-theme/build-icons/icons/media-seek-forward.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - diff --git a/src/icons/qbt-theme/build-icons/icons/network-server.svg b/src/icons/qbt-theme/build-icons/icons/network-server.svg deleted file mode 100644 index c60c0f3f5..000000000 --- a/src/icons/qbt-theme/build-icons/icons/network-server.svg +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - - - diff --git a/src/icons/qbt-theme/build-icons/icons/network-wired.svg b/src/icons/qbt-theme/build-icons/icons/network-wired.svg deleted file mode 100644 index a6b10dc94..000000000 --- a/src/icons/qbt-theme/build-icons/icons/network-wired.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - diff --git a/src/icons/qbt-theme/build-icons/icons/object-locked.svg b/src/icons/qbt-theme/build-icons/icons/object-locked.svg deleted file mode 100644 index 238cb4428..000000000 --- a/src/icons/qbt-theme/build-icons/icons/object-locked.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - diff --git a/src/icons/qbt-theme/build-icons/icons/office-chart-line.svg b/src/icons/qbt-theme/build-icons/icons/office-chart-line.svg deleted file mode 100644 index 5cc04d176..000000000 --- a/src/icons/qbt-theme/build-icons/icons/office-chart-line.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - diff --git a/src/icons/qbt-theme/build-icons/icons/preferences-desktop.svg b/src/icons/qbt-theme/build-icons/icons/preferences-desktop.svg deleted file mode 100644 index e75e55c1b..000000000 --- a/src/icons/qbt-theme/build-icons/icons/preferences-desktop.svg +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - - - - diff --git a/src/icons/qbt-theme/build-icons/icons/preferences-other.svg b/src/icons/qbt-theme/build-icons/icons/preferences-other.svg deleted file mode 100644 index 06a5216ff..000000000 --- a/src/icons/qbt-theme/build-icons/icons/preferences-other.svg +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - - - diff --git a/src/icons/qbt-theme/build-icons/icons/preferences-system-network.svg b/src/icons/qbt-theme/build-icons/icons/preferences-system-network.svg deleted file mode 100644 index 41d096e91..000000000 --- a/src/icons/qbt-theme/build-icons/icons/preferences-system-network.svg +++ /dev/null @@ -1,85 +0,0 @@ - - - - - - - - - - - - diff --git a/src/icons/qbt-theme/build-icons/icons/preferences-web-browser-cookies.svg b/src/icons/qbt-theme/build-icons/icons/preferences-web-browser-cookies.svg deleted file mode 100644 index 91fe7a7b0..000000000 --- a/src/icons/qbt-theme/build-icons/icons/preferences-web-browser-cookies.svg +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - diff --git a/src/icons/qbt-theme/build-icons/icons/security-high.svg b/src/icons/qbt-theme/build-icons/icons/security-high.svg deleted file mode 100644 index 9be517104..000000000 --- a/src/icons/qbt-theme/build-icons/icons/security-high.svg +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - diff --git a/src/icons/qbt-theme/build-icons/icons/security-low.svg b/src/icons/qbt-theme/build-icons/icons/security-low.svg deleted file mode 100644 index b7a2ce9de..000000000 --- a/src/icons/qbt-theme/build-icons/icons/security-low.svg +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - - - - diff --git a/src/icons/qbt-theme/build-icons/icons/services.svg b/src/icons/qbt-theme/build-icons/icons/services.svg deleted file mode 100644 index a2eb8d5c0..000000000 --- a/src/icons/qbt-theme/build-icons/icons/services.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - diff --git a/src/icons/qbt-theme/build-icons/icons/speedometer.svg b/src/icons/qbt-theme/build-icons/icons/speedometer.svg deleted file mode 100644 index 9a94aa755..000000000 --- a/src/icons/qbt-theme/build-icons/icons/speedometer.svg +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - - diff --git a/src/icons/qbt-theme/build-icons/icons/system-log-out.svg b/src/icons/qbt-theme/build-icons/icons/system-log-out.svg deleted file mode 100644 index 6ac2a8c90..000000000 --- a/src/icons/qbt-theme/build-icons/icons/system-log-out.svg +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - diff --git a/src/icons/qbt-theme/build-icons/icons/tab-close.svg b/src/icons/qbt-theme/build-icons/icons/tab-close.svg deleted file mode 100644 index 3db7eb64b..000000000 --- a/src/icons/qbt-theme/build-icons/icons/tab-close.svg +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - - - diff --git a/src/icons/qbt-theme/build-icons/icons/task-attention.svg b/src/icons/qbt-theme/build-icons/icons/task-attention.svg deleted file mode 100644 index 01014b1e5..000000000 --- a/src/icons/qbt-theme/build-icons/icons/task-attention.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - diff --git a/src/icons/qbt-theme/build-icons/icons/text-plain.svg b/src/icons/qbt-theme/build-icons/icons/text-plain.svg deleted file mode 100644 index 57dc87def..000000000 --- a/src/icons/qbt-theme/build-icons/icons/text-plain.svg +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - diff --git a/src/icons/qbt-theme/build-icons/icons/tools-report-bug.svg b/src/icons/qbt-theme/build-icons/icons/tools-report-bug.svg deleted file mode 100644 index 0c1516db5..000000000 --- a/src/icons/qbt-theme/build-icons/icons/tools-report-bug.svg +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - diff --git a/src/icons/qbt-theme/build-icons/icons/unavailable.svg b/src/icons/qbt-theme/build-icons/icons/unavailable.svg deleted file mode 100644 index 663039c85..000000000 --- a/src/icons/qbt-theme/build-icons/icons/unavailable.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - diff --git a/src/icons/qbt-theme/build-icons/icons/user-group-delete.svg b/src/icons/qbt-theme/build-icons/icons/user-group-delete.svg deleted file mode 100644 index d9a1c5681..000000000 --- a/src/icons/qbt-theme/build-icons/icons/user-group-delete.svg +++ /dev/null @@ -1,35 +0,0 @@ - - - - - - - - - - - - - - - - - - diff --git a/src/icons/qbt-theme/build-icons/icons/user-group-new.svg b/src/icons/qbt-theme/build-icons/icons/user-group-new.svg deleted file mode 100644 index 60403eb15..000000000 --- a/src/icons/qbt-theme/build-icons/icons/user-group-new.svg +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - - - - - - - - - - diff --git a/src/icons/qbt-theme/build-icons/icons/view-calendar-journal.svg b/src/icons/qbt-theme/build-icons/icons/view-calendar-journal.svg deleted file mode 100644 index 6dd5ba32b..000000000 --- a/src/icons/qbt-theme/build-icons/icons/view-calendar-journal.svg +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - diff --git a/src/icons/qbt-theme/build-icons/icons/view-categories.svg b/src/icons/qbt-theme/build-icons/icons/view-categories.svg deleted file mode 100644 index 9e41051e6..000000000 --- a/src/icons/qbt-theme/build-icons/icons/view-categories.svg +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - - diff --git a/src/icons/qbt-theme/build-icons/icons/view-filter.svg b/src/icons/qbt-theme/build-icons/icons/view-filter.svg deleted file mode 100644 index 6f955cf6e..000000000 --- a/src/icons/qbt-theme/build-icons/icons/view-filter.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - diff --git a/src/icons/qbt-theme/build-icons/icons/view-preview.svg b/src/icons/qbt-theme/build-icons/icons/view-preview.svg deleted file mode 100644 index df9a46279..000000000 --- a/src/icons/qbt-theme/build-icons/icons/view-preview.svg +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - diff --git a/src/icons/qbt-theme/build-icons/icons/view-refresh.svg b/src/icons/qbt-theme/build-icons/icons/view-refresh.svg deleted file mode 100644 index 068181beb..000000000 --- a/src/icons/qbt-theme/build-icons/icons/view-refresh.svg +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - diff --git a/src/icons/qbt-theme/build-icons/icons/view-statistics.svg b/src/icons/qbt-theme/build-icons/icons/view-statistics.svg deleted file mode 100644 index 519722d9b..000000000 --- a/src/icons/qbt-theme/build-icons/icons/view-statistics.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - diff --git a/src/icons/qbt-theme/build-icons/icons/wallet-open.svg b/src/icons/qbt-theme/build-icons/icons/wallet-open.svg deleted file mode 100644 index 5c251ca9a..000000000 --- a/src/icons/qbt-theme/build-icons/icons/wallet-open.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - diff --git a/src/icons/qbt-theme/build-icons/icons/webui.svg b/src/icons/qbt-theme/build-icons/icons/webui.svg deleted file mode 100644 index 57cfd9775..000000000 --- a/src/icons/qbt-theme/build-icons/icons/webui.svg +++ /dev/null @@ -1,79 +0,0 @@ - - - - - - - - - - - - - - diff --git a/src/icons/qbt-theme/build-icons/package.json b/src/icons/qbt-theme/build-icons/package.json deleted file mode 100644 index c4e5b5ca3..000000000 --- a/src/icons/qbt-theme/build-icons/package.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "name": "build-icons", - "version": "1.0.0", - "description": "Convert svg icons to png", - "main": "index.js", - "dependencies": {}, - "devDependencies": { - "grunt": "^0.4.5", - "grunt-svg2png": "git+https://git@github.com/bertyhell/grunt-svg2png.git" - }, - "author": "Bert Verhelst", - "license": "ISC" -} diff --git a/src/icons/qbt-theme/build-icons/readme.md b/src/icons/qbt-theme/build-icons/readme.md deleted file mode 100644 index 97c3fd44f..000000000 --- a/src/icons/qbt-theme/build-icons/readme.md +++ /dev/null @@ -1,14 +0,0 @@ -Convert SVG icons to PNG ------------------------- - -install npm - -Execute: -``` -npm install -``` - -Convert icons by running: -``` -grunt -``` \ No newline at end of file diff --git a/src/icons/qbt-theme/checked.png b/src/icons/qbt-theme/checked.png deleted file mode 100644 index c9f5c5116..000000000 Binary files a/src/icons/qbt-theme/checked.png and /dev/null differ diff --git a/src/icons/qbt-theme/configure.png b/src/icons/qbt-theme/configure.png deleted file mode 100644 index 73ae91627..000000000 Binary files a/src/icons/qbt-theme/configure.png and /dev/null differ diff --git a/src/icons/qbt-theme/dialog-cancel.png b/src/icons/qbt-theme/dialog-cancel.png deleted file mode 100644 index 04acdc1a5..000000000 Binary files a/src/icons/qbt-theme/dialog-cancel.png and /dev/null differ diff --git a/src/icons/qbt-theme/dialog-information.png b/src/icons/qbt-theme/dialog-information.png deleted file mode 100644 index 3cd1f75ef..000000000 Binary files a/src/icons/qbt-theme/dialog-information.png and /dev/null differ diff --git a/src/icons/qbt-theme/dialog-warning.png b/src/icons/qbt-theme/dialog-warning.png deleted file mode 100644 index fff63bbb5..000000000 Binary files a/src/icons/qbt-theme/dialog-warning.png and /dev/null differ diff --git a/src/icons/qbt-theme/document-edit-verify.png b/src/icons/qbt-theme/document-edit-verify.png deleted file mode 100644 index 3caabaeda..000000000 Binary files a/src/icons/qbt-theme/document-edit-verify.png and /dev/null differ diff --git a/src/icons/qbt-theme/document-edit.png b/src/icons/qbt-theme/document-edit.png deleted file mode 100644 index 3db4c694c..000000000 Binary files a/src/icons/qbt-theme/document-edit.png and /dev/null differ diff --git a/src/icons/qbt-theme/document-encrypt.png b/src/icons/qbt-theme/document-encrypt.png deleted file mode 100644 index 0b861f187..000000000 Binary files a/src/icons/qbt-theme/document-encrypt.png and /dev/null differ diff --git a/src/icons/qbt-theme/document-import.png b/src/icons/qbt-theme/document-import.png deleted file mode 100644 index d51161ab5..000000000 Binary files a/src/icons/qbt-theme/document-import.png and /dev/null differ diff --git a/src/icons/qbt-theme/document-new.png b/src/icons/qbt-theme/document-new.png deleted file mode 100644 index ee4fe8c37..000000000 Binary files a/src/icons/qbt-theme/document-new.png and /dev/null differ diff --git a/src/icons/qbt-theme/document-properties.png b/src/icons/qbt-theme/document-properties.png deleted file mode 100644 index 4c531a664..000000000 Binary files a/src/icons/qbt-theme/document-properties.png and /dev/null differ diff --git a/src/icons/qbt-theme/document-save.png b/src/icons/qbt-theme/document-save.png deleted file mode 100644 index 9fb8b7278..000000000 Binary files a/src/icons/qbt-theme/document-save.png and /dev/null differ diff --git a/src/icons/qbt-theme/download.png b/src/icons/qbt-theme/download.png deleted file mode 100644 index 40c25f154..000000000 Binary files a/src/icons/qbt-theme/download.png and /dev/null differ diff --git a/src/icons/qbt-theme/edit-clear-history.png b/src/icons/qbt-theme/edit-clear-history.png deleted file mode 100644 index 8c2dcc045..000000000 Binary files a/src/icons/qbt-theme/edit-clear-history.png and /dev/null differ diff --git a/src/icons/qbt-theme/edit-clear.png b/src/icons/qbt-theme/edit-clear.png deleted file mode 100644 index 6adac3e2e..000000000 Binary files a/src/icons/qbt-theme/edit-clear.png and /dev/null differ diff --git a/src/icons/qbt-theme/edit-copy.png b/src/icons/qbt-theme/edit-copy.png deleted file mode 100644 index 790e2f231..000000000 Binary files a/src/icons/qbt-theme/edit-copy.png and /dev/null differ diff --git a/src/icons/qbt-theme/edit-cut.png b/src/icons/qbt-theme/edit-cut.png deleted file mode 100644 index cb76e59cf..000000000 Binary files a/src/icons/qbt-theme/edit-cut.png and /dev/null differ diff --git a/src/icons/qbt-theme/edit-delete.png b/src/icons/qbt-theme/edit-delete.png deleted file mode 100644 index 04e772ab6..000000000 Binary files a/src/icons/qbt-theme/edit-delete.png and /dev/null differ diff --git a/src/icons/qbt-theme/edit-find-user.png b/src/icons/qbt-theme/edit-find-user.png deleted file mode 100644 index 61b32d3ae..000000000 Binary files a/src/icons/qbt-theme/edit-find-user.png and /dev/null differ diff --git a/src/icons/qbt-theme/edit-find.png b/src/icons/qbt-theme/edit-find.png deleted file mode 100644 index 6ebf1a444..000000000 Binary files a/src/icons/qbt-theme/edit-find.png and /dev/null differ diff --git a/src/icons/qbt-theme/edit-paste.png b/src/icons/qbt-theme/edit-paste.png deleted file mode 100644 index c95c2fb98..000000000 Binary files a/src/icons/qbt-theme/edit-paste.png and /dev/null differ diff --git a/src/icons/qbt-theme/edit-rename.png b/src/icons/qbt-theme/edit-rename.png deleted file mode 100644 index 376c38df7..000000000 Binary files a/src/icons/qbt-theme/edit-rename.png and /dev/null differ diff --git a/src/icons/qbt-theme/folder-documents.png b/src/icons/qbt-theme/folder-documents.png deleted file mode 100644 index 35742e0f6..000000000 Binary files a/src/icons/qbt-theme/folder-documents.png and /dev/null differ diff --git a/src/icons/qbt-theme/folder-download.png b/src/icons/qbt-theme/folder-download.png deleted file mode 100644 index 40c25f154..000000000 Binary files a/src/icons/qbt-theme/folder-download.png and /dev/null differ diff --git a/src/icons/qbt-theme/folder-new.png b/src/icons/qbt-theme/folder-new.png deleted file mode 100644 index ae7657ef4..000000000 Binary files a/src/icons/qbt-theme/folder-new.png and /dev/null differ diff --git a/src/icons/qbt-theme/folder-remote.png b/src/icons/qbt-theme/folder-remote.png deleted file mode 100644 index cb3ff46c7..000000000 Binary files a/src/icons/qbt-theme/folder-remote.png and /dev/null differ diff --git a/src/icons/qbt-theme/gear.png b/src/icons/qbt-theme/gear.png deleted file mode 100644 index 73ae91627..000000000 Binary files a/src/icons/qbt-theme/gear.png and /dev/null differ diff --git a/src/icons/qbt-theme/gear32.png b/src/icons/qbt-theme/gear32.png deleted file mode 100644 index 73ae91627..000000000 Binary files a/src/icons/qbt-theme/gear32.png and /dev/null differ diff --git a/src/icons/qbt-theme/go-bottom.png b/src/icons/qbt-theme/go-bottom.png deleted file mode 100644 index 92a923c85..000000000 Binary files a/src/icons/qbt-theme/go-bottom.png and /dev/null differ diff --git a/src/icons/qbt-theme/go-down.png b/src/icons/qbt-theme/go-down.png deleted file mode 100644 index 2abdda81c..000000000 Binary files a/src/icons/qbt-theme/go-down.png and /dev/null differ diff --git a/src/icons/qbt-theme/go-top.png b/src/icons/qbt-theme/go-top.png deleted file mode 100644 index 079644c03..000000000 Binary files a/src/icons/qbt-theme/go-top.png and /dev/null differ diff --git a/src/icons/qbt-theme/go-up.png b/src/icons/qbt-theme/go-up.png deleted file mode 100644 index 80e7a7c52..000000000 Binary files a/src/icons/qbt-theme/go-up.png and /dev/null differ diff --git a/src/icons/qbt-theme/help-about.png b/src/icons/qbt-theme/help-about.png deleted file mode 100644 index 3cd1f75ef..000000000 Binary files a/src/icons/qbt-theme/help-about.png and /dev/null differ diff --git a/src/icons/qbt-theme/help-contents.png b/src/icons/qbt-theme/help-contents.png deleted file mode 100644 index 5f746d568..000000000 Binary files a/src/icons/qbt-theme/help-contents.png and /dev/null differ diff --git a/src/icons/qbt-theme/inode-directory.png b/src/icons/qbt-theme/inode-directory.png deleted file mode 100644 index 35742e0f6..000000000 Binary files a/src/icons/qbt-theme/inode-directory.png and /dev/null differ diff --git a/src/icons/qbt-theme/insert-link.png b/src/icons/qbt-theme/insert-link.png deleted file mode 100644 index 15ce0981d..000000000 Binary files a/src/icons/qbt-theme/insert-link.png and /dev/null differ diff --git a/src/icons/qbt-theme/kt-magnet.png b/src/icons/qbt-theme/kt-magnet.png deleted file mode 100644 index 3bab5e499..000000000 Binary files a/src/icons/qbt-theme/kt-magnet.png and /dev/null differ diff --git a/src/icons/qbt-theme/kt-set-max-download-speed.png b/src/icons/qbt-theme/kt-set-max-download-speed.png deleted file mode 100644 index a8c1dc3e5..000000000 Binary files a/src/icons/qbt-theme/kt-set-max-download-speed.png and /dev/null differ diff --git a/src/icons/qbt-theme/kt-set-max-upload-speed.png b/src/icons/qbt-theme/kt-set-max-upload-speed.png deleted file mode 100644 index 87ae05fa9..000000000 Binary files a/src/icons/qbt-theme/kt-set-max-upload-speed.png and /dev/null differ diff --git a/src/icons/qbt-theme/list-add.png b/src/icons/qbt-theme/list-add.png deleted file mode 100644 index ee4fe8c37..000000000 Binary files a/src/icons/qbt-theme/list-add.png and /dev/null differ diff --git a/src/icons/qbt-theme/list-remove.png b/src/icons/qbt-theme/list-remove.png deleted file mode 100644 index 2cc1c8f8c..000000000 Binary files a/src/icons/qbt-theme/list-remove.png and /dev/null differ diff --git a/src/icons/qbt-theme/mail-folder-inbox.png b/src/icons/qbt-theme/mail-folder-inbox.png deleted file mode 100644 index dc27dc2db..000000000 Binary files a/src/icons/qbt-theme/mail-folder-inbox.png and /dev/null differ diff --git a/src/icons/qbt-theme/mail-mark-read.png b/src/icons/qbt-theme/mail-mark-read.png deleted file mode 100644 index 2641ec4ec..000000000 Binary files a/src/icons/qbt-theme/mail-mark-read.png and /dev/null differ diff --git a/src/icons/qbt-theme/media-playback-pause.png b/src/icons/qbt-theme/media-playback-pause.png deleted file mode 100644 index 237f049f8..000000000 Binary files a/src/icons/qbt-theme/media-playback-pause.png and /dev/null differ diff --git a/src/icons/qbt-theme/media-playback-start.png b/src/icons/qbt-theme/media-playback-start.png deleted file mode 100644 index 4e36ee56a..000000000 Binary files a/src/icons/qbt-theme/media-playback-start.png and /dev/null differ diff --git a/src/icons/qbt-theme/media-seek-forward.png b/src/icons/qbt-theme/media-seek-forward.png deleted file mode 100644 index 225a48651..000000000 Binary files a/src/icons/qbt-theme/media-seek-forward.png and /dev/null differ diff --git a/src/icons/qbt-theme/network-server.png b/src/icons/qbt-theme/network-server.png deleted file mode 100644 index c5d98eec8..000000000 Binary files a/src/icons/qbt-theme/network-server.png and /dev/null differ diff --git a/src/icons/qbt-theme/network-wired.png b/src/icons/qbt-theme/network-wired.png deleted file mode 100644 index 6eef747ad..000000000 Binary files a/src/icons/qbt-theme/network-wired.png and /dev/null differ diff --git a/src/icons/qbt-theme/object-locked.png b/src/icons/qbt-theme/object-locked.png deleted file mode 100644 index 0b861f187..000000000 Binary files a/src/icons/qbt-theme/object-locked.png and /dev/null differ diff --git a/src/icons/qbt-theme/office-chart-line.png b/src/icons/qbt-theme/office-chart-line.png deleted file mode 100644 index acf4924c2..000000000 Binary files a/src/icons/qbt-theme/office-chart-line.png and /dev/null differ diff --git a/src/icons/qbt-theme/preferences-desktop.png b/src/icons/qbt-theme/preferences-desktop.png deleted file mode 100644 index b19dc0b2e..000000000 Binary files a/src/icons/qbt-theme/preferences-desktop.png and /dev/null differ diff --git a/src/icons/qbt-theme/preferences-other.png b/src/icons/qbt-theme/preferences-other.png deleted file mode 100644 index 4044871c8..000000000 Binary files a/src/icons/qbt-theme/preferences-other.png and /dev/null differ diff --git a/src/icons/qbt-theme/preferences-system-network.png b/src/icons/qbt-theme/preferences-system-network.png deleted file mode 100644 index c0c94c917..000000000 Binary files a/src/icons/qbt-theme/preferences-system-network.png and /dev/null differ diff --git a/src/icons/qbt-theme/preferences-web-browser-cookies.png b/src/icons/qbt-theme/preferences-web-browser-cookies.png deleted file mode 100644 index 0d22cf6f4..000000000 Binary files a/src/icons/qbt-theme/preferences-web-browser-cookies.png and /dev/null differ diff --git a/src/icons/qbt-theme/rss-config.png b/src/icons/qbt-theme/rss-config.png deleted file mode 100644 index 2d0117adc..000000000 Binary files a/src/icons/qbt-theme/rss-config.png and /dev/null differ diff --git a/src/icons/qbt-theme/security-high.png b/src/icons/qbt-theme/security-high.png deleted file mode 100644 index 8a1599303..000000000 Binary files a/src/icons/qbt-theme/security-high.png and /dev/null differ diff --git a/src/icons/qbt-theme/security-low.png b/src/icons/qbt-theme/security-low.png deleted file mode 100644 index b13b2f8af..000000000 Binary files a/src/icons/qbt-theme/security-low.png and /dev/null differ diff --git a/src/icons/qbt-theme/services.png b/src/icons/qbt-theme/services.png deleted file mode 100644 index b46ee826c..000000000 Binary files a/src/icons/qbt-theme/services.png and /dev/null differ diff --git a/src/icons/qbt-theme/speedometer.png b/src/icons/qbt-theme/speedometer.png deleted file mode 100644 index 2d2b99a62..000000000 Binary files a/src/icons/qbt-theme/speedometer.png and /dev/null differ diff --git a/src/icons/qbt-theme/system-log-out.png b/src/icons/qbt-theme/system-log-out.png deleted file mode 100644 index ae0a83435..000000000 Binary files a/src/icons/qbt-theme/system-log-out.png and /dev/null differ diff --git a/src/icons/qbt-theme/tab-close.png b/src/icons/qbt-theme/tab-close.png deleted file mode 100644 index cf9d4cf23..000000000 Binary files a/src/icons/qbt-theme/tab-close.png and /dev/null differ diff --git a/src/icons/qbt-theme/task-attention.png b/src/icons/qbt-theme/task-attention.png deleted file mode 100644 index fff63bbb5..000000000 Binary files a/src/icons/qbt-theme/task-attention.png and /dev/null differ diff --git a/src/icons/qbt-theme/task-complete.png b/src/icons/qbt-theme/task-complete.png deleted file mode 100644 index 5ea69d2dd..000000000 Binary files a/src/icons/qbt-theme/task-complete.png and /dev/null differ diff --git a/src/icons/qbt-theme/task-ongoing.png b/src/icons/qbt-theme/task-ongoing.png deleted file mode 100644 index de6a6fce4..000000000 Binary files a/src/icons/qbt-theme/task-ongoing.png and /dev/null differ diff --git a/src/icons/qbt-theme/task-reject.png b/src/icons/qbt-theme/task-reject.png deleted file mode 100644 index 9006b077d..000000000 Binary files a/src/icons/qbt-theme/task-reject.png and /dev/null differ diff --git a/src/icons/qbt-theme/text-plain.png b/src/icons/qbt-theme/text-plain.png deleted file mode 100644 index 5991a27bf..000000000 Binary files a/src/icons/qbt-theme/text-plain.png and /dev/null differ diff --git a/src/icons/qbt-theme/tools-report-bug.png b/src/icons/qbt-theme/tools-report-bug.png deleted file mode 100644 index 3bad8256d..000000000 Binary files a/src/icons/qbt-theme/tools-report-bug.png and /dev/null differ diff --git a/src/icons/qbt-theme/unavailable.png b/src/icons/qbt-theme/unavailable.png deleted file mode 100644 index 63df6ba41..000000000 Binary files a/src/icons/qbt-theme/unavailable.png and /dev/null differ diff --git a/src/icons/qbt-theme/user-group-delete.png b/src/icons/qbt-theme/user-group-delete.png deleted file mode 100644 index b9a24e5a9..000000000 Binary files a/src/icons/qbt-theme/user-group-delete.png and /dev/null differ diff --git a/src/icons/qbt-theme/user-group-new.png b/src/icons/qbt-theme/user-group-new.png deleted file mode 100644 index e87149d0c..000000000 Binary files a/src/icons/qbt-theme/user-group-new.png and /dev/null differ diff --git a/src/icons/qbt-theme/view-calendar-journal.png b/src/icons/qbt-theme/view-calendar-journal.png deleted file mode 100644 index 59c9f1d92..000000000 Binary files a/src/icons/qbt-theme/view-calendar-journal.png and /dev/null differ diff --git a/src/icons/qbt-theme/view-categories.png b/src/icons/qbt-theme/view-categories.png deleted file mode 100644 index 61ccee0a4..000000000 Binary files a/src/icons/qbt-theme/view-categories.png and /dev/null differ diff --git a/src/icons/qbt-theme/view-filter.png b/src/icons/qbt-theme/view-filter.png deleted file mode 100644 index 71b50b384..000000000 Binary files a/src/icons/qbt-theme/view-filter.png and /dev/null differ diff --git a/src/icons/qbt-theme/view-preview.png b/src/icons/qbt-theme/view-preview.png deleted file mode 100644 index 9a5b18b50..000000000 Binary files a/src/icons/qbt-theme/view-preview.png and /dev/null differ diff --git a/src/icons/qbt-theme/view-refresh.png b/src/icons/qbt-theme/view-refresh.png deleted file mode 100644 index 86d73796b..000000000 Binary files a/src/icons/qbt-theme/view-refresh.png and /dev/null differ diff --git a/src/icons/qbt-theme/view-statistics.png b/src/icons/qbt-theme/view-statistics.png deleted file mode 100644 index a976c0c69..000000000 Binary files a/src/icons/qbt-theme/view-statistics.png and /dev/null differ diff --git a/src/icons/qbt-theme/wallet-open.png b/src/icons/qbt-theme/wallet-open.png deleted file mode 100644 index a3d85bee7..000000000 Binary files a/src/icons/qbt-theme/wallet-open.png and /dev/null differ diff --git a/src/icons/qbt-theme/webui.png b/src/icons/qbt-theme/webui.png deleted file mode 100644 index 43f5a9cc0..000000000 Binary files a/src/icons/qbt-theme/webui.png and /dev/null differ diff --git a/src/icons/skin/arrow-right.gif b/src/icons/skin/arrow-right.gif deleted file mode 100644 index da97e6814..000000000 Binary files a/src/icons/skin/arrow-right.gif and /dev/null differ diff --git a/src/icons/skin/bg-dropdown.gif b/src/icons/skin/bg-dropdown.gif deleted file mode 100644 index b598f9dd0..000000000 Binary files a/src/icons/skin/bg-dropdown.gif and /dev/null differ diff --git a/src/icons/skin/bg-handle-horizontal.gif b/src/icons/skin/bg-handle-horizontal.gif deleted file mode 100644 index 27fd405ba..000000000 Binary files a/src/icons/skin/bg-handle-horizontal.gif and /dev/null differ diff --git a/src/icons/skin/bg-header.gif b/src/icons/skin/bg-header.gif deleted file mode 100644 index 6f44fb91f..000000000 Binary files a/src/icons/skin/bg-header.gif and /dev/null differ diff --git a/src/icons/skin/bg-panel-header.gif b/src/icons/skin/bg-panel-header.gif deleted file mode 100644 index ea746f0d2..000000000 Binary files a/src/icons/skin/bg-panel-header.gif and /dev/null differ diff --git a/src/icons/skin/build-icons/Gruntfile.js b/src/icons/skin/build-icons/Gruntfile.js deleted file mode 100644 index 2a88a4639..000000000 --- a/src/icons/skin/build-icons/Gruntfile.js +++ /dev/null @@ -1,22 +0,0 @@ -module.exports = function(grunt) { - - grunt.initConfig({ - svg2png: { - all: { - options:{ - size: 256 - }, - files: [ - { - src: ['icons/*.svg'] - } - ] - } - } - }); - - grunt.loadNpmTasks('grunt-svg2png'); - - grunt.registerTask('default', ['svg2png']); - -} \ No newline at end of file diff --git a/src/icons/skin/build-icons/icons/checking.svg b/src/icons/skin/build-icons/icons/checking.svg deleted file mode 100644 index 8304276ec..000000000 --- a/src/icons/skin/build-icons/icons/checking.svg +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/src/icons/skin/build-icons/icons/completed.svg b/src/icons/skin/build-icons/icons/completed.svg deleted file mode 100644 index 65cf0eba4..000000000 --- a/src/icons/skin/build-icons/icons/completed.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - diff --git a/src/icons/skin/build-icons/icons/connected.svg b/src/icons/skin/build-icons/icons/connected.svg deleted file mode 100644 index 8b1641bde..000000000 --- a/src/icons/skin/build-icons/icons/connected.svg +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - diff --git a/src/icons/skin/build-icons/icons/disconnected.svg b/src/icons/skin/build-icons/icons/disconnected.svg deleted file mode 100644 index 53122fb8c..000000000 --- a/src/icons/skin/build-icons/icons/disconnected.svg +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - diff --git a/src/icons/skin/build-icons/icons/download.svg b/src/icons/skin/build-icons/icons/download.svg deleted file mode 100644 index a26837b5f..000000000 --- a/src/icons/skin/build-icons/icons/download.svg +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - diff --git a/src/icons/skin/build-icons/icons/downloading.svg b/src/icons/skin/build-icons/icons/downloading.svg deleted file mode 100644 index 54ffa4443..000000000 --- a/src/icons/skin/build-icons/icons/downloading.svg +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - diff --git a/src/icons/skin/build-icons/icons/error.svg b/src/icons/skin/build-icons/icons/error.svg deleted file mode 100644 index 33f3b4f16..000000000 --- a/src/icons/skin/build-icons/icons/error.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - diff --git a/src/icons/skin/build-icons/icons/filteractive.svg b/src/icons/skin/build-icons/icons/filteractive.svg deleted file mode 100644 index 445b7a101..000000000 --- a/src/icons/skin/build-icons/icons/filteractive.svg +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - diff --git a/src/icons/skin/build-icons/icons/filterall.svg b/src/icons/skin/build-icons/icons/filterall.svg deleted file mode 100644 index b08fc342e..000000000 --- a/src/icons/skin/build-icons/icons/filterall.svg +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - diff --git a/src/icons/skin/build-icons/icons/filterinactive.svg b/src/icons/skin/build-icons/icons/filterinactive.svg deleted file mode 100644 index ee4bdce0c..000000000 --- a/src/icons/skin/build-icons/icons/filterinactive.svg +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - diff --git a/src/icons/skin/build-icons/icons/firewalled.svg b/src/icons/skin/build-icons/icons/firewalled.svg deleted file mode 100644 index ed4303dc6..000000000 --- a/src/icons/skin/build-icons/icons/firewalled.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - diff --git a/src/icons/skin/build-icons/icons/paused.svg b/src/icons/skin/build-icons/icons/paused.svg deleted file mode 100644 index 6255abf2e..000000000 --- a/src/icons/skin/build-icons/icons/paused.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - diff --git a/src/icons/skin/build-icons/icons/queued.svg b/src/icons/skin/build-icons/icons/queued.svg deleted file mode 100644 index 0823efb9d..000000000 --- a/src/icons/skin/build-icons/icons/queued.svg +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - diff --git a/src/icons/skin/build-icons/icons/ratio.svg b/src/icons/skin/build-icons/icons/ratio.svg deleted file mode 100644 index 6540ed24a..000000000 --- a/src/icons/skin/build-icons/icons/ratio.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - diff --git a/src/icons/skin/build-icons/icons/resumed.svg b/src/icons/skin/build-icons/icons/resumed.svg deleted file mode 100644 index ea37ade3a..000000000 --- a/src/icons/skin/build-icons/icons/resumed.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - diff --git a/src/icons/skin/build-icons/icons/seeding.svg b/src/icons/skin/build-icons/icons/seeding.svg deleted file mode 100644 index 31aff249d..000000000 --- a/src/icons/skin/build-icons/icons/seeding.svg +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - diff --git a/src/icons/skin/build-icons/icons/stalledDL.svg b/src/icons/skin/build-icons/icons/stalledDL.svg deleted file mode 100644 index 1886deb5b..000000000 --- a/src/icons/skin/build-icons/icons/stalledDL.svg +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - diff --git a/src/icons/skin/build-icons/icons/stalledUP.svg b/src/icons/skin/build-icons/icons/stalledUP.svg deleted file mode 100644 index 804804752..000000000 --- a/src/icons/skin/build-icons/icons/stalledUP.svg +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - diff --git a/src/icons/skin/build-icons/icons/uploading.svg b/src/icons/skin/build-icons/icons/uploading.svg deleted file mode 100644 index 731567cdb..000000000 --- a/src/icons/skin/build-icons/icons/uploading.svg +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - diff --git a/src/icons/skin/build-icons/package.json b/src/icons/skin/build-icons/package.json deleted file mode 100644 index c4e5b5ca3..000000000 --- a/src/icons/skin/build-icons/package.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "name": "build-icons", - "version": "1.0.0", - "description": "Convert svg icons to png", - "main": "index.js", - "dependencies": {}, - "devDependencies": { - "grunt": "^0.4.5", - "grunt-svg2png": "git+https://git@github.com/bertyhell/grunt-svg2png.git" - }, - "author": "Bert Verhelst", - "license": "ISC" -} diff --git a/src/icons/skin/build-icons/readme.md b/src/icons/skin/build-icons/readme.md deleted file mode 100644 index 97c3fd44f..000000000 --- a/src/icons/skin/build-icons/readme.md +++ /dev/null @@ -1,14 +0,0 @@ -Convert SVG icons to PNG ------------------------- - -install npm - -Execute: -``` -npm install -``` - -Convert icons by running: -``` -grunt -``` \ No newline at end of file diff --git a/src/icons/skin/checking.png b/src/icons/skin/checking.png deleted file mode 100644 index 2d55d7ffa..000000000 Binary files a/src/icons/skin/checking.png and /dev/null differ diff --git a/src/icons/skin/collapse-expand.gif b/src/icons/skin/collapse-expand.gif deleted file mode 100644 index 5833c0c67..000000000 Binary files a/src/icons/skin/collapse-expand.gif and /dev/null differ diff --git a/src/icons/skin/completed.png b/src/icons/skin/completed.png deleted file mode 100644 index 56849ca34..000000000 Binary files a/src/icons/skin/completed.png and /dev/null differ diff --git a/src/icons/skin/connected.png b/src/icons/skin/connected.png deleted file mode 100644 index 9aa01f12f..000000000 Binary files a/src/icons/skin/connected.png and /dev/null differ diff --git a/src/icons/skin/disconnected.png b/src/icons/skin/disconnected.png deleted file mode 100755 index 594166f1e..000000000 Binary files a/src/icons/skin/disconnected.png and /dev/null differ diff --git a/src/icons/skin/dock-tabs.gif b/src/icons/skin/dock-tabs.gif deleted file mode 100644 index c835fa9c6..000000000 Binary files a/src/icons/skin/dock-tabs.gif and /dev/null differ diff --git a/src/icons/skin/download.png b/src/icons/skin/download.png deleted file mode 100755 index e293a6905..000000000 Binary files a/src/icons/skin/download.png and /dev/null differ diff --git a/src/icons/skin/downloading.png b/src/icons/skin/downloading.png deleted file mode 100644 index 4e319f820..000000000 Binary files a/src/icons/skin/downloading.png and /dev/null differ diff --git a/src/icons/skin/error.png b/src/icons/skin/error.png deleted file mode 100644 index 709a490cc..000000000 Binary files a/src/icons/skin/error.png and /dev/null differ diff --git a/src/icons/skin/filteractive.png b/src/icons/skin/filteractive.png deleted file mode 100644 index 821777651..000000000 Binary files a/src/icons/skin/filteractive.png and /dev/null differ diff --git a/src/icons/skin/filterall.png b/src/icons/skin/filterall.png deleted file mode 100644 index 23146341a..000000000 Binary files a/src/icons/skin/filterall.png and /dev/null differ diff --git a/src/icons/skin/filterinactive.png b/src/icons/skin/filterinactive.png deleted file mode 100644 index 66346e510..000000000 Binary files a/src/icons/skin/filterinactive.png and /dev/null differ diff --git a/src/icons/skin/firewalled.png b/src/icons/skin/firewalled.png deleted file mode 100644 index 2e06623ec..000000000 Binary files a/src/icons/skin/firewalled.png and /dev/null differ diff --git a/src/icons/skin/handle-icon-horizontal.gif b/src/icons/skin/handle-icon-horizontal.gif deleted file mode 100644 index fb7dff199..000000000 Binary files a/src/icons/skin/handle-icon-horizontal.gif and /dev/null differ diff --git a/src/icons/skin/handle-icon.gif b/src/icons/skin/handle-icon.gif deleted file mode 100644 index 42412517c..000000000 Binary files a/src/icons/skin/handle-icon.gif and /dev/null differ diff --git a/src/icons/skin/knob.gif b/src/icons/skin/knob.gif deleted file mode 100644 index 755e06e0d..000000000 Binary files a/src/icons/skin/knob.gif and /dev/null differ diff --git a/src/icons/skin/logo-blank.gif b/src/icons/skin/logo-blank.gif deleted file mode 100644 index f5f8d7c1d..000000000 Binary files a/src/icons/skin/logo-blank.gif and /dev/null differ diff --git a/src/icons/skin/logo.gif b/src/icons/skin/logo.gif deleted file mode 100644 index 61c19e2a1..000000000 Binary files a/src/icons/skin/logo.gif and /dev/null differ diff --git a/src/icons/skin/logo2.gif b/src/icons/skin/logo2.gif deleted file mode 100644 index fce2ad80d..000000000 Binary files a/src/icons/skin/logo2.gif and /dev/null differ diff --git a/src/icons/skin/mascot.png b/src/icons/skin/mascot.png deleted file mode 100644 index 0d13b2576..000000000 Binary files a/src/icons/skin/mascot.png and /dev/null differ diff --git a/src/icons/skin/paused.png b/src/icons/skin/paused.png deleted file mode 100644 index a7949da5f..000000000 Binary files a/src/icons/skin/paused.png and /dev/null differ diff --git a/src/icons/skin/qbittorrent-tray-dark.svg b/src/icons/skin/qbittorrent-tray-dark.svg deleted file mode 100644 index 1c43bd2eb..000000000 --- a/src/icons/skin/qbittorrent-tray-dark.svg +++ /dev/null @@ -1,83 +0,0 @@ - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - diff --git a/src/icons/skin/qbittorrent-tray-light.svg b/src/icons/skin/qbittorrent-tray-light.svg deleted file mode 100644 index 5fab7a0bd..000000000 --- a/src/icons/skin/qbittorrent-tray-light.svg +++ /dev/null @@ -1,83 +0,0 @@ - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - diff --git a/src/icons/skin/qbittorrent16.png b/src/icons/skin/qbittorrent16.png deleted file mode 100644 index 765c83492..000000000 Binary files a/src/icons/skin/qbittorrent16.png and /dev/null differ diff --git a/src/icons/skin/qbittorrent22.png b/src/icons/skin/qbittorrent22.png deleted file mode 100644 index 2d99147b4..000000000 Binary files a/src/icons/skin/qbittorrent22.png and /dev/null differ diff --git a/src/icons/skin/qbittorrent32.png b/src/icons/skin/qbittorrent32.png deleted file mode 100644 index 2086b4343..000000000 Binary files a/src/icons/skin/qbittorrent32.png and /dev/null differ diff --git a/src/icons/skin/queued.png b/src/icons/skin/queued.png deleted file mode 100644 index ce1b9989e..000000000 Binary files a/src/icons/skin/queued.png and /dev/null differ diff --git a/src/icons/skin/ratio.png b/src/icons/skin/ratio.png deleted file mode 100644 index fa4a3c89e..000000000 Binary files a/src/icons/skin/ratio.png and /dev/null differ diff --git a/src/icons/skin/resumed.png b/src/icons/skin/resumed.png deleted file mode 100644 index be7111848..000000000 Binary files a/src/icons/skin/resumed.png and /dev/null differ diff --git a/src/icons/skin/seeding.png b/src/icons/skin/seeding.png deleted file mode 100644 index d76ca3b84..000000000 Binary files a/src/icons/skin/seeding.png and /dev/null differ diff --git a/src/icons/skin/slider-area.gif b/src/icons/skin/slider-area.gif deleted file mode 100644 index f22edcdfd..000000000 Binary files a/src/icons/skin/slider-area.gif and /dev/null differ diff --git a/src/icons/skin/spacer.gif b/src/icons/skin/spacer.gif deleted file mode 100644 index 099c95f3c..000000000 Binary files a/src/icons/skin/spacer.gif and /dev/null differ diff --git a/src/icons/skin/spinner-placeholder.gif b/src/icons/skin/spinner-placeholder.gif deleted file mode 100644 index ff0c3f1fe..000000000 Binary files a/src/icons/skin/spinner-placeholder.gif and /dev/null differ diff --git a/src/icons/skin/spinner.gif b/src/icons/skin/spinner.gif deleted file mode 100644 index 879316f75..000000000 Binary files a/src/icons/skin/spinner.gif and /dev/null differ diff --git a/src/icons/skin/splash.png b/src/icons/skin/splash.png deleted file mode 100644 index 8565f3175..000000000 Binary files a/src/icons/skin/splash.png and /dev/null differ diff --git a/src/icons/skin/stalledDL.png b/src/icons/skin/stalledDL.png deleted file mode 100644 index c35b5193a..000000000 Binary files a/src/icons/skin/stalledDL.png and /dev/null differ diff --git a/src/icons/skin/stalledUP.png b/src/icons/skin/stalledUP.png deleted file mode 100644 index 21df43efa..000000000 Binary files a/src/icons/skin/stalledUP.png and /dev/null differ diff --git a/src/icons/skin/tabs.gif b/src/icons/skin/tabs.gif deleted file mode 100644 index c8b5b0c64..000000000 Binary files a/src/icons/skin/tabs.gif and /dev/null differ diff --git a/src/icons/skin/toolbox-divider.gif b/src/icons/skin/toolbox-divider.gif deleted file mode 100644 index fb70d77bc..000000000 Binary files a/src/icons/skin/toolbox-divider.gif and /dev/null differ diff --git a/src/icons/skin/toolbox-divider2.gif b/src/icons/skin/toolbox-divider2.gif deleted file mode 100644 index bbb37c50b..000000000 Binary files a/src/icons/skin/toolbox-divider2.gif and /dev/null differ diff --git a/src/icons/skin/uploading.png b/src/icons/skin/uploading.png deleted file mode 100644 index 8e37968c7..000000000 Binary files a/src/icons/skin/uploading.png and /dev/null differ diff --git a/src/icons/slow.png b/src/icons/slow.png deleted file mode 100644 index 0d978fc70..000000000 Binary files a/src/icons/slow.png and /dev/null differ diff --git a/src/icons/slow_off.png b/src/icons/slow_off.png deleted file mode 100644 index 930663e78..000000000 Binary files a/src/icons/slow_off.png and /dev/null differ diff --git a/src/icons/sphere.png b/src/icons/sphere.png deleted file mode 100644 index 687be76de..000000000 Binary files a/src/icons/sphere.png and /dev/null differ diff --git a/src/icons/sphere2.png b/src/icons/sphere2.png deleted file mode 100644 index da431f16a..000000000 Binary files a/src/icons/sphere2.png and /dev/null differ diff --git a/src/icons/url.png b/src/icons/url.png deleted file mode 100644 index cc0930ff1..000000000 Binary files a/src/icons/url.png and /dev/null differ diff --git a/src/lang.qrc b/src/lang.qrc deleted file mode 100644 index 60002a62a..000000000 --- a/src/lang.qrc +++ /dev/null @@ -1,54 +0,0 @@ - - - lang/qbittorrent_ar.qm - lang/qbittorrent_be.qm - lang/qbittorrent_bg.qm - lang/qbittorrent_ca.qm - lang/qbittorrent_cs.qm - lang/qbittorrent_da.qm - lang/qbittorrent_de.qm - lang/qbittorrent_el.qm - lang/qbittorrent_en.qm - lang/qbittorrent_en_AU.qm - lang/qbittorrent_en_GB.qm - lang/qbittorrent_es.qm - lang/qbittorrent_eo.qm - lang/qbittorrent_eu.qm - lang/qbittorrent_fi.qm - lang/qbittorrent_fr.qm - lang/qbittorrent_gl.qm - lang/qbittorrent_he.qm - lang/qbittorrent_hi_IN.qm - lang/qbittorrent_hr.qm - lang/qbittorrent_hu.qm - lang/qbittorrent_hy.qm - lang/qbittorrent_id.qm - lang/qbittorrent_is.qm - lang/qbittorrent_it.qm - lang/qbittorrent_ja.qm - lang/qbittorrent_ka.qm - lang/qbittorrent_ko.qm - lang/qbittorrent_lv_LV.qm - lang/qbittorrent_lt.qm - lang/qbittorrent_ms_MY.qm - lang/qbittorrent_nb.qm - lang/qbittorrent_nl.qm - lang/qbittorrent_oc.qm - lang/qbittorrent_pl.qm - lang/qbittorrent_pt_PT.qm - lang/qbittorrent_pt_BR.qm - lang/qbittorrent_ro.qm - lang/qbittorrent_ru.qm - lang/qbittorrent_sk.qm - lang/qbittorrent_sl.qm - lang/qbittorrent_sr.qm - lang/qbittorrent_sv.qm - lang/qbittorrent_tr.qm - lang/qbittorrent_uk.qm - lang/qbittorrent_uz@Latn.qm - lang/qbittorrent_vi.qm - lang/qbittorrent_zh.qm - lang/qbittorrent_zh_TW.qm - lang/qbittorrent_zh_HK.qm - - diff --git a/src/lang/TRANSLATION_INSTRUCTIONS b/src/lang/TRANSLATION_INSTRUCTIONS deleted file mode 100644 index c2c951a0b..000000000 --- a/src/lang/TRANSLATION_INSTRUCTIONS +++ /dev/null @@ -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: -

-
- - -
- - - diff --git a/src/webui/www/public/about.html b/src/webui/www/public/about.html deleted file mode 100644 index e597f54d7..000000000 --- a/src/webui/www/public/about.html +++ /dev/null @@ -1,10 +0,0 @@ - -

qBittorrent ${VERSION} QBT_TR(Web UI)QBT_TR[CONTEXT=OptionsDialog]

-

QBT_TR(An advanced BitTorrent client programmed in C++, based on Qt toolkit and libtorrent-rasterbar.)QBT_TR[CONTEXT=about]

-

Copyright (c) 2011-2017 The qBittorrent project

-

QBT_TR(Home Page:)QBT_TR[CONTEXT=about] http://www.qbittorrent.org

-

QBT_TR(Bug Tracker:)QBT_TR[CONTEXT=about] http://bugs.qbittorrent.org

-

QBT_TR(Forum:)QBT_TR[CONTEXT=about] http://forum.qbittorrent.org

-

QBT_TR(IRC: #qbittorrent on Freenode)QBT_TR[CONTEXT=HttpServer]

-

QBT_TR(Original authors)QBT_TR[CONTEXT=HttpServer]

-Ishan Arora, Ankit Gupta, Chandan Shikhar Dua and Swapnil Kumar. diff --git a/src/webui/www/public/addtrackers.html b/src/webui/www/public/addtrackers.html deleted file mode 100644 index c816e3f4c..000000000 --- a/src/webui/www/public/addtrackers.html +++ /dev/null @@ -1,36 +0,0 @@ - - - - - QBT_TR(Trackers addition dialog)QBT_TR[CONTEXT=TrackersAdditionDlg] - - - - - - -
-
-

QBT_TR(List of trackers to add (one per line):)QBT_TR[CONTEXT=TrackersAdditionDlg]

- -
- -
- - diff --git a/src/webui/www/public/confirmdeletion.html b/src/webui/www/public/confirmdeletion.html deleted file mode 100644 index 4640b03aa..000000000 --- a/src/webui/www/public/confirmdeletion.html +++ /dev/null @@ -1,46 +0,0 @@ - - - - - QBT_TR(Deletion confirmation - qBittorrent)QBT_TR[CONTEXT=confirmDeletionDlg] - - - - - - -
- -

  QBT_TR(Are you sure you want to delete the selected torrents from the transfer list?)QBT_TR[CONTEXT=HttpServer]

-     

-
-      -
- - diff --git a/src/webui/www/public/css/Core.css b/src/webui/www/public/css/Core.css deleted file mode 100644 index ad380838e..000000000 --- a/src/webui/www/public/css/Core.css +++ /dev/null @@ -1,54 +0,0 @@ -/* - -Core.css for Mocha UI - -Theme: Default - -Copyright: - Copyright (c) 2007-2009 Greg Houston, . - -License: - MIT-style license. - -Notes: - CSS rules in this file: - - 1. Rules required by all MochaUI components or are shared by more than one. - 2. Theme specific adjustments to plugin styles. - 3. Miscellaneous rules that have no better place to go. - -*/ - -/* Required By All ----------------------------------------------------------------- */ - -/* Clears */ - -.clear { - clear: both; - height: 0; -} - -* html .clear { - font-size: 1px; - line-height: 1px; - overflow: hidden; - visibility: hidden; -} - -/* Miscellaneous ----------------------------------------------------------------- */ - -#themeControl { - margin-top: 2px; -} - - -/* Theme Specific Adjustments to Default Plugin Styles ----------------------------------------------------------------- */ - -/* Folder Tree */ - -.tree li a { - color: #3f3f3f !important; -} diff --git a/src/webui/www/public/css/Layout.css b/src/webui/www/public/css/Layout.css deleted file mode 100644 index 45fa6fda3..000000000 --- a/src/webui/www/public/css/Layout.css +++ /dev/null @@ -1,433 +0,0 @@ -/* - -Core.css for Mocha UI - -Theme: Default - -Copyright: - Copyright (c) 2007-2009 Greg Houston, . - -License: - MIT-style license. - -Required by: - Layout.js - -*/ - -/* Layout ----------------------------------------------------------------- */ - -html, body { - background: #fff; -} - -body { - margin: 0; /* Required */ -} - -#desktop { - position: relative; - min-width: 400px; /* Helps keep header content from wrapping */ - height: 100%; - min-height: 100%; - overflow: hidden; - cursor: default; /* Fix for issue in IE7. IE7 wants to use the I-bar text cursor */ -} - -#desktopHeader { - background: #f2f2f2; -} - -#desktopTitlebarWrapper { - position: relative; - height: 45px; - overflow: hidden; - background: #718BA6 url(../images/skin/bg-header.gif) repeat-x; -} - -#desktopTitlebar { - padding: 7px 8px 6px 8px; - height: 32px; - background: url(../images/skin/logo.gif) no-repeat; - background-position: left 0; -} - -#desktopTitlebar h1.applicationTitle { - display: none; - margin: 0; - padding: 0 5px 0 0; - font-size: 20px; - line-height: 25px; - font-weight: bold; - color: #fff; -} - -#desktopTitlebar h2.tagline { - padding: 7px 0 0 0; - font-family: Verdana, Arial, Helvetica, sans-serif; - font-size: 10px; - color: #d4dce4; - font-weight: bold; - text-align: center; - text-transform: uppercase; -} - -#desktopTitlebar h2.tagline .taglineEm { - color: #fff; - font-weight: bold; -} - -#topNav { - font-family: Verdana, Arial, Helvetica, sans-serif; - font-size: 10px; - position: absolute; - right: 0; - top: 0; - color: #d4dce4; - text-align: right; - padding: 13px 10px 0 0; -} - -#topNav a { - color: #fff; - font-weight: normal; -} - -#topNav a:hover { - text-decoration: none; -} - -/* Navbar */ - -#desktopNavbar { - background: #f2f2f2; - /*height: 30px;*/ - margin: 0 0px; - overflow: hidden; /* Remove this line if you want the menu to be backward compatible with Firefox 2 */ - /* Fixes by Chris */ - /*background-color: #ccc;*/ - height: 20px; - border-bottom: 1px solid #3f3f3f; -} - -#desktopNavbar ul { - padding: 0; - margin: 0; - list-style: none; - font-size: 12px; -} - -#desktopNavbar>ul>li { - float: left; -} - -#desktopNavbar a { - display: block; -} - -#desktopNavbar ul li a { - /*padding: 6px 10px 6px 10px;*/ - color: #333; - font-weight: normal; - /* Fix by Chris */ - padding: 2px 10px 6px 10px; -} - -#desktopNavbar ul li a:hover { - color: #333; - /* Fix By Chris */ - background-color: #fff; -} - -#desktopNavbar ul li a.arrow-right, #desktopNavbar ul li a:hover.arrow-right { - background-image: url(../images/skin/arrow-right.gif); - background-repeat: no-repeat; - background-position: right 7px; -} - -#desktopNavbar li ul { - border: 1px solid #3f3f3f; - background: #fff url(../images/skin/bg-dropdown.gif) repeat-y; - position: absolute; - left: -999em; - z-index: 8000; - /* Fix by Chris */ - margin-top: -6px; -} - -#desktopNavbar li:hover ul ul, -#desktopNavbar li.ieHover ul ul, -#desktopNavbar li:hover ul ul ul, -#desktopNavbar li.ieHover ul ul ul { - left: -999em; -} - -#desktopNavbar li ul ul { /* third-and-above-level lists */ - margin: -22px 0 0 163px; -} - -#desktopNavbar li ul li .check { - position: absolute; - top: 8px; - left: 6px; - width: 5px; - height: 5px; - background: #555; - overflow: hidden; - line-height: 1px; - font-size: 1px; -} - -#desktopNavbar li ul li a { - position: relative; - /*padding: 1px 9px 1px 25px;*/ - min-width: 120px; - color: #3f3f3f; - font-weight: normal; - /* Fix By Chris */ - padding: 1px 10px 1px 20px; /* Reduce left padding */ -} - -#desktopNavbar li ul li a:hover { - background: #6C98D9; - color: #fff; - -moz-border-radius: 2px; -} - -#desktopNavbar li ul li a:hover .check { - background: #fff; -} - -#desktopNavbar li:hover ul, -#desktopNavbar li.ieHover ul, -#desktopNavbar li li.ieHover ul, -#desktopNavbar li li li.ieHover ul, -#desktopNavbar li li:hover ul, -#desktopNavbar li li li:hover ul { /* lists nested under hovered list items */ - left: auto; -} - -#desktopNavbar li:hover { /* For IE7 */ - position: static; -} - -li.divider { - margin-top: 2px; - padding-top: 3px; - border-top: 1px solid #ebebeb; -} - -#pageWrapper { - position: relative; - overflow: hidden; /* This can be set to hidden or auto */ - border-top: 1px solid #909090; - border-bottom: 1px solid #909090; - /*height: 100%;*/ -} - -/* Footer */ - -#desktopFooterWrapper { - position: absolute; - left: 0; - bottom: 0; - width: 100%; - height: 30px; - overflow: hidden; -} - -#desktopFooter { - font-family: Verdana, Arial, Helvetica, sans-serif; - font-size: 11px; - height: 24px; - padding: 6px 8px 0 8px; - background: #f2f2f2; -} - - - -/* Panel Layout ----------------------------------------------------------------- */ - -/* Columns */ - -.column { - position: relative; - float: left; - overflow: hidden; /* Required by IE6 */ -} - -/* Panels */ - -.panel { - position: relative; - overflow: auto; - background: #f8f8f8; - border-bottom: 1px solid #b9b9b9; -} - -.panelWrapper.collapsed .panel-header { - border-bottom: 0; -} - -.panelAlt { - background: #f2f2f2; -} - -.bottomPanel { - border-bottom: 0; -} - -.pad { - padding: 8px; -} - -#mainPanel { - background: #fff; -} - -.panel-header { - position: relative; - background: #f1f1f1 url(../images/skin/bg-panel-header.gif) repeat-x; - height: 30px; - overflow: hidden; - border-bottom: 1px solid #d3d3d3; -} - -.panel-headerContent { - padding-top: 2px; -} - -.panel-headerContent.tabs { - background: url(../images/skin/tabs.gif) repeat-x; - background-position: left -68px; -} - -.panel-header h2 { - display: inline-block; - font-size: 12px; - margin: 0; - padding: 3px 8px 0 8px; - height: 22px; - overflow: hidden; - color: #333; -} - -.panel-collapse { - background: url(../images/skin/collapse-expand.gif) left top no-repeat; -} - -.panel-expand { - background: url(../images/skin/collapse-expand.gif) left -16px no-repeat; -} - -.icon16 { - margin: 4px 0 0 2px; - cursor: pointer; -} - -/* Column and Panel Handles */ - -.horizontalHandle { - height: 4px; - line-height: 1px; - font-size: 1px; - overflow: hidden; - background: #eee url(../images/skin/bg-handle-horizontal.gif) repeat-x; -} - -.horizontalHandle.detached .handleIcon { - background: transparent; -} - -.horizontalHandle .handleIcon { - margin: 0 auto; - height: 4px; - line-height: 1px; - font-size: 1px; - overflow: hidden; - background: url(../images/skin/handle-icon-horizontal.gif) center center no-repeat; -} - -.columnHandle { - min-height: 10px; - float: left; - width: 4px; - overflow: hidden; - background: #c3c3c3 url(../images/skin/handle-icon.gif) center center no-repeat; - border: 1px solid #909090; - border-top: 0; - border-bottom: 0; -} - -/* Toolboxes */ - -.toolbox { - float: right; - margin-top: 3px; - padding: 0 5px; - height: 24px; - overflow: hidden; - text-align: right; -} - -.panel-header-toolbox { -} - -div.toolbox.divider { /* Have to specify div here for IE6's sake */ - background: url(../images/skin/toolbox-divider.gif) repeat-y; - padding-left: 8px; -} - -.toolbox img.disabled { - cursor: default; -} - -.iconWrapper { - display: inline-block; - height: 22px; - min-width: 22px; - overflow: hidden; - border: 1px solid transparent; -} - -* html .iconWrapper { - padding: 1px; - border: 0; -} - -.iconWrapper img { - cursor: pointer; - margin: 0; - padding: 3px; -} - -.iconWrapper:hover { - border: 1px solid #a0a0a0; - -moz-border-radius: 3px; -} - -#spinnerWrapper { - width: 16px; - height: 16px; - background: url(../images/skin/spinner-placeholder.gif) no-repeat; - margin: 4px 5px 0 5px; -} - -#spinner { - display: none; - background: url(../images/skin/spinner.gif) no-repeat; - width: 16px; - height: 16px; -} - -#desktopFooter td { - vertical-align: top; - text-align: left; -} - -td.speedLabel { - cursor: pointer; - min-width: 18em; -} diff --git a/src/webui/www/public/css/Tabs.css b/src/webui/www/public/css/Tabs.css deleted file mode 100644 index 0672c4716..000000000 --- a/src/webui/www/public/css/Tabs.css +++ /dev/null @@ -1,66 +0,0 @@ -/* - -Tabs.css for Mocha UI - -Theme: Default - -Copyright: - Copyright (c) 2007-2009 Greg Houston, . - -License: - MIT-style license. - -Required by: - Tabs.js - -*/ - -/* Toolbar Tabs */ - -.toolbarTabs { - padding: 0 5px 2px 2px; - background: url(../images/skin/tabs.gif) repeat-x; - background-position: left -70px; - overflow: visible; -} - -.tab-menu { - padding-top: 1px; - list-style: none; - margin: 0; - padding: 0; - line-height: 16px; - font-size: 11px; -} - -.tab-menu li { - display: block; - float: left; - margin: 0 0 5px 0; - cursor: pointer; - background: url(../images/skin/tabs.gif) repeat-x; - background-position: left -35px; -} - -.tab-menu li.selected { - background: url(../images/skin/tabs.gif) repeat-x; - background-position: left 0; -} - -.tab-menu li a { - display: block; - margin-left: 8px; - padding: 6px 15px 5px 9px; - text-align: center; - font-weight: normal; - color: #181818; - background: url(../images/skin/tabs.gif) repeat-x; - background-position: right -35px; -} - -.tab-menu li.selected a { - color: #181818; - font-weight: bold; - background: url(../images/skin/tabs.gif) repeat-x; - background-position: right 0; -} diff --git a/src/webui/www/public/css/Window.css b/src/webui/www/public/css/Window.css deleted file mode 100644 index f774d6910..000000000 --- a/src/webui/www/public/css/Window.css +++ /dev/null @@ -1,378 +0,0 @@ -/* - -Window.css for Mocha UI - -Theme: Default - -Copyright: - Copyright (c) 2007-2009 Greg Houston, . - -License: - MIT-style license. - -Required by: - Window.js and Modal.css - -*/ - -/* Windows ----------------------------------------------------------------- */ - -.mocha { - display: none; - overflow: hidden; - background-color: #e5e5e5; -} - -.mocha.isFocused { -} - -.mochaOverlay { - position: absolute; /* This is also set in theme.js in order to make theme transitions smoother */ - top: 0; - left: 0; -} - -/* - - We get a little creative here in order to define a gradient in the CSS using a query - string appended to a background image. - - "from" is the top color of the gradient. "to" is the bottom color of the gradient. - - Both must be hex values without the leading # sign. - -*/ - -.mochaTitlebar { - width: 100%; - overflow: hidden; - background: url(../images/skin/spacer.gif?from=fafafa&to=e5e5e5); -} - -.mochaTitlebar h3 { - font-size: 12px; - line-height: 15px; - font-weight: bold; - margin: 0; - padding: 5px 10px 4px 12px; - color: #888; -} - -.mocha.isFocused .mochaTitlebar h3 { - color: #181818; -} - -.mochaToolbarWrapper { - width: 100%; /* For IE */ - position: relative; - height: 29px; - background: #f1f1f1; - overflow: hidden; - border-top: 1px solid #d9d9d9; -} - -div.mochaToolbarWrapper.bottom { - border: 0; - border-bottom: 1px solid #d9d9d9; -} - -.mochaToolbar { - width: 100%; /* For IE */ - border-top: 1px solid #fff; -} - -.mochaContentBorder { - border-top: 1px solid #dadada; - border-bottom: 1px solid #dadada; -} - -.mochaContentWrapper { /* Has a fixed height and scrollbars if required. */ - font-size: 12px; - overflow: auto; - background: #fff; -} - -.mochaContent { - padding: 10px 12px; -} - -.mocha .handle { - position: absolute; - background: #0f0; - width: 3px; - height: 3px; - z-index: 2; - -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=0)"; /* IE8 */ - filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=0); /* IE6 and 7*/ - opacity: .0; - -moz-opacity: .0; - overflow: hidden; - font-size: 1px; /* For IE6 */ -} - -.mocha .corner { /* Corner resize handles */ - width: 10px; - height: 10px; - background: #f00; -} - -.mocha .cornerSE { /* Bottom right resize handle */ - width: 20px; - height: 20px; - background: #fefefe; /* This is the color of the visible resize handle */ -} - -.mochaCanvasHeader { - position: absolute; - top: 0; - left: 0; - background: transparent; - z-index: -1; - visibility: hidden; - overflow: hidden; -} - -.mochaControls { - position: absolute; - width: 52px; - top: 8px; - right: 8px; - height: 14px; - z-index: 4; - background: transparent; -} - -.mochaCanvasControls { - position: absolute; - top: 8px; - right: 8px; - z-index: 3; - background: transparent; -} - -/* - To use images for these buttons: - 1. Set the useCanvasControls window option to false. - 2. If you use a different button size you may need to reposition the controls. - Modify the controlsOffset window option. - 2. Replcac the background-color with a background-image for each button. - -*/ -.mochaMinimizeButton, .mochaMaximizeButton, .mochaCloseButton { - float: right; - width: 14px; - height: 14px; - font-size: 1px; - cursor: pointer; - z-index: 4; - color: #666; - background-color: #fff; - margin-left: 5px; -} - -.mochaMinimizeButton { - margin-left: 0; -} - -.mochaMaximizeButton { -} - -.mochaCloseButton { -} - -.mochaSpinner{ - display: none; - position: absolute; - bottom: 7px; - left: 6px; - width: 16px; - height: 16px; - background: url(../images/skin/spinner.gif) no-repeat; -} - -.mochaIframe { - width: 100%; -} - -/* Fix for IE6 select z-index issue */ -.zIndexFix { - display: block; - position: absolute; - top: 0; - left: 0; - z-index: -1; - filter: mask(); - width: 100px; - height: 100px; - border: 1px solid transparent; -} - -/* Viewport overlays ----------------------------------------------------------------- */ - -#modalOverlay { - display: none; - position: fixed; - top: 0; - left: 0; - width: 100%; - background: #000; - -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=0)"; /* IE8 */ - filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=0); /* IE6 and 7*/ - opacity: 0; - -moz-opacity: 0; - z-index: 10000; -} - -/* Fix for IE6 select z-index issue */ -#modalFix { - display: none; - position: absolute; - top: 0; - left: 0; - width: 100%; - -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=0)"; /* IE8 */ - filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=0); /* IE6 and 7*/ - opacity: 0; - -moz-opacity: 0; - z-index: 9999; -} - -/* Underlay */ - -#windowUnderlay { - position: fixed; - top: 0; - left: 0; - width: 100%; - background: #fff; -} - -* html #windowUnderlay { - position: absolute; -} - -/* The replaced class is used internally when converting CSS values to Canvas. These classes should not be removed. */ - -.mocha.replaced, .mochaTitlebar.replaced, .mochaMinimizeButton.replaced, .mochaMaximizeButton.replaced, .mochaCloseButton.replaced { - background-color: transparent !important; -} - -.windowClosed { - visibility: hidden; - display: none; - position: absolute; - top: -20000px; - left: -20000px; - z-index: -1; - overflow: hidden; -} - -.windowClosed .mochaContentBorder, .windowClosed .mochaToolbarWrapper, .windowClosed .mochaTitlebar, .windowClosed .mochaControls, -.windowClosed .mochaCanvasControls { - position: absolute; - top: 0; - left: 0; - visibility: hidden; - display: none; - z-index: -1; -} - -/* Modals */ - -.modal2 { - border: 8px solid #fff; -} - -.modal2 .mochaContentBorder { - border-width: 0px; -} - -/* Window Themes */ - -.mocha.no-canvas { - background: #e5e5e5; - border: 1px solid #555; -} - -.mocha.no-canvas .mochaTitlebar { - background: #e5e5e5; -} - -.mocha.transparent .mochaTitlebar h3 { - color: #fff; - display: none; -} - -.mocha.transparent .mochaContentWrapper { - background: transparent; -} - -.mocha.notification { - background: #cedff2; -} - -.mocha.notification .mochaTitlebar { - -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=0)"; /* IE8 */ - filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=0); /* IE6 and 7*/ - opacity: .0; - -moz-opacity: 0; -} - -.mocha.notification .mochaContentBorder { - border-width: 0px; -} - -.mocha.notification .mochaContentWrapper { - text-align: center; - font-size: 12px; - font-weight: bold; - background: transparent; -} - -/* Example Window Themes */ - -#about_contentWrapper { - background: #e5e5e5 url(../images/skin/logo2.gif) 3px 3px no-repeat; -} - -#builder_contentWrapper { - background: #f5f5f7; -} - -#json01 .mochaTitlebar { - background: #6dd2db; -} - -#json02 .mochaTitlebar { - background: #6db6db; -} - -#json03 .mochaTitlebar { - background: #6d92db; -} - -.jsonExample .mochaTitlebar h3 { - color: #ddd; -} - -/* This does not work in IE6. */ -.isFocused.jsonExample .mochaTitlebar h3 { - color: #fff; -} - -#fxmorpherExample .mochaContentWrapper { - background: #577a9e; -} - -#clock { - background: #fff; -} - -/* Workaround to make invisible buttons clickable */ -.mochaMinimizeButton.replaced, -.mochaMaximizeButton.replaced, -.mochaCloseButton.replaced { - background-image: url(data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7) !important; -} \ No newline at end of file diff --git a/src/webui/www/public/css/dynamicTable.css b/src/webui/www/public/css/dynamicTable.css deleted file mode 100644 index 662ae1a4b..000000000 --- a/src/webui/www/public/css/dynamicTable.css +++ /dev/null @@ -1,94 +0,0 @@ - - -/************************************************************** - - Dynamic Table - v 0.4 - -**************************************************************/ -.dynamicTable tbody tr { - background-color: #fff; -} - -.dynamicTable tbody tr:nth-child(even), -.dynamicTable tbody tr.alt { - background-color: #eee; -} - -#transferList .dynamicTable td { - padding: 0 2px; -} - -.dynamicTable tbody tr.selected { - background-color: #354158; - color: #fff; -} - -.dynamicTable tbody tr:hover { - background-color: #ee6600; - color: #fff; -} - -#transferList tr:hover { - cursor: pointer; -} - -#transferList img.stateIcon { - height: 1.3em; - vertical-align: middle; - margin-bottom: -1px; -} - -tr.dynamicTableHeader { - cursor: pointer; -} - -.dynamicTable { - table-layout: fixed; - width :1%; - padding: 0; - border-spacing: 0; -} - -.dynamicTable th { - background-color: #eee; - padding: 4px; - white-space: nowrap; - border-right-color: #ccc; - border-right-style: solid; - border-right-width: 1px; - box-sizing: border-box; - -moz-box-sizing: border-box; - -webkit-box-sizing: border-box; -} - -.dynamicTable td { - padding:0px 4px; - white-space: nowrap; -} - -.dynamicTable thead tr { - background-color: #eee; -} - -.dynamicTable th, -.dynamicTable td { - text-overflow: ellipsis; - overflow: hidden; - white-space: nowrap; -} - -.dynamicTableFixedHeaderDiv { - overflow: hidden; -} - -.dynamicTableDiv { - overflow: auto; -} - -.dynamicTableDiv thead th { - line-height: 0px !important; - height: 0px !important; - padding-top: 0px !important; - padding-bottom: 0px !important; -} diff --git a/src/webui/www/public/css/style.css b/src/webui/www/public/css/style.css deleted file mode 100644 index f8c19ac85..000000000 --- a/src/webui/www/public/css/style.css +++ /dev/null @@ -1,481 +0,0 @@ -/* Reset */ - -/*ul,ol,dl,li,dt,dd,h1,h2,h3,h4,h5,h6,pre,form,body,html,p,blockquote,fieldset,input,object,iframe { margin: 0; padding: 0; }*/ -a img,:link img,:visited img { border: none; } -/*table { border-collapse: collapse; border-spacing: 0; }*/ -:focus { outline: none; } - -/* Structure */ - -body { - margin: 0; - text-align: left; - font-family: Arial, Helvetica, sans-serif; - font-size: 12px; - line-height: 18px; - color: #555; -} - -.aside { - width: 300px; -} - -.invisible { - display: none; -} - -/* Typography */ - -h2, h3, h4 { - margin: 0; - padding: 0 0 5px 0; - font-size: 12px; - font-weight: bold; - color: #333; -} - -h2 { - font-size: 14px; - color: #555; - font-weight: bold; -} - -#mochaPage h3 { - display: block; - font-size: 12px; - padding: 6px 0 6px 0; - margin: 0 0 8px 0; - border-bottom: 1px solid #bbb; -} - -#error_div { - color: #f00; - font-weight: bold; -} - -h4 { - font-size: 11px; -} - -a { - color: #e60; - text-decoration: none; - cursor: pointer; -} - -a:hover { - text-decoration: none; -} - -p { - margin: 0; - padding: 0 0 9px 0; -} - -/* List Elements */ - -ul { - list-style: outside; - margin: 0 0 9px 16px; -} - -dt { - font-weight: bold; -} - -dd { - padding: 0 0 9px 0; -} - -/* Code */ - -pre { - background-color: #f6f6f6; - color: #006600; - display: block; - font-family: 'Courier New', Courier, monospace; - font-size: 11px; - max-height: 250px; - overflow: auto; - margin: 0 0 10px 0; - padding: 10px; - border: 1px solid #d1d7dc; - } - -/* Dividers */ - -hr { - background-color: #ddd; - color: #ccc; - height: 1px; - border: 0px; -} - -.vcenter { - vertical-align: middle; -} - -#urls { - width:90%; - height:100%; -} - -#trackersUrls { - width:90%; - height:100%; -} - -#Filters ul { - list-style-type: none; -} - -#Filters ul li { - margin-left: -16px; -} - -#Filters ul img { - padding: 2px 4px; - vertical-align: middle; - width: 16px; - height: 16px; -} - -.selectedFilter { - background-color: #415A8D; - color: #FFFFFF; -} - -.selectedFilter a { - color: #FFFFFF; -} - -#properties { - background-color: #e5e5e5; -} - -a.propButton { - border: 1px solid rgb(85, 81, 91); - /*border-radius: 3px;*/ - padding: 2px; - margin-left: 3px; - margin-right: 3px; -} - -a.propButton img { - margin-bottom: -4px; -} - -.scrollableMenu { - overflow-y: auto; - overflow-x: hidden; -} - -/* context menu specific */ - -.contextMenu { border:1px solid #999; padding:0; background:#eee; list-style-type:none; display:none;} -.contextMenu .separator { border-top:1px solid #999; } -.contextMenu li { margin:0; padding:0;} -.contextMenu li a { - display: block; - padding: 5px 20px 5px 5px; - font-size: 12px; - text-decoration: none; - font-family: tahoma,arial,sans-serif; - color: #000; - white-space: nowrap; -} -.contextMenu li a:hover { background-color:#ddd; } -.contextMenu li a.disabled { color:#ccc; font-style:italic; } -.contextMenu li a.disabled:hover { background-color:#eee; } -.contextMenu li ul { - padding: 0; - border:1px solid #999; padding:0; background:#eee; - list-style-type:none; - position: absolute; - left: -999em; - z-index: 8000; - margin: -29px 0 0 100%; - width: 164px; -} -.contextMenu li ul li a { - position: relative; -} -.contextMenu li a.arrow-right, .contextMenu li a:hover.arrow-right { - background-image: url(../images/skin/arrow-right.gif); - background-repeat: no-repeat; - background-position: right center; -} -.contextMenu li:hover ul, -.contextMenu li.ieHover ul, -.contextMenu li li.ieHover ul, -.contextMenu li li li.ieHover ul, -.contextMenu li li:hover ul, -.contextMenu li li li:hover ul { /* lists nested under hovered list items */ - left: auto; -} - -.contextMenu li img { - width: 16px; - height: 16px; - margin-bottom: -4px; - -ms-interpolation-mode : bicubic; -} - -/* Sliders */ - -.slider { - clear: both; - position: relative; - font-size: 12px; - font-weight: bold; - width: 400px; - margin-bottom: 15px; -} - -.sliderWrapper { - position: relative; - font-size: 1px; - line-height: 1px; - height: 9px; - width: 422px; -} - -.sliderarea { - position: absolute; - top: 0; - left: 0; - height: 7px; - width: 420px; - font-size: 1px; - line-height: 1px; - background: #f2f2f2 url(../images/skin/slider-area.gif) repeat-x; - border: 1px solid #a3a3a3; - border-bottom: 1px solid #ccc; - border-left: 1px solid #ccc; - margin: 0; - padding: 0; - overflow: hidden; -} - -.sliderknob { - position: absolute; - top: 0; - left: 0; - height: 9px; - width: 19px; - font-size: 1px; - line-height: 1px; - background: url(../images/skin/knob.gif) no-repeat; - cursor: pointer; - overflow: hidden; - z-index: 2; -} - -.update { - padding-bottom: 5px; -} - -.mochaToolButton { - margin-right: 10px; -} - -/* Mocha Customization */ -#mochaToolbar { - margin-top: 5px; -} - -#mochaToolbar .divider { - background-image: url(../images/skin/toolbox-divider.gif); - background-repeat: no-repeat; - background-position: left center; - padding-left: 14px; - padding-top: 15px; -} - -.MyMenuIcon { - margin-left: -18px; - margin-bottom: -3px; - padding-right: 5px; -} - -/* Tri-state checkbox */ - -label.tristate { - background: url(../images/3-state-checkbox.gif) 0 0 no-repeat; - display: block; - float: left; - height: 13px; - margin: .15em 8px 5px 0px; - overflow: hidden; - text-indent: -999em; - width: 13px; -} - -label.checked { - background-position: 0 -13px; -} - -label.partial { - background-position: 0 -26px; -} - -fieldset.settings { - border: solid 1px black; - border-radius: 8px; - -webkit-border-radius: 8px; - -moz-border-radius: 8px; - padding: 4px 4px 4px 10px; -} - -fieldset.settings legend { - margin-left: 8px; - padding: 4px; - font-weight: bold; -} - -fieldset.settings label { - padding: 2px; -} - -fieldset.settings .leftLabelSmall { - width: 5em; - float: left; - text-align: right; - margin-right: 0.5em; - display: block; -} - -fieldset.settings .leftLabelLarge { - width: 14em; - float: left; - text-align: right; - margin-right: 0.5em; - display: block; -} - -div.formRow { - clear: left; - display: block; -} - -.filterTitle { - font-weight: bold; - text-transform: uppercase; - padding-left: 5px; -} - -ul.filterList { - margin: 0 0 0 16px; - padding-left: 0; -} - -ul.filterList a { - display: block; -} - -ul.filterList li:hover { - background-color: #e60; -} - -ul.filterList li:hover a { - color: white; -} - -td.generalLabel { - white-space: nowrap; - text-align: right; - width: 1px; - vertical-align: top; -} - -#filesTable { - line-height: 20px; -} - -#trackersTable, #webseedsTable { - line-height: 25px; -} - -#addTrackersPlus { - width: 16px; - cursor: pointer; - margin-bottom: -3px; -} - -.unselectable { - -webkit-touch-callout: none; - -webkit-user-select: none; - -khtml-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; -} - -#prop_general { - padding: 2px; -} - -#watched_folders_tab { - border-collapse: collapse; -} - -#watched_folders_tab td, #watched_folders_tab th { - padding: 2px 4px; - border: 1px solid black; -} - -.select-watched-folder-editable { - position:relative; - background-color: white; - border: solid grey 1px; - width: 160px; - height: 20px; -} - -.select-watched-folder-editable select { - position: absolute; - top: 0px; - bottom: 0px; - left: 0px; - border: none; - width: 160px; - margin: 0; -} - -.select-watched-folder-editable input { - position: absolute; - top: 0px; - left: 0px; - width: 140px; - padding: 1px; - border: none; -} - -.select-watched-folder-editable select:focus, .select-editable input:focus { - outline: none; -} - -/* - * Workaround to prevent the transfer list from - * disappearing when zooming in the browser. - */ -#filtersColumn_handle { - margin-left: -1px; -} - -#error_div { - float: left; - font-size: 14px; -} - -.combo_priority { - font-size: 1em; -} - -td.statusBarSeparator { - width: 22px; - background-image: url('../images/skin/toolbox-divider.gif'); - background-repeat: no-repeat; - background-position: center 1px; - background-size: 2px 18px; -} diff --git a/src/webui/www/public/download.html b/src/webui/www/public/download.html deleted file mode 100644 index 05fadbbdb..000000000 --- a/src/webui/www/public/download.html +++ /dev/null @@ -1,66 +0,0 @@ - - - - - QBT_TR(Add Torrent Links)QBT_TR[CONTEXT=downloadFromURL] - - - - - - - -
-
-
-

QBT_TR(Download Torrents from their URLs or Magnet links)QBT_TR[CONTEXT=HttpServer]

- -

QBT_TR(Only one link per line)QBT_TR[CONTEXT=HttpServer]

-
-
- - -
-
- - -
-
- - -
-
- - - -
-
- - -
-
- -
-
-
- -
- - diff --git a/src/webui/www/public/downloadlimit.html b/src/webui/www/public/downloadlimit.html deleted file mode 100644 index 0f8f55d91..000000000 --- a/src/webui/www/public/downloadlimit.html +++ /dev/null @@ -1,62 +0,0 @@ - - - - - QBT_TR(Torrent Download Speed Limiting)QBT_TR[CONTEXT=TransferListWidget] - - - - - - - -
-
-
QBT_TR(Download limit:)QBT_TR[CONTEXT=PropertiesWidget] QBT_TR(KiB/s)QBT_TR[CONTEXT=SpeedLimitDialog]
-
-
-
-
-
-
- - -
- - - - - diff --git a/src/webui/www/public/filters.html b/src/webui/www/public/filters.html deleted file mode 100644 index ea0d7fb2d..000000000 --- a/src/webui/www/public/filters.html +++ /dev/null @@ -1,50 +0,0 @@ -QBT_TR(Status)QBT_TR[CONTEXT=TransferListFiltersWidget] - -
-QBT_TR(Categories)QBT_TR[CONTEXT=TransferListFiltersWidget] -
    -
- - diff --git a/src/webui/www/public/newcategory.html b/src/webui/www/public/newcategory.html deleted file mode 100644 index 8e8eee583..000000000 --- a/src/webui/www/public/newcategory.html +++ /dev/null @@ -1,73 +0,0 @@ - - - - - QBT_TR(New Category)QBT_TR[CONTEXT=TransferListWidget] - - - - - - -
-

QBT_TR(Category)QBT_TR[CONTEXT=TransferListWidget]:

- -
- -
-
- - diff --git a/src/webui/www/public/preferences.html b/src/webui/www/public/preferences.html deleted file mode 100644 index e10e7ad29..000000000 --- a/src/webui/www/public/preferences.html +++ /dev/null @@ -1,51 +0,0 @@ - - - - - QBT_TR(Download from URLs)QBT_TR[CONTEXT=downloadFromURL] - - - - - - - - - - - - - diff --git a/src/webui/www/public/preferences_content.html b/src/webui/www/public/preferences_content.html deleted file mode 100644 index a9990eb6f..000000000 --- a/src/webui/www/public/preferences_content.html +++ /dev/null @@ -1,1375 +0,0 @@ -
-
- QBT_TR(Hard Disk)QBT_TR[CONTEXT=HttpServer] -
- - -
-
- - - -
- -
- - - -

- QBT_TR(Automatically add torrents from:)QBT_TR[CONTEXT=OptionsDialog]
- - - - - - - -
QBT_TR(Monitored Folder)QBT_TR[CONTEXT=ScanFoldersModel]QBT_TR(Override Save Location)QBT_TR[CONTEXT=ScanFoldersModel]
-
- - - Add -
-

- -    -
- -    -
-
- -
- - -
- -
-
- -
-
- -
-
- -
- -
-
- -
-
-
- -
- - -
- QBT_TR(Supported parameters (case sensitive):)QBT_TR[CONTEXT=OptionsDialog] -
    -
  • QBT_TR(%N: Torrent name)QBT_TR[CONTEXT=OptionsDialog]
  • -
  • QBT_TR(%L: Category)QBT_TR[CONTEXT=OptionsDialog]
  • -
  • QBT_TR(%F: Content path (same as root path for multifile torrent))QBT_TR[CONTEXT=OptionsDialog]
  • -
  • QBT_TR(%R: Root path (first torrent subdirectory path))QBT_TR[CONTEXT=OptionsDialog]
  • -
  • QBT_TR(%D: Save path)QBT_TR[CONTEXT=OptionsDialog]
  • -
  • QBT_TR(%C: Number of files)QBT_TR[CONTEXT=OptionsDialog]
  • -
  • QBT_TR(%Z: Torrent size (bytes))QBT_TR[CONTEXT=OptionsDialog]
  • -
  • QBT_TR(%T: Current tracker)QBT_TR[CONTEXT=OptionsDialog]
  • -
  • QBT_TR(%I: Info hash)QBT_TR[CONTEXT=OptionsDialog]
  • -
- QBT_TR(Tip: Encapsulate parameter with quotation marks to avoid text being cut off at whitespace (e.g., "%N"))QBT_TR[CONTEXT=OptionsDialog] -
-
-
- - - - - - - - - -
-
- - diff --git a/src/webui/www/public/properties.html b/src/webui/www/public/properties.html deleted file mode 100644 index 72c849496..000000000 --- a/src/webui/www/public/properties.html +++ /dev/null @@ -1,10 +0,0 @@ - diff --git a/src/webui/www/public/properties_content.html b/src/webui/www/public/properties_content.html deleted file mode 100644 index d54689ed7..000000000 --- a/src/webui/www/public/properties_content.html +++ /dev/null @@ -1,119 +0,0 @@ -
-
- QBT_TR(Transfer)QBT_TR[CONTEXT=PropertiesWidget] - - - - - - - - - - - - - - - - - - - - - - -
QBT_TR(Time Active:)QBT_TR[CONTEXT=PropertiesWidget]QBT_TR(ETA:)QBT_TR[CONTEXT=PropertiesWidget]QBT_TR(Connections:)QBT_TR[CONTEXT=PropertiesWidget]
QBT_TR(Downloaded:)QBT_TR[CONTEXT=PropertiesWidget]QBT_TR(Uploaded:)QBT_TR[CONTEXT=PropertiesWidget]QBT_TR(Seeds:)QBT_TR[CONTEXT=PropertiesWidget]
QBT_TR(Download Speed:)QBT_TR[CONTEXT=PropertiesWidget]QBT_TR(Upload Speed:)QBT_TR[CONTEXT=PropertiesWidget]QBT_TR(Peers:)QBT_TR[CONTEXT=PropertiesWidget]
QBT_TR(Download Limit:)QBT_TR[CONTEXT=PropertiesWidget]QBT_TR(Upload Limit:)QBT_TR[CONTEXT=PropertiesWidget]QBT_TR(Wasted:)QBT_TR[CONTEXT=PropertiesWidget]
QBT_TR(Share Ratio:)QBT_TR[CONTEXT=PropertiesWidget]QBT_TR(Reannounce In:)QBT_TR[CONTEXT=PropertiesWidget]QBT_TR(Last Seen Complete:)QBT_TR[CONTEXT=PropertiesWidget]
-
-
- QBT_TR(Information)QBT_TR[CONTEXT=PropertiesWidget] - - - - - - - - - - - - - - - - -
QBT_TR(Total Size:)QBT_TR[CONTEXT=PropertiesWidget]QBT_TR(Pieces:)QBT_TR[CONTEXT=PropertiesWidget]QBT_TR(Created By:)QBT_TR[CONTEXT=PropertiesWidget]
QBT_TR(Added On:)QBT_TR[CONTEXT=PropertiesWidget]QBT_TR(Completed On:)QBT_TR[CONTEXT=PropertiesWidget]QBT_TR(Created On:)QBT_TR[CONTEXT=PropertiesWidget]
QBT_TR(Torrent Hash:)QBT_TR[CONTEXT=PropertiesWidget]
QBT_TR(Save Path:)QBT_TR[CONTEXT=PropertiesWidget]
QBT_TR(Comment:)QBT_TR[CONTEXT=PropertiesWidget]
-
-
- - - - - - - - - - diff --git a/src/webui/www/public/scripts/client.js b/src/webui/www/public/scripts/client.js deleted file mode 100644 index c3acc5425..000000000 --- a/src/webui/www/public/scripts/client.js +++ /dev/null @@ -1,719 +0,0 @@ -/* - * MIT License - * Copyright (c) 2008 Ishan Arora , - * Christophe Dumez - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -torrentsTable = new TorrentsTable(); -torrentPeersTable = new TorrentPeersTable(); - -var updatePropertiesPanel = function () {}; - -var updateTorrentData = function () {}; -var updateTrackersData = function () {}; -var updateTorrentPeersData = function () {}; -var updateWebSeedsData = function () {}; -var updateTorrentFilesData = function () {}; - -var updateMainData = function () {}; -var alternativeSpeedLimits = false; -var queueing_enabled = true; -var syncMainDataTimerPeriod = 1500; - -var clipboardEvent; - -var CATEGORIES_ALL = 1; -var CATEGORIES_UNCATEGORIZED = 2; - -var category_list = {}; - -var selected_category = CATEGORIES_ALL; -var setCategoryFilter = function(){}; - -var selected_filter = getLocalStorageItem('selected_filter', 'all'); -var setFilter = function(){}; - -var loadSelectedCategory = function () { - selected_category = getLocalStorageItem('selected_category', CATEGORIES_ALL); -}; -loadSelectedCategory(); - -function genHash(string) { - var hash = 0; - for (var i = 0; i < string.length; i++) { - var c = string.charCodeAt(i); - hash = (c + hash * 31) | 0; - } - return hash; -} - -window.addEvent('load', function () { - - var saveColumnSizes = function () { - var filters_width = $('Filters').getSize().x; - var properties_height_rel = $('propertiesPanel').getSize().y / Window.getSize().y; - localStorage.setItem('filters_width', filters_width); - localStorage.setItem('properties_height_rel', properties_height_rel); - }; - - window.addEvent('resize', function() { - // Resizing might takes some time. - saveColumnSizes.delay(200); - }); - - /*MochaUI.Desktop = new MochaUI.Desktop(); - MochaUI.Desktop.desktop.setStyles({ - 'background': '#fff', - 'visibility': 'visible' - });*/ - MochaUI.Desktop.initialize(); - - var filt_w = localStorage.getItem('filters_width'); - if ($defined(filt_w)) - filt_w = filt_w.toInt(); - else - filt_w = 120; - new MochaUI.Column({ - id : 'filtersColumn', - placement : 'left', - onResize : saveColumnSizes, - width : filt_w, - resizeLimit : [100, 300] - }); - new MochaUI.Column({ - id : 'mainColumn', - placement : 'main', - width : null, - resizeLimit : [100, 300] - }); - - setCategoryFilter = function(hash) { - selected_category = hash; - localStorage.setItem('selected_category', selected_category); - highlightSelectedCategory(); - if (typeof torrentsTable.tableBody != 'undefined') - updateMainData(); - }; - - setFilter = function (f) { - // Visually Select the right filter - $("all_filter").removeClass("selectedFilter"); - $("downloading_filter").removeClass("selectedFilter"); - $("seeding_filter").removeClass("selectedFilter"); - $("completed_filter").removeClass("selectedFilter"); - $("paused_filter").removeClass("selectedFilter"); - $("resumed_filter").removeClass("selectedFilter"); - $("active_filter").removeClass("selectedFilter"); - $("inactive_filter").removeClass("selectedFilter"); - $("errored_filter").removeClass("selectedFilter"); - $(f + "_filter").addClass("selectedFilter"); - selected_filter = f; - localStorage.setItem('selected_filter', f); - // Reload torrents - if (typeof torrentsTable.tableBody != 'undefined') - updateMainData(); - }; - - new MochaUI.Panel({ - id : 'Filters', - title : 'Panel', - header : false, - padding : { - top : 0, - right : 0, - bottom : 0, - left : 0 - }, - loadMethod : 'xhr', - contentURL : 'filters.html', - onContentLoaded : function () { - setFilter(selected_filter); - }, - column : 'filtersColumn', - height : 300 - }); - initializeWindows(); - - // Show Top Toolbar is enabled by default - var showTopToolbar = true; - if (localStorage.getItem('show_top_toolbar') !== null) - showTopToolbar = localStorage.getItem('show_top_toolbar') == "true"; - if (!showTopToolbar) { - $('showTopToolbarLink').firstChild.style.opacity = '0'; - $('mochaToolbar').addClass('invisible'); - } - - var speedInTitle = localStorage.getItem('speed_in_browser_title_bar') == "true"; - if (!speedInTitle) - $('speedInBrowserTitleBarLink').firstChild.style.opacity = '0'; - - // After Show Top Toolbar - MochaUI.Desktop.setDesktopSize(); - - var syncMainDataLastResponseId = 0; - var serverState = {}; - - var removeTorrentFromCategoryList = function(hash) { - if (hash === null || hash === "") - return false; - var removed = false; - Object.each(category_list, function(category) { - if (Object.contains(category.torrents, hash)) { - removed = true; - category.torrents.splice(category.torrents.indexOf(hash), 1); - } - }); - return removed; - }; - - var addTorrentToCategoryList = function(torrent) { - var category = torrent['category']; - if (typeof category === 'undefined') - return false; - if (category.length === 0) { // Empty category - removeTorrentFromCategoryList(torrent['hash']); - return true; - } - var categoryHash = genHash(category); - if (category_list[categoryHash] === null) // This should not happen - category_list[categoryHash] = {name: category, torrents: []}; - if (!Object.contains(category_list[categoryHash].torrents, torrent['hash'])) { - removeTorrentFromCategoryList(torrent['hash']); - category_list[categoryHash].torrents = category_list[categoryHash].torrents.combine([torrent['hash']]); - return true; - } - return false; - }; - - var updateFilter = function(filter, filterTitle) { - $(filter + '_filter').firstChild.childNodes[1].nodeValue = filterTitle.replace('%1', torrentsTable.getFilteredTorrentsNumber(filter, CATEGORIES_ALL)); - }; - - var updateFiltersList = function() { - updateFilter('all', 'QBT_TR(All (%1))QBT_TR[CONTEXT=StatusFiltersWidget]'); - updateFilter('downloading', 'QBT_TR(Downloading (%1))QBT_TR[CONTEXT=StatusFiltersWidget]'); - updateFilter('seeding', 'QBT_TR(Seeding (%1))QBT_TR[CONTEXT=StatusFiltersWidget]'); - updateFilter('completed', 'QBT_TR(Completed (%1))QBT_TR[CONTEXT=StatusFiltersWidget]'); - updateFilter('resumed', 'QBT_TR(Resumed (%1))QBT_TR[CONTEXT=StatusFiltersWidget]'); - updateFilter('paused', 'QBT_TR(Paused (%1))QBT_TR[CONTEXT=StatusFiltersWidget]'); - updateFilter('active', 'QBT_TR(Active (%1))QBT_TR[CONTEXT=StatusFiltersWidget]'); - updateFilter('inactive', 'QBT_TR(Inactive (%1))QBT_TR[CONTEXT=StatusFiltersWidget]'); - updateFilter('errored', 'QBT_TR(Errored (%1))QBT_TR[CONTEXT=StatusFiltersWidget]'); - }; - - var updateCategoryList = function() { - var categoryList = $('filterCategoryList'); - if (!categoryList) - return; - categoryList.empty(); - - var create_link = function(hash, text, count) { - var html = '' + - '' + - escapeHtml(text) + ' (' + count + ')' + ''; - var el = new Element('li', {id: hash, html: html}); - categoriesFilterContextMenu.addTarget(el); - return el; - }; - - var all = torrentsTable.getRowIds().length; - var uncategorized = 0; - Object.each(torrentsTable.rows, function(row) { - if (row['full_data'].category.length === 0) - uncategorized += 1; - }); - categoryList.appendChild(create_link(CATEGORIES_ALL, 'QBT_TR(All)QBT_TR[CONTEXT=CategoryFilterModel]', all)); - categoryList.appendChild(create_link(CATEGORIES_UNCATEGORIZED, 'QBT_TR(Uncategorized)QBT_TR[CONTEXT=CategoryFilterModel]', uncategorized)); - - var sortedCategories = []; - Object.each(category_list, function(category) { - sortedCategories.push(category.name); - }); - sortedCategories.sort(); - - Object.each(sortedCategories, function(categoryName) { - var categoryHash = genHash(categoryName); - var categoryCount = category_list[categoryHash].torrents.length; - categoryList.appendChild(create_link(categoryHash, categoryName, categoryCount)); - }); - - highlightSelectedCategory(); - }; - - var highlightSelectedCategory = function() { - var categoryList = $('filterCategoryList'); - if (!categoryList) - return; - var childrens = categoryList.childNodes; - for (var i in childrens) { - if (childrens[i].id == selected_category) - childrens[i].className = "selectedFilter"; - else - childrens[i].className = ""; - } - }; - - var syncMainDataTimer; - var syncMainData = function () { - var url = new URI('sync/maindata'); - url.setData('rid', syncMainDataLastResponseId); - var request = new Request.JSON({ - url : url, - noCache : true, - method : 'get', - onFailure : function () { - $('error_div').set('html', 'QBT_TR(qBittorrent client is not reachable)QBT_TR[CONTEXT=HttpServer]'); - clearTimeout(syncMainDataTimer); - syncMainDataTimer = syncMainData.delay(2000); - }, - onSuccess : function (response) { - $('error_div').set('html', ''); - if (response) { - var update_categories = false; - var full_update = (response['full_update'] === true); - if (full_update) { - torrentsTable.clear(); - category_list = {}; - } - if (response['rid']) { - syncMainDataLastResponseId = response['rid']; - } - if (response['categories']) { - response['categories'].each(function(category) { - var categoryHash = genHash(category); - category_list[categoryHash] = {name: category, torrents: []}; - }); - update_categories = true; - } - if (response['categories_removed']) { - response['categories_removed'].each(function(category) { - var categoryHash = genHash(category); - delete category_list[categoryHash]; - }); - update_categories = true; - } - if (response['torrents']) { - var updateTorrentList = false; - for (var key in response['torrents']) { - response['torrents'][key]['hash'] = key; - response['torrents'][key]['rowId'] = key; - if (response['torrents'][key]['state']) - response['torrents'][key]['status'] = response['torrents'][key]['state']; - torrentsTable.updateRowData(response['torrents'][key]); - if (addTorrentToCategoryList(response['torrents'][key])) - update_categories = true; - if (response['torrents'][key]['name']) - updateTorrentList = true; - } - - if (updateTorrentList) - setupCopyEventHandler(); - } - if (response['torrents_removed']) - response['torrents_removed'].each(function (hash) { - torrentsTable.removeRow(hash); - removeTorrentFromCategoryList(hash); - update_categories = true; // Allways to update All category - }); - torrentsTable.updateTable(full_update); - torrentsTable.altRow(); - if (response['server_state']) { - var tmp = response['server_state']; - for(var k in tmp) - serverState[k] = tmp[k]; - processServerState(); - } - updateFiltersList(); - if (update_categories) { - updateCategoryList(); - torrentsTableContextMenu.updateCategoriesSubMenu(category_list); - } - } - clearTimeout(syncMainDataTimer); - syncMainDataTimer = syncMainData.delay(syncMainDataTimerPeriod); - } - }).send(); - }; - - updateMainData = function() { - torrentsTable.updateTable(); - clearTimeout(syncMainDataTimer); - syncMainDataTimer = syncMainData.delay(100); - }; - - var processServerState = function () { - var transfer_info = friendlyUnit(serverState.dl_info_speed, true); - if (serverState.dl_rate_limit > 0) - transfer_info += " [" + friendlyUnit(serverState.dl_rate_limit, true) + "]"; - transfer_info += " (" + friendlyUnit(serverState.dl_info_data, false) + ")"; - $("DlInfos").set('html', transfer_info); - transfer_info = friendlyUnit(serverState.up_info_speed, true); - if (serverState.up_rate_limit > 0) - transfer_info += " [" + friendlyUnit(serverState.up_rate_limit, true) + "]"; - transfer_info += " (" + friendlyUnit(serverState.up_info_data, false) + ")"; - $("UpInfos").set('html', transfer_info); - if (speedInTitle) { - document.title = "QBT_TR([D: %1, U: %2] qBittorrent %3)QBT_TR[CONTEXT=MainWindow]".replace("%1", friendlyUnit(serverState.dl_info_speed, true)).replace("%2", friendlyUnit(serverState.up_info_speed, true)).replace("%3", "${VERSION}"); - document.title += " QBT_TR(Web UI)QBT_TR[CONTEXT=OptionsDialog]"; - }else - document.title = "qBittorrent ${VERSION} QBT_TR(Web UI)QBT_TR[CONTEXT=OptionsDialog]"; - $('DHTNodes').set('html', 'QBT_TR(DHT: %1 nodes)QBT_TR[CONTEXT=StatusBar]'.replace("%1", serverState.dht_nodes)); - - // Statistics dialog - if (document.getElementById("statisticspage")) { - $('AlltimeDL').set('html', 'QBT_TR(Alltime download:)QBT_TR[CONTEXT=StatsDialog]' + " " + friendlyUnit(serverState.alltime_dl, false)); - $('AlltimeUL').set('html', 'QBT_TR(Alltime upload:)QBT_TR[CONTEXT=StatsDialog]' + " " + friendlyUnit(serverState.alltime_ul, false)); - $('TotalWastedSession').set('html', 'QBT_TR(Total wasted (this session):)QBT_TR[CONTEXT=StatsDialog]' + " " + friendlyUnit(serverState.total_wasted_session, false)); - $('GlobalRatio').set('html', 'QBT_TR(Global ratio:)QBT_TR[CONTEXT=StatsDialog]' + " " + serverState.global_ratio); - $('TotalPeerConnections').set('html', 'QBT_TR(Total peer connections:)QBT_TR[CONTEXT=StatsDialog]' + " " + serverState.total_peer_connections); - $('ReadCacheHits').set('html', 'QBT_TR(Read cache hits:)QBT_TR[CONTEXT=StatsDialog]' + " " + serverState.read_cache_hits); - $('TotalBuffersSize').set('html', 'QBT_TR(Total buffers size:)QBT_TR[CONTEXT=StatsDialog]' + " " + friendlyUnit(serverState.total_buffers_size, false)); - $('WriteCacheOverload').set('html', 'QBT_TR(Write cache overload:)QBT_TR[CONTEXT=StatsDialog]' + " " + serverState.write_cache_overload); - $('ReadCacheOverload').set('html', 'QBT_TR(Read cache overload:)QBT_TR[CONTEXT=StatsDialog]' + " " + serverState.read_cache_overload); - $('QueuedIOJobs').set('html', 'QBT_TR(Queued I/O jobs:)QBT_TR[CONTEXT=StatsDialog]' + " " + serverState.queued_io_jobs); - $('AverageTimeInQueue').set('html', 'QBT_TR(Average time in queue:)QBT_TR[CONTEXT=StatsDialog]' + " " + serverState.average_time_queue); - $('TotalQueuedSize').set('html', 'QBT_TR(Total queued size:)QBT_TR[CONTEXT=StatsDialog]' + " " + friendlyUnit(serverState.total_queued_size, false)); - } - - if (serverState.connection_status == "connected") - $('connectionStatus').src = 'images/skin/connected.png'; - else if (serverState.connection_status == "firewalled") - $('connectionStatus').src = 'images/skin/firewalled.png'; - else - $('connectionStatus').src = 'images/skin/disconnected.png'; - - if (queueing_enabled != serverState.queueing) { - queueing_enabled = serverState.queueing; - torrentsTable.columns['priority'].force_hide = !queueing_enabled; - torrentsTable.updateColumn('priority'); - if (queueing_enabled) { - $('queueingLinks').removeClass('invisible'); - $('queueingButtons').removeClass('invisible'); - $('queueingMenuItems').removeClass('invisible'); - } - else { - $('queueingLinks').addClass('invisible'); - $('queueingButtons').addClass('invisible'); - $('queueingMenuItems').addClass('invisible'); - } - } - - if (alternativeSpeedLimits != serverState.use_alt_speed_limits) { - alternativeSpeedLimits = serverState.use_alt_speed_limits; - updateAltSpeedIcon(alternativeSpeedLimits); - } - - syncMainDataTimerPeriod = serverState.refresh_interval; - if (syncMainDataTimerPeriod < 500) - syncMainDataTimerPeriod = 500; - }; - - var updateAltSpeedIcon = function(enabled) { - if (enabled) - $('alternativeSpeedLimits').src = "images/slow.png"; - else - $('alternativeSpeedLimits').src = "images/slow_off.png"; - }; - - $('alternativeSpeedLimits').addEvent('click', function() { - // Change icon immediately to give some feedback - updateAltSpeedIcon(!alternativeSpeedLimits); - - new Request({url: 'command/toggleAlternativeSpeedLimits', - method: 'post', - onComplete: function() { - alternativeSpeedLimits = !alternativeSpeedLimits; - updateMainData(); - }, - onFailure: function() { - // Restore icon in case of failure - updateAltSpeedIcon(alternativeSpeedLimits); - } - }).send(); - }); - - $('DlInfos').addEvent('click', globalDownloadLimitFN); - $('UpInfos').addEvent('click', globalUploadLimitFN); - - $('showTopToolbarLink').addEvent('click', function(e) { - showTopToolbar = !showTopToolbar; - localStorage.setItem('show_top_toolbar', showTopToolbar.toString()); - if (showTopToolbar) { - $('showTopToolbarLink').firstChild.style.opacity = '1'; - $('mochaToolbar').removeClass('invisible'); - } - else { - $('showTopToolbarLink').firstChild.style.opacity = '0'; - $('mochaToolbar').addClass('invisible'); - } - MochaUI.Desktop.setDesktopSize(); - }); - - $('speedInBrowserTitleBarLink').addEvent('click', function(e) { - speedInTitle = !speedInTitle; - localStorage.setItem('speed_in_browser_title_bar', speedInTitle.toString()); - if (speedInTitle) - $('speedInBrowserTitleBarLink').firstChild.style.opacity = '1'; - else - $('speedInBrowserTitleBarLink').firstChild.style.opacity = '0'; - processServerState(); - }); - - $('StatisticsLink').addEvent('click', StatisticsLinkFN); - - new MochaUI.Panel({ - id : 'transferList', - title : 'Panel', - header : false, - padding : { - top : 0, - right : 0, - bottom : 0, - left : 0 - }, - loadMethod : 'xhr', - contentURL : 'transferlist.html', - onContentLoaded : function () { - updateMainData(); - }, - column : 'mainColumn', - onResize : saveColumnSizes, - height : null - }); - var prop_h = localStorage.getItem('properties_height_rel'); - if ($defined(prop_h)) - prop_h = prop_h.toFloat() * Window.getSize().y; - else - prop_h = Window.getSize().y / 2.0; - new MochaUI.Panel({ - id : 'propertiesPanel', - title : 'Panel', - header : true, - padding : { - top : 0, - right : 0, - bottom : 0, - left : 0 - }, - contentURL : 'properties_content.html', - require : { - css : ['css/Tabs.css', 'css/dynamicTable.css'], - js : ['scripts/prop-general.js', 'scripts/prop-trackers.js', 'scripts/prop-webseeds.js', 'scripts/prop-files.js'], - }, - tabsURL : 'properties.html', - tabsOnload : function() { - MochaUI.initializeTabs('propertiesTabs'); - - updatePropertiesPanel = function() { - if (!$('prop_general').hasClass('invisible')) - updateTorrentData(); - else if (!$('prop_trackers').hasClass('invisible')) - updateTrackersData(); - else if (!$('prop_peers').hasClass('invisible')) - updateTorrentPeersData(); - else if (!$('prop_webseeds').hasClass('invisible')) - updateWebSeedsData(); - else if (!$('prop_files').hasClass('invisible')) - updateTorrentFilesData(); - }; - - $('PropGeneralLink').addEvent('click', function(e){ - $('prop_general').removeClass("invisible"); - $('prop_trackers').addClass("invisible"); - $('prop_webseeds').addClass("invisible"); - $('prop_files').addClass("invisible"); - $('prop_peers').addClass("invisible"); - updatePropertiesPanel(); - localStorage.setItem('selected_tab', this.id); - }); - - $('PropTrackersLink').addEvent('click', function(e){ - $('prop_trackers').removeClass("invisible"); - $('prop_general').addClass("invisible"); - $('prop_webseeds').addClass("invisible"); - $('prop_files').addClass("invisible"); - $('prop_peers').addClass("invisible"); - updatePropertiesPanel(); - localStorage.setItem('selected_tab', this.id); - }); - - $('PropPeersLink').addEvent('click', function(e){ - $('prop_peers').removeClass("invisible"); - $('prop_trackers').addClass("invisible"); - $('prop_general').addClass("invisible"); - $('prop_webseeds').addClass("invisible"); - $('prop_files').addClass("invisible"); - updatePropertiesPanel(); - localStorage.setItem('selected_tab', this.id); - }); - - $('PropWebSeedsLink').addEvent('click', function(e){ - $('prop_webseeds').removeClass("invisible"); - $('prop_general').addClass("invisible"); - $('prop_trackers').addClass("invisible"); - $('prop_files').addClass("invisible"); - $('prop_peers').addClass("invisible"); - updatePropertiesPanel(); - localStorage.setItem('selected_tab', this.id); - }); - - $('PropFilesLink').addEvent('click', function(e){ - $('prop_files').removeClass("invisible"); - $('prop_general').addClass("invisible"); - $('prop_trackers').addClass("invisible"); - $('prop_webseeds').addClass("invisible"); - $('prop_peers').addClass("invisible"); - updatePropertiesPanel(); - localStorage.setItem('selected_tab', this.id); - }); - - $('propertiesPanel_collapseToggle').addEvent('click', function(e){ - updatePropertiesPanel(); - }); - }, - column : 'mainColumn', - height : prop_h - }); -}); - -function closeWindows() { - MochaUI.closeAll(); -} - -function setupCopyEventHandler() { - if (clipboardEvent) - clipboardEvent.destroy(); - - clipboardEvent = new Clipboard('.copyToClipboard', { - text: function(trigger) { - var textToCopy; - - switch (trigger.id) { - case "CopyName": - textToCopy = copyNameFN(); - break; - case "CopyMagnetLink": - textToCopy = copyMagnetLinkFN(); - break; - case "CopyHash": - textToCopy = copyHashFN(); - break; - } - - return textToCopy; - } - }); -} - -var keyboardEvents = new Keyboard({ - defaultEventType: 'keydown', - events: { - 'ctrl+a': function(event) { - torrentsTable.selectAll(); - event.preventDefault(); - }, - 'delete': function(event) { - deleteFN(); - event.preventDefault(); - } - } -}); - -keyboardEvents.activate(); - -var loadTorrentPeersTimer; -var syncTorrentPeersLastResponseId = 0; -var show_flags = true; -var loadTorrentPeersData = function(){ - if ($('prop_peers').hasClass('invisible') || - $('propertiesPanel_collapseToggle').hasClass('panel-expand')) { - syncTorrentPeersLastResponseId = 0; - torrentPeersTable.clear(); - return; - } - var current_hash = torrentsTable.getCurrentTorrentHash(); - if (current_hash === "") { - syncTorrentPeersLastResponseId = 0; - torrentPeersTable.clear(); - clearTimeout(loadTorrentPeersTimer); - loadTorrentPeersTimer = loadTorrentPeersData.delay(syncMainDataTimerPeriod); - return; - } - var url = new URI('sync/torrent_peers'); - url.setData('rid', syncTorrentPeersLastResponseId); - url.setData('hash', current_hash); - var request = new Request.JSON({ - url: url, - noCache: true, - method: 'get', - onFailure: function() { - $('error_div').set('html', 'QBT_TR(qBittorrent client is not reachable)QBT_TR[CONTEXT=HttpServer]'); - clearTimeout(loadTorrentPeersTimer); - loadTorrentPeersTimer = loadTorrentPeersData.delay(5000); - }, - onSuccess: function(response) { - $('error_div').set('html', ''); - if (response) { - var full_update = (response['full_update'] === true); - if (full_update) { - torrentPeersTable.clear(); - } - if (response['rid']) { - syncTorrentPeersLastResponseId = response['rid']; - } - if (response['peers']) { - for (var key in response['peers']) { - response['peers'][key]['rowId'] = key; - - if (response['peers'][key]['client']) - response['peers'][key]['client'] = escapeHtml(response['peers'][key]['client']); - - torrentPeersTable.updateRowData(response['peers'][key]); - } - } - if (response['peers_removed']) - response['peers_removed'].each(function (hash) { - torrentPeersTable.removeRow(hash); - }); - torrentPeersTable.updateTable(full_update); - torrentPeersTable.altRow(); - - if (response['show_flags']) { - if (show_flags != response['show_flags']) { - show_flags = response['show_flags']; - torrentPeersTable.columns['country'].force_hide = !show_flags; - torrentPeersTable.updateColumn('country'); - } - } - } - else { - torrentPeersTable.clear(); - } - clearTimeout(loadTorrentPeersTimer); - loadTorrentPeersTimer = loadTorrentPeersData.delay(syncMainDataTimerPeriod); - } - }).send(); -}; - -updateTorrentPeersData = function(){ - clearTimeout(loadTorrentPeersTimer); - loadTorrentPeersData(); -}; diff --git a/src/webui/www/public/scripts/clipboard.min.js b/src/webui/www/public/scripts/clipboard.min.js deleted file mode 100644 index 90fd15b1c..000000000 --- a/src/webui/www/public/scripts/clipboard.min.js +++ /dev/null @@ -1,7 +0,0 @@ -/*! - * clipboard.js v1.7.1 - * https://zenorocha.github.io/clipboard.js - * - * Licensed MIT © Zeno Rocha - */ -!function(t){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=t();else if("function"==typeof define&&define.amd)define([],t);else{var e;e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this,e.Clipboard=t()}}(function(){var t,e,n;return function t(e,n,o){function i(a,c){if(!n[a]){if(!e[a]){var l="function"==typeof require&&require;if(!c&&l)return l(a,!0);if(r)return r(a,!0);var s=new Error("Cannot find module '"+a+"'");throw s.code="MODULE_NOT_FOUND",s}var u=n[a]={exports:{}};e[a][0].call(u.exports,function(t){var n=e[a][1][t];return i(n||t)},u,u.exports,t,e,n,o)}return n[a].exports}for(var r="function"==typeof require&&require,a=0;a0&&void 0!==arguments[0]?arguments[0]:{};this.action=e.action,this.container=e.container,this.emitter=e.emitter,this.target=e.target,this.text=e.text,this.trigger=e.trigger,this.selectedText=""}},{key:"initSelection",value:function t(){this.text?this.selectFake():this.target&&this.selectTarget()}},{key:"selectFake",value:function t(){var e=this,n="rtl"==document.documentElement.getAttribute("dir");this.removeFake(),this.fakeHandlerCallback=function(){return e.removeFake()},this.fakeHandler=this.container.addEventListener("click",this.fakeHandlerCallback)||!0,this.fakeElem=document.createElement("textarea"),this.fakeElem.style.fontSize="12pt",this.fakeElem.style.border="0",this.fakeElem.style.padding="0",this.fakeElem.style.margin="0",this.fakeElem.style.position="absolute",this.fakeElem.style[n?"right":"left"]="-9999px";var o=window.pageYOffset||document.documentElement.scrollTop;this.fakeElem.style.top=o+"px",this.fakeElem.setAttribute("readonly",""),this.fakeElem.value=this.text,this.container.appendChild(this.fakeElem),this.selectedText=(0,i.default)(this.fakeElem),this.copyText()}},{key:"removeFake",value:function t(){this.fakeHandler&&(this.container.removeEventListener("click",this.fakeHandlerCallback),this.fakeHandler=null,this.fakeHandlerCallback=null),this.fakeElem&&(this.container.removeChild(this.fakeElem),this.fakeElem=null)}},{key:"selectTarget",value:function t(){this.selectedText=(0,i.default)(this.target),this.copyText()}},{key:"copyText",value:function t(){var e=void 0;try{e=document.execCommand(this.action)}catch(t){e=!1}this.handleResult(e)}},{key:"handleResult",value:function t(e){this.emitter.emit(e?"success":"error",{action:this.action,text:this.selectedText,trigger:this.trigger,clearSelection:this.clearSelection.bind(this)})}},{key:"clearSelection",value:function t(){this.trigger&&this.trigger.focus(),window.getSelection().removeAllRanges()}},{key:"destroy",value:function t(){this.removeFake()}},{key:"action",set:function t(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"copy";if(this._action=e,"copy"!==this._action&&"cut"!==this._action)throw new Error('Invalid "action" value, use either "copy" or "cut"')},get:function t(){return this._action}},{key:"target",set:function t(e){if(void 0!==e){if(!e||"object"!==(void 0===e?"undefined":r(e))||1!==e.nodeType)throw new Error('Invalid "target" value, use a valid Element');if("copy"===this.action&&e.hasAttribute("disabled"))throw new Error('Invalid "target" attribute. Please use "readonly" instead of "disabled" attribute');if("cut"===this.action&&(e.hasAttribute("readonly")||e.hasAttribute("disabled")))throw new Error('Invalid "target" attribute. You can\'t cut text from elements with "readonly" or "disabled" attributes');this._target=e}},get:function t(){return this._target}}]),t}();t.exports=c})},{select:5}],8:[function(e,n,o){!function(i,r){if("function"==typeof t&&t.amd)t(["module","./clipboard-action","tiny-emitter","good-listener"],r);else if(void 0!==o)r(n,e("./clipboard-action"),e("tiny-emitter"),e("good-listener"));else{var a={exports:{}};r(a,i.clipboardAction,i.tinyEmitter,i.goodListener),i.clipboard=a.exports}}(this,function(t,e,n,o){"use strict";function i(t){return t&&t.__esModule?t:{default:t}}function r(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}function a(t,e){if(!t)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!e||"object"!=typeof e&&"function"!=typeof e?t:e}function c(t,e){if("function"!=typeof e&&null!==e)throw new TypeError("Super expression must either be null or a function, not "+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}function l(t,e){var n="data-clipboard-"+t;if(e.hasAttribute(n))return e.getAttribute(n)}var s=i(e),u=i(n),f=i(o),d="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},h=function(){function t(t,e){for(var n=0;n0&&void 0!==arguments[0]?arguments[0]:{};this.action="function"==typeof e.action?e.action:this.defaultAction,this.target="function"==typeof e.target?e.target:this.defaultTarget,this.text="function"==typeof e.text?e.text:this.defaultText,this.container="object"===d(e.container)?e.container:document.body}},{key:"listenClick",value:function t(e){var n=this;this.listener=(0,f.default)(e,"click",function(t){return n.onClick(t)})}},{key:"onClick",value:function t(e){var n=e.delegateTarget||e.currentTarget;this.clipboardAction&&(this.clipboardAction=null),this.clipboardAction=new s.default({action:this.action(n),target:this.target(n),text:this.text(n),container:this.container,trigger:n,emitter:this})}},{key:"defaultAction",value:function t(e){return l("action",e)}},{key:"defaultTarget",value:function t(e){var n=l("target",e);if(n)return document.querySelector(n)}},{key:"defaultText",value:function t(e){return l("text",e)}},{key:"destroy",value:function t(){this.listener.destroy(),this.clipboardAction&&(this.clipboardAction.destroy(),this.clipboardAction=null)}}],[{key:"isSupported",value:function t(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:["copy","cut"],n="string"==typeof e?[e]:e,o=!!document.queryCommandSupported;return n.forEach(function(t){o=o&&!!document.queryCommandSupported(t)}),o}}]),e}(u.default);t.exports=p})},{"./clipboard-action":7,"good-listener":4,"tiny-emitter":6}]},{},[8])(8)}); \ No newline at end of file diff --git a/src/webui/www/public/scripts/contextmenu.js b/src/webui/www/public/scripts/contextmenu.js deleted file mode 100644 index 10c67bc99..000000000 --- a/src/webui/www/public/scripts/contextmenu.js +++ /dev/null @@ -1,375 +0,0 @@ -var lastShownContexMenu = null; -var ContextMenu = new Class({ - //implements - Implements: [Options, Events], - - //options - options: { - actions: {}, - menu: 'menu_id', - stopEvent: true, - targets: 'body', - trigger: 'contextmenu', - offsets: { - x: 0, - y: 0 - }, - onShow: $empty, - onHide: $empty, - onClick: $empty, - fadeSpeed: 200 - }, - - //initialization - initialize: function(options) { - //set options - this.setOptions(options); - - //option diffs menu - this.menu = $(this.options.menu); - this.targets = $$(this.options.targets); - - //fx - this.fx = new Fx.Tween(this.menu, { - property: 'opacity', - duration: this.options.fadeSpeed, - onComplete: function() { - if (this.getStyle('opacity')) { - this.setStyle('visibility', 'visible'); - } - else { - this.setStyle('visibility', 'hidden'); - } - }.bind(this.menu) - }); - - //hide and begin the listener - this.hide().startListener(); - - //hide the menu - this.menu.setStyles({ - 'position': 'absolute', - 'top': '-900000px', - 'display': 'block' - }); - }, - - adjustMenuPosition: function(e) { - this.updateMenuItems(); - - var scrollableMenuMaxHeight = document.documentElement.clientHeight * 0.75; - - if (this.menu.hasClass('scrollableMenu')) - this.menu.setStyle('max-height', scrollableMenuMaxHeight); - - // draw the menu off-screen to know the menu dimentions - this.menu.setStyles({ - left: '-999em', - top: '-999em' - }); - - // position the menu - var xPosMenu = e.page.x + this.options.offsets.x; - var yPosMenu = e.page.y + this.options.offsets.y; - if (xPosMenu + this.menu.offsetWidth > document.documentElement.clientWidth) - xPosMenu -= this.menu.offsetWidth; - if (yPosMenu + this.menu.offsetHeight > document.documentElement.clientHeight) - yPosMenu = document.documentElement.clientHeight - this.menu.offsetHeight; - if (xPosMenu < 0) - xPosMenu = 0; - if (yPosMenu < 0) - yPosMenu = 0; - this.menu.setStyles({ - left: xPosMenu, - top: yPosMenu, - position: 'absolute', - 'z-index': '2000' - }); - - // position the sub-menu - var uls = this.menu.getElementsByTagName('ul'); - for (var i = 0; i < uls.length; i++) { - var ul = uls[i]; - if (ul.hasClass('scrollableMenu')) - ul.setStyle('max-height', scrollableMenuMaxHeight); - var rectParent = ul.parentNode.getBoundingClientRect(); - var xPosOrigin = rectParent.left; - var yPosOrigin = rectParent.bottom; - var xPos = xPosOrigin + rectParent.width - 1; - var yPos = yPosOrigin - rectParent.height - 1; - if (xPos + ul.offsetWidth > document.documentElement.clientWidth) - xPos -= (ul.offsetWidth + rectParent.width - 2); - if (yPos + ul.offsetHeight > document.documentElement.clientHeight) - yPos = document.documentElement.clientHeight - ul.offsetHeight; - if (xPos < 0) - xPos = 0; - if (yPos < 0) - yPos = 0; - ul.setStyles({ - 'margin-left': xPos - xPosOrigin, - 'margin-top': yPos - yPosOrigin - }); - } - }, - - addTarget: function(t) { - this.targets[this.targets.length] = t; - t.addEvent(this.options.trigger, function(e) { - //enabled? - if (!this.options.disabled) { - //prevent default, if told to - if (this.options.stopEvent) { - e.stop(); - } - //record this as the trigger - this.options.element = $(t); - this.adjustMenuPosition(e); - //show the menu - this.show(); - } - }.bind(this)); - t.addEvent('click', function(e) { - this.hide(); - }.bind(this)); - }, - - //get things started - startListener: function() { - /* all elements */ - this.targets.each(function(el) { - /* show the menu */ - el.addEvent(this.options.trigger, function(e) { - //enabled? - if (!this.options.disabled) { - //prevent default, if told to - if (this.options.stopEvent) { - e.stop(); - } - //record this as the trigger - this.options.element = $(el); - this.adjustMenuPosition(e); - //show the menu - this.show(); - } - }.bind(this)); - el.addEvent('click', function(e) { - this.hide(); - }.bind(this)); - }, this); - - /* menu items */ - this.menu.getElements('a').each(function(item) { - item.addEvent('click', function(e) { - e.preventDefault(); - if (!item.hasClass('disabled')) { - this.execute(item.get('href').split('#')[1], $(this.options.element)); - this.fireEvent('click', [item, e]); - } - }.bind(this)); - }, this); - - //hide on body click - $(document.body).addEvent('click', function() { - this.hide(); - }.bind(this)); - }, - - updateMenuItems: function () {}, - - //show menu - show: function (trigger) { - if (lastShownContexMenu && lastShownContexMenu != this) - lastShownContexMenu.hide(); - this.fx.start(1); - this.fireEvent('show'); - this.shown = true; - lastShownContexMenu = this; - return this; - }, - - //hide the menu - hide: function (trigger) { - if (this.shown) { - this.fx.start(0); - //this.menu.fade('out'); - this.fireEvent('hide'); - this.shown = false; - } - return this; - }, - - setItemChecked: function (item, checked) { - this.menu.getElement('a[href$=' + item + ']').firstChild.style.opacity = - checked ? '1' : '0'; - return this; - }, - - getItemChecked: function (item) { - return '0' != this.menu.getElement('a[href$=' + item + ']').firstChild.style.opacity; - }, - - //hide an item - hideItem: function (item) { - this.menu.getElement('a[href$=' + item + ']').parentNode.addClass('invisible'); - return this; - }, - - //show an item - showItem: function (item) { - this.menu.getElement('a[href$=' + item + ']').parentNode.removeClass('invisible'); - return this; - }, - - //disable the entire menu - disable: function () { - this.options.disabled = true; - return this; - }, - - //enable the entire menu - enable: function () { - this.options.disabled = false; - return this; - }, - - //execute an action - execute: function (action, element) { - if (this.options.actions[action]) { - this.options.actions[action](element, this, action); - } - return this; - } -}); - -var TorrentsTableContextMenu = new Class({ - Extends: ContextMenu, - - updateMenuItems: function () { - all_are_seq_dl = true; - there_are_seq_dl = false; - all_are_f_l_piece_prio = true; - there_are_f_l_piece_prio = false; - all_are_downloaded = true; - all_are_paused = true; - there_are_paused = false; - all_are_force_start = true; - there_are_force_start = false; - all_are_super_seeding = true; - - var h = torrentsTable.selectedRowsIds(); - h.each(function(item, index){ - var data = torrentsTable.rows.get(item).full_data; - - if (data['seq_dl'] !== true) - all_are_seq_dl = false; - else - there_are_seq_dl = true; - - if (data['f_l_piece_prio'] !== true) - all_are_f_l_piece_prio = false; - else - there_are_f_l_piece_prio = true; - - if (data['progress'] != 1.0) // not downloaded - all_are_downloaded = false; - else if (data['super_seeding'] !== true) - all_are_super_seeding = false; - - if (data['state'] != 'pausedUP' && data['state'] != 'pausedDL') - all_are_paused = false; - else - there_are_paused = true; - - if (data['force_start'] !== true) - all_are_force_start = false; - else - there_are_force_start = true; - }); - - show_seq_dl = true; - - if (!all_are_seq_dl && there_are_seq_dl) - show_seq_dl = false; - - show_f_l_piece_prio = true; - - if (!all_are_f_l_piece_prio && there_are_f_l_piece_prio) - show_f_l_piece_prio = false; - - if (all_are_downloaded) { - this.hideItem('DownloadLimit'); - this.menu.getElement('a[href$=UploadLimit]').parentNode.addClass('separator'); - this.hideItem('SequentialDownload'); - this.hideItem('FirstLastPiecePrio'); - this.showItem('SuperSeeding'); - this.setItemChecked('SuperSeeding', all_are_super_seeding); - } else { - if (!show_seq_dl && show_f_l_piece_prio) - this.menu.getElement('a[href$=FirstLastPiecePrio]').parentNode.addClass('separator'); - else - this.menu.getElement('a[href$=FirstLastPiecePrio]').parentNode.removeClass('separator'); - - if (show_seq_dl) - this.showItem('SequentialDownload'); - else - this.hideItem('SequentialDownload'); - - if (show_f_l_piece_prio) - this.showItem('FirstLastPiecePrio'); - else - this.hideItem('FirstLastPiecePrio'); - - this.setItemChecked('SequentialDownload', all_are_seq_dl); - this.setItemChecked('FirstLastPiecePrio', all_are_f_l_piece_prio); - - this.showItem('DownloadLimit'); - this.menu.getElement('a[href$=UploadLimit]').parentNode.removeClass('separator'); - this.hideItem('SuperSeeding'); - } - - this.showItem('Start'); - this.showItem('Pause'); - this.showItem('ForceStart'); - if (all_are_paused) - this.hideItem('Pause'); - else if (all_are_force_start) - this.hideItem('ForceStart'); - else if (!there_are_paused && !there_are_force_start) - this.hideItem('Start'); - }, - - updateCategoriesSubMenu : function (category_list) { - var categoryList = $('contextCategoryList'); - categoryList.empty(); - categoryList.appendChild(new Element('li', {html: 'QBT_TR(New...)QBT_TR[CONTEXT=TransferListWidget] QBT_TR(New...)QBT_TR[CONTEXT=TransferListWidget]'})); - categoryList.appendChild(new Element('li', {html: 'QBT_TR(Reset)QBT_TR[CONTEXT=TransferListWidget] QBT_TR(Reset)QBT_TR[CONTEXT=TransferListWidget]'})); - - var sortedCategories = []; - Object.each(category_list, function (category) { - sortedCategories.push(category.name); - }); - sortedCategories.sort(); - - var first = true; - Object.each(sortedCategories, function (categoryName) { - var categoryHash = genHash(categoryName); - var el = new Element('li', {html: ' ' + escapeHtml(categoryName) + ''}); - if (first) { - el.addClass('separator'); - first = false; - } - categoryList.appendChild(el); - }); - } -}); - -var CategoriesFilterContextMenu = new Class({ - Extends: ContextMenu, - updateMenuItems: function () { - var id = this.options.element.id; - if (id != CATEGORIES_ALL && id != CATEGORIES_UNCATEGORIZED) - this.showItem('DeleteCategory'); - else - this.hideItem('DeleteCategory'); - } -}); diff --git a/src/webui/www/public/scripts/download.js b/src/webui/www/public/scripts/download.js deleted file mode 100644 index 6ca0ce1c8..000000000 --- a/src/webui/www/public/scripts/download.js +++ /dev/null @@ -1,42 +0,0 @@ -/* - * MIT License - * Copyright (c) 2008 Ishan Arora - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -getSavePath = function() { - var req = new Request({ - url: 'command/getSavePath', - method: 'get', - noCache: true, - onFailure: function() { - alert("Could not contact qBittorrent"); - }, - onSuccess: function(data) { - if (data) { - $('savepath').setProperty('value', data); - } - } - }).send(); -}; - -$(window).addEventListener("load", function() { - getSavePath(); -}); diff --git a/src/webui/www/public/scripts/dynamicTable.js b/src/webui/www/public/scripts/dynamicTable.js deleted file mode 100644 index ec7ad8c5d..000000000 --- a/src/webui/www/public/scripts/dynamicTable.js +++ /dev/null @@ -1,1264 +0,0 @@ -/* - * MIT License - * Copyright (c) 2008 Ishan Arora & Christophe Dumez - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -/************************************************************** - - Script : Dynamic Table - Version : 0.5 - Authors : Ishan Arora & Christophe Dumez - Desc : Programable sortable table - Licence : Open Source MIT Licence - - **************************************************************/ - -var DynamicTableHeaderContextMenuClass = null; -var ProgressColumnWidth = -1; - -var DynamicTable = new Class({ - - initialize : function () {}, - - setup : function (dynamicTableDivId, dynamicTableFixedHeaderDivId, contextMenu) { - this.dynamicTableDivId = dynamicTableDivId; - this.dynamicTableFixedHeaderDivId = dynamicTableFixedHeaderDivId; - this.fixedTableHeader = $(dynamicTableFixedHeaderDivId).getElements('tr')[0]; - this.hiddenTableHeader = $(dynamicTableDivId).getElements('tr')[0]; - this.tableBody = $(dynamicTableDivId).getElements('tbody')[0]; - this.rows = new Hash(); - this.selectedRows = []; - this.columns = []; - this.contextMenu = contextMenu; - this.sortedColumn = getLocalStorageItem('sorted_column_' + this.dynamicTableDivId, 0); - this.reverseSort = getLocalStorageItem('reverse_sort_' + this.dynamicTableDivId, '0'); - this.initColumns(); - this.loadColumnsOrder(); - this.updateTableHeaders(); - this.setupCommonEvents(); - this.setupHeaderEvents(); - this.setupHeaderMenu(); - }, - - setupCommonEvents : function () { - var scrollFn = function() { - $(this.dynamicTableFixedHeaderDivId).getElements('table')[0].style.left = - -$(this.dynamicTableDivId).scrollLeft + 'px'; - }.bind(this); - - $(this.dynamicTableDivId).addEvent('scroll', scrollFn); - - var resizeFn = function() { - var panel = $(this.dynamicTableDivId).getParent('.panel'); - var h = panel.getBoundingClientRect().height - $(this.dynamicTableFixedHeaderDivId).getBoundingClientRect().height; - $(this.dynamicTableDivId).style.height = h + 'px'; - - // Workaround due to inaccurate calculation of elements heights by browser - - var n = 2; - - while (panel.clientWidth != panel.offsetWidth && n > 0) { // is panel vertical scrollbar visible ? - n--; - h -= 0.5; - $(this.dynamicTableDivId).style.height = h + 'px'; - } - - this.lastPanelHeight = panel.getBoundingClientRect().height; - }.bind(this); - - $(this.dynamicTableDivId).getParent('.panel').addEvent('resize', resizeFn); - - this.lastPanelHeight = 0; - - // Workaround. Resize event is called not always (for example it isn't called when browser window changes it's size) - - var checkResizeFn = function() { - var panel = $(this.dynamicTableDivId).getParent('.panel'); - if (this.lastPanelHeight != panel.getBoundingClientRect().height) { - this.lastPanelHeight = panel.getBoundingClientRect().height; - panel.fireEvent('resize'); - } - }.bind(this); - - setInterval(checkResizeFn, 500); - }, - - setupHeaderEvents : function () { - this.currentHeaderAction = ''; - this.canResize = false; - - var resetElementBorderStyle = function (el, side) { - if (side === 'left' || side !== 'right') { - el.setStyle('border-left-style', ''); - el.setStyle('border-left-color', ''); - el.setStyle('border-left-width', ''); - } - if (side === 'right' || side !== 'left') { - el.setStyle('border-right-style', ''); - el.setStyle('border-right-color', ''); - el.setStyle('border-right-width', ''); - } - }; - - var mouseMoveFn = function (e) { - var brect = e.target.getBoundingClientRect(); - var mouseXRelative = e.event.clientX - brect.left; - if (this.currentHeaderAction === '') { - if (brect.width - mouseXRelative < 5) { - this.resizeTh = e.target; - this.canResize = true; - e.target.getParent("tr").style.cursor = 'col-resize'; - } - else if ((mouseXRelative < 5) && e.target.getPrevious('[class=""]')) { - this.resizeTh = e.target.getPrevious('[class=""]'); - this.canResize = true; - e.target.getParent("tr").style.cursor = 'col-resize'; - } else { - this.canResize = false; - e.target.getParent("tr").style.cursor = ''; - } - } - if (this.currentHeaderAction === 'drag') { - var previousVisibleSibling = e.target.getPrevious('[class=""]'); - var borderChangeElement = previousVisibleSibling; - var changeBorderSide = 'right'; - - if (mouseXRelative > brect.width / 2) { - borderChangeElement = e.target; - this.dropSide = 'right'; - } - else { - this.dropSide = 'left'; - } - - e.target.getParent("tr").style.cursor = 'move'; - - if (!previousVisibleSibling) { // right most column - borderChangeElement = e.target; - - if (mouseXRelative <= brect.width / 2) - changeBorderSide = 'left'; - } - - borderChangeElement.setStyle('border-' + changeBorderSide + '-style', 'solid'); - borderChangeElement.setStyle('border-' + changeBorderSide + '-color', '#e60'); - borderChangeElement.setStyle('border-' + changeBorderSide + '-width', 'initial'); - - resetElementBorderStyle(borderChangeElement, changeBorderSide === 'right' ? 'left' : 'right'); - - borderChangeElement.getSiblings('[class=""]').each(function(el){ - resetElementBorderStyle(el); - }); - } - this.lastHoverTh = e.target; - this.lastClientX = e.event.clientX; - }.bind(this); - - var mouseOutFn = function (e) { - resetElementBorderStyle(e.target); - }.bind(this); - - var onBeforeStart = function (el) { - this.clickedTh = el; - this.currentHeaderAction = 'start'; - this.dragMovement = false; - this.dragStartX = this.lastClientX; - }.bind(this); - - var onStart = function (el, event) { - if (this.canResize) { - this.currentHeaderAction = 'resize'; - this.startWidth = this.resizeTh.getStyle('width').toFloat(); - } - else { - this.currentHeaderAction = 'drag'; - el.setStyle('background-color', '#C1D5E7'); - } - }.bind(this); - - var onDrag = function (el, event) { - if (this.currentHeaderAction === 'resize') { - var width = this.startWidth + (event.page.x - this.dragStartX); - if (width < 16) - width = 16; - this.columns[this.resizeTh.columnName].width = width; - this.updateColumn(this.resizeTh.columnName); - } - }.bind(this); - - var onComplete = function (el, event) { - resetElementBorderStyle(this.lastHoverTh); - el.setStyle('background-color', ''); - if (this.currentHeaderAction === 'resize') - localStorage.setItem('column_' + this.resizeTh.columnName + '_width_' + this.dynamicTableDivId, this.columns[this.resizeTh.columnName].width); - if ((this.currentHeaderAction === 'drag') && (el !== this.lastHoverTh)) { - this.saveColumnsOrder(); - var val = localStorage.getItem('columns_order_' + this.dynamicTableDivId).split(','); - val.erase(el.columnName); - var pos = val.indexOf(this.lastHoverTh.columnName); - if (this.dropSide === 'right') pos++; - val.splice(pos, 0, el.columnName); - localStorage.setItem('columns_order_' + this.dynamicTableDivId, val.join(',')); - this.loadColumnsOrder(); - this.updateTableHeaders(); - while (this.tableBody.firstChild) - this.tableBody.removeChild(this.tableBody.firstChild); - this.updateTable(true); - } - if (this.currentHeaderAction === 'drag') { - resetElementBorderStyle(el); - el.getSiblings('[class=""]').each(function(el){ - resetElementBorderStyle(el); - }); - } - this.currentHeaderAction = ''; - }.bind(this); - - var onCancel = function (el) { - this.currentHeaderAction = ''; - this.setSortedColumn(el.columnName); - }.bind(this); - - var ths = this.fixedTableHeader.getElements('th'); - - for (var i = 0; i < ths.length; i++) { - var th = ths[i]; - th.addEvent('mousemove', mouseMoveFn); - th.addEvent('mouseout', mouseOutFn); - th.makeResizable({ - modifiers : {x: '', y: ''}, - onBeforeStart : onBeforeStart, - onStart : onStart, - onDrag : onDrag, - onComplete : onComplete, - onCancel : onCancel - }); - } - }, - - setupDynamicTableHeaderContextMenuClass : function () { - if (!DynamicTableHeaderContextMenuClass) { - DynamicTableHeaderContextMenuClass = new Class({ - Extends: ContextMenu, - updateMenuItems: function () { - for (var i = 0; i < this.dynamicTable.columns.length; i++) { - if (this.dynamicTable.columns[i].caption === '') - continue; - if (this.dynamicTable.columns[i].visible !== '0') - this.setItemChecked(this.dynamicTable.columns[i].name, true); - else - this.setItemChecked(this.dynamicTable.columns[i].name, false); - } - } - }); - } - }, - - showColumn : function (columnName, show) { - this.columns[columnName].visible = show ? '1' : '0'; - localStorage.setItem('column_' + columnName + '_visible_' + this.dynamicTableDivId, show ? '1' : '0'); - this.updateColumn(columnName); - }, - - setupHeaderMenu : function () { - this.setupDynamicTableHeaderContextMenuClass(); - - var menuId = this.dynamicTableDivId + '_headerMenu'; - - var ul = new Element('ul', {id: menuId, class: 'contextMenu scrollableMenu'}); - - var createLi = function(columnName, text) { - var html = '' + escapeHtml(text) + ''; - return new Element('li', {html: html}); - }; - - var actions = {}; - - var onMenuItemClicked = function (element, ref, action) { - this.showColumn(action, this.columns[action].visible === '0'); - }.bind(this); - - for (var i = 0; i < this.columns.length; i++) { - var text = this.columns[i].caption; - if (text === '') - continue; - ul.appendChild(createLi(this.columns[i].name, text)); - actions[this.columns[i].name] = onMenuItemClicked; - } - - ul.inject(document.body); - - this.headerContextMenu = new DynamicTableHeaderContextMenuClass({ - targets: '#' + this.dynamicTableFixedHeaderDivId + ' tr', - actions: actions, - menu : menuId, - offsets : { - x : -15, - y : 2 - } - }); - - this.headerContextMenu.dynamicTable = this; - }, - - initColumns : function () {}, - - newColumn : function (name, style, caption, defaultWidth, defaultVisible) { - var column = {}; - column['name'] = name; - column['visible'] = getLocalStorageItem('column_' + name + '_visible_' + this.dynamicTableDivId, defaultVisible ? '1' : '0'); - column['force_hide'] = false; - column['caption'] = caption; - column['style'] = style; - column['width'] = getLocalStorageItem('column_' + name + '_width_' + this.dynamicTableDivId, defaultWidth); - column['dataProperties'] = [name]; - column['getRowValue'] = function (row, pos) { - if (pos === undefined) - pos = 0; - return row['full_data'][this.dataProperties[pos]]; - }; - column['compareRows'] = function (row1, row2) { - if (this.getRowValue(row1) < this.getRowValue(row2)) - return -1; - else if (this.getRowValue(row1) > this.getRowValue(row2)) - return 1; - else return 0; - }; - column['updateTd'] = function (td, row) { - td.innerHTML = this.getRowValue(row); - }; - column['onResize'] = null; - this.columns.push(column); - this.columns[name] = column; - - this.hiddenTableHeader.appendChild(new Element('th')); - this.fixedTableHeader.appendChild(new Element('th')); - }, - - loadColumnsOrder : function () { - var columnsOrder = []; - var val = localStorage.getItem('columns_order_' + this.dynamicTableDivId); - if (val === null || val === undefined) return; - val.split(',').forEach(function(v) { - if ((v in this.columns) && (!columnsOrder.contains(v))) - columnsOrder.push(v); - }.bind(this)); - - for (i = 0; i < this.columns.length; i++) - if (!columnsOrder.contains(this.columns[i].name)) - columnsOrder.push(this.columns[i].name); - - for (i = 0; i < this.columns.length; i++) - this.columns[i] = this.columns[columnsOrder[i]]; - }, - - saveColumnsOrder : function () { - val = ''; - for (i = 0; i < this.columns.length; i++) { - if (i > 0) - val += ','; - val += this.columns[i].name; - } - localStorage.setItem('columns_order_' + this.dynamicTableDivId, val); - }, - - updateTableHeaders : function () { - this.updateHeader(this.hiddenTableHeader); - this.updateHeader(this.fixedTableHeader); - }, - - updateHeader : function (header) { - var ths = header.getElements('th'); - - for (var i = 0; i < ths.length; i++) { - th = ths[i]; - th._this = this; - th.setAttribute('title', this.columns[i].caption); - th.innerHTML = this.columns[i].caption; - th.setAttribute('style', 'width: ' + this.columns[i].width + 'px;' + this.columns[i].style); - th.columnName = this.columns[i].name; - if ((this.columns[i].visible == '0') || this.columns[i].force_hide) - th.addClass('invisible'); - else - th.removeClass('invisible'); - } - }, - - getColumnPos : function (columnName) { - for (var i = 0; i < this.columns.length; i++) - if (this.columns[i].name == columnName) - return i; - return -1; - }, - - updateColumn : function (columnName) { - var pos = this.getColumnPos(columnName); - var visible = ((this.columns[pos].visible != '0') && !this.columns[pos].force_hide); - var ths = this.hiddenTableHeader.getElements('th'); - var fths = this.fixedTableHeader.getElements('th'); - var trs = this.tableBody.getElements('tr'); - var style = 'width: ' + this.columns[pos].width + 'px;' + this.columns[pos].style; - - ths[pos].setAttribute('style', style); - fths[pos].setAttribute('style', style); - - if (visible) { - ths[pos].removeClass('invisible'); - fths[pos].removeClass('invisible'); - for (var i = 0; i < trs.length; i++) - trs[i].getElements('td')[pos].removeClass('invisible'); - } - else { - ths[pos].addClass('invisible'); - fths[pos].addClass('invisible'); - for (var j = 0; j < trs.length; j++) - trs[j].getElements('td')[pos].addClass('invisible'); - } - if (this.columns[pos].onResize !== null) - { - this.columns[pos].onResize(columnName); - } - }, - - setSortedColumn : function (column) { - if (column != this.sortedColumn) { - this.sortedColumn = column; - this.reverseSort = '0'; - } - else { - // Toggle sort order - this.reverseSort = this.reverseSort == '0' ? '1' : '0'; - } - localStorage.setItem('sorted_column_' + this.dynamicTableDivId, column); - localStorage.setItem('reverse_sort_' + this.dynamicTableDivId, this.reverseSort); - this.updateTable(false); - }, - - getSelectedRowId : function () { - if (this.selectedRows.length > 0) - return this.selectedRows[0]; - return ''; - }, - - altRow : function () { - if (!MUI.ieLegacySupport) - return; - - var trs = this.tableBody.getElements('tr'); - trs.each(function (el, i) { - if (i % 2) { - el.addClass('alt'); - } else { - el.removeClass('alt'); - } - }.bind(this)); - }, - - selectAll : function () { - this.selectedRows.empty(); - - var trs = this.tableBody.getElements('tr'); - for (var i = 0; i < trs.length; i++) { - var tr = trs[i]; - this.selectedRows.push(tr.rowId); - if (!tr.hasClass('selected')) - tr.addClass('selected'); - } - }, - - deselectAll : function () { - this.selectedRows.empty(); - }, - - selectRow : function (rowId) { - this.selectedRows.empty(); - this.selectedRows.push(rowId); - var trs = this.tableBody.getElements('tr'); - for (var i = 0; i < trs.length; i++) { - var tr = trs[i]; - if (tr.rowId == rowId) { - if (!tr.hasClass('selected')) - tr.addClass('selected'); - } - else - if (tr.hasClass('selected')) - tr.removeClass('selected'); - } - this.onSelectedRowChanged(); - }, - - onSelectedRowChanged : function () {}, - - updateRowData : function (data) { - var rowId = data['rowId']; - var row; - - if (!this.rows.has(rowId)) { - row = {}; - this.rows.set(rowId, row); - row['full_data'] = {}; - row['rowId'] = rowId; - } - else - row = this.rows.get(rowId); - - row['data'] = data; - - for(var x in data) - row['full_data'][x] = data[x]; - }, - - getFilteredAndSortedRows : function () { - var filteredRows = []; - - var rows = this.rows.getValues(); - - for (i = 0; i < rows.length; i++) - { - filteredRows.push(rows[i]); - filteredRows[rows[i].rowId] = rows[i]; - } - - filteredRows.sort(function (row1, row2) { - var column = this.columns[this.sortedColumn]; - res = column.compareRows(row1, row2); - if (this.reverseSort == '0') - return res; - else - return -res; - }.bind(this)); - return filteredRows; - }, - - getTrByRowId : function (rowId) { - trs = this.tableBody.getElements('tr'); - for (var i = 0; i < trs.length; i++) - if (trs[i].rowId == rowId) - return trs[i]; - return null; - }, - - updateTable : function (fullUpdate) { - if (fullUpdate === undefined) - fullUpdate = false; - - var rows = this.getFilteredAndSortedRows(); - - for (var i = 0; i < this.selectedRows.length; i++) - if (!(this.selectedRows[i] in rows)) { - this.selectedRows.splice(i, 1); - i--; - } - - var trs = this.tableBody.getElements('tr'); - - for (var rowPos = 0; rowPos < rows.length; rowPos++) { - var rowId = rows[rowPos]['rowId']; - tr_found = false; - for (var j = rowPos; j < trs.length; j++) - if (trs[j]['rowId'] == rowId) { - tr_found = true; - if (rowPos == j) - break; - trs[j].inject(trs[rowPos], 'before'); - var tmpTr = trs[j]; - trs.splice(j, 1); - trs.splice(rowPos, 0, tmpTr); - break; - } - if (tr_found) // row already exists in the table - this.updateRow(trs[rowPos], fullUpdate); - else { // else create a new row in the table - var tr = new Element('tr'); - - tr['rowId'] = rows[rowPos]['rowId']; - - tr._this = this; - tr.addEvent('contextmenu', function (e) { - if (!this._this.selectedRows.contains(this.rowId)) - this._this.selectRow(this.rowId); - return true; - }); - tr.addEvent('click', function (e) { - e.stop(); - if (e.control) { - // CTRL key was pressed - if (this._this.selectedRows.contains(this.rowId)) { - // remove it - this._this.selectedRows.erase(this.rowId); - // Remove selected style - this.removeClass('selected'); - } - else { - this._this.selectedRows.push(this.rowId); - // Add selected style - this.addClass('selected'); - } - } - else { - if (e.shift && this._this.selectedRows.length == 1) { - // Shift key was pressed - var first_row_id = this._this.selectedRows[0]; - var last_row_id = this.rowId; - this._this.selectedRows.empty(); - var trs = this._this.tableBody.getElements('tr'); - var select = false; - for (var i = 0; i < trs.length; i++) { - var tr = trs[i]; - - if ((tr.rowId == first_row_id) || (tr.rowId == last_row_id)) { - this._this.selectedRows.push(tr.rowId); - tr.addClass('selected'); - select = !select; - } - else { - if (select) { - this._this.selectedRows.push(tr.rowId); - tr.addClass('selected'); - } - else - tr.removeClass('selected'); - } - } - } else { - // Simple selection - this._this.selectRow(this.rowId); - } - } - return false; - }); - - this.setupTr(tr); - - for (var k = 0 ; k < this.columns.length; k++) { - var td = new Element('td'); - if ((this.columns[k].visible == '0') || this.columns[k].force_hide) - td.addClass('invisible'); - td.injectInside(tr); - } - - // Insert - if (rowPos >= trs.length) { - tr.inject(this.tableBody); - trs.push(tr); - } - else { - tr.inject(trs[rowPos], 'before'); - trs.splice(rowPos, 0, tr); - } - - // Update context menu - if (this.contextMenu) - this.contextMenu.addTarget(tr); - - this.updateRow(tr, true); - } - } - - rowPos = rows.length; - - while ((rowPos < trs.length) && (trs.length > 0)) { - trs[trs.length - 1].dispose(); - trs.pop(); - } - }, - - setupTr : function (tr) {}, - - updateRow : function (tr, fullUpdate) { - var row = this.rows.get(tr.rowId); - data = row[fullUpdate ? 'full_data' : 'data']; - - tds = tr.getElements('td'); - for (var i = 0; i < this.columns.length; i++) { - if (data.hasOwnProperty(this.columns[i].dataProperties[0])) - this.columns[i].updateTd(tds[i], row); - } - row['data'] = {}; - }, - - removeRow : function (rowId) { - this.selectedRows.erase(rowId); - var tr = this.getTrByRowId(rowId); - if (tr !== null) { - tr.dispose(); - this.rows.erase(rowId); - return true; - } - return false; - }, - - clear : function () { - this.selectedRows.empty(); - this.rows.empty(); - var trs = this.tableBody.getElements('tr'); - while (trs.length > 0) { - trs[trs.length - 1].dispose(); - trs.pop(); - } - }, - - selectedRowsIds : function () { - return this.selectedRows.slice(); - }, - - getRowIds : function () { - return this.rows.getKeys(); - }, - }); - -var TorrentsTable = new Class({ - Extends: DynamicTable, - - initColumns : function () { - this.newColumn('priority', '', '#', 30, true); - this.newColumn('state_icon', 'cursor: default', '', 22, true); - this.newColumn('name', '', 'QBT_TR(Name)QBT_TR[CONTEXT=TorrentModel]', 200, true); - this.newColumn('size', '', 'QBT_TR(Size)QBT_TR[CONTEXT=TorrentModel]', 100, true); - this.newColumn('progress', '', 'QBT_TR(Done)QBT_TR[CONTEXT=TorrentModel]', 85, true); - this.newColumn('status', '', 'QBT_TR(Status)QBT_TR[CONTEXT=TorrentModel]', 100, true); - this.newColumn('num_seeds', '', 'QBT_TR(Seeds)QBT_TR[CONTEXT=TorrentModel]', 100, true); - this.newColumn('num_leechs', '', 'QBT_TR(Peers)QBT_TR[CONTEXT=TorrentModel]', 100, true); - this.newColumn('dlspeed', '', 'QBT_TR(Down Speed)QBT_TR[CONTEXT=TorrentModel]', 100, true); - this.newColumn('upspeed', '', 'QBT_TR(Up Speed)QBT_TR[CONTEXT=TorrentModel]', 100, true); - this.newColumn('eta', '', 'QBT_TR(ETA)QBT_TR[CONTEXT=TorrentModel]', 100, true); - this.newColumn('ratio', '', 'QBT_TR(Ratio)QBT_TR[CONTEXT=TorrentModel]', 100, true); - this.newColumn('category', '', 'QBT_TR(Category)QBT_TR[CONTEXT=TorrentModel]', 100, true); - this.newColumn('added_on', '', 'QBT_TR(Added On)QBT_TR[CONTEXT=TorrentModel]', 100, true); - this.newColumn('completion_on', '', 'QBT_TR(Completed On)QBT_TR[CONTEXT=TorrentModel]', 100, false); - this.newColumn('tracker', '', 'QBT_TR(Tracker)QBT_TR[CONTEXT=TorrentModel]', 100, false); - this.newColumn('dl_limit', '', 'QBT_TR(Down Limit)QBT_TR[CONTEXT=TorrentModel]', 100, false); - this.newColumn('up_limit', '', 'QBT_TR(Up Limit)QBT_TR[CONTEXT=TorrentModel]', 100, false); - this.newColumn('downloaded', '', 'QBT_TR(Downloaded)QBT_TR[CONTEXT=TorrentModel]', 100, false); - this.newColumn('uploaded', '', 'QBT_TR(Uploaded)QBT_TR[CONTEXT=TorrentModel]', 100, false); - this.newColumn('downloaded_session', '', 'QBT_TR(Session Download)QBT_TR[CONTEXT=TorrentModel]', 100, false); - this.newColumn('uploaded_session', '', 'QBT_TR(Session Upload)QBT_TR[CONTEXT=TorrentModel]', 100, false); - this.newColumn('amount_left', '', 'QBT_TR(Remaining)QBT_TR[CONTEXT=TorrentModel]', 100, false); - this.newColumn('save_path', '', 'QBT_TR(Save path)QBT_TR[CONTEXT=TorrentModel]', 100, false); - this.newColumn('completed', '', 'QBT_TR(Completed)QBT_TR[CONTEXT=TorrentModel]', 100, false); - this.newColumn('ratio_limit', '', 'QBT_TR(Ratio Limit)QBT_TR[CONTEXT=TorrentModel]', 100, false); - this.newColumn('seen_complete', '', 'QBT_TR(Last Seen Complete)QBT_TR[CONTEXT=TorrentModel]', 100, false); - this.newColumn('last_activity', '', 'QBT_TR(Last Activity)QBT_TR[CONTEXT=TorrentModel]', 100, false); - this.newColumn('total_size', '', 'QBT_TR(Total Size)QBT_TR[CONTEXT=TorrentModel]', 100, false); - - this.columns['state_icon'].onclick = ''; - this.columns['state_icon'].dataProperties[0] = 'state'; - - this.columns['num_seeds'].dataProperties.push('num_complete'); - - this.columns['num_leechs'].dataProperties.push('num_incomplete'); - - this.initColumnsFunctions(); - }, - - initColumnsFunctions : function () { - - // state_icon - this.columns['state_icon'].updateTd = function (td, row) { - var state = this.getRowValue(row); - - if ((state === "forcedDL") || (state === "metaDL")) - state = "downloading"; - else if (state === "allocating") - state = "stalledDL"; - else if (state === "forcedUP") - state = "uploading"; - else if (state === "pausedDL") - state = "paused"; - else if (state === "pausedUP") - state = "completed"; - else if ((state === "queuedDL") || (state === "queuedUP")) - state = "queued"; - else if ((state === "checkingDL") || (state === "checkingUP") || - (state === "queuedForChecking") || (state === "checkingResumeData")) - state = "checking"; - else if ((state === "unknown") || (state === "error") || (state === "missingFiles")) - state = "error"; - - var img_path = 'images/skin/' + state + '.png'; - - if (td.getChildren('img').length) { - var img = td.getChildren('img')[0]; - if (img.src.indexOf(img_path) < 0) - img.set('src', img_path); - } - else - td.adopt(new Element('img', { - 'src' : img_path, - 'class' : 'stateIcon' - })); - }; - - // status - this.columns['status'].updateTd = function (td, row) { - var status = this.getRowValue(row); - if (!status) return; - - if ((status === "downloading") || (status === "forcedDL") || (status === "metaDL")) - status = "Downloading"; - else if ((status === "stalledDL") || (status === "stalledUP") || (status === "allocating")) - status = "Stalled"; - else if ((status === "uploading") || (status === "forcedUP")) - status = "Uploading"; - else if (status === "pausedDL") - status = "Paused"; - else if (status === "pausedUP") - status = "Completed"; - else if ((status === "queuedDL") || (status === "queuedUP")) - status = "Queued"; - else if ((status === "checkingDL") || (status === "checkingUP") || - (status === "queuedForChecking") || (status === "checkingResumeData")) - status = "Checking"; - else if ((status === "unknown") || (status === "error") || (status === "missingFiles")) - status = "Error"; - - td.set('html', status); - }; - - // priority - this.columns['priority'].updateTd = function (td, row) { - var priority = this.getRowValue(row); - td.set('html', priority < 1 ? '*' : priority); - }; - - this.columns['priority'].compareRows = function (row1, row2) { - var row1_val = this.getRowValue(row1); - var row2_val = this.getRowValue(row2); - if (row1_val < 1) - row1_val = 1000000; - if (row2_val < 1) - row2_val = 1000000; - if (row1_val < row2_val) - return -1; - else if (row1_val > row2_val) - return 1; - else return 0; - }; - - // name, category - this.columns['name'].updateTd = function (td, row) { - td.set('html', escapeHtml(this.getRowValue(row))); - }; - this.columns['category'].updateTd = this.columns['name'].updateTd; - - // size - this.columns['size'].updateTd = function (td, row) { - var size = this.getRowValue(row); - td.set('html', friendlyUnit(size, false)); - }; - - // progress - this.columns['progress'].updateTd = function (td, row) { - var progress = this.getRowValue(row); - var progressFormated = (progress * 100).round(1); - if (progressFormated == 100.0 && progress != 1.0) - progressFormated = 99.9; - - if (td.getChildren('div').length) { - var div = td.getChildren('div')[0]; - if (td.resized) { - td.resized = false; - div.setWidth(ProgressColumnWidth - 5); - } - if (div.getValue() != progressFormated) - div.setValue(progressFormated); - } - else { - if (ProgressColumnWidth < 0) - ProgressColumnWidth = td.offsetWidth; - td.adopt(new ProgressBar(progressFormated.toFloat(), { - 'width' : ProgressColumnWidth - 5 - })); - td.resized = false; - } - }; - - this.columns['progress'].onResize = function (columnName) { - var pos = this.getColumnPos(columnName); - var trs = this.tableBody.getElements('tr'); - ProgressColumnWidth = -1; - for (var i = 0; i < trs.length; i++) { - var td = trs[i].getElements('td')[pos]; - if (ProgressColumnWidth < 0) - ProgressColumnWidth = td.offsetWidth; - td.resized = true; - this.columns[columnName].updateTd(td, this.rows.get(trs[i].rowId)); - } - }.bind(this); - - // num_seeds - this.columns['num_seeds'].updateTd = function (td, row) { - var num_seeds = this.getRowValue(row, 0); - var num_complete = this.getRowValue(row, 1); - var html = num_seeds; - if (num_complete != -1) - html += ' (' + num_complete + ')'; - td.set('html', html); - }; - this.columns['num_seeds'].compareRows = function (row1, row2) { - var num_seeds1 = this.getRowValue(row1, 0); - var num_complete1 = this.getRowValue(row1, 1); - - var num_seeds2 = this.getRowValue(row2, 0); - var num_complete2 = this.getRowValue(row2, 1); - - if (num_complete1 < num_complete2) - return -1; - else if (num_complete1 > num_complete2) - return 1; - else if (num_seeds1 < num_seeds2) - return -1; - else if (num_seeds1 > num_seeds2) - return 1; - else return 0; - }; - - // num_leechs - this.columns['num_leechs'].updateTd = this.columns['num_seeds'].updateTd; - this.columns['num_leechs'].compareRows = this.columns['num_seeds'].compareRows; - - // dlspeed - this.columns['dlspeed'].updateTd = function (td, row) { - var speed = this.getRowValue(row); - td.set('html', friendlyUnit(speed, true)); - }; - - // upspeed - this.columns['upspeed'].updateTd = this.columns['dlspeed'].updateTd; - - // eta - this.columns['eta'].updateTd = function (td, row) { - var eta = this.getRowValue(row); - td.set('html', friendlyDuration(eta, true)); - }; - - // ratio - this.columns['ratio'].updateTd = function (td, row) { - var ratio = this.getRowValue(row); - var html = null; - if (ratio == -1) - html = '∞'; - else - html = (Math.floor(100 * ratio) / 100).toFixed(2); //Don't round up - td.set('html', html); - }; - - // added on - this.columns['added_on'].updateTd = function (td, row) { - var date = new Date(this.getRowValue(row) * 1000).toLocaleString(); - td.set('html', date); - }; - - // completion_on - this.columns['completion_on'].updateTd = function (td, row) { - var val = this.getRowValue(row); - if (val === 0xffffffff || val < 0) - td.set('html', ''); - else { - var date = new Date(this.getRowValue(row) * 1000).toLocaleString(); - td.set('html', date); - } - }; - - // seen_complete - this.columns['seen_complete'].updateTd = this.columns['completion_on'].updateTd; - - // dl_limit, up_limit - this.columns['dl_limit'].updateTd = function (td, row) { - var speed = this.getRowValue(row); - if (speed === 0) - td.set('html', '∞'); - else - td.set('html', friendlyUnit(speed, true)); - }; - - this.columns['up_limit'].updateTd = this.columns['dl_limit'].updateTd; - - // downloaded, uploaded, downloaded_session, uploaded_session, amount_left, completed, total_size - this.columns['downloaded'].updateTd = this.columns['size'].updateTd; - this.columns['uploaded'].updateTd = this.columns['size'].updateTd; - this.columns['downloaded_session'].updateTd = this.columns['size'].updateTd; - this.columns['uploaded_session'].updateTd = this.columns['size'].updateTd; - this.columns['amount_left'].updateTd = this.columns['size'].updateTd; - this.columns['amount_left'].updateTd = this.columns['size'].updateTd; - this.columns['completed'].updateTd = this.columns['size'].updateTd; - this.columns['total_size'].updateTd = this.columns['size'].updateTd; - - // save_path, tracker - this.columns['save_path'].updateTd = this.columns['name'].updateTd; - this.columns['tracker'].updateTd = this.columns['name'].updateTd; - - // ratio_limit - this.columns['ratio_limit'].updateTd = this.columns['ratio'].updateTd; - - // last_activity - this.columns['last_activity'].updateTd = function (td, row) { - var val = this.getRowValue(row); - if (val < 1) - td.set('html', '∞'); - else - td.set('html', 'QBT_TR(%1 ago)QBT_TR[CONTEXT=TransferListDelegate]'.replace('%1', friendlyDuration((new Date()) / 1000 - val, true))); - }; - }, - - applyFilter : function (row, filterName, categoryHash) { - var state = row['full_data'].state; - var inactive = false; - var r; - - switch(filterName) { - case 'downloading': - if (state != 'downloading' && !~state.indexOf('DL')) - return false; - break; - case 'seeding': - if (state != 'uploading' && state != 'forcedUP' && state != 'stalledUP' && state != 'queuedUP' && state != 'checkingUP') - return false; - break; - case 'completed': - if (state != 'uploading' && !~state.indexOf('UP')) - return false; - break; - case 'paused': - if (!~state.indexOf('paused')) - return false; - break; - case 'resumed': - if (~state.indexOf('paused')) - return false; - break; - case 'inactive': - inactive = true; - // fallthrough - case 'active': - if (state == 'stalledDL') - r = (row['full_data'].upspeed > 0); - else - r = state == 'metaDL' || state == 'downloading' || state == 'forcedDL' || state == 'uploading' || state == 'forcedUP'; - if (r == inactive) - return false; - break; - case 'errored': - if (state != 'error' && state != "unknown" && state != "missingFiles") - return false; - break; - } - - if (categoryHash == CATEGORIES_ALL) - return true; - - if (categoryHash == CATEGORIES_UNCATEGORIZED && row['full_data'].category.length === 0) - return true; - - if (categoryHash != genHash(row['full_data'].category)) - return false; - - return true; - }, - - getFilteredTorrentsNumber : function (filterName, categoryHash) { - var cnt = 0; - var rows = this.rows.getValues(); - - for (i = 0; i < rows.length; i++) - if (this.applyFilter(rows[i], filterName, categoryHash)) cnt++; - return cnt; - }, - - getFilteredTorrentsHashes : function (filterName, categoryHash) { - var rowsHashes = []; - var rows = this.rows.getValues(); - - for (i = 0; i < rows.length; i++) - if (this.applyFilter(rows[i], filterName, categoryHash)) - rowsHashes.push(rows[i]['rowId']); - - return rowsHashes; - }, - - getFilteredAndSortedRows : function () { - var filteredRows = []; - - var rows = this.rows.getValues(); - - for (i = 0; i < rows.length; i++) - if (this.applyFilter(rows[i], selected_filter, selected_category)) { - filteredRows.push(rows[i]); - filteredRows[rows[i].rowId] = rows[i]; - } - - filteredRows.sort(function (row1, row2) { - var column = this.columns[this.sortedColumn]; - res = column.compareRows(row1, row2); - if (this.reverseSort == '0') - return res; - else - return -res; - }.bind(this)); - return filteredRows; - }, - - setupTr : function (tr) { - tr.addEvent('dblclick', function (e) { - e.stop(); - this._this.selectRow(this.rowId); - var row = this._this.rows.get(this.rowId); - var state = row['full_data'].state; - if (~state.indexOf('paused')) - startFN(); - else - pauseFN(); - return true; - }); - tr.addClass("torrentsTableContextMenuTarget"); - }, - - getCurrentTorrentHash : function () { - return this.getSelectedRowId(); - }, - - onSelectedRowChanged : function () { - updatePropertiesPanel(); - } - }); - -var TorrentPeersTable = new Class({ - Extends: DynamicTable, - - initColumns : function () { - this.newColumn('country', '', 'QBT_TR(Country)QBT_TR[CONTEXT=PeerListWidget]', 22, true); - this.newColumn('ip', '', 'QBT_TR(IP)QBT_TR[CONTEXT=PeerListWidget]', 80, true); - this.newColumn('port', '', 'QBT_TR(Port)QBT_TR[CONTEXT=PeerListWidget]', 35, true); - this.newColumn('client', '', 'QBT_TR(Client)QBT_TR[CONTEXT=PeerListWidget]', 140, true); - this.newColumn('progress', '', 'QBT_TR(Progress)QBT_TR[CONTEXT=PeerListWidget]', 50, true); - this.newColumn('dl_speed', '', 'QBT_TR(Down Speed)QBT_TR[CONTEXT=PeerListWidget]', 50, true); - this.newColumn('up_speed', '', 'QBT_TR(Up Speed)QBT_TR[CONTEXT=PeerListWidget]', 50, true); - this.newColumn('downloaded', '', 'QBT_TR(Downloaded)QBT_TR[CONTEXT=PeerListWidget]', 50, true); - this.newColumn('uploaded', '', 'QBT_TR(Uploaded)QBT_TR[CONTEXT=PeerListWidget]', 50, true); - this.newColumn('connection', '', 'QBT_TR(Connection)QBT_TR[CONTEXT=PeerListWidget]', 50, true); - this.newColumn('flags', '', 'QBT_TR(Flags)QBT_TR[CONTEXT=PeerListWidget]', 50, true); - this.newColumn('relevance', '', 'QBT_TR(Relevance)QBT_TR[CONTEXT=PeerListWidget]', 30, true); - this.newColumn('files', '', 'QBT_TR(Files)QBT_TR[CONTEXT=PeerListWidget]', 100, true); - - this.columns['country'].dataProperties.push('country_code'); - this.columns['flags'].dataProperties.push('flags_desc'); - this.initColumnsFunctions(); - }, - - initColumnsFunctions : function () { - - // country - - this.columns['country'].updateTd = function (td, row) { - var country = this.getRowValue(row, 0); - var country_code = this.getRowValue(row, 1); - - if (!country_code) { - if (td.getChildren('img').length) - td.getChildren('img')[0].dispose(); - return; - } - - var img_path = 'images/flags/' + country_code + '.png'; - - if (td.getChildren('img').length) { - var img = td.getChildren('img')[0]; - img.set('src', img_path); - img.set('alt', country); - img.set('title', country); - } - else - td.adopt(new Element('img', { - 'src' : img_path, - 'alt' : country, - 'title' : country - })); - }; - - // ip - - this.columns['ip'].compareRows = function (row1, row2) { - var ip1 = this.getRowValue(row1); - var ip2 = this.getRowValue(row2); - - var a = ip1.split("."); - var b = ip2.split("."); - - for (var i = 0; i < 4; i++){ - if (a[i] != b[i]) - return a[i] - b[i]; - } - - return 0; - }; - - // progress, relevance - - this.columns['progress'].updateTd = function (td, row) { - var progress = this.getRowValue(row); - var progressFormated = (progress * 100).round(1); - if (progressFormated == 100.0 && progress != 1.0) - progressFormated = 99.9; - progressFormated += "%"; - td.set('html', progressFormated); - }; - - this.columns['relevance'].updateTd = this.columns['progress'].updateTd; - - // dl_speed, up_speed - - this.columns['dl_speed'].updateTd = function (td, row) { - var speed = this.getRowValue(row); - if (speed === 0) - td.set('html', ''); - else - td.set('html', friendlyUnit(speed, true)); - }; - - this.columns['up_speed'].updateTd = this.columns['dl_speed'].updateTd; - - // downloaded, uploaded - - this.columns['downloaded'].updateTd = function (td, row) { - var downloaded = this.getRowValue(row); - td.set('html', friendlyUnit(downloaded, false)); - }; - - this.columns['uploaded'].updateTd = this.columns['downloaded'].updateTd; - - // flags - - this.columns['flags'].updateTd = function (td, row) { - td.innerHTML = this.getRowValue(row, 0); - td.title = this.getRowValue(row, 1); - }; - - // files - - this.columns['files'].updateTd = function (td, row) { - td.innerHTML = escapeHtml(this.getRowValue(row, 0).replace('\n', ';')); - td.title = escapeHtml(this.getRowValue(row, 0)); - }; - - } - }); - -/*************************************************************/ diff --git a/src/webui/www/public/scripts/excanvas-compressed.js b/src/webui/www/public/scripts/excanvas-compressed.js deleted file mode 100644 index 1d9ddb266..000000000 --- a/src/webui/www/public/scripts/excanvas-compressed.js +++ /dev/null @@ -1,876 +0,0 @@ -// Copyright 2006 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - - -// Known Issues: -// -// * Patterns are not implemented. -// * Radial gradient are not implemented. The VML version of these look very -// different from the canvas one. -// * Clipping paths are not implemented. -// * Coordsize. The width and height attribute have higher priority than the -// width and height style values which isn't correct. -// * Painting mode isn't implemented. -// * Canvas width/height should is using content-box by default. IE in -// Quirks mode will draw the canvas using border-box. Either change your -// doctype to HTML5 -// (http://www.whatwg.org/specs/web-apps/current-work/#the-doctype) -// or use Box Sizing Behavior from WebFX -// (http://webfx.eae.net/dhtml/boxsizing/boxsizing.html) -// * Non uniform scaling does not correctly scale strokes. -// * Optimize. There is always room for speed improvements. - -// Only add this code if we do not already have a canvas implementation -if (!document.createElement('canvas').getContext) { - -(function() { - - // alias some functions to make (compiled) code shorter - var m = Math; - var mr = m.round; - var ms = m.sin; - var mc = m.cos; - var abs = m.abs; - var sqrt = m.sqrt; - - // this is used for sub pixel precision - var Z = 10; - var Z2 = Z / 2; - - /** - * This funtion is assigned to the elements as element.getContext(). - * @this {HTMLElement} - * @return {CanvasRenderingContext2D_} - */ - function getContext() { - return this.context_ || - (this.context_ = new CanvasRenderingContext2D_(this)); - } - - var slice = Array.prototype.slice; - - /** - * Binds a function to an object. The returned function will always use the - * passed in {@code obj} as {@code this}. - * - * Example: - * - * g = bind(f, obj, a, b) - * g(c, d) // will do f.call(obj, a, b, c, d) - * - * @param {Function} f The function to bind the object to - * @param {Object} obj The object that should act as this when the function - * is called - * @param {*} var_args Rest arguments that will be used as the initial - * arguments when the function is called - * @return {Function} A new function that has bound this - */ - function bind(f, obj, var_args) { - var a = slice.call(arguments, 2); - return function() { - return f.apply(obj, a.concat(slice.call(arguments))); - }; - } - - var G_vmlCanvasManager_ = { - init: function(opt_doc) { - if (/MSIE/.test(navigator.userAgent) && !window.opera) { - var doc = opt_doc || document; - // Create a dummy element so that IE will allow canvas elements to be - // recognized. - doc.createElement('canvas'); - doc.attachEvent('onreadystatechange', bind(this.init_, this, doc)); - } - }, - - init_: function(doc) { - // create xmlns - if (!doc.namespaces['g_vml_']) { - doc.namespaces.add('g_vml_', 'urn:schemas-microsoft-com:vml', - '#default#VML'); - - } - if (!doc.namespaces['g_o_']) { - doc.namespaces.add('g_o_', 'urn:schemas-microsoft-com:office:office', - '#default#VML'); - } - - // Setup default CSS. Only add one style sheet per document - if (!doc.styleSheets['ex_canvas_']) { - var ss = doc.createStyleSheet(); - ss.owningElement.id = 'ex_canvas_'; - ss.cssText = 'canvas{display:inline-block;overflow:hidden;' + - // default size is 300x150 in Gecko and Opera - 'text-align:left;width:300px;height:150px}' + - 'g_vml_\\:*{behavior:url(#default#VML)}' + - 'g_o_\\:*{behavior:url(#default#VML)}'; - - } - - // find all canvas elements - var els = doc.getElementsByTagName('canvas'); - for (var i = 0; i < els.length; i++) { - this.initElement(els[i]); - } - }, - - /** - * Public initializes a canvas element so that it can be used as canvas - * element from now on. This is called automatically before the page is - * loaded but if you are creating elements using createElement you need to - * make sure this is called on the element. - * @param {HTMLElement} el The canvas element to initialize. - * @return {HTMLElement} the element that was created. - */ - initElement: function(el) { - if (!el.getContext) { - - el.getContext = getContext; - - // do not use inline function because that will leak memory - el.attachEvent('onpropertychange', onPropertyChange); - el.attachEvent('onresize', onResize); - - var attrs = el.attributes; - if (attrs.width && attrs.width.specified) { - // TODO: use runtimeStyle and coordsize - // el.getContext().setWidth_(attrs.width.nodeValue); - el.style.width = attrs.width.nodeValue + 'px'; - } else { - el.width = el.clientWidth; - } - if (attrs.height && attrs.height.specified) { - // TODO: use runtimeStyle and coordsize - // el.getContext().setHeight_(attrs.height.nodeValue); - el.style.height = attrs.height.nodeValue + 'px'; - } else { - el.height = el.clientHeight; - } - //el.getContext().setCoordsize_() - } - return el; - } - }; - - function onPropertyChange(e) { - var el = e.srcElement; - - switch (e.propertyName) { - case 'width': - el.style.width = el.attributes.width.nodeValue + 'px'; - el.getContext().clearRect(); - break; - case 'height': - el.style.height = el.attributes.height.nodeValue + 'px'; - el.getContext().clearRect(); - break; - } - } - - function onResize(e) { - var el = e.srcElement; - if (el.firstChild) { - el.firstChild.style.width = el.clientWidth + 'px'; - el.firstChild.style.height = el.clientHeight + 'px'; - } - } - - G_vmlCanvasManager_.init(); - - // precompute "00" to "FF" - var dec2hex = []; - for (var i = 0; i < 16; i++) { - for (var j = 0; j < 16; j++) { - dec2hex[i * 16 + j] = i.toString(16) + j.toString(16); - } - } - - function createMatrixIdentity() { - return [ - [1, 0, 0], - [0, 1, 0], - [0, 0, 1] - ]; - } - - function matrixMultiply(m1, m2) { - var result = createMatrixIdentity(); - - for (var x = 0; x < 3; x++) { - for (var y = 0; y < 3; y++) { - var sum = 0; - - for (var z = 0; z < 3; z++) { - sum += m1[x][z] * m2[z][y]; - } - - result[x][y] = sum; - } - } - return result; - } - - function copyState(o1, o2) { - o2.fillStyle = o1.fillStyle; - o2.lineCap = o1.lineCap; - o2.lineJoin = o1.lineJoin; - o2.lineWidth = o1.lineWidth; - o2.miterLimit = o1.miterLimit; - o2.shadowBlur = o1.shadowBlur; - o2.shadowColor = o1.shadowColor; - o2.shadowOffsetX = o1.shadowOffsetX; - o2.shadowOffsetY = o1.shadowOffsetY; - o2.strokeStyle = o1.strokeStyle; - o2.globalAlpha = o1.globalAlpha; - o2.arcScaleX_ = o1.arcScaleX_; - o2.arcScaleY_ = o1.arcScaleY_; - o2.lineScale_ = o1.lineScale_; - } - - function processStyle(styleString) { - var str, alpha = 1; - - styleString = String(styleString); - if (styleString.substring(0, 3) == 'rgb') { - var start = styleString.indexOf('(', 3); - var end = styleString.indexOf(')', start + 1); - var guts = styleString.substring(start + 1, end).split(','); - - str = '#'; - for (var i = 0; i < 3; i++) { - str += dec2hex[Number(guts[i])]; - } - - if (guts.length == 4 && styleString.substr(3, 1) == 'a') { - alpha = guts[3]; - } - } else { - str = styleString; - } - - return {color: str, alpha: alpha}; - } - - function processLineCap(lineCap) { - switch (lineCap) { - case 'butt': - return 'flat'; - case 'round': - return 'round'; - case 'square': - default: - return 'square'; - } - } - - /** - * This class implements CanvasRenderingContext2D interface as described by - * the WHATWG. - * @param {HTMLElement} surfaceElement The element that the 2D context should - * be associated with - */ - function CanvasRenderingContext2D_(surfaceElement) { - this.m_ = createMatrixIdentity(); - - this.mStack_ = []; - this.aStack_ = []; - this.currentPath_ = []; - - // Canvas context properties - this.strokeStyle = '#000'; - this.fillStyle = '#000'; - - this.lineWidth = 1; - this.lineJoin = 'miter'; - this.lineCap = 'butt'; - this.miterLimit = Z * 1; - this.globalAlpha = 1; - this.canvas = surfaceElement; - - var el = surfaceElement.ownerDocument.createElement('div'); - el.style.width = surfaceElement.clientWidth + 'px'; - el.style.height = surfaceElement.clientHeight + 'px'; - el.style.overflow = 'hidden'; - el.style.position = 'absolute'; - surfaceElement.appendChild(el); - - this.element_ = el; - this.arcScaleX_ = 1; - this.arcScaleY_ = 1; - this.lineScale_ = 1; - } - - var contextPrototype = CanvasRenderingContext2D_.prototype; - contextPrototype.clearRect = function() { - this.element_.innerHTML = ''; - this.currentPath_ = []; - }; - - contextPrototype.beginPath = function() { - // TODO: Branch current matrix so that save/restore has no effect - // as per safari docs. - this.currentPath_ = []; - }; - - contextPrototype.moveTo = function(aX, aY) { - var p = this.getCoords_(aX, aY); - this.currentPath_.push({type: 'moveTo', x: p.x, y: p.y}); - this.currentX_ = p.x; - this.currentY_ = p.y; - }; - - contextPrototype.lineTo = function(aX, aY) { - var p = this.getCoords_(aX, aY); - this.currentPath_.push({type: 'lineTo', x: p.x, y: p.y}); - - this.currentX_ = p.x; - this.currentY_ = p.y; - }; - - contextPrototype.bezierCurveTo = function(aCP1x, aCP1y, - aCP2x, aCP2y, - aX, aY) { - var p = this.getCoords_(aX, aY); - var cp1 = this.getCoords_(aCP1x, aCP1y); - var cp2 = this.getCoords_(aCP2x, aCP2y); - bezierCurveTo(this, cp1, cp2, p); - }; - - // Helper function that takes the already fixed cordinates. - function bezierCurveTo(self, cp1, cp2, p) { - self.currentPath_.push({ - type: 'bezierCurveTo', - cp1x: cp1.x, - cp1y: cp1.y, - cp2x: cp2.x, - cp2y: cp2.y, - x: p.x, - y: p.y - }); - self.currentX_ = p.x; - self.currentY_ = p.y; - } - - contextPrototype.quadraticCurveTo = function(aCPx, aCPy, aX, aY) { - // the following is lifted almost directly from - // http://developer.mozilla.org/en/docs/Canvas_tutorial:Drawing_shapes - - var cp = this.getCoords_(aCPx, aCPy); - var p = this.getCoords_(aX, aY); - - var cp1 = { - x: this.currentX_ + 2.0 / 3.0 * (cp.x - this.currentX_), - y: this.currentY_ + 2.0 / 3.0 * (cp.y - this.currentY_) - }; - var cp2 = { - x: cp1.x + (p.x - this.currentX_) / 3.0, - y: cp1.y + (p.y - this.currentY_) / 3.0 - }; - - bezierCurveTo(this, cp1, cp2, p); - }; - - contextPrototype.arc = function(aX, aY, aRadius, - aStartAngle, aEndAngle, aClockwise) { - aRadius *= Z; - var arcType = aClockwise ? 'at' : 'wa'; - - var xStart = aX + mc(aStartAngle) * aRadius - Z2; - var yStart = aY + ms(aStartAngle) * aRadius - Z2; - - var xEnd = aX + mc(aEndAngle) * aRadius - Z2; - var yEnd = aY + ms(aEndAngle) * aRadius - Z2; - - // IE won't render arches drawn counter clockwise if xStart == xEnd. - if (xStart == xEnd && !aClockwise) { - xStart += 0.125; // Offset xStart by 1/80 of a pixel. Use something - // that can be represented in binary - } - - var p = this.getCoords_(aX, aY); - var pStart = this.getCoords_(xStart, yStart); - var pEnd = this.getCoords_(xEnd, yEnd); - - this.currentPath_.push({type: arcType, - x: p.x, - y: p.y, - radius: aRadius, - xStart: pStart.x, - yStart: pStart.y, - xEnd: pEnd.x, - yEnd: pEnd.y}); - - }; - - contextPrototype.rect = function(aX, aY, aWidth, aHeight) { - this.moveTo(aX, aY); - this.lineTo(aX + aWidth, aY); - this.lineTo(aX + aWidth, aY + aHeight); - this.lineTo(aX, aY + aHeight); - this.closePath(); - }; - - contextPrototype.strokeRect = function(aX, aY, aWidth, aHeight) { - // Will destroy any existing path (same as FF behaviour) - this.beginPath(); - this.moveTo(aX, aY); - this.lineTo(aX + aWidth, aY); - this.lineTo(aX + aWidth, aY + aHeight); - this.lineTo(aX, aY + aHeight); - this.closePath(); - this.stroke(); - this.currentPath_ = []; - }; - - contextPrototype.fillRect = function(aX, aY, aWidth, aHeight) { - // Will destroy any existing path (same as FF behaviour) - this.beginPath(); - this.moveTo(aX, aY); - this.lineTo(aX + aWidth, aY); - this.lineTo(aX + aWidth, aY + aHeight); - this.lineTo(aX, aY + aHeight); - this.closePath(); - this.fill(); - this.currentPath_ = []; - }; - - contextPrototype.createLinearGradient = function(aX0, aY0, aX1, aY1) { - var gradient = new CanvasGradient_('gradient'); - gradient.x0_ = aX0; - gradient.y0_ = aY0; - gradient.x1_ = aX1; - gradient.y1_ = aY1; - return gradient; - }; - - contextPrototype.createRadialGradient = function(aX0, aY0, aR0, - aX1, aY1, aR1) { - var gradient = new CanvasGradient_('gradientradial'); - gradient.x0_ = aX0; - gradient.y0_ = aY0; - gradient.r0_ = aR0; - gradient.x1_ = aX1; - gradient.y1_ = aY1; - gradient.r1_ = aR1; - return gradient; - }; - - contextPrototype.drawImage = function(image, var_args) { - var dx, dy, dw, dh, sx, sy, sw, sh; - - // to find the original width we overide the width and height - var oldRuntimeWidth = image.runtimeStyle.width; - var oldRuntimeHeight = image.runtimeStyle.height; - image.runtimeStyle.width = 'auto'; - image.runtimeStyle.height = 'auto'; - - // get the original size - var w = image.width; - var h = image.height; - - // and remove overides - image.runtimeStyle.width = oldRuntimeWidth; - image.runtimeStyle.height = oldRuntimeHeight; - - if (arguments.length == 3) { - dx = arguments[1]; - dy = arguments[2]; - sx = sy = 0; - sw = dw = w; - sh = dh = h; - } else if (arguments.length == 5) { - dx = arguments[1]; - dy = arguments[2]; - dw = arguments[3]; - dh = arguments[4]; - sx = sy = 0; - sw = w; - sh = h; - } else if (arguments.length == 9) { - sx = arguments[1]; - sy = arguments[2]; - sw = arguments[3]; - sh = arguments[4]; - dx = arguments[5]; - dy = arguments[6]; - dw = arguments[7]; - dh = arguments[8]; - } else { - throw Error('Invalid number of arguments'); - } - - var d = this.getCoords_(dx, dy); - - var w2 = sw / 2; - var h2 = sh / 2; - - var vmlStr = []; - - var W = 10; - var H = 10; - - // For some reason that I've now forgotten, using divs didn't work - vmlStr.push(' ' , - '', - ''); - - this.element_.insertAdjacentHTML('BeforeEnd', - vmlStr.join('')); - }; - - contextPrototype.stroke = function(aFill) { - var lineStr = []; - var lineOpen = false; - var a = processStyle(aFill ? this.fillStyle : this.strokeStyle); - var color = a.color; - var opacity = a.alpha * this.globalAlpha; - - var W = 10; - var H = 10; - - lineStr.push(''); - - if (!aFill) { - var lineWidth = this.lineScale_ * this.lineWidth; - - // VML cannot correctly render a line if the width is less than 1px. - // In that case, we dilute the color to make the line look thinner. - if (lineWidth < 1) { - opacity *= lineWidth; - } - - lineStr.push( - '' - ); - } else if (typeof this.fillStyle == 'object') { - var fillStyle = this.fillStyle; - var angle = 0; - var focus = {x: 0, y: 0}; - - // additional offset - var shift = 0; - // scale factor for offset - var expansion = 1; - - if (fillStyle.type_ == 'gradient') { - var x0 = fillStyle.x0_ / this.arcScaleX_; - var y0 = fillStyle.y0_ / this.arcScaleY_; - var x1 = fillStyle.x1_ / this.arcScaleX_; - var y1 = fillStyle.y1_ / this.arcScaleY_; - var p0 = this.getCoords_(x0, y0); - var p1 = this.getCoords_(x1, y1); - var dx = p1.x - p0.x; - var dy = p1.y - p0.y; - angle = Math.atan2(dx, dy) * 180 / Math.PI; - - // The angle should be a non-negative number. - if (angle < 0) { - angle += 360; - } - - // Very small angles produce an unexpected result because they are - // converted to a scientific notation string. - if (angle < 1e-6) { - angle = 0; - } - } else { - var p0 = this.getCoords_(fillStyle.x0_, fillStyle.y0_); - var width = max.x - min.x; - var height = max.y - min.y; - focus = { - x: (p0.x - min.x) / width, - y: (p0.y - min.y) / height - }; - - width /= this.arcScaleX_ * Z; - height /= this.arcScaleY_ * Z; - var dimension = m.max(width, height); - shift = 2 * fillStyle.r0_ / dimension; - expansion = 2 * fillStyle.r1_ / dimension - shift; - } - - // We need to sort the color stops in ascending order by offset, - // otherwise IE won't interpret it correctly. - var stops = fillStyle.colors_; - stops.sort(function(cs1, cs2) { - return cs1.offset - cs2.offset; - }); - - var length = stops.length; - var color1 = stops[0].color; - var color2 = stops[length - 1].color; - var opacity1 = stops[0].alpha * this.globalAlpha; - var opacity2 = stops[length - 1].alpha * this.globalAlpha; - - var colors = []; - for (var i = 0; i < length; i++) { - var stop = stops[i]; - colors.push(stop.offset * expansion + shift + ' ' + stop.color); - } - - // When colors attribute is used, the meanings of opacity and o:opacity2 - // are reversed. - lineStr.push(''); - } else { - lineStr.push(''); - } - - lineStr.push(''); - - this.element_.insertAdjacentHTML('beforeEnd', lineStr.join('')); - }; - - contextPrototype.fill = function() { - this.stroke(true); - } - - contextPrototype.closePath = function() { - this.currentPath_.push({type: 'close'}); - }; - - /** - * @private - */ - contextPrototype.getCoords_ = function(aX, aY) { - var m = this.m_; - return { - x: Z * (aX * m[0][0] + aY * m[1][0] + m[2][0]) - Z2, - y: Z * (aX * m[0][1] + aY * m[1][1] + m[2][1]) - Z2 - } - }; - - contextPrototype.save = function() { - var o = {}; - copyState(this, o); - this.aStack_.push(o); - this.mStack_.push(this.m_); - this.m_ = matrixMultiply(createMatrixIdentity(), this.m_); - }; - - contextPrototype.restore = function() { - copyState(this.aStack_.pop(), this); - this.m_ = this.mStack_.pop(); - }; - - contextPrototype.translate = function(aX, aY) { - var m1 = [ - [1, 0, 0], - [0, 1, 0], - [aX, aY, 1] - ]; - - this.m_ = matrixMultiply(m1, this.m_); - }; - - contextPrototype.rotate = function(aRot) { - var c = mc(aRot); - var s = ms(aRot); - - var m1 = [ - [c, s, 0], - [-s, c, 0], - [0, 0, 1] - ]; - - this.m_ = matrixMultiply(m1, this.m_); - }; - - contextPrototype.scale = function(aX, aY) { - this.arcScaleX_ *= aX; - this.arcScaleY_ *= aY; - var m1 = [ - [aX, 0, 0], - [0, aY, 0], - [0, 0, 1] - ]; - - var m = this.m_ = matrixMultiply(m1, this.m_); - - // Get the line scale. - // Determinant of this.m_ means how much the area is enlarged by the - // transformation. So its square root can be used as a scale factor - // for width. - var det = m[0][0] * m[1][1] - m[0][1] * m[1][0]; - this.lineScale_ = sqrt(abs(det)); - }; - - /******** STUBS ********/ - contextPrototype.clip = function() { - // TODO: Implement - }; - - contextPrototype.arcTo = function() { - // TODO: Implement - }; - - contextPrototype.createPattern = function() { - return new CanvasPattern_; - }; - - // Gradient / Pattern Stubs - function CanvasGradient_(aType) { - this.type_ = aType; - this.x0_ = 0; - this.y0_ = 0; - this.r0_ = 0; - this.x1_ = 0; - this.y1_ = 0; - this.r1_ = 0; - this.colors_ = []; - } - - CanvasGradient_.prototype.addColorStop = function(aOffset, aColor) { - aColor = processStyle(aColor); - this.colors_.push({offset: aOffset, - color: aColor.color, - alpha: aColor.alpha}); - }; - - function CanvasPattern_() {} - - // set up externs - G_vmlCanvasManager = G_vmlCanvasManager_; - CanvasRenderingContext2D = CanvasRenderingContext2D_; - CanvasGradient = CanvasGradient_; - CanvasPattern = CanvasPattern_; - -})(); - -} // if diff --git a/src/webui/www/public/scripts/misc.js b/src/webui/www/public/scripts/misc.js deleted file mode 100644 index 9444507b3..000000000 --- a/src/webui/www/public/scripts/misc.js +++ /dev/null @@ -1,106 +0,0 @@ -/* - * JS counterpart of the function in src/misc.cpp - */ -function friendlyUnit(value, isSpeed) { - units = [ - "QBT_TR(B)QBT_TR[CONTEXT=misc]", - "QBT_TR(KiB)QBT_TR[CONTEXT=misc]", - "QBT_TR(MiB)QBT_TR[CONTEXT=misc]", - "QBT_TR(GiB)QBT_TR[CONTEXT=misc]", - "QBT_TR(TiB)QBT_TR[CONTEXT=misc]", - "QBT_TR(PiB)QBT_TR[CONTEXT=misc]", - "QBT_TR(EiB)QBT_TR[CONTEXT=misc]" - ]; - - if (value < 0) - return "QBT_TR(Unknown)QBT_TR[CONTEXT=misc]"; - - var i = 0; - while (value >= 1024.0 && i < 6) { - value /= 1024.0; - ++i; - } - - function friendlyUnitPrecision(sizeUnit) { - if (sizeUnit <= 2) return 1; // KiB, MiB - else if (sizeUnit === 3) return 2; // GiB - else return 3; // TiB, PiB, EiB - } - - var ret; - if (i === 0) - ret = value + " " + units[i]; - else - ret = (Math.floor(10 * value) / 10).toFixed(friendlyUnitPrecision(i)) //Don't round up - + " " + units[i]; - - if (isSpeed) - ret += "QBT_TR(/s)QBT_TR[CONTEXT=misc]"; - return ret; -} - -/* - * JS counterpart of the function in src/misc.cpp - */ -function friendlyDuration(seconds) { - var MAX_ETA = 8640000; - if (seconds < 0 || seconds >= MAX_ETA) - return "∞"; - if (seconds === 0) - return "0"; - if (seconds < 60) - return "QBT_TR(< 1m)QBT_TR[CONTEXT=misc]"; - var minutes = seconds / 60; - if (minutes < 60) - return "QBT_TR(%1m)QBT_TR[CONTEXT=misc]".replace("%1", parseInt(minutes)); - var hours = minutes / 60; - minutes = minutes % 60; - if (hours < 24) - return "QBT_TR(%1h %2m)QBT_TR[CONTEXT=misc]".replace("%1", parseInt(hours)).replace("%2", parseInt(minutes)); - var days = hours / 24; - hours = hours % 24; - if (days < 100) - return "QBT_TR(%1d %2h)QBT_TR[CONTEXT=misc]".replace("%1", parseInt(days)).replace("%2", parseInt(hours)); - return "∞"; -} - -/* - * From: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toISOString - */ -if (!Date.prototype.toISOString) { - (function() { - - function pad(number) { - if (number < 10) { - return '0' + number; - } - return number; - } - - Date.prototype.toISOString = function() { - return this.getUTCFullYear() + - '-' + pad(this.getUTCMonth() + 1) + - '-' + pad(this.getUTCDate()) + - 'T' + pad(this.getUTCHours()) + - ':' + pad(this.getUTCMinutes()) + - ':' + pad(this.getUTCSeconds()) + - '.' + (this.getUTCMilliseconds() / 1000).toFixed(3).slice(2, 5) + - 'Z'; - }; - - }()); -} - -/* - * JS counterpart of the function in src/misc.cpp - */ -function parseHtmlLinks(text) { - var exp = /(\b(https?|ftp|file):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/ig; - return text.replace(exp,"$1"); -} - -function escapeHtml(str) { - var div = document.createElement('div'); - div.appendChild(document.createTextNode(str)); - return div.innerHTML; -} diff --git a/src/webui/www/public/scripts/mocha-init.js b/src/webui/www/public/scripts/mocha-init.js deleted file mode 100644 index bd956e8e8..000000000 --- a/src/webui/www/public/scripts/mocha-init.js +++ /dev/null @@ -1,596 +0,0 @@ -/* ----------------------------------------------------------------- - - ATTACH MOCHA LINK EVENTS - Notes: Here is where you define your windows and the events that open them. - If you are not using links to run Mocha methods you can remove this function. - - If you need to add link events to links within windows you are creating, do - it in the onContentLoaded function of the new window. - - ----------------------------------------------------------------- */ -/* Define localStorage object for older browsers */ -if (typeof localStorage == 'undefined') { - window['localStorage'] = { - getItem: function(name) { - return Cookie.read(name); - }, - setItem: function(name, value) { - Cookie.write(name, value, { - duration: 365 * 10 - }); - } - }; -} - -function getLocalStorageItem(name, defaultVal) { - val = localStorage.getItem(name); - if (val === null || val === undefined) - val = defaultVal; - return val; -} - -var deleteFN = function() {}; -var startFN = function() {}; -var pauseFN = function() {}; - -initializeWindows = function() { - - function addClickEvent(el, fn) { - ['Link', 'Button'].each(function(item) { - if ($(el + item)) { - $(el + item).addEvent('click', fn); - } - }); - } - - addClickEvent('download', function(e) { - new Event(e).stop(); - new MochaUI.Window({ - id: 'downloadPage', - title: "QBT_TR(Download from URLs)QBT_TR[CONTEXT=downloadFromURL]", - loadMethod: 'iframe', - contentURL: 'download.html', - scrollbars: true, - resizable: false, - maximizable: false, - closable: true, - paddingVertical: 0, - paddingHorizontal: 0, - width: 500, - height: 400 - }); - updateMainData(); - }); - - addClickEvent('preferences', function(e) { - new Event(e).stop(); - new MochaUI.Window({ - id: 'preferencesPage', - title: "QBT_TR(Options)QBT_TR[CONTEXT=OptionsDialog]", - loadMethod: 'xhr', - toolbar: true, - contentURL: 'preferences_content.html', - require: { - css: ['css/Tabs.css'] - }, - toolbarURL: 'preferences.html', - resizable: true, - maximizable: false, - closable: true, - paddingVertical: 0, - paddingHorizontal: 0, - width: 700, - height: 300 - }); - }); - - addClickEvent('upload', function(e) { - new Event(e).stop(); - new MochaUI.Window({ - id: 'uploadPage', - title: "QBT_TR(Upload local torrent)QBT_TR[CONTEXT=HttpServer]", - loadMethod: 'iframe', - contentURL: 'upload.html', - scrollbars: true, - resizable: false, - maximizable: false, - paddingVertical: 0, - paddingHorizontal: 0, - width: 500, - height: 240 - }); - updateMainData(); - }); - - globalUploadLimitFN = function() { - new MochaUI.Window({ - id: 'uploadLimitPage', - title: "QBT_TR(Global Upload Speed Limit)QBT_TR[CONTEXT=MainWindow]", - loadMethod: 'iframe', - contentURL: 'uploadlimit.html?hashes=global', - scrollbars: false, - resizable: false, - maximizable: false, - paddingVertical: 0, - paddingHorizontal: 0, - width: 424, - height: 80 - }); - }; - - uploadLimitFN = function() { - var hashes = torrentsTable.selectedRowsIds(); - if (hashes.length) { - var hash = hashes[0]; - new MochaUI.Window({ - id: 'uploadLimitPage', - title: "QBT_TR(Torrent Upload Speed Limiting)QBT_TR[CONTEXT=TransferListWidget]", - loadMethod: 'iframe', - contentURL: 'uploadlimit.html?hashes=' + hashes.join("|"), - scrollbars: false, - resizable: false, - maximizable: false, - paddingVertical: 0, - paddingHorizontal: 0, - width: 424, - height: 80 - }); - } - }; - - toggleSequentialDownloadFN = function() { - var hashes = torrentsTable.selectedRowsIds(); - if (hashes.length) { - new Request({ - url: 'command/toggleSequentialDownload', - method: 'post', - data: { - hashes: hashes.join("|") - } - }).send(); - updateMainData(); - } - }; - - toggleFirstLastPiecePrioFN = function() { - var hashes = torrentsTable.selectedRowsIds(); - if (hashes.length) { - new Request({ - url: 'command/toggleFirstLastPiecePrio', - method: 'post', - data: { - hashes: hashes.join("|") - } - }).send(); - updateMainData(); - } - }; - - setSuperSeedingFN = function(val) { - var hashes = torrentsTable.selectedRowsIds(); - if (hashes.length) { - new Request({ - url: 'command/setSuperSeeding', - method: 'post', - data: { - value: val, - hashes: hashes.join("|") - } - }).send(); - updateMainData(); - } - }; - - setForceStartFN = function() { - var hashes = torrentsTable.selectedRowsIds(); - if (hashes.length) { - new Request({ - url: 'command/setForceStart', - method: 'post', - data: { - value: 'true', - hashes: hashes.join("|") - } - }).send(); - updateMainData(); - } - }; - - globalDownloadLimitFN = function() { - new MochaUI.Window({ - id: 'downloadLimitPage', - title: "QBT_TR(Global Download Speed Limit)QBT_TR[CONTEXT=MainWindow]", - loadMethod: 'iframe', - contentURL: 'downloadlimit.html?hashes=global', - scrollbars: false, - resizable: false, - maximizable: false, - paddingVertical: 0, - paddingHorizontal: 0, - width: 424, - height: 80 - }); - }; - - StatisticsLinkFN = function() { - new MochaUI.Window({ - id: 'statisticspage', - title: 'QBT_TR(Statistics)QBT_TR[CONTEXT=StatsDialog]', - loadMethod: 'xhr', - contentURL: 'statistics.html', - scrollbars: false, - resizable: false, - maximizable: false, - width: 275, - height: 370, - padding: 10 - }); - }; - - downloadLimitFN = function() { - var hashes = torrentsTable.selectedRowsIds(); - if (hashes.length) { - var hash = hashes[0]; - new MochaUI.Window({ - id: 'downloadLimitPage', - title: "QBT_TR(Torrent Download Speed Limiting)QBT_TR[CONTEXT=TransferListWidget]", - loadMethod: 'iframe', - contentURL: 'downloadlimit.html?hashes=' + hashes.join("|"), - scrollbars: false, - resizable: false, - maximizable: false, - paddingVertical: 0, - paddingHorizontal: 0, - width: 424, - height: 80 - }); - } - }; - - deleteFN = function() { - var hashes = torrentsTable.selectedRowsIds(); - if (hashes.length) { - new MochaUI.Window({ - id: 'confirmDeletionPage', - title: "QBT_TR(Deletion confirmation)QBT_TR[CONTEXT=confirmDeletionDlg]", - loadMethod: 'iframe', - contentURL: 'confirmdeletion.html?hashes=' + hashes.join("|"), - scrollbars: false, - resizable: false, - maximizable: false, - padding: 10, - width: 424, - height: 140 - }); - updateMainData(); - } - }; - - addClickEvent('delete', function(e) { - new Event(e).stop(); - deleteFN(); - }); - - pauseFN = function() { - var hashes = torrentsTable.selectedRowsIds(); - if (hashes.length) { - hashes.each(function(hash, index) { - new Request({ - url: 'command/pause', - method: 'post', - data: { - hash: hash - } - }).send(); - }); - updateMainData(); - } - }; - - startFN = function() { - var hashes = torrentsTable.selectedRowsIds(); - if (hashes.length) { - hashes.each(function(hash, index) { - new Request({ - url: 'command/resume', - method: 'post', - data: { - hash: hash - } - }).send(); - }); - updateMainData(); - } - }; - - recheckFN = function() { - var hashes = torrentsTable.selectedRowsIds(); - if (hashes.length) { - hashes.each(function(hash, index) { - new Request({ - url: 'command/recheck', - method: 'post', - data: { - hash: hash - } - }).send(); - }); - updateMainData(); - } - }; - - setLocationFN = function() { - var hashes = torrentsTable.selectedRowsIds(); - if (hashes.length) { - new MochaUI.Window({ - id: 'setLocationPage', - title: "QBT_TR(Set location)QBT_TR[CONTEXT=TransferListWidget]", - loadMethod: 'iframe', - contentURL: 'setlocation.html?hashes=' + hashes.join('|'), - scrollbars: false, - resizable: false, - maximizable: false, - paddingVertical: 0, - paddingHorizontal: 0, - width: 250, - height: 100 - }); - } - }; - - torrentNewCategoryFN = function () { - var hashes = torrentsTable.selectedRowsIds(); - if (hashes.length) { - new MochaUI.Window({ - id: 'newCategoryPage', - title: "QBT_TR(New Category)QBT_TR[CONTEXT=TransferListWidget]", - loadMethod: 'iframe', - contentURL: 'newcategory.html?hashes=' + hashes.join('|'), - scrollbars: false, - resizable: false, - maximizable: false, - paddingVertical: 0, - paddingHorizontal: 0, - width: 250, - height: 100 - }); - } - }; - - torrentSetCategoryFN = function (categoryHash) { - var categoryName = ''; - if (categoryHash != 0) - categoryName = category_list[categoryHash].name; - var hashes = torrentsTable.selectedRowsIds(); - if (hashes.length) { - new Request({ - url: 'command/setCategory', - method: 'post', - data: { - hashes: hashes.join("|"), - category: categoryName - } - }).send(); - } - }; - - createCategoryFN = function () { - new MochaUI.Window({ - id: 'newCategoryPage', - title: "QBT_TR(New Category)QBT_TR[CONTEXT=CategoryFilterWidget]", - loadMethod: 'iframe', - contentURL: 'newcategory.html', - scrollbars: false, - resizable: false, - maximizable: false, - paddingVertical: 0, - paddingHorizontal: 0, - width: 250, - height: 100 - }); - updateMainData(); - }; - - removeCategoryFN = function (categoryHash) { - var categoryName = category_list[categoryHash].name; - new Request({ - url: 'command/removeCategories', - method: 'post', - data: { - categories: categoryName - } - }).send(); - setCategoryFilter(CATEGORIES_ALL); - }; - - deleteUnusedCategoriesFN = function () { - var categories = []; - for (var hash in category_list) { - if (torrentsTable.getFilteredTorrentsNumber('all', hash) === 0) - categories.push(category_list[hash].name); - } - new Request({ - url: 'command/removeCategories', - method: 'post', - data: { - categories: categories.join('\n') - } - }).send(); - setCategoryFilter(CATEGORIES_ALL); - }; - - startTorrentsByCategoryFN = function (categoryHash) { - var hashes = torrentsTable.getFilteredTorrentsHashes('all', categoryHash); - if (hashes.length) { - hashes.each(function (hash, index) { - new Request({ - url: 'command/resume', - method: 'post', - data: { - hash: hash - } - }).send(); - }); - updateMainData(); - } - }; - - pauseTorrentsByCategoryFN = function (categoryHash) { - var hashes = torrentsTable.getFilteredTorrentsHashes('all', categoryHash); - if (hashes.length) { - hashes.each(function (hash, index) { - new Request({ - url: 'command/pause', - method: 'post', - data: { - hash: hash - } - }).send(); - }); - updateMainData(); - } - }; - - deleteTorrentsByCategoryFN = function (categoryHash) { - var hashes = torrentsTable.getFilteredTorrentsHashes('all', categoryHash); - if (hashes.length) { - new MochaUI.Window({ - id: 'confirmDeletionPage', - title: "QBT_TR(Deletion confirmation)QBT_TR[CONTEXT=confirmDeletionDlg]", - loadMethod: 'iframe', - contentURL: 'confirmdeletion.html?hashes=' + hashes.join("|"), - scrollbars: false, - resizable: false, - maximizable: false, - padding: 10, - width: 424, - height: 140 - }); - updateMainData(); - } - }; - - copyNameFN = function() { - var selectedRows = torrentsTable.selectedRowsIds(); - var names = []; - if (selectedRows.length) { - var rows = torrentsTable.getFilteredAndSortedRows(); - for (var i = 0; i < selectedRows.length; i++) { - var hash = selectedRows[i]; - names.push(rows[hash].full_data.name); - } - } - return names.join("\n"); - }; - - copyMagnetLinkFN = function() { - var selectedRows = torrentsTable.selectedRowsIds(); - var magnets = []; - if (selectedRows.length) { - var rows = torrentsTable.getFilteredAndSortedRows(); - for (var i = 0; i < selectedRows.length; i++) { - var hash = selectedRows[i]; - magnets.push(rows[hash].full_data.magnet_uri); - } - } - return magnets.join("\n"); - }; - - copyHashFN = function() { - return torrentsTable.selectedRowsIds().join("\n"); - }; - - ['pauseAll', 'resumeAll'].each(function(item) { - addClickEvent(item, function(e) { - new Event(e).stop(); - new Request({ - url: 'command/' + item - }).send(); - updateMainData(); - }); - }); - - ['pause', 'resume', 'recheck'].each(function(item) { - addClickEvent(item, function(e) { - new Event(e).stop(); - var hashes = torrentsTable.selectedRowsIds(); - if (hashes.length) { - hashes.each(function(hash, index) { - new Request({ - url: 'command/' + item, - method: 'post', - data: { - hash: hash - } - }).send(); - }); - updateMainData(); - } - }); - }); - - ['decreasePrio', 'increasePrio', 'topPrio', 'bottomPrio'].each(function(item) { - addClickEvent(item, function(e) { - new Event(e).stop(); - setPriorityFN(item); - }); - }); - - setPriorityFN = function(cmd) { - var hashes = torrentsTable.selectedRowsIds(); - if (hashes.length) { - new Request({ - url: 'command/' + cmd, - method: 'post', - data: { - hashes: hashes.join("|") - } - }).send(); - updateMainData(); - } - }; - - addClickEvent('about', function(e) { - new Event(e).stop(); - new MochaUI.Window({ - id: 'aboutpage', - title: 'QBT_TR(About)QBT_TR[CONTEXT=AboutDlg]', - loadMethod: 'xhr', - contentURL: 'about.html', - width: 550, - height: 290, - padding: 10 - }); - }); - - addClickEvent('logout', function(e) { - new Event(e).stop(); - new Request({ - url: 'logout', - method: 'get', - onSuccess: function() { - window.location.reload(); - } - }).send(); - }); - - addClickEvent('shutdown', function(e) { - new Event(e).stop(); - if (confirm('QBT_TR(Are you sure you want to quit qBittorrent?)QBT_TR[CONTEXT=MainWindow]')) { - new Request({ - url: 'command/shutdown', - onSuccess: function() { - document.write("QBT_TR(qBittorrent has been shutdown.)QBT_TR[CONTEXT=HttpServer]

QBT_TR(qBittorrent has been shutdown.)QBT_TR[CONTEXT=HttpServer]

"); - stop(); - } - }).send(); - } - }); - - // Deactivate menu header links - $$('a.returnFalse').each(function(el) { - el.addEvent('click', function(e) { - new Event(e).stop(); - }); - }); -}; diff --git a/src/webui/www/public/scripts/mocha-yc.js b/src/webui/www/public/scripts/mocha-yc.js deleted file mode 100644 index 053c708f0..000000000 --- a/src/webui/www/public/scripts/mocha-yc.js +++ /dev/null @@ -1 +0,0 @@ -var MUI=MochaUI=new Hash({version:"0.9.6 development",options:new Hash({theme:"default",advancedEffects:false,standardEffects:true}),path:{source:"scripts/source/",themes:"themes/",plugins:"plugins/"},themePath:function(){return MUI.path.themes+MUI.options.theme+"/"},files:new Hash()});MUI.files[MUI.path.source+"Core/Core.js"]="loaded";MUI.extend({Windows:{instances:new Hash()},ieSupport:"excanvas",ieLegacySupport:Browser.Engine.trident&&Browser.version<9,updateContent:function(c){var c=$extend({element:null,childElement:null,method:null,data:null,title:null,content:null,loadMethod:null,url:null,scrollbars:null,padding:null,require:{},onContentLoaded:$empty},c);c.require=$extend({css:[],images:[],js:[],onload:null},c.require);var b={};if(!c.element){return}var d=c.element;if(MUI.Windows.instances.get(d.id)){b.recipient="window"}else{b.recipient="panel"}var a=d.retrieve("instance");if(c.title){a.titleEl.set("html",c.title)}var e=a.contentEl;b.contentContainer=c.childElement!=null?c.childElement:a.contentEl;var g=a.contentWrapperEl;if(!c.loadMethod){if(!a.options.loadMethod){if(!c.url){c.loadMethod="html"}else{c.loadMethod="xhr"}}else{c.loadMethod=a.options.loadMethod}}var f=c.scrollbars||a.options.scrollbars;if(b.contentContainer==a.contentEl){g.setStyles({overflow:f!=false&&c.loadMethod!="iframe"?"auto":"hidden"})}if(c.padding!=null){e.setStyles({"padding-top":c.padding.top,"padding-bottom":c.padding.bottom,"padding-left":c.padding.left,"padding-right":c.padding.right})}if(b.contentContainer==e){e.empty().show();e.getAllNext(".column").destroy();e.getAllNext(".columnHandle").destroy()}b.onContentLoaded=function(){if(c.require.js.length||typeof c.require.onload=="function"){new MUI.Require({js:c.require.js,onload:function(){if(!$defined(c.require.onload)){return}if(Browser.Engine.presto){c.require.onload.delay(100)}else{c.require.onload()}c.onContentLoaded?c.onContentLoaded():a.fireEvent("onContentLoaded",d)}.bind(this)})}else{c.onContentLoaded?c.onContentLoaded():a.fireEvent("onContentLoaded",d)}};if(c.require.css.length||c.require.images.length){new MUI.Require({css:c.require.css,images:c.require.images,onload:function(){this.loadSelect(a,c,b)}.bind(this)})}else{this.loadSelect(a,c,b)}},loadSelect:function(a,c,b){switch(c.loadMethod){case"xhr":this.updateContentXHR(a,c,b);break;case"iframe":this.updateContentIframe(a,c,b);break;case"html":default:this.updateContentHTML(a,c,b);break}},updateContentXHR:function(a,c,b){var f=a.contentEl;var e=b.contentContainer;var d=b.onContentLoaded;new Request.HTML({url:c.url,update:e,method:c.method!=null?c.method:"get",data:c.data!=null?new Hash(c.data).toQueryString():"",evalScripts:a.options.evalScripts,evalResponse:a.options.evalResponse,onRequest:function(){if(b.recipient=="window"&&e==f){a.showSpinner()}else{if(b.recipient=="panel"&&e==f&&$("spinner")){$("spinner").show()}}}.bind(this),onFailure:function(g){if(e==f){var j=new RegExp("[\n\rs]*(.*)[\n\rs]*","gmi");var h=j.exec(g.responseText);if(!h){h="Unknown"}e.set("html","

Error: "+h+"

");if(b.recipient=="window"){a.hideSpinner()}else{if(b.recipient=="panel"&&$("spinner")){$("spinner").hide()}}}}.bind(this),onSuccess:function(){if(e==f){if(b.recipient=="window"){a.hideSpinner()}else{if(b.recipient=="panel"&&$("spinner")){$("spinner").hide()}}}Browser.Engine.trident4?d.delay(750):d()}.bind(this),onComplete:function(){}.bind(this)}).send()},updateContentIframe:function(a,c,b){var f=a.contentEl;var e=b.contentContainer;var g=a.contentWrapperEl;var d=b.onContentLoaded;if(a.options.contentURL==""||e!=f){return}a.iframeEl=new Element("iframe",{id:a.options.id+"_iframe",name:a.options.id+"_iframe","class":"mochaIframe",src:c.url,marginwidth:0,marginheight:0,frameBorder:0,scrolling:"auto",styles:{height:g.offsetHeight-g.getStyle("margin-top").toInt()-g.getStyle("margin-bottom").toInt(),width:a.panelEl?g.offsetWidth-g.getStyle("margin-left").toInt()-g.getStyle("margin-right").toInt():"100%"}}).injectInside(f);a.iframeEl.addEvent("load",function(h){if(b.recipient=="window"){a.hideSpinner()}else{if(b.recipient=="panel"&&e==f&&$("spinner")){$("spinner").hide()}}Browser.Engine.trident4?d.delay(50):d()}.bind(this));if(b.recipient=="window"){a.showSpinner()}else{if(b.recipient=="panel"&&e==f&&$("spinner")){$("spinner").show()}}},updateContentHTML:function(a,c,b){var f=a.contentEl;var e=b.contentContainer;var d=b.onContentLoaded;var g=new Array("element","textnode","whitespace","collection");if(g.contains($type(c.content))){c.content.inject(e)}else{e.set("html",c.content)}if(e==f){if(b.recipient=="window"){a.hideSpinner()}else{if(b.recipient=="panel"&&$("spinner")){$("spinner").hide()}}}Browser.Engine.trident4?d.delay(50):d()},reloadIframe:function(a){Browser.Engine.gecko?$(a).src=$(a).src:top.frames[a].location.reload(true)},roundedRect:function(f,d,j,h,c,b,g,e){f.fillStyle="rgba("+g.join(",")+","+e+")";f.beginPath();f.moveTo(d,j+b);f.lineTo(d,j+c-b);f.quadraticCurveTo(d,j+c,d+b,j+c);f.lineTo(d+h-b,j+c);f.quadraticCurveTo(d+h,j+c,d+h,j+c-b);f.lineTo(d+h,j+b);f.quadraticCurveTo(d+h,j,d+h-b,j);f.lineTo(d+b,j);f.quadraticCurveTo(d,j,d,j+b);f.fill()},triangle:function(e,c,h,g,b,f,d){e.beginPath();e.moveTo(c+g,h);e.lineTo(c,h+b);e.lineTo(c+g,h+b);e.closePath();e.fillStyle="rgba("+f.join(",")+","+d+")";e.fill()},circle:function(d,b,g,f,e,c){d.beginPath();d.arc(b,g,f,0,Math.PI*2,true);d.fillStyle="rgba("+e.join(",")+","+c+")";d.fill()},notification:function(a){new MUI.Window({loadMethod:"html",closeAfter:1500,type:"notification",addClass:"notification",content:a,width:220,height:40,y:53,padding:{top:10,right:12,bottom:10,left:12},shadowBlur:5})},toggleAdvancedEffects:function(a){if(MUI.options.advancedEffects==false){MUI.options.advancedEffects=true;if(a){this.toggleAdvancedEffectsLink=new Element("div",{"class":"check",id:"toggleAdvancedEffects_check"}).inject(a)}}else{MUI.options.advancedEffects=false;if(this.toggleAdvancedEffectsLink){this.toggleAdvancedEffectsLink.destroy()}}},toggleStandardEffects:function(a){if(MUI.options.standardEffects==false){MUI.options.standardEffects=true;if(a){this.toggleStandardEffectsLink=new Element("div",{"class":"check",id:"toggleStandardEffects_check"}).inject(a)}}else{MUI.options.standardEffects=false;if(this.toggleStandardEffectsLink){this.toggleStandardEffectsLink.destroy()}}},underlayInitialize:function(){var a=new Element("div",{id:"windowUnderlay",styles:{height:parent.getCoordinates().height,opacity:0.01,display:"none"}}).inject(document.body)},setUnderlaySize:function(){$("windowUnderlay").setStyle("height",parent.getCoordinates().height)}});function fixPNG(e){if(Browser.Engine.trident4&&document.body.filters){var b=(e.id)?"id='"+e.id+"' ":"";var d=(e.className)?"class='"+e.className+"' ":"";var f=(e.title)?"title='"+e.title+"' ":"title='"+e.alt+"' ";var c="display:inline-block;"+e.style.cssText;var a="";e.outerHTML=a}}document.addEvent("mousedown",function(a){MUI.blurAll.delay(50)});window.addEvent("domready",function(){MUI.underlayInitialize()});window.addEvent("resize",function(){if($("windowUnderlay")){MUI.setUnderlaySize()}else{MUI.underlayInitialize()}});Element.implement({hide:function(){this.setStyle("display","none");return this},show:function(){this.setStyle("display","block");return this}});Element.implement({shake:function(b,h){b=b||3;h=h||500;h=(h/50).toInt()-1;var e=this.getParent();if(e!=$(document.body)&&e.getStyle("position")=="static"){e.setStyle("position","relative")}var a=this.getStyle("position");if(a=="static"){this.setStyle("position","relative");a="relative"}if(MUI.ieLegacySupport){e.setStyle("height",e.getStyle("height"))}var g=this.getPosition(e);if(a=="relative"&&!Browser.Engine.presto){g.x-=e.getStyle("paddingLeft").toInt();g.y-=e.getStyle("paddingTop").toInt()}var f=this.retrieve("morph");if(f){f.cancel();var c=f.options}var f=this.get("morph",{duration:50,link:"chain"});for(var d=0;d]*>([\s\S]*?)<\/body>/i);c=(b)?b[1]:c;var a=new Element("div");return a.set("html",c)}});MUI.getCSSRule=function(b){for(var c=0;c=200)&&(a<300))}});Browser.Request=function(){return $try(function(){return new ActiveXObject("MSXML2.XMLHTTP")},function(){return new XMLHttpRequest()})}}MUI.Require=new Class({Implements:[Options],options:{css:[],images:[],js:[],onload:$empty},initialize:function(a){this.setOptions(a);var a=this.options;this.assetsToLoad=a.css.length+a.images.length+a.js.length;this.assetsLoaded=0;var b=0;if(a.css.length){a.css.each(function(c){this.getAsset(c,function(){if(b==a.css.length-1){if(this.assetsLoaded==this.assetsToLoad-1){this.requireOnload()}else{this.assetsLoaded++;this.requireContinue.delay(50,this)}}else{b++;this.assetsLoaded++}}.bind(this))}.bind(this))}else{if(!a.js.length&&!a.images.length){this.options.onload();return true}else{this.requireContinue.delay(50,this)}}},requireOnload:function(){this.assetsLoaded++;if(this.assetsLoaded==this.assetsToLoad){this.options.onload();return true}},requireContinue:function(){var a=this.options;if(a.images.length){a.images.each(function(b){this.getAsset(b,this.requireOnload.bind(this))}.bind(this))}if(a.js.length){a.js.each(function(b){this.getAsset(b,this.requireOnload.bind(this))}.bind(this))}},getAsset:function(b,c){if(MUI.files[b]=="loaded"){if(typeof c=="function"){c()}return true}else{if(MUI.files[b]=="loading"){var d=0;var a=(function(){d++;if(MUI.files[b]=="loading"&&d<"100"){return}$clear(a);if(typeof c=="function"){c()}}).periodical(50)}else{MUI.files[b]="loading";properties={onload:c!="undefined"?c:$empty};var e=properties.onload;properties.onload=function(){MUI.files[b]="loaded";if(e){e()}}.bind(this);switch(b.match(/\.\w+$/)[0]){case".js":return Asset.javascript(b,properties);case".css":return Asset.css(b,properties);case".jpg":case".png":case".gif":return Asset.image(b,properties)}alert('The required file "'+b+'" could not be loaded')}}}});$extend(Asset,{javascript:function(f,d){d=$extend({onload:$empty,document:document,check:$lambda(true)},d);if($(d.id)){d.onload();return $(d.id)}var b=new Element("script",{src:f,type:"text/javascript"});var e=d.onload.bind(b),a=d.check,g=d.document;delete d.onload;delete d.check;delete d.document;if(!Browser.Engine.webkit419&&!Browser.Engine.presto){b.addEvents({load:e,readystatechange:function(){if(MUI.ieLegacySupport&&["loaded","complete"].contains(this.readyState)){e()}}}).setProperties(d)}else{var c=(function(){if(!$try(a)){return}$clear(c);Browser.Engine.presto?e.delay(500):e()}).periodical(50)}return b.inject(g.head)},css:function(b,a){a=$extend({id:null,media:"screen",onload:$empty},a);new Request({method:"get",url:b,onComplete:function(c){var d=new Element("link",{id:a.id,rel:"stylesheet",media:a.media,type:"text/css",href:b}).inject(document.head);a.onload()}.bind(this),onFailure:function(c){},onSuccess:function(){}.bind(this)}).send()}});MUI.extend({newWindowsFromJSON:function(a){new MUI.Require({js:[MUI.path.source+"Window/Windows-from-json.js"],onload:function(){new MUI.newWindowsFromJSON(a)}})},arrangeCascade:function(){new MUI.Require({js:[MUI.path.source+"Window/Arrange-cascade.js"],onload:function(){new MUI.arrangeCascade()}})},arrangeTile:function(){new MUI.Require({js:[MUI.path.source+"Window/Arrange-tile.js"],onload:function(){new MUI.arrangeTile()}})},saveWorkspace:function(){new MUI.Require({js:[MUI.path.source+"Layout/Workspaces.js"],onload:function(){new MUI.saveWorkspace()}})},loadWorkspace:function(){new MUI.Require({js:[MUI.path.source+"Layout/Workspaces.js"],onload:function(){new MUI.loadWorkspace()}})},Themes:{init:function(a){new MUI.Require({js:[MUI.path.source+"Utilities/Themes.js"],onload:function(){MUI.Themes.init(a)}})}}});MUI.files[MUI.path.source+"Utilities/Themes.js"]=1;MUI.Themes={init:function(a){this.newTheme=a.toLowerCase();if(!this.newTheme||this.newTheme==null||this.newTheme==MUI.options.theme.toLowerCase()){return}if($("spinner")){$("spinner").show()}this.oldURIs=[];this.oldSheets=[];$$("link").each(function(c){var b=c.get("href");if(b.contains(MUI.path.themes+MUI.options.theme)){this.oldURIs.push(b);this.oldSheets.push(c)}}.bind(this));this.newSheetURLs=this.oldURIs.map(function(c,b){return c.replace("/"+MUI.options.theme+"/","/"+MUI.Themes.newTheme+"/")}.bind(this));this.sheetsToLoad=this.oldURIs.length;this.sheetsLoaded=0;this.newSheets=[];this.newSheetURLs.each(function(d){var b=d;var c=new Request({method:"get",url:b,onComplete:function(e){var f=new Element("link",{rel:"stylesheet",media:"screen",type:"text/css",href:b});this.newSheets.push(f)}.bind(this),onFailure:function(e){this.themeLoadSuccess=false;if($("spinner")){$("spinner").hide()}MUI.notification("Stylesheets did not load.")},onSuccess:function(){this.sheetsLoaded++;if(this.sheetsLoaded==this.sheetsToLoad){this.updateThemeStylesheets();this.themeLoadSuccess=true}}.bind(this)});c.send()}.bind(this))},updateThemeStylesheets:function(){this.oldSheets.each(function(a){a.destroy()});this.newSheets.each(function(a){MUI.files[a.get("href")]=1;a.inject(document.head)});if(MUI.ieLegacySupport){this.redraw.delay(1250,this)}else{this.redraw.delay(250,this)}},redraw:function(){$$(".replaced").removeClass("replaced");$$(".mocha").each(function(c){var b=c.retrieve("instance");b.setColors();b.drawWindow()});if(MUI.Dock){if(MUI.Dock.options.useControls){MUI.Dock.setDockColors();MUI.Dock.renderDockControls()}}if(MUI.Desktop.desktop){var a=(function(){if(MUI.Desktop.desktop.getStyle("overflow")!="hidden"){return}$clear(a);MUI.Desktop.setDesktopSize()}).periodical(50)}if($("spinner")){$("spinner").hide()}MUI.options.theme=this.newTheme}};window.addEvent("load",function(){if($("themeControl")){$("themeControl").getElements("option").setProperty("selected","false");if($("chooseTheme")){$("chooseTheme").setProperty("selected","true")}}});MUI.files[MUI.path.source+"Window/Window.js"]="loading";MUI.extend({Windows:{instances:new Hash(),indexLevel:100,windowIDCount:0,windowsVisible:true,focusingWindow:false}});MUI.Windows.windowOptions={id:null,title:"New Window",icon:false,type:"window",require:{css:[],images:[],js:[],onload:null},loadMethod:null,method:"get",contentURL:null,data:null,closeAfter:false,evalScripts:true,evalResponse:false,content:"Window content",toolbar:false,toolbarPosition:"top",toolbarHeight:29,toolbarURL:"pages/lipsum.html",toolbarData:null,toolbarContent:"",toolbarOnload:$empty,toolbar2:false,toolbar2Position:"bottom",toolbar2Height:29,toolbar2URL:"pages/lipsum.html",toolbar2Data:null,toolbar2Content:"",toolbar2Onload:$empty,container:null,restrict:true,shape:"box",collapsible:true,minimizable:true,maximizable:true,closable:true,storeOnClose:false,modalOverlayClose:true,draggable:null,draggableGrid:false,draggableLimit:false,draggableSnap:false,resizable:null,resizeLimit:{x:[250,2500],y:[125,2000]},addClass:"",width:300,height:125,headerHeight:25,footerHeight:25,cornerRadius:8,x:null,y:null,scrollbars:true,padding:{top:10,right:12,bottom:10,left:12},shadowBlur:5,shadowOffset:{x:0,y:1},controlsOffset:{right:6,top:6},useCanvas:true,useCanvasControls:true,useSpinner:true,headerStartColor:[250,250,250],headerStopColor:[229,229,229],bodyBgColor:[229,229,229],minimizeBgColor:[255,255,255],minimizeColor:[0,0,0],maximizeBgColor:[255,255,255],maximizeColor:[0,0,0],closeBgColor:[255,255,255],closeColor:[0,0,0],resizableColor:[254,254,254],onBeforeBuild:$empty,onContentLoaded:$empty,onFocus:$empty,onBlur:$empty,onResize:$empty,onMinimize:$empty,onMaximize:$empty,onRestore:$empty,onClose:$empty,onCloseComplete:$empty};MUI.Windows.windowOptionsOriginal=$merge(MUI.Windows.windowOptions);MUI.Window=new Class({Implements:[Events,Options],options:MUI.Windows.windowOptions,initialize:function(a){this.setOptions(a);var a=this.options;$extend(this,{mochaControlsWidth:0,minimizebuttonX:0,maximizebuttonX:0,closebuttonX:0,headerFooterShadow:a.headerHeight+a.footerHeight+(a.shadowBlur*2),oldTop:0,oldLeft:0,isMaximized:false,isMinimized:false,isCollapsed:false,timestamp:$time()});if(a.type!="window"){a.container=document.body;a.minimizable=false}if(!a.container){a.container=MUI.Desktop&&MUI.Desktop.desktop?MUI.Desktop.desktop:document.body}if(a.resizable==null){if(a.type!="window"||a.shape=="gauge"){a.resizable=false}else{a.resizable=true}}if(a.draggable==null){a.draggable=a.type!="window"?false:true}if(a.shape=="gauge"||a.type=="notification"){a.collapsible=false;a.maximizable=false;a.contentBgColor="transparent";a.scrollbars=false;a.footerHeight=0}if(a.type=="notification"){a.closable=false;a.headerHeight=0}if(MUI.Dock&&$(MUI.options.dock)){if(MUI.Dock.dock&&a.type!="modal"&&a.type!="modal2"){a.minimizable=a.minimizable}}else{a.minimizable=false}a.maximizable=MUI.Desktop&&MUI.Desktop.desktop&&a.maximizable&&a.type!="modal"&&a.type!="modal2";if(this.options.type=="modal2"){this.options.shadowBlur=0;this.options.shadowOffset={x:0,y:0};this.options.useSpinner=false;this.options.useCanvas=false;this.options.footerHeight=0;this.options.headerHeight=0}a.id=a.id||"win"+(++MUI.Windows.windowIDCount);this.windowEl=$(a.id);if(a.require.css.length||a.require.images.length){new MUI.Require({css:a.require.css,images:a.require.images,onload:function(){this.newWindow()}.bind(this)})}else{this.newWindow()}return this},saveValues:function(){var a=this.windowEl.getCoordinates();this.options.x=a.left.toInt();this.options.y=a.top.toInt()},newWindow:function(c){var a=MUI.Windows.instances;var j=MUI.Windows.instances.get(this.options.id);var k=this.options;if(j){var h=j}if(this.windowEl&&!this.isClosing){if(h.isMinimized){MUI.Dock.restoreMinimized(this.windowEl)}else{if(h.isCollapsed){MUI.collapseToggle(this.windowEl);setTimeout(MUI.focusWindow.pass(this.windowEl,this),10)}else{if(this.windowEl.hasClass("windowClosed")){if(h.check){h.check.show()}this.windowEl.removeClass("windowClosed");this.windowEl.setStyle("opacity",0);this.windowEl.addClass("mocha");if(MUI.Dock&&$(MUI.options.dock)&&h.options.type=="window"){var f=$(h.options.id+"_dockTab");if(f!=null){f.show()}MUI.Desktop.setDesktopSize()}h.displayNewWindow()}else{var g=document.getCoordinates();if(this.windowEl.getStyle("left").toInt()>g.width||this.windowEl.getStyle("top").toInt()>g.height){MUI.centerWindow(this.windowEl)}setTimeout(MUI.focusWindow.pass(this.windowEl,this),10);if(MUI.options.standardEffects==true){this.windowEl.shake()}}}}return}else{a.set(k.id,this)}this.isClosing=false;this.fireEvent("onBeforeBuild");MUI.Windows.indexLevel++;this.windowEl=new Element("div",{"class":"mocha",id:k.id,styles:{position:"absolute",width:k.width,height:k.height,display:"block",opacity:0,zIndex:MUI.Windows.indexLevel+=2}});this.windowEl.store("instance",this);this.windowEl.addClass(k.addClass);if(k.type=="modal2"){this.windowEl.addClass("modal2")}if(MUI.ieLegacySupport&&k.shape=="gauge"){this.windowEl.setStyle("backgroundImage","url(../images/skin/spacer.gif)")}if(k.loadMethod=="iframe"){k.padding={top:0,right:0,bottom:0,left:0}}this.insertWindowElements();this.titleEl.set("html",k.title);this.contentWrapperEl.setStyle("overflow","hidden");this.contentEl.setStyles({"padding-top":k.padding.top,"padding-bottom":k.padding.bottom,"padding-left":k.padding.left,"padding-right":k.padding.right});if(k.shape=="gauge"){if(k.useCanvasControls){this.canvasControlsEl.setStyle("visibility","hidden")}else{this.controlsEl.setStyle("visibility","hidden")}this.windowEl.addEvent("mouseover",function(){this.mouseover=true;var l=function(){if(this.mouseover!=false){if(k.useCanvasControls){this.canvasControlsEl.setStyle("visibility","visible")}else{this.controlsEl.setStyle("visibility","visible")}this.canvasHeaderEl.setStyle("visibility","visible");this.titleEl.show()}};l.delay(0,this)}.bind(this));this.windowEl.addEvent("mouseleave",function(){this.mouseover=false;if(this.options.useCanvasControls){this.canvasControlsEl.setStyle("visibility","hidden")}else{this.controlsEl.setStyle("visibility","hidden")}this.canvasHeaderEl.setStyle("visibility","hidden");this.titleEl.hide()}.bind(this))}this.windowEl.inject(k.container);this.setColors();if(k.type!="notification"){this.setMochaControlsWidth()}MUI.updateContent({element:this.windowEl,content:k.content,method:k.method,url:k.contentURL,data:k.data,onContentLoaded:null,require:{js:k.require.js,onload:k.require.onload}});if(this.options.toolbar==true){MUI.updateContent({element:this.windowEl,childElement:this.toolbarEl,content:k.toolbarContent,loadMethod:"xhr",method:k.method,url:k.toolbarURL,data:k.toolbarData,onContentLoaded:k.toolbarOnload})}if(this.options.toolbar2==true){MUI.updateContent({element:this.windowEl,childElement:this.toolbar2El,content:k.toolbar2Content,loadMethod:"xhr",method:k.method,url:k.toolbar2URL,data:k.toolbar2Data,onContentLoaded:k.toolbar2Onload})}this.drawWindow();this.attachDraggable();this.attachResizable();this.setupEvents();if(k.resizable){this.adjustHandles()}if(k.container==document.body||k.container==MUI.Desktop.desktop){var b=window.getSize()}else{var b=$(this.options.container).getSize()}if(!k.y){if(MUI.Desktop&&MUI.Desktop.desktop){var d=(b.y*0.5)-(this.windowEl.offsetHeight*0.5);if(d<-k.shadowBlur){d=-k.shadowBlur}}else{var d=window.getScroll().y+(window.getSize().y*0.5)-(this.windowEl.offsetHeight*0.5);if(d<-k.shadowBlur){d=-k.shadowBlur}}}else{var d=k.y-k.shadowBlur}if(!this.options.x){var e=(b.x*0.5)-(this.windowEl.offsetWidth*0.5);if(e<-k.shadowBlur){e=-k.shadowBlur}}else{var e=k.x-k.shadowBlur}this.windowEl.setStyles({top:d,left:e});this.opacityMorph=new Fx.Morph(this.windowEl,{duration:350,transition:Fx.Transitions.Sine.easeInOut,onComplete:function(){if(MUI.ieLegacySupport){this.drawWindow()}}.bind(this)});this.displayNewWindow();this.morph=new Fx.Morph(this.windowEl,{duration:200});this.windowEl.store("morph",this.morph);this.resizeMorph=new Fx.Elements([this.contentWrapperEl,this.windowEl],{duration:400,transition:Fx.Transitions.Sine.easeInOut,onStart:function(){this.resizeAnimation=this.drawWindow.periodical(20,this)}.bind(this),onComplete:function(){$clear(this.resizeAnimation);this.drawWindow();if(this.iframeEl){this.iframeEl.setStyle("visibility","visible")}}.bind(this)});this.windowEl.store("resizeMorph",this.resizeMorph);if($(this.windowEl.id+"LinkCheck")){this.check=new Element("div",{"class":"check",id:this.options.id+"_check"}).inject(this.windowEl.id+"LinkCheck")}if(this.options.closeAfter!=false){MUI.closeWindow.delay(this.options.closeAfter,this,this.windowEl)}if(MUI.Dock&&$(MUI.options.dock)&&this.options.type=="window"){MUI.Dock.createDockTab(this.windowEl)}},displayNewWindow:function(){options=this.options;if(options.type=="modal"||options.type=="modal2"){MUI.currentModal=this.windowEl;if(Browser.Engine.trident4){$("modalFix").show()}$("modalOverlay").show();if(MUI.options.advancedEffects==false){$("modalOverlay").setStyle("opacity",0.6);this.windowEl.setStyles({zIndex:11000,opacity:1})}else{MUI.Modal.modalOverlayCloseMorph.cancel();MUI.Modal.modalOverlayOpenMorph.start({opacity:0.6});this.windowEl.setStyles({zIndex:11000});this.opacityMorph.start({opacity:1})}$$(".dockTab").removeClass("activeDockTab");$$(".mocha").removeClass("isFocused");this.windowEl.addClass("isFocused")}else{if(MUI.options.advancedEffects==false){this.windowEl.setStyle("opacity",1);setTimeout(MUI.focusWindow.pass(this.windowEl,this),10)}else{if(MUI.ieLegacySupport){this.drawWindow(false)}this.opacityMorph.start({opacity:1});setTimeout(MUI.focusWindow.pass(this.windowEl,this),10)}}},setupEvents:function(){var a=this.windowEl;if(this.closeButtonEl){this.closeButtonEl.addEvent("click",function(b){new Event(b).stop();MUI.closeWindow(a)}.bind(this))}if(this.options.type=="window"){a.addEvent("mousedown",function(b){if(MUI.ieLegacySupport){new Event(b).stop()}MUI.focusWindow(a);if(a.getStyle("top").toInt()<-this.options.shadowBlur){a.setStyle("top",-this.options.shadowBlur)}}.bind(this))}if(this.minimizeButtonEl){this.minimizeButtonEl.addEvent("click",function(b){new Event(b).stop();MUI.Dock.minimizeWindow(a)}.bind(this))}if(this.maximizeButtonEl){this.maximizeButtonEl.addEvent("click",function(b){new Event(b).stop();if(this.isMaximized){MUI.Desktop.restoreWindow(a)}else{MUI.Desktop.maximizeWindow(a)}}.bind(this))}if(this.options.collapsible==true){this.titleEl.addEvent("selectstart",function(b){b=new Event(b).stop()}.bind(this));if(MUI.ieLegacySupport){this.titleBarEl.addEvent("mousedown",function(b){this.titleEl.setCapture()}.bind(this));this.titleBarEl.addEvent("mouseup",function(b){this.titleEl.releaseCapture()}.bind(this))}this.titleBarEl.addEvent("dblclick",function(b){b=new Event(b).stop();MUI.collapseToggle(this.windowEl)}.bind(this))}},attachDraggable:function(){var a=this.windowEl;if(!this.options.draggable){return}this.windowDrag=new Drag.Move(a,{handle:this.titleBarEl,container:this.options.restrict==true?$(this.options.container):false,grid:this.options.draggableGrid,limit:this.options.draggableLimit,snap:this.options.draggableSnap,onStart:function(){if(this.options.type!="modal"&&this.options.type!="modal2"){MUI.focusWindow(a);$("windowUnderlay").show()}if(this.iframeEl){if(!MUI.ieLegacySupport){this.iframeEl.setStyle("visibility","hidden")}else{this.iframeEl.hide()}}}.bind(this),onComplete:function(){if(this.options.type!="modal"&&this.options.type!="modal2"){$("windowUnderlay").hide()}if(this.iframeEl){if(!MUI.ieLegacySupport){this.iframeEl.setStyle("visibility","visible")}else{this.iframeEl.show()}}this.saveValues()}.bind(this)})},attachResizable:function(){var a=this.windowEl;if(!this.options.resizable){return}this.resizable1=this.windowEl.makeResizable({handle:[this.n,this.ne,this.nw],limit:{y:[function(){return this.windowEl.getStyle("top").toInt()+this.windowEl.getStyle("height").toInt()-this.options.resizeLimit.y[1]}.bind(this),function(){return this.windowEl.getStyle("top").toInt()+this.windowEl.getStyle("height").toInt()-this.options.resizeLimit.y[0]}.bind(this)]},modifiers:{x:false,y:"top"},onStart:function(){this.resizeOnStart();this.coords=this.contentWrapperEl.getCoordinates();this.y2=this.coords.top.toInt()+this.contentWrapperEl.offsetHeight}.bind(this),onDrag:function(){this.coords=this.contentWrapperEl.getCoordinates();this.contentWrapperEl.setStyle("height",this.y2-this.coords.top.toInt());this.resizeOnDrag()}.bind(this),onComplete:function(){this.resizeOnComplete()}.bind(this)});this.resizable2=this.contentWrapperEl.makeResizable({handle:[this.e,this.ne],limit:{x:[this.options.resizeLimit.x[0]-(this.options.shadowBlur*2),this.options.resizeLimit.x[1]-(this.options.shadowBlur*2)]},modifiers:{x:"width",y:false},onStart:function(){this.resizeOnStart()}.bind(this),onDrag:function(){this.resizeOnDrag()}.bind(this),onComplete:function(){this.resizeOnComplete()}.bind(this)});this.resizable3=this.contentWrapperEl.makeResizable({container:this.options.restrict==true?$(this.options.container):false,handle:this.se,limit:{x:[this.options.resizeLimit.x[0]-(this.options.shadowBlur*2),this.options.resizeLimit.x[1]-(this.options.shadowBlur*2)],y:[this.options.resizeLimit.y[0]-this.headerFooterShadow,this.options.resizeLimit.y[1]-this.headerFooterShadow]},modifiers:{x:"width",y:"height"},onStart:function(){this.resizeOnStart()}.bind(this),onDrag:function(){this.resizeOnDrag()}.bind(this),onComplete:function(){this.resizeOnComplete()}.bind(this)});this.resizable4=this.contentWrapperEl.makeResizable({handle:[this.s,this.sw],limit:{y:[this.options.resizeLimit.y[0]-this.headerFooterShadow,this.options.resizeLimit.y[1]-this.headerFooterShadow]},modifiers:{x:false,y:"height"},onStart:function(){this.resizeOnStart()}.bind(this),onDrag:function(){this.resizeOnDrag()}.bind(this),onComplete:function(){this.resizeOnComplete()}.bind(this)});this.resizable5=this.windowEl.makeResizable({handle:[this.w,this.sw,this.nw],limit:{x:[function(){return this.windowEl.getStyle("left").toInt()+this.windowEl.getStyle("width").toInt()-this.options.resizeLimit.x[1]}.bind(this),function(){return this.windowEl.getStyle("left").toInt()+this.windowEl.getStyle("width").toInt()-this.options.resizeLimit.x[0]}.bind(this)]},modifiers:{x:"left",y:false},onStart:function(){this.resizeOnStart();this.coords=this.contentWrapperEl.getCoordinates();this.x2=this.coords.left.toInt()+this.contentWrapperEl.offsetWidth}.bind(this),onDrag:function(){this.coords=this.contentWrapperEl.getCoordinates();this.contentWrapperEl.setStyle("width",this.x2-this.coords.left.toInt());this.resizeOnDrag()}.bind(this),onComplete:function(){this.resizeOnComplete()}.bind(this)})},resizeOnStart:function(){$("windowUnderlay").show();if(this.iframeEl){if(!MUI.ieLegacySupport){this.iframeEl.setStyle("visibility","hidden")}else{this.iframeEl.hide()}}},resizeOnDrag:function(){this.drawWindow();this.adjustHandles()},resizeOnComplete:function(){$("windowUnderlay").hide();if(this.iframeEl){if(!MUI.ieLegacySupport){this.iframeEl.setStyle("visibility","visible")}else{this.iframeEl.show();this.iframeEl.setStyle("width","99%");this.iframeEl.setStyle("height",this.contentWrapperEl.offsetHeight);this.iframeEl.setStyle("width","100%");this.iframeEl.setStyle("height",this.contentWrapperEl.offsetHeight)}}if(this.contentWrapperEl.getChildren(".column")!=null){MUI.rWidth(this.contentWrapperEl);this.contentWrapperEl.getChildren(".column").each(function(a){MUI.panelHeight(a)})}this.fireEvent("onResize",this.windowEl)},adjustHandles:function(){var d=this.options.shadowBlur;var j=d*2;var k=this.options.shadowOffset;var e=d-k.y-1;var g=d+k.x-1;var a=d+k.y-1;var c=d-k.x-1;var f=this.windowEl.getCoordinates();var b=f.width-j+2;var h=f.height-j+2;this.n.setStyles({top:e,left:c+10,width:b-20});this.e.setStyles({top:e+10,right:g,height:h-30});this.s.setStyles({bottom:a,left:c+10,width:b-30});this.w.setStyles({top:e+10,left:c,height:h-20});this.ne.setStyles({top:e,right:g});this.se.setStyles({bottom:a,right:g});this.sw.setStyles({bottom:a,left:c});this.nw.setStyles({top:e,left:c})},detachResizable:function(){this.resizable1.detach();this.resizable2.detach();this.resizable3.detach();this.resizable4.detach();this.resizable5.detach();this.windowEl.getElements(".handle").hide()},reattachResizable:function(){this.resizable1.attach();this.resizable2.attach();this.resizable3.attach();this.resizable4.attach();this.resizable5.attach();this.windowEl.getElements(".handle").show()},insertWindowElements:function(){var c=this.options;var a=c.height;var d=c.width;var e=c.id;var b={};if(Browser.Engine.trident4){b.zIndexFixEl=new Element("iframe",{id:e+"_zIndexFix","class":"zIndexFix",scrolling:"no",marginWidth:0,marginHeight:0,src:"",styles:{position:"absolute"}}).inject(this.windowEl)}b.overlayEl=new Element("div",{id:e+"_overlay","class":"mochaOverlay",styles:{position:"absolute",top:0,left:0}}).inject(this.windowEl);b.titleBarEl=new Element("div",{id:e+"_titleBar","class":"mochaTitlebar",styles:{cursor:c.draggable?"move":"default"}}).inject(b.overlayEl,"top");b.titleEl=new Element("h3",{id:e+"_title","class":"mochaTitle"}).inject(b.titleBarEl);if(c.icon!=false){b.titleEl.setStyles({"padding-left":28,background:"url("+c.icon+") 5px 4px no-repeat"})}b.contentBorderEl=new Element("div",{id:e+"_contentBorder","class":"mochaContentBorder"}).inject(b.overlayEl);if(c.toolbar){b.toolbarWrapperEl=new Element("div",{id:e+"_toolbarWrapper","class":"mochaToolbarWrapper",styles:{height:c.toolbarHeight}}).inject(b.contentBorderEl,c.toolbarPosition=="bottom"?"after":"before");if(c.toolbarPosition=="bottom"){b.toolbarWrapperEl.addClass("bottom")}b.toolbarEl=new Element("div",{id:e+"_toolbar","class":"mochaToolbar",styles:{height:c.toolbarHeight}}).inject(b.toolbarWrapperEl)}if(c.toolbar2){b.toolbar2WrapperEl=new Element("div",{id:e+"_toolbar2Wrapper","class":"mochaToolbarWrapper",styles:{height:c.toolbar2Height}}).inject(b.contentBorderEl,c.toolbar2Position=="bottom"?"after":"before");if(c.toolbar2Position=="bottom"){b.toolbar2WrapperEl.addClass("bottom")}b.toolbar2El=new Element("div",{id:e+"_toolbar2","class":"mochaToolbar",styles:{height:c.toolbar2Height}}).inject(b.toolbar2WrapperEl)}b.contentWrapperEl=new Element("div",{id:e+"_contentWrapper","class":"mochaContentWrapper",styles:{width:d+"px",height:a+"px"}}).inject(b.contentBorderEl);if(this.options.shape=="gauge"){b.contentBorderEl.setStyle("borderWidth",0)}b.contentEl=new Element("div",{id:e+"_content","class":"mochaContent"}).inject(b.contentWrapperEl);if(this.options.useCanvas==true&&!MUI.ieLegacySupport){b.canvasEl=new Element("canvas",{id:e+"_canvas","class":"mochaCanvas",width:10,height:10}).inject(this.windowEl)}if(this.options.useCanvas==true&&MUI.ieLegacySupport){b.canvasEl=new Element("canvas",{id:e+"_canvas","class":"mochaCanvas",width:50000,height:20000,styles:{position:"absolute",top:0,left:0}}).inject(this.windowEl);if(MUI.ieLegacySupport&&MUI.ieSupport=="excanvas"){G_vmlCanvasManager.initElement(b.canvasEl);b.canvasEl=this.windowEl.getElement(".mochaCanvas")}}b.controlsEl=new Element("div",{id:e+"_controls","class":"mochaControls"}).inject(b.overlayEl,"after");if(c.useCanvasControls==true){b.canvasControlsEl=new Element("canvas",{id:e+"_canvasControls","class":"mochaCanvasControls",width:14,height:14}).inject(this.windowEl);if(MUI.ieLegacySupport&&MUI.ieSupport=="excanvas"){G_vmlCanvasManager.initElement(b.canvasControlsEl);b.canvasControlsEl=this.windowEl.getElement(".mochaCanvasControls")}}if(c.closable){b.closeButtonEl=new Element("div",{id:e+"_closeButton","class":"mochaCloseButton mochaWindowButton",title:"Close"}).inject(b.controlsEl)}if(c.maximizable){b.maximizeButtonEl=new Element("div",{id:e+"_maximizeButton","class":"mochaMaximizeButton mochaWindowButton",title:"Maximize"}).inject(b.controlsEl)}if(c.minimizable){b.minimizeButtonEl=new Element("div",{id:e+"_minimizeButton","class":"mochaMinimizeButton mochaWindowButton",title:"Minimize"}).inject(b.controlsEl)}if(c.useSpinner==true&&c.shape!="gauge"&&c.type!="notification"){b.spinnerEl=new Element("div",{id:e+"_spinner","class":"mochaSpinner",width:16,height:16}).inject(this.windowEl,"bottom")}if(this.options.shape=="gauge"){b.canvasHeaderEl=new Element("canvas",{id:e+"_canvasHeader","class":"mochaCanvasHeader",width:this.options.width,height:26}).inject(this.windowEl,"bottom");if(MUI.ieLegacySupport&&MUI.ieSupport=="excanvas"){G_vmlCanvasManager.initElement(b.canvasHeaderEl);b.canvasHeaderEl=this.windowEl.getElement(".mochaCanvasHeader")}}if(MUI.ieLegacySupport){b.overlayEl.setStyle("zIndex",2)}if(c.resizable){b.n=new Element("div",{id:e+"_resizeHandle_n","class":"handle",styles:{top:0,left:10,cursor:"n-resize"}}).inject(b.overlayEl,"after");b.ne=new Element("div",{id:e+"_resizeHandle_ne","class":"handle corner",styles:{top:0,right:0,cursor:"ne-resize"}}).inject(b.overlayEl,"after");b.e=new Element("div",{id:e+"_resizeHandle_e","class":"handle",styles:{top:10,right:0,cursor:"e-resize"}}).inject(b.overlayEl,"after");b.se=new Element("div",{id:e+"_resizeHandle_se","class":"handle cornerSE",styles:{bottom:0,right:0,cursor:"se-resize"}}).inject(b.overlayEl,"after");b.s=new Element("div",{id:e+"_resizeHandle_s","class":"handle",styles:{bottom:0,left:10,cursor:"s-resize"}}).inject(b.overlayEl,"after");b.sw=new Element("div",{id:e+"_resizeHandle_sw","class":"handle corner",styles:{bottom:0,left:0,cursor:"sw-resize"}}).inject(b.overlayEl,"after");b.w=new Element("div",{id:e+"_resizeHandle_w","class":"handle",styles:{top:10,left:0,cursor:"w-resize"}}).inject(b.overlayEl,"after");b.nw=new Element("div",{id:e+"_resizeHandle_nw","class":"handle corner",styles:{top:0,left:0,cursor:"nw-resize"}}).inject(b.overlayEl,"after")}$extend(this,b)},setColors:function(){if(this.options.useCanvas==true){var c=/\?(.*?)\)/;if(this.titleBarEl.getStyle("backgroundImage")!="none"){var d=this.titleBarEl.getStyle("backgroundImage");d=d.match(c)[1];d=d.parseQueryString();var a=d.from;var b=d.to.replace(/\"/,"");this.options.headerStartColor=new Color(a);this.options.headerStopColor=new Color(b);this.titleBarEl.addClass("replaced")}else{if(this.titleBarEl.getStyle("background-color")!==""&&this.titleBarEl.getStyle("background-color")!=="transparent"){this.options.headerStartColor=new Color(this.titleBarEl.getStyle("background-color")).mix("#fff",20);this.options.headerStopColor=new Color(this.titleBarEl.getStyle("background-color")).mix("#000",20);this.titleBarEl.addClass("replaced")}}if(this.windowEl.getStyle("background-color")!==""&&this.windowEl.getStyle("background-color")!=="transparent"){this.options.bodyBgColor=new Color(this.windowEl.getStyle("background-color"));this.windowEl.addClass("replaced")}if(this.options.resizable&&this.se.getStyle("background-color")!==""&&this.se.getStyle("background-color")!=="transparent"){this.options.resizableColor=new Color(this.se.getStyle("background-color"));this.se.addClass("replaced")}}if(this.options.useCanvasControls==true){if(this.minimizeButtonEl){if(this.minimizeButtonEl.getStyle("color")!==""&&this.minimizeButtonEl.getStyle("color")!=="transparent"){this.options.minimizeColor=new Color(this.minimizeButtonEl.getStyle("color"))}if(this.minimizeButtonEl.getStyle("background-color")!==""&&this.minimizeButtonEl.getStyle("background-color")!=="transparent"){this.options.minimizeBgColor=new Color(this.minimizeButtonEl.getStyle("background-color"));this.minimizeButtonEl.addClass("replaced")}}if(this.maximizeButtonEl){if(this.maximizeButtonEl.getStyle("color")!==""&&this.maximizeButtonEl.getStyle("color")!=="transparent"){this.options.maximizeColor=new Color(this.maximizeButtonEl.getStyle("color"))}if(this.maximizeButtonEl.getStyle("background-color")!==""&&this.maximizeButtonEl.getStyle("background-color")!=="transparent"){this.options.maximizeBgColor=new Color(this.maximizeButtonEl.getStyle("background-color"));this.maximizeButtonEl.addClass("replaced")}}if(this.closeButtonEl){if(this.closeButtonEl.getStyle("color")!==""&&this.closeButtonEl.getStyle("color")!=="transparent"){this.options.closeColor=new Color(this.closeButtonEl.getStyle("color"))}if(this.closeButtonEl.getStyle("background-color")!==""&&this.closeButtonEl.getStyle("background-color")!=="transparent"){this.options.closeBgColor=new Color(this.closeButtonEl.getStyle("background-color"));this.closeButtonEl.addClass("replaced")}}}},drawWindow:function(b){if(this.drawingWindow==true){return}this.drawingWindow=true;if(this.isCollapsed){this.drawWindowCollapsed(b);return}var g=this.windowEl;var m=this.options;var c=m.shadowBlur;var j=c*2;var l=this.options.shadowOffset;this.overlayEl.setStyles({width:this.contentWrapperEl.offsetWidth});if(this.iframeEl){this.iframeEl.setStyle("height",this.contentWrapperEl.offsetHeight)}var d=this.contentBorderEl.getStyle("margin-top").toInt()+this.contentBorderEl.getStyle("margin-bottom").toInt();var f=this.toolbarWrapperEl?this.toolbarWrapperEl.getStyle("height").toInt()+this.toolbarWrapperEl.getStyle("margin-top").toInt():0;var e=this.toolbar2WrapperEl?this.toolbar2WrapperEl.getStyle("height").toInt()+this.toolbar2WrapperEl.getStyle("margin-top").toInt():0;this.headerFooterShadow=m.headerHeight+m.footerHeight+j;var h=this.contentWrapperEl.getStyle("height").toInt()+this.headerFooterShadow+f+e+d;var a=this.contentWrapperEl.getStyle("width").toInt()+j;this.windowEl.setStyles({height:h,width:a});this.overlayEl.setStyles({height:h,top:c-l.y,left:c-l.x});if(this.options.useCanvas==true){if(MUI.ieLegacySupport){this.canvasEl.height=20000;this.canvasEl.width=50000}this.canvasEl.height=h;this.canvasEl.width=a}if(Browser.Engine.trident4){this.zIndexFixEl.setStyles({width:a,height:h})}this.titleBarEl.setStyles({width:a-j,height:m.headerHeight});if(m.useSpinner==true&&m.shape!="gauge"&&m.type!="notification"){this.spinnerEl.setStyles({left:c-l.x+3,bottom:c+l.y+4})}if(this.options.useCanvas!=false){var k=this.canvasEl.getContext("2d");k.clearRect(0,0,a,h);switch(m.shape){case"box":this.drawBox(k,a,h,c,l,b);break;case"gauge":this.drawGauge(k,a,h,c,l,b);break}if(m.resizable){MUI.triangle(k,a-(c+l.x+17),h-(c+l.y+18),11,11,m.resizableColor,1)}if(MUI.ieLegacySupport){MUI.triangle(k,0,0,10,10,m.resizableColor,0)}}if(m.type!="notification"&&m.useCanvasControls==true){this.drawControls(a,h,b)}if(MUI.Desktop&&this.contentWrapperEl.getChildren(".column").length!=0){MUI.rWidth(this.contentWrapperEl);this.contentWrapperEl.getChildren(".column").each(function(n){MUI.panelHeight(n)})}this.drawingWindow=false;return this},drawWindowCollapsed:function(b){var e=this.windowEl;var k=this.options;var c=k.shadowBlur;var f=c*2;var j=k.shadowOffset;var d=k.headerHeight+f+2;var g=d;var a=this.contentWrapperEl.getStyle("width").toInt()+f;this.windowEl.setStyle("height",g);this.overlayEl.setStyles({height:g,top:c-j.y,left:c-j.x});if(Browser.Engine.trident4){this.zIndexFixEl.setStyles({width:a,height:g})}this.windowEl.setStyle("width",a);this.overlayEl.setStyle("width",a);this.titleBarEl.setStyles({width:a-f,height:k.headerHeight});if(this.options.useCanvas!=false){this.canvasEl.height=g;this.canvasEl.width=a;var h=this.canvasEl.getContext("2d");h.clearRect(0,0,a,g);this.drawBoxCollapsed(h,a,g,c,j,b);if(k.useCanvasControls==true){this.drawControls(a,g,b)}if(MUI.ieLegacySupport){MUI.triangle(h,0,0,10,10,k.resizableColor,0)}}this.drawingWindow=false;return this},drawControls:function(g,e,h){var f=this.options;var d=f.shadowBlur;var c=f.shadowOffset;var b=f.controlsOffset;this.controlsEl.setStyles({right:d+c.x+b.right,top:d-c.y+b.top});this.canvasControlsEl.setStyles({right:d+c.x+b.right,top:d-c.y+b.top});this.closebuttonX=f.closable?this.mochaControlsWidth-7:this.mochaControlsWidth+12;this.maximizebuttonX=this.closebuttonX-(f.maximizable?19:0);this.minimizebuttonX=this.maximizebuttonX-(f.minimizable?19:0);var a=this.canvasControlsEl.getContext("2d");a.clearRect(0,0,100,100);if(this.options.closable){this.closebutton(a,this.closebuttonX,7,f.closeBgColor,1,f.closeColor,1)}if(this.options.maximizable){this.maximizebutton(a,this.maximizebuttonX,7,f.maximizeBgColor,1,f.maximizeColor,1)}if(this.options.minimizable){this.minimizebutton(a,this.minimizebuttonX,7,f.minimizeBgColor,1,f.minimizeColor,1)}if(MUI.ieLegacySupport){MUI.circle(a,0,0,3,this.options.resizableColor,0)}},drawBox:function(h,a,g,c,j,b){var k=this.options;var f=c*2;var d=this.options.cornerRadius;if(b!=false){for(var e=0;e<=c;e++){MUI.roundedRect(h,j.x+e,j.y+e,a-(e*2)-j.x,g-(e*2)-j.y,d+(c-e),[0,0,0],e==c?0.29:0.065+(e*0.01))}}this.bodyRoundedRect(h,c-j.x,c-j.y,a-f,g-f,d,k.bodyBgColor);if(this.options.type!="notification"){this.topRoundedRect(h,c-j.x,c-j.y,a-f,k.headerHeight,d,k.headerStartColor,k.headerStopColor)}},drawBoxCollapsed:function(h,a,g,c,j,b){var k=this.options;var f=c*2;var d=k.cornerRadius;if(b!=false){for(var e=0;e<=c;e++){MUI.roundedRect(h,j.x+e,j.y+e,a-(e*2)-j.x,g-(e*2)-j.y,d+(c-e),[0,0,0],e==c?0.3:0.06+(e*0.01))}}this.topRoundedRect2(h,c-j.x,c-j.y,a-f,k.headerHeight+2,d,k.headerStartColor,k.headerStopColor)},drawGauge:function(g,a,f,c,h,b){var j=this.options;var d=(a*0.5)-(c)+16;if(b!=false){for(var e=0;e<=c;e++){MUI.circle(g,a*0.5+h.x,(f+j.headerHeight)*0.5+h.x,(a*0.5)-(e*2)-h.x,[0,0,0],e==c?0.75:0.075+(e*0.04))}}MUI.circle(g,a*0.5-h.x,(f+j.headerHeight)*0.5-h.y,(a*0.5)-c,j.bodyBgColor,1);this.canvasHeaderEl.setStyles({top:c-h.y,left:c-h.x});var g=this.canvasHeaderEl.getContext("2d");g.clearRect(0,0,a,100);g.beginPath();g.lineWidth=24;g.lineCap="round";g.moveTo(13,13);g.lineTo(a-(c*2)-13,13);g.strokeStyle="rgba(0, 0, 0, .65)";g.stroke()},bodyRoundedRect:function(d,c,g,f,b,a,e){d.fillStyle="rgba("+e.join(",")+", 1)";d.beginPath();d.moveTo(c,g+a);d.lineTo(c,g+b-a);d.quadraticCurveTo(c,g+b,c+a,g+b);d.lineTo(c+f-a,g+b);d.quadraticCurveTo(c+f,g+b,c+f,g+b-a);d.lineTo(c+f,g+a);d.quadraticCurveTo(c+f,g,c+f-a,g);d.lineTo(c+a,g);d.quadraticCurveTo(c,g,c,g+a);d.fill()},topRoundedRect:function(j,g,f,a,h,e,c,d){var b=j.createLinearGradient(0,0,0,h);b.addColorStop(0,"rgb("+c.join(",")+")");b.addColorStop(1,"rgb("+d.join(",")+")");j.fillStyle=b;j.beginPath();j.moveTo(g,f);j.lineTo(g,f+h);j.lineTo(g+a,f+h);j.lineTo(g+a,f+e);j.quadraticCurveTo(g+a,f,g+a-e,f);j.lineTo(g+e,f);j.quadraticCurveTo(g,f,g,f+e);j.fill()},topRoundedRect2:function(j,g,f,a,h,e,c,d){if(navigator.userAgent.toLowerCase().indexOf("chrome")>-1){j.fillStyle="rgba("+d.join(",")+", 1)"}else{var b=j.createLinearGradient(0,this.options.shadowBlur-1,0,h+this.options.shadowBlur+3);b.addColorStop(0,"rgb("+c.join(",")+")");b.addColorStop(1,"rgb("+d.join(",")+")");j.fillStyle=b}j.beginPath();j.moveTo(g,f+e);j.lineTo(g,f+h-e);j.quadraticCurveTo(g,f+h,g+e,f+h);j.lineTo(g+a-e,f+h);j.quadraticCurveTo(g+a,f+h,g+a,f+h-e);j.lineTo(g+a,f+e);j.quadraticCurveTo(g+a,f,g+a-e,f);j.lineTo(g+e,f);j.quadraticCurveTo(g,f,g,f+e);j.fill()},maximizebutton:function(e,c,h,b,g,f,d){e.beginPath();e.arc(c,h,7,0,Math.PI*2,true);e.fillStyle="rgba("+b.join(",")+","+g+")";e.fill();e.strokeStyle="rgba("+f.join(",")+","+d+")";e.lineWidth=2;e.beginPath();e.moveTo(c,h-3.5);e.lineTo(c,h+3.5);e.moveTo(c-3.5,h);e.lineTo(c+3.5,h);e.stroke()},closebutton:function(e,c,h,b,g,f,d){e.beginPath();e.arc(c,h,7,0,Math.PI*2,true);e.fillStyle="rgba("+b.join(",")+","+g+")";e.fill();e.strokeStyle="rgba("+f.join(",")+","+d+")";e.lineWidth=2;e.beginPath();e.moveTo(c-3,h-3);e.lineTo(c+3,h+3);e.moveTo(c+3,h-3);e.lineTo(c-3,h+3);e.stroke()},minimizebutton:function(e,c,h,b,g,f,d){e.beginPath();e.arc(c,h,7,0,Math.PI*2,true);e.fillStyle="rgba("+b.join(",")+","+g+")";e.fill();e.strokeStyle="rgba("+f.join(",")+","+d+")";e.lineWidth=2;e.beginPath();e.moveTo(c-3.5,h);e.lineTo(c+3.5,h);e.stroke()},setMochaControlsWidth:function(){this.mochaControlsWidth=0;var a=this.options;if(a.minimizable){this.mochaControlsWidth+=(this.minimizeButtonEl.getStyle("margin-left").toInt()+this.minimizeButtonEl.getStyle("width").toInt())}if(a.maximizable){this.mochaControlsWidth+=(this.maximizeButtonEl.getStyle("margin-left").toInt()+this.maximizeButtonEl.getStyle("width").toInt())}if(a.closable){this.mochaControlsWidth+=(this.closeButtonEl.getStyle("margin-left").toInt()+this.closeButtonEl.getStyle("width").toInt())}this.controlsEl.setStyle("width",this.mochaControlsWidth);if(a.useCanvasControls==true){this.canvasControlsEl.setProperty("width",this.mochaControlsWidth)}},hideSpinner:function(){if(this.spinnerEl){this.spinnerEl.hide()}return this},showSpinner:function(){if(this.spinnerEl){this.spinnerEl.show()}return this},close:function(){if(!this.isClosing){MUI.closeWindow(this.windowEl)}return this},minimize:function(){MUI.Dock.minimizeWindow(this.windowEl);return this},maximize:function(){if(this.isMinimized){MUI.Dock.restoreMinimized(this.windowEl)}MUI.Desktop.maximizeWindow(this.windowEl);return this},restore:function(){if(this.isMinimized){MUI.Dock.restoreMinimized(this.windowEl)}else{if(this.isMaximized){MUI.Desktop.restoreWindow(this.windowEl)}}return this},resize:function(a){MUI.resizeWindow(this.windowEl,a);return this},center:function(){MUI.centerWindow(this.windowEl);return this},hide:function(){this.windowEl.setStyle("display","none");return this},show:function(){this.windowEl.setStyle("display","block");return this}});MUI.extend({closeWindow:function(c){var a=c.retrieve("instance");if(c!=$(c)||a.isClosing){return}a.isClosing=true;a.fireEvent("onClose",c);if(a.options.storeOnClose){this.storeOnClose(a,c);return}if(a.check){a.check.destroy()}if((a.options.type=="modal"||a.options.type=="modal2")&&Browser.Engine.trident4){$("modalFix").hide()}if(MUI.options.advancedEffects==false){if(a.options.type=="modal"||a.options.type=="modal2"){$("modalOverlay").setStyle("opacity",0)}MUI.closingJobs(c);return true}else{if(MUI.ieLegacySupport){a.drawWindow(false)}if(a.options.type=="modal"||a.options.type=="modal2"){MUI.Modal.modalOverlayCloseMorph.start({opacity:0})}var b=new Fx.Morph(c,{duration:120,onComplete:function(){MUI.closingJobs(c);return true}.bind(this)});b.start({opacity:0.4})}},closingJobs:function(e){var d=MUI.Windows.instances;var a=d.get(e.id);e.setStyle("visibility","hidden");if(MUI.ieLegacySupport){e.dispose()}else{e.destroy()}a.fireEvent("onCloseComplete");if(a.options.type!="notification"){var c=this.getWindowWithHighestZindex();this.focusWindow(c)}d.erase(a.options.id);if(this.loadingWorkspace==true){this.windowUnload()}if(MUI.Dock&&$(MUI.options.dock)&&a.options.type=="window"){var b=$(a.options.id+"_dockTab");if(b!=null){MUI.Dock.dockSortables.removeItems(b).destroy()}MUI.Desktop.setDesktopSize()}},storeOnClose:function(a,d){if(a.check){a.check.hide()}d.setStyles({zIndex:-1});d.addClass("windowClosed");d.removeClass("mocha");if(MUI.Dock&&$(MUI.options.dock)&&a.options.type=="window"){var c=$(a.options.id+"_dockTab");if(c!=null){c.hide()}MUI.Desktop.setDesktopSize()}a.fireEvent("onCloseComplete");if(a.options.type!="notification"){var b=this.getWindowWithHighestZindex();this.focusWindow(b)}a.isClosing=false},closeAll:function(){$$(".mocha").each(function(a){this.closeWindow(a)}.bind(this))},collapseToggle:function(c){var a=c.retrieve("instance");var b=c.getElements(".handle");if(a.isMaximized==true){return}if(a.isCollapsed==false){a.isCollapsed=true;b.hide();if(a.iframeEl){a.iframeEl.setStyle("visibility","hidden")}a.contentBorderEl.setStyles({visibility:"hidden",position:"absolute",top:-10000,left:-10000});if(a.toolbarWrapperEl){a.toolbarWrapperEl.setStyles({visibility:"hidden",position:"absolute",top:-10000,left:-10000})}a.drawWindowCollapsed()}else{a.isCollapsed=false;a.drawWindow();a.contentBorderEl.setStyles({visibility:"visible",position:null,top:null,left:null});if(a.toolbarWrapperEl){a.toolbarWrapperEl.setStyles({visibility:"visible",position:null,top:null,left:null})}if(a.iframeEl){a.iframeEl.setStyle("visibility","visible")}b.show()}},toggleWindowVisibility:function(){MUI.Windows.instances.each(function(a){if(a.options.type=="modal"||a.options.type=="modal2"||a.isMinimized==true){return}var b=$(a.options.id);if(b.getStyle("visibility")=="visible"){if(a.iframe){a.iframeEl.setStyle("visibility","hidden")}if(a.toolbarEl){a.toolbarWrapperEl.setStyle("visibility","hidden")}a.contentBorderEl.setStyle("visibility","hidden");b.setStyle("visibility","hidden");MUI.Windows.windowsVisible=false}else{b.setStyle("visibility","visible");a.contentBorderEl.setStyle("visibility","visible");if(a.iframe){a.iframeEl.setStyle("visibility","visible")}if(a.toolbarEl){a.toolbarWrapperEl.setStyle("visibility","visible")}MUI.Windows.windowsVisible=true}}.bind(this))},focusWindow:function(e,c){MUI.Windows.focusingWindow=true;var b=function(){MUI.Windows.focusingWindow=false};b.delay(170,this);if($$(".mocha").length==0){return}if(e!=$(e)||e.hasClass("isFocused")){return}var d=MUI.Windows.instances;var a=d.get(e.id);if(a.options.type=="notification"){e.setStyle("zIndex",11001);return}MUI.Windows.indexLevel+=2;e.setStyle("zIndex",MUI.Windows.indexLevel);$("windowUnderlay").setStyle("zIndex",MUI.Windows.indexLevel-1).inject($(e),"after");d.each(function(f){if(f.windowEl.hasClass("isFocused")){f.fireEvent("onBlur",f.windowEl)}f.windowEl.removeClass("isFocused")});if(MUI.Dock&&$(MUI.options.dock)&&a.options.type=="window"){MUI.Dock.makeActiveTab()}e.addClass("isFocused");if(c!=false){a.fireEvent("onFocus",e)}},getWindowWithHighestZindex:function(){this.highestZindex=0;$$(".mocha").each(function(a){this.zIndex=a.getStyle("zIndex");if(this.zIndex>=this.highestZindex){this.highestZindex=this.zIndex}}.bind(this));$$(".mocha").each(function(a){if(a.getStyle("zIndex")==this.highestZindex){this.windowWithHighestZindex=a}}.bind(this));return this.windowWithHighestZindex},blurAll:function(){if(MUI.Windows.focusingWindow==false){$$(".mocha").each(function(b){var a=b.retrieve("instance");if(a.options.type!="modal"&&a.options.type!="modal2"){b.removeClass("isFocused")}});$$(".dockTab").removeClass("activeDockTab")}},centerWindow:function(f){if(!f){MUI.Windows.instances.each(function(g){if(g.windowEl.hasClass("isFocused")){f=g.windowEl}})}var a=f.retrieve("instance");var b=a.options;var d=b.container.getCoordinates();var c=window.getScroll().y+(window.getSize().y*0.5)-(f.offsetHeight*0.5);if(c<-a.options.shadowBlur){c=-a.options.shadowBlur}var e=(d.width*0.5)-(f.offsetWidth*0.5);if(e<-a.options.shadowBlur){e=-a.options.shadowBlur}if(MUI.options.advancedEffects==true){a.morph.start({top:c,left:e})}else{f.setStyles({top:c,left:e})}},resizeWindow:function(f,j){var g=f.retrieve("instance");$extend({width:null,height:null,top:null,left:null,centered:true},j);var c=f.getStyle("width").toInt();var h=f.getStyle("height").toInt();var d=f.getStyle("top").toInt();var b=f.getStyle("left").toInt();if(j.centered){var e=j.top||d-((j.height-h)*0.5);var a=j.left||b-((j.width-c)*0.5)}else{var e=j.top||d;var a=j.left||b}if(MUI.options.advancedEffects==false){f.setStyles({top:e,left:a});g.contentWrapperEl.setStyles({height:j.height,width:j.width});g.drawWindow();if(g.iframeEl){if(!MUI.ieLegacySupport){g.iframeEl.setStyle("visibility","visible")}else{g.iframeEl.show()}}}else{f.retrieve("resizeMorph").start({"0":{height:j.height,width:j.width},"1":{top:e,left:a}})}return g},dynamicResize:function(d){var a=d.retrieve("instance");var c=a.contentWrapperEl;var b=a.contentEl;c.setStyles({height:b.offsetHeight,width:b.offsetWidth});a.drawWindow()}});document.addEvent("keydown",function(a){if(a.key=="q"&&a.control&&a.alt){MUI.toggleWindowVisibility()}});MUI.files[MUI.path.source+"Window/Modal.js"]="loaded";MUI.Modal=new Class({Extends:MUI.Window,options:{type:"modal"},initialize:function(a){if(!$("modalOverlay")){this.modalInitialize();window.addEvent("resize",function(){this.setModalSize()}.bind(this))}this.parent(a)},modalInitialize:function(){var a=new Element("div",{id:"modalOverlay",styles:{height:document.getCoordinates().height,opacity:0.6}}).inject(document.body);a.setStyles({position:Browser.Engine.trident4?"absolute":"fixed"});a.addEvent("click",function(d){var c=MUI.Windows.instances.get(MUI.currentModal.id);if(c.options.modalOverlayClose==true){MUI.closeWindow(MUI.currentModal)}});if(Browser.Engine.trident4){var b=new Element("iframe",{id:"modalFix",scrolling:"no",marginWidth:0,marginHeight:0,src:"",styles:{height:document.getCoordinates().height}}).inject(document.body)}MUI.Modal.modalOverlayOpenMorph=new Fx.Morph($("modalOverlay"),{duration:150});MUI.Modal.modalOverlayCloseMorph=new Fx.Morph($("modalOverlay"),{duration:150,onComplete:function(){$("modalOverlay").hide();if(Browser.Engine.trident4){$("modalFix").hide()}}.bind(this)})},setModalSize:function(){$("modalOverlay").setStyle("height",document.getCoordinates().height);if(Browser.Engine.trident4){$("modalFix").setStyle("height",document.getCoordinates().height)}}});MUI.files[MUI.path.source+"Window/Windows-from-html.js"]="loaded";MUI.extend({NewWindowsFromHTML:function(){$$(".mocha").each(function(b){if(Browser.Engine.presto||Browser.Engine.trident5){b.hide()}var d=b.getElement("h3.mochaTitle");if(Browser.Engine.presto){b.show()}var c=b.getStyles("height","width");var a={id:b.getProperty("id"),height:c.height.toInt(),width:c.width.toInt(),x:b.getStyle("left").toInt(),y:b.getStyle("top").toInt()};if(d){a.title=d.innerHTML;d.destroy()}a.content=b.innerHTML;b.destroy();new MUI.Window(a,true)}.bind(this))}});MUI.files[MUI.path.source+"Window/Windows-from-json.js"]="loaded";MUI.extend({newWindowsFromJSON:function(newWindows){newWindows.each(function(options){var temp=new Hash(options);temp.each(function(value,key,hash){if($type(value)!="string"){return}if(value.substring(0,8)=="function"){eval("options."+key+" = "+value)}});new MUI.Window(options)})}});MUI.files[MUI.path.source+"Window/Arrange-cascade.js"]="loaded";MUI.extend({arrangeCascade:function(){var g=30;var a=20;var k=50;var c=40;var j=document.getCoordinates();var d=0;MUI.Windows.instances.each(function(l){if(!l.isMinimized&&l.options.draggable){d++}});if((k*(d+1))>=(j.height-g)){var e=(j.height-g)/(d+1)}else{var e=k}if((c*(d+1))>=(j.width-a-20)){var b=(j.width-a-20)/(d+1)}else{var b=c}var h=a;var f=g;$$(".mocha").each(function(n){var l=n.retrieve("instance");if(!l.isMinimized&&!l.isMaximized&&l.options.draggable){id=n.id;MUI.focusWindow(n);h+=b;f+=e;if(MUI.options.advancedEffects==false){n.setStyles({top:f,left:h})}else{var m=new Fx.Morph(n,{duration:550});m.start({top:f,left:h})}}}.bind(this))}});MUI.files[MUI.path.source+"Window/Arrange-tile.js"]="loaded";MUI.extend({arrangeTile:function(){var g=30;var b=20;var j=10;var f=80;var a=MUI.Windows.instances;var l=0;a.each(function(o){if(!o.isMinimized&&!o.isMaximized){l++}});var h=3;var n=Math.ceil(l/h);var k=document.getCoordinates();var e=((k.width-b)/h);var d=((k.height-g)/n);var m=0;var c=0;a.each(function(x){if(!x.isMinimized&&!x.isMaximized&&x.options.draggable){var t=x.contentWrapperEl;var o=t.getCoordinates();var w=x.windowEl.getCoordinates();var s=o.top-w.top;var v=w.height-o.height-s;var r=o.left-w.left;var y=w.width-o.width-r;var p=(j+(c*e));var u=(f+(m*d));x.drawWindow();MUI.focusWindow(x.windowEl);if(MUI.options.advancedEffects==false){x.windowEl.setStyles({top:u,left:p})}else{var q=new Fx.Morph(x.windowEl,{duration:550});q.start({top:u,left:p})}if(++c===h){m++;c=0}}}.bind(this))}});MUI.files[MUI.path.source+"Components/Tabs.js"]="loaded";MUI.extend({initializeTabs:function(a){$(a).setStyle("list-style","none");$(a).getElements("li").addEvent("click",function(b){MUI.selected(this,a)})},selected:function(b,a){$(a).getChildren().each(function(c){c.removeClass("selected")});b.addClass("selected")}});MUI.files[MUI.path.source+"Layout/Layout.js"]="loaded";MUI.extend({Columns:{instances:new Hash(),columnIDCount:0},Panels:{instances:new Hash(),panelIDCount:0}});MUI.Desktop={options:{desktop:"desktop",desktopHeader:"desktopHeader",desktopFooter:"desktopFooter",desktopNavBar:"desktopNavbar",pageWrapper:"pageWrapper",page:"page",desktopFooter:"desktopFooterWrapper"},initialize:function(){this.desktop=$(this.options.desktop);this.desktopHeader=$(this.options.desktopHeader);this.desktopNavBar=$(this.options.desktopNavBar);this.pageWrapper=$(this.options.pageWrapper);this.page=$(this.options.page);this.desktopFooter=$(this.options.desktopFooter);if(this.desktop){($$("body")).setStyles({overflow:"hidden",height:"100%",margin:0});($$("html")).setStyles({overflow:"hidden",height:"100%"})}if(!MUI.Dock){this.setDesktopSize()}this.menuInitialize();window.addEvent("resize",function(a){this.onBrowserResize()}.bind(this));if(MUI.myChain){MUI.myChain.callChain()}},menuInitialize:function(){if(Browser.Engine.trident4&&this.desktopNavBar){this.desktopNavBar.getElements("li").each(function(a){a.addEvent("mouseenter",function(){this.addClass("ieHover")});a.addEvent("mouseleave",function(){this.removeClass("ieHover")})})}},onBrowserResize:function(){this.setDesktopSize();setTimeout(function(){MUI.Windows.instances.each(function(a){if(a.isMaximized){if(a.iframeEl){a.iframeEl.setStyle("visibility","hidden")}var d=document.getCoordinates();var b=a.contentBorderEl.getStyle("margin-top").toInt()+a.contentBorderEl.getStyle("margin-bottom").toInt();var c=a.toolbarWrapperEl?a.toolbarWrapperEl.getStyle("height").toInt()+a.toolbarWrapperEl.getStyle("margin-top").toInt():0;a.contentWrapperEl.setStyles({height:d.height-a.options.headerHeight-a.options.footerHeight-b-c,width:d.width});a.drawWindow();if(a.iframeEl){a.iframeEl.setStyles({height:a.contentWrapperEl.getStyle("height")});a.iframeEl.setStyle("visibility","visible")}}}.bind(this))}.bind(this),100)},setDesktopSize:function(){var d=window.getCoordinates();var b=$(MUI.options.dockWrapper);if(this.desktop){this.desktop.setStyle("height",d.height)}if(this.pageWrapper){var a=MUI.dockVisible?b.offsetHeight:0;var c=d.height;c-=this.pageWrapper.getStyle("margin-top").toInt();c-=this.pageWrapper.getStyle("margin-bottom").toInt();if(this.desktopHeader){c-=this.desktopHeader.offsetHeight}if(this.desktopFooter){c-=this.desktopFooter.offsetHeight}c-=a;if(c<0){c=0}this.pageWrapper.setStyle("height",c)}if(MUI.Columns.instances.getKeys().length>0){MUI.Desktop.resizePanels()}},resizePanels:function(){MUI.panelHeight();MUI.rWidth()},maximizeWindow:function(f){var g=MUI.Windows.instances.get(f.id);var j=g.options;var c=g.windowDrag;if(f!=$(f)||g.isMaximized){return}if(g.isCollapsed){MUI.collapseToggle(f)}g.isMaximized=true;if(g.options.restrict){c.detach();if(j.resizable){g.detachResizable()}g.titleBarEl.setStyle("cursor","default")}if(j.container!=this.desktop){this.desktop.grab(f);if(this.options.restrict){c.container=this.desktop}}g.oldTop=f.getStyle("top");g.oldLeft=f.getStyle("left");var d=g.contentWrapperEl;d.oldWidth=d.getStyle("width");d.oldHeight=d.getStyle("height");if(g.iframeEl){if(!MUI.ieLegacySupport){g.iframeEl.setStyle("visibility","hidden")}else{g.iframeEl.hide()}}var b=document.getCoordinates();var j=g.options;var e=j.shadowBlur;var h=j.shadowOffset;var a=b.height-j.headerHeight-j.footerHeight;a-=g.contentBorderEl.getStyle("margin-top").toInt();a-=g.contentBorderEl.getStyle("margin-bottom").toInt();a-=(g.toolbarWrapperEl?g.toolbarWrapperEl.getStyle("height").toInt()+g.toolbarWrapperEl.getStyle("margin-top").toInt():0);MUI.resizeWindow(f,{width:b.width,height:a,top:h.y-e,left:h.x-e});g.fireEvent("onMaximize",f);if(g.maximizeButtonEl){g.maximizeButtonEl.setProperty("title","Restore")}MUI.focusWindow(f)},restoreWindow:function(d){var a=d.retrieve("instance");if(d!=$(d)||!a.isMaximized){return}var b=a.options;a.isMaximized=false;if(b.restrict){a.windowDrag.attach();if(b.resizable){a.reattachResizable()}a.titleBarEl.setStyle("cursor","move")}if(a.iframeEl){if(!MUI.ieLegacySupport){a.iframeEl.setStyle("visibility","hidden")}else{a.iframeEl.hide()}}var c=a.contentWrapperEl;MUI.resizeWindow(d,{width:c.oldWidth,height:c.oldHeight,top:a.oldTop,left:a.oldLeft});a.fireEvent("onRestore",d);if(a.maximizeButtonEl){a.maximizeButtonEl.setProperty("title","Maximize")}}};MUI.Column=new Class({Implements:[Events,Options],options:{id:null,container:null,placement:null,width:null,resizeLimit:[],sortable:true,onResize:$empty,onCollapse:$empty,onExpand:$empty},initialize:function(b){this.setOptions(b);$extend(this,{timestamp:$time(),isCollapsed:false,oldWidth:0});if(this.options.id==null){this.options.id="column"+(++MUI.Columns.columnIDCount)}var b=this.options;var g=MUI.Columns.instances;var d=g.get(b.id);if(b.container==null){b.container=MUI.Desktop.pageWrapper}else{$(b.container).setStyle("overflow","hidden")}if(typeof this.options.container=="string"){this.options.container=$(this.options.container)}if(d){var a=d}if(this.columnEl){return}else{g.set(b.id,this)}if($(b.container).getElement(".pad")!=null){$(b.container).getElement(".pad").hide()}if($(b.container).getElement(".mochaContent")!=null){$(b.container).getElement(".mochaContent").hide()}this.columnEl=new Element("div",{id:this.options.id,"class":"column expanded",styles:{width:b.placement=="main"?null:b.width}}).inject($(b.container));this.columnEl.store("instance",this);var c=this.columnEl.getParent();var f=c.getStyle("height").toInt();this.columnEl.setStyle("height",f);if(this.options.sortable){if(!this.options.container.retrieve("sortables")){var e=new Sortables(this.columnEl,{opacity:1,handle:".panel-header",constrain:false,revert:false,onSort:function(){$$(".column").each(function(h){h.getChildren(".panelWrapper").each(function(j){j.getElement(".panel").removeClass("bottomPanel")});if(h.getChildren(".panelWrapper").getLast()){h.getChildren(".panelWrapper").getLast().getElement(".panel").addClass("bottomPanel")}MUI.panelHeight()}.bind(this))}.bind(this)});this.options.container.store("sortables",e)}else{this.options.container.retrieve("sortables").addLists(this.columnEl)}}if(b.placement=="main"){this.columnEl.addClass("rWidth")}switch(this.options.placement){case"left":this.handleEl=new Element("div",{id:this.options.id+"_handle","class":"columnHandle"}).inject(this.columnEl,"after");this.handleIconEl=new Element("div",{id:b.id+"_handle_icon","class":"handleIcon"}).inject(this.handleEl);addResizeRight(this.columnEl,b.resizeLimit[0],b.resizeLimit[1]);break;case"right":this.handleEl=new Element("div",{id:this.options.id+"_handle","class":"columnHandle"}).inject(this.columnEl,"before");this.handleIconEl=new Element("div",{id:b.id+"_handle_icon","class":"handleIcon"}).inject(this.handleEl);addResizeLeft(this.columnEl,b.resizeLimit[0],b.resizeLimit[1]);break}if(this.handleEl!=null){this.handleEl.addEvent("dblclick",function(){this.columnToggle()}.bind(this))}MUI.rWidth()},columnToggle:function(){var a=this.columnEl;if(this.isCollapsed==false){this.oldWidth=a.getStyle("width").toInt();this.resize.detach();this.handleEl.removeEvents("dblclick");this.handleEl.addEvent("click",function(){this.columnToggle()}.bind(this));this.handleEl.setStyle("cursor","pointer").addClass("detached");a.setStyle("width",0);this.isCollapsed=true;a.addClass("collapsed");a.removeClass("expanded");MUI.rWidth();this.fireEvent("onCollapse")}else{a.setStyle("width",this.oldWidth);this.isCollapsed=false;a.addClass("expanded");a.removeClass("collapsed");this.handleEl.removeEvents("click");this.handleEl.addEvent("dblclick",function(){this.columnToggle()}.bind(this));this.resize.attach();this.handleEl.setStyle("cursor",(Browser.Engine.webkit||Browser.Engine.gecko)?"col-resize":"e-resize").addClass("attached");MUI.rWidth();this.fireEvent("onExpand")}}});MUI.Column.implement(new Options,new Events);MUI.Panel=new Class({Implements:[Events,Options],options:{id:null,title:"New Panel",column:null,require:{css:[],images:[],js:[],onload:null},loadMethod:null,contentURL:null,method:"get",data:null,evalScripts:true,evalResponse:false,content:"Panel content",tabsURL:null,tabsData:null,tabsOnload:$empty,header:true,headerToolbox:false,headerToolboxURL:"pages/lipsum.html",headerToolboxOnload:$empty,height:125,addClass:"",scrollbars:true,padding:{top:8,right:8,bottom:8,left:8},collapsible:true,onBeforeBuild:$empty,onContentLoaded:$empty,onResize:$empty,onCollapse:$empty,onExpand:$empty},initialize:function(b){this.setOptions(b);$extend(this,{timestamp:$time(),isCollapsed:false,oldHeight:0,partner:null});if(this.options.id==null){this.options.id="panel"+(++MUI.Panels.panelIDCount)}var f=MUI.Panels.instances;var c=f.get(this.options.id);var b=this.options;if(c){var a=c}if(this.panelEl){return}else{f.set(this.options.id,this)}this.fireEvent("onBeforeBuild");if(b.loadMethod=="iframe"){b.padding={top:0,right:0,bottom:0,left:0}}this.showHandle=true;if($(b.column).getChildren().length==0){this.showHandle=false}this.panelWrapperEl=new Element("div",{id:this.options.id+"_wrapper","class":"panelWrapper expanded"}).inject($(b.column));this.panelEl=new Element("div",{id:this.options.id,"class":"panel expanded",styles:{height:b.height}}).inject(this.panelWrapperEl);this.panelEl.store("instance",this);this.panelEl.addClass(b.addClass);this.contentEl=new Element("div",{id:b.id+"_pad","class":"pad"}).inject(this.panelEl);this.contentWrapperEl=this.panelEl;this.contentEl.setStyles({"padding-top":b.padding.top,"padding-bottom":b.padding.bottom,"padding-left":b.padding.left,"padding-right":b.padding.right});this.panelHeaderEl=new Element("div",{id:this.options.id+"_header","class":"panel-header",styles:{display:b.header?"block":"none"}}).inject(this.panelEl,"before");var d=MUI.Columns.instances;var e=d.get(this.options.column);if(e.options.sortable){this.panelHeaderEl.setStyle("cursor","move");e.options.container.retrieve("sortables").addItems(this.panelWrapperEl)}if(this.options.collapsible){this.collapseToggleInit()}if(this.options.headerToolbox){this.panelHeaderToolboxEl=new Element("div",{id:b.id+"_headerToolbox","class":"panel-header-toolbox"}).inject(this.panelHeaderEl)}this.panelHeaderContentEl=new Element("div",{id:b.id+"_headerContent","class":"panel-headerContent"}).inject(this.panelHeaderEl);this.titleEl=new Element("h2",{id:b.id+"_title"}).inject(this.panelHeaderContentEl);this.handleEl=new Element("div",{id:b.id+"_handle","class":"horizontalHandle",styles:{display:this.showHandle==true?"block":"none"}}).inject(this.panelEl,"after");this.handleIconEl=new Element("div",{id:b.id+"_handle_icon","class":"handleIcon"}).inject(this.handleEl);addResizeBottom(b.id);if(b.require.css.length||b.require.images.length){new MUI.Require({css:b.require.css,images:b.require.images,onload:function(){this.newPanel()}.bind(this)})}else{this.newPanel()}},newPanel:function(){options=this.options;if(this.options.headerToolbox){MUI.updateContent({element:this.panelEl,childElement:this.panelHeaderToolboxEl,loadMethod:"xhr",url:options.headerToolboxURL,onContentLoaded:options.headerToolboxOnload})}if(options.tabsURL==null){this.titleEl.set("html",options.title)}else{this.panelHeaderContentEl.addClass("tabs");MUI.updateContent({element:this.panelEl,childElement:this.panelHeaderContentEl,loadMethod:"xhr",url:options.tabsURL,data:options.tabsData,onContentLoaded:options.tabsOnload})}MUI.updateContent({element:this.panelEl,content:options.content,method:options.method,data:options.data,url:options.contentURL,onContentLoaded:null,require:{js:options.require.js,onload:options.require.onload}});$(options.column).getChildren(".panelWrapper").each(function(a){a.getElement(".panel").removeClass("bottomPanel")});$(options.column).getChildren(".panelWrapper").getLast().getElement(".panel").addClass("bottomPanel");MUI.panelHeight(options.column,this.panelEl,"new")},collapseToggleInit:function(a){var a=this.options;this.panelHeaderCollapseBoxEl=new Element("div",{id:a.id+"_headerCollapseBox","class":"toolbox"}).inject(this.panelHeaderEl);if(a.headerToolbox){this.panelHeaderCollapseBoxEl.addClass("divider")}this.collapseToggleEl=new Element("div",{id:a.id+"_collapseToggle","class":"panel-collapse icon16",styles:{width:16,height:16},title:"Collapse Panel"}).inject(this.panelHeaderCollapseBoxEl);this.collapseToggleEl.addEvent("click",function(f){var b=this.panelEl;var c=this.panelWrapperEl;var g=MUI.Panels.instances;var e=[];c.getAllPrevious(".panelWrapper").each(function(j){var h=g.get(j.getElement(".panel").id);if(h.isCollapsed==false){e.push(j.getElement(".panel").id)}});c.getAllNext(".panelWrapper").each(function(j){var h=g.get(j.getElement(".panel").id);if(h.isCollapsed==false){e.push(j.getElement(".panel").id)}});if(this.isCollapsed==false){var d=MUI.Columns.instances.get($(a.column).id);if(e.length==0&&d.options.placement!="main"){var d=MUI.Columns.instances.get($(a.column).id);d.columnToggle();return}else{if(e.length==0&&d.options.placement=="main"){return}}this.oldHeight=b.getStyle("height").toInt();if(this.oldHeight<10){this.oldHeight=20}this.contentEl.setStyle("position","absolute");b.setStyle("height",0);this.isCollapsed=true;c.addClass("collapsed");c.removeClass("expanded");MUI.panelHeight(a.column,b,"collapsing");MUI.panelHeight();this.collapseToggleEl.removeClass("panel-collapsed");this.collapseToggleEl.addClass("panel-expand");this.collapseToggleEl.setProperty("title","Expand Panel");this.fireEvent("onCollapse")}else{this.contentEl.setStyle("position",null);b.setStyle("height",this.oldHeight);this.isCollapsed=false;c.addClass("expanded");c.removeClass("collapsed");MUI.panelHeight(this.options.column,b,"expanding");MUI.panelHeight();this.collapseToggleEl.removeClass("panel-expand");this.collapseToggleEl.addClass("panel-collapsed");this.collapseToggleEl.setProperty("title","Collapse Panel");this.fireEvent("onExpand")}}.bind(this))}});MUI.Panel.implement(new Options,new Events);MUI.extend({panelHeight:function(a,c,b){if(a!=null){MUI.panelHeight2($(a),c,b)}else{$$(".column").each(function(d){MUI.panelHeight2(d)}.bind(this))}},panelHeight2:function(e,m,f){var b=MUI.Panels.instances;var j=e.getParent();var h=j.getStyle("height").toInt();if(Browser.Engine.trident4&&j==MUI.Desktop.pageWrapper){h-=1}e.setStyle("height",h);var g=[];e.getChildren(".panelWrapper").each(function(n){g.push(n.getElement(".panel"))}.bind(this));var k=[];e.getChildren(".expanded").each(function(n){k.push(n.getElement(".panel"))}.bind(this));var c=[];var d;var a=0;this.panelsTotalHeight=0;this.height=0;g.each(function(n){instance=b.get(n.id);if(n.getParent().hasClass("expanded")&&n.getParent().getNext(".expanded")){instance.partner=n.getParent().getNext(".expanded").getElement(".panel");instance.resize.attach();instance.handleEl.setStyles({display:"block",cursor:(Browser.Engine.webkit||Browser.Engine.gecko)?"row-resize":"n-resize"}).removeClass("detached")}else{instance.resize.detach();instance.handleEl.setStyles({display:"none",cursor:null}).addClass("detached")}if(n.getParent().getNext(".panelWrapper")==null){instance.handleEl.hide()}}.bind(this));e.getChildren().each(function(n){n.getChildren().each(function(p){if(p.hasClass("panel")){var o=b.get(p.id);anyNextSiblingsExpanded=function(q){var r;q.getParent().getAllNext(".panelWrapper").each(function(s){var t=b.get(s.getElement(".panel").id);if(t.isCollapsed==false){r=true}}.bind(this));return r}.bind(this);anyExpandingNextSiblingsExpanded=function(q){var r;m.getParent().getAllNext(".panelWrapper").each(function(s){var t=b.get(s.getElement(".panel").id);if(t.isCollapsed==false){r=true}}.bind(this));return r}.bind(this);anyNextContainsChanging=function(r){var q=[];r.getParent().getAllNext(".panelWrapper").each(function(t){q.push(t.getElement(".panel"))}.bind(this));var s=q.contains(m);return s}.bind(this);nextExpandedChanging=function(q){var r;if(q.getParent().getNext(".expanded")){if(q.getParent().getNext(".expanded").getElement(".panel")==m){r=true}}return r};if(f=="new"){if(!o.isCollapsed&&p!=m){c.push(p);this.panelsTotalHeight+=p.offsetHeight.toInt()}}else{if(f==null||f=="collapsing"){if(!o.isCollapsed&&(!anyNextContainsChanging(p)||!anyNextSiblingsExpanded(p))){c.push(p);this.panelsTotalHeight+=p.offsetHeight.toInt()}}else{if(f=="expanding"&&!o.isCollapsed&&p!=m){if(!anyNextContainsChanging(p)||(!anyExpandingNextSiblingsExpanded(p)&&nextExpandedChanging(p))){c.push(p);this.panelsTotalHeight+=p.offsetHeight.toInt()}}}}if(p.style.height){this.height+=p.getStyle("height").toInt()}}else{this.height+=p.offsetHeight.toInt()}}.bind(this))}.bind(this));var l=e.offsetHeight.toInt()-this.height;this.height=0;e.getChildren().each(function(n){this.height+=n.offsetHeight.toInt()}.bind(this));var l=e.offsetHeight.toInt()-this.height;c.each(function(n){var q=this.panelsTotalHeight/n.offsetHeight.toInt();var p=n.getStyle("height").toInt();var o=l/q;if(!isNaN(p)){o+=p}if(o<1){o=0}n.setStyle("height",o)}.bind(this));this.height=0;e.getChildren().each(function(n){n.getChildren().each(function(o){this.height+=o.offsetHeight.toInt();if(o.hasClass("panel")&&o.getStyle("height").toInt()>a){d=o;a=o.getStyle("height").toInt()}}.bind(this))}.bind(this));var l=e.offsetHeight.toInt()-this.height;if(l!=0&&a>0){d.setStyle("height",d.getStyle("height").toInt()+l);if(d.getStyle("height")<1){d.setStyle("height",0)}}j.getChildren(".columnHandle").each(function(p){var o=p.getParent();if(o.getStyle("height").toInt()<1){return}var n=o.getStyle("height").toInt()-p.getStyle("margin-top").toInt()-p.getStyle("margin-bottom").toInt();if(Browser.Engine.trident4&&o==MUI.Desktop.pageWrapper){n-=1}p.setStyle("height",n)});k.each(function(n){MUI.resizeChildren(n)}.bind(this))},resizeChildren:function(b){var d=MUI.Panels.instances;var a=d.get(b.id);var c=a.contentWrapperEl;if(a.iframeEl){if(!MUI.ieLegacySupport){a.iframeEl.setStyles({height:c.getStyle("height"),width:c.offsetWidth-c.getStyle("margin-left").toInt()-c.getStyle("margin-right").toInt()})}else{a.iframeEl.setStyles({height:c.getStyle("height"),width:c.offsetWidth-c.getStyle("margin-left").toInt()-c.getStyle("margin-right").toInt()-1});a.iframeEl.setStyles({width:c.offsetWidth-c.getStyle("margin-left").toInt()-c.getStyle("margin-right").toInt()})}}},rWidth:function(a){if(a==null){var a=MUI.Desktop.desktop}a.getElements(".rWidth").each(function(e){var b=e.offsetWidth.toInt();b-=e.getStyle("margin-left").toInt();b-=e.getStyle("margin-right").toInt();var d=e.getParent();this.width=0;d.getChildren().each(function(g){if(g.hasClass("mocha")!=true){this.width+=g.offsetWidth.toInt()}}.bind(this));var c=d.offsetWidth.toInt()-this.width;var f=b+c;if(f<1){f=0}e.setStyle("width",f);e.getChildren(".panel").each(function(g){g.setStyle("width",f-g.getStyle("margin-left").toInt()-g.getStyle("margin-right").toInt());MUI.resizeChildren(g)}.bind(this))})}});function addResizeRight(d,c,b){if(!$(d)){return}d=$(d);var f=MUI.Columns.instances;var a=f.get(d.id);var e=d.getNext(".columnHandle");e.setStyle("cursor",(Browser.Engine.webkit||Browser.Engine.gecko)?"col-resize":"e-resize");if(!c){c=50}if(!b){b=250}if(MUI.ieLegacySupport){e.addEvents({mousedown:function(){e.setCapture()},mouseup:function(){e.releaseCapture()}})}a.resize=d.makeResizable({handle:e,modifiers:{x:"width",y:false},limit:{x:[c,b]},onStart:function(){d.getElements("iframe").setStyle("visibility","hidden");d.getNext(".column").getElements("iframe").setStyle("visibility","hidden")}.bind(this),onDrag:function(){MUI.rWidth(d.getParent());if(Browser.Engine.trident4){d.getChildren().each(function(h){var g=$(d).getStyle("width").toInt();g-=h.getStyle("margin-right").toInt();g-=h.getStyle("margin-left").toInt();g-=h.getStyle("padding-right").toInt();g-=h.getStyle("padding-left").toInt();h.setStyle("width",g)}.bind(this))}}.bind(this),onComplete:function(){MUI.rWidth(d.getParent());d.getElements("iframe").setStyle("visibility","visible");d.getNext(".column").getElements("iframe").setStyle("visibility","visible");a.fireEvent("onResize")}.bind(this)})}function addResizeLeft(d,c,b){if(!$(d)){return}d=$(d);var g=MUI.Columns.instances;var a=g.get(d.id);var f=d.getPrevious(".columnHandle");f.setStyle("cursor",(Browser.Engine.webkit||Browser.Engine.gecko)?"col-resize":"e-resize");var e=d.getPrevious(".column");if(!c){c=50}if(!b){b=250}if(MUI.ieLegacySupport){f.addEvents({mousedown:function(){f.setCapture()},mouseup:function(){f.releaseCapture()}})}a.resize=d.makeResizable({handle:f,modifiers:{x:"width",y:false},invert:true,limit:{x:[c,b]},onStart:function(){$(d).getElements("iframe").setStyle("visibility","hidden");e.getElements("iframe").setStyle("visibility","hidden")}.bind(this),onDrag:function(){MUI.rWidth(d.getParent())}.bind(this),onComplete:function(){MUI.rWidth(d.getParent());$(d).getElements("iframe").setStyle("visibility","visible");e.getElements("iframe").setStyle("visibility","visible");a.fireEvent("onResize")}.bind(this)})}function addResizeBottom(b){if(!$(b)){return}var b=$(b);var d=MUI.Panels.instances;var a=d.get(b.id);var c=a.handleEl;c.setStyle("cursor",(Browser.Engine.webkit||Browser.Engine.gecko)?"row-resize":"n-resize");partner=a.partner;min=0;max=function(){return b.getStyle("height").toInt()+partner.getStyle("height").toInt()}.bind(this);if(MUI.ieLegacySupport){c.addEvents({mousedown:function(){c.setCapture()},mouseup:function(){c.releaseCapture()}})}a.resize=b.makeResizable({handle:c,modifiers:{x:false,y:"height"},limit:{y:[min,max]},invert:false,onBeforeStart:function(){partner=a.partner;this.originalHeight=b.getStyle("height").toInt();this.partnerOriginalHeight=partner.getStyle("height").toInt()}.bind(this),onStart:function(){if(a.iframeEl){if(!MUI.ieLegacySupport){a.iframeEl.setStyle("visibility","hidden");partner.getElements("iframe").setStyle("visibility","hidden")}else{a.iframeEl.hide();partner.getElements("iframe").hide()}}}.bind(this),onDrag:function(){partnerHeight=partnerOriginalHeight;partnerHeight+=(this.originalHeight-b.getStyle("height").toInt());partner.setStyle("height",partnerHeight);MUI.resizeChildren(b,b.getStyle("height").toInt());MUI.resizeChildren(partner,partnerHeight);b.getChildren(".column").each(function(e){MUI.panelHeight(e)});partner.getChildren(".column").each(function(e){MUI.panelHeight(e)})}.bind(this),onComplete:function(){partnerHeight=partnerOriginalHeight;partnerHeight+=(this.originalHeight-b.getStyle("height").toInt());partner.setStyle("height",partnerHeight);MUI.resizeChildren(b,b.getStyle("height").toInt());MUI.resizeChildren(partner,partnerHeight);b.getChildren(".column").each(function(f){MUI.panelHeight(f)});partner.getChildren(".column").each(function(f){MUI.panelHeight(f)});if(a.iframeEl){if(!MUI.ieLegacySupport){a.iframeEl.setStyle("visibility","visible");partner.getElements("iframe").setStyle("visibility","visible")}else{a.iframeEl.show();partner.getElements("iframe").show();var e=a.iframeEl.getStyle("width").toInt();a.iframeEl.setStyle("width",e-1);MUI.rWidth();a.iframeEl.setStyle("width",e)}}a.fireEvent("onResize")}.bind(this)})}MUI.extend({closeColumn:function(b){var d=MUI.Columns.instances;var a=d.get(b.id);if(b!=$(b)||a.isClosing){return}a.isClosing=true;if(a.options.sortable){a.container.retrieve("sortables").removeLists(this.columnEl)}var c=b.getChildren(".panel");c.each(function(e){MUI.closePanel($(e.id))}.bind(this));if(MUI.ieLegacySupport){b.dispose();if(a.handleEl!=null){a.handleEl.dispose()}}else{b.destroy();if(a.handleEl!=null){a.handleEl.destroy()}}if(MUI.Desktop){MUI.Desktop.resizePanels()}d.erase(a.options.id);return true},closePanel:function(f){var e=MUI.Panels.instances;var a=e.get(f.id);if(f!=$(f)||a.isClosing){return}var b=a.options.column;a.isClosing=true;var c=MUI.Columns.instances;var d=c.get(b);if(d.options.sortable){d.options.container.retrieve("sortables").removeItems(a.panelWrapperEl)}a.panelWrapperEl.destroy();if(MUI.Desktop){MUI.Desktop.resizePanels()}$(b).getChildren(".panelWrapper").each(function(g){g.getElement(".panel").removeClass("bottomPanel")});$(b).getChildren(".panelWrapper").getLast().getElement(".panel").addClass("bottomPanel");e.erase(a.options.id);return true}});MUI.files[MUI.path.source+"Layout/Dock.js"]="loaded";MUI.options.extend({dockWrapper:"dockWrapper",dock:"dock"});MUI.extend({minimizeAll:function(){$$(".mocha").each(function(b){var a=b.retrieve("instance");if(!a.isMinimized&&a.options.minimizable==true){MUI.Dock.minimizeWindow(b)}}.bind(this))}});MUI.Dock={options:{useControls:true,dockPosition:"bottom",trueButtonColor:[70,245,70],enabledButtonColor:[115,153,191],disabledButtonColor:[170,170,170]},initialize:function(a){if(!MUI.Desktop){return}MUI.dockVisible=true;this.dockWrapper=$(MUI.options.dockWrapper);this.dock=$(MUI.options.dock);this.autoHideEvent=null;this.dockAutoHide=false;if(!this.dockWrapper){return}if(!this.options.useControls){if($("dockPlacement")){$("dockPlacement").setStyle("cursor","default")}if($("dockAutoHide")){$("dockAutoHide").setStyle("cursor","default")}}this.dockWrapper.setStyles({display:"block",position:"absolute",top:null,bottom:MUI.Desktop.desktopFooter?MUI.Desktop.desktopFooter.offsetHeight:0,left:0});if(this.options.useControls){this.initializeDockControls()}if($("dockLinkCheck")){this.sidebarCheck=new Element("div",{"class":"check",id:"dock_check"}).inject($("dockLinkCheck"))}this.dockSortables=new Sortables("#dockSort",{opacity:1,constrain:true,clone:false,revert:false});MUI.Desktop.setDesktopSize();if(MUI.myChain){MUI.myChain.callChain()}},initializeDockControls:function(){this.setDockColors();if(this.options.useControls){var b=new Element("canvas",{id:"dockCanvas",width:"15",height:"18"}).inject(this.dock);if(MUI.ieLegacySupport&&MUI.ieSupport=="excanvas"){G_vmlCanvasManager.initElement(b)}}var a=$("dockPlacement");var c=$("dockAutoHide");a.setProperty("title","Position Dock Top");a.addEvent("click",function(){this.moveDock()}.bind(this));c.setProperty("title","Turn Auto Hide On");c.addEvent("click",function(e){if(this.dockWrapper.getProperty("dockPosition")=="top"){return false}var d=$("dockCanvas").getContext("2d");this.dockAutoHide=!this.dockAutoHide;if(this.dockAutoHide){$("dockAutoHide").setProperty("title","Turn Auto Hide Off");MUI.circle(d,5,14,3,this.options.trueButtonColor,1);this.autoHideEvent=function(g){if(!this.dockAutoHide){return}if(!MUI.Desktop.desktopFooter){var f=this.dockWrapper.offsetHeight;if(f<25){f=25}}else{if(MUI.Desktop.desktopFooter){var f=this.dockWrapper.offsetHeight+MUI.Desktop.desktopFooter.offsetHeight;if(f<25){f=25}}}if(!MUI.Desktop.desktopFooter&&g.client.y>(document.getCoordinates().height-f)){if(!MUI.dockVisible){this.dockWrapper.show();MUI.dockVisible=true;MUI.Desktop.setDesktopSize()}}else{if(MUI.Desktop.desktopFooter&&g.client.y>(document.getCoordinates().height-f)){if(!MUI.dockVisible){this.dockWrapper.show();MUI.dockVisible=true;MUI.Desktop.setDesktopSize()}}else{if(MUI.dockVisible){this.dockWrapper.hide();MUI.dockVisible=false;MUI.Desktop.setDesktopSize()}}}}.bind(this);document.addEvent("mousemove",this.autoHideEvent)}else{$("dockAutoHide").setProperty("title","Turn Auto Hide On");MUI.circle(d,5,14,3,this.options.enabledButtonColor,1);document.removeEvent("mousemove",this.autoHideEvent)}}.bind(this));this.renderDockControls();if(this.options.dockPosition=="top"){this.moveDock()}},setDockColors:function(){var c=MUI.getCSSRule(".dockButtonEnabled");if(c&&c.style.backgroundColor){this.options.enabledButtonColor=new Color(c.style.backgroundColor)}var a=MUI.getCSSRule(".dockButtonDisabled");if(a&&a.style.backgroundColor){this.options.disabledButtonColor=new Color(a.style.backgroundColor)}var b=MUI.getCSSRule(".dockButtonTrue");if(b&&b.style.backgroundColor){this.options.trueButtonColor=new Color(b.style.backgroundColor)}},renderDockControls:function(){var a=$("dockCanvas").getContext("2d");a.clearRect(0,0,100,100);MUI.circle(a,5,4,3,this.options.enabledButtonColor,1);if(this.dockWrapper.getProperty("dockPosition")=="top"){MUI.circle(a,5,14,3,this.options.disabledButtonColor,1)}else{if(this.dockAutoHide){MUI.circle(a,5,14,3,this.options.trueButtonColor,1)}else{MUI.circle(a,5,14,3,this.options.enabledButtonColor,1)}}},moveDock:function(){var a=$("dockCanvas").getContext("2d");if(this.dockWrapper.getStyle("position")!="relative"){this.dockWrapper.setStyles({position:"relative",bottom:null});this.dockWrapper.addClass("top");MUI.Desktop.setDesktopSize();this.dockWrapper.setProperty("dockPosition","top");a.clearRect(0,0,100,100);MUI.circle(a,5,4,3,this.options.enabledButtonColor,1);MUI.circle(a,5,14,3,this.options.disabledButtonColor,1);$("dockPlacement").setProperty("title","Position Dock Bottom");$("dockAutoHide").setProperty("title","Auto Hide Disabled in Top Dock Position");this.dockAutoHide=false}else{this.dockWrapper.setStyles({position:"absolute",bottom:MUI.Desktop.desktopFooter?MUI.Desktop.desktopFooter.offsetHeight:0});this.dockWrapper.removeClass("top");MUI.Desktop.setDesktopSize();this.dockWrapper.setProperty("dockPosition","bottom");a.clearRect(0,0,100,100);MUI.circle(a,5,4,3,this.options.enabledButtonColor,1);MUI.circle(a,5,14,3,this.options.enabledButtonColor,1);$("dockPlacement").setProperty("title","Position Dock Top");$("dockAutoHide").setProperty("title","Turn Auto Hide On")}},createDockTab:function(e){var a=e.retrieve("instance");var d=new Element("div",{id:a.options.id+"_dockTab","class":"dockTab",title:b}).inject($("dockClear"),"before");d.addEvent("mousedown",function(f){new Event(f).stop();this.timeDown=$time()});d.addEvent("mouseup",function(f){this.timeUp=$time();if((this.timeUp-this.timeDown)<275){if(MUI.Windows.windowsVisible==false){MUI.toggleWindowVisibility();if(a.isMinimized==true){MUI.Dock.restoreMinimized.delay(25,MUI.Dock,e)}else{MUI.focusWindow(e)}return}if(a.isMinimized==true){MUI.Dock.restoreMinimized.delay(25,MUI.Dock,e)}else{if(a.windowEl.hasClass("isFocused")&&a.options.minimizable==true){MUI.Dock.minimizeWindow(e)}else{MUI.focusWindow(e)}var g=document.getCoordinates();if(e.getStyle("left").toInt()>g.width||e.getStyle("top").toInt()>g.height){MUI.centerWindow(e)}}}});this.dockSortables.addItems(d);var b=a.titleEl.innerHTML;var c=new Element("div",{id:a.options.id+"_dockTabText","class":"dockText"}).set("html",b.substring(0,19)+(b.length>19?"...":"")).inject($(d));if(a.options.icon!=false){}MUI.Desktop.setDesktopSize()},makeActiveTab:function(){var c=MUI.getWindowWithHighestZindex();var a=c.retrieve("instance");$$(".dockTab").removeClass("activeDockTab");if(a.isMinimized!=true){a.windowEl.addClass("isFocused");var b=$(a.options.id+"_dockTab");if(b!=null){b.addClass("activeDockTab")}}else{a.windowEl.removeClass("isFocused")}},minimizeWindow:function(b){if(b!=$(b)){return}var a=b.retrieve("instance");a.isMinimized=true;if(a.iframeEl){if(!MUI.ieLegacySupport){a.iframeEl.setStyle("visibility","hidden")}else{a.iframeEl.hide()}}a.contentBorderEl.setStyle("visibility","hidden");if(a.toolbarWrapperEl){a.toolbarWrapperEl.hide()}b.setStyle("visibility","hidden");MUI.Desktop.setDesktopSize();setTimeout(function(){b.setStyle("zIndex",1);b.removeClass("isFocused");this.makeActiveTab()}.bind(this),100);a.fireEvent("onMinimize",b)},restoreMinimized:function(b){var a=b.retrieve("instance");if(a.isMinimized==false){return}if(MUI.Windows.windowsVisible==false){MUI.toggleWindowVisibility()}MUI.Desktop.setDesktopSize();if(a.options.scrollbars==true&&!a.iframeEl){a.contentWrapperEl.setStyle("overflow","auto")}if(a.isCollapsed){MUI.collapseToggle(b)}b.setStyle("visibility","visible");a.contentBorderEl.setStyle("visibility","visible");if(a.toolbarWrapperEl){a.toolbarWrapperEl.show()}if(a.iframeEl){if(!MUI.ieLegacySupport){a.iframeEl.setStyle("visibility","visible")}else{a.iframeEl.show()}}a.isMinimized=false;MUI.focusWindow(b);a.fireEvent("onRestore",b)}};MUI.files[MUI.path.source+"Layout/Workspaces.js"]="loaded";MUI.extend({saveWorkspace:function(){this.cookie=new Hash.Cookie("mochaUIworkspaceCookie",{duration:3600});this.cookie.empty();MUI.Windows.instances.each(function(a){a.saveValues();this.cookie.set(a.options.id,{id:a.options.id,top:a.options.y,left:a.options.x,width:a.contentWrapperEl.getStyle("width").toInt(),height:a.contentWrapperEl.getStyle("height").toInt()})}.bind(this));this.cookie.save();new MUI.Window({loadMethod:"html",type:"notification",addClass:"notification",content:"Workspace saved.",closeAfter:"1400",width:200,height:40,y:53,padding:{top:10,right:12,bottom:10,left:12},shadowBlur:5,bodyBgColor:[255,255,255]})},windowUnload:function(){if($$(".mocha").length==0&&this.myChain){this.myChain.callChain()}},loadWorkspace2:function(workspaceWindows){workspaceWindows.each(function(workspaceWindow){windowFunction=eval("MUI."+workspaceWindow.id+"Window");if(windowFunction){eval("MUI."+workspaceWindow.id+"Window({width:"+workspaceWindow.width+",height:"+workspaceWindow.height+"});");var windowEl=$(workspaceWindow.id);windowEl.setStyles({top:workspaceWindow.top,left:workspaceWindow.left});var instance=windowEl.retrieve("instance");instance.contentWrapperEl.setStyles({width:workspaceWindow.width,height:workspaceWindow.height});instance.drawWindow()}}.bind(this));this.loadingWorkspace=false},loadWorkspace:function(){cookie=new Hash.Cookie("mochaUIworkspaceCookie",{duration:3600});workspaceWindows=cookie.load();if(!cookie.getKeys().length){new MUI.Window({loadMethod:"html",type:"notification",addClass:"notification",content:"You have no saved workspace.",closeAfter:"1400",width:220,height:40,y:25,padding:{top:10,right:12,bottom:10,left:12},shadowBlur:5,bodyBgColor:[255,255,255]});return}if($$(".mocha").length!=0){this.loadingWorkspace=true;this.myChain=new Chain();this.myChain.chain(function(){$$(".mocha").each(function(a){this.closeWindow(a)}.bind(this))}.bind(this),function(){this.loadWorkspace2(workspaceWindows)}.bind(this));this.myChain.callChain()}else{this.loadWorkspace2(workspaceWindows)}}}); \ No newline at end of file diff --git a/src/webui/www/public/scripts/mocha.js b/src/webui/www/public/scripts/mocha.js deleted file mode 100644 index daef7e552..000000000 --- a/src/webui/www/public/scripts/mocha.js +++ /dev/null @@ -1,6234 +0,0 @@ -/* - -Script: Core.js - MUI - A Web Applications User Interface Framework. - -Copyright: - Copyright (c) 2007-2009 Greg Houston, . - -License: - MIT-style license. - -Contributors: - - Scott F. Frederick - - Joel Lindau - -Note: - This documentation is taken directly from the javascript source files. It is built using Natural Docs. - -*/ - -var MUI = MochaUI = new Hash({ - - version: '0.9.6 development', - - options: new Hash({ - theme: 'default', - advancedEffects: false, // Effects that require fast browsers and are cpu intensive. - standardEffects: true // Basic effects that tend to run smoothly. - }), - - path: { - source: 'scripts/source/', // Path to MochaUI source JavaScript - themes: 'themes/', // Path to MochaUI Themes - plugins: 'plugins/' // Path to Plugins - }, - - // Returns the path to the current theme directory - themePath: function(){ - return MUI.path.themes + MUI.options.theme + '/'; - }, - - files: new Hash() - -}); - -MUI.files[MUI.path.source + 'Core/Core.js'] = 'loaded'; - -MUI.extend({ - - Windows: { - instances: new Hash() - }, - - ieSupport: 'excanvas', // Makes it easier to switch between Excanvas and Moocanvas for testing - - ieLegacySupport: Browser.Engine.trident && Browser.version < 9, - - /* - - Function: updateContent - Replace the content of a window or panel. - - Arguments: - updateOptions - (object) - - updateOptions: - element - The parent window or panel. - childElement - The child element of the window or panel recieving the content. - method - ('get', or 'post') The way data is transmitted. - data - (hash) Data to be transmitted - title - (string) Change this if you want to change the title of the window or panel. - content - (string or element) An html loadMethod option. - loadMethod - ('html', 'xhr', or 'iframe') - url - Used if loadMethod is set to 'xhr' or 'iframe'. - scrollbars - (boolean) - padding - (object) - onContentLoaded - (function) - - */ - updateContent: function(options){ - - var options = $extend({ - element: null, - childElement: null, - method: null, - data: null, - title: null, - content: null, - loadMethod: null, - url: null, - scrollbars: null, - padding: null, - require: {}, - onContentLoaded: $empty - }, options); - - options.require = $extend({ - css: [], images: [], js: [], onload: null - }, options.require); - - var args = {}; - - if (!options.element) return; - var element = options.element; - - if (MUI.Windows.instances.get(element.id)){ - args.recipient = 'window'; - } - else { - args.recipient = 'panel'; - } - - var instance = element.retrieve('instance'); - if (options.title) instance.titleEl.set('html', options.title); - - var contentEl = instance.contentEl; - args.contentContainer = options.childElement != null ? options.childElement : instance.contentEl; - var contentWrapperEl = instance.contentWrapperEl; - - if (!options.loadMethod){ - if (!instance.options.loadMethod){ - if (!options.url){ - options.loadMethod = 'html'; - } - else { - options.loadMethod = 'xhr'; - } - } - else { - options.loadMethod = instance.options.loadMethod; - } - } - - // Set scrollbars if loading content in main content container. - // Always use 'hidden' for iframe windows - var scrollbars = options.scrollbars || instance.options.scrollbars; - if (args.contentContainer == instance.contentEl) { - contentWrapperEl.setStyles({ - 'overflow': scrollbars != false && options.loadMethod != 'iframe' ? 'auto' : 'hidden' - }); - } - - if (options.padding != null) { - contentEl.setStyles({ - 'padding-top': options.padding.top, - 'padding-bottom': options.padding.bottom, - 'padding-left': options.padding.left, - 'padding-right': options.padding.right - }); - } - - // Remove old content. - if (args.contentContainer == contentEl) { - contentEl.empty().show(); - // Panels are not loaded into the padding div, so we remove them separately. - contentEl.getAllNext('.column').destroy(); - contentEl.getAllNext('.columnHandle').destroy(); - } - - args.onContentLoaded = function(){ - - if (options.require.js.length || typeof options.require.onload == 'function'){ - new MUI.Require({ - js: options.require.js, - onload: function(){ - if (!$defined(options.require.onload)) - return; - if (Browser.Engine.presto){ - options.require.onload.delay(100); - } - else { - options.require.onload(); - } - options.onContentLoaded ? options.onContentLoaded() : instance.fireEvent('onContentLoaded', element); - }.bind(this) - }); - } - else { - options.onContentLoaded ? options.onContentLoaded() : instance.fireEvent('onContentLoaded', element); - } - - }; - - if (options.require.css.length || options.require.images.length){ - new MUI.Require({ - css: options.require.css, - images: options.require.images, - onload: function(){ - this.loadSelect(instance, options, args); - }.bind(this) - }); - } - else { - this.loadSelect(instance, options, args); - } - }, - - loadSelect: function(instance, options, args){ - - // Load new content. - switch(options.loadMethod){ - case 'xhr': - this.updateContentXHR(instance, options, args); - break; - case 'iframe': - this.updateContentIframe(instance, options, args); - break; - case 'html': - default: - this.updateContentHTML(instance, options, args); - break; - } - - }, - - updateContentXHR: function(instance, options, args){ - var contentEl = instance.contentEl; - var contentContainer = args.contentContainer; - var onContentLoaded = args.onContentLoaded; - new Request.HTML({ - url: options.url, - update: contentContainer, - method: options.method != null ? options.method : 'get', - data: options.data != null ? new Hash(options.data).toQueryString() : '', - evalScripts: instance.options.evalScripts, - evalResponse: instance.options.evalResponse, - onRequest: function(){ - if (args.recipient == 'window' && contentContainer == contentEl){ - instance.showSpinner(); - } - else if (args.recipient == 'panel' && contentContainer == contentEl && $('spinner')){ - $('spinner').show(); - } - }.bind(this), - onFailure: function(response){ - if (contentContainer == contentEl){ - var getTitle = new RegExp("[\n\r\s]*(.*)[\n\r\s]*", "gmi"); - var error = getTitle.exec(response.responseText); - if (!error) error = 'Unknown'; - contentContainer.set('html', '

Error: ' + error + '

'); - if (args.recipient == 'window'){ - instance.hideSpinner(); - } - else if (args.recipient == 'panel' && $('spinner')){ - $('spinner').hide(); - } - } - }.bind(this), - onSuccess: function(){ - if (contentContainer == contentEl){ - if (args.recipient == 'window') instance.hideSpinner(); - else if (args.recipient == 'panel' && $('spinner')) $('spinner').hide(); - } - Browser.Engine.trident4 ? onContentLoaded.delay(750) : onContentLoaded(); - }.bind(this), - onComplete: function(){}.bind(this) - }).send(); - }, - - updateContentIframe: function(instance, options, args){ - var contentEl = instance.contentEl; - var contentContainer = args.contentContainer; - var contentWrapperEl = instance.contentWrapperEl; - var onContentLoaded = args.onContentLoaded; - if ( instance.options.contentURL == '' || contentContainer != contentEl) { - return; - } - instance.iframeEl = new Element('iframe', { - 'id': instance.options.id + '_iframe', - 'name': instance.options.id + '_iframe', - 'class': 'mochaIframe', - 'src': options.url, - 'marginwidth': 0, - 'marginheight': 0, - 'frameBorder': 0, - 'scrolling': 'auto', - 'styles': { - 'height': contentWrapperEl.offsetHeight - contentWrapperEl.getStyle('margin-top').toInt() - contentWrapperEl.getStyle('margin-bottom').toInt(), - 'width': instance.panelEl ? contentWrapperEl.offsetWidth - contentWrapperEl.getStyle('margin-left').toInt() - contentWrapperEl.getStyle('margin-right').toInt() : '100%' - } - }).injectInside(contentEl); - - // Add onload event to iframe so we can hide the spinner and run onContentLoaded() - instance.iframeEl.addEvent('load', function(e) { - if (args.recipient == 'window') instance.hideSpinner(); - else if (args.recipient == 'panel' && contentContainer == contentEl && $('spinner')) $('spinner').hide(); - Browser.Engine.trident4 ? onContentLoaded.delay(50) : onContentLoaded(); - }.bind(this)); - if (args.recipient == 'window') instance.showSpinner(); - else if (args.recipient == 'panel' && contentContainer == contentEl && $('spinner')) $('spinner').show(); - }, - - updateContentHTML: function(instance, options, args){ - var contentEl = instance.contentEl; - var contentContainer = args.contentContainer; - var onContentLoaded = args.onContentLoaded; - var elementTypes = new Array('element', 'textnode', 'whitespace', 'collection'); - - if (elementTypes.contains($type(options.content))){ - options.content.inject(contentContainer); - } else { - contentContainer.set('html', options.content); - } - if (contentContainer == contentEl){ - if (args.recipient == 'window') instance.hideSpinner(); - else if (args.recipient == 'panel' && $('spinner')) $('spinner').hide(); - } - Browser.Engine.trident4 ? onContentLoaded.delay(50) : onContentLoaded(); - }, - - /* - - Function: reloadIframe - Reload an iframe. Fixes an issue in Firefox when trying to use location.reload on an iframe that has been destroyed and recreated. - - Arguments: - iframe - This should be both the name and the id of the iframe. - - Syntax: - (start code) - MUI.reloadIframe(element); - (end) - - Example: - To reload an iframe from within another iframe: - (start code) - parent.MUI.reloadIframe('myIframeName'); - (end) - - */ - reloadIframe: function(iframe){ - Browser.Engine.gecko ? $(iframe).src = $(iframe).src : top.frames[iframe].location.reload(true); - }, - - roundedRect: function(ctx, x, y, width, height, radius, rgb, a){ - ctx.fillStyle = 'rgba(' + rgb.join(',') + ',' + a + ')'; - ctx.beginPath(); - ctx.moveTo(x, y + radius); - ctx.lineTo(x, y + height - radius); - ctx.quadraticCurveTo(x, y + height, x + radius, y + height); - ctx.lineTo(x + width - radius, y + height); - ctx.quadraticCurveTo(x + width, y + height, x + width, y + height - radius); - ctx.lineTo(x + width, y + radius); - ctx.quadraticCurveTo(x + width, y, x + width - radius, y); - ctx.lineTo(x + radius, y); - ctx.quadraticCurveTo(x, y, x, y + radius); - ctx.fill(); - }, - - triangle: function(ctx, x, y, width, height, rgb, a){ - ctx.beginPath(); - ctx.moveTo(x + width, y); - ctx.lineTo(x, y + height); - ctx.lineTo(x + width, y + height); - ctx.closePath(); - ctx.fillStyle = 'rgba(' + rgb.join(',') + ',' + a + ')'; - ctx.fill(); - }, - - circle: function(ctx, x, y, diameter, rgb, a){ - ctx.beginPath(); - ctx.arc(x, y, diameter, 0, Math.PI*2, true); - ctx.fillStyle = 'rgba(' + rgb.join(',') + ',' + a + ')'; - ctx.fill(); - }, - - notification: function(message){ - new MUI.Window({ - loadMethod: 'html', - closeAfter: 1500, - type: 'notification', - addClass: 'notification', - content: message, - width: 220, - height: 40, - y: 53, - padding: { top: 10, right: 12, bottom: 10, left: 12 }, - shadowBlur: 5 - }); - }, - - /* - - Function: toggleEffects - Turn effects on and off - - */ - toggleAdvancedEffects: function(link){ - if (MUI.options.advancedEffects == false) { - MUI.options.advancedEffects = true; - if (link){ - this.toggleAdvancedEffectsLink = new Element('div', { - 'class': 'check', - 'id': 'toggleAdvancedEffects_check' - }).inject(link); - } - } - else { - MUI.options.advancedEffects = false; - if (this.toggleAdvancedEffectsLink) { - this.toggleAdvancedEffectsLink.destroy(); - } - } - }, - /* - - Function: toggleStandardEffects - Turn standard effects on and off - - */ - toggleStandardEffects: function(link){ - if (MUI.options.standardEffects == false) { - MUI.options.standardEffects = true; - if (link){ - this.toggleStandardEffectsLink = new Element('div', { - 'class': 'check', - 'id': 'toggleStandardEffects_check' - }).inject(link); - } - } - else { - MUI.options.standardEffects = false; - if (this.toggleStandardEffectsLink) { - this.toggleStandardEffectsLink.destroy(); - } - } - }, - - /* - - The underlay is inserted directly under windows when they are being dragged or resized - so that the cursor is not captured by iframes or other plugins (such as Flash) - underneath the window. - - */ - underlayInitialize: function(){ - var windowUnderlay = new Element('div', { - 'id': 'windowUnderlay', - 'styles': { - 'height': parent.getCoordinates().height, - 'opacity': .01, - 'display': 'none' - } - }).inject(document.body); - }, - setUnderlaySize: function(){ - $('windowUnderlay').setStyle('height', parent.getCoordinates().height); - } -}); - -/* - -function: fixPNG - Bob Osola's PngFix for IE6. - -example: - (begin code) - foo - (end) - -note: - You must have the image height and width attributes specified in the markup. - -*/ - -function fixPNG(myImage){ - if (Browser.Engine.trident4 && document.body.filters){ - var imgID = (myImage.id) ? "id='" + myImage.id + "' " : ""; - var imgClass = (myImage.className) ? "class='" + myImage.className + "' " : ""; - var imgTitle = (myImage.title) ? "title='" + myImage.title + "' " : "title='" + myImage.alt + "' "; - var imgStyle = "display:inline-block;" + myImage.style.cssText; - var strNewHTML = ""; - myImage.outerHTML = strNewHTML; - } -} - -// Blur all windows if user clicks anywhere else on the page -document.addEvent('mousedown', function(event){ - MUI.blurAll.delay(50); -}); - -window.addEvent('domready', function(){ - MUI.underlayInitialize(); -}); - -window.addEvent('resize', function(){ - if ($('windowUnderlay')) { - MUI.setUnderlaySize(); - } - else { - MUI.underlayInitialize(); - } -}); - -Element.implement({ - hide: function(){ - this.setStyle('display', 'none'); - return this; - }, - show: function(){ - this.setStyle('display', 'block'); - return this; - } -}); - -/* - -Shake effect by Uvumi Tools -http://tools.uvumi.com/element-shake.html - -Function: shake - -Example: - Shake a window. - (start code) - $('parametrics').shake() - (end) - -*/ - -Element.implement({ - shake: function(radius,duration){ - radius = radius || 3; - duration = duration || 500; - duration = (duration/50).toInt() - 1; - var parent = this.getParent(); - if(parent != $(document.body) && parent.getStyle('position') == 'static'){ - parent.setStyle('position','relative'); - } - var position = this.getStyle('position'); - if(position == 'static'){ - this.setStyle('position','relative'); - position = 'relative'; - } - if(MUI.ieLegacySupport){ - parent.setStyle('height',parent.getStyle('height')); - } - var coords = this.getPosition(parent); - if(position == 'relative' && !Browser.Engine.presto){ - coords.x -= parent.getStyle('paddingLeft').toInt(); - coords.y -= parent.getStyle('paddingTop').toInt(); - } - var morph = this.retrieve('morph'); - if (morph){ - morph.cancel(); - var oldOptions = morph.options; - } - var morph = this.get('morph',{ - duration:50, - link:'chain' - }); - for(var i=0 ; i < duration ; i++){ - morph.start({ - top:coords.y+$random(-radius,radius), - left:coords.x+$random(-radius,radius) - }); - } - morph.start({ - top:coords.y, - left:coords.x - }).chain(function(){ - if(oldOptions){ - this.set('morph',oldOptions); - } - }.bind(this)); - return this; - } -}); - -String.implement({ - - parseQueryString: function() { - var vars = this.split(/[&;]/); - var rs = {}; - if (vars.length) vars.each(function(val) { - var keys = val.split('='); - if (keys.length && keys.length == 2) rs[decodeURIComponent(keys[0])] = decodeURIComponent(keys[1]); - }); - return rs; - } - -}); - -// Mootools Patch: Fixes issues in Safari, Chrome, and Internet Explorer caused by processing text as XML. -Request.HTML.implement({ - - processHTML: function(text){ - var match = text.match(/]*>([\s\S]*?)<\/body>/i); - text = (match) ? match[1] : text; - var container = new Element('div'); - return container.set('html', text); - } - -}); - -/* - - Examples: - (start code) - getCSSRule('.myRule'); - getCSSRule('#myRule'); - (end) - -*/ -MUI.getCSSRule = function(selector) { - for (var ii = 0; ii < document.styleSheets.length; ii++) { - var mysheet = document.styleSheets[ii]; - var myrules = mysheet.cssRules ? mysheet.cssRules : mysheet.rules; - for (i = 0; i < myrules.length; i++){ - if (myrules[i].selectorText == selector){ - return myrules[i]; - } - } - } - return false; -} - -// This makes it so Request will work to some degree locally -if (location.protocol == "file:"){ - - Request.implement({ - isSuccess : function(status){ - return (status == 0 || (status >= 200) && (status < 300)); - } - }); - - Browser.Request = function(){ - return $try(function(){ - return new ActiveXObject('MSXML2.XMLHTTP'); - }, function(){ - return new XMLHttpRequest(); - }); - }; - -} - -MUI.Require = new Class({ - - Implements: [Options], - - options: { - css: [], - images: [], - js: [], - onload: $empty - }, - - initialize: function(options){ - this.setOptions(options); - var options = this.options; - - this.assetsToLoad = options.css.length + options.images.length + options.js.length; - this.assetsLoaded = 0; - - var cssLoaded = 0; - - // Load CSS before images and JavaScript - - if (options.css.length){ - options.css.each( function(sheet){ - - this.getAsset(sheet, function(){ - if (cssLoaded == options.css.length - 1){ - - if (this.assetsLoaded == this.assetsToLoad - 1){ - this.requireOnload(); - } - else { - // Add a little delay since we are relying on cached CSS from XHR request. - this.assetsLoaded++; - this.requireContinue.delay(50, this); - } - } - else { - cssLoaded++; - this.assetsLoaded++; - } - }.bind(this)); - }.bind(this)); - } - else if (!options.js.length && !options.images.length){ - this.options.onload(); - return true; - } - else { - this.requireContinue.delay(50, this); // Delay is for Safari - } - - }, - - requireOnload: function(){ - this.assetsLoaded++; - if (this.assetsLoaded == this.assetsToLoad){ - this.options.onload(); - return true; - } - - }, - - requireContinue: function(){ - - var options = this.options; - if (options.images.length){ - options.images.each( function(image){ - this.getAsset(image, this.requireOnload.bind(this)); - }.bind(this)); - } - - if (options.js.length){ - options.js.each( function(script){ - this.getAsset(script, this.requireOnload.bind(this)); - }.bind(this)); - } - - }, - - getAsset: function(source, onload){ - - // If the asset is loaded, fire the onload function. - if ( MUI.files[source] == 'loaded' ){ - if (typeof onload == 'function'){ - onload(); - } - return true; - } - - // If the asset is loading, wait until it is loaded and then fire the onload function. - // If asset doesn't load by a number of tries, fire onload anyway. - else if ( MUI.files[source] == 'loading' ){ - var tries = 0; - var checker = (function(){ - tries++; - if (MUI.files[source] == 'loading' && tries < '100') return; - $clear(checker); - if (typeof onload == 'function'){ - onload(); - } - }).periodical(50); - } - - // If the asset is not yet loaded or loading, start loading the asset. - else { - MUI.files[source] = 'loading'; - - properties = { - 'onload': onload != 'undefined' ? onload : $empty - }; - - // Add to the onload function - var oldonload = properties.onload; - properties.onload = function() { - MUI.files[source] = 'loaded'; - if (oldonload) { - oldonload(); - } - }.bind(this); - - switch ( source.match(/\.\w+$/)[0] ) { - case '.js': return Asset.javascript(source, properties); - case '.css': return Asset.css(source, properties); - case '.jpg': - case '.png': - case '.gif': return Asset.image(source, properties); - } - - alert('The required file "' + source + '" could not be loaded'); - } - } - -}); - -$extend(Asset, { - - /* Fix an Opera bug in Mootools 1.2 */ - javascript: function(source, properties){ - properties = $extend({ - onload: $empty, - document: document, - check: $lambda(true) - }, properties); - - if ($(properties.id)) { - properties.onload(); - return $(properties.id); - } - - var script = new Element('script', {'src': source, 'type': 'text/javascript'}); - - var load = properties.onload.bind(script), check = properties.check, doc = properties.document; - delete properties.onload; delete properties.check; delete properties.document; - - if (!Browser.Engine.webkit419 && !Browser.Engine.presto){ - script.addEvents({ - load: load, - readystatechange: function(){ - if (MUI.ieLegacySupport && ['loaded', 'complete'].contains(this.readyState)) - load(); - } - }).setProperties(properties); - } - else { - var checker = (function(){ - if (!$try(check)) return; - $clear(checker); - // Opera has difficulty with multiple scripts being injected into the head simultaneously. We need to give it time to catch up. - Browser.Engine.presto ? load.delay(500) : load(); - }).periodical(50); - } - return script.inject(doc.head); - }, - - // Get the CSS with XHR before appending it to document.head so that we can have an onload callback. - css: function(source, properties){ - - properties = $extend({ - id: null, - media: 'screen', - onload: $empty - }, properties); - - new Request({ - method: 'get', - url: source, - onComplete: function(response) { - var newSheet = new Element('link', { - 'id': properties.id, - 'rel': 'stylesheet', - 'media': properties.media, - 'type': 'text/css', - 'href': source - }).inject(document.head); - properties.onload(); - }.bind(this), - onFailure: function(response){ - }, - onSuccess: function(){ - }.bind(this) - }).send(); - } - -}); - -/* - -REGISTER PLUGINS - - Register Components and Plugins for Lazy Loading - - How this works may take a moment to grasp. Take a look at MUI.Window below. - If we try to create a new Window and Window.js has not been loaded then the function - below will run. It will load the CSS required by the MUI.Window Class and then - then it will load Window.js. Here is the interesting part. When Window.js loads, - it will overwrite the function below, and new MUI.Window(arg) will be ran - again. This time it will create a new MUI.Window instance, and any future calls - to new MUI.Window(arg) will immediately create new windows since the assets - have already been loaded and our temporary function below has been overwritten. - - Example: - - MyPlugins.extend({ - - MyGadget: function(arg){ - new MUI.Require({ - css: [MUI.path.plugins + 'myGadget/css/style.css'], - images: [MUI.path.plugins + 'myGadget/images/background.gif'] - js: [MUI.path.plugins + 'myGadget/scripts/myGadget.js'], - onload: function(){ - new MyPlguins.MyGadget(arg); - } - }); - } - - }); - --------------------------------------------------------------------- */ - -MUI.extend({ - - newWindowsFromJSON: function(arg){ - new MUI.Require({ - js: [MUI.path.source + 'Window/Windows-from-json.js'], - onload: function(){ - new MUI.newWindowsFromJSON(arg); - } - }); - }, - - arrangeCascade: function(){ - new MUI.Require({ - js: [MUI.path.source + 'Window/Arrange-cascade.js'], - onload: function(){ - new MUI.arrangeCascade(); - } - }); - }, - - arrangeTile: function(){ - new MUI.Require({ - js: [MUI.path.source + 'Window/Arrange-tile.js'], - onload: function(){ - new MUI.arrangeTile(); - } - }); - }, - - saveWorkspace: function(){ - new MUI.Require({ - js: [MUI.path.source + 'Layout/Workspaces.js'], - onload: function(){ - new MUI.saveWorkspace(); - } - }); - }, - - loadWorkspace: function(){ - new MUI.Require({ - js: [MUI.path.source + 'Layout/Workspaces.js'], - onload: function(){ - new MUI.loadWorkspace(); - } - }); - }, - - Themes: { - init: function(arg){ - new MUI.Require({ - js: [MUI.path.source + 'Utilities/Themes.js'], - onload: function(){ - MUI.Themes.init(arg); - } - }); - } - } - -}); -/* - -Script: Themes.js - Allows for switching themes dynamically. - -Copyright: - Copyright (c) 2007-2009 Greg Houston, . - -License: - MIT-style license. - -Requires: - Core.js - -Notes: - Themes are new and experimental. - -Syntax: - (start code) - new MUI.Themes.init(newTheme); - (end) - -Example: - (start code) - new MUI.Themes.init('charcoal'); - (end) - -Arguments: - newTheme - (string) The theme name - -*/ - -MUI.files[MUI.path.source + 'Utilities/Themes.js'] = 1; - -MUI.Themes = { - - /* - - Function: themeInit - Initialize a theme. This is experimental and not fully implemented yet. - - */ - init: function(newTheme){ - this.newTheme = newTheme.toLowerCase(); - if (!this.newTheme || this.newTheme == null || this.newTheme == MUI.options.theme.toLowerCase()) return; - - if ($('spinner')) $('spinner').show(); - - this.oldURIs = []; - this.oldSheets = []; - - $$('link').each( function(link){ - var href = link.get('href'); - if (href.contains(MUI.path.themes + MUI.options.theme)){ - this.oldURIs.push(href); - this.oldSheets.push(link); - } - }.bind(this)); - - /* - MUI.files.each( function(value, key, hash){ - if (key.contains(MUI.path.themes + MUI.options.theme)){ - this.oldURIs.push(key); - } - }.bind(this)); - */ - - this.newSheetURLs = this.oldURIs.map(function(item, index){ - return item.replace("/" + MUI.options.theme + "/", "/" + MUI.Themes.newTheme + "/"); - }.bind(this)); - - this.sheetsToLoad = this.oldURIs.length; - this.sheetsLoaded = 0; - - // Download new stylesheets and add them to an array - this.newSheets = []; - this.newSheetURLs.each( function(link){ - var href = link; - - //var id = link.id; - - var cssRequest = new Request({ - method: 'get', - url: href, - onComplete: function(response) { - var newSheet = new Element('link', { - //'id': id, - 'rel': 'stylesheet', - 'media': 'screen', - 'type': 'text/css', - 'href': href - }); - this.newSheets.push(newSheet); - }.bind(this), - onFailure: function(response){ - this.themeLoadSuccess = false; - if ($('spinner')) $('spinner').hide(); - MUI.notification('Stylesheets did not load.'); - }, - onSuccess: function(){ - this.sheetsLoaded++; - if (this.sheetsLoaded == this.sheetsToLoad) { - this.updateThemeStylesheets(); - this.themeLoadSuccess = true; - } - }.bind(this) - }); - cssRequest.send(); - - }.bind(this)); - - }, - updateThemeStylesheets: function(){ - - this.oldSheets.each( function(sheet){ - sheet.destroy(); - }); - - this.newSheets.each( function(sheet){ - MUI.files[sheet.get('href')] = 1; - sheet.inject(document.head); - }); - - // Delay gives the stylesheets time to take effect. IE6 needs more delay. - if (MUI.ieLegacySupport){ - this.redraw.delay(1250, this); - } - else { - this.redraw.delay(250, this); - } - - }, - redraw: function(){ - - $$('.replaced').removeClass('replaced'); - - // Redraw open windows - $$('.mocha').each( function(element){ - var instance = element.retrieve('instance'); - - // Convert CSS colors to Canvas colors. - instance.setColors(); - instance.drawWindow(); - }); - - if (MUI.Dock){ - if (MUI.Dock.options.useControls){ - MUI.Dock.setDockColors(); - MUI.Dock.renderDockControls(); - } - } - - // Reformat layout - if (MUI.Desktop.desktop){ - var checker = (function(){ - // Make sure the style sheets are really ready. - if (MUI.Desktop.desktop.getStyle('overflow') != 'hidden'){ - return; - } - $clear(checker); - MUI.Desktop.setDesktopSize(); - }).periodical(50); - } - - if ($('spinner')) $('spinner').hide(); - MUI.options.theme = this.newTheme; - - /* - this.cookie = new Hash.Cookie('mochaUIthemeCookie', {duration: 3600}); - this.cookie.empty(); - this.cookie.set('theme', MUI.options.theme); - this.cookie.save(); - */ - - } -}; - -window.addEvent('load', function(){ - /* - // Load theme the user was last using. This needs work. - var cookie = new Hash.Cookie('mochaUIthemeCookie', {duration: 3600}); - var themeCookie = cookie.load(); - if(cookie.getKeys().length){ - if (themeCookie.get('theme') != MUI.Themes.options.theme){ - MUI.Themes.init.delay(1000, MUI.Themes, themeCookie.get('theme')); - } - } - */ - - if ($('themeControl')){ - $('themeControl').getElements('option').setProperty('selected', 'false'); - if ($('chooseTheme')){ - $('chooseTheme').setProperty('selected', 'true'); - } - } -}); -/* - -Script: Window.js - Build windows. - -Copyright: - Copyright (c) 2007-2009 Greg Houston, . - -License: - MIT-style license. - -Requires: - Core.js - -*/ - -MUI.files[MUI.path.source + 'Window/Window.js'] = 'loading'; -//$require(MUI.themePath() + '/css/Dock.css'); - -/* -Class: Window - Creates a single MochaUI window. - -Syntax: - (start code) - new MUI.Window(options); - (end) - -Arguments: - options - -Options: - id - The ID of the window. If not defined, it will be set to 'win' + windowIDCount. - title - The title of the window. - icon - Place an icon in the window's titlebar. This is either set to false or to the url of the icon. It is set up for icons that are 16 x 16px. - type - ('window', 'modal', 'modal2', or 'notification') Defaults to 'window'. Modals should be created with new MUI.Modal(options). - loadMethod - ('html', 'xhr', or 'iframe') Defaults to 'html' if there is no contentURL. Defaults to 'xhr' if there is a contentURL. You only really need to set this if using the 'iframe' method. - contentURL - Used if loadMethod is set to 'xhr' or 'iframe'. - closeAfter - Either false or time in milliseconds. Closes the window after a certain period of time in milliseconds. This is particularly useful for notifications. - evalScripts - (boolean) An xhr loadMethod option. Defaults to true. - evalResponse - (boolean) An xhr loadMethod option. Defaults to false. - content - (string or element) An html loadMethod option. - toolbar - (boolean) Create window toolbar. Defaults to false. This can be used for tabs, media controls, and so forth. - toolbarPosition - ('top' or 'bottom') Defaults to top. - toolbarHeight - (number) - toolbarURL - (url) Defaults to 'pages/lipsum.html'. - toolbarContent - (string) - toolbarOnload - (function) - toolbar2 - (boolean) Create window toolbar. Defaults to false. This can be used for tabs, media controls, and so forth. - toolbar2Position - ('top' or 'bottom') Defaults to top. - toolbar2Height - (number) - toolbar2URL - (url) Defaults to 'pages/lipsum.html'. - toolbar2Content - (string) - toolbar2Onload - (function) - container - (element ID) Element the window is injected in. The container defaults to 'desktop'. If no desktop then to document.body. Use 'pageWrapper' if you don't want the windows to overlap the toolbars. - restrict - (boolean) Restrict window to container when dragging. - shape - ('box' or 'gauge') Shape of window. Defaults to 'box'. - collapsible - (boolean) Defaults to true. - minimizable - (boolean) Requires MUI.Desktop and MUI.Dock. Defaults to true if dependenices are met. - maximizable - (boolean) Requires MUI.Desktop. Defaults to true if dependenices are met. - closable - (boolean) Defaults to true. - storeOnClose - (boolean) Hides a window and it's dock tab rather than destroying them on close. If you try to create the window again it will unhide the window and dock tab. - modalOverlayClose - (boolean) Whether or not you can close a modal by clicking on the modal overlay. Defaults to true. - draggable - (boolean) Defaults to false for modals; otherwise true. - draggableGrid - (false or number) Distance in pixels for snap-to-grid dragging. Defaults to false. - draggableLimit - (false or number) An object with x and y properties used to limit the movement of the Window. Defaults to false. - draggableSnap - (boolean) The distance to drag before the Window starts to respond to the drag. Defaults to false. - resizable - (boolean) Defaults to false for modals, notifications and gauges; otherwise true. - resizeLimit - (object) Minimum and maximum width and height of window when resized. - addClass - (string) Add a class to the window for more control over styling. - width - (number) Width of content area. - height - (number) Height of content area. - headerHeight - (number) Height of window titlebar. - footerHeight - (number) Height of window footer. - cornerRadius - (number) - x - (number) If x and y are left undefined the window is centered on the page. - y - (number) - scrollbars - (boolean) - padding - (object) - shadowBlur - (number) Width of shadows. - shadowOffset - Should be positive and not be greater than the ShadowBlur. - controlsOffset - Change this if you want to reposition the window controls. - useCanvas - (boolean) Set this to false if you don't want a canvas body. - useCanvasControls - (boolean) Set this to false if you wish to use images for the buttons. - useSpinner - (boolean) Toggles whether or not the ajax spinners are displayed in window footers. Defaults to true. - headerStartColor - ([r,g,b,]) Titlebar gradient's top color - headerStopColor - ([r,g,b,]) Titlebar gradient's bottom color - bodyBgColor - ([r,g,b,]) Background color of the main canvas shape - minimizeBgColor - ([r,g,b,]) Minimize button background color - minimizeColor - ([r,g,b,]) Minimize button color - maximizeBgColor - ([r,g,b,]) Maximize button background color - maximizeColor - ([r,g,b,]) Maximize button color - closeBgColor - ([r,g,b,]) Close button background color - closeColor - ([r,g,b,]) Close button color - resizableColor - ([r,g,b,]) Resizable icon color - onBeforeBuild - (function) Fired just before the window is built. - onContentLoaded - (function) Fired when content is successfully loaded via XHR or Iframe. - onFocus - (function) Fired when the window is focused. - onBlur - (function) Fired when window loses focus. - onResize - (function) Fired when the window is resized. - onMinimize - (function) Fired when the window is minimized. - onMaximize - (function) Fired when the window is maximized. - onRestore - (function) Fired when a window is restored from minimized or maximized. - onClose - (function) Fired just before the window is closed. - onCloseComplete - (function) Fired after the window is closed. - -Returns: - Window object. - -Example: - Define a window. It is suggested you name the function the same as your window ID + "Window". - (start code) - var mywindowWindow = function(){ - new MUI.Window({ - id: 'mywindow', - title: 'My Window', - loadMethod: 'xhr', - contentURL: 'pages/lipsum.html', - width: 340, - height: 150 - }); - } - (end) - -Example: - Create window onDomReady. - (start code) - window.addEvent('domready', function(){ - mywindow(); - }); - (end) - -Example: - Add link events to build future windows. It is suggested you give your anchor the same ID as your window + "WindowLink" or + "WindowLinkCheck". Use the latter if it is a link in the menu toolbar. - - If you wish to add links in windows that open other windows remember to add events to those links when the windows are created. - - (start code) - // Javascript: - if ($('mywindowLink')){ - $('mywindowLink').addEvent('click', function(e) { - new Event(e).stop(); - mywindow(); - }); - } - - // HTML: - My Window - (end) - - - Loading Content with an XMLHttpRequest(xhr): - For content to load via xhr all the files must be online and in the same domain. If you need to load content from another domain or wish to have it work offline, load the content in an iframe instead of using the xhr option. - - Iframes: - If you use the iframe loadMethod your iframe will automatically be resized when the window it is in is resized. If you want this same functionality when using one of the other load options simply add class="mochaIframe" to those iframes and they will be resized for you as well. - -*/ - -// Having these options outside of the Class allows us to add, change, and remove -// individual options without rewriting all of them. - -MUI.extend({ - Windows: { - instances: new Hash(), - indexLevel: 100, // Used for window z-Index - windowIDCount: 0, // Used for windows without an ID defined by the user - windowsVisible: true, // Ctrl-Alt-Q to toggle window visibility - focusingWindow: false - } -}); - -MUI.Windows.windowOptions = { - id: null, - title: 'New Window', - icon: false, - type: 'window', - require: { - css: [], - images: [], - js: [], - onload: null - }, - loadMethod: null, - method: 'get', - contentURL: null, - data: null, - - closeAfter: false, - - // xhr options - evalScripts: true, - evalResponse: false, - - // html options - content: 'Window content', - - // Toolbar - toolbar: false, - toolbarPosition: 'top', - toolbarHeight: 29, - toolbarURL: 'pages/lipsum.html', - toolbarData: null, - toolbarContent: '', - toolbarOnload: $empty, - - // Toolbar - toolbar2: false, - toolbar2Position: 'bottom', - toolbar2Height: 29, - toolbar2URL: 'pages/lipsum.html', - toolbar2Data: null, - toolbar2Content: '', - toolbar2Onload: $empty, - - // Container options - container: null, - restrict: true, - shape: 'box', - - // Window Controls - collapsible: true, - minimizable: true, - maximizable: true, - closable: true, - - // Close options - storeOnClose: false, - - // Modal options - modalOverlayClose: true, - - // Draggable - draggable: null, - draggableGrid: false, - draggableLimit: false, - draggableSnap: false, - - // Resizable - resizable: null, - resizeLimit: {'x': [250, 2500], 'y': [125, 2000]}, - - // Style options: - addClass: '', - width: 300, - height: 125, - headerHeight: 25, - footerHeight: 25, - cornerRadius: 8, - x: null, - y: null, - scrollbars: true, - padding: { top: 10, right: 12, bottom: 10, left: 12 }, - shadowBlur: 5, - shadowOffset: {'x': 0, 'y': 1}, - controlsOffset: {'right': 6, 'top': 6}, - useCanvas: true, - useCanvasControls: true, - useSpinner: true, - - // Color options: - headerStartColor: [250, 250, 250], - headerStopColor: [229, 229, 229], - bodyBgColor: [229, 229, 229], - minimizeBgColor: [255, 255, 255], - minimizeColor: [0, 0, 0], - maximizeBgColor: [255, 255, 255], - maximizeColor: [0, 0, 0], - closeBgColor: [255, 255, 255], - closeColor: [0, 0, 0], - resizableColor: [254, 254, 254], - - // Events - onBeforeBuild: $empty, - onContentLoaded: $empty, - onFocus: $empty, - onBlur: $empty, - onResize: $empty, - onMinimize: $empty, - onMaximize: $empty, - onRestore: $empty, - onClose: $empty, - onCloseComplete: $empty -}; - -MUI.Windows.windowOptionsOriginal = $merge(MUI.Windows.windowOptions); - -MUI.Window = new Class({ - - Implements: [Events, Options], - - options: MUI.Windows.windowOptions, - - initialize: function(options){ - this.setOptions(options); - - // Shorten object chain - var options = this.options; - - $extend(this, { - mochaControlsWidth: 0, - minimizebuttonX: 0, // Minimize button horizontal position - maximizebuttonX: 0, // Maximize button horizontal position - closebuttonX: 0, // Close button horizontal position - headerFooterShadow: options.headerHeight + options.footerHeight + (options.shadowBlur * 2), - oldTop: 0, - oldLeft: 0, - isMaximized: false, - isMinimized: false, - isCollapsed: false, - timestamp: $time() - }); - - if (options.type != 'window'){ - options.container = document.body; - options.minimizable = false; - } - if (!options.container){ - options.container = MUI.Desktop && MUI.Desktop.desktop ? MUI.Desktop.desktop : document.body; - } - - // Set this.options.resizable to default if it was not defined - if (options.resizable == null){ - if (options.type != 'window' || options.shape == 'gauge'){ - options.resizable = false; - } - else { - options.resizable = true; - } - } - - // Set this.options.draggable if it was not defined - if (options.draggable == null){ - options.draggable = options.type != 'window' ? false : true; - } - - // Gauges are not maximizable or resizable - if (options.shape == 'gauge' || options.type == 'notification'){ - options.collapsible = false; - options.maximizable = false; - options.contentBgColor = 'transparent'; - options.scrollbars = false; - options.footerHeight = 0; - } - if (options.type == 'notification'){ - options.closable = false; - options.headerHeight = 0; - } - - // Minimizable, dock is required and window cannot be modal - if (MUI.Dock && $(MUI.options.dock)){ - if (MUI.Dock.dock && options.type != 'modal' && options.type != 'modal2'){ - options.minimizable = options.minimizable; - } - } - else { - options.minimizable = false; - } - - // Maximizable, desktop is required - options.maximizable = MUI.Desktop && MUI.Desktop.desktop && options.maximizable && options.type != 'modal' && options.type != 'modal2'; - - if (this.options.type == 'modal2') { - this.options.shadowBlur = 0; - this.options.shadowOffset = {'x': 0, 'y': 0}; - this.options.useSpinner = false; - this.options.useCanvas = false; - this.options.footerHeight = 0; - this.options.headerHeight = 0; - } - - // If window has no ID, give it one. - options.id = options.id || 'win' + (++MUI.Windows.windowIDCount); - - this.windowEl = $(options.id); - - if (options.require.css.length || options.require.images.length){ - new MUI.Require({ - css: options.require.css, - images: options.require.images, - onload: function(){ - this.newWindow(); - }.bind(this) - }); - } - else { - this.newWindow(); - } - - // Return window object - return this; - }, - saveValues: function(){ - var coordinates = this.windowEl.getCoordinates(); - this.options.x = coordinates.left.toInt(); - this.options.y = coordinates.top.toInt(); - }, - - /* - - Internal Function: newWindow - - Arguments: - properties - - */ - newWindow: function(properties){ // options is not doing anything - - // Shorten object chain - var instances = MUI.Windows.instances; - var instanceID = MUI.Windows.instances.get(this.options.id); - var options = this.options; - - // Here we check to see if there is already a class instance for this window - if (instanceID) var instance = instanceID; - - // Check if window already exists and is not in progress of closing - if ( this.windowEl && !this.isClosing ){ - // Restore if minimized - if (instance.isMinimized){ - MUI.Dock.restoreMinimized(this.windowEl); - } - // Expand and focus if collapsed - else if (instance.isCollapsed){ - MUI.collapseToggle(this.windowEl); - setTimeout(MUI.focusWindow.pass(this.windowEl, this),10); - } - else if (this.windowEl.hasClass('windowClosed')){ - - if (instance.check) instance.check.show(); - - this.windowEl.removeClass('windowClosed'); - this.windowEl.setStyle('opacity', 0); - this.windowEl.addClass('mocha'); - - if (MUI.Dock && $(MUI.options.dock) && instance.options.type == 'window') { - var currentButton = $(instance.options.id + '_dockTab'); - if (currentButton != null) { - currentButton.show(); - } - MUI.Desktop.setDesktopSize(); - } - - instance.displayNewWindow(); - - } - // Else focus - else { - var coordinates = document.getCoordinates(); - if (this.windowEl.getStyle('left').toInt() > coordinates.width || this.windowEl.getStyle('top').toInt() > coordinates.height){ - MUI.centerWindow(this.windowEl); - } - setTimeout(MUI.focusWindow.pass(this.windowEl, this),10); - if (MUI.options.standardEffects == true) { - this.windowEl.shake(); - } - } - return; - } - else { - instances.set(options.id, this); - } - - this.isClosing = false; - this.fireEvent('onBeforeBuild'); - - // Create window div - MUI.Windows.indexLevel++; - this.windowEl = new Element('div', { - 'class': 'mocha', - 'id': options.id, - 'styles': { - 'position': 'absolute', - 'width': options.width, - 'height': options.height, - 'display': 'block', - 'opacity': 0, - 'zIndex': MUI.Windows.indexLevel += 2 - } - }); - - this.windowEl.store('instance', this); - - this.windowEl.addClass(options.addClass); - - if (options.type == 'modal2') { - this.windowEl.addClass('modal2'); - } - - // Fix a mouseover issue with gauges in IE7 - if ( MUI.ieLegacySupport && options.shape == 'gauge') { - this.windowEl.setStyle('backgroundImage', 'url(../images/skin/spacer.gif)'); - } - - if (options.loadMethod == 'iframe') { - options.padding = { top: 0, right: 0, bottom: 0, left: 0 }; - } - - // Insert sub elements inside windowEl - this.insertWindowElements(); - - // Set title - this.titleEl.set('html', options.title); - - this.contentWrapperEl.setStyle('overflow', 'hidden'); - - this.contentEl.setStyles({ - 'padding-top': options.padding.top, - 'padding-bottom': options.padding.bottom, - 'padding-left': options.padding.left, - 'padding-right': options.padding.right - }); - - if (options.shape == 'gauge'){ - if (options.useCanvasControls){ - this.canvasControlsEl.setStyle('visibility', 'hidden'); - } - else { - this.controlsEl.setStyle('visibility', 'hidden'); - } - this.windowEl.addEvent('mouseover', function(){ - this.mouseover = true; - var showControls = function(){ - if (this.mouseover != false){ - if (options.useCanvasControls){ - this.canvasControlsEl.setStyle('visibility', 'visible'); - } - else { - this.controlsEl.setStyle('visibility', 'visible'); - } - this.canvasHeaderEl.setStyle('visibility', 'visible'); - this.titleEl.show(); - } - }; - showControls.delay(0, this); - - }.bind(this)); - this.windowEl.addEvent('mouseleave', function(){ - this.mouseover = false; - if (this.options.useCanvasControls){ - this.canvasControlsEl.setStyle('visibility', 'hidden'); - } - else { - this.controlsEl.setStyle('visibility', 'hidden'); - } - this.canvasHeaderEl.setStyle('visibility', 'hidden'); - this.titleEl.hide(); - }.bind(this)); - } - - // Inject window into DOM - this.windowEl.inject(options.container); - - // Convert CSS colors to Canvas colors. - this.setColors(); - - if (options.type != 'notification'){ - this.setMochaControlsWidth(); - } - - // Add content to window. - MUI.updateContent({ - 'element': this.windowEl, - 'content': options.content, - 'method': options.method, - 'url': options.contentURL, - 'data': options.data, - 'onContentLoaded': null, - 'require': { - js: options.require.js, - onload: options.require.onload - } - }); - - // Add content to window toolbar. - if (this.options.toolbar == true){ - MUI.updateContent({ - 'element': this.windowEl, - 'childElement': this.toolbarEl, - 'content': options.toolbarContent, - 'loadMethod': 'xhr', - 'method': options.method, - 'url': options.toolbarURL, - 'data': options.toolbarData, - 'onContentLoaded': options.toolbarOnload - }); - } - - // Add content to window toolbar. - if (this.options.toolbar2 == true){ - MUI.updateContent({ - 'element': this.windowEl, - 'childElement': this.toolbar2El, - 'content': options.toolbar2Content, - 'loadMethod': 'xhr', - 'method': options.method, - 'url': options.toolbar2URL, - 'data': options.toolbar2Data, - 'onContentLoaded': options.toolbar2Onload - }); - } - - this.drawWindow(); - - // Attach events to the window - this.attachDraggable(); - this.attachResizable(); - this.setupEvents(); - - if (options.resizable){ - this.adjustHandles(); - } - - // Position window. If position not specified by user then center the window on the page. - if (options.container == document.body || options.container == MUI.Desktop.desktop){ - var dimensions = window.getSize(); - } - else { - var dimensions = $(this.options.container).getSize(); - } - - if (!options.y) { - if (MUI.Desktop && MUI.Desktop.desktop) { - var y = (dimensions.y * .5) - (this.windowEl.offsetHeight * .5); - if (y < -options.shadowBlur) y = -options.shadowBlur; - } - else { - var y = window.getScroll().y + (window.getSize().y * .5) - (this.windowEl.offsetHeight * .5); - if (y < -options.shadowBlur) y = -options.shadowBlur; - } - } - else { - var y = options.y - options.shadowBlur; - } - - if (!this.options.x) { - var x = (dimensions.x * .5) - (this.windowEl.offsetWidth * .5); - if (x < -options.shadowBlur) x = -options.shadowBlur; - } - else { - var x = options.x - options.shadowBlur; - } - - this.windowEl.setStyles({ - 'top': y, - 'left': x - }); - - // Create opacityMorph - - this.opacityMorph = new Fx.Morph(this.windowEl, { - 'duration': 350, - transition: Fx.Transitions.Sine.easeInOut, - onComplete: function(){ - if (MUI.ieLegacySupport){ - this.drawWindow(); - } - }.bind(this) - }); - - this.displayNewWindow(); - - // This is a generic morph that can be reused later by functions like centerWindow() - // It returns the windowEl element rather than this Class. - this.morph = new Fx.Morph(this.windowEl, { - 'duration': 200 - }); - this.windowEl.store('morph', this.morph); - - this.resizeMorph = new Fx.Elements([this.contentWrapperEl, this.windowEl], { - duration: 400, - transition: Fx.Transitions.Sine.easeInOut, - onStart: function(){ - this.resizeAnimation = this.drawWindow.periodical(20, this); - }.bind(this), - onComplete: function(){ - $clear(this.resizeAnimation); - this.drawWindow(); - // Show iframe - if ( this.iframeEl ) { - this.iframeEl.setStyle('visibility', 'visible'); - } - }.bind(this) - }); - this.windowEl.store('resizeMorph', this.resizeMorph); - - // Add check mark to menu if link exists in menu - // Need to make sure the check mark is not added to links not in menu - if ($(this.windowEl.id + 'LinkCheck')){ - this.check = new Element('div', { - 'class': 'check', - 'id': this.options.id + '_check' - }).inject(this.windowEl.id + 'LinkCheck'); - } - - if (this.options.closeAfter != false){ - MUI.closeWindow.delay(this.options.closeAfter, this, this.windowEl); - } - - if (MUI.Dock && $(MUI.options.dock) && this.options.type == 'window' ){ - MUI.Dock.createDockTab(this.windowEl); - } - - }, - displayNewWindow: function(){ - - options = this.options; - if (options.type == 'modal' || options.type == 'modal2') { - MUI.currentModal = this.windowEl; - if (Browser.Engine.trident4){ - $('modalFix').show(); - } - $('modalOverlay').show(); - if (MUI.options.advancedEffects == false){ - $('modalOverlay').setStyle('opacity', .6); - this.windowEl.setStyles({ - 'zIndex': 11000, - 'opacity': 1 - }); - } - else { - MUI.Modal.modalOverlayCloseMorph.cancel(); - MUI.Modal.modalOverlayOpenMorph.start({ - 'opacity': .6 - }); - this.windowEl.setStyles({ - 'zIndex': 11000 - }); - this.opacityMorph.start({ - 'opacity': 1 - }); - } - - $$('.dockTab').removeClass('activeDockTab'); - $$('.mocha').removeClass('isFocused'); - this.windowEl.addClass('isFocused'); - - } - else if (MUI.options.advancedEffects == false){ - this.windowEl.setStyle('opacity', 1); - setTimeout(MUI.focusWindow.pass(this.windowEl, this), 10); - } - else { - // IE cannot handle both element opacity and VML alpha at the same time. - if (MUI.ieLegacySupport){ - this.drawWindow(false); - } - this.opacityMorph.start({ - 'opacity': 1 - }); - setTimeout(MUI.focusWindow.pass(this.windowEl, this), 10); - } - - }, - setupEvents: function() { - var windowEl = this.windowEl; - // Set events - // Note: if a button does not exist, its due to properties passed to newWindow() stating otherwice - if (this.closeButtonEl){ - this.closeButtonEl.addEvent('click', function(e) { - new Event(e).stop(); - MUI.closeWindow(windowEl); - }.bind(this)); - } - - if (this.options.type == 'window'){ - windowEl.addEvent('mousedown', function(e) { - if (MUI.ieLegacySupport) { - new Event(e).stop(); - } - MUI.focusWindow(windowEl); - if (windowEl.getStyle('top').toInt() < -this.options.shadowBlur) { - windowEl.setStyle('top', -this.options.shadowBlur); - } - }.bind(this)); - } - - if (this.minimizeButtonEl) { - this.minimizeButtonEl.addEvent('click', function(e) { - new Event(e).stop(); - MUI.Dock.minimizeWindow(windowEl); - }.bind(this)); - } - - if (this.maximizeButtonEl) { - this.maximizeButtonEl.addEvent('click', function(e) { - new Event(e).stop(); - if (this.isMaximized) { - MUI.Desktop.restoreWindow(windowEl); - } else { - MUI.Desktop.maximizeWindow(windowEl); - } - }.bind(this)); - } - - if (this.options.collapsible == true){ - // Keep titlebar text from being selected on double click in Safari. - this.titleEl.addEvent('selectstart', function(e) { - e = new Event(e).stop(); - }.bind(this)); - - if (MUI.ieLegacySupport) { - this.titleBarEl.addEvent('mousedown', function(e) { - this.titleEl.setCapture(); - }.bind(this)); - this.titleBarEl.addEvent('mouseup', function(e) { - this.titleEl.releaseCapture(); - }.bind(this)); - } - - this.titleBarEl.addEvent('dblclick', function(e) { - e = new Event(e).stop(); - MUI.collapseToggle(this.windowEl); - }.bind(this)); - } - - }, - /* - - Internal Function: attachDraggable() - Make window draggable. - - */ - attachDraggable: function(){ - var windowEl = this.windowEl; - if (!this.options.draggable) return; - this.windowDrag = new Drag.Move(windowEl, { - handle: this.titleBarEl, - container: this.options.restrict == true ? $(this.options.container) : false, - grid: this.options.draggableGrid, - limit: this.options.draggableLimit, - snap: this.options.draggableSnap, - onStart: function() { - if (this.options.type != 'modal' && this.options.type != 'modal2'){ - MUI.focusWindow(windowEl); - $('windowUnderlay').show(); - } - if (this.iframeEl) { - if (!MUI.ieLegacySupport) { - this.iframeEl.setStyle('visibility', 'hidden'); - } - else { - this.iframeEl.hide(); - } - } - }.bind(this), - onComplete: function() { - if (this.options.type != 'modal' && this.options.type != 'modal2') { - $('windowUnderlay').hide(); - } - if ( this.iframeEl ){ - if (!MUI.ieLegacySupport) { - this.iframeEl.setStyle('visibility', 'visible'); - } - else { - this.iframeEl.show(); - } - } - // Store new position in options. - this.saveValues(); - }.bind(this) - }); - }, - /* - - Internal Function: attachResizable - Make window resizable. - - */ - attachResizable: function(){ - var windowEl = this.windowEl; - if (!this.options.resizable) return; - this.resizable1 = this.windowEl.makeResizable({ - handle: [this.n, this.ne, this.nw], - limit: { - y: [ - function(){ - return this.windowEl.getStyle('top').toInt() + this.windowEl.getStyle('height').toInt() - this.options.resizeLimit.y[1]; - }.bind(this), - function(){ - return this.windowEl.getStyle('top').toInt() + this.windowEl.getStyle('height').toInt() - this.options.resizeLimit.y[0]; - }.bind(this) - ] - }, - modifiers: {x: false, y: 'top'}, - onStart: function(){ - this.resizeOnStart(); - this.coords = this.contentWrapperEl.getCoordinates(); - this.y2 = this.coords.top.toInt() + this.contentWrapperEl.offsetHeight; - }.bind(this), - onDrag: function(){ - this.coords = this.contentWrapperEl.getCoordinates(); - this.contentWrapperEl.setStyle('height', this.y2 - this.coords.top.toInt()); - this.resizeOnDrag(); - }.bind(this), - onComplete: function(){ - this.resizeOnComplete(); - }.bind(this) - }); - - this.resizable2 = this.contentWrapperEl.makeResizable({ - handle: [this.e, this.ne], - limit: { - x: [this.options.resizeLimit.x[0] - (this.options.shadowBlur * 2), this.options.resizeLimit.x[1] - (this.options.shadowBlur * 2) ] - }, - modifiers: {x: 'width', y: false}, - onStart: function(){ - this.resizeOnStart(); - }.bind(this), - onDrag: function(){ - this.resizeOnDrag(); - }.bind(this), - onComplete: function(){ - this.resizeOnComplete(); - }.bind(this) - }); - - this.resizable3 = this.contentWrapperEl.makeResizable({ - container: this.options.restrict == true ? $(this.options.container) : false, - handle: this.se, - limit: { - x: [this.options.resizeLimit.x[0] - (this.options.shadowBlur * 2), this.options.resizeLimit.x[1] - (this.options.shadowBlur * 2) ], - y: [this.options.resizeLimit.y[0] - this.headerFooterShadow, this.options.resizeLimit.y[1] - this.headerFooterShadow] - }, - modifiers: {x: 'width', y: 'height'}, - onStart: function(){ - this.resizeOnStart(); - }.bind(this), - onDrag: function(){ - this.resizeOnDrag(); - }.bind(this), - onComplete: function(){ - this.resizeOnComplete(); - }.bind(this) - }); - - this.resizable4 = this.contentWrapperEl.makeResizable({ - handle: [this.s, this.sw], - limit: { - y: [this.options.resizeLimit.y[0] - this.headerFooterShadow, this.options.resizeLimit.y[1] - this.headerFooterShadow] - }, - modifiers: {x: false, y: 'height'}, - onStart: function(){ - this.resizeOnStart(); - }.bind(this), - onDrag: function(){ - this.resizeOnDrag(); - }.bind(this), - onComplete: function(){ - this.resizeOnComplete(); - }.bind(this) - }); - - this.resizable5 = this.windowEl.makeResizable({ - handle: [this.w, this.sw, this.nw], - limit: { - x: [ - function(){ - return this.windowEl.getStyle('left').toInt() + this.windowEl.getStyle('width').toInt() - this.options.resizeLimit.x[1]; - }.bind(this), - function(){ - return this.windowEl.getStyle('left').toInt() + this.windowEl.getStyle('width').toInt() - this.options.resizeLimit.x[0]; - }.bind(this) - ] - }, - modifiers: {x: 'left', y: false}, - onStart: function(){ - this.resizeOnStart(); - this.coords = this.contentWrapperEl.getCoordinates(); - this.x2 = this.coords.left.toInt() + this.contentWrapperEl.offsetWidth; - }.bind(this), - onDrag: function(){ - this.coords = this.contentWrapperEl.getCoordinates(); - this.contentWrapperEl.setStyle('width', this.x2 - this.coords.left.toInt()); - this.resizeOnDrag(); - }.bind(this), - onComplete: function(){ - this.resizeOnComplete(); - }.bind(this) - }); - - }, - resizeOnStart: function(){ - $('windowUnderlay').show(); - if (this.iframeEl){ - if (!MUI.ieLegacySupport) { - this.iframeEl.setStyle('visibility', 'hidden'); - } - else { - this.iframeEl.hide(); - } - } - }, - resizeOnDrag: function(){ - this.drawWindow(); - this.adjustHandles(); - }, - resizeOnComplete: function(){ - $('windowUnderlay').hide(); - if (this.iframeEl){ - if (!MUI.ieLegacySupport) { - this.iframeEl.setStyle('visibility', 'visible'); - } - else { - this.iframeEl.show(); - // The following hack is to get IE8 RC1 IE8 Standards Mode to properly resize an iframe - // when only the vertical dimension is changed. - this.iframeEl.setStyle('width', '99%'); - this.iframeEl.setStyle('height', this.contentWrapperEl.offsetHeight); - this.iframeEl.setStyle('width', '100%'); - this.iframeEl.setStyle('height', this.contentWrapperEl.offsetHeight); - } - } - - // Resize panels if there are any - if (this.contentWrapperEl.getChildren('.column') != null) { - MUI.rWidth(this.contentWrapperEl); - this.contentWrapperEl.getChildren('.column').each(function(column){ - MUI.panelHeight(column); - }); - } - - this.fireEvent('onResize', this.windowEl); - }, - adjustHandles: function(){ - - var shadowBlur = this.options.shadowBlur; - var shadowBlur2x = shadowBlur * 2; - var shadowOffset = this.options.shadowOffset; - var top = shadowBlur - shadowOffset.y - 1; - var right = shadowBlur + shadowOffset.x - 1; - var bottom = shadowBlur + shadowOffset.y - 1; - var left = shadowBlur - shadowOffset.x - 1; - - var coordinates = this.windowEl.getCoordinates(); - var width = coordinates.width - shadowBlur2x + 2; - var height = coordinates.height - shadowBlur2x + 2; - - this.n.setStyles({ - 'top': top, - 'left': left + 10, - 'width': width - 20 - }); - this.e.setStyles({ - 'top': top + 10, - 'right': right, - 'height': height - 30 - }); - this.s.setStyles({ - 'bottom': bottom, - 'left': left + 10, - 'width': width - 30 - }); - this.w.setStyles({ - 'top': top + 10, - 'left': left, - 'height': height - 20 - }); - this.ne.setStyles({ - 'top': top, - 'right': right - }); - this.se.setStyles({ - 'bottom': bottom, - 'right': right - }); - this.sw.setStyles({ - 'bottom': bottom, - 'left': left - }); - this.nw.setStyles({ - 'top': top, - 'left': left - }); - }, - detachResizable: function(){ - this.resizable1.detach(); - this.resizable2.detach(); - this.resizable3.detach(); - this.resizable4.detach(); - this.resizable5.detach(); - this.windowEl.getElements('.handle').hide(); - }, - reattachResizable: function(){ - this.resizable1.attach(); - this.resizable2.attach(); - this.resizable3.attach(); - this.resizable4.attach(); - this.resizable5.attach(); - this.windowEl.getElements('.handle').show(); - }, - /* - - Internal Function: insertWindowElements - - Arguments: - windowEl - - */ - insertWindowElements: function(){ - - var options = this.options; - var height = options.height; - var width = options.width; - var id = options.id; - - var cache = {}; - - if (Browser.Engine.trident4){ - cache.zIndexFixEl = new Element('iframe', { - 'id': id + '_zIndexFix', - 'class': 'zIndexFix', - 'scrolling': 'no', - 'marginWidth': 0, - 'marginHeight': 0, - 'src': '', - 'styles': { - 'position': 'absolute' // This is set here to make theme transitions smoother - } - }).inject(this.windowEl); - } - - cache.overlayEl = new Element('div', { - 'id': id + '_overlay', - 'class': 'mochaOverlay', - 'styles': { - 'position': 'absolute', // This is set here to make theme transitions smoother - 'top': 0, - 'left': 0 - } - }).inject(this.windowEl); - - cache.titleBarEl = new Element('div', { - 'id': id + '_titleBar', - 'class': 'mochaTitlebar', - 'styles': { - 'cursor': options.draggable ? 'move' : 'default' - } - }).inject(cache.overlayEl, 'top'); - - cache.titleEl = new Element('h3', { - 'id': id + '_title', - 'class': 'mochaTitle' - }).inject(cache.titleBarEl); - - if (options.icon != false){ - cache.titleEl.setStyles({ - 'padding-left': 28, - 'background': 'url(' + options.icon + ') 5px 4px no-repeat' - }); - } - - cache.contentBorderEl = new Element('div', { - 'id': id + '_contentBorder', - 'class': 'mochaContentBorder' - }).inject(cache.overlayEl); - - if (options.toolbar){ - cache.toolbarWrapperEl = new Element('div', { - 'id': id + '_toolbarWrapper', - 'class': 'mochaToolbarWrapper', - 'styles': { 'height': options.toolbarHeight } - }).inject(cache.contentBorderEl, options.toolbarPosition == 'bottom' ? 'after' : 'before'); - - if (options.toolbarPosition == 'bottom') { - cache.toolbarWrapperEl.addClass('bottom'); - } - cache.toolbarEl = new Element('div', { - 'id': id + '_toolbar', - 'class': 'mochaToolbar', - 'styles': { 'height': options.toolbarHeight } - }).inject(cache.toolbarWrapperEl); - } - - if (options.toolbar2){ - cache.toolbar2WrapperEl = new Element('div', { - 'id': id + '_toolbar2Wrapper', - 'class': 'mochaToolbarWrapper', - 'styles': { 'height': options.toolbar2Height } - }).inject(cache.contentBorderEl, options.toolbar2Position == 'bottom' ? 'after' : 'before'); - - if (options.toolbar2Position == 'bottom') { - cache.toolbar2WrapperEl.addClass('bottom'); - } - cache.toolbar2El = new Element('div', { - 'id': id + '_toolbar2', - 'class': 'mochaToolbar', - 'styles': { 'height': options.toolbar2Height } - }).inject(cache.toolbar2WrapperEl); - } - - cache.contentWrapperEl = new Element('div', { - 'id': id + '_contentWrapper', - 'class': 'mochaContentWrapper', - 'styles': { - 'width': width + 'px', - 'height': height + 'px' - } - }).inject(cache.contentBorderEl); - - if (this.options.shape == 'gauge'){ - cache.contentBorderEl.setStyle('borderWidth', 0); - } - - cache.contentEl = new Element('div', { - 'id': id + '_content', - 'class': 'mochaContent' - }).inject(cache.contentWrapperEl); - - if (this.options.useCanvas == true && !MUI.ieLegacySupport) { - cache.canvasEl = new Element('canvas', { - 'id': id + '_canvas', - 'class': 'mochaCanvas', - 'width': 10, - 'height': 10 - }).inject(this.windowEl); - } - - if (this.options.useCanvas == true && MUI.ieLegacySupport) { - cache.canvasEl = new Element('canvas', { - 'id': id + '_canvas', - 'class': 'mochaCanvas', - 'width': 50000, // IE8 excanvas requires these large numbers - 'height': 20000, - 'styles': { - 'position': 'absolute', - 'top': 0, - 'left': 0 - } - }).inject(this.windowEl); - - if (MUI.ieLegacySupport && MUI.ieSupport == 'excanvas'){ - G_vmlCanvasManager.initElement(cache.canvasEl); - cache.canvasEl = this.windowEl.getElement('.mochaCanvas'); - } - } - - cache.controlsEl = new Element('div', { - 'id': id + '_controls', - 'class': 'mochaControls' - }).inject(cache.overlayEl, 'after'); - - if (options.useCanvasControls == true){ - cache.canvasControlsEl = new Element('canvas', { - 'id': id + '_canvasControls', - 'class': 'mochaCanvasControls', - 'width': 14, - 'height': 14 - }).inject(this.windowEl); - - if (MUI.ieLegacySupport && MUI.ieSupport == 'excanvas'){ - G_vmlCanvasManager.initElement(cache.canvasControlsEl); - cache.canvasControlsEl = this.windowEl.getElement('.mochaCanvasControls'); - } - } - - if (options.closable){ - cache.closeButtonEl = new Element('div', { - 'id': id + '_closeButton', - 'class': 'mochaCloseButton mochaWindowButton', - 'title': 'Close' - }).inject(cache.controlsEl); - } - - if (options.maximizable){ - cache.maximizeButtonEl = new Element('div', { - 'id': id + '_maximizeButton', - 'class': 'mochaMaximizeButton mochaWindowButton', - 'title': 'Maximize' - }).inject(cache.controlsEl); - } - - if (options.minimizable){ - cache.minimizeButtonEl = new Element('div', { - 'id': id + '_minimizeButton', - 'class': 'mochaMinimizeButton mochaWindowButton', - 'title': 'Minimize' - }).inject(cache.controlsEl); - } - - if (options.useSpinner == true && options.shape != 'gauge' && options.type != 'notification'){ - cache.spinnerEl = new Element('div', { - 'id': id + '_spinner', - 'class': 'mochaSpinner', - 'width': 16, - 'height': 16 - }).inject(this.windowEl, 'bottom'); - } - - if (this.options.shape == 'gauge'){ - cache.canvasHeaderEl = new Element('canvas', { - 'id': id + '_canvasHeader', - 'class': 'mochaCanvasHeader', - 'width': this.options.width, - 'height': 26 - }).inject(this.windowEl, 'bottom'); - - if (MUI.ieLegacySupport && MUI.ieSupport == 'excanvas'){ - G_vmlCanvasManager.initElement(cache.canvasHeaderEl); - cache.canvasHeaderEl = this.windowEl.getElement('.mochaCanvasHeader'); - } - } - - if ( MUI.ieLegacySupport ){ - cache.overlayEl.setStyle('zIndex', 2); - } - - if (options.resizable){ - cache.n = new Element('div', { - 'id': id + '_resizeHandle_n', - 'class': 'handle', - 'styles': { - 'top': 0, - 'left': 10, - 'cursor': 'n-resize' - } - }).inject(cache.overlayEl, 'after'); - - cache.ne = new Element('div', { - 'id': id + '_resizeHandle_ne', - 'class': 'handle corner', - 'styles': { - 'top': 0, - 'right': 0, - 'cursor': 'ne-resize' - } - }).inject(cache.overlayEl, 'after'); - - cache.e = new Element('div', { - 'id': id + '_resizeHandle_e', - 'class': 'handle', - 'styles': { - 'top': 10, - 'right': 0, - 'cursor': 'e-resize' - } - }).inject(cache.overlayEl, 'after'); - - cache.se = new Element('div', { - 'id': id + '_resizeHandle_se', - 'class': 'handle cornerSE', - 'styles': { - 'bottom': 0, - 'right': 0, - 'cursor': 'se-resize' - } - }).inject(cache.overlayEl, 'after'); - - cache.s = new Element('div', { - 'id': id + '_resizeHandle_s', - 'class': 'handle', - 'styles': { - 'bottom': 0, - 'left': 10, - 'cursor': 's-resize' - } - }).inject(cache.overlayEl, 'after'); - - cache.sw = new Element('div', { - 'id': id + '_resizeHandle_sw', - 'class': 'handle corner', - 'styles': { - 'bottom': 0, - 'left': 0, - 'cursor': 'sw-resize' - } - }).inject(cache.overlayEl, 'after'); - - cache.w = new Element('div', { - 'id': id + '_resizeHandle_w', - 'class': 'handle', - 'styles': { - 'top': 10, - 'left': 0, - 'cursor': 'w-resize' - } - }).inject(cache.overlayEl, 'after'); - - cache.nw = new Element('div', { - 'id': id + '_resizeHandle_nw', - 'class': 'handle corner', - 'styles': { - 'top': 0, - 'left': 0, - 'cursor': 'nw-resize' - } - }).inject(cache.overlayEl, 'after'); - } - $extend(this, cache); - - }, - /* - - Convert CSS colors to Canvas colors. - - */ - setColors: function(){ - - if (this.options.useCanvas == true) { - - // Set TitlebarColor - var pattern = /\?(.*?)\)/; - if (this.titleBarEl.getStyle('backgroundImage') != 'none'){ - var gradient = this.titleBarEl.getStyle('backgroundImage'); - gradient = gradient.match(pattern)[1]; - gradient = gradient.parseQueryString(); - var gradientFrom = gradient.from; - var gradientTo = gradient.to.replace(/\"/, ''); // IE7 was adding a quotation mark in. No idea why. - - this.options.headerStartColor = new Color(gradientFrom); - this.options.headerStopColor = new Color(gradientTo); - this.titleBarEl.addClass('replaced'); - } - else if (this.titleBarEl.getStyle('background-color') !== '' && this.titleBarEl.getStyle('background-color') !== 'transparent') { - this.options.headerStartColor = new Color(this.titleBarEl.getStyle('background-color')).mix('#fff', 20); - this.options.headerStopColor = new Color(this.titleBarEl.getStyle('background-color')).mix('#000', 20); - this.titleBarEl.addClass('replaced'); - } - - // Set BodyBGColor - if (this.windowEl.getStyle('background-color') !== '' && this.windowEl.getStyle('background-color') !== 'transparent') { - this.options.bodyBgColor = new Color(this.windowEl.getStyle('background-color')); - this.windowEl.addClass('replaced'); - } - - // Set resizableColor, the color of the SE corner resize handle - if (this.options.resizable && this.se.getStyle('background-color') !== '' && this.se.getStyle('background-color') !== 'transparent') { - this.options.resizableColor = new Color(this.se.getStyle('background-color')); - this.se.addClass('replaced'); - } - - } - - if (this.options.useCanvasControls == true){ - - if (this.minimizeButtonEl){ - - // Set Minimize Button Foreground Color - if (this.minimizeButtonEl.getStyle('color') !== '' && this.minimizeButtonEl.getStyle('color') !== 'transparent') { - this.options.minimizeColor = new Color(this.minimizeButtonEl.getStyle('color')); - } - - // Set Minimize Button Background Color - if (this.minimizeButtonEl.getStyle('background-color') !== '' && this.minimizeButtonEl.getStyle('background-color') !== 'transparent') { - this.options.minimizeBgColor = new Color(this.minimizeButtonEl.getStyle('background-color')); - this.minimizeButtonEl.addClass('replaced'); - } - - } - - if (this.maximizeButtonEl){ - - // Set Maximize Button Foreground Color - if (this.maximizeButtonEl.getStyle('color') !== '' && this.maximizeButtonEl.getStyle('color') !== 'transparent') { - this.options.maximizeColor = new Color(this.maximizeButtonEl.getStyle('color')); - } - - // Set Maximize Button Background Color - if (this.maximizeButtonEl.getStyle('background-color') !== '' && this.maximizeButtonEl.getStyle('background-color') !== 'transparent') { - this.options.maximizeBgColor = new Color(this.maximizeButtonEl.getStyle('background-color')); - this.maximizeButtonEl.addClass('replaced'); - } - - } - - if (this.closeButtonEl){ - - // Set Close Button Foreground Color - if (this.closeButtonEl.getStyle('color') !== '' && this.closeButtonEl.getStyle('color') !== 'transparent') { - this.options.closeColor = new Color(this.closeButtonEl.getStyle('color')); - } - - // Set Close Button Background Color - if (this.closeButtonEl.getStyle('background-color') !== '' && this.closeButtonEl.getStyle('background-color') !== 'transparent') { - this.options.closeBgColor = new Color(this.closeButtonEl.getStyle('background-color')); - this.closeButtonEl.addClass('replaced'); - } - - } - } - }, - /* - - Internal function: drawWindow - This is where we create the canvas GUI - - Arguments: - windowEl: the $(window) - shadows: (boolean) false will draw a window without shadows - - */ - drawWindow: function(shadows) { - - if (this.drawingWindow == true) return; - this.drawingWindow = true; - - if (this.isCollapsed){ - this.drawWindowCollapsed(shadows); - return; - } - - var windowEl = this.windowEl; - - var options = this.options; - var shadowBlur = options.shadowBlur; - var shadowBlur2x = shadowBlur * 2; - var shadowOffset = this.options.shadowOffset; - - this.overlayEl.setStyles({ - 'width': this.contentWrapperEl.offsetWidth - }); - - // Resize iframe when window is resized - if (this.iframeEl) { - this.iframeEl.setStyle('height', this.contentWrapperEl.offsetHeight); - } - - var borderHeight = this.contentBorderEl.getStyle('margin-top').toInt() + this.contentBorderEl.getStyle('margin-bottom').toInt(); - var toolbarHeight = this.toolbarWrapperEl ? this.toolbarWrapperEl.getStyle('height').toInt() + this.toolbarWrapperEl.getStyle('margin-top').toInt() : 0; - var toolbar2Height = this.toolbar2WrapperEl ? this.toolbar2WrapperEl.getStyle('height').toInt() + this.toolbar2WrapperEl.getStyle('margin-top').toInt() : 0; - - this.headerFooterShadow = options.headerHeight + options.footerHeight + shadowBlur2x; - var height = this.contentWrapperEl.getStyle('height').toInt() + this.headerFooterShadow + toolbarHeight + toolbar2Height + borderHeight; - var width = this.contentWrapperEl.getStyle('width').toInt() + shadowBlur2x; - this.windowEl.setStyles({ - 'height': height, - 'width': width - }); - - this.overlayEl.setStyles({ - 'height': height, - 'top': shadowBlur - shadowOffset.y, - 'left': shadowBlur - shadowOffset.x - }); - - if (this.options.useCanvas == true) { - if (MUI.ieLegacySupport) { - this.canvasEl.height = 20000; - this.canvasEl.width = 50000; - } - this.canvasEl.height = height; - this.canvasEl.width = width; - } - - // Part of the fix for IE6 select z-index bug - if (Browser.Engine.trident4){ - this.zIndexFixEl.setStyles({ - 'width': width, - 'height': height - }) - } - - this.titleBarEl.setStyles({ - 'width': width - shadowBlur2x, - 'height': options.headerHeight - }); - - // Make sure loading icon is placed correctly. - if (options.useSpinner == true && options.shape != 'gauge' && options.type != 'notification'){ - this.spinnerEl.setStyles({ - 'left': shadowBlur - shadowOffset.x + 3, - 'bottom': shadowBlur + shadowOffset.y + 4 - }); - } - - if (this.options.useCanvas != false) { - - // Draw Window - var ctx = this.canvasEl.getContext('2d'); - ctx.clearRect(0, 0, width, height); - - switch (options.shape) { - case 'box': - this.drawBox(ctx, width, height, shadowBlur, shadowOffset, shadows); - break; - case 'gauge': - this.drawGauge(ctx, width, height, shadowBlur, shadowOffset, shadows); - break; - } - - if (options.resizable){ - MUI.triangle( - ctx, - width - (shadowBlur + shadowOffset.x + 17), - height - (shadowBlur + shadowOffset.y + 18), - 11, - 11, - options.resizableColor, - 1.0 - ); - } - - // Invisible dummy object. The last element drawn is not rendered consistently while resizing in IE6 and IE7 - if (MUI.ieLegacySupport){ - MUI.triangle(ctx, 0, 0, 10, 10, options.resizableColor, 0); - } - } - - if (options.type != 'notification' && options.useCanvasControls == true){ - this.drawControls(width, height, shadows); - } - - // Resize panels if there are any - if (MUI.Desktop && this.contentWrapperEl.getChildren('.column').length != 0) { - MUI.rWidth(this.contentWrapperEl); - this.contentWrapperEl.getChildren('.column').each(function(column){ - MUI.panelHeight(column); - }); - } - - this.drawingWindow = false; - return this; - - }, - drawWindowCollapsed: function(shadows) { - - var windowEl = this.windowEl; - - var options = this.options; - var shadowBlur = options.shadowBlur; - var shadowBlur2x = shadowBlur * 2; - var shadowOffset = options.shadowOffset; - - var headerShadow = options.headerHeight + shadowBlur2x + 2; - var height = headerShadow; - var width = this.contentWrapperEl.getStyle('width').toInt() + shadowBlur2x; - this.windowEl.setStyle('height', height); - - this.overlayEl.setStyles({ - 'height': height, - 'top': shadowBlur - shadowOffset.y, - 'left': shadowBlur - shadowOffset.x - }); - - // Part of the fix for IE6 select z-index bug - if (Browser.Engine.trident4){ - this.zIndexFixEl.setStyles({ - 'width': width, - 'height': height - }); - } - - // Set width - this.windowEl.setStyle('width', width); - this.overlayEl.setStyle('width', width); - this.titleBarEl.setStyles({ - 'width': width - shadowBlur2x, - 'height': options.headerHeight - }); - - // Draw Window - if (this.options.useCanvas != false) { - this.canvasEl.height = height; - this.canvasEl.width = width; - - var ctx = this.canvasEl.getContext('2d'); - ctx.clearRect(0, 0, width, height); - - this.drawBoxCollapsed(ctx, width, height, shadowBlur, shadowOffset, shadows); - if (options.useCanvasControls == true) { - this.drawControls(width, height, shadows); - } - - // Invisible dummy object. The last element drawn is not rendered consistently while resizing in IE6 and IE7 - if (MUI.ieLegacySupport){ - MUI.triangle(ctx, 0, 0, 10, 10, options.resizableColor, 0); - } - } - - this.drawingWindow = false; - return this; - - }, - drawControls : function(width, height, shadows){ - var options = this.options; - var shadowBlur = options.shadowBlur; - var shadowOffset = options.shadowOffset; - var controlsOffset = options.controlsOffset; - - // Make sure controls are placed correctly. - this.controlsEl.setStyles({ - 'right': shadowBlur + shadowOffset.x + controlsOffset.right, - 'top': shadowBlur - shadowOffset.y + controlsOffset.top - }); - - this.canvasControlsEl.setStyles({ - 'right': shadowBlur + shadowOffset.x + controlsOffset.right, - 'top': shadowBlur - shadowOffset.y + controlsOffset.top - }); - - // Calculate X position for controlbuttons - //var mochaControlsWidth = 52; - this.closebuttonX = options.closable ? this.mochaControlsWidth - 7 : this.mochaControlsWidth + 12; - this.maximizebuttonX = this.closebuttonX - (options.maximizable ? 19 : 0); - this.minimizebuttonX = this.maximizebuttonX - (options.minimizable ? 19 : 0); - - var ctx2 = this.canvasControlsEl.getContext('2d'); - ctx2.clearRect(0, 0, 100, 100); - - if (this.options.closable){ - this.closebutton( - ctx2, - this.closebuttonX, - 7, - options.closeBgColor, - 1.0, - options.closeColor, - 1.0 - ); - } - if (this.options.maximizable){ - this.maximizebutton( - ctx2, - this.maximizebuttonX, - 7, - options.maximizeBgColor, - 1.0, - options.maximizeColor, - 1.0 - ); - } - if (this.options.minimizable){ - this.minimizebutton( - ctx2, - this.minimizebuttonX, - 7, - options.minimizeBgColor, - 1.0, - options.minimizeColor, - 1.0 - ); - } - // Invisible dummy object. The last element drawn is not rendered consistently while resizing in IE6 and IE7 - if (MUI.ieLegacySupport){ - MUI.circle(ctx2, 0, 0, 3, this.options.resizableColor, 0); - } - - }, - drawBox: function(ctx, width, height, shadowBlur, shadowOffset, shadows){ - - var options = this.options; - var shadowBlur2x = shadowBlur * 2; - var cornerRadius = this.options.cornerRadius; - - // This is the drop shadow. It is created onion style. - if ( shadows != false ) { - for (var x = 0; x <= shadowBlur; x++){ - MUI.roundedRect( - ctx, - shadowOffset.x + x, - shadowOffset.y + x, - width - (x * 2) - shadowOffset.x, - height - (x * 2) - shadowOffset.y, - cornerRadius + (shadowBlur - x), - [0, 0, 0], - x == shadowBlur ? .29 : .065 + (x * .01) - ); - } - } - // Window body. - this.bodyRoundedRect( - ctx, // context - shadowBlur - shadowOffset.x, // x - shadowBlur - shadowOffset.y, // y - width - shadowBlur2x, // width - height - shadowBlur2x, // height - cornerRadius, // corner radius - options.bodyBgColor // Footer color - ); - - if (this.options.type != 'notification'){ - // Window header. - this.topRoundedRect( - ctx, // context - shadowBlur - shadowOffset.x, // x - shadowBlur - shadowOffset.y, // y - width - shadowBlur2x, // width - options.headerHeight, // height - cornerRadius, // corner radius - options.headerStartColor, // Header gradient's top color - options.headerStopColor // Header gradient's bottom color - ); - } - }, - drawBoxCollapsed: function(ctx, width, height, shadowBlur, shadowOffset, shadows){ - - var options = this.options; - var shadowBlur2x = shadowBlur * 2; - var cornerRadius = options.cornerRadius; - - // This is the drop shadow. It is created onion style. - if ( shadows != false ){ - for (var x = 0; x <= shadowBlur; x++){ - MUI.roundedRect( - ctx, - shadowOffset.x + x, - shadowOffset.y + x, - width - (x * 2) - shadowOffset.x, - height - (x * 2) - shadowOffset.y, - cornerRadius + (shadowBlur - x), - [0, 0, 0], - x == shadowBlur ? .3 : .06 + (x * .01) - ); - } - } - - // Window header - this.topRoundedRect2( - ctx, // context - shadowBlur - shadowOffset.x, // x - shadowBlur - shadowOffset.y, // y - width - shadowBlur2x, // width - options.headerHeight + 2, // height - cornerRadius, // corner radius - options.headerStartColor, // Header gradient's top color - options.headerStopColor // Header gradient's bottom color - ); - - }, - drawGauge: function(ctx, width, height, shadowBlur, shadowOffset, shadows){ - var options = this.options; - var radius = (width * .5) - (shadowBlur) + 16; - if (shadows != false) { - for (var x = 0; x <= shadowBlur; x++){ - MUI.circle( - ctx, - width * .5 + shadowOffset.x, - (height + options.headerHeight) * .5 + shadowOffset.x, - (width *.5) - (x * 2) - shadowOffset.x, - [0, 0, 0], - x == shadowBlur ? .75 : .075 + (x * .04) - ); - } - } - MUI.circle( - ctx, - width * .5 - shadowOffset.x, - (height + options.headerHeight) * .5 - shadowOffset.y, - (width *.5) - shadowBlur, - options.bodyBgColor, - 1 - ); - - // Draw gauge header - this.canvasHeaderEl.setStyles({ - 'top': shadowBlur - shadowOffset.y, - 'left': shadowBlur - shadowOffset.x - }); - var ctx = this.canvasHeaderEl.getContext('2d'); - ctx.clearRect(0, 0, width, 100); - ctx.beginPath(); - ctx.lineWidth = 24; - ctx.lineCap = 'round'; - ctx.moveTo(13, 13); - ctx.lineTo(width - (shadowBlur*2) - 13, 13); - ctx.strokeStyle = 'rgba(0, 0, 0, .65)'; - ctx.stroke(); - }, - bodyRoundedRect: function(ctx, x, y, width, height, radius, rgb){ - ctx.fillStyle = 'rgba(' + rgb.join(',') + ', 1)'; - ctx.beginPath(); - ctx.moveTo(x, y + radius); - ctx.lineTo(x, y + height - radius); - ctx.quadraticCurveTo(x, y + height, x + radius, y + height); - ctx.lineTo(x + width - radius, y + height); - ctx.quadraticCurveTo(x + width, y + height, x + width, y + height - radius); - ctx.lineTo(x + width, y + radius); - ctx.quadraticCurveTo(x + width, y, x + width - radius, y); - ctx.lineTo(x + radius, y); - ctx.quadraticCurveTo(x, y, x, y + radius); - ctx.fill(); - - }, - topRoundedRect: function(ctx, x, y, width, height, radius, headerStartColor, headerStopColor){ - var lingrad = ctx.createLinearGradient(0, 0, 0, height); - lingrad.addColorStop(0, 'rgb(' + headerStartColor.join(',') + ')'); - lingrad.addColorStop(1, 'rgb(' + headerStopColor.join(',') + ')'); - ctx.fillStyle = lingrad; - ctx.beginPath(); - ctx.moveTo(x, y); - ctx.lineTo(x, y + height); - ctx.lineTo(x + width, y + height); - ctx.lineTo(x + width, y + radius); - ctx.quadraticCurveTo(x + width, y, x + width - radius, y); - ctx.lineTo(x + radius, y); - ctx.quadraticCurveTo(x, y, x, y + radius); - ctx.fill(); - - }, - topRoundedRect2: function(ctx, x, y, width, height, radius, headerStartColor, headerStopColor){ - // Chrome is having trouble rendering the LinearGradient in this particular case - if (navigator.userAgent.toLowerCase().indexOf('chrome') > -1) { - ctx.fillStyle = 'rgba(' + headerStopColor.join(',') + ', 1)'; - } - else { - var lingrad = ctx.createLinearGradient(0, this.options.shadowBlur - 1, 0, height + this.options.shadowBlur + 3); - lingrad.addColorStop(0, 'rgb(' + headerStartColor.join(',') + ')'); - lingrad.addColorStop(1, 'rgb(' + headerStopColor.join(',') + ')'); - ctx.fillStyle = lingrad; - } - ctx.beginPath(); - ctx.moveTo(x, y + radius); - ctx.lineTo(x, y + height - radius); - ctx.quadraticCurveTo(x, y + height, x + radius, y + height); - ctx.lineTo(x + width - radius, y + height); - ctx.quadraticCurveTo(x + width, y + height, x + width, y + height - radius); - ctx.lineTo(x + width, y + radius); - ctx.quadraticCurveTo(x + width, y, x + width - radius, y); - ctx.lineTo(x + radius, y); - ctx.quadraticCurveTo(x, y, x, y + radius); - ctx.fill(); - }, - maximizebutton: function(ctx, x, y, rgbBg, aBg, rgb, a){ - // Circle - ctx.beginPath(); - ctx.arc(x, y, 7, 0, Math.PI*2, true); - ctx.fillStyle = 'rgba(' + rgbBg.join(',') + ',' + aBg + ')'; - ctx.fill(); - // X sign - ctx.strokeStyle = 'rgba(' + rgb.join(',') + ',' + a + ')'; - ctx.lineWidth = 2; - ctx.beginPath(); - ctx.moveTo(x, y - 3.5); - ctx.lineTo(x, y + 3.5); - ctx.moveTo(x - 3.5, y); - ctx.lineTo(x + 3.5, y); - ctx.stroke(); - }, - closebutton: function(ctx, x, y, rgbBg, aBg, rgb, a){ - // Circle - ctx.beginPath(); - ctx.arc(x, y, 7, 0, Math.PI*2, true); - ctx.fillStyle = 'rgba(' + rgbBg.join(',') + ',' + aBg + ')'; - ctx.fill(); - // Plus sign - ctx.strokeStyle = 'rgba(' + rgb.join(',') + ',' + a + ')'; - ctx.lineWidth = 2; - ctx.beginPath(); - ctx.moveTo(x - 3, y - 3); - ctx.lineTo(x + 3, y + 3); - ctx.moveTo(x + 3, y - 3); - ctx.lineTo(x - 3, y + 3); - ctx.stroke(); - }, - minimizebutton: function(ctx, x, y, rgbBg, aBg, rgb, a){ - // Circle - ctx.beginPath(); - ctx.arc(x,y,7,0,Math.PI*2,true); - ctx.fillStyle = 'rgba(' + rgbBg.join(',') + ',' + aBg + ')'; - ctx.fill(); - // Minus sign - ctx.strokeStyle = 'rgba(' + rgb.join(',') + ',' + a + ')'; - ctx.lineWidth = 2; - ctx.beginPath(); - ctx.moveTo(x - 3.5, y); - ctx.lineTo(x + 3.5, y); - ctx.stroke(); - }, - setMochaControlsWidth: function(){ - this.mochaControlsWidth = 0; - var options = this.options; - if (options.minimizable){ - this.mochaControlsWidth += (this.minimizeButtonEl.getStyle('margin-left').toInt() + this.minimizeButtonEl.getStyle('width').toInt()); - } - if (options.maximizable){ - this.mochaControlsWidth += (this.maximizeButtonEl.getStyle('margin-left').toInt() + this.maximizeButtonEl.getStyle('width').toInt()); - } - if (options.closable){ - this.mochaControlsWidth += (this.closeButtonEl.getStyle('margin-left').toInt() + this.closeButtonEl.getStyle('width').toInt()); - } - this.controlsEl.setStyle('width', this.mochaControlsWidth); - if (options.useCanvasControls == true){ - this.canvasControlsEl.setProperty('width', this.mochaControlsWidth); - } - }, - /* - - Function: hideSpinner - Hides the spinner. - - Example: - (start code) - $('myWindow').retrieve('instance').hideSpinner(); - (end) - - */ - hideSpinner: function() { - if (this.spinnerEl) this.spinnerEl.hide(); - return this; - }, - /* - - Function: showSpinner - Shows the spinner. - - Example: - (start code) - $('myWindow').retrieve('instance').showSpinner(); - (end) - - */ - showSpinner: function(){ - if (this.spinnerEl) this.spinnerEl.show(); - return this; - }, - /* - - Function: close - Closes the window. This is an alternative to using MUI.Core.closeWindow(). - - Example: - (start code) - $('myWindow').retrieve('instance').close(); - (end) - - */ - close: function( ) { - if (!this.isClosing) MUI.closeWindow(this.windowEl); - return this; - }, - /* - - Function: minimize - Minimizes the window. - - Example: - (start code) - $('myWindow').retrieve('instance').minimize(); - (end) - - */ - minimize: function( ){ - MUI.Dock.minimizeWindow(this.windowEl); - return this; - }, - /* - - Function: maximize - Maximizes the window. - - Example: - (start code) - $('myWindow').retrieve('instance').maximize(); - (end) - - */ - maximize: function( ) { - if (this.isMinimized){ - MUI.Dock.restoreMinimized(this.windowEl); - } - MUI.Desktop.maximizeWindow(this.windowEl); - return this; - }, - /* - - Function: restore - Restores a minimized/maximized window to its original size. - - Example: - (start code) - $('myWindow').retrieve('instance').restore(); - (end) - - */ - restore: function() { - if ( this.isMinimized ) - MUI.Dock.restoreMinimized(this.windowEl); - else if ( this.isMaximized ) - MUI.Desktop.restoreWindow(this.windowEl); - return this; - }, - /* - - Function: resize - Resize a window. - - Notes: - If Advanced Effects are on the resize is animated. If centered is set to true the window remains centered as it resizes. - - Example: - (start code) - $('myWindow').retrieve('instance').resize({width:500,height:300,centered:true}); - (end) - - */ - resize: function(options){ - MUI.resizeWindow(this.windowEl, options); - return this; - }, - /* - - Function: center - Center a window. - - Example: - (start code) - $('myWindow').retrieve('instance').center(); - (end) - - */ - center: function() { - MUI.centerWindow(this.windowEl); - return this; - }, - - hide: function(){ - this.windowEl.setStyle('display', 'none'); - return this; - }, - - show: function(){ - this.windowEl.setStyle('display', 'block'); - return this; - } - -}); - -MUI.extend({ - /* - - Function: closeWindow - Closes a window. - - Syntax: - (start code) - MUI.closeWindow(); - (end) - - Arguments: - windowEl - the ID of the window to be closed - - Returns: - true - the window was closed - false - the window was not closed - - */ - closeWindow: function(windowEl){ - - var instance = windowEl.retrieve('instance'); - - // Does window exist and is not already in process of closing ? - if (windowEl != $(windowEl) || instance.isClosing) return; - - instance.isClosing = true; - instance.fireEvent('onClose', windowEl); - - if (instance.options.storeOnClose){ - this.storeOnClose(instance, windowEl); - return; - } - if (instance.check) instance.check.destroy(); - - if ((instance.options.type == 'modal' || instance.options.type == 'modal2') && Browser.Engine.trident4){ - $('modalFix').hide(); - } - - if (MUI.options.advancedEffects == false){ - if (instance.options.type == 'modal' || instance.options.type == 'modal2'){ - $('modalOverlay').setStyle('opacity', 0); - } - MUI.closingJobs(windowEl); - return true; - } - else { - // Redraws IE windows without shadows since IE messes up canvas alpha when you change element opacity - if (MUI.ieLegacySupport) instance.drawWindow(false); - if (instance.options.type == 'modal' || instance.options.type == 'modal2'){ - MUI.Modal.modalOverlayCloseMorph.start({ - 'opacity': 0 - }); - } - var closeMorph = new Fx.Morph(windowEl, { - duration: 120, - onComplete: function(){ - MUI.closingJobs(windowEl); - return true; - }.bind(this) - }); - closeMorph.start({ - 'opacity': .4 - }); - } - - }, - closingJobs: function(windowEl){ - - var instances = MUI.Windows.instances; - var instance = instances.get(windowEl.id); - windowEl.setStyle('visibility', 'hidden'); - // Destroy throws an error in IE8 - if (MUI.ieLegacySupport) { - windowEl.dispose(); - } - else { - windowEl.destroy(); - } - instance.fireEvent('onCloseComplete'); - - if (instance.options.type != 'notification'){ - var newFocus = this.getWindowWithHighestZindex(); - this.focusWindow(newFocus); - } - - instances.erase(instance.options.id); - if (this.loadingWorkspace == true) { - this.windowUnload(); - } - - if (MUI.Dock && $(MUI.options.dock) && instance.options.type == 'window') { - var currentButton = $(instance.options.id + '_dockTab'); - if (currentButton != null) { - MUI.Dock.dockSortables.removeItems(currentButton).destroy(); - } - // Need to resize everything in case the dock becomes smaller when a tab is removed - MUI.Desktop.setDesktopSize(); - } - }, - storeOnClose: function(instance, windowEl){ - - if (instance.check) instance.check.hide(); - - windowEl.setStyles({ - zIndex: -1 - }); - windowEl.addClass('windowClosed'); - windowEl.removeClass('mocha'); - - if (MUI.Dock && $(MUI.options.dock) && instance.options.type == 'window') { - var currentButton = $(instance.options.id + '_dockTab'); - if (currentButton != null) { - currentButton.hide(); - } - MUI.Desktop.setDesktopSize(); - } - - instance.fireEvent('onCloseComplete'); - - if (instance.options.type != 'notification'){ - var newFocus = this.getWindowWithHighestZindex(); - this.focusWindow(newFocus); - } - - instance.isClosing = false; - - }, - /* - - Function: closeAll - Close all open windows. - - */ - closeAll: function() { - $$('.mocha').each(function(windowEl){ - this.closeWindow(windowEl); - }.bind(this)); - }, - /* - - Function: collapseToggle - Collapses an expanded window. Expands a collapsed window. - - */ - collapseToggle: function(windowEl){ - var instance = windowEl.retrieve('instance'); - var handles = windowEl.getElements('.handle'); - if (instance.isMaximized == true) return; - if (instance.isCollapsed == false) { - instance.isCollapsed = true; - handles.hide(); - if ( instance.iframeEl ) { - instance.iframeEl.setStyle('visibility', 'hidden'); - } - instance.contentBorderEl.setStyles({ - visibility: 'hidden', - position: 'absolute', - top: -10000, - left: -10000 - }); - if(instance.toolbarWrapperEl){ - instance.toolbarWrapperEl.setStyles({ - visibility: 'hidden', - position: 'absolute', - top: -10000, - left: -10000 - }); - } - instance.drawWindowCollapsed(); - } - else { - instance.isCollapsed = false; - instance.drawWindow(); - instance.contentBorderEl.setStyles({ - visibility: 'visible', - position: null, - top: null, - left: null - }); - if(instance.toolbarWrapperEl){ - instance.toolbarWrapperEl.setStyles({ - visibility: 'visible', - position: null, - top: null, - left: null - }); - } - if ( instance.iframeEl ) { - instance.iframeEl.setStyle('visibility', 'visible'); - } - handles.show(); - } - }, - /* - - Function: toggleWindowVisibility - Toggle window visibility with Ctrl-Alt-Q. - - */ - toggleWindowVisibility: function(){ - MUI.Windows.instances.each(function(instance){ - if (instance.options.type == 'modal' || instance.options.type == 'modal2' || instance.isMinimized == true) return; - var id = $(instance.options.id); - if (id.getStyle('visibility') == 'visible'){ - if (instance.iframe){ - instance.iframeEl.setStyle('visibility', 'hidden'); - } - if (instance.toolbarEl){ - instance.toolbarWrapperEl.setStyle('visibility', 'hidden'); - } - instance.contentBorderEl.setStyle('visibility', 'hidden'); - id.setStyle('visibility', 'hidden'); - MUI.Windows.windowsVisible = false; - } - else { - id.setStyle('visibility', 'visible'); - instance.contentBorderEl.setStyle('visibility', 'visible'); - if (instance.iframe){ - instance.iframeEl.setStyle('visibility', 'visible'); - } - if (instance.toolbarEl){ - instance.toolbarWrapperEl.setStyle('visibility', 'visible'); - } - MUI.Windows.windowsVisible = true; - } - }.bind(this)); - - }, - focusWindow: function(windowEl, fireEvent){ - - // This is used with blurAll - MUI.Windows.focusingWindow = true; - var windowClicked = function(){ - MUI.Windows.focusingWindow = false; - }; - windowClicked.delay(170, this); - - // Only focus when needed - if ($$('.mocha').length == 0) return; - if (windowEl != $(windowEl) || windowEl.hasClass('isFocused')) return; - - var instances = MUI.Windows.instances; - var instance = instances.get(windowEl.id); - - if (instance.options.type == 'notification'){ - windowEl.setStyle('zIndex', 11001); - return; - }; - - MUI.Windows.indexLevel += 2; - windowEl.setStyle('zIndex', MUI.Windows.indexLevel); - - // Used when dragging and resizing windows - $('windowUnderlay').setStyle('zIndex', MUI.Windows.indexLevel - 1).inject($(windowEl),'after'); - - // Fire onBlur for the window that lost focus. - instances.each(function(instance){ - if (instance.windowEl.hasClass('isFocused')){ - instance.fireEvent('onBlur', instance.windowEl); - } - instance.windowEl.removeClass('isFocused'); - }); - - if (MUI.Dock && $(MUI.options.dock) && instance.options.type == 'window') { - MUI.Dock.makeActiveTab(); - } - windowEl.addClass('isFocused'); - - if (fireEvent != false){ - instance.fireEvent('onFocus', windowEl); - } - - }, - getWindowWithHighestZindex: function(){ - this.highestZindex = 0; - $$('.mocha').each(function(element){ - this.zIndex = element.getStyle('zIndex'); - if (this.zIndex >= this.highestZindex) { - this.highestZindex = this.zIndex; - } - }.bind(this)); - $$('.mocha').each(function(element){ - if (element.getStyle('zIndex') == this.highestZindex) { - this.windowWithHighestZindex = element; - } - }.bind(this)); - return this.windowWithHighestZindex; - }, - blurAll: function(){ - if (MUI.Windows.focusingWindow == false) { - $$('.mocha').each(function(windowEl){ - var instance = windowEl.retrieve('instance'); - if (instance.options.type != 'modal' && instance.options.type != 'modal2'){ - windowEl.removeClass('isFocused'); - } - }); - $$('.dockTab').removeClass('activeDockTab'); - } - }, - centerWindow: function(windowEl){ - - if(!windowEl){ - MUI.Windows.instances.each(function(instance){ - if (instance.windowEl.hasClass('isFocused')){ - windowEl = instance.windowEl; - } - }); - } - - var instance = windowEl.retrieve('instance'); - var options = instance.options; - var dimensions = options.container.getCoordinates(); - - var windowPosTop = window.getScroll().y + (window.getSize().y * .5) - (windowEl.offsetHeight * .5); - if (windowPosTop < -instance.options.shadowBlur){ - windowPosTop = -instance.options.shadowBlur; - } - var windowPosLeft = (dimensions.width * .5) - (windowEl.offsetWidth * .5); - if (windowPosLeft < -instance.options.shadowBlur){ - windowPosLeft = -instance.options.shadowBlur; - } - if (MUI.options.advancedEffects == true){ - instance.morph.start({ - 'top': windowPosTop, - 'left': windowPosLeft - }); - } - else { - windowEl.setStyles({ - 'top': windowPosTop, - 'left': windowPosLeft - }); - } - }, - resizeWindow: function(windowEl, options){ - var instance = windowEl.retrieve('instance'); - - $extend({ - width: null, - height: null, - top: null, - left: null, - centered: true - }, options); - - var oldWidth = windowEl.getStyle('width').toInt(); - var oldHeight = windowEl.getStyle('height').toInt(); - var oldTop = windowEl.getStyle('top').toInt(); - var oldLeft = windowEl.getStyle('left').toInt(); - - if (options.centered){ - var top = options.top || oldTop - ((options.height - oldHeight) * .5); - var left = options.left || oldLeft - ((options.width - oldWidth) * .5); - } - else { - var top = options.top || oldTop; - var left = options.left || oldLeft; - } - - if (MUI.options.advancedEffects == false){ - windowEl.setStyles({ - 'top': top, - 'left': left - }); - instance.contentWrapperEl.setStyles({ - 'height': options.height, - 'width': options.width - }); - instance.drawWindow(); - // Show iframe - if (instance.iframeEl){ - if (!MUI.ieLegacySupport) { - instance.iframeEl.setStyle('visibility', 'visible'); - } - else { - instance.iframeEl.show(); - } - } - } - else { - windowEl.retrieve('resizeMorph').start({ - '0': { 'height': options.height, - 'width': options.width - }, - '1': { 'top': top, - 'left': left - } - }); - } - return instance; - }, - /* - - Internal Function: dynamicResize - Use with a timer to resize a window as the window's content size changes, such as with an accordian. - - */ - dynamicResize: function(windowEl){ - var instance = windowEl.retrieve('instance'); - var contentWrapperEl = instance.contentWrapperEl; - var contentEl = instance.contentEl; - - contentWrapperEl.setStyles({ - 'height': contentEl.offsetHeight, - 'width': contentEl.offsetWidth - }); - instance.drawWindow(); - } -}); - -// Toggle window visibility with Ctrl-Alt-Q -document.addEvent('keydown', function(event){ - if (event.key == 'q' && event.control && event.alt) { - MUI.toggleWindowVisibility(); - } -}); -/* - -Script: Modal.js - Create modal dialog windows. - -Copyright: - Copyright (c) 2007-2009 Greg Houston, . - -License: - MIT-style license. - -Requires: - Core.js, Window.js - -See Also: - - -*/ - -MUI.files[MUI.path.source + 'Window/Modal.js'] = 'loaded'; - -MUI.Modal = new Class({ - - Extends: MUI.Window, - - options: { - type: 'modal' - }, - - initialize: function(options){ - - if (!$('modalOverlay')){ - this.modalInitialize(); - - window.addEvent('resize', function(){ - this.setModalSize(); - }.bind(this)); - } - this.parent(options); - - }, - modalInitialize: function(){ - var modalOverlay = new Element('div', { - 'id': 'modalOverlay', - 'styles': { - 'height': document.getCoordinates().height, - 'opacity': .6 - } - }).inject(document.body); - - modalOverlay.setStyles({ - 'position': Browser.Engine.trident4 ? 'absolute' : 'fixed' - }); - - modalOverlay.addEvent('click', function(e){ - var instance = MUI.Windows.instances.get(MUI.currentModal.id); - if (instance.options.modalOverlayClose == true) { - MUI.closeWindow(MUI.currentModal); - } - }); - - if (Browser.Engine.trident4){ - var modalFix = new Element('iframe', { - 'id': 'modalFix', - 'scrolling': 'no', - 'marginWidth': 0, - 'marginHeight': 0, - 'src': '', - 'styles': { - 'height': document.getCoordinates().height - } - }).inject(document.body); - } - - MUI.Modal.modalOverlayOpenMorph = new Fx.Morph($('modalOverlay'), { - 'duration': 150 - }); - MUI.Modal.modalOverlayCloseMorph = new Fx.Morph($('modalOverlay'), { - 'duration': 150, - onComplete: function(){ - $('modalOverlay').hide(); - if (Browser.Engine.trident4){ - $('modalFix').hide(); - } - }.bind(this) - }); - }, - setModalSize: function(){ - $('modalOverlay').setStyle('height', document.getCoordinates().height); - if (Browser.Engine.trident4){ - $('modalFix').setStyle('height', document.getCoordinates().height); - } - } - -}); -/* - -Script: Windows-from-html.js - Create windows from html markup in page. - -Copyright: - Copyright (c) 2007-2009 Greg Houston, . - -License: - MIT-style license. - -Requires: - Core.js, Window.js - -Example: - HTML markup. - (start code) -
-

My Window

-

My Window Content

-
- (end) - -See Also: - - -*/ - -MUI.files[MUI.path.source + 'Window/Windows-from-html.js'] = 'loaded'; - -MUI.extend({ - NewWindowsFromHTML: function(){ - $$('.mocha').each(function(el) { - // Get the window title and destroy that element, so it does not end up in window content - if ( Browser.Engine.presto || Browser.Engine.trident5 ){ - el.hide(); // Required by Opera, and probably IE7 - } - var title = el.getElement('h3.mochaTitle'); - - if(Browser.Engine.presto) el.show(); - - var elDimensions = el.getStyles('height', 'width'); - var properties = { - id: el.getProperty('id'), - height: elDimensions.height.toInt(), - width: elDimensions.width.toInt(), - x: el.getStyle('left').toInt(), - y: el.getStyle('top').toInt() - }; - // If there is a title element, set title and destroy the element so it does not end up in window content - if ( title ) { - properties.title = title.innerHTML; - title.destroy(); - } - - // Get content and destroy the element - properties.content = el.innerHTML; - el.destroy(); - - // Create window - new MUI.Window(properties, true); - }.bind(this)); - } -}); -/* - -Script: Windows-from-json.js - Create one or more windows from JSON data. You can define all the same properties as you can for new MUI.Window(). Undefined properties are set to their defaults. - -Copyright: - Copyright (c) 2007-2009 Greg Houston, . - -License: - MIT-style license. - -Syntax: - (start code) - MUI.newWindowsFromJSON(properties); - (end) - -Example: - (start code) - MUI.jsonWindows = function(){ - var url = 'data/json-windows-data.js'; - var request = new Request.JSON({ - url: url, - method: 'get', - onComplete: function(properties) { - MUI.newWindowsFromJSON(properties.windows); - } - }).send(); - } - (end) - -Note: - Windows created from JSON are not compatible with the current cookie based version - of Save and Load Workspace. - -See Also: - - -*/ - -MUI.files[MUI.path.source + 'Window/Windows-from-json.js'] = 'loaded'; - -MUI.extend({ - newWindowsFromJSON: function(newWindows){ - newWindows.each(function(options) { - var temp = new Hash(options); - temp.each( function(value, key, hash) { - if ($type(value) != 'string') return; - if (value.substring(0,8) == 'function'){ - eval("options." + key + " = " + value); - } - }); - new MUI.Window(options); - }); - } -}); -/* - -Script: Arrange-cascade.js - Cascade windows. - -Copyright: - Copyright (c) 2007-2009 Greg Houston, . - -License: - MIT-style license. - -Requires: - Core.js, Window.js - -Syntax: - (start code) - MUI.arrangeCascade(); - (end) - -*/ - -MUI.files[MUI.path.source + 'Window/Arrange-cascade.js'] = 'loaded'; - -MUI.extend({ - arrangeCascade: function(){ - - var viewportTopOffset = 30; // Use a negative number if neccessary to place first window where you want it - var viewportLeftOffset = 20; - var windowTopOffset = 50; // Initial vertical spacing of each window - var windowLeftOffset = 40; - - // See how much space we have to work with - var coordinates = document.getCoordinates(); - - var openWindows = 0; - MUI.Windows.instances.each(function(instance){ - if (!instance.isMinimized && instance.options.draggable) openWindows ++; - }); - - if ((windowTopOffset * (openWindows + 1)) >= (coordinates.height - viewportTopOffset)) { - var topOffset = (coordinates.height - viewportTopOffset) / (openWindows + 1); - } - else { - var topOffset = windowTopOffset; - } - - if ((windowLeftOffset * (openWindows + 1)) >= (coordinates.width - viewportLeftOffset - 20)) { - var leftOffset = (coordinates.width - viewportLeftOffset - 20) / (openWindows + 1); - } - else { - var leftOffset = windowLeftOffset; - } - - var x = viewportLeftOffset; - var y = viewportTopOffset; - $$('.mocha').each(function(windowEl){ - var instance = windowEl.retrieve('instance'); - if (!instance.isMinimized && !instance.isMaximized && instance.options.draggable){ - id = windowEl.id; - MUI.focusWindow(windowEl); - x += leftOffset; - y += topOffset; - - if (MUI.options.advancedEffects == false){ - windowEl.setStyles({ - 'top': y, - 'left': x - }); - } - else { - var cascadeMorph = new Fx.Morph(windowEl, { - 'duration': 550 - }); - cascadeMorph.start({ - 'top': y, - 'left': x - }); - } - } - }.bind(this)); - } -}); -/* - -Script: Arrange-tile.js - Cascade windows. - -Copyright: - Copyright (c) 2007-2009 Greg Houston, . - -Authors: - Harry Roberts and Greg Houston - -License: - MIT-style license. - -Requires: - Core.js, Window.js - -Syntax: - (start code) - MUI.arrangeTile(); - (end) - -*/ - -MUI.files[MUI.path.source + 'Window/Arrange-tile.js'] = 'loaded'; - -MUI.extend({ - arrangeTile: function(){ - - var viewportTopOffset = 30; // Use a negative number if neccessary to place first window where you want it - var viewportLeftOffset = 20; - - var x = 10; - var y = 80; - - var instances = MUI.Windows.instances; - - var windowsNum = 0; - - instances.each(function(instance){ - if (!instance.isMinimized && !instance.isMaximized){ - windowsNum++; - } - }); - - var cols = 3; - var rows = Math.ceil(windowsNum / cols); - - var coordinates = document.getCoordinates(); - - var col_width = ((coordinates.width - viewportLeftOffset) / cols); - var col_height = ((coordinates.height - viewportTopOffset) / rows); - - var row = 0; - var col = 0; - - instances.each(function(instance){ - if (!instance.isMinimized && !instance.isMaximized && instance.options.draggable ){ - - var content = instance.contentWrapperEl; - var content_coords = content.getCoordinates(); - var window_coords = instance.windowEl.getCoordinates(); - - // Calculate the amount of padding around the content window - var padding_top = content_coords.top - window_coords.top; - var padding_bottom = window_coords.height - content_coords.height - padding_top; - var padding_left = content_coords.left - window_coords.left; - var padding_right = window_coords.width - content_coords.width - padding_left; - - /* - - // This resizes the windows - if (instance.options.shape != 'gauge' && instance.options.resizable == true){ - var width = (col_width - 3 - padding_left - padding_right); - var height = (col_height - 3 - padding_top - padding_bottom); - - if (width > instance.options.resizeLimit.x[0] && width < instance.options.resizeLimit.x[1]){ - content.setStyle('width', width); - } - if (height > instance.options.resizeLimit.y[0] && height < instance.options.resizeLimit.y[1]){ - content.setStyle('height', height); - } - - }*/ - - var left = (x + (col * col_width)); - var top = (y + (row * col_height)); - - instance.drawWindow(); - - MUI.focusWindow(instance.windowEl); - - if (MUI.options.advancedEffects == false){ - instance.windowEl.setStyles({ - 'top': top, - 'left': left - }); - } - else { - var tileMorph = new Fx.Morph(instance.windowEl, { - 'duration': 550 - }); - tileMorph.start({ - 'top': top, - 'left': left - }); - } - - if (++col === cols) { - row++; - col = 0; - } - } - }.bind(this)); - } -}); -/* - -Script: Tabs.js - Functionality for window tabs. - -Copyright: - Copyright (c) 2007-2009 Greg Houston, . - -License: - MIT-style license. - -Requires: - Core.js, Window.js (for tabbed windows) or Layout.js (for tabbed panels) - -*/ - -MUI.files[MUI.path.source + 'Components/Tabs.js'] = 'loaded'; - -MUI.extend({ - /* - - Function: initializeTabs - Add click event to each list item that fires the selected function. - - */ - initializeTabs: function(el){ - $(el).setStyle('list-style', 'none'); // This is to fix a glitch that occurs in IE8 RC1 when dynamically switching themes - $(el).getElements('li').addEvent('click', function(e){ - MUI.selected(this, el); - }); - }, - /* - - Function: selected - Add "selected" class to current list item and remove it from sibling list items. - - Syntax: - (start code) - selected(el, parent); - (end) - - Arguments: - el - the list item - parent - the ul - - */ - selected: function(el, parent){ - $(parent).getChildren().each(function(listitem){ - listitem.removeClass('selected'); - }); - el.addClass('selected'); - } -}); - -/* - -Script: Layout.js - Create web application layouts. Enables window maximize. - -Copyright: - Copyright (c) 2007-2009 Greg Houston, . - -License: - MIT-style license. - -Requires: - Core.js - -*/ - -MUI.files[MUI.path.source + 'Layout/Layout.js'] = 'loaded'; - -MUI.extend({ - Columns: { - instances: new Hash(), - columnIDCount: 0 // Used for columns without an ID defined by the user - }, - Panels: { - instances: new Hash(), - panelIDCount: 0 // Used for panels without an ID defined by the user - } -}); - -MUI.Desktop = { - - options: { - // Naming options: - // If you change the IDs of the MochaUI Desktop containers in your HTML, you need to change them here as well. - desktop: 'desktop', - desktopHeader: 'desktopHeader', - desktopFooter: 'desktopFooter', - desktopNavBar: 'desktopNavbar', - pageWrapper: 'pageWrapper', - page: 'page', - desktopFooter: 'desktopFooterWrapper' - }, - initialize: function(){ - - this.desktop = $(this.options.desktop); - this.desktopHeader = $(this.options.desktopHeader); - this.desktopNavBar = $(this.options.desktopNavBar); - this.pageWrapper = $(this.options.pageWrapper); - this.page = $(this.options.page); - this.desktopFooter = $(this.options.desktopFooter); - - if (this.desktop) { - ($$('body')).setStyles({ - overflow: 'hidden', - height: '100%', - margin: 0 - }); - ($$('html')).setStyles({ - overflow: 'hidden', - height: '100%' - }); - } - - // This is run on dock initialize so no need to do it twice. - if (!MUI.Dock){ - this.setDesktopSize(); - } - this.menuInitialize(); - - // Resize desktop, page wrapper, modal overlay, and maximized windows when browser window is resized - window.addEvent('resize', function(e){ - this.onBrowserResize(); - }.bind(this)); - - if (MUI.myChain){ - MUI.myChain.callChain(); - } - - }, - menuInitialize: function(){ - // Fix for dropdown menus in IE6 - if (Browser.Engine.trident4 && this.desktopNavBar){ - this.desktopNavBar.getElements('li').each(function(element) { - element.addEvent('mouseenter', function(){ - this.addClass('ieHover'); - }); - element.addEvent('mouseleave', function(){ - this.removeClass('ieHover'); - }); - }); - }; - }, - onBrowserResize: function(){ - this.setDesktopSize(); - // Resize maximized windows to fit new browser window size - setTimeout( function(){ - MUI.Windows.instances.each(function(instance){ - if (instance.isMaximized){ - - // Hide iframe while resize for better performance - if ( instance.iframeEl ){ - instance.iframeEl.setStyle('visibility', 'hidden'); - } - - var coordinates = document.getCoordinates(); - var borderHeight = instance.contentBorderEl.getStyle('margin-top').toInt() + instance.contentBorderEl.getStyle('margin-bottom').toInt(); - var toolbarHeight = instance.toolbarWrapperEl ? instance.toolbarWrapperEl.getStyle('height').toInt() + instance.toolbarWrapperEl.getStyle('margin-top').toInt() : 0; - instance.contentWrapperEl.setStyles({ - 'height': coordinates.height - instance.options.headerHeight - instance.options.footerHeight - borderHeight - toolbarHeight, - 'width': coordinates.width - }); - - instance.drawWindow(); - if ( instance.iframeEl ){ - instance.iframeEl.setStyles({ - 'height': instance.contentWrapperEl.getStyle('height') - }); - instance.iframeEl.setStyle('visibility', 'visible'); - } - - } - }.bind(this)); - }.bind(this), 100); - }, - setDesktopSize: function(){ - var windowDimensions = window.getCoordinates(); - - // var dock = $(MUI.options.dock); - var dockWrapper = $(MUI.options.dockWrapper); - - // Setting the desktop height may only be needed by IE7 - if (this.desktop){ - this.desktop.setStyle('height', windowDimensions.height); - } - - // Set pageWrapper height so the dock doesn't cover the pageWrapper scrollbars. - if (this.pageWrapper) { - var dockOffset = MUI.dockVisible ? dockWrapper.offsetHeight : 0; - var pageWrapperHeight = windowDimensions.height; - pageWrapperHeight -= this.pageWrapper.getStyle('margin-top').toInt(); - pageWrapperHeight -= this.pageWrapper.getStyle('margin-bottom').toInt(); - if (this.desktopHeader){ pageWrapperHeight -= this.desktopHeader.offsetHeight; } - if (this.desktopFooter){ pageWrapperHeight -= this.desktopFooter.offsetHeight; } - pageWrapperHeight -= dockOffset; - - if (pageWrapperHeight < 0){ - pageWrapperHeight = 0; - } - this.pageWrapper.setStyle('height', pageWrapperHeight); - } - - if (MUI.Columns.instances.getKeys().length > 0){ // Conditional is a fix for a bug in IE6 in the no toolbars demo. - MUI.Desktop.resizePanels(); - } - }, - resizePanels: function(){ - MUI.panelHeight(); - MUI.rWidth(); - }, - /* - - Function: maximizeWindow - Maximize a window. - - Syntax: - (start code) - MUI.Desktop.maximizeWindow(windowEl); - (end) - - */ - maximizeWindow: function(windowEl){ - - var instance = MUI.Windows.instances.get(windowEl.id); - var options = instance.options; - var windowDrag = instance.windowDrag; - - // If window no longer exists or is maximized, stop - if (windowEl != $(windowEl) || instance.isMaximized ) return; - - if (instance.isCollapsed){ - MUI.collapseToggle(windowEl); - } - - instance.isMaximized = true; - - // If window is restricted to a container, it should not be draggable when maximized. - if (instance.options.restrict){ - windowDrag.detach(); - if (options.resizable) { - instance.detachResizable(); - } - instance.titleBarEl.setStyle('cursor', 'default'); - } - - // If the window has a container that is not the desktop - // temporarily move the window to the desktop while it is minimized. - if (options.container != this.desktop){ - this.desktop.grab(windowEl); - if (this.options.restrict){ - windowDrag.container = this.desktop; - } - } - - // Save original position - instance.oldTop = windowEl.getStyle('top'); - instance.oldLeft = windowEl.getStyle('left'); - - var contentWrapperEl = instance.contentWrapperEl; - - // Save original dimensions - contentWrapperEl.oldWidth = contentWrapperEl.getStyle('width'); - contentWrapperEl.oldHeight = contentWrapperEl.getStyle('height'); - - // Hide iframe - // Iframe should be hidden when minimizing, maximizing, and moving for performance and Flash issues - if ( instance.iframeEl ) { - if (!MUI.ieLegacySupport) { - instance.iframeEl.setStyle('visibility', 'hidden'); - } - else { - instance.iframeEl.hide(); - } - } - - var windowDimensions = document.getCoordinates(); - var options = instance.options; - var shadowBlur = options.shadowBlur; - var shadowOffset = options.shadowOffset; - var newHeight = windowDimensions.height - options.headerHeight - options.footerHeight; - newHeight -= instance.contentBorderEl.getStyle('margin-top').toInt(); - newHeight -= instance.contentBorderEl.getStyle('margin-bottom').toInt(); - newHeight -= (instance.toolbarWrapperEl ? instance.toolbarWrapperEl.getStyle('height').toInt() + instance.toolbarWrapperEl.getStyle('margin-top').toInt() : 0); - - MUI.resizeWindow(windowEl, { - width: windowDimensions.width, - height: newHeight, - top: shadowOffset.y - shadowBlur, - left: shadowOffset.x - shadowBlur - }); - instance.fireEvent('onMaximize', windowEl); - - if (instance.maximizeButtonEl) { - instance.maximizeButtonEl.setProperty('title', 'Restore'); - } - MUI.focusWindow(windowEl); - - }, - /* - - Function: restoreWindow - Restore a maximized window. - - Syntax: - (start code) - MUI.Desktop.restoreWindow(windowEl); - (end) - - */ - restoreWindow: function(windowEl){ - - var instance = windowEl.retrieve('instance'); - - // Window exists and is maximized ? - if (windowEl != $(windowEl) || !instance.isMaximized) return; - - var options = instance.options; - instance.isMaximized = false; - - if (options.restrict){ - instance.windowDrag.attach(); - if (options.resizable){ - instance.reattachResizable(); - } - instance.titleBarEl.setStyle('cursor', 'move'); - } - - // Hide iframe - // Iframe should be hidden when minimizing, maximizing, and moving for performance and Flash issues - if ( instance.iframeEl ) { - if (!MUI.ieLegacySupport) { - instance.iframeEl.setStyle('visibility', 'hidden'); - } - else { - instance.iframeEl.hide(); - } - } - - var contentWrapperEl = instance.contentWrapperEl; - - MUI.resizeWindow(windowEl,{ - width: contentWrapperEl.oldWidth, - height: contentWrapperEl.oldHeight, - top: instance.oldTop, - left: instance.oldLeft - }); - instance.fireEvent('onRestore', windowEl); - - if (instance.maximizeButtonEl){ - instance.maximizeButtonEl.setProperty('title', 'Maximize'); - } - } -}; - -/* - -Class: Column - Create a column. Columns should be created from left to right. - -Syntax: -(start code) - MUI.Column(); -(end) - -Arguments: - options - -Options: - id - The ID of the column. This must be set when creating the column. - container - Defaults to MUI.Desktop.pageWrapper. - placement - Can be 'right', 'main', or 'left'. There must be at least one column with the 'main' option. - width - 'main' column is fluid and should not be given a width. - resizeLimit - resizelimit of a 'right' or 'left' column. - sortable - (boolean) Whether the panels can be reordered via drag and drop. - onResize - (function) Fired when the column is resized. - onCollapse - (function) Fired when the column is collapsed. - onExpand - (function) Fired when the column is expanded. - -*/ -MUI.Column = new Class({ - - Implements: [Events, Options], - - options: { - id: null, - container: null, - placement: null, - width: null, - resizeLimit: [], - sortable: true, - - // Events - onResize: $empty, - onCollapse: $empty, - onExpand: $empty - - }, - - initialize: function(options){ - this.setOptions(options); - - $extend(this, { - timestamp: $time(), - isCollapsed: false, - oldWidth: 0 - }); - - // If column has no ID, give it one. - if (this.options.id == null){ - this.options.id = 'column' + (++MUI.Columns.columnIDCount); - } - - // Shorten object chain - var options = this.options; - var instances = MUI.Columns.instances; - var instanceID = instances.get(options.id); - - if (options.container == null) { - options.container = MUI.Desktop.pageWrapper - } - else { - $(options.container).setStyle('overflow', 'hidden'); - } - - if (typeof this.options.container == 'string'){ - this.options.container = $(this.options.container); - } - - // Check to see if there is already a class instance for this Column - if (instanceID){ - var instance = instanceID; - } - - // Check if column already exists - if ( this.columnEl ){ - return; - } - else { - instances.set(options.id, this); - } - - // If loading columns into a panel, hide the regular content container. - if ($(options.container).getElement('.pad') != null) { - $(options.container).getElement('.pad').hide(); - } - - // If loading columns into a window, hide the regular content container. - if ($(options.container).getElement('.mochaContent') != null) { - $(options.container).getElement('.mochaContent').hide(); - } - - this.columnEl = new Element('div', { - 'id': this.options.id, - 'class': 'column expanded', - 'styles': { - 'width': options.placement == 'main' ? null : options.width - } - }).inject($(options.container)); - - this.columnEl.store('instance', this); - - var parent = this.columnEl.getParent(); - var columnHeight = parent.getStyle('height').toInt(); - this.columnEl.setStyle('height', columnHeight); - - if (this.options.sortable){ - if (!this.options.container.retrieve('sortables')){ - var sortables = new Sortables(this.columnEl, { - opacity: 1, - handle: '.panel-header', - constrain: false, - revert: false, - onSort: function(){ - $$('.column').each(function(column){ - column.getChildren('.panelWrapper').each(function(panelWrapper){ - panelWrapper.getElement('.panel').removeClass('bottomPanel'); - }); - if (column.getChildren('.panelWrapper').getLast()){ - column.getChildren('.panelWrapper').getLast().getElement('.panel').addClass('bottomPanel'); - } - MUI.panelHeight(); - }.bind(this)); - }.bind(this) - }); - this.options.container.store('sortables', sortables); - } - else { - this.options.container.retrieve('sortables').addLists(this.columnEl); - } - } - - if (options.placement == 'main'){ - this.columnEl.addClass('rWidth'); - } - - switch (this.options.placement) { - case 'left': - this.handleEl = new Element('div', { - 'id': this.options.id + '_handle', - 'class': 'columnHandle' - }).inject(this.columnEl, 'after'); - - this.handleIconEl = new Element('div', { - 'id': options.id + '_handle_icon', - 'class': 'handleIcon' - }).inject(this.handleEl); - - addResizeRight(this.columnEl, options.resizeLimit[0], options.resizeLimit[1]); - break; - case 'right': - this.handleEl = new Element('div', { - 'id': this.options.id + '_handle', - 'class': 'columnHandle' - }).inject(this.columnEl, 'before'); - - this.handleIconEl = new Element('div', { - 'id': options.id + '_handle_icon', - 'class': 'handleIcon' - }).inject(this.handleEl); - addResizeLeft(this.columnEl, options.resizeLimit[0], options.resizeLimit[1]); - break; - } - - if (this.handleEl != null){ - this.handleEl.addEvent('dblclick', function(){ - this.columnToggle(); - }.bind(this)); - } - - MUI.rWidth(); - - }, - columnToggle: function(){ - var column = this.columnEl; - - // Collapse - if (this.isCollapsed == false){ - this.oldWidth = column.getStyle('width').toInt(); - - this.resize.detach(); - this.handleEl.removeEvents('dblclick'); - this.handleEl.addEvent('click', function(){ - this.columnToggle(); - }.bind(this)); - this.handleEl.setStyle('cursor', 'pointer').addClass('detached'); - - column.setStyle('width', 0); - this.isCollapsed = true; - column.addClass('collapsed'); - column.removeClass('expanded'); - MUI.rWidth(); - this.fireEvent('onCollapse'); - } - // Expand - else { - column.setStyle('width', this.oldWidth); - this.isCollapsed = false; - column.addClass('expanded'); - column.removeClass('collapsed'); - - this.handleEl.removeEvents('click'); - this.handleEl.addEvent('dblclick', function(){ - this.columnToggle(); - }.bind(this)); - this.resize.attach(); - this.handleEl.setStyle('cursor', (Browser.Engine.webkit || Browser.Engine.gecko) ? 'col-resize' : 'e-resize').addClass('attached'); - - MUI.rWidth(); - this.fireEvent('onExpand'); - } - } -}); -MUI.Column.implement(new Options, new Events); - -/* - -Class: Panel - Create a panel. Panels go one on top of another in columns. Create your columns first and then add your panels. Panels should be created from top to bottom, left to right. - -Syntax: -(start code) - MUI.Panel(); -(end) - -Arguments: - options - -Options: - id - The ID of the panel. This must be set when creating the panel. - column - Where to inject the panel. This must be set when creating the panel. - loadMethod - ('html', 'xhr', or 'iframe') Defaults to 'html' if there is no contentURL. Defaults to 'xhr' if there is a contentURL. You only really need to set this if using the 'iframe' method. May create a 'panel' loadMethod in the future. - contentURL - Used if loadMethod is set to 'xhr' or 'iframe'. - method - ('get', or 'post') The method used to get the data. Defaults to 'get'. - data - (hash) Data to send with the URL. Defaults to null. - evalScripts - (boolean) An xhr loadMethod option. Defaults to true. - evalResponse - (boolean) An xhr loadMethod option. Defaults to false. - content - (string or element) An html loadMethod option. - tabsURL - (url) - tabsData - (hash) Data to send with the URL. Defaults to null. - tabsOnload - (function) - header - (boolean) Display the panel header or not - headerToolbox: (boolean) - headerToolboxURL: (url) - headerToolboxOnload: (function) - height - (number) Height of content area. - addClass - (string) Add a class to the panel. - scrollbars - (boolean) - padding - (object) - collapsible - (boolean) - onBeforeBuild - (function) Fired before the panel is created. - onContentLoaded - (function) Fired after the panel's conten is loaded. - onResize - (function) Fired when the panel is resized. - onCollapse - (function) Fired when the panel is collapsed. - onExpand - (function) Fired when the panel is expanded. - -*/ -MUI.Panel = new Class({ - - Implements: [Events, Options], - - options: { - id: null, - title: 'New Panel', - column: null, - require: { - css: [], - images: [], - js: [], - onload: null - }, - loadMethod: null, - contentURL: null, - - // xhr options - method: 'get', - data: null, - evalScripts: true, - evalResponse: false, - - // html options - content: 'Panel content', - - // Tabs - tabsURL: null, - tabsData: null, - tabsOnload: $empty, - - header: true, - headerToolbox: false, - headerToolboxURL: 'pages/lipsum.html', - headerToolboxOnload: $empty, - - // Style options: - height: 125, - addClass: '', - scrollbars: true, - padding: { top: 8, right: 8, bottom: 8, left: 8 }, - - // Other: - collapsible: true, - - // Events - onBeforeBuild: $empty, - onContentLoaded: $empty, - onResize: $empty, - onCollapse: $empty, - onExpand: $empty - - }, - initialize: function(options){ - this.setOptions(options); - - $extend(this, { - timestamp: $time(), - isCollapsed: false, // This is probably redundant since we can check for the class - oldHeight: 0, - partner: null - }); - - // If panel has no ID, give it one. - if (this.options.id == null){ - this.options.id = 'panel' + (++MUI.Panels.panelIDCount); - } - - // Shorten object chain - var instances = MUI.Panels.instances; - var instanceID = instances.get(this.options.id); - var options = this.options; - - // Check to see if there is already a class instance for this panel - if (instanceID){ - var instance = instanceID; - } - - // Check if panel already exists - if ( this.panelEl ){ - return; - } - else { - instances.set(this.options.id, this); - } - - this.fireEvent('onBeforeBuild'); - - if (options.loadMethod == 'iframe') { - // Iframes have their own padding. - options.padding = { top: 0, right: 0, bottom: 0, left: 0 }; - } - - this.showHandle = true; - if ($(options.column).getChildren().length == 0) { - this.showHandle = false; - } - - this.panelWrapperEl = new Element('div', { - 'id': this.options.id + '_wrapper', - 'class': 'panelWrapper expanded' - }).inject($(options.column)); - - this.panelEl = new Element('div', { - 'id': this.options.id, - 'class': 'panel expanded', - 'styles': { - 'height': options.height - } - }).inject(this.panelWrapperEl); - - this.panelEl.store('instance', this); - - this.panelEl.addClass(options.addClass); - - this.contentEl = new Element('div', { - 'id': options.id + '_pad', - 'class': 'pad' - }).inject(this.panelEl); - - // This is in order to use the same variable as the windows do in updateContent. - // May rethink this. - this.contentWrapperEl = this.panelEl; - - this.contentEl.setStyles({ - 'padding-top': options.padding.top, - 'padding-bottom': options.padding.bottom, - 'padding-left': options.padding.left, - 'padding-right': options.padding.right - }); - - this.panelHeaderEl = new Element('div', { - 'id': this.options.id + '_header', - 'class': 'panel-header', - 'styles': { - 'display': options.header ? 'block' : 'none' - } - }).inject(this.panelEl, 'before'); - - var columnInstances = MUI.Columns.instances; - var columnInstance = columnInstances.get(this.options.column); - - if (columnInstance.options.sortable){ - this.panelHeaderEl.setStyle('cursor', 'move'); - columnInstance.options.container.retrieve('sortables').addItems(this.panelWrapperEl); - } - - if (this.options.collapsible) { - this.collapseToggleInit(); - } - - if (this.options.headerToolbox) { - this.panelHeaderToolboxEl = new Element('div', { - 'id': options.id + '_headerToolbox', - 'class': 'panel-header-toolbox' - }).inject(this.panelHeaderEl); - } - - this.panelHeaderContentEl = new Element('div', { - 'id': options.id + '_headerContent', - 'class': 'panel-headerContent' - }).inject(this.panelHeaderEl); - - this.titleEl = new Element('h2', { - 'id': options.id + '_title' - }).inject(this.panelHeaderContentEl); - - this.handleEl = new Element('div', { - 'id': options.id + '_handle', - 'class': 'horizontalHandle', - 'styles': { - 'display': this.showHandle == true ? 'block' : 'none' - } - }).inject(this.panelEl, 'after'); - - this.handleIconEl = new Element('div', { - 'id': options.id + '_handle_icon', - 'class': 'handleIcon' - }).inject(this.handleEl); - - addResizeBottom(options.id); - - if (options.require.css.length || options.require.images.length){ - new MUI.Require({ - css: options.require.css, - images: options.require.images, - onload: function(){ - this.newPanel(); - }.bind(this) - }); - } - else { - this.newPanel(); - } - }, - newPanel: function(){ - - options = this.options; - - if (this.options.headerToolbox) { - MUI.updateContent({ - 'element': this.panelEl, - 'childElement': this.panelHeaderToolboxEl, - 'loadMethod': 'xhr', - 'url': options.headerToolboxURL, - 'onContentLoaded': options.headerToolboxOnload - }); - } - - if (options.tabsURL == null) { - this.titleEl.set('html', options.title); - } else { - this.panelHeaderContentEl.addClass('tabs'); - MUI.updateContent({ - 'element': this.panelEl, - 'childElement': this.panelHeaderContentEl, - 'loadMethod': 'xhr', - 'url': options.tabsURL, - 'data': options.tabsData, - 'onContentLoaded': options.tabsOnload - }); - } - - // Add content to panel. - MUI.updateContent({ - 'element': this.panelEl, - 'content': options.content, - 'method': options.method, - 'data': options.data, - 'url': options.contentURL, - 'onContentLoaded': null, - 'require': { - js: options.require.js, - onload: options.require.onload - } - }); - - // Do this when creating and removing panels - $(options.column).getChildren('.panelWrapper').each(function(panelWrapper){ - panelWrapper.getElement('.panel').removeClass('bottomPanel'); - }); - $(options.column).getChildren('.panelWrapper').getLast().getElement('.panel').addClass('bottomPanel'); - - MUI.panelHeight(options.column, this.panelEl, 'new'); - - }, - collapseToggleInit: function(options){ - - var options = this.options; - - this.panelHeaderCollapseBoxEl = new Element('div', { - 'id': options.id + '_headerCollapseBox', - 'class': 'toolbox' - }).inject(this.panelHeaderEl); - - if (options.headerToolbox) { - this.panelHeaderCollapseBoxEl.addClass('divider'); - } - - this.collapseToggleEl = new Element('div', { - 'id': options.id + '_collapseToggle', - 'class': 'panel-collapse icon16', - 'styles': { - 'width': 16, - 'height': 16 - }, - 'title': 'Collapse Panel' - }).inject(this.panelHeaderCollapseBoxEl); - - this.collapseToggleEl.addEvent('click', function(event){ - var panel = this.panelEl; - var panelWrapper = this.panelWrapperEl - - // Get siblings and make sure they are not all collapsed. - // If they are all collapsed and the current panel is collapsing - // Then collapse the column. - var instances = MUI.Panels.instances; - var expandedSiblings = []; - - panelWrapper.getAllPrevious('.panelWrapper').each(function(sibling){ - var instance = instances.get(sibling.getElement('.panel').id); - if (instance.isCollapsed == false){ - expandedSiblings.push(sibling.getElement('.panel').id); - } - }); - - panelWrapper.getAllNext('.panelWrapper').each(function(sibling){ - var instance = instances.get(sibling.getElement('.panel').id); - if (instance.isCollapsed == false){ - expandedSiblings.push(sibling.getElement('.panel').id); - } - }); - - // Collapse Panel - if (this.isCollapsed == false) { - var currentColumn = MUI.Columns.instances.get($(options.column).id); - - if (expandedSiblings.length == 0 && currentColumn.options.placement != 'main'){ - var currentColumn = MUI.Columns.instances.get($(options.column).id); - currentColumn.columnToggle(); - return; - } - else if (expandedSiblings.length == 0 && currentColumn.options.placement == 'main'){ - return; - } - this.oldHeight = panel.getStyle('height').toInt(); - if (this.oldHeight < 10) this.oldHeight = 20; - this.contentEl.setStyle('position', 'absolute'); // This is so IE6 and IE7 will collapse the panel all the way - panel.setStyle('height', 0); - this.isCollapsed = true; - panelWrapper.addClass('collapsed'); - panelWrapper.removeClass('expanded'); - MUI.panelHeight(options.column, panel, 'collapsing'); - MUI.panelHeight(); // Run this a second time for panels within panels - this.collapseToggleEl.removeClass('panel-collapsed'); - this.collapseToggleEl.addClass('panel-expand'); - this.collapseToggleEl.setProperty('title','Expand Panel'); - this.fireEvent('onCollapse'); - } - - // Expand Panel - else { - this.contentEl.setStyle('position', null); // This is so IE6 and IE7 will collapse the panel all the way - panel.setStyle('height', this.oldHeight); - this.isCollapsed = false; - panelWrapper.addClass('expanded'); - panelWrapper.removeClass('collapsed'); - MUI.panelHeight(this.options.column, panel, 'expanding'); - MUI.panelHeight(); // Run this a second time for panels within panels - this.collapseToggleEl.removeClass('panel-expand'); - this.collapseToggleEl.addClass('panel-collapsed'); - this.collapseToggleEl.setProperty('title','Collapse Panel'); - this.fireEvent('onExpand'); - } - }.bind(this)); - } -}); -MUI.Panel.implement(new Options, new Events); - -/* - arguments: - column - The column to resize the panels in - changing - The panel that is collapsing, expanding, or new - action - collapsing, expanding, or new - -*/ - -MUI.extend({ - // Panel Height - panelHeight: function(column, changing, action){ - if (column != null) { - MUI.panelHeight2($(column), changing, action); - } - else { - $$('.column').each(function(column){ - MUI.panelHeight2(column); - }.bind(this)); - } - }, - /* - - actions can be new, collapsing or expanding. - - */ - panelHeight2: function(column, changing, action){ - - var instances = MUI.Panels.instances; - - var parent = column.getParent(); - var columnHeight = parent.getStyle('height').toInt(); - if (Browser.Engine.trident4 && parent == MUI.Desktop.pageWrapper) { - columnHeight -= 1; - } - column.setStyle('height', columnHeight); - - // Get column panels - var panels = []; - column.getChildren('.panelWrapper').each( function(panelWrapper){ - panels.push(panelWrapper.getElement('.panel')); - }.bind(this)); - - // Get expanded column panels - var panelsExpanded = []; - column.getChildren('.expanded').each( function(panelWrapper){ - panelsExpanded.push(panelWrapper.getElement('.panel')); - }.bind(this)); - - // All the panels in the column whose height will be effected. - var panelsToResize = []; - - // The panel with the greatest height. Remainders will be added to this panel - var tallestPanel; - var tallestPanelHeight = 0; - - this.panelsTotalHeight = 0; // Height of all the panels in the column - this.height = 0; // Height of all the elements in the column - - // Set panel resize partners - panels.each(function(panel){ - instance = instances.get(panel.id); - if (panel.getParent().hasClass('expanded') && panel.getParent().getNext('.expanded')) { - instance.partner = panel.getParent().getNext('.expanded').getElement('.panel'); - instance.resize.attach(); - instance.handleEl.setStyles({ - 'display': 'block', - 'cursor': (Browser.Engine.webkit || Browser.Engine.gecko) ? 'row-resize' : 'n-resize' - }).removeClass('detached'); - } else { - instance.resize.detach(); - instance.handleEl.setStyles({ - 'display': 'none', - 'cursor': null - }).addClass('detached'); - } - if (panel.getParent().getNext('.panelWrapper') == null) { - instance.handleEl.hide(); - } - }.bind(this)); - - // Add panels to panelsToResize - // Get the total height of all the resizable panels - // Get the total height of all the column's children - column.getChildren().each(function(panelWrapper){ - - panelWrapper.getChildren().each(function(el){ - - if (el.hasClass('panel')){ - var instance = instances.get(el.id); - - // Are any next siblings Expanded? - anyNextSiblingsExpanded = function(el){ - var test; - el.getParent().getAllNext('.panelWrapper').each(function(sibling){ - var siblingInstance = instances.get(sibling.getElement('.panel').id); - if (siblingInstance.isCollapsed == false){ - test = true; - } - }.bind(this)); - return test; - }.bind(this); - - // If a next sibling is expanding, are any of the nexts siblings of the expanding sibling Expanded? - anyExpandingNextSiblingsExpanded = function(el){ - var test; - changing.getParent().getAllNext('.panelWrapper').each(function(sibling){ - var siblingInstance = instances.get(sibling.getElement('.panel').id); - if (siblingInstance.isCollapsed == false){ - test = true; - } - }.bind(this)); - return test; - }.bind(this); - - // Is the panel that is collapsing, expanding, or new located after this panel? - anyNextContainsChanging = function(el){ - var allNext = []; - el.getParent().getAllNext('.panelWrapper').each(function(panelWrapper){ - allNext.push(panelWrapper.getElement('.panel')); - }.bind(this)); - var test = allNext.contains(changing); - return test; - }.bind(this); - - nextExpandedChanging = function(el){ - var test; - if (el.getParent().getNext('.expanded')){ - if (el.getParent().getNext('.expanded').getElement('.panel') == changing) test = true; - } - return test; - } - - // NEW PANEL - // Resize panels that are "new" or not collapsed - if (action == 'new') { - if (!instance.isCollapsed && el != changing) { - panelsToResize.push(el); - this.panelsTotalHeight += el.offsetHeight.toInt(); - } - } - - // COLLAPSING PANELS and CURRENTLY EXPANDED PANELS - // Resize panels that are not collapsed. - // If a panel is collapsing resize any expanded panels below. - // If there are no expanded panels below it, resize the expanded panels above it. - else if (action == null || action == 'collapsing' ){ - if (!instance.isCollapsed && (!anyNextContainsChanging(el) || !anyNextSiblingsExpanded(el))){ - panelsToResize.push(el); - this.panelsTotalHeight += el.offsetHeight.toInt(); - } - } - - // EXPANDING PANEL - // Resize panels that are not collapsed and are not expanding. - // Resize any expanded panels below the expanding panel. - // If there are no expanded panels below the expanding panel, resize the first expanded panel above it. - else if (action == 'expanding' && !instance.isCollapsed && el != changing){ - if (!anyNextContainsChanging(el) || (!anyExpandingNextSiblingsExpanded(el) && nextExpandedChanging(el))){ - panelsToResize.push(el); - this.panelsTotalHeight += el.offsetHeight.toInt(); - } - } - - if (el.style.height){ - this.height += el.getStyle('height').toInt(); - } - } - else { - this.height += el.offsetHeight.toInt(); - } - }.bind(this)); - - }.bind(this)); - - // Get the remaining height - var remainingHeight = column.offsetHeight.toInt() - this.height; - - this.height = 0; - - // Get height of all the column's children - column.getChildren().each(function(el){ - this.height += el.offsetHeight.toInt(); - }.bind(this)); - - var remainingHeight = column.offsetHeight.toInt() - this.height; - - panelsToResize.each(function(panel){ - var ratio = this.panelsTotalHeight / panel.offsetHeight.toInt(); - var panelHeight = panel.getStyle('height').toInt(); - var newPanelHeight = remainingHeight / ratio; - if (!isNaN(panelHeight)) - newPanelHeight += panelHeight; - if (newPanelHeight < 1){ - newPanelHeight = 0; - } - panel.setStyle('height', newPanelHeight); - }.bind(this)); - - // Make sure the remaining height is 0. If not add/subtract the - // remaining height to the tallest panel. This makes up for browser resizing, - // off ratios, and users trying to give panels too much height. - - // Get height of all the column's children - this.height = 0; - column.getChildren().each(function(panelWrapper){ - panelWrapper.getChildren().each(function(el){ - this.height += el.offsetHeight.toInt(); - if (el.hasClass('panel') && el.getStyle('height').toInt() > tallestPanelHeight){ - tallestPanel = el; - tallestPanelHeight = el.getStyle('height').toInt(); - } - }.bind(this)); - }.bind(this)); - - var remainingHeight = column.offsetHeight.toInt() - this.height; - - if (remainingHeight != 0 && tallestPanelHeight > 0){ - tallestPanel.setStyle('height', tallestPanel.getStyle('height').toInt() + remainingHeight ); - if (tallestPanel.getStyle('height') < 1){ - tallestPanel.setStyle('height', 0 ); - } - } - - parent.getChildren('.columnHandle').each(function(handle){ - var parent = handle.getParent(); - if (parent.getStyle('height').toInt() < 1) return; // Keeps IE7 and 8 from throwing an error when collapsing a panel within a panel - var handleHeight = parent.getStyle('height').toInt() - handle.getStyle('margin-top').toInt() - handle.getStyle('margin-bottom').toInt(); - if (Browser.Engine.trident4 && parent == MUI.Desktop.pageWrapper){ - handleHeight -= 1; - } - handle.setStyle('height', handleHeight); - }); - - panelsExpanded.each(function(panel){ - MUI.resizeChildren(panel); - }.bind(this)); - - }, - // May rename this resizeIframeEl() - resizeChildren: function(panel){ - var instances = MUI.Panels.instances; - var instance = instances.get(panel.id); - var contentWrapperEl = instance.contentWrapperEl; - - if (instance.iframeEl) { - if (!MUI.ieLegacySupport) { - instance.iframeEl.setStyles({ - 'height': contentWrapperEl.getStyle('height'), - 'width': contentWrapperEl.offsetWidth - contentWrapperEl.getStyle('margin-left').toInt() - contentWrapperEl.getStyle('margin-right').toInt() - }); - } - else { - // The following hack is to get IE8 RC1 IE8 Standards Mode to properly resize an iframe - // when only the vertical dimension is changed. - instance.iframeEl.setStyles({ - 'height': contentWrapperEl.getStyle('height'), - 'width': contentWrapperEl.offsetWidth - contentWrapperEl.getStyle('margin-left').toInt() - contentWrapperEl.getStyle('margin-right').toInt() - 1 - }); - instance.iframeEl.setStyles({ - 'width': contentWrapperEl.offsetWidth - contentWrapperEl.getStyle('margin-left').toInt() - contentWrapperEl.getStyle('margin-right').toInt() - }); - } - } - - }, - // Remaining Width - rWidth: function(container){ - if (container == null) { - var container = MUI.Desktop.desktop; - } - container.getElements('.rWidth').each(function(column){ - var currentWidth = column.offsetWidth.toInt(); - currentWidth -= column.getStyle('margin-left').toInt(); - currentWidth -= column.getStyle('margin-right').toInt(); - var parent = column.getParent(); - this.width = 0; - - // Get the total width of all the parent element's children - parent.getChildren().each(function(el){ - if (el.hasClass('mocha') != true) { - this.width += el.offsetWidth.toInt(); - } - }.bind(this)); - - // Add the remaining width to the current element - var remainingWidth = parent.offsetWidth.toInt() - this.width; - var newWidth = currentWidth + remainingWidth; - if (newWidth < 1) newWidth = 0; - column.setStyle('width', newWidth); - column.getChildren('.panel').each(function(panel){ - panel.setStyle('width', newWidth - panel.getStyle('margin-left').toInt() - panel.getStyle('margin-right').toInt()); - MUI.resizeChildren(panel); - }.bind(this)); - - }); - } - -}); - -function addResizeRight(element, min, max){ - if (!$(element)) return; - element = $(element); - - var instances = MUI.Columns.instances; - var instance = instances.get(element.id); - - var handle = element.getNext('.columnHandle'); - handle.setStyle('cursor', (Browser.Engine.webkit || Browser.Engine.gecko) ? 'col-resize' : 'e-resize'); - if (!min) min = 50; - if (!max) max = 250; - if (MUI.ieLegacySupport) { - handle.addEvents({ - 'mousedown': function(){ - handle.setCapture(); - }, - 'mouseup': function(){ - handle.releaseCapture(); - } - }); - } - instance.resize = element.makeResizable({ - handle: handle, - modifiers: { - x: 'width', - y: false - }, - limit: { - x: [min, max] - }, - onStart: function(){ - element.getElements('iframe').setStyle('visibility', 'hidden'); - element.getNext('.column').getElements('iframe').setStyle('visibility', 'hidden'); - }.bind(this), - onDrag: function(){ - MUI.rWidth(element.getParent()); - if (Browser.Engine.trident4) { - element.getChildren().each(function(el){ - var width = $(element).getStyle('width').toInt(); - width -= el.getStyle('margin-right').toInt(); - width -= el.getStyle('margin-left').toInt(); - width -= el.getStyle('padding-right').toInt(); - width -= el.getStyle('padding-left').toInt(); - el.setStyle('width', width); - }.bind(this)); - } - }.bind(this), - onComplete: function(){ - MUI.rWidth(element.getParent()); - element.getElements('iframe').setStyle('visibility', 'visible'); - element.getNext('.column').getElements('iframe').setStyle('visibility', 'visible'); - instance.fireEvent('onResize'); - }.bind(this) - }); -} - -function addResizeLeft(element, min, max){ - if (!$(element)) return; - element = $(element); - - var instances = MUI.Columns.instances; - var instance = instances.get(element.id); - - var handle = element.getPrevious('.columnHandle'); - handle.setStyle('cursor', (Browser.Engine.webkit || Browser.Engine.gecko) ? 'col-resize' : 'e-resize'); - var partner = element.getPrevious('.column'); - if (!min) min = 50; - if (!max) max = 250; - if (MUI.ieLegacySupport){ - handle.addEvents({ - 'mousedown': function(){ - handle.setCapture(); - }, - 'mouseup': function(){ - handle.releaseCapture(); - } - }); - } - instance.resize = element.makeResizable({ - handle: handle, - modifiers: {x: 'width' , y: false}, - invert: true, - limit: { x: [min, max] }, - onStart: function(){ - $(element).getElements('iframe').setStyle('visibility','hidden'); - partner.getElements('iframe').setStyle('visibility','hidden'); - }.bind(this), - onDrag: function(){ - MUI.rWidth(element.getParent()); - }.bind(this), - onComplete: function(){ - MUI.rWidth(element.getParent()); - $(element).getElements('iframe').setStyle('visibility','visible'); - partner.getElements('iframe').setStyle('visibility','visible'); - instance.fireEvent('onResize'); - }.bind(this) - }); -} - -function addResizeBottom(element){ - if (!$(element)) return; - var element = $(element); - - var instances = MUI.Panels.instances; - var instance = instances.get(element.id); - var handle = instance.handleEl; - handle.setStyle('cursor', (Browser.Engine.webkit || Browser.Engine.gecko) ? 'row-resize' : 'n-resize'); - partner = instance.partner; - min = 0; - max = function(){ - return element.getStyle('height').toInt() + partner.getStyle('height').toInt(); - }.bind(this); - - if (MUI.ieLegacySupport) { - handle.addEvents({ - 'mousedown': function(){ - handle.setCapture(); - }, - 'mouseup': function(){ - handle.releaseCapture(); - } - }); - } - instance.resize = element.makeResizable({ - handle: handle, - modifiers: {x: false, y: 'height'}, - limit: { y: [min, max] }, - invert: false, - onBeforeStart: function(){ - partner = instance.partner; - this.originalHeight = element.getStyle('height').toInt(); - this.partnerOriginalHeight = partner.getStyle('height').toInt(); - }.bind(this), - onStart: function(){ - if (instance.iframeEl) { - if (!MUI.ieLegacySupport) { - instance.iframeEl.setStyle('visibility', 'hidden'); - partner.getElements('iframe').setStyle('visibility','hidden'); - } - else { - instance.iframeEl.hide(); - partner.getElements('iframe').hide(); - } - } - - }.bind(this), - onDrag: function(){ - partnerHeight = partnerOriginalHeight; - partnerHeight += (this.originalHeight - element.getStyle('height').toInt()); - partner.setStyle('height', partnerHeight); - MUI.resizeChildren(element, element.getStyle('height').toInt()); - MUI.resizeChildren(partner, partnerHeight); - element.getChildren('.column').each( function(column){ - MUI.panelHeight(column); - }); - partner.getChildren('.column').each( function(column){ - MUI.panelHeight(column); - }); - }.bind(this), - onComplete: function(){ - partnerHeight = partnerOriginalHeight; - partnerHeight += (this.originalHeight - element.getStyle('height').toInt()); - partner.setStyle('height', partnerHeight); - MUI.resizeChildren(element, element.getStyle('height').toInt()); - MUI.resizeChildren(partner, partnerHeight); - element.getChildren('.column').each( function(column){ - MUI.panelHeight(column); - }); - partner.getChildren('.column').each( function(column){ - MUI.panelHeight(column); - }); - if (instance.iframeEl) { - if (!MUI.ieLegacySupport) { - instance.iframeEl.setStyle('visibility', 'visible'); - partner.getElements('iframe').setStyle('visibility','visible'); - } - else { - instance.iframeEl.show(); - partner.getElements('iframe').show(); - // The following hack is to get IE8 Standards Mode to properly resize an iframe - // when only the vertical dimension is changed. - var width = instance.iframeEl.getStyle('width').toInt(); - instance.iframeEl.setStyle('width', width - 1); - MUI.rWidth(); - instance.iframeEl.setStyle('width', width); - } - } - instance.fireEvent('onResize'); - }.bind(this) - }); -} - -MUI.extend({ - /* - - Function: closeColumn - Destroys/removes a column. - - Syntax: - (start code) - MUI.closeColumn(); - (end) - - Arguments: - columnEl - the ID of the column to be closed - - Returns: - true - the column was closed - false - the column was not closed - - */ - closeColumn: function(columnEl){ - var instances = MUI.Columns.instances; - var instance = instances.get(columnEl.id); - if (columnEl != $(columnEl) || instance.isClosing) return; - - instance.isClosing = true; - - if (instance.options.sortable){ - instance.container.retrieve('sortables').removeLists(this.columnEl); - } - - // Destroy all the panels in the column. - var panels = columnEl.getChildren('.panel'); - panels.each(function(panel){ - MUI.closePanel($(panel.id)); - }.bind(this)); - - if (MUI.ieLegacySupport) { - columnEl.dispose(); - if (instance.handleEl != null) { - instance.handleEl.dispose(); - } - } - else { - columnEl.destroy(); - if (instance.handleEl != null) { - instance.handleEl.destroy(); - } - } - if (MUI.Desktop) { - MUI.Desktop.resizePanels(); - } - instances.erase(instance.options.id); - return true; - }, - /* - - Function: closePanel - Destroys/removes a panel. - - Syntax: - (start code) - MUI.closePanel(); - (end) - - Arguments: - panelEl - the ID of the panel to be closed - - Returns: - true - the panel was closed - false - the panel was not closed - - */ - closePanel: function(panelEl){ - var instances = MUI.Panels.instances; - var instance = instances.get(panelEl.id); - if (panelEl != $(panelEl) || instance.isClosing) return; - - var column = instance.options.column; - - instance.isClosing = true; - - var columnInstances = MUI.Columns.instances; - var columnInstance = columnInstances.get(column); - - if (columnInstance.options.sortable){ - columnInstance.options.container.retrieve('sortables').removeItems(instance.panelWrapperEl); - } - - instance.panelWrapperEl.destroy(); - - if (MUI.Desktop) { - MUI.Desktop.resizePanels(); - } - - // Do this when creating and removing panels - $(column).getChildren('.panelWrapper').each(function(panelWrapper){ - panelWrapper.getElement('.panel').removeClass('bottomPanel'); - }); - $(column).getChildren('.panelWrapper').getLast().getElement('.panel').addClass('bottomPanel'); - - instances.erase(instance.options.id); - return true; - - } -}); -/* - -Script: Dock.js - Implements the dock/taskbar. Enables window minimize. - -Copyright: - Copyright (c) 2007-2009 Greg Houston, . - -License: - MIT-style license. - -Requires: - Core.js, Window.js, Layout.js - -Todo: - - Make it so the dock requires no initial html markup. - -*/ - -MUI.files[MUI.path.source + 'Layout/Dock.js'] = 'loaded'; - -MUI.options.extend({ - // Naming options: - // If you change the IDs of the Mocha Desktop containers in your HTML, you need to change them here as well. - dockWrapper: 'dockWrapper', - dock: 'dock' -}); - -MUI.extend({ - /* - - Function: minimizeAll - Minimize all windows that are minimizable. - - */ - minimizeAll: function() { - $$('.mocha').each(function(windowEl){ - var instance = windowEl.retrieve('instance'); - if (!instance.isMinimized && instance.options.minimizable == true){ - MUI.Dock.minimizeWindow(windowEl); - } - }.bind(this)); - } -}); - -MUI.Dock = { - - options: { - useControls: true, // Toggles autohide and dock placement controls. - dockPosition: 'bottom', // Position the dock starts in, top or bottom. - // Style options - trueButtonColor: [70, 245, 70], // Color for autohide on - enabledButtonColor: [115, 153, 191], - disabledButtonColor: [170, 170, 170] - }, - - initialize: function(options){ - // Stops if MUI.Desktop is not implemented - if (!MUI.Desktop) return; - - MUI.dockVisible = true; - this.dockWrapper = $(MUI.options.dockWrapper); - this.dock = $(MUI.options.dock); - this.autoHideEvent = null; - this.dockAutoHide = false; // True when dock autohide is set to on, false if set to off - - if (!this.dockWrapper) return; - - if (!this.options.useControls){ - if($('dockPlacement')){ - $('dockPlacement').setStyle('cursor', 'default'); - } - if($('dockAutoHide')){ - $('dockAutoHide').setStyle('cursor', 'default'); - } - } - - this.dockWrapper.setStyles({ - 'display': 'block', - 'position': 'absolute', - 'top': null, - 'bottom': MUI.Desktop.desktopFooter ? MUI.Desktop.desktopFooter.offsetHeight : 0, - 'left': 0 - }); - - if (this.options.useControls){ - this.initializeDockControls(); - } - - // Add check mark to menu if link exists in menu - if ($('dockLinkCheck')){ - this.sidebarCheck = new Element('div', { - 'class': 'check', - 'id': 'dock_check' - }).inject($('dockLinkCheck')); - } - - this.dockSortables = new Sortables('#dockSort', { - opacity: 1, - constrain: true, - clone: false, - revert: false - }); - - MUI.Desktop.setDesktopSize(); - - if (MUI.myChain){ - MUI.myChain.callChain(); - } - - }, - - initializeDockControls: function(){ - - // Convert CSS colors to Canvas colors. - this.setDockColors(); - - if (this.options.useControls){ - // Insert canvas - var canvas = new Element('canvas', { - 'id': 'dockCanvas', - 'width': '15', - 'height': '18' - }).inject(this.dock); - - // Dynamically initialize canvas using excanvas. This is only required by IE - if (MUI.ieLegacySupport && MUI.ieSupport == 'excanvas'){ - G_vmlCanvasManager.initElement(canvas); - } - } - - var dockPlacement = $('dockPlacement'); - var dockAutoHide = $('dockAutoHide'); - - // Position top or bottom selector - dockPlacement.setProperty('title','Position Dock Top'); - - // Attach event - dockPlacement.addEvent('click', function(){ - this.moveDock(); - }.bind(this)); - - // Auto Hide toggle switch - dockAutoHide.setProperty('title','Turn Auto Hide On'); - - // Attach event Auto Hide - dockAutoHide.addEvent('click', function(event){ - if ( this.dockWrapper.getProperty('dockPosition') == 'top' ) - return false; - - var ctx = $('dockCanvas').getContext('2d'); - this.dockAutoHide = !this.dockAutoHide; // Toggle - if (this.dockAutoHide){ - $('dockAutoHide').setProperty('title', 'Turn Auto Hide Off'); - //ctx.clearRect(0, 11, 100, 100); - MUI.circle(ctx, 5 , 14, 3, this.options.trueButtonColor, 1.0); - - // Define event - this.autoHideEvent = function(event) { - if (!this.dockAutoHide) - return; - if (!MUI.Desktop.desktopFooter) { - var dockHotspotHeight = this.dockWrapper.offsetHeight; - if (dockHotspotHeight < 25) dockHotspotHeight = 25; - } - else if (MUI.Desktop.desktopFooter) { - var dockHotspotHeight = this.dockWrapper.offsetHeight + MUI.Desktop.desktopFooter.offsetHeight; - if (dockHotspotHeight < 25) dockHotspotHeight = 25; - } - if (!MUI.Desktop.desktopFooter && event.client.y > (document.getCoordinates().height - dockHotspotHeight)){ - if (!MUI.dockVisible){ - this.dockWrapper.show(); - MUI.dockVisible = true; - MUI.Desktop.setDesktopSize(); - } - } - else if (MUI.Desktop.desktopFooter && event.client.y > (document.getCoordinates().height - dockHotspotHeight)){ - if (!MUI.dockVisible){ - this.dockWrapper.show(); - MUI.dockVisible = true; - MUI.Desktop.setDesktopSize(); - } - } - else if (MUI.dockVisible){ - this.dockWrapper.hide(); - MUI.dockVisible = false; - MUI.Desktop.setDesktopSize(); - - } - }.bind(this); - - // Add event - document.addEvent('mousemove', this.autoHideEvent); - - } else { - $('dockAutoHide').setProperty('title', 'Turn Auto Hide On'); - //ctx.clearRect(0, 11, 100, 100); - MUI.circle(ctx, 5 , 14, 3, this.options.enabledButtonColor, 1.0); - // Remove event - document.removeEvent('mousemove', this.autoHideEvent); - } - - }.bind(this)); - - this.renderDockControls(); - - if (this.options.dockPosition == 'top'){ - this.moveDock(); - } - - }, - - setDockColors: function(){ - var dockButtonEnabled = MUI.getCSSRule('.dockButtonEnabled'); - if (dockButtonEnabled && dockButtonEnabled.style.backgroundColor){ - this.options.enabledButtonColor = new Color(dockButtonEnabled.style.backgroundColor); - } - - var dockButtonDisabled = MUI.getCSSRule('.dockButtonDisabled'); - if (dockButtonDisabled && dockButtonDisabled.style.backgroundColor){ - this.options.disabledButtonColor = new Color(dockButtonDisabled.style.backgroundColor); - } - - var trueButtonColor = MUI.getCSSRule('.dockButtonTrue'); - if (trueButtonColor && trueButtonColor.style.backgroundColor){ - this.options.trueButtonColor = new Color(trueButtonColor.style.backgroundColor); - } - }, - - renderDockControls: function(){ - // Draw dock controls - var ctx = $('dockCanvas').getContext('2d'); - ctx.clearRect(0, 0, 100, 100); - MUI.circle(ctx, 5 , 4, 3, this.options.enabledButtonColor, 1.0); - - if( this.dockWrapper.getProperty('dockPosition') == 'top'){ - MUI.circle(ctx, 5 , 14, 3, this.options.disabledButtonColor, 1.0) - } - else if (this.dockAutoHide){ - MUI.circle(ctx, 5 , 14, 3, this.options.trueButtonColor, 1.0); - } - else { - MUI.circle(ctx, 5 , 14, 3, this.options.enabledButtonColor, 1.0); - } - }, - - moveDock: function(){ - var ctx = $('dockCanvas').getContext('2d'); - // Move dock to top position - if (this.dockWrapper.getStyle('position') != 'relative'){ - this.dockWrapper.setStyles({ - 'position': 'relative', - 'bottom': null - }); - this.dockWrapper.addClass('top'); - MUI.Desktop.setDesktopSize(); - this.dockWrapper.setProperty('dockPosition','top'); - ctx.clearRect(0, 0, 100, 100); - MUI.circle(ctx, 5, 4, 3, this.options.enabledButtonColor, 1.0); - MUI.circle(ctx, 5, 14, 3, this.options.disabledButtonColor, 1.0); - $('dockPlacement').setProperty('title', 'Position Dock Bottom'); - $('dockAutoHide').setProperty('title', 'Auto Hide Disabled in Top Dock Position'); - this.dockAutoHide = false; - } - // Move dock to bottom position - else { - this.dockWrapper.setStyles({ - 'position': 'absolute', - 'bottom': MUI.Desktop.desktopFooter ? MUI.Desktop.desktopFooter.offsetHeight : 0 - }); - this.dockWrapper.removeClass('top'); - MUI.Desktop.setDesktopSize(); - this.dockWrapper.setProperty('dockPosition', 'bottom'); - ctx.clearRect(0, 0, 100, 100); - MUI.circle(ctx, 5, 4, 3, this.options.enabledButtonColor, 1.0); - MUI.circle(ctx, 5 , 14, 3, this.options.enabledButtonColor, 1.0); - $('dockPlacement').setProperty('title', 'Position Dock Top'); - $('dockAutoHide').setProperty('title', 'Turn Auto Hide On'); - } - }, - - createDockTab: function(windowEl){ - - var instance = windowEl.retrieve('instance'); - - var dockTab = new Element('div', { - 'id': instance.options.id + '_dockTab', - 'class': 'dockTab', - 'title': titleText - }).inject($('dockClear'), 'before'); - - dockTab.addEvent('mousedown', function(e){ - new Event(e).stop(); - this.timeDown = $time(); - }); - - dockTab.addEvent('mouseup', function(e){ - this.timeUp = $time(); - if ((this.timeUp - this.timeDown) < 275){ - // If the visibility of the windows on the page are toggled off, toggle visibility on. - if (MUI.Windows.windowsVisible == false) { - MUI.toggleWindowVisibility(); - if (instance.isMinimized == true) { - MUI.Dock.restoreMinimized.delay(25, MUI.Dock, windowEl); - } - else { - MUI.focusWindow(windowEl); - } - return; - } - // If window is minimized, restore window. - if (instance.isMinimized == true) { - MUI.Dock.restoreMinimized.delay(25, MUI.Dock, windowEl); - } - else{ - // If window is not minimized and is focused, minimize window. - if (instance.windowEl.hasClass('isFocused') && instance.options.minimizable == true){ - MUI.Dock.minimizeWindow(windowEl) - } - // If window is not minimized and is not focused, focus window. - else{ - MUI.focusWindow(windowEl); - } - // if the window is not minimized and is outside the viewport, center it in the viewport. - var coordinates = document.getCoordinates(); - if (windowEl.getStyle('left').toInt() > coordinates.width || windowEl.getStyle('top').toInt() > coordinates.height){ - MUI.centerWindow(windowEl); - } - } - } - }); - - this.dockSortables.addItems(dockTab); - - var titleText = instance.titleEl.innerHTML; - - var dockTabText = new Element('div', { - 'id': instance.options.id + '_dockTabText', - 'class': 'dockText' - }).set('html', titleText.substring(0,19) + (titleText.length > 19 ? '...' : '')).inject($(dockTab)); - - // If I implement this again, will need to also adjust the titleText truncate and the tab's - // left padding. - if (instance.options.icon != false){ - // dockTabText.setStyle('background', 'url(' + instance.options.icon + ') 4px 4px no-repeat'); - } - - // Need to resize everything in case the dock wraps when a new tab is added - MUI.Desktop.setDesktopSize(); - - }, - - makeActiveTab: function(){ - - // getWindowWith HighestZindex is used in case the currently focused window - // is closed. - var windowEl = MUI.getWindowWithHighestZindex(); - var instance = windowEl.retrieve('instance'); - - $$('.dockTab').removeClass('activeDockTab'); - if (instance.isMinimized != true) { - - instance.windowEl.addClass('isFocused'); - - var currentButton = $(instance.options.id + '_dockTab'); - if (currentButton != null) { - currentButton.addClass('activeDockTab'); - } - } - else { - instance.windowEl.removeClass('isFocused'); - } - }, - - minimizeWindow: function(windowEl){ - if (windowEl != $(windowEl)) return; - - var instance = windowEl.retrieve('instance'); - instance.isMinimized = true; - - // Hide iframe - // Iframe should be hidden when minimizing, maximizing, and moving for performance and Flash issues - if ( instance.iframeEl ) { - // Some elements are still visible in IE8 in the iframe when the iframe's visibility is set to hidden. - if (!MUI.ieLegacySupport) { - instance.iframeEl.setStyle('visibility', 'hidden'); - } - else { - instance.iframeEl.hide(); - } - } - - // Hide window and add to dock - instance.contentBorderEl.setStyle('visibility', 'hidden'); - if(instance.toolbarWrapperEl){ - instance.toolbarWrapperEl.hide(); - } - windowEl.setStyle('visibility', 'hidden'); - - MUI.Desktop.setDesktopSize(); - - // Have to use timeout because window gets focused when you click on the minimize button - setTimeout(function(){ - windowEl.setStyle('zIndex', 1); - windowEl.removeClass('isFocused'); - this.makeActiveTab(); - }.bind(this),100); - - instance.fireEvent('onMinimize', windowEl); - }, - - restoreMinimized: function(windowEl) { - - var instance = windowEl.retrieve('instance'); - - if (instance.isMinimized == false) return; - - if (MUI.Windows.windowsVisible == false){ - MUI.toggleWindowVisibility(); - } - - MUI.Desktop.setDesktopSize(); - - // Part of Mac FF2 scrollbar fix - if (instance.options.scrollbars == true && !instance.iframeEl){ - instance.contentWrapperEl.setStyle('overflow', 'auto'); - } - - if (instance.isCollapsed) { - MUI.collapseToggle(windowEl); - } - - windowEl.setStyle('visibility', 'visible'); - instance.contentBorderEl.setStyle('visibility', 'visible'); - if(instance.toolbarWrapperEl){ - instance.toolbarWrapperEl.show(); - } - - // Show iframe - if (instance.iframeEl){ - if (!MUI.ieLegacySupport){ - instance.iframeEl.setStyle('visibility', 'visible'); - } - else { - instance.iframeEl.show(); - } - } - - instance.isMinimized = false; - MUI.focusWindow(windowEl); - instance.fireEvent('onRestore', windowEl); - - } -}; -/* - -Script: Workspaces.js - Save and load workspaces. The Workspaces emulate Adobe Illustrator functionality remembering what windows are open and where they are positioned. - -Copyright: - Copyright (c) 2007-2009 Greg Houston, . - -License: - MIT-style license. - -Requires: - Core.js, Window.js - -To do: - - Move to Window - -*/ - -MUI.files[MUI.path.source + 'Layout/Workspaces.js'] = 'loaded'; - -MUI.extend({ - /* - - Function: saveWorkspace - Save the current workspace. - - Syntax: - (start code) - MUI.saveWorkspace(); - (end) - - Notes: - This version saves the ID of each open window to a cookie, and reloads those windows using the functions in mocha-init.js. This requires that each window have a function in mocha-init.js used to open them. Functions must be named the windowID + "Window". So if your window is called mywindow, it needs a function called mywindowWindow in mocha-init.js. - - */ - saveWorkspace: function(){ - this.cookie = new Hash.Cookie('mochaUIworkspaceCookie', {duration: 3600}); - this.cookie.empty(); - MUI.Windows.instances.each(function(instance) { - instance.saveValues(); - this.cookie.set(instance.options.id, { - 'id': instance.options.id, - 'top': instance.options.y, - 'left': instance.options.x, - 'width': instance.contentWrapperEl.getStyle('width').toInt(), - 'height': instance.contentWrapperEl.getStyle('height').toInt() - }); - }.bind(this)); - this.cookie.save(); - - new MUI.Window({ - loadMethod: 'html', - type: 'notification', - addClass: 'notification', - content: 'Workspace saved.', - closeAfter: '1400', - width: 200, - height: 40, - y: 53, - padding: { top: 10, right: 12, bottom: 10, left: 12 }, - shadowBlur: 5, - bodyBgColor: [255, 255, 255] - }); - - }, - windowUnload: function(){ - if ($$('.mocha').length == 0 && this.myChain){ - this.myChain.callChain(); - } - }, - loadWorkspace2: function(workspaceWindows){ - workspaceWindows.each(function(workspaceWindow){ - windowFunction = eval('MUI.' + workspaceWindow.id + 'Window'); - if (windowFunction){ - eval('MUI.' + workspaceWindow.id + 'Window({width:'+ workspaceWindow.width +',height:' + workspaceWindow.height + '});'); - var windowEl = $(workspaceWindow.id); - windowEl.setStyles({ - 'top': workspaceWindow.top, - 'left': workspaceWindow.left - }); - var instance = windowEl.retrieve('instance'); - instance.contentWrapperEl.setStyles({ - 'width': workspaceWindow.width, - 'height': workspaceWindow.height - }); - instance.drawWindow(); - } - }.bind(this)); - this.loadingWorkspace = false; - }, - /* - - Function: loadWorkspace - Load the saved workspace. - - Syntax: - (start code) - MUI.loadWorkspace(); - (end) - - */ - loadWorkspace: function(){ - cookie = new Hash.Cookie('mochaUIworkspaceCookie', {duration: 3600}); - workspaceWindows = cookie.load(); - - if(!cookie.getKeys().length){ - new MUI.Window({ - loadMethod: 'html', - type: 'notification', - addClass: 'notification', - content: 'You have no saved workspace.', - closeAfter: '1400', - width: 220, - height: 40, - y: 25, - padding: { top: 10, right: 12, bottom: 10, left: 12 }, - shadowBlur: 5, - bodyBgColor: [255, 255, 255] - }); - return; - } - - if ($$('.mocha').length != 0){ - this.loadingWorkspace = true; - this.myChain = new Chain(); - this.myChain.chain( - function(){ - $$('.mocha').each(function(el) { - this.closeWindow(el); - }.bind(this)); - }.bind(this), - function(){ - this.loadWorkspace2(workspaceWindows); - }.bind(this) - ); - this.myChain.callChain(); - } - else { - this.loadWorkspace2(workspaceWindows); - } - - } -}); diff --git a/src/webui/www/public/scripts/mootools-1.2-core-yc.js b/src/webui/www/public/scripts/mootools-1.2-core-yc.js deleted file mode 100644 index 288f2a8d4..000000000 --- a/src/webui/www/public/scripts/mootools-1.2-core-yc.js +++ /dev/null @@ -1,527 +0,0 @@ -/* ---- -MooTools: the javascript framework - -web build: - - http://mootools.net/core/76bf47062d6c1983d66ce47ad66aa0e0 - -packager build: - - packager build Core/Core Core/Array Core/String Core/Number Core/Function Core/Object Core/Event Core/Browser Core/Class Core/Class.Extras Core/Slick.Parser Core/Slick.Finder Core/Element Core/Element.Style Core/Element.Event Core/Element.Delegation Core/Element.Dimensions Core/Fx Core/Fx.CSS Core/Fx.Tween Core/Fx.Morph Core/Fx.Transitions Core/Request Core/Request.HTML Core/Request.JSON Core/Cookie Core/JSON Core/DOMReady Core/Swiff - -copyrights: - - [MooTools](http://mootools.net) - -licenses: - - [MIT License](http://mootools.net/license.txt) -... -*/ - -(function(){this.MooTools={version:"1.4.5",build:"ab8ea8824dc3b24b6666867a2c4ed58ebb762cf0"};var e=this.typeOf=function(i){if(i==null){return"null";}if(i.$family!=null){return i.$family(); -}if(i.nodeName){if(i.nodeType==1){return"element";}if(i.nodeType==3){return(/\S/).test(i.nodeValue)?"textnode":"whitespace";}}else{if(typeof i.length=="number"){if(i.callee){return"arguments"; -}if("item" in i){return"collection";}}}return typeof i;};var u=this.instanceOf=function(w,i){if(w==null){return false;}var v=w.$constructor||w.constructor; -while(v){if(v===i){return true;}v=v.parent;}if(!w.hasOwnProperty){return false;}return w instanceof i;};var f=this.Function;var r=true;for(var q in {toString:1}){r=null; -}if(r){r=["hasOwnProperty","valueOf","isPrototypeOf","propertyIsEnumerable","toLocaleString","toString","constructor"];}f.prototype.overloadSetter=function(v){var i=this; -return function(x,w){if(x==null){return this;}if(v||typeof x!="string"){for(var y in x){i.call(this,y,x[y]);}if(r){for(var z=r.length;z--;){y=r[z];if(x.hasOwnProperty(y)){i.call(this,y,x[y]); -}}}}else{i.call(this,x,w);}return this;};};f.prototype.overloadGetter=function(v){var i=this;return function(x){var y,w;if(typeof x!="string"){y=x;}else{if(arguments.length>1){y=arguments; -}else{if(v){y=[x];}}}if(y){w={};for(var z=0;z>>0; -b>>0;b>>0;for(var a=(d<0)?Math.max(0,b+d):d||0;a>>0,b=Array(d);for(var a=0;a>>0; -b-1:String(this).indexOf(a)>-1;},trim:function(){return String(this).replace(/^\s+|\s+$/g,""); -},clean:function(){return String(this).replace(/\s+/g," ").trim();},camelCase:function(){return String(this).replace(/-\D/g,function(a){return a.charAt(1).toUpperCase(); -});},hyphenate:function(){return String(this).replace(/[A-Z]/g,function(a){return("-"+a.charAt(0).toLowerCase());});},capitalize:function(){return String(this).replace(/\b[a-z]/g,function(a){return a.toUpperCase(); -});},escapeRegExp:function(){return String(this).replace(/([-.*+?^${}()|[\]\/\\])/g,"\\$1");},toInt:function(a){return parseInt(this,a||10);},toFloat:function(){return parseFloat(this); -},hexToRgb:function(b){var a=String(this).match(/^#?(\w{1,2})(\w{1,2})(\w{1,2})$/);return(a)?a.slice(1).hexToRgb(b):null;},rgbToHex:function(b){var a=String(this).match(/\d{1,3}/g); -return(a)?a.rgbToHex(b):null;},substitute:function(a,b){return String(this).replace(b||(/\\?\{([^{}]+)\}/g),function(d,c){if(d.charAt(0)=="\\"){return d.slice(1); -}return(a[c]!=null)?a[c]:"";});}});Number.implement({limit:function(b,a){return Math.min(a,Math.max(b,this));},round:function(a){a=Math.pow(10,a||0).toFixed(a<0?-a:0); -return Math.round(this*a)/a;},times:function(b,c){for(var a=0;a1?Array.slice(arguments,1):null,d=function(){};var c=function(){var g=e,h=arguments.length;if(this instanceof c){d.prototype=a.prototype; -g=new d;}var f=(!b&&!h)?a.call(g):a.apply(g,b&&h?b.concat(Array.slice(arguments)):b||arguments);return g==e?f:g;};return c;},pass:function(b,c){var a=this; -if(b!=null){b=Array.from(b);}return function(){return a.apply(c,b||arguments);};},delay:function(b,c,a){return setTimeout(this.pass((a==null?[]:a),c),b); -},periodical:function(c,b,a){return setInterval(this.pass((a==null?[]:a),b),c);}});delete Function.prototype.bind;Function.implement({create:function(b){var a=this; -b=b||{};return function(d){var c=b.arguments;c=(c!=null)?Array.from(c):Array.slice(arguments,(b.event)?1:0);if(b.event){c=[d||window.event].extend(c);}var e=function(){return a.apply(b.bind||null,c); -};if(b.delay){return setTimeout(e,b.delay);}if(b.periodical){return setInterval(e,b.periodical);}if(b.attempt){return Function.attempt(e);}return e();}; -},bind:function(c,b){var a=this;if(b!=null){b=Array.from(b);}return function(){return a.apply(c,b||arguments);};},bindWithEvent:function(c,b){var a=this; -if(b!=null){b=Array.from(b);}return function(d){return a.apply(c,(b==null)?arguments:[d].concat(b));};},run:function(a,b){return this.apply(b,Array.from(a)); -}});if(Object.create==Function.prototype.create){Object.create=null;}var $try=Function.attempt;(function(){var a=Object.prototype.hasOwnProperty;Object.extend({subset:function(d,g){var f={}; -for(var e=0,b=g.length;e]*>([\s\S]*?)<\/script>/gi,function(r,s){e+=s+"\n"; -return"";});if(p===true){o.exec(e);}else{if(typeOf(p)=="function"){p(e,q);}}return q;});o.extend({Document:this.Document,Window:this.Window,Element:this.Element,Event:this.Event}); -this.Window=this.$constructor=new Type("Window",function(){});this.$family=Function.from("window").hide();Window.mirror(function(e,p){h[e]=p;});this.Document=k.$constructor=new Type("Document",function(){}); -k.$family=Function.from("document").hide();Document.mirror(function(e,p){k[e]=p;});k.html=k.documentElement;if(!k.head){k.head=k.getElementsByTagName("head")[0]; -}if(k.execCommand){try{k.execCommand("BackgroundImageCache",false,true);}catch(g){}}if(this.attachEvent&&!this.addEventListener){var c=function(){this.detachEvent("onunload",c); -k.head=k.html=k.window=null;};this.attachEvent("onunload",c);}var m=Array.from;try{m(k.html.childNodes);}catch(g){Array.from=function(p){if(typeof p!="string"&&Type.isEnumerable(p)&&typeOf(p)!="array"){var e=p.length,q=new Array(e); -while(e--){q[e]=p[e];}return q;}return m(p);};var l=Array.prototype,n=l.slice;["pop","push","reverse","shift","sort","splice","unshift","concat","join","slice"].each(function(e){var p=l[e]; -Array[e]=function(q){return p.apply(Array.from(q),n.call(arguments,1));};});}if(o.Platform.ios){o.Platform.ipod=true;}o.Engine={};var d=function(p,e){o.Engine.name=p; -o.Engine[p+e]=true;o.Engine.version=e;};if(o.ie){o.Engine.trident=true;switch(o.version){case 6:d("trident",4);break;case 7:d("trident",5);break;case 8:d("trident",6); -}}if(o.firefox){o.Engine.gecko=true;if(o.version>=3){d("gecko",19);}else{d("gecko",18);}}if(o.safari||o.chrome){o.Engine.webkit=true;switch(o.version){case 2:d("webkit",419); -break;case 3:d("webkit",420);break;case 4:d("webkit",525);}}if(o.opera){o.Engine.presto=true;if(o.version>=9.6){d("presto",960);}else{if(o.version>=9.5){d("presto",950); -}else{d("presto",925);}}}if(o.name=="unknown"){switch((a.match(/(?:webkit|khtml|gecko)/)||[])[0]){case"webkit":case"khtml":o.Engine.webkit=true;break;case"gecko":o.Engine.gecko=true; -}}this.$exec=o.exec;})();(function(){var b={};var a=this.DOMEvent=new Type("DOMEvent",function(c,g){if(!g){g=window;}c=c||g.event;if(c.$extended){return c; -}this.event=c;this.$extended=true;this.shift=c.shiftKey;this.control=c.ctrlKey;this.alt=c.altKey;this.meta=c.metaKey;var i=this.type=c.type;var h=c.target||c.srcElement; -while(h&&h.nodeType==3){h=h.parentNode;}this.target=document.id(h);if(i.indexOf("key")==0){var d=this.code=(c.which||c.keyCode);this.key=b[d]||Object.keyOf(Event.Keys,d); -if(i=="keydown"){if(d>111&&d<124){this.key="f"+(d-111);}else{if(d>95&&d<106){this.key=d-96;}}}if(this.key==null){this.key=String.fromCharCode(d).toLowerCase(); -}}else{if(i=="click"||i=="dblclick"||i=="contextmenu"||i=="DOMMouseScroll"||i.indexOf("mouse")==0){var j=g.document;j=(!j.compatMode||j.compatMode=="CSS1Compat")?j.html:j.body; -this.page={x:(c.pageX!=null)?c.pageX:c.clientX+j.scrollLeft,y:(c.pageY!=null)?c.pageY:c.clientY+j.scrollTop};this.client={x:(c.pageX!=null)?c.pageX-g.pageXOffset:c.clientX,y:(c.pageY!=null)?c.pageY-g.pageYOffset:c.clientY}; -if(i=="DOMMouseScroll"||i=="mousewheel"){this.wheel=(c.wheelDelta)?c.wheelDelta/120:-(c.detail||0)/3;}this.rightClick=(c.which==3||c.button==2);if(i=="mouseover"||i=="mouseout"){var k=c.relatedTarget||c[(i=="mouseover"?"from":"to")+"Element"]; -while(k&&k.nodeType==3){k=k.parentNode;}this.relatedTarget=document.id(k);}}else{if(i.indexOf("touch")==0||i.indexOf("gesture")==0){this.rotation=c.rotation; -this.scale=c.scale;this.targetTouches=c.targetTouches;this.changedTouches=c.changedTouches;var f=this.touches=c.touches;if(f&&f[0]){var e=f[0];this.page={x:e.pageX,y:e.pageY}; -this.client={x:e.clientX,y:e.clientY};}}}}if(!this.client){this.client={};}if(!this.page){this.page={};}});a.implement({stop:function(){return this.preventDefault().stopPropagation(); -},stopPropagation:function(){if(this.event.stopPropagation){this.event.stopPropagation();}else{this.event.cancelBubble=true;}return this;},preventDefault:function(){if(this.event.preventDefault){this.event.preventDefault(); -}else{this.event.returnValue=false;}return this;}});a.defineKey=function(d,c){b[d]=c;return this;};a.defineKeys=a.defineKey.overloadSetter(true);a.defineKeys({"38":"up","40":"down","37":"left","39":"right","27":"esc","32":"space","8":"backspace","9":"tab","46":"delete","13":"enter"}); -})();var Event=DOMEvent;Event.Keys={};Event.Keys=new Hash(Event.Keys);(function(){var a=this.Class=new Type("Class",function(h){if(instanceOf(h,Function)){h={initialize:h}; -}var g=function(){e(this);if(g.$prototyping){return this;}this.$caller=null;var i=(this.initialize)?this.initialize.apply(this,arguments):this;this.$caller=this.caller=null; -return i;}.extend(this).implement(h);g.$constructor=a;g.prototype.$constructor=g;g.prototype.parent=c;return g;});var c=function(){if(!this.$caller){throw new Error('The method "parent" cannot be called.'); -}var g=this.$caller.$name,h=this.$caller.$owner.parent,i=(h)?h.prototype[g]:null;if(!i){throw new Error('The method "'+g+'" has no parent.');}return i.apply(this,arguments); -};var e=function(g){for(var h in g){var j=g[h];switch(typeOf(j)){case"object":var i=function(){};i.prototype=j;g[h]=e(new i);break;case"array":g[h]=j.clone(); -break;}}return g;};var b=function(g,h,j){if(j.$origin){j=j.$origin;}var i=function(){if(j.$protected&&this.$caller==null){throw new Error('The method "'+h+'" cannot be called.'); -}var l=this.caller,m=this.$caller;this.caller=m;this.$caller=i;var k=j.apply(this,arguments);this.$caller=m;this.caller=l;return k;}.extend({$owner:g,$origin:j,$name:h}); -return i;};var f=function(h,i,g){if(a.Mutators.hasOwnProperty(h)){i=a.Mutators[h].call(this,i);if(i==null){return this;}}if(typeOf(i)=="function"){if(i.$hidden){return this; -}this.prototype[h]=(g)?i:b(this,h,i);}else{Object.merge(this.prototype,h,i);}return this;};var d=function(g){g.$prototyping=true;var h=new g;delete g.$prototyping; -return h;};a.implement("implement",f.overloadSetter());a.Mutators={Extends:function(g){this.parent=g;this.prototype=d(g);},Implements:function(g){Array.from(g).each(function(j){var h=new j; -for(var i in h){f.call(this,i,h[i],true);}},this);}};})();(function(){this.Chain=new Class({$chain:[],chain:function(){this.$chain.append(Array.flatten(arguments)); -return this;},callChain:function(){return(this.$chain.length)?this.$chain.shift().apply(this,arguments):false;},clearChain:function(){this.$chain.empty(); -return this;}});var a=function(b){return b.replace(/^on([A-Z])/,function(c,d){return d.toLowerCase();});};this.Events=new Class({$events:{},addEvent:function(d,c,b){d=a(d); -if(c==$empty){return this;}this.$events[d]=(this.$events[d]||[]).include(c);if(b){c.internal=true;}return this;},addEvents:function(b){for(var c in b){this.addEvent(c,b[c]); -}return this;},fireEvent:function(e,c,b){e=a(e);var d=this.$events[e];if(!d){return this;}c=Array.from(c);d.each(function(f){if(b){f.delay(b,this,c);}else{f.apply(this,c); -}},this);return this;},removeEvent:function(e,d){e=a(e);var c=this.$events[e];if(c&&!d.internal){var b=c.indexOf(d);if(b!=-1){delete c[b];}}return this; -},removeEvents:function(d){var e;if(typeOf(d)=="object"){for(e in d){this.removeEvent(e,d[e]);}return this;}if(d){d=a(d);}for(e in this.$events){if(d&&d!=e){continue; -}var c=this.$events[e];for(var b=c.length;b--;){if(b in c){this.removeEvent(e,c[b]);}}}return this;}});this.Options=new Class({setOptions:function(){var b=this.options=Object.merge.apply(null,[{},this.options].append(arguments)); -if(this.addEvent){for(var c in b){if(typeOf(b[c])!="function"||!(/^on[A-Z]/).test(c)){continue;}this.addEvent(c,b[c]);delete b[c];}}return this;}});})(); -(function(){var k,n,l,g,a={},c={},m=/\\/g;var e=function(q,p){if(q==null){return null;}if(q.Slick===true){return q;}q=(""+q).replace(/^\s+|\s+$/g,"");g=!!p; -var o=(g)?c:a;if(o[q]){return o[q];}k={Slick:true,expressions:[],raw:q,reverse:function(){return e(this.raw,true);}};n=-1;while(q!=(q=q.replace(j,b))){}k.length=k.expressions.length; -return o[k.raw]=(g)?h(k):k;};var i=function(o){if(o==="!"){return" ";}else{if(o===" "){return"!";}else{if((/^!/).test(o)){return o.replace(/^!/,"");}else{return"!"+o; -}}}};var h=function(u){var r=u.expressions;for(var p=0;p+)\\s*|(\\s+)|(+|\\*)|\\#(+)|\\.(+)|\\[\\s*(+)(?:\\s*([*^$!~|]?=)(?:\\s*(?:([\"']?)(.*?)\\9)))?\\s*\\](?!\\])|(:+)(+)(?:\\((?:(?:([\"'])([^\\13]*)\\13)|((?:\\([^)]+\\)|[^()]*)+))\\))?)".replace(//,"["+f(">+~`!@$%^&={}\\;/g,"(?:[\\w\\u00a1-\\uFFFF-]|\\\\[^\\s0-9a-f])").replace(//g,"(?:[:\\w\\u00a1-\\uFFFF-]|\\\\[^\\s0-9a-f])")); -function b(x,s,D,z,r,C,q,B,A,y,u,F,G,v,p,w){if(s||n===-1){k.expressions[++n]=[];l=-1;if(s){return"";}}if(D||z||l===-1){D=D||" ";var t=k.expressions[n]; -if(g&&t[l]){t[l].reverseCombinator=i(D);}t[++l]={combinator:D,tag:"*"};}var o=k.expressions[n][l];if(r){o.tag=r.replace(m,"");}else{if(C){o.id=C.replace(m,""); -}else{if(q){q=q.replace(m,"");if(!o.classList){o.classList=[];}if(!o.classes){o.classes=[];}o.classList.push(q);o.classes.push({value:q,regexp:new RegExp("(^|\\s)"+f(q)+"(\\s|$)")}); -}else{if(G){w=w||p;w=w?w.replace(m,""):null;if(!o.pseudos){o.pseudos=[];}o.pseudos.push({key:G.replace(m,""),value:w,type:F.length==1?"class":"element"}); -}else{if(B){B=B.replace(m,"");u=(u||"").replace(m,"");var E,H;switch(A){case"^=":H=new RegExp("^"+f(u));break;case"$=":H=new RegExp(f(u)+"$");break;case"~=":H=new RegExp("(^|\\s)"+f(u)+"(\\s|$)"); -break;case"|=":H=new RegExp("^"+f(u)+"(-|$)");break;case"=":E=function(I){return u==I;};break;case"*=":E=function(I){return I&&I.indexOf(u)>-1;};break; -case"!=":E=function(I){return u!=I;};break;default:E=function(I){return !!I;};}if(u==""&&(/^[*$^]=$/).test(A)){E=function(){return false;};}if(!E){E=function(I){return I&&H.test(I); -};}if(!o.attributes){o.attributes=[];}o.attributes.push({key:B,operator:A,value:u,test:E});}}}}}return"";}var d=(this.Slick||{});d.parse=function(o){return e(o); -};d.escapeRegExp=f;if(!this.Slick){this.Slick=d;}}).apply((typeof exports!="undefined")?exports:this);(function(){var k={},m={},d=Object.prototype.toString; -k.isNativeCode=function(c){return(/\{\s*\[native code\]\s*\}/).test(""+c);};k.isXML=function(c){return(!!c.xmlVersion)||(!!c.xml)||(d.call(c)=="[object XMLDocument]")||(c.nodeType==9&&c.documentElement.nodeName!="HTML"); -};k.setDocument=function(w){var p=w.nodeType;if(p==9){}else{if(p){w=w.ownerDocument;}else{if(w.navigator){w=w.document;}else{return;}}}if(this.document===w){return; -}this.document=w;var A=w.documentElement,o=this.getUIDXML(A),s=m[o],r;if(s){for(r in s){this[r]=s[r];}return;}s=m[o]={};s.root=A;s.isXMLDocument=this.isXML(w); -s.brokenStarGEBTN=s.starSelectsClosedQSA=s.idGetsName=s.brokenMixedCaseQSA=s.brokenGEBCN=s.brokenCheckedQSA=s.brokenEmptyAttributeQSA=s.isHTMLDocument=s.nativeMatchesSelector=false; -var q,u,y,z,t;var x,v="slick_uniqueid";var c=w.createElement("div");var n=w.body||w.getElementsByTagName("body")[0]||A;n.appendChild(c);try{c.innerHTML=''; -s.isHTMLDocument=!!w.getElementById(v);}catch(C){}if(s.isHTMLDocument){c.style.display="none";c.appendChild(w.createComment(""));u=(c.getElementsByTagName("*").length>1); -try{c.innerHTML="foo";x=c.getElementsByTagName("*");q=(x&&!!x.length&&x[0].nodeName.charAt(0)=="/");}catch(C){}s.brokenStarGEBTN=u||q;try{c.innerHTML=''; -s.idGetsName=w.getElementById(v)===c.firstChild;}catch(C){}if(c.getElementsByClassName){try{c.innerHTML='';c.getElementsByClassName("b").length; -c.firstChild.className="b";z=(c.getElementsByClassName("b").length!=2);}catch(C){}try{c.innerHTML='';y=(c.getElementsByClassName("a").length!=2); -}catch(C){}s.brokenGEBCN=z||y;}if(c.querySelectorAll){try{c.innerHTML="foo";x=c.querySelectorAll("*");s.starSelectsClosedQSA=(x&&!!x.length&&x[0].nodeName.charAt(0)=="/"); -}catch(C){}try{c.innerHTML='';s.brokenMixedCaseQSA=!c.querySelectorAll(".MiX").length;}catch(C){}try{c.innerHTML=''; -s.brokenCheckedQSA=(c.querySelectorAll(":checked").length==0);}catch(C){}try{c.innerHTML='';s.brokenEmptyAttributeQSA=(c.querySelectorAll('[class*=""]').length!=0); -}catch(C){}}try{c.innerHTML='
';t=(c.firstChild.getAttribute("action")!="s");}catch(C){}s.nativeMatchesSelector=A.matchesSelector||A.mozMatchesSelector||A.webkitMatchesSelector; -if(s.nativeMatchesSelector){try{s.nativeMatchesSelector.call(A,":slick");s.nativeMatchesSelector=null;}catch(C){}}}try{A.slick_expando=1;delete A.slick_expando; -s.getUID=this.getUIDHTML;}catch(C){s.getUID=this.getUIDXML;}n.removeChild(c);c=x=n=null;s.getAttribute=(s.isHTMLDocument&&t)?function(G,E){var H=this.attributeGetters[E]; -if(H){return H.call(G);}var F=G.getAttributeNode(E);return(F)?F.nodeValue:null;}:function(F,E){var G=this.attributeGetters[E];return(G)?G.call(F):F.getAttribute(E); -};s.hasAttribute=(A&&this.isNativeCode(A.hasAttribute))?function(F,E){return F.hasAttribute(E);}:function(F,E){F=F.getAttributeNode(E);return !!(F&&(F.specified||F.nodeValue)); -};var D=A&&this.isNativeCode(A.contains),B=w&&this.isNativeCode(w.contains);s.contains=(D&&B)?function(E,F){return E.contains(F);}:(D&&!B)?function(E,F){return E===F||((E===w)?w.documentElement:E).contains(F); -}:(A&&A.compareDocumentPosition)?function(E,F){return E===F||!!(E.compareDocumentPosition(F)&16);}:function(E,F){if(F){do{if(F===E){return true;}}while((F=F.parentNode)); -}return false;};s.documentSorter=(A.compareDocumentPosition)?function(F,E){if(!F.compareDocumentPosition||!E.compareDocumentPosition){return 0;}return F.compareDocumentPosition(E)&4?-1:F===E?0:1; -}:("sourceIndex" in A)?function(F,E){if(!F.sourceIndex||!E.sourceIndex){return 0;}return F.sourceIndex-E.sourceIndex;}:(w.createRange)?function(H,F){if(!H.ownerDocument||!F.ownerDocument){return 0; -}var G=H.ownerDocument.createRange(),E=F.ownerDocument.createRange();G.setStart(H,0);G.setEnd(H,0);E.setStart(F,0);E.setEnd(F,0);return G.compareBoundaryPoints(Range.START_TO_END,E); -}:null;A=null;for(r in s){this[r]=s[r];}};var f=/^([#.]?)((?:[\w-]+|\*))$/,h=/\[.+[*$^]=(?:""|'')?\]/,g={};k.search=function(U,z,H,s){var p=this.found=(s)?null:(H||[]); -if(!U){return p;}else{if(U.navigator){U=U.document;}else{if(!U.nodeType){return p;}}}var F,O,V=this.uniques={},I=!!(H&&H.length),y=(U.nodeType==9);if(this.document!==(y?U:U.ownerDocument)){this.setDocument(U); -}if(I){for(O=p.length;O--;){V[this.getUID(p[O])]=true;}}if(typeof z=="string"){var r=z.match(f);simpleSelectors:if(r){var u=r[1],v=r[2],A,E;if(!u){if(v=="*"&&this.brokenStarGEBTN){break simpleSelectors; -}E=U.getElementsByTagName(v);if(s){return E[0]||null;}for(O=0;A=E[O++];){if(!(I&&V[this.getUID(A)])){p.push(A);}}}else{if(u=="#"){if(!this.isHTMLDocument||!y){break simpleSelectors; -}A=U.getElementById(v);if(!A){return p;}if(this.idGetsName&&A.getAttributeNode("id").nodeValue!=v){break simpleSelectors;}if(s){return A||null;}if(!(I&&V[this.getUID(A)])){p.push(A); -}}else{if(u=="."){if(!this.isHTMLDocument||((!U.getElementsByClassName||this.brokenGEBCN)&&U.querySelectorAll)){break simpleSelectors;}if(U.getElementsByClassName&&!this.brokenGEBCN){E=U.getElementsByClassName(v); -if(s){return E[0]||null;}for(O=0;A=E[O++];){if(!(I&&V[this.getUID(A)])){p.push(A);}}}else{var T=new RegExp("(^|\\s)"+e.escapeRegExp(v)+"(\\s|$)");E=U.getElementsByTagName("*"); -for(O=0;A=E[O++];){className=A.className;if(!(className&&T.test(className))){continue;}if(s){return A;}if(!(I&&V[this.getUID(A)])){p.push(A);}}}}}}if(I){this.sort(p); -}return(s)?null:p;}querySelector:if(U.querySelectorAll){if(!this.isHTMLDocument||g[z]||this.brokenMixedCaseQSA||(this.brokenCheckedQSA&&z.indexOf(":checked")>-1)||(this.brokenEmptyAttributeQSA&&h.test(z))||(!y&&z.indexOf(",")>-1)||e.disableQSA){break querySelector; -}var S=z,x=U;if(!y){var C=x.getAttribute("id"),t="slickid__";x.setAttribute("id",t);S="#"+t+" "+S;U=x.parentNode;}try{if(s){return U.querySelector(S)||null; -}else{E=U.querySelectorAll(S);}}catch(Q){g[z]=1;break querySelector;}finally{if(!y){if(C){x.setAttribute("id",C);}else{x.removeAttribute("id");}U=x;}}if(this.starSelectsClosedQSA){for(O=0; -A=E[O++];){if(A.nodeName>"@"&&!(I&&V[this.getUID(A)])){p.push(A);}}}else{for(O=0;A=E[O++];){if(!(I&&V[this.getUID(A)])){p.push(A);}}}if(I){this.sort(p); -}return p;}F=this.Slick.parse(z);if(!F.length){return p;}}else{if(z==null){return p;}else{if(z.Slick){F=z;}else{if(this.contains(U.documentElement||U,z)){(p)?p.push(z):p=z; -return p;}else{return p;}}}}this.posNTH={};this.posNTHLast={};this.posNTHType={};this.posNTHTypeLast={};this.push=(!I&&(s||(F.length==1&&F.expressions[0].length==1)))?this.pushArray:this.pushUID; -if(p==null){p=[];}var M,L,K;var B,J,D,c,q,G,W;var N,P,o,w,R=F.expressions;search:for(O=0;(P=R[O]);O++){for(M=0;(o=P[M]);M++){B="combinator:"+o.combinator; -if(!this[B]){continue search;}J=(this.isXMLDocument)?o.tag:o.tag.toUpperCase();D=o.id;c=o.classList;q=o.classes;G=o.attributes;W=o.pseudos;w=(M===(P.length-1)); -this.bitUniques={};if(w){this.uniques=V;this.found=p;}else{this.uniques={};this.found=[];}if(M===0){this[B](U,J,D,q,G,W,c);if(s&&w&&p.length){break search; -}}else{if(s&&w){for(L=0,K=N.length;L1)){this.sort(p);}return(s)?(p[0]||null):p;};k.uidx=1;k.uidk="slick-uniqueid";k.getUIDXML=function(n){var c=n.getAttribute(this.uidk); -if(!c){c=this.uidx++;n.setAttribute(this.uidk,c);}return c;};k.getUIDHTML=function(c){return c.uniqueNumber||(c.uniqueNumber=this.uidx++);};k.sort=function(c){if(!this.documentSorter){return c; -}c.sort(this.documentSorter);return c;};k.cacheNTH={};k.matchNTH=/^([+-]?\d*)?([a-z]+)?([+-]\d+)?$/;k.parseNTHArgument=function(q){var o=q.match(this.matchNTH); -if(!o){return false;}var p=o[2]||false;var n=o[1]||1;if(n=="-"){n=-1;}var c=+o[3]||0;o=(p=="n")?{a:n,b:c}:(p=="odd")?{a:2,b:1}:(p=="even")?{a:2,b:0}:{a:0,b:n}; -return(this.cacheNTH[q]=o);};k.createNTHPseudo=function(p,n,c,o){return function(s,q){var u=this.getUID(s);if(!this[c][u]){var A=s.parentNode;if(!A){return false; -}var r=A[p],t=1;if(o){var z=s.nodeName;do{if(r.nodeName!=z){continue;}this[c][this.getUID(r)]=t++;}while((r=r[n]));}else{do{if(r.nodeType!=1){continue; -}this[c][this.getUID(r)]=t++;}while((r=r[n]));}}q=q||"n";var v=this.cacheNTH[q]||this.parseNTHArgument(q);if(!v){return false;}var y=v.a,x=v.b,w=this[c][u]; -if(y==0){return x==w;}if(y>0){if(w":function(p,c,r,o,n,q){if((p=p.firstChild)){do{if(p.nodeType==1){this.push(p,c,r,o,n,q); -}}while((p=p.nextSibling));}},"+":function(p,c,r,o,n,q){while((p=p.nextSibling)){if(p.nodeType==1){this.push(p,c,r,o,n,q);break;}}},"^":function(p,c,r,o,n,q){p=p.firstChild; -if(p){if(p.nodeType==1){this.push(p,c,r,o,n,q);}else{this["combinator:+"](p,c,r,o,n,q);}}},"~":function(q,c,s,p,n,r){while((q=q.nextSibling)){if(q.nodeType!=1){continue; -}var o=this.getUID(q);if(this.bitUniques[o]){break;}this.bitUniques[o]=true;this.push(q,c,s,p,n,r);}},"++":function(p,c,r,o,n,q){this["combinator:+"](p,c,r,o,n,q); -this["combinator:!+"](p,c,r,o,n,q);},"~~":function(p,c,r,o,n,q){this["combinator:~"](p,c,r,o,n,q);this["combinator:!~"](p,c,r,o,n,q);},"!":function(p,c,r,o,n,q){while((p=p.parentNode)){if(p!==this.document){this.push(p,c,r,o,n,q); -}}},"!>":function(p,c,r,o,n,q){p=p.parentNode;if(p!==this.document){this.push(p,c,r,o,n,q);}},"!+":function(p,c,r,o,n,q){while((p=p.previousSibling)){if(p.nodeType==1){this.push(p,c,r,o,n,q); -break;}}},"!^":function(p,c,r,o,n,q){p=p.lastChild;if(p){if(p.nodeType==1){this.push(p,c,r,o,n,q);}else{this["combinator:!+"](p,c,r,o,n,q);}}},"!~":function(q,c,s,p,n,r){while((q=q.previousSibling)){if(q.nodeType!=1){continue; -}var o=this.getUID(q);if(this.bitUniques[o]){break;}this.bitUniques[o]=true;this.push(q,c,s,p,n,r);}}};for(var i in j){k["combinator:"+i]=j[i];}var l={empty:function(c){var n=c.firstChild; -return !(n&&n.nodeType==1)&&!(c.innerText||c.textContent||"").length;},not:function(c,n){return !this.matchNode(c,n);},contains:function(c,n){return(c.innerText||c.textContent||"").indexOf(n)>-1; -},"first-child":function(c){while((c=c.previousSibling)){if(c.nodeType==1){return false;}}return true;},"last-child":function(c){while((c=c.nextSibling)){if(c.nodeType==1){return false; -}}return true;},"only-child":function(o){var n=o;while((n=n.previousSibling)){if(n.nodeType==1){return false;}}var c=o;while((c=c.nextSibling)){if(c.nodeType==1){return false; -}}return true;},"nth-child":k.createNTHPseudo("firstChild","nextSibling","posNTH"),"nth-last-child":k.createNTHPseudo("lastChild","previousSibling","posNTHLast"),"nth-of-type":k.createNTHPseudo("firstChild","nextSibling","posNTHType",true),"nth-last-of-type":k.createNTHPseudo("lastChild","previousSibling","posNTHTypeLast",true),index:function(n,c){return this["pseudo:nth-child"](n,""+(c+1)); -},even:function(c){return this["pseudo:nth-child"](c,"2n");},odd:function(c){return this["pseudo:nth-child"](c,"2n+1");},"first-of-type":function(c){var n=c.nodeName; -while((c=c.previousSibling)){if(c.nodeName==n){return false;}}return true;},"last-of-type":function(c){var n=c.nodeName;while((c=c.nextSibling)){if(c.nodeName==n){return false; -}}return true;},"only-of-type":function(o){var n=o,p=o.nodeName;while((n=n.previousSibling)){if(n.nodeName==p){return false;}}var c=o;while((c=c.nextSibling)){if(c.nodeName==p){return false; -}}return true;},enabled:function(c){return !c.disabled;},disabled:function(c){return c.disabled;},checked:function(c){return c.checked||c.selected;},focus:function(c){return this.isHTMLDocument&&this.document.activeElement===c&&(c.href||c.type||this.hasAttribute(c,"tabindex")); -},root:function(c){return(c===this.root);},selected:function(c){return c.selected;}};for(var b in l){k["pseudo:"+b]=l[b];}var a=k.attributeGetters={"for":function(){return("htmlFor" in this)?this.htmlFor:this.getAttribute("for"); -},href:function(){return("href" in this)?this.getAttribute("href",2):this.getAttribute("href");},style:function(){return(this.style)?this.style.cssText:this.getAttribute("style"); -},tabindex:function(){var c=this.getAttributeNode("tabindex");return(c&&c.specified)?c.nodeValue:null;},type:function(){return this.getAttribute("type"); -},maxlength:function(){var c=this.getAttributeNode("maxLength");return(c&&c.specified)?c.nodeValue:null;}};a.MAXLENGTH=a.maxLength=a.maxlength;var e=k.Slick=(this.Slick||{}); -e.version="1.1.7";e.search=function(n,o,c){return k.search(n,o,c);};e.find=function(c,n){return k.search(c,n,null,true);};e.contains=function(c,n){k.setDocument(c); -return k.contains(c,n);};e.getAttribute=function(n,c){k.setDocument(n);return k.getAttribute(n,c);};e.hasAttribute=function(n,c){k.setDocument(n);return k.hasAttribute(n,c); -};e.match=function(n,c){if(!(n&&c)){return false;}if(!c||c===n){return true;}k.setDocument(n);return k.matchNode(n,c);};e.defineAttributeGetter=function(c,n){k.attributeGetters[c]=n; -return this;};e.lookupAttributeGetter=function(c){return k.attributeGetters[c];};e.definePseudo=function(c,n){k["pseudo:"+c]=function(p,o){return n.call(p,o); -};return this;};e.lookupPseudo=function(c){var n=k["pseudo:"+c];if(n){return function(o){return n.call(this,o);};}return null;};e.override=function(n,c){k.override(n,c); -return this;};e.isXML=k.isXML;e.uidOf=function(c){return k.getUIDHTML(c);};if(!this.Slick){this.Slick=e;}}).apply((typeof exports!="undefined")?exports:this); -var Element=function(b,g){var h=Element.Constructors[b];if(h){return h(g);}if(typeof b!="string"){return document.id(b).set(g);}if(!g){g={};}if(!(/^[\w-]+$/).test(b)){var e=Slick.parse(b).expressions[0][0]; -b=(e.tag=="*")?"div":e.tag;if(e.id&&g.id==null){g.id=e.id;}var d=e.attributes;if(d){for(var a,f=0,c=d.length;f=this.length){delete this[g--];}return e;}.protect());}Array.forEachMethod(function(g,e){Elements.implement(e,g);});Array.mirror(Elements);var d; -try{d=(document.createElement("").name=="x");}catch(b){}var c=function(e){return(""+e).replace(/&/g,"&").replace(/"/g,""");};Document.implement({newElement:function(e,g){if(g&&g.checked!=null){g.defaultChecked=g.checked; -}if(d&&g){e="<"+e;if(g.name){e+=' name="'+c(g.name)+'"';}if(g.type){e+=' type="'+c(g.type)+'"';}e+=">";delete g.name;delete g.type;}return this.id(this.createElement(e)).set(g); -}});})();(function(){Slick.uidOf(window);Slick.uidOf(document);Document.implement({newTextNode:function(e){return this.createTextNode(e);},getDocument:function(){return this; -},getWindow:function(){return this.window;},id:(function(){var e={string:function(E,D,l){E=Slick.find(l,"#"+E.replace(/(\W)/g,"\\$1"));return(E)?e.element(E,D):null; -},element:function(D,E){Slick.uidOf(D);if(!E&&!D.$family&&!(/^(?:object|embed)$/i).test(D.tagName)){var l=D.fireEvent;D._fireEvent=function(F,G){return l(F,G); -};Object.append(D,Element.Prototype);}return D;},object:function(D,E,l){if(D.toElement){return e.element(D.toElement(l),E);}return null;}};e.textnode=e.whitespace=e.window=e.document=function(l){return l; -};return function(D,F,E){if(D&&D.$family&&D.uniqueNumber){return D;}var l=typeOf(D);return(e[l])?e[l](D,F,E||document):null;};})()});if(window.$==null){Window.implement("$",function(e,l){return document.id(e,l,this.document); -});}Window.implement({getDocument:function(){return this.document;},getWindow:function(){return this;}});[Document,Element].invoke("implement",{getElements:function(e){return Slick.search(this,e,new Elements); -},getElement:function(e){return document.id(Slick.find(this,e));}});var m={contains:function(e){return Slick.contains(this,e);}};if(!document.contains){Document.implement(m); -}if(!document.createElement("div").contains){Element.implement(m);}Element.implement("hasChild",function(e){return this!==e&&this.contains(e);});(function(l,E,e){this.Selectors={}; -var F=this.Selectors.Pseudo=new Hash();var D=function(){for(var G in F){if(F.hasOwnProperty(G)){Slick.definePseudo(G,F[G]);delete F[G];}}};Slick.search=function(H,I,G){D(); -return l.call(this,H,I,G);};Slick.find=function(G,H){D();return E.call(this,G,H);};Slick.match=function(H,G){D();return e.call(this,H,G);};})(Slick.search,Slick.find,Slick.match); -var r=function(E,D){if(!E){return D;}E=Object.clone(Slick.parse(E));var l=E.expressions;for(var e=l.length;e--;){l[e][0].combinator=D;}return E;};Object.forEach({getNext:"~",getPrevious:"!~",getParent:"!"},function(e,l){Element.implement(l,function(D){return this.getElement(r(D,e)); -});});Object.forEach({getAllNext:"~",getAllPrevious:"!~",getSiblings:"~~",getChildren:">",getParents:"!"},function(e,l){Element.implement(l,function(D){return this.getElements(r(D,e)); -});});Element.implement({getFirst:function(e){return document.id(Slick.search(this,r(e,">"))[0]);},getLast:function(e){return document.id(Slick.search(this,r(e,">")).getLast()); -},getWindow:function(){return this.ownerDocument.window;},getDocument:function(){return this.ownerDocument;},getElementById:function(e){return document.id(Slick.find(this,"#"+(""+e).replace(/(\W)/g,"\\$1"))); -},match:function(e){return !e||Slick.match(this,e);}});if(window.$$==null){Window.implement("$$",function(e){var H=new Elements;if(arguments.length==1&&typeof e=="string"){return Slick.search(this.document,e,H); -}var E=Array.flatten(arguments);for(var F=0,D=E.length;F(?![^<]*<['"])/)).indexOf(F)<0){return null;}E[F]=true;}}var e=Slick.getAttribute(this,F); -return(!e&&!Slick.hasAttribute(this,F))?null:e;},getProperties:function(){var e=Array.from(arguments);return e.map(this.getProperty,this).associate(e); -},removeProperty:function(e){return this.setProperty(e,null);},removeProperties:function(){Array.each(arguments,this.removeProperty,this);return this;},set:function(D,l){var e=Element.Properties[D]; -(e&&e.set)?e.set.call(this,l):this.setProperty(D,l);}.overloadSetter(),get:function(l){var e=Element.Properties[l];return(e&&e.get)?e.get.apply(this):this.getProperty(l); -}.overloadGetter(),erase:function(l){var e=Element.Properties[l];(e&&e.erase)?e.erase.apply(this):this.removeProperty(l);return this;},hasClass:function(e){return this.className.clean().contains(e," "); -},addClass:function(e){if(!this.hasClass(e)){this.className=(this.className+" "+e).clean();}return this;},removeClass:function(e){this.className=this.className.replace(new RegExp("(^|\\s)"+e+"(?:\\s|$)"),"$1"); -return this;},toggleClass:function(e,l){if(l==null){l=!this.hasClass(e);}return(l)?this.addClass(e):this.removeClass(e);},adopt:function(){var E=this,e,G=Array.flatten(arguments),F=G.length; -if(F>1){E=e=document.createDocumentFragment();}for(var D=0;D";var a=(t.childNodes.length==1);if(!a){var s="abbr article aside audio canvas datalist details figcaption figure footer header hgroup mark meter nav output progress section summary time video".split(" "),b=document.createDocumentFragment(),u=s.length; -while(u--){b.createElement(s[u]);}}t=null;var g=Function.attempt(function(){var e=document.createElement("table");e.innerHTML="";return true; -});var c=document.createElement("tr"),o="";c.innerHTML=o;var y=(c.innerHTML==o);c=null;if(!g||!y||!a){Element.Properties.html.set=(function(l){var e={table:[1,"","
"],select:[1,""],tbody:[2,"","
"],tr:[3,"","
"]}; -e.thead=e.tfoot=e.tbody;return function(D){var E=e[this.get("tag")];if(!E&&!a){E=[0,"",""];}if(!E){return l.call(this,D);}var H=E[0],G=document.createElement("div"),F=G; -if(!a){b.appendChild(G);}G.innerHTML=[E[1],D,E[2]].flatten().join("");while(H--){F=F.firstChild;}this.empty().adopt(F.childNodes);if(!a){b.removeChild(G); -}G=null;};})(Element.Properties.html.set);}var n=document.createElement("form");n.innerHTML="";if(n.firstChild.value!="s"){Element.Properties.value={set:function(G){var l=this.get("tag"); -if(l!="select"){return this.setProperty("value",G);}var D=this.getElements("option");for(var E=0;E0||k==null?"visible":"hidden";};var f=(h?function(l,k){l.style.opacity=k;}:(e?function(l,k){var n=l.style; -if(!l.currentStyle||!l.currentStyle.hasLayout){n.zoom=1;}if(k==null||k==1){k="";}else{k="alpha(opacity="+(k*100).limit(0,100).round()+")";}var m=n.filter||l.getComputedStyle("filter")||""; -n.filter=j.test(m)?m.replace(j,k):m+k;if(!n.filter){n.removeAttribute("filter");}}:a));var g=(h?function(l){var k=l.style.opacity||l.getComputedStyle("opacity"); -return(k=="")?1:k.toFloat();}:(e?function(l){var m=(l.style.filter||l.getComputedStyle("filter")),k;if(m){k=m.match(j);}return(k==null||m==null)?1:(k[1]/100); -}:function(l){var k=l.retrieve("$opacity");if(k==null){k=(l.style.visibility=="hidden"?0:1);}return k;}));var b=(i.style.cssFloat==null)?"styleFloat":"cssFloat"; -Element.implement({getComputedStyle:function(m){if(this.currentStyle){return this.currentStyle[m.camelCase()];}var l=Element.getDocument(this).defaultView,k=l?l.getComputedStyle(this,null):null; -return(k)?k.getPropertyValue((m==b)?"float":m.hyphenate()):null;},setStyle:function(l,k){if(l=="opacity"){if(k!=null){k=parseFloat(k);}f(this,k);return this; -}l=(l=="float"?b:l).camelCase();if(typeOf(k)!="string"){var m=(Element.Styles[l]||"@").split(" ");k=Array.from(k).map(function(o,n){if(!m[n]){return""; -}return(typeOf(o)=="number")?m[n].replace("@",Math.round(o)):o;}).join(" ");}else{if(k==String(Number(k))){k=Math.round(k);}}this.style[l]=k;if((k==""||k==null)&&c&&this.style.removeAttribute){this.style.removeAttribute(l); -}return this;},getStyle:function(q){if(q=="opacity"){return g(this);}q=(q=="float"?b:q).camelCase();var k=this.style[q];if(!k||q=="zIndex"){k=[];for(var p in Element.ShortStyles){if(q!=p){continue; -}for(var o in Element.ShortStyles[p]){k.push(this.getStyle(o));}return k.join(" ");}k=this.getComputedStyle(q);}if(k){k=String(k);var m=k.match(/rgba?\([\d\s,]+\)/); -if(m){k=k.replace(m[0],m[0].rgbToHex());}}if(Browser.opera||Browser.ie){if((/^(height|width)$/).test(q)&&!(/px$/.test(k))){var l=(q=="width")?["left","right"]:["top","bottom"],n=0; -l.each(function(r){n+=this.getStyle("border-"+r+"-width").toInt()+this.getStyle("padding-"+r).toInt();},this);return this["offset"+q.capitalize()]-n+"px"; -}if(Browser.ie&&(/^border(.+)Width|margin|padding/).test(q)&&isNaN(parseFloat(k))){return"0px";}}return k;},setStyles:function(l){for(var k in l){this.setStyle(k,l[k]); -}return this;},getStyles:function(){var k={};Array.flatten(arguments).each(function(l){k[l]=this.getStyle(l);},this);return k;}});Element.Styles={left:"@px",top:"@px",bottom:"@px",right:"@px",width:"@px",height:"@px",maxWidth:"@px",maxHeight:"@px",minWidth:"@px",minHeight:"@px",backgroundColor:"rgb(@, @, @)",backgroundPosition:"@px @px",color:"rgb(@, @, @)",fontSize:"@px",letterSpacing:"@px",lineHeight:"@px",clip:"rect(@px @px @px @px)",margin:"@px @px @px @px",padding:"@px @px @px @px",border:"@px @ rgb(@, @, @) @px @ rgb(@, @, @) @px @ rgb(@, @, @)",borderWidth:"@px @px @px @px",borderStyle:"@ @ @ @",borderColor:"rgb(@, @, @) rgb(@, @, @) rgb(@, @, @) rgb(@, @, @)",zIndex:"@",zoom:"@",fontWeight:"@",textIndent:"@px",opacity:"@"}; -Element.implement({setOpacity:function(k){f(this,k);return this;},getOpacity:function(){return g(this);}});Element.Properties.opacity={set:function(k){f(this,k); -a(this,k);},get:function(){return g(this);}};Element.Styles=new Hash(Element.Styles);Element.ShortStyles={margin:{},padding:{},border:{},borderWidth:{},borderStyle:{},borderColor:{}}; -["Top","Right","Bottom","Left"].each(function(q){var p=Element.ShortStyles;var l=Element.Styles;["margin","padding"].each(function(r){var s=r+q;p[r][s]=l[s]="@px"; -});var o="border"+q;p.border[o]=l[o]="@px @ rgb(@, @, @)";var n=o+"Width",k=o+"Style",m=o+"Color";p[o]={};p.borderWidth[n]=p[o][n]=l[n]="@px";p.borderStyle[k]=p[o][k]=l[k]="@"; -p.borderColor[m]=p[o][m]=l[m]="rgb(@, @, @)";});})();(function(){Element.Properties.events={set:function(b){this.addEvents(b);}};[Element,Window,Document].invoke("implement",{addEvent:function(f,h){var i=this.retrieve("events",{}); -if(!i[f]){i[f]={keys:[],values:[]};}if(i[f].keys.contains(h)){return this;}i[f].keys.push(h);var g=f,b=Element.Events[f],d=h,j=this;if(b){if(b.onAdd){b.onAdd.call(this,h,f); -}if(b.condition){d=function(k){if(b.condition.call(this,k,f)){return h.call(this,k);}return true;};}if(b.base){g=Function.from(b.base).call(this,f);}}var e=function(){return h.call(j); -};var c=Element.NativeEvents[g];if(c){if(c==2){e=function(k){k=new DOMEvent(k,j.getWindow());if(d.call(j,k)===false){k.stop();}};}this.addListener(g,e,arguments[2]); -}i[f].values.push(e);return this;},removeEvent:function(e,d){var c=this.retrieve("events");if(!c||!c[e]){return this;}var h=c[e];var b=h.keys.indexOf(d); -if(b==-1){return this;}var g=h.values[b];delete h.keys[b];delete h.values[b];var f=Element.Events[e];if(f){if(f.onRemove){f.onRemove.call(this,d,e);}if(f.base){e=Function.from(f.base).call(this,e); -}}return(Element.NativeEvents[e])?this.removeListener(e,g,arguments[2]):this;},addEvents:function(b){for(var c in b){this.addEvent(c,b[c]);}return this; -},removeEvents:function(b){var d;if(typeOf(b)=="object"){for(d in b){this.removeEvent(d,b[d]);}return this;}var c=this.retrieve("events");if(!c){return this; -}if(!b){for(d in c){this.removeEvents(d);}this.eliminate("events");}else{if(c[b]){c[b].keys.each(function(e){this.removeEvent(b,e);},this);delete c[b]; -}}return this;},fireEvent:function(e,c,b){var d=this.retrieve("events");if(!d||!d[e]){return this;}c=Array.from(c);d[e].keys.each(function(f){if(b){f.delay(b,this,c); -}else{f.apply(this,c);}},this);return this;},cloneEvents:function(e,d){e=document.id(e);var c=e.retrieve("events");if(!c){return this;}if(!d){for(var b in c){this.cloneEvents(e,b); -}}else{if(c[d]){c[d].keys.each(function(f){this.addEvent(d,f);},this);}}return this;}});Element.NativeEvents={click:2,dblclick:2,mouseup:2,mousedown:2,contextmenu:2,mousewheel:2,DOMMouseScroll:2,mouseover:2,mouseout:2,mousemove:2,selectstart:2,selectend:2,keydown:2,keypress:2,keyup:2,orientationchange:2,touchstart:2,touchmove:2,touchend:2,touchcancel:2,gesturestart:2,gesturechange:2,gestureend:2,focus:2,blur:2,change:2,reset:2,select:2,submit:2,paste:2,input:2,load:2,unload:1,beforeunload:2,resize:1,move:1,DOMContentLoaded:1,readystatechange:1,error:1,abort:1,scroll:1}; -Element.Events={mousewheel:{base:(Browser.firefox)?"DOMMouseScroll":"mousewheel"}};if("onmouseenter" in document.documentElement){Element.NativeEvents.mouseenter=Element.NativeEvents.mouseleave=2; -}else{var a=function(b){var c=b.relatedTarget;if(c==null){return true;}if(!c){return false;}return(c!=this&&c.prefix!="xul"&&typeOf(this)!="document"&&!this.contains(c)); -};Element.Events.mouseenter={base:"mouseover",condition:a};Element.Events.mouseleave={base:"mouseout",condition:a};}if(!window.addEventListener){Element.NativeEvents.propertychange=2; -Element.Events.change={base:function(){var b=this.type;return(this.get("tag")=="input"&&(b=="radio"||b=="checkbox"))?"propertychange":"change";},condition:function(b){return this.type!="radio"||(b.event.propertyName=="checked"&&this.checked); -}};}Element.Events=new Hash(Element.Events);})();(function(){var c=!!window.addEventListener;Element.NativeEvents.focusin=Element.NativeEvents.focusout=2; -var k=function(l,m,n,o,p){while(p&&p!=l){if(m(p,o)){return n.call(p,o,p);}p=document.id(p.parentNode);}};var a={mouseenter:{base:"mouseover"},mouseleave:{base:"mouseout"},focus:{base:"focus"+(c?"":"in"),capture:true},blur:{base:c?"blur":"focusout",capture:true}}; -var b="$delegation:";var i=function(l){return{base:"focusin",remove:function(m,o){var p=m.retrieve(b+l+"listeners",{})[o];if(p&&p.forms){for(var n=p.forms.length; -n--;){p.forms[n].removeEvent(l,p.fns[n]);}}},listen:function(x,r,v,n,t,s){var o=(t.get("tag")=="form")?t:n.target.getParent("form");if(!o){return;}var u=x.retrieve(b+l+"listeners",{}),p=u[s]||{forms:[],fns:[]},m=p.forms,w=p.fns; -if(m.indexOf(o)!=-1){return;}m.push(o);var q=function(y){k(x,r,v,y,t);};o.addEvent(l,q);w.push(q);u[s]=p;x.store(b+l+"listeners",u);}};};var d=function(l){return{base:"focusin",listen:function(m,n,p,q,r){var o={blur:function(){this.removeEvents(o); -}};o[l]=function(s){k(m,n,p,s,r);};q.target.addEvents(o);}};};if(!c){Object.append(a,{submit:i("submit"),reset:i("reset"),change:d("change"),select:d("select")}); -}var h=Element.prototype,f=h.addEvent,j=h.removeEvent;var e=function(l,m){return function(r,q,n){if(r.indexOf(":relay")==-1){return l.call(this,r,q,n); -}var o=Slick.parse(r).expressions[0][0];if(o.pseudos[0].key!="relay"){return l.call(this,r,q,n);}var p=o.tag;o.pseudos.slice(1).each(function(s){p+=":"+s.key+(s.value?"("+s.value+")":""); -});l.call(this,r,q);return m.call(this,p,o.pseudos[0].value,q);};};var g={addEvent:function(v,q,x){var t=this.retrieve("$delegates",{}),r=t[v];if(r){for(var y in r){if(r[y].fn==x&&r[y].match==q){return this; -}}}var p=v,u=q,o=x,n=a[v]||{};v=n.base||p;q=function(B){return Slick.match(B,u);};var w=Element.Events[p];if(w&&w.condition){var l=q,m=w.condition;q=function(C,B){return l(C,B)&&m.call(C,B,v); -};}var z=this,s=String.uniqueID();var A=n.listen?function(B,C){if(!C&&B&&B.target){C=B.target;}if(C){n.listen(z,q,x,B,C,s);}}:function(B,C){if(!C&&B&&B.target){C=B.target; -}if(C){k(z,q,x,B,C);}};if(!r){r={};}r[s]={match:u,fn:o,delegator:A};t[p]=r;return f.call(this,v,A,n.capture);},removeEvent:function(r,n,t,u){var q=this.retrieve("$delegates",{}),p=q[r]; -if(!p){return this;}if(u){var m=r,w=p[u].delegator,l=a[r]||{};r=l.base||m;if(l.remove){l.remove(this,u);}delete p[u];q[m]=p;return j.call(this,r,w);}var o,v; -if(t){for(o in p){v=p[o];if(v.match==n&&v.fn==t){return g.removeEvent.call(this,r,n,t,o);}}}else{for(o in p){v=p[o];if(v.match==n){g.removeEvent.call(this,r,n,v.fn,o); -}}}return this;}};[Element,Window,Document].invoke("implement",{addEvent:e(f,g.addEvent),removeEvent:e(j,g.removeEvent)});})();(function(){var h=document.createElement("div"),e=document.createElement("div"); -h.style.height="0";h.appendChild(e);var d=(e.offsetParent===h);h=e=null;var l=function(m){return k(m,"position")!="static"||a(m);};var i=function(m){return l(m)||(/^(?:table|td|th)$/i).test(m.tagName); -};Element.implement({scrollTo:function(m,n){if(a(this)){this.getWindow().scrollTo(m,n);}else{this.scrollLeft=m;this.scrollTop=n;}return this;},getSize:function(){if(a(this)){return this.getWindow().getSize(); -}return{x:this.offsetWidth,y:this.offsetHeight};},getScrollSize:function(){if(a(this)){return this.getWindow().getScrollSize();}return{x:this.scrollWidth,y:this.scrollHeight}; -},getScroll:function(){if(a(this)){return this.getWindow().getScroll();}return{x:this.scrollLeft,y:this.scrollTop};},getScrolls:function(){var n=this.parentNode,m={x:0,y:0}; -while(n&&!a(n)){m.x+=n.scrollLeft;m.y+=n.scrollTop;n=n.parentNode;}return m;},getOffsetParent:d?function(){var m=this;if(a(m)||k(m,"position")=="fixed"){return null; -}var n=(k(m,"position")=="static")?i:l;while((m=m.parentNode)){if(n(m)){return m;}}return null;}:function(){var m=this;if(a(m)||k(m,"position")=="fixed"){return null; -}try{return m.offsetParent;}catch(n){}return null;},getOffsets:function(){if(this.getBoundingClientRect&&!Browser.Platform.ios){var r=this.getBoundingClientRect(),o=document.id(this.getDocument().documentElement),q=o.getScroll(),t=this.getScrolls(),s=(k(this,"position")=="fixed"); -return{x:r.left.toInt()+t.x+((s)?0:q.x)-o.clientLeft,y:r.top.toInt()+t.y+((s)?0:q.y)-o.clientTop};}var n=this,m={x:0,y:0};if(a(this)){return m;}while(n&&!a(n)){m.x+=n.offsetLeft; -m.y+=n.offsetTop;if(Browser.firefox){if(!c(n)){m.x+=b(n);m.y+=g(n);}var p=n.parentNode;if(p&&k(p,"overflow")!="visible"){m.x+=b(p);m.y+=g(p);}}else{if(n!=this&&Browser.safari){m.x+=b(n); -m.y+=g(n);}}n=n.offsetParent;}if(Browser.firefox&&!c(this)){m.x-=b(this);m.y-=g(this);}return m;},getPosition:function(p){var q=this.getOffsets(),n=this.getScrolls(); -var m={x:q.x-n.x,y:q.y-n.y};if(p&&(p=document.id(p))){var o=p.getPosition();return{x:m.x-o.x-b(p),y:m.y-o.y-g(p)};}return m;},getCoordinates:function(o){if(a(this)){return this.getWindow().getCoordinates(); -}var m=this.getPosition(o),n=this.getSize();var p={left:m.x,top:m.y,width:n.x,height:n.y};p.right=p.left+p.width;p.bottom=p.top+p.height;return p;},computePosition:function(m){return{left:m.x-j(this,"margin-left"),top:m.y-j(this,"margin-top")}; -},setPosition:function(m){return this.setStyles(this.computePosition(m));}});[Document,Window].invoke("implement",{getSize:function(){var m=f(this);return{x:m.clientWidth,y:m.clientHeight}; -},getScroll:function(){var n=this.getWindow(),m=f(this);return{x:n.pageXOffset||m.scrollLeft,y:n.pageYOffset||m.scrollTop};},getScrollSize:function(){var o=f(this),n=this.getSize(),m=this.getDocument().body; -return{x:Math.max(o.scrollWidth,m.scrollWidth,n.x),y:Math.max(o.scrollHeight,m.scrollHeight,n.y)};},getPosition:function(){return{x:0,y:0};},getCoordinates:function(){var m=this.getSize(); -return{top:0,left:0,bottom:m.y,right:m.x,height:m.y,width:m.x};}});var k=Element.getComputedStyle;function j(m,n){return k(m,n).toInt()||0;}function c(m){return k(m,"-moz-box-sizing")=="border-box"; -}function g(m){return j(m,"border-top-width");}function b(m){return j(m,"border-left-width");}function a(m){return(/^(?:body|html)$/i).test(m.tagName); -}function f(m){var n=m.getDocument();return(!n.compatMode||n.compatMode=="CSS1Compat")?n.html:n.body;}})();Element.alias({position:"setPosition"});[Window,Document,Element].invoke("implement",{getHeight:function(){return this.getSize().y; -},getWidth:function(){return this.getSize().x;},getScrollTop:function(){return this.getScroll().y;},getScrollLeft:function(){return this.getScroll().x; -},getScrollHeight:function(){return this.getScrollSize().y;},getScrollWidth:function(){return this.getScrollSize().x;},getTop:function(){return this.getPosition().y; -},getLeft:function(){return this.getPosition().x;}});(function(){var f=this.Fx=new Class({Implements:[Chain,Events,Options],options:{fps:60,unit:false,duration:500,frames:null,frameSkip:true,link:"ignore"},initialize:function(g){this.subject=this.subject||this; -this.setOptions(g);},getTransition:function(){return function(g){return -(Math.cos(Math.PI*g)-1)/2;};},step:function(g){if(this.options.frameSkip){var h=(this.time!=null)?(g-this.time):0,i=h/this.frameInterval; -this.time=g;this.frame+=i;}else{this.frame++;}if(this.frame=(7-4*d)/11){e=c*c-Math.pow((11-6*d-11*f)/4,2);break;}}return e;},Elastic:function(b,a){return Math.pow(2,10*--b)*Math.cos(20*b*Math.PI*(a&&a[0]||1)/3); -}});["Quad","Cubic","Quart","Quint"].each(function(b,a){Fx.Transitions[b]=new Fx.Transition(function(c){return Math.pow(c,a+2);});});(function(){var d=function(){},a=("onprogress" in new Browser.Request); -var c=this.Request=new Class({Implements:[Chain,Events,Options],options:{url:"",data:"",headers:{"X-Requested-With":"XMLHttpRequest",Accept:"text/javascript, text/html, application/xml, text/xml, */*"},async:true,format:false,method:"post",link:"ignore",isSuccess:null,emulation:true,urlEncoded:true,encoding:"utf-8",evalScripts:false,evalResponse:false,timeout:0,noCache:false},initialize:function(e){this.xhr=new Browser.Request(); -this.setOptions(e);this.headers=this.options.headers;},onStateChange:function(){var e=this.xhr;if(e.readyState!=4||!this.running){return;}this.running=false; -this.status=0;Function.attempt(function(){var f=e.status;this.status=(f==1223)?204:f;}.bind(this));e.onreadystatechange=d;if(a){e.onprogress=e.onloadstart=d; -}clearTimeout(this.timer);this.response={text:this.xhr.responseText||"",xml:this.xhr.responseXML};if(this.options.isSuccess.call(this,this.status)){this.success(this.response.text,this.response.xml); -}else{this.failure();}},isSuccess:function(){var e=this.status;return(e>=200&&e<300);},isRunning:function(){return !!this.running;},processScripts:function(e){if(this.options.evalResponse||(/(ecma|java)script/).test(this.getHeader("Content-type"))){return Browser.exec(e); -}return e.stripScripts(this.options.evalScripts);},success:function(f,e){this.onSuccess(this.processScripts(f),e);},onSuccess:function(){this.fireEvent("complete",arguments).fireEvent("success",arguments).callChain(); -},failure:function(){this.onFailure();},onFailure:function(){this.fireEvent("complete").fireEvent("failure",this.xhr);},loadstart:function(e){this.fireEvent("loadstart",[e,this.xhr]); -},progress:function(e){this.fireEvent("progress",[e,this.xhr]);},timeout:function(){this.fireEvent("timeout",this.xhr);},setHeader:function(e,f){this.headers[e]=f; -return this;},getHeader:function(e){return Function.attempt(function(){return this.xhr.getResponseHeader(e);}.bind(this));},check:function(){if(!this.running){return true; -}switch(this.options.link){case"cancel":this.cancel();return true;case"chain":this.chain(this.caller.pass(arguments,this));return false;}return false;},send:function(o){if(!this.check(o)){return this; -}this.options.isSuccess=this.options.isSuccess||this.isSuccess;this.running=true;var l=typeOf(o);if(l=="string"||l=="element"){o={data:o};}var h=this.options; -o=Object.append({data:h.data,url:h.url,method:h.method},o);var j=o.data,f=String(o.url),e=o.method.toLowerCase();switch(typeOf(j)){case"element":j=document.id(j).toQueryString(); -break;case"object":case"hash":j=Object.toQueryString(j);}if(this.options.format){var m="format="+this.options.format;j=(j)?m+"&"+j:m;}if(this.options.emulation&&!["get","post"].contains(e)){var k="_method="+e; -j=(j)?k+"&"+j:k;e="post";}if(this.options.urlEncoded&&["post","put"].contains(e)){var g=(this.options.encoding)?"; charset="+this.options.encoding:"";this.headers["Content-type"]="application/x-www-form-urlencoded"+g; -}if(!f){f=document.location.pathname;}var i=f.lastIndexOf("/");if(i>-1&&(i=f.indexOf("#"))>-1){f=f.substr(0,i);}if(this.options.noCache){f+=(f.contains("?")?"&":"?")+String.uniqueID(); -}if(j&&e=="get"){f+=(f.contains("?")?"&":"?")+j;j=null;}var n=this.xhr;if(a){n.onloadstart=this.loadstart.bind(this);n.onprogress=this.progress.bind(this); -}n.open(e.toUpperCase(),f,this.options.async,this.options.user,this.options.password);if(this.options.user&&"withCredentials" in n){n.withCredentials=true; -}n.onreadystatechange=this.onStateChange.bind(this);Object.each(this.headers,function(q,p){try{n.setRequestHeader(p,q);}catch(r){this.fireEvent("exception",[p,q]); -}},this);this.fireEvent("request");n.send(j);if(!this.options.async){this.onStateChange();}else{if(this.options.timeout){this.timer=this.timeout.delay(this.options.timeout,this); -}}return this;},cancel:function(){if(!this.running){return this;}this.running=false;var e=this.xhr;e.abort();clearTimeout(this.timer);e.onreadystatechange=d; -if(a){e.onprogress=e.onloadstart=d;}this.xhr=new Browser.Request();this.fireEvent("cancel");return this;}});var b={};["get","post","put","delete","GET","POST","PUT","DELETE"].each(function(e){b[e]=function(g){var f={method:e}; -if(g!=null){f.data=g;}return this.send(f);};});c.implement(b);Element.Properties.send={set:function(e){var f=this.get("send").cancel();f.setOptions(e); -return this;},get:function(){var e=this.retrieve("send");if(!e){e=new c({data:this,link:"cancel",method:this.get("method")||"post",url:this.get("action")}); -this.store("send",e);}return e;}};Element.implement({send:function(e){var f=this.get("send");f.send({data:this,url:e||f.options.url});return this;}});})(); -Request.HTML=new Class({Extends:Request,options:{update:false,append:false,evalScripts:true,filter:false,headers:{Accept:"text/html, application/xml, text/xml, */*"}},success:function(f){var e=this.options,c=this.response; -c.html=f.stripScripts(function(h){c.javascript=h;});var d=c.html.match(/]*>([\s\S]*?)<\/body>/i);if(d){c.html=d[1];}var b=new Element("div").set("html",c.html); -c.tree=b.childNodes;c.elements=b.getElements(e.filter||"*");if(e.filter){c.tree=c.elements;}if(e.update){var g=document.id(e.update).empty();if(e.filter){g.adopt(c.elements); -}else{g.set("html",c.html);}}else{if(e.append){var a=document.id(e.append);if(e.filter){c.elements.reverse().inject(a);}else{a.adopt(b.getChildren());}}}if(e.evalScripts){Browser.exec(c.javascript); -}this.onSuccess(c.tree,c.elements,c.html,c.javascript);}});Element.Properties.load={set:function(a){var b=this.get("load").cancel();b.setOptions(a);return this; -},get:function(){var a=this.retrieve("load");if(!a){a=new Request.HTML({data:this,link:"cancel",update:this,method:"get"});this.store("load",a);}return a; -}};Element.implement({load:function(){this.get("load").send(Array.link(arguments,{data:Type.isObject,url:Type.isString}));return this;}});if(typeof JSON=="undefined"){this.JSON={}; -}JSON=new Hash({stringify:JSON.stringify,parse:JSON.parse});(function(){var special={"\b":"\\b","\t":"\\t","\n":"\\n","\f":"\\f","\r":"\\r",'"':'\\"',"\\":"\\\\"}; -var escape=function(chr){return special[chr]||"\\u"+("0000"+chr.charCodeAt(0).toString(16)).slice(-4);};JSON.validate=function(string){string=string.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,"@").replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,"]").replace(/(?:^|:|,)(?:\s*\[)+/g,""); -return(/^[\],:{}\s]*$/).test(string);};JSON.encode=JSON.stringify?function(obj){return JSON.stringify(obj);}:function(obj){if(obj&&obj.toJSON){obj=obj.toJSON(); -}switch(typeOf(obj)){case"string":return'"'+obj.replace(/[\x00-\x1f\\"]/g,escape)+'"';case"array":return"["+obj.map(JSON.encode).clean()+"]";case"object":case"hash":var string=[]; -Object.each(obj,function(value,key){var json=JSON.encode(value);if(json){string.push(JSON.encode(key)+":"+json);}});return"{"+string+"}";case"number":case"boolean":return""+obj; -case"null":return"null";}return null;};JSON.decode=function(string,secure){if(!string||typeOf(string)!="string"){return null;}if(secure||JSON.secure){if(JSON.parse){return JSON.parse(string); -}if(!JSON.validate(string)){throw new Error("JSON could not decode the input; security is enabled and the value is not secure.");}}return eval("("+string+")"); -};})();Request.JSON=new Class({Extends:Request,options:{secure:true},initialize:function(a){this.parent(a);Object.append(this.headers,{Accept:"application/json","X-Request":"JSON"}); -},success:function(c){var b;try{b=this.response.json=JSON.decode(c,this.options.secure);}catch(a){this.fireEvent("error",[c,a]);return;}if(b==null){this.onFailure(); -}else{this.onSuccess(b,c);}}});var Cookie=new Class({Implements:Options,options:{path:"/",domain:false,duration:false,secure:false,document:document,encode:true},initialize:function(b,a){this.key=b; -this.setOptions(a);},write:function(b){if(this.options.encode){b=encodeURIComponent(b);}if(this.options.domain){b+="; domain="+this.options.domain;}if(this.options.path){b+="; path="+this.options.path; -}if(this.options.duration){var a=new Date();a.setTime(a.getTime()+this.options.duration*24*60*60*1000);b+="; expires="+a.toGMTString();}if(this.options.secure){b+="; secure"; -}this.options.document.cookie=this.key+"="+b;return this;},read:function(){var a=this.options.document.cookie.match("(?:^|;)\\s*"+this.key.escapeRegExp()+"=([^;]*)"); -return(a)?decodeURIComponent(a[1]):null;},dispose:function(){new Cookie(this.key,Object.merge({},this.options,{duration:-1})).write("");return this;}}); -Cookie.write=function(b,c,a){return new Cookie(b,a).write(c);};Cookie.read=function(a){return new Cookie(a).read();};Cookie.dispose=function(b,a){return new Cookie(b,a).dispose(); -};(function(i,k){var l,f,e=[],c,b,d=k.createElement("div");var g=function(){clearTimeout(b);if(l){return;}Browser.loaded=l=true;k.removeListener("DOMContentLoaded",g).removeListener("readystatechange",a); -k.fireEvent("domready");i.fireEvent("domready");};var a=function(){for(var m=e.length;m--;){if(e[m]()){g();return true;}}return false;};var j=function(){clearTimeout(b); -if(!a()){b=setTimeout(j,10);}};k.addListener("DOMContentLoaded",g);var h=function(){try{d.doScroll();return true;}catch(m){}return false;};if(d.doScroll&&!h()){e.push(h); -c=true;}if(k.readyState){e.push(function(){var m=k.readyState;return(m=="loaded"||m=="complete");});}if("onreadystatechange" in k){k.addListener("readystatechange",a); -}else{c=true;}if(c){j();}Element.Events.domready={onAdd:function(m){if(l){m.call(this);}}};Element.Events.load={base:"load",onAdd:function(m){if(f&&this==i){m.call(this); -}},condition:function(){if(this==i){g();delete Element.Events.load;}return true;}};i.addEvent("load",function(){f=true;});})(window,document);(function(){var Swiff=this.Swiff=new Class({Implements:Options,options:{id:null,height:1,width:1,container:null,properties:{},params:{quality:"high",allowScriptAccess:"always",wMode:"window",swLiveConnect:true},callBacks:{},vars:{}},toElement:function(){return this.object; -},initialize:function(path,options){this.instance="Swiff_"+String.uniqueID();this.setOptions(options);options=this.options;var id=this.id=options.id||this.instance; -var container=document.id(options.container);Swiff.CallBacks[this.instance]={};var params=options.params,vars=options.vars,callBacks=options.callBacks; -var properties=Object.append({height:options.height,width:options.width},options.properties);var self=this;for(var callBack in callBacks){Swiff.CallBacks[this.instance][callBack]=(function(option){return function(){return option.apply(self.object,arguments); -};})(callBacks[callBack]);vars[callBack]="Swiff.CallBacks."+this.instance+"."+callBack;}params.flashVars=Object.toQueryString(vars);if(Browser.ie){properties.classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"; -params.movie=path;}else{properties.type="application/x-shockwave-flash";}properties.data=path;var build='';}}build+="";this.object=((container)?container.empty():new Element("div")).set("html",build).firstChild; -},replaces:function(element){element=document.id(element,true);element.parentNode.replaceChild(this.toElement(),element);return this;},inject:function(element){document.id(element,true).appendChild(this.toElement()); -return this;},remote:function(){return Swiff.remote.apply(Swiff,[this.toElement()].append(arguments));}});Swiff.CallBacks={};Swiff.remote=function(obj,fn){var rs=obj.CallFunction(''+__flash__argumentsToXML(arguments,2)+""); -return eval(rs);};})(); \ No newline at end of file diff --git a/src/webui/www/public/scripts/mootools-1.2-more.js b/src/webui/www/public/scripts/mootools-1.2-more.js deleted file mode 100644 index 6f5304979..000000000 --- a/src/webui/www/public/scripts/mootools-1.2-more.js +++ /dev/null @@ -1,326 +0,0 @@ -// MooTools: the javascript framework. -// Load this file's selection again by visiting: http://mootools.net/more/208dad2fc7517c7e60f4afddd3e7c664 -// Or build this file again with packager using: packager build More/More More/Class.Binds More/Class.Occlude More/String.Extras More/String.QueryString More/URI More/Hash More/Fx.Elements More/Fx.Accordion More/Fx.Move More/Fx.Reveal More/Fx.Scroll More/Fx.Slide More/Fx.SmoothScroll More/Fx.Sort More/Drag More/Drag.Move More/Slider More/Sortables More/Assets More/Color More/Hash.Cookie More/HtmlTable More/Keyboard -/* ---- -copyrights: - - [MooTools](http://mootools.net) - -licenses: - - [MIT License](http://mootools.net/license.txt) -... -*/ -MooTools.More={version:"1.4.0.1",build:"a4244edf2aa97ac8a196fc96082dd35af1abab87"};Class.Mutators.Binds=function(a){if(!this.prototype.initialize){this.implement("initialize",function(){}); -}return Array.from(a).concat(this.prototype.Binds||[]);};Class.Mutators.initialize=function(a){return function(){Array.from(this.Binds).each(function(b){var c=this[b]; -if(c){this[b]=c.bind(this);}},this);return a.apply(this,arguments);};};Class.Occlude=new Class({occlude:function(c,b){b=document.id(b||this.element);var a=b.retrieve(c||this.property); -if(a&&!this.occluded){return(this.occluded=a);}this.occluded=false;b.store(c||this.property,this);return this.occluded;}});(function(){var c={a:/[àáâãäåăą]/g,A:/[ÀÁÂÃÄÅĂĄ]/g,c:/[ćčç]/g,C:/[ĆČÇ]/g,d:/[ďđ]/g,D:/[ĎÐ]/g,e:/[èéêëěę]/g,E:/[ÈÉÊËĚĘ]/g,g:/[ğ]/g,G:/[Ğ]/g,i:/[ìíîï]/g,I:/[ÌÍÎÏ]/g,l:/[ĺľł]/g,L:/[ĹĽŁ]/g,n:/[ñňń]/g,N:/[ÑŇŃ]/g,o:/[òóôõöøő]/g,O:/[ÒÓÔÕÖØ]/g,r:/[řŕ]/g,R:/[ŘŔ]/g,s:/[ššş]/g,S:/[ŠŞŚ]/g,t:/[ťţ]/g,T:/[ŤŢ]/g,ue:/[ü]/g,UE:/[Ü]/g,u:/[ùúûůµ]/g,U:/[ÙÚÛŮ]/g,y:/[ÿý]/g,Y:/[ŸÝ]/g,z:/[žźż]/g,Z:/[ŽŹŻ]/g,th:/[þ]/g,TH:/[Þ]/g,dh:/[ð]/g,DH:/[Ð]/g,ss:/[ß]/g,oe:/[œ]/g,OE:/[Œ]/g,ae:/[æ]/g,AE:/[Æ]/g},b={" ":/[\xa0\u2002\u2003\u2009]/g,"*":/[\xb7]/g,"'":/[\u2018\u2019]/g,'"':/[\u201c\u201d]/g,"...":/[\u2026]/g,"-":/[\u2013]/g,"»":/[\uFFFD]/g}; -var a=function(f,h){var e=f,g;for(g in h){e=e.replace(h[g],g);}return e;};var d=function(e,g){e=e||"";var h=g?"<"+e+"(?!\\w)[^>]*>([\\s\\S]*?)":"]+)?>",f=new RegExp(h,"gi"); -return f;};String.implement({standardize:function(){return a(this,c);},repeat:function(e){return new Array(e+1).join(this);},pad:function(e,h,g){if(this.length>=e){return this; -}var f=(h==null?" ":""+h).repeat(e-this.length).substr(0,e-this.length);if(!g||g=="right"){return this+f;}if(g=="left"){return f+this;}return f.substr(0,(f.length/2).floor())+this+f.substr(0,(f.length/2).ceil()); -},getTags:function(e,f){return this.match(d(e,f))||[];},stripTags:function(e,f){return this.replace(d(e,f),"");},tidy:function(){return a(this,b);},truncate:function(e,f,i){var h=this; -if(f==null&&arguments.length==1){f="…";}if(h.length>e){h=h.substring(0,e);if(i){var g=h.lastIndexOf(i);if(g!=-1){h=h.substr(0,g);}}if(f){h+=f;}}return h; -}});})();String.implement({parseQueryString:function(d,a){if(d==null){d=true;}if(a==null){a=true;}var c=this.split(/[&;]/),b={};if(!c.length){return b; -}c.each(function(i){var e=i.indexOf("=")+1,g=e?i.substr(e):"",f=e?i.substr(0,e-1).match(/([^\]\[]+|(\B)(?=\]))/g):[i],h=b;if(!f){return;}if(a){g=decodeURIComponent(g); -}f.each(function(k,j){if(d){k=decodeURIComponent(k);}var l=h[k];if(j0){c.pop(); -}else{if(f!="."){c.push(f);}}});return c.join("/")+"/";},combine:function(c){return c.value||c.scheme+"://"+(c.user?c.user+(c.password?":"+c.password:"")+"@":"")+(c.host||"")+(c.port&&c.port!=this.schemes[c.scheme]?":"+c.port:"")+(c.directory||"/")+(c.file||"")+(c.query?"?"+c.query:"")+(c.fragment?"#"+c.fragment:""); -},set:function(d,f,e){if(d=="value"){var c=f.match(a.regs.scheme);if(c){c=c[1];}if(c&&this.schemes[c.toLowerCase()]==null){this.parsed={scheme:c,value:f}; -}else{this.parsed=this.parse(f,(e||this).parsed)||(c?{scheme:c,value:f}:{value:f});}}else{if(d=="data"){this.setData(f);}else{this.parsed[d]=f;}}return this; -},get:function(c,d){switch(c){case"value":return this.combine(this.parsed,d?d.parsed:false);case"data":return this.getData();}return this.parsed[c]||""; -},go:function(){document.location.href=this.toString();},toURI:function(){return this;},getData:function(e,d){var c=this.get(d||"query");if(!(c||c===0)){return e?null:{}; -}var f=c.parseQueryString();return e?f[e]:f;},setData:function(c,f,d){if(typeof c=="string"){var e=this.getData();e[arguments[0]]=arguments[1];c=e;}else{if(f){c=Object.merge(this.getData(),c); -}}return this.set(d||"query",Object.toQueryString(c));},clearData:function(c){return this.set(c||"query","");},toString:b,valueOf:b});a.regs={endSlash:/\/$/,scheme:/^(\w+):/,directoryDot:/\.\/|\.$/}; -a.base=new a(Array.from(document.getElements("base[href]",true)).getLast(),{base:document.location});String.implement({toURI:function(c){return new a(this,c); -}});})();(function(){if(this.Hash){return;}var a=this.Hash=new Type("Hash",function(b){if(typeOf(b)=="hash"){b=Object.clone(b.getClean());}for(var c in b){this[c]=b[c]; -}return this;});this.$H=function(b){return new a(b);};a.implement({forEach:function(b,c){Object.forEach(this,b,c);},getClean:function(){var c={};for(var b in this){if(this.hasOwnProperty(b)){c[b]=this[b]; -}}return c;},getLength:function(){var c=0;for(var b in this){if(this.hasOwnProperty(b)){c++;}}return c;}});a.alias("each","forEach");a.implement({has:Object.prototype.hasOwnProperty,keyOf:function(b){return Object.keyOf(this,b); -},hasValue:function(b){return Object.contains(this,b);},extend:function(b){a.each(b||{},function(d,c){a.set(this,c,d);},this);return this;},combine:function(b){a.each(b||{},function(d,c){a.include(this,c,d); -},this);return this;},erase:function(b){if(this.hasOwnProperty(b)){delete this[b];}return this;},get:function(b){return(this.hasOwnProperty(b))?this[b]:null; -},set:function(b,c){if(!this[b]||this.hasOwnProperty(b)){this[b]=c;}return this;},empty:function(){a.each(this,function(c,b){delete this[b];},this);return this; -},include:function(b,c){if(this[b]==undefined){this[b]=c;}return this;},map:function(b,c){return new a(Object.map(this,b,c));},filter:function(b,c){return new a(Object.filter(this,b,c)); -},every:function(b,c){return Object.every(this,b,c);},some:function(b,c){return Object.some(this,b,c);},getKeys:function(){return Object.keys(this);},getValues:function(){return Object.values(this); -},toQueryString:function(b){return Object.toQueryString(this,b);}});a.alias({indexOf:"keyOf",contains:"hasValue"});})();Fx.Elements=new Class({Extends:Fx.CSS,initialize:function(b,a){this.elements=this.subject=$$(b); -this.parent(a);},compute:function(g,h,j){var c={};for(var d in g){var a=g[d],e=h[d],f=c[d]={};for(var b in a){f[b]=this.parent(a[b],e[b],j);}}return c; -},set:function(b){for(var c in b){if(!this.elements[c]){continue;}var a=b[c];for(var d in a){this.render(this.elements[c],d,a[d],this.options.unit);}}return this; -},start:function(c){if(!this.check(c)){return this;}var h={},j={};for(var d in c){if(!this.elements[d]){continue;}var f=c[d],a=h[d]={},g=j[d]={};for(var b in f){var e=this.prepare(this.elements[d],b,f[b]); -a[b]=e.from;g[b]=e.to;}}return this.parent(h,j);}});Fx.Accordion=new Class({Extends:Fx.Elements,options:{fixedHeight:false,fixedWidth:false,display:0,show:false,height:true,width:false,opacity:true,alwaysHide:false,trigger:"click",initialDisplayFx:true,resetHeight:true},initialize:function(){var g=function(h){return h!=null; -};var f=Array.link(arguments,{container:Type.isElement,options:Type.isObject,togglers:g,elements:g});this.parent(f.elements,f.options);var b=this.options,e=this.togglers=$$(f.togglers); -this.previous=-1;this.internalChain=new Chain();if(b.alwaysHide){this.options.link="chain";}if(b.show||this.options.show===0){b.display=false;this.previous=b.show; -}if(b.start){b.display=false;b.show=false;}var d=this.effects={};if(b.opacity){d.opacity="fullOpacity";}if(b.width){d.width=b.fixedWidth?"fullWidth":"offsetWidth"; -}if(b.height){d.height=b.fixedHeight?"fullHeight":"scrollHeight";}for(var c=0,a=e.length;c=0?a-1:0)).chain(d);}else{d();}return this;},detach:function(b){var a=function(c){c.removeEvent(this.options.trigger,c.retrieve("accordion:display")); -}.bind(this);if(!b){this.togglers.each(a);}else{a(b);}return this;},display:function(b,c){if(!this.check(b,c)){return this;}var h={},g=this.elements,a=this.options,f=this.effects; -if(c==null){c=true;}if(typeOf(b)=="element"){b=g.indexOf(b);}if(b==this.previous&&!a.alwaysHide){return this;}if(a.resetHeight){var e=g[this.previous]; -if(e&&!this.selfHidden){for(var d in f){e.setStyle(d,e[f[d]]);}}}if((this.timer&&a.link=="chain")||(b===this.previous&&!a.alwaysHide)){return this;}this.previous=b; -this.selfHidden=false;g.each(function(l,k){h[k]={};var j;if(k!=b){j=true;}else{if(a.alwaysHide&&((l.offsetHeight>0&&a.height)||l.offsetWidth>0&&a.width)){j=true; -this.selfHidden=true;}}this.fireEvent(j?"background":"active",[this.togglers[k],l]);for(var m in f){h[k][m]=j?0:l[f[m]];}if(!c&&!j&&a.resetHeight){h[k].height="auto"; -}},this);this.internalChain.clearChain();this.internalChain.chain(function(){if(a.resetHeight&&!this.selfHidden){var i=g[b];if(i){i.setStyle("height","auto"); -}}}.bind(this));return c?this.start(h):this.set(h).internalChain.callChain();}});var Accordion=new Class({Extends:Fx.Accordion,initialize:function(){this.parent.apply(this,arguments); -var a=Array.link(arguments,{container:Type.isElement});this.container=a.container;},addSection:function(c,b,e){c=document.id(c);b=document.id(b);var d=this.togglers.contains(c); -var a=this.togglers.length;if(a&&(!d||e)){e=e!=null?e:a-1;c.inject(this.togglers[e],"before");b.inject(c,"after");}else{if(this.container&&!d){c.inject(this.container); -b.inject(this.container);}}return this.parent.apply(this,arguments);}});(function(){var b=function(e,d){var f=[];Object.each(d,function(g){Object.each(g,function(h){e.each(function(i){f.push(i+"-"+h+(i=="border"?"-width":"")); -});});});return f;};var c=function(f,e){var d=0;Object.each(e,function(h,g){if(g.test(f)){d=d+h.toInt();}});return d;};var a=function(d){return !!(!d||d.offsetHeight||d.offsetWidth); -};Element.implement({measure:function(h){if(a(this)){return h.call(this);}var g=this.getParent(),e=[];while(!a(g)&&g!=document.body){e.push(g.expose()); -g=g.getParent();}var f=this.expose(),d=h.call(this);f();e.each(function(i){i();});return d;},expose:function(){if(this.getStyle("display")!="none"){return function(){}; -}var d=this.style.cssText;this.setStyles({display:"block",position:"absolute",visibility:"hidden"});return function(){this.style.cssText=d;}.bind(this); -},getDimensions:function(d){d=Object.merge({computeSize:false},d);var i={x:0,y:0};var h=function(j,e){return(e.computeSize)?j.getComputedSize(e):j.getSize(); -};var f=this.getParent("body");if(f&&this.getStyle("display")=="none"){i=this.measure(function(){return h(this,d);});}else{if(f){try{i=h(this,d);}catch(g){}}}return Object.append(i,(i.x||i.x===0)?{width:i.x,height:i.y}:{x:i.width,y:i.height}); -},getComputedSize:function(d){if(d&&d.plains){d.planes=d.plains;}d=Object.merge({styles:["padding","border"],planes:{height:["top","bottom"],width:["left","right"]},mode:"both"},d); -var g={},e={width:0,height:0},f;if(d.mode=="vertical"){delete e.width;delete d.planes.width;}else{if(d.mode=="horizontal"){delete e.height;delete d.planes.height; -}}b(d.styles,d.planes).each(function(h){g[h]=this.getStyle(h).toInt();},this);Object.each(d.planes,function(i,h){var k=h.capitalize(),j=this.getStyle(h); -if(j=="auto"&&!f){f=this.getDimensions();}j=g[h]=(j=="auto")?f[h]:j.toInt();e["total"+k]=j;i.each(function(m){var l=c(m,g);e["computed"+m.capitalize()]=l; -e["total"+k]+=l;});},this);return Object.append(e,g);}});})();(function(b){var a=Element.Position={options:{relativeTo:document.body,position:{x:"center",y:"center"},offset:{x:0,y:0}},getOptions:function(d,c){c=Object.merge({},a.options,c); -a.setPositionOption(c);a.setEdgeOption(c);a.setOffsetOption(d,c);a.setDimensionsOption(d,c);return c;},setPositionOption:function(c){c.position=a.getCoordinateFromValue(c.position); -},setEdgeOption:function(d){var c=a.getCoordinateFromValue(d.edge);d.edge=c?c:(d.position.x=="center"&&d.position.y=="center")?{x:"center",y:"center"}:{x:"left",y:"top"}; -},setOffsetOption:function(f,d){var c={x:0,y:0},g=f.measure(function(){return document.id(this.getOffsetParent());}),e=g.getScroll();if(!g||g==f.getDocument().body){return; -}c=g.measure(function(){var i=this.getPosition();if(this.getStyle("position")=="fixed"){var h=window.getScroll();i.x+=h.x;i.y+=h.y;}return i;});d.offset={parentPositioned:g!=document.id(d.relativeTo),x:d.offset.x-c.x+e.x,y:d.offset.y-c.y+e.y}; -},setDimensionsOption:function(d,c){c.dimensions=d.getDimensions({computeSize:true,styles:["padding","border","margin"]});},getPosition:function(e,d){var c={}; -d=a.getOptions(e,d);var f=document.id(d.relativeTo)||document.body;a.setPositionCoordinates(d,c,f);if(d.edge){a.toEdge(c,d);}var g=d.offset;c.left=((c.x>=0||g.parentPositioned||d.allowNegative)?c.x:0).toInt(); -c.top=((c.y>=0||g.parentPositioned||d.allowNegative)?c.y:0).toInt();a.toMinMax(c,d);if(d.relFixedPosition||f.getStyle("position")=="fixed"){a.toRelFixedPosition(f,c); -}if(d.ignoreScroll){a.toIgnoreScroll(f,c);}if(d.ignoreMargins){a.toIgnoreMargins(c,d);}c.left=Math.ceil(c.left);c.top=Math.ceil(c.top);delete c.x;delete c.y; -return c;},setPositionCoordinates:function(k,g,d){var f=k.offset.y,h=k.offset.x,e=(d==document.body)?window.getScroll():d.getPosition(),j=e.y,c=e.x,i=window.getSize(); -switch(k.position.x){case"left":g.x=c+h;break;case"right":g.x=c+h+d.offsetWidth;break;default:g.x=c+((d==document.body?i.x:d.offsetWidth)/2)+h;break;}switch(k.position.y){case"top":g.y=j+f; -break;case"bottom":g.y=j+f+d.offsetHeight;break;default:g.y=j+((d==document.body?i.y:d.offsetHeight)/2)+f;break;}},toMinMax:function(c,d){var f={left:"x",top:"y"},e; -["minimum","maximum"].each(function(g){["left","top"].each(function(h){e=d[g]?d[g][f[h]]:null;if(e!=null&&((g=="minimum")?c[h]e)){c[h]=e;}});}); -},toRelFixedPosition:function(e,c){var d=window.getScroll();c.top+=d.y;c.left+=d.x;},toIgnoreScroll:function(e,d){var c=e.getScroll();d.top-=c.y;d.left-=c.x; -},toIgnoreMargins:function(c,d){c.left+=d.edge.x=="right"?d.dimensions["margin-right"]:(d.edge.x!="center"?-d.dimensions["margin-left"]:-d.dimensions["margin-left"]+((d.dimensions["margin-right"]+d.dimensions["margin-left"])/2)); -c.top+=d.edge.y=="bottom"?d.dimensions["margin-bottom"]:(d.edge.y!="center"?-d.dimensions["margin-top"]:-d.dimensions["margin-top"]+((d.dimensions["margin-bottom"]+d.dimensions["margin-top"])/2)); -},toEdge:function(c,d){var e={},g=d.dimensions,f=d.edge;switch(f.x){case"left":e.x=0;break;case"right":e.x=-g.x-g.computedRight-g.computedLeft;break;default:e.x=-(Math.round(g.totalWidth/2)); -break;}switch(f.y){case"top":e.y=0;break;case"bottom":e.y=-g.y-g.computedTop-g.computedBottom;break;default:e.y=-(Math.round(g.totalHeight/2));break;}c.x+=e.x; -c.y+=e.y;},getCoordinateFromValue:function(c){if(typeOf(c)!="string"){return c;}c=c.toLowerCase();return{x:c.test("left")?"left":(c.test("right")?"right":"center"),y:c.test(/upper|top/)?"top":(c.test("bottom")?"bottom":"center")}; -}};Element.implement({position:function(d){if(d&&(d.x!=null||d.y!=null)){return(b?b.apply(this,arguments):this);}var c=this.setStyle("position","absolute").calculatePosition(d); -return(d&&d.returnPos)?c:this.setStyles(c);},calculatePosition:function(c){return a.getPosition(this,c);}});})(Element.prototype.position);Fx.Move=new Class({Extends:Fx.Morph,options:{relativeTo:document.body,position:"center",edge:false,offset:{x:0,y:0}},start:function(a){var b=this.element,c=b.getStyles("top","left"); -if(c.top=="auto"||c.left=="auto"){b.setPosition(b.getPosition(b.getOffsetParent()));}return this.parent(b.position(Object.merge({},this.options,a,{returnPos:true}))); -}});Element.Properties.move={set:function(a){this.get("move").cancel().setOptions(a);return this;},get:function(){var a=this.retrieve("move");if(!a){a=new Fx.Move(this,{link:"cancel"}); -this.store("move",a);}return a;}};Element.implement({move:function(a){this.get("move").start(a);return this;}});Element.implement({isDisplayed:function(){return this.getStyle("display")!="none"; -},isVisible:function(){var a=this.offsetWidth,b=this.offsetHeight;return(a==0&&b==0)?false:(a>0&&b>0)?true:this.style.display!="none";},toggle:function(){return this[this.isDisplayed()?"hide":"show"](); -},hide:function(){var b;try{b=this.getStyle("display");}catch(a){}if(b=="none"){return this;}return this.store("element:_originalDisplay",b||"").setStyle("display","none"); -},show:function(a){if(!a&&this.isDisplayed()){return this;}a=a||this.retrieve("element:_originalDisplay")||"block";return this.setStyle("display",(a=="none")?"block":a); -},swapClass:function(a,b){return this.removeClass(a).addClass(b);}});Document.implement({clearSelection:function(){if(window.getSelection){var a=window.getSelection(); -if(a&&a.removeAllRanges){a.removeAllRanges();}}else{if(document.selection&&document.selection.empty){try{document.selection.empty();}catch(b){}}}}});(function(){var a=function(d){var b=d.options.hideInputs; -if(window.OverText){var c=[null];OverText.each(function(e){c.include("."+e.options.labelClass);});if(c){b+=c.join(", ");}}return(b)?d.element.getElements(b):null; -};Fx.Reveal=new Class({Extends:Fx.Morph,options:{link:"cancel",styles:["padding","border","margin"],transitionOpacity:!Browser.ie6,mode:"vertical",display:function(){return this.element.get("tag")!="tr"?"block":"table-row"; -},opacity:1,hideInputs:Browser.ie?"select, input, textarea, object, embed":null},dissolve:function(){if(!this.hiding&&!this.showing){if(this.element.getStyle("display")!="none"){this.hiding=true; -this.showing=false;this.hidden=true;this.cssText=this.element.style.cssText;var d=this.element.getComputedSize({styles:this.options.styles,mode:this.options.mode}); -if(this.options.transitionOpacity){d.opacity=this.options.opacity;}var c={};Object.each(d,function(f,e){c[e]=[f,0];});this.element.setStyles({display:Function.from(this.options.display).call(this),overflow:"hidden"}); -var b=a(this);if(b){b.setStyle("visibility","hidden");}this.$chain.unshift(function(){if(this.hidden){this.hiding=false;this.element.style.cssText=this.cssText; -this.element.setStyle("display","none");if(b){b.setStyle("visibility","visible");}}this.fireEvent("hide",this.element);this.callChain();}.bind(this));this.start(c); -}else{this.callChain.delay(10,this);this.fireEvent("complete",this.element);this.fireEvent("hide",this.element);}}else{if(this.options.link=="chain"){this.chain(this.dissolve.bind(this)); -}else{if(this.options.link=="cancel"&&!this.hiding){this.cancel();this.dissolve();}}}return this;},reveal:function(){if(!this.showing&&!this.hiding){if(this.element.getStyle("display")=="none"){this.hiding=false; -this.showing=true;this.hidden=false;this.cssText=this.element.style.cssText;var d;this.element.measure(function(){d=this.element.getComputedSize({styles:this.options.styles,mode:this.options.mode}); -}.bind(this));if(this.options.heightOverride!=null){d.height=this.options.heightOverride.toInt();}if(this.options.widthOverride!=null){d.width=this.options.widthOverride.toInt(); -}if(this.options.transitionOpacity){this.element.setStyle("opacity",0);d.opacity=this.options.opacity;}var c={height:0,display:Function.from(this.options.display).call(this)}; -Object.each(d,function(f,e){c[e]=0;});c.overflow="hidden";this.element.setStyles(c);var b=a(this);if(b){b.setStyle("visibility","hidden");}this.$chain.unshift(function(){this.element.style.cssText=this.cssText; -this.element.setStyle("display",Function.from(this.options.display).call(this));if(!this.hidden){this.showing=false;}if(b){b.setStyle("visibility","visible"); -}this.callChain();this.fireEvent("show",this.element);}.bind(this));this.start(d);}else{this.callChain();this.fireEvent("complete",this.element);this.fireEvent("show",this.element); -}}else{if(this.options.link=="chain"){this.chain(this.reveal.bind(this));}else{if(this.options.link=="cancel"&&!this.showing){this.cancel();this.reveal(); -}}}return this;},toggle:function(){if(this.element.getStyle("display")=="none"){this.reveal();}else{this.dissolve();}return this;},cancel:function(){this.parent.apply(this,arguments); -if(this.cssText!=null){this.element.style.cssText=this.cssText;}this.hiding=false;this.showing=false;return this;}});Element.Properties.reveal={set:function(b){this.get("reveal").cancel().setOptions(b); -return this;},get:function(){var b=this.retrieve("reveal");if(!b){b=new Fx.Reveal(this);this.store("reveal",b);}return b;}};Element.Properties.dissolve=Element.Properties.reveal; -Element.implement({reveal:function(b){this.get("reveal").setOptions(b).reveal();return this;},dissolve:function(b){this.get("reveal").setOptions(b).dissolve(); -return this;},nix:function(b){var c=Array.link(arguments,{destroy:Type.isBoolean,options:Type.isObject});this.get("reveal").setOptions(b).dissolve().chain(function(){this[c.destroy?"destroy":"dispose"](); -}.bind(this));return this;},wink:function(){var c=Array.link(arguments,{duration:Type.isNumber,options:Type.isObject});var b=this.get("reveal").setOptions(c.options); -b.reveal().chain(function(){(function(){b.dissolve();}).delay(c.duration||2000);});}});})();(function(){Fx.Scroll=new Class({Extends:Fx,options:{offset:{x:0,y:0},wheelStops:true},initialize:function(c,b){this.element=this.subject=document.id(c); -this.parent(b);if(typeOf(this.element)!="element"){this.element=document.id(this.element.getDocument().body);}if(this.options.wheelStops){var d=this.element,e=this.cancel.pass(false,this); -this.addEvent("start",function(){d.addEvent("mousewheel",e);},true);this.addEvent("complete",function(){d.removeEvent("mousewheel",e);},true);}},set:function(){var b=Array.flatten(arguments); -if(Browser.firefox){b=[Math.round(b[0]),Math.round(b[1])];}this.element.scrollTo(b[0],b[1]);return this;},compute:function(d,c,b){return[0,1].map(function(e){return Fx.compute(d[e],c[e],b); -});},start:function(c,d){if(!this.check(c,d)){return this;}var b=this.element.getScroll();return this.parent([b.x,b.y],[c,d]);},calculateScroll:function(g,f){var d=this.element,b=d.getScrollSize(),h=d.getScroll(),j=d.getSize(),c=this.options.offset,i={x:g,y:f}; -for(var e in i){if(!i[e]&&i[e]!==0){i[e]=h[e];}if(typeOf(i[e])!="number"){i[e]=b[e]-j[e];}i[e]+=c[e];}return[i.x,i.y];},toTop:function(){return this.start.apply(this,this.calculateScroll(false,0)); -},toLeft:function(){return this.start.apply(this,this.calculateScroll(0,false));},toRight:function(){return this.start.apply(this,this.calculateScroll("right",false)); -},toBottom:function(){return this.start.apply(this,this.calculateScroll(false,"bottom"));},toElement:function(d,e){e=e?Array.from(e):["x","y"];var c=a(this.element)?{x:0,y:0}:this.element.getScroll(); -var b=Object.map(document.id(d).getPosition(this.element),function(g,f){return e.contains(f)?g+c[f]:false;});return this.start.apply(this,this.calculateScroll(b.x,b.y)); -},toElementEdge:function(d,g,e){g=g?Array.from(g):["x","y"];d=document.id(d);var i={},f=d.getPosition(this.element),j=d.getSize(),h=this.element.getScroll(),b=this.element.getSize(),c={x:f.x+j.x,y:f.y+j.y}; -["x","y"].each(function(k){if(g.contains(k)){if(c[k]>h[k]+b[k]){i[k]=c[k]-b[k];}if(f[k]this.elements.length){e.splice(this.elements.length-1,e.length-this.elements.length); -}}var b=0;i=a=0;e.each(function(k){var j={};if(d){j.top=i-f[k].top-b;i+=f[k].height;}else{j.left=a-f[k].left;a+=f[k].width;}b=b+f[k].margin;c[k]=j;},this); -var g={};Array.clone(e).sort().each(function(j){g[j]=c[j];});this.start(g);this.currentOrder=e;return this;},rearrangeDOM:function(a){a=a||this.currentOrder; -var b=this.elements[0].getParent();var c=[];this.elements.setStyle("opacity",0);a.each(function(d){c.push(this.elements[d].inject(b).setStyles({top:0,left:0})); -},this);this.elements.setStyle("opacity",1);this.elements=$$(c);this.setDefaultOrder();return this;},getDefaultOrder:function(){return this.elements.map(function(b,a){return a; -});},getCurrentOrder:function(){return this.currentOrder;},forward:function(){return this.sort(this.getDefaultOrder());},backward:function(){return this.sort(this.getDefaultOrder().reverse()); -},reverse:function(){return this.sort(this.currentOrder.reverse());},sortByElements:function(a){return this.sort(a.map(function(b){return this.elements.indexOf(b); -},this));},swap:function(c,b){if(typeOf(c)=="element"){c=this.elements.indexOf(c);}if(typeOf(b)=="element"){b=this.elements.indexOf(b);}var a=Array.clone(this.currentOrder); -a[this.currentOrder.indexOf(c)]=b;a[this.currentOrder.indexOf(b)]=c;return this.sort(a);}});var Drag=new Class({Implements:[Events,Options],options:{snap:6,unit:"px",grid:false,style:true,limit:false,handle:false,invert:false,preventDefault:false,stopPropagation:false,modifiers:{x:"left",y:"top"}},initialize:function(){var b=Array.link(arguments,{options:Type.isObject,element:function(c){return c!=null; -}});this.element=document.id(b.element);this.document=this.element.getDocument();this.setOptions(b.options||{});var a=typeOf(this.options.handle);this.handles=((a=="array"||a=="collection")?$$(this.options.handle):document.id(this.options.handle))||this.element; -this.mouse={now:{},pos:{}};this.value={start:{},now:{}};this.selection=(Browser.ie)?"selectstart":"mousedown";if(Browser.ie&&!Drag.ondragstartFixed){document.ondragstart=Function.from(false); -Drag.ondragstartFixed=true;}this.bound={start:this.start.bind(this),check:this.check.bind(this),drag:this.drag.bind(this),stop:this.stop.bind(this),cancel:this.cancel.bind(this),eventStop:Function.from(false)}; -this.attach();},attach:function(){this.handles.addEvent("mousedown",this.bound.start);return this;},detach:function(){this.handles.removeEvent("mousedown",this.bound.start); -return this;},start:function(a){var j=this.options;if(a.rightClick){return;}if(j.preventDefault){a.preventDefault();}if(j.stopPropagation){a.stopPropagation(); -}this.mouse.start=a.page;this.fireEvent("beforeStart",this.element);var c=j.limit;this.limit={x:[],y:[]};var e,g;for(e in j.modifiers){if(!j.modifiers[e]){continue; -}var b=this.element.getStyle(j.modifiers[e]);if(b&&!b.match(/px$/)){if(!g){g=this.element.getCoordinates(this.element.getOffsetParent());}b=g[j.modifiers[e]]; -}if(j.style){this.value.now[e]=(b||0).toInt();}else{this.value.now[e]=this.element[j.modifiers[e]];}if(j.invert){this.value.now[e]*=-1;}this.mouse.pos[e]=a.page[e]-this.value.now[e]; -if(c&&c[e]){var d=2;while(d--){var f=c[e][d];if(f||f===0){this.limit[e][d]=(typeof f=="function")?f():f;}}}}if(typeOf(this.options.grid)=="number"){this.options.grid={x:this.options.grid,y:this.options.grid}; -}var h={mousemove:this.bound.check,mouseup:this.bound.cancel};h[this.selection]=this.bound.eventStop;this.document.addEvents(h);},check:function(a){if(this.options.preventDefault){a.preventDefault(); -}var b=Math.round(Math.sqrt(Math.pow(a.page.x-this.mouse.start.x,2)+Math.pow(a.page.y-this.mouse.start.y,2)));if(b>this.options.snap){this.cancel();this.document.addEvents({mousemove:this.bound.drag,mouseup:this.bound.stop}); -this.fireEvent("start",[this.element,a]).fireEvent("snap",this.element);}},drag:function(b){var a=this.options;if(a.preventDefault){b.preventDefault(); -}this.mouse.now=b.page;for(var c in a.modifiers){if(!a.modifiers[c]){continue;}this.value.now[c]=this.mouse.now[c]-this.mouse.pos[c];if(a.invert){this.value.now[c]*=-1; -}if(a.limit&&this.limit[c]){if((this.limit[c][1]||this.limit[c][1]===0)&&(this.value.now[c]>this.limit[c][1])){this.value.now[c]=this.limit[c][1];}else{if((this.limit[c][0]||this.limit[c][0]===0)&&(this.value.now[c]d.left&&b.xd.top);},this).getLast();if(this.overed!=a){if(this.overed){this.fireEvent("leave",[this.element,this.overed]); -}if(a){this.fireEvent("enter",[this.element,a]);}this.overed=a;}},drag:function(a){this.parent(a);if(this.options.checkDroppables&&this.droppables.length){this.checkDroppables(); -}},stop:function(a){this.checkDroppables();this.fireEvent("drop",[this.element,this.overed,a]);this.overed=null;return this.parent(a);}});Element.implement({makeDraggable:function(a){var b=new Drag.Move(this,a); -this.store("dragger",b);return b;}});var Slider=new Class({Implements:[Events,Options],Binds:["clickedElement","draggedKnob","scrolledElement"],options:{onTick:function(a){this.setKnobPosition(a); -},initialStep:0,snap:false,offset:0,range:false,wheel:false,steps:100,mode:"horizontal"},initialize:function(f,a,e){this.setOptions(e);e=this.options;this.element=document.id(f); -a=this.knob=document.id(a);this.previousChange=this.previousEnd=this.step=-1;var b={},d={x:false,y:false};switch(e.mode){case"vertical":this.axis="y";this.property="top"; -this.offset="offsetHeight";break;case"horizontal":this.axis="x";this.property="left";this.offset="offsetWidth";}this.setSliderDimensions();this.setRange(e.range); -if(a.getStyle("position")=="static"){a.setStyle("position","relative");}a.setStyle(this.property,-e.offset);d[this.axis]=this.property;b[this.axis]=[-e.offset,this.full-e.offset]; -var c={snap:0,limit:b,modifiers:d,onDrag:this.draggedKnob,onStart:this.draggedKnob,onBeforeStart:(function(){this.isDragging=true;}).bind(this),onCancel:function(){this.isDragging=false; -}.bind(this),onComplete:function(){this.isDragging=false;this.draggedKnob();this.end();}.bind(this)};if(e.snap){this.setSnap(c);}this.drag=new Drag(a,c); -this.attach();if(e.initialStep!=null){this.set(e.initialStep);}},attach:function(){this.element.addEvent("mousedown",this.clickedElement);if(this.options.wheel){this.element.addEvent("mousewheel",this.scrolledElement); -}this.drag.attach();return this;},detach:function(){this.element.removeEvent("mousedown",this.clickedElement).removeEvent("mousewheel",this.scrolledElement); -this.drag.detach();return this;},autosize:function(){this.setSliderDimensions().setKnobPosition(this.toPosition(this.step));this.drag.options.limit[this.axis]=[-this.options.offset,this.full-this.options.offset]; -if(this.options.snap){this.setSnap();}return this;},setSnap:function(a){if(!a){a=this.drag.options;}a.grid=Math.ceil(this.stepWidth);a.limit[this.axis][1]=this.full; -return this;},setKnobPosition:function(a){if(this.options.snap){a=this.toPosition(this.step);}this.knob.setStyle(this.property,a);return this;},setSliderDimensions:function(){this.full=this.element.measure(function(){this.half=this.knob[this.offset]/2; -return this.element[this.offset]-this.knob[this.offset]+(this.options.offset*2);}.bind(this));return this;},set:function(a){if(!((this.range>0)^(a0)^(a>this.max))){a=this.max;}this.step=Math.round(a);return this.checkStep().fireEvent("tick",this.toPosition(this.step)).end();},setRange:function(a,b){this.min=Array.pick([a[0],0]); -this.max=Array.pick([a[1],this.options.steps]);this.range=this.max-this.min;this.steps=this.options.steps||this.full;this.stepSize=Math.abs(this.range)/this.steps; -this.stepWidth=this.stepSize*this.full/Math.abs(this.range);if(a){this.set(Array.pick([b,this.step]).floor(this.min).max(this.max));}return this;},clickedElement:function(c){if(this.isDragging||c.target==this.knob){return; -}var b=this.range<0?-1:1,a=c.page[this.axis]-this.element.getPosition()[this.axis]-this.half;a=a.limit(-this.options.offset,this.full-this.options.offset); -this.step=Math.round(this.min+b*this.toStep(a));this.checkStep().fireEvent("tick",a).end();},scrolledElement:function(a){var b=(this.options.mode=="horizontal")?(a.wheel<0):(a.wheel>0); -this.set(this.step+(b?-1:1)*this.stepSize);a.stop();},draggedKnob:function(){var b=this.range<0?-1:1,a=this.drag.value.now[this.axis];a=a.limit(-this.options.offset,this.full-this.options.offset); -this.step=Math.round(this.min+b*this.toStep(a));this.checkStep();},checkStep:function(){var a=this.step;if(this.previousChange!=a){this.previousChange=a; -this.fireEvent("change",a);}return this;},end:function(){var a=this.step;if(this.previousEnd!==a){this.previousEnd=a;this.fireEvent("complete",a+"");}return this; -},toStep:function(a){var b=(a+this.options.offset)*this.stepSize/this.full*this.steps;return this.options.steps?Math.round(b-=b%this.stepSize):b;},toPosition:function(a){return(this.full*Math.abs(this.min-a))/(this.steps*this.stepSize)-this.options.offset; -}});var Sortables=new Class({Implements:[Events,Options],options:{opacity:1,clone:false,revert:false,handle:false,dragOptions:{},snap:4,constrain:false,preventDefault:false},initialize:function(a,b){this.setOptions(b); -this.elements=[];this.lists=[];this.idle=true;this.addLists($$(document.id(a)||a));if(!this.options.clone){this.options.revert=false;}if(this.options.revert){this.effect=new Fx.Morph(null,Object.merge({duration:250,link:"cancel"},this.options.revert)); -}},attach:function(){this.addLists(this.lists);return this;},detach:function(){this.lists=this.removeLists(this.lists);return this;},addItems:function(){Array.flatten(arguments).each(function(a){this.elements.push(a); -var b=a.retrieve("sortables:start",function(c){this.start.call(this,c,a);}.bind(this));(this.options.handle?a.getElement(this.options.handle)||a:a).addEvent("mousedown",b); -},this);return this;},addLists:function(){Array.flatten(arguments).each(function(a){this.lists.include(a);this.addItems(a.getChildren());},this);return this; -},removeItems:function(){return $$(Array.flatten(arguments).map(function(a){this.elements.erase(a);var b=a.retrieve("sortables:start");(this.options.handle?a.getElement(this.options.handle)||a:a).removeEvent("mousedown",b); -return a;},this));},removeLists:function(){return $$(Array.flatten(arguments).map(function(a){this.lists.erase(a);this.removeItems(a.getChildren());return a; -},this));},getClone:function(b,a){if(!this.options.clone){return new Element(a.tagName).inject(document.body);}if(typeOf(this.options.clone)=="function"){return this.options.clone.call(this,b,a,this.list); -}var c=a.clone(true).setStyles({margin:0,position:"absolute",visibility:"hidden",width:a.getStyle("width")}).addEvent("mousedown",function(d){a.fireEvent("mousedown",d); -});if(c.get("html").test("radio")){c.getElements("input[type=radio]").each(function(d,e){d.set("name","clone_"+e);if(d.get("checked")){a.getElements("input[type=radio]")[e].set("checked",true); -}});}return c.inject(this.list).setPosition(a.getPosition(a.getOffsetParent()));},getDroppables:function(){var a=this.list.getChildren().erase(this.clone).erase(this.element); -if(!this.options.constrain){a.append(this.lists).erase(this.list);}return a;},insert:function(c,b){var a="inside";if(this.lists.contains(b)){this.list=b; -this.drag.droppables=this.getDroppables();}else{a=this.element.getAllPrevious().contains(b)?"before":"after";}this.element.inject(b,a);this.fireEvent("sort",[this.element,this.clone]); -},start:function(b,a){if(!this.idle||b.rightClick||["button","input","a","textarea"].contains(b.target.get("tag"))){return;}this.idle=false;this.element=a; -this.opacity=a.getStyle("opacity");this.list=a.getParent();this.clone=this.getClone(b,a);this.drag=new Drag.Move(this.clone,Object.merge({preventDefault:this.options.preventDefault,snap:this.options.snap,container:this.options.constrain&&this.element.getParent(),droppables:this.getDroppables()},this.options.dragOptions)).addEvents({onSnap:function(){b.stop(); -this.clone.setStyle("visibility","visible");this.element.setStyle("opacity",this.options.opacity||0);this.fireEvent("start",[this.element,this.clone]); -}.bind(this),onEnter:this.insert.bind(this),onCancel:this.end.bind(this),onComplete:this.end.bind(this)});this.clone.inject(this.element,"before");this.drag.start(b); -},end:function(){this.drag.detach();this.element.setStyle("opacity",this.opacity);if(this.effect){var b=this.element.getStyles("width","height"),d=this.clone,c=d.computePosition(this.element.getPosition(this.clone.getOffsetParent())); -var a=function(){this.removeEvent("cancel",a);d.destroy();};this.effect.element=d;this.effect.start({top:c.top,left:c.left,width:b.width,height:b.height,opacity:0.25}).addEvent("cancel",a).chain(a); -}else{this.clone.destroy();}this.reset();},reset:function(){this.idle=true;this.fireEvent("complete",this.element);},serialize:function(){var c=Array.link(arguments,{modifier:Type.isFunction,index:function(d){return d!=null; -}});var b=this.lists.map(function(d){return d.getChildren().map(c.modifier||function(e){return e.get("id");},this);},this);var a=c.index;if(this.lists.length==1){a=0; -}return(a||a===0)&&a>=0&&a=3){d="rgb";c=Array.slice(arguments,0,3);}else{if(typeof c=="string"){if(c.match(/rgb/)){c=c.rgbToHex().hexToRgb(true); -}else{if(c.match(/hsb/)){c=c.hsbToRgb();}else{c=c.hexToRgb(true);}}}}d=d||"rgb";switch(d){case"hsb":var b=c;c=c.hsbToRgb();c.hsb=b;break;case"hex":c=c.hexToRgb(true); -break;}c.rgb=c.slice(0,3);c.hsb=c.hsb||c.rgbToHsb();c.hex=c.rgbToHex();return Object.append(c,this);});a.implement({mix:function(){var b=Array.slice(arguments); -var d=(typeOf(b.getLast())=="number")?b.pop():50;var c=this.slice();b.each(function(e){e=new a(e);for(var f=0;f<3;f++){c[f]=Math.round((c[f]/100*(100-d))+(e[f]/100*d)); -}});return new a(c,"rgb");},invert:function(){return new a(this.map(function(b){return 255-b;}));},setHue:function(b){return new a([b,this.hsb[1],this.hsb[2]],"hsb"); -},setSaturation:function(b){return new a([this.hsb[0],b,this.hsb[2]],"hsb");},setBrightness:function(b){return new a([this.hsb[0],this.hsb[1],b],"hsb"); -}});this.$RGB=function(e,d,c){return new a([e,d,c],"rgb");};this.$HSB=function(e,d,c){return new a([e,d,c],"hsb");};this.$HEX=function(b){return new a(b,"hex"); -};Array.implement({rgbToHsb:function(){var c=this[0],d=this[1],k=this[2],h=0;var j=Math.max(c,d,k),f=Math.min(c,d,k);var l=j-f;var i=j/255,g=(j!=0)?l/j:0; -if(g!=0){var e=(j-c)/l;var b=(j-d)/l;var m=(j-k)/l;if(c==j){h=m-b;}else{if(d==j){h=2+e-m;}else{h=4+b-e;}}h/=6;if(h<0){h++;}}return[Math.round(h*360),Math.round(g*100),Math.round(i*100)]; -},hsbToRgb:function(){var d=Math.round(this[2]/100*255);if(this[1]==0){return[d,d,d];}else{var b=this[0]%360;var g=b%60;var h=Math.round((this[2]*(100-this[1]))/10000*255); -var e=Math.round((this[2]*(6000-this[1]*g))/600000*255);var c=Math.round((this[2]*(6000-this[1]*(60-g)))/600000*255);switch(Math.floor(b/60)){case 0:return[d,c,h]; -case 1:return[e,d,h];case 2:return[h,d,c];case 3:return[h,e,d];case 4:return[c,h,d];case 5:return[d,h,e];}}return false;}});String.implement({rgbToHsb:function(){var b=this.match(/\d{1,3}/g); -return(b)?b.rgbToHsb():null;},hsbToRgb:function(){var b=this.match(/\d{1,3}/g);return(b)?b.hsbToRgb():null;}});})();Hash.Cookie=new Class({Extends:Cookie,options:{autoSave:true},initialize:function(b,a){this.parent(b,a); -this.load();},save:function(){var a=JSON.encode(this.hash);if(!a||a.length>4096){return false;}if(a=="{}"){this.dispose();}else{this.write(a);}return true; -},load:function(){this.hash=new Hash(JSON.decode(this.read(),true));return this;}});Hash.each(Hash.prototype,function(b,a){if(typeof b=="function"){Hash.Cookie.implement(a,function(){var c=b.apply(this.hash,arguments); -if(this.options.autoSave){this.save();}return c;});}});var HtmlTable=new Class({Implements:[Options,Events,Class.Occlude],options:{properties:{cellpadding:0,cellspacing:0,border:0},rows:[],headers:[],footers:[]},property:"HtmlTable",initialize:function(){var a=Array.link(arguments,{options:Type.isObject,table:Type.isElement,id:Type.isString}); -this.setOptions(a.options);if(!a.table&&a.id){a.table=document.id(a.id);}this.element=a.table||new Element("table",this.options.properties);if(this.occlude()){return this.occluded; -}this.build();},build:function(){this.element.store("HtmlTable",this);this.body=document.id(this.element.tBodies[0])||new Element("tbody").inject(this.element); -$$(this.body.rows);if(this.options.headers.length){this.setHeaders(this.options.headers);}else{this.thead=document.id(this.element.tHead);}if(this.thead){this.head=this.getHead(); -}if(this.options.footers.length){this.setFooters(this.options.footers);}this.tfoot=document.id(this.element.tFoot);if(this.tfoot){this.foot=document.id(this.tfoot.rows[0]); -}this.options.rows.each(function(a){this.push(a);},this);},toElement:function(){return this.element;},empty:function(){this.body.empty();return this;},set:function(e,a){var d=(e=="headers")?"tHead":"tFoot",b=d.toLowerCase(); -this[b]=(document.id(this.element[d])||new Element(b).inject(this.element,"top")).empty();var c=this.push(a,{},this[b],e=="headers"?"th":"td");if(e=="headers"){this.head=this.getHead(); -}else{this.foot=this.getHead();}return c;},getHead:function(){var a=this.thead.rows;return a.length>1?$$(a):a.length?document.id(a[0]):false;},setHeaders:function(a){this.set("headers",a); -return this;},setFooters:function(a){this.set("footers",a);return this;},update:function(d,e,a){var b=d.getChildren(a||"td"),c=b.length-1;e.each(function(i,f){var j=b[f]||new Element(a||"td").inject(d),h=(i?i.content:"")||i,g=typeOf(h); -if(i&&i.properties){j.set(i.properties);}if(/(element(s?)|array|collection)/.test(g)){j.empty().adopt(h);}else{j.set("html",h);}if(f>c){b.push(j);}else{b[f]=j; -}});return{tr:d,tds:b};},push:function(e,c,d,a,b){if(typeOf(e)=="element"&&e.get("tag")=="tr"){e.inject(d||this.body,b);return{tr:e,tds:e.getChildren("td")}; -}return this.update(new Element("tr",c).inject(d||this.body,b),e,a);},pushMany:function(d,c,e,a,b){return d.map(function(f){return this.push(f,c,e,a,b); -},this);}});["adopt","inject","wraps","grab","replaces","dispose"].each(function(a){HtmlTable.implement(a,function(){this.element[a].apply(this.element,arguments); -return this;});});(function(){Events.Pseudos=function(h,e,f){var d="_monitorEvents:";var c=function(i){return{store:i.store?function(j,k){i.store(d+j,k); -}:function(j,k){(i._monitorEvents||(i._monitorEvents={}))[j]=k;},retrieve:i.retrieve?function(j,k){return i.retrieve(d+j,k);}:function(j,k){if(!i._monitorEvents){return k; -}return i._monitorEvents[j]||k;}};};var g=function(k){if(k.indexOf(":")==-1||!h){return null;}var j=Slick.parse(k).expressions[0][0],p=j.pseudos,i=p.length,o=[]; -while(i--){var n=p[i].key,m=h[n];if(m!=null){o.push({event:j.tag,value:p[i].value,pseudo:n,original:k,listener:m});}}return o.length?o:null;};return{addEvent:function(m,p,j){var n=g(m); -if(!n){return e.call(this,m,p,j);}var k=c(this),r=k.retrieve(m,[]),i=n[0].event,l=Array.slice(arguments,2),o=p,q=this;n.each(function(s){var t=s.listener,u=o; -if(t==false){i+=":"+s.pseudo+"("+s.value+")";}else{o=function(){t.call(q,s,u,arguments,o);};}});r.include({type:i,event:p,monitor:o});k.store(m,r);if(m!=i){e.apply(this,[m,p].concat(l)); -}return e.apply(this,[i,o].concat(l));},removeEvent:function(m,l){var k=g(m);if(!k){return f.call(this,m,l);}var n=c(this),j=n.retrieve(m);if(!j){return this; -}var i=Array.slice(arguments,2);f.apply(this,[m,l].concat(i));j.each(function(o,p){if(!l||o.event==l){f.apply(this,[o.type,o.monitor].concat(i));}delete j[p]; -},this);n.store(m,j);return this;}};};var b={once:function(e,f,d,c){f.apply(this,d);this.removeEvent(e.event,c).removeEvent(e.original,f);},throttle:function(d,e,c){if(!e._throttled){e.apply(this,c); -e._throttled=setTimeout(function(){e._throttled=false;},d.value||250);}},pause:function(d,e,c){clearTimeout(e._pause);e._pause=e.delay(d.value||250,this,c); -}};Events.definePseudo=function(c,d){b[c]=d;return this;};Events.lookupPseudo=function(c){return b[c];};var a=Events.prototype;Events.implement(Events.Pseudos(b,a.addEvent,a.removeEvent)); -["Request","Fx"].each(function(c){if(this[c]){this[c].implement(Events.prototype);}});})();(function(){var d={relay:false},c=["once","throttle","pause"],b=c.length; -while(b--){d[c[b]]=Events.lookupPseudo(c[b]);}DOMEvent.definePseudo=function(e,f){d[e]=f;return this;};var a=Element.prototype;[Element,Window,Document].invoke("implement",Events.Pseudos(d,a.addEvent,a.removeEvent)); -})();(function(){var a="$moo:keys-pressed",b="$moo:keys-keyup";DOMEvent.definePseudo("keys",function(d,e,c){var g=c[0],f=[],h=this.retrieve(a,[]);f.append(d.value.replace("++",function(){f.push("+"); -return"";}).split("+"));h.include(g.key);if(f.every(function(j){return h.contains(j);})){e.apply(this,c);}this.store(a,h);if(!this.retrieve(b)){var i=function(j){(function(){h=this.retrieve(a,[]).erase(j.key); -this.store(a,h);}).delay(0,this);};this.store(b,i).addEvent("keyup",i);}});DOMEvent.defineKeys({"16":"shift","17":"control","18":"alt","20":"capslock","33":"pageup","34":"pagedown","35":"end","36":"home","144":"numlock","145":"scrolllock","186":";","187":"=","188":",","190":".","191":"/","192":"`","219":"[","220":"\\","221":"]","222":"'","107":"+"}).defineKey(Browser.firefox?109:189,"-"); -})();(function(){var a=this.Keyboard=new Class({Extends:Events,Implements:[Options],options:{defaultEventType:"keydown",active:false,manager:null,events:{},nonParsedEvents:["activate","deactivate","onactivate","ondeactivate","changed","onchanged"]},initialize:function(f){if(f&&f.manager){this._manager=f.manager; -delete f.manager;}this.setOptions(f);this._setup();},addEvent:function(h,g,f){return this.parent(a.parse(h,this.options.defaultEventType,this.options.nonParsedEvents),g,f); -},removeEvent:function(g,f){return this.parent(a.parse(g,this.options.defaultEventType,this.options.nonParsedEvents),f);},toggleActive:function(){return this[this.isActive()?"deactivate":"activate"](); -},activate:function(f){if(f){if(f.isActive()){return this;}if(this._activeKB&&f!=this._activeKB){this.previous=this._activeKB;this.previous.fireEvent("deactivate"); -}this._activeKB=f.fireEvent("activate");a.manager.fireEvent("changed");}else{if(this._manager){this._manager.activate(this);}}return this;},isActive:function(){return this._manager?(this._manager._activeKB==this):(a.manager==this); -},deactivate:function(f){if(f){if(f===this._activeKB){this._activeKB=null;f.fireEvent("deactivate");a.manager.fireEvent("changed");}}else{if(this._manager){this._manager.deactivate(this); -}}return this;},relinquish:function(){if(this.isActive()&&this._manager&&this._manager.previous){this._manager.activate(this._manager.previous);}else{this.deactivate(); -}return this;},manage:function(f){if(f._manager){f._manager.drop(f);}this._instances.push(f);f._manager=this;if(!this._activeKB){this.activate(f);}return this; -},drop:function(f){f.relinquish();this._instances.erase(f);if(this._activeKB==f){if(this.previous&&this._instances.contains(this.previous)){this.activate(this.previous); -}else{this._activeKB=this._instances[0];}}return this;},trace:function(){a.trace(this);},each:function(f){a.each(this,f);},_instances:[],_disable:function(f){if(this._activeKB==f){this._activeKB=null; -}},_setup:function(){this.addEvents(this.options.events);if(a.manager&&!this._manager){a.manager.manage(this);}if(this.options.active){this.activate(); -}else{this.relinquish();}},_handle:function(h,g){if(h.preventKeyboardPropagation){return;}var f=!!this._manager;if(f&&this._activeKB){this._activeKB._handle(h,g); -if(h.preventKeyboardPropagation){return;}}this.fireEvent(g,h);if(!f&&this._activeKB){this._activeKB._handle(h,g);}}});var b={};var c=["shift","control","alt","meta"]; -var e=/^(?:shift|control|ctrl|alt|meta)$/;a.parse=function(h,g,k){if(k&&k.contains(h.toLowerCase())){return h;}h=h.toLowerCase().replace(/^(keyup|keydown):/,function(m,l){g=l; -return"";});if(!b[h]){var f,j={};h.split("+").each(function(l){if(e.test(l)){j[l]=true;}else{f=l;}});j.control=j.control||j.ctrl;var i=[];c.each(function(l){if(j[l]){i.push(l); -}});if(f){i.push(f);}b[h]=i.join("+");}return g+":keys("+b[h]+")";};a.each=function(f,g){var h=f||a.manager;while(h){g.run(h);h=h._activeKB;}};a.stop=function(f){f.preventKeyboardPropagation=true; -};a.manager=new a({active:true});a.trace=function(f){f=f||a.manager;var g=window.console&&console.log;if(g){console.log("the following items have focus: "); -}a.each(f,function(h){if(g){console.log(document.id(h.widget)||h.wiget||h);}});};var d=function(g){var f=[];c.each(function(h){if(g[h]){f.push(h);}});if(!e.test(g.key)){f.push(g.key); -}a.manager._handle(g,g.type+":keys("+f.join("+")+")");};document.addEvents({keyup:d,keydown:d});})(); \ No newline at end of file diff --git a/src/webui/www/public/scripts/parametrics.js b/src/webui/www/public/scripts/parametrics.js deleted file mode 100644 index f95dc7680..000000000 --- a/src/webui/www/public/scripts/parametrics.js +++ /dev/null @@ -1,224 +0,0 @@ -/* - -Script: Parametrics.js - Initializes the GUI property sliders. - -Copyright: - Copyright (c) 2007-2008 Greg Houston, . - -License: - MIT-style license. - -Requires: - Core.js, Window.js - -*/ -MochaUI.extend({ - addUpLimitSlider: function(hashes) { - if ($('uplimitSliderarea')) { - var windowOptions = MochaUI.Windows.windowOptions; - var sliderFirst = true; - // Get global upload limit - var maximum = 500; - var req = new Request({ - url: 'command/getGlobalUpLimit', - method: 'post', - data: {}, - onSuccess: function(data) { - if (data) { - var tmp = data.toInt(); - if (tmp > 0) { - maximum = tmp / 1024.0; - } - else { - if (hashes[0] == "global") - maximum = 10000; - else - maximum = 1000; - } - } - // Get torrents upload limit - // And create slider - if (hashes[0] == 'global') { - var up_limit = maximum; - if (up_limit < 0) up_limit = 0; - maximum = 10000; - var mochaSlide = new Slider($('uplimitSliderarea'), $('uplimitSliderknob'), { - steps: maximum, - offset: 0, - initialStep: up_limit.round(), - onChange: function(pos) { - if (pos > 0) { - $('uplimitUpdatevalue').value = pos; - $('upLimitUnit').style.visibility = "visible"; - } - else { - $('uplimitUpdatevalue').value = '∞'; - $('upLimitUnit').style.visibility = "hidden"; - } - }.bind(this) - }); - // Set default value - if (up_limit === 0) { - $('uplimitUpdatevalue').value = '∞'; - $('upLimitUnit').style.visibility = "hidden"; - } - else { - $('uplimitUpdatevalue').value = up_limit.round(); - $('upLimitUnit').style.visibility = "visible"; - } - } - else { - var req = new Request.JSON({ - url: 'command/getTorrentsUpLimit', - noCache : true, - method: 'post', - data: { - hashes: hashes.join('|') - }, - onSuccess: function(data) { - if (data) { - var up_limit = data[hashes[0]]; - for(var key in data) - if (up_limit != data[key]) { - up_limit = 0; - break; - } - if (up_limit < 0) up_limit = 0; - var mochaSlide = new Slider($('uplimitSliderarea'), $('uplimitSliderknob'), { - steps: maximum, - offset: 0, - initialStep: (up_limit / 1024.0).round(), - onChange: function(pos) { - if (pos > 0) { - $('uplimitUpdatevalue').value = pos; - $('upLimitUnit').style.visibility = "visible"; - } - else { - $('uplimitUpdatevalue').value = '∞'; - $('upLimitUnit').style.visibility = "hidden"; - } - }.bind(this) - }); - // Set default value - if (up_limit === 0) { - $('uplimitUpdatevalue').value = '∞'; - $('upLimitUnit').style.visibility = "hidden"; - } - else { - $('uplimitUpdatevalue').value = (up_limit / 1024.0).round(); - $('upLimitUnit').style.visibility = "visible"; - } - } - } - }).send(); - } - } - }).send(); - } - }, - - addDlLimitSlider: function(hashes) { - if ($('dllimitSliderarea')) { - var windowOptions = MochaUI.Windows.windowOptions; - var sliderFirst = true; - // Get global upload limit - var maximum = 500; - var req = new Request({ - url: 'command/getGlobalDlLimit', - method: 'post', - data: {}, - onSuccess: function(data) { - if (data) { - var tmp = data.toInt(); - if (tmp > 0) { - maximum = tmp / 1024.0; - } - else { - if (hashes[0] == "global") - maximum = 10000; - else - maximum = 1000; - } - } - // Get torrents download limit - // And create slider - if (hashes[0] == 'global') { - var dl_limit = maximum; - if (dl_limit < 0) dl_limit = 0; - maximum = 10000; - var mochaSlide = new Slider($('dllimitSliderarea'), $('dllimitSliderknob'), { - steps: maximum, - offset: 0, - initialStep: dl_limit.round(), - onChange: function(pos) { - if (pos > 0) { - $('dllimitUpdatevalue').value = pos; - $('dlLimitUnit').style.visibility = "visible"; - } - else { - $('dllimitUpdatevalue').value = '∞'; - $('dlLimitUnit').style.visibility = "hidden"; - } - }.bind(this) - }); - // Set default value - if (dl_limit === 0) { - $('dllimitUpdatevalue').value = '∞'; - $('dlLimitUnit').style.visibility = "hidden"; - } - else { - $('dllimitUpdatevalue').value = dl_limit.round(); - $('dlLimitUnit').style.visibility = "visible"; - } - } - else { - var req = new Request.JSON({ - url: 'command/getTorrentsDlLimit', - noCache : true, - method: 'post', - data: { - hashes: hashes.join('|') - }, - onSuccess: function(data) { - if (data) { - var dl_limit = data[hashes[0]]; - for(var key in data) - if (dl_limit != data[key]) { - dl_limit = 0; - break; - } - if (dl_limit < 0) dl_limit = 0; - var mochaSlide = new Slider($('dllimitSliderarea'), $('dllimitSliderknob'), { - steps: maximum, - offset: 0, - initialStep: (dl_limit / 1024.0).round(), - onChange: function(pos) { - if (pos > 0) { - $('dllimitUpdatevalue').value = pos; - $('dlLimitUnit').style.visibility = "visible"; - } - else { - $('dllimitUpdatevalue').value = '∞'; - $('dlLimitUnit').style.visibility = "hidden"; - } - }.bind(this) - }); - // Set default value - if (dl_limit === 0) { - $('dllimitUpdatevalue').value = '∞'; - $('dlLimitUnit').style.visibility = "hidden"; - } - else { - $('dllimitUpdatevalue').value = (dl_limit / 1024.0).round(); - $('dlLimitUnit').style.visibility = "visible"; - } - } - } - }).send(); - } - } - }).send(); - } - } -}); diff --git a/src/webui/www/public/scripts/progressbar.js b/src/webui/www/public/scripts/progressbar.js deleted file mode 100644 index 880670ae8..000000000 --- a/src/webui/www/public/scripts/progressbar.js +++ /dev/null @@ -1,110 +0,0 @@ -var ProgressBar = new Class({ - initialize: function(value, parameters) { - var vals = { - 'id': 'progressbar_' + (ProgressBars++), - 'value': $pick(value, 0), - 'width': 0, - 'height': 0, - 'darkbg': '#006', - 'darkfg': '#fff', - 'lightbg': '#fff', - 'lightfg': '#000' - }; - if (parameters && $type(parameters) == 'object') $extend(vals, parameters); - if (vals.height < 12) vals.height = 12; - var obj = new Element('div', { - 'id': vals.id, - 'class': 'progressbar_wrapper', - 'styles': { - 'border': '1px solid #000', - 'width': vals.width, - 'height': vals.height, - 'position': 'relative', - 'margin': '0 auto' - } - }); - obj.vals = vals; - obj.vals.value = $pick(value, 0); // Fix by Chris - obj.vals.dark = new Element('div', { - 'id': vals.id + '_dark', - 'class': 'progressbar_dark', - 'styles': { - 'width': vals.width, - 'height': vals.height, - 'background': vals.darkbg, - 'color': vals.darkfg, - 'position': 'absolute', - 'text-align': 'center', - 'left': 0, - 'top': 0, - 'line-height': vals.height - } - }); - obj.vals.light = new Element('div', { - 'id': vals.id + '_light', - 'class': 'progressbar_light', - 'styles': { - 'width': vals.width, - 'height': vals.height, - 'background': vals.lightbg, - 'color': vals.lightfg, - 'position': 'absolute', - 'text-align': 'center', - 'left': 0, - 'top': 0, - 'line-height': vals.height - } - }); - obj.appendChild(obj.vals.dark); - obj.appendChild(obj.vals.light); - obj.getValue = ProgressBar_getValue; - obj.setValue = ProgressBar_setValue; - obj.setWidth = ProgressBar_setWidth; - if (vals.width) obj.setValue(vals.value); - else setTimeout('ProgressBar_checkForParent("' + obj.id + '")', 1); - return obj; - } -}); - -function ProgressBar_getValue() { - return this.vals.value; -} - -function ProgressBar_setValue(value) { - value = parseFloat(value); - if (isNaN(value)) value = 0; - if (value > 100) value = 100; - if (value < 0) value = 0; - this.vals.value = value; - this.vals.dark.empty(); - this.vals.light.empty(); - this.vals.dark.appendText(value + '%'); - this.vals.light.appendText(value + '%'); - var r = parseInt(this.vals.width * (value / 100)); - this.vals.dark.setStyle('clip', 'rect(0,' + r + 'px,' + this.vals.height + 'px,0)'); - this.vals.light.setStyle('clip', 'rect(0,' + this.vals.width + 'px,' + this.vals.height + 'px,' + r + 'px)'); -} - -function ProgressBar_setWidth(value) { - if (this.vals.width !== value) { - this.vals.width = value; - this.setStyle('width', value); - this.vals.dark.setStyle('width', value); - this.vals.light.setStyle('width', value); - this.setValue(this.vals.value); - } -} - -function ProgressBar_checkForParent(id) { - var obj = $(id); - if (!obj) return; - if (!obj.parentNode) return setTimeout('ProgressBar_checkForParent("' + id + '")', 1); - obj.setStyle('width', '100%'); - var w = obj.offsetWidth; - obj.vals.dark.setStyle('width', w); - obj.vals.light.setStyle('width', w); - obj.vals.width = w; - obj.setValue(obj.vals.value); -} - -var ProgressBars = 0; diff --git a/src/webui/www/public/scripts/prop-files.js b/src/webui/www/public/scripts/prop-files.js deleted file mode 100644 index 89b98a58f..000000000 --- a/src/webui/www/public/scripts/prop-files.js +++ /dev/null @@ -1,351 +0,0 @@ -var is_seed = true; -var current_hash = ""; - -if (!(Browser.name == "ie" && Browser.version < 9)) { - $("all_files_cb").removeClass("tristate"); - $("all_files_cb").removeClass("partial"); - $("all_files_cb").removeClass("checked"); - $("tristate_cb").style.display = "inline"; -} - -var setCBState = function(state) { - if (Browser.name == "ie" && Browser.version < 9) { - if (state == "partial") { - if (!$("all_files_cb").hasClass("partial")) { - $("all_files_cb").removeClass("checked"); - $("all_files_cb").addClass("partial"); - } - return; - } - if (state == "checked") { - if (!$("all_files_cb").hasClass("checked")) { - $("all_files_cb").removeClass("partial"); - $("all_files_cb").addClass("checked"); - } - return; - } - $("all_files_cb").removeClass("partial"); - $("all_files_cb").removeClass("checked"); - } - else { - if (state == "partial") { - $("tristate_cb").indeterminate = true; - } - else if (state == "checked") { - $("tristate_cb").indeterminate = false; - $("tristate_cb").checked = true; - } - else { - $("tristate_cb").indeterminate = false; - $("tristate_cb").checked = false; - } - } -}; - -var switchCBState = function() { - // Uncheck - if ($("all_files_cb").hasClass("partial")) { - $("all_files_cb").removeClass("partial"); - // Uncheck all checkboxes - $$('input.DownloadedCB').each(function(item, index) { - item.erase("checked"); - setFilePriority(index, 0); - }); - return; - } - if ($("all_files_cb").hasClass("checked")) { - $("all_files_cb").removeClass("checked"); - // Uncheck all checkboxes - $$('input.DownloadedCB').each(function(item, index) { - item.erase("checked"); - setFilePriority(index, 0); - }); - return; - } - // Check - $("all_files_cb").addClass("checked"); - // Check all checkboxes - $$('input.DownloadedCB').each(function(item, index) { - item.set("checked", "checked"); - setFilePriority(index, 1); - }); -}; - -var allCBChecked = function() { - var CBs = $$('input.DownloadedCB'); - for (var i = 0; i < CBs.length; i += 1) { - var item = CBs[i]; - if (!$defined(item.get('checked')) || !item.get('checked')) - return false; - } - return true; -}; - -var allCBUnchecked = function() { - var CBs = $$('input.DownloadedCB'); - for (var i = 0; i < CBs.length; i += 1) { - var item = CBs[i]; - if ($defined(item.get('checked')) && item.get('checked')) - return false; - } - return true; -}; - -var setFilePriority = function(id, priority) { - if (current_hash === "") return; - new Request({ - url: 'command/setFilePrio', - method: 'post', - data: { - 'hash': current_hash, - 'id': id, - 'priority': priority - } - }).send(); - // Display or add combobox - if (priority > 0) { - $('comboPrio' + id).set("value", 1); - $('comboPrio' + id).removeClass("invisible"); - } - else { - $('comboPrio' + id).addClass("invisible"); - } -}; - -var createDownloadedCB = function(id, downloaded) { - var CB = new Element('input'); - CB.set('type', 'checkbox'); - if (downloaded) - CB.set('checked', 'checked'); - CB.set('id', 'cbPrio' + id); - CB.set('class', 'DownloadedCB'); - CB.addEvent('change', function(e) { - var checked = 0; - if ($defined($('cbPrio' + id).get('checked')) && $('cbPrio' + id).get('checked')) - checked = 1; - setFilePriority(id, checked); - if (allCBChecked()) { - setCBState("checked"); - } - else { - if (allCBUnchecked()) { - setCBState("unchecked"); - } - else { - setCBState("partial"); - } - } - }); - return CB; -}; - -var createPriorityCombo = function(id, selected_prio) { - var select = new Element('select'); - select.set('id', 'comboPrio' + id); - select.addEvent('change', function(e) { - var new_prio = $('comboPrio' + id).get('value'); - setFilePriority(id, new_prio); - }); - var opt = new Element("option"); - opt.set('value', '1'); - opt.set('html', "QBT_TR(Normal)QBT_TR[CONTEXT=PropListDelegate]"); - if (selected_prio <= 1) - opt.setAttribute('selected', ''); - opt.injectInside(select); - opt = new Element("option"); - opt.set('value', '2'); - opt.set('html', "QBT_TR(High)QBT_TR[CONTEXT=PropListDelegate]"); - if (selected_prio == 2) - opt.setAttribute('selected', ''); - opt.injectInside(select); - opt = new Element("option"); - opt.set('value', '7'); - opt.set('html', "QBT_TR(Maximum)QBT_TR[CONTEXT=PropListDelegate]"); - if (selected_prio == 7) - opt.setAttribute('selected', ''); - opt.injectInside(select); - if (is_seed || selected_prio < 1) { - select.addClass("invisible"); - } - else { - select.removeClass("invisible"); - } - select.addClass("combo_priority"); - return select; -}; - -var filesDynTable = new Class({ - - initialize: function() {}, - - setup: function(table) { - this.table = $(table); - this.rows = new Hash(); - }, - - removeRow: function(id) { - if (this.rows.has(id)) { - var tr = this.rows.get(id); - tr.dispose(); - this.rows.erase(id); - return true; - } - return false; - }, - - removeAllRows: function() { - this.rows.each(function(tr, id) { - this.removeRow(id); - }.bind(this)); - }, - - updateRow: function(tr, row, id) { - var tds = tr.getElements('td'); - for (var i = 0; i < row.length; i++) { - switch (i) { - case 0: - if (row[i] > 0) - tds[i].getChildren('input')[0].set('checked', 'checked'); - else - tds[i].getChildren('input')[0].removeProperty('checked'); - break; - case 3: - $('pbf_' + id).setValue(row[i].toFloat()); - break; - case 4: - if (!is_seed && row[i] > 0) { - tds[i].getChildren('select').set('value', row[i]); - $('comboPrio' + id).removeClass("invisible"); - } - else { - if (!$('comboPrio' + id).hasClass("invisible")) - $('comboPrio' + id).addClass("invisible"); - } - break; - default: - tds[i].set('html', row[i]); - } - } - return true; - }, - - insertRow: function(id, row) { - if (this.rows.has(id)) { - var tableRow = this.rows.get(id); - this.updateRow(tableRow, row, id); - return; - } - //this.removeRow(id); - var tr = new Element('tr'); - this.rows.set(id, tr); - for (var i = 0; i < row.length; i++) { - var td = new Element('td'); - switch (i) { - case 0: - var tree_img = new Element('img', { - src: 'images/L.gif', - style: 'margin-bottom: -2px' - }); - td.adopt(tree_img, createDownloadedCB(id, row[i])); - break; - case 1: - td.set('html', row[i]); - td.set('title', row[i]); - break; - case 3: - td.adopt(new ProgressBar(row[i].toFloat(), { - 'id': 'pbf_' + id, - 'width': 80 - })); - break; - case 4: - td.adopt(createPriorityCombo(id, row[i])); - break; - default: - td.set('html', row[i]); - break; - } - td.injectInside(tr); - } - tr.injectInside(this.table); - }, -}); - -var loadTorrentFilesDataTimer; -var loadTorrentFilesData = function() { - if ($('prop_files').hasClass('invisible') || - $('propertiesPanel_collapseToggle').hasClass('panel-expand')) { - // Tab changed, don't do anything - return; - } - var new_hash = torrentsTable.getCurrentTorrentHash(); - if (new_hash === "") { - fTable.removeAllRows(); - clearTimeout(loadTorrentFilesDataTimer); - loadTorrentFilesDataTimer = loadTorrentFilesData.delay(5000); - return; - } - if (new_hash != current_hash) { - fTable.removeAllRows(); - current_hash = new_hash; - } - var url = 'query/propertiesFiles/' + current_hash; - var request = new Request.JSON({ - url: url, - noCache: true, - method: 'get', - onFailure: function() { - $('error_div').set('html', 'QBT_TR(qBittorrent client is not reachable)QBT_TR[CONTEXT=HttpServer]'); - clearTimeout(loadTorrentFilesDataTimer); - loadTorrentFilesDataTimer = loadTorrentFilesData.delay(10000); - }, - onSuccess: function(files) { - $('error_div').set('html', ''); - if (files) { - // Update Trackers data - var i = 0; - files.each(function(file) { - if (i === 0) { - is_seed = file.is_seed; - } - var row = []; - row.length = 4; - row[0] = file.priority; - row[1] = escapeHtml(file.name); - row[2] = friendlyUnit(file.size, false); - row[3] = (file.progress * 100).round(1); - if (row[3] == 100.0 && file.progress < 1.0) - row[3] = 99.9; - row[4] = file.priority; - fTable.insertRow(i, row); - i++; - }.bind(this)); - // Set global CB state - if (allCBChecked()) { - setCBState("checked"); - } - else { - if (allCBUnchecked()) { - setCBState("unchecked"); - } - else { - setCBState("partial"); - } - } - } - else { - fTable.removeAllRows(); - } - clearTimeout(loadTorrentFilesDataTimer); - loadTorrentFilesDataTimer = loadTorrentFilesData.delay(5000); - } - }).send(); -}; - -var updateTorrentFilesData = function() { - clearTimeout(loadTorrentFilesDataTimer); - loadTorrentFilesData(); -}; - -fTable = new filesDynTable(); -fTable.setup($('filesTable')); diff --git a/src/webui/www/public/scripts/prop-general.js b/src/webui/www/public/scripts/prop-general.js deleted file mode 100644 index 346404c7d..000000000 --- a/src/webui/www/public/scripts/prop-general.js +++ /dev/null @@ -1,169 +0,0 @@ -var clearData = function() { - $('time_elapsed').set('html', ''); - $('eta').set('html', ''); - $('nb_connections').set('html', ''); - $('total_downloaded').set('html', ''); - $('total_uploaded').set('html', ''); - $('dl_speed').set('html', ''); - $('up_speed').set('html', ''); - $('dl_limit').set('html', ''); - $('up_limit').set('html', ''); - $('total_wasted').set('html', ''); - $('seeds').set('html', ''); - $('peers').set('html', ''); - $('share_ratio').set('html', ''); - $('reannounce').set('html', ''); - $('last_seen').set('html', ''); - $('total_size').set('html', ''); - $('pieces').set('html', ''); - $('created_by').set('html', ''); - $('addition_date').set('html', ''); - $('completion_date').set('html', ''); - $('creation_date').set('html', ''); - $('torrent_hash').set('html', ''); - $('save_path').set('html', ''); - $('comment').set('html', ''); -}; - -var loadTorrentDataTimer; -var loadTorrentData = function() { - if ($('prop_general').hasClass('invisible') || - $('propertiesPanel_collapseToggle').hasClass('panel-expand')) { - // Tab changed, don't do anything - return; - } - var current_hash = torrentsTable.getCurrentTorrentHash(); - if (current_hash === "") { - clearData(); - clearTimeout(loadTorrentDataTimer); - loadTorrentDataTimer = loadTorrentData.delay(5000); - return; - } - // Display hash - $('torrent_hash').set('html', current_hash); - var url = 'query/propertiesGeneral/' + current_hash; - var request = new Request.JSON({ - url: url, - noCache: true, - method: 'get', - onFailure: function() { - $('error_div').set('html', 'QBT_TR(qBittorrent client is not reachable)QBT_TR[CONTEXT=HttpServer]'); - clearTimeout(loadTorrentDataTimer); - loadTorrentDataTimer = loadTorrentData.delay(10000); - }, - onSuccess: function(data) { - $('error_div').set('html', ''); - if (data) { - var temp; - // Update Torrent data - if (data.seeding_time > 0) - temp = "QBT_TR(%1 (%2 this session))QBT_TR[CONTEXT=PropertiesWidget]" - .replace("%1", friendlyDuration(data.time_elapsed)) - .replace("%2", friendlyDuration(data.seeding_time)); - else - temp = friendlyDuration(data.time_elapsed); - $('time_elapsed').set('html', temp); - - $('eta').set('html', friendlyDuration(data.eta)); - - temp = "QBT_TR(%1 (%2 max))QBT_TR[CONTEXT=PropertiesWidget]" - .replace("%1", data.nb_connections) - .replace("%2", data.nb_connections_limit < 0 ? "∞" : data.nb_connections_limit); - $('nb_connections').set('html', temp); - - temp = "QBT_TR(%1 (%2 this session))QBT_TR[CONTEXT=PropertiesWidget]" - .replace("%1", friendlyUnit(data.total_downloaded)) - .replace("%2", friendlyUnit(data.total_downloaded_session)); - $('total_downloaded').set('html', temp); - - temp = "QBT_TR(%1 (%2 this session))QBT_TR[CONTEXT=PropertiesWidget]" - .replace("%1", friendlyUnit(data.total_uploaded)) - .replace("%2", friendlyUnit(data.total_uploaded_session)); - $('total_uploaded').set('html', temp); - - temp = "QBT_TR(%1 (%2 avg.))QBT_TR[CONTEXT=PropertiesWidget]" - .replace("%1", friendlyUnit(data.dl_speed, true)) - .replace("%2", friendlyUnit(data.dl_speed_avg, true)); - $('dl_speed').set('html', temp); - - temp = "QBT_TR(%1 (%2 avg.))QBT_TR[CONTEXT=PropertiesWidget]" - .replace("%1", friendlyUnit(data.up_speed, true)) - .replace("%2", friendlyUnit(data.up_speed_avg, true)); - $('up_speed').set('html', temp); - - temp = (data.dl_limit == -1 ? "∞" : friendlyUnit(data.dl_limit, true)); - $('dl_limit').set('html', temp); - - temp = (data.up_limit == -1 ? "∞" : friendlyUnit(data.up_limit, true)); - $('up_limit').set('html', temp); - - $('total_wasted').set('html', friendlyUnit(data.total_wasted)); - - temp = "QBT_TR(%1 (%2 total))QBT_TR[CONTEXT=PropertiesWidget]" - .replace("%1", data.seeds) - .replace("%2", data.seeds_total); - $('seeds').set('html', temp); - - temp = "QBT_TR(%1 (%2 total))QBT_TR[CONTEXT=PropertiesWidget]" - .replace("%1", data.peers) - .replace("%2", data.peers_total); - $('peers').set('html', temp); - - $('share_ratio').set('html', data.share_ratio.toFixed(2)); - - $('reannounce').set('html', friendlyDuration(data.reannounce)); - - if (data.last_seen != -1) - temp = new Date(data.last_seen * 1000).toLocaleString(); - else - temp = "QBT_TR(Never)QBT_TR[CONTEXT=PropertiesWidget]"; - $('last_seen').set('html', temp); - - $('total_size').set('html', friendlyUnit(data.total_size)); - - if (data.pieces_num != -1) - temp = "QBT_TR(%1 x %2 (have %3))QBT_TR[CONTEXT=PropertiesWidget]" - .replace("%1", data.pieces_num) - .replace("%2", friendlyUnit(data.piece_size)) - .replace("%3", data.pieces_have); - else - temp = "QBT_TR(Unknown)QBT_TR[CONTEXT=HttpServer]"; - $('pieces').set('html', temp); - - $('created_by').set('html', escapeHtml(data.created_by)); - if (data.addition_date != -1) - temp = new Date(data.addition_date * 1000).toLocaleString(); - else - temp = "QBT_TR(Unknown)QBT_TR[CONTEXT=HttpServer]"; - - $('addition_date').set('html', temp); - if (data.completion_date != -1) - temp = new Date(data.completion_date * 1000).toLocaleString(); - else - temp = ""; - - $('completion_date').set('html', temp); - - if (data.creation_date != -1) - temp = new Date(data.creation_date * 1000).toLocaleString(); - else - temp = "QBT_TR(Unknown)QBT_TR[CONTEXT=HttpServer]"; - $('creation_date').set('html', temp); - - $('save_path').set('html', data.save_path); - - $('comment').set('html', parseHtmlLinks(escapeHtml(data.comment))); - } - else { - clearData(); - } - clearTimeout(loadTorrentDataTimer); - loadTorrentDataTimer = loadTorrentData.delay(5000); - } - }).send(); -}; - -var updateTorrentData = function() { - clearTimeout(loadTorrentDataTimer); - loadTorrentData(); -}; diff --git a/src/webui/www/public/scripts/prop-trackers.js b/src/webui/www/public/scripts/prop-trackers.js deleted file mode 100644 index 32a61b056..000000000 --- a/src/webui/www/public/scripts/prop-trackers.js +++ /dev/null @@ -1,131 +0,0 @@ -var trackersDynTable = new Class({ - - initialize: function() {}, - - setup: function(table) { - this.table = $(table); - this.rows = new Hash(); - }, - - removeRow: function(url) { - if (this.rows.has(url)) { - var tr = this.rows.get(url); - tr.dispose(); - this.rows.erase(url); - return true; - } - return false; - }, - - removeAllRows: function() { - this.rows.each(function(tr, url) { - this.removeRow(url); - }.bind(this)); - }, - - updateRow: function(tr, row) { - var tds = tr.getElements('td'); - for (var i = 0; i < row.length; i++) { - tds[i].set('html', row[i]); - } - return true; - }, - - insertRow: function(row) { - var url = row[0]; - if (this.rows.has(url)) { - var tableRow = this.rows.get(url); - this.updateRow(tableRow, row); - return; - } - //this.removeRow(id); - var tr = new Element('tr'); - this.rows.set(url, tr); - for (var i = 0; i < row.length; i++) { - var td = new Element('td'); - td.set('html', row[i]); - td.injectInside(tr); - } - tr.injectInside(this.table); - }, -}); - -var current_hash = ""; - -var loadTrackersDataTimer; -var loadTrackersData = function() { - if ($('prop_trackers').hasClass('invisible') || - $('propertiesPanel_collapseToggle').hasClass('panel-expand')) { - // Tab changed, don't do anything - return; - } - var new_hash = torrentsTable.getCurrentTorrentHash(); - if (new_hash === "") { - tTable.removeAllRows(); - clearTimeout(loadTrackersDataTimer); - loadTrackersDataTimer = loadTrackersData.delay(10000); - return; - } - if (new_hash != current_hash) { - tTable.removeAllRows(); - current_hash = new_hash; - } - var url = 'query/propertiesTrackers/' + current_hash; - var request = new Request.JSON({ - url: url, - noCache: true, - method: 'get', - onFailure: function() { - $('error_div').set('html', 'QBT_TR(qBittorrent client is not reachable)QBT_TR[CONTEXT=HttpServer]'); - clearTimeout(loadTrackersDataTimer); - loadTrackersDataTimer = loadTrackersData.delay(20000); - }, - onSuccess: function(trackers) { - $('error_div').set('html', ''); - if (trackers) { - // Update Trackers data - trackers.each(function(tracker) { - var row = []; - row.length = 4; - row[0] = escapeHtml(tracker.url); - row[1] = tracker.status; - row[2] = tracker.num_peers; - row[3] = escapeHtml(tracker.msg); - tTable.insertRow(row); - }); - } - else { - tTable.removeAllRows(); - } - clearTimeout(loadTrackersDataTimer); - loadTrackersDataTimer = loadTrackersData.delay(10000); - } - }).send(); -}; - -var updateTrackersData = function() { - clearTimeout(loadTrackersDataTimer); - loadTrackersData(); -}; - -tTable = new trackersDynTable(); -tTable.setup($('trackersTable')); - -// Add trackers code -$('addTrackersPlus').addEvent('click', function addTrackerDlg() { - if (current_hash.length === 0) return; - new MochaUI.Window({ - id: 'trackersPage', - title: "QBT_TR(Trackers addition dialog)QBT_TR[CONTEXT=TrackersAdditionDlg]", - loadMethod: 'iframe', - contentURL: 'addtrackers.html?hash=' + current_hash, - scrollbars: true, - resizable: false, - maximizable: false, - closable: true, - paddingVertical: 0, - paddingHorizontal: 0, - width: 500, - height: 250 - }); -}); diff --git a/src/webui/www/public/scripts/prop-webseeds.js b/src/webui/www/public/scripts/prop-webseeds.js deleted file mode 100644 index 12f366ca9..000000000 --- a/src/webui/www/public/scripts/prop-webseeds.js +++ /dev/null @@ -1,109 +0,0 @@ -var webseedsDynTable = new Class({ - - initialize: function() {}, - - setup: function(table) { - this.table = $(table); - this.rows = new Hash(); - }, - - removeRow: function(url) { - if (this.rows.has(url)) { - var tr = this.rows.get(url); - tr.dispose(); - this.rows.erase(url); - return true; - } - return false; - }, - - removeAllRows: function() { - this.rows.each(function(tr, url) { - this.removeRow(url); - }.bind(this)); - }, - - updateRow: function(tr, row) { - var tds = tr.getElements('td'); - for (var i = 0; i < row.length; i++) { - tds[i].set('html', row[i]); - } - return true; - }, - - insertRow: function(row) { - var url = row[0]; - if (this.rows.has(url)) { - var tableRow = this.rows.get(url); - this.updateRow(tableRow, row); - return; - } - //this.removeRow(id); - var tr = new Element('tr'); - this.rows.set(url, tr); - for (var i = 0; i < row.length; i++) { - var td = new Element('td'); - td.set('html', row[i]); - td.injectInside(tr); - } - tr.injectInside(this.table); - }, -}); - -var current_hash = ""; - -var loadWebSeedsDataTimer; -var loadWebSeedsData = function() { - if ($('prop_webseeds').hasClass('invisible') || - $('propertiesPanel_collapseToggle').hasClass('panel-expand')) { - // Tab changed, don't do anything - return; - } - var new_hash = torrentsTable.getCurrentTorrentHash(); - if (new_hash === "") { - wsTable.removeAllRows(); - clearTimeout(loadWebSeedsDataTimer); - loadWebSeedsDataTimer = loadWebSeedsData.delay(10000); - return; - } - if (new_hash != current_hash) { - wsTable.removeAllRows(); - current_hash = new_hash; - } - var url = 'query/propertiesWebSeeds/' + current_hash; - var request = new Request.JSON({ - url: url, - noCache: true, - method: 'get', - onFailure: function() { - $('error_div').set('html', 'QBT_TR(qBittorrent client is not reachable)QBT_TR[CONTEXT=HttpServer]'); - clearTimeout(loadWebSeedsDataTimer); - loadWebSeedsDataTimer = loadWebSeedsData.delay(20000); - }, - onSuccess: function(webseeds) { - $('error_div').set('html', ''); - if (webseeds) { - // Update WebSeeds data - webseeds.each(function(webseed) { - var row = []; - row.length = 1; - row[0] = webseed.url; - wsTable.insertRow(row); - }); - } - else { - wsTable.removeAllRows(); - } - clearTimeout(loadWebSeedsDataTimer); - loadWebSeedsDataTimer = loadWebSeedsData.delay(10000); - } - }).send(); -}; - -var updateWebSeedsData = function() { - clearTimeout(loadWebSeedsDataTimer); - loadWebSeedsData(); -}; - -wsTable = new webseedsDynTable(); -wsTable.setup($('webseedsTable')); diff --git a/src/webui/www/public/setlocation.html b/src/webui/www/public/setlocation.html deleted file mode 100644 index 94a171ca8..000000000 --- a/src/webui/www/public/setlocation.html +++ /dev/null @@ -1,55 +0,0 @@ - - - - - QBT_TR(Set location)QBT_TR[CONTEXT=HttpServer] - - - - - - -
-

QBT_TR(Location)QBT_TR[CONTEXT=TransferListWidget]:

- -
- -
-
- - diff --git a/src/webui/www/public/statistics.html b/src/webui/www/public/statistics.html deleted file mode 100644 index bf98848c8..000000000 --- a/src/webui/www/public/statistics.html +++ /dev/null @@ -1,47 +0,0 @@ -

QBT_TR(User statistics)QBT_TR[CONTEXT=StatsDialog]

- - - - - - - - - - - - - - - - -
- -

QBT_TR(Cache statistics)QBT_TR[CONTEXT=StatsDialog]

- - - - - - - -
- -

QBT_TR(Performance statistics)QBT_TR[CONTEXT=StatsDialog]

- - - - - - - - - - - - - - - - -
diff --git a/src/webui/www/public/transferlist.html b/src/webui/www/public/transferlist.html deleted file mode 100644 index d28150441..000000000 --- a/src/webui/www/public/transferlist.html +++ /dev/null @@ -1,85 +0,0 @@ -
- - - - -
-
- -
- - - - - -
-
- - diff --git a/src/webui/www/public/upload.html b/src/webui/www/public/upload.html deleted file mode 100644 index f9d53b527..000000000 --- a/src/webui/www/public/upload.html +++ /dev/null @@ -1,62 +0,0 @@ - - - - - QBT_TR(Upload local torrent)QBT_TR[CONTEXT=HttpServer] - - - - - - - -
-

-

- -
-

-
-
- - -
-
- - -
-
- - - -
-
- - -
-
- -
-
-
- -
- - diff --git a/src/webui/www/public/uploadlimit.html b/src/webui/www/public/uploadlimit.html deleted file mode 100644 index e4a03c22b..000000000 --- a/src/webui/www/public/uploadlimit.html +++ /dev/null @@ -1,62 +0,0 @@ - - - - - QBT_TR(Torrent Upload Speed Limiting)QBT_TR[CONTEXT=TransferListWidget] - - - - - - - -
-
-
QBT_TR(Upload limit:)QBT_TR[CONTEXT=PropertiesWidget] QBT_TR(KiB/s)QBT_TR[CONTEXT=SpeedLimitDialog]
-
-
-
-
-
-
- - -
- - - - - diff --git a/uncrustify.cfg b/uncrustify.cfg deleted file mode 100644 index 5c2d31df1..000000000 --- a/uncrustify.cfg +++ /dev/null @@ -1,84 +0,0 @@ -set FOR foreach -set WORD slots - -newlines = LF - -indent_with_tabs = 0 -indent_columns = 4 -indent_switch_case = 0 -indent_namespace = true -indent_class = true -indent_col1_comment = true -indent_access_spec = -4 - -nl_after_func_body = 2 -nl_collapse_empty_body = false -nl_enum_brace = add -nl_union_brace = add -nl_struct_brace = add -nl_class_brace = add -nl_case_colon_brace = remove -nl_do_brace = remove -nl_if_brace = remove -nl_for_brace = remove -nl_else_brace = remove -nl_while_brace = remove -nl_switch_brace = remove -nl_brace_while = remove -nl_brace_else = remove -nl_try_brace = remove -nl_fcall_brace = remove -nl_fdef_brace = add -nl_after_return = false -nl_brace_else = add -nl_class_leave_one_liners = true -nl_before_access_spec = 2 -nl_end_of_file = force -nl_end_of_file_min = 1 -nl_namespace_brace = add - -mod_full_brace_if = remove -mod_full_brace_if_chain = true -mod_full_brace_do = remove -mod_full_brace_while = remove -mod_full_brace_for = remove -mod_full_brace_if_chain = true -mod_full_brace_nl = 3 -mod_full_paren_if_bool = true - -sp_else_brace = force -sp_try_brace = force -sp_arith = force -sp_assign = force -sp_defined_paren = ignore -sp_pp_concat = ignore -sp_pp_stringify = ignore -sp_bool = force -sp_after_class_colon = force -sp_before_class_colon = remove -sp_cmt_cpp_start = add -sp_cmt_cpp_doxygen = true -sp_angle_shift = remove -sp_permit_cpp11_shift = true -sp_before_sparen = force -sp_after_operator = remove -sp_after_operator_sym = remove - -sp_before_ptr_star = force -sp_before_byref = force -sp_after_ptr_star = remove -sp_after_byref = remove -sp_before_unnamed_ptr_star = force -sp_before_unnamed_byref = force -sp_after_ptr_star_func = remove -sp_after_byref_func = remove -sp_before_ptr_star_func = force -sp_before_byref_func = force - -eat_blanks_before_close_brace = true - -pos_arith = lead -pos_conditional = lead -pos_constr_comma = lead_break -pos_constr_colon = lead_break - diff --git a/unixconf.pri b/unixconf.pri deleted file mode 100644 index 2280f282a..000000000 --- a/unixconf.pri +++ /dev/null @@ -1,130 +0,0 @@ -# Generated by the configure file -# Ignore any WARNING about 'conf.pri' missing during configure. The file should be found during make. -# If not there will be a WARNING again. -# The first path is used when the source is being build by packagers (pbuilder/sbuild/etc) -# The second path is used when you manually run the configure script in the root folder (eg when using qt creator) -exists($$OUT_PWD/../conf.pri) { - include($$OUT_PWD/../conf.pri) -} else { - include(conf.pri) -} - -# COMPILATION SPECIFIC -!nogui:dbus: QT += dbus - -QMAKE_CXXFLAGS += -Wformat -Wformat-security -!haiku: QMAKE_LFLAGS_APP += -rdynamic - -# Man page -nogui { - man.files = ../doc/qbittorrent-nox.1 -} else { - man.files = ../doc/qbittorrent.1 -} - -man.path = $$MANPREFIX/man1 -INSTALLS += man - -DIST_PATH = ../dist/unix - -# Systemd Service file -nogui:systemd { - systemdService.files = $$DIST_PATH/systemd/qbittorrent-nox@.service - systemdService.path = $$PREFIX/lib/systemd/system/ - INSTALLS += systemdService -} - -# Menu Icon -!nogui { - menuicon.files = icons/qbittorrent.desktop - menuicon.path = $$DATADIR/applications/ - INSTALLS += menuicon - - appdata.files = $$DIST_PATH/qbittorrent.appdata.xml - appdata.path = $$DATADIR/appdata/ - INSTALLS += appdata - - # Apps icons - icon16.files = $$DIST_PATH/menuicons/16x16/apps/qbittorrent.png - icon16.path = $$DATADIR/icons/hicolor/16x16/apps/ - icon22.files = $$DIST_PATH/menuicons/22x22/apps/qbittorrent.png - icon22.path = $$DATADIR/icons/hicolor/22x22/apps/ - icon24.files = $$DIST_PATH/menuicons/24x24/apps/qbittorrent.png - icon24.path = $$DATADIR/icons/hicolor/24x24/apps/ - icon32.files = $$DIST_PATH/menuicons/32x32/apps/qbittorrent.png - icon32.path = $$DATADIR/icons/hicolor/32x32/apps/ - icon36.files = $$DIST_PATH/menuicons/36x36/apps/qbittorrent.png - icon36.path = $$DATADIR/icons/hicolor/36x36/apps/ - icon48.files = $$DIST_PATH/menuicons/48x48/apps/qbittorrent.png - icon48.path = $$DATADIR/icons/hicolor/48x48/apps/ - icon64.files = $$DIST_PATH/menuicons/64x64/apps/qbittorrent.png - icon64.path = $$DATADIR/icons/hicolor/64x64/apps/ - icon72.files = $$DIST_PATH/menuicons/72x72/apps/qbittorrent.png - icon72.path = $$DATADIR/icons/hicolor/72x72/apps/ - icon96.files = $$DIST_PATH/menuicons/96x96/apps/qbittorrent.png - icon96.path = $$DATADIR/icons/hicolor/96x96/apps/ - icon128.files = $$DIST_PATH/menuicons/128x128/apps/qbittorrent.png - icon128.path = $$DATADIR/icons/hicolor/128x128/apps/ - icon192.files = $$DIST_PATH/menuicons/192x192/apps/qbittorrent.png - icon192.path = $$DATADIR/icons/hicolor/192x192/apps/ - # Status icons - statusIcon16.files = $$DIST_PATH/menuicons/16x16/status/qbittorrent-tray.png - statusIcon16.path = $$DATADIR/icons/hicolor/16x16/status/ - statusIcon22.files = $$DIST_PATH/menuicons/22x22/status/qbittorrent-tray.png - statusIcon22.path = $$DATADIR/icons/hicolor/22x22/status/ - statusIcon24.files = $$DIST_PATH/menuicons/24x24/status/qbittorrent-tray.png - statusIcon24.path = $$DATADIR/icons/hicolor/24x24/status/ - statusIcon32.files = $$DIST_PATH/menuicons/32x32/status/qbittorrent-tray.png - statusIcon32.path = $$DATADIR/icons/hicolor/32x32/status/ - statusIcon36.files = $$DIST_PATH/menuicons/36x36/status/qbittorrent-tray.png - statusIcon36.path = $$DATADIR/icons/hicolor/36x36/status/ - statusIcon48.files = $$DIST_PATH/menuicons/48x48/status/qbittorrent-tray.png - statusIcon48.path = $$DATADIR/icons/hicolor/48x48/status/ - statusIcon64.files = $$DIST_PATH/menuicons/64x64/status/qbittorrent-tray.png - statusIcon64.path = $$DATADIR/icons/hicolor/64x64/status/ - statusIcon72.files = $$DIST_PATH/menuicons/72x72/status/qbittorrent-tray.png - statusIcon72.path = $$DATADIR/icons/hicolor/72x72/status/ - statusIcon96.files = $$DIST_PATH/menuicons/96x96/status/qbittorrent-tray.png - statusIcon96.path = $$DATADIR/icons/hicolor/96x96/status/ - statusIcon128.files = $$DIST_PATH/menuicons/128x128/status/qbittorrent-tray.png - statusIcon128.path = $$DATADIR/icons/hicolor/128x128/status/ - statusIcon192.files = $$DIST_PATH/menuicons/192x192/status/qbittorrent-tray.png - statusIcon192.path = $$DATADIR/icons/hicolor/192x192/status/ - - statusIconScalable.files = $$PWD/src/icons/skin/qbittorrent-tray-dark.svg \ - $$PWD/src/icons/skin/qbittorrent-tray-light.svg - statusIconScalable.path = $$DATADIR/icons/hicolor/scalable/status/ - - INSTALLS += \ - icon16 \ - icon22 \ - icon24 \ - icon32 \ - icon36 \ - icon48 \ - icon64 \ - icon72 \ - icon96 \ - icon128 \ - icon192 \ - statusIcon16 \ - statusIcon22 \ - statusIcon24 \ - statusIcon32 \ - statusIcon36 \ - statusIcon48 \ - statusIcon64 \ - statusIcon72 \ - statusIcon96 \ - statusIcon128 \ - statusIcon192 \ - statusIconScalable - - pixmap.files = $$DIST_PATH/menuicons/128x128/apps/qbittorrent.png - pixmap.path = $$DATADIR/pixmaps/ - INSTALLS += pixmap -} - -# INSTALL -target.path = $$PREFIX/bin/ -INSTALLS += target diff --git a/version.pri b/version.pri deleted file mode 100644 index 7cc0ac37a..000000000 --- a/version.pri +++ /dev/null @@ -1,32 +0,0 @@ -# keep it all lowercase to match program naming convention on *nix systems -PROJECT_NAME = qbittorrent - -# Define version numbers here -VER_MAJOR = 3 -VER_MINOR = 4 -VER_BUGFIX = 0 -VER_BUILD = 0 -VER_STATUS = beta # Should be empty for stable releases! - -# Don't touch the rest part -PROJECT_VERSION = $${VER_MAJOR}.$${VER_MINOR}.$${VER_BUGFIX} - -!equals(VER_BUILD, 0) { - PROJECT_VERSION = $${PROJECT_VERSION}.$${VER_BUILD} -} - -PROJECT_VERSION = $${PROJECT_VERSION}$${VER_STATUS} - -DEFINES += QBT_VERSION_MAJOR=$${VER_MAJOR} -DEFINES += QBT_VERSION_MINOR=$${VER_MINOR} -DEFINES += QBT_VERSION_BUGFIX=$${VER_BUGFIX} -DEFINES += QBT_VERSION_BUILD=$${VER_BUILD} - -os2 { - DEFINES += QBT_VERSION=\'\"v$${PROJECT_VERSION}\"\' - DEFINES += QBT_VERSION_2=\'\"$${PROJECT_VERSION}\"\' -} -else { - DEFINES += QBT_VERSION=\\\"v$${PROJECT_VERSION}\\\" - DEFINES += QBT_VERSION_2=\\\"$${PROJECT_VERSION}\\\" -} diff --git a/winconf-mingw.pri b/winconf-mingw.pri deleted file mode 100644 index de56bda16..000000000 --- a/winconf-mingw.pri +++ /dev/null @@ -1,35 +0,0 @@ -strace_win{ - contains(QMAKE_HOST.arch, x86) { - # i686 arch requires frame pointer preservation - QMAKE_CXXFLAGS_RELEASE += -fno-omit-frame-pointer - QMAKE_CXXFLAGS_DEBUG += -fno-omit-frame-pointer - } - - QMAKE_LFLAGS += -Wl,--export-all-symbols - - LIBS += libdbghelp -} - -CONFIG(debug, debug|release) { - # Make sure binary is not relocatable, otherwise debugging will fail - QMAKE_LFLAGS -= -Wl,--dynamicbase -} - -RC_FILE = qbittorrent_mingw.rc - -# Adapt the lib names/versions accordingly -CONFIG(debug, debug|release) { - LIBS += libtorrent-rasterbar \ - libboost_system-mt \ - libboost_filesystem-mt \ - libboost_thread_win32-mt -} else { - LIBS += libtorrent-rasterbar \ - libboost_system-mt \ - libboost_filesystem-mt \ - libboost_thread_win32-mt -} - -LIBS += libadvapi32 libshell32 libuser32 -LIBS += libcrypto libssl libwsock32 libws2_32 libz libiconv -LIBS += libpowrprof diff --git a/winconf-msvc.pri b/winconf-msvc.pri deleted file mode 100644 index f27a1f791..000000000 --- a/winconf-msvc.pri +++ /dev/null @@ -1,32 +0,0 @@ -strace_win { - contains(QMAKE_HOST.arch, x86) { - # i686 arch requires frame pointer preservation - QMAKE_CXXFLAGS_RELEASE += -Oy- - QMAKE_CXXFLAGS_DEBUG += -Oy- - } - release { - QMAKE_CXXFLAGS_RELEASE += -Zi - QMAKE_LFLAGS += "/DEBUG" - } - LIBS += dbghelp.lib -} - -CONFIG -= embed_manifest_exe -QMAKE_LFLAGS += "/MANIFEST:EMBED /MANIFESTINPUT:$$quote($${PWD}/src/qbittorrent.exe.manifest) /STACK:0x800000" -QMAKE_LFLAGS_RELEASE += "/OPT:REF /OPT:ICF" - -RC_FILE = qbittorrent.rc - -# Adapt the lib names/versions accordingly -CONFIG(debug, debug|release) { - LIBS += libtorrentd.lib \ - libboost_system-vc90-mt-sgd-1_51.lib -} else { - LIBS += libtorrent.lib \ - libboost_system-vc90-mt-s-1_51.lib -} - -LIBS += advapi32.lib shell32.lib crypt32.lib User32.lib -LIBS += libeay32.lib ssleay32.lib -LIBS += PowrProf.lib -LIBS += zlib.lib diff --git a/winconf.pri b/winconf.pri deleted file mode 100644 index ca36e0a92..000000000 --- a/winconf.pri +++ /dev/null @@ -1,67 +0,0 @@ -# Adapt these paths on Windows - -# Point this to the boost include folder -INCLUDEPATH += $$quote(C:/qBittorrent/boost_1_51_0) -# Point this to the libtorrent include folder -INCLUDEPATH += $$quote(C:/qBittorrent/RC_0_16/include) -# Point this to the zlib include folder -INCLUDEPATH += $$quote(C:/qBittorrent/Zlib/include) -# Point this to the openssl include folder -INCLUDEPATH += $$quote(C:/qBittorrent/openssl/include) - -# Point this to the boost lib folder -LIBS += $$quote(-LC:/qBittorrent/boost_1_51_0/stage/lib) -# Point this to the libtorrent lib folder -LIBS += $$quote(-LC:/qBittorrent/RC_0_16/bin/path-according-to-the-build-options-chosen) -# Point this to the zlib lib folder -LIBS += $$quote(-LC:/qBittorrent/Zlib/lib) -# Point this to the openssl lib folder -LIBS += $$quote(-LC:/qBittorrent/openssl/lib) - -# BOOST DEFINES -DEFINES += BOOST_ALL_NO_LIB -DEFINES += BOOST_ASIO_HASH_MAP_BUCKETS=1021 -# Disable this if building against libtorrent 1.1.x (RC_1_1) -DEFINES += BOOST_ASIO_SEPARATE_COMPILATION -# After 1.55 some Windows users reported regular UI freezes. -# This makes ASIO use the pre-1.56 way of doing things. See issue #2003 -DEFINES += BOOST_ASIO_DISABLE_CONNECTEX -# Boost 1.60+ defaults to Vista+ support. The define below enables XP support again. -DEFINES += BOOST_USE_WINAPI_VERSION=0x0501 -DEFINES += BOOST_EXCEPTION_DISABLE -DEFINES += BOOST_SYSTEM_STATIC_LINK=1 - -# LIBTORRENT DEFINES -DEFINES += TORRENT_USE_OPENSSL -DEFINES += TORRENT_DISABLE_GEO_IP -DEFINES += TORRENT_DISABLE_RESOLVE_COUNTRIES - -# QBT DEFINES -DEFINES += UNICODE -DEFINES += _UNICODE -DEFINES += WIN32 -DEFINES += _WIN32 -DEFINES += WIN32_LEAN_AND_MEAN -DEFINES += NTDDI_VERSION=0x05010000 -DEFINES += _WIN32_WINNT=0x0501 -DEFINES += _WIN32_IE=0x0501 -DEFINES += _CRT_SECURE_NO_DEPRECATE -DEFINES += _SCL_SECURE_NO_DEPRECATE -DEFINES += __USE_W32_SOCKETS -DEFINES += _FILE_OFFSET_BITS=64 - -CONFIG(debug, debug|release) { - DEFINES += TORRENT_DEBUG -} else { - DEFINES += NDEBUG -} - -# Enable backtrace support -CONFIG += strace_win - -win32-g++* { - include(winconf-mingw.pri) -} -else { - include(winconf-msvc.pri) -}