diff --git a/src/webui/www/private/css/style.css b/src/webui/www/private/css/style.css index c47a6a758..44600d285 100644 --- a/src/webui/www/private/css/style.css +++ b/src/webui/www/private/css/style.css @@ -320,6 +320,9 @@ a.propButton img { #mochaToolbar { margin-top: 5px; + position: relative; + height: 29px; + overflow-y: hidden; } #mochaToolbar .divider { @@ -336,6 +339,11 @@ a.propButton img { padding-right: 5px; } +#mainWindowTabs { + float: right; + margin: 4px 5px 0 0; +} + /* Tri-state checkbox */ label.tristate { @@ -550,3 +558,47 @@ td.statusBarSeparator { .statisticsValue { text-align: right; } + +/* Search tab */ + +#SearchPanel, #SearchPanel_wrapper, #SearchPanel_pad { + height: inherit; +} + +#searchResults { + padding: 0 20px; + height: 100%; +} + +#searchResultsTableContainer { + height: calc(100% - 140px); + -moz-height: calc(100% - 140px); + -webkit-height: calc(100% - 140px); + overflow: auto; +} + +#searchResultsTableDiv { + height: calc(100% - 26px) !important; + -moz-height: calc(100% - 26px) !important; + -webkit-height: calc(100% - 26px) !important; +} + +#searchResults .dynamicTable { + width: 100%; +} + +#searchResults .numSearchResults { + font-style: italic; +} + +.red { + color: red; +} + +.green { + color: green; +} + +.searchPluginsTableRow { + cursor: pointer; +} diff --git a/src/webui/www/private/download.html b/src/webui/www/private/download.html index 7cef3f000..de48c7e3f 100644 --- a/src/webui/www/private/download.html +++ b/src/webui/www/private/download.html @@ -81,7 +81,7 @@ }); if (urls.length) - $('urls').set('value', escapeHtml(urls.join("\n"))); + $('urls').set('value', urls.join("\n")); } var submitted = false; diff --git a/src/webui/www/private/index.html b/src/webui/www/private/index.html index b4c2645a0..a04261257 100644 --- a/src/webui/www/private/index.html +++ b/src/webui/www/private/index.html @@ -66,7 +66,8 @@
  • QBT_TR(Top Toolbar)QBT_TR[CONTEXT=MainWindow]QBT_TR(Top Toolbar)QBT_TR[CONTEXT=MainWindow]
  • QBT_TR(Status Bar)QBT_TR[CONTEXT=MainWindow]QBT_TR(Status Bar)QBT_TR[CONTEXT=MainWindow]
  • QBT_TR(Speed in Title Bar)QBT_TR[CONTEXT=MainWindow]QBT_TR(Speed in Title Bar)QBT_TR[CONTEXT=MainWindow]
  • -
  • QBT_TR(Statistics)QBT_TR[CONTEXT=MainWindow]QBT_TR(Statistics)QBT_TR[CONTEXT=MainWindow]
  • +
  • QBT_TR(Search Engine)QBT_TR[CONTEXT=MainWindow]QBT_TR(Search Engine)QBT_TR[CONTEXT=MainWindow]
  • +
  • QBT_TR(Statistics)QBT_TR[CONTEXT=MainWindow]QBT_TR(Statistics)QBT_TR[CONTEXT=MainWindow]
  • @@ -99,6 +100,13 @@ QBT_TR(Minimum Priority)QBT_TR[CONTEXT=MainWindow] QBT_TR(Options)QBT_TR[CONTEXT=OptionsDialog] +
    + +
    +
    diff --git a/src/webui/www/private/installsearchplugin.html b/src/webui/www/private/installsearchplugin.html new file mode 100644 index 000000000..87f277657 --- /dev/null +++ b/src/webui/www/private/installsearchplugin.html @@ -0,0 +1,69 @@ + + +
    +

    QBT_TR(Plugin path:)QBT_TR[CONTEXT=PluginSourceDlg]

    + +
    + +
    + +
    +
    +
    +
    + + diff --git a/src/webui/www/private/scripts/client.js b/src/webui/www/private/scripts/client.js index f99ac217b..230e242d0 100644 --- a/src/webui/www/private/scripts/client.js +++ b/src/webui/www/private/scripts/client.js @@ -24,6 +24,8 @@ torrentsTable = new TorrentsTable(); torrentPeersTable = new TorrentPeersTable(); +searchResultsTable = new SearchResultsTable(); +searchPluginsTable = new SearchPluginsTable(); var updatePropertiesPanel = function() {}; @@ -76,8 +78,9 @@ window.addEvent('load', function() { }; window.addEvent('resize', function() { - // Resizing might takes some time. - saveColumnSizes.delay(200); + // only save sizes if the columns are visible + if (!$("mainColumn").hasClass("invisible")) + saveColumnSizes.delay(200); // Resizing might takes some time. }); /*MochaUI.Desktop = new MochaUI.Desktop(); @@ -87,22 +90,40 @@ window.addEvent('load', function() { });*/ 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: [1, 300] - }); - new MochaUI.Column({ - id: 'mainColumn', - placement: 'main' - }); + var buildTransfersTab = function() { + 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: [1, 300] + }); + + new MochaUI.Column({ + id: 'mainColumn', + placement: 'main' + }); + }; + + var buildSearchTab = function() { + new MochaUI.Column({ + id: 'searchTabColumn', + placement: 'main', + width: null + }); + + // start off hidden + $("searchTabColumn").addClass("invisible"); + }; + + buildTransfersTab(); + buildSearchTab(); + MochaUI.initializeTabs('mainWindowTabsList'); setCategoryFilter = function(hash) { selected_category = hash; @@ -184,6 +205,15 @@ window.addEvent('load', function() { $('speedInBrowserTitleBarLink').firstChild.style.opacity = '0'; // After showing/hiding the toolbar + status bar + var showSearchEngine = localStorage.getItem('show_search_engine') === "true"; + if (!showSearchEngine) { + // uncheck menu option + $('showSearchEngineLink').firstChild.style.opacity = '0'; + // hide tabs + $('mainWindowTabs').addClass('invisible'); + } + + // After Show Top Toolbar MochaUI.Desktop.setDesktopSize(); var syncMainDataLastResponseId = 0; @@ -543,8 +573,83 @@ window.addEvent('load', function() { processServerState(); }); + $('showSearchEngineLink').addEvent('click', function(e) { + showSearchEngine = !showSearchEngine; + localStorage.setItem('show_search_engine', showSearchEngine.toString()); + if (showSearchEngine) { + $('showSearchEngineLink').firstChild.style.opacity = '1'; + $('mainWindowTabs').removeClass('invisible'); + + addMainWindowTabsEventListener(); + if (!MochaUI.Panels.instances.SearchPanel) + addSearchPanel(); + } + else { + $('showSearchEngineLink').firstChild.style.opacity = '0'; + $('mainWindowTabs').addClass('invisible'); + $("transfersTabLink").click(); + + removeMainWindowTabsEventListener(); + } + }); + $('StatisticsLink').addEvent('click', StatisticsLinkFN); + // main window tabs + + var showTransfersTab = function() { + $("filtersColumn").removeClass("invisible"); + $("filtersColumn_handle").removeClass("invisible"); + $("mainColumn").removeClass("invisible"); + hideSearchTab(); + }; + + var hideTransfersTab = function() { + $("filtersColumn").addClass("invisible"); + $("filtersColumn_handle").addClass("invisible"); + $("mainColumn").addClass("invisible"); + MochaUI.Desktop.resizePanels(); + }; + + var showSearchTab = function() { + $("searchTabColumn").removeClass("invisible"); + hideTransfersTab(); + }; + + var hideSearchTab = function() { + $("searchTabColumn").addClass("invisible"); + MochaUI.Desktop.resizePanels(); + }; + + var addMainWindowTabsEventListener = function() { + $('transfersTabLink').addEvent('click', showTransfersTab); + $('searchTabLink').addEvent('click', showSearchTab); + }; + + var removeMainWindowTabsEventListener = function() { + $('transfersTabLink').removeEvent('click', showTransfersTab); + $('searchTabLink').removeEvent('click', showSearchTab); + }; + + var addSearchPanel = function() { + new MochaUI.Panel({ + id : 'SearchPanel', + title : 'Search', + header : false, + padding : { + top : 0, + right : 0, + bottom : 0, + left : 0 + }, + loadMethod : 'xhr', + contentURL : 'search.html', + content: '', + column : 'searchTabColumn', + height : null + }); + }; + new MochaUI.Panel({ id: 'transferList', title: 'Panel', @@ -658,6 +763,12 @@ window.addEvent('load', function() { column: 'mainColumn', height: prop_h }); + + if (showSearchEngine) { + addMainWindowTabsEventListener(); + addSearchPanel(); + } + }); function closeWindows() { @@ -677,6 +788,8 @@ function setupCopyEventHandler() { return copyMagnetLinkFN(); case "CopyHash": return copyHashFN(); + case "copyDescriptionPageUrl": + return copySearchTorrentUrl(); default: return ""; } diff --git a/src/webui/www/private/scripts/contextmenu.js b/src/webui/www/private/scripts/contextmenu.js index 2c26dc037..b41c9e538 100644 --- a/src/webui/www/private/scripts/contextmenu.js +++ b/src/webui/www/private/scripts/contextmenu.js @@ -400,3 +400,21 @@ var CategoriesFilterContextMenu = new Class({ } } }); + +var SearchPluginsTableContextMenu = new Class({ + Extends: ContextMenu, + + updateMenuItems: function () { + var enabledColumnIndex = function(text) { + var columns = $("searchPluginsTableFixedHeaderRow").getChildren("th"); + for (var i = 0; i < columns.length; ++i) + if (columns[i].get("html") === "Enabled") + return i; + }; + + this.showItem('Enabled'); + this.setItemChecked('Enabled', this.options.element.getChildren("td")[enabledColumnIndex()].get("html") === "Yes"); + + this.showItem('Uninstall'); + } +}); diff --git a/src/webui/www/private/scripts/dynamicTable.js b/src/webui/www/private/scripts/dynamicTable.js index ae5121569..13cc1e724 100644 --- a/src/webui/www/private/scripts/dynamicTable.js +++ b/src/webui/www/private/scripts/dynamicTable.js @@ -1384,4 +1384,165 @@ var TorrentPeersTable = new Class({ } }); +var SearchResultsTable = new Class({ + Extends: DynamicTable, + + initColumns: function () { + this.newColumn('fileName', '', 'QBT_TR(Name)QBT_TR[CONTEXT=SearchResultsTable]', 500, true); + this.newColumn('fileSize', '', 'QBT_TR(Size)QBT_TR[CONTEXT=SearchResultsTable]', 100, true); + this.newColumn('nbSeeders', '', 'QBT_TR(Seeders)QBT_TR[CONTEXT=SearchResultsTable]', 100, true); + this.newColumn('nbLeechers', '', 'QBT_TR(Leechers)QBT_TR[CONTEXT=SearchResultsTable]', 100, true); + this.newColumn('siteUrl', '', 'QBT_TR(Search engine)QBT_TR[CONTEXT=SearchResultsTable]', 250, true); + + this.initColumnsFunctions(); + }, + + initColumnsFunctions: function () { + var displayText = function (td, row) { + var value = this.getRowValue(row); + td.set('html', escapeHtml(value)); + } + var displaySize = function(td, row) { + var size = this.getRowValue(row); + td.set('html', friendlyUnit(size, false)); + } + var displayNum = function (td, row) { + var value = escapeHtml(this.getRowValue(row)); + td.set('html', (value === "-1") ? "Unknown" : value); + } + + this.columns['fileName'].updateTd = displayText; + this.columns['fileSize'].updateTd = displaySize; + this.columns['nbSeeders'].updateTd = displayNum; + this.columns['nbLeechers'].updateTd = displayNum; + this.columns['siteUrl'].updateTd = displayText; + }, + + getFilteredAndSortedRows: function () { + var containsAll = function(text, searchTerms) { + text = text.toLowerCase(); + for (var i = 0; i < searchTerms.length; ++i) { + if (text.indexOf(searchTerms[i].toLowerCase()) === -1) + return false; + } + + return true; + }; + + var getSizeFilters = function() { + var minSize = (searchSizeFilter.min > 0.00) ? (searchSizeFilter.min * Math.pow(1024, searchSizeFilter.minUnit)) : 0.00; + var maxSize = (searchSizeFilter.max > 0.00) ? (searchSizeFilter.max * Math.pow(1024, searchSizeFilter.maxUnit)) : 0.00; + + if ((minSize > maxSize) && (maxSize > 0.00)) { + var tmp = minSize; + minSize = maxSize; + maxSize = tmp; + } + + return { + min: minSize, + max: maxSize + } + }; + + var getSeedsFilters = function() { + var minSeeds = (searchSeedsFilter.min > 0) ? searchSeedsFilter.min : 0; + var maxSeeds = (searchSeedsFilter.max > 0) ? searchSeedsFilter.max : 0; + + if ((minSeeds > maxSeeds) && (maxSeeds > 0)) { + var tmp = minSeeds; + minSeeds = maxSeeds; + maxSeeds = tmp; + } + + return { + min: minSeeds, + max: maxSeeds + } + } + + var filteredRows = []; + var rows = this.rows.getValues(); + var searchTerms = searchPattern.toLowerCase().split(" "); + var filterTerms = searchFilterPattern.toLowerCase().split(" "); + var sizeFilters = getSizeFilters(); + var seedsFilters = getSeedsFilters(); + var searchInTorrentName = $('searchInTorrentName').get('value') === "names"; + + if (searchInTorrentName || filterTerms.length || (searchSizeFilter.min > 0.00) || (searchSizeFilter.max > 0.00)) { + for (var i = 0; i < rows.length; ++i) { + var row = rows[i]; + + if (searchInTorrentName && !containsAll(row.full_data.fileName, searchTerms)) continue; + if (filterTerms.length && !containsAll(row.full_data.fileName, filterTerms)) continue; + if ((sizeFilters.min > 0.00) && (row.full_data.fileSize < sizeFilters.min)) continue; + if ((sizeFilters.max > 0.00) && (row.full_data.fileSize > sizeFilters.max)) continue; + if ((seedsFilters.min > 0) && (row.full_data.nbSeeders < seedsFilters.min)) continue; + if ((seedsFilters.max > 0) && (row.full_data.nbSeeders > seedsFilters.max)) continue; + + filteredRows.push(row); + } + } + else { + filteredRows = rows; + } + + filteredRows.sort(function (row1, row2) { + var column = this.columns[this.sortedColumn]; + var res = column.compareRows(row1, row2); + if (this.reverseSort == '0') + return res; + else + return -res; + }.bind(this)); + + return filteredRows; + }, + + setupTr: function (tr) { + tr.addClass("searchTableRow"); + } + }); + +var SearchPluginsTable = new Class({ + Extends: DynamicTable, + + initColumns: function () { + this.newColumn('fullName', '', 'QBT_TR(Name)QBT_TR[CONTEXT=SearchPluginsTable]', 175, true); + this.newColumn('version', '', 'QBT_TR(Version)QBT_TR[CONTEXT=SearchPluginsTable]', 100, true); + this.newColumn('url', '', 'QBT_TR(Url)QBT_TR[CONTEXT=SearchPluginsTable]', 175, true); + this.newColumn('enabled', '', 'QBT_TR(Enabled)QBT_TR[CONTEXT=SearchPluginsTable]', 100, true); + + this.initColumnsFunctions(); + }, + + initColumnsFunctions: function () { + var displayText = function (td, row) { + var value = this.getRowValue(row); + td.set('html', escapeHtml(value)); + } + + this.columns['fullName'].updateTd = displayText; + this.columns['version'].updateTd = displayText; + this.columns['url'].updateTd = displayText; + this.columns['enabled'].updateTd = function(td, row) { + var value = this.getRowValue(row); + if (value) { + td.set('html', "Yes"); + td.getParent("tr").addClass("green"); + td.getParent("tr").removeClass("red"); + } + else { + td.set('html', "No"); + td.getParent("tr").addClass("red"); + td.getParent("tr").removeClass("green"); + } + }; + }, + + setupTr: function (tr) { + tr.addClass("searchPluginsTableRow"); + } + }); + /*************************************************************/ diff --git a/src/webui/www/private/search.html b/src/webui/www/private/search.html new file mode 100644 index 000000000..c7921e7f3 --- /dev/null +++ b/src/webui/www/private/search.html @@ -0,0 +1,644 @@ + + +
    +
    +
    + + + + +
    +
    + +
    + + + + + + +
    + There aren't any search plugins installed.
    Click the "Search plugins..." button at the bottom right of the window to install some. +
    + +
    + +
    + + + QBT_TR(Results (showing)QBT_TR[CONTEXT=SearchEngineWidget] 0 QBT_TR(out of)QBT_TR[CONTEXT=SearchEngineWidget] 0): + +
    + + + + QBT_TR(Seeds:)QBT_TR[CONTEXT=SearchEngineWidget] + + to + + + QBT_TR(Size:)QBT_TR[CONTEXT=SearchEngineWidget] + + + to + + +
    +
    + +
    +
    + + + + +
    +
    +
    + + + + + +
    +
    +
    + +
    + + + + +
    +
    + + diff --git a/src/webui/www/private/searchplugins.html b/src/webui/www/private/searchplugins.html new file mode 100644 index 000000000..2c93410cd --- /dev/null +++ b/src/webui/www/private/searchplugins.html @@ -0,0 +1,219 @@ + + +
    +

    QBT_TR(Installed search plugins:)QBT_TR[CONTEXT=PluginSelectDlg]

    + +
    +
    + + + + +
    +
    +
    + + + + + +
    +
    +
    + + QBT_TR(Warning: Be sure to comply with your country's copyright laws when downloading torrents from any of these search engines.)QBT_TR[CONTEXT=PluginSelectDlg] + QBT_TR(You can get new search engine plugins here:)QBT_TR[CONTEXT=PluginSelectDlg] http://plugins.qbittorrent.org +
    + + + +
    +
    + + + + diff --git a/src/webui/www/webui.qrc b/src/webui/www/webui.qrc index 6fc7a9670..999fa25a4 100644 --- a/src/webui/www/webui.qrc +++ b/src/webui/www/webui.qrc @@ -13,12 +13,15 @@ private/downloadlimit.html private/filters.html private/index.html + private/installsearchplugin.html private/newcategory.html private/preferences.html private/preferences_content.html private/properties.html private/properties_content.html private/rename.html + private/search.html + private/searchplugins.html private/scripts/client.js private/scripts/contextmenu.js private/scripts/download.js