Compare commits

...

2 Commits

Author SHA1 Message Date
Chocobo1
8aa1a96d71 Revise Interface section layout in Options dialog
The Language option now has its own layout since it is independent to other options (Style and Color scheme).
This avoids text in Language combobox to be left out and replaced by `...` due to Style Hint text being too long.

PR #22823.
2025-06-08 17:15:42 +08:00
Chocobo1
4132173b30 WebUI: avoid redundant operations when sorting
Avoid recomputing the same result on every sort operation.
Also clean up the caller site.

PR #22821.
2025-06-08 17:08:47 +08:00
3 changed files with 174 additions and 158 deletions

View File

@@ -1760,9 +1760,9 @@ void OptionsDialog::initializeStyleCombo()
m_ui->labelStyle->hide();
m_ui->comboStyle->hide();
m_ui->labelStyleHint->hide();
m_ui->UISettingsBoxLayout->removeWidget(m_ui->labelStyle);
m_ui->UISettingsBoxLayout->removeWidget(m_ui->comboStyle);
m_ui->UISettingsBoxLayout->removeWidget(m_ui->labelStyleHint);
m_ui->layoutStyle->removeWidget(m_ui->labelStyle);
m_ui->layoutStyle->removeWidget(m_ui->comboStyle);
m_ui->layoutStyle->removeWidget(m_ui->labelStyleHint);
#endif
}
@@ -1776,9 +1776,9 @@ void OptionsDialog::initializeColorSchemeOptions()
#else
m_ui->labelColorScheme->hide();
m_ui->comboColorScheme->hide();
m_ui->UISettingsBoxLayout->removeWidget(m_ui->labelColorScheme);
m_ui->UISettingsBoxLayout->removeWidget(m_ui->comboColorScheme);
m_ui->UISettingsBoxLayout->removeItem(m_ui->spacerColorScheme);
m_ui->layoutStyle->removeWidget(m_ui->labelColorScheme);
m_ui->layoutStyle->removeWidget(m_ui->comboColorScheme);
m_ui->layoutStyle->removeItem(m_ui->spacerColorScheme);
#endif
}

View File

@@ -137,8 +137,8 @@
<property name="title">
<string>Interface</string>
</property>
<layout class="QGridLayout" name="UISettingsBoxLayout">
<item row="0" column="0" colspan="3">
<layout class="QVBoxLayout" name="UISettingsBoxLayout">
<item>
<widget class="QLabel" name="labelRestartRequired">
<property name="font">
<font>
@@ -150,72 +150,80 @@
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="labelLanguage">
<property name="text">
<string>Language:</string>
</property>
</widget>
<item>
<layout class="QHBoxLayout" name="layoutLanguage">
<item>
<widget class="QLabel" name="labelLanguage">
<property name="text">
<string>Language:</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="comboLanguage"/>
</item>
<item>
<spacer name="spacerLanguage">
<property name="orientation">
<enum>Qt::Orientation::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>200</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item row="1" column="1">
<widget class="QComboBox" name="comboLanguage"/>
<item>
<layout class="QGridLayout" name="layoutStyle">
<item row="0" column="0">
<widget class="QLabel" name="labelStyle">
<property name="text">
<string>Style:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QComboBox" name="comboStyle"/>
</item>
<item row="0" column="2">
<widget class="QLabel" name="labelStyleHint">
<property name="font">
<font>
<italic>true</italic>
</font>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="labelColorScheme">
<property name="text">
<string>Color scheme:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QComboBox" name="comboColorScheme"/>
</item>
<item row="1" column="2">
<spacer name="spacerColorScheme">
<property name="orientation">
<enum>Qt::Orientation::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item row="1" column="2">
<spacer name="spacerLanguage">
<property name="orientation">
<enum>Qt::Orientation::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>200</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="2" column="0">
<widget class="QLabel" name="labelStyle">
<property name="text">
<string>Style:</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QComboBox" name="comboStyle"/>
</item>
<item row="2" column="2">
<widget class="QLabel" name="labelStyleHint">
<property name="font">
<font>
<italic>true</italic>
</font>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="labelColorScheme">
<property name="text">
<string>Color scheme:</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QComboBox" name="comboColorScheme"/>
</item>
<item row="3" column="2">
<spacer name="spacerColorScheme">
<property name="orientation">
<enum>Qt::Orientation::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="4" column="0" colspan="3">
<item>
<widget class="QGroupBox" name="checkUseCustomTheme">
<property name="title">
<string>Use custom UI Theme</string>
@@ -237,15 +245,21 @@
</layout>
</widget>
</item>
<item row="5" column="0" colspan="2">
<item>
<widget class="QCheckBox" name="checkUseSystemIcon">
<property name="text">
<string>Use icons from system theme</string>
</property>
</widget>
</item>
<item row="6" column="0" colspan="2">
<item>
<widget class="QPushButton" name="buttonCustomizeUITheme">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Customize UI Theme...</string>
</property>

View File

@@ -829,13 +829,11 @@ window.qBittorrent.DynamicTable ??= (() => {
filteredRows[row.rowId] = row;
}
const column = this.columns[this.sortedColumn];
const isReverseSort = (this.reverseSort === "0");
filteredRows.sort((row1, row2) => {
const column = this.columns[this.sortedColumn];
const res = column.compareRows(row1, row2);
if (this.reverseSort === "0")
return res;
else
return -res;
const result = column.compareRows(row1, row2);
return isReverseSort ? result : -result;
});
return filteredRows;
}
@@ -1777,13 +1775,11 @@ window.qBittorrent.DynamicTable ??= (() => {
}
}
const column = this.columns[this.sortedColumn];
const isReverseSort = (this.reverseSort === "0");
filteredRows.sort((row1, row2) => {
const column = this.columns[this.sortedColumn];
const res = column.compareRows(row1, row2);
if (this.reverseSort === "0")
return res;
else
return -res;
const result = column.compareRows(row1, row2);
return isReverseSort ? result : -result;
});
return filteredRows;
}
@@ -2037,13 +2033,11 @@ window.qBittorrent.DynamicTable ??= (() => {
filteredRows = [...this.getRowValues()];
}
const column = this.columns[this.sortedColumn];
const isReverseSort = (this.reverseSort === "0");
filteredRows.sort((row1, row2) => {
const column = this.columns[this.sortedColumn];
const res = column.compareRows(row1, row2);
if (this.reverseSort === "0")
return res;
else
return -res;
const result = column.compareRows(row1, row2);
return isReverseSort ? result : -result;
});
return filteredRows;
@@ -2454,26 +2448,31 @@ window.qBittorrent.DynamicTable ??= (() => {
this.updateGlobalCheckbox();
}
#sortNodesByColumn(nodes, column) {
nodes.sort((row1, row2) => {
// list folders before files when sorting by name
if (column.name === "original") {
const node1 = this.getNode(row1.data.rowId);
const node2 = this.getNode(row2.data.rowId);
if (node1.isFolder && !node2.isFolder)
return -1;
if (node2.isFolder && !node1.isFolder)
return 1;
}
#sortNodesByColumn(root, column) {
const isColumnOriginal = (column.name === "original");
const isReverseSort = (this.reverseSort === "0");
const res = column.compareRows(row1, row2);
return (this.reverseSort === "0") ? res : -res;
});
const stack = [root];
while (stack.length > 0) {
const node = stack.pop();
nodes.each((node) => {
if (node.children.length > 0)
this.#sortNodesByColumn(node.children, column);
});
node.children.sort((row1, row2) => {
// list folders before files when sorting by name
if (isColumnOriginal) {
const node1 = this.getNode(row1.data.rowId);
const node2 = this.getNode(row2.data.rowId);
if (node1.isFolder && !node2.isFolder)
return -1;
if (!node1.isFolder && node2.isFolder)
return 1;
}
const result = column.compareRows(row1, row2);
return isReverseSort ? result : -result;
});
stack.push(...node.children);
}
}
#filterNodes(root, filterTerms) {
@@ -2532,7 +2531,8 @@ window.qBittorrent.DynamicTable ??= (() => {
}
getFilteredAndSortedRows() {
if (this.getRoot() === null)
const root = this.getRoot();
if (root === null)
return [];
const generateRowsSignature = () => {
@@ -2542,16 +2542,6 @@ window.qBittorrent.DynamicTable ??= (() => {
return JSON.stringify(rowsData);
};
const getFilteredRows = () => {
if (this.filterTerms.length === 0) {
const nodeArray = this.fileTree.toArray();
const filteredRows = nodeArray.map(node => this.getRow(node));
return filteredRows;
}
return this.#filterNodes(this.getRoot().children[0], this.filterTerms);
};
const hasRowsChanged = function(rowsString, prevRowsStringString) {
const rowsChanged = (rowsString !== prevRowsStringString);
const isFilterTermsChanged = this.filterTerms.reduce((acc, term, index) => {
@@ -2570,16 +2560,23 @@ window.qBittorrent.DynamicTable ??= (() => {
return this.prevFilteredRows;
// sort, then filter
const column = this.columns[this.sortedColumn];
this.#sortNodesByColumn(this.getRoot().children, column);
const filteredRows = getFilteredRows();
this.#sortNodesByColumn(root, this.columns[this.sortedColumn]);
const rows = (() => {
if (this.filterTerms.length === 0) {
const nodeArray = this.fileTree.toArray();
const filteredRows = nodeArray.map(node => this.getRow(node));
return filteredRows;
}
return this.#filterNodes(root.children[0], this.filterTerms);
})();
this.prevFilterTerms = this.filterTerms;
this.prevRowsString = rowsString;
this.prevFilteredRows = filteredRows;
this.prevFilteredRows = rows;
this.prevSortedColumn = this.sortedColumn;
this.prevReverseSort = this.reverseSort;
return filteredRows;
return rows;
}
setIgnored(rowId, ignore) {
@@ -2917,26 +2914,31 @@ window.qBittorrent.DynamicTable ??= (() => {
this.columns["availability"].updateTd = displayPercentage;
}
#sortNodesByColumn(nodes, column) {
nodes.sort((row1, row2) => {
// list folders before files when sorting by name
if (column.name === "name") {
const node1 = this.getNode(row1.data.rowId);
const node2 = this.getNode(row2.data.rowId);
if (node1.isFolder && !node2.isFolder)
return -1;
if (node2.isFolder && !node1.isFolder)
return 1;
}
#sortNodesByColumn(root, column) {
const isColumnName = (column.name === "name");
const isReverseSort = (this.reverseSort === "0");
const res = column.compareRows(row1, row2);
return (this.reverseSort === "0") ? res : -res;
});
const stack = [root];
while (stack.length > 0) {
const node = stack.pop();
nodes.each((node) => {
if (node.children.length > 0)
this.#sortNodesByColumn(node.children, column);
});
node.children.sort((row1, row2) => {
// list folders before files when sorting by name
if (isColumnName) {
const node1 = this.getNode(row1.data.rowId);
const node2 = this.getNode(row2.data.rowId);
if (node1.isFolder && !node2.isFolder)
return -1;
if (!node1.isFolder && node2.isFolder)
return 1;
}
const result = column.compareRows(row1, row2);
return isReverseSort ? result : -result;
});
stack.push(...node.children);
}
}
#filterNodes(root, filterTerms) {
@@ -2995,7 +2997,8 @@ window.qBittorrent.DynamicTable ??= (() => {
}
getFilteredAndSortedRows() {
if (this.getRoot() === null)
const root = this.getRoot();
if (root === null)
return [];
const generateRowsSignature = () => {
@@ -3005,8 +3008,6 @@ window.qBittorrent.DynamicTable ??= (() => {
return JSON.stringify(rowsData);
};
const getFilteredRows = () => this.#filterNodes(this.getRoot().children[0], this.filterTerms);
const hasRowsChanged = function(rowsString, prevRowsStringString) {
const rowsChanged = (rowsString !== prevRowsStringString);
const isFilterTermsChanged = this.filterTerms.reduce((acc, term, index) => {
@@ -3025,16 +3026,15 @@ window.qBittorrent.DynamicTable ??= (() => {
return this.prevFilteredRows;
// sort, then filter
const column = this.columns[this.sortedColumn];
this.#sortNodesByColumn(this.getRoot().children, column);
const filteredRows = getFilteredRows();
this.#sortNodesByColumn(root, this.columns[this.sortedColumn]);
const rows = this.#filterNodes(root.children[0], this.filterTerms);
this.prevFilterTerms = this.filterTerms;
this.prevRowsString = rowsString;
this.prevFilteredRows = filteredRows;
this.prevFilteredRows = rows;
this.prevSortedColumn = this.sortedColumn;
this.prevReverseSort = this.reverseSort;
return filteredRows;
return rows;
}
setIgnored(rowId, ignore) {
@@ -3603,10 +3603,11 @@ window.qBittorrent.DynamicTable ??= (() => {
filteredRows = [...this.getRowValues()];
}
const column = this.columns[this.sortedColumn];
const isReverseSort = (this.reverseSort === "0");
filteredRows.sort((row1, row2) => {
const column = this.columns[this.sortedColumn];
const res = column.compareRows(row1, row2);
return (this.reverseSort === "0") ? res : -res;
const result = column.compareRows(row1, row2);
return isReverseSort ? result : -result;
});
this.filteredLength = filteredRows.length;
@@ -3661,10 +3662,11 @@ window.qBittorrent.DynamicTable ??= (() => {
filteredRows = [...this.getRowValues()];
}
const column = this.columns[this.sortedColumn];
const isReverseSort = (this.reverseSort === "0");
filteredRows.sort((row1, row2) => {
const column = this.columns[this.sortedColumn];
const res = column.compareRows(row1, row2);
return (this.reverseSort === "0") ? res : -res;
const result = column.compareRows(row1, row2);
return isReverseSort ? result : -result;
});
return filteredRows;