diff options
author | Martin Jones <martin.jones@nokia.com> | 2009-09-17 06:37:15 (GMT) |
---|---|---|
committer | Martin Jones <martin.jones@nokia.com> | 2009-09-17 06:37:15 (GMT) |
commit | 2f9017c7736b3f8db721f6605e6131ab376cb864 (patch) | |
tree | e2a5c7fdacdc19e2ebddcb6dcf628255d81d78f2 | |
parent | 0c2e40683007c9405b8fc9f7efbd728ef519d78f (diff) | |
parent | 8caff8b4be02a2f28c9a2a50d3b5ef274138021e (diff) | |
download | Qt-2f9017c7736b3f8db721f6605e6131ab376cb864.zip Qt-2f9017c7736b3f8db721f6605e6131ab376cb864.tar.gz Qt-2f9017c7736b3f8db721f6605e6131ab376cb864.tar.bz2 |
Merge branch 'kinetic-declarativeui' of git@scm.dev.nokia.troll.no:qt/kinetic into kinetic-declarativeui
23 files changed, 501 insertions, 50 deletions
diff --git a/doc/src/declarative/elements.qdoc b/doc/src/declarative/elements.qdoc index ca17fda..1fe4892 100644 --- a/doc/src/declarative/elements.qdoc +++ b/doc/src/declarative/elements.qdoc @@ -36,7 +36,7 @@ The following table lists the QML elements provided by the Qt Declarative module \o \l ParentAction \o \l ScriptAction \o \l Transition -\o \l Follow +\o \l SpringFollow \o \l EaseFollow \o \l Behavior \endlist @@ -86,7 +86,6 @@ The following table lists the QML elements provided by the Qt Declarative module \list \o \l MouseRegion \o \l FocusScope -\o \l KeyProxy \endlist \o diff --git a/examples/declarative/sql/README b/examples/declarative/sql/README new file mode 100644 index 0000000..a7baab2 --- /dev/null +++ b/examples/declarative/sql/README @@ -0,0 +1,7 @@ +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 new file mode 100644 index 0000000..e43d320 --- /dev/null +++ b/examples/declarative/sql/hello.qml @@ -0,0 +1,36 @@ +import Qt 4.6 + +Text { + Script { + function allGreetings() + { + var db = openDatabase("QmlExampleDB", "", "The Example QML SQL!", 1000000); + var r = "" + + db.transaction(function(tx) { + tx.executeSql('CREATE TABLE IF NOT EXISTS Greeting(salutation TEXT, salutee TEXT)', []); + tx.executeSql('INSERT INTO Greeting VALUES(?, ?)', [ 'hello', 'world' ]); + tx.executeSql('SELECT * FROM Greeting', [], + function(tx, rs) { + /* Inefficient HTML5-compatible way + for(var i = 0; i < rs.rows.length; i++) { + r += rs.rows[i][0] + ", " + rs.rows[i][1] + "\n" + } + */ + /* Efficient way: forward only, not "length" query */ + rs.rows.forwardOnly = true; + for(var i = 0; rs.rows[i]; i++) { + r += rs.rows[i][0] + ", " + rs.rows[i][1] + "\n" + } + }, + function(tx, error) { + print("ERROR:", error.message) + } + ); + }) + + return r + } + } + text: allGreetings() +} diff --git a/src/declarative/fx/qfxborderimage.cpp b/src/declarative/fx/qfxborderimage.cpp index d199d5d..ee505f2 100644 --- a/src/declarative/fx/qfxborderimage.cpp +++ b/src/declarative/fx/qfxborderimage.cpp @@ -386,11 +386,9 @@ void QFxBorderImage::paint(QPainter *p, const QStyleOptionGraphicsItem *, QWidge if (d->smooth) p->setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform, d->smooth); - QPixmap pix = d->pix; - QMargins margins(border()->top(), border()->left(), border()->bottom(), border()->right()); QTileRules rules((Qt::TileRule)d->horizontalTileMode, (Qt::TileRule)d->verticalTileMode); - qDrawBorderPixmap(p, QRect(0, 0, (int)d->width, (int)d->height), margins, pix, pix.rect(), margins, rules); + qDrawBorderPixmap(p, QRect(0, 0, (int)d->width, (int)d->height), margins, d->pix, d->pix.rect(), margins, rules); if (d->smooth) { p->setRenderHint(QPainter::Antialiasing, oldAA); p->setRenderHint(QPainter::SmoothPixmapTransform, oldSmooth); diff --git a/src/declarative/fx/qfxitem.cpp b/src/declarative/fx/qfxitem.cpp index 962fee2..dd51aa6 100644 --- a/src/declarative/fx/qfxitem.cpp +++ b/src/declarative/fx/qfxitem.cpp @@ -2688,9 +2688,23 @@ void QFxItem::setWidth(qreal w) QRectF(x(), y(), oldWidth, height())); } +void QFxItem::resetWidth() +{ + Q_D(QFxItem); + d->widthValid = false; + setImplicitWidth(implicitWidth()); +} + +qreal QFxItem::implicitWidth() const +{ + Q_D(const QFxItem); + return d->implicitWidth; +} + void QFxItem::setImplicitWidth(qreal w) { Q_D(QFxItem); + d->implicitWidth = w; if (d->width == w || widthValid()) return; @@ -2733,9 +2747,23 @@ void QFxItem::setHeight(qreal h) QRectF(x(), y(), width(), oldHeight)); } +void QFxItem::resetHeight() +{ + Q_D(QFxItem); + d->heightValid = false; + setImplicitHeight(implicitHeight()); +} + +qreal QFxItem::implicitHeight() const +{ + Q_D(const QFxItem); + return d->implicitHeight; +} + void QFxItem::setImplicitHeight(qreal h) { Q_D(QFxItem); + d->implicitHeight = h; if (d->height == h || heightValid()) return; diff --git a/src/declarative/fx/qfxitem.h b/src/declarative/fx/qfxitem.h index 7ec1ab2..b309cb3 100644 --- a/src/declarative/fx/qfxitem.h +++ b/src/declarative/fx/qfxitem.h @@ -75,8 +75,8 @@ class Q_DECLARATIVE_EXPORT QFxItem : public QGraphicsObject, public QmlParserSta Q_PROPERTY(QmlList<QmlState *>* states READ states DESIGNABLE false) Q_PROPERTY(QmlList<QmlTransition *>* transitions READ transitions DESIGNABLE false) Q_PROPERTY(QString state READ state WRITE setState NOTIFY stateChanged) - Q_PROPERTY(qreal width READ width WRITE setWidth NOTIFY widthChanged FINAL) - Q_PROPERTY(qreal height READ height WRITE setHeight NOTIFY heightChanged FINAL) + Q_PROPERTY(qreal width READ width WRITE setWidth NOTIFY widthChanged RESET resetWidth FINAL) + Q_PROPERTY(qreal height READ height WRITE setHeight NOTIFY heightChanged RESET resetHeight FINAL) Q_PROPERTY(QRectF childrenRect READ childrenRect NOTIFY childrenRectChanged DESIGNABLE false FINAL) Q_PROPERTY(QFxAnchors * anchors READ anchors DESIGNABLE false CONSTANT FINAL) Q_PROPERTY(QFxAnchorLine left READ left CONSTANT FINAL) @@ -134,9 +134,13 @@ public: qreal width() const; void setWidth(qreal); + void resetWidth(); + qreal implicitWidth() const; qreal height() const; void setHeight(qreal); + void resetHeight(); + qreal implicitHeight() const; TransformOrigin transformOrigin() const; void setTransformOrigin(TransformOrigin); diff --git a/src/declarative/fx/qfxitem_p.h b/src/declarative/fx/qfxitem_p.h index b2560ee..df75148 100644 --- a/src/declarative/fx/qfxitem_p.h +++ b/src/declarative/fx/qfxitem_p.h @@ -108,7 +108,7 @@ public: widthValid(false), heightValid(false), _componentComplete(true), _keepMouse(false), smooth(false), keyHandler(0), - width(0), height(0) + width(0), height(0), implicitWidth(0), implicitHeight(0) {} ~QFxItemPrivate() { delete _anchors; } @@ -213,6 +213,8 @@ public: qreal width; qreal height; + qreal implicitWidth; + qreal implicitHeight; QPointF computeTransformOrigin() const; diff --git a/src/declarative/fx/qfxlistview.cpp b/src/declarative/fx/qfxlistview.cpp index 015eacf..5de9bf3 100644 --- a/src/declarative/fx/qfxlistview.cpp +++ b/src/declarative/fx/qfxlistview.cpp @@ -831,8 +831,9 @@ void QFxListViewPrivate::fixupX() \inherits Flickable \brief The ListView item provides a list view of items provided by a model. - The model is typically provided by a QAbstractListModel "C++ model object", but can also be created directly in QML. - The items are laid out vertically or horizontally and may be flicked to scroll. + The model is typically provided by a QAbstractListModel "C++ model object", + but can also be created directly in QML. The items are laid out vertically + or horizontally and may be flicked to scroll. The below example creates a very simple vertical list, using a QML model. \image trivialListView.png @@ -871,9 +872,10 @@ QFxListView::~QFxListView() The model provides a set of data that is used to create the items for the view. For large or dynamic datasets the model is usually provided by a C++ model object. The C++ model object must be a \l - {QAbstractItemModel} subclass, a VisualModel, or a simple list. + {QAbstractItemModel} subclass or a simple list. - Models can also be created directly in QML, using a \l{ListModel} or \l{XmlListModel}. + Models can also be created directly in QML, using a \l{ListModel}, + \l{XmlListModel} or \l{VisualItemModel}. */ QVariant QFxListView::model() const { diff --git a/src/declarative/fx/qfxloader.cpp b/src/declarative/fx/qfxloader.cpp index 668faa4..d0c2690 100644 --- a/src/declarative/fx/qfxloader.cpp +++ b/src/declarative/fx/qfxloader.cpp @@ -361,10 +361,8 @@ void QFxLoaderPrivate::_q_updateSize() return; switch (resizeMode) { case QFxLoader::SizeLoaderToItem: - if (!q->widthValid()) - q->setImplicitWidth(item->width()); - if (!q->heightValid()) - q->setImplicitHeight(item->height()); + q->setImplicitWidth(item->width()); + q->setImplicitHeight(item->height()); break; case QFxLoader::SizeItemToLoader: item->setWidth(q->width()); diff --git a/src/declarative/fx/qfxrect.cpp b/src/declarative/fx/qfxrect.cpp index fbd7ee8..7d6340f 100644 --- a/src/declarative/fx/qfxrect.cpp +++ b/src/declarative/fx/qfxrect.cpp @@ -69,14 +69,17 @@ void QFxPen::setColor(const QColor &c) { _color = c; _valid = _color.alpha() ? true : false; - emit updated(); + emit penChanged(); } void QFxPen::setWidth(int w) { + if (_width == w) + return; + _width = w; _valid = (_width < 1) ? false : true; - emit updated(); + emit penChanged(); } @@ -293,6 +296,7 @@ void QFxRect::setRadius(qreal radius) d->radius = radius; d->rectImage = QPixmap(); update(); + emit radiusChanged(); } /*! @@ -326,6 +330,7 @@ void QFxRect::setColor(const QColor &c) d->color = c; d->rectImage = QPixmap(); update(); + emit colorChanged(); } void QFxRect::generateRoundedRect() @@ -395,7 +400,7 @@ void QFxRect::paint(QPainter *p, const QStyleOptionGraphicsItem *, QWidget *) void QFxRect::drawRect(QPainter &p) { Q_D(QFxRect); - if (d->gradient && d->gradient->gradient() /*|| p.usingQt() */) { + if (d->gradient && d->gradient->gradient()) { // XXX This path is still slower than the image path // Image path won't work for gradients though bool oldAA = p.testRenderHint(QPainter::Antialiasing); diff --git a/src/declarative/fx/qfxrect.h b/src/declarative/fx/qfxrect.h index 439cc65..e5bb8d3 100644 --- a/src/declarative/fx/qfxrect.h +++ b/src/declarative/fx/qfxrect.h @@ -55,8 +55,8 @@ class Q_DECLARATIVE_EXPORT QFxPen : public QObject { Q_OBJECT - Q_PROPERTY(int width READ width WRITE setWidth) - Q_PROPERTY(QColor color READ color WRITE setColor) + Q_PROPERTY(int width READ width WRITE setWidth NOTIFY penChanged) + Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY penChanged) public: QFxPen(QObject *parent=0) : QObject(parent), _width(1), _color("#000000"), _valid(false) @@ -71,7 +71,7 @@ public: bool isValid() { return _valid; }; Q_SIGNALS: - void updated(); + void penChanged(); private: int _width; @@ -135,10 +135,10 @@ class Q_DECLARATIVE_EXPORT QFxRect : public QFxItem { Q_OBJECT - Q_PROPERTY(QColor color READ color WRITE setColor) + Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged) Q_PROPERTY(QFxGradient *gradient READ gradient WRITE setGradient) - Q_PROPERTY(QFxPen * border READ border) - Q_PROPERTY(qreal radius READ radius WRITE setRadius) + Q_PROPERTY(QFxPen * border READ border CONSTANT) + Q_PROPERTY(qreal radius READ radius WRITE setRadius NOTIFY radiusChanged) public: QFxRect(QFxItem *parent=0); @@ -157,6 +157,10 @@ public: void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *); +Q_SIGNALS: + void colorChanged(); + void radiusChanged(); + private Q_SLOTS: void doUpdate(); diff --git a/src/declarative/fx/qfxrect_p.h b/src/declarative/fx/qfxrect_p.h index 8eb074a..c055b76 100644 --- a/src/declarative/fx/qfxrect_p.h +++ b/src/declarative/fx/qfxrect_p.h @@ -85,7 +85,7 @@ public: if (!pen) { Q_Q(QFxRect); pen = new QFxPen; - QObject::connect(pen, SIGNAL(updated()), q, SLOT(doUpdate())); + QObject::connect(pen, SIGNAL(penChanged()), q, SLOT(doUpdate())); } return pen; } diff --git a/src/declarative/fx/qfxtext.cpp b/src/declarative/fx/qfxtext.cpp index 5b10289..c4e534e 100644 --- a/src/declarative/fx/qfxtext.cpp +++ b/src/declarative/fx/qfxtext.cpp @@ -513,17 +513,9 @@ void QFxTextPrivate::updateSize() } q->setBaselineOffset(fm.ascent() + yoff); - if (!q->widthValid()) { - int newWidth = (richText ? (int)doc->idealWidth() : size.width()); - q->setImplicitWidth(newWidth); - } - if (!q->heightValid()) { - if (richText) { - q->setImplicitHeight((int)doc->size().height()); - } else { - q->setImplicitHeight(size.height()); - } - } + //### need to comfirm cost of always setting these for richText + q->setImplicitWidth(richText ? (int)doc->idealWidth() : size.width()); + q->setImplicitHeight(richText ? (int)doc->size().height() : size.height()); } else { dirty = true; } diff --git a/src/declarative/fx/qfxtextedit.cpp b/src/declarative/fx/qfxtextedit.cpp index c106ee0..d1bafd6 100644 --- a/src/declarative/fx/qfxtextedit.cpp +++ b/src/declarative/fx/qfxtextedit.cpp @@ -1043,18 +1043,13 @@ void QFxTextEdit::updateSize() yoff = dy/2; } setBaselineOffset(fm.ascent() + yoff + d->textMargin); - if (!widthValid()) { - int newWidth = (int)d->document->idealWidth(); - d->document->setTextWidth(newWidth); // ### QTextDoc> Alignment will not work unless textWidth is set - setImplicitWidth(newWidth); - } - if (!heightValid()) { - if (d->text.isEmpty()) { - setImplicitHeight(fm.height()); - } else { - setImplicitHeight((int)d->document->size().height()); - } - } + + //### need to comfirm cost of always setting these + int newWidth = (int)d->document->idealWidth(); + d->document->setTextWidth(newWidth); // ### QTextDoc> Alignment will not work unless textWidth is set. Does Text need this line as well? + setImplicitWidth(newWidth); + setImplicitHeight(d->text.isEmpty() ? fm.height() : (int)d->document->size().height()); + setContentsSize(QSize(width(), height())); } else { d->dirty = true; diff --git a/src/declarative/qml/qml.pri b/src/declarative/qml/qml.pri index 29d97ba..9ca69df 100644 --- a/src/declarative/qml/qml.pri +++ b/src/declarative/qml/qml.pri @@ -32,6 +32,7 @@ SOURCES += qml/qmlparser.cpp \ qml/qmlvaluetype.cpp \ qml/qmlbindingoptimizations.cpp \ qml/qmlxmlhttprequest.cpp \ + qml/qmlsqldatabase.cpp \ qml/qmetaobjectbuilder.cpp HEADERS += qml/qmlparser_p.h \ @@ -81,6 +82,7 @@ HEADERS += qml/qmlparser_p.h \ qml/qmlvaluetype_p.h \ qml/qmlbindingoptimizations_p.h \ qml/qmlxmlhttprequest_p.h \ + qml/qmlsqldatabase_p.h \ qml/qmetaobjectbuilder_p.h # for qtscript debugger diff --git a/src/declarative/qml/qmlengine.cpp b/src/declarative/qml/qmlengine.cpp index 3cf7e69..1aa2cb9 100644 --- a/src/declarative/qml/qmlengine.cpp +++ b/src/declarative/qml/qmlengine.cpp @@ -82,6 +82,7 @@ #include <private/qmlenginedebug_p.h> #include <private/qmlstringconverters_p.h> #include <private/qmlxmlhttprequest_p.h> +#include <private/qmlsqldatabase_p.h> Q_DECLARE_METATYPE(QmlMetaProperty) Q_DECLARE_METATYPE(QList<QObject *>); @@ -110,7 +111,7 @@ QScriptValue desktopOpenUrl(QScriptContext *ctxt, QScriptEngine *e) QmlEnginePrivate::QmlEnginePrivate(QmlEngine *e) : rootContext(0), currentExpression(0), isDebugging(false), contextClass(0), objectClass(0), valueTypeClass(0), - nodeListClass(0), namedNodeMapClass(0), scriptEngine(this), rootComponent(0), + nodeListClass(0), namedNodeMapClass(0), sqlQueryClass(0), scriptEngine(this), rootComponent(0), networkAccessManager(0), typeManager(e), uniqueId(1) { QScriptValue qtObject = @@ -121,6 +122,7 @@ QmlEnginePrivate::QmlEnginePrivate(QmlEngine *e) scriptEngine.globalObject().setProperty(QLatin1String("Qt"), qtObject); qt_add_qmlxmlhttprequest(&scriptEngine); + qt_add_qmlsqldatabase(&scriptEngine); //types qtObject.setProperty(QLatin1String("rgba"), scriptEngine.newFunction(QmlEnginePrivate::rgba, 4)); @@ -154,6 +156,8 @@ QmlEnginePrivate::~QmlEnginePrivate() nodeListClass = 0; delete namedNodeMapClass; namedNodeMapClass = 0; + delete sqlQueryClass; + sqlQueryClass = 0; for(int ii = 0; ii < bindValues.count(); ++ii) clear(bindValues[ii]); diff --git a/src/declarative/qml/qmlengine_p.h b/src/declarative/qml/qmlengine_p.h index 15ab40d..0eeae0c 100644 --- a/src/declarative/qml/qmlengine_p.h +++ b/src/declarative/qml/qmlengine_p.h @@ -154,6 +154,8 @@ public: // Used by DOM Core 3 API QScriptClass *nodeListClass; QScriptClass *namedNodeMapClass; + // Used by SQL database API + QScriptClass *sqlQueryClass; struct QmlScriptEngine : public QScriptEngine { diff --git a/src/declarative/qml/qmlpropertyvaluesource.cpp b/src/declarative/qml/qmlpropertyvaluesource.cpp index 429080b..529ce37 100644 --- a/src/declarative/qml/qmlpropertyvaluesource.cpp +++ b/src/declarative/qml/qmlpropertyvaluesource.cpp @@ -56,6 +56,10 @@ QmlPropertyValueSource::QmlPropertyValueSource() { } +QmlPropertyValueSource::~QmlPropertyValueSource() +{ +} + /*! \fn void QmlPropertyValueSource::setTarget(const QmlMetaProperty &property) Set the target \a property for the value source. This method will diff --git a/src/declarative/qml/qmlpropertyvaluesource.h b/src/declarative/qml/qmlpropertyvaluesource.h index ee4ea2c..384d2f9 100644 --- a/src/declarative/qml/qmlpropertyvaluesource.h +++ b/src/declarative/qml/qmlpropertyvaluesource.h @@ -55,6 +55,7 @@ class Q_DECLARATIVE_EXPORT QmlPropertyValueSource { public: QmlPropertyValueSource(); + virtual ~QmlPropertyValueSource(); virtual void setTarget(const QmlMetaProperty &) = 0; }; Q_DECLARE_INTERFACE(QmlPropertyValueSource, "com.trolltech.qml.QmlPropertyValueSource") diff --git a/src/declarative/qml/qmlsqldatabase.cpp b/src/declarative/qml/qmlsqldatabase.cpp new file mode 100644 index 0000000..144a170 --- /dev/null +++ b/src/declarative/qml/qmlsqldatabase.cpp @@ -0,0 +1,304 @@ +/**************************************************************************** +** +** 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 <QtCore/qobject.h> +#include <QtDeclarative/qmlengine.h> +#include <private/qmlengine_p.h> +#include <QtScript/qscriptvalue.h> +#include <QtScript/qscriptvalueiterator.h> +#include <QtScript/qscriptcontext.h> +#include <QtScript/qscriptengine.h> +#include <QtSql/qsqldatabase.h> +#include <QtSql/qsqlquery.h> +#include <QtSql/qsqlerror.h> +#include <QtSql/qsqlrecord.h> +#include <private/qmlrefcount_p.h> +#include <private/qmlengine_p.h> +#include <QtCore/qstack.h> +#include <QtCore/qcryptographichash.h> +#include "qmlsqldatabase_p.h" +#include <QtCore/qsettings.h> +#include <QtCore/qdir.h> +#include <QtCore/qdebug.h> + +#ifdef Q_OS_WIN // for %APPDATA% +#include "qt_windows.h" +#include "qlibrary.h" +#define CSIDL_APPDATA 0x001a // <username>\Application Data +#endif + +Q_DECLARE_METATYPE(QSqlDatabase) +Q_DECLARE_METATYPE(QSqlQuery) + +class QmlSqlQueryScriptClass: public QScriptClass { +public: + QmlSqlQueryScriptClass(QScriptEngine *engine) : QScriptClass(engine) + { + str_length = engine->toStringHandle(QLatin1String("length")); + str_forwardOnly = engine->toStringHandle(QLatin1String("forwardOnly")); // not in HTML5 (optimization) + } + + QueryFlags queryProperty(const QScriptValue &object, + const QScriptString &name, + QueryFlags flags, uint *id) + { + if (flags & HandlesReadAccess) { + if (name == str_length) { + return HandlesReadAccess; + } else if (name == str_forwardOnly) { + return flags; + } else { + bool ok; + qint32 pos = name.toString().toInt(&ok); + if (pos < 0 || !ok) + return 0; + QSqlQuery query = qscriptvalue_cast<QSqlQuery>(object.data()); + *id = pos; + if (*id < (uint)query.size()) + return HandlesReadAccess; + } + } + if (flags & HandlesWriteAccess) + if (name == str_forwardOnly) + return flags; + return 0; + } + + QScriptValue property(const QScriptValue &object, + const QScriptString &name, uint id) + { + QSqlQuery query = qscriptvalue_cast<QSqlQuery>(object.data()); + if (name == str_length) { + int s = query.size(); + if (s<0) { + // Inefficient. + query.last(); + return query.at()+1; + } else { + return s; + } + } else if (name == str_forwardOnly) { + return query.isForwardOnly(); + } else { + if (query.at() == id || query.seek(id)) { // Qt 4.6 doesn't optimize at()==id + QSqlRecord r = query.record(); + QScriptValue row = engine()->newArray(r.count()); + for (int j=0; j<r.count(); ++j) { + // XXX only strings + row.setProperty(j, QScriptValue(engine(),r.value(j).toString())); + } + return row; + } + } + return engine()->undefinedValue(); + } + + void setProperty(QScriptValue &object, + const QScriptString &name, uint, const QScriptValue & value) + { + if (name == str_forwardOnly) { + QSqlQuery query = qscriptvalue_cast<QSqlQuery>(object.data()); + query.setForwardOnly(value.toBool()); + } + } + +private: + QScriptString str_length; + QScriptString str_forwardOnly; +}; + +static QScriptValue qmlsqldatabase_executeSql(QScriptContext *context, QScriptEngine *engine) +{ + QSqlDatabase db = qscriptvalue_cast<QSqlDatabase>(context->thisObject()); + QString sql = context->argument(0).toString(); + QScriptValue values = context->argument(1); + QScriptValue cb = context->argument(2); + QScriptValue cberr = context->argument(3); + QSqlQuery query(db); + bool err = false; + if (query.prepare(sql)) { + if (values.isArray()) { + for (QScriptValueIterator it(values); it.hasNext();) { + it.next(); + query.addBindValue(it.value().toVariant()); + } + } else { + query.bindValue(0,values.toVariant()); + } + if (query.exec()) { + QScriptValue rs = engine->newObject(); + if (!QmlEnginePrivate::get(engine)->sqlQueryClass) + QmlEnginePrivate::get(engine)->sqlQueryClass= new QmlSqlQueryScriptClass(engine); + QScriptValue rows = engine->newObject(QmlEnginePrivate::get(engine)->sqlQueryClass); + rows.setData(engine->newVariant(qVariantFromValue(query))); + rs.setProperty(QLatin1String("rows"),rows); + rs.setProperty(QLatin1String("rowsAffected"),query.numRowsAffected()); + rs.setProperty(QLatin1String("insertId"),query.lastInsertId().toString()); // XXX only string + cb.call(QScriptValue(), QScriptValueList() << context->thisObject() << rs); + } else { + err = true; + } + } else { + err = true; + } + if (err) { + QScriptValue error = engine->newObject(); + error.setProperty(QLatin1String("message"), query.lastError().text()); + cberr.call(QScriptValue(), QScriptValueList() << context->thisObject() << error); + } + return engine->undefinedValue(); +} + +static QScriptValue qmlsqldatabase_transaction(QScriptContext *context, QScriptEngine *engine) +{ + QSqlDatabase db = qscriptvalue_cast<QSqlDatabase>(context->thisObject()); + if (context->argumentCount() < 1) + return engine->undefinedValue(); + QScriptValue cb = context->argument(0); + if (!cb.isFunction()) + return engine->undefinedValue(); + + // Call synchronously... - XXX could do asynch with threads + QScriptValue instance = engine->newObject(); + instance.setProperty(QLatin1String("executeSql"), engine->newFunction(qmlsqldatabase_executeSql,4)); + QScriptValue tx = engine->newVariant(instance,qVariantFromValue(db)); + + db.transaction(); + cb.call(QScriptValue(), QScriptValueList() << tx); + if (engine->hasUncaughtException()) { + db.rollback(); + QScriptValue cb = context->argument(1); + if (cb.isFunction()) + cb.call(); + } else { + db.commit(); + QScriptValue cb = context->argument(2); + if (cb.isFunction()) + cb.call(); + } + return engine->undefinedValue(); +} + +// XXX Something like this should be exported by Qt. +static QString userLocalDataPath(const QString& app) +{ + QString result; + +#ifdef Q_OS_WIN +#ifndef Q_OS_WINCE + QLibrary library(QLatin1String("shell32")); +#else + QLibrary library(QLatin1String("coredll")); +#endif // Q_OS_WINCE + typedef BOOL (WINAPI*GetSpecialFolderPath)(HWND, LPWSTR, int, BOOL); + GetSpecialFolderPath SHGetSpecialFolderPath = (GetSpecialFolderPath)library.resolve("SHGetSpecialFolderPathW"); + if (SHGetSpecialFolderPath) { + wchar_t path[MAX_PATH]; + SHGetSpecialFolderPath(0, path, CSIDL_APPDATA, FALSE); + result = QString::fromWCharArray(path); + } +#endif // Q_OS_WIN + +#ifdef Q_OS_MAC + result = QLatin1String(qgetenv("HOME")); + result += "/Library/Application Support"; +#else + if (result.isEmpty()) { + // Fallback: UNIX style + result = QLatin1String(qgetenv("XDG_DATA_HOME")); + if (result.isEmpty()) { + result = QLatin1String(qgetenv("HOME")); + result += QLatin1String("/.local/share"); + } + } +#endif + + result += QLatin1Char('/'); + result += app; + return result; +} + + +static QScriptValue qmlsqldatabase_open(QScriptContext *context, QScriptEngine *engine) +{ + QSqlDatabase database; + + QString dbname = context->argument(0).toString(); + QString dbversion = context->argument(1).toString(); + QString dbdescription = context->argument(2).toString(); + int dbestimatedsize = context->argument(3).toNumber(); + + QCryptographicHash md5(QCryptographicHash::Md5); + md5.addData(dbname.toUtf8()); + md5.addData(dbversion.toUtf8()); + QString dbid(QLatin1String(md5.result().toHex())); + + // Uses SQLLITE (like HTML5), but any could be used. + + if (QSqlDatabase::connectionNames().contains(dbid)) { + database = QSqlDatabase::database(dbid); + } else { + database = QSqlDatabase::addDatabase(QLatin1String("QSQLITE"), dbid); + } + if (!database.isOpen()) { + QString basename = userLocalDataPath(QLatin1String("Nokia/Qt/QML/Databases/")); + QDir().mkpath(basename); + basename += dbid; + database.setDatabaseName(basename+QLatin1String(".sqllite")); + QSettings ini(basename+QLatin1String(".ini"),QSettings::IniFormat); + ini.setValue(QLatin1String("Name"), dbname); + ini.setValue(QLatin1String("Version"), dbversion); + ini.setValue(QLatin1String("Description"), dbdescription); + ini.setValue(QLatin1String("EstimatedSize"), dbestimatedsize); + database.open(); + } + + QScriptValue instance = engine->newObject(); + instance.setProperty(QLatin1String("transaction"), engine->newFunction(qmlsqldatabase_transaction,3)); + return engine->newVariant(instance,qVariantFromValue(database)); +} + +void qt_add_qmlsqldatabase(QScriptEngine *engine) +{ + QScriptValue openDatabase = engine->newFunction(qmlsqldatabase_open, 4); + engine->globalObject().setProperty(QLatin1String("openDatabase"), openDatabase); +} + diff --git a/src/declarative/qml/qmlsqldatabase_p.h b/src/declarative/qml/qmlsqldatabase_p.h new file mode 100644 index 0000000..f76a2fd --- /dev/null +++ b/src/declarative/qml/qmlsqldatabase_p.h @@ -0,0 +1,60 @@ +/**************************************************************************** +** +** 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 QMLSQLDATABASE_P_H +#define QMLSQLDATABASE_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +class QScriptEngine; +void qt_add_qmlsqldatabase(QScriptEngine *engine); + +#endif // QMLSQLDATABASE_P_H + diff --git a/src/declarative/util/qmleasefollow.cpp b/src/declarative/util/qmleasefollow.cpp index b58ad14..860c63a 100644 --- a/src/declarative/util/qmleasefollow.cpp +++ b/src/declarative/util/qmleasefollow.cpp @@ -242,6 +242,8 @@ Rectangle { Keys.onDownPressed: Rect1.y = Rect1.y + 100 } \endcode + + \sa SpringFollow */ QmlEaseFollow::QmlEaseFollow(QObject *parent) diff --git a/src/declarative/util/qmlspringfollow.cpp b/src/declarative/util/qmlspringfollow.cpp index 8c902aa..2dae448 100644 --- a/src/declarative/util/qmlspringfollow.cpp +++ b/src/declarative/util/qmlspringfollow.cpp @@ -236,6 +236,8 @@ void QmlSpringFollowPrivate::stop() y: SpringFollow { source: Rect1.y; velocity: 200 } } \endcode + + \sa EaseFollow */ QmlSpringFollow::QmlSpringFollow(QObject *parent) |