Browse Source

refactored code to use native qml object hierarchy instead of forcing

object properties from c++
cl-refactor
arkpar 10 years ago
parent
commit
b3d43bd511
  1. 122
      mix/AppContext.cpp
  2. 88
      mix/AppContext.h
  3. 26
      mix/ClientModel.cpp
  4. 10
      mix/ClientModel.h
  5. 39
      mix/Clipboard.cpp
  6. 29
      mix/Clipboard.h
  7. 88
      mix/CodeEditorExtensionManager.cpp
  8. 71
      mix/CodeEditorExtensionManager.h
  9. 3
      mix/CodeModel.cpp
  10. 2
      mix/CodeModel.h
  11. 82
      mix/Extension.cpp
  12. 75
      mix/Extension.h
  13. 42
      mix/MixApplication.cpp
  14. 4
      mix/MixApplication.h
  15. 3
      mix/QContractDefinition.cpp
  16. 4
      mix/qml/ContractLibrary.qml
  17. 2
      mix/qml/DebugInfoList.qml
  18. 2
      mix/qml/DeploymentDialog.qml
  19. 4
      mix/qml/LogsPane.qml
  20. 4
      mix/qml/MainContent.qml
  21. 5
      mix/qml/ProjectModel.qml
  22. 2
      mix/qml/TransactionLog.qml
  23. 4
      mix/qml/WebCodeEditor.qml
  24. 11
      mix/qml/WebPreview.qml
  25. 37
      mix/qml/main.qml

122
mix/AppContext.cpp

@ -1,122 +0,0 @@
/*
This file is part of cpp-ethereum.
cpp-ethereum is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file AppContext.cpp
* @author Yann yann@ethdev.com
* @date 2014
* Provides access to the current QQmlApplicationEngine which is used to add QML file on the fly.
* In the future this class can be extended to add more variable related to the context of the application.
* For now AppContext provides reference to:
* - QQmlApplicationEngine
* - dev::WebThreeDirect (and dev::eth::Client)
* - KeyEventManager
*/
#include <QMessageBox>
#include <QClipboard>
#include <QQmlComponent>
#include <QQmlContext>
#include <QQmlApplicationEngine>
#include <QWindow>
#include "CodeModel.h"
#include "FileIo.h"
#include "ClientModel.h"
#include "CodeEditorExtensionManager.h"
#include "Exceptions.h"
#include "QEther.h"
#include "QVariableDefinition.h"
#include "HttpServer.h"
#include "AppContext.h"
#include "SortFilterProxyModel.h"
using namespace dev;
using namespace dev::eth;
using namespace dev::mix;
const QString c_projectFileName = "project.mix";
AppContext::AppContext(QQmlApplicationEngine* _engine)
{
m_applicationEngine = _engine;
m_codeModel.reset(new CodeModel(this));
m_clientModel.reset(new ClientModel(this));
m_fileIo.reset(new FileIo());
connect(QApplication::clipboard(), &QClipboard::dataChanged, [this] { emit clipboardChanged();});
}
AppContext::~AppContext()
{
}
void AppContext::load()
{
m_applicationEngine->rootContext()->setContextProperty("appContext", this);
QFont f;
m_applicationEngine->rootContext()->setContextProperty("systemPointSize", f.pointSize());
qmlRegisterType<FileIo>("org.ethereum.qml", 1, 0, "FileIo");
m_applicationEngine->rootContext()->setContextProperty("codeModel", m_codeModel.get());
m_applicationEngine->rootContext()->setContextProperty("fileIo", m_fileIo.get());
qmlRegisterType<QEther>("org.ethereum.qml.QEther", 1, 0, "QEther");
qmlRegisterType<QBigInt>("org.ethereum.qml.QBigInt", 1, 0, "QBigInt");
qmlRegisterType<QVariableDeclaration>("org.ethereum.qml.QVariableDeclaration", 1, 0, "QVariableDeclaration");
qmlRegisterType<RecordLogEntry>("org.ethereum.qml.RecordLogEntry", 1, 0, "RecordLogEntry");
qmlRegisterType<SortFilterProxyModel>("org.ethereum.qml.SortFilterProxyModel", 1, 0, "SortFilterProxyModel");
qmlRegisterType<QSolidityType>("org.ethereum.qml.QSolidityType", 1, 0, "QSolidityType");
QQmlComponent projectModelComponent(m_applicationEngine, QUrl("qrc:/qml/ProjectModel.qml"));
QObject* projectModel = projectModelComponent.create();
if (projectModelComponent.isError())
{
QmlLoadException exception;
for (auto const& e : projectModelComponent.errors())
exception << QmlErrorInfo(e);
BOOST_THROW_EXCEPTION(exception);
}
m_applicationEngine->rootContext()->setContextProperty("projectModel", projectModel);
qmlRegisterType<CodeEditorExtensionManager>("CodeEditorExtensionManager", 1, 0, "CodeEditorExtensionManager");
qmlRegisterType<HttpServer>("HttpServer", 1, 0, "HttpServer");
m_applicationEngine->load(QUrl("qrc:/qml/main.qml"));
QWindow *window = qobject_cast<QWindow*>(m_applicationEngine->rootObjects().at(0));
window->setIcon(QIcon(":/res/mix_256x256x32.png"));
appLoaded();
}
QQmlApplicationEngine* AppContext::appEngine()
{
return m_applicationEngine;
}
void AppContext::displayMessageDialog(QString _title, QString _message)
{
// TODO : move to a UI dedicated layer.
QObject* dialogWin = m_applicationEngine->rootObjects().at(0)->findChild<QObject*>("alertMessageDialog", Qt::FindChildrenRecursively);
QObject* dialogWinComponent = m_applicationEngine->rootObjects().at(0)->findChild<QObject*>("alertMessageDialogContent", Qt::FindChildrenRecursively);
dialogWinComponent->setProperty("source", QString("qrc:/qml/BasicMessage.qml"));
dialogWin->setProperty("title", _title);
dialogWin->setProperty("width", "250");
dialogWin->setProperty("height", "100");
dialogWin->findChild<QObject*>("messageContent", Qt::FindChildrenRecursively)->setProperty("text", _message);
QMetaObject::invokeMethod(dialogWin, "open");
}
QString AppContext::clipboard() const
{
QClipboard *clipboard = QApplication::clipboard();
return clipboard->text();
}
void AppContext::toClipboard(QString _text)
{
QClipboard *clipboard = QApplication::clipboard();
clipboard->setText(_text);
}

88
mix/AppContext.h

@ -1,88 +0,0 @@
/*
This file is part of cpp-ethereum.
cpp-ethereum is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file AppContext.h
* @author Yann yann@ethdev.com
* @date 2014
* Provides access to the current QQmlApplicationEngine which is used to add QML file on the fly.
* In the future this class can be extended to add more variable related to the context of the application.
* For now AppContext provides reference to:
* - QQmlApplicationEngine
* - dev::WebThreeDirect (and dev::eth::Client)
* - KeyEventManager
*/
#pragma once
#include <memory>
#include <QUrl>
#include <QObject>
class QQmlApplicationEngine;
namespace dev
{
namespace mix
{
class CodeModel;
class ClientModel;
class FileIo;
/**
* @brief Provides access to application scope variable.
*/
class AppContext: public QObject
{
Q_OBJECT
Q_PROPERTY(QString clipboard READ clipboard WRITE toClipboard NOTIFY clipboardChanged)
public:
AppContext(QQmlApplicationEngine* _engine);
virtual ~AppContext();
/// Load the UI from qml files
void load();
/// Get the current QQMLApplicationEngine instance.
QQmlApplicationEngine* appEngine();
/// Get code model
CodeModel* codeModel() { return m_codeModel.get(); }
/// Get client model
ClientModel* clientModel() { return m_clientModel.get(); }
/// Display an alert message.
void displayMessageDialog(QString _title, QString _message);
/// Copy text to clipboard
Q_INVOKABLE void toClipboard(QString _text);
/// Get text from clipboard
QString clipboard() const;
signals:
/// Triggered once components have been loaded
void appLoaded();
void clipboardChanged();
private:
QQmlApplicationEngine* m_applicationEngine; //owned by app
std::unique_ptr<CodeModel> m_codeModel;
std::unique_ptr<ClientModel> m_clientModel;
std::unique_ptr<FileIo> m_fileIo;
public slots:
/// Delete the current instance when application quit.
void quitApplication() {}
};
}
}

26
mix/ClientModel.cpp

@ -21,6 +21,7 @@
// Make sure boost/asio.hpp is included before windows.h. // Make sure boost/asio.hpp is included before windows.h.
#include <boost/asio.hpp> #include <boost/asio.hpp>
#include "ClientModel.h"
#include <QtConcurrent/QtConcurrent> #include <QtConcurrent/QtConcurrent>
#include <QDebug> #include <QDebug>
#include <QQmlContext> #include <QQmlContext>
@ -29,7 +30,6 @@
#include <jsonrpccpp/server.h> #include <jsonrpccpp/server.h>
#include <libethcore/CommonJS.h> #include <libethcore/CommonJS.h>
#include <libethereum/Transaction.h> #include <libethereum/Transaction.h>
#include "AppContext.h"
#include "DebuggingStateWrapper.h" #include "DebuggingStateWrapper.h"
#include "Exceptions.h" #include "Exceptions.h"
#include "QContractDefinition.h" #include "QContractDefinition.h"
@ -39,7 +39,6 @@
#include "CodeModel.h" #include "CodeModel.h"
#include "QEther.h" #include "QEther.h"
#include "Web3Server.h" #include "Web3Server.h"
#include "ClientModel.h"
#include "MixClient.h" #include "MixClient.h"
using namespace dev; using namespace dev;
@ -67,8 +66,8 @@ private:
}; };
ClientModel::ClientModel(AppContext* _context): ClientModel::ClientModel():
m_context(_context), m_running(false), m_rpcConnector(new RpcConnector()) m_running(false), m_rpcConnector(new RpcConnector())
{ {
qRegisterMetaType<QBigInt*>("QBigInt*"); qRegisterMetaType<QBigInt*>("QBigInt*");
qRegisterMetaType<QVariableDefinition*>("QVariableDefinition*"); qRegisterMetaType<QVariableDefinition*>("QVariableDefinition*");
@ -87,7 +86,6 @@ ClientModel::ClientModel(AppContext* _context):
m_web3Server.reset(new Web3Server(*m_rpcConnector.get(), m_client->userAccounts(), m_client.get())); m_web3Server.reset(new Web3Server(*m_rpcConnector.get(), m_client->userAccounts(), m_client.get()));
connect(m_web3Server.get(), &Web3Server::newTransaction, this, &ClientModel::onNewTransaction, Qt::DirectConnection); connect(m_web3Server.get(), &Web3Server::newTransaction, this, &ClientModel::onNewTransaction, Qt::DirectConnection);
_context->appEngine()->rootContext()->setContextProperty("clientModel", this);
} }
ClientModel::~ClientModel() ClientModel::~ClientModel()
@ -184,8 +182,8 @@ void ClientModel::setupState(QVariantMap _state)
} }
else else
{ {
if (contractId.isEmpty() && m_context->codeModel()->hasContract()) //TODO: This is to support old project files, remove later if (contractId.isEmpty() && m_codeModel->hasContract()) //TODO: This is to support old project files, remove later
contractId = m_context->codeModel()->contracts().keys()[0]; contractId = m_codeModel->contracts().keys()[0];
TransactionSettings transactionSettings(contractId, functionId, value, gas, gasPrice, Secret(sender.toStdString())); TransactionSettings transactionSettings(contractId, functionId, value, gas, gasPrice, Secret(sender.toStdString()));
transactionSettings.parameterValues = transaction.value("parameters").toMap(); transactionSettings.parameterValues = transaction.value("parameters").toMap();
@ -220,7 +218,7 @@ void ClientModel::executeSequence(std::vector<TransactionSettings> const& _seque
if (!transaction.stdContractUrl.isEmpty()) if (!transaction.stdContractUrl.isEmpty())
{ {
//std contract //std contract
dev::bytes const& stdContractCode = m_context->codeModel()->getStdContractCode(transaction.contractId, transaction.stdContractUrl); dev::bytes const& stdContractCode = m_codeModel->getStdContractCode(transaction.contractId, transaction.stdContractUrl);
TransactionSettings stdTransaction = transaction; TransactionSettings stdTransaction = transaction;
stdTransaction.gas = 500000;// TODO: get this from std contracts library stdTransaction.gas = 500000;// TODO: get this from std contracts library
Address address = deployContract(stdContractCode, stdTransaction); Address address = deployContract(stdContractCode, stdTransaction);
@ -230,7 +228,7 @@ void ClientModel::executeSequence(std::vector<TransactionSettings> const& _seque
else else
{ {
//encode data //encode data
CompiledContract const& compilerRes = m_context->codeModel()->contract(transaction.contractId); CompiledContract const& compilerRes = m_codeModel->contract(transaction.contractId);
QFunctionDefinition const* f = nullptr; QFunctionDefinition const* f = nullptr;
bytes contractCode = compilerRes.bytes(); bytes contractCode = compilerRes.bytes();
std::shared_ptr<QContractDefinition> contractDef = compilerRes.sharedContract(); std::shared_ptr<QContractDefinition> contractDef = compilerRes.sharedContract();
@ -320,7 +318,7 @@ void ClientModel::showDebuggerForTransaction(ExecutionResult const& _t)
auto nameIter = m_contractNames.find(code.address); auto nameIter = m_contractNames.find(code.address);
if (nameIter != m_contractNames.end()) if (nameIter != m_contractNames.end())
{ {
CompiledContract const& compilerRes = m_context->codeModel()->contract(nameIter->second); CompiledContract const& compilerRes = m_codeModel->contract(nameIter->second);
eth::AssemblyItems assemblyItems = !_t.isConstructor() ? compilerRes.assemblyItems() : compilerRes.constructorAssemblyItems(); eth::AssemblyItems assemblyItems = !_t.isConstructor() ? compilerRes.assemblyItems() : compilerRes.constructorAssemblyItems();
codes.back()->setDocument(compilerRes.documentId()); codes.back()->setDocument(compilerRes.documentId());
codeItems.push_back(std::move(assemblyItems)); codeItems.push_back(std::move(assemblyItems));
@ -439,12 +437,6 @@ void ClientModel::debugRecord(unsigned _index)
showDebuggerForTransaction(e); showDebuggerForTransaction(e);
} }
void ClientModel::showDebugError(QString const& _error)
{
//TODO: change that to a signal
m_context->displayMessageDialog(tr("Debugger"), _error);
}
Address ClientModel::deployContract(bytes const& _code, TransactionSettings const& _ctrTransaction) Address ClientModel::deployContract(bytes const& _code, TransactionSettings const& _ctrTransaction)
{ {
Address newAddress = m_client->transact(_ctrTransaction.sender, _ctrTransaction.value, _code, _ctrTransaction.gas, _ctrTransaction.gasPrice); Address newAddress = m_client->transact(_ctrTransaction.sender, _ctrTransaction.value, _code, _ctrTransaction.gas, _ctrTransaction.gasPrice);
@ -527,7 +519,7 @@ void ClientModel::onNewTransaction()
auto contractAddressIter = m_contractNames.find(contractAddress); auto contractAddressIter = m_contractNames.find(contractAddress);
if (contractAddressIter != m_contractNames.end()) if (contractAddressIter != m_contractNames.end())
{ {
CompiledContract const& compilerRes = m_context->codeModel()->contract(contractAddressIter->second); CompiledContract const& compilerRes = m_codeModel->contract(contractAddressIter->second);
const QContractDefinition* def = compilerRes.contract(); const QContractDefinition* def = compilerRes.contract();
contract = def->name(); contract = def->name();
if (abi) if (abi)

10
mix/ClientModel.h

@ -34,13 +34,13 @@ namespace dev
namespace mix namespace mix
{ {
class AppContext;
class Web3Server; class Web3Server;
class RpcConnector; class RpcConnector;
class QEther; class QEther;
class QDebugData; class QDebugData;
class MixClient; class MixClient;
class QVariableDefinition; class QVariableDefinition;
class CodeModel;
struct SolidityType; struct SolidityType;
/// Backend transaction config class /// Backend transaction config class
@ -127,7 +127,7 @@ class ClientModel: public QObject
Q_OBJECT Q_OBJECT
public: public:
ClientModel(AppContext* _context); ClientModel();
~ClientModel(); ~ClientModel();
/// @returns true if currently executing contract code /// @returns true if currently executing contract code
Q_PROPERTY(bool running MEMBER m_running NOTIFY runStateChanged) Q_PROPERTY(bool running MEMBER m_running NOTIFY runStateChanged)
@ -143,6 +143,8 @@ public:
Q_INVOKABLE QString apiCall(QString const& _message); Q_INVOKABLE QString apiCall(QString const& _message);
/// Simulate mining. Creates a new block /// Simulate mining. Creates a new block
Q_INVOKABLE void mine(); Q_INVOKABLE void mine();
/// Get/set code model. Should be set from qml
Q_PROPERTY(CodeModel* codeModel MEMBER m_codeModel)
public slots: public slots:
/// Setup state, run transaction sequence, show debugger for the last transaction /// Setup state, run transaction sequence, show debugger for the last transaction
@ -157,8 +159,6 @@ public slots:
private slots: private slots:
/// Update UI with machine states result. Display a modal dialog. /// Update UI with machine states result. Display a modal dialog.
void showDebugger(); void showDebugger();
/// Update UI with transaction run error.
void showDebugError(QString const& _error);
signals: signals:
/// Transaction execution started /// Transaction execution started
@ -201,7 +201,6 @@ private:
void showDebuggerForTransaction(ExecutionResult const& _t); void showDebuggerForTransaction(ExecutionResult const& _t);
QVariant formatValue(SolidityType const& _type, dev::u256 const& _value); QVariant formatValue(SolidityType const& _type, dev::u256 const& _value);
AppContext* m_context;
std::atomic<bool> m_running; std::atomic<bool> m_running;
std::atomic<bool> m_mining; std::atomic<bool> m_mining;
std::unique_ptr<MixClient> m_client; std::unique_ptr<MixClient> m_client;
@ -211,6 +210,7 @@ private:
std::map<Address, QString> m_contractNames; std::map<Address, QString> m_contractNames;
std::map<QString, Address> m_stdContractAddresses; std::map<QString, Address> m_stdContractAddresses;
std::map<Address, QString> m_stdContractNames; std::map<Address, QString> m_stdContractNames;
CodeModel* m_codeModel = nullptr;
}; };
} }

39
mix/StatusPane.cpp → mix/Clipboard.cpp

@ -1,55 +1,40 @@
/* /*
This file is part of cpp-ethereum. This file is part of cpp-ethereum.
cpp-ethereum is free software: you can redistribute it and/or modify cpp-ethereum is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
cpp-ethereum is distributed in the hope that it will be useful, cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>. along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/ */
/** @file ConstantCompilationControl.cpp /** @file Clipboard.cpp
* @author Yann yann@ethdev.com * @author Yann yann@ethdev.com
* @date 2014 * @date 2015
* Ethereum IDE client.
*/ */
#include <QQmlContext> #include "Clipboard.h"
#include <QQuickItem>
#include <QtCore/QFileInfo>
#include <QApplication> #include <QApplication>
#include <QQmlApplicationEngine> #include <QClipboard>
#include <QtCore/QtCore>
#include <QDebug>
#include "StatusPane.h"
#include "QContractDefinition.h"
#include "AppContext.h"
#include "CodeModel.h"
using namespace dev::mix; using namespace dev::mix;
StatusPane::StatusPane(AppContext* _context): Extension(_context, ExtensionDisplayBehavior::HeaderView) Clipboard::Clipboard()
{ {
_context->appEngine()->rootContext()->setContextProperty("statusPane", this); connect(QApplication::clipboard(), &QClipboard::dataChanged, [this] { emit clipboardChanged();});
} }
QString StatusPane::contentUrl() const QString Clipboard::text() const
{ {
return QStringLiteral("qrc:/qml/StatusPane.qml"); QClipboard *clipboard = QApplication::clipboard();
return clipboard->text();
} }
QString StatusPane::title() const void Clipboard::setText(QString _text)
{ {
return QApplication::tr("compiler"); QClipboard *clipboard = QApplication::clipboard();
clipboard->setText(_text);
} }
void StatusPane::start() const
{
}

29
mix/StatusPane.h → mix/Clipboard.h

@ -1,25 +1,27 @@
/* /*
This file is part of cpp-ethereum. This file is part of cpp-ethereum.
cpp-ethereum is free software: you can redistribute it and/or modify cpp-ethereum is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
cpp-ethereum is distributed in the hope that it will be useful, cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>. along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/ */
/** @file ConstantCompilationControl.h /** @file Clipboard.h
* @author Yann yann@ethdev.com * @author Yann yann@ethdev.com
* @date 2014 * @date 2015
* Ethereum IDE client.
*/ */
#pragma once #pragma once
#include "Extension.h" #include <QObject>
namespace dev namespace dev
{ {
@ -27,20 +29,23 @@ namespace mix
{ {
/** /**
* @brief Extension which display assembly code of the contract being edited. * @brief Provides access to system clipboard
*/ */
class StatusPane: public Extension
class Clipboard: public QObject
{ {
Q_OBJECT Q_OBJECT
Q_PROPERTY(QString text READ text WRITE setText NOTIFY clipboardChanged)
public: public:
StatusPane(AppContext* _appContext); Clipboard();
~StatusPane() {} /// Copy text to clipboard
void start() const override; void setText(QString _text);
QString title() const override; /// Get text from clipboard
QString contentUrl() const override; QString text() const;
public slots: signals:
void clipboardChanged();
}; };
} }

88
mix/CodeEditorExtensionManager.cpp

@ -1,88 +0,0 @@
/*
This file is part of cpp-ethereum.
cpp-ethereum is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file CodeEditorExtensionManager.cpp
* @author Yann yann@ethdev.com
* @date 2014
* Ethereum IDE client.
*/
#include <QQuickItem>
#include <QGraphicsObject>
#include <QQmlEngine>
#include <QQmlComponent>
#include <QQuickTextDocument>
#include "StatusPane.h"
#include "AppContext.h"
#include "MixApplication.h"
#include "CodeModel.h"
#include "ClientModel.h"
#include "CodeHighlighter.h"
#include "CodeEditorExtensionManager.h"
using namespace dev::mix;
CodeEditorExtensionManager::CodeEditorExtensionManager():
m_appContext(static_cast<MixApplication*>(QApplication::instance())->context())
{
}
CodeEditorExtensionManager::~CodeEditorExtensionManager()
{
m_features.clear();
}
void CodeEditorExtensionManager::loadEditor(QQuickItem* _editor)
{
if (!_editor)
return;
}
void CodeEditorExtensionManager::initExtension(std::shared_ptr<Extension> _ext)
{
if (!_ext->contentUrl().isEmpty())
{
try
{
if (_ext->getDisplayBehavior() == ExtensionDisplayBehavior::RightView)
_ext->addTabOn(m_rightView);
if (_ext->getDisplayBehavior() == ExtensionDisplayBehavior::HeaderView)
_ext->addTabOn(m_headerView);
}
catch (...)
{
qDebug() << "Exception when adding tab into view.";
return;
}
}
_ext->start();
m_features.append(_ext);
}
void CodeEditorExtensionManager::applyCodeHighlight()
{
//TODO: reimplement
}
void CodeEditorExtensionManager::setRightView(QQuickItem* _rightView)
{
m_rightView = _rightView;
}
void CodeEditorExtensionManager::setHeaderView(QQuickItem* _headerView)
{
m_headerView = _headerView;
}

71
mix/CodeEditorExtensionManager.h

@ -1,71 +0,0 @@
/*
This file is part of cpp-ethereum.
cpp-ethereum is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file CodeEditorExtensionManager.h
* @author Yann yann@ethdev.com
* @date 2014
* Ethereum IDE client.
*/
#pragma once
#include <memory>
#include <QQuickItem>
#include <QTextDocument>
#include <QVector>
#include "StatusPane.h"
namespace dev
{
namespace mix
{
class AppContext;
/**
* @brief Init and provides connection between extensions.
*/
class CodeEditorExtensionManager: public QObject
{
Q_OBJECT
Q_PROPERTY(QQuickItem* headerView MEMBER m_headerView WRITE setHeaderView)
Q_PROPERTY(QQuickItem* rightView MEMBER m_rightView WRITE setRightView)
public:
CodeEditorExtensionManager();
~CodeEditorExtensionManager();
/// Initialize extension.
void initExtension(std::shared_ptr<Extension>);
/// Set current tab view
void setHeaderView(QQuickItem*);
/// Set current right tab view.
void setRightView(QQuickItem*);
private slots:
void applyCodeHighlight();
private:
QVector<std::shared_ptr<Extension>> m_features;
QQuickItem* m_headerView;
QQuickItem* m_rightView;
AppContext* m_appContext;
void loadEditor(QQuickItem* _editor);
};
}
}

3
mix/CodeModel.cpp

@ -129,8 +129,7 @@ QString CompiledContract::codeHex() const
return QString::fromStdString(toJS(m_bytes)); return QString::fromStdString(toJS(m_bytes));
} }
CodeModel::CodeModel(QObject* _parent): CodeModel::CodeModel():
QObject(_parent),
m_compiling(false), m_compiling(false),
m_codeHighlighterSettings(new CodeHighlighterSettings()), m_codeHighlighterSettings(new CodeHighlighterSettings()),
m_backgroundWorker(this), m_backgroundWorker(this),

2
mix/CodeModel.h

@ -125,7 +125,7 @@ class CodeModel: public QObject
Q_OBJECT Q_OBJECT
public: public:
CodeModel(QObject* _parent); CodeModel();
~CodeModel(); ~CodeModel();
Q_PROPERTY(QVariantMap contracts READ contracts NOTIFY codeChanged) Q_PROPERTY(QVariantMap contracts READ contracts NOTIFY codeChanged)

82
mix/Extension.cpp

@ -1,82 +0,0 @@
/*
This file is part of cpp-ethereum.
cpp-ethereum is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file Extension.cpp
* @author Yann yann@ethdev.com
* @date 2014
* Ethereum IDE client.
*/
#include <QMessageBox>
#include <QDebug>
#include <QQmlApplicationEngine>
#include <libevm/VM.h>
#include <libwebthree/WebThree.h>
#include "Extension.h"
#include "AppContext.h"
using namespace dev;
using namespace dev::mix;
Extension::Extension(AppContext* _context)
{
init(_context);
}
Extension::Extension(AppContext* _context, ExtensionDisplayBehavior _displayBehavior)
{
init(_context);
m_displayBehavior = _displayBehavior;
}
void Extension::init(AppContext* _context)
{
m_ctx = _context;
m_appEngine = m_ctx->appEngine();
}
void Extension::addTabOn(QObject* _view)
{
if (contentUrl() == "")
return;
QVariant returnValue;
QQmlComponent* component = new QQmlComponent(
m_appEngine,
QUrl(contentUrl()), _view);
QMetaObject::invokeMethod(_view, "addTab",
Q_RETURN_ARG(QVariant, returnValue),
Q_ARG(QVariant, this->title()),
Q_ARG(QVariant, QVariant::fromValue(component)));
m_view = qvariant_cast<QObject*>(returnValue);
}
void Extension::addContentOn(QObject* _view)
{
Q_UNUSED(_view);
if (m_displayBehavior == ExtensionDisplayBehavior::ModalDialog)
{
QQmlComponent* component = new QQmlComponent(m_appEngine, QUrl(contentUrl()), _view);
QObject* dialogWin = m_appEngine->rootObjects().at(0)->findChild<QObject*>("dialog", Qt::FindChildrenRecursively);
QObject* dialogWinComponent = m_appEngine->rootObjects().at(0)->findChild<QObject*>("modalDialogContent", Qt::FindChildrenRecursively);
dialogWinComponent->setProperty("sourceComponent", QVariant::fromValue(component));
dialogWin->setProperty("title", title());
QMetaObject::invokeMethod(dialogWin, "open");
}
//TODO add more view type.
}

75
mix/Extension.h

@ -1,75 +0,0 @@
/*
This file is part of cpp-ethereum.
cpp-ethereum is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file Extension.h
* @author Yann yann@ethdev.com
* @date 2014
* Ethereum IDE client.
*/
#pragma once
#include <QApplication>
#include <QQmlComponent>
class QQmlApplicationEngine;
namespace dev
{
namespace mix
{
class AppContext;
enum ExtensionDisplayBehavior
{
HeaderView,
RightView,
ModalDialog
};
class Extension: public QObject
{
Q_OBJECT
public:
Extension(AppContext* _context);
Extension(AppContext* _context, ExtensionDisplayBehavior _displayBehavior);
/// Return the QML url of the view to display.
virtual QString contentUrl() const { return ""; }
/// Return the title of this extension.
virtual QString title() const { return ""; }
/// Initialize extension.
virtual void start() const {}
/// Add the view define in contentUrl() in the _view QObject.
void addContentOn(QObject* _view);
/// Add the view define in contentUrl() in the _view QObject (_view has to be a tab).
void addTabOn(QObject* _view);
/// Modify the display behavior of this extension.
void setDisplayBehavior(ExtensionDisplayBehavior _displayBehavior) { m_displayBehavior = _displayBehavior; }
/// Get the display behavior of thi extension.
ExtensionDisplayBehavior getDisplayBehavior() { return m_displayBehavior; }
protected:
QObject* m_view;
ExtensionDisplayBehavior m_displayBehavior;
AppContext* m_ctx;
QQmlApplicationEngine* m_appEngine;
private:
void init(AppContext* _context);
};
}
}

42
mix/MixApplication.cpp

@ -19,22 +19,26 @@
* @date 2014 * @date 2014
*/ */
#include <QDebug> #include "MixApplication.h"
#include <QQmlApplicationEngine> #include <QQmlApplicationEngine>
#include <QUrl>
#include <QIcon>
#ifdef ETH_HAVE_WEBENGINE #ifdef ETH_HAVE_WEBENGINE
#include <QtWebEngine/QtWebEngine> #include <QtWebEngine/QtWebEngine>
#endif #endif
#include "CodeModel.h"
#include "MixApplication.h" #include "ClientModel.h"
#include "AppContext.h" #include "FileIo.h"
#include "QEther.h"
#include <QMenuBar> #include "QVariableDeclaration.h"
#include "SortFilterProxyModel.h"
#include "Clipboard.h"
#include "HttpServer.h"
using namespace dev::mix; using namespace dev::mix;
MixApplication::MixApplication(int& _argc, char* _argv[]): MixApplication::MixApplication(int& _argc, char* _argv[]):
QApplication(_argc, _argv), m_engine(new QQmlApplicationEngine()), m_appContext(new AppContext(m_engine.get())) QApplication(_argc, _argv), m_engine(new QQmlApplicationEngine())
{ {
setOrganizationName(tr("Ethereum")); setOrganizationName(tr("Ethereum"));
setOrganizationDomain(tr("ethereum.org")); setOrganizationDomain(tr("ethereum.org"));
@ -43,8 +47,26 @@ MixApplication::MixApplication(int& _argc, char* _argv[]):
#ifdef ETH_HAVE_WEBENGINE #ifdef ETH_HAVE_WEBENGINE
QtWebEngine::initialize(); QtWebEngine::initialize();
#endif #endif
QObject::connect(this, SIGNAL(lastWindowClosed()), context(), SLOT(quitApplication())); //use to kill ApplicationContext and other stuff
m_appContext->load(); QFont f;
m_engine->rootContext()->setContextProperty("systemPointSize", f.pointSize());
qmlRegisterType<CodeModel>("org.ethereum.qml.CodeModel", 1, 0, "CodeModel");
qmlRegisterType<ClientModel>("org.ethereum.qml.ClientModel", 1, 0, "ClientModel");
qmlRegisterType<FileIo>("org.ethereum.qml.FileIo", 1, 0, "FileIo");
qmlRegisterType<QEther>("org.ethereum.qml.QEther", 1, 0, "QEther");
qmlRegisterType<QBigInt>("org.ethereum.qml.QBigInt", 1, 0, "QBigInt");
qmlRegisterType<QVariableDeclaration>("org.ethereum.qml.QVariableDeclaration", 1, 0, "QVariableDeclaration");
qmlRegisterType<RecordLogEntry>("org.ethereum.qml.RecordLogEntry", 1, 0, "RecordLogEntry");
qmlRegisterType<SortFilterProxyModel>("org.ethereum.qml.SortFilterProxyModel", 1, 0, "SortFilterProxyModel");
qmlRegisterType<QSolidityType>("org.ethereum.qml.QSolidityType", 1, 0, "QSolidityType");
qmlRegisterType<Clipboard>("org.ethereum.qml.Clipboard", 1, 0, "Clipboard");
qmlRegisterType<HttpServer>("HttpServer", 1, 0, "HttpServer");
qRegisterMetaType<CodeModel*>("CodeModel*");
qRegisterMetaType<ClientModel*>("ClientModel*");
m_engine->load(QUrl("qrc:/qml/main.qml"));
QWindow *window = qobject_cast<QWindow*>(m_engine->rootObjects().at(0));
window->setIcon(QIcon(":/res/mix_256x256x32.png"));
} }
MixApplication::~MixApplication() MixApplication::~MixApplication()

4
mix/MixApplication.h

@ -33,8 +33,6 @@ namespace dev
namespace mix namespace mix
{ {
class AppContext;
class MixApplication: public QApplication class MixApplication: public QApplication
{ {
Q_OBJECT Q_OBJECT
@ -42,12 +40,10 @@ class MixApplication: public QApplication
public: public:
MixApplication(int& _argc, char* _argv[]); MixApplication(int& _argc, char* _argv[]);
virtual ~MixApplication(); virtual ~MixApplication();
AppContext* context() { return m_appContext.get(); }
QQmlApplicationEngine* engine() { return m_engine.get(); } QQmlApplicationEngine* engine() { return m_engine.get(); }
private: private:
std::unique_ptr<QQmlApplicationEngine> m_engine; std::unique_ptr<QQmlApplicationEngine> m_engine;
std::unique_ptr<AppContext> m_appContext;
}; };
} }

3
mix/QContractDefinition.cpp

@ -21,14 +21,13 @@
#include <QObject> #include <QObject>
#include "QContractDefinition.h"
#include <libsolidity/CompilerStack.h> #include <libsolidity/CompilerStack.h>
#include <libsolidity/AST.h> #include <libsolidity/AST.h>
#include <libsolidity/Scanner.h> #include <libsolidity/Scanner.h>
#include <libsolidity/Parser.h> #include <libsolidity/Parser.h>
#include <libsolidity/Scanner.h> #include <libsolidity/Scanner.h>
#include <libsolidity/NameAndTypeResolver.h> #include <libsolidity/NameAndTypeResolver.h>
#include "AppContext.h"
#include "QContractDefinition.h"
using namespace dev::solidity; using namespace dev::solidity;
using namespace dev::mix; using namespace dev::mix;

4
mix/qml/ContractLibrary.qml

@ -5,8 +5,8 @@ Item {
property alias model: contractListModel; property alias model: contractListModel;
Connections { Connections {
target: appContext target: mainApplication
Component.onCompleted: { onLoaded: {
//TODO: load a list, dependencies, ets, from external files //TODO: load a list, dependencies, ets, from external files
contractListModel.append({ contractListModel.append({

2
mix/qml/DebugInfoList.qml

@ -136,7 +136,7 @@ ColumnLayout {
var str = ""; var str = "";
for (var i = 0; i < listModel.length; i++) for (var i = 0; i < listModel.length; i++)
str += listModel[i] + "\n"; str += listModel[i] + "\n";
appContext.toClipboard(str); clipboard.text = str;
} }
} }

2
mix/qml/DeploymentDialog.qml

@ -223,7 +223,7 @@ Window {
enabled: deploymentDialog.packageBase64 !== "" enabled: deploymentDialog.packageBase64 !== ""
tooltip: qsTr("Copy Base64 conversion to ClipBoard") tooltip: qsTr("Copy Base64 conversion to ClipBoard")
onTriggered: { onTriggered: {
appContext.toClipboard(deploymentDialog.packageBase64); clipboard.text = deploymentDialog.packageBase64;
} }
} }

4
mix/qml/LogsPane.qml

@ -67,7 +67,7 @@ Rectangle
var log = logsModel.get(k); var log = logsModel.get(k);
content += log.type + "\t" + log.level + "\t" + log.date + "\t" + log.content + "\n"; content += log.type + "\t" + log.level + "\t" + log.date + "\t" + log.content + "\n";
} }
appContext.toClipboard(content); clipboard.text = content;
} }
} }
@ -207,7 +207,7 @@ Rectangle
{ {
var log = logsModel.get(logsTable.currentRow); var log = logsModel.get(logsTable.currentRow);
if (log) if (log)
appContext.toClipboard(log.type + "\t" + log.level + "\t" + log.date + "\t" + log.content); clipboard.text = (log.type + "\t" + log.level + "\t" + log.date + "\t" + log.content);
} }
model: SortFilterProxyModel { model: SortFilterProxyModel {

4
mix/qml/MainContent.qml

@ -2,7 +2,6 @@ import QtQuick 2.2
import QtQuick.Controls 1.1 import QtQuick.Controls 1.1
import QtQuick.Layouts 1.0 import QtQuick.Layouts 1.0
import QtQuick.Controls.Styles 1.1 import QtQuick.Controls.Styles 1.1
import CodeEditorExtensionManager 1.0
import Qt.labs.settings 1.0 import Qt.labs.settings 1.0
import org.ethereum.qml.QEther 1.0 import org.ethereum.qml.QEther 1.0
import "js/QEtherHelper.js" as QEtherHelper import "js/QEtherHelper.js" as QEtherHelper
@ -101,9 +100,6 @@ Rectangle {
rightView.displayCompilationErrorIfAny(); rightView.displayCompilationErrorIfAny();
} }
CodeEditorExtensionManager {
}
Settings { Settings {
id: mainSettings id: mainSettings
property alias codeWebOrientation: codeWebSplitter.orientation property alias codeWebOrientation: codeWebSplitter.orientation

5
mix/qml/ProjectModel.qml

@ -69,8 +69,8 @@ Item {
function formatAppUrl() { ProjectModelCode.formatAppUrl(url); } function formatAppUrl() { ProjectModelCode.formatAppUrl(url); }
Connections { Connections {
target: appContext target: mainApplication
onAppLoaded: { onLoaded: {
if (projectSettings.lastProjectPath && projectSettings.lastProjectPath !== "") if (projectSettings.lastProjectPath && projectSettings.lastProjectPath !== "")
projectModel.loadProject(projectSettings.lastProjectPath) projectModel.loadProject(projectSettings.lastProjectPath)
} }
@ -173,7 +173,6 @@ Item {
{ {
target: projectModel target: projectModel
onProjectClosed: { onProjectClosed: {
projectSettings.lastProjectPath = "";
projectPath = ""; projectPath = "";
} }
} }

2
mix/qml/TransactionLog.qml

@ -163,7 +163,7 @@ Item {
Keys.onPressed: { Keys.onPressed: {
if ((event.modifiers & Qt.ControlModifier) && event.key === Qt.Key_C && currentRow >=0 && currentRow < logTable.model.count) { if ((event.modifiers & Qt.ControlModifier) && event.key === Qt.Key_C && currentRow >=0 && currentRow < logTable.model.count) {
var item = logTable.model.get(currentRow); var item = logTable.model.get(currentRow);
appContext.toClipboard(item.returned); clipboard.text = item.returned;
} }
} }
} }

4
mix/qml/WebCodeEditor.qml

@ -34,7 +34,7 @@ Item {
function syncClipboard() { function syncClipboard() {
if (Qt.platform.os == "osx") { if (Qt.platform.os == "osx") {
var text = appContext.clipboard; var text = clipboard.text;
editorBrowser.runJavaScript("setClipboardBase64(\"" + Qt.btoa(text) + "\")"); editorBrowser.runJavaScript("setClipboardBase64(\"" + Qt.btoa(text) + "\")");
} }
} }
@ -59,7 +59,7 @@ Item {
} }
Connections { Connections {
target: appContext target: clipboard
onClipboardChanged: syncClipboard() onClipboardChanged: syncClipboard()
} }

11
mix/qml/WebPreview.qml

@ -58,16 +58,11 @@ Item {
function changePage() { function changePage() {
setPreviewUrl(urlInput.text); setPreviewUrl(urlInput.text);
/*if (pageCombo.currentIndex >= 0 && pageCombo.currentIndex < pageListModel.count) {
urlInput.text = httpServer.url + "/" + pageListModel.get(pageCombo.currentIndex).documentId;
setPreviewUrl(httpServer.url + "/" + pageListModel.get(pageCombo.currentIndex).documentId);
} else {
setPreviewUrl("");
}*/
} }
Connections { Connections {
target: appContext target: mainApplication
onAppLoaded: { onLoaded: {
//We need to load the container using file scheme so that web security would allow loading local files in iframe //We need to load the container using file scheme so that web security would allow loading local files in iframe
var containerPage = fileIo.readFile("qrc:///qml/html/WebContainer.html"); var containerPage = fileIo.readFile("qrc:///qml/html/WebContainer.html");
webView.loadHtml(containerPage, httpServer.url + "/WebContainer.html") webView.loadHtml(containerPage, httpServer.url + "/WebContainer.html")

37
mix/qml/main.qml

@ -7,9 +7,15 @@ import QtQuick.Window 2.1
import QtQuick.PrivateWidgets 1.1 import QtQuick.PrivateWidgets 1.1
import Qt.labs.settings 1.0 import Qt.labs.settings 1.0
import org.ethereum.qml.QEther 1.0 import org.ethereum.qml.QEther 1.0
import org.ethereum.qml.CodeModel 1.0
import org.ethereum.qml.ClientModel 1.0
import org.ethereum.qml.FileIo 1.0
import org.ethereum.qml.Clipboard 1.0
ApplicationWindow { ApplicationWindow {
id: mainApplication id: mainApplication
signal loaded;
visible: true visible: true
width: 1200 width: 1200
height: 800 height: 800
@ -17,8 +23,28 @@ ApplicationWindow {
minimumHeight: 300 minimumHeight: 300
title: qsTr("Mix") title: qsTr("Mix")
Connections CodeModel {
{ id: codeModel
}
ClientModel {
id: clientModel
codeModel: codeModel
}
ProjectModel {
id: projectModel
}
FileIo {
id: fileIo
}
Clipboard {
id: clipboard
}
Connections {
target: mainApplication target: mainApplication
onClosing: onClosing:
{ {
@ -27,8 +53,11 @@ ApplicationWindow {
} }
} }
function close() Component.onCompleted: {
{ loaded();
}
function close() {
projectModel.appIsClosing = true; projectModel.appIsClosing = true;
if (projectModel.projectPath !== "") if (projectModel.projectPath !== "")
projectModel.closeProject(function() { Qt.quit(); }) projectModel.closeProject(function() { Qt.quit(); })

Loading…
Cancel
Save