From 13ad623fdff541d028a74705ddf0a94f47092a56 Mon Sep 17 00:00:00 2001 From: "Jesper K. Pedersen" Date: Thu, 16 May 2013 19:26:02 +0200 Subject: implement a QFileInfo prototype so it can be used from scripts Change-Id: I84755a64207d71451768981b725c1ce3bdeb0907 Reviewed-by: Nicolas Arnaud-Cormos --- scripting.pro | 8 +- scriptrunner.cpp | 7 ++ scriptrunner.h | 1 + tests/qfileinfo/qfileinfo.qs | 36 ++++++ tests/qfileinfo/test.cpp | 5 + tests/test.js | 14 +++ utils/utils.cpp | 5 + utils/utils.h | 4 + wrappers/qfileinfoprototype.cpp | 235 ++++++++++++++++++++++++++++++++++++++++ wrappers/qfileinfoprototype.h | 158 +++++++++++++++++++++++++++ wrappers/scriptwrappers.cpp | 19 ++++ 11 files changed, 490 insertions(+), 2 deletions(-) create mode 100644 tests/qfileinfo/qfileinfo.qs create mode 100644 tests/qfileinfo/test.cpp create mode 100644 wrappers/qfileinfoprototype.cpp create mode 100644 wrappers/qfileinfoprototype.h diff --git a/scripting.pro b/scripting.pro index 9af8614..ac779b4 100644 --- a/scripting.pro +++ b/scripting.pro @@ -24,7 +24,8 @@ SOURCES += scriptingplugin.cpp \ objects/mark.cpp \ utils/position.cpp \ utils/utils.cpp \ - objects/cppclass.cpp + objects/cppclass.cpp \ + wrappers/qfileinfoprototype.cpp HEADERS += scriptingplugin.h \ scripting_global.h \ @@ -48,7 +49,8 @@ HEADERS += scriptingplugin.h \ objects/mark.h \ utils/position.h \ utils/utils.h \ - objects/cppclass.h + objects/cppclass.h \ + wrappers/qfileinfoprototype.h # Qt Creator linking @@ -82,6 +84,8 @@ OTHER_FILES += \ tests/test.js \ tests/class/class.qs \ tests/class/test.h \ + tests/qfileinfo/qfileinfo.qs \ + tests/qfileinfo/test.cpp diff --git a/scriptrunner.cpp b/scriptrunner.cpp index a047928..a2e7e30 100644 --- a/scriptrunner.cpp +++ b/scriptrunner.cpp @@ -166,8 +166,15 @@ QString ScriptRunner::absolutePath(const QString &path) return path; } +QString ScriptRunner::currentScriptRoot() +{ + return rootDir; +} + Q_DECLARE_METATYPE(QList) + + ScriptRunner::QScriptEnginePtr ScriptRunner::ensureEngineInitialized() { if (!m_engine.isNull()) diff --git a/scriptrunner.h b/scriptrunner.h index e88ccc0..1bd4ede 100644 --- a/scriptrunner.h +++ b/scriptrunner.h @@ -69,6 +69,7 @@ public: QScriptEnginePtr scriptEngine() { return ensureEngineInitialized(); } static QString absolutePath(const QString& path); + static QString currentScriptRoot(); private: QScriptEnginePtr ensureEngineInitialized(); diff --git a/tests/qfileinfo/qfileinfo.qs b/tests/qfileinfo/qfileinfo.qs new file mode 100644 index 0000000..e061d2c --- /dev/null +++ b/tests/qfileinfo/qfileinfo.qs @@ -0,0 +1,36 @@ +include("../test.js") + +var absolute = new QFileInfo(utils.currentScripRoot + "/test.cpp") +var relative = new QFileInfo("relative") + +compare(absolute.exists, true) +compare(relative.exists, false) + +compare(relative.filePath, "relative") +assert(endsWith(absolute.filePath, "test.cpp"), "filePath for absolute files") + +assert(startsWith(relative.absoluteFilePath,"/")) +compare(absolute.fileName, "test.cpp") + +compare(absolute.isRelative, false) +compare(relative.isRelative, true) +compare(absolute.size, 61) + +assert(absolute.created.getFullYear() > 2012) + +var gotIt = false +try { + new QFileInfo() +} +catch(message) { + gotIt = true +} +assert(gotIt, "We should throw an error when constructing a QFileInfo without a file") + +function endsWith(str,pattern) { + return str.substr(str.length-pattern.length,pattern.length) == pattern +} + +function startsWith(str,pattern) { + return str.substr(0,pattern.length) == pattern +} diff --git a/tests/qfileinfo/test.cpp b/tests/qfileinfo/test.cpp new file mode 100644 index 0000000..4304ec5 --- /dev/null +++ b/tests/qfileinfo/test.cpp @@ -0,0 +1,5 @@ +class Foo { + void bar() { + qDebug("yay"); + } +}; diff --git a/tests/test.js b/tests/test.js index 4bb7f60..9269328 100644 --- a/tests/test.js +++ b/tests/test.js @@ -72,4 +72,18 @@ if (TEST_JS_LOADED == undefined) { compare(editor.currentColumn(), column, message) } + function assert(cond, message) { + if ( verbose ) { + if ( message != undefined ) + console.log("assert(" + message + "): " + cond) + else + console.log("assert: " + cond) + } + if ( !cond ) { + if ( message != undefined ) + error("Assertion failed: " + message) + else + error("Assertion failed") + } + } } diff --git a/utils/utils.cpp b/utils/utils.cpp index 30e8c6c..26ea3b5 100644 --- a/utils/utils.cpp +++ b/utils/utils.cpp @@ -56,6 +56,11 @@ QStringList Utils::backtrace() const return result; } +QString Utils::currentScripRoot() const +{ + return ScriptRunner::currentScriptRoot(); +} + } // namespace Internal } // namespace Scripting diff --git a/utils/utils.h b/utils/utils.h index 252cb3b..2c25d2a 100644 --- a/utils/utils.h +++ b/utils/utils.h @@ -39,12 +39,16 @@ namespace Internal { class Utils : public QObject { Q_OBJECT + Q_PROPERTY(QString currentScripRoot READ currentScripRoot); public: explicit Utils(QObject *parent = 0); public slots: QStringList subDirectories(const QString& directory) const; QStringList backtrace() const; + +public: + QString currentScripRoot() const; }; } // namespace Internal diff --git a/wrappers/qfileinfoprototype.cpp b/wrappers/qfileinfoprototype.cpp new file mode 100644 index 0000000..ef1e54f --- /dev/null +++ b/wrappers/qfileinfoprototype.cpp @@ -0,0 +1,235 @@ +/************************************************************************** +** +** Copyright (C) 2013 Kläralvdalens Datakonsult AB, a KDAB Group company. +** Contact: Kläralvdalens Datakonsult AB (info@kdab.com) +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** 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, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "qfileinfoprototype.h" +#include +#include +#include "scriptrunner.h" + +namespace Scripting { +namespace Internal { + +QScriptValue QFileInfoPrototype::construct(QScriptContext *context, QScriptEngine *engine) +{ + if ( context->isCalledAsConstructor() ) { + if ( context->argumentCount() != 1 ) { + context->throwError(tr("QFileInfo object must be constructed with a filename as parameter")); + return engine->undefinedValue(); + } + return engine->toScriptValue( QFileInfo(context->argument(0).toString())); + } + else { + return engine->undefinedValue(); + } +} + +#define FILE qscriptvalue_cast(thisObject()) + +bool QFileInfoPrototype::exists() const +{ + return FILE.exists(); +} + +QString QFileInfoPrototype::filePath() const +{ + return FILE.filePath(); +} + +QString QFileInfoPrototype::absoluteFilePath() const +{ + return FILE.absoluteFilePath(); +} + +QString QFileInfoPrototype::canonicalFilePath() const +{ + return FILE.canonicalFilePath(); +} + +QString QFileInfoPrototype::fileName() const +{ + return FILE.fileName(); +} + +QString QFileInfoPrototype::baseName() const +{ + return FILE.baseName(); +} + +QString QFileInfoPrototype::completeBaseName() const +{ + return FILE.completeBaseName(); +} + +QString QFileInfoPrototype::suffix() const +{ + return FILE.suffix(); +} + +QString QFileInfoPrototype::bundleName() const +{ + return FILE.bundleName(); +} + +QString QFileInfoPrototype::completeSuffix() const +{ + return FILE.completeSuffix(); +} + +QString QFileInfoPrototype::path() const +{ + return FILE.path(); +} + +QString QFileInfoPrototype::absolutePath() const +{ + return FILE.absolutePath(); +} + +QString QFileInfoPrototype::canonicalPath() const +{ + return FILE.canonicalPath(); +} + +QDir QFileInfoPrototype::dir() const +{ + return FILE.dir(); +} + +QDir QFileInfoPrototype::absoluteDir() const +{ + return FILE.absoluteDir(); +} + +bool QFileInfoPrototype::isReadable() const +{ + return FILE.isReadable(); +} + +bool QFileInfoPrototype::isWritable() const +{ + return FILE.isWritable(); +} + +bool QFileInfoPrototype::isExecutable() const +{ + return FILE.isExecutable(); +} + +bool QFileInfoPrototype::isHidden() const +{ + return FILE.isHidden(); +} + +bool QFileInfoPrototype::isRelative() const +{ + return FILE.isRelative(); +} + +bool QFileInfoPrototype::isAbsolute() const +{ + return FILE.isAbsolute(); +} + +bool QFileInfoPrototype::isFile() const +{ + return FILE.isFile(); +} + +bool QFileInfoPrototype::isDir() const +{ + return FILE.isDir(); +} + +bool QFileInfoPrototype::isSymLink() const +{ + return FILE.isSymLink(); +} + +bool QFileInfoPrototype::isRoot() const +{ + return FILE.isRoot(); +} + +bool QFileInfoPrototype::isBundle() const +{ + return FILE.isBundle(); +} + +QString QFileInfoPrototype::readLink() const +{ + return FILE.readLink(); +} + +QString QFileInfoPrototype::symLinkTarget() const +{ + return FILE.symLinkTarget(); +} + +QString QFileInfoPrototype::owner() const +{ + return FILE.owner(); +} + +uint QFileInfoPrototype::ownerId() const +{ + return FILE.ownerId(); +} + +QString QFileInfoPrototype::group() const +{ + return FILE.group(); +} + +uint QFileInfoPrototype::groupId() const +{ + return FILE.groupId(); +} + +qint64 QFileInfoPrototype::size() const +{ + return FILE.size(); +} + +QDateTime QFileInfoPrototype::created() const +{ + return FILE.created(); +} + +QDateTime QFileInfoPrototype::lastModified() const +{ + return FILE.lastModified(); +} + +QDateTime QFileInfoPrototype::lastRead() const +{ + return FILE.lastRead(); +} + +} // namespace Internal +} // namespace Scripting diff --git a/wrappers/qfileinfoprototype.h b/wrappers/qfileinfoprototype.h new file mode 100644 index 0000000..661d618 --- /dev/null +++ b/wrappers/qfileinfoprototype.h @@ -0,0 +1,158 @@ +/************************************************************************** +** +** Copyright (C) 2013 Kläralvdalens Datakonsult AB, a KDAB Group company. +** Contact: Kläralvdalens Datakonsult AB (info@kdab.com) +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** 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, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef SCRIPTING_INTERNAL_QFILEINFOPROTOTYPE_H +#define SCRIPTING_INTERNAL_QFILEINFOPROTOTYPE_H + +#include +#include +#include +#include +#include +#include + +namespace Scripting { +namespace Internal { + +/** + * @brief Wrapper for QFileInfo, which makes it available in scripts + */ +class QFileInfoPrototype : public QObject, public QScriptable +{ + // Methods comments out using //XXX are methods from QFileInfo, which are not wrapped + // The reason is that they make no sense, as this wrapper wraps a QFileInfo, not a QFileInfo*, + // so the QFileInfo is copied, and therefore read only. + Q_OBJECT + + Q_PROPERTY( bool exists READ exists) + Q_PROPERTY( QString filePath READ filePath) + Q_PROPERTY( QString absoluteFilePath READ absoluteFilePath) + Q_PROPERTY( QString canonicalFilePath READ canonicalFilePath) + Q_PROPERTY( QString fileName READ fileName) + Q_PROPERTY( QString baseName READ baseName) + Q_PROPERTY( QString completeBaseName READ completeBaseName) + Q_PROPERTY( QString suffix READ suffix) + Q_PROPERTY( QString bundleName READ bundleName) + Q_PROPERTY( QString completeSuffix READ completeSuffix) + Q_PROPERTY( QString path READ path) + Q_PROPERTY( QString absolutePath READ absolutePath) + Q_PROPERTY( QString canonicalPath READ canonicalPath) + Q_PROPERTY( QDir dir READ dir) + Q_PROPERTY( QDir absoluteDir READ absoluteDir) + Q_PROPERTY( bool isReadable READ isReadable) + Q_PROPERTY( bool isWritable READ isWritable) + Q_PROPERTY( bool isExecutable READ isExecutable) + Q_PROPERTY( bool isHidden READ isHidden) + Q_PROPERTY( bool isRelative READ isRelative) + Q_PROPERTY( bool isAbsolute READ isAbsolute) + Q_PROPERTY( bool isFile READ isFile) + Q_PROPERTY( bool isDir READ isDir) + Q_PROPERTY( bool isSymLink READ isSymLink) + Q_PROPERTY( bool isRoot READ isRoot) + Q_PROPERTY( bool isBundle READ isBundle) + Q_PROPERTY( QString readLink READ readLink) + Q_PROPERTY( QString symLinkTarget READ symLinkTarget) + Q_PROPERTY( QString owner READ owner) + Q_PROPERTY( uint ownerId READ ownerId) + Q_PROPERTY( QString group READ group) + Q_PROPERTY( uint groupId READ groupId) + Q_PROPERTY( qint64 size READ size) + Q_PROPERTY( QDateTime created READ created) + Q_PROPERTY( QDateTime lastModified READ lastModified) + Q_PROPERTY( QDateTime lastRead READ lastRead) + +public: + static QScriptValue construct(QScriptContext* context, QScriptEngine* engine); + + //XXX void setFile(const QString &file); + //XXX void setFile(const QFile &file); + //XXX void setFile(const QDir &dir, const QString &file); + bool exists() const; + //XXX void refresh(); + + QString filePath() const; + QString absoluteFilePath() const; + QString canonicalFilePath() const; + QString fileName() const; + QString baseName() const; + QString completeBaseName() const; + QString suffix() const; + QString bundleName() const; + QString completeSuffix() const; + + QString path() const; + QString absolutePath() const; + QString canonicalPath() const; + QDir dir() const; + QDir absoluteDir() const; + + bool isReadable() const; + bool isWritable() const; + bool isExecutable() const; + bool isHidden() const; + + bool isRelative() const; + bool isAbsolute() const; + // bool makeAbsolute(); + + bool isFile() const; + bool isDir() const; + bool isSymLink() const; + bool isRoot() const; + bool isBundle() const; + + QString readLink() const; + QString symLinkTarget() const; + + QString owner() const; + uint ownerId() const; + QString group() const; + uint groupId() const; + + // Not yet implemented, but could be. + // bool permission(QFile::Permissions permissions) const; + // QFile::Permissions permissions() const; + + qint64 size() const; + + QDateTime created() const; + QDateTime lastModified() const; + QDateTime lastRead() const; + + //XXX void detach(); + //XXX bool caching() const; + //XXX void setCaching(bool on); +}; + +} // namespace Internal +} // namespace Scripting + +Q_DECLARE_METATYPE(QFileInfo) + +#endif // SCRIPTING_INTERNAL_QFILEINFOPROTOTYPE_H diff --git a/wrappers/scriptwrappers.cpp b/wrappers/scriptwrappers.cpp index 2ae4cb1..de8e709 100644 --- a/wrappers/scriptwrappers.cpp +++ b/wrappers/scriptwrappers.cpp @@ -30,10 +30,13 @@ #include "scriptwrappers.h" #include #include "utils/position.h" +#include +#include "qfileinfoprototype.h" namespace Scripting { namespace Internal { +// ==================== Position ==================== QScriptValue scriptValueFromPosition(QScriptEngine *engine, const Position &pos) { QScriptValue obj = engine->newObject(); @@ -48,6 +51,7 @@ void PositionFromScriptValue(const QScriptValue &obj, Position& pos) pos.setColumn( obj.property(QLatin1String("column")).toInt32() ); } +// ==================== QRect ==================== QScriptValue scriptValueFromQRect(QScriptEngine *engine, const QRect &rect) { QScriptValue obj = engine->newObject(); @@ -66,11 +70,26 @@ void QRectFromScriptValue(const QScriptValue &obj, QRect& rect) rect.setHeight( obj.property(QLatin1String("height")).toInt32() ); } +// ==================== Prototypes ==================== + +#define registerProtoType(WrappedType, Prototype) \ +{\ + const int typeId = qRegisterMetaType(#WrappedType);\ + QScriptValue prototype = engine->newQObject(new Prototype );\ + engine->setDefaultPrototype( typeId, prototype );\ +\ + QScriptValue creator = engine->newFunction( Prototype::construct, prototype );\ + engine->globalObject().setProperty(QLatin1String(#WrappedType), creator);\ +} + + void registerWrappers(QScriptEngine* engine ) { qScriptRegisterMetaType(engine, scriptValueFromPosition, PositionFromScriptValue ); qScriptRegisterMetaType(engine, scriptValueFromQRect, QRectFromScriptValue ); + + registerProtoType(QFileInfo, QFileInfoPrototype); } } // namespace Internal -- cgit v1.2.3