diff --git a/README.MD b/README.MD index 22dddae..f4876c3 100644 --- a/README.MD +++ b/README.MD @@ -13,31 +13,31 @@ ### Clone this repo (Windows) 1. Clone or download this repo as a .ZIP 2. Move it somewhere where qBittorrent can find it. +3. Ensure you use a trailing slash. ### Clone this repo (Linux) -1. `cd /opt` -2. `sudo git clone https://github.com/repslet/nightwalker.git` -3. `sudo chmod -R 777 nightwalker` +1. `sudo git clone https://github.com/brettpetch/nightwalker.git /opt/nightwalker` +3. `sudo chown -R nobody:nogroup /opt/nightwalker/` ### Activate Alterative WebUI in qBittorrent 1. Under `Tools->Preferences->WebUI` enable `Use alternative WebUI`. -2. Choose a location that points to the `Nightwalker` folder, i.e. `/opt/nightwalker` +2. Choose a location that points to the `nightwalker` folder, i.e. `/opt/nightwalker/` 3. Restart qBittorrent or refresh your browser for changes to take effect. You can also change these settings via the config file. The relevant entries are: -- WebUI\AlternativeUIEnabled=true -- WebUI\RootFolder=/path/to/Nightwalker +- `WebUI\AlternativeUIEnabled=true` +- `WebUI\RootFolder=/opt/nightwalker/` ### Update theme (Linux) -1. `cd /opt/nightwalker` -2. `git checkout main` -3. `git fetch origin main` -4. `git reset --hard origin/main` +1. `git -C /opt/nightwalker checkout main` +2. `git -C /opt/nightwalker fetch origin main` +3. `git -C /opt/nightwalker reset --hard origin/main` +4. `sudo chown -R nobody:nogroup /opt/nightwalker` ### Tested -Based on the standard qBittorrent WebUI theme (4.3.2 release). -Tested in 4.3.1 and 4.3.2 +Based on the standard qBittorrent WebUI theme (4.3.8 release). +Tested in Updated to 4.3.8 #### A note for those who used the [Theme Park][theme.park] nginx mod Modify your nginx config and remove the lines that introduced the external css, anything after `rewrite ^/qbittorrent/(.*) /$1 break; ` (non inclusive) is something that can be removed. Do not leave -modded, or any other files that are not necessary for nginx to function in the `/etc/nginx/apps/` directory. Reload nginx after making changes by doing `sudo service nginx configtest`, if it returns OK, then proceed and do `sudo service nginx reload`. diff --git a/private/addpeers.html b/private/addpeers.html index f128349..e4760d6 100644 --- a/private/addpeers.html +++ b/private/addpeers.html @@ -1,70 +1,72 @@ - - - QBT_TR(Add Peers)QBT_TR[CONTEXT=PeersAdditionDialog] - - - - - + + - + }); + + - -
-

QBT_TR(List of peers to add (one IP per line):)QBT_TR[CONTEXT=PeersAdditionDialog]

- -
- - -
+ +
+

QBT_TR(List of peers to add (one IP per line):)QBT_TR[CONTEXT=PeersAdditionDialog]

+ +
+ +
- +
+ + diff --git a/private/addtrackers.html b/private/addtrackers.html index b4c7f8e..bb9978d 100644 --- a/private/addtrackers.html +++ b/private/addtrackers.html @@ -6,8 +6,8 @@ QBT_TR(Trackers addition dialog)QBT_TR[CONTEXT=TrackersAdditionDialog] - - + + - + + - + + - + + - + + - + + @@ -17,7 +17,7 @@
-
+

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/private/downloadlimit.html b/private/downloadlimit.html index 9b1bef8..3aa937f 100644 --- a/private/downloadlimit.html +++ b/private/downloadlimit.html @@ -6,9 +6,9 @@ QBT_TR(Torrent Download Speed Limiting)QBT_TR[CONTEXT=TransferListWidget] - - - + + + diff --git a/private/edittracker.html b/private/edittracker.html index 1160ae7..5e84244 100644 --- a/private/edittracker.html +++ b/private/edittracker.html @@ -6,8 +6,8 @@ QBT_TR(Tracker editing)QBT_TR[CONTEXT=TrackerListWidget] - - + + - - + + + - + @@ -49,69 +47,69 @@

qBittorrent Web User Interface QBT_TR(File)QBT_TR[CONTEXT=MainWindow]
  • QBT_TR(Edit)QBT_TR[CONTEXT=MainWindow]
  • QBT_TR(View)QBT_TR[CONTEXT=MainWindow]
  • QBT_TR(Tools)QBT_TR[CONTEXT=MainWindow]
  • QBT_TR(Help)QBT_TR[CONTEXT=MainWindow]
  •    - QBT_TR(Add Torrent Link...)QBT_TR[CONTEXT=MainWindow] - QBT_TR(Add Torrent File...)QBT_TR[CONTEXT=MainWindow] - QBT_TR(Delete)QBT_TR[CONTEXT=TransferListWidget] - QBT_TR(Resume)QBT_TR[CONTEXT=TransferListWidget] - QBT_TR(Pause)QBT_TR[CONTEXT=TransferListWidget] + QBT_TR(Add Torrent Link...)QBT_TR[CONTEXT=MainWindow] + QBT_TR(Add Torrent File...)QBT_TR[CONTEXT=MainWindow] + QBT_TR(Delete)QBT_TR[CONTEXT=TransferListWidget] + QBT_TR(Resume)QBT_TR[CONTEXT=TransferListWidget] + QBT_TR(Pause)QBT_TR[CONTEXT=TransferListWidget] - QBT_TR(Top of Queue)QBT_TR[CONTEXT=MainWindow] - QBT_TR(Move Up Queue)QBT_TR[CONTEXT=MainWindow] - QBT_TR(Move Down Queue)QBT_TR[CONTEXT=MainWindow] - QBT_TR(Bottom of Queue)QBT_TR[CONTEXT=MainWindow] + QBT_TR(Top of Queue)QBT_TR[CONTEXT=MainWindow] + QBT_TR(Move Up Queue)QBT_TR[CONTEXT=MainWindow] + QBT_TR(Move Down Queue)QBT_TR[CONTEXT=MainWindow] + QBT_TR(Bottom of Queue)QBT_TR[CONTEXT=MainWindow] - QBT_TR(Options)QBT_TR[CONTEXT=OptionsDialog] + QBT_TR(Options)QBT_TR[CONTEXT=OptionsDialog]
      -
    • QBT_TR(Rename...)QBT_TR[CONTEXT=PropertiesWidget] QBT_TR(Rename...)QBT_TR[CONTEXT=PropertiesWidget]
    • +
    • QBT_TR(Rename...)QBT_TR[CONTEXT=PropertiesWidget] QBT_TR(Rename...)QBT_TR[CONTEXT=PropertiesWidget]
    • QBT_TR(Priority)QBT_TR[CONTEXT=PropertiesWidget]
        @@ -230,7 +228,7 @@

        qBittorrent Web User Interface QBT_TR(Connection status)QBT_TR[CONTEXT=MainWindow] - QBT_TR(Alternative speed limits)QBT_TR[CONTEXT=MainWindow] + QBT_TR(Alternative speed limits)QBT_TR[CONTEXT=MainWindow] QBT_TR(Download speed icon)QBT_TR[CONTEXT=MainWindow] diff --git a/private/newcategory.html b/private/newcategory.html index 798619d..8505645 100644 --- a/private/newcategory.html +++ b/private/newcategory.html @@ -6,8 +6,8 @@ QBT_TR(New Category)QBT_TR[CONTEXT=TransferListWidget] - - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + + diff --git a/private/uploadlimit.html b/private/uploadlimit.html index 2b295df..12cfcc5 100644 --- a/private/uploadlimit.html +++ b/private/uploadlimit.html @@ -6,9 +6,9 @@ QBT_TR(Torrent Upload Speed Limiting)QBT_TR[CONTEXT=TransferListWidget] - - - + + + diff --git a/private/views/about.html b/private/views/about.html index 4463a1e..92042cb 100644 --- a/private/views/about.html +++ b/private/views/about.html @@ -82,7 +82,10 @@

        QBT_TR(Original authors)QBT_TR[CONTEXT=HttpServer]

    - +
    @@ -127,22 +127,6 @@ - - - - -
    - - - Add -
    - - - @@ -246,7 +230,7 @@
    - +
    @@ -658,6 +642,7 @@ + @@ -675,6 +660,7 @@ + @@ -684,6 +670,7 @@ + @@ -803,7 +790,8 @@
    - + +
    @@ -1094,6 +1082,14 @@ + + + (?) + + + + + @@ -1129,6 +1125,14 @@ + + + + + + + + @@ -1191,7 +1195,7 @@ - + @@ -1199,31 +1203,31 @@ - - + +   % - - + +   % - - + +   s - +
    @@ -1274,37 +1278,17 @@ }; // Downloads tab - const WatchedFoldersTable = new HtmlTable($("watched_folders_tab")); + const watchedFoldersTable = new HtmlTable($("watched_folders_tab")); const updateTempDirEnabled = function() { const isTempDirEnabled = $('temppath_checkbox').getProperty('checked'); $('temppath_text').setProperty('disabled', !isTempDirEnabled); }; - const addWatchFolder = function() { - const new_folder = $('new_watch_folder_txt').getProperty('value').trim(); - if (new_folder.length <= 0) return; - - const new_other = $('new_watch_folder_other_txt').getProperty('value').trim(); - if (new_other.length <= 0) return; - - const new_select = $('new_watch_folder_select').getProperty('value').trim(); - - const i = $('watched_folders_tab').getChildren('tbody')[0].getChildren('tr').length; - pushWatchFolder(i, new_folder, new_select, new_other); - - // Clear fields - $('new_watch_folder_txt').setProperty('value', ''); - const elt = $('new_watch_folder_select'); - elt.setProperty('value', 'watch_folder'); - const text = elt.options[elt.selectedIndex].innerHTML; - $('new_watch_folder_other_txt').setProperty('value', text); - }; - - const changeWatchFolderSelect = function(item) { - if (item.value == "other") { + const changeWatchFolderSelect = (item) => { + if (item.value === "other") { item.nextElementSibling.hidden = false; - item.nextElementSibling.value = 'QBT_TR(Type folder here)QBT_TR[CONTEXT=HttpServer]'; + item.nextElementSibling.value = 'QBT_TR(Type folder here)QBT_TR[CONTEXT=ScanFoldersModel]'; item.nextElementSibling.select(); } else { @@ -1314,40 +1298,47 @@ } }; - const pushWatchFolder = function(pos, folder, sel, other) { + const addWatchFolder = (folder = "", sel = "default_folder", other = "") => { + const pos = $('watched_folders_tab').getChildren('tbody')[0].getChildren('tr').length; const myinput = ""; - const disableInput = (sel != "other"); + const disableInput = (sel !== "other"); const mycb = "
    " + "" - + "
    "; + + "" + + "Add" + + "
    "; - WatchedFoldersTable.push([myinput, mycb]); + watchedFoldersTable.push([myinput, mycb]); $('cb_watch_' + pos).setProperty('value', sel); if (disableInput) { const elt = $('cb_watch_' + pos); other = elt.options[elt.selectedIndex].innerHTML; } $('cb_watch_txt_' + pos).setProperty('value', other); + + // hide previous img + if (pos > 0) + $('addFolderImg_' + (pos - 1)).style.display = "none"; }; - const getWatchedFolders = function() { + const getWatchedFolders = () => { const nb_folders = $("watched_folders_tab").getChildren("tbody")[0].getChildren("tr").length; const folders = new Hash(); for (let i = 0; i < nb_folders; ++i) { const fpath = $('text_watch_' + i).getProperty('value').trim(); if (fpath.length > 0) { - let other; const sel = $('cb_watch_' + i).getProperty('value').trim(); - if (sel == "other") { + + let other; + if (sel === "other") other = $('cb_watch_txt_' + i).getProperty('value').trim(); - } - else { - other = (sel == "watch_folder") ? 0 : 1; - } + else + other = (sel === "watch_folder") ? 0 : 1; + folders.set(fpath, other); } } @@ -1654,19 +1645,19 @@ updateExportDirFinEnabled(); // Automatically add torrents from - let i = 0; - for (const folder in pref.scan_dirs) { - let sel; + for (const [folder, folderType] of Object.entries(pref.scan_dirs)) { + let sel = ""; let other = ""; - if (typeof pref.scan_dirs[folder] == "string") { - other = pref.scan_dirs[folder]; - sel = "other"; + if (typeof folderType === "number") { + sel = (folderType === 0) ? "watch_folder" : "default_folder"; } else { - sel = (pref.scan_dirs[folder] == 0) ? "watch_folder" : "default_folder"; + sel = "other"; + other = folderType; } - pushWatchFolder(i++, folder, sel, other); + addWatchFolder(folder, sel, other); } + addWatchFolder(); // Email notification upon download completion $('mail_notification_checkbox').setProperty('checked', pref.mail_notification_enabled); @@ -1920,10 +1911,12 @@ $('outgoingPortsMin').setProperty('value', pref.outgoing_ports_min); $('outgoingPortsMax').setProperty('value', pref.outgoing_ports_max); $('UPnPLeaseDuration').setProperty('value', pref.upnp_lease_duration); + $('peerToS').setProperty('value', pref.peer_tos); $('utpTCPMixedModeAlgorithm').setProperty('value', pref.utp_tcp_mixed_mode); $('IDNSupportCheckbox').setProperty('checked', pref.idn_support_enabled); $('allowMultipleConnectionsFromTheSameIPAddress').setProperty('checked', pref.enable_multi_connections_from_same_ip); $('validateHTTPSTrackerCertificate').setProperty('checked', pref.validate_https_tracker_certificate); + $('mitigateSSRF').setProperty('checked', pref.ssrf_mitigation); $('blockPeersOnPrivilegedPorts').setProperty('checked', pref.block_peers_on_privileged_ports); $('enableEmbeddedTracker').setProperty('checked', pref.enable_embedded_tracker); $('embeddedTrackerPort').setProperty('value', pref.embedded_tracker_port); @@ -2308,10 +2301,12 @@ settings.set('outgoing_ports_min', $('outgoingPortsMin').getProperty('value')); settings.set('outgoing_ports_max', $('outgoingPortsMax').getProperty('value')); settings.set('upnp_lease_duration', $('UPnPLeaseDuration').getProperty('value')); + settings.set('peer_tos', $('peerToS').getProperty('value')); settings.set('utp_tcp_mixed_mode', $('utpTCPMixedModeAlgorithm').getProperty('value')); settings.set('idn_support_enabled', $('IDNSupportCheckbox').getProperty('checked')); settings.set('enable_multi_connections_from_same_ip', $('allowMultipleConnectionsFromTheSameIPAddress').getProperty('checked')); settings.set('validate_https_tracker_certificate', $('validateHTTPSTrackerCertificate').getProperty('checked')); + settings.set('ssrf_mitigation', $('mitigateSSRF').getProperty('checked')); settings.set('block_peers_on_privileged_ports', $('blockPeersOnPrivilegedPorts').getProperty('checked')); settings.set('enable_embedded_tracker', $('enableEmbeddedTracker').getProperty('checked')); settings.set('embedded_tracker_port', $('embeddedTrackerPort').getProperty('value')); diff --git a/private/views/propertiesToolbar.html b/private/views/propertiesToolbar.html index 789dc32..aa0c924 100644 --- a/private/views/propertiesToolbar.html +++ b/private/views/propertiesToolbar.html @@ -1,7 +1,7 @@
    - +
      diff --git a/private/views/rss.html b/private/views/rss.html index b2028fb..2f42e95 100644 --- a/private/views/rss.html +++ b/private/views/rss.html @@ -1,19 +1,99 @@ + +
      - - - - - + + + + +
      @@ -58,36 +138,21 @@
      \ No newline at end of file + diff --git a/private/views/rssDownloader.html b/private/views/rssDownloader.html index 4bd0801..891f1f2 100644 --- a/private/views/rssDownloader.html +++ b/private/views/rssDownloader.html @@ -32,7 +32,7 @@
      QBT_TR(Rule Definition)QBT_TR[CONTEXT=AutomatedRssDownloader]
      - +
      @@ -239,8 +239,8 @@ $('rulesTable').style.height = 'calc(100% - ' + $('rulesTableDesc').getBoundingClientRect().height + 'px)'; $('rssDownloaderArticlesTable').style.height = 'calc(100% - ' + $('articleTableDesc').getBoundingClientRect().height + 'px)'; - let centerRowNotTableHeight = $('saveButton').getBoundingClientRect().height + - $('ruleSettings').getBoundingClientRect().height + 15; + let centerRowNotTableHeight = $('saveButton').getBoundingClientRect().height + + $('ruleSettings').getBoundingClientRect().height + 15; $('rssDownloaderFeeds').style.height = 'calc(100% - ' + centerRowNotTableHeight + 'px)'; @@ -320,7 +320,7 @@ let flatten = (root) => { for (let child in root) { if (root[child].uid !== undefined) - feedList.push({name: child, url: root[child].url}); + feedList.push({ name: child, url: root[child].url }); else flatten(root[child]); } @@ -408,11 +408,12 @@ }; const removeRules = (rules) => { + const encodedRules = rules.map((rule) => encodeURIComponent(rule)); new MochaUI.Window({ id: 'removeRulePage', title: 'QBT_TR(Rule deletion confirmation)QBT_TR[CONTEXT=AutomatedRssDownloader]', loadMethod: 'iframe', - contentURL: 'confirmruledeletion.html?rules=' + encodeURIComponent(rules.join('|')), + contentURL: 'confirmruledeletion.html?rules=' + encodeURIComponent(encodedRules.join('|')), scrollbars: false, resizable: false, maximizable: false, @@ -422,11 +423,12 @@ }; const clearDownloadedEpisodes = (rules) => { + const encodedRules = rules.map((rule) => encodeURIComponent(rule)); new MochaUI.Window({ id: 'clearRulesPage', title: 'QBT_TR(New rule name)QBT_TR[CONTEXT=AutomatedRssDownloader]', loadMethod: 'iframe', - contentURL: 'confirmruleclear.html?rules=' + encodeURIComponent(rules.join('|')), + contentURL: 'confirmruleclear.html?rules=' + encodeURIComponent(encodedRules.join('|')), scrollbars: false, resizable: false, maximizable: false, @@ -630,37 +632,36 @@ mainPart = 'QBT_TR(Regex mode: use Perl-compatible regular expressions)QBT_TR[CONTEXT=AutomatedRssDownloader]\n\n'; } else { - mainPart = 'QBT_TR(Wildcard mode: you can use)QBT_TR[CONTEXT=AutomatedRssDownloader]\n\n' + - ' ● QBT_TR(? to match any single character)QBT_TR[CONTEXT=AutomatedRssDownloader]\n' + - ' ● QBT_TR(* to match zero or more of any characters)QBT_TR[CONTEXT=AutomatedRssDownloader]\n' + - ' ● QBT_TR(Whitespaces count as AND operators (all words, any order))QBT_TR[CONTEXT=AutomatedRssDownloader]\n' + - ' ● QBT_TR(| is used as OR operator)QBT_TR[CONTEXT=AutomatedRssDownloader]\n\n' + - 'QBT_TR(If word order is important use * instead of whitespace.)QBT_TR[CONTEXT=AutomatedRssDownloader]\n\n'; + mainPart = 'QBT_TR(Wildcard mode: you can use)QBT_TR[CONTEXT=AutomatedRssDownloader]\n\n' + + ' ● QBT_TR(? to match any single character)QBT_TR[CONTEXT=AutomatedRssDownloader]\n' + + ' ● QBT_TR(* to match zero or more of any characters)QBT_TR[CONTEXT=AutomatedRssDownloader]\n' + + ' ● QBT_TR(Whitespaces count as AND operators (all words, any order))QBT_TR[CONTEXT=AutomatedRssDownloader]\n' + + ' ● QBT_TR(| is used as OR operator)QBT_TR[CONTEXT=AutomatedRssDownloader]\n\n' + + 'QBT_TR(If word order is important use * instead of whitespace.)QBT_TR[CONTEXT=AutomatedRssDownloader]\n\n'; } let secondPart = 'QBT_TR(An expression with an empty %1 clause (e.g. %2))QBT_TR[CONTEXT=AutomatedRssDownloader]' - .replace('%1', '|').replace('%2', 'expr|'); + .replace('%1', '|').replace('%2', 'expr|'); $('mustContainText').title = mainPart + secondPart + 'QBT_TR( will match all articles.)QBT_TR[CONTEXT=AutomatedRssDownloader]'; $('mustNotContainText').title = mainPart + secondPart + 'QBT_TR( will exclude all articles.)QBT_TR[CONTEXT=AutomatedRssDownloader]'; - let episodeFilterTitle = 'QBT_TR(Matches articles based on episode filter.)QBT_TR[CONTEXT=AutomatedRssDownloader]\n\n' + - 'QBT_TR(Example: )QBT_TR[CONTEXT=AutomatedRssDownloader]' + - '1x2;8-15;5;30-;' + - 'QBT_TR( will match 2, 5, 8 through 15, 30 and onward episodes of season one)QBT_TR[CONTEXT=AutomatedRssDownloader]\n\n' + - 'QBT_TR(Episode filter rules: )QBT_TR[CONTEXT=AutomatedRssDownloader]\n\n' + - ' ● QBT_TR(Season number is a mandatory non-zero value)QBT_TR[CONTEXT=AutomatedRssDownloader]\n' + - ' ● QBT_TR(Episode number is a mandatory positive value)QBT_TR[CONTEXT=AutomatedRssDownloader]\n' + - ' ● QBT_TR(Filter must end with semicolon)QBT_TR[CONTEXT=AutomatedRssDownloader]\n' + - ' ● QBT_TR(Three range types for episodes are supported: )QBT_TR[CONTEXT=AutomatedRssDownloader]\n' + - ' ● QBT_TR(Single number: 1x25; matches episode 25 of season one)QBT_TR[CONTEXT=AutomatedRssDownloader]\n' + - ' ● QBT_TR(Normal range: 1x25-40; matches episodes 25 through 40 of season one)QBT_TR[CONTEXT=AutomatedRssDownloader]\n' + - ' ● QBT_TR(Infinite range: 1x25-; matches episodes 25 and upward of season one, and all episodes of later seasons)QBT_TR[CONTEXT=AutomatedRssDownloader]'; + let episodeFilterTitle = 'QBT_TR(Matches articles based on episode filter.)QBT_TR[CONTEXT=AutomatedRssDownloader]\n\n' + + 'QBT_TR(Example: )QBT_TR[CONTEXT=AutomatedRssDownloader]' + + '1x2;8-15;5;30-;' + + 'QBT_TR( will match 2, 5, 8 through 15, 30 and onward episodes of season one)QBT_TR[CONTEXT=AutomatedRssDownloader]\n\n' + + 'QBT_TR(Episode filter rules: )QBT_TR[CONTEXT=AutomatedRssDownloader]\n\n' + + ' ● QBT_TR(Season number is a mandatory non-zero value)QBT_TR[CONTEXT=AutomatedRssDownloader]\n' + + ' ● QBT_TR(Episode number is a mandatory positive value)QBT_TR[CONTEXT=AutomatedRssDownloader]\n' + + ' ● QBT_TR(Filter must end with semicolon)QBT_TR[CONTEXT=AutomatedRssDownloader]\n' + + ' ● QBT_TR(Three range types for episodes are supported: )QBT_TR[CONTEXT=AutomatedRssDownloader]\n' + + ' ● QBT_TR(Single number: 1x25; matches episode 25 of season one)QBT_TR[CONTEXT=AutomatedRssDownloader]\n' + + ' ● QBT_TR(Normal range: 1x25-40; matches episodes 25 through 40 of season one)QBT_TR[CONTEXT=AutomatedRssDownloader]\n' + + ' ● QBT_TR(Infinite range: 1x25-; matches episodes 25 and upward of season one, and all episodes of later seasons)QBT_TR[CONTEXT=AutomatedRssDownloader]'; episodeFilterTitle = episodeFilterTitle.replace(//g, '').replace(/<\/b>/g, ''); $('episodeFilterText').title = episodeFilterTitle; } - initRssDownloader(); return exports(); })(); diff --git a/private/views/search.html b/private/views/search.html index 99d917b..587ffe1 100644 --- a/private/views/search.html +++ b/private/views/search.html @@ -41,7 +41,10 @@ margin-right: 20px; } - #searchMinSeedsFilter, #searchMaxSeedsFilter, #searchMinSizeFilter, #searchMaxSizeFilter { + #searchMinSeedsFilter, + #searchMaxSeedsFilter, + #searchMinSizeFilter, + #searchMaxSizeFilter { width: 4em; } @@ -89,7 +92,7 @@ @@ -114,7 +117,7 @@
      QBT_TR(Seeds:)QBT_TR[CONTEXT=SearchEngineWidget] - to + QBT_TR(to)QBT_TR[CONTEXT=SearchEngineWidget] QBT_TR(Size:)QBT_TR[CONTEXT=SearchEngineWidget] @@ -128,7 +131,7 @@ - to + QBT_TR(to)QBT_TR[CONTEXT=SearchEngineWidget]
      - There aren't any search plugins installed.
      Click the "Search plugins..." button at the bottom right of the window to install some. + There aren't any search plugins installed.
      Click the "Search plugins..." button at the bottom right of the window to install some.