diff --git a/src/gui/issueswidget.cpp b/src/gui/issueswidget.cpp index edc984a7d..c132ff925 100644 --- a/src/gui/issueswidget.cpp +++ b/src/gui/issueswidget.cpp @@ -107,6 +107,16 @@ void IssuesWidget::showEvent(QShowEvent *ev) { ConfigFile cfg; cfg.restoreGeometryHeader(_ui->_treeWidget->header()); + + // Sorting by section was newly enabled. But if we restore the header + // from a state where sorting was disabled, both of these flags will be + // false and sorting will be impossible! + _ui->_treeWidget->header()->setSectionsClickable(true); + _ui->_treeWidget->header()->setSortIndicatorShown(true); + + // Switch back to "first important, then by time" ordering + _ui->_treeWidget->sortByColumn(0, Qt::DescendingOrder); + QWidget::showEvent(ev); } @@ -119,6 +129,8 @@ void IssuesWidget::hideEvent(QHideEvent *ev) void IssuesWidget::cleanItems(const QString &folder) { + _ui->_treeWidget->setSortingEnabled(false); + // The issue list is a state, clear it and let the next sync fill it // with ignored files and propagation errors. int itemCnt = _ui->_treeWidget->topLevelItemCount(); @@ -129,6 +141,9 @@ void IssuesWidget::cleanItems(const QString &folder) delete item; } } + + _ui->_treeWidget->setSortingEnabled(true); + // update the tabtext emit(issueCountUpdated(_ui->_treeWidget->topLevelItemCount())); } @@ -240,7 +255,7 @@ bool IssuesWidget::shouldBeVisible(QTreeWidgetItem *item, AccountState *filterAc const QString &filterFolderAlias) const { bool visible = true; - auto status = item->data(0, Qt::UserRole); + auto status = item->data(3, Qt::UserRole); visible &= (_ui->showIgnores->isChecked() || status != SyncFileItem::FileIgnored); visible &= (_ui->showWarnings->isChecked() || (status != SyncFileItem::SoftError @@ -368,13 +383,14 @@ void IssuesWidget::addError(const QString &folderAlias, const QString &message, QIcon icon = Theme::instance()->syncStateIcon(SyncResult::Error); - QTreeWidgetItem *twitem = new QTreeWidgetItem(columns); + QTreeWidgetItem *twitem = new SortedTreeWidgetItem(columns); twitem->setData(0, Qt::SizeHintRole, QSize(0, ActivityItemDelegate::rowHeight())); + twitem->setData(0, Qt::UserRole, timestamp); twitem->setIcon(0, icon); twitem->setToolTip(0, longTimeStr); - twitem->setToolTip(3, message); - twitem->setData(0, Qt::UserRole, SyncFileItem::NormalError); twitem->setData(2, Qt::UserRole, folderAlias); + twitem->setToolTip(3, message); + twitem->setData(3, Qt::UserRole, SyncFileItem::NormalError); addItem(twitem); addErrorWidget(twitem, message, category); diff --git a/src/gui/issueswidget.ui b/src/gui/issueswidget.ui index 27bfe1118..2d1161e78 100644 --- a/src/gui/issueswidget.ui +++ b/src/gui/issueswidget.ui @@ -99,6 +99,9 @@ false + + true + 4 diff --git a/src/gui/protocolwidget.cpp b/src/gui/protocolwidget.cpp index f3a52dff6..e27152563 100644 --- a/src/gui/protocolwidget.cpp +++ b/src/gui/protocolwidget.cpp @@ -32,6 +32,19 @@ namespace OCC { +bool SortedTreeWidgetItem::operator<(const QTreeWidgetItem &other) const +{ + int column = treeWidget()->sortColumn(); + if (column != 0) { + return QTreeWidgetItem::operator<(other); + } + + // Items with empty "File" column are larger than others, + // otherwise sort by time (this uses lexicographic ordering) + return std::forward_as_tuple(text(1).isEmpty(), data(0, Qt::UserRole).toDateTime()) + < std::forward_as_tuple(other.text(1).isEmpty(), other.data(0, Qt::UserRole).toDateTime()); +} + ProtocolWidget::ProtocolWidget(QWidget *parent) : QWidget(parent) , _ui(new Ui::ProtocolWidget) @@ -86,6 +99,16 @@ void ProtocolWidget::showEvent(QShowEvent *ev) { ConfigFile cfg; cfg.restoreGeometryHeader(_ui->_treeWidget->header()); + + // Sorting by section was newly enabled. But if we restore the header + // from a state where sorting was disabled, both of these flags will be + // false and sorting will be impossible! + _ui->_treeWidget->header()->setSectionsClickable(true); + _ui->_treeWidget->header()->setSortIndicatorShown(true); + + // Switch back to "by time" ordering + _ui->_treeWidget->sortByColumn(0, Qt::DescendingOrder); + QWidget::showEvent(ev); } @@ -158,14 +181,15 @@ QTreeWidgetItem *ProtocolWidget::createCompletedTreewidgetItem(const QString &fo columns << Utility::octetsToString(item._size); } - QTreeWidgetItem *twitem = new QTreeWidgetItem(columns); + QTreeWidgetItem *twitem = new SortedTreeWidgetItem(columns); twitem->setData(0, Qt::SizeHintRole, QSize(0, ActivityItemDelegate::rowHeight())); + twitem->setData(0, Qt::UserRole, timestamp); twitem->setIcon(0, icon); twitem->setToolTip(0, longTimeStr); twitem->setToolTip(1, item._file); - twitem->setToolTip(3, message); - twitem->setData(0, Qt::UserRole, item._status); twitem->setData(2, Qt::UserRole, folder); + twitem->setToolTip(3, message); + twitem->setData(3, Qt::UserRole, item._status); return twitem; } diff --git a/src/gui/protocolwidget.h b/src/gui/protocolwidget.h index 7e3a154a5..77bb641b4 100644 --- a/src/gui/protocolwidget.h +++ b/src/gui/protocolwidget.h @@ -34,6 +34,21 @@ namespace Ui { } class Application; +/** + * A QTreeWidgetItem with special sorting. + * + * It allows items for global entries to be moved to the top if the + * sorting section is the "Time" column. + */ +class SortedTreeWidgetItem : public QTreeWidgetItem +{ +public: + using QTreeWidgetItem::QTreeWidgetItem; + +private: + bool operator<(const QTreeWidgetItem &other) const override; +}; + /** * @brief The ProtocolWidget class * @ingroup gui diff --git a/src/gui/protocolwidget.ui b/src/gui/protocolwidget.ui index 143c2d627..7cec20f9d 100644 --- a/src/gui/protocolwidget.ui +++ b/src/gui/protocolwidget.ui @@ -35,6 +35,9 @@ true + + true + 4