summaryrefslogtreecommitdiffstats
path: root/src/widgets
diff options
context:
space:
mode:
authorGiuseppe D'Angelo <giuseppe.dangelo@kdab.com>2020-10-20 13:19:43 +0200
committerGiuseppe D'Angelo <giuseppe.dangelo@kdab.com>2020-11-30 18:16:21 +0200
commitd982fdfca43165b31db7f7c3602b93f7197aeee8 (patch)
tree41ae57ce777d883abd909a092e91317341363440 /src/widgets
parent3cacf1d1bd97c631465bb98edf6d00bff5bd5099 (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')
-rw-r--r--src/widgets/itemviews/qheaderview.cpp79
-rw-r--r--src/widgets/itemviews/qheaderview.h5
-rw-r--r--src/widgets/itemviews/qheaderview_p.h3
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