diff options
author | Jason Barron <jbarron@trolltech.com> | 2009-07-28 10:58:46 (GMT) |
---|---|---|
committer | Jason Barron <jbarron@trolltech.com> | 2009-07-28 11:45:59 (GMT) |
commit | 7eba68adc4a7862d9474179592e5c8393a7acdbb (patch) | |
tree | 73014cabc8b10f46203844aeb40de574d97032dc /src | |
parent | a20f8dcbeafa34b50ef69d1c5db0f17b09731d2a (diff) | |
parent | 3bf3981c7026de9017887d08312391b54fe8afc6 (diff) | |
download | Qt-7eba68adc4a7862d9474179592e5c8393a7acdbb.zip Qt-7eba68adc4a7862d9474179592e5c8393a7acdbb.tar.gz Qt-7eba68adc4a7862d9474179592e5c8393a7acdbb.tar.bz2 |
Merge commit 'qt/master-stable'
Conflicts:
configure.exe
src/corelib/io/io.pri
src/corelib/io/qfilesystemwatcher.cpp
tests/auto/qfileinfo/tst_qfileinfo.cpp
tools/configure/configureapp.cpp
Diffstat (limited to 'src')
78 files changed, 1454 insertions, 851 deletions
diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h index fb708b5..a767c31 100644 --- a/src/corelib/global/qglobal.h +++ b/src/corelib/global/qglobal.h @@ -325,10 +325,6 @@ namespace QT_NAMESPACE {} # endif #endif -#ifdef QT_MAC_USE_COCOA -#define QT_MAC_NO_QUICKDRAW 1 -#endif - #ifdef __LSB_VERSION__ # if __LSB_VERSION__ < 40 # error "This version of the Linux Standard Base is unsupported" diff --git a/src/corelib/io/io.pri b/src/corelib/io/io.pri index edbab9c..b49554e 100644 --- a/src/corelib/io/io.pri +++ b/src/corelib/io/io.pri @@ -66,7 +66,10 @@ win32 { SOURCES += io/qfsfileengine_iterator_unix.cpp symbian:SOURCES += io/qprocess_symbian.cpp else:SOURCES += io/qprocess_unix.cpp - mac:SOURCES += io/qsettings_mac.cpp + macx-*: { + HEADERS += io/qfilesystemwatcher_fsevents_p.h + SOURCES += io/qsettings_mac.cpp io/qfilesystemwatcher_fsevents.cpp + } linux-*:{ SOURCES += \ diff --git a/src/corelib/io/qdatastream.cpp b/src/corelib/io/qdatastream.cpp index 244299c..1023868 100644 --- a/src/corelib/io/qdatastream.cpp +++ b/src/corelib/io/qdatastream.cpp @@ -362,17 +362,19 @@ QDataStream::~QDataStream() /*! \fn QIODevice *QDataStream::device() const - Returns the I/O device currently set. + Returns the I/O device currently set, or 0 if no + device is currently set. - \sa setDevice(), unsetDevice() + \sa setDevice() */ /*! void QDataStream::setDevice(QIODevice *d) - Sets the I/O device to \a d. + Sets the I/O device to \a d, which can be 0 + to unset to current I/O device. - \sa device(), unsetDevice() + \sa device() */ void QDataStream::setDevice(QIODevice *d) diff --git a/src/corelib/io/qfilesystemwatcher.cpp b/src/corelib/io/qfilesystemwatcher.cpp index 8f18df8..883a77a 100644 --- a/src/corelib/io/qfilesystemwatcher.cpp +++ b/src/corelib/io/qfilesystemwatcher.cpp @@ -58,6 +58,9 @@ # include "qfilesystemwatcher_inotify_p.h" # include "qfilesystemwatcher_dnotify_p.h" #elif defined(Q_OS_FREEBSD) || defined(Q_OS_MAC) +# if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5) +# include "qfilesystemwatcher_fsevents_p.h" +# endif //MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5) # include "qfilesystemwatcher_kqueue_p.h" #elif defined(Q_OS_SYMBIAN) # include "qfilesystemwatcher_symbian_p.h" @@ -245,7 +248,12 @@ QFileSystemWatcherEngine *QFileSystemWatcherPrivate::createNativeEngine() eng = QDnotifyFileSystemWatcherEngine::create(); return eng; #elif defined(Q_OS_FREEBSD) || defined(Q_OS_MAC) - return QKqueueFileSystemWatcherEngine::create(); +# if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5) + if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_5) + return QFSEventsFileSystemWatcherEngine::create(); + else +# endif + return QKqueueFileSystemWatcherEngine::create(); #elif defined(Q_OS_SYMBIAN) return new QSymbianFileSystemWatcherEngine; #else @@ -380,15 +388,17 @@ void QFileSystemWatcherPrivate::_q_directoryChanged(const QString &path, bool re \note The act of monitoring files and directories for modifications consumes system resources. This implies there is a limit to the number of files and directories your process can - monitor simultaneously. On Mac OS and all BSD variants, for + monitor simultaneously. On Mac OS X 10.4 and all BSD variants, for example, an open file descriptor is required for each monitored - file. The system limits the number of open file descriptors to 256 + file. Some system limits the number of open file descriptors to 256 by default. This means that addPath() and addPaths() will fail if your process tries to add more than 256 files or directories to the file system monitor. Also note that your process may have other file descriptors open in addition to the ones for files being monitored, and these other open descriptors also count in - the total. + the total. Mac OS X 10.5 and up use a different backend and do not + suffer from this issue. + \sa QFile, QDir */ diff --git a/src/corelib/io/qfilesystemwatcher_fsevents.cpp b/src/corelib/io/qfilesystemwatcher_fsevents.cpp new file mode 100644 index 0000000..3e0aee8 --- /dev/null +++ b/src/corelib/io/qfilesystemwatcher_fsevents.cpp @@ -0,0 +1,467 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://www.qtsoftware.com/contact. +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#include <qplatformdefs.h> + +#include "qfilesystemwatcher.h" +#include "qfilesystemwatcher_fsevents_p.h" + +#include <qdebug.h> +#include <qfile.h> +#include <qdatetime.h> +#include <qfileinfo.h> +#include <qvarlengtharray.h> + +#include <mach/mach.h> +#include <sys/types.h> +#include <CoreFoundation/CFRunLoop.h> +#include <CoreFoundation/CFUUID.h> +#include <CoreServices/CoreServices.h> +#include <AvailabilityMacros.h> +#include <private/qcore_mac_p.h> + +QT_BEGIN_NAMESPACE + +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 +// Static operator overloading so for the sake of some convieniece. +// They only live in this compilation unit to avoid polluting Qt in general. +static bool operator==(const struct ::timespec &left, const struct ::timespec &right) +{ + return left.tv_sec == right.tv_sec + && left.tv_nsec == right.tv_nsec; +} + +static bool operator==(const struct ::stat64 &left, const struct ::stat64 &right) +{ + return left.st_dev == right.st_dev + && left.st_mode == right.st_mode + && left.st_size == right.st_size + && left.st_ino == right.st_ino + && left.st_uid == right.st_uid + && left.st_gid == right.st_gid + && left.st_mtimespec == right.st_mtimespec + && left.st_ctimespec == right.st_ctimespec + && left.st_flags == right.st_flags; +} + +static bool operator!=(const struct ::stat64 &left, const struct ::stat64 &right) +{ + return !(operator==(left, right)); +} + + +static void addPathToHash(PathHash &pathHash, const QString &key, const QFileInfo &fileInfo, + const QString &path) +{ + PathInfoList &list = pathHash[key]; + list.push_back(PathInfo(path, + fileInfo.absoluteFilePath().normalized(QString::NormalizationForm_D).toUtf8())); + pathHash.insert(key, list); +} + +static void removePathFromHash(PathHash &pathHash, const QString &key, const QString &path) +{ + PathInfoList &list = pathHash[key]; + // We make the assumption that the list contains unique paths + PathInfoList::iterator End = list.end(); + PathInfoList::iterator it = list.begin(); + while (it != End) { + if (it->originalPath == path) { + list.erase(it); + break; + } + ++it; + } + if (list.isEmpty()) + pathHash.remove(key); +} + +static void stopFSStream(FSEventStreamRef stream) +{ + if (stream) { + FSEventStreamStop(stream); + FSEventStreamInvalidate(stream); + } +} + +static QString createFSStreamPath(const QString &absolutePath) +{ + // The path returned has a trailing slash, so ensure that here. + QString string = absolutePath; + string.reserve(string.size() + 1); + string.append(QLatin1Char('/')); + return string; +} + +static void cleanupFSStream(FSEventStreamRef stream) +{ + if (stream) + FSEventStreamRelease(stream); +} + +const FSEventStreamCreateFlags QtFSEventFlags = (kFSEventStreamCreateFlagUseCFTypes | kFSEventStreamCreateFlagNoDefer /* | kFSEventStreamCreateFlagWatchRoot*/); + +const CFTimeInterval Latency = 0.033; // This will do updates 30 times a second which is probably more than you need. +#endif + +QFSEventsFileSystemWatcherEngine::QFSEventsFileSystemWatcherEngine() + : fsStream(0), pathsToWatch(0), threadsRunLoop(0) +{ +} + +QFSEventsFileSystemWatcherEngine::~QFSEventsFileSystemWatcherEngine() +{ +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 + // I assume that at this point, QFileSystemWatcher has already called stop + // on me, so I don't need to invalidate or stop my stream, simply + // release it. + cleanupFSStream(fsStream); + if (pathsToWatch) + CFRelease(pathsToWatch); +#endif +} + +QFSEventsFileSystemWatcherEngine *QFSEventsFileSystemWatcherEngine::create() +{ + return new QFSEventsFileSystemWatcherEngine(); +} + +QStringList QFSEventsFileSystemWatcherEngine::addPaths(const QStringList &paths, + QStringList *files, + QStringList *directories) +{ +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 + stop(); + QMutexLocker locker(&mutex); + QStringList failedToAdd; + // if we have a running FSStreamEvent, we have to kill it, we'll re-add the stream soon. + FSEventStreamEventId idToCheck; + if (fsStream) { + idToCheck = FSEventStreamGetLatestEventId(fsStream); + cleanupFSStream(fsStream); + } else { + idToCheck = kFSEventStreamEventIdSinceNow; + } + + // Brain-dead approach, but works. FSEvents actually can already read sub-trees, but since it's + // work to figure out if we are doing a double register, we just register it twice as FSEvents + // seems smart enough to only deliver one event. We also duplicate directory entries in here + // (e.g., if you watch five files in the same directory, you get that directory included in the + // array 5 times). This stupidity also makes remove work correctly though. I'll freely admit + // that we could make this a bit smarter. If you do, check the auto-tests, they should catch at + // least a couple of the issues. + QCFType<CFMutableArrayRef> tmpArray = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); + for (int i = 0; i < paths.size(); ++i) { + const QString &path = paths.at(i); + + QFileInfo fileInfo(path); + if (!fileInfo.exists()) { + failedToAdd.append(path); + continue; + } + + if (fileInfo.isDir()) { + if (directories->contains(path)) { + failedToAdd.append(path); + continue; + } else { + directories->append(path); + // Full file path for dirs. + QCFString cfpath(createFSStreamPath(fileInfo.absoluteFilePath())); + addPathToHash(dirPathInfoHash, cfpath, fileInfo, path); + CFArrayAppendValue(tmpArray, cfpath); + } + } else { + if (files->contains(path)) { + failedToAdd.append(path); + continue; + } else { + // Just the absolute path (minus it's filename) for files. + QCFString cfpath(createFSStreamPath(fileInfo.absolutePath())); + files->append(path); + addPathToHash(filePathInfoHash, cfpath, fileInfo, path); + CFArrayAppendValue(tmpArray, cfpath); + } + } + } + if (CFArrayGetCount(tmpArray) > 0) { + if (pathsToWatch) { + CFArrayAppendArray(tmpArray, pathsToWatch, CFRangeMake(0, CFArrayGetCount(pathsToWatch))); + CFRelease(pathsToWatch); + } + pathsToWatch = CFArrayCreateCopy(kCFAllocatorDefault, tmpArray); + } + FSEventStreamContext context = { 0, this, 0, 0, 0 }; + fsStream = FSEventStreamCreate(kCFAllocatorDefault, + QFSEventsFileSystemWatcherEngine::fseventsCallback, + &context, pathsToWatch, + idToCheck, Latency, QtFSEventFlags); + warmUpFSEvents(); + + return failedToAdd; +#else + Q_UNUSED(paths); + Q_UNUSED(files); + Q_UNUSED(directories); + return QStringList(); +#endif +} + +void QFSEventsFileSystemWatcherEngine::warmUpFSEvents() +{ +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 + // This function assumes that the mutex has already been grabbed before calling it. + // It exits with the mutex still locked (Q_ASSERT(mutex.isLocked()) ;-). + start(); + waitCondition.wait(&mutex); +#endif +} + +QStringList QFSEventsFileSystemWatcherEngine::removePaths(const QStringList &paths, + QStringList *files, + QStringList *directories) +{ +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 + stop(); + QMutexLocker locker(&mutex); + // short circuit for smarties that call remove before add and we have nothing. + if (pathsToWatch == 0) + return paths; + QStringList failedToRemove; + // if we have a running FSStreamEvent, we have to stop it, we'll re-add the stream soon. + FSEventStreamEventId idToCheck; + if (fsStream) { + idToCheck = FSEventStreamGetLatestEventId(fsStream); + cleanupFSStream(fsStream); + fsStream = 0; + } else { + idToCheck = kFSEventStreamEventIdSinceNow; + } + + CFIndex itemCount = CFArrayGetCount(pathsToWatch); + QCFType<CFMutableArrayRef> tmpArray = CFArrayCreateMutableCopy(kCFAllocatorDefault, itemCount, + pathsToWatch); + CFRelease(pathsToWatch); + pathsToWatch = 0; + for (int i = 0; i < paths.size(); ++i) { + // Get the itemCount at the beginning to avoid any overruns during the iteration. + itemCount = CFArrayGetCount(tmpArray); + const QString &path = paths.at(i); + QFileInfo fi(path); + QCFString cfpath(createFSStreamPath(fi.absolutePath())); + + CFIndex index = CFArrayGetFirstIndexOfValue(tmpArray, CFRangeMake(0, itemCount), cfpath); + if (index != -1) { + CFArrayRemoveValueAtIndex(tmpArray, index); + files->removeAll(path); + removePathFromHash(filePathInfoHash, cfpath, path); + } else { + // Could be a directory we are watching instead. + QCFString cfdirpath(createFSStreamPath(fi.absoluteFilePath())); + index = CFArrayGetFirstIndexOfValue(tmpArray, CFRangeMake(0, itemCount), cfdirpath); + if (index != -1) { + CFArrayRemoveValueAtIndex(tmpArray, index); + directories->removeAll(path); + removePathFromHash(dirPathInfoHash, cfpath, path); + } else { + failedToRemove.append(path); + } + } + } + itemCount = CFArrayGetCount(tmpArray); + if (itemCount != 0) { + pathsToWatch = CFArrayCreateCopy(kCFAllocatorDefault, tmpArray); + + FSEventStreamContext context = { 0, this, 0, 0, 0 }; + fsStream = FSEventStreamCreate(kCFAllocatorDefault, + QFSEventsFileSystemWatcherEngine::fseventsCallback, + &context, pathsToWatch, idToCheck, Latency, QtFSEventFlags); + warmUpFSEvents(); + } + return failedToRemove; +#else + Q_UNUSED(paths); + Q_UNUSED(files); + Q_UNUSED(directories); + return QStringList(); +#endif +} + +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 +void QFSEventsFileSystemWatcherEngine::updateList(PathInfoList &list, bool directory, bool emitSignals) +{ + PathInfoList::iterator End = list.end(); + PathInfoList::iterator it = list.begin(); + while (it != End) { + struct ::stat64 newInfo; + if (::stat64(it->absolutePath, &newInfo) == 0) { + if (emitSignals) { + if (newInfo != it->savedInfo) { + it->savedInfo = newInfo; + if (directory) + emit directoryChanged(it->originalPath, false); + else + emit fileChanged(it->originalPath, false); + } + } else { + it->savedInfo = newInfo; + } + } else { + if (errno == ENOENT) { + if (emitSignals) { + if (directory) + emit directoryChanged(it->originalPath, true); + else + emit fileChanged(it->originalPath, true); + } + it = list.erase(it); + continue; + } else { + qWarning("%s:%d:QFSEventsFileSystemWatcherEngine: stat error on %s:%s", + __FILE__, __LINE__, qPrintable(it->originalPath), strerror(errno)); + + } + } + ++it; + } +} + +void QFSEventsFileSystemWatcherEngine::updateHash(PathHash &pathHash) +{ + PathHash::iterator HashEnd = pathHash.end(); + PathHash::iterator it = pathHash.begin(); + const bool IsDirectory = (&pathHash == &dirPathInfoHash); + while (it != HashEnd) { + updateList(it.value(), IsDirectory, false); + if (it.value().isEmpty()) + it = pathHash.erase(it); + else + ++it; + } +} +#endif + +void QFSEventsFileSystemWatcherEngine::fseventsCallback(ConstFSEventStreamRef , + void *clientCallBackInfo, size_t numEvents, + void *eventPaths, + const FSEventStreamEventFlags eventFlags[], + const FSEventStreamEventId []) +{ +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 + QFSEventsFileSystemWatcherEngine *watcher = static_cast<QFSEventsFileSystemWatcherEngine *>(clientCallBackInfo); + QMutexLocker locker(&watcher->mutex); + CFArrayRef paths = static_cast<CFArrayRef>(eventPaths); + for (size_t i = 0; i < numEvents; ++i) { + const QString path = QCFString::toQString( + static_cast<CFStringRef>(CFArrayGetValueAtIndex(paths, i))); + const FSEventStreamEventFlags pathFlags = eventFlags[i]; + // There are several flags that may be passed, but we really don't care about them ATM. + // Here they are and why we don't care. + // kFSEventStreamEventFlagHistoryDone--(very unlikely to be gotten, but even then, not much changes). + // kFSEventStreamEventFlagMustScanSubDirs--Likely means the data is very much out of date, we + // aren't coalescing our directories, so again not so much of an issue + // kFSEventStreamEventFlagRootChanged | kFSEventStreamEventFlagMount | kFSEventStreamEventFlagUnmount-- + // These three flags indicate something has changed, but the stat will likely show this, so + // there's not really much to worry about. + // (btw, FSEvents is not the correct way of checking for mounts/unmounts, + // there are real CarbonCore events for that.) + Q_UNUSED(pathFlags); + if (watcher->filePathInfoHash.contains(path)) + watcher->updateList(watcher->filePathInfoHash[path], false, true); + + if (watcher->dirPathInfoHash.contains(path)) + watcher->updateList(watcher->dirPathInfoHash[path], true, true); + } +#else + Q_UNUSED(clientCallBackInfo); + Q_UNUSED(numEvents); + Q_UNUSED(eventPaths); + Q_UNUSED(eventFlags); +#endif +} + +void QFSEventsFileSystemWatcherEngine::stop() +{ +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 + stopFSStream(fsStream); + if (threadsRunLoop) + CFRunLoopStop(threadsRunLoop); +#endif +} + +void QFSEventsFileSystemWatcherEngine::updateFiles() +{ +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 + QMutexLocker locker(&mutex); + updateHash(filePathInfoHash); + updateHash(dirPathInfoHash); + if (filePathInfoHash.isEmpty() && dirPathInfoHash.isEmpty()) { + // Everything disappeared before we got to start, don't bother. + stop(); + cleanupFSStream(fsStream); + } + waitCondition.wakeAll(); +#endif +} + +void QFSEventsFileSystemWatcherEngine::run() +{ +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 + threadsRunLoop = CFRunLoopGetCurrent(); + FSEventStreamScheduleWithRunLoop(fsStream, threadsRunLoop, kCFRunLoopDefaultMode); + bool startedOK = FSEventStreamStart(fsStream); + // It's recommended by Apple that you only update the files after you've started + // the stream, because otherwise you might miss an update in between starting it. + updateFiles(); +#ifdef QT_NO_DEBUG + Q_UNUSED(startedOK); +#else + Q_ASSERT(startedOK); +#endif + // If for some reason we called stop up above (and invalidated our stream), this call will return + // immediately. + CFRunLoopRun(); + threadsRunLoop = 0; +#endif +} + +QT_END_NAMESPACE diff --git a/src/corelib/io/qfilesystemwatcher_fsevents_p.h b/src/corelib/io/qfilesystemwatcher_fsevents_p.h new file mode 100644 index 0000000..4770867 --- /dev/null +++ b/src/corelib/io/qfilesystemwatcher_fsevents_p.h @@ -0,0 +1,127 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://www.qtsoftware.com/contact. +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#ifndef FILEWATCHER_FSEVENTS_P_H +#define FILEWATCHER_FSEVENTS_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of the QLibrary class. This header file may change from +// version to version without notice, or even be removed. +// +// We mean it. +// + +#include "qfilesystemwatcher_p.h" + +#include <QtCore/qmutex.h> +#include <QtCore/qwaitcondition.h> +#include <QtCore/qthread.h> +#include <QtCore/QHash> +#include <QtCore/QLinkedList> +#include <private/qcore_mac_p.h> +#include <sys/stat.h> + +typedef struct __FSEventStream *FSEventStreamRef; +typedef const struct __FSEventStream *ConstFSEventStreamRef; +typedef const struct __CFArray *CFArrayRef; +typedef UInt32 FSEventStreamEventFlags; +typedef uint64_t FSEventStreamEventId; + +QT_BEGIN_NAMESPACE + +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 +// Yes, I use a stat64 element here. QFileInfo requires too much knowledge about implementation +// details to be used as a long-standing record. Since I'm going to have to store this information, I can +// do the stat myself too. +struct PathInfo { + PathInfo(const QString &path, const QByteArray &absPath) + : originalPath(path), absolutePath(absPath) {} + QString originalPath; // The path we need to emit + QByteArray absolutePath; // The path we need to stat. + struct ::stat64 savedInfo; // All the info for the path so we can compare it. +}; +typedef QLinkedList<PathInfo> PathInfoList; +typedef QHash<QString, PathInfoList> PathHash; +#endif + +class QFSEventsFileSystemWatcherEngine : public QFileSystemWatcherEngine +{ + Q_OBJECT +public: + ~QFSEventsFileSystemWatcherEngine(); + + static QFSEventsFileSystemWatcherEngine *create(); + + QStringList addPaths(const QStringList &paths, QStringList *files, QStringList *directories); + QStringList removePaths(const QStringList &paths, QStringList *files, QStringList *directories); + + void stop(); + +private: + QFSEventsFileSystemWatcherEngine(); + void warmUpFSEvents(); + void updateFiles(); + + static void fseventsCallback(ConstFSEventStreamRef streamRef, void *clientCallBackInfo, size_t numEvents, + void *eventPaths, const FSEventStreamEventFlags eventFlags[], + const FSEventStreamEventId eventIds[]); + void run(); + FSEventStreamRef fsStream; + CFArrayRef pathsToWatch; + CFRunLoopRef threadsRunLoop; + QMutex mutex; + QWaitCondition waitCondition; +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 + PathHash filePathInfoHash; + PathHash dirPathInfoHash; + void updateHash(PathHash &pathHash); + void updateList(PathInfoList &list, bool directory, bool emitSignals); +#endif +}; + +#endif + +QT_END_NAMESPACE diff --git a/src/corelib/io/qfsfileengine_win.cpp b/src/corelib/io/qfsfileengine_win.cpp index 27f4aef..68eef5f 100644 --- a/src/corelib/io/qfsfileengine_win.cpp +++ b/src/corelib/io/qfsfileengine_win.cpp @@ -529,8 +529,7 @@ qint64 QFSFileEnginePrivate::nativeSize() const GetFileExInfoStandard, &attribData); if (!ok) { int errorCode = GetLastError(); - if (errorCode != ERROR_INVALID_NAME - && errorCode != ERROR_FILE_NOT_FOUND && errorCode != ERROR_PATH_NOT_FOUND) { + if (errorCode == ERROR_ACCESS_DENIED || errorCode == ERROR_SHARING_VIOLATION) { QByteArray path = nativeFilePath; // path for the FindFirstFile should not end with a trailing slash while (path.endsWith('\\')) @@ -903,8 +902,7 @@ static inline bool isDirPath(const QString &dirPath, bool *existed) DWORD fileAttrib = ::GetFileAttributes((wchar_t*)QFSFileEnginePrivate::longFileName(path).utf16()); if (fileAttrib == INVALID_FILE_ATTRIBUTES) { int errorCode = GetLastError(); - if (errorCode != ERROR_INVALID_NAME - && errorCode != ERROR_FILE_NOT_FOUND && errorCode != ERROR_PATH_NOT_FOUND) { + if (errorCode == ERROR_ACCESS_DENIED || errorCode == ERROR_SHARING_VIOLATION) { // path for the FindFirstFile should not end with a trailing slash while (path.endsWith(QLatin1Char('\\'))) path.chop(1); @@ -1194,8 +1192,7 @@ bool QFSFileEnginePrivate::doStat() const fileAttrib = GetFileAttributes((wchar_t*)QFSFileEnginePrivate::longFileName(fname).utf16()); if (fileAttrib == INVALID_FILE_ATTRIBUTES) { int errorCode = GetLastError(); - if (errorCode != ERROR_INVALID_NAME - && errorCode != ERROR_FILE_NOT_FOUND && errorCode != ERROR_PATH_NOT_FOUND) { + if (errorCode == ERROR_ACCESS_DENIED || errorCode == ERROR_SHARING_VIOLATION) { QString path = QDir::toNativeSeparators(fname); // path for the FindFirstFile should not end with a trailing slash while (path.endsWith(QLatin1Char('\\'))) @@ -1810,8 +1807,7 @@ QDateTime QFSFileEngine::fileTime(FileTime time) const bool ok = ::GetFileAttributesEx((wchar_t*)QFSFileEnginePrivate::longFileName(d->filePath).utf16(), GetFileExInfoStandard, &attribData); if (!ok) { int errorCode = GetLastError(); - if (errorCode != ERROR_INVALID_NAME - && errorCode != ERROR_FILE_NOT_FOUND && errorCode != ERROR_PATH_NOT_FOUND) { + if (errorCode == ERROR_ACCESS_DENIED || errorCode == ERROR_SHARING_VIOLATION) { QString path = QDir::toNativeSeparators(d->filePath); // path for the FindFirstFile should not end with a trailing slash while (path.endsWith(QLatin1Char('\\'))) diff --git a/src/corelib/io/qprocess.cpp b/src/corelib/io/qprocess.cpp index 03ae1fe..871ea63 100644 --- a/src/corelib/io/qprocess.cpp +++ b/src/corelib/io/qprocess.cpp @@ -310,7 +310,7 @@ void QProcessPrivate::Channel::clear() writes to its standard output and standard error will be written to the standard output and standard error of the main process. - \sa setReadChannelMode() + \sa setProcessChannelMode() */ /*! @@ -878,7 +878,7 @@ void QProcess::setReadChannelMode(ProcessChannelMode mode) Returns the channel mode of the QProcess standard output and standard error channels. - \sa setReadChannelMode(), ProcessChannelMode, setReadChannel() + \sa setProcessChannelMode(), ProcessChannelMode, setReadChannel() */ QProcess::ProcessChannelMode QProcess::processChannelMode() const { @@ -895,7 +895,7 @@ QProcess::ProcessChannelMode QProcess::processChannelMode() const \snippet doc/src/snippets/code/src_corelib_io_qprocess.cpp 0 - \sa readChannelMode(), ProcessChannelMode, setReadChannel() + \sa processChannelMode(), ProcessChannelMode, setReadChannel() */ void QProcess::setProcessChannelMode(ProcessChannelMode mode) { diff --git a/src/corelib/io/qresource.cpp b/src/corelib/io/qresource.cpp index 0899eef..f46877a 100644 --- a/src/corelib/io/qresource.cpp +++ b/src/corelib/io/qresource.cpp @@ -572,7 +572,7 @@ QResource::addSearchPath(const QString &path) Returns the current search path list. This list is consulted when creating a relative resource. - \sa addSearchPath() + \sa QDir::addSearchPath() QDir::setSearchPaths() */ QStringList diff --git a/src/corelib/kernel/qabstractitemmodel.cpp b/src/corelib/kernel/qabstractitemmodel.cpp index 1c3371f..3d9263e 100644 --- a/src/corelib/kernel/qabstractitemmodel.cpp +++ b/src/corelib/kernel/qabstractitemmodel.cpp @@ -2278,7 +2278,8 @@ void QAbstractItemModel::endRemoveColumns() \note The view to which the model is attached to will be reset as well. When a model is reset it means that any previous data reported from the - model is now invalid and has to be queried for again. + model is now invalid and has to be queried for again. This also means + that the current item and any selected items will become invalid. When a model radically changes its data it can sometimes be easier to just call this function rather than emit dataChanged() to inform other diff --git a/src/corelib/tools/qsharedpointer_impl.h b/src/corelib/tools/qsharedpointer_impl.h index 3043dc9..d9fc73c 100644 --- a/src/corelib/tools/qsharedpointer_impl.h +++ b/src/corelib/tools/qsharedpointer_impl.h @@ -48,6 +48,7 @@ #pragma qt_sync_stop_processing #endif +#include <new> #include <QtCore/qatomic.h> #include <QtCore/qobject.h> // for qobject_cast @@ -184,15 +185,89 @@ namespace QtSharedPointer { }; template <class T, typename Deleter> - struct ExternalRefCountWithSpecializedDeleter: public ExternalRefCountData + struct CustomDeleter { - T *ptr; Deleter deleter; + T *ptr; + + inline CustomDeleter(T *p, Deleter d) : deleter(d), ptr(p) {} + }; + + struct ExternalRefCountWithDestroyFn: public ExternalRefCountData + { + typedef void (*DestroyerFn)(ExternalRefCountData *); + DestroyerFn destroyer; - inline ExternalRefCountWithSpecializedDeleter(T *p, Deleter d) - : ptr(p), deleter(d) + inline ExternalRefCountWithDestroyFn(DestroyerFn d) + : destroyer(d) { } - inline bool destroy() { executeDeleter(ptr, deleter); return true; } + + inline bool destroy() { destroyer(this); return true; } + inline void operator delete(void *ptr) { ::operator delete(ptr); } + }; + + template <class T, typename Deleter> + struct ExternalRefCountWithCustomDeleter: public ExternalRefCountWithDestroyFn + { + typedef ExternalRefCountWithCustomDeleter Self; + typedef ExternalRefCountWithDestroyFn Parent; + typedef CustomDeleter<T, Deleter> Next; + Next extra; + + static inline void deleter(ExternalRefCountData *self) + { + Self *realself = static_cast<Self *>(self); + executeDeleter(realself->extra.ptr, realself->extra.deleter); + } + + static inline Self *create(T *ptr, Deleter userDeleter) + { + DestroyerFn destroy = &deleter; + Self *d = static_cast<Self *>(::operator new(sizeof(Self))); + + // initialize the two sub-objects + new (&d->extra) Next(ptr, userDeleter); + new (d) Parent(destroy); // can't throw + + return d; + } + private: + // prevent construction and the emission of virtual symbols + ExternalRefCountWithCustomDeleter(); + ~ExternalRefCountWithCustomDeleter(); + }; + + template <class T> + struct ExternalRefCountWithContiguousData: public ExternalRefCountWithDestroyFn + { + typedef ExternalRefCountWithDestroyFn Parent; + typedef ExternalRefCountWithContiguousData Self; + T data; + + static void deleter(ExternalRefCountData *self) + { + ExternalRefCountWithContiguousData *that = + static_cast<ExternalRefCountWithContiguousData *>(self); + that->data.~T(); + } + + static inline ExternalRefCountData *create(T **ptr) + { + DestroyerFn destroy = &deleter; + Self *d = static_cast<Self *>(::operator new(sizeof(Self))); + + // initialize the d-pointer sub-object + // leave d->data uninitialized + new (d) Parent(destroy); // can't throw + + *ptr = &d->data; + return d; + } + + private: + // prevent construction and the emission of virtual symbols + ExternalRefCountWithContiguousData(); + ~ExternalRefCountWithContiguousData(); }; template <class T> @@ -223,7 +298,15 @@ namespace QtSharedPointer { Basic<T>::internalConstruct(ptr); Q_ASSERT(!d); if (ptr) - d = new ExternalRefCountWithSpecializedDeleter<T, Deleter>(ptr, deleter); + d = ExternalRefCountWithCustomDeleter<T, Deleter>::create(ptr, deleter); + } + + inline void internalCreate() + { + T *ptr; + d = ExternalRefCountWithContiguousData<T>::create(&ptr); + + Basic<T>::internalConstruct(ptr); } inline ExternalRefCount() : d(0) { } @@ -353,6 +436,17 @@ public: inline void clear() { *this = QSharedPointer<T>(); } QWeakPointer<T> toWeakRef() const; + +public: + static inline QSharedPointer<T> create() + { + QSharedPointer<T> result; + result.internalCreate(); + + // now initialize the data + new (result.data()) T(); + return result; + } }; template <class T> diff --git a/src/corelib/tools/qstringbuilder.h b/src/corelib/tools/qstringbuilder.h index 3b43253..463c32d 100644 --- a/src/corelib/tools/qstringbuilder.h +++ b/src/corelib/tools/qstringbuilder.h @@ -163,7 +163,7 @@ template <> struct QConcatenable<QString> static inline void appendTo(const QString &a, QChar *&out) { const int n = a.size(); - memcpy(out, (char*)a.constData(), sizeof(QChar) * n); + memcpy(out, reinterpret_cast<const char*>(a.constData()), sizeof(QChar) * n); out += n; } }; @@ -175,7 +175,7 @@ template <> struct QConcatenable<QStringRef> static inline void appendTo(QStringRef a, QChar *&out) { const int n = a.size(); - memcpy(out, (char*)a.constData(), sizeof(QChar) * n); + memcpy(out, reinterpret_cast<const char*>(a.constData()), sizeof(QChar) * n); out += n; } }; diff --git a/src/corelib/xml/qxmlstream.cpp b/src/corelib/xml/qxmlstream.cpp index 3c771fd..cbf367e 100644 --- a/src/corelib/xml/qxmlstream.cpp +++ b/src/corelib/xml/qxmlstream.cpp @@ -334,12 +334,17 @@ QXmlStreamEntityResolver *QXmlStreamReader::entityResolver() const from the PrematureEndOfDocumentError error and continues parsing the new data with the next call to readNext(). - For example, if you read data from the network using QHttp, you - would connect its \l{QHttp::readyRead()}{readyRead()} signal to a - custom slot. In this slot, you read all available data with - \l{QHttp::readAll()}{readAll()} and pass it to the XML stream reader - using addData(). Then you call your custom parsing function that - reads the XML events from the reader. + For example, if your application reads data from the network using a + \l{QNetworkAccessManager} {network access manager}, you would issue + a \l{QNetworkRequest} {network request} to the manager and receive a + \l{QNetworkReply} {network reply} in return. Since a QNetworkReply + is a QIODevice, you connect its \l{QNetworkReply::readyRead()} + {readyRead()} signal to a custom slot, e.g. \c{slotReadyRead()} in + the code snippet shown in the discussion for QNetworkAccessManager. + In this slot, you read all available data with + \l{QNetworkReply::readAll()} {readAll()} and pass it to the XML + stream reader using addData(). Then you call your custom parsing + function that reads the XML events from the reader. \section1 Performance and memory consumption diff --git a/src/gui/dialogs/qabstractprintdialog.cpp b/src/gui/dialogs/qabstractprintdialog.cpp index 2ffc400..beb6918 100644 --- a/src/gui/dialogs/qabstractprintdialog.cpp +++ b/src/gui/dialogs/qabstractprintdialog.cpp @@ -395,10 +395,8 @@ void QAbstractPrintDialogPrivate::setPrinter(QPrinter *newPrinter) On Windows and Mac OS X, the native print dialog is used, which means that some QWidget and QDialog properties set on the dialog won't be respected. - The native print dialog on - Mac OS X does not support setting printer options, i.e. - QAbstractPrintDialog::setEnabledOptions() and - QAbstractPrintDialog::addEnabledOption() have no effect. + The native print dialog on Mac OS X does not support setting printer options, + i.e. setOptions() and setOption() have no effect. In Qt 4.4, it was possible to use the static functions to show a sheet on Mac OS X. This is no longer supported in Qt 4.5. If you want this diff --git a/src/gui/embedded/qdirectpainter_qws.cpp b/src/gui/embedded/qdirectpainter_qws.cpp index e97367c..b3dff06 100644 --- a/src/gui/embedded/qdirectpainter_qws.cpp +++ b/src/gui/embedded/qdirectpainter_qws.cpp @@ -150,14 +150,14 @@ QT_BEGIN_NAMESPACE \value ReservedSynchronous The allocated region will never change and each function that changes the allocated region will be blocking. - \sa reservedRegion(), allocatedRegion() + \sa allocatedRegion() */ /*! \fn QRegion QDirectPainter::region() \obsolete - Use QDirectPainter::reservedRegion() instead. + Use QDirectPainter::allocatedRegion() instead. */ static inline QScreen *getPrimaryScreen() @@ -346,7 +346,7 @@ void QDirectPainter::setRegion(const QRegion ®ion) returned by the allocatedRegion() function. Otherwise they might differ (see \l {Dynamic Allocation} for details). - \sa geometry(), setRegion() + \sa geometry(), setRegion(), allocatedRegion() */ QRegion QDirectPainter::requestedRegion() const { @@ -540,7 +540,7 @@ void QDirectPainter::lower() any. If not released explicitly, the region will be released on application exit. - \sa reservedRegion(), {Static Allocation} + \sa allocatedRegion(), {Static Allocation} \obsolete diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index 7e155e1..c4ff7c6 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -325,6 +325,10 @@ \value ItemAcceptsInputMethod The item supports input methods typically used for Asian languages. This flag was introduced in Qt 4.6. + + \value ItemAutoDetectsFocusProxy The item will assign any child that + gains input focus as its focus proxy. See also focusProxy(). + This flag was introduced in Qt 4.6. */ /*! @@ -908,12 +912,12 @@ void QGraphicsItemPrivate::setParentItemHelper(QGraphicsItem *newParent) scene->d_func()->index->itemChange(q, QGraphicsItem::ItemParentChange, newParentVariant); } - if (QGraphicsWidget *w = isWidget ? static_cast<QGraphicsWidget *>(q) : q->parentWidget()) { - // Update the child focus chain; when reparenting a widget that has a + QGraphicsItem *lastSubFocusItem = subFocusItem; + if (subFocusItem) { + // Update the child focus chain; when reparenting an item that has a // focus child, ensure that that focus child clears its focus child // chain from our parents before it's reparented. - if (QGraphicsWidget *focusChild = w->focusWidget()) - focusChild->clearFocus(); + subFocusItem->clearFocus(); } // We anticipate geometry changes. If the item is deleted, it will be @@ -1001,6 +1005,21 @@ void QGraphicsItemPrivate::setParentItemHelper(QGraphicsItem *newParent) resolveDepth(parent ? parent->d_ptr->depth : -1); dirtySceneTransform = 1; + // Restore the sub focus chain. + if (lastSubFocusItem) + lastSubFocusItem->d_ptr->setSubFocus(); + + // Auto-update focus proxy. The closest parent that detects + // focus proxies is updated as the proxy gains or loses focus. + QGraphicsItem *p = newParent; + while (p) { + if (p->d_ptr->flags & QGraphicsItem::ItemAutoDetectsFocusProxy) { + p->setFocusProxy(q); + break; + } + p = p->d_ptr->parent; + } + // Deliver post-change notification q->itemChange(QGraphicsItem::ItemParentHasChanged, newParentVariant); @@ -2463,33 +2482,45 @@ bool QGraphicsItem::hasFocus() const be passed into any focus event generated by this function; it is used to give an explanation of what caused the item to get focus. - Only items that set the ItemIsFocusable flag can accept keyboard focus. + Only enabled items that set the ItemIsFocusable flag can accept keyboard + focus. - If this item is not visible (i.e., isVisible() returns false), not - enabled, not associated with a scene, or if it already has input focus, - this function will do nothing. + If this item is not visible, or not associated with a scene, it will not + gain immediate input focus. However, it will be registered as the preferred + focus item for its subtree of items, should it later become visible. As a result of calling this function, this item will receive a focus in event with \a focusReason. If another item already has focus, that item will first receive a focus out event indicating that it has lost input focus. - \sa clearFocus(), hasFocus() + \sa clearFocus(), hasFocus(), focusItem() */ void QGraphicsItem::setFocus(Qt::FocusReason focusReason) { - if (!d_ptr->scene || !isEnabled() || hasFocus() || !(d_ptr->flags & ItemIsFocusable)) + // Disabled / unfocusable items cannot accept focus. + if (!isEnabled() || !(d_ptr->flags & QGraphicsItem::ItemIsFocusable)) + return; + + // Find focus proxy. + QGraphicsItem *f = this; + while (f->d_ptr->focusProxy) + f = f->d_ptr->focusProxy; + + // Return if it already has focus. + if (d_ptr->scene && d_ptr->scene->focusItem() == f) return; - QGraphicsItem *item = this; - QGraphicsItem *f; - while ((f = item->d_ptr->focusProxy)) - item = f; - if (item->isVisible()) { - // Visible items immediately gain focus from scene. - d_ptr->scene->d_func()->setFocusItemHelper(item, focusReason); - } else if (item->d_ptr->isWidget) { - // Just set up subfocus. - static_cast<QGraphicsWidget *>(item)->d_func()->setFocusWidget(); + + // Update the child focus chain. + d_ptr->setSubFocus(); + + // Update the scene's focus item. + if (d_ptr->scene) { + QGraphicsWidget *w = window(); + if (!w || w->isActiveWindow()) { + // Visible items immediately gain focus from scene. + d_ptr->scene->d_func()->setFocusItemHelper(f, focusReason); + } } } @@ -2508,10 +2539,8 @@ void QGraphicsItem::clearFocus() { if (!d_ptr->scene) return; - if (d_ptr->isWidget) { - // Invisible widget items with focus must explicitly clear subfocus. - static_cast<QGraphicsWidget *>(this)->d_func()->clearFocusWidget(); - } + // Invisible items with focus must explicitly clear subfocus. + d_ptr->clearSubFocus(); if (hasFocus()) { // If this item has the scene's input focus, clear it. d_ptr->scene->setFocusItem(0); @@ -2579,6 +2608,18 @@ void QGraphicsItem::setFocusProxy(QGraphicsItem *item) } /*! + If this item, a child or descendant of this item currently has input + focus, this function will return a pointer to that item. If + no descendant has input focus, 0 is returned. + + \sa QWidget::focusWidget() +*/ +QGraphicsItem *QGraphicsItem::focusItem() const +{ + return d_ptr->subFocusItem; +} + +/*! \since 4.4 Grabs the mouse input. @@ -4668,6 +4709,34 @@ void QGraphicsItemPrivate::ensureSceneTransform() /*! \internal +*/ +void QGraphicsItemPrivate::setSubFocus() +{ + // Update focus child chain. + QGraphicsItem *item = q_ptr; + QGraphicsItem *parent = item; + bool hidden = !visible; + do { + parent->d_func()->subFocusItem = item; + } while (!parent->isWindow() && (parent = parent->d_ptr->parent) && (!hidden || !parent->d_func()->visible)); +} + +/*! + \internal +*/ +void QGraphicsItemPrivate::clearSubFocus() +{ + // Reset focus child chain. + QGraphicsItem *parent = q_ptr; + do { + if (parent->d_ptr->subFocusItem != q_ptr) + break; + parent->d_ptr->subFocusItem = 0; + } while (!parent->isWindow() && (parent = parent->d_ptr->parent)); +} + +/*! + \internal Tells us if it is a proxy widget */ @@ -10164,6 +10233,9 @@ QDebug operator<<(QDebug debug, QGraphicsItem::GraphicsItemFlag flag) case QGraphicsItem::ItemAcceptsInputMethod: str = "ItemAcceptsInputMethod"; break; + case QGraphicsItem::ItemAutoDetectsFocusProxy: + str = "ItemAutoDetectsFocusProxy"; + break; } debug << str; return debug; diff --git a/src/gui/graphicsview/qgraphicsitem.h b/src/gui/graphicsview/qgraphicsitem.h index fef09f0..f8e74f3 100644 --- a/src/gui/graphicsview/qgraphicsitem.h +++ b/src/gui/graphicsview/qgraphicsitem.h @@ -100,7 +100,8 @@ public: ItemUsesExtendedStyleOption = 0x200, ItemHasNoContents = 0x400, ItemSendsGeometryChanges = 0x800, - ItemAcceptsInputMethod = 0x1000 + ItemAcceptsInputMethod = 0x1000, + ItemAutoDetectsFocusProxy = 0x2000 // NB! Don't forget to increase the d_ptr->flags bit field by 1 when adding a new flag. }; Q_DECLARE_FLAGS(GraphicsItemFlags, GraphicsItemFlag) @@ -230,6 +231,8 @@ public: QGraphicsItem *focusProxy() const; void setFocusProxy(QGraphicsItem *item); + QGraphicsItem *focusItem() const; + void grabMouse(); void ungrabMouse(); void grabKeyboard(); diff --git a/src/gui/graphicsview/qgraphicsitem_p.h b/src/gui/graphicsview/qgraphicsitem_p.h index c395cd6..8097519 100644 --- a/src/gui/graphicsview/qgraphicsitem_p.h +++ b/src/gui/graphicsview/qgraphicsitem_p.h @@ -123,6 +123,7 @@ public: siblingIndex(-1), depth(0), focusProxy(0), + subFocusItem(0), acceptedMouseButtons(0x1f), visible(1), explicitlyHidden(0), @@ -391,6 +392,9 @@ public: || (childrenCombineOpacity() && isFullyTransparent()); } + void setSubFocus(); + void clearSubFocus(); + inline QTransform transformToParent() const; inline void ensureSortedChildren(); @@ -411,6 +415,7 @@ public: int siblingIndex; int depth; QGraphicsItem *focusProxy; + QGraphicsItem *subFocusItem; // Packed 32 bytes quint32 acceptedMouseButtons : 5; @@ -440,7 +445,7 @@ public: // New 32 bits quint32 fullUpdatePending : 1; - quint32 flags : 13; + quint32 flags : 14; quint32 dirtyChildrenBoundingRect : 1; quint32 paintedViewBoundingRectsNeedRepaint : 1; quint32 dirtySceneTransform : 1; @@ -453,7 +458,7 @@ public: quint32 acceptedTouchBeginEvent : 1; quint32 filtersDescendantEvents : 1; quint32 sceneTransformTranslateOnly : 1; - quint32 unused : 6; // feel free to use + quint32 unused : 5; // feel free to use // Optional stacking order int globalStackingOrder; diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index a1a2b60..7e2f7c8 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -484,6 +484,8 @@ void QGraphicsScenePrivate::removeItemHelper(QGraphicsItem *item) index->removeItem(item); } + item->d_ptr->clearSubFocus(); + if (!item->d_ptr->inDestructor && item == tabFocusFirst) { QGraphicsWidget *widget = static_cast<QGraphicsWidget *>(item); widget->d_func()->fixFocusChainBeforeReparenting(0, 0); @@ -572,17 +574,34 @@ void QGraphicsScenePrivate::setFocusItemHelper(QGraphicsItem *item, Q_Q(QGraphicsScene); if (item == focusItem) return; + + // Clear focus if asked to set focus on something that can't + // accept input focus. if (item && (!(item->flags() & QGraphicsItem::ItemIsFocusable) || !item->isVisible() || !item->isEnabled())) { item = 0; } + // Set focus on the scene if an item requests focus. if (item) { q->setFocus(focusReason); if (item == focusItem) return; } + // Auto-update focus proxy. The closest parent that detects + // focus proxies is updated as the proxy gains or loses focus. + if (item) { + QGraphicsItem *p = item->d_ptr->parent; + while (p) { + if (p->d_ptr->flags & QGraphicsItem::ItemAutoDetectsFocusProxy) { + p->setFocusProxy(item); + break; + } + p = p->d_ptr->parent; + } + } + if (focusItem) { QFocusEvent event(QEvent::FocusOut, focusReason); lastFocusItem = focusItem; @@ -602,11 +621,6 @@ void QGraphicsScenePrivate::setFocusItemHelper(QGraphicsItem *item, } if (item) { - if (item->isWidget()) { - // Update focus child chain. - static_cast<QGraphicsWidget *>(item)->d_func()->setFocusWidget(); - } - focusItem = item; QFocusEvent event(QEvent::FocusIn, focusReason); sendEvent(item, &event); @@ -2342,6 +2356,11 @@ void QGraphicsScene::addItem(QGraphicsItem *item) // Deliver post-change notification item->itemChange(QGraphicsItem::ItemSceneHasChanged, newSceneVariant); + // Ensure that newly added items that have subfocus set, gain + // focus automatically if there isn't a focus item already. + if (!d->focusItem && item->focusItem()) + item->focusItem()->setFocus(); + d->updateInputMethodSensitivityInViews(); } @@ -3457,7 +3476,7 @@ void QGraphicsScene::helpEvent(QGraphicsSceneHelpEvent *helpEvent) text = toolTipItem->toolTip(); point = helpEvent->screenPos(); } - QToolTip::showText(point, text); + QToolTip::showText(point, text, helpEvent->widget()); helpEvent->setAccepted(!text.isEmpty()); #endif } @@ -3556,8 +3575,7 @@ void QGraphicsScenePrivate::leaveScene() { Q_Q(QGraphicsScene); #ifndef QT_NO_TOOLTIP - // Remove any tooltips - QToolTip::showText(QPoint(), QString()); + QToolTip::hideText(); #endif // Send HoverLeave events to all existing hover items, topmost first. QGraphicsView *senderWidget = qobject_cast<QGraphicsView *>(q->sender()); @@ -4698,7 +4716,7 @@ void QGraphicsScenePrivate::processDirtyItemsRecursive(QGraphicsItem *item, bool background has been drawn, and before the foreground has been drawn. All painting is done in \e scene coordinates. Before drawing each item, the painter must be transformed using - QGraphicsItem::sceneMatrix(). + QGraphicsItem::sceneTransform(). The \a options parameter is the list of style option objects for each item in \a items. The \a numItems parameter is the number of diff --git a/src/gui/graphicsview/qgraphicssceneevent.cpp b/src/gui/graphicsview/qgraphicssceneevent.cpp index 97e8e46..73cc787 100644 --- a/src/gui/graphicsview/qgraphicssceneevent.cpp +++ b/src/gui/graphicsview/qgraphicssceneevent.cpp @@ -1475,7 +1475,7 @@ void QGraphicsSceneDragDropEvent::acceptProposedAction() /*! Returns the action that was performed in this drag and drop. This should be set by the receiver of the drop and is - returned by QDrag::start(). + returned by QDrag::exec(). \sa setDropAction(), acceptProposedAction() */ diff --git a/src/gui/graphicsview/qgraphicsview.cpp b/src/gui/graphicsview/qgraphicsview.cpp index a3005ae..e1f9f62 100644 --- a/src/gui/graphicsview/qgraphicsview.cpp +++ b/src/gui/graphicsview/qgraphicsview.cpp @@ -97,8 +97,8 @@ static const int QGRAPHICSVIEW_PREALLOC_STYLE_OPTIONS = 503; // largest prime < setViewport(new QGLWidget). QGraphicsView takes ownership of the viewport widget. - QGraphicsView supports affine transformations, using QMatrix. You can - either pass a matrix to setMatrix(), or you can call one of the + QGraphicsView supports affine transformations, using QTransform. You can + either pass a matrix to setTransform(), or you can call one of the convenience functions rotate(), scale(), translate() or shear(). The most two common transformations are scaling, which is used to implement zooming, and rotation. QGraphicsView keeps the center of the view fixed @@ -1598,7 +1598,7 @@ void QGraphicsView::setSceneRect(const QRectF &rect) Returns the current transformation matrix for the view. If no current transformation is set, the identity matrix is returned. - \sa setMatrix(), rotate(), scale(), shear(), translate() + \sa setMatrix(), transform(), rotate(), scale(), shear(), translate() */ QMatrix QGraphicsView::matrix() const { @@ -1630,7 +1630,7 @@ QMatrix QGraphicsView::matrix() const a view coordinate to a floating point scene coordinate, or mapFromScene() to map from floating point scene coordinates to view coordinates. - \sa matrix(), rotate(), scale(), shear(), translate() + \sa matrix(), setTransform(), rotate(), scale(), shear(), translate() */ void QGraphicsView::setMatrix(const QMatrix &matrix, bool combine) { @@ -1639,6 +1639,8 @@ void QGraphicsView::setMatrix(const QMatrix &matrix, bool combine) /*! Resets the view transformation matrix to the identity matrix. + + \sa resetTransform() */ void QGraphicsView::resetMatrix() { @@ -1648,7 +1650,7 @@ void QGraphicsView::resetMatrix() /*! Rotates the current view transformation \a angle degrees clockwise. - \sa setMatrix(), matrix(), scale(), shear(), translate() + \sa setTransform(), transform(), scale(), shear(), translate() */ void QGraphicsView::rotate(qreal angle) { @@ -1661,7 +1663,7 @@ void QGraphicsView::rotate(qreal angle) /*! Scales the current view transformation by (\a sx, \a sy). - \sa setMatrix(), matrix(), rotate(), shear(), translate() + \sa setTransform(), transform(), rotate(), shear(), translate() */ void QGraphicsView::scale(qreal sx, qreal sy) { @@ -1674,7 +1676,7 @@ void QGraphicsView::scale(qreal sx, qreal sy) /*! Shears the current view transformation by (\a sh, \a sv). - \sa setMatrix(), matrix(), rotate(), scale(), translate() + \sa setTransform(), transform(), rotate(), scale(), translate() */ void QGraphicsView::shear(qreal sh, qreal sv) { @@ -1687,7 +1689,7 @@ void QGraphicsView::shear(qreal sh, qreal sv) /*! Translates the current view transformation by (\a dx, \a dy). - \sa setMatrix(), matrix(), rotate(), shear() + \sa setTransform(), transform(), rotate(), shear() */ void QGraphicsView::translate(qreal dx, qreal dy) { @@ -1845,7 +1847,7 @@ void QGraphicsView::ensureVisible(const QGraphicsItem *item, int xmargin, int ym If \a rect is empty, or if the viewport is too small, this function will do nothing. - \sa setMatrix(), ensureVisible(), centerOn() + \sa setTransform(), ensureVisible(), centerOn() */ void QGraphicsView::fitInView(const QRectF &rect, Qt::AspectRatioMode aspectRatioMode) { diff --git a/src/gui/graphicsview/qgraphicswidget.cpp b/src/gui/graphicsview/qgraphicswidget.cpp index 922db04..5e5c826 100644 --- a/src/gui/graphicsview/qgraphicswidget.cpp +++ b/src/gui/graphicsview/qgraphicswidget.cpp @@ -1716,14 +1716,16 @@ void QGraphicsWidget::setFocusPolicy(Qt::FocusPolicy policy) /*! If this widget, a child or descendant of this widget currently has input focus, this function will return a pointer to that widget. If - no descendant has input focus, 0 is returned. + no descendant widget has input focus, 0 is returned. - \sa QWidget::focusWidget() + \sa QGraphicsItem::focusItem(), QWidget::focusWidget() */ QGraphicsWidget *QGraphicsWidget::focusWidget() const { Q_D(const QGraphicsWidget); - return d->focusChild; + if (d->subFocusItem && d->subFocusItem->d_ptr->isWidget) + return static_cast<QGraphicsWidget *>(d->subFocusItem); + return 0; } /*! \property QGraphicsWidget::horizontalShear diff --git a/src/gui/graphicsview/qgraphicswidget_p.cpp b/src/gui/graphicsview/qgraphicswidget_p.cpp index c9212f7..8eac063 100644 --- a/src/gui/graphicsview/qgraphicswidget_p.cpp +++ b/src/gui/graphicsview/qgraphicswidget_p.cpp @@ -626,34 +626,6 @@ bool QGraphicsWidgetPrivate::hasDecoration() const return (windowFlags & Qt::Window) && (windowFlags & Qt::WindowTitleHint); } -/*! - \internal -*/ -void QGraphicsWidgetPrivate::setFocusWidget() -{ - // Update focus child chain. - QGraphicsWidget *widget = static_cast<QGraphicsWidget *>(q_ptr); - QGraphicsWidget *parent = widget; - bool hidden = !visible; - do { - parent->d_func()->focusChild = widget; - } while (!parent->isWindow() && (parent = parent->parentWidget()) && (!hidden || !parent->d_func()->visible)); -} - -/*! - \internal -*/ -void QGraphicsWidgetPrivate::clearFocusWidget() -{ - // Reset focus child chain. - QGraphicsWidget *parent = static_cast<QGraphicsWidget *>(q_ptr); - do { - if (parent->d_func()->focusChild != q_ptr) - break; - parent->d_func()->focusChild = 0; - } while (!parent->isWindow() && (parent = parent->parentWidget())); -} - /** * is called after a reparent has taken place to fix up the focus chain(s) */ @@ -670,12 +642,6 @@ void QGraphicsWidgetPrivate::fixFocusChainBeforeReparenting(QGraphicsWidget *new QGraphicsWidget *firstOld = 0; bool wasPreviousNew = true; - - if (focusChild) { - // Ensure that the current focus child doesn't leave pointers around - // before reparenting. - focusChild->clearFocus(); - } while (w != q) { bool isCurrentNew = q->isAncestorOf(w); diff --git a/src/gui/graphicsview/qgraphicswidget_p.h b/src/gui/graphicsview/qgraphicswidget_p.h index 0c34baa..92e520a 100644 --- a/src/gui/graphicsview/qgraphicswidget_p.h +++ b/src/gui/graphicsview/qgraphicswidget_p.h @@ -83,7 +83,6 @@ public: focusPolicy(Qt::NoFocus), focusNext(0), focusPrev(0), - focusChild(0), windowFlags(0), windowData(0), setWindowFrameMargins(false), @@ -178,9 +177,6 @@ public: Qt::FocusPolicy focusPolicy; QGraphicsWidget *focusNext; QGraphicsWidget *focusPrev; - QGraphicsWidget *focusChild; - void setFocusWidget(); - void clearFocusWidget(); // Windows Qt::WindowFlags windowFlags; diff --git a/src/gui/image/qimage.cpp b/src/gui/image/qimage.cpp index d3a4855..d71aef3 100644 --- a/src/gui/image/qimage.cpp +++ b/src/gui/image/qimage.cpp @@ -596,9 +596,8 @@ bool QImageData::checkForAlphaPixels() const The mirrored() function returns a mirror of the image in the desired direction, the scaled() returns a copy of the image scaled - to a rectangle of the desired measures, the rgbSwapped() function - constructs a BGR image from a RGB image, and the alphaChannel() - function constructs an image from this image's alpha channel. + to a rectangle of the desired measures, and the rgbSwapped() function + constructs a BGR image from a RGB image. The scaledToWidth() and scaledToHeight() functions return scaled copies of the image. diff --git a/src/gui/image/qpixmap.cpp b/src/gui/image/qpixmap.cpp index 12287d3..b7d5efd 100644 --- a/src/gui/image/qpixmap.cpp +++ b/src/gui/image/qpixmap.cpp @@ -675,12 +675,7 @@ void QPixmap::resize_helper(const QSize &s) p.drawPixmap(0, 0, *this, 0, 0, qMin(width(), w), qMin(height(), h)); } -#if defined(Q_WS_MAC) -#ifndef QT_MAC_NO_QUICKDRAW - if(macData && macData->qd_alpha) - macData->macQDUpdateAlpha(); -#endif -#elif defined(Q_WS_X11) +#if defined(Q_WS_X11) if (x11Data && x11Data->x11_mask) { QX11PixmapData *pmData = static_cast<QX11PixmapData*>(pm.data); pmData->x11_mask = (Qt::HANDLE)XCreatePixmap(X11->display, @@ -1952,11 +1947,6 @@ void QPixmap::detach() if (data->ref != 1) { *this = copy(); -#if defined(Q_WS_MAC) && !defined(QT_MAC_NO_QUICKDRAW) - if (id == QPixmapData::MacClass) { - macData->qd_alpha = 0; - } -#endif } ++data->detach_no; diff --git a/src/gui/image/qpixmap_mac.cpp b/src/gui/image/qpixmap_mac.cpp index 25ef8ba..45392f1 100644 --- a/src/gui/image/qpixmap_mac.cpp +++ b/src/gui/image/qpixmap_mac.cpp @@ -166,9 +166,6 @@ QMacPixmapData::QMacPixmapData(PixelType type) : QPixmapData(type, MacClass), has_alpha(0), has_mask(0), uninit(true), pixels(0), pixelsToFree(0), bytesPerRow(0), cg_data(0), cg_dataBeingReleased(0), cg_mask(0), -#ifndef QT_MAC_NO_QUICKDRAW - qd_data(0), qd_alpha(0), -#endif pengine(0) { } @@ -494,13 +491,6 @@ int QMacPixmapData::metric(QPaintDevice::PaintDeviceMetric theMetric) const QMacPixmapData::~QMacPixmapData() { validDataPointers.remove(this); -#ifndef QT_MAC_NO_QUICKDRAW - macQDDisposeAlpha(); - if (qd_data) { - DisposeGWorld(qd_data); - qd_data = 0; - } -#endif if (cg_mask) { CGImageRelease(cg_mask); cg_mask = 0; @@ -589,48 +579,9 @@ void QMacPixmapData::macGetAlphaChannel(QMacPixmapData *pix, bool asMask) const void QMacPixmapData::macSetHasAlpha(bool b) { has_alpha = b; -#ifndef QT_MAC_NO_QUICKDRAW - macQDDisposeAlpha(); //let it get created lazily -#endif macReleaseCGImageRef(); } -#ifndef QT_MAC_NO_QUICKDRAW -void QMacPixmapData::macQDDisposeAlpha() -{ - if (qd_alpha) { - DisposeGWorld(qd_alpha); - qd_alpha = 0; - } -} - -void QMacPixmapData::macQDUpdateAlpha() -{ - macQDDisposeAlpha(); // get rid of alpha pixmap - if (!has_alpha && !has_mask) - return; - - //setup - Rect rect; - SetRect(&rect, 0, 0, w, h); - const int params = alignPix | stretchPix | newDepth; - NewGWorld(&qd_alpha, 32, &rect, 0, 0, params); - int *dptr = (int *)GetPixBaseAddr(GetGWorldPixMap(qd_alpha)), *drow; - unsigned short dbpr = GetPixRowBytes(GetGWorldPixMap(qd_alpha)); - const int *sptr = (int*)pixels, *srow; - const uint sbpr = bytesPerRow; - uchar clr; - for (int y = 0; y < h; ++y) { - drow = (int*)((char *)dptr + (y * dbpr)); - srow = (int*)((char *)sptr + (y * sbpr)); - for (int x=0; x < w; x++) { - clr = qAlpha(*(srow + x)); - *(drow + x) = qRgba(~clr, ~clr, ~clr, 0); - } - } -} -#endif - void QMacPixmapData::macCreateCGImageRef() { Q_ASSERT(cg_data == 0); @@ -979,31 +930,12 @@ QPixmap QPixmap::grabWindow(WId window, int x, int y, int w, int h) relocated. \warning This function is only available on Mac OS X. + \warning As of Qt 4.6, this function \e{always} returns zero. */ Qt::HANDLE QPixmap::macQDHandle() const { -#ifndef QT_MAC_NO_QUICKDRAW - QMacPixmapData *d = static_cast<QMacPixmapData*>(data); - if (!d->qd_data) { //create the qd data - Rect rect; - SetRect(&rect, 0, 0, d->w, d->h); - unsigned long qdformat = k32ARGBPixelFormat; - GWorldFlags qdflags = 0; - //we play such games so we can use the same buffer in CG as QD this - //makes our merge much simpler, at some point the hacks will go away - //because QD will be removed, but until that day this keeps them coexisting - if (QSysInfo::ByteOrder == QSysInfo::LittleEndian) - qdformat = k32BGRAPixelFormat; - - if(NewGWorldFromPtr(&d->qd_data, qdformat, &rect, 0, 0, qdflags, - (char*)d->pixels, d->bytesPerRow) != noErr) - qWarning("Qt: internal: QPixmap::init error (%d %d %d %d)", rect.left, rect.top, rect.right, rect.bottom); - } - return d->qd_data; -#else return 0; -#endif } /*! \internal @@ -1013,18 +945,11 @@ Qt::HANDLE QPixmap::macQDHandle() const long as it can be relocated. \warning This function is only available on Mac OS X. + \warning As of Qt 4.6, this function \e{always} returns zero. */ Qt::HANDLE QPixmap::macQDAlphaHandle() const { -#ifndef QT_MAC_NO_QUICKDRAW - QMacPixmapData *d = static_cast<QMacPixmapData*>(data); - if (d->has_alpha || d->has_mask) { - if (!d->qd_alpha) //lazily created - d->macQDUpdateAlpha(); - return d->qd_alpha; - } -#endif return 0; } @@ -1094,7 +1019,6 @@ IconRef qt_mac_create_iconref(const QPixmap &px) if (px.isNull()) return 0; - QMacSavedPortInfo pi; //save the current state //create icon IconFamilyHandle iconFamily = reinterpret_cast<IconFamilyHandle>(NewHandle(0)); //create data diff --git a/src/gui/image/qpixmap_mac_p.h b/src/gui/image/qpixmap_mac_p.h index a3ff0d3..ea6fe60 100644 --- a/src/gui/image/qpixmap_mac_p.h +++ b/src/gui/image/qpixmap_mac_p.h @@ -109,11 +109,6 @@ private: uint bytesPerRow; QRectF cg_mask_rect; CGImageRef cg_data, cg_dataBeingReleased, cg_mask; -#ifndef QT_MAC_NO_QUICKDRAW - GWorldPtr qd_data, qd_alpha; - void macQDDisposeAlpha(); - void macQDUpdateAlpha(); -#endif static QSet<QMacPixmapData*> validDataPointers; QPaintEngine *pengine; diff --git a/src/gui/image/qpixmapcache.h b/src/gui/image/qpixmapcache.h index c86f3fa..de589fc 100644 --- a/src/gui/image/qpixmapcache.h +++ b/src/gui/image/qpixmapcache.h @@ -54,7 +54,7 @@ class Q_GUI_EXPORT QPixmapCache { public: class KeyData; - class Key + class Q_GUI_EXPORT Key { public: Key(); diff --git a/src/gui/itemviews/qlistwidget.cpp b/src/gui/itemviews/qlistwidget.cpp index 7113217..2565657 100644 --- a/src/gui/itemviews/qlistwidget.cpp +++ b/src/gui/itemviews/qlistwidget.cpp @@ -561,6 +561,13 @@ Qt::DropActions QListModel::supportedDropActions() const given \a parent. If the parent is not specified, the item will need to be inserted into a list widget with QListWidget::insertItem(). + + \note that this constructor inserts this same object into the model of + the parent that is passed to the constructor. If the model is sorted then + the behavior of the insert is undetermined since the model will call + the '<' operator method on this object which has still not yet been + constructed. In this case it would be better not to specify the parent + and use the QListWidget::insertItem method to insert the item instead. \sa type() */ @@ -582,6 +589,13 @@ QListWidgetItem::QListWidgetItem(QListWidget *view, int type) given \a text and \a parent. If the parent is not specified, the item will need to be inserted into a list widget with QListWidget::insertItem(). + + \note that this constructor inserts this same object into the model of + the parent that is passed to the constructor. If the model is sorted then + the behavior of the insert is undetermined since the model will call + the '<' operator method on this object which has still not yet been + constructed. In this case it would be better not to specify the parent + and use the QListWidget::insertItem method to insert the item instead. \sa type() */ @@ -605,7 +619,14 @@ QListWidgetItem::QListWidgetItem(const QString &text, QListWidget *view, int typ given \a icon, \a text and \a parent. If the parent is not specified, the item will need to be inserted into a list widget with QListWidget::insertItem(). - + + \note that this constructor inserts this same object into the model of + the parent that is passed to the constructor. If the model is sorted then + the behavior of the insert is undetermined since the model will call + the '<' operator method on this object which has still not yet been + constructed. In this case it would be better not to specify the parent + and use the QListWidget::insertItem method to insert the item instead. + \sa type() */ QListWidgetItem::QListWidgetItem(const QIcon &icon,const QString &text, @@ -1268,7 +1289,7 @@ void QListWidgetPrivate::_q_dataChanged(const QModelIndex &topLeft, This signal is emitted whenever the selection changes. - \sa selectedItems() isItemSelected() currentItemChanged() + \sa selectedItems() QListWidgetItem::isSelected() currentItemChanged() */ /*! diff --git a/src/gui/itemviews/qtablewidget.cpp b/src/gui/itemviews/qtablewidget.cpp index d975d58..5756f35 100644 --- a/src/gui/itemviews/qtablewidget.cpp +++ b/src/gui/itemviews/qtablewidget.cpp @@ -1719,7 +1719,7 @@ void QTableWidgetPrivate::_q_dataChanged(const QModelIndex &topLeft, This signal is emitted whenever the selection changes. - \sa selectedItems() isItemSelected() + \sa selectedItems() QTableWidgetItem::isSelected() */ diff --git a/src/gui/itemviews/qtreewidget.cpp b/src/gui/itemviews/qtreewidget.cpp index 7dded8d..7cded49 100644 --- a/src/gui/itemviews/qtreewidget.cpp +++ b/src/gui/itemviews/qtreewidget.cpp @@ -2437,7 +2437,7 @@ void QTreeWidgetPrivate::_q_dataChanged(const QModelIndex &topLeft, \note This signal will not be emitted if an item changes its state when expandAll() is invoked. - \sa isItemExpanded(), itemCollapsed(), expandItem() + \sa QTreeWidgetItem::isExpanded(), itemCollapsed(), expandItem() */ /*! @@ -2449,7 +2449,7 @@ void QTreeWidgetPrivate::_q_dataChanged(const QModelIndex &topLeft, \note This signal will not be emitted if an item changes its state when collapseAll() is invoked. - \sa isItemExpanded(), itemExpanded(), collapseItem() + \sa QTreeWidgetItem::isExpanded(), itemExpanded(), collapseItem() */ /*! @@ -3109,9 +3109,9 @@ bool QTreeWidget::isItemExpanded(const QTreeWidgetItem *item) const \sa expandItem(), collapseItem(), itemExpanded() - \obsolete + \obsolete - This function is deprecated. Use \l{QTreeWidgetItem::setExpanded()} instead. + This function is deprecated. Use \l{QTreeWidgetItem::setExpanded()} instead. */ void QTreeWidget::setItemExpanded(const QTreeWidgetItem *item, bool expand) { diff --git a/src/gui/kernel/qeventdispatcher_mac.mm b/src/gui/kernel/qeventdispatcher_mac.mm index cde0c47..af36d9f 100644 --- a/src/gui/kernel/qeventdispatcher_mac.mm +++ b/src/gui/kernel/qeventdispatcher_mac.mm @@ -506,16 +506,6 @@ bool QEventDispatcherMac::processEvents(QEventLoop::ProcessEventsFlags flags) wakeUp(); emit awake(); -#ifndef QT_MAC_NO_QUICKDRAW - if(!qt_mac_safe_pdev) { //create an empty widget and this can be used for a port anytime - QWidget *tlw = new QWidget; - tlw->setAttribute(Qt::WA_DeleteOnClose); - tlw->setObjectName(QLatin1String("empty_widget")); - tlw->hide(); - qt_mac_safe_pdev = tlw; - } -#endif - bool retVal = false; forever { if (d->interrupt) diff --git a/src/gui/kernel/qgridlayout.cpp b/src/gui/kernel/qgridlayout.cpp index 8dbc3cb..7ac874e 100644 --- a/src/gui/kernel/qgridlayout.cpp +++ b/src/gui/kernel/qgridlayout.cpp @@ -1034,14 +1034,15 @@ QRect QGridLayoutPrivate::cellRect(int row, int col) const other layouts into the cells of your grid layout using addWidget(), addItem(), and addLayout(). - QGridLayout also includes two margin widths: the margin() and the - spacing(). The margin is the width of the reserved space along - each of the QGridLayout's four sides. The spacing is the width of - the automatically allocated spacing between neighboring boxes. - - The default margin() and spacing() values are provided by the - style. The default margin Qt styles specify is 9 for child - widgets and 11 for windows. The spacing defaults to the same as + QGridLayout also includes two margin widths: + the \l{getContentsMargins()}{contents margin} and the spacing(). + The contents margin is the width of the reserved space along each + of the QGridLayout's four sides. The spacing() is the width of the + automatically allocated spacing between neighboring boxes. + + The default contents margin values are provided by the + \l{QStyle::pixelMetric()}{style}. The default value Qt styles specify + is 9 for child widgets and 11 for windows. The spacing defaults to the same as the margin width for a top-level layout, or to the same as the parent layout. @@ -1078,7 +1079,7 @@ QGridLayout::QGridLayout() #ifdef QT3_SUPPORT /*! - \obsolete + \obsolete Constructs a new QGridLayout with \a nRows rows, \a nCols columns and parent widget, \a parent. \a parent may not be 0. The grid layout is called \a name. diff --git a/src/gui/kernel/qt_cocoa_helpers_mac.mm b/src/gui/kernel/qt_cocoa_helpers_mac.mm index 223e36b..3d4164a 100644 --- a/src/gui/kernel/qt_cocoa_helpers_mac.mm +++ b/src/gui/kernel/qt_cocoa_helpers_mac.mm @@ -74,6 +74,7 @@ ****************************************************************************/ #include <private/qcore_mac_p.h> +#include <qaction.h> #include <qwidget.h> #include <qdesktopwidget.h> #include <qevent.h> @@ -1193,4 +1194,32 @@ void qt_mac_constructQIconFromIconRef(const IconRef icon, const IconRef overlayI } } +void qt_mac_menu_collapseSeparators(void */*NSMenu **/ theMenu, bool collapse) +{ + OSMenuRef menu = static_cast<OSMenuRef>(theMenu); + if (collapse) { + bool previousIsSeparator = true; // setting to true kills all the separators placed at the top. + NSMenuItem *previousItem = nil; + for (NSMenuItem *item in [menu itemArray]) { + if ([item isSeparatorItem]) { + [item setHidden:previousIsSeparator]; + } + + if (![item isHidden]) { + previousItem = item; + previousIsSeparator = ([previousItem isSeparatorItem]); + } + } + + // We now need to check the final item since we don't want any separators at the end of the list. + if (previousItem && previousIsSeparator) + [previousItem setHidden:YES]; + } else { + for (NSMenuItem *item in [menu itemArray]) { + if (QAction *action = reinterpret_cast<QAction *>([item tag])) + [item setHidden:!action->isVisible()]; + } + } +} + QT_END_NAMESPACE diff --git a/src/gui/kernel/qt_cocoa_helpers_mac_p.h b/src/gui/kernel/qt_cocoa_helpers_mac_p.h index af3b4cb..2cc7dee 100644 --- a/src/gui/kernel/qt_cocoa_helpers_mac_p.h +++ b/src/gui/kernel/qt_cocoa_helpers_mac_p.h @@ -133,6 +133,7 @@ void qt_dispatchTabletProximityEvent(void * /*NSEvent * */ tabletEvent); #ifdef QT_MAC_USE_COCOA bool qt_dispatchKeyEventWithCocoa(void * /*NSEvent * */ keyEvent, QWidget *widgetToGetEvent); #endif +void qt_mac_menu_collapseSeparators(void * /*NSMenu */ menu, bool collapse); bool qt_dispatchKeyEvent(void * /*NSEvent * */ keyEvent, QWidget *widgetToGetEvent); void qt_dispatchModifiersChanged(void * /*NSEvent * */flagsChangedEvent, QWidget *widgetToGetEvent); void qt_mac_dispatchNCMouseMessage(void */* NSWindow* */eventWindow, void */* NSEvent* */mouseEvent, diff --git a/src/gui/kernel/qwidget_mac.mm b/src/gui/kernel/qwidget_mac.mm index 1717fbd..70eea3a 100644 --- a/src/gui/kernel/qwidget_mac.mm +++ b/src/gui/kernel/qwidget_mac.mm @@ -1116,23 +1116,9 @@ OSStatus QWidgetPrivate::qt_widget_event(EventHandlerCallRef er, EventRef event, //update handles GrafPtr qd = 0; CGContextRef cg = 0; -#ifndef QT_MAC_NO_QUICKDRAW - { - if(GetEventParameter(event, kEventParamGrafPort, typeGrafPtr, 0, sizeof(qd), 0, &qd) != noErr) { - GDHandle dev = 0; - GetGWorld(&qd, &dev); //just use the global port.. - } - } - bool end_cg_context = false; - if(GetEventParameter(event, kEventParamCGContextRef, typeCGContextRef, 0, sizeof(cg), 0, &cg) != noErr && qd) { - end_cg_context = true; - QDBeginCGContext(qd, &cg); - } -#else if(GetEventParameter(event, kEventParamCGContextRef, typeCGContextRef, 0, sizeof(cg), 0, &cg) != noErr) { Q_ASSERT(false); } -#endif widget->d_func()->hd = cg; widget->d_func()->qd_hd = qd; CGContextSaveGState(cg); @@ -1252,10 +1238,6 @@ OSStatus QWidgetPrivate::qt_widget_event(EventHandlerCallRef er, EventRef event, widget->d_func()->hd = 0; widget->d_func()->qd_hd = 0; CGContextRestoreGState(cg); -#ifndef QT_MAC_NO_QUICKDRAW - if(end_cg_context) - QDEndCGContext(qd, &cg); -#endif } else if(!HIObjectIsOfClass((HIObjectRef)hiview, kObjectQWidget)) { CallNextEventHandler(er, event); } diff --git a/src/gui/math3d/qvector3d.cpp b/src/gui/math3d/qvector3d.cpp index 881f47c..c1f5a3e 100644 --- a/src/gui/math3d/qvector3d.cpp +++ b/src/gui/math3d/qvector3d.cpp @@ -513,7 +513,8 @@ QVector4D QVector3D::toVector4D() const /*! \fn QPoint QVector3D::toPoint() const - Returns the QPoint form of this 3D vector. + Returns the QPoint form of this 3D vector. The z coordinate + is dropped. \sa toPointF(), toVector2D() */ @@ -521,7 +522,8 @@ QVector4D QVector3D::toVector4D() const /*! \fn QPointF QVector3D::toPointF() const - Returns the QPointF form of this 3D vector. + Returns the QPointF form of this 3D vector. The z coordinate + is dropped. \sa toPoint(), toVector2D() */ diff --git a/src/gui/math3d/qvector4d.cpp b/src/gui/math3d/qvector4d.cpp index 1a84db6..ae03bc7 100644 --- a/src/gui/math3d/qvector4d.cpp +++ b/src/gui/math3d/qvector4d.cpp @@ -484,7 +484,8 @@ QVector3D QVector4D::toVector3DAffine() const /*! \fn QPoint QVector4D::toPoint() const - Returns the QPoint form of this 4D vector. + Returns the QPoint form of this 4D vector. The z and w coordinates + are dropped. \sa toPointF(), toVector2D() */ @@ -492,7 +493,8 @@ QVector3D QVector4D::toVector3DAffine() const /*! \fn QPointF QVector4D::toPointF() const - Returns the QPointF form of this 4D vector. + Returns the QPointF form of this 4D vector. The z and w coordinates + are dropped. \sa toPoint(), toVector2D() */ diff --git a/src/gui/painting/qmatrix.cpp b/src/gui/painting/qmatrix.cpp index 221267f..bc08235 100644 --- a/src/gui/painting/qmatrix.cpp +++ b/src/gui/painting/qmatrix.cpp @@ -60,6 +60,9 @@ QT_BEGIN_NAMESPACE A matrix specifies how to translate, scale, shear or rotate the coordinate system, and is typically used when rendering graphics. + QMatrix, in contrast to QTransform, does not allow perspective + transformations. QTransform is the recommended transformation + class in Qt. A QMatrix object can be built using the setMatrix(), scale(), rotate(), translate() and shear() functions. Alternatively, it @@ -172,8 +175,8 @@ QT_BEGIN_NAMESPACE \snippet doc/src/snippets/matrix/matrix.cpp 2 \endtable - \sa QPainter, {The Coordinate System}, {demos/affine}{Affine - Transformations Demo}, {Transformations Example} + \sa QPainter, QTransform, {The Coordinate System}, + {demos/affine}{Affine Transformations Demo}, {Transformations Example} */ diff --git a/src/gui/painting/qpaintengine_mac_p.h b/src/gui/painting/qpaintengine_mac_p.h index 755b7b1..20a4a08 100644 --- a/src/gui/painting/qpaintengine_mac_p.h +++ b/src/gui/painting/qpaintengine_mac_p.h @@ -58,9 +58,6 @@ #include "private/qpaintengine_p.h" #include "private/qpolygonclipper_p.h" #include "QtCore/qhash.h" -#ifndef QT_MAC_NO_QUICKDRAW -#include <private/qwidget_p.h> -#endif typedef struct CGColorSpace *CGColorSpaceRef; QT_BEGIN_NAMESPACE @@ -69,108 +66,6 @@ extern int qt_defaultDpi(); extern int qt_defaultDpiX(); extern int qt_defaultDpiY(); -#ifndef QT_MAC_NO_QUICKDRAW -class QMacSavedPortInfo -{ - RgnHandle clip; - GWorldPtr world; - GDHandle handle; - PenState pen; //go pennstate - RGBColor back, fore; - bool valid_gworld; - void init(); - -public: - inline QMacSavedPortInfo() { init(); } - inline QMacSavedPortInfo(QPaintDevice *pd) { init(); setPaintDevice(pd); } - inline QMacSavedPortInfo(QPaintDevice *pd, const QRect &r) - { init(); setPaintDevice(pd); setClipRegion(r); } - inline QMacSavedPortInfo(QPaintDevice *pd, const QRegion &r) - { init(); setPaintDevice(pd); setClipRegion(r); } - ~QMacSavedPortInfo(); - static inline bool setClipRegion(const QRect &r); - static inline bool setClipRegion(const QRegion &r); - static inline bool setPaintDevice(QPaintDevice *); -}; - -inline bool -QMacSavedPortInfo::setClipRegion(const QRect &rect) -{ - Rect r; - SetRect(&r, rect.x(), rect.y(), rect.right()+1, rect.bottom()+1); - ClipRect(&r); - return true; -} - -inline bool -QMacSavedPortInfo::setClipRegion(const QRegion &r) -{ - if(r.isEmpty()) - return setClipRegion(QRect()); - QMacSmartQuickDrawRegion rgn(r.toQDRgn()); - SetClip(rgn); - return true; -} - -inline bool -QMacSavedPortInfo::setPaintDevice(QPaintDevice *pd) -{ - if(!pd) - return false; - bool ret = true; - extern GrafPtr qt_mac_qd_context(const QPaintDevice *); // qpaintdevice_mac.cpp - if(pd->devType() == QInternal::Widget) - SetPortWindowPort(qt_mac_window_for(static_cast<QWidget*>(pd))); - else if(pd->devType() == QInternal::Pixmap || pd->devType() == QInternal::Printer) - SetGWorld((GrafPtr)qt_mac_qd_context(pd), 0); //set the gworld - return ret; -} - -inline void -QMacSavedPortInfo::init() -{ - GetBackColor(&back); - GetForeColor(&fore); - GetGWorld(&world, &handle); - valid_gworld = true; - clip = NewRgn(); - GetClip(clip); - GetPenState(&pen); -} - -inline QMacSavedPortInfo::~QMacSavedPortInfo() -{ - bool set_state = false; - if(valid_gworld) { - set_state = IsValidPort(world); - if(set_state) - SetGWorld(world,handle); //always do this one first - } else { - setPaintDevice(qt_mac_safe_pdev); - } - if(set_state) { - SetClip(clip); - SetPenState(&pen); - RGBForeColor(&fore); - RGBBackColor(&back); - } - DisposeRgn(clip); -} -#else -class QMacSavedPortInfo -{ -public: - inline QMacSavedPortInfo() { } - inline QMacSavedPortInfo(QPaintDevice *) { } - inline QMacSavedPortInfo(QPaintDevice *, const QRect &) { } - inline QMacSavedPortInfo(QPaintDevice *, const QRegion &) { } - ~QMacSavedPortInfo() { } - static inline bool setClipRegion(const QRect &) { return false; } - static inline bool setClipRegion(const QRegion &) { return false; } - static inline bool setPaintDevice(QPaintDevice *) { return false; } -}; -#endif - class QCoreGraphicsPaintEnginePrivate; class QCoreGraphicsPaintEngine : public QPaintEngine { diff --git a/src/gui/painting/qpaintengine_raster.cpp b/src/gui/painting/qpaintengine_raster.cpp index 2febdfa..3d8e349 100644 --- a/src/gui/painting/qpaintengine_raster.cpp +++ b/src/gui/painting/qpaintengine_raster.cpp @@ -1104,6 +1104,9 @@ void QRasterPaintEnginePrivate::systemStateChanged() #ifdef QT_DEBUG_DRAW qDebug() << "systemStateChanged" << this << "deviceRect" << deviceRect << clipRect << systemClip; #endif + + exDeviceRect = deviceRect; + Q_Q(QRasterPaintEngine); q->state()->strokeFlags |= QPaintEngine::DirtyClipRegion; q->state()->fillFlags |= QPaintEngine::DirtyClipRegion; @@ -1711,11 +1714,30 @@ void QRasterPaintEngine::stroke(const QVectorPath &path, const QPen &pen) if (!s->penData.blend) return; - if (s->flags.fast_pen && path.shape() <= QVectorPath::NonCurvedShapeHint && s->lastPen.brush().isOpaque()) { - strokePolygonCosmetic((QPointF *) path.points(), path.elementCount(), - path.hasImplicitClose() - ? WindingMode - : PolylineMode); + if (s->flags.fast_pen && path.shape() <= QVectorPath::NonCurvedShapeHint + && s->lastPen.brush().isOpaque()) { + int count = path.elementCount(); + QPointF *points = (QPointF *) path.points(); + const QPainterPath::ElementType *types = path.elements(); + if (types) { + int first = 0; + int last; + while (first < count) { + while (first < count && types[first] != QPainterPath::MoveToElement) ++first; + last = first + 1; + while (last < count && types[last] == QPainterPath::LineToElement) ++last; + strokePolygonCosmetic(points + first, last - first, + path.hasImplicitClose() && last == count // only close last one.. + ? WindingMode + : PolylineMode); + first = last; + } + } else { + strokePolygonCosmetic(points, count, + path.hasImplicitClose() + ? WindingMode + : PolylineMode); + } } else if (s->flags.non_complex_pen && path.shape() == QVectorPath::LinesHint) { qreal width = s->lastPen.isCosmetic() diff --git a/src/gui/painting/qpaintengineex.cpp b/src/gui/painting/qpaintengineex.cpp index 2fc23f9..a71fe52 100644 --- a/src/gui/painting/qpaintengineex.cpp +++ b/src/gui/painting/qpaintengineex.cpp @@ -362,12 +362,12 @@ void QPaintEngineEx::stroke(const QVectorPath &path, const QPen &pen) d->activeStroker = 0; } else { // ### re-enable... -// if (pen.isCosmetic()) { -// d->dashStroker->setClipRect(d->deviceRect); -// } else { -// QRectF clipRect = s->matrix.inverted().mapRect(QRectF(d->deviceRect)); -// d->dashStroker->setClipRect(clipRect); -// } + if (pen.isCosmetic()) { + d->dasher.setClipRect(d->exDeviceRect); + } else { + QRectF clipRect = state()->matrix.inverted().mapRect(QRectF(d->exDeviceRect)); + d->dasher.setClipRect(clipRect); + } d->dasher.setDashPattern(pen.dashPattern()); d->dasher.setDashOffset(pen.dashOffset()); d->activeStroker = &d->dasher; diff --git a/src/gui/painting/qpaintengineex_p.h b/src/gui/painting/qpaintengineex_p.h index 2a50a51..22354bc 100644 --- a/src/gui/painting/qpaintengineex_p.h +++ b/src/gui/painting/qpaintengineex_p.h @@ -225,6 +225,8 @@ public: StrokeHandler *strokeHandler; QStrokerOps *activeStroker; QPen strokerPen; + + QRect exDeviceRect; }; inline uint QVectorPath::polygonFlags(QPaintEngine::PolygonDrawMode mode) { diff --git a/src/gui/painting/qpainter.cpp b/src/gui/painting/qpainter.cpp index 8738f54..1b128bd 100644 --- a/src/gui/painting/qpainter.cpp +++ b/src/gui/painting/qpainter.cpp @@ -196,7 +196,7 @@ void QPainterPrivate::checkEmulation() extended = emulationEngine; extended->setState(state); } - } else if (emulationEngine && emulationEngine != extended) { + } else if (emulationEngine == extended) { extended = emulationEngine->real_engine; } } @@ -1031,7 +1031,7 @@ void QPainterPrivate::updateState(QPainterState *newState) \o layoutDirection() defines the layout direction used by the painter when drawing text. - \o matrixEnabled() tells whether world transformation is enabled. + \o worldMatrixEnabled() tells whether world transformation is enabled. \o viewTransformEnabled() tells whether view transformation is enabled. diff --git a/src/gui/painting/qpainterpath.cpp b/src/gui/painting/qpainterpath.cpp index ec8a46c..b5301d1 100644 --- a/src/gui/painting/qpainterpath.cpp +++ b/src/gui/painting/qpainterpath.cpp @@ -3165,7 +3165,7 @@ void QPainterPath::addRoundRect(const QRectF &r, int xRnd, int yRnd) Set operations on paths will treat the paths as areas. Non-closed paths will be treated as implicitly closed. - \sa intersected(), subtracted(), subtractedInverted() + \sa intersected(), subtracted() */ QPainterPath QPainterPath::united(const QPainterPath &p) const { diff --git a/src/gui/painting/qprinter.cpp b/src/gui/painting/qprinter.cpp index efaeb43..bc54b5c 100644 --- a/src/gui/painting/qprinter.cpp +++ b/src/gui/painting/qprinter.cpp @@ -2161,8 +2161,8 @@ bool QPrinter::collateCopiesEnabled() const } /*! - Use QPrintDialog::addEnabledOption(QPrintDialog::PrintCollateCopies) - or QPrintDialog::setEnabledOptions(QPrintDialog::enabledOptions() + Use QPrintDialog::setOption(QPrintDialog::PrintCollateCopies) + or QPrintDialog::setOptions(QPrintDialog::options() & ~QPrintDialog::PrintCollateCopies) instead, depending on \a enable. */ diff --git a/src/gui/painting/qstroker.cpp b/src/gui/painting/qstroker.cpp index 0649589..b24bf86 100644 --- a/src/gui/painting/qstroker.cpp +++ b/src/gui/painting/qstroker.cpp @@ -1012,10 +1012,13 @@ void QDashStroker::processCurrentSubpath() int dashCount = qMin(m_dashPattern.size(), 32); qfixed dashes[32]; + qreal longestLength = 0; qreal sumLength = 0; for (int i=0; i<dashCount; ++i) { dashes[i] = qMax(m_dashPattern.at(i), qreal(0)) * m_stroker->strokeWidth(); sumLength += dashes[i]; + if (dashes[i] > longestLength) + longestLength = dashes[i]; } if (qFuzzyIsNull(sumLength)) @@ -1053,7 +1056,7 @@ void QDashStroker::processCurrentSubpath() qfixed2d line_to_pos; // Pad to avoid clipping the borders of thick pens. - qfixed padding = qMax(m_stroker->strokeWidth(), m_stroker->miterLimit()); + qfixed padding = qt_real_to_fixed(qMax(m_stroker->strokeWidth(), m_stroker->miterLimit()) * longestLength); qfixed2d clip_tl = { qt_real_to_fixed(m_clip_rect.left()) - padding, qt_real_to_fixed(m_clip_rect.top()) - padding }; qfixed2d clip_br = { qt_real_to_fixed(m_clip_rect.right()) + padding , diff --git a/src/gui/styles/qcommonstyle.cpp b/src/gui/styles/qcommonstyle.cpp index 308a0b8..ba28e75 100644 --- a/src/gui/styles/qcommonstyle.cpp +++ b/src/gui/styles/qcommonstyle.cpp @@ -2960,6 +2960,9 @@ QRect QCommonStyle::subElementRect(SubElement sr, const QStyleOption *opt, horizontalShift *= -1; verticalShift *= -1; } + if (tab->shape == QTabBar::RoundedWest || tab->shape == QTabBar::TriangularWest) + horizontalShift = -horizontalShift; + tr.adjust(0, 0, horizontalShift, verticalShift); if (selected) { diff --git a/src/gui/styles/qstyle.cpp b/src/gui/styles/qstyle.cpp index a5ab80e..c869976 100644 --- a/src/gui/styles/qstyle.cpp +++ b/src/gui/styles/qstyle.cpp @@ -1108,7 +1108,7 @@ void QStyle::drawItemPixmap(QPainter *painter, const QRect &rect, int alignment, \value CC_ScrollBar A scroll bar, like QScrollBar. \value CC_Slider A slider, like QSlider. \value CC_ToolButton A tool button, like QToolButton. - \value CC_TitleBar A Title bar, like those used in QWorkspace. + \value CC_TitleBar A Title bar, like those used in QMdiSubWindow. \value CC_Q3ListView Used for drawing the Q3ListView class. \value CC_GroupBox A group box, like QGroupBox. \value CC_Dial A dial, like QDial. @@ -1894,7 +1894,7 @@ void QStyle::drawItemPixmap(QPainter *painter, const QRect &rect, int alignment, can follow some existing GUI style or guideline. \value SP_TitleBarMinButton Minimize button on title bars (e.g., - in QWorkspace). + in QMdiSubWindow). \value SP_TitleBarMenuButton Menu button on a title bar. \value SP_TitleBarMaxButton Maximize button on title bars. \value SP_TitleBarCloseButton Close button on title bars. @@ -1966,22 +1966,7 @@ void QStyle::drawItemPixmap(QPainter *painter, const QRect &rect, int alignment, \value SP_CustomBase Base value for custom standard pixmaps; custom values must be greater than this value. - \sa standardPixmap() standardIcon() -*/ - -/*### - \enum QStyle::IconMode - - This enum represents the effects performed on a pixmap to achieve a - GUI style's perferred way of representing the image in different - states. - - \value IM_Disabled A disabled pixmap (drawn on disabled widgets) - \value IM_Active An active pixmap (drawn on active tool buttons and menu items) - \value IM_CustomBase Base value for custom PixmapTypes; custom - values must be greater than this value - - \sa generatedIconPixmap() + \sa standardIcon() */ /*! @@ -2264,7 +2249,7 @@ QPalette QStyle::standardPalette() const slot in your subclass instead. The standardIcon() function will dynamically detect the slot and call it. - \sa standardIconImplementation(), standardPixmap() + \sa standardIconImplementation() */ QIcon QStyle::standardIcon(StandardPixmap standardIcon, const QStyleOption *option, const QWidget *widget) const @@ -2289,8 +2274,7 @@ QIcon QStyle::standardIcon(StandardPixmap standardIcon, const QStyleOption *opti subclass; because of binary compatibility constraints, the standardIcon() function (introduced in Qt 4.1) is not virtual. Instead, standardIcon() will dynamically detect and call - \e this slot. The default implementation simply calls the - standardPixmap() function with the given parameters. + \e this slot. The \a standardIcon is a standard pixmap which can follow some existing GUI style or guideline. The \a option argument can be diff --git a/src/gui/styles/qstyleoption.cpp b/src/gui/styles/qstyleoption.cpp index e174370..0ff1ccf 100644 --- a/src/gui/styles/qstyleoption.cpp +++ b/src/gui/styles/qstyleoption.cpp @@ -4258,8 +4258,7 @@ QStyleOptionRubberBand::QStyleOptionRubberBand(int version) parameters for drawing a title bar. QStyleOptionTitleBar contains all the information that QStyle - functions need to draw the title bars of QWorkspace's MDI - children. + functions need to draw the title bar of a QMdiSubWindow. For performance reasons, the access to the member variables is direct (i.e., using the \c . or \c -> operator). This low-level feel @@ -4269,7 +4268,7 @@ QStyleOptionRubberBand::QStyleOptionRubberBand(int version) For an example demonstrating how style options can be used, see the \l {widgets/styles}{Styles} example. - \sa QStyleOption, QStyleOptionComplex, QWorkspace + \sa QStyleOption, QStyleOptionComplex, QMdiSubWindow */ /*! @@ -4983,8 +4982,7 @@ QStyleOptionSizeGrip::QStyleOptionSizeGrip(int version) */ /*! - Constructs a QStyleOptionGraphicsItem. The levelOfDetail parameter is - initialized to 1. + Constructs a QStyleOptionGraphicsItem. */ QStyleOptionGraphicsItem::QStyleOptionGraphicsItem() : QStyleOption(Version, Type), levelOfDetail(1) @@ -5054,7 +5052,7 @@ qreal QStyleOptionGraphicsItem::levelOfDetailFromTransform(const QTransform &wor To find the dimentions of an item in screen coordinates (i.e., pixels), you can use the mapping functions of QMatrix, such as QMatrix::map(). - \sa QStyleOptionGraphicsItem::levelOfDetail + \sa QStyleOptionGraphicsItem::levelOfDetailFromTransform() */ /*! diff --git a/src/gui/text/qtextcontrol.cpp b/src/gui/text/qtextcontrol.cpp index 78fd13b..88f8028 100644 --- a/src/gui/text/qtextcontrol.cpp +++ b/src/gui/text/qtextcontrol.cpp @@ -1245,8 +1245,7 @@ void QTextControlPrivate::keyPressEvent(QKeyEvent *e) process: { QString text = e->text(); - if (!text.isEmpty() && (text.at(0).isPrint() || text.at(0) == QLatin1Char('\t')) && - ((e->modifiers() & (Qt::ControlModifier | Qt::AltModifier | Qt::MetaModifier)) == Qt::NoModifier)) { + if (!text.isEmpty() && (text.at(0).isPrint() || text.at(0) == QLatin1Char('\t'))) { if (overwriteMode // no need to call deleteChar() if we have a selection, insertText // does it already diff --git a/src/gui/text/qtextlist.cpp b/src/gui/text/qtextlist.cpp index 02b1c63..5e9898a 100644 --- a/src/gui/text/qtextlist.cpp +++ b/src/gui/text/qtextlist.cpp @@ -129,8 +129,6 @@ QTextList::~QTextList() /*! Returns the number of items in the list. - - \sa isEmpty() */ int QTextList::count() const { diff --git a/src/gui/util/qsystemtrayicon_win.cpp b/src/gui/util/qsystemtrayicon_win.cpp index 85eae26..a0648a1 100644 --- a/src/gui/util/qsystemtrayicon_win.cpp +++ b/src/gui/util/qsystemtrayicon_win.cpp @@ -106,6 +106,7 @@ public: private: uint notifyIconSize; int maxTipLength; + bool ignoreNextMouseRelease; }; bool QSystemTrayIconSys::allowsMessages() @@ -128,7 +129,8 @@ bool QSystemTrayIconSys::supportsMessages() } QSystemTrayIconSys::QSystemTrayIconSys(QSystemTrayIcon *object) - : hIcon(0), q(object) + : hIcon(0), q(object), ignoreNextMouseRelease(false) + { #ifndef Q_OS_WINCE notifyIconSize = FIELD_OFFSET(NOTIFYICONDATA, guidItem); // NOTIFYICONDATAW_V2_SIZE; @@ -311,10 +313,15 @@ bool QSystemTrayIconSys::winEvent( MSG *m, long *result ) switch (m->lParam) { case WM_LBUTTONUP: - emit q->activated(QSystemTrayIcon::Trigger); + if (ignoreNextMouseRelease) + ignoreNextMouseRelease = false; + else + emit q->activated(QSystemTrayIcon::Trigger); break; case WM_LBUTTONDBLCLK: + ignoreNextMouseRelease = true; // Since DBLCLICK Generates a second mouse + // release we must ignore it emit q->activated(QSystemTrayIcon::DoubleClick); break; diff --git a/src/gui/widgets/qcocoamenu_mac.mm b/src/gui/widgets/qcocoamenu_mac.mm index 3338fd8..f3bb73e 100644 --- a/src/gui/widgets/qcocoamenu_mac.mm +++ b/src/gui/widgets/qcocoamenu_mac.mm @@ -98,7 +98,9 @@ QT_USE_NAMESPACE while (QWidget *popup = QApplication::activePopupWidget()) popup->close(); - qt_mac_emit_menuSignals(((QT_MANGLE_NAMESPACE(QCocoaMenu) *)menu)->qmenu, true); + QMenu *qtmenu = static_cast<QT_MANGLE_NAMESPACE(QCocoaMenu) *>(menu)->qmenu; + qt_mac_emit_menuSignals(qtmenu, true); + qt_mac_menu_collapseSeparators(menu, qtmenu->separatorsCollapsible()); } - (void)menuWillClose:(NSMenu*)menu; diff --git a/src/gui/widgets/qlineedit.cpp b/src/gui/widgets/qlineedit.cpp index 01d5711..4d69a9f 100644 --- a/src/gui/widgets/qlineedit.cpp +++ b/src/gui/widgets/qlineedit.cpp @@ -2181,8 +2181,7 @@ void QLineEdit::keyPressEvent(QKeyEvent *event) if (unknown && !d->readOnly) { QString t = event->text(); - if (!t.isEmpty() && t.at(0).isPrint() && - ((event->modifiers() & (Qt::ControlModifier | Qt::AltModifier | Qt::MetaModifier)) == Qt::NoModifier)) { + if (!t.isEmpty() && t.at(0).isPrint()) { insert(t); #ifndef QT_NO_COMPLETER d->complete(event->key()); diff --git a/src/gui/widgets/qmenu.cpp b/src/gui/widgets/qmenu.cpp index b69e8bb..4a969db 100644 --- a/src/gui/widgets/qmenu.cpp +++ b/src/gui/widgets/qmenu.cpp @@ -3050,12 +3050,19 @@ bool QMenu::separatorsCollapsible() const void QMenu::setSeparatorsCollapsible(bool collapse) { Q_D(QMenu); + if (d->collapsibleSeparators == collapse) + return; + d->collapsibleSeparators = collapse; d->itemsDirty = 1; if (isVisible()) { d->updateActionRects(); update(); } +#ifdef Q_WS_MAC + if (d->mac_menu) + d->syncSeparatorsCollapsible(collapse); +#endif } #ifdef QT3_SUPPORT diff --git a/src/gui/widgets/qmenu_mac.mm b/src/gui/widgets/qmenu_mac.mm index 87f6f82..e6239f4 100644 --- a/src/gui/widgets/qmenu_mac.mm +++ b/src/gui/widgets/qmenu_mac.mm @@ -458,7 +458,8 @@ OSStatus qt_mac_menu_event(EventHandlerCallRef er, EventRef event, void *) int merged = 0; const QMenuPrivate::QMacMenuPrivate *mac_menu = qmenu->d_func()->mac_menu; - for(int i = 0; i < mac_menu->actionItems.size(); ++i) { + const int ActionItemsCount = mac_menu->actionItems.size(); + for(int i = 0; i < ActionItemsCount; ++i) { QMacMenuAction *action = mac_menu->actionItems.at(i); if (action->action->isSeparator()) { bool hide = false; @@ -972,7 +973,7 @@ void Q_GUI_EXPORT qt_mac_set_menubar_merge(bool b) { qt_mac_no_menubar_merge = ! /***************************************************************************** QMenu bindings *****************************************************************************/ -QMenuPrivate::QMacMenuPrivate::QMacMenuPrivate(QMenuPrivate *menu) : menu(0), qmenu(menu) +QMenuPrivate::QMacMenuPrivate::QMacMenuPrivate() : menu(0) { } @@ -1300,61 +1301,22 @@ QMenuPrivate::QMacMenuPrivate::syncAction(QMacMenuAction *action) #else int itemIndex = [menu indexOfItem:item]; Q_ASSERT(itemIndex != -1); - - // Separator handling: Menu items and separators can be added to a QMenu in - // any order (for example, add all the separators first and then "fill inn" - // the menu items). Create NSMenuItem seperatorItems for the Qt separators, - // and make sure that there are no double separators and no seprators - // at the top or bottom of the menu. - bool itemIsSeparator = action->action->isSeparator(); - bool previousItemIsSeparator = false; - if (itemIndex > 0) { - if ([[menu itemAtIndex : itemIndex - 1] isSeparatorItem]) - previousItemIsSeparator = true; - } - bool nexItemIsSeparator = false; - if (itemIndex > 0 && itemIndex < [menu numberOfItems] -1) { - if ([[menu itemAtIndex : itemIndex + 1] isSeparatorItem]) - nexItemIsSeparator = true; - } - bool itemIsAtBottomOfMenu = (itemIndex == [menu numberOfItems] - 1); - bool itemIsAtTopOfMenu = (itemIndex == 0); - - - if (itemIsSeparator) { - // Create separators items for actions that are now separators + if (action->action->isSeparator()) { action->menuItem = [NSMenuItem separatorItem]; [action->menuItem retain]; - - // Hide duplicate/top/bottom separators. - if (qmenu->collapsibleSeparators && (previousItemIsSeparator || itemIsAtBottomOfMenu || itemIsAtTopOfMenu)) { - [action->menuItem setHidden : true]; - } - [menu insertItem: action->menuItem atIndex:itemIndex]; [menu removeItem:item]; [item release]; item = action->menuItem; return; - } else { - // Create standard menu items for actions that are no longer separators - if ([item isSeparatorItem]) { - action->menuItem = createNSMenuItem(action->action->text()); - [menu insertItem:action->menuItem atIndex:itemIndex]; - [menu removeItem:item]; - [item release]; - item = action->menuItem; - } - - // Show separators that should now be visible since a non-separator - // item (the current item) was added. - if (previousItemIsSeparator) { - [[menu itemAtIndex : itemIndex - 1] setHidden : false]; - } else if (itemIsAtTopOfMenu && nexItemIsSeparator) { - [[menu itemAtIndex : itemIndex + 1] setHidden : false]; - } + } else if ([item isSeparatorItem]) { + // I'm no longer a separator... + action->menuItem = createNSMenuItem(action->action->text()); + [menu insertItem:action->menuItem atIndex:itemIndex]; + [menu removeItem:item]; + [item release]; + item = action->menuItem; } - #endif //find text (and accel) @@ -1540,7 +1502,7 @@ QMenuPrivate::macMenu(OSMenuRef merge) if (mac_menu && mac_menu->menu) return mac_menu->menu; if (!mac_menu) - mac_menu = new QMacMenuPrivate(this); + mac_menu = new QMacMenuPrivate; mac_menu->menu = qt_mac_create_menu(q); if (merge) { #ifndef QT_MAC_USE_COCOA @@ -1552,12 +1514,31 @@ QMenuPrivate::macMenu(OSMenuRef merge) QList<QAction*> items = q->actions(); for(int i = 0; i < items.count(); i++) mac_menu->addAction(items[i], 0, this); + syncSeparatorsCollapsible(collapsibleSeparators); return mac_menu->menu; } /*! \internal */ +void +QMenuPrivate::syncSeparatorsCollapsible(bool collapse) +{ +#ifndef QT_MAC_USE_COCOA + if (collapse) + ChangeMenuAttributes(mac_menu->menu, kMenuAttrCondenseSeparators, 0); + else + ChangeMenuAttributes(mac_menu->menu, 0, kMenuAttrCondenseSeparators); +#else + qt_mac_menu_collapseSeparators(mac_menu->menu, collapse); +#endif +} + + + +/*! + \internal +*/ void QMenuPrivate::setMacMenuEnabled(bool enable) { if (!macMenu(0)) diff --git a/src/gui/widgets/qmenu_p.h b/src/gui/widgets/qmenu_p.h index 355ecb4..0218dc7 100644 --- a/src/gui/widgets/qmenu_p.h +++ b/src/gui/widgets/qmenu_p.h @@ -282,9 +282,8 @@ public: struct QMacMenuPrivate { QList<QMacMenuAction*> actionItems; OSMenuRef menu; - QMenuPrivate *qmenu; - QMacMenuPrivate(QMenuPrivate *menu); - ~QMacMenuPrivate(); + QMacMenuPrivate(); + ~QMacMenuPrivate(); bool merged(const QAction *action) const; void addAction(QAction *, QMacMenuAction* =0, QMenuPrivate *qmenu = 0); @@ -304,6 +303,7 @@ public: } *mac_menu; OSMenuRef macMenu(OSMenuRef merge); void setMacMenuEnabled(bool enable = true); + void syncSeparatorsCollapsible(bool collapsible); static QHash<OSMenuRef, OSMenuRef> mergeMenuHash; static QHash<OSMenuRef, QMenuMergeList*> mergeMenuItemsHash; #endif diff --git a/src/gui/widgets/qmenubar.cpp b/src/gui/widgets/qmenubar.cpp index bb1dd29..3f7675b 100644 --- a/src/gui/widgets/qmenubar.cpp +++ b/src/gui/widgets/qmenubar.cpp @@ -1790,6 +1790,9 @@ void QMenuBarPrivate::_q_internalShortcutActivated(int id) activateAction(act, QAction::Trigger); //100 is the same as the default value in QPushButton::animateClick autoReleaseTimer.start(100, q); + } else if (act && q->style()->styleHint(QStyle::SH_MenuBar_AltKeyNavigation, 0, q)) { + // When we open a menu using a shortcut, we should end up in keyboard state + setKeyboardMode(true); } } diff --git a/src/gui/widgets/qprogressbar.cpp b/src/gui/widgets/qprogressbar.cpp index 6593cd6..7e40c0d 100644 --- a/src/gui/widgets/qprogressbar.cpp +++ b/src/gui/widgets/qprogressbar.cpp @@ -190,10 +190,11 @@ bool QProgressBarPrivate::repaintRequired() const with setValue(). The progress bar can be rewound to the beginning with reset(). - If minimum and maximum both are set to 0, the bar shows a busy indicator - instead of a percentage of steps. This is useful, for example, when using - QFtp or QHttp to download items when they are unable to determine the - size of the item being downloaded. + If minimum and maximum both are set to 0, the bar shows a busy + indicator instead of a percentage of steps. This is useful, for + example, when using QFtp or QNetworkAccessManager to download + items when they are unable to determine the size of the item being + downloaded. \table \row \o \inlineimage macintosh-progressbar.png Screenshot of a Macintosh style progress bar diff --git a/src/gui/widgets/qworkspace.cpp b/src/gui/widgets/qworkspace.cpp index 2833c08..3184140 100644 --- a/src/gui/widgets/qworkspace.cpp +++ b/src/gui/widgets/qworkspace.cpp @@ -110,11 +110,11 @@ bool QMDIControl::event(QEvent *event) QStyle::SubControl ctrl = style()->hitTestComplexControl(QStyle::CC_MdiControls, &opt, helpEvent->pos(), this); if (ctrl == QStyle::SC_MdiCloseButton) - QToolTip::showText(helpEvent->globalPos(), QWorkspace::tr("Close")); + QToolTip::showText(helpEvent->globalPos(), QWorkspace::tr("Close"), this); else if (ctrl == QStyle::SC_MdiMinButton) - QToolTip::showText(helpEvent->globalPos(), QWorkspace::tr("Minimize")); + QToolTip::showText(helpEvent->globalPos(), QWorkspace::tr("Minimize"), this); else if (ctrl == QStyle::SC_MdiNormalButton) - QToolTip::showText(helpEvent->globalPos(), QWorkspace::tr("Restore Down")); + QToolTip::showText(helpEvent->globalPos(), QWorkspace::tr("Restore Down"), this); else QToolTip::hideText(); #endif // QT_NO_TOOLTIP diff --git a/src/network/access/qftp.cpp b/src/network/access/qftp.cpp index acf1a27..8e72323 100644 --- a/src/network/access/qftp.cpp +++ b/src/network/access/qftp.cpp @@ -1390,7 +1390,7 @@ int QFtpPrivate::addCommand(QFtpCommand *cmd) \warning The current version of QFtp doesn't fully support non-Unix FTP servers. - \sa QHttp, QNetworkAccessManager, QNetworkRequest, QNetworkReply, + \sa QNetworkAccessManager, QNetworkRequest, QNetworkReply, {FTP Example} */ @@ -1737,8 +1737,8 @@ int QFtp::setTransferMode(TransferMode mode) Enables use of the FTP proxy on host \a host and port \a port. Calling this function with \a host empty disables proxying. - QFtp does not support FTP-over-HTTP proxy servers. Use QHttp for - this. + QFtp does not support FTP-over-HTTP proxy servers. Use + QNetworkAccessManager for this. */ int QFtp::setProxy(const QString &host, quint16 port) { diff --git a/src/network/kernel/qauthenticator.cpp b/src/network/kernel/qauthenticator.cpp index a26a1fc..8bad6d3 100644 --- a/src/network/kernel/qauthenticator.cpp +++ b/src/network/kernel/qauthenticator.cpp @@ -68,8 +68,8 @@ static QByteArray qNtlmPhase3(QAuthenticatorPrivate *ctx, const QByteArray& phas \inmodule QtNetwork The QAuthenticator class is usually used in the - \l{QHttp::}{authenticationRequired()} and - \l{QHttp::}{proxyAuthenticationRequired()} signals of QHttp and + \l{QNetworkAccessManager::}{authenticationRequired()} and + \l{QNetworkAccessManager::}{proxyAuthenticationRequired()} signals of QNetworkAccessManager and QAbstractSocket. The class provides a way to pass back the required authentication information to the socket when accessing services that require authentication. diff --git a/src/network/kernel/qnetworkproxy.cpp b/src/network/kernel/qnetworkproxy.cpp index 608db65..df478fd 100644 --- a/src/network/kernel/qnetworkproxy.cpp +++ b/src/network/kernel/qnetworkproxy.cpp @@ -54,10 +54,10 @@ QNetworkProxy provides the method for configuring network layer proxy support to the Qt network classes. The currently supported classes are QAbstractSocket, QTcpSocket, QUdpSocket, QTcpServer, - QHttp and QFtp. The proxy support is designed to be as transparent - as possible. This means that existing network-enabled applications - that you have written should automatically support network proxy - using the following code. + QNetworkAccessManager and QFtp. The proxy support is designed to + be as transparent as possible. This means that existing + network-enabled applications that you have written should + automatically support network proxy using the following code. \snippet doc/src/snippets/code/src_network_kernel_qnetworkproxy.cpp 0 @@ -160,8 +160,7 @@ \row \o Caching-only HTTP \o Implemented using normal HTTP commands, it is useful only - in the context of HTTP requests (see QHttp, - QNetworkAccessManager) + in the context of HTTP requests (see QNetworkAccessManager) \o CachingCapability, HostNameLookupCapability \row diff --git a/src/network/socket/qabstractsocket.cpp b/src/network/socket/qabstractsocket.cpp index 9545291..035d5b6 100644 --- a/src/network/socket/qabstractsocket.cpp +++ b/src/network/socket/qabstractsocket.cpp @@ -160,7 +160,7 @@ issue to be aware of, though: You must make sure that enough data is available before attempting to read it using operator>>(). - \sa QFtp, QHttp, QTcpServer + \sa QFtp, QNetworkAccessManager, QTcpServer */ /*! diff --git a/src/network/socket/qtcpsocket.cpp b/src/network/socket/qtcpsocket.cpp index dc0439d..60722cc 100644 --- a/src/network/socket/qtcpsocket.cpp +++ b/src/network/socket/qtcpsocket.cpp @@ -60,10 +60,10 @@ \bold{Note:} TCP sockets cannot be opened in QIODevice::Unbuffered mode. - \sa QTcpServer, QUdpSocket, QFtp, QHttp, {Fortune Server Example}, - {Fortune Client Example}, {Threaded Fortune Server Example}, - {Blocking Fortune Client Example}, {Loopback Example}, - {Torrent Example} + \sa QTcpServer, QUdpSocket, QFtp, QNetworkAccessManager, + {Fortune Server Example}, {Fortune Client Example}, + {Threaded Fortune Server Example}, {Blocking Fortune Client Example}, + {Loopback Example}, {Torrent Example} */ #include "qlist.h" diff --git a/src/opengl/qgl_x11.cpp b/src/opengl/qgl_x11.cpp index 43bdec7..a95b7a0 100644 --- a/src/opengl/qgl_x11.cpp +++ b/src/opengl/qgl_x11.cpp @@ -1648,11 +1648,13 @@ QGLTexture *QGLContextPrivate::bindTextureFromNativePixmap(QPixmap *pm, const qi void QGLTexture::deleteBoundPixmap() { +#if defined(GLX_VERSION_1_3) && !defined(Q_OS_HPUX) if (boundPixmap) { glXReleaseTexImageEXT(QX11Info::display(), boundPixmap, GLX_FRONT_LEFT_EXT); glXDestroyPixmap(QX11Info::display(), boundPixmap); boundPixmap = 0; } +#endif } diff --git a/src/opengl/qgl_x11egl.cpp b/src/opengl/qgl_x11egl.cpp index 99b026d..c6904fe 100644 --- a/src/opengl/qgl_x11egl.cpp +++ b/src/opengl/qgl_x11egl.cpp @@ -258,7 +258,8 @@ void QGLWidget::setContext(QGLContext *context, const QGLContext* shareContext, // If the application has set WA_TranslucentBackground and not explicitly set // the alpha buffer size to zero, modify the format so it have an alpha channel QGLFormat& fmt = d->glcx->d_func()->glFormat; - if (testAttribute(Qt::WA_TranslucentBackground) && fmt.alphaBufferSize() == -1) + const bool useArgbVisual = testAttribute(Qt::WA_TranslucentBackground); + if (useArgbVisual && fmt.alphaBufferSize() == -1) fmt.setAlphaBufferSize(1); bool createFailed = false; @@ -297,8 +298,24 @@ void QGLWidget::setContext(QGLContext *context, const QGLContext* shareContext, int matchingCount = 0; chosenVisualInfo = XGetVisualInfo(x11Info().display(), VisualIDMask, &vi, &matchingCount); if (chosenVisualInfo) { - qDebug("Using X Visual ID (%d) provided by EGL", (int)vi.visualid); - vi = *chosenVisualInfo; + if (useArgbVisual) { + // Check to make sure the visual provided by EGL is ARGB + XRenderPictFormat *format; + format = XRenderFindVisualFormat(x11Info().display(), chosenVisualInfo->visual); + if (format->type == PictTypeDirect && format->direct.alphaMask) { + qDebug("Using opaque X Visual ID (%d) provided by EGL", (int)vi.visualid); + vi = *chosenVisualInfo; + } + else { + qWarning("Warning: EGL suggested using X visual ID %d for config %d, but this is not ARGB", + nativeVisualId, (int)qeglCtx->config()); + vi.visualid = 0; + } + } + else { + qDebug("Using opaque X Visual ID (%d) provided by EGL", (int)vi.visualid); + vi = *chosenVisualInfo; + } XFree(chosenVisualInfo); } else { diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbmouse.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbmouse.cpp index 142993d..4365a5d 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbmouse.cpp +++ b/src/plugins/gfxdrivers/directfb/qdirectfbmouse.cpp @@ -203,7 +203,6 @@ void QDirectFBMouseHandlerPrivate::readMouseData() int wheel = 0; if (input.type == DIET_AXISMOTION) { -#ifdef QT_NO_DIRECTFB_LAYER if (input.flags & DIEF_AXISABS) { switch (input.axis) { case DIAI_X: x = input.axisabs; break; @@ -223,19 +222,6 @@ void QDirectFBMouseHandlerPrivate::readMouseData() "unknown axis (releative) %d", input.axis); } } -#else - if (input.axis == DIAI_X || input.axis == DIAI_Y) { - DFBResult result = layer->GetCursorPosition(layer, &x, &y); - if (result != DFB_OK) { - DirectFBError("QDirectFBMouseHandler::readMouseData", - result); - } - } else if (input.axis == DIAI_Z) { - Q_ASSERT(input.flags & DIEF_AXISREL); - wheel = input.axisrel; - wheel *= -120; - } -#endif } Qt::MouseButtons buttons = Qt::NoButton; diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbpaintengine.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbpaintengine.cpp index 94f1aeb..b264ac0 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbpaintengine.cpp +++ b/src/plugins/gfxdrivers/directfb/qdirectfbpaintengine.cpp @@ -466,7 +466,7 @@ void QDirectFBPaintEngine::drawImage(const QRectF &r, const QImage &image, d->blit(r, imgSurface, sr); if (release) { #if (Q_DIRECTFB_VERSION >= 0x010000) - imgSurface->ReleaseSource(imgSurface); + d->surface->ReleaseSource(d->surface); #endif imgSurface->Release(imgSurface); } @@ -608,6 +608,8 @@ void QDirectFBPaintEngine::drawTextItem(const QPointF &p, void QDirectFBPaintEngine::fill(const QVectorPath &path, const QBrush &brush) { + if (brush.style() == Qt::NoBrush) + return; RASTERFALLBACK(FILL_PATH, path, brush, VOID_ARG()); Q_D(QDirectFBPaintEngine); d->lock(); @@ -618,6 +620,8 @@ void QDirectFBPaintEngine::fill(const QVectorPath &path, const QBrush &brush) void QDirectFBPaintEngine::fillRect(const QRectF &rect, const QBrush &brush) { Q_D(QDirectFBPaintEngine); + if (brush.style() == Qt::NoBrush) + return; d->updateClip(); if (!d->unsupportedCompositionMode && !(d->transformationType & (QDirectFBPaintEnginePrivate::RectsUnsupported)) diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp index 0928643..4b76ef6 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp +++ b/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp @@ -70,7 +70,6 @@ public: IDirectFBDisplayLayer *dfbLayer; #endif IDirectFBScreen *dfbScreen; - QRegion prevExpose; QSet<IDirectFBSurface*> allocatedSurfaces; @@ -82,6 +81,7 @@ public: #endif QDirectFBScreen::DirectFBFlags directFBFlags; QImage::Format alphaPixmapFormat; + QColor backgroundColor; }; QDirectFBScreenPrivate::QDirectFBScreenPrivate(QDirectFBScreen *screen) @@ -141,6 +141,7 @@ IDirectFBSurface *QDirectFBScreen::createDFBSurface(const QImage &img, SurfaceCr { if (img.isNull()) // assert? return 0; + if (QDirectFBScreen::getSurfacePixelFormat(img.format()) == DSPF_UNKNOWN) { QImage image = img.convertToFormat(img.hasAlphaChannel() ? d_ptr->alphaPixmapFormat @@ -321,10 +322,10 @@ IDirectFBSurface *QDirectFBScreen::copyToDFBSurface(const QImage &img, DFBResult result = dfbSurface->Blit(dfbSurface, imgSurface, 0, 0, 0); if (result != DFB_OK) DirectFBError("QDirectFBScreen::copyToDFBSurface()", result); + imgSurface->Release(imgSurface); #if (Q_DIRECTFB_VERSION >= 0x010000) dfbSurface->ReleaseSource(dfbSurface); #endif - imgSurface->Release(imgSurface); #else // QT_NO_DIRECTFB_PREALLOCATED Q_ASSERT(image.format() == pixmapFormat); int bpl; @@ -1047,6 +1048,14 @@ bool QDirectFBScreen::connect(const QString &displaySpec) printDirectFBInfo(d_ptr->dfb, d_ptr->dfbSurface); #endif + QRegExp backgroundColorRegExp("bgcolor=?(.+)"); + backgroundColorRegExp.setCaseSensitivity(Qt::CaseInsensitive); + if (displayArgs.indexOf(backgroundColorRegExp) != -1) { + d_ptr->backgroundColor.setNamedColor(backgroundColorRegExp.cap(1)); + } + if (!d_ptr->backgroundColor.isValid()) + d_ptr->backgroundColor = Qt::green; + return true; } @@ -1087,7 +1096,7 @@ bool QDirectFBScreen::initDevice() #endif #ifndef QT_NO_QWS_CURSOR -#ifdef QT_NO_DIRECTFB_LAYER +#if defined QT_NO_DIRECTFB_WM || defined QT_NO_DIRECTFB_LAYER QScreenCursor::initSoftwareCursor(); #else qt_screencursor = new QDirectFBScreenCursor; @@ -1145,203 +1154,134 @@ QWSWindowSurface *QDirectFBScreen::createSurface(const QString &key) const return QScreen::createSurface(key); } -void QDirectFBScreen::compose(const QRegion ®ion) -{ - const QList<QWSWindow*> windows = QWSServer::instance()->clientWindows(); - - QRegion blitRegion = region; - QRegion blendRegion; - - d_ptr->dfbSurface->SetBlittingFlags(d_ptr->dfbSurface, DSBLIT_NOFX); - - // blit opaque region - for (int i = 0; i < windows.size(); ++i) { - QWSWindow *win = windows.at(i); - QWSWindowSurface *surface = win->windowSurface(); - if (!surface) - continue; - - const QRegion r = win->allocatedRegion() & blitRegion; - if (r.isEmpty()) - continue; - - blitRegion -= r; - - if (surface->isRegionReserved()) { - // nothing - } else if (win->isOpaque()) { - const QPoint offset = win->requestedRegion().boundingRect().topLeft(); - - if (surface->key() == QLatin1String("directfb")) { - QDirectFBWindowSurface *s = static_cast<QDirectFBWindowSurface*>(surface); - blit(s->directFBSurface(), offset, r); - } else { - blit(surface->image(), offset, r); - } - } else { - blendRegion += r; - } - if (blitRegion.isEmpty()) - break; - } - - { // fill background - const QRegion fill = blitRegion + blendRegion; - if (!fill.isEmpty()) { - const QColor color = QWSServer::instance()->backgroundBrush().color(); - solidFill(color, fill); - blitRegion = QRegion(); - } - } - - if (blendRegion.isEmpty()) - return; - - // blend non-opaque region - for (int i = windows.size() - 1; i >= 0; --i) { - QWSWindow *win = windows.at(i); - QWSWindowSurface *surface = win->windowSurface(); - if (!surface) - continue; - - const QRegion r = win->allocatedRegion() & blendRegion; - if (r.isEmpty()) - continue; - - DFBSurfaceBlittingFlags flags = DSBLIT_NOFX; - if (!win->isOpaque()) { - flags |= DSBLIT_BLEND_ALPHACHANNEL; - const uint opacity = win->opacity(); - if (opacity < 255) { - flags |= DSBLIT_BLEND_COLORALPHA; - d_ptr->dfbSurface->SetColor(d_ptr->dfbSurface, 0xff, 0xff, 0xff, opacity); - } - } - d_ptr->dfbSurface->SetBlittingFlags(d_ptr->dfbSurface, flags); - - const QPoint offset = win->requestedRegion().boundingRect().topLeft(); - - if (surface->key() == QLatin1String("directfb")) { - QDirectFBWindowSurface *s = static_cast<QDirectFBWindowSurface*>(surface); - blit(s->directFBSurface(), offset, r); - } else { - blit(surface->image(), offset, r); - } - } -#if (Q_DIRECTFB_VERSION >= 0x010000) - d_ptr->dfbSurface->ReleaseSource(d_ptr->dfbSurface); -#endif -} - // Normally, when using DirectFB to compose the windows (I.e. when // QT_NO_DIRECTFB_WM isn't set), exposeRegion will simply return. If // QT_NO_DIRECTFB_WM is set, exposeRegion will compose only non-directFB // window surfaces. Normal, directFB surfaces are handled by DirectFB. +static inline bool needExposeRegion() +{ +#ifdef QT_NO_DIRECTFB_WM + return true; +#endif +#ifdef QT_NO_DIRECTFB_LAYER +#ifndef QT_NO_QWS_CURSOR + return true; +#endif +#endif + return false; +} + void QDirectFBScreen::exposeRegion(QRegion r, int changing) { + if (!needExposeRegion()) { + return; + } + const QList<QWSWindow*> windows = QWSServer::instance()->clientWindows(); if (changing < 0 || changing >= windows.size()) return; -#ifndef QT_NO_DIRECTFB_WM + QWSWindow *win = windows.at(changing); QWSWindowSurface *s = win->windowSurface(); - if (s && s->key() == QLatin1String("directfb")) - return; -#endif - r &= region(); if (r.isEmpty()) return; - if (d_ptr->flipFlags & DSFLIP_BLIT) { - const QRect brect = r.boundingRect(); - DFBRegion dfbRegion = { brect.left(), brect.top(), - brect.right(), brect.bottom() }; - compose(r); - d_ptr->dfbSurface->Flip(d_ptr->dfbSurface, &dfbRegion, - d_ptr->flipFlags); + const QRect brect = r.boundingRect(); + + if (!s) { + solidFill(d_ptr->backgroundColor, r); } else { - compose(r + d_ptr->prevExpose); - d_ptr->dfbSurface->Flip(d_ptr->dfbSurface, 0, d_ptr->flipFlags); + const QRect windowGeometry = s->geometry(); + const QRegion outsideWindow = r.subtracted(windowGeometry); + if (!outsideWindow.isEmpty()) { + solidFill(d_ptr->backgroundColor, outsideWindow); + } + const QRegion insideWindow = r.intersected(windowGeometry); + if (!insideWindow.isEmpty()) { + QDirectFBWindowSurface *dfbWindowSurface = (s->key() == QLatin1String("directfb")) + ? static_cast<QDirectFBWindowSurface*>(s) : 0; + if (dfbWindowSurface) { + IDirectFBSurface *surface = dfbWindowSurface->directFBSurface(); + const int n = insideWindow.numRects(); + if (n == 1 || d_ptr->directFBFlags & BoundingRectFlip) { + const QRect source = (insideWindow.boundingRect().intersected(windowGeometry)).translated(-windowGeometry.topLeft()); + const DFBRectangle rect = { + source.x(), source.y(), source.width(), source.height() + }; + d_ptr->dfbSurface->Blit(d_ptr->dfbSurface, surface, &rect, + windowGeometry.x() + source.x(), + windowGeometry.y() + source.y()); + } else { + const QVector<QRect> rects = insideWindow.rects(); + QVarLengthArray<DFBRectangle, 16> dfbRectangles(n); + QVarLengthArray<DFBPoint, 16> dfbPoints(n); + + for (int i=0; i<n; ++i) { + const QRect source = (rects.at(i).intersected(windowGeometry)).translated(-windowGeometry.topLeft()); + DFBRectangle &rect = dfbRectangles[i]; + rect.x = source.x(); + rect.y = source.y(); + rect.w = source.width(); + rect.h = source.height(); + dfbPoints[i].x = (windowGeometry.x() + source.x()); + dfbPoints[i].y = (windowGeometry.y() + source.y()); + } + d_ptr->dfbSurface->BatchBlit(d_ptr->dfbSurface, surface, dfbRectangles.constData(), + dfbPoints.constData(), n); + } + } + } } - d_ptr->prevExpose = r; -} - -void QDirectFBScreen::blit(const QImage &img, const QPoint &topLeft, - const QRegion ®) -{ - IDirectFBSurface *src = createDFBSurface(img, QDirectFBScreen::DontTrackSurface); - if (!src) { - qWarning("QDirectFBScreen::blit(): Error creating surface"); - return; - } - blit(src, topLeft, reg); + if (QScreenCursor *cursor = QScreenCursor::instance()) { + const QRect cursorRectangle = cursor->boundingRect(); + if (cursor->isVisible() && !cursor->isAccelerated() && cursorRectangle.intersects(brect)) { + const QImage image = cursor->image(); + IDirectFBSurface *surface = createDFBSurface(image, QDirectFBScreen::DontTrackSurface); + d_ptr->dfbSurface->SetBlittingFlags(d_ptr->dfbSurface, DSBLIT_BLEND_ALPHACHANNEL); + d_ptr->dfbSurface->Blit(d_ptr->dfbSurface, surface, 0, cursorRectangle.x(), cursorRectangle.y()); + surface->Release(surface); #if (Q_DIRECTFB_VERSION >= 0x010000) - d_ptr->dfbSurface->ReleaseSource(d_ptr->dfbSurface); + d_ptr->dfbSurface->ReleaseSource(d_ptr->dfbSurface); #endif - src->Release(src); -} - -void QDirectFBScreen::blit(IDirectFBSurface *src, const QPoint &topLeft, - const QRegion ®ion) -{ - const QVector<QRect> rs = region.translated(-offset()).rects(); - const int size = rs.size(); - const QPoint tl = topLeft - offset(); - - QVarLengthArray<DFBRectangle> rects(size); - QVarLengthArray<DFBPoint> points(size); - - int n = 0; - for (int i = 0; i < size; ++i) { - const QRect r = rs.at(i); - if (!r.isValid()) - continue; - rects[n].x = r.x() - tl.x(); - rects[n].y = r.y() - tl.y(); - rects[n].w = r.width(); - rects[n].h = r.height(); - points[n].x = r.x(); - points[n].y = r.y(); - ++n; + } } - - d_ptr->dfbSurface->BatchBlit(d_ptr->dfbSurface, src, rects.data(), - points.data(), n); + flipSurface(d_ptr->dfbSurface, d_ptr->flipFlags, r, QPoint()); } -// This function is only ever called by QScreen::drawBackground which -// is only ever called by QScreen::compose which is never called with -// DirectFB so it's really a noop. void QDirectFBScreen::solidFill(const QColor &color, const QRegion ®ion) { if (region.isEmpty()) return; - if (QDirectFBScreen::getImageFormat(d_ptr->dfbSurface) == QImage::Format_RGB32) { - data = QDirectFBScreen::lockSurface(d_ptr->dfbSurface, DSLF_WRITE, &lstep); - if (!data) - return; - - QScreen::solidFill(color, region); - d_ptr->dfbSurface->Unlock(d_ptr->dfbSurface); - data = 0; - lstep = 0; + d_ptr->dfbSurface->SetColor(d_ptr->dfbSurface, + color.red(), color.green(), color.blue(), + color.alpha()); + const int n = region.numRects(); + if (n > 1) { + const QRect r = region.boundingRect(); + d_ptr->dfbSurface->FillRectangle(d_ptr->dfbSurface, r.x(), r.y(), r.width(), r.height()); } else { - d_ptr->dfbSurface->SetColor(d_ptr->dfbSurface, - color.red(), color.green(), color.blue(), - color.alpha()); const QVector<QRect> rects = region.rects(); - for (int i=0; i<rects.size(); ++i) { + QVarLengthArray<DFBRectangle, 32> rectArray(n); + for (int i=0; i<n; ++i) { const QRect &r = rects.at(i); - d_ptr->dfbSurface->FillRectangle(d_ptr->dfbSurface, - r.x(), r.y(), r.width(), r.height()); + rectArray[i].x = r.x(); + rectArray[i].y = r.y(); + rectArray[i].w = r.width(); + rectArray[i].h = r.height(); } + d_ptr->dfbSurface->FillRectangles(d_ptr->dfbSurface, rectArray.constData(), n); } } +void QDirectFBScreen::erase(const QRegion ®ion) +{ + solidFill(d_ptr->backgroundColor, region); +} + QImage::Format QDirectFBScreen::alphaPixmapFormat() const { return d_ptr->alphaPixmapFormat; @@ -1377,3 +1317,31 @@ uchar *QDirectFBScreen::lockSurface(IDirectFBSurface *surface, uint flags, int * return reinterpret_cast<uchar*>(mem); } + +void QDirectFBScreen::flipSurface(IDirectFBSurface *surface, DFBSurfaceFlipFlags flipFlags, + const QRegion ®ion, const QPoint &offset) +{ + if (!(flipFlags & DSFLIP_BLIT)) { + surface->Flip(surface, 0, flipFlags); + } else { + if (!(d_ptr->directFBFlags & BoundingRectFlip) && region.numRects() > 1) { + const QVector<QRect> rects = region.rects(); + const DFBSurfaceFlipFlags nonWaitFlags = flipFlags & ~DSFLIP_WAIT; + for (int i=0; i<rects.size(); ++i) { + const QRect &r = rects.at(i); + const DFBRegion dfbReg = { r.x() + offset.x(), r.y() + offset.y(), + r.x() + r.width() + offset.x(), + r.y() + r.height() + offset.y() }; + surface->Flip(surface, &dfbReg, i + 1 < rects.size() ? nonWaitFlags : flipFlags); + } + } else { + const QRect r = region.boundingRect(); + const DFBRegion dfbReg = { r.x() + offset.x(), r.y() + offset.y(), + r.x() + r.width() + offset.x(), + r.y() + r.height() + offset.y() }; + surface->Flip(surface, &dfbReg, flipFlags); + } + } +} + + diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbscreen.h b/src/plugins/gfxdrivers/directfb/qdirectfbscreen.h index 69b09e9..63c608e 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbscreen.h +++ b/src/plugins/gfxdrivers/directfb/qdirectfbscreen.h @@ -52,7 +52,6 @@ QT_MODULE(Gui) #define Q_DIRECTFB_VERSION ((DIRECTFB_MAJOR_VERSION << 16) | (DIRECTFB_MINOR_VERION << 8) | DIRECTFB_MICRO_VERSION) -#include <QDebug> #define DIRECTFB_DECLARE_OPERATORS_FOR_FLAGS(F) \ static inline F operator~(F f) { return F(~int(f)); } \ static inline F operator&(F left, F right) { return F(int(left) & int(right)); } \ @@ -94,7 +93,6 @@ public: void shutdownDevice(); void exposeRegion(QRegion r, int changing); - void blit(const QImage &img, const QPoint &topLeft, const QRegion ®ion); void scroll(const QRegion ®ion, const QPoint &offset); void solidFill(const QColor &color, const QRegion ®ion); @@ -131,9 +129,12 @@ public: QImage::Format format, SurfaceCreationOptions options); IDirectFBSurface *copyToDFBSurface(const QImage &image, - QImage::Format format, - SurfaceCreationOptions options); + QImage::Format format, + SurfaceCreationOptions options); + void flipSurface(IDirectFBSurface *surface, DFBSurfaceFlipFlags flipFlags, + const QRegion ®ion, const QPoint &offset); void releaseDFBSurface(IDirectFBSurface *surface); + void erase(const QRegion ®ion); using QScreen::depth; static int depth(DFBSurfacePixelFormat format); @@ -155,14 +156,9 @@ public: #endif static uchar *lockSurface(IDirectFBSurface *surface, uint flags, int *bpl = 0); - private: IDirectFBSurface *createDFBSurface(DFBSurfaceDescription desc, SurfaceCreationOptions options); - void compose(const QRegion &r); - void blit(IDirectFBSurface *src, const QPoint &topLeft, - const QRegion ®ion); - QDirectFBScreenPrivate *d_ptr; friend class SurfaceCache; }; diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbwindowsurface.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbwindowsurface.cpp index 7dcf398..a1009ac 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbwindowsurface.cpp +++ b/src/plugins/gfxdrivers/directfb/qdirectfbwindowsurface.cpp @@ -44,10 +44,10 @@ #include "qdirectfbpaintengine.h" #include <qwidget.h> +#include <qwindowsystem_qws.h> #include <qpaintdevice.h> #include <qvarlengtharray.h> - //#define QT_DIRECTFB_DEBUG_SURFACES 1 QDirectFBWindowSurface::QDirectFBWindowSurface(DFBSurfaceFlipFlags flip, QDirectFBScreen *scr) @@ -59,6 +59,11 @@ QDirectFBWindowSurface::QDirectFBWindowSurface(DFBSurfaceFlipFlags flip, QDirect , flipFlags(flip) , boundingRectFlip(scr->directFBFlags() & QDirectFBScreen::BoundingRectFlip) { +#ifdef QT_NO_DIRECTFB_WM + mode = Offscreen; +#else + mode = Window; +#endif setSurfaceFlags(Opaque | Buffered); #ifdef QT_DIRECTFB_TIMING frames = 0; @@ -75,11 +80,17 @@ QDirectFBWindowSurface::QDirectFBWindowSurface(DFBSurfaceFlipFlags flip, QDirect , flipFlags(flip) , boundingRectFlip(scr->directFBFlags() & QDirectFBScreen::BoundingRectFlip) { - onscreen = widget->testAttribute(Qt::WA_PaintOnScreen); - if (onscreen) + if (widget && widget->testAttribute(Qt::WA_PaintOnScreen)) { setSurfaceFlags(Opaque | RegionReserved); - else + mode = Primary; + } else { +#ifdef QT_NO_DIRECTFB_WM + mode = Offscreen; +#else + mode = Window; +#endif setSurfaceFlags(Opaque | Buffered); + } #ifdef QT_DIRECTFB_TIMING frames = 0; timer.start(); @@ -99,7 +110,7 @@ bool QDirectFBWindowSurface::isValid() const void QDirectFBWindowSurface::createWindow() { #ifdef QT_NO_DIRECTFB_LAYER -#warning QT_NO_DIRECTFB_LAYER requires QT_NO_DIRECTFB_WM +#error QT_NO_DIRECTFB_LAYER requires QT_NO_DIRECTFB_WM #else IDirectFBDisplayLayer *layer = screen->dfbDisplayLayer(); if (!layer) @@ -129,8 +140,40 @@ void QDirectFBWindowSurface::createWindow() } #endif // QT_NO_DIRECTFB_WM -void QDirectFBWindowSurface::setGeometry(const QRect &rect, const QRegion &mask) +#ifndef QT_NO_DIRECTFB_WM +static DFBResult setGeometry(IDirectFBWindow *dfbWindow, const QRect &old, const QRect &rect) { + DFBResult result = DFB_OK; + const bool isMove = old.isEmpty() || rect.topLeft() != old.topLeft(); + const bool isResize = rect.size() != old.size(); + +#if (Q_DIRECTFB_VERSION >= 0x010000) + if (isResize && isMove) { + result = dfbWindow->SetBounds(dfbWindow, rect.x(), rect.y(), + rect.width(), rect.height()); + } else if (isResize) { + result = dfbWindow->Resize(dfbWindow, + rect.width(), rect.height()); + } else if (isMove) { + result = dfbWindow->MoveTo(dfbWindow, rect.x(), rect.y()); + } +#else + if (isResize) { + result = dfbWindow->Resize(dfbWindow, + rect.width(), rect.height()); + } + if (isMove) { + result = dfbWindow->MoveTo(dfbWindow, rect.x(), rect.y()); + } +#endif + return result; +} +#endif + +void QDirectFBWindowSurface::setGeometry(const QRect &rect) +{ + IDirectFBSurface *primarySurface = screen->dfbSurface(); + Q_ASSERT(primarySurface); if (rect.isNull()) { #ifndef QT_NO_DIRECTFB_WM if (dfbWindow) { @@ -138,22 +181,21 @@ void QDirectFBWindowSurface::setGeometry(const QRect &rect, const QRegion &mask) dfbWindow = 0; } #endif - if (dfbSurface && dfbSurface != screen->dfbSurface()) { - dfbSurface->Release(dfbSurface); + if (dfbSurface) { + if (dfbSurface != primarySurface) { + dfbSurface->Release(dfbSurface); + } dfbSurface = 0; } } else if (rect != geometry()) { + const QRect oldRect = geometry(); DFBResult result = DFB_OK; - // If we're in a resize, the surface shouldn't be locked Q_ASSERT((lockedImage == 0) || (rect.size() == geometry().size())); - - if (onscreen) { - IDirectFBSurface *primarySurface = screen->dfbSurface(); - Q_ASSERT(primarySurface); + switch (mode) { + case Primary: if (dfbSurface && dfbSurface != primarySurface) dfbSurface->Release(dfbSurface); - if (rect == screen->region().boundingRect()) { dfbSurface = primarySurface; } else { @@ -161,58 +203,32 @@ void QDirectFBWindowSurface::setGeometry(const QRect &rect, const QRegion &mask) rect.width(), rect.height() }; result = primarySurface->GetSubSurface(primarySurface, &r, &dfbSurface); } - } else { - const bool isResize = rect.size() != geometry().size(); -#ifdef QT_NO_DIRECTFB_WM - if (isResize) { + break; + case Window: +#ifndef QT_NO_DIRECTFB_WM + if (!dfbWindow) + createWindow(); + ::setGeometry(dfbWindow, oldRect, rect); + // ### do I need to release and get the surface again here? +#endif + break; + case Offscreen: { + if (!dfbSurface || oldRect.size() != rect.size()) { if (dfbSurface) dfbSurface->Release(dfbSurface); - - IDirectFB *dfb = screen->dfb(); - if (!dfb) { - qFatal("QDirectFBWindowSurface::setGeometry(): " - "Unable to get DirectFB handle!"); - } - dfbSurface = screen->createDFBSurface(rect.size(), screen->pixelFormat(), QDirectFBScreen::DontTrackSurface); - } else { - Q_ASSERT(dfbSurface); - } -#else - const QRect oldRect = geometry(); - const bool isMove = oldRect.isEmpty() || - rect.topLeft() != oldRect.topLeft(); - - if (!dfbWindow) - createWindow(); - -#if (Q_DIRECTFB_VERSION >= 0x010000) - if (isResize && isMove) { - result = dfbWindow->SetBounds(dfbWindow, rect.x(), rect.y(), - rect.width(), rect.height()); - } else if (isResize) { - result = dfbWindow->Resize(dfbWindow, - rect.width(), rect.height()); - } else if (isMove) { - result = dfbWindow->MoveTo(dfbWindow, rect.x(), rect.y()); - } -#else - if (isResize) { - result = dfbWindow->Resize(dfbWindow, - rect.width(), rect.height()); - } - if (isMove) { - result = dfbWindow->MoveTo(dfbWindow, rect.x(), rect.y()); } -#endif -#endif + const QRegion region = QRegion(oldRect.isEmpty() ? screen->region() : QRegion(oldRect)).subtracted(rect); + screen->erase(region); + screen->flipSurface(primarySurface, flipFlags, region, QPoint()); + break; } } if (result != DFB_OK) DirectFBErrorFatal("QDirectFBWindowSurface::setGeometry()", result); } - QWSWindowSurface::setGeometry(rect, mask); + QWSWindowSurface::setGeometry(rect); } QByteArray QDirectFBWindowSurface::permanentState() const @@ -254,7 +270,6 @@ static inline void scrollSurface(IDirectFBSurface *surface, const QRect &r, int surface->Blit(surface, surface, &rect, r.x() + dx, r.y() + dy); } - bool QDirectFBWindowSurface::scroll(const QRegion ®ion, int dx, int dy) { if (!dfbSurface || !(flipFlags & DSFLIP_BLIT) || region.isEmpty()) @@ -272,35 +287,13 @@ bool QDirectFBWindowSurface::scroll(const QRegion ®ion, int dx, int dy) return true; } -bool QDirectFBWindowSurface::move(const QPoint &offset) -{ - QWSWindowSurface::move(offset); - -#ifdef QT_NO_DIRECTFB_WM - return true; // buffered -#else - if (!dfbWindow) - return false; - - DFBResult status = dfbWindow->Move(dfbWindow, offset.x(), offset.y()); - return (status == DFB_OK); -#endif -} - -QRegion QDirectFBWindowSurface::move(const QPoint &offset, const QRegion &newClip) +bool QDirectFBWindowSurface::move(const QPoint &moveBy) { -#ifdef QT_NO_DIRECTFB_WM - return QWSWindowSurface::move(offset, newClip); -#else - Q_UNUSED(offset); - Q_UNUSED(newClip); - - // DirectFB handles the entire move, so there's no need to blit. - return QRegion(); -#endif + setGeometry(geometry().translated(moveBy)); + return true; } -QPaintEngine* QDirectFBWindowSurface::paintEngine() const +QPaintEngine *QDirectFBWindowSurface::paintEngine() const { if (!engine) { QDirectFBWindowSurface *that = const_cast<QDirectFBWindowSurface*>(this); @@ -333,57 +326,93 @@ inline bool isWidgetOpaque(const QWidget *w) return false; } -void QDirectFBWindowSurface::flush(QWidget *widget, const QRegion ®ion, + +void QDirectFBWindowSurface::flush(QWidget *, const QRegion ®ion, const QPoint &offset) { - Q_UNUSED(widget); -#ifdef QT_NO_DIRECTFB_WM - Q_UNUSED(region); - Q_UNUSED(offset); -#endif - - QWidget *win = window(); - // hw: make sure opacity information is updated before compositing - const bool opaque = isWidgetOpaque(win); - if (opaque != isOpaque()) { - SurfaceFlags flags = Buffered; - if (opaque) - flags |= Opaque; - setSurfaceFlags(flags); - } + if (QWidget *win = window()) { + + const bool opaque = isWidgetOpaque(win); + if (opaque != isOpaque()) { + SurfaceFlags flags = surfaceFlags(); + if (opaque) { + flags |= Opaque; + } else { + flags &= ~Opaque; + } + setSurfaceFlags(flags); + } #ifndef QT_NO_DIRECTFB_WM - const quint8 winOpacity = quint8(win->windowOpacity() * 255); - quint8 opacity; + const quint8 winOpacity = quint8(win->windowOpacity() * 255); + quint8 opacity; - if (dfbWindow) { - dfbWindow->GetOpacity(dfbWindow, &opacity); - if (winOpacity != opacity) - dfbWindow->SetOpacity(dfbWindow, winOpacity); - } + if (dfbWindow) { + dfbWindow->GetOpacity(dfbWindow, &opacity); + if (winOpacity != opacity) + dfbWindow->SetOpacity(dfbWindow, winOpacity); + } #endif - if (!(flipFlags & DSFLIP_BLIT)) { - dfbSurface->Flip(dfbSurface, 0, flipFlags); - } else { - if (!boundingRectFlip && region.numRects() > 1) { + } + + const QRect windowGeometry = QDirectFBWindowSurface::geometry(); + IDirectFBSurface *primarySurface = screen->dfbSurface(); + if (mode == Offscreen) { + primarySurface->SetBlittingFlags(primarySurface, DSBLIT_NOFX); + const QRect windowRect(0, 0, windowGeometry.width(), windowGeometry.height()); + const int n = region.numRects(); + if (n == 1 || boundingRectFlip ) { + const QRect regionBoundingRect = region.boundingRect().translated(offset); + const QRect source = windowRect & regionBoundingRect; + const DFBRectangle rect = { + source.x(), source.y(), source.width(), source.height() + }; + primarySurface->Blit(primarySurface, dfbSurface, &rect, + windowGeometry.x() + source.x(), + windowGeometry.y() + source.y()); + } else { const QVector<QRect> rects = region.rects(); - const DFBSurfaceFlipFlags nonWaitFlags = flipFlags & ~DSFLIP_WAIT; - for (int i=0; i<rects.size(); ++i) { - const QRect &r = rects.at(i); - const DFBRegion dfbReg = { r.x() + offset.x(), r.y() + offset.y(), - r.x() + r.width() + offset.x(), - r.y() + r.height() + offset.y() }; - dfbSurface->Flip(dfbSurface, &dfbReg, i + 1 < rects.size() ? nonWaitFlags : flipFlags); + QVarLengthArray<DFBRectangle, 16> dfbRectangles(n); + QVarLengthArray<DFBPoint, 16> dfbPoints(n); + + for (int i=0; i<n; ++i) { + const QRect &r = rects.at(i).translated(offset); + const QRect source = windowRect & r; + DFBRectangle &rect = dfbRectangles[i]; + rect.x = source.x(); + rect.y = source.y(); + rect.w = source.width(); + rect.h = source.height(); + dfbPoints[i].x = (windowGeometry.x() + source.x()); + dfbPoints[i].y = (windowGeometry.y() + source.y()); } - } else { - const QRect r = region.boundingRect(); - const DFBRegion dfbReg = { r.x() + offset.x(), r.y() + offset.y(), - r.x() + r.width() + offset.x(), - r.y() + r.height() + offset.y() }; - dfbSurface->Flip(dfbSurface, &dfbReg, flipFlags); + primarySurface->BatchBlit(primarySurface, dfbSurface, dfbRectangles.constData(), + dfbPoints.constData(), n); } } + + if (QScreenCursor *cursor = QScreenCursor::instance()) { + const QRect cursorRectangle = cursor->boundingRect(); + if (cursor->isVisible() && !cursor->isAccelerated() + && region.intersects(cursorRectangle.translated(-(offset + windowGeometry.topLeft())))) { + const QImage image = cursor->image(); + + IDirectFBSurface *surface = screen->createDFBSurface(image, QDirectFBScreen::DontTrackSurface); + primarySurface->SetBlittingFlags(primarySurface, DSBLIT_BLEND_ALPHACHANNEL); + primarySurface->Blit(primarySurface, surface, 0, cursorRectangle.x(), cursorRectangle.y()); + surface->Release(surface); +#if (Q_DIRECTFB_VERSION >= 0x010000) + primarySurface->ReleaseSource(primarySurface); +#endif + } + } + if (mode == Offscreen) { + screen->flipSurface(primarySurface, flipFlags, region, offset + windowGeometry.topLeft()); + } else { + screen->flipSurface(dfbSurface, flipFlags, region, offset); + } + #ifdef QT_DIRECTFB_TIMING enum { Secs = 3 }; ++frames; diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbwindowsurface.h b/src/plugins/gfxdrivers/directfb/qdirectfbwindowsurface.h index 7885b73..c46d93b 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbwindowsurface.h +++ b/src/plugins/gfxdrivers/directfb/qdirectfbwindowsurface.h @@ -67,7 +67,7 @@ public: bool isValid() const; - void setGeometry(const QRect &rect, const QRegion &mask); + void setGeometry(const QRect &rect); QString key() const { return QLatin1String("directfb"); } QByteArray permanentState() const; @@ -76,7 +76,6 @@ public: bool scroll(const QRegion &area, int dx, int dy); bool move(const QPoint &offset); - QRegion move(const QPoint &offset, const QRegion &newClip); QImage image() const { return QImage(); } QPaintDevice *paintDevice() { return this; } @@ -88,7 +87,6 @@ public: void endPaint(const QRegion &); QImage *buffer(const QWidget *widget); - private: #ifndef QT_NO_DIRECTFB_WM void createWindow(); @@ -96,7 +94,11 @@ private: #endif QDirectFBPaintEngine *engine; - bool onscreen; + enum Mode { + Primary, + Offscreen, + Window + } mode; QList<QImage*> bufferImages; DFBSurfaceFlipFlags flipFlags; diff --git a/src/testlib/qtestcoreelement.h b/src/testlib/qtestcoreelement.h index a6aa56d..8c029b5 100644 --- a/src/testlib/qtestcoreelement.h +++ b/src/testlib/qtestcoreelement.h @@ -74,7 +74,7 @@ class QTestCoreElement: public QTestCoreList<ElementType> template<class ElementType> QTestCoreElement<ElementType>::QTestCoreElement(int t) -:listOfAttributes(0), type((QTest::LogElementType)t) + :listOfAttributes(0), type(QTest::LogElementType(t)) { } diff --git a/src/testlib/qtestfilelogger.cpp b/src/testlib/qtestfilelogger.cpp index a717058..a64a452 100644 --- a/src/testlib/qtestfilelogger.cpp +++ b/src/testlib/qtestfilelogger.cpp @@ -73,10 +73,10 @@ void QTestFileLogger::init() QTestResult::currentTestObjectName()); // Keep filenames simple - for (int i = 0; i < sizeof(filename) && filename[i]; ++i) { + for (uint i = 0; i < sizeof(filename) && filename[i]; ++i) { char& c = filename[i]; - if (!(c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z' || c >= '0' && c <= '9' || c == '-' - || c == '.')) { + if (!((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') + || (c >= '0' && c <= '9') || c == '-' || c == '.')) { c = '_'; } } diff --git a/src/xml/sax/qxml.cpp b/src/xml/sax/qxml.cpp index 125e939..dac2c8a 100644 --- a/src/xml/sax/qxml.cpp +++ b/src/xml/sax/qxml.cpp @@ -3037,19 +3037,13 @@ void QXmlSimpleReaderPrivate::initIncrementalParsing() parse() to work incrementally, and making subsequent calls to the parseContinue() function, until all the data has been processed. - A common way to perform incremental parsing is to connect the - \c readyRead() signal of the input source to a slot, and handle the - incoming data there. For example, the following code shows how a - parser for \l{http://web.resource.org/rss/1.0/}{RSS feeds} can be - used to incrementally parse data that it receives from a QHttp - object: - - \snippet doc/src/snippets/xml/rsslisting/rsslisting.cpp 1 - + A common way to perform incremental parsing is to connect the \c + readyRead() signal of a \l{QNetworkReply} {network reply} a slot, + and handle the incoming data there. See QNetworkAccessManager. + Aspects of the parsing behavior can be adapted using setFeature() - and setProperty(). For example, the following code could be used - to enable reporting of namespace prefixes to the content handler: - + and setProperty(). + QXmlSimpleReader is not reentrant. If you want to use the class in threaded code, lock the code using QXmlSimpleReader with a locking mechanism, such as a QMutex. |