From 925366b08087f82b6b3d74c167946dd07e73b5c1 Mon Sep 17 00:00:00 2001 From: Warwick Allison Date: Tue, 20 Oct 2009 15:29:51 +1000 Subject: typo QT-2335 --- src/declarative/qml/qmlsqldatabase.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/declarative/qml/qmlsqldatabase.cpp b/src/declarative/qml/qmlsqldatabase.cpp index 4a5983d..9e39ffc 100644 --- a/src/declarative/qml/qmlsqldatabase.cpp +++ b/src/declarative/qml/qmlsqldatabase.cpp @@ -340,7 +340,7 @@ static QScriptValue qmlsqldatabase_open(QScriptContext *context, QScriptEngine * QString basename = QmlEnginePrivate::get(engine)->offlineStoragePath + QLatin1String("/Databases/"); QDir().mkpath(basename); basename += dbid; - database.setDatabaseName(basename+QLatin1String(".sqllite")); + database.setDatabaseName(basename+QLatin1String(".sqlite")); QSettings ini(basename+QLatin1String(".ini"),QSettings::IniFormat); ini.setValue(QLatin1String("Name"), dbname); ini.setValue(QLatin1String("Version"), dbversion); -- cgit v0.12 From 5b3e751f4c19ec05c72f212ff0ce672d982c490d Mon Sep 17 00:00:00 2001 From: Warwick Allison Date: Tue, 20 Oct 2009 15:33:32 +1000 Subject: doc now in globalobject.qdoc, not README QT-2335 --- examples/declarative/sql/README | 7 - examples/declarative/sql/hello.qml | 7 +- tools/qdoc3/qmlcodemarker.cpp | 1175 ++++++++++++++++++++++++++++++++++++ tools/qdoc3/qmlcodemarker.h | 96 +++ 4 files changed, 1277 insertions(+), 8 deletions(-) delete mode 100644 examples/declarative/sql/README create mode 100644 tools/qdoc3/qmlcodemarker.cpp create mode 100644 tools/qdoc3/qmlcodemarker.h diff --git a/examples/declarative/sql/README b/examples/declarative/sql/README deleted file mode 100644 index a7baab2..0000000 --- a/examples/declarative/sql/README +++ /dev/null @@ -1,7 +0,0 @@ -Simple demonstration of HTML5-compatible SQL database interface. -Adds another "hello, world" every time you run it. -Database is stored in: - - %APPDATA%/Nokia/Qt/QML/Databases/ (Windows) - - ~/.local/share/Nokia/Qt/QML/Databases/ (Unix) - - ~/Library/Application Support/Nokia/Qt/QML/Databases/ (Mac OS X) -No quota management. diff --git a/examples/declarative/sql/hello.qml b/examples/declarative/sql/hello.qml index 20ea611..dc3ca35 100644 --- a/examples/declarative/sql/hello.qml +++ b/examples/declarative/sql/hello.qml @@ -3,12 +3,17 @@ import Qt 4.6 Text { Script { function findGreetings() { - var db = openDatabase("QmlExampleDB", "", "The Example QML SQL!", 1000000); + var db = openDatabase("QmlExampleDB", "1.0", "The Example QML SQL!", 1000000); db.transaction( function(tx) { + // Create the database if it doesn't already exist tx.executeSql('CREATE TABLE IF NOT EXISTS Greeting(salutation TEXT, salutee TEXT)', []); + + // Add (another) greeting row tx.executeSql('INSERT INTO Greeting VALUES(?, ?)', [ 'hello', 'world' ]); + + // Show all added greetings tx.executeSql('SELECT * FROM Greeting', [], function(tx, rs) { var r = "" diff --git a/tools/qdoc3/qmlcodemarker.cpp b/tools/qdoc3/qmlcodemarker.cpp new file mode 100644 index 0000000..1062f9c --- /dev/null +++ b/tools/qdoc3/qmlcodemarker.cpp @@ -0,0 +1,1175 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the tools applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/* + cppcodemarker.cpp +*/ + +#include +#include "atom.h" +#include "cppcodemarker.h" +#include "node.h" +#include "text.h" +#include "tree.h" + +QT_BEGIN_NAMESPACE + +static int insertTagAround(QString &result, int pos, int len, const QString &tagName, + const QString &attributes = QString()) +{ + QString s; + //s.reserve(result.size() + tagName.size() * 2 + attributes.size() + 20); + s += result.midRef(0, pos); + s += QLatin1Char('<'); + s += tagName; + if (!attributes.isEmpty()) { + s += QLatin1Char(' '); + s += attributes; + } + s += QLatin1Char('>'); + s += result.midRef(pos, len); + s += QLatin1String("'); + s += result.midRef(pos + len); + int diff = s.length() - result.length(); + result = s; + return diff; +} + +/*! + The constructor does nothing. + */ +CppCodeMarker::CppCodeMarker() +{ + // nothing. +} + +/*! + The destructor does nothing. + */ +CppCodeMarker::~CppCodeMarker() +{ + // nothing. +} + +/*! + Returns true. + */ +bool CppCodeMarker::recognizeCode(const QString & /* code */) +{ + return true; +} + +/*! + Returns true if \a ext is any of a list of file extensions + for the C++ language. + */ +bool CppCodeMarker::recognizeExtension(const QString& ext) +{ + return ext == "c" || + ext == "c++" || + ext == "cc" || + ext == "cpp" || + ext == "cxx" || + ext == "ch" || + ext == "h" || + ext == "h++" || + ext == "hh" || + ext == "hpp" || + ext == "hxx"; +} + +/*! + Returns true if \a lang is either "C" or "Cpp". + */ +bool CppCodeMarker::recognizeLanguage(const QString &lang) +{ + return lang == "C" || lang == "Cpp"; +} + +/*! + Returns the \a node name, or "()" if \a node is a + Node::Function node. + */ +QString CppCodeMarker::plainName(const Node *node) +{ + QString name = node->name(); + if (node->type() == Node::Function) + name += "()"; + return name; +} + +QString CppCodeMarker::plainFullName(const Node *node, const Node *relative) +{ + if (node->name().isEmpty()) { + return "global"; + } + else { + QString fullName; + for (;;) { + fullName.prepend(plainName(node)); + if (node->parent() == relative || node->parent()->name().isEmpty()) + break; + fullName.prepend("::"); + node = node->parent(); + } + return fullName; + } +} + +QString CppCodeMarker::markedUpCode(const QString &code, + const Node *relative, + const QString &dirPath) +{ + return addMarkUp(protect(code), relative, dirPath); +} + +QString CppCodeMarker::markedUpSynopsis(const Node *node, + const Node * /* relative */, + SynopsisStyle style) +{ + const int MaxEnumValues = 6; + const FunctionNode *func; + const PropertyNode *property; + const VariableNode *variable; + const EnumNode *enume; + const TypedefNode *typedeff; + QString synopsis; + QString extra; + QString name; + + name = taggedNode(node); + if (style != Detailed) + name = linkTag(node, name); + name = "<@name>" + name + ""; + + if (style == Detailed && !node->parent()->name().isEmpty() && + node->type() != Node::Property) + name.prepend(taggedNode(node->parent()) + "::"); + + switch (node->type()) { + case Node::Namespace: + synopsis = "namespace " + name; + break; + case Node::Class: + synopsis = "class " + name; + break; + case Node::Function: + func = (const FunctionNode *) node; + if (style != SeparateList && !func->returnType().isEmpty()) + synopsis = typified(func->returnType()) + " "; + synopsis += name; + if (func->metaness() != FunctionNode::MacroWithoutParams) { + synopsis += " ("; + if (!func->parameters().isEmpty()) { + synopsis += " "; + QList::ConstIterator p = func->parameters().begin(); + while (p != func->parameters().end()) { + if (p != func->parameters().begin()) + synopsis += ", "; + synopsis += typified((*p).leftType()); + if (style != SeparateList && !(*p).name().isEmpty()) + synopsis += + " <@param>" + protect((*p).name()) + ""; + synopsis += protect((*p).rightType()); + if (style != SeparateList && !(*p).defaultValue().isEmpty()) + synopsis += " = " + protect((*p).defaultValue()); + ++p; + } + synopsis += " "; + } + synopsis += ")"; + } + if (func->isConst()) + synopsis += " const"; + + if (style == Summary || style == Accessors) { + if (func->virtualness() != FunctionNode::NonVirtual) + synopsis.prepend("virtual "); + if (func->virtualness() == FunctionNode::PureVirtual) + synopsis.append(" = 0"); + } + else if (style == SeparateList) { + if (!func->returnType().isEmpty() && func->returnType() != "void") + synopsis += " : " + typified(func->returnType()); + } + else { + QStringList bracketed; + if (func->isStatic()) { + bracketed += "static"; + } + else if (func->virtualness() != FunctionNode::NonVirtual) { + if (func->virtualness() == FunctionNode::PureVirtual) + bracketed += "pure"; + bracketed += "virtual"; + } + + if (func->access() == Node::Protected) { + bracketed += "protected"; + } + else if (func->access() == Node::Private) { + bracketed += "private"; + } + + if (func->metaness() == FunctionNode::Signal) { + bracketed += "signal"; + } + else if (func->metaness() == FunctionNode::Slot) { + bracketed += "slot"; + } + if (!bracketed.isEmpty()) + extra += " [" + bracketed.join(" ") + "]"; + } + break; + case Node::Enum: + enume = static_cast(node); + synopsis = "enum " + name; + if (style == Summary) { + synopsis += " { "; + + QStringList documentedItems = enume->doc().enumItemNames(); + if (documentedItems.isEmpty()) { + foreach (const EnumItem &item, enume->items()) + documentedItems << item.name(); + } + QStringList omitItems = enume->doc().omitEnumItemNames(); + foreach (const QString &item, omitItems) + documentedItems.removeAll(item); + + if (documentedItems.size() <= MaxEnumValues) { + for (int i = 0; i < documentedItems.size(); ++i) { + if (i != 0) + synopsis += ", "; + synopsis += documentedItems.at(i); + } + } + else { + for (int i = 0; i < documentedItems.size(); ++i) { + if (i < MaxEnumValues-2 || i == documentedItems.size()-1) { + if (i != 0) + synopsis += ", "; + synopsis += documentedItems.at(i); + } + else if (i == MaxEnumValues - 1) { + synopsis += ", ..."; + } + } + } + if (!documentedItems.isEmpty()) + synopsis += " "; + synopsis += "}"; + } + break; + case Node::Typedef: + typedeff = static_cast(node); + if (typedeff->associatedEnum()) { + synopsis = "flags " + name; + } + else { + synopsis = "typedef " + name; + } + break; + case Node::Property: + property = static_cast(node); + synopsis = name + " : " + typified(property->qualifiedDataType()); + break; + case Node::Variable: + variable = static_cast(node); + if (style == SeparateList) { + synopsis = name + " : " + typified(variable->dataType()); + } + else { + synopsis = typified(variable->leftType()) + " " + + name + protect(variable->rightType()); + } + break; + default: + synopsis = name; + } + + if (style == Summary) { + if (node->status() == Node::Preliminary) { + extra += " (preliminary)"; + } + else if (node->status() == Node::Deprecated) { + extra += " (deprecated)"; + } + else if (node->status() == Node::Obsolete) { + extra += " (obsolete)"; + } + } + + if (!extra.isEmpty()) { + extra.prepend("<@extra>"); + extra.append(""); + } + return synopsis + extra; +} + +#ifdef QDOC_QML +/*! + */ +QString CppCodeMarker::markedUpQmlItem(const Node* node, bool summary) +{ + QString name = taggedQmlNode(node); + if (summary) { + name = linkTag(node,name); + } + name = "<@name>" + name + ""; + QString synopsis = name; + if (node->type() == Node::QmlProperty) { + const QmlPropertyNode* pn = static_cast(node); + synopsis += " : " + typified(pn->dataType()); + } + + QString extra; + if (summary) { + if (node->status() == Node::Preliminary) { + extra += " (preliminary)"; + } + else if (node->status() == Node::Deprecated) { + extra += " (deprecated)"; + } + else if (node->status() == Node::Obsolete) { + extra += " (obsolete)"; + } + } + + if (!extra.isEmpty()) { + extra.prepend("<@extra>"); + extra.append(""); + } + return synopsis + extra; +} +#endif + +QString CppCodeMarker::markedUpName(const Node *node) +{ + QString name = linkTag(node, taggedNode(node)); + if (node->type() == Node::Function) + name += "()"; + return name; +} + +QString CppCodeMarker::markedUpFullName(const Node *node, const Node *relative) +{ + if (node->name().isEmpty()) { + return "global"; + } + else { + QString fullName; + for (;;) { + fullName.prepend(markedUpName(node)); + if (node->parent() == relative || node->parent()->name().isEmpty()) + break; + fullName.prepend("<@op>::"); + node = node->parent(); + } + return fullName; + } +} + +QString CppCodeMarker::markedUpEnumValue(const QString &enumValue, + const Node *relative) +{ + const Node *node = relative->parent(); + QString fullName; + while (node->parent()) { + fullName.prepend(markedUpName(node)); + if (node->parent() == relative || node->parent()->name().isEmpty()) + break; + fullName.prepend("<@op>::"); + node = node->parent(); + } + if (!fullName.isEmpty()) + fullName.append("<@op>::"); + fullName.append(enumValue); + return fullName; +} + +QString CppCodeMarker::markedUpIncludes(const QStringList& includes) +{ + QString code; + + QStringList::ConstIterator inc = includes.begin(); + while (inc != includes.end()) { + code += "#include <<@headerfile>" + *inc + ">\n"; + ++inc; + } + return addMarkUp(code, 0, ""); +} + +QString CppCodeMarker::functionBeginRegExp(const QString& funcName) +{ + return "^" + QRegExp::escape(funcName) + "$"; + +} + +QString CppCodeMarker::functionEndRegExp(const QString& /* funcName */) +{ + return "^\\}$"; +} + +#if 0 + FastSection privateReimpFuncs(classe, + "Private Reimplemented Functions", + "private reimplemented function", + "private reimplemented functions"); + FastSection protectedReimpFuncs(classe, + "Protected Reimplemented Functions", + "protected reimplemented function", + "protected reimplemented functions"); + FastSection publicReimpFuncs(classe, + "Public Reimplemented Functions", + "public reimplemented function", + "public reimplemented functions"); +#endif + +QList
CppCodeMarker::sections(const InnerNode *inner, + SynopsisStyle style, + Status status) +{ + QList
sections; + + if (inner->type() == Node::Class) { + const ClassNode *classe = static_cast(inner); + + if (style == Summary) { + FastSection privateFunctions(classe, + "Private Functions", + "private function", + "private functions"); + FastSection privateSlots(classe, "Private Slots", "private slot", "private slots"); + FastSection privateTypes(classe, "Private Types", "private type", "private types"); + FastSection protectedFunctions(classe, + "Protected Functions", + "protected function", + "protected functions"); + FastSection protectedSlots(classe, + "Protected Slots", + "protected slot", + "protected slots"); + FastSection protectedTypes(classe, + "Protected Types", + "protected type", + "protected types"); + FastSection protectedVariables(classe, + "Protected Variables", + "protected type", + "protected variables"); + FastSection publicFunctions(classe, + "Public Functions", + "public function", + "public functions"); + FastSection publicSignals(classe, "Signals", "signal", "signals"); + FastSection publicSlots(classe, "Public Slots", "public slot", "public slots"); + FastSection publicTypes(classe, "Public Types", "public type", "public types"); + FastSection publicVariables(classe, + "Public Variables", + "public type", + "public variables"); + FastSection properties(classe, "Properties", "property", "properties"); + FastSection relatedNonMembers(classe, + "Related Non-Members", + "related non-member", + "related non-members"); + FastSection staticPrivateMembers(classe, + "Static Private Members", + "static private member", + "static private members"); + FastSection staticProtectedMembers(classe, + "Static Protected Members", + "static protected member", + "static protected members"); + FastSection staticPublicMembers(classe, + "Static Public Members", + "static public member", + "static public members"); + FastSection macros(inner, "Macros", "macro", "macros"); + + NodeList::ConstIterator r = classe->relatedNodes().begin(); + while (r != classe->relatedNodes().end()) { + if ((*r)->type() == Node::Function) { + FunctionNode *func = static_cast(*r); + if (func->isMacro()) + insert(macros, *r, style, status); + else + insert(relatedNonMembers, *r, style, status); + } + else { + insert(relatedNonMembers, *r, style, status); + } + ++r; + } + + QStack stack; + stack.push(classe); + + while (!stack.isEmpty()) { + const ClassNode *ancestorClass = stack.pop(); + + NodeList::ConstIterator c = ancestorClass->childNodes().begin(); + while (c != ancestorClass->childNodes().end()) { + bool isSlot = false; + bool isSignal = false; + bool isStatic = false; + if ((*c)->type() == Node::Function) { + const FunctionNode *func = (const FunctionNode *) *c; + isSlot = (func->metaness() == FunctionNode::Slot); + isSignal = (func->metaness() == FunctionNode::Signal); + isStatic = func->isStatic(); + } + else if ((*c)->type() == Node::Variable) { + const VariableNode *var = static_cast(*c); + isStatic = var->isStatic(); + } + + switch ((*c)->access()) { + case Node::Public: + if (isSlot) { + insert(publicSlots, *c, style, status); + } + else if (isSignal) { + insert(publicSignals, *c, style, status); + } + else if (isStatic) { + if ((*c)->type() != Node::Variable + || !(*c)->doc().isEmpty()) + insert(staticPublicMembers,*c,style,status); + } + else if ((*c)->type() == Node::Property) { + insert(properties, *c, style, status); + } + else if ((*c)->type() == Node::Variable) { + if (!(*c)->doc().isEmpty()) + insert(publicVariables, *c, style, status); + } + else if ((*c)->type() == Node::Function) { + if (!insertReimpFunc(publicFunctions,*c,status)) + insert(publicFunctions, *c, style, status); + } + else { + insert(publicTypes, *c, style, status); + } + break; + case Node::Protected: + if (isSlot) { + insert(protectedSlots, *c, style, status); + } + else if (isStatic) { + if ((*c)->type() != Node::Variable + || !(*c)->doc().isEmpty()) + insert(staticProtectedMembers,*c,style,status); + } + else if ((*c)->type() == Node::Variable) { + if (!(*c)->doc().isEmpty()) + insert(protectedVariables,*c,style,status); + } + else if ((*c)->type() == Node::Function) { + if (!insertReimpFunc(protectedFunctions,*c,status)) + insert(protectedFunctions, *c, style, status); + } + else { + insert(protectedTypes, *c, style, status); + } + break; + case Node::Private: + if (isSlot) { + insert(privateSlots, *c, style, status); + } + else if (isStatic) { + if ((*c)->type() != Node::Variable + || !(*c)->doc().isEmpty()) + insert(staticPrivateMembers,*c,style,status); + } + else if ((*c)->type() == Node::Function) { + if (!insertReimpFunc(privateFunctions,*c,status)) + insert(privateFunctions, *c, style, status); + } + else { + insert(privateTypes,*c,style,status); + } + } + ++c; + } + + QList::ConstIterator r = + ancestorClass->baseClasses().begin(); + while (r != ancestorClass->baseClasses().end()) { + stack.prepend((*r).node); + ++r; + } + } + + append(sections, publicTypes); + append(sections, properties); + append(sections, publicFunctions); + append(sections, publicSlots); + append(sections, publicSignals); + append(sections, publicVariables); + append(sections, staticPublicMembers); + append(sections, protectedTypes); + append(sections, protectedFunctions); + append(sections, protectedSlots); + append(sections, protectedVariables); + append(sections, staticProtectedMembers); + append(sections, privateTypes); + append(sections, privateFunctions); + append(sections, privateSlots); + append(sections, staticPrivateMembers); + append(sections, relatedNonMembers); + append(sections, macros); + } + else if (style == Detailed) { + FastSection memberFunctions(classe,"Member Function Documentation"); + FastSection memberTypes(classe,"Member Type Documentation"); + FastSection memberVariables(classe,"Member Variable Documentation"); + FastSection properties(classe,"Property Documentation"); + FastSection relatedNonMembers(classe,"Related Non-Members"); + FastSection macros(classe,"Macro Documentation"); + + NodeList::ConstIterator r = classe->relatedNodes().begin(); + while (r != classe->relatedNodes().end()) { + if ((*r)->type() == Node::Function) { + FunctionNode *func = static_cast(*r); + if (func->isMacro()) + insert(macros, *r, style, status); + else + insert(relatedNonMembers, *r, style, status); + } + else { + insert(relatedNonMembers, *r, style, status); + } + ++r; + } + + NodeList::ConstIterator c = classe->childNodes().begin(); + while (c != classe->childNodes().end()) { + if ((*c)->type() == Node::Enum || + (*c)->type() == Node::Typedef) { + insert(memberTypes, *c, style, status); + } + else if ((*c)->type() == Node::Property) { + insert(properties, *c, style, status); + } + else if ((*c)->type() == Node::Variable) { + if (!(*c)->doc().isEmpty()) + insert(memberVariables, *c, style, status); + } + else if ((*c)->type() == Node::Function) { + FunctionNode *function = static_cast(*c); + if (!function->associatedProperty()) + insert(memberFunctions, function, style, status); + } + ++c; + } + + append(sections, memberTypes); + append(sections, properties); + append(sections, memberFunctions); + append(sections, memberVariables); + append(sections, relatedNonMembers); + append(sections, macros); + } + else { + FastSection all(classe); + + QStack stack; + stack.push(classe); + + while (!stack.isEmpty()) { + const ClassNode *ancestorClass = stack.pop(); + + NodeList::ConstIterator c = ancestorClass->childNodes().begin(); + while (c != ancestorClass->childNodes().end()) { + if ((*c)->access() != Node::Private && + (*c)->type() != Node::Property) + insert(all, *c, style, status); + ++c; + } + + QList::ConstIterator r = + ancestorClass->baseClasses().begin(); + while (r != ancestorClass->baseClasses().end()) { + stack.prepend((*r).node); + ++r; + } + } + append(sections, all); + } + } + else { + if (style == Summary || style == Detailed) { + FastSection namespaces(inner, + "Namespaces", + "namespace", + "namespaces"); + FastSection classes(inner, + "Classes", + "class", + "classes"); + FastSection types(inner, + style == Summary ? + "Types" : "Type Documentation", + "type", + "types"); + FastSection functions(inner, + style == Summary ? + "Functions" : "Function Documentation", + "function", + "functions"); + FastSection macros(inner, + style == Summary ? + "Macros" : "Macro Documentation", + "macro", + "macros"); + + NodeList nodeList = inner->childNodes(); + nodeList += inner->relatedNodes(); + + NodeList::ConstIterator n = nodeList.begin(); + while (n != nodeList.end()) { + switch ((*n)->type()) { + case Node::Namespace: + insert(namespaces, *n, style, status); + break; + case Node::Class: + insert(classes, *n, style, status); + break; + case Node::Enum: + case Node::Typedef: + insert(types, *n, style, status); + break; + case Node::Function: + { + FunctionNode *func = static_cast(*n); + if (func->isMacro()) + insert(macros, *n, style, status); + else + insert(functions, *n, style, status); + } + break; + default: + ; + } + ++n; + } + append(sections, namespaces); + append(sections, classes); + append(sections, types); + append(sections, functions); + append(sections, macros); + } + } + + return sections; +} + +const Node *CppCodeMarker::resolveTarget(const QString &target, + const Tree *tree, + const Node *relative) +{ + if (target.endsWith("()")) { + const FunctionNode *func; + QString funcName = target; + funcName.chop(2); + + QStringList path = funcName.split("::"); + if ((func = tree->findFunctionNode(path, + relative, + Tree::SearchBaseClasses)) + && func->metaness() != FunctionNode::MacroWithoutParams) + return func; + } + else if (target.contains("#")) { + // ### this doesn't belong here; get rid of TargetNode hack + int hashAt = target.indexOf("#"); + QString link = target.left(hashAt); + QString ref = target.mid(hashAt + 1); + const Node *node; + if (link.isEmpty()) { + node = relative; + } + else { + QStringList path(link); + node = tree->findNode(path, tree->root(), Tree::SearchBaseClasses); + } + if (node && node->isInnerNode()) { + const Atom *atom = node->doc().body().firstAtom(); + while (atom) { + if (atom->type() == Atom::Target && atom->string() == ref) { + Node *parentNode = const_cast(node); + return new TargetNode(static_cast(parentNode), + ref); + } + atom = atom->next(); + } + } + } + else { + QStringList path = target.split("::"); + const Node *node; + if ((node = tree->findNode(path, + relative, + Tree::SearchBaseClasses | + Tree::SearchEnumValues | + Tree::NonFunction))) + return node; + } + return 0; +} + +QString CppCodeMarker::addMarkUp(const QString& protectedCode, + const Node * /* relative */, + const QString& /* dirPath */) +{ + static QRegExp globalInclude("#include +<([^<>&]+)>"); + static QRegExp yHasTypeX("(?:^|\n *)([a-zA-Z_][a-zA-Z_0-9]*)" + "(?:<[^;{}]+>)?(?: *(?:\\*|&) *| +)" + "([a-zA-Z_][a-zA-Z_0-9]*)? *[,;()=]"); + static QRegExp xNewY("([a-zA-Z_][a-zA-Z_0-9]*) *= *new +([a-zA-Z_0-9]+)"); + static QRegExp xDotY("\\b([a-zA-Z_][a-zA-Z_0-9]*) *(?:\\.|->|,[ \n]*S(?:IGNAL|LOT)\\() *" + "([a-zA-Z_][a-zA-Z_0-9]*)(?= *\\()"); + static QRegExp xIsStaticZOfY("[\n:;{(=] *(([a-zA-Z_0-9]+)::([a-zA-Z_0-9]+))(?= *\\()"); + static QRegExp classX("[:,][ \n]*(?:p(?:ublic|r(?:otected|ivate))[ \n]+)?" + "([a-zA-Z_][a-zA-Z_0-9]*)"); + static QRegExp globalX("[\n{()=] *([a-zA-Z_][a-zA-Z_0-9]*)[ \n]*\\("); + static QRegExp multiLineComment("/(?:( )?\\*(?:[^*]+|\\*(?! /))*\\*\\1/)"); + multiLineComment.setMinimal(true); + static QRegExp singleLineComment("//(?!!)[^!\n]*"); + static QRegExp preprocessor("(?:^|\n)(#[ \t]*(?:include|if|elif|endif|error|pragma|define" + "|warning)(?:(?:\\\\\n|\\n#)[^\n]*)*)"); + static QRegExp literals(""(?:[^\\\\&]|\\\\[^\n]|&(?!quot;))*"" + "|'(?:[^\\\\]|\\\\(?:[^x0-9']|x[0-9a-f]{1,4}|[0-9]{1,3}))'"); + + QString result = protectedCode; + int pos; + + if (!hurryUp()) { + /* + Mark global includes. For example: + + #include <<@headerfile>QString + */ + pos = 0; + while ((pos = result.indexOf(globalInclude, pos)) != -1) + pos += globalInclude.matchedLength() + + insertTagAround(result, + globalInclude.pos(1), + globalInclude.cap(1).length(), + "@headerfile"); + + /* + Look for variable definitions and similar constructs, mark + the data type, and remember the type of the variable. + */ + QMap > typesForVariable; + pos = 0; + while ((pos = yHasTypeX.indexIn(result, pos)) != -1) { + QString x = yHasTypeX.cap(1); + QString y = yHasTypeX.cap(2); + + if (!y.isEmpty()) + typesForVariable[y].insert(x); + + /* + Without the minus one at the end, 'void member(Class + var)' would give 'member' as a variable of type 'void', + but would ignore 'Class var'. (### Is that true?) + */ + pos += yHasTypeX.matchedLength() + + insertTagAround(result, + yHasTypeX.pos(1), + x.length(), + "@type") - 1; + } + + /* + Do syntax highlighting of preprocessor directives. + */ + pos = 0; + while ((pos = preprocessor.indexIn(result, pos)) != -1) + pos += preprocessor.matchedLength() + + insertTagAround(result, + preprocessor.pos(1), + preprocessor.cap(1).length(), + "@preprocessor"); + + /* + Deal with string and character literals. + */ + pos = 0; + while ((pos = literals.indexIn(result, pos)) != -1) + pos += literals.matchedLength() + + insertTagAround(result, + pos, + literals.matchedLength(), + result.at(pos) == + QLatin1Char(' ') ? "@string" : "@char"); + + /* + Look for 'var = new Class'. + */ + pos = 0; + while ((pos = xNewY.indexIn(result, pos)) != -1) { + QString x = xNewY.cap(1); + QString y = xNewY.cap(2); + typesForVariable[x].insert(y); + + pos += xNewY.matchedLength() + insertTagAround(result, + xNewY.pos(2), + y.length(), + "@type"); + } + + /* + Insert some stuff that cannot harm. + */ + typesForVariable["qApp"].insert("QApplication"); + + /* + Add link to ': Class'. + */ + pos = 0; + while ((pos = classX.indexIn(result, pos)) != -1) + pos += classX.matchedLength() + + insertTagAround(result, + classX.pos(1), + classX.cap(1).length(), + "@type") - 1; + + /* + Find use of any of + + var.method() + var->method() + var, SIGNAL(method()) + var, SLOT(method()). + */ + pos = 0; + while ((pos = xDotY.indexIn(result, pos)) != -1) { + QString x = xDotY.cap(1); + QString y = xDotY.cap(2); + + QSet types = typesForVariable.value(x); + pos += xDotY.matchedLength() + + insertTagAround(result, + xDotY.pos(2), + xDotY.cap(2).length(), + "@func", + (types.count() == 1) ? "target=\"" + + protect(*types.begin() + "::" + y) + + "()\"" : QString()); + } + + /* + Add link to 'Class::method()'. + */ + pos = 0; + while ((pos = xIsStaticZOfY.indexIn(result, pos)) != -1) { + QString x = xIsStaticZOfY.cap(1); + QString z = xIsStaticZOfY.cap(3); + + pos += insertTagAround(result, + xIsStaticZOfY.pos(3), + z.length(), + "@func", + "target=\"" + protect(x) + "()\""); + pos += insertTagAround(result, + xIsStaticZOfY.pos(2), + xIsStaticZOfY.cap(2).length(), + "@type"); + pos += xIsStaticZOfY.matchedLength() - 1; + } + + /* + Add link to 'globalFunction()'. + */ + pos = 0; + while ((pos = globalX.indexIn(result, pos)) != -1) { + QString x = globalX.cap(1); + if (x != "QT_FORWARD_DECLARE_CLASS") { + pos += globalX.matchedLength() + + insertTagAround(result, + globalX.pos(1), + x.length(), + "@func", + "target=\"" + protect(x) + "()\"") - 1; + } + else + pos += globalX.matchedLength(); + } + } + + /* + Do syntax highlighting of comments. Also alter the code in a + minor way, so that we can include comments in documentation + comments. + */ + pos = 0; + while (pos != -1) { + int mlpos; + int slpos; + int len; + slpos = singleLineComment.indexIn(result, pos); + mlpos = multiLineComment.indexIn(result, pos); + + if (slpos == -1 && mlpos == -1) + break; + + if (slpos == -1) { + pos = mlpos; + len = multiLineComment.matchedLength(); + } + else if (mlpos == -1) { + pos = slpos; + len = singleLineComment.matchedLength(); + } + else { + if (slpos < mlpos) { + pos = slpos; + len = singleLineComment.matchedLength(); + } + else { + pos = mlpos; + len = multiLineComment.matchedLength(); + } + } + + if (result.at(pos + 1) == QLatin1Char(' ')) { + result.remove(pos + len - 2, 1); + result.remove(pos + 1, 1); + len -= 2; + + forever { + int endcodePos = result.indexOf("\\ endcode", pos); + if (endcodePos == -1 || endcodePos >= pos + len) + break; + result.remove(endcodePos + 1, 1); + len -= 1; + } + } + pos += len + insertTagAround(result, pos, len, "@comment"); + } + + return result; +} + +#ifdef QDOC_QML +/*! + This function is for documenting QML properties. It returns + the list of documentation sections for the children of the + \a qmlClassNode. + + Currently, it only handles QML property groups. + */ +QList
CppCodeMarker::qmlSections(const QmlClassNode* qmlClassNode, + SynopsisStyle style) +{ + QList
sections; + if (qmlClassNode) { + if (style == Summary) { + FastSection qmlproperties(qmlClassNode, + "Properties", + "property", + "properties"); + FastSection qmlsignals(qmlClassNode, + "Signals", + "signal", + "signals"); + FastSection qmlmethods(qmlClassNode, + "Methods", + "method", + "methods"); + + NodeList::ConstIterator c = qmlClassNode->childNodes().begin(); + while (c != qmlClassNode->childNodes().end()) { + if ((*c)->subType() == Node::QmlPropertyGroup) { + const QmlPropGroupNode* qpgn = static_cast(*c); + NodeList::ConstIterator p = qpgn->childNodes().begin(); + while (p != qpgn->childNodes().end()) { + if ((*p)->type() == Node::QmlProperty) { + insert(qmlproperties,*p,style,Okay); + } + ++p; + } + } + else if ((*c)->type() == Node::QmlSignal) { + insert(qmlsignals,*c,style,Okay); + } + else if ((*c)->type() == Node::QmlMethod) { + insert(qmlmethods,*c,style,Okay); + } + ++c; + } + append(sections,qmlproperties); + append(sections,qmlsignals); + append(sections,qmlmethods); + } + else if (style == Detailed) { + FastSection qmlproperties(qmlClassNode, "Property Documentation"); + FastSection qmlsignals(qmlClassNode,"Signal Documentation"); + FastSection qmlmethods(qmlClassNode,"Method Documentation"); + NodeList::ConstIterator c = qmlClassNode->childNodes().begin(); + while (c != qmlClassNode->childNodes().end()) { + if ((*c)->subType() == Node::QmlPropertyGroup) { + insert(qmlproperties,*c,style,Okay); + } + else if ((*c)->type() == Node::QmlSignal) { + insert(qmlsignals,*c,style,Okay); + } + else if ((*c)->type() == Node::QmlMethod) { + insert(qmlmethods,*c,style,Okay); + } + ++c; + } + append(sections,qmlproperties); + append(sections,qmlsignals); + append(sections,qmlmethods); + } + } + + return sections; +} +#endif + +QT_END_NAMESPACE diff --git a/tools/qdoc3/qmlcodemarker.h b/tools/qdoc3/qmlcodemarker.h new file mode 100644 index 0000000..8c83c04 --- /dev/null +++ b/tools/qdoc3/qmlcodemarker.h @@ -0,0 +1,96 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the tools applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/* + cppcodemarker.h +*/ + +#ifndef CPPCODEMARKER_H +#define CPPCODEMARKER_H + +#include "codemarker.h" + +QT_BEGIN_NAMESPACE + +class CppCodeMarker : public CodeMarker +{ + public: + CppCodeMarker(); + ~CppCodeMarker(); + + bool recognizeCode(const QString& code); + bool recognizeExtension(const QString& ext); + bool recognizeLanguage(const QString& lang); + QString plainName(const Node *node); + QString plainFullName(const Node *node, const Node *relative); + QString markedUpCode(const QString& code, + const Node *relative, + const QString& dirPath); + QString markedUpSynopsis(const Node *node, + const Node *relative, + SynopsisStyle style); +#ifdef QDOC_QML + QString markedUpQmlItem(const Node *node, bool summary); +#endif + QString markedUpName(const Node *node); + QString markedUpFullName(const Node *node, const Node *relative); + QString markedUpEnumValue(const QString &enumValue, const Node *relative); + QString markedUpIncludes(const QStringList& includes); + QString functionBeginRegExp(const QString& funcName); + QString functionEndRegExp(const QString& funcName); + QList
sections(const InnerNode *innerNode, + SynopsisStyle style, + Status status); + QList
qmlSections(const QmlClassNode* qmlClassNode, + SynopsisStyle style); + const Node *resolveTarget(const QString& target, + const Tree *tree, + const Node *relative); + +private: + QString addMarkUp(const QString& protectedCode, + const Node *relative, + const QString& dirPath); +}; + +QT_END_NAMESPACE + +#endif -- cgit v0.12 From c2aa20e6eda3654022976db2b1abbf23f9abbcfb Mon Sep 17 00:00:00 2001 From: Martin Jones Date: Wed, 21 Oct 2009 11:37:56 +1000 Subject: Move QmlFolderListModel to the loader example. --- examples/declarative/loader/loader.pro | 3 +- examples/declarative/loader/qmlfolderlistmodel.cpp | 413 +++++++++++++++++++++ examples/declarative/loader/qmlfolderlistmodel.h | 128 +++++++ src/declarative/extra/extra.pri | 2 - src/declarative/extra/qmlfolderlistmodel.cpp | 413 --------------------- src/declarative/extra/qmlfolderlistmodel.h | 128 ------- 6 files changed, 543 insertions(+), 544 deletions(-) create mode 100644 examples/declarative/loader/qmlfolderlistmodel.cpp create mode 100644 examples/declarative/loader/qmlfolderlistmodel.h delete mode 100644 src/declarative/extra/qmlfolderlistmodel.cpp delete mode 100644 src/declarative/extra/qmlfolderlistmodel.h diff --git a/examples/declarative/loader/loader.pro b/examples/declarative/loader/loader.pro index 9b03b8f..8c93210 100644 --- a/examples/declarative/loader/loader.pro +++ b/examples/declarative/loader/loader.pro @@ -1,4 +1,5 @@ -SOURCES = main.cpp +SOURCES = main.cpp qmlfolderlistmodel.cpp +HEADERS = qmlfolderlistmodel.h RESOURCES = loader.qrc QT += script declarative network diff --git a/examples/declarative/loader/qmlfolderlistmodel.cpp b/examples/declarative/loader/qmlfolderlistmodel.cpp new file mode 100644 index 0000000..0e5c275 --- /dev/null +++ b/examples/declarative/loader/qmlfolderlistmodel.cpp @@ -0,0 +1,413 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "private/qobject_p.h" +#include +#include +#include "qmlfolderlistmodel.h" +#include + +QT_BEGIN_NAMESPACE + +class QmlFolderListModelPrivate : public QObjectPrivate +{ +public: + QmlFolderListModelPrivate() + : sortField(QmlFolderListModel::Name), sortReversed(false), count(0) { + nameFilters << QLatin1String("*"); + } + + void updateSorting() { + QDir::SortFlags flags = 0; + switch(sortField) { + case QmlFolderListModel::Unsorted: + flags |= QDir::Unsorted; + break; + case QmlFolderListModel::Name: + flags |= QDir::Name; + break; + case QmlFolderListModel::Time: + flags |= QDir::Time; + break; + case QmlFolderListModel::Size: + flags |= QDir::Size; + break; + case QmlFolderListModel::Type: + flags |= QDir::Type; + break; + } + + if (sortReversed) + flags |= QDir::Reversed; + + model.setSorting(flags); + } + + QDirModel model; + QUrl folder; + QStringList nameFilters; + QModelIndex folderIndex; + QmlFolderListModel::SortField sortField; + bool sortReversed; + int count; +}; + +/*! + \qmlclass FolderListModel + \brief The FolderListModel provides a model of the contents of a folder in a filesystem. + + FolderListModel provides access to the local filesystem. The \e folder property + specifies the folder to list. + + Qt uses "/" as a universal directory separator in the same way that "/" is + used as a path separator in URLs. If you always use "/" as a directory + separator, Qt will translate your paths to conform to the underlying + operating system. + + The roles available are: + \list + \o fileName + \o filePath + \endlist + + Additionally a file entry can be differentiated from a folder entry + via the \l isFolder() method. +*/ + +QmlFolderListModel::QmlFolderListModel(QObject *parent) + : QListModelInterface(*(new QmlFolderListModelPrivate), parent) +{ + Q_D(QmlFolderListModel); + d->model.setFilter(QDir::AllDirs | QDir::Files | QDir::Drives | QDir::NoDotAndDotDot); + connect(&d->model, SIGNAL(rowsInserted(const QModelIndex&,int,int)) + , this, SLOT(inserted(const QModelIndex&,int,int))); + connect(&d->model, SIGNAL(rowsRemoved(const QModelIndex&,int,int)) + , this, SLOT(removed(const QModelIndex&,int,int))); + connect(&d->model, SIGNAL(dataChanged(const QModelIndex&,const QModelIndex&)) + , this, SLOT(dataChanged(const QModelIndex&,const QModelIndex&))); + connect(&d->model, SIGNAL(modelReset()), this, SLOT(refresh())); + connect(&d->model, SIGNAL(layoutChanged()), this, SLOT(refresh())); +} + +QmlFolderListModel::~QmlFolderListModel() +{ +} + +QHash QmlFolderListModel::data(int index, const QList &roles) const +{ + Q_UNUSED(roles); + Q_D(const QmlFolderListModel); + QHash folderData; + QModelIndex modelIndex = d->model.index(index, 0, d->folderIndex); + if (modelIndex.isValid()) { + folderData[QDirModel::FileNameRole] = d->model.data(modelIndex, QDirModel::FileNameRole); + folderData[QDirModel::FilePathRole] = QUrl::fromLocalFile(d->model.data(modelIndex, QDirModel::FilePathRole).toString()); + } + + return folderData; +} + +int QmlFolderListModel::count() const +{ + Q_D(const QmlFolderListModel); + return d->count; +} + +QList QmlFolderListModel::roles() const +{ + QList r; + r << QDirModel::FileNameRole; + r << QDirModel::FilePathRole; + return r; +} + +QString QmlFolderListModel::toString(int role) const +{ + switch (role) { + case QDirModel::FileNameRole: + return QLatin1String("fileName"); + case QDirModel::FilePathRole: + return QLatin1String("filePath"); + } + + return QString(); +} + +/*! + \qmlproperty string FolderListModel::folder + + The \a folder property holds the folder the model is currently providing. + + It is a URL, but must be a file: or qrc: URL (or relative to such a URL). +*/ +QUrl QmlFolderListModel::folder() const +{ + Q_D(const QmlFolderListModel); + return d->folder; +} + +void QmlFolderListModel::setFolder(const QUrl &folder) +{ + Q_D(QmlFolderListModel); + if (folder == d->folder) + return; + QModelIndex index = d->model.index(folder.toLocalFile()); + if (index.isValid() && d->model.isDir(index)) { + d->folder = folder; + QMetaObject::invokeMethod(this, "refresh", Qt::QueuedConnection); + emit folderChanged(); + } +} + +QUrl QmlFolderListModel::parentFolder() const +{ + Q_D(const QmlFolderListModel); + int pos = d->folder.path().lastIndexOf(QLatin1Char('/')); + if (pos == -1) + return QUrl(); + QUrl r = d->folder; + r.setPath(d->folder.path().left(pos)); + return r; +} + +/*! + \qmlproperty list FolderListModel::nameFilters + + The \a nameFilters property contains a list of filename filters. + The filters may include the ? and * wildcards. + + The example below filters on PNG and JPEG files: + + \code + FolderListModel { + nameFilters: [ "*.png", "*.jpg" ] + } + \endcode +*/ +QStringList QmlFolderListModel::nameFilters() const +{ + Q_D(const QmlFolderListModel); + return d->nameFilters; +} + +void QmlFolderListModel::setNameFilters(const QStringList &filters) +{ + Q_D(QmlFolderListModel); + d->nameFilters = filters; + d->model.setNameFilters(d->nameFilters); +} + +void QmlFolderListModel::componentComplete() +{ + Q_D(QmlFolderListModel); + if (!d->folder.isValid() || !QDir().exists(d->folder.toLocalFile())) + setFolder(QUrl(QLatin1String("file://")+QDir::currentPath())); + + if (!d->folderIndex.isValid()) + QMetaObject::invokeMethod(this, "refresh", Qt::QueuedConnection); +} + +QmlFolderListModel::SortField QmlFolderListModel::sortField() const +{ + Q_D(const QmlFolderListModel); + return d->sortField; +} + +void QmlFolderListModel::setSortField(SortField field) +{ + Q_D(QmlFolderListModel); + if (field != d->sortField) { + d->sortField = field; + d->updateSorting(); + } +} + +bool QmlFolderListModel::sortReversed() const +{ + Q_D(const QmlFolderListModel); + return d->sortReversed; +} + +void QmlFolderListModel::setSortReversed(bool rev) +{ + Q_D(QmlFolderListModel); + if (rev != d->sortReversed) { + d->sortReversed = rev; + d->updateSorting(); + } +} + +/*! + \qmlmethod bool FolderListModel::isFolder(int index) + + Returns true if the entry \a index is a folder; otherwise + returns false. +*/ +bool QmlFolderListModel::isFolder(int index) const +{ + Q_D(const QmlFolderListModel); + if (index != -1) { + QModelIndex idx = d->model.index(index, 0, d->folderIndex); + if (idx.isValid()) + return d->model.isDir(idx); + } + return false; +} + +void QmlFolderListModel::refresh() +{ + Q_D(QmlFolderListModel); + d->folderIndex = QModelIndex(); + if (d->count) { + int tmpCount = d->count; + d->count = 0; + emit itemsRemoved(0, tmpCount); + } + d->folderIndex = d->model.index(d->folder.toLocalFile()); + d->count = d->model.rowCount(d->folderIndex); + if (d->count) { + emit itemsInserted(0, d->count); + } +} + +void QmlFolderListModel::inserted(const QModelIndex &index, int start, int end) +{ + Q_D(QmlFolderListModel); + if (index == d->folderIndex) { + d->count = d->model.rowCount(d->folderIndex); + emit itemsInserted(start, end - start + 1); + } +} + +void QmlFolderListModel::removed(const QModelIndex &index, int start, int end) +{ + Q_D(QmlFolderListModel); + if (index == d->folderIndex) { + d->count = d->model.rowCount(d->folderIndex); + emit itemsRemoved(start, end - start + 1); + } +} + +void QmlFolderListModel::dataChanged(const QModelIndex &start, const QModelIndex &end) +{ + Q_D(QmlFolderListModel); + qDebug() << "data changed"; + if (start.parent() == d->folderIndex) + emit itemsChanged(start.row(), end.row() - start.row() + 1, roles()); +} + +/*! + \qmlproperty bool FolderListModel::showDirs + + If true (the default), directories are included in the model. + + Note that the nameFilters are ignored for directories. +*/ +bool QmlFolderListModel::showDirs() const +{ + Q_D(const QmlFolderListModel); + return d->model.filter() & QDir::AllDirs; +} + +void QmlFolderListModel::setShowDirs(bool on) +{ + Q_D(QmlFolderListModel); + if (!(d->model.filter() & QDir::AllDirs) == !on) + return; + if (on) + d->model.setFilter(d->model.filter() | QDir::AllDirs | QDir::Drives); + else + d->model.setFilter(d->model.filter() & ~(QDir::AllDirs | QDir::Drives)); +} + +/*! + \qmlproperty bool FolderListModel::showDotAndDotDot + + If true, the "." and ".." directories are included in the model. + + The default is false. +*/ +bool QmlFolderListModel::showDotAndDotDot() const +{ + Q_D(const QmlFolderListModel); + return !(d->model.filter() & QDir::NoDotAndDotDot); +} + +void QmlFolderListModel::setShowDotAndDotDot(bool on) +{ + Q_D(QmlFolderListModel); + if (!(d->model.filter() & QDir::NoDotAndDotDot) == on) + return; + if (on) + d->model.setFilter(d->model.filter() & ~QDir::NoDotAndDotDot); + else + d->model.setFilter(d->model.filter() | QDir::NoDotAndDotDot); +} + +/*! + \qmlproperty bool FolderListModel::showOnlyReadable + + If true, only readable files and directories are shown. + + The default is false. +*/ +bool QmlFolderListModel::showOnlyReadable() const +{ + Q_D(const QmlFolderListModel); + return d->model.filter() & QDir::Readable; +} + +void QmlFolderListModel::setShowOnlyReadable(bool on) +{ + Q_D(QmlFolderListModel); + if (!(d->model.filter() & QDir::Readable) == !on) + return; + if (on) + d->model.setFilter(d->model.filter() | QDir::Readable); + else + d->model.setFilter(d->model.filter() & ~QDir::Readable); +} + + +QML_DEFINE_TYPE(Qt,4,6,(QT_VERSION&0x00ff00)>>8,FolderListModel,QmlFolderListModel) + +QT_END_NAMESPACE + diff --git a/examples/declarative/loader/qmlfolderlistmodel.h b/examples/declarative/loader/qmlfolderlistmodel.h new file mode 100644 index 0000000..66e600b --- /dev/null +++ b/examples/declarative/loader/qmlfolderlistmodel.h @@ -0,0 +1,128 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QMLFOLDERLISTMODEL_H +#define QMLFOLDERLISTMODEL_H + +#include +#include + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Declarative) + +class QmlContext; +class QModelIndex; + +class QmlFolderListModelPrivate; +class Q_DECLARATIVE_EXPORT QmlFolderListModel : public QListModelInterface, public QmlParserStatus +{ + Q_OBJECT + Q_INTERFACES(QmlParserStatus) + + Q_PROPERTY(QUrl folder READ folder WRITE setFolder NOTIFY folderChanged) + Q_PROPERTY(QUrl parentFolder READ parentFolder NOTIFY folderChanged) + Q_PROPERTY(QStringList nameFilters READ nameFilters WRITE setNameFilters) + Q_PROPERTY(SortField sortField READ sortField WRITE setSortField) + Q_PROPERTY(bool sortReversed READ sortReversed WRITE setSortReversed) + Q_PROPERTY(bool showDirs READ showDirs WRITE setShowDirs) + Q_PROPERTY(bool showDotAndDotDot READ showDotAndDotDot WRITE setShowDotAndDotDot) + Q_PROPERTY(bool showOnlyReadable READ showOnlyReadable WRITE setShowOnlyReadable) + +public: + QmlFolderListModel(QObject *parent = 0); + ~QmlFolderListModel(); + + virtual QHash data(int index, const QList &roles = (QList())) const; + virtual int count() const; + virtual QList roles() const; + virtual QString toString(int role) const; + + QUrl folder() const; + void setFolder(const QUrl &folder); + + QUrl parentFolder() const; + + QStringList nameFilters() const; + void setNameFilters(const QStringList &filters); + + virtual void componentComplete(); + + Q_INVOKABLE bool isFolder(int index) const; + + enum SortField { Unsorted, Name, Time, Size, Type }; + SortField sortField() const; + void setSortField(SortField field); + Q_ENUMS(SortField) + + bool sortReversed() const; + void setSortReversed(bool rev); + + bool showDirs() const; + void setShowDirs(bool); + bool showDotAndDotDot() const; + void setShowDotAndDotDot(bool); + bool showOnlyReadable() const; + void setShowOnlyReadable(bool); + +Q_SIGNALS: + void folderChanged(); + +private Q_SLOTS: + void refresh(); + void inserted(const QModelIndex &index, int start, int end); + void removed(const QModelIndex &index, int start, int end); + void dataChanged(const QModelIndex &start, const QModelIndex &end); + +private: + Q_DECLARE_PRIVATE(QmlFolderListModel) + Q_DISABLE_COPY(QmlFolderListModel) +}; + +QT_END_NAMESPACE + +QML_DECLARE_TYPE(QmlFolderListModel) + +QT_END_HEADER + +#endif // QMLFOLDERLISTMODEL_H diff --git a/src/declarative/extra/extra.pri b/src/declarative/extra/extra.pri index 6730550..726f099 100644 --- a/src/declarative/extra/extra.pri +++ b/src/declarative/extra/extra.pri @@ -3,7 +3,6 @@ SOURCES += \ extra/qmlnumberformatter.cpp \ extra/qmldatetimeformatter.cpp \ extra/qfxintegermodel.cpp \ - extra/qmlfolderlistmodel.cpp \ extra/qfxanimatedimageitem.cpp \ extra/qfxparticles.cpp \ extra/qmlbehavior.cpp \ @@ -15,7 +14,6 @@ HEADERS += \ extra/qmlnumberformatter.h \ extra/qmldatetimeformatter.h \ extra/qfxintegermodel.h \ - extra/qmlfolderlistmodel.h \ extra/qfxanimatedimageitem.h \ extra/qfxanimatedimageitem_p.h \ extra/qfxparticles.h \ diff --git a/src/declarative/extra/qmlfolderlistmodel.cpp b/src/declarative/extra/qmlfolderlistmodel.cpp deleted file mode 100644 index 0e5c275..0000000 --- a/src/declarative/extra/qmlfolderlistmodel.cpp +++ /dev/null @@ -1,413 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Qt Software Information (qt-info@nokia.com) -** -** This file is part of the QtDeclarative module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the either Technology Preview License Agreement or the -** Beta Release License Agreement. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at qt-sales@nokia.com. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "private/qobject_p.h" -#include -#include -#include "qmlfolderlistmodel.h" -#include - -QT_BEGIN_NAMESPACE - -class QmlFolderListModelPrivate : public QObjectPrivate -{ -public: - QmlFolderListModelPrivate() - : sortField(QmlFolderListModel::Name), sortReversed(false), count(0) { - nameFilters << QLatin1String("*"); - } - - void updateSorting() { - QDir::SortFlags flags = 0; - switch(sortField) { - case QmlFolderListModel::Unsorted: - flags |= QDir::Unsorted; - break; - case QmlFolderListModel::Name: - flags |= QDir::Name; - break; - case QmlFolderListModel::Time: - flags |= QDir::Time; - break; - case QmlFolderListModel::Size: - flags |= QDir::Size; - break; - case QmlFolderListModel::Type: - flags |= QDir::Type; - break; - } - - if (sortReversed) - flags |= QDir::Reversed; - - model.setSorting(flags); - } - - QDirModel model; - QUrl folder; - QStringList nameFilters; - QModelIndex folderIndex; - QmlFolderListModel::SortField sortField; - bool sortReversed; - int count; -}; - -/*! - \qmlclass FolderListModel - \brief The FolderListModel provides a model of the contents of a folder in a filesystem. - - FolderListModel provides access to the local filesystem. The \e folder property - specifies the folder to list. - - Qt uses "/" as a universal directory separator in the same way that "/" is - used as a path separator in URLs. If you always use "/" as a directory - separator, Qt will translate your paths to conform to the underlying - operating system. - - The roles available are: - \list - \o fileName - \o filePath - \endlist - - Additionally a file entry can be differentiated from a folder entry - via the \l isFolder() method. -*/ - -QmlFolderListModel::QmlFolderListModel(QObject *parent) - : QListModelInterface(*(new QmlFolderListModelPrivate), parent) -{ - Q_D(QmlFolderListModel); - d->model.setFilter(QDir::AllDirs | QDir::Files | QDir::Drives | QDir::NoDotAndDotDot); - connect(&d->model, SIGNAL(rowsInserted(const QModelIndex&,int,int)) - , this, SLOT(inserted(const QModelIndex&,int,int))); - connect(&d->model, SIGNAL(rowsRemoved(const QModelIndex&,int,int)) - , this, SLOT(removed(const QModelIndex&,int,int))); - connect(&d->model, SIGNAL(dataChanged(const QModelIndex&,const QModelIndex&)) - , this, SLOT(dataChanged(const QModelIndex&,const QModelIndex&))); - connect(&d->model, SIGNAL(modelReset()), this, SLOT(refresh())); - connect(&d->model, SIGNAL(layoutChanged()), this, SLOT(refresh())); -} - -QmlFolderListModel::~QmlFolderListModel() -{ -} - -QHash QmlFolderListModel::data(int index, const QList &roles) const -{ - Q_UNUSED(roles); - Q_D(const QmlFolderListModel); - QHash folderData; - QModelIndex modelIndex = d->model.index(index, 0, d->folderIndex); - if (modelIndex.isValid()) { - folderData[QDirModel::FileNameRole] = d->model.data(modelIndex, QDirModel::FileNameRole); - folderData[QDirModel::FilePathRole] = QUrl::fromLocalFile(d->model.data(modelIndex, QDirModel::FilePathRole).toString()); - } - - return folderData; -} - -int QmlFolderListModel::count() const -{ - Q_D(const QmlFolderListModel); - return d->count; -} - -QList QmlFolderListModel::roles() const -{ - QList r; - r << QDirModel::FileNameRole; - r << QDirModel::FilePathRole; - return r; -} - -QString QmlFolderListModel::toString(int role) const -{ - switch (role) { - case QDirModel::FileNameRole: - return QLatin1String("fileName"); - case QDirModel::FilePathRole: - return QLatin1String("filePath"); - } - - return QString(); -} - -/*! - \qmlproperty string FolderListModel::folder - - The \a folder property holds the folder the model is currently providing. - - It is a URL, but must be a file: or qrc: URL (or relative to such a URL). -*/ -QUrl QmlFolderListModel::folder() const -{ - Q_D(const QmlFolderListModel); - return d->folder; -} - -void QmlFolderListModel::setFolder(const QUrl &folder) -{ - Q_D(QmlFolderListModel); - if (folder == d->folder) - return; - QModelIndex index = d->model.index(folder.toLocalFile()); - if (index.isValid() && d->model.isDir(index)) { - d->folder = folder; - QMetaObject::invokeMethod(this, "refresh", Qt::QueuedConnection); - emit folderChanged(); - } -} - -QUrl QmlFolderListModel::parentFolder() const -{ - Q_D(const QmlFolderListModel); - int pos = d->folder.path().lastIndexOf(QLatin1Char('/')); - if (pos == -1) - return QUrl(); - QUrl r = d->folder; - r.setPath(d->folder.path().left(pos)); - return r; -} - -/*! - \qmlproperty list FolderListModel::nameFilters - - The \a nameFilters property contains a list of filename filters. - The filters may include the ? and * wildcards. - - The example below filters on PNG and JPEG files: - - \code - FolderListModel { - nameFilters: [ "*.png", "*.jpg" ] - } - \endcode -*/ -QStringList QmlFolderListModel::nameFilters() const -{ - Q_D(const QmlFolderListModel); - return d->nameFilters; -} - -void QmlFolderListModel::setNameFilters(const QStringList &filters) -{ - Q_D(QmlFolderListModel); - d->nameFilters = filters; - d->model.setNameFilters(d->nameFilters); -} - -void QmlFolderListModel::componentComplete() -{ - Q_D(QmlFolderListModel); - if (!d->folder.isValid() || !QDir().exists(d->folder.toLocalFile())) - setFolder(QUrl(QLatin1String("file://")+QDir::currentPath())); - - if (!d->folderIndex.isValid()) - QMetaObject::invokeMethod(this, "refresh", Qt::QueuedConnection); -} - -QmlFolderListModel::SortField QmlFolderListModel::sortField() const -{ - Q_D(const QmlFolderListModel); - return d->sortField; -} - -void QmlFolderListModel::setSortField(SortField field) -{ - Q_D(QmlFolderListModel); - if (field != d->sortField) { - d->sortField = field; - d->updateSorting(); - } -} - -bool QmlFolderListModel::sortReversed() const -{ - Q_D(const QmlFolderListModel); - return d->sortReversed; -} - -void QmlFolderListModel::setSortReversed(bool rev) -{ - Q_D(QmlFolderListModel); - if (rev != d->sortReversed) { - d->sortReversed = rev; - d->updateSorting(); - } -} - -/*! - \qmlmethod bool FolderListModel::isFolder(int index) - - Returns true if the entry \a index is a folder; otherwise - returns false. -*/ -bool QmlFolderListModel::isFolder(int index) const -{ - Q_D(const QmlFolderListModel); - if (index != -1) { - QModelIndex idx = d->model.index(index, 0, d->folderIndex); - if (idx.isValid()) - return d->model.isDir(idx); - } - return false; -} - -void QmlFolderListModel::refresh() -{ - Q_D(QmlFolderListModel); - d->folderIndex = QModelIndex(); - if (d->count) { - int tmpCount = d->count; - d->count = 0; - emit itemsRemoved(0, tmpCount); - } - d->folderIndex = d->model.index(d->folder.toLocalFile()); - d->count = d->model.rowCount(d->folderIndex); - if (d->count) { - emit itemsInserted(0, d->count); - } -} - -void QmlFolderListModel::inserted(const QModelIndex &index, int start, int end) -{ - Q_D(QmlFolderListModel); - if (index == d->folderIndex) { - d->count = d->model.rowCount(d->folderIndex); - emit itemsInserted(start, end - start + 1); - } -} - -void QmlFolderListModel::removed(const QModelIndex &index, int start, int end) -{ - Q_D(QmlFolderListModel); - if (index == d->folderIndex) { - d->count = d->model.rowCount(d->folderIndex); - emit itemsRemoved(start, end - start + 1); - } -} - -void QmlFolderListModel::dataChanged(const QModelIndex &start, const QModelIndex &end) -{ - Q_D(QmlFolderListModel); - qDebug() << "data changed"; - if (start.parent() == d->folderIndex) - emit itemsChanged(start.row(), end.row() - start.row() + 1, roles()); -} - -/*! - \qmlproperty bool FolderListModel::showDirs - - If true (the default), directories are included in the model. - - Note that the nameFilters are ignored for directories. -*/ -bool QmlFolderListModel::showDirs() const -{ - Q_D(const QmlFolderListModel); - return d->model.filter() & QDir::AllDirs; -} - -void QmlFolderListModel::setShowDirs(bool on) -{ - Q_D(QmlFolderListModel); - if (!(d->model.filter() & QDir::AllDirs) == !on) - return; - if (on) - d->model.setFilter(d->model.filter() | QDir::AllDirs | QDir::Drives); - else - d->model.setFilter(d->model.filter() & ~(QDir::AllDirs | QDir::Drives)); -} - -/*! - \qmlproperty bool FolderListModel::showDotAndDotDot - - If true, the "." and ".." directories are included in the model. - - The default is false. -*/ -bool QmlFolderListModel::showDotAndDotDot() const -{ - Q_D(const QmlFolderListModel); - return !(d->model.filter() & QDir::NoDotAndDotDot); -} - -void QmlFolderListModel::setShowDotAndDotDot(bool on) -{ - Q_D(QmlFolderListModel); - if (!(d->model.filter() & QDir::NoDotAndDotDot) == on) - return; - if (on) - d->model.setFilter(d->model.filter() & ~QDir::NoDotAndDotDot); - else - d->model.setFilter(d->model.filter() | QDir::NoDotAndDotDot); -} - -/*! - \qmlproperty bool FolderListModel::showOnlyReadable - - If true, only readable files and directories are shown. - - The default is false. -*/ -bool QmlFolderListModel::showOnlyReadable() const -{ - Q_D(const QmlFolderListModel); - return d->model.filter() & QDir::Readable; -} - -void QmlFolderListModel::setShowOnlyReadable(bool on) -{ - Q_D(QmlFolderListModel); - if (!(d->model.filter() & QDir::Readable) == !on) - return; - if (on) - d->model.setFilter(d->model.filter() | QDir::Readable); - else - d->model.setFilter(d->model.filter() & ~QDir::Readable); -} - - -QML_DEFINE_TYPE(Qt,4,6,(QT_VERSION&0x00ff00)>>8,FolderListModel,QmlFolderListModel) - -QT_END_NAMESPACE - diff --git a/src/declarative/extra/qmlfolderlistmodel.h b/src/declarative/extra/qmlfolderlistmodel.h deleted file mode 100644 index 66e600b..0000000 --- a/src/declarative/extra/qmlfolderlistmodel.h +++ /dev/null @@ -1,128 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Qt Software Information (qt-info@nokia.com) -** -** This file is part of the QtDeclarative module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the either Technology Preview License Agreement or the -** Beta Release License Agreement. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at qt-sales@nokia.com. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QMLFOLDERLISTMODEL_H -#define QMLFOLDERLISTMODEL_H - -#include -#include - -QT_BEGIN_HEADER - -QT_BEGIN_NAMESPACE - -QT_MODULE(Declarative) - -class QmlContext; -class QModelIndex; - -class QmlFolderListModelPrivate; -class Q_DECLARATIVE_EXPORT QmlFolderListModel : public QListModelInterface, public QmlParserStatus -{ - Q_OBJECT - Q_INTERFACES(QmlParserStatus) - - Q_PROPERTY(QUrl folder READ folder WRITE setFolder NOTIFY folderChanged) - Q_PROPERTY(QUrl parentFolder READ parentFolder NOTIFY folderChanged) - Q_PROPERTY(QStringList nameFilters READ nameFilters WRITE setNameFilters) - Q_PROPERTY(SortField sortField READ sortField WRITE setSortField) - Q_PROPERTY(bool sortReversed READ sortReversed WRITE setSortReversed) - Q_PROPERTY(bool showDirs READ showDirs WRITE setShowDirs) - Q_PROPERTY(bool showDotAndDotDot READ showDotAndDotDot WRITE setShowDotAndDotDot) - Q_PROPERTY(bool showOnlyReadable READ showOnlyReadable WRITE setShowOnlyReadable) - -public: - QmlFolderListModel(QObject *parent = 0); - ~QmlFolderListModel(); - - virtual QHash data(int index, const QList &roles = (QList())) const; - virtual int count() const; - virtual QList roles() const; - virtual QString toString(int role) const; - - QUrl folder() const; - void setFolder(const QUrl &folder); - - QUrl parentFolder() const; - - QStringList nameFilters() const; - void setNameFilters(const QStringList &filters); - - virtual void componentComplete(); - - Q_INVOKABLE bool isFolder(int index) const; - - enum SortField { Unsorted, Name, Time, Size, Type }; - SortField sortField() const; - void setSortField(SortField field); - Q_ENUMS(SortField) - - bool sortReversed() const; - void setSortReversed(bool rev); - - bool showDirs() const; - void setShowDirs(bool); - bool showDotAndDotDot() const; - void setShowDotAndDotDot(bool); - bool showOnlyReadable() const; - void setShowOnlyReadable(bool); - -Q_SIGNALS: - void folderChanged(); - -private Q_SLOTS: - void refresh(); - void inserted(const QModelIndex &index, int start, int end); - void removed(const QModelIndex &index, int start, int end); - void dataChanged(const QModelIndex &start, const QModelIndex &end); - -private: - Q_DECLARE_PRIVATE(QmlFolderListModel) - Q_DISABLE_COPY(QmlFolderListModel) -}; - -QT_END_NAMESPACE - -QML_DECLARE_TYPE(QmlFolderListModel) - -QT_END_HEADER - -#endif // QMLFOLDERLISTMODEL_H -- cgit v0.12 From b54b0357f59fd398db07161fd8320b306220c104 Mon Sep 17 00:00:00 2001 From: Martin Jones Date: Wed, 21 Oct 2009 11:39:17 +1000 Subject: Doc. --- src/declarative/fx/qfxlistview.cpp | 46 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/src/declarative/fx/qfxlistview.cpp b/src/declarative/fx/qfxlistview.cpp index 4fb0ec1..2ea1cb7 100644 --- a/src/declarative/fx/qfxlistview.cpp +++ b/src/declarative/fx/qfxlistview.cpp @@ -864,6 +864,52 @@ QFxListView::~QFxListView() } /*! + \qmlattachedproperty bool ListView::isCurrentItem + This attched property is true if this delegate is the current item; otherwise false. + + It is attached to each instance of the delegate. + + This property may be used to adjust the appearance of the current item, for example: + + \snippet doc/src/snippets/declarative/listview/highlight.qml 0 +*/ + +/*! + \qmlattachedproperty ListView ListView::view + This attached property holds the view that manages this delegate instance. + + It is attached to each instance of the delegate. +*/ + +/*! + \qmlattachedproperty string ListView::prevSection + This attached property holds the section of the previous element. + + It is attached to each instance of the delegate. + + The section is evaluated using the \l {ListView::sectionExpression}{sectionExpression} property. +*/ + +/*! + \qmlattachedproperty string ListView::section + This attached property holds the section of this element. + + It is attached to each instance of the delegate. + + The section is evaluated using the \l {ListView::sectionExpression}{sectionExpression} property. +*/ + +/*! + \qmlattachedproperty bool ListView::delayRemove + This attached property holds whether the delegate may be destroyed. + + It is attached to each instance of the delegate. + + It is sometimes necessary to delay the destruction of an item + until an animation completes. +*/ + +/*! \qmlproperty model ListView::model This property holds the model providing data for the list. -- cgit v0.12 From db6a53356aa72e59fcbc631c5cde77c14d51acc1 Mon Sep 17 00:00:00 2001 From: Martin Jones Date: Wed, 21 Oct 2009 11:40:50 +1000 Subject: Docs. --- doc/src/declarative/qmlmodels.qdoc | 45 +++++++++++++++++++--- .../snippets/declarative/listview/highlight.qml | 12 ++++++ 2 files changed, 51 insertions(+), 6 deletions(-) diff --git a/doc/src/declarative/qmlmodels.qdoc b/doc/src/declarative/qmlmodels.qdoc index 6ebb734..45df29b 100644 --- a/doc/src/declarative/qmlmodels.qdoc +++ b/doc/src/declarative/qmlmodels.qdoc @@ -50,12 +50,18 @@ creates an instance for each item in the model. Models may be static, or have items modified, inserted, removed or moved dynamically. Data is provided to the delegate via named data roles which the -delegate may bind to. A special \e index role containing the -index of the item in the model is also available. Models that do -not have named roles will have the data provided via the \e modelData -role. The \e modelData role is also provided for Models that have -only one role. In this case the \e modelData role contains the same -data as the named role. +delegate may bind to. The roles are exposed as properties of the +\model property, though this property is set as a default property +of the delegate so, unless there is a naming clash with a +property in the delegate, the roles are usually accessed unqualified. + +A special \e index role containing the index of the item in the model +is also available. + +Models that do not have named roles will have the data provided via +the \e modelData role. The \e modelData role is also provided for +Models that have only one role. In this case the \e modelData role +contains the same data as the named role. There are a number of QML elements that operate using data models: @@ -189,4 +195,31 @@ ListView { An Object Instance specifies a model with a single Object element. The properties of the object are provided as roles. +The example below creates a list with one item, showing the color of the +\e myText text. Note the use of the \e model property to specify the model +data rather than the \e color property of the Text element in the delegate. + +\code +Rectangle { + Text { + id: myText + text: "Hello" + color: "#dd44ee" + } + + Component { + id: myDelegate + Text { + text: model.color + } + } + ListView { + anchors.fill: parent + anchors.topMargin: 30 + model: myText + delegate: myDelegate + } +} +\endcode + */ diff --git a/doc/src/snippets/declarative/listview/highlight.qml b/doc/src/snippets/declarative/listview/highlight.qml index 2234ee7..7970ede 100644 --- a/doc/src/snippets/declarative/listview/highlight.qml +++ b/doc/src/snippets/declarative/listview/highlight.qml @@ -20,6 +20,18 @@ Rectangle { Text { text: 'Name: ' + name } Text { text: 'Number: ' + number } } + // Use the ListView.isCurrentItem attached property to + // indent the item if it is the current item. + states: [ + State { + name: "Current" + when: wrapper.ListView.isCurrentItem + PropertyChanges { target: wrapper; x: 10 } + } + ] + transitions: [ + Transition { NumberAnimation { properties: "x"; duration: 200 } } + ] } } //! [0] -- cgit v0.12 From 2f1f614aec6011a60102f2ca45980fb9b62a2e2c Mon Sep 17 00:00:00 2001 From: Michael Brasser Date: Wed, 21 Oct 2009 09:16:48 +1000 Subject: Add missing Q_OBJECT macros. --- src/declarative/util/qmlanimation_p.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/declarative/util/qmlanimation_p.h b/src/declarative/util/qmlanimation_p.h index 4f6edb7..22c4e2d 100644 --- a/src/declarative/util/qmlanimation_p.h +++ b/src/declarative/util/qmlanimation_p.h @@ -92,6 +92,7 @@ private: //performs an action of type QAbstractAnimationAction class QActionAnimation : public QAbstractAnimation { + Q_OBJECT public: QActionAnimation(QObject *parent = 0) : QAbstractAnimation(parent), animAction(0), policy(KeepWhenStopped) {} QActionAnimation(QAbstractAnimationAction *action, QObject *parent = 0) @@ -126,6 +127,7 @@ private: //animates QmlTimeLineValue (assumes start and end values will be reals or compatible) class QmlTimeLineValueAnimator : public QVariantAnimation { + Q_OBJECT public: QmlTimeLineValueAnimator(QObject *parent = 0) : QVariantAnimation(parent), animValue(0), fromSourced(0), policy(KeepWhenStopped) {} void setAnimValue(QmlTimeLineValue *value, DeletionPolicy p) -- cgit v0.12 From 4b36e00eba66eab873d3fe15aa3ceedd5dd18ae0 Mon Sep 17 00:00:00 2001 From: Michael Brasser Date: Wed, 21 Oct 2009 09:17:18 +1000 Subject: Revert "Additional temporary fix for animation bug." This reverts commit 04eae20d3b86cc61ab3b3bdded74caa370a84c43. --- src/corelib/animation/qabstractanimation.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/corelib/animation/qabstractanimation.cpp b/src/corelib/animation/qabstractanimation.cpp index 8d34a98..f23ad3c 100644 --- a/src/corelib/animation/qabstractanimation.cpp +++ b/src/corelib/animation/qabstractanimation.cpp @@ -228,7 +228,11 @@ void QUnifiedTimer::updateAnimationsTime() void QUnifiedTimer::restartAnimationTimer() { - if (!animationTimer.isActive()) { + if (runningLeafAnimations == 0 && !runningPauseAnimations.isEmpty()) { + int closestTimeToFinish = closestPauseAnimationTimeToFinish(); + animationTimer.start(closestTimeToFinish, this); + isPauseTimerActive = true; + } else if (!animationTimer.isActive() || isPauseTimerActive) { animationTimer.start(timingInterval, this); isPauseTimerActive = false; } -- cgit v0.12 From b8c939903b8afc0abe38ab2e315a5bda32221aae Mon Sep 17 00:00:00 2001 From: Michael Brasser Date: Wed, 21 Oct 2009 09:29:13 +1000 Subject: Manually apply proper animation fixes. --- src/corelib/animation/qabstractanimation.cpp | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/src/corelib/animation/qabstractanimation.cpp b/src/corelib/animation/qabstractanimation.cpp index f23ad3c..0d5f278 100644 --- a/src/corelib/animation/qabstractanimation.cpp +++ b/src/corelib/animation/qabstractanimation.cpp @@ -278,11 +278,11 @@ void QUnifiedTimer::registerAnimation(QAbstractAnimation *animation, bool isTopL void QUnifiedTimer::unregisterAnimation(QAbstractAnimation *animation) { - unregisterRunningAnimation(animation); - if (!QAbstractAnimationPrivate::get(animation)->hasRegisteredTimer) return; + unregisterRunningAnimation(animation); + int idx = animations.indexOf(animation); if (idx != -1) { animations.removeAt(idx); @@ -318,6 +318,7 @@ void QUnifiedTimer::unregisterRunningAnimation(QAbstractAnimation *animation) runningPauseAnimations.removeOne(animation); else runningLeafAnimations--; + Q_ASSERT(runningLeafAnimations >= 0); } int QUnifiedTimer::closestPauseAnimationTimeToFinish() @@ -328,9 +329,9 @@ int QUnifiedTimer::closestPauseAnimationTimeToFinish() int timeToFinish; if (animation->direction() == QAbstractAnimation::Forward) - timeToFinish = animation->duration() - QAbstractAnimationPrivate::get(animation)->currentTime; + timeToFinish = animation->duration() - animation->currentTime(); else - timeToFinish = QAbstractAnimationPrivate::get(animation)->totalCurrentTime; + timeToFinish = animation->currentTime(); if (timeToFinish < closestTimeToFinish) closestTimeToFinish = timeToFinish; @@ -648,13 +649,13 @@ int QAbstractAnimation::currentLoop() const */ int QAbstractAnimation::totalDuration() const { - Q_D(const QAbstractAnimation); - if (d->loopCount < 0) - return -1; int dura = duration(); - if (dura == -1) + if (dura <= 0) + return dura; + int loopcount = loopCount(); + if (loopcount < 0) return -1; - return dura * d->loopCount; + return dura * loopcount; } /*! @@ -685,7 +686,7 @@ void QAbstractAnimation::setCurrentTime(int msecs) // Calculate new time and loop. int dura = duration(); - int totalDura = (d->loopCount < 0 || dura == -1) ? -1 : dura * d->loopCount; + int totalDura = dura <= 0 ? dura : ((d->loopCount < 0) ? -1 : dura * d->loopCount); if (totalDura != -1) msecs = qMin(totalDura, msecs); d->totalCurrentTime = msecs; -- cgit v0.12 From 2c70994c3b9b0839ef5d489e6dfcaaf6c4ed6b4d Mon Sep 17 00:00:00 2001 From: Michael Brasser Date: Wed, 21 Oct 2009 10:57:02 +1000 Subject: Rename QBindableMap to QmlPropertyMap. Task-number: QT-2316 --- src/declarative/extra/extra.pri | 2 - src/declarative/extra/qbindablemap.cpp | 182 ------------------- src/declarative/extra/qbindablemap.h | 86 --------- src/declarative/util/qmlpropertymap.cpp | 198 +++++++++++++++++++++ src/declarative/util/qmlpropertymap.h | 83 +++++++++ src/declarative/util/util.pri | 6 +- .../auto/declarative/qbindablemap/qbindablemap.pro | 3 - .../declarative/qbindablemap/tst_qbindablemap.cpp | 77 -------- .../declarative/qmlpropertymap/qmlpropertymap.pro | 3 + .../qmlpropertymap/tst_qmlpropertymap.cpp | 77 ++++++++ 10 files changed, 365 insertions(+), 352 deletions(-) delete mode 100644 src/declarative/extra/qbindablemap.cpp delete mode 100644 src/declarative/extra/qbindablemap.h create mode 100644 src/declarative/util/qmlpropertymap.cpp create mode 100644 src/declarative/util/qmlpropertymap.h delete mode 100644 tests/auto/declarative/qbindablemap/qbindablemap.pro delete mode 100644 tests/auto/declarative/qbindablemap/tst_qbindablemap.cpp create mode 100644 tests/auto/declarative/qmlpropertymap/qmlpropertymap.pro create mode 100644 tests/auto/declarative/qmlpropertymap/tst_qmlpropertymap.cpp diff --git a/src/declarative/extra/extra.pri b/src/declarative/extra/extra.pri index 726f099..502504a 100644 --- a/src/declarative/extra/extra.pri +++ b/src/declarative/extra/extra.pri @@ -6,7 +6,6 @@ SOURCES += \ extra/qfxanimatedimageitem.cpp \ extra/qfxparticles.cpp \ extra/qmlbehavior.cpp \ - extra/qbindablemap.cpp \ extra/qmlfontloader.cpp HEADERS += \ @@ -18,7 +17,6 @@ HEADERS += \ extra/qfxanimatedimageitem_p.h \ extra/qfxparticles.h \ extra/qmlbehavior.h \ - extra/qbindablemap.h \ extra/qmlfontloader.h contains(QT_CONFIG, xmlpatterns) { diff --git a/src/declarative/extra/qbindablemap.cpp b/src/declarative/extra/qbindablemap.cpp deleted file mode 100644 index 5254e2a..0000000 --- a/src/declarative/extra/qbindablemap.cpp +++ /dev/null @@ -1,182 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Qt Software Information (qt-info@nokia.com) -** -** This file is part of the QtDeclarative module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the either Technology Preview License Agreement or the -** Beta Release License Agreement. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at qt-sales@nokia.com. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qbindablemap.h" -#include -#include - -QT_BEGIN_NAMESPACE - -//QBindableMapMetaObject lets us listen for changes coming from QML -//so we can emit the changed signal. -class QBindableMapMetaObject : public QmlOpenMetaObject -{ -public: - QBindableMapMetaObject(QBindableMap *obj) : QmlOpenMetaObject(obj) - { - map = obj; - } - -protected: - virtual void propertyWrite(int index) - { - map->emitChanged(QString::fromUtf8(name(index))); - } - -private: - QBindableMap *map; -}; - -/*! - \class QBindableMap - \brief The QBindableMap class allows you to set key-value pairs that can be used in bindings. - - QBindableMap provides a convenient way to expose domain data to the UI layer. - The following example shows how you might declare data in C++ and then - access it in QML. - - Setup in C++: - \code - //create our data - QBindableMap ownerData; - ownerData.setValue("name", QVariant(QString("John Smith"))); - ownerData.setValue("phone", QVariant(QString("555-5555"))); - - //expose it to the UI layer - QmlContext *ctxt = view->bindContext(); - ctxt->setProperty("owner", &data); - \endcode - - Then, in QML: - \code - Text { text: owner.name } - Text { text: owner.phone } - \endcode - - The binding is dynamic - whenever a key's value is updated, anything bound to that - key will be updated as well. - - To detect value changes made in the UI layer you can connect to the changed() signal. - However, note that changed() is \b NOT emitted when changes are made by calling setValue() - or clearValue() - it is only emitted when a value is updated from QML. -*/ - -// is there a more efficient way to store/return keys? -// (or should we just provide an iterator or something else instead?) -// can we provide a way to clear keys? -// do we want to make any claims regarding key ordering? -// should we have signals for insertion and and deletion -- becoming more model like -// should we emit change for our own changes as well? -// Bug or Feature?: values can be created in QML (owner.somethingElse = "Hello") will create somethingElse property. (need to verify if this is actually the case) -// Bug or Feature?: all values are read-write (there are no read-only values) - -/*! - Constructs a bindable map with parent object \a parent. -*/ -QBindableMap::QBindableMap(QObject *parent) -: QObject(parent) -{ - m_mo = new QBindableMapMetaObject(this); -} - -/*! - Destroys the bindable map. -*/ -QBindableMap::~QBindableMap() -{ -} - -/*! - Clears the value (if any) associated with \a key. -*/ -void QBindableMap::clearValue(const QString &key) -{ - //m_keys.remove(); //### - m_mo->setValue(key.toUtf8(), QVariant()); - //emit changed(key); -} - -/*! - Returns the value associated with \a key. - - If no value has been set for this key (or if the value has been cleared), - an invalid QVariant is returned. -*/ -QVariant QBindableMap::value(const QString &key) const -{ - return m_mo->value(key.toUtf8()); -} - -/*! - Sets the value associated with \a key to \a value. - - If the key doesn't exist, it is automatically created. -*/ -void QBindableMap::setValue(const QString &key, QVariant value) -{ - if (!m_keys.contains(key)) - m_keys.append(key); - m_mo->setValue(key.toUtf8(), value); - //emit changed(key); -} - -/*! - Returns the list of keys. - - Keys that have been cleared will still appear in this list, even though their - associated values are invalid QVariants. -*/ -QStringList QBindableMap::keys() const -{ - return m_keys; -} - -/*! - \fn void QBindableMap::changed(const QString &key) - This signal is emitted whenever one of the values in the map is changed. \a key - is the key corresponding to the value that was changed. - */ - -void QBindableMap::emitChanged(const QString &key) -{ - emit changed(key); -} -QT_END_NAMESPACE diff --git a/src/declarative/extra/qbindablemap.h b/src/declarative/extra/qbindablemap.h deleted file mode 100644 index aa1908e..0000000 --- a/src/declarative/extra/qbindablemap.h +++ /dev/null @@ -1,86 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Qt Software Information (qt-info@nokia.com) -** -** This file is part of the QtDeclarative module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the either Technology Preview License Agreement or the -** Beta Release License Agreement. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at qt-sales@nokia.com. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QBINDABLEMAP_H -#define QBINDABLEMAP_H - -#include -#include -#include -#include -#include - -QT_BEGIN_HEADER - -QT_BEGIN_NAMESPACE - -QT_MODULE(Declarative) - -class QBindableMapMetaObject; -class Q_DECLARATIVE_EXPORT QBindableMap : public QObject -{ - Q_OBJECT -public: - QBindableMap(QObject *parent = 0); - virtual ~QBindableMap(); - - QVariant value(const QString &key) const; - void setValue(const QString &key, QVariant value); - void clearValue(const QString &key); - - Q_INVOKABLE QStringList keys() const; - -Q_SIGNALS: - void changed(const QString &key); - -private: - Q_DISABLE_COPY(QBindableMap) - void emitChanged(const QString &key); - QBindableMapMetaObject *m_mo; - QStringList m_keys; - friend class QBindableMapMetaObject; -}; - -QT_END_NAMESPACE - -QT_END_HEADER - -#endif diff --git a/src/declarative/util/qmlpropertymap.cpp b/src/declarative/util/qmlpropertymap.cpp new file mode 100644 index 0000000..e23eebf --- /dev/null +++ b/src/declarative/util/qmlpropertymap.cpp @@ -0,0 +1,198 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qmlpropertymap.h" +#include +#include + +QT_BEGIN_NAMESPACE + +//QBindableMapMetaObject lets us listen for changes coming from QML +//so we can emit the changed signal. +class QmlPropertyMapMetaObject : public QmlOpenMetaObject +{ +public: + QmlPropertyMapMetaObject(QmlPropertyMap *obj, QmlPropertyMapPrivate *objPriv); + +protected: + virtual void propertyWrite(int index); + +private: + QmlPropertyMap *map; + QmlPropertyMapPrivate *priv; +}; + +class QmlPropertyMapPrivate : public QObjectPrivate +{ + Q_DECLARE_PUBLIC(QmlPropertyMap) +public: + QmlPropertyMapMetaObject *mo; + QStringList keys; + void emitChanged(const QString &key); +}; + +void QmlPropertyMapPrivate::emitChanged(const QString &key) +{ + Q_Q(QmlPropertyMap); + emit q->changed(key); +} + +QmlPropertyMapMetaObject::QmlPropertyMapMetaObject(QmlPropertyMap *obj, QmlPropertyMapPrivate *objPriv) : QmlOpenMetaObject(obj) +{ + map = obj; + priv = objPriv; +} + +void QmlPropertyMapMetaObject::propertyWrite(int index) +{ + priv->emitChanged(QString::fromUtf8(name(index))); +} + +/*! + \class QBindableMap + \brief The QBindableMap class allows you to set key-value pairs that can be used in bindings. + + QBindableMap provides a convenient way to expose domain data to the UI layer. + The following example shows how you might declare data in C++ and then + access it in QML. + + Setup in C++: + \code + //create our data + QBindableMap ownerData; + ownerData.setValue("name", QVariant(QString("John Smith"))); + ownerData.setValue("phone", QVariant(QString("555-5555"))); + + //expose it to the UI layer + QmlContext *ctxt = view->bindContext(); + ctxt->setProperty("owner", &data); + \endcode + + Then, in QML: + \code + Text { text: owner.name } + Text { text: owner.phone } + \endcode + + The binding is dynamic - whenever a key's value is updated, anything bound to that + key will be updated as well. + + To detect value changes made in the UI layer you can connect to the changed() signal. + However, note that changed() is \b NOT emitted when changes are made by calling setValue() + or clearValue() - it is only emitted when a value is updated from QML. +*/ + +// is there a more efficient way to store/return keys? +// (or should we just provide an iterator or something else instead?) +// can we provide a way to clear keys? +// do we want to make any claims regarding key ordering? +// should we have signals for insertion and and deletion -- becoming more model like + +/*! + Constructs a bindable map with parent object \a parent. +*/ +QmlPropertyMap::QmlPropertyMap(QObject *parent) +: QObject(*(new QmlPropertyMapPrivate), parent) +{ + Q_D(QmlPropertyMap); + d->mo = new QmlPropertyMapMetaObject(this, d); +} + +/*! + Destroys the bindable map. +*/ +QmlPropertyMap::~QmlPropertyMap() +{ +} + +/*! + Clears the value (if any) associated with \a key. +*/ +void QmlPropertyMap::clearValue(const QString &key) +{ + Q_D(QmlPropertyMap); + d->mo->setValue(key.toUtf8(), QVariant()); +} + +/*! + Returns the value associated with \a key. + + If no value has been set for this key (or if the value has been cleared), + an invalid QVariant is returned. +*/ +QVariant QmlPropertyMap::value(const QString &key) const +{ + Q_D(const QmlPropertyMap); + return d->mo->value(key.toUtf8()); +} + +/*! + Sets the value associated with \a key to \a value. + + If the key doesn't exist, it is automatically created. +*/ +void QmlPropertyMap::setValue(const QString &key, const QVariant &value) +{ + Q_D(QmlPropertyMap); + if (!d->keys.contains(key)) + d->keys.append(key); + d->mo->setValue(key.toUtf8(), value); +} + +/*! + Returns the list of keys. + + Keys that have been cleared will still appear in this list, even though their + associated values are invalid QVariants. +*/ +QStringList QmlPropertyMap::keys() const +{ + Q_D(const QmlPropertyMap); + return d->keys; +} + +/*! + \fn void QBindableMap::changed(const QString &key) + This signal is emitted whenever one of the values in the map is changed. \a key + is the key corresponding to the value that was changed. +*/ + +QT_END_NAMESPACE diff --git a/src/declarative/util/qmlpropertymap.h b/src/declarative/util/qmlpropertymap.h new file mode 100644 index 0000000..295f4b7 --- /dev/null +++ b/src/declarative/util/qmlpropertymap.h @@ -0,0 +1,83 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QMLPROPERTYMAP_H +#define QMLPROPERTYMAP_H + +#include +#include +#include +#include +#include + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Declarative) + +class QmlPropertyMapPrivate; +class Q_DECLARATIVE_EXPORT QmlPropertyMap : public QObject +{ + Q_OBJECT +public: + QmlPropertyMap(QObject *parent = 0); + virtual ~QmlPropertyMap(); + + QVariant value(const QString &key) const; + void setValue(const QString &key, const QVariant &value); + void clearValue(const QString &key); + + Q_INVOKABLE QStringList keys() const; + +Q_SIGNALS: + void changed(const QString &key); + +private: + Q_DECLARE_PRIVATE(QmlPropertyMap) + Q_DISABLE_COPY(QmlPropertyMap) +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/declarative/util/util.pri b/src/declarative/util/util.pri index ec9967c..01ad898 100644 --- a/src/declarative/util/util.pri +++ b/src/declarative/util/util.pri @@ -19,7 +19,8 @@ SOURCES += \ util/qmlopenmetaobject.cpp \ util/qmltimeline.cpp \ util/qmltimer.cpp \ - util/qmlbind.cpp + util/qmlbind.cpp \ + util/qmlpropertymap.cpp HEADERS += \ util/qmlview.h \ @@ -46,4 +47,5 @@ HEADERS += \ util/qmlnullablevalue_p.h \ util/qmltimeline_p.h \ util/qmltimer.h \ - util/qmlbind.h + util/qmlbind.h \ + util/qmlpropertymap.h diff --git a/tests/auto/declarative/qbindablemap/qbindablemap.pro b/tests/auto/declarative/qbindablemap/qbindablemap.pro deleted file mode 100644 index b042405..0000000 --- a/tests/auto/declarative/qbindablemap/qbindablemap.pro +++ /dev/null @@ -1,3 +0,0 @@ -load(qttest_p4) -contains(QT_CONFIG,declarative): QT += declarative -SOURCES += tst_qbindablemap.cpp diff --git a/tests/auto/declarative/qbindablemap/tst_qbindablemap.cpp b/tests/auto/declarative/qbindablemap/tst_qbindablemap.cpp deleted file mode 100644 index c1b31c2..0000000 --- a/tests/auto/declarative/qbindablemap/tst_qbindablemap.cpp +++ /dev/null @@ -1,77 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include - -class tst_QBindableMap : public QObject -{ - Q_OBJECT -public: - tst_QBindableMap() {} - -private slots: - void insert(); - void clear(); - void changed(); -}; - -void tst_QBindableMap::insert() -{ - QBindableMap map; - map.setValue(QLatin1String("key1"),100); - map.setValue(QLatin1String("key2"),200); - QVERIFY(map.keys().count() == 2); - - QCOMPARE(map.value(QLatin1String("key1")), QVariant(100)); - QCOMPARE(map.value(QLatin1String("key2")), QVariant(200)); - - map.setValue(QLatin1String("key1"),"Hello World"); - QCOMPARE(map.value(QLatin1String("key1")), QVariant("Hello World")); -} - -void tst_QBindableMap::clear() -{ - QBindableMap map; - map.setValue(QLatin1String("key1"),100); - QVERIFY(map.keys().count() == 1); - - QCOMPARE(map.value(QLatin1String("key1")), QVariant(100)); - - map.clearValue(QLatin1String("key1")); - QVERIFY(map.keys().count() == 1); - QCOMPARE(map.value(QLatin1String("key1")), QVariant()); -} - -void tst_QBindableMap::changed() -{ - QBindableMap map; - QSignalSpy spy(&map, SIGNAL(changed(const QString&))); - map.setValue(QLatin1String("key1"),100); - map.setValue(QLatin1String("key2"),200); - QCOMPARE(spy.count(), 0); - - map.clearValue(QLatin1String("key1")); - QCOMPARE(spy.count(), 0); - - //make changes in QML - QmlEngine engine; - QmlContext *ctxt = engine.rootContext(); - ctxt->setContextProperty(QLatin1String("testdata"), &map); - QmlComponent component(&engine, "import Qt 4.6\nText { text: { testdata.key1 = 'Hello World'; 'X' } }", - QUrl("file://")); - QVERIFY(component.isReady()); - QFxText *txt = qobject_cast(component.create()); - QVERIFY(txt); - QCOMPARE(txt->text(), QString('X')); - QCOMPARE(spy.count(), 1); - QList arguments = spy.takeFirst(); - QCOMPARE(arguments.at(0).toString(),QLatin1String("key1")); - QCOMPARE(map.value(QLatin1String("key1")), QVariant("Hello World")); -} - -QTEST_MAIN(tst_QBindableMap) - -#include "tst_qbindablemap.moc" diff --git a/tests/auto/declarative/qmlpropertymap/qmlpropertymap.pro b/tests/auto/declarative/qmlpropertymap/qmlpropertymap.pro new file mode 100644 index 0000000..94f138f --- /dev/null +++ b/tests/auto/declarative/qmlpropertymap/qmlpropertymap.pro @@ -0,0 +1,3 @@ +load(qttest_p4) +contains(QT_CONFIG,declarative): QT += declarative +SOURCES += tst_qmlpropertymap.cpp diff --git a/tests/auto/declarative/qmlpropertymap/tst_qmlpropertymap.cpp b/tests/auto/declarative/qmlpropertymap/tst_qmlpropertymap.cpp new file mode 100644 index 0000000..a923234 --- /dev/null +++ b/tests/auto/declarative/qmlpropertymap/tst_qmlpropertymap.cpp @@ -0,0 +1,77 @@ +#include +#include +#include +#include +#include +#include +#include + +class tst_QmlPropertyMap : public QObject +{ + Q_OBJECT +public: + tst_QmlPropertyMap() {} + +private slots: + void insert(); + void clear(); + void changed(); +}; + +void tst_QmlPropertyMap::insert() +{ + QmlPropertyMap map; + map.setValue(QLatin1String("key1"),100); + map.setValue(QLatin1String("key2"),200); + QVERIFY(map.keys().count() == 2); + + QCOMPARE(map.value(QLatin1String("key1")), QVariant(100)); + QCOMPARE(map.value(QLatin1String("key2")), QVariant(200)); + + map.setValue(QLatin1String("key1"),"Hello World"); + QCOMPARE(map.value(QLatin1String("key1")), QVariant("Hello World")); +} + +void tst_QmlPropertyMap::clear() +{ + QmlPropertyMap map; + map.setValue(QLatin1String("key1"),100); + QVERIFY(map.keys().count() == 1); + + QCOMPARE(map.value(QLatin1String("key1")), QVariant(100)); + + map.clearValue(QLatin1String("key1")); + QVERIFY(map.keys().count() == 1); + QCOMPARE(map.value(QLatin1String("key1")), QVariant()); +} + +void tst_QmlPropertyMap::changed() +{ + QmlPropertyMap map; + QSignalSpy spy(&map, SIGNAL(changed(const QString&))); + map.setValue(QLatin1String("key1"),100); + map.setValue(QLatin1String("key2"),200); + QCOMPARE(spy.count(), 0); + + map.clearValue(QLatin1String("key1")); + QCOMPARE(spy.count(), 0); + + //make changes in QML + QmlEngine engine; + QmlContext *ctxt = engine.rootContext(); + ctxt->setContextProperty(QLatin1String("testdata"), &map); + QmlComponent component(&engine, "import Qt 4.6\nText { text: { testdata.key1 = 'Hello World'; 'X' } }", + QUrl("file://")); + QVERIFY(component.isReady()); + QFxText *txt = qobject_cast(component.create()); + QVERIFY(txt); + QCOMPARE(txt->text(), QString('X')); + QCOMPARE(spy.count(), 1); + QList arguments = spy.takeFirst(); + QCOMPARE(arguments.at(0).toString(),QLatin1String("key1")); + QCOMPARE(map.value(QLatin1String("key1")), QVariant("Hello World")); +} + +QTEST_MAIN(tst_QmlPropertyMap) + +#include "tst_qmlpropertymap.moc" -- cgit v0.12 From ee086ea4fd9baa3df94909dd9f5884578c1eaeb7 Mon Sep 17 00:00:00 2001 From: Michael Brasser Date: Wed, 21 Oct 2009 11:50:01 +1000 Subject: Prepend element name for detailed attached property docs. --- tools/qdoc3/cppcodemarker.cpp | 4 ++++ tools/qdoc3/node.h | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/tools/qdoc3/cppcodemarker.cpp b/tools/qdoc3/cppcodemarker.cpp index 3bee3d9..30ea251 100644 --- a/tools/qdoc3/cppcodemarker.cpp +++ b/tools/qdoc3/cppcodemarker.cpp @@ -353,6 +353,10 @@ QString CppCodeMarker::markedUpQmlItem(const Node* node, bool summary) QString name = taggedQmlNode(node); if (summary) { name = linkTag(node,name); + } else if (node->type() == Node::QmlProperty) { + const QmlPropertyNode* pn = static_cast(node); + if (pn->isAttached()) + name.prepend(pn->element() + QLatin1Char('.')); } name = "<@name>" + name + ""; QString synopsis = name; diff --git a/tools/qdoc3/node.h b/tools/qdoc3/node.h index c6f860f..6b19f60 100644 --- a/tools/qdoc3/node.h +++ b/tools/qdoc3/node.h @@ -376,7 +376,7 @@ class QmlPropGroupNode : public FakeNode bool attached); virtual ~QmlPropGroupNode() { } - const QString& element() const { return name(); } + const QString& element() const { return parent()->name(); } void setDefault() { isdefault = true; } bool isDefault() const { return isdefault; } bool isAttached() const { return att; } @@ -405,7 +405,7 @@ class QmlPropertyNode : public LeafNode bool isDesignable() const { return fromTrool(des,false); } bool isAttached() const { return att; } - const QString& element() const { return parent()->name(); } + const QString& element() const { return static_cast(parent())->element(); } private: enum Trool { Trool_True, Trool_False, Trool_Default }; -- cgit v0.12