summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--doc/src/snippets/qstring/stringbuilder.cpp28
-rw-r--r--src/corelib/tools/qstring.cpp68
-rw-r--r--src/corelib/tools/qstringbuilder.cpp2
-rw-r--r--src/gui/graphicsview/qgraphicsitem_p.h8
-rw-r--r--src/gui/graphicsview/qgraphicsscene.cpp18
-rw-r--r--src/gui/itemviews/qlistview.cpp2
-rw-r--r--src/gui/widgets/qmenubar.cpp3
-rw-r--r--src/opengl/qpaintengine_opengl.cpp23
-rw-r--r--src/opengl/qpaintengine_opengl_p.h1
-rw-r--r--tests/auto/modeltest/modeltest.cpp4
-rw-r--r--tests/auto/qhttpnetworkconnection/qhttpnetworkconnection.pro1
-rw-r--r--tests/auto/qhttpnetworkreply/qhttpnetworkreply.pro1
-rw-r--r--tests/auto/qmenubar/tst_qmenubar.cpp36
-rw-r--r--tests/auto/qstatemachine/tst_qstatemachine.cpp10
-rw-r--r--tests/auto/qtabbar/tst_qtabbar.cpp2
-rw-r--r--tests/auto/windowsmobile/test/tst_windowsmobile.cpp2
16 files changed, 187 insertions, 22 deletions
diff --git a/doc/src/snippets/qstring/stringbuilder.cpp b/doc/src/snippets/qstring/stringbuilder.cpp
new file mode 100644
index 0000000..90803e2
--- /dev/null
+++ b/doc/src/snippets/qstring/stringbuilder.cpp
@@ -0,0 +1,28 @@
+
+//! [0]
+ QString foo;
+ QString type = "long";
+
+ foo->setText(QLatin1String("vector<") + type + QLatin1String(">::iterator"));
+
+ if (foo.startsWith("(" + type + ") 0x"))
+ ...
+//! [0]
+
+//! [3]
+ #define QT_USE_FAST_CONCATENATION
+//! [3]
+
+//! [4]
+ #define QT_USE_FAST_CONCATENATION
+ #define QT_USE_FAST_OPERATOR_PLUS
+//! [4]
+
+//! [5]
+ #include <QStringBuilder>
+
+ QString hello("hello");
+ QStringRef el(&hello, 2, 3);
+ QLatin1String world("world");
+ QString message = hello % el % world % QChar('!');
+//! [5]
diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp
index ced6dd5..3b70f44 100644
--- a/src/corelib/tools/qstring.cpp
+++ b/src/corelib/tools/qstring.cpp
@@ -663,6 +663,74 @@ const QString::Null QString::null = { };
formats, the \e precision represents the maximum number of
significant digits (trailing zeroes are omitted).
+ \section1 More Efficient String Construction
+
+ Using the QString \c{'+'} operator, it is easy to construct a
+ complex string from multiple substrings. You will often write code
+ like this:
+
+ \snippet doc/src/snippets/qstring/stringbuilder.cpp 0
+
+ There is nothing wrong with either of these string constructions,
+ but there are a few hidden inefficiencies. Beginning with Qt 4.6,
+ you can eliminate them.
+
+ First, multiple uses of the \c{'+'} operator usually means
+ multiple memory allocations. When concatenating \e{n} substrings,
+ where \e{n > 2}, there can be as many as \e{n - 1} calls to the
+ memory allocator.
+
+ Second, QLatin1String does not store its length internally but
+ calls qstrlen() when it needs to know its length.
+
+ In 4.6, an internal template class \c{QStringBuilder} has been
+ added along with a few helper functions. This class is marked
+ internal and does not appear in the documentation, because you
+ aren't meant to instantiate it in your code. Its use will be
+ automatic, as described below. The class is found in
+ \c {src/corelib/tools/qstringbuilder.cpp} if you want to have a
+ look at it.
+
+ \c{QStringBuilder} uses expression templates and reimplements the
+ \c{'%'} operator so that when you use \c{'%'} for string
+ concatenation instead of \c{'+'}, multiple substring
+ concatenations will be postponed until the final result is about
+ to be assigned to a QString. At this point, the amount of memory
+ required for the final result is known. The memory allocator is
+ then called \e{once} to get the required space, and the substrings
+ are copied into it one by one.
+
+ \c{QLatin1Literal} is a second internal class that can replace
+ QLatin1String, which can't be changed for compatibility reasons.
+ \c{QLatin1Literal} stores its length, thereby saving time when
+ \c{QStringBuilder} computes the amount of memory required for the
+ final string.
+
+ Additional efficiency is gained by inlining and reduced reference
+ counting (the QString created from a \c{QStringBuilder} typically
+ has a ref count of 1, whereas QString::append() needs an extra
+ test).
+
+ There are three ways you can access this improved method of string
+ construction. The straightforward way is to include
+ \c{QStringBuilder} wherever you want to use it, and use the
+ \c{'%'} operator instead of \c{'+'} when concatenating strings:
+
+ \snippet doc/src/snippets/qstring/stringbuilder.cpp 5
+
+ A more global approach is to include this define:
+
+ \snippet doc/src/snippets/qstring/stringbuilder.cpp 3
+
+ and use \c{'%'} instead of \c{'+'} for string concatenation
+ everywhere. The third approach, which is the most convenient but
+ not entirely source compatible, is to include two defines:
+
+ \snippet doc/src/snippets/qstring/stringbuilder.cpp 4
+
+ and the \c{'+'} will automatically be performed as the
+ \c{QStringBuilder} \c{'%'} everywhere.
+
\sa fromRawData(), QChar, QLatin1String, QByteArray, QStringRef
*/
diff --git a/src/corelib/tools/qstringbuilder.cpp b/src/corelib/tools/qstringbuilder.cpp
index 17e2cec..fbb784e 100644
--- a/src/corelib/tools/qstringbuilder.cpp
+++ b/src/corelib/tools/qstringbuilder.cpp
@@ -43,6 +43,7 @@
/*!
\class QLatin1Literal
+ \internal
\reentrant
\since 4.6
@@ -83,6 +84,7 @@
/*!
\class QStringBuilder
+ \internal
\reentrant
\since 4.6
diff --git a/src/gui/graphicsview/qgraphicsitem_p.h b/src/gui/graphicsview/qgraphicsitem_p.h
index b7fb122..b9e7041 100644
--- a/src/gui/graphicsview/qgraphicsitem_p.h
+++ b/src/gui/graphicsview/qgraphicsitem_p.h
@@ -366,14 +366,6 @@ public:
|| (childrenCombineOpacity() && isFullyTransparent());
}
- inline bool updateHelper(QGraphicsViewPrivate *view, const QRectF &rect, const QTransform &xform) const
- {
- Q_ASSERT(view);
- if (hasBoundingRegionGranularity)
- return view->updateRegion(xform.map(QRegion(rect.toRect())));
- return view->updateRect(xform.mapRect(rect).toRect());
- }
-
inline QTransform transformToParent() const;
QPainterPath cachedClipPath;
diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp
index 71a4f08..d9d31ef 100644
--- a/src/gui/graphicsview/qgraphicsscene.cpp
+++ b/src/gui/graphicsview/qgraphicsscene.cpp
@@ -5306,6 +5306,16 @@ void QGraphicsScenePrivate::markDirty(QGraphicsItem *item, const QRectF &rect, b
}
}
+static inline bool updateHelper(QGraphicsViewPrivate *view, QGraphicsItemPrivate *item,
+ const QRectF &rect, const QTransform &xform)
+{
+ Q_ASSERT(view);
+ Q_ASSERT(item);
+ if (item->hasBoundingRegionGranularity)
+ return view->updateRegion(xform.map(QRegion(rect.toRect())));
+ return view->updateRect(xform.mapRect(rect).toRect());
+}
+
void QGraphicsScenePrivate::processDirtyItemsRecursive(QGraphicsItem *item, bool dirtyAncestorContainsChildren,
qreal parentOpacity)
{
@@ -5401,14 +5411,14 @@ void QGraphicsScenePrivate::processDirtyItemsRecursive(QGraphicsItem *item, bool
bool valid = false;
if (untransformableItem) {
- valid = item->d_ptr->updateHelper(viewPrivate, dirtyRect,
- item->deviceTransform(view->viewportTransform()));
+ valid = updateHelper(viewPrivate, item->d_ptr, dirtyRect,
+ item->deviceTransform(view->viewportTransform()));
} else if (!view->isTransformed()) {
- valid = item->d_ptr->updateHelper(viewPrivate, dirtyRect, item->d_ptr->sceneTransform);
+ valid = updateHelper(viewPrivate, item->d_ptr, dirtyRect, item->d_ptr->sceneTransform);
} else {
QTransform deviceTransform = item->d_ptr->sceneTransform;
deviceTransform *= view->viewportTransform();
- valid = !item->d_ptr->updateHelper(viewPrivate, dirtyRect, deviceTransform);
+ valid = updateHelper(viewPrivate, item->d_ptr, dirtyRect, deviceTransform);
}
if (!valid)
paintedViewBoundingRect = QRect();
diff --git a/src/gui/itemviews/qlistview.cpp b/src/gui/itemviews/qlistview.cpp
index 9b25730..f1b0d19 100644
--- a/src/gui/itemviews/qlistview.cpp
+++ b/src/gui/itemviews/qlistview.cpp
@@ -827,6 +827,8 @@ void QListView::rowsAboutToBeRemoved(const QModelIndex &parent, int start, int e
*/
void QListView::mouseMoveEvent(QMouseEvent *e)
{
+ if (!isVisible())
+ return;
Q_D(QListView);
QAbstractItemView::mouseMoveEvent(e);
if (state() == DragSelectingState
diff --git a/src/gui/widgets/qmenubar.cpp b/src/gui/widgets/qmenubar.cpp
index 3857e30..34de252 100644
--- a/src/gui/widgets/qmenubar.cpp
+++ b/src/gui/widgets/qmenubar.cpp
@@ -1253,7 +1253,8 @@ void QMenuBar::mouseMoveEvent(QMouseEvent *e)
void QMenuBar::leaveEvent(QEvent *)
{
Q_D(QMenuBar);
- if(!hasFocus() && !d->popupState)
+ if((!hasFocus() && !d->popupState) ||
+ (d->currentAction && d->currentAction->menu() == 0))
d->setCurrentAction(0);
}
diff --git a/src/opengl/qpaintengine_opengl.cpp b/src/opengl/qpaintengine_opengl.cpp
index 84ad4d5..b594f5b 100644
--- a/src/opengl/qpaintengine_opengl.cpp
+++ b/src/opengl/qpaintengine_opengl.cpp
@@ -662,6 +662,7 @@ public:
, txop(QTransform::TxNone)
, inverseScale(1)
, moveToCount(0)
+ , last_created_state(0)
, shader_ctx(0)
, grad_palette(0)
, drawable_texture(0)
@@ -788,6 +789,8 @@ public:
void updateGLMatrix() const;
+ mutable QPainterState *last_created_state;
+
QGLContext *shader_ctx;
GLuint grad_palette;
@@ -2219,6 +2222,8 @@ void QOpenGLPaintEnginePrivate::updateDepthClip()
{
Q_Q(QOpenGLPaintEngine);
+ ++q->state()->depthClipId;
+
glDisable(GL_DEPTH_TEST);
glDisable(GL_SCISSOR_TEST);
@@ -5501,9 +5506,20 @@ void QOpenGLPaintEngine::clip(const QVectorPath &path, Qt::ClipOperation op)
void QOpenGLPaintEngine::setState(QPainterState *s)
{
Q_D(QOpenGLPaintEngine);
+ QOpenGLPaintEngineState *new_state = static_cast<QOpenGLPaintEngineState *>(s);
+ QOpenGLPaintEngineState *old_state = state();
+
QPaintEngineEx::setState(s);
+
+ // are we in a save() ?
+ if (s == d->last_created_state) {
+ d->last_created_state = 0;
+ return;
+ }
+
if (isActive()) {
- d->updateDepthClip();
+ if (old_state->depthClipId != new_state->depthClipId)
+ d->updateDepthClip();
penChanged();
brushChanged();
opacityChanged();
@@ -5515,12 +5531,15 @@ void QOpenGLPaintEngine::setState(QPainterState *s)
QPainterState *QOpenGLPaintEngine::createState(QPainterState *orig) const
{
+ const Q_D(QOpenGLPaintEngine);
+
QOpenGLPaintEngineState *s;
if (!orig)
s = new QOpenGLPaintEngineState();
else
s = new QOpenGLPaintEngineState(*static_cast<QOpenGLPaintEngineState *>(orig));
+ d->last_created_state = s;
return s;
}
@@ -5534,11 +5553,13 @@ QOpenGLPaintEngineState::QOpenGLPaintEngineState(QOpenGLPaintEngineState &other)
clipRegion = other.clipRegion;
hasClipping = other.hasClipping;
fastClip = other.fastClip;
+ depthClipId = other.depthClipId;
}
QOpenGLPaintEngineState::QOpenGLPaintEngineState()
{
hasClipping = false;
+ depthClipId = 0;
}
QOpenGLPaintEngineState::~QOpenGLPaintEngineState()
diff --git a/src/opengl/qpaintengine_opengl_p.h b/src/opengl/qpaintengine_opengl_p.h
index 891cbd6..439782b 100644
--- a/src/opengl/qpaintengine_opengl_p.h
+++ b/src/opengl/qpaintengine_opengl_p.h
@@ -69,6 +69,7 @@ public:
QRegion clipRegion;
bool hasClipping;
QRect fastClip;
+ uint depthClipId;
};
class QOpenGLPaintEngine : public QPaintEngineEx
diff --git a/tests/auto/modeltest/modeltest.cpp b/tests/auto/modeltest/modeltest.cpp
index 68b723f..c4cc820 100644
--- a/tests/auto/modeltest/modeltest.cpp
+++ b/tests/auto/modeltest/modeltest.cpp
@@ -475,7 +475,7 @@ void ModelTest::data()
void ModelTest::rowsAboutToBeInserted ( const QModelIndex &parent, int start, int end )
{
// Q_UNUSED(end);
- qDebug() << "rowsAboutToBeInserted" << "start=" << start << "end=" << end << "parent=" << model->data ( parent ).value<QString>()
+ qDebug() << "rowsAboutToBeInserted" << "start=" << start << "end=" << end << "parent=" << model->data ( parent ).toString()
<< "current count of parent=" << model->rowCount ( parent ); // << "display of last=" << model->data( model->index(start-1, 0, parent) );
// qDebug() << model->index(start-1, 0, parent) << model->data( model->index(start-1, 0, parent) );
Changing c;
@@ -496,7 +496,7 @@ void ModelTest::rowsInserted ( const QModelIndex & parent, int start, int end )
Changing c = insert.pop();
Q_ASSERT ( c.parent == parent );
qDebug() << "rowsInserted" << "start=" << start << "end=" << end << "oldsize=" << c.oldSize
- << "parent=" << model->data ( parent ).value<QString>() << "current rowcount of parent=" << model->rowCount ( parent );
+ << "parent=" << model->data ( parent ).toString() << "current rowcount of parent=" << model->rowCount ( parent );
for (int ii=start; ii <= end; ii++)
{
diff --git a/tests/auto/qhttpnetworkconnection/qhttpnetworkconnection.pro b/tests/auto/qhttpnetworkconnection/qhttpnetworkconnection.pro
index bc750c5..3283873 100644
--- a/tests/auto/qhttpnetworkconnection/qhttpnetworkconnection.pro
+++ b/tests/auto/qhttpnetworkconnection/qhttpnetworkconnection.pro
@@ -1,4 +1,5 @@
load(qttest_p4)
SOURCES += tst_qhttpnetworkconnection.cpp
+INCLUDEPATH += $$(QTDIR)/src/3rdparty/zlib
QT = core network
diff --git a/tests/auto/qhttpnetworkreply/qhttpnetworkreply.pro b/tests/auto/qhttpnetworkreply/qhttpnetworkreply.pro
index 9593c55..0755055 100644
--- a/tests/auto/qhttpnetworkreply/qhttpnetworkreply.pro
+++ b/tests/auto/qhttpnetworkreply/qhttpnetworkreply.pro
@@ -1,4 +1,5 @@
load(qttest_p4)
SOURCES += tst_qhttpnetworkreply.cpp
+INCLUDEPATH += $$(QTDIR)/src/3rdparty/zlib
QT = core network
diff --git a/tests/auto/qmenubar/tst_qmenubar.cpp b/tests/auto/qmenubar/tst_qmenubar.cpp
index 5404d46..8a38782 100644
--- a/tests/auto/qmenubar/tst_qmenubar.cpp
+++ b/tests/auto/qmenubar/tst_qmenubar.cpp
@@ -149,6 +149,7 @@ private slots:
void check_shortcutPress();
void check_menuPosition();
void task223138_triggered();
+ void task256322_highlight();
#if defined(QT3_SUPPORT)
void indexBasedInsertion_data();
@@ -1520,6 +1521,41 @@ void tst_QMenuBar::task223138_triggered()
QCOMPARE(submenuSpy.count(), 1);
}
+void tst_QMenuBar::task256322_highlight()
+{
+ QMainWindow win;
+ QMenu menu;
+ QAction *file = win.menuBar()->addMenu(&menu);
+ file->setText("file");
+ QMenu menu2;
+ QAction *file2 = win.menuBar()->addMenu(&menu2);
+ file2->setText("file2");
+ QAction *nothing = win.menuBar()->addAction("nothing");
+
+ win.show();
+
+ QTest::mouseClick(win.menuBar(), Qt::LeftButton, 0, win.menuBar()->actionGeometry(file).center());
+ QVERIFY(menu.isVisible());
+ QVERIFY(!menu2.isVisible());
+ QCOMPARE(win.menuBar()->activeAction(), file);
+
+ QTest::mouseMove(win.menuBar(), win.menuBar()->actionGeometry(file2).center());
+ QVERIFY(!menu.isVisible());
+ QVERIFY(menu2.isVisible());
+ QCOMPARE(win.menuBar()->activeAction(), file2);
+
+ QTest::mouseMove(win.menuBar(), win.menuBar()->actionGeometry(nothing).center());
+ QVERIFY(!menu.isVisible());
+ QVERIFY(!menu2.isVisible());
+ QCOMPARE(win.menuBar()->activeAction(), nothing);
+
+ QTest::mouseMove(&win, win.menuBar()->geometry().bottomLeft() + QPoint(1,1));
+
+ QVERIFY(!menu.isVisible());
+ QVERIFY(!menu2.isVisible());
+ QVERIFY(!win.menuBar()->activeAction());
+}
+
#if defined(QT3_SUPPORT)
void tst_QMenuBar::indexBasedInsertion_data()
diff --git a/tests/auto/qstatemachine/tst_qstatemachine.cpp b/tests/auto/qstatemachine/tst_qstatemachine.cpp
index 6040abd..b39f0a1 100644
--- a/tests/auto/qstatemachine/tst_qstatemachine.cpp
+++ b/tests/auto/qstatemachine/tst_qstatemachine.cpp
@@ -413,7 +413,7 @@ void tst_QStateMachine::customGlobalErrorState()
machine.start();
QCoreApplication::processEvents();
- QCOMPARE(machine.errorState(), customErrorState);
+ QCOMPARE(machine.errorState(), static_cast<QAbstractState*>(customErrorState));
QCOMPARE(machine.configuration().count(), 1);
QVERIFY(machine.configuration().contains(initialState));
@@ -1724,18 +1724,18 @@ void tst_QStateMachine::signalTransitions()
QStateMachine machine;
QState *s0 = new QState(machine.rootState());
QTest::ignoreMessage(QtWarningMsg, "QState::addTransition: sender cannot be null");
- QCOMPARE(s0->addTransition(0, SIGNAL(noSuchSignal()), 0), (QAbstractTransition*)0);
+ QCOMPARE(s0->addTransition(0, SIGNAL(noSuchSignal()), 0), (QSignalTransition*)0);
SignalEmitter emitter;
QTest::ignoreMessage(QtWarningMsg, "QState::addTransition: signal cannot be null");
- QCOMPARE(s0->addTransition(&emitter, 0, 0), (QAbstractTransition*)0);
+ QCOMPARE(s0->addTransition(&emitter, 0, 0), (QSignalTransition*)0);
QTest::ignoreMessage(QtWarningMsg, "QState::addTransition: cannot add transition to null state");
- QCOMPARE(s0->addTransition(&emitter, SIGNAL(signalWithNoArg()), 0), (QAbstractTransition*)0);
+ QCOMPARE(s0->addTransition(&emitter, SIGNAL(signalWithNoArg()), 0), (QSignalTransition*)0);
QFinalState *s1 = new QFinalState(machine.rootState());
QTest::ignoreMessage(QtWarningMsg, "QState::addTransition: no such signal SignalEmitter::noSuchSignal()");
- QCOMPARE(s0->addTransition(&emitter, SIGNAL(noSuchSignal()), s1), (QAbstractTransition*)0);
+ QCOMPARE(s0->addTransition(&emitter, SIGNAL(noSuchSignal()), s1), (QSignalTransition*)0);
QSignalTransition *trans = s0->addTransition(&emitter, SIGNAL(signalWithNoArg()), s1);
QVERIFY(trans != 0);
diff --git a/tests/auto/qtabbar/tst_qtabbar.cpp b/tests/auto/qtabbar/tst_qtabbar.cpp
index 29f42df..f908d3f 100644
--- a/tests/auto/qtabbar/tst_qtabbar.cpp
+++ b/tests/auto/qtabbar/tst_qtabbar.cpp
@@ -370,7 +370,7 @@ void tst_QTabBar::tabButton()
tabbar.setTabButton(0, position, button);
- QCOMPARE(tabbar.tabButton(0, position), static_cast<const QWidget *>(button));
+ QCOMPARE(tabbar.tabButton(0, position), static_cast<QWidget *>(button));
QTRY_VERIFY(!button->isHidden());
QVERIFY(tabbar.tabButton(0, otherSide) == 0);
QCOMPARE(button->parent(), static_cast<QObject *>(&tabbar));
diff --git a/tests/auto/windowsmobile/test/tst_windowsmobile.cpp b/tests/auto/windowsmobile/test/tst_windowsmobile.cpp
index 843974d..8c7c021 100644
--- a/tests/auto/windowsmobile/test/tst_windowsmobile.cpp
+++ b/tests/auto/windowsmobile/test/tst_windowsmobile.cpp
@@ -44,8 +44,10 @@
#include <QtCore/QDebug>
#include <QtCore/QObject>
#include <QtGui>
+#ifdef Q_OS_WINCE_WM
#include <windows.h>
#include <ddhelper.h>
+#endif