diff options
46 files changed, 1144 insertions, 253 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 <limits.h> +#undef _POSIX_ + +#include <tchar.h> +#include <io.h> +#include <direct.h> +#include <stdio.h> +#include <fcntl.h> +#include <errno.h> +#include <sys/stat.h> +#include <stdlib.h> +#include <windows.h> + +#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 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/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; } 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<Data *>(qMalloc(DataHeaderSize + x->alloc * sizeof(void *))); + Data* t = static_cast<Data *>(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..8c75c98 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> &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<T>::takeLast() { T t = last(); removeLast(); return t; } template <typename T> +Q_OUTOFLINE_TEMPLATE void QList<T>::reserve(int alloc) +{ + if (d->alloc < alloc) { + if (d->ref != 1) + detach_helper(alloc); + else + p.realloc(alloc); + } +} + +template <typename T> Q_OUTOFLINE_TEMPLATE void QList<T>::append(const T &t) { detach(); @@ -575,11 +589,20 @@ Q_OUTOFLINE_TEMPLATE QList<T> QList<T>::mid(int pos, int alength) const alength = size() - pos; if (pos == 0 && alength == size()) return *this; - QList<T> cpy; if (pos + alength > size()) alength = size() - pos; - for (int i = pos; i < pos + alength; ++i) - cpy += at(i); + QList<T> cpy; + cpy.reserve(alength); + cpy.d->end = alength; + QT_TRY { + cpy.node_copy(reinterpret_cast<Node *>(cpy.p.begin()), + reinterpret_cast<Node *>(cpy.p.end()), + reinterpret_cast<Node *>(p.begin() + pos)); + } QT_CATCH(...) { + // restore the old end + cpy.d->end = 0; + QT_RETHROW; + } return cpy; } @@ -599,10 +622,10 @@ Q_OUTOFLINE_TEMPLATE T QList<T>::value(int i, const T& defaultValue) const } template <typename T> -Q_OUTOFLINE_TEMPLATE void QList<T>::detach_helper() +Q_OUTOFLINE_TEMPLATE void QList<T>::detach_helper(int alloc) { Node *n = reinterpret_cast<Node *>(p.begin()); - QListData::Data *x = p.detach3(); + QListData::Data *x = p.detach(alloc); QT_TRY { node_copy(reinterpret_cast<Node *>(p.begin()), reinterpret_cast<Node *>(p.end()), n); } QT_CATCH(...) { @@ -616,6 +639,12 @@ Q_OUTOFLINE_TEMPLATE void QList<T>::detach_helper() } template <typename T> +Q_OUTOFLINE_TEMPLATE void QList<T>::detach_helper() +{ + detach_helper(d->alloc); +} + +template <typename T> Q_OUTOFLINE_TEMPLATE QList<T>::~QList() { if (d && !d->ref.deref()) 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 <typename T> Q_OUTOFLINE_TEMPLATE QList<T> QSet<T>::toList() const { QList<T> result; + result.reserve(size()); typename QSet<T>::const_iterator i = constBegin(); while (i != constEnd()) { result.append(*i); diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp index dec59b7..ac1bee7 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 @@ -1766,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)); @@ -3867,7 +3902,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. @@ -3960,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<QChar *>(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<QChar *>(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<QChar *>(result.d->data)); return result; } 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); 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<T> QVector<T>::mid(int pos, int length) const length = size() - pos; if (pos == 0 && length == size()) return *this; - QVector<T> copy; if (pos + length > size()) length = size() - pos; + QVector<T> copy; + copy.reserve(length); for (int i = pos; i < pos + length; ++i) copy += at(i); return copy; @@ -740,6 +741,7 @@ template <typename T> Q_OUTOFLINE_TEMPLATE QList<T> QVector<T>::toList() const { QList<T> result; + result.reserve(size()); for (int i = 0; i < size(); ++i) result.append(at(i)); return result; diff --git a/src/gui/text/qtextcursor.cpp b/src/gui/text/qtextcursor.cpp index c81d538..c91df3c 100644 --- a/src/gui/text/qtextcursor.cpp +++ b/src/gui/text/qtextcursor.cpp @@ -1145,7 +1145,7 @@ void QTextCursor::setPosition(int pos, MoveMode m) Returns the absolute position of the cursor within the document. The cursor is positioned between characters. - \sa setPosition() movePosition() anchor() + \sa setPosition() movePosition() anchor() positionInBlock() */ int QTextCursor::position() const { @@ -1155,6 +1155,22 @@ int QTextCursor::position() const } /*! + \since 4.7 + Returns the relative position of the cursor within the block. + The cursor is positioned between characters. + + This is equivalent to \c{ position() - block().position()}. + + \sa position() +*/ +int QTextCursor::positionInBlock() const +{ + if (!d || !d->priv) + return 0; + return d->position - d->block().position(); +} + +/*! Returns the anchor position; this is the same as position() unless there is a selection in which case position() marks one end of the selection and anchor() marks the other end. Just like the cursor @@ -2414,9 +2430,17 @@ int QTextCursor::blockNumber() const return d->block().blockNumber(); } + /*! \since 4.2 Returns the position of the cursor within its containing line. + + Note that this is the column number relative to a wrapped line, + not relative to the block (i.e. the paragraph). + + You probably want to call positionInBlock() instead. + + \sa positionInBlock() */ int QTextCursor::columnNumber() const { diff --git a/src/gui/text/qtextcursor.h b/src/gui/text/qtextcursor.h index 38bc39d..3e968a3 100644 --- a/src/gui/text/qtextcursor.h +++ b/src/gui/text/qtextcursor.h @@ -89,6 +89,7 @@ public: void setPosition(int pos, MoveMode mode = MoveAnchor); int position() const; + int positionInBlock() const; int anchor() const; 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); 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<iNumDevs;i++) { if(waveOutGetDevCaps(i, &woc, sizeof(WAVEOUTCAPS)) == MMSYSERR_NOERROR) { - tmp = QString::fromUtf16((const unsigned short*)woc.szPname); + tmp = QString((const QChar *)woc.szPname); if(tmp.compare(device) == 0) { match = true; fmt = woc.dwFormats; @@ -238,7 +238,7 @@ void QAudioDeviceInfoInternal::updateLists() for(i=0;i<iNumDevs;i++) { if(waveInGetDevCaps(i, &woc, sizeof(WAVEINCAPS)) == MMSYSERR_NOERROR) { - tmp = QString::fromUtf16((const unsigned short*)woc.szPname); + tmp = QString((const QChar *)woc.szPname); if(tmp.compare(device) == 0) { match = true; fmt = woc.dwFormats; @@ -347,7 +347,7 @@ QList<QByteArray> QAudioDeviceInfoInternal::availableDevices(QAudio::Mode mode) for(i=0;i<iNumDevs;i++) { if(waveOutGetDevCaps(i, &woc, sizeof(WAVEOUTCAPS)) == MMSYSERR_NOERROR) { - devices.append(QString::fromUtf16((const unsigned short*)woc.szPname).toLocal8Bit().constData()); + devices.append(QString((const QChar *)woc.szPname).toLocal8Bit().constData()); } } } else { @@ -357,7 +357,7 @@ QList<QByteArray> QAudioDeviceInfoInternal::availableDevices(QAudio::Mode mode) for(i=0;i<iNumDevs;i++) { if(waveInGetDevCaps(i, &woc, sizeof(WAVEINCAPS)) == MMSYSERR_NOERROR) { - devices.append(QString::fromUtf16((const unsigned short*)woc.szPname).toLocal8Bit().constData()); + devices.append(QString((const QChar *)woc.szPname).toLocal8Bit().constData()); } } diff --git a/src/multimedia/audio/qaudioinput_win32_p.cpp b/src/multimedia/audio/qaudioinput_win32_p.cpp index 84fd2a5..cc4fdee 100644 --- a/src/multimedia/audio/qaudioinput_win32_p.cpp +++ b/src/multimedia/audio/qaudioinput_win32_p.cpp @@ -255,7 +255,7 @@ bool QAudioInputPrivate::open() if(waveInGetDevCaps(ii, &wic, sizeof(WAVEINCAPS)) == MMSYSERR_NOERROR) { QString tmp; - tmp = QString::fromUtf16((const unsigned short*)wic.szPname); + tmp = QString((const QChar *)wic.szPname); if(tmp.compare(QLatin1String(m_device)) == 0) { devId = ii; break; diff --git a/src/multimedia/audio/qaudiooutput_win32_p.cpp b/src/multimedia/audio/qaudiooutput_win32_p.cpp index c31e048..bce45c1 100644 --- a/src/multimedia/audio/qaudiooutput_win32_p.cpp +++ b/src/multimedia/audio/qaudiooutput_win32_p.cpp @@ -250,7 +250,7 @@ bool QAudioOutputPrivate::open() if(waveOutGetDevCaps(ii, &woc, sizeof(WAVEOUTCAPS)) == MMSYSERR_NOERROR) { QString tmp; - tmp = QString::fromUtf16((const unsigned short*)woc.szPname); + tmp = QString((const QChar *)woc.szPname); if(tmp.compare(QLatin1String(m_device)) == 0) { devId = ii; break; diff --git a/src/sql/drivers/db2/qsql_db2.cpp b/src/sql/drivers/db2/qsql_db2.cpp index d5b3984..ea0b42e 100644 --- a/src/sql/drivers/db2/qsql_db2.cpp +++ b/src/sql/drivers/db2/qsql_db2.cpp @@ -109,7 +109,7 @@ public: static QString qFromTChar(SQLTCHAR* str) { - return QString::fromUtf16(str); + return QString((const QChar *)str); } // dangerous!! (but fast). Don't use in functions that @@ -833,7 +833,7 @@ bool QDB2Result::exec() break; case QVariant::String: if (bindValueType(i) & QSql::Out) - values[i] = QString::fromUtf16((ushort*)tmpStorage.takeFirst().constData()); + values[i] = QString((const QChar *)tmpStorage.takeFirst().constData()); break; default: { values[i] = QString::fromAscii(tmpStorage.takeFirst().constData()); diff --git a/src/sql/drivers/oci/qsql_oci.cpp b/src/sql/drivers/oci/qsql_oci.cpp index 01c4124..b5c85e6 100644 --- a/src/sql/drivers/oci/qsql_oci.cpp +++ b/src/sql/drivers/oci/qsql_oci.cpp @@ -364,8 +364,8 @@ static void qOraOutValue(QVariant &value, QList<QByteArray> &storage) value = qMakeDate(storage.takeFirst()); break; case QVariant::String: - value = QString::fromUtf16( - reinterpret_cast<const ushort *>(storage.takeFirst().constData())); + value = QString( + reinterpret_cast<const QChar *>(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<const ushort *>(errbuf)); + return QString(reinterpret_cast<const QChar *>(errbuf)); } void qOraWarning(const char* msg, OCIError *err) @@ -989,8 +989,7 @@ int QOCICols::readPiecewise(QVector<QVariant> &values, int index) } else { if (isStringField) { QString str = values.at(fieldNum + index).toString(); - str += QString::fromUtf16(reinterpret_cast<const ushort *>(col), - chunkSize / 2); + str += QString(reinterpret_cast<const QChar *>(col), chunkSize / 2); values[fieldNum + index] = str; fieldInf[fieldNum].ind = 0; } else { @@ -1457,7 +1456,7 @@ bool QOCICols::execBatch(QOCIResultPrivate *d, QVector<QVariant> &boundValues, b break; case SQLT_STR: - (*list)[r] = QString::fromUtf16(reinterpret_cast<ushort *>(data + (*list)[r] = QString(reinterpret_cast<const QChar *>(data + r * columns[i].maxLen)); break; @@ -1608,7 +1607,7 @@ void QOCICols::getValues(QVector<QVariant> &v, int index) } // else fall through case QVariant::String: - v[index + i] = QString::fromUtf16(reinterpret_cast<const ushort *>(fld.data)); + v[index + i] = QString(reinterpret_cast<const QChar *>(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<ushort *>(vertxt)); + versionStr = QString(reinterpret_cast<const QChar *>(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<const ushort *>(sqlite3_errmsg16(access))), + QString(reinterpret_cast<const QChar *>(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<const ushort *>(sqlite3_column_name16(stmt, i)) + QString colName = QString(reinterpret_cast<const QChar *>( + sqlite3_column_name16(stmt, i)) ).remove(QLatin1Char('"')); // must use typeName for resolving the type to match QSqliteDriver::record - QString typeName = QString::fromUtf16( - static_cast<const ushort *>(sqlite3_column_decltype16(stmt, i))); + QString typeName = QString(reinterpret_cast<const QChar *>( + sqlite3_column_decltype16(stmt, i))); int dotIdx = colName.lastIndexOf(QLatin1Char('.')); QSqlField fld(colName.mid(dotIdx == -1 ? 0 : dotIdx + 1), qGetColumnType(typeName)); 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<QString> list; + list << "foo" << "bar" << "baz" << "bak" << "buck" << "hello" << "kitty"; + + QCOMPARE(list.mid(3, 3), + QList<QString>() << "bak" << "buck" << "hello"); +} + QTEST_APPLESS_MAIN(tst_QList) #include "tst_qlist.moc" 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<QString>("full" ); + QTest::addColumn<QString>("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() 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/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<QKeyEvent*>(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: diff --git a/tools/assistant/tools/assistant/bookmarkmanager.cpp b/tools/assistant/tools/assistant/bookmarkmanager.cpp index 8fba811..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 <QtGui/QFileDialog> #include <QtGui/QMenu> #include <QtGui/QKeyEvent> #include <QtGui/QMessageBox> #include <QtGui/QSortFilterProxyModel> -#include <QFile> -#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); @@ -187,6 +185,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())); } @@ -194,7 +196,9 @@ BookmarkManager::BookmarkManager() BookmarkManager::~BookmarkManager() { TRACE_OBJ + delete bookmarkManagerWidget; HelpEngineWrapper::instance().setBookmarks(bookmarkModel->bookmarks()); + delete bookmarkModel; } void BookmarkManager::removeItem(const QModelIndex &index) @@ -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() @@ -335,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() { @@ -348,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(); @@ -375,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 @@ -484,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 <QtCore/QCoreApplication> +#include <QtCore/QFile> +#include <QtCore/QUrl> + +#include <QtGui/QCloseEvent> +#include <QtGui/QFileDialog> +#include <QtGui/QKeySequence> +#include <QtGui/QMessageBox> +#include <QtGui/QShortcut> + +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<QKeyEvent*>(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<QMouseEvent*>(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<br> 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<QUrl>()) { + 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 <QtCore/QPersistentModelIndex> + +#include <QtGui/QMenu> + +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<QPersistentModelIndex> 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 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>BookmarkManagerWidget</class> + <widget class="QWidget" name="BookmarkManagerWidget"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>517</width> + <height>348</height> + </rect> + </property> + <property name="windowTitle"> + <string>Manage Bookmarks</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <layout class="QHBoxLayout" name="horizontalLayout"> + <item> + <spacer name="horizontalSpacer"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QLabel" name="label"> + <property name="text"> + <string>Search:</string> + </property> + </widget> + </item> + <item> + <widget class="QLineEdit" name="lineEdit"/> + </item> + </layout> + </item> + <item> + <widget class="QTreeView" name="treeView"> + <property name="acceptDrops"> + <bool>true</bool> + </property> + <property name="showDropIndicator" stdset="0"> + <bool>true</bool> + </property> + <property name="dragEnabled"> + <bool>true</bool> + </property> + <property name="autoExpandDelay"> + <number>1000</number> + </property> + <property name="uniformRowHeights"> + <bool>true</bool> + </property> + <property name="allColumnsShowFocus"> + <bool>true</bool> + </property> + <attribute name="headerDefaultSectionSize"> + <number>225</number> + </attribute> + <attribute name="headerMinimumSectionSize"> + <number>50</number> + </attribute> + <attribute name="headerDefaultSectionSize"> + <number>225</number> + </attribute> + <attribute name="headerMinimumSectionSize"> + <number>50</number> + </attribute> + </widget> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_2"> + <item> + <widget class="QPushButton" name="remove"> + <property name="text"> + <string>Remove</string> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="importExport"> + <property name="text"> + <string>Import and Backup</string> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer_2"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QPushButton" name="pushButton_5"> + <property name="text"> + <string>OK</string> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </widget> + <resources/> + <connections> + <connection> + <sender>pushButton_5</sender> + <signal>clicked()</signal> + <receiver>BookmarkManagerWidget</receiver> + <slot>close()</slot> + <hints> + <hint type="sourcelabel"> + <x>445</x> + <y>328</y> + </hint> + <hint type="destinationlabel"> + <x>340</x> + <y>313</y> + </hint> + </hints> + </connection> + </connections> +</ui> diff --git a/tools/assistant/tools/assistant/bookmarkmodel.cpp b/tools/assistant/tools/assistant/bookmarkmodel.cpp index c785f16..e446ff0 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<BookmarkItem*> (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); } @@ -299,6 +306,18 @@ BookmarkModel::itemFromIndex(const QModelIndex &index) const return rootItem; } +QList<QPersistentModelIndex> +BookmarkModel::indexListFor(const QString &label) const +{ + QList<QPersistentModelIndex> 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<QPersistentModelIndex> indexListFor(const QString &label) const; bool insertRows(int position, int rows, const QModelIndex &parent); bool removeRows(int position, int rows, const QModelIndex &parent); 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 @@ <string>Bookmarks</string> </property> <layout class="QVBoxLayout" name="verticalLayout"> + <property name="margin"> + <number>4</number> + </property> <item> <layout class="QHBoxLayout" name="horizontalLayout"> <item> diff --git a/tools/assistant/tools/assistant/centralwidget.cpp b/tools/assistant/tools/assistant/centralwidget.cpp index dd91326..f56e9e3 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) @@ -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; } @@ -514,15 +515,12 @@ void CentralWidget::setGlobalActions(const QList<QAction*> &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 <QtCore/QCoreApplication> +#include <QtCore/QFileInfo> +#include <QtCore/QStringBuilder> +#include <QtCore/QTemporaryFile> #include <QtCore/QUrl> +#include <QtGui/QDesktopServices> + QT_BEGIN_NAMESPACE +QString AbstractHelpViewer::AboutBlank = + QCoreApplication::translate("HelpViewer", "<title>about:blank</title>"); + +QString AbstractHelpViewer::LocalHelpFile = QLatin1String("qthelp://" + "com.trolltech.com.assistantinternal-1.0.0/assistant/assistant.html"); + QString AbstractHelpViewer::PageNotFoundMessage = QCoreApplication::translate("HelpViewer", "<title>Error 404...</title><div " "align=\"center\"><br><br><h1>The page could not be found</h1><br><h3>'%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 1e439dc..bba2850 100644 --- a/tools/assistant/tools/assistant/helpviewer_qtb.cpp +++ b/tools/assistant/tools/assistant/helpviewer_qtb.cpp @@ -39,7 +39,6 @@ ** ****************************************************************************/ #include "helpviewer_qtb.h" -#include "helpviewer_qwv.h" #if defined(QT_NO_WEBKIT) @@ -47,15 +46,12 @@ #include "helpenginewrapper.h" #include "tracer.h" -#include <QtCore/QDir> #include <QtCore/QStringBuilder> #include <QtGui/QContextMenuEvent> #include <QtGui/QMenu> #include <QtGui/QClipboard> #include <QtGui/QApplication> -#include <QtGui/QMessageBox> -#include <QtGui/QDesktopServices> 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 2d29774..5b38870 100644 --- a/tools/assistant/tools/assistant/helpviewer_qtb.h +++ b/tools/assistant/tools/assistant/helpviewer_qtb.h @@ -81,8 +81,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 e302b5e..9bb66e1 100644 --- a/tools/assistant/tools/assistant/helpviewer_qwv.cpp +++ b/tools/assistant/tools/assistant/helpviewer_qwv.cpp @@ -50,10 +50,8 @@ #include <QtCore/QFileInfo> #include <QtCore/QString> #include <QtCore/QStringBuilder> -#include <QtCore/QTemporaryFile> #include <QtCore/QTimer> -#include <QtGui/QDesktopServices> #include <QtGui/QWheelEvent> #include <QtNetwork/QNetworkAccessManager> @@ -212,45 +210,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 @@ -338,12 +318,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() diff --git a/tools/designer/src/lib/shared/qtresourceview.cpp b/tools/designer/src/lib/shared/qtresourceview.cpp index c15942f..859f239 100644 --- a/tools/designer/src/lib/shared/qtresourceview.cpp +++ b/tools/designer/src/lib/shared/qtresourceview.cpp @@ -664,6 +664,8 @@ QString QtResourceView::selectedResource() const void QtResourceView::selectResource(const QString &resource) { + if (resource.isEmpty()) + return; QFileInfo fi(resource); QDir dir = fi.absoluteDir(); if (fi.isDir()) diff --git a/translations/qtconfig_ru.ts b/translations/qtconfig_ru.ts index 26db840..9f74712 100644 --- a/translations/qtconfig_ru.ts +++ b/translations/qtconfig_ru.ts @@ -909,7 +909,7 @@ p, li { white-space: pre-wrap; } <a href="http://www.kde.org">http://www.kde.org</a> </p></source> <translation><p> -<a href="http://qtsoftware.com">http://qtsoftware.com</a> +<a href="http://qt.nokia.com">http://qt.nokia.com</a> </p> <p> <a href="http://www.kde.org">http://www.kde.org</a> |