Merge branch 'release' into stable
Change-Id: I5e94c4f01564df633c9925561ebb0b553bd31a2e
This commit is contained in:
commit
6a56fd3069
@ -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" \
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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.
|
||||
|
||||
|
@ -166,6 +166,7 @@ public:
|
||||
unsigned cwex_flags) const;
|
||||
|
||||
QWindow *windowUnderMouse() const;
|
||||
void clearWindowUnderMouse();
|
||||
|
||||
inline bool windowsProc(HWND hwnd, UINT message,
|
||||
QtWindows::WindowsEventType et,
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
|
Loading…
Reference in New Issue
Block a user