summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorQt Continuous Integration System <qt-info@nokia.com>2010-06-14 23:59:31 (GMT)
committerQt Continuous Integration System <qt-info@nokia.com>2010-06-14 23:59:31 (GMT)
commiteaa981c943293bf346a041aa4ad3d254e99ebd78 (patch)
tree860d47d678f1ff9fb640b1046b8f67cf01df375a
parent7390cfbcbd5000a7da3eb5dbef790d114b06d042 (diff)
parent3d85883b9e4957f44a870ffb8530acc16882ac01 (diff)
downloadQt-eaa981c943293bf346a041aa4ad3d254e99ebd78.zip
Qt-eaa981c943293bf346a041aa4ad3d254e99ebd78.tar.gz
Qt-eaa981c943293bf346a041aa4ad3d254e99ebd78.tar.bz2
Merge branch 'qt-4.7-from-4.6' of scm.dev.nokia.troll.no:qt/qt-integration into 4.7-integration
* 'qt-4.7-from-4.6' of scm.dev.nokia.troll.no:qt/qt-integration: Prospective S60 build fix Thread safety for QFontEngineS60 Allow to build Qt in static with mingw Fix incorrect line breaking in QtWebKit. QLocalSocket: don't emit readChannelFinished() twice on Windows QLocalSocket/Win: QLocalSocketPrivate::bytesAvailable renamed QLocalSocket: fix reading from a socket after broken connection QLocalServer: make many simultaneous connection attempts work on Windows tst_QLocalSocket::threadedConnection autotest stabilized tst_qlocalsocket: pro files of client / server examples fixed Updated WebKit from /home/shausman/src/webkit/trunk to qtwebkit/qtwebkit-4.6 ( d8a9d09376a47b92ea49f1a078c392cbfdbc0ed6 )
-rw-r--r--src/corelib/tools/qtextboundaryfinder.cpp12
-rw-r--r--src/gui/kernel/qapplication_s60.cpp25
-rw-r--r--src/gui/kernel/qt_s60_p.h26
-rw-r--r--src/gui/text/qfontdatabase_s60.cpp20
-rw-r--r--src/gui/text/qfontengine_s60.cpp2
-rw-r--r--src/network/socket/qlocalserver_p.h1
-rw-r--r--src/network/socket/qlocalserver_win.cpp6
-rw-r--r--src/network/socket/qlocalsocket_p.h2
-rw-r--r--src/network/socket/qlocalsocket_win.cpp25
-rw-r--r--tests/auto/qlocalsocket/example/client/client.pro6
-rw-r--r--tests/auto/qlocalsocket/example/server/server.pro6
-rw-r--r--tests/auto/qlocalsocket/tst_qlocalsocket.cpp54
-rw-r--r--tests/auto/qtextboundaryfinder/tst_qtextboundaryfinder.cpp111
13 files changed, 221 insertions, 75 deletions
diff --git a/src/corelib/tools/qtextboundaryfinder.cpp b/src/corelib/tools/qtextboundaryfinder.cpp
index 9205297..bcddcb2 100644
--- a/src/corelib/tools/qtextboundaryfinder.cpp
+++ b/src/corelib/tools/qtextboundaryfinder.cpp
@@ -131,6 +131,11 @@ static void init(QTextBoundaryFinder::BoundaryType type, const QChar *chars, int
Line break boundaries give possible places where a line break
might happen and sentence boundaries will show the beginning and
end of whole sentences.
+
+ The first position in a string is always a valid boundary and
+ refers to the position before the first character. The last
+ position at the length of the string is also valid and refers
+ to the position after the last character.
*/
/*!
@@ -363,7 +368,8 @@ int QTextBoundaryFinder::toNextBoundary()
++pos;
break;
case Line:
- while (pos < length && d->attributes[pos].lineBreakType < HB_Break)
+ Q_ASSERT(pos);
+ while (pos < length && d->attributes[pos-1].lineBreakType < HB_Break)
++pos;
break;
}
@@ -405,7 +411,7 @@ int QTextBoundaryFinder::toPreviousBoundary()
--pos;
break;
case Line:
- while (pos > 0 && d->attributes[pos].lineBreakType < HB_Break)
+ while (pos > 0 && d->attributes[pos-1].lineBreakType < HB_Break)
--pos;
break;
}
@@ -430,7 +436,7 @@ bool QTextBoundaryFinder::isAtBoundary() const
case Word:
return d->attributes[pos].wordBoundary;
case Line:
- return d->attributes[pos].lineBreakType >= HB_Break;
+ return (pos > 0) ? d->attributes[pos-1].lineBreakType >= HB_Break : true;
case Sentence:
return d->attributes[pos].sentenceBoundary;
}
diff --git a/src/gui/kernel/qapplication_s60.cpp b/src/gui/kernel/qapplication_s60.cpp
index a50fd95..d5d4be6 100644
--- a/src/gui/kernel/qapplication_s60.cpp
+++ b/src/gui/kernel/qapplication_s60.cpp
@@ -2196,4 +2196,29 @@ void QApplication::restoreOverrideCursor()
#endif // QT_NO_CURSOR
+QS60ThreadLocalData::QS60ThreadLocalData()
+{
+ CCoeEnv *env = CCoeEnv::Static();
+ if (env) {
+ //if this is the UI thread, share objects owned by CONE
+ usingCONEinstances = true;
+ wsSession = env->WsSession();
+ screenDevice = env->ScreenDevice();
+ }
+ else {
+ usingCONEinstances = false;
+ qt_symbian_throwIfError(wsSession.Connect(qt_s60GetRFs()));
+ screenDevice = new CWsScreenDevice(wsSession);
+ screenDevice->Construct();
+ }
+}
+
+QS60ThreadLocalData::~QS60ThreadLocalData()
+{
+ if (!usingCONEinstances) {
+ delete screenDevice;
+ wsSession.Close();
+ }
+}
+
QT_END_NAMESPACE
diff --git a/src/gui/kernel/qt_s60_p.h b/src/gui/kernel/qt_s60_p.h
index fe3fa57..ed53ccf 100644
--- a/src/gui/kernel/qt_s60_p.h
+++ b/src/gui/kernel/qt_s60_p.h
@@ -63,6 +63,7 @@
#include "qpointer.h"
#include "qapplication.h"
#include "qelapsedtimer.h"
+#include "QtCore/qthreadstorage.h"
#include <w32std.h>
#include <coecntrl.h>
#include <eikenv.h>
@@ -86,10 +87,21 @@ const TInt KInternalStatusPaneChange = 0x50000000;
//this macro exists because EColor16MAP enum value doesn't exist in Symbian OS 9.2
#define Q_SYMBIAN_ECOLOR16MAP TDisplayMode(13)
+class QS60ThreadLocalData
+{
+public:
+ QS60ThreadLocalData();
+ ~QS60ThreadLocalData();
+ bool usingCONEinstances;
+ RWsSession wsSession;
+ CWsScreenDevice *screenDevice;
+};
+
class QS60Data
{
public:
QS60Data();
+ QThreadStorage<QS60ThreadLocalData *> tls;
TUid uid;
int screenDepth;
QPoint lastCursorPos;
@@ -132,9 +144,9 @@ public:
int memoryLimitForHwRendering;
QApplication::QS60MainApplicationFactory s60ApplicationFactory; // typedef'ed pointer type
static inline void updateScreenSize();
- static inline RWsSession& wsSession();
+ inline RWsSession& wsSession();
static inline RWindowGroup& windowGroup();
- static inline CWsScreenDevice* screenDevice();
+ inline CWsScreenDevice* screenDevice();
static inline CCoeAppUi* appUi();
static inline CEikMenuBar* menuBar();
#ifdef Q_WS_S60
@@ -265,7 +277,10 @@ inline void QS60Data::updateScreenSize()
inline RWsSession& QS60Data::wsSession()
{
- return CCoeEnv::Static()->WsSession();
+ if(!tls.hasLocalData()) {
+ tls.setLocalData(new QS60ThreadLocalData);
+ }
+ return tls.localData()->wsSession;
}
inline RWindowGroup& QS60Data::windowGroup()
@@ -275,7 +290,10 @@ inline RWindowGroup& QS60Data::windowGroup()
inline CWsScreenDevice* QS60Data::screenDevice()
{
- return CCoeEnv::Static()->ScreenDevice();
+ if(!tls.hasLocalData()) {
+ tls.setLocalData(new QS60ThreadLocalData);
+ }
+ return tls.localData()->screenDevice;
}
inline CCoeAppUi* QS60Data::appUi()
diff --git a/src/gui/text/qfontdatabase_s60.cpp b/src/gui/text/qfontdatabase_s60.cpp
index 943df7f..cdfba3d 100644
--- a/src/gui/text/qfontdatabase_s60.cpp
+++ b/src/gui/text/qfontdatabase_s60.cpp
@@ -118,7 +118,7 @@ public:
{
if (!font)
return;
- QS60Data::screenDevice()->ReleaseFont(font);
+ S60->screenDevice()->ReleaseFont(font);
}
};
@@ -205,7 +205,7 @@ const QSymbianTypeFaceExtras *QSymbianFontDatabaseExtrasImplementation::extras(c
CFont* font = NULL;
#ifdef Q_SYMBIAN_HAS_FONTTABLE_API
- const TInt err = QS60Data::screenDevice()->GetNearestFontToDesignHeightInPixels(font, searchSpec);
+ const TInt err = S60->screenDevice()->GetNearestFontToDesignHeightInPixels(font, searchSpec);
Q_ASSERT(err == KErrNone && font);
QScopedPointer<CFont, CFontFromScreenDeviceReleaser> sFont(font);
QSymbianTypeFaceExtras *extras = new QSymbianTypeFaceExtras(font);
@@ -260,17 +260,19 @@ QFontEngineFTS60::QFontEngineFTS60(const QFontDef &fd)
*/
qreal QFontEngineS60::pixelsToPoints(qreal pixels, Qt::Orientation orientation)
{
+ CWsScreenDevice* device = S60->screenDevice();
return (orientation == Qt::Horizontal?
- S60->screenDevice()->HorizontalPixelsToTwips(pixels)
- :S60->screenDevice()->VerticalPixelsToTwips(pixels)) / KTwipsPerPoint;
+ device->HorizontalPixelsToTwips(pixels)
+ :device->VerticalPixelsToTwips(pixels)) / KTwipsPerPoint;
}
qreal QFontEngineS60::pointsToPixels(qreal points, Qt::Orientation orientation)
{
+ CWsScreenDevice* device = S60->screenDevice();
const int twips = points * KTwipsPerPoint;
return orientation == Qt::Horizontal?
- S60->screenDevice()->HorizontalTwipsToPixels(twips)
- :S60->screenDevice()->VerticalTwipsToPixels(twips);
+ device->HorizontalTwipsToPixels(twips)
+ :device->VerticalTwipsToPixels(twips);
}
QFontEngineMultiS60::QFontEngineMultiS60(QFontEngine *first, int script, const QStringList &fallbackFamilies)
@@ -309,16 +311,16 @@ static void initializeDb()
QSymbianFbsHeapLock lock(QSymbianFbsHeapLock::Unlock);
- const int numTypeFaces = QS60Data::screenDevice()->NumTypefaces();
+ const int numTypeFaces = S60->screenDevice()->NumTypefaces();
const QSymbianFontDatabaseExtrasImplementation *dbExtras =
static_cast<const QSymbianFontDatabaseExtrasImplementation*>(db->symbianExtras);
bool fontAdded = false;
for (int i = 0; i < numTypeFaces; i++) {
TTypefaceSupport typefaceSupport;
- QS60Data::screenDevice()->TypefaceSupport(typefaceSupport, i);
+ S60->screenDevice()->TypefaceSupport(typefaceSupport, i);
CFont *font; // We have to get a font instance in order to know all the details
TFontSpec fontSpec(typefaceSupport.iTypeface.iName, 11);
- if (QS60Data::screenDevice()->GetNearestFontInPixels(font, fontSpec) != KErrNone)
+ if (S60->screenDevice()->GetNearestFontInPixels(font, fontSpec) != KErrNone)
continue;
QScopedPointer<CFont, QSymbianFontDatabaseExtrasImplementation::CFontFromScreenDeviceReleaser> sFont(font);
if (font->TypeUid() == KCFbsFontUid) {
diff --git a/src/gui/text/qfontengine_s60.cpp b/src/gui/text/qfontengine_s60.cpp
index 925b3bf..f691413 100644
--- a/src/gui/text/qfontengine_s60.cpp
+++ b/src/gui/text/qfontengine_s60.cpp
@@ -66,7 +66,7 @@ QSymbianTypeFaceExtras::QSymbianTypeFaceExtras(CFont* cFont, COpenFont *openFont
QSymbianTypeFaceExtras::~QSymbianTypeFaceExtras()
{
- QS60Data::screenDevice()->ReleaseFont(m_cFont);
+ S60->screenDevice()->ReleaseFont(m_cFont);
}
QByteArray QSymbianTypeFaceExtras::getSfntTable(uint tag) const
diff --git a/src/network/socket/qlocalserver_p.h b/src/network/socket/qlocalserver_p.h
index feaaae0..4f92b64 100644
--- a/src/network/socket/qlocalserver_p.h
+++ b/src/network/socket/qlocalserver_p.h
@@ -99,6 +99,7 @@ public:
struct Listener {
HANDLE handle;
OVERLAPPED overlapped;
+ bool connected;
};
void setError(const QString &function);
diff --git a/src/network/socket/qlocalserver_win.cpp b/src/network/socket/qlocalserver_win.cpp
index 07baf1e..61220e4 100644
--- a/src/network/socket/qlocalserver_win.cpp
+++ b/src/network/socket/qlocalserver_win.cpp
@@ -85,8 +85,10 @@ bool QLocalServerPrivate::addListener()
if (!ConnectNamedPipe(listener.handle, &listener.overlapped)) {
switch (GetLastError()) {
case ERROR_IO_PENDING:
+ listener.connected = false;
break;
case ERROR_PIPE_CONNECTED:
+ listener.connected = true;
SetEvent(eventHandle);
break;
default:
@@ -155,7 +157,9 @@ void QLocalServerPrivate::_q_onNewConnection()
// a client connection first, so there is no way around polling all of them.
for (int i = 0; i < listeners.size(); ) {
HANDLE handle = listeners[i].handle;
- if (GetOverlappedResult(handle, &listeners[i].overlapped, &dummy, FALSE)) {
+ if (listeners[i].connected
+ || GetOverlappedResult(handle, &listeners[i].overlapped, &dummy, FALSE))
+ {
listeners.removeAt(i);
addListener();
diff --git a/src/network/socket/qlocalsocket_p.h b/src/network/socket/qlocalsocket_p.h
index 0f1c23c..57ca3c2 100644
--- a/src/network/socket/qlocalsocket_p.h
+++ b/src/network/socket/qlocalsocket_p.h
@@ -135,7 +135,7 @@ public:
void _q_canWrite();
void _q_pipeClosed();
void _q_emitReadyRead();
- DWORD bytesAvailable();
+ DWORD checkPipeState();
void startAsyncRead();
bool completeAsyncRead();
void checkReadyRead();
diff --git a/src/network/socket/qlocalsocket_win.cpp b/src/network/socket/qlocalsocket_win.cpp
index 5f46ecb..2223ebe 100644
--- a/src/network/socket/qlocalsocket_win.cpp
+++ b/src/network/socket/qlocalsocket_win.cpp
@@ -192,6 +192,9 @@ qint64 QLocalSocket::readData(char *data, qint64 maxSize)
{
Q_D(QLocalSocket);
+ if (d->pipeClosed && d->actualReadBufferSize == 0)
+ return -1; // signal EOF
+
qint64 readSoFar;
// If startAsyncRead() read data, copy it to its destination.
if (maxSize == 1 && d->actualReadBufferSize > 0) {
@@ -213,10 +216,8 @@ qint64 QLocalSocket::readData(char *data, qint64 maxSize)
}
if (d->pipeClosed) {
- if (readSoFar == 0) {
+ if (d->actualReadBufferSize == 0)
QTimer::singleShot(0, this, SLOT(_q_pipeClosed()));
- return -1; // signal EOF
- }
} else {
if (!d->readSequenceStarted)
d->startAsyncRead();
@@ -250,7 +251,10 @@ void QLocalSocketPrivate::checkReadyRead()
void QLocalSocketPrivate::startAsyncRead()
{
do {
- DWORD bytesToRead = bytesAvailable();
+ DWORD bytesToRead = checkPipeState();
+ if (pipeClosed)
+ return;
+
if (bytesToRead == 0) {
// There are no bytes in the pipe but we need to
// start the overlapped read with some buffer size.
@@ -333,9 +337,11 @@ void QLocalSocket::abort()
}
/*!
- The number of bytes available from the pipe
- */
-DWORD QLocalSocketPrivate::bytesAvailable()
+ \internal
+ Returns the number of available bytes in the pipe.
+ Sets QLocalSocketPrivate::pipeClosed to true if the connection is broken.
+ */
+DWORD QLocalSocketPrivate::checkPipeState()
{
Q_Q(QLocalSocket);
DWORD bytes;
@@ -345,7 +351,8 @@ DWORD QLocalSocketPrivate::bytesAvailable()
if (!pipeClosed) {
pipeClosed = true;
emit q->readChannelFinished();
- QTimer::singleShot(0, q, SLOT(_q_pipeClosed()));
+ if (actualReadBufferSize == 0)
+ QTimer::singleShot(0, q, SLOT(_q_pipeClosed()));
}
}
return 0;
@@ -529,7 +536,7 @@ bool QLocalSocket::waitForDisconnected(int msecs)
}
QIncrementalSleepTimer timer(msecs);
forever {
- d->bytesAvailable(); // to check if PeekNamedPipe fails
+ d->checkPipeState();
if (d->pipeClosed)
close();
if (state() == UnconnectedState)
diff --git a/tests/auto/qlocalsocket/example/client/client.pro b/tests/auto/qlocalsocket/example/client/client.pro
index eb7e6e6..84f20d6 100644
--- a/tests/auto/qlocalsocket/example/client/client.pro
+++ b/tests/auto/qlocalsocket/example/client/client.pro
@@ -1,14 +1,8 @@
-######################################################################
-# Automatically generated by qmake (2.01a) Wed Jun 6 17:07:12 2007
-######################################################################
-
TEMPLATE = app
TARGET =
DEPENDPATH += .
INCLUDEPATH += .
CONFIG += console
-include(../../src/src.pri)
-# Input
QT = core network
SOURCES += main.cpp
diff --git a/tests/auto/qlocalsocket/example/server/server.pro b/tests/auto/qlocalsocket/example/server/server.pro
index 438462d..bfd14d2 100644
--- a/tests/auto/qlocalsocket/example/server/server.pro
+++ b/tests/auto/qlocalsocket/example/server/server.pro
@@ -1,7 +1,3 @@
-######################################################################
-# Automatically generated by qmake (2.01a) Wed Jun 6 15:16:48 2007
-######################################################################
-
TEMPLATE = app
TARGET =
DEPENDPATH += .
@@ -11,8 +7,6 @@ CONFIG += console
QT = core network
-include(../../src/src.pri)
-
# Input
SOURCES += main.cpp
diff --git a/tests/auto/qlocalsocket/tst_qlocalsocket.cpp b/tests/auto/qlocalsocket/tst_qlocalsocket.cpp
index 44f3c12..d2cba6e 100644
--- a/tests/auto/qlocalsocket/tst_qlocalsocket.cpp
+++ b/tests/auto/qlocalsocket/tst_qlocalsocket.cpp
@@ -683,25 +683,11 @@ public:
QString testLine = "test";
LocalSocket socket;
QSignalSpy spyReadyRead(&socket, SIGNAL(readyRead()));
- int tries = 0;
- do {
- socket.connectToServer("qlocalsocket_threadtest");
- if (socket.error() != QLocalSocket::ServerNotFoundError
- && socket.error() != QLocalSocket::ConnectionRefusedError)
- break;
- QTest::qWait(100);
- ++tries;
- } while ((socket.error() == QLocalSocket::ServerNotFoundError
- || socket.error() == QLocalSocket::ConnectionRefusedError)
- && tries < 1000);
- if (tries == 0 && socket.state() != QLocalSocket::ConnectedState) {
- QVERIFY(socket.waitForConnected(7000));
- QVERIFY(socket.state() == QLocalSocket::ConnectedState);
- }
+ socket.connectToServer("qlocalsocket_threadtest");
+ QVERIFY(socket.waitForConnected(1000));
// We should *not* have this signal yet!
- if (tries == 0)
- QCOMPARE(spyReadyRead.count(), 0);
+ QCOMPARE(spyReadyRead.count(), 0);
socket.waitForReadyRead();
QCOMPARE(spyReadyRead.count(), 1);
QTextStream in(&socket);
@@ -715,6 +701,8 @@ class Server : public QThread
public:
int clients;
+ QMutex mutex;
+ QWaitCondition wc;
void run()
{
QString testLine = "test";
@@ -722,6 +710,9 @@ public:
server.setMaxPendingConnections(10);
QVERIFY2(server.listen("qlocalsocket_threadtest"),
server.errorString().toLatin1().constData());
+ mutex.lock();
+ wc.wakeAll();
+ mutex.unlock();
int done = clients;
while (done > 0) {
bool timedOut = true;
@@ -746,14 +737,9 @@ void tst_QLocalSocket::threadedConnection_data()
QTest::addColumn<int>("threads");
QTest::newRow("1 client") << 1;
QTest::newRow("2 clients") << 2;
-#ifdef Q_OS_WINCE
- QTest::newRow("4 clients") << 4;
-#endif
-#ifndef Q_OS_WIN
QTest::newRow("5 clients") << 5;
- QTest::newRow("10 clients") << 10;
-#endif
#ifndef Q_OS_WINCE
+ QTest::newRow("10 clients") << 10;
QTest::newRow("20 clients") << 20;
#endif
}
@@ -770,7 +756,9 @@ void tst_QLocalSocket::threadedConnection()
server.setStackSize(0x14000);
#endif
server.clients = threads;
+ server.mutex.lock();
server.start();
+ server.wc.wait(&server.mutex);
QList<Client*> clients;
for (int i = 0; i < threads; ++i) {
@@ -784,9 +772,7 @@ void tst_QLocalSocket::threadedConnection()
server.wait();
while (!clients.isEmpty()) {
QVERIFY(clients.first()->wait(3000));
- Client *client =clients.takeFirst();
- client->terminate();
- delete client;
+ delete clients.takeFirst();
}
}
@@ -994,6 +980,7 @@ void tst_QLocalSocket::writeToClientAndDisconnect()
QLocalServer server;
QLocalSocket client;
+ QSignalSpy readChannelFinishedSpy(&client, SIGNAL(readChannelFinished()));
QVERIFY(server.listen("writeAndDisconnectServer"));
client.connectToServer("writeAndDisconnectServer");
@@ -1006,10 +993,19 @@ void tst_QLocalSocket::writeToClientAndDisconnect()
memset(buffer, 0, sizeof(buffer));
QCOMPARE(clientSocket->write(buffer, sizeof(buffer)), (qint64)sizeof(buffer));
clientSocket->waitForBytesWritten();
- clientSocket->disconnectFromServer();
- QVERIFY(client.waitForReadyRead());
+ clientSocket->close();
+ server.close();
+
+ // Wait for the client to notice the broken connection.
+ int timeout = 5000;
+ do {
+ const int timestep = 100;
+ QTest::qWait(timestep);
+ timeout -= timestep;
+ } while (!readChannelFinishedSpy.count() && timeout > 0);
+
+ QCOMPARE(readChannelFinishedSpy.count(), 1);
QCOMPARE(client.read(buffer, sizeof(buffer)), (qint64)sizeof(buffer));
- QVERIFY(client.waitForDisconnected());
QCOMPARE(client.state(), QLocalSocket::UnconnectedState);
}
diff --git a/tests/auto/qtextboundaryfinder/tst_qtextboundaryfinder.cpp b/tests/auto/qtextboundaryfinder/tst_qtextboundaryfinder.cpp
index c60af5e..a562fbe 100644
--- a/tests/auto/qtextboundaryfinder/tst_qtextboundaryfinder.cpp
+++ b/tests/auto/qtextboundaryfinder/tst_qtextboundaryfinder.cpp
@@ -71,6 +71,10 @@ private slots:
void isAtWordStart();
void fastConstructor();
void isAtBoundaryLine();
+ void toNextBoundary_data();
+ void toNextBoundary();
+ void toPreviousBoundary_data();
+ void toPreviousBoundary();
};
tst_QTextBoundaryFinder::tst_QTextBoundaryFinder()
@@ -292,25 +296,120 @@ void tst_QTextBoundaryFinder::fastConstructor()
void tst_QTextBoundaryFinder::isAtBoundaryLine()
{
- // idx 0 1 2 3 4 5
- // break? - - - + - +
+ // idx 0 1 2 3 4 5 6
+ // break? - - - - + - +
QChar s[] = { 0x0061, 0x00AD, 0x0062, 0x0009, 0x0063, 0x0064 };
QString text(s, sizeof(s)/sizeof(s[0]));
- qDebug() << "text = " << text << ", length = " << text.length();
+// qDebug() << "text = " << text << ", length = " << text.length();
QTextBoundaryFinder finder(QTextBoundaryFinder::Line, text.constData(), text.length(), /*buffer*/0, /*buffer size*/0);
finder.setPosition(0);
- QVERIFY(!finder.isAtBoundary());
+ QVERIFY(finder.isAtBoundary());
finder.setPosition(1);
QVERIFY(!finder.isAtBoundary());
finder.setPosition(2);
QVERIFY(!finder.isAtBoundary());
finder.setPosition(3);
- QVERIFY(finder.isAtBoundary());
- finder.setPosition(4);
QVERIFY(!finder.isAtBoundary());
+ finder.setPosition(4);
+ QVERIFY(finder.isAtBoundary());
finder.setPosition(5);
+ QVERIFY(!finder.isAtBoundary());
+ finder.setPosition(6);
QVERIFY(finder.isAtBoundary());
}
+Q_DECLARE_METATYPE(QList<int>)
+
+void tst_QTextBoundaryFinder::toNextBoundary_data()
+{
+ QTest::addColumn<QString>("text");
+ QTest::addColumn<int>("type");
+ QTest::addColumn< QList<int> >("boundaries");
+
+ QList<int> boundaries;
+ boundaries << 0 << 3 << 4 << 7 << 8 << 11 << 12 << 13 << 16 << 17 << 20 << 21 << 24 << 25;
+ QTest::newRow("Line") << QString("Aaa bbb ccc. Ddd eee fff.") << int(QTextBoundaryFinder::Word) \
+ << boundaries;
+
+ boundaries.clear();
+ boundaries << 0 << 13 << 25;
+ QTest::newRow("Line") << QString("Aaa bbb ccc. Ddd eee fff.") << int(QTextBoundaryFinder::Sentence) \
+ << boundaries;
+
+ boundaries.clear();
+ boundaries << 0 << 4 << 8 << 13 << 17 << 21 << 25;
+ QTest::newRow("Line") << QString("Aaa bbb ccc. Ddd eee fff.") << int(QTextBoundaryFinder::Line) \
+ << boundaries;
+
+ boundaries.clear();
+ boundaries << 0 << 5 << 9 << 15 << 17 << 21 << 28;
+ QTest::newRow("Line") << QString::fromUtf8("Diga-nos qualé a sua opinião") << int(QTextBoundaryFinder::Line)
+ << boundaries;
+
+}
+
+void tst_QTextBoundaryFinder::toNextBoundary()
+{
+ QFETCH(QString, text);
+ QFETCH(int, type);
+ QFETCH(QList<int>, boundaries);
+
+ QList<int> foundBoundaries;
+ QTextBoundaryFinder boundaryFinder(QTextBoundaryFinder::BoundaryType(type), text);
+ boundaryFinder.toStart();
+ for(int next = 0; next != -1; next = boundaryFinder.toNextBoundary())
+ foundBoundaries << next;
+ QCOMPARE(boundaries, foundBoundaries);
+}
+
+void tst_QTextBoundaryFinder::toPreviousBoundary_data()
+{
+ QTest::addColumn<QString>("text");
+ QTest::addColumn<int>("type");
+ QTest::addColumn< QList<int> >("boundaries");
+
+ QList<int> boundaries;
+ boundaries << 25 << 24 << 21 << 20 << 17 << 16 << 13 << 12 << 11 << 8 << 7 << 4 << 3 << 0;
+ QTest::newRow("Line") << QString("Aaa bbb ccc. Ddd eee fff.") << int(QTextBoundaryFinder::Word)
+ << boundaries;
+
+ boundaries.clear();
+ boundaries << 25 << 13 << 0;
+ QTest::newRow("Line") << QString("Aaa bbb ccc. Ddd eee fff.") << int(QTextBoundaryFinder::Sentence)
+ << boundaries;
+
+ boundaries.clear();
+ boundaries << 25 << 21 << 17 << 13 << 8 << 4 << 0;
+ QTest::newRow("Line") << QString("Aaa bbb ccc. Ddd eee fff.") << int(QTextBoundaryFinder::Line)
+ << boundaries;
+
+ boundaries.clear();
+ boundaries << 28 << 21 << 17 << 15 << 9 << 5 << 0;
+ QTest::newRow("Line") << QString::fromUtf8("Diga-nos qualé a sua opinião") << int(QTextBoundaryFinder::Line)
+ << boundaries;
+
+}
+
+void tst_QTextBoundaryFinder::toPreviousBoundary()
+{
+ QFETCH(QString, text);
+ QFETCH(int, type);
+ QFETCH(QList<int>, boundaries);
+
+ QList<int> foundBoundaries;
+ QTextBoundaryFinder boundaryFinder(QTextBoundaryFinder::BoundaryType(type), text);
+ boundaryFinder.toEnd();
+ for (int previous = boundaryFinder.position();
+ previous != -1;
+ previous = boundaryFinder.toPreviousBoundary())
+ {
+ foundBoundaries << previous;
+ }
+ QCOMPARE(boundaries, foundBoundaries);
+}
+
+
+
+
QTEST_MAIN(tst_QTextBoundaryFinder)
#include "tst_qtextboundaryfinder.moc"