From 9215506e6a057d8aef7415c2921214e1ba1c760d Mon Sep 17 00:00:00 2001 From: "Bradley T. Hughes" Date: Thu, 10 Dec 2009 09:15:34 +0100 Subject: Prevent posted event starvation by native Windows messages Avoid live-lock if native messages are generated quickly enough by allowing posted events to be sent if more than 10ms has passed since we last sent them. This means that we can allow multiple calls to sendPostedEvents() during a single call to processEvents(), but only when the QEventLoop::EventLoopExec flag is passed to processEvents(). Task-number: QTBUG-1697 --- src/corelib/kernel/qeventdispatcher_win.cpp | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/corelib/kernel/qeventdispatcher_win.cpp b/src/corelib/kernel/qeventdispatcher_win.cpp index c6eef5e..105cf28 100644 --- a/src/corelib/kernel/qeventdispatcher_win.cpp +++ b/src/corelib/kernel/qeventdispatcher_win.cpp @@ -341,6 +341,7 @@ public: // for controlling when to send posted events QAtomicInt serialNumber; int lastSerialNumber; + int lastMessageTime; QAtomicInt wakeUps; // timers @@ -364,7 +365,8 @@ public: }; QEventDispatcherWin32Private::QEventDispatcherWin32Private() - : threadId(GetCurrentThreadId()), interrupt(false), internalHwnd(0), getMessageHook(0), serialNumber(0), lastSerialNumber(0), wakeUps(0) + : threadId(GetCurrentThreadId()), interrupt(false), internalHwnd(0), getMessageHook(0), + serialNumber(0), lastSerialNumber(0), lastMessageTime(0), wakeUps(0) { resolveTimerAPI(); } @@ -479,6 +481,7 @@ LRESULT CALLBACK qt_internal_proc(HWND hwnd, UINT message, WPARAM wp, LPARAM lp) int localSerialNumber = d->serialNumber; if (localSerialNumber != d->lastSerialNumber) { d->lastSerialNumber = localSerialNumber; + d->lastMessageTime = GetMessageTime(); QCoreApplicationPrivate::sendPostedEvents(0, 0, d->threadData); } return 0; @@ -495,9 +498,10 @@ LRESULT CALLBACK qt_GetMessageHook(int code, WPARAM wp, LPARAM lp) if (q) { QEventDispatcherWin32Private *d = q->d_func(); int localSerialNumber = d->serialNumber; - if (HIWORD(GetQueueStatus(QS_INPUT | QS_RAWINPUT | QS_TIMER)) == 0) { - // no more input or timer events in the message queue, we can allow posted events to be - // sent now + if (HIWORD(GetQueueStatus(QS_INPUT | QS_RAWINPUT | QS_TIMER)) == 0 + || GetMessageTime() - d->lastMessageTime >= 10) { + // no more input or timer events in the message queue or more than 10ms has elapsed since + // we send posted events, we can allow posted events to be sent now (void) d->wakeUps.fetchAndStoreRelease(0); MSG *msg = (MSG *) lp; if (localSerialNumber != d->lastSerialNumber @@ -732,7 +736,9 @@ bool QEventDispatcherWin32::processEvents(QEventLoop::ProcessEventsFlags flags) } if (haveMessage) { if (d->internalHwnd == msg.hwnd && msg.message == WM_QT_SENDPOSTEDEVENTS) { - if (seenWM_QT_SENDPOSTEDEVENTS) { + if (seenWM_QT_SENDPOSTEDEVENTS && !(flags & QEventLoop::EventLoopExec)) { + // when calling processEvents() "manually", we only want to send posted + // events once needWM_QT_SENDPOSTEDEVENTS = true; continue; } -- cgit v0.12 From d7159b1aa1c24cc320a3ba013c9d0f3cf97b6684 Mon Sep 17 00:00:00 2001 From: Richard Moe Gustavsen Date: Thu, 10 Dec 2009 11:32:33 +0100 Subject: Mac: add support for public.vcard UTI (DnD) Added a QMacPasteboard converter for data dragged from the address book on Mac. It is an easy piece of code, and will make it easier for Mac people to work with standard Mac apps. --- src/gui/kernel/qmime_mac.cpp | 57 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/src/gui/kernel/qmime_mac.cpp b/src/gui/kernel/qmime_mac.cpp index 4d842df..c68cdde 100644 --- a/src/gui/kernel/qmime_mac.cpp +++ b/src/gui/kernel/qmime_mac.cpp @@ -154,6 +154,7 @@ CFStringRef qt_mac_mime_typeUTI = CFSTR("com.pasteboard.trolltech.marker"); \i public.url - converts to "text/uri-list" \i public.file-url - converts to "text/uri-list" \i public.tiff - converts to "application/x-qt-image" + \i public.vcard - converts to "text/plain" \i com.apple.traditional-mac-plain-text - converts to "text/plain" \i com.apple.pict - converts to "application/x-qt-image" \endlist @@ -909,6 +910,61 @@ QList QMacPasteboardMimeUrl::convertFromMime(const QString &mime, QV return ret; } +class QMacPasteboardMimeVCard : public QMacPasteboardMime +{ +public: + QMacPasteboardMimeVCard() : QMacPasteboardMime(MIME_ALL){ } + QString convertorName(); + + QString flavorFor(const QString &mime); + QString mimeFor(QString flav); + bool canConvert(const QString &mime, QString flav); + QVariant convertToMime(const QString &mime, QList data, QString flav); + QList convertFromMime(const QString &mime, QVariant data, QString flav); +}; + +QString QMacPasteboardMimeVCard::convertorName() +{ + return QString("VCard"); +} + +bool QMacPasteboardMimeVCard::canConvert(const QString &mime, QString flav) +{ + return mimeFor(flav) == mime; +} + +QString QMacPasteboardMimeVCard::flavorFor(const QString &mime) +{ + if(mime.startsWith(QLatin1String("text/plain"))) + return QLatin1String("public.vcard"); + return QString(); +} + +QString QMacPasteboardMimeVCard::mimeFor(QString flav) +{ + if (flav == QLatin1String("public.vcard")) + return QLatin1String("text/plain"); + return QString(); +} + +QVariant QMacPasteboardMimeVCard::convertToMime(const QString &mime, QList data, QString) +{ + QByteArray cards; + if (mime == QLatin1String("text/plain")) { + for (int i=0; i QMacPasteboardMimeVCard::convertFromMime(const QString &mime, QVariant data, QString) +{ + QList ret; + if (mime == QLatin1String("text/plain")) + ret.append(data.toString().toUtf8()); + return ret; +} + #ifdef QT3_SUPPORT class QMacPasteboardMimeQt3Any : public QMacPasteboardMime { private: @@ -1116,6 +1172,7 @@ void QMacPasteboardMime::initialize() new QMacPasteboardMimeFileUri; new QMacPasteboardMimeUrl; new QMacPasteboardMimeTypeName; + new QMacPasteboardMimeVCard; //make sure our "non-standard" types are always last! --Sam new QMacPasteboardMimeAny; #ifdef QT3_SUPPORT -- cgit v0.12 From 4a982617bf6de92df118ecac024f415770a7bbb6 Mon Sep 17 00:00:00 2001 From: ck Date: Thu, 10 Dec 2009 15:20:35 +0100 Subject: Assistant: Added rebuild-search-index command line option. Reviewed-by: kh1 --- tools/assistant/tools/assistant/cmdlineparser.cpp | 10 ++++++++ tools/assistant/tools/assistant/cmdlineparser.h | 2 ++ tools/assistant/tools/assistant/main.cpp | 31 ++++++++++++++++++++--- 3 files changed, 40 insertions(+), 3 deletions(-) diff --git a/tools/assistant/tools/assistant/cmdlineparser.cpp b/tools/assistant/tools/assistant/cmdlineparser.cpp index 733e2ff..a93d63f 100644 --- a/tools/assistant/tools/assistant/cmdlineparser.cpp +++ b/tools/assistant/tools/assistant/cmdlineparser.cpp @@ -72,6 +72,7 @@ const QString CmdLineParser::m_helpMessage = QLatin1String( " file.\n" "-setCurrentFilter filter Set the filter as the active filter.\n" "-remove-search-index Removes the full text search index.\n" + "-rebuild-search-index Re-builds the full text search index (potentially slow)\n." "-quiet Does not display any error or\n" " status message.\n" "-help Displays this help.\n" @@ -87,6 +88,7 @@ CmdLineParser::CmdLineParser(const QStringList &arguments) m_search(Untouched), m_register(None), m_removeSearchIndex(false), + m_rebuildSearchIndex(false), m_quiet(false) { TRACE_OBJ @@ -126,6 +128,8 @@ CmdLineParser::Result CmdLineParser::parse() handleSetCurrentFilterOption(); else if (arg == QLatin1String("-remove-search-index")) m_removeSearchIndex = true; + else if (arg == QLatin1String("-rebuild-search-index")) + m_rebuildSearchIndex = true; else if (arg == QLatin1String("-help")) showHelp = true; else @@ -343,6 +347,12 @@ bool CmdLineParser::removeSearchIndex() const return m_removeSearchIndex; } +bool CmdLineParser::rebuildSearchIndex() const +{ + TRACE_OBJ + return m_rebuildSearchIndex; +} + CmdLineParser::RegisterState CmdLineParser::registerRequest() const { TRACE_OBJ diff --git a/tools/assistant/tools/assistant/cmdlineparser.h b/tools/assistant/tools/assistant/cmdlineparser.h index c1621d6..2bc7f2a 100644 --- a/tools/assistant/tools/assistant/cmdlineparser.h +++ b/tools/assistant/tools/assistant/cmdlineparser.h @@ -70,6 +70,7 @@ public: ShowState search() const; QString currentFilter() const; bool removeSearchIndex() const; + bool rebuildSearchIndex() const; RegisterState registerRequest() const; QString helpFile() const; @@ -106,6 +107,7 @@ private: RegisterState m_register; QString m_currentFilter; bool m_removeSearchIndex; + bool m_rebuildSearchIndex; bool m_quiet; QString m_error; }; diff --git a/tools/assistant/tools/assistant/main.cpp b/tools/assistant/tools/assistant/main.cpp index 79ed2c8..ce85854 100644 --- a/tools/assistant/tools/assistant/main.cpp +++ b/tools/assistant/tools/assistant/main.cpp @@ -52,7 +52,8 @@ #include #include -#include +#include +#include #include @@ -205,6 +206,23 @@ bool removeSearchIndex(const QString &collectionFile) return true; } +bool rebuildSearchIndex(QCoreApplication &app, const QString &collectionFile, + CmdLineParser &cmd) +{ + TRACE_OBJ + QHelpEngine engine(collectionFile); + if (!engine.setupData()) { + cmd.showMessage(QObject::tr("Error: %1").arg(engine.error()), true); + return false; + } + + QHelpSearchEngine * const searchEngine = engine.searchEngine(); + QObject::connect(searchEngine, SIGNAL(indexingFinished()), &app, + SLOT(quit())); + searchEngine->reindexDocumentation(); + return app.exec() == 0; +} + bool checkForSqlite(CmdLineParser &cmd) { TRACE_OBJ @@ -225,7 +243,8 @@ bool useGui(int argc, char *argv[]) #ifndef Q_OS_WIN // Look for arguments that imply command-line mode. const char * cmdModeArgs[] = { - "-help", "-register", "-unregister", "-remove-search-index" + "-help", "-register", "-unregister", "-remove-search-index", + "-rebuild-search-index" }; for (int i = 1; i < argc; ++i) { for (size_t j = 0; j < sizeof cmdModeArgs/sizeof *cmdModeArgs; ++j) { @@ -376,7 +395,13 @@ int main(int argc, char *argv[]) } if (cmd.removeSearchIndex()) { - return removeSearchIndex(cachedCollectionFile) ? EXIT_SUCCESS : EXIT_FAILURE; + return removeSearchIndex(cachedCollectionFile) + ? EXIT_SUCCESS : EXIT_FAILURE; + } + + if (cmd.rebuildSearchIndex()) { + return rebuildSearchIndex(a, cachedCollectionFile, cmd) + ? EXIT_SUCCESS : EXIT_FAILURE; } if (!checkForSqlite(cmd)) -- cgit v0.12 From 46e080ba1b0b7fdb67eda60002991f6b20e0f0ab Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Thu, 10 Dec 2009 12:58:06 +0100 Subject: fix (internal) apidoc --- src/corelib/tools/qstring.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp index 33c45c4..98d88ac 100644 --- a/src/corelib/tools/qstring.cpp +++ b/src/corelib/tools/qstring.cpp @@ -1092,7 +1092,7 @@ QString::QString(QChar ch) \internal */ -/*! \fn void QString::isDetached() const +/*! \fn bool QString::isDetached() const \internal */ -- cgit v0.12 From b6352d487491e4d25db8a008de75280a666b0fce Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Thu, 10 Dec 2009 15:38:17 +0100 Subject: add {QString,QByteArray,QList,QLinkedList,QHash,QMap,QVector}::isSharedWith() these functions just compare the d pointers of two objects. this can be used to verify the validity of cached data: you keep a copy of the original data in your cache. consequently, any changes to the original data must detach, so this function reflects whether the cached data is still up-to-date. of course, this is not thread safe, as the data might change right after you check it, but that's a general problem of cache coherency which needs to be handled further up the stack. the functions are internal because the other detaching-related functions are internal as well for reasons beyond me. Reviewed-by: brad --- src/corelib/tools/qbytearray.cpp | 5 +++++ src/corelib/tools/qbytearray.h | 1 + src/corelib/tools/qhash.cpp | 5 +++++ src/corelib/tools/qhash.h | 1 + src/corelib/tools/qlinkedlist.cpp | 5 +++++ src/corelib/tools/qlinkedlist.h | 1 + src/corelib/tools/qlist.cpp | 5 +++++ src/corelib/tools/qlist.h | 1 + src/corelib/tools/qmap.cpp | 5 +++++ src/corelib/tools/qmap.h | 1 + src/corelib/tools/qstring.cpp | 5 +++++ src/corelib/tools/qstring.h | 1 + src/corelib/tools/qvector.cpp | 5 +++++ src/corelib/tools/qvector.h | 1 + 14 files changed, 42 insertions(+) diff --git a/src/corelib/tools/qbytearray.cpp b/src/corelib/tools/qbytearray.cpp index bf9b6bd..e43c2b5 100644 --- a/src/corelib/tools/qbytearray.cpp +++ b/src/corelib/tools/qbytearray.cpp @@ -1048,6 +1048,11 @@ QByteArray &QByteArray::operator=(const char *str) \internal */ +/*! \fn bool QByteArray::isSharedWith(const QByteArray &other) + + \internal +*/ + /*! \fn char QByteArray::at(int i) const Returns the character at index position \a i in the byte array. diff --git a/src/corelib/tools/qbytearray.h b/src/corelib/tools/qbytearray.h index 7dd6f4f..ba344cb 100644 --- a/src/corelib/tools/qbytearray.h +++ b/src/corelib/tools/qbytearray.h @@ -164,6 +164,7 @@ public: inline const char *constData() const; inline void detach(); bool isDetached() const; + inline bool isSharedWith(const QByteArray &other) const { return d == other.d; } void clear(); #ifdef Q_COMPILER_MANGLES_RETURN_TYPE diff --git a/src/corelib/tools/qhash.cpp b/src/corelib/tools/qhash.cpp index c82c389..a616ac2 100644 --- a/src/corelib/tools/qhash.cpp +++ b/src/corelib/tools/qhash.cpp @@ -847,6 +847,11 @@ void QHashData::checkSanity() \internal */ +/*! \fn bool QHash::isSharedWith(const QHash &other) const + + \internal +*/ + /*! \fn void QHash::clear() Removes all items from the hash. diff --git a/src/corelib/tools/qhash.h b/src/corelib/tools/qhash.h index 2de03dc..66e9cde 100644 --- a/src/corelib/tools/qhash.h +++ b/src/corelib/tools/qhash.h @@ -299,6 +299,7 @@ public: inline void detach() { if (d->ref != 1) detach_helper(); } inline bool isDetached() const { return d->ref == 1; } inline void setSharable(bool sharable) { if (!sharable) detach(); d->sharable = sharable; } + inline bool isSharedWith(const QHash &other) const { return d == other.d; } void clear(); diff --git a/src/corelib/tools/qlinkedlist.cpp b/src/corelib/tools/qlinkedlist.cpp index 281508e..987e538 100644 --- a/src/corelib/tools/qlinkedlist.cpp +++ b/src/corelib/tools/qlinkedlist.cpp @@ -197,6 +197,11 @@ QLinkedListData QLinkedListData::shared_null = { \internal */ +/*! \fn bool QLinkedList::isSharedWith(const QLinkedList &other) const + + \internal +*/ + /*! \fn bool QLinkedList::isEmpty() const Returns true if the list contains no items; otherwise returns diff --git a/src/corelib/tools/qlinkedlist.h b/src/corelib/tools/qlinkedlist.h index e119a50..395adf2 100644 --- a/src/corelib/tools/qlinkedlist.h +++ b/src/corelib/tools/qlinkedlist.h @@ -93,6 +93,7 @@ public: { if (d->ref != 1) detach_helper(); } inline bool isDetached() const { return d->ref == 1; } inline void setSharable(bool sharable) { if (!sharable) detach(); d->sharable = sharable; } + inline bool isSharedWith(const QLinkedList &other) const { return d == other.d; } inline bool isEmpty() const { return d->size == 0; } diff --git a/src/corelib/tools/qlist.cpp b/src/corelib/tools/qlist.cpp index 9b20c82..da93d5f 100644 --- a/src/corelib/tools/qlist.cpp +++ b/src/corelib/tools/qlist.cpp @@ -599,6 +599,11 @@ void **QListData::erase(void **xi) \internal */ +/*! \fn bool QList::isSharedWith(const QList &other) const + + \internal +*/ + /*! \fn bool QList::isEmpty() const Returns true if the list contains no items; otherwise returns diff --git a/src/corelib/tools/qlist.h b/src/corelib/tools/qlist.h index 49b5c0d..e65ee15 100644 --- a/src/corelib/tools/qlist.h +++ b/src/corelib/tools/qlist.h @@ -130,6 +130,7 @@ public: inline bool isDetached() const { return d->ref == 1; } inline void setSharable(bool sharable) { if (!sharable) detach(); d->sharable = sharable; } + inline bool isSharedWith(const QList &other) const { return d == other.d; } inline bool isEmpty() const { return p.isEmpty(); } diff --git a/src/corelib/tools/qmap.cpp b/src/corelib/tools/qmap.cpp index 3b48c3f..432b5a5 100644 --- a/src/corelib/tools/qmap.cpp +++ b/src/corelib/tools/qmap.cpp @@ -473,6 +473,11 @@ void QMapData::dump() \internal */ +/*! \fn bool QMap::isSharedWith(const QMap &other) const + + \internal +*/ + /*! \fn void QMap::setInsertInOrder(bool sharable) \internal diff --git a/src/corelib/tools/qmap.h b/src/corelib/tools/qmap.h index 0441107..ce97178 100644 --- a/src/corelib/tools/qmap.h +++ b/src/corelib/tools/qmap.h @@ -182,6 +182,7 @@ public: inline void detach() { if (d->ref != 1) detach_helper(); } inline bool isDetached() const { return d->ref == 1; } inline void setSharable(bool sharable) { if (!sharable) detach(); d->sharable = sharable; } + inline bool isSharedWith(const QMap &other) const { return d == other.d; } inline void setInsertInOrder(bool ordered) { d->insertInOrder = ordered; } void clear(); diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp index 98d88ac..f3355df 100644 --- a/src/corelib/tools/qstring.cpp +++ b/src/corelib/tools/qstring.cpp @@ -1097,6 +1097,11 @@ QString::QString(QChar ch) \internal */ +/*! \fn bool QString::isSharedWith(const QString &other) const + + \internal +*/ + // ### Qt 5: rename freeData() to avoid confusion. See task 197625. void QString::free(Data *d) { diff --git a/src/corelib/tools/qstring.h b/src/corelib/tools/qstring.h index 668be35..c6fd80a 100644 --- a/src/corelib/tools/qstring.h +++ b/src/corelib/tools/qstring.h @@ -122,6 +122,7 @@ public: inline void detach(); inline bool isDetached() const; + inline bool isSharedWith(const QString &other) const { return d == other.d; } void clear(); inline const QChar at(int i) const; diff --git a/src/corelib/tools/qvector.cpp b/src/corelib/tools/qvector.cpp index 8bb1074..00d663b 100644 --- a/src/corelib/tools/qvector.cpp +++ b/src/corelib/tools/qvector.cpp @@ -392,6 +392,11 @@ int QVectorData::grow(int sizeofTypedData, int size, int sizeofT, bool excessive \internal */ +/*! \fn bool QVector::isSharedWith(const QVector &other) const + + \internal +*/ + /*! \fn T *QVector::data() Returns a pointer to the data stored in the vector. The pointer diff --git a/src/corelib/tools/qvector.h b/src/corelib/tools/qvector.h index e00cf3f..043617f 100644 --- a/src/corelib/tools/qvector.h +++ b/src/corelib/tools/qvector.h @@ -134,6 +134,7 @@ public: inline void detach() { if (d->ref != 1) detach_helper(); } inline bool isDetached() const { return d->ref == 1; } inline void setSharable(bool sharable) { if (!sharable) detach(); d->sharable = sharable; } + inline bool isSharedWith(const QVector &other) const { return d == other.d; } inline T *data() { detach(); return p->array; } inline const T *data() const { return p->array; } -- cgit v0.12