diff options
author | Joona Petrell <joona.t.petrell@nokia.com> | 2010-11-30 06:52:46 (GMT) |
---|---|---|
committer | Joona Petrell <joona.t.petrell@nokia.com> | 2010-11-30 06:52:46 (GMT) |
commit | a93a09e3a59563421a3deb76a5b0509c4b1d1cea (patch) | |
tree | 7191d6d24504cfc85a023aa8de4ed14ff9c4a4d1 | |
parent | 3aabc92c72bdd9f7e7bc67dd22dae203033e958a (diff) | |
parent | e42d95d4e9d0dc547c604939f88de95180e74fa0 (diff) | |
download | Qt-a93a09e3a59563421a3deb76a5b0509c4b1d1cea.zip Qt-a93a09e3a59563421a3deb76a5b0509c4b1d1cea.tar.gz Qt-a93a09e3a59563421a3deb76a5b0509c4b1d1cea.tar.bz2 |
Merge branch '4.7' of scm.dev.nokia.troll.no:qt/qt into 4.7
Conflicts:
src/declarative/qml/qdeclarativeengine.cpp
src/declarative/qml/qdeclarativepropertycache.cpp
80 files changed, 1791 insertions, 556 deletions
diff --git a/doc/src/platforms/platform-notes.qdoc b/doc/src/platforms/platform-notes.qdoc index 9c5f3c8..177d3f6 100644 --- a/doc/src/platforms/platform-notes.qdoc +++ b/doc/src/platforms/platform-notes.qdoc @@ -737,18 +737,23 @@ \o \c PowerMgmt if QProcess::kill(...) or QProcess::terminate(...) is called. \row \o QtCore \o \c AllFiles when \l{http://developer.symbian.org/wiki/index.php/Capabilities_%28Symbian_Signed%29/AllFiles_Capability}{accessing specific areas.} + \row \o QtDeclarative + \o \c NetworkServices is automatically added for this module. + \row \o QtNetwork + \o \c NetworkServices is automatically added for this module. \row \o QtNetwork - \o \c NetworkServices is basically always required for this module. \o \c ReadUserData is required to include all the phone's SSL certificates in the system's default CA certificate list (for example those added by the user or stored in the SIM card), without this capability only the CA certs built into the phone are used. \row \o QtMultiMedia \o \c UserEnvironment if QAudioInput is used. + \row \o QtWebkit + \o \c NetworkServices is automatically added for this module. \endtable - Note that some modules rely on other modules. If your application uses - QtXmlPatterns, QtWebkit or QtScript it may still require \c NetworkServices - as these modules rely on QtNetwork to go online. + \note Some modules rely on other modules. E.g. QtWebkit and QtDeclarative + depend on QtNetwork and therefore any application that + depends on these modules is also likely to need \c NetworkServices capability. For more information see the documentation of the individual Qt classes. If a class does not mention Symbian capabilities, it requires none. diff --git a/doc/src/snippets/declarative/keynavigation.qml b/doc/src/snippets/declarative/keynavigation.qml new file mode 100644 index 0000000..e11cdf1 --- /dev/null +++ b/doc/src/snippets/declarative/keynavigation.qml @@ -0,0 +1,84 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** $QT_END_LICENSE$ +** +****************************************************************************/ +//![0] +import QtQuick 1.0 + +Grid { + width: 100; height: 100 + columns: 2 + + Rectangle { + id: topLeft + width: 50; height: 50 + color: focus ? "red" : "lightgray" + focus: true + + KeyNavigation.right: topRight + KeyNavigation.down: bottomLeft + } + + Rectangle { + id: topRight + width: 50; height: 50 + color: focus ? "red" : "lightgray" + + KeyNavigation.left: topLeft + KeyNavigation.down: bottomRight + } + + Rectangle { + id: bottomLeft + width: 50; height: 50 + color: focus ? "red" : "lightgray" + + KeyNavigation.right: bottomRight + KeyNavigation.up: topLeft + } + + Rectangle { + id: bottomRight + width: 50; height: 50 + color: focus ? "red" : "lightgray" + + KeyNavigation.left: bottomLeft + KeyNavigation.up: topRight + } +} +//![0] diff --git a/mkspecs/common/symbian/symbian.conf b/mkspecs/common/symbian/symbian.conf index f8586b0..11907cf 100644 --- a/mkspecs/common/symbian/symbian.conf +++ b/mkspecs/common/symbian/symbian.conf @@ -139,7 +139,11 @@ SYMBIAN_SUPPORTED_LANGUAGES = \ mr mo mn nb pl pt pa ro ru sr \ si sk sl so es sw sv tl ta te \ th bo ti tr tk uk ur vi cy zu \ - nn + nn eu zh gl fa st en_US fr_BE \ + pt_BR en_CA fr_CA el_CY tr_CY \ + en_TW en_HK en_CN en_JP en_TH \ + sv_FI zh_HK es_419 en_ZA fr_CH \ + de_CH it_CH zh_TW # These directories must match what configure uses for QT_INSTALL_PLUGINS and QT_INSTALL_IMPORTS QT_PLUGINS_BASE_DIR = /resource/qt$${QT_LIBINFIX}/plugins diff --git a/mkspecs/features/qt_functions.prf b/mkspecs/features/qt_functions.prf index afc708a..59d49c6 100644 --- a/mkspecs/features/qt_functions.prf +++ b/mkspecs/features/qt_functions.prf @@ -49,16 +49,23 @@ defineTest(qtAddLibrary) { isEqual(LIB_NAME, QtGui) { # Needed for #include <QtGui> because qs60mainapplication.h includes aknapp.h INCLUDEPATH *= $$MW_LAYER_SYSTEMINCLUDE - } - isEqual(LIB_NAME, QtWebKit) { + } else:isEqual(LIB_NAME, QtWebKit) { # Needed for because relative inclusion problem in toolchain INCLUDEPATH *= $$QMAKE_INCDIR_QT/QtXmlPatterns INCLUDEPATH *= $$QMAKE_INCDIR_QT/QtNetwork - } - isEqual(LIB_NAME, QtXmlPatterns) { + TARGET.CAPABILITY *= NetworkServices + isEmpty(TARGET.EPOCHEAPSIZE):TARGET.EPOCHEAPSIZE = 0x20000 0x2000000 + } else:isEqual(LIB_NAME, QtXmlPatterns) { # Needed for #include <QtXmlPatterns/QtXmlPatterns> because relative inclusion problem in toolchain INCLUDEPATH *= $$QMAKE_INCDIR_QT/QtNetwork + } else:isEqual(LIB_NAME, QtNetwork) { + TARGET.CAPABILITY *= NetworkServices + } else:isEqual(LIB_NAME, QtDeclarative) { + TARGET.CAPABILITY *= NetworkServices + isEmpty(TARGET.EPOCHEAPSIZE):TARGET.EPOCHEAPSIZE = 0x20000 0x2000000 } + export(TARGET.EPOCHEAPSIZE) + export(TARGET.CAPABILITY) } isEmpty(LINKAGE) { if(!debug_and_release|build_pass):CONFIG(debug, debug|release) { diff --git a/mkspecs/features/symbian/localize_deployment.prf b/mkspecs/features/symbian/localize_deployment.prf index 5f52dbc..26a254b 100644 --- a/mkspecs/features/symbian/localize_deployment.prf +++ b/mkspecs/features/symbian/localize_deployment.prf @@ -3,11 +3,13 @@ SYMBIAN_LANG.sq = 35 #Albanian SYMBIAN_LANG.am = 36 #Amharic SYMBIAN_LANG.ar = 37 #Arabic SYMBIAN_LANG.hy = 38 #Armenian +SYMBIAN_LANG.eu = 102 #Basque SYMBIAN_LANG.bn = 41 #Bengali SYMBIAN_LANG.bg = 42 #Bulgarian SYMBIAN_LANG.my = 43 #Burmese SYMBIAN_LANG.be = 40 #Byelorussian SYMBIAN_LANG.ca = 44 #Catalan +SYMBIAN_LANG.zh = 31 #Chinese SYMBIAN_LANG.hr = 45 #Croatian SYMBIAN_LANG.cs = 25 #Czech SYMBIAN_LANG.da = 07 #Danish @@ -17,6 +19,7 @@ SYMBIAN_LANG.et = 49 #Estonian SYMBIAN_LANG.fi = 09 #Finnish SYMBIAN_LANG.fr = 02 #French SYMBIAN_LANG.gd = 52 #Gaelic +SYMBIAN_LANG.gl = 103 #Galician SYMBIAN_LANG.ka = 53 #Georgian SYMBIAN_LANG.de = 03 #German SYMBIAN_LANG.el = 54 #Greek @@ -42,6 +45,8 @@ SYMBIAN_LANG.mr = 72 #Marathi SYMBIAN_LANG.mo = 73 #Moldavian SYMBIAN_LANG.mn = 74 #Mongolian SYMBIAN_LANG.nb = 08 #Norwegian +SYMBIAN_LANG.nn = 75 #Nynorsk +SYMBIAN_LANG.fa = 50 #Persian SYMBIAN_LANG.pl = 27 #Polish SYMBIAN_LANG.pt = 13 #Portuguese SYMBIAN_LANG.pa = 77 #Punjabi @@ -52,6 +57,7 @@ SYMBIAN_LANG.si = 80 #Singhalese SYMBIAN_LANG.sk = 26 #Slovak SYMBIAN_LANG.sl = 28 #Slovenian SYMBIAN_LANG.so = 81 #Somali +SYMBIAN_LANG.st = 101 #South Sotho/Sesotho SYMBIAN_LANG.es = 04 #Spanish SYMBIAN_LANG.sw = 84 #Swahili SYMBIAN_LANG.sv = 06 #Swedish @@ -68,7 +74,28 @@ SYMBIAN_LANG.ur = 94 #Urdu SYMBIAN_LANG.vi = 96 #Vietnamese SYMBIAN_LANG.cy = 97 #Welsh SYMBIAN_LANG.zu = 98 #Zulu -SYMBIAN_LANG.nn = 75 #Nynorsk + +# Regional dialects +SYMBIAN_LANG.en_US = 10 #American English +SYMBIAN_LANG.fr_BE = 21 #Belgian French +SYMBIAN_LANG.pt_BR = 76 #Brazilian Portuguese +SYMBIAN_LANG.en_CA = 46 #Canadian English +SYMBIAN_LANG.fr_CA = 51 #Canadian French +SYMBIAN_LANG.el_CY = 55 #Cyprus Greek +SYMBIAN_LANG.tr_CY = 91 #Cyprus Turkish +SYMBIAN_LANG.en_TW = 157 #English as appropriate for use in Taiwan +SYMBIAN_LANG.en_HK = 158 #English as appropriate for use in Hong Kong +SYMBIAN_LANG.en_CN = 159 #English as appropriate for use in the Peoples Republic of China +SYMBIAN_LANG.en_JP = 160 #English as appropriate for use in Japan +SYMBIAN_LANG.en_TH = 161 #English as appropriate for use in Thailand +SYMBIAN_LANG.sv_FI = 85 #Finland Swedish +SYMBIAN_LANG.zh_HK = 30 #HongKong Chinese +SYMBIAN_LANG.es_419 = 83 #Latin American Spanish +SYMBIAN_LANG.en_ZA = 48 #South African English +SYMBIAN_LANG.fr_CH = 11 #Swiss French +SYMBIAN_LANG.de_CH = 12 #Swiss German +SYMBIAN_LANG.it_CH = 61 #Swiss Italian +SYMBIAN_LANG.zh_TW = 29 #Taiwan Chinese isEmpty(SYMBIAN_MATCHED_LANGUAGES) { matchSymbianLanguages() diff --git a/qmake/generators/symbian/symmake_sbsv2.cpp b/qmake/generators/symbian/symmake_sbsv2.cpp index c4b51f2..c219f1d 100644 --- a/qmake/generators/symbian/symmake_sbsv2.cpp +++ b/qmake/generators/symbian/symmake_sbsv2.cpp @@ -377,7 +377,6 @@ void SymbianSbsv2MakefileGenerator::writeWrapperMakefile(QFile& wrapperFile, boo t << qmakeCmd << endl; t << endl; - QString currentClause; QString locFileDep = generateLocFileTarget(t, qmakeCmd); t << "debug: " << locFileDep << BLD_INF_FILENAME << endl; diff --git a/src/3rdparty/phonon/phonon/effectwidget.cpp b/src/3rdparty/phonon/phonon/effectwidget.cpp index a2fe50f..edcbe1f 100644 --- a/src/3rdparty/phonon/phonon/effectwidget.cpp +++ b/src/3rdparty/phonon/phonon/effectwidget.cpp @@ -112,7 +112,7 @@ void EffectWidgetPrivate::autogenerateUi() #endif QWidget *control = 0; - switch (para.type()) { + switch (int(para.type())) { case QVariant::String: { QComboBox *cb = new QComboBox(q); diff --git a/src/3rdparty/phonon/phonon/globalconfig.cpp b/src/3rdparty/phonon/phonon/globalconfig.cpp index be751ce..f83ebc4 100644 --- a/src/3rdparty/phonon/phonon/globalconfig.cpp +++ b/src/3rdparty/phonon/phonon/globalconfig.cpp @@ -97,7 +97,7 @@ static void filter(ObjectDescriptionType type, BackendInterface *backendIface, Q static QList<int> sortDevicesByCategoryPriority(const GlobalConfig *config, const QSettingsGroup *backendConfig, ObjectDescriptionType type, Phonon::Category category, QList<int> &defaultList) { - Q_ASSERT(config); + Q_ASSERT(config); Q_UNUSED(config); Q_ASSERT(backendConfig); Q_ASSERT(type == AudioOutputDeviceType || type == AudioCaptureDeviceType); diff --git a/src/3rdparty/phonon/phonon/mediacontroller.cpp b/src/3rdparty/phonon/phonon/mediacontroller.cpp index 59fd5c7..37af3f7 100644 --- a/src/3rdparty/phonon/phonon/mediacontroller.cpp +++ b/src/3rdparty/phonon/phonon/mediacontroller.cpp @@ -76,9 +76,9 @@ MediaController::~MediaController() MediaController::Features MediaController::supportedFeatures() const { if (!d || !d->media) { - return false; + return Features(); } - IFACE false; + IFACE Features(); Features ret; if (iface->hasInterface(AddonInterface::AngleInterface)) { ret |= Angles; diff --git a/src/3rdparty/phonon/phonon/pulsesupport.cpp b/src/3rdparty/phonon/phonon/pulsesupport.cpp index 642843f..b1ba196 100644 --- a/src/3rdparty/phonon/phonon/pulsesupport.cpp +++ b/src/3rdparty/phonon/phonon/pulsesupport.cpp @@ -56,7 +56,7 @@ static int debugLevel() { static int level = -1; if (level < 1) { level = 0; - QString pulseenv = qgetenv("PHONON_PULSEAUDIO_DEBUG"); + QByteArray pulseenv = qgetenv("PHONON_PULSEAUDIO_DEBUG"); int l = pulseenv.toInt(); if (l > 0) level = (l > 2 ? 2 : l); @@ -71,18 +71,18 @@ static void logMessage(const QString &message, int priority, QObject *obj) QString output; if (obj) { // Strip away namespace from className - QString className(obj->metaObject()->className()); + QByteArray className(obj->metaObject()->className()); int nameLength = className.length() - className.lastIndexOf(':') - 1; className = className.right(nameLength); output.sprintf("%s %s (%s %p)", message.toLatin1().constData(), obj->objectName().toLatin1().constData(), - className.toLatin1().constData(), obj); + className.constData(), obj); } else { output = message; } if (priority <= debugLevel()) { - qDebug() << QString("PulseSupport(%1): %2").arg(priority).arg(output); + qDebug() << QString::fromLatin1("PulseSupport(%1): %2").arg(priority).arg(output); } } } @@ -96,7 +96,7 @@ class AudioDevice : pulseName(name), pulseIndex(index) { properties["name"] = desc; - properties["description"] = ""; // We don't have descriptions (well we do, but we use them as the name!) + properties["description"] = QLatin1String(""); // We don't have descriptions (well we do, but we use them as the name!) properties["icon"] = icon; properties["available"] = (index != PA_INVALID_INDEX); properties["isAdvanced"] = false; // Nothing is advanced! @@ -158,8 +158,8 @@ static void createGenericDevices() s_outputDevices.clear(); s_outputDevicePriorities.clear(); index = s_deviceIndexCounter++; - s_outputDeviceIndexes.insert("sink:default", index); - s_outputDevices.insert(index, AudioDevice("sink:default", QObject::tr("PulseAudio Sound Server").toUtf8(), "audio-backend-pulseaudio", 0)); + s_outputDeviceIndexes.insert(QLatin1String("sink:default"), index); + s_outputDevices.insert(index, AudioDevice(QLatin1String("sink:default"), QObject::tr("PulseAudio Sound Server"), QLatin1String("audio-backend-pulseaudio"), 0)); for (int i = Phonon::NoCategory; i <= Phonon::LastCategory; ++i) { Phonon::Category cat = static_cast<Phonon::Category>(i); s_outputDevicePriorities[cat].insert(0, index); @@ -169,8 +169,8 @@ static void createGenericDevices() s_captureDevices.clear(); s_captureDevicePriorities.clear(); index = s_deviceIndexCounter++; - s_captureDeviceIndexes.insert("source:default", index); - s_captureDevices.insert(index, AudioDevice("source:default", QObject::tr("PulseAudio Sound Server").toUtf8(), "audio-backend-pulseaudio", 0)); + s_captureDeviceIndexes.insert(QLatin1String("source:default"), index); + s_captureDevices.insert(index, AudioDevice(QLatin1String("source:default"), QObject::tr("PulseAudio Sound Server"), QLatin1String("audio-backend-pulseaudio"), 0)); for (int i = Phonon::NoCategory; i <= Phonon::LastCategory; ++i) { Phonon::Category cat = static_cast<Phonon::Category>(i); s_captureDevicePriorities[cat].insert(0, index); @@ -397,7 +397,7 @@ void sink_input_cb(pa_context *c, const pa_sink_input_info *i, int eol, void *us if (pa_context_errno(c) == PA_ERR_NOENTITY) return; - logMessage(QString("Sink input callback failure")); + logMessage(QLatin1String("Sink input callback failure")); return; } @@ -409,8 +409,8 @@ void sink_input_cb(pa_context *c, const pa_sink_input_info *i, int eol, void *us // loop through (*i) and extract phonon->streamindex... const char *t; if ((t = pa_proplist_gets(i->proplist, "phonon.streamid"))) { - logMessage(QString("Found PulseAudio stream index %1 for Phonon Output Stream %2").arg(i->index).arg(t)); - s_outputStreamIndexMap[QString(t)] = i->index; + logMessage(QString::fromLatin1("Found PulseAudio stream index %1 for Phonon Output Stream %2").arg(i->index).arg(QLatin1String(t))); + s_outputStreamIndexMap[QLatin1String(t)] = i->index; // Find the sink's phonon index and notify whoever cares... if (PA_INVALID_INDEX != i->sink) { @@ -426,8 +426,8 @@ void sink_input_cb(pa_context *c, const pa_sink_input_info *i, int eol, void *us } if (found) { // OK so we just emit our signal - logMessage(QString("Letting the rest of phonon know about this")); - s_instance->emitUsingDevice(QString(t), device); + logMessage(QLatin1String("Letting the rest of phonon know about this")); + s_instance->emitUsingDevice(QLatin1String(t), device); } } } @@ -441,7 +441,7 @@ void source_output_cb(pa_context *c, const pa_source_output_info *i, int eol, vo if (pa_context_errno(c) == PA_ERR_NOENTITY) return; - logMessage(QString("Source output callback failure")); + logMessage(QLatin1String("Source output callback failure")); return; } @@ -453,8 +453,8 @@ void source_output_cb(pa_context *c, const pa_source_output_info *i, int eol, vo // loop through (*i) and extract phonon->streamindex... const char *t; if ((t = pa_proplist_gets(i->proplist, "phonon.streamid"))) { - logMessage(QString("Found PulseAudio stream index %1 for Phonon Capture Stream %2").arg(i->index).arg(t)); - s_captureStreamIndexMap[QString(t)] = i->index; + logMessage(QString::fromLatin1("Found PulseAudio stream index %1 for Phonon Capture Stream %2").arg(i->index).arg(QLatin1String(t))); + s_captureStreamIndexMap[QLatin1String(t)] = i->index; // Find the source's phonon index and notify whoever cares... if (PA_INVALID_INDEX != i->source) { @@ -470,8 +470,8 @@ void source_output_cb(pa_context *c, const pa_source_output_info *i, int eol, vo } if (found) { // OK so we just emit our signal - logMessage(QString("Letting the rest of phonon know about this")); - s_instance->emitUsingDevice(QString(t), device); + logMessage(QLatin1String("Letting the rest of phonon know about this")); + s_instance->emitUsingDevice(QLatin1String(t), device); } } } @@ -486,17 +486,17 @@ static void subscribe_cb(pa_context *c, pa_subscription_event_type_t t, uint32_t QString phononid = s_outputStreamIndexMap.key(index); if (!phononid.isEmpty()) { if (s_outputStreamIndexMap.contains(phononid)) { - logMessage(QString("Phonon Output Stream %1 is gone at the PA end. Marking it as invalid in our cache as we may reuse it.").arg(phononid)); + logMessage(QString::fromLatin1("Phonon Output Stream %1 is gone at the PA end. Marking it as invalid in our cache as we may reuse it.").arg(phononid)); s_outputStreamIndexMap[phononid] = PA_INVALID_INDEX; } else { - logMessage(QString("Removing Phonon Output Stream %1 (it's gone!)").arg(phononid)); + logMessage(QString::fromLatin1("Removing Phonon Output Stream %1 (it's gone!)").arg(phononid)); s_outputStreamIndexMap.remove(phononid); } } } else { pa_operation *o; if (!(o = pa_context_get_sink_input_info(c, index, sink_input_cb, NULL))) { - logMessage(QString("pa_context_get_sink_input_info() failed")); + logMessage(QLatin1String("pa_context_get_sink_input_info() failed")); return; } pa_operation_unref(o); @@ -508,17 +508,17 @@ static void subscribe_cb(pa_context *c, pa_subscription_event_type_t t, uint32_t QString phononid = s_captureStreamIndexMap.key(index); if (!phononid.isEmpty()) { if (s_captureStreamIndexMap.contains(phononid)) { - logMessage(QString("Phonon Capture Stream %1 is gone at the PA end. Marking it as invalid in our cache as we may reuse it.").arg(phononid)); + logMessage(QString::fromLatin1("Phonon Capture Stream %1 is gone at the PA end. Marking it as invalid in our cache as we may reuse it.").arg(phononid)); s_captureStreamIndexMap[phononid] = PA_INVALID_INDEX; } else { - logMessage(QString("Removing Phonon Capture Stream %1 (it's gone!)").arg(phononid)); + logMessage(QString::fromLatin1("Removing Phonon Capture Stream %1 (it's gone!)").arg(phononid)); s_captureStreamIndexMap.remove(phononid); } } } else { pa_operation *o; if (!(o = pa_context_get_source_output_info(c, index, source_output_cb, NULL))) { - logMessage(QString("pa_context_get_sink_input_info() failed")); + logMessage(QLatin1String("pa_context_get_sink_input_info() failed")); return; } pa_operation_unref(o); @@ -528,29 +528,27 @@ static void subscribe_cb(pa_context *c, pa_subscription_event_type_t t, uint32_t } -static const char* statename(pa_context_state_t state) +static QString statename(pa_context_state_t state) { switch (state) { - case PA_CONTEXT_UNCONNECTED: return "Unconnected"; - case PA_CONTEXT_CONNECTING: return "Connecting"; - case PA_CONTEXT_AUTHORIZING: return "Authorizing"; - case PA_CONTEXT_SETTING_NAME: return "Setting Name"; - case PA_CONTEXT_READY: return "Ready"; - case PA_CONTEXT_FAILED: return "Failed"; - case PA_CONTEXT_TERMINATED: return "Terminated"; + case PA_CONTEXT_UNCONNECTED: return QLatin1String("Unconnected"); + case PA_CONTEXT_CONNECTING: return QLatin1String("Connecting"); + case PA_CONTEXT_AUTHORIZING: return QLatin1String("Authorizing"); + case PA_CONTEXT_SETTING_NAME: return QLatin1String("Setting Name"); + case PA_CONTEXT_READY: return QLatin1String("Ready"); + case PA_CONTEXT_FAILED: return QLatin1String("Failed"); + case PA_CONTEXT_TERMINATED: return QLatin1String("Terminated"); } - static QString unknown; - unknown = QString("Unknown state: %0").arg(state); - return unknown.toAscii().constData(); + return QString::fromLatin1("Unknown state: %0").arg(state); } static void context_state_callback(pa_context *c, void *) { Q_ASSERT(c); - logMessage(QString("context_state_callback %1").arg(statename(pa_context_get_state(c)))); + logMessage(QString::fromLatin1("context_state_callback %1").arg(statename(pa_context_get_state(c)))); pa_context_state_t state = pa_context_get_state(c); if (state == PA_CONTEXT_READY) { // We've connected to PA, so it is active @@ -566,7 +564,7 @@ static void context_state_callback(pa_context *c, void *) if (!(o = pa_context_subscribe(c, (pa_subscription_mask_t) (PA_SUBSCRIPTION_MASK_SINK_INPUT| PA_SUBSCRIPTION_MASK_SOURCE_OUTPUT), NULL, NULL))) { - logMessage(QString("pa_context_subscribe() failed")); + logMessage(QLatin1String("pa_context_subscribe() failed")); return; } pa_operation_unref(o); @@ -639,27 +637,27 @@ PulseSupport::PulseSupport() { #ifdef HAVE_PULSEAUDIO // Initialise our map (is there a better way to do this?) - s_roleCategoryMap["none"] = Phonon::NoCategory; - s_roleCategoryMap["video"] = Phonon::VideoCategory; - s_roleCategoryMap["music"] = Phonon::MusicCategory; - s_roleCategoryMap["game"] = Phonon::GameCategory; - s_roleCategoryMap["event"] = Phonon::NotificationCategory; - s_roleCategoryMap["phone"] = Phonon::CommunicationCategory; - //s_roleCategoryMap["animation"]; // No Mapping - //s_roleCategoryMap["production"]; // No Mapping - s_roleCategoryMap["a11y"] = Phonon::AccessibilityCategory; + s_roleCategoryMap[QLatin1String("none")] = Phonon::NoCategory; + s_roleCategoryMap[QLatin1String("video")] = Phonon::VideoCategory; + s_roleCategoryMap[QLatin1String("music")] = Phonon::MusicCategory; + s_roleCategoryMap[QLatin1String("game")] = Phonon::GameCategory; + s_roleCategoryMap[QLatin1String("event")] = Phonon::NotificationCategory; + s_roleCategoryMap[QLatin1String("phone")] = Phonon::CommunicationCategory; + //s_roleCategoryMap[QLatin1String("animation")]; // No Mapping + //s_roleCategoryMap[QLatin1String("production")]; // No Mapping + s_roleCategoryMap[QLatin1String("a11y")] = Phonon::AccessibilityCategory; // To allow for easy debugging, give an easy way to disable this pulseaudio check - QString pulseenv = qgetenv("PHONON_PULSEAUDIO_DISABLE"); + QByteArray pulseenv = qgetenv("PHONON_PULSEAUDIO_DISABLE"); if (pulseenv.toInt()) { - logMessage("PulseAudio support disabled: PHONON_PULSEAUDIO_DISABLE is set"); + logMessage(QLatin1String("PulseAudio support disabled: PHONON_PULSEAUDIO_DISABLE is set")); return; } // We require a glib event loop - if (QLatin1String(QAbstractEventDispatcher::instance()->metaObject()->className()) - != "QGuiEventDispatcherGlib") { - logMessage("Disabling PulseAudio integration for lack of GLib event loop."); + if (strcmp(QAbstractEventDispatcher::instance()->metaObject()->className(), + "QGuiEventDispatcherGlib") != 0) { + logMessage(QLatin1String("Disabling PulseAudio integration for lack of GLib event loop.")); return; } @@ -667,21 +665,21 @@ PulseSupport::PulseSupport() // use a fully async integrated mainloop method to connect and get proper support. pa_mainloop *p_test_mainloop; if (!(p_test_mainloop = pa_mainloop_new())) { - logMessage("PulseAudio support disabled: Unable to create mainloop"); + logMessage(QLatin1String("PulseAudio support disabled: Unable to create mainloop")); return; } pa_context *p_test_context; if (!(p_test_context = pa_context_new(pa_mainloop_get_api(p_test_mainloop), "libphonon-probe"))) { - logMessage("PulseAudio support disabled: Unable to create context"); + logMessage(QLatin1String("PulseAudio support disabled: Unable to create context")); pa_mainloop_free(p_test_mainloop); return; } - logMessage("Probing for PulseAudio..."); + logMessage(QLatin1String("Probing for PulseAudio...")); // (cg) Convert to PA_CONTEXT_NOFLAGS when PulseAudio 0.9.19 is required if (pa_context_connect(p_test_context, NULL, static_cast<pa_context_flags_t>(0), NULL) < 0) { - logMessage(QString("PulseAudio support disabled: %1").arg(pa_strerror(pa_context_errno(p_test_context)))); + logMessage(QString::fromLatin1("PulseAudio support disabled: %1").arg(QString::fromLocal8Bit(pa_strerror(pa_context_errno(p_test_context))))); pa_context_disconnect(p_test_context); pa_context_unref(p_test_context); pa_mainloop_free(p_test_mainloop); @@ -693,7 +691,7 @@ PulseSupport::PulseSupport() pa_mainloop_iterate(p_test_mainloop, 1, NULL); if (!PA_CONTEXT_IS_GOOD(pa_context_get_state(p_test_context))) { - logMessage("PulseAudio probe complete."); + logMessage(QLatin1String("PulseAudio probe complete.")); break; } } @@ -702,12 +700,12 @@ PulseSupport::PulseSupport() pa_mainloop_free(p_test_mainloop); if (!s_pulseActive) { - logMessage("PulseAudio support is not available."); + logMessage(QLatin1String("PulseAudio support is not available.")); return; } // If we're still here, PA is available. - logMessage("PulseAudio support enabled"); + logMessage(QLatin1String("PulseAudio support enabled")); // Now we connect for real using a proper main loop that we can forget // all about processing. @@ -856,7 +854,7 @@ static void setDevicePriority(Category category, QStringList list) if (role.isEmpty()) return; - logMessage(QString("Reindexing %1: %2").arg(role).arg(list.join(", "))); + logMessage(QString::fromLatin1("Reindexing %1: %2").arg(role).arg(list.join(QLatin1String(", ")))); char **devices; devices = pa_xnew(char *, list.size()+1); @@ -926,7 +924,7 @@ void PulseSupport::setStreamPropList(Category category, QString streamUuid) if (role.isEmpty()) return; - logMessage(QString("Setting role to %1 for streamindex %2").arg(role).arg(streamUuid)); + logMessage(QString::fromLatin1("Setting role to %1 for streamindex %2").arg(role).arg(streamUuid)); setenv("PULSE_PROP_media.role", role.toLatin1().constData(), 1); setenv("PULSE_PROP_phonon.streamid", streamUuid.toLatin1().constData(), 1); #endif @@ -952,30 +950,30 @@ bool PulseSupport::setOutputDevice(QString streamUuid, int device) { return true; if (!s_outputDevices.contains(device)) { - logMessage(QString("Attempting to set Output Device for invalid device id %1.").arg(device)); + logMessage(QString::fromLatin1("Attempting to set Output Device for invalid device id %1.").arg(device)); return false; } const QVariant var = s_outputDevices[device].properties["name"]; - logMessage(QString("Attempting to set Output Device to '%1' for Output Stream %2").arg(var.toString()).arg(streamUuid)); + logMessage(QString::fromLatin1("Attempting to set Output Device to '%1' for Output Stream %2").arg(var.toString()).arg(streamUuid)); // Attempt to look up the pulse stream index. if (s_outputStreamIndexMap.contains(streamUuid) && s_outputStreamIndexMap[streamUuid] != PA_INVALID_INDEX) { - logMessage(QString("... Found in map. Moving now")); + logMessage(QLatin1String("... Found in map. Moving now")); uint32_t pulse_device_index = s_outputDevices[device].pulseIndex; uint32_t pulse_stream_index = s_outputStreamIndexMap[streamUuid]; - logMessage(QString("Moving Pulse Sink Input %1 to '%2' (Pulse Sink %3)").arg(pulse_stream_index).arg(var.toString()).arg(pulse_device_index)); + logMessage(QString::fromLatin1("Moving Pulse Sink Input %1 to '%2' (Pulse Sink %3)").arg(pulse_stream_index).arg(var.toString()).arg(pulse_device_index)); /// @todo Find a way to move the stream without saving it... We don't want to pollute the stream restore db. pa_operation* o; if (!(o = pa_context_move_sink_input_by_index(s_context, pulse_stream_index, pulse_device_index, NULL, NULL))) { - logMessage(QString("pa_context_move_sink_input_by_index() failed")); + logMessage(QLatin1String("pa_context_move_sink_input_by_index() failed")); return false; } pa_operation_unref(o); } else { - logMessage(QString("... Not found in map. We will be notified of the device when the stream appears and we can process any moves needed then")); + logMessage(QLatin1String("... Not found in map. We will be notified of the device when the stream appears and we can process any moves needed then")); } return true; #endif @@ -991,30 +989,30 @@ bool PulseSupport::setCaptureDevice(QString streamUuid, int device) { return true; if (!s_captureDevices.contains(device)) { - logMessage(QString("Attempting to set Capture Device for invalid device id %1.").arg(device)); + logMessage(QString::fromLatin1("Attempting to set Capture Device for invalid device id %1.").arg(device)); return false; } const QVariant var = s_captureDevices[device].properties["name"]; - logMessage(QString("Attempting to set Capture Device to '%1' for Capture Stream %2").arg(var.toString()).arg(streamUuid)); + logMessage(QString::fromLatin1("Attempting to set Capture Device to '%1' for Capture Stream %2").arg(var.toString()).arg(streamUuid)); // Attempt to look up the pulse stream index. if (s_captureStreamIndexMap.contains(streamUuid) && s_captureStreamIndexMap[streamUuid] == PA_INVALID_INDEX) { - logMessage(QString("... Found in map. Moving now")); + logMessage(QString::fromLatin1("... Found in map. Moving now")); uint32_t pulse_device_index = s_captureDevices[device].pulseIndex; uint32_t pulse_stream_index = s_captureStreamIndexMap[streamUuid]; - logMessage(QString("Moving Pulse Source Output %1 to '%2' (Pulse Sink %3)").arg(pulse_stream_index).arg(var.toString()).arg(pulse_device_index)); + logMessage(QString::fromLatin1("Moving Pulse Source Output %1 to '%2' (Pulse Sink %3)").arg(pulse_stream_index).arg(var.toString()).arg(pulse_device_index)); /// @todo Find a way to move the stream without saving it... We don't want to pollute the stream restore db. pa_operation* o; if (!(o = pa_context_move_source_output_by_index(s_context, pulse_stream_index, pulse_device_index, NULL, NULL))) { - logMessage(QString("pa_context_move_source_output_by_index() failed")); + logMessage(QString::fromLatin1("pa_context_move_source_output_by_index() failed")); return false; } pa_operation_unref(o); } else { - logMessage(QString("... Not found in map. We will be notified of the device when the stream appears and we can process any moves needed then")); + logMessage(QString::fromLatin1("... Not found in map. We will be notified of the device when the stream appears and we can process any moves needed then")); } return true; #endif @@ -1025,7 +1023,7 @@ void PulseSupport::clearStreamCache(QString streamUuid) { Q_UNUSED(streamUuid); return; #else - logMessage(QString("Clearing stream cache for stream %1").arg(streamUuid)); + logMessage(QString::fromLatin1("Clearing stream cache for stream %1").arg(streamUuid)); s_outputStreamIndexMap.remove(streamUuid); s_captureStreamIndexMap.remove(streamUuid); #endif diff --git a/src/corelib/io/qfilesystemwatcher.cpp b/src/corelib/io/qfilesystemwatcher.cpp index 18c3c9f..1e6dcee 100644 --- a/src/corelib/io/qfilesystemwatcher.cpp +++ b/src/corelib/io/qfilesystemwatcher.cpp @@ -228,8 +228,14 @@ void QPollingFileSystemWatcherEngine::timeout() dit.remove(); emit directoryChanged(path, true); } else if (x.value() != fi) { - x.value() = fi; - emit directoryChanged(path, false); + fi.refresh(); + if (!fi.exists()) { + dit.remove(); + emit directoryChanged(path, true); + } else { + x.value() = fi; + emit directoryChanged(path, false); + } } } diff --git a/src/corelib/io/qfilesystemwatcher_kqueue.cpp b/src/corelib/io/qfilesystemwatcher_kqueue.cpp index 378ad20..3664396 100644 --- a/src/corelib/io/qfilesystemwatcher_kqueue.cpp +++ b/src/corelib/io/qfilesystemwatcher_kqueue.cpp @@ -117,67 +117,77 @@ QStringList QKqueueFileSystemWatcherEngine::addPaths(const QStringList &paths, QStringList *files, QStringList *directories) { - QMutexLocker locker(&mutex); - QStringList p = paths; - QMutableListIterator<QString> it(p); - while (it.hasNext()) { - QString path = it.next(); - int fd; + { + QMutexLocker locker(&mutex); + + QMutableListIterator<QString> it(p); + while (it.hasNext()) { + QString path = it.next(); + int fd; #if defined(O_EVTONLY) - fd = qt_safe_open(QFile::encodeName(path), O_EVTONLY); + fd = qt_safe_open(QFile::encodeName(path), O_EVTONLY); #else - fd = qt_safe_open(QFile::encodeName(path), O_RDONLY); + fd = qt_safe_open(QFile::encodeName(path), O_RDONLY); #endif - if (fd == -1) { - perror("QKqueueFileSystemWatcherEngine::addPaths: open"); - continue; - } + if (fd == -1) { + perror("QKqueueFileSystemWatcherEngine::addPaths: open"); + continue; + } + if (fd >= (int)FD_SETSIZE / 2 && fd < (int)FD_SETSIZE) { + int fddup = fcntl(fd, F_DUPFD, FD_SETSIZE); + if (fddup != -1) { + ::close(fd); + fd = fddup; + } + } + fcntl(fd, F_SETFD, FD_CLOEXEC); - QT_STATBUF st; - if (QT_FSTAT(fd, &st) == -1) { - perror("QKqueueFileSystemWatcherEngine::addPaths: fstat"); - ::close(fd); - continue; - } - int id = (S_ISDIR(st.st_mode)) ? -fd : fd; - if (id < 0) { - if (directories->contains(path)) { + QT_STATBUF st; + if (QT_FSTAT(fd, &st) == -1) { + perror("QKqueueFileSystemWatcherEngine::addPaths: fstat"); ::close(fd); continue; } - } else { - if (files->contains(path)) { + int id = (S_ISDIR(st.st_mode)) ? -fd : fd; + if (id < 0) { + if (directories->contains(path)) { + ::close(fd); + continue; + } + } else { + if (files->contains(path)) { + ::close(fd); + continue; + } + } + + struct kevent kev; + EV_SET(&kev, + fd, + EVFILT_VNODE, + EV_ADD | EV_ENABLE | EV_CLEAR, + NOTE_DELETE | NOTE_WRITE | NOTE_EXTEND | NOTE_ATTRIB | NOTE_RENAME | NOTE_REVOKE, + 0, + 0); + if (kevent(kqfd, &kev, 1, 0, 0, 0) == -1) { + perror("QKqueueFileSystemWatcherEngine::addPaths: kevent"); ::close(fd); continue; } - } - struct kevent kev; - EV_SET(&kev, - fd, - EVFILT_VNODE, - EV_ADD | EV_ENABLE | EV_ONESHOT, - NOTE_DELETE | NOTE_WRITE | NOTE_EXTEND | NOTE_ATTRIB | NOTE_RENAME | NOTE_REVOKE, - 0, - 0); - if (kevent(kqfd, &kev, 1, 0, 0, 0) == -1) { - perror("QKqueueFileSystemWatcherEngine::addPaths: kevent"); - ::close(fd); - continue; - } + it.remove(); + if (id < 0) { + DEBUG() << "QKqueueFileSystemWatcherEngine: added directory path" << path; + directories->append(path); + } else { + DEBUG() << "QKqueueFileSystemWatcherEngine: added file path" << path; + files->append(path); + } - it.remove(); - if (id < 0) { - DEBUG() << "QKqueueFileSystemWatcherEngine: added directory path" << path; - directories->append(path); - } else { - DEBUG() << "QKqueueFileSystemWatcherEngine: added file path" << path; - files->append(path); + pathToID.insert(path, id); + idToPath.insert(id, path); } - - pathToID.insert(path, id); - idToPath.insert(id, path); } if (!isRunning()) @@ -192,43 +202,35 @@ QStringList QKqueueFileSystemWatcherEngine::removePaths(const QStringList &paths QStringList *files, QStringList *directories) { - QMutexLocker locker(&mutex); - + bool isEmpty; QStringList p = paths; - QMutableListIterator<QString> it(p); - while (it.hasNext()) { - QString path = it.next(); - int id = pathToID.take(path); - QString x = idToPath.take(id); - if (x.isEmpty() || x != path) - continue; - - int fd = id < 0 ? -id : id; - struct kevent kev; - EV_SET(&kev, - fd, - EVFILT_VNODE, - EV_DELETE, - NOTE_DELETE | NOTE_WRITE | NOTE_EXTEND | NOTE_ATTRIB | NOTE_RENAME | NOTE_REVOKE, - 0, - 0); - if (kevent(kqfd, &kev, 1, 0, 0, 0) == -1) { - perror("QKqueueFileSystemWatcherEngine::removeWatch: kevent"); - } - ::close(fd); + { + QMutexLocker locker(&mutex); + if (pathToID.isEmpty()) + return p; + + QMutableListIterator<QString> it(p); + while (it.hasNext()) { + QString path = it.next(); + int id = pathToID.take(path); + QString x = idToPath.take(id); + if (x.isEmpty() || x != path) + continue; - it.remove(); - if (id < 0) - directories->removeAll(path); - else - files->removeAll(path); + ::close(id < 0 ? -id : id); + + it.remove(); + if (id < 0) + directories->removeAll(path); + else + files->removeAll(path); + } + isEmpty = pathToID.isEmpty(); } - if (pathToID.isEmpty()) { + if (isEmpty) { stop(); - locker.unlock(); wait(); - locker.relock(); } else { write(kqpipe[1], "@", 1); } @@ -243,19 +245,15 @@ void QKqueueFileSystemWatcherEngine::stop() void QKqueueFileSystemWatcherEngine::run() { - static const struct timespec ZeroTimeout = { 0, 0 }; - forever { + int r; struct kevent kev; DEBUG() << "QKqueueFileSystemWatcherEngine: waiting for kevents..."; - int r = kevent(kqfd, 0, 0, &kev, 1, 0); + EINTR_LOOP(r, kevent(kqfd, 0, 0, &kev, 1, 0)); if (r < 0) { perror("QKqueueFileSystemWatcherEngine: error during kevent wait"); return; - } - - QMutexLocker locker(&mutex); - do { + } else { int fd = kev.ident; DEBUG() << "QKqueueFileSystemWatcherEngine: processing kevent" << kev.ident << kev.filter; @@ -287,6 +285,8 @@ void QKqueueFileSystemWatcherEngine::run() break; } } else { + QMutexLocker locker(&mutex); + int id = fd; QString path = idToPath.value(id); if (path.isEmpty()) { @@ -295,12 +295,12 @@ void QKqueueFileSystemWatcherEngine::run() path = idToPath.value(id); if (path.isEmpty()) { DEBUG() << "QKqueueFileSystemWatcherEngine: received a kevent for a file we're not watching"; - goto process_next_event; + continue; } } if (kev.filter != EVFILT_VNODE) { DEBUG() << "QKqueueFileSystemWatcherEngine: received a kevent with the wrong filter"; - goto process_next_event; + continue; } if ((kev.fflags & (NOTE_DELETE | NOTE_REVOKE | NOTE_RENAME)) != 0) { @@ -315,31 +315,15 @@ void QKqueueFileSystemWatcherEngine::run() else emit fileChanged(path, true); } else { - DEBUG() << path << "changed, re-enabling watch"; + DEBUG() << path << "changed"; if (id < 0) emit directoryChanged(path, false); else emit fileChanged(path, false); - - // renable the watch - EV_SET(&kev, - fd, - EVFILT_VNODE, - EV_ADD | EV_ENABLE | EV_ONESHOT, - NOTE_DELETE | NOTE_WRITE | NOTE_EXTEND | NOTE_ATTRIB | NOTE_RENAME | NOTE_REVOKE, - 0, - 0); - if (kevent(kqfd, &kev, 1, 0, 0, 0) == -1) { - perror("QKqueueFileSystemWatcherEngine::processKqueueEvents: kevent EV_ADD"); - } } } - - // are there any more? -process_next_event: - r = kevent(kqfd, 0, 0, &kev, 1, &ZeroTimeout); - } while (r > 0); + } } } diff --git a/src/corelib/io/qprocess_symbian.cpp b/src/corelib/io/qprocess_symbian.cpp index 003e781..5b283a5 100644 --- a/src/corelib/io/qprocess_symbian.cpp +++ b/src/corelib/io/qprocess_symbian.cpp @@ -1050,6 +1050,7 @@ bool QProcessPrivate::startDetached(const QString &program, const QStringList &a newProc->Resume(); newProc->Close(); + delete newProc; return true; } diff --git a/src/dbus/qdbusconnection_p.h b/src/dbus/qdbusconnection_p.h index 1bd00da..67145b8 100644 --- a/src/dbus/qdbusconnection_p.h +++ b/src/dbus/qdbusconnection_p.h @@ -203,6 +203,8 @@ public: void disconnectRelay(const QString &service, const QString &path, const QString &interface, QDBusAbstractInterface *receiver, const char *signal); + void registerService(const QString &serviceName); + void unregisterService(const QString &serviceName); bool handleMessage(const QDBusMessage &msg); void waitForFinished(QDBusPendingCallPrivate *pcall); @@ -247,9 +249,11 @@ public slots: void socketWrite(int); void objectDestroyed(QObject *o); void relaySignal(QObject *obj, const QMetaObject *, int signalId, const QVariantList &args); - void _q_serviceOwnerChanged(const QString &name, const QString &oldOwner, const QString &newOwner); - void registerService(const QString &serviceName); - void unregisterService(const QString &serviceName); + +private slots: + void serviceOwnerChangedNoLock(const QString &name, const QString &oldOwner, const QString &newOwner); + void registerServiceNoLock(const QString &serviceName); + void unregisterServiceNoLock(const QString &serviceName); signals: void serviceOwnerChanged(const QString &name, const QString &oldOwner, const QString &newOwner); @@ -303,6 +307,9 @@ public: QObject *receiver, const char *signal, int minMIdx, bool buildSignature); static DBusHandlerResult messageFilter(DBusConnection *, DBusMessage *, void *); + static bool checkReplyForDelivery(QDBusConnectionPrivate *target, QObject *object, + int idx, const QList<int> &metaTypes, + const QDBusMessage &msg); static QDBusCallDeliveryEvent *prepareReply(QDBusConnectionPrivate *target, QObject *object, int idx, const QList<int> &metaTypes, const QDBusMessage &msg); diff --git a/src/dbus/qdbusintegrator.cpp b/src/dbus/qdbusintegrator.cpp index a5d8ada..1842e5a 100644 --- a/src/dbus/qdbusintegrator.cpp +++ b/src/dbus/qdbusintegrator.cpp @@ -552,6 +552,9 @@ bool QDBusConnectionPrivate::handleMessage(const QDBusMessage &amsg) (*(*list)[i])(amsg); } + if (!ref) + return false; + switch (amsg.type()) { case QDBusMessage::SignalMessage: handleSignal(amsg); @@ -713,6 +716,8 @@ static int findSlot(const QMetaObject *mo, const QByteArray &name, int flags, return -1; } +static QDBusCallDeliveryEvent * const DIRECT_DELIVERY = (QDBusCallDeliveryEvent *)1; + QDBusCallDeliveryEvent* QDBusConnectionPrivate::prepareReply(QDBusConnectionPrivate *target, QObject *object, int idx, const QList<int> &metaTypes, @@ -736,6 +741,8 @@ QDBusCallDeliveryEvent* QDBusConnectionPrivate::prepareReply(QDBusConnectionPriv // we can deliver // prepare for the call + if (target == object) + return DIRECT_DELIVERY; return new QDBusCallDeliveryEvent(QDBusConnection(target), idx, target, msg, metaTypes); } @@ -750,6 +757,12 @@ void QDBusConnectionPrivate::activateSignal(const QDBusConnectionPrivate::Signal // Slots can optionally have one final parameter that is a QDBusMessage // Slots receive read-only copies of the message (i.e., pass by value or by const-ref) QDBusCallDeliveryEvent *call = prepareReply(this, hook.obj, hook.midx, hook.params, msg); + if (call == DIRECT_DELIVERY) { + // short-circuit delivery + Q_ASSERT(this == hook.obj); + deliverCall(this, 0, msg, hook.params, hook.midx); + return; + } if (call) postEventToThread(ActivateSignalAction, hook.obj, call); } @@ -1207,11 +1220,11 @@ void QDBusConnectionPrivate::relaySignal(QObject *obj, const QMetaObject *mo, in q_dbus_message_unref(msg); } -void QDBusConnectionPrivate::_q_serviceOwnerChanged(const QString &name, - const QString &oldOwner, const QString &newOwner) +void QDBusConnectionPrivate::serviceOwnerChangedNoLock(const QString &name, + const QString &oldOwner, const QString &newOwner) { Q_UNUSED(oldOwner); - QDBusWriteLocker locker(UpdateSignalHookOwnerAction, this); +// QDBusWriteLocker locker(UpdateSignalHookOwnerAction, this); WatchedServicesHash::Iterator it = watchedServices.find(name); if (it == watchedServices.end()) return; @@ -1686,11 +1699,11 @@ void QDBusConnectionPrivate::setConnection(DBusConnection *dbc, const QDBusError hook.obj = this; hook.params << QMetaType::Void << QVariant::String; // both functions take a QString as parameter and return void - hook.midx = staticMetaObject.indexOfSlot("registerService(QString)"); + hook.midx = staticMetaObject.indexOfSlot("registerServiceNoLock(QString)"); Q_ASSERT(hook.midx != -1); signalHooks.insert(QLatin1String("NameAcquired:" DBUS_INTERFACE_DBUS), hook); - hook.midx = staticMetaObject.indexOfSlot("unregisterService(QString)"); + hook.midx = staticMetaObject.indexOfSlot("unregisterServiceNoLock(QString)"); Q_ASSERT(hook.midx != -1); signalHooks.insert(QLatin1String("NameLost:" DBUS_INTERFACE_DBUS), hook); @@ -2081,7 +2094,7 @@ void QDBusConnectionPrivate::connectSignal(const QString &key, const SignalHook // we need to watch for this service changing connectSignal(dbusServiceString(), QString(), dbusInterfaceString(), QLatin1String("NameOwnerChanged"), QStringList() << hook.service, QString(), - this, SLOT(_q_serviceOwnerChanged(QString,QString,QString))); + this, SLOT(serviceOwnerChangedNoLock(QString,QString,QString))); data.owner = getNameOwnerNoCache(hook.service); qDBusDebug() << this << "Watching service" << hook.service << "for owner changes (current owner:" << data.owner << ")"; @@ -2342,12 +2355,22 @@ QDBusConnectionPrivate::findMetaObject(const QString &service, const QString &pa void QDBusConnectionPrivate::registerService(const QString &serviceName) { QDBusWriteLocker locker(RegisterServiceAction, this); + registerServiceNoLock(serviceName); +} + +void QDBusConnectionPrivate::registerServiceNoLock(const QString &serviceName) +{ serviceNames.append(serviceName); } void QDBusConnectionPrivate::unregisterService(const QString &serviceName) { QDBusWriteLocker locker(UnregisterServiceAction, this); + unregisterServiceNoLock(serviceName); +} + +void QDBusConnectionPrivate::unregisterServiceNoLock(const QString &serviceName) +{ serviceNames.removeAll(serviceName); } diff --git a/src/declarative/graphicsitems/qdeclarativeitem.cpp b/src/declarative/graphicsitems/qdeclarativeitem.cpp index e0df751..9d6fe12 100644 --- a/src/declarative/graphicsitems/qdeclarativeitem.cpp +++ b/src/declarative/graphicsitems/qdeclarativeitem.cpp @@ -421,58 +421,28 @@ void QDeclarativeItemKeyFilter::componentComplete() \since 4.7 \brief The KeyNavigation attached property supports key navigation by arrow keys. - It is common in key-based UIs to use arrow keys to navigate - between focused items. The KeyNavigation property provides a - convenient way of specifying which item will gain focus - when an arrow key is pressed. The following example provides - key navigation for a 2x2 grid of items. - - \code - Grid { - columns: 2 - width: 100; height: 100 - Rectangle { - id: item1 - focus: true - width: 50; height: 50 - color: focus ? "red" : "lightgray" - KeyNavigation.right: item2 - KeyNavigation.down: item3 - } - Rectangle { - id: item2 - width: 50; height: 50 - color: focus ? "red" : "lightgray" - KeyNavigation.left: item1 - KeyNavigation.down: item4 - } - Rectangle { - id: item3 - width: 50; height: 50 - color: focus ? "red" : "lightgray" - KeyNavigation.right: item4 - KeyNavigation.up: item1 - } - Rectangle { - id: item4 - width: 50; height: 50 - color: focus ? "red" : "lightgray" - KeyNavigation.left: item3 - KeyNavigation.up: item2 - } - } - \endcode + Key-based user interfaces commonly allow the use of arrow keys to navigate between + focusable items. The KeyNavigation attached property enables this behavior by providing a + convenient way to specify the item that should gain focus when an arrow or tab key is pressed. + + The following example provides key navigation for a 2x2 grid of items: - By default KeyNavigation receives key events after the item it is attached to. - If the item accepts an arrow key event, the KeyNavigation - attached property will not receive an event for that key. Setting the - \l priority property to KeyNavigation.BeforeItem allows handling - of the key events before normal item processing. + \snippet doc/src/snippets/declarative/keynavigation.qml 0 - If an item has been set for a direction and the KeyNavigation - attached property receives the corresponding - key press and release events, the events will be accepted by - KeyNavigation and will not propagate any further. + The top-left item initially receives focus by setting \l {Item::}{focus} to + \c true. When an arrow key is pressed, the focus will move to the + appropriate item, as defined by the value that has been set for + the KeyNavigation \l left, \l right, \l up or \l down properties. + + Note that if a KeyNavigation attached property receives the key press and release + events for a requested arrow or tab key, the event is accepted and does not + propagate any further. + + By default, KeyNavigation receives key events after the item to which it is attached. + If the item accepts the key event, the KeyNavigation attached property will not + receive an event for that key. Setting the \l priority property to + \c KeyNavigation.BeforeItem allows the event to be used for key navigation + before the item, rather than after. \sa {Keys}{Keys attached property} */ @@ -599,7 +569,7 @@ void QDeclarativeKeyNavigationAttached::setBacktab(QDeclarativeItem *i) \list \o KeyNavigation.BeforeItem - process the key events before normal - item key processing. If the event is accepted it will not + item key processing. If the event is used for key navigation, it will be accepted and will not be passed on to the item. \o KeyNavigation.AfterItem (default) - process the key events after normal item key handling. If the item accepts the key event it will not be diff --git a/src/declarative/qml/qdeclarativebinding.cpp b/src/declarative/qml/qdeclarativebinding.cpp index cb6ad8c..a7fbf44 100644 --- a/src/declarative/qml/qdeclarativebinding.cpp +++ b/src/declarative/qml/qdeclarativebinding.cpp @@ -55,6 +55,158 @@ QT_BEGIN_NAMESPACE +QDeclarativeAbstractBinding::QDeclarativeAbstractBinding() +: m_object(0), m_propertyIndex(-1), m_mePtr(0), m_prevBinding(0), m_nextBinding(0) +{ +} + +QDeclarativeAbstractBinding::~QDeclarativeAbstractBinding() +{ + Q_ASSERT(m_prevBinding == 0); + Q_ASSERT(m_mePtr == 0); +} + +/*! +Destroy the binding. Use this instead of calling delete. + +Bindings are free to implement their own memory management, so the delete operator is not +necessarily safe. The default implementation clears the binding, removes it from the object +and calls delete. +*/ +void QDeclarativeAbstractBinding::destroy() +{ + removeFromObject(); + clear(); + + delete this; +} + +/*! +Add this binding to \a object. + +This transfers ownership of the binding to the object, marks the object's property as +being bound. + +However, it does not enable the binding itself or call update() on it. +*/ +void QDeclarativeAbstractBinding::addToObject(QObject *object, int index) +{ + Q_ASSERT(object); + + if (m_object == object && m_propertyIndex == index) + return; + + removeFromObject(); + + Q_ASSERT(!m_prevBinding); + + m_object = object; + m_propertyIndex = index; + + QDeclarativeData *data = QDeclarativeData::get(object, true); + + if (index & 0xFF000000) { + // Value type + + int coreIndex = index & 0xFFFFFF; + + // Find the value type proxy (if there is one) + QDeclarativeValueTypeProxyBinding *proxy = 0; + if (data->hasBindingBit(coreIndex)) { + QDeclarativeAbstractBinding *b = data->bindings; + while (b && b->propertyIndex() != coreIndex) + b = b->m_nextBinding; + Q_ASSERT(b && b->bindingType() == QDeclarativeAbstractBinding::ValueTypeProxy); + proxy = static_cast<QDeclarativeValueTypeProxyBinding *>(b); + } + + if (!proxy) { + proxy = new QDeclarativeValueTypeProxyBinding(object, coreIndex); + proxy->addToObject(object, coreIndex); + } + + m_nextBinding = proxy->m_bindings; + if (m_nextBinding) m_nextBinding->m_prevBinding = &m_nextBinding; + m_prevBinding = &proxy->m_bindings; + proxy->m_bindings = this; + + } else { + m_nextBinding = data->bindings; + if (m_nextBinding) m_nextBinding->m_prevBinding = &m_nextBinding; + m_prevBinding = &data->bindings; + data->bindings = this; + + data->setBindingBit(m_object, index); + } +} + +/*! +Remove the binding from the object. +*/ +void QDeclarativeAbstractBinding::removeFromObject() +{ + if (m_prevBinding) { + int index = propertyIndex(); + + *m_prevBinding = m_nextBinding; + if (m_nextBinding) m_nextBinding->m_prevBinding = m_prevBinding; + m_prevBinding = 0; + m_nextBinding = 0; + + if (index & 0xFF000000) { + // Value type - we don't remove the proxy from the object. It will sit their happily + // doing nothing until it is removed by a write, a binding change or it is reused + // to hold more sub-bindings. + } else if (m_object) { + QDeclarativeData *data = QDeclarativeData::get(m_object, false); + if (data) data->clearBindingBit(index); + } + + m_object = 0; + m_propertyIndex = -1; + } +} + +static void bindingDummyDeleter(QDeclarativeAbstractBinding *) +{ +} + +QDeclarativeAbstractBinding::Pointer QDeclarativeAbstractBinding::weakPointer() +{ + if (m_selfPointer.isNull()) + m_selfPointer = QSharedPointer<QDeclarativeAbstractBinding>(this, bindingDummyDeleter); + + return m_selfPointer.toWeakRef(); +} + +void QDeclarativeAbstractBinding::clear() +{ + if (m_mePtr) { + *m_mePtr = 0; + m_mePtr = 0; + } +} + +QString QDeclarativeAbstractBinding::expression() const +{ + return QLatin1String("<Unknown>"); +} + +QObject *QDeclarativeAbstractBinding::object() const +{ + return m_object; +} + +int QDeclarativeAbstractBinding::propertyIndex() const +{ + return m_propertyIndex; +} + +void QDeclarativeAbstractBinding::setEnabled(bool enabled, QDeclarativePropertyPrivate::WriteFlags flags) +{ + if (enabled) update(flags); +} + void QDeclarativeBindingPrivate::refresh() { Q_Q(QDeclarativeBinding); @@ -255,20 +407,8 @@ void QDeclarativeBinding::setEnabled(bool e, QDeclarativePropertyPrivate::WriteF d->enabled = e; setNotifyOnValueChanged(e); - QDeclarativeAbstractBinding::setEnabled(e, flags); - - if (e) { - addToObject(d->property.object()); + if (e) update(flags); - } else { - removeFromObject(); - } -} - -int QDeclarativeBinding::propertyIndex() -{ - Q_D(QDeclarativeBinding); - return QDeclarativePropertyPrivate::bindingIndex(d->property); } bool QDeclarativeBinding::enabled() const @@ -283,127 +423,6 @@ QString QDeclarativeBinding::expression() const return QDeclarativeExpression::expression(); } -QDeclarativeAbstractBinding::QDeclarativeAbstractBinding() -: m_object(0), m_mePtr(0), m_prevBinding(0), m_nextBinding(0) -{ -} - -QDeclarativeAbstractBinding::~QDeclarativeAbstractBinding() -{ - Q_ASSERT(m_prevBinding == 0); - Q_ASSERT(m_mePtr == 0); -} - -void QDeclarativeAbstractBinding::destroy() -{ - removeFromObject(); - clear(); - - delete this; -} - -void QDeclarativeAbstractBinding::addToObject(QObject *object) -{ - Q_ASSERT(object); - - if (m_object == object) - return; - - int index = propertyIndex(); - - removeFromObject(); - - Q_ASSERT(!m_prevBinding); - - m_object = object; - QDeclarativeData *data = QDeclarativeData::get(object, true); - - if (index & 0xFF000000) { - // Value type - - int coreIndex = index & 0xFFFFFF; - - // Find the value type proxy (if there is one) - QDeclarativeValueTypeProxyBinding *proxy = 0; - if (data->hasBindingBit(coreIndex)) { - QDeclarativeAbstractBinding *b = data->bindings; - while (b && b->propertyIndex() != coreIndex) - b = b->m_nextBinding; - Q_ASSERT(b && b->bindingType() == QDeclarativeAbstractBinding::ValueTypeProxy); - proxy = static_cast<QDeclarativeValueTypeProxyBinding *>(b); - } - - if (!proxy) - proxy = new QDeclarativeValueTypeProxyBinding(object, coreIndex); - proxy->addToObject(object); - - m_nextBinding = proxy->m_bindings; - if (m_nextBinding) m_nextBinding->m_prevBinding = &m_nextBinding; - m_prevBinding = &proxy->m_bindings; - proxy->m_bindings = this; - - } else { - m_nextBinding = data->bindings; - if (m_nextBinding) m_nextBinding->m_prevBinding = &m_nextBinding; - m_prevBinding = &data->bindings; - data->bindings = this; - - data->setBindingBit(m_object, index); - } -} - -void QDeclarativeAbstractBinding::removeFromObject() -{ - if (m_prevBinding) { - int index = propertyIndex(); - - *m_prevBinding = m_nextBinding; - if (m_nextBinding) m_nextBinding->m_prevBinding = m_prevBinding; - m_prevBinding = 0; - m_nextBinding = 0; - - if (index & 0xFF000000) { - // Value type - we don't remove the proxy from the object. It will sit their happily - // doing nothing for ever more. - } else if (m_object) { - QDeclarativeData *data = QDeclarativeData::get(m_object, false); - if (data) data->clearBindingBit(index); - } - - m_object = 0; - } -} - -static void bindingDummyDeleter(QDeclarativeAbstractBinding *) -{ -} - -QDeclarativeAbstractBinding::Pointer QDeclarativeAbstractBinding::weakPointer() -{ - if (m_selfPointer.isNull()) - m_selfPointer = QSharedPointer<QDeclarativeAbstractBinding>(this, bindingDummyDeleter); - - return m_selfPointer.toWeakRef(); -} - -void QDeclarativeAbstractBinding::clear() -{ - if (m_mePtr) { - *m_mePtr = 0; - m_mePtr = 0; - } -} - -QString QDeclarativeAbstractBinding::expression() const -{ - return QLatin1String("<Unknown>"); -} - -void QDeclarativeAbstractBinding::setEnabled(bool e, QDeclarativePropertyPrivate::WriteFlags) -{ - if (e) m_mePtr = 0; -} - QDeclarativeValueTypeProxyBinding::QDeclarativeValueTypeProxyBinding(QObject *o, int index) : m_object(o), m_index(index), m_bindings(0) { @@ -421,16 +440,10 @@ QDeclarativeValueTypeProxyBinding::~QDeclarativeValueTypeProxyBinding() void QDeclarativeValueTypeProxyBinding::setEnabled(bool e, QDeclarativePropertyPrivate::WriteFlags flags) { if (e) { - addToObject(m_object); - QDeclarativeAbstractBinding *bindings = m_bindings; - m_bindings = 0; recursiveEnable(bindings, flags); } else { - removeFromObject(); - QDeclarativeAbstractBinding *bindings = m_bindings; - m_bindings = 0; recursiveDisable(bindings); } } @@ -440,13 +453,7 @@ void QDeclarativeValueTypeProxyBinding::recursiveEnable(QDeclarativeAbstractBind if (!b) return; - QDeclarativeAbstractBinding *next = b->m_nextBinding; - b->m_prevBinding = 0; - b->m_nextBinding = 0; - Q_ASSERT(b->m_mePtr == 0); - b->m_mePtr = &b; - - recursiveEnable(next, flags); + recursiveEnable(b->m_nextBinding, flags); if (b) b->setEnabled(true, flags); @@ -459,19 +466,8 @@ void QDeclarativeValueTypeProxyBinding::recursiveDisable(QDeclarativeAbstractBin recursiveDisable(b->m_nextBinding); - b->setEnabled(false, 0); - - Q_ASSERT(b->m_prevBinding == 0); - Q_ASSERT(b->m_nextBinding == 0); - b->m_nextBinding = m_bindings; - if (b->m_nextBinding) b->m_nextBinding->m_prevBinding = &b->m_nextBinding; - b->m_prevBinding = &m_bindings; - m_bindings = b; -} - -int QDeclarativeValueTypeProxyBinding::propertyIndex() -{ - return m_index; + if (b) + b->setEnabled(false, 0); } void QDeclarativeValueTypeProxyBinding::update(QDeclarativePropertyPrivate::WriteFlags) @@ -488,4 +484,25 @@ QDeclarativeAbstractBinding *QDeclarativeValueTypeProxyBinding::binding(int prop return binding; } +/*! +Removes a collection of bindings, corresponding to the set bits in \a mask. +*/ +void QDeclarativeValueTypeProxyBinding::removeBindings(quint32 mask) +{ + QDeclarativeAbstractBinding *binding = m_bindings; + while (binding) { + if (mask & (1 << (binding->propertyIndex() >> 24))) { + QDeclarativeAbstractBinding *remove = binding; + binding = remove->m_nextBinding; + *remove->m_prevBinding = remove->m_nextBinding; + if (remove->m_nextBinding) remove->m_nextBinding->m_prevBinding = remove->m_prevBinding; + remove->m_prevBinding = 0; + remove->m_nextBinding = 0; + remove->destroy(); + } else { + binding = binding->m_nextBinding; + } + } +} + QT_END_NAMESPACE diff --git a/src/declarative/qml/qdeclarativebinding_p.h b/src/declarative/qml/qdeclarativebinding_p.h index 0b9bde6..7823a3d 100644 --- a/src/declarative/qml/qdeclarativebinding_p.h +++ b/src/declarative/qml/qdeclarativebinding_p.h @@ -78,14 +78,16 @@ public: enum Type { PropertyBinding, ValueTypeProxy }; virtual Type bindingType() const { return PropertyBinding; } + QObject *object() const; + int propertyIndex() const; + void setEnabled(bool e) { setEnabled(e, QDeclarativePropertyPrivate::DontRemoveBinding); } virtual void setEnabled(bool, QDeclarativePropertyPrivate::WriteFlags) = 0; - virtual int propertyIndex() = 0; void update() { update(QDeclarativePropertyPrivate::DontRemoveBinding); } virtual void update(QDeclarativePropertyPrivate::WriteFlags) = 0; - void addToObject(QObject *); + void addToObject(QObject *, int); void removeFromObject(); static Pointer getPointer(QDeclarativeAbstractBinding *p) { return p ? p->weakPointer() : Pointer(); } @@ -98,12 +100,14 @@ private: Pointer weakPointer(); friend class QDeclarativeData; + friend class QDeclarativeComponentPrivate; friend class QDeclarativeValueTypeProxyBinding; friend class QDeclarativePropertyPrivate; friend class QDeclarativeVME; friend class QtSharedPointer::ExternalRefCount<QDeclarativeAbstractBinding>; QObject *m_object; + int m_propertyIndex; QDeclarativeAbstractBinding **m_mePtr; QDeclarativeAbstractBinding **m_prevBinding; QDeclarativeAbstractBinding *m_nextBinding; @@ -118,11 +122,12 @@ public: virtual Type bindingType() const { return ValueTypeProxy; } virtual void setEnabled(bool, QDeclarativePropertyPrivate::WriteFlags); - virtual int propertyIndex(); virtual void update(QDeclarativePropertyPrivate::WriteFlags); QDeclarativeAbstractBinding *binding(int propertyIndex); + void removeBindings(quint32 mask); + protected: ~QDeclarativeValueTypeProxyBinding(); @@ -154,7 +159,6 @@ public: // Inherited from QDeclarativeAbstractBinding virtual void setEnabled(bool, QDeclarativePropertyPrivate::WriteFlags flags); - virtual int propertyIndex(); virtual void update(QDeclarativePropertyPrivate::WriteFlags flags); virtual QString expression() const; diff --git a/src/declarative/qml/qdeclarativecompiledbindings.cpp b/src/declarative/qml/qdeclarativecompiledbindings.cpp index fbe5829..5c295b9 100644 --- a/src/declarative/qml/qdeclarativecompiledbindings.cpp +++ b/src/declarative/qml/qdeclarativecompiledbindings.cpp @@ -187,7 +187,6 @@ public: // Inherited from QDeclarativeAbstractBinding virtual void setEnabled(bool, QDeclarativePropertyPrivate::WriteFlags flags); - virtual int propertyIndex(); virtual void update(QDeclarativePropertyPrivate::WriteFlags flags); virtual void destroy(); @@ -294,14 +293,6 @@ QDeclarativeAbstractBinding *QDeclarativeCompiledBindings::configBinding(int ind void QDeclarativeCompiledBindingsPrivate::Binding::setEnabled(bool e, QDeclarativePropertyPrivate::WriteFlags flags) { - if (e) { - addToObject(target); - } else { - removeFromObject(); - } - - QDeclarativeAbstractBinding::setEnabled(e, flags); - if (enabled != e) { enabled = e; @@ -309,11 +300,6 @@ void QDeclarativeCompiledBindingsPrivate::Binding::setEnabled(bool e, QDeclarati } } -int QDeclarativeCompiledBindingsPrivate::Binding::propertyIndex() -{ - return property & 0xFFFF; -} - void QDeclarativeCompiledBindingsPrivate::Binding::update(QDeclarativePropertyPrivate::WriteFlags flags) { parent->run(this, flags); diff --git a/src/declarative/qml/qdeclarativecompiler.cpp b/src/declarative/qml/qdeclarativecompiler.cpp index 645402e..df428b1 100644 --- a/src/declarative/qml/qdeclarativecompiler.cpp +++ b/src/declarative/qml/qdeclarativecompiler.cpp @@ -946,6 +946,16 @@ void QDeclarativeCompiler::genObject(QDeclarativeParser::Object *obj) QDeclarativePropertyCache::Data::IsVMEFunction, QDeclarativePropertyCache::Data::IsVMESignal); + // Add flag for alias properties + if (!obj->synthdata.isEmpty()) { + const QDeclarativeVMEMetaData *vmeMetaData = + reinterpret_cast<const QDeclarativeVMEMetaData *>(obj->synthdata.constData()); + for (int ii = 0; ii < vmeMetaData->aliasCount; ++ii) { + int index = obj->metaObject()->propertyOffset() + vmeMetaData->propertyCount + ii; + propertyCache->property(index)->flags |= QDeclarativePropertyCache::Data::IsAlias; + } + } + if (obj == unitRoot) { propertyCache->addref(); output->rootPropertyCache = propertyCache; @@ -1003,7 +1013,8 @@ void QDeclarativeCompiler::genObjectBody(QDeclarativeParser::Object *obj) seenDefer = true; continue; } - genValueProperty(prop, obj); + if (!prop->isAlias) + genValueProperty(prop, obj); } if (seenDefer) { QDeclarativeInstruction defer; @@ -1113,25 +1124,56 @@ void QDeclarativeCompiler::genObjectBody(QDeclarativeParser::Object *obj) } foreach(Property *prop, obj->valueTypeProperties) { - QDeclarativeInstruction fetch; - fetch.type = QDeclarativeInstruction::FetchValueType; - fetch.fetchValue.property = prop->index; - fetch.fetchValue.type = prop->type; - fetch.line = prop->location.start.line; + if (!prop->isAlias) + genValueTypeProperty(obj, prop); + } - output->bytecode << fetch; + foreach(Property *prop, obj->valueProperties) { + if (prop->isDeferred) + continue; + if (prop->isAlias) + genValueProperty(prop, obj); + } + + foreach(Property *prop, obj->valueTypeProperties) { + if (prop->isAlias) + genValueTypeProperty(obj, prop); + } +} +void QDeclarativeCompiler::genValueTypeProperty(QDeclarativeParser::Object *obj,QDeclarativeParser::Property *prop) +{ + QDeclarativeInstruction fetch; + fetch.type = QDeclarativeInstruction::FetchValueType; + fetch.fetchValue.property = prop->index; + fetch.fetchValue.type = prop->type; + fetch.fetchValue.bindingSkipList = 0; + fetch.line = prop->location.start.line; + + if (obj->type == -1 || output->types.at(obj->type).component) { + // We only have to do this if this is a composite type. If it is a builtin + // type it can't possibly already have bindings that need to be cleared. foreach(Property *vprop, prop->value->valueProperties) { - genPropertyAssignment(vprop, prop->value, prop); + if (!vprop->values.isEmpty()) { + Q_ASSERT(vprop->index >= 0 && vprop->index < 32); + fetch.fetchValue.bindingSkipList |= (1 << vprop->index); + } } + } - QDeclarativeInstruction pop; - pop.type = QDeclarativeInstruction::PopValueType; - pop.fetchValue.property = prop->index; - pop.fetchValue.type = prop->type; - pop.line = prop->location.start.line; - output->bytecode << pop; + output->bytecode << fetch; + + foreach(Property *vprop, prop->value->valueProperties) { + genPropertyAssignment(vprop, prop->value, prop); } + + QDeclarativeInstruction pop; + pop.type = QDeclarativeInstruction::PopValueType; + pop.fetchValue.property = prop->index; + pop.fetchValue.type = prop->type; + pop.fetchValue.bindingSkipList = 0; + pop.line = prop->location.start.line; + output->bytecode << pop; } void QDeclarativeCompiler::genComponent(QDeclarativeParser::Object *obj) @@ -1440,10 +1482,22 @@ bool QDeclarativeCompiler::buildProperty(QDeclarativeParser::Property *prop, if (p.name()) { prop->type = p.userType(); } - } - if (prop->index != -1) - prop->parent->setBindingBit(prop->index); + // Check if this is an alias + if (prop->index != -1 && + prop->parent && + prop->parent->type != -1 && + output->types.at(prop->parent->type).component) { + + QDeclarativePropertyCache *cache = output->types.at(prop->parent->type).component->rootPropertyCache; + if (cache && cache->property(prop->index) && + cache->property(prop->index)->flags & QDeclarativePropertyCache::Data::IsAlias) + prop->isAlias = true; + } + + if (prop->index != -1 && !prop->values.isEmpty()) + prop->parent->setBindingBit(prop->index); + } if (!prop->isDefault && prop->name == "id" && !ctxt.isSubContext()) { @@ -1778,6 +1832,12 @@ bool QDeclarativeCompiler::buildGroupedProperty(QDeclarativeParser::Property *pr COMPILE_EXCEPTION(prop, tr( "Invalid property assignment: \"%1\" is a read-only property").arg(QString::fromUtf8(prop->name))); } + + if (prop->isAlias) { + foreach (Property *vtProp, prop->value->properties) + vtProp->isAlias = true; + } + COMPILE_CHECK(buildValueTypeProperty(enginePrivate->valueTypes[prop->type], prop->value, obj, ctxt.incr())); obj->addValueTypeProperty(prop); @@ -2423,7 +2483,7 @@ bool QDeclarativeCompiler::buildDynamicMeta(QDeclarativeParser::Object *obj, Dyn if (p.type == Object::DynamicProperty::Alias) { if (mode == ResolveAliases) { ((QDeclarativeVMEMetaData *)dynamicData.data())->aliasCount++; - compileAlias(builder, dynamicData, obj, p); + COMPILE_CHECK(compileAlias(builder, dynamicData, obj, p)); } else { // Need a fake signal so that the metaobject remains consistent across // the resolve and non-resolve alias runs @@ -2694,7 +2754,10 @@ void QDeclarativeCompiler::genBindingAssignment(QDeclarativeParser::Value *bindi } QDeclarativeInstruction store; - store.type = QDeclarativeInstruction::StoreBinding; + if (!prop->isAlias) + store.type = QDeclarativeInstruction::StoreBinding; + else + store.type = QDeclarativeInstruction::StoreBindingOnAlias; store.assignBinding.value = output->indexForByteArray(ref.compiledData); store.assignBinding.context = ref.bindingContext.stack; store.assignBinding.owner = ref.bindingContext.owner; @@ -2769,13 +2832,17 @@ bool QDeclarativeCompiler::completeComponentBuild() expr.expression = binding.expression; expr.imports = unit->imports(); - int index = bindingCompiler.compile(expr, enginePrivate); - if (index != -1) { - binding.dataType = BindingReference::Experimental; - binding.compiledIndex = index; - componentStat.optimizedBindings.append(iter.key()->location); - continue; - } + // ### We don't currently optimize for bindings on alias's - because + // of the solution to QTBUG-13719 + if (!binding.property->isAlias) { + int index = bindingCompiler.compile(expr, enginePrivate); + if (index != -1) { + binding.dataType = BindingReference::Experimental; + binding.compiledIndex = index; + componentStat.optimizedBindings.append(iter.key()->location); + continue; + } + } binding.dataType = BindingReference::QtScript; diff --git a/src/declarative/qml/qdeclarativecompiler_p.h b/src/declarative/qml/qdeclarativecompiler_p.h index 5cd1fd2..7d76ad9 100644 --- a/src/declarative/qml/qdeclarativecompiler_p.h +++ b/src/declarative/qml/qdeclarativecompiler_p.h @@ -252,6 +252,7 @@ private: void genObject(QDeclarativeParser::Object *obj); void genObjectBody(QDeclarativeParser::Object *obj); + void genValueTypeProperty(QDeclarativeParser::Object *obj,QDeclarativeParser::Property *); void genComponent(QDeclarativeParser::Object *obj); void genValueProperty(QDeclarativeParser::Property *prop, QDeclarativeParser::Object *obj); void genListProperty(QDeclarativeParser::Property *prop, QDeclarativeParser::Object *obj); diff --git a/src/declarative/qml/qdeclarativecomponent.cpp b/src/declarative/qml/qdeclarativecomponent.cpp index 2686ce3..63bde0f 100644 --- a/src/declarative/qml/qdeclarativecomponent.cpp +++ b/src/declarative/qml/qdeclarativecomponent.cpp @@ -876,9 +876,12 @@ void QDeclarativeComponentPrivate::complete(QDeclarativeEnginePrivate *enginePri QDeclarativeEnginePrivate::SimpleList<QDeclarativeAbstractBinding> bv = state->bindValues.at(ii); for (int jj = 0; jj < bv.count; ++jj) { - if(bv.at(jj)) + if(bv.at(jj)) { + // XXX akennedy + bv.at(jj)->m_mePtr = 0; bv.at(jj)->setEnabled(true, QDeclarativePropertyPrivate::BypassInterceptor | QDeclarativePropertyPrivate::DontRemoveBinding); + } } QDeclarativeEnginePrivate::clear(bv); } diff --git a/src/declarative/qml/qdeclarativeinstruction.cpp b/src/declarative/qml/qdeclarativeinstruction.cpp index 1767d2f..818c15d 100644 --- a/src/declarative/qml/qdeclarativeinstruction.cpp +++ b/src/declarative/qml/qdeclarativeinstruction.cpp @@ -63,7 +63,7 @@ void QDeclarativeCompiledData::dump(QDeclarativeInstruction *instr, int idx) qWarning().nospace() << idx << "\t\t" << line << "\t" << "INIT\t\t\t" << instr->init.bindingsSize << "\t" << instr->init.parserStatusSize << "\t" << instr->init.contextCache << "\t" << instr->init.compiledBinding; break; case QDeclarativeInstruction::CreateObject: - qWarning().nospace() << idx << "\t\t" << line << "\t" << "CREATE\t\t\t" << instr->create.type << "\t\t\t" << types.at(instr->create.type).className; + qWarning().nospace() << idx << "\t\t" << line << "\t" << "CREATE\t\t\t" << instr->create.type << "\t" << instr->create.bindingBits << "\t\t" << types.at(instr->create.type).className; break; case QDeclarativeInstruction::CreateSimpleObject: qWarning().nospace() << idx << "\t\t" << line << "\t" << "CREATE_SIMPLE\t\t" << instr->createSimple.typeSize; @@ -174,6 +174,9 @@ void QDeclarativeCompiledData::dump(QDeclarativeInstruction *instr, int idx) case QDeclarativeInstruction::StoreBinding: qWarning().nospace() << idx << "\t\t" << line << "\t" << "STORE_BINDING\t" << instr->assignBinding.property << "\t" << instr->assignBinding.value << "\t" << instr->assignBinding.context; break; + case QDeclarativeInstruction::StoreBindingOnAlias: + qWarning().nospace() << idx << "\t\t" << line << "\t" << "STORE_BINDING_ALIAS\t" << instr->assignBinding.property << "\t" << instr->assignBinding.value << "\t" << instr->assignBinding.context; + break; case QDeclarativeInstruction::StoreCompiledBinding: qWarning().nospace() << idx << "\t\t" << line << "\t" << "STORE_COMPILED_BINDING\t" << instr->assignBinding.property << "\t" << instr->assignBinding.value << "\t" << instr->assignBinding.context; break; @@ -203,7 +206,7 @@ void QDeclarativeCompiledData::dump(QDeclarativeInstruction *instr, int idx) qWarning().nospace() << idx << "\t\t" << line << "\t" << "FETCH\t\t\t" << instr->fetch.property; break; case QDeclarativeInstruction::FetchValueType: - qWarning().nospace() << idx << "\t\t" << line << "\t" << "FETCH_VALUE\t\t" << instr->fetchValue.property << "\t" << instr->fetchValue.type; + qWarning().nospace() << idx << "\t\t" << line << "\t" << "FETCH_VALUE\t\t" << instr->fetchValue.property << "\t" << instr->fetchValue.type << "\t" << instr->fetchValue.bindingSkipList; break; case QDeclarativeInstruction::PopFetchedObject: qWarning().nospace() << idx << "\t\t" << line << "\t" << "POP"; diff --git a/src/declarative/qml/qdeclarativeinstruction_p.h b/src/declarative/qml/qdeclarativeinstruction_p.h index f0b032c..94676fc 100644 --- a/src/declarative/qml/qdeclarativeinstruction_p.h +++ b/src/declarative/qml/qdeclarativeinstruction_p.h @@ -132,6 +132,7 @@ public: AssignCustomType, /* assignCustomType */ StoreBinding, /* assignBinding */ + StoreBindingOnAlias, /* assignBinding */ StoreCompiledBinding, /* assignBinding */ StoreValueSource, /* assignValueSource */ StoreValueInterceptor, /* assignValueInterceptor */ @@ -214,6 +215,7 @@ public: struct FetchValueInstruction { int property; int type; + quint32 bindingSkipList; }; struct FetchQmlListInstruction { int property; diff --git a/src/declarative/qml/qdeclarativeparser.cpp b/src/declarative/qml/qdeclarativeparser.cpp index 8d00ef8..effecb1 100644 --- a/src/declarative/qml/qdeclarativeparser.cpp +++ b/src/declarative/qml/qdeclarativeparser.cpp @@ -205,13 +205,13 @@ QDeclarativeParser::Object::DynamicSlot::DynamicSlot(const DynamicSlot &o) QDeclarativeParser::Property::Property() : parent(0), type(0), index(-1), value(0), isDefault(true), isDeferred(false), - isValueTypeSubProperty(false) + isValueTypeSubProperty(false), isAlias(false) { } QDeclarativeParser::Property::Property(const QByteArray &n) : parent(0), type(0), index(-1), value(0), name(n), isDefault(false), - isDeferred(false), isValueTypeSubProperty(false) + isDeferred(false), isValueTypeSubProperty(false), isAlias(false) { } diff --git a/src/declarative/qml/qdeclarativeparser_p.h b/src/declarative/qml/qdeclarativeparser_p.h index 77184c2..633847d 100644 --- a/src/declarative/qml/qdeclarativeparser_p.h +++ b/src/declarative/qml/qdeclarativeparser_p.h @@ -358,6 +358,9 @@ namespace QDeclarativeParser bool isDeferred; // True if this property is a value-type pseudo-property bool isValueTypeSubProperty; + // True if this property is a property alias. Set by the + // QDeclarativeCompiler + bool isAlias; LocationSpan location; LocationRange listValueRange; diff --git a/src/declarative/qml/qdeclarativeproperty.cpp b/src/declarative/qml/qdeclarativeproperty.cpp index 1395e97..df0917f 100644 --- a/src/declarative/qml/qdeclarativeproperty.cpp +++ b/src/declarative/qml/qdeclarativeproperty.cpp @@ -607,26 +607,7 @@ QDeclarativePropertyPrivate::binding(const QDeclarativeProperty &that) if (!that.isProperty() || !that.d->object) return 0; - QDeclarativeData *data = QDeclarativeData::get(that.d->object); - if (!data) - return 0; - - if (!data->hasBindingBit(that.d->core.coreIndex)) - return 0; - - QDeclarativeAbstractBinding *binding = data->bindings; - while (binding && binding->propertyIndex() != that.d->core.coreIndex) - binding = binding->m_nextBinding; - - if (binding && that.d->valueType.valueTypeCoreIdx != -1) { - if (binding->bindingType() == QDeclarativeAbstractBinding::ValueTypeProxy) { - QDeclarativeValueTypeProxyBinding *proxy = static_cast<QDeclarativeValueTypeProxyBinding *>(binding); - - binding = proxy->binding(bindingIndex(that)); - } - } - - return binding; + return binding(that.d->object, that.d->core.coreIndex, that.d->valueType.valueTypeCoreIdx); } /*! @@ -658,12 +639,106 @@ QDeclarativePropertyPrivate::setBinding(const QDeclarativeProperty &that, } QDeclarativeAbstractBinding * +QDeclarativePropertyPrivate::binding(QObject *object, int coreIndex, int valueTypeIndex) +{ + QDeclarativeData *data = QDeclarativeData::get(object); + if (!data) + return 0; + + QDeclarativePropertyCache::Data *propertyData = + data->propertyCache?data->propertyCache->property(coreIndex):0; + if (propertyData && propertyData->flags & QDeclarativePropertyCache::Data::IsAlias) { + const QDeclarativeVMEMetaObject *vme = + static_cast<const QDeclarativeVMEMetaObject *>(metaObjectForProperty(object->metaObject(), coreIndex)); + + QObject *aObject = 0; int aCoreIndex = -1; int aValueTypeIndex = -1; + if (!vme->aliasTarget(coreIndex, &aObject, &aCoreIndex, &aValueTypeIndex)) + return 0; + + // This will either be a value type sub-reference or an alias to a value-type sub-reference not both + Q_ASSERT(valueTypeIndex == -1 || aValueTypeIndex == -1); + return binding(aObject, aCoreIndex, (valueTypeIndex == -1)?aValueTypeIndex:valueTypeIndex); + } + + if (!data->hasBindingBit(coreIndex)) + return 0; + + QDeclarativeAbstractBinding *binding = data->bindings; + while (binding && binding->propertyIndex() != coreIndex) + binding = binding->m_nextBinding; + + if (binding && valueTypeIndex != -1) { + if (binding->bindingType() == QDeclarativeAbstractBinding::ValueTypeProxy) { + int index = coreIndex | (valueTypeIndex << 24); + binding = static_cast<QDeclarativeValueTypeProxyBinding *>(binding)->binding(index); + } + } + + return binding; +} + +void QDeclarativePropertyPrivate::findAliasTarget(QObject *object, int bindingIndex, + QObject **targetObject, int *targetBindingIndex) +{ + int coreIndex = bindingIndex & 0xFFFFFF; + int valueTypeIndex = bindingIndex >> 24; + if (valueTypeIndex == 0) valueTypeIndex = -1; + + QDeclarativeData *data = QDeclarativeData::get(object, false); + if (data) { + QDeclarativePropertyCache::Data *propertyData = + data->propertyCache?data->propertyCache->property(coreIndex):0; + if (propertyData && propertyData->flags & QDeclarativePropertyCache::Data::IsAlias) { + const QDeclarativeVMEMetaObject *vme = + static_cast<const QDeclarativeVMEMetaObject *>(metaObjectForProperty(object->metaObject(), coreIndex)); + QObject *aObject = 0; int aCoreIndex = -1; int aValueTypeIndex = -1; + if (vme->aliasTarget(coreIndex, &aObject, &aCoreIndex, &aValueTypeIndex)) { + // This will either be a value type sub-reference or an alias to a value-type sub-reference not both + Q_ASSERT(valueTypeIndex == -1 || aValueTypeIndex == -1); + + int aBindingIndex = aCoreIndex; + if (aValueTypeIndex != -1) + aBindingIndex |= aValueTypeIndex << 24; + else if (valueTypeIndex != -1) + aBindingIndex |= valueTypeIndex << 24; + + findAliasTarget(aObject, aBindingIndex, targetObject, targetBindingIndex); + return; + } + } + } + + *targetObject = object; + *targetBindingIndex = bindingIndex; +} + +QDeclarativeAbstractBinding * QDeclarativePropertyPrivate::setBinding(QObject *object, int coreIndex, int valueTypeIndex, QDeclarativeAbstractBinding *newBinding, WriteFlags flags) { QDeclarativeData *data = QDeclarativeData::get(object, 0 != newBinding); QDeclarativeAbstractBinding *binding = 0; + if (data) { + QDeclarativePropertyCache::Data *propertyData = + data->propertyCache?data->propertyCache->property(coreIndex):0; + if (propertyData && propertyData->flags & QDeclarativePropertyCache::Data::IsAlias) { + const QDeclarativeVMEMetaObject *vme = + static_cast<const QDeclarativeVMEMetaObject *>(metaObjectForProperty(object->metaObject(), coreIndex)); + + QObject *aObject = 0; int aCoreIndex = -1; int aValueTypeIndex = -1; + if (!vme->aliasTarget(coreIndex, &aObject, &aCoreIndex, &aValueTypeIndex)) { + if (newBinding) newBinding->destroy(); + return 0; + } + + // This will either be a value type sub-reference or an alias to a value-type sub-reference not both + Q_ASSERT(valueTypeIndex == -1 || aValueTypeIndex == -1); + return setBinding(aObject, aCoreIndex, (valueTypeIndex == -1)?aValueTypeIndex:valueTypeIndex, + newBinding, flags); + } + } + if (data && data->hasBindingBit(coreIndex)) { binding = data->bindings; @@ -671,16 +746,72 @@ QDeclarativePropertyPrivate::setBinding(QObject *object, int coreIndex, int valu binding = binding->m_nextBinding; } - if (binding && valueTypeIndex != -1 && binding->bindingType() == QDeclarativeAbstractBinding::ValueTypeProxy) { - int index = coreIndex | (valueTypeIndex << 24); + int index = coreIndex; + if (valueTypeIndex != -1) + index |= (valueTypeIndex << 24); + + if (binding && valueTypeIndex != -1 && binding->bindingType() == QDeclarativeAbstractBinding::ValueTypeProxy) binding = static_cast<QDeclarativeValueTypeProxyBinding *>(binding)->binding(index); + + if (binding) { + binding->removeFromObject(); + binding->setEnabled(false, 0); } + if (newBinding) { + newBinding->addToObject(object, index); + newBinding->setEnabled(true, flags); + } + + return binding; +} + +QDeclarativeAbstractBinding * +QDeclarativePropertyPrivate::setBindingNoEnable(QObject *object, int coreIndex, int valueTypeIndex, + QDeclarativeAbstractBinding *newBinding) +{ + QDeclarativeData *data = QDeclarativeData::get(object, 0 != newBinding); + QDeclarativeAbstractBinding *binding = 0; + + if (data) { + QDeclarativePropertyCache::Data *propertyData = + data->propertyCache?data->propertyCache->property(coreIndex):0; + if (propertyData && propertyData->flags & QDeclarativePropertyCache::Data::IsAlias) { + const QDeclarativeVMEMetaObject *vme = + static_cast<const QDeclarativeVMEMetaObject *>(metaObjectForProperty(object->metaObject(), coreIndex)); + + QObject *aObject = 0; int aCoreIndex = -1; int aValueTypeIndex = -1; + if (!vme->aliasTarget(coreIndex, &aObject, &aCoreIndex, &aValueTypeIndex)) { + if (newBinding) newBinding->destroy(); + return 0; + } + + // This will either be a value type sub-reference or an alias to a value-type sub-reference not both + Q_ASSERT(valueTypeIndex == -1 || aValueTypeIndex == -1); + return setBindingNoEnable(aObject, aCoreIndex, (valueTypeIndex == -1)?aValueTypeIndex:valueTypeIndex, + newBinding); + } + } + + if (data && data->hasBindingBit(coreIndex)) { + binding = data->bindings; + + while (binding && binding->propertyIndex() != coreIndex) + binding = binding->m_nextBinding; + } + + int index = coreIndex; + if (valueTypeIndex != -1) + index |= (valueTypeIndex << 24); + + if (binding && valueTypeIndex != -1 && binding->bindingType() == QDeclarativeAbstractBinding::ValueTypeProxy) + binding = static_cast<QDeclarativeValueTypeProxyBinding *>(binding)->binding(index); + if (binding) - binding->setEnabled(false); + binding->removeFromObject(); if (newBinding) - newBinding->setEnabled(true, flags); + newBinding->addToObject(object, index); return binding; } @@ -1392,11 +1523,26 @@ static inline int QMetaObject_methods(const QMetaObject *metaObject) int className; int classInfoCount, classInfoData; int methodCount, methodData; + int propertyCount, propertyData; }; return reinterpret_cast<const Private *>(metaObject->d.data)->methodCount; } +static inline int QMetaObject_properties(const QMetaObject *metaObject) +{ + struct Private + { + int revision; + int className; + int classInfoCount, classInfoData; + int methodCount, methodData; + int propertyCount, propertyData; + }; + + return reinterpret_cast<const Private *>(metaObject->d.data)->propertyCount; +} + static inline void flush_vme_signal(const QObject *object, int index) { QDeclarativeData *data = static_cast<QDeclarativeData *>(QObjectPrivate::get(const_cast<QObject *>(object))->declarativeData); @@ -1437,4 +1583,19 @@ bool QDeclarativePropertyPrivate::connect(const QObject *sender, int signal_inde return QMetaObject::connect(sender, signal_index, receiver, method_index, type, types); } +/*! +Return \a metaObject's [super] meta object that provides data for \a property. +*/ +const QMetaObject *QDeclarativePropertyPrivate::metaObjectForProperty(const QMetaObject *metaObject, int property) +{ + int propertyOffset = metaObject->propertyOffset(); + + while (propertyOffset > property) { + metaObject = metaObject->d.superdata; + propertyOffset -= QMetaObject_properties(metaObject); + } + + return metaObject; +} + QT_END_NAMESPACE diff --git a/src/declarative/qml/qdeclarativeproperty_p.h b/src/declarative/qml/qdeclarativeproperty_p.h index a9d6979..6392f88 100644 --- a/src/declarative/qml/qdeclarativeproperty_p.h +++ b/src/declarative/qml/qdeclarativeproperty_p.h @@ -68,7 +68,7 @@ class QDeclarativeExpression; class Q_DECLARATIVE_PRIVATE_EXPORT QDeclarativePropertyPrivate { public: - enum WriteFlag { BypassInterceptor = 0x01, DontRemoveBinding = 0x02 }; + enum WriteFlag { BypassInterceptor = 0x01, DontRemoveBinding = 0x02, RemoveBindingOnAliasWrite = 0x04 }; Q_DECLARE_FLAGS(WriteFlags, WriteFlag) QDeclarativePropertyPrivate() @@ -108,9 +108,13 @@ public: const QVariant &value, int flags); static bool write(QObject *, const QDeclarativePropertyCache::Data &, const QVariant &, QDeclarativeContextData *, WriteFlags flags = 0); + static void findAliasTarget(QObject *, int, QObject **, int *); static QDeclarativeAbstractBinding *setBinding(QObject *, int coreIndex, int valueTypeIndex /* -1 */, QDeclarativeAbstractBinding *, WriteFlags flags = DontRemoveBinding); + static QDeclarativeAbstractBinding *setBindingNoEnable(QObject *, int coreIndex, int valueTypeIndex /* -1 */, + QDeclarativeAbstractBinding *); + static QDeclarativeAbstractBinding *binding(QObject *, int coreIndex, int valueTypeIndex /* -1 */); static QByteArray saveValueType(const QMetaObject *, int, const QMetaObject *, int); @@ -120,7 +124,6 @@ public: static bool equal(const QMetaObject *, const QMetaObject *); static bool canConvert(const QMetaObject *from, const QMetaObject *to); - // "Public" (to QML) methods static QDeclarativeAbstractBinding *binding(const QDeclarativeProperty &that); static QDeclarativeAbstractBinding *setBinding(const QDeclarativeProperty &that, @@ -136,6 +139,7 @@ public: static bool connect(const QObject *sender, int signal_index, const QObject *receiver, int method_index, int type = 0, int *types = 0); + static const QMetaObject *metaObjectForProperty(const QMetaObject *, int); }; Q_DECLARE_OPERATORS_FOR_FLAGS(QDeclarativePropertyPrivate::WriteFlags) diff --git a/src/declarative/qml/qdeclarativepropertycache.cpp b/src/declarative/qml/qdeclarativepropertycache.cpp index af3d53f..dd9a224 100644 --- a/src/declarative/qml/qdeclarativepropertycache.cpp +++ b/src/declarative/qml/qdeclarativepropertycache.cpp @@ -320,8 +320,6 @@ void QDeclarativePropertyCache::update(QDeclarativeEngine *engine, const QMetaOb { Q_ASSERT(engine); Q_ASSERT(metaObject); - QDeclarativeEnginePrivate *enginePriv = QDeclarativeEnginePrivate::get(engine); - Q_UNUSED(enginePriv) clear(); diff --git a/src/declarative/qml/qdeclarativepropertycache_p.h b/src/declarative/qml/qdeclarativepropertycache_p.h index 922010d..f7c5daa 100644 --- a/src/declarative/qml/qdeclarativepropertycache_p.h +++ b/src/declarative/qml/qdeclarativepropertycache_p.h @@ -83,6 +83,7 @@ public: IsConstant = 0x00000001, IsWritable = 0x00000002, IsResettable = 0x00000004, + IsAlias = 0x00000008, // These are mutualy exclusive IsFunction = 0x00000010, diff --git a/src/declarative/qml/qdeclarativevaluetype.cpp b/src/declarative/qml/qdeclarativevaluetype.cpp index b9e9cec..5dc6ffd 100644 --- a/src/declarative/qml/qdeclarativevaluetype.cpp +++ b/src/declarative/qml/qdeclarativevaluetype.cpp @@ -109,36 +109,54 @@ void QDeclarativeValueTypeFactory::registerValueTypes() QDeclarativeValueType *QDeclarativeValueTypeFactory::valueType(int t) { + QDeclarativeValueType *rv = 0; + switch (t) { case QVariant::Point: - return new QDeclarativePointValueType; + rv = new QDeclarativePointValueType; + break; case QVariant::PointF: - return new QDeclarativePointFValueType; + rv = new QDeclarativePointFValueType; + break; case QVariant::Size: - return new QDeclarativeSizeValueType; + rv = new QDeclarativeSizeValueType; + break; case QVariant::SizeF: - return new QDeclarativeSizeFValueType; + rv = new QDeclarativeSizeFValueType; + break; case QVariant::Rect: - return new QDeclarativeRectValueType; + rv = new QDeclarativeRectValueType; + break; case QVariant::RectF: - return new QDeclarativeRectFValueType; + rv = new QDeclarativeRectFValueType; + break; case QVariant::Vector2D: - return new QDeclarativeVector2DValueType; + rv = new QDeclarativeVector2DValueType; + break; case QVariant::Vector3D: - return new QDeclarativeVector3DValueType; + rv = new QDeclarativeVector3DValueType; + break; case QVariant::Vector4D: - return new QDeclarativeVector4DValueType; + rv = new QDeclarativeVector4DValueType; + break; case QVariant::Quaternion: - return new QDeclarativeQuaternionValueType; + rv = new QDeclarativeQuaternionValueType; + break; case QVariant::Matrix4x4: - return new QDeclarativeMatrix4x4ValueType; + rv = new QDeclarativeMatrix4x4ValueType; + break; case QVariant::EasingCurve: - return new QDeclarativeEasingValueType; + rv = new QDeclarativeEasingValueType; + break; case QVariant::Font: - return new QDeclarativeFontValueType; + rv = new QDeclarativeFontValueType; + break; default: - return 0; + break; } + + Q_ASSERT(!rv || rv->metaObject()->propertyCount() < 32); + return rv; } QDeclarativeValueType::QDeclarativeValueType(QObject *parent) diff --git a/src/declarative/qml/qdeclarativevme.cpp b/src/declarative/qml/qdeclarativevme.cpp index db90aff..c742dec 100644 --- a/src/declarative/qml/qdeclarativevme.cpp +++ b/src/declarative/qml/qdeclarativevme.cpp @@ -154,7 +154,8 @@ QObject *QDeclarativeVME::run(QDeclarativeVMEStack<QObject *> &stack, QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(ctxt->engine); int status = -1; //for dbus - QDeclarativePropertyPrivate::WriteFlags flags = QDeclarativePropertyPrivate::BypassInterceptor; + QDeclarativePropertyPrivate::WriteFlags flags = QDeclarativePropertyPrivate::BypassInterceptor | + QDeclarativePropertyPrivate::RemoveBindingOnAliasWrite; for (int ii = start; !isError() && ii < (start + count); ++ii) { const QDeclarativeInstruction &instr = comp->bytecode.at(ii); @@ -664,6 +665,7 @@ QObject *QDeclarativeVME::run(QDeclarativeVMEStack<QObject *> &stack, break; case QDeclarativeInstruction::StoreBinding: + case QDeclarativeInstruction::StoreBindingOnAlias: { QObject *target = stack.at(stack.count() - 1 - instr.assignBinding.owner); @@ -675,14 +677,20 @@ QObject *QDeclarativeVME::run(QDeclarativeVMEStack<QObject *> &stack, int coreIndex = mp.index(); - if (stack.count() == 1 && bindingSkipList.testBit(coreIndex)) + if ((stack.count() - instr.assignBinding.owner) == 1 && bindingSkipList.testBit(coreIndex)) break; QDeclarativeBinding *bind = new QDeclarativeBinding((void *)datas.at(instr.assignBinding.value).constData(), comp, context, ctxt, comp->name, instr.line, 0); bindValues.append(bind); bind->m_mePtr = &bindValues.values[bindValues.count - 1]; bind->setTarget(mp); - bind->addToObject(target); + + if (instr.type == QDeclarativeInstruction::StoreBindingOnAlias) { + QDeclarativeAbstractBinding *old = QDeclarativePropertyPrivate::setBindingNoEnable(target, coreIndex, QDeclarativePropertyPrivate::valueTypeCoreIndex(mp), bind); + if (old) { old->destroy(); } + } else { + bind->addToObject(target, QDeclarativePropertyPrivate::bindingIndex(mp)); + } } break; @@ -701,7 +709,7 @@ QObject *QDeclarativeVME::run(QDeclarativeVMEStack<QObject *> &stack, ctxt->optimizedBindings->configBinding(instr.assignBinding.value, target, scope, property); bindValues.append(binding); binding->m_mePtr = &bindValues.values[bindValues.count - 1]; - binding->addToObject(target); + binding->addToObject(target, property); } break; @@ -874,8 +882,26 @@ QObject *QDeclarativeVME::run(QDeclarativeVMEStack<QObject *> &stack, case QDeclarativeInstruction::FetchValueType: { QObject *target = stack.top(); - QDeclarativeValueType *valueHandler = - ep->valueTypes[instr.fetchValue.type]; + + if (instr.fetchValue.bindingSkipList != 0) { + // Possibly need to clear bindings + QDeclarativeData *targetData = QDeclarativeData::get(target); + if (targetData) { + QDeclarativeAbstractBinding *binding = + QDeclarativePropertyPrivate::binding(target, instr.fetchValue.property, -1); + + if (binding && binding->bindingType() != QDeclarativeAbstractBinding::ValueTypeProxy) { + QDeclarativePropertyPrivate::setBinding(target, instr.fetchValue.property, -1, 0); + binding->destroy(); + } else if (binding) { + QDeclarativeValueTypeProxyBinding *proxy = + static_cast<QDeclarativeValueTypeProxyBinding *>(binding); + proxy->removeBindings(instr.fetchValue.bindingSkipList); + } + } + } + + QDeclarativeValueType *valueHandler = ep->valueTypes[instr.fetchValue.type]; valueHandler->read(target, instr.fetchValue.property); stack.push(valueHandler); } diff --git a/src/declarative/qml/qdeclarativevmemetaobject.cpp b/src/declarative/qml/qdeclarativevmemetaobject.cpp index e28062b..38c1709 100644 --- a/src/declarative/qml/qdeclarativevmemetaobject.cpp +++ b/src/declarative/qml/qdeclarativevmemetaobject.cpp @@ -46,6 +46,7 @@ #include "qdeclarativeexpression.h" #include "private/qdeclarativeexpression_p.h" #include "private/qdeclarativecontext_p.h" +#include "private/qdeclarativebinding_p.h" Q_DECLARE_METATYPE(QScriptValue); @@ -589,7 +590,21 @@ int QDeclarativeVMEMetaObject::metaCall(QMetaObject::Call c, int _id, void **a) if (d->isObjectAlias()) { *reinterpret_cast<QObject **>(a[0]) = target; return -1; - } else if (d->isValueTypeAlias()) { + } + + // Remove binding (if any) on write + if(c == QMetaObject::WriteProperty) { + int flags = *reinterpret_cast<int*>(a[3]); + if (flags & QDeclarativePropertyPrivate::RemoveBindingOnAliasWrite) { + QDeclarativeData *targetData = QDeclarativeData::get(target); + if (targetData && targetData->hasBindingBit(d->propertyIndex())) { + QDeclarativeAbstractBinding *binding = QDeclarativePropertyPrivate::setBinding(target, d->propertyIndex(), d->isValueTypeAlias()?d->valueTypeIndex():-1, 0); + if (binding) binding->destroy(); + } + } + } + + if (d->isValueTypeAlias()) { // Value type property QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(ctxt->engine); @@ -821,6 +836,36 @@ void QDeclarativeVMEMetaObject::setVMEProperty(int index, const QScriptValue &v) return writeVarProperty(index - propOffset, v); } +bool QDeclarativeVMEMetaObject::aliasTarget(int index, QObject **target, int *coreIndex, int *valueTypeIndex) const +{ + Q_ASSERT(index >= propOffset + metaData->propertyCount); + + *target = 0; + *coreIndex = -1; + *valueTypeIndex = -1; + + if (!ctxt) + return false; + + QDeclarativeVMEMetaData::AliasData *d = metaData->aliasData() + (index - propOffset - metaData->propertyCount); + QDeclarativeContext *context = ctxt->asQDeclarativeContext(); + QDeclarativeContextPrivate *ctxtPriv = QDeclarativeContextPrivate::get(context); + + *target = ctxtPriv->data->idValues[d->contextIdx].data(); + if (!*target) + return false; + + if (d->isObjectAlias()) { + } else if (d->isValueTypeAlias()) { + *coreIndex = d->propertyIndex(); + *valueTypeIndex = d->valueTypeIndex(); + } else { + *coreIndex = d->propertyIndex(); + } + + return true; +} + void QDeclarativeVMEMetaObject::connectAlias(int aliasId) { if (!aConnected.testBit(aliasId)) { diff --git a/src/declarative/qml/qdeclarativevmemetaobject_p.h b/src/declarative/qml/qdeclarativevmemetaobject_p.h index 5134763..7b6b410 100644 --- a/src/declarative/qml/qdeclarativevmemetaobject_p.h +++ b/src/declarative/qml/qdeclarativevmemetaobject_p.h @@ -138,6 +138,7 @@ public: QDeclarativeCompiledData *compiledData); ~QDeclarativeVMEMetaObject(); + bool aliasTarget(int index, QObject **target, int *coreIndex, int *valueTypeIndex) const; void registerInterceptor(int index, int valueIndex, QDeclarativePropertyValueInterceptor *interceptor); QScriptValue vmeMethod(int index); int vmeMethodLineNumber(int index); @@ -146,6 +147,7 @@ public: void setVMEProperty(int index, const QScriptValue &); void connectAliasSignal(int index); + protected: virtual int metaCall(QMetaObject::Call _c, int _id, void **_a); diff --git a/src/gui/dialogs/qdialog.cpp b/src/gui/dialogs/qdialog.cpp index b7a0026..fbdc522 100644 --- a/src/gui/dialogs/qdialog.cpp +++ b/src/gui/dialogs/qdialog.cpp @@ -282,8 +282,8 @@ QDialog::QDialog(QWidget *parent, Qt::WindowFlags f) QDialog::QDialog(QWidget *parent, const char *name, bool modal, Qt::WindowFlags f) : QWidget(*new QDialogPrivate, parent, f - | QFlag(modal ? Qt::WShowModal : 0) - | QFlag((f & Qt::WindowType_Mask) == 0 ? Qt::Dialog : 0) + | QFlag(modal ? Qt::WShowModal : Qt::WindowType(0)) + | QFlag((f & Qt::WindowType_Mask) == 0 ? Qt::Dialog : Qt::WindowType(0)) ) { setObjectName(QString::fromAscii(name)); diff --git a/src/gui/itemviews/qabstractitemview.cpp b/src/gui/itemviews/qabstractitemview.cpp index 7b81761..acc8deb 100644 --- a/src/gui/itemviews/qabstractitemview.cpp +++ b/src/gui/itemviews/qabstractitemview.cpp @@ -827,7 +827,7 @@ QVariant QAbstractItemView::inputMethodQuery(Qt::InputMethodQuery query) const deleted. QAbstractItemView does not take ownership of \a delegate. \note If a delegate has been assigned to both a row and a column, the row - delegate (i.e., this delegate) will take presedence and manage the + delegate (i.e., this delegate) will take precedence and manage the intersecting cell index. \warning You should not share the same instance of a delegate between views. @@ -885,7 +885,7 @@ QAbstractItemDelegate *QAbstractItemView::itemDelegateForRow(int row) const deleted. QAbstractItemView does not take ownership of \a delegate. \note If a delegate has been assigned to both a row and a column, the row - delegate will take presedence and manage the intersecting cell index. + delegate will take precedence and manage the intersecting cell index. \warning You should not share the same instance of a delegate between views. Doing so can cause incorrect or unintuitive editing behavior since each diff --git a/src/gui/itemviews/qstandarditemmodel.cpp b/src/gui/itemviews/qstandarditemmodel.cpp index 767b5a9..7d20bbb 100644 --- a/src/gui/itemviews/qstandarditemmodel.cpp +++ b/src/gui/itemviews/qstandarditemmodel.cpp @@ -1130,7 +1130,7 @@ Qt::ItemFlags QStandardItem::flags() const meaning that the user can interact with the item; if \a enabled is false, the user cannot interact with the item. - This flag takes presedence over the other item flags; e.g. if an item is not + This flag takes precedence over the other item flags; e.g. if an item is not enabled, it cannot be selected by the user, even if the Qt::ItemIsSelectable flag has been set. diff --git a/src/gui/painting/qpdf.cpp b/src/gui/painting/qpdf.cpp index ba5d164..bd68d2a 100644 --- a/src/gui/painting/qpdf.cpp +++ b/src/gui/painting/qpdf.cpp @@ -1390,7 +1390,7 @@ int QPdfBaseEngine::metric(QPaintDevice::PaintDeviceMetric metricType) const void QPdfBaseEngine::setProperty(PrintEnginePropertyKey key, const QVariant &value) { Q_D(QPdfBaseEngine); - switch (key) { + switch (int(key)) { case PPK_CollateCopies: d->collate = value.toBool(); break; @@ -1480,7 +1480,7 @@ QVariant QPdfBaseEngine::property(PrintEnginePropertyKey key) const Q_D(const QPdfBaseEngine); QVariant ret; - switch (key) { + switch (int(key)) { case PPK_CollateCopies: ret = d->collate; break; diff --git a/src/gui/styles/qs60style_s60.cpp b/src/gui/styles/qs60style_s60.cpp index 7b75d40..92f53ff 100644 --- a/src/gui/styles/qs60style_s60.cpp +++ b/src/gui/styles/qs60style_s60.cpp @@ -698,7 +698,7 @@ void QS60StylePrivate::deleteStoredSettings() { QSettings settings(QSettings::UserScope, QLatin1String("Trolltech")); settings.beginGroup(QLatin1String("QS60Style")); - settings.remove(""); + settings.remove(QString()); settings.endGroup(); } @@ -717,7 +717,6 @@ QColor QS60StylePrivate::colorFromFrameGraphics(SkinFrameElements frame) const QT_TRAP_THROWING( CRepository *themeRepository = CRepository::NewLC(personalisationUID); if (themeRepository) { - static const TInt KThemePkgIDDesSize = 23; //size of the stored theme package ID TBuf<32> value; //themeID is currently max of 8 + 1 + 8 characters, but lets have some extra space const TUint32 key = 0x00000002; //active theme key in the repository error = themeRepository->Get(key, value); @@ -747,7 +746,7 @@ QColor QS60StylePrivate::colorFromFrameGraphics(SkinFrameElements frame) const return storedColor; } } - settings.remove(""); //if color was invalid, or theme has been changed, just delete all stored settings + settings.remove(QString()); //if color was invalid, or theme has been changed, just delete all stored settings } } #endif diff --git a/src/gui/styles/qstyle.cpp b/src/gui/styles/qstyle.cpp index 3ebfab2..be8f794 100644 --- a/src/gui/styles/qstyle.cpp +++ b/src/gui/styles/qstyle.cpp @@ -2456,6 +2456,8 @@ QDebug operator<<(QDebug debug, QStyle::State state) qSort(states); debug << states.join(QLatin1String(" | ")); debug << ')'; +#else + Q_UNUSED(state); #endif return debug; } diff --git a/src/gui/styles/qstyleoption.cpp b/src/gui/styles/qstyleoption.cpp index 4780edf..05ca793 100644 --- a/src/gui/styles/qstyleoption.cpp +++ b/src/gui/styles/qstyleoption.cpp @@ -5483,6 +5483,8 @@ QDebug operator<<(QDebug debug, const QStyleOption::OptionType &optionType) case QStyleOption::SO_GraphicsItem: debug << "SO_GraphicsItem"; break; } +#else + Q_UNUSED(optionType); #endif return debug; } @@ -5496,6 +5498,8 @@ QDebug operator<<(QDebug debug, const QStyleOption &option) debug << ',' << option.state; debug << ',' << option.rect; debug << ')'; +#else + Q_UNUSED(option); #endif return debug; } diff --git a/src/gui/text/qtextformat.cpp b/src/gui/text/qtextformat.cpp index 46db253..fdbb680 100644 --- a/src/gui/text/qtextformat.cpp +++ b/src/gui/text/qtextformat.cpp @@ -265,10 +265,18 @@ private: friend QDataStream &operator>>(QDataStream &, QTextFormat &); }; -// this is only safe if sizeof(int) == sizeof(float) +// this is only safe because sizeof(int) == sizeof(float) static inline uint hash(float d) { +#ifdef Q_CC_GNU + // this is a GCC extension and isn't guaranteed to work in other compilers + // the reinterpret_cast below generates a strict-aliasing warning with GCC + union { float f; uint u; } cvt; + cvt.f = d; + return cvt.u; +#else return reinterpret_cast<uint&>(d); +#endif } static inline uint hash(const QColor &color) diff --git a/src/network/socket/qlocalsocket_win.cpp b/src/network/socket/qlocalsocket_win.cpp index 1e0bced..5b42578 100644 --- a/src/network/socket/qlocalsocket_win.cpp +++ b/src/network/socket/qlocalsocket_win.cpp @@ -322,9 +322,9 @@ bool QLocalSocketPrivate::completeAsyncRead() // buffer. We will read the remaining data in the next call. break; case ERROR_PIPE_NOT_CONNECTED: - setErrorString(QLatin1String("QLocalSocketPrivate::completeAsyncRead")); - // fall through + return false; default: + setErrorString(QLatin1String("QLocalSocketPrivate::completeAsyncRead")); return false; } } diff --git a/src/network/ssl/qsslcertificate.cpp b/src/network/ssl/qsslcertificate.cpp index a3ea555..275c7be 100644 --- a/src/network/ssl/qsslcertificate.cpp +++ b/src/network/ssl/qsslcertificate.cpp @@ -716,7 +716,7 @@ QSslCertificate QSslCertificatePrivate::QSslCertificate_from_X509(X509 *x509) static bool matchLineFeed(const QByteArray &pem, int *offset) { - char ch; + char ch = 0; // ignore extra whitespace at the end of the line while (*offset < pem.size() && (ch = pem.at(*offset)) == ' ') diff --git a/src/opengl/qgl.cpp b/src/opengl/qgl.cpp index ed9753e..18f1203 100644 --- a/src/opengl/qgl.cpp +++ b/src/opengl/qgl.cpp @@ -2095,7 +2095,9 @@ void QGLContextPrivate::cleanup() void QGLContextPrivate::setVertexAttribArrayEnabled(int arrayIndex, bool enabled) { Q_ASSERT(arrayIndex < QT_GL_VERTEX_ARRAY_TRACKED_COUNT); +#ifdef glEnableVertexAttribArray Q_ASSERT(glEnableVertexAttribArray); +#endif if (vertexAttributeArraysEnabledState[arrayIndex] && !enabled) glDisableVertexAttribArray(arrayIndex); @@ -2108,7 +2110,9 @@ void QGLContextPrivate::setVertexAttribArrayEnabled(int arrayIndex, bool enabled void QGLContextPrivate::syncGlState() { +#ifdef glEnableVertexAttribArray Q_ASSERT(glEnableVertexAttribArray); +#endif for (int i = 0; i < QT_GL_VERTEX_ARRAY_TRACKED_COUNT; ++i) { if (vertexAttributeArraysEnabledState[i]) glEnableVertexAttribArray(i); diff --git a/src/opengl/qgl_x11egl.cpp b/src/opengl/qgl_x11egl.cpp index d33ea56..75dd1b6 100644 --- a/src/opengl/qgl_x11egl.cpp +++ b/src/opengl/qgl_x11egl.cpp @@ -97,7 +97,6 @@ QGLTemporaryContext::QGLTemporaryContext(bool, QWidget *) XVisualInfo visualInfo; XVisualInfo *vi; int numVisuals; - EGLint id = 0; visualInfo.visualid = QEgl::getCompatibleVisualId(config); vi = XGetVisualInfo(X11->display, VisualIDMask, &visualInfo, &numVisuals); @@ -346,7 +345,7 @@ void QGLWidgetPrivate::recreateEglSurface() // old surface before re-creating a new one. Note: This should not be the case as the // surface should be deleted before the old window id. if (glcx->d_func()->eglSurface != EGL_NO_SURFACE && (currentId != eglSurfaceWindowId)) { - qWarning("EGL surface for deleted window %x was not destroyed", eglSurfaceWindowId); + qWarning("EGL surface for deleted window %x was not destroyed", uint(eglSurfaceWindowId)); glcx->d_func()->destroyEglSurfaceForDevice(); } diff --git a/src/opengl/qglpixelbuffer_egl.cpp b/src/opengl/qglpixelbuffer_egl.cpp index 0b94f5a..2d9f6f1 100644 --- a/src/opengl/qglpixelbuffer_egl.cpp +++ b/src/opengl/qglpixelbuffer_egl.cpp @@ -74,7 +74,6 @@ bool QGLPixelBufferPrivate::init(const QSize &size, const QGLFormat &f, QGLWidge // Use the same configuration as the widget we are sharing with. ctx->setConfig(shareContext->config()); #if QGL_RENDER_TEXTURE - EGLint value = EGL_FALSE; if (ctx->configAttrib(EGL_BIND_TO_TEXTURE_RGBA) == EGL_TRUE) textureFormat = EGL_TEXTURE_RGBA; else if (ctx->configAttrib(EGL_BIND_TO_TEXTURE_RGB) == EGL_TRUE) diff --git a/src/plugins/bearer/connman/qconnmanengine.cpp b/src/plugins/bearer/connman/qconnmanengine.cpp index 184ceb4..7f3501e 100644 --- a/src/plugins/bearer/connman/qconnmanengine.cpp +++ b/src/plugins/bearer/connman/qconnmanengine.cpp @@ -726,6 +726,7 @@ void QConnmanEngine::addNetworkConfiguration(const QString &networkPath) if(servicePath.isEmpty()) { id = QString::number(qHash(networkPath)); + serv = 0; } else { id = QString::number(qHash(servicePath)); serv = new QConnmanServiceInterface(servicePath,this); diff --git a/src/plugins/bearer/connman/qconnmanservice_linux.cpp b/src/plugins/bearer/connman/qconnmanservice_linux.cpp index 952a444..0545422 100644 --- a/src/plugins/bearer/connman/qconnmanservice_linux.cpp +++ b/src/plugins/bearer/connman/qconnmanservice_linux.cpp @@ -216,7 +216,6 @@ void QConnmanManagerInterface::registerCounter(const QString &path, quint32 inte { QDBusReply<QList<QDBusObjectPath> > reply = this->call(QLatin1String("RegisterCounter"), QVariant::fromValue(path), QVariant::fromValue(interval)); - bool ok = true; if(reply.error().type() == QDBusError::InvalidArgs) { qWarning() << reply.error().message(); } @@ -225,7 +224,6 @@ void QConnmanManagerInterface::registerCounter(const QString &path, quint32 inte void QConnmanManagerInterface::unregisterCounter(const QString &path) { QDBusReply<QList<QDBusObjectPath> > reply = this->call(QLatin1String("UnregisterCounter"), QVariant::fromValue(path)); - bool ok = true; if(reply.error().type() == QDBusError::InvalidArgs) { qWarning() << reply.error().message(); } diff --git a/src/xmlpatterns/data/qatomicvalue.cpp b/src/xmlpatterns/data/qatomicvalue.cpp index ecc78bf..fc4cf2e 100644 --- a/src/xmlpatterns/data/qatomicvalue.cpp +++ b/src/xmlpatterns/data/qatomicvalue.cpp @@ -202,7 +202,7 @@ ItemType::Ptr AtomicValue::qtToXDMType(const QXmlItem &item) Q_ASSERT(item.isAtomicValue()); const QVariant v(item.toAtomicValue()); - switch(v.type()) + switch(int(v.type())) { case QVariant::Char: /* Fallthrough. */ diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/AliasBindingsAssignCorrectlyType.qml b/tests/auto/declarative/qdeclarativeecmascript/data/AliasBindingsAssignCorrectlyType.qml new file mode 100644 index 0000000..0eda67d --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/AliasBindingsAssignCorrectlyType.qml @@ -0,0 +1,9 @@ +import QtQuick 1.0 + +QtObject { + id: root + + property real realProperty + property alias aliasProperty: root.realProperty +} + diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/AliasBindingsOverrideTargetType.qml b/tests/auto/declarative/qdeclarativeecmascript/data/AliasBindingsOverrideTargetType.qml new file mode 100644 index 0000000..f539fb6 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/AliasBindingsOverrideTargetType.qml @@ -0,0 +1,14 @@ +import QtQuick 1.0 +import Qt.test 1.0 + +MyTypeObject { + id: root + + property int data: 7 + + property int targetProperty: root.data * 43 - root.data + property alias aliasProperty: root.targetProperty + + pointProperty: Qt.point(data, data); + property alias pointAliasProperty: root.pointProperty +} diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/AliasBindingsOverrideTargetType3.qml b/tests/auto/declarative/qdeclarativeecmascript/data/AliasBindingsOverrideTargetType3.qml new file mode 100644 index 0000000..a4b0527 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/AliasBindingsOverrideTargetType3.qml @@ -0,0 +1,9 @@ +import QtQuick 1.0 + +QtObject { + id: root + + property int testProperty + property alias aliasProperty: root.testProperty +} + diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/aliasBindingsAssignCorrectly.qml b/tests/auto/declarative/qdeclarativeecmascript/data/aliasBindingsAssignCorrectly.qml new file mode 100644 index 0000000..f0808c4 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/aliasBindingsAssignCorrectly.qml @@ -0,0 +1,59 @@ +import QtQuick 1.0 + +Item { + id: root + + property bool test: false + + property real testData: 9 + property real testData2: 9 + + states: State { + name: "change" + PropertyChanges { + target: myType + realProperty: if (testData2 > 3) 9; else 11; + } + } + + AliasBindingsAssignCorrectlyType { + id: myType + + aliasProperty: if (testData > 3) 14; else 12; + } + + Component.onCompleted: { + // Check original binding works + if (myType.aliasProperty != 14) return; + + testData = 2; + if (myType.aliasProperty != 12) return; + + // Change binding indirectly by modifying the "realProperty" + root.state = "change"; + if (myType.aliasProperty != 9) return; + + // Check the new binding works + testData2 = 1; + if (myType.aliasProperty != 11) return; + + // Try and trigger the old binding (that should have been removed) + testData = 6; + if (myType.aliasProperty != 11) return; + + // Restore the original binding + root.state = ""; + if (myType.aliasProperty != 14) return; + + // Test the restored binding works + testData = 0; + if (myType.aliasProperty != 12) return; + + // Test the old binding isn't somehow hanging around and still in effect + testData2 = 13; + if (myType.aliasProperty != 12) return; + + test = true; + } +} + diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/aliasBindingsOverrideTarget.2.qml b/tests/auto/declarative/qdeclarativeecmascript/data/aliasBindingsOverrideTarget.2.qml new file mode 100644 index 0000000..4f07cbf --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/aliasBindingsOverrideTarget.2.qml @@ -0,0 +1,29 @@ +import QtQuick 1.0 + +Item { + id: me + property bool test: false + + property int value: 9 + + AliasBindingsOverrideTargetType { + id: aliasType + pointAliasProperty.x: me.value + } + + Component.onCompleted: { + if (aliasType.pointAliasProperty.x != 9) return; + + me.value = 11; + if (aliasType.pointAliasProperty.x != 11) return; + + aliasType.data = 8; + if (aliasType.pointAliasProperty.x != 11) return; + + me.value = 4; + if (aliasType.pointAliasProperty.x != 4) return; + + test = true; + } +} + diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/aliasBindingsOverrideTarget.3.qml b/tests/auto/declarative/qdeclarativeecmascript/data/aliasBindingsOverrideTarget.3.qml new file mode 100644 index 0000000..937ae91 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/aliasBindingsOverrideTarget.3.qml @@ -0,0 +1,24 @@ +import QtQuick 1.0 + +Item { + id: root + property bool test: false; + + property int value1: 10 + property int value2: 11 + + AliasBindingsOverrideTargetType3 { + id: obj + + testProperty: root.value1 * 9 + aliasProperty: root.value2 * 10 + } + + Component.onCompleted: { + if (obj.testProperty != 110) return; + if (obj.aliasProperty != 110) return; + + test = true; + } +} + diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/aliasBindingsOverrideTarget.qml b/tests/auto/declarative/qdeclarativeecmascript/data/aliasBindingsOverrideTarget.qml new file mode 100644 index 0000000..a01dc5b --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/aliasBindingsOverrideTarget.qml @@ -0,0 +1,28 @@ +import QtQuick 1.0 + +Item { + id: me + property bool test: false + + property int value: 9 + + AliasBindingsOverrideTargetType { + id: aliasType + aliasProperty: me.value + } + + Component.onCompleted: { + if (aliasType.aliasProperty != 9) return; + + me.value = 11; + if (aliasType.aliasProperty != 11) return; + + aliasType.data = 8; + if (aliasType.aliasProperty != 11) return; + + me.value = 4; + if (aliasType.aliasProperty != 4) return; + + test = true; + } +} diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/aliasWritesOverrideBindings.2.qml b/tests/auto/declarative/qdeclarativeecmascript/data/aliasWritesOverrideBindings.2.qml new file mode 100644 index 0000000..5bf9f6a --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/aliasWritesOverrideBindings.2.qml @@ -0,0 +1,29 @@ +import QtQuick 1.0 + +Item { + id: me + property bool test: false + + property int value: 9 + + AliasBindingsOverrideTargetType { + id: aliasType + } + + Component.onCompleted: { + if (aliasType.aliasProperty != 294) return; + + aliasType.data = 8; + if (aliasType.aliasProperty != 336) return; + + aliasType.aliasProperty = 4; + if (aliasType.aliasProperty != 4) return; + + aliasType.data = 7; + if (aliasType.aliasProperty != 4) return; + + test = true; + } +} + + diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/aliasWritesOverrideBindings.3.qml b/tests/auto/declarative/qdeclarativeecmascript/data/aliasWritesOverrideBindings.3.qml new file mode 100644 index 0000000..a23ad4a --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/aliasWritesOverrideBindings.3.qml @@ -0,0 +1,23 @@ +import QtQuick 1.0 + +Item { + id: me + property bool test: false + + property int value: 9 + + AliasBindingsOverrideTargetType { + id: aliasType + pointAliasProperty.x: 9 + } + + Component.onCompleted: { + if (aliasType.pointAliasProperty.x != 9) return; + + aliasType.data = 8; + if (aliasType.pointAliasProperty.x != 9) return; + + test = true; + } +} + diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/aliasWritesOverrideBindings.qml b/tests/auto/declarative/qdeclarativeecmascript/data/aliasWritesOverrideBindings.qml new file mode 100644 index 0000000..ac20371 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/aliasWritesOverrideBindings.qml @@ -0,0 +1,23 @@ +import QtQuick 1.0 + +Item { + id: me + property bool test: false + + property int value: 9 + + AliasBindingsOverrideTargetType { + id: aliasType + aliasProperty: 11 + } + + Component.onCompleted: { + if (aliasType.aliasProperty != 11) return; + + aliasType.data = 8; + if (aliasType.aliasProperty != 11) return; + + test = true; + } +} + diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/writeRemovesBinding.qml b/tests/auto/declarative/qdeclarativeecmascript/data/writeRemovesBinding.qml new file mode 100644 index 0000000..035f037 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/writeRemovesBinding.qml @@ -0,0 +1,46 @@ +import QtQuick 1.0 + +QtObject { + id: root + + property bool test: false + + property real data: 9 + property real binding: data + + property alias aliasProperty: root.aliasBinding + property real aliasBinding: data + + Component.onCompleted: { + // Non-aliased properties + if (binding != 9) return; + + data = 11; + if (binding != 11) return; + + binding = 6; + if (binding != 6) return; + + data = 3; + if (binding != 6) return; + + + // Writing through an aliased property + if (aliasProperty != 3) return; + if (aliasBinding != 3) return; + + data = 4; + if (aliasProperty != 4) return; + if (aliasBinding != 4) return; + + aliasProperty = 19; + if (aliasProperty != 19) return; + if (aliasBinding != 19) return; + + data = 5; + if (aliasProperty != 19) return; + if (aliasBinding != 19) return; + + test = true; + } +} diff --git a/tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp b/tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp index 652404c..14755f32 100644 --- a/tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp +++ b/tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp @@ -164,6 +164,10 @@ private slots: void in(); void sharedAttachedObject(); void objectName(); + void writeRemovesBinding(); + void aliasBindingsAssignCorrectly(); + void aliasBindingsOverrideTarget(); + void aliasWritesOverrideBindings(); void include(); @@ -741,11 +745,9 @@ void tst_qdeclarativeecmascript::constantsOverrideBindings() QVERIFY(object != 0); QCOMPARE(object->property("c1").toInt(), 0); - QEXPECT_FAIL("", "QTBUG-13719", Continue); QCOMPARE(object->property("c3").toInt(), 10); object->setProperty("c1", QVariant(9)); QCOMPARE(object->property("c1").toInt(), 9); - QEXPECT_FAIL("", "QTBUG-13719", Continue); QCOMPARE(object->property("c3").toInt(), 10); } } @@ -2671,6 +2673,97 @@ void tst_qdeclarativeecmascript::objectName() delete o; } +void tst_qdeclarativeecmascript::writeRemovesBinding() +{ + QDeclarativeComponent component(&engine, TEST_FILE("writeRemovesBinding.qml")); + QObject *o = component.create(); + QVERIFY(o != 0); + + QCOMPARE(o->property("test").toBool(), true); + + delete o; +} + +// Test bindings assigned to alias properties actually assign to the alias' target +void tst_qdeclarativeecmascript::aliasBindingsAssignCorrectly() +{ + QDeclarativeComponent component(&engine, TEST_FILE("aliasBindingsAssignCorrectly.qml")); + QObject *o = component.create(); + QVERIFY(o != 0); + + QCOMPARE(o->property("test").toBool(), true); + + delete o; +} + +// Test bindings assigned to alias properties override a binding on the target (QTBUG-13719) +void tst_qdeclarativeecmascript::aliasBindingsOverrideTarget() +{ + { + QDeclarativeComponent component(&engine, TEST_FILE("aliasBindingsOverrideTarget.qml")); + QObject *o = component.create(); + QVERIFY(o != 0); + + QCOMPARE(o->property("test").toBool(), true); + + delete o; + } + + { + QDeclarativeComponent component(&engine, TEST_FILE("aliasBindingsOverrideTarget.2.qml")); + QObject *o = component.create(); + QVERIFY(o != 0); + + QCOMPARE(o->property("test").toBool(), true); + + delete o; + } + + { + QDeclarativeComponent component(&engine, TEST_FILE("aliasBindingsOverrideTarget.3.qml")); + QObject *o = component.create(); + QVERIFY(o != 0); + + QCOMPARE(o->property("test").toBool(), true); + + delete o; + } +} + +// Test that writes to alias properties override bindings on the alias target (QTBUG-13719) +void tst_qdeclarativeecmascript::aliasWritesOverrideBindings() +{ + { + QDeclarativeComponent component(&engine, TEST_FILE("aliasWritesOverrideBindings.qml")); + QObject *o = component.create(); + QVERIFY(o != 0); + + QCOMPARE(o->property("test").toBool(), true); + + delete o; + } + + { + QDeclarativeComponent component(&engine, TEST_FILE("aliasWritesOverrideBindings.2.qml")); + QObject *o = component.create(); + QVERIFY(o != 0); + + QCOMPARE(o->property("test").toBool(), true); + + delete o; + } + + { + QDeclarativeComponent component(&engine, TEST_FILE("aliasWritesOverrideBindings.3.qml")); + QObject *o = component.create(); + QVERIFY(o != 0); + + QCOMPARE(o->property("test").toBool(), true); + + delete o; + } +} + QTEST_MAIN(tst_qdeclarativeecmascript) #include "tst_qdeclarativeecmascript.moc" diff --git a/tests/auto/declarative/qdeclarativeinstruction/tst_qdeclarativeinstruction.cpp b/tests/auto/declarative/qdeclarativeinstruction/tst_qdeclarativeinstruction.cpp index db1f191..4470d65 100644 --- a/tests/auto/declarative/qdeclarativeinstruction/tst_qdeclarativeinstruction.cpp +++ b/tests/auto/declarative/qdeclarativeinstruction/tst_qdeclarativeinstruction.cpp @@ -458,6 +458,7 @@ void tst_qdeclarativeinstruction::dump() i.type = QDeclarativeInstruction::FetchValueType; i.fetchValue.property = 34; i.fetchValue.type = 6; + i.fetchValue.bindingSkipList = 7; data->bytecode << i; } @@ -538,7 +539,7 @@ void tst_qdeclarativeinstruction::dump() << "Index\tLine\tOperation\t\tData1\tData2\tData3\tComments" << "-------------------------------------------------------------------------------" << "0\t\t0\tINIT\t\t\t0\t3\t-1\t-1" - << "1\t\t1\tCREATE\t\t\t0\t\t\t\"Test\"" + << "1\t\t1\tCREATE\t\t\t0\t-1\t\t\"Test\"" << "2\t\t2\tSETID\t\t\t0\t\t\t\"testId\"" << "3\t\t3\tSET_DEFAULT" << "4\t\t4\tCREATE_COMPONENT\t3" @@ -578,7 +579,7 @@ void tst_qdeclarativeinstruction::dump() << "38\t\t40\tFETCH_ATTACHED\t\t23" << "39\t\t42\tFETCH_QLIST\t\t32" << "40\t\t43\tFETCH\t\t\t33" - << "41\t\t44\tFETCH_VALUE\t\t34\t6" + << "41\t\t44\tFETCH_VALUE\t\t34\t6\t7" << "42\t\t45\tPOP" << "43\t\t46\tPOP_QLIST" << "44\t\t47\tPOP_VALUE\t\t35\t8" diff --git a/tests/auto/declarative/qdeclarativeproperty/data/aliasPropertyBindings.qml b/tests/auto/declarative/qdeclarativeproperty/data/aliasPropertyBindings.qml new file mode 100644 index 0000000..a253a58 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeproperty/data/aliasPropertyBindings.qml @@ -0,0 +1,19 @@ +import QtQuick 1.0 + +Item { + id: root + + property real test: 9 + property real test2: 3 + + property real realProperty: test * test + test + property alias aliasProperty: root.realProperty + + states: State { + name: "switch" + PropertyChanges { + target: root + aliasProperty: 32 * test2 + } + } +} diff --git a/tests/auto/declarative/qdeclarativeproperty/tst_qdeclarativeproperty.cpp b/tests/auto/declarative/qdeclarativeproperty/tst_qdeclarativeproperty.cpp index 0ca0e03..3cc71bb 100644 --- a/tests/auto/declarative/qdeclarativeproperty/tst_qdeclarativeproperty.cpp +++ b/tests/auto/declarative/qdeclarativeproperty/tst_qdeclarativeproperty.cpp @@ -132,6 +132,7 @@ private slots: // Bugs void crashOnValueProperty(); + void aliasPropertyBindings(); void copy(); private: @@ -1308,6 +1309,74 @@ void tst_qdeclarativeproperty::crashOnValueProperty() QCOMPARE(p.read(), QVariant(20)); } +// QTBUG-13719 +void tst_qdeclarativeproperty::aliasPropertyBindings() +{ + QDeclarativeComponent component(&engine, TEST_FILE("aliasPropertyBindings.qml")); + + QObject *object = component.create(); + QVERIFY(object != 0); + + QCOMPARE(object->property("realProperty").toReal(), 90.); + QCOMPARE(object->property("aliasProperty").toReal(), 90.); + + object->setProperty("test", 10); + + QCOMPARE(object->property("realProperty").toReal(), 110.); + QCOMPARE(object->property("aliasProperty").toReal(), 110.); + + QDeclarativeProperty realProperty(object, QLatin1String("realProperty")); + QDeclarativeProperty aliasProperty(object, QLatin1String("aliasProperty")); + + // Check there is a binding on these two properties + QVERIFY(QDeclarativePropertyPrivate::binding(realProperty) != 0); + QVERIFY(QDeclarativePropertyPrivate::binding(aliasProperty) != 0); + + // Check that its the same binding on these two properties + QCOMPARE(QDeclarativePropertyPrivate::binding(realProperty), + QDeclarativePropertyPrivate::binding(aliasProperty)); + + // Change the binding + object->setProperty("state", QString("switch")); + + QVERIFY(QDeclarativePropertyPrivate::binding(realProperty) != 0); + QVERIFY(QDeclarativePropertyPrivate::binding(aliasProperty) != 0); + QCOMPARE(QDeclarativePropertyPrivate::binding(realProperty), + QDeclarativePropertyPrivate::binding(aliasProperty)); + + QCOMPARE(object->property("realProperty").toReal(), 96.); + QCOMPARE(object->property("aliasProperty").toReal(), 96.); + + // Check the old binding really has not effect any more + object->setProperty("test", 4); + + QCOMPARE(object->property("realProperty").toReal(), 96.); + QCOMPARE(object->property("aliasProperty").toReal(), 96.); + + object->setProperty("test2", 9); + + QCOMPARE(object->property("realProperty").toReal(), 288.); + QCOMPARE(object->property("aliasProperty").toReal(), 288.); + + // Revert + object->setProperty("state", QString("")); + + QVERIFY(QDeclarativePropertyPrivate::binding(realProperty) != 0); + QVERIFY(QDeclarativePropertyPrivate::binding(aliasProperty) != 0); + QCOMPARE(QDeclarativePropertyPrivate::binding(realProperty), + QDeclarativePropertyPrivate::binding(aliasProperty)); + + QCOMPARE(object->property("realProperty").toReal(), 20.); + QCOMPARE(object->property("aliasProperty").toReal(), 20.); + + object->setProperty("test2", 3); + + QCOMPARE(object->property("realProperty").toReal(), 20.); + QCOMPARE(object->property("aliasProperty").toReal(), 20.); + + delete object; +} + void tst_qdeclarativeproperty::copy() { PropertyObject object; diff --git a/tests/auto/declarative/qdeclarativevaluetypes/data/BindingsSpliceCorrectlyType.qml b/tests/auto/declarative/qdeclarativevaluetypes/data/BindingsSpliceCorrectlyType.qml new file mode 100644 index 0000000..f625d08 --- /dev/null +++ b/tests/auto/declarative/qdeclarativevaluetypes/data/BindingsSpliceCorrectlyType.qml @@ -0,0 +1,7 @@ +import Test 1.0 + +MyTypeObject { + property bool boldProperty: false + + font.bold: boldProperty +} diff --git a/tests/auto/declarative/qdeclarativevaluetypes/data/BindingsSpliceCorrectlyType4.qml b/tests/auto/declarative/qdeclarativevaluetypes/data/BindingsSpliceCorrectlyType4.qml new file mode 100644 index 0000000..0bdccce --- /dev/null +++ b/tests/auto/declarative/qdeclarativevaluetypes/data/BindingsSpliceCorrectlyType4.qml @@ -0,0 +1,7 @@ +import Test 1.0 + +MyTypeObject { + property int dataProperty: 7 + + point: Qt.point(dataProperty, dataProperty) +} diff --git a/tests/auto/declarative/qdeclarativevaluetypes/data/BindingsSpliceCorrectlyType5.qml b/tests/auto/declarative/qdeclarativevaluetypes/data/BindingsSpliceCorrectlyType5.qml new file mode 100644 index 0000000..151c499 --- /dev/null +++ b/tests/auto/declarative/qdeclarativevaluetypes/data/BindingsSpliceCorrectlyType5.qml @@ -0,0 +1,7 @@ +import Test 1.0 + +MyTypeObject { + property int dataProperty: 7 + + point.x: dataProperty +} diff --git a/tests/auto/declarative/qdeclarativevaluetypes/data/bindingsSpliceCorrectly.1.qml b/tests/auto/declarative/qdeclarativevaluetypes/data/bindingsSpliceCorrectly.1.qml new file mode 100644 index 0000000..7012143 --- /dev/null +++ b/tests/auto/declarative/qdeclarativevaluetypes/data/bindingsSpliceCorrectly.1.qml @@ -0,0 +1,29 @@ +import Test 1.0 +import QtQuick 1.0 + +BindingsSpliceCorrectlyType { + property bool test: false + + property bool italicProperty: false + + font.italic: italicProperty + + Component.onCompleted: { + // Test initial state + if (font.italic != false) return; + if (font.bold != false) return; + + // Test italic binding worked + italicProperty = true; + + if (font.italic != true) return; + if (font.bold != false) return; + + // Test bold binding worked + boldProperty = true; + if (font.italic != true) return; + if (font.bold != true) return; + + test = true; + } +} diff --git a/tests/auto/declarative/qdeclarativevaluetypes/data/bindingsSpliceCorrectly.2.qml b/tests/auto/declarative/qdeclarativevaluetypes/data/bindingsSpliceCorrectly.2.qml new file mode 100644 index 0000000..69dbcab --- /dev/null +++ b/tests/auto/declarative/qdeclarativevaluetypes/data/bindingsSpliceCorrectly.2.qml @@ -0,0 +1,31 @@ +import Test 1.0 +import QtQuick 1.0 + +BindingsSpliceCorrectlyType { + property bool test: false + + property bool italicProperty: false + + font.italic: italicProperty + font.bold: false + + Component.onCompleted: { + // Test initial state + if (font.italic != false) return; + if (font.bold != false) return; + + // Test italic binding worked + italicProperty = true; + + if (font.italic != true) return; + if (font.bold != false) return; + + // Test bold binding was removed by constant write + boldProperty = true; + if (font.italic != true) return; + if (font.bold != false) return; + + test = true; + } +} + diff --git a/tests/auto/declarative/qdeclarativevaluetypes/data/bindingsSpliceCorrectly.3.qml b/tests/auto/declarative/qdeclarativevaluetypes/data/bindingsSpliceCorrectly.3.qml new file mode 100644 index 0000000..669feb9 --- /dev/null +++ b/tests/auto/declarative/qdeclarativevaluetypes/data/bindingsSpliceCorrectly.3.qml @@ -0,0 +1,36 @@ +import Test 1.0 +import QtQuick 1.0 + +BindingsSpliceCorrectlyType { + property bool test: false + + property bool italicProperty: false + property bool boldProperty2: false + + font.italic: italicProperty + font.bold: boldProperty2 + + Component.onCompleted: { + // Test initial state + if (font.italic != false) return; + if (font.bold != false) return; + + // Test italic binding worked + italicProperty = true; + + if (font.italic != true) return; + if (font.bold != false) return; + + // Test bold binding was overridden + boldProperty = true; + if (font.italic != true) return; + if (font.bold != false) return; + + boldProperty2 = true; + if (font.italic != true) return; + if (font.bold != true) return; + + test = true; + } +} + diff --git a/tests/auto/declarative/qdeclarativevaluetypes/data/bindingsSpliceCorrectly.4.qml b/tests/auto/declarative/qdeclarativevaluetypes/data/bindingsSpliceCorrectly.4.qml new file mode 100644 index 0000000..f28584f --- /dev/null +++ b/tests/auto/declarative/qdeclarativevaluetypes/data/bindingsSpliceCorrectly.4.qml @@ -0,0 +1,27 @@ +import Test 1.0 +import QtQuick 1.0 + +BindingsSpliceCorrectlyType4 { + property bool test: false + + property int dataProperty2: 8 + + point.x: dataProperty2 + + Component.onCompleted: { + if (point.x != 8) return; + if (point.y != 4) return; + + dataProperty = 9; + + if (point.x != 8) return; + if (point.y != 4) return; + + dataProperty2 = 13; + + if (point.x != 13) return; + if (point.y != 4) return; + + test = true; + } +} diff --git a/tests/auto/declarative/qdeclarativevaluetypes/data/bindingsSpliceCorrectly.5.qml b/tests/auto/declarative/qdeclarativevaluetypes/data/bindingsSpliceCorrectly.5.qml new file mode 100644 index 0000000..1214c83 --- /dev/null +++ b/tests/auto/declarative/qdeclarativevaluetypes/data/bindingsSpliceCorrectly.5.qml @@ -0,0 +1,27 @@ +import Test 1.0 +import QtQuick 1.0 + +BindingsSpliceCorrectlyType5 { + property bool test: false + + property int dataProperty2: 8 + + point: Qt.point(dataProperty2, dataProperty2); + + Component.onCompleted: { + if (point.x != 8) return; + if (point.y != 8) return; + + dataProperty = 9; + + if (point.x != 8) return; + if (point.y != 8) return; + + dataProperty2 = 13; + + if (point.x != 13) return; + if (point.y != 13) return; + + test = true; + } +} diff --git a/tests/auto/declarative/qdeclarativevaluetypes/tst_qdeclarativevaluetypes.cpp b/tests/auto/declarative/qdeclarativevaluetypes/tst_qdeclarativevaluetypes.cpp index a4819f3..c243a75 100644 --- a/tests/auto/declarative/qdeclarativevaluetypes/tst_qdeclarativevaluetypes.cpp +++ b/tests/auto/declarative/qdeclarativevaluetypes/tst_qdeclarativevaluetypes.cpp @@ -94,6 +94,7 @@ private slots: void conflictingBindings(); void returnValues(); void varAssignment(); + void bindingsSpliceCorrectly(); private: QDeclarativeEngine engine; @@ -942,6 +943,61 @@ void tst_qdeclarativevaluetypes::varAssignment() delete object; } +// Test bindings splice together correctly +void tst_qdeclarativevaluetypes::bindingsSpliceCorrectly() +{ + { + QDeclarativeComponent component(&engine, TEST_FILE("bindingsSpliceCorrectly.1.qml")); + QObject *object = component.create(); + QVERIFY(object != 0); + + QCOMPARE(object->property("test").toBool(), true); + + delete object; + } + + { + QDeclarativeComponent component(&engine, TEST_FILE("bindingsSpliceCorrectly.2.qml")); + QObject *object = component.create(); + QVERIFY(object != 0); + + QCOMPARE(object->property("test").toBool(), true); + + delete object; + } + + + { + QDeclarativeComponent component(&engine, TEST_FILE("bindingsSpliceCorrectly.3.qml")); + QObject *object = component.create(); + QVERIFY(object != 0); + + QCOMPARE(object->property("test").toBool(), true); + + delete object; + } + + { + QDeclarativeComponent component(&engine, TEST_FILE("bindingsSpliceCorrectly.4.qml")); + QObject *object = component.create(); + QVERIFY(object != 0); + + QCOMPARE(object->property("test").toBool(), true); + + delete object; + } + + { + QDeclarativeComponent component(&engine, TEST_FILE("bindingsSpliceCorrectly.5.qml")); + QObject *object = component.create(); + QVERIFY(object != 0); + + QCOMPARE(object->property("test").toBool(), true); + + delete object; + } +} + QTEST_MAIN(tst_qdeclarativevaluetypes) #include "tst_qdeclarativevaluetypes.moc" diff --git a/tests/auto/qdbusconnection/tst_qdbusconnection.cpp b/tests/auto/qdbusconnection/tst_qdbusconnection.cpp index 599abbd..4494d6f 100644 --- a/tests/auto/qdbusconnection/tst_qdbusconnection.cpp +++ b/tests/auto/qdbusconnection/tst_qdbusconnection.cpp @@ -106,6 +106,8 @@ private slots: void slotsWithLessParameters(); void nestedCallWithCallback(); + void serviceRegistrationRaceCondition(); + public: QString serviceName() const { return "com.trolltech.Qt.Autotests.QDBusConnection"; } bool callMethod(const QDBusConnection &conn, const QString &path); @@ -647,6 +649,73 @@ void tst_QDBusConnection::nestedCallWithCallback() QCOMPARE(signalsReceived, 1); } +class RaceConditionSignalWaiter : public QObject +{ + Q_OBJECT +public: + int count; + RaceConditionSignalWaiter() : count (0) {} + virtual ~RaceConditionSignalWaiter() {} + +public slots: + void countUp() { ++count; emit done(); } +signals: + void done(); +}; + +void tst_QDBusConnection::serviceRegistrationRaceCondition() +{ + // There was a race condition in the updating of list of name owners in + // QtDBus. When the user connects to a signal coming from a given + // service, we must listen for NameOwnerChanged signals relevant to that + // name and update when the owner changes. However, it's possible that we + // receive in one chunk from the server both the NameOwnerChanged signal + // about the service and the signal we're interested in. Since QtDBus + // posts events in order to handle the incoming signals, the update + // happens too late. + + const QString connectionName = "testConnectionName"; + const QString serviceName = "org.example.SecondaryName"; + + QDBusConnection session = QDBusConnection::sessionBus(); + QVERIFY(!session.interface()->isServiceRegistered(serviceName)); + + // connect to the signal: + RaceConditionSignalWaiter recv; + session.connect(serviceName, "/", "com.trolltech.TestCase", "oneSignal", &recv, SLOT(countUp())); + + // create a secondary connection and register a name + QDBusConnection connection = QDBusConnection::connectToBus(QDBusConnection::SessionBus, connectionName); + QDBusConnection::disconnectFromBus(connectionName); // disconnection happens when "connection" goes out of scope + QVERIFY(connection.isConnected()); + QVERIFY(connection.registerService(serviceName)); + + // send a signal + QDBusMessage msg = QDBusMessage::createSignal("/", "com.trolltech.TestCase", "oneSignal"); + connection.send(msg); + + // make a blocking call just to be sure that the buffer was flushed + msg = QDBusMessage::createMethodCall("org.freedesktop.DBus", "/org/freedesktop/DBus", "org.freedesktop.DBus", + "NameHasOwner"); + msg << connectionName; + connection.call(msg); // ignore result + + // Now here's the race condition (more info on task QTBUG-15651): + // the bus has most likely queued three signals for us to work on: + // 1) NameOwnerChanged for the connection we created above + // 2) NameOwnerChanged for the service we registered above + // 3) The "oneSignal" signal we sent + // + // We'll most likely receive all three in one go from the server. We must + // update the owner of serviceName before we start processing the + // "oneSignal" signal. + + QTestEventLoop::instance().connect(&recv, SIGNAL(done()), SLOT(exitLoop())); + QTestEventLoop::instance().enterLoop(1); + QVERIFY(!QTestEventLoop::instance().timeout()); + QCOMPARE(recv.count, 1); +} + QString MyObject::path; QTEST_MAIN(tst_QDBusConnection) diff --git a/tests/auto/qfilesystemwatcher/tst_qfilesystemwatcher.cpp b/tests/auto/qfilesystemwatcher/tst_qfilesystemwatcher.cpp index a26e34d..1feaced 100644 --- a/tests/auto/qfilesystemwatcher/tst_qfilesystemwatcher.cpp +++ b/tests/auto/qfilesystemwatcher/tst_qfilesystemwatcher.cpp @@ -135,14 +135,11 @@ void tst_QFileSystemWatcher::basicTest() // create watcher, forcing it to use a specific backend QFileSystemWatcher watcher; watcher.setObjectName(QLatin1String("_qt_autotest_force_engine_") + backend); + watcher.removePath(testFile.fileName()); watcher.addPath(testFile.fileName()); QSignalSpy changedSpy(&watcher, SIGNAL(fileChanged(const QString &))); QEventLoop eventLoop; - connect(&watcher, - SIGNAL(fileChanged(const QString &)), - &eventLoop, - SLOT(quit())); QTimer timer; connect(&timer, SIGNAL(timeout()), &eventLoop, SLOT(quit())); @@ -278,10 +275,6 @@ void tst_QFileSystemWatcher::watchDirectory() QSignalSpy changedSpy(&watcher, SIGNAL(directoryChanged(const QString &))); QEventLoop eventLoop; - connect(&watcher, - SIGNAL(directoryChanged(const QString &)), - &eventLoop, - SLOT(quit())); QTimer timer; connect(&timer, SIGNAL(timeout()), &eventLoop, SLOT(quit())); diff --git a/tests/auto/qnetworkreply/tst_qnetworkreply.cpp b/tests/auto/qnetworkreply/tst_qnetworkreply.cpp index 90416f2..9cf61f9 100644 --- a/tests/auto/qnetworkreply/tst_qnetworkreply.cpp +++ b/tests/auto/qnetworkreply/tst_qnetworkreply.cpp @@ -4490,6 +4490,7 @@ void tst_QNetworkReply::httpProxyCommandsSynchronous() QVERIFY(reply->isFinished()); // synchronous manager.setProxy(QNetworkProxy()); serverThread.quit(); + serverThread.wait(3000); //qDebug() << reply->error() << reply->errorString(); diff --git a/tests/auto/qsettings/tst_qsettings.cpp b/tests/auto/qsettings/tst_qsettings.cpp index 0395eff..0813e28 100644 --- a/tests/auto/qsettings/tst_qsettings.cpp +++ b/tests/auto/qsettings/tst_qsettings.cpp @@ -51,6 +51,7 @@ #include <QtCore/QMetaType> #include <QtCore/QtDebug> #include <QtCore/QString> +#include "../../shared/util.h" #if !defined(Q_OS_SYMBIAN) # include <cctype> @@ -1726,26 +1727,22 @@ void tst_QSettings::testUpdateRequestEvent() settings1.setValue("key1", 1); QVERIFY(QFileInfo("foo").size() == 0); - qApp->processEvents(); - QVERIFY(QFileInfo("foo").size() > 0); + QTRY_VERIFY(QFileInfo("foo").size() > 0); settings1.remove("key1"); QVERIFY(QFileInfo("foo").size() > 0); - qApp->processEvents(); - QVERIFY(QFileInfo("foo").size() == 0); + QTRY_VERIFY(QFileInfo("foo").size() == 0); settings1.setValue("key2", 2); QVERIFY(QFileInfo("foo").size() == 0); - qApp->processEvents(); - QVERIFY(QFileInfo("foo").size() > 0); + QTRY_VERIFY(QFileInfo("foo").size() > 0); settings1.clear(); QVERIFY(QFileInfo("foo").size() > 0); - qApp->processEvents(); - QVERIFY(QFileInfo("foo").size() == 0); + QTRY_VERIFY(QFileInfo("foo").size() == 0); } const int NumIterations = 5; diff --git a/tests/auto/qsharedpointer/tst_qsharedpointer.cpp b/tests/auto/qsharedpointer/tst_qsharedpointer.cpp index 6b4904f..a05aa97 100644 --- a/tests/auto/qsharedpointer/tst_qsharedpointer.cpp +++ b/tests/auto/qsharedpointer/tst_qsharedpointer.cpp @@ -283,8 +283,8 @@ void tst_QSharedPointer::operators() QSharedPointer<char> p1; QSharedPointer<char> p2(new char); qptrdiff diff = p2.data() - p1.data(); - Q_ASSERT(p1.data() < p2.data()); - Q_ASSERT(diff > 0); + Q_ASSERT(p1.data() != p2.data()); + Q_ASSERT(diff != 0); // operator- QCOMPARE(p2 - p1.data(), diff); diff --git a/tools/shared/windows/registry.cpp b/tools/shared/windows/registry.cpp index 48e9ae6..f520910 100644 --- a/tools/shared/windows/registry.cpp +++ b/tools/shared/windows/registry.cpp @@ -157,6 +157,9 @@ QString qt_readRegistryKey(HKEY parentHandle, const QString &rSubkey) } RegCloseKey(handle); +#else + Q_UNUSED(parentHandle); + Q_UNUSED(rSubkey) #endif return result; |