diff options
author | axis <qt-info@nokia.com> | 2009-08-21 13:23:42 (GMT) |
---|---|---|
committer | axis <qt-info@nokia.com> | 2009-08-21 13:23:42 (GMT) |
commit | 044680951401487590c0ed554092dd9b7e0ee783 (patch) | |
tree | ed2492ad2fd49481148fdd7a1486cbf197c9bfe7 | |
parent | ab1df6dea670a60bfef5efd81d6687f9534cfc5d (diff) | |
parent | 00ba962d428dcdff70fcde74a9e5cb316545cef6 (diff) | |
download | Qt-044680951401487590c0ed554092dd9b7e0ee783.zip Qt-044680951401487590c0ed554092dd9b7e0ee783.tar.gz Qt-044680951401487590c0ed554092dd9b7e0ee783.tar.bz2 |
Merge branch 'master' of git@scm.dev.nokia.troll.no:qt/qt
Conflicts:
src/corelib/io/qprocess.h
-rwxr-xr-x | configure | 2 | ||||
-rw-r--r-- | doc/src/snippets/qprocess-environment/main.cpp | 6 | ||||
-rw-r--r-- | src/corelib/io/qfile.cpp | 22 | ||||
-rw-r--r-- | src/corelib/io/qfsfileengine_unix.cpp | 46 | ||||
-rw-r--r-- | src/corelib/io/qfsfileengine_win.cpp | 42 | ||||
-rw-r--r-- | src/corelib/io/qprocess.cpp | 394 | ||||
-rw-r--r-- | src/corelib/io/qprocess.h | 39 | ||||
-rw-r--r-- | src/corelib/io/qprocess_p.h | 19 | ||||
-rw-r--r-- | src/corelib/io/qprocess_unix.cpp | 26 | ||||
-rw-r--r-- | src/corelib/io/qprocess_win.cpp | 19 | ||||
-rw-r--r-- | src/corelib/io/qresource.cpp | 6 | ||||
-rw-r--r-- | src/corelib/kernel/qabstractitemmodel.cpp | 11 | ||||
-rw-r--r-- | src/gui/kernel/qapplication_p.h | 12 | ||||
-rw-r--r-- | src/gui/kernel/qapplication_win.cpp | 128 | ||||
-rw-r--r-- | src/gui/kernel/qgesture.cpp | 37 | ||||
-rw-r--r-- | src/gui/kernel/qgesture.h | 8 | ||||
-rw-r--r-- | src/gui/kernel/qgesture_p.h | 5 | ||||
-rw-r--r-- | src/gui/kernel/qstandardgestures.cpp | 126 | ||||
-rw-r--r-- | src/gui/kernel/qstandardgestures.h | 4 | ||||
-rw-r--r-- | src/gui/kernel/qstandardgestures_p.h | 5 | ||||
-rw-r--r-- | src/gui/kernel/qwidget_win.cpp | 23 | ||||
-rw-r--r-- | tests/auto/auto.pro | 5 | ||||
-rw-r--r-- | tests/auto/qprocess/tst_qprocess.cpp | 37 |
23 files changed, 737 insertions, 285 deletions
@@ -103,7 +103,7 @@ EOF "$TEST_COMPILER" "$@" -o /dev/null conftest.cpp ret=$? rm -f conftest.cpp conftest.o - return $? + return $ret } # relies on $TEST_COMPILER being set correctly diff --git a/doc/src/snippets/qprocess-environment/main.cpp b/doc/src/snippets/qprocess-environment/main.cpp index a143bf8..0fa0896 100644 --- a/doc/src/snippets/qprocess-environment/main.cpp +++ b/doc/src/snippets/qprocess-environment/main.cpp @@ -57,10 +57,10 @@ process.start("myapp"); { //! [1] QProcess process; -QHash<QString, QString> env = QProcess::systemEnvironmentHash(); +QProcessEnvironment env = QProcessEnvironment::systemEnvironment(); env.insert("TMPDIR", "C:\\MyApp\\temp"); // Add an environment variable -env["PATH"] += ";C:\\Bin"; -process.setEnvironment(env); +env.insert("PATH", env.value("Path") + ";C:\\Bin"); +process.setProcessEnvironment(env); process.start("myapp"); //! [1] } diff --git a/src/corelib/io/qfile.cpp b/src/corelib/io/qfile.cpp index 5e1a5e7..026c1fd 100644 --- a/src/corelib/io/qfile.cpp +++ b/src/corelib/io/qfile.cpp @@ -52,10 +52,6 @@ # include "qcoreapplication.h" #endif -#if !defined(Q_OS_WINCE) -#include <errno.h> -#endif - #ifdef QT_NO_QOBJECT #define tr(X) QString::fromLatin1(X) #endif @@ -653,11 +649,7 @@ QFile::remove() unsetError(); return true; } -#if defined(Q_OS_WIN) - d->setError(QFile::RemoveError, GetLastError()); -#else - d->setError(QFile::RemoveError, errno); -#endif + d->setError(QFile::RemoveError, fileEngine()->errorString()); } return false; } @@ -812,7 +804,7 @@ QFile::link(const QString &linkName) unsetError(); return true; } - d->setError(QFile::RenameError, errno); + d->setError(QFile::RenameError, fileEngine()->errorString()); return false; } @@ -1258,7 +1250,7 @@ QFile::resize(qint64 sz) unsetError(); return true; } - d->setError(QFile::ResizeError, errno); + d->setError(QFile::ResizeError, fileEngine()->errorString()); return false; } @@ -1322,7 +1314,7 @@ QFile::setPermissions(Permissions permissions) unsetError(); return true; } - d->setError(QFile::PermissionsError, errno); + d->setError(QFile::PermissionsError, fileEngine()->errorString()); return false; } @@ -1478,7 +1470,7 @@ bool QFile::seek(qint64 off) d->setError(err, fileEngine()->errorString()); return false; } - d->error = NoError; + unsetError(); return true; } @@ -1506,7 +1498,7 @@ qint64 QFile::readLineData(char *data, qint64 maxlen) qint64 QFile::readData(char *data, qint64 len) { Q_D(QFile); - d->error = NoError; + unsetError(); if (!d->ensureFlushed()) return -1; @@ -1588,7 +1580,7 @@ qint64 QFile::writeData(const char *data, qint64 len) { Q_D(QFile); - d->error = NoError; + unsetError(); d->lastWasWrite = true; bool buffered = !(d->openMode & Unbuffered); diff --git a/src/corelib/io/qfsfileengine_unix.cpp b/src/corelib/io/qfsfileengine_unix.cpp index 4ee5c68..3bc2616 100644 --- a/src/corelib/io/qfsfileengine_unix.cpp +++ b/src/corelib/io/qfsfileengine_unix.cpp @@ -394,7 +394,10 @@ bool QFSFileEnginePrivate::nativeIsSequential() const bool QFSFileEngine::remove() { Q_D(QFSFileEngine); - return unlink(d->nativeFilePath.constData()) == 0; + bool ret = unlink(d->nativeFilePath.constData()) == 0; + if (!ret) + setError(QFile::RemoveError, qt_error_string(errno)); + return ret; } bool QFSFileEngine::copy(const QString &newName) @@ -422,6 +425,7 @@ bool QFSFileEngine::copy(const QString &newName) return (err == KErrNone); #else // ### Add copy code for Unix here + setError(QFile::UnspecifiedError, QLatin1String("Not implemented!")); return false; #endif } @@ -429,13 +433,19 @@ bool QFSFileEngine::copy(const QString &newName) bool QFSFileEngine::rename(const QString &newName) { Q_D(QFSFileEngine); - return ::rename(d->nativeFilePath.constData(), QFile::encodeName(newName).constData()) == 0; + bool ret = ::rename(d->nativeFilePath.constData(), QFile::encodeName(newName).constData()) == 0; + if (!ret) + setError(QFile::RenameError, qt_error_string(errno)); + return ret; } bool QFSFileEngine::link(const QString &newName) { Q_D(QFSFileEngine); - return ::symlink(d->nativeFilePath.constData(), QFile::encodeName(newName).constData()) == 0; + bool ret = ::symlink(d->nativeFilePath.constData(), QFile::encodeName(newName).constData()) == 0; + if (!ret) + setError(QFile::RenameError, qt_error_string(errno)); + return ret; } qint64 QFSFileEnginePrivate::nativeSize() const @@ -1143,6 +1153,7 @@ QString QFSFileEngine::owner(FileOwner own) const bool QFSFileEngine::setPermissions(uint perms) { Q_D(QFSFileEngine); + bool ret = false; mode_t mode = 0; if (perms & ReadOwnerPerm) mode |= S_IRUSR; @@ -1169,18 +1180,27 @@ bool QFSFileEngine::setPermissions(uint perms) if (perms & ExeOtherPerm) mode |= S_IXOTH; if (d->fd != -1) - return !fchmod(d->fd, mode); - return !::chmod(d->nativeFilePath.constData(), mode); + ret = fchmod(d->fd, mode) == 0; + else + ret = ::chmod(d->nativeFilePath.constData(), mode) == 0; + if (!ret) + setError(QFile::PermissionsError, qt_error_string(errno)); + return ret; } bool QFSFileEngine::setSize(qint64 size) { Q_D(QFSFileEngine); + bool ret = false; if (d->fd != -1) - return !QT_FTRUNCATE(d->fd, size); - if (d->fh) - return !QT_FTRUNCATE(QT_FILENO(d->fh), size); - return !QT_TRUNCATE(d->nativeFilePath.constData(), size); + ret = QT_FTRUNCATE(d->fd, size) == 0; + else if (d->fh) + ret = QT_FTRUNCATE(QT_FILENO(d->fh), size) == 0; + else + ret = QT_TRUNCATE(d->nativeFilePath.constData(), size) == 0; + if (!ret) + setError(QFile::ResizeError, qt_error_string(errno)); + return ret; } QDateTime QFSFileEngine::fileTime(FileTime time) const @@ -1202,14 +1222,14 @@ uchar *QFSFileEnginePrivate::map(qint64 offset, qint64 size, QFile::MemoryMapFla { Q_Q(QFSFileEngine); Q_UNUSED(flags); - if (offset < 0) { - q->setError(QFile::UnspecifiedError, qt_error_string(int(EINVAL))); - return 0; - } if (openMode == QIODevice::NotOpen) { q->setError(QFile::PermissionsError, qt_error_string(int(EACCES))); return 0; } + if (offset < 0) { + q->setError(QFile::UnspecifiedError, qt_error_string(int(EINVAL))); + return 0; + } int access = 0; if (openMode & QIODevice::ReadOnly) access |= PROT_READ; if (openMode & QIODevice::WriteOnly) access |= PROT_WRITE; diff --git a/src/corelib/io/qfsfileengine_win.cpp b/src/corelib/io/qfsfileengine_win.cpp index e01b42b..afe7b35 100644 --- a/src/corelib/io/qfsfileengine_win.cpp +++ b/src/corelib/io/qfsfileengine_win.cpp @@ -780,21 +780,30 @@ bool QFSFileEnginePrivate::nativeIsSequential() const bool QFSFileEngine::remove() { Q_D(QFSFileEngine); - return ::DeleteFile((wchar_t*)QFSFileEnginePrivate::longFileName(d->filePath).utf16()) != 0; + bool ret = ::DeleteFile((wchar_t*)QFSFileEnginePrivate::longFileName(d->filePath).utf16()) != 0; + if (!ret) + setError(QFile::RemoveError, qt_error_string()); + return ret; } bool QFSFileEngine::copy(const QString ©Name) { Q_D(QFSFileEngine); - return ::CopyFile((wchar_t*)QFSFileEnginePrivate::longFileName(d->filePath).utf16(), - (wchar_t*)QFSFileEnginePrivate::longFileName(copyName).utf16(), true) != 0; + bool ret = ::CopyFile((wchar_t*)QFSFileEnginePrivate::longFileName(d->filePath).utf16(), + (wchar_t*)QFSFileEnginePrivate::longFileName(copyName).utf16(), true) != 0; + if (!ret) + setError(QFile::CopyError, qt_error_string()); + return ret; } bool QFSFileEngine::rename(const QString &newName) { Q_D(QFSFileEngine); - return ::MoveFile((wchar_t*)QFSFileEnginePrivate::longFileName(d->filePath).utf16(), - (wchar_t*)QFSFileEnginePrivate::longFileName(newName).utf16()) != 0; + bool ret = ::MoveFile((wchar_t*)QFSFileEnginePrivate::longFileName(d->filePath).utf16(), + (wchar_t*)QFSFileEnginePrivate::longFileName(newName).utf16()) != 0; + if (!ret) + setError(QFile::RenameError, qt_error_string()); + return ret; } static inline bool mkDir(const QString &path) @@ -1303,6 +1312,9 @@ bool QFSFileEngine::link(const QString &newName) } psl->Release(); } + if (!ret) + setError(QFile::RenameError, qt_error_string()); + if(neededCoInit) CoUninitialize(); @@ -1319,7 +1331,10 @@ bool QFSFileEngine::link(const QString &newName) // Need to append on our own orgName.prepend(QLatin1Char('"')); orgName.append(QLatin1Char('"')); - return SUCCEEDED(SHCreateShortcut((wchar_t*)linkName.utf16(), (wchar_t*)orgName.utf16())); + bool ret = SUCCEEDED(SHCreateShortcut((wchar_t*)linkName.utf16(), (wchar_t*)orgName.utf16())); + if (!ret) + setError(QFile::RenameError, qt_error_string()); + return ret; #endif // Q_OS_WINCE } @@ -1643,7 +1658,9 @@ bool QFSFileEngine::setPermissions(uint perms) if (mode == 0) // not supported return false; - ret = ::_wchmod((wchar_t*)d->longFileName(d->filePath).utf16(), mode) == 0; + ret = ::_wchmod((wchar_t*)QFSFileEnginePrivate::longFileName(d->filePath).utf16(), mode) == 0; + if (!ret) + setError(QFile::PermissionsError, qt_error_string(errno)); return ret; } @@ -1675,7 +1692,10 @@ bool QFSFileEngine::setSize(qint64 size) // resize file on disk QFile file(d->filePath); if (file.open(QFile::ReadWrite)) { - return file.resize(size); + bool ret = file.resize(size); + if (!ret) + setError(QFile::ResizeError, file.errorString()); + return ret; } } return false; @@ -1778,11 +1798,11 @@ uchar *QFSFileEnginePrivate::map(qint64 offset, qint64 size, Q_Q(QFSFileEngine); Q_UNUSED(flags); if (openMode == QFile::NotOpen) { - q->setError(QFile::PermissionsError, qt_error_string()); + q->setError(QFile::PermissionsError, qt_error_string(ERROR_ACCESS_DENIED)); return 0; } if (offset == 0 && size == 0) { - q->setError(QFile::UnspecifiedError, qt_error_string()); + q->setError(QFile::UnspecifiedError, qt_error_string(ERROR_INVALID_PARAMETER)); return 0; } @@ -1864,7 +1884,7 @@ bool QFSFileEnginePrivate::unmap(uchar *ptr) { Q_Q(QFSFileEngine); if (!maps.contains(ptr)) { - q->setError(QFile::PermissionsError, qt_error_string()); + q->setError(QFile::PermissionsError, qt_error_string(ERROR_ACCESS_DENIED)); return false; } uchar *start = ptr - maps[ptr].first; diff --git a/src/corelib/io/qprocess.cpp b/src/corelib/io/qprocess.cpp index 18ed676..057492d 100644 --- a/src/corelib/io/qprocess.cpp +++ b/src/corelib/io/qprocess.cpp @@ -101,27 +101,294 @@ QT_END_NAMESPACE QT_BEGIN_NAMESPACE -static QHash<QString, QString> environmentHashFromList(const QStringList &environment) +/*! + \class QProcessEnvironment + + \brief The QProcessEnvironment class holds the environment variables that + can be passed to a program. + + \ingroup io + \ingroup misc + \mainclass + \reentrant + \since 4.6 + + A process's environment is composed of a set of key=value pairs known as + environment variables. The QProcessEnvironment class wraps that concept + and allows easy manipulation of those variables. It's meant to be used + along with QProcess, to set the environment for child processes. It + cannot be used to change the current process's environment. + + The environment of the calling process can be obtained using + QProcessEnvironment::systemEnvironment(). + + On Unix systems, the variable names are case-sensitive. For that reason, + this class will not touch the names of the variables. Note as well that + Unix environment allows both variable names and contents to contain arbitrary + binary data (except for the NUL character), but this is not supported by + QProcessEnvironment. This class only supports names and values that are + encodable by the current locale settings (see QTextCodec::codecForLocale). + + On Windows, the variable names are case-insensitive. Therefore, + QProcessEnvironment will always uppercase the names and do case-insensitive + comparisons. + + On Windows CE, the concept of environment does not exist. This class will + keep the values set for compatibility with other platforms, but the values + set will have no effect on the processes being created. + + \sa QProcess, QProcess::systemEnvironment(), QProcess::setProcessEnvironment() +*/ +#ifdef Q_OS_WIN +static inline QProcessEnvironmentPrivate::Unit prepareName(const QString &name) +{ return name.toUpper(); } +static inline QProcessEnvironmentPrivate::Unit prepareName(const QByteArray &name) +{ return QString::fromLocal8Bit(name).toUpper(); } +static inline QString nameToString(const QProcessEnvironmentPrivate::Unit &name) +{ return name; } +static inline QProcessEnvironmentPrivate::Unit prepareValue(const QString &value) +{ return value; } +static inline QProcessEnvironmentPrivate::Unit prepareValue(const QByteArray &value) +{ return QString::fromLocal8Bit(value); } +static inline QString valueToString(const QProcessEnvironmentPrivate::Unit &value) +{ return value; } +static inline QByteArray valueToByteArray(const QProcessEnvironmentPrivate::Unit &value) +{ return value.toLocal8Bit(); } +#else +static inline QProcessEnvironmentPrivate::Unit prepareName(const QByteArray &name) +{ return name; } +static inline QProcessEnvironmentPrivate::Unit prepareName(const QString &name) +{ return name.toLocal8Bit(); } +static inline QString nameToString(const QProcessEnvironmentPrivate::Unit &name) +{ return QString::fromLocal8Bit(name); } +static inline QProcessEnvironmentPrivate::Unit prepareValue(const QByteArray &value) +{ return value; } +static inline QProcessEnvironmentPrivate::Unit prepareValue(const QString &value) +{ return value.toLocal8Bit(); } +static inline QString valueToString(const QProcessEnvironmentPrivate::Unit &value) +{ return QString::fromLocal8Bit(value); } +static inline QByteArray valueToByteArray(const QProcessEnvironmentPrivate::Unit &value) +{ return value; } +#endif + +template<> void QSharedDataPointer<QProcessEnvironmentPrivate>::detach() +{ + if (d && d->ref == 1) + return; + QProcessEnvironmentPrivate *x = (d ? new QProcessEnvironmentPrivate(*d) + : new QProcessEnvironmentPrivate); + x->ref.ref(); + if (d && !d->ref.deref()) + delete d; + d = x; +} + +QStringList QProcessEnvironmentPrivate::toList() const { - QHash<QString, QString> result; - QStringList::ConstIterator it = environment.constBegin(), - end = environment.constEnd(); + QStringList result; + QHash<Unit, Unit>::ConstIterator it = hash.constBegin(), + end = hash.constEnd(); for ( ; it != end; ++it) { - int equals = it->indexOf(QLatin1Char('=')); + QString data = nameToString(it.key()); + QString value = valueToString(it.value()); + data.reserve(data.length() + value.length() + 1); + data.append(QLatin1Char('=')); + data.append(value); + result << data; + } + return result; +} +QProcessEnvironment QProcessEnvironmentPrivate::fromList(const QStringList &list) +{ + QProcessEnvironment env; + QStringList::ConstIterator it = list.constBegin(), + end = list.constEnd(); + for ( ; it != end; ++it) { + int pos = it->indexOf(QLatin1Char('=')); + if (pos < 1) + continue; + + QString value = it->mid(pos + 1); QString name = *it; - QString value; - if (equals != -1) { - name.truncate(equals); -#ifdef Q_OS_WIN - name = name.toUpper(); -#endif - value = it->mid(equals + 1); - } - result.insert(name, value); + name.truncate(pos); + env.insert(name, value); } + return env; +} - return result; +/*! + Creates a new QProcessEnvironment object. This constructor creates an + empty environment. If set on a QProcess, this will cause the current + environment variables to be removed. +*/ +QProcessEnvironment::QProcessEnvironment() + : d(0) +{ +} + +/*! + Frees the resources associated with this QProcessEnvironment object. +*/ +QProcessEnvironment::~QProcessEnvironment() +{ +} + +/*! + Creates a QProcessEnvironment object that is a copy of \a other. +*/ +QProcessEnvironment::QProcessEnvironment(const QProcessEnvironment &other) + : d(other.d) +{ +} + +/*! + Copies the contents of the \a other QProcessEnvironment object into this + one. +*/ +QProcessEnvironment &QProcessEnvironment::operator=(const QProcessEnvironment &other) +{ + d = other.d; + return *this; +} + +/*! + \fn bool QProcessEnvironment::operator !=(const QProcessEnvironment &other) const + + Returns true if this and the \a other QProcessEnvironment objects are different. + + \sa operator==() +*/ + +/*! + Returns true if this and the \a other QProcessEnvironment objects are equal. + + Two QProcessEnvironment objects are considered equal if they have the same + set of key=value pairs. The comparison of keys is done case-sensitive on + platforms where the environment is case-sensitive. + + \sa operator!=(), contains() +*/ +bool QProcessEnvironment::operator==(const QProcessEnvironment &other) const +{ + return d->hash == other.d->hash; +} + +/*! + Returns true if this QProcessEnvironment object is empty: that is + there are no key=value pairs set. + + \sa clear(), systemEnvironment(), insert() +*/ +bool QProcessEnvironment::isEmpty() const +{ + return d ? d->hash.isEmpty() : true; +} + +/*! + Removes all key=value pairs from this QProcessEnvironment object, making + it empty. + + \sa isEmpty(), systemEnvironment() +*/ +void QProcessEnvironment::clear() +{ + if (d) + d->hash.clear(); +} + +/*! + Returns true if the environment variable of name \a name is found in + this QProcessEnvironment object. + + On Windows, variable names are case-insensitive, so the key is converted + to uppercase before searching. On other systems, names are case-sensitive + so no trasformation is applied. + + \sa insert(), value() +*/ +bool QProcessEnvironment::contains(const QString &name) const +{ + return d ? d->hash.contains(prepareName(name)) : false; +} + +/*! + Inserts the environment variable of name \a name and contents \a value + into this QProcessEnvironment object. If that variable already existed, + it is replaced by the new value. + + On Windows, variable names are case-insensitive, so this function always + uppercases the variable name before inserting. On other systems, names + are case-sensitive, so no transformation is applied. + + On most systems, inserting a variable with no contents will have the + same effect for applications as if the variable had not been set at all. + However, to guarantee that there are no incompatibilities, to remove a + variable, please use the remove() function. + + \sa contains(), remove(), value() +*/ +void QProcessEnvironment::insert(const QString &name, const QString &value) +{ + d->hash.insert(prepareName(name), prepareValue(value)); +} + +/*! + Removes the environment variable identified by \a name from this + QProcessEnvironment object. If that variable did not exist before, + nothing happens. + + On Windows, variable names are case-insensitive, so the key is converted + to uppercase before searching. On other systems, names are case-sensitive + so no trasformation is applied. + + \sa contains(), insert(), value() +*/ +void QProcessEnvironment::remove(const QString &name) +{ + if (d) + d->hash.remove(prepareName(name)); +} + +/*! + Searches this QProcessEnvironment object for a variable identified by + \a name and returns its value. If the variable is not found in this object, + then \a defaultValue is returned instead. + + On Windows, variable names are case-insensitive, so the key is converted + to uppercase before searching. On other systems, names are case-sensitive + so no trasformation is applied. + + \sa contains(), insert(), remove() +*/ +QString QProcessEnvironment::value(const QString &name, const QString &defaultValue) const +{ + if (!d) + return defaultValue; + + QProcessEnvironmentPrivate::Hash::ConstIterator it = d->hash.constFind(prepareName(name)); + if (it == d->hash.constEnd()) + return defaultValue; + + return valueToString(it.value()); +} + +/*! + Converts this QProcessEnvironment object into a list of strings, one for + each environment variable that is set. The environment variable's name + and its value are separated by an equal character ('='). + + The QStringList contents returned by this function are suitable for use + with the QProcess::setEnvironment function. However, it is recommended + to use QProcess::setProcessEnvironment instead since that will avoid + unnecessary copying of the data. + + \sa systemEnvironment(), QProcess::systemEnvironment(), QProcess::environment(), + QProcess::setEnvironment() +*/ +QStringList QProcessEnvironment::toStringList() const +{ + return d ? d->toList() : QStringList(); } void QProcessPrivate::Channel::clear() @@ -451,7 +718,6 @@ QProcessPrivate::QProcessPrivate() sequenceNumber = 0; exitCode = 0; exitStatus = QProcess::NormalExit; - environment = 0; startupSocketNotifier = 0; deathNotifier = 0; notifier = 0; @@ -482,7 +748,6 @@ QProcessPrivate::QProcessPrivate() */ QProcessPrivate::~QProcessPrivate() { - delete environment; if (stdinChannel.process) stdinChannel.process->stdoutChannel.clear(); if (stdoutChannel.process) @@ -1235,6 +1500,7 @@ QProcess::ProcessState QProcess::state() const } /*! + \deprecated Sets the environment that QProcess will use when starting a process to the \a environment specified which consists of a list of key=value pairs. @@ -1243,14 +1509,18 @@ QProcess::ProcessState QProcess::state() const \snippet doc/src/snippets/qprocess-environment/main.cpp 0 - \sa environment(), systemEnvironment(), setEnvironmentHash() + \note This function is less efficient than the setProcessEnvironment() + function. + + \sa environment(), setProcessEnvironment(), systemEnvironment() */ void QProcess::setEnvironment(const QStringList &environment) { - setEnvironmentHash(environmentHashFromList(environment)); + setProcessEnvironment(QProcessEnvironmentPrivate::fromList(environment)); } /*! + \deprecated Returns the environment that QProcess will use when starting a process, or an empty QStringList if no environment has been set using setEnvironment() or setEnvironmentHash(). If no environment @@ -1259,67 +1529,50 @@ void QProcess::setEnvironment(const QStringList &environment) \note The environment settings are ignored on Windows CE and Symbian, as there is no concept of an environment. - \sa environmentHash(), setEnvironment(), systemEnvironment() + \sa processEnvironment(), setEnvironment(), systemEnvironment() */ QStringList QProcess::environment() const { Q_D(const QProcess); - - QStringList result; - if (!d->environment) - return result; - - QHash<QString, QString>::ConstIterator it = d->environment->constBegin(), - end = d->environment->constEnd(); - for ( ; it != end; ++it) { - QString data = it.key(); - data.reserve(data.length() + it.value().length() + 1); - data.append(QLatin1Char('=')); - data.append(it.value()); - result << data; - } - return result; + return d->environment.toStringList(); } /*! - \since 4.5 + \since 4.6 Sets the environment that QProcess will use when starting a process to the - \a environment hash map. + \a environment object. For example, the following code adds the \c{C:\\BIN} directory to the list of executable paths (\c{PATHS}) on Windows and sets \c{TMPDIR}: \snippet doc/src/snippets/qprocess-environment/main.cpp 1 - \sa environment(), systemEnvironmentHash(), setEnvironment() + Note how, on Windows, environment variable names are case-insensitive. + + \sa processEnvironment(), QProcessEnvironment::systemEnvironment(), setEnvironment() */ -void QProcess::setEnvironmentHash(const QHash<QString, QString> &environment) +void QProcess::setProcessEnvironment(const QProcessEnvironment &environment) { Q_D(QProcess); - if (!d->environment) - d->environment = new QHash<QString, QString>(environment); - else - *d->environment = environment; + d->environment = environment; } /*! - \since 4.5 + \since 4.6 Returns the environment that QProcess will use when starting a - process, or an empty QHash if no environment has been set using - setEnvironment() or setEnvironmentHash(). If no environment has + process, or an empty object if no environment has been set using + setEnvironment() or setProcessEnvironment(). If no environment has been set, the environment of the calling process will be used. \note The environment settings are ignored on Windows CE, as there is no concept of an environment. - \sa setEnvironmentHash(), setEnvironment(), systemEnvironmentHash() + \sa setProcessEnvironment(), setEnvironment(), QProcessEnvironment::isValid() */ -QHash<QString, QString> QProcess::environmentHash() const +QProcessEnvironment QProcess::processEnvironment() const { Q_D(const QProcess); - if (d->environment) - return *d->environment; - return QHash<QString, QString>(); + return d->environment; } /*! @@ -1924,7 +2177,16 @@ QT_END_INCLUDE_NAMESPACE \snippet doc/src/snippets/code/src_corelib_io_qprocess.cpp 8 - \sa systemEnvironmentHash(), environment(), setEnvironment() + This function does not cache the system environment. Therefore, it's + possible to obtain an updated version of the environment if low-level C + library functions like \tt setenv ot \tt putenv have been called. + + However, note that repeated calls to this function will recreate the + list of environment variables, which is a non-trivial operation. + + \note For new code, it is recommended to use QProcessEvironment::systemEnvironment() + + \sa QProcessEnvironment::systemEnvironment(), environment(), setEnvironment() */ QStringList QProcess::systemEnvironment() { @@ -1937,15 +2199,33 @@ QStringList QProcess::systemEnvironment() } /*! - \since 4.5 + \since 4.6 + + Returns the environment of the calling process as a QProcessEnvironment. - Returns the environment of the calling process as a QHash. + This function does not cache the system environment. Therefore, it's + possible to obtain an updated version of the environment if low-level C + library functions like \tt setenv ot \tt putenv have been called. - \sa systemEnvironment(), environmentHash(), setEnvironmentHash() + However, note that repeated calls to this function will recreate the + QProcessEnvironment object, which is a non-trivial operation. + + \sa QProcess::systemEnvironment() */ -QHash<QString, QString> QProcess::systemEnvironmentHash() +QProcessEnvironment QProcessEnvironment::systemEnvironment() { - return environmentHashFromList(systemEnvironment()); + QProcessEnvironment env; + const char *entry; + for (int count = 0; (entry = environ[count]); ++count) { + const char *equal = strchr(entry, '='); + if (!equal) + continue; + + QByteArray name(entry, equal - entry); + QByteArray value(equal + 1); + env.insert(QString::fromLocal8Bit(name), QString::fromLocal8Bit(value)); + } + return env; } /*! diff --git a/src/corelib/io/qprocess.h b/src/corelib/io/qprocess.h index 5faca5c..e0c7efb 100644 --- a/src/corelib/io/qprocess.h +++ b/src/corelib/io/qprocess.h @@ -44,6 +44,7 @@ #include <QtCore/qiodevice.h> #include <QtCore/qstringlist.h> +#include <QtCore/qshareddata.h> QT_BEGIN_HEADER @@ -53,8 +54,6 @@ QT_MODULE(Core) #ifndef QT_NO_PROCESS -template <class Key, class T> class QHash; - #if (!defined(Q_OS_WIN32) && !defined(Q_OS_WINCE) && !defined(Q_OS_SYMBIAN)) || defined(qdoc) typedef qint64 Q_PID; #elif defined(Q_OS_SYMBIAN) @@ -69,6 +68,37 @@ QT_BEGIN_NAMESPACE #endif class QProcessPrivate; +class QProcessEnvironmentPrivate; + +class Q_CORE_EXPORT QProcessEnvironment +{ +public: + QProcessEnvironment(); + QProcessEnvironment(const QProcessEnvironment &other); + ~QProcessEnvironment(); + QProcessEnvironment &operator=(const QProcessEnvironment &other); + + bool operator==(const QProcessEnvironment &other) const; + inline bool operator!=(const QProcessEnvironment &other) const + { return !(*this == other); } + + bool isEmpty() const; + void clear(); + + bool contains(const QString &name) const; + void insert(const QString &name, const QString &value); + void remove(const QString &name); + QString value(const QString &name, const QString &defaultValue = QString()) const; + + QStringList toStringList() const; + + static QProcessEnvironment systemEnvironment(); + +private: + friend class QProcessPrivate; + friend class QProcessEnvironmentPrivate; + QSharedDataPointer<QProcessEnvironmentPrivate> d; +}; class Q_CORE_EXPORT QProcess : public QIODevice { @@ -128,8 +158,8 @@ public: void setEnvironment(const QStringList &environment); QStringList environment() const; - void setEnvironmentHash(const QHash<QString, QString> &environment); - QHash<QString, QString> environmentHash() const; + void setProcessEnvironment(const QProcessEnvironment &environment); + QProcessEnvironment processEnvironment() const; QProcess::ProcessError error() const; QProcess::ProcessState state() const; @@ -165,7 +195,6 @@ public: static bool startDetached(const QString &program); static QStringList systemEnvironment(); - static QHash<QString, QString> systemEnvironmentHash(); public Q_SLOTS: void terminate(); diff --git a/src/corelib/io/qprocess_p.h b/src/corelib/io/qprocess_p.h index 34797b9..62a2ecc 100644 --- a/src/corelib/io/qprocess_p.h +++ b/src/corelib/io/qprocess_p.h @@ -55,6 +55,8 @@ #include "QtCore/qprocess.h" #include "QtCore/qstringlist.h" +#include "QtCore/qhash.h" +#include "QtCore/qshareddata.h" #include "private/qringbuffer_p.h" #include "private/qiodevice_p.h" @@ -76,6 +78,21 @@ class QWindowsPipeWriter; class QWinEventNotifier; class QTimer; +class QProcessEnvironmentPrivate: public QSharedData +{ +public: +#ifdef Q_OS_WIN + typedef QString Unit; +#else + typedef QByteArray Unit; +#endif + typedef QHash<Unit, Unit> Hash; + Hash hash; + + static QProcessEnvironment fromList(const QStringList &list); + QStringList toList() const; +}; + class QProcessPrivate : public QIODevicePrivate { public: @@ -161,7 +178,7 @@ public: QString program; QStringList arguments; - QHash<QString, QString> *environment; + QProcessEnvironment environment; QRingBuffer outputReadBuffer; QRingBuffer errorReadBuffer; diff --git a/src/corelib/io/qprocess_unix.cpp b/src/corelib/io/qprocess_unix.cpp index d28cdc4..dfeeb71 100644 --- a/src/corelib/io/qprocess_unix.cpp +++ b/src/corelib/io/qprocess_unix.cpp @@ -458,11 +458,11 @@ bool QProcessPrivate::createChannel(Channel &channel) } } -static char **_q_dupEnvironment(const QHash<QString, QString> *environment, int *envc) +static char **_q_dupEnvironment(const QHash<QByteArray, QByteArray> &environment, int *envc) { *envc = 0; - if (!environment) - return 0; // use the default environment + if (environment.isEmpty()) + return 0; // if LD_LIBRARY_PATH exists in the current environment, but // not in the environment list passed by the programmer, then @@ -474,17 +474,17 @@ static char **_q_dupEnvironment(const QHash<QString, QString> *environment, int #endif const QByteArray envLibraryPath = qgetenv(libraryPath); bool needToAddLibraryPath = !envLibraryPath.isEmpty() && - !environment->contains(QLatin1String(libraryPath)); + !environment.contains(libraryPath); - char **envp = new char *[environment->count() + 2]; - envp[environment->count()] = 0; - envp[environment->count() + 1] = 0; + char **envp = new char *[environment.count() + 2]; + envp[environment.count()] = 0; + envp[environment.count() + 1] = 0; - QHash<QString, QString>::ConstIterator it = environment->constBegin(); - const QHash<QString, QString>::ConstIterator end = environment->constEnd(); + QHash<QByteArray, QByteArray>::ConstIterator it = environment.constBegin(); + const QHash<QByteArray, QByteArray>::ConstIterator end = environment.constEnd(); for ( ; it != end; ++it) { - QByteArray key = it.key().toLocal8Bit(); - QByteArray value = it.value().toLocal8Bit(); + QByteArray key = it.key(); + QByteArray value = it.value(); key.reserve(key.length() + 1 + value.length()); key.append('='); key.append(value); @@ -590,7 +590,9 @@ void QProcessPrivate::startProcess() // Duplicate the environment. int envc = 0; - char **envp = _q_dupEnvironment(environment, &envc); + char **envp = 0; + if (environment.d.constData()) + envp = _q_dupEnvironment(environment.d.constData()->hash, &envc); // Encode the working directory if it's non-empty, otherwise just pass 0. const char *workingDirPtr = 0; diff --git a/src/corelib/io/qprocess_win.cpp b/src/corelib/io/qprocess_win.cpp index acb169f..8ece6ec 100644 --- a/src/corelib/io/qprocess_win.cpp +++ b/src/corelib/io/qprocess_win.cpp @@ -278,17 +278,17 @@ static QString qt_create_commandline(const QString &program, const QStringList & return args; } -static QByteArray qt_create_environment(const QHash<QString, QString> *environment) +static QByteArray qt_create_environment(const QHash<QString, QString> &environment) { QByteArray envlist; - if (environment) { - QHash<QString, QString> copy = *environment; + if (!environment.isEmpty()) { + QHash<QString, QString> copy = environment; // add PATH if necessary (for DLL loading) if (!copy.contains(QLatin1String("PATH"))) { QByteArray path = qgetenv("PATH"); if (!path.isEmpty()) - copy.insert(QLatin1String("PATH"), QString::fromLocal8Bit(path)); + copy.insert(QLatin1String("PATH"), QString::fromLocal8Bit(path)); } // add systemroot if needed @@ -362,7 +362,9 @@ void QProcessPrivate::startProcess() QString args = qt_create_commandline(QString(), arguments); #else QString args = qt_create_commandline(program, arguments); - QByteArray envlist = qt_create_environment(environment); + QByteArray envlist; + if (environment.d.constData()) + envlist = qt_create_environment(environment.d.constData()->hash); #endif #if defined QPROCESS_DEBUG @@ -393,9 +395,13 @@ void QProcessPrivate::startProcess() }; success = CreateProcess(0, (wchar_t*)args.utf16(), 0, 0, TRUE, dwCreationFlags, - environment ? envlist.data() : 0, + environment.isEmpty() ? 0 : envlist.data(), workingDirectory.isEmpty() ? 0 : (wchar_t*)QDir::toNativeSeparators(workingDirectory).utf16(), &startupInfo, pid); + if (!success) { + // Capture the error string before we do CloseHandle below + q->setErrorString(QProcess::tr("Process failed to start: %1").arg(qt_error_string())); + } if (stdinChannel.pipe[0] != INVALID_Q_PIPE) { CloseHandle(stdinChannel.pipe[0]); @@ -414,7 +420,6 @@ void QProcessPrivate::startProcess() if (!success) { cleanup(); processError = QProcess::FailedToStart; - q->setErrorString(QProcess::tr("Process failed to start")); emit q->error(processError); q->setProcessState(QProcess::NotRunning); return; diff --git a/src/corelib/io/qresource.cpp b/src/corelib/io/qresource.cpp index ab4a7b7..ff1a31f 100644 --- a/src/corelib/io/qresource.cpp +++ b/src/corelib/io/qresource.cpp @@ -1485,11 +1485,7 @@ uchar *QResourceFileEnginePrivate::map(qint64 offset, qint64 size, QFile::Memory { Q_Q(QResourceFileEngine); Q_UNUSED(flags); - if (!resource.isValid() - || offset < 0 - || size < 0 - || offset + size > resource.size() - || (size == 0)) { + if (offset < 0 || size <= 0 || !resource.isValid() || offset + size > resource.size()) { q->setError(QFile::UnspecifiedError, QString()); return 0; } diff --git a/src/corelib/kernel/qabstractitemmodel.cpp b/src/corelib/kernel/qabstractitemmodel.cpp index 17af60d..3b7059b 100644 --- a/src/corelib/kernel/qabstractitemmodel.cpp +++ b/src/corelib/kernel/qabstractitemmodel.cpp @@ -1216,7 +1216,16 @@ void QAbstractItemModelPrivate::columnsRemoved(const QModelIndex &parent, layoutChanged() after changing the layout. Subclasses should update any persistent model indexes before emitting - layoutChanged(). + layoutChanged(). In other words, when the structure changes: + + \list + \o Call beginLayoutChanged() + \o Remember the QModelIndex that will change + \o Update your internal data + \o Call changePersistentIndex() + \o Call endLayoutChanged() + \endlist + \sa layoutAboutToBeChanged(), dataChanged(), headerDataChanged(), reset(), changePersistentIndex() diff --git a/src/gui/kernel/qapplication_p.h b/src/gui/kernel/qapplication_p.h index 7a27756..e839617 100644 --- a/src/gui/kernel/qapplication_p.h +++ b/src/gui/kernel/qapplication_p.h @@ -249,6 +249,17 @@ typedef struct tagGESTURECONFIG #endif // WM_GESTURE +#if defined(Q_WS_WINCE_WM) && defined(QT_WINCE_GESTURES) +#undef GID_ZOOM +#define GID_ZOOM 0xf000 +#undef GID_ROTATE +#define GID_ROTATE 0xf001 +#undef GID_TWOFINGERTAP +#define GID_TWOFINGERTAP 0xf002 +#undef GID_ROLLOVER +#define GID_ROLLOVER 0xf003 +#endif + #endif // Q_WS_WIN class QPanGesture; @@ -536,6 +547,7 @@ public: PtrBeginPanningFeedback BeginPanningFeedback; PtrUpdatePanningFeedback UpdatePanningFeedback; PtrEndPanningFeedback EndPanningFeedback; + QWidget *gestureWidget; #endif #ifdef QT_RX71_MULTITOUCH diff --git a/src/gui/kernel/qapplication_win.cpp b/src/gui/kernel/qapplication_win.cpp index 7d9e6ea..12cd879 100644 --- a/src/gui/kernel/qapplication_win.cpp +++ b/src/gui/kernel/qapplication_win.cpp @@ -452,7 +452,7 @@ public: bool translateConfigEvent(const MSG &msg); bool translateCloseEvent(const MSG &msg); bool translateTabletEvent(const MSG &msg, PACKET *localPacketBuf, int numPackets); - bool translateGestureEvent(const MSG &msg); + bool translateGestureEvent(const MSG &msg, const GESTUREINFO &gi); void repolishStyle(QStyle &style); inline void showChildren(bool spontaneous) { d_func()->showChildren(spontaneous); } inline void hideChildren(bool spontaneous) { d_func()->hideChildren(spontaneous); } @@ -848,6 +848,7 @@ void qt_init(QApplicationPrivate *priv, int) (PtrEndPanningFeedback)QLibrary::resolve(QLatin1String("uxtheme"), "EndPanningFeedback"); #endif + priv->gestureWidget = 0; } /***************************************************************************** @@ -2513,10 +2514,38 @@ LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam } result = false; break; - case WM_GESTURE: - widget->translateGestureEvent(msg); + case WM_GESTURE: { + GESTUREINFO gi; + memset(&gi, 0, sizeof(GESTUREINFO)); + gi.cbSize = sizeof(GESTUREINFO); + + QApplicationPrivate *qAppPriv = QApplicationPrivate::instance(); + BOOL bResult = false; + if (qAppPriv->GetGestureInfo) + bResult = qAppPriv->GetGestureInfo((HANDLE)msg.lParam, &gi); + if (bResult) { + if (gi.dwID == GID_BEGIN) { + // find the alien widget for the gesture position. + // This might not be accurate as the position is the center + // point of two fingers for multi-finger gestures. + QPoint pt(gi.ptsLocation.x, gi.ptsLocation.y); + QWidget *w = widget->childAt(widget->mapFromGlobal(pt)); + qAppPriv->gestureWidget = w ? w : widget; + } + if (qAppPriv->gestureWidget) + static_cast<QETWidget*>(qAppPriv->gestureWidget)->translateGestureEvent(msg, gi); + if (qAppPriv->CloseGestureInfoHandle) + qAppPriv->CloseGestureInfoHandle((HANDLE)msg.lParam); + if (gi.dwID == GID_END) + qAppPriv->gestureWidget = 0; + } else { + DWORD dwErr = GetLastError(); + if (dwErr > 0) + qWarning() << "translateGestureEvent: error = " << dwErr; + } result = true; break; + } default: result = false; // event was not processed break; @@ -3725,69 +3754,42 @@ bool QETWidget::translateCloseEvent(const MSG &) return d_func()->close_helper(QWidgetPrivate::CloseWithSpontaneousEvent); } -bool QETWidget::translateGestureEvent(const MSG &msg) +bool QETWidget::translateGestureEvent(const MSG &, const GESTUREINFO &gi) { - GESTUREINFO gi; - memset(&gi, 0, sizeof(GESTUREINFO)); - gi.cbSize = sizeof(GESTUREINFO); + const QPoint widgetPos = QPoint(gi.ptsLocation.x, gi.ptsLocation.y); + QWidget *alienWidget = !internalWinId() ? this : childAt(widgetPos); + if (alienWidget && alienWidget->internalWinId()) + alienWidget = 0; + QWidget *widget = alienWidget ? alienWidget : this; - QApplicationPrivate *qAppPriv = QApplicationPrivate::instance(); -#if defined(Q_WS_WINCE_WM) && defined(QT_WINCE_GESTURES) -#undef GID_ZOOM -#define GID_ZOOM 0xf000 -#undef GID_ROTATE -#define GID_ROTATE 0xf001 -#undef GID_TWOFINGERTAP -#define GID_TWOFINGERTAP 0xf002 -#undef GID_ROLLOVER -#define GID_ROLLOVER 0xf003 -#endif - BOOL bResult = false; - if (qAppPriv->GetGestureInfo) - bResult = qAppPriv->GetGestureInfo((HANDLE)msg.lParam, &gi); - - if (bResult) { - const QPoint widgetPos = QPoint(gi.ptsLocation.x, gi.ptsLocation.y); - QWidget *alienWidget = !internalWinId() ? this : childAt(widgetPos); - if (alienWidget && alienWidget->internalWinId()) - alienWidget = 0; - QWidget *widget = alienWidget ? alienWidget : this; - - QNativeGestureEvent event; - event.sequenceId = gi.dwSequenceID; - event.position = QPoint(gi.ptsLocation.x, gi.ptsLocation.y); - event.argument = gi.ullArguments; - - switch (gi.dwID) { - case GID_BEGIN: - event.gestureType = QNativeGestureEvent::GestureBegin; - break; - case GID_END: - event.gestureType = QNativeGestureEvent::GestureEnd; - break; - case GID_ZOOM: - event.gestureType = QNativeGestureEvent::Zoom; - break; - case GID_PAN: - event.gestureType = QNativeGestureEvent::Pan; - break; - case GID_ROTATE: - event.gestureType = QNativeGestureEvent::Rotate; - break; - case GID_TWOFINGERTAP: - case GID_ROLLOVER: - default: - break; - } - if (qAppPriv->CloseGestureInfoHandle) - qAppPriv->CloseGestureInfoHandle((HANDLE)msg.lParam); - if (event.gestureType != QNativeGestureEvent::None) - qt_sendSpontaneousEvent(widget, &event); - } else { - DWORD dwErr = GetLastError(); - if (dwErr > 0) - qWarning() << "translateGestureEvent: error = " << dwErr; + QNativeGestureEvent event; + event.sequenceId = gi.dwSequenceID; + event.position = QPoint(gi.ptsLocation.x, gi.ptsLocation.y); + event.argument = gi.ullArguments; + + switch (gi.dwID) { + case GID_BEGIN: + event.gestureType = QNativeGestureEvent::GestureBegin; + break; + case GID_END: + event.gestureType = QNativeGestureEvent::GestureEnd; + break; + case GID_ZOOM: + event.gestureType = QNativeGestureEvent::Zoom; + break; + case GID_PAN: + event.gestureType = QNativeGestureEvent::Pan; + break; + case GID_ROTATE: + event.gestureType = QNativeGestureEvent::Rotate; + break; + case GID_TWOFINGERTAP: + case GID_ROLLOVER: + default: + break; } + if (event.gestureType != QNativeGestureEvent::None) + qt_sendSpontaneousEvent(widget, &event); return true; } diff --git a/src/gui/kernel/qgesture.cpp b/src/gui/kernel/qgesture.cpp index 79dcae1..eeb6528 100644 --- a/src/gui/kernel/qgesture.cpp +++ b/src/gui/kernel/qgesture.cpp @@ -149,20 +149,18 @@ private: \sa setGraphicsItem() */ -QGesture::QGesture(QObject *parent) +QGesture::QGesture(QObject *gestureTarget, QObject *parent) : QObject(*new QGesturePrivate, parent) { - if (parent) - parent->installEventFilter(this); + setGestureTarget(gestureTarget); } /*! \internal */ -QGesture::QGesture(QGesturePrivate &dd, QObject *parent) +QGesture::QGesture(QGesturePrivate &dd, QObject *gestureTarget, QObject *parent) : QObject(dd, parent) { - if (parent) - parent->installEventFilter(this); + setGestureTarget(gestureTarget); } /*! @@ -172,6 +170,33 @@ QGesture::~QGesture() { } +/*! + \property QGesture::gestureTarget + + Gesture target is the object that the gesture will observe for events. + Typically this means that the gesture installs an event filter on the + target object. +*/ +void QGesture::setGestureTarget(QObject *object) +{ + d_func()->setupGestureTarget(object); +} + +QObject* QGesture::gestureTarget() const +{ + return d_func()->gestureTarget; +} + +void QGesturePrivate::setupGestureTarget(QObject *object) +{ + Q_Q(QGesture); + if (gestureTarget) + gestureTarget->removeEventFilter(q); + if (object) + object->installEventFilter(q); + gestureTarget = object; +} + /*! \internal */ bool QGesture::eventFilter(QObject *receiver, QEvent *event) diff --git a/src/gui/kernel/qgesture.h b/src/gui/kernel/qgesture.h index ee28ea4..1d2fa6d 100644 --- a/src/gui/kernel/qgesture.h +++ b/src/gui/kernel/qgesture.h @@ -63,20 +63,24 @@ class Q_GUI_EXPORT QGesture : public QObject Q_DECLARE_PRIVATE(QGesture) Q_PROPERTY(Qt::GestureState state READ state) + Q_PROPERTY(QObject* gestureTarget READ gestureTarget WRITE setGestureTarget) public: - explicit QGesture(QObject *parent = 0); + explicit QGesture(QObject *gestureTarget = 0, QObject *parent = 0); ~QGesture(); virtual bool filterEvent(QEvent *event) = 0; + void setGestureTarget(QObject *object); + QObject* gestureTarget() const; + void setGraphicsItem(QGraphicsItem *); QGraphicsItem *graphicsItem() const; Qt::GestureState state() const; protected: - QGesture(QGesturePrivate &dd, QObject *parent); + QGesture(QGesturePrivate &dd, QObject *gestureTarget, QObject *parent); bool eventFilter(QObject*, QEvent*); virtual void reset(); diff --git a/src/gui/kernel/qgesture_p.h b/src/gui/kernel/qgesture_p.h index 37f3146..f584713 100644 --- a/src/gui/kernel/qgesture_p.h +++ b/src/gui/kernel/qgesture_p.h @@ -69,11 +69,14 @@ class QGesturePrivate : public QObjectPrivate public: QGesturePrivate() - : graphicsItem(0), eventFilterProxyGraphicsItem(0), state(Qt::NoGesture) + : gestureTarget(0), graphicsItem(0), eventFilterProxyGraphicsItem(0), + state(Qt::NoGesture) { } + virtual void setupGestureTarget(QObject *o); + QPointer<QObject> gestureTarget; QGraphicsItem *graphicsItem; QGraphicsItem *eventFilterProxyGraphicsItem; diff --git a/src/gui/kernel/qstandardgestures.cpp b/src/gui/kernel/qstandardgestures.cpp index 10689ba..d798d32 100644 --- a/src/gui/kernel/qstandardgestures.cpp +++ b/src/gui/kernel/qstandardgestures.cpp @@ -69,42 +69,35 @@ QWidgetPrivate *qt_widget_private(QWidget *widget); On some platform like Windows it's necessary to provide a non-null widget as \a parent to get native gesture support. */ -QPanGesture::QPanGesture(QWidget *parent) - : QGesture(*new QPanGesturePrivate, parent) +QPanGesture::QPanGesture(QWidget *gestureTarget, QObject *parent) + : QGesture(*new QPanGesturePrivate, gestureTarget, parent) { - if (parent) { - QApplicationPrivate *qAppPriv = QApplicationPrivate::instance(); - qAppPriv->widgetGestures[parent].pan = this; -#ifdef Q_WS_WIN - qt_widget_private(parent)->winSetupGestures(); -#endif - } } -/*! \internal */ -bool QPanGesture::event(QEvent *event) +void QPanGesturePrivate::setupGestureTarget(QObject *newGestureTarget) { - switch (event->type()) { - case QEvent::ParentAboutToChange: - if (QWidget *w = qobject_cast<QWidget*>(parent())) { - QApplicationPrivate::instance()->widgetGestures[w].pan = 0; + Q_Q(QPanGesture); + if (gestureTarget && gestureTarget->isWidgetType()) { + QWidget *w = static_cast<QWidget*>(gestureTarget.data()); + QApplicationPrivate::instance()->widgetGestures[w].pan = 0; #ifdef Q_WS_WIN - qt_widget_private(w)->winSetupGestures(); + qt_widget_private(w)->winSetupGestures(); #endif - } - break; - case QEvent::ParentChange: - if (QWidget *w = qobject_cast<QWidget*>(parent())) { - QApplicationPrivate::instance()->widgetGestures[w].pan = this; + } + + if (newGestureTarget && newGestureTarget->isWidgetType()) { + QWidget *w = static_cast<QWidget*>(newGestureTarget); + QApplicationPrivate::instance()->widgetGestures[w].pan = q; #ifdef Q_WS_WIN - qt_widget_private(w)->winSetupGestures(); + qt_widget_private(w)->winSetupGestures(); #endif - } - break; - default: - break; } + QGesturePrivate::setupGestureTarget(newGestureTarget); +} +/*! \internal */ +bool QPanGesture::event(QEvent *event) +{ #if defined(Q_OS_MAC) && !defined(QT_MAC_USE_COCOA) Q_D(QPanGesture); if (event->type() == QEvent::Timer) { @@ -179,27 +172,29 @@ bool QPanGesture::filterEvent(QEvent *event) d->lastOffset = d->totalOffset = QSize(); } else if (event->type() == QEvent::TouchEnd) { if (state() != Qt::NoGesture) { - if (!ev->touchPoints().isEmpty()) { - QTouchEvent::TouchPoint p = ev->touchPoints().at(0); - const QPoint pos = p.pos().toPoint(); - const QPoint lastPos = p.lastPos().toPoint(); - const QPoint startPos = p.startPos().toPoint(); - d->lastOffset = QSize(pos.x() - lastPos.x(), pos.y() - lastPos.y()); - d->totalOffset = QSize(pos.x() - startPos.x(), pos.y() - startPos.y()); + if (ev->touchPoints().size() == 2) { + QTouchEvent::TouchPoint p1 = ev->touchPoints().at(0); + QTouchEvent::TouchPoint p2 = ev->touchPoints().at(1); + d->lastOffset = + QSize(p1.pos().x() - p1.lastPos().x() + p2.pos().x() - p2.lastPos().x(), + p1.pos().y() - p1.lastPos().y() + p2.pos().y() - p2.lastPos().y()) / 2; + d->totalOffset += d->lastOffset; } updateState(Qt::GestureFinished); } reset(); } else if (event->type() == QEvent::TouchUpdate) { - QTouchEvent::TouchPoint p = ev->touchPoints().at(0); - const QPoint pos = p.pos().toPoint(); - const QPoint lastPos = p.lastPos().toPoint(); - const QPoint startPos = p.startPos().toPoint(); - d->lastOffset = QSize(pos.x() - lastPos.x(), pos.y() - lastPos.y()); - d->totalOffset = QSize(pos.x() - startPos.x(), pos.y() - startPos.y()); - if (d->totalOffset.width() > 10 || d->totalOffset.height() > 10 || - d->totalOffset.width() < -10 || d->totalOffset.height() < -10) { - updateState(Qt::GestureUpdated); + if (ev->touchPoints().size() == 2) { + QTouchEvent::TouchPoint p1 = ev->touchPoints().at(0); + QTouchEvent::TouchPoint p2 = ev->touchPoints().at(1); + d->lastOffset = + QSize(p1.pos().x() - p1.lastPos().x() + p2.pos().x() - p2.lastPos().x(), + p1.pos().y() - p1.lastPos().y() + p2.pos().y() - p2.lastPos().y()) / 2; + d->totalOffset += d->lastOffset; + if (d->totalOffset.width() > 10 || d->totalOffset.height() > 10 || + d->totalOffset.width() < -10 || d->totalOffset.height() < -10) { + updateState(Qt::GestureUpdated); + } } } #ifdef Q_OS_MAC @@ -287,41 +282,35 @@ QSize QPanGesture::lastOffset() const On some platform like Windows it's necessary to provide a non-null widget as \a parent to get native gesture support. */ -QPinchGesture::QPinchGesture(QWidget *parent) - : QGesture(*new QPinchGesturePrivate, parent) +QPinchGesture::QPinchGesture(QWidget *gestureTarget, QObject *parent) + : QGesture(*new QPinchGesturePrivate, gestureTarget, parent) { - if (parent) { - QApplicationPrivate *qAppPriv = QApplicationPrivate::instance(); - qAppPriv->widgetGestures[parent].pinch = this; -#ifdef Q_WS_WIN - qt_widget_private(parent)->winSetupGestures(); -#endif - } } -/*! \internal */ -bool QPinchGesture::event(QEvent *event) +void QPinchGesturePrivate::setupGestureTarget(QObject *newGestureTarget) { - switch (event->type()) { - case QEvent::ParentAboutToChange: - if (QWidget *w = qobject_cast<QWidget*>(parent())) { - QApplicationPrivate::instance()->widgetGestures[w].pinch = 0; + Q_Q(QPinchGesture); + if (gestureTarget && gestureTarget->isWidgetType()) { + QWidget *w = static_cast<QWidget*>(gestureTarget.data()); + QApplicationPrivate::instance()->widgetGestures[w].pinch = 0; #ifdef Q_WS_WIN - qt_widget_private(w)->winSetupGestures(); + qt_widget_private(w)->winSetupGestures(); #endif - } - break; - case QEvent::ParentChange: - if (QWidget *w = qobject_cast<QWidget*>(parent())) { - QApplicationPrivate::instance()->widgetGestures[w].pinch = this; + } + + if (newGestureTarget && newGestureTarget->isWidgetType()) { + QWidget *w = static_cast<QWidget*>(newGestureTarget); + QApplicationPrivate::instance()->widgetGestures[w].pinch = q; #ifdef Q_WS_WIN - qt_widget_private(w)->winSetupGestures(); + qt_widget_private(w)->winSetupGestures(); #endif - } - break; - default: - break; } + QGesturePrivate::setupGestureTarget(newGestureTarget); +} + +/*! \internal */ +bool QPinchGesture::event(QEvent *event) +{ return QObject::event(event); } @@ -399,6 +388,7 @@ bool QPinchGesture::eventFilter(QObject *receiver, QEvent *event) return QGesture::eventFilter(receiver, event); } + /*! \internal */ bool QPinchGesture::filterEvent(QEvent *event) { diff --git a/src/gui/kernel/qstandardgestures.h b/src/gui/kernel/qstandardgestures.h index 8b5421b..0eb9d92 100644 --- a/src/gui/kernel/qstandardgestures.h +++ b/src/gui/kernel/qstandardgestures.h @@ -63,7 +63,7 @@ class Q_GUI_EXPORT QPanGesture : public QGesture Q_PROPERTY(QSize lastOffset READ lastOffset) public: - QPanGesture(QWidget *parent); + QPanGesture(QWidget *gestureTarget, QObject *parent = 0); bool filterEvent(QEvent *event); @@ -97,7 +97,7 @@ class Q_GUI_EXPORT QPinchGesture : public QGesture Q_PROPERTY(QPoint centerPoint READ centerPoint) public: - QPinchGesture(QWidget *parent); + QPinchGesture(QWidget *gestureTarget, QObject *parent = 0); bool filterEvent(QEvent *event); void reset(); diff --git a/src/gui/kernel/qstandardgestures_p.h b/src/gui/kernel/qstandardgestures_p.h index c52d16b..5fbcc5d 100644 --- a/src/gui/kernel/qstandardgestures_p.h +++ b/src/gui/kernel/qstandardgestures_p.h @@ -76,6 +76,8 @@ public: #endif } + void setupGestureTarget(QObject *o); + QSize totalOffset; QSize lastOffset; QPoint lastPosition; @@ -98,6 +100,9 @@ public: #endif { } + + void setupGestureTarget(QObject *o); + qreal scaleFactor; qreal lastScaleFactor; qreal rotationAngle; diff --git a/src/gui/kernel/qwidget_win.cpp b/src/gui/kernel/qwidget_win.cpp index 3d618fe..4fc37b1 100644 --- a/src/gui/kernel/qwidget_win.cpp +++ b/src/gui/kernel/qwidget_win.cpp @@ -2070,11 +2070,21 @@ void QWidgetPrivate::winSetupGestures() bool needh = false; bool needv = false; bool singleFingerPanEnabled = false; - QStandardGestures gestures = qAppPriv->widgetGestures[q]; + QApplicationPrivate::WidgetStandardGesturesMap::const_iterator it = + qAppPriv->widgetGestures.find(q); + if (it == qAppPriv->widgetGestures.end()) + return; + const QStandardGestures &gestures = it.value(); WId winid = 0; if (QAbstractScrollArea *asa = qobject_cast<QAbstractScrollArea*>(q)) { - winid = asa->viewport()->winId(); + winid = asa->viewport()->internalWinId(); + if (!winid) { + QWidget *nativeParent = asa->viewport()->nativeParentWidget(); + if (!nativeParent) + return; + winid = nativeParent->internalWinId(); + } QScrollBar *hbar = asa->horizontalScrollBar(); QScrollBar *vbar = asa->verticalScrollBar(); Qt::ScrollBarPolicy hbarpolicy = asa->horizontalScrollBarPolicy(); @@ -2085,9 +2095,13 @@ void QWidgetPrivate::winSetupGestures() (vbarpolicy == Qt::ScrollBarAsNeeded && vbar->minimum() < vbar->maximum())); singleFingerPanEnabled = asa->d_func()->singleFingerPanEnabled; } else { - winid = q->winId(); + winid = q->internalWinId(); + if (!winid) { + if (QWidget *nativeParent = q->nativeParentWidget()) + winid = nativeParent->internalWinId(); + } } - if (qAppPriv->SetGestureConfig) { + if (winid && qAppPriv->SetGestureConfig) { GESTURECONFIG gc[3]; memset(gc, 0, sizeof(gc)); gc[0].dwID = GID_PAN; @@ -2116,7 +2130,6 @@ void QWidgetPrivate::winSetupGestures() else gc[2].dwBlock = GC_ROTATE; - Q_ASSERT(winid); qAppPriv->SetGestureConfig(winid, 0, sizeof(gc)/sizeof(gc[0]), gc, sizeof(gc[0])); } } diff --git a/tests/auto/auto.pro b/tests/auto/auto.pro index 772b562..073bb10 100644 --- a/tests/auto/auto.pro +++ b/tests/auto/auto.pro @@ -301,7 +301,10 @@ SUBDIRS += \ qstatusbar \ qstl \ qstring \ - qstringbuilder \ + qstringbuilder1 \ + qstringbuilder2 \ + qstringbuilder3 \ + qstringbuilder4 \ qstringmatcher \ qstringlist \ qstringlistmodel \ diff --git a/tests/auto/qprocess/tst_qprocess.cpp b/tests/auto/qprocess/tst_qprocess.cpp index 368b2a0..9ea5e99 100644 --- a/tests/auto/qprocess/tst_qprocess.cpp +++ b/tests/auto/qprocess/tst_qprocess.cpp @@ -134,6 +134,8 @@ private slots: void exitCodeTest(); void setEnvironment_data(); void setEnvironment(); + void setProcessEnvironment_data(); + void setProcessEnvironment(); void systemEnvironment(); void spaceInName(); void lockupsInStartDetached(); @@ -1872,16 +1874,39 @@ void tst_QProcess::setEnvironment() QCOMPARE(process.readAll(), value.toLocal8Bit()); } +#endif +} + +//----------------------------------------------------------------------------- +void tst_QProcess::setProcessEnvironment_data() +{ + setEnvironment_data(); +} + +void tst_QProcess::setProcessEnvironment() +{ +#if !defined (Q_OS_WINCE) + // there is no concept of system variables on Windows CE as there is no console + + // make sure our environment variables are correct + QVERIFY(qgetenv("tst_QProcess").isEmpty()); + QVERIFY(!qgetenv("PATH").isEmpty()); +#ifdef Q_OS_WIN + QVERIFY(!qgetenv("PROMPT").isEmpty()); +#endif + + QFETCH(QString, name); + QFETCH(QString, value); + QString executable = QDir::currentPath() + "/testProcessEnvironment/testProcessEnvironment"; - // use the hash variant now { QProcess process; - QHash<QString, QString> environment = QProcess::systemEnvironmentHash(); + QProcessEnvironment environment = QProcessEnvironment::systemEnvironment(); if (value.isNull()) environment.remove(name); else environment.insert(name, value); - process.setEnvironmentHash(environment); + process.setProcessEnvironment(environment); process.start(executable, QStringList() << name); QVERIFY(process.waitForFinished()); @@ -1899,12 +1924,12 @@ void tst_QProcess::systemEnvironment() #if defined (Q_OS_WINCE) || defined(Q_OS_SYMBIAN) // there is no concept of system variables on Windows CE as there is no console QVERIFY(QProcess::systemEnvironment().isEmpty()); - QVERIFY(QProcess::systemEnvironmentHash().isEmpty()); + QVERIFY(QProcessEnvironment::systemEnvironment().isEmpty()); #else QVERIFY(!QProcess::systemEnvironment().isEmpty()); - QVERIFY(!QProcess::systemEnvironmentHash().isEmpty()); + QVERIFY(!QProcessEnvironment::systemEnvironment().isEmpty()); - QVERIFY(QProcess::systemEnvironmentHash().contains("PATH")); + QVERIFY(QProcessEnvironment::systemEnvironment().contains("PATH")); QVERIFY(!QProcess::systemEnvironment().filter(QRegExp("^PATH=", Qt::CaseInsensitive)).isEmpty()); #endif } |