diff options
author | Christian Kandeler <christian.kandeler@digia.com> | 2014-01-09 17:50:40 +0100 |
---|---|---|
committer | Joerg Bornemann <joerg.bornemann@digia.com> | 2014-01-10 18:11:22 +0100 |
commit | 81af9acaa295a574c1cb5e6714725197dac7f530 (patch) | |
tree | cc8c94467f49a7d267e5249f624874feecc7eed4 /src/lib/corelib/jsextensions | |
parent | 2fe25eb3f20ffb4e58cb559f2bcb9950c963290a (diff) |
Move Qt profile setup into a dedicated library.
Otherwise all changes to the implementation will have to be duplicated
in IDEs.
Change-Id: I61e6d4fa1ee9b724eb5d9de9f233dc915a6c8bc3
Reviewed-by: Joerg Bornemann <joerg.bornemann@digia.com>
Diffstat (limited to 'src/lib/corelib/jsextensions')
-rw-r--r-- | src/lib/corelib/jsextensions/domxml.cpp | 370 | ||||
-rw-r--r-- | src/lib/corelib/jsextensions/domxml.h | 118 | ||||
-rw-r--r-- | src/lib/corelib/jsextensions/file.cpp | 134 | ||||
-rw-r--r-- | src/lib/corelib/jsextensions/file.h | 44 | ||||
-rw-r--r-- | src/lib/corelib/jsextensions/jsextensions.cpp | 65 | ||||
-rw-r--r-- | src/lib/corelib/jsextensions/jsextensions.h | 59 | ||||
-rw-r--r-- | src/lib/corelib/jsextensions/jsextensions.pri | 17 | ||||
-rw-r--r-- | src/lib/corelib/jsextensions/moduleproperties.cpp | 154 | ||||
-rw-r--r-- | src/lib/corelib/jsextensions/moduleproperties.h | 62 | ||||
-rw-r--r-- | src/lib/corelib/jsextensions/process.cpp | 223 | ||||
-rw-r--r-- | src/lib/corelib/jsextensions/process.h | 91 | ||||
-rw-r--r-- | src/lib/corelib/jsextensions/textfile.cpp | 185 | ||||
-rw-r--r-- | src/lib/corelib/jsextensions/textfile.h | 74 |
13 files changed, 1596 insertions, 0 deletions
diff --git a/src/lib/corelib/jsextensions/domxml.cpp b/src/lib/corelib/jsextensions/domxml.cpp new file mode 100644 index 000000000..a66f2b21b --- /dev/null +++ b/src/lib/corelib/jsextensions/domxml.cpp @@ -0,0 +1,370 @@ +/**************************************************************************** +** +** Copyright (C) 2014 BogDan Vatra <bogdan@kde.org> +** Contact: http://www.qt-project.org/legal +** +** This file is part of the Qt Build Suite. +** +** 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 "domxml.h" + +#include <QFile> +#include <QScriptEngine> + + +namespace qbs { +namespace Internal { + +void initializeJsExtensionXml(QScriptValue extensionObject) +{ + QScriptEngine *engine = extensionObject.engine(); + QScriptValue obj = engine->newQMetaObject(&XmlDomDocument::staticMetaObject, engine->newFunction(&XmlDomDocument::ctor)); + extensionObject.setProperty("XmlDomDocument", obj); + obj = engine->newQMetaObject(&XmlDomNode::staticMetaObject, engine->newFunction(&XmlDomNode::ctor)); + extensionObject.setProperty("XmlDomElement", obj); +} + +QScriptValue XmlDomDocument::ctor(QScriptContext *context, QScriptEngine *engine) +{ + XmlDomDocument *xml = 0; + switch (context->argumentCount()) { + case 0: + xml = new XmlDomDocument(context); + break; + case 1: + xml = new XmlDomDocument(context, context->argument(0).toString()); + break; + default: + return context->throwError("DomXml(QString file = QLatin1String(\"\"))"); + } + QScriptValue obj = engine->newQObject(xml, QScriptEngine::ScriptOwnership); + return obj; +} + +QScriptValue XmlDomDocument::documentElement() +{ + return engine()->newQObject(new XmlDomNode(m_domDocument.documentElement()), QScriptEngine::ScriptOwnership); +} + +QScriptValue XmlDomDocument::createElement(const QString &tagName) +{ + return engine()->newQObject(new XmlDomNode(m_domDocument.createElement(tagName)), QScriptEngine::ScriptOwnership); +} + +QScriptValue XmlDomDocument::createCDATASection(const QString &value) +{ + return engine()->newQObject(new XmlDomNode(m_domDocument.createCDATASection(value)), QScriptEngine::ScriptOwnership); +} + +QScriptValue XmlDomDocument::createTextNode(const QString &value) +{ + return engine()->newQObject(new XmlDomNode(m_domDocument.createTextNode(value)), QScriptEngine::ScriptOwnership); +} + +bool XmlDomDocument::setContent(const QString &content) +{ + return m_domDocument.setContent(content); +} + +QString XmlDomDocument::toString(int indent) +{ + return m_domDocument.toString(indent); +} + +void XmlDomDocument::save(const QString &filePath, int indent) +{ + QFile f(filePath); + if (!f.open(QIODevice::WriteOnly)) { + context()->throwError(QString::fromLatin1("unable to open '%1'") + .arg(filePath)); + return; + } + + QByteArray buff(m_domDocument.toByteArray(indent)); + if (buff.size() != f.write(buff)) + { + context()->throwError(f.errorString()); + f.close(); + return; + } + + f.close(); + if (f.error() != QFile::NoError) + context()->throwError(f.errorString()); +} + +void XmlDomDocument::load(const QString &filePath) +{ + QFile f(filePath); + if (!f.open(QIODevice::ReadOnly)) { + context()->throwError(QString::fromLatin1("unable to open '%1'") + .arg(filePath)); + return; + } + + QString errorMsg; + if (!m_domDocument.setContent(&f, &errorMsg)) { + context()->throwError(errorMsg); + return; + } +} + +XmlDomDocument::XmlDomDocument(QScriptContext *context, const QString &name):m_domDocument(name) +{ + Q_UNUSED(context) + m_domNode = m_domDocument; +} + +QScriptValue XmlDomNode::ctor(QScriptContext *context, QScriptEngine *engine) +{ + Q_UNUSED(context) + return engine->newQObject(new XmlDomNode(), QScriptEngine::ScriptOwnership); +} + +bool XmlDomNode::isElement() const +{ + return m_domNode.isElement(); +} + +bool XmlDomNode::isCDATASection() const +{ + return m_domNode.isCDATASection(); +} + +bool XmlDomNode::isText() const +{ + return m_domNode.isText(); +} + +QString XmlDomNode::attribute(const QString &name, const QString &defValue) +{ + QDomElement el = m_domNode.toElement(); + if (el.isNull()) { + context()->throwError(QString::fromLatin1("Node '%1' is not an element node").arg(m_domNode.nodeName())); + return defValue; + } + return el.attribute(name, defValue); +} + +void XmlDomNode::setAttribute(const QString &name, const QString &value) +{ + QDomElement el = m_domNode.toElement(); + if (el.isNull()) { + context()->throwError(QString::fromLatin1("Node '%1' is not an element node").arg(m_domNode.nodeName())); + return; + } + el.setAttribute(name, value); +} + +bool XmlDomNode::hasAttribute(const QString &name) const +{ + QDomElement el = m_domNode.toElement(); + if (el.isNull()) { + context()->throwError(QString::fromLatin1("Node '%1' is not an element node").arg(m_domNode.nodeName())); + return false; + } + return el.hasAttribute(name); +} + +QString XmlDomNode::tagName() const +{ + QDomElement el = m_domNode.toElement(); + if (el.isNull()) { + context()->throwError(QString::fromLatin1("Node '%1' is not an element node").arg(m_domNode.nodeName())); + return QString(); + } + return el.tagName(); +} + +void XmlDomNode::setTagName(const QString &name) +{ + QDomElement el = m_domNode.toElement(); + if (el.isNull()) { + context()->throwError(QString::fromLatin1("Node '%1' is not an element node").arg(m_domNode.nodeName())); + return; + } + el.setTagName(name); +} + +QString XmlDomNode::text() const +{ + QDomElement el = m_domNode.toElement(); + if (el.isNull()) { + context()->throwError(QString::fromLatin1("Node '%1' is not an element node").arg(m_domNode.nodeName())); + return QString(); + } + return el.text(); +} + +QString XmlDomNode::data() const +{ + if (m_domNode.isText()) + return m_domNode.toText().data(); + if (m_domNode.isCDATASection()) + return m_domNode.toCDATASection().data(); + if (m_domNode.isCharacterData()) + return m_domNode.toCharacterData().data(); + context()->throwError(QString::fromLatin1("Node '%1' is not a character data node").arg(m_domNode.nodeName())); + return QString(); +} + +void XmlDomNode::setData(const QString &v) const +{ + if (m_domNode.isText()) + return m_domNode.toText().setData(v); + if (m_domNode.isCDATASection()) + return m_domNode.toCDATASection().setData(v); + if (m_domNode.isCharacterData()) + return m_domNode.toCharacterData().setData(v); + context()->throwError(QString::fromLatin1("Node '%1' is not a character data node").arg(m_domNode.nodeName())); + return; +} + +void XmlDomNode::clear() +{ + m_domNode.clear(); +} + +bool XmlDomNode::hasAttributes() const +{ + return m_domNode.hasAttributes(); +} + +bool XmlDomNode::hasChildNodes() const +{ + return m_domNode.hasChildNodes(); +} + +QScriptValue XmlDomNode::parentNode() const +{ + return engine()->newQObject(new XmlDomNode(m_domNode.parentNode()), QScriptEngine::ScriptOwnership); +} + +QScriptValue XmlDomNode::firstChild(const QString &tagName) +{ + if (tagName.isEmpty()) + return engine()->newQObject(new XmlDomNode(m_domNode.firstChild()), QScriptEngine::ScriptOwnership); + return engine()->newQObject(new XmlDomNode(m_domNode.firstChildElement(tagName)), QScriptEngine::ScriptOwnership); +} + +QScriptValue XmlDomNode::lastChild(const QString &tagName) const +{ + if (tagName.isEmpty()) + return engine()->newQObject(new XmlDomNode(m_domNode.lastChild()), QScriptEngine::ScriptOwnership); + return engine()->newQObject(new XmlDomNode(m_domNode.lastChildElement(tagName)), QScriptEngine::ScriptOwnership); +} + +QScriptValue XmlDomNode::previousSibling(const QString &tagName) const +{ + if (tagName.isEmpty()) + return engine()->newQObject(new XmlDomNode(m_domNode.previousSibling()), QScriptEngine::ScriptOwnership); + return engine()->newQObject(new XmlDomNode(m_domNode.previousSiblingElement(tagName)), QScriptEngine::ScriptOwnership); +} + +QScriptValue XmlDomNode::nextSibling(const QString &tagName) const +{ + if (tagName.isEmpty()) + return engine()->newQObject(new XmlDomNode(m_domNode.nextSibling()), QScriptEngine::ScriptOwnership); + return engine()->newQObject(new XmlDomNode(m_domNode.nextSiblingElement(tagName)), QScriptEngine::ScriptOwnership); +} + +QScriptValue XmlDomNode::appendChild(QScriptValue newChild) +{ + XmlDomNode *newNode = qobject_cast<XmlDomNode*>(newChild.toQObject()); + if (!newNode) { + context()->throwError(QString::fromLatin1("First argument is not a XmlDomNode object")); + return QScriptValue(); + } + return engine()->newQObject(new XmlDomNode(m_domNode.appendChild(newNode->m_domNode)), QScriptEngine::ScriptOwnership); +} + +QScriptValue XmlDomNode::insertBefore(const QScriptValue &newChild, const QScriptValue &refChild) +{ + XmlDomNode *newNode = qobject_cast<XmlDomNode*>(newChild.toQObject()); + if (!newNode) { + context()->throwError(QString::fromLatin1("First argument is not a XmlDomNode object")); + return QScriptValue(); + } + + XmlDomNode *refNode = qobject_cast<XmlDomNode*>(refChild.toQObject()); + if (!refNode) { + context()->throwError(QString::fromLatin1("Second argument is not a XmlDomNode object")); + return QScriptValue(); + } + + return engine()->newQObject(new XmlDomNode(m_domNode.insertBefore(newNode->m_domNode, refNode->m_domNode)), QScriptEngine::ScriptOwnership); +} + +QScriptValue XmlDomNode::insertAfter(const QScriptValue &newChild, const QScriptValue &refChild) +{ + XmlDomNode *newNode = qobject_cast<XmlDomNode*>(newChild.toQObject()); + if (!newNode) { + context()->throwError(QString::fromLatin1("First argument is not a XmlDomNode object")); + return QScriptValue(); + } + + XmlDomNode *refNode = qobject_cast<XmlDomNode*>(refChild.toQObject()); + if (!refNode) { + context()->throwError(QString::fromLatin1("Second argument is not a XmlDomNode object")); + return QScriptValue(); + } + + return engine()->newQObject(new XmlDomNode(m_domNode.insertAfter(newNode->m_domNode, refNode->m_domNode)), QScriptEngine::ScriptOwnership); +} + +QScriptValue XmlDomNode::replaceChild(const QScriptValue &newChild, const QScriptValue &oldChild) +{ + XmlDomNode *newNode = qobject_cast<XmlDomNode*>(newChild.toQObject()); + if (!newNode) { + context()->throwError(QString::fromLatin1("First argument is not a XmlDomNode object")); + return QScriptValue(); + } + + XmlDomNode *oldNode = qobject_cast<XmlDomNode*>(oldChild.toQObject()); + if (!oldNode) { + context()->throwError(QString::fromLatin1("Second argument is not a XmlDomNode object")); + return QScriptValue(); + } + + return engine()->newQObject(new XmlDomNode(m_domNode.replaceChild(newNode->m_domNode, oldNode->m_domNode)), QScriptEngine::ScriptOwnership); +} + +QScriptValue XmlDomNode::removeChild(const QScriptValue &oldChild) +{ + XmlDomNode *oldNode = qobject_cast<XmlDomNode*>(oldChild.toQObject()); + if (!oldNode) { + context()->throwError(QString::fromLatin1("First argument is not a XmlDomNode object")); + return QScriptValue(); + } + + return engine()->newQObject(new XmlDomNode(m_domNode.removeChild(oldNode->m_domNode)), QScriptEngine::ScriptOwnership); +} + +XmlDomNode::XmlDomNode(const QDomNode &other) +{ + m_domNode = other; +} + +} // namespace Internal +} // namespace qbs diff --git a/src/lib/corelib/jsextensions/domxml.h b/src/lib/corelib/jsextensions/domxml.h new file mode 100644 index 000000000..7df603328 --- /dev/null +++ b/src/lib/corelib/jsextensions/domxml.h @@ -0,0 +1,118 @@ +/**************************************************************************** +** +** Copyright (C) 2014 BogDan Vatra <bogdan@kde.org> +** Contact: http://www.qt-project.org/legal +** +** This file is part of the Qt Build Suite. +** +** 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 DOMXML_H +#define DOMXML_H + +#include <QDomDocument> +#include <QDomNode> +#include <QObject> +#include <QScriptValue> +#include <QScriptable> +#include <QVariant> + +namespace qbs { +namespace Internal { + +class XmlDomDocument; + +void initializeJsExtensionXml(QScriptValue extensionObject); + +class XmlDomNode: public QObject, public QScriptable +{ + Q_OBJECT +public: + static QScriptValue ctor(QScriptContext *context, QScriptEngine *engine); + + Q_INVOKABLE bool isElement() const; + Q_INVOKABLE bool isCDATASection() const; + Q_INVOKABLE bool isText() const; + + Q_INVOKABLE QString attribute(const QString & name, const QString & defValue = QString()); + Q_INVOKABLE void setAttribute(const QString & name, const QString & value); + Q_INVOKABLE bool hasAttribute(const QString & name) const; + Q_INVOKABLE QString tagName() const; + Q_INVOKABLE void setTagName(const QString & name); + + Q_INVOKABLE QString text() const; + + Q_INVOKABLE QString data() const; + Q_INVOKABLE void setData(const QString &v) const; + + Q_INVOKABLE void clear(); + Q_INVOKABLE bool hasAttributes() const; + Q_INVOKABLE bool hasChildNodes() const; + Q_INVOKABLE QScriptValue parentNode() const; + Q_INVOKABLE QScriptValue firstChild(const QString & tagName = QString()); + Q_INVOKABLE QScriptValue lastChild(const QString & tagName = QString()) const; + Q_INVOKABLE QScriptValue previousSibling(const QString & tagName = QString()) const; + Q_INVOKABLE QScriptValue nextSibling(const QString & tagName = QString()) const; + + Q_INVOKABLE QScriptValue appendChild(QScriptValue newChild); + Q_INVOKABLE QScriptValue insertBefore(const QScriptValue& newChild, const QScriptValue& refChild); + Q_INVOKABLE QScriptValue insertAfter(const QScriptValue& newChild, const QScriptValue& refChild); + Q_INVOKABLE QScriptValue replaceChild(const QScriptValue& newChild, const QScriptValue& oldChild); + Q_INVOKABLE QScriptValue removeChild(const QScriptValue& oldChild); + +protected: + friend class XmlDomDocument; + XmlDomNode(const QDomNode &other = QDomNode()); + QDomNode m_domNode; +}; + +class XmlDomDocument: public XmlDomNode +{ + Q_OBJECT +public: + static QScriptValue ctor(QScriptContext *context, QScriptEngine *engine); + Q_INVOKABLE QScriptValue documentElement(); + Q_INVOKABLE QScriptValue createElement(const QString & tagName); + Q_INVOKABLE QScriptValue createCDATASection(const QString & value); + Q_INVOKABLE QScriptValue createTextNode(const QString & value); + + Q_INVOKABLE bool setContent(const QString & content); + Q_INVOKABLE QString toString(int indent = 1); + + Q_INVOKABLE void save(const QString & filePath, int indent = 1); + Q_INVOKABLE void load(const QString & filePath); + +protected: + XmlDomDocument(QScriptContext *context, const QString &name = QString()); + +private: + QDomDocument m_domDocument; +}; + +} // namespace Internal +} // namespace qbs + +Q_DECLARE_METATYPE(qbs::Internal::XmlDomDocument *) +Q_DECLARE_METATYPE(qbs::Internal::XmlDomNode *) + +#endif // DOMXML_H diff --git a/src/lib/corelib/jsextensions/file.cpp b/src/lib/corelib/jsextensions/file.cpp new file mode 100644 index 000000000..1e6f2947c --- /dev/null +++ b/src/lib/corelib/jsextensions/file.cpp @@ -0,0 +1,134 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the Qt Build Suite. +** +** 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 "file.h" + +#include <language/scriptengine.h> +#include <logging/translator.h> +#include <tools/fileinfo.h> + +#include <QFileInfo> +#include <QScriptEngine> + +namespace qbs { +namespace Internal { + +class File +{ + friend void initializeJsExtensionFile(QScriptValue extensionObject); + +private: + static QScriptValue js_ctor(QScriptContext *context, QScriptEngine *engine); + static QScriptValue js_copy(QScriptContext *context, QScriptEngine *engine); + static QScriptValue js_exists(QScriptContext *context, QScriptEngine *engine); + static QScriptValue js_lastModified(QScriptContext *context, QScriptEngine *engine); + static QScriptValue js_remove(QScriptContext *context, QScriptEngine *engine); +}; + + +void initializeJsExtensionFile(QScriptValue extensionObject) +{ + QScriptEngine *engine = extensionObject.engine(); + QScriptValue fileObj = engine->newFunction(File::js_ctor); + fileObj.setProperty("copy", engine->newFunction(File::js_copy)); + fileObj.setProperty("exists", engine->newFunction(File::js_exists)); + fileObj.setProperty("lastModified", engine->newFunction(File::js_lastModified)); + fileObj.setProperty("remove", engine->newFunction(File::js_remove)); + extensionObject.setProperty("File", fileObj); +} + +QScriptValue File::js_ctor(QScriptContext *context, QScriptEngine *engine) +{ + // Add instance variables here etc., if needed. + Q_UNUSED(context); + Q_UNUSED(engine); + return true; +} + +QScriptValue File::js_copy(QScriptContext *context, QScriptEngine *engine) +{ + Q_UNUSED(engine); + if (Q_UNLIKELY(context->argumentCount() < 2)) { + return context->throwError(QScriptContext::SyntaxError, + Tr::tr("copy expects 2 arguments")); + } + + const QString sourceFile = context->argument(0).toString(); + const QString targetFile = context->argument(1).toString(); + QString errorMessage; + if (Q_UNLIKELY(!copyFileRecursion(sourceFile, targetFile, false, &errorMessage))) + return context->throwError(errorMessage); + return true; +} + +QScriptValue File::js_exists(QScriptContext *context, QScriptEngine *engine) +{ + Q_UNUSED(engine); + if (Q_UNLIKELY(context->argumentCount() < 1)) { + return context->throwError(QScriptContext::SyntaxError, + Tr::tr("exist expects 1 argument")); + } + const QString filePath = context->argument(0).toString(); + const bool exists = FileInfo::exists(filePath); + ScriptEngine * const se = static_cast<ScriptEngine *>(engine); + se->addFileExistsResult(filePath, exists); + return exists; +} + +QScriptValue File::js_remove(QScriptContext *context, QScriptEngine *engine) +{ + Q_UNUSED(engine); + if (Q_UNLIKELY(context->argumentCount() < 1)) { + return context->throwError(QScriptContext::SyntaxError, + Tr::tr("remove expects 1 argument")); + } + QString fileName = context->argument(0).toString(); + + QString errorMessage; + if (Q_UNLIKELY(!removeFileRecursion(QFileInfo(fileName), &errorMessage))) + return context->throwError(errorMessage); + return true; +} + +QScriptValue File::js_lastModified(QScriptContext *context, QScriptEngine *engine) +{ + Q_UNUSED(engine); + if (Q_UNLIKELY(context->argumentCount() < 1)) { + return context->throwError(QScriptContext::SyntaxError, + Tr::tr("File.lastModified() expects an argument")); + } + const QString filePath = context->argument(0).toString(); + const FileTime timestamp = FileInfo(filePath).lastModified(); + ScriptEngine * const se = static_cast<ScriptEngine *>(engine); + se->addFileLastModifiedResult(filePath, timestamp); + return static_cast<qsreal>(timestamp.m_fileTime); +} + +} // namespace Internal +} // namespace qbs diff --git a/src/lib/corelib/jsextensions/file.h b/src/lib/corelib/jsextensions/file.h new file mode 100644 index 000000000..874c40c71 --- /dev/null +++ b/src/lib/corelib/jsextensions/file.h @@ -0,0 +1,44 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the Qt Build Suite. +** +** 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 QBS_FILE_H +#define QBS_FILE_H + +#include <QScriptContext> +#include <QScriptValue> + +namespace qbs { +namespace Internal { + +void initializeJsExtensionFile(QScriptValue extensionObject); + +} // namespace Internal +} // namespace qbs + +#endif // QBS_FILE_H diff --git a/src/lib/corelib/jsextensions/jsextensions.cpp b/src/lib/corelib/jsextensions/jsextensions.cpp new file mode 100644 index 000000000..b6b5e099b --- /dev/null +++ b/src/lib/corelib/jsextensions/jsextensions.cpp @@ -0,0 +1,65 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the Qt Build Suite. +** +** 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 "jsextensions.h" + +#include "domxml.h" +#include "file.h" +#include "process.h" +#include "textfile.h" + +namespace qbs { +namespace Internal { + +void JsExtensions::setupExtensions(const QStringList &names, QScriptValue scope) +{ + foreach (const QString &name, names) + initializers().value(name)(scope); +} + +bool JsExtensions::hasExtension(const QString &name) +{ + return initializers().contains(name); +} + +JsExtensions::InitializerMap JsExtensions::initializers() +{ + if (m_initializers.isEmpty()) { + m_initializers.insert(QLatin1String("File"), &initializeJsExtensionFile); + m_initializers.insert(QLatin1String("Process"), &initializeJsExtensionProcess); + m_initializers.insert(QLatin1String("Xml"), &initializeJsExtensionXml); + m_initializers.insert(QLatin1String("TextFile"), &initializeJsExtensionTextFile); + } + return m_initializers; +} + +JsExtensions::InitializerMap JsExtensions::m_initializers; + +} // namespace Internal +} // namespace qbs diff --git a/src/lib/corelib/jsextensions/jsextensions.h b/src/lib/corelib/jsextensions/jsextensions.h new file mode 100644 index 000000000..e268ec215 --- /dev/null +++ b/src/lib/corelib/jsextensions/jsextensions.h @@ -0,0 +1,59 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the Qt Build Suite. +** +** 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 QBS_JSEXTENSIONS_H +#define QBS_JSEXTENSIONS_H + +#include <QHash> +#include <QStringList> + +QT_BEGIN_NAMESPACE +class QScriptValue; +QT_END_NAMESPACE + +namespace qbs { +namespace Internal { + +class JsExtensions +{ +public: + static void setupExtensions(const QStringList &names, QScriptValue scope); + static bool hasExtension(const QString &name); + +private: + typedef QHash<QString, void (*)(QScriptValue)> InitializerMap; + static InitializerMap initializers(); + + static InitializerMap m_initializers; +}; + +} // namespace Internal +} // namespace qbs + +#endif // Include guard. diff --git a/src/lib/corelib/jsextensions/jsextensions.pri b/src/lib/corelib/jsextensions/jsextensions.pri new file mode 100644 index 000000000..21c97ef64 --- /dev/null +++ b/src/lib/corelib/jsextensions/jsextensions.pri @@ -0,0 +1,17 @@ +QT += xml + +HEADERS += \ + $$PWD/file.h \ + $$PWD/textfile.h \ + $$PWD/process.h \ + $$PWD/moduleproperties.h \ + $$PWD/domxml.h \ + $$PWD/jsextensions.h + +SOURCES += \ + $$PWD/file.cpp \ + $$PWD/textfile.cpp \ + $$PWD/process.cpp \ + $$PWD/moduleproperties.cpp \ + $$PWD/domxml.cpp \ + $$PWD/jsextensions.cpp diff --git a/src/lib/corelib/jsextensions/moduleproperties.cpp b/src/lib/corelib/jsextensions/moduleproperties.cpp new file mode 100644 index 000000000..83d92e776 --- /dev/null +++ b/src/lib/corelib/jsextensions/moduleproperties.cpp @@ -0,0 +1,154 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the Qt Build Suite. +** +** 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 "moduleproperties.h" + +#include <buildgraph/artifact.h> +#include <language/language.h> +#include <language/scriptengine.h> +#include <logging/translator.h> +#include <tools/error.h> +#include <tools/propertyfinder.h> + +#include <QScriptEngine> + +namespace qbs { +namespace Internal { + +static QString ptrKey() { return QLatin1String("__internalPtr"); } +static QString typeKey() { return QLatin1String("__type"); } +static QString productType() { return QLatin1String("product"); } +static QString artifactType() { return QLatin1String("artifact"); } + +void ModuleProperties::init(QScriptValue productObject, + const ResolvedProductConstPtr &product) +{ + init(productObject, product.data(), productType()); +} + +void ModuleProperties::init(QScriptValue artifactObject, const Artifact *artifact) +{ + init(artifactObject, artifact, artifactType()); +} + +void ModuleProperties::init(QScriptValue objectWithProperties, const void *ptr, + const QString &type) +{ + QScriptEngine * const engine = objectWithProperties.engine(); + objectWithProperties.setProperty("moduleProperties", + engine->newFunction(ModuleProperties::js_moduleProperties, 2)); + objectWithProperties.setProperty("moduleProperty", + engine->newFunction(ModuleProperties::js_moduleProperty, 2)); + objectWithProperties.setProperty(ptrKey(), engine->toScriptValue(quintptr(ptr))); + objectWithProperties.setProperty(typeKey(), type); +} + +QScriptValue ModuleProperties::js_moduleProperties(QScriptContext *context, QScriptEngine *engine) +{ + try { + return moduleProperties(context, engine, false); + } catch (const ErrorInfo &e) { + return context->throwError(e.toString()); + } +} + +QScriptValue ModuleProperties::js_moduleProperty(QScriptContext *context, QScriptEngine *engine) +{ + try { + return moduleProperties(context, engine, true); + } catch (const ErrorInfo &e) { + return context->throwError(e.toString()); + } +} + +QScriptValue ModuleProperties::moduleProperties(QScriptContext *context, QScriptEngine *engine, + bool oneValue) +{ + if (Q_UNLIKELY(context->argumentCount() < 2)) { + return context->throwError(QScriptContext::SyntaxError, + Tr::tr("Function moduleProperties() expects 2 arguments")); + } + + const QScriptValue objectWithProperties = context->thisObject(); + const QScriptValue typeScriptValue = objectWithProperties.property(typeKey()); + if (Q_UNLIKELY(!typeScriptValue.isString())) { + return context->throwError(QScriptContext::TypeError, + QLatin1String("Internal error: __type not set up")); + } + const QScriptValue ptrScriptValue = objectWithProperties.property(ptrKey()); + if (Q_UNLIKELY(!ptrScriptValue.isNumber())) { + return context->throwError(QScriptContext::TypeError, + QLatin1String("Internal error: __internalPtr not set up")); + } + + const void *ptr = reinterpret_cast<const void *>(qscriptvalue_cast<quintptr>(ptrScriptValue)); + PropertyMapConstPtr properties; + const Artifact *artifact = 0; + if (typeScriptValue.toString() == productType()) { + properties = static_cast<const ResolvedProduct *>(ptr)->properties; + } else if (typeScriptValue.toString() == artifactType()) { + artifact = static_cast<const Artifact *>(ptr); + properties = artifact->properties; + } else { + return context->throwError(QScriptContext::TypeError, + QLatin1String("Internal error: invalid type")); + } + + ScriptEngine * const qbsEngine = static_cast<ScriptEngine *>(engine); + const QString moduleName = internalModuleName(context->argument(0).toString()); + const QString propertyName = context->argument(1).toString(); + + QVariant value = qbsEngine->retrieveFromPropertyCache(moduleName, propertyName, properties); + if (!value.isValid()) { + if (oneValue) + value = PropertyFinder().propertyValue(properties->value(), moduleName, propertyName); + else + value = PropertyFinder().propertyValues(properties->value(), moduleName, propertyName); + const Property p(moduleName, propertyName, value); + if (artifact) + qbsEngine->addPropertyRequestedFromArtifact(artifact, p); + else + qbsEngine->addPropertyRequestedInScript(p); + + // Cache the variant value. We must not cache the QScriptValue here, because it's a + // reference and the user might change the actual object. + qbsEngine->addToPropertyCache(moduleName, propertyName, properties, value); + } + return engine->toScriptValue(value); +} + +QString ModuleProperties::internalModuleName(const QString &name) +{ + QString result = name; + result.replace(QLatin1Char('.'), QLatin1Char('/')); + return result; +} + +} // namespace Internal +} // namespace qbs diff --git a/src/lib/corelib/jsextensions/moduleproperties.h b/src/lib/corelib/jsextensions/moduleproperties.h new file mode 100644 index 000000000..81f27f6ec --- /dev/null +++ b/src/lib/corelib/jsextensions/moduleproperties.h @@ -0,0 +1,62 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the Qt Build Suite. +** +** 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 QBS_MODULEPROPERTIES_H +#define QBS_MODULEPROPERTIES_H + +#include <buildgraph/forward_decls.h> +#include <language/forward_decls.h> + +#include <QScriptContext> +#include <QScriptValue> + +namespace qbs { +namespace Internal { + +class ModuleProperties +{ +public: + static void init(QScriptValue productObject, const ResolvedProductConstPtr &product); + static void init(QScriptValue artifactObject, const Artifact *artifact); + +private: + static void init(QScriptValue objectWithProperties, const void *ptr, const QString &type); + + static QScriptValue js_moduleProperties(QScriptContext *context, QScriptEngine *engine); + static QScriptValue js_moduleProperty(QScriptContext *context, QScriptEngine *engine); + + static QScriptValue moduleProperties(QScriptContext *context, QScriptEngine *engine, + bool oneValue); + static QString internalModuleName(const QString &name); +}; + +} // namespace Internal +} // namespace qbs + +#endif // QBS_MODULEPROPERTIES_H diff --git a/src/lib/corelib/jsextensions/process.cpp b/src/lib/corelib/jsextensions/process.cpp new file mode 100644 index 000000000..3cf74ab31 --- /dev/null +++ b/src/lib/corelib/jsextensions/process.cpp @@ -0,0 +1,223 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the Qt Build Suite. +** +** 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 "process.h" + +#include <logging/translator.h> +#include <tools/hostosinfo.h> + +#include <QProcess> +#include <QScriptEngine> +#include <QScriptValue> +#include <QTextCodec> +#include <QTextStream> + +namespace qbs { +namespace Internal { + +void initializeJsExtensionProcess(QScriptValue extensionObject) +{ + QScriptEngine *engine = extensionObject.engine(); + QScriptValue obj = engine->newQMetaObject(&Process::staticMetaObject, engine->newFunction(&Process::ctor)); + extensionObject.setProperty("Process", obj); +} + +QScriptValue Process::ctor(QScriptContext *context, QScriptEngine *engine) +{ + Process *t; + switch (context->argumentCount()) { + case 0: + t = new Process(context); + break; + default: + return context->throwError("Process()"); + } + + QScriptValue obj = engine->newQObject(t, QScriptEngine::ScriptOwnership); + + // Get environment + QVariant v = engine->property("_qbs_procenv"); + if (!v.isNull()) + t->m_environment + = QProcessEnvironment(*reinterpret_cast<QProcessEnvironment*>(v.value<void*>())); + + return obj; +} + +Process::~Process() +{ + delete m_textStream; + delete m_qProcess; +} + +Process::Process(QScriptContext *context) +{ + Q_UNUSED(context); + Q_ASSERT(thisObject().engine() == engine()); + + m_qProcess = new QProcess; + m_textStream = new QTextStream(m_qProcess); +} + +QString Process::getEnv(const QString &name) +{ + Q_ASSERT(thisObject().engine() == engine()); + return m_environment.value(name); +} + +void Process::setEnv(const QString &name, const QString &value) +{ + Q_ASSERT(thisObject().engine() == engine()); + m_environment.insert(name, value); +} + +QString Process::workingDirectory() +{ + Q_ASSERT(thisObject().engine() == engine()); + return m_workingDirectory; +} + +void Process::setWorkingDirectory(const QString &dir) +{ + Q_ASSERT(thisObject().engine() == engine()); + m_workingDirectory = dir; +} + +bool Process::start(const QString &program, const QStringList &arguments) +{ + Q_ASSERT(thisObject().engine() == engine()); + + if (!m_workingDirectory.isEmpty()) + m_qProcess->setWorkingDirectory(m_workingDirectory); + + m_qProcess->setProcessEnvironment(m_environment); + m_qProcess->start(program, arguments); + return m_qProcess->waitForStarted(); +} + +int Process::exec(const QString &program, const QStringList &arguments, bool throwOnError) +{ + Q_ASSERT(thisObject().engine() == engine()); + + if (!start(program, arguments)) { + if (throwOnError) { + context()->throwError(Tr::tr("Error running '%1': %2") + .arg(program, m_qProcess->errorString())); + } + return -1; + } + m_qProcess->closeWriteChannel(); + m_qProcess->waitForFinished(-1); + if (throwOnError) { + if (m_qProcess->error() != QProcess::UnknownError) { + context()->throwError(Tr::tr("Error running '%1': %2") + .arg(program, m_qProcess->errorString())); + } else if (m_qProcess->exitCode() != 0) { + QString errorMessage = Tr::tr("Process '%1' finished with exit code %2.") + .arg(program).arg(m_qProcess->exitCode()); + const QString stdErr = readStdErr(); + if (!stdErr.isEmpty()) + errorMessage.append(Tr::tr(" The standard error output was:\n")).append(stdErr); + context()->throwError(errorMessage); + } + } + if (m_qProcess->error() != QProcess::UnknownError) + return -1; + return m_qProcess->exitCode(); +} + +void Process::close() +{ + Q_ASSERT(thisObject().engine() == engine()); + delete m_qProcess; + m_qProcess = 0; + delete m_textStream; + m_textStream = 0; +} + +bool Process::waitForFinished(int msecs) +{ + Q_ASSERT(thisObject().engine() == engine()); + + if (m_qProcess->state() == QProcess::NotRunning) + return true; + return m_qProcess->waitForFinished(msecs); +} + +void Process::terminate() +{ + m_qProcess->terminate(); +} + +void Process::kill() +{ + m_qProcess->kill(); +} + +void Process::setCodec(const QString &codec) +{ + Q_ASSERT(thisObject().engine() == engine()); + m_textStream->setCodec(qPrintable(codec)); +} + +QString Process::readLine() +{ + return m_textStream->readLine(); +} + +QString Process::readStdOut() +{ + return m_textStream->readAll(); +} + +QString Process::readStdErr() +{ + return m_textStream->codec()->toUnicode(m_qProcess->readAllStandardError()); +} + +int Process::exitCode() const +{ + return m_qProcess->exitCode(); +} + +void Process::write(const QString &str) +{ + (*m_textStream) << str; +} + +void Process::writeLine(const QString &str) +{ + (*m_textStream) << str; + if (HostOsInfo::isWindowsHost()) + (*m_textStream) << '\r'; + (*m_textStream) << '\n'; +} + +} // namespace Internal +} // namespace qbs diff --git a/src/lib/corelib/jsextensions/process.h b/src/lib/corelib/jsextensions/process.h new file mode 100644 index 000000000..1dea021a3 --- /dev/null +++ b/src/lib/corelib/jsextensions/process.h @@ -0,0 +1,91 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the Qt Build Suite. +** +** 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 QBS_PROCESS_H +#define QBS_PROCESS_H + +#include <QObject> +#include <QProcessEnvironment> +#include <QScriptable> +#include <QVariant> + +QT_BEGIN_NAMESPACE +class QProcess; +class QTextStream; +QT_END_NAMESPACE + +namespace qbs { +namespace Internal { +void initializeJsExtensionProcess(QScriptValue extensionObject); + +class Process : public QObject, public QScriptable +{ + Q_OBJECT +public: + static QScriptValue ctor(QScriptContext *context, QScriptEngine *engine); + Process(QScriptContext *context); + ~Process(); + + Q_INVOKABLE QString getEnv(const QString &name); + Q_INVOKABLE void setEnv(const QString &name, const QString &value); + Q_INVOKABLE void setCodec(const QString &codec); + + Q_INVOKABLE QString workingDirectory(); + Q_INVOKABLE void setWorkingDirectory(const QString &dir); + + Q_INVOKABLE bool start(const QString &program, const QStringList &arguments); + Q_INVOKABLE int exec(const QString &program, const QStringList &arguments, + bool throwOnError = false); + Q_INVOKABLE void close(); + Q_INVOKABLE bool waitForFinished(int msecs = 30000); + Q_INVOKABLE void terminate(); + Q_INVOKABLE void kill(); + + Q_INVOKABLE QString readLine(); + Q_INVOKABLE QString readStdOut(); + Q_INVOKABLE QString readStdErr(); + + Q_INVOKABLE void write(const QString &str); + Q_INVOKABLE void writeLine(const QString &str); + + Q_INVOKABLE int exitCode() const; + +private: + QProcess *m_qProcess; + QProcessEnvironment m_environment; + QString m_workingDirectory; + QTextStream *m_textStream; +}; + +} // namespace Internal +} // namespace qbs + +Q_DECLARE_METATYPE(qbs::Internal::Process *) + +#endif // QBS_PROCESS_H diff --git a/src/lib/corelib/jsextensions/textfile.cpp b/src/lib/corelib/jsextensions/textfile.cpp new file mode 100644 index 000000000..7129ee955 --- /dev/null +++ b/src/lib/corelib/jsextensions/textfile.cpp @@ -0,0 +1,185 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the Qt Build Suite. +** +** 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 "textfile.h" + +#include <tools/hostosinfo.h> + +#include <QFile> +#include <QScriptEngine> +#include <QScriptValue> +#include <QTextStream> + +namespace qbs { +namespace Internal { + +void initializeJsExtensionTextFile(QScriptValue extensionObject) +{ + QScriptEngine *engine = extensionObject.engine(); + QScriptValue obj = engine->newQMetaObject(&TextFile::staticMetaObject, engine->newFunction(&TextFile::ctor)); + extensionObject.setProperty("TextFile", obj); +} + +QScriptValue TextFile::ctor(QScriptContext *context, QScriptEngine *engine) +{ + TextFile *t; + switch (context->argumentCount()) { + case 1: + t = new TextFile(context, + context->argument(0).toString()); + break; + case 2: + t = new TextFile(context, + context->argument(0).toString(), + static_cast<OpenMode>(context->argument(1).toInt32()) + ); + break; + case 3: + t = new TextFile(context, + context->argument(0).toString(), + static_cast<OpenMode>(context->argument(1).toInt32()), + context->argument(2).toString() + ); + break; + default: + return context->throwError("TextFile(QString file, OpenMode mode = ReadOnly, QString codec = QLatin1String(\"UTF8\"))"); + } + + QScriptValue obj = engine->newQObject(t, QScriptEngine::ScriptOwnership); +// obj.setProperty("d", engine->newQObject(new FileImplementation(t), +// QScriptEngine::QScriptEngine::QtOwnership)); + return obj; +} + +TextFile::~TextFile() +{ + delete qstream; + delete qfile; +} + +TextFile::TextFile(QScriptContext *context, const QString &file, OpenMode mode, const QString &codec) +{ + Q_UNUSED(codec) + Q_ASSERT(thisObject().engine() == engine()); + TextFile *t = this; + + t->qfile = new QFile(file); + QIODevice::OpenMode m = QIODevice::ReadOnly; + if (mode == ReadWrite) + m = QIODevice::ReadWrite; + else if (mode == ReadOnly) + m = QIODevice::ReadOnly; + else if (mode == WriteOnly) + m = QIODevice::WriteOnly; + if (Q_UNLIKELY(!t->qfile->open(m))) { + delete t->qfile; + t->qfile = 0; + context->throwError(QString::fromLatin1("unable to open '%1'") + .arg(file) + ); + } + + t->qstream = new QTextStream(t->qfile); +} + +void TextFile::close() +{ + Q_ASSERT(thisObject().engine() == engine()); + TextFile *t = qscriptvalue_cast<TextFile*>(thisObject()); + if (t->qfile) + t->qfile->close(); + delete t->qfile; + t->qfile = 0; + delete t->qstream; + t->qstream = 0; +} + +void TextFile::setCodec(const QString &codec) +{ + Q_ASSERT(thisObject().engine() == engine()); + TextFile *t = qscriptvalue_cast<TextFile*>(thisObject()); + if (!t->qstream) + return; + t->qstream->setCodec(qPrintable(codec)); +} + +QString TextFile::readLine() +{ + TextFile *t = qscriptvalue_cast<TextFile*>(thisObject()); + if (!t->qfile) + return QString(); + return t->qstream->readLine(); +} + +QString TextFile::readAll() +{ + TextFile *t = qscriptvalue_cast<TextFile*>(thisObject()); + if (!t->qfile) + return QString(); + return t->qstream->readAll(); +} + +bool TextFile::atEof() const +{ + TextFile *t = qscriptvalue_cast<TextFile*>(thisObject()); + if (!t->qstream) + return true; + return t->qstream->atEnd(); +} + +void TextFile::truncate() +{ + TextFile *t = qscriptvalue_cast<TextFile*>(thisObject()); + if (!t->qstream) + return; + t->qfile->resize(0); + t->qstream->reset(); +} + +void TextFile::write(const QString &str) +{ + TextFile *t = qscriptvalue_cast<TextFile*>(thisObject()); + if (!t->qstream) + return; + (*t->qstream) << str; +} + +void TextFile::writeLine(const QString &str) +{ + TextFile *t = qscriptvalue_cast<TextFile*>(thisObject()); + if (!t->qstream) + return; + (*t->qstream) << str; + if (HostOsInfo::isWindowsHost()) + (*t->qstream) << '\r'; + (*t->qstream) << '\n'; +} + +} // namespace Internal +} // namespace qbs diff --git a/src/lib/corelib/jsextensions/textfile.h b/src/lib/corelib/jsextensions/textfile.h new file mode 100644 index 000000000..ff8aaf43b --- /dev/null +++ b/src/lib/corelib/jsextensions/textfile.h @@ -0,0 +1,74 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the Qt Build Suite. +** +** 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 QBS_TEXTFILE_H +#define QBS_TEXTFILE_H + +#include <QObject> +#include <QScriptable> +#include <QVariant> + +QT_BEGIN_NAMESPACE +class QFile; +class QTextStream; +QT_END_NAMESPACE + +namespace qbs { +namespace Internal { + +void initializeJsExtensionTextFile(QScriptValue extensionObject); + +class TextFile : public QObject, public QScriptable +{ + Q_OBJECT + Q_ENUMS(OpenMode) +public: + enum OpenMode { ReadOnly, WriteOnly, ReadWrite }; + static QScriptValue ctor(QScriptContext *context, QScriptEngine *engine); + TextFile(QScriptContext *context, const QString &file, OpenMode mode = ReadOnly, const QString &codec = QLatin1String("UTF8")); + ~TextFile(); + Q_INVOKABLE void close(); + Q_INVOKABLE void setCodec(const QString &codec); + Q_INVOKABLE QString readLine(); + Q_INVOKABLE QString readAll(); + Q_INVOKABLE bool atEof() const; + Q_INVOKABLE void truncate(); + Q_INVOKABLE void write(const QString &str); + Q_INVOKABLE void writeLine(const QString &str); +private: + QFile *qfile; + QTextStream *qstream; +}; + +} // namespace Internal +} // namespace qbs + +Q_DECLARE_METATYPE(qbs::Internal::TextFile *) + +#endif // QBS_TEXTFILE_H |