summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--doc/global/manifest-meta.qdocconf1
-rw-r--r--qmake/doc/qmake.qdocconf49
-rw-r--r--qmake/doc/src/qmake-manual.qdoc3
-rw-r--r--src/corelib/global/qglobal.cpp2
-rw-r--r--src/network/access/qhttpmultipart.cpp3
-rw-r--r--src/plugins/platforms/cocoa/qprintengine_mac.mm5
-rw-r--r--src/plugins/platforms/windows/qwindowscontext.cpp5
-rw-r--r--src/plugins/platforms/windows/qwindowscontext.h1
-rw-r--r--src/plugins/platforms/windows/qwindowsmousehandler.h1
-rw-r--r--src/plugins/platforms/windows/qwindowswindow.cpp5
-rw-r--r--src/plugins/platforms/xcb/qxcbkeyboard.cpp69
-rw-r--r--src/plugins/platforms/xcb/qxcbkeyboard.h4
-rw-r--r--src/widgets/doc/src/modelview.qdoc32
-rw-r--r--tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp44
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();