Browse Source

WebUI: Implement subcategories

PR #18740.
adaptive-webui-19844
Bartu Özen 2 years ago committed by GitHub
parent
commit
b55d4b1733
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 3
      src/webui/api/appcontroller.cpp
  2. 3
      src/webui/api/synccontroller.cpp
  3. 1
      src/webui/www/private/index.html
  4. 5
      src/webui/www/private/newcategory.html
  5. 33
      src/webui/www/private/scripts/client.js
  6. 7
      src/webui/www/private/scripts/contextmenu.js
  7. 12
      src/webui/www/private/scripts/dynamicTable.js
  8. 20
      src/webui/www/private/scripts/mocha-init.js
  9. 3
      src/webui/www/private/views/filters.html
  10. 6
      src/webui/www/private/views/preferences.html

3
src/webui/api/appcontroller.cpp

@ -134,6 +134,7 @@ void AppController::preferencesAction()
data[u"torrent_changed_tmm_enabled"_qs] = !session->isDisableAutoTMMWhenCategoryChanged(); data[u"torrent_changed_tmm_enabled"_qs] = !session->isDisableAutoTMMWhenCategoryChanged();
data[u"save_path_changed_tmm_enabled"_qs] = !session->isDisableAutoTMMWhenDefaultSavePathChanged(); data[u"save_path_changed_tmm_enabled"_qs] = !session->isDisableAutoTMMWhenDefaultSavePathChanged();
data[u"category_changed_tmm_enabled"_qs] = !session->isDisableAutoTMMWhenCategorySavePathChanged(); data[u"category_changed_tmm_enabled"_qs] = !session->isDisableAutoTMMWhenCategorySavePathChanged();
data[u"use_subcategories"] = session->isSubcategoriesEnabled();
data[u"save_path"_qs] = session->savePath().toString(); data[u"save_path"_qs] = session->savePath().toString();
data[u"temp_path_enabled"_qs] = session->isDownloadPathEnabled(); data[u"temp_path_enabled"_qs] = session->isDownloadPathEnabled();
data[u"temp_path"_qs] = session->downloadPath().toString(); data[u"temp_path"_qs] = session->downloadPath().toString();
@ -489,6 +490,8 @@ void AppController::setPreferencesAction()
session->setDisableAutoTMMWhenDefaultSavePathChanged(!it.value().toBool()); session->setDisableAutoTMMWhenDefaultSavePathChanged(!it.value().toBool());
if (hasKey(u"category_changed_tmm_enabled"_qs)) if (hasKey(u"category_changed_tmm_enabled"_qs))
session->setDisableAutoTMMWhenCategorySavePathChanged(!it.value().toBool()); session->setDisableAutoTMMWhenCategorySavePathChanged(!it.value().toBool());
if (hasKey(u"use_subcategories"_qs))
session->setSubcategoriesEnabled(it.value().toBool());
if (hasKey(u"save_path"_qs)) if (hasKey(u"save_path"_qs))
session->setSavePath(Path(it.value().toString())); session->setSavePath(Path(it.value().toString()));
if (hasKey(u"temp_path_enabled"_qs)) if (hasKey(u"temp_path_enabled"_qs))

3
src/webui/api/synccontroller.cpp

@ -61,6 +61,7 @@ namespace
const QString KEY_SYNC_MAINDATA_QUEUEING = u"queueing"_qs; const QString KEY_SYNC_MAINDATA_QUEUEING = u"queueing"_qs;
const QString KEY_SYNC_MAINDATA_REFRESH_INTERVAL = u"refresh_interval"_qs; const QString KEY_SYNC_MAINDATA_REFRESH_INTERVAL = u"refresh_interval"_qs;
const QString KEY_SYNC_MAINDATA_USE_ALT_SPEED_LIMITS = u"use_alt_speed_limits"_qs; const QString KEY_SYNC_MAINDATA_USE_ALT_SPEED_LIMITS = u"use_alt_speed_limits"_qs;
const QString KEY_SYNC_MAINDATA_USE_SUBCATEGORIES = u"use_subcategories"_qs;
// Sync torrent peers keys // Sync torrent peers keys
const QString KEY_SYNC_TORRENT_PEERS_SHOW_FLAGS = u"show_flags"_qs; const QString KEY_SYNC_TORRENT_PEERS_SHOW_FLAGS = u"show_flags"_qs;
@ -549,6 +550,7 @@ void SyncController::makeMaindataSnapshot()
m_maindataSnapshot.serverState[KEY_SYNC_MAINDATA_QUEUEING] = session->isQueueingSystemEnabled(); m_maindataSnapshot.serverState[KEY_SYNC_MAINDATA_QUEUEING] = session->isQueueingSystemEnabled();
m_maindataSnapshot.serverState[KEY_SYNC_MAINDATA_USE_ALT_SPEED_LIMITS] = session->isAltGlobalSpeedLimitEnabled(); m_maindataSnapshot.serverState[KEY_SYNC_MAINDATA_USE_ALT_SPEED_LIMITS] = session->isAltGlobalSpeedLimitEnabled();
m_maindataSnapshot.serverState[KEY_SYNC_MAINDATA_REFRESH_INTERVAL] = session->refreshInterval(); m_maindataSnapshot.serverState[KEY_SYNC_MAINDATA_REFRESH_INTERVAL] = session->refreshInterval();
m_maindataSnapshot.serverState[KEY_SYNC_MAINDATA_USE_SUBCATEGORIES] = session->isSubcategoriesEnabled();
} }
QJsonObject SyncController::generateMaindataSyncData(const int id, const bool fullUpdate) QJsonObject SyncController::generateMaindataSyncData(const int id, const bool fullUpdate)
@ -657,6 +659,7 @@ QJsonObject SyncController::generateMaindataSyncData(const int id, const bool fu
serverState[KEY_SYNC_MAINDATA_QUEUEING] = session->isQueueingSystemEnabled(); serverState[KEY_SYNC_MAINDATA_QUEUEING] = session->isQueueingSystemEnabled();
serverState[KEY_SYNC_MAINDATA_USE_ALT_SPEED_LIMITS] = session->isAltGlobalSpeedLimitEnabled(); serverState[KEY_SYNC_MAINDATA_USE_ALT_SPEED_LIMITS] = session->isAltGlobalSpeedLimitEnabled();
serverState[KEY_SYNC_MAINDATA_REFRESH_INTERVAL] = session->refreshInterval(); serverState[KEY_SYNC_MAINDATA_REFRESH_INTERVAL] = session->refreshInterval();
serverState[KEY_SYNC_MAINDATA_USE_SUBCATEGORIES] = session->isSubcategoriesEnabled();
processMap(m_maindataSnapshot.serverState, serverState, m_maindataSyncBuf.serverState); processMap(m_maindataSnapshot.serverState, serverState, m_maindataSyncBuf.serverState);
m_maindataSnapshot.serverState = serverState; m_maindataSnapshot.serverState = serverState;

1
src/webui/www/private/index.html

@ -188,6 +188,7 @@
</ul> </ul>
<ul id="categoriesFilterMenu" class="contextMenu"> <ul id="categoriesFilterMenu" class="contextMenu">
<li><a href="#createCategory"><img src="images/list-add.svg" alt="QBT_TR(Add category...)QBT_TR[CONTEXT=CategoryFilterWidget]" /> QBT_TR(Add category...)QBT_TR[CONTEXT=CategoryFilterWidget]</a></li> <li><a href="#createCategory"><img src="images/list-add.svg" alt="QBT_TR(Add category...)QBT_TR[CONTEXT=CategoryFilterWidget]" /> QBT_TR(Add category...)QBT_TR[CONTEXT=CategoryFilterWidget]</a></li>
<li><a href="#createSubcategory"><img src="images/list-add.svg" alt="QBT_TR(Add subcategory...)QBT_TR[CONTEXT=CategoryFilterWidget]" /> QBT_TR(Add subcategory...)QBT_TR[CONTEXT=CategoryFilterWidget]</a></li>
<li><a href="#editCategory"><img src="images/edit-rename.svg" alt="QBT_TR(Edit category...)QBT_TR[CONTEXT=CategoryFilterWidget]" /> QBT_TR(Edit category...)QBT_TR[CONTEXT=CategoryFilterWidget]</a></li> <li><a href="#editCategory"><img src="images/edit-rename.svg" alt="QBT_TR(Edit category...)QBT_TR[CONTEXT=CategoryFilterWidget]" /> QBT_TR(Edit category...)QBT_TR[CONTEXT=CategoryFilterWidget]</a></li>
<li><a href="#deleteCategory"><img src="images/list-remove.svg" alt="QBT_TR(Remove category)QBT_TR[CONTEXT=CategoryFilterWidget]" /> QBT_TR(Remove category)QBT_TR[CONTEXT=CategoryFilterWidget]</a></li> <li><a href="#deleteCategory"><img src="images/list-remove.svg" alt="QBT_TR(Remove category)QBT_TR[CONTEXT=CategoryFilterWidget]" /> QBT_TR(Remove category)QBT_TR[CONTEXT=CategoryFilterWidget]</a></li>
<li><a href="#deleteUnusedCategories"><img src="images/list-remove.svg" alt="QBT_TR(Remove unused categories)QBT_TR[CONTEXT=CategoryFilterWidget]" /> QBT_TR(Remove unused categories)QBT_TR[CONTEXT=CategoryFilterWidget]</a></li> <li><a href="#deleteUnusedCategories"><img src="images/list-remove.svg" alt="QBT_TR(Remove unused categories)QBT_TR[CONTEXT=CategoryFilterWidget]" /> QBT_TR(Remove unused categories)QBT_TR[CONTEXT=CategoryFilterWidget]</a></li>

5
src/webui/www/private/newcategory.html

@ -44,6 +44,10 @@
$('savePath').set('value', window.qBittorrent.Misc.escapeHtml(uriSavePath)); $('savePath').set('value', window.qBittorrent.Misc.escapeHtml(uriSavePath));
$('savePath').focus(); $('savePath').focus();
} }
else if (uriAction === "createSubcategory") {
$('categoryName').set('value', window.qBittorrent.Misc.escapeHtml(uriCategoryName));
$('categoryName').focus();
}
else { else {
$('categoryName').focus(); $('categoryName').focus();
} }
@ -95,6 +99,7 @@
}).send(); }).send();
break; break;
case "create": case "create":
case "createSubcategory":
if (!verifyCategoryName(categoryName)) if (!verifyCategoryName(categoryName))
return; return;

33
src/webui/www/private/scripts/client.js

@ -33,6 +33,7 @@ let alternativeSpeedLimits = false;
let queueing_enabled = true; let queueing_enabled = true;
let serverSyncMainDataInterval = 1500; let serverSyncMainDataInterval = 1500;
let customSyncMainDataInterval = null; let customSyncMainDataInterval = null;
let useSubcategories = true;
let searchTabInitialized = false; let searchTabInitialized = false;
let rssTabInitialized = false; let rssTabInitialized = false;
let logTabInitialized = false; let logTabInitialized = false;
@ -429,9 +430,17 @@ window.addEvent('load', function() {
categoryList.empty(); categoryList.empty();
const create_link = function(hash, text, count) { const create_link = function(hash, text, count) {
const html = '<a href="#" onclick="setCategoryFilter(' + hash + ');return false;">' let display_name = text;
let margin_left = 0;
if (useSubcategories) {
const category_path = text.split("/");
display_name = category_path[category_path.length - 1];
margin_left = (category_path.length - 1) * 20;
}
const html = '<a href="#" style="margin-left: ' + margin_left + 'px" onclick="setCategoryFilter(' + hash + ');return false;">'
+ '<img src="images/view-categories.svg"/>' + '<img src="images/view-categories.svg"/>'
+ window.qBittorrent.Misc.escapeHtml(text) + ' (' + count + ')' + '</a>'; + window.qBittorrent.Misc.escapeHtml(display_name) + ' (' + count + ')' + '</a>';
const el = new Element('li', { const el = new Element('li', {
id: hash, id: hash,
html: html html: html
@ -455,11 +464,20 @@ window.addEvent('load', function() {
}); });
sortedCategories.sort(); sortedCategories.sort();
Object.each(sortedCategories, function(categoryName) { for (let i = 0; i < sortedCategories.length; ++i) {
const categoryName = sortedCategories[i];
const categoryHash = genHash(categoryName); const categoryHash = genHash(categoryName);
const categoryCount = category_list[categoryHash].torrents.length; let categoryCount = category_list[categoryHash].torrents.length;
if (useSubcategories) {
for (let j = i + 1; j < sortedCategories.length && sortedCategories[j].startsWith(categoryName + "/"); ++j) {
const hash = genHash(sortedCategories[j]);
categoryCount += category_list[hash].torrents.length;
}
}
categoryList.appendChild(create_link(categoryHash, categoryName, categoryCount)); categoryList.appendChild(create_link(categoryHash, categoryName, categoryCount));
}); }
highlightSelectedCategory(); highlightSelectedCategory();
}; };
@ -821,6 +839,11 @@ window.addEvent('load', function() {
updateAltSpeedIcon(alternativeSpeedLimits); updateAltSpeedIcon(alternativeSpeedLimits);
} }
if (useSubcategories != serverState.use_subcategories) {
useSubcategories = serverState.use_subcategories;
updateCategoryList();
}
serverSyncMainDataInterval = Math.max(serverState.refresh_interval, 500); serverSyncMainDataInterval = Math.max(serverState.refresh_interval, 500);
}; };

7
src/webui/www/private/scripts/contextmenu.js

@ -517,10 +517,17 @@ window.qBittorrent.ContextMenu = (function() {
if ((id != CATEGORIES_ALL) && (id != CATEGORIES_UNCATEGORIZED)) { if ((id != CATEGORIES_ALL) && (id != CATEGORIES_UNCATEGORIZED)) {
this.showItem('editCategory'); this.showItem('editCategory');
this.showItem('deleteCategory'); this.showItem('deleteCategory');
if (useSubcategories) {
this.showItem('createSubcategory');
}
else {
this.hideItem('createSubcategory');
}
} }
else { else {
this.hideItem('editCategory'); this.hideItem('editCategory');
this.hideItem('deleteCategory'); this.hideItem('deleteCategory');
this.hideItem('createSubcategory');
} }
} }
}); });

12
src/webui/www/private/scripts/dynamicTable.js

@ -1383,8 +1383,16 @@ window.qBittorrent.DynamicTable = (function() {
return false; return false;
break; // do nothing break; // do nothing
default: default:
if (categoryHashInt !== genHash(row['full_data'].category)) if (!useSubcategories) {
return false; if (categoryHashInt !== genHash(row['full_data'].category))
return false;
}
else {
const selectedCategoryName = category_list[categoryHash].name + "/";
const torrentCategoryName = row['full_data'].category + "/";
if (!torrentCategoryName.startsWith(selectedCategoryName))
return false;
}
} }
} }

20
src/webui/www/private/scripts/mocha-init.js

@ -66,6 +66,7 @@ let renameFilesFN = function() {};
let torrentNewCategoryFN = function() {}; let torrentNewCategoryFN = function() {};
let torrentSetCategoryFN = function() {}; let torrentSetCategoryFN = function() {};
let createCategoryFN = function() {}; let createCategoryFN = function() {};
let createSubcategoryFN = function() {};
let editCategoryFN = function() {}; let editCategoryFN = function() {};
let removeCategoryFN = function() {}; let removeCategoryFN = function() {};
let deleteUnusedCategoriesFN = function() {}; let deleteUnusedCategoriesFN = function() {};
@ -604,6 +605,25 @@ const initializeWindows = function() {
updateMainData(); updateMainData();
}; };
createSubcategoryFN = function(categoryHash) {
const action = "createSubcategory";
const categoryName = category_list[categoryHash].name + "/";
new MochaUI.Window({
id: 'newSubcategoryPage',
title: "QBT_TR(New Category)QBT_TR[CONTEXT=CategoryFilterWidget]",
loadMethod: 'iframe',
contentURL: new URI("newcategory.html").setData("action", action).setData("categoryName", categoryName).toString(),
scrollbars: false,
resizable: true,
maximizable: false,
paddingVertical: 0,
paddingHorizontal: 0,
width: 400,
height: 150
});
updateMainData();
};
editCategoryFN = function(categoryHash) { editCategoryFN = function(categoryHash) {
const action = "edit"; const action = "edit";
const categoryName = category_list[categoryHash].name; const categoryName = category_list[categoryHash].name;

3
src/webui/www/private/views/filters.html

@ -63,6 +63,9 @@
createCategory: function(element, ref) { createCategory: function(element, ref) {
createCategoryFN(); createCategoryFN();
}, },
createSubcategory: function(element, ref) {
createSubcategoryFN(element.id);
},
editCategory: function(element, ref) { editCategory: function(element, ref) {
editCategoryFN(element.id); editCategoryFN(element.id);
}, },

6
src/webui/www/private/views/preferences.html

@ -135,6 +135,10 @@
</td> </td>
</tr> </tr>
</table> </table>
<div class="formRow">
<input type="checkbox" id="use_subcategories_checkbox" />
<label for="use_subcategories_checkbox">QBT_TR(Use Subcategories)QBT_TR[CONTEXT=OptionsDialog]</label>
</div>
<table> <table>
<tr> <tr>
<td> <td>
@ -1844,6 +1848,7 @@ Use ';' to split multiple entries. Can use wildcard '*'.)QBT_TR[CONTEXT=OptionsD
$('torrent_changed_tmm_combobox').setProperty('value', pref.torrent_changed_tmm_enabled); $('torrent_changed_tmm_combobox').setProperty('value', pref.torrent_changed_tmm_enabled);
$('save_path_changed_tmm_combobox').setProperty('value', pref.save_path_changed_tmm_enabled); $('save_path_changed_tmm_combobox').setProperty('value', pref.save_path_changed_tmm_enabled);
$('category_changed_tmm_combobox').setProperty('value', pref.category_changed_tmm_enabled); $('category_changed_tmm_combobox').setProperty('value', pref.category_changed_tmm_enabled);
$('use_subcategories_checkbox').setProperty('checked', pref.use_subcategories);
$('savepath_text').setProperty('value', pref.save_path); $('savepath_text').setProperty('value', pref.save_path);
$('temppath_checkbox').setProperty('checked', pref.temp_path_enabled); $('temppath_checkbox').setProperty('checked', pref.temp_path_enabled);
$('temppath_text').setProperty('value', pref.temp_path); $('temppath_text').setProperty('value', pref.temp_path);
@ -2199,6 +2204,7 @@ Use ';' to split multiple entries. Can use wildcard '*'.)QBT_TR[CONTEXT=OptionsD
settings.set('torrent_changed_tmm_enabled', $('torrent_changed_tmm_combobox').getProperty('value')); settings.set('torrent_changed_tmm_enabled', $('torrent_changed_tmm_combobox').getProperty('value'));
settings.set('save_path_changed_tmm_enabled', $('save_path_changed_tmm_combobox').getProperty('value')); settings.set('save_path_changed_tmm_enabled', $('save_path_changed_tmm_combobox').getProperty('value'));
settings.set('category_changed_tmm_enabled', $('category_changed_tmm_combobox').getProperty('value')); settings.set('category_changed_tmm_enabled', $('category_changed_tmm_combobox').getProperty('value'));
settings.set('use_subcategories', $('use_subcategories_checkbox').getProperty('checked'));
settings.set('save_path', $('savepath_text').getProperty('value')); settings.set('save_path', $('savepath_text').getProperty('value'));
settings.set('temp_path_enabled', $('temppath_checkbox').getProperty('checked')); settings.set('temp_path_enabled', $('temppath_checkbox').getProperty('checked'));
settings.set('temp_path', $('temppath_text').getProperty('value')); settings.set('temp_path', $('temppath_text').getProperty('value'));

Loading…
Cancel
Save