QMdiArea: fix quadratic behavior

Repeatedly calling QVector::erase(it) (via QMutableVectorIterator::remove())
results in quadratic runtime.

Use std::stable_partition, which does exactly what the old code tried to do,
except in linear time.

Change-Id: I6e5911ee781071bbb84d72449c969e3b9907da51
Reviewed-by: Olivier Goffart (Woboq GmbH) <ogoffart@woboq.com>
This commit is contained in:
Marc Mutz 2015-12-03 13:47:27 +01:00
parent 0d1024e0f1
commit dc41ff5a84

View File

@ -161,7 +161,6 @@
#include <QResizeEvent> #include <QResizeEvent>
#include <QScrollBar> #include <QScrollBar>
#include <QtAlgorithms> #include <QtAlgorithms>
#include <QMutableVectorIterator>
#include <QPainter> #include <QPainter>
#include <QFontMetrics> #include <QFontMetrics>
#include <QStyleOption> #include <QStyleOption>
@ -480,17 +479,16 @@ QVector<QRect> MinOverlapPlacer::getCandidatePlacements(const QSize &size, const
*/ */
QVector<QRect> MinOverlapPlacer::findNonInsiders(const QRect &domain, QVector<QRect> &source) QVector<QRect> MinOverlapPlacer::findNonInsiders(const QRect &domain, QVector<QRect> &source)
{ {
QVector<QRect> result; const auto containedInDomain =
result.reserve(source.size()); [domain](const QRect &srcRect) { return domain.contains(srcRect); };
QMutableVectorIterator<QRect> it(source); const auto firstOut = std::stable_partition(source.begin(), source.end(), containedInDomain);
while (it.hasNext()) {
const QRect srcRect = it.next(); QVector<QRect> result;
if (!domain.contains(srcRect)) { result.reserve(source.end() - firstOut);
result << srcRect; std::copy(firstOut, source.end(), std::back_inserter(result));
it.remove();
} source.erase(firstOut, source.end());
}
return result; return result;
} }