summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-xconfigure2
-rw-r--r--doc/src/snippets/qprocess-environment/main.cpp6
-rw-r--r--src/corelib/io/qfile.cpp22
-rw-r--r--src/corelib/io/qfsfileengine_unix.cpp46
-rw-r--r--src/corelib/io/qfsfileengine_win.cpp42
-rw-r--r--src/corelib/io/qprocess.cpp394
-rw-r--r--src/corelib/io/qprocess.h39
-rw-r--r--src/corelib/io/qprocess_p.h19
-rw-r--r--src/corelib/io/qprocess_unix.cpp26
-rw-r--r--src/corelib/io/qprocess_win.cpp19
-rw-r--r--src/corelib/io/qresource.cpp6
-rw-r--r--src/corelib/kernel/qabstractitemmodel.cpp11
-rw-r--r--src/gui/kernel/qapplication_p.h12
-rw-r--r--src/gui/kernel/qapplication_win.cpp128
-rw-r--r--src/gui/kernel/qgesture.cpp37
-rw-r--r--src/gui/kernel/qgesture.h8
-rw-r--r--src/gui/kernel/qgesture_p.h5
-rw-r--r--src/gui/kernel/qstandardgestures.cpp126
-rw-r--r--src/gui/kernel/qstandardgestures.h4
-rw-r--r--src/gui/kernel/qstandardgestures_p.h5
-rw-r--r--src/gui/kernel/qwidget_win.cpp23
-rw-r--r--tests/auto/auto.pro5
-rw-r--r--tests/auto/qprocess/tst_qprocess.cpp37
23 files changed, 737 insertions, 285 deletions
diff --git a/configure b/configure
index 6bd7552..48a0202 100755
--- a/configure
+++ b/configure
@@ -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 &copyName)
{
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
}