diff options
author | Giuseppe D'Angelo <giuseppe.dangelo@kdab.com> | 2020-10-20 13:19:43 +0200 |
---|---|---|
committer | Giuseppe D'Angelo <giuseppe.dangelo@kdab.com> | 2020-11-30 18:16:21 +0200 |
commit | d982fdfca43165b31db7f7c3602b93f7197aeee8 (patch) | |
tree | 41ae57ce777d883abd909a092e91317341363440 /src/widgets/itemviews | |
parent | 3cacf1d1bd97c631465bb98edf6d00bff5bd5099 (diff) |
QHeaderView: allow un-sorting of models
If one clicks on a QHeaderView's section, the header view will
sort the view by the respective column/row. By clicking multiple
times, one is able to toggle the sorting between ascending
and descending. Something that is NOT possible to do however is to
un-sort the view -- that is, to restore the model's original
sorting. This must be done via code, by asking the header or the
view to sort by section -1.
This commit adds new property to QHeaderView to make it possible
to unsort models. Basically, the sort indicator becomes a tri-state:
sort ascending, sort descending, unsort (sort by column -1).
[ChangeLog][QtWidgets][QHeaderView] Added the sortIndicatorClearable
property. Setting this property allows the user to clear the sort
indicator on a section, resetting the model to its default ordering.
Change-Id: Ibf4e280b2086b75ccd64d619ea4d70816dc3529f
Reviewed-by: Shawn Rutledge <shawn.rutledge@qt.io>
Reviewed-by: David Faure <david.faure@kdab.com>
Diffstat (limited to 'src/widgets/itemviews')
-rw-r--r-- | src/widgets/itemviews/qheaderview.cpp | 79 | ||||
-rw-r--r-- | src/widgets/itemviews/qheaderview.h | 5 | ||||
-rw-r--r-- | src/widgets/itemviews/qheaderview_p.h | 3 |
3 files changed, 81 insertions, 6 deletions
diff --git a/src/widgets/itemviews/qheaderview.cpp b/src/widgets/itemviews/qheaderview.cpp index 8daa2bab9a..db594edd53 100644 --- a/src/widgets/itemviews/qheaderview.cpp +++ b/src/widgets/itemviews/qheaderview.cpp @@ -1467,6 +1467,41 @@ Qt::SortOrder QHeaderView::sortIndicatorOrder() const } /*! + \property QHeaderView::sortIndicatorClearable + \brief Whether the sort indicator can be cleared by clicking on a section multiple times + \since 6.1 + + This property controls whether the user is able to remove the + sorting indicator on a given section by clicking on the section + multiple times. Normally, clicking on a section will simply change + the sorting order for that section. By setting this property to + true, the sorting indicator will be cleared after alternating to + ascending and descending; this will typically restore the original + sorting of a model. + + Setting this property to true has no effect unless + sectionsClickable() is also true (which is the default for certain + views, for instance QTableView, or is automatically set when making + a view sortable, for instance by calling + QTreeView::setSortingEnabled). +*/ + +void QHeaderView::setSortIndicatorClearable(bool clearable) +{ + Q_D(QHeaderView); + if (d->sortIndicatorClearable == clearable) + return; + d->sortIndicatorClearable = clearable; + emit sortIndicatorClearableChanged(clearable); +} + +bool QHeaderView::isSortIndicatorClearable() const +{ + Q_D(const QHeaderView); + return d->sortIndicatorClearable; +} + +/*! \property QHeaderView::stretchLastSection \brief whether the last visible section in the header takes up all the available space @@ -3691,22 +3726,48 @@ void QHeaderViewPrivate::clear() } } +static Qt::SortOrder flipOrder(Qt::SortOrder order) +{ + switch (order) { + case Qt::AscendingOrder: + return Qt::DescendingOrder; + case Qt::DescendingOrder: + return Qt::AscendingOrder; + }; + Q_UNREACHABLE(); + return Qt::AscendingOrder; +}; + void QHeaderViewPrivate::flipSortIndicator(int section) { Q_Q(QHeaderView); Qt::SortOrder sortOrder; if (sortIndicatorSection == section) { - sortOrder = (sortIndicatorOrder == Qt::DescendingOrder) ? Qt::AscendingOrder : Qt::DescendingOrder; + if (sortIndicatorClearable) { + const Qt::SortOrder defaultSortOrder = defaultSortOrderForSection(section); + if (sortIndicatorOrder == defaultSortOrder) { + sortOrder = flipOrder(sortIndicatorOrder); + } else { + section = -1; + sortOrder = Qt::AscendingOrder; + } + } else { + sortOrder = flipOrder(sortIndicatorOrder); + } } else { - const QVariant value = model->headerData(section, orientation, Qt::InitialSortOrderRole); - if (value.canConvert<int>()) - sortOrder = static_cast<Qt::SortOrder>(value.toInt()); - else - sortOrder = Qt::AscendingOrder; + sortOrder = defaultSortOrderForSection(section); } q->setSortIndicator(section, sortOrder); } +Qt::SortOrder QHeaderViewPrivate::defaultSortOrderForSection(int section) const +{ + const QVariant value = model->headerData(section, orientation, Qt::InitialSortOrderRole); + if (value.canConvert<int>()) + return static_cast<Qt::SortOrder>(value.toInt()); + return Qt::AscendingOrder; +} + void QHeaderViewPrivate::cascadingResize(int visual, int newSize) { Q_Q(QHeaderView); @@ -4009,6 +4070,7 @@ void QHeaderViewPrivate::write(QDataStream &out) const out << resizeContentsPrecision; out << customDefaultSectionSize; out << lastSectionSize; + out << int(sortIndicatorClearable); } bool QHeaderViewPrivate::read(QDataStream &in) @@ -4152,6 +4214,11 @@ bool QHeaderViewPrivate::read(QDataStream &in) doDelayedResizeSections(); } + int inSortIndicatorClearable; + in >> inSortIndicatorClearable; + if (in.status() == QDataStream::Ok) // we haven't read past end + sortIndicatorClearable = inSortIndicatorClearable; + return true; } diff --git a/src/widgets/itemviews/qheaderview.h b/src/widgets/itemviews/qheaderview.h index a836f4a50a..baad5c024b 100644 --- a/src/widgets/itemviews/qheaderview.h +++ b/src/widgets/itemviews/qheaderview.h @@ -62,6 +62,7 @@ class Q_WIDGETS_EXPORT QHeaderView : public QAbstractItemView Q_PROPERTY(int minimumSectionSize READ minimumSectionSize WRITE setMinimumSectionSize) Q_PROPERTY(int maximumSectionSize READ maximumSectionSize WRITE setMaximumSectionSize) Q_PROPERTY(Qt::Alignment defaultAlignment READ defaultAlignment WRITE setDefaultAlignment) + Q_PROPERTY(bool sortIndicatorClearable READ isSortIndicatorClearable WRITE setSortIndicatorClearable NOTIFY sortIndicatorClearableChanged) public: @@ -140,6 +141,9 @@ public: int sortIndicatorSection() const; Qt::SortOrder sortIndicatorOrder() const; + void setSortIndicatorClearable(bool clearable); + bool isSortIndicatorClearable() const; + bool stretchLastSection() const; void setStretchLastSection(bool stretch); @@ -186,6 +190,7 @@ Q_SIGNALS: void sectionHandleDoubleClicked(int logicalIndex); void geometriesChanged(); void sortIndicatorChanged(int logicalIndex, Qt::SortOrder order); + void sortIndicatorClearableChanged(bool clearable); protected Q_SLOTS: void updateSection(int logicalIndex); diff --git a/src/widgets/itemviews/qheaderview_p.h b/src/widgets/itemviews/qheaderview_p.h index ecbcd6e5e4..b27b718089 100644 --- a/src/widgets/itemviews/qheaderview_p.h +++ b/src/widgets/itemviews/qheaderview_p.h @@ -77,6 +77,7 @@ public: sortIndicatorOrder(Qt::DescendingOrder), sortIndicatorSection(0), sortIndicatorShown(false), + sortIndicatorClearable(false), lastPos(-1), firstPos(-1), originalSize(-1), @@ -248,6 +249,7 @@ public: void clear(); void flipSortIndicator(int section); + Qt::SortOrder defaultSortOrderForSection(int section) const; void cascadingResize(int visual, int newSize); enum State { NoState, ResizeSection, MoveSection, SelectSections, NoClear } state; @@ -257,6 +259,7 @@ public: Qt::SortOrder sortIndicatorOrder; int sortIndicatorSection; bool sortIndicatorShown; + bool sortIndicatorClearable; mutable QList<int> visualIndices; // visualIndex = visualIndices.at(logicalIndex) mutable QList<int> logicalIndices; // logicalIndex = row or column in the model |