Merge remote-tracking branch 'origin/5.7' into 5.8

Conflicts:
	src/gui/image/qpixmap.cpp
	src/widgets/kernel/qformlayout.cpp

Change-Id: I8a8391a202adf7f18464a22ddf0a6c4974eab692
This commit is contained in:
Liang Qi 2016-10-11 07:40:32 +02:00
commit 905329200f
33 changed files with 278 additions and 125 deletions

View File

@ -110,12 +110,13 @@ void Client::readFortune()
in.setVersion(QDataStream::Qt_4_0);
if (blockSize == 0) {
if (socket->bytesAvailable() < (int)sizeof(quint16))
// Relies on the fact that QDataStream format streams a quint32 into sizeof(quint32) bytes
if (socket->bytesAvailable() < (int)sizeof(quint32))
return;
in >> blockSize;
}
if (in.atEnd())
if (socket->bytesAvailable() < blockSize || in.atEnd())
return;
QString nextFortune;

View File

@ -86,7 +86,7 @@ private:
QLocalSocket *socket;
QString currentFortune;
quint16 blockSize;
quint32 blockSize;
};
#endif

View File

@ -106,10 +106,10 @@ void Server::sendFortune()
QByteArray block;
QDataStream out(&block, QIODevice::WriteOnly);
out.setVersion(QDataStream::Qt_4_0);
out << (quint16)0;
out << (quint32)0;
out << fortunes.at(qrand() % fortunes.size());
out.device()->seek(0);
out << (quint16)(block.size() - sizeof(quint16));
out << (quint32)(block.size() - sizeof(quint32));
QLocalSocket *clientConnection = server->nextPendingConnection();
connect(clientConnection, SIGNAL(disconnected()),

View File

@ -3,7 +3,7 @@ MAKEFILE_GENERATOR = UNIX
QMAKE_PLATFORM = android
QMAKE_COMPILER = gcc clang llvm
CONFIG += android_install unversioned_soname unversioned_libname android_deployment_settings
CONFIG += android_install unversioned_soname unversioned_libname plugin_with_soname android_deployment_settings
include(../common/linux.conf)
include(../common/clang.conf)

View File

@ -3,7 +3,7 @@ MAKEFILE_GENERATOR = UNIX
QMAKE_PLATFORM = android
QMAKE_COMPILER = gcc
CONFIG += android_install unversioned_soname unversioned_libname android_deployment_settings
CONFIG += android_install unversioned_soname unversioned_libname plugin_with_soname android_deployment_settings
include(../common/linux.conf)
include(../common/gcc-base-unix.conf)

View File

@ -87,8 +87,9 @@ have_target:!static:if(darwin|!isEmpty(QMAKE_OBJCOPY)) {
QMAKE_POST_LINK = $$mkdir_debug_info && $$copy_debug_info && $$strip_debug_info $$QMAKE_POST_LINK
} else {
link_debug_info = $$QMAKE_OBJCOPY --add-gnu-debuglink=$$shell_target_debug_info $$shell_target
chmod_debug_info = chmod -x $$shell_target_debug_info
QMAKE_POST_LINK = $$copy_debug_info && $$strip_debug_info && $$link_debug_info && $$chmod_debug_info $$QMAKE_POST_LINK
!contains(QMAKE_HOST.os, Windows): \
QMAKE_POST_LINK = && chmod -x $$shell_target_debug_info $$QMAKE_POST_LINK
QMAKE_POST_LINK = $$copy_debug_info && $$strip_debug_info && $$link_debug_info $$QMAKE_POST_LINK
}
silent:QMAKE_POST_LINK = @echo creating $@.$$debug_info_suffix && $$QMAKE_POST_LINK

View File

@ -87,7 +87,7 @@ bool QFseventsFileSystemWatcherEngine::checkDir(DirsByName::iterator &it)
if (res == -1) {
needsRestart |= derefPath(info.watchedPath);
emit emitDirectoryChanged(info.origPath, true);
it = watchedDirectories.erase(it);
it = watchingState.watchedDirectories.erase(it);
} else if (st.st_ctimespec != info.ctime || st.st_mode != info.mode) {
info.ctime = st.st_ctimespec;
info.mode = st.st_mode;
@ -138,7 +138,8 @@ bool QFseventsFileSystemWatcherEngine::rescanDirs(const QString &path)
{
bool needsRestart = false;
for (DirsByName::iterator it = watchedDirectories.begin(); it != watchedDirectories.end(); ) {
for (DirsByName::iterator it = watchingState.watchedDirectories.begin();
it != watchingState.watchedDirectories.end(); ) {
if (it.key().startsWith(path))
needsRestart |= checkDir(it);
else
@ -177,11 +178,12 @@ bool QFseventsFileSystemWatcherEngine::rescanFiles(const QString &path)
{
bool needsRestart = false;
for (FilesByPath::iterator i = watchedFiles.begin(); i != watchedFiles.end(); ) {
for (FilesByPath::iterator i = watchingState.watchedFiles.begin();
i != watchingState.watchedFiles.end(); ) {
if (i.key().startsWith(path)) {
needsRestart |= rescanFiles(i.value());
if (i.value().isEmpty()) {
i = watchedFiles.erase(i);
i = watchingState.watchedFiles.erase(i);
continue;
}
}
@ -232,8 +234,8 @@ void QFseventsFileSystemWatcherEngine::processEvent(ConstFSEventStreamRef stream
if (eFlags & kFSEventStreamEventFlagRootChanged) {
// re-check everything:
DirsByName::iterator dirIt = watchedDirectories.find(path);
if (dirIt != watchedDirectories.end())
DirsByName::iterator dirIt = watchingState.watchedDirectories.find(path);
if (dirIt != watchingState.watchedDirectories.end())
needsRestart |= checkDir(dirIt);
needsRestart |= rescanFiles(path);
continue;
@ -243,13 +245,13 @@ void QFseventsFileSystemWatcherEngine::processEvent(ConstFSEventStreamRef stream
needsRestart |= rescanDirs(path);
// check watched directories:
DirsByName::iterator dirIt = watchedDirectories.find(path);
if (dirIt != watchedDirectories.end())
DirsByName::iterator dirIt = watchingState.watchedDirectories.find(path);
if (dirIt != watchingState.watchedDirectories.end())
needsRestart |= checkDir(dirIt);
// check watched files:
FilesByPath::iterator pIt = watchedFiles.find(path);
if (pIt != watchedFiles.end())
FilesByPath::iterator pIt = watchingState.watchedFiles.find(path);
if (pIt != watchingState.watchedFiles.end())
needsRestart |= rescanFiles(pIt.value());
}
@ -276,12 +278,11 @@ void QFseventsFileSystemWatcherEngine::doEmitDirectoryChanged(const QString &pat
emit directoryChanged(path, removed);
}
void QFseventsFileSystemWatcherEngine::restartStream()
bool QFseventsFileSystemWatcherEngine::restartStream()
{
QMacAutoReleasePool pool;
QMutexLocker locker(&lock);
stopStream();
startStream();
return startStream();
}
QFseventsFileSystemWatcherEngine *QFseventsFileSystemWatcherEngine::create(QObject *parent)
@ -311,6 +312,7 @@ QFseventsFileSystemWatcherEngine::~QFseventsFileSystemWatcherEngine()
{
QMacAutoReleasePool pool;
// Stop the stream in case we have to wait for the lock below to be acquired.
if (stream)
FSEventStreamStop(stream);
@ -334,8 +336,10 @@ QStringList QFseventsFileSystemWatcherEngine::addPaths(const QStringList &paths,
QMutexLocker locker(&lock);
bool wasRunning = stream != Q_NULLPTR;
bool needsRestart = false;
WatchingState oldState = watchingState;
QStringList p = paths;
QMutableListIterator<QString> it(p);
while (it.hasNext()) {
@ -356,7 +360,7 @@ QStringList QFseventsFileSystemWatcherEngine::addPaths(const QStringList &paths,
const bool isDir = S_ISDIR(st.st_mode);
if (isDir) {
if (watchedDirectories.contains(realPath))
if (watchingState.watchedDirectories.contains(realPath))
continue;
directories->append(origPath);
watchedPath = realPath;
@ -371,17 +375,18 @@ QStringList QFseventsFileSystemWatcherEngine::addPaths(const QStringList &paths,
parentPath = watchedPath;
}
for (PathRefCounts::const_iterator i = watchedPaths.begin(), ei = watchedPaths.end(); i != ei; ++i) {
for (PathRefCounts::const_iterator i = watchingState.watchedPaths.begin(),
ei = watchingState.watchedPaths.end(); i != ei; ++i) {
if (watchedPath.startsWith(i.key())) {
watchedPath = i.key();
break;
}
}
PathRefCounts::iterator it = watchedPaths.find(watchedPath);
if (it == watchedPaths.end()) {
PathRefCounts::iterator it = watchingState.watchedPaths.find(watchedPath);
if (it == watchingState.watchedPaths.end()) {
needsRestart = true;
watchedPaths.insert(watchedPath, 1);
watchingState.watchedPaths.insert(watchedPath, 1);
DEBUG("Adding '%s' to watchedPaths", qPrintable(watchedPath));
} else {
++it.value();
@ -392,18 +397,25 @@ QStringList QFseventsFileSystemWatcherEngine::addPaths(const QStringList &paths,
DirInfo dirInfo;
dirInfo.dirInfo = info;
dirInfo.entries = scanForDirEntries(realPath);
watchedDirectories.insert(realPath, dirInfo);
watchingState.watchedDirectories.insert(realPath, dirInfo);
DEBUG("-- Also adding '%s' to watchedDirectories", qPrintable(realPath));
} else {
watchedFiles[parentPath].insert(realPath, info);
watchingState.watchedFiles[parentPath].insert(realPath, info);
DEBUG("-- Also adding '%s' to watchedFiles", qPrintable(realPath));
}
}
if (needsRestart) {
stopStream();
if (!startStream())
if (!startStream()) {
// ok, something went wrong, let's try to restore the previous state
watchingState = qMove(oldState);
// and because we don't know which path caused the issue (if any), fail on all of them
p = paths;
if (wasRunning)
startStream();
}
}
return p;
@ -419,6 +431,7 @@ QStringList QFseventsFileSystemWatcherEngine::removePaths(const QStringList &pat
bool needsRestart = false;
WatchingState oldState = watchingState;
QStringList p = paths;
QMutableListIterator<QString> it(p);
while (it.hasNext()) {
@ -431,10 +444,10 @@ QStringList QFseventsFileSystemWatcherEngine::removePaths(const QStringList &pat
realPath = fi.canonicalFilePath();
if (fi.isDir()) {
DirsByName::iterator dirIt = watchedDirectories.find(realPath);
if (dirIt != watchedDirectories.end()) {
DirsByName::iterator dirIt = watchingState.watchedDirectories.find(realPath);
if (dirIt != watchingState.watchedDirectories.end()) {
needsRestart |= derefPath(dirIt->dirInfo.watchedPath);
watchedDirectories.erase(dirIt);
watchingState.watchedDirectories.erase(dirIt);
directories->removeAll(origPath);
it.remove();
DEBUG("Removed directory '%s'", qPrintable(realPath));
@ -442,15 +455,15 @@ QStringList QFseventsFileSystemWatcherEngine::removePaths(const QStringList &pat
} else {
QFileInfo fi(realPath);
QString parentPath = fi.path();
FilesByPath::iterator pIt = watchedFiles.find(parentPath);
if (pIt != watchedFiles.end()) {
FilesByPath::iterator pIt = watchingState.watchedFiles.find(parentPath);
if (pIt != watchingState.watchedFiles.end()) {
InfoByName &filesInDir = pIt.value();
InfoByName::iterator fIt = filesInDir.find(realPath);
if (fIt != filesInDir.end()) {
needsRestart |= derefPath(fIt->watchedPath);
filesInDir.erase(fIt);
if (filesInDir.isEmpty())
watchedFiles.erase(pIt);
watchingState.watchedFiles.erase(pIt);
files->removeAll(origPath);
it.remove();
DEBUG("Removed file '%s'", qPrintable(realPath));
@ -461,26 +474,33 @@ QStringList QFseventsFileSystemWatcherEngine::removePaths(const QStringList &pat
locker.unlock();
if (needsRestart)
restartStream();
if (needsRestart) {
if (!restartStream()) {
watchingState = qMove(oldState);
startStream();
}
}
return p;
}
// Returns false if FSEventStream* calls failed for some mysterious reason, true if things got a
// thumbs-up.
bool QFseventsFileSystemWatcherEngine::startStream()
{
Q_ASSERT(stream == 0);
QMacAutoReleasePool pool;
if (stream) // This shouldn't happen, but let's be nice and handle it.
if (stream) // Ok, this really shouldn't happen, esp. not after the assert. But let's be nice in release mode and still handle it.
stopStream();
if (watchedPaths.isEmpty())
return false;
QMacAutoReleasePool pool;
DEBUG() << "Starting stream with paths" << watchedPaths.keys();
if (watchingState.watchedPaths.isEmpty())
return true; // we succeeded in doing nothing
NSMutableArray *pathsToWatch = [NSMutableArray arrayWithCapacity:watchedPaths.size()];
for (PathRefCounts::const_iterator i = watchedPaths.begin(), ei = watchedPaths.end(); i != ei; ++i)
DEBUG() << "Starting stream with paths" << watchingState.watchedPaths.keys();
NSMutableArray *pathsToWatch = [NSMutableArray arrayWithCapacity:watchingState.watchedPaths.size()];
for (PathRefCounts::const_iterator i = watchingState.watchedPaths.begin(), ei = watchingState.watchedPaths.end(); i != ei; ++i)
[pathsToWatch addObject:i.key().toNSString()];
struct FSEventStreamContext callBackInfo = {
@ -504,7 +524,7 @@ bool QFseventsFileSystemWatcherEngine::startStream()
latency,
FSEventStreamCreateFlags(0));
if (!stream) {
if (!stream) { // nope, no way to know what went wrong, so just fail
DEBUG() << "Failed to create stream!";
return false;
}
@ -514,7 +534,7 @@ bool QFseventsFileSystemWatcherEngine::startStream()
if (FSEventStreamStart(stream)) {
DEBUG() << "Stream started successfully with sinceWhen =" << lastReceivedEvent;
return true;
} else {
} else { // again, no way to know what went wrong, so just clean up and fail
DEBUG() << "Stream failed to start!";
FSEventStreamInvalidate(stream);
FSEventStreamRelease(stream);
@ -525,6 +545,7 @@ bool QFseventsFileSystemWatcherEngine::startStream()
void QFseventsFileSystemWatcherEngine::stopStream(bool isStopped)
{
QMacAutoReleasePool pool;
if (stream) {
if (!isStopped)
FSEventStreamStop(stream);
@ -554,9 +575,9 @@ QFseventsFileSystemWatcherEngine::InfoByName QFseventsFileSystemWatcherEngine::s
bool QFseventsFileSystemWatcherEngine::derefPath(const QString &watchedPath)
{
PathRefCounts::iterator it = watchedPaths.find(watchedPath);
if (it != watchedPaths.end() && --it.value() < 1) {
watchedPaths.erase(it);
PathRefCounts::iterator it = watchingState.watchedPaths.find(watchedPath);
if (it != watchingState.watchedPaths.end() && --it.value() < 1) {
watchingState.watchedPaths.erase(it);
DEBUG("Removing '%s' from watchedPaths.", qPrintable(watchedPath));
return true;
}

View File

@ -87,7 +87,7 @@ Q_SIGNALS:
private slots:
void doEmitFileChanged(const QString &path, bool removed);
void doEmitDirectoryChanged(const QString &path, bool removed);
void restartStream();
bool restartStream();
private:
struct Info {
@ -118,6 +118,19 @@ private:
typedef QHash<QString, DirInfo> DirsByName;
typedef QHash<QString, qint64> PathRefCounts;
struct WatchingState {
// These fields go hand-in-hand. FSEvents watches paths, and there is no use in watching
// the same path multiple times. So, the "refcount" on a path is the number of watched
// files that have the same path, plus the number of directories that have the same path.
//
// If the stream fails to start after adding files/directories, the watcher will try to
// keep watching files/directories that it was already watching. It does that by restoring
// the previous WatchingState and restarting the stream.
FilesByPath watchedFiles;
DirsByName watchedDirectories;
PathRefCounts watchedPaths;
};
QFseventsFileSystemWatcherEngine(QObject *parent);
bool startStream();
void stopStream(bool isStopped = false);
@ -131,10 +144,8 @@ private:
QMutex lock;
dispatch_queue_t queue;
FSEventStreamRef stream;
FilesByPath watchedFiles;
DirsByName watchedDirectories;
PathRefCounts watchedPaths;
FSEventStreamEventId lastReceivedEvent;
WatchingState watchingState;
};
QT_END_NAMESPACE

View File

@ -665,7 +665,7 @@ QString QTemporaryFile::fileTemplate() const
/*!
Sets the static portion of the file name to \a name. If the file
template ends in XXXXXX that will automatically be replaced with
template contains XXXXXX that will automatically be replaced with
the unique part of the filename, otherwise a filename will be
determined automatically based on the static portion specified.

View File

@ -611,6 +611,8 @@ void QTimer::singleShot(int msec, Qt::TimerType timerType, const QObject *receiv
A single-shot timer fires only once, non-single-shot timers fire
every \l interval milliseconds.
The default value for this property is \c false.
\sa interval, singleShot()
*/

View File

@ -39,6 +39,9 @@
#include "qdbusargument_p.h"
#include "qdbusconnection.h"
#include <qscopedpointer.h>
#include <stdlib.h>
QT_BEGIN_NAMESPACE
@ -423,12 +426,12 @@ QDBusDemarshaller *QDBusDemarshaller::endCommon()
QDBusArgument QDBusDemarshaller::duplicate()
{
QDBusDemarshaller *d = new QDBusDemarshaller(capabilities);
QScopedPointer<QDBusDemarshaller> d(new QDBusDemarshaller(capabilities));
d->iterator = iterator;
d->message = q_dbus_message_ref(message);
q_dbus_message_iter_next(&iterator);
return QDBusArgumentPrivate::create(d);
return QDBusArgumentPrivate::create(d.take());
}
QT_END_NAMESPACE

View File

@ -760,39 +760,37 @@ QBitmap QPixmap::createMaskFromColor(const QColor &maskColor, Qt::MaskMode mode)
bool QPixmap::load(const QString &fileName, const char *format, Qt::ImageConversionFlags flags)
{
if (fileName.isEmpty()) {
data.reset();
return false;
}
detach();
if (!fileName.isEmpty()) {
QFileInfo info(fileName);
// Note: If no extension is provided, we try to match the
// file against known plugin extensions
if (info.completeSuffix().isEmpty() || info.exists()) {
QString key = QLatin1String("qt_pixmap")
% info.absoluteFilePath()
% HexString<uint>(info.lastModified().toSecsSinceEpoch())
% HexString<quint64>(info.size())
% HexString<uint>(data ? data->pixelType() : QPlatformPixmap::PixmapType);
// Note: If no extension is provided, we try to match the
// file against known plugin extensions
if (!info.completeSuffix().isEmpty() && !info.exists()) {
data.reset();
return false;
}
if (QPixmapCache::find(key, this))
return true;
if (!data)
data = QPlatformPixmap::create(0, 0, QPlatformPixmap::PixmapType);
data = QPlatformPixmap::create(0, 0, data ? data->pixelType() : QPlatformPixmap::PixmapType);
if (data->fromFile(fileName, format, flags)) {
QPixmapCache::insert(key, *this);
return true;
}
}
}
if (!isNull()) {
if (isQBitmap())
*this = QBitmap();
else
data.reset();
}
return false;
}

View File

@ -1667,7 +1667,7 @@ QResizeEvent::~QResizeEvent()
The event handler QWidget::closeEvent() receives close events. The
default implementation of this event handler accepts the close
event. If you do not want your widget to be hidden, or want some
special handing, you should reimplement the event handler and
special handling, you should reimplement the event handler and
ignore() the event.
The \l{mainwindows/application#close event handler}{closeEvent() in the

View File

@ -674,8 +674,7 @@ bool QHttpNetworkConnectionPrivate::dequeueRequest(QAbstractSocket *socket)
HttpMessagePair messagePair = highPriorityQueue.takeLast();
if (!messagePair.second->d_func()->requestIsPrepared)
prepareRequest(messagePair);
channels[i].request = messagePair.first;
channels[i].reply = messagePair.second;
updateChannel(i, messagePair);
return true;
}
@ -684,13 +683,21 @@ bool QHttpNetworkConnectionPrivate::dequeueRequest(QAbstractSocket *socket)
HttpMessagePair messagePair = lowPriorityQueue.takeLast();
if (!messagePair.second->d_func()->requestIsPrepared)
prepareRequest(messagePair);
channels[i].request = messagePair.first;
channels[i].reply = messagePair.second;
updateChannel(i, messagePair);
return true;
}
return false;
}
void QHttpNetworkConnectionPrivate::updateChannel(int i, const HttpMessagePair &messagePair)
{
channels[i].request = messagePair.first;
channels[i].reply = messagePair.second;
// Now that reply is assigned a channel, correct reply to channel association
// previously set in queueRequest.
channels[i].reply->d_func()->connectionChannel = &channels[i];
}
QHttpNetworkRequest QHttpNetworkConnectionPrivate::predictNextRequest() const
{
if (!highPriorityQueue.isEmpty())

View File

@ -210,6 +210,7 @@ public:
void requeueRequest(const HttpMessagePair &pair); // e.g. after pipeline broke
bool dequeueRequest(QAbstractSocket *socket);
void prepareRequest(HttpMessagePair &request);
void updateChannel(int i, const HttpMessagePair &messagePair);
QHttpNetworkRequest predictNextRequest() const;
void fillPipeline(QAbstractSocket *socket);

View File

@ -1111,6 +1111,7 @@ void QHttpNetworkConnectionChannel::_q_encrypted()
connection->d_func()->dequeueRequest(socket);
if (reply) {
reply->setSpdyWasUsed(false);
Q_ASSERT(reply->d_func()->connectionChannel == this);
emit reply->encrypted();
}
if (reply)
@ -1137,8 +1138,6 @@ void QHttpNetworkConnectionChannel::_q_sslErrors(const QList<QSslError> &errors)
connection->d_func()->pauseConnection();
if (pendingEncrypt && !reply)
connection->d_func()->dequeueRequest(socket);
if (reply) // a reply was actually dequeued.
reply->d_func()->connectionChannel = this; // set correct channel like in sendRequest() and queueRequest();
if (connection->connectionType() == QHttpNetworkConnection::ConnectionTypeHTTP) {
if (reply)
emit reply->sslErrors(errors);

View File

@ -95,6 +95,12 @@ bool QDBusMenuConnection::registerTrayIconMenu(QDBusTrayIcon *item)
return success;
}
void QDBusMenuConnection::unregisterTrayIconMenu(QDBusTrayIcon *item)
{
if (item->menu())
connection().unregisterObject(MenuBarPath);
}
bool QDBusMenuConnection::registerTrayIcon(QDBusTrayIcon *item)
{
bool success = connection().registerService(item->instanceId());
@ -124,7 +130,7 @@ bool QDBusMenuConnection::registerTrayIcon(QDBusTrayIcon *item)
bool QDBusMenuConnection::unregisterTrayIcon(QDBusTrayIcon *item)
{
connection().unregisterObject(MenuBarPath);
unregisterTrayIconMenu(item);
connection().unregisterObject(StatusNotifierItemPath);
bool success = connection().unregisterService(item->instanceId());
if (!success)

View File

@ -72,6 +72,7 @@ public:
bool isStatusNotifierHostRegistered() const { return m_statusNotifierHostRegistered; }
#ifndef QT_NO_SYSTEMTRAYICON
bool registerTrayIconMenu(QDBusTrayIcon *item);
void unregisterTrayIconMenu(QDBusTrayIcon *item);
bool registerTrayIcon(QDBusTrayIcon *item);
bool unregisterTrayIcon(QDBusTrayIcon *item);
#endif // QT_NO_SYSTEMTRAYICON

View File

@ -214,20 +214,21 @@ QPlatformMenu *QDBusTrayIcon::createMenu() const
void QDBusTrayIcon::updateMenu(QPlatformMenu * menu)
{
qCDebug(qLcTray) << menu;
bool needsRegistering = !m_menu;
if (!m_menu)
m_menu = qobject_cast<QDBusPlatformMenu *>(menu);
if (!m_menuAdaptor) {
QDBusPlatformMenu *newMenu = qobject_cast<QDBusPlatformMenu *>(menu);
if (m_menu != newMenu) {
if (m_menu) {
dBusConnection()->unregisterTrayIconMenu(this);
delete m_menuAdaptor;
}
m_menu = newMenu;
m_menuAdaptor = new QDBusMenuAdaptor(m_menu);
// TODO connect(m_menu, , m_menuAdaptor, SIGNAL(ItemActivationRequested(int,uint)));
connect(m_menu, SIGNAL(propertiesUpdated(QDBusMenuItemList,QDBusMenuItemKeysList)),
m_menuAdaptor, SIGNAL(ItemsPropertiesUpdated(QDBusMenuItemList,QDBusMenuItemKeysList)));
connect(m_menu, SIGNAL(updated(uint,int)),
m_menuAdaptor, SIGNAL(LayoutUpdated(uint,int)));
}
m_menu->emitUpdated();
if (needsRegistering)
dBusConnection()->registerTrayIconMenu(this);
}
}
void QDBusTrayIcon::showMessage(const QString &title, const QString &msg, const QIcon &icon,

View File

@ -394,11 +394,6 @@ bool QCocoaKeyMapper::updateKeyboard()
keyboardInputLocale = QLocale::c();
keyboardInputDirection = Qt::LeftToRight;
}
const auto newMode = keyboard_mode;
deleteLayouts();
keyboard_mode = newMode;
return true;
}
@ -421,8 +416,10 @@ void QCocoaKeyMapper::clearMappings()
void QCocoaKeyMapper::updateKeyMap(unsigned short macVirtualKey, QChar unicodeKey)
{
updateKeyboard();
if (updateKeyboard()) {
// ### Qt 4 did this:
// QKeyMapper::changeKeyboard();
}
if (keyLayout[macVirtualKey])
return;
@ -478,8 +475,9 @@ QList<int> QCocoaKeyMapper::possibleKeys(const QKeyEvent *event) const
for (int i = 1; i < 8; ++i) {
Qt::KeyboardModifiers neededMods = ModsTbl[i];
int key = kbItem->qtKey[i];
if (key && key != baseKey && ((keyMods & neededMods) == neededMods))
ret << int(key + neededMods);
if (key && key != baseKey && ((keyMods & neededMods) == neededMods)) {
ret << int(key + (keyMods & ~neededMods));
}
}
return ret;
}

View File

@ -507,7 +507,7 @@ static const uint CmdTbl[] = { // Multimedia keys mapping table
Qt::Key_Open, // 30 0x1e APPCOMMAND_OPEN
Qt::Key_Close, // 31 0x1f APPCOMMAND_CLOSE
Qt::Key_Save, // 32 0x20 APPCOMMAND_SAVE
Qt::Key_Print, // 33 0x21 APPCOMMAND_PRINT
Qt::Key_Printer, // 33 0x21 APPCOMMAND_PRINT
Qt::Key_Undo, // 34 0x22 APPCOMMAND_UNDO
Qt::Key_Redo, // 35 0x23 APPCOMMAND_REDO
Qt::Key_Copy, // 36 0x24 APPCOMMAND_COPY

View File

@ -737,7 +737,7 @@
\image spinboxdelegate-example.png
We subclass the delegate from \l QItemDelegate because we do not want
We subclass the delegate from \l QStyledItemDelegate because we do not want
to write custom display functions. However, we must still provide
functions to manage the editor widget:

View File

@ -274,6 +274,11 @@ QGraphicsWidget::~QGraphicsWidget()
// Remove this graphics widget from widgetStyles
widgetStyles()->setStyleForWidget(this, 0);
// Unset the parent here, when we're still a QGraphicsWidget.
// It is otherwise done in ~QGraphicsItem() where we'd be
// calling QGraphicsWidget members on an ex-QGraphicsWidget object
setParentItem(Q_NULLPTR);
}
/*!

View File

@ -1786,13 +1786,18 @@ void QAbstractItemView::mousePressEvent(QMouseEvent *event)
d->autoScroll = false;
d->selectionModel->setCurrentIndex(index, QItemSelectionModel::NoUpdate);
d->autoScroll = autoScroll;
QRect rect(visualRect(d->currentSelectionStartIndex).center(), pos);
if (command.testFlag(QItemSelectionModel::Toggle)) {
command &= ~QItemSelectionModel::Toggle;
d->ctrlDragSelectionFlag = d->selectionModel->isSelected(index) ? QItemSelectionModel::Deselect : QItemSelectionModel::Select;
command |= d->ctrlDragSelectionFlag;
}
if ((command & QItemSelectionModel::Current) == 0) {
setSelection(QRect(pos, QSize(1, 1)), command);
} else {
QRect rect(visualRect(d->currentSelectionStartIndex).center(), pos);
setSelection(rect, command);
}
// signal handlers may change the model
emit pressed(index);

View File

@ -165,7 +165,7 @@ public:
int insertRow(int row);
void insertRows(int row, int count);
void removeRow(int row);
void setItem(int row, QFormLayout::ItemRole role, QLayoutItem *item);
bool setItem(int row, QFormLayout::ItemRole role, QLayoutItem *item);
void setLayout(int row, QFormLayout::ItemRole role, QLayout *layout);
void setWidget(int row, QFormLayout::ItemRole role, QWidget *widget);
@ -933,21 +933,21 @@ void QFormLayoutPrivate::removeRow(int row)
m_matrix.removeRow(row);
}
void QFormLayoutPrivate::setItem(int row, QFormLayout::ItemRole role, QLayoutItem *item)
bool QFormLayoutPrivate::setItem(int row, QFormLayout::ItemRole role, QLayoutItem *item)
{
const bool fullRow = role == QFormLayout::SpanningRole;
const int column = role == QFormLayout::SpanningRole ? 1 : static_cast<int>(role);
if (Q_UNLIKELY(uint(row) >= uint(m_matrix.rowCount()) || uint(column) > 1U)) {
qWarning("QFormLayoutPrivate::setItem: Invalid cell (%d, %d)", row, column);
return;
return false;
}
if (!item)
return;
return false;
if (Q_UNLIKELY(m_matrix(row, column))) {
qWarning("QFormLayoutPrivate::setItem: Cell (%d, %d) already occupied", row, column);
return;
return false;
}
QFormLayoutItem *i = new QFormLayoutItem(item);
@ -955,6 +955,7 @@ void QFormLayoutPrivate::setItem(int row, QFormLayout::ItemRole role, QLayoutIte
m_matrix(row, column) = i;
m_things.append(i);
return true;
}
void QFormLayoutPrivate::setLayout(int row, QFormLayout::ItemRole role, QLayout *layout)
@ -971,7 +972,9 @@ void QFormLayoutPrivate::setWidget(int row, QFormLayout::ItemRole role, QWidget
if (widget) {
Q_Q(QFormLayout);
q->addChildWidget(widget);
setItem(row, role, QLayoutPrivate::createWidgetItem(q, widget));
QWidgetItem *item = QLayoutPrivate::createWidgetItem(q, widget);
if (!setItem(row, role, item))
delete item;
}
}

View File

@ -1315,7 +1315,9 @@ QDockWidget::DockWidgetFeatures QDockWidget::features() const
By default, this property is \c true.
\sa isWindow()
When this property changes, the \c {topLevelChanged()} signal is emitted.
\sa isWindow(), topLevelChanged()
*/
void QDockWidget::setFloating(bool floating)
{

View File

@ -1514,7 +1514,7 @@ void QTextEditPrivate::paint(QPainter *p, QPaintEvent *e)
if (layout)
layout->setViewport(QRect());
if (!placeholderText.isEmpty() && doc->isEmpty()) {
if (!placeholderText.isEmpty() && doc->isEmpty() && !control->isPreediting()) {
QColor col = control->palette().text().color();
col.setAlpha(128);
p->setPen(col);

View File

@ -2584,6 +2584,11 @@ bool QWidgetTextControl::isWordSelectionEnabled() const
return d->wordSelectionEnabled;
}
bool QWidgetTextControl::isPreediting()
{
return d_func()->isPreediting();
}
#ifndef QT_NO_PRINTER
void QWidgetTextControl::print(QPagedPaintDevice *printer) const
{

View File

@ -173,6 +173,8 @@ public:
bool isWordSelectionEnabled() const;
void setWordSelectionEnabled(bool enabled);
bool isPreediting();
void print(QPagedPaintDevice *printer) const;
virtual int hitTest(const QPointF &point, Qt::HitTestAccuracy accuracy) const;

View File

@ -1479,6 +1479,33 @@ void tst_QPixmap::loadAsBitmapOrPixmap()
QVERIFY(!bitmap.isNull());
QCOMPARE(bitmap.depth(), 1);
QVERIFY(bitmap.isQBitmap());
// check that a QBitmap stays a QBitmap even when loading fails:
ok = bitmap.load(QString());
QVERIFY(!ok);
QVERIFY(bitmap.isNull());
QVERIFY(bitmap.isQBitmap());
ok = bitmap.load("does not exist");
QVERIFY(!ok);
QVERIFY(bitmap.isNull());
QVERIFY(bitmap.isQBitmap());
ok = bitmap.load("does not exist.png");
QVERIFY(!ok);
QVERIFY(bitmap.isNull());
QVERIFY(bitmap.isQBitmap());
QTemporaryFile garbage;
QVERIFY(garbage.open());
const QString garbagePath = garbage.fileName();
garbage.write(reinterpret_cast<const char *>(&garbage), sizeof garbage);
garbage.close();
ok = bitmap.load(garbagePath);
QVERIFY(!ok);
QVERIFY(bitmap.isNull());
QVERIFY(bitmap.isQBitmap());
}
void tst_QPixmap::toImageDeepCopy()

View File

@ -148,6 +148,7 @@ private slots:
void QTBUG50102_SH_ItemView_ScrollMode();
void QTBUG50535_update_on_new_selection_model();
void testSelectionModelInSyncWithView();
void testClickToSelect();
};
class MyAbstractItemDelegate : public QAbstractItemDelegate
@ -2102,5 +2103,56 @@ void tst_QAbstractItemView::testSelectionModelInSyncWithView()
QCOMPARE(view.selectionModel()->selection().indexes(), QModelIndexList() << model.index(0, 0));
}
class SetSelectionTestView : public QListView
{
Q_OBJECT
public:
SetSelectionTestView() : QListView() {}
signals:
void setSelectionCalled(const QRect &rect);
protected:
void setSelection(const QRect &rect, QItemSelectionModel::SelectionFlags flags) Q_DECL_OVERRIDE
{
emit setSelectionCalled(rect);
QListView::setSelection(rect, flags);
}
};
void tst_QAbstractItemView::testClickToSelect()
{
// This test verifies that the QRect that is passed from QAbstractItemView::mousePressEvent
// to the virtual method QAbstractItemView::setSelection(const QRect &, SelectionFlags)
// is the 1x1 rect which conains exactly the clicked pixel if no modifiers are pressed.
QStringList list;
list << "A" << "B" << "C";
QStringListModel model(list);
SetSelectionTestView view;
view.setModel(&model);
view.show();
QTest::qWaitForWindowExposed(&view);
QSignalSpy spy(&view, &SetSelectionTestView::setSelectionCalled);
const QModelIndex indexA(model.index(0, 0));
const QRect visualRectA = view.visualRect(indexA);
const QPoint centerA = visualRectA.center();
// Click the center of the visualRect of item "A"
QTest::mouseClick(view.viewport(), Qt::LeftButton, Qt::NoModifier, centerA);
QCOMPARE(spy.count(), 1);
QCOMPARE(spy.back().front().value<QRect>(), QRect(centerA, QSize(1, 1)));
// Click a point slightly away from the center
const QPoint nearCenterA = centerA + QPoint(1, 1);
QVERIFY(visualRectA.contains(nearCenterA));
QTest::mouseClick(view.viewport(), Qt::LeftButton, Qt::NoModifier, nearCenterA);
QCOMPARE(spy.count(), 2);
QCOMPARE(spy.back().front().value<QRect>(), QRect(nearCenterA, QSize(1, 1)));
}
QTEST_MAIN(tst_QAbstractItemView)
#include "tst_qabstractitemview.moc"

View File

@ -1207,7 +1207,8 @@ QShortcut *tst_QShortcut::setupShortcut(QWidget *parent, const char *name, int t
void tst_QShortcut::shortcutDestroyed(QObject* obj)
{
shortcuts.removeAll(static_cast<QShortcut *>(obj));
shortcuts.erase(std::remove(shortcuts.begin(), shortcuts.end(), obj),
shortcuts.end());
}
void tst_QShortcut::sendKeyEvents(int k1, QChar c1, int k2, QChar c2, int k3, QChar c3, int k4, QChar c4)

View File

@ -163,7 +163,8 @@ private:
void tst_QStackedWidget::dynamicPages()
{
QStackedWidget *sw = new QStackedWidget;
QStackedWidget stackedWidget;
QStackedWidget *sw = &stackedWidget;
TestPage *w1 = new TestPage(true);
w1->setN(3);