Merge 5.5 into 5.5.1

Change-Id: I3a78e7228aa21b7c83cf7f07dc6e1c8ad0d0ebff
bb10
Oswald Buddenhagen 2015-09-11 22:22:46 +02:00
commit 8ed2fcd366
83 changed files with 903 additions and 291 deletions

View File

@ -27,24 +27,16 @@
/*!
\externalpage http://doc.qt.io/qtcreator/creator-deployment-qnx.html
\title Qt Creator: Deploying Applications to QNX Devices
\title Qt Creator: Deploying Applications to QNX Neutrino Devices
*/
/*!
\externalpage http://doc.qt.io/qtcreator/creator-developing-baremetal.html
\title Qt Creator: Connecting Bare Metal Devices
*/
/*!
\externalpage http://doc.qt.io/qtcreator/creator-developing-bb10.html
\title Qt Creator: Connecting BlackBerry 10 Devices
*/
/*!
\externalpage http://doc.qt.io/qtcreator/creator-developing-qnx.html
\title Qt Creator: Connecting QNX Devices
*/
/*!
\externalpage http://doc.qt.io/qtcreator/creator-deployment-bb10.html
\title Qt Creator: Deploying Applications to BlackBerry 10 Devices
*/
/*!
\externalpage http://doc.qt.io/qtcreator/creator-developing-generic-linux.html
\title Qt Creator: Connecting Embedded Linux Devices
@ -98,7 +90,19 @@
\title Qt Creator: Creating Screens
*/
/*!
\externalpage http://doc.qt.io/qtcreator/creator-qml-application.html
\externalpage http://doc.qt.io/qtcreator/creator-qtquick-designer-extensions.html
\title Qt Creator: Using Qt Quick Designer Extensions
*/
/*!
\externalpage http://doc.qt.io/qtcreator/qmldesigner-pathview-editor.html
\title Qt Creator: Editing PathView Properties
*/
/*!
\externalpage http://doc.qt.io/qtcreator/qmldesigner-connections.html
\title Qt Creator: Adding Connections
*/
/*!
\externalpage http://doc.qt.io/qtcreator/qtcreator-transitions-example.html
\title Qt Creator: Creating a Qt Quick Application
*/
/*!
@ -279,7 +283,7 @@
*/
/*!
\externalpage http://doc.qt.io/qtcreator/creator-testing.html
\title Qt Creator: Debugging and Analyzing
\title Qt Creator: Testing
*/
/*!
\externalpage http://doc.qt.io/qtcreator/creator-deployment.html
@ -297,10 +301,6 @@
\externalpage http://doc.qt.io/qtcreator/creator-design-mode.html
\title Qt Creator: Designing User Interfaces
*/
/*!
\externalpage http://doc.qt.io/qtcreator/creator-publish-ovi.html
\title Qt Creator: Publishing
*/
/*!
\externalpage http://doc.qt.io/qtcreator/creator-glossary.html
\title Qt Creator: Glossary
@ -476,7 +476,7 @@
\title Qt Creator: Adding Debuggers
*/
/*!
\externalpage http://doc.qt.io/qtcreator/creator-mobile-app-tutorial.html
\externalpage http://doc.qt.io/qtcreator/qtcreator-accelbubble-example.html
\title Qt Creator: Creating a Mobile Application
*/
/*!
@ -499,7 +499,19 @@
\externalpage http://doc.qt.io/qtcreator/creator-quick-ui-forms.html
\title Qt Creator: Qt Quick UI Forms
*/
/*!
\externalpage http://doc.qt.io/qtcreator/qtcreator-uiforms-example.html
\title Qt Creator: Using Qt Quick UI Forms
*/
/*!
\externalpage http://doc.qt.io/qtcreator/creator-clang-static-analyzer.html
\title Qt Creator: Using Clang Static Analyzer
*/
/*!
\externalpage http://doc.qt.io/qtcreator/creator-cpu-usage-analyzer.html
\title Qt Creator: Analyzing CPU Usage
*/
/*!
\externalpage http://doc.qt.io/qtcreator/creator-autotest.html
\title Qt Creator: Running Autotests
*/

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

View File

@ -0,0 +1,183 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the documentation of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:FDL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see http://www.qt.io/terms-conditions. For further
** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Free Documentation License Usage
** Alternatively, this file may be used under the terms of the GNU Free
** Documentation License version 1.3 as published by the Free Software
** Foundation and appearing in the file included in the packaging of
** this file. Please review the following information to ensure
** the GNU Free Documentation License version 1.3 requirements
** will be met: http://www.gnu.org/copyleft/fdl.html.
** $QT_END_LICENSE$
**
****************************************************************************/
/*!
\example desktop/systray
\title System Tray Icon Example
The System Tray Icon example shows how to add an icon with a menu
and popup messages to a desktop environment's system tray.
\image systemtray-example.png Screenshot of the System Tray Icon.
Modern operating systems usually provide a special area on the
desktop, called the system tray or notification area, where
long-running applications can display icons and short messages.
This example consists of one single class, \c Window, providing
the main application window (i.e., an editor for the system tray
icon) and the associated icon.
\image systemtray-editor.png
The editor allows the user to choose the preferred icon as well as
set the balloon message's type and duration. The user can also
edit the message's title and body. Finally, the editor provide a
checkbox controlling whether the icon is actually shown in the
system tray, or not.
\section1 Window Class Definition
The \c Window class inherits QWidget:
\snippet desktop/systray/window.h 0
We implement several private slots to respond to user
interaction. The other private functions are only convenience
functions provided to simplify the constructor.
The tray icon is an instance of the QSystemTrayIcon class. To
check whether a system tray is present on the user's desktop, call
the static QSystemTrayIcon::isSystemTrayAvailable()
function. Associated with the icon, we provide a menu containing
the typical \gui minimize, \gui maximize, \gui restore and \gui
quit actions. We reimplement the QWidget::setVisible() function to
update the tray icon's menu whenever the editor's appearance
changes, e.g., when maximizing or minimizing the main application
window.
Finally, we reimplement QWidget's \l {QWidget::}{closeEvent()}
function to be able to inform the user (when closing the editor
window) that the program will keep running in the system tray
until the user chooses the \gui Quit entry in the icon's context
menu.
\section1 Window Class Implementation
When constructing the editor widget, we first create the various
editor elements before we create the actual system tray icon:
\snippet desktop/systray/window.cpp 0
We ensure that the application responds to user input by
connecting most of the editor's input widgets (including the
system tray icon) to the application's private slots. But note the
visibility checkbox; its \l {QCheckBox::}{toggled()} signal is
connected to the \e {icon}'s \l {QSystemTrayIcon::}{setVisible()}
function instead.
\snippet desktop/systray/window.cpp 3
The \c setIcon() slot is triggered whenever the current index in
the icon combobox changes, i.e., whenever the user chooses another
icon in the editor. Note that it is also called when the user
activates the tray icon with the left mouse button, triggering the
icon's \l {QSystemTrayIcon::}{activated()} signal. We will come
back to this signal shortly.
The QSystemTrayIcon::setIcon() function sets the \l
{QSystemTrayIcon::}{icon} property that holds the actual system
tray icon. On Windows, the system tray icon size is 16x16; on X11,
the preferred size is 22x22. The icon will be scaled to the
appropriate size as necessary.
Note that on X11, due to a limitation in the system tray
specification, mouse clicks on transparent areas in the icon are
propagated to the system tray. If this behavior is unacceptable,
we suggest using an icon with no transparency.
\snippet desktop/systray/window.cpp 4
Whenever the user activates the system tray icon, it emits its \l
{QSystemTrayIcon::}{activated()} signal passing the triggering
reason as parameter. QSystemTrayIcon provides the \l
{QSystemTrayIcon::}{ActivationReason} enum to describe how the
icon was activated.
In the constructor, we connected our icon's \l
{QSystemTrayIcon::}{activated()} signal to our custom \c
iconActivated() slot: If the user has clicked the icon using the
left mouse button, this function changes the icon image by
incrementing the icon combobox's current index, triggering the \c
setIcon() slot as mentioned above. If the user activates the icon
using the middle mouse button, it calls the custom \c
showMessage() slot:
\snippet desktop/systray/window.cpp 5
When the \e showMessage() slot is triggered, we first retrieve the
message icon depending on the currently chosen message type. The
QSystemTrayIcon::MessageIcon enum describes the icon that is shown
when a balloon message is displayed. Then we call
QSystemTrayIcon's \l {QSystemTrayIcon::}{showMessage()} function
to show the message with the title, body, and icon for the time
specified in milliseconds.
OS X users note: The Growl notification system must be
installed for QSystemTrayIcon::showMessage() to display messages.
QSystemTrayIcon also has the corresponding, \l {QSystemTrayIcon::}
{messageClicked()} signal, which is emitted when the user clicks a
message displayed by \l {QSystemTrayIcon::}{showMessage()}.
\snippet desktop/systray/window.cpp 6
In the constructor, we connected the \l
{QSystemTrayIcon::}{messageClicked()} signal to our custom \c
messageClicked() slot that simply displays a message using the
QMessageBox class.
QMessageBox provides a modal dialog with a short message, an icon,
and buttons laid out depending on the current style. It supports
four severity levels: "Question", "Information", "Warning" and
"Critical". The easiest way to pop up a message box in Qt is to
call one of the associated static functions, e.g.,
QMessageBox::information().
As we mentioned earlier, we reimplement a couple of QWidget's
virtual functions:
\snippet desktop/systray/window.cpp 1
Our reimplementation of the QWidget::setVisible() function updates
the tray icon's menu whenever the editor's appearance changes,
e.g., when maximizing or minimizing the main application window,
before calling the base class implementation.
\snippet desktop/systray/window.cpp 2
We have reimplemented the QWidget::closeEvent() event handler to
receive widget close events, showing the above message to the
users when they are closing the editor window.
In addition to the functions and slots discussed above, we have
also implemented several convenience functions to simplify the
constructor: \c createIconGroupBox(), \c createMessageGroupBox(),
\c createActions() and \c createTrayIcon(). See the \l
{desktop/systray/window.cpp}{window.cpp} file for details.
*/

View File

@ -728,8 +728,7 @@
\section2 Creating and Moving Xcode Projects
Developers on OS X can take advantage of the qmake support for Xcode
project files, as described in
\l{Qt is OS X Native#Development Tools}{Qt is OS X Native},
project files, as described in \l{Additional Command-Line Options},
by running qmake to generate an Xcode project from an existing qmake project
file. For example:

View File

@ -655,6 +655,7 @@ void VcprojGenerator::writeSubDirs(QTextStream &t)
switch (which_dotnet_version(project->first("MSVC_VER").toLatin1())) {
case NET2015:
t << _slnHeader140;
break;
case NET2013:
t << _slnHeader120;
break;

View File

@ -648,7 +648,7 @@ err_free:
}
#endif // FORKFD_NO_FORKFD
#if defined(_POSIX_SPAWN) && !defined(FORKFD_NO_SPAWNFD)
#if _POSIX_SPAWN > 0 && !defined(FORKFD_NO_SPAWNFD)
int spawnfd(int flags, pid_t *ppid, const char *path, const posix_spawn_file_actions_t *file_actions,
posix_spawnattr_t *attrp, char *const argv[], char *const envp[])
{

View File

@ -29,7 +29,7 @@
#include <stdint.h>
#include <unistd.h> // to get the POSIX flags
#ifdef _POSIX_SPAWN
#if _POSIX_SPAWN > 0
# include <spawn.h>
#endif
@ -51,7 +51,7 @@ int forkfd(int flags, pid_t *ppid);
int forkfd_wait(int ffd, forkfd_info *info, struct rusage *rusage);
int forkfd_close(int ffd);
#ifdef _POSIX_SPAWN
#if _POSIX_SPAWN > 0
/* only for spawnfd: */
# define FFD_SPAWN_SEARCH_PATH O_RDWR

View File

@ -25,8 +25,7 @@ qhp.QtCore.subprojects.classes.sortPages = true
tagfile = ../../../doc/qtcore/qtcore.tags
depends += activeqt qtdbus qtgui qtwidgets qtnetwork qtdoc qtmacextras qtquick qtlinguist qtdesigner qtconcurrent qtxml qmake qtwinextras
# depends += qtqml # Qt namespace collides with QtQml::Qt, see QTBUG-38630
depends += activeqt qtdbus qtgui qtwidgets qtnetwork qtdoc qtmacextras qtquick qtlinguist qtdesigner qtconcurrent qtxml qmake qtwinextras qtqml
headerdirs += ..

View File

@ -71,6 +71,8 @@
which are currently active. All the states in a valid configuration of the state machine will
have a common ancestor.
\sa {The Declarative State Machine Framework}
\section1 Classes in the State Machine Framework
These classes are provided by qt for creating event-driven state machines.

View File

@ -1695,6 +1695,17 @@
\value Key_Sleep
\value Key_Zoom
\value Key_Cancel
\value Key_MicVolumeUp
\value Key_Find
\value Key_Open
\value Key_MicVolumeDown
\value Key_New
\value Key_Settings
\value Key_Redo
\value Key_Exit
\value Key_Info
\value Key_Undo
\value Key_Guide
\sa QKeyEvent::key()
*/

View File

@ -2858,7 +2858,7 @@ QTextStream &endl(QTextStream &stream)
/*!
\relates QTextStream
Calls \l{QTextStream::flush()}{flush()} on \a stream and returns \a stream.
Calls QTextStream::flush() on \a stream and returns \a stream.
\sa endl(), reset(), {QTextStream manipulators}
*/

View File

@ -391,6 +391,8 @@ LRESULT QT_WIN_CALLBACK qt_internal_proc(HWND hwnd, UINT message, WPARAM wp, LPA
QSockNot *sn = dict ? dict->value(wp) : 0;
if (sn) {
d->doWsaAsyncSelect(sn->fd, 0);
d->active_fd[sn->fd].selected = false;
if (type < 3) {
QEvent event(QEvent::SockAct);
QCoreApplication::sendEvent(sn->obj, &event);
@ -633,19 +635,12 @@ void QEventDispatcherWin32Private::sendTimerEvent(int timerId)
}
}
void QEventDispatcherWin32Private::doWsaAsyncSelect(int socket)
void QEventDispatcherWin32Private::doWsaAsyncSelect(int socket, long event)
{
Q_ASSERT(internalHwnd);
int sn_event = 0;
if (sn_read.contains(socket))
sn_event |= FD_READ | FD_CLOSE | FD_ACCEPT;
if (sn_write.contains(socket))
sn_event |= FD_WRITE | FD_CONNECT;
if (sn_except.contains(socket))
sn_event |= FD_OOB;
// BoundsChecker may emit a warning for WSAAsyncSelect when sn_event == 0
// BoundsChecker may emit a warning for WSAAsyncSelect when event == 0
// This is a BoundsChecker bug and not a Qt bug
WSAAsyncSelect(socket, internalHwnd, sn_event ? int(WM_QT_SOCKETNOTIFIER) : 0, sn_event);
WSAAsyncSelect(socket, internalHwnd, event ? int(WM_QT_SOCKETNOTIFIER) : 0, event);
}
void QEventDispatcherWin32::createInternalHwnd()
@ -658,13 +653,6 @@ void QEventDispatcherWin32::createInternalHwnd()
installMessageHook();
// register all socket notifiers
QList<int> sockets = (d->sn_read.keys().toSet()
+ d->sn_write.keys().toSet()
+ d->sn_except.keys().toSet()).toList();
for (int i = 0; i < sockets.count(); ++i)
d->doWsaAsyncSelect(sockets.at(i));
// start all normal timers
for (int i = 0; i < d->timerVec.count(); ++i)
d->registerTimer(d->timerVec.at(i));
@ -749,28 +737,40 @@ bool QEventDispatcherWin32::processEvents(QEventLoop::ProcessEventsFlags flags)
msg = d->queuedSocketEvents.takeFirst();
} else {
haveMessage = PeekMessage(&msg, 0, 0, 0, PM_REMOVE);
if (haveMessage && (flags & QEventLoop::ExcludeUserInputEvents)
&& ((msg.message >= WM_KEYFIRST
&& msg.message <= WM_KEYLAST)
|| (msg.message >= WM_MOUSEFIRST
&& msg.message <= WM_MOUSELAST)
|| msg.message == WM_MOUSEWHEEL
|| msg.message == WM_MOUSEHWHEEL
|| msg.message == WM_TOUCH
if (haveMessage) {
if ((flags & QEventLoop::ExcludeUserInputEvents)
&& ((msg.message >= WM_KEYFIRST
&& msg.message <= WM_KEYLAST)
|| (msg.message >= WM_MOUSEFIRST
&& msg.message <= WM_MOUSELAST)
|| msg.message == WM_MOUSEWHEEL
|| msg.message == WM_MOUSEHWHEEL
|| msg.message == WM_TOUCH
#ifndef QT_NO_GESTURES
|| msg.message == WM_GESTURE
|| msg.message == WM_GESTURENOTIFY
|| msg.message == WM_GESTURE
|| msg.message == WM_GESTURENOTIFY
#endif
|| msg.message == WM_CLOSE)) {
// queue user input events for later processing
haveMessage = false;
d->queuedUserInputEvents.append(msg);
}
if (haveMessage && (flags & QEventLoop::ExcludeSocketNotifiers)
&& (msg.message == WM_QT_SOCKETNOTIFIER && msg.hwnd == d->internalHwnd)) {
// queue socket events for later processing
haveMessage = false;
d->queuedSocketEvents.append(msg);
|| msg.message == WM_CLOSE)) {
// queue user input events for later processing
d->queuedUserInputEvents.append(msg);
continue;
}
if ((flags & QEventLoop::ExcludeSocketNotifiers)
&& (msg.message == WM_QT_SOCKETNOTIFIER && msg.hwnd == d->internalHwnd)) {
// queue socket events for later processing
d->queuedSocketEvents.append(msg);
continue;
}
} else if (!(flags & QEventLoop::ExcludeSocketNotifiers)) {
// register all socket notifiers
for (QSFDict::iterator it = d->active_fd.begin(), end = d->active_fd.end();
it != end; ++it) {
QSockFd &sd = it.value();
if (!sd.selected) {
d->doWsaAsyncSelect(it.key(), sd.event);
sd.selected = true;
}
}
}
}
if (!haveMessage) {
@ -896,8 +896,25 @@ void QEventDispatcherWin32::registerSocketNotifier(QSocketNotifier *notifier)
sn->fd = sockfd;
dict->insert(sn->fd, sn);
if (d->internalHwnd)
d->doWsaAsyncSelect(sockfd);
long event = 0;
if (d->sn_read.contains(sockfd))
event |= FD_READ | FD_CLOSE | FD_ACCEPT;
if (d->sn_write.contains(sockfd))
event |= FD_WRITE | FD_CONNECT;
if (d->sn_except.contains(sockfd))
event |= FD_OOB;
QSFDict::iterator it = d->active_fd.find(sockfd);
if (it != d->active_fd.end()) {
QSockFd &sd = it.value();
if (sd.selected) {
d->doWsaAsyncSelect(sockfd, 0);
sd.selected = false;
}
sd.event |= event;
} else {
d->active_fd.insert(sockfd, QSockFd(event));
}
}
void QEventDispatcherWin32::unregisterSocketNotifier(QSocketNotifier *notifier)
@ -916,6 +933,19 @@ void QEventDispatcherWin32::unregisterSocketNotifier(QSocketNotifier *notifier)
#endif
Q_D(QEventDispatcherWin32);
QSFDict::iterator it = d->active_fd.find(sockfd);
if (it != d->active_fd.end()) {
QSockFd &sd = it.value();
if (sd.selected)
d->doWsaAsyncSelect(sockfd, 0);
const long event[3] = { FD_READ | FD_CLOSE | FD_ACCEPT, FD_WRITE | FD_CONNECT, FD_OOB };
sd.event ^= event[type];
if (sd.event == 0)
d->active_fd.erase(it);
else
sd.selected = false;
}
QSNDict *sn_vec[3] = { &d->sn_read, &d->sn_write, &d->sn_except };
QSNDict *dict = sn_vec[type];
QSockNot *sn = dict->value(sockfd);
@ -924,9 +954,6 @@ void QEventDispatcherWin32::unregisterSocketNotifier(QSocketNotifier *notifier)
dict->remove(sockfd);
delete sn;
if (d->internalHwnd)
d->doWsaAsyncSelect(sockfd);
}
void QEventDispatcherWin32::registerTimer(int timerId, int interval, Qt::TimerType timerType, QObject *object)
@ -1165,6 +1192,7 @@ void QEventDispatcherWin32::closingDown()
unregisterSocketNotifier((*(d->sn_write.begin()))->obj);
while (!d->sn_except.isEmpty())
unregisterSocketNotifier((*(d->sn_except.begin()))->obj);
Q_ASSERT(d->active_fd.isEmpty());
// clean up any timers
for (int i = 0; i < d->timerVec.count(); ++i)

View File

@ -115,6 +115,14 @@ struct QSockNot {
};
typedef QHash<int, QSockNot *> QSNDict;
struct QSockFd {
long event;
bool selected;
explicit inline QSockFd(long ev = 0) : event(ev), selected(false) { }
};
typedef QHash<int, QSockFd> QSFDict;
struct WinTimerInfo { // internal timer info
QObject *dispatcher;
int timerId;
@ -169,7 +177,8 @@ public:
QSNDict sn_read;
QSNDict sn_write;
QSNDict sn_except;
void doWsaAsyncSelect(int socket);
QSFDict active_fd;
void doWsaAsyncSelect(int socket, long event);
QList<QWinEventNotifier *> winEventNotifierList;
void activateEventNotifier(QWinEventNotifier * wen);

View File

@ -1548,12 +1548,13 @@ bool QMetaObject::invokeMethod(QObject *obj,
/*!
\fn QMetaObject::Connection &QMetaObject::Connection::operator=(Connection &&other)
Move-assigns \a other to this object.
Move-assigns \a other to this object, and returns a reference.
*/
/*!
\fn QMetaObject::Connection::Connection(Connection &&o)
Move-constructs a Connection instance, making it point to the same object that \a o was pointing to.
Move-constructs a Connection instance, making it point to the same object
that \a o was pointing to.
*/
/*!

View File

@ -98,42 +98,6 @@ public:
QTcpSocket and QUdpSocket provide notification through signals, so
there is normally no need to use a QSocketNotifier on them.
\section1 Notes for Windows Users
The socket passed to QSocketNotifier will become non-blocking, even if
it was created as a blocking socket.
The activated() signal is sometimes triggered by high general activity
on the host, even if there is nothing to read. A subsequent read from
the socket can then fail, the error indicating that there is no data
available (e.g., \c{WSAEWOULDBLOCK}). This is an operating system
limitation, and not a bug in QSocketNotifier.
To ensure that the socket notifier handles read notifications correctly,
follow these steps when you receive a notification:
\list 1
\li Disable the notifier.
\li Read data from the socket.
\li Re-enable the notifier if you are interested in more data (such as after
having written a new command to a remote server).
\endlist
To ensure that the socket notifier handles write notifications correctly,
follow these steps when you receive a notification:
\list 1
\li Disable the notifier.
\li Write as much data as you can (before \c EWOULDBLOCK is returned).
\li Re-enable notifier if you have more data to write.
\endlist
\b{Further information:}
On Windows, Qt always disables the notifier after getting a notification,
and only re-enables it if more data is expected. For example, if data is
read from the socket and it can be used to read more, or if reading or
writing is not possible because the socket would block, in which case
it is necessary to wait before attempting to read or write again.
\sa QFile, QProcess, QTcpSocket, QUdpSocket
*/

View File

@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Copyright (C) 2015 Klaralvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author David Faure <david.faure@kdab.com>
** Contact: http://www.qt.io/licensing/
**
** This file is part of the QtCore module of the Qt Toolkit.

View File

@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Copyright (C) 2015 Klaralvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author David Faure <david.faure@kdab.com>
** Contact: http://www.qt.io/licensing/
**
** This file is part of the QtCore module of the Qt Toolkit.

View File

@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Copyright (C) 2015 Klaralvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author David Faure <david.faure@kdab.com>
** Contact: http://www.qt.io/licensing/
**
** This file is part of the QtCore module of the Qt Toolkit.

View File

@ -38,6 +38,7 @@
#ifndef QT_NO_MIMETYPE
#include "qmimetypeparser_p.h"
#include <QtCore/QList>
#include <QtCore/QDebug>
#include <qendian.h>
@ -231,26 +232,53 @@ static inline QByteArray makePattern(const QByteArray &value)
return pattern;
}
QMimeMagicRule::QMimeMagicRule(QMimeMagicRule::Type theType,
// Evaluate a magic match rule like
// <match value="must be converted with BinHex" type="string" offset="11"/>
// <match value="0x9501" type="big16" offset="0:64"/>
QMimeMagicRule::QMimeMagicRule(const QString &typeStr,
const QByteArray &theValue,
int theStartPos,
int theEndPos,
const QByteArray &theMask) :
const QString &offsets,
const QByteArray &theMask,
QString *errorString) :
d(new QMimeMagicRulePrivate)
{
Q_ASSERT(!theValue.isEmpty());
d->type = theType;
d->value = theValue;
d->startPos = theStartPos;
d->endPos = theEndPos;
d->mask = theMask;
d->matchFunction = 0;
d->type = QMimeMagicRule::type(typeStr.toLatin1());
if (d->type == Invalid) {
*errorString = QStringLiteral("Type %s is not supported").arg(typeStr);
}
// Parse for offset as "1" or "1:10"
const int colonIndex = offsets.indexOf(QLatin1Char(':'));
const QString startPosStr = colonIndex == -1 ? offsets : offsets.mid(0, colonIndex);
const QString endPosStr = colonIndex == -1 ? offsets : offsets.mid(colonIndex + 1);
if (!QMimeTypeParserBase::parseNumber(startPosStr, &d->startPos, errorString) ||
!QMimeTypeParserBase::parseNumber(endPosStr, &d->endPos, errorString)) {
d->type = Invalid;
return;
}
if (d->value.isEmpty()) {
d->type = Invalid;
if (errorString)
*errorString = QLatin1String("Invalid empty magic rule value");
return;
}
if (d->type >= Host16 && d->type <= Byte) {
bool ok;
d->number = d->value.toUInt(&ok, 0); // autodetect
Q_ASSERT(ok);
if (!ok) {
d->type = Invalid;
if (errorString)
*errorString = QString::fromLatin1("Invalid magic rule value \"%1\"").arg(
QString::fromLatin1(d->value));
return;
}
d->numberMask = !d->mask.isEmpty() ? d->mask.toUInt(&ok, 0) : 0; // autodetect
}
@ -259,9 +287,23 @@ QMimeMagicRule::QMimeMagicRule(QMimeMagicRule::Type theType,
d->pattern = makePattern(d->value);
d->pattern.squeeze();
if (!d->mask.isEmpty()) {
Q_ASSERT(d->mask.size() >= 4 && d->mask.startsWith("0x"));
d->mask = QByteArray::fromHex(QByteArray::fromRawData(d->mask.constData() + 2, d->mask.size() - 2));
Q_ASSERT(d->mask.size() == d->pattern.size());
if (d->mask.size() < 4 || !d->mask.startsWith("0x")) {
d->type = Invalid;
if (errorString)
*errorString = QString::fromLatin1("Invalid magic rule mask \"%1\"").arg(
QString::fromLatin1(d->mask));
return;
}
const QByteArray &tempMask = QByteArray::fromHex(QByteArray::fromRawData(
d->mask.constData() + 2, d->mask.size() - 2));
if (tempMask.size() != d->pattern.size()) {
d->type = Invalid;
if (errorString)
*errorString = QString::fromLatin1("Invalid magic rule mask size \"%1\"").arg(
QString::fromLatin1(d->mask));
return;
}
d->mask = tempMask;
} else {
d->mask.fill(char(-1), d->pattern.size());
}

View File

@ -61,7 +61,8 @@ class QMimeMagicRule
public:
enum Type { Invalid = 0, String, Host16, Host32, Big16, Big32, Little16, Little32, Byte };
QMimeMagicRule(Type type, const QByteArray &value, int startPos, int endPos, const QByteArray &mask = QByteArray());
QMimeMagicRule(const QString &typeStr, const QByteArray &value, const QString &offsets,
const QByteArray &mask, QString *errorString);
QMimeMagicRule(const QMimeMagicRule &other);
~QMimeMagicRule();

View File

@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Copyright (C) 2015 Klaralvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author David Faure <david.faure@kdab.com>
** Contact: http://www.qt.io/licensing/
**
** This file is part of the QtCore module of the Qt Toolkit.

View File

@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Copyright (C) 2015 Klaralvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author David Faure <david.faure@kdab.com>
** Contact: http://www.qt.io/licensing/
**
** This file is part of the QtCore module of the Qt Toolkit.

View File

@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Copyright (C) 2015 Klaralvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author David Faure <david.faure@kdab.com>
** Contact: http://www.qt.io/licensing/
**
** This file is part of the QtCore module of the Qt Toolkit.

View File

@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Copyright (C) 2015 Klaralvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author David Faure <david.faure@kdab.com>
** Contact: http://www.qt.io/licensing/
**
** This file is part of the QtCore module of the Qt Toolkit.

View File

@ -153,8 +153,8 @@ QMimeTypeParserBase::ParseState QMimeTypeParserBase::nextState(ParseState curren
return ParseError;
}
// Parse int number from an (attribute) string)
static bool parseNumber(const QString &n, int *target, QString *errorMessage)
// Parse int number from an (attribute) string
bool QMimeTypeParserBase::parseNumber(const QString &n, int *target, QString *errorMessage)
{
bool ok;
*target = n.toInt(&ok);
@ -165,37 +165,14 @@ static bool parseNumber(const QString &n, int *target, QString *errorMessage)
return true;
}
// Evaluate a magic match rule like
// <match value="must be converted with BinHex" type="string" offset="11"/>
// <match value="0x9501" type="big16" offset="0:64"/>
#ifndef QT_NO_XMLSTREAMREADER
static bool createMagicMatchRule(const QXmlStreamAttributes &atts,
QString *errorMessage, QMimeMagicRule *&rule)
static QMimeMagicRule *createMagicMatchRule(const QXmlStreamAttributes &atts, QString *errorMessage)
{
const QString type = atts.value(QLatin1String(matchTypeAttributeC)).toString();
QMimeMagicRule::Type magicType = QMimeMagicRule::type(type.toLatin1());
if (magicType == QMimeMagicRule::Invalid) {
qWarning("%s: match type %s is not supported.", Q_FUNC_INFO, type.toUtf8().constData());
return true;
}
const QString value = atts.value(QLatin1String(matchValueAttributeC)).toString();
if (value.isEmpty()) {
*errorMessage = QString::fromLatin1("Empty match value detected.");
return false;
}
// Parse for offset as "1" or "1:10"
int startPos, endPos;
const QString offsetS = atts.value(QLatin1String(matchOffsetAttributeC)).toString();
const int colonIndex = offsetS.indexOf(QLatin1Char(':'));
const QString startPosS = colonIndex == -1 ? offsetS : offsetS.mid(0, colonIndex);
const QString endPosS = colonIndex == -1 ? offsetS : offsetS.mid(colonIndex + 1);
if (!parseNumber(startPosS, &startPos, errorMessage) || !parseNumber(endPosS, &endPos, errorMessage))
return false;
const QString offsets = atts.value(QLatin1String(matchOffsetAttributeC)).toString();
const QString mask = atts.value(QLatin1String(matchMaskAttributeC)).toString();
rule = new QMimeMagicRule(magicType, value.toUtf8(), startPos, endPos, mask.toLatin1());
return true;
return new QMimeMagicRule(type, value.toUtf8(), offsets, mask.toLatin1(), errorMessage);
}
#endif
@ -283,9 +260,10 @@ bool QMimeTypeParserBase::parse(QIODevice *dev, const QString &fileName, QString
}
break;
case ParseMagicMatchRule: {
QMimeMagicRule *rule = 0;
if (!createMagicMatchRule(atts, errorMessage, rule))
return false;
QString magicErrorMessage;
QMimeMagicRule *rule = createMagicMatchRule(atts, &magicErrorMessage);
if (!rule->isValid())
qWarning("QMimeDatabase: Error parsing %s\n%s", qPrintable(fileName), qPrintable(magicErrorMessage));
QList<QMimeMagicRule> *ruleList;
if (currentRules.isEmpty())
ruleList = &rules;

View File

@ -66,6 +66,8 @@ public:
bool parse(QIODevice *dev, const QString &fileName, QString *errorMessage);
static bool parseNumber(const QString &n, int *target, QString *errorMessage);
protected:
virtual bool process(const QMimeType &t, QString *errorMessage) = 0;
virtual bool process(const QMimeGlobPattern &t, QString *errorMessage) = 0;

View File

@ -37,7 +37,8 @@ depends += \
qtqml \
qtquick \
qtwidgets \
qtdoc
qtdoc \
qmake
headerdirs += ..

View File

@ -313,7 +313,7 @@ bool QImageData::checkForAlphaPixels() const
sharing}. QImage objects can also be streamed and compared.
\note If you would like to load QImage objects in a static build of Qt,
refer to the \l{How To Create Qt Plugins}{Plugin HowTo}.
refer to the \l{How to Create Qt Plugins}{Plugin HowTo}.
\warning Painting on a QImage with the format
QImage::Format_Indexed8 is not supported.

View File

@ -1170,7 +1170,7 @@ QImageIOHandler::Transformations QImageReader::transformation() const
Sets if images returned by read() should have transformation metadata automatically applied.
\sa autoTransform(), transform(), read()
\sa autoTransform(), transformation(), read()
*/
void QImageReader::setAutoTransform(bool enabled)
{

View File

@ -387,7 +387,7 @@ QCursor::QCursor(const QPixmap &pixmap, int hotX, int hotY)
bmm.fill(Qt::color1);
}
d = QCursorData::setBitmap(bm, bmm, hotX, hotY);
d = QCursorData::setBitmap(bm, bmm, hotX, hotY, pixmap.devicePixelRatio());
d->pixmap = pixmap;
}
@ -430,7 +430,7 @@ QCursor::QCursor(const QPixmap &pixmap, int hotX, int hotY)
QCursor::QCursor(const QBitmap &bitmap, const QBitmap &mask, int hotX, int hotY)
: d(0)
{
d = QCursorData::setBitmap(bitmap, mask, hotX, hotY);
d = QCursorData::setBitmap(bitmap, mask, hotX, hotY, 1.0);
}
/*!
@ -650,7 +650,7 @@ void QCursorData::initialize()
QCursorData::initialized = true;
}
QCursorData *QCursorData::setBitmap(const QBitmap &bitmap, const QBitmap &mask, int hotX, int hotY)
QCursorData *QCursorData::setBitmap(const QBitmap &bitmap, const QBitmap &mask, int hotX, int hotY, qreal devicePixelRatio)
{
if (!QCursorData::initialized)
QCursorData::initialize();
@ -664,8 +664,8 @@ QCursorData *QCursorData::setBitmap(const QBitmap &bitmap, const QBitmap &mask,
d->bm = new QBitmap(bitmap);
d->bmm = new QBitmap(mask);
d->cshape = Qt::BitmapCursor;
d->hx = hotX >= 0 ? hotX : bitmap.width() / 2;
d->hy = hotY >= 0 ? hotY : bitmap.height() / 2;
d->hx = hotX >= 0 ? hotX : bitmap.width() / 2 / devicePixelRatio;
d->hy = hotY >= 0 ? hotY : bitmap.height() / 2 / devicePixelRatio;
return d;
}

View File

@ -70,7 +70,8 @@ public:
short hx, hy;
static bool initialized;
void update();
static QCursorData *setBitmap(const QBitmap &bitmap, const QBitmap &mask, int hotX, int hotY);
static QCursorData *setBitmap(const QBitmap &bitmap, const QBitmap &mask, int hotX, int hotY,
qreal devicePixelRatio);
};
extern QCursorData *qt_cursorTable[Qt::LastCursor + 1]; // qcursor.cpp

View File

@ -148,8 +148,6 @@ QMatrix4x4::QMatrix4x4(const float *values)
top-most 4 rows of \a matrix. If \a matrix has less than 4 columns
or rows, the remaining elements are filled with elements from the
identity matrix.
\sa QMatrix4x4(const QGenericMatrix &)
*/
/*!

View File

@ -1152,7 +1152,7 @@ void QNetworkReplyHttpImplPrivate::replyDownloadMetaData
if (statusCode == 304) {
#if defined(QNETWORKACCESSHTTPBACKEND_DEBUG)
qDebug() << "Received a 304 from" << url();
qDebug() << "Received a 304 from" << request.url();
#endif
QAbstractNetworkCache *nc = managerPrivate->networkCache;
if (nc) {
@ -1457,7 +1457,7 @@ QNetworkCacheMetaData QNetworkReplyHttpImplPrivate::fetchCacheMetaData(const QNe
}
#if defined(QNETWORKACCESSHTTPBACKEND_DEBUG)
QByteArray n = rawHeader(header);
QByteArray n = q->rawHeader(header);
QByteArray o;
if (it != cacheHeaders.rawHeaders.constEnd())
o = (*it).second;
@ -1676,6 +1676,11 @@ void QNetworkReplyHttpImplPrivate::_q_startOperation()
Q_ARG(QString, QCoreApplication::translate("QNetworkReply", "backend start error.")));
QMetaObject::invokeMethod(q, "_q_finished", synchronous ? Qt::DirectConnection : Qt::QueuedConnection);
return;
#endif
} else {
#ifndef QT_NO_BEARERMANAGEMENT
QObject::connect(session.data(), SIGNAL(stateChanged(QNetworkSession::State)),
q, SLOT(_q_networkSessionStateChanged(QNetworkSession::State)), Qt::QueuedConnection);
#endif
}
@ -1844,6 +1849,16 @@ void QNetworkReplyHttpImplPrivate::_q_networkSessionConnected()
}
}
void QNetworkReplyHttpImplPrivate::_q_networkSessionStateChanged(QNetworkSession::State sessionState)
{
if (sessionState == QNetworkSession::Disconnected
&& (state != Idle || state != Reconnecting)) {
error(QNetworkReplyImpl::NetworkSessionFailedError,
QCoreApplication::translate("QNetworkReply", "Network session error."));
finished();
}
}
void QNetworkReplyHttpImplPrivate::_q_networkSessionFailed()
{
// Abort waiting and working replies.

View File

@ -95,6 +95,7 @@ public:
#ifndef QT_NO_BEARERMANAGEMENT
Q_PRIVATE_SLOT(d_func(), void _q_networkSessionConnected())
Q_PRIVATE_SLOT(d_func(), void _q_networkSessionFailed())
Q_PRIVATE_SLOT(d_func(), void _q_networkSessionStateChanged(QNetworkSession::State))
Q_PRIVATE_SLOT(d_func(), void _q_networkSessionUsagePoliciesChanged(QNetworkSession::UsagePolicies))
#endif
Q_PRIVATE_SLOT(d_func(), void _q_finished())
@ -170,6 +171,7 @@ public:
#ifndef QT_NO_BEARERMANAGEMENT
void _q_networkSessionConnected();
void _q_networkSessionFailed();
void _q_networkSessionStateChanged(QNetworkSession::State);
void _q_networkSessionUsagePoliciesChanged(QNetworkSession::UsagePolicies);
#endif
void _q_finished();

View File

@ -126,6 +126,11 @@ void QNetworkReplyImplPrivate::_q_startOperation()
finished();
#endif
return;
} else {
#ifndef QT_NO_BEARERMANAGEMENT
QObject::connect(session.data(), SIGNAL(stateChanged(QNetworkSession::State)),
q, SLOT(_q_networkSessionStateChanged(QNetworkSession::State)), Qt::QueuedConnection);
#endif
}
#ifndef QT_NO_BEARERMANAGEMENT
@ -310,6 +315,16 @@ void QNetworkReplyImplPrivate::_q_networkSessionConnected()
}
}
void QNetworkReplyImplPrivate::_q_networkSessionStateChanged(QNetworkSession::State sessionState)
{
if (sessionState == QNetworkSession::Disconnected
&& (state != Idle || state != Reconnecting)) {
error(QNetworkReplyImpl::NetworkSessionFailedError,
QCoreApplication::translate("QNetworkReply", "Network session error."));
finished();
}
}
void QNetworkReplyImplPrivate::_q_networkSessionFailed()
{
// Abort waiting and working replies.

View File

@ -89,6 +89,7 @@ public:
#ifndef QT_NO_BEARERMANAGEMENT
Q_PRIVATE_SLOT(d_func(), void _q_networkSessionConnected())
Q_PRIVATE_SLOT(d_func(), void _q_networkSessionFailed())
Q_PRIVATE_SLOT(d_func(), void _q_networkSessionStateChanged(QNetworkSession::State))
Q_PRIVATE_SLOT(d_func(), void _q_networkSessionUsagePoliciesChanged(QNetworkSession::UsagePolicies))
#endif
@ -124,6 +125,7 @@ public:
#ifndef QT_NO_BEARERMANAGEMENT
void _q_networkSessionConnected();
void _q_networkSessionFailed();
void _q_networkSessionStateChanged(QNetworkSession::State);
void _q_networkSessionUsagePoliciesChanged(QNetworkSession::UsagePolicies);
#endif

View File

@ -26,7 +26,7 @@ qhp.QtNetwork.subprojects.classes.sortPages = true
tagfile = ../../../doc/qtnetwork/qtnetwork.tags
depends += qtcore qtgui qtdoc
depends += qtcore qtgui qtdoc qmake
headerdirs += ..

View File

@ -739,15 +739,9 @@ bool QAbstractSocketPrivate::canReadNotification()
return true;
}
if (socketEngine) {
// turn the socket engine off if we've either:
// - got pending datagrams
// - reached the buffer size limit
if (isBuffered)
socketEngine->setReadNotificationEnabled(readBufferMaxSize == 0 || readBufferMaxSize > q->bytesAvailable());
else if (socketType != QAbstractSocket::TcpSocket)
socketEngine->setReadNotificationEnabled(!socketEngine->hasPendingDatagrams());
}
// turn the socket engine off if we've reached the buffer size limit
if (socketEngine && isBuffered)
socketEngine->setReadNotificationEnabled(readBufferMaxSize == 0 || readBufferMaxSize > q->bytesAvailable());
// reset the read socket notifier state if we reentered inside the
// readyRead() connected slot.

View File

@ -1090,8 +1090,11 @@ qint64 QNativeSocketEnginePrivate::nativeBytesAvailable() const
buf.buf = &c;
buf.len = sizeof(c);
DWORD flags = MSG_PEEK;
if (::WSARecvFrom(socketDescriptor, &buf, 1, 0, &flags, 0,0,0,0) == SOCKET_ERROR)
return 0;
if (::WSARecvFrom(socketDescriptor, &buf, 1, 0, &flags, 0,0,0,0) == SOCKET_ERROR) {
int err = WSAGetLastError();
if (err != WSAECONNRESET && err != WSAENETRESET)
return 0;
}
}
return nbytes;
}
@ -1119,14 +1122,7 @@ bool QNativeSocketEnginePrivate::nativeHasPendingDatagrams() const
int err = WSAGetLastError();
if (ret == SOCKET_ERROR && err != WSAEMSGSIZE) {
WS_ERROR_DEBUG(err);
if (err == WSAECONNRESET || err == WSAENETRESET) {
// Discard error message to prevent QAbstractSocket from
// getting this message repeatedly after reenabling the
// notifiers.
flags = 0;
::WSARecvFrom(socketDescriptor, &buf, 1, &available, &flags,
&storage.a, &storageSize, 0, 0);
}
result = (err == WSAECONNRESET || err == WSAENETRESET);
} else {
// If there's no error, or if our buffer was too small, there must be
// a pending datagram.
@ -1179,12 +1175,21 @@ qint64 QNativeSocketEnginePrivate::nativePendingDatagramSize() const
if (recvResult != SOCKET_ERROR) {
ret = qint64(bytesRead);
break;
} else if (recvResult == SOCKET_ERROR && err == WSAEMSGSIZE) {
bufferCount += 5;
delete[] buf;
} else if (recvResult == SOCKET_ERROR) {
WS_ERROR_DEBUG(err);
ret = -1;
} else {
switch (err) {
case WSAEMSGSIZE:
bufferCount += 5;
delete[] buf;
continue;
case WSAECONNRESET:
case WSAENETRESET:
ret = 0;
break;
default:
WS_ERROR_DEBUG(err);
ret = -1;
break;
}
break;
}
}

View File

@ -54,7 +54,7 @@ QT_BEGIN_NAMESPACE
elliptic-curve cipher algorithms.
Elliptic curves can be constructed from a "short name" (SN) (fromShortName()),
and by a call to QSslSocket::supportedEllipticCurves().
and by a call to QSslConfiguration::supportedEllipticCurves().
QSslEllipticCurve instances can be compared for equality and can be used as keys
in QHash and QSet. They cannot be used as key in a QMap.
@ -65,7 +65,7 @@ QT_BEGIN_NAMESPACE
Constructs an invalid elliptic curve.
\sa isValid(), QSslSocket::supportedEllipticCurves()
\sa isValid(), QSslConfiguration::supportedEllipticCurves()
*/
/*!
@ -136,7 +136,6 @@ QT_BEGIN_NAMESPACE
\relates QSslEllipticCurve
Returns true if the curve \a lhs represents the same curve of \a rhs;
false otherwise.
*/
/*!

View File

@ -257,7 +257,6 @@ int QSslPreSharedKeyAuthenticator::maximumPreSharedKeyLength() const
identity hint, identity, pre shared key, maximum length for the identity
and maximum length for the pre shared key.
\sa operator!=(const QSslPreSharedKeyAuthenticator &lhs, const QSslPreSharedKeyAuthenticator &rhs)
*/
bool operator==(const QSslPreSharedKeyAuthenticator &lhs, const QSslPreSharedKeyAuthenticator &rhs)
{
@ -277,7 +276,6 @@ bool operator==(const QSslPreSharedKeyAuthenticator &lhs, const QSslPreSharedKey
Returns true if the authenticator object \a lhs is different than \a rhs;
false otherwise.
\sa operator==(const QSslPreSharedKeyAuthenticator &lhs, const QSslPreSharedKeyAuthenticator &rhs)
*/
QT_END_NAMESPACE

View File

@ -19,7 +19,7 @@ exampledirs += ../../../examples/opengl \
imagedirs += images \
../../../examples/opengl/doc/images
depends += qtdoc qtcore qtgui qtwidgets
depends += qtdoc qtcore qtgui qtwidgets qmake
examplesinstallpath = opengl

View File

@ -39,6 +39,10 @@
#include <QtPlatformHeaders/QEGLNativeContext>
#include <QDebug>
#ifdef Q_OS_ANDROID
#include <QtCore/private/qjnihelpers_p.h>
#endif
QT_BEGIN_NAMESPACE
/*!
@ -294,6 +298,14 @@ void QEGLPlatformContext::updateFormatFromGL()
QByteArray version = QByteArray(reinterpret_cast<const char *>(s));
int major, minor;
if (QPlatformOpenGLContext::parseOpenGLVersion(version, major, minor)) {
#ifdef Q_OS_ANDROID
// Some Android 4.2.2 devices report OpenGL ES 3.0 without the functions being available.
static int apiLevel = QtAndroidPrivate::androidSdkVersion();
if (apiLevel <= 17 && major >= 3) {
major = 2;
minor = 0;
}
#endif
m_format.setMajorVersion(major);
m_format.setMinorVersion(minor);
}

View File

@ -304,7 +304,7 @@ NSCursor *QCocoaCursor::createCursorFromPixmap(const QPixmap pixmap, const QPoin
NSImage *nsimage;
if (pixmap.devicePixelRatio() > 1.0) {
QSize layoutSize = pixmap.size() / pixmap.devicePixelRatio();
QPixmap scaledPixmap = pixmap.scaled(layoutSize);
QPixmap scaledPixmap = pixmap.scaled(layoutSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
nsimage = static_cast<NSImage *>(qt_mac_create_nsimage(scaledPixmap));
CGImageRef cgImage = qt_mac_toCGImage(pixmap.toImage());
NSBitmapImageRep *imageRep = [[NSBitmapImageRep alloc] initWithCGImage:cgImage];

View File

@ -86,9 +86,17 @@ void QCocoaScreen::updateGeometry()
NSRect frameRect = [nsScreen frame];
if (m_screenIndex == 0) {
// Since Mavericks, there is a setting, System Preferences->Mission Control->
// Displays have separate Spaces.
BOOL spansDisplays = NO;
#if QT_OSX_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_9)
if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_9)
spansDisplays = [NSScreen screensHaveSeparateSpaces];
#endif
if (spansDisplays || m_screenIndex == 0) {
m_geometry = QRect(frameRect.origin.x, frameRect.origin.y, frameRect.size.width, frameRect.size.height);
// This is the primary screen, the one that contains the menubar. Its origin should be
// Displays have separate Spaces setting is on or this is the primary screen,
// the one that contains the menubar. Its origin should be
// (0, 0), and it's the only one whose available geometry differs from its full geometry.
NSRect visibleRect = [nsScreen visibleFrame];
m_availableGeometry = QRect(visibleRect.origin.x,

View File

@ -464,6 +464,13 @@ void QCocoaMenu::showPopup(const QWindow *parentWindow, const QRect &targetRect,
NSView *view = cocoaWindow ? cocoaWindow->contentView() : nil;
NSMenuItem *nsItem = item ? ((QCocoaMenuItem *)item)->nsItem() : nil;
QScreen *screen = 0;
if (parentWindow)
screen = parentWindow->screen();
if (!screen && !QGuiApplication::screens().isEmpty())
screen = QGuiApplication::screens().at(0);
Q_ASSERT(screen);
// Ideally, we would call -popUpMenuPositioningItem:atLocation:inView:.
// However, this showed not to work with modal windows where the menu items
// would appear disabled. So, we resort to a more artisanal solution. Note
@ -480,6 +487,21 @@ void QCocoaMenu::showPopup(const QWindow *parentWindow, const QRect &targetRect,
[popupCell setTransparent:YES];
[popupCell setMenu:m_nativeMenu];
[popupCell selectItem:nsItem];
int availableHeight = screen->availableSize().height();
const QPoint &globalPos = parentWindow->mapToGlobal(pos);
int menuHeight = m_nativeMenu.size.height;
if (globalPos.y() + menuHeight > availableHeight) {
// Maybe we need to fix the vertical popup position but we don't know the
// exact popup height at the moment (and Cocoa is just guessing) nor its
// position. So, instead of translating by the popup's full height, we need
// to estimate where the menu will show up and translate by the remaining height.
float idx = ([m_nativeMenu indexOfItem:nsItem] + 1.0f) / m_nativeMenu.numberOfItems;
float heightBelowPos = (1.0 - idx) * menuHeight;
if (globalPos.y() + heightBelowPos > availableHeight)
pos.setY(pos.y() - globalPos.y() + availableHeight - heightBelowPos);
}
NSRect cellFrame = NSMakeRect(pos.x(), pos.y(), m_nativeMenu.minimumWidth, 10);
[popupCell performClickWithFrame:cellFrame inView:view];
} else {
@ -488,22 +510,21 @@ void QCocoaMenu::showPopup(const QWindow *parentWindow, const QRect &targetRect,
if (view) {
// convert coordinates from view to the view's window
nsPos = [view convertPoint:nsPos toView:nil];
} else if (!QGuiApplication::screens().isEmpty()) {
QScreen *screen = QGuiApplication::screens().at(0);
} else {
nsPos.y = screen->availableVirtualSize().height() - nsPos.y;
}
if (view) {
// Finally, we need to synthesize an event.
NSEvent *menuEvent = [NSEvent mouseEventWithType:NSRightMouseDown
location:nsPos
modifierFlags:0
timestamp:0
windowNumber:view ? view.window.windowNumber : 0
context:nil
eventNumber:0
clickCount:1
pressure:1.0];
location:nsPos
modifierFlags:0
timestamp:0
windowNumber:view ? view.window.windowNumber : 0
context:nil
eventNumber:0
clickCount:1
pressure:1.0];
[NSMenu popUpContextMenu:m_nativeMenu withEvent:menuEvent forView:view];
} else {
[m_nativeMenu popUpMenuPositioningItem:nsItem atLocation:nsPos inView:0];

View File

@ -369,7 +369,7 @@ void QIOSMenu::syncMenuItem(QPlatformMenuItem *)
switch (m_effectiveMenuType) {
case EditMenu:
[m_menuController setVisibleMenuItems:visibleMenuItems()];
[m_menuController setVisibleMenuItems:filterFirstResponderActions(visibleMenuItems())];
break;
default:
[m_pickerView setVisibleMenuItems:visibleMenuItems() selectItem:m_targetItem];

View File

@ -333,65 +333,73 @@
#ifndef QT_NO_SHORTCUT
- (void)sendShortcut:(QKeySequence::StandardKey)standardKey
{
const int keys = QKeySequence(standardKey)[0];
Qt::Key key = Qt::Key(keys & 0x0000FFFF);
Qt::KeyboardModifiers modifiers = Qt::KeyboardModifiers(keys & 0xFFFF0000);
[self sendKeyPressRelease:key modifiers:modifiers];
}
- (void)cut:(id)sender
{
Q_UNUSED(sender);
[self sendKeyPressRelease:Qt::Key_X modifiers:Qt::ControlModifier];
[self sendShortcut:QKeySequence::Cut];
}
- (void)copy:(id)sender
{
Q_UNUSED(sender);
[self sendKeyPressRelease:Qt::Key_C modifiers:Qt::ControlModifier];
[self sendShortcut:QKeySequence::Copy];
}
- (void)paste:(id)sender
{
Q_UNUSED(sender);
[self sendKeyPressRelease:Qt::Key_V modifiers:Qt::ControlModifier];
[self sendShortcut:QKeySequence::Paste];
}
- (void)selectAll:(id)sender
{
Q_UNUSED(sender);
[self sendKeyPressRelease:Qt::Key_A modifiers:Qt::ControlModifier];
[self sendShortcut:QKeySequence::SelectAll];
}
- (void)delete:(id)sender
{
Q_UNUSED(sender);
[self sendKeyPressRelease:Qt::Key_Delete modifiers:Qt::ControlModifier];
[self sendShortcut:QKeySequence::Delete];
}
- (void)toggleBoldface:(id)sender
{
Q_UNUSED(sender);
[self sendKeyPressRelease:Qt::Key_B modifiers:Qt::ControlModifier];
[self sendShortcut:QKeySequence::Bold];
}
- (void)toggleItalics:(id)sender
{
Q_UNUSED(sender);
[self sendKeyPressRelease:Qt::Key_I modifiers:Qt::ControlModifier];
[self sendShortcut:QKeySequence::Italic];
}
- (void)toggleUnderline:(id)sender
{
Q_UNUSED(sender);
[self sendKeyPressRelease:Qt::Key_U modifiers:Qt::ControlModifier];
[self sendShortcut:QKeySequence::Underline];
}
// -------------------------------------------------------------------------
- (void)undo
{
[self sendKeyPressRelease:Qt::Key_Z modifiers:Qt::ControlModifier];
[self sendShortcut:QKeySequence::Undo];
[self rebuildUndoStack];
}
- (void)redo
{
[self sendKeyPressRelease:Qt::Key_Z modifiers:Qt::ControlModifier|Qt::ShiftModifier];
[self sendShortcut:QKeySequence::Redo];
[self rebuildUndoStack];
}
@ -730,6 +738,15 @@
return toCGRect(startRect.united(endRect));
}
- (NSArray *)selectionRectsForRange:(UITextRange *)range
{
Q_UNUSED(range);
// This method is supposed to return a rectangle for each line with selection. Since we don't
// expose an API in Qt/IM for getting this information, and since we never seems to be getting
// a call from UIKit for this, we return an empty array until a need arise.
return [[NSArray new] autorelease];
}
- (CGRect)caretRectForPosition:(UITextPosition *)position
{
Q_UNUSED(position);

View File

@ -805,7 +805,7 @@ void QUnixPrintWidgetPrivate::applyPrinterProperties()
home += QLatin1Char('/');
if (!cur.isEmpty() && cur.at(cur.length()-1) != QLatin1Char('/'))
cur += QLatin1Char('/');
if (cur.left(home.length()) != home)
if (!cur.startsWith(home))
cur = home;
if (QGuiApplication::platformName() == QLatin1String("xcb")) {
if (printer->docName().isEmpty()) {

View File

@ -146,8 +146,16 @@ void QAlphaPaintEngine::updateState(const QPaintEngineState &state)
d->m_hasalpha = d->m_alphaOpacity || d->m_alphaBrush || d->m_alphaPen;
if (d->m_picengine)
if (d->m_picengine) {
const QPainter *p = painter();
d->m_picpainter->setPen(p->pen());
d->m_picpainter->setBrush(p->brush());
d->m_picpainter->setBrushOrigin(p->brushOrigin());
d->m_picpainter->setFont(p->font());
d->m_picpainter->setOpacity(p->opacity());
d->m_picpainter->setTransform(p->combinedTransform());
d->m_picengine->updateState(state);
}
}
void QAlphaPaintEngine::drawPath(const QPainterPath &path)

View File

@ -25,7 +25,7 @@ qhp.QtSql.subprojects.classes.selectors = class fake:headerfile
qhp.QtSql.subprojects.classes.sortPages = true
tagfile = ../../../doc/qtsql/qtsql.tags
depends += qtcore qtwidgets qtdoc
depends += qtcore qtwidgets qtdoc qmake
headerdirs += ..

View File

@ -90,9 +90,8 @@
\brief Basic set of UI components
This is a listing of a list of UI components implemented by QML types. These
files are available for general import and they are based off the \l{Qt
Quick Code Samples}.
files are available for general import and they are based on the
\l{Qt Quick Examples and Tutorials}{Qt Quick Code Samples}.
This module is part of the \l{componentset}{UIComponents} example.
*/

View File

@ -4,12 +4,12 @@ contains(QT_CONFIG, accessibility) {
HEADERS += \
accessible/qaccessiblewidget.h \
accessible/qaccessiblewidgetfactory_p.h \
accessible/complexwidgets.h \
accessible/itemviews.h \
accessible/qaccessiblemenu.h \
accessible/qaccessiblewidgets.h \
accessible/rangecontrols.h \
accessible/simplewidgets.h
accessible/complexwidgets_p.h \
accessible/itemviews_p.h \
accessible/qaccessiblemenu_p.h \
accessible/qaccessiblewidgets_p.h \
accessible/rangecontrols_p.h \
accessible/simplewidgets_p.h
SOURCES += \
accessible/qaccessiblewidget.cpp \

View File

@ -31,7 +31,7 @@
**
****************************************************************************/
#include "complexwidgets.h"
#include "complexwidgets_p.h"
#include <qaccessible.h>
#include <qapplication.h>

View File

@ -34,6 +34,17 @@
#ifndef COMPLEXWIDGETS_H
#define COMPLEXWIDGETS_H
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists purely as an
// implementation detail. This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
//
#include <QtCore/qpointer.h>
#include <QtWidgets/qaccessiblewidget.h>
#include <QtWidgets/qabstractitemview.h>

View File

@ -31,7 +31,7 @@
**
****************************************************************************/
#include "itemviews.h"
#include "itemviews_p.h"
#include <qheaderview.h>
#include <qtableview.h>

View File

@ -34,6 +34,17 @@
#ifndef ACCESSIBLE_ITEMVIEWS_H
#define ACCESSIBLE_ITEMVIEWS_H
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists purely as an
// implementation detail. This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
//
#include "QtCore/qpointer.h"
#include <QtGui/qaccessible.h>
#include <QtWidgets/qaccessiblewidget.h>

View File

@ -31,7 +31,7 @@
**
****************************************************************************/
#include "qaccessiblemenu.h"
#include "qaccessiblemenu_p.h"
#include <qmenu.h>
#include <qmenubar.h>

View File

@ -34,6 +34,17 @@
#ifndef QACCESSIBLEMENU_H
#define QACCESSIBLEMENU_H
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists purely as an
// implementation detail. This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
//
#include <QtWidgets/qaccessiblewidget.h>
#include <QtCore/qpointer.h>

View File

@ -31,12 +31,12 @@
**
****************************************************************************/
#include "qaccessiblewidgets.h"
#include "qaccessiblemenu.h"
#include "simplewidgets.h"
#include "rangecontrols.h"
#include "complexwidgets.h"
#include "itemviews.h"
#include "qaccessiblewidgets_p.h"
#include "qaccessiblemenu_p.h"
#include "simplewidgets_p.h"
#include "rangecontrols_p.h"
#include "complexwidgets_p.h"
#include "itemviews_p.h"
#include <qpushbutton.h>
#include <qtoolbutton.h>

View File

@ -36,6 +36,17 @@
#ifndef QACCESSIBLEWIDGETFACTORY_H
#define QACCESSIBLEWIDGETFACTORY_H
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists purely as an
// implementation detail. This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
//
QT_BEGIN_NAMESPACE
QAccessibleInterface *qAccessibleFactory(const QString &classname, QObject *object);

View File

@ -31,7 +31,7 @@
**
****************************************************************************/
#include "qaccessiblewidgets.h"
#include "qaccessiblewidgets_p.h"
#include "qabstracttextdocumentlayout.h"
#include "qapplication.h"
#include "qclipboard.h"

View File

@ -34,6 +34,17 @@
#ifndef QACCESSIBLEWIDGETS_H
#define QACCESSIBLEWIDGETS_H
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists purely as an
// implementation detail. This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
//
#include <QtWidgets/qaccessiblewidget.h>
#ifndef QT_NO_ACCESSIBILITY

View File

@ -31,7 +31,7 @@
**
****************************************************************************/
#include "rangecontrols.h"
#include "rangecontrols_p.h"
#include <qslider.h>
#include <qdial.h>
@ -47,7 +47,7 @@
#include <qmath.h>
#include <private/qmath_p.h>
#include "simplewidgets.h" // let spinbox use line edit's interface
#include "simplewidgets_p.h" // let spinbox use line edit's interface
QT_BEGIN_NAMESPACE

View File

@ -34,6 +34,17 @@
#ifndef RANGECONTROLS_H
#define RANGECONTROLS_H
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists purely as an
// implementation detail. This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
//
#include <QtWidgets/qaccessiblewidget.h>
QT_BEGIN_NAMESPACE

View File

@ -31,7 +31,7 @@
**
****************************************************************************/
#include "simplewidgets.h"
#include "simplewidgets_p.h"
#include <qabstractbutton.h>
#include <qcheckbox.h>

View File

@ -34,6 +34,17 @@
#ifndef SIMPLEWIDGETS_H
#define SIMPLEWIDGETS_H
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists purely as an
// implementation detail. This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
//
#include <QtCore/qcoreapplication.h>
#include <QtWidgets/qaccessiblewidget.h>

View File

@ -2851,6 +2851,9 @@ void QFileDialogPrivate::createWidgets()
completer = new QFSCompleter(model, q);
qFileDialogUi->fileNameEdit->setCompleter(completer);
#endif // QT_NO_FSCOMPLETER
qFileDialogUi->fileNameEdit->setInputMethodHints(Qt::ImhNoPredictiveText);
QObject::connect(qFileDialogUi->fileNameEdit, SIGNAL(textChanged(QString)),
q, SLOT(_q_autoCompleteFileName(QString)));
QObject::connect(qFileDialogUi->fileNameEdit, SIGNAL(textChanged(QString)),

View File

@ -26,7 +26,7 @@ qhp.QtWidgets.subprojects.classes.sortPages = true
tagfile = ../../../doc/qtwidgets/qtwidgets.tags
depends += qtcore qtgui qtdoc qtsql qtdesigner qtquick
depends += qtcore qtgui qtdoc qtsql qtdesigner qtquick qmake qtsvg
headerdirs += ..

View File

@ -5828,7 +5828,10 @@ QPixmap QWidgetEffectSourcePrivate::pixmap(Qt::CoordinateSystem system, QPoint *
pixmapOffset -= effectRect.topLeft();
QPixmap pixmap(effectRect.size());
const qreal dpr = context->painter->device()->devicePixelRatio();
QPixmap pixmap(effectRect.size() * dpr);
pixmap.setDevicePixelRatio(dpr);
pixmap.fill(Qt::transparent);
m_widget->render(&pixmap, pixmapOffset, QRegion(), QWidget::DrawChildren);
return pixmap;

View File

@ -26,7 +26,7 @@ qhp.QtXml.subprojects.classes.sortPages = true
tagfile = ../../../doc/qtxml/qtxml.tags
depends += qtcore qtnetwork qtdoc qtwidgets
depends += qtcore qtnetwork qtdoc qtwidgets qmake
headerdirs += ..

View File

@ -41,12 +41,7 @@
#include <private/qeventloop_p.h>
#include <private/qthread_p.h>
#ifdef QT_GUI_LIB
#include <QtGui/QGuiApplication>
typedef QGuiApplication TestApplication;
#else
typedef QCoreApplication TestApplication;
#endif
class EventSpy : public QObject
{

View File

@ -40,6 +40,7 @@
#include <QtCore/QSocketNotifier>
#include <QtNetwork/QTcpServer>
#include <QtNetwork/QTcpSocket>
#include <QtNetwork/QUdpSocket>
#ifndef Q_OS_WINRT
#include <private/qnativesocketengine_p.h>
#else
@ -66,8 +67,29 @@ private slots:
#ifdef Q_OS_UNIX
void posixSockets();
#endif
void asyncMultipleDatagram();
protected slots:
void async_readDatagramSlot();
void async_writeDatagramSlot();
private:
QUdpSocket *m_asyncSender;
QUdpSocket *m_asyncReceiver;
};
static QHostAddress makeNonAny(const QHostAddress &address,
QHostAddress::SpecialAddress preferForAny = QHostAddress::LocalHost)
{
if (address == QHostAddress::Any)
return preferForAny;
if (address == QHostAddress::AnyIPv4)
return QHostAddress::LocalHost;
if (address == QHostAddress::AnyIPv6)
return QHostAddress::LocalHostIPv6;
return address;
}
class UnexpectedDisconnectTester : public QObject
{
Q_OBJECT
@ -299,5 +321,56 @@ void tst_QSocketNotifier::posixSockets()
}
#endif
void tst_QSocketNotifier::async_readDatagramSlot()
{
char buf[1];
QVERIFY(m_asyncReceiver->hasPendingDatagrams());
do {
QCOMPARE(m_asyncReceiver->pendingDatagramSize(), qint64(1));
QCOMPARE(m_asyncReceiver->readDatagram(buf, sizeof(buf)), qint64(1));
if (buf[0] == '1') {
// wait for the second datagram message.
QTest::qSleep(100);
}
} while (m_asyncReceiver->hasPendingDatagrams());
if (buf[0] == '3')
QTestEventLoop::instance().exitLoop();
}
void tst_QSocketNotifier::async_writeDatagramSlot()
{
m_asyncSender->writeDatagram("3", makeNonAny(m_asyncReceiver->localAddress()),
m_asyncReceiver->localPort());
}
void tst_QSocketNotifier::asyncMultipleDatagram()
{
m_asyncSender = new QUdpSocket;
m_asyncReceiver = new QUdpSocket;
QVERIFY(m_asyncReceiver->bind(QHostAddress(QHostAddress::AnyIPv4), 0));
quint16 port = m_asyncReceiver->localPort();
QVERIFY(port != 0);
QSignalSpy spy(m_asyncReceiver, &QIODevice::readyRead);
connect(m_asyncReceiver, &QIODevice::readyRead, this,
&tst_QSocketNotifier::async_readDatagramSlot);
m_asyncSender->writeDatagram("1", makeNonAny(m_asyncReceiver->localAddress()), port);
m_asyncSender->writeDatagram("2", makeNonAny(m_asyncReceiver->localAddress()), port);
// wait a little to ensure that the datagrams we've just sent
// will be delivered on receiver side.
QTest::qSleep(100);
QTimer::singleShot(500, this, &tst_QSocketNotifier::async_writeDatagramSlot);
QTestEventLoop::instance().enterLoop(1);
QVERIFY(!QTestEventLoop::instance().timeout());
QCOMPARE(spy.count(), 2);
delete m_asyncSender;
delete m_asyncReceiver;
}
QTEST_MAIN(tst_QSocketNotifier)
#include <tst_qsocketnotifier.moc>

View File

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<mime-info xmlns='http://www.freedesktop.org/standards/shared-mime-info'>
<mime-type type="text/invalid-magic1">
<comment>wrong value for byte type</comment>
<magic>
<match value="foo" type="byte" offset="0"/>
</magic>
</mime-type>
</mime-info>

View File

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<mime-info xmlns='http://www.freedesktop.org/standards/shared-mime-info'>
<mime-type type="text/invalid-magic2">
<comment>mask doesn't start with 0x</comment>
<magic>
<match value="foo" type="string" mask="ffff" offset="0"/>
</magic>
</mime-type>
</mime-info>

View File

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<mime-info xmlns='http://www.freedesktop.org/standards/shared-mime-info'>
<mime-type type="text/invalid-magic3">
<comment>mask has wrong size</comment>
<magic>
<match value="foo" type="string" mask="0xffff" offset="0"/>
</magic>
</mime-type>
</mime-info>

View File

@ -4,5 +4,8 @@
<file alias="qml-again.xml">qml-again.xml</file>
<file alias="text-x-objcsrc.xml">text-x-objcsrc.xml</file>
<file alias="test.qml">test.qml</file>
<file>invalid-magic1.xml</file>
<file>invalid-magic2.xml</file>
<file>invalid-magic3.xml</file>
</qresource>
</RCC>

View File

@ -45,9 +45,16 @@
#include <QtTest/QtTest>
static const char yastFileName[] ="yast2-metapackage-handler-mimetypes.xml";
static const char qmlAgainFileName[] ="qml-again.xml";
static const char textXObjCSrcFileName[] ="text-x-objcsrc.xml";
static const char *const additionalMimeFiles[] = {
"yast2-metapackage-handler-mimetypes.xml",
"qml-again.xml",
"text-x-objcsrc.xml",
"invalid-magic1.xml",
"invalid-magic2.xml",
"invalid-magic3.xml",
0
};
#define RESOURCE_PREFIX ":/qt-project.org/qmime/"
void initializeLang()
@ -149,12 +156,12 @@ void tst_QMimeDatabase::initTestCase()
qWarning("%s", qPrintable(testSuiteWarning()));
errorMessage = QString::fromLatin1("Cannot find '%1'");
m_yastMimeTypes = QLatin1String(RESOURCE_PREFIX) + yastFileName;
QVERIFY2(QFile::exists(m_yastMimeTypes), qPrintable(errorMessage.arg(yastFileName)));
m_qmlAgainFileName = QLatin1String(RESOURCE_PREFIX) + qmlAgainFileName;
QVERIFY2(QFile::exists(m_qmlAgainFileName), qPrintable(errorMessage.arg(qmlAgainFileName)));
m_textXObjCSrcFileName = QLatin1String(RESOURCE_PREFIX) + textXObjCSrcFileName;
QVERIFY2(QFile::exists(m_textXObjCSrcFileName), qPrintable(errorMessage.arg(textXObjCSrcFileName)));
for (uint i = 0; i < sizeof additionalMimeFiles / sizeof additionalMimeFiles[0] - 1; i++) {
const QString resourceFilePath = QString::fromLatin1(RESOURCE_PREFIX) + QLatin1String(additionalMimeFiles[i]);
QVERIFY2(QFile::exists(resourceFilePath), qPrintable(errorMessage.arg(resourceFilePath)));
m_additionalMimeFileNames.append(QLatin1String(additionalMimeFiles[i]));
m_additionalMimeFilePaths.append(resourceFilePath);
}
initTestCaseInternal();
m_isUsingCacheProvider = !qEnvironmentVariableIsSet("QT_NO_MIME_CACHE");
@ -859,6 +866,14 @@ static void checkHasMimeType(const QString &mimeType)
QVERIFY(found);
}
static void ignoreInvalidMimetypeWarnings(const QString &mimeDir)
{
const QByteArray basePath = QFile::encodeName(mimeDir) + "/packages/";
QTest::ignoreMessage(QtWarningMsg, ("QMimeDatabase: Error parsing " + basePath + "invalid-magic1.xml\nInvalid magic rule value \"foo\"").constData());
QTest::ignoreMessage(QtWarningMsg, ("QMimeDatabase: Error parsing " + basePath + "invalid-magic2.xml\nInvalid magic rule mask \"ffff\"").constData());
QTest::ignoreMessage(QtWarningMsg, ("QMimeDatabase: Error parsing " + basePath + "invalid-magic3.xml\nInvalid magic rule mask size \"0xffff\"").constData());
}
QT_BEGIN_NAMESPACE
extern Q_CORE_EXPORT int qmime_secondsBetweenChecks; // see qmimeprovider.cpp
QT_END_NAMESPACE
@ -879,23 +894,21 @@ void tst_QMimeDatabase::installNewGlobalMimeType()
const QString mimeDir = m_globalXdgDir + QLatin1String("/mime");
const QString destDir = mimeDir + QLatin1String("/packages/");
const QString destFile = destDir + QLatin1String(yastFileName);
QFile::remove(destFile);
const QString destQmlFile = destDir + QLatin1String(qmlAgainFileName);
QFile::remove(destQmlFile);
const QString destTextXObjCSrcFile = destDir + QLatin1String(textXObjCSrcFileName);
QFile::remove(destTextXObjCSrcFile);
//qDebug() << destFile;
if (!QFileInfo(destDir).isDir())
QVERIFY(QDir(m_globalXdgDir).mkpath(destDir));
QString errorMessage;
QVERIFY2(copyResourceFile(m_yastMimeTypes, destFile, &errorMessage), qPrintable(errorMessage));
QVERIFY2(copyResourceFile(m_qmlAgainFileName, destQmlFile, &errorMessage), qPrintable(errorMessage));
QVERIFY2(copyResourceFile(m_textXObjCSrcFileName, destTextXObjCSrcFile, &errorMessage), qPrintable(errorMessage));
for (int i = 0; i < m_additionalMimeFileNames.size(); ++i) {
const QString destFile = destDir + m_additionalMimeFileNames.at(i);
QFile::remove(destFile);
QVERIFY2(copyResourceFile(m_additionalMimeFilePaths.at(i), destFile, &errorMessage), qPrintable(errorMessage));
}
if (m_isUsingCacheProvider && !waitAndRunUpdateMimeDatabase(mimeDir))
QSKIP("shared-mime-info not found, skipping mime.cache test");
if (!m_isUsingCacheProvider)
ignoreInvalidMimetypeWarnings(mimeDir);
QCOMPARE(db.mimeTypeForFile(QLatin1String("foo.ymu"), QMimeDatabase::MatchExtension).name(),
QString::fromLatin1("text/x-SuSE-ymu"));
QVERIFY(db.mimeTypeForName(QLatin1String("text/x-suse-ymp")).isValid());
@ -916,10 +929,9 @@ void tst_QMimeDatabase::installNewGlobalMimeType()
qDebug() << objcsrc.globPatterns();
}
// Now test removing it again
QVERIFY(QFile::remove(destFile));
QVERIFY(QFile::remove(destQmlFile));
QVERIFY(QFile::remove(destTextXObjCSrcFile));
// Now test removing the mimetype definitions again
for (int i = 0; i < m_additionalMimeFileNames.size(); ++i)
QFile::remove(destDir + m_additionalMimeFileNames.at(i));
if (m_isUsingCacheProvider && !waitAndRunUpdateMimeDatabase(mimeDir))
QSKIP("shared-mime-info not found, skipping mime.cache test");
QCOMPARE(db.mimeTypeForFile(QLatin1String("foo.ymu"), QMimeDatabase::MatchExtension).name(),
@ -936,23 +948,35 @@ void tst_QMimeDatabase::installNewLocalMimeType()
qmime_secondsBetweenChecks = 0;
QMimeDatabase db;
// Check that we're starting clean
QVERIFY(!db.mimeTypeForName(QLatin1String("text/x-suse-ymp")).isValid());
QVERIFY(!db.mimeTypeForName(QLatin1String("text/invalid-magic1")).isValid());
const QString destDir = m_localMimeDir + QLatin1String("/packages/");
QDir().mkpath(destDir);
const QString destFile = destDir + QLatin1String(yastFileName);
QFile::remove(destFile);
const QString destQmlFile = destDir + QLatin1String(qmlAgainFileName);
QFile::remove(destQmlFile);
QVERIFY(QDir().mkpath(destDir));
QString errorMessage;
QVERIFY2(copyResourceFile(m_yastMimeTypes, destFile, &errorMessage), qPrintable(errorMessage));
QVERIFY2(copyResourceFile(m_qmlAgainFileName, destQmlFile, &errorMessage), qPrintable(errorMessage));
if (m_isUsingCacheProvider && !runUpdateMimeDatabase(m_localMimeDir)) {
for (int i = 0; i < m_additionalMimeFileNames.size(); ++i) {
const QString destFile = destDir + m_additionalMimeFileNames.at(i);
QFile::remove(destFile);
QVERIFY2(copyResourceFile(m_additionalMimeFilePaths.at(i), destFile, &errorMessage), qPrintable(errorMessage));
}
if (m_isUsingCacheProvider && !waitAndRunUpdateMimeDatabase(m_localMimeDir)) {
const QString skipWarning = QStringLiteral("shared-mime-info not found, skipping mime.cache test (")
+ QDir::toNativeSeparators(m_localMimeDir) + QLatin1Char(')');
QSKIP(qPrintable(skipWarning));
}
if (!m_isUsingCacheProvider)
ignoreInvalidMimetypeWarnings(m_localMimeDir);
QVERIFY(db.mimeTypeForName(QLatin1String("text/x-suse-ymp")).isValid());
// These mimetypes have invalid magic, but still do exist.
QVERIFY(db.mimeTypeForName(QLatin1String("text/invalid-magic1")).isValid());
QVERIFY(db.mimeTypeForName(QLatin1String("text/invalid-magic2")).isValid());
QVERIFY(db.mimeTypeForName(QLatin1String("text/invalid-magic3")).isValid());
QCOMPARE(db.mimeTypeForFile(QLatin1String("foo.ymu"), QMimeDatabase::MatchExtension).name(),
QString::fromLatin1("text/x-SuSE-ymu"));
QVERIFY(db.mimeTypeForName(QLatin1String("text/x-suse-ymp")).isValid());
@ -968,8 +992,8 @@ void tst_QMimeDatabase::installNewLocalMimeType()
QString::fromLatin1("text/x-qml"));
// Now test removing the local mimetypes again (note, this leaves a mostly-empty mime.cache file)
QVERIFY(QFile::remove(destFile));
QVERIFY(QFile::remove(destQmlFile));
for (int i = 0; i < m_additionalMimeFileNames.size(); ++i)
QFile::remove(destDir + m_additionalMimeFileNames.at(i));
if (m_isUsingCacheProvider && !waitAndRunUpdateMimeDatabase(m_localMimeDir))
QSKIP("shared-mime-info not found, skipping mime.cache test");
QCOMPARE(db.mimeTypeForFile(QLatin1String("foo.ymu"), QMimeDatabase::MatchExtension).name(),

View File

@ -36,6 +36,7 @@
#include <QtCore/QObject>
#include <QtCore/QTemporaryDir>
#include <QtCore/QStringList>
class tst_QMimeDatabase : public QObject
{
@ -92,9 +93,8 @@ private:
QString m_globalXdgDir;
QString m_localMimeDir;
QString m_yastMimeTypes;
QString m_qmlAgainFileName;
QString m_textXObjCSrcFileName;
QStringList m_additionalMimeFileNames;
QStringList m_additionalMimeFilePaths;
QTemporaryDir m_temporaryDir;
QString m_testSuite;
bool m_isUsingCacheProvider;

View File

@ -60,6 +60,7 @@ class tst_QGuiApplication: public tst_QCoreApplication
Q_OBJECT
private slots:
void initTestCase();
void cleanup();
void displayName();
void firstWindowTitle();
@ -84,6 +85,21 @@ private slots:
void settableStyleHints(); // Needs to run last as it changes style hints.
};
void tst_QGuiApplication::initTestCase()
{
#ifdef QT_QPA_DEFAULT_PLATFORM_NAME
if ((QString::compare(QStringLiteral(QT_QPA_DEFAULT_PLATFORM_NAME),
QStringLiteral("eglfs"), Qt::CaseInsensitive) == 0) ||
(QString::compare(QString::fromLatin1(qgetenv("QT_QPA_PLATFORM")),
QStringLiteral("eglfs"), Qt::CaseInsensitive) == 0)) {
// Set env variables to disable input and cursor because eglfs is single fullscreen window
// and trying to initialize input and cursor will crash test.
qputenv("QT_QPA_EGLFS_DISABLE_INPUT", "1");
qputenv("QT_QPA_EGLFS_HIDECURSOR", "1");
}
#endif
}
void tst_QGuiApplication::cleanup()
{
QVERIFY(QGuiApplication::allWindows().isEmpty());

View File

@ -116,10 +116,12 @@ private slots:
void linkLocalIPv4();
void readyRead();
void readyReadForEmptyDatagram();
void asyncReadDatagram();
protected slots:
void empty_readyReadSlot();
void empty_connectedSlot();
void async_readDatagramSlot();
private:
#ifndef QT_NO_BEARERMANAGEMENT
@ -127,6 +129,8 @@ private:
QNetworkConfiguration networkConfiguration;
QSharedPointer<QNetworkSession> networkSession;
#endif
QUdpSocket *m_asyncSender;
QUdpSocket *m_asyncReceiver;
};
static QHostAddress makeNonAny(const QHostAddress &address, QHostAddress::SpecialAddress preferForAny = QHostAddress::LocalHost)
@ -1671,5 +1675,55 @@ void tst_QUdpSocket::readyReadForEmptyDatagram()
QCOMPARE(receiver.readDatagram(buf, sizeof buf), qint64(0));
}
void tst_QUdpSocket::async_readDatagramSlot()
{
char buf[1];
QVERIFY(m_asyncReceiver->hasPendingDatagrams());
QCOMPARE(m_asyncReceiver->pendingDatagramSize(), qint64(1));
QCOMPARE(m_asyncReceiver->bytesAvailable(), qint64(1));
QCOMPARE(m_asyncReceiver->readDatagram(buf, sizeof(buf)), qint64(1));
if (buf[0] == '2') {
QTestEventLoop::instance().exitLoop();
return;
}
m_asyncSender->writeDatagram("2", makeNonAny(m_asyncReceiver->localAddress()), m_asyncReceiver->localPort());
// wait a little to ensure that the datagram we've just sent
// will be delivered on receiver side.
QTest::qSleep(100);
}
void tst_QUdpSocket::asyncReadDatagram()
{
QFETCH_GLOBAL(bool, setProxy);
if (setProxy)
return;
m_asyncSender = new QUdpSocket;
m_asyncReceiver = new QUdpSocket;
#ifdef FORCE_SESSION
m_asyncSender->setProperty("_q_networksession", QVariant::fromValue(networkSession));
m_asyncReceiver->setProperty("_q_networksession", QVariant::fromValue(networkSession));
#endif
QVERIFY(m_asyncReceiver->bind(QHostAddress(QHostAddress::AnyIPv4), 0));
quint16 port = m_asyncReceiver->localPort();
QVERIFY(port != 0);
QSignalSpy spy(m_asyncReceiver, SIGNAL(readyRead()));
connect(m_asyncReceiver, SIGNAL(readyRead()), SLOT(async_readDatagramSlot()));
m_asyncSender->writeDatagram("1", makeNonAny(m_asyncReceiver->localAddress()), port);
QTestEventLoop::instance().enterLoop(1);
QVERIFY(!QTestEventLoop::instance().timeout());
QCOMPARE(spy.count(), 2);
delete m_asyncSender;
delete m_asyncReceiver;
}
QTEST_MAIN(tst_QUdpSocket)
#include "tst_qudpsocket.moc"

View File

@ -45,9 +45,11 @@ private slots:
void tst_QProcess_and_GuiEventLoop::waitForAndEventLoop()
{
#if defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_NO_SDK)
#if defined(QT_NO_PROCESS)
QSKIP("QProcess not supported");
#elif defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_NO_SDK)
QSKIP("Not supported on Android");
#endif
#else
// based on testcase provided in QTBUG-39488
QByteArray msg = "Hello World";
@ -78,6 +80,7 @@ void tst_QProcess_and_GuiEventLoop::waitForAndEventLoop()
QCOMPARE(process.exitCode(), 0);
QCOMPARE(spy.count(), 1);
QCOMPARE(process.readAll().trimmed(), msg);
#endif
}
QTEST_MAIN(tst_QProcess_and_GuiEventLoop)