From e6b629f3ebc1d530218f01a735275e56bf474a18 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Tue, 16 Feb 2010 18:21:55 +0100 Subject: add QString(const QChar *) c'tor to complement the QString(const QChar *, int) one, which unfortunately clamps sizes below zero to zero instead of computing the length itself instead. Reviewed-by: denis Reviewed-by: joao --- src/corelib/tools/qstring.cpp | 36 +++++++++++++++++++++++++++++++++++- src/corelib/tools/qstring.h | 3 ++- 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp index dec59b7..f85d794 100644 --- a/src/corelib/tools/qstring.cpp +++ b/src/corelib/tools/qstring.cpp @@ -989,6 +989,40 @@ QString::QString(const QChar *unicode, int size) } } +/*! + \since 4.7 + + Constructs a string initialized with the characters of the QChar array + \a unicode, which must be terminated with a 0. + + QString makes a deep copy of the string data. The unicode data is copied as + is and the Byte Order Mark is preserved if present. +*/ +QString::QString(const QChar *unicode) +{ + if (!unicode) { + d = &shared_null; + d->ref.ref(); + } else { + int size = 0; + while (unicode[size] != 0) + ++size; + if (!size) { + d = &shared_empty; + d->ref.ref(); + } else { + d = (Data*) qMalloc(sizeof(Data)+size*sizeof(QChar)); + Q_CHECK_PTR(d); + d->ref = 1; + d->alloc = d->size = size; + d->clean = d->asciiCache = d->simpletext = d->righttoleft = d->capacity = 0; + d->data = d->array; + memcpy(d->array, unicode, size * sizeof(QChar)); + d->array[size] = '\0'; + } + } +} + /*! Constructs a string of the given \a size with every character set @@ -3867,7 +3901,7 @@ QString QString::fromUtf8(const char *str, int size) host byte order is assumed. This function is comparatively slow. - Use QString(const ushort *, int) if possible. + Use QString(const ushort *, int) or QString(const ushort *) if possible. QString makes a deep copy of the Unicode data. diff --git a/src/corelib/tools/qstring.h b/src/corelib/tools/qstring.h index 702a21a..8de3c7d 100644 --- a/src/corelib/tools/qstring.h +++ b/src/corelib/tools/qstring.h @@ -91,7 +91,8 @@ class Q_CORE_EXPORT QString { public: inline QString(); - QString(const QChar *unicode, int size); + QString(const QChar *unicode, int size); // Qt5: don't cap size < 0 + explicit QString(const QChar *unicode); // Qt5: merge with the above QString(QChar c); QString(int size, QChar c); inline QString(const QLatin1String &latin1); -- cgit v0.12 From d590fc729e3afaedf181da58f8b685d7597040da Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Tue, 16 Feb 2010 18:23:18 +0100 Subject: optimization: get rid of QString::fromUtf16() usage, part 2 QString::fromUtf16() is slow - it does a BOM check and optionally byte swapping, which is utterly irrelevant when converting internal data structures which are raw utf16 in host byte order. so replace it with QString::fromUnicode() where possible (which seems to be everywhere). the reasoning is the same as in commit e0fda52f, so not getting further reviews. Reviewed-by: denis Reviewed-by: joao --- src/3rdparty/phonon/ds9/mediagraph.cpp | 12 ++++++------ src/3rdparty/phonon/waveout/mediaobject.cpp | 2 +- src/corelib/io/qprocess_symbian.cpp | 2 +- src/multimedia/audio/qaudiodeviceinfo_win32_p.cpp | 8 ++++---- src/multimedia/audio/qaudioinput_win32_p.cpp | 2 +- src/multimedia/audio/qaudiooutput_win32_p.cpp | 2 +- src/sql/drivers/db2/qsql_db2.cpp | 4 ++-- src/sql/drivers/oci/qsql_oci.cpp | 15 +++++++-------- src/sql/drivers/odbc/qsql_odbc.cpp | 2 +- src/sql/drivers/sqlite/qsql_sqlite.cpp | 10 +++++----- 10 files changed, 29 insertions(+), 30 deletions(-) diff --git a/src/3rdparty/phonon/ds9/mediagraph.cpp b/src/3rdparty/phonon/ds9/mediagraph.cpp index a467dd7..3e7a68b 100644 --- a/src/3rdparty/phonon/ds9/mediagraph.cpp +++ b/src/3rdparty/phonon/ds9/mediagraph.cpp @@ -379,7 +379,7 @@ namespace Phonon FILTER_INFO info; filter->QueryFilterInfo(&info); #ifdef GRAPH_DEBUG - qDebug() << "removeFilter" << QString::fromUtf16(info.achName); + qDebug() << "removeFilter" << QString((const QChar *)info.achName); #endif if (info.pGraph) { info.pGraph->Release(); @@ -875,7 +875,7 @@ namespace Phonon { FILTER_INFO info; filter->QueryFilterInfo(&info); - qDebug() << Q_FUNC_INFO << QString::fromUtf16(info.achName); + qDebug() << Q_FUNC_INFO << QString((const QChar *)info.achName); if (info.pGraph) { info.pGraph->Release(); } @@ -921,7 +921,7 @@ namespace Phonon { FILTER_INFO info; filter->QueryFilterInfo(&info); - qDebug() << "found a decoder filter" << QString::fromUtf16(info.achName); + qDebug() << "found a decoder filter" << QString((const QChar *)info.achName); if (info.pGraph) { info.pGraph->Release(); } @@ -937,7 +937,7 @@ namespace Phonon { FILTER_INFO info; filter->QueryFilterInfo(&info); - qDebug() << Q_FUNC_INFO << QString::fromUtf16(info.achName); + qDebug() << Q_FUNC_INFO << QString((const QChar *)info.achName); if (info.pGraph) { info.pGraph->Release(); } @@ -956,7 +956,7 @@ namespace Phonon { FILTER_INFO info; filter->QueryFilterInfo(&info); - qDebug() << Q_FUNC_INFO << QString::fromUtf16(info.achName); + qDebug() << Q_FUNC_INFO << QString((const QChar *)info.achName); if (info.pGraph) { info.pGraph->Release(); } @@ -990,7 +990,7 @@ namespace Phonon { FILTER_INFO info; filter->QueryFilterInfo(&info); - qDebug() << "found a demuxer filter" << QString::fromUtf16(info.achName); + qDebug() << "found a demuxer filter" << QString((const QChar *)info.achName); if (info.pGraph) { info.pGraph->Release(); } diff --git a/src/3rdparty/phonon/waveout/mediaobject.cpp b/src/3rdparty/phonon/waveout/mediaobject.cpp index db71942..08af4ee 100644 --- a/src/3rdparty/phonon/waveout/mediaobject.cpp +++ b/src/3rdparty/phonon/waveout/mediaobject.cpp @@ -50,7 +50,7 @@ namespace Phonon { ushort b[256]; waveOutGetErrorText(error, (LPWSTR)b, 256); - return QString::fromUtf16(b); + return QString((const QChar *)b); } class WorkerThread : public QThread diff --git a/src/corelib/io/qprocess_symbian.cpp b/src/corelib/io/qprocess_symbian.cpp index 75cde51..07d10ad 100644 --- a/src/corelib/io/qprocess_symbian.cpp +++ b/src/corelib/io/qprocess_symbian.cpp @@ -1002,7 +1002,7 @@ bool QProcessPrivate::waitForDeadChild() TExitCategoryName catName = symbianProcess->ExitCategory(); qDebug() << "QProcessPrivate::waitForDeadChild() dead with exitCode" << exitCode << ", crashed:" << crashed - << ", category:" << QString::fromUtf16(catName.Ptr()); + << ", category:" << QString((const QChar *)catName.Ptr()); #endif } else { QPROCESS_DEBUG_PRINT("QProcessPrivate::waitForDeadChild() not dead!"); diff --git a/src/multimedia/audio/qaudiodeviceinfo_win32_p.cpp b/src/multimedia/audio/qaudiodeviceinfo_win32_p.cpp index 955a880..67dc90c 100644 --- a/src/multimedia/audio/qaudiodeviceinfo_win32_p.cpp +++ b/src/multimedia/audio/qaudiodeviceinfo_win32_p.cpp @@ -218,7 +218,7 @@ void QAudioDeviceInfoInternal::updateLists() for(i=0;i QAudioDeviceInfoInternal::availableDevices(QAudio::Mode mode) for(i=0;i QAudioDeviceInfoInternal::availableDevices(QAudio::Mode mode) for(i=0;i &storage) value = qMakeDate(storage.takeFirst()); break; case QVariant::String: - value = QString::fromUtf16( - reinterpret_cast(storage.takeFirst().constData())); + value = QString( + reinterpret_cast(storage.takeFirst().constData())); break; default: break; //nothing @@ -454,7 +454,7 @@ QString qOraWarn(OCIError *err, int *errorCode) OCI_HTYPE_ERROR); if (errorCode) *errorCode = errcode; - return QString::fromUtf16(reinterpret_cast(errbuf)); + return QString(reinterpret_cast(errbuf)); } void qOraWarning(const char* msg, OCIError *err) @@ -989,8 +989,7 @@ int QOCICols::readPiecewise(QVector &values, int index) } else { if (isStringField) { QString str = values.at(fieldNum + index).toString(); - str += QString::fromUtf16(reinterpret_cast(col), - chunkSize / 2); + str += QString(reinterpret_cast(col), chunkSize / 2); values[fieldNum + index] = str; fieldInf[fieldNum].ind = 0; } else { @@ -1457,7 +1456,7 @@ bool QOCICols::execBatch(QOCIResultPrivate *d, QVector &boundValues, b break; case SQLT_STR: - (*list)[r] = QString::fromUtf16(reinterpret_cast(data + (*list)[r] = QString(reinterpret_cast(data + r * columns[i].maxLen)); break; @@ -1608,7 +1607,7 @@ void QOCICols::getValues(QVector &v, int index) } // else fall through case QVariant::String: - v[index + i] = QString::fromUtf16(reinterpret_cast(fld.data)); + v[index + i] = QString(reinterpret_cast(fld.data)); break; case QVariant::ByteArray: if (fld.len > 0) @@ -2102,7 +2101,7 @@ bool QOCIDriver::open(const QString & db, qWarning("QOCIDriver::open: could not get Oracle server version."); } else { QString versionStr; - versionStr = QString::fromUtf16(reinterpret_cast(vertxt)); + versionStr = QString(reinterpret_cast(vertxt)); QRegExp vers(QLatin1String("([0-9]+)\\.[0-9\\.]+[0-9]")); if (vers.indexIn(versionStr) >= 0) d->serverVersion = vers.cap(1).toInt(); diff --git a/src/sql/drivers/odbc/qsql_odbc.cpp b/src/sql/drivers/odbc/qsql_odbc.cpp index 18bc743..fab3ab3 100644 --- a/src/sql/drivers/odbc/qsql_odbc.cpp +++ b/src/sql/drivers/odbc/qsql_odbc.cpp @@ -1558,7 +1558,7 @@ bool QODBCResult::exec() case QVariant::String: if (d->unicode) { if (bindValueType(i) & QSql::Out) - values[i] = QString::fromUtf16((ushort*)tmpStorage.takeFirst().constData()); + values[i] = QString((QChar *)tmpStorage.takeFirst().constData()); break; } // fall through diff --git a/src/sql/drivers/sqlite/qsql_sqlite.cpp b/src/sql/drivers/sqlite/qsql_sqlite.cpp index d3be304..24dcad9 100644 --- a/src/sql/drivers/sqlite/qsql_sqlite.cpp +++ b/src/sql/drivers/sqlite/qsql_sqlite.cpp @@ -95,7 +95,7 @@ static QSqlError qMakeError(sqlite3 *access, const QString &descr, QSqlError::Er int errorCode = -1) { return QSqlError(descr, - QString::fromUtf16(static_cast(sqlite3_errmsg16(access))), + QString(reinterpret_cast(sqlite3_errmsg16(access))), type, errorCode); } @@ -162,13 +162,13 @@ void QSQLiteResultPrivate::initColumns(bool emptyResultset) q->init(nCols); for (int i = 0; i < nCols; ++i) { - QString colName = QString::fromUtf16( - static_cast(sqlite3_column_name16(stmt, i)) + QString colName = QString(reinterpret_cast( + sqlite3_column_name16(stmt, i)) ).remove(QLatin1Char('"')); // must use typeName for resolving the type to match QSqliteDriver::record - QString typeName = QString::fromUtf16( - static_cast(sqlite3_column_decltype16(stmt, i))); + QString typeName = QString(reinterpret_cast( + sqlite3_column_decltype16(stmt, i))); int dotIdx = colName.lastIndexOf(QLatin1Char('.')); QSqlField fld(colName.mid(dotIdx == -1 ? 0 : dotIdx + 1), qGetColumnType(typeName)); -- cgit v0.12 From 7134f8b25a7a69960767280f9c23981b08d8e68b Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Thu, 28 Jan 2010 21:02:34 +0100 Subject: add QList::reserve() while this reserves memory "only" for the pointer list, this still amounts to 100% of the re-allocs for small simple types. for big/complex/static types the gain is lower, but still. Reviewed-by: Denis Reviewed-by: Joao --- src/corelib/tools/qlist.cpp | 39 ++++++++++++++++++++++++++++++++++----- src/corelib/tools/qlist.h | 26 +++++++++++++++++++++++--- 2 files changed, 57 insertions(+), 8 deletions(-) diff --git a/src/corelib/tools/qlist.cpp b/src/corelib/tools/qlist.cpp index ce62016..ac0dc46 100644 --- a/src/corelib/tools/qlist.cpp +++ b/src/corelib/tools/qlist.cpp @@ -125,22 +125,23 @@ QListData::Data *QListData::detach2() } /*! - * Detaches the QListData by reallocating new memory. + * Detaches the QListData by allocating new memory for a list which possibly + * has a different size than the copied one. * Returns the old (shared) data, it is up to the caller to deref() and free() * For the new data node_copy needs to be called. * * \internal */ -QListData::Data *QListData::detach3() +QListData::Data *QListData::detach(int alloc) { Data *x = d; - Data* t = static_cast(qMalloc(DataHeaderSize + x->alloc * sizeof(void *))); + Data* t = static_cast(qMalloc(DataHeaderSize + alloc * sizeof(void *))); Q_CHECK_PTR(t); t->ref = 1; t->sharable = true; - t->alloc = x->alloc; - if (!t->alloc) { + t->alloc = alloc; + if (!alloc) { t->begin = 0; t->end = 0; } else { @@ -152,6 +153,21 @@ QListData::Data *QListData::detach3() return x; } +/*! + * Detaches the QListData by reallocating new memory. + * Returns the old (shared) data, it is up to the caller to deref() and free() + * For the new data node_copy needs to be called. + * + * \internal + */ +#if QT_VERSION >= 0x050000 +# error "Remove QListData::detach3(), it is only required for binary compatibility for 4.5.x to 4.6.x" +#endif +QListData::Data *QListData::detach3() +{ + return detach(d->alloc); +} + void QListData::realloc(int alloc) { Q_ASSERT(d->ref == 1); @@ -647,6 +663,19 @@ void **QListData::erase(void **xi) Same as at(). */ +/*! \fn QList::reserve(int alloc) + + Reserve space for \a alloc elements. + + If \a alloc is smaller than the current size of the list, nothing will happen. + + Use this function to avoid repetetive reallocation of QList's internal + data if you can predict how many elements will be appended. + Note that the reservation applies only to the internal pointer array. + + \since 4.7 +*/ + /*! \fn void QList::append(const T &value) Inserts \a value at the end of the list. diff --git a/src/corelib/tools/qlist.h b/src/corelib/tools/qlist.h index 1d08c41..3b9eefa 100644 --- a/src/corelib/tools/qlist.h +++ b/src/corelib/tools/qlist.h @@ -72,9 +72,10 @@ struct Q_CORE_EXPORT QListData { }; enum { DataHeaderSize = sizeof(Data) - sizeof(void *) }; + Data *detach(int alloc); Data *detach(); // remove in 5.0 Data *detach2(); // remove in 5.0 - Data *detach3(); + Data *detach3(); // remove in 5.0 void realloc(int alloc); static Data shared_null; Data *d; @@ -140,6 +141,7 @@ public: const T &operator[](int i) const; T &operator[](int i); + void reserve(int size); void append(const T &t); void append(const QList &t); void prepend(const T &t); @@ -331,6 +333,7 @@ public: #endif private: + void detach_helper(int alloc); void detach_helper(); void free(QListData::Data *d); @@ -464,6 +467,17 @@ inline T QList::takeLast() { T t = last(); removeLast(); return t; } template +Q_OUTOFLINE_TEMPLATE void QList::reserve(int alloc) +{ + if (d->alloc < alloc) { + if (d->ref != 1) + detach_helper(alloc); + else + p.realloc(alloc); + } +} + +template Q_OUTOFLINE_TEMPLATE void QList::append(const T &t) { detach(); @@ -599,10 +613,10 @@ Q_OUTOFLINE_TEMPLATE T QList::value(int i, const T& defaultValue) const } template -Q_OUTOFLINE_TEMPLATE void QList::detach_helper() +Q_OUTOFLINE_TEMPLATE void QList::detach_helper(int alloc) { Node *n = reinterpret_cast(p.begin()); - QListData::Data *x = p.detach3(); + QListData::Data *x = p.detach(alloc); QT_TRY { node_copy(reinterpret_cast(p.begin()), reinterpret_cast(p.end()), n); } QT_CATCH(...) { @@ -616,6 +630,12 @@ Q_OUTOFLINE_TEMPLATE void QList::detach_helper() } template +Q_OUTOFLINE_TEMPLATE void QList::detach_helper() +{ + detach_helper(d->alloc); +} + +template Q_OUTOFLINE_TEMPLATE QList::~QList() { if (d && !d->ref.deref()) -- cgit v0.12 From 5723f1bcb538a5624cbed871c34507ff26285878 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Thu, 28 Jan 2010 21:05:21 +0100 Subject: optimization: use QList::reserve() in QSet::toList() Reviewed-by: Denis Reviewed-by: Joao --- src/corelib/tools/qset.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/corelib/tools/qset.h b/src/corelib/tools/qset.h index 6525880..9acbed4 100644 --- a/src/corelib/tools/qset.h +++ b/src/corelib/tools/qset.h @@ -292,6 +292,7 @@ template Q_OUTOFLINE_TEMPLATE QList QSet::toList() const { QList result; + result.reserve(size()); typename QSet::const_iterator i = constBegin(); while (i != constEnd()) { result.append(*i); -- cgit v0.12 From c03b21d272f617b037ad9d0ccaa2f442638bf302 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Thu, 28 Jan 2010 21:07:18 +0100 Subject: optimize QList::mid() instead of append()ing each element separately, reserve enough space and do a low-level node copy. obviously, the gain for small simple types is the biggest. Reviewed-by: joao Reviewed-by: denis --- src/corelib/tools/qlist.h | 15 ++++++++++++--- tests/auto/qlist/tst_qlist.cpp | 10 ++++++++++ 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/src/corelib/tools/qlist.h b/src/corelib/tools/qlist.h index 3b9eefa..8c75c98 100644 --- a/src/corelib/tools/qlist.h +++ b/src/corelib/tools/qlist.h @@ -589,11 +589,20 @@ Q_OUTOFLINE_TEMPLATE QList QList::mid(int pos, int alength) const alength = size() - pos; if (pos == 0 && alength == size()) return *this; - QList cpy; if (pos + alength > size()) alength = size() - pos; - for (int i = pos; i < pos + alength; ++i) - cpy += at(i); + QList cpy; + cpy.reserve(alength); + cpy.d->end = alength; + QT_TRY { + cpy.node_copy(reinterpret_cast(cpy.p.begin()), + reinterpret_cast(cpy.p.end()), + reinterpret_cast(p.begin() + pos)); + } QT_CATCH(...) { + // restore the old end + cpy.d->end = 0; + QT_RETHROW; + } return cpy; } diff --git a/tests/auto/qlist/tst_qlist.cpp b/tests/auto/qlist/tst_qlist.cpp index 59b2c7b..a590fca 100644 --- a/tests/auto/qlist/tst_qlist.cpp +++ b/tests/auto/qlist/tst_qlist.cpp @@ -60,6 +60,7 @@ private slots: void length() const; void lengthSignature() const; void append() const; + void mid() const; }; void tst_QList::length() const @@ -129,5 +130,14 @@ void tst_QList::append() const } +void tst_QList::mid() const +{ + QList list; + list << "foo" << "bar" << "baz" << "bak" << "buck" << "hello" << "kitty"; + + QCOMPARE(list.mid(3, 3), + QList() << "bak" << "buck" << "hello"); +} + QTEST_APPLESS_MAIN(tst_QList) #include "tst_qlist.moc" -- cgit v0.12 From 82027baa2c7705ae49300ce3ca0ac9eb4add2e96 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Tue, 16 Feb 2010 13:00:07 +0100 Subject: optimize qHash() some more on modern architectures, a longer data dependency chain is worse than a slightly bigger instruction. as it happens, the code is also clearer. would you have guessed that qHash() is only 28 bits wide? Reviewed-by: joao Reviewed-by: denis --- src/corelib/tools/qhash.cpp | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/src/corelib/tools/qhash.cpp b/src/corelib/tools/qhash.cpp index 285f4c9..85a8b63 100644 --- a/src/corelib/tools/qhash.cpp +++ b/src/corelib/tools/qhash.cpp @@ -64,13 +64,11 @@ QT_BEGIN_NAMESPACE static uint hash(const uchar *p, int n) { uint h = 0; - uint g; while (n--) { h = (h << 4) + *p++; - g = h & 0xf0000000; - h ^= g >> 23; - h &= ~g; + h ^= (h & 0xf0000000) >> 23; + h &= 0x0fffffff; } return h; } @@ -78,13 +76,11 @@ static uint hash(const uchar *p, int n) static uint hash(const QChar *p, int n) { uint h = 0; - uint g; while (n--) { h = (h << 4) + (*p++).unicode(); - g = h & 0xf0000000; - h ^= g >> 23; - h &= ~g; + h ^= (h & 0xf0000000) >> 23; + h &= 0x0fffffff; } return h; } -- cgit v0.12 From 5af4e7d0e44be7d35c38c439fa9fc42f54ccd09b Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Tue, 16 Feb 2010 15:37:44 +0100 Subject: avoid double reallocation in string-growing replace() case detach() followed by resize() is suboptimal, as it first creates an identically sized copy, and then a differently sized one. Reviewed-by: joao Reviewed-by: denis --- src/corelib/tools/qstring.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp index f85d794..cce313b 100644 --- a/src/corelib/tools/qstring.cpp +++ b/src/corelib/tools/qstring.cpp @@ -1800,13 +1800,14 @@ void QString::replace_helper(uint *indices, int nIndices, int blen, const QChar } QT_TRY { - detach(); if (blen == alen) { // replace in place + detach(); for (int i = 0; i < nIndices; ++i) memcpy(d->data + indices[i], afterBuffer, alen * sizeof(QChar)); } else if (alen < blen) { // replace from front + detach(); uint to = indices[0]; if (alen) memcpy(d->data+to, after, alen*sizeof(QChar)); -- cgit v0.12 From 02135be18f3c4b1d1525aff6dfe96c9c8521084d Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Tue, 16 Feb 2010 15:44:41 +0100 Subject: avoid double reallocations in appending operations operator+=() and co. would first detach, and then realloc if they found the reservation too small. in particular, appending anything to an empty list would trigger this double reallocation (first copy shared_null, then grow the copy). Reviewed-by: joao Reviewed-by: denis --- src/corelib/tools/qlist.cpp | 18 ++++++++++++++++++ src/corelib/tools/qlist.h | 28 ++++++++++++++++++++++++---- 2 files changed, 42 insertions(+), 4 deletions(-) diff --git a/src/corelib/tools/qlist.cpp b/src/corelib/tools/qlist.cpp index ac0dc46..a468c77 100644 --- a/src/corelib/tools/qlist.cpp +++ b/src/corelib/tools/qlist.cpp @@ -154,6 +154,19 @@ QListData::Data *QListData::detach(int alloc) } /*! + * Detaches the QListData by allocating new memory for a list which will be bigger + * than the copied one and is expected to grow further. + * Returns the old (shared) data, it is up to the caller to deref() and free() + * For the new data node_copy needs to be called. + * + * \internal + */ +QListData::Data *QListData::detach_grow(int alloc) +{ + return detach(grow(alloc)); +} + +/*! * Detaches the QListData by reallocating new memory. * Returns the old (shared) data, it is up to the caller to deref() and free() * For the new data node_copy needs to be called. @@ -596,6 +609,11 @@ void **QListData::erase(void **xi) \internal */ +/*! \fn void QList::detach_grow(int alloc) + + \internal +*/ + /*! \fn void QList::detachShared() \internal diff --git a/src/corelib/tools/qlist.h b/src/corelib/tools/qlist.h index 8c75c98..1edac03 100644 --- a/src/corelib/tools/qlist.h +++ b/src/corelib/tools/qlist.h @@ -73,6 +73,7 @@ struct Q_CORE_EXPORT QListData { enum { DataHeaderSize = sizeof(Data) - sizeof(void *) }; Data *detach(int alloc); + Data *detach_grow(int alloc); Data *detach(); // remove in 5.0 Data *detach2(); // remove in 5.0 Data *detach3(); // remove in 5.0 @@ -121,6 +122,7 @@ public: inline int size() const { return p.size(); } inline void detach() { if (d->ref != 1) detach_helper(); } + inline void detach_grow(int by) { if (d->ref != 1) detach_helper_grow(d->end - d->begin + by); } inline void detachShared() { @@ -333,6 +335,7 @@ public: #endif private: + void detach_helper_grow(int alloc); void detach_helper(int alloc); void detach_helper(); void free(QListData::Data *d); @@ -480,7 +483,7 @@ Q_OUTOFLINE_TEMPLATE void QList::reserve(int alloc) template Q_OUTOFLINE_TEMPLATE void QList::append(const T &t) { - detach(); + detach_grow(1); if (QTypeInfo::isLarge || QTypeInfo::isStatic) { Node *n = reinterpret_cast(p.append()); QT_TRY { @@ -504,7 +507,7 @@ Q_OUTOFLINE_TEMPLATE void QList::append(const T &t) template inline void QList::prepend(const T &t) { - detach(); + detach_grow(1); if (QTypeInfo::isLarge || QTypeInfo::isStatic) { Node *n = reinterpret_cast(p.prepend()); QT_TRY { @@ -528,7 +531,7 @@ inline void QList::prepend(const T &t) template inline void QList::insert(int i, const T &t) { - detach(); + detach_grow(1); if (QTypeInfo::isLarge || QTypeInfo::isStatic) { Node *n = reinterpret_cast(p.insert(i)); QT_TRY { @@ -622,6 +625,23 @@ Q_OUTOFLINE_TEMPLATE T QList::value(int i, const T& defaultValue) const } template +Q_OUTOFLINE_TEMPLATE void QList::detach_helper_grow(int alloc) +{ + Node *n = reinterpret_cast(p.begin()); + QListData::Data *x = p.detach_grow(alloc); + QT_TRY { + node_copy(reinterpret_cast(p.begin()), reinterpret_cast(p.end()), n); + } QT_CATCH(...) { + qFree(d); + d = x; + QT_RETHROW; + } + + if (!x->ref.deref()) + free(x); +} + +template Q_OUTOFLINE_TEMPLATE void QList::detach_helper(int alloc) { Node *n = reinterpret_cast(p.begin()); @@ -730,7 +750,7 @@ Q_OUTOFLINE_TEMPLATE typename QList::iterator QList::erase(typename QList< template Q_OUTOFLINE_TEMPLATE QList &QList::operator+=(const QList &l) { - detach(); + detach_grow(l.size()); Node *n = reinterpret_cast(p.append2(l.p)); QT_TRY{ node_copy(n, reinterpret_cast(p.end()), reinterpret_cast(l.p.begin())); -- cgit v0.12 From 4f9f068ccd2da8859eb0208455ac2a6ca494afdc Mon Sep 17 00:00:00 2001 From: kh1 Date: Wed, 17 Feb 2010 12:31:42 +0100 Subject: Fix broken Drag&Drop, reset and clear the model if we set new bookmarks. Reviewed-by: ck --- tools/assistant/tools/assistant/bookmarkmodel.cpp | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/tools/assistant/tools/assistant/bookmarkmodel.cpp b/tools/assistant/tools/assistant/bookmarkmodel.cpp index c785f16..f9c9980 100644 --- a/tools/assistant/tools/assistant/bookmarkmodel.cpp +++ b/tools/assistant/tools/assistant/bookmarkmodel.cpp @@ -79,6 +79,9 @@ BookmarkModel::bookmarks() const void BookmarkModel::setBookmarks(const QByteArray &bookmarks) { + beginResetModel(); + + delete rootItem; folderIcon = QApplication::style()->standardIcon(QStyle::SP_DirClosedIcon); bookmarkIcon = QIcon(QLatin1String(":/trolltech/assistant/images/bookmark.png")); @@ -115,6 +118,8 @@ BookmarkModel::setBookmarks(const QByteArray &bookmarks) setupCache(root); cache.insert(static_cast (root.internalPointer()), root); + + endResetModel(); } void @@ -220,9 +225,9 @@ BookmarkModel::flags(const QModelIndex &index) const if (m_editable) defaultFlags |= Qt::ItemIsEditable; - if (itemFromIndex(index) && index.data(UserRoleFolder).toBool() - && index.column() > 0) { - defaultFlags &= ~Qt::ItemIsEditable; + if (itemFromIndex(index) && index.data(UserRoleFolder).toBool()) { + if (index.column() > 0) + return defaultFlags &~ Qt::ItemIsEditable; return defaultFlags | Qt::ItemIsDropEnabled; } @@ -241,11 +246,13 @@ BookmarkModel::data(const QModelIndex &index, int role) const return QLatin1String(""); return item->data(index.column()); } break; + case Qt::DecorationRole: { if (index.column() == 0) return index.data(UserRoleFolder).toBool() ? folderIcon : bookmarkIcon; } break; + default:; return item->data(role); } -- cgit v0.12 From 4941c9b9a83a6ea5c07f470fb853d1111ce4c7b9 Mon Sep 17 00:00:00 2001 From: kh1 Date: Wed, 17 Feb 2010 13:19:11 +0100 Subject: Make sure the bookmarks menu updates on add/ remove as well. Reviewed-by: ck --- tools/assistant/tools/assistant/bookmarkmanager.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/tools/assistant/tools/assistant/bookmarkmanager.cpp b/tools/assistant/tools/assistant/bookmarkmanager.cpp index 8fba811..b73fbb5 100644 --- a/tools/assistant/tools/assistant/bookmarkmanager.cpp +++ b/tools/assistant/tools/assistant/bookmarkmanager.cpp @@ -187,6 +187,10 @@ BookmarkManager::BookmarkManager() connect(&HelpEngineWrapper::instance(), SIGNAL(setupFinished()), this, SLOT(setupFinished())); + connect(bookmarkModel, SIGNAL(rowsRemoved(QModelIndex, int, int)), this, + SLOT(refeshBookmarkMenu())); + connect(bookmarkModel, SIGNAL(rowsInserted(QModelIndex, int, int)), this, + SLOT(refeshBookmarkMenu())); connect(bookmarkModel, SIGNAL(dataChanged(QModelIndex, QModelIndex)), this, SLOT(refeshBookmarkMenu())); } @@ -323,10 +327,8 @@ void BookmarkManager::setupFinished() void BookmarkManager::addBookmark() { TRACE_OBJ - if (CentralWidget *widget = CentralWidget::instance()) { - showBookmarkDialog(widget->currentTitle(), - widget->currentSource().toString()); - } + if (CentralWidget *widget = CentralWidget::instance()) + addBookmark(widget->currentTitle(), widget->currentSource().toString()); } void BookmarkManager::removeBookmark() -- cgit v0.12 From 5c1bcbf309339f017415c851ad74e928ed709e6b Mon Sep 17 00:00:00 2001 From: kh1 Date: Wed, 17 Feb 2010 13:32:15 +0100 Subject: Move launch with external app in base class. Reviewed-by: ck --- tools/assistant/tools/assistant/centralwidget.cpp | 15 +++--- tools/assistant/tools/assistant/helpviewer.cpp | 45 +++++++++++++++- tools/assistant/tools/assistant/helpviewer.h | 4 ++ tools/assistant/tools/assistant/helpviewer_qtb.cpp | 62 +++++----------------- tools/assistant/tools/assistant/helpviewer_qtb.h | 2 - tools/assistant/tools/assistant/helpviewer_qwv.cpp | 57 ++++++-------------- 6 files changed, 82 insertions(+), 103 deletions(-) diff --git a/tools/assistant/tools/assistant/centralwidget.cpp b/tools/assistant/tools/assistant/centralwidget.cpp index dd91326..d0a6e56 100644 --- a/tools/assistant/tools/assistant/centralwidget.cpp +++ b/tools/assistant/tools/assistant/centralwidget.cpp @@ -310,7 +310,7 @@ void CentralWidget::setLastShownPages() { TRACE_OBJ HelpEngineWrapper &helpEngine = HelpEngineWrapper::instance(); - const QStringList lastShownPageList = helpEngine.lastShownPages(); + const QStringList &lastShownPageList = helpEngine.lastShownPages(); const int pageCount = lastShownPageList.count(); if (pageCount == 0) { if (usesDefaultCollection) @@ -514,15 +514,12 @@ void CentralWidget::setGlobalActions(const QList &actions) void CentralWidget::setSourceInNewTab(const QUrl &url, qreal zoom) { TRACE_OBJ - HelpViewer *viewer; - -#if defined(QT_NO_WEBKIT) - viewer = currentHelpViewer(); - if (viewer && viewer->launchedWithExternalApp(url)) - return; -#endif + if (HelpViewer *viewer = currentHelpViewer()) { + if (viewer->launchWithExternalApp(url)) + return; + } - viewer = new HelpViewer(this, zoom); + HelpViewer *viewer = new HelpViewer(this, zoom); viewer->installEventFilter(this); viewer->setSource(url); viewer->setFocus(Qt::OtherFocusReason); diff --git a/tools/assistant/tools/assistant/helpviewer.cpp b/tools/assistant/tools/assistant/helpviewer.cpp index 8597f6b..9b06400 100644 --- a/tools/assistant/tools/assistant/helpviewer.cpp +++ b/tools/assistant/tools/assistant/helpviewer.cpp @@ -39,13 +39,25 @@ ** ****************************************************************************/ #include "helpviewer.h" +#include "helpenginewrapper.h" #include "tracer.h" #include +#include +#include +#include #include +#include + QT_BEGIN_NAMESPACE +QString AbstractHelpViewer::AboutBlank = + QCoreApplication::translate("HelpViewer", "about:blank"); + +QString AbstractHelpViewer::LocalHelpFile = QLatin1String("qthelp://" + "com.trolltech.com.assistantinternal-1.0.0/assistant/assistant.html"); + QString AbstractHelpViewer::PageNotFoundMessage = QCoreApplication::translate("HelpViewer", "Error 404...


The page could not be found


'%1'" @@ -76,7 +88,38 @@ bool AbstractHelpViewer::canOpenPage(const QString &url) TRACE_OBJ return url.endsWith(QLatin1String(".html"), Qt::CaseInsensitive) || url.endsWith(QLatin1String(".htm"), Qt::CaseInsensitive) - || url == QLatin1String("blank"); + || url == QLatin1String("about:blank"); +} + +bool AbstractHelpViewer::launchWithExternalApp(const QUrl &url) +{ + TRACE_OBJ + if (isLocalUrl(url)) { + const HelpEngineWrapper &helpEngine = HelpEngineWrapper::instance(); + const QUrl &resolvedUrl = helpEngine.findFile(url); + if (!resolvedUrl.isValid()) + return false; + + const QString& path = resolvedUrl.path(); + if (!canOpenPage(path)) { + QTemporaryFile tmpTmpFile; + if (!tmpTmpFile.open()) + return false; + + const QString &extension = QFileInfo(path).completeSuffix(); + QFile actualTmpFile(tmpTmpFile.fileName() % QLatin1String(".") + % extension); + if (!actualTmpFile.open(QIODevice::ReadWrite | QIODevice::Truncate)) + return false; + + actualTmpFile.write(helpEngine.fileData(resolvedUrl)); + actualTmpFile.close(); + return QDesktopServices::openUrl(QUrl(actualTmpFile.fileName())); + } + } else if (url.scheme() == QLatin1String("http")) { + return QDesktopServices::openUrl(url); + } + return false; } QT_END_NAMESPACE diff --git a/tools/assistant/tools/assistant/helpviewer.h b/tools/assistant/tools/assistant/helpviewer.h index fe860fd..0bfe904 100644 --- a/tools/assistant/tools/assistant/helpviewer.h +++ b/tools/assistant/tools/assistant/helpviewer.h @@ -64,9 +64,13 @@ public: virtual void resetScale() = 0; virtual qreal scale() const = 0; + static QString AboutBlank; + static QString LocalHelpFile; static QString PageNotFoundMessage; + static bool isLocalUrl(const QUrl &url); static bool canOpenPage(const QString &url); + static bool launchWithExternalApp(const QUrl &url); }; QT_END_NAMESPACE diff --git a/tools/assistant/tools/assistant/helpviewer_qtb.cpp b/tools/assistant/tools/assistant/helpviewer_qtb.cpp index 3aafe67..b5af165 100644 --- a/tools/assistant/tools/assistant/helpviewer_qtb.cpp +++ b/tools/assistant/tools/assistant/helpviewer_qtb.cpp @@ -41,21 +41,17 @@ #if defined(QT_NO_WEBKIT) #include "helpviewer_qtb.h" -#include "helpviewer_qwv.h" #include "centralwidget.h" #include "helpenginewrapper.h" #include "tracer.h" -#include #include #include #include #include #include -#include -#include QT_BEGIN_NAMESPACE @@ -136,62 +132,28 @@ void HelpViewer::resetScale() void HelpViewer::setSource(const QUrl &url) { TRACE_OBJ - bool help = url.toString() == QLatin1String("help"); - if (url.isValid() && !help) { - if (launchedWithExternalApp(url)) + const QString &string = url.toString(); + if (url.isValid() && string != QLatin1String("help")) { + if (launchWithExternalApp(url)) return; - QUrl u = helpEngine.findFile(url); - if (u.isValid()) { - QTextBrowser::setSource(u); + const QUrl &resolvedUrl = helpEngine.findFile(url); + if (resolvedUrl.isValid()) { + QTextBrowser::setSource(resolvedUrl); return; - } + } } - if (help) { - QTextBrowser::setSource(QUrl(QLatin1String("qthelp://com.trolltech.com." - "assistantinternal-1.0.0/assistant/assistant.html"))); - } else { + if (string != QLatin1String("help")) { QTextBrowser::setSource(url); - setHtml(PageNotFoundMessage.arg(url.toString())); + setHtml(string == QLatin1String("about:blank") ? AboutBlank + : PageNotFoundMessage.arg(url.toString())); emit sourceChanged(url); + } else { + QTextBrowser::setSource(LocalHelpFile); } } -bool HelpViewer::launchedWithExternalApp(const QUrl &url) -{ - TRACE_OBJ - const bool canOpen = canOpenPage(url.path()); - if (!isLocalUrl(url) || !canOpen) { - bool launched = false; - if (!canOpen && url.scheme() == QLatin1String("qthelp")) { - const QString& path = url.path(); - const int lastDash = path.lastIndexOf(QChar('/')); - QString fileName = QDir::tempPath() + QDir::separator(); - if (lastDash < 0) - fileName += path; - else - fileName += path.mid(lastDash + 1, path.length()); - - QFile tmpFile(QDir::cleanPath(fileName)); - if (tmpFile.open(QIODevice::ReadWrite)) { - tmpFile.write(helpEngine.fileData(url)); - tmpFile.close(); - } - launched = QDesktopServices::openUrl(QUrl(tmpFile.fileName())); - } else { - launched = QDesktopServices::openUrl(url); - } - - if (!launched) { - QMessageBox::information(this, tr("Help"), - tr("Unable to launch external application.\n"), tr("OK")); - } - return true; - } - return false; -} - QVariant HelpViewer::loadResource(int type, const QUrl &name) { TRACE_OBJ diff --git a/tools/assistant/tools/assistant/helpviewer_qtb.h b/tools/assistant/tools/assistant/helpviewer_qtb.h index e927b34..98617cb 100644 --- a/tools/assistant/tools/assistant/helpviewer_qtb.h +++ b/tools/assistant/tools/assistant/helpviewer_qtb.h @@ -79,8 +79,6 @@ public: inline bool hasSelection() const { return textCursor().hasSelection(); } - bool launchedWithExternalApp(const QUrl &url); - public Q_SLOTS: void home(); diff --git a/tools/assistant/tools/assistant/helpviewer_qwv.cpp b/tools/assistant/tools/assistant/helpviewer_qwv.cpp index 4857e00..b4e53a2 100644 --- a/tools/assistant/tools/assistant/helpviewer_qwv.cpp +++ b/tools/assistant/tools/assistant/helpviewer_qwv.cpp @@ -49,10 +49,8 @@ #include #include #include -#include #include -#include #include #include @@ -211,45 +209,27 @@ bool HelpPage::acceptNavigationRequest(QWebFrame *, const QNetworkRequest &request, QWebPage::NavigationType type) { TRACE_OBJ - const QUrl &url = request.url(); const bool closeNewTab = closeNewTabIfNeeded; closeNewTabIfNeeded = false; - if (AbstractHelpViewer::isLocalUrl(url)) { - const QString& path = url.path(); - if (!AbstractHelpViewer::canOpenPage(path)) { - QTemporaryFile tmpTmpFile; - if (!tmpTmpFile.open()) - return false; - const QString &extension = QFileInfo(path).completeSuffix(); - QFile actualTmpFile(tmpTmpFile.fileName() % QLatin1String(".") - % extension); - if (actualTmpFile.open(QIODevice::ReadWrite | QIODevice::Truncate)) { - actualTmpFile.write(HelpEngineWrapper::instance().fileData(url)); - actualTmpFile.close(); - QDesktopServices::openUrl(QUrl(actualTmpFile.fileName())); - } - - if (closeNewTab) - QMetaObject::invokeMethod(CentralWidget::instance(), "closeTab"); + const QUrl &url = request.url(); + if (AbstractHelpViewer::launchWithExternalApp(url)) { + if (closeNewTab) + QMetaObject::invokeMethod(centralWidget, "closeTab"); + return false; + } + + if (type == QWebPage::NavigationTypeLinkClicked + && (m_keyboardModifiers & Qt::ControlModifier + || m_pressedButtons == Qt::MidButton)) { + if (HelpViewer* viewer = centralWidget->newEmptyTab()) + centralWidget->setSource(url); + m_pressedButtons = Qt::NoButton; + m_keyboardModifiers = Qt::NoModifier; return false; - } - - if (type == QWebPage::NavigationTypeLinkClicked - && (m_keyboardModifiers & Qt::ControlModifier - || m_pressedButtons == Qt::MidButton)) { - HelpViewer* viewer = centralWidget->newEmptyTab(); - if (viewer) - CentralWidget::instance()->setSource(url); - m_pressedButtons = Qt::NoButton; - m_keyboardModifiers = Qt::NoModifier; - return false; - } - return true; } - QDesktopServices::openUrl(url); - return false; + return true; } // -- HelpViewer @@ -337,12 +317,7 @@ void HelpViewer::setSource(const QUrl &url) { TRACE_OBJ loadFinished = false; - if (url.toString() == QLatin1String("help")) { - load(QUrl(QLatin1String("qthelp://com.trolltech.com." - "assistantinternal-1.0.0/assistant/assistant.html"))); - } else { - load(url); - } + load(url.toString() == QLatin1String("help") ? LocalHelpFile : url); } void HelpViewer::home() -- cgit v0.12 From fd717e5e182433a8c68a6e84ad207e6bba154334 Mon Sep 17 00:00:00 2001 From: kh1 Date: Wed, 17 Feb 2010 13:33:28 +0100 Subject: Fix broken set last shown pagen when the last page was about:blank. Reviewed-by: ck --- tools/assistant/tools/assistant/centralwidget.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tools/assistant/tools/assistant/centralwidget.cpp b/tools/assistant/tools/assistant/centralwidget.cpp index d0a6e56..f56e9e3 100644 --- a/tools/assistant/tools/assistant/centralwidget.cpp +++ b/tools/assistant/tools/assistant/centralwidget.cpp @@ -333,9 +333,10 @@ void CentralWidget::setLastShownPages() for (int curTab = 0; curTab < pageCount; ++curTab) { const QString &curFile = lastShownPageList.at(curTab); - if (helpEngine.findFile(curFile).isValid()) + if (helpEngine.findFile(curFile).isValid() + || curFile == QLatin1String("about:blank")) { setSourceInNewTab(curFile, zoomFactors.at(curTab).toFloat()); - else if (curTab + searchIsAttached <= tabToShow) + } else if (curTab + searchIsAttached <= tabToShow) --tabToShow; } -- cgit v0.12 From 29aa6e9d15a28e9a384d6a70585a43888745d34b Mon Sep 17 00:00:00 2001 From: kh1 Date: Wed, 17 Feb 2010 13:46:40 +0100 Subject: Prevent renaming the bookmarks menu root item, it's just a placeholder. Reviewed-by: ck --- tools/assistant/tools/assistant/bookmarkdialog.cpp | 20 ++++++++++++++++---- tools/assistant/tools/assistant/bookmarkdialog.h | 1 + 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/tools/assistant/tools/assistant/bookmarkdialog.cpp b/tools/assistant/tools/assistant/bookmarkdialog.cpp index c053b62..8b195c1 100644 --- a/tools/assistant/tools/assistant/bookmarkdialog.cpp +++ b/tools/assistant/tools/assistant/bookmarkdialog.cpp @@ -105,6 +105,11 @@ BookmarkDialog::~BookmarkDialog() TRACE_OBJ } +bool BookmarkDialog::isRootItem(const QModelIndex &index) const +{ + return !bookmarkTreeModel->parent(index).isValid(); +} + bool BookmarkDialog::eventFilter(QObject *object, QEvent *event) { TRACE_OBJ @@ -115,9 +120,12 @@ bool BookmarkDialog::eventFilter(QObject *object, QEvent *event) QKeyEvent *ke = static_cast(event); switch (ke->key()) { case Qt::Key_F2: { - bookmarkModel->setItemsEditable(true); - ui.treeView->edit(ui.treeView->currentIndex()); - bookmarkModel->setItemsEditable(false); + const QModelIndex &index = ui.treeView->currentIndex(); + if (!isRootItem(index)) { + bookmarkModel->setItemsEditable(true); + ui.treeView->edit(index); + bookmarkModel->setItemsEditable(false); + } } break; default: break; } @@ -212,13 +220,17 @@ void BookmarkDialog::textChanged(const QString& text) void BookmarkDialog::customContextMenuRequested(const QPoint &point) { TRACE_OBJ + const QModelIndex &index = ui.treeView->currentIndex(); + if (isRootItem(index)) + return; // check if we go to rename the "Bookmarks Menu", bail + QMenu menu(QLatin1String(""), this); QAction *renameItem = menu.addAction(tr("Rename Folder")); QAction *picked = menu.exec(ui.treeView->mapToGlobal(point)); if (picked == renameItem) { bookmarkModel->setItemsEditable(true); - ui.treeView->edit(ui.treeView->currentIndex()); + ui.treeView->edit(index); bookmarkModel->setItemsEditable(false); } } diff --git a/tools/assistant/tools/assistant/bookmarkdialog.h b/tools/assistant/tools/assistant/bookmarkdialog.h index ba38c7a..e177af6 100644 --- a/tools/assistant/tools/assistant/bookmarkdialog.h +++ b/tools/assistant/tools/assistant/bookmarkdialog.h @@ -58,6 +58,7 @@ public: ~BookmarkDialog(); private: + bool isRootItem(const QModelIndex &index) const; bool eventFilter(QObject *object, QEvent *event); private slots: -- cgit v0.12 From c2fee16b4d60962979943fd31ce7cffce54d8096 Mon Sep 17 00:00:00 2001 From: kh1 Date: Wed, 17 Feb 2010 14:56:55 +0100 Subject: Fix spacing. --- tools/assistant/tools/assistant/bookmarkwidget.ui | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tools/assistant/tools/assistant/bookmarkwidget.ui b/tools/assistant/tools/assistant/bookmarkwidget.ui index 3015740..a31a277 100644 --- a/tools/assistant/tools/assistant/bookmarkwidget.ui +++ b/tools/assistant/tools/assistant/bookmarkwidget.ui @@ -14,6 +14,9 @@ Bookmarks + + 4 + -- cgit v0.12 From 27f8dc149efa49bdea809df130b0c14d15359964 Mon Sep 17 00:00:00 2001 From: kh1 Date: Wed, 17 Feb 2010 15:16:23 +0100 Subject: Fix memmory leak. --- tools/assistant/tools/assistant/bookmarkmanager.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/assistant/tools/assistant/bookmarkmanager.cpp b/tools/assistant/tools/assistant/bookmarkmanager.cpp index b73fbb5..00f6346 100644 --- a/tools/assistant/tools/assistant/bookmarkmanager.cpp +++ b/tools/assistant/tools/assistant/bookmarkmanager.cpp @@ -199,6 +199,7 @@ BookmarkManager::~BookmarkManager() { TRACE_OBJ HelpEngineWrapper::instance().setBookmarks(bookmarkModel->bookmarks()); + delete bookmarkModel; } void BookmarkManager::removeItem(const QModelIndex &index) -- cgit v0.12 From 4dc56aa381d72335f8759da0bb8ca29897fce3a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thorbj=C3=B8rn=20Lindeijer?= Date: Wed, 17 Feb 2010 16:58:53 +0100 Subject: Added QPlainTextEditor::anchorAt(const QPoint &pos) The equivalent of QTextEdit::anchorAt. Done-with: mae --- src/gui/widgets/qplaintextedit.cpp | 20 ++++++++++++++++++++ src/gui/widgets/qplaintextedit.h | 2 ++ 2 files changed, 22 insertions(+) diff --git a/src/gui/widgets/qplaintextedit.cpp b/src/gui/widgets/qplaintextedit.cpp index 0d798b7..ef9fac3 100644 --- a/src/gui/widgets/qplaintextedit.cpp +++ b/src/gui/widgets/qplaintextedit.cpp @@ -1320,6 +1320,26 @@ QTextCursor QPlainTextEdit::textCursor() const return d->control->textCursor(); } +/*! + Returns the reference of the anchor at position \a pos, or an + empty string if no anchor exists at that point. + + \since 4.7 + */ +QString QPlainTextEdit::anchorAt(const QPoint &pos) const +{ + Q_D(const QPlainTextEdit); + int cursorPos = d->control->hitTest(pos + QPoint(d->horizontalOffset(), + d->verticalOffset()), + Qt::ExactHit); + if (cursorPos < 0) + return QString(); + + QTextDocumentPrivate *pieceTable = document()->docHandle(); + QTextDocumentPrivate::FragmentIterator it = pieceTable->find(cursorPos); + QTextCharFormat fmt = pieceTable->formatCollection()->charFormat(it->format); + return fmt.anchorHref(); +} /*! Undoes the last operation. diff --git a/src/gui/widgets/qplaintextedit.h b/src/gui/widgets/qplaintextedit.h index 15cf0967..106ae6d 100644 --- a/src/gui/widgets/qplaintextedit.h +++ b/src/gui/widgets/qplaintextedit.h @@ -159,6 +159,8 @@ public: QRect cursorRect(const QTextCursor &cursor) const; QRect cursorRect() const; + QString anchorAt(const QPoint &pos) const; + bool overwriteMode() const; void setOverwriteMode(bool overwrite); -- cgit v0.12 From 5084d1694e62c3c704c83cc0f27afb6a39b20781 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Wed, 17 Feb 2010 16:05:47 +0100 Subject: amend "purge msvc.net and msvc2002 makespecs" - win32-msvc.net/qplatformdefs.h was included from msvc2003. inline it. - purge references to msvc.net from feature files Reviewed-by: mariusSO --- mkspecs/features/incredibuild_xge.prf | 2 +- mkspecs/features/moc.prf | 2 +- mkspecs/features/win32/thread.prf | 4 -- mkspecs/win32-msvc2003/qplatformdefs.h | 100 ++++++++++++++++++++++++++++++++- 4 files changed, 101 insertions(+), 7 deletions(-) diff --git a/mkspecs/features/incredibuild_xge.prf b/mkspecs/features/incredibuild_xge.prf index 2fce443..e241ca4 100644 --- a/mkspecs/features/incredibuild_xge.prf +++ b/mkspecs/features/incredibuild_xge.prf @@ -3,7 +3,7 @@ contains(TEMPLATE, "vc.*")|contains(TEMPLATE_PREFIX, "vc") { # The VCPROJ generator will replace the \r\h with the coded \r\n: # No other generator understands the \h - win32-msvc.net|win32-msvc2*|wince*msvc*: EOC = \$\$escape_expand(\r\h) + win32-msvc2*|wince*msvc*: EOC = \$\$escape_expand(\r\h) for(xge, INCREDIBUILD_XGE) { eval($${xge}.commands = Rem IncrediBuild_AllowRemote $$EOC Rem IncrediBuild_OutputFile $$replace($${xge}.output,/,\\) $$EOC $$eval($${xge}.commands)) diff --git a/mkspecs/features/moc.prf b/mkspecs/features/moc.prf index e4b7dae..e806ef6 100644 --- a/mkspecs/features/moc.prf +++ b/mkspecs/features/moc.prf @@ -22,7 +22,7 @@ win32:count($$list($$INCPATH), 40, >) { if(contains(TEMPLATE, "vc.*")|contains(TEMPLATE_PREFIX, "vc")) { # the VCPROJ generator will replace the \r\h with the coded \r\n: # No other generator understands the \h - if(win32-msvc.net|win32-msvc2*|wince*msvc*): EOC = $$escape_expand(\r\h) + if(win32-msvc2*|wince*msvc*): EOC = $$escape_expand(\r\h) else: EOC = $$escape_expand(\\)$$escape_expand(\n\t) } diff --git a/mkspecs/features/win32/thread.prf b/mkspecs/features/win32/thread.prf index aa844d2..76354a8 100644 --- a/mkspecs/features/win32/thread.prf +++ b/mkspecs/features/win32/thread.prf @@ -23,8 +23,4 @@ debug { } } -win32-msvc|win32-msvc.net { - !contains(DEFINES, QT_DLL):!target_qt:!isEqual(TARGET, qtmain):QMAKE_LFLAGS += /NODEFAULTLIB:"libc" -} - QMAKE_LIBS += $$QMAKE_LIBS_RTMT diff --git a/mkspecs/win32-msvc2003/qplatformdefs.h b/mkspecs/win32-msvc2003/qplatformdefs.h index 6d71abf..05584c9 100644 --- a/mkspecs/win32-msvc2003/qplatformdefs.h +++ b/mkspecs/win32-msvc2003/qplatformdefs.h @@ -39,4 +39,102 @@ ** ****************************************************************************/ -#include "../win32-msvc.net/qplatformdefs.h" +#ifndef QPLATFORMDEFS_H +#define QPLATFORMDEFS_H + +#ifdef UNICODE +#ifndef _UNICODE +#define _UNICODE +#endif +#endif + +// Get Qt defines/settings + +#include "qglobal.h" + +#define _POSIX_ +#include +#undef _POSIX_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define Q_FS_FAT +#ifdef QT_LARGEFILE_SUPPORT +#define QT_STATBUF struct _stati64 // non-ANSI defs +#define QT_STATBUF4TSTAT struct _stati64 // non-ANSI defs +#define QT_STAT ::_stati64 +#define QT_FSTAT ::_fstati64 +#else +#define QT_STATBUF struct _stat // non-ANSI defs +#define QT_STATBUF4TSTAT struct _stat // non-ANSI defs +#define QT_STAT ::_stat +#define QT_FSTAT ::_fstat +#endif +#define QT_STAT_REG _S_IFREG +#define QT_STAT_DIR _S_IFDIR +#define QT_STAT_MASK _S_IFMT +#if defined(_S_IFLNK) +# define QT_STAT_LNK _S_IFLNK +#endif +#define QT_FILENO _fileno +#define QT_OPEN ::_open +#define QT_CLOSE ::_close +#ifdef QT_LARGEFILE_SUPPORT +#define QT_LSEEK ::_lseeki64 +#define QT_TSTAT ::_tstati64 +#else +#define QT_LSEEK ::_lseek +#define QT_TSTAT ::_tstat +#endif +#define QT_READ ::_read +#define QT_WRITE ::_write +#define QT_ACCESS ::_access +#define QT_GETCWD ::_getcwd +#define QT_CHDIR ::_chdir +#define QT_MKDIR ::_mkdir +#define QT_RMDIR ::_rmdir +#define QT_OPEN_LARGEFILE 0 +#define QT_OPEN_RDONLY _O_RDONLY +#define QT_OPEN_WRONLY _O_WRONLY +#define QT_OPEN_RDWR _O_RDWR +#define QT_OPEN_CREAT _O_CREAT +#define QT_OPEN_TRUNC _O_TRUNC +#define QT_OPEN_APPEND _O_APPEND +#if defined(O_TEXT) +# define QT_OPEN_TEXT _O_TEXT +# define QT_OPEN_BINARY _O_BINARY +#endif + +#include "../common/c89/qplatformdefs.h" + +#ifdef QT_LARGEFILE_SUPPORT +#undef QT_FTELL +#undef QT_OFF_T + +// 64-bit versions of fseek/ftell not always available. E.g., when linking +// dynamically to CRT (/MT) +#define QT_FTELL (QT_OFF_T)::ftell +#define QT_OFF_T __int64 +#endif + +#define QT_SIGNAL_ARGS int + +#define QT_VSNPRINTF ::_vsnprintf +#define QT_SNPRINTF ::_snprintf + +# define F_OK 0 +# define X_OK 1 +# define W_OK 2 +# define R_OK 4 + +typedef int mode_t; + +#endif // QPLATFORMDEFS_H -- cgit v0.12 From 8653f5a3233bff64ec7438fb5e38a6df57dce10e Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Wed, 17 Feb 2010 13:52:35 +0100 Subject: optimization: use QList::reserve() and QVector::reserve() Co-authored-by: denis --- src/corelib/tools/qvector.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/corelib/tools/qvector.h b/src/corelib/tools/qvector.h index 61b22fd..2fc4d6c 100644 --- a/src/corelib/tools/qvector.h +++ b/src/corelib/tools/qvector.h @@ -728,9 +728,10 @@ Q_OUTOFLINE_TEMPLATE QVector QVector::mid(int pos, int length) const length = size() - pos; if (pos == 0 && length == size()) return *this; - QVector copy; if (pos + length > size()) length = size() - pos; + QVector copy; + copy.reserve(length); for (int i = pos; i < pos + length; ++i) copy += at(i); return copy; @@ -740,6 +741,7 @@ template Q_OUTOFLINE_TEMPLATE QList QVector::toList() const { QList result; + result.reserve(size()); for (int i = 0; i < size(); ++i) result.append(at(i)); return result; -- cgit v0.12 From a8b92f26bcd9fa5c1e77c8e8e5d6ce6f16a68bae Mon Sep 17 00:00:00 2001 From: kh1 Date: Wed, 17 Feb 2010 18:04:25 +0100 Subject: Implement bookmark manager widget. Add some more flexible approach to rename, export and import bookmarks. --- tools/assistant/tools/assistant/assistant.pro | 3 + .../assistant/tools/assistant/bookmarkmanager.cpp | 74 ++--- tools/assistant/tools/assistant/bookmarkmanager.h | 8 +- .../tools/assistant/bookmarkmanagerwidget.cpp | 321 +++++++++++++++++++++ .../tools/assistant/bookmarkmanagerwidget.h | 102 +++++++ .../tools/assistant/bookmarkmanagerwidget.ui | 137 +++++++++ tools/assistant/tools/assistant/bookmarkmodel.cpp | 12 + tools/assistant/tools/assistant/bookmarkmodel.h | 1 + 8 files changed, 606 insertions(+), 52 deletions(-) create mode 100644 tools/assistant/tools/assistant/bookmarkmanagerwidget.cpp create mode 100644 tools/assistant/tools/assistant/bookmarkmanagerwidget.h create mode 100644 tools/assistant/tools/assistant/bookmarkmanagerwidget.ui diff --git a/tools/assistant/tools/assistant/assistant.pro b/tools/assistant/tools/assistant/assistant.pro index 0733128..ff0ecc5 100644 --- a/tools/assistant/tools/assistant/assistant.pro +++ b/tools/assistant/tools/assistant/assistant.pro @@ -21,6 +21,7 @@ HEADERS += aboutdialog.h \ bookmarkfiltermodel.h \ bookmarkitem.h \ bookmarkmanager.h \ + bookmarkmanagerwidget.h \ bookmarkmodel.h \ centralwidget.h \ cmdlineparser.h \ @@ -49,6 +50,7 @@ SOURCES += aboutdialog.cpp \ bookmarkfiltermodel.cpp \ bookmarkitem.cpp \ bookmarkmanager.cpp \ + bookmarkmanagerwidget.cpp \ bookmarkmodel.cpp \ centralwidget.cpp \ cmdlineparser.cpp \ @@ -72,6 +74,7 @@ SOURCES += aboutdialog.cpp \ ../shared/collectionconfiguration.cpp \ FORMS += bookmarkdialog.ui \ + bookmarkmanagerwidget.ui \ bookmarkwidget.ui \ filternamedialog.ui \ installdialog.ui \ diff --git a/tools/assistant/tools/assistant/bookmarkmanager.cpp b/tools/assistant/tools/assistant/bookmarkmanager.cpp index 00f6346..70f562e 100644 --- a/tools/assistant/tools/assistant/bookmarkmanager.cpp +++ b/tools/assistant/tools/assistant/bookmarkmanager.cpp @@ -41,6 +41,7 @@ #include "tracer.h" #include "bookmarkmanager.h" +#include "bookmarkmanagerwidget.h" #include "bookmarkdialog.h" #include "bookmarkfiltermodel.h" #include "bookmarkitem.h" @@ -48,15 +49,11 @@ #include "centralwidget.h" #include "helpenginewrapper.h" -#include #include #include #include #include -#include -#include "xbelsupport.h" - QT_BEGIN_NAMESPACE // -- BookmarkManager::BookmarkWidget @@ -163,6 +160,7 @@ BookmarkManager::BookmarkManager() , bookmarkModel(new BookmarkModel) , bookmarkWidget(new BookmarkWidget) , bookmarkTreeView(new BookmarkTreeView) + , bookmarkManagerWidget(0) { TRACE_OBJ bookmarkWidget->installEventFilter(this); @@ -198,6 +196,7 @@ BookmarkManager::BookmarkManager() BookmarkManager::~BookmarkManager() { TRACE_OBJ + delete bookmarkManagerWidget; HelpEngineWrapper::instance().setBookmarks(bookmarkModel->bookmarks()); delete bookmarkModel; } @@ -338,10 +337,21 @@ void BookmarkManager::removeBookmark() removeItem(bookmarkTreeView->currentIndex()); } -//void BookmarkManager::manageBookmarks() -//{ -// TRACE_OBJ -//} +void BookmarkManager::manageBookmarks() +{ + TRACE_OBJ + if (bookmarkManagerWidget == 0) { + bookmarkManagerWidget = new BookmarkManagerWidget(bookmarkModel); + connect(bookmarkManagerWidget, SIGNAL(setSource(QUrl)), this, + SIGNAL(setSource(QUrl))); + connect(bookmarkManagerWidget, SIGNAL(setSourceInNewTab(QUrl)) + , this, SIGNAL(setSourceInNewTab(QUrl))); + connect(bookmarkManagerWidget, SIGNAL(managerWidgetAboutToClose()) + , this, SLOT(managerWidgetAboutToClose())); + } + bookmarkManagerWidget->show(); + bookmarkManagerWidget->raise(); +} void BookmarkManager::refeshBookmarkMenu() { @@ -351,10 +361,8 @@ void BookmarkManager::refeshBookmarkMenu() bookmarkMenu->clear(); - //bookmarkMenu->addAction(tr("Manage Bookmarks..."), this, - // SLOT(manageBookmarks())); - bookmarkMenu->addAction(tr("Import..."), this, SLOT(importBookmarks())); - bookmarkMenu->addAction(tr("Export..."), this, SLOT(exportBookmarks())); + bookmarkMenu->addAction(tr("Manage Bookmarks..."), this, + SLOT(manageBookmarks())); bookmarkMenu->addAction(tr("Add Bookmark..."), this, SLOT(addBookmark()), QKeySequence(tr("Ctrl+D"))); bookmarkMenu->addSeparator(); @@ -378,42 +386,6 @@ void BookmarkManager::renameBookmark(const QModelIndex &index) bookmarkModel->setItemsEditable(false); } -void BookmarkManager::importBookmarks() -{ - TRACE_OBJ - const QString &fileName = QFileDialog::getOpenFileName(0, tr("Open File"), - QDir::currentPath(), tr("Files (*.xbel)")); - - if (fileName.isEmpty()) - return; - - QFile file(fileName); - if (file.open(QIODevice::ReadOnly)) { - XbelReader reader(bookmarkModel); - reader.readFromFile(&file); - } -} - -void BookmarkManager::exportBookmarks() -{ - TRACE_OBJ - QString fileName = QFileDialog::getSaveFileName(0, tr("Save File"), - QLatin1String("untitled.xbel"), tr("Files (*.xbel)")); - - const QLatin1String suffix(".xbel"); - if (!fileName.endsWith(suffix)) - fileName.append(suffix); - - QFile file(fileName); - if (file.open(QIODevice::WriteOnly)) { - XbelWriter writer(bookmarkModel); - writer.writeToFile(&file); - } else { - QMessageBox::information(bookmarkTreeView, tr("Qt Assistant"), - tr("Unable to save bookmarks."), tr("OK")); - } -} - void BookmarkManager::setSourceFromAction(QAction *action) { TRACE_OBJ @@ -487,6 +459,12 @@ void BookmarkManager::focusInEvent() bookmarkTreeView->setCurrentIndex(index); } +void BookmarkManager::managerWidgetAboutToClose() +{ + delete bookmarkManagerWidget; + bookmarkManagerWidget = 0; +} + void BookmarkManager::textChanged(const QString &text) { TRACE_OBJ diff --git a/tools/assistant/tools/assistant/bookmarkmanager.h b/tools/assistant/tools/assistant/bookmarkmanager.h index 88342d5..c26dad8 100644 --- a/tools/assistant/tools/assistant/bookmarkmanager.h +++ b/tools/assistant/tools/assistant/bookmarkmanager.h @@ -48,6 +48,7 @@ QT_BEGIN_NAMESPACE +class BookmarkManagerWidget; class BookmarkModel; class BookmarkFilterModel; class QKeyEvent; @@ -90,17 +91,15 @@ private slots: void addBookmark(); void removeBookmark(); -// void manageBookmarks(); + void manageBookmarks(); void refeshBookmarkMenu(); void renameBookmark(const QModelIndex &index); - void importBookmarks(); - void exportBookmarks(); - void setSourceFromAction(QAction *action); void setSourceFromIndex(const QModelIndex &index, bool newTab = false); void focusInEvent(); + void managerWidgetAboutToClose(); void textChanged(const QString &text); void customContextMenuRequested(const QPoint &point); @@ -118,6 +117,7 @@ private: BookmarkWidget *bookmarkWidget; BookmarkTreeView *bookmarkTreeView; + BookmarkManagerWidget *bookmarkManagerWidget; }; class BookmarkManager::BookmarkWidget : public QWidget diff --git a/tools/assistant/tools/assistant/bookmarkmanagerwidget.cpp b/tools/assistant/tools/assistant/bookmarkmanagerwidget.cpp new file mode 100644 index 0000000..65df6be --- /dev/null +++ b/tools/assistant/tools/assistant/bookmarkmanagerwidget.cpp @@ -0,0 +1,321 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Assistant of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include "bookmarkmanagerwidget.h" +#include "bookmarkitem.h" +#include "bookmarkmodel.h" +#include "tracer.h" +#include "xbelsupport.h" + +#include +#include +#include + +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +namespace { + #define TR(x) QCoreApplication::translate("BookmarkManager", x) +} + +BookmarkManagerWidget::BookmarkManagerWidget(BookmarkModel *sourceModel, + QWidget *parent) + : QWidget(parent) + , bookmarkModel(sourceModel) +{ + TRACE_OBJ + ui.setupUi(this); + + ui.treeView->setModel(bookmarkModel); + + ui.treeView->expandAll(); + ui.treeView->installEventFilter(this); + ui.treeView->viewport()->installEventFilter(this); + ui.treeView->setContextMenuPolicy(Qt::CustomContextMenu); + + connect(ui.treeView, SIGNAL(customContextMenuRequested(QPoint)), this, + SLOT(customContextMenuRequested(QPoint))); + + connect(ui.remove, SIGNAL(clicked()), this, SLOT(removeItem())); + connect(ui.lineEdit, SIGNAL(textChanged(QString)), this, + SLOT(textChanged(QString))); + new QShortcut(QKeySequence::Find, ui.lineEdit, SLOT(setFocus())); + + importExportMenu.addAction(tr("Import..."), this, SLOT(importBookmarks())); + importExportMenu.addAction(tr("Export..."), this, SLOT(exportBookmarks())); + ui.importExport->setMenu(&importExportMenu); + + new QShortcut(QKeySequence::FindNext, this, SLOT(findNext())); + new QShortcut(QKeySequence::FindPrevious, this, SLOT(findPrevious())); + + connect(bookmarkModel, SIGNAL(rowsRemoved(QModelIndex, int, int)), this, + SLOT(refeshBookmarkCache())); + connect(bookmarkModel, SIGNAL(rowsInserted(QModelIndex, int, int)), this, + SLOT(refeshBookmarkCache())); + connect(bookmarkModel, SIGNAL(dataChanged(QModelIndex, QModelIndex)), this, + SLOT(refeshBookmarkCache())); + + ui.treeView->setCurrentIndex(ui.treeView->indexAt(QPoint(2, 2))); +} + +BookmarkManagerWidget::~BookmarkManagerWidget() +{ + TRACE_OBJ +} + +void BookmarkManagerWidget::closeEvent(QCloseEvent *event) +{ + TRACE_OBJ + event->accept(); + emit managerWidgetAboutToClose(); +} + +void BookmarkManagerWidget::renameItem(const QModelIndex &index) +{ + TRACE_OBJ + // check if we should rename the "Bookmarks Menu", bail + if (!bookmarkModel->parent(index).isValid()) + return; + + bookmarkModel->setItemsEditable(true); + ui.treeView->edit(index); + bookmarkModel->setItemsEditable(false); +} + +static int nextIndex(int current, int count, bool forward) +{ + TRACE_OBJ + if (current >= 0) + return (forward ? (current + 1) : ((current - 1) + count)) % count; + return 0; +} + +void BookmarkManagerWidget::selectNextIndex(bool direction) const +{ + QModelIndex current = ui.treeView->currentIndex(); + if (current.isValid() && !cache.isEmpty()) { + current = cache.at(nextIndex(cache.indexOf(current), cache.count(), + direction)); + } + ui.treeView->setCurrentIndex(current); +} + +bool BookmarkManagerWidget::eventFilter(QObject *object, QEvent *event) +{ + TRACE_OBJ + if (object != ui.treeView && object != ui.treeView->viewport()) + return QWidget::eventFilter(object, event); + + if (event->type() == QEvent::KeyPress) { + QKeyEvent *ke = static_cast(event); + switch (ke->key()) { + case Qt::Key_F2: { + renameItem(ui.treeView->currentIndex()); + } break; + + case Qt::Key_Delete: { + removeItem(ui.treeView->currentIndex()); + } break; + + default: break; + } + } + + if (event->type() == QEvent::MouseButtonRelease) { + QMouseEvent *me = static_cast(event); + switch (me->button()) { + case Qt::LeftButton: { + if (me->modifiers() & Qt::ControlModifier) + setSourceFromIndex(ui.treeView->currentIndex(), true); + } break; + + case Qt::MidButton: { + setSourceFromIndex(ui.treeView->currentIndex(), true); + } break; + + default: break; + } + } + return QObject::eventFilter(object, event); +} + +void BookmarkManagerWidget::findNext() +{ + TRACE_OBJ + selectNextIndex(true); +} + +void BookmarkManagerWidget::findPrevious() +{ + TRACE_OBJ + selectNextIndex(false); +} + +void BookmarkManagerWidget::importBookmarks() +{ + TRACE_OBJ + const QString &fileName = QFileDialog::getOpenFileName(0, TR("Open File"), + QDir::currentPath(), TR("Files (*.xbel)")); + + if (fileName.isEmpty()) + return; + + QFile file(fileName); + if (file.open(QIODevice::ReadOnly)) { + XbelReader reader(bookmarkModel); + reader.readFromFile(&file); + } +} + +void BookmarkManagerWidget::exportBookmarks() +{ + TRACE_OBJ + QString fileName = QFileDialog::getSaveFileName(0, TR("Save File"), + QLatin1String("untitled.xbel"), TR("Files (*.xbel)")); + + const QLatin1String suffix(".xbel"); + if (!fileName.endsWith(suffix)) + fileName.append(suffix); + + QFile file(fileName); + if (file.open(QIODevice::WriteOnly)) { + XbelWriter writer(bookmarkModel); + writer.writeToFile(&file); + } else { + QMessageBox::information(this, TR("Qt Assistant"), + TR("Unable to save bookmarks."), TR("OK")); + } +} + +void BookmarkManagerWidget::refeshBookmarkCache() +{ + TRACE_OBJ + cache.clear(); + + const QString &text = ui.lineEdit->text(); + if (!text.isEmpty()) + cache = bookmarkModel->indexListFor(text); +} + +void BookmarkManagerWidget::textChanged(const QString &/*text*/) +{ + TRACE_OBJ + refeshBookmarkCache(); + if (!cache.isEmpty()) + ui.treeView->setCurrentIndex(cache.at(0)); +} + +void BookmarkManagerWidget::removeItem(const QModelIndex &index) +{ + TRACE_OBJ + QModelIndex current = index.isValid() ? index : ui.treeView->currentIndex(); + if (!bookmarkModel->parent(current).isValid()) + return; // check if we should delete the "Bookmarks Menu", bail + + if (bookmarkModel->hasChildren(current)) { + int value = QMessageBox::question(this, TR("Remove"), TR("You are going" + "to delete a Folder, this will also
remove it's content. Are " + "you sure to continue?"), + QMessageBox::Yes | QMessageBox::Cancel, QMessageBox::Cancel); + if (value == QMessageBox::Cancel) + return; + } + bookmarkModel->removeItem(current); +} + +void BookmarkManagerWidget::customContextMenuRequested(const QPoint &point) +{ + TRACE_OBJ + const QModelIndex &index = ui.treeView->indexAt(point); + if (!index.isValid()) + return; + + // check if we should open the menu on "Bookmarks Menu", bail + if (!bookmarkModel->parent(index).isValid()) + return; + + QAction *remove = 0; + QAction *rename = 0; + QAction *showItem = 0; + QAction *showItemInNewTab = 0; + + QMenu menu(QLatin1String("")); + if (bookmarkModel->data(index, UserRoleFolder).toBool()) { + remove = menu.addAction(TR("Delete Folder")); + rename = menu.addAction(TR("Rename Folder")); + } else { + showItem = menu.addAction(TR("Show Bookmark")); + showItemInNewTab = menu.addAction(TR("Show Bookmark in New Tab")); + menu.addSeparator(); + remove = menu.addAction(TR("Delete Bookmark")); + rename = menu.addAction(TR("Rename Bookmark")); + } + + QAction *pickedAction = menu.exec(ui.treeView->mapToGlobal(point)); + if (pickedAction == rename) + renameItem(index); + else if (pickedAction == remove) + removeItem(index); + else if (pickedAction == showItem || pickedAction == showItemInNewTab) + setSourceFromIndex(index, pickedAction == showItemInNewTab); +} + +void +BookmarkManagerWidget::setSourceFromIndex(const QModelIndex &index, bool newTab) +{ + TRACE_OBJ + if (bookmarkModel->data(index, UserRoleFolder).toBool()) + return; + + const QVariant &data = bookmarkModel->data(index, UserRoleUrl); + if (data.canConvert()) { + if (newTab) + emit setSourceInNewTab(data.toUrl()); + else + emit setSource(data.toUrl()); + } +} + +QT_END_NAMESPACE diff --git a/tools/assistant/tools/assistant/bookmarkmanagerwidget.h b/tools/assistant/tools/assistant/bookmarkmanagerwidget.h new file mode 100644 index 0000000..94384a6 --- /dev/null +++ b/tools/assistant/tools/assistant/bookmarkmanagerwidget.h @@ -0,0 +1,102 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Assistant of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#ifndef BOOKMARKMANAGERWIDGET_H +#define BOOKMARKMANAGERWIDGET_H + +#include "ui_bookmarkmanagerwidget.h" + +#include + +#include + +QT_BEGIN_NAMESPACE + +class BookmarkModel; +class QCloseEvent; +class QString; + +class BookmarkManagerWidget : public QWidget +{ + Q_OBJECT +public: + BookmarkManagerWidget(BookmarkModel *bookmarkModel, QWidget *parent = 0); + ~BookmarkManagerWidget(); + +protected: + void closeEvent(QCloseEvent *event); + +signals: + void setSource(const QUrl &url); + void setSourceInNewTab(const QUrl &url); + + void managerWidgetAboutToClose(); + +private: + void renameItem(const QModelIndex &index); + void selectNextIndex(bool direction) const; + bool eventFilter(QObject *object, QEvent *event); + +private slots: + void findNext(); + void findPrevious(); + + void importBookmarks(); + void exportBookmarks(); + + void refeshBookmarkCache(); + void textChanged(const QString &text); + + void removeItem(const QModelIndex &index = QModelIndex()); + + void customContextMenuRequested(const QPoint &point); + void setSourceFromIndex(const QModelIndex &index, bool newTab = false); + +private: + QMenu importExportMenu; + Ui::BookmarkManagerWidget ui; + QList cache; + + BookmarkModel *bookmarkModel; +}; + +QT_END_NAMESPACE + +#endif // BOOKMARKMANAGERWIDGET_H \ No newline at end of file diff --git a/tools/assistant/tools/assistant/bookmarkmanagerwidget.ui b/tools/assistant/tools/assistant/bookmarkmanagerwidget.ui new file mode 100644 index 0000000..dc965d9 --- /dev/null +++ b/tools/assistant/tools/assistant/bookmarkmanagerwidget.ui @@ -0,0 +1,137 @@ + + + BookmarkManagerWidget + + + + 0 + 0 + 517 + 348 + + + + Manage Bookmarks + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Search: + + + + + + + + + + + + true + + + true + + + true + + + 1000 + + + true + + + true + + + 225 + + + 50 + + + 225 + + + 50 + + + + + + + + + Remove + + + + + + + Import and Backup + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + OK + + + + + + + + + + + pushButton_5 + clicked() + BookmarkManagerWidget + close() + + + 445 + 328 + + + 340 + 313 + + + + + diff --git a/tools/assistant/tools/assistant/bookmarkmodel.cpp b/tools/assistant/tools/assistant/bookmarkmodel.cpp index f9c9980..e446ff0 100644 --- a/tools/assistant/tools/assistant/bookmarkmodel.cpp +++ b/tools/assistant/tools/assistant/bookmarkmodel.cpp @@ -306,6 +306,18 @@ BookmarkModel::itemFromIndex(const QModelIndex &index) const return rootItem; } +QList +BookmarkModel::indexListFor(const QString &label) const +{ + QList hits; + const QModelIndexList &list = collectItems(QModelIndex()); + foreach(const QModelIndex &index, list) { + if (index.data().toString().contains(label, Qt::CaseInsensitive)) + hits.prepend(index); // list is reverse sorted + } + return hits; +} + bool BookmarkModel::insertRows(int position, int rows, const QModelIndex &parent) { diff --git a/tools/assistant/tools/assistant/bookmarkmodel.h b/tools/assistant/tools/assistant/bookmarkmodel.h index 6b2a0b8..6469258 100644 --- a/tools/assistant/tools/assistant/bookmarkmodel.h +++ b/tools/assistant/tools/assistant/bookmarkmodel.h @@ -84,6 +84,7 @@ public: QModelIndex indexFromItem(BookmarkItem *item) const; BookmarkItem *itemFromIndex(const QModelIndex &index) const; + QList indexListFor(const QString &label) const; bool insertRows(int position, int rows, const QModelIndex &parent); bool removeRows(int position, int rows, const QModelIndex &parent); -- cgit v0.12 From 03ac778172b783d26bb1c7c5d92bdedd045fcc92 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Wed, 17 Feb 2010 18:28:47 +0100 Subject: unbreak QList::append() and co. again make sure that the detached object is always at least as big as the original one. that may be somewhat wasteful, but it is no worse than before the detach() optimization. one may consider improvements later. Reviewed-by: joao --- src/corelib/tools/qlist.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/corelib/tools/qlist.h b/src/corelib/tools/qlist.h index 1edac03..84c7424 100644 --- a/src/corelib/tools/qlist.h +++ b/src/corelib/tools/qlist.h @@ -122,7 +122,7 @@ public: inline int size() const { return p.size(); } inline void detach() { if (d->ref != 1) detach_helper(); } - inline void detach_grow(int by) { if (d->ref != 1) detach_helper_grow(d->end - d->begin + by); } + inline void detach_grow(int by) { if (d->ref != 1) detach_helper_grow(d->alloc + by); } inline void detachShared() { -- cgit v0.12 From 4145038db1e87f3438233ea7822a3a81f657c334 Mon Sep 17 00:00:00 2001 From: Kai Koehne Date: Thu, 18 Feb 2010 09:56:11 +0100 Subject: Revert optimizations to QString::append This reverts commit 03ac778172b783d26bb1c7c5d92bdedd045fcc92 and commit 02135be18f3c4b1d1525aff6dfe96c9c8521084d. They broke qt on all platforms (e.g. qmake didn't compile on Windows any more). --- src/corelib/tools/qlist.cpp | 18 ------------------ src/corelib/tools/qlist.h | 28 ++++------------------------ 2 files changed, 4 insertions(+), 42 deletions(-) diff --git a/src/corelib/tools/qlist.cpp b/src/corelib/tools/qlist.cpp index a468c77..ac0dc46 100644 --- a/src/corelib/tools/qlist.cpp +++ b/src/corelib/tools/qlist.cpp @@ -154,19 +154,6 @@ QListData::Data *QListData::detach(int alloc) } /*! - * Detaches the QListData by allocating new memory for a list which will be bigger - * than the copied one and is expected to grow further. - * Returns the old (shared) data, it is up to the caller to deref() and free() - * For the new data node_copy needs to be called. - * - * \internal - */ -QListData::Data *QListData::detach_grow(int alloc) -{ - return detach(grow(alloc)); -} - -/*! * Detaches the QListData by reallocating new memory. * Returns the old (shared) data, it is up to the caller to deref() and free() * For the new data node_copy needs to be called. @@ -609,11 +596,6 @@ void **QListData::erase(void **xi) \internal */ -/*! \fn void QList::detach_grow(int alloc) - - \internal -*/ - /*! \fn void QList::detachShared() \internal diff --git a/src/corelib/tools/qlist.h b/src/corelib/tools/qlist.h index 84c7424..8c75c98 100644 --- a/src/corelib/tools/qlist.h +++ b/src/corelib/tools/qlist.h @@ -73,7 +73,6 @@ struct Q_CORE_EXPORT QListData { enum { DataHeaderSize = sizeof(Data) - sizeof(void *) }; Data *detach(int alloc); - Data *detach_grow(int alloc); Data *detach(); // remove in 5.0 Data *detach2(); // remove in 5.0 Data *detach3(); // remove in 5.0 @@ -122,7 +121,6 @@ public: inline int size() const { return p.size(); } inline void detach() { if (d->ref != 1) detach_helper(); } - inline void detach_grow(int by) { if (d->ref != 1) detach_helper_grow(d->alloc + by); } inline void detachShared() { @@ -335,7 +333,6 @@ public: #endif private: - void detach_helper_grow(int alloc); void detach_helper(int alloc); void detach_helper(); void free(QListData::Data *d); @@ -483,7 +480,7 @@ Q_OUTOFLINE_TEMPLATE void QList::reserve(int alloc) template Q_OUTOFLINE_TEMPLATE void QList::append(const T &t) { - detach_grow(1); + detach(); if (QTypeInfo::isLarge || QTypeInfo::isStatic) { Node *n = reinterpret_cast(p.append()); QT_TRY { @@ -507,7 +504,7 @@ Q_OUTOFLINE_TEMPLATE void QList::append(const T &t) template inline void QList::prepend(const T &t) { - detach_grow(1); + detach(); if (QTypeInfo::isLarge || QTypeInfo::isStatic) { Node *n = reinterpret_cast(p.prepend()); QT_TRY { @@ -531,7 +528,7 @@ inline void QList::prepend(const T &t) template inline void QList::insert(int i, const T &t) { - detach_grow(1); + detach(); if (QTypeInfo::isLarge || QTypeInfo::isStatic) { Node *n = reinterpret_cast(p.insert(i)); QT_TRY { @@ -625,23 +622,6 @@ Q_OUTOFLINE_TEMPLATE T QList::value(int i, const T& defaultValue) const } template -Q_OUTOFLINE_TEMPLATE void QList::detach_helper_grow(int alloc) -{ - Node *n = reinterpret_cast(p.begin()); - QListData::Data *x = p.detach_grow(alloc); - QT_TRY { - node_copy(reinterpret_cast(p.begin()), reinterpret_cast(p.end()), n); - } QT_CATCH(...) { - qFree(d); - d = x; - QT_RETHROW; - } - - if (!x->ref.deref()) - free(x); -} - -template Q_OUTOFLINE_TEMPLATE void QList::detach_helper(int alloc) { Node *n = reinterpret_cast(p.begin()); @@ -750,7 +730,7 @@ Q_OUTOFLINE_TEMPLATE typename QList::iterator QList::erase(typename QList< template Q_OUTOFLINE_TEMPLATE QList &QList::operator+=(const QList &l) { - detach_grow(l.size()); + detach(); Node *n = reinterpret_cast(p.append2(l.p)); QT_TRY{ node_copy(n, reinterpret_cast(p.end()), reinterpret_cast(l.p.begin())); -- cgit v0.12 From 26c367b9b9e220056af3a47eced366d6d187a890 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Thu, 18 Feb 2010 16:03:22 +0100 Subject: optimize qstring::simplified() - avoid detaching if the string is already simplified - avoid calling isSpace() multiple times on the same character Reviewed-by: joao --- src/corelib/tools/qstring.cpp | 82 ++++++++++++++++++++++++++++++-------- tests/auto/qstring/tst_qstring.cpp | 50 +++++++++++++++++++---- 2 files changed, 109 insertions(+), 23 deletions(-) diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp index cce313b..ac1bee7 100644 --- a/src/corelib/tools/qstring.cpp +++ b/src/corelib/tools/qstring.cpp @@ -3995,24 +3995,74 @@ QString QString::simplified() const { if (d->size == 0) return *this; - QString result(d->size, Qt::Uninitialized); - const QChar *from = (const QChar*) d->data; - const QChar *fromend = (const QChar*) from+d->size; - int outc=0; - QChar *to = (QChar*) result.d->data; - for (;;) { - while (from!=fromend && from->isSpace()) - from++; - while (from!=fromend && !from->isSpace()) - to[outc++] = *from++; - if (from!=fromend) - to[outc++] = QLatin1Char(' '); - else + + const QChar * const start = reinterpret_cast(d->data); + const QChar *from = start; + const QChar *fromEnd = start + d->size; + forever { + QChar ch = *from; + if (!ch.isSpace()) + break; + if (++from == fromEnd) { + // All-whitespace string + shared_empty.ref.ref(); + return QString(&shared_empty, 0); + } + } + // This loop needs no underflow check, as we already determined that + // the string contains non-whitespace. If the string has exactly one + // non-whitespace, it will be checked twice - we can live with that. + while (fromEnd[-1].isSpace()) + fromEnd--; + // The rest of the function depends on the fact that we already know + // that the last character in the source is no whitespace. + const QChar *copyFrom = from; + int copyCount; + forever { + if (++from == fromEnd) { + // Only leading and/or trailing whitespace, if any at all + return mid(copyFrom - start, from - copyFrom); + } + QChar ch = *from; + if (!ch.isSpace()) + continue; + if (ch != QLatin1Char(' ')) { + copyCount = from - copyFrom; break; + } + ch = *++from; + if (ch.isSpace()) { + copyCount = from - copyFrom - 1; + break; + } + } + // 'from' now points at the non-trailing whitespace which made the + // string not simplified in the first place. 'copyCount' is the number + // of already simplified characters - at least one, obviously - + // without a trailing space. + QString result((fromEnd - from) + copyCount, Qt::Uninitialized); + QChar *to = reinterpret_cast(result.d->data); + ::memcpy(to, copyFrom, copyCount * 2); + to += copyCount; + fromEnd--; + QChar ch; + forever { + *to++ = QLatin1Char(' '); + do { + ch = *++from; + } while (ch.isSpace()); + if (from == fromEnd) + break; + do { + *to++ = ch; + ch = *++from; + if (from == fromEnd) + goto done; + } while (!ch.isSpace()); } - if (outc > 0 && to[outc-1] == QLatin1Char(' ')) - outc--; - result.truncate(outc); + done: + *to++ = ch; + result.truncate(to - reinterpret_cast(result.d->data)); return result; } diff --git a/tests/auto/qstring/tst_qstring.cpp b/tests/auto/qstring/tst_qstring.cpp index c9b3436..9c9524a 100644 --- a/tests/auto/qstring/tst_qstring.cpp +++ b/tests/auto/qstring/tst_qstring.cpp @@ -120,6 +120,7 @@ private slots: void operator_eqeq_nullstring(); void operator_smaller(); void insert(); + void simplified_data(); void simplified(); void trimmed(); void toLower(); @@ -1592,16 +1593,51 @@ void tst_QString::trimmed() QCOMPARE(a.trimmed(),(QString)"a"); } +void tst_QString::simplified_data() +{ + QTest::addColumn("full" ); + QTest::addColumn("simple" ); + + QTest::newRow("null") << QString() << QString(); + QTest::newRow("empty") << "" << ""; + QTest::newRow("one char") << "a" << "a"; + QTest::newRow("one word") << "foo" << "foo"; + QTest::newRow("chars trivial") << "a b" << "a b"; + QTest::newRow("words trivial") << "foo bar" << "foo bar"; + QTest::newRow("allspace") << " \t\v " << ""; + QTest::newRow("char trailing") << "a " << "a"; + QTest::newRow("char trailing tab") << "a\t" << "a"; + QTest::newRow("char multitrailing") << "a " << "a"; + QTest::newRow("char multitrailing tab") << "a \t" << "a"; + QTest::newRow("char leading") << " a" << "a"; + QTest::newRow("char leading tab") << "\ta" << "a"; + QTest::newRow("char multileading") << " a" << "a"; + QTest::newRow("char multileading tab") << "\t a" << "a"; + QTest::newRow("chars apart") << "a b" << "a b"; + QTest::newRow("words apart") << "foo bar" << "foo bar"; + QTest::newRow("enclosed word") << " foo \t " << "foo"; + QTest::newRow("enclosed chars apart") << " a b " << "a b"; + QTest::newRow("enclosed words apart") << " foo bar " << "foo bar"; + QTest::newRow("chars apart posttab") << "a \tb" << "a b"; + QTest::newRow("chars apart pretab") << "a\t b" << "a b"; + QTest::newRow("many words") << " just some random\ttext here" << "just some random text here"; +} + void tst_QString::simplified() { - QString j; - j.simplified(); + QFETCH(QString, full); + QFETCH(QString, simple); - QString a; - a = "a "; - QCOMPARE(a.simplified(),(QString)"a"); - a=" a b "; - QCOMPARE(a.simplified(),(QString)"a b"); + QString result = full.simplified(); + if (simple.isNull()) { + QVERIFY2(result.isNull(), qPrintable("'" + full + "' did not yield null: " + result)); + } else if (simple.isEmpty()) { + QVERIFY2(result.isEmpty() && !result.isNull(), qPrintable("'" + full + "' did not yield empty: " + result)); + } else { + QCOMPARE(result, simple); + if (full == simple) + QVERIFY(result.isSharedWith(full)); + } } void tst_QString::insert() -- cgit v0.12