summaryrefslogtreecommitdiffstats
path: root/src/widgets/itemviews
diff options
context:
space:
mode:
Diffstat (limited to 'src/widgets/itemviews')
-rw-r--r--src/widgets/itemviews/itemviews.pri1
-rw-r--r--src/widgets/itemviews/qabstractitemview.cpp20
-rw-r--r--src/widgets/itemviews/qabstractitemview_p.h2
-rw-r--r--src/widgets/itemviews/qcolumnview.cpp11
-rw-r--r--src/widgets/itemviews/qfileiconprovider.cpp93
-rw-r--r--src/widgets/itemviews/qfileiconprovider.h14
-rw-r--r--src/widgets/itemviews/qfileiconprovider_p.h87
-rw-r--r--src/widgets/itemviews/qheaderview.cpp155
-rw-r--r--src/widgets/itemviews/qheaderview.h8
-rw-r--r--src/widgets/itemviews/qheaderview_p.h21
-rw-r--r--src/widgets/itemviews/qitemdelegate.cpp7
-rw-r--r--src/widgets/itemviews/qlistview.cpp8
-rw-r--r--src/widgets/itemviews/qlistwidget.cpp10
-rw-r--r--src/widgets/itemviews/qstyleditemdelegate.cpp7
-rw-r--r--src/widgets/itemviews/qtableview.cpp223
-rw-r--r--src/widgets/itemviews/qtableview.h2
-rw-r--r--src/widgets/itemviews/qtableview_p.h2
-rw-r--r--src/widgets/itemviews/qtablewidget.cpp4
-rw-r--r--src/widgets/itemviews/qtreeview.cpp207
-rw-r--r--src/widgets/itemviews/qtreeview.h5
-rw-r--r--src/widgets/itemviews/qtreeview_p.h14
-rw-r--r--src/widgets/itemviews/qtreewidget.cpp10
22 files changed, 744 insertions, 167 deletions
diff --git a/src/widgets/itemviews/itemviews.pri b/src/widgets/itemviews/itemviews.pri
index 0bc0309271..4e152d18bb 100644
--- a/src/widgets/itemviews/itemviews.pri
+++ b/src/widgets/itemviews/itemviews.pri
@@ -26,6 +26,7 @@ HEADERS += \
itemviews/qtreewidgetitemiterator.h \
itemviews/qdatawidgetmapper.h \
itemviews/qfileiconprovider.h \
+ itemviews/qfileiconprovider_p.h \
itemviews/qcolumnviewgrip_p.h \
itemviews/qcolumnview.h \
itemviews/qcolumnview_p.h \
diff --git a/src/widgets/itemviews/qabstractitemview.cpp b/src/widgets/itemviews/qabstractitemview.cpp
index 70c8f44a73..b79525b9df 100644
--- a/src/widgets/itemviews/qabstractitemview.cpp
+++ b/src/widgets/itemviews/qabstractitemview.cpp
@@ -1108,6 +1108,7 @@ void QAbstractItemView::reset()
QAccessible::updateAccessibility(&accessibleEvent);
}
#endif
+ d->updateGeometry();
}
/*!
@@ -1124,6 +1125,7 @@ void QAbstractItemView::setRootIndex(const QModelIndex &index)
}
d->root = index;
d->doDelayedItemsLayout();
+ d->updateGeometry();
}
/*!
@@ -2668,8 +2670,10 @@ void QAbstractItemView::updateEditorGeometries()
*/
void QAbstractItemView::updateGeometries()
{
+ Q_D(QAbstractItemView);
updateEditorGeometries();
- d_func()->fetchMoreTimer.start(0, this); //fetch more later
+ d->fetchMoreTimer.start(0, this); //fetch more later
+ d->updateGeometry();
}
/*!
@@ -3231,6 +3235,7 @@ void QAbstractItemView::dataChanged(const QModelIndex &topLeft, const QModelInde
QAccessible::updateAccessibility(&accessibleEvent);
}
#endif
+ d->updateGeometry();
}
/*!
@@ -3332,6 +3337,7 @@ void QAbstractItemViewPrivate::_q_rowsRemoved(const QModelIndex &index, int star
QAccessible::updateAccessibility(&accessibleEvent);
}
#endif
+ updateGeometry();
}
/*!
@@ -3412,6 +3418,7 @@ void QAbstractItemViewPrivate::_q_columnsRemoved(const QModelIndex &index, int s
QAccessible::updateAccessibility(&accessibleEvent);
}
#endif
+ updateGeometry();
}
@@ -3435,6 +3442,7 @@ void QAbstractItemViewPrivate::_q_rowsInserted(const QModelIndex &index, int sta
QAccessible::updateAccessibility(&accessibleEvent);
}
#endif
+ updateGeometry();
}
/*!
@@ -3459,6 +3467,7 @@ void QAbstractItemViewPrivate::_q_columnsInserted(const QModelIndex &index, int
QAccessible::updateAccessibility(&accessibleEvent);
}
#endif
+ updateGeometry();
}
/*!
@@ -4084,7 +4093,14 @@ void QAbstractItemViewPrivate::interruptDelayedItemsLayout() const
delayedPendingLayout = false;
}
-
+void QAbstractItemViewPrivate::updateGeometry()
+{
+ Q_Q(QAbstractItemView);
+ if (sizeAdjustPolicy == QAbstractScrollArea::AdjustIgnored)
+ return;
+ if (sizeAdjustPolicy == QAbstractScrollArea::AdjustToContents || !shownOnce)
+ q->updateGeometry();
+}
QWidget *QAbstractItemViewPrivate::editor(const QModelIndex &index,
const QStyleOptionViewItem &options)
diff --git a/src/widgets/itemviews/qabstractitemview_p.h b/src/widgets/itemviews/qabstractitemview_p.h
index 86eab174ed..5da22615e2 100644
--- a/src/widgets/itemviews/qabstractitemview_p.h
+++ b/src/widgets/itemviews/qabstractitemview_p.h
@@ -127,6 +127,8 @@ public:
void doDelayedItemsLayout(int delay = 0);
void interruptDelayedItemsLayout() const;
+ void updateGeometry();
+
void startAutoScroll()
{ // ### it would be nice to make this into a style hint one day
int scrollInterval = (verticalScrollMode == QAbstractItemView::ScrollPerItem) ? 150 : 50;
diff --git a/src/widgets/itemviews/qcolumnview.cpp b/src/widgets/itemviews/qcolumnview.cpp
index 5aee78fab4..32a3dddca1 100644
--- a/src/widgets/itemviews/qcolumnview.cpp
+++ b/src/widgets/itemviews/qcolumnview.cpp
@@ -332,11 +332,14 @@ void QColumnView::scrollTo(const QModelIndex &index, ScrollHint hint)
}
#ifndef QT_NO_ANIMATION
- d->currentAnimation.setEndValue(newScrollbarValue);
- d->currentAnimation.start();
-#else
- horizontalScrollBar()->setValue(newScrollbarValue);
+ if (style()->styleHint(QStyle::SH_Widget_Animate, 0, this)) {
+ d->currentAnimation.setEndValue(newScrollbarValue);
+ d->currentAnimation.start();
+ } else
#endif //QT_NO_ANIMATION
+ {
+ horizontalScrollBar()->setValue(newScrollbarValue);
+ }
}
/*!
diff --git a/src/widgets/itemviews/qfileiconprovider.cpp b/src/widgets/itemviews/qfileiconprovider.cpp
index 8a0736ec70..71697ddc40 100644
--- a/src/widgets/itemviews/qfileiconprovider.cpp
+++ b/src/widgets/itemviews/qfileiconprovider.cpp
@@ -40,9 +40,8 @@
****************************************************************************/
#include "qfileiconprovider.h"
+#include "qfileiconprovider_p.h"
-#ifndef QT_NO_FILEICONPROVIDER
-#include <qstyle.h>
#include <qapplication.h>
#include <qdir.h>
#include <qpixmapcache.h>
@@ -83,34 +82,15 @@ QT_BEGIN_NAMESPACE
\value File
*/
-class QFileIconProviderPrivate
-{
- Q_DECLARE_PUBLIC(QFileIconProvider)
-
-public:
- QFileIconProviderPrivate();
- QIcon getIcon(QStyle::StandardPixmap name) const;
- QIcon getIcon(const QFileInfo &fi) const;
-
- QFileIconProvider *q_ptr;
- const QString homePath;
-
-private:
- mutable QIcon file;
- mutable QIcon fileLink;
- mutable QIcon directory;
- mutable QIcon directoryLink;
- mutable QIcon harddisk;
- mutable QIcon floppy;
- mutable QIcon cdrom;
- mutable QIcon ram;
- mutable QIcon network;
- mutable QIcon computer;
- mutable QIcon desktop;
- mutable QIcon trashcan;
- mutable QIcon generic;
- mutable QIcon home;
-};
+
+/*!
+ \enum QFileIconProvider::Option
+ \since 5.2
+
+ \value DontUseCustomDirectoryIcons Always use the default directory icon.
+ Some platforms allow the user to set a different icon. Custom icon lookup
+ cause a big performance impact over network or removable drives.
+*/
QFileIconProviderPrivate::QFileIconProviderPrivate() :
homePath(QDir::home().absolutePath())
@@ -193,6 +173,31 @@ QFileIconProvider::~QFileIconProvider()
}
/*!
+ \since 5.2
+ Sets \a options that affect the icon provider.
+ \sa options()
+*/
+
+void QFileIconProvider::setOptions(QFileIconProvider::Options options)
+{
+ Q_D(QFileIconProvider);
+ d->options = options;
+}
+
+/*!
+ \since 5.2
+ Returns all the options that affect the icon provider.
+ By default, all options are disabled.
+ \sa setOptions()
+*/
+
+QFileIconProvider::Options QFileIconProvider::options() const
+{
+ Q_D(const QFileIconProvider);
+ return d->options;
+}
+
+/*!
Returns an icon set for the given \a type.
*/
@@ -220,6 +225,23 @@ QIcon QFileIconProvider::icon(IconType type) const
return QIcon();
}
+static bool isCacheable(const QFileInfo &fi)
+{
+ if (!fi.isFile())
+ return false;
+
+#ifdef Q_OS_WIN
+ // On windows it's faster to just look at the file extensions. QTBUG-13182
+ const QString fileExtension = fi.suffix();
+ // Will return false for .exe, .lnk and .ico extensions
+ return fileExtension.compare(QLatin1String("exe"), Qt::CaseInsensitive) &&
+ fileExtension.compare(QLatin1String("lnk"), Qt::CaseInsensitive) &&
+ fileExtension.compare(QLatin1String("ico"), Qt::CaseInsensitive);
+#else
+ return !fi.isExecutable() && !fi.isSymLink();
+#endif
+}
+
QIcon QFileIconProviderPrivate::getIcon(const QFileInfo &fi) const
{
QIcon retIcon;
@@ -231,10 +253,9 @@ QIcon QFileIconProviderPrivate::getIcon(const QFileInfo &fi) const
if (sizes.isEmpty())
return retIcon;
- const QString fileExtension = fi.suffix().toUpper();
const QString keyBase = QLatin1String("qt_.") + fi.suffix().toUpper();
- bool cacheable = fi.isFile() && !fi.isExecutable() && !fi.isSymLink() && fileExtension != QLatin1String("ICO");
+ bool cacheable = isCacheable(fi);
if (cacheable) {
QPixmap pixmap;
QPixmapCache::find(keyBase + QString::number(sizes.at(0)), pixmap);
@@ -253,8 +274,12 @@ QIcon QFileIconProviderPrivate::getIcon(const QFileInfo &fi) const
}
}
+ QPlatformTheme::IconOptions iconOptions;
+ if (options & QFileIconProvider::DontUseCustomDirectoryIcons)
+ iconOptions |= QPlatformTheme::DontUseCustomDirectoryIcons;
+
Q_FOREACH (int size, sizes) {
- QPixmap pixmap = theme->fileIconPixmap(fi, QSizeF(size, size));
+ QPixmap pixmap = theme->fileIconPixmap(fi, QSizeF(size, size), iconOptions);
if (!pixmap.isNull()) {
retIcon.addPixmap(pixmap);
if (cacheable)
@@ -372,5 +397,3 @@ QString QFileIconProvider::type(const QFileInfo &info) const
}
QT_END_NAMESPACE
-
-#endif
diff --git a/src/widgets/itemviews/qfileiconprovider.h b/src/widgets/itemviews/qfileiconprovider.h
index cac135fe71..6f7e28395b 100644
--- a/src/widgets/itemviews/qfileiconprovider.h
+++ b/src/widgets/itemviews/qfileiconprovider.h
@@ -49,8 +49,6 @@
QT_BEGIN_NAMESPACE
-#ifndef QT_NO_FILEICONPROVIDER
-
class QFileIconProviderPrivate;
class Q_WIDGETS_EXPORT QFileIconProvider
@@ -59,19 +57,27 @@ public:
QFileIconProvider();
virtual ~QFileIconProvider();
enum IconType { Computer, Desktop, Trashcan, Network, Drive, Folder, File };
+
+ enum Option {
+ DontUseCustomDirectoryIcons = 0x00000001
+ };
+ Q_DECLARE_FLAGS(Options, Option)
+
virtual QIcon icon(IconType type) const;
virtual QIcon icon(const QFileInfo &info) const;
virtual QString type(const QFileInfo &info) const;
+ void setOptions(Options options);
+ Options options() const;
+
private:
Q_DECLARE_PRIVATE(QFileIconProvider)
QScopedPointer<QFileIconProviderPrivate> d_ptr;
Q_DISABLE_COPY(QFileIconProvider)
};
-#endif // QT_NO_FILEICONPROVIDER
+Q_DECLARE_OPERATORS_FOR_FLAGS(QFileIconProvider::Options)
QT_END_NAMESPACE
#endif // QFILEICONPROVIDER_H
-
diff --git a/src/widgets/itemviews/qfileiconprovider_p.h b/src/widgets/itemviews/qfileiconprovider_p.h
new file mode 100644
index 0000000000..9b2d536258
--- /dev/null
+++ b/src/widgets/itemviews/qfileiconprovider_p.h
@@ -0,0 +1,87 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtWidgets module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFILEICONPROVIDER_P_H
+#define QFILEICONPROVIDER_P_H
+
+#include "qfileiconprovider.h"
+
+#include <QtCore/qstring.h>
+#include <QtGui/qicon.h>
+#include <QtWidgets/qstyle.h>
+
+QT_BEGIN_NAMESPACE
+
+class QFileInfo;
+
+class QFileIconProviderPrivate
+{
+ Q_DECLARE_PUBLIC(QFileIconProvider)
+
+public:
+ QFileIconProviderPrivate();
+ QIcon getIcon(QStyle::StandardPixmap name) const;
+ QIcon getIcon(const QFileInfo &fi) const;
+
+ QFileIconProvider *q_ptr;
+ const QString homePath;
+ QFileIconProvider::Options options;
+
+private:
+ mutable QIcon file;
+ mutable QIcon fileLink;
+ mutable QIcon directory;
+ mutable QIcon directoryLink;
+ mutable QIcon harddisk;
+ mutable QIcon floppy;
+ mutable QIcon cdrom;
+ mutable QIcon ram;
+ mutable QIcon network;
+ mutable QIcon computer;
+ mutable QIcon desktop;
+ mutable QIcon trashcan;
+ mutable QIcon generic;
+ mutable QIcon home;
+};
+
+QT_END_NAMESPACE
+
+#endif // QFILEICONPROVIDER_P_H
diff --git a/src/widgets/itemviews/qheaderview.cpp b/src/widgets/itemviews/qheaderview.cpp
index 864a55d2ea..239cc84a0a 100644
--- a/src/widgets/itemviews/qheaderview.cpp
+++ b/src/widgets/itemviews/qheaderview.cpp
@@ -80,6 +80,8 @@ QDataStream &operator>>(QDataStream &in, QHeaderViewPrivate::SectionItem &sectio
}
#endif // QT_NO_DATASTREAM
+static const int maxSizeSection = 1048575; // since section size is in a bitfield (uint 20). See qheaderview_p.h
+ // if this is changed then the docs in maximumSectionSize should be changed.
/*!
\class QHeaderView
@@ -550,9 +552,25 @@ QSize QHeaderView::sizeHint() const
}
/*!
+ \reimp
+*/
+
+void QHeaderView::setVisible(bool v)
+{
+ bool actualChange = (v != isVisible());
+ QAbstractItemView::setVisible(v);
+ if (actualChange) {
+ QAbstractScrollArea *parent = qobject_cast<QAbstractScrollArea*>(parentWidget());
+ if (parent)
+ parent->updateGeometry();
+ }
+}
+
+
+/*!
Returns a suitable size hint for the section specified by \a logicalIndex.
- \sa sizeHint(), defaultSectionSize(), minimumSectionSize(),
+ \sa sizeHint(), defaultSectionSize(), minimumSectionSize(), maximumSectionSize()
Qt::SizeHintRole
*/
@@ -570,7 +588,7 @@ int QHeaderView::sectionSizeHint(int logicalIndex) const
else
size = sectionSizeFromContents(logicalIndex);
int hint = d->orientation == Qt::Horizontal ? size.width() : size.height();
- return qMax(minimumSectionSize(), hint);
+ return qBound(minimumSectionSize(), hint, maximumSectionSize());
}
/*!
@@ -868,7 +886,7 @@ void QHeaderView::swapSections(int first, int second)
void QHeaderView::resizeSection(int logical, int size)
{
Q_D(QHeaderView);
- if (logical < 0 || logical >= count() || size < 0)
+ if (logical < 0 || logical >= count() || size < 0 || size > maxSizeSection)
return;
if (isSectionHidden(logical)) {
@@ -918,6 +936,18 @@ void QHeaderView::resizeSection(int logical, int size)
d->doDelayedResizeSections();
r = d->viewport->rect();
}
+
+ // If the parent is a QAbstractScrollArea with QAbstractScrollArea::AdjustToContents
+ // then we want to change the geometry on that widget. Not doing it at once can/will
+ // cause scrollbars flicker as they would be shown at first but then removed.
+ // In the same situation it will also allow shrinking the whole view when stretchLastSection is set
+ // (It is default on QTreeViews - and it wouldn't shrink since the last stretch was made before the
+ // viewport was resized)
+
+ QAbstractScrollArea *parent = qobject_cast<QAbstractScrollArea *>(parentWidget());
+ if (parent && parent->sizeAdjustPolicy() == QAbstractScrollArea::AdjustToContents)
+ parent->updateGeometry();
+
d->viewport->update(r.normalized());
emit sectionResized(logical, oldSize, size);
}
@@ -1225,7 +1255,7 @@ void QHeaderView::setSectionResizeMode(ResizeMode mode)
property is set to true. This is the default for the horizontal headers provided
by QTreeView.
- \sa setStretchLastSection()
+ \sa setStretchLastSection(), resizeContentsPrecision()
*/
void QHeaderView::setSectionResizeMode(int logicalIndex, ResizeMode mode)
@@ -1288,6 +1318,53 @@ QHeaderView::ResizeMode QHeaderView::sectionResizeMode(int logicalIndex) const
return d->headerSectionResizeMode(visual);
}
+/*!
+ \since 5.2
+ Sets how precise QHeaderView should calculate the size when ResizeToContents is used.
+ A low value will provide a less accurate but fast auto resize while a higher
+ value will provide a more accurate resize that however can be slow.
+
+ The number \a precision specifies how many sections that should be consider
+ when calculating the preferred size.
+
+ The default value is 1000 meaning that a horizontal column with auto-resize will look
+ at maximum 1000 rows on calculating when doing an auto resize.
+
+ Special value 0 means that it will look at only the visible area.
+ Special value -1 will imply looking at all elements.
+
+ This value is used in QTableView::sizeHintForColumn(), QTableView::sizeHintForRow()
+ and QTreeView::sizeHintForColumn(). Reimplementing these functions can make this
+ function not having an effect.
+
+ If \a resizeSectionsNow is set to true (default) it will do adjustment of sections by calling
+ resizeSections(). (regardless if the precision was changed).
+
+ \sa resizeContentsPrecision(), setSectionResizeMode(), resizeSections(), QTableView::sizeHintForColumn(), QTableView::sizeHintForRow(), QTreeView::sizeHintForColumn()
+*/
+
+void QHeaderView::setResizeContentsPrecision(int precision, bool resizeSectionsNow)
+{
+ Q_D(QHeaderView);
+ d->resizeContentsPrecision = precision;
+ if (resizeSectionsNow)
+ resizeSections();
+}
+
+/*!
+ \since 5.2
+ Returns how precise QHeaderView will calculate on ResizeToContents.
+
+ \sa setResizeContentsPrecision(), setSectionResizeMode()
+
+*/
+
+int QHeaderView::resizeContentsPrecision() const
+{
+ Q_D(const QHeaderView);
+ return d->resizeContentsPrecision;
+}
+
// ### Qt 6 - remove this obsolete function
/*!
\obsolete
@@ -1492,7 +1569,7 @@ int QHeaderView::defaultSectionSize() const
void QHeaderView::setDefaultSectionSize(int size)
{
Q_D(QHeaderView);
- if (size < 0)
+ if (size < 0 || size > maxSizeSection)
return;
d->setDefaultSectionSize(size);
}
@@ -1527,12 +1604,52 @@ int QHeaderView::minimumSectionSize() const
void QHeaderView::setMinimumSectionSize(int size)
{
Q_D(QHeaderView);
- if (size < 0)
+ if (size < 0 || size > maxSizeSection)
return;
d->minimumSectionSize = size;
+ if (d->minimumSectionSize > maximumSectionSize())
+ d->maximumSectionSize = size;
}
/*!
+ \since 5.2
+ \property QHeaderView::maximumSectionSize
+ \brief the maximum size of the header sections.
+
+ The maximum section size is the largest section size allowed.
+ The default value for this property is 1048575, which is also the largest
+ possible size for a section. Setting maximum to -1 will reset the value to
+ the largest section size.
+
+ With exception of stretch this property is honored by all \l{ResizeMode}{resize modes}
+
+ \sa setSectionResizeMode(), defaultSectionSize
+*/
+int QHeaderView::maximumSectionSize() const
+{
+ Q_D(const QHeaderView);
+ if (d->maximumSectionSize == -1)
+ return maxSizeSection;
+ return d->maximumSectionSize;
+}
+
+void QHeaderView::setMaximumSectionSize(int size)
+{
+ Q_D(QHeaderView);
+ if (size == -1) {
+ d->maximumSectionSize = maxSizeSection;
+ return;
+ }
+ if (size < 0 || size > maxSizeSection)
+ return;
+ if (minimumSectionSize() > size)
+ d->minimumSectionSize = size;
+
+ d->maximumSectionSize = size;
+}
+
+
+/*!
\since 4.1
\property QHeaderView::defaultAlignment
\brief the default alignment of the text in each header section
@@ -2341,7 +2458,8 @@ void QHeaderView::mouseMoveEvent(QMouseEvent *e)
d->cascadingResize(visual, d->headerSectionSize(visual) + delta);
} else {
int delta = d->reverse() ? d->firstPos - pos : pos - d->firstPos;
- resizeSection(d->section, qMax(d->originalSize + delta, minimumSectionSize()));
+ int newsize = qBound(minimumSectionSize(), d->originalSize + delta, maximumSectionSize());
+ resizeSection(d->section, newsize);
}
d->lastPos = pos;
return;
@@ -3160,6 +3278,8 @@ void QHeaderViewPrivate::resizeSections(QHeaderView::ResizeMode globalMode, bool
int logicalIndex = q->logicalIndex(i);
sectionSize = qMax(viewSectionSizeHint(logicalIndex),
q->sectionSizeHint(logicalIndex));
+ if (sectionSize > q->maximumSectionSize())
+ sectionSize = q->maximumSectionSize();
}
section_sizes.append(sectionSize);
lengthToStretch -= sectionSize;
@@ -3492,7 +3612,7 @@ QHeaderView::ResizeMode QHeaderViewPrivate::headerSectionResizeMode(int visual)
{
if (visual < 0 || visual >= sectionItems.count())
return globalResizeMode;
- return sectionItems.at(visual).resizeMode;
+ return static_cast<QHeaderView::ResizeMode>(sectionItems.at(visual).resizeMode);
}
void QHeaderViewPrivate::setGlobalHeaderResizeMode(QHeaderView::ResizeMode mode)
@@ -3530,6 +3650,19 @@ int QHeaderViewPrivate::adjustedVisualIndex(int visualIndex) const
return visualIndex;
}
+void QHeaderViewPrivate::setScrollOffset(const QScrollBar *scrollBar, QAbstractItemView::ScrollMode scrollMode)
+{
+ Q_Q(QHeaderView);
+ if (scrollMode == QAbstractItemView::ScrollPerItem) {
+ if (scrollBar->maximum() > 0 && scrollBar->value() == scrollBar->maximum())
+ q->setOffsetToLastSection();
+ else
+ q->setOffsetToSectionPosition(scrollBar->value());
+ } else {
+ q->setOffset(scrollBar->value());
+ }
+}
+
#ifndef QT_NO_DATASTREAM
void QHeaderViewPrivate::write(QDataStream &out) const
{
@@ -3560,6 +3693,8 @@ void QHeaderViewPrivate::write(QDataStream &out) const
out << int(globalResizeMode);
out << sectionItems;
+ if (out.version() >= QDataStream::Qt_5_2)
+ out << resizeContentsPrecision;
}
bool QHeaderViewPrivate::read(QDataStream &in)
@@ -3611,6 +3746,10 @@ bool QHeaderViewPrivate::read(QDataStream &in)
}
sectionItems = newSectionItems;
recalcSectionStartPos();
+
+ if (in.version() >= QDataStream::Qt_5_2)
+ in >> resizeContentsPrecision;
+
return true;
}
diff --git a/src/widgets/itemviews/qheaderview.h b/src/widgets/itemviews/qheaderview.h
index 8fcd8d7a36..b3ed666aa6 100644
--- a/src/widgets/itemviews/qheaderview.h
+++ b/src/widgets/itemviews/qheaderview.h
@@ -61,6 +61,7 @@ class Q_WIDGETS_EXPORT QHeaderView : public QAbstractItemView
Q_PROPERTY(bool cascadingSectionResizes READ cascadingSectionResizes WRITE setCascadingSectionResizes)
Q_PROPERTY(int defaultSectionSize READ defaultSectionSize WRITE setDefaultSectionSize)
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_ENUMS(ResizeMode)
@@ -84,6 +85,7 @@ public:
int offset() const;
int length() const;
QSize sizeHint() const;
+ void setVisible(bool v);
int sectionSizeHint(int logicalIndex) const;
int visualIndexAt(int position) const;
@@ -132,6 +134,10 @@ public:
ResizeMode sectionResizeMode(int logicalIndex) const;
void setSectionResizeMode(ResizeMode mode);
void setSectionResizeMode(int logicalIndex, ResizeMode mode);
+
+ void setResizeContentsPrecision(int precision, bool resizeNow = true);
+ int resizeContentsPrecision() const;
+
#if QT_DEPRECATED_SINCE(5, 0)
inline QT_DEPRECATED void setResizeMode(ResizeMode mode)
{ setSectionResizeMode(mode); }
@@ -161,6 +167,8 @@ public:
int minimumSectionSize() const;
void setMinimumSectionSize(int size);
+ int maximumSectionSize() const;
+ void setMaximumSectionSize(int size);
Qt::Alignment defaultAlignment() const;
void setDefaultAlignment(Qt::Alignment alignment);
diff --git a/src/widgets/itemviews/qheaderview_p.h b/src/widgets/itemviews/qheaderview_p.h
index f886430ba8..b2af821e9b 100644
--- a/src/widgets/itemviews/qheaderview_p.h
+++ b/src/widgets/itemviews/qheaderview_p.h
@@ -95,11 +95,13 @@ public:
stretchSections(0),
contentsSections(0),
minimumSectionSize(-1),
+ maximumSectionSize(-1),
lastSectionSize(0),
sectionIndicatorOffset(0),
sectionIndicator(0),
globalResizeMode(QHeaderView::Interactive),
- sectionStartposRecalc(true)
+ sectionStartposRecalc(true),
+ resizeContentsPrecision(1000)
{}
@@ -286,6 +288,7 @@ public:
int contentsSections;
int defaultSectionSize;
int minimumSectionSize;
+ int maximumSectionSize;
int lastSectionSize; // $$$
int sectionIndicatorOffset;
Qt::Alignment defaultAlignment;
@@ -293,26 +296,31 @@ public:
QHeaderView::ResizeMode globalResizeMode;
QList<QPersistentModelIndex> persistentHiddenSections;
mutable bool sectionStartposRecalc;
+ int resizeContentsPrecision;
// header sections
struct SectionItem {
- int size;
+ uint size : 20;
+ uint reservedForIsHidden : 1;
+ uint resizeMode : 5; // (holding QHeaderView::ResizeMode)
+ uint currentlyUnusedPadding : 6;
+
union { // This union is made in order to save space and ensure good vector performance (on remove)
mutable int calculated_startpos; // <- this is the primary used member.
mutable int tmpLogIdx; // When one of these 'tmp'-members has been used we call
int tmpDataStreamSectionCount; // recalcSectionStartPos() or set sectionStartposRecalc to true
}; // to ensure that calculated_startpos will be calculated afterwards.
- QHeaderView::ResizeMode resizeMode;
+
inline SectionItem() : size(0), resizeMode(QHeaderView::Interactive) {}
inline SectionItem(int length, QHeaderView::ResizeMode mode)
- : size(length), calculated_startpos(-1), resizeMode(mode) {}
+ : size(length), resizeMode(mode), calculated_startpos(-1) {}
inline int sectionSize() const { return size; }
inline int calculatedEndPos() const { return calculated_startpos + size; }
#ifndef QT_NO_DATASTREAM
inline void write(QDataStream &out) const
- { out << size; out << 1; out << (int)resizeMode; }
+ { out << static_cast<int>(size); out << 1; out << (int)resizeMode; }
inline void read(QDataStream &in)
- { in >> size; in >> tmpDataStreamSectionCount; int m; in >> m; resizeMode = (QHeaderView::ResizeMode)m; }
+ { int m; in >> m; size = m; in >> tmpDataStreamSectionCount; in >> m; resizeMode = m; }
#endif
};
@@ -343,6 +351,7 @@ public:
// other
int viewSectionSizeHint(int logical) const;
int adjustedVisualIndex(int visualIndex) const;
+ void setScrollOffset(const QScrollBar *scrollBar, QAbstractItemView::ScrollMode scrollMode);
#ifndef QT_NO_DATASTREAM
void write(QDataStream &out) const;
diff --git a/src/widgets/itemviews/qitemdelegate.cpp b/src/widgets/itemviews/qitemdelegate.cpp
index c040322ba1..3e34568a12 100644
--- a/src/widgets/itemviews/qitemdelegate.cpp
+++ b/src/widgets/itemviews/qitemdelegate.cpp
@@ -1295,8 +1295,11 @@ bool QItemDelegate::editorEvent(QEvent *event,
return false;
}
- Qt::CheckState state = (static_cast<Qt::CheckState>(value.toInt()) == Qt::Checked
- ? Qt::Unchecked : Qt::Checked);
+ Qt::CheckState state = static_cast<Qt::CheckState>(value.toInt());
+ if (flags & Qt::ItemIsTristate)
+ state = ((Qt::CheckState)((state + 1) % 3));
+ else
+ state = (state == Qt::Checked) ? Qt::Unchecked : Qt::Checked;
return model->setData(index, state, Qt::CheckStateRole);
}
diff --git a/src/widgets/itemviews/qlistview.cpp b/src/widgets/itemviews/qlistview.cpp
index 3690b15650..331748eedc 100644
--- a/src/widgets/itemviews/qlistview.cpp
+++ b/src/widgets/itemviews/qlistview.cpp
@@ -1833,18 +1833,18 @@ void QCommonListViewBase::removeHiddenRow(int row)
dd->hiddenRows.remove(dd->model->index(row, 0, qq->rootIndex()));
}
-void QCommonListViewBase::updateHorizontalScrollBar(const QSize &step)
+void QCommonListViewBase::updateHorizontalScrollBar(const QSize & /*step*/)
{
- horizontalScrollBar()->setSingleStep(step.width() + spacing());
horizontalScrollBar()->setPageStep(viewport()->width());
horizontalScrollBar()->setRange(0, contentsSize.width() - viewport()->width());
+ // we do not want to overwrite (a possible user set) single step
}
-void QCommonListViewBase::updateVerticalScrollBar(const QSize &step)
+void QCommonListViewBase::updateVerticalScrollBar(const QSize & /*step*/)
{
- verticalScrollBar()->setSingleStep(step.height() + spacing());
verticalScrollBar()->setPageStep(viewport()->height());
verticalScrollBar()->setRange(0, contentsSize.height() - viewport()->height());
+ // we do not want to overwrite (a possible user set) single step
}
void QCommonListViewBase::scrollContentsBy(int dx, int dy, bool /*scrollElasticBand*/)
diff --git a/src/widgets/itemviews/qlistwidget.cpp b/src/widgets/itemviews/qlistwidget.cpp
index 39d03124ce..27abfb8eb4 100644
--- a/src/widgets/itemviews/qlistwidget.cpp
+++ b/src/widgets/itemviews/qlistwidget.cpp
@@ -304,7 +304,7 @@ void QListModel::sort(int column, Qt::SortOrder order)
}
LessThan compare = (order == Qt::AscendingOrder ? &itemLessThan : &itemGreaterThan);
- qSort(sorting.begin(), sorting.end(), compare);
+ std::sort(sorting.begin(), sorting.end(), compare);
QModelIndexList fromIndexes;
QModelIndexList toIndexes;
for (int r = 0; r < sorting.count(); ++r) {
@@ -338,7 +338,7 @@ void QListModel::ensureSorted(int column, Qt::SortOrder order, int start, int en
}
LessThan compare = (order == Qt::AscendingOrder ? &itemLessThan : &itemGreaterThan);
- qSort(sorting.begin(), sorting.end(), compare);
+ std::sort(sorting.begin(), sorting.end(), compare);
QModelIndexList oldPersistentIndexes = persistentIndexList();
QModelIndexList newPersistentIndexes = oldPersistentIndexes;
@@ -347,7 +347,11 @@ void QListModel::ensureSorted(int column, Qt::SortOrder order, int start, int en
bool changed = false;
for (int i = 0; i < count; ++i) {
int oldRow = sorting.at(i).second;
+ int tmpitepos = lit - tmp.begin();
QListWidgetItem *item = tmp.takeAt(oldRow);
+ if (tmpitepos > tmp.size())
+ --tmpitepos;
+ lit = tmp.begin() + tmpitepos;
lit = sortedInsertionIterator(lit, tmp.end(), order, item);
int newRow = qMax(lit - tmp.begin(), 0);
lit = tmp.insert(lit, item);
@@ -1828,7 +1832,7 @@ void QListWidget::dropEvent(QDropEvent *event) {
if (persIndexes.contains(topIndex))
return;
- qSort(persIndexes); // The dropped items will remain in the same visual order.
+ std::sort(persIndexes.begin(), persIndexes.end()); // The dropped items will remain in the same visual order.
QPersistentModelIndex dropRow = model()->index(row, col, topIndex);
diff --git a/src/widgets/itemviews/qstyleditemdelegate.cpp b/src/widgets/itemviews/qstyleditemdelegate.cpp
index 7e1933ad1e..c1fa9fe28e 100644
--- a/src/widgets/itemviews/qstyleditemdelegate.cpp
+++ b/src/widgets/itemviews/qstyleditemdelegate.cpp
@@ -764,8 +764,11 @@ bool QStyledItemDelegate::editorEvent(QEvent *event,
return false;
}
- Qt::CheckState state = (static_cast<Qt::CheckState>(value.toInt()) == Qt::Checked
- ? Qt::Unchecked : Qt::Checked);
+ Qt::CheckState state = static_cast<Qt::CheckState>(value.toInt());
+ if (flags & Qt::ItemIsTristate)
+ state = ((Qt::CheckState)((state + 1) % 3));
+ else
+ state = (state == Qt::Checked) ? Qt::Unchecked : Qt::Checked;
return model->setData(index, state, Qt::CheckStateRole);
}
diff --git a/src/widgets/itemviews/qtableview.cpp b/src/widgets/itemviews/qtableview.cpp
index a6623b9462..871ad656ea 100644
--- a/src/widgets/itemviews/qtableview.cpp
+++ b/src/widgets/itemviews/qtableview.cpp
@@ -931,6 +931,59 @@ void QTableViewPrivate::drawCell(QPainter *painter, const QStyleOptionViewItem &
}
/*!
+ \internal
+ Get sizeHint width for single Index (providing existing hint and style option)
+*/
+int QTableViewPrivate::widthHintForIndex(const QModelIndex &index, int hint, const QStyleOptionViewItem &option) const
+{
+ Q_Q(const QTableView);
+ QWidget *editor = editorForIndex(index).widget.data();
+ if (editor && persistent.contains(editor)) {
+ hint = qMax(hint, editor->sizeHint().width());
+ int min = editor->minimumSize().width();
+ int max = editor->maximumSize().width();
+ hint = qBound(min, hint, max);
+ }
+ hint = qMax(hint, q->itemDelegate(index)->sizeHint(option, index).width());
+ return hint;
+}
+
+/*!
+ \internal
+ Get sizeHint height for single Index (providing existing hint and style option)
+*/
+int QTableViewPrivate::heightHintForIndex(const QModelIndex &index, int hint, QStyleOptionViewItem &option) const
+{
+ Q_Q(const QTableView);
+ QWidget *editor = editorForIndex(index).widget.data();
+ if (editor && persistent.contains(editor)) {
+ hint = qMax(hint, editor->sizeHint().height());
+ int min = editor->minimumSize().height();
+ int max = editor->maximumSize().height();
+ hint = qBound(min, hint, max);
+ }
+
+ if (wrapItemText) {// for wrapping boundaries
+ option.rect.setY(q->rowViewportPosition(index.row()));
+ int height = q->rowHeight(index.row());
+ // if the option.height == 0 then q->itemDelegate(index)->sizeHint(option, index) will be wrong.
+ // The option.height == 0 is used to conclude that the text is not wrapped, and hence it will
+ // (exactly like widthHintForIndex) return a QSize with a long width (that we don't use) -
+ // and the height of the text if it was/is on one line.
+ // What we want is a height hint for the current width (and we know that this section is not hidden)
+ // Therefore we catch this special situation with:
+ if (height == 0)
+ height = 1;
+ option.rect.setHeight(height);
+ option.rect.setX(q->columnViewportPosition(index.column()));
+ option.rect.setWidth(q->columnWidth(index.column()));
+ }
+ hint = qMax(hint, q->itemDelegate(index)->sizeHint(option, index).height());
+ return hint;
+}
+
+
+/*!
\class QTableView
\brief The QTableView class provides a default model/view
@@ -1056,6 +1109,19 @@ QTableView::~QTableView()
/*!
\reimp
*/
+QSize QTableView::viewportSizeHint() const
+{
+ Q_D(const QTableView);
+ QSize result( (d->verticalHeader->isHidden() ? 0 : d->verticalHeader->width()) + d->horizontalHeader->length(),
+ (d->horizontalHeader->isHidden() ? 0 : d->horizontalHeader->height()) + d->verticalHeader->length());
+ result += QSize(verticalScrollBar()->isVisible() ? verticalScrollBar()->width() : 0,
+ horizontalScrollBar()->isVisible() ? horizontalScrollBar()->height() : 0);
+ return result;
+}
+
+/*!
+ \reimp
+*/
void QTableView::setModel(QAbstractItemModel *model)
{
Q_D(QTableView);
@@ -1113,15 +1179,7 @@ void QTableView::doItemsLayout()
{
Q_D(QTableView);
QAbstractItemView::doItemsLayout();
- if (verticalScrollMode() == QAbstractItemView::ScrollPerItem) {
- const int max = verticalScrollBar()->maximum();
- if (max > 0 && verticalScrollBar()->value() == max)
- d->verticalHeader->setOffsetToLastSection();
- else
- d->verticalHeader->setOffsetToSectionPosition(verticalScrollBar()->value());
- } else {
- d->verticalHeader->setOffset(verticalScrollBar()->value());
- }
+ d->verticalHeader->d_func()->setScrollOffset(verticalScrollBar(), verticalScrollMode());
if (!d->verticalHeader->updatesEnabled())
d->verticalHeader->setUpdatesEnabled(true);
}
@@ -1258,29 +1316,19 @@ void QTableView::scrollContentsBy(int dx, int dy)
dx = isRightToLeft() ? -dx : dx;
if (dx) {
+ int oldOffset = d->horizontalHeader->offset();
+ d->horizontalHeader->d_func()->setScrollOffset(horizontalScrollBar(), horizontalScrollMode());
if (horizontalScrollMode() == QAbstractItemView::ScrollPerItem) {
- int oldOffset = d->horizontalHeader->offset();
- if (horizontalScrollBar()->value() == horizontalScrollBar()->maximum())
- d->horizontalHeader->setOffsetToLastSection();
- else
- d->horizontalHeader->setOffsetToSectionPosition(horizontalScrollBar()->value());
int newOffset = d->horizontalHeader->offset();
dx = isRightToLeft() ? newOffset - oldOffset : oldOffset - newOffset;
- } else {
- d->horizontalHeader->setOffset(horizontalScrollBar()->value());
}
}
if (dy) {
+ int oldOffset = d->verticalHeader->offset();
+ d->verticalHeader->d_func()->setScrollOffset(verticalScrollBar(), verticalScrollMode());
if (verticalScrollMode() == QAbstractItemView::ScrollPerItem) {
- int oldOffset = d->verticalHeader->offset();
- if (verticalScrollBar()->value() == verticalScrollBar()->maximum())
- d->verticalHeader->setOffsetToLastSection();
- else
- d->verticalHeader->setOffsetToSectionPosition(verticalScrollBar()->value());
int newOffset = d->verticalHeader->offset();
dy = oldOffset - newOffset;
- } else {
- d->verticalHeader->setOffset(verticalScrollBar()->value());
}
}
d->scrollContentsBy(dx, dy);
@@ -1760,13 +1808,13 @@ QModelIndex QTableView::moveCursor(CursorAction cursorAction, Qt::KeyboardModifi
visualRow = bottom;
break;
case MovePageUp: {
- int newRow = rowAt(visualRect(current).top() - d->viewport->height());
+ int newRow = rowAt(visualRect(current).bottom() - d->viewport->height());
if (newRow == -1)
newRow = d->logicalRow(0);
return d->model->index(newRow, current.column(), d->root);
}
case MovePageDown: {
- int newRow = rowAt(visualRect(current).bottom() + d->viewport->height());
+ int newRow = rowAt(visualRect(current).top() + d->viewport->height());
if (newRow == -1)
newRow = d->logicalRow(bottom);
return d->model->index(newRow, current.column(), d->root);
@@ -2128,7 +2176,7 @@ void QTableView::updateGeometries()
} else { // ScrollPerPixel
horizontalScrollBar()->setPageStep(vsize.width());
horizontalScrollBar()->setRange(0, horizontalLength - vsize.width());
- horizontalScrollBar()->setSingleStep(qMax(vsize.width() / (columnsInViewport + 1), 2));
+ // here we do not want to overwrite (a possible user set) single step
}
// vertical scroll bar
@@ -2156,7 +2204,7 @@ void QTableView::updateGeometries()
} else { // ScrollPerPixel
verticalScrollBar()->setPageStep(vsize.height());
verticalScrollBar()->setRange(0, verticalLength - vsize.height());
- verticalScrollBar()->setSingleStep(qMax(vsize.height() / (rowsInViewport + 1), 2));
+ // here we do not want to overwrite (a possible user set) single step
}
d->geometryRecursionBlock = false;
@@ -2175,7 +2223,7 @@ void QTableView::updateGeometries()
if a larger row height is required by either the vertical header or
the item delegate, that width will be used instead.
- \sa QWidget::sizeHint, verticalHeader()
+ \sa QWidget::sizeHint, verticalHeader(), QHeaderView::resizeContentsPrecision()
*/
int QTableView::sizeHintForRow(int row) const
{
@@ -2185,6 +2233,8 @@ int QTableView::sizeHintForRow(int row) const
return -1;
ensurePolished();
+ const int maximumProcessCols = d->verticalHeader->resizeContentsPrecision();
+
int left = qMax(0, d->horizontalHeader->visualIndexAt(0));
int right = d->horizontalHeader->visualIndexAt(d->viewport->width());
@@ -2195,27 +2245,55 @@ int QTableView::sizeHintForRow(int row) const
int hint = 0;
QModelIndex index;
- for (int column = left; column <= right; ++column) {
+ int columnsProcessed = 0;
+ int column = left;
+ for (; column <= right; ++column) {
int logicalColumn = d->horizontalHeader->logicalIndex(column);
if (d->horizontalHeader->isSectionHidden(logicalColumn))
continue;
index = d->model->index(row, logicalColumn, d->root);
- if (d->wrapItemText) {// for wrapping boundaries
- option.rect.setY(rowViewportPosition(index.row()));
- option.rect.setHeight(rowHeight(index.row()));
- option.rect.setX(columnViewportPosition(index.column()));
- option.rect.setWidth(columnWidth(index.column()));
- }
+ hint = d->heightHintForIndex(index, hint, option);
+
+ ++columnsProcessed;
+ if (columnsProcessed == maximumProcessCols)
+ break;
+ }
- QWidget *editor = d->editorForIndex(index).widget.data();
- if (editor && d->persistent.contains(editor)) {
- hint = qMax(hint, editor->sizeHint().height());
- int min = editor->minimumSize().height();
- int max = editor->maximumSize().height();
- hint = qBound(min, hint, max);
+ int actualRight = d->model->columnCount(d->root) - 1;
+ int idxLeft = left;
+ int idxRight = column - 1;
+
+ if (maximumProcessCols == 0)
+ columnsProcessed = 0; // skip the while loop
+
+ while (columnsProcessed != maximumProcessCols && (idxLeft > 0 || idxRight < actualRight)) {
+ int logicalIdx = -1;
+
+ if ((columnsProcessed % 2 && idxLeft > 0) || idxRight == actualRight) {
+ while (idxLeft > 0) {
+ --idxLeft;
+ int logcol = d->horizontalHeader->logicalIndex(idxLeft);
+ if (d->horizontalHeader->isSectionHidden(logcol))
+ continue;
+ logicalIdx = logcol;
+ break;
+ }
+ } else {
+ while (idxRight < actualRight) {
+ ++idxRight;
+ int logcol = d->horizontalHeader->logicalIndex(idxRight);
+ if (d->horizontalHeader->isSectionHidden(logcol))
+ continue;
+ logicalIdx = logcol;
+ break;
+ }
}
+ if (logicalIdx < 0)
+ continue;
- hint = qMax(hint, itemDelegate(index)->sizeHint(option, index).height());
+ index = d->model->index(row, logicalIdx, d->root);
+ hint = d->heightHintForIndex(index, hint, option);
+ ++columnsProcessed;
}
return d->showGrid ? hint + 1 : hint;
@@ -2234,7 +2312,7 @@ int QTableView::sizeHintForRow(int row) const
required by either the horizontal header or the item delegate, the larger
width will be used instead.
- \sa QWidget::sizeHint, horizontalHeader()
+ \sa QWidget::sizeHint, horizontalHeader(), QHeaderView::resizeContentsPrecision()
*/
int QTableView::sizeHintForColumn(int column) const
{
@@ -2244,6 +2322,7 @@ int QTableView::sizeHintForColumn(int column) const
return -1;
ensurePolished();
+ const int maximumProcessRows = d->horizontalHeader->resizeContentsPrecision();
int top = qMax(0, d->verticalHeader->visualIndexAt(0));
int bottom = d->verticalHeader->visualIndexAt(d->viewport->height());
@@ -2253,22 +2332,56 @@ int QTableView::sizeHintForColumn(int column) const
QStyleOptionViewItem option = d->viewOptions();
int hint = 0;
+ int rowsProcessed = 0;
QModelIndex index;
- for (int row = top; row <= bottom; ++row) {
+ int row = top;
+ for (; row <= bottom; ++row) {
int logicalRow = d->verticalHeader->logicalIndex(row);
if (d->verticalHeader->isSectionHidden(logicalRow))
continue;
index = d->model->index(logicalRow, column, d->root);
- QWidget *editor = d->editorForIndex(index).widget.data();
- if (editor && d->persistent.contains(editor)) {
- hint = qMax(hint, editor->sizeHint().width());
- int min = editor->minimumSize().width();
- int max = editor->maximumSize().width();
- hint = qBound(min, hint, max);
+ hint = d->widthHintForIndex(index, hint, option);
+ ++rowsProcessed;
+ if (rowsProcessed == maximumProcessRows)
+ break;
+ }
+
+ int actualBottom = d->model->rowCount(d->root) - 1;
+ int idxTop = top;
+ int idxBottom = row - 1;
+
+ if (maximumProcessRows == 0)
+ rowsProcessed = 0; // skip the while loop
+
+ while (rowsProcessed != maximumProcessRows && (idxTop > 0 || idxBottom < actualBottom)) {
+ int logicalIdx = -1;
+
+ if ((rowsProcessed % 2 && idxTop > 0) || idxBottom == actualBottom) {
+ while (idxTop > 0) {
+ --idxTop;
+ int logrow = d->verticalHeader->logicalIndex(idxTop);
+ if (d->verticalHeader->isSectionHidden(logrow))
+ continue;
+ logicalIdx = logrow;
+ break;
+ }
+ } else {
+ while (idxBottom < actualBottom) {
+ ++idxBottom;
+ int logrow = d->verticalHeader->logicalIndex(idxBottom);
+ if (d->verticalHeader->isSectionHidden(logrow))
+ continue;
+ logicalIdx = logrow;
+ break;
+ }
}
+ if (logicalIdx < 0)
+ continue;
- hint = qMax(hint, itemDelegate(index)->sizeHint(option, index).width());
+ index = d->model->index(logicalIdx, column, d->root);
+ hint = d->widthHintForIndex(index, hint, option);
+ ++rowsProcessed;
}
return d->showGrid ? hint + 1 : hint;
@@ -2934,6 +3047,8 @@ void QTableView::showColumn(int column)
/*!
Resizes the given \a row based on the size hints of the delegate
used to render each item in the row.
+
+ \sa resizeRowsToContents(), sizeHintForRow(), QHeaderView::resizeContentsPrecision()
*/
void QTableView::resizeRowToContents(int row)
{
@@ -2946,6 +3061,8 @@ void QTableView::resizeRowToContents(int row)
/*!
Resizes all rows based on the size hints of the delegate
used to render each item in the rows.
+
+ \sa resizeRowToContents(), sizeHintForRow(), QHeaderView::resizeContentsPrecision()
*/
void QTableView::resizeRowsToContents()
{
@@ -2959,6 +3076,8 @@ void QTableView::resizeRowsToContents()
\note Only visible columns will be resized. Reimplement sizeHintForColumn()
to resize hidden columns as well.
+
+ \sa resizeColumnsToContents(), sizeHintForColumn(), QHeaderView::resizeContentsPrecision()
*/
void QTableView::resizeColumnToContents(int column)
{
@@ -2971,6 +3090,8 @@ void QTableView::resizeColumnToContents(int column)
/*!
Resizes all columns based on the size hints of the delegate
used to render each item in the columns.
+
+ \sa resizeColumnToContents(), sizeHintForColumn(), QHeaderView::resizeContentsPrecision()
*/
void QTableView::resizeColumnsToContents()
{
diff --git a/src/widgets/itemviews/qtableview.h b/src/widgets/itemviews/qtableview.h
index 824348dbe8..db956480d6 100644
--- a/src/widgets/itemviews/qtableview.h
+++ b/src/widgets/itemviews/qtableview.h
@@ -118,6 +118,8 @@ public:
void sortByColumn(int column, Qt::SortOrder order);
+ QSize viewportSizeHint() const;
+
public Q_SLOTS:
void selectRow(int row);
void selectColumn(int column);
diff --git a/src/widgets/itemviews/qtableview_p.h b/src/widgets/itemviews/qtableview_p.h
index 923beec253..d36dcd2c3a 100644
--- a/src/widgets/itemviews/qtableview_p.h
+++ b/src/widgets/itemviews/qtableview_p.h
@@ -181,6 +181,8 @@ public:
const QStyleOptionViewItem &option, QBitArray *drawn,
int firstVisualRow, int lastVisualRow, int firstVisualColumn, int lastVisualColumn);
void drawCell(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index);
+ int widthHintForIndex(const QModelIndex &index, int hint, const QStyleOptionViewItem &option) const;
+ int heightHintForIndex(const QModelIndex &index, int hint, QStyleOptionViewItem &option) const;
bool showGrid;
Qt::PenStyle gridStyle;
diff --git a/src/widgets/itemviews/qtablewidget.cpp b/src/widgets/itemviews/qtablewidget.cpp
index d56314b23d..f15124605f 100644
--- a/src/widgets/itemviews/qtablewidget.cpp
+++ b/src/widgets/itemviews/qtablewidget.cpp
@@ -510,7 +510,7 @@ void QTableModel::sort(int column, Qt::SortOrder order)
}
LessThan compare = (order == Qt::AscendingOrder ? &itemLessThan : &itemGreaterThan);
- qStableSort(sortable.begin(), sortable.end(), compare);
+ std::stable_sort(sortable.begin(), sortable.end(), compare);
QVector<QTableWidgetItem*> sorted_table(tableItems.count());
QModelIndexList from;
@@ -558,7 +558,7 @@ void QTableModel::ensureSorted(int column, Qt::SortOrder order,
}
LessThan compare = (order == Qt::AscendingOrder ? &itemLessThan : &itemGreaterThan);
- qStableSort(sorting.begin(), sorting.end(), compare);
+ std::stable_sort(sorting.begin(), sorting.end(), compare);
QModelIndexList oldPersistentIndexes = persistentIndexList();
QModelIndexList newPersistentIndexes = oldPersistentIndexes;
diff --git a/src/widgets/itemviews/qtreeview.cpp b/src/widgets/itemviews/qtreeview.cpp
index 6aefbb5367..b5f1b12365 100644
--- a/src/widgets/itemviews/qtreeview.cpp
+++ b/src/widgets/itemviews/qtreeview.cpp
@@ -61,6 +61,8 @@
#include <private/qtreeview_p.h>
#include <private/qheaderview_p.h>
+#include <algorithm>
+
QT_BEGIN_NAMESPACE
/*!
@@ -335,6 +337,7 @@ void QTreeView::setHeader(QHeaderView *header)
this, SLOT(updateGeometries()));
setSortingEnabled(d->sortingEnabled);
+ d->updateGeometry();
}
/*!
@@ -952,6 +955,36 @@ bool QTreeView::wordWrap() const
return d->wrapItemText;
}
+/*!
+ \since 5.2
+
+ This specifies that the tree structure should be placed at logical index \a index.
+ If \index is set to -1 then the tree will always follow visual index 0.
+
+ \sa treePosition(), QHeaderView::swapSections(), QHeaderView::moveSection()
+*/
+
+void QTreeView::setTreePosition(int index)
+{
+ Q_D(QTreeView);
+ d->treePosition = index;
+ update();
+}
+
+/*!
+ \since 5.2
+
+ Return the logical index the tree is set on. If the return value is -1 then the
+ tree is placed on the visual index 0.
+
+ \sa setTreePosition()
+*/
+
+int QTreeView::treePosition() const
+{
+ Q_D(const QTreeView);
+ return d->treePosition;
+}
/*!
\reimp
@@ -1067,7 +1100,7 @@ QRect QTreeView::visualRect(const QModelIndex &index) const
int x = (spanning ? 0 : columnViewportPosition(index.column()));
int w = (spanning ? d->header->length() : columnWidth(index.column()));
// handle indentation
- if (index.column() == 0) {
+ if (d->isTreePosition(index.column())) {
int i = d->indentationForItem(vi);
w -= i;
if (!isRightToLeft())
@@ -1284,6 +1317,14 @@ void QTreeView::paintEvent(QPaintEvent *event)
}
}
+int QTreeViewPrivate::logicalIndexForTree() const
+{
+ int index = treePosition;
+ if (index < 0)
+ index = header->logicalIndex(0);
+ return index;
+}
+
void QTreeViewPrivate::paintAlternatingRowColors(QPainter *painter, QStyleOptionViewItem *option, int y, int bottom) const
{
Q_Q(const QTreeView);
@@ -1516,7 +1557,7 @@ void QTreeViewPrivate::calcLogicalIndices(QVector<int> *logicalIndices, QVector<
if (columnCount == 1 || (nextLogicalSection == 0 && prevLogicalSection == -1)
|| (headerSection == 0 && nextLogicalSection == -1) || spanning)
pos = QStyleOptionViewItem::OnlyOne;
- else if (headerSection == 0 || (nextLogicalSection != 0 && prevLogicalSection == -1))
+ else if (isTreePosition(headerSection) || (nextLogicalSection != 0 && prevLogicalSection == -1))
pos = QStyleOptionViewItem::Beginning;
else if (nextLogicalSection == 0 || nextLogicalSection == -1)
pos = QStyleOptionViewItem::End;
@@ -1526,6 +1567,23 @@ void QTreeViewPrivate::calcLogicalIndices(QVector<int> *logicalIndices, QVector<
}
}
+/*!
+ \internal
+ Get sizeHint width for single index (providing existing hint and style option) and index in viewIndex i.
+*/
+int QTreeViewPrivate::widthHintForIndex(const QModelIndex &index, int hint, const QStyleOptionViewItem &option, int i) const
+{
+ QWidget *editor = editorForIndex(index).widget.data();
+ if (editor && persistent.contains(editor)) {
+ hint = qMax(hint, editor->sizeHint().width());
+ int min = editor->minimumSize().width();
+ int max = editor->maximumSize().width();
+ hint = qBound(min, hint, max);
+ }
+ int xhint = delegateForIndex(index)->sizeHint(option, index).width();
+ hint = qMax(hint, xhint + (isTreePosition(index.column()) ? indentationForItem(i) : 0));
+ return hint;
+}
/*!
Draws the row in the tree view that contains the model item \a index,
@@ -1668,7 +1726,7 @@ void QTreeView::drawRow(QPainter *painter, const QStyleOptionViewItem &option,
alternate row color was provided by the view. For backward compatibility,
this is now delegated to the style using PE_PanelViewItemRow which
does the appropriate fill */
- if (headerSection == 0) {
+ if (d->isTreePosition(headerSection)) {
const int i = d->indentationForItem(d->current);
QRect branches(reverse ? position + width - i : position, y, i, height);
const bool setClipRect = branches.width() > width;
@@ -2123,10 +2181,10 @@ QModelIndex QTreeView::moveCursor(CursorAction cursorAction, Qt::KeyboardModifie
if (!current.isValid()) {
int i = d->below(-1);
int c = 0;
- while (c < d->header->count() && d->header->isSectionHidden(c))
+ while (c < d->header->count() && d->header->isSectionHidden(d->header->logicalIndex(c)))
++c;
if (i < d->viewItems.count() && c < d->header->count()) {
- return d->modelIndex(i, c);
+ return d->modelIndex(i, d->header->logicalIndex(c));
}
return QModelIndex();
}
@@ -2400,16 +2458,11 @@ void QTreeView::scrollContentsBy(int dx, int dy)
dx = isRightToLeft() ? -dx : dx;
if (dx) {
+ int oldOffset = d->header->offset();
+ d->header->d_func()->setScrollOffset(horizontalScrollBar(), horizontalScrollMode());
if (horizontalScrollMode() == QAbstractItemView::ScrollPerItem) {
- int oldOffset = d->header->offset();
- if (horizontalScrollBar()->value() == horizontalScrollBar()->maximum())
- d->header->setOffsetToLastSection();
- else
- d->header->setOffsetToSectionPosition(horizontalScrollBar()->value());
int newOffset = d->header->offset();
dx = isRightToLeft() ? newOffset - oldOffset : oldOffset - newOffset;
- } else {
- d->header->setOffset(horizontalScrollBar()->value());
}
}
@@ -2552,7 +2605,7 @@ void QTreeView::columnCountChanged(int oldCount, int newCount)
/*!
Resizes the \a column given to the size of its contents.
- \sa columnWidth(), setColumnWidth()
+ \sa columnWidth(), setColumnWidth(), sizeHintForColumn(), QHeaderView::resizeContentsPrecision()
*/
void QTreeView::resizeColumnToContents(int column)
{
@@ -2619,6 +2672,35 @@ void QTreeView::selectAll()
}
/*!
+ \reimp
+*/
+QSize QTreeView::viewportSizeHint() const
+{
+ Q_D(const QTreeView);
+ d->executePostedLayout(); // Make sure that viewItems are up to date.
+
+ if (d->viewItems.size() == 0)
+ return QAbstractItemView::viewportSizeHint();
+
+ // Get rect for last item
+ const QRect deepestRect = visualRect(d->viewItems.last().index);
+
+ if (!deepestRect.isValid())
+ return QAbstractItemView::viewportSizeHint();
+
+ QSize result = QSize(d->header->length(), deepestRect.bottom() + 1);
+
+ // add size for header
+ result += QSize(0, d->header->isVisible() ? d->header->height() : 0);
+
+ // add size for scrollbars
+ result += QSize(verticalScrollBar()->isVisible() ? verticalScrollBar()->width() : 0,
+ horizontalScrollBar()->isVisible() ? horizontalScrollBar()->height() : 0);
+
+ return result;
+}
+
+/*!
\since 4.2
Expands all expandable items.
@@ -2740,7 +2822,6 @@ void QTreeView::updateGeometries()
QRect vg = d->viewport->geometry();
QRect geometryRect(vg.left(), vg.top() - hint.height(), vg.width(), hint.height());
d->header->setGeometry(geometryRect);
- //d->header->setOffset(horizontalScrollBar()->value()); // ### bug ???
QMetaObject::invokeMethod(d->header, "updateGeometries");
d->updateScrollBars();
d->geometryRecursionBlock = false;
@@ -2760,7 +2841,7 @@ void QTreeView::updateGeometries()
if a larger column width is required by either the view's header or
the item delegate, that width will be used instead.
- \sa QWidget::sizeHint, header()
+ \sa QWidget::sizeHint, header(), QHeaderView::resizeContentsPrecision()
*/
int QTreeView::sizeHintForColumn(int column) const
{
@@ -2773,28 +2854,58 @@ int QTreeView::sizeHintForColumn(int column) const
QStyleOptionViewItem option = d->viewOptions();
const QVector<QTreeViewItem> viewItems = d->viewItems;
- int start = 0;
- int end = viewItems.count();
- if(end > 1000) { //if we have too many item this function would be too slow.
- //we get a good approximation by only iterate over 1000 items.
- start = qMax(0, d->firstVisibleItem() - 100);
- end = qMin(end, start + 900);
- }
+ const int maximumProcessRows = d->header->resizeContentsPrecision(); // To avoid this to take forever.
+
+ int offset = 0;
+ int start = d->firstVisibleItem(&offset);
+ int end = d->lastVisibleItem(start, offset);
- for (int i = start; i < end; ++i) {
+ int rowsProcessed = 0;
+
+ for (int i = start; i <= end; ++i) {
if (viewItems.at(i).spanning)
continue; // we have no good size hint
QModelIndex index = viewItems.at(i).index;
index = index.sibling(index.row(), column);
- QWidget *editor = d->editorForIndex(index).widget.data();
- if (editor && d->persistent.contains(editor)) {
- w = qMax(w, editor->sizeHint().width());
- int min = editor->minimumSize().width();
- int max = editor->maximumSize().width();
- w = qBound(min, w, max);
+ w = d->widthHintForIndex(index, w, option, i);
+ ++rowsProcessed;
+ if (rowsProcessed == maximumProcessRows)
+ break;
+ }
+
+ --end;
+ int actualBottom = viewItems.size() - 1;
+
+ if (maximumProcessRows == 0)
+ rowsProcessed = 0; // skip the while loop
+
+ while (rowsProcessed != maximumProcessRows && (start > 0 || end < actualBottom)) {
+ int idx = -1;
+
+ if ((rowsProcessed % 2 && start > 0) || end == actualBottom) {
+ while (start > 0) {
+ --start;
+ if (viewItems.at(start).spanning)
+ continue;
+ idx = start;
+ break;
+ }
+ } else {
+ while (end < actualBottom) {
+ ++end;
+ if (viewItems.at(end).spanning)
+ continue;
+ idx = end;
+ break;
+ }
}
- int hint = d->delegateForIndex(index)->sizeHint(option, index).width();
- w = qMax(w, hint + (column == 0 ? d->indentationForItem(i) : 0));
+ if (idx < 0)
+ continue;
+
+ QModelIndex index = viewItems.at(idx).index;
+ index = index.sibling(index.row(), column);
+ w = d->widthHintForIndex(index, w, option, idx);
+ ++rowsProcessed;
}
return w;
}
@@ -2915,6 +3026,7 @@ void QTreeViewPrivate::initialize()
header->setDefaultAlignment(Qt::AlignLeft|Qt::AlignVCenter);
q->setHeader(header);
#ifndef QT_NO_ANIMATION
+ animationsEnabled = q->style()->styleHint(QStyle::SH_Widget_Animate, 0, q);
QObject::connect(&animatedOperation, SIGNAL(finished()), q, SLOT(_q_endAnimatedOperation()));
#endif //QT_NO_ANIMATION
}
@@ -3314,7 +3426,7 @@ int QTreeViewPrivate::coordinateForItem(int item) const
if (verticalScrollMode == QAbstractItemView::ScrollPerPixel) {
if (uniformRowHeights)
return (item * defaultItemHeight) - vbar->value();
- // ### optimize (spans or caching)
+ // ### optimize (maybe do like QHeaderView by letting items have startposition)
int y = 0;
for (int i = 0; i < viewItems.count(); ++i) {
if (i == item)
@@ -3481,7 +3593,7 @@ int QTreeViewPrivate::firstVisibleItem(int *offset) const
*offset = -(value % defaultItemHeight);
return value / defaultItemHeight;
}
- int y = 0; // ### optimize (use spans ?)
+ int y = 0; // ### (maybe do like QHeaderView by letting items have startposition)
for (int i = 0; i < viewItems.count(); ++i) {
y += itemHeight(i); // the height value is cached
if (y > value) {
@@ -3493,6 +3605,21 @@ int QTreeViewPrivate::firstVisibleItem(int *offset) const
return -1;
}
+int QTreeViewPrivate::lastVisibleItem(int firstVisual, int offset) const
+{
+ if (firstVisual < 0 || offset < 0)
+ firstVisual = firstVisibleItem(&offset);
+ int y = - offset;
+ int value = viewport->height();
+
+ for (int i = firstVisual; i < viewItems.count(); ++i) {
+ y += itemHeight(i); // the height value is cached
+ if (y > value)
+ return i;
+ }
+ return viewItems.size() - 1;
+}
+
int QTreeViewPrivate::columnAt(int x) const
{
return header->logicalIndexAt(x);
@@ -3535,13 +3662,13 @@ void QTreeViewPrivate::updateScrollBars()
int contentsHeight = 0;
if (uniformRowHeights) {
contentsHeight = defaultItemHeight * viewItems.count();
- } else { // ### optimize (spans or caching)
+ } else { // ### (maybe do like QHeaderView by letting items have startposition)
for (int i = 0; i < viewItems.count(); ++i)
contentsHeight += itemHeight(i);
}
vbar->setRange(0, contentsHeight - viewportSize.height());
vbar->setPageStep(viewportSize.height());
- vbar->setSingleStep(qMax(viewportSize.height() / (itemsInViewport + 1), 2));
+ // here we do not want to overwrite (a possible user set) single step
}
const int columnCount = header->count();
@@ -3567,7 +3694,7 @@ void QTreeViewPrivate::updateScrollBars()
viewportSize = maxSize;
hbar->setPageStep(viewportSize.width());
hbar->setRange(0, qMax(horizontalLength - viewportSize.width(), 0));
- hbar->setSingleStep(qMax(viewportSize.width() / (columnsInViewport + 1), 2));
+ // here we do not want to overwrite (a possible user set) single step
}
}
@@ -3576,7 +3703,7 @@ int QTreeViewPrivate::itemDecorationAt(const QPoint &pos) const
executePostedLayout();
int x = pos.x();
int column = header->logicalIndexAt(x);
- if (column != 0)
+ if (!isTreePosition(column))
return -1; // no logical index at x
int viewItemIndex = itemAtCoordinate(pos.y());
@@ -3598,8 +3725,8 @@ QRect QTreeViewPrivate::itemDecorationRect(const QModelIndex &index) const
return QRect();
int itemIndentation = indentationForItem(viewItemIndex);
- int position = header->sectionViewportPosition(0);
- int size = header->sectionSize(0);
+ int position = header->sectionViewportPosition(logicalIndexForTree());
+ int size = header->sectionSize(logicalIndexForTree());
QRect rect;
if (q->isRightToLeft())
@@ -3633,7 +3760,7 @@ QList<QPair<int, int> > QTreeViewPrivate::columnRanges(const QModelIndex &topInd
}
}
//let's sort the list
- qSort(logicalIndexes.begin(), logicalIndexes.end());
+ std::sort(logicalIndexes.begin(), logicalIndexes.end());
QList<QPair<int, int> > ret;
QPair<int, int> current;
diff --git a/src/widgets/itemviews/qtreeview.h b/src/widgets/itemviews/qtreeview.h
index 73f11f1a48..d9c6cd9269 100644
--- a/src/widgets/itemviews/qtreeview.h
+++ b/src/widgets/itemviews/qtreeview.h
@@ -128,6 +128,9 @@ public:
void setWordWrap(bool on);
bool wordWrap() const;
+ void setTreePosition(int logicalIndex);
+ int treePosition() const;
+
void keyboardSearch(const QString &search);
QRect visualRect(const QModelIndex &index) const;
@@ -144,6 +147,8 @@ public:
void dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector<int> &roles = QVector<int>());
void selectAll();
+ QSize viewportSizeHint() const;
+
Q_SIGNALS:
void expanded(const QModelIndex &index);
void collapsed(const QModelIndex &index);
diff --git a/src/widgets/itemviews/qtreeview_p.h b/src/widgets/itemviews/qtreeview_p.h
index 90e83cb58c..89de435606 100644
--- a/src/widgets/itemviews/qtreeview_p.h
+++ b/src/widgets/itemviews/qtreeview_p.h
@@ -91,10 +91,16 @@ public:
expandsOnDoubleClick(true),
allColumnsShowFocus(false), current(0), spanning(false),
animationsEnabled(false), columnResizeTimerID(0),
- autoExpandDelay(-1), hoverBranch(-1), geometryRecursionBlock(false), hasRemovedItems(false) {}
+ autoExpandDelay(-1), hoverBranch(-1), geometryRecursionBlock(false), hasRemovedItems(false),
+ treePosition(0) {}
~QTreeViewPrivate() {}
void initialize();
+ int logicalIndexForTree() const;
+ inline bool isTreePosition(int logicalIndex) const
+ {
+ return logicalIndex == logicalIndexForTree();
+ }
QItemViewPaintPairs draggablePaintPairs(const QModelIndexList &indexes, QRect *r) const;
void adjustViewOptionsForIndex(QStyleOptionViewItem *option, const QModelIndex &current) const;
@@ -148,6 +154,7 @@ public:
#endif
int firstVisibleItem(int *offset = 0) const;
+ int lastVisibleItem(int firstVisual = -1, int offset = -1) const;
int columnAt(int x) const;
bool hasVisibleChildren( const QModelIndex& parent) const;
@@ -171,7 +178,7 @@ public:
// logicalIndices: vector of currently visibly logical indices
// itemPositions: vector of view item positions (beginning/middle/end/onlyone)
void calcLogicalIndices(QVector<int> *logicalIndices, QVector<QStyleOptionViewItem::ViewItemPosition> *itemPositions, int left, int right) const;
-
+ int widthHintForIndex(const QModelIndex &index, int hint, const QStyleOptionViewItem &option, int i) const;
QHeaderView *header;
int indent;
@@ -251,6 +258,9 @@ public:
// If we should clean the set
bool hasRemovedItems;
+
+ // tree position
+ int treePosition;
};
QT_END_NAMESPACE
diff --git a/src/widgets/itemviews/qtreewidget.cpp b/src/widgets/itemviews/qtreewidget.cpp
index f72abd20ab..f098236d5c 100644
--- a/src/widgets/itemviews/qtreewidget.cpp
+++ b/src/widgets/itemviews/qtreewidget.cpp
@@ -614,7 +614,7 @@ void QTreeModel::ensureSorted(int column, Qt::SortOrder order,
}
LessThan compare = (order == Qt::AscendingOrder ? &itemLessThan : &itemGreaterThan);
- qStableSort(sorting.begin(), sorting.end(), compare);
+ std::stable_sort(sorting.begin(), sorting.end(), compare);
QModelIndexList oldPersistentIndexes;
QModelIndexList newPersistentIndexes;
@@ -623,7 +623,13 @@ void QTreeModel::ensureSorted(int column, Qt::SortOrder order,
for (int i = 0; i < count; ++i) {
int oldRow = sorting.at(i).second;
+
+ int tmpitepos = lit - lst.begin();
QTreeWidgetItem *item = lst.takeAt(oldRow);
+ if (tmpitepos > lst.size())
+ --tmpitepos;
+ lit = lst.begin() + tmpitepos;
+
lit = sortedInsertionIterator(lit, lst.end(), order, item);
int newRow = qMax(lit - lst.begin(), 0);
@@ -848,7 +854,7 @@ void QTreeModel::sortItems(QList<QTreeWidgetItem*> *items, int column, Qt::SortO
// do the sorting
LessThan compare = (order == Qt::AscendingOrder ? &itemLessThan : &itemGreaterThan);
- qStableSort(sorting.begin(), sorting.end(), compare);
+ std::stable_sort(sorting.begin(), sorting.end(), compare);
QModelIndexList fromList;
QModelIndexList toList;