From 1e9188127f42df13a39329e52e37fa04d9d0bb1f Mon Sep 17 00:00:00 2001 From: sledgehammer999 Date: Sat, 18 Apr 2020 01:15:25 +0300 Subject: [PATCH] Delete unnecessary files --- .appveyor.yml | 58 - .editorconfig | 12 - .github/ISSUE_TEMPLATE.md | 14 - .travis.yml | 196 - .tx/config | 19 - 5B7CC9A2.asc | 92 - AUTHORS | 132 - CMakeLists.txt | 61 - CODING_GUIDELINES.md | 308 - CONTRIBUTING.md | 35 - COPYING | 294 - Changelog | 2109 ---- INSTALL | 54 - NEWS | 4 - README.md | 53 - README.os2 | 74 - TODO | 2 - bootstrap.sh | 4 - build-aux/compile | 347 - build-aux/config.guess | 1421 --- build-aux/config.sub | 1807 --- build-aux/install-sh | 501 - build-aux/missing | 215 - cmake/Modules/DeployQt5.cmake | 355 - cmake/Modules/FindLibtorrentRasterbar.cmake | 127 - cmake/Modules/FindQtSingleApplication.cmake | 94 - cmake/Modules/FindSystemd.cmake | 26 - cmake/Modules/FunctionReadVersion.cmake | 28 - cmake/Modules/MacroConfigureMSVCRuntime.cmake | 38 - cmake/Modules/MacroGlibcDetect.cmake | 49 - cmake/Modules/MacroLinkQtComponents.cmake | 28 - cmake/Modules/MacroQbtCompilerSettings.cmake | 89 - cmake/Modules/QbtTargetSources.cmake | 16 - cmake/Modules/bundle.cmake | 21 - cmake/Modules/winconf-mingw.cmake | 14 - cmake/Modules/winconf-msvc.cmake | 21 - cmake/Modules/winconf.cmake | 91 - codingStyleQtCreator.xml | 39 - conf.pri.in | 24 - configure | 8027 ------------ configure.ac | 237 - dist/CMakeLists.txt | 10 - dist/mac/CMakeLists.txt | 0 dist/mac/Info.plist | 94 - dist/mac/qBitTorrentDocument.icns | Bin 127327 -> 0 bytes dist/mac/qbittorrent_mac.icns | Bin 50278 -> 0 bytes dist/mac/qt.conf | 3 - dist/qt-translations/qt_ar.qm | Bin 33913 -> 0 bytes dist/qt-translations/qt_bg.qm | Bin 89612 -> 0 bytes dist/qt-translations/qt_ca.qm | Bin 172 -> 0 bytes dist/qt-translations/qt_cs.qm | Bin 176 -> 0 bytes dist/qt-translations/qt_da.qm | Bin 119839 -> 0 bytes dist/qt-translations/qt_de.qm | Bin 172 -> 0 bytes dist/qt-translations/qt_es.qm | Bin 82414 -> 0 bytes dist/qt-translations/qt_eu.qm | Bin 96890 -> 0 bytes dist/qt-translations/qt_fa.qm | Bin 293114 -> 0 bytes dist/qt-translations/qt_fi.qm | Bin 136 -> 0 bytes dist/qt-translations/qt_fr.qm | Bin 172 -> 0 bytes dist/qt-translations/qt_gl.qm | Bin 323580 -> 0 bytes dist/qt-translations/qt_he.qm | Bin 25669 -> 0 bytes dist/qt-translations/qt_hu.qm | Bin 272165 -> 0 bytes dist/qt-translations/qt_it.qm | Bin 172 -> 0 bytes dist/qt-translations/qt_ja.qm | Bin 165 -> 0 bytes dist/qt-translations/qt_ko.qm | Bin 165 -> 0 bytes dist/qt-translations/qt_lt.qm | Bin 165376 -> 0 bytes dist/qt-translations/qt_nl.qm | Bin 144243 -> 0 bytes dist/qt-translations/qt_pl.qm | Bin 180 -> 0 bytes dist/qt-translations/qt_pt.qm | Bin 70324 -> 0 bytes dist/qt-translations/qt_pt_BR.qm | Bin 143803 -> 0 bytes dist/qt-translations/qt_ru.qm | Bin 183 -> 0 bytes dist/qt-translations/qt_sk.qm | Bin 176 -> 0 bytes dist/qt-translations/qt_sl.qm | Bin 228421 -> 0 bytes dist/qt-translations/qt_sv.qm | Bin 65851 -> 0 bytes dist/qt-translations/qt_tr.qm | Bin 70920 -> 0 bytes dist/qt-translations/qt_uk.qm | Bin 183 -> 0 bytes dist/qt-translations/qt_zh_CN.qm | Bin 117340 -> 0 bytes dist/qt-translations/qt_zh_TW.qm | Bin 117256 -> 0 bytes dist/qt-translations/qtbase_ca.qm | Bin 174279 -> 0 bytes dist/qt-translations/qtbase_cs.qm | Bin 158455 -> 0 bytes dist/qt-translations/qtbase_de.qm | Bin 172682 -> 0 bytes dist/qt-translations/qtbase_fi.qm | Bin 160668 -> 0 bytes dist/qt-translations/qtbase_fr.qm | Bin 166157 -> 0 bytes dist/qt-translations/qtbase_he.qm | Bin 139222 -> 0 bytes dist/qt-translations/qtbase_hu.qm | Bin 91101 -> 0 bytes dist/qt-translations/qtbase_it.qm | Bin 154226 -> 0 bytes dist/qt-translations/qtbase_ja.qm | Bin 129904 -> 0 bytes dist/qt-translations/qtbase_ko.qm | Bin 124101 -> 0 bytes dist/qt-translations/qtbase_lv.qm | Bin 153598 -> 0 bytes dist/qt-translations/qtbase_pl.qm | Bin 142385 -> 0 bytes dist/qt-translations/qtbase_ru.qm | Bin 157842 -> 0 bytes dist/qt-translations/qtbase_sk.qm | Bin 125753 -> 0 bytes dist/qt-translations/qtbase_uk.qm | Bin 158264 -> 0 bytes dist/unix/CMakeLists.txt | 45 - .../menuicons/128x128/apps/qbittorrent.png | Bin 21112 -> 0 bytes .../128x128/status/qbittorrent-tray.png | Bin 21112 -> 0 bytes .../unix/menuicons/16x16/apps/qbittorrent.png | Bin 893 -> 0 bytes .../16x16/status/qbittorrent-tray.png | Bin 893 -> 0 bytes .../menuicons/192x192/apps/qbittorrent.png | Bin 36987 -> 0 bytes .../192x192/status/qbittorrent-tray.png | Bin 36987 -> 0 bytes .../unix/menuicons/22x22/apps/qbittorrent.png | Bin 1399 -> 0 bytes .../22x22/status/qbittorrent-tray.png | Bin 1399 -> 0 bytes .../unix/menuicons/24x24/apps/qbittorrent.png | Bin 1623 -> 0 bytes .../24x24/status/qbittorrent-tray.png | Bin 1623 -> 0 bytes .../unix/menuicons/32x32/apps/qbittorrent.png | Bin 2455 -> 0 bytes .../32x32/status/qbittorrent-tray.png | Bin 2455 -> 0 bytes .../unix/menuicons/36x36/apps/qbittorrent.png | Bin 2944 -> 0 bytes .../36x36/status/qbittorrent-tray.png | Bin 2944 -> 0 bytes .../unix/menuicons/48x48/apps/qbittorrent.png | Bin 4629 -> 0 bytes .../48x48/status/qbittorrent-tray.png | Bin 4629 -> 0 bytes .../unix/menuicons/64x64/apps/qbittorrent.png | Bin 7494 -> 0 bytes .../64x64/status/qbittorrent-tray.png | Bin 7494 -> 0 bytes .../unix/menuicons/72x72/apps/qbittorrent.png | Bin 9063 -> 0 bytes .../72x72/status/qbittorrent-tray.png | Bin 9063 -> 0 bytes .../unix/menuicons/96x96/apps/qbittorrent.png | Bin 14165 -> 0 bytes .../96x96/status/qbittorrent-tray.png | Bin 14165 -> 0 bytes dist/unix/qbittorrent.appdata.xml | 66 - dist/unix/systemd/qbittorrent-nox@.service.in | 14 - dist/windows/CMakeLists.txt | 1 - dist/windows/README.txt | 67 - dist/windows/UAC.nsh | 299 - .../installer-translations/afrikaans.nsi | 53 - .../installer-translations/albanian.nsi | 53 - .../windows/installer-translations/arabic.nsi | 53 - .../windows/installer-translations/basque.nsi | 53 - .../installer-translations/belarusian.nsi | 53 - .../installer-translations/bosnian.nsi | 53 - .../windows/installer-translations/breton.nsi | 53 - .../installer-translations/bulgarian.nsi | 53 - .../installer-translations/catalan.nsi | 53 - .../installer-translations/croatian.nsi | 53 - dist/windows/installer-translations/czech.nsi | 53 - .../windows/installer-translations/danish.nsi | 53 - dist/windows/installer-translations/dutch.nsi | 53 - .../installer-translations/english.nsi | 53 - .../installer-translations/esperanto.nsi | 53 - .../installer-translations/estonian.nsi | 53 - dist/windows/installer-translations/farsi.nsi | 53 - .../installer-translations/finnish.nsi | 53 - .../windows/installer-translations/french.nsi | 53 - .../installer-translations/galician.nsi | 53 - .../windows/installer-translations/german.nsi | 53 - dist/windows/installer-translations/greek.nsi | 53 - .../windows/installer-translations/hebrew.nsi | 53 - .../installer-translations/hungarian.nsi | 53 - .../installer-translations/icelandic.nsi | 53 - .../installer-translations/indonesian.nsi | 53 - dist/windows/installer-translations/irish.nsi | 53 - .../installer-translations/italian.nsi | 53 - .../installer-translations/japanese.nsi | 53 - .../windows/installer-translations/korean.nsi | 53 - .../installer-translations/kurdish.nsi | 53 - .../installer-translations/latvian.nsi | 53 - .../installer-translations/lithuanian.nsi | 53 - .../installer-translations/luxembourgish.nsi | 53 - .../installer-translations/macedonian.nsi | 53 - dist/windows/installer-translations/malay.nsi | 53 - .../installer-translations/mongolian.nsi | 53 - .../installer-translations/norwegian.nsi | 53 - .../norwegiannynorsk.nsi | 53 - .../windows/installer-translations/polish.nsi | 53 - .../installer-translations/portuguese.nsi | 53 - .../installer-translations/portugueseBR.nsi | 53 - .../installer-translations/romanian.nsi | 53 - .../installer-translations/russian.nsi | 53 - .../installer-translations/serbian.nsi | 53 - .../installer-translations/serbianlatin.nsi | 53 - .../installer-translations/simpchinese.nsi | 53 - .../windows/installer-translations/slovak.nsi | 53 - .../installer-translations/slovenian.nsi | 53 - .../installer-translations/spanish.nsi | 53 - .../spanishinternational.nsi | 53 - .../installer-translations/swedish.nsi | 53 - dist/windows/installer-translations/thai.nsi | 53 - .../installer-translations/tradchinese.nsi | 53 - .../installer-translations/turkish.nsi | 53 - .../installer-translations/ukrainian.nsi | 53 - dist/windows/installer-translations/uzbek.nsi | 53 - dist/windows/installer-translations/welsh.nsi | 53 - dist/windows/installer.nsi | 247 - .../nsis plugins/FindProcDLL_mod_by_hnedka.7z | Bin 9387 -> 0 bytes dist/windows/nsis plugins/UAC.zip | Bin 52034 -> 0 bytes dist/windows/nsis plugins/nsisFirewall.zip | Bin 19047 -> 0 bytes dist/windows/options.nsi | 135 - dist/windows/qbittorrent.nsi | 4 - dist/windows/qt.conf | 5 - dist/windows/translations.nsi | 123 - dist/windows/uninstaller.nsi | 172 - doc/qbittorrent-nox.1 | 44 - doc/qbittorrent.1 | 42 - install.os2 | 187 - m4/ax_boost_base.m4 | 285 - m4/ax_boost_system.m4 | 121 - m4/ax_define_dir.m4 | 49 - m4/pkg.m4 | 214 - m4/qbittorrent.m4 | 38 - macxconf.pri | 75 - os2conf.pri | 16 - qbittorrent.pro | 19 - qm_gen.pri | 21 - src/CMakeLists.txt | 103 - src/app/CMakeLists.txt | 191 - src/app/app.pri | 38 - src/app/application.cpp | 723 -- src/app/application.h | 152 - src/app/cmdoptions.cpp | 587 - src/app/cmdoptions.h | 78 - src/app/filelogger.cpp | 176 - src/app/filelogger.h | 79 - src/app/main.cpp | 390 - src/app/qtsingleapplication/CMakeLists.txt | 31 - src/app/qtsingleapplication/QtLockedFile | 1 - .../qtsingleapplication/QtSingleApplication | 1 - src/app/qtsingleapplication/qtlocalpeer.cpp | 204 - src/app/qtsingleapplication/qtlocalpeer.h | 77 - src/app/qtsingleapplication/qtlockedfile.cpp | 193 - src/app/qtsingleapplication/qtlockedfile.h | 97 - .../qtsingleapplication/qtlockedfile_unix.cpp | 115 - .../qtsingleapplication/qtlockedfile_win.cpp | 211 - .../qtsingleapplication.cpp | 347 - .../qtsingleapplication/qtsingleapplication.h | 105 - .../qtsingleapplication.pri | 16 - .../qtsinglecoreapplication.cpp | 149 - .../qtsinglecoreapplication.h | 71 - .../qtsinglecoreapplication.pri | 10 - src/app/stacktrace.h | 104 - src/app/stacktrace_win.h | 346 - src/app/stacktrace_win_dlg.h | 84 - src/app/stacktrace_win_dlg.ui | 35 - src/app/upgrade.h | 275 - src/base/CMakeLists.txt | 145 - src/base/asyncfilestorage.cpp | 88 - src/base/asyncfilestorage.h | 64 - src/base/base.pri | 124 - src/base/bittorrent/addtorrentparams.h | 56 - src/base/bittorrent/cachestatus.h | 46 - src/base/bittorrent/infohash.cpp | 97 - src/base/bittorrent/infohash.h | 61 - src/base/bittorrent/magneturi.cpp | 125 - src/base/bittorrent/magneturi.h | 68 - src/base/bittorrent/peerinfo.cpp | 409 - src/base/bittorrent/peerinfo.h | 115 - .../bittorrent/private/bandwidthscheduler.cpp | 95 - .../bittorrent/private/bandwidthscheduler.h | 50 - .../bittorrent/private/filterparserthread.cpp | 608 - .../bittorrent/private/filterparserthread.h | 70 - .../private/resumedatasavingmanager.cpp | 55 - .../private/resumedatasavingmanager.h | 50 - src/base/bittorrent/private/speedmonitor.cpp | 60 - src/base/bittorrent/private/speedmonitor.h | 90 - src/base/bittorrent/private/statistics.cpp | 84 - src/base/bittorrent/private/statistics.h | 41 - src/base/bittorrent/session.cpp | 4082 ------- src/base/bittorrent/session.h | 687 -- src/base/bittorrent/sessionstatus.h | 78 - src/base/bittorrent/torrentcreatorthread.cpp | 172 - src/base/bittorrent/torrentcreatorthread.h | 73 - src/base/bittorrent/torrenthandle.cpp | 2144 ---- src/base/bittorrent/torrenthandle.h | 477 - src/base/bittorrent/torrentinfo.cpp | 352 - src/base/bittorrent/torrentinfo.h | 116 - src/base/bittorrent/tracker.cpp | 257 - src/base/bittorrent/tracker.h | 103 - src/base/bittorrent/trackerentry.cpp | 95 - src/base/bittorrent/trackerentry.h | 72 - src/base/filesystemwatcher.cpp | 276 - src/base/filesystemwatcher.h | 52 - src/base/global.h | 30 - src/base/http/connection.cpp | 144 - src/base/http/connection.h | 73 - src/base/http/irequesthandler.h | 45 - src/base/http/requestparser.cpp | 344 - src/base/http/requestparser.h | 72 - src/base/http/responsebuilder.cpp | 74 - src/base/http/responsebuilder.h | 58 - src/base/http/responsegenerator.cpp | 107 - src/base/http/responsegenerator.h | 45 - src/base/http/server.cpp | 167 - src/base/http/server.h | 82 - src/base/http/types.h | 110 - src/base/iconprovider.cpp | 64 - src/base/iconprovider.h | 55 - src/base/indexrange.h | 130 - src/base/logger.cpp | 97 - src/base/logger.h | 77 - src/base/net/dnsupdater.cpp | 301 - src/base/net/dnsupdater.h | 90 - src/base/net/downloadhandler.cpp | 248 - src/base/net/downloadhandler.h | 79 - src/base/net/downloadmanager.cpp | 230 - src/base/net/downloadmanager.h | 76 - src/base/net/geoipmanager.cpp | 462 - src/base/net/geoipmanager.h | 76 - src/base/net/portforwarder.cpp | 146 - src/base/net/portforwarder.h | 73 - src/base/net/private/geoipdatabase.cpp | 488 - src/base/net/private/geoipdatabase.h | 102 - src/base/net/proxyconfigurationmanager.cpp | 163 - src/base/net/proxyconfigurationmanager.h | 87 - src/base/net/reverseresolution.cpp | 90 - src/base/net/reverseresolution.h | 67 - src/base/net/smtp.cpp | 546 - src/base/net/smtp.h | 129 - src/base/preferences.cpp | 1477 --- src/base/preferences.h | 356 - src/base/private/profile_p.cpp | 194 - src/base/private/profile_p.h | 135 - src/base/profile.cpp | 118 - src/base/profile.h | 92 - src/base/rss/private/rss_parser.cpp | 460 - src/base/rss/private/rss_parser.h | 77 - src/base/rss/rss_article.cpp | 158 - src/base/rss/rss_article.h | 94 - src/base/rss/rss_autodownloader.cpp | 387 - src/base/rss/rss_autodownloader.h | 114 - src/base/rss/rss_autodownloadrule.cpp | 538 - src/base/rss/rss_autodownloadrule.h | 95 - src/base/rss/rss_feed.cpp | 451 - src/base/rss/rss_feed.h | 121 - src/base/rss/rss_folder.cpp | 143 - src/base/rss/rss_folder.h | 70 - src/base/rss/rss_item.cpp | 115 - src/base/rss/rss_item.h | 88 - src/base/rss/rss_session.cpp | 485 - src/base/rss/rss_session.h | 154 - src/base/scanfoldersmodel.cpp | 404 - src/base/scanfoldersmodel.h | 117 - src/base/searchengine.cpp | 683 -- src/base/searchengine.h | 152 - src/base/settingsstorage.cpp | 313 - src/base/settingsstorage.h | 65 - src/base/settingvalue.h | 115 - src/base/torrentfileguard.cpp | 89 - src/base/torrentfileguard.h | 86 - src/base/torrentfilter.cpp | 191 - src/base/torrentfilter.h | 101 - src/base/tristatebool.cpp | 58 - src/base/tristatebool.h | 53 - src/base/types.h | 46 - src/base/unicodestrings.h | 93 - src/base/utils/fs.cpp | 286 - src/base/utils/fs.h | 68 - src/base/utils/gzip.cpp | 151 - src/base/utils/gzip.h | 44 - src/base/utils/misc.cpp | 688 -- src/base/utils/misc.h | 116 - src/base/utils/net.cpp | 42 - src/base/utils/net.h | 41 - src/base/utils/random.cpp | 75 - src/base/utils/random.h | 44 - src/base/utils/string.cpp | 191 - src/base/utils/string.h | 68 - src/base/utils/version.h | 195 - src/config.h.cmakein | 14 - src/gui/CMakeLists.txt | 159 - src/gui/about.qrc | 7 - src/gui/about.ui | 461 - src/gui/about_imp.h | 104 - src/gui/addnewtorrentdialog.cpp | 790 -- src/gui/addnewtorrentdialog.h | 118 - src/gui/addnewtorrentdialog.ui | 478 - src/gui/advancedsettings.cpp | 412 - src/gui/advancedsettings.h | 96 - src/gui/autoexpandabledialog.cpp | 97 - src/gui/autoexpandabledialog.h | 60 - src/gui/autoexpandabledialog.ui | 64 - src/gui/bandwidth_limit.ui | 79 - src/gui/banlistoptions.cpp | 114 - src/gui/banlistoptions.h | 63 - src/gui/banlistoptions.ui | 127 - src/gui/categoryfiltermodel.cpp | 447 - src/gui/categoryfiltermodel.h | 81 - src/gui/categoryfilterproxymodel.cpp | 57 - src/gui/categoryfilterproxymodel.h | 52 - src/gui/categoryfilterwidget.cpp | 262 - src/gui/categoryfilterwidget.h | 64 - src/gui/confirmdeletiondlg.ui | 153 - src/gui/cookiesdialog.cpp | 102 - src/gui/cookiesdialog.h | 61 - src/gui/cookiesdialog.ui | 189 - src/gui/cookiesmodel.cpp | 178 - src/gui/cookiesmodel.h | 74 - src/gui/deletionconfirmationdlg.h | 86 - src/gui/downloadfromurldlg.h | 111 - src/gui/downloadfromurldlg.ui | 100 - src/gui/executionlog.cpp | 113 - src/gui/executionlog.h | 64 - src/gui/executionlog.ui | 55 - src/gui/fspathedit.cpp | 372 - src/gui/fspathedit.h | 151 - src/gui/fspathedit_p.cpp | 352 - src/gui/fspathedit_p.h | 164 - src/gui/gpl.html | 517 - src/gui/gui.pri | 149 - src/gui/guiiconprovider.cpp | 147 - src/gui/guiiconprovider.h | 64 - src/gui/hidabletabwidget.h | 69 - src/gui/lineedit/CMakeLists.txt | 16 - src/gui/lineedit/lineedit.pri | 4 - src/gui/lineedit/resources/lineeditimages.qrc | 6 - .../resources/lineeditimages/clear_left.png | Bin 241 -> 0 bytes .../resources/lineeditimages/search.png | Bin 292 -> 0 bytes src/gui/lineedit/src/lineedit.cpp | 44 - src/gui/lineedit/src/lineedit.h | 31 - src/gui/login.ui | 233 - src/gui/loglistwidget.cpp | 103 - src/gui/loglistwidget.h | 63 - src/gui/mainwindow.cpp | 2096 ---- src/gui/mainwindow.h | 264 - src/gui/mainwindow.ui | 472 - src/gui/messageboxraised.cpp | 63 - src/gui/messageboxraised.h | 59 - src/gui/optionsdlg.cpp | 1721 --- src/gui/optionsdlg.h | 191 - src/gui/optionsdlg.ui | 3438 ------ src/gui/powermanagement/CMakeLists.txt | 25 - src/gui/powermanagement/powermanagement.cpp | 90 - src/gui/powermanagement/powermanagement.h | 70 - src/gui/powermanagement/powermanagement.pri | 9 - .../powermanagement/powermanagement_x11.cpp | 185 - src/gui/powermanagement/powermanagement_x11.h | 71 - src/gui/preview.ui | 99 - src/gui/previewlistdelegate.h | 96 - src/gui/previewselect.cpp | 136 - src/gui/previewselect.h | 73 - src/gui/programupdater.cpp | 172 - src/gui/programupdater.h | 61 - src/gui/properties/CMakeLists.txt | 47 - src/gui/properties/downloadedpiecesbar.cpp | 180 - src/gui/properties/downloadedpiecesbar.h | 70 - src/gui/properties/peerlistdelegate.h | 124 - src/gui/properties/peerlistsortmodel.h | 63 - src/gui/properties/peerlistwidget.cpp | 473 - src/gui/properties/peerlistwidget.h | 102 - src/gui/properties/peersadditiondlg.cpp | 109 - src/gui/properties/peersadditiondlg.h | 66 - src/gui/properties/peersadditiondlg.ui | 72 - src/gui/properties/pieceavailabilitybar.cpp | 170 - src/gui/properties/pieceavailabilitybar.h | 63 - src/gui/properties/piecesbar.cpp | 338 - src/gui/properties/piecesbar.h | 109 - src/gui/properties/properties.pri | 33 - src/gui/properties/propertieswidget.cpp | 897 -- src/gui/properties/propertieswidget.h | 144 - src/gui/properties/propertieswidget.ui | 1116 -- src/gui/properties/proplistdelegate.cpp | 224 - src/gui/properties/proplistdelegate.h | 76 - src/gui/properties/proptabbar.cpp | 143 - src/gui/properties/proptabbar.h | 66 - src/gui/properties/speedplotview.cpp | 302 - src/gui/properties/speedplotview.h | 128 - src/gui/properties/speedwidget.cpp | 203 - src/gui/properties/speedwidget.h | 89 - src/gui/properties/trackerlist.cpp | 635 - src/gui/properties/trackerlist.h | 106 - src/gui/properties/trackersadditiondlg.cpp | 143 - src/gui/properties/trackersadditiondlg.h | 70 - src/gui/properties/trackersadditiondlg.ui | 98 - src/gui/qtnotify/CMakeLists.txt | 11 - src/gui/qtnotify/notifications.cpp | 26 - src/gui/qtnotify/notifications.h | 84 - src/gui/qtnotify/notifications.xml | 31 - src/gui/qtnotify/qtnotify.pri | 5 - src/gui/rss/CMakeLists.txt | 26 - src/gui/rss/articlelistwidget.cpp | 133 - src/gui/rss/articlelistwidget.h | 67 - src/gui/rss/automatedrssdownloader.cpp | 715 -- src/gui/rss/automatedrssdownloader.h | 109 - src/gui/rss/automatedrssdownloader.ui | 500 - src/gui/rss/feedlistwidget.cpp | 273 - src/gui/rss/feedlistwidget.h | 78 - src/gui/rss/htmlbrowser.cpp | 93 - src/gui/rss/htmlbrowser.h | 30 - src/gui/rss/rsswidget.cpp | 530 - src/gui/rss/rsswidget.h | 92 - src/gui/rss/rsswidget.ui | 210 - src/gui/scanfoldersdelegate.cpp | 118 - src/gui/scanfoldersdelegate.h | 63 - src/gui/search/CMakeLists.txt | 37 - src/gui/search/pluginselectdlg.cpp | 470 - src/gui/search/pluginselectdlg.h | 98 - src/gui/search/pluginselectdlg.ui | 142 - src/gui/search/pluginsourcedlg.cpp | 59 - src/gui/search/pluginsourcedlg.h | 61 - src/gui/search/pluginsourcedlg.ui | 53 - src/gui/search/searchlistdelegate.cpp | 73 - src/gui/search/searchlistdelegate.h | 45 - src/gui/search/searchsortmodel.cpp | 161 - src/gui/search/searchsortmodel.h | 96 - src/gui/search/searchtab.cpp | 348 - src/gui/search/searchtab.h | 123 - src/gui/search/searchtab.ui | 250 - src/gui/search/searchwidget.cpp | 474 - src/gui/search/searchwidget.h | 103 - src/gui/search/searchwidget.ui | 179 - src/gui/shutdownconfirmdlg.cpp | 139 - src/gui/shutdownconfirmdlg.h | 72 - src/gui/shutdownconfirmdlg.ui | 127 - src/gui/speedlimitdlg.cpp | 120 - src/gui/speedlimitdlg.h | 61 - src/gui/statsdialog.cpp | 105 - src/gui/statsdialog.h | 54 - src/gui/statsdialog.ui | 236 - src/gui/statusbar.cpp | 271 - src/gui/statusbar.h | 76 - src/gui/tagfiltermodel.cpp | 337 - src/gui/tagfiltermodel.h | 88 - src/gui/tagfilterproxymodel.cpp | 56 - src/gui/tagfilterproxymodel.h | 52 - src/gui/tagfilterwidget.cpp | 225 - src/gui/tagfilterwidget.h | 64 - src/gui/thanks.html | 15 - src/gui/torrentcontentfiltermodel.cpp | 145 - src/gui/torrentcontentfiltermodel.h | 67 - src/gui/torrentcontentmodel.cpp | 498 - src/gui/torrentcontentmodel.h | 84 - src/gui/torrentcontentmodelfile.cpp | 87 - src/gui/torrentcontentmodelfile.h | 52 - src/gui/torrentcontentmodelfolder.cpp | 198 - src/gui/torrentcontentmodelfolder.h | 67 - src/gui/torrentcontentmodelitem.cpp | 141 - src/gui/torrentcontentmodelitem.h | 107 - src/gui/torrentcontenttreeview.cpp | 87 - src/gui/torrentcontenttreeview.h | 46 - src/gui/torrentcreatordlg.cpp | 266 - src/gui/torrentcreatordlg.h | 90 - src/gui/torrentcreatordlg.ui | 356 - src/gui/torrentmodel.cpp | 478 - src/gui/torrentmodel.h | 107 - src/gui/trackerlogin.cpp | 62 - src/gui/trackerlogin.h | 61 - src/gui/transferlistdelegate.cpp | 286 - src/gui/transferlistdelegate.h | 58 - src/gui/transferlistfilterswidget.cpp | 702 -- src/gui/transferlistfilterswidget.h | 176 - src/gui/transferlistsortmodel.cpp | 254 - src/gui/transferlistsortmodel.h | 65 - src/gui/transferlistwidget.cpp | 1207 -- src/gui/transferlistwidget.h | 141 - src/gui/translators.html | 51 - src/gui/updownratiodlg.cpp | 127 - src/gui/updownratiodlg.h | 68 - src/gui/updownratiodlg.ui | 177 - src/icons.qrc | 381 - src/icons/3-state-checkbox.gif | Bin 322 -> 0 bytes src/icons/L.gif | Bin 66 -> 0 bytes src/icons/flags/ad.png | Bin 451 -> 0 bytes src/icons/flags/ae.png | Bin 330 -> 0 bytes src/icons/flags/af.png | Bin 418 -> 0 bytes src/icons/flags/ag.png | Bin 455 -> 0 bytes src/icons/flags/ai.png | Bin 516 -> 0 bytes src/icons/flags/al.png | Bin 431 -> 0 bytes src/icons/flags/am.png | Bin 331 -> 0 bytes src/icons/flags/an.png | Bin 409 -> 0 bytes src/icons/flags/ao.png | Bin 388 -> 0 bytes src/icons/flags/ar.png | Bin 364 -> 0 bytes src/icons/flags/as.png | Bin 538 -> 0 bytes src/icons/flags/at.png | Bin 290 -> 0 bytes src/icons/flags/au.png | Bin 579 -> 0 bytes src/icons/flags/aw.png | Bin 393 -> 0 bytes src/icons/flags/ax.png | Bin 476 -> 0 bytes src/icons/flags/az.png | Bin 420 -> 0 bytes src/icons/flags/ba.png | Bin 469 -> 0 bytes src/icons/flags/bb.png | Bin 402 -> 0 bytes src/icons/flags/bd.png | Bin 368 -> 0 bytes src/icons/flags/be.png | Bin 294 -> 0 bytes src/icons/flags/bf.png | Bin 341 -> 0 bytes src/icons/flags/bg.png | Bin 320 -> 0 bytes src/icons/flags/bh.png | Bin 376 -> 0 bytes src/icons/flags/bi.png | Bin 564 -> 0 bytes src/icons/flags/bj.png | Bin 310 -> 0 bytes src/icons/flags/bm.png | Bin 499 -> 0 bytes src/icons/flags/bn.png | Bin 500 -> 0 bytes src/icons/flags/bo.png | Bin 341 -> 0 bytes src/icons/flags/br.png | Bin 477 -> 0 bytes src/icons/flags/bs.png | Bin 391 -> 0 bytes src/icons/flags/bt.png | Bin 470 -> 0 bytes src/icons/flags/bv.png | Bin 397 -> 0 bytes src/icons/flags/bw.png | Bin 326 -> 0 bytes src/icons/flags/by.png | Bin 382 -> 0 bytes src/icons/flags/bz.png | Bin 474 -> 0 bytes src/icons/flags/ca.png | Bin 470 -> 0 bytes src/icons/flags/cc.png | Bin 493 -> 0 bytes src/icons/flags/cd.png | Bin 476 -> 0 bytes src/icons/flags/cf.png | Bin 454 -> 0 bytes src/icons/flags/cg.png | Bin 379 -> 0 bytes src/icons/flags/ch.png | Bin 287 -> 0 bytes src/icons/flags/ci.png | Bin 304 -> 0 bytes src/icons/flags/ck.png | Bin 488 -> 0 bytes src/icons/flags/cl.png | Bin 324 -> 0 bytes src/icons/flags/cm.png | Bin 347 -> 0 bytes src/icons/flags/cn.png | Bin 349 -> 0 bytes src/icons/flags/co.png | Bin 330 -> 0 bytes src/icons/flags/cr.png | Bin 349 -> 0 bytes src/icons/flags/cs.png | Bin 376 -> 0 bytes src/icons/flags/cu.png | Bin 440 -> 0 bytes src/icons/flags/cv.png | Bin 437 -> 0 bytes src/icons/flags/cx.png | Bin 489 -> 0 bytes src/icons/flags/cy.png | Bin 348 -> 0 bytes src/icons/flags/cz.png | Bin 363 -> 0 bytes src/icons/flags/de.png | Bin 359 -> 0 bytes src/icons/flags/dj.png | Bin 429 -> 0 bytes src/icons/flags/dk.png | Bin 352 -> 0 bytes src/icons/flags/dm.png | Bin 507 -> 0 bytes src/icons/flags/do.png | Bin 368 -> 0 bytes src/icons/flags/dz.png | Bin 452 -> 0 bytes src/icons/flags/ec.png | Bin 355 -> 0 bytes src/icons/flags/ee.png | Bin 351 -> 0 bytes src/icons/flags/eg.png | Bin 348 -> 0 bytes src/icons/flags/eh.png | Bin 386 -> 0 bytes src/icons/flags/er.png | Bin 496 -> 0 bytes src/icons/flags/es.png | Bin 342 -> 0 bytes src/icons/flags/et.png | Bin 445 -> 0 bytes src/icons/flags/fi.png | Bin 362 -> 0 bytes src/icons/flags/fj.png | Bin 516 -> 0 bytes src/icons/flags/fk.png | Bin 526 -> 0 bytes src/icons/flags/fm.png | Bin 406 -> 0 bytes src/icons/flags/fo.png | Bin 396 -> 0 bytes src/icons/flags/fr.png | Bin 367 -> 0 bytes src/icons/flags/ga.png | Bin 342 -> 0 bytes src/icons/flags/gb.png | Bin 545 -> 0 bytes src/icons/flags/gd.png | Bin 458 -> 0 bytes src/icons/flags/ge.png | Bin 492 -> 0 bytes src/icons/flags/gf.png | Bin 367 -> 0 bytes src/icons/flags/gh.png | Bin 336 -> 0 bytes src/icons/flags/gi.png | Bin 383 -> 0 bytes src/icons/flags/gl.png | Bin 351 -> 0 bytes src/icons/flags/gm.png | Bin 362 -> 0 bytes src/icons/flags/gn.png | Bin 319 -> 0 bytes src/icons/flags/gp.png | Bin 353 -> 0 bytes src/icons/flags/gq.png | Bin 404 -> 0 bytes src/icons/flags/gr.png | Bin 389 -> 0 bytes src/icons/flags/gs.png | Bin 522 -> 0 bytes src/icons/flags/gt.png | Bin 331 -> 0 bytes src/icons/flags/gu.png | Bin 384 -> 0 bytes src/icons/flags/gw.png | Bin 346 -> 0 bytes src/icons/flags/gy.png | Bin 520 -> 0 bytes src/icons/flags/hk.png | Bin 393 -> 0 bytes src/icons/flags/hm.png | Bin 579 -> 0 bytes src/icons/flags/hn.png | Bin 411 -> 0 bytes src/icons/flags/hr.png | Bin 384 -> 0 bytes src/icons/flags/ht.png | Bin 326 -> 0 bytes src/icons/flags/hu.png | Bin 293 -> 0 bytes src/icons/flags/icons-set-readme.txt | 9 - src/icons/flags/id.png | Bin 350 -> 0 bytes src/icons/flags/ie.png | Bin 330 -> 0 bytes src/icons/flags/il.png | Bin 350 -> 0 bytes src/icons/flags/in.png | Bin 376 -> 0 bytes src/icons/flags/io.png | Bin 575 -> 0 bytes src/icons/flags/iq.png | Bin 402 -> 0 bytes src/icons/flags/ir.png | Bin 397 -> 0 bytes src/icons/flags/is.png | Bin 410 -> 0 bytes src/icons/flags/it.png | Bin 339 -> 0 bytes src/icons/flags/jm.png | Bin 499 -> 0 bytes src/icons/flags/jo.png | Bin 353 -> 0 bytes src/icons/flags/jp.png | Bin 340 -> 0 bytes src/icons/flags/ke.png | Bin 434 -> 0 bytes src/icons/flags/kg.png | Bin 353 -> 0 bytes src/icons/flags/kh.png | Bin 422 -> 0 bytes src/icons/flags/ki.png | Bin 544 -> 0 bytes src/icons/flags/km.png | Bin 452 -> 0 bytes src/icons/flags/kn.png | Bin 475 -> 0 bytes src/icons/flags/kp.png | Bin 423 -> 0 bytes src/icons/flags/kr.png | Bin 506 -> 0 bytes src/icons/flags/kw.png | Bin 350 -> 0 bytes src/icons/flags/ky.png | Bin 529 -> 0 bytes src/icons/flags/kz.png | Bin 454 -> 0 bytes src/icons/flags/la.png | Bin 414 -> 0 bytes src/icons/flags/lb.png | Bin 393 -> 0 bytes src/icons/flags/lc.png | Bin 459 -> 0 bytes src/icons/flags/li.png | Bin 399 -> 0 bytes src/icons/flags/lk.png | Bin 462 -> 0 bytes src/icons/flags/lr.png | Bin 385 -> 0 bytes src/icons/flags/ls.png | Bin 498 -> 0 bytes src/icons/flags/lt.png | Bin 344 -> 0 bytes src/icons/flags/lu.png | Bin 337 -> 0 bytes src/icons/flags/lv.png | Bin 339 -> 0 bytes src/icons/flags/ly.png | Bin 276 -> 0 bytes src/icons/flags/ma.png | Bin 293 -> 0 bytes src/icons/flags/mc.png | Bin 302 -> 0 bytes src/icons/flags/md.png | Bin 403 -> 0 bytes src/icons/flags/me.png | Bin 392 -> 0 bytes src/icons/flags/mg.png | Bin 313 -> 0 bytes src/icons/flags/mh.png | Bin 516 -> 0 bytes src/icons/flags/mk.png | Bin 442 -> 0 bytes src/icons/flags/ml.png | Bin 322 -> 0 bytes src/icons/flags/mm.png | Bin 336 -> 0 bytes src/icons/flags/mn.png | Bin 342 -> 0 bytes src/icons/flags/mo.png | Bin 456 -> 0 bytes src/icons/flags/mp.png | Bin 481 -> 0 bytes src/icons/flags/mq.png | Bin 539 -> 0 bytes src/icons/flags/mr.png | Bin 408 -> 0 bytes src/icons/flags/ms.png | Bin 497 -> 0 bytes src/icons/flags/mt.png | Bin 340 -> 0 bytes src/icons/flags/mu.png | Bin 360 -> 0 bytes src/icons/flags/mv.png | Bin 391 -> 0 bytes src/icons/flags/mw.png | Bin 365 -> 0 bytes src/icons/flags/mx.png | Bin 422 -> 0 bytes src/icons/flags/my.png | Bin 460 -> 0 bytes src/icons/flags/mz.png | Bin 438 -> 0 bytes src/icons/flags/na.png | Bin 555 -> 0 bytes src/icons/flags/nc.png | Bin 469 -> 0 bytes src/icons/flags/ne.png | Bin 391 -> 0 bytes src/icons/flags/nf.png | Bin 472 -> 0 bytes src/icons/flags/ng.png | Bin 339 -> 0 bytes src/icons/flags/ni.png | Bin 370 -> 0 bytes src/icons/flags/nl.png | Bin 309 -> 0 bytes src/icons/flags/no.png | Bin 397 -> 0 bytes src/icons/flags/np.png | Bin 387 -> 0 bytes src/icons/flags/nr.png | Bin 391 -> 0 bytes src/icons/flags/nu.png | Bin 465 -> 0 bytes src/icons/flags/nz.png | Bin 529 -> 0 bytes src/icons/flags/om.png | Bin 339 -> 0 bytes src/icons/flags/pa.png | Bin 390 -> 0 bytes src/icons/flags/pe.png | Bin 317 -> 0 bytes src/icons/flags/pf.png | Bin 379 -> 0 bytes src/icons/flags/pg.png | Bin 438 -> 0 bytes src/icons/flags/ph.png | Bin 413 -> 0 bytes src/icons/flags/pk.png | Bin 448 -> 0 bytes src/icons/flags/pl.png | Bin 293 -> 0 bytes src/icons/flags/pm.png | Bin 566 -> 0 bytes src/icons/flags/pn.png | Bin 544 -> 0 bytes src/icons/flags/pr.png | Bin 440 -> 0 bytes src/icons/flags/ps.png | Bin 391 -> 0 bytes src/icons/flags/pt.png | Bin 407 -> 0 bytes src/icons/flags/pw.png | Bin 423 -> 0 bytes src/icons/flags/py.png | Bin 343 -> 0 bytes src/icons/flags/qa.png | Bin 369 -> 0 bytes src/icons/flags/re.png | Bin 367 -> 0 bytes src/icons/flags/ro.png | Bin 333 -> 0 bytes src/icons/flags/rs.png | Bin 376 -> 0 bytes src/icons/flags/ru.png | Bin 297 -> 0 bytes src/icons/flags/rw.png | Bin 382 -> 0 bytes src/icons/flags/sa.png | Bin 428 -> 0 bytes src/icons/flags/sb.png | Bin 519 -> 0 bytes src/icons/flags/sc.png | Bin 480 -> 0 bytes src/icons/flags/sd.png | Bin 364 -> 0 bytes src/icons/flags/se.png | Bin 389 -> 0 bytes src/icons/flags/sg.png | Bin 349 -> 0 bytes src/icons/flags/sh.png | Bin 516 -> 0 bytes src/icons/flags/si.png | Bin 383 -> 0 bytes src/icons/flags/sj.png | Bin 397 -> 0 bytes src/icons/flags/sk.png | Bin 436 -> 0 bytes src/icons/flags/sl.png | Bin 321 -> 0 bytes src/icons/flags/sm.png | Bin 396 -> 0 bytes src/icons/flags/sn.png | Bin 356 -> 0 bytes src/icons/flags/so.png | Bin 376 -> 0 bytes src/icons/flags/sr.png | Bin 369 -> 0 bytes src/icons/flags/st.png | Bin 427 -> 0 bytes src/icons/flags/sv.png | Bin 371 -> 0 bytes src/icons/flags/sy.png | Bin 344 -> 0 bytes src/icons/flags/sz.png | Bin 505 -> 0 bytes src/icons/flags/tc.png | Bin 509 -> 0 bytes src/icons/flags/td.png | Bin 378 -> 0 bytes src/icons/flags/tf.png | Bin 397 -> 0 bytes src/icons/flags/tg.png | Bin 407 -> 0 bytes src/icons/flags/th.png | Bin 327 -> 0 bytes src/icons/flags/tj.png | Bin 416 -> 0 bytes src/icons/flags/tk.png | Bin 519 -> 0 bytes src/icons/flags/tl.png | Bin 395 -> 0 bytes src/icons/flags/tm.png | Bin 456 -> 0 bytes src/icons/flags/tn.png | Bin 366 -> 0 bytes src/icons/flags/to.png | Bin 346 -> 0 bytes src/icons/flags/tr.png | Bin 365 -> 0 bytes src/icons/flags/tt.png | Bin 484 -> 0 bytes src/icons/flags/tv.png | Bin 437 -> 0 bytes src/icons/flags/tw.png | Bin 330 -> 0 bytes src/icons/flags/tz.png | Bin 509 -> 0 bytes src/icons/flags/ua.png | Bin 303 -> 0 bytes src/icons/flags/ug.png | Bin 387 -> 0 bytes src/icons/flags/um.png | Bin 454 -> 0 bytes src/icons/flags/us.png | Bin 488 -> 0 bytes src/icons/flags/uy.png | Bin 409 -> 0 bytes src/icons/flags/uz.png | Bin 410 -> 0 bytes src/icons/flags/va.png | Bin 419 -> 0 bytes src/icons/flags/vc.png | Bin 411 -> 0 bytes src/icons/flags/ve.png | Bin 404 -> 0 bytes src/icons/flags/vg.png | Bin 508 -> 0 bytes src/icons/flags/vi.png | Bin 521 -> 0 bytes src/icons/flags/vn.png | Bin 324 -> 0 bytes src/icons/flags/vu.png | Bin 448 -> 0 bytes src/icons/flags/wf.png | Bin 437 -> 0 bytes src/icons/flags/ws.png | Bin 352 -> 0 bytes src/icons/flags/ye.png | Bin 302 -> 0 bytes src/icons/flags/yt.png | Bin 456 -> 0 bytes src/icons/flags/za.png | Bin 522 -> 0 bytes src/icons/flags/zm.png | Bin 359 -> 0 bytes src/icons/flags/zw.png | Bin 462 -> 0 bytes src/icons/loading.png | Bin 178 -> 0 bytes src/icons/qbittorrent.desktop | 190 - src/icons/qbittorrent.png | Bin 36987 -> 0 bytes src/icons/qbt-theme/README.md | 7 - src/icons/qbt-theme/application-exit.png | Bin 5650 -> 0 bytes src/icons/qbt-theme/application-rss+xml.png | Bin 7901 -> 0 bytes .../qbt-theme/application-x-mswinurl.png | Bin 12210 -> 0 bytes src/icons/qbt-theme/build-icons/Gruntfile.js | 22 - .../build-icons/icons/application-exit.svg | 13 - .../build-icons/icons/application-rss+xml.svg | 17 - .../icons/application-x-mswinurl.svg | 74 - .../qbt-theme/build-icons/icons/checked.svg | 11 - .../qbt-theme/build-icons/icons/configure.svg | 28 - .../build-icons/icons/dialog-cancel.svg | 14 - .../build-icons/icons/dialog-information.svg | 17 - .../build-icons/icons/dialog-warning.svg | 15 - .../icons/document-edit-verify.svg | 20 - .../build-icons/icons/document-edit.svg | 20 - .../build-icons/icons/document-encrypt.svg | 13 - .../build-icons/icons/document-import.svg | 22 - .../build-icons/icons/document-new.svg | 23 - .../build-icons/icons/document-properties.svg | 28 - .../build-icons/icons/document-save.svg | 16 - .../qbt-theme/build-icons/icons/download.svg | 16 - .../build-icons/icons/edit-clear-history.svg | 43 - .../build-icons/icons/edit-clear.svg | 40 - .../qbt-theme/build-icons/icons/edit-copy.svg | 21 - .../qbt-theme/build-icons/icons/edit-cut.svg | 31 - .../build-icons/icons/edit-delete.svg | 13 - .../build-icons/icons/edit-find-user.svg | 45 - .../qbt-theme/build-icons/icons/edit-find.svg | 21 - .../build-icons/icons/edit-paste.svg | 21 - .../build-icons/icons/edit-rename.svg | 23 - .../build-icons/icons/folder-documents.svg | 23 - .../build-icons/icons/folder-download.svg | 16 - .../build-icons/icons/folder-new.svg | 31 - .../build-icons/icons/folder-remote.svg | 141 - .../qbt-theme/build-icons/icons/gear.svg | 28 - .../qbt-theme/build-icons/icons/gear32.svg | 28 - .../qbt-theme/build-icons/icons/go-bottom.svg | 17 - .../qbt-theme/build-icons/icons/go-down.svg | 16 - .../qbt-theme/build-icons/icons/go-top.svg | 17 - .../qbt-theme/build-icons/icons/go-up.svg | 17 - .../build-icons/icons/help-about.svg | 17 - .../build-icons/icons/help-contents.svg | 22 - .../build-icons/icons/inode-directory.svg | 23 - .../build-icons/icons/insert-link.svg | 39 - .../qbt-theme/build-icons/icons/list-add.svg | 23 - .../build-icons/icons/list-remove.svg | 10 - .../build-icons/icons/mail-folder-inbox.svg | 12 - .../build-icons/icons/mail-mark-read.svg | 23 - .../icons/media-playback-pause.svg | 13 - .../icons/media-playback-start.svg | 10 - .../build-icons/icons/media-seek-forward.svg | 10 - .../build-icons/icons/network-server.svg | 19 - .../build-icons/icons/network-wired.svg | 11 - .../build-icons/icons/object-locked.svg | 13 - .../build-icons/icons/office-chart-line.svg | 11 - .../build-icons/icons/preferences-desktop.svg | 29 - .../build-icons/icons/preferences-other.svg | 36 - .../icons/preferences-system-network.svg | 85 - .../icons/preferences-web-browser-cookies.svg | 14 - .../build-icons/icons/security-high.svg | 21 - .../build-icons/icons/security-low.svg | 25 - .../qbt-theme/build-icons/icons/services.svg | 15 - .../build-icons/icons/speedometer.svg | 22 - .../build-icons/icons/system-log-out.svg | 17 - .../qbt-theme/build-icons/icons/tab-close.svg | 18 - .../build-icons/icons/task-attention.svg | 15 - .../build-icons/icons/text-plain.svg | 18 - .../build-icons/icons/tools-report-bug.svg | 17 - .../build-icons/icons/unavailable.svg | 15 - .../build-icons/icons/user-group-delete.svg | 35 - .../build-icons/icons/user-group-new.svg | 34 - .../icons/view-calendar-journal.svg | 18 - .../build-icons/icons/view-categories.svg | 22 - .../build-icons/icons/view-filter.svg | 11 - .../build-icons/icons/view-preview.svg | 14 - .../build-icons/icons/view-refresh.svg | 17 - .../build-icons/icons/view-statistics.svg | 10 - .../build-icons/icons/wallet-open.svg | 11 - .../qbt-theme/build-icons/icons/webui.svg | 79 - src/icons/qbt-theme/build-icons/package.json | 13 - src/icons/qbt-theme/build-icons/readme.md | 14 - src/icons/qbt-theme/checked.png | Bin 3110 -> 0 bytes src/icons/qbt-theme/configure.png | Bin 6559 -> 0 bytes src/icons/qbt-theme/dialog-cancel.png | Bin 9288 -> 0 bytes src/icons/qbt-theme/dialog-information.png | Bin 6785 -> 0 bytes src/icons/qbt-theme/dialog-warning.png | Bin 5776 -> 0 bytes src/icons/qbt-theme/document-edit-verify.png | Bin 6164 -> 0 bytes src/icons/qbt-theme/document-edit.png | Bin 3721 -> 0 bytes src/icons/qbt-theme/document-encrypt.png | Bin 4075 -> 0 bytes src/icons/qbt-theme/document-import.png | Bin 3626 -> 0 bytes src/icons/qbt-theme/document-new.png | Bin 3017 -> 0 bytes src/icons/qbt-theme/document-properties.png | Bin 5604 -> 0 bytes src/icons/qbt-theme/document-save.png | Bin 3083 -> 0 bytes src/icons/qbt-theme/download.png | Bin 3607 -> 0 bytes src/icons/qbt-theme/edit-clear-history.png | Bin 5906 -> 0 bytes src/icons/qbt-theme/edit-clear.png | Bin 5123 -> 0 bytes src/icons/qbt-theme/edit-copy.png | Bin 3130 -> 0 bytes src/icons/qbt-theme/edit-cut.png | Bin 12221 -> 0 bytes src/icons/qbt-theme/edit-delete.png | Bin 5650 -> 0 bytes src/icons/qbt-theme/edit-find-user.png | Bin 10856 -> 0 bytes src/icons/qbt-theme/edit-find.png | Bin 6808 -> 0 bytes src/icons/qbt-theme/edit-paste.png | Bin 2521 -> 0 bytes src/icons/qbt-theme/edit-rename.png | Bin 4721 -> 0 bytes src/icons/qbt-theme/folder-documents.png | Bin 5721 -> 0 bytes src/icons/qbt-theme/folder-download.png | Bin 3607 -> 0 bytes src/icons/qbt-theme/folder-new.png | Bin 6082 -> 0 bytes src/icons/qbt-theme/folder-remote.png | Bin 16124 -> 0 bytes src/icons/qbt-theme/gear.png | Bin 6559 -> 0 bytes src/icons/qbt-theme/gear32.png | Bin 6559 -> 0 bytes src/icons/qbt-theme/go-bottom.png | Bin 1905 -> 0 bytes src/icons/qbt-theme/go-down.png | Bin 1544 -> 0 bytes src/icons/qbt-theme/go-top.png | Bin 1926 -> 0 bytes src/icons/qbt-theme/go-up.png | Bin 2733 -> 0 bytes src/icons/qbt-theme/help-about.png | Bin 6785 -> 0 bytes src/icons/qbt-theme/help-contents.png | Bin 4336 -> 0 bytes src/icons/qbt-theme/inode-directory.png | Bin 5721 -> 0 bytes src/icons/qbt-theme/insert-link.png | Bin 8920 -> 0 bytes src/icons/qbt-theme/kt-magnet.png | Bin 4391 -> 0 bytes .../qbt-theme/kt-set-max-download-speed.png | Bin 435 -> 0 bytes .../qbt-theme/kt-set-max-upload-speed.png | Bin 406 -> 0 bytes src/icons/qbt-theme/list-add.png | Bin 3017 -> 0 bytes src/icons/qbt-theme/list-remove.png | Bin 1056 -> 0 bytes src/icons/qbt-theme/mail-folder-inbox.png | Bin 3509 -> 0 bytes src/icons/qbt-theme/mail-mark-read.png | Bin 7078 -> 0 bytes src/icons/qbt-theme/media-playback-pause.png | Bin 1294 -> 0 bytes src/icons/qbt-theme/media-playback-start.png | Bin 3909 -> 0 bytes src/icons/qbt-theme/media-seek-forward.png | Bin 2866 -> 0 bytes src/icons/qbt-theme/network-server.png | Bin 3151 -> 0 bytes src/icons/qbt-theme/network-wired.png | Bin 3155 -> 0 bytes src/icons/qbt-theme/object-locked.png | Bin 4075 -> 0 bytes src/icons/qbt-theme/office-chart-line.png | Bin 2406 -> 0 bytes src/icons/qbt-theme/preferences-desktop.png | Bin 7108 -> 0 bytes src/icons/qbt-theme/preferences-other.png | Bin 11027 -> 0 bytes .../qbt-theme/preferences-system-network.png | Bin 13849 -> 0 bytes .../preferences-web-browser-cookies.png | Bin 8657 -> 0 bytes src/icons/qbt-theme/rss-config.png | Bin 1949 -> 0 bytes src/icons/qbt-theme/security-high.png | Bin 6508 -> 0 bytes src/icons/qbt-theme/security-low.png | Bin 8027 -> 0 bytes src/icons/qbt-theme/services.png | Bin 3872 -> 0 bytes src/icons/qbt-theme/speedometer.png | Bin 9542 -> 0 bytes src/icons/qbt-theme/system-log-out.png | Bin 3635 -> 0 bytes src/icons/qbt-theme/tab-close.png | Bin 4931 -> 0 bytes src/icons/qbt-theme/task-attention.png | Bin 5776 -> 0 bytes src/icons/qbt-theme/task-complete.png | Bin 756 -> 0 bytes src/icons/qbt-theme/task-ongoing.png | Bin 958 -> 0 bytes src/icons/qbt-theme/task-reject.png | Bin 842 -> 0 bytes src/icons/qbt-theme/text-plain.png | Bin 3044 -> 0 bytes src/icons/qbt-theme/tools-report-bug.png | Bin 5202 -> 0 bytes src/icons/qbt-theme/unavailable.png | Bin 6995 -> 0 bytes src/icons/qbt-theme/user-group-delete.png | Bin 11095 -> 0 bytes src/icons/qbt-theme/user-group-new.png | Bin 9531 -> 0 bytes src/icons/qbt-theme/view-calendar-journal.png | Bin 3371 -> 0 bytes src/icons/qbt-theme/view-categories.png | Bin 2744 -> 0 bytes src/icons/qbt-theme/view-filter.png | Bin 2156 -> 0 bytes src/icons/qbt-theme/view-preview.png | Bin 4088 -> 0 bytes src/icons/qbt-theme/view-refresh.png | Bin 5942 -> 0 bytes src/icons/qbt-theme/view-statistics.png | Bin 1120 -> 0 bytes src/icons/qbt-theme/wallet-open.png | Bin 1593 -> 0 bytes src/icons/qbt-theme/webui.png | Bin 10567 -> 0 bytes src/icons/skin/arrow-right.gif | Bin 54 -> 0 bytes src/icons/skin/bg-dropdown.gif | Bin 53 -> 0 bytes src/icons/skin/bg-handle-horizontal.gif | Bin 57 -> 0 bytes src/icons/skin/bg-header.gif | Bin 91 -> 0 bytes src/icons/skin/bg-panel-header.gif | Bin 229 -> 0 bytes src/icons/skin/build-icons/Gruntfile.js | 22 - src/icons/skin/build-icons/icons/checking.svg | 29 - .../skin/build-icons/icons/completed.svg | 13 - .../skin/build-icons/icons/connected.svg | 9 - .../skin/build-icons/icons/disconnected.svg | 9 - src/icons/skin/build-icons/icons/download.svg | 9 - .../skin/build-icons/icons/downloading.svg | 9 - src/icons/skin/build-icons/icons/error.svg | 10 - .../skin/build-icons/icons/filteractive.svg | 9 - .../skin/build-icons/icons/filterall.svg | 9 - .../skin/build-icons/icons/filterinactive.svg | 9 - .../skin/build-icons/icons/firewalled.svg | 15 - src/icons/skin/build-icons/icons/paused.svg | 10 - src/icons/skin/build-icons/icons/queued.svg | 16 - src/icons/skin/build-icons/icons/ratio.svg | 12 - src/icons/skin/build-icons/icons/resumed.svg | 8 - src/icons/skin/build-icons/icons/seeding.svg | 9 - .../skin/build-icons/icons/stalledDL.svg | 9 - .../skin/build-icons/icons/stalledUP.svg | 9 - .../skin/build-icons/icons/uploading.svg | 9 - src/icons/skin/build-icons/package.json | 13 - src/icons/skin/build-icons/readme.md | 14 - src/icons/skin/checking.png | Bin 6344 -> 0 bytes src/icons/skin/collapse-expand.gif | Bin 198 -> 0 bytes src/icons/skin/completed.png | Bin 3598 -> 0 bytes src/icons/skin/connected.png | Bin 5566 -> 0 bytes src/icons/skin/disconnected.png | Bin 5540 -> 0 bytes src/icons/skin/dock-tabs.gif | Bin 404 -> 0 bytes src/icons/skin/download.png | Bin 3516 -> 0 bytes src/icons/skin/downloading.png | Bin 2312 -> 0 bytes src/icons/skin/error.png | Bin 2478 -> 0 bytes src/icons/skin/filteractive.png | Bin 3310 -> 0 bytes src/icons/skin/filterall.png | Bin 3331 -> 0 bytes src/icons/skin/filterinactive.png | Bin 3256 -> 0 bytes src/icons/skin/firewalled.png | Bin 4533 -> 0 bytes src/icons/skin/handle-icon-horizontal.gif | Bin 46 -> 0 bytes src/icons/skin/handle-icon.gif | Bin 46 -> 0 bytes src/icons/skin/knob.gif | Bin 198 -> 0 bytes src/icons/skin/logo-blank.gif | Bin 979 -> 0 bytes src/icons/skin/logo.gif | Bin 2031 -> 0 bytes src/icons/skin/logo2.gif | Bin 1610 -> 0 bytes src/icons/skin/mascot.png | Bin 21876 -> 0 bytes src/icons/skin/paused.png | Bin 1441 -> 0 bytes src/icons/skin/qbittorrent-tray-dark.svg | 83 - src/icons/skin/qbittorrent-tray-light.svg | 83 - src/icons/skin/qbittorrent16.png | Bin 899 -> 0 bytes src/icons/skin/qbittorrent22.png | Bin 1352 -> 0 bytes src/icons/skin/qbittorrent32.png | Bin 2510 -> 0 bytes src/icons/skin/queued.png | Bin 7189 -> 0 bytes src/icons/skin/ratio.png | Bin 3762 -> 0 bytes src/icons/skin/resumed.png | Bin 4040 -> 0 bytes src/icons/skin/seeding.png | Bin 3469 -> 0 bytes src/icons/skin/slider-area.gif | Bin 78 -> 0 bytes src/icons/skin/spacer.gif | Bin 49 -> 0 bytes src/icons/skin/spinner-placeholder.gif | Bin 80 -> 0 bytes src/icons/skin/spinner.gif | Bin 793 -> 0 bytes src/icons/skin/splash.png | Bin 66403 -> 0 bytes src/icons/skin/stalledDL.png | Bin 2282 -> 0 bytes src/icons/skin/stalledUP.png | Bin 2319 -> 0 bytes src/icons/skin/tabs.gif | Bin 2060 -> 0 bytes src/icons/skin/toolbox-divider.gif | Bin 48 -> 0 bytes src/icons/skin/toolbox-divider2.gif | Bin 56 -> 0 bytes src/icons/skin/uploading.png | Bin 2364 -> 0 bytes src/icons/slow.png | Bin 1375 -> 0 bytes src/icons/slow_off.png | Bin 1414 -> 0 bytes src/icons/sphere.png | Bin 277 -> 0 bytes src/icons/sphere2.png | Bin 277 -> 0 bytes src/icons/url.png | Bin 646 -> 0 bytes src/lang.qrc | 54 - src/lang/TRANSLATION_INSTRUCTIONS | 42 - src/lang/qbittorrent_ar.ts | 9164 -------------- src/lang/qbittorrent_be.ts | 9176 -------------- src/lang/qbittorrent_bg.ts | 9183 -------------- src/lang/qbittorrent_ca.ts | 9218 -------------- src/lang/qbittorrent_cs.ts | 9184 -------------- src/lang/qbittorrent_da.ts | 9219 -------------- src/lang/qbittorrent_de.ts | 9220 -------------- src/lang/qbittorrent_el.ts | 9184 -------------- src/lang/qbittorrent_en.ts | 9159 -------------- src/lang/qbittorrent_en_AU.ts | 9611 --------------- src/lang/qbittorrent_en_GB.ts | 9619 --------------- src/lang/qbittorrent_eo.ts | 9171 -------------- src/lang/qbittorrent_es.ts | 9219 -------------- src/lang/qbittorrent_eu.ts | 9218 -------------- src/lang/qbittorrent_fi.ts | 9165 -------------- src/lang/qbittorrent_fr.ts | 9182 -------------- src/lang/qbittorrent_gl.ts | 9208 -------------- src/lang/qbittorrent_he.ts | 9217 -------------- src/lang/qbittorrent_hi_IN.ts | 9592 --------------- src/lang/qbittorrent_hr.ts | 9181 -------------- src/lang/qbittorrent_hu.ts | 9178 -------------- src/lang/qbittorrent_hy.ts | 9614 --------------- src/lang/qbittorrent_id.ts | 9182 -------------- src/lang/qbittorrent_is.ts | 9430 -------------- src/lang/qbittorrent_it.ts | 9217 -------------- src/lang/qbittorrent_ja.ts | 9182 -------------- src/lang/qbittorrent_ka.ts | 9612 --------------- src/lang/qbittorrent_ko.ts | 9219 -------------- src/lang/qbittorrent_lt.ts | 9195 -------------- src/lang/qbittorrent_lv_LV.ts | 9179 -------------- src/lang/qbittorrent_ms_MY.ts | 9182 -------------- src/lang/qbittorrent_nb.ts | 9208 -------------- src/lang/qbittorrent_nl.ts | 9183 -------------- src/lang/qbittorrent_oc.ts | 9182 -------------- src/lang/qbittorrent_pl.ts | 9218 -------------- src/lang/qbittorrent_pt_BR.ts | 9218 -------------- src/lang/qbittorrent_pt_PT.ts | 9182 -------------- src/lang/qbittorrent_ro.ts | 9183 -------------- src/lang/qbittorrent_ru.ts | 9218 -------------- src/lang/qbittorrent_sk.ts | 9185 -------------- src/lang/qbittorrent_sl.ts | 9183 -------------- src/lang/qbittorrent_sr.ts | 10140 ---------------- src/lang/qbittorrent_sv.ts | 9171 -------------- src/lang/qbittorrent_tr.ts | 9218 -------------- src/lang/qbittorrent_uk.ts | 9212 -------------- src/lang/qbittorrent_uz@Latn.ts | 9165 -------------- src/lang/qbittorrent_vi.ts | 9160 -------------- src/lang/qbittorrent_zh.ts | 9218 -------------- src/lang/qbittorrent_zh_HK.ts | 9180 -------------- src/lang/qbittorrent_zh_TW.ts | 9217 -------------- src/qbittorrent.exe.manifest | 39 - src/qbittorrent.ico | Bin 170966 -> 0 bytes src/qbittorrent.rc | Bin 2868 -> 0 bytes src/qbittorrent_file.ico | Bin 176650 -> 0 bytes src/qbittorrent_mingw.rc | 3 - src/qbittorrent_os2.ico | Bin 3428 -> 0 bytes src/qbittorrent_os2.rc | 1 - src/searchengine.qrc | 16 - src/searchengine/nova/__init__.py | 0 src/searchengine/nova/fix_encoding.py | 371 - src/searchengine/nova/helpers.py | 115 - src/searchengine/nova/nova2.py | 184 - src/searchengine/nova/nova2dl.py | 61 - src/searchengine/nova/novaprinter.py | 68 - src/searchengine/nova/socks.py | 391 - src/searchengine/nova3/__init__.py | 0 src/searchengine/nova3/helpers.py | 114 - src/searchengine/nova3/nova2.py | 183 - src/searchengine/nova3/nova2dl.py | 61 - src/searchengine/nova3/novaprinter.py | 63 - src/searchengine/nova3/sgmllib3.py | 547 - src/searchengine/nova3/socks.py | 391 - src/src.pro | 82 - src/update_qrc_files.py | 92 - src/webui/CMakeLists.txt | 24 - src/webui/abstractwebapplication.cpp | 487 - src/webui/abstractwebapplication.h | 116 - src/webui/btjson.cpp | 1065 -- src/webui/btjson.h | 62 - src/webui/extra_translations.h | 93 - src/webui/jsonutils.h | 51 - src/webui/prefjson.cpp | 441 - src/webui/prefjson.h | 47 - src/webui/webapplication.cpp | 919 -- src/webui/webapplication.h | 118 - src/webui/websessiondata.h | 43 - src/webui/webui.cpp | 123 - src/webui/webui.h | 64 - src/webui/webui.pri | 18 - src/webui/webui.qrc | 46 - src/webui/www/private/index.html | 163 - src/webui/www/private/login.html | 87 - src/webui/www/public/about.html | 10 - src/webui/www/public/addtrackers.html | 36 - src/webui/www/public/confirmdeletion.html | 46 - src/webui/www/public/css/Core.css | 54 - src/webui/www/public/css/Layout.css | 433 - src/webui/www/public/css/Tabs.css | 66 - src/webui/www/public/css/Window.css | 378 - src/webui/www/public/css/dynamicTable.css | 94 - src/webui/www/public/css/style.css | 481 - src/webui/www/public/download.html | 66 - src/webui/www/public/downloadlimit.html | 62 - src/webui/www/public/filters.html | 50 - src/webui/www/public/newcategory.html | 73 - src/webui/www/public/preferences.html | 51 - src/webui/www/public/preferences_content.html | 1375 --- src/webui/www/public/properties.html | 10 - src/webui/www/public/properties_content.html | 119 - src/webui/www/public/scripts/client.js | 719 -- src/webui/www/public/scripts/clipboard.min.js | 7 - src/webui/www/public/scripts/contextmenu.js | 375 - src/webui/www/public/scripts/download.js | 42 - src/webui/www/public/scripts/dynamicTable.js | 1264 -- .../www/public/scripts/excanvas-compressed.js | 876 -- src/webui/www/public/scripts/misc.js | 106 - src/webui/www/public/scripts/mocha-init.js | 596 - src/webui/www/public/scripts/mocha-yc.js | 1 - src/webui/www/public/scripts/mocha.js | 6234 ---------- .../public/scripts/mootools-1.2-core-yc.js | 527 - .../www/public/scripts/mootools-1.2-more.js | 326 - src/webui/www/public/scripts/parametrics.js | 224 - src/webui/www/public/scripts/progressbar.js | 110 - src/webui/www/public/scripts/prop-files.js | 351 - src/webui/www/public/scripts/prop-general.js | 169 - src/webui/www/public/scripts/prop-trackers.js | 131 - src/webui/www/public/scripts/prop-webseeds.js | 109 - src/webui/www/public/setlocation.html | 55 - src/webui/www/public/statistics.html | 47 - src/webui/www/public/transferlist.html | 85 - src/webui/www/public/upload.html | 62 - src/webui/www/public/uploadlimit.html | 62 - uncrustify.cfg | 84 - unixconf.pri | 130 - version.pri | 32 - winconf-mingw.pri | 35 - winconf-msvc.pri | 32 - winconf.pri | 67 - 1162 files changed, 582042 deletions(-) delete mode 100644 .appveyor.yml delete mode 100644 .editorconfig delete mode 100644 .github/ISSUE_TEMPLATE.md delete mode 100644 .travis.yml delete mode 100644 .tx/config delete mode 100644 5B7CC9A2.asc delete mode 100644 AUTHORS delete mode 100644 CMakeLists.txt delete mode 100644 CODING_GUIDELINES.md delete mode 100644 CONTRIBUTING.md delete mode 100644 COPYING delete mode 100644 Changelog delete mode 100644 INSTALL delete mode 100644 NEWS delete mode 100644 README.md delete mode 100644 README.os2 delete mode 100644 TODO delete mode 100755 bootstrap.sh delete mode 100755 build-aux/compile delete mode 100755 build-aux/config.guess delete mode 100755 build-aux/config.sub delete mode 100755 build-aux/install-sh delete mode 100755 build-aux/missing delete mode 100644 cmake/Modules/DeployQt5.cmake delete mode 100644 cmake/Modules/FindLibtorrentRasterbar.cmake delete mode 100644 cmake/Modules/FindQtSingleApplication.cmake delete mode 100644 cmake/Modules/FindSystemd.cmake delete mode 100644 cmake/Modules/FunctionReadVersion.cmake delete mode 100644 cmake/Modules/MacroConfigureMSVCRuntime.cmake delete mode 100644 cmake/Modules/MacroGlibcDetect.cmake delete mode 100644 cmake/Modules/MacroLinkQtComponents.cmake delete mode 100644 cmake/Modules/MacroQbtCompilerSettings.cmake delete mode 100644 cmake/Modules/QbtTargetSources.cmake delete mode 100644 cmake/Modules/bundle.cmake delete mode 100644 cmake/Modules/winconf-mingw.cmake delete mode 100644 cmake/Modules/winconf-msvc.cmake delete mode 100644 cmake/Modules/winconf.cmake delete mode 100644 codingStyleQtCreator.xml delete mode 100644 conf.pri.in delete mode 100755 configure delete mode 100644 configure.ac delete mode 100644 dist/CMakeLists.txt delete mode 100644 dist/mac/CMakeLists.txt delete mode 100644 dist/mac/Info.plist delete mode 100644 dist/mac/qBitTorrentDocument.icns delete mode 100644 dist/mac/qbittorrent_mac.icns delete mode 100644 dist/mac/qt.conf delete mode 100644 dist/qt-translations/qt_ar.qm delete mode 100644 dist/qt-translations/qt_bg.qm delete mode 100644 dist/qt-translations/qt_ca.qm delete mode 100644 dist/qt-translations/qt_cs.qm delete mode 100644 dist/qt-translations/qt_da.qm delete mode 100644 dist/qt-translations/qt_de.qm delete mode 100644 dist/qt-translations/qt_es.qm delete mode 100644 dist/qt-translations/qt_eu.qm delete mode 100644 dist/qt-translations/qt_fa.qm delete mode 100644 dist/qt-translations/qt_fi.qm delete mode 100644 dist/qt-translations/qt_fr.qm delete mode 100644 dist/qt-translations/qt_gl.qm delete mode 100644 dist/qt-translations/qt_he.qm delete mode 100644 dist/qt-translations/qt_hu.qm delete mode 100644 dist/qt-translations/qt_it.qm delete mode 100644 dist/qt-translations/qt_ja.qm delete mode 100644 dist/qt-translations/qt_ko.qm delete mode 100644 dist/qt-translations/qt_lt.qm delete mode 100644 dist/qt-translations/qt_nl.qm delete mode 100644 dist/qt-translations/qt_pl.qm delete mode 100644 dist/qt-translations/qt_pt.qm delete mode 100644 dist/qt-translations/qt_pt_BR.qm delete mode 100644 dist/qt-translations/qt_ru.qm delete mode 100644 dist/qt-translations/qt_sk.qm delete mode 100644 dist/qt-translations/qt_sl.qm delete mode 100644 dist/qt-translations/qt_sv.qm delete mode 100644 dist/qt-translations/qt_tr.qm delete mode 100644 dist/qt-translations/qt_uk.qm delete mode 100644 dist/qt-translations/qt_zh_CN.qm delete mode 100644 dist/qt-translations/qt_zh_TW.qm delete mode 100644 dist/qt-translations/qtbase_ca.qm delete mode 100644 dist/qt-translations/qtbase_cs.qm delete mode 100644 dist/qt-translations/qtbase_de.qm delete mode 100644 dist/qt-translations/qtbase_fi.qm delete mode 100644 dist/qt-translations/qtbase_fr.qm delete mode 100644 dist/qt-translations/qtbase_he.qm delete mode 100644 dist/qt-translations/qtbase_hu.qm delete mode 100644 dist/qt-translations/qtbase_it.qm delete mode 100644 dist/qt-translations/qtbase_ja.qm delete mode 100644 dist/qt-translations/qtbase_ko.qm delete mode 100644 dist/qt-translations/qtbase_lv.qm delete mode 100644 dist/qt-translations/qtbase_pl.qm delete mode 100644 dist/qt-translations/qtbase_ru.qm delete mode 100644 dist/qt-translations/qtbase_sk.qm delete mode 100644 dist/qt-translations/qtbase_uk.qm delete mode 100644 dist/unix/CMakeLists.txt delete mode 100644 dist/unix/menuicons/128x128/apps/qbittorrent.png delete mode 100644 dist/unix/menuicons/128x128/status/qbittorrent-tray.png delete mode 100644 dist/unix/menuicons/16x16/apps/qbittorrent.png delete mode 100644 dist/unix/menuicons/16x16/status/qbittorrent-tray.png delete mode 100644 dist/unix/menuicons/192x192/apps/qbittorrent.png delete mode 100644 dist/unix/menuicons/192x192/status/qbittorrent-tray.png delete mode 100644 dist/unix/menuicons/22x22/apps/qbittorrent.png delete mode 100644 dist/unix/menuicons/22x22/status/qbittorrent-tray.png delete mode 100644 dist/unix/menuicons/24x24/apps/qbittorrent.png delete mode 100644 dist/unix/menuicons/24x24/status/qbittorrent-tray.png delete mode 100644 dist/unix/menuicons/32x32/apps/qbittorrent.png delete mode 100644 dist/unix/menuicons/32x32/status/qbittorrent-tray.png delete mode 100644 dist/unix/menuicons/36x36/apps/qbittorrent.png delete mode 100644 dist/unix/menuicons/36x36/status/qbittorrent-tray.png delete mode 100644 dist/unix/menuicons/48x48/apps/qbittorrent.png delete mode 100644 dist/unix/menuicons/48x48/status/qbittorrent-tray.png delete mode 100644 dist/unix/menuicons/64x64/apps/qbittorrent.png delete mode 100644 dist/unix/menuicons/64x64/status/qbittorrent-tray.png delete mode 100644 dist/unix/menuicons/72x72/apps/qbittorrent.png delete mode 100644 dist/unix/menuicons/72x72/status/qbittorrent-tray.png delete mode 100644 dist/unix/menuicons/96x96/apps/qbittorrent.png delete mode 100644 dist/unix/menuicons/96x96/status/qbittorrent-tray.png delete mode 100644 dist/unix/qbittorrent.appdata.xml delete mode 100644 dist/unix/systemd/qbittorrent-nox@.service.in delete mode 100644 dist/windows/CMakeLists.txt delete mode 100644 dist/windows/README.txt delete mode 100644 dist/windows/UAC.nsh delete mode 100644 dist/windows/installer-translations/afrikaans.nsi delete mode 100644 dist/windows/installer-translations/albanian.nsi delete mode 100644 dist/windows/installer-translations/arabic.nsi delete mode 100644 dist/windows/installer-translations/basque.nsi delete mode 100644 dist/windows/installer-translations/belarusian.nsi delete mode 100644 dist/windows/installer-translations/bosnian.nsi delete mode 100644 dist/windows/installer-translations/breton.nsi delete mode 100644 dist/windows/installer-translations/bulgarian.nsi delete mode 100644 dist/windows/installer-translations/catalan.nsi delete mode 100644 dist/windows/installer-translations/croatian.nsi delete mode 100644 dist/windows/installer-translations/czech.nsi delete mode 100644 dist/windows/installer-translations/danish.nsi delete mode 100644 dist/windows/installer-translations/dutch.nsi delete mode 100644 dist/windows/installer-translations/english.nsi delete mode 100644 dist/windows/installer-translations/esperanto.nsi delete mode 100644 dist/windows/installer-translations/estonian.nsi delete mode 100644 dist/windows/installer-translations/farsi.nsi delete mode 100644 dist/windows/installer-translations/finnish.nsi delete mode 100644 dist/windows/installer-translations/french.nsi delete mode 100644 dist/windows/installer-translations/galician.nsi delete mode 100644 dist/windows/installer-translations/german.nsi delete mode 100644 dist/windows/installer-translations/greek.nsi delete mode 100644 dist/windows/installer-translations/hebrew.nsi delete mode 100644 dist/windows/installer-translations/hungarian.nsi delete mode 100644 dist/windows/installer-translations/icelandic.nsi delete mode 100644 dist/windows/installer-translations/indonesian.nsi delete mode 100644 dist/windows/installer-translations/irish.nsi delete mode 100644 dist/windows/installer-translations/italian.nsi delete mode 100644 dist/windows/installer-translations/japanese.nsi delete mode 100644 dist/windows/installer-translations/korean.nsi delete mode 100644 dist/windows/installer-translations/kurdish.nsi delete mode 100644 dist/windows/installer-translations/latvian.nsi delete mode 100644 dist/windows/installer-translations/lithuanian.nsi delete mode 100644 dist/windows/installer-translations/luxembourgish.nsi delete mode 100644 dist/windows/installer-translations/macedonian.nsi delete mode 100644 dist/windows/installer-translations/malay.nsi delete mode 100644 dist/windows/installer-translations/mongolian.nsi delete mode 100644 dist/windows/installer-translations/norwegian.nsi delete mode 100644 dist/windows/installer-translations/norwegiannynorsk.nsi delete mode 100644 dist/windows/installer-translations/polish.nsi delete mode 100644 dist/windows/installer-translations/portuguese.nsi delete mode 100644 dist/windows/installer-translations/portugueseBR.nsi delete mode 100644 dist/windows/installer-translations/romanian.nsi delete mode 100644 dist/windows/installer-translations/russian.nsi delete mode 100644 dist/windows/installer-translations/serbian.nsi delete mode 100644 dist/windows/installer-translations/serbianlatin.nsi delete mode 100644 dist/windows/installer-translations/simpchinese.nsi delete mode 100644 dist/windows/installer-translations/slovak.nsi delete mode 100644 dist/windows/installer-translations/slovenian.nsi delete mode 100644 dist/windows/installer-translations/spanish.nsi delete mode 100644 dist/windows/installer-translations/spanishinternational.nsi delete mode 100644 dist/windows/installer-translations/swedish.nsi delete mode 100644 dist/windows/installer-translations/thai.nsi delete mode 100644 dist/windows/installer-translations/tradchinese.nsi delete mode 100644 dist/windows/installer-translations/turkish.nsi delete mode 100644 dist/windows/installer-translations/ukrainian.nsi delete mode 100644 dist/windows/installer-translations/uzbek.nsi delete mode 100644 dist/windows/installer-translations/welsh.nsi delete mode 100644 dist/windows/installer.nsi delete mode 100644 dist/windows/nsis plugins/FindProcDLL_mod_by_hnedka.7z delete mode 100644 dist/windows/nsis plugins/UAC.zip delete mode 100644 dist/windows/nsis plugins/nsisFirewall.zip delete mode 100644 dist/windows/options.nsi delete mode 100644 dist/windows/qbittorrent.nsi delete mode 100644 dist/windows/qt.conf delete mode 100644 dist/windows/translations.nsi delete mode 100644 dist/windows/uninstaller.nsi delete mode 100644 doc/qbittorrent-nox.1 delete mode 100644 doc/qbittorrent.1 delete mode 100644 install.os2 delete mode 100644 m4/ax_boost_base.m4 delete mode 100644 m4/ax_boost_system.m4 delete mode 100644 m4/ax_define_dir.m4 delete mode 100644 m4/pkg.m4 delete mode 100644 m4/qbittorrent.m4 delete mode 100644 macxconf.pri delete mode 100644 os2conf.pri delete mode 100644 qbittorrent.pro delete mode 100644 qm_gen.pri delete mode 100644 src/CMakeLists.txt delete mode 100644 src/app/CMakeLists.txt delete mode 100644 src/app/app.pri delete mode 100644 src/app/application.cpp delete mode 100644 src/app/application.h delete mode 100644 src/app/cmdoptions.cpp delete mode 100644 src/app/cmdoptions.h delete mode 100644 src/app/filelogger.cpp delete mode 100644 src/app/filelogger.h delete mode 100644 src/app/main.cpp delete mode 100644 src/app/qtsingleapplication/CMakeLists.txt delete mode 100644 src/app/qtsingleapplication/QtLockedFile delete mode 100644 src/app/qtsingleapplication/QtSingleApplication delete mode 100644 src/app/qtsingleapplication/qtlocalpeer.cpp delete mode 100644 src/app/qtsingleapplication/qtlocalpeer.h delete mode 100644 src/app/qtsingleapplication/qtlockedfile.cpp delete mode 100644 src/app/qtsingleapplication/qtlockedfile.h delete mode 100644 src/app/qtsingleapplication/qtlockedfile_unix.cpp delete mode 100644 src/app/qtsingleapplication/qtlockedfile_win.cpp delete mode 100644 src/app/qtsingleapplication/qtsingleapplication.cpp delete mode 100644 src/app/qtsingleapplication/qtsingleapplication.h delete mode 100644 src/app/qtsingleapplication/qtsingleapplication.pri delete mode 100644 src/app/qtsingleapplication/qtsinglecoreapplication.cpp delete mode 100644 src/app/qtsingleapplication/qtsinglecoreapplication.h delete mode 100644 src/app/qtsingleapplication/qtsinglecoreapplication.pri delete mode 100644 src/app/stacktrace.h delete mode 100644 src/app/stacktrace_win.h delete mode 100644 src/app/stacktrace_win_dlg.h delete mode 100644 src/app/stacktrace_win_dlg.ui delete mode 100644 src/app/upgrade.h delete mode 100644 src/base/CMakeLists.txt delete mode 100644 src/base/asyncfilestorage.cpp delete mode 100644 src/base/asyncfilestorage.h delete mode 100644 src/base/base.pri delete mode 100644 src/base/bittorrent/addtorrentparams.h delete mode 100644 src/base/bittorrent/cachestatus.h delete mode 100644 src/base/bittorrent/infohash.cpp delete mode 100644 src/base/bittorrent/infohash.h delete mode 100644 src/base/bittorrent/magneturi.cpp delete mode 100644 src/base/bittorrent/magneturi.h delete mode 100644 src/base/bittorrent/peerinfo.cpp delete mode 100644 src/base/bittorrent/peerinfo.h delete mode 100644 src/base/bittorrent/private/bandwidthscheduler.cpp delete mode 100644 src/base/bittorrent/private/bandwidthscheduler.h delete mode 100644 src/base/bittorrent/private/filterparserthread.cpp delete mode 100644 src/base/bittorrent/private/filterparserthread.h delete mode 100644 src/base/bittorrent/private/resumedatasavingmanager.cpp delete mode 100644 src/base/bittorrent/private/resumedatasavingmanager.h delete mode 100644 src/base/bittorrent/private/speedmonitor.cpp delete mode 100644 src/base/bittorrent/private/speedmonitor.h delete mode 100644 src/base/bittorrent/private/statistics.cpp delete mode 100644 src/base/bittorrent/private/statistics.h delete mode 100644 src/base/bittorrent/session.cpp delete mode 100644 src/base/bittorrent/session.h delete mode 100644 src/base/bittorrent/sessionstatus.h delete mode 100644 src/base/bittorrent/torrentcreatorthread.cpp delete mode 100644 src/base/bittorrent/torrentcreatorthread.h delete mode 100644 src/base/bittorrent/torrenthandle.cpp delete mode 100644 src/base/bittorrent/torrenthandle.h delete mode 100644 src/base/bittorrent/torrentinfo.cpp delete mode 100644 src/base/bittorrent/torrentinfo.h delete mode 100644 src/base/bittorrent/tracker.cpp delete mode 100644 src/base/bittorrent/tracker.h delete mode 100644 src/base/bittorrent/trackerentry.cpp delete mode 100644 src/base/bittorrent/trackerentry.h delete mode 100644 src/base/filesystemwatcher.cpp delete mode 100644 src/base/filesystemwatcher.h delete mode 100644 src/base/global.h delete mode 100644 src/base/http/connection.cpp delete mode 100644 src/base/http/connection.h delete mode 100644 src/base/http/irequesthandler.h delete mode 100644 src/base/http/requestparser.cpp delete mode 100644 src/base/http/requestparser.h delete mode 100644 src/base/http/responsebuilder.cpp delete mode 100644 src/base/http/responsebuilder.h delete mode 100644 src/base/http/responsegenerator.cpp delete mode 100644 src/base/http/responsegenerator.h delete mode 100644 src/base/http/server.cpp delete mode 100644 src/base/http/server.h delete mode 100644 src/base/http/types.h delete mode 100644 src/base/iconprovider.cpp delete mode 100644 src/base/iconprovider.h delete mode 100644 src/base/indexrange.h delete mode 100644 src/base/logger.cpp delete mode 100644 src/base/logger.h delete mode 100644 src/base/net/dnsupdater.cpp delete mode 100644 src/base/net/dnsupdater.h delete mode 100644 src/base/net/downloadhandler.cpp delete mode 100644 src/base/net/downloadhandler.h delete mode 100644 src/base/net/downloadmanager.cpp delete mode 100644 src/base/net/downloadmanager.h delete mode 100644 src/base/net/geoipmanager.cpp delete mode 100644 src/base/net/geoipmanager.h delete mode 100644 src/base/net/portforwarder.cpp delete mode 100644 src/base/net/portforwarder.h delete mode 100644 src/base/net/private/geoipdatabase.cpp delete mode 100644 src/base/net/private/geoipdatabase.h delete mode 100644 src/base/net/proxyconfigurationmanager.cpp delete mode 100644 src/base/net/proxyconfigurationmanager.h delete mode 100644 src/base/net/reverseresolution.cpp delete mode 100644 src/base/net/reverseresolution.h delete mode 100644 src/base/net/smtp.cpp delete mode 100644 src/base/net/smtp.h delete mode 100644 src/base/preferences.cpp delete mode 100644 src/base/preferences.h delete mode 100644 src/base/private/profile_p.cpp delete mode 100644 src/base/private/profile_p.h delete mode 100644 src/base/profile.cpp delete mode 100644 src/base/profile.h delete mode 100644 src/base/rss/private/rss_parser.cpp delete mode 100644 src/base/rss/private/rss_parser.h delete mode 100644 src/base/rss/rss_article.cpp delete mode 100644 src/base/rss/rss_article.h delete mode 100644 src/base/rss/rss_autodownloader.cpp delete mode 100644 src/base/rss/rss_autodownloader.h delete mode 100644 src/base/rss/rss_autodownloadrule.cpp delete mode 100644 src/base/rss/rss_autodownloadrule.h delete mode 100644 src/base/rss/rss_feed.cpp delete mode 100644 src/base/rss/rss_feed.h delete mode 100644 src/base/rss/rss_folder.cpp delete mode 100644 src/base/rss/rss_folder.h delete mode 100644 src/base/rss/rss_item.cpp delete mode 100644 src/base/rss/rss_item.h delete mode 100644 src/base/rss/rss_session.cpp delete mode 100644 src/base/rss/rss_session.h delete mode 100644 src/base/scanfoldersmodel.cpp delete mode 100644 src/base/scanfoldersmodel.h delete mode 100644 src/base/searchengine.cpp delete mode 100644 src/base/searchengine.h delete mode 100644 src/base/settingsstorage.cpp delete mode 100644 src/base/settingsstorage.h delete mode 100644 src/base/settingvalue.h delete mode 100644 src/base/torrentfileguard.cpp delete mode 100644 src/base/torrentfileguard.h delete mode 100644 src/base/torrentfilter.cpp delete mode 100644 src/base/torrentfilter.h delete mode 100644 src/base/tristatebool.cpp delete mode 100644 src/base/tristatebool.h delete mode 100644 src/base/types.h delete mode 100644 src/base/unicodestrings.h delete mode 100644 src/base/utils/fs.cpp delete mode 100644 src/base/utils/fs.h delete mode 100644 src/base/utils/gzip.cpp delete mode 100644 src/base/utils/gzip.h delete mode 100644 src/base/utils/misc.cpp delete mode 100644 src/base/utils/misc.h delete mode 100644 src/base/utils/net.cpp delete mode 100644 src/base/utils/net.h delete mode 100644 src/base/utils/random.cpp delete mode 100644 src/base/utils/random.h delete mode 100644 src/base/utils/string.cpp delete mode 100644 src/base/utils/string.h delete mode 100644 src/base/utils/version.h delete mode 100644 src/config.h.cmakein delete mode 100644 src/gui/CMakeLists.txt delete mode 100644 src/gui/about.qrc delete mode 100644 src/gui/about.ui delete mode 100644 src/gui/about_imp.h delete mode 100644 src/gui/addnewtorrentdialog.cpp delete mode 100644 src/gui/addnewtorrentdialog.h delete mode 100644 src/gui/addnewtorrentdialog.ui delete mode 100644 src/gui/advancedsettings.cpp delete mode 100644 src/gui/advancedsettings.h delete mode 100644 src/gui/autoexpandabledialog.cpp delete mode 100644 src/gui/autoexpandabledialog.h delete mode 100644 src/gui/autoexpandabledialog.ui delete mode 100644 src/gui/bandwidth_limit.ui delete mode 100644 src/gui/banlistoptions.cpp delete mode 100644 src/gui/banlistoptions.h delete mode 100644 src/gui/banlistoptions.ui delete mode 100644 src/gui/categoryfiltermodel.cpp delete mode 100644 src/gui/categoryfiltermodel.h delete mode 100644 src/gui/categoryfilterproxymodel.cpp delete mode 100644 src/gui/categoryfilterproxymodel.h delete mode 100644 src/gui/categoryfilterwidget.cpp delete mode 100644 src/gui/categoryfilterwidget.h delete mode 100644 src/gui/confirmdeletiondlg.ui delete mode 100644 src/gui/cookiesdialog.cpp delete mode 100644 src/gui/cookiesdialog.h delete mode 100644 src/gui/cookiesdialog.ui delete mode 100644 src/gui/cookiesmodel.cpp delete mode 100644 src/gui/cookiesmodel.h delete mode 100644 src/gui/deletionconfirmationdlg.h delete mode 100644 src/gui/downloadfromurldlg.h delete mode 100644 src/gui/downloadfromurldlg.ui delete mode 100644 src/gui/executionlog.cpp delete mode 100644 src/gui/executionlog.h delete mode 100644 src/gui/executionlog.ui delete mode 100644 src/gui/fspathedit.cpp delete mode 100644 src/gui/fspathedit.h delete mode 100644 src/gui/fspathedit_p.cpp delete mode 100644 src/gui/fspathedit_p.h delete mode 100644 src/gui/gpl.html delete mode 100644 src/gui/gui.pri delete mode 100644 src/gui/guiiconprovider.cpp delete mode 100644 src/gui/guiiconprovider.h delete mode 100644 src/gui/hidabletabwidget.h delete mode 100644 src/gui/lineedit/CMakeLists.txt delete mode 100644 src/gui/lineedit/lineedit.pri delete mode 100644 src/gui/lineedit/resources/lineeditimages.qrc delete mode 100644 src/gui/lineedit/resources/lineeditimages/clear_left.png delete mode 100644 src/gui/lineedit/resources/lineeditimages/search.png delete mode 100644 src/gui/lineedit/src/lineedit.cpp delete mode 100644 src/gui/lineedit/src/lineedit.h delete mode 100644 src/gui/login.ui delete mode 100644 src/gui/loglistwidget.cpp delete mode 100644 src/gui/loglistwidget.h delete mode 100644 src/gui/mainwindow.cpp delete mode 100644 src/gui/mainwindow.h delete mode 100644 src/gui/mainwindow.ui delete mode 100644 src/gui/messageboxraised.cpp delete mode 100644 src/gui/messageboxraised.h delete mode 100644 src/gui/optionsdlg.cpp delete mode 100644 src/gui/optionsdlg.h delete mode 100644 src/gui/optionsdlg.ui delete mode 100644 src/gui/powermanagement/CMakeLists.txt delete mode 100644 src/gui/powermanagement/powermanagement.cpp delete mode 100644 src/gui/powermanagement/powermanagement.h delete mode 100644 src/gui/powermanagement/powermanagement.pri delete mode 100644 src/gui/powermanagement/powermanagement_x11.cpp delete mode 100644 src/gui/powermanagement/powermanagement_x11.h delete mode 100644 src/gui/preview.ui delete mode 100644 src/gui/previewlistdelegate.h delete mode 100644 src/gui/previewselect.cpp delete mode 100644 src/gui/previewselect.h delete mode 100644 src/gui/programupdater.cpp delete mode 100644 src/gui/programupdater.h delete mode 100644 src/gui/properties/CMakeLists.txt delete mode 100644 src/gui/properties/downloadedpiecesbar.cpp delete mode 100644 src/gui/properties/downloadedpiecesbar.h delete mode 100644 src/gui/properties/peerlistdelegate.h delete mode 100644 src/gui/properties/peerlistsortmodel.h delete mode 100644 src/gui/properties/peerlistwidget.cpp delete mode 100644 src/gui/properties/peerlistwidget.h delete mode 100644 src/gui/properties/peersadditiondlg.cpp delete mode 100644 src/gui/properties/peersadditiondlg.h delete mode 100644 src/gui/properties/peersadditiondlg.ui delete mode 100644 src/gui/properties/pieceavailabilitybar.cpp delete mode 100644 src/gui/properties/pieceavailabilitybar.h delete mode 100644 src/gui/properties/piecesbar.cpp delete mode 100644 src/gui/properties/piecesbar.h delete mode 100644 src/gui/properties/properties.pri delete mode 100644 src/gui/properties/propertieswidget.cpp delete mode 100644 src/gui/properties/propertieswidget.h delete mode 100644 src/gui/properties/propertieswidget.ui delete mode 100644 src/gui/properties/proplistdelegate.cpp delete mode 100644 src/gui/properties/proplistdelegate.h delete mode 100644 src/gui/properties/proptabbar.cpp delete mode 100644 src/gui/properties/proptabbar.h delete mode 100644 src/gui/properties/speedplotview.cpp delete mode 100644 src/gui/properties/speedplotview.h delete mode 100644 src/gui/properties/speedwidget.cpp delete mode 100644 src/gui/properties/speedwidget.h delete mode 100644 src/gui/properties/trackerlist.cpp delete mode 100644 src/gui/properties/trackerlist.h delete mode 100644 src/gui/properties/trackersadditiondlg.cpp delete mode 100644 src/gui/properties/trackersadditiondlg.h delete mode 100644 src/gui/properties/trackersadditiondlg.ui delete mode 100644 src/gui/qtnotify/CMakeLists.txt delete mode 100644 src/gui/qtnotify/notifications.cpp delete mode 100644 src/gui/qtnotify/notifications.h delete mode 100644 src/gui/qtnotify/notifications.xml delete mode 100644 src/gui/qtnotify/qtnotify.pri delete mode 100644 src/gui/rss/CMakeLists.txt delete mode 100644 src/gui/rss/articlelistwidget.cpp delete mode 100644 src/gui/rss/articlelistwidget.h delete mode 100644 src/gui/rss/automatedrssdownloader.cpp delete mode 100644 src/gui/rss/automatedrssdownloader.h delete mode 100644 src/gui/rss/automatedrssdownloader.ui delete mode 100644 src/gui/rss/feedlistwidget.cpp delete mode 100644 src/gui/rss/feedlistwidget.h delete mode 100644 src/gui/rss/htmlbrowser.cpp delete mode 100644 src/gui/rss/htmlbrowser.h delete mode 100644 src/gui/rss/rsswidget.cpp delete mode 100644 src/gui/rss/rsswidget.h delete mode 100644 src/gui/rss/rsswidget.ui delete mode 100644 src/gui/scanfoldersdelegate.cpp delete mode 100644 src/gui/scanfoldersdelegate.h delete mode 100644 src/gui/search/CMakeLists.txt delete mode 100644 src/gui/search/pluginselectdlg.cpp delete mode 100644 src/gui/search/pluginselectdlg.h delete mode 100644 src/gui/search/pluginselectdlg.ui delete mode 100644 src/gui/search/pluginsourcedlg.cpp delete mode 100644 src/gui/search/pluginsourcedlg.h delete mode 100644 src/gui/search/pluginsourcedlg.ui delete mode 100644 src/gui/search/searchlistdelegate.cpp delete mode 100644 src/gui/search/searchlistdelegate.h delete mode 100644 src/gui/search/searchsortmodel.cpp delete mode 100644 src/gui/search/searchsortmodel.h delete mode 100644 src/gui/search/searchtab.cpp delete mode 100644 src/gui/search/searchtab.h delete mode 100644 src/gui/search/searchtab.ui delete mode 100644 src/gui/search/searchwidget.cpp delete mode 100644 src/gui/search/searchwidget.h delete mode 100644 src/gui/search/searchwidget.ui delete mode 100644 src/gui/shutdownconfirmdlg.cpp delete mode 100644 src/gui/shutdownconfirmdlg.h delete mode 100644 src/gui/shutdownconfirmdlg.ui delete mode 100644 src/gui/speedlimitdlg.cpp delete mode 100644 src/gui/speedlimitdlg.h delete mode 100644 src/gui/statsdialog.cpp delete mode 100644 src/gui/statsdialog.h delete mode 100644 src/gui/statsdialog.ui delete mode 100644 src/gui/statusbar.cpp delete mode 100644 src/gui/statusbar.h delete mode 100644 src/gui/tagfiltermodel.cpp delete mode 100644 src/gui/tagfiltermodel.h delete mode 100644 src/gui/tagfilterproxymodel.cpp delete mode 100644 src/gui/tagfilterproxymodel.h delete mode 100644 src/gui/tagfilterwidget.cpp delete mode 100644 src/gui/tagfilterwidget.h delete mode 100644 src/gui/thanks.html delete mode 100644 src/gui/torrentcontentfiltermodel.cpp delete mode 100644 src/gui/torrentcontentfiltermodel.h delete mode 100644 src/gui/torrentcontentmodel.cpp delete mode 100644 src/gui/torrentcontentmodel.h delete mode 100644 src/gui/torrentcontentmodelfile.cpp delete mode 100644 src/gui/torrentcontentmodelfile.h delete mode 100644 src/gui/torrentcontentmodelfolder.cpp delete mode 100644 src/gui/torrentcontentmodelfolder.h delete mode 100644 src/gui/torrentcontentmodelitem.cpp delete mode 100644 src/gui/torrentcontentmodelitem.h delete mode 100644 src/gui/torrentcontenttreeview.cpp delete mode 100644 src/gui/torrentcontenttreeview.h delete mode 100644 src/gui/torrentcreatordlg.cpp delete mode 100644 src/gui/torrentcreatordlg.h delete mode 100644 src/gui/torrentcreatordlg.ui delete mode 100644 src/gui/torrentmodel.cpp delete mode 100644 src/gui/torrentmodel.h delete mode 100644 src/gui/trackerlogin.cpp delete mode 100644 src/gui/trackerlogin.h delete mode 100644 src/gui/transferlistdelegate.cpp delete mode 100644 src/gui/transferlistdelegate.h delete mode 100644 src/gui/transferlistfilterswidget.cpp delete mode 100644 src/gui/transferlistfilterswidget.h delete mode 100644 src/gui/transferlistsortmodel.cpp delete mode 100644 src/gui/transferlistsortmodel.h delete mode 100644 src/gui/transferlistwidget.cpp delete mode 100644 src/gui/transferlistwidget.h delete mode 100644 src/gui/translators.html delete mode 100644 src/gui/updownratiodlg.cpp delete mode 100644 src/gui/updownratiodlg.h delete mode 100644 src/gui/updownratiodlg.ui delete mode 100644 src/icons.qrc delete mode 100644 src/icons/3-state-checkbox.gif delete mode 100644 src/icons/L.gif delete mode 100755 src/icons/flags/ad.png delete mode 100755 src/icons/flags/ae.png delete mode 100755 src/icons/flags/af.png delete mode 100755 src/icons/flags/ag.png delete mode 100755 src/icons/flags/ai.png delete mode 100755 src/icons/flags/al.png delete mode 100755 src/icons/flags/am.png delete mode 100755 src/icons/flags/an.png delete mode 100644 src/icons/flags/ao.png delete mode 100755 src/icons/flags/ar.png delete mode 100755 src/icons/flags/as.png delete mode 100755 src/icons/flags/at.png delete mode 100755 src/icons/flags/au.png delete mode 100755 src/icons/flags/aw.png delete mode 100755 src/icons/flags/ax.png delete mode 100755 src/icons/flags/az.png delete mode 100755 src/icons/flags/ba.png delete mode 100755 src/icons/flags/bb.png delete mode 100755 src/icons/flags/bd.png delete mode 100755 src/icons/flags/be.png delete mode 100755 src/icons/flags/bf.png delete mode 100755 src/icons/flags/bg.png delete mode 100755 src/icons/flags/bh.png delete mode 100755 src/icons/flags/bi.png delete mode 100755 src/icons/flags/bj.png delete mode 100755 src/icons/flags/bm.png delete mode 100755 src/icons/flags/bn.png delete mode 100755 src/icons/flags/bo.png delete mode 100755 src/icons/flags/br.png delete mode 100755 src/icons/flags/bs.png delete mode 100755 src/icons/flags/bt.png delete mode 100755 src/icons/flags/bv.png delete mode 100755 src/icons/flags/bw.png delete mode 100755 src/icons/flags/by.png delete mode 100755 src/icons/flags/bz.png delete mode 100755 src/icons/flags/ca.png delete mode 100755 src/icons/flags/cc.png delete mode 100644 src/icons/flags/cd.png delete mode 100755 src/icons/flags/cf.png delete mode 100755 src/icons/flags/cg.png delete mode 100755 src/icons/flags/ch.png delete mode 100755 src/icons/flags/ci.png delete mode 100755 src/icons/flags/ck.png delete mode 100755 src/icons/flags/cl.png delete mode 100755 src/icons/flags/cm.png delete mode 100755 src/icons/flags/cn.png delete mode 100755 src/icons/flags/co.png delete mode 100755 src/icons/flags/cr.png delete mode 100755 src/icons/flags/cs.png delete mode 100755 src/icons/flags/cu.png delete mode 100755 src/icons/flags/cv.png delete mode 100755 src/icons/flags/cx.png delete mode 100755 src/icons/flags/cy.png delete mode 100755 src/icons/flags/cz.png delete mode 100755 src/icons/flags/de.png delete mode 100755 src/icons/flags/dj.png delete mode 100755 src/icons/flags/dk.png delete mode 100755 src/icons/flags/dm.png delete mode 100755 src/icons/flags/do.png delete mode 100755 src/icons/flags/dz.png delete mode 100755 src/icons/flags/ec.png delete mode 100755 src/icons/flags/ee.png delete mode 100755 src/icons/flags/eg.png delete mode 100755 src/icons/flags/eh.png delete mode 100755 src/icons/flags/er.png delete mode 100755 src/icons/flags/es.png delete mode 100755 src/icons/flags/et.png delete mode 100755 src/icons/flags/fi.png delete mode 100755 src/icons/flags/fj.png delete mode 100755 src/icons/flags/fk.png delete mode 100755 src/icons/flags/fm.png delete mode 100755 src/icons/flags/fo.png delete mode 100755 src/icons/flags/fr.png delete mode 100755 src/icons/flags/ga.png delete mode 100644 src/icons/flags/gb.png delete mode 100755 src/icons/flags/gd.png delete mode 100755 src/icons/flags/ge.png delete mode 100755 src/icons/flags/gf.png delete mode 100755 src/icons/flags/gh.png delete mode 100755 src/icons/flags/gi.png delete mode 100755 src/icons/flags/gl.png delete mode 100755 src/icons/flags/gm.png delete mode 100755 src/icons/flags/gn.png delete mode 100755 src/icons/flags/gp.png delete mode 100755 src/icons/flags/gq.png delete mode 100755 src/icons/flags/gr.png delete mode 100755 src/icons/flags/gs.png delete mode 100755 src/icons/flags/gt.png delete mode 100755 src/icons/flags/gu.png delete mode 100755 src/icons/flags/gw.png delete mode 100755 src/icons/flags/gy.png delete mode 100755 src/icons/flags/hk.png delete mode 100755 src/icons/flags/hm.png delete mode 100755 src/icons/flags/hn.png delete mode 100755 src/icons/flags/hr.png delete mode 100755 src/icons/flags/ht.png delete mode 100755 src/icons/flags/hu.png delete mode 100755 src/icons/flags/icons-set-readme.txt delete mode 100755 src/icons/flags/id.png delete mode 100755 src/icons/flags/ie.png delete mode 100755 src/icons/flags/il.png delete mode 100755 src/icons/flags/in.png delete mode 100755 src/icons/flags/io.png delete mode 100755 src/icons/flags/iq.png delete mode 100755 src/icons/flags/ir.png delete mode 100755 src/icons/flags/is.png delete mode 100755 src/icons/flags/it.png delete mode 100755 src/icons/flags/jm.png delete mode 100755 src/icons/flags/jo.png delete mode 100755 src/icons/flags/jp.png delete mode 100755 src/icons/flags/ke.png delete mode 100755 src/icons/flags/kg.png delete mode 100755 src/icons/flags/kh.png delete mode 100755 src/icons/flags/ki.png delete mode 100755 src/icons/flags/km.png delete mode 100755 src/icons/flags/kn.png delete mode 100755 src/icons/flags/kp.png delete mode 100755 src/icons/flags/kr.png delete mode 100755 src/icons/flags/kw.png delete mode 100755 src/icons/flags/ky.png delete mode 100755 src/icons/flags/kz.png delete mode 100755 src/icons/flags/la.png delete mode 100755 src/icons/flags/lb.png delete mode 100644 src/icons/flags/lc.png delete mode 100755 src/icons/flags/li.png delete mode 100755 src/icons/flags/lk.png delete mode 100755 src/icons/flags/lr.png delete mode 100755 src/icons/flags/ls.png delete mode 100755 src/icons/flags/lt.png delete mode 100755 src/icons/flags/lu.png delete mode 100755 src/icons/flags/lv.png delete mode 100755 src/icons/flags/ly.png delete mode 100755 src/icons/flags/ma.png delete mode 100755 src/icons/flags/mc.png delete mode 100755 src/icons/flags/md.png delete mode 100644 src/icons/flags/me.png delete mode 100755 src/icons/flags/mg.png delete mode 100755 src/icons/flags/mh.png delete mode 100755 src/icons/flags/mk.png delete mode 100755 src/icons/flags/ml.png delete mode 100755 src/icons/flags/mm.png delete mode 100755 src/icons/flags/mn.png delete mode 100755 src/icons/flags/mo.png delete mode 100755 src/icons/flags/mp.png delete mode 100755 src/icons/flags/mq.png delete mode 100755 src/icons/flags/mr.png delete mode 100755 src/icons/flags/ms.png delete mode 100755 src/icons/flags/mt.png delete mode 100755 src/icons/flags/mu.png delete mode 100755 src/icons/flags/mv.png delete mode 100755 src/icons/flags/mw.png delete mode 100755 src/icons/flags/mx.png delete mode 100755 src/icons/flags/my.png delete mode 100755 src/icons/flags/mz.png delete mode 100755 src/icons/flags/na.png delete mode 100755 src/icons/flags/nc.png delete mode 100755 src/icons/flags/ne.png delete mode 100755 src/icons/flags/nf.png delete mode 100755 src/icons/flags/ng.png delete mode 100755 src/icons/flags/ni.png delete mode 100755 src/icons/flags/nl.png delete mode 100755 src/icons/flags/no.png delete mode 100755 src/icons/flags/np.png delete mode 100755 src/icons/flags/nr.png delete mode 100755 src/icons/flags/nu.png delete mode 100755 src/icons/flags/nz.png delete mode 100755 src/icons/flags/om.png delete mode 100755 src/icons/flags/pa.png delete mode 100755 src/icons/flags/pe.png delete mode 100755 src/icons/flags/pf.png delete mode 100755 src/icons/flags/pg.png delete mode 100755 src/icons/flags/ph.png delete mode 100755 src/icons/flags/pk.png delete mode 100755 src/icons/flags/pl.png delete mode 100755 src/icons/flags/pm.png delete mode 100755 src/icons/flags/pn.png delete mode 100755 src/icons/flags/pr.png delete mode 100755 src/icons/flags/ps.png delete mode 100755 src/icons/flags/pt.png delete mode 100755 src/icons/flags/pw.png delete mode 100755 src/icons/flags/py.png delete mode 100755 src/icons/flags/qa.png delete mode 100755 src/icons/flags/re.png delete mode 100755 src/icons/flags/ro.png delete mode 100644 src/icons/flags/rs.png delete mode 100755 src/icons/flags/ru.png delete mode 100755 src/icons/flags/rw.png delete mode 100755 src/icons/flags/sa.png delete mode 100755 src/icons/flags/sb.png delete mode 100755 src/icons/flags/sc.png delete mode 100755 src/icons/flags/sd.png delete mode 100755 src/icons/flags/se.png delete mode 100755 src/icons/flags/sg.png delete mode 100755 src/icons/flags/sh.png delete mode 100755 src/icons/flags/si.png delete mode 100755 src/icons/flags/sj.png delete mode 100755 src/icons/flags/sk.png delete mode 100755 src/icons/flags/sl.png delete mode 100755 src/icons/flags/sm.png delete mode 100755 src/icons/flags/sn.png delete mode 100755 src/icons/flags/so.png delete mode 100755 src/icons/flags/sr.png delete mode 100755 src/icons/flags/st.png delete mode 100755 src/icons/flags/sv.png delete mode 100755 src/icons/flags/sy.png delete mode 100755 src/icons/flags/sz.png delete mode 100755 src/icons/flags/tc.png delete mode 100755 src/icons/flags/td.png delete mode 100755 src/icons/flags/tf.png delete mode 100755 src/icons/flags/tg.png delete mode 100755 src/icons/flags/th.png delete mode 100755 src/icons/flags/tj.png delete mode 100755 src/icons/flags/tk.png delete mode 100755 src/icons/flags/tl.png delete mode 100755 src/icons/flags/tm.png delete mode 100755 src/icons/flags/tn.png delete mode 100755 src/icons/flags/to.png delete mode 100755 src/icons/flags/tr.png delete mode 100755 src/icons/flags/tt.png delete mode 100755 src/icons/flags/tv.png delete mode 100755 src/icons/flags/tw.png delete mode 100755 src/icons/flags/tz.png delete mode 100755 src/icons/flags/ua.png delete mode 100755 src/icons/flags/ug.png delete mode 100755 src/icons/flags/um.png delete mode 100755 src/icons/flags/us.png delete mode 100755 src/icons/flags/uy.png delete mode 100755 src/icons/flags/uz.png delete mode 100755 src/icons/flags/va.png delete mode 100755 src/icons/flags/vc.png delete mode 100755 src/icons/flags/ve.png delete mode 100755 src/icons/flags/vg.png delete mode 100755 src/icons/flags/vi.png delete mode 100755 src/icons/flags/vn.png delete mode 100755 src/icons/flags/vu.png delete mode 100755 src/icons/flags/wf.png delete mode 100755 src/icons/flags/ws.png delete mode 100755 src/icons/flags/ye.png delete mode 100755 src/icons/flags/yt.png delete mode 100755 src/icons/flags/za.png delete mode 100755 src/icons/flags/zm.png delete mode 100755 src/icons/flags/zw.png delete mode 100644 src/icons/loading.png delete mode 100644 src/icons/qbittorrent.desktop delete mode 100644 src/icons/qbittorrent.png delete mode 100644 src/icons/qbt-theme/README.md delete mode 100644 src/icons/qbt-theme/application-exit.png delete mode 100644 src/icons/qbt-theme/application-rss+xml.png delete mode 100644 src/icons/qbt-theme/application-x-mswinurl.png delete mode 100644 src/icons/qbt-theme/build-icons/Gruntfile.js delete mode 100644 src/icons/qbt-theme/build-icons/icons/application-exit.svg delete mode 100644 src/icons/qbt-theme/build-icons/icons/application-rss+xml.svg delete mode 100644 src/icons/qbt-theme/build-icons/icons/application-x-mswinurl.svg delete mode 100644 src/icons/qbt-theme/build-icons/icons/checked.svg delete mode 100644 src/icons/qbt-theme/build-icons/icons/configure.svg delete mode 100644 src/icons/qbt-theme/build-icons/icons/dialog-cancel.svg delete mode 100644 src/icons/qbt-theme/build-icons/icons/dialog-information.svg delete mode 100644 src/icons/qbt-theme/build-icons/icons/dialog-warning.svg delete mode 100644 src/icons/qbt-theme/build-icons/icons/document-edit-verify.svg delete mode 100644 src/icons/qbt-theme/build-icons/icons/document-edit.svg delete mode 100644 src/icons/qbt-theme/build-icons/icons/document-encrypt.svg delete mode 100644 src/icons/qbt-theme/build-icons/icons/document-import.svg delete mode 100644 src/icons/qbt-theme/build-icons/icons/document-new.svg delete mode 100644 src/icons/qbt-theme/build-icons/icons/document-properties.svg delete mode 100644 src/icons/qbt-theme/build-icons/icons/document-save.svg delete mode 100644 src/icons/qbt-theme/build-icons/icons/download.svg delete mode 100644 src/icons/qbt-theme/build-icons/icons/edit-clear-history.svg delete mode 100644 src/icons/qbt-theme/build-icons/icons/edit-clear.svg delete mode 100644 src/icons/qbt-theme/build-icons/icons/edit-copy.svg delete mode 100644 src/icons/qbt-theme/build-icons/icons/edit-cut.svg delete mode 100644 src/icons/qbt-theme/build-icons/icons/edit-delete.svg delete mode 100644 src/icons/qbt-theme/build-icons/icons/edit-find-user.svg delete mode 100644 src/icons/qbt-theme/build-icons/icons/edit-find.svg delete mode 100644 src/icons/qbt-theme/build-icons/icons/edit-paste.svg delete mode 100644 src/icons/qbt-theme/build-icons/icons/edit-rename.svg delete mode 100644 src/icons/qbt-theme/build-icons/icons/folder-documents.svg delete mode 100644 src/icons/qbt-theme/build-icons/icons/folder-download.svg delete mode 100644 src/icons/qbt-theme/build-icons/icons/folder-new.svg delete mode 100644 src/icons/qbt-theme/build-icons/icons/folder-remote.svg delete mode 100644 src/icons/qbt-theme/build-icons/icons/gear.svg delete mode 100644 src/icons/qbt-theme/build-icons/icons/gear32.svg delete mode 100644 src/icons/qbt-theme/build-icons/icons/go-bottom.svg delete mode 100644 src/icons/qbt-theme/build-icons/icons/go-down.svg delete mode 100644 src/icons/qbt-theme/build-icons/icons/go-top.svg delete mode 100644 src/icons/qbt-theme/build-icons/icons/go-up.svg delete mode 100644 src/icons/qbt-theme/build-icons/icons/help-about.svg delete mode 100644 src/icons/qbt-theme/build-icons/icons/help-contents.svg delete mode 100644 src/icons/qbt-theme/build-icons/icons/inode-directory.svg delete mode 100644 src/icons/qbt-theme/build-icons/icons/insert-link.svg delete mode 100644 src/icons/qbt-theme/build-icons/icons/list-add.svg delete mode 100644 src/icons/qbt-theme/build-icons/icons/list-remove.svg delete mode 100644 src/icons/qbt-theme/build-icons/icons/mail-folder-inbox.svg delete mode 100644 src/icons/qbt-theme/build-icons/icons/mail-mark-read.svg delete mode 100644 src/icons/qbt-theme/build-icons/icons/media-playback-pause.svg delete mode 100644 src/icons/qbt-theme/build-icons/icons/media-playback-start.svg delete mode 100644 src/icons/qbt-theme/build-icons/icons/media-seek-forward.svg delete mode 100644 src/icons/qbt-theme/build-icons/icons/network-server.svg delete mode 100644 src/icons/qbt-theme/build-icons/icons/network-wired.svg delete mode 100644 src/icons/qbt-theme/build-icons/icons/object-locked.svg delete mode 100644 src/icons/qbt-theme/build-icons/icons/office-chart-line.svg delete mode 100644 src/icons/qbt-theme/build-icons/icons/preferences-desktop.svg delete mode 100644 src/icons/qbt-theme/build-icons/icons/preferences-other.svg delete mode 100644 src/icons/qbt-theme/build-icons/icons/preferences-system-network.svg delete mode 100644 src/icons/qbt-theme/build-icons/icons/preferences-web-browser-cookies.svg delete mode 100644 src/icons/qbt-theme/build-icons/icons/security-high.svg delete mode 100644 src/icons/qbt-theme/build-icons/icons/security-low.svg delete mode 100644 src/icons/qbt-theme/build-icons/icons/services.svg delete mode 100644 src/icons/qbt-theme/build-icons/icons/speedometer.svg delete mode 100644 src/icons/qbt-theme/build-icons/icons/system-log-out.svg delete mode 100644 src/icons/qbt-theme/build-icons/icons/tab-close.svg delete mode 100644 src/icons/qbt-theme/build-icons/icons/task-attention.svg delete mode 100644 src/icons/qbt-theme/build-icons/icons/text-plain.svg delete mode 100644 src/icons/qbt-theme/build-icons/icons/tools-report-bug.svg delete mode 100644 src/icons/qbt-theme/build-icons/icons/unavailable.svg delete mode 100644 src/icons/qbt-theme/build-icons/icons/user-group-delete.svg delete mode 100644 src/icons/qbt-theme/build-icons/icons/user-group-new.svg delete mode 100644 src/icons/qbt-theme/build-icons/icons/view-calendar-journal.svg delete mode 100644 src/icons/qbt-theme/build-icons/icons/view-categories.svg delete mode 100644 src/icons/qbt-theme/build-icons/icons/view-filter.svg delete mode 100644 src/icons/qbt-theme/build-icons/icons/view-preview.svg delete mode 100644 src/icons/qbt-theme/build-icons/icons/view-refresh.svg delete mode 100644 src/icons/qbt-theme/build-icons/icons/view-statistics.svg delete mode 100644 src/icons/qbt-theme/build-icons/icons/wallet-open.svg delete mode 100644 src/icons/qbt-theme/build-icons/icons/webui.svg delete mode 100644 src/icons/qbt-theme/build-icons/package.json delete mode 100644 src/icons/qbt-theme/build-icons/readme.md delete mode 100644 src/icons/qbt-theme/checked.png delete mode 100644 src/icons/qbt-theme/configure.png delete mode 100644 src/icons/qbt-theme/dialog-cancel.png delete mode 100644 src/icons/qbt-theme/dialog-information.png delete mode 100644 src/icons/qbt-theme/dialog-warning.png delete mode 100644 src/icons/qbt-theme/document-edit-verify.png delete mode 100644 src/icons/qbt-theme/document-edit.png delete mode 100644 src/icons/qbt-theme/document-encrypt.png delete mode 100644 src/icons/qbt-theme/document-import.png delete mode 100644 src/icons/qbt-theme/document-new.png delete mode 100644 src/icons/qbt-theme/document-properties.png delete mode 100644 src/icons/qbt-theme/document-save.png delete mode 100644 src/icons/qbt-theme/download.png delete mode 100644 src/icons/qbt-theme/edit-clear-history.png delete mode 100644 src/icons/qbt-theme/edit-clear.png delete mode 100644 src/icons/qbt-theme/edit-copy.png delete mode 100644 src/icons/qbt-theme/edit-cut.png delete mode 100644 src/icons/qbt-theme/edit-delete.png delete mode 100644 src/icons/qbt-theme/edit-find-user.png delete mode 100644 src/icons/qbt-theme/edit-find.png delete mode 100644 src/icons/qbt-theme/edit-paste.png delete mode 100644 src/icons/qbt-theme/edit-rename.png delete mode 100644 src/icons/qbt-theme/folder-documents.png delete mode 100644 src/icons/qbt-theme/folder-download.png delete mode 100644 src/icons/qbt-theme/folder-new.png delete mode 100644 src/icons/qbt-theme/folder-remote.png delete mode 100644 src/icons/qbt-theme/gear.png delete mode 100644 src/icons/qbt-theme/gear32.png delete mode 100644 src/icons/qbt-theme/go-bottom.png delete mode 100644 src/icons/qbt-theme/go-down.png delete mode 100644 src/icons/qbt-theme/go-top.png delete mode 100644 src/icons/qbt-theme/go-up.png delete mode 100644 src/icons/qbt-theme/help-about.png delete mode 100644 src/icons/qbt-theme/help-contents.png delete mode 100644 src/icons/qbt-theme/inode-directory.png delete mode 100644 src/icons/qbt-theme/insert-link.png delete mode 100644 src/icons/qbt-theme/kt-magnet.png delete mode 100644 src/icons/qbt-theme/kt-set-max-download-speed.png delete mode 100644 src/icons/qbt-theme/kt-set-max-upload-speed.png delete mode 100644 src/icons/qbt-theme/list-add.png delete mode 100644 src/icons/qbt-theme/list-remove.png delete mode 100644 src/icons/qbt-theme/mail-folder-inbox.png delete mode 100644 src/icons/qbt-theme/mail-mark-read.png delete mode 100644 src/icons/qbt-theme/media-playback-pause.png delete mode 100644 src/icons/qbt-theme/media-playback-start.png delete mode 100644 src/icons/qbt-theme/media-seek-forward.png delete mode 100644 src/icons/qbt-theme/network-server.png delete mode 100644 src/icons/qbt-theme/network-wired.png delete mode 100644 src/icons/qbt-theme/object-locked.png delete mode 100644 src/icons/qbt-theme/office-chart-line.png delete mode 100644 src/icons/qbt-theme/preferences-desktop.png delete mode 100644 src/icons/qbt-theme/preferences-other.png delete mode 100644 src/icons/qbt-theme/preferences-system-network.png delete mode 100644 src/icons/qbt-theme/preferences-web-browser-cookies.png delete mode 100644 src/icons/qbt-theme/rss-config.png delete mode 100644 src/icons/qbt-theme/security-high.png delete mode 100644 src/icons/qbt-theme/security-low.png delete mode 100644 src/icons/qbt-theme/services.png delete mode 100644 src/icons/qbt-theme/speedometer.png delete mode 100644 src/icons/qbt-theme/system-log-out.png delete mode 100644 src/icons/qbt-theme/tab-close.png delete mode 100644 src/icons/qbt-theme/task-attention.png delete mode 100644 src/icons/qbt-theme/task-complete.png delete mode 100644 src/icons/qbt-theme/task-ongoing.png delete mode 100644 src/icons/qbt-theme/task-reject.png delete mode 100644 src/icons/qbt-theme/text-plain.png delete mode 100644 src/icons/qbt-theme/tools-report-bug.png delete mode 100644 src/icons/qbt-theme/unavailable.png delete mode 100644 src/icons/qbt-theme/user-group-delete.png delete mode 100644 src/icons/qbt-theme/user-group-new.png delete mode 100644 src/icons/qbt-theme/view-calendar-journal.png delete mode 100644 src/icons/qbt-theme/view-categories.png delete mode 100644 src/icons/qbt-theme/view-filter.png delete mode 100644 src/icons/qbt-theme/view-preview.png delete mode 100644 src/icons/qbt-theme/view-refresh.png delete mode 100644 src/icons/qbt-theme/view-statistics.png delete mode 100644 src/icons/qbt-theme/wallet-open.png delete mode 100644 src/icons/qbt-theme/webui.png delete mode 100644 src/icons/skin/arrow-right.gif delete mode 100644 src/icons/skin/bg-dropdown.gif delete mode 100644 src/icons/skin/bg-handle-horizontal.gif delete mode 100644 src/icons/skin/bg-header.gif delete mode 100644 src/icons/skin/bg-panel-header.gif delete mode 100644 src/icons/skin/build-icons/Gruntfile.js delete mode 100644 src/icons/skin/build-icons/icons/checking.svg delete mode 100644 src/icons/skin/build-icons/icons/completed.svg delete mode 100644 src/icons/skin/build-icons/icons/connected.svg delete mode 100644 src/icons/skin/build-icons/icons/disconnected.svg delete mode 100644 src/icons/skin/build-icons/icons/download.svg delete mode 100644 src/icons/skin/build-icons/icons/downloading.svg delete mode 100644 src/icons/skin/build-icons/icons/error.svg delete mode 100644 src/icons/skin/build-icons/icons/filteractive.svg delete mode 100644 src/icons/skin/build-icons/icons/filterall.svg delete mode 100644 src/icons/skin/build-icons/icons/filterinactive.svg delete mode 100644 src/icons/skin/build-icons/icons/firewalled.svg delete mode 100644 src/icons/skin/build-icons/icons/paused.svg delete mode 100644 src/icons/skin/build-icons/icons/queued.svg delete mode 100644 src/icons/skin/build-icons/icons/ratio.svg delete mode 100644 src/icons/skin/build-icons/icons/resumed.svg delete mode 100644 src/icons/skin/build-icons/icons/seeding.svg delete mode 100644 src/icons/skin/build-icons/icons/stalledDL.svg delete mode 100644 src/icons/skin/build-icons/icons/stalledUP.svg delete mode 100644 src/icons/skin/build-icons/icons/uploading.svg delete mode 100644 src/icons/skin/build-icons/package.json delete mode 100644 src/icons/skin/build-icons/readme.md delete mode 100644 src/icons/skin/checking.png delete mode 100644 src/icons/skin/collapse-expand.gif delete mode 100644 src/icons/skin/completed.png delete mode 100644 src/icons/skin/connected.png delete mode 100755 src/icons/skin/disconnected.png delete mode 100644 src/icons/skin/dock-tabs.gif delete mode 100755 src/icons/skin/download.png delete mode 100644 src/icons/skin/downloading.png delete mode 100644 src/icons/skin/error.png delete mode 100644 src/icons/skin/filteractive.png delete mode 100644 src/icons/skin/filterall.png delete mode 100644 src/icons/skin/filterinactive.png delete mode 100644 src/icons/skin/firewalled.png delete mode 100644 src/icons/skin/handle-icon-horizontal.gif delete mode 100644 src/icons/skin/handle-icon.gif delete mode 100644 src/icons/skin/knob.gif delete mode 100644 src/icons/skin/logo-blank.gif delete mode 100644 src/icons/skin/logo.gif delete mode 100644 src/icons/skin/logo2.gif delete mode 100644 src/icons/skin/mascot.png delete mode 100644 src/icons/skin/paused.png delete mode 100644 src/icons/skin/qbittorrent-tray-dark.svg delete mode 100644 src/icons/skin/qbittorrent-tray-light.svg delete mode 100644 src/icons/skin/qbittorrent16.png delete mode 100644 src/icons/skin/qbittorrent22.png delete mode 100644 src/icons/skin/qbittorrent32.png delete mode 100644 src/icons/skin/queued.png delete mode 100644 src/icons/skin/ratio.png delete mode 100644 src/icons/skin/resumed.png delete mode 100644 src/icons/skin/seeding.png delete mode 100644 src/icons/skin/slider-area.gif delete mode 100644 src/icons/skin/spacer.gif delete mode 100644 src/icons/skin/spinner-placeholder.gif delete mode 100644 src/icons/skin/spinner.gif delete mode 100644 src/icons/skin/splash.png delete mode 100644 src/icons/skin/stalledDL.png delete mode 100644 src/icons/skin/stalledUP.png delete mode 100644 src/icons/skin/tabs.gif delete mode 100644 src/icons/skin/toolbox-divider.gif delete mode 100644 src/icons/skin/toolbox-divider2.gif delete mode 100644 src/icons/skin/uploading.png delete mode 100644 src/icons/slow.png delete mode 100644 src/icons/slow_off.png delete mode 100644 src/icons/sphere.png delete mode 100644 src/icons/sphere2.png delete mode 100644 src/icons/url.png delete mode 100644 src/lang.qrc delete mode 100644 src/lang/TRANSLATION_INSTRUCTIONS delete mode 100644 src/lang/qbittorrent_ar.ts delete mode 100644 src/lang/qbittorrent_be.ts delete mode 100644 src/lang/qbittorrent_bg.ts delete mode 100644 src/lang/qbittorrent_ca.ts delete mode 100644 src/lang/qbittorrent_cs.ts delete mode 100644 src/lang/qbittorrent_da.ts delete mode 100644 src/lang/qbittorrent_de.ts delete mode 100644 src/lang/qbittorrent_el.ts delete mode 100644 src/lang/qbittorrent_en.ts delete mode 100644 src/lang/qbittorrent_en_AU.ts delete mode 100644 src/lang/qbittorrent_en_GB.ts delete mode 100644 src/lang/qbittorrent_eo.ts delete mode 100644 src/lang/qbittorrent_es.ts delete mode 100644 src/lang/qbittorrent_eu.ts delete mode 100644 src/lang/qbittorrent_fi.ts delete mode 100644 src/lang/qbittorrent_fr.ts delete mode 100644 src/lang/qbittorrent_gl.ts delete mode 100644 src/lang/qbittorrent_he.ts delete mode 100644 src/lang/qbittorrent_hi_IN.ts delete mode 100644 src/lang/qbittorrent_hr.ts delete mode 100644 src/lang/qbittorrent_hu.ts delete mode 100644 src/lang/qbittorrent_hy.ts delete mode 100644 src/lang/qbittorrent_id.ts delete mode 100644 src/lang/qbittorrent_is.ts delete mode 100644 src/lang/qbittorrent_it.ts delete mode 100644 src/lang/qbittorrent_ja.ts delete mode 100755 src/lang/qbittorrent_ka.ts delete mode 100644 src/lang/qbittorrent_ko.ts delete mode 100644 src/lang/qbittorrent_lt.ts delete mode 100644 src/lang/qbittorrent_lv_LV.ts delete mode 100644 src/lang/qbittorrent_ms_MY.ts delete mode 100644 src/lang/qbittorrent_nb.ts delete mode 100644 src/lang/qbittorrent_nl.ts delete mode 100644 src/lang/qbittorrent_oc.ts delete mode 100644 src/lang/qbittorrent_pl.ts delete mode 100644 src/lang/qbittorrent_pt_BR.ts delete mode 100644 src/lang/qbittorrent_pt_PT.ts delete mode 100644 src/lang/qbittorrent_ro.ts delete mode 100644 src/lang/qbittorrent_ru.ts delete mode 100644 src/lang/qbittorrent_sk.ts delete mode 100644 src/lang/qbittorrent_sl.ts delete mode 100644 src/lang/qbittorrent_sr.ts delete mode 100644 src/lang/qbittorrent_sv.ts delete mode 100644 src/lang/qbittorrent_tr.ts delete mode 100644 src/lang/qbittorrent_uk.ts delete mode 100644 src/lang/qbittorrent_uz@Latn.ts delete mode 100644 src/lang/qbittorrent_vi.ts delete mode 100644 src/lang/qbittorrent_zh.ts delete mode 100644 src/lang/qbittorrent_zh_HK.ts delete mode 100644 src/lang/qbittorrent_zh_TW.ts delete mode 100644 src/qbittorrent.exe.manifest delete mode 100644 src/qbittorrent.ico delete mode 100644 src/qbittorrent.rc delete mode 100644 src/qbittorrent_file.ico delete mode 100644 src/qbittorrent_mingw.rc delete mode 100644 src/qbittorrent_os2.ico delete mode 100644 src/qbittorrent_os2.rc delete mode 100644 src/searchengine.qrc delete mode 100644 src/searchengine/nova/__init__.py delete mode 100644 src/searchengine/nova/fix_encoding.py delete mode 100644 src/searchengine/nova/helpers.py delete mode 100644 src/searchengine/nova/nova2.py delete mode 100644 src/searchengine/nova/nova2dl.py delete mode 100644 src/searchengine/nova/novaprinter.py delete mode 100644 src/searchengine/nova/socks.py delete mode 100644 src/searchengine/nova3/__init__.py delete mode 100644 src/searchengine/nova3/helpers.py delete mode 100644 src/searchengine/nova3/nova2.py delete mode 100644 src/searchengine/nova3/nova2dl.py delete mode 100644 src/searchengine/nova3/novaprinter.py delete mode 100644 src/searchengine/nova3/sgmllib3.py delete mode 100644 src/searchengine/nova3/socks.py delete mode 100644 src/src.pro delete mode 100755 src/update_qrc_files.py delete mode 100644 src/webui/CMakeLists.txt delete mode 100644 src/webui/abstractwebapplication.cpp delete mode 100644 src/webui/abstractwebapplication.h delete mode 100644 src/webui/btjson.cpp delete mode 100644 src/webui/btjson.h delete mode 100644 src/webui/extra_translations.h delete mode 100644 src/webui/jsonutils.h delete mode 100644 src/webui/prefjson.cpp delete mode 100644 src/webui/prefjson.h delete mode 100644 src/webui/webapplication.cpp delete mode 100644 src/webui/webapplication.h delete mode 100644 src/webui/websessiondata.h delete mode 100644 src/webui/webui.cpp delete mode 100644 src/webui/webui.h delete mode 100644 src/webui/webui.pri delete mode 100644 src/webui/webui.qrc delete mode 100644 src/webui/www/private/index.html delete mode 100644 src/webui/www/private/login.html delete mode 100644 src/webui/www/public/about.html delete mode 100644 src/webui/www/public/addtrackers.html delete mode 100644 src/webui/www/public/confirmdeletion.html delete mode 100644 src/webui/www/public/css/Core.css delete mode 100644 src/webui/www/public/css/Layout.css delete mode 100644 src/webui/www/public/css/Tabs.css delete mode 100644 src/webui/www/public/css/Window.css delete mode 100644 src/webui/www/public/css/dynamicTable.css delete mode 100644 src/webui/www/public/css/style.css delete mode 100644 src/webui/www/public/download.html delete mode 100644 src/webui/www/public/downloadlimit.html delete mode 100644 src/webui/www/public/filters.html delete mode 100644 src/webui/www/public/newcategory.html delete mode 100644 src/webui/www/public/preferences.html delete mode 100644 src/webui/www/public/preferences_content.html delete mode 100644 src/webui/www/public/properties.html delete mode 100644 src/webui/www/public/properties_content.html delete mode 100644 src/webui/www/public/scripts/client.js delete mode 100644 src/webui/www/public/scripts/clipboard.min.js delete mode 100644 src/webui/www/public/scripts/contextmenu.js delete mode 100644 src/webui/www/public/scripts/download.js delete mode 100644 src/webui/www/public/scripts/dynamicTable.js delete mode 100644 src/webui/www/public/scripts/excanvas-compressed.js delete mode 100644 src/webui/www/public/scripts/misc.js delete mode 100644 src/webui/www/public/scripts/mocha-init.js delete mode 100644 src/webui/www/public/scripts/mocha-yc.js delete mode 100644 src/webui/www/public/scripts/mocha.js delete mode 100644 src/webui/www/public/scripts/mootools-1.2-core-yc.js delete mode 100644 src/webui/www/public/scripts/mootools-1.2-more.js delete mode 100644 src/webui/www/public/scripts/parametrics.js delete mode 100644 src/webui/www/public/scripts/progressbar.js delete mode 100644 src/webui/www/public/scripts/prop-files.js delete mode 100644 src/webui/www/public/scripts/prop-general.js delete mode 100644 src/webui/www/public/scripts/prop-trackers.js delete mode 100644 src/webui/www/public/scripts/prop-webseeds.js delete mode 100644 src/webui/www/public/setlocation.html delete mode 100644 src/webui/www/public/statistics.html delete mode 100644 src/webui/www/public/transferlist.html delete mode 100644 src/webui/www/public/upload.html delete mode 100644 src/webui/www/public/uploadlimit.html delete mode 100644 uncrustify.cfg delete mode 100644 unixconf.pri delete mode 100644 version.pri delete mode 100644 winconf-mingw.pri delete mode 100644 winconf-msvc.pri delete mode 100644 winconf.pri 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 - -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 -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 4132085e74338e65c899dc59074eb32393629e14..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 127327 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%0Amgrks>UQ&_vqbwXMwK;$*WQ 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

g@sEpg zL%WDU$&xInpYAw^QQL9DgOEHLfFNQh8(?gXnGqWuz}dP3WyKV23N91!>goqlmkXHz zu(S?Jx(YIwAUhfr)xpy(Qx&k2F2IEUroCoo3Els{>;pC3+p?8S7Jx^68Uzs1t|c<; zaj;|2T}yz(IP()E)LD$g*y@bcpQ>COruvPp(6I_`DQ$bQ_@(26j9Hv$`R;T`wG1ReMI)^IW@>hh_mNX@ zJAT|#0@%6Sq-1FS&7rV4wcqLYX^E@OGmD+PDH@H&^{1fA^bf8~H@Ijl3 zfMUcb4)5cl#A|V9>Ozm+%t(XqROT_XT3V9)x!YpvdvT)^AmV|WF*@FO>|p}-*WHQG zQ{ntFn!t$&M_95OL8PU$4Oj#@ma-X;MH{Ht6ALtGA*@6%7&0uli;p+OnMZ#Z%=#_J z%pn9<(zl)`na_wGRuWiA1kuk`C5 zr?)L4A&Zr6rF1D2y%hDu1Z2sVL8A)A^wf-^J!mb8Sg2sK!OphU-oDQM%D^QEaw)Bn z&*40Bus=`wI0Zd_p86&#@6{ubM){U=?$+sTyruVMjP&Lbr zTt+|^EmRAMkB*M>xj{zeFWPqE*l+U)2(IkLvln*GDf=LQP@x!QeZ-Yr8ZrA>+400R zxUw!o!#$lH{R7>DtqETs$nDBnQB_qS`VyIZ;iN%>1Q=fuhL z^5vPFzCzZ3KXc!itkhE1fNKAIp_5CSANBINoTMxaE4RvKTADUG(JtolAAdd&znk16O-hq0VY*-IjK&fu&?`{_~ z4|EMQR#twoy`DA1;}5aL!~FWuBKiJHQh_9+psTQ|B|W2$+H&=ZOeji9Zq48~q$P9} z$S?1cv${)JeVJ9A1w46}Fwj}@1lM)%r3+h?35f2&kM9vg zX%T{deR=TigJa9*-omei+Ep_Og`&>%%egD7vf#tqSLu&%VR6nsJ}MN9WeB46ua63a z8S-V#Uq4H~Is{hx%h&PyfB67!A3XTKpYI+2Kc8n0eI@a3$W9d75}e=1;Z@dEP(SA`5;f>aCtu%o1l7C=?Ss z7W;xVvS2HBynSk7j5NAnY;v|Tx9$NMS-84@Egcx>?ICo3(bLo2(>pLuNfV#9L>4Uw z&WY{mkT=WFrlpO|BU3F+&GOFn&;rhnL}bzPa#wzHok%D|tCxyuh7`2|p{Pz?=+5^d zAnU%%3-YR~WHA{`W*MK$?49K@=!|k+6**S)JBF-#Rf0vaiFgZqz9sE-Sds@YdQM38+9 zPjyu)(?^Gx$D*k}x=dAMo2sKN>lAN~zw_g62ZueH@Fo3aqh;0>qnlO>Yv+m=7k+c0~%lpBh>KD!A-yY zw%#fK_YM2D{_@+;KmD@h=pEyj($xfH4T0gJaqaMq&3|*I?)}^P^}qc3+vXjIuWGnf zydffMzRk(9`*{7>o(;P0JAT5;w(dE0Rm+7IvA_~pb)YQ8Uhm<#!#g)`-Lhrd&b^1v zJuu+4)7OxZZ_k%yxuPE*T|RT-*s&95t~~l^9;V=Lw?f{c$ig3~ zV=ed{*vvv02&S6lBJh$$J4K3~>8XkFal+Wb@rkL~CQ;`@aFn&2=C0x4fqtxSNpF8& zfB(SnL^Zz)JY~&-#A^CLPe)s;T;9^sHa6AX+SbwAQ&d+Ap0ehhEJM=PC=u7!*VQ$M zhZT}Kv81tslhqXfp0bKll-elbS5{P3@M^0o`e&;vxE1```q1)@1JF>KlF*!L7Qecx zjKO1<7Wd3D=z>~)nJ_Y@!xQ(EY`SX!r*&j>q`#}Th(hU_t{n$Yk(VVq3#z_GkgcL* z`~0>cK@qjGyE`X0rBgB6%;NMb8sbTX9e*ImJxK(KHOvYM4GpO7&W#RlpDhRq4osLB zk26o|(m)WSx*)WsE5ggiFGSE8>+RV%8}H@o>)xP9Fpg-oK@iKD0E^m2H*dcXZ+4rv zgKhmxqMwtKjRi{)qaWJrh~E&1RyWuccF`nyrXd zpA4wYR>oG+X)9MdQ+=TVGmVsE2%;{DLzBD0KIwiiVoS|T?5bx>P0insCL7*aCA7oT za=0PO-nzaq!#%vZx!&4Bw?e`6A^UZ%Q`moW$(8NEhhL_jiCcYVTT5a=9m)D7YoZrC zWz_$fg?}Y=0eFgSL%hAFp0l&jy|g+_9aGHst(Bjr?h`%7#5O%>fSnD+0hS+BA3wUE zTKndKy4w9m_wGG>sznT83UNqxW({nRY zQ&Q5h3fL0%$9do>d+g|9F$~YOVqvD{YVefhM_yVGiAMLfe)g1kJD-wWTpYAct#mrGDTh$_qa=+9;GqLw~eIRDPr?Mogcw}sxYIRok|;vKH`d78_#MrX`nvjhu}oS& zG%KwG*J+WLbWh;3i1BQBMN_R*)>u<5sjcD-%vKAe%@R>_F-PHtA`2FloF|{iPfKZ=DKE&#NU>;8Fk{PRUGW>3Y5jxg*|`~s%@aAv ziQs(287T?%3Ti?*UT#0l$>&(BVbkt;INxeAzNG!@lZwF*vh zTx4R$SZZQ!>uhpLT13`#cWi+`@eDyuPBc=eW8<|Y6$4Yl`I$-03TbIh>Cid_C8;*?nBxH+*JmN;0yU%$#t^SXx>RNT-xD zGGenCwF(nxfc>K#Tv|qaTwJttG%Y4MJ~}ogIyN!8xVo!#4fsZoLdq@9Nl%HFO=QF; zBqSy#rKIOj`O;ZE@Qv>qN5njOVRo8Oo|&AIlA4y0U05n;9?ipjp=s~zY^kzUUy#CJuKYM{N{S)e=CBI^A9)(VTzgiY6&^} z&miyfok~AC_5HnY?$2c8*1tk19cKNt6n`(f`L7$4F3bPDSfLnu{*N1!4!8dQ#c;zv z5PsnNr(%UdzGV(!zQcbmRw$z9wAkPO-^!=X0)VpPe=Alf!c-7sUG0A_Z(WZd=coUB zxdK$s`ya&+=_`5suX0~RIqZLxhbt+E|F7~;CB*N4mAfk;=Krf4mh3nGNBQ(Q1X=$d z8}IW&qO}O3@;?-C#5>~IssARSZy(;k3!?v9x&3^+9NF?8dKdl(`}?_KP+{ypA+#R) zr>i{w4>z=2{%0{DH2pgQ^IuQT)gclVy8rs>vH9UIPvbW%I2+RP_ws3>{r=B2|9kyD z|509l!^}54)Lr-7y8qyxf4^1f-(ZoqdicsqXA&=0{PQ~wS@G-1D|a71eWCv9)yrp3 z9^5>?`%5|UrP7L9M9(Nng|I=^(u%e(X_Gfg>uaitf*dt>Nsy%*P7~4@RkaOLaczyT znkZOaEv%`nmo!SHvN~$SvptK1$ch!utP6y7b@es83KoN2LMx`Cw3WrQVp>Tly`0Oh z7S&7Tje-<|LpsO+SBv-@T5e`Gty0=CI65&k4YBZdGt-mfBfYJ4Y+7MaNjbNwUfL$5 zTkK#WU;X$pqCzBOmE>n+6!BXJ$ETeYU(ZaA_J~;pc}0wJjzH2TXFG2yL6)sH%wpD5 zl~Z$5GnkTr32(($Q^Rdllyac)X-iEJcPv23D?pOaBo!Yr?pbT`Kz%|*UcQRgZY z(%Ag;xSZOdNX4@87DieorG&|;Y98R3EXhK?{NAMl5<%36q&P;`3|ZkdOI9o$s?JHy zrP9keHQoJzJ2Q}_htp?fCuX`Lg3@b76bkaJ^$Z3t^6YZORBKUEMgfhu=GVS+f0!HY0~;TMRL%cm9Ng80~sTq=Xj?HTm=ISyI+qeoAFb8BZ$-#{sWM&aS*qcan%@Tla>0$Mp&HWu+?1SA+-)AY5T}7ped%OCF1_%24 z&|a(u>vr$LI?*ny8|zus+uPUIKL`LbjiEl#N%-U3o*vD`LC7klQ-zW;ZfRn$yHn2K z*x+DaZ*Na`cNaWM=x}OR>FDh0#5&M+tOM&@)z#Gvd6VA0fx#J$r%y~0bZHj1x9JYR z?8t4VmzPBO`nn`^PW1Qn077R+M|(TghP67#(N^Wo!4Yg!Ww^6NjV&o`$srO)WyB`?#(7Px9UUV8Hr*jF&qK;BR3H9=^3ziJEx5GNPxmhM_YHUQMM2TI)0?0qM$z?d)RBL?$QKBT3qK&JX zASi2=%UfG}yP{Fo$b{6~; zaycB7O<*aNvq{u&HVZ0DFD*f7O2x&t)J4TK zrT|b&Xhf=VA-xlD$NBkIRJ0hSt%i9YDi6l1=GeZ_HusKA$|@@3wU@4OLe|Z5sV)Pn z`@35iy>;PMv&xx_QaofRq7)XQ1!z86NGMobNTJfp=(OUZLSlh(F0CC$ugE48C>ItM z5c1a*6c!ax@$iDdEaz4SzkY9E6CMwBXE#Wmf{2|I0W~ur#LEHGejCWIC}Y5yi%Nkt zFoh0QP@?6cIZJbMVS$!cz@}3Q^YikExyo6THe3oP1IzstitJDr0A+k|Wtf7t7$;<{HkXy38Xe$D`t(jKSpZ_FfRXkWGNS;m zYeQv0HaSZ+$;!%1&tuDa#|V?_hP!HEHC_Np(@H7|KdEX!Q^cp`mvW>6 z$ZD+lBCe_=J2Bkb9@T$glEVcd1-aRI+{VsMa>rLN{E5pl1o&Xt+e%MQO+(YsOqGn} zoECy&@mN_xT2gj(-^?sYv37QLtf4R?Cm+-)E3tm^RtF1+OUWrNub1gMAgj(4R}`kl z1-X$;wbd+(n3RINtn^}Wdxu@y7oF{r=5`p4yXD1b^5T@V^fdTM%mx7q$4aA8IRi7Z zwu;rW1I*M+uqci0^5mtaiEC6sMj=DclCs1eS!Kjy<)uXVIS`CKK5;Ce=H+Ijmo>M` z<#w&BTFIAp%JQOP;^H%C z#gJ!$R09m;qjjCLE{bo*=?STs*`<-MAAZm_gI3L^vg#Y30_Z*(uP7rn$l20V_xTHd zYIbT0Q{DipFP1?OZ9bdL0WvFR8EksXl<)2%}Py7Oi0Se zE~#qnXluq~%Ui{%!QtWA1&L7+5mDipZMKR-1Tzy$%p5edb$GOTI2 zT%6<|5|y4385RV2)Qom3#r&D(qJ)SLG;m&USPX5@Qt{0sEj%tgQUAvCk2)59@hQ19 zj<|N04YG1cGM|Rn*L!#OLqvKUqeX@`&TncFCHwjk{1AW4Z?&(lUsM%7mA2F; z`US?M!~_TW2LuHswU8C_8?!=veSHYN^L%`~6FMywDgWW)x$5KVR7+}4Op$f#|`r1P3Z@ot{B-rsq6mBZvJZLW>;3yLpD@b&ff z@$-w9St{oD<_CIsc#*wTJY8aYh>DeCc>%GB#+RSG)-tk-Ovt1#gpKw9ugc;Sq(ucd z5R5fnUH=dgU(zH+C5xLHGMwBzJlx$q$nM{{dNT3(TUHzE9~BuM=;h(=;pLqUGr|0+ zx(F9%Hyd{qH~XS-qT=hy;Lv!Zi;vVb^+{pizI1^!zy?{NQ&FCm66t4$8hm_t^?hJE zPlk6PDZ|~-)y`$LlN&=SX=rE?#l^fq4~8pxvk zV~s96c=1se^8*hkt!$($vqo0f^O-q`5k5BN`tP4#dE-Z|m!RVLjWyBMj!rfX>m3~( zTuSlSqfr=_8sp{a}cM2 z3R$}`i$}|h3-utG>b_RJ@+6>23Xz6boIxO2VPpbnCE1E>ZD;T1T_T1!MOqc+=4@w8 zAgPcs7a^utI6IK%Zf9dnMo9>nNJ7cVsDlJrgz4e+{_GvqH`>MyQHfba<#qKpK%?D- zmBkscA#TJ^I+g)iWvg5x~KE2Gq+WtW7&iyW>U&T()(7(nuD~8qO_P`7tC1a z)sri?!X>p3-PAK&OfW0-E6kE?S3?^iU0zd1voltMWp|FnasI5oR zSJpr)Ku~{>QD_8-U}kJc(w}c&VE85gV!*FkLNza+z4=I8%LwzG6V>(-M4kRD$^|vl zeEI0ojgWc)pD(CM)zi|^(Kq)Av3IgYZ9+XwjSO_P^fIff_hu4ngrn zzn`{qXt=!@lv`@g*U`~c_kuqCb!YhVv*&Lhzw`<vyF0$}bIB5SjG3Ki4rJy85^nX?-BQSNWjoiR;(mcUBe{2 zcxCxo<;`<_kn}~L%cFN1x`x)ax*siH&wum!?LAmjLl41D9>0Wlcq77G52FZ=%mXL1o^!dvdFW^W0 z%?m@YUU{e}9SP*^g3UGwqK$xFANywW!QEK=C?2(&xS zsGy|91i2H9wO^~=K4U@WR&creES*O$ob;5StCyC~mOOcxh)4C+C8m#`5}wU} zuKwmN2|E85z4o`BzkF}tVxjq({7gmdUeXu{qTl=d^yNFaAfkU#dLdIJzHNo9K2lmq zg(=RHWUT#0_0Cx{N*OFc`1zmip=t}BslPMAo~Rl~SG<+T6sg=_bozST1&2d3bIE%ziy z+n$Y2AECZBruy%n-9N7uP6ze`mm6^R?xQC!G&DaveEi@Z@&1zAk7Dp;3!iFm`yO_G z!IP)@HX0gCTpIb}g9obWnj~w&)5i~p_mwYV5NEAy`LN@}h3og9y*Dto3Qommk%FJC zke`2wsbb_LhWpu@>wkRl@Xx#cv|?6yd1d;`EB7D1A*epOf0uN7$@M#t9CmpbuSnCxxOM)81hkuW+kd*kyA3*8RuNOmyzux_Sk>ta9O`WiLVT z&5ZxPJ%60Pc33bo? z`6Z>LbQUwj+D`k%pYZ&Z2c~f>PAPtsQO2k0UcY_w+Kt;EKHR!;;#MJe`Xrb1;?a#i z&z`?<7Ck-h)T!H^{UC6{e%G$!XD;1_CNw741*JncRhwdm9QWXr6~LU}PBheht9JL& zNxhuHBEV)=RFwu{x>_IgQ13i8n+{7`SVKeVm}&M{PwU=|TN)p(TsVBQfTUPj7j33~ z_tN?E=l;BIIxZh_O||{`|kPu z8>cSX7Zp%xrA#)vvZ|t_m`bnYG9XD$D=jT9p);8krABu@=sdac;KhTBXAfO3uu?3Z zk#n<>l9MvI9VEqfv!aKa_8tA>!VT~`eG9UCTvj2YR`7=%vi?LN9~P)#zK-U4AJre- zzH<1gAGMHH!YD5*F9mdZ36+W!uPUMWC%`A@nD5SCd9Qv$Tlebell!mcTPl!QXT_?S zx)+;v9z1sD(yd1?KN=BieN%F%ocjDH!ogmtDZl3Y|o`UqC#nU!b!1es^;aEZNDErdHyO4 zhuWqjr{MJblB#+edt}{0GcFfT(|Fl_()sZG!Ocsje!u2j3|N3iqOL6|O?toUpbumy zipw)p51qHP(0=jfsbhzCUCf82`dv@;Hf8^x3%Xd^?X&Mn7{F8EF-I~3^ z0a>>pvWf}mh#(IuW1aWUAKtil`sm&rm&hpvG#VsjwiRVX7+%=3d;hM3UXTqbWTrpZ zbL8ZuCvP5|KXvlZS&IZ8S2tISbH@*>dUJcmi8J4icIKO$-uL^ioqG-*JALuS!{_hx z%&c8QAuq?PwRS>InzFf&WeN3hFxS%ny{?@5GuV`4JPCq)6-d)(Y`}c#p zcI@7N(CX@o!zGU)f>;mwPuk008%Ysa2FJ9lp1 zwsq_FUAuSh+P!P*UiTtOK|Vd@_LiM{_8mI$r<&H&D_3sbIQIK~bl-wKaL=yoo3V{Q zZrZ$U_x^(ic5UCa@6d5*w};PR;bY?-lu}Sq*$}$K3HfQcdlfhkj7N^<`kJqy-(5I$ z?7-fgJN6&gw{I^FMA*4@%bw5DQg3bAwqxg>0|zfXQ-Aa3!T$ZbcA`71cK*0)*Pgxm z_V3@ZZP(rd$4*^0XJTBqt>*z|GniI^e@wm(QL!{5$A0 zCuHZ&9ox2T-?nYzF1I2`RFx***syu)Rvhif@neU7-?wucx>XtOz_zX5z8z|?bN8OT zd$w=ex##yIC(d5J1xo3f+k5yY6qInJaSL6LzpeGHVpG!NLVcVF2AXfw?p?ol=J=ug zdv#gR&n;zVuKVHTlRH-~{Bh&}G}U%= zrxN_yif&o5VVg59qBQC1FB=J)Rkm!|3RkT*qgzx!z3u3ZHCwms*uD4Qky970+E{K=yS_U-~pq1#t%+qz}*=1sqB zaV*Tw%_&K|{PPClM&;i&Zp41G+=y=adGlsq_-)_56@GyokDfe#85;kcj)lF4UwBqA zv%d1aJF-^kQL(TTyeZh*k!Y;>`sw|fm(QL&dT=i&fo)aVycylNg!@+7JGO1v1h)EV zlS6)Pc2;rxh3|hNtXKN^XYzWbUw%P<#TEEr6PRh|p8W@po;dU8)jN-$zc;e9cMb3j zEh=NnW4`r4wrvO$0U;+jI>^(Wh#I}a@o`HX`hD+iP+`-ijX!U;&&$cmq{acf?Rw>3 zep!$Hx_-k3ycxFQz4!M+xN)ul_B%s@jk8~%eSuA1ohb4Zb<$Eo0F4wR3=MM*;%wF2-$czv5rg2O^pqigErHDt9tL&wM*yE zoIG~uz<#j!#`Wue{^@Uj+kkGuHmU&bMr_k>;8S1^z}~z6z@cL&PoKYd?bbcDcbZtf zkjp48VO5I+ZN;aRf{@?lU&*P1#!QKUn%fdF3nPt}5AR&R^5@ypCypIH_&Ywbf@xro zP};JE2;;$TFdoby@7eeJ!NbQ+oId;KmFu@3zSJ<(NNVeWy}3q7y-;3qAr#rN=x$Lx z3-Yyi&Fw5P)I|5K+Pz!XFJCx!3a}3ym;>JhL+bYJL>MQ2+p%*O443<$#z&5wICbvA z5F$|A~rQAB{tOG-JV21%?vePKf$d6)joOr z=#fJQ0UWBnhqQa+o;`c_?)&|~!9$0S9zO}Sy>#u?eHir(O$mB_Eq(26^5&+7)_%`5 z5y+-*4A}q+rVjJ>bhNU>%uVz^zEZn)M*un!<_>Kyj_DGK>*wF$t|^3viXg1nt=Nkr7t zNDqdv2e%<8zHsjBnNxq9JPz2TBO8ta+zG$~z)QGQpT5@AGd4vn?d%BL;enp6j@JIM zfFEN3(xAMaQ<9gS5Dm7qw*VQ#S;{9VBvi{q*MRgUW1zE{4p#h%Gwm7DVk-qN7 zw=Y#6-nn`0%B4#e(Lae7&_92^c*VflAJaQN*w?S% z>8wsbHY~oEQ_E)*<)p?%2K%}>*jkeb7N3j_^mH}ey?(Ct`2M}yH*Z|Oj$QlZ`t=(( zZ{NHBSnc_1NI>Wr7=JRy$hMAdUIAgQl(F%lDMjU<$;huNR})0l<;8jFiP2$!UapRI zHdeUOMuz&j+L|BVy-|PhOic|_U9YD03~~(bK5A;~>Khsvn_3XaHV&>{e!-DZ0iwwX zILmP=4OxHGwH%Z!%ubDu3iXFPtUc(9K@!f`$Uq;$C2egjEll%gEiG+r9X&mL10$%E z1!iew=j7(;7Ze_o5*y#EP;}dG&p>|qL8G{aUrx=>Oo@vM4e)Y-6t0aGiGW#{elmgT z85$7ve>5B>D{EUj2PYSIPjA1V(8!piwCwyMCP&UQ zT2g?ln}5c=SjcCW6y;^6CdNgD1^M}SdqU0~>fuOoSmWsA?CRzLPX^+T#wVp^48=}X#8q!SqUW%9!`#rjS3G9L4%1wtAj&=LqfwNqhjI{lG9CUCFO3j?&tu z!b4VUxNaJgU(Vz6D%ebzai|muTDY>Hpb$0&i%Xg1>DXlOw(pKxq zktMCjiiJOI-*@QPi9b%CKJ~|mBM0_u{^qZIvA@1wvHrwmaKLAfI>Vjm`q|y^{Mr?_ zEPdh`qNcX4-u{81p@F{cPPtS>4RX@hDM6O~dd4!RQrgzl(+w1jHlU4s)z;SD-q{6w zl%8%0EkbPwRd#3%Vj`9K<@BCJ|L} zxI$U)=oBnYzn-0*80wJLRExxtrqz6w;xtSiSu+an$MDA|CuSz=@wAN)9v+yD{2>Bay)JOPrx{!U2vW~kOzryya1XNm!!H#%W|3Gio z1W3k!ZblsN>L&u-3>#XBOCO&dC@(Cl;NcIBjhZhFMZUSr>1%9h6msaC&JoagYzRnW z0~j3lvFauFpg=jpda*vN|GR;K!J(m%vGLjV!u)bBuNvw;IiRs92wACofjcCTiApKi z8NAVnQE;gKezZ>sIDT-t&Z%o2(7JknfrfMux=}#<7T9Ot@xx=Yb?F6wB&?G*P0Mcu zA>ZvQ9}`POl$?Uhvcc&Q7!vw$Z|?@$S|_o?wtap_N6*MO@b;8Pd)rZfP&To zbhd%P@$s@m3Y*KX5liKYk_`dKkIVfAq+&5Glaf^+n;Pz)!}`n~!-tf1Vw-KN3Xl({ z@SXQwoM{Iaf!VeSCywEu0~6iZ2{bkrI)}7-DiGLXtCwguw$w=38F{&B{LvBMwRO+2 z(b{2rng@rVFntqh3&HGE*V^dAGCEIK74hcooM&+zKOcn#8NhNx`xJ) z5q%(%t-aOQQzaJWW)`Ftb&SH95uBIS);f2t3Tr0G$W04?=GNWO2B6B*9gUa_YhKp^ zxUE2bfZ?yJb6~JIG=s^hgjQ*p-~*Lx?YBvNwZgjMwEWEUYWxr|;K^HnP$p|?!WxNE z8_5Exv{5E)o`Y-?6Qo$jS%VOv`)#_Gv+gj%!?sYk{08pNW8IgVOO4Y3Y| zD{C4WB%nf5Ga&a0!u-?}4md9MMzHyW3ogyoe%C#{$E4G@7) zw(4$8n}ExJ^g}{GZhLD}qoe`&bRrRu=?K-Z+On9Ji^G2n;w> zxVi=e*3~yi8f9H&?#}TvHf{*nXvGFMWYwa$&N?28nwyvDAIR&JN};l_gIryW36Lrh zP~g4-q8QNJBy}}#)}xAFA%K0#d6Nn#^YlD*QI>J%Dw^L%VY|0n0SQX-$3Sin1%as}2IU<~h zZUtPse=zOvolIekq$Y%9?~@Csutk#QVfrd3g2%UtB6UXQZ0*>DGb;PTQX5qPz=fAQbAk)IALntXs?tF zbhWZ_Hn*~t?SY29gJ5!G03A{phMCl=fB8^169V>Z zN(Hx+O3B07jw)k~y*P_(qB6gzq?DgSHnVr~$>DIJQ+Bnh+9BT@6*gCMn3T8>KUWed zg+ni<2>J(!eJTS(ecfos{LUT-F@O-hqQ8H*t0XloD~C!e$jQpiDg~$gJB@6RnOj6- z=h+(DIJqUx4K(t;2%wP}NThrgJv%Dc#~HIpXBFqOI|m58D+Y(;{1Qlg=jBuBJW0>+ zU?0}Ie6WL>n3`Hzo|l;ptUYQsP9tlr16r&=I*8NAWQDm!jC@B!D<_w*5-zxFQ*SZQ z$ikXx;iy^~tb85KZL=78G}$0X=4lF@{DNhw*JVW5#saWnIZ3tja|4$i*$TrP0xJHae5#>Qnz@yKJKEk7t_ z`EfC^(YZZ9A#2Icq)^=T2zE};X}Ek*Luc1V*v333kO??+YJ8xdo2`*Ooa|^FKzkPU z_P68#c`w!~W>s`Vv7seWjfZMbr9R6A6^EjuaSUDJ&0|sBy7D7Qsc8+ zG)+m4Zr*8l6F2n=cL1?#RaOg}dZcBB`gu55>JgLcdmw=8>J>%!23ZGw9S|546c8-H zj|B8K=j9}Y1_xpRUj_NcN)`C&_I|2=SWqC&TSNn}KxNNVpopxTDvwKb)c9oS;O3Rc z;Z)U1yCr9Uue6KVT*GA+rvp#io~UP$D(gi%=5=?`ef&^=OTU%={(b?$!BKJ5-EjDz zw3~7O85X8mXeKaB3yL!ao9ZAyJat#C=;o+UN zI6c_c-HxDVn$g;gwyShEXSid&DnMiO#(Y-z`UeKZB_>vPLGafj%MJGTv-DAR4*?Mi z#+WIw{(io;J}RDGH8?w?E1@zXAj=NUKPp5=)y)`w^2Xe-GM!DUc z5FK{cM!Mq34KFWG56o+YuU|kyLP&5G9%A;$(tW(VEIpN70_%a0JDeX96XfUZW$UTz zTn4T3bz@R6;iCz`*3B!Vuwt&m0=eaH7wVe?>{4n9iTmD}7E*SEY}Wo2whpD?L3R#pB_ZkrnLa>cO3p(-`IG zOmb1S_YvV@(%jPEgzZrn?(`7895^C#D~mNc*o!8bM4Er~^jR*Ug#} z(^2N?={O zXBScu1btt3W;*C-;HL8q%&i1xY##)&+V9sJ{~}AzFuxl@{ML4clbwTulUHI^SY(h- zaAv$aq~&ZKSrD+xyCh*&cJ`Rve0zI4vbzvy5krag5gFMb?k-La_Vxt4z=0Ttlb?FC zh#$0YBmPz5;T!)~Vs2M!OG|5ese_H3or7CMrk|&)i<_4lWbbUP>{*bvZs}|YA=>~u z(*|c<5?z6vvt%fq>=9a!8581cZ-?3Dv#rFAY-3~V=;G_`Xm5wpKW(h6NVa8db25W0t*qhO3bj_ooI&RDp;*+x#V;l~ z+SLvUtgSF>6&thIIm<@rzSS`y{!7n3ARMm0D#bfXQEITShaJ&KCqWJ}qRM6hP!E1^ztApHB2IT9$y`(iN4)XL7$IXKkOh71=ClW=lZtN;6V z`k#n)9^QZNFg-w^Tz$C#@Bc;M${zNXpFW1c5&jl=2iFO5u8YX_K9GwCA}B^&f|40? zg6jP(2$n<@GQkDf?~B0*BO=MpIXKG3icD0oG)Nx-K~e|x5BjE-4jw*1pL=H41E4=$ z1V@7`Yi5X#hXdJEBV5|t(%jt6butBbf~Ae8w!u-~~_Sv8kI%?bDM za3Y&&1lKjf(ymS5WsF*YUe=!e7-ng{!~~_oKgMZluk$tmrs#ak(#|tc3O!^XMArhd zaxe09AfrU{`4*^&S>-IqDuP1~h8AQ;FTaq2N}fp4(RdLjhgQK@$Slf_^7eGLLbco~ z8sT5jvst+<*j?SUDa2;+2jOYUSh|5LU?Ji=>@3$3e5-S#I3(PRLaC^HdTw0Lkr%x6{`;gE; z)SO^4@6#tOe~7YHcG^FAuWN$YxcCM|P#xDBLR>-fvQJU*`<;8^wkf^tVnIvD@ z03`NSHd)8i)H>K4Pud$Ap@vJ1jP#7C_)@n`fGB6|Cxd(*Amhh|VTDrU-W+BNSW+|m)g?M{HZ_)OsY!IW; zFIt!u+NS1~n2Di2s<#fdCbTv60tEQVyH)6^EDs<@%GDpzjp?P#%ADL zX2u4X-aLKn_l2P1N;&rEgSL@5^qHX0L?*0ATU!Y>$W{YsBLreaxe-2IF4hEX^8z>r z2git|3A%YJIgm(Mk!DXm?6Lc-J7u%PXb;Eb||LK#fi)cpAWSKN01HhEq9 z%L@a>cmSTV4PKBmX_Gdui}s}>uYIp09k0nN+t}<)2zz~!ZDs<5Kp+D`Se}wKEm>ZY z_uku<XmSy4wjyVKz($`+U@Tgz&QNq`mN~X3T&@>B*1vZv^P~0W~EDSU;XHVQ>^_v zKdotOK*=o~U5&CESYR&SNUT(MsNhmiDq&C^s?Uyp^x=_x2QR$8XZMB!g^?D!_T*1a z9Nt6iwB5D;L{uZelND}XzIn&q!%*gxFOVxzQQg>~VV`9LoK>mNf9WY0g%{6+AKkT& zrzEL>@Csr=-~`O7R+`Pe%vO3L>+Jdg z0w-&wmapHsYaba3pWM95&#$U&>TCJ!S%%jiE7h1=GExPfU%7Pd#Ib{04#850FQ=uI zYPKbgrAAhhdvjA#KAP3sS$%%jp7&23xb)G!ZClsATW}Q#L+z)RuiXrF9Xs*N#xcU{B5EI#hqJKHw16Y57MStehzNjF&d$*y%9 z!`80fykiec;{6Xly%i@&hfA(Q^Zt3pe_m*9Azhxr{~YZ?x9r=!4PfS-XRlrR6j?+U z_lE)R92UBIy<|!rYgO2$ty>~KI}23&_N@@K(SAed>Q!O;F5IAEd}D8(+p|7w<7P

PNTgRA9_B^_{cWv3^_prg<@sA$_Je0^PL2y3;~no#yy zk5%guiTAFhlv)`Q8n$Ws-jg4l+Q0wEk!{ra?;!>jx^`{I>XplvEeCPZn$QiK@O0Rw zZ9DfKqT6IY{cjvd^yWAlcv(2bimZdkuA z4APh(E5pP@Tx-ek6>CD!DVz46dhgu1@b&9M*Q|*Mv0fVzLWTN-ty{lg!(uU#7oS?kuW4co9~2Qo(Am2tT3{r#>#?Gw;y*{9yW^l6kJNtRyT&@|Az;u6ExYHPiw9z#nm&LnD8Qz!hj715NT-8wyhi+W@+oP%}#e4xw{O4Ccc<%)3@cuo!wr!@3Ap{Lty?WVwNpCGf z@zY`=SJ;5|3mrs-c%x(1ZP>hR=bi&cSSQ~5;L1&8rza&As+6OZKl_OB1FOFlbvM$M zAdb6z)0SSdHy0gzYZ?aHv^_O=#PSM@O%6gv0RN;@(*){qg80gsyR+5=Dy!Khrh9mf|Z z%f*W3mfntc=6uTdzEgOcrlGPVKOjJ@!vyl|O zom3rap&}yBT>R|zCpkle3l5H|PF=+xZ!&^sZ>aBYLg+sivqd~GBT)c9o{D52KSDrE zyLatC`CA}>+BgGq-g^9HZw%bDdCOK5yleNKeFqL5q1ch9&O_t3ueXd34-pTcW@PdJ z;AX*djo?q}8AbkP}U(gb8i$41`<`s!2!>-e$5bm7>7 zla20nl5Dn<+7Yx9prm)+A(*5?z$8(m;A^*|V>rA|i^j(ZH%YJ7a>qZ45$JOcC8Im@ zveJQQL(X+95{s{Va0YO>5JD%wo9-NI|gIq51)39Y{#C z6{%7lT*{o-sJnN*xc>2FWR*@KppG6ra+Gz1b#&3OW57X0oP6)X<&Ur5yaUf|JXau+ zq;b+m4Z3lyrS70NhY>huW92|=JtmP{;F(06cy0oz=$%_PuVaIOj97r8BE!Sk{^0;r zojm>i1>mu+-@J9_ZgebaCz8n0vUnwvMxDu0`6nLZk9I3_`Zb`iE-A=CFY&=Y$K%9B zBMm{>jHzE`NCO!iDqa;obW1@)baRKmX#^ZDff@$8iz_2<@gKA|Y-y8ZDNB z{}wVle;3o%tE#IiE6U5pG(mgm6XIiI&|>Pg?X8q^z>0QLV1H{bL2g#cz|aNz)0q5Tbve!pM@RvSd^;C1WK~ zGPmTE6mU`~NFGgoQAv4ajk2Sw`u1DdjCsC$`Smy#HPlv?mlT7SBReCV&|IW3(%Eu1 zg4i(1{%2v(9Zl82X{la-O7K-LSDwSZ>V zAaTUfQc!{@TicbzpT2EX#Bg@|;{{o5Yo{8()tahGL~W@OtD*vS-aJrQ6apWHiq$o@ zwYODBj{eB5oZJQS&n+Zit^Hij|s)}9dj2LxIJssk1Q&kGX|Kd=?aGnwThto0g zDm+Yw_gmW{S{Xn|*ta%Srr+H2bB|`m?7(HndrvI{XsL;%azKGKWqFcMSlfT+2&CDp z;2;0z8~^jCH{blrn}7b}?|-xORnG^}We@)Bvgnt8_}^u#u(1hSyL!djZ~pd`*_{jr zmw!Zj%r9*RG6%R6Fe%LhUsxkJ%C^4@pqc;gPo>uPj!y#8MYwNSAcArvI4`4KJKUCg zchwJoGjnoYd%0LMKB*_D8U*!5P7FJNKM5S56Zop3Pnq!Uk3mm1`xh5WdMEW0V?(`N z-Cex{fR|0^S;hqhutovRGCYLX<@kibVjOCUU+oQmnOzvab#ziU3Ra`OL7JKj_%bs& zMw?A0Bj&P^q2XaXg6i}X9DON|;pDSP+O5}*4Pm|?9Gx(lE?R8OCcSQy8kz+@rwOBF zr0iTUL6_~zYRC7;x-hIYnt(1dniD+s;R?ERN>MA(TWyzGh4A+d{_dWmOi7$!r-Y?gis-99YXNhT;AxVFpVJ z4J%uR=npvFj2$(g&^u$MOy>b8J7b<}F^qw(iWD|s=|2iQnT_x1P77t2VKhy)bP+Bz zE0c*bvJGeTYy)M)FDLMjX}k}hEHq}^GIkNuzg=LQ#iG|!20PP4+o%NqHe_ zK&4qGP?wGLka~`cjF~MlfnXpD=30z^J)sPkn#Mv*!=PtRSnG5Xk-F2`NS!rE$?!Xv z?eM(WI0(}t?Hn^%2(--JH{N2@0(VA%M@`!~Vu5K-0`{oWje~>BYJ8kMc5*yo3_q~6 zv&P5iPhiy)iqiLX0=qQ`n=zR$Ip1Q;w`QR#7z7Zl*N+asD=?u2iy8|oYG+2zjIqF^ zwm=7?H<(Nootlg|*zc%i>OBa^wS;K@%PUe9zSigjA;iNl^S)g-ei~{q--MqybU3o z9zJlU-)>-FScm?dwAKv+tHvJmq>F_y14C#swbgVC(48|uW6YeLqb(TPO?6%Bjxn=d zI|imU)C0J+0d{{x-|1eP{(%uAiOG)u`Nbxs6Yv`~>;f30N!w7Xnd)kzhmBBY_PZC;W1Nx zMQt}34A3|YD_gK~$kMOvuW9UR(`fZ0biIJ5qk64+dRX0&U8gj*J%HWPOEgHNp*pI-utf_ojMn5fTN9nkJ(2 zOots9z&pDT(z7=9tHV1fjV%I@-N5P1LzzQ^;{#P??NftLZy}H}58I1I-N1NfO^c?b zV|ZkMFvXGLG~jm&?}$`W?cr)W;NaRj=`#D;SZa0$)#-_VBO#1KQNzOxg;kyO6fkD) z4JC-OUp8AH3r^=Yr5d|#y2xobUAX#0yEQ?;VfnG`P`7p<_+oABZK2v3ZQ*L~{|~5x z4n|vZbDMhT=IboEi;!|PTWlE}=x=Z7=&Y~o7(pl+6(txw*dxf}PP8yusg~IULf3&b zjb`-}SWii{M6@#TCSYm=Schs4_7@}-x6wU6W*%c%fu(G1mvL~QTh-R7%q<%jKm?ee z^-yjrie#%!G_zE*+uGEc?hfGVT4{Wprip3}2c4W3!Pe2>x~`s{;f6#>C9wgl8kX_^ zB)iR)(REgJwB@C#z;_2_k|i5Xc@?YqgpvWw-duuo)2M-DgP*rig}|4sQ3GIHxRTZE zO%Qg|;JvPau8g?U#;JPiCke33YhAB_)VoDpo|w}GfFclv2zSue@*7V6EY4rc?`B&@AAz`%8J;Y&98LsCdcZ4*>B`HGzFlt!%GN7FP9> zj2fJCX=i97fZnI;?cqMw40pFQu^Mda>ua0nqT6du058Y{e2;dK101OC=x<7j6_&$} zF$Wk&juJFkShoRdo~orOTacpcC6L1hz=3CKXEbVBfg`UAueGjjm_qPXod8dsRXqxK zr=fvRNtasA;U>2Xk~+gc044L9nP3+%|)1+Dd}QdT8ZVO3Sn zQhGPl(^aW&fS6WIrGT4|q#WuaKw4uQguD-wRbNj_b#AIqT&;l&c>QXsYg-4#BlOM_ zgI$f_>!`uQjYDdH{36S(ORFKmL9YZLv8=RO)iFLje5)kPErTsaBF!F=6QoS)+~FIHCgt+%nljnD}rN0YHv4>~V&^F|VXW3xvCeS*xrdWh+~< zV~`6{MNj?{1|INaZkKdWQEx+DW|}xIQ-v{sH##Q<`};czGC)GhD^fxQ?RrzV!NzPh=%{f!t=sM3F)+&vbV9C16%c>eG#die~ zah8Vc4z9iU{UX5ay<5^wXQ;^Y?EN(?P814`ypGl30m zUxgwgRU9KMtF7q7RuDTw^Jpb<_fKScfOfrT$cQ6?MO&VcU5r3YPG)9SR{78gi%nlu zUS@cP9iWPF3! zeulv`S}xDXJe}bt&*(-LgWfb=k(pE0T%MVU6Jb{AAb@1!by;$Sf}OztL86T!y%?7k z%ri6;R8%E_G%87wPqtYj6Iuc$J2IrjM!mBDM0mm|QE8b?3{|V{0DNrtWra4fRY8TfCWJRKSQ@-Dh*V`XI(xqzEe>2?YQ zZXqy(sBE%I2Bath?=j@;bX%m~XA-d7U|B&WqY&7VBbO%$ zqXY$QlSWE!Z_-xC(o@ON*g7pWg-U%XEfpf^CYr}9>dFYSVrojNJiVZg93Cv-noLhk zO#vNbYFY|?pteqGLK?t4T}^IT5-0*?vgE2EGOrsOfkJa-7T`eB+t-{WPnQa!d4+u@ zDAm@~n}M2xbdr(GPH{z1$*FWJ&0|#+d4w2}m13Km-Ax*4J5iOKPQIBMnPQg=OnL$K z9rH}eykf~Mjvy&DxoiY8@0g+UH$X@HOgTB+-_zR!RIXGQ%_$jynanckmB6N^Bqz%v zlbuu2(=v0Wn^&4CN0XE7@KF-M!rJOpS*fY)WNVo$B_i2cDo4cGwJoneM3`$+WyOPi z*dH4Dz~$reUzi&Ediol{o+%Z?#Fc9y$ksGoDo$p}7)dPIyd-!tQc`mY3Z`U@Ri-B= zM-Z}05Fy%4HWufmq_AYRNlBo?WXo)%vJL|I=*-Iz+=>@S(~@&F*h`P-2i`i#uz#~x zH`oU#8YOpzte6^{wQR{g zloXPH&<)4?jp!`bp2Ca-T2N|cD;dg@gUcc4AA|PEXgWNO*$j7k@Bht+G3zMjdPoWrlc!WkT5(s2>6fv zKOc}FjJs21q9tfj#FT`RS|>>)RFZRQd8Hy*BI~#(L>!T5BcbU#?R7=clJb;f>8V6p zNn%17Hs7v8B`NWDAV)4&D2IuhA<$NNtiVw2>+Y?`z)cdyM%U4D4DC`emFSs_(U~Pr zQIr6iDwT>PQ-Vfw1foc>HD3ng#%x_dVnt<2vJC#I6JndhghFgbT}R5LQFk~Zsazp% zf~1iNf`GGMH7$u!yeJdK#y8PAGqi{?*^5((D>HL5k~1m`;pxJy9Mh7rc!Efwbpjy@ zg(Oi9GB~7(iJ}ui8&N_YK{Sn52yRCuh-9e!1CmzXm-PK4Q5<(#l1fA*C1qEp%W(Gv zsw@@?dG{sZmJFdlz#`J z*+41g%fy^%nR*r2PK8Ljl&4bSc|bRd1wuYgG~K#v9$y$Cu;xl3&`FoeNt7UGssJ3I zLOjG0*a+kEXl>@j+y+&(3{y2}ai7qE2pfBm>U9LbvNMMLa?5V&{81yz70X;n}xeCOkgfXQg zJ#Nz2CF2U<9~Owx(n;wFES?)zpq^@B2FO|Ah)zi03x!#r5q8&R#qfCGuuYc;dE|W_ z7yrc7k#XI@`yz%bl%{59XEtNhjp_&fj>+n80~6S6b$1lVGvzXIY_Sdm?vBQOMI0od z_Gwvsenf&Bhfk~2G?D=?I$Ylge1SB*3>#Ajj85Q*)0)$zB1pm~#4pZmB{Noi^sRWF zSeBlfo81iO*QlZAe<1J=ATICk?dmF#XJaVGXAkPBiMfXHqG(i>CzPcpL2x+NA)Yra zQ4z;sac2Oto|B!4X={!)D+(2p)t9A81iWyrO+uUq$p3k!f?Ibv{6yR&kej1|v@t{L zFHbUFd%cZF>+UI+XOnm_%BbsPbLFL)E41sOmRN{wa?WLN@5zH_>Rq!LH zC-Wq&1~A#%8@du>d3L{w9=~l$HhWaU0sHHS$g|T<6Lr#~`v>nU#@^m<+#)Wb@6| zj}^ou@TI7B0*k|lXK~!3xot$CVMHEHty`#zxnph4Ti* zU&IrwX5@eYuWM*pNnK?;S0qanB*X*Xg1}j< zxJrwv*g&UK64P@LOcFt&gH~}j0XZExa;TJwwyt(IVYLmgmh^IvS37)Dlh zk1CtAP{vR0FpQ&#&U&4)v?3z`85OY!iTRy+BU|S(F<~0X;-X)9e7T&@jpCzyb4*?N zNs0XU*tj@|qGGK1WyoHbZ!EqW#pT0dGH}O3Q4_pw zaBM=$(z)o3BTdCfbI&er9D)NE4oQlLGidV@v$MoJfkMtB;=p+}P?s$ep`+um(<%a6 z@B(uy=O#=lF-4ILGQqMoh?*EZfn(B*ainziboJC^nN5B9330J;NGX!Y(s3HZ zskO0}c*2XE084wVYLaNEs}m>D!W^hbBI3qMtNX^-x|b)kLmeeT5OPPyPfJRT29rZ- zRw}HQ!!K;FMdo9nh{sK??42-%o0$f!I#0ksOF2AYVp6Ii8#!mS4Y+T1ctU&rJj4C= z1eAt2kSZ^$kZ3I_QJ4@LE6k)y?ZLK?Cy9@ap<=!7OG_j1S58`S2G(mVzhq{jI7{MU zqT&;?ije+SQLGSg;<&tNc~B$l3c<+^IEhWFrRQ-+Sf>HbT-?T3nU!A%)`%1-VVa;g zGcl+!&=47=;$Du8iC0baRVsqfm`D>91=vB#WITGFCxa5#nMFt8PfRR_N^mFPXxvhU zSZpq`SsGQ%J!qhbHw%fAZVKZV882PU`PoGUImm5;M1BHREG$+L@m>&nuh-H67KlUg zl{5q4M>&T>#o5N9pD^>W<9#3k>oL8Kh(Uvqf!k`z>HyNl1ZV6HyTI_VIxu7yqC2iS zJHHs|i)qPHsEKSFAc?{x>4-owx0P<#P&y`+xS41gHcwaxS@E_I9Tyi4eKN_q&mo@> zL5j>gBzLRYnmb`3mQ(=Kd=}>!N64zLX)VnyDngJqEjbBoB6|#oqByMhIk6lh&X14l z2O$Twcf!U63oT}K$RKljc)S&dOC@+f4SYiDfjD>$(VSYP>O+Hi*Ii^RvOYCBiN5OT z(liw07w6|@%IOxNy4ZTb+_-4cJwcO$Fb#BFWV{V2pNg}JM@tq#XOIBdXpE4Efw>nJ zmp8Pvt2&2=wHDc&4;h||3N55L;DoO#COU9Ueyiz!EggWyNL1 zc{v$G4sr$s0ydvYn8S@vn9|umdR+V&jt$u+gmZ1lMv71IJoy3<@*~lLjGX+!vbq*E z?n*(F(juOXdqMm%EMu4+!0^#fS`K^&+Au|jBBBH=o?}8nJg=2BU~*6n<)Fsglbi^y zRRXr3-h6VwULuL+1B-yZu2r>nsVdak5sUJdA2FC#t2)iNF&cZkwrWgxg}^1CA7n`q zXb9VGM|1>_uJ`1iA|8scqqkJp<*^c2Tz}La;}jCm$v7wjYml8+SX$T8*3nVbI5ws? zT?7J+>2Sv~0oA~t-&|Q0R2MmPw9WLc;Xm9 zjw%2f04G4O1%>4PzxJ-isy?00lH&d`;|H%5Sw_hopsTZ~ysEyefCT&@CmFqfq(L-? zC%7jD0|T={0$NA!yNL~HjakqZ zNI_CwZ6lqUn+bl#6y%lTlqnMPMV%yyZW+twCb0PSv@v5cWAg){C341sM@)i?4FPr_ z1fPW!4b82%SE;6cblf;}0EjfE>lM9zN(6E?>XlU(8_13(7h^yMC7COdDCuO&t_))K z!V@?a2BO|#5h)oRP41@vC?YSvq!I)dZ5y6A4)O@g#q8RmbS`|L$14MiqK;us%5mr56#E>~nh z>3N0VE+0S`5wkj|HY|02vi_XmH*-^;1+frP_12p5`W9tP8M#jd7n8_I;i*(I1Gkc} zr8dw3w8WB9NsHjZBGo0h66iV)1FJ?^0(Tia5);_zS{nX(li@pO{|H9Flul~O>RXx{ zs!OIzR)9c=mCAr?DO|>YL&!cEB_cZ*?lspm)RsU`P-;naeM>{ZAl!cTI0b4=777rw zg-+)UCVj>_AauV34cto;&y>FQ5a-oR!`tq7)u(#D#l@`%=%b;kM!XC~`^dhRBW{3ab zXO_YSj@oQ0*9}+YRMmmcrlmEnop^Gg2$O{i;+EimTT{jMVwP#DtZqV_3DFU-=@140 zq}^wc1bszDgu)tbQ7Us`R#rBaF(|d57^4k&1cXSVppV4$^}rnP0%91x{?`$}#-fF@ zhelOX)zm`sMATLi{7-Hkcmt?xn=E*c+1czIAH0EN__E4c5++gM(k0{>j1rO|q_M^Z z#xY!d-yb5zMY3PJ+G;^F(4wN0b4aiRU?lVyuKNK`K~7G1?i~Dxekm#eBB;KRQo7&{ zCq%)ztLr8#Mx)8nK>2VO0dx0vTgJhNLaL{30?9wBhu|N%b*ZMZoW=|lvhxEA5NIIO z2Dl=Lgm6eqjpz>n&d#2SRwK!>t@$gD;WlH7(xM+CD8!x~OJ-ao$8X)zEuBjomWwJRII;RIe1@^I_P7Hj;=YMVD50Pe=4 zh}n+}OxB)qO=Y;vT$3?unMAAcFuDV%tw!)Rf#Bt28-*yfD+wCYQDgck{e+6URKf5J zI9M=hFpSX*Ie4tAolemq+%1u679!;K(*g26YQSzxukRAA%w{+QoXj7>Q3e1>0xEFq z?NUR#EkunVl3{DC5XGk%YG(EK!!I$Zk*smfV>rIJH=_ft2rYT6AJ5Igtdh)og0$!po|@&O%4vPOYA0Gfar@W%8-qU8uclQ1}_yaum&vh^JRK@d3tzyq9#6mev20Rc)QJab#`=^Im6cascOLrU2bPT z+tGQRyO-~xfPjEN|HVJ~@3+IY?>mZA+9#|>*Y4j*>N_}!c*!8 zV(V!7?78#YnTvt~d;)*)`ig_s(@N^w`Ve*pN7?Ae@IYr%h5SbNx?jKK@6GgOy3dqQi@T41px=_8u8Ya-9sy71SH28mJ*9VcyuQfC+uPk`?ksy- zQo=Wr^{8(V&7#g`~&8x5m4_8O@!grSsv$M0Gd!j(8q>!MonUA4E#;%ntZZjE zIJx-*2fn(uc=%h(o_e4sF>En9!N~zu@a!W@MgT`J4(l6=9W+1@L_to zI?Tjm@F)X+lriWF7R8t z==D3G(tW~L`{kufru*EPGrpk)&{NiSvz*-h1HZQ^<=YwkqiZ@Y`iGylhx05uRN$L* z0+c`7*)wSI%STj?F7R8wTe3CK%gbf_yy0Y3VfXn zV6mGq+r=v|@QqKNo_LEzbLLfa!EAKFV|xItx3-(@;vKN)Z$QXD&DYR}uX%Z(3m(5F zlYs~22Q2z)=F=2T${N1>nwKYS1CP@HEZ^BPFz~NgPg}gjGWy}Go}OeBJaW#Ndeh2w zrjtidz<;GYeepQ6o_@j0(`hEA;;(o?`!gNg0+zh=@srJYUsd^@BSGHojx)b7GrnRqgy}oDFqgb^;AsxLhihE=7Sr3+flP#tc#+Qc z3|_dt`{8Gv>TjZ@Uu6R5{26l=1O)$7`cwsesW9!OB}_Nc1OK7{GV!?j1pn~b#Frj< zy1#aA_hq`0Y3R!x0NaQ57ac_g;WK?@z2S{P_%9}CWks|f^!xm0DjbFDK3?pD9{5rR z;FvMXg}L~JTTf%be|!^KLYY1;v%YjJu(GyybPEjFsDAvjPvcW_;%iJdNBf5@0Q0`9 z?~+%a!L zp6%W~&eIlXW#ce!QQ&&yq&~lw?rxCJJcp@O(Av(?J;*=iac-@rU$N3(VJkW{0&MJY z+*_LaWryC=m-%3cnlNuKCwm)W05({9d^bPKUEhO(r+*&1?CaV<*gDSlQvs@dE)Ona}mr@M}LeN3sap%)o*3S1r%C`z@B-AFM&}^Eu4(3p_aVyyfdY_gzS)U@JR^1^)gwkh}kUU&izo7A|nG zgZw$}fs5tO=EVEBCRHr;bDv`ecaNh-z)wq`xA|EtO@H$BaKt7EYyYA@)IYAK&*rnv zWn>RvWo7T=z3}b!XCvcrrS@-NdOO);=k3h&4efi}H=oUC!@Inh&i2+={F%({&wcn| z0yyBw#1_CB^1b&x=h>fVbo7`9pNv1xgZ~EmAKJ!*d>b0ONd#!WW>z?-p#H{+yfT{Bb&R_0+zkaUX2Xx0I@B0B$=Px+F z=J~yt^z0qa4;jJm$$)_QQ!X%a{`UW9{GpGZ`7d1?eWuUf4B~(AUiVzxFBWso&jauI zAK-s+WB$7AnK$`C0h3YwLFj(k14#T&KEYAXbq44P3&iPj%Kt?CZ$94JpO^EQRzv+y z7kl6HzcH``x%>XA;z9j9PxUz0osH&pwEfIv6mc$yyk^#ADivkx=0<(ba_`Wr7S zX8ue3nL*<3Za#}YdFFn|y#ERcSnx0LcQOWnKk)u-&NEiP(BVbFkHQ}i(BEvB;Pz*G z64QP9>SCWq<1YyQ#ErS+(lcF##6Jo4hxQ+VKS2)={EgRA@iXj!uCRqf`}YEm4~_uH zC-@_8=08fGSp_=xy|jes@>TdFvJA|b&-B~+tUws*gD(ax{A&Ca#vt%#?%qL%pUqax zc;%%fICFe8{%qO=yqBDQChl0-8~#BaU)A~3ra0)j$i>6+wGW?e7nr4g^$+l-0kB_|`0(#E z{?^&U`_(f~69w3Q`L{uV1OWUs_*=A}?gAGt&le7>p4vRnao~G_fz!%=toCVL5Dc!1 zmsjAH;-^#r<-wPh1bNbZ|FE(j`P&r!99`h|58=~rOY1nHF9-R%JAGsPIWa=u@7MTE_dH6OM;p69KTim0nq^R zFI+vDK5u-YdV)P6(k}uQ2Y9%AyZj3>3a0W;+?n2sL&e_}8qu4+;e}wJ9lt~V2|5D9 z0QomwKFrq+WPX=@d6)diD*=oBJ-){pMUAg^bYvmuhxZsE-!EF00klPFOhvY*xOoHoO*5l^4DJu@CgW9=a7}S8|pU$E4PmyEl>-)meKP_9oYyUBJICW(2w$QhJk9~b05>pq^`KNP8{^{2) zwf9Q@CjUnbh!XDQ-!4S*tq-zqJ@E4MLiX(8pKL6P5ndTo)*MP2q t9rW<%{A(nEKg0a%>3;e*=AYlU6f!1=Q9gzI`^{lH-bT4|eq&}Z{vY!ra3}x( 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 372c1ab8facc738d350fbf2c8d48c89237dc3b79..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 33913 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 QpuFyhn;d5)HKyYK17ixEC;$Ke diff --git a/dist/qt-translations/qt_bg.qm b/dist/qt-translations/qt_bg.qm deleted file mode 100644 index 2cab8a1bf8b3f5c4a81a78ebc165495b2f498f55..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 89612 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 diff --git a/dist/qt-translations/qt_ca.qm b/dist/qt-translations/qt_ca.qm deleted file mode 100644 index b9d29a1e0ce4b8e26b48ff6225bde7efd5ed46d4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 172 zcmcE7ks@*G{hX<16=n7(EZlo{8Uq8v1Rxe-C}b#MNMcB2C}v1yh-XL!vKSb|z@o)K zUJ*kkLjh0)s!Sn6DNsC_A)CPvE+YrllM9r|0jker$OW300;Ch+DipvfDu6OMKr<78 Ws!D)riWu^Mc7x6D09wt&$Or%m(gu`*_H|bU?D~GsJx`mN=Sjk@`~SWA(VLmM^_+80yXT%e_3oy= z&-`oa`OhCP;GyN)9(Z?#5XF;)5F>?h>{BR531xJp5RSuy_+~xIGL)~NM7>?ZP?n>l z?<-KgjB=(ByQiQ;o87-hISb_ul(U7{gMJ-zP@aKufe_ygMp=up1LZ;?z8i|N4kdkF zgz^QH^+J3<1m$9sn^7)7`45y!h4^6-%4H}|MR}AEGv5-zd593hFcy`E{K)0p_qcrE zbuNGHfwCI)e?mE5CjzPV7Swi%kE<{xYzP}yixhTIAVnLly#-A%h?Kwhe zx>$&XzZ0SvXj`&bD3LdWI6Q{+%oE~>xKY`GdPlx1#Mw6pam-^vnF_p7Ija$U z-7CcWHle%*Jk|~uSr0uXMDIJfoLwgzr(7yTp9Ggn3uLK`K3O;}0PY$~WT_mvQ8+Fd zEtD~j3&*t`LOJ>#;kfQKz%Ib$B^St2sp~5o*Iy&VzUK(XO_=Z4BH_6CVDy9E@4z_K zuM5YWm`CL&vQ*ZGP`-zHn}y@0A|duedn%WGDIBi~!0#mCc;ieVKA$X0#e@0av*H`h zWx-3r@x?gMM?Ws-j^Of!C%AlIu`HGGJ}%ckCmee~V;_RNP%7gm3#T8n0Me0VV4!f0 zdQB*kb_?g|tAwaIP?pNf{=zx6UWgmRvQ!Qlf^r+^Y^HElo`iZKSt>JU3+HU~-|q=7 zt4DGfxPZ%#72#Yw6Z3yjIGaIh{eR{1u)bW*b8>m4hs&Ec$x_+pIxg$(5YCp@h2jYc zXBc!n`Dx)i19ZITGA`>&g!7^&Kufv8xy>oWpx3ypUc_bKDdD{KJR$b?3g=DBg)-%@ zT(0>@IB)3?qV+4`yyp%fdSV?^9(EYEPf&;h5?ofF%4I{Aa6V4sKF?+SQ6l#ywBP+_ zQMmDJq0DI$J&r~>`x(*m?5~B`dV&~m@l!&{`9%!9_!FTtJSc`w{Id{8{Tn5IKYA#( zVNaBYquhjYix>$y6T?<;dGYhIRBFE!Bi{fYS&=J765b~*lBKe4A2F&D>%RUuSt=Xm ziBVO%gtBgi7)5aI^$C~t7l=`394o}MN|d*v|ChPEq*Rv5!Ui$wBKmzbO7z!zE|;?p z;Ie*?7)5YhQNiU6lVquExJ8TtJjC#9E-z`6rLqv?J@o_nyH*_Zd+hHKBg7#+ZxPBx zw~51E?j@97xuSf^WkNi?TvUz=3Gs_xR7NHW@yeTAzIue1bph}-dy|;G2K%VEgUi`> zi`gIS7D{-tm@^Ffs^M2L=W~=(*T_=Y=VdW>6yP}gATjsA^HDy_<@86noHLBe>KnPd z;UX??E|sO?$l`J%>NPfi-u@=$)$W7wo)z=X0$i3oBB~C56#MpdQFQ|P@9{C0(?1tg z7dL>feI}|Worry*h-%DD{5(Tc2md0J<*$qC6Tp9*&x@Kf?h~SEzL>xMbRnkC7Yiz9 zg2$e~<&DqFQrY;JsQuDPeYUMm)FJ|Fw+c(M4buh4Ej*zi?Csr$QFau(?D*NL)J zavtMy@@Hb{_Q%27C(2TZt`ke2y%?XL7fUf;<>0Mi+2fdJ%WARg<7V%GOwe|NC3T_B$d%l%3Ay$!odXd?}aP)^Pdyzqow+9a$>1ZRoQsv+P0Ia7Q+ z6MW>n;o|ET0z&EijrjK2?}b=%w359FZg=~E2jzN>H$hG@FsD{J<7nT zJA`tEPZ`vXdV7vg2E926}x;7h+MBXn zvrZ{}81?qtqD)%7ALRA7%Jkj|A=cI?rr`d;vXv*#(_Bx6FHxhE_4?j1tBc}tde8R{>ekmcR;fe^30pEWoPzPNd5 z)`$Uvu&!gW#yotr5V7{Gv4_?`-w9`pe`}}^k8aAERJc)yNYAXP{>Rbp3t7`IEEVFV zkFuuUhkC#JOIG!^53z6eWYw(1JieQiRsRt9>SsH%mVCQWDA(?jb=14S*Wlh+%Rk#k zi1HRL|9)TAit~ZbmK|B)7JUC{O;)%Aa^M_)R(Qi5_;a;`hg8-AMd+)&*Q% zzg3pXhCx}kAH5Ch9hi0d3E1Za9a(pR|A=8*xxDxnSt<)hW!<&#G9mtTYSvxEf4+Vo z>)t~L3h`h?*1g|eCY1b_v+mzm0zCaA>%mRfmkZv_dT{HH*e~0&9@-!C8*&bp?G0HE z&D@F4FLBv^S=Pf;e`r3J?Qds2zHSTT`!88f9r`CBp8G26naSV-`#zNQPJfi`)miU6 z26~@9EbH$_03N$8&-$S1b|K!*&f0Oc0=@HutS>f2gd*lmIaCu&KkGKCJl1fVUJMFl>E+qQccb2U zyRt{TJ_!132)=w$_6j%n z>Cum7ui78*nOm5h_PFC4N%pztlYqDRShw%#^lcn;E6 zmUl?s805I%_8K7)%N!TncNFT^aCzi4jtifA0{Z!dj*I3%Kj?EEm&Mc6@_H_3e<4d{ zpEfRMuHtgtUmcfcgAON5M7a!Q1SR<8gzHhlZkq4`%F~2WT7~jrlqaLS0p-Ie??L$k z%1=QLZ=w7ipL;qkhkdO~nuZeXCN4&ab`#G+iFOm8L5X&g94JwL;sD3CWCi4T4wuKi zO{xq7d-|2?={Enn}N6Sg^oQx;`?v6I=-s|9XDU?_;JB1 zA>to9ep!4HY~~|nsRaJ*_?7yvU*dFb1wZK7N0!R?+qtZ~(dpR)dw};Lj&J7oQ9Lv-x@FQ4fKCpOobCjK4Trwt=4i5OS_0J9zTd z&W>H6>yhs|k0bg0u9_mesx|y_7@?@JUkEcUt8e3`4IHqy3KjZTJZhW?ao_cfXnxl&f5+? z5}yY-Z#(r7^!uapw%^C`8Qs z=V{Jg4#0R{T;TF;&j;TLxC(y&-Cp~ItJlT`_)yN^GEn2%Hwu0-V6kgZbx+9uRjva* zhhBYpnQPP=N$7RwxkmkKf>8Ru;~Kl`B*+`VW&TXp!~q+Hc>4afc)gdQG?vfA(del*~l=3d#*AUqyKb z%GXf-({+Th5BC2-uA^3t#5$L_j{Yzrlv7r?j%mm5xi`6j1!qIA9P0{Q26(Sp!sWUH zTq|pVzl)!AMc)BEpZl(>;}GoED;K)fxgbCCT&@ktvp}y$x;8)#D}&$X^3W@}jD%eq z?z|rM$EmIp-H&0vWVud$Wsp!V{K0iP$>9@Eah>@(#yjgX*IBXKpr3|Z7Z%RIz8mMd zboEt`6B}HYo&dW1=gYEGawfa3xTysC$^b48ebu$?mI=W78Ln#$)}sIA(iY zw+1SN*fGO(N5zSddq=qLSav)75AVC~dKdjo`jX2v`CLA7zw6$QG5@o!a6NpC59?7} zkBtJJ*4*IQUil{>t~t^5%$1mD#WpVgahL0vC(++Os$I`~+yozBE0@=N$mQEBx%}Yw zTz-~tJv$EYZ#&cV+@ynrI4$ma`AqcRW4`OHQQ&vS_jbKqQzyg+`@43WvOnm0kL!#3 z>VoqP|jJ0pM&z(oXcJ3fuGjqT>dBE^LOv$Z0pk# z{QJk88~?TncGi@f+viP%TsS}Hj^1bwm0@wan6T7-U0soTF&S9&4fQ^SI)m?Z-IT#;#T&-KJW9MJF93C z_UF^?>`NDcu4>)cH)Mk!eC93)VW0Q@hr8E);DbLu?%wx@5co^EyZ^yOu!{@b{a@aJ zGT|QZ>l)Zk%iTkM_h%tK>f$9pmCpM%_YF9m-&<`MV3h0y0$e&)V+C+K4NHursh4x<0T z?)$$0Un{C|Kd|{}@XML*hZ{hTj^o{ro{VwUPH{i}7U0_Or2DCI=wVfp-Ot<(d|dyt zER_u%?q}|N9d@hJ{oM8^VE3Hse)Z^F*qaXb+pnD{lua)8JLe4%iu(%pyTk{MkGenj z8{lyAUG9HZqMuP!T;5pf{`$UUun&d%oA&M4k5{;V`W|rJ?;$P^-{$_g405f{gj~lC z%x|X1b#4IMuA83gUKJD~IXE}>?WatFM<3;KU)?u1J)pJ!`xr_TEY>)n!j=#-i8uMf#BzwS@4U$S%O9RNST zl1;e{0_!aB<~E$wAe8zoxeX64hrMyJ`IsLOk_s?&){UMSr_vFgJ6Lh-g zz1)jO{34Vqe#pK28t{pQ6}eab<#G6DW^?&yzuaq21bk;anR^}4`C~uk-tY?aRIxSp zkJG*p%Klg8{&CYCkl(J{yFUVa&)mf2)mP`<8_5#l^2*%p&pw9r9+CUZGVJ4#XXgHG z-pA0_%5vWouM1`Iy4-(m27F)7&Hbtf{)qa&=kD==|Mk2v_uKn$o-%2zM>!PxXv=nw zA5Z z`oH{6&p}Dd_q1ZqA!q(ohznlz9NKpW==K=TjHf;oO4bvexu*>l;)RpA-0^qMyiy1J zN%K4l-?;^9%wIi=IzWG4lzSHa0y-aaxTk)_MA&1`c#b+7<2@JhEdP@edf#qYDg$2j zG&n%Nf4JGxI2`lvZ1ptW1-v`H^EAEmJmf&GC%6^zw%(=1tOD~bdd!oUx(IZtmd9P^Nn&2g z@R?lBKg6^465#WRsh*BWSHmyV=Gpkoc|x2~<~iw8(8c(_c}{uZVEFki_FOb)s}K{v z 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

mtwn6x)5fM-Xsso|O5@_eqHIkqx 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 X0#%g&)f6%00qq8x-vP9miIEWi5&0yU diff --git a/dist/qt-translations/qt_es.qm b/dist/qt-translations/qt_es.qm deleted file mode 100644 index 7f721facaa2a815c04b21be07e9fff1424e75d46..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 82414 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 diff --git a/dist/qt-translations/qt_eu.qm b/dist/qt-translations/qt_eu.qm deleted file mode 100644 index 44beb43380a9c0fad2acac358456ed166be17005..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 96890 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 B-WmV^ diff --git a/dist/qt-translations/qt_fa.qm b/dist/qt-translations/qt_fa.qm deleted file mode 100644 index 0968c5d4ebc30fe40ee0a069337f921afcd7c154..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 293114 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%0AqNyKG~q4cOHZYHD`|XEKGDk~ad$%jKq6L-k!2 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 Ao&W#< diff --git a/dist/qt-translations/qt_fr.qm b/dist/qt-translations/qt_fr.qm deleted file mode 100644 index d40706bfa17b92b0ceb2f55654de6b23d6939844..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 172 zcmcE7ks@*G{hX<16=n7(EZlo{8Uq8v1Rxe-C}b#MNMcB2C}v1yh-XM+C<2O#fklfM zl7YNTh611pRGC7CQlNM;LpFmUTt*J8Cl@G_15}^MkP9>~1xP2tRVaW}Q~+gifMzBF WRh0nM6fxuh?FO6Q0koQlnGpadWhCYR diff --git a/dist/qt-translations/qt_gl.qm b/dist/qt-translations/qt_gl.qm deleted file mode 100644 index 4f7e3c433f05cb1b71be8709e2501224d7c54e70..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 323580 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 z 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 VQW$OjhGC=qt(BFPzjorp{{te3W0(K{ diff --git a/dist/qt-translations/qt_he.qm b/dist/qt-translations/qt_he.qm deleted file mode 100644 index 04da4c9fa71a173236435cf77f60bb0b725045cc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 25669 zcmcIs3wRt?b-t2zR=ca!!?J9G<2Vz=-U!Q<^|l=cJ9=8OC0lFBkA$XVy&6f2S3B!{ zST>~v^7ulNG(aIGG->%#AW#T|ek6p36k0+FNvW}HDYj!f*ok9XhL*I1e1zB6|J*w} zGdnx8k{tT!)1G~td+xdCoO{l>=iWOveS7$-7k}}{ga3Km((m2==)at4XUun&F;>gi z%?~mrZD4GnD&W;S1(Y8auu=Pd!+rR?ow1I87jW|vfd9%^_hOJi`+_q9UVD>(*G&Qf zzu=n!UR%akPc!=a7T`x2YyS_%wmi#N+caZa3mJ1aGS=6L?*{-s1^5NV1_sezH)FRZ z80-24WAA?s{oO2JPa7-z9zGYI67bqDFxNfc+4WHYuYXd&o6j)Um!=r2x6fS(@;xcp1Z_49hjr$a#b0|M3`6tGeIzWsm2 z=PhqB*IO-&HU3P%j-^bhMgJY2Wl|5m_v{n!x>W)OJ|Rgh*X2?`&hN|KAF??W6BsE4=Lt=#)QJ_!$@USlm+h*^dIce!H+`6amTlanu_Vt2*b#(&ve6sMxb#3qiPZs|4eW2g`^}=7h(GPp=7I5pb!nYth zR`WvvYdeZu6Q5vg!S@Bc`L?3=`_OLPeML{aupIuaOu(J@7k%T7rx**~Sai7TPZ`^F zUD5w+Ao^}s??L#rt3T|zr62Nnk6XanyIhf99AoU=&$%8rMfUNC>u;XKxNF_6hk9WL zu5SofnbzR6fO3(5o3!7%74dn?i>^o0os6x#Tfo)LuE$ql{Gh~P-30;Lekb7O1p@Z& zbp7*-uQS$kvw$0Yt{=BxT)vlFlOsFezdkMCich+J^>`TebIkSDZ{H2QY>=c!ASbq4 zz>aYNH-Aj3xb`0zyYaBJq62oaC@$?IKikLDgPwe9dk$i{ygOM69HF$ z*!^ejBE~j8>Av?e{6g?)_rrIBpQeKXZtQYD)p-|U)W5r*K7;SC_6oSFT)@VM-RJMQ z7JM9b|KW*th-GPU=QSr_2d9d+UOmlN$+qIuHGc_MQT&Np|C+H)e^Gq+w_ebHqIh~u z72L)bihuT*3hpN&BN zMc)wcdfE5;dy?=gw+pyDUg94|zh$2<>6$`6epWKF+AE4)o$4fqc+K>41gn(-*1nj+|+F$p=Yp}Z+|Jv>+VaJF4J9a_N@BN&Au_TFB4xf5~37cYGy)xuc)V*>VlwDi~4d>8Fg0`^yx zz3+37=eDQI4!i(8l%Fkoo^rY+50?Ee`Pp@A%S-<2DEzJluYa|C`O7;Y-@)?Ee*nLW zzE@S5yo!WS_I2;ORq@BrHdZCWp4WKRH8~sDaPB9U{hx(6&ecdjVc8KcSgD>UD9!- z?oc#okLr=8q-p7#^qP+B?u{jtM9P8i5wLMt$8`-Q(oS?=m5xcLq@U`z?w#@BkORZF zvK6d>`M}FXa5E{r&SdGdbOf(w(ccBUtHZC8pg1jE#J5MJ%Xpo_ua~8h(j?wbYv0XC zXZSA}I(2&gwJREY-I1sw$JCTOqNZcRb-s=$Ii7_P7$W$1am*fPYq+f@B~cy-jgo2Oq9|D<9g-V7z9Iq`+Y409SbKXe)q!TGQG& zXv!FeH?T97R1+y>*uE!{li5;Sfm@WMJ?b8I6Wh;HY$KF^gsU2+zy~%dodB!H`4A_i zOE8*g4EbezKFyWJ4TqbV%&Gw!@wy4r)(CpKP#SL9pW4`#P~<~uT27|5HxrTMn4D7O zVLs{P6%BIripJ_qH?0A(J*P`Bq|=%yPJ)}0#4W2~E7^PWzDnDoQJIV^Dc7ugk3F4b zj&$m>XqB63)j3hCfGm!{bWY;$Eb*lC;%iH#5|O>>l#}RvXn35gL7LJVx!ObFefE6Q zbUn#+a#}}scZ6bLC2HTG8Y+Di$`tc^nv3pL5V?eR+HBSdE$mR^hh#M&_p1jKImBgX zPjx9b1foHn;v)WO7959t&X~rrpd+EcH_6+S3AtO14l4?qNWPN%wukai&CHt-xqbsuEqukY zVaR%~MV%3cq4{;}X_JF50lpGWsfmcQS$qm1Hu4sBPag+XODbVo$=LjQ+iSkz^{50hD3%8SW>UF=}t0 zs_v5mk(h(jTv<`VwGHyMXRs>or1H%+o0ix$hm$l^*5d$+o8jSv~c}MjR5K zN|@*gNSOGg{1$Fm=eBr9K#8g$hoqqjV<+DRzr$7|Oq{0lP;cwqp@fE4tFfrVtX!Pc z`V=>yNt2d+y!}KX;^f-PIDsSVMvJ|AsNs!{rdkOty#lTgL^0yYtcg}kxs}}JppQym zALqd^*Q-|!A}tB05C~^+M$2Io7q~aP2y&UEgtA&%16<|;H9}0~;Fvlg2gV}9!!XDZ z%2VvE(gWW%4c!@$-ZdEcpo7zJqbGBA=o&<7Xis;kK!v1EQ_ccW2f(B?0GAR0dG8@P z;2en;TPg9B*chro!`a&{vC;rH)^QtjoCV3R|-7rlx3L>{Kb=v3M>?5O$Kmzr>N4en{!k>g8!4hX!KG3O^}z9g2>Jc&g;a501ZjnyOjugB zf`#*llGBhYF+nAp^PqN-e?oqO?@od?`GhGjIs=CBsxx;DGKxef6;Wd{n2g7jVRDyb z8)=k!NRkVJP1}^zgqqklkWf=8QwQa$0*J!j~xY>Vk3gC{dok<=~Pr zYBNj6E)?Y$8(gehd1x}qb5ekos3ck+2CW=Sbqz;SnoOsFdkiBnu-$=yP*S8CR`d!U zs9)u=kE~`=XGcQ$W|-$y);3fgqI!rS7zrg9dt5i>CG5zc+7VSk+$OA4sUUO|0yGzd zTpj5E58hVfGB6<0l_@G<=;VD`s)A~Top3y`YKo~w@kr{3s-kvDT|`n*r9G73f~3;r zQ3%o??&%L5jL;m+kj_Sb1VVaUb86; zHtkGA#S~KoYYDJMF>jg|Kq#7Git@5k170a`lY1o3^a?LgA@u}jsC{TY##H^_--y)S zl(WG)2`3Y3%uDv(Ajok3d1%du~Dj^jH?Ie9nbFQ zb7pCyE%{ERze(6k^QmZA3jV=8?bN{6>2s($SH_VnA0;*mY-Y`3^m!a~Cuxpy%E$282w=$SVlk|SDceaX zBgk-g1))6Hwl|qdgu28(Ngqdrap;2Px60r`L{IC z9!f^S@Z`>vYRq&%b#^|>0vdz)$kJw&NWm_eii*X7%?U-xloYLl5*u6;N6(nr@C-&P zLRwqUcG46Np)h|4-zZs=a|q0BKRBmZ zp6%Tn-1+V9<}{z@)@)AuY!S`2y_(Z}UYnmetsPxp4(439jB*wSrL&dIgdw zxK=d4Nh|!H)H50%mD7|2_E~tTDW|0$6aPF~XCK)p?iv}v!i4AjIZeb-g`<4AN4ufc zVU^HWP`(Wu659be1bngUY%Z(yE@H` zG>1nz5oKQK@;+#woNhM1?=sPaq)r6*8A+N)#;EN^ znAz&drm`SIML%tsO{vPv38a+W+Q(blFyLl8*bwW}nOzthdVgQrE!%evy}z?}M_0#C z@AhrfQF(B4Izsynkucx);Kp-h#wP`PQhyxlGf}!S^UF&h+s+)SASMcbEbGc5iA@b; zqEu?bsSMTwT@A4TZmy^Bz4;u?!k(d_0TgKVrxlpn2#&IeDP|&fW!7pU@J`LuL~364 zYHGI>4vuQcbP&}znnOqCP}b1RxN3JoMNu{^PUOfqg*=)XBRe)xq77o_T_$gkb`a;f z$z;Kv%N~=ZNxm&63#tgx4*NzH+&rh;EtqrMV6wET6z&tYDYN(CeIvU~SArKlZ?*is z6^*x%llnJHd}PZYJd$kiO9Mu=j{&#jBPoaMzd_>*|eZ;th;&M{z$;s&a-Lc z$!U_c0cg{LQg5yeOkT=WPM9(szor(s6Z?P;`lOtW%HG&P1O?h0p~El6l?eY}DuiRq zF*z`#@@;4v9`e-`q+q`iOY_*~xSlZKS{U4h z*nB_{_4uyXC>$6ciwA*2W#dfIXN{{z6=zV3gWLCh068?rb6koH40LXf(*{7&Sc>={ zeX8>wH|?N%`*70jSlv)OrR61@d(@;Cjh3o8i2C#{m2t{~uYTs-*Yh(3r zGBs=+Yo?5i9mIbF{?@VecsGteV?(*JtzNEK*W4ft(V8gwc7v#iAdH8rW$04 zSPg3dnP!b_ri*N%3)&jwnwIs=AWEe3(rn~3o8b?MX<{`)-%7Jlu4!(p2Th`!mu3^E z*$6(@YBV$Stu&kDn#T2OL6a!wrP;!1HelrIG@6Z&2k~sB*&^38G_M2A#)esFwrVu% zG3Jb#1br*bR?w_(0ZpRp$fpb)(THpCn$ZyPNYt|_RmtVvglplhYJUan~(t$?I6HMmH=uf&r)+8?9KCD`Oa z59TFVNn11$N-9a?=$zHG1FT(}F(fSdGn7FJw+e4zJLXJ7eLdM?Lvur(5ibX2F=^I< zYQ`9iUb4qs*^X(mww?ygsXGo`=48brZ{i)0Vw!DOt!Rf0)-=)dZqCDJH3*7{*kT%g zhUaW97qnv{w(!9duZ~O-O)(LhU_JDXn9R_((!@k;YH1>sgK}P)q>mbKOOyo741Fuj zW=!rDQW8&WCX5EK)!RiB80bT)(K?U;zIG!a2FFEud{h0Ty+1YIjNOhnktK^Y_+sV!$65L*{$ z)W8;7byYWlQ=5R((b5GOwvw(J8}kI5<*bwS>12hgB}R#CuG_8b>?5+Ub|Ra{glbqf zLVT1(@G1<+Al(Gsb4gd>URFefEpg&aO?il~1jh;+W}|pbaPrL{nem*Bu!&rOEb3FR zGn0Uzn@DesYxBq?Pj2K7THP8Yx5wZV&*|BN#8D_^%*C$AV8fkeADr{@R&q$3o6Buk z#gCeaW4l_9rfjuDv`&O#qkJKe+kO>R>LIolI#HpOVNEMSRHX2X2(xW-Fa03?#A&N!>8-D0N#a92cR)xAPy)D*$B#wV1c}NHUlem4&pS$ z_&Ad2>tPvPu>-g>5?3fPkbh{*m-s9}du$kFBGPvU8KpXV$YVz=53lcnRRTL&x{=#Rq!(S49~l1 zt1PT?3BPw?kD8=NW3Z&o4xHz~&8SOeK%Ib4Hn(hk@h7)QunmK}7$ZB;sTBQ(qqB^##BbDIioh_JdL|1q`9j^$N zf^FEyTNTTaw+D8SU8itm>JvF#lfxZ0y6%ecEe;Es53xUn(IArQs8Sa$4)P=77GyV& zlPs(w7Ih`VcEdsNH?Iwfx-+*(EMsx3JX!k9Q!ub#x>+xVlQcNQ!!B$%ByZ>VR16DA zA725{(J^D+&DE!j*x9*@rmfz2p?DmGgYvH5{K3cFL;1dHjsxCcfZ48_Coce1#S>lzr{$;(w1&hy0x3#uRcI10=vjcH(BtRo3rzH)J zMQqjS;gJnFmo6G<(82lm!P6lqh=#piM|Wexe222%MoVsyj_H_1NVIIws5)i6pV$K`1T*1Np;_MV{e~RaC(7jvSG~uy`@B8rcmnYHN6uzT9pO;NX z0V~B5An4&530c9F7;zxbAZ(Xg7h`X8B$61X@f(`R#VTc|yifghW~lMmFyFh8+qP|WKZ3^d!BZv0$h;!8VaXe&YE5M>F!9c(8uD(gBv zYRBl(-T;i>^Y1VDgLH`ribx^;^ArU5C~rI7W6EtXmtCgZR{1uXa+Hgv4bmjs7YHEK%h=%i!z_K(ZB<3%^PHYe1yNZH(C-suj)WnA#eMx2!wwLfQVEL_EDh}k%S z?H(KpIEZTAdwJIW?t;sw$1Yvw>b-!Hkhs_&3O$!#Q>1ornV0V6(`AWcJSa@#m5MD_oVi7bh1Fqx6HEz5L)z_NtPztb?1|x# zXY`a4(=WN^Csj-w|eMq5y^fEe{`M1m`=;HSJIj|;-N&6WEn;!3cY5FV7^^y z$3%3`K3kXkDK6PvZkgvO=^Ab3dS>QnNv}XR<{Mirc}G61hSM~3nVzKtrHtTeE$zT& z^R;fCe7yp$PLV$5C=5IXC0G6%=h-P;_a{?44gr{JR)M?%z*RE^k0=n82gBa#;m&cc zP)jz=_9kXJ&GVDo(k}3^8Y%kKqC1?Y97SPTT-iqvG6^yBwYSm72VkXHEQ20}0b@3y zG{nE5nMKP5I)Eu|w`R>V{7PO$1R!x+OjyMv4$O37MbfG3VS_%)$o9eAs1n071~QWl z4nh+LzjurZsyYEAOx(_)&TN}F`2Wv6pTl$lOPqcbkH0e{z4=PV63RR>Pd*TeiU(mD zTDf&z<2nziizP1UXs%jl#_0gz>#kV*t#G+?X;IV@=?eO5_(Tuh6W1%nRcLXkmz<&I z9CbsuAriyju>(MlVZ)ix1l>L7&ozTTjKpx|GR;%JY^5)QaO{I2m8Xq5aV4H{iV@1V z#FB|X*@Rj_1`YU4P%P*$*T|DmB&DktBuf!nGEafCdbPkfj#eR>Aa3xGHzzmt&a1D6 znJnXS$b`L1kUt$4q${74C7UFH)o2<~29Jp1aZS6QZxFiOQKXreEAoqXo;$Stk#mHl zWbb&0m-#s>lh7&U4Tb>xsnDoA9!ZXeQel2J(il2j#h@ff*szvb=@wd*j%93z?s3u; zV5`NI^8jA<3+b-&tsm>0})pZ*XL+9?7J0E+~Gv{vC2GfbC6!8tl z0810MW*m{CK5-pVfUd-K>;-HDd=6|( zTtH`_4{?DxfGvP*eqZ8(`T_lbZ-Fg|3yuK#1MdP`5oehQY)xE<2G|DJ7uXia=Iuxn z))r_dZsSYfB;uw`0!{&L1I_^61fC~uQW)?iaXXq4iM5D4p2*liDdRd13ArLWWsJ-Y z^uqiDfz63KwqM2vJg_}+cUJ-T5O=WvkrI0fTSlac1fBt|A+A5>ajrsKOii#8>y@7+ z<7y`vH^2O@1f(+7h@EpQ{0riQ95pLO!p8s3~Zv(uJrQoFF4-13n4-QZ<~Ei$eiL&888;uC{NF&sRq6f5Iy8M*Z% zNHKOKaqByfVrp@slX)cMb1Hz4!^ZKXm|ljsO)W^VI3DzklaS9nnG{RT6E!R(A*T(M zkQZu`V(B8H%F9TxVhrBjO^TH@FmE4HY{L2*dy--^_PNSYLhf!u33+!P;0^Hc11U}^ zApahuIPFMOwVsUoW|86?K`zOp_+u<_E#Ju)|4_z0o-z(-M~X|(iycKs@s!CL>oZ(C zMnbN@Y#EDGk#X0233>N*qQLHVh?dA=8!mg4e^RcGK&33oPL04{V)l+)5A%e4ZS_Hg~Ykg$FtbiJdvn2_RVm^ zGZ~LBBXRL$Jby#t3cPo2wuF4`5+tsUCp!O?#I@k-g~lXq+eB1Okg>~dn74(f-XR$` z=9lsKH4>AtFEM8-V*ca%pzm=co`M}L0G}CNj3mtp=wlZr(jCNpdgP&O{U#9iD1ow_ z%|(3n8kD^gK0o|QIVQX!PCuD)UcFD8M@h<^*n;>KPbg0#JJDD_%3J9<31_{iU{Nbk zi~%5?y#rrI?j2V~rNl}eB9MbxQ3a1G`kBq68yDk0BDQ0eLH`whSY z@C&tMT-{Q}UCpU9ljk30B;*RfUE(wEf%zc^@?0w+r^WY7F8pjNeF$`RdQFut!(Y`3 zrfTEh*H*5lYOBDnxt*wH4bZ#hCe_NZn)skCRA&e5`s_8TeM%w;J@cn3As&2sY%r-@K-Zs>{3?7HBmBd^pKD%5GrHg z#xllqlX3P985fL{adSNhc~2K=5)=r#T0l*i7#24nvUH_H0mWa9S^?m z3!!GZh4BA2YSs?=yzK}z8;t$9B+A&O6E&L=2!EHIys8X=-HMJ-`~Via*R%9CI9PQ8;fA0b;W22J)}hiTF^C{MYm$TDgP#Zy;`;y+o}lVBW~X zGWM%Rtq?+~#sX?J418$ynOcon1b+vlyZ*>`ac*=OPBels6{;WJjZ4T8S?o@tib0nE)-3kf$a>J?3u^I4l zEvXIYbnH|Q?452*yd*PS{j!N-Azs6$8Sw^Lgg zZmZ6w?XqiBC`5(asZ zy+~c6m}=BV0r`{`sE;e;mirnF47x$WLK6-8a)7uOqiFDfBgBokLPO%lA?|uf$Tw(C zLmxw*nvbF3=hq?bm8Q`l*@W@MiXD74K1CGb?aB76`^N|e$PcKXKy1aF`L#l-bmcxbF`^U3JJ=Gv}Lvf z3F-&5W&cPb==yf%|1FznXB#_F!c|Hd=uXtLw~Q;x(Sdx>o6D!@ps$sL!5`_!Cir*w zBMIN^l<~7cLN5D48S8J7(Q}lHWAe*5t_dA07)yMCp1|`&tz2ZhqoUKg2E;kepwlg@ z5Z}88ohx;cDEn->Q6hna?f2%vd(qRZ3y%>unOmP(t^(=Irn03fkQd> za}|iLHRZgfL2q2EbAAV)SKDfG0lxK!b`9bzZxC0m6y+@Mfbm7S5Fg~^)sJ(bW;fzX z*tv+|!-<>lg^Nh6NR&TZLhh-Vv-u8(e>uq6_C*t4X$BYNkwX0Jj$G6t$YskYF4hV3 zPjKeqj;|+*-5_IJ7p})<*k6%5Tu=CPZhRB2PjBdD=QZ5G_2IGN51AJuJQIGG=ylFGxtyh`^Yto zd-&2qe9L6+>7`sG1Rms`uTLg=d4~Hd{x=fboVdRZcOpJX#l6}-1a(by?saT5(U&gV z8$0MMnXS;x*U$kuYI6uWJjs@}B2)@9yCHReZKv#WBv2F9g5Bzi!AE z4K0a0ax-5nVm0<%gLia1PTbDFc&9eOL?edqB?~z~KLoz)o`pm=YxCvmcw>Jx_;Squ zjF03iTq;gn@i}~zZ2gF?G~jESlR?*BzIFoQ!0&VTIt5dRKWF0W&H`PNUHE#_DiT*E zkgvA`d~bM-ukQhR_C)dZTRkV?kdbdtGzEUE7VkChF7ag(dGBsa9`ktr-QlQz7Vxd# zgRXWKzT@@B@SolJE`R1GvivR~*K{f0b&8$%Vh{O3^FaJqG-luI0y7_#64aF@9VG^uPBTe!SyZ;#=M4 zCl`a>wD;quDUc6VUCmEF2>J#r;%5wGpCe@4cZgr01b>4+@(Y>Yc;~_|?4Lx!*y8-6 z%8A79zr-(E55E6>i(jmSAE3c9=3T}wXZhNy9TIZ+JtX8ka`G!T`VntB&2Q{95Ao_8 zzi}|)YyYqOX5nLYUJ@A15UNq%QP z7veh(;FAVzB%bc`NwYr_clr~*yGRmoi;GCeS8T%X_PCGFp%U^HNAP>_KDT(8gnY%r zd~)vu;>BkCp*o1CE?4-Y)e-+HU*b;ygOcZDA*F?pXfbLXNlx$^3%}H%Q2>;-3z(5@$WdKlcY8 zeTwqWQ^423ZTVLpCXmqWF8_KE^fN>$A(uN;M)yrJHZ#dMwxEo#i?^2|i7QZvfBV7< z^@dtP-u*KF&SNssr5Q5ba~5c>75Pa6LD2(wk$W}?xrI@J;!X+)HChSEPSD%>CPDog zacaung62eH;%vhOeFEgXmlLvGf&S$9UC4grHgTTRKxnExC^+;WRh^c4JwZi?Wv74vmICzQP4fI4u7P^z2-_(&)< zD}e;zuuwV?eV#hEgwpew9v2tNc!QtMHVIV=;(O1WLM=7yuh>DM-muEVJr5Haj0WF> z#|a)mGl`%0S@2wUANlJQp>YfF^=mevX+QA!%yOam3e4LgkI?RI2I8Z<&O%o;@}?sZLgX1M384dp?nNN)$Ay9Lw>|-a{bnq2H`WNT&YRFTau9lpbxHWW zgV48I0C9JE3VrvTN1c&R7`O}Z@m#nt+_x_Aqt^)|ZVANsKNQBE!#>-s62?7qAi=k{ zFn)uPg#6otX&=rIU9Bf9h)*IiO%N7LO@W-I3d?SuB~CX;SiT196t6CCK`V5p>WdJiTD=Pg)>b-N7+Wg`DVa=pM*a~ zp9ycrW~&y)p8rJPH~Eew4qW zppUMQ-w=gR(1G}ks}w3XD+v*`6{j2i5-hL0jwwN8+?LXo@t4dPEcQsm2a z3;Od|QLqv8WmJ7d;W`c^%o(U~YBU6N)KWODL7fuzQQ@LaAihnAqTC|LSdn^*0m^yi!PL zJ6qva2=+SPu4vrTkEo-!qDg+xRknws>8Je2$CoRb6}U{?<|u_1r4V0djl%bW3kgoW z6u$Q{ujPuOjfW%RQ&B}*FXUO5KFWA+q@vT_BoYcmD}s}o5?^_OB4p_e5(Pc{K4spm>A?wMGGln=7G+z!-^i_ z4dND7Rt(qy{k_~tF`_57$FvRo$;VgeMSD>@Lr;i_WHaKt?~r6Qr2BXLta6$#!$ zkYAQjBwS^6a=c<(0OF&aS4^nY68)n7im4mDiEcY8rtav7dhVEne9kJ0X~z!`*XM#_ zdgGnwpDvcs{j!W69x|?}At5(xnv8d|%Xn|8guL5&#SCY}f&FU5Y}EgJ&S1q{0se9S zIAB}gDInr{vIz)%OKuJvN!&j6{R|-cei`0l-){r5?;qni`}`4z&x*#x9XJKVxMYSH zcL3ijFzx{R9^(#-1LFPUaf*4d?nKw;%J^8RSoHfz5*p`FEOu9*&vZ+%*tQ>eUIE35 zgm=VE9R_?4yrx)L2J&)=kdV{Pka4m_#;t8+yx&PeUg)k^xdQwQy`otApe}I}Pb)S) zhCXjjRBStnc~oP=L@ zQtT`2Lj1#WioT%=WIE!&c7x*BB)nhdy5e}1;zTtUC{AkNXP=E$ zoT|Pb^_5L=Cd3!@fUArLwka+&tV_bGIf_3@!O!f!skrpW0sX5Sikr_i5iPi>xaI#4 z`tw?GJD-v0m7n5vXM8{7t>XTP8mP0zDIR&Fzp*10h(5tC55?mtu$zPB6i=ofLcXt7 zJZ;er&yOqKt_&jbX{31fIX~)}^@Q9B6saJr_1e4+WG?&3Y1 zY3ve>J3GNoaH8qK6yl3^6tfk9UUcmv=A4*F!mfQ{&Xtfy(p53fJr<`ci3N5JLSE(| z7Py5z&HMV2-Q=;(F?b{!--jYj@^MkzWi zxk3E2IbzAf6^Y~LizQzq62D9@mR^PVx?UE`YzIc<5UWf_emvhSR=IzWxI>O&^$E$q zRbut!@W+R4inTgJ-}=oI>lIr-T+V)Cy}GgRb1JdkF8G~tn?%pp!KgR<#HL1XEW`()eaQBp2Lr9XdrrDfqZL~5}PlmOT6{6=)3zB^1mgbe-+S~xL#~E3H_?G-NlZ( z6G7iy89$X2Et3(~r%Vz<*LEWA_&l-OX84^G@nZZN_^-x^;s93Xg;fv-^{5BG_(B~0 zJM266FmX&3JL>)067nwX#4(-+pbrPdF*_5`Z)zltt2vPP!nMQ+C&BmXZN*9I`&fUG zIJLS4-%k^#XTL$hfkEQ*hK@uRi-^-_TTw4J5T~y|+?e!A#>AcCj7yM%tBW}E&?3|i zZNyn4rh|`HWIWSUoLzb$`dEEsyk`{WEOsXv_C}o79vKIDveww(tTndq4x460|^4Rmo#5K`J zh_figwKX~*|M()V9kCZ@QNiNcaWVM5slg z{yb5>X5#*xko)Dy;z2d!r-~2{=0!Z~V@a@wPcy`` zb9xa~J1d^OJOp;!OgvZeInK%g#Pj*XiF=|DFD$7?-2IW_rBQXz_u3}o@*d)qcF?2X zR^rw0zQ}8m#H+nV6K$O*UYmq7z=fN|Ya76~_rHlZwv_oziB0Yxd(cL zs$xpfMD$IgmBLieQ7D^II}3U~^RyDRlajKsHoq%jLnt*JWjcy51!83Q)S6aK_nIq4XG=Nc@wWO3zRS5{CII8z!N@a;d1Y;Xde7FJ9U3 zBN{Dx10b!$0&?dSwTn<0~nf4~!=6T6?9>nI%MPmMU8eeGWQqD}9f< zA#ZA{^g951Yx_Xia+8sSNhwNy{tZ#V&N8O>Nys@@Rr;f6O0P~U+a!Q55wXg)$vdD= zDrLLe*vH=umFt`TZp76_67uc^lpVX3f}Cn9JAPVC z{8CqCr@L0-n>SZ>_QCsCS}8k60pq(UEv5;GV}q38iO_@VUuAq8s_fPx33=H7Wn{hL z=x;4j+OB#N-)XY4=bg*={74yJ3+G!o1}b|i1)L|glkx6FW#8EGu&WQszNqiGMcrh) z+EYTlbPHwQ%}ddT{#!Xv1->66sodx}YpOwR-`XRYLrX1c2 zc;pY|@G-!iQY(zH;gobk1C z%WT+bH=}aPb@)?%ZyE15kdXUrlXC0Y1mdTRQEq=Y9{rP|%AMzvQE#Y}JKrrMaw??U zRn|(v#&*hG5gXBGDW}}iSr55%RPOnlLj2WW<-P#)7l!6n?k^2Hs5M7hMqe3eHZf)Ak=B;@kcm(f!z zqxVu7TRJF@mCucF-pb=uY7o8OraUti`Ov_R%Ci(sH1Ce`oC5owYgS$=jlAbCALSKq zKjOSAD(@aL5K31ND9E&TTbVHoFGEw<7el>A5KPaE>0H4byDW3-q zB(9vB^4%EN)0ipBlr;^|m#(2qxgADavq37Z2i|v`t5QteMV#13WvG}!LLC=XUhPHX z(@RwOYIP#MtB0ykz5FCB(W}fuVILpzsEQ^|!uk0oRf#uA#1E>aD!qIm(UTxmnKAA- zKg_Nw$MVY=?Nt?@79iTRPgQ9$^li04RkTF4jL&QrPhcSPRisB$lS3H9we zRl}pm`@)B+8sG9JevQAXNqPA5wgps8K0=P|_Ntl|yg*c|tg7i6@V&xHRf~SBiJuju z^6!IsZc|@Xt7_PfzLl!=Anbd8YgLDp=m*D@P<2=XdJ241bu0&c-{znSh(17Ef<|RQ zT`c5yuL>>YLj3L3s?fh72kmN=wL1Lzs|qS>Yv^~hk1EP(9`ce!s_ugmP@msX*$a(5tbw|CgQLRwsB(Csv)w=N9MEwI*>+i2d+<2kdsIrof&0DpR*_)}GYGc#d$iF|R zHieWXJ`bKdpK*Y6#JUkE(Zvkq6C4QhkU^Az>${`gjR;x6M;c z&AmzJa8AwTMjWqnSyNCh)>uGCfsJZYct7Ne z57gNwohGnpEz4x^fvZ=-c|iu|MkR`|EhMJn1ueGL0#ekM_i>v>azD;NSJa+?eac>_<-^1 zD&0JY8#zi{XYd`I=lM#=ttl(x*9Gc&c+Tl7$(Ze&x_%SX8Jj+;>%Tz#RQ841&E6RO zs%L7CkYwWCZ&Q13_rZOg4Qiib&q*-EsawP#uO(M?D@Wu5w*zIovtQlDUyJ&%j=J3# zyw_#0y32jo&+^>rfWCr1t7zs}o5Gi&GDu0>4za zj(U{;0F1k>9`!f~`B+=^XlEA^j;~dZUU?b!yGp62aL9ue+74gIUYe^AB|*!F!i_Y0egqvzL15VA#WHPQ82%{C(g#3At74)vMNQg8q(EZ@LkU zbH`Qc&1>(HaMf466?X^tyms~WY`DL7@s4`?{Z6>gP+h%ay#@R4q~7_|O5}Dxy=%;2 z)J@CPdjjEKd9`}quqvoKwy2XYL61(XR3CENiF5lM>cidp5nsQ(`iK(xyX%Ge=*BAO zTW^<;_ZXx;y7>a`V|`K|KLY>P@1gpH0DGKcQ=k0||LB@qeXf%R=TOzv=Mo)=Ke9`G z<@^xho9NV6C;vuV&pPVsES@(`P~R-!O+r_b`pz}T&wH5qu4@8uwYI8Xc!DoY%1X!; zG^tmO7-igBZz-D)Nf1IC1HL?^}EX6M7FQ$PfpN_wNdIXAE9?u-^jRsxcYBb z)JK&nY83ZCZ)iu2*cbB8ds3tBZXvo`T%)RrZ19tgHLri$|Jn-Ifszt*D6z z06h+`H4z~%VV_4e5wCfou8lOdA>D}2u}Ncp=1pAP4Vu{7CrKFhQq!}$1Nz=oHGOPJ zB$R8d>5sU=_d25))Cc=0d0aDs17FV6(u_ECg9QGiX5?Pz^|(HoQCpgzPdiRCdI`o| z>#G@KN1aq_i;M?9XvX}3ef;%Ulb`|J9Y1Iip21HAoYqX)fzRE7G*cfBf?e&@Odo}L z{pxC_zs0;SM9qwn;8)6E%}md_#K$$)%={Dls#8sqxb`{meRZ0-i*68YTcMdB0r@XE zsF}YZ8TsQ{3Ay40HH(J~!8yrJ%@XD(owS;z4Y0rSL7HV}N8+5Ngl5Hk*zGJI&B`@H ziQBtRv#RcEoO2sBs|IaCo$IAp(`_*P&?U|K=NRXjq}i}D5$7BCHCrD*Z$H0~kjwQ_ zv)#%QXA0Hqcnv=8ZLisR8*&`=w`S)<^v|-D(j?Wu{`(cu>}iGkv`%-;-a&{jMIUJn z#umeUmi(F{xXa7uE~7cx7WbT2yJ*g|#ru`+Xs$JVh(45AbDb^_uNtnoT|WVR?-rV8 zW1#0Xr)r*iB;)?VX3g`6e#CF`(7bfSdA2fE^P1_Ay_Dviel_a&P|f=t=o1_?X+Gva z-zk2T=5smlZ|Zx^XE!D2Zms3&VBWUATE(O8=tmsTD)sKf4e6v+enI}&VyITtcO&X@ zcdhyh@`WSiv>Mw+)aU)R+GNnNsFgPFu9L)%S*y*LY$SoZsx_~~e9O*gi*E)$s`k^C z+=P5BGD=&j+K99Av#=_4k>uPJW zdewGTTPNQ=_`&Ad28SLK*ZrWj!7D57>Q2#mz8#Iev(VMFl{4EZsI;x&^GpT zA)$h!w#i8Fw^Dv>(~1h>YaG)0UR{kkzmwMYi3jqi>)Mv_$SYbE(Y8$K1b;tX>)#dn zpgX4RI05^0>7ec81pXch(so%V620-0kQ-fF#sr%-PyxSb*sTrRjr}jTXoH+VU$4&E zpe-J#`@*%sr%#|C;;gmIMqjhqL>ZGmYb}c{#QpwAYgyVG@;;yqNvMGH?=9MpFQw2w zZm$ik;!j-cIBn>2(CJfL8)i%)VMGsYx4F1~Qn!XS+PxT&dn2vAHuCtTY zzv8@%U#n^3vQI|8bWlyPE5?c5O9+0NqHxm{lp_e`h# zy(#Lk9W%7^kHYU4Kcrny)JXjB&f3M&^C#M+O^`303)e31Uz{jlmW150)!LPgQABOF zYgd*TihG_lWZW5~T~lWt2}>tv*B-w>)ONIX{qQ8>!{fB;9~4I%EU4Y)U74t48|}_9 zcEsC?+FjOYoMUUWyKMV_jkLSFD2Sep(eCpLM!%?^cHcqBBPE+Q*?1TCuD5BEqd;fw zUE1Vcz&xY02Xi(+-jQ2-C=Pr+_epzrO$p=^3ECrek@$K~v`3C(-RaM?MUwy_WZ46oIjqC@j*51^?r8L z|5vm(s#ZrHt=HbDTNm+nk@nss)SI78+6Qsaf1hUBM>}g0b!w`85~3lhI9bM|cG@>w z5(zhd)4s1f7IkVJ?R(rq;-6L5emIJ}=0aKRhtCNl)Gn|6cn{+oYij=_9IkVF?T`I#(|MeS-q!l8YkU)V@^4|fW)l{{ukP11d*=W? zUXze_YoPNA>Oi!Cbj|ta#6Ntf^Kk*a5pFu)3(rwE<#TjCU!!yDdK}_FM^9bP z+sIcZ2k7GGMdMxv>3V0gl5je|u5XJ)#9e-)>(>nO8rWJl_zmRl?4uhpC>QZn9_U6t z0Dlr(bz>S~|K-2RxGR@#>@_{?Bt)0+_bv3#*6PL^uwK$}-T2dt?{#$(iX*St(_1&u zr9S$~3A#xWQ%EQpt(%lG5&5Q8H%%Xods?KMd8{^3(@VNp*@i;T59;P$EQob`>lU#2 z8#b4a(;ktK7Z&Oke9`0kinx|LrXi3=N{TXVSy^y$2e`%39H763i%lXP2@ zkb|+fZu>*{^~!a0yK%pXYm!~JuiJUzIcMGebHlODaowRDN6>%ztUK%ldy8MJJA5c7 zkw*{RQSZ8_C${R2l|$cTV{6^oJgcSp?lgA z>mAeTUPyc?p?f_SaW*heLT*Kfj420oZ_A?(f9$dD-DKo3C64Oe=fiwn{<`-}ue~*T zD$e}RCOyC8F>(HpdVYC7oHJF@i@i`^mkiabv_sIh^pNq<3cYF=##b7kSC45-bZW9* z{UJZ@ffm;5Ykc8N7zN6-Xy}`ye_IYJ@O_Yx{yA{JM=}4SJvlrh2B(Hsm}#H z5}Fp&=NcM=I^I{Gd)Y?hhhh3WJsY8KFioFlF!IZ6@p^}1&r#R6(VJHz@8UM;i$=k& z>^JqrcbniJ>**b<1_HP0U5vQT|b9X|%VbnKR1-=bG zu6G~M689n|>pjm~@q2<{`i2wXPm0Iu8$UUQ^OVo}CUsLtD78)R6?liZvlI0`=vz^? z4SL^J3HTjCaS8eQzX6d4MW^U}cUy5^VT|6-WiD~|&guOc!v9o0q4(P}7X6D?`j(@x z?wynRw)b=6_W*D8Z6CfxA4RWkKV=s28h?EU0{<>n*IU*>4y8Bg!;p{AsnYtc)oesN z7U(0Lr{H%IvHGZa`{A#7eay0E=#vfB$G$*(+&N7jH}DPe^zQm$Ghr8VZ|ldLL7nh< zgg)UB;*0MH{rFv=H@LinT#h0#HdM&yJ5WF2r4jeJCh8~7f?U4r(@%N?KONFjLay0u z{bcSM{83K*!g0_pc$~!_4;Y$Tu4ajp`Tp_eYoOE8B4qBXMgcS-RZ5LQxfs9 zjGKP$l9s4L-sqS4b|U@{PyMoyD&o~8^egwmzXp$&@ohB;xg4KmY@m^`@i-aBOqFrm zLH(+1(}>i|^=pU04)2uJugg)FgeI-@o6b0(U-eqQ`JoH(-Dl~y1}IRU*!A0e6zJE~ z((lm5quyMl-?0vQ9r;1OQ%E6-ETm7e;Qj5<`lO!Q@YBL~`h8d2h&OfCCzo)*`O`=J zfv=ED)NcKu%aGI1ME&7QDxv~=^+&?++}2coBqrb-%)#LSN2Vs0iXZ^X2=TM(**I$~KLc(uD^*85Z{pUN$*MItm_}~_={~Pxx zh1u2gU%yy!e?OOjcGp0?5pLkK+tKfNVi5QM;{IG|5DFWK-+a&@40R!)#8QJ|$OWAH zPcVoz1L4Oe8btr@BuwmO5N{2@z2GE+YJ^DK%MJ$ZQRH_WN*Qz^gK&?rqKvak81#9I zlQ4RnA;eA(gd}W&2LdbKLi3SJlUJ^XV8h$JOoP-lWhTrO- zZ#ihK!Epxm8-31Dg2R4_^ffp)#`{+v8l2yGqtE}hp>*BtM4d|;N_R^nVP0uN`Ln3A zz4{oc=B$k0&D1f}I+8>@f5qT-8T0JiYw!%sPF(qFhNc&hZ&V~hv!K-^oZ<~W_D$$( z^p}wLoNw@ZS_XO71w+dnkW<-5hAvHw;0GCka9&S|RSd!S4Uy1kgdyY+ZgFm&}kiF>M-3|*PL%-aoJ&%tj* z4L5Xah<(n!Xo$Frd~8O5A+iSifBv?>dl(;Mur7qY1m-lvl;}soe$fz17_^y3XZ*!v4t%6Mg;gnX$%h8}$v;`vh< zuY8q|FSXAQpKK*Q-(^Fe_N#F}sDNR>7zYx{oH7hp&EY&@v0)%P*Sa*^F!(V1<>ePL z-uufi`)+PENFXjxJ#r2TeEJIRHZ}{I*hU8+%n@*Yy zhtB$=zUpK+vKI2_-qvv9FHf9PtutKxmlvQxgxwvCH$1(7I(wD3;jdW^#J>qKys%dxuE0?V zdCx9}7fbPc=LW+o+#3`8^BdmQOCbK5v*Fzu=uP4*!-v92#1*O|A>S~s;X}!Vh%+w? zA8<~=9eiN;gzu?Yq>)=z9QOFmsN_L+_3TDvEzG-Qno-#Uav8e7sIMPDLdR#uY;)kZ zTMswp8h#aeQBp?tp2pk@9}_vhG3LQ@O0I9rS2czBPuGq4YBMw$^ACq!^?Pb87|O=K zF&4Q3zR#a)G|z`TZjUz>4R}s8IK)_L_zEKbd=m0*eU0S~c@VXlEFtG~%UHREoydH} zSm)0M`29plV`C4DKYh>Gc%%#Q_jel`AMZ@`L}6^Y1?SLrZy3GRiQvmhWAo;)dt)A> zAAbKp`PIfYzVKt3m}gI=F&3_p7T`v^8#;~NqmvdxWu65WX~4mQ>$exKbqG#~V6S6^eo z4ba!Ev2lEzlf*xMV4SoZex+)JacW<05{~UL&e;Ww?`vF8xfAg*R^!qV*vB>>XZyrpr+YS>Bp zlE$4msvy5wVcd0S8uGan#-v9H=)-h3?!H+Q`Cd8W9@Jfe)?hqTz#ZqkobgZt=#^iR z@#q8GJJCiMPbx&jIlb|$1Ngn@lJO7p{e>2{jeqRFLzE}VcufcXjBjqd77f3r%W1qm zHHEnFCdL;z77&iv$Hyk!Gvo!88_T%oktut_ zB%BZ4GUbYJM;~dgDYq5-?B2(edpY=ceYUCafx|feoMI}1{qdcz1pS3GrV+*M=$CIdjqZ*2LMocZZ+(M&f0JoS7t|45=9p$9ZxvkZrrCGe67T9~ zn)4(9ab}-sUi&xb`yDgQe_xk`YWYozlC}_Eu8L_%Nz~2x!c5DpH*l}$jA_M*1-Qrc z!n8UUl`OKp-+n(n+5h#M) zpGS9sTjK&E!h_BJzRj|jCJ#AM z1q`xcqB!b`DMB%wC4IQsHP9AoH#=5fV{>`Ax^;H-@oCoB&9!CY=H8vXJiPr=>5->l zyNJdlU9qFbpf6)0Rip4=%RkQJOkUuHm4Z`giImuC#;2dntCQw!ZV$6W$NYMag{T4M zxs913=o$9M1ZJadVAT>%Nw%% zX02IMQj#3h67)r5WI!sdF&SgsY>|<%*6^SJd$`T|<5(j#!C0nL-I&nQ$B7LCB4w6j zUQ12wus7>B3MhKT#)Jp`II|hH91cpL_1IM;{>zLKG)fZ9M4z|K9v+gqMM(^q*VIxg z%*0gpb;kZ$LG5intjZawHaKa=dJ$At8W#h;^a5vO1!c-<#wTYyD~Wdl@fI_&+Eh;Z zn>~rf-*qud0O(|rVB@>dJN%cKU>QmH7W~cBAOKIzFiRW8F;~MJMU?bj2;ODhD+2Ga zF>&~oal?$c!m&S_WR5m`%hZUCV>-aJfX&F9R*0m#@%TFu&u!9kHVb=~Ny~~i7>8q1 z*J0neNR*^=Ae~=hYKPe)BkKC~2)74?gUvqftDcHq&XliAUq-(zvA=O zOni0)eOYO|8E<`WBh2~Pz!9eZ@C5iIk7agZl{B8sWT)4XHm2DVv*FCPm=-LU=11cn z3o$>Rwq8a2CEMiB_}WS4Ys-IDV{@?05@WX7?B*V}=x#2OR(l3SL@+~;^d8p0biN|f z`G3W|+W+WV%v3`1EG0nGcRnQDDhv2p;w;e+EwerBA=Ug!I94d}OB?y{OW(@4cqP@> z*tzbINjUrklNCz=f+SsL@h1}huqewsH1jD95ijkM9GJ&pGGV?f0{$gb8fnJ2%sMQ1 z%48RZzg$R*w|@L5bGnhHS!tFOhxsIbj#+MFEgM!yi_LO0l>f^#iml3a$=1ur1N*fO zh_*s}HO*~pu@J8$+!%``lCd!?AkHFrx4;18iVgiF=fnI~L~LldHO7p8?U24D*hOnj z{~rQ(syAeI701GhIVLtL$_Du`-xp}HSk1xVG0gOWnRE)Id9a4Ece6y-tl0p9v{-|g zBjd9D4?<$jhPnPw$-J0Jq=}+DSY3h2Q`t-+iNWVku+Ii|W)|?j7nL{MTNuQ^@?93D z(nQ0;Nd%sB14c<|!%`_GCT9FuB`v=c-8Z@5kbfn-DDW~M)M5@zV{dtv3gyeD%CKyx z%@&-sApLCclCu0lECF@|A_Oj`5t$??WuX5cLYhsDzz&%;z3>;aA~}tUFS%$$Z%8nV414wxxi}Las&UnV2+mW>} z`*x)A>0YFZt2x@zJvN+0+#p-9C5VOO$Z%wg)=(G8KCBje1;a>He91OKY!MN*9?Szu zW1M43vNu>JAct&(al6H8uW5EH&$Qhk3vKtZ1cwJS5A13Ql0rA6w2+XQb#}?IXvqU(*<4nzBN}h_!as~*?3v8AADvcNtdizvkZ@sS zFR(Tk!g(jTIp*3z@kTTP6w_yBb1c1*le2X3a1AgIV>tV7+4S`oErD6s=Z|*D(m`3g z%;nnP=2!yA626S8sE1pCm4zkvBeLopYQEV>gbn4<|G1Gp(nit(+_!*aL9#mq9K)YJl=As_;|cyK(NfjKtj-*f!e zs_^eg&DeCI?>7BEDT32a`!%e5O4HShMRTR~ZDfTr+vB7DJr62piU+SDlnf7D7Q*=i zakHl}2$#%VMP)K}CokD2r#k5{OGFfsl9-_A@F=@E0PY%Iz-s^3CSWBWD0W72ma&!Z z6E&%0ByH|Ok6es?A8uTHq%U}|Rs%54polQLaenDX-Sl*-9G=-bHl!^%45k)%ML z?gosmspeqm3I0pnhacuB02_~$JfKYyIV<0#CdfD4AH7t^n&m>4xz`_N>5$1&eA^IU zUNbH4l2>5SA`0waj?4;m$|$rl;$&KpB}Kz@ddkZCK;bQ?KtZ<1D4P|5JO%C{^%sV>L_iOJ$iHWKJ$wC_#FVK6myE4}o;V ziaaCBsk4zgdb3{G?)RJ1xchqjVowej$nvUhLl|?p-%n$3mqJzaFQzIWH5-|RWhUv{ zqDAi>9+OJPPgrl3SfAnLS+M;ncllv9lOV;ES8(~N55&aeEOdv~Yt3oO) ziFgg(F^Mo0VVhzFbSzU?e7cQA!tn;P)$bQ6=xwpH#se(yn`Z1U7IaB<72htJ;R3$x zPD$x?I%jgGEfi}_ZxdxnQ7#x`Ml<01{i?lfzt~)XbVL3jy-MGR1}$B5|6;9DrTl|z zGB4jv^7Oqj50-M2EcagMoAtkK9!Ra!^hpeC2dVY@PmIk;;xcpPkq{h<*US;Kl$E6p ztQ`1mN;r43Ed&W`q%B(N!~Z~7KD6RLVFEehkA^#ADu~Q4eP8P4==g-7^2(C7^4Jn< zd3=JF#bJ3Xw!~`ipC+{F^BR2u>|s(`{d2beFCjL&k0n~FC2i<_{5;GSM>4|fwWriX zU`~b=0IZ&sQ&;IAE`75(e4=eVy*N zu_FDSxBYLjl)M?uQXD^`<(^s>WVv@XAxkiSrOq0EYw$1h*_j%{BQg_Xr-inxrK&RKwre&1&mmm9@g`>{y{>mYZ`*KNR{QCxaoUuaGgXbYNsorTXV8R}sEG z?bKL4+>y?GF{7M_X0GN~6o^h=BfE!mtjsDfCbHC%Ve>aBY0a9hfoNw11lgtDi4VFh zmS`zY&Acu<{JD*e1+)EsUN=YPbwiMZGoJmsg{w*$+6_ywdPP2Yx1&|UBIhp(hjgNI zHnRl;OKqfx@F=rf0sQ;b%Y5U^S&GfbWr@r8{WPgCAI2VQXOHj{|7GDl~&DY6GTh>J$B21#rTYa^PeJk`j8{*BgszrLJb$*X4O|F2io`vjn6@}J3d zmYB|Rak(!h7q-7*vChw8>Gq%3(MrCQ)esrUl;~K&+^82bkAj)~5Ic7D=pKtZEWJ`) zkb9Q8@hz9wK|tE6-9KsSue2oJk6ZahJIbfKcGgRg*Jm~<2M@MBV_;TJKBw&DaY_@# z`q=4SJ~Qd=F#+EzL_SnZ@?n24CYO)Ida?8+UFlUG)*nxP&}67t(<3AVg{dceI`K*P-zHcHQicD;}k*7JDbyE=fq{x@qi+fn(!lP~0 zNR(&+5z^^lptK~bu79>94s;}M;|yNLe6yfQUeF#6KjIu2^B-2Loayva%JL+CnI@MQ zoH|D1U->SJ9ON?y)wx@&a2)afjl!z`uqJCzhv1)2@NBFQ`+ik}dw56)uByOY{U^?5 zzD1ImR#pZwnwe&@c*#;6_L+Im@421F*Afx|MZpGQkaaQr{C~%E=C&BwR&0QoioAS- zZ-kv``3M|4M_~B||D(*);@HpV|B?FavabG5ggbvD`HYn_2>y}SwAKC>I$ct4jmZ}W zWvgP+WhTpz$@d#}r#lFPugw<8tXEp}$9&{xmMd2q?EaAKQPafuBUL78h5v=7ewmV5 z`DRgCYdp=vW|7!RCyi`Z83#bDwfqcGAQoI;-=x)FauiLA4@^qzv?X=!bRJdDoT$nz z_?oFFK&%s=xknj{6br?tRj$)A2aWH}9%1<3=I#HT#0;`Bh{}99A#*dpIcriRB7UgV ze!cY^lE%r#%cTBoP|!4!O;wHsnd6urxMQ)k#!UrQZb)I^|9$8zk||XC#YTq&1X;ch zpE;z4BfIMwnR+uMqejO4K)Wo!TxnCal5$r++@4L%JWflQ2Md*-BuB3c9?9IR$w;9#xvi+!hDPr7r)Pj%R>TX zks-_X_Snp6_xrvd$!-p&z02NWyJNvVqh@IBk9<+S0wJzXAi%RS| zYlNh(@|j|q50P(Huqs4uTSp>;kna6Tt7cp*VA5lehaKfGj(?k`<#UY;#N|UWJbF4`lzT}3{_lu~}F<}Q?85z8yWpr%TE95}R$J&;xlb@Ov zXAt5a6^uh|rYAq_Y?vfctz;4zeTFnK{Ls~v?qYa=QIc}QWWK$L!OSD`9PI9V#tjT6 zptQo0rR=P;DW73woXM7Utf2Ko(;}mN>5_W?A&NCM*?lb5)3Dl+DCqLYM%6g0g zsAtCOB=xJ=jTq*xnyjln%Q*^U25u@*Bht;OhcIu%ZB<@@75zTN>hJG*0} zbzvavN{@V@jQJ~;T`-$u-6!T#m^Wv!AQ~#e6pd}no_ha@{kozU6uBb)TTi+xD$SX` zfeN*|+v~cf-i%4VBGV&0CXD%DB;ZIcn2#vtSg}~W+U4-_&zO|?E@OtWJLAkcqpC5m z3xrH9W6aK_q`dk^%8NlrjNy#MjM~g|xn!Ep^zD2uKbtWhjF??fVkQ|V8CNV~@V7Vl zwXSx1ba)_wuynZn||5EeRUh8uv-Ud6*x<_GivahZnmg+cIDj5hU&QXNZd z<1p{Hw*Z)?%U9~zUNWf8?uM=+^upWH!|Z8`Kz@?-{8}6wv%P}Z=?bSnwD^gk<&qq3 zns&=ILt7U^{9M^R_P zO~gzLN#DHS9{v+jbA3OC*<|`S9mb)kwMB>jOucgaFurE`Xl>f)_?lUhu1?G9(}##s z-u<(;Q?)GpZ3Q#PtY6OajY?*?+>E{H*if?*3pzj9T!Bn8WE2nq^usKyEcnSRrNAHg zc!XuSOtQ?=eXqFEC4h9YjGp0$iRsMCn!tQ=Y{O(}F*x-n4e8V98(RZXe_Hf&E;WN^ zVdqzDS3l~UrWtO{{6gaj{6L)(=3^c!gGZWXHd{BdQ@Hgf98!W1+ zYr9V$s{JR!E|m2Ip#9t5pBXZy`Ki?w_~}d;zhl#XGtW>HT_V8KJak;=*# zc32T1l^yu;Q96y;np<(*FV!sL&9PBgvnt0gk`%?Sa+Du(8#1S_EwX{;tQRbkZZ1rj zSd!0*F?NeW(op1;>FV{3&(DqD4aUKtNzUHvCSOYaNhGV7z5?TueE*N#o|KO{55TOi)929m;+kezn>9kZYVe~oH`57lF?Ezwuu2737Bgw3nR-Nr|13V`L28>e zm<7btdNF+~YBm9@6@Nw#(+N5EWDbn+JOKV)%1xI6hzuCOLV=8G+|pU*PUvGOD>_hR>p(t2PS6@1z$Lq?R& z;m3a7=@b?ojDCw$kNkuZt&|=~=iTW$RrukQC2QtolXjL>+O6Kf)6bKYQd!Q;Y%}g(%=>fSob{erYf<9WznJ^yOk_Xx zjRL*Q(wV-nkd-dtbm~=p?01R*Kgm&RrnccCkw~-bl-=rLZBBMP%D9;JLyzx6Gk!Lh zzCy15L*2VH*L7uSVki+Wf-exFD2k$(Cz&D$F-eL9AEH<+W#U1IOc5kNfTAk9x~ndL z3*d?u_ag6uB_$gur= zYn}Z#=j?s%1x2acnIVY;&faV7wbx#Iz4yxA4ywwen5)P2Jl!Wa!>2x&V;-2ehO^Ko zgm#>C*c!LE2@h&1CC6Zkr%qx^nZZ@4Kw)M+>50QXIFV+Djy!1vc zORf`;ECprD0zN_)oxMrJ$RCy&(oM1>M>%pcs(XGcgY-g=vYVak5GQLZV}+6UwYYNf zjOiTNYU-G)f(%U;4UgR&)bIJ4%|~9wt(ro1{bMTr4=!JSh-N-{Yl$~yy8}~>ylm26k81T;LKWba4+DtYja$2$cJ$|R`st7+9 zh!XPgB;ZF-ZzVY2K*d&bcNet|xJ!9FkrpEM^YP{DX$~%u4kbBR7ShvYGQNBr1GZ4B z*!J9-<5))>7Y`L>mXE!*>mQogMaL5EB)q$DQG0`W!YYhlaD+M*n{8OXL4 z`=j&K%?dK6MfEAnGl~mGN?ovDQx$D!4*e#82U?94-xbOv$i zF%Y2os&j9nrVRv6VGKKxuxOYbYi_9M>2~b!9uuo=5@c}q-VhwG8)6RR zzb2@!McGiU(Ue`EPlw<-4UY}SABN`Y)rxRZ9u`T#t|(N9+0VqCg~7S*r09wHA?F7E zPpqD(smqA^w5qstu+rJ!)Z4LCmxk9dMAV}~QrnTok`nl$ACDPP>(r~W6-{XT*c+kV zTTQ2=Fd(xrbcLI8y3Tt${KO-K5QHN~1|gXh{eDdnWdS!bNc!Q(}5 zVn$p%%bxLfyOxWzE+K$eDYLVKr~}YxCip{bw_B%IkOw`E+~1}Kb=HVbCw3kY73#c% zF9Ag&;~@tNm53T~rD93#AiB!Q&0I83MHgSnB8Ddehnd8V8a)5@mBNS(*Qj_-YM_5w4i!XY^%fmW>o;yJZzC;rxxL%k`Ee zyIs8mO&!zg7Bzrn3k&4}LmR@MYZ9ui!K=)+)SO)EqKK@51EECSNY8@pUeRc_cGS3{ zAo3Ajf*Y4xwI}^a1$m3*_U zkwxI0YE{tmR-4Vb5zD6rrZA+KlkWmq2dBE4f-ga=Bg@yHw(6?)G*zR}`B;Za!Q^V_=TO%9C#vghUtdq-909VlJhJ?a1bi+4!TpjYZ*Az(ox$d! zR#>oI+@JTeINEbuQv=>qV}8V!^R2fW*U4tT%i-BJ9t_=Os${h1N+~===s$FZaJ%sE+#- zfUF-dJozT4PONP!(#{q41gUR@)XKo=XEM+tR-DgJ7@2e_3Zu){pVeMhTGFa%fGImP z8Oi-r-?Qm2Ba;ZXB5#DkCOeLaFL{%9Xwulc*>7npewFIIevh9o?21PwAHj}IBo8G! zb^`e=bntt&rWbzjq7Z1V&`zV3r?QZSkhYd0gUOo}979Xa*U-&<@)Cy}$go4PH-6P?aYM0F`Y z&6vzGY3!2lM69uA1^Z5FmWms}VlsqqcU!!8$CpieS@>>TC*=w7z;lq@L|}cRW^@K+ zEH7-f6J3#M_g10BY&!H0(C8@#)I-2Cs?HFj6mN-yVEBI%JM2tWUu*h>0i`A~^!Ke+ zW#1>fn)|n9(tfusQ!!gXCbaS}Q!5gKxgLj^9$N(A-4s zrr-VW6R!o+rF*Zc>)j5IdBO&crYBoFSw^ek=}RhR{AG?TUVm;rc=Icg`E z3efz67<+V7(9NO_lK8NQXFD8@PH%?N1a59g;q6I!OL#1Ol@v zdF_aw&VD|;+T7aGd*I-5=KCu}AXttIiOrbIxx&^0cweR&fCoZiAh8`||#s z1P?PkfUHBihUq7ohOMarf57xCPtAHn-A~y|4o_QR&y6 zgvpzk(=Pr9^c1v;hIchS%V~^X3FBtxIXao5Q#R3IO!QmH(b@1=Z)EaIx)akxv-}ds z@n2&M6OfSvV*yG4ATovss~?gnBfN{*0Fuh5KYpdsiHx7X_ysF`Sgzua`?^w(j5`Z* zPlDi^vYm8>Q%2CsM`P5@acpL?zPnvXpn%{ej?G3z_A6lV+#5MOTc7Njti?R3P7M5K z3=tnMz;WOGjJ~1!-O1QU?aEGmqh#d~sQ~#jxyO^tjxZlG=^jmuJO4L@7_F7F(oHwIToTl63Jl6w%zV4f|Y&vT-b|Rm}_R zNpDgzpi|mPCbylDWp+|JJozm<`KIt09d_Hmm62U_&$0`ordEZ#$H%ym%?=VhUCV+n zB<%=7+NcA@G$2uUbhhl}s5H*GpI6b+u$@$QcC|--c=FqJ8S0QnoB~HqQw6oHrFyA& z)AOfHy`&A{w&VnXr9OJ-P|~(i6sa)4c@H3sF}E6m(DGrnVsM4SWqkoo5;&SW@fMfZ z6xx4c;qh&|WWiHy;B~?XOsEkHv>|)?WR0m8IBmqDX#?RkYI6(5`>7}~-v3-Ov3x^} z8p;+{%(@sV-CQv*8$5Yn!Jc_)SH=h&o_Ij3ltvqs^)N=c#nL?B+_Gn-$2T1 z$c^SYbwLVRmzfr#D)j?*^eJF9vg7h{(00TU;*>+GT}3Komq`nxeVE?#D5%udP^7=b zyf(LhZfI-YcVO0-yZ)lmsu_z|sE#-Z@(M(Y)ZCxE9cV0iE`xcTZaGQ>@U>mkhYng* zv~uK6bzrZsZGv4_4kF3SBdIl^JSEcH2U?ROCgYeX)9Tk2;(HF_W))8?AaKxX2VohX zNwM2=7-likiM;JN`9vOa15TvSBAFy++;c4Hyn-dX8ORUvAW;I+Y;C0Z!TIg{4d52d zdXO4|HzfbeMpIS@vBA%j9grH9+};N7wyL`oMCnR5co6kE_w49*W)?}HBg;&JU4@^? z=8o{Yr|!F@_;)Dba^F=XP8XaH9pKz|yRq-s=!^_F1No@|X`XWSf71j8Rgl!7M&ZT| z?5Z*$+-2uKJA-Joc4Ea%SV0@$wAoa$UPpgfuKA;7H2tVo=qq_qH6A@XOpf2S6{>Cr zh=pQCdBQ*G?Mw~8+{hFKEXcctf79gWO~<23y?{MTnYO~C#KP<6eCEmG{Ylyd8<`eB zpJkwp%c7335hYB1_;%1Op5Ci{iA#^a)#by@5#6!tj zeWO+UFJK3fa2FESv;rjI83Js9nEV;F6DObi4WkJ|CZQbjJ;1to>QbVtV*(1+fN#H- zKf4%8>RiA#?%Jm8;Y&F5!{srd=0sR^&nvP5ldp=5XuejmzKyu*x>5)oXz5vI6Kc2! zzwI{Uj)y}B^}figyOgXo@u=6%C5B#Ktb-5OWlv^ki}U2&3?J(+gnR#OWb1it{Q-!R zB=oFM*XBLxmP>6jykw3c*IENPuyiI8*1UyZx2zz`t|VA|?KSgm>PdA2&l*5|t0Yil z*nL!gRKBp*J{M+?R^>drG_m&IWHA}Mbt$>^l`rP&;9|4^fL_B)9H2^-fZZCR_t3eo z(eEPT<*EN+mikB^-yxP@#m#cW9+e{25TV8t8fpqev0n;)ltoB3zrp+_qE?R5-A((aTwqxa zFJ_2voMF6P#@BYrSNabnDTz}Jd+6}9*}0TROO8vBN_d57KN9M{>wA@PA+0M7ORKlJ(u^qPO7|s;HxbJy=y0HO z_5$PI`GlDo-dvd$Ix}P^_8~^7C%{}h?mFZZ=(zIYQj^c*!8T4Wn|iaki&FoNM4%Ex z!gQY=G|KsK?XBT$BpP>;i6LAaE9D%{lRa@pB1OF%-`8&)-|!jA?pv1j*L$wRyC8IX ze(FVqk4xF2uJv4$y$JhR(yNk_pGX1%jas@6sNfalIc1*~3aX34>Ev4BsxnMtvg%>c zFC4cSt%TlS>L5soQ(cwOem+65g=SlNpU+nDnoOW^bGevv3A3&jB74RsE&SEH$T-|ck=7EcCD;Lp z12h3~ec<@p37BVc5;;CM^ zZ-Z>jTr1|M@>)iY2mWo6+I==wYs7yqCAKnA{VY378wEsoHrZhpf3)Of0L#{uH{Z$Y_hT7@DsA0<)oaJ_!hJj>G)wKGj;Lo#2?zWJRPv3>?F{vnSjrhL) z`yiIOZw!nUNoVeCbBJv4M08{7ouNu8+A3wo(q+h8$*u^@knwkHXoZzIk>cBrFE8xr zC|e#?sqoTzi(|KlUzRVzaFBJ{#8)sI+@L?n#?U~g7dHDCPC-?-$IW1cni2YuBo@SC z9(@7FJyUDq3304egIFz~9+9<$52Ghc1%xW@j6|$~`SlfGNIHw>*_3)H{b;q&1ubS+bBQ#{Q$N<~F%l8l|ptleDaXFs9~R24j%mNZdgZRvmxVl>3-S z#$xS~{+w5WJT#Oba!W@$b9DA3;|v}imK&M%@sepm^=Q#pgxM(hh4HPJg-^B%cN5Q@ zx~lel{w$WK=ewG##0Sx&lF=a5kTK#z|m4QE%PM9{NC%b?!?hce>ZK-j6K9lp4|;ZGQ_zBH@R*Y2>v%!4A1vNiEYh{BZrmG(|2_Ji z(RY9>6vi>*$|)n10#x4layQ-o3<8vYNq0K~tb8e%hxQBn$vH92&-iAtX1!@GUI&gG zeyNde9&7H;4zeoEY}C#eD%8x}27X@iLLA?iHazS3r5Fw{cyd%Kd%z;MX^4B8kn zYvJKdp9P0{i6M7u8(+{9#Q$EoYgks2o#R{j`UjG;XlYQ|(Q;)3g@H;xfN5`fEZr%| zpGKGNg~1rptZnph-QA9^D6ea}oStk^;yH_tQQlLvvR@uuh@w!uYcGRDOo*c6+;@=q z>7XAQgxpQL*2Dvo>GtDo%`|);-{(jBK#6xiaSthy)pzHkW@+V6!!GRuv2UV?Y5g&K z2h+MCJH@Wa%c+?_b<@6VXrh9kBA%dj8wDycRYuqK|-2hf|$%)_2*OE|>1q z8VX3OP}TZd(YJ4TMcfI^7mV-8FH7;4MA1I6ufJvN^G&(_1Rg8$)WuT#*~z(2^#AQ! zN1qluty^04jJ@>7P*-{`NZuXkkE8zEx4tN2Q0OD8Mt=9Vv`ghnYjzod=x<^F?kz8j z$DWT$ZNXRZCQBhLPU8nFTSd80W8dIDx1jNs7m@Wh$8VMLlb-sQ`{SaweXZDj6{V_5 z`3|(v8l}%2c-z+sX|5TNnhxCWq3*FG=yZ+{QGYwK{g#=^JhK&Nr}Ev{$9?#=g=-BO z2`_hA1THsRy_hTmWpF-ggkCKbt~PbNfj0`ZF0)*r|Br8ZFW}0+4X92ab!??MhtOi^ zC*AK|GTmdjY2dVfvHW*$dBMh`pY60_3Nl;>#l_bf+%VQ#uV>C}w5QuLbGFEXbM zGQfeYwcr9Wrh7R`x1xKYo?LFYw&3RWYm^;yu=`+HAO%bhdV3cSX!Qd72qb1m8_ev9P})jVsR6UJjr^2dSxGEBM2Wol2qu#B4CK#Mgi*j?1rKtUxZnYP1yEHwyaP-~!N{J$Fbuk8x>;;mMzC3&YC-z%=N5%prFQQ1n1$S8MAoPgB} zX&_9bIURup^{lwl7%HO&R{X-T!zz4t{Leo!=N+Xn`Mes0L@IKj@<8^7DeLUAm_lWP zWbn%u9lk1>pwNlzfY`PadLN}vQnyI7x{b;Uyc%PQvHHV=kA`P4aa8CBgLk1a8plPh5d0j1}&iR!Yyg`{FLmiE0 zD6d?Y6qEe1&gOjaZl+D;KV+;U;oY_ix!^kOwC|uJ9C{6+*^ZQW4DmttV5Js2{j{H3X*b<0j!L91-LGk4Hw9oY)6+~d)uz^A?5 z^|X-~iM3C8h;U%hR;DP{?!kLcYcA^tw+_vjv|bs|v>A#UQ#H)S4BDxLVdp7iAMkBa zn`pzL3lZWb@~&xQ8qVBiDh_$d?%##9o^|DSbzCTQq>8c@z0DjVuatO7T6e~9zin~z zOSMU*d^z7baHo00atpMYvRHiN!NT*sH3aqGb|F42YUYI&gZ&UQY54|QSDCC<{z)}W z9#QUgf|a|+Z6fA?!$)eVC6p+Q=@Cm@cgj>j<6WrNc6r~)nR+A`Z2}s1g=)2nc>WNa z&TitJc9z26n%_54{}$(slBy#;hP4)o$Z?a5K0-50>tlIcXxfIhEKu((mvT<5sdM;K zSYy?6wXA02C#qfH^IrEfpX-j%U}(&s^Fg)s0^E15wsFp?t)%pOzU<=g#U>tG6jJ}~ zK3C=6AH2fyCa2!*;g$IgMN-T$@3q*P(u*gPQZD(#J(jg%#*E5T*;}A{5|RPN@&AgZ)9|N7SiJI5n8jOUh)o# zMmMUjs6CoC94uz&fx?{t3ar;YnZBd!EEJP|MaixQLDf56iY{?aYkhc#Dd(XsSZ=xL64KBWK?HQd zbBl6+-iMSPElG#2W}5|dy6=a^6KuNUwA z*@6ET|FfrXXqjE{cpd4Va=$*jQirzQx{qpFWzXPOhgNp0cywkFwX56uh zyYsb$I5>~QdjcF0&`o_4o$ml?wCnZ2uk5#npP@h-{WDj$YwceZ#`M$kaXba0%|cCc zH9k+n7Rp*v5Gox@%=pa6du|0&8P6N-YxXP<1S{m8rK}{RT?N{Oloe$CNC$13#7vb)iyi^ znufx{AdZUVLv1M=RU5(kHtXoyP1X&MJcYZMcP`Di3}W^SjN!bXKLOt(jZahZm{k}q zAJ?wIBGb3b{e2&Pu!Xl#N?@IpqiWuTr+qLfibFb?L;TTXlTOF7?$p}P7|d-yO)8Uo*QHwaO7HNT5 zY|zViO*Hi6LV_B$haqnF(=;SXD^uaSpqmL7A)ZSiDTkI9Q1>rec0US+?Y>x7?ErBx zBs6n=RpM}2`8eb$Q*O$~*;CN9MiKIDYsJPP(VmS%I_X1-u23JQQ1eflt~#%#mK*VX z!nFH~CE*9@-0GUZqXyj;j9NZ3lOy0o5RhJ6>LBLrAqr$VTfCGCEW|kl-=CM<9BrP* zIS~>t#pT}KT(lk9)#u75$ryg416vDy>F$@tkrwZh3ka`v(V-9*w>W~6wR$RKyqPxz zX?1@;7YRZQCh(fIz;pB>3sOsZZRjPqP{8YwnZ75fd%Qor81U6+Xe%Stxv1kqm>RvY z5P5HOV7llVwO#S)3##xL=u?{>zW;-STE+zHT-SL(HV32d{07P#$3(M}BqHkr;UQ<( zh6jlUm3^J?N*?~pw&k4VGQQATmHe)bhtT7|%nj;z{dK;=tGBqwq#{SFk>$CMD`QKj zXwgtqZByTHMGs5KNj9%9;d2t^B_j1(=s2KFgAU0-_4=OwgGUI*Z9fG8ve5DipTWW@ zQ)G{Ou31>VpXJ_=r~pvDcR1ep*>0wJ zGXB~E#VX$Be=g5rK#@=>h-3+E%vE3k#EY;K-~coy+Iv~q3p2u~gk2h*5FeUhA##uu zSqqDG(BA<&3Ye*Zivyq7eLMnvI^nTtCsP+CidrDiIqaheS1^p5o$5+vx?}!yS0WRB zu}_NH7!ibG$D{AhXV?apH;sRuQeu+!VLI}qiW;_3ycU)agR^NQx3K=Zl4-^$znT*~ z$M3EDxhFt~wJIjFrMoN^HAxXOFX zuWugZj<;a1nV62nO;y=d}C z%ci_h9NeoAj4=#=@e&1d8i_uxTdFx_-!VzFOG37gk5sie1nEsOZK)YmFM(KEm{9<)Dshf&FQ4U&veV>sQ+Yw81? zR@c0{_66Ud6|0yD-OPUzYdURSf939{YhT>m{bCjG=&84)g69A1YsMj$w3+>8^(B)o zwvmH@ULY-WKEtn@$u2wIcg5YrK54Dz+SWcy?{eWh>PzPE1V1DW5T0=|S{Y@`Az=i| zlH;ZXiwB$JiJ!QVNJAKxa`NQwuJ9buphfue(%408NJ$7IJY)ifA)S^y3%rMXhvk8p zhA3G_mKTs_is+4GR*M696bF+R!J4K1@Jy?+R$C{{1K%IUd#D8RdmK{tn8@f%3vGI8 zmDJN;fTCd*)*A58x-i$sY_+k4j$lz>3s{Y|f^|Y?XcpJ0Bn}7g8xvihUWk@m(cmmx zEm072AQh9Vkh^S0jLz+~;PQ-8VI1nSMy*+wo`E%A-H9zHKI$MxB_(K1AXGwGNf!!< z2!t)NWAoJ)EK$NMNs&b!9r#it97{dG8+PRAm(^x#E52=G7^g2BZrL$Id=xQ8{c#NF zicls`p$&{3Hu`1vTX{()f})NjXLYgRh~4-jTRYw7+p)#*rM}=47oD%N)2M7#BcYAE$H(1Rs$nL2~zp3n2PzocmDFEXr_>h~$yi}AySV$vZ z;Z2juMkPW9vhTK>VYir}ueMPb9~p2M16Xs<4o;3{!(SmH7(I={P+%(qO^efkhm~ez z`Z4*G{e0ZghaTc8il1~kh!{lRn={U3I`pu%wJrK&fLPS%5pTdhe4T>--Lc3WT&&b9 zd-x}P4yhnpIG8;VNo$%{{?Qm&+^aNjV@6gtiWt@f63{{$e01Tf7%dLtYm%D5Atx$^ zA0dBGQ@8>v8-t*rZUL95g)#CN&s(IGi@_m}K|88KjtE1Kx3;4M7#n!ZMU!?G#?a$d zZ7;@TqtL&lm!tdq2@)aKBUGA7Yg(z9VJ+zPs@)Kc^3L2PvbkfwiIv(8TBkBQAeq}n z4tmKkSs`!9a@1&yWYq*EwhxB%1B+?z!s3>{i>kB@ zG}~^n`D?E|r-&dX)briOjlp5jp}H647RE)GH`oCWT91|6mPyJ6k_*Nh^&EsJZF(aE zDoo$UU~j+*n%V>h5Yh~GkzL#W2!@g3FgtK;@+s4!`BYVK^id(4`n+M%+HoWIHa8Jm zG`4CM$Bzq3V}=Fuow-ypl<(a=#1-NlyU9K4SIkZ~20Mu=ihubGuT*d@!#H0mfG2Q9 z@bw8twaj!)jz#uc>SnS5SFWd4dt4-V(k@>~auB_8!2x`>D_0cjYAi;054@A@ZeT1*SVrfZFobt-@nbxciY(Ntpg zBys245R&hetk)6b6(hhAl7;E4`w$HcGie>DS*^~kqMS(udg=M~m6NU%m`#pR>b4=7 zIxJn~OLYyL^|YI<1NtPe3`f`=I|yXU5c(*9kRfY+gMTY{XgREAp=db;eVL{^6{B=~ z_??AVBvUq_Daru$)cnlDhaIb={?u-C9wUAGGqeeDs_Mrbcx z3ZTo(;h)@%edIoblO~CwUMMR-^bPQ^m~a$yGgFuG!)wRQ+n;2|S*7e4F zOy&+uYFIEEEp#DjQ*%W5*Y9SWVKAmY9^k9H%FD*%NH;(IAFl1bMwoluSK|+xXao@5 z_OqF^_rj602lxoP@}!b1FFoDc#MBF408t7GR;${C86e(2oj#J7M}LIUN5tJ>c~h9D zEX>kVayAr3z|!))A&#U01=kP4$$fnu+@Y)u^WOA?fADm-uk%e)e|6xA-OzWJSO5Cq z%wIl!y874i51!ncTYd2O5zp1J=2CF&=qfNphn z>rOmUrA2+=k_<-(2bX#19yB(aGWVO4G&j+WRCX8TfMdP5lsPJrAR}UqT102I5WEv? zKaP5^4He*=vqZN3>us#q_^(6LzEuK;08B<0cO4eR4o+%5O&;%qOGGTGY;2$?v~7D1 zg(iRVEey>@^)B0~UsX+Nvf(z^@6U7*KtUF&J{kZO>~~!xZ^}J1w0ytwqpIT`fFDsG z_n^Ej_1BwHQ>zQoAA+q+$(-<1s#NRc`S#{rOOK>)J4Cf2k>T`hogaR9qJ?e$2Zlvi#$9`c6g1sc^8|2Cco8Qt?=qt zT54s4WL)wZh5*1LO-Or&39(UqQPWO@9&}Z~?&E@4g|mUG9@n7z7153?tatCPt}e-u zMJ|1+r{s3(1s11MugK)Z9i!Gt7V!&H3i3jtzf4KxeL!C$4Lr6*TEX2&#)1zDmmA*$ z5wCzn@eWa3G3pPENJ<#(eznG`#FdB0pxoU>s)R&(`D_SuZN5{UTgltjvb{a{anx)N zz+2R_3$yCwN!Be&eroY#T~RKud(QoOM(*rX+P9NR<`&3NKHebJ@RkuRe6%K$ooe~u z0~3xGmR;XQ!(wbQU#-ajyBpOK95DZcUPd}F4Q$G}bqnrH2An;F+sK1A<=ysfyO`1A z$@&a7kYv=vRa2wx=6fwZgnlON9`Mk1RkG+)1s~@;w;(!55}Ysg9eD*Mf4@8R5gKW} z+RN=w{GNU*!2070dUvw|ONm7inrdvHXvd!D(N8L@$}Z>_v`6SkGD3xtP}^|O#Yb`D z3^vMl8uv^G=i}7A$La)S3c4|Dw6`nIjn$splvP1Jzt_f*V;XwW6Xv@`r~>O9QM~V= z*<0>Azrt2cNJ0^RnJ@ghw%2Dp&-gbYYG&wM)4!B;=6+Jkl4^f2h(b@V{LT{m#51)1 zLO(Qk@0luygqN+3^tj95`!;ps=@ddUWavG$t_OEbqq zQ}bxjN}CE5QdJZ~CFxzCsuSpSw!@xOuY`>v*nE@IY#dC7p>h7{f4>L0nZ~$-|7*_} z_K7hKaEjW_FQonzgx}d=@KgPCFKeA`MYk7%8#x3WT458yO6gCH zr-#2mtl4tOr;04HgQe0gd*>OwB?&F} zqS!z5SoD|BS1G6wD_ zLTMHOu0@?rIx`J|N>I!qVoaJ}ICrPHym;gDrzDgiC$DcgCzhptt|+FefJ4!lP9@0F zlyQ?&Gcdw}6k^R=z1H|sUnt&k)j>21XWC<=5IG*wn$+}C#?M_*sVftD z&s(NetIj@rEJZBElO2|mhGPkb6-5r7-k*)CS(!MseODItIJyf0Bcute5u-!rslF1 zs{4V7ufUP5eTr#^Qlh#*FxS9U8NTu-e|NRnM8!{IFA-Ma8YFozhxeO1Mf`~}y{!%` z+*{&8jx0Z5^Pf4oCtj)cbWyUk*Mah5IJ}a9Z}1N_VFw6_MXV%i0y9y7AgYx)x_x2`6@xWCz-$%V{__Dftnea!w0N=Nf$yPw&I zL5>Fli%h$hi^67_&k)nWLIN`YVMd-NW5 zwuQd)(#u$CyditJ=U)EoeMpmh@>f1b#zq~B4u4i#GR)IA$|UCHt4Nj=y3);Xay%axK%E7C86XX;qFs>%lGw7tBv4#^{d%sQi! z@9b1|rMG-|_a50ak|KOM>fRIsPeJdZ$fFE}1xOK1$*1P4RHdrkkcI)TbA}IT&ZDB? zATB)LXaAEWWb-4x3Z8OQIi&dqlJ;p{DZz2I?e?==@zCQ6Lty_tFz1Nysl)JIp#7f= zECVY#UEE5pSQfp&>QlMnOye9nSmad08N1v`b_L@rMK1kML415D^g*F@4p?Ld(8-y9 zz(L`S%%mHG*CxEgTll}hInV1HM@4~#q$%;ef}c!LE}&P?`GM>5?;CjaBpLWu`1{R) ze{I+I7hIpNLFkGiTD0A%H5hb->z3*Z7MTi?E6LRP=_}{2Upar{ljL8Wzxl6=tNuUU z(yIGkCACQ!g{I%3#>wg3U~Hb;NXk%T7w4qLVEBRpTqAr&!afJxTt>vReNrkFCOfrP z(8btm5#c9zl(plT5)_S9u1Fq5mXrV2w?xA?{P2O*#1&l=|Ebuo>n zO)lZ5q_z52O)eXMdwt-X<+8{7quo98_}yB!1{c)x>K^Wd>2sHoEu6h`=dYhD@*Sgh zuYm`{K-w2eJ-EGS;P$`ZCh;2B{hatCc8Dw}a~7l}oprVb&i|V$k6CVDQ}0Fb*zqcX zk!z_sghYAm33w3KdZT&|g+g+#vpw4^*qPhL1E3_q!LUPzCzmRCZj5xyjUAINA}kN7 z*sq5spP&zV;9~+}(NWsC3S2`KDT^aYdO}0FtgkSXj3&Wc3vF<&J1K=LIm}pVWm917 z*Tb%5T<-gGD5+M&RLnE0Me~1|{Y^39OxUrs-X`tjo15t_*!h~M3p^T{gms$nx}0wAt2NLrHg@bW`ASL+%dmhC%j!D$u}=n1gdTK=P)>=BB( zTuy9pqG>ykIt}(?f4xTlK^v?H=aPj(R-jcU1!2N_R14C4Ui`^dRZkFtiT_qxEf|sd z-d7R8MGN37khEAiL-i`3G%VA@zDlb_igc1dtq@%Eh^UZoe_g1E2Tre7UL=0R%r_=a zavdHZFCJ!A;y}5TC@ax!rJ}Y4z?z-MofhlcGL8UXzS>r+vIB2IGpScv`q)kpz@#PB zKYEIe^{WF+mXXGZy-AHRNwvjk7wojen*xQKY%*dfWcC-+JWjC85=T_Qm5vnQQh(8- zw*pG>y)v3vs%aWcGPL{ebAFA*CzW+{32OJp01pN>ptTnBBrCFNhXHh4yFX_=Snwz4 zTkF|yUvXh~q6;g&CaS?k_PPB%nZ*MBzysVe&xy)O@&$`yzEulT`J4~iAyH8XN=9_# z&HI#%l9bKrlk47M^9iw$i&7xcwUUwo?Iw9srb&J3$thBV3af7QgK{ZiAqo>^BuIGO zPCoUR85lTIx~F_{g#Cf8aOWpntJ3@_1REFs5^pzp0o9+-Eu9B_wZ!VoN={ba!SZ#x z<(8R7#dWvx5EyErDrX{Q{yUe34~=QMO~cCT237r8gF2nm~d0g3#|^)UT#(B)x} zJk%c^cKOh4uvw}N8iomfHFvTcX{qT@TaCq{z1`JVG>=jkhz4x)7YGz6@Ny_9X^u2E zKrC+{!3+&3?e-vhON|64^W@di(>xYls)aDR_pAw+y&p_Gk%Al7kJE;!p(2IHD4!6Z zO7aFSboE6!_`GD98eB~E@#vsWuLy4g5oBP5;WLUzVfrS}PC5otXk~zCfEUv(@?g1C z9&xP?&_&X`QS~Y=%zmCn#d11aDqMX;s-1uv>=6jeGD>v@H9VKj*wj;$IdxE5ka}Sj zH)`nLToI#SLe!B2PFnSvO?zImgD7~u3=i0}c)*S2C@6~uoV$>eHtH!|A^WGQew-A+YB(B~9B!6+)dIeciDj35HzBxuiDkKAeW z9N&*Na_?0Yjbmlm-mt!U_GZ7&^eDBs z-oCqi{R_P0hjOvy&fQP(7xn<<14+BBrnpHYj)BmHdFKB7HM9!d{el~P2#b?fl+3${ zr{(TaymD)^5JwHP;0z^#sQ~R#p?!Or3MQLR1y|MkD_FM+L>;@&_vN*td;7{2aX1&I z4n8|q`07Rw0Zqnm4H8`9SPl{C5!?fjY4JY?G8e!DG;Y++puU+t9O8L34yL|X4e(Da zFXDQy1+pdR;SNK{&i=jK!?Q9KIyGg2{z)6v3F~MX%bh({1g9}cIi-Imj6$SUpQD6P zwSv^6Z;I~D5GDB=dX`McoKY1%S;Vk74XsEf27VJ;%wqXs(Dl61(P&-=!3$X2Of*69 zPotZ#@jQMeKX@rGu*sn>U;7h?c1?Mp<6A?{TJ7q&jqn>*$nm9h6%DMGq7tK&p_;b~ z&6f78-x&MG4E#fE+S^vw5zeuBp@z>!XzDjaHL-5f>CNI$Zr8iZj}WDNQ7u&6{5?`Y zmO#5(fS7e{72Wl8fw4G^toa9gO&x*v235wynKw zRsO|H2g$p;NG5M`W0D6;FK(F?V{sM4VJjW_TL>+&WXcP)G*-Y;-XU>tG!jQ+M; z$${q7h_#ol{c5xfHp}2-U8W;Cxo0bF)8nPt?7MipvlQTIr0r1){2oi=Hi!J|M;=u> zFPp9B&buC^)jW<;*tx!40FyV|xk5Iqb58dU4PfVH?vI5u|1=A-pUryL0PJ_a7LaaN z=2ItMn4}J8osu`nOLQ6VnsFdb=}U=Jv1&K7~;5n{OA5OUy`?%R)(+x zJr1xv7UPehT;ZmGeJ!v2$rTaZ+_#tF83o}y&sjk%Q3w&e^e2R>Og}`0lvbDWy_I4t zA`0?jx$jND*N79+%sbSUVrN!yJ(&(KY0RVY0?#V-Jldx+aL5!CoXB9XbDzr14K-IE z?ke4V71$IAy2o1mL!Dzov<|bf;++@{VgG_yKpX_5~D#APXaT*rEby$j?y4uztKAIrf2Euk!q-i>3 zF9Ic8$mi-32Cd++WIXR&ZEzRxElM~?lC>5RO4pGyk}52v2x<>RJua7_+M4${c|SJa z5}I(`ndEv8O-e<1E|ax_eTYYT2etE?9uSg~hk-B9WS-8oS6l!Zz+@$7D}ih;g}3 z6XOqasK8~W2@tSLI%e`Oo<4biTwiG!`#}~4byOdOO7;weL;{#QDokHLP5T-=+fKRo z$SD_@P(2-FeIc}lE6n6KD{)O18dw1$zf~NC3ajaA&|91`p8sSc$vltvy`|UnG;t&@ zKmF2pw}i7fnldeOskWQhyXlr5}{00Ol1Y)oy#j}#KF@C3xKyF*6dckhkFVbXK zT)$)|B$ids4}w;Hwr(iL^b4rV@tOW^34w~}rAN6yrW5%iZK%@&`mal%yZEVYkdorH zxOGh3gUc*A`-DYin)1eaGwzf0m~cDQ1D91RNT~zqyEJ~XdyyJtPL8}hI&Zr2P;cU% z5kX$9ECWxUrVa{){D%Gb9NmLXKL#_O%`xdm74dfG1dRLg2V3JpT2RmMA z#TR}S;3vxA*&~MFf7;)LFQub4)m$M*460A?^F2`pr*YcpMWbWXc+s?z5|tb>33WCN zd}+@~N12nx=Y*o1Hoc^BX9!UOkYeq^l<7Rjh%7QK__K`2#y;vKk$3j630?P$V*uJT z-Fd*Ao_-RYtKf;t@`2|w^mhF8D*WJ0sZDI8{=-f9NzlnCwzi8RDYE*m(MhSPN!Y3G}cjiBQ?awGkf%4XSbg2(?3QWauj`RG{Kd2MF-PX6W%@<1s)dsW^Jph zd9SjTV+PuaZlSJxDDst__1qIuhqnjM}%jpi7OfqN)!YV0B-(cDe9!V3l;`pDB}eSAg{Y(jfsw+a5l zft4lq!nC7%30kuH%|8Qr4tPjaY-asZG|3&_{EE?X`m)TC4sk?kSXe&)c}hRKiZ#9* ziP#fX)80d{N!qLQT7yzsa}{}Zvz+PHQN+;DJ8PjynA_s`nL3F~S5&BAkxXhlF{(i^ zLA)>Ov*?#}`bnwpancp8&B!yKo6@CZ_oA;Q>D8pHP8QcKrw$%IxX#a*WiaFUacuuf zL3X#gu8(eIjyInoCGVS;Nc%aYbSP(gvhqrxTh^MQq<(dFS&^N0rG1| z=JGNeo}CZ}P!nr-dxZ=@?OSg4%iTY{4#*8*v+{menyBLyX4{o}UbbLL{Mhp2xd;Ce z3GpGouR%>Nr3Ozdd&jYUmrh~rv*nmAAYtu-y#!n5&g5q20p1n5mZ{7}z?6aW9D#Vt zOa0AxNI!Wtdct@WhT z-gfafO^2tqgGM*yK4Ue7tS#K5)b`BxYCuu(EcjI{b{CvyR?_Fu3bng~hemKItyS3k zD^2mXEaBn$qowZWiK2e}A`$W%q@l$yX()Qi2;pV=nyhvufX(;~k$}CS!mMIWLlK)) z+S@JgWR8LShA_i1t(q0e&XehtD`cB~F@hCd=p*nRQ|a9CHZIeAjyZJ?e#chsej$$6 zNeKnjP3bEaf<+&5n5b_SS@H-R%;L|p+fP>IbZGhU{Op`}ow!i5V^!1IBkP*(ugIwY z;6GXaU7rB3k<78C>b3#3ml<@lVcq4DRVR79>+Q-5J>UjOf95h)82slP2qfAQanA{* zG&BjrSIGpQQ?=c=V2k>YuLZ{-A5@2#ijZMv4?#}%Zb*RuU#GlP5$Ucqu=EbF!vH0` z9#`_XS|TPJ(O7n%HjO#F^y% zH1Wsc<(&aM!A_q~543*rTev`&{|8yWkMU0S?7$q%R+@$K93Y$scf3<*DJ&zE`mZs=Q_Qh~`JUi!E6A;%!9Nf1^9w?HMu*7VYiR4$0UW*{!E2WK4izdb zXP~xB#{%yXHcnyYnZ7?keg6u6dQZN^h9L69`Ph4m!muJ+Y*v#$OIav93*ULCVNaxl z-n)11AT6faVg0&^LbDj?0?IW1dhY3ymB&y1dS!KH^}*bQ1opDMMv_VgPjljti|UnR zNjrfcbh!RJ*+Ys=LLroFz^rGVc;AuW_|?1hnc2g0LbA}eqXm2Bx@#d4vxT3ja*Yl8 zvt`SJUZGlAs)vVq!HPjJTBnw!vO9!4e7#EYe3sWFc1MsPNH1pzn-;2&qV^Ta!12^t zDN_qhPYs#}os+cF$Rw}I5FihTj<7`ZS}bZs+-9w%FN*2`@^;D;v{Fr?z->!%LB2G~ z5j76fvl0|&9T^$HMe4RuRm<0%84htFDb#5x zT^+Q97qw+srurS?2$jA&_DB09e$BJiOAj%TF3OQR{9Cv@fvF2~M4E;C9#9Zrl#Fx8) z$PBw_p|cZ`j8mc}Xe^CfIA&9`GttW$E^xRqGM@L5<;QE^;7vSYS4ob}u1!xFPt>*xab9r*}*eX{Dmt4jKBoQty_G`GM{X*VHZO&N#HZ z^dlAcJHX*a<^{-aS>JH*V|~mE7`%PuJ4amB#2OECO_T>7Qj@q|Zk~F!Q@gvS{m4}) z=78w+Og7&y2=8X;BGsu3h&qEpXUW|re*Ryojbil>CzkiUI^T7qBOryuR?F+=cz4;q zjMODXzY)lPT! znbf{WL}naCho+IZD4v!&gA1t0NQFsYAS>_~N~z#lr@pu~aK{cExnHeqZFi*kXBg}R zbYE(&+k!nUHrH_O(1Qk)Lm*yjlpsDP)soK#UU&-L!H0b6XuYB?gfQg8f_Dq}e(xoH zk1V3IP^}?1Zg|{TDX^p_o~J!~UOMc@7jdCj+V7On{shbcD(SkV>Dw}vh=(4xYS>1U z`KX&RjMhn1`>-s9Ia015#BIeGH$7=1m9=Cy#@r+p{Lm7}D0LEHz^B|8NwRJM0a^|Y z^bwf>sfyj!dKvTy%tZTz_RbWR;y=fDXsKCibifO{of2LcMfEs$##MfdE}>AWRZ){S zynwSQ=WBhd37s(hmSw8rPpYh?M2G3#%ylL>ry6h$xp6ZitGUXNJONvgmGBgGJZE&e zItmZtAa}M)HueN~!|2^C8xpp+TYO}#+3Dczq#fb?vZKzdcviF(=Qt#Nw|mWS0>)Ak z#_U>fj>9cVi=JqlOoO9pyA)9w>oj+JPNF{JY&TM0L)J7+8pI|Ih$^THjGbm+EbSZ0 zARYr@>^YpKY#dqEs>z4^k)~?Ac{*`mGV}6dL5qeMVcSlXigkHliz0#H)nC~S{}k;T zOnqVX6$%X7SH|X>G{Vu<5s!tzCyFi$Ep6If>->r=ad;U4_eRHS-u!jiAR?0dC|G^Q z0*@h8GTuWXh*RI|EJV|fD9D#C>B?CP72_WjTuY{IetrXR3B50{)8PdZESq{y0pzqSoeMT7~#SVDox)nL+0_~p2$tsiZ5;1u zsV+8~e??HF3P*L$DMIIGZUD7wqzDn**}0V5zA}9af4z3?%4ck~3?)x4_1uQ%c;aRl zU2e`zLH8QazMWFZpq{7F&1CA@joU;82=zs!TXC?gt)3DZ5do!xqL2rB3t+F_6uPME^K4gYhKh(H$T_{?X?)MsRWLhcLZ?J&%iy!ALo@Xn zo@;9(g)t;{vRpVDk%{a#tTK_i!T&pkAYbNp=iOOI#cNlu@>E>Aajidk&4%z3fjpav z#m@lPP|P8crP{FpB!v`k9sU)3RO#%Uj?UZh_A& zEk4KJco}OpQ0^9(rRe>PVxI`|7Pxiga}wzDE4Od-eGAM+#qq2lNpVah&FNFr^HicZ zo)&Qog!-aVR21Vmpu6uEAEN zp~05tHA|%l%mZvyAL>t4JE*;{5El)T>k)vz!u_@`xdfUTLDGGO^XQHOQ8C&X&+avl z(gCa-PFmt4a9#*$1^)MC-Y3DihH&MR&yzJjGn-)Ko^oB zVHSNJJO3#9=!XeBso*UB;C8W_4E}M71OF4Kz+w254-H$cwp=_W&o7AoB)k>DrfNA` z4NxW!gp9d2hDyB~g>eo`cnaD64*$3K9+$b2)n+2cFKq=^#3%p!MI(=$-*QdoL=IP& z1UCkLBNU{Eo-Wuep(Ha1Hd2ph+3XWK`+Bz}o~m7V;=^FrjUh)u0Yrb1whW`c51=eD z4(ZgbN+Uk!SC~V~3(dP9436dDRP3C`bj~*Fg(RCTjO(QUu9mrE+bF=6kToC^!B=FSCu z#?LGH*pf&o+safLQi5|~wV8eu@xb0f?%N9B^QtFDvpk>y0=Dt9UqFCgMTV!A(5>O8 zElJ(_y?5Q7e7b^XMs{{k2KWo8Pxl%xs&!Nbh1v5rDX=+A#a&=v$$(*cTq8{>VO~2E zNwR*NY3v|{bawyFhY^4_C%&EOsGAYnc}60042((Z3;f$?MUZgz=pE4x22f@;q11#| zc1bpw(wxx=u8Qs8Oc{;F@zufX*8(1w()IeD>9J!Tp^y{eIrUHA5EW`?EPf+iNo4U< z42!;Z-hO@H{I&C3!@C+fSYqN$^`!@_cZb;M&~u{mnqG=zDW$Cn95&r?j~gAqds>LF zF{}Z3Q;N~m=(I&SlLd0Z0|GI#B4VZ#)(OBe8F=>mS>lZ?FrO|lmqnBiXA#wK*APoI zdA^zUNP;-l8eORMG23Jy&PZJ)HtRvoiWZuk?b4<84$?>0cM1pDPa7;!3eo=l2=!GU z8!#~4BlZdHN%u1z-3xiMZWkr&F3A?91lrGRNVM%r!{#W>dc?t_Y!Mnp$&~#LR|o6eDwyG0xH@P^Yo4z!{tqopw#+3=~g_nin`*+N*k%i1vPKrN9nemswXBXlp@C$L8?4b zHrFsl?5$L;vP}!A)W$sY(YPvCTLfa)amm#PfP@X`Pq^n%J-SgtgH>kzN)>$CCy&G( zg<{a;lb)gsZ1+T)y%T$*ZMrM=M)-0LVd!chjMEN`MT{SUrM1(OmN2rD0sR^5gu@Gt zeFJ=qQ4a>jsTW8~Ux({ddRqE}fNowtLG%+Nor);T_e3GP*FXV#pMaw@yEzN`l!8td zOg}>uu-4INM=J9y43ESMOwOWCE#ow10-L$`UYvuue;}=<&b`M3rq%AlrB;l|_xja(K zHduIM93({1XbT0Vnv|1W;X|-INR)ZWhhBlZRLO*+}pr1j>L>;EDR-J=8zE zBFvHHC)F)@+62w%3^+108*fy^Kgz8w195^N>dof!$~JqEMj%|xKv2&py$Fm4w@c@j zC7?N874Pd&ghv3}#Z**hwUpo7GuD%jlci^dZRL2Qyav7K>?A)s-`;zsXffGD`4V`D z4ZTD%WaxDfScjinAl0}@EQVni#Z5hK>JM2yxz%j#6?WlDbXMJ5ZauF<7G`uk*0nRs zC5}Gzg_)q-)WHRYmbz-Ayilr^2sSnb@hJksORL zDW^ceW=#@PG7wzEhouR+aIKn2do^3>a2!wQNXM$Axh~PiB2Rpby&)Rhf3g+h3B3AP z|3cM1`~2e3E{dSh4XgtZojwhdL5)I@5z!9j_zq)rcZzC~k|5jh@1$O$RDnnU^Hwo8 z?dUS<-_Y85+G|nr0}E1J--2L4Y6#*_){Z3v{4JNIy5+~pQbS1m_`MJ;RIl36mDgvx z6tFGa?Ve)RxQDafY+sKnJCqR9O5N@GtgRa)?6;0i+|xQpNkE}R`USfiW`z}7vC z!PZu2)P-mq1yoCO#D` z&6g2!mamGh?KDKw)Av{C7fXG%7MMp!$glhZ+<`UG>jWMU{Yab-cB+GO&BlhPr^NRC zWsO20gvQ|qTa9L`+9xKX#>Hl_88r^Ja-1?5Lx)zNw$!Va+uKbEU6s<4-YM#C zVn|r9!}G|w(%{dj;%<1(t-*o+Yv5Zu?7*X{@LTzq+i>8~&#e-PXExM8$~XzBw6c|y zpLsVixllu|6ZDH$PDve|$5K@1`J9MpOnwHi$jtgEAltLp<$9scBXej1)k0QJqm5=P zBzADJiwM#%(AUMr=bb~bsV8)5K`K!{XLSB^)*HmUDF%bS2b?g<$8=s*R?$K~I;lF? zY3gb=4*1pX*eF(v7?L(zDK0s~SHp9iR{fWfw$kIvQTZTrOzq4??518*PNL5SExuoEs_!ZcYN9CXK?|k#93^6=L zMz#)4#w1fm!uVm%vzSkP;M(gbHrG*|%j8-_=R1jbE-xx|*z#O*A|wJ3)$*JxE(7xikCF9*a~EvGrj~1O{zd zq|Muv9C^}ha487uwl&IKoH)aD2UoUho1I_w$5W%}$Ng}Y`8L8|*yRZnPVu^}inPk^ z$ibCPbvFS?B?eVo1BM@!JFd8yqcRk7EV`9PQRm3cEqOLjppTJG5*<2~-bTC>m{OLy#=ul!fTz|062Y>CLC;W;kSh;4e_feP`g)0amSlil4dE zUFH-}+iK(Id|N?9KC`XaS@Khvhqpg<>Q4t=Vm6BFEBJ@MKZgqWN&IOIzug`9bJ3c! zhb-sYfO~BN$J}>=|K@IO2O;p*`d^&8gDUw?HC-5w;?~=rZpa0PTmIA94l{v1ec7t) zUfFGIo%>?4vDV)G^A%iXXjRM~@2dapXSus^4oMa~-qn_On_rYY=ZZ|)E=k{kds{tQ z^ucf)a4Fd%adZwftB7wm+EC!MFsLtBy;CmxnuZ?YTx&gx+Mtnwea$rHWTKs6)R%pI z&2j=9%u`2~6%`xGGZ!g5^lY2G-tbQEhL{_DO&M*fb~?AGQa{mmd$r!9SAe^?PAxr9 zD1%&Qp0E#cuva>GcF(ElJv7-KqoXVCF>W#_K2&t@eA2Crhh^+?-g8oes-K!5a$g)u zmv;|86BmDYYTsv`l}i)z`fyH8Fcs##5=5CtEZ@LZj9ZKP@q60u)UANKQked23Dm;G zCj)qA;_wbJ;q>rWv)zksOr@fz(Q2w}|5+~| zPNf35qXgq=v;}6cA&lc?2_?`Hv$vS%$(dO0q!=e=Uwc5KZV}SuhxOj-F`8AHI@*OF zheZDL9LRi{Y|h8v*GO&cF|PMjWn?MrU&r^}#X2f=c+h4nFAdL1t1Cht#2UX-&>#usSnE|b)m6Fjb}v&`6@qp zL`G}IcOK_cUJ`l)Hd7!=U_S;#Q^Tf#D(F-Wa~aK8R0#7dbko_(AFo~Kq^(zIg3}rF zBg+>Q!plEuk7Aa)(DjXKk$Ki5yU!<)L~44FQBBD2^w<;WLKfTVvjbm3w6K91YWM9P~1W@OKcNE>j`b;;dDLG%}fI5gtzoy zI#qa6N5x<1AKC+}O{sUtbN{T=8?kGymb5)Z;@*RSZ}4}Tl69$zGVV-c^HxAbwlvlfM5CpLSKCOCbz*+>?Q;7V=p_PTQKY{Ugid>qrt|&0Zsswl1aX zGEVR?*^YDeehBrkU6z?p&3|<%ry)Cww2&(^t=!51L~q%7H$f8h2WuEy!}vbwLhkfq zT)<|hsp&Urv<1MpeKwQR%CLK35g+GtCS`);j_mRoi?(A`W(8zJ;zu|e`4KJ{^?L+R zo3c}pVe-?NLDgftfGbna!S2&{1Z(n!_|Uk|h9}A)?bip9PnU zgTUOk?c92Hp;^EhXVRK!AgX(*H)0dwR{f|>!#Y9YAoY+1GKhpoK2?lMrY*Ga`<;5s z$dN2`%jVp@M>xm`lgtcc^58)-Ja`$|*DpLkeu|^z6p)TY%!LBwCs?{AqX3oTDuKcD zY1Rl(ZN#W@F#IN<5gC4p3+c;D4K2u3Cyx;_BDXCvACm(5G~neL-mOG#k#v$J+3}o% z(09`z-93}lFOZpl%lgCK!CfQ0rP9+-t;A{)HUYWY3 z@~FJZ?Jrx5a$4jH+ZVYk$5PZz8Kq1CsT!;y<)Z7{5=nQPz zO+7e^w>J=D&?@>IlreF&Qzm&2e1KRXE*J-pe+E6agdPYpS`Z_%t>#O-@*AMXAiAx2 zi5PS9fp4_`IMa-Hi+nEtTpjk&auRUU+ew2N-SR9zs=xUB! z!*F#!9$0ao%|Bkr&zgaI09ibxA9!g#IasH#Scc={{Rl=7;MfgcZKr@Jm3k!EV-gBQ z{s}*^s2`kfu6K9PEnT$r9PB|lOYNtFA>o->=GeVjyPHVtymYmPSG;U99}L|yb%OqyGoKu|*Iq9LGK>$>2Sxlzu!3PY zto(+;2NtwuDfgLH89PlC`h#8ML8Fs~Hs&b0Xi+I;ML5i0J7@%fWLE#=(FRIm5b1Oa zK^w524=&Vep*!8yCt8F@XnW#{NR6?*@)r$ z=w;R|KR}1|n`E}q__mT?erC3@^vhlxVrInWJ!U+V&iI?kPWeKPm=CMXUUQD8pTce3 z>5aiL^L4A*`(uN}ljcsP$I6bT^RDo@cP+<>?vkMw;ym@%_+Bf#c)<#{*1y_lRCM}NeG-`fcX?^o;P(+%IRV!DtzNL1;n;c3z0D*u`} zc)zyBa-X8Pn89}Reyvs6sx->E@woXa`Kr>X0G-0;LON)b@P)k=D@AQlCn-kmI{+s^=re?f_c~>-%^##!y7Tttxsqh@GB6%w{|%upY^`uhVb3DwNi+qC0qV$sO_u(RIf>AU=OK364Aoh*%aCD91`V* z&#AAfduvTt(wfkrO_wYx3I3|7Ud`=g44C=`NQ=6cV< zdMFXP$Bj?Hrg@@+&DkQN+-ln6ZZy zy!*VJOkI^$mOfts8IHf!-}q~>@zec{pN@^c-rxA^vGF(h8-F7<{$_vUZ^p*o>Tmq5 z*!a)-8~<5s{O$h6-;Ry{yub0E$Hvd}H-08Iezw2yv$64W{f(cCji2vt{CsTuz5d4E zi;YJI+J4TjwxZ3Q->Yf!XL^RTNl>mWF4gKqo0pnR-DlOH-_I#<24pNC$YsU)Fy3)| zUM<%F@J+kDS5V?HEBoiCoyM|V7RuNncOfzPt~t(0ybacg5A|<*MBKi%q!x znyo%GxsQX>$8@&$0uvWiw#>Rl7rV$7fx!|W-RQt?m2j3=LyO&ZZ9VYm$$@A1l--?8 z(pd$k*SXI}7x$7CMCJ+x0L~=)V6pp-?>0fE`ODC^Ol0=m^6xwg)j5IvJzqRF*`v$eey6s#c&(FVQr(A|2~7< zLCK}->De2R&x$Mo{7>Rw@kM8~RTv7B(2LvpCG_Ggc%(8&;6Yh*Cn?2qcxkIAl7mZI zK@5*Vy69a^PreJI4=rt{4GME|h4B?MmCZ2L=n}FT&_^Z2T-v{s@mfA6S#(SvTxz}q z0|ZQy92v}mk3K$`PY!E)TV%^stD%#}3PW~lp+w2|tsQw%-30zp*6jnp9-d(FCE- zNuxc*-I%6whQ7mo^pS9$TZbMlO{y0@(|xlvN2)qsr3ma6%NgX>#+n^B528Y zCht)xG%f)g9y@mY!9la@KeV#TZhYt_SJcFXJ5~Tzb34}jxCWfcjg7T}Op!g|5WLx7 zVGKr;%%hNvq!S&SK2D=6-8Ho2(qi)*^HDL?5VsW=7S6~@cbAU{1UN6Y{TR~5End!k z!z+93C)MBOr_HeFQGC;>?j-oGi;TO{Zx7&&k^BcB9HVS{o+uSrZbD7hIc~>REA8jW zQl(K0U1Bu1nC@|XLj-q#CClh46C=?LD*$sCsW!e2J-Av6dZpPJl$wN`2Al}z5guA) z-DP0v(_%nwrHO6kA@HoWKZ>mJBxE6EXgjis#L;Fj%y3v<9!L|i?23nx>y#Gb<=BS? zy(W;-f60_)O?)X=^AD}Is(7s|=A>mVO=!}Xa(^(LE~pz#h}@yo%`{&2Cv_<$$DY>l z20gCB4OI2w`~|4aK&Q_%?*xIcPDtDNy7T zF9Yh(*UdVj-7(4@70^2cmxCF$*exouz&I&j5#5RuevwKU4m|Me*|Pw#CkFlzx(w}| zqLw}Kj7h1*d4b+UYGP48rLWu10ULf+U7M>&L%AGj$1#eMk`hx`!?OG6GjyS4y+8oP zMA%6kCE7xO@OYmH%AWar^ch?V=$tM+K7&a@TD{KuE$fsR{AM9|lZ`^Sumr~`_y_*7 zsIF%SJ@Q+cu*IXE`RG{sQ4$Y7_Im%|K}gf>@705}zCX7+he4H9+NlgWfBsjx4X#aXz&S?qsGWt5{E@Hl(R0$_&lI4HXgP>cKLj z_gf5>8QfPTSZ0LwZ(SEHxr2Xer)XCuM0p6Gq_i{Xu_eHg;1RoyiGQ+uFc2%~OHZX-8L8xcE~FRL4rJPvKi zQn!TpD1=4_>e2=)Tqt^@h}@Cq&AECi;O0HGQhtGMlC3j3`(?F(mdEuRmza*krSRuf z%fk}?2n?7#yNiER1ERO!do>D#F!_$nbe>3`bxVj3A5}YO)9^fr^k6O_1CN%YFX_$R zQ%VpQRxYdjU;}6{WTnf}xK2%5?0cm*QQ)RQA9E@6#Pkik&>Q+^B}kag&{0G#7LKl| z+%gPO7sV9qbu7tGD8Oyx9*NM{L|Z`7{-RKR?TI4_2MQv#tYF;gCbG|&$!hk3$C0Ol ztYOPREbOx)mJ&#$Hf7dL_D%0J*PC@$@m7KbcRbJN*-CmRQp?2oM@BfVBi|OP?>;2@ zDIxeOu4npmdDSw;g9C4ucxZL?VS=W)P@~GJ`Y^3bAT?=`b24`0Ew0e9nJKS%4%%-B zD_sQx`pJmrpEk72#;g$(29Ime%{sc#Bv)T)x?+^jeRLjQX>N9qNU?~d8q)x7R9p?X zrz|CqQffO<6~EWUM^=8gQTJYHmu0j|DvsjYw9a09=dmP<2fqw^&Hcw`g2VRVkP41x zc6U|INLr@r7WOdJsz;Ysc598<<}1+=M!`$}49$PdeYl8LhLpkC4|{IQ;PT4v>M|!w zD99jm@EB33{!!kYJiy|`$A5oip-yOL`D73FG5Q|VI_+N(2RG?SOv+qk@GFe5fCn0P z+GedK=7t*;&dK*OqTQ!w5h-Dj4etm(v6{)o_b`1|yC$Nb8TG7qG6SYY4po*#s8RAq z%!O;(uF}gDbATh^Blp2nl%6!XY&nXD<01NOgJdjo;txOFMfYIYdj~vj`M7U>3$8O2 z@RWfx`8BBNBqA?o4c?~J*B~+9-5{Z9X0xDx%t9T9L8?pmjW1a)fkCKbLZG~$)1Z>9 z^N}^=4brXtvewy#9A&BErSuI4l<&9esuK%WegoObQsNc-pVE^%P1?D721-;$sVNY( ztdA-db zv2A!?XMeek2UZ{^Wz{kI{~I`;!Y@S-7Q@zwJWofVs+NsU1xgJDH+VQ|_=39Ew{mRr z2lVF;8hH4j1}g`53_B4d>$P3DG`RT2Cb&uT3&DNfbm8 zzo86j$`Zd5a>l--G(_eT#Iz=ui2IBTZ&5n`7~O}OoAOBa+)Q@GxG~di6};T@`2LMG zC$wIQW~|zFgi4PI!#-RGFN-Ym8^c3$1$3?M1){u+_$5N!hS{Z`i0I(DIeW=&cdcGq zFFOdlOSEK~H^Vx7CA>?>dJO-NSy(U3!@*-p?+Gt8#)-YhLque#9m{J{7~N9w?&@|m zS*swi1$qtI9#rrS2;afQHCIPs5dLFZnkUJC^KA)`nLAA%Ps?5C^F*DYi(Ks;b|D znLUoX4DV2z+5(ULK@K&&NzQD&96+aCt#4j#*S7F1)}@4o92(rWP@x~*fG4G7ad;V> z!(c@xwenC!9IM{~FJ4d(IhI&g^Vkt9eVRvw3@Haevr%1d?d?Vod|iqlJsTZ-!M-=N z8MRpulLT2k7!eBixq7Een^(@EqJAXSZ zMVG>ZM%fuY5tLc_JI#)yVxHgx=*((HQewILgEF5s5;bB!QC&JH%}X|L#ggOX zr3Y*j+K1?UptmnS#2cr$gvEyPL`!HB_4T#=-B9N2D2vhbNR1B5XrB;cJbu&#V|fUq zcXE1MtZynW;{HzdK;?ylVOYCp%~%Dm^&f7KirMpD|r}M2}oX1HM71aPmjU7 z+uePG#cs%A)zj4xg#6bkc)8KvMzx%MFjFVIoO59kFeWc$W|SCqD-y^#u%@`2-72=l za1mVf$c06VC-9NCRUux{h)0;3w=tB4&Lpmh;n4J;=Anu+#o9W~bX{~4{-z=ti54G{3!O)6hU;sgGek0%(cIX& zYlkWB8|;hTs__=7jl@yO`HZxPz+sn)6?#n|x(gCt>jp^ed-V~G$yAmz05VJY$o>NN|I(fb>W?l1@p)gQx znmIgq6X}!#!iQ#YsiTHC2I6can2N3>^cc_7n*43I23}4k`TGXh)bA3anPT@cL4iR8pCV;B4AoE~f7!;uYKq z9&zJqu^?H%$6KI%D2kRSno3LT8&%aLtD6+vq9``|A~w}c_Kg?I zHb+@iS=GtT%Bsn#>YK-gVHk!+Yj_RAFb0M&Fbu;O7z1N57z_-FLO{g?^g!o&e!gq_`sTmlNb;^RL(E+;U}mN#%k+*4)D>%$kcg7Xqe z95yk%P8o2&@IJ+yb=qtA(`<{P-o=M=D5|*faVl;3;rDR9X8DCaaZr(ZA}p(-EtJLF zH)lmn*AbiLcirWwgXNd#Rc-Bp7C$Cy-7$?Flvw13qSzD2-7QBK0)&5o%1_s5o~_SYYfR-FAXsXk8N zzWo;mD^e@l{ybmD>RN-J^uoY2p?Tl_x6sc*{%U{wFur{j-)0hvVTa~a973ROi~UT= zioU@8_x5u%2m9LOYV`6ONW|~q4a^zl!?iwnVrRb;GPRdAGbP;q%Gc)pbD#l9uED&{ z%wj_m6^{2YKcFomz2iD?uKlo%ccilxJ-O?gX#h?$Sr4fV(Qi={@52o?S~L6E3ym)- z$McdoI-F{u2^E!jUh^h>(F|wM*LrR41ytC;A&Rg1`eo+5F%xVX4)3~y=YiXMXU<=H zLG{gBE1OCB_0!e{7N7Jlduu$DY8s-UP!4i?eINH^OP|#fpr`ygsE!jDBQL*X zdxGrcGz9Y^`XIvCSG=CC)B<=*uPWejbQu(^oA{T^KE=;c2iBSXsk0YP^{`{C49*j) zbr-fb7GzE>5^YO^73Mri|Jh690ECNBjXfwj`gOXrUSnxd`VtWQv9lM?$*fv`H!+KD zuRSZTeRBpyw6K|dU(6EF(PgZmDuMo!I`&SNub;j6W{oZz$ofrC$M+xgLlbDFnsi|T(7XRpbkDG$W!?Ix4htPm~aqv=c5Q8muC1ZuI*T*%(^ zl=#~A9N$Pe-2B367K*gv&BjCDk1z_&Jdq$Om}c1vPo$6EP)A~rvHZ!>V0z1RgH&fT zF~NWFDM}3e9u4wJ;_@62>LG{H=WWC=vb>-aSRncwHaAcyfV2ckjP$Ce#&Y+E<#v}S)2u+v0B@_q&ZZD9v`N-zlwTR9g{LkAXmx+6fM#YEfeJNVf zwkS2dM?e(9)|>c$EtK;@H(bMlYMI3w`;PQBhc^bJEt!P$X&yg2eT2{SmIR(UK{^@8 zkN@5V9jJ5m&GGr1g1{R(`R}9nuSEna_M6Ca`|-w={>?26?nj;x_p<_ZukIr%I2aL<||9i4Vj*1uMPF z8@-cyRYzavljq0sMD*^+4MS*kx|n3$G`f7?_y~0j@&1AQ5l<#YcG^Qes}B*IPI1bg z!kYk@*I2_c7@($E?a%3m{!^pDI`WV0@4namE}mjl`SHd8=pXuq=I+xcQ;dq*$q{Gf z{ZzY$0)$A=MO_E_BDoI6UN@IGUOzbhTZ&x*aNgO1Ll@^Y=Nn}sDO1p@`d&lX_hm6} znwr9b;_DuM6?*Qq%a_k1(HA?w^M^eJHzyq-rVnMPUz%9>(5nMn2N~DhCgj6#Z0Ugz zS7u?Ex0rqM)s2xT!TkLXLank3OI)hB@Z`3={Np{K1gy-YHq-QAjpOb=0Sc=FlRx61 z#NXtQYhY4xOtTbFrjaE;z*kOiEF9PIr0N0a9pR1zJsneTc? z-&KG7>v!^ayjF`rxNWkmlo>~IhYi|Gd+$i8=jEH|E|6F+-{2ECW7cIdXwf8%Hfxb} z+*p0~#1-7jFzC@4X!FSn(%qo(J=a4~!rGX^fqo^jMBk8T6Hx$a6Mo9Wu`lW_A7R{R$q46nsS{c_e={ zn+)3z)@GbGif1G8b8_pwGu7l^eD$YJYO=2VKD*{uxjMCH#AcWr`4HRin-PA=T0Svv#Gv@w8)1*uQ1b4KWmA9W{xfUi*nE{b)5Wj! z^wahtaR=CH0w-aohm8ID{qT0GkK{y7a=MB$1Ini8{=ykt9KXt>@gP=M<`g4F$5xq- zKqqwpYQrhe_=Jn>3O>{#oDdB!=w>qWu9{^Co}ro0_>KqB216eWU?_%$js^_K&LSD# zruQP6NVq<>*Wc+Ybj)7$6+HpBHC4poIL4&qHGe*=x!)TPuA}cjTNHD$J{_LMrx@N! zLpJTXk7dtgZTQ**$=^0L9uhr31V9`X*Oqtyin$8(`}EvNSlDzj)%|C-`-pqn4}S?h zc^@jY50WoKREDsMJkM3CQ!&m~$3eDJA?g8l&Krfk_aMTgedLGc+a61Hgtx7OfMwG0f+fPp3_2(qd7I*=UPl%Ca8*WP| zc__cNI{)V5G2&Ao)-hxELq5mMFDncy!P>*<6QZ|Aiz;I*;+r2jJ4C}HE}iPHEMp{O zn=^HiWQr3Vp2Ppg2Ry(_+2ObzK76?SWo8+PR8Xju@H}b?_-!yTsh5`veeo>r%fi4M zWNW5I!3QCW6bqsS3}@DGp!5WpEzRnH;xd21YI)9&cGeb#GEXI^^GjlORoK+?V7m-E z=6T)}MpdeYLAl41p5%dZK$f+(6<`Z1wOg)_AXIHyo$mC0HV1QE6je6M@NeanJUx3Q zE8&`<_F`V_v>2TWQGWgY*{?4v@i#iXS|eVnLQ(X>+s%9+!$C(^_Ei=%rs)R`shPeu zDPFzf^(cA3;gJh_)7DTX$H_gso?@0mOj8$7_LqrxSoWYM7p#YY%gT7N!$};fPyzMo zG8uc?X>^g&=4#sK@YJjol+WVjJ0OKByZjVpzP@}CU0zRD$2FA4OsS5l(LW2GDq5-w zH}qg*N?NMCn)%9EWUHxbs$(6_#Qn?i5)O7*LYXBvVu0Rp4B#ON?003~Gh-mNcj*AX zFW_as3K-D$5V`FvVGMO!>u`ws)aOQ>^5w$wV1O{*y8YBIAyT8m74TxLwHZ);mgDrQ zq2$2`+{#cwIc0_O*ihxqb&dCVd0u~qchI6X6yvtqt9l%(qV?83Va2!z@gl_(clj`? zP``_*nrOpEAd1r4_G6yT9^>gVx@wxq>dT?P%g!E43?G;l=hbS8C-(~uXOE?|aet&~GqR4eMPQ9{O=v>Woz2?UBl0|;-Cj3F-12>w ztAcUcz?KdZ&p-VXc#`zFEgYvU?nLVtLsD4sH1^l^LIUJfa8@W=An7Q!M5N(8xropp|XJiMEr${@U}Dr($T`e=n8wQ{BHV}0)8fcMT< zpLQ@4+2vx3 z(277*X#t+-Q`~}t_w_#@W49_E$cu>wqRmfMSd(^wQ{fU2kp~l@N-(Mi$q98{lGiv#^`G|M$RYCN+M2cZmf}`4v(e@;U`0r zM`u*@SoKw9jG>f;{^jaR>#)Ln^}S8dGu_@VRo_&OAYQ4yr3=29zWIs#&9gvF7KB*U zRDOb`7weYO*ZpGQb>%JY_D#erXT7NmkJVVE2?sV|;`D93d|zD<$(k@UU)v_)S1K=AiN5o_)_(CWdWyi-!23BdQQsh#dRS+Tz$6*dHHQ$ zo$|Kw;T;2rlwS>`@F0upIOW0s8r7-vWZFeoU&ggY*E^OHCfA`LtDjv{&?m3{0<-dBz7kbVz`|Vbo+lo)k153t5N%I`eh&fR^11Vpr zz5h|E0NsL?W!VbrPBF(dlJhh88sd5s5VTkRm|iP0r`Pzjzx&xsJLu`HfBTZ~I%|5@ z@aAR-)Jk@+O!0gX0gZc zDgp+*?v{M6^LDMLld_#NysXpzYk@;D5F}m5CiSaGOcS9HH^Lf<|drp zEoOzUaMEy}V|iKIa2VI$aE5d5dLQM4_%-G%Y)T$k2`ZD4bA}zkhgE`TD%`!;(A|=r zux#%?g6g^{jk%ee@NZG;;2tRaOe17gqtI4vbB;>n5KMC7m>JYghdNN1;ev2>aN}_A z6l;LP&p8H?7G~>MuYH(y?H4-&(@6Bc$7N9MPd_3&`#}+&{S10q2a~eaeY7-PCGO-? zVWvv^ee=*>X*z>-IJ5)`^BOMSMB^}{Wqn%mtKN;>&@}+9_S&MrX<3T@y z=#u@vtkQyxL}AZj`^-6}T|vrQ$vp4}-?`G?#weAZ zeA_3U=EFaA0XKAEK8pPM(J+00Tto}sC?MN^8knG70m`r4LhvSEdjMa%gp9;mVt4P` z|JqgLCd_!7Tn|+a98;@oeb?yn{Pfq(M>`hGQLG75-`#rrp2)1h4NYed#gyS^GgHZ=T56^FFEM zDSh*aoB_l`jMt3EC4U-oGB`A-`0@wwh;xF(f^Xwj?%RK9c&qsNNAUTx*kO`MjNke+ zMrvSMxn?7pquld-~y!bbN{6)`zs`7 z$%1-?2nn%e72N&7cEZxftv?8-9ivUhz5T)5H`nlE$Sqx)ck#%x_>)fRRXmVh*as4k z+yHUH^*)K>R^mn z5=={An%oElWOAVwEDXZW@k)P$YgDq|VDz)p81%B)?&9RVd+u!dQA*n(*`mKs-I<15J;Nq^0MQgTRLZSm3phnk4w@Aao2V)aN!M5;ceYuQ*{W^c_(AQlR< zw@7JDA`A8K{_>X^FQ?kqsgd;ASRl!C;9g%0-&PCp{l)J!UR;7KV&g~PCYE$Fyf+T) zvb5)?(!>A`z2+{o9^kHuoQqz_)~bO6MfC2FCwOxCE1OI~Hm1PoH4K(}>_UM3Qwe~J z;E-BDlXm|4mxJozsc_CN@eIneCK~(r8N(kd4zdgBw1zmX+Wd;X95BEdZcPG9qJJGN zq+7VOR4TWeAN~Z-V@RWNsX;^fcFN~R*$SA;)*C5uDK3-BW)JbRI<%IlJOWFMiM0iU z(#N9FlcgGE>($_^tGJQhdN_8dK%wpdr8`Go`{NSRj6oVT_pF^cYJ2gm_+5@&CKu}T(1MQ4ohFn5`lCxRJA?nt$ z2TE&RxJ&IA^qaf#TGFR?#=$bQECQ^+^~r`fVDN)(2t4dG;A3X-R4Neep2;m1ST2DJ zyPcB$QPWfR0A|r{p^OK!OLzKgRnxig=)mF)7ka;vM@)pMx-#SEhyCjz)OY{hr}r}O z*Lg2QrZpi&>p)Oe=f3dgJltDgV>0rpj?P@F0|?`=gd=eYkK{|hyN*nG zSA8ZhZNbg>)Q4>bUOju}L=O$%2q~8A(>~)z%7P08a;{`1Xt8?X~@v zef%lTQL>(e)_ThBk+@IA)jcJwNc&5L&yr|0Wo&un^@n7E1Cb#=JKuvF+grnkT^Y9C zq%dZme6z;0?7Gy;KfE>c(c{r`M%2WP_`ynX8;gO+ z?E_RxNC=lr=p1$w!nC-l$4?muqtxWZ0-Ku~lXzEC&P}Ya^=Ur&3qQi%NVgO^@ZB8b zi*QkuM1Vv59q7dJHmbLTi4aY3st`E2xWku{3HnX@&Ge%+zvQk|lb~NdCCE#Uocd!o1xNaGQd%Qj@&*?40R(t3Ia-g>jI6<&+uCrcPPJg0(~hy zJ9Pd`R@P}75wr8qd zldou>t;i#PnD7QfTU=Y6Ce5QP;XA&9Cu{}rXdRp>zW8vJC?)an7saEVDk4X#PjBin z_n`e9U$o7Hph8^a;x5is-?JAp`;@(Zx7PJCbQG`fxs3m*F0wihW`a~fEC!7xw&8G%9x_FkkD7u3F)C0AEEu#Lv~Mlj$r>`b%~Uwb2} zFw{S;4sW#WP04uZWk;5nBhIR|@bnmTQU-r!@p|sf(RYy=oVbV{+yCf1b0QGbIRBc4 z^hLV7A_rCCctu?-2f!mU6T%3<@&nGZkDs5QRcCt#xK9@w@&YD0Plssu67HS8DcfA= zoh7fkn1ePqVLY}aS5(~R6>(zPNV?zBlfuwBgQ^QxR+TQj0vsm`eEwp@hEbaok<`Gi z;*WrlU0>E^oU#^f{q0^KEBkBjNaUO#TVw zeZ9V1yUG!C5*yS!85V2NLFf7ni1cXf!M7ZGEQV{W)@pq{$bp7|sV8p+ta%qSTa_5n z@p5!}{3LUeS)WOk;vR`feYo`*SC@`3@odr`6%UnjI;+tfR$xAF>NGm}aj9Ai>%qMY(;YVXF=`TtiKtVNRwEBb@47{U9O?47C*X zZ8}O0`RumVyv^8w+B=GN_yKH;xk5w1`Zy2Bxpg-n_JYtHp@F z!W~3Vfw&sBLcx<_T1>X)eM%!#Ytya5CE&=~V8l8gw%T_7E)c)85mO;Nk_9Z1h9FfL z+|(HVPeq~9MI}OsR8X5L(UZ!=-Z_hm-@1X%ds%==8!<&C3yUX=D5AG#5arb-QBV(y z^bY}v_07@XhSEUDgqy5Eu@-@9)cJ8ZY!w6+3QRwC+LsbYm>R=%?2;DyH-$-l3xBJ9 zOGleKoe0mk1#{hSIom%t7+bW$Qrb~;T%%w)gtWo19_#()z9YY77f$sxvn#Vnr}N9o z$3PL^*|9s`S?xrBe;4cbWP?+k!cDoL_-aQn`8MTOi%V1ml;rBe#H_wNWrtV#TRl`& zq2wYQk7QsWijHa@_pa&W8fpL?ep zxFJ86ps2e0|8`89Th#*7hE^3>KMxTyIF*Bca7P@R9*xPLA5ZE+xV#;ibtLVj*SPPm z@A0BlQPRbxV5aHDqw?>zC#8H$-%}&aa2;nNiWfU=pB$)Xhl5)hEcfXp@rMx3s7q-J zF|wmZ9p(d>kM8OUl!8#oryt$Zv)0b5AnC9isjX=qYkDpyy3+f|GCKAZDl8&PkKw(z z(Iq^6G62#%fVV_QtKjd_;PV~k{*~UN4x%AEmOWA@keFA)^=r6uscL=3*Cvc>9-OQ1m=AWchpbwWH=r_1{^S9uG zt@f7(+uEpT-dDH^yLzIpbX+(mbmbU}Qro%f%jsg$*VkzFXW`Y_IHFZS9Ac<70%W8b zB`Da0^C%h&acE(UP0A3Feukz=*^`@5%I8o;GY&tMZfXPL>VVXs_yr@b`T#0%gGquQ zQNF`9BnSlzhnT`Ne-sGd5>AC&a_4oax;2gq&=Lv_f^K0ehHw(ou<}77IE=&7Y_V?p z2tH%)WHhUcbu`fwXR&Q_=)qS|R1{uu+5tM?0#Asr)DemUPrY^|eqQE0Y3><~h;^sy zcUrsGU6veJcZ}_rsc8&q)BB2YPa}7dDK@E(LU+wM_e8SWpr+aPieN*4w%cg1~ODrPYj_GKQgVSJ@7OS+mzPQQ$Ii81>1~GV7 z@iZclujvA7ir%+GugSQQ3V9s7KX9lURoqHIZp3Z&BM70kcGtG^{l<1?X%U{|68>ND zU)3hX`o4s@XmoASCP!Z9Eq%%oA>XJv0+;u^N)|G2qY$5}g9E^^{%D+mDb8Bo*7Anl znpd#af4J+#sg(O!)7#>bMuIt0Zn<0v3VEc&OXi)qx7PO4zB_GOTf6}y!7PU2U^@@t zoREjxLawF8ISiaif>2UVoF2q`X&J>+S?lI%f-+l;=|nC%NT~c4Q=k>BXsC~;`m6Qr zTO&Np)fV!OB!q8WH5`PCzXni=hT5dSqV5^~d4(WptXSK!X?LD|`uVobuImierKlF6 zWpI$t!WkzGV@eZ9M>0#QL^X-%_Z}$HNu`)0X#8!fO7}%Nr2nq*xzUC2!Sp@Ri=DP7 z-AO#<8dujAU*c*_70KAOx%V;BflFM&##FpD5nUJI)CGT`xp?{-(Et-YPXH(kY5+?j z=CAExsltf5u5M(fo21TGiat}x&@4GC9ZptG&kv(CwtCJ<9jX3%fo3&x$d!z+BD!ii zJ%rcKArUC$_}%qTx6>d#XsjeY57a}(`3nEXGwNr@Q#+Nv3VST8b80f~i7qQ4qkK

48n$%E1Zen_cjPN8dBbpH;26M^hTj7}yjlfvDxyEdVC-s2%514?S+|V);!~ zoo?r7c22Xl^L(N?zE$3iY7B1bXgH+Srk<}c(MyF*kqPMZX|0bbXFmZ#)>JO8(%7>Q zI0Dlq;U|T`N1(O*xc2td!rN=nEEU-rvW=`TU^n3w$jGixmYl_59avcbZ-@>KVSig^ zBjGd|tnDC+!HNgyr zsZ3LnIg`>P-mO`lA+kKGIX_JYLTzEn2C64}Eg|gVkT@Yn=e|0dFuK&OT8;(g54E^p z;5GCSu(D3$V*{m9KCbZ)Q)P6j^Mx6_lcvDx8ytX-D2TN!P7_k?u=7nGZEf<-_x5ve zxK&---1jTf_l+~w!$u@wYJoUVRKB(I{oN_&OZlg%Vt8%ry<7I(&DlQJ+T#ei;trVh z?bfDLnb~Gi4^n+(FUp9N{jgECqpOm)e z>a?tG%lw#e-IRlTcFIAPwpcsVe==oPZLLR$K*I-u57sHxJeZGyt#iwl?^Q#S)Qxlp z#$)J+C`1rpSL)#}!^XH=X#tV=Mk{<+!=f=6qn@H`AZp(wO0kw47;m-!*d3lqHjQQT z(sK2w9ddWMdsOG9~32`XCT82tqC302{sJxZZf&dH*0O9Cekzbh?2sW}|^6mL0{Pml* z@?j1O%Z6J!PL^GEdD#(JAr#GrF~!{`vr)viKNX9xaF9^ zdARo)2A-g>6z#eGmHzg|`fyol=#U`aVXh6q+#)ZRzFL)!r^C^x=AP=g#~9)Zaru_6 z)CS!`s9>qOT1dlYBcCIA8`SL<I1S=~w5D#Z7#twTaac%Dp-I zqa6rs9qzr2>u^_k{0t6mGB{Sr!dvrsZNn+}+(Sn)OP!oC+I_#?q=$N>ihQ9WSq*mW zrQK-ipn`TPfX^ef2$U+v+L5=3gzg||#kYR#0y|i&U0diD*g>GrI}NS zu3f$u+=PuAiZJ(vSNwPra$yD5z)P>0MvA0iO*=zGRx%sR<;uX{`%Ce?JL9Y4jq79F ziYK_0Nbd}WFwIox5XOu1Y`VYl$>fz@R&F`+8b7=;gCDHi{5eR^v-0-7=sWAB_4fx- zr&(;4kUw|$*+wsCfz;<`tin6xbl??R;i-o!vw9LSVSpJ_VxPHX2qxu3gjePihsiy- zJvUD7snP1y8LJ#)J<2F-`=YJVszmQWaB6+6ur7|?f>ur&4hppT`x&cHlvV|S*;G1~ zR-sqhYAez<2%wPTJj7vt?$7=`EIB*qSX&3#Go_-hTq+(ql+Z2mkid>7ChD zfE;yHeOfK?h39*N!)u49U_Zv`CS9pwQ5#U&AwQ)w@Usg;A5uf*sO5N~H(KpKpBWL1u{mKTecXVGE*GOTMSJiU=v&LKXO;*ycscUssFkKBU z%1DmZnrGP=?U3Q;?q@-2pMYwwOV|-QWHj z9k(w9$9KGQ^RSHhy0AerI=eT=|5nHSr)5!hOa`l`P%^NlrVAlEH;2nS;@4&48OvX#zlfMfJ`g zj+?cOr|3AhMZeFNxNpi5$2S$Tuc~4L;B5&67ur!JW5>%e;;qMvyckx&it=+b8cyO* ziGb|{sWo>O_WWlusy?@v2J+T-p=_ylhjRLW zOIgaQ2E|ZDRa0=fF#{FSNDdX=DZ?tIwmmOYrp3d24ODRXqz{g3W zkYclMR04ID)gQqshzKw=<)1!DLHC++Lai!~yD~1Ye2CW(9F;wH)r0Dox_)81a}86&pzCGvMpR9={#bj-E;vke?LO@g-chjm~D+%;1rY z2Mq6xHcIW3qNEKS57tEcp4r3~Hwb4yX7E)q0^B(3sz{@wR*qHEw(o@vrp)Sk)z~pz zAlXB^D{YzeE&B#o$((G!up^URTjrFy8>=tWJSbxo;`B?h8k$)u6BdThZ)0G_zbXFD z;iUAu2S!L37x&85u&>IPfn z@Zo?D)`55v_wD{why`}BzOnaBd?{{%0)7QP-8FGgoOTc4 zmDl0AE~C#S481F;-G3p^p>Xg-^v@&V&!geb=kZ(3ZS0$S0e^40u`W;=)sX|V){hP@ z`B}w}?wKN2?59=Ln|m3#`sZiJNn?E9_k|+hc^o5Hym}4Af5AMTC%g$n%XM1xOFtbBDoA^x*j@Eewg;JS z(E2$Oe6_VSIvrwY`fx&PwE5$?H?dc(=vP;rG>})x{*?ygJL)$ZJ(Zdc^#FC|uJIZ0Rhw6yQh^Tte(NLQ@;p;Agb^*5u|7xL2e8cx?yQ z<{jMk+@ae3|5H33?vR-&azIjn28=G=5P4eYxAo}}}ni?q54fjNj*=JIQp(u6U1lo)l z4mzUFA@3t(9SM!>!X1`-P;)ZaB;%){fKE-(n+a)+T_{e03UVc6wC9nb;Ee<)_4;5m zS^x#sVG}~Q2GK#+W2hLfvCiwV5EUAxlX?79&K!dDzLa=0kC@prR*6#O>jc2&+`4Cv z_v{#OgC~j)SBS(yJBP|u31^3EV+~>JV*Nj72SHI}bB(^6ZpaGONj7tmlW?Z;+J{H9 zfX6lr;-NLAI_HWflR6M_foo{Rn zsa{ZSivs7BAqKG{Va&MN4pu<09`F3nM2uwaBnwnKz~70Rr-u0nHp~p6YWKF@<#7<& zQgZmjOFF}3dLEXA$O?P$8;ZO-18WqZ)sU`#AkJIcH&Oj}Wq{VRc&uJ!#?%{UWa40{ zrfWMo8B~qD8U0CAI(brFMVoOEEp2WgnscBRkK<E+T`{ zy083SBBeDHcg&hOOJ@%klT^)=7?8@u9H!FmjX~8fW=g?hK|%xs320CBo)cbdz}tdp z9U11PD@xaDPtDKM8t?o(Zys*~XX!8qIZS2Y!#%Ke&d-9ZhkmL)Gm65kHpwz16G^ZM4Nn_IrtVHEY5^y~u{sGf zcTn9(Z4duy#vaUl zp^ltW<9vY{BHb1j;1p34Hcm3gE5kM9P7dQv*f>^YG2%lt8od#PLIuqgLGCcRhfz`i zDlBQ`D^!6wd+P4ou`2l6xI*5NMuDQ@q+>_r={IJllWSP&au}yi)Q&z1RW-R&?Ii;d z3OCg+!4sBCq&9{ark|uW1QL#RF;{+9zM*2gDvCk98C8~kmaiS}-QopJ8>_3BWD~*N zkaL(Im>4jSI!th7ygb_BB}puUpdZNwIbweNQ0)v)#}SrlU3HbD(t1$ox3I${vCssB z+K@X#0blPIkFPHc*LF5`wt5r#L;@|=UjElD3(^O9oA^{m_QB#(hp&uvX}n~@XbuJ4 z4f~l3D6K+U+rD$$VXdy***k>_%$pGn(-I_+NO(=i=VEGZjYMx0NL0dvb01#8Ml-xu z!0)$&YyF&_<2GWIG0>K(j4eyIkzR69aO(aO)KzIg%uO=0c^e9zE?&*8*E67ZumN|F zB1Nk6)1@a6q@W1$Q#>iP%yedHLinv*l=<({>Ui2TKnhl?3Sz~u6KEwP(3sVN?)dgY z!!D$&4>h?gASV#z704b`r~;hxl4Wrs!51GcIZu0LOSGgG^l_m z)ZBHm6ZbpWPOH9`Hm<@aMD>jf)d)SzwM}eGrihTTgV1)^YA?%`CaE^7PZe_+s79wSBBhB+rgOHjD-6|H35QO~c ze7De8_(Hbu3>&F0`Tbolc{XhodS>-Ynyug6!coVkgF$Lcb9TzYttWumggSz86m0{U zDy40Eiok)4rmUm~Qvi!I70fPH{JXZOYrz{Zel@VCB$Q0IXt+bZEOWnBD{I=N%kocW z%a_7sTlp65@#8g9E3p2eZuUL5;2H;#YTQ%jmEWC0a;Qfz=xzz$R>Gv5`hM zY90k$t!V^ptkOmrTH1<{;S>${>oX}@=r?Ris!Q}$)4 zqu6yxManE9aV37zAP6h-CYxxclUCEA8HK%_oxhoFMgVGWIfVa;`)9*d$1ztst*OPz ztxNoE0GCUgnR9ADtv9C(Y8=D#9`S>8@!Te*(d*W!Qm7#bl+w=lrhSXBGRb)nUsNg8 zG>mkP@=ihiLXa>kBoboO4e9?fcd7bvDsPHteOCUoGd4o0;h09Q55WbB9GBx*649Z5 zVg3fMh5nByly7Ckf|p^`NE;H>lMPtjd&CcEt1_k`J9JN?42w% z9q|88K6-DL1f$-x;dyt?P#32f1w|N$PpHRY@pLn7R`vwH?mJqWZ0u|@%IxS5{;#`Q zmhx>$gK7+s`T?r@(&(aNIf&mfq`8iz!Ew1*Di9^W&UDbC-d%*N27j%p zd`0nU^S-u|hgSdkaG&j6(Uhpdc62~#Q{0zQ8WQ(Z>rytnq`mL^neO|(K3uNCegF0j zHbL7$@R-5E68@`G>vqd7^xJ*bv-<}|gx#6g?@uGg_I31j#gPt?DPV2M5=*#PAo$N{ zbw?=;e16{iGQ;{>xnODEh9$bB)4^axkxoWn@`jLUUd;Oe4!Fb^e&|mZc1ez29!{2J zKvpc~tm%3iT2x+j%>gCs+6N*oY<$T!*`pUskyOCFF@;s znw35+e|vg$JYc}(VVDKJ=1yhZqp~Di-FGUBrsh@6 z7b5enrz1TVX_Y-n^(0PD)h42PR18G*QadlIM^d8uzP)RjC=Q`w!~a>I$J5MV3eEkc z8G&Onb|;At*$_)c2I%$yH%g0iZ5P%eqex)+Jf}%UdWK4my0LX`e8KmD1!hN-R%>NE zT6c{8TDc9JSm(*o9!T*f-)T!fPnFIv9icI}xC|fC=#x*o&3K@`bqaiM8U^Szha8G( zwZ4>hqb?!kQ+%jC+u{Gk|3$^BR#ilxP3|Jk$Y-auoGi_~D()W9MXgm$?TO;=Cg-Y) zsE>@^lx^A&R*I45NJGDnh~G=2=x1KV2n$q<1X#X=DUSx@H3UjiM+U!t7naOm_=cni z*)7E8?deNjoW1n*{*ALA+v@3|p9OjE-s*?ryS@6Lgs@8O@=<0{CZd-;5jTaxm(#vk z$?-yi_8~4KS9^wdAXT0!UsJi~uY!`{>dKIM>QLw~E*4!I%ct>Y+Ro_;RN3CHoZty@ zPCR#|ooFSb+TYpS{ja_{+E~6Cx^sx)OZZ?uQcQ%04r$s%R9~&L6Y=^0J%1Cz513S_ zdGsZE<>5OuOR@yU%1e27uMupE)DF`$!h)6GR#ZZms5V_6{F88^R9`d$#5~%aF#MT2 zf__?DAXQpAMT(Uz>LjayR~*&cOrE30cWJ`(NmT;;1_Y z*M=VgJj5uyDT&lSn)_~68|HjccHPNm+RvkkSzTO3gmefJ_vO3y>5#^+OfqS%rM=&@ z3GTHM=}k!lOOhBzJbRfNG0(OG8QK_%k{Ua&cFUcH8{I^+n#gt=-Quq4va+CuH#oSV z?wv6BN@48?V#(CBdV9~yg>{siVmix;yQLFJ{r&sm`_oCHFykVVA?T>dJ<1t!^`Uqq03dSRjmZRhD@20Mu*dYc=9LJho+;ooW{p+ zX#nAzNtsU7lY-o8Y0{soBcp9m{PqZeeEar}@rm>vZp45dPnp7n@8+OZ0B;*(yJBJh z(T52?^e>0Snwn#^Q?-!e2YaSB=_!;)U7!l`SSLx>!$D{JRe8*3hDaI{y46 zeg094I#yp2V@e_fqU-Kr#>XK4Y2r4EjNS4;uAJsOZgpCc=U;a?eqGnkV`}G}Dh2LI zUdMcvX@}fZf6?OQFc@1-S(CvcfobJa-)U}I0@j_)k@N;eFNIvb8wF<7UtKpxrR^q! zn5(8S)QhBB$5aM0vN9?=hQo(T%O7uyQ96mTNsNy~gn-ebLFv|P>+2o()*@hcoM>W} z!pbK2I~(C#o?0ujT#`?JV`u3SrV{m+s};IdFkh#mA#o+dB+vZL#-t84sp)`10Cr{& za(0%+mYd&f$doi81ua@DZRIE6W*$8|G5JY{*XRLecbnl~YD zw7V(tk(ZpFtP>%YZlo|5u$wpp9{rne`|I%59|T4#?JzwodXn`ccR?xpTB-}`-*5T= z=bJm0R*C$?3x1IJ1(vjR>gc(mNu ztHV5&(#Xig_sxtZ@X^itGj}d?4JAE{Vr2V}yG-HZHIkU4cV_M+++SXX=o|NT0J_5j zDl}|s=A~F7sZGcFT~0(`5ZH$x_=cY2hO|3Cj`z$-=3%JqL+>#FNJORR7`Qe>lN%cQ zD=C-%+Cf>)vRlmZ=N3z2^YnY_$5V<~)XFXLw<`PPEVsoHrmCm&hJEU1f)+4%a`?X~ zA)6<(jF__w2BT8in~G8LTS>xbYlCxpy95w@zy{+5bcqAzXB=3g{lC0Rw70$Qrh>pu zEIp%gOvR_Cpznp5)HB;ysu>6-$4OsTufN@3DlYjs9Be7r@aoBQL%AQ4+IkH;)3G!* zQJO_`d5axPh*X_R0ui-yu{sQTB;gOSt^uwSjlovMtxe1;MAoXt0>3+DPwhb1O@*4A zv_3q|C#w!&C_Sy7P6f<$$}7n}eUnftjZ$$-fHcb;YkT~YySPUe>U6)B%ePJh%^fjI zsd<081kB@&3NRmB=6Jf(c1^E9KpoFwPs91xj74U33s`5&dvTaAC)-Ml+#Zk8iWl!> zSAKLZtmSeH6~Q(l`|VD9+T}sL91hBtM|aJ7LVEbSsn=A0n3-|unLpXz?o&ks6i*KgmoWiy9& z3jbS%s4_lK)Np#r;l-Jopremu-YM%Xo1T5RySq69_PHm!Ib&lKKCay`LwS$RW;p)X z&xX6XM`tq}cRZW%F6D+Eux7*dmVf<~w#4i$1-ppp93&{yIp(Di8sHo=4GgXziKRbj zMlxSL*~j2#DbBSnKVDh24y$}+O6>hwHhzY~P^hT&m8P&6BWjVaW`;~1F0uuWM?zNQiI=3Z?7VFVYLOZF~*B0@h3+x zu>)Yb68zRlG+3`=5ZH3?W*T}tq>ERHPGMr$NtvTFU2{zC(xwy*p!3yzJ1=(I&i2N3 zf7E3!HlCyuI;bProJXk>5si~-BM0ZPP7L`9RSFzM6@!D+Z3QY+u>H$PX#=mp}|?tf%#?37hhqLR(C7_tPr3+8N!NLKQ15F7sBI zg90`xJ1+$?T9lkaJ`i#3Fqy(*Sy_k&Dz$C>*`Bx6p0lJ1*FiZgf3ad4kICvy9fW}W zm|vT|ZJi0vgNc>N| z@luoJwLMxJWqps$U1?ZHxRA<~?j%FIgNQphNsw`qjpG-5N|by3%Jw_}Etbfy^7BAaVHrqO9L? z7t};NH*J5^Pdq1|pi#9rU3W_-om|1mi>cprkUNq)EO`Y0Z?)uFdk6O|%6fM&d6hwGltp+=deUvDdRy8hBhn_3ubcE88#di9#(+N*yX zk*3zmkoCz7d^Jg;SGf`3HMY(jwQga0S9o>);|$Fs$Iaf+Ss+8^FyS)AQT({?g)4HJ~) z9d^>Z5%0Jk5HfT825F3KkbU~j!*{(p8f zKVMu~+K8enG7qwjA2s3Ur;@cvn-S{2#wjF(HP%+OiVOl%bnfcYxcR?q+?}~ndcLHR z!69@Y`FBb$zc(G^J$!N}K#hB`DBE{!)pue!zBy|TyR#j4cQd=yE?qa%(MsIC&D@DK z=(d^8_TcVr=H8r4XU)%C;cg_I-sRoM)Vh}&?^6ESQe+}-NePn_y6U(p%wh$;Ji)e1leR8ye{JPt$F zdGy~3sl%0MVQR|y-@`rXes71zC>AJin2eXArbv&qzOw9@mvZ$Z&`EU1056gZ_zlbj zTM#W`WjDKCe5s%!O+gxmYM_#`lE+5<+NCFsfa11BPIzL2B9p3s9tIfVKSoI!EeJqj zxl0*yt{9NA#WdWQE$~_Orm`18+Q95REtnRxHc>rpRJWTJuYTp!Nbm4Pj;!M(I=hhE zUuj0wM6JuHUoM6bX+FT;o~h-;=`9!bY-@OS+P|4>0p#v7_BTx`$65RVy{a)SOCVG4 z%h@vZG8B%o-aMX#!i>zjG4NK_%R!#z_led16wt^mnVO_fqi^?QzFk6vfq{A$g9fP# z``DT%){Zh+0@8gTtNd zei_D*3j~@sc9yp{s`I&RAhR({eWmsr#r&-UcL3pbn)WJdl2QMY!MH}R*BbOP1w%N; zs^h1RU#3*1^7vG`64eXzf}sR3C2hv(Ej3o-=T?Rq>G8IQ#SkRo&vWlt`PwP=jnX<( z*g9rLtE$WHe6k~)z1;i=+Y6kv=#2G@xap$xYKOZ{=H|L>$Fdm}O0#mZ`c%11bl9>s0pP#UsHPfYW0v{?7*rp=HwNEM9`pc@am|aIO zEt#mil-3rcmHqWf0}s7<>nL5Abh~Gh?Z&*h)*EYkBP^NiJA(*tFF3 zb|&YeuP1~>JhLJ-RB#mNGtB6qd}Z!67*Q6GbBO$Hh-FRBQD9TosR>G@Mh}ay#Ib7Q z!F1hb_Y9a$EhRJQYf_hytJIKDcX{D}WfYUtxFklMOi$-zvK4~0RzfAvtki5%nblLT zTrEo?&2iA-yb9};6o#*IzP!pf8M2FBXtUWYE5Uq~`s-Y|=WkQDCUqA=*et1UavHDT zz|Sy=M+(SlM(l?TCYtRoRflgO@Ev zF;Pno*aeFEoORTIKg8fPC-&&osQOc;(W&G#()5Wh_J%cZ{03xz?wggu@U3Za!LQGz z2+Jq7hub?cdQWHn^jBAhqoLMui3o zy|<($NfeUEZf%`M8z<=N>{2V2qAo%m+-@HVE|Fdz;-B6P zTH@cQMB06#ex$zjQ^l>v%bE8rrZ>AaF~?aDOSo7_&Qj}-2vykDc*43of*rI@X@sa= z7ESAlkcbt$YK=Jkj`cxZ#N;{K9wTxoqYa@sph^^(@2p)RzC{6=Av{gAsHr)3hnfDe zEo--Tcx=x7??Nj=f=!<@weKZg)tnbsG}ianewG#XIivi_Dd~VWC$-QzuWiz?SKdBZ zQ%66Z`w!ScH;ij`E?olxdRV_Hs^z!vw;G1VpEKy9YEh@yEq^nk{Jm4n$(4dR2rD%} zwPU^C-1ppX#qzjtBT=lTtA_s8GD4k4Pu+AO`P-_yrZrKdQSK9`hl9}y(I2`9>*KS!@Hy(>+D!DoU*JTJ#?w!+b{hhq z+LYk&>ARzBH7-1fwh8;fsg)$sM%bC1N->R;37cLwowL+FU9M0ByfyITi=qJG%9=)bAPmh+cQubhZ{zbrSvrFumb~6ZPG(C7 zu_xENBg=!N&&}jEH5P5iEm+B?aJ@Uydw$0!h0#7&Q!IZP=$At`CG}Q^CN%y?X{T}*U{@piGjB-o7YddJuW+YzGcY{?q_eGp9c zAWHGxl)~O+Kk1xv=yAoenV=3ok5$wNy93YYCe(saYp?Sj)N?< zI-G3be$~mEUT_ZQj6c-@JTc=f`ES-RFNB%o@I{&aMyL@UOKyQxfhDjvBMh>AF#I< zk?d>@R_1#fV@yQTUxqN2AE}-A@9b*NtKi)={67;3H}SuE0RZ=;csdJ_G}3Qt$5cnW zT-@dA&R81Zlbwcw0KhO40K`F;)b{5bJ^f76Gb692X4rOZ0gdjud}`cjnj@nw-V*bq zy<^G&s(YQI-z@H3PBJBc8tHi%cE0b(JkOQF&2yKsA<20`RaS`ciAV3~ux;Dw0o6_2 z2Ve+gdor`7hE>rKM^qI@7Prs2VCZEo^sY2nbOoR1Z@0lZ{24ti`&QY5@^GX^eucYT z(B6l#N*lp$77w9dwg7dfr()Wr-y8ALc)*xq!FYd+G_}Tg=kvYmR|ezG$2IqV{G1)v zy(0XTJrh272!Z~)rSqRk2NX4crr=ZdwJ<<+zH13yj!7JgJ!)y4plWeRKpGl!b*P+e2+*=8f&E=N zDOTZNns@@jMr;QZ93)8znm53`J)Jxzo~s*S1TZ?}kX9TGfMJ7fxb=)PR#Y@eAthb) zlCiPS$(-})&3&W*51&yW|7*eTL5cO)kC6gF>Nql-5V%MvkU z3@{k{+={~RjWY`B;-upJ7M$2NL;#CFDJLN;*!Nt8)!z=GcJoC&L{;yL1QM_C!7gNS zdUWRFDf?^4=?P&!s;A3KoD4z%g)gvTsOMhENJZ8uztc!Yf)c_|+&InO9Kc#o>@pJJ zhk{6HHW?tW8eAJpIkPbwVV)VCU~PeC&|{UWREOk_+p%|3Z;hZQ;KV8in5AIANqGFs z_5tm}P8Zx?VMRa)(~%}$Wu19{j62$J?33PA@&JIdF{Z`VD9f4S`N;Mh!f?1aJ#Pi6 znL~5@(-(XA%=TbCjuXTJyiY3e&S%|Tcu}$1fH#)cp(>R%73x#h)=q9sQN|a1g;<^x zJV{czQ7r}cCG3Nns0#8p$d9gu+zGo`xWSOBOa;EYn_LZ$kvKYk0K|a`$P)HW=jXFs zq{G0oFsN_E1yg7Gz8f~drst7_YzBUKi3H7cUc@At8An8$MmyL}Yx!~yeGkxEj!wo@ z70Rb*#a9XGSBtv-xV1#(L&g+zrbk$Sa&sMfZ({$~Ah2|#&9T0XXOx`nS(`gHWpmNt z_1v3-an)SOdx*G)P$(p6PFSrd)tHHmcgk1Xz2Z%Z!Z=1Yy*cmDSzJzF_NqBDx63Vf zt9x81-NxPAfHyyF!5#0u+xwcCusRFUcf0p)`kK4lc(+%EFyMylly;z!k1p)s z)ce2Ekt2et#QUk}lx@4_KV7dJ&DI+#L`HXTCtr5M<&$SO`YXT@bYcTE6Xqe{*&z{H zGpFa(Xo+_~)y*AJH?D}^t3ZhfF4Ybr0($w|Fc%BruyD2`zrhFqpO1dt6X*Kd%U1?c z3q~G<#MWjuDk}wBPd^3B4z~9QydO8y`)a8OBqGZ0jPAtO z*4>$Twz1|rb!Y4{rCClwo92F2yLAx0nXVlR-=mB07ihvXOq-}4{Szkn2vc1ZD@wG_ zY>!31=PdN-DrcP2mxkrzPjB_OHuNERqE1q_)E^QP42X>1~uc~ysmML#?p zdQ1$8h|p1wF`jJ>wxN76wLwil3{N*j>DyBjEZf99o;^mvXR(tsIl=UnkG^#dq((DW zn_+_Jc^*#0SptRP%lND5 zX`PKFC4kL2P{T2XDWUA(kd;7$O7)t7v}(vaN9Z^r$+ZC1BgoCn7c2V(S%3ziU@60? zE5q$DuqIP-V+NP0zEONJ*A?tQIh1VwO=30Sstd^+Mc{Brm;wL_hk{Wp01_Lbeqe~i z;ZUM$+TeLY7r5k$vvdb5hiaSto1iDsL~6b;Q(|UMe?FAxTTY%-9o`#dItjv+b4DAJ za#3PCEfwxi^720TMV~++@TxMBTW?j@v5owui^220(Eyf#`~UF{`beP?RRqp^PD|E$08mg|w_L))ZLNp6AXkjT|%L z1j*?yPz^CTMniK>&dH>?^vSljFfDVS)obNddDEBj4&(h?6cybh_rz+E=!E|!2*&Bm zlQFVd=0K=RzO}PSPh+rhxOW`zV*F?Fu{1roGMwQ4<ng`^3upis9-DsQLm>9Nl{7g2mCMeoIj(t}+We0r6 z=0sY^=9}FN0Zzr6zk-dI?LGG{> zeF5ttb<}DQX6IprMny_c7sUMscXMf2vN{5-)GuRE0UEGY7#==6%Hhh?&b${Q6>}%GEw2QvZN`ni_({AN zurxBCxB&-_nMta0U`ht=_zKxZsM-7}LY7Ma}lnK*g z_)I7SkP86A`fCgCPOfYdk^jFciz>V@h-`(|tyEXpB-Iv16-zy^oF}D62ORtjG!AH` zaEqBUc)UiFe>Zm?0z*iLK_$IpdO!n7F%v$bH_Rwom&kC9nRfnE$Go*IF|F_^2%y@$ zRk72Qfi#k$H>I`V)G`cn_4$+-t$9;X=Wj_iWOY0*M9ol*i1kqW%lC12nt@m*{ zEKcJX*Oqy`jNF!l@QBxO6Ub<^)L*`ud?8L+;uDZns2uT2!Qa$MyPsm!7F!SwOC2ls z7~3O(o_GUSd5HG}qttOG(3QE@vHuZb8{#6 zM{_5@Pgc`Mqp7r0JCuUU#)<98;mRHQ`yFte-W<~mu1NuhCuw*LF0rVOwRf(BUVM|~ zemo1rY>3^$Xhei(IzAlUyc8W7;0O&0QQWB31Kvt@YW%KdEcY4>n`)kzX2sR25Wdr_ zG{38o+LNf21sp0bq@%{MzNZ&tPm~etD+$D;-c2zr*lp@q%*dMDL`=Fd+Nc%1&An9F z(E`@M6;em2Owc6T`c)D7n!cK>X~BX9I=KDK%|X99iReek%c)-8l7nA{!XZg|_^tkp zz#@G&st^8*3P)oprt8QgZ6#(^BvfX~h^DJcpZ2Ysk*$z?Z;gk`$d&g_;6Ixi9F1`T zMKUVh5SZxGbFehJ1QsbpJLCA{n!bKN*|hRb)5UBf9lC+GX6Jbj8Buwork;RwXmXZV z*f;fj+*Al?!8#%SNTCf%$u$nwxHgz<^=lir5mY5XSgNBB@H*}8FbbE;xa=HEIUJFb zvm69LV+sbJML;LFqC9=y&dYCZqLL6Jt|$W72g7hH??U97O@AYZrO4HyYJnrQecA0w zce*b};mDP~+Wpg48x~hv)elf+O`JfhNqD@(m+6Ea1C4T=mS&2lk&h>*H?1s2r9vr6 zBCKScUwaeBzKTl~j`dE+EI3rusm<)ciKV)!t?}}VHSTR)Px-p!#y1?e4yudmLzrDL z>j$NtOVLtwL&$yPE=DLU#U~XZhS5d*h4cLh(rJUqWMjg5t;&P135YkX6O}4Vi+UBG z9OA`<_vwMLGk{B=j%8wxo)Ik=Bo{saJ+xUB28XdsxdlaX_0pBe+nQH6ToN<+k?$NX zv$Sbtxj(7bQ2a26a$5uax58l0o`*Mwu9cvmHfX;g+NqY>GXQIIZ`!*~o0-!JH}!t` zUz!`5Dq7{~c6#1-!U$+I8T40p8M~sxjIC*8rdwxQ=`3usxf8CiJKp(?u+lxCoMscK zeKY{z07`YvxEM8Ht|1w)C?VVT8ZeaL)$tSv3JfKdSQgWMTJKK#vJJN+1#O=>KiOE{ z*e3h}-chK29d|M=_t5}=2{~K1u40t{{jyvKQBxT2%}p!xbf`)T6Sz>%adJy4>m&k! zF5ZGjSzf?t(A#sP@Qti6v{`7=sjgzR<5HVWsM1|GU@cV!bEZpfI-bwxOWs?|z?mGS zO2ZNalwV?)*BO$^JO!uh;fsS+goK<93r4`1-%-8cD)c)&D`iE-92&baZOb5^u%@ z;NPS_u207~U0k-yoi3CW8|q<`O?CE-A#_}@FKd5XmbfXhp84Jq0BTT`t%H&-tqIcv zSE6{U7;iUy7Vj&y$F0I7Y7)S82G${;rzT(ymFa#%ka;W|fja{1p~>G;cP;__2CpC}k*ar#X`Nn~Jzs-Ajnw{?= z_`Q25o3nkJraSg>MK1T|$!#Go$i6^rn5OGO zFRQlSl`cmI*NIhVbWq}8VmVGfB05+`Ge0a1hM1<>wevNBsoarS%O;3&p)sIA!6|CXf=TcQZQ@ z2SKMjXm2vk4?b zw9`{ERCVtU1=JnPeH&xM2*+&%gn0C}AzL%CdwF82xfs(Gt*pL+};z_p*92 zB2k%<6xwOgo5stkjR{XWJBHofBqRn5?Ar$r=3W^tp^b6n03ye&A#z(x(OJuAPiHcQ zX;6dJRg|RFm~c~0wmG1OC=vsOTrG5KQ0p2W&R^1bN0pGbQ(SoWSI;UL_U#i4NR?#M z&wOV3>cwdpjMq>mFGjLPer+|lyX4qjdX0jyBB+*cX<|q(ybk@%U-%Q<=y#S z$U3U2_g35SLgQTa7Qk4cnB}>0g`|1viFm=Bnn_g5J@=nL5fHMQH3zILN${clH}t~uCM-UY?uW`+9D30&=S5h4Cs1~#qT!OOwp!0&YA}LS(=I|rI1)#Vmt9YP{Npg z*J3OBY5bfP<&c|{6Ed$W)(L!5_QM_t9kd#Yj&(4H#b?3Kf|LY5vQkgL`4(x*9R~^7 zLb*s^KDXKIo#5T`7vO+WN!*0ekknmV>Qk2?Rr{V>kg<2*t)xhaY3O$^uuiP9uD=vV z?-F!5k5wy7&)`pUN;UVPi5OL4bY=A*jNqje6CL`AM5IP=DkjglTMLx$TkB96Mp&$- zRjsLddWSo`gvMypjGmER&)(`ly99zEjOAG<7e%!b^o>@J5-3ZG>0o=btVjy#YDVX8 z3&eRFzC06yI=tP=7-`;jPo%>j(kbw5yAYQ=x&U&OOMQ*-d??j2HN2u^w ziR1z0cS_q3Jsvl~$-z=lD-DvU$kvOf=qgp~?tUj|+^euXD|oRwY}CHC*tAqimu)@9 z{08NU3P+>;93!9-<&$_$@1nKrEdFeUO}@bk+#qW{wcK;xbMrlse;KeV%`gb0X<8u! z8`9~+Ig`*VI8B?0|L(c7*fj3>T?X`AJHOu!XdHt@E-+1Hb1THiiJ15CcPpdeDXCIP zv8n#I3W1izx4Jx7@__}Ohu-ZrCGEQzZ0%pM_inEdjEQROLsfi2Sd3QZES5``gKX7gCzTqqZtZL+cP678>_NASpG|LOEE5@wCq2whlUWMJ z8)s1-4TdrPN6i%q_~!L9)D-r)>sJ6nNzJO$KWc_qmOk0>b}aiN~h; zdK1KCg_++0PGT6z$w#RwOhMC+qy^Ovn$sKMohdIiNC z?0Hl+(JFOvJe8|`hr)alm9vZk2Zhi3I{h$qco>a2;jDE_%b=lb4Xcdj1H;_!$%P&$ z3*~R;dpEX@-9&A^3}uM-v%{ao&sX|4FAvuT_S2dc`{NejNrL8#_f%W?mS}AluRAfD zq^F7}fpyHi6K~(#^Z02w9C1ROzjH!G`a!qvI|>tkGV|waG&m|Q%_>ZnR`oIr?_PQN zi?Yg%WsK}dHCF9qmJ`dG+wejvqM>L;^*vdPq&AVn_hGCbfZUwHL$f2}R-zs~!i8{j z!w^p3E$wjt9b$8yc*mQA@d_n63{EZURVe;EfO5f8u$$qQffnqbq9$@f@BGjN@1Kz+ zat0q4gDah>Pg0c;>gSC2E6cMSsrQ{yZ4xOl{ZMn8booESV!2#xpd)G>nr!hioBYTq zdPSZ{?1t&#G)Q@#8$q8cI{f9rnl#eTerq4vh=J_`0b6P;@n51R!L)(Ruj3KZf1p*{ zlFj*;0XnU;QR!S>MaP=KKb2SdDgL|EoMH9q{8M`Y+m??Eiu@9u_Xa-2O1V@QkWKX| zdOaWiu4R88%FkV{uabDYU=5{wgH497xagn{ygV~QVJL^94UpfgBjhl(Vj#Nc#r5G0 zX(V65)P(^?P;cWEn7>dX`DGD#hTz(Zk>hT67!XHEe3~27IsE|%tA?-@4*x#ZmqH2T zZ1SOV__{EM9&d?{9ffppq%HGfILuXAvvI6C6byu^K{9Ya0x6C)O8#@fa|mb9$+bi# z*VWF2k!i^izKfcis`}AAGe%?krpBBB7{R~I{O~469TlR^kbbKvvEProWmmUO(A+^9 zEs5y@KS>-){&9emQ7SZ+=^Wu%>_6uNpI5*YW2sV&Gt+Dnb>Sg-Z3_~XZ6p(4PrJ>|`D|4sEm9nuPxaryS zpqxD4%E*HeMVL{7bT15d;!lgdg!&U|MQ*Ka=kMco($Q;rzHU&I6S+7TdBM+{jVY9I zbKV%vlE>62ke?Wi(1V#43o1c~4X9*m1nH}yVIz^LRp?rzTI+IyFk!fxkRl*RXb?gB z(cvCGi6&tI4Vj;i_%c#SrWoj#Yt!I9aeqY%+qxO}Q^w3xs`jI_87!*MK#t+v2EC&9 z27O4{%VbFWl&3+%ntwy1ZeDJx<8{u1CM?9G)GA1zt~4p{R)em2>Fl^Z##LNJ>iHNV zMjgZOQQd|V|NoKEJ`UIdaoJutxi(n&7Hw_-Vo|CP5`GXgn?r+NSN+wha1k5(?)=l>7Cs<=CF(MVIAAuP(F&Trb?D5 z!lCGD-^_`sj8#-WMpf{Zirm5Ny83~y*VI0ucW?pDRf_F!>rmNq|HKo?A>`vwnL?u< z>rsa_n5{te(o$*K*S#E}Sp)Y5J#0_2yuOm04ag7@?_wS2uxiQ$HN=Eo1mV zwDO1(k)(m%ne-T{bKE1MPE2RRJ+q=@1SCgSuQnN0&h(Q34&gnQS}sp-SrHnd4(i|2 zSILV~N=Z|CO2_fP((lqI(FY<0)uN;@n(8Tq&>T|p7?9uK^liRLJu4UA+*;{{ip@RQ z;1enazg*Gvn1IRSjmf&hOb|PPbOZp4=~?l>e8vWC`1%&^GlO!6d1u;%(435Qd0ziS z`#Vt0;o-sIwrP~h5!1I;hjYFM0@Fx;AgbT1Yuk{rGBOE95u^~%jH?r?LZo5{VGyIp z193u#kB*z75l*m00RbZRzuDiCOX}EPIo^O?pTI%d+|Z$N%nFJ>Q?unZQ@XU&re{8F z+4RfF8|J4^+s3Pu#pX69p_Nq|MN1pOUU||ZjMJ>`=Gh=OO+(;TR`(=GJ_zijmE5rT zf+;XA;bHB4f3(~8fj-B<5~N7O$(OGegRlhC51oDlQ3)#g!wU zIC7=?>AlJ#a*0qxLxHw7Y#>fefD%g(iFyOcKN0oPCOMbo!3I^jhVE`8Xz@*blesiV zFn7u}sR0V3VG_qG>Dhjgjv*GLHyog;YexBqw?P1N?jaA@DnQ`ciT*=aWP9GE;yxE3IRc}*OEQf57p0{IXA7QIyQc=(5#A!dL{YK~YHS)$} z14uZrP8uQ}_0|9`q2K;U180F0Iml_cg4Batm?oD3LA3^wB6i4sRW@#O|16NW3qh$+ zO8%j4KP484asnJ;6U9;k=0>Yq9!OI91$tzHM6yY<+@fH^MxXfOE{ULjm^%$N?v~0o z-;E^Es!Nss8iD8#yN&jI10#nm)B&X+J-L<~OR$LdNKjba$Iv&Ez^5dNSFF`|FcovJ zoN#XYZE{;u#2Mgs?Vhhx4Vb4SnDFw(Is(*~UV;gL?V}OL)FJ$hZgPNLVDDLGBn)ZU z<_Z&@j9#-UrDh$g#-?T3ns?)STxjf3;RbX?B^?rO38OY3EI86@6G3j_{g6K4 z(H+stzUL*|R!@UkR;{!_Eve9r5j9a9x-IsmZ}TmtIJA<)lnDJ(Keuo5+;odPtk~3& z=({M-5g@|$hFh2>RXfLj9=ySHjD_Z0y^fn$CtV%tdiA7f;eBq2AE{;Cg1-Wv zmSRm`Q1__o^v~y{Rh;*BA`vGp18VTuCT7~TJa(afU8Z0*Yhc~GHwfl6hHDqF&p1)7OW_pu-WeX|t3 zrs_!}%}bMc$nfk0Y-^R5E+dZ^SD4nCyLR5v&U5PTE#`;$@oBo{MX-8qRLIO4Wj1j^ zjp+H`G%NF^%V9`_g^VGWQWN}>cw@=2ard2qVHTQt&dc>p|M@8&vbVzu!S^sX#B~th zkBt%XL$&3sqI}Kg42d;i@p|4%_J=?f^%n3WiDU{BCSs2E}jxk z$<85n7LLj$Nb=Z}5(TQC-U?>^_mmj>Z^K@=PV(J4h{pss-6A7l*+uf*q#RRvj#)NU zvSvm!4@YY+N*mUak6<+ z+zqkFIF?4<-R8CY&-wZI)Xi(L1oEettf&EU=dJ$16dtdix1Mxb?N1@(Nh2#MAgW>^ z6i+qSDy;fbVsXUToU@uY4qmYBnx@H4*cc$&ZX5_eH(DFy`>VMAaVSA-?WEreqpWET zxS+l)m+6nY+YJ8=%&5k?SXIqLMl8hAvdB)o@T(n{8Z;43V{Z-0&*w{q%R?XLPA=%g z6uB(y>v9mueE2 zNdfDDk_5sPRY)A&n*?a$0hT{8M3qB2uf}|ROZ+a4s)b6gpciW^xWI&A30RP6(~vjS zsw^vIO?=zK`N~^koeiR~r?0f0jz3>{xwcgKEewX9c-%?zmJV7_=hHRYK3fd9OYtVi zIzt-TZTK2f$1D6XVm2T5s9vsRv*_&8Hj`Nx*Qql9_(ne-e+#8t_hR^CKI8JKDYrKF`kk(OWoXcSFyzO( z=`%Rid%5Y3VBc$a1RZn-$GRHb=u-p-W_d8Gw( z59K5LORZ#zL}?uY-D*0=E1|@MzKQB7ww}?LGy2erijQPBq8@r%at1J+a84xHVVHhn zc`!gD5cJS+eP_LQaNm(?ImPamtU0X#(4-{^$IV=5Sg-%GWtW!xbZN<;`_ce8Cc(gS{MeoM5a&sjIEzEui5d`EXBm3|Z4 z_OQ(ZNj)s{_|hM5$&mp-szMQe7PhKR%x=Q>HkXyj5Vr+8$g-qa@hag&a;y6RzgF71 z#cCM|8sX11;oY2M-2(M-Ad4e3UAIfoA|Yt<*}DLTU*cAKlAruXg;V}kX{$-B8q^2Q zI3l4G%4sKTMM3QaSl)&`=Gv3MV44YO%e<3$wcl$QKj*nHvCPggMmZYWdZnkI*s-^9 zr{4hM>#T2MAKqSD_Ek?u((p~-eC~+IR01qT|U}{$B;f% zXX^V_j=vo;ejs(=mTF0z&V7-)o(Lk~R;U zDOHW+EJ8K>sg{EB=MagQ6*>6MkrO@6ObAn3&{CuGbP~Chi`Xmajf=Zn7gxlKG(Uij zAurS1q4nc!2+JzwnHkwF4iOsvp(c7dh%@8B!T!jW{M^d{HyqrYt!#izp>jx z6$s~&dEq2gg!AR(ohxXpL`Oobcm%t7ogm7MLXS;Q+VM^=D-%Rr(_~|3?Fyd3Nk%cf zFa3C1C^+O?8m)w%?C?NpjQkhjLmLnvXw$BFQYPJWwMY%^ic>t3 z;;RK!P@^)A7g@4!gSD`L>o$oJcet@p%UDw^JI-5ktU8Jc1(82JPON)P^X413jWHSNgfP&QC>)=wmh;$ zb(+j4js{cVd`)PGXbz>q@EUV+XG~)9yYs9fLiN1;9z3f9WN^z3Zt@$U=nJ1BE*Fee7@t-V;!n(lLoSte@-XNp z*r;3<&JpFc^t29@V*X?-t{L0d$Qnv?9xs(3m7EGWK|bR5&AAqK3~D{R;kJ48HCe(x zYd#d;rfwn+Vhius)gea#x+VvfR(FDef^)LaOY#7rFi*z)vR57yAM4p+9HW+h`ng!A zE0nX{qNFM|Kd*|p`#W)COd0NOwvC>P-n*+Uglb-BR#b?19%`?dw5Q?ZPpD-1bDj~6 zCx1iZ$uvCuTDA1_6s_!%KUc%0sSJ5~r0ARP#Mw0IARAW8Oa|*4$nDNc2)wzi9d}^# zo8g{Q$qC!+n;tHDLplFeg;f6#df!bG8*!^I@t20UT)LF zPZhN$$!vB%iI)at_L<$k*>cyeP0qg)E+8afOnblu(2EOA)I()AGi{hG3e{oP7V=vX zu-R8C>HvM427PeKL3#IN6>2}t8>;oEr!&IOB~F`LfjZENaNohguVO?FjS?1X6TX%P zdZ!%p+0tMQgR-=@zaC|O+FCv%kKHHLqZQ8hl9V4%iIIg_ub~--oAK+P9o)cpF(ji= zpjLUvtECm8htf!kOqW5h`cF1&(KZ^p^?p&DEMo2epB)>Eh`6<-sg>10dYEUE@057Sa5 z;LMM(B;M)!({}lH+r+Ug*91BxQ~KFXV*GDqnAQ-$2#cuR!0}RGwzi0rCYKMo7aa=| ziQ#*NlI6^AD@0TBuz9&ZL7y1h$FWd}g9-bL^{hdqMvo`44hAI*p;Pp#sRbXrHJEJ7 VP=ilYo+XMY?(ehqq_SH6{{Xl?eVPCO diff --git a/dist/qt-translations/qt_it.qm b/dist/qt-translations/qt_it.qm deleted file mode 100644 index a4b9f255963d6d7328f4d9198f40ea606c099483..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 172 zcmcE7ks@*G{hX<16=n7(EZlo{8Uq8v1Rxe-C}b#MNMcB2C}v1yh-b(I@)#Jzz@o(r z$qYq6kpiF?s!Sn6DNsC_A)CPvE+YrllM9r|0jker$OW300;Ch+DipvfDu6OMKr<78 Ws!D)riWu^Mc7x6D09wt&$Or%~nR+b04MDvVgLXD diff --git a/dist/qt-translations/qt_lt.qm b/dist/qt-translations/qt_lt.qm deleted file mode 100644 index 8a2255325fe0793cf4f3a92315f8577f1db79011..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 165376 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 z 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 diff --git a/dist/qt-translations/qt_nl.qm b/dist/qt-translations/qt_nl.qm deleted file mode 100644 index ce9f56f47ceb665095cfcf2df671c317cd81068a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 144243 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�~7U*8|=89n}e;CZH}Xcor* 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

g2sYU{8Ymb$8jKE=6V63@7 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 bu;|kuB+&J9w3zhY1U79hfv#U#Qu6-+3+KK# diff --git a/dist/qt-translations/qt_pt_BR.qm b/dist/qt-translations/qt_pt_BR.qm deleted file mode 100644 index 4bafaad2e0264b6ce5c6c65641d8d31323de1322..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 143803 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 diff --git a/dist/qt-translations/qt_ru.qm b/dist/qt-translations/qt_ru.qm deleted file mode 100644 index d54bae8eb3a9e66a07f6545f63f70d1200440d68..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 183 zcmcE7ks@*G{hX<16=n7(EZlo{8Uq8v1Rxe-C}b#MNMcB2C}v1yh-WBbChe7buehRG-O^3p6hUNGHNoD1cQ|0A+H3W+nnv gl>pTgG2{X52Akgjw3=6t@vkQLe-S2@zdBsP0P)Hw+5i9m diff --git a/dist/qt-translations/qt_sk.qm b/dist/qt-translations/qt_sk.qm deleted file mode 100644 index 9e8f8622d00820a7ff6a0dc2d3f8354063b6130c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 176 zcmcE7ks@*G{hX<16=n7(EZlo{8Uq8v1Rxe-C}b#MNMcB2C}v1yhzF9{Kv6NUXfZ=F zLlHwJLjh0)s!Sn6DNsBasMZiJBL~)#3zW$Ls?TJ|1)7%vq!ZyP6u>GffHFBiGZTTT ZN`PvL81jI&g3a#$TFu7D_@9M|1pvsOCJz7r diff --git a/dist/qt-translations/qt_sl.qm b/dist/qt-translations/qt_sl.qm deleted file mode 100644 index 2575b3fab4b9fe397149896279886857db16c0f5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 228421 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%0AS@b^#q(+D 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 O%mN|Rpu310ocn*<)lS3! diff --git a/dist/qt-translations/qt_tr.qm b/dist/qt-translations/qt_tr.qm deleted file mode 100644 index b0d14e9ff669541cc420372e28ef04b78d2b795e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 70920 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 diff --git a/dist/qt-translations/qt_zh_CN.qm b/dist/qt-translations/qt_zh_CN.qm deleted file mode 100644 index d6f3648ff65c8ff7392494ac1069c138e9e1518e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 117340 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 -%Bg?v!hW$Si;g>q(CKsKv?{cF@qVQ}dKKp9 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

U;7(6||g z$@iI_A6y81J!pC{W-;vO9j1c>>+be4(;;CY&h4L>4r^f7qVG4o(tb9<|4c_d9ZiIi z;ijXm_n^;%IJ}}Uy-n}?AB{GBF&h2PK5jbStO@+frl#+P{EqX%RnvDF;P1(?ra#=h zVQ=N8zYew~WLh4FtG01?Jf6c7-A&il7ULY!(sVr+`ti?Cb|P#U90dj{$Uss?+@unJ z8@%DNZA9@Cw!!y&HpfBC_?JR5n8cA@_*+l*ck{$c*%#C2csgI#kNKkNK&fU$)aDN} zyJn6k*V5mV7f(=Ssfs?yO008H8i_K7Dbj~3!Fj@e(*~BgD=P+PPqn*?%IuC(v)gHQ zm)Xo#PqE!;uBx!s7FvtS&BeAFdy&mNuyAl(uYo-a2M;WC^&C94%wAMxp5m!?n+t74 z)=FU2SnUrB7g^D+G2=GT3&Tr}M_>x*kE2>+O?VL`f8IN#xvk@aAHtt=jBx zy3JFauJQyXi(%G^3MxJ(Ey$2csyCHXz2l7@b7sj7 z6*@g`b6hWq5tEjbJSiz7V{~eAQch~RWm4KuOD;oIuYc;Uw*nAVBkaYthT&z_Sl$;q z)G@qtD4eUh{yw!C>G`wjdW_%P{-TI&%n-GzIw2w91_Wkhluim7uPW1HzwvP8rG_k; zv&0vSI@{)=YvBg`sy8}o`)8J|JTE~kb51oURaDf^r+P(9)?-v5L_|YU5xT3k7uqZA z?plhi&M0#_oR0qe*>uQPwye|oTPHg!D?JW-k=1Q?I>NOcS=d`_tr(7F%Z3s}bHn8+ zGJmTyPqn=$9Icj9&xx%J7N^@@;_Wyb%}IA=yd}0)jDgBHLunQ-Dajdmz2)Q`*%#;j zQ?a^KGk)$bl+-|4}+W~;i|W~-!YuFP6vW5%%1iiI>h+wHPJS}IG`+Km6)SoXH!1g%;8A12sqJgEt+p@TG6d#b9OSj^NQ7TRnMbFsaeTFGKM{Fc7S z9A541pnv}%SoJnXF`M4$5d>07s)GcQND{C^B$6Ja3VVo$loC5}pj8k2&51w75R^7l zP{drSvD{0ARI@N^>)e0Bh-qPi#8d^Yt)(_|sc#^O3B3|~c%{{&)afh^FS2YWwhk_- z5}VcSalyJW*$2pqt?wHNYhdAQiy&f`a~56A z!u&kTmGnh)gDo%4EFJ&+^_DPaiK1>!PBOb}cY5qDTd}#wS!^pZ+pEo$cC0~1X#&#} zhYkM(74fP7(~=TrMTK)J-2@m;=jtxB1>HjN&md6bbhvE}cYkwSBAxfPVdg!}R&2MX z7f!Ji@%?cAoi|mSUbiIwIAxX1p0@7zlm|=CP2N$nkS&T}9Wc{DUe{aVryUr-dGZeL z^3g&c?C={xbtY6-3bDYdvB1n!NRp*8HQDN*dmeNis_gR&63kj{a+wXARIStFGK)Iw zlMJ&$%p0h*mfNrrTsGR$tYs5iVJ{SwMN|~F+Wc#)p|WaBWkn}^-0IEmr7v=tY}`{wFjGgy>oq|6tQ9a`#kH6gv#0uBj(FXY+(}_Z+&ZZH z|0Yt4AxB+tx@IArvAiYLQIhe+q&jM>74~B9G@0GCRSoBS2o+a(vEx+M=`m&Li|P*9 z+#4>hdMi;@N+y1@vJM@l&2dy6z#>W{ao6>wB>OV`E&C01wBsa<U5wn@j^!HV1nzcF>uuIustyw7rm2d6B{a1 z9o6ub!xNm^PHZR7ad{%pEBV#7M{K9ett!S64ofedij`>jMl)q?*$8Tvxm8|vanh>! zswr!83=-w(7S~HV%#I@wHJ&9-j|1)kx0qE{cNsH{CHQ9tTnlE1^qGBV^Ax+a!dc1{ zfeMdwCh;VNbP;(}#rvfgilfbmXBZXnvj?b8F=r;nl{2-BXLgpl@% z_;i?|@EFmnPT2P3%*rt^tSm_{s`xB6`0#l8%--Y2GMsD)jv_uAzFBw-V`Fl+p(i3Yb#D(uYq^E2Pb*=LUB`^YOgM%wxyUY54xt>$MtT1`@o)P9DcCT z)XSwxh(0@$t`gP_)DfkMRBi6uwM%&Hm>}$g01754g@i~n(|>xkHihOc5wc6j3Iy6RbpQyyHrUc}I)*xU%Sn8(;{Q^VuPYc8yji|wOQ?2#A` zXs1IvIG#?IJ<{YUY5VIfMao(qMs5EHjI8Nd_psPpG1TR9Mq(vk=Hygy!;>^p^U4+~ zOq+xk9Yrz6Q!^TYnZ~pW>S8eLoN(CG!-#;bo}eq79Uw2`Fgs3oq6osXtET?k__5jk zn1?>qVf7y9BaKm=)$E?KfH~KUw!^20Jmb-nJH&J7CXpI2GRc6Yw5d5fQT@i~#V=9iqeo2t-C@;`anp z*;Te8xV+)V8=aL%=dWhrjQB;9R(6<`AqpubyS5U6cNQbR!CZm}U4&tXm?T6Z?>sSC zi9WW&&}b~7QSVsfbPE#sm*-&12|s8oKk0JHqbsSN^`{;GL#8cgIcXSD5=5wxpAe0oghytaP)iktlU9BLV5HbDxq3*|{Fz@ygf)W-FuGZ0Q< zRG)&lZ0sk(414%-YUh1lCqpb6e?%?OC*zvXSqanUy{W+ll4i9#^58=`r?P2+^~-7| zBB(|qDB<6ygW5*Z=+0cl#7mYQ<%Pv3(kF;`ZLkr$c+?RcR#hQR3tLDP4skE$d^XDL zW3jpE)m?_m>2?-5dAK9ufg?Jz4;q#tDqSr(l*{w;Je|c}6-iZ9d}BmF1HlYw!$=32 z(3bSxQY5KPv6Wao6>hevgto1Fyu>KBm5;DhFpnm*9X*_i?PUBwAJR%sPf%=wOO|YK zig}PfVp-AKhRR9=<3P}9#$W7Jo(g)Fr3)c4 z`Hs}xp=7CdKyMLfceJzd3((P{SvO}UTds(m4NI|C(|Z8UG_@&aXNjZ-7Tcn?9$tnV zZkMwnm?66;c&U6EPf$@dY=iSVWhG{odCE5wiruzO!%c!zQ05X3Vjb1k40!a3&Z3l< zvXta^%8nHYsMD;|?9>#6lQ0@jFaTVYyVoeM5Nx1MjHayqj%~)!C1xh zB;_!6f{OFV2R-IY_SOKOF+RiNMhqVl$r&&9&Y_qd;BdMsx$_h}ct)CzC<5trKGNP{ z!d!Y&4kFW3=QOhDCKpcf$CLG0HdtH4v!J&u0vOB&MbQSJ;C#SQ_*pC%K|b@ZS$B#; zRc6=1vQ&nfFm1`N`7MKX8&w*3@oqHO+H#!E3UTFKSC@93dhWVLq^;@fag;m2H;a-P zGW+DZD)=VivI|tEGZ)mTyE4@k%j5rm>2AnQZbFj#&ynBmzGEz4D86&={;38O7 zdR2%G9=kpL8#_QqH+*jxCJaNZLmA=$tN=C!G=vT6K+)bEIEeZ@jmRCh4DC4k{Ye`F z{K3QqbX#h3vtHSl>7<4kWSG9Pnq^)M7~;(h=&J&e6FS2GG&<@7{p-;oo9Tw5Glxo& zdWN*GAZ@y%0b_L8{=E`)4CTP*JpN}cum}80Rc;*0g}5-=hmIWgX6z1{CsgoIei+@+ zQ=f}%^HP6C74MHCt26uL*{54wJjX&meraJeYd=il7O3J8;X_ECDriu9>V2{H(tv;> z-sgq|wvM*wXas__r$NiM;s{mo7PwVr7TgcSFTbMeRb z>@0joqz-T0;Xs&!-a;Z%3jQw(^q4Y}3X!2Ka#cQvKxO#eop$`45rpAAu|utSUq?4z_R6}U*d z85gFH9NZo%`g$ZD8%T~a93cOeUV=E9de1XAo`qiBH8t;%~Is~?#wx-=xEWw`M^-yl4?Jaz*AlWq)2Cg~)Nm|b?u6{ZT(YhitIdYU<&XDP8ug&=HsxFcs!o0jxY z1vw^R&AO4ARD*RpmYC@gL!8N2pT<&6u#IIQavUJ24G5wp&$_m9nuw=hx9hwa`>Rj8 zmpqR9+sr>46{07+G@qlhLsg&`Vi+cS1cRw4~~Y)qf;V$w>I80@C; zNyRKxj0Zq4iV7!BcGYLHze_>|(Ro)(yNgt$X5Rp#j}%Ot>gvG`;6b|a8RNa3*N3j3 z^#Egjc)<0MDtLpik>{uTGBYNXMIZF#3VOX$F0a)2qcLXe> zWw#e+Oc2f(YefW{mQbz=WI~o9pUphqwQ&IJb94Z{DJj09s?2J}?gDciiIV=V6ATxj z2noN+ArdpNH}V`Cg|*oDysLc07jkaUZ~1M3OGQe zot1@7pX!ItstIZo;qoh}l`LF7O;DQ{8n8tyx&({ciA~v@-^-RK4$BnRtG~I#jcdsg z++*`CG8+84Y{8Z*n$ub1$rxDDbNcj}g(8h;N~7F{gtlt4t+I;eMTaNC^PpN%C&Sa; z(~c4o$;47J9tX48EKq_RMNp-(4o{5vDn)Nw9=0rzB!#!m6-m&z3zEv=UpcDbVtI40 zwV5eHdZ)Nx$Gq_$%FW6SMcYMA8c9ho-+?j_jK{jqKCvP-p!>FdTo}j-et@r^foRGA z&8MIDeb#9@9+8peeqz-&T#&e%uk|_-jUZ>U3Q=Q#zusr zKO&oKuVEviJFji*il0R$TKOs1*shBE0yn&YN+i&Vd`PIU5P#vC?DuDMw~!gbL^@6V zbV_V^;eu1PtGa#))LEBMhzX|PfX5z=1$I$DS(rs|Wf6Gc-6EI>5-psrV(&d?Sdlo^ zXKacj61=9VvLe`0uSn#ue`%s1WJzh1X+tKx6wHA;FUE4^BtzORBXT<=-uvlUSuiFn zy(($Dsz~j$@O4tK^;=1WNL7(ZcSFi3{~Obg=5Um0`f@SL`X2!V2mW3`{ONyso;5jw zB_9T1Q#ZQ`m^R=z;nUFb0bUP?UFvXIhahws@)23YSkkeao(jc=@)W0o9Y9o!NpEhR zc4do_o|eN~UcBzl0Mh4`S>5nBbCC6YJ7p&T4nFtH{~uoikx2fh;yRAgC%}P9-(!FOPUC+Bi+k!(^aP_r4lJFOc<-H8 zcna_UkU}j@gf!5t2Dz8TcofE+JPiz+3%~Ftn9HXpY%CCkARh%+fvR$FtMCbG!L0)B zOT-+T;8x*tFM?Y|SlGJE6oicO?8OLQvzz*^*F=oL+nQo6-x9NKNZE=!Q%dI!Hrbc)Z2N6`Q%N z;1PNiSYBMGo$O?rjx?CmJf5XKu@@0|K1lJ*)>6b*Cv0vPp(wq}LzW zcZ?lbG9=&t7ds5+Hu{naR)OV#m<#ddiA6^w*xlLiy@6qRZR39^L4Tslx};}Le0kBd z1Cl7(D5RypO0Y!aT7U33L7Ra)eLTa#3Cdo=6FT5R({|#`4w}N(;zq|E6}PY6Z1 z;ggdPl*Tj=#xv-d!I0(@>Tu5?&7luL*0TjeS(N$%{s$!?2n~Br5`uQ4=OiHr{I!o6 z?Lh$w$z1-Nqun2ukpEL2rTCH9*LudEa;-RA6<~PPNvCpSpkZz9WS9 zfB(EAghX@cP<^&BKtFGyuUPyqSiCCf9UT=$_<==u2NJ>nJJ?fYrY zuP8zh_#+C*IMnR%g!k=4X#2uOH4E4OHP7$J>(Xiw;IG7H&Vvb|D85$>;?xB_q6oo= z5R?sRr*z#MpmEU|h!A0a5ckrs+Mz8aD^Arc%uBTSA0`;GY(*3^gKjF`>_a-Al08&T za}~rPD6?q#0dqe?*s4EcKcu;mdYwe_tb#e3VOjqVsrez@$!RK(I1b$Musoo!-LV{G zSis@Le?_jq-aLE=Z63|M44$OqKj8RqMg`%FY5-1J5KdYHaB_lha_YgM?}Fi+rl(~l z&q@(RpvH&_YrU`c!Vjtd&lypTh>-xf2#Lf_*z!Sz6Th7olafu`7Lg<=d4$H{59kpZTmDMV6@?U)cxC{G_Z03Xh8I zRYPo!QdBOW(-fuy`Ib|g-xC`vhQQ9Uvs1XHGdD<@%7@?;Y6PN6+mnSy^Sg;;)ycIk zJ8Dv~vOVD_XOEOpPO()+Vpo|xGJp%bSgo|1>tQ7ZaeW)E^l6~pikc%<6zj2zjA>JB zHC6}01+Iu4=I*L^K`Q>?Hm9pJviRi%`gtFU^cD2NI+8r2$#4|LnZj7I(#!)9O+DN* z1xCUhi7AfhLhT_BE;P#mFHvdWd+cY`dcjf{)OVoVo*IW8{A$ zn}OX7hLMfZHa4q^#9*K`E}SC`L77)Fv)VOSq^-z7)@mfudXfWM#;a+0L=YK>@s9ly6o}gHg9Tf2vgBCY(-yEFrlF`fY_xe&lL|ffY=Br%&^0~Et)rDfv0N!x*vkPO8a zhzlT!XR$s+U$(b6B>pVc&sG>(0lCNRB(%h=D*%mfMb@ zu!>HBGZoEiLxsU=1la)1f0#07srBSD1=w+ z!W}S+^irLW0!br#liHX2R(Pa9v%<{!R_JZ5$ zpl(%86#Szb60dL>G?d0<1Qu8h5*y8n=T!vWT{jt#las-e23O!-%NB&5D57T*Gu_X4 zIa%xg+4wV>nCYV;OMGe9S?8BHSN4`1?fX;W**+7)> zSX+gV9<7TT#6!dP9f>6W?ZzWPz2VLyX{)C@TgbX>&2}np-CR6Y4p^l@qigL8b3&%# zRMA8O%K*tizJ)LB$)>ER49|3_9G%51&L?3gEV(gf7B8C8Vx#}S**buns6=I`+~G_8 z6s<=~T6vnLM=zd76(B1y=lcv@djC?xm@-kTTUk)q8O6X6U#5xDP{tzef#I(~<85p? z>sE5~5V^HMafxZQLGp@Z)fzykVKbnn3nL(x(v*dg$8=3tX-*~Iz9lk__9?&P{*^5Q zvO!{~R@1_t)n&BAuRo_>f*r#Lf9FjbqnDIW51L9U z!6PDtm^_ygmI(?#OFWwqr7v}}ccT*Af47x2Vp|!112~kPv3MxEV`j8S(rQD8TUe zEqz1A+R{HdevYviXhbjI$k&0dSMOT)AN=SyE-G2|a;~Zo#3@<9w2OcvT=Njpl4rX& zrdRmRtlWTg)r`|ac`_QD^K(qC(~ZedQURyJn>abI&GVD<`xNyM_U%ogArzG~Hh^rv z$tVJo?9B)*iyrU_Mv@Z3Ym^7Q!O>@?;t`!q@(QOh%{rp~O2N($pCguQ70uFPhZ667 z5*=YEq5t?QC<3AX^1demsZ}U)9q@`oQncHOa`miGdB8IgFCnBd`(Eg0zp8Du{MzDx-v$>jx-0pujSiR5m;oA~I4Ke6AasJS5Om89Yo zfBQpU?jT8ymk|kN%6mv!UnHqQg%Fdka6F1+7n`jv7q8$Fiq6DDt6@+ARH;Npn)`_$ zbC}aG(^!v0nS$j_36-9!D-0<37(@u$HLkwxV%|S28$G2cATL3P~PXF=xU*wD7X#iukXe^MwveELexVatO`{>5^0o z$s;sx{_v2|=`1xPln!HvK8K@|FKUqFL7ne89Gm>`gJQgRGmwLMY2ts0#uAVtbHb?5 z!gpatB%y+!T(S8EROkUO3>C@KI-V^VnT(Ns1i_-6c5?O#M~g4#s1J{Rg#(|m9muVOb7LCiPI*$qN! zj^}PxJg_%I8*!4Q5A3N4ukcq{Xqsj%GN)&o$9m0nr48?pycq_m)Q~4rhjto|1jUj( zTq@GHcTO@Dp9l#i7Q<`#(eL8WEudanN-&cud3G2zHr4y?Fr-@}ZyM5FG*BAS6>9U- zQD+R4y1wOP(2ImgmIlc4ScgA5)#tAMbfRkq&+MKenY-liAfNu#2+iNy3C{# z%l7INBn-s)eVZj}&sCXe_HTGen5iT{#{+e$pQdEX^WfsWKB67-I`h%u$wd!*O8Ycy1oV9o!V)+F@~0zwP^fN}z+#_)>t^J?8OO%x(sl(`?Z?;B#lULAWY3ti z!5cvJFX8lm$Nf-mr~{!wJHA##s~gboKXf;jLRZ?y^=Tg}eebC%OKI83r6}t6O|)-B zWau}ne1?g>j1kXQVRWrwyG)?mZd5u{0~6@*zc#;N<wUk)^= zb;OU@1huFIAq{TS>4bdA!rN_9Y=$;un^s2RVdffizK zqDi&^k#i#@V4<&~#QUs>$n+}(0pW7iMF;c(=$< zQbtaSh93gP!brd&@s%_S84;`JB^5_VfQ6O&kdTmsSA2Z!< zPJ@<~LbTUuuCTgF1E$7L##?^G7xAW3Bua%Jw(Ec@X;k3?B;1Tr^Ohas->3*x8~?z<(hMnM)>c9jE^fF|W({O_>FbV_ z0qnMrkfvS|{gzvO47cTq1=m$lDvlS53n&xUh0 zGlMb3I_^AVCrVXv=x2v0>cz2-2r}0#lnxupe+#mOWr^0mp|6D{r2r&FbXWx(?66M520RWH5Im3+C-MakSR_mmK?o-I zU!o8ZX#@mlZdBMOf^2AAoq(8{L^eFQ=Z~j_Wh69m|551Cl5oY>+gV zR?ke)@(g^Y@Ks`eYNA9qyfiYKCy+%bHas;pQIuK$oml_aIGy@Pu(%~9L5CGU=B8jW z{x~5g7(tu0w8S#~)|A6j#_zWh8ku#3_bAQc>KLLnJ6x9 z4RWk{;Ox!Bw|of8T5)IgGg22!jPATuk8}1rID8;XJZ~K5ff78eEJd#B9;UsV z&bG*ss{To?ryM%XGmM}b@|BLe28mrLvdfT$5TR+bCqJ+AM%na>Y~a!_7wEIyR)h{6 z=J*^Z`v63kv9NNM0iEHYBTj}9yNjevicC5+Y|+W-UL!KE;+0Ps`_e`<1}!!cKc*#V z;rj?Z!X{!n??>n}y(#0~0wKOCSP|4$2i8~}5??zb{b*BN_2k!rD#M%D7w7pG^n4$U z4?zxF!8D|mk-k+8*9CjCdV?;sv?fDPG*;uy0_UO7#+hj_`}UA{XmozdRVO$mt!FAp zNNLLukadouqCWy_uEym%s+Y1iE6qcR@;Dfq)vomTX}g;~(zINmF|^E5+ud|=BAOPd z)3o|K#pfWbZXRQDBOrlGV;WCJaM!L09C=?+4O$x*UTB*o2t06b@)UcX`1=ZO@)o=Tdc7<*IIS?^Apb>G@Q5^`sozGA z&ot({QjiqYX)7L~X<$k`MpH>t+juRgh*a5GfSw|P-V;Q#EVQ7K;Ss5{^_|KwO#!Du zdfh$V|CKQ@6V0nW{Cc_yU%aS)0%$?=fFmoue8|2$j$<*PVTue@XFVUuTd zbITbNcZ;`|3Dd^p05hi-VtW-fH$adPF&$A`FwRWJLD95wO* zxYb10q`{|BzY2K)tLq>@p+rjB`U!voKKn#2lc&h^>g`K-{%` z_OD*{V!R0&{Ml4+#(Q*N_8EV_)iTp-{FB)CgOl-5417=wpYU+-ub431@sqvYvb>mn zksdWRg1>*-!Fx}}!euljnL$5APn{xvF*VA4i@+X-Av;0ZVM~8!_~wRp3_+K|F~KA8 z-3Z@+cJoPFAbBPonuJ1k(ICogvuNrGze}K5C{*KFMk^fBP6D@9TWi6LBnU`P5G>gW9kUgZW-Z z`3G~OZt&phhTXK5cHL@~*0Ly)96u?DlWflKGDBIgYvyT0HQrMdmZDx9M>i_*7C76uX z?~sTBk;KIP9sxDu!N_c9rD`vtN_N%?XQ`9Ltb(z)NBf_?JrG6&A(_dNKsw7z4oux- z%peTsOG<7|$4{Nua(Q~1Zw#C^REKsm-^$6i~USL%YedvR3P-(9ZY>Ta7L3!z{mwo zHt@6XQ#PJ;CgHzS{N9`~uId0?5)&#WcS@Ai9iQ@G>AA@}n9J_#&Fq_FJRt&IaZYQQ zK5^~t-`_=V?&!_D??go}@;c!Hd{T05R(5*Ur0kreoYdq_X2hw)HDI&BH4 zmB@+{vyVj4+Pp3^RabK{`{D~dWR}=VJv@nkE^scO;I%~!PJ_Rr5}w4rHWDFZ*t(+E zt)i$Tdjq>_4Lbm4Tqs(DKfn^wGqakML@AlHwEl0fRNypSKO5A>HRLNUAzX+9$w~{L zAUVVG3uoLK*VvsN7MBX4!j{gzwv{1d|xIxnKu_O-v1}3$^eS-wikVe2a7f^2*n={@{%Yb^L@P8T9E@$(uaif zYA=kmyj7_!T6*Y4_W`l%Fh}KBetqFRRx+ACmpfoE|F6!d0YoEKi_FMKNw1n6y9+5mLQH`+CvV-h{6yY)C^MA?lS3cC?L!M>Gyzgx1 z-yM&DGo?JopS!OaO<&m;S*zGhdjyP?b+gWjqgSQjUIa;yqG5`X zsb3TcK@CKP2~i*kUjP>u5CL2WFFquCD4N!glw?68i_~}$%~ZB# zl3DM%yxGcbjn>(nR32LsmsXQ0&m>bxoJq~f<+8I;%5of+9R>Nm(~rOZ|NeaeN=a?0 zOq0Oh-KS5VK7HN?fvIDY@<@5U?;cOTW52IC!J454TN6dGmHi_JwAG!{V?Z=~rAm2B zUaacMeFJ;Q*&W1H@hF6G7sDL~S}0d_0R`fEE3!=IE0YV(GHYZEY_yCLEwa*zcYkQt zS>2T%o1DcNP0bb~o3FMwh^Xj-=Xg4!+T|sKSCM}I+#8XDUEh;M{R4P^$Co}}868;? zeTUR&I<1Q@UDp5aB2-%j@}C_of{xPEYKNTG4CZHNQ8NG)FhN!R%TapvN6x6#lAE{W znDocanCfZXrll83RXKyIX7f`^4yiGT9=RP%?sAfJHj6h(r3IN(2^y`k!;&kprdx$d zbnr*2jpOos3<(1z6uBf&y+2e-iJLFqe5L=Vv33$W5&dSoZl3NR2w9s}>65zuM|F4C zG|1M;WZS0f=%FQ8wLD=6O80!~FIa2ZLBl?*88ryo<|{+eF+{usD55C!xIskGy*==^gC$}A&DC{U0tgNsBsnc-{GpPtc4s*LkTg**9ADk@`Sg^m-sQxw zmDLH3l9wciFF+qX#Fi}Kp-5$O`MG5f+Yi1ldnne8C2}4IcjANORoI`g+0L}0tvUI# zZTw8|x4&e!L`h!6zgqC${*nXu8bK}*a21A*q?g=pdGp`Ng! zO;m%z&$jY2S$z*y+l{|*bpuIs?e%RfLH(WsyRkMQD7ti*i@2h#HF@J)8aa|Uy50DH zqJT>qFyc$M2KBpJo3S(jD7ti*p0%QFmw)M9vUDqUy-zP~z=$usE2wWhun$WUfTBz9 zc8+^@^3v_tHPKv;J-66h8!)(Z1Ae<7QEjaZHxitX7@7zs1q_E6wzusDXf4DF0i2j< z2=+I%?!`Y_TAKDT=MMsiJZyyrPx=TS+!bwmlELL6?GbQW0QP~1NFt9A$A7405&xeWj)cDWCW z8*GKZL@~CZ9Sn0{Gf^f$c#&2n(}s`5%Jvoy23UMTu?-#OJrP#g1 z#vNwe?q$~PLXo7*5bp*F(QU792eaNINayCgyDr6E9A@3_W!Cr%o8*S~$lthS14evl zFza1=c9BQ{K+&ZgX5H>#)>{FgVb)wwVcUQaUz*H#4@r#x6kXb3yzL&w+m59TznLB6GeId+{zDusAt@fAQ%qcqiJ)nD_BvAb@-)_BI_Lk`6TO-@Vj3(O%*(>vk`* z#%FR!EufQ-Su4=vm?E=o6=n^fiek!P*6m(q-7Yt=9(yPABy|`dq6^owgIVwA`^43Y zuIn)Cb}zGT*UWmaW!4IU=&I}5!L0X^S!3yXjaYej&(Y*ZVw?I>pYUEwa;?~Uf|QDRaKw8_Vy&&kq|}#xa%+WM zzU=TEa&5#WQ}{%b!M)Vs!g{2`3#)voVO89cL_t`2hohLt4EA)(Jb777{~M$uZ>kvT1x6)41wbetb*{a~6KT^~{>LUloiS(Ukh^CD~3vBPk2ztTTZvK3`qbU*T-Hb7x-i(*L7sMl!YEt zF8Y&!zBtyy@Is6ADyiWh0ffn@Ps~Cpq?l3~IP9#eir6)3_+?MC1UWY09GmQ@^)f2x z%?EO|nwmVu9I0#(S+7!!MA$>}CeVa2J@w*0>I<8htyUwZ(Ky1x4XZeY#;J4|IKNJf znn8?~1XU!jwlUlxis5wONjT=@px&$IK!}U%vcBucF^~4UH8xKk9=2KhZ%F#;OqI+! zvu=*hiU@Q1S+vc#@W9q0d?AAtdgEYGVLaRj7JKrM z)uZrZ4l%gAAV~O9c~p<|=Ji(|YHC1aM;f3X1|kS{9@U_Nl83=Z$aRn6UwA_WO;gTW zT6;3h9-9;JVm^#l`RL?)b{uic$pq1=mN>UxGO=XhR|Y!&?U{S9fH53g1nW|kwJ7ek zCocqHKnw}3#cW*CcLi%murDv1y=rSzfG=Lj5xkbkP*;#$Fht3YS})PY@-eOD7<*@Y^zhZo6G$<@T2Cgy&vmKkj0DL-vAWM)u`}dIxMs@9h4SR7H}jSQ0${ zO}p9}R6ByZg5k8dheg*7oN3feOoulyGU-NVQe4BdT*IPsmoZ+&iLt0UHa3k+jVbt~ zijJ#bF|l{fmdH2NAS{$F`xCtW>h&3mP&E7qhMtorr_nUW28H0PA?X3}F zM=;OQTl77*-nHZfe5dB--?t}@)!?5A^aU%97UmeAamj4GWEYQQhL{+@0}=9OazL}G7-HMyygs^VeI14GgfoPliwl!9O|!;*;s%ZD!`I-Qkp&Flv65yE)Sog z@+W#XQu@`VGwUo0D`bf7dgULp(0cnD;h45zG@cw%th3fIIi{D*q9)wZaR5b!M37P1 zrP)W(A)^nS38kX)!})O}`U=z8s9?jTVfM!i5+RYzEwNsu?{r=Z6^T_CqcTwaBPuxJ z`G*EV)K$r-fFU;|J^#?s)F;`C7JFrf^HV@m@gZd#;yB&0D-II>vVWn9+kbiXL*9S8 z*t#Rg3*fgz#dxq z6wW;(8CAuHFQpXtH@mcQ;2&F>e&30@K!pwofhZ1XSxl+W1s8P4N|CiL{D02LSAo?* za9PID_k?BAmmi%BaOTdfdvW=H`6qxg!Zv zcA{jwvp(n?MdE=X4+tAr`ASqu!j8s|&e%1Y4C^TBdd62XcpI{K9m2aqKlbXbx@p6i zd8UPMmPQ`4a_2EE{I)DTbz}7TuoMZt249KT4IEUJF=5%+#j0MUCVQZ-l?Z-B+_NCZ znYF#^Qy(&0(O%$&F!~SMnZzTfi8kpB zy)d28J53d*IQz4+kLI1%K%*oWn$FCOs`opJr|OdfJ%7%Tk;XJ^e?ee%OB$&wF`H3! zJ!0cImVqjfeizLBm+_=TxdYKo7tuKaQ=br)hY{$q(`XYNNIqd@%-{JCf)$-&g+V=X zlFkc|bJN*JjTbaJdnrRR?a7oOffMO!JcV^680g+JGZ9TKvGNWgF6U-O+vgC&HL2u@ zp8v8CKJlv#k7iXT^6Ks$X#|!@P5@XZx*p-74aP$ip2%saYh}XMpaR zO9%wKNZ`u5d$Kv`WU^SGrhryV%SRsQ$)HVc7Jm+x1d$0ha>DU^{(OebnSArmD8NR9!b3UoKCkv3J**gI1?6T(Xr&terinMefN1Z z0XyLYF5hd4803f0zFS#J3eZu#@MKSOcW&Xwx4U{m584LAUV=-2IU#Qdg?kZrTrjfc z%=*+TXMdFaqxtLUFW>&=i*=SRHb@nE$R!eSH=M=zg3;A1S!0s5?a1{gEF;nML4Igx zZW^YOM7EJGCcb&&$XL16e1y@X{ ziB$D-dP%567Vr*aRSHW_nq>nM)YS16P>nu3*3*ELEMjxJYcAv7{PQpx| zjtYDe-8~WbW?B{v#7eCu%vHfF8VRGXKu(SgoHrw!qh6c-hsXiF_~r+(D)*bZGAL2Z z;CEOK=U{X&#qHfAa^?}lG7pXOS?1uR=1L(_wAxaW3ehBhBh%b94JS+_Y0e~Jrzek- z(x3@Af1%iR?y_WO0u-g^-oE^i#YS1X1VMAjs&1GVp}4naR6KCm*&jv1?<+glm4xoT zq^~Q^tVyjN`YmT`m8_L6r4oGKS4F-rm+zHt${Bn)+VL-p?nq;Z1c~N+-(4gR$(Khgh}*C@C5iyM$|rOTOgDrFQ(Iw)IZTn zzrOMUCyU79+jt~1mrx#ZqH%0uDi0+<1ZAC+5oVh(OX+RLpGQqy9IQ*q&qLnZ*(-*kMa3;80gb1NFEf2Jt ze~n%)?goVv!U@@8$h$?;L4a+5#u%7K(4PNh?2;p*h#;b+3+bDtBwKZ%=#^hq5q<3; z)w++W8kImMD@q=-$iL??;<*x>4`#q2ZJ94aXf`Su*pF7Wsgm8X&r09;!KpC6tdzBN z5+>V#;7&H~I**WpDfwGy@~Pw)X?d0~aIGCUi(#Q}vYdkui?9KN(Q+GbLfLEbM z=1kC@hx;_)YX#X1;0h32!9HN&8x6=X(o{T-ZCpX72A(VlZ99MrgHDQzFE*sK_oeht zEnKCCb&N^utBTW)^#3$Mft80dQ!@d~mPx2B{Jesnd%iAX0bD2WyW+5_Un}9?F+kL} zVXUmcv0bHyXQ#zZ6#J6ll8CLa z=v{e4nUi9l6=``BA%CO^zBOkjEADZQp9(;_z z9J}_)qccMZpH-{Ra4Xzck}`a(vuR^6l);qk<|wQ@rqb|ZpH&R5pTCZ1y8G?=mB%vk zdDd`~mm&5!oEC2!x1W|C8y`y~{DG@IC+t_{$V0x6nU*IxKHbpoWdC>jVcAm%sZx?( z{JZ3u@3F5cN}j@vo^V2KY{7}xm(j8ml`Knv3W7?>iG5mzN-dKmGZx5|$5k?N?6cCL zKXc65W%vkQ*@R=PqM;WC)@COFtEwY|N;{)LeX~S!#b!1mT9QVz6dTc+G@`ZGh+Rn| zb`=|e4s8}Sb|1Tojo6bkVo$LVdy_`&EjD6b(ujSZYyTwd+C{8#H6 zasq{h6E2kudhWNr^@GTuYBLDVs!YNtR;eTSRI4#P*`a(Qvy~BD zXU>OGm4+*gtn-9@c)D7|;Xsd81}SGOcF_Mqb%u_8xuQ3;^RGxrAbac!bPww9i-ay&EBXeo1Su;L*?m=X(gAw1ry~JZ6*S32BC?dN$|Fbc z^Qy?_%94~QMphvXID?#w8Rua`0SVnoFNVTue4HzgY|FZGK1k$ySD-EJ%6Y+)(xH*W4 zq3mAPgE+hC#EH`%JJ)=bnAQ@et)Lw$LVL!j<|B}T0aeO)<@vsJ_<=KF^^~%7HZwhx zv_D+C;s4tr0^c!UJOSV;gdUILJYW#AU!w`jSRxlIgRSL?i-t6NPAAM-I`H-0D|Wte zbZ40y9u&PicEY6*PEzXOA=Lo#5-68P_JWf$NA*@LJrsB@WZ+>w5L}$uwV)ZFj{`5jqdgqMu3Yd>ipsZiQ&SmzYKmFFfu(Ma{ z*%N_TF|yNsxbk$OO0blfzPvj3(03=a-Dg1O z^UO$66^OgrZiRW}_0ZN$vrsW^j*sUrz=k(?DM)u7ekMJ?N0%Wky5{DvI5Ss2`!iM6 zjb2fEwsp=*@MKR(M+4nuU<#cFB#K~M_<(nB8=~t(Ip!nA7uO5$BjT!8N zHWVm{3OB^8X$Y>$d>4grQ+RG>(pbFDgGHt`(LUZ2)E%C~MJ&;6RMVSkaVSw6kuJtHHMDGYp>DLt<7{wyk5rJO2aD{BkLW%2WR@uWRJ;f5BWn z*44xNnAB9obAZ)&IeL-S7eokob#HG6ygyTjsS_)S7rx!9mUtoa2(e4jP5t#n)^u!! zMcOq1p}U8a7q^5A%z$E4)XWgVse|T=%1Gn|p!AKEXVzO(mv-1ly7bi8q-kANI`Z?= zo5PPz}1yeM-d2Cr!({Dvyim?k)J!FblJ%% z#3aSGmh`TNOK)cQ#+(1_n^W}N4E<^6?_}P5^>~aYG~f{UCV__L@w}s?))4a$M#y-w zw$&FL9u2zwC)~6%VbP%ed%v50N!c)rD-tw~7CTOBhBP-vxP+ zV5qnHe0C|=hvyI&tgwSD#$hx`JfHPW%<6GW)Z^)TCw^EV-t;~gm!=`kQTs5niL+n& z2j86X&isYw%u^^eP0}esG8?0DzA=jYyqZsS>(DX3zP;(AX5)@UiJ$;3K>(m;OQjKQZ@*Z)*4W+pqH9i{ibuoM|U?VzXy) z3Cc_2AUBwr8yp`SDuxqjoXpT=M!3Z=;*@+=1@;)6=tId}g-z6SD^)BF(QpcGL?zuW z5#u1c6OSkPZ1NO$?Vv9@&0YBDljr%=F4*MhblBg?fk=BVCpt|+NWs^fmR?oey+_hc z5TexgX6Ua9X|%-T6slz#MmG*MJ_XEAp5Pv11TF7|;%tJ#@VO_l#~M>2-;-lG4eIBw zGcdhCirNNqnhr{5j5G8l1`eyj8@AXs2?fv(O{J0Lr*+8co8>n?k%WuGPQt}1s4!Ea zpj3DF!Z3?Re-@E#^3+tn_PtbDe820tf~<~J=$1UJOK=n{GVq7# z-<1(3BVe7J^o`iajerumsAkH@4rk=O+)q%40J-zDQQE?^39$A&pIR;B-OjqDhv(|V zZd5qH>l7{gRC1#t7O5)Th9ire%y)3FCD5(g$6O0616Z{ z@L}!wVd+OIRoWpj=w79E3H15{-Pksx45xBMa_Kj!2x_M+z zPUq)T*ncSxHvG(-XZ*8@#RvG9EN-!%mLHTSL&|5WufsCoMc0PaZRotpZz#5Q_}K=^ zn%5ipR$u(y(BJOa%OnR2MWB3<=nXL@GCrjyTnx!~Kp?kDB6Zr$0X1(Vcz$f>UaETSw2)01zRuEI%UQ`;D{tMhX4H%Q=`GW_vT9 z!qQ7^kflzTrJld<)+W1~+K!$R0l8E-JL>XEpv2M>t37m@iCGynvWJH|dOCf3V4m@` zPL^DHrH!g~M@ca7RQIn~XL|IY7>P3|V z>5qGw&;F?JKzdO3$sULt1aZdj&AUGkE`D4V_9i?OMMGpEA2 z@0^RxzWKSnRAhQ~-@BV7Hp&ud(3A$BjK*FG0H5x1p|`GEKleDkmK=9)e;K(OPi8Pg3ur|7rOt2(7vJlAtD!U^yNr9|b#N547 z-^Ma>D>KH1ZW?%@>jUZ;r~WGYr58`VdTZq8SF2NvPDn|eK#Wkp%&&5N6f~m2K*>P3-wu1O%^oo*oFdkKCx>iSu zwp49Lq9y_l>yw65WxxCEyFJZ#HNuRE^)PU=oYD~$C7PKQ(JH!BZEDT6yckiR60;V_ zlY6(ws%Zz-pX%-HLcXYV*hHr&ed*4(eqaZbw&%yi02cemm%R}EY%RMd4gTl;zH8;# z-*nRH?w72<07>$&)=dX}W9Sr`p30(4fO?Rkvs9Q_EL3aNc>j0Y9#3BM-}{tH_d*C3JefUk5A}`sf5od)!NT1<#P(Mg*zyv z>}tPUd3a7l*657Ll)lwyzbQYG9mycyt8lIjwAS@BpC3N?o&LW0>yaG4FBp4Wo?-e- z^P`x;zh2PM645ndbG?4yoe+WtqjSv|p~pX4X{6OeugjuJ2lQuw`oc_T4SEyV$+-X#h!bU?c>grH55LuCQB@8xcS?K8qdP0j z{tbu6lpRM#>zG7XMnBtz7d!)3Tn5^!Et6IfygJegsbPBw-Z|Hn{<){o^&I|wR7nfk z#$owHM?GabU)HQNP$$g#d1qEg;N5m4P%&xhs4zl}1e4kSk-Y8uK((I;l}rC;~_`Q-lR@9Sw^xQ|_+(_en} z>DbkNTh=X3zd+>KC!ucPu^oaDE8x`N;&1R2v2VMn`P& zx}_(_E0w_bH--~4?x<^ZMCIG=nU;+)qk3QTtZJgO-srG&fNDF5IF=cg2_m`j@+M4X z$V*GJXAWrcXw>b~C3xy84N7mRVA(LF)07h!=t@2hZP}ir9}5J}Lt& zTulE(>ernoBhnX#O1_RN+o|OJ*icDzE)>DogpghQippOVG?k4W%l&T_*eVG!6s@I@ zU&-fDNlZTXNn)HmDv8PG9f^_{7fABP*GR6* zky-SHV)DxUo{5TXDnUf?&6B*b2o)trC9&;AgawZ<5}8sFW<*kWIJ(iul*=Z~$czsb znK2oCYo#=4p~2}sWENgnuF6c6+cJO(qh}XheNVh~l%sDW| zhbPOffe5L`Jc>f9phYSRa7qLR<(G%dZ)a?9558(ZL9yBKY(s$W=Gp94G+B)z#wn=BLy0`z;TXX$=i<_HE?0$EN z9}upHaVv9 zGx+&sx`s!#!a@EjF?%E~aO#Hxe<Lp3VuPEI0VPSwMW5A&6dkAJr|S91E1 zbgfMOtOHQxiA>!^6vIS*J(27oqaRSly&|R9UWsqwL{ToWPy*Em48eo~yqy zIPiz|^JL?&-_WQ^2(1devkheteqLX{C)n-Zs2rw5)loIcO1^5aH9z( z0+(mjQf3_YDDoRbSc8Yc{TB%l6wBeWCpz3uNt>nJ&rYcDp$GcvPuDK|xc^5;1Z|wZ z&PR-Ju%y4!D;9JA+iQi>uZn3^=O68VHmBa$ctVm#7&B#Mx_zIs+HMw67~ zt^DMtT^YeF(_@23LksJNhByEeg*ad_QI-ly*#B-@QuI@Ay!Mrovt>-^03}>krB7M1 z+M@UoQ~Zj}phfaUY&*;6lEaKmqGHmV6;i{ERI{XL=1->H>+d`NzMX3WvI!_}vY3_T zI?+?u#2b`)g=Xy3hp8%Z6?L=h6m=*_Mz;pIhA=YiWGH@l?xr?sxQD8Rb8q}yA>A&& z0U|lvDd_kHXDJKOD*tgfDDZLYSFgtSblZPpeq8nZeJ>5C)|_z&4P49PuaDI>WUynTF!%AqRc+WD&GS<9HiU5_5;= zdheK<)c3mJKI0Bwm}aSd2JYc5Mwi&)JB8_|at*J9VVJE5Uz2<&LymX*2yQUXFK(?$MGC-#h^><4;jToPf>+;}`@w>_t#Dy`!^h{{ zqILkqYfW#(_@B>THw-2=cVofa$&4lNu2i#F-Fa+e=Y`ch&GXksc9sN|j8``VV6j0C znK+LSzi}9)I{lmPliN7E-PmS%GhQk_#M$9Q)NLfHa4>RIDG9)JrrCVd2w-Z5b9n8h z*c3@QO5(88vhp&MPcOa)T^^RG1 zBsM>B6SaH=&K$b@QLggz=HK3=99hm}4;{UT;=2Y9D0XN9S&V3vJgcG4-YcNY%WuCG zL(Z1tA-MI``WI4piTq1N^>;^$nWa4HON>R?d+s(Y8+ymAfQ!El!*kER)6Q5F_ zGwTCpR*S+=)JvRft(lCZ)kXx=8LUgPHs82Wh&f&z;&!)<1!yXApf z`s!KJnSd$n3#6BV1lf6jaH1T= zvfZsI%&e{ojP)ZZ?O4EBlGwy1`c|)%vn}EL^-zj&pbzM8rNGHRD+m_+t1H?h!d=6& zrg);5t1}&XJL=^9WpRp{uDQtu_?I9K63^~L@KCzq;3cq#S<$8wA%f&%lnfGdPqR^= z6+WGb_w-oJ1zszwYv>abtl}ucJLRXm&1xlA#wu8CYh<;!(8bjfx3jgcUWsr@SIbqN zd!y&`n0#x=S^RgXWUI5Gx-^4bp*9AOoIQI;y*7?MR_qPiDl!%jpZ>|v@2CGc7Py4+ zBq&umSc|_;mgJpfw!)%fj2xMvq3qP`4DY0Jpx_>qEUz|C=L|>*O4o=Nv z=Z5pnc}}1uc95BxV!Uc*ggO(=C-UO^IC7a1=~2@r6Cg0v?;fPWdkHYTECHejvVA5Khp|K@>1yM zC~>;TJH((9#B1Q%^Bi9}=}h`)?8#9E0Ym|tFx8?DfR@Uyl?zJ1{@5mxdMaJHT#MZ6 z%pqsJ2FQM7R@>2-H8YDchCDyDnC4;9nh&U&%*w{rbk9OQ@4}Tvj}X-+NU}al0;Zd% z|6<^dJz10qb{e!!XYop-O_szwB+Rl~iK*#Ty^p0{>8ocMAth&;y>#c){e@hmJDxcE zILfu4Vr8J}qld_B78eSJLTo4lJ)9j?LZb?|sAJk8mKtIO3Va((8CBtCdG?~TXOhf| zH;xbe%fTA+v*r~q?7dpOSk0eKy_f!7_1)=f27Efgcnl8EGfMD=N(2+2beyAYttmK+ z2o-rc@{wQ6m;_7If}R;;XY=4G7>Yo44ZyPPNhDhq4X$npWAp8bi!)etdD*>PaP0t7lOq+3z zqfm>au&U&QlRd|MsM}`tYxWrK`}v0l)=5@(=n&jlu*br!LH3dBg=BB>7W(&;S~Id! zA@li%a}8{?7?ZtGM4VLPXx#|RX0l~Am|)EiD~>0uAt^1S301e``GKCjBx(m^DBrDT zH-)TcP`-U4BgE&!msaRUc6O~cX~pWII}@WyznwT_vgWG#X4dR4L<)#l^KKX`n%LKw zFNm{_Mvs(dqM;LXO$OZ3)Ev`#640Z`imMsZ!Tfa|M(hZ7tG&2u5bHwL8CKxXR?0@l zO6l97zNX<0*&o~4&(?&sXu<|Ra38yb-8`kJm^0I?sfa4v*ZjYK{yw!Y3Jf%2;CnnU zv?js4@v7!?yBt`aD})7)SPpsOvVF>h&hA|sZBuX@tzsxzps{y`yi4T9h9KLNYYMjS z@?mFdxCaHlfs$lPNFC_3Im$g1Sws>`z&f$2ZyDzhddj{DJwJ8`5u&;9 zNh=d@BBMI9Z*GT#c?{|qXphcXNK~?Y^V-6DjnE) zDi5v%lR1P~3L%P{_h83d=Zx zp8uM9F8F6utb3Zv>I*c24nd~y9Ig@`)9t$&j9f`fJLy#DTQ`o>^B1d6{ndH2)x$U75us4w(8m`6A%!pm4*}b=$T^1u6ClwM zEJE@zknD)N-pXeHKtfHYLq!W8zEjtTgBO1@Z%nT8uE9D0ux3$qM_`&j7lO|UlJrbL z&N^~Y*-*g2z*;PI0i=f3zep+dZD|8t%BeM1KcQeO+X;PM_qS0#l*2-5D({6Bfps!d z!m({K)1^LClOfskxrlG%!GcLi9~YQ+30B^qC)!6qJtNVX+`*%`RJOVmL z#aZ}lNjHkVW>L8F63az7csR%fwS!I&!e`zXl9dcE+>2sND8xV8J(r!n(iboP z)zo{2W}t%sk!*(KfYIC*7)0QtSi=d%|BEQKq=OEHtB>U-RZ~kpDeWM+6CJlIUcAF~ zo`2}dk>(XVz?&}*yqkK0|K`KvtbM8t0?yzxGMy>c&f&?`Hv$qwmJd55-eHZU@k ztgic*!Ce47YFL$flZV0}Nn```8Jf%~u|;G@k&JxE*i0?w#wbxj5OS5YzQ$x=kjBjH zCG^=E%|iaOo0gSFSqYD#AT6;thGHto1HEfpBBVS*&Z=Y*t4CrrtL32Ds)(DQ_))&= znl1-X$6EVI{Ji%R<;IZY5p;p09@$A`Yc2X!*Hh{s} zk)7m-=T_$KL}buQZE-2XHJAuW)DblWIJ)S03D&aU%CNa*C|}A!No)@8JoLSzBO|cz zG6DeIbnv=PQeB>dfJGC7hY4+QH_Xj~2_*skxF2wJn%?DoD<5)Krl?L*;*-}k4@9nJ zvH0c{M5!DHSYU1kZCmGuNB?HTQPPzFnNXQ|8G#2_OeP(Pe0VH}B9u*%w;_a1sl!yS z@WC4+L_R3VglHZFmi_(Igm@_Z<-UK@dE(NqiItI^@}P=Sw+AY%60#_ur=H=%ihrZ{ z#Mz&{{`Kx(@uv>|d8#eA%y5+a$Ov0)83|Df=x7d$294m$O%%H(hsNg^KthF!kA>;4 z#*chhfiG-iE&anc-{^Ug=i{vXxweVHvD_T`Aq3Op&mtB3COXKQZEhYno%%4U(M`Qa zz4L0de1q*K%9w}RCb6ByP~UL*4USr@ShSAGu{UUgp==i&{d}+iwd6N0gd|wamt1G% z{`mUx)LI(5YkstwT-D`&e11Z*JO2R`M*M_d5oaf%$vX#d63`godU@0s9EEKWMTxaU zuISeg4O*hXQ{qF?)+9zv?*g;FDCRhTeUX6KkOt2^QBDRt4+uk@WyLTZFX#gxc0tWc z!J?wh(k;tbTHXq&E9!qL4sn5Ze@LF$_1x5ZwC%t9Lj)~#z4*uP{;+uk)uBa+<}gG( zf1U3(O@<3&4nV^ZfF^083nc@@4xj*u)V|1oL#e!VXmZ22q`gK*LQ)5Gx)7gA)YG?D zv^yWls567Jl60un!B@^S?Jk~{g4%&|SDR7U$WO3_J`TlGj7JE{jRDv%VD8{zTq<0s zBtZFGAr@H}K*ePA#@Ow+@`Db1@qO2@uVc79lb;G}KEm3@9bfMSm{K}EYBlbvS zck~Sa$?Tr2HF}!B@o(Qbw!&d%&J3s%7nZyhq|sC(7rpuNPw~}FieZJn1se6tQFVNoPmGih@I^zW6OAR3kF_`Qrk%T+i%5?@udhvED%qn*TsmT zHtT-`V8d)aPxqb=NrB71Lx6OX*UmC}l_ut9=b({N$uV!G zN3Lq(V)jfBH%DI?z0m1eno6eL>pYlB@m+ss#TnP9do;2%7y z*&+6lLA@32h84pFIRM%M!KgCtR~(MG7$D2_kT_KQU?G2YZ;{pa&>5{j1j4I?#_tg z@Kw(>FORj>J9iv%5BEF>+blw!MVC`2NK^n+Z6=+hQ<$8BE~N~DCu#lgL0_f9hGxGz z{l`{=-gtOydWa5Jq`BBwArEuglB-C4V&CaTTCTDm<{nhn(%I#MM=~HjF+3R`GCjK! z@Y;_Sc`O^k$&6NG7Srg4_&9RrHABh;H@?;@z6MDgdU~kJfZ1!cy0>S$BJF1>Cj$+ z%^yX7uMt=QhhQEWLv^w&(9@3U+Ii_*l_{BAtR(B0V~EpO*XqGq{;4ub(!VRDRw1S( z_C=+cDUb?h<20lbskHSu+sgP%KA{EyUjwf-ZK1q-OtseGZrVN~VJ8>zLIHHRXg8s7 zK<_i$YGsBZq779dewTXYw9ETCj~b~!Y+uU}aNG-RwID5A_%6`{A&6wcDh80I_DGIG zQxq6-VQrms@dW0JT%x>JwA>u71&KpeQ(BaBR)J?F(U*|7=G#ZX+|;M3Njh^s=FE); zLj*A`Ze{3O#n0FXg06{WEkhAKS5gohxY=1ot_#HSY%mTto^RH@E@DE#-@egMR*ZiW zKB9R<4M9P1HulB%it2D&O;neK%ovefBA24+0>+6RjOMI}$QiL$z-vR@)=FG643KfY5|5RmdXc6@D#UlbgFSTZL-%MY zmxKq(J*5WJ<+MMAAff4Rx3hzz*g-aAQncDlx-qcZTN|i;X(p>l(j-qp*e3Pu_5nFc zl)u_-LQ-b3j zg$SzMHwFt-QjNKwDd-Z{4&PAvyTf021j>fK`j;L`*CNJV982`}r5dBwGm>M>`}pPK z5RBotLUfz5QaBDLcXS#z^5r+jdwf0C;VVH5KLu$KNP_2FE7 z_Iu}la0Z?W;1-uMwdO{L17~Lqzi2fz#Ua0;#PzoaX>)c@d4iJ13Uy; z6c2lO6^~?rfx%ijgqYC)GWoFc{|Yx`HLOdCn@G5rVA}4k4Ao{#Kp*)F6%G}55at)r zoq;!C+1q{k(`{F{l5dlvpLvs--{|1QyWP_vWF6@cDRK~XQ`Ifae(&X3nu%O>OzM1<$x-Yzo z(LFhf>_}dOiNLI);_Su8*J`*56EzgRoVg#t+!w~ikxGh_2Q9nkGU*#Yl5b)Ne^)>0 zt7je7?)m<&U2b~k9PBdie=(4;=l8m^6ttY>+K#ip71weX%Aj?DeWzjW603e@67^?r zQq#eC9vh^5@p^d#h#lM^rDbc!kqd6a2cV@I(~-S5`x1eXvm=FQ6JU!I5GrTs6QyhT zejyFy%ROZ*an%1)yU+tCm}kQPLmU?77b9I3E+fWjcs5jTBA$5pVJpCkzC;k)i4!Uc zN(DE~C}Ah!7c-B_XNXyA`0Y)f=JpF{FfM(@+uvaAj$-FwxPwqM&f1)Af?*KVwZ+~j zc1YKfupHCip{OY?^{g=sTE)Sd;$C>@cGu}gJm$F5C(r_6Oxcp4g_EefHbbfpyW)1a zF;tgF`JGG4wapzgDudyXd;~+ijU02aA~kTPWn|~A|8cSU=F9KYbU#IFT_k+1GiCE( zVz1sHD>EzR7SvPl8Y9nzUIee8icun^H;~c7H7AT}_)#ApX)wT&5iXnJPlmv`@s|I6 zD8K5;-+lcfb^&(SSxqWC%N#2dRh-CzvV7Y^_Pq+`54{ECQ_f7SDI|Vr-5sid<&G*+ z6Fx|#tLbctq5)kDp|V^M_hh7FELCAu)?z4gh;?DK6V`aY>7mij@Ew_sp!oi`jZuZnAw;a_pstk zqJT%D5Y|KyG|HJciq*}TmL{jk?wfZ4=_+^^B;ogn=y7|Rn_LrF3&g@`uHLo}ox zYLg)xJ^-ZKbQA~zz|C1qenFPi3Til|rXdf3qFXxo2B?OCwwaO~d?1;UAp7ha|3TuZ z9$KvC+mNeNq5kUUcFA)ovMy~6o|?|&kd)};j*9T*u#jHkI;AOV1P-}D^l)?r#EnHB zn77iVL0g`AX35z|Tu|mdyfv6=bk1V0IO7Q=-cskqQrhGY>NSv_c`WeIAPNtOg5!Cw zv0@V+bOvy6_0a6;toNX^o(-3xO+(nt3X5b{7|a5bW}P>Y3CZys+27*&Yj;)ez0o=t?}~5c6ZG z8Nmtw86OyX*+{qhupte;!?X+8*BRK+5}7!(l>^WL<`9aDph_m?!MLrEL6H$povWsZ z9n9?*FK}I>>>FqkZL|uFhUyO#i1u!{*7q)p=r36mX`j zhcO4v_P2K8d`A$s^f)r~8HxpSkcz}(O(=<+_V9&`g|j>JZVTrU2e5Hp)U|MTK|=l;N17ro*06L~4(V2nNpct^uZ3D!fwWyDyFP#YSO_y-@$*hcwy{(9f9 z@O0_itHt{V?wC4quxGmA<~!M^5_w=KwT6P;V~}APy@P#kZ+Sv$%(*}Iiz{38qR>g~ zq9|ZD_*Jd1xJ#n8vtCjzzpSNd+JQUM*)u}L(6_z)lxe{aTUBm8v&~P9_Wh?DC?Slz zed};Bx%PY{D^Fv30m<}ooVm)+oOJ4e;@5t%8pgwS8tGV z_cT0#lwiCO26UH>b#BZ_ghWL$Bjso>l6@ApK_DT94~HULB=GzISF(0dqMEW>UR;EcC|l*%#r4xZYv0E9yFifQ-GF-)mCOJ}0Z9as zf*2O54iyK9SkM945K8D97dMpHgCJXn`2b#tq|OCQn}3{e_U;@3bx;5w5&)sL1MplCB;%pluN*b zdR|_f4sxrgMcWdba8QDBMahJQrt6T{;#Iyw48jT>tX#=sq{Sz!eP`K88$rTV$tYu^ zW`+tL6@x-Uq$XpNEH{fW+5_hmAy7P%sn*%OU;jV__}L{NmL+v6^$;X^<|ASeVP-nC z&vQdsQEj)OubB~j>KJIr<(-H-DOnUMrbzGOvgXW%|1;VNP7TJCkVWOeze%Q|Sqm?v zKi-GpE_?m}MV-9LMdrmNvIqYpbq{MkFe0G$F*f(c-|A8uZ@w%Uina)nY{Y#$ZwjE6 z0^G>hFhSWIMF+SX&d1a`hWvo5-=OqTZpM6vgn5(~nL-f<#hv9Yh^t$4$%JAxWaD2t`9^Wn^;Uf7Y%PrcN6_h^y>-PL>#o*JZcXb@u5h(u@AcH7wX>q zVL{;X=VeVK;7LigCF7I>TExtDVE+8V>F=j&uaz?ZVg8q$f796vnjjG{_yU>VqXZjZ z(?)lQgoPTT!@U1GxWL0gx4pA!{@a^nD6Hp zO{%ezS(Zn4t=u?-O?k3Z$?F$lJbMq9*L|HFPN5u@N`|){U`a|NGxwcY>+2s4yg7fJ zA*-p9^I63lDAy0xrhiwZ4HGcNTwh(4dgkr7oC7#dKp4Y{cP~4|#{r>j83euwA2m!? z`?QoQ0P2ny9fWu5hZJOnf)ZmFXBm@eOcb+N0-hot_#2J0H?gkL4g#p+*#hO<_0~r6 z5Jup>s<|CQ<>)QL)~SW%-Gq}DJe$z<;fDuDr&E3z_1=#3)t~(tL)9tQsVIG-zqfj% zJq%@JDLz9r*UI_!U;fC#=@RO5+`qu20@&%bLP0GjX21wBHkg!O+bVvfE+HtMf-4w! zg~MmXDmQ{RWLlY@=_Q%J&O2=~4z86;5f1zWA^@UaRk|<2+Yn1zXdAzA_VUZAR~({y z)$R#*-HGK=1{9$|Y}V0UtT}pk3{@TwF0KPixF>iEr7sI49>X@Q3dG-o^6W1l2LU&z z<%qW#@)@#LeMA|Y`$gw|Dr8}rMPI#f6-5-4CnB3sO>+?40Cp8>UlxAZn>`=j;?1no zV{jdsa+_C(F9*MyzfK|4fa74cHwKI@$Rn3o>uNBg>JyF<4tFO4t5o8Q^+O^6M60{_HQo(u7cK>o1GaBIR+!K_8%w7~eS8>5 zC%$+8yKlan9E%m!Vd5?4&Kc%R9mP4Rr=$CGbZYQW0;(gEr6`%wDUBxkPpmWgA>y$^*<`CXl)QC{sCpiWV^MMq5k;V;-V-gSf`og$Z?4`1i^M&< zinBz4aw+obP^!=P@>DJyfd zw6(%GKz0wBCk1LjAmpIvHK_yT5Q;L)2pmW`yF?#Yl=1!_FS z7K*zd4G}`cO5j-Wh(Y^Lx~wOZ6_zF@H-&ur9;NtB!nKO+H=#BLF%@ASlD^=s>WxL( z!K{psp?CeS3-_>_%ivd2YhZ={<=g*CS66UZnY@5uDxqT4QyH|dM^Hcez2JqB_9!!` zVj#g3wAM+XG#~HULD4+~MKzS+>o@eLoxkG&qn#LwgP}_<76Al!Cz{7m=)ng~f!Byk z;l{UB+$~??{;!?=*|l=R+XQ{EYO3E`mLPAld2^IGQ)^}-_cR6VOg)x|SjZTF83&H_ zEb(M5@#E$4LHt1ET@^!42(g7otho`0A^>?fNrRbN@o%S2Q47z>?4EqV;RvE|>9x%L zmKZ=5C4#+B@ihq%+0s7hcseu>n*z=Xl~njtT=JD8RAv+f8O238A;OYckr<+{ z63S&3a(0kQE(m2BDkC&DNN(1)0bT=vm5wA<1eq2YQ%mDu@?_zX!?{G|SDhR&e_i&e z%YLf8LRN8$?l;EZSMs#H$PsFg2g8ThBR0ead`;Cw4lki9UKhGfOim$_ORRLT$2oYB z=2Tpk2u5y}8uccVe25+m%#zgB2fpXKRCb}xEb-ddA_Y4b6UNIk^{9bvUapx)pb@p3yTFj~HOA8E>H+qk5p**Vlt@HV?R zcz#%UyEQ$e5mz+|tMdeG(2e-t1+iOamF7q?=5pqe+GP*-GMC%>wGFpb&fCV!1v;q< zJhUOdBYZvruVW=9P127GKj5FcU{qH{fTW#+L&6WxSdE=Ojs#t=#h7^f+a>7winn)^a*CfX*D3Nxnoam3*tG(RDo=Mxfz z_OgJJu7?V5l>+Y0IjT#c{$L4O_n(|RKbgN^a&|+8;@?%XWng$4R1sc%k)$Z+LJH-{(ZE+CBjHkZF43c> zq(UqBN61vMx1nqn_WlV3f=tX!z+17)tF07Wx--S4&#X&adPmaIxFLgCyvn>EORoJm zIl0-W3G-A6BYql*df}IH)Y6p0K|tFn&A1f{rI=$?K9LE+f9e1j3AxlxWrY6t4*c=C zd80v%w9`?0^^=8l3#stP=?DvpJ5Z~l9upCKru&#rOLu^2Ob7gg`V?ebZ8cO6QpjhG zIt4v+IzN|Fb<`U}QlbMPOt}~9P4NOFd*|j|$lbsVN+V{6d^5s5IcR=b?Zkb`u@xvI ztSU&y5_RfikQ|Aw*z@tYPL{+CFn2t>+h~H?-gO^Dj#nlZn3Jc(G$9=~>GpAf(&WKF z=>SovN)~{QZ~Y9oID>BG(uC;tS9baeVR6JB@L!bNnZI#j?m^yJ;?2OMI5)W=f5UPN zS688mv)C-%`%NMF#{FfY-SAXt6(!mS|J>t(xTB+Zsqi%4wb(y5@9K|p2uJ4Q#oR?Ag9ZnM2+BT8XCJJMnQiA~ zqpms#N+M-MQtWAUVo6N#r7^um7b!J`WyAegAxgYV4BS%r?Xi7&6v#S0w2Z|#`?E{G zzKx2jw};GEUdUZwkn|IFjY`0QEXP=Fha6>C7H=*-l9*4xYh3)y2#TkcziVP~; zijR+p#t4wn2J?=upT{)VpM7RjWLMJTLsVyxvVQq8-iAp;Dj<@cWuA;3g>nPs#jXzw zn~g`qm@l2XKBgpM%WcGQtbUdxR*>A{LIv3{cFSL>fuR_ntrV0ud^FZ@ZdR9v6LE(! zor*3S*%>kk_NI$!X{XszP(1^tTAWh{Z!nt!NiEg7pp@ib4||npbRNp7=;=Rwg}D>< zbJQG1i9JLz!;a`1!~rbV6%LZD6Bf0b_6@3H8>-l_YSH9zw~LHh%W4E z_awj>fU^Nl0Xz$ECg5#=bBKCf16V~$r=x%|Qg-rqD@i#4^RRwG%FAnsY$xM)K?!>= zmGIzU0hRGBBrG^x!tfEm$@u+~fK!N4FB4GNHy-dQQVwq>vY&~6{}S*hDc%1dattS> z2k<&7h*Pv@(JJ+QpSSaeSP>H{ymHN{Q*%n zV4n#@;|7rOWP8AwM6l63vQ|a&RPY&L`#J z4n(KocRx=jnzM|QZr2jcdzPq~ML^}3w}@)WNKHKsYw|eJ@LNcEE1PKKGE$#>7W3;x z*7MgBO?*{A<>{x$ddY>PJbeXOuiQ$?v-gno>dwH?4{$ct&r8;8djY;l);nu3uX6=d zUcmEr0oN^U1yu9!`}E&LyOD?kwTFqY@U)k+5_dS>MAtzFbb$@4(xK zK9=yH{H%-%i_gmI^8{39;NO42@88%UpgQ0xvRPlnI$T3G?{P$d$z=0qL0tI0NLAJ**{vP}oSPq<4!rFanF z9i(KfBU|YXqJj?vRL18>xF7#s_BJW=N0P1lDN+vL-=kQMFCt{S81nj6e*x7oKTDYP z6WLaSe=VLP+qJt$nJ`PjZx)d4dhqYt$H{gReFYNE+C{ee@cs9Hl5Hc_ zv1BeFbhP9mvTX)m4(=!0V_S*Z{R6cM;<+;=ob?OYc7l$>D+E-tPLVLXkZdnKL&`6w zk?mE;;}HkhThAfo*QI2?z89&ML1f=_2C4SmWXC$H&^`OtM5=Q>Ir>Z_)qNk}?ST8q z0sg37FF7_GAvJ9gIUe0gYKu=Obs_jX=5lJb{BlxT|3J;>GF(h)mmea!?RrXk!9&VQ z2etU%04XgmrVi^s$D9i4HsC>`=>>rJ-SqRJ?rDJA09ODWq#i8CH%}K(&3&7CyaU}0 zo=rUo#sM^}HDJ+xlm~O?dt>0o5rJsOPo#{+Ql? zcy8Ri5>}>BPv(DcmxK>t9Pp8D{z^b~$_ncF{2zF39-VY4?83HFY48g^Qt1ymIc+1U zRTtCnZP1(Vd()`bTadDF7L6HtBhl}jC?^a%WN#s%yAO@MdM)&NCg4t@=DTRziRZ#5 zJxt@44#D?V()g~>_t}5b_?iQx_D`b;Jy($O+-o#p5N!O(y(N6;egTzns)Wx^qzT1E zkjuwu;$@iElnk2WxgC1^4^5hdb$@X-O*$9Pw=1Mcf1U$dR6vte*rB|>GpMfpg zMpG|>e9oUjQ*XPClsi_?)CVl2Kex4~qOZntmSW@0v@~FS-MIG*Lk106wq23i@{zO~33X z{Jxx~|B?+obkmI0w-LFjXvSrQq)dxRI448GFK5vy&x6ljy+^0)-bu>%YC7e`bqFH62 z)gMHig(d$_$=kecj;97MWiekMW@agKy>6)0hPbJbm|{ZLO=IXAl8x8Mc+|b zv5k~j^Cucb zCS`FEtz2>`?C41Xs<{<({#y@_^7@Z-LG$-Xsm`T~OPdpwUrMXHkAWZihSm(2M9SoR zS~GAX;FWaQpfT_trF7MCUz2iEIo&b)A@KEn+B|*>DId3>M;6Bb^Xci;Cy;XaTH3j{ z3)a0m?P`Pd`sH`py){hK^?V7J&zEpjK*D=x2&km~BVlW&g!lB8aKi?Au|52nB~`-3 zH_?k%OeSUOBlMaFzW#`f-u$DG)XZn-{bIx*H(f#>cefDvd(gfUG0%)A03QTA3JAJS z90>@zPdpoNE8x?#Zw>VN%S&nh-_=Az^XZFju;(Wqrf()c4!K-GKU`Ez$|eULdL=+g z#p#NpvJn1xoZ|RkEugBjT^JhnACa{gX=P`IV$hFIT!ugT4FZGo{1a`gmEp7ZYGq{07*XsACF{+;L<_em6DA)a<)Ran8Bu z`~vpj=KjjOiQ9>89H7k4%!HoqRRU8HyNr8Z2_Cr-{^1rS_zU2??n?Rj=aaH|qEdci zKT_L|P|9!aN6MAQC>67I!+(xaD!$%GG-{!;WX*S^WX({PJ`B10@dRbrW014^A5~V3 zg`Un^sjPl#72>&J%DROGq%1w8tiRb0yL6Uvvk(5@;tQ0Un>hdvDYv{jgVYI?%H92% zLI1u`?q5|#bm{%d{oiIm9~LTGw`3q5d{KFL>c^y(FIFCT-$_d3H|5EF`-%F!t2{Ma zC1uxSETBDwe7z4$md!&^>D3_c~*}9qO=( zdq}zV6LsV@;HR}n9k~s1a*9)(|4l2R?xzW;w2!LgWuX7~7HWA7{MVWxYWZ3OUQ@49 z7cYnWw7gec5`&*Su24Ybu@d!+A-9rp`egOezJJ5+-lwkZw1d=zU#n}UK`w_sr(PZS zl$2p-0e%MfG$7_P+yaRC4bN8B&A1%)H)x7lI$Vo$5L&1*^I`A5Cu!R|yCT%_L1 z{w;F9gb&`M-hVlsYdu-rv=?^klD_Jexwn9S&D1UD!mgIiS0847aPukw)hQ|JBU7AnffID zUDV8E$#kFgZ=DmX}=iwV{1gR_hu+WGWAT5pf|SQvSdM=+Nb2ODEa{KlNNS|Y((Tb9uv_m~y1(5Kao{RT zk8ZH%gB8HFqzrfg5bHXSKVw}74h6g!unO=Nzzu+qtAPgqZzE+;M?lz-K{EiczJo3U zyc2LY;9Xen5tbe&Vjf5KSbAha-*5F=dS2`zCAXQS=Z(nQQZBdj%H2Y0N4MoUh-7@>nT||y6 zET}%>T3n(E~M>;&&iFAH8cSIq);lMf)wK`*xCAxz4iC3BNU? z)KU>^N$RoZTPja1B${xkW$|%X$72>*VxLr#^5=3(b+@g^J5nuYE((zH&%2hhKZac! zRA@Qp35-|tisgb&Eu?fg&T{dwKaf&z$Z~Q1$E2)Jvt07#a_HMg%jFg)skT9uYf_$p zUms(+=C{{jkNaD0{OT=INB6bdnc^cg|7FWPpS(eIYe&nb-JOXpe_ueQ>NNq?z?+uM zD-dU&dcI}Lr~Bb=U$Z>+1MK12BFpy8$H2cHv~2(9E~5KJSe~+ip3s+;r@ezn`6Kw*3M>m_or#3Vtx0y!=(88SoZx4 zyMF&v%l=+(5uLr-^6lIIkTUUgEB&4c{v5U1JgrDsav_G;vSv7;M`c;o6YtoG?-yDJe0V%5udcBUT-hG$)y+D5^v|SR zHNiS^V0ThRM6ILduOj8Pk=8L$E9~7G>-c2_h{yi0PHOi)DbMe)PCYP!)anPVGbevW zv>Cz82IdoM_l|W**Xv0MKV&_78`f*V+tza{5f4suTQ694m~(sU>hm%G zv>fZ24-gk0^O^PPEs)d7YphpqLtgdZch+lO+C@sy57ukPBaR*WyoBKv67IT7Ky~^7 z>$+|a!aja(y~#43l=p4~oC&xWFht7xtpRHQrvhF`%DWo@*8zS5cn^M;4)_>g5#ZPO zeh}dAfKlsBTsPYLI3S*Te-9v@+iM5Jb9+Yv;<>%c0rC6y*H~|<&O)5mQ^IP+dh5t5 zh%Q@Yz4as5&D4I@JF~!-8Evh1PWlz~fYH`FBhSL0j~U@%32&Jw zptAdR0oA+;>xTQlmlGlq_I=*E@c{UH*FDxPUqentw6{LC=K$&l`y`z0v_9_IPqezN zgqQ5JK7G|IqUoGyFAv*n*TY`DdBkSl`~d8GzRkS?@-?rut;GiL z^Sl2F@wvnA~BifK>%X#%#`)tv1dx<&^vMsGSlT^=k z+w%2WV0RDM&g+|oy!1-j#TTOPk$t^w^}rbNyS28}To)+3&9-{`8sv2;wkw?nh>EPX zs|UOAd7J-l z8n~YPuezLT7}P-+qQlTI((Pg9=_mhQhP49J-Qlld#J|t z#F*ZsR4uSQGw?;!srJ~O8#9-vy43dK4$!mmfbEU~V{i3i2C4nL_KuUWUe|23cRc57 zQdU1}KmOY%iB{ZV?=lkd{*%?-{ZJaIsdw9Zu7{lFZngJ(5dLi5t@fS=`;&6-llESn z@w@f6*-t#O3h`Ytd!L2lNja~;KA;2i+4;GB(93y5-nZ<7UPZm>+m80Zy^&XBcef8~ zzlzjeXV`}w8z#EyU3=zjSD{{V$exw@CH&Gi_OUyDA}Tv%ANvaEp4rwusr?be3#;st zGT|48HMdJSzui9N9Qe=QHrw-Fhrg}Nv`@X#5B+@KKJ_K|nK!4}3rfMC^M9}x?1Dd> z=(bN&G0ue^34b}mKJDW|=#JnSHL$= zpY09!CSWn(TY&5Avz1n`!xQau7WDvskFn2B|g zzG0tN2{^CBKL4bjkstN8mzKQ`JN%h_QT`72&(Zd9XT(`)H`^m0K%c`S?3Du`Cnv78 zSN?Q>ROLDQ;;%X(?`md0-HyDuMGFCy;*kB!>dT;?4*Qu)0k?FspZW0JsAD{2Kkto> zq(+~&UvT7B)FCqM7a*{?nITvFA)?dzA^ zhB#t{ef_!6-)^%dJaxVOmW};U5C7eMN8VSUf2sY>VUTm{di&km*C9@D+V8#L2-bI@ zeZzG{h_epaH=T>T(Z0~WHESiQvk%#~&fJ20`%n8LAH`7694=vOo`i>b+aLe(GQ?^3 z*`J!{h25ENe_{iRVqApg1B{#rl8g^n)v z*Dv`J^`fZ#orV0l)c#)2wnR(!+TZ)PaIU%2GVn>|2L=MQ7;Qa}Mj( z@C(LX4^+b5nOB`4(Yueu!i>~r*a0_)NIHb=kj+F@TK+cD^h z*O9+%bqwtf|Iqnb$B5T^kdmI~7V{^d%>KkN=S0ZMo@I_ebQdZ24R@5XKWKfnqx?__^k|tQ zJQ#A^wWXsfXC^7v&2dz3bRf=r$#Dihf9i0@nM-GZj(Z(vUWfTT^rd6v+PS2hHp#Kt z(hBj9&$0SdiwVisINj_IuP} zHaj-YcN2AZ&$0P5(6RP6#{(^fA&z>=v1Q^g!~t(Pwrq!AY&O90%p>PwpXeh2)gezh zcBw5%sr=0G+`A8vQhb-=#lh#pPM+#`?bhW)FMj5DdkofFJ@6U4V`xAD*V6fxcZQ1a9A;-Z#R+4f< z*zx;&;QO8(PPNNG*uBk8%RSKZYezeqUjg}lJI&e3Hv)Bz9B1qAU>7I9>1@k!`PoyQ zC!F;l(LXObyIipYcH=Q;*S8f?)JvT`*N0%YzjgL}v^!vqGvn7aq%I!p>@#~U^3s*g z0k7GJavpOIT$D{pRCNwN7j=gxz86qEd4O|7-wfn6&pSurd%E>q3GaT&Icfsr>$!iN zV`AemP77ytDfrMk&zbWF=oviJIsV{ZL~U9+b05zm<+C%K)4M>wD&LYYTIM`u8rCDP z#5s3z3*@Cs0m0{!wmavo0lzN!#yS7M0a6})!dYa`f`2~fEE@X=(YhthqPaFwT~9j~ zjK2zT)Ffx<8^}qEYG(!5rF?pmb6H>bnde$MPwUYS@lS3;0e1J7-qM-W?(3az&UK+qHo&>}t(BzCI@kHZ+7n2bJH+`B+u51l zI6wcegw%Q0JNIR-ft~r=`C|^o+cMdCXdCpdlgoLyayQYk>zu#e(HC*RGUp%Z;PaEC zoqzp~^~~Gi{CoI4q+Bu7W!(=tdj?##GoeqLe{ne%2Z^HJxmhm?O4tv3`KX$u1EeazaD|Yq24)pw0?HV=_@y_ha zT(d{Of1J?WRYW|`?_5Qf!CvJIb`@=(54)V@D%vq0^`G}#Wz!B3-8sXxU`la{@48mMbA(j?a@QIc;-iW?U02lr?~qSiSAV?%`aRTj-O3@T zdmMD#bjQa;Sy#Dk+Kak@?L6155AB3MyFs+_r)0UJ)%UyT;T|#tHrt8j?kf*;7 zyY6B=J+j<&&l?w_p6qmO*t81y!C9{RM;s<)JHR0%k_3j8uaf)KO-><%%6!+^AdIq|F$j0|i|KR$mOIPsyUDvPMAdh>0asBb= z8(6=0U4M?T!~Ps~{j(GFU6tonhQp35*zC4`wHR@8XSdy(g?+YNZu?&wQ3tx)?KpD_ z;@oy_=U?!zGfr^3B3lqQxZUp8z+YvByXE&Cuz!D<`}jwHBjv1D-CesqOJtiV;XNm~ zyO)B0!_Rkj-wMAoZG*eVi3gz1gWNq(cUOAOaA%Bw{N44EyWd?0P+xYtPpUqQ`bjJI z$(OuOw0?toc$@vOtG~HNJ^;P*E^?1^Ax_IU;+}9}CsLHd?)>lZdE#;IsUK`aoZQP@ zSmQ$cJi}dh6#nL!AKlXy4uHL@aL?p^g|6g2HFhKF5y!aaTn_m6{qDKx;Ma!(-18r> zA%FT-K;>@vS-EekyT}T?z5Nq+aW~LC|1@{;BiV?@n!8ID#EAO;><(U!ymxA@J9zi$ zu(zkXOV{)z3f=E6{R@6LaGJYpAnd^GvF@^(Cy-wq>n{5tOlly@9UE4NIAoE#8uTfT zM+H=eKIdL`9pvxlr`^jBuO&M7Gxy5-J0l;u)P4DEe1GN1?rXvO1Bb?J>PxP!k(}`17cH|CPuyPHOEwaNl^;owmEb+CCIwrrTCpLHgwg-NqWQ+UvKRdw>o$3DjeB_O}4|uHDuc7eC9@{mr58aOO zxUL0V;|6$Kze4^W?CEhIA41-$c-&F&ZTDV}r$Z~)>t{V_AKe1JboHFjJ4W=!I#1UY zD-i!5^z^(hM9P%oJ$=s0MO?DXGknzXptIaFis^Cm^klC89rf*lo-v1~VVPGE6OBWAEeAC)fGiDtrBfs>VnSTfJonD@cows8@rLSl8IN%*u=DFlUFXW<` z=d#x@?^nlrF7FKcKj~-B6&a&2?vI}J%~oOkx_WL9Nh>Urt$!>}&{Ja6^Rg5RI#dFMUI#SM1P`;TCKT$?<5yF5gcveNUx zSj_vT-#s7Td*##*JRc6i_$e=YJ_lZ9>-nB9lwG9Kt)6eX*B~xE(eqs);=9iddk)_O z`G35Pfa=hY=g3aT)yP86&waT5u+~eRp*P=L;Z^U#{5r4mS_l44O1}@hwqISO^w0L% z$KQj`4zGPH)}!BIuXFWy)Y-yb&)xXG|0b{JaeP0Ztv6*w7s&J1-c(ylQoH%RX}=(z z-}kq-CH7U7bH4VrJ{SJ>?o#hDj~1gI)Xv-SNK4G~W3PYX$B19rd5`xDL|)U$+bOpT z=5@9=WA{FyRx$6uS5T+OdCYrK&KBgq2fahj1O2N~y(3=5c;Sa7TwEw&)eH$Qd{V-T zUzG5YB@*7SR>Hqe5m1@9LO`|eJPC(XdPlu^5#+wRH}g{;`VQ{!W|tx^TQJN!QN&~C zOPGDGcj6UK!0#UPPA>W!eF7hNr(6&IyC-?4PG5ummNtO!2Q5pz1!KWa%j@2Pr_e`L zQth1)c@TDZv3Dlt%MTCs&b|tL0Tb`>&fN(+eQ9U!0{9V{>+mi-DS~+Vkhk&{__J0! zywyMc1UdZByYdRqwQQ&Nf*rRaUw+TK`gO#GtG@DHGOqw~(%rk}D;x5x551Q?Q3yTs zN_g+b0xGT7Na)|P4{4)!?Jn4@xp#Z7zT^kQ z0js?0i`T)=lK1+*fJb@Adqa2V&7Y&aH{At1cRuUA=Ryam5@g0Plv+F`wbDc{iU2dH!dG_tAhAaaC{cV``9;2Qt0elq%GH zzVN!#K4q6Ee1gUK1vyUC!Qa0ZpzSy;D6P$l#_SwAa%<2l$^5W$kTsHnfNZ` znm$d*i)}@G{YXl|cfGI~{GkFWFQ1gM@Xd{+%!sB` z4B3zGH>QMd2R|0Sol;Hse*eyt>OF4AU5k|Jzn&(w%@rw2((iy@*_pDG|NWuaDNE11 z9q^WvGiF0xmpN0;;rh?dXQrI{!V$y~(njFiP&Qr1kk2fd9GQ?7Y-F44j3 zQm&i0AO5RH%5B>b-`x0d%DqQWf0(==WmA`v;1_qLJZyUqankuIJ3GM-eDQ9|^KVQ; zJX4sgng?~2kPSMasGYqcbk1Z?mUF} zV!JQnycpt(O}-PK&nB`|OZfAAU;pJtVJE`AlYT;6J9MLOaC>~teBL+salj6Z*n2e8swY38Tzz(jc@+J z-Po@v_60I_Ar61aSH}CFe{}MNYsQkg^o<*ON)fjZVHzH_?R5VuxJ7`6IV zwSm06-phAE_)1cpoqbo{3;DB6@~vHR0V&l#`mTHZ2;$9`d^atG-5ULh@20)bm+>F_ zHgy|;-@osB=mO+>qyO-2`4xJ8VX5zt&4}Zj*Z3ZN2J3j*Cg0%N`QjPO?+f26R?zqBBfj_E?2LZKdwd^8!H-*B z^nG;oQBv}I`SwK-zkKqk??A^wQu5~e4rIf;WVZKxVS&BRZ07rE>UQM+_xb*aK8<|r zBHy1mt%xT6lj=Mv4Ssb{s_SEnlWI?OKm0!G*-KMB-(x){FH3D%o`t-rS8BV7{eZtD z^*G>DBPpq!PH>`cSDYfqn$UlGSmfCkK^yjwEQ~NCiy&v^U9oFm>tn+oL!_R03`?x=K_=BrR&EA$e zViD>l(V3|^Ck-IA{pqO_Z-G1=Ju`Ju=L}M3cSxPh@pJm7)S>}VQb*27Ek>`LvZXvV z*dOzA9hX`LsLZ}1HH3T~0ZnRXQz7!FwAAvEyI|)Jq*fl?MauE#rJmLw>+syT)YB2~ zsu{CVPhTE@K8#E~Cmr}`w1k$yspn)N4yn2;^}J`VBxOZ;>iK`&Nc2c?>II!+$k*4V zUiRn_`0a;NZLwfND7gz#w_E~$ zF>FBU4$4Kk{9x+Se#FIV&Psju{TTN9m!j`}?vB0%{dz+{b$E8_?hm)%xyMpp>W#X>iO;3J^Zhi$cc-U*bqw;+ zId7zXJ^EMF3mmE6+>CvZl^3P{`2KR_gTqpPeiMFZ@S@aT2O*!l@zT`aVp#v?nW?`| zhJ0MKE%nbG9f|IFS3o8890~8fPr?m7Q~&-P@_nu!n=i{YS|D*9sE`5_regf*r%DP^ z6~)9iH572-2V}?pt}*42s-V9xP~^ZTkN7mYIu?tB6&|D| z6seB+yY%H}TTad#GcPkQZ_@ZNnT6x0 zjEszi2W?3Om|_%D^iv52t252~>QLj1@?i`nX$k%enWp9}2u7ELKt;nOw4=!s5vv@< zQuU?<_~Zvc5sK+^auzIzEcIuWmp43AKTy&Y1MrG7tBNqU7%jwSo?p56z8C|C@n4XZ zf!f15inKA2a5z{T3q`_yFtEBRSi;Cs^D~R8V$ncxtRPanC>Rr>(GNlzqzZ^<6~>i( zt1~XXXAH&ovjljIskAiViG?bHC4LBFQcMG&=FE;NeO@ulEP|P7bLxsuQGp|j?@IWS zJ}2L}NL9=qj>P<>k?L^r`J~e+cs2@pnR8)*F#y_``YQYv0={wz>f^S^4aSy6qKo|1 z;b<^WydY3i9!xrganJ(RV_w~2X1R_cBv^=n0fRuxdR`((;7`oJaxwKocrHTaI{MC2 zDudC0SSc)4l~@;ls7g$z-W2H98iAI4{ zTMX8qBwB;-zZSAD7mCef)I?w3!e~t>T;`8O{BZ{Pmo5mE2enVEV_2_H*k2iqltqJ8 z!bBugwa%0-%nM5i3uFkAz=EFGPI%G_g5^+R%~Uiqw6`)89vxX0x9r&%BVEYa5{w1O z(^>0GFNg&z{neE$&xs%RL4f#i<`4eYA9af-(@P>tvF(@a;g*zzIaGnkycE?KB1Fsd zA)HykVrW#A(580znZ>Z4RUv3srZ7z7!?9qrG*BEA(@0M=lrA+qvGQ8hAWa+G4{zgN z5-6{35}IB#6;w*IBh8th8HlPe1L>tdr7|%e!$UV48wpnVivq=q`~iPupsY!#22duv z2rtN&VqhLzTJ1{GQQ*5O5L8Bg;ZO6@wGt>Hb3DCpa9OO$c$)!lHAd7V-$L?I4l zPn3cYmxLnKRZXU<7o?lLPo}xDJYIc%FF#(aV2bw{(cQ$ zkDOf5Tcw@LS8pXvJON3p4E7VuR8=uqEP}zbeA!-`yDun(T zmd_POGfkMj#wOFD-eeLjN1XI3zh)F08@5NnVc7~KUxyZw@G5pUtor3mTo1ONwIxjE z3ew`#Ux$`;@I;%s9*KEXm;Y{Uc6jb?IEyCnmBXBYiM9|Ii#eoDi(+}$!T_g*WutTB#faP zTL$mu^rl52#I+1brdTPYGl;>O!dELNAo`N1xe~QVMW0Ay^hi{QznoNJkX3E0KWP--FUcZNY9{2!o)0t zNnq9Cm63|&r~9~kK-++ULq5$FXi*SHrkn=m;~7q$`%y1IEtlXtrf$ks`}h4#xqGkd zWx?X=80S;|u3h?eMJBqqIs|9z&qp5Kub0f@#E1SOv-jp_R#ujWibXagqQV^51@=>% z6>7O@5rl&$!#G-u~r`=UcJc|o-olcZG^Uk zQ6~u@q~pXSo_Fd)*pY&lhRTxB;T8i_;&DUUtz#mUHOU_+1dek2XFOmTBeVKM6gnZV zqUfSiWX)a{N;)B*$RM@U$FS*+DV40n!lWlcBlDCpkQV05UPorj3sgzdlIW>6$;wRn z^KPTSl#C+@X2_+aWIylpFH$^r?F=u`6w)vSE@ylyLPpj;BS~|>Tg8x@CL^VB>9Ju1 z>7o3R_hp@hQGy3*jlA$mXxsR8&h2si&Xf>M9L$w!srEJ{5>laD36rI6^~t< zNEQXQbQp_I1@*GzS(MOFT^1eb zW23=fcqlJt{fT+;#5mOICd0TJ&)Cz)6;7U%0XgtZ! zSDT)-k1kKI4kkf86{tmlNoaud^X!q?&$7RDYY8lvSB>wo!IUw8QubuJ$WD$~`-nhp zlt?>|sg71fqW%EaxqHFKvURJf@@E%}VeKgnpo}i6&h@2hVI8t$EzC?96KIIdP(g10 z1msrXS4|`L#Jc46lKME*-=%-kDR+YVgB-nX>R+n_M-qt?qInbbp{_qj zpoF>w@W%atFlvd_%SkyP2$ocT$d(f*mqj)gtYJk_L@N!Bg0C%Nhk^Bw^jv~~kU5)C5B6U~<+X$bEBL1StGJlmQPIC3LGEymhNFDr6$Q0W+ zBPp;JMrEC@&M#X+j~Q#VaB|G;D${zpGoxkINO59SLZ{MrmKA|;$)r#?m=}mv1*5|9 z_o$PI1>(`IOe|T`76Jj+;;FoKc{&@Mw2$i|q z6pfd*B`sR)Z_K~#5YjB}P!9TDFOH!G6 z9A0SKD%$Q{Q^@Zy4W-da)X1^(^si=+q0fNTQR9pBg>1k$8sV~RU3qCaExagZirHA0L9s)Mi!wy|%6YvZN8@xjd7#I9*oD4_DgY*ms; zcN)#c%quZ}xie8kb95`?nk}bXHK(BwGDLRCQ<0lM>{LZA0hQK_(0$Mq&ZZa9HhuKe zE`5jkOJk8m{?Y*UR>baJGw69VST`l?relzrRV;iUdrG;9!`q}G)^dI9W<2(yU=8om z1S=|IBK1i;_y~P)xo@Z?zUzY>`lBWC-;TwT6jj7RZfN&QjST83x}yraS-xQyP*>nrH}flERZ_ zqlRqNv_y-@);f?K7~Um9;~Nu?M5G(3%?wi?lY; znr6^=tQvb(-tpIRTmCzL;`Rs*r4p=cUNjVr`NvnFOCp47X!4cqrDI@AAY%qLK&)ph zH=35Q{1_a?#=(MMNi}RI^A)NRE=$VS0U`)4gAB-u9y?-DRv@CVK@=X*v!2V8>X|pjJz%C*&QG@iK8-4Ao+UVw6YYEYMdhr2s(y ztW2@L5M3zAL^UnG%fKd;nTPCKAHi7=Lqr*f3eS^h-Mv^9<~|!IgX?xY7M1yFqK5{F z-kK;L;_y!vku_GcX)+tAJ_!s|hr$J+sLts=eKc`y#87byQ(aEG3nP{OhPf>>6^>Fk zV~~!uwqZB9p=sgbMos%TsaP0H+8G`=20f9fH(P1hKTw5litsOtR&E=H;GCpw+*ugQ}gafi7L=phQ6wBm9ZD$&d(a%FDn{CWG}K4Y0HdSdfkwMiC|A3Z(Y$5H8&#? zOta!)#b9CE~gPjnD=B1MzChEU)DMyjp((#fjcPnQ-Xf6o5uODK64ZP z(GB9~h=J#=C0k5^EDabQ%~0}I2JX^etayRHG!(5$h_zw)OOBQ2UBCGSNsp#n5-&Hv zB%17`|8TNQ5I6a-RPx_zcZ#;Hi#`g62Qw^_r+>HL%+?^-&4OhXwI(fiWi(hBh&Hm| zJ{Zxi7@IRnvqw{>Ok|d&zz$Vc6-EO!ZeP)-0q$pbv z+L?Zrm;84KcZ~4@6-mddH2w^R`ytH#WHT7kdd3_tt!A!j_0&^tF}2x$pX9llOrX1a^u3dQG5|B z7hLw5QX^x_#ySxOgek7`YrBwSgNxSOfDB~n{LYEOPwn*9S`a!-ggkYA=|=1kg5;Sy zC#;1vm5F}aO;jn^Js9OHPUP4~8ii)WO!^A6FxpmSSvj7xLp#D%lOmBt)s=z^xeaP4 z_lU~+Dl^(JMx1?DVEtv-z^^R1d=0GnDVV5X?>GO;CFRqZMVXCKTB?x8Xg&&1tyGVU_-PELzAc5=Z*a~UI?- zvC1|?UN;tB{!>enYX{v~I(y3FjeGFK=tC+(qjV%tg5DB8lqp(`@+VBT_8a~u-q46k zUqb>n3-ZsarkN!zX45RBTsbpiIla<#bucOl{>j$3TYU4MdCL_{L(J+BtRq81v+!HItyUcsv466`MF4w~9W#}ML>7BtXICGG5b2z@+7cTv7FCz| z<5LhjAqmEA1CclSi+Nv^m)g9)=gkSk5atW2l8xeq+gpNN33Jbib4DN<*7jf$U~afz zX5L}u9xS7uiW?=-Q3KwZv+?$0uqg~5%g4J=mFUt}q>ea?TPYiNZTUIaRTm4{Fk;pj z7Cv6i+K5G5f$xRkF%~n97>75*8ro2}KGqTS+=khPnz3qqZiy$_+Ki9WpU^xczE{AX70Jhy!F|(jbo1nD!~+715m7`8OdvC2qT$j!>4?DY}lP;y?fM8?Smu2w?b{PLJB${m3UXj0wb zhhlG#ZBgA86B$2n6Av#STL(`1WQ!C#1UPGbL0jiYx5yr9DYl}6{-Sc&)jF#=G$C_M z0)p|iK-mbxnVH6v+7}qY0>1-OElXF3%>Rts9I7J7Gu)W*Rt5O8ze;|zG9{#S)Uo`PZ8V`lEIld;wI4>BE-;NEgIUyLZY8k zo^&vY<&E*#EdUi-D9*{7Oo%z8XPhiEEUbJolRcft9q@Nam3f}bc#eoQRWg1nWrB5_ z!^299!E?Nira@Y`eXkO7g+vtp#yN}3U5u8f(THSOt^C1o85$k^fhCYtu`L3#7ynKd zq(Rsd0joi^k?C~YW$@2gTk=8;}UChIMvRqFY+39SwgG9NJ+G z5_dslxbw>Spt&E}T&NUV!Z1syO7idgCC1O$P%RBq$sAi~U7R__>47`{1#`?o@PE&i zTG(`kWP%~=+MC7;Ax@&2)d(BXM6Z+K49%^C4n!A>(j;64|Hj3m2EL|5rg2(TLYPAc zPqr`uOCUn5WZbvM8B!7cWV66cX&ikRTRpvjE>MoRrlcnB`Z93%#9tGs##*AL0n5#m zDcmFA55>e@P`yQUiw<%221aJ#NFTExf@^mY&VmmX@Tn$aPt@#^9qCzUeU^ug>fvf9 zS{|Z!lv^E`3F$)9u(hl&nkPLsxYVD6PA{1e)ftLFlK>Z4(AOrZRy7G9$s+M4%Yzz?@B2E_~9FZ;@*>p^_1lJQ3Y|UZa zAScM1YL*6Sl8MVxkWFzLkn1WI?pT*TfT3Ag`ExhC2-;|3Nx|Je zLWQdQ-Fk?wmH*YCtl-H9ZG$|8OA$T6@hbi3CqjCCn$FDfSWoQ=fOCb10s0#9} zKk4Ep^+Wv)JempDA&TDmqjr8&9@MY*+&Dohif$p3H5SxTrV}Pl<|+;R@OWoPe7VT zLvLAo*>;%QI@^trTOlxaCBYc)jw}hmh*V&^`G1O=o3-Qg=nK@wz+H}bwGqtY8cg-r z*w6X3O@pwg-TWiuVr6XKjE|3{L24;(GknG_R z{ORmA6Vu#TsJL0Kr0X>gXJVijt^vo-1xKR@VLWK#2NSy=yiMBt2qaxnz|oXw{xEf` z`ou8)NU1-DK9J-y(l%_hvFfD(I*TzPDv+97h}w0%b>&MZOuDB(Yj1!N&4j7t5;ync znQO0(oJe$Oyid0ts@7r~P-Zfmb1^Gwg>GYUb}gB?_KGqdV?+OgPNf@@2UlRJlS@FcNl@?ltJGB@pTIKcLa8O{d2_Liz=at+QcRGYI3<~hBJ*U4Gn8mJF$$~lF6~TkYGMHpE4D@^%w~^o5XLf ztfw)2uL4U$yd0_vr+uoZaV8W*HuD_yOSdYmsG%?p&KmrgiI<*R^E6s(1)kUwh{kYR zNJ4~OluPtmHFXkgVjm&l1H5OTKLAOoWsdQgH$G(hubEwGV!-qTp%R=m61A7alW2!i z-)zvh7%nSU9H8!=a3wEm#X;R|pHLEj(;WnM|$Hg)xe)w}5hD2N2o~T{%lv|ygY{(c@;^<$F)(d~rej}R^YlID!;p(R% z4rAG38!Y$TWwnq;;F@6>#*tJ@x36^+@i}j~XK&P?Bg2YD6vEqx3Q(smeLL}u0HSh) z{d2w}He=X{MI(k)j=+tV@hU3%+~A*N7h*4LmB!Em9>hj2-;2Qa$Z}UAHz`K^mE1&8 zE%qs@aNrTPU&Q8#xz5)SC$rs7v*Aws_t@Lei?}i+KL;lf z(RCdtLaA5mWjg68VRno3AKNpdfuc|`+rk9D=LnAv`LGHZ?Pku*C=OGE0;0H<;3*%> zJwL&l_2s6^yd0xZg-3@@5@bFa3uIi*T!udl^KKgrZ!8K13325DR~a4@B>;V1*3qaI zCP9>jaEhag??D~k2x9J7b&jct@^Ri|9O1i-_|gZ18`i8~MY1Wi(S9w=S0XxH{ItIT zVx{YoL48256k)MGO*i%_0%3FmM3a%g)k5AgF$WJeYk0ha$-T^v9fIs~5st$C5EsKFOLjn_Ud zSQM2dhJ@_UZom<@{OP#t{2K2+z?yL1fx%wKQTQSM(jaq_-`~*ipnTyS zZzzXE#oCl6O(`l5VdFZ_7Fuz&CHYFOWNiN}2=?`{< zX8VGpGD$VC6E4>0WE)x(4?cMlm}kau5(lh?lS?ZIRp2T|zW2dDW&yUZlj^s_+?U?;l-%j0>SZzVaXhYp(50dlNp-Yq9OPDxH7{T2$yutnK3SJMLRBE z_82H{L^fKAx;9h7L+}!qx18K4af!1kNo9)@eV&c1gKE`GE_LykwL*w=HfqdhBM^e2c5DE$@!sC0&ZyP9-c4G6sOndd-}BpPh5Sm7X+Z; ziRUm39AFLLS!g04OLj7mZX#jv%g~apOfyt_`R=_0OfHB;L+Oix@wbuGTcjSs=rG4P z_~j}N*Eczj=KX2rqP|0|D`V=6Xgb6eedMyfl2BN3k~F39qOgUO4OH54)UOr~#df&4 z+2UBS^~Ol`+Hm|Rz);jim;`HnPD~!P9EwS4r+#E*$+%B|H{&^b;i3VT6L`~6luYrB z8K3q-7np67rukG#{M567W#Y`}FEhGyc9BOjN_m9qVZ5uQ$yM z(=>UPR329`_mHv0;i(I{^!00wi)^%a;uP~6mqb2g%q!0{E{AbVc;8L~b2c;eSQBPb zOMF7^=D}dGO#X|v@idW&<4jcOZ&=Z}U00YUB@|>fWh}_dAFaM5g;`pix<&5#>&%<1 zO%vy=|7bmA6^u8I_-}^!JcbJge3y|X0;bm@88VPqedVnAq9xAdMFTXrz~l3*Irz~! zrRvVNJ-@m^JAT6Dp$3$f_aj+7H5FzD#f{PIM6?QI!^(@xqlCU1&0w_+MB+7-vtT!+ zZ6Py0ZFY^DD6#+3v?U#pM5yG}k_;C#+sIRum(Lu=H957dVzWsRv_vN5Wt(^hf?=W9 znVOw&N-j6cn_qWi$Ut6FBAHYAPKj`AZ1tMXsbj^SO4C?1;XkCJA!%%*<8M$Dx!!0T ziV$jq$+A(cyHk;(-G&&{u1`1En3ZG#Y(O|3;|@VqQ-gsGk=}M%Ws}s1JNJ0Exz@!6 zx(h(lpMC|dCx2`>QV~Rk7r*SE?;kFVKWe0D_H@$`q&iPDevqaf5)LM_gk&2i%zbus zFmy5~0;5GQp z%Njp5dknuikRMFVA6p%&d;elyT)7NGCENbEGQ-EbwSb?E2uD2JK&@?@G<*&=Eq)GG z?oa3kVO{xb*2d#9LQ(VmZ=|!%Q2+Dy(fM>zGt02=D(L+mpUF>z;{W-QBqCw}M9Q3L zb;a7t76Nor#I?NM&8oTx>ermcFTW5CDlCJEQ2jR|kZ8OfjTt8~omHDe2)%JG+y z@DiIa&rOQiXqDj-G6zvyf9A%T|AeMv^P-VueD^~9{V5F+HN64HE8VzuFRUo1i0G2N ziE##}R{n(V3-I40ok1-N3MTo{j9OB)fUmWcX<8k|XnWz@L&!LJc{rTou6SlQyLwSD z#P%V!g}TXCRA!5VIKrw& z>j}1zG8%r5zpH)E2EV|e5RC#x)KfpCPa-?|0(8s59Xx#Y1?OA%E)M^=!ooa!sH(*K zQ{v~kz^`Ru*E9+J3u>7>)&{1UTY0!qK`stAK4`58GD&DMt#~p%Q=RG)2wt0jU{Nd;F}ZwY2oo%GH9kD5Z-!zzeA>XcyNAr2EVVzk-5f#pY`033m(!zhUfy1tM7T=+qs%>7c`C{DbiryRYYppOr5r4ByDIXsmzVr~DeAr2dsW=HumzPZk&032Qb&Yyb!)kS8?FL4fJR0WRB&;*?qK z%U!+sP4bB*s#^S7BQ1l_xU$0>eu9soS4DDql;_tD7Iuo#AqTNG@8~aQAfhcZTHEF9! zKxWlJ$T63B`fM&_W}=x4jvh@$Lj2tjoJ8cbG04HYAS5;Z5*U%hB$d=5sWE~$k!NeF zWe~OZ05r=g4G$lCsD1HK9pc1oN8&9LiHR%yKOwH3y6H=4l4s_fF3Js%*s$5*!q~sO z``1{$gm?eem*R#g_&@V}Cb4e#!f7M$H1sI>5}0mY77?eh2#H1H|4#>KV!@yWB~{xl zV+P1J@X?6zrpZ?HU>N}6sq*KQZrFCnXs zyWx47!yTDO)tzSx;}#NeVNmi}4sMX6vV()0DS3vC;^NB#{K;`O>sUC#dPV%1av-Ym+Y|%HSe{^g9Y_B`m~OBxsfiLCCrEE+A{iTaVtDFHqjra zwkP#mbSZh>C=*guZ6#tHlp5o=uBxZ zcJI(8A&AGd2Z07TFE=1+7X#|=ESm_^5sBlXwKtPt6Dn{e+*D{({Jj>upH)vpF)!Zp zNpz>NPrJ_6kk$Hw)_t2q-B78v0pRGcp+JfEY&mi>-$G~dG{QWDcv|L2sm?V28(FA7 zzhP+1<&uk}i?y7$z;!Bh_VIVzVrfLb=3Q*O5yQApRZajWRZ*acJIgv#sBh<35qaS` zJvQ&xHDq*}ORK_nk#lB_S8%ShS4YVY5O zGuMRqf3Q@h(f;2pl?iFOc-fH5K}rxb9K`=x@W5v$g zP>#RiN=osXP8NvN{0UW&Fix^o1w}FaVxdWBj?PtZJ z5i=p$(Qy^$QH*qz*PQ8R_ zlZ|>Zeb-)yqV*uM)W!P*bY!iC=SN4NIImd6uR;mn-mjz!*r$nDbOq8e9iw5A?+|Sq zRU5ICS}z8N7wl1SN>d-QIgUgIxhuvWDHiW+5Rps51xE>g6RZ$5*C*5)PO>l#3T7cb6D%D`L*V=bk};Ov296;s=<)3$`z zTgh8lS!Q_t@)mA(9-Mp_hXLBf5N?$O#r^R(3BWIFZPZkxC!ocQk&nn>3q$938sos> z40hs;nV}59@OUK$bCmfg|0x4B(XX!Sig7?C4fjgNcpV^FZalvl;e-9P`57qL|cb5f0Dd!T)448CNd-n8MtfhPBPi%T_Wuk9Y4;u8v1aI zhLmHOfImNmt23(6(8zqOjVZSgOxnA!y7SnA$r&%aB26>GcrCBod#s9#ZU+{0R10OmGG3`bFNt6M6TRtu>z4n~0p?YaW3 zu)rE1?}zQLuT1ASQBnC$1b>w{MdcTl1fbKlOFvu_+rR!IHEqx1zvWnmIC0gYmAX-$ zmDJjblaYmd|GLq5q6I+mU-fM`aErg;_&1Rf^ODB7sdKJ-p3q%+^=Q0JNaT_1e36Tx zJ^}`^5Y}fOQ(C_&V62zfxJXNvh$ z*Pi1S|BvUGi`mP3SZ=zo+;Jw%Tg1}9aECM-n7Vw_>Ui2}^OM|B%>j`n*X$1XJ9+Yy zjS>IKe6`Aqf62eN4pxMgA(Z2*_2sJv)V7r2}hLyhB*M{G>!Gf2rGQ?x*)2uIO8l%r`9I86Nvc~sW$gQ zXxIDK36XTO)=Z0rP(;FOmF4lE+QXH{<16z;+PrGq@y(LUa>}WI41=V6^1o>P;#`5y zir+>J=su(oY!Rf~%l-NqGOoo=M`Be~E$css!HXB5;)IK5aF?ez5rTKYi1?*GV~57c ztsSe?RW2!ZoWq2{D?W0HZ*;D-k`Y@;4N_8YB`$OIab+~X03MmeS}M6XnWB%Mwlo?+ z!fT#Z{lWR5!Wax7UYn~wYD*szzw6wEU^Q&S;LY&!Y~bX0MZ9Z7f5e`i7eF?~80tL3 zD5hfJO8E_(`tNPHLAXR5xUchbpMI*L?gRXuk_6-P$xXg)nDaz&Kvu_L9aEhyDvEVb zH1TT8I#0V2n?83_(g7REO4;@3@Ntk25+DAym1jZOma`jfj z7=EZeyfFa|*PC#vROeS~o{9;bsju<>WA9y_yW_?zW;!~0HOq;P8?(4^H=gC4M?}wR zb`vpw!K}3Nc;UDa*3NMk^ZR9<*Z0-=zA8|Z>~_cw@d1A4oIH6l^W^JfT8#MxZ@L9l zr=(;hd#R&@H;1*E!&@ZlMv*0%(!bRx?c#B$@u|d7=n0t03~Q<8-X`41ys@usiLA~& z)ZHHL8zS`@jZSSzm$xi;#5;y!&09Wy6yZuTS3$1~nr=;`cXa5Yx=sM^*UK!D1D7Vn zJpO{_;&fI$#R~v5dm-u2sRo{w=0%bq635JWw-G%Ip1gLEupK9OH0lub5=cmwZ}gCC zrU|$4**&MHNjG2zY+nUQ6CE|klis=heQs3~+LMyL1V4JN)^B!50wFV+w5rkWB?7~nFjxpB<9gzV{Gku9n~>4_}z&OeVRmzK8ua? zd#engr37)D(7rK2@5R=dv2 zzl^$uOsYlb++;d~wfQJJ$a_})t~Y91APOnA(TVUmlcG;EhFnZhr255IfJ_CIazU8h zM_6?a)EvB5`7NImvsUJ_=8jzBdp}!wun^=L|CzF$vS3UW`lkHRm?Lz@@S5MSLA+95 zcK+gIQFzd@f z7m^sOdhk+V;-&fyXrVGS!o|GgZ)xG|6?`NVNP{6T2&^c?b=xh8h#5W*aDucqo5$pz znREvx0L2kRkUAyH%9;U91WT?K(j51t(w}0)J7<*^T|z4G!8l203UNRcHXE*5Mo-`% zB`%ADVyfs7Acu+KbiC}^HpL>2|Gc#|L=;PU4~$lqBTUWRqXB5EMJ# zsc2Et-@<K`vfkUMOe1?uya|UzKTY7=P+$2};42?S9qbG6dryhq```nNTWPO-3K3s>DucV$ zzKDz&g8zn9*8N+E{p0u07L!B~`TVePDbYJ>dKbF09fD&?4mD?NaS67_VxtZXmjg5m z5C@m@a8TTTII;-azJ7tb7J|&}r2lStr=GKmBNCt;7gbej*&!9jjYN^n@n@A?Q&ujr zoL1%Uj7nqq_<)IdNhI4+8>&b5Z`RmQ8`09D!7Ie6$E z`kEJPQXPXa8W}7mkrU!k3HM-I&A@8`FjIY-6D20V(D1bEe6B68wMsEPbJ90t! zpHPv08)36srk*zMW7<<;K#(=-^&72PpH2){=X~fiV!|L(>uAR_cg)&e8d7EP+OP04 zdIW7iDqKx#zdaK3tCDHJN<6n6f#l*2|8 zY8x0~Y{1URHC4%H0E`c}?OAYco^IG*fQl|-7tCWKMEt_kc*UO-ezl*iVZb%jXduKS zT<(IWN?xMUpg8iLAMTBz-bs9y#ya66G{2V_^aKcvzF(j;(ax$|K{Z09&ISBS6>~nr z&lMJ?sVXmX2i#9D5XDAwEso!Xhe~lr$jJkwni%bHzuXD&o(H|23hjT79eZM2QN3b} zY>-0S^HMXTT8VlZ`ZaN+It2?OEB&Q$q@gnHA=|+1#;?=7t@%cThq&Sn@Z`b3qNmE; zSgvK+Y4QiP9IAzcpcpT9H-wve^>8u;h3i=_A3Y$%p;8+8gA}dx7gUGp#0$S6ttsVO z-=)$}He{$c_Y~9{&vNCgbmPA5PZ>^QNL8_MQJ~I3#66O)td}QjKBzm;#8&bMZ5F=|{PnR0>6Lmi7RQIuf6r@8&^F=X;t4deLbnQH#oBtyaG(>%}2>kInwSskDpMU;f0vM zPl-X@!WX#GS}iFzQ5Jw8)_jX zd}Z}imH%zrgI@M3rP#aIY7+WW%jNnvN%qTVHnV`Pj+Owt=h#hvCozHKk+b-H3iA3g zQtA@CbJ@lot?tY*nwD3^NZto6xx0xqa-G+DNTK@VhI%RQcZgoeJ7DeiOh8387=|Jb^KldzV-f6j8TW;sdE&cK=Bk+ z1J2S+TF>>^SDnpU2_fg&Q&mpQKITy9v${Hi8r+ZNm|ke`0#2B(FYF4F_%l1rcnZw> z!qQ*yZY}oJmeRHOCXHboQjJpK9B`-jrd{v}{>AcAFMF_jl;#-=Us@C1HGzHdnYXM| zKDwP)YjfZ(j7yl3ur5*k`JH!|(y;Rw4Z!hGGFflbn#~JnTiN2X$)r?A#|joElgGwS z$~(0>`a-qD_S9Kmpguuczh=TJUpwUsCTh&!EV@qZR9epwQRk%SSige@#$WJJbh-Js zRjc!{E`!?$KQ^U3Uvn~8%v9hqBu{g6k6DUq{1i?PG@=j>ZN%ueOl4%IE8X;-?jWwvN_7$N*s~@y>JmH4uP| z5ZQbS!TJvuA0`VQE-g4O#nj|w&cdIEKfW?~DIYbt6Gc$MZ!>5CVFyGj4iwVohO{-u zCUSN_;z8t9n{X6vs5|5zmaCxaon)zvb~fuESUp_py20*a#~a_vNNO|wOmQaLJWSA; z792=@hln{2idmn+xl&Tl5k|AEZ{aYSYj&Jq=A?LleqB=`>y3*Sf7zO>)GjJ-V3mufZe@OQ^J3|ium+A5UiOBxe+O$w zlDlDHyACr!8*ERMOw685rY>E6SMp2n=`6G3!3_&7JYZvl7g!;8R`GOot&P`}As_Pt zVvS4Gwjd0E4>`j?X+b!)*P4}$3V3zm0$A&;g$mPv ztPKf+NRg<`y|4m<6{L-tyj+9;?!?ap2m$`w1~`n`Xk%2el8beN zYlq=obnQZx7cT{&DVaFteH^_O^&q8hOlnD02^4tm;dkCgwM?i@sK@U+@1yFv)GfdB zK6ZNatp!94`#bNWdIUp{1Eq{wZTe8=--Gw@inAWno7dg*Xf0k^b!q?OUVVSgQiw|M zUZ^eRf!y1U>^<@Acptr|hFMy~Bt12jZhG@1({9)MjFv0;kawH6y1yeN$PVRbVw6 z&z$w!(e&@|a$V`&os;s?zzlzhuBj_~gqps&zc80tfiLLv6#N^fr<^}x&mJG7d-mj+ z`7^nIGOn3kTtad8&FL#d)D?%Q-W@k5qH2Hof>K5IyR$v%A zOl#_8PsL7D%OS;1m|oWT>vzvAf9IaDX-VHD524M*Uz2-gyt>w`|INQsAI&!oJRC;W z#qMRw5gnZL-x^NEET7( z@HKAs*Qg-ildWHankLgPXtgqlIV^Ym>Rsg4C3DC^tn4&R+3Svp4ssh$B@*{(h92FPaLM*xEf>pqU7}li^#HiQr41GL67Bsj+O@ElQpelpt}ioFppI4CwRq7X7 z!KrY&-#|C_T+~kOy~(UY0XiO5tH{G+nslm8SMF-drnD{}M3c0_*Twplhwn3eHvvR#WreQ0ubf89Lh)+Ssq+8Sxkz97EB$9hrFSFrV?jj#RjxckRLfKNZz7Qdm z>t$jOCMID0_3_qHqt>de*LITDb9A*~`n~II)dhFALD3DvRJ@;<21gddJ?C)u>MEpm zt-;0yuEt;PuBL>}`Id=C@jFap_wakOPy4#fy=iv~ouFn_vejR;6t#QYQMi%G$f_Dt zU@>WnRlci%YzP?mSY}1&ajb}})dF+(c+;o{tR3Z7(aTk@el4#W;$TPG3gB(I+wG6J zHcB}lQ9RhQz4v|b+gvdI$y^Qk{3|3QGFSt*IX9~UlVY0Z%eHB(wxQPnwHxJpJ)E!_ zewdgMRsiLJ`ho`XbjWS#JhucKK6|c|h_JCOh0TX4Qu))#slo%b;)^+xpdRk#LePp!M-kDsa20PNt^1+(FyGpT zcb2+lc^K^e!`F{rc|d(FBvgHA;qecu+azlZG`?6z;c25c6#}|eSjcHFfGUmfBCko+ z*fLV`May;IqPmi;eiwjC5x#~F;E(0$R(DxmTojKdZ@ZtV{>mCTR5GX<;mMqXCaAmB zD6f~HAVa&{MNLZdUMob|2Zbo3LT@!Gn?02WLQoE{$u@7jt$)7D`ZO|_^)Fq}-F9E~ z$Y*!I;w|=G>GWVnmD5~NG!wb&mAXTES2Bv-WuZ()AwhS0IrG3O28E}0Dy6ik`4yJB zL{6f^+1PDuFoqX2Bu=f-fBb<_a;BxW?<`c*@=OUTNOi+h9e;>YN%Kx>dU>fmVf^&3 zTD9}x@;utVTqfLare~+}9Zudd8sbY5c>t349)%^@Lt6+?`0EWtF&^UMim9EPFBBoz z@py^d0`RU6`k8L(WM)%rZ?ROVr_eT;I+sqmFtC`$I=<%lQ8jCAFE}m}y)3(! zSynG=Z%Wv%3f4|fF&EI22i6ay*`$Gr3};@p?F~9xkCX}okBZN@(;aP@LaUXDd2z5D z3LE^|+T1Dud3o@V`Jk9LeZ>*@k4@7Nc_T*9mP#$O)4{v3bjRBaRo=m~*pMpErH~lq zsg83ylI1OXYF*Y^O0A`ILT45?mp&}Im{gmy)}Ys+E!x8B`6rjz##*#j-2SBvp4eui zwi{4X7uY_5nPFe->-|ocSeM5tN};4tr%%uq7~iS%;}y!IoPk1N+C2xp-x$>>*=O!f5FT{z-k9Ed4=?g4YQd!Wj8Z{#;t9ZJ{FfmX!Rj zfzgsp_gwGKktdzv;^yIk&d0Gs8}TlYE?YG_Eg2o>kMa=Q__ry z0`)s^Tp5cz|+ite74$Dwv({fytI zaEHgeFQ{sKpJZz&g?YQ2!f|;Y6U#?>%TsYl9H^gymfTK2Ye&{p`DQieMoaJSymkIE zgo9&6LHJ$NCzwaM1L1&}Ka^sVZ*r+Gu$ecdk#{d2_WscIQgyuyey0HXHr9A8#ldb5 zlhQnkwPRSZMs+f+9%IFZH;F=_anzba@Ud)Gw%XdNM2_-RyV8pCjNnQ;TPVMK*A-7Jfk@`%-YJb&GuMKV=~**g-rZAhI*dH8do{Ma3XUX-%4i@WBV9Eah4q zC280ZQGj&@q5*cPQF(&0D-J(Tj1AZ6_s;5$a?;p^YK0UpEx^wgZ`>iZTWhP?FI8Zx zW=T=R5o+D}o8monZ;4cfSIha@>}I@SjmG2jd1*bJp7!=g9PM5V#?D0riq(jD%h9i8 zt7K{g#Nr)HatBs?h9_bGX1yGq&K>}_elQ~0TUsO{TMm|`d1*-K6|8bLM&f$$&>->M zP`PD)0PhI+_40aU6W0t~ik{qUX`Hn(tFh?S-Ho8Gb=*c8XC}eRJpiaX?UB4B(2~LXL@B_t%e-ha zn85GH8Z*_{+}SP@$^do?s#v_#&MVo?S+g(RXhQ?nyiAyF;CYbBA1w=8w9j9PL8k|* zoa^aM53)K6m7`gJTqMs5Pq4G+i$f6;a0PMXe>8rPP{yix7JO+Aur|1$%hU zc;~D%XhE2+y;~JCe@!|Zn|2}Y@B-+I{o$R^t7vuoYGRa_ZW5D4mvu_T56f?vnFs}k z1@y#`5p;O4T~ZVYuG2#d4aFqXGgJ;8L3qGIQMi6FR%m~!A*_`-^$_Agxj0D&t#h`* z)+G`|iy`DjAyreQ)Z?LCQggVoU(f5FF1HXpPS~0xwpKCn)y1rZn+r)IhWu!^m@G;D zSsHd7cyNDiW;VEvUQ|TK`*n3p|6d9Z)Vpm=J1`t7Tb10F$EdeYLQ&5ZO^Gi>2ZRykwi2+Sak0={ zh1`l=^s^*;bU23m3NNTv*r>17S_lESX;lqybQ{%V3lS3Z3S61)A(;5KmRv;Mn7JK~KKswu4ok91)U(7ySUb(;gioto`S%tEAM@>VxG;loBkn3m;;Z z>yKH*vXM}TB^$6&wN9ZoMLZ=3+D0+4bZQ%l4r&`jsveGy!3XWwjLv}yrLd!;OBY`< zFaL&DG7a`#EZ<3}%qp{Hy>CDnsNm9eExNmzLLt^MIVec!h}1`a0F+NhGjDkM&^~XQ zl}0m=Ou?Rtwa3`9G}!+H5~lL9>y`}c7+rD)2`JHx7E@4cMct@+q5m5;3P#Ld*QzKT zr?>ZY)d5eor)JMmTpqW1zYddd?P>y7TYm~>yheiYgKf=D;YHmZJfqJE8zs!cZ(l^je_j#;9>_tvoF;gX#|onLDr z1aoG|#lj^!-Pd0GDh41BV{N4S6oF7I#<;&SDBdruXy)?r7{ehsXo9$o8~_x{cCAU3 zm;%xH?K3s;9stk}1!UHN{>tnuWzX1yB?R_X%B^<&)5-=+MR9Q)#itCwQjpQ>%^n5l zQs4$3m_=RbMh)eRXQlOFe3lb(;q~)py0N{X(lyyApa71;fJ3uI$ns13t_S2cvV@e7WMb+6 z`9BH?Z3%dw;zqB;1ORCTQyf^TRjMeXK2dKK%rPcCHni3+uQ31AVQ2~AzeY(-{Wu-< z6KaRUeSkI}gGrjf0Wc|7i|jh%xND4J7e*Dl;?KIF0Bk65YwNd^{<9CFu zQo2ob#B>|wGgMZImE&?-89|!XGvvk~X^ZDGtO^GtmS`INppZ-M+gGM9<$UAQpkJAm z%;(HJ1DNM>Fw?&2%Xw2x1!yEY`rXJkoSA*BV#s+ncMF{PS}^mq$jtoaz2KYoa=!7x^p)xBIp6#wnCB;v zZ$`1!B7A>L&G%~a!1UtEd?KoI2A|>gUR~AiMP)7c{{K@4Yk6L|au6U30%52tY; zZf4>#VkUUh@ybkG+~AvFrhPLx;%25V5H~Y%aWfN&o0*unA=rW7n28AveiLx!Oq?_E zO`J1lia2v7G2ITPp1nZAHCXX2bW(-&~&OpG)4Y*%JD?>ZF5T)Pz5nUMR8 z7B3%Y>z$Uie~+lmnoOL&JUc75n=yo6XeC;yexhmk5ZNOlq-CbG9*nuy!QXPH@zY_lz-BW#CR;sUy690lL(W_u7 zB5frEdqOn|V$YZhnU#)#_O!l;2GW_NnyzN>>Rb)IyUNKDo|3MY8j_xwnPd#tl0FUL z1rUmc1GlTvsI8ntWkhzMmlwgnxZp^y=r8JEU`#HgSDXz*rXM&Plfv17UI7dS#zb>= zpqIbFz?dM;4)i);Ffb;avje@P4hF_Vc6MOwIA*&a$7~>-gB4@PaX3Xe7#Lg`qmFiF zul2I1SHyxvV{-pkX3=dBFJqq`!LRzIw`=VrhUC0SJhC&BbVoR{5xwf;AedW-s6HoC zTTqLeYFO4Q}kk3$x*-hzLJ_aC<1*e|cJt!ZS z9=DSi#pg{DI~bWHb}+|NsNpkuO%)1LApDN*)v6_EsSy+(P0h1}$UE;}&-RBLR+g4$ zlNjfxx8r6AWRAy)%n_42aWFhu(_qA~8lS=AG(AHMrSTa&rKe|z5qf+EFJIC##JD{^ zgO~g18Dg>~K7*GU=^0{zBR+#yA=5L&)XDe^UcpSy5LY(Cn@@ctE}-F9_BBtOaJhlT zW43b|n1`Tu(04$c9+-zKNz|T*&k*Ag&Jg2~_zW@f<_z7*+wLMpoSY#>oJUfet~2-} zIp|P{@v#$0Z{cU=GKm53Gu$OH0Qes3nV8U;vCqqBqVGMl9iI~Oh$Gf>t<8BwDHvi8uJhCl&TjtYY5kWi0-o|6Q6qh?dIN?A5HBMZ< zI(hv)K?nMmMA0!W;X~f%Bq?Hh3M<&7?%d*$JGGq(0;$(0r`{u)^Y%1~`ats{F+vB% zz(?~dNz{oEe(&Xjejk$yhl2S-nKURXM1@hfgcl&XL`-mm-}~E8zmMI5;rE`q_4^oC zhu`~~PQQ=caN+m z&2xyKfR4u?4;ASw(B7{Jpi$+~0Uh&gGGW0_)CtF^nIaF6BdPIOFFJN10OWYmk7WiM ze|iv3w#(;v)rTY{23T+kMgJnIhD8v52(ry+#xUMKcHa+*LVHb$nq~|RKjaF8QD(@M zsn`&DDRdPXg0nF-Al-TgxE=;4GnK6fn4_4$xjEb*ghF$D8Y8CWY*@o|;6WR2bZe3M zX~$|_K<8_o;T2>BNGJQqz(W{lLtUZod~l`Bn0Jh}(nCBinISPAI)!XuO2o+RrslmAl5^B^z7u#B41?1R(QDBje)+oX~ zcmwlWRWv})gYPg-bR0u89i0_>S`NaI#qk;|uTEt}O>C9L0-1eCUjzTHW|^jwFin8T zkUmzAgau@np@;ljd9#F9dcM-xi<%yFVp&m&<_prBgQKQKb_sF9LIViQfHaE)+B-d$) zs4A+1PsaCn6a>hMydf{%?7QhOd0_m0orS5J$<3R+&v2{nR%C`-x8gG#fz;du9R6hk z&fbk57?*R24?P4UkY?It5XmljK0v2T@RTkXi)V8v7g$-3 zk7eYP0Wn)}ORq#GQ8H_r9K}*Ggwkhp=^HNo3*|s4@K4NWY8kkFwN^i$EHL2kjd^K81QM{YkUSBnnf ze-V>}LRH0*))LGLPX0Ruo4&b83n3OAqX_;s#oJF=x{igxOr;gdXuc5pIzoz`AN}H(S=>G*>k^hGI;gTrn}v zJ{9G)PibM-)!8>Nr~WCe6#FZG%ih6fG`D*RcJ2yuyYcK3RfOfI30{Dl$rO_TRp31c zT8KF2L7~QYPII z<~5lQ;yMvAV0yxI($=M(=H?B*gtNF4T%WJ&3g8!6VPa|SPR>PuJ8e8+E>&rspit75ywqxdf)U;TeJ5vDYv!vQ8n%i> z6g_)aEK+#elVVW>z@8L~3<#-%jSKK`oTPpFr=g`ZCnm}(?nXGI6^+3lVnxI!9S|Go zv>UYV^ySn1@^!VQmiS1v{4_ACj!Qg^lwzI6lnBD5ZjytypYde^FEy-QI2|t;T7mK& zT7*j=$lZh^claJUsY7cmob7Gst`z9%vru8xaXq+MhwfBfcusb-3f@(?IfpstQ@*Sy z1hltDVg-lr|B6OUyb=8|oZ-D$FDMIdc}^97wLQF8e%1r7&chE+E14Grt5Naoa{984 zL8?!vx@Dv`NcPHoGZth%& zF2VPr-Wa8k1`2Pn-~<1rB|B9u;8j4i>Z=e&xKa|s{e@_o#5*~SGw`rOQq&uUIuZY! z&yVmEx5R7GvTd`p&LWLuY%xc3_i{J0jCx>bRq^4B_ri$#RetJg;CPw~0XQxI(2Yb1 zM}-RSEqZ_?yJ7VLc^^|63Emw!ChIk^UD!umB^kZ)DqnD34rzm**YMOzpYi0P>X5i? zRVxj3y&)NFo>S(I?sO;d+*klbpOn&=fg$TaI`C0#Eiw8n3FWB0I9R5#RVg=vyQ8O< zy&V$-uc8^$vL=bgN1G2B}cbr3oXUz!fiq7ne&Rh;37LJwKQ`u|Pzm#Vk* zLH3AdeGO zS@iNV2qK6h97ypNdm^uVpy(ObD3huTdRo+dDMTT|9L*1Z*eE?mHMMH2@k%XXQ2k+*F+P|;*Aa9?C?6*jYDX<+GWV0v{%>-9Sm4CAMmR}>_zvuqKIgr z8psH%-`1<|RaM^QAE1VV?VDt&?(b$9G_Qw? zA!BAd<-QGmc;#St1vRUs)LZckM*`~C?tP(icLdiVOoZ;l|4KkvuV^Yl{=P>LhFAnq z?gkQWV0;nr6QL2~hzPEQ0XRs*mbUxSE{ovHo}^3X0*6t^jFs#d!&6l_AYl6J7@f%h zZXCNw`~6fVrPwam=|RJItZk})Fj*jK2 zm7c-^#j$g|hKsa@5`{lSh!-A%LgQM&pmXdf0v)!!qQ~R@Rdh(q*>BZ&(c>lPG#sfV zK2@YqrSw5UZ@kd|Os=FfrxU=3yp=~xGaHA4^S;s$&{>7j22BEG5jW5kLtDkNCyZ%Z zLqrcj^{B0*T)Mmqll>m6sq z-O%P`mq0qu$n5M{qPtS}87y_Tv%`xr{Z^y2i|*o^m8$jtNRt5lJsD^*rIyd%l%0@b z{hjlwp`T>EQ9|VqdA63G@n3tJ5vwTvbVK9;^_WlK=baGoTdgKSPb;N~h0@C@{)`Tj zHJO`pPzxrXG0&R`x;}<`%kD#4%kU^r84-8IM6+Ic3RKyXNst3rkBL-!F$>rJn{jPOTZhu}_B>fti4jFq2=9wN?~ zU(6$~2mIk6p}dxRB;9^G4aw&zp45wk!p=6!DdEUgmDM^SW{vHM=`1c94 zwx7g*p1@vZ1e{kSO3Iv@JSP-$DsbKQ64I}2)X0~C<(5iaFc85wfQRfc)B>g5j zFg-3u%|m7fC`SfOvV4`O@?U?Q53r)1VRnr8!)Y+XfCr4MNMtp2pUpJq_lA8_o zIvi{I2rD()gqee|F^y2GCQ=k;V03f7ZXv9#<1wZNlRCD&iJ%spDmA>qT*KzK1?UZ& z27|~tHPwL@P(a#O-&)v@Me|c=GEpsNfaL-BZwBi7hsY6}LJrS+!CT0)B)qlqb_F%v zq^_oG!g3y6Im*d{)tQGMUYNS_p4Mo%+GVxqH*g zAD>NjQ5`YaW;!UMm8f#n-bG>_7e7o1*WM{LAmw;5K`e-{J1=m2g8OzE^g}p2{b}1h z3O?>Kbk820IQPlz<(acWO|TJaTUC^3l3nI4w2Xz`$0FK-hkyRtzIQ;Ze}}VW0EXwx zD^Ra>y8KBKs>|`j6cH3jHuJ(?l4mF0UuH|5iTD5ZoeO`rQQ4}rnu-bpaPd4%`obmX z-y_#&9)urZ6&?UpU?%-1aQ57WO*;=2`ZoTih-g9W_t9p;X+>EC-M-(LpFEV`c}?;AwgdC>((LkWsgxhehvd=1`Q*_K{#*Pt(>i~H zKRrB8L_ca5(bTrAs?5scqVlXtI&<~1EsuzFs}p${$Da_n6ummyx+ECDy$^@aeBWmd z{&P$BSLQzhe(4;i7=YJ@l-~pol*26*)94d}E)9^7u`RWc;doCmE61iR1}cVpX>A4` z5Q97pOxX&Vne$m{2}ZkZysO(FuA!(ZsVrV)W8>XLp_bQI$_W@|~R z(WgR2^$I5YQL1}?+3Sx`&z%B`F{V07yF+jn&A*8GXR(3`4du*Tgzoe}6bE!}Ne)1C%r&4Rb)-BFwcAabo_WGOC~ z>6O{}dC{m#xacIflqbRd3lOm7PD2?iF4k4CP$s%4ghf-FdcU3#36_7>6Jq`ZrJnuU zMju;hP->6_`Bs8r+p@3ynY}{7wd@*PSxbWZz~SFM+Oj7fUMD4r?)CDP z^xuE<_-pOFXm|gN%Rk*roZOeDN8Pzo-toQisb1BrAEKg6f7P>AvBsya_O4Nt)e7j3 zunLWX70?Eajh9B6eostD*&h<`|KF6$9CHw_jlfsN?ROPL~Whf#Movd62PQR=zcf zY`;PY?xNH9m079t+9MCCk1(Tu0y@h{^ju6sa?CUh__m+B|Ccs&;>nlZhCh1_R{Lv^Z4VP>G=ixL4G`Y|K7d%)k5{| z1MDGt4TZY9I?72$)aM%}olxnD>gt4p@`Ss8;MFraerXc|5DMr-5sIlnP{Ry!5xD?= z)=BzS+n{nsQTfZh|K_{V;b&0bG$4duEgR92;wCx9WI{TyFVgiPg4!fGf|eh(5ks1U z6^Kgo=UBv1M82Nge$uj6?rHPExtU~l66Sw|y9l)qFrkY#a3gLz5bGxl2qNb#`Z!g0D*$|fyjPYEPr1i9BOcKr0$fJRO%oP|)xfEQx zKrJClKQQCZEc%!dwT8c`Cdz&42+|k-M2aTg!2HDDbWXXd9bM0CRO|~h-nDRcLnNT1 zgHd0bntu)@8vkg7q%#YQa49;PxkBpLz{5&4UezHOmmTjoV2_D)>S!Xda^syM5Iztr zRE=wZbYijNmnW`DkO|}@@(=~>Bm63VbIYH!#<6jiPy{^t^>4(ctNr>nML<+>NF-9) zp8mGw(I)Ua(WWG6>c7}Ki+7YY2PXP%_5BpzUIK_4sC9A)|L2p`ar}BS_?J!GjGMuo zaE-o1V+K5|RwQ;JztmZ2J(;-m)8x{#jq8^#CFA4CP5H~_=4Rnla03oF>;K_ml&&pt zzL5@9esY_tP7tpNOo@lM#C!?3W9(zQxrtm&*h#QQHrN$w@!^6v*z;KCy3x*qkQk;` zb|L1}5vEQLN}F9|P>EaA9pDikXkw?v-7;JW^3FJK$WC*m75t|rd6*J#qEdyBYvLI$U!*SH{&a!v7xVC>2!J{4(|QCo;K0cn*gJ!2 zJe(%vl)59Rs1Yk2tl%*61LyOUcE>j~vMyAeH-Z~PJQ16< zwz_fiHeF0W+yt+@YzRk>hDR=`8V=YWWq}R+$&Boj3cb3;MD$z3YbveDS4!ThTBxg) z$W)U0Ed(T;R~zVU$UpH}-v-Ev|GI_!Y(t+v+vi<3S34os2H>^2h;3XsNFvzy#b)JM zd1I$s-D+)56iVw!oVjLX>x;IBFd6Q^bFA;Gm72VPSaK+Q!k#I-Xdsya@Twy#rA2{ql7?u?K2KTYI z#J+Eraw;Q@n@fcUwJn!L)=Z(diBzsOq)kYQL80`fG5o;)2KX|@kvrmZ7Rs_TD+*M9 z$Sh~=h$pp3<}M0>tGv&N8Ul#DgXf$Gk_AcM!5)D6L_~L|&6?vnb%dh<3dR@7pA4(C zasHZX@GQvdneb6T?@+Zyw=gGyY2?l#%w3Nj`6IXhtOm+B3dIM73-2`z-+L~73#}ud zu+!uHXi4-%mkV{)*mVVBt8 zVrpe7e}vz9S_uc^GmKy}uUcPF#h@daVTw3dPFh%)Y)GX-yr>4QM}@AdZiurKxc|gyf zu&~-gQG~riZ3O}2dHhS-p|;w07p}L(fV^%9g<6jev-cr@OrV(lv!&&Si?_v-w({}( zlJ%sm-o3q8NRLN_<*iBJlvQ`SLpF$B#J#`DigfH(uY_&j4q{4(oM%a_5tn+F-oBlP zP(nzWB)U%5&HDje(i?$2pS;LMj*FC5e}Zb?R&n*OiI6G55abp! z3cIVLGbw(s61!83@yw`-%;I3Wjsmv}9r4%uC&8#vb(8RVvUc#{;D)K!ut|Z}VH=t#OR>LjwmLvH*hI zixd528%3omo0Z~lTl#k7S?XO#0j@+vyO0tyt@XSJoTn8|_}P#&j)-TtlyIa(y5)Jy+ISKfOsnPBJy zXr}>j9Z4G-kifX};1BRrIQ_g02+Jwxa`&f{l!z$4_g^DlH*t@{X_J=y>;1 zho?aESwBCjBR8OmngljYfRwUPE~6M?QbiHF;$(;a@!Nq`4kc@<+e=zW(YhnuM%1Cs_nx|Ev&l0?szg zR#Zu*K1IqQQ_!)YSwH+YCyrqRE1aB#xTH9tCzi3Stovged0Op8lcmV<8gK_b9k$tq z5l{z-OJY9~)U}Leo~*kAkm7+$8!SnC^Xa`IK)lf_0F|-^EaA}jwvSZe9^pME1@!2- z^ZxrHHDU%>q;>gB96wa#i81RmV#*k?OgESnA=bUy86Nv#Llflan>QJ9J%_{YU|Tdm z2!Rc45dY-s^odzSdG~9OWabcaM(iKs`PAp=#(bghinWK5DkzJFnMC=bDVy_M9+%Dg~rV!!Gp z-Hs`(P{(XTe+XAKG2Z0-;-b$U%0$*2tThTx;hzDl3Azg4RB5;|E0wr0Dmv+GPL&&) z?VWbuYfggI4D7#=Q#-R;?3}-V!8qHu%%r;#J}Z1i0c|K%4C zXP1D7I*Z~IvCY5yg>03+U|%o)Z}z&`)jRN`cHiw?xVahVRM8o#Xq`8rUIJu(`o2iD zJVr{h@a}ty${Jc`JSYD=MPX>4wj(bF^X}l!av@1eMH@-C#AEp;EvVSHME~!(;+%tw z4up+>Dewl#N~X(~@V`P{SjDzchyW<)4KP&>LIZ?o=1+srzoY62W+`;SC#mnebu`!y z_={-xCQgJtMC-K520&B}rCrf3tJi^YtXGf1cX52F=n>tn(pKNJHPFdiMf{ zuY>Mw3te4bX~QaEgjg+i>+CH;(j+)2Ye=Od()#Zds!&|q!f&*zDEtc30M9SIiBz=G zvMAs&=MDKgJQ!Z2aU{@l;a@jgaL|mmtNw|Ezt3Ijhh(t5f1wDxyDtemUu!w(0+bYB z&XYke3mkt*bpvOq2s?8x0XvV}api%ciNDR{Q4uJ&;Dhygj0&^Pcl(UHtKp^+hRiNB z<$ySwW+xVY&m`RiQa^mLdzcUno+&p>U0!x_UfV?NxO(- ztoj6j{2kfME&kTSDy!hqx3^YiwRZF;uQri6Xfo~(J?MnsBepnT@QfF6#}B1tEsoljpzo#Ne@B;k4x6*a_9kwJB2{dUZqgsDX4X- zfRH4p@VcB}hl$`s%F<8_7hKr3#GMG;P*WuHp>vL&{nvTs4B75KZq~_=d@mOi~OEh!FuFFRyb$~G2n!6fdM0{e!Kh^ z0pQQVei1mbM3*MHZ-DzEFq}YQKN(3Stlr&@s2xiUp{xaxo;7*S&JwT>qiHnNR7mP0 zJL{!asja%lm*QyCd@3rtDs0uqFEu9IipQ3aevS9A$P9v%&DNvniqd~tO0kJ6qCro%r#V z^xaLm&<*$Mi^gYM#-I~42yl2vZnMz}-J`4|5vkx$QW$=~zBsItA@|{DhM_}~j|`q& zm(pUTA}z7|056Z+zHyx zOi8uP<3X`Bo~C-dsP=kF9hSxgY#+#@$j*?hKTA?ne5dQrYSp}r+EaPy*=?3wSfutI zD+9z}VfVT(B~wcCTU-fthfl5f+pwKHx`DyFMwP1cW(EZet?ZkfBdk9c0YEEm=V9}N zDUq&4NT|y*nyA54|Az5^9wJ_O$FX@lIt$O%w{^2~pv-^tT+c=4@Dv-P6gy|$`Hbhz z$$fSrYt-yB_q^ih+7k{%{_!`9|_^5wG7Lm*GpKINYd}o7FRT#!Vqfm>`>x3|Zc| zC$9xW8lH4uMY~}++CR+c)9tNtW_;VtXeF$wCt=#3FW524d07<4I?5t2YQHX`PH#h| zc+pf=WKcDuoc3{3jqzn<3BKltOKwLex$?SH^+!d=UzHiNLU|=f>um%pF6Hdb<12cM zZuZwWdoKqt>CmM<N7uamov{aQwRU)|ar{S@tkjE03$2h6Y zr6p2wuyD!&O`DOq3AE%>#Og3{kaLnIX=U_pC1Xo)~EigstA~So`s==;yhE?Ji?19_cq2UPOHHiXH zo225HRkgEBdDUUVLrdhUQ&Eo_jDn@?x zFf@o@{Q>r*Q{3n_D$5H)iCJYz&gGo@Bey*9#>@asg`v@4BNs|mo_sZI$&iBamVxw$ z2XYDnY?@zypn(JFZDOSP9GNh?7b?4Tw4m8gmd8QhF@QL<^3LL#gD^`!p%Y~dtJjPI zL_zAEXd*b<&XKlLTYsE`i(5UdWQCn~of%$nyFJR?`W1IekIUr0oK=6`)2ezl+MG75 zJnH$>-b*1SP|wFf^@B82v>PZCK%WIDx!DtNT$+!v@{T}Q&m*K=Em+Zu->&{^a}20lE^H4JIP?C8d)@93ubx>&s1d7Y&5Y36owHyc zm}SnGk(qt4etjG26}cmS3hW0{JQRZ|Gr=K&Li2XunR2I$A*@CfBU3srDA;^Gv;G-0 z@rrEmuzblDcocd>+qPR^m}8LopbwrhP>sS-LvbLv>uyLtP#NQIcG)K7SeIrfUk7Iz zwWlaw6@jiFc{_7%@>gc(BHtXvH{@{Z_End(N7Kk`X=fdE{?NfXGMWv|S=JKW96p9;OZ8@gYWJ~|C3UL0ksdU}K{;bi z$dOU*QB##HAW#Nx@{le@XVGA;THeWHtmCO!C)YYy09?;VlkX`MCA#dU8IfrcG#iNtDbk&Z{kaiX7z%mhKvfb`f=W2R5g#Kl zxNO}7=tP4u+ES}NG7HIqxjl5+W)tU!XAw?rS1W2fc2EWfQZ1sZrWJUdhh|Z~5xvEv zOlp@=UPH8_rXoO&36OrRD{gak)Ri7aUF{fkH8M(@0#SSMhu@EeI&q0Qi=8)u)=B-d ztwu~rXagr|L+KQpeY5S@9WwwifZ~k~;C*xVS0buF#VzkPt+p=|SV0d!t4oFuU<1w=2yydb3v4ubm;tV}}080jjKK#~+aK zXxoa?brFycVL|5A69AapZrS~}zd%{r$bb=C7^>g-J?^`mqsT3bDB>O9iv{n$%|gME znFjz0aN$7Mce}YB`HXF|h%zQ#is*0y1~8yh&)=oX#&9DBZ)=`KWEmw+Jb85=_aht? z!^i+I5{9kz-O;l9nWH)kor$WNjevv(-mo?9VwdWe!?*^CJTVU5!Q)i~eYgVrf?Uv=IOt)Q;8{X+Po~LIuGV+%>#WOk+D2RKZH6F0e%3S`};tnedR-WE}TK= z5WeCTH{5*tKWrcsJu=}CDrVEg7|{2JZPVl`GwUc`*zyvSXC-dtfxD>v*pA7jW8wGU zUq;xfRE^!(Q5~Dil&W8pBEX$==S$5&Rj?QgBW9jBvt{AX8Del?nkXDcGduYRJHgvJ zw~qs6{f|n!vEw-2F}y4{YzV?ZJ4Lw`hat&KLaT>nc;{}$%v4J-bMkg{vST(fVCP(~ z+PNC#ys5IgTLxgvT#oH-xwc!1VmJ#AB|d$dYSDRlddR@Dg0h1ZtyrI-Qnst3#>0_C zG-GLRh3!frv^N5wMC~%%hSGYB=?@v)J;uf#2Zq=n;C)k$}E@9&F&yJbus<7$FKV~s)pinp78_-+MdSn;esCR@g25VcMwqJ+bS?p7M5 ztx`3{qo=Z?fc1|to_DT*8!Z2tohSJi37r5vHlcz+(*7f$4<*y!UBvTzB0=am9Py{_ zHrs!<7L}pw@uBoZD1F5L0KZS}Z*Eqi_eR*6PGfNTmQqN~Ejlcd*shA1BUjB{{f@sA z{$;8~O^!Bo>D|Q>w}ndeaqQA#OD<*$Puf`@H)6ax( z#0Tp(Hh=*rIvpX-$Nv8vYoEoo7_$DSRZOaFP+3Bv0WR5wau0dJ}0s zMto6;z&w^qqeBIx`GI)yT(?&2Q;ouiKiSA0-di-JG+y8}rehzMpRd*U>c#t+^DN&P z2#PkaYE^C$-;1t$G`4QkT4v3E-u3Fkxrn2nQc1~RS7&M#lXBROLG@lC#V$L4!$GjX zgp%Zb^&(gS@LstZ6STKre2bzjuoHf=jW$POG)W_9RM;5OrO0Hi zf-6DnINi~O*x)W|}qja~kiZR~7p>}+pi=VD{$dK-H?HuiRJWADVq-ieLX z$cL4CRyxr4rqaPX*$)_AzE`Tm%%5`^L7-xW0w#>OrGt;7c1lW@h)h%qKNdXfXTD)% z1Rb_oCXBAnKob<{JJa5Yxhszv4T-z1;{UwA!odRzwJp?sjV`y0uPL^rdA*~tQ6i}z zYBVasUS+bsB?s=68t5kwS%=?iDTC*M9ft3l&F3-o=bG_9=~EwSU0>oDQiUSiO`!RU zJZ}%l;d?w0M4E8}aM!y5xC)Z?0U!5=c?Oj*zfsCq$>hPQw`>gcH$h>l-IKcq&?oAP!f5UN}eL;0wk zEhiYtWC34wO%gO`<-W-4X``=~&t?((l3;SSy_ql=uD&CCoKvI>g(xIae& zIb^>CjV<-fxbHD}wVf=@L@<3ALx^D}`?N$2^SjJ(&L~$$9$VVikaaJ&R6eMkO*DhX49s7?WhrXP24;TmHX+KxS?vI8st=p z^OiUoEb&Qg2M*;twfHJf8Ae)JYoPaaj&!aQRfA_H4NQrBRv!*dxTcU;Zdcf#!L{Z(J*D@gfp*T z93Bqev#(fYk$zFZi?*0Mf+C(F0LejdWB1={H!JHAAWq=A)rdXqBn{fq(q_2Ao4rH# zo+m3v6^hxu0|@xl0^iNP#j;eY&anNMeAbc-8FnA^llNmlY~p^7a65QqF?K<5ahM$L zt9`IDBD)O3w&?*w7?5XR`>1Vt%pk_(1a0#dI$$iIoPk4#Z)LIs?xW0QbT8&h5X(cb z*@D~r5Jw~rmlq#00N!*Y zCEIX3K9N3gh_V*LNwlZQC}A1e{Y%g(V)P$V3-EDVAz)_E6YOq@yL0;*SlY_jlwNk( z@B5dwa$sM@#&_^Amu@G2AM9V^RS-F(LvSO}$kv<7bI1_-+_D{Nj7y4jn*N*=EqYOn zW5R8FWC=af8hQ6dY{amRh&v)qb%?k8EQZ5NMtMq#L>t3OY-&mcjM56%r2~Hd5~_5^ z)I>js$3`;p>glKqO7LVO9_69WP#2`*Q(Jv|WphwQN41GVCXz%b!`SUU_&*}&J|eub znF>+$8VLrCp2yfF?~g34>3ozz|K$77ME% zagJ-YIwc55)^%vJ@3M04IZdTw0#)bG5q&$AGcp!{9#}yVlJ-E&5Z;*Bl+@BqdaeTy zV|MZ~5qQ_6E%5#o(}p)QzvfA3aSBFuNmXgHX=p_Y+{Gwo1WFo1eNfaKT>JAp^rPa7 z;1dV1s{6bjDd6##7gJk!Ca4GDzTUsGg94us+87bqASHMX+P`8ub!0X@A;}>sHt5=* zvCq;qF!}K-bG*L9RR_(}tviZ{w^e=RyWpSc|N=&v#)CV zbL?gkC|g)jBPRAd2Mw*X*U*7Inq4z0qbPzyH_PCPFGZF)G98d52MlOJSB#1IQQVT0 zzcg|^aSp6JZ!VXA89~+C=6i|fNexYklf0)jhcFMG)g+j!jmI>R`35BCZ_S<5zSU@I zATM(g%BCzy;?cU@_KkoCePp%Ne4H$mkR%ydZVbyYc41>N!7;3AE%(@{Aw+L^1OYp) zR-#eU^TIN_nBV48Q6-jCS~2=Af>CKUB3>Tc!iQHSy$agU&dx=N-N$(MddJ)a?wmfZ zl=YW=->l<3Ul;RKWeN(0tH2WOZ1%6#YCAFcb^`K^yJ8SZ^)>aC5P}fHC?cEV`#FcZ zor*AB6MvAi{Sxw(LXgB|<7WK3_biXD*4pda_0k5T(UG$rFPxL|J3Ze4KVM8&xzvGv zbp!D#hyw2L_Ntp$@gITpkZ5eYSNM+8?{N@A8?|U=#Hgev8tcKWHGtP7PoktBPuyp) zlBDWS`M_$U%(_lFHc>2fzjKmdGfC7?IwjsOeK?U|byfi(7HKe0{{~sR{k-~c2bGkd zl_7~22~cqnrn*H&p?(NGE`n(aZO!-fhQTXQFh_vkKgdPp-4gph0U)tyi<3qBKdD5$ zB$`#O4t*OIrhwo*%ZCA;5JoksKi-%KB6!{Y!E)NvD3Qx%;5c708mtn_LIsVP# z5Z5_gM>oZ=fhLOkfxb`qfA{gePe1)Ma+qUItt8GuD`N0dK5UH6eFTi`o+bd%Pl0HE z0S$awUc+mG$YMu;A4)lW$xFoto-_yH(5ICKG|lKkxN|^~04kIWay$=)49SrD(Tw#`P{S&~;Z5%!3k_66@<(XtI=*J% zBl~RT3@|{;1zD@WioPYL*Mq{44IYVTT5euu9mktanE%bB^}LRTrAUP`1!~ph@cM%l zyiIAo%U{c_+f@|kvjuMS;R3IA)?5F|tw(KvG)RAor)fiE2GfpA#)G|}P7g|yK6{?9$Q+A?Hp(c> z1wWm-LUMPq0sLr72Q3-IY6UIP0JTgHFTSt6O9$~=F^ExV2p& zo?&Bp6x^zk5s!$3?M3GgVj#DmU~jM_0=Xv_=({lgNDtJ68C2m*MDhx$Kc4ED%gp73y2fjLTTR!C`?TK++Ohuky# z;+qFjy0eCFEPhx3>vGHtfu+R?uU1y6^mN`SE^`Ew!{8AGY8x5pA~;<$(OlG} z>t`yN>0L)bPN725_k^CUH2;9y|&{Ev*bc?1J?kaQQ$wC<$g6> z3ix~eWftai|G-`itlJk=7H7K1@?P@u2w7!|528NJku9X$2fC5$VvLsxS+{7cZ^BniZzVb_c|oh(+^GAaEl+D3%E>c zNJyvDOV7HH>nVuabdrQ_iHuG;6{^h#OFKwkM#Jc4v!q4YjyzbYSEkpgg;rn|A}Eh) zZBiU+3|MFQo*}HXFLbz6t>9`jg@E&CIE<0hZ~_73Pb$+9q<9v6)km+lh%`6LFjAe6 z4v%J76e{wS&Si{p|Xf(SfeKvotYr$N$u0Dk?&w%=eB_P%9 z7>{9b5?_1Z4YQIo#@;|Ci7UpIzvk7*nn()A`7kx6+lt4dE27m^MVKUi*%1J)2IKD> zq6Sb;@JUJBMEL_pK{33SrCgyK+K)Pf;(yB@IELe45{|ww2I;xM``K5i%Q25*SuLuq zx1l|3%4+T-8$1{mS9Y>idsa+7V61TrLQqwgqTebfEFGz~s;Nrhv;+;) zCfo3|cLVLD)OMk~)=PtcvelV-`n;7hjO$K zI>qZB7oFNSyR7$h=BEs7qAW+Zi4IG022Diz9mPO&ko0e&!*DSiL-qjOp#7Vyj9ffw zRK!&_ST?xTDAl($O)LM@M?lX;j=MGcA(2m)Z7Ix>2z}==fY8ZihS|Qzd@)#CZJy|tXSNYHbWNRLxylt109>ZQJgEaX()U5XJ zl-ATQpO5l$Ks1Ad^es}g)GP(cU8_gvp@u=3QRFY9&MHfEYm!m^^rM)viZdnM`}?|o z2T$m_(Ju!X{l%dL12v?Vzv3yZNa{0E#~plZx?xV2AnULT3myl8$hS1`Eg@x%-L7InZm15uJTXO{@)3VS zjybJyswdAcMEbG_j4gH0E|qjY=n-s!WQF*wqmTWh$gb)fV}wj3P=(I>v4>f5UL<5O zZ5}to#n__~S_5;Xt$>kwt=_Kppt>g!+ERO(;Qc=ES&hOD+Ydfvowr^g>t(%L^l=Z8dig z!R#Uz`vFoA^F%pX4ZP;dn-OfEStqHyB3H#Oe_Uv{s@?5PA?uLTpKGCVI$%7X3^nWM zJJi)UD8ewNKz>nIwK03?&>^If)GM+h>~zp>cBhsRUJ;}ELt?R1}N zTy&LWB^YW!(lq))UNyxfq=o3Mlnm z{)ES5m<)ek!T%TVyOtaGkBWb&4cw&8JX>+BtSqPx0?asZT3@hdAxQiDJ0YMNMpTkq z_%4VpO z&nGwDl@wA@6Gxwy7 zuCzG}bu|U4HC5FwsjyI)(#O1|j!5G7?dt5Q!6ajxRUWl4KJ4sh>_o|vL}?#**l?M1 zLf|a4Td3=C5W&EY=HYRNUdJAx((NEwuhh|fMGUvxecLWprWmm%#)!j ziNEvTcpCO!z4r4XbV>_|v&rsdJLoA?W=s(RR^x41mOcv6AT!FiRj^EP<8$S9|-bF!3juPZ?94fbUP%sY5pWkrf~Mv(xp5){nf_Sy~@xj@|90!D3; z4Yg~Z<_I|K>JxlbbI8{d4q~5UCkE%ST<7C(ggb(l%%A zf}F?}K%q`b;%4GN2pA=1Hqv_`0$Q`Yvw5Le*{YVor%Z%E56A{uEyNFG$LP^M!;Ny> z#=l50R0N4E%5?2dsdp|BM=G)~>zgJkOp9gxr7YZpS5o1O)TfFK$-hxvZ#=K(fd0gx zm;}!2<+p;cIRRQ-SRiKnoZHB!1=a3aaCmw3e_K=uPa96c2Y#rZWHxc8Ns%+X310vj zWFhn*nmAadiDR%L-*u48(rY7UH*7_q;hS%6CpV%ynJFWjRo?qnzW1+gD={WlDWuH> zZC;5_i_v4^hG~gYlca^FZ!NTra+o$n37F1?R1YSjC;uPD>9Lc7siBgacmZlUPI_(S zHdl>IzM^z(VjfaH|IFQx7xWUdoI!~hax2M+l9b*8?v+J4bd-(3aPRtWl($|NlJFDe zvKS)y`RmXAlwN=^&sH(Sf6XWH0Dn%P{;zWA?M4IfYPN9H3K3{i)y(lSZkWheFa#GdWZ5)OaSCmje=T!VF7LYqxn$e18#8f}F zlzA?_dSFf??GK#Ou$mL}ZiUX9*b!O#z4L$Z^rn%isQd2;UEPmKb zAY8!&&?N$;CPLk~pBDjjDD~7yZ<9s$NDYqv&l2Vcx2xG@E?}2In!T=m^>U%Y{wS4u z@^iQyEadC}$S$e3W9K=3uRVs?Li8@cb6U&D-Q?$81q(&4D&-Wv{F`c#Bto?tY#fC) z1zDbMfG}C%$J|7{oDsPoi?tmz<6+=5uDIF8;px>?q)_+q*OOi&-3{;w2Z@!`UV0<5 zsZa*Pp3hQgs7HGLhu0nb%~r>|PjA>2s%!4-uL!Wts)KqZH%b6y`i$vViE-C|?0UrZ zAl2-*o;e;hQLI`#&2J_r>0RvQNA|r2cdz#}kBD*6KVlBrY&si9Qg7(=j!bjE4df>! zv(w>Ou&wAW%lB=t4Yc0Uf(g9WUKg(kY~KcZ62^A_k6&Z=N@_~(fo+1Fg!@m+(9Evg zX}(vmJ4zyBz<8Niu&4jIa8Kd+S&hmv2>;I8#cE)kP6^fZ{JC3A?8U6NkKL|Avb8s* z=Qkv4!iwNY@6EPbGR~JhT4~sSc(yUq=N&@sZMF!=0Jgx%^$&$-WT}LAHMxPF4dtv5 zE@}Zbr;z;ff>g&xZ#!@pv0a;o8TB?=r<3Tk21hy z@xr~UZ-M>;)o#1tq{@LbLfE- zAwePZCHU@|5{Nv7r_Yw+RQt-GJ=HUF4z!my=}~zr8-hsY^$8cF0hp5EAA{_uRD;;H zjR~-K-mLy9`~F$>P0jiE%SS@YR??q|k^S%e?%FV~7!f9*|y|-|Rjb>Ru zWWvZ>KOtFnQx37Jf~~j}8+tPHFj!fN;U}66KJRJ&9WZY05fnChh%I|m%DUKy8*>CC zD(B!HxQBSTJ_C;p?^cB}Hm0ZQcd>yi?@XTzp-gkp;4+-0rZ7uvr(;HbWi zLJ&FmlR`|)1Yt=gnsE%rli<P6wC8#Ux6&`Oe7Nucpb-*%8{NQb|wf$9_dJo`(>alD=24`HJIFnQF-j@ z@KCO`mM=Y&j7a*$-eC83BrNZe5pk061e+{OTIk<(U%kfkENm zIO^e`3!g>=g1g2ukOpGP6~>_(>v#Ci=C!27SFA~bE9q!@B@8}TEv?Ozba(8~O9|7F zG!2MVF7j7>*aLCzU?0_DkBKYpnVR*k$%_bY&3w(ArWQGs#)uMS6W0S}oxiN!M(%?t zl>mZlN);5E;AAwX%$ws|udhfw5;?wWg+!C~gn5qe+U*;&lJ~-OC@diQ?4z`y2di79 zJ4h3fbw10ileMhUD|xXU>inu45*hjmJN@+Z%?u=Xl8vV$q#Eu!4b9Ip(4<*~8bWvp zdZHyfx1>6FG!MX10`EEhOfV0;Je2*|gV!vV z9}_yoTH#U7netAWX3QXmRdke-)sq|?5m2Ml9dpjSF|X%Tt|LE#WaN?*(npq8+k<;6 z+P4N(C=&P;InGL)4mch69#fd~Wv`)Yv?@{8b{eehi~++~DgCQjqCM^my;FGhu2+2xRP&rq}GYTT&n~=_m&OSH_2m1I5 zDIJe+%NIAwPgrD*p{27>AHHocJcjE6( z#P^-W-@H1@?J{qQGKul0Jl4Lk!WyJ7521UTeNL3O%*}8%yXTH;B7KI16}(3tu=L=E zjas`dlHQi^R+P_wX=PFtdos^womiuFtTDji1uB`=#8g3YfAt6&wOc7bXS6L;Q^v zG5g*7$0?|3hdho}V%Dd!N&pyyPzZVh?=t~UJee%=YzU=E>tOpna)QKW^nea%7s3#pBw zo=T_nS=j4h2}BS!usgXlcPCk5^&D|l!7hd5XN8B7JQ3&(op&;T(T8uvg14x6ujK<3 zQrKHdbMqZQ?TN-d&m3?OW2zbHnUIXwNs$xaf`v3|E-wVEDJ)5jAdljG!Jb(21G$&T z4Bf!+h*fz@phDEWxx6s1=A(mUPl&sfVa~lEC&ix23->Z`^v<3enbYfyJ@*1?ib0nb z0tQW=rKV3`#L5pE8fLsHsn5WLzWG?`$ zK+o`c1CX$?6k@?WlkSd$V|@>xBrr8rl}QaU{ju+Tr@4)Ox?O4^m3bAu@AoO=#vbq| zP5ymaYO;#<@k-x0H{^Tg_}$(U6}u=#iup<|=r z7IC8L_Z z%<>E(v~tAcKXrRov6d=@zJSW>#7Z*GPULJY=E@=Et*Z9GxLj*8mxH)}wmmM-x$}k| zh7Q^W6IiV^Y>6~5hw{^^edY~kg>U+-(%0t&Jlr6^GDhm(bB$=jJBT;<%SfSykZYIv~D(|Hg7QL0|X?>1TZxA?nSYnEnc zBGoa98e|zSNhbS7@c#wbe;SwmJsojFdi8tOYmIx1W80banE$jmr%v}>kw0G*$3<+t z{MmXxyVIzy$`!B4ukXpP*ZU?dSA6fn19=xfPlhl?3prn^3U@MxdltZtEOWSLgK(fr zrgKx9xxkBV9uiK<+p1lJGsF zDa$^r!yjCp92sGvnw`G`F0;}GXFGj)^7Pc?=_`|`uPRg>Uw7`}^t+R%uT7qQZ}Rl@ z$zH@mA8)8>=s$eN<*&uT@jJkPHe%x~`YYt=m|Juj1F{v<_K)91$uxWAx{t^3DW!8~ zU*!Gcwk2|E_9NK=pxnTNBZCt0;G~8f?z@Q(^_nK3<3CF>eSH8Ep^ugP7v7zNAJ))aB(iaK3&|c}fAswRPY5P8qgC*g@FbVQ z#QG$;q~=VAK`#DO!}Pq|=;|ePS=S10<>K+0!TLwJs8q140Ley=2uU1*&tMk$`p7>k zSK+nNWQz42mL6g}7yjTTyI`TvB;G|MiP8NFUU2HWqNm%z`*+D;{_NgD_$le5|G{Uw z>O^GoT%XowVa|tA@kBAsJ{hWZTg-4YNrvhI|4qN){O|@l!nh)7fi}@x%H4z;feQ++ z{GiU38}t*dXi7Ppi*GpSrQVio81vvhVBW%_AC6!`lxMUhCbr z70%kaytUa#6tQ@xD=98atN?6jWWF50Ld{G$P`2j~*bOjOIn`tApI!>aRQVwVkUwnt z>sN-Nc_|ZI-%CTS<#@T%cMGv=OW$Zu4WtuEvX0iZ^t<}(rR>Vm47G9NN$L^RQ1d%! z;O}1=P*wwCVpap%r#^-Bj5J<|LUfuyHA-9vX%fAW;toy2Wmh3eJMt`LCQnk;L)HP} z`%ba)9ai4bgwUt zkC50lw>p=`@Be0?@Kw^RYl4?vMM6B>ugyoI68)Eii4R{C6L97>DkwyVG9#rO)ek%! z{D+rB2b4Pg6!$ENix`gzef zRC7)zVrZ~9KJn3DVl-W4bd%W?X;{f2d%bd$lj9eSy{haL>Q!Z{mO^oINIciBnj5F% zrorvwne6F*&=sLdo(hZ#ROx4HT68I zdQJt>UVbXdi$Kb-ki+1(B1tYCadX63BaOX9$+ET1H`M@(DoL=w)r^F}W&v_Wkb758 z-;YmUrf?0)lq@}*S(u+qd`$*%aE#FYT0zOl(ylltJ~Hs=%qoEuD*i;Tnj-tur>{A; zQ{N9eU~wiTFPbPEpGWZGAau4XksLVB8p+8PTyXO8AdCN-@c7tlYl?&L#-p~zm;>hwH8_)QAMEVSX{Q4*Zys8s zST5y_=q{%Ayrw_fBYvggMHY;gmFj%VvB3u%mY^v_TYW616iXk28tu?|{I+#Y=vfBO z^2ldd?EXC1Y5IiJ$_R{HES?3G_~+%ppHpz~ex--OM*TfjCI}WD9*Ip-!Jkp}WW9yj z1w!~x*hP|7ThZfS@xiqF!XB{2Px@-7S>cy{^S1aY5;=Ezdex7t!4ueur;c zZ%z!IAH+wCx<>Tzy8cp-#2d$6nuM1-Xa-OpbL+UIB+37cB51+55!0uoJ|5a$6ydZS z)iHHj z!atp+8V1`5P;qh|y-&8_aH4FKKyc_YivqzG<5^tG#fgPfkjKRGQClLCZaIhc=mMuC zuanZh`?Rlx)8@+ey8<##Me{THr)(=a{TU@*-l`$tzZI@)^#qtK@LWdsv z)m;_HLg?A>w1vi7qfnzV4$%LCozL!JwQ0@;XG z+o+mcI}aa?hjh4JKB$uB@Ly>jefpCQy4OHHX^|~sh_DBbn%E>dp$xX6epyDbop?du3b!#bV3@6ETVd2c}&wuS`R0}7I>^hcm zKYB`%B$A>%_*4mfDq}CBu}5H8NhMb-g3W+SP}$Jn+##Gi|IAa!s_f2+Yk!gtQ&q7f z!ud{I@IS>a-FxW?N+9cuewn2zC&q139WZKnKsHc+_pIH1VYMrnS5!O3*l47h~pUZ0dWg7_E6%LEqq6J^?1j? zAf!l__zFt0^p4yT-wSFv@N{mls3why1~eCeW|izBo^u&wtuS9=T4@JeE6KV(ZxUEe X8?aKQ9+nBm1HBAe}84(e228D~l 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 QIHO}o{1Yt3(IZFx0hKJjqyPW_ diff --git a/dist/qt-translations/qtbase_fi.qm b/dist/qt-translations/qtbase_fi.qm deleted file mode 100644 index 980e087c35a8631708f16621e472fc7350a7360d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 160668 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%0AeN)+$vy&v#`|%uuDJ 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 diff --git a/dist/qt-translations/qtbase_fr.qm b/dist/qt-translations/qtbase_fr.qm deleted file mode 100644 index 8353f0a934abaea9c5523e2318dded0974e5f3e1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 166157 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


v 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�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 diff --git a/dist/qt-translations/qtbase_he.qm b/dist/qt-translations/qtbase_he.qm deleted file mode 100644 index 0ac1ed2207907878057148111a902be89b15d6f8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 139222 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

bkv6w3hDKx%AVL>t!`+Z9v4rC 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 `%5uxs){ApirD7m}OLLEnX6 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�dE&G|$328H zvpExL3kD1wrLQJoS)CTW0nuzgc+v**%i}*2g7Gu)T{vlrZ(5V~lKsA7l)1>%fN#@* z=jr|u-nK*Q_6_|Z*HiOZV4{Q%@@Si|<@=&XK5W`Z&jCgGp7z{KQ!iVlCCh5FIxV?w zyWWdmN~R~j5eF~BeE1_PNO+cQI44R5#n29BjLnJAn7{T0p?zYb#GWuVJSJEmZJY0~ z+8tJBk>8mOOAB#vJe;&E!EqkkF3IuA@ie|;Y7pMe#dE%OX*`$1MD8!LK^||nG2_@5 zuj#o`Up^-}KdG(QpnPA4)#fzy%ERf66>$as91o)Hn0>N`1zhe)IDwGY2uo%mRzKwj z1kjf4mmdvYYC>9!e#B%j+)D;qkd|H?sgZ2K@j<33d4x5KGR7^8En1e!7`mdwaVmks zVR3sxUgD(APz_p^)jg@B*dQ<&n+#T8hA9OnTmD2tKC+r^vDikP?1YtIb}$|2YXPty<|gDMpzvpw|L$yMx`!Ybv9Xcp%}-sDfWC* z>0Hyhl~yqs)Ti1q%2Zv!^TV?nQyJ)AE9!;v2vLD0E~( z6F~(f<807etSuqX!4A8;H=FWOMC_22icHDY4SW#Cg7lCHY6g4bt?9u_gZJ#9rVJ88Cf`ju zFOGQub=7?!uIfQtU~!tvg-!%@C!pw_?ghn;lm7 zkt^dulBJ+9S2$X(2`zFQ`|JtCT_57F5S#QKdvy;^3yYaqOf2?EEpw4d3En!{B&i0h zy89UXGf=qzPTt$#>qkE5t>nR-WpQSVFlAXC1wOHw*m2N{;Dmwa7A65FJpl7XXgxQH zSO7w1MQNl~D~Z+tb%+Hnn13ai+W^kUU6?Ry!GIEM_G2eW*qraM z1tj#LLkz?^DJ)2Fn2UNrSF@!ePwtr%=Xow7jy`8hjKVHMRjS01!jr@1c%JNA>XTBO z=DZihneYEeCI1x_L$QB-{}Ep7a?;R(yhQ;PC^Js0fCB@jarEFq$JK1c;mGK3I_aJd7JQCmT*-JVmJ z&&FwjY+j?PBqfkvFgO)nzPR}DFKNa~NTj_G79mXvf!Bx46{mA~W+V*QT%!*1piU~Z zvGvEgXdon;hzm@J$0zbLSyBwrPK1smj%9V0ei9mvfS$X{bb1nn?Z)M$iGwKCQxxe% z`jXMGWK3+)-N&-ah8Fq)I_N4(0XoCmsCmKL3!e9HP)0sUhhBY0w=tPBGig)@X9Do; z*;o;Cpbo!@uFi}?2hx|ExkcVtCjQtFHmY{gUVbFlArRY2LabZ0Nu9Cky=-u%DXSlG*e}peJz+dap(%lIWg?NZ7lBwO;#zLaiYf58mN)?s zMgys|+i;SS%Xs<%{ge~>@yM&Vo+`L;zMw!FT$or6R7#+Tr<@zl2xLE%CDp;=G{%tu zm_lDH4RIsHI?2VVp&`s{%L|OvB_mS71#jbNqK(gvg54casu78!0{Q~ogotD4ivV?! zpHWnHBhR9J3Vj3f~)Hae^y2($&JU8y4Np*I=S_A85C z$_J$Qy#OOzG7M8_GgQV2@Hz#Pn&OAsqP#h2CQ8{W(d5du6Vy;_yn*k@l%IEcS$Q1A zx`oe_4R+W{Tj4>220)3igBka#5M{XnyiZ7+6-Qd|DTRem8m=Z-wKkGT90)L30ZlmT zoyZR_Lq&$fV>c**%_`>Cnb584^trU|LSPsjLbUeGqP4JQr6;t~G{g{Cl=fUI%UOjs zb}BAp^NC4`{&ZhWH+tTdR3p1qa%DdOvzlTDG{%8gjddK0-b&(U{<;_}cHuefjb#xH ziA@d{(ZpOJA$8O9q|NnYY#9uW5(&(8ofJcF;@}P2VXobri31!HM8;7FKOYO<{S5ty zM!Q_IQrbk&P4F3AYb)j=**HV8K?&KH? zJ7)KXSnmoR7eBTSbjP4A?qhm??Ug06xfLvbn@)f(F$x)}k~n2B)+}{2H{!s34|9&- zewAomnKc*ELNd|ZG={}Fed1HY#i9!TX}vVF0|`TA(W%6FsMKqbg}L1pmIM(8NkT}S zS&m^jwfkM+r?9h~Yhc!X3~!I;ECy=2c;B$8%`vZNPgn_L93Aes*xN7D>WI6N?^sTGUV@O&Zj zLXjAQg965E-i11noyQ6ZH!hEO)@J_Y*ADP6<4iCI9ztS?#OtcAPLQ{3b9Z62dG}CL zB;MxkgPkju#8+90&o8|piIFhvUCBZGf~4LMSy5++qFT*`%VEj0kA`VvFLb~n$ikqh zOh|_B;j9O#-Ey7Jac#1~X6-R#t3+7}5L|U_7c`Ta?Y8V#q71aLDSBM_a8q9VOs$R= zTAabqWmP~eJ4!e6fFwQCqdq8aOVeaMq8Z?V81k{B#}(Fc9}r1gt4d59UAffvU$ujpPWK~c0Obj## zREgkc!hR`9T$n3PgD~Z=cOe7foD2ID-E#3n3sC}Ucw#niz%J>vPZp{GW`Y!V3)N#OhA z_=$~(ahzJ{*eluL5Svm{Av@t^OoY!Xq);2s&!9*_b^;f z{KrFxz!0c1elhCVbTMzQ48q+P#$05HGO5B|K)aJnoM*I+Tx(3K04LJ3f1-Wa#>Zt` zf(JuC_aR+HgiV3aoQr)Xv&f|in;}cgRAes%Z{dSLS5Qw6*D6d_Cky6zF}SOJ&P8CT}#A`W}CTHIA2@b?Cz4En`eE zIQ|rDMK1(6I^q*pvjj;qMHo$r@kwNmM@6${NW>D^ra~H)JJ#Uc6HUEiO{7#e8!Bz7AzWLF7iFGG@WWa7XMnw4Ln6euGP%8ORr&91~oJpQrtJdf<_Xa1>*7@ z6W#(-gGTK5>HiM}T}1v-l!Hs03r*S>iF+1;+zWBe)DgMP#_l^8UR?)??UJB>v&jfa zOAT!)-m>s&su!E4l6Xe2?VCSQ&u>j6hv1RF+LptTYr%zt& zo|3#ft|A?EHATV)6g zf-!#aRrTP@g`H3awtCY2rKGtim=2Qtq`D{A?c$EOUHIM~Di&8Nyp5jlh(j+QDcIj- zD3;QZRB$0No60~Vr;A$bTUm-KRJ$ikd|DSJOie#bjn7%pOZg~i=GslI!leK&IWmHX?Q@G%aQO@TO8hd-JUdJ^k3|iIjwM2G+=A&oVi2Oyrx&ASu^*n>A!Y z9g$A7hxaZTO@0|#e00iE1|~0d|4ben;VO-cx~)LpM*|6p@%XFGzcd~7~qg~BF*XZfcd10AiZOL zhKEdVy3OJ_XpOCin*7wfROO z_nkoE`{5T?)xO)y>BNgvig_r$ANHG$;_q=kStS6e z0x~S(tcGyjK~o$|5_8{0xFE4sjzq&`^NT@QWKL%+TSy$<$3b7lsapV=|jPTb+ z&0k=5h1ZKMlszr!4#EBMF?6|QMMARY*#~)9MC&Vk`>D4rL zvBDR@#e_&58tvwaA}HDZvX|d-Xhw z1V6vxtsY-HAvwNjzkkHXgOaUzxS&sO>X;%&;4GsQVc!i-p62g}ZB@xu+XzgmpHa)H z0VO`HOfJI3M}O>8LeU`FDSa9_*#30A5>=sokgN(t3QpzxqdpE6Np9$;SaJ)qS#b>? z^GZ=a<4<`ANf}{=j`uf2TAoULR*q-=DJ`~3N>nzU^}F2E$ol@Sm|LVuv8E%;eFP<|J19PPI`HIfF(tEv{=;L)0F0ux=rY!PV8-{cWiv#!5+;Pz29jPs^4(h+; zxukA_Dmp6*;dr-$SN!p+?!h2JP5?%EKL8KcaO{7AG zm=}qz%7iS}NJzq#=6RRL6+Cxk!VFrAl9{v~y245f&`qDeN{2Nh_$0YlKF8d|A8sbe z{%RlAlJp=}%oDj#a)L@sKf8%h7H?_v{>7$0m>JlI*^K$)NEPY@(VLELHcJXXdidPL z9Rfh`@CdTR9=cKnOQ*FuEh*;C|D#^2UqP)|g4ZQZv_;{^MNlT4o^$Eq0^g$ea&l8m zBd2^UEnMLVS9nP+3xmEGV{2mg+n~-Kma$gL#oCd>;CIy8>_)C@W1du=z<8P=B`xLX znS~P4!j4NzpMe@Iy!c{+s^{hw@>FU5Qt6nhikM5C*cZ)V^bAreYOFHM3yE5_)ch9` zv>>=cuG$%F?<;Y(FP6#BCHAn{^DGEDxr$X8gltH!M#?ZrR%MAc{;~_bkn77lS}%dQ z94mt}h#!a?xZ)*yD>8Cez>C)4MW7h7FKj&}a42z6Z6P5iF7IV!WDQHetA(jDbeizqjs!8>^LGD zp?cQ)e{>1M7lQwq9lnrObmjljD|@&-)Sq65@+bgxfK`U_xc47$< zt4c@4$EF1%Cnvtx)CHy3X(nYeR#x%bO zcb;=i1;R~#!RC};GWeOdDiOtI%FQiivX*C3EYwtvW{HhV@w5_oPfKmk%3LX=FJ0`Y zck~c{abGFn8p!m0`=LP;ZsO7WLd+_?uVm_(lF}C+3i45G&Xrk;(Trs=Z+{fHd&Pl{ zTMkB`>QXTJ%|Y4|=PQR-oV>b11~0uKPD3MtVag6$7%63S-bCyY!xw~a=H%S&n4`0h zn7w`^rn%554$WDnYH?X)Tt{lHkXQTS1PFdjEE~6t)+<3Cb54@Vvf0Od*1CP!YH(R; zwAhm1o1n;r1r?XD)`W5yepntNj#{Yhy}NzF{@jjYPWIuY}1OTiq5bzhV)t8>O9HKZ*wjZ{pn4T zV$~m9-Qcd8yRJkVTyBoXUF=jSS5wI@g^Fs$T|;y(4MNnB=HC@$I1n#Ho(mFI%Ier_ zd@syybG2M55eUywSF`jCk@p$S{AZymbP6fRA7xH>sQWaOOyw^>6 zQGyXga^H_fk)}-CNJr5JiTp|?#KaKN!@t8qIZ3~>UDbmWCA9>crc5jj--zqL%6JF1 z!m}4(bP3e#z91{fXIhT}raT-hMrWv%w3zg|8F{ctu<+E6a_pJUO=|agg*D0~q z7GQShrNDij=@z9&Qp|+yr5ck3RTz|woXr=qG`Z2gwJk(AMKm%I@#xO(Gj@uIZ*xIb6Hb3=(; zq4Q7m3v4{#{F#QjDa$Pbg*^{IIk8p*+e^)iJf71*r*q*3E7&mC| z>!5&L2~h^2|ontc?KT?7tNK$gX^r) zYe;q<9aN(o6tV(Dh?^o)NsRXU=ptxVc=9ijI~7tkm+xzFt(W|A!tI1Sn0Y{uGFd}d* z#9S(G=n)jl!!CK-OVm9qdAWE*8EYyJ7k`r=m+k^zt~wnq@$fWu7o_mazjx!{!j64U zyDY;6ewKqo1G42{r36U#x)KDvD3`sdF^Tu@-0u}a?0`}@EPa>}y4e#DK`}5-F$IAj zRF6_R(1s!CTjfCrR^>) z<{GpF*MG<^Nz4B&yCjIU^kqKuW}zgD+7QjEnwW(ewk($#W1+^T6P+y(B%PMq7jRh4H7>mY?Hok|iaLnDra8^5XP z7g(4lA`OdL@(1-VCKd)Hi&>DiX0jFLr3)E0KHKYsH6zsO6<184yEQA*>$mfoVm%mY zx5tpCsFG=-r_ZoOr7~K<>MG)sniA6vW&`R>vUs;oid;xxB)SV~yD!ty;!GZ{RdFMQ z32x4J-;vE=XU;wmSGDA0m^o1MvnO;P_X}@l)Jsv;aHE8D87nRdrfE6a{8pq1LpxOwWAv6VrntrUD!-1vkt%4H)Ac7=%S;x%uO z2X;z*sPag(wa|hUCVK{}Q^j^6pRBCMQf#mAwBB=$)b8>*`daq%k@N;F_5nBDLRo4Q zX{Xh>{jz};8%BtG6V%<)Sj8Z+%3ym;%Yw2;T@>5zh->gvCv(rbWXKh(S<6;vG;u!p=xqNOD2y zxUaAxZQZR0qGMxBF5ztu+Jc>#s1sf9U}0luChZcPu{X@H`1Kvv=`)S{`>;*jozY#< zOyBI1kE|>qC8~H2-K0HaYh0z^=*|5M+!SpJ7supwCEP>8@O3ufNP zrRCIJ=LfD1TZ*HqCsrh3wXIAAERoQ}u2>*(A+!a`Qnd7Dr_Zs?ykY6$)s?68MTo1b zLY5Iy=IErtpN*i1OXRH~I5HC=N3ro_@+0OQNO!}AeVMEaMHXCVX3UDF+XF0DcvKh| zolNgxi5FeKL&<6v7lyC^MOun41<8fo`bZlPYFHE#8fw$wz(!n;&AcfX;TdUh8hEaZ zcRMX$mvN|yV`rMUj6=_9TR?G!qI5R>+X|OTO=J-M)ml>azcZy(&=10Er*NHyzIqdz zr{vX8u3}!zsH`^&ZP_feRYTLD(AMl#0mY?qvELEk)v4%T;Nb}AXgmuA(G+^6NID9f zH#08)*B2eM(9m5P-sAV;-!^Hx6g>^Gv(`R}pGY)u|Nn5jE~(A4j)e(8OE3v#ri4l! z0$Xs+xS0?29hNvMTO*;dL{1Z=hhB>c5Z7XDN*NA8aeyhV4q8t`JlOCdFE8rV6rUrB zOYG+)+{k=v*i^2=aBoSaFYR-=)q{=j^GX^w2A7wPCMIDVVR9iF z(2*iD%DHz*xR|K5F67M>N6?N@K!QSalh*BVz>d)inpD1s?Uh&-||jKvK~bmF(*K#AvG=p|<*+6d*IXdOjYP7cqC(lE8- zj-?cvExLE(wPMW1giJxV(%I4{#^T^ASEvcdOued9`04H}czbNuX8CvGa19hyJS`5y z+$i5@g579Ji3e7qh~i1J>p_p1n&4luGaXYp8 z*F?SP>*7Y^en&XGZS2_W)uXlnty0v;1QB0;UW$0NqcfKvzBHVwK77FY1E||P28m3P zm!V@tu=0rPV9fXE8i{1xfDtw3|?drJ;RU=#qJeEE`GYxkoLqZ8YZeVSnnDTtO_a>Vqn?#_nzPesHB&Me7Z!08j1%R7QBvk1$sO#ajU59 zIl>cDB+RC`wB*ECSHMAF6#GV!yJ9LUJ4Wn5@@j~53(asZ@#+zMVoBWp^Yhx09T=EO z5ItRyRNpUP@kOBERkFmLV!jtWi7HtYRPufpb_zvP66jTO(XsUI;QuJ6rX(MN6aP+H zP7fBCRqXqvERuJ;u$QtRQJlqk*-FR4H%b(PIA2JddEwya9z_IRR~K}aV2T^ zJ?)lo*L~VeUzy^m>Fka8zdb@{Y?O@ofAuaJZ%SR4a!P#*jfA5@hK?uYr6i&M`}ewd zlkAP(_+go>$57O;CE zzsnC!`nv8?aaQ)INC9VQ=o(-%EtaNMCVGhm7SM}KpxL>g+s{fXhhPW2CV2w6$#{L6 z#M{v}NJR>`6IbY5k%qWTD{APOnfDOHc4-p=wnBWTg(SYCL6w)Lh}E=Uv6{d{v`a3; zD+=LmjbV*n;9`r9R(e{>iuq)55-Js8aVTs|C&fn-yj)S@{Yf20HOfvhKKW@`_U%?5 z-RVVkgiF|=q`V0C#|!@z(|vTHM6Cq8;#J&fH@-kT49F_ru0o z^IUgyeRU!<6gyGJnM-|M%}SD>!j{-V9)}mQ`zLF#(M6WD>Zm5p8fGhlEZR`)L>-5B z7L+m!wR`Tx7OK*x+`EC^)xbnA75W*EHhl@=CByLFB(WouvO*Gvp9YnOwu4Oep}F3) z{*_mdL7(iz+vRXj8u3%^mpNXJt7OS2l ze9!79QFjZ$RC?2px{7u&cq+aPScsXyD)bJU(n?II!6cH@uG5H?T_V!ym9Ru-r{?%T zt0mFb59d4V%*|wRU&N-7u+4IX@Dkci&GWlZ#_1AWb?04guu>cnDm=O9x3j#yy)5uc z!*TTfI(^5{T6}Yty|!9Dm3(f8W$8jVM(PAFEnWnx9A8{gNAePTSIGk2ip!HbQ|c(>4N(c{|z=O_ACDsz9PGXWp=E3ASfZqep;nT|XEwVld-AZ?$M$+Ni9EB%$=LBq z+#qBch%pZEuWQ+C=&eZ-l|)-Zr!?1@YO?r z{ES@vlaKElZhGHpZlYuOXTEH^C`I z;ts5|#D7Cy@(Rh!58Tr8nc0p}X*TlWAsAk(bM|U>-$J2#Q5Rjz?-`u08Te11^%foL z!`gr08H8zc=)td>A*bkf#JxHEp6a)cBb{2;JrAAPepGp1j9mm&S#KCPs1+AEpV$kEXr5VM zl)H+*Da95rB8Ss<5kF01259-if2RMJ@MrqIjNeak1^Fe0J%O`H9jMEwEZ-fPgIN88 z;Jyk*DO&sxAyTyNW#RXV$Bv%84g68dX98XcXP#`!sv&!#>XljTySvI`|a zmnh^fm0Lt98%ppJp|1J)(jxWSBGCrj`O2E}Ns% zj0-bGU`GHd%zy|nD&cXK=YYCmK0k%3g45_}Qsz#lrD}z2{^g26CIJ!v1V;LlpybPw zDCYv_5Ftdg-V7!}1m?|I1Z~kkneY$=5NfLEPuRp?qJ~ZR;%);}r8K>S(zNI%fI5hx z$o5o;O>e3MK06z!R=R3MGKuonqE;g8vS=lWP_iX>H!1v>NqoM5sZGi*E^rW|RT?Mz zEx~h1!AHD!`osOh$5QG0N7GuH*h?^Ke%jM5lnk*SA<8)55VMBpL0^VwGPcxNoTx0m z!(dxhb%;Z!xZpUJL4>!gf!GHrYof+a#FE^bYMnY3Yun8KeRgjKmj(S+Tptc@Cbi5hz~H5RCSO92%OC?Xni zk!N7jmt(C#O<&31SVC#!)=|y}W>_DOwed}H4V8IM;x5F$8pGNL!0;(iN4+8==4ysp zd)L-{C6VwuDTIW}{nkO!o!RQU5a5)jwnL;VmFu zsR%~`oqyTcgDUNdd`VnN#4p^Jh%OwW=gnio*p_qonxyMTjn1sKJ?}_sC0*5g$;{yP z_Pe<%Z;^U+k&eq9urSi}{=TypPOpVU?lyv3fO@9xSF6B;b5w6zT&^rc5sV;Q3hZ;0kX{wCv5?Xd?1l#JyR8UoL$&y!;h$Ttdqz$o?YbxwWY>uD#VQ}NO3$^ z;^p>HRf>YTD%5&SooJH7F@(bfxoYh=WKpS1k+|C7>jbcobJlc_3kSH=+WI%rEvw4U zKrVBflhUXox2H1zA64660^o>{v)ipv{_8`SaF>f7K#^FsXdjqf30*ZKPoT5tvo#mZ z+Xx3NWY9f~HL1JCkKS<-ZHKnlQ8AU05ikMPhCN5wg3NH$orDytL2(t{V^C2=zLBQS z;Su_*MlLo5ju#OU+)COju}~LHJcHN6R>Fx&6%-#aOZC)b^@=6@7<#WP1Q&^H2e+o9 zwmMW!ixMZ)DZVCq+}3i-R^R8M8{C56WyCs9<}iz8oa#=93)vG7N2NYWI88XV4;P1l zl0*o%x1)F6GO%udOIY3GTU%csbVa-lx+JMNyz~4;H{{E8~$3l|DZW62Xcqs za?5fLuJuVniF0fqcXIY}!%Uq3I<0a~ZD6rR=EDQ5<3qH{q^^NTdWyIa3Y1WVH)I@) zre@m_k%uHpZHUm)4P)}^>gCX$ekccdYApqFivT^L2*5g;i4BqhAVcZ>h}E@95jd6^ zMAST2;=C;gmDCy&=%L_|g_0@K1ays+WmTiuD?^>!M;QV}*QFt6hM3%@(Bvq(d9<(? zSoS_SBOUt#Gvb3#bEjp1RG_n`B#9sLzb-3OcD`=}V%6qyImmk?a$FCJl_|)3S*Y*e zJWH8!Mhs489b$l@l0OIeS{NR&!9@ttB~_%+Ony*yiLZALw*y@ z5p|hE7Ycg61QV7+Tyhk4E0aq^3>J*+22U@K2pwTgS8HD`MwzPo#Inhb9_Gkg5&KP9 z%tZB2gVQ>=Cm`afNW>@LT#*sx`dnO76d*m3Tnk(*O22=gIjjhe1=XI=qr{!$>+V}K zlr~1SqR7A{OeH^czj|Rb51MxyX&32kY5u z!loSc;yhG`Mey7VWgD<)QiWnumXcsLWF>#=@$nia-XXY%!yw^0pd55ad<5Re3TV`97L_-Y{I%fS z6rk(B!-CmqE-yPjOK6>XVk1q9{q(?ADl-W!P^p}dd|N__`gwu%qIcKpm#0Vtgd3wc zSJZ(Qat=P#HqwLh95tRd%^Jm%d-BJPE!p5dL5tGFLFFEiaO0Z)M!EIWYWj65)rOl$ z?}_HEjtQZuQLGt?v_(?ntvDf?SD64*o^%j?1ZJNNtjd=7S#%vf>^E6c2)@7CeS-#^ z5R+(H%O|@o)b!5-^`-!e>v_tyQdf3Cmx0b=Y|=WV$KokCU6`qgsBPY$wF*{N@E)(Y zi?7_j;wX#K=xN#8_l)-td+YTx(7>=QQ{qnV+~ztr0dp;E@wkB@66k;~!tYpsTws)1 zFPA7s%Y}1rgXwh~)GELkNqLHzQE?!YkEMEzD^Dz&1C7}n5U*ht5Ht_<%23ns-yta0 zKu=`hpo;Me ziV9xe=G#FycpZg*s|zUEkJB{4+2S$+U6ahf_;Uxwho?@4$}b>UH5g}njpB?gyJB{|MZw`VNN;_de3%e#v506M8yV>9H$>2lWw_J~KN?JsfjWqAaU2ec5c`T(I`fB! z3Ofr;fP3AaJ@dYQ!m&|zr_FMG#6LLFXbg2%Oc&3%e5JTe=Xi0z&os5!g!d3N5D*C@ zD~Yq>Q!~{~?|&onRpc=L6%NH~-ZlBIs1<7lJIS{My_`_Hdja`|#02#qb7hA)%Mmlo zxoE8kWuzY9UyAgsnf`Afj$kAb*?Z+V z_HW3jKz-sbG8YS(dGEdOx8;{8TUc4;DM4f#^3u-qAIoG%GH0^mz2k%Z+bA+a3o}$M z6EPzBZuC{oQLpKQu6M&1WTrA?X4gt#l| zCKmf)fP1TCY7O9a++M%QS3)h<8<#mJ2U!=oc_x;*1DbF|RbahGMyXPfZ8TjdSB&#x zEO;}-1$ldx1J=-71lW0ad90I7)hl4Er&1|&Z*NxtdA%d*OP4_i0wyNc!r=}UtP%|pk2~n3@@J9&LW)12M z*j|JU=Nk7@ss(Bsyej-%QDBYyMs5;T3(QDqlLd!$gEC%j#LYx;;%32;=6;03mP@Iw{(eq-vyZ1% zvD9AB?}^&bUqwC{mov8yiQ^I-@MkwL;GP|IDgG$*q@VKqFw98bN}>S=EEZh@15wkP z{_khj(p9SQ#g8In(2cR-Bj50j88ty0AIMWcB^Lv=FQ*MU+;#5{c!rd<;#Wy&9xURr ztfaaM#fT}cJG+C%O8crTjcGt>N+TkZD`C249UnP)?y_ED;}Gf^7K$uG?Q>oS_3jNk z1L-mNCeM5Uc>w;*+lHtm^+FzT#hCuWLd5iw*~QEOuQ+~_=l30NMq^imPjg_Vd(v%4 zAfoEtKL7z=K`M&hUAdV!HI>dm$>2-NzKB*izWCvWN1r#gOpGp-5mO$qZ7tQV%eO&Z ze9ZftF*eDVE653q7`hH;hA1}mI}osFv{Xm1cZ+Fb~2xfxKqj;d(D867=AHmuRrZg5^}CGn4cvNEl|#5NYLD1W8H6RH`YsBB);(&QX&E(;?Tczt za4Dv=&f*?DVr*&yB=pj31m7fvn=kz+aOl@el$IcNk=sFM-%Xh~rPgUGu8jIL@yPc= zNSe9edVLg-CO(RV2ysh$y5xVl7;)Sa+3TU%w1`;udecb^Cqo01OGtaEH%ujVe;q7D zIansy&`C9Q0kI759ulRS#MKI^!FOsLFFC)7{mNd?@r@t9va**$Rzh$Z0B4T@X;tqY z7brjOV`XoT1D#)aa%Jyc%QtO6hon2yRlR_RY&n+G`;zG0n>um<9Bdgyi`}QcT-m$N z@(n@W=YYJ=3At5{8pSia8mnj=jlKKu78Or~5XBUtEN-(LhRy3i2@J}rVtAoZw1j)~ zmn(bkaV+5;#}e*wE`cELHz4n~K&EdF7~dRld~?wF=Ah%7w;SKQ-SSNfa1F!4Fo>1- z3SvX=aCR`oN@9pI=J&qJCcbC2E#mtldM@JoBaZoGpmjcg`Sj}Vn|oC`z*KLYL4CGC z-08zIGlj`txq->Gd^N~lzA?x}12xE}ficKNh&aqjhREo%pYuMWNaM;ryU4&d2BcMe z4w2CpGekz8U1apd43W`i6B#sZB2Ym)72Msy86u1)n`9ledg)v zv!AZMm~p!L?5C?QW}L1*+v$pY3x)V`i+VR<)uO2O!S=jt@2X>M@`qwuWv=`TVI1mEIse)ZmN6fV!~2 zQ01$nE>u!>eW*dz*MPb>$xs(3S%qB&)TIDaQy(^=E(xeYF%Cg(Mq@6fxqHxiZ`8L&KAF_+qKkD<042Va-R1oSvFbS zBU zjY$c&ok_zpx3L+Gwy{}TXy!h#*J!d~tc}(!3(XKiVJYh`_avmV4P`f?TR-jnd$?Vw zfYXm56uM#ukiOo-ia4pEct_yR_i!mD-&(lg$OUvXr`+yT*MaVyd!XO!@w)GUCB&vU zbvdw*vafIi)yG={@CA4Wa1Wk=kD-ngr7B#J{@luHQIuP#{oMA<{ z2bxJYI&&Q`wro!b?M96j{L{5(U-!WSyiko;y?@7u?`?OB`MrOui0^H;iTS;MkBIMW_lNnt ze{+cMZ8wJby)VAR_cpn;0e+v~L;fnc_IBex-!SFdbk?Txa8#C4yHjkTve|W7p|^=6 z$*vr&6|LsuWw~M~Ih_XpXRW2PS)59jv2#5p{dvojecKhLjKULo$~OB|y9QE=zeNsr zO`uJW4O>Mqb4Kj2jQU7xZKDdQ%RbuR{of#&@1BbfBYW9G+E%3};_BERdr0p^BP)jc zABr5Z7dKC6$le~?5Uq{kDTg7ku9Mpg$=*!3Ffi3u;7){Lb>I5fhV#k!%1+>hq>II0 ze#2N5nGUjH2K&^N;lC9R`7hy0k`cC=08OZ5iE1QpiCRgJg?W2XR$22osWDq652B5O zS|LjPA^v%hLu}_{BlwoGw?D@BqwB!6jU(Kugg!|TCvKe&3AGr13*@1or0?s+u2C>t zJlu->qyg^%=o_6dM*Et@s?K31YU|jjtj&TD_yyroX+gmL0FO9njEHxh6isk#L*m1` z<|g#4R-@XFC{1Ji_G+QpWqgZzYZqy&Y~LpROb|Vy0cm{5C2Lz#*Q@OK+ukKMr?_w|KWF1D{&Ih>%o4(Mgq(R%0!V}%2ZD* zYLch(_;BUG<(#G;iQd7>Em^PzCp|P&^zKNB-ae;J9H)k4sOyA!qsieUWunVJKNP!9 z6L>egv8q%^{sQV!Rl1V{B`!3ls_jwbG%mG}DlFYctllz)Y^I{w*jF@R0p@T{IpOB| zSu!Phe2sUF6MQK$TUX-LvpIm-1haU%lR9*^R6>*irJ$=Khuo=)I>U6^XSE&))H0Nf z#UG9z6qiG>LmFRm=g1<(c2`n|4&4Zh!$yT-AI4!WI$TSg77Fv>8H74i5f$xdTgjq} zA$#CY-ed4+;~qRjF6`lFRxP47Rvu{FK8!=(JiXAwp8ct=eHZpQ2DXwl7{hwP=z3CJ zJx+A3WZjjc%%-7@`)HKt3|c$MR0gl1CE*oh%>SiKTcu%#@7hVr$Tv?_OIKAn^CLy>EWce;*sys@3PnR*o}Q6 zumn zMO@nY0OtBL)|>6*beK`5_8o z7Ew2sTEx>uq3Yh2rl%d(L!892-iy_Ir`flmL!Afj0(Gf@;m9mic@vMs0Z%b&%VL$a zyR;5ZyaDdIEH6WEj-cro+$`XLn;1^l=)h5jFl<+n!N%_ap|CuDH^9~KdkEYz`28r+ zm2%z%7gf(@{{f1@3i|2gzTsane)^Pmg?n&PG50YlXO90<+em7|zEabL6P>pmEteLy zQ777}uH*}DK(%4K4yoQ443Xf7)VA@G{K~QG?GV%?uA6P*In&^?@r;SQj5b7_VH@5lfl zxHHI=YmQu?2uu=kz!(XlMdt2=ZkwZ&m4lMZGyG0+PC$kzc~-?Rn}e6L*d%8T1qszO zoJX&yy6a4e0~83%7opdjpAflB_gFjutBa9iSH8DXuQCvE?4(eVQ<;K`T*I74^~LKh z)Fq#t_}WOsU`M_VL*JiyW-l3Fg{qyBTpzj2bx%Ko*YuFQ0cVI2@q~ItFa0L289bev zq*5ug238`SbK0abQzbyr#en%c0Cod|HH%aub9@=_JF+K+W6sI8F;r34ei;Ox_|C~~ zdZCT)E+HgZ1nD}L7k_W}>9u-Df``b&1Lv4F*slK{7}T_upvN~qSeif&PJWTmCaqJ# zii%rML3cx5bzqy{fa~h>yx~7Ygg$(68d5uNI4%a%gOOwF0gO|+iw2-mU25iFBmgxC z!ux|prI3ppG`wOw;rStvjr~X#!zD)Z>ktdZL8iKI6;yj&tcqNt2E@FXwRTryRH+<2 zrbUe5>YA_XNhWz@Y6vCsqlYKxI9>g_{GuM(fFkMGh3H|N)I!6In0%~}269lodyOrX zpTTAkeyz3iSIgYfKoQpsATfN`%M&zfJ>#_lD2p)s&_-*%cH&uQOGsO2;)mcom9u1|%)# ztHE`Xm6^u!$IrC}sR8_7Kza|W(Xrc`z81>jP-om^i(hT{aDyI)wqcwm6OFI^>V=74 zr}WjUf0t=MH42lJo3bdl#FYr5VIN8c#%-yFC*HC(;@YlFk+Dg5f zVbNiigt5U5oz(Z6cUQiKOxYQFMXd_Hn~X0Vr?M7g^2)9!(DHfWUB(=6o<#E($28Ux zbF1gw_!?ftQP>H6?Q@M}_D(W4I-s=UGLlyiLok~JHjj1&?jXy&EgDOsp{vx6NT|!t z=P!BT5pUSOr|yhjH&(TJ9FjL=(8~N|UI`#V?R<_0nOqv@Od+yDNki`iBj#ET&qE zw}&^6y1L_Ch}u%0^q!zrYOq>3E5>TFZ#cp=c>^UwQI?R_REx;dh>Xgx%R;kWppi?U zx0n;jCPpG!@1=DuO;Oj-Ea2Tf%s{w>-c)|NfYv~@Gv26YoW|Z$Z;9W9UQJ#FGsS+b z+(oor${}ep5>D~C^C*!r#|8GnaBfv_sJI?Vnqiq-7_W9-qk3Kzc(E?DI-v7NTUwHZ z2tSKknxdQbz{ZW39B+nA5po8G75cDa4ymrnV(vWkPm+{R!CS(u;R~pZ%l(J;^c-M& zO^~a%=&9JIijpVvP}lrKmGg;tWJOI)0u*56*qtEk%?dWvjzSe#I^?cC7#cF^!<=0l zY=;qqybotjv?1V1XKZ?(=B8zHAYNemNLYqeaTi>JoKq_+>UN0t|enXiEiZB?&#jZJJc~YR=hw)Hu0XI{-@IW z)~c=ouSi$1-j`6FJDdN|spEWDUM+k%{~-{BB<~9Zt8pxopMjNyh2Ta31o?L*{5ywCJnA8ri%kW9p>X6BIt-QO zakFw9}Msf`#5gup6g6-T^JzJ%U(2rAM5+Ef<-+}in>lJFA;#wNuyUVP!D|Dkpi zw0yLA67jKtQ7vLr?BLa&(Jgx1%?ev-60z#Sx>&O%C-i1afQYjkB!~uo5G|_ARH#HF ziXDw3Snn7bJMMzG*$aU~%_gs9|HETcn?yT4^)$BAR!-z+(cD;+lGL>uccOYC+DVP~ z9lL*5&)x$p0|M(>H}*m3iu+$0^{y4)hrXC$nc9v*1h|Mn6+{iA>y<1p6@ak;?vrBn z-b|x+g_$=EE1ERJ>M6D_6j0p~PZQ2!p2`DK4WTwjSzAKC)H``5WXKJcW4Q_4g19bX zsx&!C54&3CXdixRhK8fV2eh=|J|yb11JT(6}w zx4=7+hM8oFi-no+?&#Vv)SG!|dujoNH&U|{I{-s6(!i@K;;5ZYXLUYT#t9|yg9E|` zm0XxRVh?UbhSQegMA@ zfJFyW`u!>No!u3CB)@p-IDT4$m*d@g2nq_V8x-Ua@HM{ORb@#4ErV2BKrHWW0 zZ03mFvJQ;P4R`=S$T^s=m3DLq!dAHl%K7WT+=c%>U&W~CLU4OV`!h$l7A+5^Z0N0af&Ut zjNcvGNyI!|C60H^b{}Rtg4nXb*a=`RJ~lI+pxPQ9NOF;3Vi>HvA1RBCz1=Q$} zlTU9EwbUTOq98vw@ec0_DepKt>h?4R_IB?Tto5hRVA0drqt0ljDZA0LRO8m$(s{a{ zi4Q{o)!v36T430sO1gj>Hxf7>Oqt3m!l}*8!BLOyxdB*7<2O+&|8$QUTm z%r0~sA4HGc>}0usZiUno6~a@t>_vN9*3@16w1v4~28s`9Wh91>b{mds(1KuVPHq`? z6^%xz$?jxcaJ7s}xP*FNQB--D^@U!Xm44i4qtFny^G!us#8K!ggSg%NpY-D{8N$DV z{2g&U=`bbIVTgJb1?@hNN$D+WYn9ldqQG4{di(p2jE-;LiQgXW9Zcgl{Nw(Sp`pR? zNJW6Os{8PtJbeK{YU8erS~B95EVZ@VG!8fvlCCHsb%W`v!Y~MAR4M8+kkzl^c+#V) zh+~^RxefQ(NpF}U8};_=_IW}?2!JzAS7A}?hW?Cla$`jo zT{F4i|He9k((dMBdn2{GJy7UGi(xz{oGKm~K}r=*_={Y}@ZNFsQ{@nmBCf=*`F9tK z>h#rP=uw(QNK(`--RFmdlEj7a1dNTcgi>kHoshZ9suagct&&G1ibNZE7w%TvFK&vO zTW&pT*_!4l#qW1Vf%YV?(Ixg?Ttq_6Es1Ll+&1UDmNqG+UOvl+;V(RXnf27t(hR zWAv{dbGn~w0a9@~RxGfMjDK0Al4q%|!|zOa7p4w+UaGS*b%_5kJv|*Mh&)WHjDJgv zN>mNT6Au#^#?;f4`R=8QcUgK@tfxok^fba8pi4q;<0i_($I|I2N>Puy@4`G$yzse^ zzYJQvwCL&Zjg?dyd;#qVh0(&r@m=a2MX}JlzcUDxdOwsA=5vrd{DABfr;K=8TsdqN z6&=iRFQM-fGegu$cJLGKI0&R3bK3jvrO$u!+|Sr95o`mzu~5WOuW+y8rPT0|<7s-- z$+)^GWShw*A#4F$(^;_B$05zBl-yTgnf2{GcWB!LTLtbFrc{c9n1;$7g=K#Ymg|rn z2wELEU04w1`Qh>uIH`DD*fMf=7&9Toqm=cC!aRvmYGwfDR&Y>ng zl|lX#u$~FXHEJ391{)cFz&D$#(NSM`b}&A0ao_oiySR$9sffS=sHGjhS9DJ#7Zav} zllCnx?_Kn+Jpbp0Yx%D5L<|cI*$i_Wc8YsmNJ&7P_&zVcLB$F3Xiosel`Og zaTcRXf&dTjjYE`-xpP~2Mt6u1^&3!Ad;_?Z+1dvDJ&U~j6K z_dzS<4s+HAmjPH>c}Xo`=}&ep()~O`vfrwJYE^&~J1>&ZJ*>j9A%ZS8srUaDl)KO1 zkW##`QudTa>63nk!k6b-u7)Co)2d$sY@djd7@KWVAn(3@`1vUHlY>3|^wPKiM1418 ziby~FkEcHJ;(1Wprq_4*wqf7kpcH&&bC_g_&!bk}Ejm z-{kq*QS}eX6j^^xkFsvDsEHqi&y%hYdT2{rLZ1W1;8Q|anti%&_A&YoXTJHALKXRd zXmjevP0D~B$)zdC8`-a2@z|0pDt~ zxJg2k96cd&?p=^}{@Nc?FvlrKZ)x--3;rBQ*9aVUN*rYP00KHO*oVieIRrya7orWW z`|4ms>G0}VFa6>Rc%$panOa-gDlp^ijSwIh@VTV;4dEXkUo9Attv*=wX?CPi>_%vh zVqGskioaL-8}uMyW}JpwPS0nb;o+sN3nY%5-h1Fcs*4PHAP}i{2jQ%m%154~^?ZDb z=o?8X{ON_iuMt>xEyBo9L{f@!n$Rvx<*8#Qx;<53AdV6%-7ff8Y8P;Ro}U-;nPDt+ zcU`OqWm%%$6#R^cTw|wkl@wV~s6V@p+ zrpX{;TB3Zneeij_#kT`P@{ru){AujC@fwTT;dOJ9Pe1?EY~^PTqvoAu;dmySlJq>^ zfDzN~x-F{rU8F&6n~$5tW>kEM9#jyt+>WUPt1(6FleRBhaMV2V z%EkA~#+$P9u0F6kV5(tHD9$4-TL+fFi$aNBIn~OoPSdrJyHHrDE}#yJf8kdm zPw8QZ#!>0@UX=f5A2jACYU`Jv)k@_USQ86Dzy0{Tl%gWXgwFVsG-zn5BlkiXsiY{@n?k8@ z^Kq1cJU5DR!gfc0bLLq8C|0#dId)O>eD@7aoDLq{gOUN3IrVqk=+wuL!lF=r?j4z- z{HyF{OP{2Wy`b;rcDfc(NA4m$I?kg`i|=6L7+ROS?xVBJo(of28yKMJQ5in|7ey8S z7Ac>BL}Y`{cIY|KBf~VOQ41G&BKLUsCz88%3_lD196w=dCMF*?M#I1wuN!rTyny&+FQFsxdOF3WAvPhH* zyMZ!aL@jZHP`OV1?98{kboOiJn@nFzw^WO$1p(Cwfxy0c7X@{n4hz$7KvLoG#!KO) zCw@mAEk#I0*dEeZE&3s2{*9pBOYFnFZ&%a=b~q<+$cYwh(<9MxwG`LMbR#5jYF}qP zgriX_?6R)#G&t%;(TNa`O6qhJx^5A!;Qc3DBk)bLm*MN)b-G&B4W}a@%{cjWM>ttP znRF#GgLFQvDr4bfZG&Qilh{JQGSypft2 zUml(L*N7%`_qH^;Z;D=wP}u#NSaNR-s9_fR6gkDb&n=gQl- z$fy=9ZyldnfWO6TYQgYJ;Zh5p4tN89i(=jN)n%%U38drbzK3eG!7!WP+x$LvokPMi ztRm_0gtoevaMq6^IEtIk(Hj_VQ7FiKVUa+q12?MOxY5#_+soqe6KGgRvjFZHjy?Jt z-rUoTn5?ZmICAQp4)5K5qg~Y~d;zDafK*<}2omKW5g3MtC?~Nv*JeXp>t8pUCUb#i z1B(OnMkK=tw|10NFq&^lsUTe17IKBVkzWI+i1ItN^ELJYVg^A6nkJ6f_T;~N>I5z- zl_j%`s!m$rL4PJh0FWtwa$hWkn+Rvq7?s_lj2e!O->EQ3)AtB2%#X_S!8eRNh@e4b z6OCt;jV&u&i;v2^K@nM!F%=;^`>i$w7$a3CA&%N7Q7890NcpBEDCAD6q(VzWc_Eab zgic2xnnA-t2xS{JkHbArJy*FYtR_^0Ujr&RhLA*ra`)v#O}{p324@}A#MP;&QZJD) zJg()RZxUJ0S9`qoX+$D#da87ubPK;rWj3G95#%4G>X~SMvFotWmUc` zj9gC`4p6^jMk6PBi}E7j5pC3&&Ptl3D3{}+O)H*rwiz}H(j%_lPM3!X&8R4HF6ZbRrk2@WZd;H1w_ z4RLG~ONey}W&XR~oCfT_<=P2sur6giNFt(u4SeQfw}l{4x}198LimPfb5PBOBHPF+ z$yKSy42%w^UUBTPnI;(tR&q2k-b7er`(o;VN)}6`972Z8!eGXIJuG-T6kbgMle9Mx z%;gYMh;!P%X#~+w)?g?_Q;UwZ1af+*B$6?O1mCd=aN^uG^;|4Xi zK$s>MMbrCu3&DepgRP%1Gfp8$z`2{93ZUX=t%wHlc!R*1iCH0)smPA~*sp-=RC9`V zqhnKonV{!nGj&bWdmH4^6CCV zc81kzN-RdIMXE1J?&0~;9JPaNxjxl_>wngYcFlFEAq zk)B27-D~U?sh#s3K^&yt5l3T}mo@!YpzXNG!EESHzgmodsM%23-c%kq+PP{@k?=$W z9-mrttaA`!W$bP}ZUqNLL$ji~Bxs1jS3;Zj;QXyrZvr0px##~W^FQm)TY6E-@@Vc{ z3ECP9n$XDP^LOB>QM~f`{E{AXQ}5JSO6lz5+ZFCsW}?tQY7#qd^w3?^JI@zZ=(7$k z))sPKX-sXszQU*rv4$aVB{Ua=n@k9-^$-n1AgGw}Pg#%tI2ecmT7TdB_SkdPJM~0v z>a9+pp-2WU8x-zB9eC!;5SR`VjB*BQ5G@jfj_VAKj=%KXM|bJ3cSuUhD<)KTF9uzcNyB-K-_Ac5%VFF>BYp;wNNDJ#;p%`0Ed=+EMPsF`V*bSoA~zV+9!vRMr* z*`J%AL{2uIg|=_6Zn*N8{x*(p=Ph5gq4>aeFiFw+=o7~JTl!(yDCfY8ld4g2NKlE9 zzl)dU7buxk<7$;7v$Iv&7z@@qRW3rrZsphO*TIM^(KVi?{@h|Eg~~=Y+P8t6Ih>IS zg8fT$V)U>C4Reh`#5z5c{|GGc``9_ZhILCnQnrivc^4zM86#f-LB6i>CDlkPKR4h; zH2Vgw?w`-+Y&4@HYu^V$6+;7(JRpTqYqn$T?i&#za#9#_sLqiwbAORk05eiQbibK+ynm@|JC6w}KLMxP z6}<_o`mNM&Kve?xIQ`ECMzXdU;;ErZlVue1s%k3%C}(dS8Y4 z{0H90^!LhgfMT!ofYnFN!v1FYv;i@@NafHUt~yfW zh>#HaB!9Mqy(sHXS0AB*Bo3IB*rfh&)sYHU-4DaWJ5uHi=uaE)X>QTBrZ{-Bf5j*8MuHFMPJtp2n~DX}(Xv_%?C|0ATZe;GF(MNl@3 zlNMsd3mY$Q*0AIF&_@3Rz`hX>%kiW01)G8q4_Fx+-MUzV_rF15__mMweq5Ng310Zz zsgLNdR^HEH>mf3&y!mZ`P-Q0N8;a8Oc?wI7UDe`IO%DgVGJ zj2LXiXpB2`eD06*Oq(UP2XhNHLT~cXAwNG4)xf^sH403=WXIp(1EP7KdG=(}LS3aI_dE}_$zWo-O%pP`-#{FW&KmiM+hS<({!YiY+M%p{8XPS7R zP|nTdiuThYzmDyO`u%zQ_aF7Ro7A|}LkNt(#B2cKr}K0EBfs$hSeSj+kZDaIqLipG zkcJ0Dn&DmiRXC}9$=gidr$(ly3s&jdB8LU5(l+rRRjD{6omz%J2MY(~ ze_l6wP-DnaDqSef*)E0nd;ai*f7QeXi_^BV-2kI~F;>w_T{T#=0-L;V%%?{KK0=g~ zg-w#QFX1Q0L)Z}4lS2#$DJ49>sgwjn-fDb%wqTh_qJ~Qn5zMik?P}k`Zocjn*(MZz zk*|L!e{rHjF^0Zf$n~zVK?^?C*V&+1-#QzOnSCEu*=yi}kAn+-LR_b}?G_C$O%Ary zNO3pV&q9`V1KfA;3<;FF*Fc8yMVq)-#~I2+uDLJ=UZl#de`83$_H+(*vtd!SCWGRw zRteaG2sWgIdR){}uOOMuRZ-O|C38W;{Lc}Y&M~5^m1PWiOS$lfCR3I%=n>@_BU(&Z z#-L%AYm8`|Wf^mid(1r?D{2|D-#uo(Ys>-n7*Tc9g6E)n%t05Px4Xx@-8BYH^jvi7 zb&Wx8j%!SxYfQg;OuuW)fP2hq`zxo8Pr#uw;5LwxE($nkX;Sw z(hTZrSOB-EmHz5?uddMGTWE<9_THrTpCQLTgNKVhrG}wg88x;nI1vD{UOQAkfYIVC71A84S{3sSIk@=p^R-@^aW&6w)$3wqHao_;?0J^-}D7tf)V47@cuUJi*@| zGtCmCGu9c$U;2q*5m`M-V$DLlc=a8lf2MC z6jff!E=gGXeUtd!{zz-c3QzqWJ>T%#kjYc`YzzAM^M5|_9SsyM#$^}!5XcrBa4Ljf1(6LVMn`fq z5Ve3^dDk@qs0w=x0VQpijgb1&2DUsFECAc#Tm2}u>~-%q$l*2p&xY`A&6Fs(J#`$K z5}f6h(T?Wmq4~7=>;UBi70~p&C{z{fP(iS^&HW+<(qi5WiE$O<>X5G;veat{X2|&( zd7c#Us*bTiH%3DiPGC_NJhZBKpdkakqi#qx8eLssa6&vQ%fyGF1sYlx(UkfuHBA-0-HtWL}(_u=$bWfww{2^(r`Z{Ly22lM>nL1Ug#S z{hUy_I5%E@-I(bliY;QX# zCjuqkfD|XsrccFIj6!H+3L~osh_sAuK$QhEvT4=0H5{S^)TT?~Pbk7ePbxW{tIVNG zG{QS9pyQW*G;_E9HZd+LL|MO_?t9VjU5^*6mi9IZ%!%zL{|DHtar&P%?DlbXNaJRl zpWn^i7uz}5?7yPvg7;?CTbiJSWa+IEqI~hfN59+k!fx=sND@y^X7zZfG;fo>t+;4$ zv}<07iE)$}al9(qLH94HT zaJiVq=CvAtpp<3**{X8x@fUhDX&N!8T(Wwh;`u)`yzC9*W!y0~R%!XjHxOPIevdYf zm-7^)>(C|Dpx|q-Ne;3qmFu4S;G_TY(cQ=Y>an{n{{;-s$709vy!WectUWfrgdi{U znah)N*LIK-WBuM7j2V7fLi`wRW(%cO-t}vmMk}q;iD$lAeTV*L^}|4G0~8N5K8`<( z9?ceXt=_lrXnd7T_pcb7n|!zgXH|;28d*lQSSBMZsJ?|1a5*5fdWQKwnz++`0*3>X{YCyrXxulTQj@k#&c zZ8(YBTI36c?xQ$j>jyOURVN*9pjp#>{BE*tSPyP;3?IgJ2fWQ|<>x84*Evbeg1w&v z`v1nM|F4B~aZ6+2L7UjJwG$q(MuD|JBOAwCva)KOyufEvgC<)2HiZCMI2`39{M%Ebfh?gPI?^AelOI3 z5rn@zg#V}5WWgn85N$$r=BN|NS12!H^50zkh`4DZ z*>m@xtVUTX^Uj&%!#5?qnK4Fcw=3C@b0i7T7trY zJ~M*ToT$2&v7<$q;$$XEZMr{SL_qO;XwOtbJmOX-&Q9oSRAz-_&!?vTXyi0vEh5|e z4d+o%2Hp0k1PWKj3by%kA`*QgiAm5C!@}PGi z<6RvGlZ30(H;<2}scsr>P*$egE78S@!fPSw5eJGaK^!4w3J-O{&4A0T$BH83NUaD| z1V@VeBd!AOT@WFe&MCA$Gd=zwGz4l1-dDDp|7#XXwTNE#XTcr{NTeE~Plf(#&WLs$>SBSZYxMa}>hy<(VpEw@Nm=c!HV z6ns`XG20C_6@&^;GX=1|Zh^kR3LV8g3(SIU6eue1rRfq-x-@?*AWz4dP4LGTZ688>`!b=4TFjjBHYFyqT zVb7g))24@jU6{x>km-`B$k9fqZ- zuW3DWBH7_v;NmceN(&Pxcw3J|?N5E{xzC>a01AszdBiW_zc1=}+(M=LL=V1P8F~+; zY1BJU6s`7CWB~j8(LhB>#fu<<2sQ7xxC***4@$~Gh{MoxZlGZ$_JX?y+Vc_;Q!+0h zT4KcWi)YqqdU+@^vqf~A&C}c9zgp_8!**6Yp#nvwOpoY*P zX{6I3;~m_iS~2QPh~}^0*MMhe7SX{diGbIoXk8cu;+t6GYZPus9aZ#Rw9J;4=D6NN ze!h;RZH1+R;v=Z;tC=g;1Sbb+kM&N6Y}^Z3X4>dlRP6zjS*f#I6xj5ij5E1i(KxLquf|s{1G0lkVXSxUkF+-#EI-aH?MP5YzCBA;R429?}Xd zq}#rNX(G*DPqc}KrVu|+hwUjai(^OWajHir=+*~!)H$6L@FND-pl1N}(Z}ci?$>;s zC64E9osCRlL#S@+=e@7_vt5LqmXe9QZc?@TLplE1r1TmE0^O18k-Q;fKVMC}P)7lX z&;8B^-l-?tM1`|hQbfy`4!9>suVS~qqP2#STr4f3wQhX{trZ|BRFBLZ<}SBDXGRHh zST&Zh(*)vADA!R?QO{xxfQUkyM8fFx&_uofUG;B;&Z%KEFIFqFDWS$iLukP{{ymtm zgZgDl8IllpJ!`Dd09G3I=~c)^j{Z9FR5~PelNhs1y+l`s3J^V6;i^#eNxt%uf0`RB z!u}II+lJwdgK#cG|o?;h2PQGX6xVLdNVSwuDo~Qnj_} zG7e6Hha<;c@5*Wjs(RNIjp8g}Jt|HK!qM9=o-^cz^(AVOhM}@qS@>VwUk3r@r(;6_*!^2wyog z-HHl#rOftfmv4xvF`(^4oDms~A*IiemkXV9sa-YlnJCDFALQt712t|Zs`?Rn)CH@| z3p+MjIQGNXl%;q$*w`sukdk;W;8zsY<@z{*@#RGzB?f zkwPSX6a4onSD9BA%Bd=~nq&IS!gN=eh5O5eatCY5pTKD@N{q7$EBkJ-*_2*EAv-S8>0^1f zz;vGKuAz1kmv^K(>M+!xNpxW{g(vwr^oVsaU>CKJr-Jz|Of{QytHMad?Gq+$fD(zlu_3mSc3+Ak0#@lBv`;7d1;w78X&Yko8sPI#OOibHI~@ zjj-oylP!K{mZiQ6rDu)Ju2A7vG*3adb~u)(O%T8E!mJ(HHwzH+RO{L%Rkpw<)*DMn z=A09q;^d!di@I+eL5O>4np=MK_Xg*QB5(2;Xv1?9-nT_atfH1EMY^P*LsH|1boOsl zCjuOYb6~J;(m|tTzi&1&5=3w59AWn5qxD+5;?ZswYOf6O?&;lju5N&~v zG>!G|Rx}VkxEG&B6N0Bv-~PP;M(7;JIT=r9cS}L7Jdf1;Lp1(i@1JdHqsRYoW@l#q zZ3B)5+;GUhtM$@%X;R+x*5!8x5ZTDs}`_b2j+^uKuus{j*7tiBQ*Pi>J_kb+J z=Z9PzqDi4ldSMcdJCuaWp#x|IZ*Z8CMc+fJ!w-`U^f~TQ!V}G3n8cpg8F!Q9wc<=u z=GB=yF_AP>=VxmW-%f~)bHUIJ|3>&gY*0K*aB;+J%^XuWxmWOwrWP1Luk_js7cfrp{e@D*e9I zietPL-XmU7{0w_I3nc_)m%KMQ0XSXx+3_yTUB$C!UVP<+>N6)YTThL8v(-iFxkV)l z9Zvh-;iXi|)aHz8D2rqm6yK~=aT?9Da~>k3oTo}M5S0`8NlJEu#ti{3z7?H1z>V-R zz=)kHiu7X|M!l~HKJh9Lumt3a=AsQ0{LoYv@FEvUgqkZm+o?MPx4oF1ulm}~*n5^o z#ff*#G`(*%orECWeCpPv*@u2{nxP32QBt%wsU?X?Qh9SOlM07W(*UM1?ylm?oFZuw zEY!}5zXuOJIUIZck8yc$S<;X`aX+n4c+?@6LwiPje&nQtQbQkBxZfyuA2OK6woh9E zye+)?WAZ9P?cC5zw$n^3+$aKPOWN>ArRyD6UM+<%{VNFU@h*WV+rm@pB~J>R6e1^8F%+h}5o`Os0t zl{7Jr>WE|wwOAeDzq1V zYM6mpcN2bJSFs=l%7`b%&f!*QtfWXQ$q?9)pnXR3EAIxy5YFRiWgY-pV6|AO7T8R< ztlijzdI02CyY}>7<7DU;Ud>_Mz9LQxmw;j;70-Y}dsYkb&#eYGo>B3A^1nv7@gUvqj9h9r$Xs2gz>=2*DPzbRCtlx zDV%zt@iY$PD|1UCvC1|#dz3@4`l5Xtr{)TanZ}l&v;>uSXd5QN4$K&=)knehPSQ1q z;!zrbu1#eJ{%xG`KQnCI4MVW#il}ef09Wd{^;>sRt?lz9yhYd9UtoBsGI&DDj33*W zR_>obeOQ9L(jxjWAn7N9WfC+vz&0If*mBNFl5w+))WmL<03weDr51tnbk`a^`sQ)i z;7Vl*3K}q5)7Vzt=lv<^)9iGRt%&f1+{R||ZFo4&0RzRWyoqn*-#a5!?;e68OV(L* zGtQv^foS?e$`1OCQV}%ygKb;)Y@_psJ_VFaIt1dXi1htWH;$7Bj=Wm01t&t1UHy%7 z3Om&lNVd}}jXYsgCKvh@XaetF{W**(ECKuv;Sw!gJ%8~hP$#&9g7={Jlve?x{S>t( zDFS6~?6IpGNCm(6@Yn;^4qEq<856Os2wbFsnM4zDh33jLc|0-b{U|yw@B;*`sw-Fp zzMd|lT)J3F1o4)8omlApb2d9^8xzTYS;X3-)JIu_o$3Y{)}A5U@PK-T@H1I=V6lVp z`zPFR-wHcG-810Ip6rhtHYs=O3OmeAd|J@l#JtX-f}8{cEvpxS9c-J(yFi_XvCwnE z=&pt62I6g%fSY(q8E? zp_L*@uF1tLr>L;*vQY%}!SpS>Eb=WEdbi)w&mIVZMvpZdV-@+A7#p9-={{o{=<<>q z5Q3;le_IF^VzUu3L_0w93&PtWXZ3>j9t9P$JJg0PG}nzLd}`K#Tp6CU9Yr@!nOdRNo@Zo6wp^a;cPM=K(`DEYUCGTPA76} zBXp23n;8yA>cYk#9b}FKk@W(m2;i0bhgx64ln?~_AiM?RFrrprMtvCm0rDD<#~=ka z47p=cAVP^e-m&e+pYe)3iF&NLOQ7dut*&CJxNE#z%|BdVk4;avx4o7}gLBeNv$gyJ zevREEo?NIsEi4H1AWdD-ZFmE@v~&fga3sPeFl0Qm%Y^!;7eFAjGC&ERbsfQ^rY_1Qd&BcKj;E- zR$ciSDG#=XXILW~f;5UKAd(!TyxaTBrRpL}kv6^)QYefSt~r8gB2y(D&JY|GkdJQFyis|1aPWlbbIkoqcqOXYeOF(o_>9$9^0?GGzVH>|p9>p$vB^TzVyF zwS`Iv{XF|4WEJNb&BIpKuafA+EO^ z_=bA*k^hiLv&4TxC&uTHO``)xQ=^nF#g9z9Qy^n0l>se(@CsZWp$_t7h&Sp@#>F4E zj}8phOyh<)A@5$*Bbu~5vQApL&qlyyXE*~(nBGl zyN?eCP>>dRBWTt!nk){TT*jqK=Pn1AkR3JGpktuxFQEY@CDYE>a(p(ogz$!OSb^>% zsn9k?KdI24d%17`-%ut<;#0nC?~4gAdek2#x`{7vV+dSN`K?Q8DsG3PE|b4IaVnvJoZ>%EU8+wM%UPl zc-0|4$19%LH}NiLk^bV-2ArE|?Ws;G%}*69b*7sOY8yr1Q~w;E(YOIA-e2wH2yWL< zXBQ&ZfEIWmFCt{=TA(OeQWQl?^@^la*Wkl}JE;eMqB;%VXFHorpW{D&njL&K!JV3s zw#WcuvW&}nst2wR=y7yW;Wt$j!=Qb*9n6C*IbRVL)1HArxP*`dL*_T)q7_f!DMEJ1 zZ*z+K03@-xF?(>EBHkEpq;TY(=%u;h#?~SqHp=X~ zPy9=SR3Ov_-$$-px%KckhUtrc-OIo3Ly*t1DJY@b!z1_euLte=C6VcCFU@rux~#!fVDDv0`*B$F?} z*C%B%r*HCr2aEx$J5_g=z~@w!`~rVG9QasOBoBPtW_}E=Gv2J7G$6%q*5HuXp;(F< zdom8Ql2+rPRHy3k85p9H?9Gh%2FMH~&8r(ouQpESNE4-@ABKF_epM0 zS15|+mZ9$goxBEQLD}Fpfi9(u_m@xxOr*yLKBL@QWYOxW>E1eluliyqVnea?sgGWX z!MIaG1&iyrRYbp5G^FC6KLim+zS); z3XAFqzC~axO>zX=R7xxn5x?vTBX<|6AS3LER zCw`kEF_y8edm`7Ra)Lz3DLDMt;U(C@`nIvyK<1-VFkJ{)^;CoSdF&z{XO&%@op3oJ$Ws@|b_nK%yE zW@I5J!P+ox%Z0H~nG)*H<0JS(2gV12OnL9=N8ht;bjvR^oBMy>*}!B_E+9h|2^~4v z3fQL;DOi$DV;>ZBS~h+5Ar@bp^`DzC9gp3GX!)~a-&<-JzdZam2t74T?AuhDKgS1? z#T$V(T#JWHhLjFaSH8zhUD&RweB>4=%U35j{ZBNd!z2X9e&?72rhKnRB)wwLn| zmzBafWId4#mZ2j4p6?9ZR?EAWdf(#vhsv9N8cr!Al33reElar>sBRSw^bW4QefTNF zDjX-b5bv|eFNn!fI~z3f`fK0l4_8hYDusugH36+N0HMk+S!v1l5}Zkw$X&{R==}+A zMhTab>v(Ujv2dXPX*1PoN3|#=NsR=7)Hu(Ua57Wlqz6%L5jz%3X$`}85Y?nA^{5mj zO^h2=4Fal)P*i4#)8;1e>j=@Fg_$2q+$ko{0)`cLJF^5=bx`_oO5O^J?}Z{tmdazO z(@G{e7$RaRm5V^gSyW(`{AWt+ZCm%yaW;}TMvwKS2m4cgCIBnvNz!_<$n(uDuyVaa zVHV;itgm^+@ii!o7{qmF4KA&yk$AG=5zz}NuVfQ*#yWP@z_trIj`_D@+QG9;dn>YE zJM%Iz-BYubpLr!Dvo%A%dlLU~)*ooRO`o#nom4m>HG@YU#|(w3)J3-zjbLg~#1e^| z-(Wq*FP3TU$8Ej(uAx{O+>orj8;xUQM!i(AA^R7nw zx>w}WJ9l;A>ir-ZpH^dAx(EfL+gQ~o;P*%-nOs7+KJPs4dOobhCF|-sNe~2A#HZJ% z9Azx%CwJ_&Bdjo|m~iy)7P_^Ab{$fVk?@y$?XA!|+jK-d3T&hZj3ptOxz(7*dOem3 zm9giI<0Y(%><(O+#hJTLA4Zt`$twxS2x7XlH-!nx8_Ga(*O3cUep%9wvL~gORhOt0 z+Xiur=x|=T^x_Lpx#__bJf@olQCn&T?+-eZY*{s*Kv7_^SNw{LrPRe@On9Bj!lgHr zCX5x_dNE5MoX~0vU^kh-oWf&E7>;iR<7&3Sb>D8nR2Kj=Bs?UovkYA+0v8>49bIQ0 z?5zsAuT0{`3cW9_cqBELq)O=y&U~YSt;ytQQ2S2^`5zLX9foDogY7gD`GU z(~@^J-)+|UtP{iwDzV0PZ&8qLRH*MqdhGY{U`B{PYZZdu=MWuU5U$`d9T)!Xj%qs9@YmC89&p73$>EX zCY(B{n=-40v)&4-Q7qI%JQ1mmzDhas#b%1~vdLOP0iF;d^jlMVw61PTfOpbYJ79^J zffo2Yzd;8`%QyCK!>FovyeuizW$5M4@LfZ-ljy%|GLbBN&ul+Y9A65r@V*wff`gRZU#EUnb46?&jBm^L&N{& zJ=ck`c-o+?){-a;9!5<5dGXA%ST+`CM7o-byN^?<`~@yn@>K*(`P{UCT=NtP+@j4- zD#r=gfvQDTZ}ep^YskK9hcD76ic(|^r5v|fXekp-n=Z21P3m%SBL nw?e|2QaT{^ienFam|_uyStH0b+e25oI4+!ZAcB^h7wi8AXm-D4 diff --git a/dist/qt-translations/qtbase_ko.qm b/dist/qt-translations/qtbase_ko.qm deleted file mode 100644 index f960d8ac45027fd092610c527a67beefbd7ac30f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 124101 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 diff --git a/dist/qt-translations/qtbase_pl.qm b/dist/qt-translations/qtbase_pl.qm deleted file mode 100644 index 021088e4f88843782b22b4500dcbae86b94913f9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 142385 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 diff --git a/dist/qt-translations/qtbase_ru.qm b/dist/qt-translations/qtbase_ru.qm deleted file mode 100644 index a11b7c75a6ad63cbeabf057ca41b0a5427fddf2e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 157842 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 C-`hX{ diff --git a/dist/qt-translations/qtbase_uk.qm b/dist/qt-translations/qtbase_uk.qm deleted file mode 100644 index 7d588e99f3f91e3172845beb084e4d062a583e45..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 158264 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°-i@+p9F&HCf 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 P00000NkvXXu0mjf4JNuF 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 d66343bacf80f7d298234fd20850e2db3c546902..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 21112 zcmV)BK*PU@P)UfV*|0l*ai?PkrD`4u>fo*mhC`erzMalRYFNk3WSDA zEmcWkBMG6TY1*`*BoX8ViV{Lwzz8|5N(^B92<-Z?Uauc}clW-|Yi2r{I}%4D-5QA3 zSzKoQo&P^`bY`{szW*_EOmKD%;`l1%+xwR9DGT>qIR06Ivqb>Zl0zM$9sksSvrD*z z>r1#sTO3B78!#&B}UkHV^}`x-Qr9g>t)8lpwhsNTx} zsoI>1ZjvIKS?g=?bUI$VXkp*L;NoQ;{LqyPR$hAPlG#1|%Zlx@3Vv4e%(+h~_k~ha z2t}j<6eN^V=4I_T5+oqTXn=rH4MM>fQM4(K7)WBK;y9R^oERM$*?;)p(Cfec)i3^M z*RGdd-@Rw=NDu_IR8S?35K>|=z)a{B$P5u4v!E%`eGAXd#~L{u1CG>^!3kO$o*0dgl7mLej*hjAt8lAl4!^#>CzBSG?d|<5=#fMMpWCKOoeecS+7n^j=cWbOS_-n@%+x`o_luJ3p;;v&=M|FVu&7o8V z34l2Dou?u_lZyCyTOr?d;qsLitX;q1lI53t;F_L!^E>jzQl|ppLP{D&3F<+DFpLo; z0)!B7s^Bq(e5MKC)8JHF3eGgBVb~0*0HH6j&=3+)tPmy=jYt|RBp{VC>-ww-$|yKv z$odSv$H5>16<4d3lP5-Zzw+DPJn{3NJ@@p}Prr2N@W{y&0g-{t3QqHQmJ6VDNAIPO zwZtn8mhrvP#+x>;{_yG>E?c^6`N~{zR*5mc7zv3u)}%LLG-8QFD3h`a9z$D!p}oM7 z_Zf1AYyw7Lo)bc#jj`^qLa^Dw5N?PM6NMlWsD=_#bzy#AETmbFGr*@5oKtunLzWv~ zTT&0ICnrV^4!``%Cx8AQKmN&&pL^-$R}Q9j95JjAEQE9Bpw2b{5KF2X@jMmrSt}4Z zFn|90R(<5!%dcF$cI}c2R}AFZI@_fJuQej*Xh#qWZIxNIkY$)vs zpW3r`-{DlmM;f8ClaLlfL!C_mpcdT1OA*gBWN&Zpye(Tculdlb8&-ApEa+?R>gh@Z z&F~7mk@bj4?`LQjA%q&0dV&)*jY@1vg~zE8g2!OQ;B$^b z&O=5|cnHTw-q`=z6F+_I$?re%$Wwdw?mKEp78-%mEJ}lSsQ}!4GI1I_u930GX-LXg z+b1_~x%!q{Z`m|=@Z3emYox^eJnCVDI2H(FiFzbWWOtQ3^mqE`EO1RcHL3UyHWUyF ziAo@FY%0cBB|#7gBZ7=a;Wf*T5k@xSqrJ#MqT2DHy}SSWyWjctW8eFi@9k(b!fL84 z1R9CcD5~kq2ILGidR&90(tW|+i)9xrU;4!_erfaSkF2_)SC5^q9YrMsGT9u0NTLx7 zC<#OSKv&j8em+An(?*miQxZnY5k@B?=v(AG0^c-?#0b^bwp7fZRA8!69y_>m$FslM zwr%?lckFn6Z)%GeT8LCOQ11o-xa(1i^gcePk=KxnvGzax^k>$7_ER@szhcFT3jna; z(K7z)wNcEP)7K4Yv?Ft zQOct+yyw*yfAFv0e{}nU+n=h{>yrRzsyB$-6GaO(lQRIZ;2Ja)^?6(GqyGK{17E)L z&RaKaT)%owS63$hG{Quae;9|y6Xe@wA&~<8vol!KlQT^oC8yS^nn9g&H552_GQ#0< zXm$>Hk0HaX5E#G+K|b%JyTb#ItA`(d^wFPf-?sgcU9Y@yz%CJMG&CYheli`IfKAgU zTBgBMb-rlt{XhEPl~?`U1AqV7n>KB@wou3y;-tC1o~i|S@ps1%kv!T8KF*(;$GLrZ zwCA~bu3A&wdRDcjio6~15cPJYVfuj1JU3aZ779!?1cb6OwaX)*?ei`#TPHV ze6^=jqBtFOK~>KxTeYt`uvUNRk>zLWBccFte(v5&90@2~Eg_}|b>3BP?Slrf4QjcTVBc6B zMheYCE_&uADIL}w zmzax7jB+P_Pq@k=>02AntwlsAO!=yX3HFbL7&;L^f}r3LlO;IU);5XRjE8w$8K62o z{NVO&|FC`AgO8UdCno@q79xO!`h$KAY?1c!8tCgEIOmhMe15~0Kl#M<3+MOsj!h+? z1mF}<_QWkp1gMH}`FXRN5Gyj}2q0BrsF`V&9zF&j zlOj5H`++kp0Mdf|bh9T0&RMj4>%D*bxlMn({%QtbtQ?#v3<#KBsrzb=P-OB5*q$c}6pUbFR;wJw6sJJolo%xcB}$)^1pHMYSpr z)I)e4v%~{Ll4f+-`X2@XKp8yWhY)WPY&<2QtN>iC11XU}PKy9s*ZsUfYyi4vpM($% zWix?!ZXN}(G_`-p+&q$4VDGUIb;Y2-?BCd2HNz#2kJq78u5|tS4V&Xc$ggbO`i}<> z9Xe`7pezz=<(V!4Gzo6Q#;&`qVq?ch#x3e8d_{zPsHZ)VyvlAVfCj zK(wJ&4CV`CQv~x0s0Im!%duUXTEP=-8Q@8rDAz$qzWA|Cn?5lyK3>23p1c34T%MS; z0jFF{=Ptngoa-m+!spj(fg(a~KHLXoTj=7=?uWo(`%2&m-_X`^8R# z8ZklOq zj{Yn(2&MeWRo7kjmHY0$ZE*4XdXFEkn`Wn4tzqnB6;lyIHH2w=mh=}er|6mOP%N6u zCQ?9&#FA}{jrJ75O10YWyK}$S#>NJyA=(JhQJ7Q;ZrOLYhwd(b5MrOJCOc9Z0Z_tF zQwsCvv|;H~h@Jb!F-f3BkpqlWnpxBQcoGLj>lmEZ-hcbnJ8wBMGIIP!k3If^6@YZh zfU&1p0B-bWZS)5huDtA;JMa7Ymlppockcmg>rvkc{<^<(^11QF9F!wM1R;VXkcAOm zV{A)fFpCZ2W!F3F_1bF>wx?{SJmYbh#ep$9#>0>iK{5tQ7+HV-%S54^ke*)9%kRFM zPCj4i-dq2FclCD<=ia)b5=G6P_qx7t&iz9FbL@)_Y&w3jM`7E3e~9C!m(WQh;77<+ zPSLy|RMg&m-=om2=Xnq#*HT)cKTMD$ znE?#O>jZqk0te8%wa6eegwoJb0m{Qr2wbph3TKxFcU$^wGyoJ$>-t5rYJ|8Je~)AO{#t zX!l|)qfOda6b7WYx{ss&;V?y(;EGzU$SJOd8+EKcZyB5&e?Kl{Y^9()@F<@aK zC7WqkrbtxP*5Mer(yXuo5aTX3s{9Fy48on~9ey{16e`Uy91gK>OASZ1H1Wfui&&02 z@TZ$F#Y;v%Vbk*5(f~VVD_ei*ZEw5voA>?mQ{VmW_nsQz0_p`o09UXv!us{}?B?@t z`Q=}EW4+m|&&_opJfGzG{QNR{v4$*H(2q09joUq2!emvTKNymD(B%HL4j%BnQ})K{ z0q!`30o#)mBeQ8`q9Na0!EmsmRrp_xNu3ZAzXLWxm}VMPAheLx9W;0luR9;;>G z{Oxs|nCoC^sf$u6f^3vY0;U3xLcOnH$)QcPtzg3Po*08S|B_7g1k{L;%` zb^T5M>egGn_n{Ae1HhLB;QOU=rToAA z#=GCPYwzCe^NU@w<%e00e!q`670_NtL63fafay|#t&I|CyIHD{YX!}K-zW#5@5d1Q z`Y51()I1Z&>6n!-E)6rWTqw=?32BzoBtwg}E=yb@%kwco<9xiAP>8iTfE5W!(7rIE zpJv!RS;OXrhjWWdSXv4ZMj-;P!q1)qoRQ6vL_9tNl59D)}N*shH*;YXIjC_^L01? zyQy>1$`!Cq;Hc;ZhHwJH0vR@A2!hzTViS~O262jNIl`_j6L|LcJeC*cP$`G34|qPL z*6>Lb@Mw1isLoWUUjN27-Td*7fBe2@4jy_AfU^o#*-IPe0CFVYgRoTD^)tWtORt@n z-aNCs+(nXeJzbI{gb11NkY*WLOXpCL1MJwmg(f;4#00{eO+SkOytVsq7J!@V@qT|X z9uM5NmbJnLpV;K`g8+G!lO3O?8Od^ocpwp_1S9E~59=>vwUJ#u%4M8oFbe!t?%{$W zsF@pRNn1t$5|08wl4IL+1DmF5c>3sBET5Z0sZ>H3Ov3jC&AaDm__-!CvDHnn>%fJV zyz77c_1FFG@BGe3ayAR&0vz)VasZyUF?PRt{m;GS6_;J{qKnfsqby#^>q|4@0GSrZ zlt#C`gkEP6+qX}UOLI6(p_F0&xikMLog*h87v;U9eBQHj=-k9&Jp_Pb`9ctj6uyrz zQ{JC5j274gs_?1NGPdQGo+!a}3G*Lb4{|Neq${ z@<(r+12_cm{2-{WBz69LqdqmW-0mS)K$ZbXk`n985MtQxpuI4MK;+mq(?B^4 zFo;u{Fr~B+0c7?$4loLM=LswV)sdIlKoO#)FbHCsl}d$d?0z~xrkofWRT`91B$n2* zCfN$mkV zNImm_%pgOY=GeODzy-Jb;w`WG_ka8!KCQJ5oI=P`^L#nL;O3wIpWl4ZrI+r`az#0O zDJerMBTJDh4@nZE-(EzoH^B5n1rv=jO?H|w@Rb3&Qpy6Hk-!1mDSTrxe>V1UtUvI5 zR4P>r;{>f%ho6C*FKe-QX6?SWHV0ra!S8LUc>OWz4J>j3rw@pN2#^wVEQLTnPSL2A z(5yu`v+N;FQX;Tgqls{;N%Ko12bIEi`zflE^~oDw|Ay;7_`$#Z%IULb=Li9uD9{__ z0L8W}(hp0G8*X~ztDB9f>FyvQnUm&*`g4s`X$*TU4EjBykm*Jl6Sauy`dIlhfX@vg zXuZ}Llk(*tE61h$Yo`@hb}Bsq1&v;>PwYNd2Kk)zF(w^?+`NR$Y8`~jHAsgLV!YIM z9_$f~g#c`UD}f>cC}#nXqt9amK$4*p`PejF#i3J6NOFN;zlYZ19BPdky=RsKsR#IE z9_HvJ+S|Hk-=#O*bmJ8t{rD%pS}4ZNd92R?#0c<10Ldj+Tz&cFE9F}nki%h2K&KlU zP7n|JNCrK!3ZQ{{C4%pH`M z;w0yJ(TuRtlaSJxfl6o&1WO5IpqNCxT0#(bq<4kBK(DogUZ;g{avE8ltqg%o>Xo5r zj;3qV(?5Ol&%SB}0ls0IWsO7&^?C>}TGQv<@Y6qcb+b9$7z|USxnS0wvpt-~F@}R4 zaf3L`5k)?x8fCJxdr1bxY@deH0~EpN5`~mUuYe?FL|$xlF}Kh~ZxBO}V@L9{3qWcX1-aA+@*I=(GMd#0?QViR z3NakU=qxXxT5mx5k_pn&$hF}930Y9SGLn@R@C@`^5hZ(4Vs@&D zsi_H6DrMG~m0mwdO?sGU2GC7lc6J8cUJnb4%a~tS#^%j4n3UGm8N99U(xYUS653S=4G(GJA5h@hYd{&l-(7U1N4;5`iB8g59*%=2lFx zOdU4YT(Tm@`I$UfRztUyNIGBtSx5;^GOB3WwQU*)c5XtgT4F`+zb^rW#Khhm)0mm8 z;;BQYF}K`JT+@fA97W$NAXgc^TP_Ld$wAkcXl!}$i>};n5TMvrSB+HyM>s&TcmMg9 z@7}v>pVmsGS%%z{a;@yIj073WO``miV&sz875fJi5~F-=o}D1z3+d5s#}F9%<|XSE zL-N+CRTCe0J_Co9J*I@UG)925X{CY8YVDNi$!t|ipxYfFPEvXot03fzWOR=)A2P}I z?U=P4$M6DwC>8CZeVfr6CRl0@P(nbaUXm#IQjq?TWo(7{o5?rN!CPH7Siu$4d-$H=k_N?Z3S z1H4@F>A~0m#IkZ~qK3_zW&q*QZ$>}9?-6x&+C7|GSVFtqMVhksu)ZNF1oz?#Jk+XX zH0w1?G#dybAIc~_qctH)fuDn;eB?jRQ;nJFI)cDQtJNhcQRY5Um%s@Ws<1 zCv_^8i&pdWML_m{mT9VVjY{DP@TU=$BBI#Q5UM97X|hL;oyO_81;jA{#HLVNp6QQ9TD!h)nNqW~X^s#Nz1g^MXJK6SYA=&P&GdMHf!*ger2=KnlIhf@O zC>yU(0!je!V1Q&8Ls!ZK8y=84r9h69-e8Eu9TEL|j9YC{LvpRu`+$lgCFJLY-q~{S54~HpH6`Q9< z5tU>K(0Lc{Uw=Gzasf{rIfHYHT|y`u#~8&QkZ&QUu4hZF9_AL>c-4!~!|YUT4O3BK z`=$oYEVfD6vs}`Xk`+CI2aAO)&Bz1WXf}xZvLD011{#&-#N?}A^O}7t2yn>2)+^|H zIRSeN65vHIzi#{V^i)09T4dIZs=;g~%aAKRcIN?UYv0n8Y~87;I)ys(EOU1;RNU?K z@c2`Qae8ivUW^n!qWTS+grrO^=Y2{&Yl!NqAd-fHf(C?tiR<9D(C!M~fU`9v? zb4?d3SZge``*`rl<2ZI|p1gDHQ*fL^YmDz8VJP&(*%rQW|1)^)%P+uGvx;$_tuswb z)E9B=%rbE!bIhLdMo7$zAi zrI19RGVW-_^F_cW3ytPkvL3_l#gSLx2a}T%I{@gB#WVT;2?AteS{hW>&5bSs%swBYI8#Qu{sMN_qI@X$4{*mKnnN8Egjs&UJEcq_B_%;Qn zx#uE^W;hd(#ZseQB{|$~_eeKU#ND6S#gy#sMjkaw*q|`q1+_@FtwNNVg zkhZ2lxa9!We}3n75<=pMLuavn*Cy=P+{BmCYa`x`gv4AR2U~WvV zdbL6>-Yj38%H;`(!7yHtopb2+hm@$1Q?O`Uq*4^liIE9Zw58_};4tsV73kSW4JYcS z*a4-j<%QftXv=ZP?W$9aPG^Y0Z~%!4dYML*SUXeN&~QA-?3ngl09%fser3+=5cL=p0e0x=%{wNy@7UQC8j^r$WxWs6sFPG-Y{Osa4>4K24CD z585RvoSR!lt_Ga^KR%U>Uf2x4rF5xL4q*2gFoQut2p1>J`d!wKyS|j9*m43( znzJ|vR@?h&PKp@6H{HKj$*gR8*vK=hRj?NhDd>JjPc7oo16vU_e-r_#<#1(0gv>E1 zr?z*1gtDo1@S!wSGqDIjMg&C!pqN92rD|oV)Uj34bE3I5)5E>0Ou?xjQh&j)GkLe>C0N0i1jS5~R!l8kI_k zY-5{#rABl}B?M{b%gbFdi_+ZqGn`rBatRcWW{MmrRy6q10bdGG?S53LqE;(o(2tEM zF&xkV-D)sns2`*4q^JQzt2@M0vog*aAQ!L(s0VREa$Y-F*rBw^d&uE?a0F{$=Z9gX zR;|_@OLD|ME*hvS)mkkomn*JL&rldF%O9aQrY3f|dLG5Wl^SiK#(8TCOKo!W$S@>U zJX+{6lB?lZG`on6yjG~z%H$n%(Y(U2$4XN^eVk_G@l$+m&8CxCt|-Q!pvF2FeW9t0 zy<9F65-zuUM%1WL&3{aPM={Qjq2i8KXGlOC*Z8^=QceMjuS^jPv?vtPLeR+41X(;p zRE-#3kd{Lu3S<;TrMiRjhzJ<@LPb%z76d_=E?_Xc$N}s*Xi)?*N2-E=T$-uMT?Ze* zh|}#4$qu$*OYIw zH5`GYd3U>gEG~CYp?E*bU(RcB;?4nEt*;OQl=ijQ?i1og(jSKallp5Oq9-E&#`&eUkA#amy%zkUaz8BEx{9lI7z3+$rM&LS|l|DLg#w@82v#) zaSCQ1>xFvPPY6)}xo2CQ0XKYZ)<~q~$`OjuWj5A@PzdrIcKR{hI|?xRq5A}$B!9y& zRnVMSI)ca2hTT`ukR=LFLU^7>ncbtSs`}%e*7N+bl#pYJY{xF7Ysy@ZCW=<`P-B>^ zrZ6SRSdJ$c!D*LpaUL|uELgD%l>wuP5*iIQ=gyp6B*iYtI0C8Ec&2WfQDvrC$CXYvdtFZZ%54Pf{mJ91LVZ1RCpT z^iEO;>B(>$to?C_E-cC|>Adkv+RwJ- z=}F;`SW3WoOxG1PLK-2Z*u3lwT=a8v_&!xJ(Y(b;>bTpgT1P&sSBX+*N;3{gf5VkQ zLQ3*-tk+4)Ndl*VhrUlrms0G9S5Bd0R!y3?v1jQ!rluee#7;})5a;HX36YQ~a%X}& zc98yXZn48avgunHVLV$YYPA)h6pxG}m4xbI91Cz0W)fQni0kAHf--Ivm%0?`+`Vfv z&YWFBtJAm2vPGgbxxY|O1mudWr#0_sTkLiE32{&9vonvyvn-0>4J9IN1Oc=V!rLG# z8?_>7g7Q&QSQv^l*+jW2e$ABJ9SjkcLJWr)hUox#1}L3VEWAI6DZ-d=sMdyxnQElx zkX`+#j8e*&sm4sV?PfUGSZwFU;v!e;x0%lsi?M~}9wGCN?K7C2okU2^rWA`yJ$A%6 z-PR(yyO*|U;sqsp?P^4-tnLm{n%iik`gB8GVmU^Vk3#}~t-Fe~P{vJ~t-YfmgftVx zWAu@n6=9S%2&c)WIp*d&==M?q@Q}jK{GHWkZKo}zS%&}=O^8(50C`j|;r*QT4HxEh zTHozhILn@E~wid?}x z5}hn+EKB7*xlXHUz8`1i>1?A2Ae2%WA;G9AMmyY03DO8ZV~2X4BpKE2#k_)+U^5Ih zS6)g=#1N1~@g|Hz&YGMmZY9!efJ!Aos(?ImUdB~D0Y!1a1yF$`Q=EqT=St1l;^1>a z=(RO+%cWSJt`mU-z27j&;Zrz#h;A>z6t||XH99c5VTf#9*;$UaVM3^6Q$^HM-?abgS%)VBZOcC=%hK? zeNGWCrqwZ56{H_X-$RS8W**TC)Ad-@=FBvHm%lp;3gd^WVlFE48SK9tY^W+Ie z4|^5ouj5P~8y1!V>o$l;GtM%~m4pa6ysaVO2OiSYq|Gb1n8iqDi!=^3DPSBm0le`y zCG&5-H9(vw${Pfvt1*;#$WZwBIXJNJuK!Tx@l?0XAhwuhFxSxSojx7|W?% zjY!)c_gU)1m|GkW5_{5f;zAYzxHQ*_VF7KS2K%!#)2Uf~M2@&8wLiwRmwA@B+d5b2_-dPeSv(ZH$@&jV; znt?pZLPrt6v3*?_3~h@rw6^iM&)LN;&b5Zn;A~|fB@Yn65yzAU(1M1b;c!GC ziL-t@7<3DXAbOl1K=YskgKnB+Ls2moGa9S4^`+-SXc($jkXANHN#WFXZ-^+Y!c*F@ zV`$W?C6bldksP`5EjB|N5fKCdfn{;IN3xr94%co5!+@~CDvaj>MzPC;9ua4nJ9B7I zG0W_9gV^!HVh71^0AOOgSaG7qAZU&x$tdWwWz!^%pI$(kX{182j#CU7+Yccl>k>27 zGNzhkn!_=kNm@pyGe{A5o>REp*0r{ks{zljX9DgI27^ww+bY6&R0q(7_w$GSUS~KQ z4kVgPolGP)AY+h#^*|vQ@OHb@?W5BhQodV8d25m{oNEH`WU~fO`bbhGSW~OR*_V8KcB)cWD#5hN+DdhqO zd~8fIK^04m1!x-JE!gj1&CUXm5%9G&UnypgpgV}EvME>VuN!O!pdI4%fuqOIVb}H< z3R9b~Gn=5Ro}D+=a=GllCN$Q_5I%T(35QO#2-u$Q8?E0}6MMpAs;3aSsWdjn0-Vhx zg;r-y9cvvq^4xMU9o*>vV-{MQJ9TXF#K{v27oN92mr{B}r9?sI!eJSb$VWNgd!*&l zM9wXAuxD3}KuYAwv0kM#aezHLW^n3UhvmCxykV(}US*k$Kr+U;_$MC=Z8LZ&W0oew zy_FrB?Qt+CfvL@hr4UUnR;o&#p00CyxYI4f@%pY{xQrZ^q>}T@M!ux*?y*x#Y~B)b z0>uhMTj$Un06>kqcGlw$^eM$!tg45_dAsNtYj`QH=jV4cmuWtu* zo-Um`a|A#(uARIb7r^d!+uf7T9X_g*$~a?}l_(pJ_kHeGQ@fCexarj%RHSwsXrmvO9|H_xzi5+8A#k^Ow}d0R0v zS>x}DISTZ9%~`Zcx*i2ac@w7CWb390D)nl2hiLbRbFJHP)P}(|)$Q5dfLyT@1R(*t zKg{SEGh;0%8l0-FwV;Ti%7Hh$Vn4Rc)G_8mvj6^P&eG~4rH~Q8Qoe*i0?!}?7myM$ zfXz#07L+!g4j0ay`5^!~u2+x~0joPp%5H1;^>UUK;!eC^v$6H){vk5ivlwsD*zp-!R&O5`ma zb8`ksI>yzP@5W26*hiv-x_pk&a&%#3xlwbuQ7w~A|Iic1DJdh)6cV*wD_W2{I?ef= z1L?sJ_`SExG^riUbElR_JlLKDE?(wD;V{YYx|i(1^;hpk6nbNQ4c~b11P&f=6ZJEo znbUcm(F16$LEq>AnmVBQe!#Auf^R17^|MDFe&o1g{WS7%B0v>>Bu}3>dbBr)~z(acQqY`Al1CN|OjDaFm#8Q_!Lp=N3Ja%rIA^SGXHJgN>kT97%S6#M;x{E&g z)G2sI%dFSS=yYSWhcN?=dkYzsujxLuY6%zZ-;9@Exewd6PIK{RnvX^$cp?BsR_C!a zzhmxDt8-;>s}m#FpuD>@U0Vc52`bPOQkd%E2oQoqQD=}~ak)#^$Q9T;b%;y*%ETG2 zy>bWM`KHS;Ss(9jIC8p;dmlJ~Za>3xvjj;dpk#fF>Mtb`l`mN|OD?e^N0fwXCA%{8 za%-{s^?Sd5vbfCLxZ+S%U=bMr|Kacd^PzJK3rmyr>NMY+8$WwS;RvEKv22m$@Puy~ zFXjkBA9|4D@bLv)xNix2cWy$GCWOU83mg1FsT|?@Yc9sN*$JwK^?VPf&McEFS(#pZ zN()m*&o=u0-P5?@qMf8eNKcaJC|2TF51HgRIw6ctDQY~JgJ@V?d9gLH$(~43MZnJp zSmWGk-1_E?uiQ@x+2K>m#OnJ)E;BoIwqr#kKf8^B(e-$Cr3 z2}bJzECS&8vrnEqd+Oxj^Y-lA<9X62StE192{f@iKP*8eJyJ}3Pcxeml)OO>jK>b1 z!j?@<`fZje%LM>qKSz;=t5(=}yVJ)rN9NG)r`We!B6n@lh~l?wYGD7)SxipWnBtNQ zd6HW3!@(k8Rf9-n{=QNQP^*-%Wpk5Q^XaoK%Kg`1v88fN3TUc8!>nJiX35rzF4#=t z;E5$X_`^9oab$t&_*&$zr)C+9>|iRaL;5~O?wQONgXF3riZc`|(9{`;RYg`p_0e~c!DDtn?Z zhR2URcPM%3OJC^|0>E+rNN7?7gRl(W>mj283<=NZ0wMJW%<$yFIc%A2;_A!xFy$%D zW{TAZvYbY>QpVL+?8TLrDD(yivrJGqGyza??;EE00=8QBv`wfK8hp&&HWm*`QEXxu zXJqS#0V%5VjJ!12 z83~vxGce8!RF+kI=Nn&s@TXq?({G-coT&IRC5-l^!A8nAkKpwJ76X#ml}92$P(J%Y zYk+_L{$VPKK7a2Psu7gZx^0Df8frI_(J_ea89i;d`8j8%7b>T-Su;QV4zK_^HFk z4j+8XwE6ElMc;koI8Udo8$0yFM-R;}ES{ko284AqEGGz}5}7`1834Y0Kwmyhp=B4 z+{3n#IZ4=Tl!3JNJ9Y8`c-4(KwZ8}Z44kq!ZqPN-7i{r%cK1GWY#D!c+e7%y<7Y{m zj{?^28Q`87l7>$fm@uM%v#G);B%)z1&E_psnm+J@`=2{>S z*vZEpfApy&&EhEV>T};BiN+L&q2K*)Kngrw*NAccv#z z$kYXEjCsB8$1_UL+ne_r7oU z`h$+|`v?iZ!aNkO{U1hU1YrapiV?u~=)7k%*MQo!g*bMmgHNqc>sP<^Lv%VZCx>WZ z3McwpkeP_4^sPsqK26*phs1I_ zCaqf7Fq$OF=gH66D=cir_5 zPuR|28|f6PN5nt^AbRrQ?>=_?99(dw3u6@x?T(W;NYV{JyEMemHj`}#Qs@sjR*y`cYgJaR)4XP`cU+NN~cuGT;1O`ct zZ#;Yki+x~zu}jLQOYD!ZNW<~-h$mL`_;%Npo}SKCOxA& zO!4Tmi@5ip6ZqbfbJXIU+uHJrOQv*V?g;~AkFMzllDVqy(>WS}hcF6g>uJE3n&K@g zjXMwDf8X6pORZ%C&(w*4^*e>?5k)XM`1lWwKKb~=_n&{>fdgUam4hsYp9us~Ao17- z9hR#I23@2oGptI&r>#cjYj_HT5IPJ9(9fN1*RbFhfj7e z-;PN?35?@r$lX+#r91J-`#$aSkVNs!b$yQj9R-vzP1iEwnck;0f2{q5JMQ=afB^te zwEZ3M*GGV?C^zo=%9rkY)vIr~ar@@koq?B;J)e4-mVeDWMg4l>N)>6=g39^jxNVHb zHoecvlczK}ia3-(?d*3K-qOFDxSAf<63ae13E&n-i!t1gCqG zt`Y}tiQRiasxTGnqVpZ`7#Lvs9tzUH39 ziH9F~?6F54eB3nq>=ik{M!SUwfr2>je%8Gx@8dU#oJOaEyih& zE^0`n)O2m4W?`EvP=5c=*xA&0iemGCpvAAAJ+@%HglwJYLfM*t8p%&!XH6(YL9;3* zWoVA!^G}W2nF3Qzu1ltJzaa1Zz;nj|bAT`k3D9Kzg)9O*0V2jq$w#j}zxb6e-+5oJ zKUie=I^b`(E`WaQWJlOuIyZmcSHFDkl`9R1C+gMdL6X7GB?96CpsL`YR6?a%Lz*rl z&pFdIRSLe62y#H>9&!(i@mfH;v~BXl1wK)Yi{)!sSWF7EZ(*QKSUV>UV9d5r4xj)9 zXAuY`p!v^?Immqt=UYQ8cVl?w-np_dd|}GT4fU_eB9~wu;FbV$_`&yQvrLFiLTolhK5qf`nI`qCUr`kO}{fBfj@KK1c0oAn*Lg=OW{ zhAV?cxq#L>y6^74|CiUk;Z6V3H7~vT+LABHZ=SMMKu8cOfvj9ZIZ2Rrht#n$^nB!= zM(*b}ENZxbfNS2)_IjMzm9Rwd`$CI%!ACANoY_D0n1B2m>uV_H3);fUBnLb$GO->v zzP=Shxn}w2@(?UC+Wlgsi9-Nw3wIdEE=Px-H_Q149=mu6=+=J{5a2Dq>6qm`i46ii z$$Sqf$^TM0v;iUV9Cljs=kB`W(|;GIX~*!PWDM)yFb5C?F%X?Oe(=P1@B7AAF1h5A zi|bJ|8KpyHxg-E*z9d#21|iDjDzY?19_PpdAAypEc(`^e7if|VjiW?!z15* z=>|2q^-QBk~3HWDb2v1vvFu2}|>5&wc*0x82+8b&mrGM}V*Xd)Eyt zF42^li}`aWj~>7G?k{}lyz|e$Xr@t_8m2vjN^mL0Bo350&E2^1u`dDJs3KMojF}$b?8g{=t7gKfG1Ym z2^IfHMNgCYkl&PPUI~oLFGYAPn@}HDYsTkmU0!U-{ zk)%Xc&jX2sQYi492OfC(i=Y48U8XH;-@q&#rT&d`0GA~sED~s~!>|1PC%^KF*WC2# z>#lp%P36!RS)L)x1&INQ<9mu*!{!y_x6+O{S4wXY#bZ;D zgE*u!8O4nOZ+!y1ACM(LmeC5}iPeX6>;w4#o*tlHnc`!WVQQj;<3|pk_`sk4=_dw* ze#f!@@!r3UBfxmSKy>c(u`{2)?Z4i>ci(}F_U_!WJIgv;fJy#zVXA{YSf9Y!v-2a{X0Ql?K{m+L3uouY%6k@G)^e_MP`ER}KHLt&C z+pTYTTe%dK(tL>ADtmTOC>=lnJQBn0sWMbu_C}xqTotb?dr3wF5rrUi{;jgjKyi-pW7c6^aZIUpSLT3YOqxSmoV!h zsO0RSE$0#%#|{k-p+}TX8hx!AAqq)1AcV+=9h3rKW@eH-g#wtU2l$tJzxLo?z4t$U zD$6np@OTXM>*vn_91>*a;$A%Hb#MP~fAQG^=Us5=D_;8IYsy(lEo7C?3YS&}Xkp1T zUFt!|9H>Q5QUL=4fRrVS)I=*(O#@SICCCg@uJVO!d2QZEvl8hk2n+l%egJ2o6?4WM z#N9VyOufC6=MDkf^@NtZ_1v0(q~Hm-f(-$O03`d3d1sWqzyLquE!p+88p(VX3m#C8 ze26@OR0GV+Oi-VsI8L#7YaN~TQtLCH_{g2-=FUC~ASlTG%mV-UbAa*sKx&Yn^6V22 z9{kcBpZxUx^Df-8WvaF{%UZ@QE6wsH9Cg#W1g$a*hC^a+4O-(y0?Y~Q44ZfAWF&(w zrfU&qrza`ZZDOK=UaK|yFYo)a+wb|uFaD#^`uj!d-)P2y2jF?M79j}A6GxsoQEAT9 z&%5M`%T|C8s5~>;cCjOy1f<7){w$_MQa>tLub5S@jp<*kMI0G`tA#V}TMb^_W8bzW zf>%N^VM3ceOMtpu}lDP5kv zPgGCrorm<`Tic#|`I17oky&3bDn~R*q|r;1f|X&SfGX)@qAaj;`z*pJqWPPi@bT3< zzj)7k|Kof9qT6Y=nc^J+jF2cz5rQRr7AN733M#HgHyLp;l^gh5z3bfs9dwIy3N zZ^9;Z_`=xwcG!GJA3-Ukl~!jOA>BL6VH-Q4>gQ|+Wd-j8W z{g}DK5_WD&wl8yKC*N7{%x0DuOS3H@y$NdE4%E+W-bJAD`%F}eb*p4YTzmo20?1TRsr5{O71$^FCY5B_rGUs z{;q*VHk$MILL)$t6QpL&VgRN4@B63wKl0cA=|lhK-T&eD_HLivj#kIED|Kz#Aq}$D zAkZTu5S}K5hcaHm82y2_GEyoz7n<2Bw>(!ICosxoE(rk`8Eg)`3JkZ=t|G@elw4)c zNShhggt$;w!24?=0BruhE7cm2`M&k^(eRi9P$`QDn<5^ zl#$zY0~fTPW*U>z5e_|l@Z_KT!Mi{3wST(nE(3$q+Wh04J}*26fWt5+3ese#zw(7o z-cznMCw~36|KK;b&(vn}rH*mmN;7%NnB0+3uDXcR0RUe5RmzfagQnCKY#8Sx0xTQN zq=IJ}K1r$Vl5lQe1a8v@Dn^#ti2?(8Xa1Y5vYMSX`?i0dDn?hHLxDd5c;`NU5EJ4lBa9~>t3~i7@;h$3?aq6?{110J zHqUbZc~ZYq0$+gPXK9ihdHV4~L8XZcu6W6%jcQavnnI%}PqoYQlRo?OvxICmNr4Z~ z#=wcHE#2-bNf=*eb(A7Rogs4&uR3kYL2#7916m zK1T=g7y^orLQ0-Yc9PH_AX&{_3g=v5pcCLn5W!T>+Cml^cenm{-vSg2RNo*9)e*u1 znZL7a+~nfhW51ZS6L@Uek#|ob3b>%9T8+q|Q>})i?FXJ@&z>hR=q}?$2WGKnYm>uU z+V%B;>9bU=g{V~|K6~5W-}k5QdG}wPICkXV7~tpQfdAtY0X)Qro7j?hdH(Flvmbl^ zAAi*IJo)BZ-ul*Bqt-yX%aJe?DO$r50i>)EfRf<=sTx4a2-5crz&u2uLYf5_Mj0h& z#&OCue7Qz0t-LfrBqgDX(Lv3n;XpB(SPU}3?K{VhYla2zkixQjrWzq^4PH^}XK!BQ z6P1@roU0dDWl+)}1ORf>OA@oqGMRjCqMibfArxjOY>j&S8spYV6%?cI+wVIp~sQFf>`lASPnt*emIOV(}*xxiwLn47?G6X z9!!%}i4@Qu`^4?{{K+5w{@)xsdgw6&{NYHXZ=^-?kDmjqA2oExr8CD5pZ>^SzURZ8 z<)y)`Z-3|8w#_!T$fXV`gIw#T5laP;00JI7Q6_638TOE5Ln!S-`XQ8-MC~GnDTMH# zBA@F0vXuJu@mhbWSrH`Tynp;1G|4cLCRpie_2j(Weid_}Is8`-j^;{@*@-=H&5X z2Kaqz?~n8L{Ui~fhy=x1Ew5A-o%!hd|NTc67v@^;_&2}xulH=o-}#}yv^2eg&EctAQpr76`+Y;pN!Wtf3tG*8PoIiS>_1 z9)If8@BQBIf8fh^ec?_3G5FJ8BgT)PGy>=`=3xr=DG$2s)*T=Ii_Z>vou#+``ftDU zk_+}-<%KDF-M)3FLV6lrrXk7R4~>!)B8>;g@))_!;mH8X^N{7H;WX(09Q5%$m-VA; zAc|KpGb@UWtaPFj^ti@dvKY*ftUwa7+4Cs$<#YOhM`8h{X@k=VC|gR}edZEEIxE|ALrBuC*fgQuxQh?Aw`iq#{C{-*2N7k-h)ZA zko3Y*YxvPmeDWVZ_OXwD>9GgDf4`CSIe^}X!k1%YMdhD70*t?=FbH7Xe`OP{#LoQ} z@BX>B{qMi@3vYSr&(2OZccjCZl%he(9S9r5u?| zuCXLEo!6?^J(TxhkJo!}F%knh6Kj;4Ssieykepn7*ls?}#=U9oQjR2>>{J?BtpEzyAYw{?+^b^lt%u&dk-I;N(f1wZ*`Hp@H?|x}G${Ge{7btqP+` z^Jm`jt{ZRugHpStbu@BF*l?lF|EMwPua5WBvKiwm!K=>>28mH*?GYhV4^ z8~5zox*K^WhJ*+jiJ|^XDWl|ZU4EA5#1Yaofl@gYhiFPUlbrksyMVGwE_D?|1}WBm zV4&dsl};R(K>(($bgbVNbJBOAVf{`KG^>A!3|pqEm_L2^xliBz#e4qqpa0qCdhNv{ zW_~ha`Ht%I(Spt&7m$9O*VQ8nQwQc{OJ-jOVX5|-n{U1LO>ceY&tHDo6<5zpG&W^P zf+S6-U^B}!(u}H)xa+3^Yxp!0S}`-rQX}Ujl#q-N0HB1+K~y&HaD5CI?X=BE0O$0v z@?SXMJD0MJ0T>04DBnk|Tq4wLFP@%%{LzOV|G@j-_vuHz|E>F+qG#B>^XsQ0?cBuw zSO_rwKGF=|jG&+(>aDx?Z@KQLZ+YEoZ~nQPFS_WWiyPI_l+ZvtjLFVV$ixF9L0;(U zp*8X>CnU)7l#s)%rp4Sr(d}JD(zw;ooa{Gj-*riM769!#rH^$08wet{Pg_pq3Q;a` z>h|)&;@L+Z`oRzH`r>E4de`lrybD05P`5WIBywcy#q|G2M*uyd7x*-+ZonV8b=Ur# zH{bfNZ+zJ+Z+Pv67hZ5dvr(V&wDRI4L7FJm1u|y}W?I`4acWkjvYhf0c~NS`?BCwj zv~n*BdI$E^^#Cr`@3?`{0~p9c(!MWY%|H$SMLtD00hP5{i_1?u_VAH^xZ^XQ`}*Bq z{9doKe4LS<^C=v=XTXohd-4A#1Q@-aER4X6khje8b{@ER*UN9X`Bm55_%qk--@pH| znW^c?k}oS7K$2xhQ+D{I1_=}`=O(NYh}^Dpp69$(%9WQF(!U_=<2aV@23(F`ffIOu z>DURIv(F8(q(qtwJFVrV_CpUo@ZdMTa@Tk7y!{h*L+73Uuf1!3Z6XN5-eYfL9-11f zH0Du5Dj1s-A^}xue-Z@$R{;b83}69T3My@Vi`IJS3r$E&nxwhQ<=kx7o3IlKK@e$g zVOZD;5b}L9x0{*SZ^RLfgxO%|0!IM;^bi2=w@^d?B6uQ)L+SHEX=!2c;p4>{xqK;= zOvag_NSG2mz)=hqeLnmlm?qVt?_UOvDT=YJ^iQaRwF z*h5tL5JTq$r)%#RPhNi5Tz}`--J0mq?Q>5DkGCa{M-{xM zo&YE<4MZSfHl&Lz$=rM~b*p&4Fn{~roqWEKi^XE`3z2Y$8X8qxRTpw?;&O^(kRARS zP(TgLmBgw&MuMh*>Lq=cd3W_e#Sg>Ga-9BA>#)@|x6Q9_*4IpSBUgE){Pb*L{LW}f)2(lbxHHMDm*mkee?bx+y_0X)C8}Bz>eSE$8 z;`_I)FPpUk^T7MwkRk_92OA)dN1&fI0ssl{iD5h$h@^ZG7+NZun_ehA$j&6v>2Nff zh^I2w6Y<2<#S7tJfYKl#B%o>vb7C%wDT=|M$;WkEm-nzZgT8H99VVF4ZPaV+or>Am z+uz%+ReyZm`m|YDUtQj9vvTN>sjZM)&FhUF()(HuznogOAQx+U_-r&QbAM_dWy`i)kL%(D9daZ7!)%Hj_&1iPXgU105;`>lY<5`iWHhK5R(NPAk_>+HWYyr2~Yr;8+r!o zd|=>x0{q=x0SJMC(#EdCtV~wt2p)_8hcyH^*yO_}z~rw8ILHIo8Ya!;1dzoQPyr@9 z`*$JUCjd5hKLZhDqD(+~01yF-+T_@bhfje2?^NO9)?Yl}8GIfQ;*^cwXIm4R*C!H7 P00000NkvXXu0mjf4JNuF diff --git a/dist/unix/menuicons/16x16/apps/qbittorrent.png b/dist/unix/menuicons/16x16/apps/qbittorrent.png deleted file mode 100644 index 440f254fad8177a71ab83ffb3bb2c73a02cadb30..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 893 zcmV-@1A_dCP)~#i!NK zP?~TJXtp(UbQ3iiUbi2hA{8NK07B${5@cLA6qchwt5)92wp35o3vd)A3M@pG7)XasxKNa{-9a zC~^e_tj~|2RL9KaJZPH2Ks*eGQ0V9ck-limL%UOoW}w?NDvANAW&kx4qiqxGr4Dw* z395>YTAQG)=}>hGwU!0S4YM7`q06$g$psj!%WXu&FvPwH68$mwSr)44zU1C$SOCWb zaqnHbQEC|2s99jWAe;HMyyrK!VOC4d+3@VV@N*8MyW+@8b!=5S&}=V$S*ZZD7h|^% zz$OImo}EW>D2}F_ySkcQSzs*7)C8XEy6?fq4}CwI#l#O;EM&^K`_?$7=L%TN)^TxG z!gq69n3|W-)65a6FYHvZb-hn_ylg%d*-yw??stvl7t z^py*rpZfT#b7wvRVBA>1?G`J*vZ39>d-nJA_Qf2>c8bz^{`d6qqGda+|7!mLx+|l3 Tx1cG{00000NkvXXu0mjf!k?|h 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 440f254fad8177a71ab83ffb3bb2c73a02cadb30..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 893 zcmV-@1A_dCP)~#i!NK zP?~TJXtp(UbQ3iiUbi2hA{8NK07B${5@cLA6qchwt5)92wp35o3vd)A3M@pG7)XasxKNa{-9a zC~^e_tj~|2RL9KaJZPH2Ks*eGQ0V9ck-limL%UOoW}w?NDvANAW&kx4qiqxGr4Dw* z395>YTAQG)=}>hGwU!0S4YM7`q06$g$psj!%WXu&FvPwH68$mwSr)44zU1C$SOCWb zaqnHbQEC|2s99jWAe;HMyyrK!VOC4d+3@VV@N*8MyW+@8b!=5S&}=V$S*ZZD7h|^% zz$OImo}EW>D2}F_ySkcQSzs*7)C8XEy6?fq4}CwI#l#O;EM&^K`_?$7=L%TN)^TxG z!gq69n3|W-)65a6FYHvZb-hn_ylg%d*-yw??stvl7t z^py*rpZfT#b7wvRVBA>1?G`J*vZ39>d-nJA_Qf2>c8bz^{`d6qqGda+|7!mLx+|l3 Tx1cG{00000NkvXXu0mjf!k?|h diff --git a/dist/unix/menuicons/192x192/apps/qbittorrent.png b/dist/unix/menuicons/192x192/apps/qbittorrent.png deleted file mode 100644 index 9ec69b38a4163b11693a871669b97d56e8c96d9b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 36987 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 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 9ec69b38a4163b11693a871669b97d56e8c96d9b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 36987 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 diff --git a/dist/unix/menuicons/22x22/apps/qbittorrent.png b/dist/unix/menuicons/22x22/apps/qbittorrent.png deleted file mode 100644 index 6da1543cde81e8b6da3a5251ade3a7f814550c8f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1399 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 V@j0G)Ym@*0002ovPDHLkV1hdt1D*f? 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 32267058cefb19239a5e6a1cfaa7aab8f1a9deb2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1623 zcmV-d2B`UoP)BDj>R9MFJ{pmV(isp|a~X3rNIW6ay-*22@!L zP*#8}8&exyvdgmU7IvdpL9zu(B({jO+EQ>zJOBT0-rvl;yT?h=#2~7PUvhHq+`0FB z-+kxHx%dGn;tYmjp5saYSn)l<;agx7gtDLCd*7okyt=FXF9$o{@9a9$ee}fH(+4|G zoP1+n`=MX|cI`726&1Dk78q`@ZfSn-q2E08`1&X2%xaoiCtVmn@hCS%cZgBb&>EF`a^q@1rRU1_L-^F$p}93d5x^ASj{W z6OS%x?(OY6b6pLH$+F?4?QK=l=gkTPB;;~g#FJ?x(-{g0DGHh+BdIVFv8rlFrZR{o zL>QsL&1Vp2?(*&X-)S$KQ0lqv1`8H1UGwy|civ3JqnJI#3Q19sC-piT|2CwU15c`J zy_N6>V~7(W&+*`S4mOJ!r}|^?OsPfpp+6ni`1F&l<2NuGg|e2_8-F+SWe_$)2H|*` zl#wD*9ZQnRc!mhGbOX7tuIoCIqJnT#L?R^>)6V*tYoiw? zqX2={!a+YY!D+jD!J@_E1b5xLXkkjqLY5V{Tuw}^n22Ft5a%xp7Dl7lf*dm-qvnvx zsGthNJE;`Wq=Ykl!x#%CFr$7F%w`i3bYtJOAm-k^;2tu8SpZ-zubMnL7EeLT>Tpje z#lX-Qdd~M3R1#owIH5BRfrto`NdPh6bl+8Ue=-cCz?1S3v_3c&| z)*01@4j__{X+MV~5l~$qYdS?9G$oN77{I;?fgGV`6*+Bl+mKQ6NMqno^wV9i_bnSc}Y1B`K2;Ga?5-js~w? zD=l^+ONlNFhH&TY(=e^R8g{1x_szQvHPvNQ9|le^A(GSzHf?IGg3Dnci<_|GfuCYR zu@(P5{UwTBcDRcj7`)VbF_BCJK)}N**KGJ;Kx4n(caAN2;W+#AaUVN#MPXh2BHM9f zko~ngz;+(_f-T$hANGq4ovi1x0Q-0##74s+6RB9fV4AIK`yZRL<_KH2r-z*!RN2bb zHJit6`hMr%|DmNqiCS+3EJY?9_-7wp-1`x>?EeV6-#te)QIS@3d@(9Q$#Gb>`z%&$ zIe|xB{tzp+p2V`vUHGs!RIu(%HRaIdXsYYIqes8iD%L)`Wyi9|H$L^j*?wFcj=?vU zf<%Q?)GRi&&P6CHVb8(yuv(0T#z&727yvQ|>{b&h%j}p@SBCrVti!SP*Y~}#b@OTv z1d0OM_io>I*SrT7&YWJ~kj(=eZ$u#cRl87eVJLnGD>$+((X7BF!?-9x1s^}Z^Vp^h!oOU2PxIB`%iTA8aOxX>a>v%Tj_${huw!Oz30UCci!CiJtA;OA^6z>wT_tYMs`Y<(e*WU+kHF-# zhm#T#q5_RP4;0j+*lt0o%K|OsPjnqV@b2DS+g?)?WduJ2Q*Lg&{jpW+H@Cfg^yI&~ zF9(mE^QDiS8%ZBN^|}9#`~P-)`O4MLRe8KK@gu-YxAK-(R!yg9bU0l#08IEE_&@5h V@j0G)Ym@*0002ovPDHLkV1hdt1D*f? diff --git a/dist/unix/menuicons/32x32/apps/qbittorrent.png b/dist/unix/menuicons/32x32/apps/qbittorrent.png deleted file mode 100644 index ba838a3d3815d3c0ed29ee395bb7769a094d3bde..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2455 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

MNb7benNug9mnk zS+jQC##PG~uVBRv0MO3zyKJbKWumGP~^X7M6ImL{2jz6V`;u?3!#l#1&52E}5x=%-GE!v7M%X*ncf;YeHaks~{IY~8Va z>)YFUPIesvkfP?#{l6dQF6_B-<*>%lldqgPchPkV7T-62;hk%*zva#~bLKBvHDThF q^GnJr#{=+DO@g{}lmbKFCiyp*hgBL_pqMxS0000q8`` z>3S@k*H1+9`jL>XANHqnZ*JN4-j!EQ`91*i|HQ(Nvw?Blv|zzK$J;x5_q3$+=0H}@ zszh;)lFVrO;qH|FX{V+i3#2oTZFu5oo7GZwHb9d2kR+TTMuWjn_LFr#d+6s6ty$XB zpMjcFQCs3bUI&#QLWP;3VJ3kp!ARu=?V$|5>d9b4brHV$bo&R(Z@XpLNqxx?7j5TDxTTfi9T% z)?wC=V(KJQY3gZL@oZ4j%&shC*$7vWU4Td=(*H51KbAm)Pll|kIMfnC)8*5rKDh4T zpPm`$rvozhO3TLHyZ)&M+x&65M?+(&ktv)+oW=)|8EP7dB(DT9c%>3dPTXhdQUk%L zY7X(iu}LwPHaLf4N0gXwvZoKn$kq*uS1y}0Y2u9k2FSW-**z=fCimXN$Q(<&;hY(X`dF6d; z?=cu8=b3<{vWluPv*s1(S&JlC@ozD_aL)K}D-uDSk4*X-G|=Y0U$AVaPxGiFckCxE_i zzgQr}os^V#QCnLD#cC1E#1bhOO=i^ARKY`#Mzc(Yvd|?1STHe|cnvirxMIRclz56n zTv6b4IdJjlTG$CxJkuov0wMIpR7{vSb&ACzmlhZ*DXXj>)_B4Bf&Lhh^gA;YPNxGU zr9MQWNgO0FDf<~kn_!38T-EMKy!P5jAmirobd!R z=DaG59$rpYH6srRk#Lmr5*Sw1Kp8O{fL{QrYiMk66nl%?0$rl`nT;lReIBqcVgDD+ z=;#VUHjAOi(Jgs|asH^h2tic?4G+*=IgyzZe0sP8JNGt2v6w{Gu`XfzC&y4(=7zV} z28YeU*wV)SSWtjk!0z>{#0>f*p1i|^5 zChR%LGzBf)QM!qYb3LO$f~0d!GCfdWs4p1kmGnG>QAOr%R0QdY;vxqeP6t5&p=d_z zHXP3~c68yoEd3^!$xE=aE)8%Vg}cvleumknLW6;GR7hl_si9Of(9ezr7>ibz&1O;G zbOJtcqP@ESsH3g9C7X{cu6HjC&@M_Yq}t!a~*Q0jAuooaOD=#e#;J9E6CT8Kne z%?g5%v~Yz;60ehN*vLc-9X$hp!Gzo9T!?b79Xs}S;_L1>Tuv*j78y=bKM?7Qwlp7W zEx4?!y`}YJS6iFAY~&~!qOk;a?rX)c8ZSn%Zd8}Mm`!m}eM`AmcW+b#DL0E^R&uk+ zfUn!bqP9?Q-L&&Cb$l(p?g$Ilj;eFR=dz*AAH#;%4$=<6Fuoi%1zvX%TEE z$rxVk!o5qDJ{k!07T6gAh@x(Ma{VJs<1QY1@x-gA5)dRow+u@#Aqu0SsG`n1{?a~i z=(k!Gl3VBqqM5SAz)UcT0AnIE7M21l=3i08c(lOdwcv@LuYZ2qmbYI9kUJY7WHaf& z19#oB^mniR_4Tn$6ULib{OtZovCF<#mJK(>9+wrhN~NDfBjq1I2uPxfAj$xlfzu%~ zu&r=Y>pZ}?`XUCo0l$6j#Vt=i_V9WDaccgIGxbpE5A`;$xOw)C`*y$o!MKqXXsC3f zqS%DGQVY(j_h3|m7bCbrJ!!A0aH6Wr!7Ou%?{!r!46pTIB*$

MNb7benNug9mnk zS+jQC##PG~uVBRv0MO3zyKJbKWumGP~^X7M6ImL{2jz6V`;u?3!#l#1&52E}5x=%-GE!v7M%X*ncf;YeHaks~{IY~8Va z>)YFUPIesvkfP?#{l6dQF6_B-<*>%lldqgPchPkV7T-62;hk%*zva#~bLKBvHDThF q^GnJr#{=+DO@g{}lmbKFCiyp*hgBL_pqMxS0000VbtSf^h^|Iq9MU07>{wH zxaJHRfe4O>5O;~VAPCaXYyv_zH1zuRSM_S0Tlds?r$;$zlvJPF)m8P^|Gw|u@4x^3 z|JMSJ?;!@(zh959`OJsQcAO6B+u>zkGMN%sh%77uDNR$;YABRe6(udpazYdlb{tpi z_nsJ-_pLnkE#6bf!ep^gnfQ_tSZ|-v998N1lD@jioRAW&Ns^udiRT@{RRt zSH8CX6}o=$=|8>j$Gd;M@K>{EU;Ho4O~b|kh*!yfLoC8K0ImdHPmCKsVam))F1v90 zITxHWxOvpba3rRvvVf2T$i4-TY!@(X!14fxOd!*9ot?Y3Y}oMfi+_IkmDQ`>%I5MN zfwXKsAAbT>iA1JNn|Ah`t8Tbz+Kh{4NLo^pJqzgwP!p9935gKJV|VMg9*Pwgy+s>+ zx(7L=A{7yEWM6B`k|+Q0%paeA>IL1XbO!{i<3&JV;AH7^dgQO}x%-y$FPVFJM>!gj zyb7A@R5YX&h{E3%Ov~|bsIP*9eI_(bLt|YCySBW)e!=`-{N|l?e_aQ_4oG<4f&f3) zd^_dT(`G#J#1r>So-}dv>WzodI3S6!L!*!-0r>oYruP#r8ub^b{R5H6)Rc z^unWy7TkZ|!iA5z9tvMYLiifsV;9c8s3*E zUVxm=$0i^IC!tC~5(WQFv>q;FZPd$C>O*hRi>3Z*%kr2KL{N-2w z{I}K@?rbfoqnKjA)P)1(X&EtIL4>A9!Cg00JQJFM-KOqQsGGX)9oNR|WM6 z6(={vv2OK>W!GIf_tvs*^Z_uBMMB2056JyM6scri+XdV>Dw2?7bwhf1jq!WOqbCtj`zU)3SNcvyzwqM*@l>!-I%5n>!(d!jv3TjBbwO!T@SG`6H;UG z#0hsVT6~WdtxaueJqSULU}9q!x~?+-mk=`nM((02{V(XB;D{nLNklBFG0=QbN4`+< z?*{}#a1=y=iG@`K6Nkm{#`X*}HHCeLb%>gd)zhmg@FOg~Y9;8sx5EwJvH0H4{u0G_Yd!(<|CdZ#uO2P6Tu?Le=XkVG+P z!v-eABpez8A=Iii4s{j~BJ#;tGWN^gJTU*F^UvK@D(hVU%wrH>W}y?uOqf3Bnt4}z z)}BFk(SzdY7!->lSFCX7j^p^CS^xA4RrucjPd21!Hp{XgT2-Yo8Qrk>SyjUXTnr*X z_t_7l2B~=YqeG}kM$yq-!05?mOuypFD}VI(V~Zc_9|ieyGi~ge8-ISCpv2YQdR zl2%J7^mSrTO$>#y37rTON(M@01Ey(_IjC3!lI|Dj9$Trx1Pdh{xqON4RfvQMgW9vy zsu8HZ!_O>>`XW+=vd*7DeRAJJ2Bgq&sGa-j%NuAMIcD4i7tWl)c-g8EVCRG`n0?vz zLy?4*>*zplPd6kHJg9O-oj$-sA|6F;O%j@_28sdS@9WFLaUCQRaq_l=0|$?wVwx-o z#?9xTJrOSu(V>HC*b=d@A2p6@wot~wj$Y&nI=8P$Mu?b=&d#GqC1W5Cxadc7W-VR% z{0e|)X}d~532F8JFys4YXA2b+3VC8(L?SG6)+tj28ix)*U0s?7n<$`4AR5(>OeJ93 zHe^|5iI~PZ}V^4QT$!%rNUBQKOoMd-wwyvY)1XsAbRT@74M zK!KvMdv80oZrh8N?fbCn({}V_3UFP{AgGX)3=6~*hG`>{E5UMHCJq42L+X6+?3lJA zeb~0=Ft&es7~OqEey+$8CZ0SLk}PqwWJw06-dvurScs(u4xBXQlnDrABqJa&e)4G( zLt0EJ8J#dHW{`1QM8Xl&5O~`KGJSb`ymco<#9(;@Vc@?fj2nsOronIsv`OI9kb-Pp zCp}lF4-LV=QrWrxC|Y(OCXecT%@UAAOrJag6HXigRgp1#NG&$+?qGBk(?x*@n1kwJ z1DJB!=@VAH^wOUJ*kUz(j-GIm?RY#u2|St0^?O}?n)O(r`x`&mgWinqQ4mOK>#(6v zt{`7BxVW?FS2!H@b<6uhJyrlC)XP6#N7;)05pjH!u2ngX}%_Eu&%i+*c$Qhs@$^<3?#}m+Tv=1F!8OV~z zDKc25bIzA#38EzVKv-tQl8N4I*>?b$OQg#@HlRq{mmo+!FeU(0`ytXMK5gs4)bYa* z3#*)d%M}X_BpB>ib_NDC3~8We5xUNcU>b5LmPjRS+u;v%oS;+?BqAYl3Ov%4C2iZ# zD-KD_CUY1-EE<6*$b3z?o;}@_DN;oI^y%<@(r#654uOzl8Gf{NgZtrjdT{RO&i9)P zMU)K3zv5(InI=a#6jGuxVdg@F^+)cbL8H1sUE@K3%O=8MS%3ifIo*aR$w;Q+P!t8p zc#I=;xI53}JWpWq#j@o~g4>tqtP`+6LDbG<0?}xg-{p3J>6U|Rv4Y@WNtSe*VKOGq zWip~9$V9OJJiu}jQN17&eDEUcosjWB(#d>4vf?0DGKrK`oy;u9tCBS=kK0P3f9*me z0s(#o{aHr_BO2=viG_!lbo8%<{2MO)*qn|;mJQb= z1)Tue4nndBL6RxVF5H~%>zoOdbe^n;oCk}5xgHx4a9I+P#Me+&wYt!^savd%X1yuv`nky4^W8*q|6d2>o$kb z^}v%7X_Uu>;|eGT-Xg1d&UFFD@d^2Q_Q+g>RgKeVu=IrO@O?HS#;Y+N2OM1ogX7Z;`2?zj0rhKHM{fHVO;IhnKP(vY}`FisPb>^aRa2*s? zWm!?SAgx+3EKrmj+LZPQ`zrBX5UWXn9KFffOuh$B5*-*8saZI9$) zBdlqda#91g+i{>5dpq(>UXc~XB=f>ZK-+W%Tc{m=A;+$!tIRz3QF0Zpi6AF3g!gD8L;+Q4^#sk@x7;8Nm4)Zwa%ou@w!5$O@ z84hH$br#5q=*gKNzPNVQL=32jaJ%Ji?S<_MT#JQ5J|=}tk$|1sw(bhn1g;#^!}hk# z8(QEw&=e7oXoPgn?D0`c8^(@mKsv7ClnKokKCBKq_IC0tTUQgqs1pWq{XzrTmkEbC zm5ee;i>$A^1W~AtIed3&GwRb(e6-^z4j#>82uWseT?`jYZ^pRcb=>Bi&4;n(!#32W z2}dZzz$0PbR9J>?Zr-$EYv6c~3HY|7W%JhFp3bg#I58j+iBLEd#G@V#9?4)UYo z_a`A8Q;<%@G40d@I8XB&;StG$yhxcgxruaakz@=cV`0ufJskz46DoyXVsO4pPaoUB zcC6#QZAWnDlN%r_Aw)D4s;bbtGUBla_u008`@Wq!T6gs$z=zk{dHBF5AAh*v?DH<3 z70nrlMWe`<9n_?vXx-b5N1l5h7o0f?O+(VvbxcpDgpJ$U@zw`>G4tFpoUctA$P_Ht z4%lmwBJ;hsw;UlLB0k*F#r4nmQyXdjC&?Mkc0JBGYd5rG`P=)by-QJzLL&mva0s!8 zibUKeAmhc?R=;f+Mi&65nnr_*(%S!Bw(7hKe=sYqiAW|B$Q4S|fr^@R4DF=Vho9ew z`c#+~=eFa}bAxA78c>8?;(5R&Gi(p-2Qnm&7#atqxy{07w{TJbz~#WQH}|0?8HTF( zgP(K0pSHOIP9}T>s9a9OqhX{HVWjDvRW2HMcsz& ziYz@v5jp!D%@{lZ$RckDv);oRYn|5y@tDfvDMb=&7!b$nEB@!T9j)891Y0ZK=hwuJ zQ7#@?^5pNITKLctze`3Wl#@wbN*b2PVYPkG5IAr1j)cpLdrqzNxVk^&xB`QPL+=rR zU{S`C5WIdHTB1Z2JQPLFd?XnLpNMLxt4+ekF(4g7HFFtmQWamORSUHE$dWis>YY%PZ7-f-K`@A~!q z_v~-akXB8~I5}i>zf`XH^*w9aFvu*2ONX#VAXJ&l-tLSJ+jgtH3#e`(R?{zy3myw< zNJ3bZ5DWXBS8>|tIt-=357$A{peP(GpP4)Rdp~Jy`Q-J0fc`oNXf zU4PBKgBf(?2za)DLIuc{UG(&okT06hgB2IA4@`$M5^tFU9E|`w8+%>^B-!_T6}<0t zPS>?D;F@zAIc=Jr-_Ub^{DavyzwwvV&j;X*ue&>K!E=lE&%fo4cp@G7!KIhZk=n8h zOwJXc5Q=Cx&E-TcZ=lF!uLH|+IH$Y5F#}W&Q6%%f!^El~Mezh-s)Ds|m!FaI@`9+3LZ*=J6Xf>#8=h3HwF@}e=# z&l+S3G)?BgsHwiOcZ0OZVA<2@q=x#MC|g}R%q2>i-i?NUF@sf%9Gvj?fwI@koqOBL z<3yM9LKt4Bi#V1US67_r4$@S*#LZ@L>XYqA>Ig{=H3MiMO9gVbtSf^h^|Iq9MU07>{wH zxaJHRfe4O>5O;~VAPCaXYyv_zH1zuRSM_S0Tlds?r$;$zlvJPF)m8P^|Gw|u@4x^3 z|JMSJ?;!@(zh959`OJsQcAO6B+u>zkGMN%sh%77uDNR$;YABRe6(udpazYdlb{tpi z_nsJ-_pLnkE#6bf!ep^gnfQ_tSZ|-v998N1lD@jioRAW&Ns^udiRT@{RRt zSH8CX6}o=$=|8>j$Gd;M@K>{EU;Ho4O~b|kh*!yfLoC8K0ImdHPmCKsVam))F1v90 zITxHWxOvpba3rRvvVf2T$i4-TY!@(X!14fxOd!*9ot?Y3Y}oMfi+_IkmDQ`>%I5MN zfwXKsAAbT>iA1JNn|Ah`t8Tbz+Kh{4NLo^pJqzgwP!p9935gKJV|VMg9*Pwgy+s>+ zx(7L=A{7yEWM6B`k|+Q0%paeA>IL1XbO!{i<3&JV;AH7^dgQO}x%-y$FPVFJM>!gj zyb7A@R5YX&h{E3%Ov~|bsIP*9eI_(bLt|YCySBW)e!=`-{N|l?e_aQ_4oG<4f&f3) zd^_dT(`G#J#1r>So-}dv>WzodI3S6!L!*!-0r>oYruP#r8ub^b{R5H6)Rc z^unWy7TkZ|!iA5z9tvMYLiifsV;9c8s3*E zUVxm=$0i^IC!tC~5(WQFv>q;FZPd$C>O*hRi>3Z*%kr2KL{N-2w z{I}K@?rbfoqnKjA)P)1(X&EtIL4>A9!Cg00JQJFM-KOqQsGGX)9oNR|WM6 z6(={vv2OK>W!GIf_tvs*^Z_uBMMB2056JyM6scri+XdV>Dw2?7bwhf1jq!WOqbCtj`zU)3SNcvyzwqM*@l>!-I%5n>!(d!jv3TjBbwO!T@SG`6H;UG z#0hsVT6~WdtxaueJqSULU}9q!x~?+-mk=`nM((02{V(XB;D{nLNklBFG0=QbN4`+< z?*{}#a1=y=iG@`K6Nkm{#`X*}HHCeLb%>gd)zhmg@FOg~Y9;8sx5EwJvH0H4{u0G_Yd!(<|CdZ#uO2P6Tu?Le=XkVG+P z!v-eABpez8A=Iii4s{j~BJ#;tGWN^gJTU*F^UvK@D(hVU%wrH>W}y?uOqf3Bnt4}z z)}BFk(SzdY7!->lSFCX7j^p^CS^xA4RrucjPd21!Hp{XgT2-Yo8Qrk>SyjUXTnr*X z_t_7l2B~=YqeG}kM$yq-!05?mOuypFD}VI(V~Zc_9|ieyGi~ge8-ISCpv2YQdR zl2%J7^mSrTO$>#y37rTON(M@01Ey(_IjC3!lI|Dj9$Trx1Pdh{xqON4RfvQMgW9vy zsu8HZ!_O>>`XW+=vd*7DeRAJJ2Bgq&sGa-j%NuAMIcD4i7tWl)c-g8EVCRG`n0?vz zLy?4*>*zplPd6kHJg9O-oj$-sA|6F;O%j@_28sdS@9WFLaUCQRaq_l=0|$?wVwx-o z#?9xTJrOSu(V>HC*b=d@A2p6@wot~wj$Y&nI=8P$Mu?b=&d#GqC1W5Cxadc7W-VR% z{0e|)X}d~532F8JFys4YXA2b+3VC8(L?SG6)+tj28ix)*U0s?7n<$`4AR5(>OeJ93 zHe^|5iI~PZ}V^4QT$!%rNUBQKOoMd-wwyvY)1XsAbRT@74M zK!KvMdv80oZrh8N?fbCn({}V_3UFP{AgGX)3=6~*hG`>{E5UMHCJq42L+X6+?3lJA zeb~0=Ft&es7~OqEey+$8CZ0SLk}PqwWJw06-dvurScs(u4xBXQlnDrABqJa&e)4G( zLt0EJ8J#dHW{`1QM8Xl&5O~`KGJSb`ymco<#9(;@Vc@?fj2nsOronIsv`OI9kb-Pp zCp}lF4-LV=QrWrxC|Y(OCXecT%@UAAOrJag6HXigRgp1#NG&$+?qGBk(?x*@n1kwJ z1DJB!=@VAH^wOUJ*kUz(j-GIm?RY#u2|St0^?O}?n)O(r`x`&mgWinqQ4mOK>#(6v zt{`7BxVW?FS2!H@b<6uhJyrlC)XP6#N7;)05pjH!u2ngX}%_Eu&%i+*c$Qhs@$^<3?#}m+Tv=1F!8OV~z zDKc25bIzA#38EzVKv-tQl8N4I*>?b$OQg#@HlRq{mmo+!FeU(0`ytXMK5gs4)bYa* z3#*)d%M}X_BpB>ib_NDC3~8We5xUNcU>b5LmPjRS+u;v%oS;+?BqAYl3Ov%4C2iZ# zD-KD_CUY1-EE<6*$b3z?o;}@_DN;oI^y%<@(r#654uOzl8Gf{NgZtrjdT{RO&i9)P zMU)K3zv5(InI=a#6jGuxVdg@F^+)cbL8H1sUE@K3%O=8MS%3ifIo*aR$w;Q+P!t8p zc#I=;xI53}JWpWq#j@o~g4>tqtP`+6LDbG<0?}xg-{p3J>6U|Rv4Y@WNtSe*VKOGq zWip~9$V9OJJiu}jQN17&eDEUcosjWB(#d>4vf?0DGKrK`oy;u9tCBS=kK0P3f9*me z0s(#o{aHr_BO2=viG_!lbo8%<{2MO)*qn|;mJQb= z1)Tue4nndBL6RxVF5H~%>zoOdbe^n;oCk}5xgHx4a9I+P#Me+&wYt!^savd%X1yuv`nky4^W8*q|6d2>o$kb z^}v%7X_Uu>;|eGT-Xg1d&UFFD@d^2Q_Q+g>RgKeVu=IrO@O?HS#;Y+N2OM1ogX7Z;`2?zj0rhKHM{fHVO;IhnKP(vY}`FisPb>^aRa2*s? zWm!?SAgx+3EKrmj+LZPQ`zrBX5UWXn9KFffOuh$B5*-*8saZI9$) zBdlqda#91g+i{>5dpq(>UXc~XB=f>ZK-+W%Tc{m=A;+$!tIRz3QF0Zpi6AF3g!gD8L;+Q4^#sk@x7;8Nm4)Zwa%ou@w!5$O@ z84hH$br#5q=*gKNzPNVQL=32jaJ%Ji?S<_MT#JQ5J|=}tk$|1sw(bhn1g;#^!}hk# z8(QEw&=e7oXoPgn?D0`c8^(@mKsv7ClnKokKCBKq_IC0tTUQgqs1pWq{XzrTmkEbC zm5ee;i>$A^1W~AtIed3&GwRb(e6-^z4j#>82uWseT?`jYZ^pRcb=>Bi&4;n(!#32W z2}dZzz$0PbR9J>?Zr-$EYv6c~3HY|7W%JhFp3bg#I58j+iBLEd#G@V#9?4)UYo z_a`A8Q;<%@G40d@I8XB&;StG$yhxcgxruaakz@=cV`0ufJskz46DoyXVsO4pPaoUB zcC6#QZAWnDlN%r_Aw)D4s;bbtGUBla_u008`@Wq!T6gs$z=zk{dHBF5AAh*v?DH<3 z70nrlMWe`<9n_?vXx-b5N1l5h7o0f?O+(VvbxcpDgpJ$U@zw`>G4tFpoUctA$P_Ht z4%lmwBJ;hsw;UlLB0k*F#r4nmQyXdjC&?Mkc0JBGYd5rG`P=)by-QJzLL&mva0s!8 zibUKeAmhc?R=;f+Mi&65nnr_*(%S!Bw(7hKe=sYqiAW|B$Q4S|fr^@R4DF=Vho9ew z`c#+~=eFa}bAxA78c>8?;(5R&Gi(p-2Qnm&7#atqxy{07w{TJbz~#WQH}|0?8HTF( zgP(K0pSHOIP9}T>s9a9OqhX{HVWjDvRW2HMcsz& ziYz@v5jp!D%@{lZ$RckDv);oRYn|5y@tDfvDMb=&7!b$nEB@!T9j)891Y0ZK=hwuJ zQ7#@?^5pNITKLctze`3Wl#@wbN*b2PVYPkG5IAr1j)cpLdrqzNxVk^&xB`QPL+=rR zU{S`C5WIdHTB1Z2JQPLFd?XnLpNMLxt4+ekF(4g7HFFtmQWamORSUHE$dWis>YY%PZ7-f-K`@A~!q z_v~-akXB8~I5}i>zf`XH^*w9aFvu*2ONX#VAXJ&l-tLSJ+jgtH3#e`(R?{zy3myw< zNJ3bZ5DWXBS8>|tIt-=357$A{peP(GpP4)Rdp~Jy`Q-J0fc`oNXf zU4PBKgBf(?2za)DLIuc{UG(&okT06hgB2IA4@`$M5^tFU9E|`w8+%>^B-!_T6}<0t zPS>?D;F@zAIc=Jr-_Ub^{DavyzwwvV&j;X*ue&>K!E=lE&%fo4cp@G7!KIhZk=n8h zOwJXc5Q=Cx&E-TcZ=lF!uLH|+IH$Y5F#}W&Q6%%f!^El~Mezh-s)Ds|m!FaI@`9+3LZ*=J6Xf>#8=h3HwF@}e=# z&l+S3G)?BgsHwiOcZ0OZVA<2@q=x#MC|g}R%q2>i-i?NUF@sf%9Gvj?fwI@koqOBL z<3yM9LKt4Bi#V1US67_r4$@S*#LZ@L>XYqA>Ig{=H3MiMO9g9(FBRnAF2h!n%0}NY_zsydRCmX`t-9_u3E8l`B{s*=k)hx+w%EDDxH)S&?QNd zC4?765TS%p7&=yYrdXVr7(KXe_u%#|o45XY-HV&HY~H-b3!>@RS_Cmn(C?i90o;tq zRAlJ9;G#>;z3flkzGlU$H>_;y>g|=ZqydtoX|kdink4J03@Uz5ktISz+6F&}z(Mg) za5qq;$k!Cl4Qti%&}+MPJ^!nxo_X{qk36w$`_3Hz;0VG!lHV5rG65G`NG20~e|qKB zmtS$s^=}(kwsJ`zC(~XCWSm-{GqbZK2ZT^ zL*V`G8nkCLFf;|^-_FU{J!~(8(HR#G7F>uxf$r8Mw4{9N$iY2(zW2>j=%cr4}b8JAOG9;^v#>sJ!AQ>ZEylX>#%Hoj?Fy^2}X46oE1f{L$h@3qC%4R zEz1pI?~xk3Heo|jS7BaP3S$h|n_v9Z|J-xuXYPIerI()(BzP!+z!;r40pi3a&3i4a z?MrX_#2p{G`R4arneXUm^<98+wF-{yKxZxuhM|KWFiHX{HWBX&s+pYQuLnWO&4wT` zaKQlot;ztdAHkl{D(oJsfvzdgn@_`>4m}#&w&CT^-F4T!KmFO-p9**IUazW@ep9n= z%jE}dzw7Tmb>q$N`O~y%>eZ?bGNKCIDj2E+nQVqrSQLhgl5q?0(QFGBN1|gng*1C{ zk^nDAkY&&n8G;~$ZNpXAHD*J?P@yN6fcZTpjO^XE@zb~8{@JxZfBdoE#2wVvAs|k3 zt?#?_W4FHRrW>z}Bwal)Vj=S~WK7EE3Mi@qjvL^j{J5$SIHOsZk8l3s^TOl^C`!XE zVmDw3kOWiLV9A^$rb`zFryNiu;yr>>PF;4+o%j6x9i?Ki^8AZ0{Yqe{owy4$QeFDG z8$a+jAHVy)ze%Q2={t5ZMFbt zCg7+gq!T(6sxG{+s{m6LpcN!BIO=f9oCIun;mId%{i_fC?e0B$cL;ZIPQ(J@A}6}| z(#x;@(Cv5JWTvv|?RyTx;DihPomuG2XdpuXj_*T+Bm|*YG1auO|HlNpP5_h@1$13O zQ`W@CA}E$E@Phz>%fkGHWe95^3n}9J*@OY7^(5fAoilKxMD<1lhbL4x^N-eC^07~R z;$Sl#7@D-fG?TDwUIMau2$iY> ze#m~$*cf=&? znu4*43}?KZ5angGU3#|9Hb2i`n$7G7}~MrhHKw(^R8XH zw+MXR|78J^(0+K)nzz1f%@xQ(pzu)=*=Ix<(Atcwg8ssI0W#%oJgj+-~Ij%-(aM2Er&)Yq2vI} z6w5Hs0g%?xP;~;ZU7v_x0>X&&9Do!>aS_zOJiBLB6$)TXmKT!M_?$sJB%=8o&%@&= z92^@}0)vh?4#*%20z5y2OxnaCXo3+OhC_!AL-zEAP^x;6#=vs%TduhLyz^H5$4f7- ze^y}hjz@ro5?!?BPp(*c=IUj|iY=8b4+ByS+{z?$^miiT3RG(jc&MQ$KmZ|&$p7rW zagdtDErUl<`7<@gCGGRyo)>`c2Ld{00@~-}vMgdshysmZNF*u>N}UBzYBHpgCUmu# zuyt@4=5)7%-q{8-)f)7)=DTjZ`2&Bx?&bCC!X_)2O@Kn8>qh>X>u-FAq9;?Oi85+B zfQchVAgKn(asq7BO0DLBPm$jb*z|c_O(q|PBw@T*I)XqHNa12_#{tLj*u>+P=i&8; z#3mDP5xj%Pkqf?_OdvT`)?FYZ1rPv5W>RS20O8qK>UonU~9$cf}0rAiIT782?@;Ob;8WCaGK5(bPTB2R{QT!PGj1_soK1js*%en^Y9unLV$p+|WdT-H;JE>tR~UqB{w@N{Qq=Bf!)=;~ zX-qREG1zc?D3(eH)`MI-lBY;~{^WEC$?=d7g-9dKvJd+~jGoWuxR6A^{c}2CPFE{` z|Ew1W$;0C_aByTAQ?d)1tkCzcr5+e9!1UBKv~{$DMKLC68t1?1(u<9+eEA{AaSO2( zG!q~hiR7HKS6{Hw4P?WzYhYDNP_Y~armG72Es}!T%ja5P?%Yn)sK#J@pECh#E{@Wg zp+aX@4g#O+1J378$fnN(s+vp|A>sg^6dM4?li3Dq!3mZx1pk_Nh zM|?$9kx(Bj%VzWEv?hR&*)Ll(mv{Uif334r2aJ&G|X~~{@?i*J$5x~A62?C@uSFB!PnkgOeAaEOe3PhwWNn*cE znpw!_J3x{ZS{R%6fkPuGqwI%L#6+=w>zW2_EotcQ>w$b{J6nMt0WTz~heasNR1mxe zkpL6^rk+2PA9%@Fe{D z)dMg#S)we*U1!`OR;?QR&nx@c9WOY0Az2ys5nb&WIEcRQ63L;2pd{Srbnc0S!p5j$8%IPQHtaon1V23Q%xjHz;2L$u(=M8Ou+sFV;sPc zAtWk9iBJL-4(gn?WR4TDn1+F%B^aA15&$}fHRbsY3dl-cc;z)XG&(IhK!w)9fIJi` zp95Umj{Qeq@bGlZ8_J&tX&(h#)V*3s3|)rBT0Vqfe6VZOUJ*U{0{ zffts@99cpl03bkciDZKPHj*R`hC^5(&Xj88hg`Eqv!{4?MAKC!A>bZ~g~84gEpZNi zlKpq4WRdDc5R{m31%Wzlhy*n5powcUF%x*5q46RtnxAJ7rU-zP_5x0F5-Sm-K9lc< zp_ImTioWZ29p9=i=UdSe|C^~o^feDT=Lx|XorV3Rm ztOz^@KMkek1ni=rD56})VOI-7nM~b8D@=oU9VI~1wIrIBP8KbIiv=Nz3{V2$!ceWb zP_bNa@WYBnRbKr#ty9GXq|*rwR1;GrFwGhhhb-};Diw!KRMVxn@8N1Q@M8+=X|+(Y zD9v%McMuTFnlsB1y9%a08#V4T0bCj*ah5|aC@Mx;KaopH0IDd-gA{`>HwVE84{F?G z#WiijCyN}d@ZW*3M91}sWiD1SNd=>Qib`S*YFKX|%PRVBf$RN_d{lP<0Fed4dM2Q* zrs4Ahx;Y5)F;og<(n*RzL=qow9v(Y>!0&mYtmaY~B(#ipKqJp;$;6yhmXz7OKqS%O zW{O$o;tV1{n6eZ})WwNfJ>)9OaC}agCDcZ#>@wRG1W)X_K_u#V7T$L$;K{fnEQ(0+ z#OENM_Ea6TvXv0yvo;D?l z0|Y)~z+oKNxCV%a9St?{-Jq!oyG=_bMQ+IF5pt=C0Kj#qBAx^RxsC%x%Y)Wziiwn% z2ytOn1kG{+ubF_TPC(#9q!@7zPf=9THcx!nPo0p{P@n2?&<2V!( z$X!^&41mcHK@ig=#|{t{Kz^IaBv4Y#3kA<3m-0CfYP!xOxgK9za8$P>)6^i9&_pox zVPvv`mJ(o1pmB4=B9Q>?6G@Kec_J`1*@t60mCz4t0?#KQ0Sr!2c;Hbi+cW~>K$l4+ z!AuzS6s4#vWy^<(O=T`?839D1HfVAI0_I12EG9zJD0P`s60_?F{16aeAE1C4$0IAi zIHPJB#RmS4suMDy?X9V!!_?`r1N%p2IKF6_Lcm4CMFJ=i^#-+xiK${U0qhTx<0I2E zGt)&)mLnC})ifPsQPM^r!(_>#fWzfzDrGWfvSLfoN;O=gSQ+H zUfMp2al?kzOoCllRb=X7S&5n|0qzDP!v}^ii;)F@AV4T63`>Li_6*7jc)B8yX|nHW zqQ5>eS%tyj0%?oqfw|T+yyc>0@P?JA;vx+upFz!dB{Fb#*sDlmMc!h!jw zE0)8xZ$1sdDGXry;57XFr9(WNF%6xoP!>|4sWK7Nk8aztdAGPzZYw% z{n-uI7|52PDm=+iRf~L#>+cQQhM;e58!Vic0}mOW*VBewSO!KXN=Q(JO*-3>WWQ|9 zCiy&Mn=4CH3Hzami)qKE#j+gk2`XsHHEOFH6ML@au6xT8c+;vr*f(5+*A5p+`<#Kg zb4fUJAPH{BRhIt!9WZWj2=2Pv}xn|ZG=@20CE!n z^3dS!J^Oa=+-2x;VCpg?khz3`Cu=-#tMx7uaK&}}$P8^=F;6I-ogl%Z{ zG~&vpbjW2*1Zc$InZ#!{9fmuwSSy-==slgQUp5^UBN5tuI%q zwD4$lB^Z(fo;Uscvrj&=>fAS;n>3Y_S(71^&Tt`Qc)(?;joR9Ka2ng$&9HPq2acrL z$k%v5z8|71lwm)DK5%%NXMcUY9aJ+g0ije6f)kS#$jS`nejQ^(3&)!s2WH^jA8w+l z5oeFRX!)q`*!tQuc7qj4bF3U)*C@uY>m^K$6_ZIJ zX}IrNh3d~AedNi;168w1Vey9g%bz{+;!b>QZT2pg>Q2|v3>}u zlnzBvNVUSAp(2AZbcNG0a3%@sRi__PhN85`rf)KEGJ67_pqnCSJ!HjFxMkxjJ2tFe zw@#S9H=6(uK4FX=+P~wuXPKh8 zQBfor0jq54hDMrKS@R}q-elmZgo|DR73zyEEjIJp8?H{^-q@ zzV*_UT-Urx1vQ#VLW^y41?Tw^o3Td#K?j+ls~0w=Vcbg-_&Om+8w{36kU~QenaktJ zqAQfbLyman!0*L9i7sw|acxiEA-+r1R02+*SrSM_Hl5(!A&DoowIt95)M(T5>t22G z@wGo~*8Xt_;5W^^+cvEG#o9;L-f-j1H??LB&GI9>aE3?Ce&~W%pRN!<6b`6tuAJ@& z7*i|=XkdqcBm`jvG9h70irYfoG@b|%B8j*7qT~iBvX}!ZZ1Twji3ZtB0zqdWY08k$ z0%2k>mLWxLNAT2#|7g z%oTCB6`*!#zQ=Y%(2|sbhkyJZPd)wQ~$xHiL`@Cjg@3k^}IRK$N~Th7P%PR>f^IP2t%B*|m_y z{qTmq<93(#g~kcE#92UN@G1(`8;bCI6EjMh>kmWruvjvozc&Y4H@>*-fq(q+13?fJ z;y8CAkIO6j_w3l+(cRm7&Z={kBM8}bsOF~`pwEj^HJvrYelOZiMa;(}+LsjuQmi(v*psv!d%owDHHf3a6QH^h;hC%#d@X5P@f#9I;QntWZ6 z*n+r0(_{qCe$P2Rm)79?({r$Fek+tLkDIhP-DxP7N|mqQd(VSUKe6^d#pP|3@I)Vz zb5IgvL;H7p?Q?hC*V2~DtX#F~Jl1ynq(-I6_wRKzMNJ6J4EPq7=1@EcDNnNoO-hRt z@K7WMEyaZJD-Qm$FnQWnWKMV7KxypvvPf|%b$k3?f4dB4^d+G$Z$P1$*3)PxOLsN0*mzo`s8HflDpw0ddM+2SA?gOAoxAB%4lOAv(jp{=?jh9N?>_jw$L{~ym;RCFBeC{>+h>L4__5QK7rga~kA3>?JI+35 z^|@0sHEC?R#*d+tEekBi1uxRT4Q1-?s0?PYZNEOnLE#%MC}jTpk4b1e2B+|CGuApq zdJ<9DsTANi?HQ`f@j&t|SiLX}tCn;F@&jYzM+)D1@Vh_x$``-z^TA78FWk_H@&uK09Iq^iAZc2JB**?=w*W<^Esqg|)+I1ias`z&KEKm|Q}epJasA7$-t!Ni|Mt^Q zJ@FIa^P$jubTWQ05tHEIircQd?)}%j=avuNbn2pk0oPNKlx4p7Md zqd1$O$WkK+YNUNp_?TSsa;ZxbpwPFAGuvNTxATV&ed7nee1hxy8KD>(#r<9WXi7!V z1ncJFGtWKu>UX{Ox(hCP^F^KbiXoge4<-`CIPv?d~qp7{eyFZtsuFFpUl zOD|e9aN5$Aw$_X+YdXdP6$7B+2TTHsXcL(LMFvs$$f2Uh6g^zKR&_>(4-Ri!_rm&L zKK|HK8((^69S1pKeFC`uhw#Hmc3s{!B5&I%int$-w<>6md&Q|6HqDu_h;vOpFX29NxKY)2?ls)^Favb>j}y{)jMdIWBAj@aPZi zx5H9gH;8R0jv2VgwB+(_9i2Vxx?!eeRW@WvRuF#}27%{$zEvztmL|tXrvl$C3GD_= zYjj1U7XE+w@w7bahtqJ3Ux!PxJ|8u8ZegtHSWd!1e`hc0gnmBHa`IpQ3&14>N%W&M QV*mgE07*qoM6N<$g3OXBf&c&j 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 edfe65866950fa2185fe2622721b5123cf80a5d5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7494 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 QV*mgE07*qoM6N<$g3OXBf&c&j diff --git a/dist/unix/menuicons/72x72/apps/qbittorrent.png b/dist/unix/menuicons/72x72/apps/qbittorrent.png deleted file mode 100644 index 8958cfb45651cce9d1b29be03a29ce3e00f5afad..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9063 zcmV-tBbeNYP)Mkq0iP?ih`TWh?OD0VS|b* zWg84GY$FLtRzwL2B{Y&|Mq!4@xu@fM-TnIIaMS+IckZqC+Kp0Sf!NwR^VPlYz8lW@ zo$vd7;hcU7{rWeBW&ZKowIhgR-sk@ZHwB_WOo#=s!(%->ufD^5YIvOy-eZKHKls7@ zHM~S)k((cmz7m3zNG0RR?w+26ZCSRiX{Ms8nyM&@ANbe;*Yo{mrBbftXY<8MwO%Bm z8pI8sqlOYh&;D%zNM&h(uR~&~bh0DU+t<_C)!jERxM-lae_*h;Z=kP#V5ln=kHrmL zvouXL6l_7@d!83Kp655pr9wG3HG%(QF{Sy-tqoq=@Sg$vPb~z9~k`D_&%oA-K z0c+9Xy*)jPFW&l*^RL`~-Q{PUf9VC?{fmcu#Za4$N94O?Xg=8h$I=xtHI;OTs!D`B zpU4G5P1mQo8&Ja`a(snUO{18lQ#=MRo6YLz@xzB+e&N{{pMLVO=U;tg$6JMBc{&J! z2&8Bq{3ZcX+JJE&iPfuDow@zm8$Wj8W!tu{7~Zr>wL4NxPl=g2DIGD5I^rrNO^tzJ z%^`>~zcE210VD*h?)X%0_*AHQ*atuW&#@FYrZ>P&bNK^r?b`kD1NS}r;DZl51HKv$ z+ZBYI<^LuC(jjIDl0VQtuzuf9cf+e|*nyS8rKddcm-`{^65{@Arw1gS-RBQqW;L6g#^OMPjBdQ&Eux=R0+TczPq zuH@2G(VC!13tR zOr6H_O=@~X13f8Pu~;X!6k?W-AP*1r_iA{-+c8izV@|mJ^A!gPt|JmYG`WSdj&~Bo=-~HbAe-z>T zUdda3ADUxB{8ei3|M{mGr5xb?cNh8?r2P;m`p?E4-(ltJl449CO(`H*%n5CGCU zSlGgEq<$=HkP^((eMD325i@C%HsGDV7^~1!p-HZf%O(ST$?~=9zx-eS^h@zX(){+f z|M~}Q8WgbniU1j*Xp5Jv*z|{Ax$BEJ-}Z@*CSsP6FF53T0hy)%Kx z<%J|z*uBS10<;hu)0C7LdRmmCk@Y3i~St2f^9#XCP= zDVLoe{NM-oV*raJH}_ZJAT7+B;+g(|RiFFvf4TFsU%2yAwx#PQPZdRXslUsj&NzVa z9nv)g0`u}h4*4>!<(VGk5;!pMB0S zY-?m}mPTi4@K!cmv^GuM35^s0;JDBlfD?h>V;{W$$B`zzx6oWw8Ei#7hlsTi$!j|( z63hr7$xjSa+%`E?dE?kD9hz#A9W$v5=AY?|(~?1pPVIZ+)j$67m;d~gmv=meHoH;O z{eDa=;vEey@7i+d6_@{qul)DV>PFl=JvvE8$19|oHf_w1=l5z`;XrFoj5vg7*rL8U};jS?6AO@n=5&pMF1` z?ud_1%+SPajq098tGZ&eve%$`txiqPCD#k2cKE!P8Z+O-7DB@3=6_ZI4ynZ2qTy;S z%+CN5G}Om=uVrfUOfTdmLD(Ly3p}!5UaJQa^xBaEWoIjtu+pRghtoNWK7PwBHy_xy z_t2q3-#i99>tUb0cL%5y40_!?y=$(y`IFaOaOsu}+36Z(^JSW;!p@W|-g zb;HxOiQF_5>nhcn4lU^kD3gGvs5w+`cs$yGf`dXo2stR2&o}&ep1ncjUBb(d3WC=Z zl>zXYK4TZqe1Mvc&{U7q7ChXl#POn?o1`hfYm2 zY2BG;ZT_9#z5UjmyLRoG&Clhz?_oOfb^xi7Tkp>FuiJj(C$Cw&d`aJtlSL|494gkJ z@@|DPmP!`xEY#3oLCm4nV8`48X#oMR4aB017+?038EZUPSCH&{3TC*b&SF zh;MHJ#9*t88plV)N|X9P&ONbd+A}&unVvLh_?(-qL5n)9^Depk(rw#5cJXliSyBJZnt_prGJMRg7wWZkAGdol>^SoKtHwsOh>=nnE0O0)o#C z$Hg&!7YRPMiR&?7x^6H44(_kknpCSh@_X>wJOyMg`OBZ#h|W3O1_;iF-k* zoiS3K3QdlV;T@7Q$8$b)^e!H}=@Xy6sUw}r0N@3+Zhc|li_COq*P^SoU4K=wqd$|I zsc^7Wt<|V9m!s~!44IZe<(dG4N0~JU?w!p;YEVQufqbZ@&aa620LIV-U-12nMiYSY zz5H2$c%IID7HtSf*;6`#gM8*08B)x5^{kPau9D_!c)ri%9divzCu7tJ4$4kVQE#S~ zVpbQYM_q}8J-qp>vo6@OWz&lYXEh3Xc;^AYO0`DiN|pH~nMk1FCYgqgXIE*q zn5T%Ul!%M4XA^88#3k5L6(-nlSR4Af)6|I$$83Y&84fvX^<1e+({mN7R7Cuvivi_0 zr~~%}Ao2XnEcIkEl#JVWrb|}BieG%$RhKPV{Pz#c=JONcb@Ksg*D1HRL9kzn#cf$v*4mSA>B$>)mjQABC}uav zvLx?#Ssx$^GbK(_OatdNXq_v}b$;H4^o4;K%yiIDUl;ZDq&Z^#Wm`{Y5@3{QY-*0C z^A#!}Q0z#>ghuf@P?Dv>T!A_}I{>&rHAIz5R<0f1v}yDDBZm(kfW}WpW~R59mv6`7 z9qZ3LXZ^sUWrK4SU#*~1wOWNu1f(YN9QInCBO}#;{tWf@cCy{0Gu$!Xk*+)REexm* zAiJzIgT)-93gkqmNdUyEW9Wu7Pn<-M7u_FiJQ&M{dT8lTHzi_ryZh(&Mf`&eAZP%w zlTzTEy+BSdb7&(198@c>>0QL0t z^=>%h?Dd*1W*@2qzCs6@GCSw+UBkI1)Y_!JOb@{60w_`7MpT8zD3vN8+$I2%F^OgA zoU_HzDewZDnWm`>D2N&2l3^NL1pvSB=qdu@lms^l54t-N)D6v0Bph}+f0*+0IfwHr3A>*>w(0igX659w{* zi#j^H`&O-4zs3b1O(6gSq!&iY9yi=|1K55CbwNEH9%!izrx9a}jAdc>H4cmArf{lY z0)Wnr6f~}vIy#aJ5S}M^hKb$+c;Gc2k}OC^$Vm@uiR=jN(3h3~O(UvLQnRIk^`h33@(RBzwVKxSZYAgr9$827dy zH;$>`fv!wnHySB}Fi(KwLx?%ZqW~I^0@>N3VN9e`xj8y~Y!s1ck+1Pd;f{O06x_~Q zQm!;O?(mp1s&R({k~JUKcSRV%W*2Q`Xv|c;!siSCi*KTMNJ_xk!cJgvrc8%VWf46m z*wjGU;3JDQvd)wtCmt~v%&~YT^N^wu^$!g6_4IV5M#m<{MVBIgf^=t3qPKsr3zj3x z3LbkV;w>!A$}C=C@*anlxxNGw8@qUb#ain7!s~J$B#ro< z%>Ds#GMz@KmQ4I>4)QD;%5KMPT*FZ>iytMR5+taQY>rAYSS;1pYyhbAWULxd2FV>} z4<a&uL3rvg*maOVGE>{7Pke@WNQg5=~*>Rw^dcMBINaG7%;jRB;Df1wA;44Qkn*Th(;>l z(LmzI*BD%nZe`K{mAy&|q+A0T767JU$7P1Du&ZWAP(gI8>KcOs0oeRD=AbrwIMk>& zL?j+#&1h#l=yATo}MDxnNEJgg>UL9(g< zHvBVwc@bS^ukzmYA(4rM!CF%iWjLxb2!v)asC6;w^(LDU5=-uUyJq4e z34GPC&I~2w=gA<_Ur;bBAx^5|d=JPs5syK8Jx-)s^FcvadGuN1T2GL`b8d-2wPF_c zX<>I6U=Ga}0L1mc*32FwE=7&h7~}`{&#s&=V7Q%d0E_TC4tpz|-6w3FHBIH{nO`i! zfS?^<;a-KiXHH=AjQEUX5q{o+sxp8tSIW$PUFifz-xvgOX_O4`I~`ZNPnvuLK^1M! z73$Q$J7Fx4Hbsd#S2GU3nW2D+!nJ8aE;C2wg3`f`cf;KLUTPx=$<*E zXMzk(6Yn#5u~h^zbJEmI71y=*3&#pXPG3vYcH9O6U?);9Jz_V+JPqG<>ugLCpa^L; z8|*owud{6v*L32xMH-)X0hW9rIEp*qNUaIy%cPfbqy|NOz`sD1yL=K%gc@--Mg4Vl;z!0J)yzrW|6Yi7ZF%Ja-0= z<-2?Z@0Z20G!LxWW_y%9kWy zh%cx=(;+#@mw6b>l{*Y!(BpU>+&BX^hkN{1pvZt1s}6q$O=71|32WFm#Tq+P#2|oc zmY~#e!G@v8yy)a)k@g&&raAz(O&&-F$k3(en%p<*o|~PTm_mWCEHG)W2PsaoQJR_< zov4)S4a?LmL-lc!C0sT3bzYc|gNmM>%wzhtlT1CvS~R?R5uF^Jp;4S~Iy{n0<~~ta z$x~_Zq8{3?dWbf!U&^6^6P8n>q|}oiFuJzjC{8NVabup7fthnPvsxFPP@|GqVOFd| z(?ou!a1F`9fUIAhp=}qgq@hfbqHV|C3EFdfmJ%_GO;^{2s5sWxsX(}Yv(vem?BwL6 z;Pi-tA`N0Io6b#6=Cb1xwuKvXh3hoBA&-&I@RZ8YQ_~#AJ7K{qg%Q8Y z7oi3Y9x+7(%~LFAZ(K^(ee^8)*yWq3zrRzGvnTn&)S1V)1dBY6J32jAr?G62iM`#; z5A?+8(leLP+GV}0Wf%mW(s4aG5Qx^1!Dr~-U3&&yb^cO{wvnk4J^$u7&j|N)#@W1d zLuib`@3#ycA_;xu#F10uO%)7i;Wr;eUjvTWsYQ>)9HEs46}1OOvW zqZ0)>cr42myEI6!0h`S9rXUGgHC>kAIUd`3S7(CVv1Q35wGNX2!A6+~+dTl~dJ%Fj zP9!UW<2;4=rF}WkqD+eJxM35G=E}?`C&mgeUl{`>VkRvgOw+l;eW+E(`CP<3KYa2K zy>)Ds2f||W5(BOav*OaPWeW>Y3189CL;DXG^0V0}d1yB=pP7Cpmpy!7-@%VuvF!@J z31XQhcR&-BL;#|cRC;~?7<-AUFJ28zG06)H>>U6jo`^-0cx=}R0U~(m*hrSa-84Le zdkmiK0H=V{8nme2r0%Y`NDXkV%KYN{tYPizf>?`J4s`&mB*5rrO(dB{@L^N}Vny*I2X@Rg%yrUp`9XQw17c z(MN;5N%nRgM}nMsfKSTMoN0P<|2RBgjkcV*EF@+IfThv^i14cLejLPgq4sQ4n|%H! z82!$q#Zmduu_7Hlou}1{I%vc4E?U-~q*UDGcLofmkCdiChfWvh<-L=%`^YpWx0svf zHXBSACYL?n$(XQ_O!HKbuDZ?Lue|u$>C+=85PsAmOj-c7w5T~fIX;Tz{V%Luy>?|P zVWnfm8oTp&JPsFIqlT`5i)<$78PtTI+jR=sF-3zJn3rvGLjy>q>aeDjsxmC-NZG8` z0zY2rpb!U@wT7qymN^_))R)F|P7>zZ5Q=^ z1spQ?@P1XA1R2)=3^W8_V_>m23<*k%wFck_&51)|LNuz(P8Obi{Gp#!N@ZbQUMTd- z08(nTYVpNqfAajtZ@Be_!NtoF)aq10!%#!w`fbD0K+FNZ2orZAqUGw};gPv;t&U6> zDUf+s9OkKMF6TyGTbdC?(=J~s0z8l0i4r_b3??DG8o0}KWWechwJ;og8Bw2@s6eaA z;e=xp2B@S#Q&Q~8r8!wbER6+GIs+63I5G6A696j6v5xHDe|*P_FYH9$D=jP*0>l}X z<20)W-`cqc_V{KW{%i?e$esgFB+$`DB7sJOL`@Y9Hy}ReS8+%~)3~kzklNQj=V@B2Xh#Z9PFg%e*;chw6@Dg(>qX$l z@l6XPTaY;CcyWNFvNmNhHkGpD*=L@3^qG7s*uPUhlJ_{is+z;L}0AYRF z4|6lA7D2SEg};wB&hn+&ggK);_5)T~<|H_iP;&r`5F8_%;It@V!^{j1^K2bdELcZ&pm&(XaEF&0)RZurRwDK@JWD3){e0EWUl7AtOY*jLn;HPs&aH~n5gH- zWYG^KfbB3yR2cN=6K|?KA8D4Q9v;SV#CCd z21^%bf>ORv{oZ%}>W8~udu2xmPV@b)lMX_{GA2%+IQYOnefRF+jhoh-f5Ew16p|~> z{J70zq5v2@ZOVMDRO3QAsT}^Z<|tg^R9Rytb5(la*<;~q*g#GKnz9LzzYc9SI%Iy4 zipBu(b9IOsX^jw}MQmCc#6+lI(fTDRI%`!oPk2J(Masi5meVLVzV(ei``(ThfA$f1?%OTe*52)pC4#_ru_7x!IX*T$e8xG$%a#rH!QQzTuWEW&33O%oz?AWe!ln>) zh?n3&6oDs4#j+~NVHdk$Ev)Qmk?{4J%)C_yYlv{&5L1&pX0ZE)NOMXiEO@3k=ZlMb zExKg5gVrrggOD}$T+0@TDJR$c{@?uXdw=-7zxnRWbnYaZRj56`%HN9_;dSZlxBmVu zcYfuocdpy8_Kc|<$`ZK}mFqrL%2le0d2UysswZmKJl_>9%49$sj+r?Ak^BR}PJRv| z>uReYMs8gE<0ZmDsFf-}<3yIhVZMo*LPIz@4!j1f8#HPAIRp64=0G$ZgLyaV&OiV2 zy-$7Pe|+sPM@LTnA_T`_fZk!#-p8Nact;PswGUG*-cqapS-NDPS4B6_S+3CW=DVyh zmSqTG?J#r*cPi8fjTc#BugSeGxx~=h#0WLURApkxA_%xezNw_i=}T8ShKSwa|Mq3;+2~zO;V*nql7ybW?NC(FF4lvSG1+ip|Z^O-=|=qlCEBgrEWtu6OpsX`pBU zdZa<^L7>WY5PQ=WOc3CMWQv7C{cr#NA0GM6xBl1P zj-5XBdgvl+QGb4QfLdP74K+@A=FxlaFXU%RU%cyoe(A!C&b=^Ia4CyonG%?yBWzlY zMjaOmLKRwMa%a4_!FiO&MRt!poGgrSaM_Lzo0G!DbcHog)0vC-v!?N$E1j01kPV5M zI5g_8V@w9)B5hfnks`J?qk3p^OZ@4zJ}fSdPbY;}Dsfd2)_l zniz@w!jWh#pCRV92%t!-Ohe&xqAQi)iewz$7blO7J^$3h&;Izn`yN4<^C}U|wE^S& zx_?+e4PTx*Z|g@t^6{HK^*fhbwslKi|B9umZrG^Hh*~qG#tY9K*M$V^S$vWJ1;ko4 zAD}kvQ8`oy2udQkh|8;*;5M#HCE>x;z@uV*YU0?w-AA5$Y||74FAfzvx9Lxej*RVo^`+OId-~Czp2bPpJiMniQhMDT>$@F&j zWcs_hGyR$V!G2UL2YWLp^`|>h&l1Vu^SHd6xm(GzciM!v{c! zl~Da{)C+Sn Ze*yP*8Xx?u1D^l@002ovPDHLkV1j8Yc=rGR 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 8958cfb45651cce9d1b29be03a29ce3e00f5afad..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9063 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 Ze*yP*8Xx?u1D^l@002ovPDHLkV1j8Yc=rGR diff --git a/dist/unix/menuicons/96x96/apps/qbittorrent.png b/dist/unix/menuicons/96x96/apps/qbittorrent.png deleted file mode 100644 index a7e8f781e78409cfdbcfa19638f0339666dfd350..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 14165 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 - - - 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 01cc54de6f235b6d0eb8e34190149dd242b9ce57..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9387 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�)J#SY_gOHvw3>QG>bQKg0lJB-IxNu_C5e?8!ED;7r%`)*i>1;2L7tLw|n7^tZ z0EvdiKd@$PUnpMx$!l6MzAnAKXvYeLb&@FGf~>$6jbB-br6Dn4pDQwq;|vesUzLVl zZ%^8Wg7I#yK3173V=&q*x@@(~dkcr5=7rkQy$04|Rg+d?o79t~U-HZ~RwCY2e6D6n z7G9-D)mVD2A~HKQ3p?Y53C<1Z=xwdOWiQY|c|eTf5v$}iv*%+=#SATSI^eA!#gKSp zJ8R@z)f%A{MaouLqlm;B*4F1{Yg*y!FMW|`kv;wg-SHnw1*hQ+S{MYDkG~)~PT|wP z8g&56z75FnIT^RHnPRH}BPcG!sSD8?ZYiNv4&{&J^9YMJvO))h0XEx_VOhH6*rzNV zVa;B~4KhPmzf@BB9OgWWR(~%unPfggfYQoh!RLLHp^rd&yP3=77zaO+qrQ_yj)Lj= zeX>GnE>^P}3LhhiW@Tz_6eM@9a>d@Tx6^I@avY0-Yx#;4TWBTs2|8MUMk0@j! zcDT{dGDB4e(}uuX*LMG_&oy8zqfi|*Z0`fP;toj>rVyB7^G@*p#Lw)qkJYb75ryC} zBU40o6aIelhQ`y_>1w7k^SUCZ@FLpf5IQ-=}xIS$+(q86=x!!Z$yaBx^*uM9VOpHr!i~g$e>q}@SN!) ziuW0;RY;7!Vrtzsip9Xs3|2()1w1!?BO(sArfW-lo>do z9ZpL`KPBt4`1M&;!VF{y4=QZjjL?C}RiMG<9769=$L)%Ukp#?f?~%jOxUf>7qxZal z&S&K^jSVQTJ1bQdpY^6*`(Iai|K@4QF`QxnJ;DogE46_ ze>)y8^*`(S{l1`I7V85tPR(^q`V=3|_a9ScteEuS#&0qyct&u^JeI$p^ge~Jhq@H0 zSbfd50AR1Y2V7QzG*odXC8HQx&qq8ZbbQRciH(Cwd*kPQk_T^^S%wsZX%J^*;Nq$R zr0B6zq#2_`_a+VZpv}6Jhvgz?y$|2i^9ikt-Qul;6D^f%2l8yvGc8kz3xdnyUXR%2 zQ85*aak~^1?0;EiTRj9d2H|#$DeBTwR}CqxMuQ9&ui3)H29H1=|4llEpL|lBa=HQ; zN7G)FlTWpaJJ!eab2?ki%D3F*63!|8fUunu ze%v-7bP_%%1 zqQ!+9(#qP`#R$dJv5blJyXE7f)A~d(n{BUWTG?aj> zjCJKf7m_sO+FYkD=13;%1|J!S0DW~$Be0+prHA6ua?~GA(I<}%0riLBxlc)hnkJ7H zqG*VsGa)y;cZ|UkRi)C7%_%1z)=$m@UU-Sd)UWmxyWz}SIb($U?I9Rsh zDkv-(3cng!VTni@l2K6x2~K;w6(PHmJQ{9bo)cJduHxgw zk?DWUB?;L39kpK?mXu^J6UhJ6HaJue#!*~uk)&xkw&(XM+;nXJ)GCGNnFM>{%5ZQ} zhCW38THrQqgODCXB`neAA~%=%yA7}{qe7#uEV+Lc7Irlqx{S~$BZVH^CjbOwB}Y0g zqI!i!kN8*+dSrUO?YOY=+@}s_$Z+Z(dJza(_R*_r#irzws%^1p36O4~iWoq@u3_qH zY9rHU_qBp1P(WLIZ;P}K>|6O*<&l1aQ#&#&wiVt(px`QpD%AYxIG4OVzM$xAqv~i- z+3?MQB-iLO68|2mI8z=R1aT?HB6E?h9Df2e=B6{lAxlTt3v28E2P+!F1`5|*kS6%1 z6HUz%N-P5(6~mMs&yXzXLH(y3KlIY8smE9WB6jKY74%1whFB5BG zt9>_7%ZZU$UqnO-Ne*5j6Wy?0|JAbp&4B2`sJg4M!3RhsH5<7t=Q6l0&1w(Kt=k(W zH0HRh{-<_Fh$pv*jR3sa%)>$h*jH#ofl zgI(Qw5pS`_&FGaJ;lBrNSX!~fPW{t9#O%N?udi1{+o-;9eg@@3iQ3>uo-ntz6vfwm zB_AwLvTD&Uhoy&F!V@k3U{h7hHVPlr&S}U7;LsE@eiE4}H}YNKOE05K#F06%!%%m~ zlJ0`|POuER~HWRLd)h{_f|uc z3i_k9gvUxuKc#<9z2QN+zWLY^MQgv<(KE+!9mI79uDMM!n<^xTBG{jcZ!0KTo3L5f zwKb+ho8`xyfmrp#2PM0jm?13f0lt6L7j702p$P3f8Uq2{-4u)ay1O>}BDQ?no|ZVm z*%T1II=)~*W*Fa*eU-84whAwReKfG%+O%d-R%2+qRwQ2Se~(Cxk-;ngf-t7!Hlq9( zCa|cbtChtCYBIF=FV@<-&=1qcYH+%L!gUuy)r0sAlykiWJo`i@Rlv_Lz49G+BbD8I z-*?nBgf?dQHS*oPoch$?d9Y%h?vV&qY2aZk)`p7MOmGO0z2xcee`uj9R94Pnzusyo zG-&V^1939Wm#3Kjruwu1%|%(qZVK3OYcbv^k}k|S0Hjc81Fs4vfKdbs5=< zU%Fs?Ghwq2iqeJ%9+3azVs6m1V^(Z~ko&2B=+qVz z@Y%C{WQS;(Wf=yHhC7PtB+I;|J08XyM?!$wE+{q3pz#a_eB)Db_BP0mvv4f2(115A%*IS@j}IDItWL@4Xr54WO#Ga`Tu6Lcn(}y7v8CV7`6+f5Tslx&zK6 zvR012VWMee&q}mRaq{+PTWYum;i`>Bdv08*F|_I7@cF>1Z@7pa>B+v6zck9xr;bHw zO=blmF{XF7Hs7awo{^=+iu&&$&O`B04?>aOos{#%ONkR5Ypv5z9wht#n{&PlXHgpD!Y|H}pEwbQra_vyE)$05!&YRyot*xux z;0|%a@<<(4&sRV#wMSaA6!UkElH)QkYE+sMUCMc)nbpX!Z;>d4c$wNwM+4-zr*?Dl z6eO|BqY4jI%g4#ujCfr^&6{CouPN%ri$yvQoaAIJ(9#Hgz)|ol$^b*BF*$y1i&mLm z>%{6y6=TYsyX|Jj*|a@bY`hBN=+OQmD$I2b>MGs7nmwB`0B6gOpYe2yNJ@epQLvPD z)T-gvKuVlw*=fBb2J%8PzGV_wyL#fh-g~?icYe1o#qr!oE_(44Hr#V_9h;8ZNSxdV zk~0oT)NgYA7h6dU2>-S)cK1voG~0dXx`~nDIXr#Ylb31*f);&=x#5%OtIwA!O&P#E zbVtDq+{NX864X~pOLTg2E~M~`Wi2-=_blxfcAq}_^X-i#S{=7bZ}Lkf{DdK!%5ijq zyuH#wKY03aXRA|jbX{6VReY2btqy_W@y{_HzbY0UU{O@!Cwy?vdMKsXSnvD z_Rf(I$T(CDGSBMi6QCrt$Y=Znq||r#Y=X7V;3)C%`w%f-fty!7XN>dZxREH>W3Wug zvBO4!zYTTL&>?_Aw=N0dP|+$q97#ta+Z{;im5ECGT`-v_dmdnWp zw2~?;nvI${i6qKG;zr#>N|{{3QI{X9i$Lp$xc;fQtBC_NHeCA%F&!&;?tNSTM=In0 zPK_FUxuw2HV@ZghCK}6`Im}ekBa0(=7o8H@msH?Tg4mGi8*y=d3$5H$Do{+BGtP5T zvK@90Bm6!&Q?r0S2z!TR#S@3cOWI=hrgd%60F2>Jye}@ht4xB_v!b-3&TCnn4w z+-YS;xI?l#(En(t4r1;k8=Jy78>75Q>%tQZ=P1Gqv*40PmMQ9`4njiTZb^i}4CD|epnTezp=fz&83RMfgZ)o6py!R8ZjoX*ayvVA8URu{5Wbn2 zAVcGwY+j=}Afzu17JHSd^thIWe%CY(Gg!0tZ~zzg>;=2(^#7CrFGTNr=I6FHv5GZf!s@dH9c(?vux?Vv8=wna^nH6B zkG@~cA&L~tny{3hea!=p*?*mkvEO6hBt?PNbR!Ty0WW)#kt_kI^#S50 z{>D#alDfLRQ~j47`8CZrOQ+x3I#qH}%QG8)jO5;^J5##u9^z+-}v_J3;9$D3KICjIbl-%1(RfowGdKRz% zRRo9JGf*0Pq^e?%Y(^1v*h~(C@7Ot;R&)<{i(dCGk(LjNaw?Hv2JoGye{F_12mo5q}|Z=f34aD0!=%Yuw)mRgyGtk zWql{VVH6A?!~ydcFDH2PIZS9miL$eNz{cJH<)G%5e6+hvI^JeK$#F<*Bx}kP!%q2&xFPHA} z_%_M57FIJ+CBz_?uiYQz1vU~WRnFn2+k`-@fnHz7>&~a1tM&ONCa|{&n0A!`x(vir z$^2uO`1q#%R6KbY=@@t?su9*CET&m&I(d;JO6C@E&qiE;Ywtj05K-cgp zd2-c9h#7~UHxm9{QloIJlL7*O%N-!>nUPH&qr>4vLH@43xvL?dR5b8tcd z{RW~%>g)gkH79W(PQK2VV`d0a@A?x81t5T&Z0?eDIDvwdyuoC*B*FAlLL^Q6B;dVm zGhf!;W-$3&i2zda8yEC!4XnxH_;K`VAZN$mRYYX&FYzzOgCTlb`af&eh{VhYBo;?)6in_Ah@oD2SEH zL&MWuS14fvVhh)q;kwZWl)aig7=~A-?%Lq}r+o+=U>3NxP+GLT#`VuelC58jC)M7X zU4Fz>^QKdaIrwfo+BxP!HPetkQ$!CdTD{i`Fal9vDN*W?NLfrRkePE7lCwMz{}Jd` z$EuBX3$(TpIWRBuO9AzH#=TskUp!6R{%UoVHv6 zl_@c&3Cxy+Z=}y7$#o60+itLR<<(uPzx{tvNnqx{Z21l9 zf^|8G$rg;Xwz1Q2CkA2Bb^7jB%WYOfA!Jl*Lk~#&mek9Esuum6TlLk=_XpD*LcL0H zUCm1~-}}BGMdJ9kOyTi}P?~I>Ut~k**6}Ab&&+TXB4fYG_B#>ro6$ML~Q8&e_vy8XrA=n~#=NbSGwSr~_CuWusimZJWmE=rKeJ!I=!EUcXDJ6;yMeV;_-xH`6*rI{o#88N_El5kO>EXMNrHy!Qq5ZW4i?{2 zs@E!Zk$lo=NomgZ?YQMtD zc`a8}Mq8p1#1%%Do?PjYOG@O!`Gvil{Q93zwnw^!)|4TqrCYk5!1F-)iXc{%n+;ZQ zXYtO21d9hE2ATEHKYD@JyQFfw51j`%xh!g-m`HdY?rK*~I!FT768<*KoYd^c(s;o_ zXK4aZ!xJQhC8uga;hDaV$7KNT?aI)oe-}duaqO+zsl8+DmvacI4RU9>J0pmvKyGmd zX^2Cw(N~HT{E0Yrnmf9>+!z&-@-vUInfKb{q4uno%9(^TBpq6SX-5M}%X#nTT)3;w z@LmW;QloG!S#w6yJr){VqibZpBBVG=cmcTmZACc0I$b;?ZlO5VVdb{v#syZkxm$iti6N|x$b-$Pjwzrf z>gj~@E*Y&ehz?KZsFjFxol>w+P*l3b15=0^!70TTh93hYxCkDS981p;z_%epnp=($ zVR{Vd8|#JnRTRsbdTT71U+2ugZ~*(X2toh=XeEDZk?=SBiO8Yokyz}q z%Pii?x=GR82lX-^VKl-ze4~67i4Y;aQk;mz87o#ee`A$Njb?hFprq3M|aRiTO+zDRZ3x9=pJMVA!ZaRE$339|F zbVBs*s^9%!SnzlS7q8;N{&k} z|Fx0tgdp~}f8+eL*}@s_Sq3oc{0+;svnoflQG(&ckw`yKpVgDnqxjFZF2{8!mV;G; zGQ!2={LGD~@D!XWWqMr=vu%W?o{z%c`7q(q8k}v&)NZOHJYf;KALk!kq3G#QC&4uq z;eHfJg;Y49kKxjScj%1WtJ1LcV;BUiy>M6A*)NCjz zvzbg(bksJ~lEf;|JAS7h+xS^wg`A)~b;`k}ACA`*wnA;x96s#7faxRHmm=nk>Y7el zC;;@t!78FqnJ*J4>~ZpO^^1sJ+a9WH5FW_HEayg09oZO(8CC+5$E0096Dg1!m?r$S;r003xYJT(9S diff --git a/dist/windows/nsis plugins/UAC.zip b/dist/windows/nsis plugins/UAC.zip deleted file mode 100644 index 66489aacdb9656cf1347c991b223fe37df07893e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 52034 zcmZ6xQ;;r9(52hfZrir;wr%gWZQHhO+qSXWwr$(Sd~;^v{1J1N5p_{FnU%3tJxg91 z6buyz2nY)3y1G-0n|d>>2pR}T7aa)b≀97EaD~jvn;R?#?CZHckg@h(B91TYhuK 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 diff --git a/dist/windows/nsis plugins/nsisFirewall.zip b/dist/windows/nsis plugins/nsisFirewall.zip deleted file mode 100644 index 3d34ac4e7fc9cfc19a5b4856819a5be4a9b138a0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 19047 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 GKK%zFLzB?} 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 18a541fc3f25d31679c6b187edc8ab2e2d4c6b32..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 241 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPFP2=EDU1=4UJAtCYq|9=Muhwa<9 zcXV{@-Mcp`DoR&Zck<-PnVFeDW#`YIZ+@d84P>#D1o;Is7)iQKI4pG&$j|X~aSY*z zPEK%OaC1};U^Du1kMW>08{4w!m$gqnXO^r|cdCw3mNPQgyH`|7RO;&lM}6Jg?2H%N z+IjqAV*WTij*&AuvbXxXiHXRH?yq-uU)XWMV!^r{Ym!*=egRukh@-@sg$@Eo a8W-m~#P$l;!@elF{r5}E+Q+*7Uq diff --git a/src/gui/lineedit/resources/lineeditimages/search.png b/src/gui/lineedit/resources/lineeditimages/search.png deleted file mode 100644 index fb8df709ea51e7fd7745530b154ba04763be9014..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 292 zcmV+<0o(qGP)WG{Jlhd`Z`32oX0X^tdXb0Hc9UMf$3Mw^XvwHSjGZx(O?G4 qNb!jfJ2P3v3Oz*aAC|F7oAem6SqDjo4&sRb0000 -** -** 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 f7918e84ce2f365bce7eab1f632432240dfe871a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 322 zcmV-I0lof5Nk%w1VGRH$0E7ns98rKFp&{|{@9*#I`T6+l?CJCK@&Et-_xJYo_4MWC z;^^q*`}_L-{{GzD*W%*d;NaW+{rukE+4}nV{QUdk;@#)x<>le^_4EDx{o~`` z|NsC0|NsC0|NsC0EC2ui01W^q000HYARvw;>6{YuC`&O2BC4{kV8rR#zD6SEG+qKB zn(b^uf=E~EAqWgn5cy<8L`Nqy(hxP1*2Y03ta1-y0Cg)ym)`KWs6yXhESKiIV#hZ# zbA5R)0U1O9f;9mFPa<~#ii-pjB6y1eivg1qB6*pT6BHU=grK5b06ZC*p&DW$Hinz7 zZU6?dt!-&?yl^KDKu0ma5XD(ID#Z{&KQqcyMJo!^1l83`3ZI!!QVZIWR{%#5A|$g^sGwiL@81tn9Ty{NG20a(zgj4T6b=J*;2=~b(27N7dC;BioPW9aU8m>ve*Jy1_H&pXA6_bz z6rpLU8qkVG1l?(#qIG3^90ukUH5D0((fd6>RclXMlHxU2;002ovPDHLkV1nBL#wq{+ diff --git a/src/icons/flags/ae.png b/src/icons/flags/ae.png deleted file mode 100755 index 3aaf20d841344b394a5e395b4808402587f8ecfe..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 330 zcmV-Q0k!^#P)o>%=m@E0B|VpGys4w6aYhlI`ptr22N`4eM(`u>E??OP1(cV zOSELN$ku?qCWJhB2iCyw|NoPx41fOu(Sy&w|Ni~^`#(?}P!Wjy_4n7Wf4_hXSsq!S z4J=@@|3g#*m92DM`5y;hWMq7(`j7?aR7Rj`uoD=5|M`y_fIRu{AJ|EMKxPxxz{vRL z&mXXp{(_AE|N9qy4UAw*z)k`h|LYgXRlk1WaSxCLItiqK8D#u#hTovDv9`AU_3PK~ z-@l~S3s;H=3ym%3$f$8@j21!Yfo|;im(AnYD;?>+=eAPu(o6cbjGN$GO^Oah>0=AP9VYLCA@oP z=KTK=>HLPhy}kK-j$4v`Utad*q@?^XL;QZnu?aVB@q@qeJvXg)A*7vPB9b0SL5XRnnYb|YOS}MDM z{_Ln)*4y{>@q=BHCz(njup}unWs8(lWE~#r-5Z^r_Je~SG)Z&HU=tP?W3k9g>xRiF zsjsf&{ywG{R%R8E(WjikWDNRj-s)2O`D1BwyWhK?XWxd!!bW5$#Uz9gRkkBS z63HG>uU^OFjdISuoPkUg&B$;!gb{#lMFh!;sIONtzv`H=93}FO7^3nRb zNJ*d|4$?pl_LB5)6FU#qoz9+EV8H)=0UbynfdmqG0-Wyx0VJ@7zxzdLQ(^xJ4FCWD M07*qoM6N<$g1IimQ2+n{ diff --git a/src/icons/flags/ag.png b/src/icons/flags/ag.png deleted file mode 100755 index da53be824249704cd7b076ae00f07ace45229b89..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 455 zcmV;&0XY7NP)lI;c=9IIB*A&_zV)W*1%RP|(Q?mO_Uv3Q8@4 zgAnjf=#X|1m7)}>b`hH7clW-pL+s|_Gdyr`$6*ZrNA@1rn4SFvxVyV&u;PBZazWu* zY3s)hyIqN-G)x{}T`imjs)*LN?>)0{do<1UPgXlbH=aGgGn2gaFm-z=$j2ii3CI)B z@R%@@c{ty;ZR}JkS6QiXd^9bs^utr4rcyddmVkl-`$`9|c89-C%=BaE+>xbcn>Y2v zWiE@!ORdk%>8#(s^ZIU~T=K!dXocsM!k$i1&yOa*FHRL7I#TG`S$@*&?ug_&GFs#;p;bIkDcY^ z)Za*=(_nHScOaxta?%p{?oDrPZP4zmcedu|jdUu+a1&4v;Ih0@&B%~K+Fo3&&&@@i xZ$EF9N1GuJ6Wm+|AnO1L5a4?rMEuJI;1AFIBHo2?(6|5q002ovPDHLkV1l*y*G&Kb diff --git a/src/icons/flags/ai.png b/src/icons/flags/ai.png deleted file mode 100755 index 9bde3ce70994e4011c77a51823ebaad6e1000659..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 516 zcmV+f0{i`mP)D+sWGXPQX!dKB1K#zD7Xj(hhn!5I=G30gCNDJbWrHv;GhVCMVHco zAfg2qMZ_WqRYXb!QDgB@vZU#YdH3D>`{NJ_!r|}@XZYX*m#(b6NOGNAxMJ6fIa~;v z=Nr*{{QlIdGBSa6AdAeS@1PcNX2S+M3&&sD(o|dwQ@cEVV%Gm!3NO!}>o`#_!X!?> zs;v6(;(fE+TPtj&Gwn8#M4g}g_BE4mCVM?so7!VkqI@OF7f9m7=EDF;&7DH?Mt!m| zy3JoUHG(-hv6r~@UG!O<$L;B3Ls^0#?3tl!tDArgA9qI@6V;`px@``&!vhcMXQR>T zYJbEMoJgVj6y3Y|;V9}nA_3sd^f(sZ{e1qtcSt$Md~fB$n_Btwk^Wo9jun6zn{z*| zOX&=&0BL~9CkwZltzGL`NQ6X*#gh_imU8`Mt!M%g?OOJ&oo82XhR7VLxWSs$lXy}` z!X%=)_4)UoRN@p{A6p^RCyI8N|XYQXVD z@BO*8lAU&cbI@e%@ie3<&C=!2_eMpORIaaw$5+x#S~dG|Jh!>6hkxE*WwSC%Qx82w zg{Q0J*9fF1Yh7!twYGJ(Kc9BJl-8oPl7KOx+>uAOcLl)1G}%Y3-#7G7y8 z8InP7fV^bh+T`|P=ii-0E$6nJ+k;cx)1S-9tz?*G_z{c=8A@52VfOsoFt~0HbLRLO_%dS&jez002ovPDHLkV1koR(MJFP diff --git a/src/icons/flags/am.png b/src/icons/flags/am.png deleted file mode 100755 index 763478ffecdbcad7b4d74360e3fe0de196e1f9df..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 331 zcmV-R0kr;!P)wR7x62^?`f-b9K!4-4aet!J* zyL$o5gmFdZOvU9XO_(tqqoaF|3}JH(5MXOWJ388;7D0+-5byMg_PhfQ@PK(jf+vD0 d2^c1Dg?||4hs{bNg>wJ^002ovPDHLkV1k+Pi{k(Q diff --git a/src/icons/flags/an.png b/src/icons/flags/an.png deleted file mode 100755 index 4e2a57c3983bd8c02e3a28595855d219600541af..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 409 zcmV;K0cQS*P)`~Cm{0rvR)b#yNN{{MY_%K-rY^z`}q`uzL*{vRI=!NG=O z0%`*q2e$to5Vg0P{r&T=q5gDj&8gpi{@2$V{rdIy*ROv-1T>L>;SbPBfBydc3v}GC z-+zHNWM=O3@l$nnlKl7g-?kl3^70M<%>wEH8~2xi;RoZ}w{Q9R`Jt|d0BdWgkAa@K zZ~^WCpr`NLxx?}g6!Hux8i48`s*yqo5-LE4fHc5WLnBXCmhty*pdQ`w49-9QAYu#v#%WHz<6S*U00000NkvXXu0mjf D>~P26 diff --git a/src/icons/flags/ao.png b/src/icons/flags/ao.png deleted file mode 100644 index 33827bb7aab880c71bdcccf176a160e589702052..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 388 zcmV-~0ek+5P)3!BDJcOiV<_aJ2q`!ojRXbO(nA0S z#-LK<1%LfC?g zPt>_vGP|xt)3Dc?8bZx7fm7t^Y2A4&o2w(ls`~)A*{~|ADn&hfZN=9)-F|~owv4-z zZ@J%y-u4ET42RjAM3@Etsrm6e>X}QEDJ@2`)e*QL5FhM?^yhcc76_OD2Tu+LN>Y|Gsui zB>N1HKY38uBFuzJC38_Q6*J5*6?3s%Wc*!uaxEu_I$%h^c4*FY7L8zQ>$8ss<5W2& zKaa&=TAQGSg{6&!g{z$*GvkY^>l>F>$HXLxF@hUW#0~W9ko{Zh@%kRCWlpFuMvvb0 z!7HrAg-7l_^uJ-qomCe3$E~W59=PEe!2AgOuipkq_MEDwXm?Tv9QUNb9wpx;<$hzi~XIn zHfhtO8QK)VK-!_voM5>9`tZlhRLsRxOqGTdnF$0^q)135%lrlQ0dVIaS-iFY0000< KMNUMnLSTX@A*r|k diff --git a/src/icons/flags/as.png b/src/icons/flags/as.png deleted file mode 100755 index c0729de336ce2dd1ba1062c34179eacb5620e574..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 538 zcmV+#0_FXQP)6mTi3vUz>9TDpp!sE zib81-iG*voi%MIRR%+Sevg|yszv%75qKJw`{3WH0V;BR#0v7*RVE8U>_Q3c6OQmRN z2n3KNV_*!7A+4bld|ldynaEjkAjA54uO;(%VvKVRBFxW|*3b%45tKNL=O>-lTe0fb z)P`LrL}Pk3`$o*nF68nY09n!+N+Gh@4u7g4QE(HGKSrXN9d?%9LSj~>3C`_y*n za&yNyuB8oa={z5cf}F=xVs|F!?q_vP^vB}F@Yi>*cugjB7Xy^miax(u9_`vJ*x-w| zwRB$jvmsL^m;za9IrOL&7H$w)Y)3uFje1|p6p$I+BABLC;hPNn0Mv6;%>l=<9uX*7#QF} zl87meDUL}9NJ()_B+7m6%l2TZ+Aa8vJA>2RPrj`(paNLH0vfP@1uS3z4OskUfk_uP c?g2Z1Uym61d`4<282|tP07*qoM6N<$f`%0UGynhq diff --git a/src/icons/flags/at.png b/src/icons/flags/at.png deleted file mode 100755 index 700a656671b796a9077d375cadf01d4f7ca58f40..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 290 zcmV+-0p0$IP))H65#(tg2R-mDwzzW4YAp8~uP% z?nEd;?sC5x_gd@AFywAmPN!4f_kbjX&>w28O(&Dd<#K5&ja|RyF(9eCHa(nw15#!d zTP(_IrSqAajpd=ZJA;Ta44<1#mxsgiey`(^F_tltQJZnYgZUij5}wSNPGyD%ZkQD_ o+-d6G5+@>|eBVFvpC31V0DRV3O?V3gg#Z8m07*qoM6N<$f|jm%*#H0l diff --git a/src/icons/flags/au.png b/src/icons/flags/au.png deleted file mode 100755 index 27c4d0a7bfe55d826289a4afe717749ca9f7188d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 579 zcmV-J0=)f+P)AxbM3QNsk2K(|Fk&9-zK+urZ}{&p2Umyh&uU*X~Ftv?U% zZ6CZ}fNBwd0?@$=1Br((0oDPqG!z+o6zwB+1l*?Sx4E1#ymuf1G84nbxgb`Mpjp6<7*ukIDs zQ*X~1Eb-=`-XAELTaFy`D)xq}!~0Z3&K~m_Wa((H8vyD3Qft1!F_T54hO$-N)KY1= zqPKAMdGeRn(=wU(wwA9HHq@p@UtbsFc}S*g*Q3?3X~JdPaX2yycoiSQO1EYf+^=*FrjI5^g*&zu5rcy zs15*Q%7hT1J#Fny^U3gT4HHZ#CKMBCZ4 RvYr3{002ovPDHLkV1kQl0uulL diff --git a/src/icons/flags/aw.png b/src/icons/flags/aw.png deleted file mode 100755 index 7b7d01c10fca7e3b00c0c0c14c162a59f92d8f3e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 393 zcmV;40e1e0P)9=C5Jl&f!=oVt1OiYEmS3o-eg^S^;3o)4aSaZOD7XeJic}zKFklLvfWi?(6A0p^ zNpH{WSsQUL0nE;t$xLP?Gu(dm@wC$xZ5#zibd-vaLd@9-DY~LA~tzW>#57Wr50BB&fJ?p~&)&xbb`G^YP=xV)3;j>;<7M@%S zXF1EW(gY$p?Odor({wp;75U$SRU{UU&X8YYxV~q73#XmtpZr@^IES|N^Yhzw@%hn{ z)t&F_^GP&u7F8t7okCc!b#3$Y`JA~_2>czhg*p9+-@DNcwny#3q|d?3R>Vk@ z*iIgA0M0pcf&qdsBo5~AWXcY8R|_*Yb9GlZfN`R4i}m@(QFajw;dr$dD+3#fF@=#E zg^??pmAW~-_31;-D?72apLRwe5?zUw{pCKC5)~9mOi{W-R29ORDt|%dH%;$C-@C>= zC4sL`;`+djrr^r0GOI#s*X-7-hr=?9JhQp+{KoS3Xew$?F2Czp7Y(j_y``!oT3AVx z#YpVz!tnb?g^*+_&Pi0JlbYd$g9R)gMJEZUGR6m@GC!L|QT0z?fiP%J z%?;WkVDF2WsI#bAs1Z;SmfzxEi!r0+pHCmo--q7C;)|O=1r&e*1{hF4f&PDS9ZW4B S3=~`d00000-4G$d2CbI) z?>*;SX?XMoD*^xj12jw!AVGr!jW9?A(RV#g`CxYnzy(*SiiT`f(Wa3y?R2H;`TTW{ z$pmZt*RzzNs>|(sXe5FNw$yO=VOW0Jn$3PaeYRRI&)&Xk16!~SM9@GVfJ7-v zG}B#ud-AvV diff --git a/src/icons/flags/ba.png b/src/icons/flags/ba.png deleted file mode 100755 index 688c1af9a800cbfb6ee8e93c4160bcb41c69d483..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 469 zcmV;`0V@89P)b0U(G71Q9?G z3%1n(0?`eiGT8g0$qScmJe_$sux47YEMpez3YOp!6+UukwNv-T-gEzH-8Om*)#rRIM0*d z3X{w%k(vWi5?$tDl(}9s+81lh!Qs7QQzOZ&*kCLSQ3Aq~j6s)sn5W$1*{k;XYIA7& z{dRn2;sU0z00000 LNkvXXu0mjf-#^sR diff --git a/src/icons/flags/bb.png b/src/icons/flags/bb.png deleted file mode 100755 index 61557ba509fbfecefc72b5ab8bb281504a1b00bb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 402 zcmV;D0d4+?P)5|WUhI0IFUq@7Xu=#Ygwm#in|Qio2Y03h)3Z*VW70Qh5Qk)@V%;+8Dy{we^K`l1d7w33vz$ wz<>e#`0%z)Q5zIdJE(!(2m8PuU;`9@zhs-YHXeC4}y@57Cuu%(nBHCynlFawb zth4)ksFlMoEW`J=yN$3He#%0S5SUx)9{oBXv>ev&^%K}Dnwrv7jnt}vY8s&!^aic0 z9Lu*SO*q{yv45`%?})_X1Wr3RZ;Pk^=*)H;+VU8#TnX=#I2>wIB$7d}^dUztGV0>2 z5E!6vLet}F)Z|WVl}u0oneEP)AQ08qGehzJ4+P6vP2sop;833*oCiP^ zbwzzqHx$2K0o&~ssH&=3pCy+G9_?d%bfJE5OKrFG{rI>7pm)31%*@OxL3V3)s-L1G zS{k>vb3;{UrZX*dXLoeFTiwwe9hv~78OTge(v;i#KfnaoDd`Uozd)&Do`k(`u5|qoM^r>8) z4gLA!x#14$oAvH}CrcJhnoLHL8IeIV6f{@otIhqU15hQ4Dyc*>95h*siYU?%6*N_X z(J>$gX;4(CiH$@=V;~3yf&-(1MGizq$0JtPoV|upQYgs`iAqu-kr^^2Eid%6LH~Tf z*`@qKkVRG;A35?UL@3);-U8jgKw+^c5=w|58wm*`OUNACKsx}QG=AGZ5r8i|&}D{g S&`PHO0000{x2$u;qPAv_a7MjfiWP65vYNemlvYq|G&QsuU|9FoB#jSYlgpn{{Q*I z@aNCJ@8AFb{taXU$uFBWu|Spn{|}-rUtyRv^Z(m-48MMX6oJvduV4Rzxs0;1KpU74 zs)0aP_kUv(gSa?E#s6QwK@2zoYGzbet2S^-@USGMw0#y3r#}9}-|E5j*S6Rt`8ny74h5!I} W>r`zOABU0v0000mKokGO z5-GMuV=plsL#)D&d#>9w?k{H)j$NNQ?#~nIrG$zdE&T;w2rs7*ajqi-ZK z9GaXIkwP)2EDFZs^54DX_)KP|KR5tCY{U#8=-#ndNROqil%*jeoG%%L-y*Up>df5f zw`=dZ{1Gt(P1x$()S_9m%V{c7-zrN|Q*GU`_MTp;HdbpZl}62H`YcVv1cvRGlUOtf zmH(6)+}Pte^y9^&VrH?lo>_f-KVn9;UFFMpVoS4z8#c|_(v&S_J3XCG2B*9tyU$O<-2R7=}-Xl+$0Y*{v!ONh2|*}(7xbLb=h?^Umn z%p`Y}J3jSBtAGO_fB^y&zyJdTQ~?KYbo%Au&W*o)XeM-fj4tv30000X~s5Cm)ATSpL(Ios0}ous zAb@_2{XbxG;r_)v;MnmwP5{1*q4U&nRHEdXm&@D91oGkg$4Cuo6fhK6O^yscpVPS-Tihu_c;o2Ydv2qG%p_C z-*`A50sVC`GstCn zhV%96`VZYZLSLL|s8m8KgAde2TV@M z&9#h}-|0`BS%B#J;)0?HGFa(@giHyaGlt>dYB4bvf6H`wz znK&KCC(k~15dk6rI^vAknT@vT?PWfFuH?dPQBy_d;4C`^2c6kOz2lzQyZTMURby3G pB_MbXP&cG>(+WWUH5MQZ`~xmxgGdT%p&>aSAP9+Fx^xuk)-gI2f>A*%HnY3wjsg1*3g{FlbP764 z2+bBHMcc||wQTO4y6yKo@Apa8$L((d9tiLs2@r=!PyvDj2`ZEz;miy`)O`kRk!>(C zBb>r1RRIOnOlWGRe?Po%W(L5_FvRFLJ5L9DKYSP-9rYA}6Pg&kON{SqymY0drNaC? zhRh6rnQhj-C*Q1OW?q{KqmU{zA3t)oRatcaip659)w(q|cWP|x+{8rG>-{V*s`ts8 zPmX0QZf4q$)`D|vuB|u#`TWC1qppWUOP9~bV)5|mjqHih@Ohbja5}$eLoNt9ySuLY z5$^b-FQ01*%b|*j#LHKv?!H%2$mOo38&iT(m!_w0&(7v@IoGKmnR!5|gMGxr;QJj)PtCMh!?pWO z@m^I_qii-?sZ?Bh9jWnqFs1g5YS17qz88TKON*HdLT)v6Yg->L?^ml;xAPWMkWddQ qNKg^P;T1dph+qVo0thO;Zr~qWrac}t6K9720000j`{Zy)1Ve+Dxv1~x@g)!lSK z_tHm4Tq80j5MV`$;6E4u@Zl4Hrb~>Z4(ug9+6S?6t;#iT-+vqcQ1s^y*hng2Z@Xfp ziX|&9k52){-7DXJG4o_a)VOxTMzCtutQE87;o;r+8OH5v+&o>)ODoikS~g7o5;kn+ z;oi-!cNhp7w`zsBWy0=53TDHGi4IYM5uso!gspOQ*mrLxVWYwl#uwqGdC~8LDHD1l zrL)UMt{xoM&nw28Gv4y@eV!RAVmLEd?qn;Lil5{1?Ti6I(P^AiF>*996>Zo~>)5qn n2n)Uf0rU?xIj_InirDiXts{K5|IMJP00000NkvXXu0mjf`#F+= diff --git a/src/icons/flags/br.png b/src/icons/flags/br.png deleted file mode 100755 index a011b1dd11974bc099c3fb5ce396531d34891056..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 477 zcmV<30V4j1P)rlYcUL2g zdp4z|UL77Do3?_`2bw>gUOe>Rt6Z;Us3H_ZBrwpZNqTF4S{mT=htiQs;pWhvN~u26 zz4FY3p~Gup^;kVp!~{(wAbNAn+xsMOameN8gQsu!)hAiTCFf6geq+%+y2m%C=8Js| zq(~4kJC~e%Mn`myTk>y(KJ&>(C&PTri_2fP9(LV}uiguCNI;OBTSyMv4^y9G<>=_z z#kBU*WznmT8oRfjdpsLAjAg&nve~6s)DaLtr>Ka^_{+?tp7h0)9WH$?;@uxNj|Z_p z6)I^25D+0`Vc9CGhzYr(JSpX^jZCm>57({EQ%$K#6H^1wg`I7SokrWH6`lMA@;i00000NkvXXu0mjfJDA|$ diff --git a/src/icons/flags/bs.png b/src/icons/flags/bs.png deleted file mode 100755 index 1030207a11d5fbd3e94a2da41b5ddc3d248c6c47..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 391 zcmV;20eJq2P)QqOh|5{AP8fcMiWj*q>wW3nXznyo~( z0NS#dF!?;2bpSB`b~T^3$)w%A#}!*bgMGT3a%hjY?!dbp06T5*Ll+nCUM^oeZE+=v z8COyp;J`=Mt1lgZ)|w+h5)2SlH|{8ew_0ARb^Ox+f3VV zlZEwzBo%9SsIv*j2bJnq|9u#k7KQ*wR+V=5&feCmXBAc2roBm6iL^ooKoa-&d3yR` z{GfhS*>wJ9EL+aQY<=x!9RMEPKX~(+dwaUQ)hM)SE8)gQOPbyC8@23kczF5v5f%&F l-1IuvUaS6dymr66{Rdtzc<9KmFn9m}002ovPDHLkV1n>nuGjzo diff --git a/src/icons/flags/bt.png b/src/icons/flags/bt.png deleted file mode 100755 index dd3bb1c2c1806d9d1272db71ca73e1b3b989e81f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 470 zcmV;{0V)28P)aJlLDC45K@0{V z76VBQauR8J*SlWN{rWuL=ld~;SiJHc-^JuD!EpX^+`$M9yu>R!;@}ND;13AF2*+;# z!ja=yWH2=r6)nWiDlC(VXnK`)o~{KCfE0hAjAto9R`Z1KTdFF>YFzfNjk>Y3`lWX4 zu-7R8p?|k$g{bY1gTW}KT=!VCm$%k_7JH(mk|#MCAko9F(Ob8HK4z-I-P5q*hm`>D2kFP|iKNq-G+SLvTYfxv7ZMthe{N zPpbWmL9SAN(ws{h_VT6%Q8TH?$)R*do>YsI*$eC8Zhy1g%-gBgZQZ-L@Zs5bZoYr^ zjz$SHWiu!}Ld`UNvOhdM{cU^k;gw>#Iehb2?CR4>`}Ub5_s^*vWl5faP|l*#^saYs zeVM7Oqw}q=FY1k099W=CvcGYQ3IG5A M07*qoM6N<$f(@kOE&u=k diff --git a/src/icons/flags/bv.png b/src/icons/flags/bv.png deleted file mode 100755 index 74264c5866b6768e421e265c20b7fb4920a50f61..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 397 zcmV;80doF{P)uvT^z*GMerxw97J#v9TYe53l#hS7YA42(XS8+Dni|?6{_e^ z0>#DTCf9r3Yen=DPLjhp$+?MsQKOn;p4@!+yjt!V6P1buSuW@orovWFjs=sYFK~w>AL=Yy2 zQyrvGi^l;I?}twA5wU0VaVY zLzsz+N52srlv1FOf+a|xKw;Md!)xOD90mm2(F6gsrJ#Q`kD5)n0BDUQv+`R%GizUaCjlVV>-A(Z`TzHQ8WD@dVmNs^y1K;k z)+OwF(wTB~yM#Z#aeIF}fRab22i;0EgF-2K(}ZR;N0SAB3fz5QyB8|)6>a{Nu|VJe YpJ#P_VLV+}EdT%j07*qoM6N<$g6?{Txc~qF diff --git a/src/icons/flags/by.png b/src/icons/flags/by.png deleted file mode 100755 index e9f9c3486610ab457ef1757f6f90bfb68629f9b1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 382 zcmV-^0fGLBP)#8G13&vC67iBh+ATwD=1;bN{Oy@Iu?l0XmFlmINZ6VO~k?K+&ToHwFDxY zB$&@JnfMZgp5uUWD?-L?Xf`2t_xn|Vs(DrHKP+7$w*g7Qvl&lsw;$MYS?<^)d?~g^ zC;a?W49-pmq^(j$YooN$%1Yl0qezOD4jc4xBR4!g*z2p!{asd9SzQaSE0pUb0AAHUYMASJa)hawc_LRr`>vcf9+m$q2NHCgMb$s cz2000;m7yt8V#C<-A(5OYyfeDOl3Rjic<$>xvG8(%;9 z?`bnBU%j>+ViKZ7aj+CIHCJ^}S{FMtKT{~z^Ih?sPIFw5ks1BAAOqHk} z)H=JhV?R2{Plmyl@;uP+6)t^UvB zN_Xw!%^(`Y#8R+~98sbYgt4TrU){R@aHCS}i*Q8p?)mE8AyG^$RZW15{rzNeu07`> zMDZ|_ZN6QuR!6G*J1ErLtCf+Oo4Sk~wv#Rx7#Ii$Oke~8B`5)4U;qIB0Vs4CFi%h& QvH$=807*qoM6N<$f;0KbM*si- diff --git a/src/icons/flags/ca.png b/src/icons/flags/ca.png deleted file mode 100755 index c4df905ce58f35b946cc4c8a89d8f5191bf3e556..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 470 zcmV;{0V)28P)LAPN3UN6jB0@PNl;lt?!3-iOh^4cA!J z<-^CTZ^s+^`_?A7)=A1hK#Zo@R85p59^B=@0jrT~qFF)}Mv zEk%-}ot@v)by=-cn`W}HHk*;u7@4GqWFT16P}Nehl*|luy|%a4e*WZo^<-ADp*ANy{NUayp5f5q0i$>%IU$bcnvld&(YbB-i{-eld8 z26*qCbJe~3o$-cgHozSM24vtTaAUEEF_HuzA|wH*>T-L#3mE?S0~WC|-5!2$iU0rr M07*qoM6N<$f&iq}Q~&?~ diff --git a/src/icons/flags/cc.png b/src/icons/flags/cc.png deleted file mode 100755 index bf5dcf17641507a614924c1265027be299feccdb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 493 zcmVo64MEb-(ijCbH1#nWad($U(+l|uv*M5(% z#68^HEZoA!diSr4HXr>ef8I%+->MaW>EZ11lj4b?*4;D9v(Ltg<&H_TLN!c7SIpM_ zwm&tJk;)Jq5*X~3^}={_vM1|ywV0Py7WYqYKAfzJ>+H}!5&76i#Pw8~ArxpOPgnbA zs;k|KU41tkIe9Qu|DDD4FX@f(#$?()kkZ0>&s5sJG?JSir$C|pVXOFdy}BdeY8uv? z)7#(DKJ@W=@#ryMSSv}$>+NLVM=#4H1m4w+tlR8(Cq!K{)jP+xJEA|E%q^wjDrzs! zZY=)E0||nLOPGc39{9fL+)`z@yjPppl&-3)n5ygfH-jDy6cEf!P1RN1+OB1E=KYbq zP%#lVbv-xGezjGyaG-#oVb%UYb+d3Y)o=|vq@MPvxldH~u8rku-w!V~49GDB0sdApZs!ig6um14(*+5G*1E;5X4~;e>BFR z6P$iNJe1p(BoG48?%EM9J=(Q7`gSxR)nc7E+kMEy)_VumUZ*k?7uCYoFXSW^*(tKg z_x;tm%4aEm)Z_10OK(@|KW~T~kb~=glV4_o6nE4BKT<3gy>7{L`I9~Vp)=lWzx*{T zlF~N$6;ByR`@+831IWIXS2ps&kK?Kjp8s*TM-%cfd0}HprwabF-kRmw)6jOfy*TEK zPLiOyr@)A@4P{U{6bPsKxYb^0ot=q}75X!n#n5R}8jKG2R~X4iLuu3+R0cTR$IbSW zrE@d2Qg;DX9Ec8OG)s9q)vSd~s{hhw%jd5?OesC>xeG8Zd=s#r@AT>)%6}>ZRB=XnfVhR S(T-;T0000CzzEeXNtnk_-l zHHA>1pb>4xU4!rYKJOC}LBGM=UPZaUu`h-^^#gvDrTzUGfPGW1YaJTjR)!Td@TmqIKvh8!1VP8l zWUl`J0x%p7>&5qrOV^eTj}9p^$wo5cftlRbzOF?wjT9rJ)9m#6y}G~IpS?J{H`=qb zV0gOI?wiYO_2a71oNj4OpKec&Hbyl9E;m|aIL*?HCUdzP&FMz-+5^EVZ~}F20rzI& zw|mMnov@V2TxKtCI@6Pu@)XaEapf`UJ0~&M38^bNK*=S?1xLiKu1g_>M1TO#-9Xvi wMx%jN3(Y1@p9P3aa0UtF7m&yViA?T|pu9S4%>V!Z07*qoM6N<$g2Q9Zr2qf` diff --git a/src/icons/flags/cg.png b/src/icons/flags/cg.png deleted file mode 100755 index a6e0490fc80c95e74db961ce2d3f08f1b8792d00..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 379 zcmV->0fhdEP)3l-yn(%yO~gX2(xnnfYb(S;#KIGJ1R;%uf?8PX1@s1b0;4AL z*ZF3%D)=!xcA4LMJNr!rPXG+RN6S}E&tEHTWmFxfV$(Coy)jrD1gUB&CJZ9N8E|ib z^9q@zUzkW0P{tZ;Y@E2%VW#zwr|Na8OpT9tZ zfB*jd>({TJKoA}Mo`C^u3nSxyFn}5W0}%IuZTay7EC7bcD!zUNs$c|0RXP4$B(Ben*sm;002ovPDHLkV1lWsefR(X diff --git a/src/icons/flags/ci.png b/src/icons/flags/ci.png deleted file mode 100755 index 2ee79a3646f7f622a64ba6ff0ba76d184ba1aa3c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 304 zcmV-00nh%4P)t2 z)BFHy0ECj&%{xdEn~=uOV+08aM+|(x^&McTS)P)uhJHHZ-V_COQbS#88NuBdrQ7Odt?oiPTw*CQUJ!8A_rF zj)H+L-B79A652I$cK83j_x&wgrRaG+;CUV|czNmCv-Rlq(zo%-q7y&H-qWr;bT~RY z_go|+QWMd?9rX8KpTBv$+8o)+J0C0C+M_7B@Nsi-xwvinPSVqi^dw0?eQV53l_tZb z*3|l1T>jzXII$~L!`7jy&Tgb#qLDDr<|Z!;=JFlsW|3O>qV1^f-tT&P(9-JLI~xx4 zRnwituJDd?~aH_D59hX z{hv^s00AC3c>~~^`KvG+8o4JTPDDZ56E%|dtIRxUAW3iDNPp_`{jN-8=0zkB>HGJ~ e+HactPd@>+wnO$ad?H=|0000c-xCvyAZnA+tU*LviiI|UWfoxNPExrC8(SeZwt`3y>|%Z-n&i&h8H)tT zGv;tOFr4p9;Oc>IMIpk>*onDw3fRAbl8IiQ9bO#ocOC~>a-&{A01qJ)MG<546-_3S zh;eyxfOCGd_x3S=AI)J|uYJeNB5?aO$nJN~BT?6kZ$XT2EDEPFIdjk-^#4y$jMgBY#f4;g5;z1MR|h`NYN@+6*;OC@8gHSBgvgCOE5 zp<02eG^(zuP#P4fF2XOgK2t$6IkOlc9D-?}g@}l0Y*uRALL0 zUWSio(h*+!=_6axP$|VEO@fYa#F!o)H3A7FfR0bFw6nRxqL7naV#-EB0*R^6^qtNs tbgbe2@eTq60A~+4_&YOD@8isaz5ukSU@QpdA;kay002ovPDHLkV1nElkh}l@ diff --git a/src/icons/flags/cn.png b/src/icons/flags/cn.png deleted file mode 100755 index 9f1b3109088219c58ed80138450c857a18f28848..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 349 zcmV-j0iyniP)uoQ1TUaR@EGP0mRfin3z3+@#!^ANfS$lYMGzAcvopJE@xK=y z!WP4_GyAdIc>w|lpbG%lKF0eU&@=@AP)k<<>|UG?PB6QS{$6Yz`Sz>NCW0xYBtuHF z=;!IQ3ScnK-p=b_?4M^I3vL{G|A6xwCYi>hg;|o-Xrux%zsi{T&#n6}I|EOdzcGzr zmRyBdU8H~tKz#YfsgT+_Qnkl0RN{YtT#X^h(U%~J<)KdS%@i5cL0@upnAh$l3jU< vb$oOFkl-Hf=`Nu2*m`7JsP*hZZ+r00000NkvXXu0mjfRA`g) diff --git a/src/icons/flags/co.png b/src/icons/flags/co.png deleted file mode 100755 index a2fb4769378e0ab2487d6f3f84fcce79c030fd40..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 330 zcmV-Q0k!^#P)=;&tG(@s&DRv^O0&9_gVKlu86yedbod?lmE znWK9>ynFuU#k-vYHg?B7F{9&JN1Z57+M9uHBjX*j|;6j-8b*cO7oP_8APoKp@~h c_)h}A0kD8;!FaSuAOHXW07*qoM6N<$g0%^ig#Z8m diff --git a/src/icons/flags/cr.png b/src/icons/flags/cr.png deleted file mode 100755 index 413797bfe27985c3c3591a73d5b76cfb36ca7294..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 349 zcmV-j0iyniP)^Velof(UtM8#nk z7}#BgordiR0!v7Uf(6ts#!3TFhmFz2<)Hx^vPG99sc6!ql47aEDxZ!o+QJ?JumKo= zZNPug`_|g)eBNO;!``01J}twtR-`Q10%_7x+t`fToAvo04GMwd1XE^fr?WJZ4Xm8WWX#YST z?|sl-waRT0q-2YOt*xi?v-Y)Ebi<*g<%?|F`u`=Mwf6k-(twl6)e%diiYkg!mMF4Z v5-G_=*}k5R8*sd8ab4%y{uB%pAYkwfGWUCT^E*_B00000NkvXXu0mjfqzIo4 diff --git a/src/icons/flags/cs.png b/src/icons/flags/cs.png deleted file mode 100755 index 23f716dc40c511f64b6940577cd529650a75e519..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 376 zcmV-;0f+vHP)@!3#=_Nd?@I;lj>5z;5ftIs-b>n`)`PIJb2D z(*xyW8J*RJkmdUBXyXM?kN`miP@5^-7E1nc2MlJtsGK-n%H1QI!67^cJB%6jEsU&;IWUhU$Hi2$go=Xt*GJN#=5=D`9RW<#?fBFTR WiT;J39PC8^0000rc z(5_fwzx`(BH|G0h-I#gv=GWAlnfH6_9%$-2g2xZ*8w3aeL9jK%FT1cbYan7Rw8M=50+hk8oR0X$#3Y*;*i|vCen9d&pk3he)I(7_@h`3s&JW z(0&pevk2x^2f}$lJ8r1)9xtCd0^j_+N~iNe1i}+)H1wwd0NO(~n`IfGa%Sc|o%YSm zVsOaqi0O)3k?9wV>F1XW%L89i(_6tsTf#KnB*0A}ogAc8l9W_PZYJ0r&{?}z4Al}) i0uaBjT_%^|a>)<(I$Y&=cFNrV0000@y7xH diff --git a/src/icons/flags/cv.png b/src/icons/flags/cv.png deleted file mode 100755 index eb96f9ca62e6bed752f246541df0277f44f7ea3c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 437 zcmV;m0ZRUfP)!qh_1-rw%^D{HCa;ke_TyNA0Y5LM7HDS@L0pa5I~m0uoFvjVUoEjg#jLMbJQ zP#};dl#ql=lS>0*E|vB|ZN{wv%4$VV%NgZcG!PL>r#|!U=L6rLI^^L z(hJ-J=}~_hF^soT$yPGW)kE3u0}SV%DtDl;Q7O-s|DJc!QD(;4t?~yqY8oX%CARa06(wg f5}2%i-h#GIixNU5Cg%<*00000NkvXXu0mjfA=Saz diff --git a/src/icons/flags/cx.png b/src/icons/flags/cx.png deleted file mode 100755 index 35ca80cf8cc4e853243ed0ade17fd11c7f0127a5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 489 zcmV0DwtwMG;t29>}N~$2L00F8%luONN9AgX_AV(>oNKq1-N*E(Tq{^g( zWo2BL)^*`X+q&KReET6znG4IPBczwp8w-8r`+S0>N_cyDhsI$Bv;vRk)v5~s2~jf(JLl^#eJI)?}N@edzV z6^af3Lqi#}5Jf&RQX%77HC^iC-F)1sPLGENXwGX36c;Fx!0AS#t6rBvA(PK{&&>Ru zdU|-dzP|ElaJ*EK`5kYwvu~Qq>bhy&#@gpv0(e|3?p<75jbm>%jdU`IM5K!}C@#@o zJ%3LRz0Rd_vrlFtfFibgPkQ)Lc5LjMYU@!|h;*yEYL`8~YzxQj%*20ilR%>lW;<8{ fy0!wCN8;5#lTbZEKi3Wf00000NkvXXu0mjfGFI0* diff --git a/src/icons/flags/cy.png b/src/icons/flags/cy.png deleted file mode 100755 index cd9253d6c07f3cd4ae56aa99a6c5d9b5c1b66707..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 348 zcmV-i0i*tjP)|AZ=ex{(rgj|F1Xy zf4=_zZrgtj*8h9~|Aiv||7U_2`sdFd7Kr~K1~72y{%8L6|NpE1Z2$kWN&n}u`Y#v{ zcNqiNNgxd{f&YIQ*bg)L>I;A4L+S3_yNqw&zUAZNLpBCm u$btlb7^nf{hj;JZL1OU_7~%quzytu4s9gl@_G{Sy0000S5T3-PpjC)a5mW(l)Qccqt0w_L5a`{zKwrcc5h`L%zCf>SDv06>NCdT!0GtGddoZMuVE&|6_JsQUbUc>I~e z*0!9*k|$C`?_4B|xU~3;(C~vVy`vs{eE@J+0Dy~GFVPrcfL}8ic@qzG_Dlc(002ov JPDHLkV1h~1oJarw diff --git a/src/icons/flags/de.png b/src/icons/flags/de.png deleted file mode 100755 index 5cf32c744bbcdfb96df170110bda334c5ef46c34..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 359 zcmV-t0hs=YP)q5u1=q+>F%vZO9tPgRiwJuO6HPseAk(jZ?VedQvZtr0_olvS z=Ez1K9`xAEvmZ`(ejeD-M)@}-vfC6_^c1}HD|SY zev63my??l_32WfMeLbg@xro-XlM*6slz>c>{IN;_kJ2_~8iiZX7@>mIMGx)@NL7SH`BaTa zLTd_Z|BY_@a=vHq#0Inp4#Ylsf*W{%ahX*QCt$!A;|Dk(hhZ_CMV|lw002ovPDHLk FV1gLQoALkv diff --git a/src/icons/flags/dj.png b/src/icons/flags/dj.png deleted file mode 100755 index de0faaa0d33f48948b13280bdb013843101b98eb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 429 zcmV;e0aE^nP)2L!oDcJuMNv}-g*3S8&=$_t=QF79UMi(kH@|C{kKKqZifpoAhc3YAbP8ih*HSW9DjIO5YGhrbK} z5|YzSk#eRbU&@QMVGB%-^W?E_Pq6!qvynTHcBVtlbmUcicd|ih0o%aL1Mc7Qhp+4( z8EiS_$Sai2grbflY&JK2etz#J&u9H~#=XWAcdqFcH^ogcLt22nJ#TFI^pwTLrt$0} z|LJ{S|9Bo!WQG)}NL@_yxbwCJJU8cl-}Cd>vepOdug=zfJp5T*i%L~3D%ExR#x&1% zTS-mRcwqrJxHwonUfn*~uCD)Tm#P|y>;ywvN!@PO_SWgv^6~P~=%_U1zwcUILN%1( z1X@W04PFo4?3}#sbta~IQ&qL9hU0QWk=3Z XeA8YduZ!ND00000NkvXXu0mjft@h2) diff --git a/src/icons/flags/dk.png b/src/icons/flags/dk.png deleted file mode 100755 index 622cebd2ce6885bf0f304ac418f32853177b2264..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 352 zcmV-m0iXVfP)$D zJ5B>p44n6N3j~Tpg_L3&Zoom{AhgisRw;9cTp?A+E_(og^6427 zijbs;*gWK6FH%O)WR_$dhHM>>nxaVnl9HA!lqO@Ei7cc|2@!IaJLr;BtM+>sL6ezC zn1K|TK#7P_iX=&`yfW34-zc??yIqeT9|WQ0=|2=HGy84V&2DdFvyr>ZPFE|9 diff --git a/src/icons/flags/dm.png b/src/icons/flags/dm.png deleted file mode 100755 index 9f6a3dd5f0039643a3bad0f81f95569423f75626..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 507 zcmVGSs^82ih3eA_)rK${z(t4{ff5hZdX8xlCqn>Epa7A^^ht3{GxL4F z(P(%WL-BmE(yEXUD~)_@AF8+Bopi$`dU#f@zi*ejgGUFAh5NVnm*cVz1`9iJB;FtB&)1LVUX?Cnltn~L xL2^*4`~gj!ER0g8_i6wD002ovPDHLkV1l(P=#&5e diff --git a/src/icons/flags/do.png b/src/icons/flags/do.png deleted file mode 100755 index 46230992f8b71bde1e8959006297cf11fb146886..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 368 zcmV-$0gwKPP)Qr_)gM}v$f)_}a-V3CN-AZafS-a%Tycvss zBe8Ib;qjPx1M|k}%>^FNGRm-jetZ8+yYB~w1`OyC&j3E1zYUPU9XqnuPcY{7^V8Fi zkwRJuxxKuc0VMeG>#i4dyE~oCZf>_JhUKb|tK(w>a~lb|(@wY5k?bUKs={(HRVF7= zzzkV_P-}0PM>4HaZ+&t z-G{G|sg_Ln<%_3ZK7O7IWFIP5r7HK8`@8BaYRZ(Q?lz#=z`i(gak?srlj8oiy47j_ zHBi%LGsvhd4suMZX^hR$y4y>2w$%YVZvK7b!mnmF@15Yun_n)^{k|U7zglYt9z=se1c);5EZe=?IJT`6Ew$Dv8X*KBYx(V+ zsU;1dw312+Da{XN~nI;^u@*T}t#v%*0mkx0b$CP8CBO+vD#r{$C4gO6?d zt({(8Q^!a7m33`dQc5c-W&{xU#+&odgz&?nGuMLM^Bewf&^t4$5mhn?02D$Ny8`mc_wEN`= z+Q;3!AK$jXEJ{p>7Nu6pjhyUOI4gcWLOI{kHc*tUS>yBXG2 z!b)i*z)CT!h#^Bk%I)8;z;F%_@LTbf!7H->JOTV{fg=J?zBvE@002ovPDHLkV1hlY Bo8SNd diff --git a/src/icons/flags/ee.png b/src/icons/flags/ee.png deleted file mode 100755 index 4bd818044298ad56508d8be70500d98767e3799a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 351 zcmV-l0igbgP)p4Y=ys zvOT%7x}DsU6|yOJrc`vX4UB>e`sVv%ff)VdJy0B^8c6;93nGEizyE;9Uw{7n0&;)< zlNDxXVEDrVbjClBkwAk%rUF&}0vQQX4N?ar|A6%T{s+_ybnzb+hW(CzP0Ri~dh`bf zeuE$c{Q3nZU=&D5UY>#BAjnC7{`>`U;ToXQ$jZSqP#&llq~Y&hkm6szf5FTLDL^(G zZUj&<436e=mNm>H=Je#!u49DXWA{+tI z5hhJ0=}NO^tstAjLjmp1$w_l`jNbm{d;}u6=GN(Z^RS()mKw=Y>GgK*?@L6KQUKV7 zVK_5Bmbc*J_Q3_*`ioM^YPD**cQ+YqyS`j&y~D u;e0-C0gxID1|+4Bx44+{USQO^P(1^TQT_Zn(m*^u1_zlFP5ncKQAyi1`i2pIF4axf z+uPcnBGj$l#@>%@zilrL|3L&0*QZviX=G*}po9pCj3Xii)6~UevK~by0FZwFP0O?Z zl2eI>0Cw(rJWgjapSq#j?Ix2+Et>8(m{~N5_*E=som0XpNNuMQ%ZXVx1d~=vnoSvv zq*~RcUZIekPL+VV3K)1X+eo`D^}19l(r9RA-W|pRk!`TO^Y&o*yp&3E{~)m?&1Iin zhQ~)6K@gjrH259>0C}>bC5R9Acz@S6Pu_V&r1?BNC~Oi*_-H(LmMfo>J0BhNh>VV% z^9~6udbG*nxYSpWb4 diff --git a/src/icons/flags/er.png b/src/icons/flags/er.png deleted file mode 100755 index 8223dbfcb9a0234a307d9afeddd3c7dbac831142..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 496 zcmV42JocYe_le7GT?hrV%auS8P#{HA zmZAkRVC0xM0zul|-n66@G6s-Xu0b~~e?g_wE+nBz3=Y9?i zuvYN3Bi1O;a-@+)dR0$)Rik>HeK6}%AchY&8z)LU`N_s3u5RncV|+0rTahSKC_+)w zO1=WZ0SJmdy2&ik?6>9fI(dv;@vpO5lgMc-C*y<0R;%@l<5Kr}&luE8OOgWQ>7 za$BTi$rru6rDKcy8F8U(uaE2Z5ycK%2p~4D+P+CCQ-|nt6>UiDJhZ3_5A7>P4Elt~aF%i-*UW)p0z%>j-q7`RI!98^f}M z{o)@*Uq9-i2`-!0l&ibOO1ylfc|+OuG#6O!O{8RrH!QA zLL8(Wh(t_%w*%;6z-cG#8Ti`lt91`AUq9D$1@(cW^_%yW@&L@|%tG@SK=%Q7{BUgs mx3Ys5ktWa-*xudi_rQO~z#cs_4q^uY0000p$0U9|v6e{YE(LS{V&Rg+cK zDzmb;m(UWZ2m<1HkuM8v@7B>5mrSZs9ZVX<@*hnC1o+d^;}R~~<^A!h>z}?8RT$6! z5R#34pZJ}Z)9J>1zk4Wa@xvd_qyZ$Cy#03gc$l0|M_-RxZAzU~-&m!JER!aaKIVG< zXX|@i{pfzpey(g3`gxHyQQxHLEmE^bav*+g)56>%yk zSZWDM!30xdl74ybd7g8qihBHp`*B>t_9`Z0oFoj{5E+>;z<>(KK>l48P-6V;{>?`K zA{26uuyD6*;TAG?x|3nhfafzx9rq82+hkFDgd$Lrv=rNt{v0^r4Bgyu16F`Zz z!E$5HVrJnHHYd(qyi=>yJz`Q-hy4dqMW?wn&!5EwBzL5A7wAg{*^{^3;cRK6-8(qC zv^%)cs2|?DdPB+*Q|gSzuL}TxOOz;Zn(G_w-oeqTMO^DVA09WP{0mqF3ILKxCS)n6 zqI$Kz70Ru}4=+D%pE))9bAT9uL?Cr<>B}dW$#R}!XY=Xz(~Ar({1|ngZIzmcgjs5@ z4SVm(0BU{HK0%5sbAGsU{e5%Y%`fl0DL7NkGQu3k4xkL6pkZZ2B+Owf$aQ`dOr4g@ nUq&`WA0E8le0s=*93KnUU^X5l0uz;JB30jg33MF9l_kZ7O3 z{<^kt0Z4T3$<8ptJb$nWIZ0A$?d|(-^E7j&sWqu-m|=!VB1MW6DN=L<`YcEyDaqwa zXIpP1z8DuQ}(f)Gz7t?fT_em2Mh5!Hn07*qo IM6N<$f+|IzjsO4v diff --git a/src/icons/flags/fj.png b/src/icons/flags/fj.png deleted file mode 100755 index 4e8d07340584885cd869dd373207a8697a4fa78a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 516 zcmV+f0{i`mP)GYBx-Ak2BD>*p(v=y zgusGAg9f3XYs+%EJ1M-nv-=I}P&0_Z3{```4fkAp{$NseW^1{RtX5q|wzYlRLM~cM4~I#_pcus{ zN-^G^+YIl@6PN4X^7dt-RI(^)Y-@`IhlNWAhR{M)iqR{*vZL7{ws1Z*bf#~As+5m} zZhI!#*SqnhkgGI#r7EZAFEvD!^hqh+^XTrKi>HJ9$T62pKK>l8`sT0IhKE19f?c~e z*yNQInwQKep~UT{#k@cerU&-T7h9Ht{#s|3Gkvw1Slc@=cu0JSro{DI4O>~9oX9+S zije>(emGpyo1@5A>djCm7Ns{<$#XBR^b~Vi*<_gbHhARd(o~4plundl5T#doV_gtz zoxPE1Wnp5h{nLRGQoprU9HrLBmgVg&^U7abf0#ZjEZp%k3lyQoNUDoWK9 z>gP}qV@Vr2sI(d-w0@;rlFQxy<2?sa5T4=Lp5aL>UAZ>ix%=wfA9tJyf^*^Pq3b&q zPYmP>V@<#Z1PB2F1R%go3>I!o-aH!QHYXP zu@Up~)2+DDlX+2u-$2lg*JZ>ePX*yaf8T19$POKVG0jM$c4QXHfSB?8(D3%1p4X`# zKga8{$-Z8{Rxi6N$cWl_CVg;tS9Q5u z4~R%KWSyFw?@n@SCFP0*$hcFFZf`jKYKecP43iY+=1To*2Rp1r0Y{0HaR#<+`CfUQ zbo!VCATu(H%O@R)+K*eFuw{+r%e9h#;BXkNk$QFJ*|(MDF7{U00%QPTwIo(pS(MmP z9J3W>y>tc?J)aKx#ofBcf9mev_@*cZ5D{foW@Qm#C01soNJsD6^M`ADQDvf*(qyUU zPa$B5b6Jl?MO4_bDvJs$tDXMP9V-#5#70#CN&sg8AE5sU0r`9PpIE^A4ZgoWj3U0b Qb^rhX07*qoM6N<$g6Y}r$^ZZW diff --git a/src/icons/flags/fm.png b/src/icons/flags/fm.png deleted file mode 100755 index a77a777a6d07ad5e40954694ef6da2757c334680..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 406 zcmV;H0crk;P)kZ;9t&3wk{;Z;B#9^qiJhhS*`Oc4{u0>$CU)*W z-WViFI`}=2Kn&yL+t-$pJbL~?Giqb7S(=|y^&kX-IG9XkMtbtPM6FZYxTRoj*{O5O{_iffLpSgN*Dappx z4oTap9;zFFguK|?NqE0~*u-Rg^XLB2I5j2-26YeB?Wm36?Wcokhn!oSGuhrfdbzcm zD9~V{=2*2bHf?M~#;NaIU%7i@WvrHBXfQxj3}bbZg_E;(40h&y{MnoDNzR@+5k#=# z01-WN{@&BEy1K{0)v8vty49^}73x;ETB0TW2T4Vjbhy_le*gdg07*qoM6N<$g07st AWB>pF diff --git a/src/icons/flags/fo.png b/src/icons/flags/fo.png deleted file mode 100755 index 957b0df668b8638c5ec6b64e16ba31fc16405cd8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 396 zcmV;70dxL|P)6Q|MCt|k(VU}LZWs@9~cC|liXvx z$-p4mSp4V7ga3bll7IgH0V@0jQuQ0e_y=PAf-qR+6fbW)%A(GEJzq%d!OuUx{(=-Q zd=wcfz7%LA$m~B*vmvCC7|SV!%PjBTNbvIVLY(MY{ObR&Uq65SJ3L7Q(*r8 zfrK|i2$jFK^0}W$90YENP597<1FX6E$EBjzS qgRLXO-kUdNkYg7ZoPWR$0RjMcFkj{r!My_j0000zCJ(=A4p9w$`4!c;;Jhf`EYyz^mtv0K~C#Jl;zJAc^fHciw*tm#ebYkGJnO z?1G=?CB^pXbjpS8)|#a2@84WAHF5s|fel6+DYB*X-buFBdhhz6;zsM$rOXwgN_%|+9pyuZ5x9Cr*#K04SUC+cI^EJVwpEk&|p;H_c# ofR}+`3}P7BeDdbo0SsVz2b?2lUyC@QnE(I)07*qoM6N<$g3M-?9{>OV diff --git a/src/icons/flags/gb.png b/src/icons/flags/gb.png deleted file mode 100644 index 405e897c5298a4ef4b1e45a81e292b9fb43ccdfd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 545 zcmV++0^a?JP)7tLGkNShC{O z|Bb8u{ri9W;g>}lZqHwT2gv?ErRRTNE08g1;pN`B7fzmd{I9F#-`}4THeFyyYB{*) z7_h9sy$HX8wQi;=-M`j-JblnvMwSPGkT&6yydp5E}a5&ks!usO-$O zmketXYyVH~_@9#UKR*6{WaR&l5Rg(IpMS2dzwGUQT3UWLG5M;e_f=c_XRuqVycG@` zY;FITSwPGM;=h0Y{`vdo_n$u}ufAZgkK5EU=X_M!jw@H+|9|`DXL3A9m66GBeM7K@ zzfYYU_s`raAw4T3VLgLzHiLQCy2a~3A@jMh?n75sOvy1I`;WHnFHLQrtF7#p{QUp_ z%dELC5@MRBo?{S9XPCVC^1pw7zqeN$J#f3Q;b30FVW12DhIsrAa{l-CZ+P0a(74sx z58wLx=f~>=-|V6#3{~?EOmRte&Ris@GlxfGGKcDf^VeRqN?Wvuo1DJ#l0m$fL9~ED jI9J55u6NIMSJONIJWOb+P?rm600000NkvXXu0mjfi76Tv diff --git a/src/icons/flags/gd.png b/src/icons/flags/gd.png deleted file mode 100755 index e533b304a8e4cc008aed60312c79f584a71192a5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 458 zcmV;*0X6=KP)2^ZDmq*7YW za?z@XP@2s%($m^}-k_z3x<`Sa3Q9=| zc!pCvQQ}z?zkO~+H?F^`f%Tm^`{&1nrcAa=4v8okN|Zy&R2KWVZHrr?ITTR0AR~Jl zWp1rZH99w1_STk_XDVg=ZF}0+i@t55;|Qn&qLi7#KJ(dMZ}{?GogdTmvlgnBF4^NX z`@SU$)36i*T0l@bX#PW`)apNVmME78esys0CEvDXX%=S1ym&wjDEz?}?@gK&-&N_; zv>kiY!m5?-VE0d3HCdV}c_^R`aMxSR@iUEG98+i5@|Fl)F*`Y;himrym)zac9cl;R zol$igofuJKSu8_|Wm^+%%{F#+pYHXG^-Dk%gj4zH9p%(S zx!EfQ)g}Z41Vk6U67Ps9!ii<#2(h1dPXGY?2SULwA^LnmEdT%j07*qoM6N<$f<>Rp AdjJ3c diff --git a/src/icons/flags/ge.png b/src/icons/flags/ge.png deleted file mode 100755 index 38a2a8b12f0a8cfcf04b5887af517be549ce0bdd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 492 zcmVKJ`Jew|xzeBMcDp#HssL0qJX?XsxZT#Ah^Q(6RSf`?%VqX^ z{`)suytw-Y6BrpteX-Rm|wgoXHSD<^_4A^{eGJwbOPt7o|BXGB5z+aiRnb0qjM8; zbHnyQ5IkD47i&0o9>!>z(tE~Z`P`(4y>cC4NRzCJ(=A4p9w$`4!c;;Jhf`EYyz^mtv0K~C#Jl;zJAc^fHciw*tm#ebYkGJnO z?1G=?CB^pXbjpS8)|#a2@84WAHF5s|fel6+DYB*X-buFBdhh~;gJ z06M+bCTrhS#ZnspX@GTtWeMQcs0-cx)~Ao6ba~0MM{L!y6&B$awwKbXHQ-h^pSi!$ z;g6Q`>h0Fv0MFn7fYz;xE#Rw{d~(6v#o^6swud7?R5Mr~zQ?;4`u39^D`do>o=efQ zFI2=(k;hLT`|Ag+FdQq=Xp0$YbaW~7$P-UMtROT#KRZ|Ci8pfOu||$vCrOhD1`DnL i0tR>@pIm&@0Ki{{GG%4t@;Pe&0000{{8*- z^g)`TPk@15hzk15|+FKiA^fZ13N?-oM82?k!t&G0;qea}VU!Q7P|1&Wm)Prqc`3ErrVh;lYmzp}$tfdj*pj9-CXK|(uTI38oS_wIKoID1+;j`NbSt-i>QqdLTv(clSmduuJWCkGXbw( z)-b?x=5P+vJ^;d_Y92Ln%`oyw!1mD*092(aHsrD*l?1Y+A|r)-e|kCr0Mfr+#fDvE z*&&MzS)Ik6-iv&?wIyJBbAA14eI2PJ0g$1;Py;Jzt=)h6+?M-(_qN^qf=8W-{9rp& zqp;sxr6!PnAj`2(nl#&OV+s9AIyE@8a%)Ce7~N-3QR@Cf!w3d1r0s{P=u= zz-Z(722GV^vdE%JEXq=3+p){&XxImS104|1|FPyovkO?@58eK35w0Qn(f|Me07*qo IM6N<$f;yz8^8f$< diff --git a/src/icons/flags/gn.png b/src/icons/flags/gn.png deleted file mode 100755 index 72e879adf312efccb86ac1cdfcac2ccf4cb366f5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 319 zcmV-F0l@x=P)QnGX+8*BnqSznua@Y4=O6oL9^%JB6}AqTA*PI8n%cXhvNMVFS1hklO1In z{!f5k@ERZ?;qi&LpP`_@U@idn_rN4u!t)*)ylp<8{qmVUeY7LRYCU{;xBxKo{RiE2 zPYZfRyE^*zyDFvD^~IIq0!(JPwYzJ^Gn%QHs#bNWr542{uytdPjdtHnl^lR*CEyS#M7G`NaDV>&FC6`~@=^XNAlf Rk`e#_002ovPDHLkV1l{Wi%0+f diff --git a/src/icons/flags/gp.png b/src/icons/flags/gp.png deleted file mode 100755 index 160dae80c0babb920d7bbe6910da9127a9db2ecb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 353 zcmV-n0iOPeP)@*W5~TV0 z_BigZzAbIOx8063@Jot_$=CDnGQ9r@(+U32K`>34G}D>p&_H0kU7sGEb)1K{I_xdh zs$>>QD48+^$|X@waWe&Ui&9g zOlP9fOaXm&4_rR_`UXyvkOkH_g;bP4OBpNz{q*~nm3JR3y%tVW0Eqa#dlIy$A~H~LK3smYa{S-K)6wsT0{j7`sY5186a*ar0000xnI&it=)D9iy@Z(Tvm||o0E`zQeTsNhgaK`hyh>qYORKJANWC%D zu5+FzoVzvR|Nnc=@p#Vfoa5!zS^&=W@&L*kFQE4kTf{_6#3q@a2A@Ps$OHf?<$M^1 zlGc~6A??=|B?y27xt1gf_tBFVMNz3#k^}&Nq}Jst1xlnOk%`V`{AT?zaHg>vz}3x% zC5@G}G*-sQSkkJH54LyPUV61zT`3&=`6a2c*(P{4Am8_Uy@%j$WAJ+^^**FVNpjgE7z$2IXHuv2 zL2z>3UzpGRAH>$mQr2=T=$53VELF%&)ebve=k9H`kd_4Ze2^q07yTxLNa5c_*TdXV j@{vOV=0_25`*8CM>ligP)*>u4xd;(n2_to;5FZ4|dVNO59!0?8F;TIVFfRilj?L7Za3FcKTd$?sE z!-w~;wbh06RjQUf$<9{(_3Q7S-+zDqfsp@x|NgsaQ!dMY>E@@K8F`m37Wnq#@0VY! z$2p(<_}|L@KIDPzr=S0S|N8a&FT?L&e}4Y_AuB7&z`($g@X5Z@H;DJsoiF>&GHD3& z+UUI4eszMX-Et*S#zl(A+jN2HJ}>-TSy z-&!vg5UrD`E%w_ zPl%#%r55Y&A3uKoX6EPTSaI~oN0p;nwlanUhk%@vdGS@g1LvPVZ}vT7{qvjY_iv`J zSFYrq`}gY?!|&hUU%&ZeA@)k@uc{~?>zz90vHAq*hNuyE1Q#fwh^x!=BhRZ)?IX!r)? zOG@$sNuVVldqA2Y44}wAAmi`fe}Dh-0!fGlmihB*U=ayKzZviX05c0J#+izCqyPW_ M07*qoM6N<$f-Hs-iU0rr diff --git a/src/icons/flags/gt.png b/src/icons/flags/gt.png deleted file mode 100755 index abeaa198609a88a4b98ea5ad889bd45bf62c35e9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 331 zcmV-R0kr;!P) zzPY?jZvYrp|NQpnFnt8rzFqzD^;2YIHgjP19iQI-v{M?-E-#idAV9?V+X}HF?0rvrF$@YgRJyIIZZ_pffA9FXLb-?zH{ dcm)P?@(;&hbC%CH<%R$N002ovPDHLkV1nUBmN@_b diff --git a/src/icons/flags/gu.png b/src/icons/flags/gu.png deleted file mode 100755 index f1248c5d45d0f6de7b5c8bf9b302cc4df73860e8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 384 zcmV-`0e}99P)vM372JffHT5r`hVO5*gpsWJ2Gs@utP?M7%JtA;KlY* zKfeC)D>5X=k^J=d-Hk2>{nnsXOew|OU2X(A0M^8&L*c>imtP;9+}d1!cJ!*4VyaRM z6$70ID4;+^1eyCkPvha}Lvz;HTgEs87Ti_GgY{___I1Y+*p6}`E)*1t4cW}q)etI zkSS(h$n4BtKl%1?;X`}B`g}6YkdcB>5|!ICkfA_9?B34yi@8ITB0+9a6c}h{*FxnL eJg$h#?EeDemPqDwmLvxN0000R;%6s diff --git a/src/icons/flags/gw.png b/src/icons/flags/gw.png deleted file mode 100755 index 2ad970b20ba49bc95b8753e3415437e864df9df7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 346 zcmV-g0j2(lP)396N7)ZV}oX-IUkZ=feCl~Sef4&FdTL!uBATybXR9L2rYZsKI} zWs1q1%rcx`!}c9)XwwbsO?z)_R)DiJV7iy?lY5!tfM*Pz(abr&ynV9*F!Sj%3CTo| z8C_7#)QpzpPVYWU&m>DS5|f!awCud`NA^P%@~ijyaa3hhm!isnt-IIt{UvL|k@UO@d#c>} zlTxHsb?q6soi;0L!zFtpq>(CBn^F$xNG`YBafhF*4I7!$(~)p)pXlmk?JCuB>~WGz sGGW8=3;Kd?-G^%c6c~Ik4O_U$UtzCtj$RDlasU7T07*qoM6N<$f-5wlV*mgE diff --git a/src/icons/flags/gy.png b/src/icons/flags/gy.png deleted file mode 100755 index b8f6a04421e55895022702daf41f2fdcec678df3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 520 zcmV+j0{8uiP)9qK`(vzTrV<<0G)o{xbWV_9=p_p3A_Sd;P60uagxW>$5(!8P=+uBtfdOF< z1d&7v1-Oew+G?q7LpRfj+ke~pzTfu-NMP{rJ3W^lj~N(<;%@ARw_MH@-~$c-AcvrT zO8{V&fSo6)&~V?G{@9-ezs|iY*78;w0udEaW-H>Dov`KEXS3b~z?L=_rWQZNz4%CX z;^K{xezgyp7YPPku<=q#9OzUXx>yN2fgiY7g!avrIC_uF~+$1G`oA zKH08f%}cLLuT@K!hvxvptVB7HRFJMG`SPU})${B|i?zUu)wgqnOt$h(sCusREUNGv z&>}L&{HDhyANO>IMoa$DU;F;#V(R#nD$so!NAO&QA?L(#M|I!W+AcVi~2R0%0vH2nZ0000< KMNUMnLSTa9to1?w diff --git a/src/icons/flags/hk.png b/src/icons/flags/hk.png deleted file mode 100755 index 5a3663a87cf3d3e9ba953fb89201a97607a69b8e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 393 zcmV;40e1e0P)J&;kk3#1OBs_(}Q;6b}8WJy|;&MbtMEH)dv%90XBWxy< zEhd@W{HkXlF`oSKzj6S80|^wMcA$H3005cFR0KQ}jtG$=<^Jn~Uau|ypuD?Rgd#vH zqPw}Jnd!HalQfDZGm&Lw1wa9S)HoecN-3R=c6YS4Hnq4|6{OinA|0p`P=ws!UR70d zc&L{b-P~%b=^P!+JUqPb?b&cRIxm45fILLPJsG;b*7mk~XKET{==?lCKGF=N-1Dcw z;Vzo!ugAx;fHpRisp+OYJ!RXDe;^$w34oND=xH`NKd<$5nd$OEO*7H$j?!|^-v+pg zOj6|6<72hI|JmTAxbM3QNsk2K(|Fk&9-zK+urZ}{&p2Umyh&uU*X~Ftv?U% zZ6CZ}fNBwd0?@$=1Br((0oDPqG!z+o6zwB+1l*?Sx4E1#ymuf1G84nbxgb`Mpjp6<7*ukIDs zQ*X~1Eb-=`-XAELTaFy`D)xq}!~0Z3&K~m_Wa((H8vyD3Qft1!F_T54hO$-N)KY1= zqPKAMdGeRn(=wU(wwA9HHq@p@UtbsFc}S*g*Q3?3X~JdPaX2yycoiSQO1EYf+^=*FrjI5^g*&zu5rcy zs15*Q%7hT1J#Fny^U3gT4HHZ#CKMBCZ4 RvYr3{002ovPDHLkV1kQl0uulL diff --git a/src/icons/flags/hn.png b/src/icons/flags/hn.png deleted file mode 100755 index 97630a336f4662f6c85850ad003a7e8c164d1024..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 411 zcmV;M0c8G(P)6$D5X9%=Bj&t5CZLKS*!l$&reUFG?DE%<>eLs8o_4l8{uIt*i?YeG0pRd$!ZQDM%id)mu zws$@qeAqj%eRpePygI7XfTR^k%iBZItDPUVZ%^0n+*r5$diQ5P^^A# zo@j94%s41gq^k*vDW)@B1C{}dfcwDOvdD6rsjb(&_8-~3bi=R-g&_a{002ovPDHLk FV1l?#!T$gN diff --git a/src/icons/flags/hr.png b/src/icons/flags/hr.png deleted file mode 100755 index 42d6f0727bb4fd7cbd904da77b1318d2365e7414..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 384 zcmV-`0e}99P)Y5Z$|6w6PJyE+~S3Mr>`;h=)yLlL&&4LM(!i1cap4!XlXekisVZ1B-x_nqJf* z+4*?RZITOuv%}omnfGRA_Y%03>0kV>Ct0!4umIJ_K5-0%3PUs|9}|HY%lI=G1c3uS zCQiiMvKL1k-T}XYceQtU0`lX@I01^BO(Ly_Gc=pHJ4d@kG%I+T3mj1%|We(PRH2jb`>i#fvP4sJM<6O*p&); zJ)|i{qg)UHnV?X9zB%5Te9lO~q9pqLKIwapG(9}HTDyO<46CxBw7LFReM+2X+fzne z2nyT#<K^1D*;fOt43TeuJG~jmj`*ou2DG#dDV3bR4 z^m*h5A=obl@N`sewr?SXT%)FYvKM5{-P7vYxWVeIiG0sv$I zEj(8N6M*%03!sxuU_*`tDN>UyH5n=7VYizA0L|x@wqZ9J8)V2PQw*!CLSC)cnJ;wu zv)xrKbup~4x|phYzJOtSi~*p#(P;Ev8DpGIr}?Fe^$x!VVSCK^(j`;2+5jdL7_F{X3?(b1$xsrT rvJ_c1Y#YG9Jy1Xa=O0i&<6GVUBIIobr=PTO00000NkvXXu0mjf`rULa 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 ba72a73f25c6b1d0495333c28eac8a53d12d0430..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 350 zcmV-k0iphhP)laX*k%#ve0|SddZYqb3{ojutLGJknMj(fQ8GpcjfLQ+bFSCH4*!i=J zfB%Al=06ZHfFW+c#KiRe{d<;w|Nb#DGJ@1I;8P8e1^R*sr~$uHG;JUofObLjFu(xN wP6iYJ%j#^h$~@!vvaEBuiFKIkn;y7hS+a z$X#7($;xe7$%+ceFcEFZT3%}9gq>dLmDK1mOhlztFSV+dIu^nE?n5K%X$dRfEO;2U!3A^ZS2J*ndC2|G$6# zk8wt^0%$rD5W`gi!OH#rfB*TvVZ;C4rT>5b{XcgblKTHZfB#{DYk=63;s;`P&iT*9 z`hP|-D6EiWfr_DiKntAGBzVXmG(bGfBJc9Ar4bm|48Xt!lE7H{^Oxc8Uq&Da68sB_ w86X!J5C8r%tf=|Nc>DHk(#kGRVtSi^O&Y;Q?5wib-O55Xaf`ik zek|_pn&HeabLPyMmJ@8lQyMT#*znYFGZH-j9DD!}xW$M9!EE6rvqQyJ%=P)<9)M1Mbd`u)KpR#g>t0qzyspUKPdNr-Yiee?9eul0glvL8SERugc3@$4(hEQw>x z*QD9LeP;RkmGkE>#&?f@{{7GPP;m7b?mvJ2{rUS>+V07nKM(%=WPJ7gW_9RumM!l@ zd{i|VxLE$(x%d0QBTjvNpxpasZ=D?^Wu;Sjz2nAec^{m1Wr&uoA2`_I3>|AHiKSKD0teo*h%`CWQ*CpWOje7N)O zzmkTj7{fchhnF4+^RxbuQsme zzSHMkh=_8^h;tn~{aitg_u-?@{MtJA%TB0FF%8w{JfN`k@pOg)kC`{$X(cfDw?v001Tl6yC*d0mA?Q N002ovPDHLkV1n0@Hyi)} diff --git a/src/icons/flags/iq.png b/src/icons/flags/iq.png deleted file mode 100755 index 9ac7f01c33258b82d9115587815fa40829454960..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 402 zcmV;D0d4+?P)ArqD0Y4-oY;Qm4;Xh^6*Hh}el5Z4(Sj0Ohhkt zNp5#`$GJO21uGwqw-0vSn_WTh4fEUoNf8B#MHVs!m|7ER&`5}YNJ`NU^~+@|t|NME z@n|%yRHC1htdgW;FESb4U_m}l%PWwwfq+ngHpKOs2vx)=jJ%v=2&t5*RJcwXV?u*R z_Z37vMC>bh+B!dbx(J5D?!bHPzwce|d%hn8LA%{fo&+Zk$2V`ce(0qq=hG9jSI?K$ z$mqD3=!Ly{w|?g}$k1+fhpVml2ei4cA+=n0)_CFc*wkt|M+A#A8NSNRxd)BI?WHZA z;5_t5&PcW>dwGF%lDL><|^A w&StX!U;zMEIgS(6b3Z0Q_LwL`e*yl14|tA3er6?r;{X5v07*qoM6N<$f(?DC{r~^~ diff --git a/src/icons/flags/ir.png b/src/icons/flags/ir.png deleted file mode 100755 index f038dc9ae1376b3a2bf33f618a17d1aa3b6eea5e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 397 zcmV;80doF{P);UA>47ym&!OR*5^G>WA*DMSd^1rn85sRZ*N z-m_ycLb>(b+F9Ef9t@qTI_Ch81VNDFln?hbvRdU*mNPi#`u%<~`F2{H#Oo`5 zelY8KdBH^hX696Nx-h*@s`B)dB0M@`CNrN;lBCz`WlnNAY;W`N5outv$uwoN$=yAA zPct?eOj9-*7?1J%JiNPgDUhkvtldTk6rl*`X2C<%RVrUkPu_s!C&k7FMGzHHAmT(2 rBPJRnRH2Fx3~(dB7Kp#;zZQUB&wE22=2${300000NkvXXu0mjfTEeLI diff --git a/src/icons/flags/is.png b/src/icons/flags/is.png deleted file mode 100755 index a4f546273d10864ed5781b9549f71bb52ff90d3c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 410 zcmV;L0cHM)P)00nVZH^CS130%A$1ra9)K^z1(5eIP-CkOio4&o*_ z^ajzk92^vm?@PWooafXGSwa#*8g9JC3i|rsXV+bmy1kbOB8UYMga`ycAbJ4L4)y_5 zxwST&902X`$xYELlSNsjWTooO_+1YG@UOFlssQl#81VG>dD5vO6|9uV8f~os>`_&M zswCSs({`{(r0m< zM0$M?4ltK7N0{{R307*qoM6N<$ Ef>AuUQ2+n{ diff --git a/src/icons/flags/it.png b/src/icons/flags/it.png deleted file mode 100755 index 8f248c52c984f5314b94f2733e0a59802255c59d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 339 zcmV-Z0j&OsP)BoF);jLc$)O|A1aViRs9E+gdi4%FAUYL)gbji@c*Brq~!nqK;HlVa4II| z|L@=b|NH@xUp8%GVPFA?Kl%Ff@4vr5fKUeqw{QRd^$Vz)QC1dc0}Id^pvgehe}L%k zZ*0ImE7LjN%Vk_Mn+7NAFgX8->C`_ErO8i4W)3?L1E z!Dj#Z_Y0^8j|N7tlbC=Se*gdd>n}+4@4vsWYXBP$boCzw2C$PrN`FHTb`5`k8h}3i z3-kjEFxGzm`yexsJs(#+qy1yy3F-`zTe*)W~X@Y;Q9FA@q+i5`Hi+u7|#I!9N+-`Cjyj#T6}Cq zEClaZC;C%Y#~LwSa3e+cOHEg12CHpy8CSZPHSuB<$6ocN$Q6#aXcN7<8|WZ z`Jhi8K4o2$SOCnd{6_~zbuy#v2YGZIo0igyn?f>`k)8p*of48YTm)2&q^f3oy>^$~ z7iD9Df#cU{xp0&DqKL@Cpkh!}6-vBT&m3VQDt?h>(y)d%I^|X`KYSLFtQbhD%AsA_ zen6Imna;|+S&HM?h@41rV7>J8^L|>bVptW{lO1f?#$1WFzsP7o=qOIEf8(nHuf*ii zIks%JN5cldYpO=qDP6HL`X@iWOMj&y zDT!Yc7M4;9$!4<&pa$SHqz!42Txe~2f6wEns%kJ8G!lS>wKZohFnn|EZg=d#c4jsJ zU}eSaw%6B9dN_2q>$CGQIuH>x0QdXubo}rD7Q6P=whs?}`jri!k$_3x-QoRxFkSqo zHP!}TJ2UG9CL&DUuCmjbqOQvSe-tSe6=p<|Vx*R5mL5+Y>jd7W;&NyHX?b#95g8Pj zjEqpo!3;^VltQ371&+3XS)hy(-$sl^0s#OYxQ1J~ysM2H00000NkvXXu0mjf=2(;^ diff --git a/src/icons/flags/jp.png b/src/icons/flags/jp.png deleted file mode 100755 index fcb41a1318e3ef9617c8f6165db7bd4719067b64..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 340 zcmV-a0jvIrP)UV68QJ;AB03^z`>t?|5$*cTwGj0^8f$;5Itb}|9?1z1YW#&!2(nCAHmqS@BiT= z|9}7bZ)W!2%L}fWk&zK-2@AUFwQK(`T=@UbpZ~vp|37^A|I;V`lT#oXATDHryB;L; z_U-@GtN;K0{r}f5C|bPa|KrDSOaA=%!vygh+>QS~euOIh4JN;Q`Ty|Yf0z|O#VkM! zR1ZWk|EGa3dAO8ObDrSNk4^;nOSopuc|No!ApsImnaPWUQIe3Tx zNfx-1pgI#0{&R8t-?a;*+RpBOObpz|Kmhau04N00002!K@)Z5%_FBZ2>em&aS`cf2=$z(Jhk47Vs0OW8u?5?kedn_sEbKl*Cs`q+V+wF_s zp5=}G!8`c@TzkG_vu~jqN~rEsf3_uGF?+E%d0D$xb)*z#`Q6TV?|ohZ&9bty-=P|b znd>pnZKWBsd3kOrqE4O|no!jV$S(m|CJ=E!h)Bq(64A)aTIND^CQxB6<^bgI(}(Wr zhM8Sl4L|)p#p^ejTK)LpjXRwPj|lh38~Mlmw}NMQ^5E&`vk{H-lsqo`mHQJ);$D}> z_A_~@Ms-`ee(&JbFh>Pdt~NU~swKZ=2rqRs`s3p>B=}f^DDz6iCbcb6vUu c4k*yVUt3~5E7mb0rT_o{07*qoM6N<$g7DMJ2LJ#7 diff --git a/src/icons/flags/kg.png b/src/icons/flags/kg.png deleted file mode 100755 index 6ded1b102cda9ddf47dcdb6af2a55c64338e7faa..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 353 zcmV-n0iOPeP)}e44iZN#FdDGK*6`sjYUB5JN%>mi7UUMKj2adCIXrXUrk`cJ~wqgh& zgd~&6j4Rw*Z}H#c&J6(A0eEkMMrwQ7y$&n{)~k5?f%A=WOMg*cDP&u4rE2?=ofxZNI06kjulL9piuQ#s($bd(Bz&$)t3OZaN z^*YJee)qKo{irl0k;aFRr)1-}=k){*_f4sQb+&MsGvfg zJfPe!UmAVd{!jzm9*5&;L-n@=j~^dWx~F;(x#tN?E8rtwt04d5WYRt52#ho{t6^GMd&F zlWK>QlD1oAw_vwx*KO~;-|zb;&NLtZ02dGd00961_y7O_1R#I_0AUwceZ2<&RFy@A z*wyH%CFKf6MBVQu?!o(Dr;iucQIQI&PR&z#S5+RzK2>C^{#bIEQoWd zJKfQ~|G^tSxocHI@`G<}!GziyqRiZVuNa28+_d82Gc#Z0{xg-0C;FV;`y=6sjrBV# zr)QU6e<-vj*NV#Rp;=)$+g$Z|sx&+?-*K`=Se}gLbKhS%*l;sDmKu0Icl=NyoAXBB z=dG1gW0i>ZKmJWD=MJy?I#U{+nD0uh-`mjVG`9`y+p}ZKrizbWio{Y^8yAsxpB9Pb z$brO6&Ku7Zc5hv&g7M74ot`TW$~x;?YDdyPw{nBA0$ z5;i=gHwNSWI?jEACi!;y_Py`jPn~lQ>)wIQ8u0sogb3N9W9CaHWHN&Z*cgenhoGWZ z15hbM1t1Zn>w?0sr)~}ygdy4$akx`k>I_r_3%rE@AMWq$G5}+N*Xwl#gAg5!OgGG= zK2w_)vEgc~Do}<0NHfM9CusnC+xB=oGsoe%`q|~v)z0#+p31&LmiLDsAesCD;*asI zi>+8k%-XlO;;p{WeBB&scT}xG8|C=&o-WV60RR{~8jCbV7Ec!1Zh22a6ul5Al;kLc z795rE21ALXa|29T<4Y|o_M5%7H#Kx68t>_%;7Xw2S_qU}OLFNWU@!g+q~&MuDNy#@ z_K{m`nxHn!oEp(IMF})`^7HTRZW;8#s5R?Pclu>BM@TDFh*E)6{K0 diff --git a/src/icons/flags/kn.png b/src/icons/flags/kn.png deleted file mode 100755 index 4570fc6120c294d71beb33e2f59591af682e1bd2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 475 zcmV<10VMv3P)v=${1MO4y~5w3_SP2{4gsi^?1B03N;rjX_mkOL=^WTn;m zzmAENxNGKWjADMz^Zk887tqJ!13ti$U>sORhY0AO1q47ywqvq@^2tt;pn|c%F#yqH z^k{C1W>J!|OefZH`mvfVF8mb9dcB?^1>nu!EpxMIj5ISExAk&pB_CXmw<^_g`9kW= zzD*n6Uq*_E7~P`DO_4^+b%oK*dNIMfU&GEl$GW=CK-Oce3DOo4DYM0zDHjqfE0qFF%Wr;Y*k^N<2S>%d6Mi|6Ruq1-mHdm z!Iy|WMIc3hN$ZO`RSa{l4o*FrYPCZM?ClBnZ?HHUe1aZ=lL;At6gdoSWcoccUJsUz z4!0MvJpDAwI62DXYVd_l4ap?|>7xP6RQ2%#8E5tnlxE-5D%V2)C;Hjoq>~6#&5QWdZ`?5k zba-;2-Fwacewj|SS|u})u>JwLXZH*=4#a2_S69EDJxBGB)ZSowTU%RUChsUY++$~F z12h*O*N+}Ff}&^MQHP`m^+JS@Aj~hmr@_;k`s0sC4{Y$ys|Ws?j(`KV@f!_s&#|nl?wQ*Xp28U^vxgO?RAm0;Jd&A_D`tzR6r1~PX%>Z zMW8@LRBA5?rmEDMG2=huKQM#`o`XIXR^jIM z>d)T>f`UGdXW0%^HtJOc1&{I*6(gj7dCR zD3-RjxA<^48i};FwPCjcA;d5Y(=>-i5?zu=*4N4MGFhA_t1In7^W@Z&rfCnwBG8}$ z0uKSk53+K(%mxBz@6fmLo0#Sc_SEa|{M^jb%xtxyNwS0xx+&ayU6-Ja#bS``YQY4i zO^<(Vc&SilR_@LR8HST3AW#TFOCYe>0A1IcIQCWPUr>J1jSaVqV7%4U#H3Pt*7T|< ziU>5e2g?F>KA+EIGT=Kk0B=7dhpr}Q54Iva6dXe z>FMqHHT~magux%Azn!_h&Tnq*M59rj=Yin1WLJ=7IhjnBN+m%MK|j!G>j5n-QYw`K wfubnRTq*RR>)!|Ybx_zzoIz6K3Hq>jnh*s^;|b&)z)R>E>}&;3kUr`SasZ3mzynyPOFRw55KkqwE;&Lj9U74J{?Y*6=odJMt zNgB0Uu8xn6>m77mw_2Fa=V&ddhNXPyJo? z^aYYi`o&`X@Gw=<0N!l)?f!n#TD4YWwHETf5Fu}!p1wXm4*=5X$Klaea+G_qraP%8 wr!jgPcG*490r(Ak0bYR2`(hT8gV_Y|51nXbDW{3!*#H0l07*qoM6N<$g3QE{zW@LL diff --git a/src/icons/flags/ky.png b/src/icons/flags/ky.png deleted file mode 100755 index 13de72efab78226df25e5c8e648b274aafdb9add..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 529 zcmV+s0`C2ZP)nsSrto`OW&{y62u}JB#M@f@A`dVAWqDwo|C2r zBaw-X=Jm7CuLUU-q7^Ih;wPt26wc2Vyfr!CE{q^R}5owLi20cx_FT0+s{`|nX7Dh;zf%B|d46D6K< zqD0=ecjN{iIRNc(z z4YAt+nEuh}Rl7xm(sK|F*z<>X(?kghoC~>w`?{R-?yqfE&Rk3ZFhHKYCs7e)5n?3| z4jfx|sWrQ7;@Zuz&nj}XdF}bV)q7GffQTrIG7Ga3E3vQ$iFOV|TAKX+rrJfut&!l% zOay=dEVHhzEMa!?k7HJLDy+=%>J#34B^I}o4K%C(3_!hCI{^z2U;zRwp!knJh&U^B TqK2Lq00000NkvXXu0mjfw{G+3 diff --git a/src/icons/flags/kz.png b/src/icons/flags/kz.png deleted file mode 100755 index 947e721abece32f552c02169977d17b7c6a64b1e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 454 zcmV;%0XhDOP)O~9LK-Uvq!7Fyqi@lv8It)RtmYSD3w-jqvA;6B1ds@b6YE?6(y95H#cd~t3WwP zMVfJ$6?(m!ChwmA@BjI#=xh6niiyetQi!#XLP81z0tG5jpg^^XzP7u2XIC`(Of%WS z$`Vkyw?SV|RmK^Io$R?c>y@Mx?Yfs{N(&Tr*gN@r!0irOpZnxG{TT<|-e0JulqC6- z=QG-{voYzA7p8c8l-3cR{KE++JFuY4V#Hq`axv_}sifC%XTqn7=2{mF96jSl~q9zzRwQc0R)_sN*ebG`{8WY2TT0Ys?=m`$~u5z=5(YqLSFb;#F=4 zXKRT)pBUfF&uQNsVtGDaf9Ycd4wNmSN&!xnHr;Ode4wxr3bwuV1)%G}F`QjwoGk@~ wT7Pdw^IG{^fdbW1jRFM<1PW9lp`KLgKfh^Ob9m8}+5i9m07*qoM6N<$f|$(JaR2}S diff --git a/src/icons/flags/la.png b/src/icons/flags/la.png deleted file mode 100755 index 257d2bc3c4d446a62da7581d6e70c415652d0fd8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 414 zcmV;P0b%}$P)8^?L<4dh=R|c<}LCJ2{BeaL3{vhMQb5-IxV6hq_PMSkoZMRp+uC#4+|Ud zGvDp(PKx7BU6x@MW|sZ2-*}8{u_0`Ewwyo-U}}98fHIM(2t|lg5TxiLlP(hUpC5Kg z04U42{)?m-3aZtKuG-UGtW|qaO(#%}UR{k<6#z(*0K2)r**@IW@@+Lt7h;|6a?g4wI_sg4BIOia!E$!)+o!{lfCdAbm;}9Gh;Htp7tW-kxpIUU nx*q_rAI~3|PafQrXc54F5K~0v^sbmZ00000NkvXXu0mjfb(F95 diff --git a/src/icons/flags/lc.png b/src/icons/flags/lc.png deleted file mode 100644 index e610fe7134ba1ae2c5a75f28f369228561a2c88d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 459 zcmV;+0W|)JP)@0EQLmpo7w3owmzp3Hm)cwla}9!@{`uXP zje~C+MWzI<`HGC7s?^8F4uMjgtagAS#XKy+kd4sSkfzdqQK^UN10giS+42=ovFg);+a z{m!rb+so;d#ZRd$TeKvlXws5RNtQgjboCXU_P2{?Yd@y=epHU4iY&(eoZ_TyKER?c zfmKsuT9ITaQY_zivgVF4Z%GOz#u002ovPDHLkV1gg^q`LqB diff --git a/src/icons/flags/lk.png b/src/icons/flags/lk.png deleted file mode 100755 index 165bcd2cc194c8b52a6b4358f3dbfc275fe71c62..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 462 zcmV;<0WtoGP)ShxXuJD1^V)Jj}HB~6;Nq9rIQ(^k^y z{A<7OeV+HR^efWN3;T~D8ABEdnkXU!i6RvsQJLB6jecSFCWjT_PtK3_rn~PK#s>-q z;dBUS_0zTc!%pjKWoF5B>Ssn8DOI1=+Rg3+(<05FK%+`&g7&4^kM-uwdu3&&FokGA zg)2B2@aS{n;mdFPo2~xR2{Xrs@oS?!J+Ax~N>h;Zfapd@PDey;&d*k!|Gsd0xc#o% zxjgIN7}7n6G87&FTy((|PIoD{uTFQ?IwoIzwY&WIpnGLPcaoKYfO|m5Mkt)_IMw$L zb9YwCu<6C{T(h)MgF1NPt`1kMM-@icg_YWBS{{8#c zuU|iZ{`~Rd$M^5wU*EjW0@UH+q|VOHVq>keW9QZ9)y4n+`~jkWK=SwR|9^q(-~WJ& z-@jQTBri;y1=6r*&rKT}rHz{|{r>Y;qNV3Q4#3FBXqJ)<)bQuxl_%SGUI7~V_s`#F z#n~XUL8ijY{tGnz&%fWlSS4jn&sxOz`|WFHL1Bm)K->P~28>KhZ*SaSxg;zq)7SR< z*)x!NAa?^@4{|ZkY%l|8FPQu15397y$%U&KzrTLT3bp~i@jzLiA70$J#&StiT)wUT z=hG)(V<49N`Ui3}*anDyK;&O`Ik{uYH!^;G{*+Bb49yQ1wt)nI`1#e#EaxPp|DZchiQ diff --git a/src/icons/flags/ls.png b/src/icons/flags/ls.png deleted file mode 100755 index e9c653aa87b235ed0f9f4411fe402630551a2b3b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 498 zcmVe|9ppv~Z31fWM=iP(5i<|YZ%?c*M@T`p*74P*-ZY(;ia4QsUCwo%f z`xf#2g|)(Nlb9$LJ~_|nI)-46^qn3VpZfUnkx*-F@?O#&_1+iD!JUPT;IK{VIgaVV zV@_1XX3&NO@ax;ksmv%~%EdRwZd`h}SbV=7v|?d36n*E5c}iBC4%=hT5|3y1057$ oB#(Z;0udm900ao2fB^mY3#0*1WjWyZ@Bjb+07*qoM6N<$g6B%>F8}}l diff --git a/src/icons/flags/lt.png b/src/icons/flags/lt.png deleted file mode 100755 index 2e3b86f78c9f0e2f08f3052e2cceb087dccba25e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 344 zcmV-e0jK_nP)~e!ZPLvBs?vd8Q#@facNEEA7rU)dYk_XDp?2N_te7Y>d zkJ;JXg%5zREei%F_+yF0OM|r;}VNW&yzM2&5%=`;M(1*+kY5m*ZB73`S*IQmMoey*({S?)y3x2 z(}TmC9~gLn+-%B{#b&wKq*-0n?`vvdjRBw|Mdeb@4^`f*m5Y-@h5*LpcYF$;AInr! zU9@J5W^J??YX4MMKQTT7hyT@o8Pa5`Qni7tBSt;;`ztUCXeviXA)$^K5+o#$iv%g% qOSigTfaMn;z;C*RsrcXxx-J zG>@Jjf^sI9CY^MKBc0(4N0g0C0Tst5-rdLAIw+ft_%kir9`PMK?X39<1ChL9A26ePz_WQ&l!{hN= z*gv!L$_sEtR{?nM*RtLRK>Y#kS1SM+kr63{E9B`O?m@~u$Z!|=x?a}`0QvjznNmnW zHWwMBjG~2^$nkt0Ks^H<$?M%_au1_uqRA*TkwfwXl&|e}vRKG0GZB$MwB9m1h;C7b z!?(?*NGhddW@Z9t@NbpD;CMLH@7-=Zo5>8>?#%A@nHO$P)zRpEyDd+^!*Y4t@55bY z!LDOnz^qN__U`U^x2pk!dy>&)7G^=FS(4ennXZ%oR0EQJGo1z*E_r{l4*V`Bo!opOG$Nst4INPxG~oda1Q3d-Sr_51SQTvfhYXn=?Dm*J*KXEUH~p% zmj(i-<8~57YN@425kpyQUVpC(K%;MeH^*)dVn7oW(#7!ne%>6?aXfmC87e9ln+$2v ztdv?PEChyUhCy$jkg3}1a?yl_5Ua(=(GF#$XjaJ7JUT{UL2zrvIM6f0BUu*1jUb!m z@zHTVOxT>REMy3+L-<9$LWMFJyA5GMVEFO&>4=eXw~}Q@wj#IPMsULS(;~M#MINrR aa^N3-D3J4-Dxi6fssbFGa;N$LB_l!eBK?5_*4ek)Ts=EwkkKF~aDT-mHi>|3|#$2^N z|A}S*`#k_xp$eH+B4r7ZNiXel&j+gEZ>0&8m$qY~? zZ{Om}OvT*`y_nEuOQa(p^@k1P@rfpj3qO)2b-`8t;uOo2i6iD45lUpD3pNyXJCjgC r1ldSP=q&XNky$`HuNV2xj(hzA`O8|sI`WqW00000NkvXXu0mjfK@fRp diff --git a/src/icons/flags/mc.png b/src/icons/flags/mc.png deleted file mode 100755 index 6647ff98b06e4edee10e71bd1b783e7c9c838ab7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 302 zcmV+}0nz@6P)Nkldd1*!fG(ZKNgH&6o$ z5HkW*16BO_!|)qOVlf-80cbi411l?otn7almj8c&9{7WBF_P0EB!iUHzk>%EU%!4W zBqa172pGT+H(+97x_P)W|mTgs# z`nFq_&M(?NKY#g~w6J+Z26_k%R8g67!uhL}(@)x!*Nge~EN*UeYt>pr0RzfXv`jf+ zRd?cQi>a@D+)SAa`F{Z_o3tvT<0f^RZyu4peR(V4*d{F*7ywJALb>Rq-MGniaKF^< z-2D?XO%Y8-H5yo;ygU&z!_Qlrv|BpHN6qD1%QYG#`RwXc3d@+R!Dl9?*jveOOpeSh xRH|HsDgzzx9MB;@-raK#@53H>y8&Yaz&~)hWL0+PPx1f&002ovPDHLkV1n8tuNnXV diff --git a/src/icons/flags/me.png b/src/icons/flags/me.png deleted file mode 100644 index 9b316f169623808ebb6d2beace69e22f9d8973db..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 392 zcmV;30eAk1P)f7zW_$J?~!?6Nj@4hC)QSxH#$1Q1k)ZTKWu)O)gC?Q9+xFyQ|R_fnkt?fwW|` zG$a*?bvozw+_&ud>$?CTw8}(Co6cyhWKB2c|DRh&C>Rhz2+@!V=RQ8(1oF+3p@bm} zVRUK;r*B@J=_bmegdrS%`KGhm`rvW*`(X%s*6M+D2#dx3lQ(kl?Edh~$(mj{zyIv5 z#bOawvZ=5L!!CATynXrpN8S19(>o{6{#}GHtg%@g7GX5MA01q~aCrUu*Uvp)b^POt zVF=Nr2d2Z)6J7P+=fC{({-f_MeS7cl>EB0ZZa;ZvF*-U-dthaB)vCqfwXd$d{Q8gC zcBdZvcKgFe(P1bvHq)ua5QabB`ytGopQA7D3MGWr*45$E&8vGt8A>$-gi;c_zaHL5 mo3WDCOw(qhO(iKJwD1bVH4S_ktbIEG0000uSwSA=v75bY!8Za8Fs_QvUd7g#EBF!*qMln*H-s@$2srr08 zJ@Wl4q8O84G8{}s2F-^%zFyGU9^1N|~9J=|rH}?RK_pOR~LwUgHfga03Vs5P$#!0%rIIB(P&2RMN6+00000 LNkvXXu0mjftVe(Q diff --git a/src/icons/flags/mh.png b/src/icons/flags/mh.png deleted file mode 100755 index ae1ca1da141a1514ebb322925d34580d871df6c8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 516 zcmV+f0{i`mP)R<_)bLxDq0swA|vMoZ8n&C$}*R82KRHFSu9 zcuChyVuv{#XIv$cSE6|ys=&f}#4F#F)j zU|(l4(X_a{@hf!9N+QfcB#t;@SckOvdbMS#`!)=K!>I#f7kX4tELA_2e=rHLI1)!v zcR_-8CtDWAn+r{cj_gjs01}S{06Y(|Sn&6iS?kWT4#Q2wnbvG?az~G6bo7Q?dt_j# z^lkTfcC9TL%NI8tu_bM|phLe;9DF;LDrw({4o_>>iAcTK`|}1Y^@e+qD?3sm4kM3P zGG=MIqtMxZO3yvi)XB6)? zH&5Oz6e^orzmFYF0oDM-EOqA_TN_UG&H)m&kId%NZofcnOFEJQ3U{|1+Pw$m4TSHqFVi?#L2nu}~# zTcV>i?ns2$35ZyjNfaROQs!oUqj~331NaQs|B!u!0Q>>v=O6Z)nbVvA0000O~9LGP;`#x@(lS1AlN^ek`+KGyr3QkHcoYs!wGLdrJPLhhtS}Dy*EElwjYDiYO zXuQx`MIkk_e&7H9_f>1d1l$Ek0034<$Q}s^2?;q$F3>UwH?MLDKg{NLQmacPO4F3? zc(iZ{#Wi~CwT^|)mUw%KE=oU7cgek*GAKyKwva>yg$iSV+TnO?r61^mO@sqCpf zDz;QV4KEcV6Fwf^Cr^c6i(w_SIYu*F*(e?qmW%hxhvYFi<)7hS;c0n2yhHTGb6Q>j z)$8(F;al-LnebuR^84^#`FePFct{MDyh6(ne4+S5@%P|gabNC+7iEXP%Io0=vcp@| z98}(-%|)6~`Ag6%J`?^dKMG5>ybwMiUku+9OT~Xmfi|H#R6H&Y$TRY@aD+$XP2o9t zRz4P<7H=x^6=?G$oyo$=cHb7Om7PLr_KHqnmr&tj;YQ_h<#f#+ZO*ZAb|&XZNB|P@ k8kyt^5)u;f33Oq=f5eqP*2NX%%>V!Z07*qoM6N<$f=o@w1ONa4 diff --git a/src/icons/flags/ml.png b/src/icons/flags/ml.png deleted file mode 100755 index 0796eaa5c7bebafdd309b62804e3a017a88f9019..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 322 zcmV-I0lof-P)A+yb#Y6FOB< zqhSWvIMUYn^YfmT=4>_eS`C8ciFhk!b_|Qp@CO7(IP(1qZ(iKaZ2S#>#9-L(A7eCf UGCA$1fB*mh07*qoM6N<$f+$3bBme*a diff --git a/src/icons/flags/mm.png b/src/icons/flags/mm.png deleted file mode 100755 index d931b1dbe476d4f43a9fdcadde44e503a74f9409..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 336 zcmV-W0k8gvP)Wuib~)p2idC#5)Mdwj$zUuRH&oGm68FMKYOY{_mfE zG6`U}W`cMrqk;%)f8 z`|E}pX$O*)VXwIV9RE_|9_|ipfi?H|_8tSQU@kn9GZkp$?C*z!XIw~0!kyaP$+=d6 i^uGE?{`>AY0zLsV>{b$zyAZbk0000d&85_4a@-RHLu9WUbg+RKl-E6TI^!4(1Uxvh!i{0 z=IUw&AUXZcb>mn2=Jwl>7NqvBFR3+BIXmkx0eKxBH{P{KGPOpE>Y(-1xjn)`~>Al&UW)`%k&!&e$DmD_uQ}J_J8|YAO o4t}x25uf1XV6geh%h8Sc3!WKH5+dr8*Z=?k07*qoM6N<$f`D6zC6vfYb{t1*9Y3dRhiDD*OY}KVp(aC;j@a7;P0f^t_$imFbLyKe+F;Q;{ z1l`nBU2k@=-nn-7;+^%*8X_KVKD@W~d|Khz`CLqB1aS)2u{GG5)Dv;}GL;9H?r(Ru zTY2laJidJ9%IQ{nrPX=y{ey-sx0XkrMhS$5iV2-+GW1JE`A diff --git a/src/icons/flags/mp.png b/src/icons/flags/mp.png deleted file mode 100755 index df0c4b8c186fad44701f02f30b980b119f445f07..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 481 zcmV<70UrK|P)K3G52H8vk)`aJ|`#la(>2Vx4-5p#CCvM|EjBo}c9N`RIhb}<}5pX@m0Pfzr z2p|MALoVwN7yWF>Wx)EcftOWV|DK`(DN6Tm+=~GKVRLIo3WX7OyqxgsYLXOE7@as$ zKYw)R$+yy4Bl1)}w-0a;V8MbED4Q(W$%6aH>4%@ouhUc4pH5}1vv4Um%9Er37lFnQ zC^NIu`PTAA``P0DpmdD<+m)>cpUN4mdq?L*8sH*0nu27WQbr*@c4}s5Y&d;x_Tc>7 zWVJfn-yfXhX_Np)pi!bkTCzPhQ~I&I(P*`kmD<`;y>IT!s&5Z?FY<3gjIJ{UPb2kw zY4A|=<j|Sim XFwa04#%s(k00000NkvXXu0mjfd2ZMK diff --git a/src/icons/flags/mq.png b/src/icons/flags/mq.png deleted file mode 100755 index 05452001f6feda64989f639d4ea0fe96d02a200c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 539 zcmV+$0_6RPP)S1rwoyHJ}&;)oG0gDCm+g>a;F{5fF4NDk`7| zitf=aqcQ>uC?Fg)hmr>KUH>o7^ZP~X)JI@^3AS8Z$nD!5zVql);mvmtsm)tNWSZB3 z?%Au;smVxw{wYugNQW=Gym%}Wu(FxNiCi)|HawL}PNfq7oRBY*I~X4Joj$&Q_FP&- zc70x5HJ|~EO1)d!XiV(g(P-Jtj>B8lt1a7+mZkr!wqqlHA_k-ZS9+3WkB-N81`Qp$ zE(VUrTlxdflWO5&CKNC`eOCwoeR1zaF*6ab)Y_(@F(Vi-2ab0nHOkB@g)$MbFJK1ue1`e zATzHN%4-`<4Z`tc@msxG>)d|uUck)XSe|LL?Mr7S+Z|`={s$(0b@wDQ=Po?=Ts0aU zx;A(C$?LDBa_jBmn;Ikm==7X-#Y(_$j%@Qm@IOkCB>MHcSNKw$$tD>9qye_2QdiEW z#-c;6QU~^gwI2{d0EkC|q$oe1j&2Y1Y*!NuNC8|1+W5-?T%ZYbYqe)Y6pKv*eZUV` d00Cuy{s1x|6P3`5A+-Pi002ovPDHLkV1gGL> z#2{oN+4*^o#pepb6b}P4Q_KjDfhjNs0MuLt3~&wup8$(!_=U}Dn*gd;^-7PO%WkuUt+YP4x^!?+5^h8ltoSPTayPkfQx@dAlMU&+T8pZ&sdMb977L*=Nd23C# z*Tf?-v*ksSq^StR7)B6x`&c(7W>HNWuX$yMY@CI6*2yEXs2TzVS5#8h`yYCCRXijQ zsBh$VzTD77Q;hHsI0S0`EB}XoegP-IIs5_XdT3pi5%ebj0000rU;L?fu=;bdEs1iq3N^q1w!8k3sPDhnQkg@jpPhjXp*15HtbC=vUuOV|BucBxa^3X4rI_cWXgDwTGakJt$VaD7Q7 zQj35kjfpt0cdJXsM&Eq3bHNA!D;xE-vCKr$dE93>s149o1FHc_#EJLY7f#pC?Ciu_ zaeA|t7U=f(-iL245>J_~Rvw%mc^@W} n+GR%skLcQ;qyNSJ5fITY<#$Fc)@>fQ00000NkvXXu0mjfwRGeU diff --git a/src/icons/flags/mt.png b/src/icons/flags/mt.png deleted file mode 100755 index a3703194afb17080bd4fca1a37e3a31e9395ce2c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 340 zcmV-a0jvIrP)e;hDzkll+8vX|ylo1|%C8!A@eqZv4OhaCLCwfdTc0 zfdSzp6b=9Xp&0)MsNpZe-@iaLEXb!tP=b!83o> z;>(8wvMj@Ihk=1@UjgC&WIeTVR#^OT2RJ-ADF6wQvP&*2Qb|RY6msG3XJ_Lh@ErS> z7r)Am6}l`_Ax(P9WF}4Cd$fHEjANW0-+%V=&!rqWmZwTG>B&%@^qi*r_`&`sTnu2( zZKw_PC`EK4M4RY@XLVMe=tO6`4cr|#_`KabxuuLv-({eXiUex_0000 z`8XE43Bki~nCi?Kp5X)t5Nzhmug!T005Ac#w7(Ak36io)hE-A|kdQ)J0{Q*$Z~_37 zfBbCoN>Wr=VK1quB8$CR-}<#2_x1!#0V*Zr?W?=1SxQ>f>eh5~F<-p<^S-6^(ZjMI zJUzNd1{edtF3Dlc=GBey`jhR)SBA?E=J#XTq?yi;T6ZWJqRWb#mv^>qtNiBV^$atY z6~V0DOWGuqRU}J~q+wGwkU{MIBJZ7P7?YZ!a6bB%r8acXx+`91+~yt2G3v?0(I* l1q|O#De4^2v;Ch&;2&wdOE8Vg`SAb%002ovPDHLkV1iklv)KRu diff --git a/src/icons/flags/mw.png b/src/icons/flags/mw.png deleted file mode 100755 index 1ee6485edd3eb694522ac36bc24de3c2a68ab34b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 365 zcmV-z0h0cSP)$- zA#2uQ0L1UFFDe>_V`aij#sxvFHo?B8UHk&37c?0Jo5Acikog5f5Ud7+Nz{o|O!Izs z&trHU4D>jTU%0zP|LDB*KpN6>{YQ(W^?EI7j4{X9Z*Qh=nwjh;AK_hMAOQ{!4_A_; zd35x>?d^6SUbK%u@B|Lbd;G};_V)H9osqOP=5~9ly#X)VyY?6OY!2+V{JwAR*gN(% zNLp1|S|u}?k7C)D-FrXs%w)>knG#ihf+mw?d(K*fqs91CPIhwA!k! zX{BS4>|WTVWHf~VgN!gplbN=iZK`7}dMN#pBKgEQ1v!BsMY^azj-y@M+EXqF00000 LNkvXXu0mjfigToT diff --git a/src/icons/flags/mx.png b/src/icons/flags/mx.png deleted file mode 100755 index 755f3be4d4e7d3a6f91eb8d005924338df3b6447..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 422 zcmV;X0a^ZuP)&9fJ5SEMr)X%>M2fnsGbE2C(6JUV#k;uX&+!WlNKa*4ozK#GU=uVm%V z{M}ju&|1S>>wR%;6@X}tM&vXZP;C6 z7hE8`H}hu9n`h0#us3&GFO%g{lNANjm4FmN=ISGpF~)|sfu5syX64tie( zhfLU#amgIPm~rE`9-C48AI99yh*u~8n1;=+F*^4BD(OD z71GU4%|-`$4mW{SEy_Y~Ng=u;6K9bspq zGDsbb*L;9b`kG9VI8bAa+v!^{Cb&mZJmD~ty%DoOs-}9aHNUp@e1D&?>^&(ik**7g z->`mY1@_rm)r=U%%k?!$0F{=-(`k>yxd-zz>CJdozv;Sxy1LU?jC`e1MmYS7$!#4< z|9(Il=;?DJVK@(&@4GvpigTe(&T#GF-??u@9`FOY7FyXJ%f+Gq0000 C%-XO3 diff --git a/src/icons/flags/mz.png b/src/icons/flags/mz.png deleted file mode 100755 index 9128db2a1eb7c3459b045b8ba127f536f1c9e701..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 438 zcmV;n0ZIOeP)Y|HgHrAqWvh7&Q>YLb3J*1i>nxoyJ-#wGo0zCxR$i2EkMo!EQiQA3($| zX`&C1V6g@vWL@vM_gtF{2#4?cic_9n#>1PyabN-n@Q(k_Iu?`%n^?TF++M=ZS;-U` zt_ZoOyWB;FyGS{M?OIy^oEzoR#?Jbc_%#{Ihc*shFR~7N1Bgr@-ED}Q@3O#FGTsVF&l8ZUDR>piKnc1 zV|4$opX-Uq>vgtuY>U@>0=KWo+exF85L=0Xss45wfCXcLoEBLiV%k!-uDfe%#qzwT zyHgf(qDZ2f{|)wh+h85+-)#eGCGWaAa;V&0m|YB=XstiIw=(c(L|%*uDN#yJp89j< z`2Fnj$@Cj!U;|8SGTDl7IFh{CP)W<43!U;~UWmjODh&6{)cP+?b-W&RbGcGZfk-Ph z#748xVAxghYDY_(gd!4jsMhACUE7~7yqx&_I_L@d+&f6FaQI7{0Bhq6`97axwilS002ovPDHLkV1fcq`$hl& diff --git a/src/icons/flags/nc.png b/src/icons/flags/nc.png deleted file mode 100755 index b8f86548b0ed31ca1541ac975e5eb87831dc1507..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 469 zcmV;`0V@89P)PN>E#|N~bn~6k=y@p-l=Av9k&Yfpk$&BvwM$ z6zaN0o)(I*jfKBRen|H1%$*sF2bLZVr@GC}aH)lV&_RF>AqWT|4k3!NMB!-=#qH}y z0ifI4oxVk6>)k_AP4qAev!DgdX-(2>VrRPHCfx(`Rv{0=BG2H z(?aQLuJnULRe=$&5!kEcYbLaLF*vHjM5g9O2oymoQ4Z@H;k+ZrLw75#o-Xz^oBtz0XO<#_-J z1=RTb^Knk4h+`6LFUh$xalinIs{Zmv!`yL$k3)y2upLlQgyg$~Uk-4r2(KnEvPn$kQ! z_a%eZ(m!cWl58m?OCgtB^0gdt$k+0fd`puqr8gfWVGk@fZn;L+tZT26E;@11dHL?s zq$?@m_l4YY)2V8lbW%wr9aNAx?mlp9Y=4|CmJih_2`m6W02msB4IZ-_7vH{)?RL9Z zEF=L!2)=(|eM;>(c*c{L004|JHk-|4TM__B0{Hcl)n|6eY|i5s003wV+mmeoKnMZc zIpFDYa>xBg00003Y>$)klf!$5(P4}*1{oP}*$o)mo=@}D`D*B`j$a+G|E{w$JEJ2y z(it6D8J+1UXLTRlK05n&Hfc{eYPrA6&T?00I@4LMbXHeU-Q9G%byGv{r9YCTkU|Qn lq>w@?sicrfvJ}$3{sX^aYHBG7A3Fd5002ovPDHLkV1kKLpX>kt diff --git a/src/icons/flags/nf.png b/src/icons/flags/nf.png deleted file mode 100755 index 659bc0f0a13f32428044a37eccdd4b2271e00933..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 472 zcmV;}0Vn>6P)Nkl2(+aFV-_aFLUU!ZoLYR)tz6p%6bnB5F}zB}9~z#19ZeA{xd00o9>93odq@ z-7|YL-^_StVRm*hGx^@v`%883rNsiZOrM+h>+q^(8~ zvqCEJsCr+04xXQar@hNPvIG{yPLm3p18a=~8@A-WtJ^D~L|eAugM^?sH&#HV4iXGT zHEsbrsh%J-r!9u9@ZkF3*TKlYNRqI_6;e5vlJ%he8Gp7!>*4L;OMRg=GyuHToJLCM zhX+&iw=lIZJvP02wu}AR{8}MjsJ+yb!?{;U1#n<4_7x%M?&`^9bLHN0X{ZFmU zdRQMTlr%;v@Tf@8xS7!A@#gBpN_S^Ah=W8XgSo*tiT7{zk2a3zZ+rtj>r^1l!!nWp O00008{;(#JNN5NJ4Gjk&_8x%RcmXRKD|<_>!6i5Z1&uZoBpOUMGw;2z*l37^ zS4=ZA`QEqU8*Bjxi2INChx>;~fFzIG$Mdh}2m%EQ3r}3VzuK)cIX*hxtlz-Q46y0V z<%dhr9ku)B`etDP=KJp-j%_DlJ^$kP?&n>lI(>R@N>~WVI94q8yhyn!)$VpvEP$~_ ziWL2Koupjl>U3xKAQZP-mZISWLA9$S3$Y*^DXNsLS1ZjkLQj`VR=XxM&!jUcS5GT) z{t{&Eoca}MO>3+ev9P71leZ`Bmb_Z6fZYW4)_Z5~&OG+mF~y3{@CyW6*mC>j_Gteo l2_Wg=>EYtj1pz>Cz#r3mb|7(gQ8xep002ovPDHLkV1jo_l_UTF diff --git a/src/icons/flags/ni.png b/src/icons/flags/ni.png deleted file mode 100755 index 6aab83f0743279002f5c9c196569d5f3da345cd1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 370 zcmV-&0ge8NP)$%ih_nT(bgt{rG9~pACcBC5G?WwsZyj22q9Gd-YfcP~4MY8P!$de{7@J~j%|YI<7DnpO+G zuvT^z*GMerxw97J#v9TYe53l#hS7YA42(XS8+Dni|?6{_e^ z0>#DTCf9r3Yen=DPLjhp$+?MsQKOn;p4@!+yjt!V6P1buSuW@orovWFjs=sYFK~w>AL=Yy2 zQyrvGi^l;I?#w9_S4h(+uI2aJPHp!3J^pK5Jw9UNe&iW5gKw48+8Z` zI{Dn(`Q6?5-{1M*;QHj``sU`s0074T0MGyc*Z=_B007+p0Nwxq-%Cs5Qc~nsSL9t? z=WT83eSPYJg6seQ?1+f)008o?t_Tb`FekY)DaH~UcoQ9e77{iX9)B7YJ{>KV9vD?3 z9Bd~agDN7KEJU;}C94JrHU|nf2Mai>006T90KotN`|9fZ>+AgR@TW$6j{pDw33O6U zQvmb!{Qds^{{G$r<^uo#0ANW(K~#8NCB{<%#4r>9z}I$F+qTxW?tiEz&3p~arV}7m z?VKW8*7kxPcl#Tx!{A-I-#7AiXy-V*9yV(Q;1o2K3fQr<%tXf97do52MYOG#rS9jY h0Z0PRY5ntY9{`S=2)`{Gc7p%_002ovPDHLkV1hRJoI3yj diff --git a/src/icons/flags/nr.png b/src/icons/flags/nr.png deleted file mode 100755 index 2c319caecd68661aae023279ff0a50980894c880..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 391 zcmV;20eJq2P))XGA!5kx}p1}t&`f^B-MG`0~e1S`>7kX(eA+QKS@h{S-2 zh>)Q9_MM+&vAaQWnBu^B2F_2z{VxxI8ic3M9s!7xf^8>qoJf&P zMKW#5JKI|g0ICkYA3J4Rp0z{y%$=fq0jEc@5Rc%BDylG1MF}fP)RxD4t8Ujf?ml@j z+5fhD|JK#rk6(^|O*>7h+oZcJi8SSFlZ)?Pqk$r`e&@#K#=VDYw>O{foDO1&43$oE zzE8RUpaEU-hrNTtA19x_9u32kiz7;sEm^jc#IwLarAB!9cK7GW>G;xlIaC&CWNU_d l9_Vkjw*UL+SzY*7e*nA#b7H*OXI=mR002ovPDHLkV1jf-uzvsm diff --git a/src/icons/flags/nu.png b/src/icons/flags/nu.png deleted file mode 100755 index 5e365e12441e4cab6491270db189e13770394993..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 465 zcmV;?0WSWDP)yhEhlkPDHkU>OD>!wBuN34k|Lo+T7^w4 zynQp@jBoZ?dA+{oy?*ome)A2BMlYtt+*IC($_Y;#_Ka4}d%ib&J=pdzw6V01?Ph7j z;5C{a6ffb@>%N)sudBElVZ+V+mxVRSvmLS8x~X|&k!L%OCK8MWM3C_m->!HqX{=(! z%lZ2WU>AkE_om^X=;Wi}Xg=JLLZeXmQu<0shcW-ncf?biA%aGDem34WBwmg5O!7m> zchu5og(O2g$ch-Pd8})%uC1*2hTT@T7gVhr%dyf#!BVJm;j6y2agB2p&{P;0Oe$gS zVzqncvyUzBE{{(7>rJrr8R>})oaXkrB9x&~qjntfK$g7fcFS`}5fQ;?0!YKoL#y;x zKqDA_@e{>*ihxp&#QXr)is1=y3%&&m{ojSD*CTc6#5GvFG>~(OiQ30pX zk*MJeP#GsA(n^G-J?u&gic7^k8)?I>aUcyD8MN2@yNT)#V2*SLA14UR00000NkvXX Hu0mjfs?^p; diff --git a/src/icons/flags/nz.png b/src/icons/flags/nz.png deleted file mode 100755 index be935de872823591e7f7f71ac9e4230cdaac955c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 529 zcmV+s0`C2ZP)4hhoFqMmG|fqq#t>`4Mlk`g{Q(xiNu{9ZXh(5y5LX?fgS%s)h}eSYA}V49 z6)ZaFQ0SLM2m3+O(3r%=rpZa(=Xu`OAt2puF0O031E23qzS~bec(i;!wHmgpd*vfH zhV;dAC$Bsy0WE+52HJoE6krEVr*F+YpWtM=z4je`3z=*zm3XsIU0mNM(#-n2TmI1K zZ}?1XUO%3+XRH^&)k5TNEwooRemmsF+oaF>>Q!yjCo}F8bIsp%KR&gS9L&Z6wqCj; zl*@;Qa}-PHqeDF-XATmXrO>es8%6T0mikohn<@=Vcts-uD62YlIS`FK-Eg)7-WItt z^+7wIuZLr8C3n5Gq=VVYz%_UCgsEMK6af`H)$n$m)R*NyzTa7|(#LN*E4z~Fk;O8P zJKF_QncMRg8g9RCzBR+!Ki=E3zwFz=ILGjndzpm#_-BPyN}|Zz+$<Uw5Q$Q{Lq?JAdPG{0T#s%riLeHg4KTBi5@P8}iiDJ?ZqNKMz2xa;r?)dN zquroIY%=L6kuVFhCKh605@O9P)1k3Tk>b2gix@xxz*XSj(3c9}L;F8rKm+bS_>elR T5|4?e00000NkvXXu0mjfp5FDO diff --git a/src/icons/flags/om.png b/src/icons/flags/om.png deleted file mode 100755 index dce4f36ea94063825c2fd837c112e0a8b594dee2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 339 zcmV-Z0j&OsP)8;6I>@px-6F!^7*!*(+PPKU#{`Mji}QY_M>gT-)!$%-(!-S0n4r>%if z7Fm)hh=>3QvLdR}E=T}c0hKDr3{yR_7zj2I4cA&-CVT4x(h-&_;^vl-!6dy7;h?G1 z$-W-%&;qbz(qxg5@zqO4k`9@2DidCR(B{!mkyak>kS3F|Xv$J4Gt-$!2+chpK!5=O l*H=IQ0$u?F{usM8@D9A}d3Y#Xfv^Ao002ovPDHLkV1fb%j>7-| diff --git a/src/icons/flags/pa.png b/src/icons/flags/pa.png deleted file mode 100755 index 59a45a1b228b25ec5785e399722630fd1675836c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 390 zcmV;10eSw3P)aTKtnKp*wy{htV(CK!1$!Yrft73%h=p1x26xrq zo{t%e>n=JR4paQjXBmw~cqbA7Nuu8;&?2UWKnI}L>jC)pUnKhTkO0VbcKG}(cSX$d z-N{MU8sCid>pY((`o2~ddPP$Hz2xIq=5&*p-0R|EvGp{oIP%M`bFgNCbt5-HnavRw9(Ci0WPjgYN9C zyZ*zQ2VFhLQ$cykQy%5h?hk!btu?l{D~v%*IeF-1B2UgZJ3O?5gLW#(3Y*d?OL;0q zk2gApLq9$Bwu{sT)v5DQ3Qbv2Oq|L-3oP^q~1e~=mf8UO!hW?*3Y|NnnX z%>UoN|Nr>|B)@Fh1lGXt|NoPx41fOu(SL|?WN`cT|6jj=su^Wvfi|#!&HfKn{rfk% zY9Iir25VsW{Trx(1&A4es)08C`NQ!0&wosSqycCg*hzo>LR?8e!=FDu)4@*q`v>f& zU-&gJf}I3*643Zxzd)`6N?_FhHXdl`9|i`H24--O0i6hP7*-8`fEqxd0(1^Y1Jmz6 z43d&yWBx*7kdcuQ5uHj(kT3)ypkl_aNU;ct;q&LA5e)Pq1lZa_rN96H0zF}bUop?F P00000NkvXXu0mjf#Wjm? diff --git a/src/icons/flags/pf.png b/src/icons/flags/pf.png deleted file mode 100755 index 0da2b6c3da4f81c3ef8cff6e44cd9c9987f1be00..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 379 zcmV->0fhdEP)NQq}kQ zIELQVb@B`+=OcNN6CMD?AN>CfEiLd=frUl`0Nm+LGpfPVRiWx4RHX=2UF7cMBy}Kw z^87+Gm{EjgF2dnOafu!yMbcU=0^z;WnX6O)fFub7;x>D1hMDrz{4Tk{A>2a<-7HId z^gRI}5N}`I^A4qpk3w@BBPRm=H>ldY2bKhQFoGncjT~!TNz*4yMET$N@tGcyOm6%a>5YJuqgy@w

b?q0yO{+x3(?; zovK1rA=8n_a0HgZ=j2!6nH*thwzt;=@C&~GeY&1`HFHTqrX^cGFL&f+dY68y+UjZr z)B#kLBlAtGb+6GFWtz0)b@?KFqV#EcgElQyKpjA4M#S~a%`+PtcgZKxTy#M{qF>Sn z^hdf&O91Ksn$2df*BfkaKi_@U?RKBGTDMAm{X~DJcjWi<1^NXYQ2`AAYinx&Mx&7y z4vJ!WeEgb(be61rkWbP3s-0Y(Pp5SNM@L7);jk=A+nr8lHk*+=lpc^bq;I4j3uQPW zfF^*5kks$@CzHuwFd!+3q@;J!74lB#T4X&FKofuzD=RBSQH;mqcDt>Gh>#QuJDFcH gZ)UdepKb&H06v~M8(q;wS^xk507*qoM6N<$f*ydj?EnA( diff --git a/src/icons/flags/ph.png b/src/icons/flags/ph.png deleted file mode 100755 index 89083e94226d82314689dce902d6c4c8bffd1ac8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 413 zcmV;O0b>4%P)B^2V={}`%A7F zJJ^$BYe3u>xWEdK;9ZqlyS%B;y}Hv4_iM@pzJOtJ5~pX}+2(t_)7KWt1~jyW3(T>0 zgu`22T_TadfDb8S?n*>#p>+fU#Cw97@6|=~yX3!Z|3@@GHz8H~f;VqT00000NkvXX Hu0mjf0j0ZL diff --git a/src/icons/flags/pk.png b/src/icons/flags/pk.png deleted file mode 100755 index fc036d270a3f82121b7f2781ae3356737ae534e2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 448 zcmV;x0YCnUP)N7UuL=n9I8=A5hwBF(^$g9Z?bYm#2pIQAYJ;eJiyklt2Y- qG#<$iKKHjzw#mo82VQ*m74idz%0P@XgwqxP0000{)G diff --git a/src/icons/flags/pl.png b/src/icons/flags/pl.png deleted file mode 100755 index 52c7a9d55b3e45ba0af19e5c968ebfcb0c5c6bce..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 293 zcmV+=0owkFP)zsfNc{i*pAoF>|9=p{`2RmM0|V246!7KQGZqG@qW{Q@ z|JVQ{Bjdk6e^`iA4Uqymi3R9ZM!0G)#G?VIgN1>gpP{es|FdWR|NLS2^XESt{r>&` zH<0lg%=itGm6raua3R=94VEzI_51&?Um!LT$@u9L&^cfyfrUWE zBP&8x4YB+W0|Q6{GuQzPa7CEf{s1-nW%&CS=p2v+rr&=UBqhPd{AKt9(#Z%mk^w>j r(cixi1XRrU6&$&6#DL00lL7(&(DhuX&W!BM00000NkvXXu0mjfsZNPn diff --git a/src/icons/flags/pm.png b/src/icons/flags/pm.png deleted file mode 100755 index 0eea37cd780f0e7533d0858e0d13f861041a90f2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 566 zcmV-60?GY}P)_P5hP18&|X5CWEL$6q9lS|qL-jvGN6Ehpn_h4q7aAzp~9-3 z1cIKU2vjKk?>YB=C)ob0Sm>J;4h<#ewm&}vEP#MI-~|kT01c=D z9B=^gtW8a~uHB;}<97~Cx}E*;vHnCN_U^?$Z(!p6%e-Gdd3?P4$$hg%X9f<8q*s1$ zB2rMow%uAamus$N8#X-P_Q zZKemyK5z3>e6cfZTt5Fjq8qW!;=z3xJ!k;LR#GWF9NFVzyEeOhW7%P>zjwX2Yvan) zS3smQ9m9i}Uw^vhzYJeITR3r{#x-5Hr4&RU<&u4R?B|Z@>xmY$_Ld{1BGITjt|OzN zA}JSeyv1@o77QvdQp#00JeVFCNCo`0nYZy+$JX-i?v^za4H=1}3(wx%0_Io=@IQW_ zvbpSz=cX|g*0-PDo%M0cth6}t5!q4oz+rWvW-mC~@VAfK~%<0>bM6uH=5L*S9y+r+dj^tA+9BpGI3Y<4gzv+lGhR zmSEf?fhyYs$^Zwx0oO4J2*3gaz=0~j0RqZE8&C(d|LK|xW7%75xc~qF07*qoM6N<$ Ef*#NXHUIzs diff --git a/src/icons/flags/pn.png b/src/icons/flags/pn.png deleted file mode 100755 index edf6e5722541153e0241343501a6e4b4fb47e281..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 544 zcmV+*0^j|KP)|Rwo{f9uEq**`Z+P8_F35fh?^^q7l?_A?(joLY z=|q%ymR4tnW#5%yR<&X)AK21Tx3K;C-oVe2n0fnpzpLfi4X<{l-_iZ^U4lH zgsL+|1+V4TY-ph)bsG-ZLSxc9di6~x@-<*Mmxr<^F6977wMH|i21C73x!6kfu*P)n zb@SKeyXfc&@2TwW{N6T>Xsgy<2?GIpeWaLQ(1PEKNlSl{8%)T$vTlDCvPuId7oS$l zF=`r3I$V!;nz0Ktt0-IrfNL*a&Lu96SF6QYWJKrG<-#A2Tz+2LZTQmb2-lFP!!(hE z&RhVl0JtCp3SSYZ3gjpm_y!Y1=y=AXi7XOU)@DfHott?8QUHiZA__#o+vWd&B;U^; z+b;J{rV6z$L(Anp0MY`PFODP%HiXbZ11F{-^**25|4- ik^j-2JOBca0Pq)+(=S?nUlGXw0000Qqp(xdwxY1fsOlV2c zSZJH~J?}YR=j?}s)6=)-{P>){PhSRHZKKnR+$UfG@`voaP%=sezyMkcWV;aY8mCTX za#N5k$>vfhV;3YjS5oFQ9M-@>0LcexaX-%lDm^u2B#8i0g-XjX^j6CB^|c24e)>ow z^#*4dtt_Fgo(x8R7h~)tkx+ox+++j&I6k8D7*ek^(im=gk9hbqakJP=zPcJ3PC_9K zL?g`CN6CAdn?)u=Ig5tHdY8H9uyUX3sby(#Uf$Yz5RGbJaUO$1w6{y~IIAwTlx%(is^0000RQ% diff --git a/src/icons/flags/ps.png b/src/icons/flags/ps.png deleted file mode 100755 index 12a338a26585e985bb121e90e6b930db9cacafb9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 391 zcmV;20eJq2P)rA1O)v4{ToICiA|d}u>duRF#L~t@^s(dzsvvr z{rLMgQ2B2-_yvMM0A$L_$^sRGH2nYfpW*Lcr@wy{fB#nS@cy3=`yU%%WMq8!@FB}T zppI|f7(v?pDg6HPf9JOUO#lDK#9(RwDg?Tj3E`a|KmY&!{r}^~|BDv=@9Y1MO$X3B zED**2KY#i6{~yEeU;qEJ{Pzp|pOucqNnlHufKCD${O{LKhVS1W^8EVm<$+Z-$k6{l zSN{X~f%(rLpq|~TzbAOG{rbz(|Nj8>00a8(|G$6#{bl&Wz}U&aP#(y@AjH7% l3x@t6G5)|9|G*>z0|4ZpR54X7>!JVv002ovPDHLkV1jN0)P(>5 diff --git a/src/icons/flags/pt.png b/src/icons/flags/pt.png deleted file mode 100755 index dfe00c44c2c1272c5f496af5e3ea3c699fd3bbd9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 407 zcmV;I0cie-P)8}y6ot?C=53;t(n31eA%cS<;-vitI=OXpadQwS=Zr3b_zT2MaJHb}9}qrZH)0mSi&+1W*A)q=!G>_w82Qcg_X# z0cVf7`O1=(#-#u7%;OUQD09v~RmjkAh`uX=_LT1qQj(S;58J+H!ev z^=4Z(qO{zwB+msYfC__$6#7208~6Rzo8j)2Ym0*)mewCzwrhuM$N(w?I?e6#vHG_; zeR#6-=V$kboiA4A=i87{((-~rbp94!e`RmWKD{;dSjLv*N)RE3JAjIRptQHWM^Wxd zV!%q~mOw&+1otHYG`I(hfiu8>GoWDf_u?Nf^B<1aMs_{sUkU&K002ovPDHLkV1i#- B!G!<- diff --git a/src/icons/flags/pw.png b/src/icons/flags/pw.png deleted file mode 100755 index 0581288c77bd09c20252abeba39251c3685c2329..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 423 zcmV;Y0a*TtP)6o#Mg-~WhAGc_?q(BK9*HzzWYN{*ylfN}vU<;(@h;ZQkLO2`o|z?qXNg-K(Y zN+w~?%=Ue2y{~FF+pJcrR`s@e)>C+Bw%ILFK@br7-*tEP^bEOs0YJ7~G6+aJqC^>l zx|R;P$u0eIdDzndtZz9@2ImgHUp)G@INq!;zFRxr>?&8erH@Y+q#lr*B7&<6%hylc zFKn3kvvaSld#_fPDz534ZV6Q#QbGv2cICu_!Wu+jqbqASPCsE#Yq+Lsy2(^Jf)FiT z_&eQyn&5Y3^U(fpQ{~Sj5DB3Uk#fjeZEDySCV|xK_wCuAqXSj0>8kMsbySVXc544@ z^_DyjgVbE)?BkC&hdcYm#F3;-M2{3XXz3;%t=#_d>&)e2&vAY6_0rSN*D4;rb?k$n zXQZa?$U#~<#LDKUxW_sz~&Tr>$d zEW_;X?836im_dvB-$(|~>jAI?2@z%>XcDAz_8d?8{R#kJ5AP9y2U0ED`1o*LLjqtM{sU%-WE(}H@wj?Xy;hbe%c%v{VDNo;p`7d8eRR9C1u2c2x@a%` zTWZ^rx6|#X!^w`{pFIzNR3T}>ZDVD5@5%>XXINfY@Y|5mYy%bVAp=l4W!oLMs zMpYKWhf%`%?a}ep-6)gF1gT7u$}?d~L3cOn^ONfejTqioFM`UTYR2ZVkBNg-(&paLdj)&Kte z3$JYisRgM3Df$g&{Qd<(KpTK+Sm2I>Xj@!W1~T>6FR%?zv%%coe?eYjU;>&7Q4P@$ z-O>S({`33iACSRN)xW_cPyq{2!+)sq|NsB}pI=e{a>g%&)4?|U{s;0mNCVS9xbYwz z{}a0V!AAZ9k-xw?p%(rIh8j=<3j@qa5TDG<%>Ww@aXQ%eKOp1(0K@nXNG0RP_iwp) z_~3p3l6|oef5Bb`hy7m=35t=wz?hkE;ylO?AKtzD2L?cS6IuC}4EO*5Ykgbgfe3O& P00000NkvXXu0mjfQ&+5p diff --git a/src/icons/flags/re.png b/src/icons/flags/re.png deleted file mode 100755 index 25cbe709b99abc07cb5ce525af39a91bc62831bb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 367 zcmV-#0g(QQP)zCJ(=A4p9w$`4!c;;Jhf`EYyz^mtv0K~C#Jl;zJAc^fHciw*tm#ebYkGJnO z?1G=?CB^pXbjpS8)|#a2@84WAHF5s|fel6+DYB*X-buFBdhh`F@GLjf521W&v4|9d7Qm}Iob|P2^iAXT!n>+Vfyr=nfxaFLg z19#!#BR>Sd3ghO(<>@0ZHa6oIzQ8xnr8$8PCkx0ICcFxgE77)Jf*U z`OM@W02oZGQ_3G;+xrVt=B|X~4d}L%si-*uW>UvW%dRwC&6K5-*fsw9P=yppFu0fG zDwk5d90A*h%A8T5rW+WbQl36Jl%hUa*E9IJECqsMi07hvi(!FxFhN_7U*EqN0}F$N fzvGvC$J_h{C#`RtbM7A^00000NkvXXu0mjfZ?lsw diff --git a/src/icons/flags/rs.png b/src/icons/flags/rs.png deleted file mode 100644 index 23f716dc40c511f64b6940577cd529650a75e519..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 376 zcmV-;0f+vHP)@!3#=_Nd?@I;lj>5z;5ftIs-b>n`)`PIJb2D z(*xyW8J*RJkmdUBXyXM?kN`miP@5^-7E1nc2MlJtsGK-n%H1QI!67^cJB%6jEsU&;IWUhU$Hi2$go=Xt*GJN#=5=D`9RW<#?fBFTR WiT;J39PC8^0000;3PVRsBqnd>?OHq{h)g!SvwtUB zj>qJTi0GlSxPpTLm`ngN6AF;ovjXGHQC?ub{~7=wGcQTrLMbI8%5s^jRUQsR&|0=e zM7EapA8+S$TGs2&VY`jRqU?6qX(6YSQr3Fy=W~Dou#xh2p||^7RjQsUc7YgxE?Siq z=h1%(QbG(H#!q_rt{-7%b;wZ_a!4mq-K224^TUSM;Tgt$3%%by-id`6 vvy^bdLMl@K3>%x)x&@RY#D(!Uy=nnJKZ#`?dmlM#00000NkvXXu0mjfR4I95 diff --git a/src/icons/flags/rw.png b/src/icons/flags/rw.png deleted file mode 100755 index f4b0136eaebba0612ce0c95aa99954bb31cb41c7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 382 zcmV-^0fGLBP)F(nGlM;W2nJ$gB7%Y7ni=Q;%=8cmNb zVgD8fZ%=O_G%`fDD3m-iC0BX7W4^?}qmQpBFZU;`*X`$DET)InXM=Xyw8Ks~?UZAV zHe0{8`u=WQ8~`@%zl?xqCjP6vU%kACA)&Rj1K|16xi&zXB*x+~9^B-ob*3^avmz9; z$x1r2f|aSdex=?&!@vnnx4bY8hjP)1J@+cJCp&XW7CEt0RrO<2SfSxIum$4G^Na?d cT@*0z5BRxg!H9UPwg3PC07*qoM6N<$f>t%CqW}N^ diff --git a/src/icons/flags/sa.png b/src/icons/flags/sa.png deleted file mode 100755 index 36ebcb7cf3722219cb3dca06fa9885b11b0c7de3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 428 zcmV;d0aN~oP)jM zg*Ca!-h0l>`CFK1Y@A}4=EuNHh6nho00^N;^O+q?p>$*8!S-J|KL?ETqvblBr&idtz zv-&gS#8|K94@Vc>CPxX8?ngoPIQ$cISF4m#*}R-r@MLWjmcs zf7Fu#g^4Z)ki(!5<%7k++F)&5Pim{H?^U-mUwx~(#lmnr+^hB^Qao!=FeU7Me3hk) zL6eyq$%bv7<&%>M=_%4VV4&!7^LF$0=0drcQu?!1f4=YXCp(W@wTz1Zox$xl+YE)m zWKK8P*8Q#hFZ(Y4Jv4w44LrEqUuL+Il)Idwhg017@KV(3(lrJn0ziiKe~v_p|LYep WdN&u#UCkf>0000I_GzMe*aP;(K|W$acb&7GU;mF z01N;?0P`<9fz|sL;zOgbQmOFR*iPHV#Ki7_f$gPIlZ4hr#1k<>AH_NuU5E|6^E$33 z9zXE`Z&Rs*!^2(a^iS7St(MW+BMs@1wjY}}FF!xjUtC$YZLn!(U6+$fgz!k6F>8^zi-(D%CEoe zxKng#*cP|jBBJ%*2Wxbs5{xZJ_7=ZGp1pVSD_`kR>9(5`C5EE47!AO>c;r?naJF}U zeG_Z;P@&_Q_E8t*{`V{~G002ov JPDHLkV1iBR^Sb~5 diff --git a/src/icons/flags/sc.png b/src/icons/flags/sc.png deleted file mode 100755 index 8ad512b7e9fc1002a96ce1b3bdd5531034cb6366..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 480 zcmV<60U!Q}P)X^RQ56j5y78(z|A>HKKwSnxAks}jR|V!(NqAL6 zmm<)RLaiyoCWBeDWNrFB&-)yK&xqh~;K2FifLY)G01yGam6eC1qX1wA+lR%lLm2+S z0o`i#4gj-(T&_MgcApG@rc?)BX>?DhN;&54(vkxlz-F@_MLItIk!%BjB77ozFZ4q3 z^qwNAY&KaiGlUT3^IO?$8wga-IpsT{c#5Z&Bmj{lfDi~APE33Pl_s1MF8|j}?>RDp z>1oW&I6zgS+?D#!P>WPP6~6TpIrfFXLV;6LEL=m{S*Md+@}Nis#6nFHML<>v5(9n32iJw=$w@YZdX%RGNBu}YBL?r!5xqq10WK(~1FGhYZ6 zglEpORATuqPoL^BeEj2 z;oHvoMrWhdYxNKMY8nvY!8lmJ3Ajg-jmIzR3)kZ>+f}><+CT?Tz<>x)!2gvBWN-wt WjXhI+aVN)LHfWU}M$XLWk z8}{?+%7G~By<+KW@3M>~mN|@#ejWM2&_54upE^*30dD_F#E8w#ZEFmyUuY z(T4{IAXuPhclvefcBi#cEKJPXIEbQ`TFrr=1_?stqkAl_Tc`P1WEgv(st!a@Qt8!a zAuCpkvD;=AnGFuAzoy=&+H39jJMMk;RMpI?jwDIa@An-PG^Vd?a{%glIjn$H~ zlA9{3sJ2=LYUlvt&H{Cm5MkVLCmnZOah-&u+ z>t|JDQ7sp$Ar5n9&NhJK2~|yRUEOR7mu?{q_x82Rl$)kSN3vwufCsjo{vYzk$9)hc jZtUI%2-Nxv5HNth+_`y(blKyj00000NkvXXu0mjfSz4*l diff --git a/src/icons/flags/sg.png b/src/icons/flags/sg.png deleted file mode 100755 index 975d6bb08ad6dc7befa0d835e7b181a07a2d8073..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 349 zcmV-j0iyniP)t_+`Tn vj4|*BQfgOU37E^%iN8T&7XUrgSpR@8muXDcS|)?Z00000NkvXXu0mjfVD6Md diff --git a/src/icons/flags/sh.png b/src/icons/flags/sh.png deleted file mode 100755 index 9b6d05e3b32176bac472216b316ba8aba0f5da85..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 516 zcmV+f0{i`mP)?9Fm+>fAz%3)wrFoyo&vm-`n7 zfEpkG0R|92K;UHuC&rJ%L>#3LnPZ_V-~?)v+p*6EQUv(Z{#%c`ni9 zu8iP!5v5g_x>U+l>&qMrdD%!Dv%-kQs&#DHn9AL~AH1_oyVG4Qf6Ep`t|{TC)1{!k zP;HJ^wHEnT2Oq9WuBggVIdyGn7$AS-^vx(pJncVQY3nRBug~o{RY_&esqX78;IaLQs}e21Fik5vVjqQe&+&Xbl=5z}kODIZ4^7E4jV^0000+fLeEP@7DNexje8GP3Au*qbVdeSqjG1 z_WT82)%*C_|M}wI-$5pstz~QLa5530D67lYfNG$lFrOz01w@dAgoMc@L`*VJM!*}w d|Lv(2fWKadTrncAD{24$002ovPDHLkV1f%dtDpb? diff --git a/src/icons/flags/sj.png b/src/icons/flags/sj.png deleted file mode 100755 index 74264c5866b6768e421e265c20b7fb4920a50f61..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 397 zcmV;80doF{P)uvT^z*GMerxw97J#v9TYe53l#hS7YA42(XS8+Dni|?6{_e^ z0>#DTCf9r3Yen=DPLjhp$+?MsQKOn;p4@!+yjt!V6P1buSuW@orovWFjs=sYFK~w>AL=Yy2 zQyrvGi^l;I?H*}#{{JkLzNnWM}{27n+BA{&skyxgWPlSP22k+d{u${~eof?)0)gTTaO zh!^HKmFDP*u1ZRhAIQT4Iq^2(ht|Sf>bR6R-=yoik@F?tA{B9;Wy> z%pWreclag&1OTvObwGf~02Vh301l4`ib62V!zofU7-bfuxVm5E+V|OBR5L)AGiWlC zSy)l2Jn2tBK zSwhW@h!6NxNJ-L(q|S){g$PM$I(?ka$A<&myR8{sccd@ix7*!jbH3ZX znaND0sFW7WqL{4I8a2%Tc*+3HG#;O}r>4xptc5z$UGCuyKnb}0eB;m17pQ@Efl_hy TH(*S=00000NkvXXu0mjfwG)i( diff --git a/src/icons/flags/sm.png b/src/icons/flags/sm.png deleted file mode 100755 index 07282bb5575da6d51149716d9ee63b453efef372..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 396 zcmV;70dxL|P)5iDIhic1IoHkaBGIL& zpb{{k!9>ja?mef&GxEU0f%|vvUugFPq7Ra}$z2vyOZ%(#W z|11}KXb7nL_qot~l2Jx{8Ew=qf1QoYccUh*cdsimhrQ|OGFPpdY;Qa!FgO)+x=t^C zrq!hUa#ZOYw7LVwH@~ARx*}y1j46z+U@jxf)g4^g&pv$Rn%m1xx&HK=xRh6&f>{cq zdC6RnFjvRNKMiT)?^G|-?84a9KgIZZtrN(QBBL=GE~CE$7cGoUesk))rCJ3hxCfV< q02#2@MMfBr<-}|Fma#qw0RI8DL{Fj14OaF500002Ov5JcZE`9MJg8!-`LkuH^;c6Jta9>7Ad^a!bP18*Xv@gjDDg=i(%7!`MBcP##2 z2oA4(?69-A;3k7!b8rB|Y?wJ?xM2sJzc>dbGnw_Mp~35q561_$l~;}wJJQwVwM7gCz8Rb)@D$+VR8Q3w*q^F(sC^V_W9j#PSDQyDMUTE5}+a4#nlHPyT z-`301x_9`Wz$SQFEss4W`uL+he9=$o;oW-vK&gEt?13Go#~#;|+lijsuct@)UG?lp znVSo1U&$z{E|1j}MC$FC5_Kwb-N%mYO>kQ+jnqntRHCF-lqglPaMKO!C^SC4bF7xP zx1zNK2C>Yk>E0MvynzBkLGk?^a6R)d#XR0`yyYMMEL)MlF}zFw0000ESwF04^NQ1*=BlJhJsKrdF1s(YshynZ#ZyTF%oLQ!p_r1r%BqY*g<)R4 zK5MN>($8~@5>>Ee7^Xs*VMZu(dp#*xB_cR-RAE@ZFL->&lLwq^*%iZ#ViaZ6(@L=> zBb#nLy2s6Z?jJCTXAe34!@Dmel&MHvt6p;CSwQ&kjr~3DuDNrS^%dTKT~wK}RB2Um z7@>lr?cmc7HrD};j`_8vtrkB)Jd@Bu8fvq_T|5UlkTBFMt3k_e(Zb7zjl zzq>e`;xKTVdxu_2f3>;ZVksnVnLMPKW(qyM`%F?(-IVOEZYSlo%O~>St_4(w}&|~S>cF2jH_kW*h{_FY&^Nnc?hWMN7 P00000NkvXXu0mjf@s6)K diff --git a/src/icons/flags/st.png b/src/icons/flags/st.png deleted file mode 100755 index fb781300c3f75b27f3cd3cca0ab9ddc8457581fd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 427 zcmV;c0aX5pP)o^}m5c^~)%07yVv+@9ECi}nPt`Tf@2Q)rx-Y1nC{TvAFV zOEQ^a^4WvuZ4W5djpg;5ecM)2X(gGY$s{wv5#pg;htWX`p!d6)Ip2Hly2>n91)u^m zqbdrliZo|Be6b&G0*&4Mq}nMwR9$Bke~$U)H5ZqnD#kzf>SdfCuxWT?0WAQ?6|679 zx~eF}XvEP|O0l@a<;U@4H6nOvC0^8R?he`wU}Ih@rw<+oYSuJmGAT=-ETxprG;NI0z6A#3M_2)3E8156Yo6*~z+a6& VQkd!Qb58&O002ovPDHLkV1jO9!tek9 diff --git a/src/icons/flags/sv.png b/src/icons/flags/sv.png deleted file mode 100755 index bed69b9abaa328762b6f2260b103ec03c437630e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 371 zcmV-(0gV2MP)ryRW&Te09O>4!LZF+!_Eif1Z9;a)^r`IJjODU3U z%d%|y_r>8Ye6|F^*g%F)+9+t0?o6|ikEIGi9^U}FIL(KtCe`B5~U?Z4mpepQ#AP{WySjn=Ze z6iK9?&!(S0eH#R}W*b8bXAtQKwvy|KIty7k&Ek1+M4czkf_X3^#TC{q_5w>|1qv1%$im&dS}7 zc1^!J9cBf?pFe+C{=wbA@IOc~;M32KAtB7vG-8s6|7#j9>>dzJ2?apPwJU z>mjm?jEr~g++hT=($doI-MjZ241R$DgaIPKtUrH#|M~M*MMdS}#fzX|{r&roq@*NJ q3MdMcgMdF^)*mqV3j;vKBqIRNo=PfHR@XuR0000R2_R2|=$4Bq~`SR)Gt!s-v=1e$d(pD_qouCv%Vn&IUy4P&nUw8>< zl4coC&wOv~+_`;dxbxW7uF-qnm_?*Ulqyj|RxEE>*|2%!#X^7o;UkB7M5JD?51y?& zn|NF3Iz99J{J~RuLjg<_l$z4Xcz|Gw^z0 vDY7E6MpkCHDzOqPL5V>OQYC;Cv^M+&B<^8OJ`hSq00000NkvXXu0mjf_6z91 diff --git a/src/icons/flags/tc.png b/src/icons/flags/tc.png deleted file mode 100755 index 729ce5a636b518c2288ac5cd1268c3fc529f6405..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 509 zcmV zzu9P2lSyxbm~nf$JiKSnYgfOlm+n@s6LF+|=29e;dfFLTi;XtI%;Ut7$ib=toAV}{ECM1wLIi=ahENeOiw2_1Dgq|& zUgh+K-_27Sn-4ymQ1Xe)B?44MRG=ctP!^T`s;;$?H=kWJ)c|246B4mY#DZ|FkP;YR zfC@}h`v;nZs;W5}swt5&*I*JBI-`1NO%GTAiu?uXb(xhc!apEoImvtM2c7&a1AMGgy21#&8` zw6Ym8qKjQLFiMsqy9z46iWOH<0b^yIwj!D`Fd&y)iWITgN|-oiTE#RO(^S_#z_H3y zrjYzMC{WCBx`YxW0RxLvpe#i~%!EnBa+5<(9xHq@Oi89fc?z~-#`bYiDPpWtrOLp- zK~=tZw577H*xWmBn=`#b)afFM79{+{O~__`Z1r6eNi7+u5tiL@W_*&WsfQ)IC6RVVGN2Kd zvfjM^PHM_Jdy6vZW%DxEXce1xvFW-EAkHrX-9m-O3@~3%q%G*2Nf#K4{GY_AC zlmqkuplMT0Y64f8G%3<2jvd;(zLxZhCmZW)tJ9TA>Xnm6Buk+!wKcme_S+9%u3kR3 r_3G31&Nn~v##n_iA&Q$kJ!ziP-M#jDTB&S3dVGP!b1?J^Ow_S|*7wk8=+Tk3+r+GZ z5?#G}e830q0}$CGU^Xy4r-7&nD1*RSE?YgNzMe-_ByF2v!BmdRadNmMH?yk63n@o` z3T3Z-$I)(L1qr+AT=)Dsd+1Vgg7FCvkU;b&6A7_T(m>)+ap9&%+582qj4)&p0+x{0 zK;meK1E*^Q5sNR}9+RU@qPM{z`}nQp-yca_r*Cm?Low}G;-dfn002ovPDHLkV1hG@ BvK{~c diff --git a/src/icons/flags/th.png b/src/icons/flags/th.png deleted file mode 100755 index c1817ebc942861bfdd96ac1c4389d759438cac10..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 327 zcmV-N0l5B&P)_ic}q{i&GbMa&gez!H*Fft3Tk+bQQWuaW8&F_d3)H_MRli;X!Mm8bSzX z2;rn8Ht@FJ$&vt`p8=!=C&+YykrK!xGa@6BOmaCImCOXt>e}Qklu{OpMY+9udAPs) z_*ltlrEJkuilQu9GQ+fw`}=5 z85zu4+uE+xH8QH(3kkpt@GX&y8fIu6|2w-@ML41Y%cggDadzH6IP8*1DrnLSkq(*^ zY0{EUPkYnpOcgqIO+fY z|3LEBodzZz?f(qSe?OjJR;d2Z$oU@(7#SJapFU-RdjO>RKf~{b6PN@n|Ns5=|IY_z znXJE$Cj3VNfByVo`uFc2L^Tlne%Q|}o5v{V0+jmy@6Uf$DMq=9zxV2)%7I@0_mA=8 z$B#TbJpUo){|D*(`>^x>w|gKB?9z<#wQ%E^n3(S0zs~|U9?oEtEoA^{|IdKr7`P7^ z8B`h4YSQk#y7&9f@85ra|N8R_h=A;0f59Y3@YkQezyJLGt0Jy)vGpPg!w-hvfB#7G zOa2Cn0_A`Vpwd78{y@k-e?jpA0{{L3ZD3#!XJFuGU|?q;5&!_zv^a`2R<-~D0000< KMNUMnLSTZG*VP~Z diff --git a/src/icons/flags/tk.png b/src/icons/flags/tk.png deleted file mode 100755 index f3aa0f77f4d0c954de38467b57000fc42f417475..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 519 zcmV+i0{H!jP)neCelDrm-z*RB&I=h42+<>NIkf1rFB0K^h`(prD{YoGmWjY6i?gB5d|_ zOm(%+)TEb!X?Z>U@k`t5{Qkw2U7{u$9^HNsCjyw8cd?*X2b+fP&Sk6DUryyzf;a8X zJ=cFTcgBvE%GHhaNw5gReDFSOZTd?$ii2kk4?jGeiI+3U#roZIe^yhi4aJ`JNv9@a zpb_5uwrE9;A9~ffw{Y%Cap*$p&5?oY_fAdyXz=RCCJuHse|6484O|2j)gWrU?S)i& z<81%P`JvBFf{1_ep-WX`xTfq+C#D)eBT#Qa)qc&_IA<-{*(043PQtcO+LY1t@@)3) zWUl=8luQGhr5&wwiYxfG}TmLV^k!Gf=fanH0Ipm5NJW0VM9hN$l!}B{I96LLKlP>TD00x6Ff5tWOQC zg*7x=%)`t>M8YgV?$zryfX5fpj=gPen9zlmX9cZ=$d@7^B}xgA6^$Ce24IZb-{_B? z-pX*esij8J39O_f@a$L9)#;&e={tTQ?!XCznZ*95D-Qmge;tDVm#IKNLL zO_oz7uLEDdy)d%}xUM_DK-pyqAG6%KKYf0|1lG{nzacThYvYqcWx_jSia=x$ff-(A phSr`8U@rlyI~5f?@}D1j@eP%wKER4);BNo`002ovPDHLkV1ln~r^EmN diff --git a/src/icons/flags/tm.png b/src/icons/flags/tm.png deleted file mode 100755 index cb1b24dd1e1e9a9e95f690980f1515c560faa8dd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 456 zcmV;(0XP1MP)X=9IwZLI3}-t$PYKrn;LXpa-pB3`xVr)fGpkol-_~Kk7}L!$ zAqKEfd$Qcki%?D%st?oNOu6!F*t=cZ+HD=|cN%grka9X-)HWjkDDeB}Ym~Q-cit~l z&g`{6%vWb0zua6~y_w5CeLre++l_Bcx&TB72t`QJqTd~*N!V!}+`F;1eYm%N>p@hC zDoNQyqnVQ;fEWP^J|6INlxL+vj@R{fPw#Bd{rUE*)=9@m6Dd*x5W^6HCyDE?l;008M5xqb5Ca$^D-}gTqFA_M-K==av>F y(MhLV@*tN7cXtH=C}AEL<5`aLz-M3`|KTqS&_O0BCgHaL0000$7!Ag+aiHMC|()$gTVr6Zq+6exGwKkU`=@TrhM8OMKSR~lmCSPER;LYxH z_U2RqA;a#l?7TPc?Q9No3;X;0=gPU_cq|Flde)LLU_*vI<}7n2j=_ve{+`bh0s)_2 z0(Izam&#=n3Xq5*Y`0jiaXJaw3xZSu7Ad;Zq2m$LDGmn&0h&$tcX+r*^db^Tm?k1t`zQ$H#Ez&i_@b7(zlAR8{}~XJE+9W&HDp`OhDw-@pI= z`STw}e%Z8%1!D03mKKJ;e;Hca{?D7sz{vRj{(X=lAo>L)fBpaU3&>`al?B?s1X2w& zv$&Xnh2?)?0fY-x3R3qIME-*60cwESz@Ve^f9_m{{~!ngAQcF+AtVD3F)*<3@bfbi z75{(u0O(4F-+%u9fl9;G!HsA5^9N`H$cF!a|A77U3#8#U#Ngk^W<&h|b`lE^GlGSH z2B0WHRSlB;19SreNCPuC$Qa;?Ftz;wYWNEZMg|6u2BzPC7$haZ#{6aY1JcO|Hj)8C s0@2^U5Cl}r_!TuG8E{1KKUh)#0RA0L-zzQwEdT%j07*qoM6N<$f|jnC$N&HU diff --git a/src/icons/flags/tr.png b/src/icons/flags/tr.png deleted file mode 100755 index 97c147b8843606add8ae4c828df90f8c19c5d588..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 365 zcmV-z0h0cSP)8V=Mju2P#2P&+5LRq z%t9iBJRZwq=lh#C0pzEW=lRbLNEnSIj*%pyt%Hpvwy;*Lg)#W`y>B*Iss#Zq7ljht z=_n1`Ev{GMA_Eg4igXSt6?Gti+8*8SOS4H_t%mW~;UaPzL5xvChPf53j@7EP+n7!< z7+}3d7-F%&>zngQO%$79q_1!OegA-(?Dsr79J@cAMCd1GG>T|hohNME?H00000 LNkvXXu0mjfc0QZo diff --git a/src/icons/flags/tt.png b/src/icons/flags/tt.png deleted file mode 100755 index add5c9a8e7e7baba93173595d8d4078d4368b9d8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 484 zcmV`pT)*-gXD0B7bq|9{T0>7&v7!oqMk1OU6;K2Q|kc}S%UfPc5mvbgx( z>)ky*s;X)j#?8yiMm!G7%UmvJ#n^%n!I=EsUzv;zRF$h#R+pB7u~@g;?f3hG!N9w_ zOGYD-N)Zhaq!CS{zd474DF6T|mEhy^aBEA7L^_>LyWRE#gFc=o<1x8UGR6b|AqLRH z={h_=0n$#KPB9c}wOY+)^YG&0^7xoBiNq9ui2`7qxlE^NNOZZ}lGJE4>h-$Qdm1@E zV@y2G0E~Yv>Da7Eqs;+L3%K3;qFAfds@2M-AY2FhjETj#KTC+YqzRaGGD)AqUhlTY z^JcC!*MS@gQE`&Z;t60iTgE~rNo1KaQJ-&}=S$^su~=N$*?G9Sg4tP66b4ujhPgS@ zr4E>pT%iCnGdJO|+wZ6K&_=r?DJ+VHATZ$jHZdI}Ooy7!8+&_4g@Pj*r9nkeWLZ{U aUw;6>o?jX(|Flh73so85u>Tq$G-0eB&i&|>l;85@9=7}&9{cXeJ@O9@g)A&@A} zG~+^Y*3bqH7o0{7r$?EwZK9OIY70w5{S}0eY&L7Rj?+1|bpDbxa$HKhoTG+NNUWqn z?lg~Vy-rSrGG*FHYR;J+T=v%td7WGerh5bxoNCn7*t3@GKYH^558@TQXx;A~)7eFZy&kJC$QY@t^{5M9+;>m-_EgNV_h3cYy$8p!$ z25Pz-<%yX%VT=*;Ds8-nFFnS`CoNf*it+Cm_FMZR_rrJjz`^t$$>;Mnn@vyh&vLB5 zQ`}M}lOa6-qq9MQwsH5YfSe1B%+*Nio7huQ+#V_^1ukwPaZLih9@R>-fMGXyJ77Hu fyM@PA#ozD+ChJpB+I?_*00000NkvXXu0mjf|0%rw diff --git a/src/icons/flags/tw.png b/src/icons/flags/tw.png deleted file mode 100755 index 242fa9ee24774c4cd18ec70bf87064c1f35457d8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 330 zcmV-Q0k!^#P)m zxq1F9OMivKTWp>T8Od1d@$GaU@E46pN#jmwyO4eard&4tXXS*Ez+o5=Vm1IVa2+2b(e$xez3^XwxV^7gNLf+=22z>W9nix>C=h`H)D#X5G6@AlkQE6D#U(@(8K{>1L*l>d cZoU9~0ZCJ4;6A`DbpQYW07*qoM6N<$f;@DD{{R30 diff --git a/src/icons/flags/tz.png b/src/icons/flags/tz.png deleted file mode 100755 index 80f0bda04eb51322e079f7746bd169055c2753db..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 509 zcmVQznISXmL|BYnIj$e&7_yFs-YG4uYR z-W~VgU@-G)DqcldS(n9Ve7SVY@!ctU`iz=Q4z*D>%X<#SUwnoGpiuE5EY>FJejbQ$ zWrlNCcy^Xr*01GL6Os0wg|B~XK5_ZDgFsBV$xFHV|K-qtnxxjqa3}rzCKvKt`A$TfTuP@Wf-C!?#hIN~-&~>qlARu84vUdn z$GsuCb6bkjM9e~zImCk_-BnGTdpY*1x`_Z$sCkIE_e0RKj9%kvm0RN7boQdf`+J^$ z-8S_hQ>GZ37xQ8e0|aj4YK)(ha5#}j@UE?zI@}%#>&t}$-lQ_Q00000NkvXXu0mjfX_D*n diff --git a/src/icons/flags/ua.png b/src/icons/flags/ua.png deleted file mode 100755 index 7182cb3878a9a92eb3dc193c6083be75d3f1176a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 303 zcmV+~0nq-5P)5poq_N6peG4>`&g zr;RUlgya%wQm$gyS&p4I%A*|RC_tT|a!ZkN?tlNWXUZY?ptD>rk1t1kmz+|FltKzQ zN-0Ind3AEc`D3eBSl!q!X5h5L9{+NhuHK*4U7|Vc0eL7L*pPN6bcqFN2kfPP&Y+-3 zy2Rv!v)wizS_??nGH08TXq#swlr!1qZQyrA06$2FZs;mH{mK9U002ovPDHLkV1k3k BflvSd diff --git a/src/icons/flags/ug.png b/src/icons/flags/ug.png deleted file mode 100755 index 339774547188c38fdc90fefbaecd4df57991ca8a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 387 zcmV-}0et?6P)Nkl*xb1)^ssUJEUjtC(s?4k^Ntr20qI3tMr0wnfc4drU)jl^8 zNSj8YXw#rgJM6I8+N(d8-@DOcv=;``P88v^!qN@`~@2sL`T}>5dZ)H002ovPDHLkV1h1?u2TR2 diff --git a/src/icons/flags/um.png b/src/icons/flags/um.png deleted file mode 100755 index 714556bfa9318b2214f2384caf8ee17dc2940972..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 454 zcmV;%0XhDOP)Y5S{zLR`d)6^AFM{WjY(tCRP>}7IuVHn;#e)_)edERI=a+0uZyId|SB-ma}J1&<=keGmoKwPgLgEK_emA;2T zpc;$s^&1_5(oifIwf5HrVaqHQmZ~k&Mya2jk$ya=Dp6InexsoS0!Xa2EOMo4YCzS$ zh!#q=xhaDnevDxhX{nU)@SxLnE4hVg(~O(6EW*pCxl=F>Z%wUI86NP)xRA7-e6ygd@)Jl5gwW-kBwUG6BQZO@qIF)@Y`t>GupU44SQM``yC#%5DrXklAwW5wYVv(ibz9|;*L zDyLj;$I;T@d(*p~PLfO}U0YkvIrp6IgU7aQH~3+CZIQ^&??`74#&$8Ag?wI5?21y< z(=&!1a9%d@YU%73Nu^E$fyRR0|BzAd)$fN8oYHE5GbvT|*KzXq^-GE1eI(og1tuyZax-I!s8vWfOw{0000(DDvMRls8I#q0MHuJlm)A#o0=6Kxq zH6n&h0TxRz{vvSDoKu94%fxu+~5x~aDa_!E3x&QF%_SX2| zN55iNld!6)3MtN=KCyf>O&@0Svs-5*{ypTl7^~GHqLlRd?KIh?r#G*kcaU&JJ-S@D z!ofibml23~w)-T_zRVp50FIJ5j$`2Nm;r`6X4&iy%#)O<+pimw00000NkvXXu0mjf DvzEF_ diff --git a/src/icons/flags/uz.png b/src/icons/flags/uz.png deleted file mode 100755 index e387bea75f3a372a7113f5970557830e5415fdbf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 410 zcmV;L0cHM)P)0aBKEzMhkLNpplTPJ~w z4d|)S=q(pi+nl13Mgd^IR?yU;NSYvAqa>-Z367TMIZKMl24W$enT)h4a09;|i6`-*Y zgAvg4X(p3NMhB;GwJS_}?&zgThiu!`wjB{6DFcG*zci{%gN`(t@$g`4XXnN7yj{C_ ze`#q&Qj!S!#9b{~#VU6Gws*Ms{&`ztfbFd>PiDV9lT46dx=Xv*#im_cXO~ycKYsM| zXm@w~ad3O%Re$h6QWjuzdfJ_S?r0o~M?YTvoW8!cbZ<2-eR%hFxN>EoX|o8pTE(En zza_|4Y5N4fECSeoJ z2xgc_L_J3IA`&71oEZ*n0PgmW@f+wj1c(qpLWF>Gw>E|4|KHpl`~g#zMlQLeqM!f( N002ovPDHLkV1iZGz`pr%TAJ0lMlbiddY#KNqN$WZogwYAQ>v!)ex%() zF3s@HCBFW~w?EXNH#iOVhLlQ9mu^q<;Z1J6QxqTF((odg>U#bsNsv;?D&D=!ckwNdlVINhAa95spjU++ts%7zy(0}hstsT z0Uop-PDf-!1dIlF4iNYZ_~)y2xL@~d<}|Kt00t5O{sB*WTJ7NGT07S$n y6l`W)FoDP=IU`d;1Sw{Ajn>Pyz~A!U$l?os^jdVGonS=(0000%{de?XX%nmhgP6cU1hDz}8^K)P z^>B4h>dm9Dxuxw+dZ5r{|5Q6!_;Re7q#$4shDz+BC`ZJ>oL{?m@KE+o*oxQuzJYZ4 zz{aP|*dd0w66Wr$?=|Q^=EppD;~2! zlf&iA`IASXG2nD`B6I}!c(J3HQT$~&PK^^=H z#2|vUx(U`u8lpCR3D@S*M3TGQ-IL$Xl1agj=yW>x3lRX?0f7ET11KimsOE%FbdG8q zd{NRj!_G5^P|w_u-B(b?g_fg16!l6CC#C^PL}7RPA=oy}U5c7D;YajMRm((I*gPG! zi(%jCh3-Hb-Dr(yQc@y)nS**SSZ1om4Q2kpNh5X6_m8)o=Iq>aYvkkVc9@H2%*5?% zHlY-Yzof*<`ZOtf!oES$YdKqAKjg~`hwI;cgWr2zXeE!u({qc9xn{GkDZtMk-kNi8 z-=R|gJonbU`Mqm*?_1ZdZascv=yKD)^J(Ge%#0-?kBF3fA=Ye0mZdZJ{F6(8wgqa}X@_uKHI+qsEC$}Xh6r>^>W zY%B?&R;y}61b~?V=-C(hcb63XM1K5rIJz3qfp?|rg~IgIRGgWG5K@wG9LKh89s)qb z022j4u(7mc`~E=J#pGlPU;vd$MKl@>`j?cFhyX|_X$VA;2t$7W=;0>w{;*qE00000 LNkvXXu0mjfn6LFV diff --git a/src/icons/flags/vn.png b/src/icons/flags/vn.png deleted file mode 100755 index a2cd8a151a29edb2d6cfa8b65fb6ef3ab1f774d2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 324 zcmV-K0lWT*P)?3UlUge24O zA(@EStcsK3)>Lt1w#`EkE3Ix#!Nrg(%xUb@}F4W$s6szR2 zQ%+h6xvhSWEne-2Z~bYWnm0{CL*- z9tYfu9Ihlar3P7~vf9=BdFy2xMLR|fr?g^R5kL-wb0>V;7A^nO!>777jY~7^iRP4>$;?SNbMAINTM_Eo zZ_jb+qF%mLUGu?BIa35mq=-gDD$xx0b(@?0C&&Okebw;^E&s4~OWjU7bG0_3Xhzb8 zO>%U!di5F^!1D!uShDeb>UMCUR}D_v;0WooFcz8{3sp4OAiO{ZAgbMBx0BBI{@8@o z2aPo?j6n;sn1Tvda#Y9w_U_Tiqr0Xa{oQ_QD_f+K>!~6JRiuy?_i!%`Lry?@)9j8h q;4m--EC2xru+?t`2ml~pBmM#LmrWkV*bn0X00002oU1}Ws1e;rb-STV#vPCC`Z*4DDn-yHf-=J}5OCLJgzR@Zug&JqXk^!FdzV)n zzk&`gXLs?V?XR0>$@u2!iR6OKW}FZ_4rjAFmi5+b#!WL;DmlF#I{4oopF-K(+;IdY z=%B(Nz#9{SNj`hMc)kAJ??>`^@FMx~@e&iY6YLsOipO@fy4z@MmCKPr!8Xl6G`bW> zZ)M9uwkN<;bUL*y3tuIpz_>r1Rsy0NSRj#5D`I$qmC{?kvPHnTE*HRe3-G)4FU1-r ftBD?B4+8uFmO(vn4wmcq00000NkvXXu0mjf0EN3> diff --git a/src/icons/flags/ws.png b/src/icons/flags/ws.png deleted file mode 100755 index 8b40fdd2245afc61aef7bc83c5a48dc4b4ff537f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 352 zcmV-m0iXVfP)<}^1Z0OSM+p)?r0@9pn=e13PkLo&-KTA1yg0RVEqaupR8H>dag-rJG_Oh%F6 zH=O_}0(rn4!nNzgdj`sxN>8@VdzLCiAS2xj(n4r44ap@Xpe&_|^92?#5ef(a2`Evh yR-J?bM35N?3CSgdkTj`OoE*;{nZEt6()<8^hFW15T+?O%0000NklZiiv;--=Azwo(oxFYI5Ts99+!ul+YZ0ai0%qS0|78UO$Q07*qoM6N<$f&~Y8 ABme*a diff --git a/src/icons/flags/yt.png b/src/icons/flags/yt.png deleted file mode 100755 index a12f24d012a2ca3dde5bd9adc8b640ed6da1082d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 456 zcmV;(0XP1MP)-=?UMz}Ke}`AS_2?fE#EXDe{VN_tT0y7^2-;g|sl>E2 zCEeZZIB5b7yTg3!oA-tlVHlFsjKPC0iKH})5%g$6V4MWTXw0zhx-NR?^+=;Zayg)s z*fzv*QZxpF0IF4RT>$8Iy9pp^0FZp1)M|hUC5VC80B4Dp5-baml+uJRdkrucjWi*1 zxm>f^34Wyke6J6y%R>}48hM__rou9Y?{+)zeH^{EUVOO!>h&VRKu3CScj>eBs+5^s znBUyo(prmj&2bnO3I)rtqexgSKxEp3zmXsh)G00{$Lj1cYUY~{}W4PEI~MREZcS*trT{%9gqQ&<<*rzFz^<=nbVVaTBL-a!hXMBEEN&; y&*1xh_K{k4IvqXzU>t_jC<$jVA%??Y3ity$(I3{10Z2gr0000igP)z5ln`N;fFcSnous;yVHVUyjOtX>v6E1S zP(?sc#%csBpcZKp$QDxsw)frqegFIdV#na&;kiEsH(CKcykls*<#_wxNv}`<06_nP z8QrsF<9DI_qN#Z7{hP$=x8~gpgd)r_<|vV4b`4jjrp%Ua=s8ijlB>?o|M^h*a%tb` zbz#-ae00S*N8~Iyvd&sZ6zS|#z#KV?YWXFg5hBEzqEprPl2%M@@ zaiUHYDNom|H2@~3>zii73%kSH#ndmvujMAhAsI`GGRZ%P9Cv8jlOOjC0A_hQ9h8@2 z7mwC%{Y;kCt8-YXl&p{yOF~wOgqvgqB^UrAd~kpCz+SyyOcYn*bq?66=eH(ANr;45 ziImgcDx_fm3>=DV*c`c8@IP0KwZWZTSN*8JIO~U15pk+c)ro4_Hyz#Q%%d@^?=k1I z&5HpePQ%+yy?PvfHo06XFA%9EM^>4YSu>ebKL65aKQ8BeFBz>% M07*qoM6N<$f~-F9a{vGU diff --git a/src/icons/flags/zm.png b/src/icons/flags/zm.png deleted file mode 100755 index 69dddb861f379f2b25f433101336b4e8b9219161..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 359 zcmV-t0hs=YP)C-`wB0okWo>wPh>(KKgR?;qd3L71inc4}Z2W5OmtHJC0MD|i5NQ&~&zI1g(5Z&iRTK$B0x(cew7#}JUo!tY zay+*GF1>l&YQLT=0%q8I>FB~&0fnn;yajdv0N;RDz!S}{cT1avv$FsI002ovPDHLk FV1kYKqOt%0 diff --git a/src/icons/flags/zw.png b/src/icons/flags/zw.png deleted file mode 100755 index a795223b7c0ace74a491fbfedb305b12490a18da..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 462 zcmV;<0WtoGP)68a?)PvAk-&v}=5uoEXKP|^0yBUD4mhBF7C-?RfD-c9(3o!O z+QyyHleBOT^DqzfP;)h>g__e`HF)Fw^Na$Dj-~qTH?Nkar@N5|SOfVqbzv?3+&pv%W z*4;JI$)Fg;gibMXUz<%Jm(I+{=P#w>tS)}-yq&+axKeL4_*Y1ZNdJW7k&12tIiEOf z-`+)N=fi=*RAc?h?1O`QMmohwr-afet}NI18psZ>UR!bZnB0DReg1s0os)#q!ARnX zo+J{Zprw)?1u_62QMxZ)E-b8WN0tZ)@5$*~0uh#yow|!$E|>pw+K)DF4o?m>e^h(o z-DyE}b^G7MB5e67^48AQ_@QxJ2G;vgr5}5cd+jUu2LXdh+vpb$2mk;807*qoM6N<$ Ef-5T3)c^nh diff --git a/src/icons/loading.png b/src/icons/loading.png deleted file mode 100644 index 09376599d028e8986ba9c745493c08406443ac2e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 178 zcmeAS@N?(olHy`uVBq!ia0vp^A|TAd3?%E9GuQzsp#Yx{R|W}&nKNgmrKK4g8w16* zZrxgBbMzXJ#aI&L7tG-B>_!@p=*$oR6LKvBw7bx6G?P21vU}V@L W$o+MGd;fo+$qb&ZelF{r5}E*Qk2(4P 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 9ec69b38a4163b11693a871669b97d56e8c96d9b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 36987 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 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 04e772ab6d6285dd836a5ba536e5a2a9a2c1b2f1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5650 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 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 9b6bc538ea497e6d0e51de580c24eb521debb86f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7901 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 ToC-=%bPp)JRDDtO9O3srl_jbJ 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 c9f5c511676491309c782a99c3e1abc2c98e08d8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3110 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 G>Hh)PsA>cN diff --git a/src/icons/qbt-theme/configure.png b/src/icons/qbt-theme/configure.png deleted file mode 100644 index 73ae9162706c7b1d39bdf54ab61d6d99bf5718d4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6559 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 O3!tL-0$w6-8u%ami)T*& diff --git a/src/icons/qbt-theme/dialog-cancel.png b/src/icons/qbt-theme/dialog-cancel.png deleted file mode 100644 index 04acdc1a5c56f94b7c81e3ec693c21d69616e2a4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9288 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 a-(yUkcFgFPe>cGV4KUO*!8YhP$NWEX&wr@^ diff --git a/src/icons/qbt-theme/dialog-information.png b/src/icons/qbt-theme/dialog-information.png deleted file mode 100644 index 3cd1f75efea538a3caf293d191b9aded555d43f6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6785 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 diff --git a/src/icons/qbt-theme/dialog-warning.png b/src/icons/qbt-theme/dialog-warning.png deleted file mode 100644 index fff63bbb5f7e0fa419a3a274bf9e7b333c34112b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5776 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 yrpE!iRcf9t$YLT*a*#7{pjKa16 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 3caabaeda9f1a43e49054273a22fd4de8a2a3e79..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6164 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 VF>DlQr7yf?X=!eQD>ili=YQDZhr<8> diff --git a/src/icons/qbt-theme/document-encrypt.png b/src/icons/qbt-theme/document-encrypt.png deleted file mode 100644 index 0b861f187e2589c28d86b98d8a2f3aa4e6d7234b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4075 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 VawyPjgQNBubg(^TQ)J~8`ERw^i+KP5 diff --git a/src/icons/qbt-theme/download.png b/src/icons/qbt-theme/download.png deleted file mode 100644 index 40c25f154288205b51d28294c008e828b67e3d46..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3607 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 n$uWnA%oG{q|4(KJCyXA#d-v=fi7bG`g3 diff --git a/src/icons/qbt-theme/edit-clear.png b/src/icons/qbt-theme/edit-clear.png deleted file mode 100644 index 6adac3e2e5489c350c9fab74fedd7156c171ad0c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5123 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 diff --git a/src/icons/qbt-theme/edit-copy.png b/src/icons/qbt-theme/edit-copy.png deleted file mode 100644 index 790e2f231510f67897282281afd150d6e7388d60..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3130 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 Ij6LH20g%?K-2eap diff --git a/src/icons/qbt-theme/edit-cut.png b/src/icons/qbt-theme/edit-cut.png deleted file mode 100644 index cb76e59cf5b42dbc62b2168b8dea744a3eee8a5e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12221 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 Xh|*3>y&Vy@DnLP2Ri;|XH01vQeq)TJ diff --git a/src/icons/qbt-theme/edit-delete.png b/src/icons/qbt-theme/edit-delete.png deleted file mode 100644 index 04e772ab6d6285dd836a5ba536e5a2a9a2c1b2f1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5650 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 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 61b32d3ae67fbe24e5bacf1d3ff5818965e4f85d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10856 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 Teg4`2?(H`1(k#9i& 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 Ri2Q2_&{We?ExT(O{6FQPiEsb_ diff --git a/src/icons/qbt-theme/edit-paste.png b/src/icons/qbt-theme/edit-paste.png deleted file mode 100644 index c95c2fb98699221928936dd2b0766d644765fa45..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2521 zcmcImdpOkF8eTI-dnlJ76dGX+DPcRzX==8g8kcd&Y-*=+jR>Jk3?rFopB#4;ZPdnS zRMU2(lvEnjIK@69lKT*C8krflF-&gf*WTxx=Q;gz`sb|YSpR=@3+>o-e;v# z_dBa7>nZ~PR46WFF8~m*i2&$z@ZcNE4TT33Z7<~j8g6INA!+bj>6FW18UU(IpF85p zc2zwXOQMh+4kY|67DQ(Ktf=*3=0mF}-ka;h_s}?I<%rx{p%hGFksQ*7^D`eb*D z&^oS1C-Llwx2ZQ~+g2_YYd==FaSVU7XRtvSLMfP>wn4S#g?5dM8CSZE)w_k7I!8f? zMWVqsZN!EZk++)tCf<#A`rWzyz7O{EqCB;^lEyvTmPyQK zwvofPe_UT;_lDv)>}0ZXG%qjAL)2ew$#B_XtK6{o@qESN=*t~X-Byx&oO8Jq&lLji zxMkF*N6;qbbo>*7g?im_2NS^HSxN`t`zUH$Z9%y z%3;9^1*tT|w&%>0lH0kNWBh>nf4uFp@J^9xpE2dTF&o5v*5?jM(};b%x$)u0Qb?+L zrb>o5C7&BLzCjA>wC51mNi}NBmc`Lhowl_eU2ZY}`kVi?Hww690g#RXt(PvW<;@EH z&x1usdY%~jrl>>jHLw4hMnN0aSHK8>Yuc>uzvhtl19=Ksh%f*)ww2-qRlg^ae4$0$ z-Po~yM9VpKo&xXEdp=Z6<29r#yqgvtdfFkUNw1pE?tgQ2);l2IuCR|P#Y&wn0~dVp z&ihg0K@A&j_lvR{sKzxZO5j~H8eH7;CAF>ANPu$!%%=b0G%pK|e^q_3r&yE6iADqS zXXOra<3q;R|^GI7~Rw@1hJk4(V6>Q2yLNig7m z4o0YpfNC(TJL=$o0jAIf$z*Ir()I$X0XeX{b2++^NSmPKVY7y;ZO&DP@aJUHe>G;O z7Y7qw4P@&Y0^7jOA2sQ@etNuM{7;onBz%>awg7-LvReNX1(9ZA1D(*|VHB3#(+yQIu(Kf+tgVT7*K9)iP?l*xoNJCKr#<7u!#Frhjzg!C)8O4 z*h@yK8UvS1v^u~QkUqo5b6^q7C%|Tc#|s#KmlBc*BSS{sC^WFjmZw9LN6inz_9+xE zmuaV(^B`LI_uzSD1jspt{SJB%E}s?_FlKys5MTxi<50e`m9m4CW&V49sDUyM{IZ>`fU?;P~Vn&Ki&OASKmQ!9eKaTm38U`SBf*vVm zets%@5YD+3uOh86ZP0zp0)XW!yP#FkQ?fCx6tI1~lf64Me{Cvf?Gq~o4Qu0o*#Qns z_*kfNJh-#}%Jv>r@*p0Vbv50wSQ=ch?AYx(-ldasbh;>wj{+BL!jDQ*HJ%Vh%@EMY zRq=Rei<;AvnP%QjpN9;7QbxTSpgtNNOq#RbxU67h5@PqZo-5>_fFWLj9Ui?iz@g`- zAAWD_IE({nqvAaO)$4->8CWlD{R3ep3Ixfb1;kypw=o4Wa?G}GcJn@iWwIec{Tf8; za5jlLHBlral?{5DeZrNlBR?{I7(>K`yLT?mzMa&mH5Ko$75^plw7Lb#r=;%}7AX*$+*Iek>i^}u zH>&XN9C!K}xOwm_Xf4^cjAw>B?omki14;nC@nIbVgnQLA5cTbnxzR~Sq<$bqXT}c@ z}{?J6kleq z^ykyHurBH6t|xTs{YXT&~Zi`*gRo<%G5ua?WdZ8TW7m+ngp>pNZ<$)Ufyn>uk`sAA&? zA{xuJx?g7qw{Wrlb)T*;{HmN{pbZ79-ck=FmALv+sF)TcS<0xV0M{4p_Ar4>J6Gz3 z*HG*bVz)dm9Rnig~si+cQ_3niAXIb}xWDXbMc`2a1DJ?&egE&`rAw zmx{%dwMOIJFZe@?HC%pS(X)ekJHK5Rz!mHA6nP_(+{AsHO96{j#z53 diff --git a/src/icons/qbt-theme/edit-rename.png b/src/icons/qbt-theme/edit-rename.png deleted file mode 100644 index 376c38df7588304429afb1fb1212e77447871418..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4721 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 KsFFLjr2hbx+_P8! diff --git a/src/icons/qbt-theme/folder-download.png b/src/icons/qbt-theme/folder-download.png deleted file mode 100644 index 40c25f154288205b51d28294c008e828b67e3d46..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3607 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 YW{34MbZKtD_H{s3Qc%sA-(0E>Hzi2wiq diff --git a/src/icons/qbt-theme/gear.png b/src/icons/qbt-theme/gear.png deleted file mode 100644 index 73ae9162706c7b1d39bdf54ab61d6d99bf5718d4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6559 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 O3!tL-0$w6-8u%ami)T*& diff --git a/src/icons/qbt-theme/gear32.png b/src/icons/qbt-theme/gear32.png deleted file mode 100644 index 73ae9162706c7b1d39bdf54ab61d6d99bf5718d4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6559 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 O3!tL-0$w6-8u%ami)T*& diff --git a/src/icons/qbt-theme/go-bottom.png b/src/icons/qbt-theme/go-bottom.png deleted file mode 100644 index 92a923c854b3bd17c67a121660f022d5f83fb4f7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1905 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 diff --git a/src/icons/qbt-theme/go-up.png b/src/icons/qbt-theme/go-up.png deleted file mode 100644 index 80e7a7c52353c65bb0dd3568cc19c85033dbc42f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2733 zcmc&$i96KW8~=XEPQzHPHL{0mDJljtX)yNX(okI8A-Y*gYD%_oQI?^m2-&4F<2Hp1 zVyu}N6bgm0{V?3PV;L#S;5Ygw?)yCFdC&5E&byrRdCy66ceR%gRTKpPK*9lq^aKEq z*98G#L7wuvUKz|&hoWp8yo7lYD;$){8;e{+`9=Z2;dciO%+Wur1OTFL4#+cJw+q?h z%qVY`3Tskq_VHPPj3Tc}9PV zzc?b*l(OOFmgAx#M{qW=o{~2Ywe*jq<<5$%unZy{;@ikZI(qtCMO_-cx=XL$$pby9P3PULW4TDG@FUQ>zJ03Tw zX7nG+(XZb1+kz$l7+lSbeo7`h9y}YDQ2#CVy%ZXUB#zNu< z;N?g|;2#!8;6Vpg%Jsg`k(1|n+1UvTX|J0Vl{C)nF%|n=A+q_}&-*|M!D;E(D_)%#*ENoAx#s4iI+a znfIC#>_BlB&W& z@}Kov_M4U{PVN%eY7G{yfOSsyGRd)_uN}w@K+b7rIz$Z5FKbbfrWfS_RTA@4wc7tI zglsD&v5y-)KNe&**eieu7$A0jW{RC~*2aC$QkFU@Z-g#kH#4zvT)1GHeTUDUrFUaj z!;{e4oY5v;441@lZqB)Ih4jFE$l!&Eyzb$M$>t-F>K#N1vk68cO zo@-sLqPch)^f_1mEHKdzrIPB-3pM`8scJue%F7qz{v1 zGLOF#v7SaX+8@L|uEYQaX?M2P@g^ZNBp15iPTxo$)YcC)$TMt>QCnpFBIPmMMP_^) zE@+Zt@>awVY5s<-)?u)WfJz3t*o2qFFX5D0qy!oVy)rUjHRW*oRTb(f+n^+8p| zpaS9uf*Efj~zWj=R!` zM324l2A!kTe!+u%1z|!WO0Iywo7m7V&7Af5n>_)_G{!ycvR_|p2XM!+k6%w8a#!oE z$9`}MkZf81g+Lmw%Ibc3XXex?UdH4K0a3Mpc-cQ|inK)W3?U1%;p>XmbKf5g3QsZrEq%@J;94|$Jta_*21Nd$~Pl@eAI+bE+%}n?_{SHFO9|ML%XAP zjUH9T{$<8ab+L<=sJ-~t}u4mCcjLq)G^o_aB-0}nCJGuh*tFqy!Zy>KE z68o`+HAU}M^mB z7H@}zG%nD-lNdb4yWh5(t59DDkq_wl_E#0Lu#mMR1_aTzl~&Pn9fQxv*4 zWhn8k#Kd~IPW7=GBd~z7@m#0H>Xd=reP$nD44zOg9r5=D8=U|ThGj?)EJ649Iih2d z^sTsCP-9wlMFBwx=((>?T9qJF~4Nl67dr=(`*&iE1(anHl4U)QRm&StBk zJqa`s9d@pi4~ewkv{uRx=Xs|0=?Y9N)^UR%qO&{3dFj6%W@}8-M9vL*S{Xr&z!$yn zla=MIuZslsLh$AmCT`6A@AQ_3vAqH-|dq zNziwG;F*1%m&=rXLSN}UZo@wx1R3?=969X>CC) zos#vOV|9J^Zg0j<^p}Cf~4iQ=sW!gJ1lg^+f_lUvM@zM;Zt4h-smV+bIDx z0lIKUr0sb+ohI06%ooW7=hXw^z2iEta>$Hy!~E?CPT3P?sF3yEW<@BhKTH4%JiZk3 zTf}&D3a3-f+xIvDZ{<^axHJdh)PI|JzzaPEdpQxCKkZ7w3yLzPs_FYGI;xbHZHIDSw^pZB(YoayY z7^NYZ2Qn;oZ`5#`zlpK#xe*zkj$f^rr`d-J!j%-(!WQz=+PLz@CKd@0*1Z*?Wxo8& z*mf*FU-aDy-_KY0nYO*HnQ>CeKgaFHla;CtcLXRNMwZd){)Ii|G_sZ3#N&$pCg;_t zV6^!n`6Q*f-@v2%)uot0LrpGT4=L*a+Eb%gDvDP0DUq<-WFNk8@DKct1fj`=XzvM^ TrW!Ue4qR}sbw!eGF8=j@{By^? diff --git a/src/icons/qbt-theme/help-about.png b/src/icons/qbt-theme/help-about.png deleted file mode 100644 index 3cd1f75efea538a3caf293d191b9aded555d43f6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6785 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 diff --git a/src/icons/qbt-theme/help-contents.png b/src/icons/qbt-theme/help-contents.png deleted file mode 100644 index 5f746d5689ace1a5ed541cf36a646294179f86fa..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4336 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 diff --git a/src/icons/qbt-theme/inode-directory.png b/src/icons/qbt-theme/inode-directory.png deleted file mode 100644 index 35742e0f6276e3eb2c828c0d89d2eb53d4fafd66..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5721 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 KsFFLjr2hbx+_P8! diff --git a/src/icons/qbt-theme/insert-link.png b/src/icons/qbt-theme/insert-link.png deleted file mode 100644 index 15ce0981d04db6b7e1bb40c77226a4309dae6e03..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8920 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 Mst&S38TI0S01C!)iU0rr diff --git a/src/icons/qbt-theme/kt-magnet.png b/src/icons/qbt-theme/kt-magnet.png deleted file mode 100644 index 3bab5e4990c329d3f76bcc7e2d2d80a0396a859f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4391 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 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 87ae05fa91a1739a111bcd3c714e83bd31306950..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 406 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 M8s8}V%PHjl06DaTR{#J2 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 2641ec4ec1dff1db7f9b7c8b51644ffa14453e15..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7078 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 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 237f049f8c4a10cc9f8b0a79b47942c5635c5bbf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1294 zcmeAS@N?(olHy`uVBq!ia0y~yU<5K5893O0R7}x|G$6%N?Bp530R%N1DIGvQXMsm# zF#`kN5fEmas?8@2RI|a;#WAE}&fA-Y-E%@E+8%yCqqityVTY3AhOL6G7hMFKGhKU= zyj(YIzP+ISkc7yV&ED$X7f$KLcI_|}6J(JV4dM93EOKXV@-2)pJcUtm11?(37or?b|7UDY1-e)GS`f8P0Px5w@Oa`e%ib2o#Z zuU^%^?`71t8S^9iO1>PqUH*4t_3!qpx1ty4OFjv@zrwt1n}5CauL)Y!UtYyucdM?| zs+KwOhUvo@@Aq=IZpYLGhW7XEOI;H8_xh{Z{%>l&-8--Re#7z5;G2&Zh%M%~=upeg5TKs;-qN7EXd3W<~ zCD$u|i@2J@^x^8amG4(wR|iTh;1;+0|KQOs`K`zIwY>o+!BwxmTfa^Tjg_iBp7NzG zH9z@d8t*Ufoc?T{d?Ul`fHKItr%%h>(5D7*Cji)go3d+RH2Kbx;V@BY6R+b5Ra zc)V)mo5Fz2zt{poOACMh)n5Bv?ro?wFbgjFp8ECQ$E3~n_O1N0ZI^95?s)c{^a1-V z%j0fZ#a!(R-O3(4JN^vcqgVT<{rbN3=DBw{^ZzA&vAv$iPh1%RRF#nQkLksQpFL8k RKURP=dAjWDvScSxV`2&+ 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 UVAuBQ=Rf;a*mD@h$;*-d0O;oqqW}N^ 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 225a48651dbc54b556cfd104de65d59a507c3cf5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2866 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 diff --git a/src/icons/qbt-theme/network-server.png b/src/icons/qbt-theme/network-server.png deleted file mode 100644 index c5d98eec8c69ade9cd915701fa21a87723f362b0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3151 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 diff --git a/src/icons/qbt-theme/object-locked.png b/src/icons/qbt-theme/object-locked.png deleted file mode 100644 index 0b861f187e2589c28d86b98d8a2f3aa4e6d7234b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4075 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 b;>{Vh-Qezu^}h^`sg|DZzHWD2B2xbcQh!bu diff --git a/src/icons/qbt-theme/preferences-desktop.png b/src/icons/qbt-theme/preferences-desktop.png deleted file mode 100644 index b19dc0b2eb1070adc48eefb21bedf887981e87c1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7108 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 diff --git a/src/icons/qbt-theme/preferences-other.png b/src/icons/qbt-theme/preferences-other.png deleted file mode 100644 index 4044871c834471d6cf5e6a677953e9be5dbe090b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 11027 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 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 c0c94c917fc44170a79630a885e863f1b001d0f8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 13849 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ⅇorC1j18?Hqj%Ar|i>(^4c; zx|Mq4LEL;|C(Ze+j9-vk_Hs3dEhNL7eHnZX)G{Z=HU*i3@_fS087|O15}s&WUpPoM zWGzox&St})`RbNxIKCT7-uy5#%)Id08B!_@yIv+b2zBR;>!Em;NZ4iVR4g$^i=wD(^aepob)xiN`MMc5U(c7uu_w#$) zgMA@zZGHE>zJy8?BUz7rNo&Hu?##+GQC~0|H2v4JkyNwm6t-_oqMA-4^2tKL_^(8o zO^9oafP0`!4M|5Xj4?02Kf20@Qai3=MtgS|u_#AHea&zP2-p$J_t0Lc$+-wXaE1O9 zS=#q42SUrK0ge_LZ#CCo)I(L@3gO@k4(6V3q@U%k@BX<5CD4-Q%XUL)H;hQE_-f1N zpr+DP;Mx7>d77qv&~vEm$eXW|5@5tFzGhUss_M6=X(Il%-~Fqq{GgRPKYTm?&Jo}F z0R?1dpK6oV#@*DdnD7}n!Nw`8{H=q!6^fR`oQy6k3K>cXz8pWlRatLKd&W6GneTnT zqM>JxT(-a=T^)L32L>Ya)p6A%UI~YcOdg*U*?+W)a^C|oaLWsXgHujP+UG8JZD7py6EzOOI<6pMJX3RE*VUASJ-4R z^dC$KBgyG06Cgm)E_a}y@tMVKW(omfrUQJFAa~r({sV~7O6u(o+(}1qJB#L;c{H{@ zV37?$Ij1AX8JCvqKv#@x&JiNkq0ETaqbSMu^DZ4mr8Y93uWAml$+OZ1$d)I}_xq#x zyGX`e1z5jc2iL;go!jyWsP%5`U}U_&Q)V2=-*{UuW~$3&%TIdF5C5owvvT`)oaMpH z=+^i{GmY`-M$%_B@y1^B)mQFn+Loog65JA69gLBi<(}haf6euu9$EU(uVm}>%^e-1 zUC5WaL{IwHxi1`!-{NOuo0n^yI?F38Upi(b*|8*V7JnS$_iC=FbL9EM=5VF_&4O=^ pL#ZsiWWpZV_}|vf|Fo0tPLD%`FH@UT^2-jOPw0m5z=i;+@}KxS#nb=* diff --git a/src/icons/qbt-theme/security-high.png b/src/icons/qbt-theme/security-high.png deleted file mode 100644 index 8a1599303caa08979365b3e77785aa69d10ea318..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6508 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 KM)~g^asLJqEFoY3 diff --git a/src/icons/qbt-theme/speedometer.png b/src/icons/qbt-theme/speedometer.png deleted file mode 100644 index 2d2b99a624a4bfdee9937ad8a036dca5cc736fa1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9542 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 yrpE!iRcf9t$YLT*a*#7{pjKa16 diff --git a/src/icons/qbt-theme/task-complete.png b/src/icons/qbt-theme/task-complete.png deleted file mode 100644 index 5ea69d2dd82f34721a0ffb7077666068acb583e0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 756 zcmVPx#24YJ`L;(K){{a7>y{D4^000SaNLh0L01ejw01ejxLMWSf00007bV*G`2igW6 z6EhbnFTFbe00MMLL_t(I%axK{Xw7jL$3MT{`JbJazw>6pq7Aj(cuAb0NL-MT*SQ!` z&UP-iz>OPuiKLK1xfy9(C{1~tq?1wRrD-~C-j@w>t?)dl5GP3i(3gd5mA#)77VXaE+? z+(d9xnDgy1q%p{zSVw8|^K0xowHnhuivE-uGRS8X4qtiu`3^@~=K(OQb`={IpWtBA zYe0~E)5h_OYX}B{2qCeu&Je)L7V&vq`28+2RxfAT7XT2g*#yAL4{e-FtR)f-~?e#ASfv2nO@^5J1|#hrN$2DkDXz z#}}D2K@kdfll&6pS*o7eDi77;ZK^75#+5ttzqi3EOO!qnm@{|D>YRLaK5Kn7m2%Js zl+yej5Kxrtsk@IF5)L`k^^D!$l|F00000Q+er diff --git a/src/icons/qbt-theme/task-ongoing.png b/src/icons/qbt-theme/task-ongoing.png deleted file mode 100644 index de6a6fce41a8fe2d284b3ad4fa5a48ddd4b47b94..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 958 zcmV;v13~Px#24YJ`L;(K){{a7>y{D4^000SaNLh0L01ejw01ejxLMWSf00007bV*G`2igW5 z4;?Awz+6TE00TZrL_t(I%T1G8Xj^pv#()2ulWR|!Caq0EM;8`r5jT+4#o28**Es}j z2l`O2tfCLYDL7Y95vF?>4jfe{MSYQ3>@EmSY#md=I}*@Q)4*z~}9Vmwu^rgtr@2Yx7661VT_=UYo)y4hu&=>GZZ{ z>G~Egv?LEqs1 zR5O#a^F04xl$HD%b9sp+Z47CXUo+SowRo{3Ma$hANMB2HorZ||DBQ7eXJ&{lig|fk! zOKJMfeFebL13SrPW+^WG$*Y~a065Wmn*Na`T>dKR!Zo0m_Ndrq!oo#qwSZRN$gwZ4 z;`Ms?Zft`0Uf54rH+cEz`y?7-^o`^R27|2Ti-h9!;Ft*&;i9NZ4Aa1{9IB&9-a4Nq z;RMTp!HC0{6!nOkP)w?$ACRIn$9ugt`20|K*LMyL)RUz|l#(*F8q z=%!@K+r;mGnNZ1sQ$eeafZ_&QPO3Qe5XjbSL19xg!o*?;YzI_7gR|Og5Nz=1ARt*E zVSL^IMS>%TTnMFy>=e{Qv8!qcY5`C^;PHajw{Euw6c0fyfDF_^I0o4X5K522>_~;! zR`3RP=af3`NygYvqcXQ>g4++MP_ekLsfKWUoa-4IR%c-O<~v;e;Cu1!nNqKOL*uq~ z8dLZbgSO^sEPI`0)g>5C7to~}ZjQqA*Z^Z6bpR*;Y(ET_KRiotqeJHULzX|n4L!nm zDa3f*!;OrNwKNS^2Vr^oZAMQWWcy*58R5SLx8>X2U9Fdm*Kq8;xZDWsgG351o gdi0-8=Kr7n8--U~8R8*`v;Y7A07*qoM6N<$f<+dx#Q*>R diff --git a/src/icons/qbt-theme/task-reject.png b/src/icons/qbt-theme/task-reject.png deleted file mode 100644 index 9006b077d6b19f9529298e384b26c3609151fd04..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 842 zcmV-Q1GW5#P)Px#24YJ`L;(K){{a7>y{D4^000SaNLh0L01ejw01ejxLMWSf00007bV*G`2igW5 z6)O}Z1*e1n00PQML_t(I%axK#XcJ)+g};Ahl9)-v#5S?fHm#41f~KtnMX3*5w7PTQ z!kt=CK@{8xq9_#~2x=8XLFz_OaHAW=il8k;L`4M^UkeLuHEBC(YBHHjGym@*rB*lM z-Q3kVoco;%z}cn<|2yZKX9FPiHq~&}N&$u$>^}6S*l~1u1Oafm zG1MJREZMn!|0x22ARd4ae+rdC2VA$r(eq;=(%3N=2qvPR2>g(#*+|`9Y5TGU=r@xdO(lT>dnAKB zI?DLa5SJSpu}4QqHZ)L^NRS&C;6f@zK9eCBjZ(BMN=l!ZKqHs_jxNBI60^P@X`0go zlueUJGReg7Fz+5bzz4WXW&xAG8JMO?btpvbiWO{s@q(~vlK=V@C!MA$7GvAJd$^W` zJ{8;XW8x%c-39P$x ziMio0lbH-37A|C--_Kkr>6<^Fa-l#?EJoXzGYFtqo>`*@Lf3h_bt~yxxB1wxh?s5= z*9@Y%fjL>`QDOm~ZrtGMzI{lbB&RL>;Ca_&a)|HGo zl61jkNDA&s7&K=0yc(WpGXQ94IrnYw!_D29A0f~4ka(a#PDK=AYHOfr8sSLwcVAuV zB*Q(3rk1t5e%a5;we3+6sR{|rj}Rav3Q!0Ex==`=&@`l1LXMBvulnv!G_TsgFYci! UhZhFxqW}N^07*qoM6N<$g5Wo91ONa4 diff --git a/src/icons/qbt-theme/text-plain.png b/src/icons/qbt-theme/text-plain.png deleted file mode 100644 index 5991a27bfcb12cd6b1f395fd12714a1465478494..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3044 zcmb7GXH=6(7oNm`5k-v(q5?vIASj_lk)^5$MFY4%1SE<;s7kK}l;Gz|f+9_XC?ZOc zA}Ccth!jDJG+{ML3DN`!MM?yLm3`Uo?7#i|&dxdSnfE^T&dfc}GxwfhoHjQW71=8S z01!1b!CL|VgMMKEDGW_y{~T9nLIfN)wMIfC97&-=_9kBwy8r;T)~|oCq=Q@c0kHXo zDgKysXzEn|m0OZQQjN1SA+9r_o~Rf^FG>PYZ zLZ--2Ns-9D{_-rOX#-M1=J`Uo!U56i7*Vmxun;4>vJl}8O(83DDhVEC(>y}9mxvqizZ0Rv}A0mDJ)=dM?-|9s3mJf67zy2Uj62v%~3FDvN z4kmR}@`m%ti1d>DG2%`Rf#h1ryY>sS0duxkX8C(lPm)Dt+VFki#tUac999;3c<&z1 zo#5Jc;xvoc!)jHYrMTy90tpAo_hs8yZSNobdH%QgvL@H_#xKQ8)yWxL8ETBx4X$n4 zY+-XgNKbi2V?`uAgP$;yBm9EJi@cLEsb2IZKj6tgtATj7qOV^1uX)s5zNkrj%cDH1 zbK}l1t<=sd&4YzwBP5Ii>=3ypEb!1=DqqT7Y~_^wQC4VxhhQuB)Ep-98SpG>^W(q@ zGD{RQ%3~CR9O~ER>B?rJs_D=n z^w%Fqke%vz**A-^ier?}Yu1c`ngS^*N*F&GE#FQ(2%o>Z&}uSNr7H_kij`kAT&$m* zkZ-q)*LGxk%fn~zKrM^Z(vaUeQYqh#hR+xQwRd)9x`8Zufys~>`l~qt*j-2(bb3Z# z)nL4$*F>NIkKRUZ2Nbi2i15HchXJj4 zorI(9i|deiu66X*9_=Z%Yp}(RvG0;FIE~m-np-X2*0vr|2*>^z@l2f&Re(C$_^>+VgP_sFfr}foIve!v{#ke~v zSNNFZ76$!Db*l;-_}nT~)mQZ^wZ*6TEUUds+>PbieOOg~fdo~ScGVLswfCy`KHO|e z6Jw?&*JF|)cz(RHwz|==!nUQ z2QV?bKrQ8q#>fCeIPqF+1+Nncr&Z>@{!D#ky)#AX6ZM1~5=^*et5)!6lkJ6C;%+R|^jtAtC1;z~ z23gd*x#-?8l`rfUo%&aAFtL_J7AX^s$_cpxOgBtaPRndzNT~?S(CPK`%zz>~WM-`; zQ|Qgz4x7!!e#jI=4>J2O;iGafrJKA~4|R=Q`Ldg{F2rZ}_}XQ6HXRorpX zaT4E;BiDg6jJ6&@a`zQm7<{H4OZ!J2De~jmYcx_~nNOo#r=@)L6gn#Q93VJfd{2ySYFMeJDMi@;S|bvCQip@k zTL4JQ{nQ+GO~2D--=&%1OM4(~4BIbyChD{oS>#&{RPr`tpJq*X+~eERJiEQk81)CJ zuV?eI809nFQk#>%rLKPPomJw7%|$=d@|O+D5LIC;Ua}m-aGA?yOc^#;j2I-cDZG| zI`}Y14<4#YhW|e{{^n|0$mAiG+!H`HbJpMcbgOu2Ozd6ZG;wd?lVUKFw^a&ynsvc{ zoIBKovK^#y+8M&Taa2cv_ppA$R_8br3ynRA2#hJlBcM6h!PyL zJw#7-p7@!S7UzbLA>`@4Y_lX`t*q*I?)vBJY3WiGQ|2MgKEEDMTE4{>V!G8ir=THO z4s0pJ#V3Oj429m~zL8^uJPm|hCU*-AOZ_y786s>X#Gvn_`+M;JlX(h1eR* zhO$?{A}pY$MJEbhxR@JJXYC!p+3>;VQYNmVUqCmaXaF=izJbeVmgedJO*T((!^q_b za2`!sE3d)&ayIbToU>RSpNh}W*auMY6Fo!cFwphgxJp6iZ|l>ZTGd)hF}oZ(oERJ^ z;AJU0gys*q5dlqo8ZCv%yG)lPtKT#WOwQBwa=L#!-hTf+to|rf{NKE2p;-3^ ZYk;%CFj#Zg%6omODZw0Hc>Kb(KLJl0Gj{+0 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 3bad8256db2a68045e961b3f3c0cfc5dd0792088..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5202 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 H_}l*j;xK^G diff --git a/src/icons/qbt-theme/unavailable.png b/src/icons/qbt-theme/unavailable.png deleted file mode 100644 index 63df6ba41955c14100dfd2d61a9577b2572cb072..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6995 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 R5C~ELaNgJoTVv>v@PB0*5{Uo+ 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 b9a24e5a999ed787740f743759d2491b4286bbb7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 11095 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 CYxmRu 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 e87149d0c9baf842b8d836ec5d98852ccbe07efb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9531 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 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 59c9f1d92bd802e2864c461a4468351436f68f15..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3371 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 Cq9We_ diff --git a/src/icons/qbt-theme/view-categories.png b/src/icons/qbt-theme/view-categories.png deleted file mode 100644 index 61ccee0a488411af36920434673924d89b6def48..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2744 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 diff --git a/src/icons/qbt-theme/view-filter.png b/src/icons/qbt-theme/view-filter.png deleted file mode 100644 index 71b50b384d7f855029cf080092f883a855d34751..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2156 zcmdUwdo)|w9>;f%Tn-Hp>OIATNOd&Mq*`w4k&+InTyZmQwL?5=n3j59HA*BdRR-g& zdOc#Mw;fYTj4BI_)6o@6=~NZLRAa82(p!(F>Q#^2lQsX(|97u-*8c4M{qDVg=l9!Z zoqT^kZ(SX89RPqX%ZJGY0EZzCz?xVWoYWYFb@*gYRsf8(4EW1DY^)NFmd4VG3z<^S=QF!{hznV~Z4x_w7B-5OW%x6|3hny;%d8vWq zKb4YR8oBh8ja(h!1s3&0O#B57FKy`=I`7j^DlT#0p55P4wp_dV+EaE}w)?4vWIjV8 zUzt~Sxf52h(%iOwNrRjyJcqw${CrD2}w#I;&2_HS>v!W0ztRkF8D> zbOx(BJ!0eHeuld$@`uver?rAFNRA1{HgDW%89HF~^^xK+$((0)8npSsZ9~vD z9L14IG^%1JDxX@NNLrYhPPNsz0-YU>B92RNXTl{5nf}|ktC~uD!u-Q{0Xari*TUCo z_GC@fxAIiaKCkiE;w%N_D)Hj`uc&)YH+@rQrq8?QwQilnH&nbUopweKJuxl_ik6oU zYyq!3Fh&lV?k#k4w{yR=#+|LOsJFNOwPQv2x7WrB$BuX(O#@*$XJ=Ey8+443+M%Qx?!y*44D25e zu@THT(weF|zxHA9ZV@$FKHACBv?k#`BxdeVzqS15i_LOvEo{90)qm$Wc9udWezL|` zDss|SQ{5Si4AgX^3ZwlPb#+f*WUQuM;{lPAshZ9<&2h}t0r%ciD5<*GepwS8?tA}I zVzG@JniF`h;(VA5N2MwO^p-}tkgW`51DZATJZfi!3a;yCU8L^~848Cmz$$-kSaRij z%v@kcyqP(!3nEqLZb(&+`lSLhD8Yz~#7PCQP=YQQ@ssu)fy5eQgeL7vhQwZEL{Hjx z0ut{dBbTIo>5$l$jIgDB&X8D(j5tX9QX#Q786imfJRmWV?0;RkA_9x$@L2fHuD;MR z4~;ex2=EP5ve;ZIcf>7}!VcG!8ys-O4)WzD(IW51?d%!|Df(IUm9?MTIUP@0+QF^qnbhw5Q7+Ne%Gdel_)SR4H&A2l)+ z7(xD7aPZHYO(fxI<}6PdS_uNiGVq0c$8n9#Q?RMZ8b*PW32x4cfHTdDB8Tl{lYs_( z3sYuc6lEWSq#iyH!uTrW`1<>-UzfXWUdP?#`^I;_o6WylB$Byj7d(l!LX9eV&ur(o zrxb%&~@9*yP?9F+nw%rDXunT^x|SU5ZkOUt+mQ`(y6VEw_MBV zszvNF$`5bQ*KaoQ!CaE;0r7<^XDeis-~Q%Z+feU+0s@VR?wu){ovg=qRw7dILbr3F zp`q!DC5=wUsCLfnp=&*H$}{xsH%iXT-|0lRdyRanKm6@tA}ZM>rX8(B=!E!8wU>3u LkJ;iG_K*JocvgN# diff --git a/src/icons/qbt-theme/view-preview.png b/src/icons/qbt-theme/view-preview.png deleted file mode 100644 index 9a5b18b5000624016ce72e97b9ffa914e859b70c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4088 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 Qk$*>npLaS}X%%?)KPwx@YXATM diff --git a/src/icons/qbt-theme/view-refresh.png b/src/icons/qbt-theme/view-refresh.png deleted file mode 100644 index 86d73796b2be014e2130fdf2a18f0d06336e48fa..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5942 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 BNq_(V diff --git a/src/icons/qbt-theme/view-statistics.png b/src/icons/qbt-theme/view-statistics.png deleted file mode 100644 index a976c0c691f1748e1333543639a4fd40bb786df9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1120 zcmeAS@N?(olHy`uVBq!ia0y~yU<5K5893O0R7}x|G$6%N?Bp530R%N1DIGvQXMsm# zF#`kN5fEmas?8@2RKw)y;uumf=j~m?Zkbe>;~&%0`mCE`xlV5}^lcL0E!)=`!!^4^ zX$j9eYme31O|4vJ(~6#19GouD@jULqstHq8PQKN=!8kctI4IZ1Zgctm^ULQy|DXTt z^tnR@OMzAr4Gyqg^eMft*1G$A`@WhjFH2W1e(E3mmLVrCebeN&k9oJv;`be%%EVxt z`8wX^&=a6W;a9hvtM_QvR9}7-5T{djDNrV zO4IJQ$_&wI@7L_V)^~T+qZ23h@t^$pSP++Ukc~reCjp7inFeOxZoWO*{(9T~pyaU2 zW&i)wZm5Y$4pU-GNPfNX&GzK)$x{<+D}%gtMy7@-^rM9W0n@RB8=8)YE6We&z18>g z)-=yLEB)))3R8jFU|GO?lpgZZjYG?(cF3C z&3mSrqUZn4?ksQkoRa<~&dx4o-;5_~H2Es!-`-gJ>>lH}$qT2<_tyNr%;GfRbO}sI zH&XPOdvm{MTYm|)6K6enY@^NWYIdSC9Z=y7tN%>Z=MrPhP9ALq>GO2;b6Mw<&;$U@ Cja$C} diff --git a/src/icons/qbt-theme/wallet-open.png b/src/icons/qbt-theme/wallet-open.png deleted file mode 100644 index a3d85bee780a3654beb5e22cadc58b646be51c3c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1593 zcmcIke^Al~6#wEhwG7ir8_Z*iG;fAwrIbG+f0U_ZhD8lUtQ8uGN{aXsTz6_7mffZ1 z%3MYzrb$jgljxU(&I)#kf`YnCG!py?k|;8|{kywu-R*Pt?!C|5d-s0a=U#DCWa#RZ zkd*)ctPVR6f(8JPIRpVVE6gtTJd0p71FGTYTwVuj#wFZk_sMoSpplui>`^S1;IMA-?2;*=q`0 zkBu~X1l9yK>)eAKtfQNrw}S&B0wn3pNxlRt2NzL$Z(VQ2b=eZV)VW|NmQZa%sq{ME zBJo`8?3n&A?JV3p$d@4geD|HLYaF~#^dur_xLltRZNx#nv{#?lw`^ZOm?+y|BpJG& zNJZ7Sfl6(jn^XQG*uQ;hzR|Q4)g2`9Js$pZwFDQhAPTZ2ZEIX9MjQeH=4xki?MfT8FHL5eU-d*Z8Yywvo2(Dvvf-PXb^ zPqmGAa!B#oo*aFyQr#1A?)|RwNuWwU?OkyQqV{$f_433)Sus)YDoR^o8G z7sQy*^aq6|rliqSm_o~hhQGFh4!$RqCVpV9V%YaVhEuXuD7wv?XQ>oy7YDt!VpuIj^6gtj;eWs9A&aQ)s2Ft+fm08S;rF`(XZSBYPh)=6UVAW< z2L##&M!x3R(?nZOdL-DBnzz68Wkd`Qz1oTjLA zk0WGA4gAiS>X|+hRMD#9;2*^C7jeHB=7p0wdM|b?V#eULbeQub?wtQLqX*AZ%vQcJ zE*>}4_7^Z=o*WaVxGkY-{6!=h9(Q>UxFuI>VvijLki2xV?kx{R79(HjaM$1?%Z^Rv zw2ll6ypJiI)lk)0pA^*6r@Jrj=rmZSHZQFW@!Z$f2B&7X(YGylXQeqlsuhgk&N^1X6=vFgfB#EnT&dm%_d)!-{-gf cC3tqi2#p`uWe8Z$p8i}Pwl6ZIF)04RpGKFVF8}}l diff --git a/src/icons/qbt-theme/webui.png b/src/icons/qbt-theme/webui.png deleted file mode 100644 index 43f5a9cc03e783a2eeb6ad64d8d3f8b532dfa83b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10567 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 DhpBN% 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 2d55d7ffaa819836cde3b45743c92145c31b22b6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6344 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 diff --git a/src/icons/skin/collapse-expand.gif b/src/icons/skin/collapse-expand.gif deleted file mode 100644 index 5833c0c67171a6ec3097af6080c83ee84c6150c0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 198 zcmZ?wbhEHb78fpw=O&W|NsBunfrkxR-pKkg^`Pa zgF%M@2tZ~quoMfN^wd^;`obwkB5DOMBWu?q1Hp{jijmr4K^b>;2wsz#Al)GA^kg?{ z>qfZ(wZxN7`bRvM&8k_kluPZ%#t@c!8!F!1&0BOWQ%gH=@hXnzpFenIO^ca#R^yU< gojZG#y}3uRv~PQfaGs_}xUPy=8hdO?oFIcW05Mlyxc~qF diff --git a/src/icons/skin/completed.png b/src/icons/skin/completed.png deleted file mode 100644 index 56849ca3441526ac0c4d280410b967d02efe665a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3598 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 UzyE9-bf5!RM>mIRd;fd?1IT@8JOBUy diff --git a/src/icons/skin/connected.png b/src/icons/skin/connected.png deleted file mode 100644 index 9aa01f12f47e2b017416e5045e889591e3067c6d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5566 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 diff --git a/src/icons/skin/disconnected.png b/src/icons/skin/disconnected.png deleted file mode 100755 index 594166f1e9b7e33069d928543488fb6b716b4da8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5540 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 diff --git a/src/icons/skin/dock-tabs.gif b/src/icons/skin/dock-tabs.gif deleted file mode 100644 index c835fa9c6c79bebca6c6bfad23862798d1e45680..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 404 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 diff --git a/src/icons/skin/downloading.png b/src/icons/skin/downloading.png deleted file mode 100644 index 4e319f8203d957e7fbfba7be3d25c938ff172867..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2312 zcmd^>|3B2(9>>pT%+{x_jE_pgG!gc(Ma+oH#xy1d$(JJO%D0Jp+lb08afi{A#4s+6 zc5@jk#cF+dD9cJ?d>cv0B^%M5GP=IartxJOW{mrp$KL;8f4JxIIFHx+ecsR4`<%!5 z;XKaG6F%#W zbZaKWv(O;`0M~fXkNBtj^Y;nw?9ylhk!+s&L#6)DkE{+j*QOn5U_@=r%0FC^vy&d9 zdn_b3XDI6GqoW3*ydj6!4(|1GUDpSNwR)CBn^WfxdW68v_5mED5<9;<>z{@XadW-A zhoT&8rsvc7(`y@y02{5(|5@XArDfezcLpQC^NCaoOzj0MYYf1f{;5*ZM+M^+<^=PL z0luMIdW@B2rTfg4{z>QQZ5B%XxIB~cFf`GLHc%hS7I zvMi9MCDzW6p7W%piM4*V1!kCp-Ib5V75CeMwBf>GLFG$?pzg1`*c}r&dyp z4#}E|+WQ2Ng=HJ^rFnbRY5oD%jAw!`u;n(+so@`FMeY592*dmg=I>#y?3d@n5N2>^ zPuz*EMfNxfshEzT-76;;}@8g{V&@$ z-FWbv2suO{2iFKzjZLTV>+PtxDl_CCuKK85Ug8F zm09t;#W$%5Vm?1j_3P5+J=Da0!ODu`spZ(~)H3Fq>WX&q=|(Qz)pxa*ad+b3+SIJg zShLVGY#&g0R*p)kZmt$lQQ2aW7|ME{#M>pRqV0m?Wf0a+95fo<8 zf4fHSXGE8G3r(^I(T-?q=Mci6Z9aHcP9T z=4f5}?8dF#_?%&))K8fuJ^%ME_SZGX#B1$!b0F@`gCV6gB7795HZ7>y;k*8o zuO*gdg89C%SVU^t4sODX&NGDeR{_AxgtaC1qRKA~D#!++pGRb#@taT(UsT*nY9eSr zdM!8X8%Lmr2n%+jW+Tno?O+kEq*|1bs!neYZ57QY0PR1H6OhPg($?Dx$ z##*+JKvq+*#+#ARZpCGUMUf*6)hbN08i&d13&vnoY9drTW`iWQHx{4KtjqcsL&b2~ z(_mV&EddgVy|LwKcXEMb!3s0z{esStB@>{Tx;azS#05z~O=!1ojltW~A*lN>Oe5CZ z1d{r{K-KQkC^GK?=7z@5jT{ixT9OsoHxyg$Q>sA-Q1$6l)UyuL-VUKh7^i_b`xO-Z zPM2lpWr?De*mB}_E|4VPpqTz{4MGQRY~&gQVcF$rka%o)h^aeE*31Qu;uH4EUa8nh zr_+Wd_Ngw5BJ_@<>^e>w(GPtuX6HKU;Wqp)m9xl@*Hv*(uGH zPoHQHi-IUF$ec%O{E}zK$9S1GAiDt&f&H^Z?$qn{xLqf_{V@8K0UoYC^g3t8)&BzS C6P^bE diff --git a/src/icons/skin/error.png b/src/icons/skin/error.png deleted file mode 100644 index 709a490ccd1e6159fe5d6264a8e86849287a5999..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2478 zcmd5;dsGuw8ox6nID}WCL|!$FNYxe)B)9>2MGVTL0&S^iMZiY^YeWpXVh|lrOcWM9 zDvC%nT}43=Vex@r1U2ZQgdpltBpO5>CmMpZXn;W2J9PipzxSLyr*qDn``z#L`{wuE zx%VE9j$CO;bD#kLEW<*1-vNL?5doMf9O49JNpPT~2ZzOA@Y#!P7Q?w&TIkwz0IcNX zixj$AIYM1@7;jljM#iN#lLu~JJPmk(Gksxg-5*K6y3me;kn0+VeeY)B)xAkS+*}{ zda6qNiub6Ul=_+-dz{3-OY~XFJ42&M9l1zo`Bwpe5Mbb#9Rg;~1Kf=i5SkCbVFth# zqrhbaAmo24*~heCCJ9# zca@vX8$%GU5gr$C7OY-w`iMv8P}mRudK{1{f- z85^!7U|^GK{rKW-wbu*JA$bhq$jw#hyEXQKzkI7fri0b`b|ejr4nU);(@t9v4B|a> zTGHc6;Nayv!2CV|@lh`+XCY-pc{2zmcM>La4qggYfGaD(*O%_0-CvP9#YikDL1GF( z%r|57G=J9Zr2f(YvYaG_A>wG&I#FfZhA|IrX?gfks!gF?T~5V*HwesbYy!i7#exhDH`s`u+|Qx7Bz2Zi;E z9l}f#$1DUmE3nR+$k1 zx^lMOvU0k2b>xePylx9FK3LdAbYLvetv_VzIS64FEv_qN!W zG}@DP=@}){q>)C3Nk_ftLu7TRP;ojNo3=9IkdHs%mJ}`*s|2--P!ojSowFOQLLsx1 zg)GzoffU%Jq$1PqjZ4U0!Umx>*2v$O1O>&pJE)CwrKTv3Q_iDnrdvY^jW_RaCDEna zH1kA0;z9?=5fRZk8+L&%&A?K~?**0@t}Pd>j zJ){^g*wuN_sux4Z15G$}{`+f$6%X_Z(LVgW$8171-Akojf;ac*1Q8Ba@5#zu) zcnh_07OvP*{R8N{eeX{&uxE!v`ev1(f z`U9>>4eF)B8&{GC7j$%RRN9LAA=d!&L-Rn6O1m|7_g~{DmUYZ=3wWC0pBlA|zgMX+ z_Ug{N2UwqacXqvPsi;xMleZ}1Y5Jf{b%X4((;M$qyox)W7qnx$ez=)07X;qT9Aa=X z<;AjumOF-X`{xI)=Oh2?p8hBofABzCymI1^qV-34p=^S`z3b9ZA3Mfl#bnX%PkA$u zXy&lMTXA@>xi^7&c{J~gtg3UDB*b6&GErD|OX_KO{c>#LE&IA`^>3o7smQ4LC&~>g ziezhrv)x2MY*rKdMxtODJ~ib%hg4}#pJ?81=+rtghKJf~5`9qIrKR#3ucT~HG&L`% zA!9h`tx*Cg_CcjCJ-4GIK~qYS`y?;ltx2|!-whaX?2)#qoo#W^D_Kb4HnW1>cip_# z5GSNqEdPI9wDy;}^+G!MS ze!cp6ZNpAMR@Q|PH%^zfZu?qw&^n=&+hb1sqHyc%zT8erwxPUX%J^Bsc~iUk=K`lW zzP~k%?KNIJ8xa4qsg{M%Z5gqONhZ7g?qeraZRd|gS+8Gz$%^WEH!7Mnpwkz1a?JOB qoHEu7IORvpO8)cT3;ye(VgS+kcO|<7`3~^H1;Roid6mJ5IsXR8Y@=%c diff --git a/src/icons/skin/filteractive.png b/src/icons/skin/filteractive.png deleted file mode 100644 index 821777651f864afa652f13f04eba91021a3e2491..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3310 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 N2qu=suZ-O8{0nNKxZ(f+ diff --git a/src/icons/skin/filterall.png b/src/icons/skin/filterall.png deleted file mode 100644 index 23146341a486e0936a2d21b120cb8515270d1668..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3331 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 diff --git a/src/icons/skin/filterinactive.png b/src/icons/skin/filterinactive.png deleted file mode 100644 index 66346e51093ad42669797d197ddb6a2cc72bb037..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3256 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 diff --git a/src/icons/skin/knob.gif b/src/icons/skin/knob.gif deleted file mode 100644 index 755e06e0df8d1f23b476bce8511b9bae2fa5f0d8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 198 zcmZ?wbhEHb6lUOLI3mdK|NsBGx`vF5%;e;huI|3+GiLYpO=xIrUb}9?q$$&T`zI|} zv~>2|1xuE%>Yq4y%Ji9$k&!?x3`7IPpDc_F41x?gARQn(8CabYSb9@3`xZU0$$7o4 z&p^sI_x=t;y_)?D4)XnmNfP}$3JjGpqVp~^8F9(V3f<62ntfKzt+^q|N3Wl=ksbCW72MCCQ-)J=#kXiKh|l+!vt zuYFN?cEih8ufwwHldC3X*G`Bl?%clbXlzmEmFu?~CoD*>pOMipv$kh;XhzM%xvMJM zr$**BClxq`RhTW_)RPSY};)-@J&N#;T6#DbZS#!Rb9D$E54+A>AIcq zr9G*&Q$KzB#4wnE;!hT^b96u?C{7sI|2Oan3A1tY%5ib|clY%6^-q{MY4Vh*)27du z+21M0%grV%#K*(I%*422rKlvYzlXdk`zF6FTeofBv2)k%J$v`)^hf`TYK$f3fn~Pic90$|# zmHs093LO_1mM%Eh%pt55b7I57!|ejfUUPl~G;?t9YuH2v9Asq7SgDaSfw5`P$;leQ zt73i%xO7R0h@?z7kQl$8!8m14!pY6c&(GJ1UsADQ(Lt7e1?CAHj9XS-ULLTpp`qYG zCnFEfq)#2EwywV3sU#N@abVFi-=_G>t3p>VJj}jW_y4!0QQq70LO4`yW)vuhPrbXp zp>mPM0tF{Vrayn!;?6`o;yBc1|1H~R=cYp}p~}r$&fF|wQujCUf9F&6@%e>z^XYN9 z;tUzgE8REGn|p2R)f-)zub*W}Z+miQceDB1Uh9Srj~zPyoAvFn^nSW(uD3mB?6)tk z1y?g4KR0(_*|WQcwg2etvvKwZG%Bq|Jj=xm<>4nVlFta2yJOd uDK=pUILs;S+i-A7$iD?l!s;;#7^a_XUC_+`S;k>mv7$-f5#B}y25SItyn9yw diff --git a/src/icons/skin/logo.gif b/src/icons/skin/logo.gif deleted file mode 100644 index 61c19e2a1379786dde22de1427818c84e8b92953..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2031 zcmbu6`#;l-0>}5Yi%s$Daj7M;$z{vs(Q_X0#F1|6qRUDNxipuVWwX_aENI2}Lo=qa-7jgd%dAyc|O;9p^mfUpSv1-oL$nd4Eow!CU`H6obq_Ga!(2K%}_& zZ6x;zBdN6imr8hcOpgly^wl%`lD=CBpqy!nK>MfN;+Ig3LQ4-Q#vb z9Mr9;((Y!C;xCyW>QFeHt}{`L<*11;fE&XrWJ@im`TlDL-pAkp2M^cE-{q&A^ADsi(1H&Il;aLO2qebF+&pXM!VVSO>JcUBB zva$mDKZe3mH^ypU3=it*k&}`iq@;4v(lZ`rW@YE(rY0OT#AslR z_v`Q50Rxwno0=GsZ&+CA*80^yX=rSE`mDL-`HR*zNqa-Bu9bxu+0eukSyEbFhS58s zYha19u|to6K7F2;{4zEDb!K+%zqJ;}&~`RBO9NfJ9tQhvA52tEHaECD$EhjhOQPT! z2i&?I7j?uT_n*z*AjGC<8o2Qh5-$jtT<#_Xc|{e!&cHf~-8QALUoqx(mDUHnJzIfO zEKTC;I#F+-X%Z4cEP<$`qLruTfcoL`y&YLc*IT6~hUKPuIh1N@mVS zdcGH5H4(se3eIk?3tb%=X#<*8Udt%V?#%I4*1e^*N7c!o>1`5f z?)y0Dq+Kv8oj{X*fNkQ+@Jf4=JG}ub8Xg2SqI4eB)@gtb&_-MOB0b41n7;=II zKoe=5IG7S=eqZLCr9B&jg3#I85g{U08S2CYkJM<#S*W~DnVDo!upAtas83&Hbdpr` zL&gy|Cc{xH(?$<$3$B^u{W6!0hryXLv&V4yELB?#R51cwDA-#Ou2Vl+kXX;-#%58j zNZoTs?ar_o*YM4`Py2Ems!DL~*ZmueKgz0F6uvB898R4D+J-6s8TMK2tyB3Oij#zZ zL;#hK&qW;(yR_#0toY1U{JQsX0!;2_Cj3yv8(`AfOpS>$DcL&n7K4rPqNnRcs`Y~BhfqAqI?u)6$Pke6Fv0GRWVd}p4PHlyp zwc-BuY)!#X#Vz@}NqvIU(9#s9sG6*`>@m1QSJEF;wic#J8lc!Sl;}FMxsZ^o{@i)} zxYjjf)wy{9t#rt#et7P}-7*{gz-3rD6~VGKa^OuU{yM^amCEoF=s}JLwJrtVJ-R5_ z17fFRmRr3xkft`U`L)9%F-Uh!(D-{zg1vyz1MuaT;w#2h%56x(u9Emr4|-;&zcfZ? zm8f*p2}tyvI7b{!?p?gY)@XMKo&9|z=-o>;yC8|?etfF$5e(0ZXYcU2!rs$|XCboA z02;P#1{sD20O#~8klzO@OcMZ&GtzDAmc;32p=%)INqdkm;Pb!FW{IcbYtvrgG!nZ+ zjjkhf!{hw+9Zvi%onjwCvI?m{1r69DX5Z#6ss(2qbJUM9XtMuJy%_1f6Do`_j}~y#?7Nq;xIAmN zRddN1+)nhnJO7 zlH0*Ygx&TR(+N?bumc|FP)e$F`&fi2QS*|jiTfK)j81+L)X+kLc!(ZqD1{M~D$0?Pe3qmekB%#DJE3%bq#d$ja!+C#re|(?k-Lcb??i?ltY=Gwg0O!<88#`xb zXZv1{&CJXw6pBc`L|oQ9q4+fPZgOH`;{KC?8P%5xm-RuIXOK&ExOsLR4PAy{1}*&x3si0K0XfopO6>9|MKg9_{S4~ zT47|ydaXCS*d{sAe$?f9Psu6oiomLY^7toHiA|%`oZYt9p33VIyJ8ye5#bz`B^#~V zZNxAA)T>T{c|5fP`uZ%Q8c)v95+FQBT7{;JbJgoPNQY5KF z6TbK?01KB$$6x)DM?#}yB*ji5Y}9mH({GJ+we9)FgUU);IMmDonFd!G&3G6SWzdr4ounBO;$gO zg&A+ngx>hJhdB{CY9PX30zKmlAa0;b0dB2_43kpBJ`;F?P{|8qt!=^7%wQ^5oCxc6 z9fVUK1+gN6B$3@f8%#Ipz!=K1Yw~M-x|7*%vH`Uqd;un$_7>o3q#MT)`Ju24fY@|4 zR8vjA0myTb#K(uS!5|HN`q$Ard4~ZF3MV+1$@&ey+HpUnh;!T-MCSNTyI4v!YT)Dq z&QZrk>H*dDAy}$cR z>AHq&>LbDeB67D^>h**{r3J}J_a{J0AjjyeWKy+20uYYrDb9`OpW*s*UgA_?NcCkM zvk;|&M*jBU(w5*z=X9rcX?T$FHtuOGy$xt$r%I?+_N-nFincx@$%Kd;ig{63+YCJp zdpQ=*BXX|nVUkmGc?8>k5K=c3C%4I(Zu2l7oGgA5b6!E0Y-B#CL&9sKRKUeI=J7;-hF6xf5bLdm$6>55_4`?)&o@v!%hTc~ zuYyIbhhDS8wKHyEa|f8FE0^uJVeFeXNZp?lWH@(s$RTA^P)6jCYTx4~^|f(URSUyk z$FF51hsFTQL)V%KOD3348x_V}S=nsI;D_pZZ}GUFMee5l25=-%ex;?)Iv~l^rR3)a znk|b6*dQz^y8QXzu49ic=Hb#CytuonpuT;LZ!$v!={@Ic+U6TzW!h zR%<4Q?_V-&Gf$JPsG!oKqynmuTc&1s*K~5Yv+u3SdIi3~_E38i-br>>N(*5IyH79o zOr0ESJ5ANV1r#cS9%&t`c<5BFm~?Y@ZU#(s3}s8EwqKLK^4E{PvN1wic&V?61Xd&G zZthvWTgwG-p=v0%zHd78zqE$l0hO*k09rtFzw|ieIvE4#&5o=y zvY%;aVufAK)O9yE>_zy9O*8u!BuIa=j_(+*dC~jr>$V28IX+T}|LH8WJ>C8!WJyPh I2>`DD0x<`)F#rGn diff --git a/src/icons/skin/mascot.png b/src/icons/skin/mascot.png deleted file mode 100644 index 0d13b25764150566954a0f61dcb3588882b54eba..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 21876 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 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 765c83492a828aaf95c37e97f5bb2db344d56d98..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 899 zcmV-}1AP36P)q z{cBrg6vsc$b6@k;CQXwzeNScGrZNi(V0&I%!nAdI$%xt2@mUnC59l?P0JFbHElOytJiD`u0Kw5_2@ z0YDVRg_a-9ukH93l9v2@I&ZxTH2!ZO)tD$2i$N&PPYx$l9MkCrhhz|=(pZ{gCU1z} zH@pQeh>jgECC&hj4q(XW{py}~zL-kj1U>rw@UZy6(@7g8hw4rP!_XK@>nyD|pG;fY zCzC_wtGd!zuJ1HIuwoCl;nNNJszLvN3Qd!QN|$LGY~FXUECb6h5S=#HZ^vgxpD2AM zDr#Fit^MPj~{-%$;#?Fv1YOBc5##oA-M79CSPCvgD`^8VwTGGF4abNUN`Mj+3PA~ z-Qvc|Ep{E3K`&%-%4eUG3<@``0AeN@7SEO!IYjl~IDB*S>JCs9e2CZ&P zFP7M*PRomkgu&y-$GCEH8{1Bhvh})dnfkA#!r+PTuHNOv)5m!EOrC1Jt)_&a+1#n@ z<0*=Tm*&YN4OZ71Tw1E|%*k0svi7pVmy2`L!*Bhy(G(wjb^Y)UM9SYjdy@5?fV4#K9Aq+M%=)M@M$n7WP`r2*sOUpJFwl1Xa^d5 z9=Pg!WNwV79vf%AJn*HZi!0(_nWP|V5?%Ux!#VZa-6r=cZ5-Ff5BdO@hDJ7HF)@cZ6lqL@Y?B>2yS07HuBMATpC`n~y}9}NqL)eh7Wrnb`cT8q~%fAiBT=U!vBm_(O? Ze*qA3fZluvE;9fC002ovPDHLkV1gEKzS#f( diff --git a/src/icons/skin/qbittorrent22.png b/src/icons/skin/qbittorrent22.png deleted file mode 100644 index 2d99147b4d20ca6a27af434b5c7dc4cf5c81dfde..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1352 zcmV-O1-JT%P)u(fg6vm&q>}7Vl+jiUSuG^M!Db!LCR3HUf1I08UMkEF?QDP)~@f)B08~k95-~EE3 zqJ#>GV2q&%l!yf?6sS<__OjchyW5?e*_pk}%`yd z6$N-i9*zSfr>EAWW~Vbx-BMslVVB$58>YqT#~T+xTtt zayr}^JKn$lZECUt9=Vxi)aeJeHqAVk7#kYe*K%<0c33o;X*>9jSR)bx3p@vr=W+G! z97fKbsR$nbJA((_y}%m(NZ`qv*Zjq7YGUiFJ9>uqYy;2Puo$%7|6jM^fCrVDg{qsU z3nz%>aJcm-gOSrGv!UkLYXifF=0%sTE-!r+iN<=?cWx+o49iBT zVz5YDiR9ep58#zu`=XQMV<(BZS4_=Jb!tlfSaj14)G8HFY_I`x4d!|kzLKj&S?E<0 zvSz^R;jtRNV?ag|M1dO|zjAR<%r4Fz<)tQHN;a^I9`txT2nKvCOgcg=Q>|P@p;Td+ z+SE)GcyzTjAS8*5xg?XJvVn!H3aP1sFPC!1MO{(e$W$aGh!74+kR%_{c@-LsDtSdD zTEo!(*<@K$1oTdsrW4rGZC*q{(Y$;~t1@Vf zpv0k<*u$)7d;&Y<*doU@C=`!F;EF-lE6)_QntS}%nJ>{b9W!XukT)D&gH>gYDg<%B zvqj0&P}Zwp4GkO2C36e{nDk7QL1n5|%6xXIgaTdjj@twVuhpyxyDTGD)R26lVq<3; z0+JtsAfUG^P8s`IBm`!~0qATEx}&r6yr;Jf-7kdj{k0?vBAQhNh9k@i?R|UJ(tP^@ zE$vv$t5_3jLhsrb646Ei)d2A1s)89>ssrG~_9lcR4*_Es+7f3c;>`6q{CX!tOQdNR z{(@~9=R`sDeqDT${3Nz%yFXXdar)9EI$A^2-NLe>mPx@0f&dS(j*E-Z$E}t z6d0TX`zl$H*wG}B+lN?Qn7Xu~|KN}alDaf^!m+J^KvR6JKhzAKhz`IuoysXFC^|v# z^nb`Iu&%O_M|S2;J{0XZ1`>1ZYIWs~*L( zl)U-#PNS-SNUq$7+Gz(txRD4#S@8H4MXz*S3b%e0@7Zw$&(J?R%Gk{A=+Y7Z0000< KMNUMnLSTZsf{%p& diff --git a/src/icons/skin/qbittorrent32.png b/src/icons/skin/qbittorrent32.png deleted file mode 100644 index 2086b4343a291e040e87a8dba79901231a1bb69d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2510 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 YUqQ8B-SfF3dH?_b07*qoM6N<$g1Vr-y#N3J diff --git a/src/icons/skin/queued.png b/src/icons/skin/queued.png deleted file mode 100644 index ce1b9989e00828a033f63480c13927eddd86294b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7189 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 diff --git a/src/icons/skin/ratio.png b/src/icons/skin/ratio.png deleted file mode 100644 index fa4a3c89eb1681aaec38a7e26e8f7c38ef4fd532..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3762 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 MJC}oxY)@SJ5BDZQRsaA1 diff --git a/src/icons/skin/seeding.png b/src/icons/skin/seeding.png deleted file mode 100644 index d76ca3b84eff49f980e8d52e95f2d51cc798d94f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3469 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 diff --git a/src/icons/skin/spinner.gif b/src/icons/skin/spinner.gif deleted file mode 100644 index 879316f753450a884ad9784b01d243d26c134ebc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 793 zcmZ?wbhEHb6krfw*v!e$J7rdT-;_nmS7#Pg9XND!z&!tPBjC3_2jiAY&O=TntXmJhnjMwoUKM*)0lFzK4bz zOiX%puvnYW}EP!8SFGK-2-MY7wf5qK!Z73NHEw5#>25HC`Pfe-09`EDL4v_vprGKKIa`GT&0zO=>5edi z1vt760u5$wCc$71kiq9?&JGblGuUHZx)aP`HfAmcpuxOtBp7@SWU%0@*)9TT20PD7 wcZC_u!`9^hG?=-O1cL<@0S!JrV|IxQn!#@K(p_K%Gcb591RBiRgw0@U04%*3l>h($ diff --git a/src/icons/skin/splash.png b/src/icons/skin/splash.png deleted file mode 100644 index 8565f31757f7ecf46ec13b226c341b445812e0a5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 66403 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 diff --git a/src/icons/skin/stalledUP.png b/src/icons/skin/stalledUP.png deleted file mode 100644 index 21df43efa0a43743e6f1708da1f1652d5632313a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2319 zcmd^B`&ScJ9={Vtn93{D+7baJfa?;g5u98O)VMc@RWD@Hy|!j8ah$$=%#DKiPJRlH|@tEd8JExEI=T_{_JPOgCN6YRYMC z`{RZSwGH*il`1BavLn65oIA?w`0f!RyxV4SK;&W>M?)9PP6Yn!AAhGSc6+LL_m=_R z1l4+IhcaJjS2HCUGX0x~5k*Cof)^hC0x+in9RS%10#{K$BmJiE`hnVn7(FC6a5$bC z0pGo5>2ZfEJa!epG&(C@As3>=5{PcL!<>sO3&P2}Gvm}HL`nbcRmBX)JuPk~= z_K+;1n3T?BPC;tB`4(w_^h!-}##Fnnr)K4)eBZu(V}~erA7v@bkGK$y)D;gNX2rLD z|NZ-hp!M#!J?%`m?;zN?r(oVwNK+!TGaPS&De7Vax%7V4Jx(T^bpqGQCRgm}RiD9C zAW0-S0QdO=_n`^nkUdO}K~?98IqpR4P+%d>Eii!lkJpS@V+f7Yz6a0hwSjt>Ha&P& zrV}VvFW^S9A51p!HfAmO1E1ZsM!hdW%X{l()SE!+x;sYwC`*IPRE zN5WMBEPFvNlJ*g#7Jm7wECBe>&KSvEFu82dSlE7qMt*KIdJ-{mpRqz7Oa>|ehIBcB zT`~G1C&C4URzO;RDx_Hu`akRzcscd^68Z_;vJk1go8bkTlR?D1 z&**<}CM+_*1U9d*Ld#qU)EJRqSt!*LvCYx?#Q=CB7swG+rJoZu3uc>=1X)69B8pMm z49jSa(h-EQ^%w9FBKCosfk$Uwg4qO-WWP|FhDggu0xdD;1&X;*4H_rHEl0rUTInc4 zL`A?JQYp+(k~QQ7s}$C#mk(hMA_>Go=>QQkp&ImPjts@LPgnkS0QMz8JVfP+i%8Jx zy!p}s4_(xZ5eEC=rnSgjgK@wVgu$Vh&V2 zvSMfQ$Dq3?x9%WqI}kbK9Tj18oG)bUB0M+4=3`E=P!}JZxD}dDdjPTZWhMUb4GY}) zZSmHep9#_xw}js@s_FnWTONELbunfv9*c%=AV9@9$ts{N-By0=Cy4rJw&-AW!2pByLw9#~g~pJp-v7-PNg$LZ_)|ng=3bpu-0;YV z{wV7mcYu3n$1rGJy=HE+J9cf^Jdmj|gf=;BcxXXmz4HqW4z3vB0uHC5qC$|a-Fdnw z!c;oC-YOQ0ZTM#WbxMk7m8I z!6{ioeV;~9Y8^~jQ^>_`wl|{+#2Zxi>!*}zJ1dojJ3G?0`09RGts!f1;$;}6MsZs? zBu^yrhacZSq`s2oX;v(G&7=j}V3f`leyP ztj-y1dC=0L4PCNKs;{rVsQpU4AI~UcQuqz^_2;T*<7CQ5=R$5P71gr* zXSJ0@;-lR-iy)daE)s9BCSu8}1?8RX9UZGb)dZK0-Sp*rn2?a* z5OLzf3clWkHHQ1@thp$dZ2dxRC=b=ObWAQ3zL_r`%o|;cU2^m?9)~I0k~tx5t6>9q rBH3tlh}4mXUn86WMkRpX7*_qJB=g{L!@rE?HmGVF_Zv_;P`v^^T=Qr&41HSjZ_rBP;n8@$0ggRUUOauXh zLSaQkh1qO2nM_8b(O@v>^?IF7r`2jT8jV`5R;g4<=^weT>p4##rwYMwZ4Es9zWw*T zuS8=6WnowORdMY^(aXrY>mPaTq)~fK^h1|@>tn2f@Ph@xKk+-7#z+bE@V*N>)-aUB z_Vii)8;XRMJXp97!JtmJr;auMBnZFxk&2aecdMI6a^HKOX#s^76yxa|Iy$3 z$)FgcTpsQ3+q7tx1-}pcE%)=L)u5ao9T@oEF2KMAjFV^TLauWFdEtTct$g-F_n5%N zM|;ktEAYsc|-M@8$eOD3B#4Dc5zIIx??;B@dM2vm7r#P%v7p77xF?jm@B0> zHo6omKt>*=jsCT$Q9V)#bj1y`Q9+RLAqDVQ_Fml48 zGK@xp4jaX%y>1%c!w$6=KOiI2#<7Ih!=~}G=Wm)O5>r}ClNYnpCP{LBOS}7N@2AS? zR8ossiXL;x^S-tx8R(Nv|0{R)p1j2}mt#?9%|8Y|5(b%6EuFh5gVXPfKT8uN2u)`~n*jbLr zb;lB%4#C(i@QmZdd;&0n%if)>eF$;ALI?|d>rttF6o{;KK{5CJ*rk0OhOKo?ferdd z>HnHZd$~J{JGkGbMSr(d>z)rA^7HuR_yoMpql`Ng5T*Mg0qfVsaHIt%=?W8tb)KEv zcSnkM!M=8`_vXNczp2z=Q<3#P67Fz#w+@$qtq03toG7XNm*W2v0zhUi=X;y(3C6Vn z0*d3F^wHxBkPUubJZ?;s{wW>}ZGgVXgD2^ql?xjJB6z&`Z2fbBYhz$+9REzEzJ!ci z4Z5(}JjT?&pko_DQ{n_kQhg~?*mxw1C%9zOm$6)lVYywDOAZU=TqN~Y!W+GBGt>aw$k8CU_<@g+;EW=l^x}*2mJn!n9QpJi`1`^nW1Y8%923ERUz}~M zhqyJtV&NbDh+l08L^Z+B^FNe!8yoFmxF%#u@C(M2kr*jziqGPYRojfDXt(BseE4{s zkBJOJHJ>Ttj}xOzO$oT>vn2RLbCRh!an|K$27jV8+eArrqa4!>l2N~6peqJD*>^8q)@QTqXh#9HW%wURIZq=UZ zp0k-dS#GTv`Nym6do4^Zs`XBp;9^jerAv%!{gs56g(X?Kr$nupor2koY_F%k@1ot~ zAm;RymfpMcAX2tOFlX+z^l5RloS8MTO={`4ifH#Og86NmWdN|7jsYQ)bAS$j+YJ1av?INS=X-lSggE$=AI1jaV71 E0X2~e1poj5 diff --git a/src/icons/skin/uploading.png b/src/icons/skin/uploading.png deleted file mode 100644 index 8e37968c7974d2bbc06f33f8a3cde10a7da52759..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2364 zcmd^>`B#%y8pm(mzJ<3gn2e4F5Qxb^l*I;O4JeR+fuP7DFfyoZA`nDHsBB>id1Eb$ zrV>#E1R;XV5!(?Isw_f+3m6pvEh@5gj6gUdnaCCbgn85c5&dEAIrn_;eV*_0dF~JQ zoO^Qv{n@Kmn5_T+tls0p3IYI!EpY%b!sKxLjVMgu1kXJo2sSd1$Q*3{)%QMO2>_Tp zGE7{7oryUB$j}~^M@UNPr#?>fAm6k@Gv;!v=>W^O&)%eztRE--;=MA#iD-+IbXL>% z(DCYlN1LB;Nn4z3E1XO#{8p?@rkF>k@4p5djyZ4W`(UZD!4|Z&~SExUF zE&e;K-`-_8vrE0Obe|I{DqUN4ZYnk5Mef&K{EIlrZ@KP(xe)>g1)$WwRBFHNF(xth z{;c@K3z&_g(GrG_ZXFDtjA$#ob_8a6?fn=vd#RXld#7H%!Gxi$>+O`aI@4z+d+XzC znuV`A-Axm%%|@S14XzWw-u6|#WiJb3%LSu9p0v_EpE$f_j$X4;#jiQVq!s5Psh=jNfeulO*pAg%$`C zKVmqcD}+Zi91l30fMz-BPY^`Tu+&2=#2Opnq7mh=B_Y}p7Y&rdF63@|h#D@I@mW$A zn0tmOT+U(A5P1$&-$oGiPyj`)&CW)|>v2S+& zOecu+c+?_%@e>M9QiCFPonDM z@glxAxb;B$Y&U$@8|*l;I6{Wruz@~LQ<#SwJ_m@(P)~Ts-yMiKYX}XVJ2BlrcuO(| z?Q6&+Gti!QB@O-n$+f4x89{u$L^Tn1HwlujfU+Zb9fd@|@>he-F*P{uqN*SWK5GJ$ zY*`37Fa{7AMpbwb`3t$$(Y}f;Z2;8FRfiOWEw(^xRT*>~K5JmyC?JZ+7`*4wOR_|O z)m%9c1m7`X-U+GtFz1-L{bYFZe`0vEBazi-TY2~}V|l(X-4L2K?cVNKm-6nSz(#l8 zBhnm=9DlsK#?RGEU|c_#nV~UOyi`}HRiSrrwNL%Exog8@OP=}xht%F;#Y`phGR{Y# zpMNQG>+%}L6%|`t5$I0aJo`LT!~+8pd9Pj_eO;*rJ5p_RXlA4-pru>u0JrY8W;$DC zuDiek`D62`D@U3>#g*%Pr&ljMaRRZe44o0Tj&^UUFZj+n0lVhTD(2qV9+f%TX`)|Z zSS8Z)S}Q}tjN}f3y2Xg#bPPX~-#&TX{hAdP9OxMSl|S-AMMDqrl7$8$4Mas1Fg6Mx zZdCHA*w2)x@u?pEG^HOj^t+7(__^Z+#f3{s#{5W4(p4<9G)8)}T zOWIrn=C=EYxyzp3JX$!~#AgjdZoW3nb740#Ed?E?^Y`~)h1$DY~j#bPU_gJg89(F#UWL{(La2^(C3Ax6WPm6iSwc5 zZkqmIRS~r<555!j_5EESmkjngrbjLNsT=RRzFE51xYV29Vk-D8*)~8{?A)r2oVMr= zJ_vR+$lg46zo$u<*t)C7@eqv$q3ygSYZBUq2TURkoFV+52)f=UDx!zZO3~l0Zt0=l zpn#K-#dg(N@6eD<*PJg7%YEbeQy7YRzvCJ*AJF`+nNg&v{N+x$w*9;2u5->a&{F{;^#SofeID zy3701G#cafUCQyoQT;X5AtreD_>(t%d8V;ZF|G>s=4H(EmS5@LP@$G*VQ<*)wv)=T zi4DF97p;Wjg7j8~n;^YQK4?@C!njYM=IP}jw_Zg417*uOI}*?cX3A-DgxSG zYY_>KpForK4aCl>B9fohHHMgRAm{-CNMZo~V$mDte>ZNt|4nrw_Wc2Sy!=_WJh`X; E2XRQWFaQ7m diff --git a/src/icons/slow.png b/src/icons/slow.png deleted file mode 100644 index 0d978fc708bb5b2877e5f7b2acba6722636f0299..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1375 zcmV-l1)%zgP)ZbLql}^`t@NV z`eEn10sn>Zi=Se)?V1Y4ovtpqiAmRbdwYrD2?m403qqQko1@2%AJgFAAdQcY)AI7N zBoBwfB;aSXwY3pjB@ty~2Ye3y!ow?H#|Yoi(V;zi_Kdtq@;u{U%pHNZns;IhK2lm4>6+G*Vkj8BYN80SZHtlj=F)E z+ueQ6)wOl!+Ulw}NMBvNNLf}Z)z#HeOG^tiH8oK~Lj#>TbB1baYUuRo(^OSeMd|73 zl$w@CeSLkjxw%Oj8yi9iKi6E6K1b*$vJ9Pl-+KR(qcr|~J(W^qC@O$9*o$B78b(+s^)YKfewqe%RSMgT+6AX3SL3DB^-pNhC$MzPa z*#7{GQCM`kz_mpTXJg{5EEWr*qN1cXnM^WMm9w^5t*EZ40Yj*uo0^*PaHh7LoSdL) z-M8-=5kcUK^IzhFcPsFF#u2o2^Z+g&UVI@D?`gO3QQvu_O?HFKaWL}bCW9VEqY)7i z5#mzm4F&^@Y(ylL;QEP21euwcW|lRT6|t%d3k#VdDyODlZgvJ4>FIF%HI449BWQiH z#H3qLB9oA4aHA%20H50$vDYzyfMNitI)DI0k(H5N&xAaeh~Qvu-n=QZPDn^l78e$j zSq?&F-Hp5hYYqo??cNOz0A8OT*~&49;`@TLyr1=1`5d=~l*bqiNvS)D~N z6hMGw=1vqu(i4%)nja7GEiJ&NQ`MhTkJk%kCi~N;Qli<}S+b6E|=>Sjv#`g3$lNM2Nz3AOL7F3S5|nB z3-NvzYX7_%_M3F-H}QvQWzRk(F+Nrj#Kgo%V=~dPQc^}guj#p=d_1RPJcp;iGos*m z2nnoQ+dL-AXX1SRyUAaipMPy&QA-`^>7<{3yc+HsxKDQ5^a*bFLu~o;^Yi&!f4QH7 h&tnO#_y_oR>^W6Xd002ovPDHLkV1iH&itYda diff --git a/src/icons/slow_off.png b/src/icons/slow_off.png deleted file mode 100644 index 930663e7899f121adf9f308acecb5f88c21234e0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1414 zcmV;11$p|3P)+z*h;IKSgp}$(nQmT)`T`OeX;btB=)7RHfc;- zlP3CNjJC#jYp5!rZLk6YK??{7!Y;52?EN}BbNZjL8k;ojNhWh~+1b+F-TidmzI{&;i3Bec3d}GJNRk9aQQ&g9u&}Uj%>vxSFUinKB33W&-bNuFEAJY{4w|tiRhBLt7W_1(a{mBt*v#Jl$3By(^xv4 zMtgfZdV70ex7$(b^MR3^#0=4B)ROk-(W7W>ZACJfgs@^{WQ5Jl&0+WM-5yd$^7(wx ze*z8+DR0zoD%`krC$_b|&IEXg+wI1wQ>XC#nKL+i=n%*sYeVwK0wOYCj6oDcMS?iu z+}X2eY;3gN&CJZ`@pxQqZf^F_ckvg1J%5g|*K5}E-+KGQt12s(*=ec6<>CkSzALR; zzaBex>_m7W43bZT2_&EJ2dPvFQE3c``Sdw12aG{^5SE{roH-E;f z8){(8PVi7~7qbuiI_;>cEtW4|zT8k*S=mk-s0*Qa?fR`d#-RiI^V4%7gS_CppzDmA zs*q90S|ETT3XiI)P!$DCdd5!YK%O%&(?H{@6}W%(BHl`kqBK0gGRY*@%2pNCeD>9H zWn*>qxkUV#r(d2ti9PSM$icaglu9Oa$uu-FjpZl=LROua%0fP3ClgR!l982E*o+u< z6&u*1g|K1A7OX%H_SNgKl*%JhQH!{J1&_%^a)rs_70?Ay^%$GUtF~vM7z*zmKVzfUG1F3C&CGX)zo|nct7#>@4DxJPDko!5|pr^93#eENv^s z$0HZDR|-+)Mxn^1X8@-LXg(AoK}cB-9w$Bc{N@Zg$Aa+K2k^nCZB~jcbtLIWB}rya z1_GQ?$Am946pBnbWqG8KH-@S~QWYkvHtb4GVoQFSnIf?&XQqqMJrC$}h~#|uDe6P} za2l>$5+d;n;gDrThK`8H1F2Q3)NR^yd~AIDG$kxY-Gg7haRbpvM5C%C0qS%*A<0%a z_{Dfa|L{#&GbuQnk&kYUsi+sN-5CsJP0U4l;3%?#dA(S(X0=&axjo-~@16)1Tf26x zjqb-80K{Uk(^Sc8RDq3RO}W&!QA37kPvT&UIY|$bLbCVKS!0JbF9!&-W7$EbdrFa} zV3ZPwi?Tp%%sP+apM=Kmln;g4U5*;SLu!}D+3f5r^ZWh$fr07i>E`C$n=bM1T00001bW%=J06^y0W&i*HOG!jQR0ti7z*P=_Fc1a6S1<1F z6uJKm$?{La;3u_Zhr-Ji*IoA(ByX7GQw5?~7$;nV$S6qtS%SFL?B-lRMAr`GDDV=@ b;{x9v{sIGC`}}`Q00000NkvXXu0mjf@NSAQ diff --git a/src/icons/sphere2.png b/src/icons/sphere2.png deleted file mode 100644 index da431f16aacba9211a30bfdcba3538577a298a63..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 277 zcmV+w0qXvVP) diff --git a/src/icons/url.png b/src/icons/url.png deleted file mode 100644 index cc0930ff1b142dfe52b1778e35d122d31ee4fe4c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 646 zcmV;10(t$3P)&!Egr+$eQ?LM@mRTeOep zbPfj5V=88{gjSOpHj~GEn_UXc{?VPI$;50v`uu7N`V@-J0l9b(TbsGn@=F)-U%fzZ~y2f5qX5UcByFPLe$V@04*lXB@M>5t( z6-6shqF+;fDSnk;yS5R?um8)km-JJxUGlpU#f@#O<;NKBf6DODLzDNZikeUSiCHCr z*>u7pd$EEiZaDqp09UJLz2a*4V g$bO)@l?D#~1GWD4uVd6Wl>h($07*qoM6N<$g4d`u!T - - 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) -}