From 72acc2eac69a5f58f8d99c25cb58f0afaebec7a4 Mon Sep 17 00:00:00 2001 From: Jocelyn Turcotte Date: Thu, 24 Jun 2010 13:38:49 +0200 Subject: qmake: Fix CONFIG += exceptions_off with the MSVC project generator, take 2. The previous patch caused the pch header to be compiled without exception handling since the compilertool for the pch compilation do not get its options filled from the compiler flags. This patch instead set the value to off before calling parseOptions. This also reverts commit 73fa311f67b21c9b897de0196d3b8227f27d828f. Reviewed-by: Oswald Buddenhagen --- qmake/generators/win32/msbuild_objectmodel.cpp | 1 - qmake/generators/win32/msvc_objectmodel.cpp | 7 ++----- qmake/generators/win32/msvc_vcproj.cpp | 1 + qmake/generators/win32/msvc_vcxproj.cpp | 1 + 4 files changed, 4 insertions(+), 6 deletions(-) diff --git a/qmake/generators/win32/msbuild_objectmodel.cpp b/qmake/generators/win32/msbuild_objectmodel.cpp index bf874b2..75fc910 100644 --- a/qmake/generators/win32/msbuild_objectmodel.cpp +++ b/qmake/generators/win32/msbuild_objectmodel.cpp @@ -385,7 +385,6 @@ VCXCLCompilerTool::VCXCLCompilerTool() DisableLanguageExtensions(unset), EnableFiberSafeOptimizations(unset), EnablePREfast(unset), - ExceptionHandling("false"), ExpandAttributedSource(unset), FloatingPointExceptions(unset), ForceConformanceInForLoopScope(unset), diff --git a/qmake/generators/win32/msvc_objectmodel.cpp b/qmake/generators/win32/msvc_objectmodel.cpp index e23e119..1e060a0 100644 --- a/qmake/generators/win32/msvc_objectmodel.cpp +++ b/qmake/generators/win32/msvc_objectmodel.cpp @@ -360,11 +360,8 @@ inline XmlOutput::xml_output xformUsePrecompiledHeaderForNET2005(pchOption whatP inline XmlOutput::xml_output xformExceptionHandlingNET2005(exceptionHandling eh, DotNET compilerVersion) { - if (eh == ehDefault) { - if (compilerVersion >= NET2005) - return attrE(_ExceptionHandling, ehNone); - return attrS(_ExceptionHandling, "false"); - } + if (eh == ehDefault) + return noxml(); if (compilerVersion >= NET2005) return attrE(_ExceptionHandling, eh); diff --git a/qmake/generators/win32/msvc_vcproj.cpp b/qmake/generators/win32/msvc_vcproj.cpp index 35e4896..8686ae8 100644 --- a/qmake/generators/win32/msvc_vcproj.cpp +++ b/qmake/generators/win32/msvc_vcproj.cpp @@ -900,6 +900,7 @@ void VcprojGenerator::initCompilerTool() conf.compiler.AssemblerListingLocation = placement ; conf.compiler.ProgramDataBaseFileName = ".\\" ; conf.compiler.ObjectFile = placement ; + conf.compiler.ExceptionHandling = ehNone; // PCH if (usePCH) { conf.compiler.UsePrecompiledHeader = pchUseUsingSpecific; diff --git a/qmake/generators/win32/msvc_vcxproj.cpp b/qmake/generators/win32/msvc_vcxproj.cpp index 05c1511..f68a435 100644 --- a/qmake/generators/win32/msvc_vcxproj.cpp +++ b/qmake/generators/win32/msvc_vcxproj.cpp @@ -274,6 +274,7 @@ void VcxprojGenerator::initCompilerTool() conf.compiler.AssemblerListingLocation = placement ; conf.compiler.ProgramDataBaseFileName = ".\\" ; conf.compiler.ObjectFileName = placement ; + conf.compiler.ExceptionHandling = "false"; // PCH if (usePCH) { conf.compiler.PrecompiledHeader = "Use"; -- cgit v0.12 From a91f8d704c3ff3826f0ea8b7e73fc6d91dd5b836 Mon Sep 17 00:00:00 2001 From: Kent Hansen Date: Wed, 23 Jun 2010 17:22:47 +0200 Subject: Use custom static scopes to improve QML/JavaScript performance This commit introduces a new internal JS object type, QScriptStaticScopeObject, that enables the JS compiler to make more aggressive optimizations of scoped property access. QScriptStaticScopeObject registers all its properties in a symbol table that the JS compiler has access to. If the compiler finds the property in the symbol table, it will generate the fast index-based op_{get,put}_scoped_var bytecodes, rather than the dynamic (slow) op_resolve and friends. If the compiler _doesn't_ find the property in the symbol table, it infers that it's safe to skip the scope object when later resolving the property, which will also improve performance (see op_resolve_skip bytecode). QScriptStaticScopeObject is only safe to use when all relevant properties are known at JS compile time; that is, when a function that has the static scope object in its scope chain is compiled. It's up to the user of the class (e.g. QtDeclarative) to ensure that this constraint is not violated. The API for constructing QScriptStaticScopeObject instances is not public; it lives in QScriptDeclarativeClass for now, an internal class exported for the purpose of QML. The instance is returned as a QScriptValue and can be manipulated like any other JS object (e.g. by QScriptValue::setProperty()). The other part of this commit utilizes QScriptStaticScopeObject in QtDeclarative in the two major places where it's currently possible: 1) QML disallows adding properties to the Global Object. Furthermore, it's not possible for QML IDs and properties to "shadow" global variables. Hence, a QScriptStaticScopeObject can be used to hold all the standard ECMA properties, and this scope object can come _before_ the QML component in the scope chain. This enables binding expressions and scripts to have optimized (direct) access to e.g. Math.sin. 2) Imported scripts can have their properties (resulting from variable declarations ("var" statements) and function declarations) added to a static scope object. This enables functions in the script to have optimized (direct) access to the script's own properties, as well as to global properties such as Math. With this change, it's no longer possible to delete properties of the Global Object, nor delete properties of an imported script. It's a compromise we make in order to make the optimization safe. Task-number: QTBUG-8576 Reviewed-by: Aaron Kennedy Reviewed-by: Olivier Goffart Reviewed-by: Jedrzej Nowacki --- src/declarative/qml/qdeclarativecontext.cpp | 12 +- src/declarative/qml/qdeclarativeexpression.cpp | 8 +- .../qml/qdeclarativeglobalscriptclass.cpp | 39 ++-- .../qml/qdeclarativeglobalscriptclass_p.h | 4 +- src/declarative/qml/qdeclarativeinclude.cpp | 2 +- src/script/api/qscriptengine.cpp | 12 +- src/script/api/qscriptengine_p.h | 15 ++ src/script/bridge/bridge.pri | 2 + src/script/bridge/qscriptdeclarativeclass.cpp | 36 +++ src/script/bridge/qscriptdeclarativeclass_p.h | 5 + src/script/bridge/qscriptstaticscopeobject.cpp | 157 +++++++++++++ src/script/bridge/qscriptstaticscopeobject_p.h | 103 +++++++++ tests/auto/qscriptengine/tst_qscriptengine.cpp | 242 +++++++++++++++++++++ .../script/qscriptengine/tst_qscriptengine.cpp | 52 +++++ 14 files changed, 652 insertions(+), 37 deletions(-) create mode 100644 src/script/bridge/qscriptstaticscopeobject.cpp create mode 100644 src/script/bridge/qscriptstaticscopeobject_p.h diff --git a/src/declarative/qml/qdeclarativecontext.cpp b/src/declarative/qml/qdeclarativecontext.cpp index 2221d78..60e9dd3 100644 --- a/src/declarative/qml/qdeclarativecontext.cpp +++ b/src/declarative/qml/qdeclarativecontext.cpp @@ -660,10 +660,9 @@ void QDeclarativeContextData::addImportedScript(const QDeclarativeParser::Object QScriptContext *scriptContext = QScriptDeclarativeClass::pushCleanContext(scriptEngine); scriptContext->pushScope(enginePriv->contextClass->newUrlContext(url)); - scriptContext->pushScope(enginePriv->globalClass->globalObject()); + scriptContext->pushScope(enginePriv->globalClass->staticGlobalObject()); - QScriptValue scope = scriptEngine->newObject(); - scriptContext->setActivationObject(scope); + QScriptValue scope = QScriptDeclarativeClass::newStaticScopeObject(scriptEngine); scriptContext->pushScope(scope); scriptEngine->evaluate(code, url, 1); @@ -686,10 +685,9 @@ void QDeclarativeContextData::addImportedScript(const QDeclarativeParser::Object QScriptContext *scriptContext = QScriptDeclarativeClass::pushCleanContext(scriptEngine); scriptContext->pushScope(enginePriv->contextClass->newUrlContext(this, 0, url)); - scriptContext->pushScope(enginePriv->globalClass->globalObject()); - - QScriptValue scope = scriptEngine->newObject(); - scriptContext->setActivationObject(scope); + scriptContext->pushScope(enginePriv->globalClass->staticGlobalObject()); + + QScriptValue scope = QScriptDeclarativeClass::newStaticScopeObject(scriptEngine); scriptContext->pushScope(scope); scriptEngine->evaluate(code, url, 1); diff --git a/src/declarative/qml/qdeclarativeexpression.cpp b/src/declarative/qml/qdeclarativeexpression.cpp index b1aecfa..8ae5f2f 100644 --- a/src/declarative/qml/qdeclarativeexpression.cpp +++ b/src/declarative/qml/qdeclarativeexpression.cpp @@ -145,7 +145,7 @@ void QDeclarativeExpressionPrivate::init(QDeclarativeContextData *ctxt, void *ex if (!dd->cachedClosures.at(progIdx)) { QScriptContext *scriptContext = QScriptDeclarativeClass::pushCleanContext(scriptEngine); scriptContext->pushScope(ep->contextClass->newSharedContext()); - scriptContext->pushScope(ep->globalClass->globalObject()); + scriptContext->pushScope(ep->globalClass->staticGlobalObject()); dd->cachedClosures[progIdx] = new QScriptValue(scriptEngine->evaluate(data->expression, data->url, data->line)); scriptEngine->popContext(); } @@ -188,7 +188,7 @@ QScriptValue QDeclarativeExpressionPrivate::evalInObjectScope(QDeclarativeContex } else { scriptContext->pushScope(ep->contextClass->newContext(context, object)); } - scriptContext->pushScope(ep->globalClass->globalObject()); + scriptContext->pushScope(ep->globalClass->staticGlobalObject()); QScriptValue rv = ep->scriptEngine.evaluate(program, fileName, lineNumber); ep->scriptEngine.popContext(); return rv; @@ -206,7 +206,7 @@ QScriptValue QDeclarativeExpressionPrivate::evalInObjectScope(QDeclarativeContex } else { scriptContext->pushScope(ep->contextClass->newContext(context, object)); } - scriptContext->pushScope(ep->globalClass->globalObject()); + scriptContext->pushScope(ep->globalClass->staticGlobalObject()); QScriptValue rv = ep->scriptEngine.evaluate(program); ep->scriptEngine.popContext(); return rv; @@ -369,7 +369,7 @@ QScriptValue QDeclarativeExpressionPrivate::eval(QObject *secondaryScope, bool * QScriptContext *scriptContext = QScriptDeclarativeClass::pushCleanContext(scriptEngine); data->expressionContext = ep->contextClass->newContext(data->context(), data->me); scriptContext->pushScope(data->expressionContext); - scriptContext->pushScope(ep->globalClass->globalObject()); + scriptContext->pushScope(ep->globalClass->staticGlobalObject()); if (data->expressionRewritten) { data->expressionFunction = scriptEngine->evaluate(data->expression, diff --git a/src/declarative/qml/qdeclarativeglobalscriptclass.cpp b/src/declarative/qml/qdeclarativeglobalscriptclass.cpp index 6e107fb..39ea101 100644 --- a/src/declarative/qml/qdeclarativeglobalscriptclass.cpp +++ b/src/declarative/qml/qdeclarativeglobalscriptclass.cpp @@ -41,10 +41,13 @@ #include "private/qdeclarativeglobalscriptclass_p.h" +#include #include #include #include +#include + QT_BEGIN_NAMESPACE /* @@ -55,23 +58,31 @@ QDeclarativeGlobalScriptClass::QDeclarativeGlobalScriptClass(QScriptEngine *engi { QString eval = QLatin1String("eval"); - QScriptValue globalObject = engine->globalObject(); + QScriptValue originalGlobalObject = engine->globalObject(); - m_globalObject = engine->newObject(); QScriptValue newGlobalObject = engine->newObject(); - QScriptValueIterator iter(globalObject); - - while (iter.hasNext()) { - iter.next(); - - QString name = iter.name(); - - if (name != eval) - m_globalObject.setProperty(iter.scriptName(), iter.value()); - newGlobalObject.setProperty(iter.scriptName(), iter.value()); - - m_illegalNames.insert(name); + { + QScriptValueIterator iter(originalGlobalObject); + QVector names; + QVector values; + QVector flags; + while (iter.hasNext()) { + iter.next(); + + QString name = iter.name(); + + if (name != eval) { + names.append(name); + values.append(iter.value()); + flags.append(iter.flags() | QScriptValue::Undeletable); + } + newGlobalObject.setProperty(iter.scriptName(), iter.value()); + + m_illegalNames.insert(name); + } + m_staticGlobalObject = QScriptDeclarativeClass::newStaticScopeObject( + engine, names.size(), names.constData(), values.constData(), flags.constData()); } newGlobalObject.setScriptClass(this); diff --git a/src/declarative/qml/qdeclarativeglobalscriptclass_p.h b/src/declarative/qml/qdeclarativeglobalscriptclass_p.h index 7690edd..414bf02 100644 --- a/src/declarative/qml/qdeclarativeglobalscriptclass_p.h +++ b/src/declarative/qml/qdeclarativeglobalscriptclass_p.h @@ -75,13 +75,13 @@ public: void explicitSetProperty(const QString &, const QScriptValue &); - const QScriptValue &globalObject() const { return m_globalObject; } + const QScriptValue &staticGlobalObject() const { return m_staticGlobalObject; } const QSet &illegalNames() const { return m_illegalNames; } private: QSet m_illegalNames; - QScriptValue m_globalObject; + QScriptValue m_staticGlobalObject; }; QT_END_NAMESPACE diff --git a/src/declarative/qml/qdeclarativeinclude.cpp b/src/declarative/qml/qdeclarativeinclude.cpp index c29005a..f26b54f 100644 --- a/src/declarative/qml/qdeclarativeinclude.cpp +++ b/src/declarative/qml/qdeclarativeinclude.cpp @@ -240,7 +240,7 @@ QScriptValue QDeclarativeInclude::include(QScriptContext *ctxt, QScriptEngine *e QScriptContext *scriptContext = QScriptDeclarativeClass::pushCleanContext(engine); scriptContext->pushScope(ep->contextClass->newUrlContext(context, 0, urlString)); - scriptContext->pushScope(ep->globalClass->globalObject()); + scriptContext->pushScope(ep->globalClass->staticGlobalObject()); QScriptValue scope = QScriptDeclarativeClass::scopeChainValue(ctxt, -5); scriptContext->pushScope(scope); scriptContext->setActivationObject(scope); diff --git a/src/script/api/qscriptengine.cpp b/src/script/api/qscriptengine.cpp index e2999c1..655026c 100644 --- a/src/script/api/qscriptengine.cpp +++ b/src/script/api/qscriptengine.cpp @@ -64,6 +64,7 @@ #include "bridge/qscriptqobject_p.h" #include "bridge/qscriptglobalobject_p.h" #include "bridge/qscriptactivationobject_p.h" +#include "bridge/qscriptstaticscopeobject_p.h" #ifndef QT_NO_QOBJECT #include @@ -905,6 +906,7 @@ QScriptEnginePrivate::QScriptEnginePrivate() JSC::ExecState* exec = globalObject->globalExec(); scriptObjectStructure = QScriptObject::createStructure(globalObject->objectPrototype()); + staticScopeObjectStructure = QScriptStaticScopeObject::createStructure(JSC::jsNull()); qobjectPrototype = new (exec) QScript::QObjectPrototype(exec, QScript::QObjectPrototype::createStructure(globalObject->objectPrototype()), globalObject->prototypeFunctionStructure()); qobjectWrapperObjectStructure = QScriptObject::createStructure(qobjectPrototype); @@ -1770,15 +1772,7 @@ void QScriptEnginePrivate::setProperty(JSC::ExecState *exec, JSC::JSValue object } else if (flags != QScriptValue::KeepExistingFlags) { if (thisObject->hasOwnProperty(exec, id)) thisObject->deleteProperty(exec, id); // ### hmmm - can't we just update the attributes? - unsigned attribs = 0; - if (flags & QScriptValue::ReadOnly) - attribs |= JSC::ReadOnly; - if (flags & QScriptValue::SkipInEnumeration) - attribs |= JSC::DontEnum; - if (flags & QScriptValue::Undeletable) - attribs |= JSC::DontDelete; - attribs |= flags & QScriptValue::UserRange; - thisObject->putWithAttributes(exec, id, value, attribs); + thisObject->putWithAttributes(exec, id, value, propertyFlagsToJSCAttributes(flags)); } else { JSC::PutPropertySlot slot; thisObject->put(exec, id, value, slot); diff --git a/src/script/api/qscriptengine_p.h b/src/script/api/qscriptengine_p.h index 56366e2..1b35704 100644 --- a/src/script/api/qscriptengine_p.h +++ b/src/script/api/qscriptengine_p.h @@ -205,6 +205,7 @@ public: inline QScriptValue scriptValueFromJSCValue(JSC::JSValue value); inline JSC::JSValue scriptValueToJSCValue(const QScriptValue &value); + static inline unsigned propertyFlagsToJSCAttributes(const QScriptValue::PropertyFlags &flags); static inline JSC::JSValue jscValueFromVariant(JSC::ExecState*, const QVariant &value); static QVariant jscValueToVariant(JSC::ExecState*, JSC::JSValue value, int targetType); @@ -346,6 +347,7 @@ public: JSC::ExecState *currentFrame; WTF::RefPtr scriptObjectStructure; + WTF::RefPtr staticScopeObjectStructure; QScript::QObjectPrototype *qobjectPrototype; WTF::RefPtr qobjectWrapperObjectStructure; @@ -639,6 +641,19 @@ inline JSC::JSValue QScriptEnginePrivate::scriptValueToJSCValue(const QScriptVal return vv->jscValue; } +inline unsigned QScriptEnginePrivate::propertyFlagsToJSCAttributes(const QScriptValue::PropertyFlags &flags) +{ + unsigned attribs = 0; + if (flags & QScriptValue::ReadOnly) + attribs |= JSC::ReadOnly; + if (flags & QScriptValue::SkipInEnumeration) + attribs |= JSC::DontEnum; + if (flags & QScriptValue::Undeletable) + attribs |= JSC::DontDelete; + attribs |= flags & QScriptValue::UserRange; + return attribs; +} + inline QScriptValuePrivate::~QScriptValuePrivate() { if (engine) diff --git a/src/script/bridge/bridge.pri b/src/script/bridge/bridge.pri index 09e2dfb..ab0a322 100644 --- a/src/script/bridge/bridge.pri +++ b/src/script/bridge/bridge.pri @@ -6,6 +6,7 @@ SOURCES += \ $$PWD/qscriptqobject.cpp \ $$PWD/qscriptglobalobject.cpp \ $$PWD/qscriptactivationobject.cpp \ + $$PWD/qscriptstaticscopeobject.cpp \ $$PWD/qscriptdeclarativeobject.cpp \ $$PWD/qscriptdeclarativeclass.cpp @@ -17,5 +18,6 @@ HEADERS += \ $$PWD/qscriptqobject_p.h \ $$PWD/qscriptglobalobject_p.h \ $$PWD/qscriptactivationobject_p.h \ + $$PWD/qscriptstaticscopeobject_p.h \ $$PWD/qscriptdeclarativeobject_p.h \ $$PWD/qscriptdeclarativeclass_p.h diff --git a/src/script/bridge/qscriptdeclarativeclass.cpp b/src/script/bridge/qscriptdeclarativeclass.cpp index 1093448..8080b9f 100644 --- a/src/script/bridge/qscriptdeclarativeclass.cpp +++ b/src/script/bridge/qscriptdeclarativeclass.cpp @@ -24,6 +24,7 @@ #include "qscriptdeclarativeclass_p.h" #include "qscriptdeclarativeobject_p.h" #include "qscriptobject_p.h" +#include "qscriptstaticscopeobject_p.h" #include #include #include @@ -549,4 +550,39 @@ QScriptContext *QScriptDeclarativeClass::context() const return d_ptr->context; } +/*! + Creates a scope object with a fixed set of undeletable properties. +*/ +QScriptValue QScriptDeclarativeClass::newStaticScopeObject( + QScriptEngine *engine, int propertyCount, const QString *names, + const QScriptValue *values, const QScriptValue::PropertyFlags *flags) +{ + QScriptEnginePrivate *eng_p = QScriptEnginePrivate::get(engine); + QScript::APIShim shim(eng_p); + JSC::ExecState *exec = eng_p->currentFrame; + QScriptStaticScopeObject::PropertyInfo *props = new QScriptStaticScopeObject::PropertyInfo[propertyCount]; + for (int i = 0; i < propertyCount; ++i) { + unsigned attribs = QScriptEnginePrivate::propertyFlagsToJSCAttributes(flags[i]); + Q_ASSERT_X(attribs & JSC::DontDelete, Q_FUNC_INFO, "All properties must be undeletable"); + JSC::Identifier id = JSC::Identifier(exec, names[i]); + JSC::JSValue jsval = eng_p->scriptValueToJSCValue(values[i]); + props[i] = QScriptStaticScopeObject::PropertyInfo(id, jsval, attribs); + } + QScriptValue result = eng_p->scriptValueFromJSCValue(new (exec)QScriptStaticScopeObject(eng_p->staticScopeObjectStructure, + propertyCount, props)); + delete[] props; + return result; +} + +/*! + Creates a static scope object that's initially empty, but to which new + properties can be added. +*/ +QScriptValue QScriptDeclarativeClass::newStaticScopeObject(QScriptEngine *engine) +{ + QScriptEnginePrivate *eng_p = QScriptEnginePrivate::get(engine); + QScript::APIShim shim(eng_p); + return eng_p->scriptValueFromJSCValue(new (eng_p->currentFrame)QScriptStaticScopeObject(eng_p->staticScopeObjectStructure)); +} + QT_END_NAMESPACE diff --git a/src/script/bridge/qscriptdeclarativeclass_p.h b/src/script/bridge/qscriptdeclarativeclass_p.h index 714a67c..420b133 100644 --- a/src/script/bridge/qscriptdeclarativeclass_p.h +++ b/src/script/bridge/qscriptdeclarativeclass_p.h @@ -92,6 +92,11 @@ public: static QScriptValue scopeChainValue(QScriptContext *, int index); static QScriptContext *pushCleanContext(QScriptEngine *); + static QScriptValue newStaticScopeObject( + QScriptEngine *, int propertyCount, const QString *names, + const QScriptValue *values, const QScriptValue::PropertyFlags *flags); + static QScriptValue newStaticScopeObject(QScriptEngine *); + class Q_SCRIPT_EXPORT PersistentIdentifier { public: diff --git a/src/script/bridge/qscriptstaticscopeobject.cpp b/src/script/bridge/qscriptstaticscopeobject.cpp new file mode 100644 index 0000000..44548a4 --- /dev/null +++ b/src/script/bridge/qscriptstaticscopeobject.cpp @@ -0,0 +1,157 @@ +/**************************************************************************** +** +** 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 QtScript module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL-ONLY$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "config.h" +#include "qscriptstaticscopeobject_p.h" + +namespace JSC +{ + ASSERT_CLASS_FITS_IN_CELL(QT_PREPEND_NAMESPACE(QScriptStaticScopeObject)); +} + +QT_BEGIN_NAMESPACE + +/*! + \class QScriptStaticScopeObject + \internal + + Represents a static scope object. + + This class allows the VM to determine at JS script compile time whether + the object has a given property or not. If the object has the property, + a fast, index-based read/write operation will be used. If the object + doesn't have the property, the compiler knows it can safely skip this + object when dynamically resolving the property. Either way, this can + greatly improve performance. + + \sa QScriptContext::pushScope() +*/ + +const JSC::ClassInfo QScriptStaticScopeObject::info = { "QScriptStaticScopeObject", 0, 0, 0 }; + +/*! + Creates a static scope object with a fixed set of undeletable properties. + + It's not possible to add new properties to the object after construction. +*/ +QScriptStaticScopeObject::QScriptStaticScopeObject(WTF::NonNullPassRefPtr structure, + int propertyCount, const PropertyInfo* props) + : JSC::JSVariableObject(structure, new Data(/*canGrow=*/false)) +{ + int index = growRegisterArray(propertyCount); + for (int i = 0; i < propertyCount; ++i, --index) { + const PropertyInfo& prop = props[i]; + JSC::SymbolTableEntry entry(index, prop.attributes); + symbolTable().add(prop.identifier.ustring().rep(), entry); + registerAt(index) = prop.value; + } +} + +/*! + Creates an empty static scope object. + + Properties can be added to the object after construction, either by + calling QScriptValue::setProperty(), or by pushing the object on the + scope chain; variable declarations ("var" statements) and function + declarations in JavaScript will create properties on the scope object. + + Note that once the scope object has been used in a closure and the + resulting function has been compiled, it's no longer safe to add + properties to the scope object (because the VM will bypass this + object the next time the function is executed). +*/ +QScriptStaticScopeObject::QScriptStaticScopeObject(WTF::NonNullPassRefPtr structure) + : JSC::JSVariableObject(structure, new Data(/*canGrow=*/true)) +{ +} + +QScriptStaticScopeObject::~QScriptStaticScopeObject() +{ + delete d; +} + +bool QScriptStaticScopeObject::getOwnPropertySlot(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::PropertySlot& slot) +{ + return symbolTableGet(propertyName, slot); +} + +bool QScriptStaticScopeObject::getOwnPropertyDescriptor(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::PropertyDescriptor& descriptor) +{ + return symbolTableGet(propertyName, descriptor); +} + +void QScriptStaticScopeObject::putWithAttributes(JSC::ExecState* exec, const JSC::Identifier &propertyName, JSC::JSValue value, unsigned attributes) +{ + if (symbolTablePutWithAttributes(propertyName, value, attributes)) + return; + Q_ASSERT(d_ptr()->canGrow); + addSymbolTableProperty(propertyName, value, attributes); +} + +void QScriptStaticScopeObject::put(JSC::ExecState* exec, const JSC::Identifier& propertyName, JSC::JSValue value, JSC::PutPropertySlot&) +{ + if (symbolTablePut(propertyName, value)) + return; + Q_ASSERT(d_ptr()->canGrow); + addSymbolTableProperty(propertyName, value, /*attributes=*/0); +} + +bool QScriptStaticScopeObject::deleteProperty(JSC::ExecState*, const JSC::Identifier&) +{ + return false; +} + +void QScriptStaticScopeObject::markChildren(JSC::MarkStack& markStack) +{ + JSC::Register* registerArray = d_ptr()->registerArray.get(); + if (!registerArray) + return; + markStack.appendValues(reinterpret_cast(registerArray), d_ptr()->registerArraySize); +} + +void QScriptStaticScopeObject::addSymbolTableProperty(const JSC::Identifier& name, JSC::JSValue value, unsigned attributes) +{ + int index = growRegisterArray(1); + JSC::SymbolTableEntry newEntry(index, attributes | JSC::DontDelete); + symbolTable().add(name.ustring().rep(), newEntry); + registerAt(index) = value; +} + +/*! + Grows the register array by \a count elements, and returns the offset of + the newly added elements (note that the register file grows downwards, + starting at index -1). +*/ +int QScriptStaticScopeObject::growRegisterArray(int count) +{ + size_t oldSize = d_ptr()->registerArraySize; + size_t newSize = oldSize + count; + JSC::Register* registerArray = new JSC::Register[newSize]; + if (d_ptr()->registerArray) + memcpy(registerArray + count, d_ptr()->registerArray.get(), oldSize * sizeof(JSC::Register)); + setRegisters(registerArray + newSize, registerArray); + d_ptr()->registerArraySize = newSize; + return -oldSize - 1; +} + +QT_END_NAMESPACE diff --git a/src/script/bridge/qscriptstaticscopeobject_p.h b/src/script/bridge/qscriptstaticscopeobject_p.h new file mode 100644 index 0000000..0a0e7ef --- /dev/null +++ b/src/script/bridge/qscriptstaticscopeobject_p.h @@ -0,0 +1,103 @@ +/**************************************************************************** +** +** 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 QtScript module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL-ONLY$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QSCRIPTSTATICSCOPEOBJECT_P_H +#define QSCRIPTSTATICSCOPEOBJECT_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include + +#include "JSVariableObject.h" + +QT_BEGIN_NAMESPACE + +class QScriptStaticScopeObject : public JSC::JSVariableObject { +public: + struct PropertyInfo { + PropertyInfo(const JSC::Identifier& i, JSC::JSValue v, unsigned a) + : identifier(i), value(v), attributes(a) + { } + PropertyInfo() {} + + JSC::Identifier identifier; + JSC::JSValue value; + unsigned attributes; + }; + + QScriptStaticScopeObject(WTF::NonNullPassRefPtr structure, + int propertyCount, const PropertyInfo*); + QScriptStaticScopeObject(WTF::NonNullPassRefPtr structure); + virtual ~QScriptStaticScopeObject(); + + virtual bool isDynamicScope() const { return false; } + + virtual bool getOwnPropertySlot(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::PropertySlot&); + virtual bool getOwnPropertyDescriptor(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::PropertyDescriptor&); + + virtual void putWithAttributes(JSC::ExecState *exec, const JSC::Identifier &propertyName, JSC::JSValue value, unsigned attributes); + virtual void put(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::JSValue value, JSC::PutPropertySlot&); + + virtual bool deleteProperty(JSC::ExecState*, const JSC::Identifier& propertyName); + + virtual void markChildren(JSC::MarkStack&); + + virtual const JSC::ClassInfo* classInfo() const { return &info; } + static const JSC::ClassInfo info; + + static WTF::PassRefPtr createStructure(JSC::JSValue proto) { + return JSC::Structure::create(proto, JSC::TypeInfo(JSC::ObjectType, StructureFlags)); + } + +protected: + static const unsigned StructureFlags = JSC::OverridesGetOwnPropertySlot | JSC::NeedsThisConversion | JSC::OverridesMarkChildren | JSC::OverridesGetPropertyNames | JSC::JSVariableObject::StructureFlags; + + struct Data : public JSVariableObjectData { + Data(bool canGrow_) + : JSVariableObjectData(&symbolTable, /*registers=*/0), + canGrow(canGrow_), registerArraySize(0) + { } + bool canGrow; + int registerArraySize; + JSC::SymbolTable symbolTable; + }; + + Data* d_ptr() const { return static_cast(JSVariableObject::d); } + +private: + void addSymbolTableProperty(const JSC::Identifier&, JSC::JSValue, unsigned attributes); + int growRegisterArray(int); +}; + +QT_END_NAMESPACE + +#endif diff --git a/tests/auto/qscriptengine/tst_qscriptengine.cpp b/tests/auto/qscriptengine/tst_qscriptengine.cpp index 5e59950..6885adf 100644 --- a/tests/auto/qscriptengine/tst_qscriptengine.cpp +++ b/tests/auto/qscriptengine/tst_qscriptengine.cpp @@ -51,6 +51,8 @@ #include #include +#include + Q_DECLARE_METATYPE(QList) Q_DECLARE_METATYPE(QObjectList) Q_DECLARE_METATYPE(QScriptProgram) @@ -169,6 +171,8 @@ private slots: void qRegExpInport_data(); void qRegExpInport(); void reentrency(); + void newFixedStaticScopeObject(); + void newGrowingStaticScopeObject(); }; tst_QScriptEngine::tst_QScriptEngine() @@ -4955,5 +4959,243 @@ void tst_QScriptEngine::reentrency() QCOMPARE(eng.evaluate("foo() + hello").toInt32(), 5+6+9); } +void tst_QScriptEngine::newFixedStaticScopeObject() +{ + QScriptEngine eng; + static const int propertyCount = 4; + QString names[] = { "foo", "bar", "baz", "Math" }; + QScriptValue values[] = { 123, "ciao", true, false }; + QScriptValue::PropertyFlags flags[] = { QScriptValue::Undeletable, + QScriptValue::ReadOnly | QScriptValue::Undeletable, + QScriptValue::SkipInEnumeration | QScriptValue::Undeletable, + QScriptValue::Undeletable }; + QScriptValue scope = QScriptDeclarativeClass::newStaticScopeObject(&eng, propertyCount, names, values, flags); + + // Query property. + for (int i = 0; i < propertyCount; ++i) { + for (int x = 0; x < 2; ++x) { + if (x) { + // Properties can't be deleted. + scope.setProperty(names[i], QScriptValue()); + } + QVERIFY(scope.property(names[i]).equals(values[i])); + QCOMPARE(scope.propertyFlags(names[i]), flags[i]); + } + } + + // Property that doesn't exist. + QVERIFY(!scope.property("noSuchProperty").isValid()); + QCOMPARE(scope.propertyFlags("noSuchProperty"), QScriptValue::PropertyFlags()); + + // Write to writable property. + { + QScriptValue oldValue = scope.property("foo"); + QVERIFY(oldValue.isNumber()); + QScriptValue newValue = oldValue.toNumber() * 2; + scope.setProperty("foo", newValue); + QVERIFY(scope.property("foo").equals(newValue)); + scope.setProperty("foo", oldValue); + QVERIFY(scope.property("foo").equals(oldValue)); + } + + // Write to read-only property. + scope.setProperty("bar", 456); + QVERIFY(scope.property("bar").equals("ciao")); + + // Iterate. + { + QScriptValueIterator it(scope); + QSet iteratedNames; + while (it.hasNext()) { + it.next(); + iteratedNames.insert(it.name()); + } + for (int i = 0; i < propertyCount; ++i) + QVERIFY(iteratedNames.contains(names[i])); + } + + // Push it on the scope chain of a new context. + QScriptContext *ctx = eng.pushContext(); + ctx->pushScope(scope); + QCOMPARE(ctx->scopeChain().size(), 3); // Global Object, native activation, custom scope + QVERIFY(ctx->activationObject().equals(scope)); + + // Read property from JS. + for (int i = 0; i < propertyCount; ++i) { + for (int x = 0; x < 2; ++x) { + if (x) { + // Property can't be deleted from JS. + QScriptValue ret = eng.evaluate(QString::fromLatin1("delete %0").arg(names[i])); + QVERIFY(ret.equals(false)); + } + QVERIFY(eng.evaluate(names[i]).equals(values[i])); + } + } + + // Property that doesn't exist. + QVERIFY(eng.evaluate("noSuchProperty").equals("ReferenceError: Can't find variable: noSuchProperty")); + + // Write property from JS. + { + QScriptValue oldValue = eng.evaluate("foo"); + QVERIFY(oldValue.isNumber()); + QScriptValue newValue = oldValue.toNumber() * 2; + QVERIFY(eng.evaluate("foo = foo * 2; foo").equals(newValue)); + scope.setProperty("foo", oldValue); + QVERIFY(eng.evaluate("foo").equals(oldValue)); + } + + // Write to read-only property. + QVERIFY(eng.evaluate("bar = 456; bar").equals("ciao")); + + // Create a closure and return properties from there. + { + QScriptValue props = eng.evaluate("(function() { var baz = 'shadow'; return [foo, bar, baz, Math, Array]; })()"); + QVERIFY(props.isArray()); + // "foo" and "bar" come from scope object. + QVERIFY(props.property(0).equals(scope.property("foo"))); + QVERIFY(props.property(1).equals(scope.property("bar"))); + // "baz" shadows property in scope object. + QVERIFY(props.property(2).equals("shadow")); + // "Math" comes from scope object, and shadows Global Object's "Math". + QVERIFY(props.property(3).equals(scope.property("Math"))); + QVERIFY(!props.property(3).equals(eng.globalObject().property("Math"))); + // "Array" comes from Global Object. + QVERIFY(props.property(4).equals(eng.globalObject().property("Array"))); + } + + // As with normal JS, assigning to an undefined variable will create + // the property on the Global Object, not the inner scope. + QVERIFY(!eng.globalObject().property("newProperty").isValid()); + QVERIFY(eng.evaluate("(function() { newProperty = 789; })()").isUndefined()); + QVERIFY(!scope.property("newProperty").isValid()); + QVERIFY(eng.globalObject().property("newProperty").isNumber()); + + // Nested static scope. + { + static const int propertyCount2 = 2; + QString names2[] = { "foo", "hum" }; + QScriptValue values2[] = { 321, "hello" }; + QScriptValue::PropertyFlags flags2[] = { QScriptValue::Undeletable, + QScriptValue::ReadOnly | QScriptValue::Undeletable }; + QScriptValue scope2 = QScriptDeclarativeClass::newStaticScopeObject(&eng, propertyCount2, names2, values2, flags2); + ctx->pushScope(scope2); + + // "foo" shadows scope.foo. + QVERIFY(eng.evaluate("foo").equals(scope2.property("foo"))); + QVERIFY(!eng.evaluate("foo").equals(scope.property("foo"))); + // "hum" comes from scope2. + QVERIFY(eng.evaluate("hum").equals(scope2.property("hum"))); + // "Array" comes from Global Object. + QVERIFY(eng.evaluate("Array").equals(eng.globalObject().property("Array"))); + + ctx->popScope(); + } + + QScriptValue fun = eng.evaluate("(function() { return foo; })"); + QVERIFY(fun.isFunction()); + eng.popContext(); + // Function's scope chain persists after popContext(). + QVERIFY(fun.call().equals(scope.property("foo"))); +} + +void tst_QScriptEngine::newGrowingStaticScopeObject() +{ + QScriptEngine eng; + QScriptValue scope = QScriptDeclarativeClass::newStaticScopeObject(&eng); + + // Initially empty. + QVERIFY(!QScriptValueIterator(scope).hasNext()); + QVERIFY(!scope.property("foo").isValid()); + + // Add a static property. + scope.setProperty("foo", 123); + QVERIFY(scope.property("foo").equals(123)); + QCOMPARE(scope.propertyFlags("foo"), QScriptValue::Undeletable); + + // Modify existing property. + scope.setProperty("foo", 456); + QVERIFY(scope.property("foo").equals(456)); + + // Add a read-only property. + scope.setProperty("bar", "ciao", QScriptValue::ReadOnly); + QVERIFY(scope.property("bar").equals("ciao")); + QCOMPARE(scope.propertyFlags("bar"), QScriptValue::ReadOnly | QScriptValue::Undeletable); + + // Attempt to modify read-only property. + scope.setProperty("bar", "hello"); + QVERIFY(scope.property("bar").equals("ciao")); + + // Properties can't be deleted. + scope.setProperty("foo", QScriptValue()); + QVERIFY(scope.property("foo").equals(456)); + scope.setProperty("bar", QScriptValue()); + QVERIFY(scope.property("bar").equals("ciao")); + + // Iterate. + { + QScriptValueIterator it(scope); + QSet iteratedNames; + while (it.hasNext()) { + it.next(); + iteratedNames.insert(it.name()); + } + QCOMPARE(iteratedNames.size(), 2); + QVERIFY(iteratedNames.contains("foo")); + QVERIFY(iteratedNames.contains("bar")); + } + + // Push it on the scope chain of a new context. + QScriptContext *ctx = eng.pushContext(); + ctx->pushScope(scope); + QCOMPARE(ctx->scopeChain().size(), 3); // Global Object, native activation, custom scope + QVERIFY(ctx->activationObject().equals(scope)); + + // Read property from JS. + QVERIFY(eng.evaluate("foo").equals(scope.property("foo"))); + QVERIFY(eng.evaluate("bar").equals(scope.property("bar"))); + + // Write property from JS. + { + QScriptValue oldValue = eng.evaluate("foo"); + QVERIFY(oldValue.isNumber()); + QScriptValue newValue = oldValue.toNumber() * 2; + QVERIFY(eng.evaluate("foo = foo * 2; foo").equals(newValue)); + scope.setProperty("foo", oldValue); + QVERIFY(eng.evaluate("foo").equals(oldValue)); + } + + // Write to read-only property. + QVERIFY(eng.evaluate("bar = 456; bar").equals("ciao")); + + // Shadow property. + QVERIFY(eng.evaluate("Math").equals(eng.globalObject().property("Math"))); + scope.setProperty("Math", "fake Math"); + QVERIFY(eng.evaluate("Math").equals(scope.property("Math"))); + + // Variable declarations will create properties on the scope. + eng.evaluate("var baz = 456"); + QVERIFY(scope.property("baz").equals(456)); + + // Function declarations will create properties on the scope. + eng.evaluate("function fun() { return baz; }"); + QVERIFY(scope.property("fun").isFunction()); + QVERIFY(scope.property("fun").call().equals(scope.property("baz"))); + + // Demonstrate the limitation of a growable static scope: Once a function that + // uses the scope has been compiled, it won't pick up properties that are added + // to the scope later. + { + QScriptValue fun = eng.evaluate("(function() { return futureProperty; })"); + QVERIFY(fun.isFunction()); + QCOMPARE(fun.call().toString(), QString::fromLatin1("ReferenceError: Can't find variable: futureProperty")); + scope.setProperty("futureProperty", "added after the function was compiled"); + // If scope were dynamic, this would return the new property. + QCOMPARE(fun.call().toString(), QString::fromLatin1("ReferenceError: Can't find variable: futureProperty")); + } + + eng.popContext(); +} + QTEST_MAIN(tst_QScriptEngine) #include "tst_qscriptengine.moc" diff --git a/tests/benchmarks/script/qscriptengine/tst_qscriptengine.cpp b/tests/benchmarks/script/qscriptengine/tst_qscriptengine.cpp index 35e2f28..4610046 100644 --- a/tests/benchmarks/script/qscriptengine/tst_qscriptengine.cpp +++ b/tests/benchmarks/script/qscriptengine/tst_qscriptengine.cpp @@ -42,6 +42,8 @@ #include #include +#include + //TESTED_FILES= class tst_QScriptEngine : public QObject @@ -74,6 +76,8 @@ private slots: void nativeCall(); void translation_data(); void translation(); + void readScopeProperty_data(); + void readScopeProperty(); }; tst_QScriptEngine::tst_QScriptEngine() @@ -288,5 +292,53 @@ void tst_QScriptEngine::translation() } } +void tst_QScriptEngine::readScopeProperty_data() +{ + QTest::addColumn("staticScope"); + QTest::addColumn("nestedScope"); + QTest::newRow("single dynamic scope") << false << false; + QTest::newRow("single static scope") << true << false; + QTest::newRow("double dynamic scope") << false << true; + QTest::newRow("double static scope") << true << true; +} + +void tst_QScriptEngine::readScopeProperty() +{ + QFETCH(bool, staticScope); + QFETCH(bool, nestedScope); + + QScriptEngine engine; + QScriptContext *ctx = engine.pushContext(); + + QScriptValue scope; + if (staticScope) + scope = QScriptDeclarativeClass::newStaticScopeObject(&engine); + else + scope = engine.newObject(); + scope.setProperty("foo", 123); + ctx->pushScope(scope); + + if (nestedScope) { + QScriptValue scope2; + if (staticScope) + scope2 = QScriptDeclarativeClass::newStaticScopeObject(&engine); + else + scope2 = engine.newObject(); + scope2.setProperty("bar", 456); // ensure a miss in inner scope + ctx->pushScope(scope2); + } + + QScriptValue fun = engine.evaluate("(function() {\n" + " for (var i = 0; i < 10000; ++i) {\n" + " foo; foo; foo; foo; foo; foo; foo; foo;\n" + " }\n" + "})"); + engine.popContext(); + QVERIFY(fun.isFunction()); + QBENCHMARK { + fun.call(); + } +} + QTEST_MAIN(tst_QScriptEngine) #include "tst_qscriptengine.moc" -- cgit v0.12 From 06ea7cfc8f682904496889aedec03b1f00b0a8e7 Mon Sep 17 00:00:00 2001 From: Martin Smith Date: Fri, 25 Jun 2010 10:23:44 +0200 Subject: doc: Added more DITA output to the XML generator Output Q_PROPERTY as a cxxVariable. Task-number: QTBUG-11391 --- tools/qdoc3/cppcodeparser.cpp | 32 +++++++- tools/qdoc3/ditaxmlgenerator.cpp | 56 +++++++++++++- tools/qdoc3/ditaxmlgenerator.h | 1 + tools/qdoc3/node.cpp | 39 +++++++++- tools/qdoc3/node.h | 155 ++++++++++++++++++++++----------------- 5 files changed, 207 insertions(+), 76 deletions(-) diff --git a/tools/qdoc3/cppcodeparser.cpp b/tools/qdoc3/cppcodeparser.cpp index 13678af..ce7eba3 100644 --- a/tools/qdoc3/cppcodeparser.cpp +++ b/tools/qdoc3/cppcodeparser.cpp @@ -1850,16 +1850,40 @@ bool CppCodeParser::matchProperty(InnerNode *parent) else if (key == "WRITE") { tre->addPropertyFunction(property, value, PropertyNode::Setter); property->setWritable(true); - } else if (key == "STORED") + } + else if (key == "STORED") property->setStored(value.toLower() == "true"); - else if (key == "DESIGNABLE") - property->setDesignable(value.toLower() == "true"); + else if (key == "DESIGNABLE") { + QString v = value.toLower(); + if (v == "true") + property->setDesignable(true); + else if (v == "false") + property->setDesignable(false); + else { + property->setDesignable(false); + property->setRuntimeDesFunc(value); + } + } else if (key == "RESET") tre->addPropertyFunction(property, value, PropertyNode::Resetter); else if (key == "NOTIFY") { tre->addPropertyFunction(property, value, PropertyNode::Notifier); } - + else if (key == "SCRIPTABLE") { + QString v = value.toLower(); + if (v == "true") + property->setScriptable(true); + else if (v == "false") + property->setScriptable(false); + else { + property->setScriptable(false); + property->setRuntimeScrFunc(value); + } + } + else if (key == "COSTANT") + property->setConstant(); + else if (key == "FINAL") + property->setFinal(); } match(Tok_RightParen); return true; diff --git a/tools/qdoc3/ditaxmlgenerator.cpp b/tools/qdoc3/ditaxmlgenerator.cpp index be734ac..852d209 100644 --- a/tools/qdoc3/ditaxmlgenerator.cpp +++ b/tools/qdoc3/ditaxmlgenerator.cpp @@ -4914,9 +4914,9 @@ void DitaXmlGenerator::writeProperties(const Section& s, writer.writeAttribute("value",pn->accessString()); writer.writeEndElement(); // - if (!pn->dataType().isEmpty()) { + if (!pn->qualifiedDataType().isEmpty()) { writer.writeStartElement(CXXVARIABLEDECLAREDTYPE); - writer.writeCharacters(pn->dataType()); + writer.writeCharacters(pn->qualifiedDataType()); writer.writeEndElement(); // } QString fq = fullQualification(pn); @@ -4925,11 +4925,49 @@ void DitaXmlGenerator::writeProperties(const Section& s, writer.writeCharacters(fq); writer.writeEndElement(); // } + + writer.writeStartElement(CXXVARIABLEPROTOTYPE); + writer.writeCharacters("Q_PROPERTY("); + writer.writeCharacters(pn->qualifiedDataType()); + writer.writeCharacters(" "); + writer.writeCharacters(pn->name()); + writerFunctions("READ",pn->getters()); + writerFunctions("WRITE",pn->setters()); + writerFunctions("RESET",pn->resetters()); + writerFunctions("NOTIFY",pn->notifiers()); + if (pn->isDesignable() != pn->designableDefault()) { + writer.writeCharacters(" DESIGNABLE "); + if (!pn->runtimeDesignabilityFunction().isEmpty()) + writer.writeCharacters(pn->runtimeDesignabilityFunction()); + else + writer.writeCharacters(pn->isDesignable() ? "true" : "false"); + } + if (pn->isScriptable() != pn->scriptableDefault()) { + writer.writeCharacters(" SCRIPTABLE "); + if (!pn->runtimeScriptabilityFunction().isEmpty()) + writer.writeCharacters(pn->runtimeScriptabilityFunction()); + else + writer.writeCharacters(pn->isScriptable() ? "true" : "false"); + } + if (pn->isWritable() != pn->writableDefault()) { + writer.writeCharacters(" STORED "); + writer.writeCharacters(pn->isStored() ? "true" : "false"); + } + if (pn->isUser() != pn->userDefault()) { + writer.writeCharacters(" USER "); + writer.writeCharacters(pn->isUser() ? "true" : "false"); + } + if (pn->isConstant()) + writer.writeCharacters(" CONSTANT"); + if (pn->isFinal()) + writer.writeCharacters(" FINAL"); + writer.writeCharacters(")"); + writer.writeEndElement(); // + writer.writeStartElement(CXXVARIABLENAMELOOKUP); writer.writeCharacters(pn->parent()->name() + "::" + pn->name()); writer.writeEndElement(); // - if (pn->overriddenFrom() != 0) { PropertyNode* opn = (PropertyNode*)pn->overriddenFrom(); writer.writeStartElement(CXXVARIABLEREIMPLEMENTED); @@ -4954,4 +4992,16 @@ void DitaXmlGenerator::writeProperties(const Section& s, } } +void DitaXmlGenerator::writerFunctions(const QString& tag, const NodeList& nlist) +{ + NodeList::const_iterator n = nlist.begin(); + while (n != nlist.end()) { + writer.writeCharacters(" "); + writer.writeCharacters(tag); + writer.writeCharacters(" "); + writer.writeCharacters((*n)->name()); + ++n; + } +} + QT_END_NAMESPACE diff --git a/tools/qdoc3/ditaxmlgenerator.h b/tools/qdoc3/ditaxmlgenerator.h index 8c7e439..26788d7 100644 --- a/tools/qdoc3/ditaxmlgenerator.h +++ b/tools/qdoc3/ditaxmlgenerator.h @@ -133,6 +133,7 @@ class DitaXmlGenerator : public PageGenerator void writeProperties(const Section& s, const ClassNode* cn, CodeMarker* marker); + void writerFunctions(const QString& tag, const NodeList& nlist); private: enum SubTitleSize { SmallSubTitle, LargeSubTitle }; diff --git a/tools/qdoc3/node.cpp b/tools/qdoc3/node.cpp index 26957ac..7596825 100644 --- a/tools/qdoc3/node.cpp +++ b/tools/qdoc3/node.cpp @@ -1287,21 +1287,39 @@ void FunctionNode::debug() const /*! \class PropertyNode + + This class describes one instance of using the Q_PROPERTY macro. */ /*! + The constructor sets the \a parent and the \a name, but + everything else is set to default values. */ PropertyNode::PropertyNode(InnerNode *parent, const QString& name) : LeafNode(Property, parent, name), sto(Trool_Default), des(Trool_Default), + scr(Trool_Default), + wri(Trool_Default), + usr(Trool_Default), + cst(false), + fnl(false), overrides(0) { + // nothing. } /*! + Sets this property's \e {overridden from} property to + \a baseProperty, which indicates that this property + overrides \a baseProperty. To begin with, all the values + in this property are set to the corresponding values in + \a baseProperty. + + We probably should ensure that the constant and final + attributes are not being overridden improperly. */ -void PropertyNode::setOverriddenFrom(const PropertyNode *baseProperty) +void PropertyNode::setOverriddenFrom(const PropertyNode* baseProperty) { for (int i = 0; i < NumFunctionRoles; ++i) { if (funcs[i].isEmpty()) @@ -1311,6 +1329,12 @@ void PropertyNode::setOverriddenFrom(const PropertyNode *baseProperty) sto = baseProperty->sto; if (des == Trool_Default) des = baseProperty->des; + if (scr == Trool_Default) + scr = baseProperty->scr; + if (wri == Trool_Default) + wri = baseProperty->wri; + if (usr == Trool_Default) + usr = baseProperty->usr; overrides = baseProperty; } @@ -1336,7 +1360,9 @@ QString PropertyNode::qualifiedDataType() const } } -/*! +/*! Converts the \a boolean value to an enum representation + of the boolean type, which includes an enum value for the + \e {default value} of the item, i.e. true, false, or default. */ PropertyNode::Trool PropertyNode::toTrool(bool boolean) { @@ -1344,6 +1370,15 @@ PropertyNode::Trool PropertyNode::toTrool(bool boolean) } /*! + Converts the enum \a troolean back to a boolean value. + If \a troolean is neither the true enum value nor the + false enum value, the boolean value returned is + \a defaultValue. + + Note that runtimeDesignabilityFunction() should be called + first. If that function returns the name of a function, it + means the function must be called at runtime to determine + whether the property is Designable. */ bool PropertyNode::fromTrool(Trool troolean, bool defaultValue) { diff --git a/tools/qdoc3/node.h b/tools/qdoc3/node.h index 37f2f26..b13e113 100644 --- a/tools/qdoc3/node.h +++ b/tools/qdoc3/node.h @@ -153,7 +153,7 @@ class Node void setStatus(Status status) { sta = status; } void setThreadSafeness(ThreadSafeness safeness) { saf = safeness; } void setSince(const QString &since) { sinc = since; } - void setRelates(InnerNode *pseudoParent); + void setRelates(InnerNode* pseudoParent); void setModuleName(const QString &module) { mod = module; } void setLink(LinkType linkType, const QString &link, const QString &desc); void setUrl(const QString &url); @@ -167,8 +167,8 @@ class Node virtual bool isQmlNode() const { return false; } Type type() const { return typ; } virtual SubType subType() const { return NoSubType; } - InnerNode *parent() const { return par; } - InnerNode *relates() const { return rel; } + InnerNode* parent() const { return par; } + InnerNode* relates() const { return rel; } const QString& name() const { return nam; } QMap > links() const { return linkMap; } QString moduleName() const; @@ -195,7 +195,7 @@ class Node QString ditaXmlHref(); protected: - Node(Type type, InnerNode *parent, const QString& name); + Node(Type type, InnerNode* parent, const QString& name); private: @@ -212,8 +212,8 @@ class Node PageType pageTyp : 4; Status sta : 3; #endif - InnerNode *par; - InnerNode *rel; + InnerNode* par; + InnerNode* rel; QString nam; Location loc; Doc d; @@ -228,35 +228,35 @@ class Node class FunctionNode; class EnumNode; -typedef QList NodeList; +typedef QList NodeList; class InnerNode : public Node { public: virtual ~InnerNode(); - Node *findNode(const QString& name); - Node *findNode(const QString& name, Type type); - FunctionNode *findFunctionNode(const QString& name); - FunctionNode *findFunctionNode(const FunctionNode *clone); + Node* findNode(const QString& name); + Node* findNode(const QString& name, Type type); + FunctionNode* findFunctionNode(const QString& name); + FunctionNode* findFunctionNode(const FunctionNode* clone); void addInclude(const QString &include); void setIncludes(const QStringList &includes); - void setOverload(const FunctionNode *func, bool overlode); + void setOverload(const FunctionNode* func, bool overlode); void normalizeOverloads(); void makeUndocumentedChildrenInternal(); void deleteChildren(); void removeFromRelated(); virtual bool isInnerNode() const; - const Node *findNode(const QString& name) const; - const Node *findNode(const QString& name, Type type) const; - const FunctionNode *findFunctionNode(const QString& name) const; - const FunctionNode *findFunctionNode(const FunctionNode *clone) const; - const EnumNode *findEnumNodeForValue(const QString &enumValue) const; + const Node* findNode(const QString& name) const; + const Node* findNode(const QString& name, Type type) const; + const FunctionNode* findFunctionNode(const QString& name) const; + const FunctionNode* findFunctionNode(const FunctionNode* clone) const; + const EnumNode* findEnumNodeForValue(const QString &enumValue) const; const NodeList & childNodes() const { return children; } const NodeList & relatedNodes() const { return related; } int count() const { return children.size(); } - int overloadNumber(const FunctionNode *func) const; + int overloadNumber(const FunctionNode* func) const; int numOverloads(const QString& funcName) const; NodeList overloads(const QString &funcName) const; const QStringList& includes() const { return inc; } @@ -269,23 +269,23 @@ class InnerNode : public Node virtual void setAbstract(bool ) { } protected: - InnerNode(Type type, InnerNode *parent, const QString& name); + InnerNode(Type type, InnerNode* parent, const QString& name); private: friend class Node; - static bool isSameSignature(const FunctionNode *f1, const FunctionNode *f2); - void addChild(Node *child); - void removeChild(Node *child); - void removeRelated(Node *pseudoChild); + static bool isSameSignature(const FunctionNode* f1, const FunctionNode* f2); + void addChild(Node* child); + void removeChild(Node* child); + void removeRelated(Node* pseudoChild); QStringList pageKeywds; QStringList inc; NodeList children; NodeList enumChildren; NodeList related; - QMap childMap; - QMap primaryFunctionMap; + QMap childMap; + QMap primaryFunctionMap; QMap secondaryFunctionMap; }; @@ -304,7 +304,7 @@ class LeafNode : public Node class NamespaceNode : public InnerNode { public: - NamespaceNode(InnerNode *parent, const QString& name); + NamespaceNode(InnerNode* parent, const QString& name); virtual ~NamespaceNode() { } }; @@ -329,11 +329,11 @@ struct RelatedClass class ClassNode : public InnerNode { public: - ClassNode(InnerNode *parent, const QString& name); + ClassNode(InnerNode* parent, const QString& name); virtual ~ClassNode() { } void addBaseClass(Access access, - ClassNode *node, + ClassNode* node, const QString &dataTypeWithTemplateArgs = ""); void fixBaseClasses(); @@ -363,12 +363,12 @@ class FakeNode : public InnerNode { public: - FakeNode(InnerNode *parent, const QString& name, SubType subType); + FakeNode(InnerNode* parent, const QString& name, SubType subType); virtual ~FakeNode() { } void setTitle(const QString &title) { tle = title; } void setSubTitle(const QString &subTitle) { stle = subTitle; } - void addGroupMember(Node *node) { gr.append(node); } + void addGroupMember(Node* node) { gr.append(node); } SubType subType() const { return sub; } QString title() const { return tle; } @@ -388,7 +388,7 @@ class FakeNode : public InnerNode class QmlClassNode : public FakeNode { public: - QmlClassNode(InnerNode *parent, + QmlClassNode(InnerNode* parent, const QString& name, const ClassNode* cn); virtual ~QmlClassNode(); @@ -411,7 +411,7 @@ class QmlClassNode : public FakeNode class QmlBasicTypeNode : public FakeNode { public: - QmlBasicTypeNode(InnerNode *parent, + QmlBasicTypeNode(InnerNode* parent, const QString& name); virtual ~QmlBasicTypeNode() { } virtual bool isQmlNode() const { return true; } @@ -498,41 +498,41 @@ class TypedefNode; class EnumNode : public LeafNode { public: - EnumNode(InnerNode *parent, const QString& name); + EnumNode(InnerNode* parent, const QString& name); virtual ~EnumNode() { } void addItem(const EnumItem& item); - void setFlagsType(TypedefNode *typedeff); + void setFlagsType(TypedefNode* typedeff); bool hasItem(const QString &name) const { return names.contains(name); } const QList& items() const { return itms; } Access itemAccess(const QString& name) const; - const TypedefNode *flagsType() const { return ft; } + const TypedefNode* flagsType() const { return ft; } QString itemValue(const QString &name) const; private: QList itms; QSet names; - const TypedefNode *ft; + const TypedefNode* ft; }; class TypedefNode : public LeafNode { public: - TypedefNode(InnerNode *parent, const QString& name); + TypedefNode(InnerNode* parent, const QString& name); virtual ~TypedefNode() { } - const EnumNode *associatedEnum() const { return ae; } + const EnumNode* associatedEnum() const { return ae; } private: - void setAssociatedEnum(const EnumNode *enume); + void setAssociatedEnum(const EnumNode* enume); friend class EnumNode; - const EnumNode *ae; + const EnumNode* ae; }; -inline void EnumNode::setFlagsType(TypedefNode *typedeff) +inline void EnumNode::setFlagsType(TypedefNode* typedeff) { ft = typedeff; typedeff->setAssociatedEnum(this); @@ -584,8 +584,8 @@ class FunctionNode : public LeafNode Native }; enum Virtualness { NonVirtual, ImpureVirtual, PureVirtual }; - FunctionNode(InnerNode *parent, const QString &name); - FunctionNode(Type type, InnerNode *parent, const QString &name, bool attached); + FunctionNode(InnerNode* parent, const QString &name); + FunctionNode(Type type, InnerNode* parent, const QString &name, bool attached); virtual ~FunctionNode() { } void setReturnType(const QString& returnType) { rt = returnType; } @@ -598,8 +598,8 @@ class FunctionNode : public LeafNode void setReimp(bool r); void addParameter(const Parameter& parameter); inline void setParameters(const QList& parameters); - void borrowParameterNames(const FunctionNode *source); - void setReimplementedFrom(FunctionNode *from); + void borrowParameterNames(const FunctionNode* source); + void setReimplementedFrom(FunctionNode* from); const QString& returnType() const { return rt; } Metaness metaness() const { return met; } @@ -616,9 +616,9 @@ class FunctionNode : public LeafNode int numOverloads() const; const QList& parameters() const { return params; } QStringList parameterNames() const; - const FunctionNode *reimplementedFrom() const { return rf; } - const QList &reimplementedBy() const { return rb; } - const PropertyNode *associatedProperty() const { return ap; } + const FunctionNode* reimplementedFrom() const { return rf; } + const QList &reimplementedBy() const { return rb; } + const PropertyNode* associatedProperty() const { return ap; } const QStringList& parentPath() const { return pp; } QStringList reconstructParams(bool values = false) const; @@ -632,7 +632,7 @@ class FunctionNode : public LeafNode void debug() const; private: - void setAssociatedProperty(PropertyNode *property); + void setAssociatedProperty(PropertyNode* property); friend class InnerNode; friend class PropertyNode; @@ -652,9 +652,9 @@ class FunctionNode : public LeafNode bool reimp: 1; bool att: 1; QList params; - const FunctionNode *rf; - const PropertyNode *ap; - QList rb; + const FunctionNode* rf; + const PropertyNode* ap; + QList rb; }; class PropertyNode : public LeafNode @@ -663,16 +663,22 @@ class PropertyNode : public LeafNode enum FunctionRole { Getter, Setter, Resetter, Notifier }; enum { NumFunctionRoles = Notifier + 1 }; - PropertyNode(InnerNode *parent, const QString& name); + PropertyNode(InnerNode* parent, const QString& name); virtual ~PropertyNode() { } void setDataType(const QString& dataType) { dt = dataType; } - void addFunction(FunctionNode *function, FunctionRole role); - void addSignal(FunctionNode *function, FunctionRole role); + void addFunction(FunctionNode* function, FunctionRole role); + void addSignal(FunctionNode* function, FunctionRole role); void setStored(bool stored) { sto = toTrool(stored); } void setDesignable(bool designable) { des = toTrool(designable); } + void setScriptable(bool scriptable) { scr = toTrool(scriptable); } void setWritable(bool writable) { wri = toTrool(writable); } - void setOverriddenFrom(const PropertyNode *baseProperty); + void setUser(bool user) { usr = toTrool(user); } + void setOverriddenFrom(const PropertyNode* baseProperty); + void setRuntimeDesFunc(const QString& rdf) { runtimeDesFunc = rdf; } + void setRuntimeScrFunc(const QString& scrf) { runtimeScrFunc = scrf; } + void setConstant() { cst = true; } + void setFinal() { fnl = true; } const QString &dataType() const { return dt; } QString qualifiedDataType() const; @@ -684,8 +690,20 @@ class PropertyNode : public LeafNode NodeList notifiers() const { return functions(Notifier); } bool isStored() const { return fromTrool(sto, storedDefault()); } bool isDesignable() const { return fromTrool(des, designableDefault()); } + bool isScriptable() const { return fromTrool(scr, scriptableDefault()); } + const QString& runtimeDesignabilityFunction() const { return runtimeDesFunc; } + const QString& runtimeScriptabilityFunction() const { return runtimeScrFunc; } bool isWritable() const { return fromTrool(wri, writableDefault()); } - const PropertyNode *overriddenFrom() const { return overrides; } + bool isUser() const { return fromTrool(usr, userDefault()); } + bool isConstant() const { return cst; } + bool isFinal() const { return fnl; } + const PropertyNode* overriddenFrom() const { return overrides; } + + bool storedDefault() const { return true; } + bool userDefault() const { return false; } + bool designableDefault() const { return !setters().isEmpty(); } + bool scriptableDefault() const { return true; } + bool writableDefault() const { return !setters().isEmpty(); } private: enum Trool { Trool_True, Trool_False, Trool_Default }; @@ -693,16 +711,18 @@ class PropertyNode : public LeafNode static Trool toTrool(bool boolean); static bool fromTrool(Trool troolean, bool defaultValue); - bool storedDefault() const { return true; } - bool designableDefault() const { return !setters().isEmpty(); } - bool writableDefault() const { return !setters().isEmpty(); } - QString dt; + QString runtimeDesFunc; + QString runtimeScrFunc; NodeList funcs[NumFunctionRoles]; Trool sto; Trool des; + Trool scr; Trool wri; - const PropertyNode *overrides; + Trool usr; + bool cst; + bool fnl; + const PropertyNode* overrides; }; inline void FunctionNode::setParameters(const QList ¶meters) @@ -710,13 +730,13 @@ inline void FunctionNode::setParameters(const QList ¶meters) params = parameters; } -inline void PropertyNode::addFunction(FunctionNode *function, FunctionRole role) +inline void PropertyNode::addFunction(FunctionNode* function, FunctionRole role) { funcs[(int)role].append(function); function->setAssociatedProperty(this); } -inline void PropertyNode::addSignal(FunctionNode *function, FunctionRole role) +inline void PropertyNode::addSignal(FunctionNode* function, FunctionRole role) { funcs[(int)role].append(function); } @@ -732,7 +752,7 @@ inline NodeList PropertyNode::functions() const class VariableNode : public LeafNode { public: - VariableNode(InnerNode *parent, const QString &name); + VariableNode(InnerNode* parent, const QString &name); virtual ~VariableNode() { } void setLeftType(const QString &leftType) { lt = leftType; } @@ -750,15 +770,16 @@ class VariableNode : public LeafNode bool sta; }; -inline VariableNode::VariableNode(InnerNode *parent, const QString &name) +inline VariableNode::VariableNode(InnerNode* parent, const QString &name) : LeafNode(Variable, parent, name), sta(false) { + // nothing. } class TargetNode : public LeafNode { public: - TargetNode(InnerNode *parent, const QString& name); + TargetNode(InnerNode* parent, const QString& name); virtual ~TargetNode() { } virtual bool isInnerNode() const; -- cgit v0.12 From 65725d65882bd821c2a704307d201d246d8342b5 Mon Sep 17 00:00:00 2001 From: Zeno Albisser Date: Fri, 25 Jun 2010 11:14:22 +0200 Subject: Fix warnings in QSslSocketPrivate::systemCaCertificates() Reviewed-by: Markus Goetz --- src/network/ssl/qsslsocket_openssl.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/network/ssl/qsslsocket_openssl.cpp b/src/network/ssl/qsslsocket_openssl.cpp index 36a0cc7..9bd93a2 100644 --- a/src/network/ssl/qsslsocket_openssl.cpp +++ b/src/network/ssl/qsslsocket_openssl.cpp @@ -574,17 +574,17 @@ QList QSslSocketPrivate::systemCaCertificates() } } #elif defined(Q_OS_AIX) - systemCerts.append(QSslCertificate::fromPath("/var/ssl/certs/*.pem", QSsl::Pem, QRegExp::Wildcard)); + systemCerts.append(QSslCertificate::fromPath(QLatin1String("/var/ssl/certs/*.pem"), QSsl::Pem, QRegExp::Wildcard)); #elif defined(Q_OS_SOLARIS) - systemCerts.append(QSslCertificate::fromPath("/usr/local/ssl/certs/*.pem", QSsl::Pem, QRegExp::Wildcard)); + systemCerts.append(QSslCertificate::fromPath(QLatin1String("/usr/local/ssl/certs/*.pem"), QSsl::Pem, QRegExp::Wildcard)); #elif defined(Q_OS_HPUX) - systemCerts.append(QSslCertificate::fromPath("/opt/openssl/certs/*.pem", QSsl::Pem, QRegExp::Wildcard)); + systemCerts.append(QSslCertificate::fromPath(QLatin1String("/opt/openssl/certs/*.pem"), QSsl::Pem, QRegExp::Wildcard)); #elif defined(Q_OS_LINUX) - systemCerts.append(QSslCertificate::fromPath("/etc/ssl/certs/*.pem", QSsl::Pem, QRegExp::Wildcard)); // (K)ubuntu, OpenSUSE, Mandriva, ... - systemCerts.append(QSslCertificate::fromPath("/etc/pki/tls/certs/ca-bundle.crt", QSsl::Pem)); // Fedora - systemCerts.append(QSslCertificate::fromPath("/usr/lib/ssl/certs/*.pem", QSsl::Pem, QRegExp::Wildcard)); // Gentoo, Mandrake - systemCerts.append(QSslCertificate::fromPath("/usr/share/ssl/*.pem", QSsl::Pem, QRegExp::Wildcard)); // Centos, Redhat, SuSE - systemCerts.append(QSslCertificate::fromPath("/usr/local/ssl/*.pem", QSsl::Pem, QRegExp::Wildcard)); // Normal OpenSSL Tarball + systemCerts.append(QSslCertificate::fromPath(QLatin1String("/etc/ssl/certs/*.pem"), QSsl::Pem, QRegExp::Wildcard)); // (K)ubuntu, OpenSUSE, Mandriva, ... + systemCerts.append(QSslCertificate::fromPath(QLatin1String("/etc/pki/tls/certs/ca-bundle.crt"), QSsl::Pem)); // Fedora + systemCerts.append(QSslCertificate::fromPath(QLatin1String("/usr/lib/ssl/certs/*.pem"), QSsl::Pem, QRegExp::Wildcard)); // Gentoo, Mandrake + systemCerts.append(QSslCertificate::fromPath(QLatin1String("/usr/share/ssl/*.pem"), QSsl::Pem, QRegExp::Wildcard)); // Centos, Redhat, SuSE + systemCerts.append(QSslCertificate::fromPath(QLatin1String("/usr/local/ssl/*.pem"), QSsl::Pem, QRegExp::Wildcard)); // Normal OpenSSL Tarball #endif return systemCerts; } -- cgit v0.12 From a144416f28ff256eed9913edc8453acb00760876 Mon Sep 17 00:00:00 2001 From: "Bradley T. Hughes" Date: Fri, 25 Jun 2010 11:21:21 +0200 Subject: QSemaphore::tryAquire(timeout) -- never times out on an active semaphore If a thread trying to acquire multiple resources is continuously preempted by threads acquiring smaller amounts, the larger consumer would end up waiting forever (instead of for the given timeout). Fix this by keeping track of elapsed time between wakeups using QElapsedTimer. Task-number: QTBUG-11500 Reviewed-by: thiago --- src/corelib/thread/qsemaphore.cpp | 7 ++++- tests/auto/qsemaphore/tst_qsemaphore.cpp | 49 ++++++++++++++++++++++++++++++-- 2 files changed, 53 insertions(+), 3 deletions(-) diff --git a/src/corelib/thread/qsemaphore.cpp b/src/corelib/thread/qsemaphore.cpp index 9dc828d..8e8a88a 100644 --- a/src/corelib/thread/qsemaphore.cpp +++ b/src/corelib/thread/qsemaphore.cpp @@ -44,6 +44,8 @@ #ifndef QT_NO_THREAD #include "qmutex.h" #include "qwaitcondition.h" +#include "qelapsedtimer.h" +#include "qdatetime.h" QT_BEGIN_NAMESPACE @@ -218,8 +220,11 @@ bool QSemaphore::tryAcquire(int n, int timeout) while (n > d->avail) d->cond.wait(locker.mutex()); } else { + QElapsedTimer timer; + timer.start(); while (n > d->avail) { - if (!d->cond.wait(locker.mutex(), timeout)) + if (timer.hasExpired(timeout) + || !d->cond.wait(locker.mutex(), timeout - timer.elapsed())) return false; } } diff --git a/tests/auto/qsemaphore/tst_qsemaphore.cpp b/tests/auto/qsemaphore/tst_qsemaphore.cpp index ace33dc..7cede30 100644 --- a/tests/auto/qsemaphore/tst_qsemaphore.cpp +++ b/tests/auto/qsemaphore/tst_qsemaphore.cpp @@ -63,6 +63,7 @@ private slots: void tryAcquire(); void tryAcquireWithTimeout_data(); void tryAcquireWithTimeout(); + void tryAcquireWithTimeoutStarvation(); void release(); void available(); void producerConsumer(); @@ -232,8 +233,8 @@ void tst_QSemaphore::tryAcquireWithTimeout_data() { QTest::addColumn("timeout"); - QTest::newRow("") << 1000; - QTest::newRow("") << 10000; + QTest::newRow("1s") << 1000; + QTest::newRow("10s") << 10000; } void tst_QSemaphore::tryAcquireWithTimeout() @@ -316,6 +317,50 @@ void tst_QSemaphore::tryAcquireWithTimeout() QCOMPARE(semaphore.available(), 0); } +void tst_QSemaphore::tryAcquireWithTimeoutStarvation() +{ + class Thread : public QThread + { + public: + QSemaphore startup; + QSemaphore *semaphore; + int amountToConsume, timeout; + + void run() + { + startup.release(); + forever { + if (!semaphore->tryAcquire(amountToConsume, timeout)) + break; + semaphore->release(amountToConsume); + } + } + }; + + QSemaphore semaphore; + semaphore.release(1); + + Thread consumer; + consumer.semaphore = &semaphore; + consumer.amountToConsume = 1; + consumer.timeout = 1000; + + // start the thread and wait for it to start consuming + consumer.start(); + consumer.startup.acquire(); + + // try to consume more than the thread we started is, and provide a longer + // timeout... we should timeout, not wait indefinitely + QVERIFY(!semaphore.tryAcquire(consumer.amountToConsume * 2, consumer.timeout * 2)); + + // the consumer should still be running + QVERIFY(consumer.isRunning() && !consumer.isFinished()); + + // acquire, and wait for smallConsumer to timeout + semaphore.acquire(); + QVERIFY(consumer.wait()); +} + void tst_QSemaphore::release() { DEPENDS_ON("acquire"); } -- cgit v0.12 From 451a017e4d819a53d22b5dd5b562f99bda7ac087 Mon Sep 17 00:00:00 2001 From: Martin Smith Date: Fri, 25 Jun 2010 13:29:45 +0200 Subject: doc: Added more DITA output to the XML generator Output the \variable stuff as a cxxVariable. Task-number: QTBUG-11391 --- tools/qdoc3/codechunk.h | 2 +- tools/qdoc3/ditaxmlgenerator.cpp | 72 ++++++++++++++++++++++++++++++++++++---- 2 files changed, 66 insertions(+), 8 deletions(-) diff --git a/tools/qdoc3/codechunk.h b/tools/qdoc3/codechunk.h index e78873c..a0c554e 100644 --- a/tools/qdoc3/codechunk.h +++ b/tools/qdoc3/codechunk.h @@ -55,7 +55,7 @@ QT_BEGIN_NAMESPACE /* The CodeChunk class represents a tiny piece of C++ code. - The class provides convertion between a list of lexemes and a string. It adds + The class provides conversion between a list of lexemes and a string. It adds spaces at the right place for consistent style. The tiny pieces of code it represents are data types, enum values, and default parameter values. diff --git a/tools/qdoc3/ditaxmlgenerator.cpp b/tools/qdoc3/ditaxmlgenerator.cpp index 852d209..0135983 100644 --- a/tools/qdoc3/ditaxmlgenerator.cpp +++ b/tools/qdoc3/ditaxmlgenerator.cpp @@ -4573,7 +4573,8 @@ void DitaXmlGenerator::writeLocation(const Node* n) s2 = CXXTYPEDEFDECLARATIONFILE; s3 = CXXTYPEDEFDECLARATIONFILELINE; } - else if (n->type() == Node::Property) { + else if ((n->type() == Node::Property) || + (n->type() == Node::Variable)) { s1 = CXXVARIABLEAPIITEMLOCATION; s2 = CXXVARIABLEDECLARATIONFILE; s3 = CXXVARIABLEDECLARATIONFILELINE; @@ -4716,6 +4717,8 @@ void DitaXmlGenerator::writeParameters(const FunctionNode* fn, CodeMarker* marke writer.writeStartElement(CXXFUNCTIONPARAMETER); writer.writeStartElement(CXXFUNCTIONPARAMETERDECLAREDTYPE); writer.writeCharacters((*p).leftType()); + if (!(*p).rightType().isEmpty()) + writer.writeCharacters((*p).rightType()); writer.writeEndElement(); // writer.writeStartElement(CXXFUNCTIONPARAMETERDECLARATIONNAME); writer.writeCharacters((*p).name()); @@ -4888,12 +4891,6 @@ void DitaXmlGenerator::writeTypedefs(const Section& s, } } -void DitaXmlGenerator::writeDataMembers(const Section& s, - const ClassNode* cn, - CodeMarker* marker) -{ -} - void DitaXmlGenerator::writeProperties(const Section& s, const ClassNode* cn, CodeMarker* marker) @@ -4992,6 +4989,67 @@ void DitaXmlGenerator::writeProperties(const Section& s, } } +void DitaXmlGenerator::writeDataMembers(const Section& s, + const ClassNode* cn, + CodeMarker* marker) +{ + NodeList::ConstIterator m = s.members.begin(); + while (m != s.members.end()) { + if ((*m)->type() == Node::Variable) { + const VariableNode* vn = static_cast(*m); + writer.writeStartElement(CXXVARIABLE); + writer.writeAttribute("id",vn->guid()); + writer.writeStartElement(APINAME); + writer.writeCharacters(vn->name()); + writer.writeEndElement(); // + generateBrief(vn,marker); + writer.writeStartElement(CXXVARIABLEDETAIL); + writer.writeStartElement(CXXVARIABLEDEFINITION); + writer.writeStartElement(CXXVARIABLEACCESSSPECIFIER); + writer.writeAttribute("value",vn->accessString()); + writer.writeEndElement(); // + + writer.writeStartElement(CXXVARIABLEDECLAREDTYPE); + writer.writeCharacters(vn->leftType()); + if (!vn->rightType().isEmpty()) + writer.writeCharacters(vn->rightType()); + writer.writeEndElement(); // + + QString fq = fullQualification(vn); + if (!fq.isEmpty()) { + writer.writeStartElement(CXXVARIABLESCOPEDNAME); + writer.writeCharacters(fq); + writer.writeEndElement(); // + } + + writer.writeStartElement(CXXVARIABLEPROTOTYPE); + writer.writeCharacters(vn->leftType() + " "); + //writer.writeCharacters(vn->parent()->name() + "::" + vn->name()); + writer.writeCharacters(vn->name()); + if (!vn->rightType().isEmpty()) + writer.writeCharacters(vn->rightType()); + writer.writeEndElement(); // + + writer.writeStartElement(CXXVARIABLENAMELOOKUP); + writer.writeCharacters(vn->parent()->name() + "::" + vn->name()); + writer.writeEndElement(); // + + writeLocation(vn); + writer.writeEndElement(); // + writer.writeStartElement(APIDESC); + + if (!vn->doc().isEmpty()) { + generateBody(vn, marker); + } + + writer.writeEndElement(); // + writer.writeEndElement(); // + writer.writeEndElement(); // + } + ++m; + } +} + void DitaXmlGenerator::writerFunctions(const QString& tag, const NodeList& nlist) { NodeList::const_iterator n = nlist.begin(); -- cgit v0.12 From 287f6e933add5dc822c484170c5fece25c7ac846 Mon Sep 17 00:00:00 2001 From: Morten Engvoldsen Date: Fri, 25 Jun 2010 14:08:21 +0200 Subject: Doc: fixing search bug --- tools/qdoc3/htmlgenerator.cpp | 12 +++++++++++- tools/qdoc3/test/qt-html-templates.qdocconf | 6 ++++-- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/tools/qdoc3/htmlgenerator.cpp b/tools/qdoc3/htmlgenerator.cpp index 339c390..9e16676 100644 --- a/tools/qdoc3/htmlgenerator.cpp +++ b/tools/qdoc3/htmlgenerator.cpp @@ -1890,7 +1890,17 @@ void HtmlGenerator::generateFooter(const Node *node) } else { - out() << " \n"; + out() << " \n";\n"; + out() << " \n"; out() << "\n"; } out() << "\n"; diff --git a/tools/qdoc3/test/qt-html-templates.qdocconf b/tools/qdoc3/test/qt-html-templates.qdocconf index 1fb000b..b82e337 100644 --- a/tools/qdoc3/test/qt-html-templates.qdocconf +++ b/tools/qdoc3/test/qt-html-templates.qdocconf @@ -11,7 +11,7 @@ HTML.postheader = "
\n" \ " Qt Reference Documentation\n" \ "
\n" \ "
\n" \ - " \n" \ + " \n" \ "
\n" \ "
\n" \ "
\n" \ @@ -160,7 +160,9 @@ HTML.footer = " \n" \ "
\n" \ "
X
\n" \ "
\n" \ - "

\n" \ + "

Thank you for giving your feedback.

Make sure it is related the page. For more general bugs and \n" \ + " requests, please use the Qt Bug Tracker

\n" \ + "

\n" \ "

\n" \ "
\n" \ "
\n" \ -- cgit v0.12 From 075648e46650797f2b520f98513a7aed9f0ffec7 Mon Sep 17 00:00:00 2001 From: Harald Fernengel Date: Fri, 25 Jun 2010 15:47:58 +0200 Subject: Warn if surface creation fails MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Output the same warning that qegl.cpp does also in the X11 implementation. Reviewed-by: Trond Kjernåsen --- src/gui/egl/qegl_x11.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/gui/egl/qegl_x11.cpp b/src/gui/egl/qegl_x11.cpp index 969acc4..fea6e8d 100644 --- a/src/gui/egl/qegl_x11.cpp +++ b/src/gui/egl/qegl_x11.cpp @@ -415,7 +415,10 @@ EGLSurface QEgl::createSurface(QPaintDevice *device, EGLConfig config, const QEg // At this point, the widget's window should be created and have the correct visual. Now we // just need to create the EGL surface for it: - return eglCreateWindowSurface(QEgl::display(), config, (EGLNativeWindowType)widget->winId(), 0); + EGLSurface surf = eglCreateWindowSurface(QEgl::display(), config, (EGLNativeWindowType)widget->winId(), 0); + if (surf == EGL_NO_SURFACE) + qWarning("QEglContext::createSurface(): Unable to create EGL surface, error = 0x%x", eglGetError()); + return surf; } if (x11PixmapData) { -- cgit v0.12 From 860094d4e2614c0926f2af0e3538412ece31f726 Mon Sep 17 00:00:00 2001 From: Benjamin Poulain Date: Fri, 25 Jun 2010 16:05:25 +0200 Subject: Avoid memory allocation when converting from Gbk to unicode. This change is the equivalent of 19e1b32bdeeeb5c7865038cab97b40dbac0e6c42 and 987458462994497f764baf253baca0faabdb63cc but for the Gbk case. It improve performance by avoiding the constructor of QChar and by allocating the memory once instead of doing it for each character. This also fix QTBUG-11704. Reviewed-by: Andreas Kling --- src/plugins/codecs/cn/qgb18030codec.cpp | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/src/plugins/codecs/cn/qgb18030codec.cpp b/src/plugins/codecs/cn/qgb18030codec.cpp index 3f2eec7..e10c8b1 100644 --- a/src/plugins/codecs/cn/qgb18030codec.cpp +++ b/src/plugins/codecs/cn/qgb18030codec.cpp @@ -319,7 +319,7 @@ QString QGbkCodec::convertToUnicode(const char* chars, int len, ConverterState * { uchar buf[2]; int nbuf = 0; - QChar replacement = QChar::ReplacementCharacter; + ushort replacement = QChar::ReplacementCharacter; if (state) { if (state->flags & ConvertInvalidToNull) replacement = QChar::Null; @@ -330,6 +330,9 @@ QString QGbkCodec::convertToUnicode(const char* chars, int len, ConverterState * int invalid = 0; QString result; + result.resize(len); + int unicodeLen = 0; + ushort *const resultData = reinterpret_cast(result.data()); //qDebug("QGbkDecoder::toUnicode(const char* chars = \"%s\", int len = %d)", chars, len); for (int i=0; i(u)); + ++unicodeLen; } else { - result += replacement; + resultData[unicodeLen] = replacement; + ++unicodeLen; ++invalid; } nbuf = 0; } else { // Error - result += replacement; + resultData[unicodeLen] = replacement; + ++unicodeLen; ++invalid; nbuf = 0; } break; } } + result.resize(unicodeLen); if (state) { state->remainingChars = nbuf; -- cgit v0.12 From 0fa3175421a3329fe4cb3fb9f79f30807105b02f Mon Sep 17 00:00:00 2001 From: Kent Hansen Date: Fri, 25 Jun 2010 14:51:12 +0200 Subject: Fix conversion between JavaScript Date and QDateTime Use JavaScriptCore's conversion functions rather than our own (incomplete) implementation. Specifically, this means daylight saving time is finally handled correctly on Windows. Task-number: QTBUG-9770 Reviewed-by: Olivier Goffart --- src/script/api/qscriptengine.cpp | 47 +++++ src/script/api/qscriptengine_p.h | 10 +- src/script/script.pri | 1 - src/script/utils/qscriptdate.cpp | 365 --------------------------------------- src/script/utils/qscriptdate_p.h | 52 ------ src/script/utils/utils.pri | 5 - 6 files changed, 53 insertions(+), 427 deletions(-) delete mode 100644 src/script/utils/qscriptdate.cpp delete mode 100644 src/script/utils/qscriptdate_p.h delete mode 100644 src/script/utils/utils.pri diff --git a/src/script/api/qscriptengine.cpp b/src/script/api/qscriptengine.cpp index 655026c..7bccffe 100644 --- a/src/script/api/qscriptengine.cpp +++ b/src/script/api/qscriptengine.cpp @@ -438,6 +438,53 @@ qsreal ToNumber(const QString &value) #endif +static const qsreal MsPerSecond = 1000.0; + +static inline int MsFromTime(qsreal t) +{ + int r = int(::fmod(t, MsPerSecond)); + return (r >= 0) ? r : r + int(MsPerSecond); +} + +/*! + \internal + Converts a JS date value (milliseconds) to a QDateTime (local time). +*/ +QDateTime MsToDateTime(JSC::ExecState *exec, qsreal t) +{ + if (qIsNaN(t)) + return QDateTime(); + JSC::GregorianDateTime tm; + JSC::msToGregorianDateTime(exec, t, /*output UTC=*/true, tm); + int ms = MsFromTime(t); + QDateTime convertedUTC = QDateTime(QDate(tm.year + 1900, tm.month + 1, tm.monthDay), + QTime(tm.hour, tm.minute, tm.second, ms), Qt::UTC); + return convertedUTC.toLocalTime(); +} + +/*! + \internal + Converts a QDateTime to a JS date value (milliseconds). +*/ +qsreal DateTimeToMs(JSC::ExecState *exec, const QDateTime &dt) +{ + if (!dt.isValid()) + return qSNaN(); + QDateTime utc = dt.toUTC(); + QDate date = utc.date(); + QTime time = utc.time(); + JSC::GregorianDateTime tm; + tm.year = date.year() - 1900; + tm.month = date.month() - 1; + tm.monthDay = date.day(); + tm.weekDay = date.dayOfWeek(); + tm.yearDay = date.dayOfYear(); + tm.hour = time.hour(); + tm.minute = time.minute(); + tm.second = time.second(); + return JSC::gregorianDateTimeToMS(exec, tm, time.msec(), /*inputIsUTC=*/true); +} + void GlobalClientData::mark(JSC::MarkStack& markStack) { engine->mark(markStack); diff --git a/src/script/api/qscriptengine_p.h b/src/script/api/qscriptengine_p.h index 1b35704..c71465d 100644 --- a/src/script/api/qscriptengine_p.h +++ b/src/script/api/qscriptengine_p.h @@ -50,7 +50,6 @@ #include "bridge/qscriptobject_p.h" #include "bridge/qscriptqobject_p.h" #include "bridge/qscriptvariant_p.h" -#include "utils/qscriptdate_p.h" #include "DateConstructor.h" #include "DateInstance.h" @@ -119,6 +118,9 @@ namespace QScript inline QString ToString(qsreal); #endif + QDateTime MsToDateTime(JSC::ExecState *, qsreal); + qsreal DateTimeToMs(JSC::ExecState *, const QDateTime &); + //some conversion helper functions inline QScriptEnginePrivate *scriptEngineFromExec(const JSC::ExecState *exec); bool isFunction(JSC::JSValue value); @@ -861,7 +863,7 @@ inline JSC::JSValue QScriptEnginePrivate::newDate(JSC::ExecState *exec, qsreal v inline JSC::JSValue QScriptEnginePrivate::newDate(JSC::ExecState *exec, const QDateTime &value) { - return newDate(exec, QScript::FromDateTime(value)); + return newDate(exec, QScript::DateTimeToMs(exec, value)); } inline JSC::JSValue QScriptEnginePrivate::newObject() @@ -994,12 +996,12 @@ inline JSC::UString QScriptEnginePrivate::toString(JSC::ExecState *exec, JSC::JS return str; } -inline QDateTime QScriptEnginePrivate::toDateTime(JSC::ExecState *, JSC::JSValue value) +inline QDateTime QScriptEnginePrivate::toDateTime(JSC::ExecState *exec, JSC::JSValue value) { if (!isDate(value)) return QDateTime(); qsreal t = static_cast(JSC::asObject(value))->internalNumber(); - return QScript::ToDateTime(t, Qt::LocalTime); + return QScript::MsToDateTime(exec, t); } inline QObject *QScriptEnginePrivate::toQObject(JSC::ExecState *exec, JSC::JSValue value) diff --git a/src/script/script.pri b/src/script/script.pri index 2ee1a82..9cd71d3 100644 --- a/src/script/script.pri +++ b/src/script/script.pri @@ -1,4 +1,3 @@ include($$PWD/api/api.pri) include($$PWD/bridge/bridge.pri) include($$PWD/parser/parser.pri) -include($$PWD/utils/utils.pri) diff --git a/src/script/utils/qscriptdate.cpp b/src/script/utils/qscriptdate.cpp deleted file mode 100644 index 5980256..0000000 --- a/src/script/utils/qscriptdate.cpp +++ /dev/null @@ -1,365 +0,0 @@ -/**************************************************************************** -** -** 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 QtScript module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL-ONLY$ -** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qscriptdate_p.h" - -#include -#include - -#include - -#ifndef Q_WS_WIN -# include -# include -#else -# include -#endif - -QT_BEGIN_NAMESPACE - -namespace QScript { - -qsreal ToInteger(qsreal n); - -static const qsreal HoursPerDay = 24.0; -static const qsreal MinutesPerHour = 60.0; -static const qsreal SecondsPerMinute = 60.0; -static const qsreal msPerSecond = 1000.0; -static const qsreal msPerMinute = 60000.0; -static const qsreal msPerHour = 3600000.0; -static const qsreal msPerDay = 86400000.0; - -static qsreal LocalTZA = 0.0; // initialized at startup - -static inline qsreal TimeWithinDay(qsreal t) -{ - qsreal r = ::fmod(t, msPerDay); - return (r >= 0) ? r : r + msPerDay; -} - -static inline int HourFromTime(qsreal t) -{ - int r = int(::fmod(::floor(t / msPerHour), HoursPerDay)); - return (r >= 0) ? r : r + int(HoursPerDay); -} - -static inline int MinFromTime(qsreal t) -{ - int r = int(::fmod(::floor(t / msPerMinute), MinutesPerHour)); - return (r >= 0) ? r : r + int(MinutesPerHour); -} - -static inline int SecFromTime(qsreal t) -{ - int r = int(::fmod(::floor(t / msPerSecond), SecondsPerMinute)); - return (r >= 0) ? r : r + int(SecondsPerMinute); -} - -static inline int msFromTime(qsreal t) -{ - int r = int(::fmod(t, msPerSecond)); - return (r >= 0) ? r : r + int(msPerSecond); -} - -static inline qsreal Day(qsreal t) -{ - return ::floor(t / msPerDay); -} - -static inline qsreal DaysInYear(qsreal y) -{ - if (::fmod(y, 4)) - return 365; - - else if (::fmod(y, 100)) - return 366; - - else if (::fmod(y, 400)) - return 365; - - return 366; -} - -static inline qsreal DayFromYear(qsreal y) -{ - return 365 * (y - 1970) - + ::floor((y - 1969) / 4) - - ::floor((y - 1901) / 100) - + ::floor((y - 1601) / 400); -} - -static inline qsreal TimeFromYear(qsreal y) -{ - return msPerDay * DayFromYear(y); -} - -static inline qsreal YearFromTime(qsreal t) -{ - int y = 1970; - y += (int) ::floor(t / (msPerDay * 365.2425)); - - qsreal t2 = TimeFromYear(y); - return (t2 > t) ? y - 1 : ((t2 + msPerDay * DaysInYear(y)) <= t) ? y + 1 : y; -} - -static inline bool InLeapYear(qsreal t) -{ - qsreal x = DaysInYear(YearFromTime(t)); - if (x == 365) - return 0; - - Q_ASSERT (x == 366); - return 1; -} - -static inline qsreal DayWithinYear(qsreal t) -{ - return Day(t) - DayFromYear(YearFromTime(t)); -} - -static inline qsreal MonthFromTime(qsreal t) -{ - qsreal d = DayWithinYear(t); - qsreal l = InLeapYear(t); - - if (d < 31.0) - return 0; - - else if (d < 59.0 + l) - return 1; - - else if (d < 90.0 + l) - return 2; - - else if (d < 120.0 + l) - return 3; - - else if (d < 151.0 + l) - return 4; - - else if (d < 181.0 + l) - return 5; - - else if (d < 212.0 + l) - return 6; - - else if (d < 243.0 + l) - return 7; - - else if (d < 273.0 + l) - return 8; - - else if (d < 304.0 + l) - return 9; - - else if (d < 334.0 + l) - return 10; - - else if (d < 365.0 + l) - return 11; - - return qSNaN(); // ### assert? -} - -static inline qsreal DateFromTime(qsreal t) -{ - int m = (int) ToInteger(MonthFromTime(t)); - qsreal d = DayWithinYear(t); - qsreal l = InLeapYear(t); - - switch (m) { - case 0: return d + 1.0; - case 1: return d - 30.0; - case 2: return d - 58.0 - l; - case 3: return d - 89.0 - l; - case 4: return d - 119.0 - l; - case 5: return d - 150.0 - l; - case 6: return d - 180.0 - l; - case 7: return d - 211.0 - l; - case 8: return d - 242.0 - l; - case 9: return d - 272.0 - l; - case 10: return d - 303.0 - l; - case 11: return d - 333.0 - l; - } - - return qSNaN(); // ### assert -} - -static inline qsreal WeekDay(qsreal t) -{ - qsreal r = ::fmod (Day(t) + 4.0, 7.0); - return (r >= 0) ? r : r + 7.0; -} - - -static inline qsreal MakeTime(qsreal hour, qsreal min, qsreal sec, qsreal ms) -{ - return ((hour * MinutesPerHour + min) * SecondsPerMinute + sec) * msPerSecond + ms; -} - -static inline qsreal DayFromMonth(qsreal month, qsreal leap) -{ - switch ((int) month) { - case 0: return 0; - case 1: return 31.0; - case 2: return 59.0 + leap; - case 3: return 90.0 + leap; - case 4: return 120.0 + leap; - case 5: return 151.0 + leap; - case 6: return 181.0 + leap; - case 7: return 212.0 + leap; - case 8: return 243.0 + leap; - case 9: return 273.0 + leap; - case 10: return 304.0 + leap; - case 11: return 334.0 + leap; - } - - return qSNaN(); // ### assert? -} - -static qsreal MakeDay(qsreal year, qsreal month, qsreal day) -{ - year += ::floor(month / 12.0); - - month = ::fmod(month, 12.0); - if (month < 0) - month += 12.0; - - qsreal t = TimeFromYear(year); - qsreal leap = InLeapYear(t); - - day += ::floor(t / msPerDay); - day += DayFromMonth(month, leap); - - return day - 1; -} - -static inline qsreal MakeDate(qsreal day, qsreal time) -{ - return day * msPerDay + time; -} - -static inline qsreal DaylightSavingTA(double t) -{ -#ifndef Q_WS_WIN - long int tt = (long int)(t / msPerSecond); - struct tm *tmtm = localtime((const time_t*)&tt); - if (! tmtm) - return 0; - return (tmtm->tm_isdst > 0) ? msPerHour : 0; -#else - Q_UNUSED(t); - /// ### implement me - return 0; -#endif -} - -static inline qsreal LocalTime(qsreal t) -{ - return t + LocalTZA + DaylightSavingTA(t); -} - -static inline qsreal UTC(qsreal t) -{ - return t - LocalTZA - DaylightSavingTA(t - LocalTZA); -} - -static inline qsreal TimeClip(qsreal t) -{ - if (! qIsFinite(t) || fabs(t) > 8.64e15) - return qSNaN(); - return ToInteger(t); -} - -static qsreal getLocalTZA() -{ -#ifndef Q_WS_WIN - struct tm* t; - time_t curr; - time(&curr); - t = localtime(&curr); - time_t locl = mktime(t); - t = gmtime(&curr); - time_t globl = mktime(t); - return double(locl - globl) * 1000.0; -#else - TIME_ZONE_INFORMATION tzInfo; - GetTimeZoneInformation(&tzInfo); - return -tzInfo.Bias * 60.0 * 1000.0; -#endif -} - -/*! - \internal - - Converts the QDateTime \a dt to an ECMA Date value (in UTC form). -*/ -qsreal FromDateTime(const QDateTime &dt) -{ - if (!dt.isValid()) - return qSNaN(); - if (!LocalTZA) // ### move - LocalTZA = getLocalTZA(); - QDate date = dt.date(); - QTime taim = dt.time(); - int year = date.year(); - int month = date.month() - 1; - int day = date.day(); - int hours = taim.hour(); - int mins = taim.minute(); - int secs = taim.second(); - int ms = taim.msec(); - double t = MakeDate(MakeDay(year, month, day), - MakeTime(hours, mins, secs, ms)); - if (dt.timeSpec() == Qt::LocalTime) - t = UTC(t); - return TimeClip(t); -} - -/*! - \internal - - Converts the ECMA Date value \tt (in UTC form) to QDateTime - according to \a spec. -*/ -QDateTime ToDateTime(qsreal t, Qt::TimeSpec spec) -{ - if (qIsNaN(t)) - return QDateTime(); - if (!LocalTZA) // ### move - LocalTZA = getLocalTZA(); - if (spec == Qt::LocalTime) - t = LocalTime(t); - int year = int(YearFromTime(t)); - int month = int(MonthFromTime(t) + 1); - int day = int(DateFromTime(t)); - int hours = HourFromTime(t); - int mins = MinFromTime(t); - int secs = SecFromTime(t); - int ms = msFromTime(t); - return QDateTime(QDate(year, month, day), QTime(hours, mins, secs, ms), spec); -} - -} // namespace QScript - -QT_END_NAMESPACE diff --git a/src/script/utils/qscriptdate_p.h b/src/script/utils/qscriptdate_p.h deleted file mode 100644 index b9c9fd4..0000000 --- a/src/script/utils/qscriptdate_p.h +++ /dev/null @@ -1,52 +0,0 @@ -/**************************************************************************** -** -** 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 QtScript module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL-ONLY$ -** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QSCRIPTDATE_P_H -#define QSCRIPTDATE_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include - -QT_BEGIN_NAMESPACE - -typedef double qsreal; - -namespace QScript -{ - qsreal FromDateTime(const QDateTime &dt); - QDateTime ToDateTime(qsreal t, Qt::TimeSpec spec); -} - -QT_END_NAMESPACE - -#endif diff --git a/src/script/utils/utils.pri b/src/script/utils/utils.pri deleted file mode 100644 index d8302d5..0000000 --- a/src/script/utils/utils.pri +++ /dev/null @@ -1,5 +0,0 @@ -SOURCES += \ - $$PWD/qscriptdate.cpp - -HEADERS += \ - $$PWD/qscriptdate_p.h -- cgit v0.12 From ea2ec1a4621bd80b3279ddc67e52cd16084a409b Mon Sep 17 00:00:00 2001 From: Harald Fernengel Date: Fri, 25 Jun 2010 16:23:41 +0200 Subject: Add qDebug() operator for QGLFormat MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Very handy to trace GL issues on a device with broken gdb Reviewed-by: Trond Kjernåsen --- src/opengl/qgl.cpp | 26 ++++++++++++++++++++++++++ src/opengl/qgl.h | 7 +++++++ 2 files changed, 33 insertions(+) diff --git a/src/opengl/qgl.cpp b/src/opengl/qgl.cpp index b4c85ac..9effb34 100644 --- a/src/opengl/qgl.cpp +++ b/src/opengl/qgl.cpp @@ -1521,6 +1521,32 @@ bool operator==(const QGLFormat& a, const QGLFormat& b) && a.d->profile == b.d->profile); } +#ifndef QT_NO_DEBUG_STREAM +QDebug operator<<(QDebug dbg, const QGLFormat &f) +{ + const QGLFormatPrivate * const d = f.d; + + dbg.nospace() << "QGLFormat(" + << "options " << d->opts + << ", plane " << d->pln + << ", depthBufferSize " << d->depthSize + << ", accumBufferSize " << d->accumSize + << ", stencilBufferSize " << d->stencilSize + << ", redBufferSize " << d->redSize + << ", greenBufferSize " << d->greenSize + << ", blueBufferSize " << d->blueSize + << ", alphaBufferSize " << d->alphaSize + << ", samples " << d->numSamples + << ", swapInterval " << d->swapInterval + << ", majorVersion " << d->majorVersion + << ", minorVersion " << d->minorVersion + << ", profile " << d->profile + << ')'; + + return dbg.space(); +} +#endif + /*! Returns false if all the options of the two QGLFormat objects diff --git a/src/opengl/qgl.h b/src/opengl/qgl.h index f0b36f7..f85cad5 100644 --- a/src/opengl/qgl.h +++ b/src/opengl/qgl.h @@ -281,6 +281,9 @@ private: friend Q_OPENGL_EXPORT bool operator==(const QGLFormat&, const QGLFormat&); friend Q_OPENGL_EXPORT bool operator!=(const QGLFormat&, const QGLFormat&); +#ifndef QT_NO_DEBUG_STREAM + friend Q_OPENGL_EXPORT QDebug operator<<(QDebug, const QGLFormat &); +#endif }; Q_DECLARE_OPERATORS_FOR_FLAGS(QGLFormat::OpenGLVersionFlags) @@ -288,6 +291,10 @@ Q_DECLARE_OPERATORS_FOR_FLAGS(QGLFormat::OpenGLVersionFlags) Q_OPENGL_EXPORT bool operator==(const QGLFormat&, const QGLFormat&); Q_OPENGL_EXPORT bool operator!=(const QGLFormat&, const QGLFormat&); +#ifndef QT_NO_DEBUG_STREAM +Q_OPENGL_EXPORT QDebug operator<<(QDebug, const QGLFormat &); +#endif + class Q_OPENGL_EXPORT QGLContext { Q_DECLARE_PRIVATE(QGLContext) -- cgit v0.12 From 8c39d25f58dbf5b401e102d73eb2371c68be141e Mon Sep 17 00:00:00 2001 From: Mark Brand Date: Sat, 26 Jun 2010 21:25:15 +0200 Subject: Corrected filename case for wincrypt.h The case doesn't matter when building on Windows, but does when cross-compiling on Unix. Merge-request: 709 Reviewed-by: Andreas Kling --- src/network/ssl/qsslsocket_p.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/network/ssl/qsslsocket_p.h b/src/network/ssl/qsslsocket_p.h index 42ae98f..d3c3858 100644 --- a/src/network/ssl/qsslsocket_p.h +++ b/src/network/ssl/qsslsocket_p.h @@ -73,7 +73,7 @@ QT_BEGIN_NAMESPACE typedef OSStatus (*PtrSecTrustSettingsCopyCertificates)(int, CFArrayRef*); typedef OSStatus (*PtrSecTrustCopyAnchorCertificates)(CFArrayRef*); #elif defined(Q_OS_WIN) -#include +#include #ifndef HCRYPTPROV_LEGACY #define HCRYPTPROV_LEGACY HCRYPTPROV #endif -- cgit v0.12 From 1a72f98a15ef78004894dc6636b8a5d969d66fde Mon Sep 17 00:00:00 2001 From: Rohan McGovern Date: Sun, 27 Jun 2010 09:28:54 +1000 Subject: Fixed copy-paste error in htmlgenerator.cpp MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes: htmlgenerator.cpp:1893: error: stray ‘\’ in program --- tools/qdoc3/htmlgenerator.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/qdoc3/htmlgenerator.cpp b/tools/qdoc3/htmlgenerator.cpp index 9e16676..b93db4f 100644 --- a/tools/qdoc3/htmlgenerator.cpp +++ b/tools/qdoc3/htmlgenerator.cpp @@ -1890,7 +1890,7 @@ void HtmlGenerator::generateFooter(const Node *node) } else { - out() << " \n";\n"; + out() << " \n"; out() << "