diff options
author | Sergio Ahumada <sergio.ahumada@digia.com> | 2013-08-09 14:04:08 +0200 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2013-08-09 16:28:34 +0200 |
commit | 08d91d4b8e72b8fe6f6a86b53c995fb548cff81b (patch) | |
tree | e33f2fdab86f5f1e49350ed0383cf688f525eea6 | |
parent | 071c48a5ff8842d43fcdc95db08b561d340a2bfd (diff) | |
parent | 6a56fd306937552dbeb53b30149288dc83d2c90b (diff) |
Merge "Merge branch 'release' into stable" into refs/staging/stable
-rw-r--r-- | doc/global/manifest-meta.qdocconf | 1 | ||||
-rw-r--r-- | qmake/doc/qmake.qdocconf | 49 | ||||
-rw-r--r-- | qmake/doc/src/qmake-manual.qdoc | 3 | ||||
-rw-r--r-- | src/corelib/global/qglobal.cpp | 2 | ||||
-rw-r--r-- | src/network/access/qhttpmultipart.cpp | 3 | ||||
-rw-r--r-- | src/plugins/platforms/cocoa/qprintengine_mac.mm | 5 | ||||
-rw-r--r-- | src/plugins/platforms/windows/qwindowscontext.cpp | 5 | ||||
-rw-r--r-- | src/plugins/platforms/windows/qwindowscontext.h | 1 | ||||
-rw-r--r-- | src/plugins/platforms/windows/qwindowsmousehandler.h | 1 | ||||
-rw-r--r-- | src/plugins/platforms/windows/qwindowswindow.cpp | 5 | ||||
-rw-r--r-- | src/plugins/platforms/xcb/qxcbkeyboard.cpp | 69 | ||||
-rw-r--r-- | src/plugins/platforms/xcb/qxcbkeyboard.h | 4 | ||||
-rw-r--r-- | src/widgets/doc/src/modelview.qdoc | 32 | ||||
-rw-r--r-- | tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp | 44 |
14 files changed, 179 insertions, 45 deletions
diff --git a/doc/global/manifest-meta.qdocconf b/doc/global/manifest-meta.qdocconf index a86f3a14e4..ccf3622be9 100644 --- a/doc/global/manifest-meta.qdocconf +++ b/doc/global/manifest-meta.qdocconf @@ -36,6 +36,7 @@ manifestmeta.filters = highlighted webkit1 webkit2 android manifestmeta.highlighted.names = "QtQuick/Qt Quick Demo - Same Game" \ "QtQuick/Qt Quick Demo - Photo Surface" \ + "QtQuick/Qt Quick Demo - Tweet Search" \ "QtQuick/Qt Quick Demo - Maroon*" \ "QtQuick/Qt Quick Demo - Calqlatr" \ "QtQuick/Qt Quick Particles Examples - Emitters" \ diff --git a/qmake/doc/qmake.qdocconf b/qmake/doc/qmake.qdocconf index 67e6e95650..cd8ac4d0ab 100644 --- a/qmake/doc/qmake.qdocconf +++ b/qmake/doc/qmake.qdocconf @@ -22,5 +22,54 @@ language = Cpp sources = src/qmake-manual.qdoc +depends += \ + activeqt \ + qt3d \ + qtassistant \ + qtbluetooth \ + qtconcurrent \ + qtcontacts \ + qtcore \ + qtdbus \ + qtdesigner \ + qtfeedback \ + qtgraphicaleffects \ + qtgui \ + qthelp \ + qtimageformats \ + qtlinguist \ + qtlocation \ + qtmultimedia \ + qtmultimediawidgets \ + qtnetwork \ + qtopengl \ + qtorganizer \ + qtprintsupport \ + qtpublishsubscribe \ + qtqml \ + qtquick \ + qtquickcontrols \ + qtquickcontrolsstyles \ + qtquickdialogs \ + qtquicklayouts \ + qtscript \ + qtscripttools \ + qtsensors \ + qtserialport \ + qtserviceframework \ + qtsql \ + qtsvg \ + qtsysteminfo \ + qttestlib \ + qttools \ + qtuitools \ + qtversit \ + qtwebkit \ + qtwebkitexamples \ + qtwidgets \ + qtx11extras \ + qtxml \ + qtxmlpatterns + imagedirs = src/images exampledirs = src diff --git a/qmake/doc/src/qmake-manual.qdoc b/qmake/doc/src/qmake-manual.qdoc index 2bc6cc508f..5f8672c163 100644 --- a/qmake/doc/src/qmake-manual.qdoc +++ b/qmake/doc/src/qmake-manual.qdoc @@ -851,6 +851,7 @@ \contentspage {qmake Manual}{Contents} \previouspage Reference \nextpage Replace Functions + \keyword qmake Variable Reference The fundamental behavior of qmake is influenced by variable declarations that define the build process of each project. Some of these declare resources, @@ -2422,6 +2423,7 @@ \contentspage {qmake Manual}{Contents} \previouspage Variables \nextpage Test Functions + \keyword qmake Function Reference - Replace Functions qmake provides functions for processing the contents of variables during the configuration process. These functions are called @@ -2751,6 +2753,7 @@ \title Test Functions \contentspage {qmake Manual}{Contents} \previouspage Replace Functions + \keyword qmake Function Reference - Test Functions Test functions return a boolean value that you can test for in the conditional parts of scopes. Test functions can be divided into diff --git a/src/corelib/global/qglobal.cpp b/src/corelib/global/qglobal.cpp index bcd0d06777..85cb698afc 100644 --- a/src/corelib/global/qglobal.cpp +++ b/src/corelib/global/qglobal.cpp @@ -2322,7 +2322,7 @@ Q_GLOBAL_STATIC(SeedStorage, randTLS) // Thread Local Storage for seed value */ void qsrand(uint seed) { -#if defined(Q_OS_UNIX) && !defined(QT_NO_THREAD) +#if defined(Q_OS_UNIX) && !defined(QT_NO_THREAD) && defined(_POSIX_THREAD_SAFE_FUNCTIONS) && (_POSIX_THREAD_SAFE_FUNCTIONS - 0 > 0) SeedStorage *seedStorage = randTLS(); if (seedStorage) { SeedStorageType *pseed = seedStorage->localData(); diff --git a/src/network/access/qhttpmultipart.cpp b/src/network/access/qhttpmultipart.cpp index 4397ef8205..5985ed94e0 100644 --- a/src/network/access/qhttpmultipart.cpp +++ b/src/network/access/qhttpmultipart.cpp @@ -497,7 +497,8 @@ qint64 QHttpMultiPartIODevice::readData(char *data, qint64 maxSize) // skip the parts we have already read while (index < multiPart->parts.count() && - readPointer >= partOffsets.at(index) + multiPart->parts.at(index).d->size()) + readPointer >= partOffsets.at(index) + multiPart->parts.at(index).d->size() + + multiPart->boundary.count() + 6) // 6 == 2 boundary dashes, \r\n after boundary, \r\n after multipart index++; // read the data diff --git a/src/plugins/platforms/cocoa/qprintengine_mac.mm b/src/plugins/platforms/cocoa/qprintengine_mac.mm index 2dedf99582..ee8d7ea157 100644 --- a/src/plugins/platforms/cocoa/qprintengine_mac.mm +++ b/src/plugins/platforms/cocoa/qprintengine_mac.mm @@ -187,10 +187,8 @@ void QMacPrintEnginePrivate::setPaperName(const QString &name) if (PMSessionGetCurrentPrinter(session(), &printer) == noErr) { CFArrayRef array; - if (PMPrinterGetPaperList(printer, &array) != noErr) { - PMRelease(printer); + if (PMPrinterGetPaperList(printer, &array) != noErr) return; - } int count = CFArrayGetCount(array); for (int i = 0; i < count; ++i) { PMPaper paper = static_cast<PMPaper>(const_cast<void *>(CFArrayGetValueAtIndex(array, i))); @@ -208,7 +206,6 @@ void QMacPrintEnginePrivate::setPaperName(const QString &name) } } } - PMRelease(printer); } } diff --git a/src/plugins/platforms/windows/qwindowscontext.cpp b/src/plugins/platforms/windows/qwindowscontext.cpp index 42b0ee9bfe..37a51e1fec 100644 --- a/src/plugins/platforms/windows/qwindowscontext.cpp +++ b/src/plugins/platforms/windows/qwindowscontext.cpp @@ -582,6 +582,11 @@ QWindow *QWindowsContext::windowUnderMouse() const return d->m_mouseHandler.windowUnderMouse(); } +void QWindowsContext::clearWindowUnderMouse() +{ + d->m_mouseHandler.clearWindowUnderMouse(); +} + /*! \brief Find a child window at a screen point. diff --git a/src/plugins/platforms/windows/qwindowscontext.h b/src/plugins/platforms/windows/qwindowscontext.h index d60b632beb..6b80075379 100644 --- a/src/plugins/platforms/windows/qwindowscontext.h +++ b/src/plugins/platforms/windows/qwindowscontext.h @@ -166,6 +166,7 @@ public: unsigned cwex_flags) const; QWindow *windowUnderMouse() const; + void clearWindowUnderMouse(); inline bool windowsProc(HWND hwnd, UINT message, QtWindows::WindowsEventType et, diff --git a/src/plugins/platforms/windows/qwindowsmousehandler.h b/src/plugins/platforms/windows/qwindowsmousehandler.h index caf30e6b1a..7a7b92ca7e 100644 --- a/src/plugins/platforms/windows/qwindowsmousehandler.h +++ b/src/plugins/platforms/windows/qwindowsmousehandler.h @@ -72,6 +72,7 @@ public: static Qt::MouseButtons queryMouseButtons(); QWindow *windowUnderMouse() const { return m_windowUnderMouse.data(); } + void clearWindowUnderMouse() { m_windowUnderMouse = 0; } private: inline bool translateMouseWheelEvent(QWindow *window, HWND hwnd, diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp index dcab51ce3e..e7e964a128 100644 --- a/src/plugins/platforms/windows/qwindowswindow.cpp +++ b/src/plugins/platforms/windows/qwindowswindow.cpp @@ -871,6 +871,9 @@ void QWindowsWindow::destroyWindow() qDebug() << __FUNCTION__ << this << window() << m_data.hwnd; if (m_data.hwnd) { // Stop event dispatching before Window is destroyed. setFlag(WithinDestroy); + QWindowsContext *context = QWindowsContext::instance(); + if (context->windowUnderMouse() == window()) + context->clearWindowUnderMouse(); if (hasMouseCapture()) setMouseGrabEnabled(false); unregisterDropSite(); @@ -893,7 +896,7 @@ void QWindowsWindow::destroyWindow() #endif // !Q_OS_WINCE if (m_data.hwnd != GetDesktopWindow()) DestroyWindow(m_data.hwnd); - QWindowsContext::instance()->removeWindow(m_data.hwnd); + context->removeWindow(m_data.hwnd); m_data.hwnd = 0; } } diff --git a/src/plugins/platforms/xcb/qxcbkeyboard.cpp b/src/plugins/platforms/xcb/qxcbkeyboard.cpp index 14893d9acc..d1729ed168 100644 --- a/src/plugins/platforms/xcb/qxcbkeyboard.cpp +++ b/src/plugins/platforms/xcb/qxcbkeyboard.cpp @@ -575,7 +575,7 @@ static const Qt::KeyboardModifiers ModsTbl[] = { Qt::AltModifier | Qt::ShiftModifier, // 5 Qt::AltModifier | Qt::ControlModifier, // 6 Qt::AltModifier | Qt::ShiftModifier | Qt::ControlModifier, // 7 - Qt::NoModifier // Fall-back to raw Key_* + Qt::NoModifier // Fall-back to raw Key_*, for non-latin1 kb layouts }; Qt::KeyboardModifiers QXcbKeyboard::translateModifiers(int s) const @@ -594,8 +594,9 @@ Qt::KeyboardModifiers QXcbKeyboard::translateModifiers(int s) const return ret; } -void QXcbKeyboard::readXKBConfig(struct xkb_rule_names *xkb_names) +void QXcbKeyboard::readXKBConfig() { + clearXKBConfig(); xcb_generic_error_t *error; xcb_get_property_cookie_t cookie; xcb_get_property_reply_t *config_reply; @@ -626,15 +627,30 @@ void QXcbKeyboard::readXKBConfig(struct xkb_rule_names *xkb_names) length -= len + 1; } while (p < end || i < 5); - xkb_names->rules = qstrdup(names[0]); - xkb_names->model = qstrdup(names[1]); - xkb_names->layout = qstrdup(names[2]); - xkb_names->variant = qstrdup(names[3]); - xkb_names->options = qstrdup(names[4]); + xkb_names.rules = qstrdup(names[0]); + xkb_names.model = qstrdup(names[1]); + xkb_names.layout = qstrdup(names[2]); + xkb_names.variant = qstrdup(names[3]); + xkb_names.options = qstrdup(names[4]); free(config_reply); } +void QXcbKeyboard::clearXKBConfig() +{ + if (xkb_names.rules) + delete[] xkb_names.rules; + if (xkb_names.model) + delete[] xkb_names.model; + if (xkb_names.layout) + delete[] xkb_names.layout; + if (xkb_names.variant) + delete[] xkb_names.variant; + if (xkb_names.options) + delete[] xkb_names.options; + memset(&xkb_names, 0, sizeof(xkb_names)); +} + void QXcbKeyboard::updateKeymap() { m_config = true; @@ -646,22 +662,13 @@ void QXcbKeyboard::updateKeymap() return; } } - - struct xkb_rule_names xkb_names = {0, 0, 0, 0, 0}; - - readXKBConfig(&xkb_names); + readXKBConfig(); // Compile a keymap from RMLVO (rules, models, layouts, variants and options) names if (xkb_keymap) xkb_keymap_unref(xkb_keymap); xkb_keymap = xkb_keymap_new_from_names(xkb_context, &xkb_names, (xkb_keymap_compile_flags)0); - delete[] xkb_names.rules; - delete[] xkb_names.model; - delete[] xkb_names.layout; - delete[] xkb_names.variant; - delete[] xkb_names.options; - if (!xkb_keymap) { qWarning("Qt: Failed to compile a keymap"); m_config = false; @@ -835,7 +842,7 @@ QList<int> QXcbKeyboard::possibleKeys(const QKeyEvent *event) const xkb_mod_index_t controlMod = xkb_keymap_mod_get_index(xkb_keymap, "Control"); xkb_mod_mask_t depressed; - + struct xkb_keymap *fallback_keymap = 0; int qtKey = 0; //obtain a list of possible shortcuts for the given key event for (uint i = 1; i < sizeof(ModsTbl) / sizeof(*ModsTbl) ; ++i) { @@ -851,8 +858,23 @@ QList<int> QXcbKeyboard::possibleKeys(const QKeyEvent *event) const depressed |= (1 << controlMod); // update a keyboard state from a set of explicit masks - xkb_state_update_mask(kb_state, depressed, latchedMods, lockedMods, - baseLayout, latchedLayout, lockedLayout); + if (i == 8) { + // Add a fall back key for layouts with non Latin-1 characters + if (baseQtKey > 255) { + struct xkb_rule_names names = { xkb_names.rules, xkb_names.model, "us", 0, 0 }; + fallback_keymap = xkb_keymap_new_from_names(xkb_context, &names, (xkb_keymap_compile_flags)0); + if (!fallback_keymap) + continue; + xkb_state_unref(kb_state); + kb_state = xkb_state_new(fallback_keymap); + if (!kb_state) + continue; + } else + continue; + } else { + xkb_state_update_mask(kb_state, depressed, latchedMods, lockedMods, + baseLayout, latchedLayout, lockedLayout); + } sym = xkb_state_key_get_one_sym(kb_state, event->nativeScanCode()); if (sym == XKB_KEY_NoSymbol) @@ -867,8 +889,11 @@ QList<int> QXcbKeyboard::possibleKeys(const QKeyEvent *event) const result += (qtKey + mods); } } + if (kb_state) + xkb_state_unref(kb_state); + if (fallback_keymap) + xkb_keymap_unref(fallback_keymap); - xkb_state_unref(kb_state); return result; } @@ -938,6 +963,7 @@ QXcbKeyboard::QXcbKeyboard(QXcbConnection *connection) , core_device_id(0) #endif { + memset(&xkb_names, 0, sizeof(xkb_names)); updateKeymap(); #ifndef QT_NO_XKB if (connection->hasXKB()) { @@ -979,6 +1005,7 @@ QXcbKeyboard::~QXcbKeyboard() #ifdef QT_NO_XKB xcb_key_symbols_free(m_key_symbols); #endif + clearXKBConfig(); } #ifndef QT_NO_XKB diff --git a/src/plugins/platforms/xcb/qxcbkeyboard.h b/src/plugins/platforms/xcb/qxcbkeyboard.h index 770a7eabea..0256602782 100644 --- a/src/plugins/platforms/xcb/qxcbkeyboard.h +++ b/src/plugins/platforms/xcb/qxcbkeyboard.h @@ -91,7 +91,8 @@ protected: int keysymToQtKey(xcb_keysym_t keysym) const; int keysymToQtKey(xcb_keysym_t keysym, Qt::KeyboardModifiers &modifiers, QString text) const; - void readXKBConfig(struct xkb_rule_names *names); + void readXKBConfig(); + void clearXKBConfig(); #ifdef QT_NO_XKB void updateModifiers(); @@ -107,6 +108,7 @@ private: struct xkb_context *xkb_context; struct xkb_keymap *xkb_keymap; struct xkb_state *xkb_state; + struct xkb_rule_names xkb_names; struct _mod_masks { uint alt; diff --git a/src/widgets/doc/src/modelview.qdoc b/src/widgets/doc/src/modelview.qdoc index 97d1c72e85..b2f9da9563 100644 --- a/src/widgets/doc/src/modelview.qdoc +++ b/src/widgets/doc/src/modelview.qdoc @@ -73,7 +73,7 @@ This tutorial includes example code for you to edit and integrate into your project. The tutorial's source code is located in Qt's - \c examples/tutorials/modelview directory. + \e examples/widgets/tutorials/modelview directory. For more detailed information you may also want to look at the \l{model-view-programming.html}{reference documentation} @@ -190,14 +190,14 @@ Below are 7 very simple and independent applications that show different sides of model/view programming. The source code can be found inside the - \c{examples/tutorials/modelview} directory. + \c{examples/widgets/tutorials/modelview} directory. \section2 2.1 A Read Only Table We start with an application that uses a QTableView to show data. We will add editing capabilities later. - (file source: examples/tutorials/modelview/1_readonly/main.cpp) + (file source: examples/widgets/tutorials/modelview/1_readonly/main.cpp) \snippet tutorials/modelview/1_readonly/main.cpp Quoting ModelView Tutorial We have the usual \l {modelview-part2-main-cpp.html}{main()} function: @@ -218,12 +218,12 @@ We have a table data set, so let's start with QAbstractTableModel since it is easier to use than the more general QAbstractItemModel. - (file source: examples/tutorials/modelview/1_readonly/mymodel.h) + (file source: examples/widgets/tutorials/modelview/1_readonly/mymodel.h) \snippet tutorials/modelview/1_readonly/mymodel.h Quoting ModelView Tutorial QAbstractTableModel requires the implementation of three abstract methods. - (file source: examples/tutorials/modelview/1_readonly/mymodel.cpp) + (file source: examples/widgets/tutorials/modelview/1_readonly/mymodel.cpp) \snippet tutorials/modelview/1_readonly/mymodel.cpp Quoting ModelView Tutorial The number of rows and columns is provided by @@ -259,7 +259,7 @@ result shown above. The difference is that this time we use parameter int role to return different pieces of information depending on its value. - (file source: examples/tutorials/modelview/2_formatting/mymodel.cpp) + (file source: examples/widgets/tutorials/modelview/2_formatting/mymodel.cpp) \snippet tutorials/modelview/2_formatting/mymodel.cpp Quoting ModelView Tutorial Each formatting property will be requested from the model with a separate @@ -320,7 +320,7 @@ We still have a read only table, but this time the content changes every second because we are showing the current time. - (file source: examples/tutorials/modelview/3_changingmodel/mymodel.cpp) + (file source: examples/widgets/tutorials/modelview/3_changingmodel/mymodel.cpp) \snippet tutorials/modelview/3_changingmodel/mymodel.cpp quoting mymodel_QVariant Something is missing to make the clock tick. We need to tell the view every @@ -328,12 +328,12 @@ this with a timer. In the constructor, we set its interval to 1 second and connect its timeout signal. - (file source: examples/tutorials/modelview/3_changingmodel/mymodel.cpp) + (file source: examples/widgets/tutorials/modelview/3_changingmodel/mymodel.cpp) \snippet tutorials/modelview/3_changingmodel/mymodel.cpp quoting mymodel_a Here is the corresponding slot: - (file source: examples/tutorials/modelview/3_changingmodel/mymodel.cpp) + (file source: examples/widgets/tutorials/modelview/3_changingmodel/mymodel.cpp) \snippet tutorials/modelview/3_changingmodel/mymodel.cpp quoting mymodel_b We ask the view to read the data in the top left cell again by emitting the @@ -349,7 +349,7 @@ The header content, however, is set via the model, so we reimplement the \l{QAbstractItemModel::headerData()}{headerData()} method: - (file source: examples/tutorials/modelview/4_headers/mymodel.cpp) + (file source: examples/widgets/tutorials/modelview/4_headers/mymodel.cpp) \snippet tutorials/modelview/4_headers/mymodel.cpp quoting mymodel_c Note that method \l{QAbstractItemModel::headerData()}{headerData()} also has @@ -368,7 +368,7 @@ enabled. This is done by reimplementing the following virtual methods: \l{QAbstractItemModel::}{setData()} and \l{QAbstractItemModel::}{flags()}. - (file source: examples/tutorials/modelview/5_edit/mymodel.h) + (file source: examples/widgets/tutorials/modelview/5_edit/mymodel.h) \snippet tutorials/modelview/5_edit/mymodel.h Quoting ModelView Tutorial We use \c the two-dimensional array QString \c m_gridData to store our data. @@ -377,7 +377,7 @@ interface. We have also introduced the \c editCompleted() signal, which makes it possible to transfer the modified text to the window title. - (file source: examples/tutorials/modelview/5_edit/mymodel.cpp) + (file source: examples/widgets/tutorials/modelview/5_edit/mymodel.cpp) \snippet tutorials/modelview/5_edit/mymodel.cpp quoting mymodel_e \l{QAbstractItemModel::setData()}{setData()} will be called each time the @@ -388,7 +388,7 @@ checkbox to be selected, calls would also be made with the role set to \l Qt::CheckStateRole. - (file source: examples/tutorials/modelview/5_edit/mymodel.cpp) + (file source: examples/widgets/tutorials/modelview/5_edit/mymodel.cpp) \snippet tutorials/modelview/5_edit/mymodel.cpp quoting mymodel_f Various properties of a cell can be adjusted with @@ -432,7 +432,7 @@ \image tree_2_with_algorithm.png - (file source: examples/tutorials/modelview/6_treeview/mainwindow.cpp) + (file source: examples/widgets/tutorials/modelview/6_treeview/mainwindow.cpp) \snippet tutorials/modelview/6_treeview/mainwindow.cpp Quoting ModelView Tutorial We simply instantiate a QStandardItemModel and add a couple of @@ -450,7 +450,7 @@ So let's create a couple of items: - (file source: examples/tutorials/modelview/7_selections/mainwindow.cpp) + (file source: examples/widgets/tutorials/modelview/7_selections/mainwindow.cpp) \snippet tutorials/modelview/7_selections/mainwindow.cpp quoting modelview_a Views manage selections within a separate selection model, which can be @@ -458,7 +458,7 @@ retrieve the selection Model in order to connect a slot to its \l{QAbstractItemView::}{selectionChanged()} signal. - (file source: examples/tutorials/modelview/7_selections/mainwindow.cpp) + (file source: examples/widgets/tutorials/modelview/7_selections/mainwindow.cpp) \snippet tutorials/modelview/7_selections/mainwindow.cpp quoting modelview_b We get the model index that corresponds to the selection by calling diff --git a/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp b/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp index 5c04ac8a01..ce8293edbc 100644 --- a/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp +++ b/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp @@ -221,6 +221,7 @@ private Q_SLOTS: void postToHttpSynchronous(); void postToHttpMultipart_data(); void postToHttpMultipart(); + void multipartSkipIndices(); // QTBUG-32534 #ifndef QT_NO_SSL void putToHttps_data(); void putToHttps(); @@ -2382,6 +2383,49 @@ void tst_QNetworkReply::postToHttpMultipart() QCOMPARE(replyData, expectedReplyData); } +void tst_QNetworkReply::multipartSkipIndices() // QTBUG-32534 +{ + QHttpMultiPart *multiPart = new QHttpMultiPart(QHttpMultiPart::MixedType); + QUrl url("http://" + QtNetworkSettings::serverName() + "/qtest/cgi-bin/multipart.cgi"); + QNetworkRequest request(url); + QList<QByteArray> parts; + parts << QByteArray(56083, 'X') << QByteArray(468, 'X') << QByteArray(24952, 'X'); + + QHttpPart part1; + part1.setHeader(QNetworkRequest::ContentDispositionHeader, "form-data; name=\"field1\"; filename=\"aaaa.bin\""); + part1.setHeader(QNetworkRequest::ContentTypeHeader, "application/octet-stream"); + part1.setBody(parts.at(0)); + multiPart->append(part1); + + QHttpPart part2; + part2.setHeader(QNetworkRequest::ContentDispositionHeader, "form-data; name=\"field2\"; filename=\"bbbb.txt\""); + part2.setHeader(QNetworkRequest::ContentTypeHeader, "text/plain"); + part2.setBody(parts.at(1)); + multiPart->append(part2); + + QHttpPart part3; + part3.setHeader(QNetworkRequest::ContentDispositionHeader, "form-data; name=\"text-3\"; filename=\"cccc.txt\""); + part3.setHeader(QNetworkRequest::ContentTypeHeader, "text/plain"); + part3.setBody(parts.at(2)); + multiPart->append(part3); + + QNetworkReplyPtr reply; + RUN_REQUEST(runMultipartRequest(request, reply, multiPart, "POST")); + + QCOMPARE(reply->error(), QNetworkReply::NoError); + + QCOMPARE(reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(), 200); // 200 Ok + QByteArray line; + int partIndex = 0; + while ((line = reply->readLine()) != QByteArray("")) { + if (line.startsWith("content:")) { + // before, the 3rd part would return garbled output at the end + QCOMPARE("content: " + parts[partIndex++] + "\n", line); + } + } + multiPart->deleteLater(); +} + void tst_QNetworkReply::putToHttpMultipart_data() { postToHttpMultipart_data(); |