Browse Source

Merge branch 'mix' of https://github.com/arkpar/cpp-ethereum into

ide_m25

Conflicts:
	libdevcore/CommonJS.cpp
	libdevcore/CommonJS.h
	mix/AssemblyDebuggerCtrl.cpp
	mix/AssemblyDebuggerCtrl.h
	mix/AssemblyDebuggerModel.cpp
	mix/DebuggingStateWrapper.cpp
	mix/QBasicNodeDefinition.h
	mix/QFunctionDefinition.h
	mix/QVariableDeclaration.h
	mix/TransactionBuilder.cpp
	mix/TransactionBuilder.h
cl-refactor
yann300 10 years ago
parent
commit
c3d38d54f8
  1. 16
      alethzero/MainWin.cpp
  2. 8
      alethzero/MainWin.h
  3. 64
      libdevcore/CommonJS.cpp
  4. 3
      libdevcore/CommonJS.h
  5. 18
      libevmcore/Instruction.h
  6. 43
      mix/AppContext.cpp
  7. 20
      mix/AppContext.h
  8. 93
      mix/AssemblyDebuggerCtrl.cpp
  9. 23
      mix/AssemblyDebuggerCtrl.h
  10. 29
      mix/AssemblyDebuggerModel.cpp
  11. 6
      mix/AssemblyDebuggerModel.h
  12. 36
      mix/CodeEditorExtensionManager.cpp
  13. 4
      mix/CodeEditorExtensionManager.h
  14. 10
      mix/ConstantCompilationCtrl.cpp
  15. 7
      mix/ConstantCompilationCtrl.h
  16. 4
      mix/ConstantCompilationModel.cpp
  17. 5
      mix/ConstantCompilationModel.h
  18. 9
      mix/ContractCallDataEncoder.cpp
  19. 1
      mix/ContractCallDataEncoder.h
  20. 72
      mix/DebuggingStateWrapper.cpp
  21. 28
      mix/DebuggingStateWrapper.h
  22. 25
      mix/Extension.cpp
  23. 12
      mix/Extension.h
  24. 8
      mix/KeyEventManager.h
  25. 1
      mix/MixApplication.h
  26. 2
      mix/QBasicNodeDefinition.h
  27. 6
      mix/QContractDefinition.h
  28. 6
      mix/QFunctionDefinition.h
  29. 2
      mix/QVariableDeclaration.h
  30. 4
      mix/QVariableDefinition.h
  31. 63
      mix/TransactionBuilder.cpp
  32. 7
      mix/TransactionBuilder.h
  33. 217
      mix/TransactionListModel.cpp
  34. 165
      mix/TransactionListModel.h
  35. 56
      mix/TransactionListView.cpp
  36. 56
      mix/TransactionListView.h
  37. 8
      mix/main.cpp
  38. 2
      mix/qml.qrc
  39. 8
      mix/qml/BasicContent.qml
  40. 2
      mix/qml/BasicMessage.qml
  41. 2
      mix/qml/Debugger.qml
  42. 107
      mix/qml/MainContent.qml
  43. 187
      mix/qml/TransactionDialog.qml
  44. 89
      mix/qml/TransactionList.qml
  45. 10
      mix/qml/main.qml

16
alethzero/MainWin.cpp

@ -64,7 +64,7 @@ static void initUnits(QComboBox* _b)
_b->addItem(QString::fromStdString(units()[n].second), n); _b->addItem(QString::fromStdString(units()[n].second), n);
} }
static QString fromRaw(dev::h256 _n, unsigned* _inc = nullptr) QString Main::fromRaw(dev::h256 _n, unsigned* _inc)
{ {
if (_n) if (_n)
{ {
@ -148,7 +148,7 @@ Main::Main(QWidget *parent) :
statusBar()->addPermanentWidget(ui->peerCount); statusBar()->addPermanentWidget(ui->peerCount);
statusBar()->addPermanentWidget(ui->mineStatus); statusBar()->addPermanentWidget(ui->mineStatus);
statusBar()->addPermanentWidget(ui->blockCount); statusBar()->addPermanentWidget(ui->blockCount);
connect(ui->ourAccounts->model(), SIGNAL(rowsMoved(const QModelIndex &, int, int, const QModelIndex &, int)), SLOT(ourAccountsRowsMoved())); connect(ui->ourAccounts->model(), SIGNAL(rowsMoved(const QModelIndex &, int, int, const QModelIndex &, int)), SLOT(ourAccountsRowsMoved()));
m_webThree.reset(new WebThreeDirect(string("AlethZero/v") + dev::Version + "/" DEV_QUOTED(ETH_BUILD_TYPE) "/" DEV_QUOTED(ETH_BUILD_PLATFORM), getDataDir() + "/AlethZero", false, {"eth", "shh"})); m_webThree.reset(new WebThreeDirect(string("AlethZero/v") + dev::Version + "/" DEV_QUOTED(ETH_BUILD_TYPE) "/" DEV_QUOTED(ETH_BUILD_PLATFORM), getDataDir() + "/AlethZero", false, {"eth", "shh"}));
@ -173,17 +173,17 @@ Main::Main(QWidget *parent) :
connect(f, &QWebFrame::javaScriptWindowObjectCleared, QETH_INSTALL_JS_NAMESPACE(f, this, qweb)); connect(f, &QWebFrame::javaScriptWindowObjectCleared, QETH_INSTALL_JS_NAMESPACE(f, this, qweb));
connect(m_qweb, SIGNAL(onNewId(QString)), this, SLOT(addNewId(QString))); connect(m_qweb, SIGNAL(onNewId(QString)), this, SLOT(addNewId(QString)));
}); });
connect(ui->webView, &QWebView::loadFinished, [=]() connect(ui->webView, &QWebView::loadFinished, [=]()
{ {
m_qweb->poll(); m_qweb->poll();
}); });
connect(ui->webView, &QWebView::titleChanged, [=]() connect(ui->webView, &QWebView::titleChanged, [=]()
{ {
ui->tabWidget->setTabText(0, ui->webView->title()); ui->tabWidget->setTabText(0, ui->webView->title());
}); });
readSettings(); readSettings();
installWatches(); installWatches();
startTimer(100); startTimer(100);
@ -1067,7 +1067,7 @@ void Main::timerEvent(QTimerEvent*)
// 7/18, Alex: aggregating timers, prelude to better threading? // 7/18, Alex: aggregating timers, prelude to better threading?
// Runs much faster on slower dual-core processors // Runs much faster on slower dual-core processors
static int interval = 100; static int interval = 100;
// refresh mining every 200ms // refresh mining every 200ms
if (interval / 100 % 2 == 0) if (interval / 100 % 2 == 0)
refreshMining(); refreshMining();
@ -1093,7 +1093,7 @@ void Main::timerEvent(QTimerEvent*)
} }
else else
interval += 100; interval += 100;
if (m_qweb) if (m_qweb)
m_qweb->poll(); m_qweb->poll();
@ -1759,7 +1759,7 @@ void Main::on_net_triggered()
{ {
ui->port->setEnabled(!ui->net->isChecked()); ui->port->setEnabled(!ui->net->isChecked());
ui->clientName->setEnabled(!ui->net->isChecked()); ui->clientName->setEnabled(!ui->net->isChecked());
string n = string("AlethZero/v") + dev::Version; string n = string("AlethZero/v") + dev::Version;
if (ui->clientName->text().size()) if (ui->clientName->text().size())
n += "/" + ui->clientName->text().toStdString(); n += "/" + ui->clientName->text().toStdString();
n += "/" DEV_QUOTED(ETH_BUILD_TYPE) "/" DEV_QUOTED(ETH_BUILD_PLATFORM); n += "/" DEV_QUOTED(ETH_BUILD_TYPE) "/" DEV_QUOTED(ETH_BUILD_PLATFORM);

8
alethzero/MainWin.h

@ -69,7 +69,7 @@ struct WorldState
class Main : public QMainWindow class Main : public QMainWindow
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit Main(QWidget *parent = 0); explicit Main(QWidget *parent = 0);
~Main(); ~Main();
@ -79,7 +79,7 @@ public:
std::shared_ptr<dev::shh::WhisperHost> whisper() const { return m_webThree->whisper(); } std::shared_ptr<dev::shh::WhisperHost> whisper() const { return m_webThree->whisper(); }
QList<dev::KeyPair> owned() const { return m_myIdentities + m_myKeys; } QList<dev::KeyPair> owned() const { return m_myIdentities + m_myKeys; }
public slots: public slots:
void load(QString _file); void load(QString _file);
void note(QString _entry); void note(QString _entry);
@ -146,7 +146,7 @@ private slots:
void on_debugDumpState_triggered(int _add = 1); void on_debugDumpState_triggered(int _add = 1);
void on_debugDumpStatePre_triggered(); void on_debugDumpStatePre_triggered();
void on_refresh_triggered(); void on_refresh_triggered();
void on_usePrivate_triggered(); void on_usePrivate_triggered();
void on_enableOptimizer_triggered(); void on_enableOptimizer_triggered();
void on_turboMining_triggered(); void on_turboMining_triggered();
void on_go_triggered(); void on_go_triggered();
@ -259,4 +259,6 @@ private:
QWebThreeConnector* m_qwebConnector; QWebThreeConnector* m_qwebConnector;
std::unique_ptr<OurWebThreeStubServer> m_server; std::unique_ptr<OurWebThreeStubServer> m_server;
QWebThree* m_qweb = nullptr; QWebThree* m_qweb = nullptr;
static QString fromRaw(dev::h256 _n, unsigned* _inc = nullptr);
}; };

64
libdevcore/CommonJS.cpp

@ -61,4 +61,68 @@ std::string unpadded(std::string _b)
return _b; return _b;
} }
std::string prettyU256(u256 _n)
{
unsigned inc = 0;
std::string raw;
std::ostringstream s;
if (!(_n >> 64))
s << " " << (uint64_t)_n << " (0x" << (uint64_t)_n << ")";
else if (!~(_n >> 64))
s << " " << (int64_t)_n << " (0x" << (int64_t)_n << ")";
else if ((_n >> 160) == 0)
{
Address a = right160(_n);
std::string n = a.abridged();
if (n.empty())
s << "0x" << a;
else
s << n << "(0x" << a.abridged() << ")";
}
else if ((raw = fromRaw((h256)_n, &inc)).size())
return "\"" + raw + "\"" + (inc ? " + " + std::to_string(inc) : "");
else
s << "" << (h256)_n;
return s.str();
}
std::string fromRaw(h256 _n, unsigned* _inc)
{
if (_n)
{
std::string s((char const*)_n.data(), 32);
auto l = s.find_first_of('\0');
if (!l)
return "";
if (l != std::string::npos)
{
auto p = s.find_first_not_of('\0', l);
if (!(p == std::string::npos || (_inc && p == 31)))
return "";
if (_inc)
*_inc = (byte)s[31];
s.resize(l);
}
for (auto i: s)
if (i < 32)
return "";
return s;
}
return "";
}
Address fromString(std::string _sn)
{
if (_sn.size() > 32)
_sn.resize(32);
h256 n;
memcpy(n.data(), _sn.data(), _sn.size());
memset(n.data() + _sn.size(), 0, 32 - _sn.size());
if (_sn.size() == 40)
return Address(fromHex(_sn));
else
return Address();
}
} }

3
libdevcore/CommonJS.h

@ -50,6 +50,9 @@ bytes jsToBytes(std::string const& _s);
bytes padded(bytes _b, unsigned _l); bytes padded(bytes _b, unsigned _l);
bytes unpadded(bytes _s); bytes unpadded(bytes _s);
std::string unpadded(std::string _s); std::string unpadded(std::string _s);
std::string prettyU256(u256 _n);
std::string fromRaw(h256 _n, unsigned* _inc = nullptr);
Address fromString(std::string _a);
template <unsigned N> FixedHash<N> jsToFixed(std::string const& _s) template <unsigned N> FixedHash<N> jsToFixed(std::string const& _s)
{ {

18
libevmcore/Instruction.h

@ -173,6 +173,24 @@ enum class Instruction: uint8_t
SUICIDE = 0xff ///< halt execution and register account for later deletion SUICIDE = 0xff ///< halt execution and register account for later deletion
}; };
/// @returns the number of PUSH Instruction _inst
inline unsigned getPushNumber(Instruction _inst)
{
return (byte)_inst - unsigned(Instruction::PUSH1) + 1;
}
/// @returns the number of DUP Instruction _inst
inline unsigned getDupNumber(Instruction _inst)
{
return (byte)_inst - unsigned(Instruction::DUP1) + 1;
}
/// @returns the number of SWAP Instruction _inst
inline unsigned getSwapNumber(Instruction _inst)
{
return (byte)_inst - unsigned(Instruction::SWAP1) + 1;
}
/// @returns the PUSH<_number> instruction /// @returns the PUSH<_number> instruction
inline Instruction pushInstruction(unsigned _number) inline Instruction pushInstruction(unsigned _number)
{ {

43
mix/ApplicationCtx.cpp → mix/AppContext.cpp

@ -11,12 +11,12 @@
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 ApplicationCtx.cpp /** @file AppContext.cpp
* @author Yann yann@ethdev.com * @author Yann yann@ethdev.com
* @date 2014 * @date 2014
* Provides an access to the current QQmlApplicationEngine which is used to add QML file on the fly. * 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. * In the future this class can be extended to add more variable related to the context of the application.
* For now ApplicationCtx provides reference to: * For now AppContext provides reference to:
* - QQmlApplicationEngine * - QQmlApplicationEngine
* - dev::WebThreeDirect (and dev::eth::Client) * - dev::WebThreeDirect (and dev::eth::Client)
* - KeyEventManager * - KeyEventManager
@ -28,63 +28,56 @@
#include <QQmlApplicationEngine> #include <QQmlApplicationEngine>
#include "libdevcrypto/FileSystem.h" #include "libdevcrypto/FileSystem.h"
#include "KeyEventManager.h" #include "KeyEventManager.h"
#include "ApplicationCtx.h" #include "AppContext.h"
using namespace dev; using namespace dev;
using namespace dev::mix; using namespace dev::mix;
using namespace dev::eth; using namespace dev::eth;
ApplicationCtx* ApplicationCtx::Instance = nullptr; AppContext* AppContext::Instance = nullptr;
ApplicationCtx::ApplicationCtx(QQmlApplicationEngine* _engine) AppContext::AppContext(QQmlApplicationEngine* _engine)
{ {
m_applicationEngine = _engine; m_applicationEngine = std::unique_ptr<QQmlApplicationEngine>(_engine);
m_keyEventManager = std::unique_ptr<KeyEventManager>(new KeyEventManager()); m_keyEventManager = std::unique_ptr<KeyEventManager>(new KeyEventManager());
m_webThree = std::unique_ptr<dev::WebThreeDirect>(new WebThreeDirect(std::string("Mix/v") + dev::Version + "/" DEV_QUOTED(ETH_BUILD_TYPE) "/" DEV_QUOTED(ETH_BUILD_PLATFORM), getDataDir() + "/Mix", false, {"eth", "shh"})); m_webThree = std::unique_ptr<dev::WebThreeDirect>(new WebThreeDirect(std::string("Mix/v") + dev::Version + "/" DEV_QUOTED(ETH_BUILD_TYPE) "/" DEV_QUOTED(ETH_BUILD_PLATFORM), getDataDir() + "/Mix", false, {"eth", "shh"}));
} }
ApplicationCtx::~ApplicationCtx() QQmlApplicationEngine* AppContext::appEngine()
{ {
delete m_applicationEngine; return m_applicationEngine.get();
} }
QQmlApplicationEngine* ApplicationCtx::appEngine() dev::eth::Client* AppContext::getEthereumClient()
{ {
return m_applicationEngine; return m_webThree->ethereum();
} }
dev::eth::Client* ApplicationCtx::getEthereumClient() void AppContext::initKeyEventManager()
{
return m_webThree.get()->ethereum();
}
void ApplicationCtx::initKeyEventManager()
{ {
QObject* mainContent = m_applicationEngine->rootObjects().at(0)->findChild<QObject*>("mainContent", Qt::FindChildrenRecursively); QObject* mainContent = m_applicationEngine->rootObjects().at(0)->findChild<QObject*>("mainContent", Qt::FindChildrenRecursively);
if (mainContent) if (mainContent)
{
QObject::connect(mainContent, SIGNAL(keyPressed(QVariant)), m_keyEventManager.get(), SLOT(keyPressed(QVariant))); QObject::connect(mainContent, SIGNAL(keyPressed(QVariant)), m_keyEventManager.get(), SLOT(keyPressed(QVariant)));
}
else else
qDebug() << "Unable to find QObject of mainContent.qml. KeyEvent will not be handled!"; qDebug() << "Unable to find QObject of mainContent.qml. KeyEvent will not be handled!";
} }
KeyEventManager* ApplicationCtx::getKeyEventManager() KeyEventManager* AppContext::getKeyEventManager()
{ {
return m_keyEventManager.get(); return m_keyEventManager.get();
} }
void ApplicationCtx::setApplicationContext(QQmlApplicationEngine* _engine) void AppContext::setApplicationContext(QQmlApplicationEngine* _engine)
{ {
if (Instance == nullptr) if (Instance == nullptr)
Instance = new ApplicationCtx(_engine); Instance = new AppContext(_engine);
} }
void ApplicationCtx::displayMessageDialog(QString _title, QString _message) void AppContext::displayMessageDialog(QString _title, QString _message)
{ {
QQmlComponent component(m_applicationEngine, QUrl("qrc:/qml/BasicMessage.qml")); QQmlComponent component(m_applicationEngine.get(), QUrl("qrc:/qml/BasicMessage.qml"));
QObject* dialog = component.create(); QObject* dialog = component.create();
dialog->findChild<QObject*>("messageContent", Qt::FindChildrenRecursively)->setProperty("text", _message); dialog->findChild<QObject*>("messageContent", Qt::FindChildrenRecursively)->setProperty("text", _message);
QObject* dialogWin = ApplicationCtx::getInstance()->appEngine()->rootObjects().at(0)->findChild<QObject*>("messageDialog", Qt::FindChildrenRecursively); QObject* dialogWin = AppContext::getInstance()->appEngine()->rootObjects().at(0)->findChild<QObject*>("messageDialog", Qt::FindChildrenRecursively);
QMetaObject::invokeMethod(dialogWin, "close"); QMetaObject::invokeMethod(dialogWin, "close");
dialogWin->setProperty("contentItem", QVariant::fromValue(dialog)); dialogWin->setProperty("contentItem", QVariant::fromValue(dialog));
dialogWin->setProperty("title", _title); dialogWin->setProperty("title", _title);

20
mix/ApplicationCtx.h → mix/AppContext.h

@ -14,11 +14,12 @@
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 ApplicationCtx.h /** @file AppContext.h
* @author Yann yann@ethdev.com * @author Yann yann@ethdev.com
* Provides an access to the current QQmlApplicationEngine which is used to add QML file on the fly. * @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. * In the future this class can be extended to add more variable related to the context of the application.
* For now ApplicationCtx provides reference to: * For now AppContext provides reference to:
* - QQmlApplicationEngine * - QQmlApplicationEngine
* - dev::WebThreeDirect (and dev::eth::Client) * - dev::WebThreeDirect (and dev::eth::Client)
* - KeyEventManager * - KeyEventManager
@ -32,18 +33,17 @@
namespace dev namespace dev
{ {
namespace mix namespace mix
{ {
class ApplicationCtx: public QObject class AppContext: public QObject
{ {
Q_OBJECT Q_OBJECT
public: public:
ApplicationCtx(QQmlApplicationEngine* _engine); AppContext(QQmlApplicationEngine* _engine);
~ApplicationCtx(); ~AppContext() {}
static ApplicationCtx* getInstance() { return Instance; } static AppContext* getInstance() { return Instance; }
static void setApplicationContext(QQmlApplicationEngine* _engine); static void setApplicationContext(QQmlApplicationEngine* _engine);
QQmlApplicationEngine* appEngine(); QQmlApplicationEngine* appEngine();
dev::eth::Client* getEthereumClient(); dev::eth::Client* getEthereumClient();
@ -52,8 +52,8 @@ public:
void displayMessageDialog(QString _title, QString _message); void displayMessageDialog(QString _title, QString _message);
private: private:
static ApplicationCtx* Instance; static AppContext* Instance;
QQmlApplicationEngine* m_applicationEngine; std::unique_ptr<QQmlApplicationEngine> m_applicationEngine;
std::unique_ptr<dev::WebThreeDirect> m_webThree; std::unique_ptr<dev::WebThreeDirect> m_webThree;
std::unique_ptr<KeyEventManager> m_keyEventManager; std::unique_ptr<KeyEventManager> m_keyEventManager;

93
mix/AssemblyDebuggerCtrl.cpp

@ -17,6 +17,7 @@
* display opcode debugging. * display opcode debugging.
*/ */
#include <QtConcurrent/QtConcurrent>
#include <QDebug> #include <QDebug>
#include <QVariableDefinition.h> #include <QVariableDefinition.h>
#include <QQmlContext> #include <QQmlContext>
@ -27,8 +28,9 @@
#include "AssemblyDebuggerCtrl.h" #include "AssemblyDebuggerCtrl.h"
#include "TransactionBuilder.h" #include "TransactionBuilder.h"
#include "KeyEventManager.h" #include "KeyEventManager.h"
#include "ApplicationCtx.h" #include "AppContext.h"
#include "DebuggingStateWrapper.h" #include "DebuggingStateWrapper.h"
#include "TransactionListModel.h"
#include "QContractDefinition.h" #include "QContractDefinition.h"
#include "QVariableDeclaration.h" #include "QVariableDeclaration.h"
#include "ContractCallDataEncoder.h" #include "ContractCallDataEncoder.h"
@ -42,6 +44,11 @@ AssemblyDebuggerCtrl::AssemblyDebuggerCtrl(QTextDocument* _doc): Extension(Exten
qRegisterMetaType<QList<QVariableDefinition*>>("QList<QVariableDefinition*>"); qRegisterMetaType<QList<QVariableDefinition*>>("QList<QVariableDefinition*>");
qRegisterMetaType<QVariableDeclaration*>("QVariableDeclaration*"); qRegisterMetaType<QVariableDeclaration*>("QVariableDeclaration*");
qRegisterMetaType<AssemblyDebuggerData>();
qRegisterMetaType<DebuggingStatusResult>();
connect(this, SIGNAL(dataAvailable(bool, DebuggingStatusResult, QList<QObject*>, AssemblyDebuggerData)),
this, SLOT(updateGUI(bool, DebuggingStatusResult, QList<QObject*>, AssemblyDebuggerData)), Qt::QueuedConnection);
m_modelDebugger = std::unique_ptr<AssemblyDebuggerModel>(new AssemblyDebuggerModel); m_modelDebugger = std::unique_ptr<AssemblyDebuggerModel>(new AssemblyDebuggerModel);
m_compilation = std::unique_ptr<ConstantCompilationModel>(new ConstantCompilationModel); m_compilation = std::unique_ptr<ConstantCompilationModel>(new ConstantCompilationModel);
m_senderAddress = KeyPair::create(); //this address will be used as the sender address. m_senderAddress = KeyPair::create(); //this address will be used as the sender address.
@ -62,7 +69,7 @@ QString AssemblyDebuggerCtrl::title() const
void AssemblyDebuggerCtrl::start() const void AssemblyDebuggerCtrl::start() const
{ {
//start to listen on F5 //start to listen on F5
ApplicationCtx::getInstance()->getKeyEventManager()->registerEvent(this, SLOT(keyPressed(int))); m_ctx->getKeyEventManager()->registerEvent(this, SLOT(keyPressed(int)));
} }
void AssemblyDebuggerCtrl::keyPressed(int _key) void AssemblyDebuggerCtrl::keyPressed(int _key)
@ -71,43 +78,53 @@ void AssemblyDebuggerCtrl::keyPressed(int _key)
{ {
m_previousDebugResult = deployContract(); m_previousDebugResult = deployContract();
} }
else if(_key == Qt::Key_F4) /*else if(_key == Qt::Key_F4)
callContract(m_previousDebugResult.contractAddress); callContract(m_previousDebugResult.contractAddress);
else if(_key == Qt::Key_F3) else if(_key == Qt::Key_F3)
{ {
//Reset state; //Reset state;
m_modelDebugger.get()->resetState(); m_modelDebugger.get()->resetState();
} }*/
} }
void AssemblyDebuggerCtrl::callContract(Address contractAddress) void AssemblyDebuggerCtrl::callContract(dev::mix::TransactionSettings _tr)
{ {
CompilerResult compilerRes = m_compilation.get()->compile(m_doc->toPlainText()); CompilerResult compilerRes = m_compilation.get()->compile(m_doc->toPlainText());
if (!compilerRes.success) if (!compilerRes.success)
{ {
ApplicationCtx::getInstance()->displayMessageDialog("debugger","compilation failed"); AppContext::getInstance()->displayMessageDialog("debugger","compilation failed");
return; return;
} }
ContractCallDataEncoder c; ContractCallDataEncoder c;
std::shared_ptr<QContractDefinition> contractDef = QContractDefinition::Contract(m_doc->toPlainText()); std::shared_ptr<QContractDefinition> contractDef = QContractDefinition::Contract(m_doc->toPlainText());
QFunctionDefinition* fo = nullptr;
for (int i = 0; i < contractDef->functions().size(); i++) QFunctionDefinition* f = nullptr;
for (int k = 0; k < contractDef.get()->functions().size(); k++)
{ {
QFunctionDefinition* f = (QFunctionDefinition*)contractDef->functions().at(i); if (contractDef.get()->functions().at(k)->name() == _tr.functionId)
if (f->name() == "test2")
{ {
fo = f; f = (QFunctionDefinition*)contractDef->functions().at(k);
c.encode(i);
for (int k = 0; k < f->parameters().size(); k++)
{
c.encode((QVariableDeclaration*)f->parameters().at(k), QString("3"));
}
} }
} }
if (!f)
{
AppContext::getInstance()->displayMessageDialog("debugger","contract code changed. redeploy contract");
return;
}
c.encode(f->index());
for (int k = 0; k < f->parameters().size(); k++)
{
QVariableDeclaration* var = (QVariableDeclaration*)f->parameters().at(k);
c.encode(var, _tr.parameterValues[var->name()]);
}
Transaction tr = m_trBuilder.getDefaultBasicTransaction(contractAddress, c.encodedData(), m_senderAddress); DebuggingContent debuggingContent = m_modelDebugger->getContractCallDebugStates(m_previousDebugResult.contractAddress,
DebuggingContent debuggingContent = m_modelDebugger->getContractCallDebugStates(tr); c.encodedData(),
debuggingContent.returnParameters = c.decode(fo->returnParameters(), debuggingContent.returnValue); m_senderAddress,
_tr);
debuggingContent.returnParameters = c.decode(f->returnParameters(), debuggingContent.returnValue);
finalizeExecution(debuggingContent); finalizeExecution(debuggingContent);
} }
@ -116,14 +133,13 @@ DebuggingContent AssemblyDebuggerCtrl::deployContract()
CompilerResult compilerRes = m_compilation.get()->compile(m_doc->toPlainText()); CompilerResult compilerRes = m_compilation.get()->compile(m_doc->toPlainText());
if (!compilerRes.success) if (!compilerRes.success)
{ {
ApplicationCtx::getInstance()->displayMessageDialog("debugger","compilation failed"); AppContext::getInstance()->displayMessageDialog("debugger","compilation failed");
DebuggingContent res; DebuggingContent res;
res.contentAvailable = false; res.contentAvailable = false;
return res; return res;
} }
Transaction tr = m_trBuilder.getDefaultCreationTransaction(compilerRes.bytes, m_senderAddress); DebuggingContent debuggingContent = m_modelDebugger->getContractInitiationDebugStates(compilerRes.bytes, m_senderAddress);
DebuggingContent debuggingContent = m_modelDebugger->getContractInitiationDebugStates(tr);
finalizeExecution(debuggingContent); finalizeExecution(debuggingContent);
return debuggingContent; return debuggingContent;
} }
@ -132,17 +148,36 @@ void AssemblyDebuggerCtrl::finalizeExecution(DebuggingContent debuggingContent)
{ {
//we need to wrap states in a QObject before sending to QML. //we need to wrap states in a QObject before sending to QML.
QList<QObject*> wStates; QList<QObject*> wStates;
for(int i = 0; i < debuggingContent.states.size(); i++) for(int i = 0; i < debuggingContent.machineStates.size(); i++)
{ {
DebuggingStateWrapper* s = new DebuggingStateWrapper(debuggingContent.executionCode, debuggingContent.executionData.toBytes()); DebuggingStateWrapper* s = new DebuggingStateWrapper(debuggingContent.executionCode, debuggingContent.executionData.toBytes(), this);
s->setState(debuggingContent.states.at(i)); s->setState(debuggingContent.machineStates.at(i));
wStates.append(s); wStates.append(s);
} }
std::tuple<QList<QObject*>, QQMLMap*> code = DebuggingStateWrapper::getHumanReadableCode(debuggingContent.executionCode, this); std::tuple<QList<QObject*>, QQMLMap*> code = DebuggingStateWrapper::getHumanReadableCode(debuggingContent.executionCode, this);
ApplicationCtx::getInstance()->appEngine()->rootContext()->setContextProperty("debugStates", QVariant::fromValue(wStates)); AppContext::getInstance()->appEngine()->rootContext()->setContextProperty("debugStates", QVariant::fromValue(wStates));
ApplicationCtx::getInstance()->appEngine()->rootContext()->setContextProperty("humanReadableExecutionCode", QVariant::fromValue(std::get<0>(code))); AppContext::getInstance()->appEngine()->rootContext()->setContextProperty("humanReadableExecutionCode", QVariant::fromValue(std::get<0>(code)));
ApplicationCtx::getInstance()->appEngine()->rootContext()->setContextProperty("bytesCodeMapping", QVariant::fromValue(std::get<1>(code))); AppContext::getInstance()->appEngine()->rootContext()->setContextProperty("bytesCodeMapping", QVariant::fromValue(std::get<1>(code)));
ApplicationCtx::getInstance()->appEngine()->rootContext()->setContextProperty("contractCallReturnParameters", AppContext::getInstance()->appEngine()->rootContext()->setContextProperty("contractCallReturnParameters",
QVariant::fromValue(new QVariableDefinitionList(debuggingContent.returnParameters))); QVariant::fromValue(new QVariableDefinitionList(debuggingContent.returnParameters)));
this->addContentOn(this); this->addContentOn(this);
} }
void AssemblyDebuggerCtrl::updateGUI(bool success, DebuggingStatusResult reason, QList<QObject*> _wStates, AssemblyDebuggerData _code)
{
Q_UNUSED(reason);
if (success)
{
m_appEngine->rootContext()->setContextProperty("debugStates", QVariant::fromValue(_wStates));
m_appEngine->rootContext()->setContextProperty("humanReadableExecutionCode", QVariant::fromValue(std::get<0>(_code)));
m_appEngine->rootContext()->setContextProperty("bytesCodeMapping", QVariant::fromValue(std::get<1>(_code)));
this->addContentOn(this);
}
else
m_ctx->displayMessageDialog("debugger","compilation failed");
}
void AssemblyDebuggerCtrl::runTransaction(TransactionSettings _tr)
{
callContract(_tr);
}

23
mix/AssemblyDebuggerCtrl.h

@ -23,12 +23,23 @@
#include "QTextDocument" #include "QTextDocument"
#include "Extension.h" #include "Extension.h"
#include "ConstantCompilationModel.h" #include "ConstantCompilationModel.h"
#include "TransactionListModel.h"
#include "AssemblyDebuggerModel.h" #include "AssemblyDebuggerModel.h"
#include "TransactionBuilder.h" #include "TransactionBuilder.h"
#include "AppContext.h"
namespace dev using AssemblyDebuggerData = std::tuple<QList<QObject*>, dev::mix::QQMLMap*>;
enum DebuggingStatusResult
{ {
Ok,
Compilationfailed
};
Q_DECLARE_METATYPE(AssemblyDebuggerData)
Q_DECLARE_METATYPE(DebuggingStatusResult)
namespace dev
{
namespace mix namespace mix
{ {
@ -50,13 +61,19 @@ private:
TransactionBuilder m_trBuilder; TransactionBuilder m_trBuilder;
KeyPair m_senderAddress; KeyPair m_senderAddress;
DebuggingContent deployContract(); DebuggingContent deployContract();
void callContract(Address contractAddress); void callContract(dev::mix::TransactionSettings contractAddress);
void finalizeExecution(DebuggingContent content); void finalizeExecution(DebuggingContent content);
DebuggingContent m_previousDebugResult; DebuggingContent m_previousDebugResult;
public Q_SLOTS: public slots:
void keyPressed(int); void keyPressed(int);
void updateGUI(bool success, DebuggingStatusResult reason, QList<QObject*> _wStates = QList<QObject*>(), AssemblyDebuggerData _code = AssemblyDebuggerData());
void runTransaction(dev::mix::TransactionSettings _tr);
signals:
void dataAvailable(bool success, DebuggingStatusResult reason, QList<QObject*> _wStates = QList<QObject*>(), AssemblyDebuggerData _code = AssemblyDebuggerData());
}; };
} }

29
mix/AssemblyDebuggerModel.cpp

@ -22,9 +22,9 @@
#include "libethereum/ExtVM.h" #include "libethereum/ExtVM.h"
#include "libevm/VM.h" #include "libevm/VM.h"
#include "libdevcore/Common.h" #include "libdevcore/Common.h"
#include "libdevcore/CommonJS.h" #include "AppContext.h"
#include "ApplicationCtx.h"
#include "TransactionBuilder.h" #include "TransactionBuilder.h"
#include "TransactionListModel.h"
#include "AssemblyDebuggerModel.h" #include "AssemblyDebuggerModel.h"
#include "ConstantCompilationModel.h" #include "ConstantCompilationModel.h"
#include "DebuggingStateWrapper.h" #include "DebuggingStateWrapper.h"
@ -46,7 +46,7 @@ void AssemblyDebuggerModel::addBalance(KeyPair address, u256 amount)
DebuggingContent AssemblyDebuggerModel::executeTransaction() DebuggingContent AssemblyDebuggerModel::executeTransaction()
{ {
QList<DebuggingState> states; QList<DebuggingState> machineStates;
std::vector<DebuggingState const*> levels; std::vector<DebuggingState const*> levels;
bytes code; bytes code;
bytesConstRef data; bytesConstRef data;
@ -64,11 +64,11 @@ DebuggingContent AssemblyDebuggerModel::executeTransaction()
} }
if (levels.size() < ext.depth) if (levels.size() < ext.depth)
levels.push_back(&states.back()); levels.push_back(&machineStates.back());
else else
levels.resize(ext.depth); levels.resize(ext.depth);
states.append(DebuggingState({steps, ext.myAddress, vm.curPC(), inst, newMemSize, vm.gas(), machineStates.append(DebuggingState({steps, ext.myAddress, vm.curPC(), inst, newMemSize, vm.gas(),
vm.stack(), vm.memory(), gasCost, ext.state().storage(ext.myAddress), levels})); vm.stack(), vm.memory(), gasCost, ext.state().storage(ext.myAddress), levels}));
}; };
@ -78,7 +78,7 @@ DebuggingContent AssemblyDebuggerModel::executeTransaction()
DebuggingContent d; DebuggingContent d;
d.returnValue = m_currentExecution.get()->out().toVector(); d.returnValue = m_currentExecution.get()->out().toVector();
d.states = states; d.machineStates = machineStates;
d.executionCode = code; d.executionCode = code;
d.executionData = data; d.executionData = data;
d.contentAvailable = true; d.contentAvailable = true;
@ -86,8 +86,11 @@ DebuggingContent AssemblyDebuggerModel::executeTransaction()
return d; return d;
} }
DebuggingContent AssemblyDebuggerModel::getContractInitiationDebugStates(Transaction _tr) DebuggingContent AssemblyDebuggerModel::getContractInitiationDebugStates(bytes _code, KeyPair _sender)
{ {
TransactionBuilder trBuilder;
dev::eth::Transaction _tr = trBuilder.getDefaultCreationTransaction(_code, _sender,
m_executiveState.transactionsFrom(dev::toAddress(_sender.secret())));
bytes b = _tr.rlp(); bytes b = _tr.rlp();
dev::bytesConstRef bytesRef = &b; dev::bytesConstRef bytesRef = &b;
m_currentExecution.get()->forceSetup(bytesRef); m_currentExecution.get()->forceSetup(bytesRef);
@ -99,15 +102,21 @@ DebuggingContent AssemblyDebuggerModel::getContractInitiationDebugStates(Transac
return d; return d;
} }
DebuggingContent AssemblyDebuggerModel::getContractCallDebugStates(Transaction _tr) DebuggingContent AssemblyDebuggerModel::getContractCallDebugStates(Address _contract, bytes _data,
KeyPair _sender, dev::mix::TransactionSettings _tr)
{ {
TransactionBuilder trBuilder;
dev::eth::Transaction tr = trBuilder.getBasicTransaction(_tr.value,_tr.gasPrice,_tr.gas, _contract, _data,
m_executiveState.transactionsFrom(dev::toAddress(_sender.secret())), _sender.secret());
m_currentExecution = std::unique_ptr<Executive>(new Executive(m_executiveState)); m_currentExecution = std::unique_ptr<Executive>(new Executive(m_executiveState));
bytes b = _tr.rlp(); bytes b = tr.rlp();
dev::bytesConstRef bytesRef = &b; dev::bytesConstRef bytesRef = &b;
m_currentExecution.get()->forceSetup(bytesRef); m_currentExecution.get()->forceSetup(bytesRef);
DebuggingContent d = executeTransaction(); DebuggingContent d = executeTransaction();
d.contractAddress = _tr.receiveAddress(); d.contractAddress = tr.receiveAddress();
m_currentExecution.reset(); m_currentExecution.reset();
return d; return d;
} }

6
mix/AssemblyDebuggerModel.h

@ -26,10 +26,10 @@
#include "libethereum/Executive.h" #include "libethereum/Executive.h"
#include "libdevcore/Common.h" #include "libdevcore/Common.h"
#include "DebuggingStateWrapper.h" #include "DebuggingStateWrapper.h"
#include "TransactionListModel.h"
namespace dev namespace dev
{ {
namespace mix namespace mix
{ {
@ -37,8 +37,8 @@ class AssemblyDebuggerModel
{ {
public: public:
AssemblyDebuggerModel(); AssemblyDebuggerModel();
DebuggingContent getContractInitiationDebugStates(dev::eth::Transaction); DebuggingContent getContractInitiationDebugStates(bytes code, KeyPair _sender);
DebuggingContent getContractCallDebugStates(dev::eth::Transaction); DebuggingContent getContractCallDebugStates(Address _contract, bytes _data, KeyPair _sender, dev::mix::TransactionSettings _tr);
void addBalance(KeyPair address, u256 amount); void addBalance(KeyPair address, u256 amount);
void resetState(); void resetState();

36
mix/CodeEditorExtensionManager.cpp

@ -28,7 +28,8 @@
#include <libevm/VM.h> #include <libevm/VM.h>
#include "ConstantCompilationCtrl.h" #include "ConstantCompilationCtrl.h"
#include "AssemblyDebuggerCtrl.h" #include "AssemblyDebuggerCtrl.h"
#include "ApplicationCtx.h" #include "TransactionListView.h"
#include "AppContext.h"
#include "CodeEditorExtensionManager.h" #include "CodeEditorExtensionManager.h"
using namespace dev::mix; using namespace dev::mix;
@ -48,7 +49,17 @@ void CodeEditorExtensionManager::loadEditor(QQuickItem* _editor)
{ {
QQuickTextDocument* qqdoc = doc.value<QQuickTextDocument*>(); QQuickTextDocument* qqdoc = doc.value<QQuickTextDocument*>();
if (qqdoc) if (qqdoc)
{
m_doc = qqdoc->textDocument(); m_doc = qqdoc->textDocument();
auto args = QApplication::arguments();
if (args.length() > 1)
{
QString path = args[1];
QFile file(path);
if (file.exists() && file.open(QFile::ReadOnly))
m_doc->setPlainText(file.readAll());
}
}
} }
} }
catch (...) catch (...)
@ -60,19 +71,23 @@ void CodeEditorExtensionManager::loadEditor(QQuickItem* _editor)
void CodeEditorExtensionManager::initExtensions() void CodeEditorExtensionManager::initExtensions()
{ {
initExtension(std::make_shared<ConstantCompilationCtrl>(m_doc)); initExtension(std::make_shared<ConstantCompilationCtrl>(m_doc));
initExtension(std::make_shared<AssemblyDebuggerCtrl>(m_doc)); std::shared_ptr<AssemblyDebuggerCtrl> debug = std::make_shared<AssemblyDebuggerCtrl>(m_doc);
std::shared_ptr<TransactionListView> tr = std::make_shared<TransactionListView>(m_doc);
QObject::connect(tr->model(), &TransactionListModel::transactionRan, debug.get(), &AssemblyDebuggerCtrl::runTransaction);
initExtension(debug);
initExtension(tr);
} }
void CodeEditorExtensionManager::initExtension(std::shared_ptr<Extension> _ext) void CodeEditorExtensionManager::initExtension(std::shared_ptr<Extension> _ext)
{ {
if (!_ext.get()->contentUrl().isEmpty()) if (!_ext->contentUrl().isEmpty())
{ {
try try
{ {
if (_ext.get()->getDisplayBehavior() == ExtensionDisplayBehavior::Tab) if (_ext->getDisplayBehavior() == ExtensionDisplayBehavior::Tab)
{ _ext->addTabOn(m_tabView);
_ext.get()->addTabOn(m_tabView); else if (_ext->getDisplayBehavior() == ExtensionDisplayBehavior::RightTab)
} _ext->addTabOn(m_rightTabView);
} }
catch (...) catch (...)
{ {
@ -80,7 +95,7 @@ void CodeEditorExtensionManager::initExtension(std::shared_ptr<Extension> _ext)
return; return;
} }
} }
_ext.get()->start(); _ext->start();
m_features.append(_ext); m_features.append(_ext);
} }
@ -90,6 +105,11 @@ void CodeEditorExtensionManager::setEditor(QQuickItem* _editor)
this->initExtensions(); this->initExtensions();
} }
void CodeEditorExtensionManager::setRightTabView(QQuickItem* _tabView)
{
m_rightTabView = _tabView;
}
void CodeEditorExtensionManager::setTabView(QQuickItem* _tabView) void CodeEditorExtensionManager::setTabView(QQuickItem* _tabView)
{ {
m_tabView = _tabView; m_tabView = _tabView;

4
mix/CodeEditorExtensionManager.h

@ -30,7 +30,6 @@
namespace dev namespace dev
{ {
namespace mix namespace mix
{ {
@ -40,6 +39,7 @@ class CodeEditorExtensionManager: public QObject
Q_PROPERTY(QQuickItem* editor MEMBER m_editor WRITE setEditor) Q_PROPERTY(QQuickItem* editor MEMBER m_editor WRITE setEditor)
Q_PROPERTY(QQuickItem* tabView MEMBER m_tabView WRITE setTabView) Q_PROPERTY(QQuickItem* tabView MEMBER m_tabView WRITE setTabView)
Q_PROPERTY(QQuickItem* rightTabView MEMBER m_rightTabView WRITE setRightTabView)
public: public:
CodeEditorExtensionManager() {} CodeEditorExtensionManager() {}
@ -48,11 +48,13 @@ public:
void initExtension(std::shared_ptr<Extension>); void initExtension(std::shared_ptr<Extension>);
void setEditor(QQuickItem*); void setEditor(QQuickItem*);
void setTabView(QQuickItem*); void setTabView(QQuickItem*);
void setRightTabView(QQuickItem*);
private: private:
QQuickItem* m_editor; QQuickItem* m_editor;
QVector<std::shared_ptr<Extension>> m_features; QVector<std::shared_ptr<Extension>> m_features;
QQuickItem* m_tabView; QQuickItem* m_tabView;
QQuickItem* m_rightTabView;
QTextDocument* m_doc; QTextDocument* m_doc;
void loadEditor(QQuickItem*); void loadEditor(QQuickItem*);
}; };

10
mix/ConstantCompilationCtrl.cpp

@ -27,7 +27,6 @@
#include <QQmlApplicationEngine> #include <QQmlApplicationEngine>
#include <QtCore/QtCore> #include <QtCore/QtCore>
#include <QDebug> #include <QDebug>
#include "ApplicationCtx.h"
#include "ConstantCompilationCtrl.h" #include "ConstantCompilationCtrl.h"
#include "ConstantCompilationModel.h" #include "ConstantCompilationModel.h"
#include "QContractDefinition.h" #include "QContractDefinition.h"
@ -36,12 +35,7 @@ using namespace dev::mix;
ConstantCompilationCtrl::ConstantCompilationCtrl(QTextDocument* _doc): Extension(ExtensionDisplayBehavior::Tab) ConstantCompilationCtrl::ConstantCompilationCtrl(QTextDocument* _doc): Extension(ExtensionDisplayBehavior::Tab)
{ {
m_editor = _doc; m_editor = _doc;
m_compilationModel = new ConstantCompilationModel(); m_compilationModel = std::unique_ptr<ConstantCompilationModel>(new ConstantCompilationModel());
}
ConstantCompilationCtrl::~ConstantCompilationCtrl()
{
delete m_compilationModel;
} }
QString ConstantCompilationCtrl::contentUrl() const QString ConstantCompilationCtrl::contentUrl() const
@ -67,7 +61,7 @@ void ConstantCompilationCtrl::compile()
resetOutPut(); resetOutPut();
return; return;
} }
CompilerResult res = m_compilationModel->compile(m_editor->toPlainText().replace("\t", " ")); CompilerResult res = m_compilationModel->compile(m_editor->toPlainText().replace("\t", " "));
writeOutPut(res); writeOutPut(res);
} }

7
mix/ConstantCompilationCtrl.h

@ -25,7 +25,6 @@
namespace dev namespace dev
{ {
namespace mix namespace mix
{ {
@ -35,18 +34,18 @@ class ConstantCompilationCtrl: public Extension
public: public:
ConstantCompilationCtrl(QTextDocument*); ConstantCompilationCtrl(QTextDocument*);
~ConstantCompilationCtrl(); ~ConstantCompilationCtrl() {}
void start() const override; void start() const override;
QString title() const override; QString title() const override;
QString contentUrl() const override; QString contentUrl() const override;
private: private:
QTextDocument* m_editor; QTextDocument* m_editor;
ConstantCompilationModel* m_compilationModel; std::unique_ptr<ConstantCompilationModel> m_compilationModel;
void writeOutPut(CompilerResult const&); void writeOutPut(CompilerResult const&);
void resetOutPut(); void resetOutPut();
public Q_SLOTS: public slots:
void compile(); void compile();
}; };

4
mix/ConstantCompilationModel.cpp

@ -14,7 +14,7 @@
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 ApplicationCtx.h /** @file ConstantCompilationModel.h
* @author Yann yann@ethdev.com * @author Yann yann@ethdev.com
* @date 2014 * @date 2014
* Ethereum IDE client. * Ethereum IDE client.
@ -52,7 +52,7 @@ CompilerResult ConstantCompilationModel::compile(QString _code)
ostringstream error; ostringstream error;
solidity::SourceReferenceFormatter::printExceptionInformation(error, _exception, "Error", compiler.getScanner()); solidity::SourceReferenceFormatter::printExceptionInformation(error, _exception, "Error", compiler.getScanner());
res.success = false; res.success = false;
res.comment = QString::fromStdString(error.str()).toHtmlEscaped(); res.comment = QString::fromStdString(error.str());
res.hexCode = ""; res.hexCode = "";
} }
catch (...) catch (...)

5
mix/ConstantCompilationModel.h

@ -14,7 +14,7 @@
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 ApplicationCtx.h /** @file ConstantCompilationModel.h
* @author Yann yann@ethdev.com * @author Yann yann@ethdev.com
* @date 2014 * @date 2014
* Ethereum IDE client. * Ethereum IDE client.
@ -28,7 +28,6 @@
namespace dev namespace dev
{ {
namespace mix namespace mix
{ {
@ -46,7 +45,7 @@ class ConstantCompilationModel
public: public:
ConstantCompilationModel() {} ConstantCompilationModel() {}
~ConstantCompilationModel() {} ~ConstantCompilationModel() {}
CompilerResult compile(QString); CompilerResult compile(QString _code);
}; };
} }

9
mix/ContractCallDataEncoder.cpp

@ -58,6 +58,15 @@ void ContractCallDataEncoder::encode(QVariableDeclaration* _dec, QString _value)
m_encodedData.insert(m_encodedData.end(), data.begin(), data.end()); m_encodedData.insert(m_encodedData.end(), data.begin(), data.end());
} }
void ContractCallDataEncoder::encode(QVariableDeclaration* _dec, u256 _value)
{
int padding = this->padding(_dec->type());
std::ostringstream s;
s << _value;
bytes data = padded(jsToBytes(s.str()), padding);
m_encodedData.insert(m_encodedData.end(), data.begin(), data.end());
}
QList<QVariableDefinition*> ContractCallDataEncoder::decode(QList<QObject*> _returnParameters, bytes _value) QList<QVariableDefinition*> ContractCallDataEncoder::decode(QList<QObject*> _returnParameters, bytes _value)
{ {
QList<QVariableDefinition*> r; QList<QVariableDefinition*> r;

1
mix/ContractCallDataEncoder.h

@ -35,6 +35,7 @@ class ContractCallDataEncoder
public: public:
ContractCallDataEncoder(); ContractCallDataEncoder();
void encode(QVariableDeclaration* _dec, QString _value); void encode(QVariableDeclaration* _dec, QString _value);
void encode(QVariableDeclaration* _dec, u256 _value);
QList<QVariableDefinition*> decode(QList<QObject*> _dec, bytes _value); QList<QVariableDefinition*> decode(QList<QObject*> _dec, bytes _value);
void encode(QVariableDeclaration* _dec, bool _value); void encode(QVariableDeclaration* _dec, bool _value);
void encode(int _functionIndex); void encode(int _functionIndex);

72
mix/DebuggingStateWrapper.cpp

@ -14,7 +14,7 @@
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 DebuggingState.h /** @file DebuggingStateWrapper.cpp
* @author Yann yann@ethdev.com * @author Yann yann@ethdev.com
* @date 2014 * @date 2014
* Used to translate c++ type (u256, bytes, ...) into friendly value (to be used by QML). * Used to translate c++ type (u256, bytes, ...) into friendly value (to be used by QML).
@ -23,6 +23,8 @@
#include <QDebug> #include <QDebug>
#include <QString> #include <QString>
#include <QTextStream> #include <QTextStream>
#include "libevmcore/Instruction.h"
#include "libdevcore/CommonJS.h"
#include "libdevcrypto/Common.h" #include "libdevcrypto/Common.h"
#include "libevmcore/Instruction.h" #include "libevmcore/Instruction.h"
#include "libdevcore/Common.h" #include "libdevcore/Common.h"
@ -42,12 +44,12 @@ std::tuple<QList<QObject*>, QQMLMap*> DebuggingStateWrapper::getHumanReadableCod
{ {
QString s = QString::fromStdString(instructionInfo((Instruction)b).name); QString s = QString::fromStdString(instructionInfo((Instruction)b).name);
std::ostringstream out; std::ostringstream out;
out << std::setw(4) << std::setfill('0') << i; out << std::hex << std::setw(4) << std::setfill('0') << i;
codeMapping[i] = codeStr.size(); codeMapping[i] = codeStr.size();
int line = i; int line = i;
if (b >= (byte)Instruction::PUSH1 && b <= (byte)Instruction::PUSH32) if (b >= (byte)Instruction::PUSH1 && b <= (byte)Instruction::PUSH32)
{ {
unsigned bc = b - (byte)Instruction::PUSH1 + 1; unsigned bc = getPushNumber((Instruction)b);
s = "PUSH 0x" + QString::fromStdString(toHex(bytesConstRef(&_code[i + 1], bc))); s = "PUSH 0x" + QString::fromStdString(toHex(bytesConstRef(&_code[i + 1], bc)));
i += bc; i += bc;
} }
@ -68,7 +70,7 @@ QString DebuggingStateWrapper::debugStack()
{ {
QString stack; QString stack;
for (auto i: m_state.stack) for (auto i: m_state.stack)
stack.prepend(prettyU256(i) + "\n"); stack.prepend(QString::fromStdString(prettyU256(i)) + "\n");
return stack; return stack;
} }
@ -77,7 +79,7 @@ QString DebuggingStateWrapper::debugStorage()
{ {
std::stringstream s; std::stringstream s;
for (auto const& i: m_state.storage) for (auto const& i: m_state.storage)
s << "@" << prettyU256(i.first).toStdString() << "&nbsp;&nbsp;&nbsp;&nbsp;" << prettyU256(i.second).toStdString(); s << "@" << prettyU256(i.first) << "&nbsp;&nbsp;&nbsp;&nbsp;" << prettyU256(i.second);
return QString::fromStdString(s.str()); return QString::fromStdString(s.str());
} }
@ -89,7 +91,6 @@ QString DebuggingStateWrapper::debugMemory()
QString DebuggingStateWrapper::debugCallData() QString DebuggingStateWrapper::debugCallData()
{ {
return QString::fromStdString(memDump(m_data, 16, false)); return QString::fromStdString(memDump(m_data, 16, false));
} }
@ -102,7 +103,7 @@ QStringList DebuggingStateWrapper::levels()
std::ostringstream out; std::ostringstream out;
out << m_state.cur.abridged(); out << m_state.cur.abridged();
if (i) if (i)
out << " " << instructionInfo(m_state.inst).name << " @0x" << m_state.curPC; out << " " << instructionInfo(m_state.inst).name << " @0x" << std::hex << m_state.curPC;
levelsStr.append(QString::fromStdString(out.str())); levelsStr.append(QString::fromStdString(out.str()));
} }
return levelsStr; return levelsStr;
@ -111,7 +112,7 @@ QStringList DebuggingStateWrapper::levels()
QString DebuggingStateWrapper::headerInfo() QString DebuggingStateWrapper::headerInfo()
{ {
std::ostringstream ss; std::ostringstream ss;
ss << dec << " STEP: " << m_state.steps << " | PC: 0x" << hex << m_state.curPC << " : " << dev::eth::instructionInfo(m_state.inst).name << " | ADDMEM: " << dec << m_state.newMemSize << " words | COST: " << dec << m_state.gasCost << " | GAS: " << dec << m_state.gas; ss << std::dec << " STEP: " << m_state.steps << " | PC: 0x" << std::hex << m_state.curPC << " : " << dev::eth::instructionInfo(m_state.inst).name << " | ADDMEM: " << std::dec << m_state.newMemSize << " words | COST: " << std::dec << m_state.gasCost << " | GAS: " << std::dec << m_state.gas;
return QString::fromStdString(ss.str()); return QString::fromStdString(ss.str());
} }
@ -130,60 +131,9 @@ QString DebuggingStateWrapper::endOfDebug()
return "RETURN " + QString::fromStdString(dev::memDump(out, 16, false)); return "RETURN " + QString::fromStdString(dev::memDump(out, 16, false));
} }
else if (m_state.inst == Instruction::STOP) else if (m_state.inst == Instruction::STOP)
return "STOP"; return "STOP";
else if (m_state.inst == Instruction::SUICIDE && m_state.stack.size() >= 1) else if (m_state.inst == Instruction::SUICIDE && m_state.stack.size() >= 1)
return "SUICIDE 0x" + QString::fromStdString(toString(right160(m_state.stack.back()))); return "SUICIDE 0x" + QString::fromStdString(toString(right160(m_state.stack.back())));
else else
return "EXCEPTION"; return "EXCEPTION";
} }
QString DebuggingStateWrapper::prettyU256(u256 _n)
{
unsigned inc = 0;
QString raw;
std::ostringstream s;
if (!(_n >> 64))
s << " " << (uint64_t)_n << " (0x" << (uint64_t)_n << ")";
else if (!~(_n >> 64))
s << " " << (int64_t)_n << " (0x" << (int64_t)_n << ")";
else if ((_n >> 160) == 0)
{
Address a = right160(_n);
QString n = QString::fromStdString(a.abridged());//pretty(a);
if (n.isNull())
s << "0x" << a;
else
s << n.toHtmlEscaped().toStdString() << "(0x" << a.abridged() << ")";
}
else if ((raw = fromRaw((h256)_n, &inc)).size())
return "\"" + raw.toHtmlEscaped() + "\"" + (inc ? " + " + QString::number(inc) : "");
else
s << "" << (h256)_n;
return QString::fromStdString(s.str());
}
QString DebuggingStateWrapper::fromRaw(h256 _n, unsigned* _inc)
{
if (_n)
{
std::string s((char const*)_n.data(), 32);
auto l = s.find_first_of('\0');
if (!l)
return QString();
if (l != std::string::npos)
{
auto p = s.find_first_not_of('\0', l);
if (!(p == std::string::npos || (_inc && p == 31)))
return QString();
if (_inc)
*_inc = (byte)s[31];
s.resize(l);
}
for (auto i: s)
if (i < 32)
return QString();
return QString::fromStdString(s);
}
return QString();
}

28
mix/DebuggingStateWrapper.h

@ -14,7 +14,7 @@
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 DebuggingState.h /** @file DebuggingStateWrapper.h
* @author Yann yann@ethdev.com * @author Yann yann@ethdev.com
* @date 2014 * @date 2014
* Ethereum IDE client. * Ethereum IDE client.
@ -30,7 +30,6 @@
namespace dev namespace dev
{ {
namespace mix namespace mix
{ {
@ -51,7 +50,7 @@ struct DebuggingState
struct DebuggingContent struct DebuggingContent
{ {
QList<DebuggingState> states; QList<DebuggingState> machineStates;
bytes executionCode; bytes executionCode;
bytesConstRef executionData; bytesConstRef executionData;
Address contractAddress; Address contractAddress;
@ -61,7 +60,9 @@ struct DebuggingContent
QList<QVariableDefinition*> returnParameters; QList<QVariableDefinition*> returnParameters;
}; };
/* contains the line nb of the assembly code and the corresponding index in the code bytes array */ /**
* @brief Contains the line nb of the assembly code and the corresponding index in the code bytes array.
*/
class HumanReadableCode: public QObject class HumanReadableCode: public QObject
{ {
Q_OBJECT Q_OBJECT
@ -78,20 +79,25 @@ private:
int m_processIndex; int m_processIndex;
}; };
/* used to publish QMap type to QML */
/**
* @brief Publish QMap type to QML.
*/
class QQMLMap: public QObject class QQMLMap: public QObject
{ {
Q_OBJECT Q_OBJECT
public: public:
QQMLMap(QMap<int, int> _map, QObject* _parent): QObject(_parent), m_map(_map) { } QQMLMap(QMap<int, int> _map, QObject* _parent): QObject(_parent), m_map(_map) { }
Q_INVOKABLE int getValue(int _key) { return m_map.value(_key); } Q_INVOKABLE int getValue(int _key) { return m_map.value(_key); }
private: private:
QMap<int, int> m_map; QMap<int, int> m_map;
}; };
/* used to publish DebuggingState struct to QML */ /**
* @brief Wrap DebuggingState in QObject
*/
class DebuggingStateWrapper: public QObject class DebuggingStateWrapper: public QObject
{ {
Q_OBJECT Q_OBJECT
@ -108,7 +114,7 @@ class DebuggingStateWrapper: public QObject
Q_PROPERTY(QStringList levels READ levels) Q_PROPERTY(QStringList levels READ levels)
public: public:
DebuggingStateWrapper(bytes _code, bytes _data) : m_code(_code), m_data(_data) {} DebuggingStateWrapper(bytes _code, bytes _data, QObject* _parent): QObject(_parent), m_code(_code), m_data(_data) {}
int step() { return (int)m_state.steps; } int step() { return (int)m_state.steps; }
int curPC() { return (int)m_state.curPC; } int curPC() { return (int)m_state.curPC; }
int gasCost() { return (int)m_state.gasCost; } int gasCost() { return (int)m_state.gasCost; }
@ -122,14 +128,12 @@ public:
QStringList levels(); QStringList levels();
DebuggingState state() { return m_state; } DebuggingState state() { return m_state; }
void setState(DebuggingState _state) { m_state = _state; } void setState(DebuggingState _state) { m_state = _state; }
static std::tuple<QList<QObject*>, QQMLMap*> getHumanReadableCode(bytes const& code, QObject* _objUsedAsParent); static std::tuple<QList<QObject*>, QQMLMap*> getHumanReadableCode(bytes const& _code, QObject* _objUsedAsParent);
private: private:
DebuggingState m_state; DebuggingState m_state;
bytes m_code; bytes m_code;
bytes m_data; bytes m_data;
QString prettyU256(u256 _n);
QString fromRaw(h256 _n, unsigned* _inc = nullptr);
}; };
} }

25
mix/Extension.cpp

@ -21,10 +21,27 @@
#include <QDebug> #include <QDebug>
#include <libevm/VM.h> #include <libevm/VM.h>
#include "Extension.h" #include "Extension.h"
#include "ApplicationCtx.h" #include "AppContext.h"
using namespace dev; using namespace dev;
using namespace dev::mix; using namespace dev::mix;
Extension::Extension()
{
init();
}
Extension::Extension(ExtensionDisplayBehavior _displayBehavior)
{
init();
m_displayBehavior = _displayBehavior;
}
void Extension::init()
{
m_ctx = AppContext::getInstance();
m_appEngine = m_ctx->appEngine();
}
void Extension::addTabOn(QObject* _view) void Extension::addTabOn(QObject* _view)
{ {
if (contentUrl() == "") if (contentUrl() == "")
@ -32,7 +49,7 @@ void Extension::addTabOn(QObject* _view)
QVariant returnValue; QVariant returnValue;
QQmlComponent* component = new QQmlComponent( QQmlComponent* component = new QQmlComponent(
ApplicationCtx::getInstance()->appEngine(), AppContext::getInstance()->appEngine(),
QUrl(contentUrl()), _view); QUrl(contentUrl()), _view);
QMetaObject::invokeMethod(_view, "addTab", QMetaObject::invokeMethod(_view, "addTab",
@ -48,9 +65,9 @@ void Extension::addContentOn(QObject* _view)
Q_UNUSED(_view); Q_UNUSED(_view);
if (m_displayBehavior == ExtensionDisplayBehavior::ModalDialog) if (m_displayBehavior == ExtensionDisplayBehavior::ModalDialog)
{ {
QQmlComponent component(ApplicationCtx::getInstance()->appEngine(), QUrl(contentUrl())); QQmlComponent component(AppContext::getInstance()->appEngine(), QUrl(contentUrl()));
QObject* dialog = component.create(); QObject* dialog = component.create();
QObject* dialogWin = ApplicationCtx::getInstance()->appEngine()->rootObjects().at(0)->findChild<QObject*>("dialog", Qt::FindChildrenRecursively); QObject* dialogWin = AppContext::getInstance()->appEngine()->rootObjects().at(0)->findChild<QObject*>("dialog", Qt::FindChildrenRecursively);
QMetaObject::invokeMethod(dialogWin, "close"); QMetaObject::invokeMethod(dialogWin, "close");
dialogWin->setProperty("contentItem", QVariant::fromValue(dialog)); dialogWin->setProperty("contentItem", QVariant::fromValue(dialog));
dialogWin->setProperty("title", title()); dialogWin->setProperty("title", title());

12
mix/Extension.h

@ -21,16 +21,17 @@
#include <QApplication> #include <QApplication>
#include <QQmlComponent> #include <QQmlComponent>
#include "AppContext.h"
namespace dev namespace dev
{ {
namespace mix namespace mix
{ {
enum ExtensionDisplayBehavior enum ExtensionDisplayBehavior
{ {
Tab, Tab,
RightTab,
ModalDialog ModalDialog
}; };
@ -40,8 +41,8 @@ class Extension: public QObject
Q_OBJECT Q_OBJECT
public: public:
Extension() {} Extension();
Extension(ExtensionDisplayBehavior _displayBehavior) { m_displayBehavior = _displayBehavior; } Extension(ExtensionDisplayBehavior _displayBehavior);
virtual QString contentUrl() const { return ""; } virtual QString contentUrl() const { return ""; }
virtual QString title() const { return ""; } virtual QString title() const { return ""; }
virtual void start() const {} virtual void start() const {}
@ -53,6 +54,11 @@ public:
protected: protected:
QObject* m_view; QObject* m_view;
ExtensionDisplayBehavior m_displayBehavior; ExtensionDisplayBehavior m_displayBehavior;
AppContext* m_ctx;
QQmlApplicationEngine* m_appEngine;
private:
void init();
}; };
} }

8
mix/KeyEventManager.h

@ -30,13 +30,13 @@ class KeyEventManager: public QObject
public: public:
KeyEventManager() {} KeyEventManager() {}
void registerEvent(const QObject* receiver, const char* slot); void registerEvent(const QObject* _receiver, const char* _slot);
void unRegisterEvent(QObject* receiver); void unRegisterEvent(QObject* _receiver);
signals: signals:
void onKeyPressed(int); void onKeyPressed(int);
public Q_SLOTS: public slots:
void keyPressed(QVariant event); void keyPressed(QVariant _event);
}; };

1
mix/MixApplication.h

@ -27,7 +27,6 @@
namespace dev namespace dev
{ {
namespace mix namespace mix
{ {

2
mix/QBasicNodeDefinition.h

@ -39,7 +39,7 @@ public:
~QBasicNodeDefinition() { ~QBasicNodeDefinition() {
} }
QBasicNodeDefinition(std::shared_ptr<dev::solidity::Declaration> _d): QObject(), m_dec(_d) {} QBasicNodeDefinition(std::shared_ptr<dev::solidity::Declaration> _d): QObject(), m_dec(_d) {}
QString name() { return QString::fromStdString(m_dec.get()->getName()); } QString name() const { return QString::fromStdString(m_dec.get()->getName()); }
protected: protected:
std::shared_ptr<dev::solidity::Declaration> m_dec; std::shared_ptr<dev::solidity::Declaration> m_dec;

6
mix/QContractDefinition.h

@ -34,15 +34,15 @@ namespace mix
class QContractDefinition: public QBasicNodeDefinition class QContractDefinition: public QBasicNodeDefinition
{ {
Q_OBJECT Q_OBJECT
Q_PROPERTY(QList<QObject*> functions READ functions) Q_PROPERTY(QList<QFunctionDefinition*> functions READ functions)
public: public:
QContractDefinition(std::shared_ptr<dev::solidity::ContractDefinition> _contract); QContractDefinition(std::shared_ptr<dev::solidity::ContractDefinition> _contract);
QList<QObject*> functions() { return m_functions; } QList<QFunctionDefinition*> functions() const { return m_functions; }
static std::shared_ptr<QContractDefinition> Contract(QString _code); static std::shared_ptr<QContractDefinition> Contract(QString _code);
private: private:
QList<QObject*> m_functions; QList<QFunctionDefinition*> m_functions;
void initQFunctions(); void initQFunctions();
}; };

6
mix/QFunctionDefinition.h

@ -38,9 +38,9 @@ class QFunctionDefinition: public QBasicNodeDefinition
public: public:
QFunctionDefinition(std::shared_ptr<dev::solidity::FunctionDefinition> _f, int _index): QBasicNodeDefinition(_f), m_index(_index) { initQParameters(); } QFunctionDefinition(std::shared_ptr<dev::solidity::FunctionDefinition> _f, int _index): QBasicNodeDefinition(_f), m_index(_index) { initQParameters(); }
QList<QObject*> parameters() { return m_parameters; } QList<QObject*> parameters() const { return m_parameters; }
QList<QObject*> returnParameters() { return m_returnParameters; } QList<QObject*> returnParameters() const { return m_returnParameters; }
int index() { return m_index; } int index() const { return m_index; }
private: private:
QList<QObject*> m_parameters; QList<QObject*> m_parameters;

2
mix/QVariableDeclaration.h

@ -36,7 +36,7 @@ class QVariableDeclaration: public QBasicNodeDefinition
public: public:
QVariableDeclaration(std::shared_ptr<dev::solidity::VariableDeclaration> _v): QBasicNodeDefinition(_v), m_var(_v) {} QVariableDeclaration(std::shared_ptr<dev::solidity::VariableDeclaration> _v): QBasicNodeDefinition(_v), m_var(_v) {}
QString type() { return QString::fromStdString(m_var.get()->getType()->toString()); } QString type() const { return QString::fromStdString(m_var.get()->getType()->toString()); }
private: private:
std::shared_ptr<dev::solidity::VariableDeclaration> m_var; std::shared_ptr<dev::solidity::VariableDeclaration> m_var;

4
mix/QVariableDefinition.h

@ -38,8 +38,8 @@ class QVariableDefinition: public QObject
public: public:
QVariableDefinition(QVariableDeclaration* _def, QString _value): QObject(_def->parent()), m_value(_value), m_dec(_def) {} QVariableDefinition(QVariableDeclaration* _def, QString _value): QObject(_def->parent()), m_value(_value), m_dec(_def) {}
QVariableDeclaration* declaration() { return m_dec; } QVariableDeclaration* declaration() const { return m_dec; }
QString value() { return m_value; } QString value() const { return m_value; }
private: private:
QVariableDeclaration* m_dec; QVariableDeclaration* m_dec;

63
mix/TransactionBuilder.cpp

@ -18,8 +18,10 @@
*/ */
#include "libethereum/Executive.h" #include "libethereum/Executive.h"
#include "libdevcore/CommonJS.h"
#include "libdevcore/Common.h" #include "libdevcore/Common.h"
#include "ApplicationCtx.h" #include "AppContext.h"
#include "TransactionListModel.h"
#include "TransactionBuilder.h" #include "TransactionBuilder.h"
using namespace dev::mix; using namespace dev::mix;
using namespace dev::eth; using namespace dev::eth;
@ -37,72 +39,25 @@ Transaction TransactionBuilder::getBasicTransaction(u256 _value, u256 _gasPrice,
return Transaction(_value, _gasPrice, _gas, address, _data, _nonce, _secret); return Transaction(_value, _gasPrice, _gas, address, _data, _nonce, _secret);
} }
Transaction TransactionBuilder::getDefaultCreationTransaction(dev::bytes code, KeyPair sender) const Transaction TransactionBuilder::getDefaultCreationTransaction(dev::bytes _code, KeyPair _sender, u256 _nonce) const
{ {
u256 gasPrice = 10000000000000; u256 gasPrice = 10000000000000;
u256 gas = 1000000; u256 gas = 1000000;
u256 amount = 100; u256 amount = 100;
return getCreationTransaction(amount, gasPrice, gas, code, 0, sender.secret()); return getCreationTransaction(amount, gasPrice, gas, _code, _nonce, _sender.secret());
} }
Transaction TransactionBuilder::getDefaultBasicTransaction(Address contractAddress, dev::bytes data, KeyPair sender) const Transaction TransactionBuilder::getDefaultBasicTransaction(Address _contractAddress, dev::bytes _data, KeyPair _sender, u256 _nonce) const
{ {
u256 gasPrice = 10000000000000; u256 gasPrice = 10000000000000;
u256 gas = 1000000; u256 gas = 1000000;
u256 amount = 100; u256 amount = 100;
return getBasicTransaction(amount, gasPrice, gas, contractAddress, data, 0, sender.secret()); return getBasicTransaction(amount, gasPrice, gas, _contractAddress, _data, _nonce, _sender.secret());
} }
int TransactionBuilder::fromHex(char _i) const Transaction TransactionBuilder::getTransaction(Address _contractAddress, dev::bytes _data, KeyPair _sender, u256 _nonce, dev::mix::TransactionSettings _tr)
{ {
if (_i >= '0' && _i <= '9') return getBasicTransaction(_tr.value, _tr.gasPrice, _tr.gas, _contractAddress, _data, _nonce, _sender.secret());
return _i - '0';
if (_i >= 'a' && _i <= 'f')
return _i - 'a' + 10;
if (_i >= 'A' && _i <= 'F')
return _i - 'A' + 10;
BOOST_THROW_EXCEPTION(BadHexCharacter() << errinfo_invalidSymbol(_i));
} }
bytes TransactionBuilder::fromHex(std::string const& _s) const
{
unsigned s = (_s[0] == '0' && _s[1] == 'x') ? 2 : 0;
std::vector<uint8_t> ret;
ret.reserve((_s.size() - s + 1) / 2);
if (_s.size() % 2)
try
{
ret.push_back(fromHex(_s[s++]));
}
catch (...){ ret.push_back(0); cwarn << boost::current_exception_diagnostic_information(); }
for (unsigned i = s; i < _s.size(); i += 2)
try
{
ret.push_back((byte)(fromHex(_s[i]) * 16 + fromHex(_s[i + 1])));
}
catch (...){ ret.push_back(0); cwarn << boost::current_exception_diagnostic_information(); }
return ret;
}
Address TransactionBuilder::fromString(QString const& _a) const
{
Client* ethClient = ApplicationCtx::getInstance()->getEthereumClient();
std::string sn = _a.toStdString();
if (sn.size() > 32)
sn.resize(32);
h256 n;
memcpy(n.data(), sn.data(), sn.size());
memset(n.data() + sn.size(), 0, 32 - sn.size());
if (_a.size() == 40)
return Address(fromHex(_a.toStdString()));
else
{
//we try to resolve the recipient adress using nameReg contract state
const Address c_config = Address("661005d2720d855f1d9976f88bb10c1a3398c77f"); //NameReg contract
if (h160 nameReg = (u160)ethClient->stateAt(c_config, 0))
if (h256 a = ethClient->stateAt(nameReg, n))
return right160(a);
}
return Address(); // should maybe throws exception instead of returning blank address.
}

7
mix/TransactionBuilder.h

@ -22,10 +22,10 @@
#include <QString> #include <QString>
#include "libdevcore/Common.h" #include "libdevcore/Common.h"
#include "libethereum/Transaction.h" #include "libethereum/Transaction.h"
#include "TransactionListModel.h"
namespace dev namespace dev
{ {
namespace mix namespace mix
{ {
@ -37,8 +37,9 @@ public:
dev::Address address, bytes _data, dev::u256 _nonce, Secret _secret) const; dev::Address address, bytes _data, dev::u256 _nonce, Secret _secret) const;
dev::eth::Transaction getCreationTransaction(dev::u256 _value, dev::u256 _gasPrice, dev::u256 _gas, dev::eth::Transaction getCreationTransaction(dev::u256 _value, dev::u256 _gasPrice, dev::u256 _gas,
dev::bytes _data, dev::u256 _nonce, Secret _secret) const; dev::bytes _data, dev::u256 _nonce, Secret _secret) const;
dev::eth::Transaction getDefaultCreationTransaction(dev::bytes code, KeyPair sender) const; dev::eth::Transaction getDefaultCreationTransaction(dev::bytes code, KeyPair sender, dev::u256 _nonce) const;
dev::eth::Transaction getDefaultBasicTransaction(dev::Address contractAddress, dev::bytes data, KeyPair sender) const; dev::eth::Transaction getDefaultBasicTransaction(dev::Address contractAddress, dev::bytes data, KeyPair sender, dev::u256 _nonce) const;
dev::eth::Transaction getTransaction(Address _contractAddress, dev::bytes _data, KeyPair _sender, u256 _nonce, dev::mix::TransactionSettings _tr);
private: private:
bytes fromHex(std::string const& _s) const; bytes fromHex(std::string const& _s) const;

217
mix/TransactionListModel.cpp

@ -0,0 +1,217 @@
/*
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 TransactionListModel.cpp
* @author Arkadiy Paronyan arkadiy@ethdev.com
* @date 2014
* Ethereum IDE client.
*/
#include <QObject>
#include <QQmlEngine>
#include <QTextDocument>
#include <QAbstractListModel>
#include "TransactionListModel.h"
#include "QContractDefinition.h"
#include "QFunctionDefinition.h"
#include "QVariableDeclaration.h"
#include "libdevcore/CommonJS.h"
namespace dev
{
namespace mix
{
u256 fromQString(QString const& _s)
{
return dev::jsToU256(_s.toStdString());
}
QString toQString(u256 _value)
{
std::ostringstream s;
s << _value;
return QString::fromStdString(s.str());
}
TransactionListItem::TransactionListItem(int _index, TransactionSettings const& _t, QObject* _parent):
QObject(_parent), m_index(_index), m_title(_t.title), m_functionId(_t.functionId), m_value(toQString(_t.value)),
m_gas(toQString(_t.gas)), m_gasPrice(toQString(_t.gasPrice))
{}
TransactionListModel::TransactionListModel(QObject* _parent, QTextDocument* _document):
QAbstractListModel(_parent), m_document(_document)
{}
QHash<int, QByteArray> TransactionListModel::roleNames() const
{
QHash<int, QByteArray> roles;
roles[TitleRole] = "title";
roles[IdRole] = "transactionIndex";
return roles;
}
int TransactionListModel::rowCount(QModelIndex const& _parent) const
{
Q_UNUSED(_parent);
return m_transactions.size();
}
QVariant TransactionListModel::data(QModelIndex const& _index, int _role) const
{
if(_index.row() < 0 || _index.row() >= (int)m_transactions.size())
return QVariant();
auto const& transaction = m_transactions.at(_index.row());
switch(_role)
{
case TitleRole:
return QVariant(transaction.title);
case IdRole:
return QVariant(_index.row());
default:
return QVariant();
}
}
//TODO: get parameters from code model
QList<TransactionParameterItem*> buildParameters(QTextDocument* _document, TransactionSettings const& _transaction, QString const& _functionId)
{
QList<TransactionParameterItem*> params;
try
{
QString code = _document->toPlainText().replace("\n", ""); //TODO: is this required?
std::shared_ptr<QContractDefinition> contract = QContractDefinition::Contract(code);
auto functions = contract->functions();
for(auto qf : functions)
{
QFunctionDefinition const& f = (QFunctionDefinition const&) *qf;
if (f.name() != _functionId)
continue;
auto parameters = f.parameters();
for(auto qp : parameters)
{
QVariableDeclaration const& p = (QVariableDeclaration const&) *qp;
QString paramValue;
if (f.name() == _transaction.functionId)
{
auto paramValueIter = _transaction.parameterValues.find(p.name());
if (paramValueIter != _transaction.parameterValues.cend())
paramValue = toQString(paramValueIter->second);
}
TransactionParameterItem* item = new TransactionParameterItem(p.name(), p.type(), paramValue);
QQmlEngine::setObjectOwnership(item, QQmlEngine::JavaScriptOwnership);
params.append(item);
}
}
}
catch (boost::exception const&)
{
//TODO:
}
return params;
}
//TODO: get fnctions from code model
QList<QString> TransactionListModel::getFunctions()
{
QList<QString> functionNames;
try
{
QString code = m_document->toPlainText().replace("\n", ""); //TODO: is this required?
std::shared_ptr<QContractDefinition> contract(QContractDefinition::Contract(code));
auto functions = contract->functions();
for(auto qf : functions)
{
QFunctionDefinition const& f = (QFunctionDefinition const&) *qf;
functionNames.append(f.name());
}
}
catch (boost::exception const&)
{
}
return functionNames;
}
QVariantList TransactionListModel::getParameters(int _index, QString const& _functionId)
{
TransactionSettings const& transaction = (_index >=0 && _index < (int)m_transactions.size()) ? m_transactions[_index] : TransactionSettings();
auto plist = buildParameters(m_document, transaction, _functionId);
QVariantList vl;
for(QObject* p : plist)
vl.append(QVariant::fromValue(p));
return vl;
}
QObject* TransactionListModel::getItem(int _index)
{
TransactionSettings const& transaction = (_index >=0 && _index < (int)m_transactions.size()) ? m_transactions[_index] : TransactionSettings();
TransactionListItem* item = new TransactionListItem(_index, transaction, nullptr);
QQmlEngine::setObjectOwnership(item, QQmlEngine::JavaScriptOwnership);
return item;
}
void TransactionListModel::edit(QObject* _data)
{
//these properties come from TransactionDialog QML object
int index = _data->property("transactionIndex").toInt();
QString title = _data->property("transactionTitle").toString();
QString gas = _data->property("gas").toString();
QString gasPrice = _data->property("gasPrice").toString();
QString value = _data->property("transactionValue").toString();
QString functionId = _data->property("functionId").toString();
QAbstractListModel* paramsModel = qvariant_cast<QAbstractListModel*>(_data->property("transactionParams"));
TransactionSettings transaction(title, functionId, fromQString(value), fromQString(gas), fromQString(gasPrice));
int paramCount = paramsModel->rowCount(QModelIndex());
for(int p = 0; p < paramCount; ++p)
{
QString paramName = paramsModel->data(paramsModel->index(p, 0), Qt::DisplayRole).toString();
QString paramValue = paramsModel->data(paramsModel->index(p, 0), Qt::DisplayRole + 2).toString();
if (!paramValue.isEmpty() && !paramName.isEmpty())
transaction.parameterValues[paramName] = fromQString(paramValue);
}
if (index >= 0 && index < (int)m_transactions.size())
{
beginRemoveRows(QModelIndex(), index, index);
m_transactions.erase(m_transactions.begin() + index);
endRemoveRows();
}
else
index = rowCount(QModelIndex());
beginInsertRows(QModelIndex(), index, index);
m_transactions.push_back(transaction);
emit transactionAdded();
emit countChanged();
endInsertRows();
}
int TransactionListModel::getCount() const
{
return rowCount(QModelIndex());
}
void TransactionListModel::runTransaction(int _index)
{
TransactionSettings tr = m_transactions.at(_index);
emit transactionRan(tr);
}
}
}

165
mix/TransactionListModel.h

@ -0,0 +1,165 @@
/*
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 TransactionListView.h
* @author Arkadiy Paronyan arkadiy@ethdev.com
* @date 2014
* Ethereum IDE client.
*/
#pragma once
#include <QObject>
#include <QVariant>
#include <QAbstractListModel>
#include <QHash>
#include <QByteArray>
#include <libdevcore/Common.h>
class QTextDocument;
namespace dev
{
namespace mix
{
/// Backend transaction config class
struct TransactionSettings
{
TransactionSettings():
value(0), gas(10000), gasPrice(10) {}
TransactionSettings(QString const& _title, QString const& _functionId, u256 _value, u256 _gas, u256 _gasPrice):
title(_title), functionId(_functionId), value(_value), gas(_gas), gasPrice(_gasPrice) {}
/// User specified transaction title
QString title;
/// Contract function name
QString functionId;
/// Transaction value
u256 value;
/// Gas
u256 gas;
/// Gas price
u256 gasPrice;
/// Mapping from contract function parameter name to value
std::map<QString, u256> parameterValues;
};
/// QML transaction parameter class
class TransactionParameterItem: public QObject
{
Q_OBJECT
Q_PROPERTY(QString name READ name CONSTANT)
Q_PROPERTY(QString type READ type CONSTANT)
Q_PROPERTY(QString value READ value CONSTANT)
public:
TransactionParameterItem(QString const& _name, QString const& _type, QString const& _value):
m_name(_name), m_type(_type), m_value(_value) {}
/// Parameter name, set by contract definition
QString name() { return m_name; }
/// Parameter type, set by contract definition
QString type() { return m_type; }
/// Parameter value, set by user
QString value() { return m_value; }
private:
QString m_name;
QString m_type;
QString m_value;
};
class TransactionListItem: public QObject
{
Q_OBJECT
Q_PROPERTY(int index READ index CONSTANT)
Q_PROPERTY(QString title READ title CONSTANT)
Q_PROPERTY(QString functionId READ functionId CONSTANT)
Q_PROPERTY(QString gas READ gas CONSTANT)
Q_PROPERTY(QString gasPrice READ gasPrice CONSTANT)
Q_PROPERTY(QString value READ value CONSTANT)
public:
TransactionListItem(int _index, TransactionSettings const& _t, QObject* _parent);
/// User specified transaction title
QString title() { return m_title; }
/// Gas
QString gas() { return m_gas; }
/// Gas cost
QString gasPrice() { return m_gasPrice; }
/// Transaction value
QString value() { return m_value; }
/// Contract function name
QString functionId() { return m_functionId; }
/// Index of this transaction in the transactions list
int index() { return m_index; }
private:
int m_index;
QString m_title;
QString m_functionId;
QString m_value;
QString m_gas;
QString m_gasPrice;
};
/// QML model for a list of transactions
class TransactionListModel: public QAbstractListModel
{
Q_OBJECT
Q_PROPERTY(int count READ getCount() NOTIFY countChanged())
enum Roles
{
TitleRole = Qt::DisplayRole,
IdRole = Qt::UserRole + 1
};
public:
TransactionListModel(QObject* _parent, QTextDocument* _document);
~TransactionListModel() {}
QHash<int, QByteArray> roleNames() const override;
int rowCount(QModelIndex const& _parent) const override;
QVariant data(QModelIndex const& _index, int _role) const override;
int getCount() const;
/// Apply changes from transaction dialog. Argument is a dialog model as defined in TransactionDialog.qml
/// @todo Change that to transaction item
Q_INVOKABLE void edit(QObject* _data);
/// @returns transaction item for a give index
Q_INVOKABLE QObject* getItem(int _index);
/// @returns a list of functions for current contract
Q_INVOKABLE QList<QString> getFunctions();
/// @returns function parameters along with parameter values if set. @see TransactionParameterItem
Q_INVOKABLE QVariantList getParameters(int _id, QString const& _functionId);
Q_INVOKABLE void runTransaction(int _index);
signals:
void transactionAdded();
void countChanged();
void transactionRan(dev::mix::TransactionSettings);
private:
std::vector<TransactionSettings> m_transactions;
QTextDocument* m_document;
};
}
}

56
mix/TransactionListView.cpp

@ -0,0 +1,56 @@
/*
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 TransactionListView.cpp
* @author Arkadiy Paronyan arkadiy@ethdev.com
* @date 2014
* Ethereum IDE client.
*/
#include <QQuickItem>
#include <QApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include <QDebug>
#include "TransactionListView.h"
#include "TransactionListModel.h"
using namespace dev::mix;
TransactionListView::TransactionListView(QTextDocument* _doc): Extension(ExtensionDisplayBehavior::RightTab)
{
m_editor = _doc;
m_model.reset(new TransactionListModel(this, _doc));
m_appEngine->rootContext()->setContextProperty("transactionListModel", m_model.get());
}
TransactionListView::~TransactionListView()
{
//implementation is in cpp file so that all types deleted are complete
}
QString TransactionListView::contentUrl() const
{
return QStringLiteral("qrc:/qml/TransactionList.qml");
}
QString TransactionListView::title() const
{
return QApplication::tr("Transactions");
}
void TransactionListView::start() const
{
}

56
mix/TransactionListView.h

@ -0,0 +1,56 @@
/*
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 TransactionListView.h
* @author Arkadiy Paronyan arkadiy@ethdev.com
* @date 2014
* Ethereum IDE client.
*/
#pragma once
#include <QTextDocument>
#include "TransactionListView.h"
#include "Extension.h"
namespace dev
{
namespace mix
{
class TransactionListModel;
/// Transactions list control
/// @todo This should be moved into state as a sequence
class TransactionListView: public Extension
{
Q_OBJECT
public:
TransactionListView(QTextDocument*);
~TransactionListView();
void start() const override;
QString title() const override;
QString contentUrl() const override;
TransactionListModel* model() const { return m_model.get(); }
private:
QTextDocument* m_editor;
std::unique_ptr<TransactionListModel> m_model;
public slots:
};
}
}

8
mix/main.cpp

@ -24,7 +24,7 @@
#include <QQmlApplicationEngine> #include <QQmlApplicationEngine>
#include <QQuickItem> #include <QQuickItem>
#include "CodeEditorExtensionManager.h" #include "CodeEditorExtensionManager.h"
#include "ApplicationCtx.h" #include "AppContext.h"
#include "MixApplication.h" #include "MixApplication.h"
using namespace dev::mix; using namespace dev::mix;
@ -33,11 +33,11 @@ int main(int _argc, char *_argv[])
QApplication app(_argc, _argv); QApplication app(_argc, _argv);
qmlRegisterType<CodeEditorExtensionManager>("CodeEditorExtensionManager", 1, 0, "CodeEditorExtensionManager"); qmlRegisterType<CodeEditorExtensionManager>("CodeEditorExtensionManager", 1, 0, "CodeEditorExtensionManager");
QQmlApplicationEngine* engine = new QQmlApplicationEngine(); QQmlApplicationEngine* engine = new QQmlApplicationEngine();
ApplicationCtx::setApplicationContext(engine); AppContext::setApplicationContext(engine);
QObject::connect(&app, SIGNAL(lastWindowClosed()), ApplicationCtx::getInstance(), SLOT(quitApplication())); //use to kill ApplicationContext and other stuff QObject::connect(&app, SIGNAL(lastWindowClosed()), AppContext::getInstance(), SLOT(quitApplication())); //use to kill ApplicationContext and other stuff
engine->load(QUrl(QStringLiteral("qrc:/qml/main.qml"))); engine->load(QUrl(QStringLiteral("qrc:/qml/main.qml")));
ApplicationCtx::getInstance()->initKeyEventManager(); //has to be called after the loading of the main view. AppContext::getInstance()->initKeyEventManager(); //has to be called after the loading of the main view.
return app.exec(); return app.exec();
} }

2
mix/qml.qrc

@ -7,5 +7,7 @@
<file>qml/Debugger.qml</file> <file>qml/Debugger.qml</file>
<file>qml/js/Debugger.js</file> <file>qml/js/Debugger.js</file>
<file>qml/BasicMessage.qml</file> <file>qml/BasicMessage.qml</file>
<file>qml/TransactionDialog.qml</file>
<file>qml/TransactionList.qml</file>
</qresource> </qresource>
</RCC> </RCC>

8
mix/qml/BasicContent.qml

@ -7,13 +7,13 @@ Rectangle {
height: parent.height height: parent.height
color: "lightgray" color: "lightgray"
Text { Text {
font.pointSize: 7 font.pointSize: 9
anchors.left: parent.left anchors.left: parent.left
anchors.top: parent.top anchors.top: parent.top
anchors.topMargin: 3 anchors.topMargin: 3
anchors.leftMargin: 3 anchors.leftMargin: 3
height: 9 height: 9
font.family: "Sego UI light" font.family: "Monospace"
objectName: "status" objectName: "status"
id: status id: status
} }
@ -23,8 +23,8 @@ Rectangle {
anchors.leftMargin: 10 anchors.leftMargin: 10
anchors.top: status.bottom anchors.top: status.bottom
anchors.topMargin: 3 anchors.topMargin: 3
font.pointSize: 7 font.pointSize: 9
font.family: "Sego UI light" font.family: "Monospace"
height: parent.height * 0.8 height: parent.height * 0.8
width: parent.width - 20 width: parent.width - 20
wrapMode: Text.Wrap wrapMode: Text.Wrap

2
mix/qml/BasicMessage.qml

@ -1,4 +1,4 @@
import QtQuick 2.3 import QtQuick 2.2
import QtQuick.Controls.Styles 1.2 import QtQuick.Controls.Styles 1.2
import QtQuick.Controls 1.2 import QtQuick.Controls 1.2
import QtQuick.Dialogs 1.2 import QtQuick.Dialogs 1.2

2
mix/qml/Debugger.qml

@ -1,4 +1,4 @@
import QtQuick 2.3 import QtQuick 2.2
import QtQuick.Controls.Styles 1.2 import QtQuick.Controls.Styles 1.2
import QtQuick.Controls 1.2 import QtQuick.Controls 1.2
import QtQuick.Dialogs 1.2 import QtQuick.Dialogs 1.2

107
mix/qml/MainContent.qml

@ -1,4 +1,4 @@
import QtQuick 2.3 import QtQuick 2.2
import QtQuick.Controls 1.2 import QtQuick.Controls 1.2
import QtQuick.Layouts 1.0 import QtQuick.Layouts 1.0
import QtQuick.Controls.Styles 1.2 import QtQuick.Controls.Styles 1.2
@ -16,47 +16,66 @@ Rectangle {
anchors.fill: parent anchors.fill: parent
height: parent.height height: parent.height
width: parent.width; width: parent.width;
id:root id:root
SplitView { SplitView {
anchors.fill: parent orientation: Qt.Horizontal
orientation: Qt.Vertical anchors.fill: parent
Rectangle { SplitView {
anchors.top: parent.top //anchors.fill: parent
id: contentView width: parent.width * 0.8
width: parent.width orientation: Qt.Vertical
height: parent.height * 0.7 Rectangle {
TextArea { anchors.top: parent.top
id: codeEditor id: contentView
height: parent.height width: parent.width
font.family: "Verdana" height: parent.height * 0.7
font.pointSize: 9 TextArea {
width: parent.width id: codeEditor
anchors.centerIn: parent height: parent.height
tabChangesFocus: false font.family: "Monospace"
Keys.onPressed: { font.pointSize: 12
if (event.key === Qt.Key_Tab) { width: parent.width
codeEditor.insert(codeEditor.cursorPosition, "\t"); anchors.centerIn: parent
event.accepted = true; tabChangesFocus: false
} Keys.onPressed: {
} if (event.key === Qt.Key_Tab) {
} codeEditor.insert(codeEditor.cursorPosition, "\t");
} event.accepted = true;
Rectangle { }
anchors.bottom: parent.bottom }
id: contextualView }
width: parent.width }
Layout.minimumHeight: 20 Rectangle {
height: parent.height * 0.3 anchors.bottom: parent.bottom
TabView { id: contextualView
id: contextualTabs width: parent.width
antialiasing: true Layout.minimumHeight: 20
anchors.fill: parent height: parent.height * 0.3
style: TabStyle {} TabView {
} id: contextualTabs
} antialiasing: true
CodeEditorExtensionManager { anchors.fill: parent
tabView: contextualTabs style: TabStyle {}
editor: codeEditor }
} }
} }
Rectangle {
anchors.right: parent.right
id: rightPaneView
width: parent.width * 0.2
height: parent.height
Layout.minimumWidth: 20
TabView {
id: rightPaneTabs
antialiasing: true
anchors.fill: parent
//style: TabStyle {}
}
}
CodeEditorExtensionManager {
tabView: contextualTabs
rightTabView: rightPaneTabs
editor: codeEditor
}
}
} }

187
mix/qml/TransactionDialog.qml

@ -0,0 +1,187 @@
import QtQuick 2.3
import QtQuick.Controls 1.2
import QtQuick.Dialogs 1.2
import QtQuick.Layouts 1.1
import QtQuick.Window 2.0
Dialog {
modality: Qt.WindowModal
standardButtons: StandardButton.Ok | StandardButton.Cancel
width:640
height:480
property alias focus : titleField.focus
property alias transactionTitle : titleField.text
property int transactionIndex
property alias transactionParams : paramsModel;
property alias gas : gasField.text;
property alias gasPrice : gasPriceField.text;
property alias transactionValue : valueField.text;
property alias functionId : functionComboBox.currentText;
property var model;
function reset(index, m) {
model = m;
var item = model.getItem(index);
transactionIndex = index;
transactionTitle = item.title;
gas = item.gas;
gasPrice = item.gasPrice;
transactionValue = item.value;
var functionId = item.functionId;
functionsModel.clear();
var functionIndex = -1;
var functions = model.getFunctions();
for (var f = 0; f < functions.length; f++) {
functionsModel.append({ text: functions[f] });
if (functions[f] === item.functionId)
functionIndex = f;
}
functionComboBox.currentIndex = functionIndex;
}
function loadParameters() {
if (!paramsModel)
return;
paramsModel.clear();
if (functionComboBox.currentIndex >= 0 && functionComboBox.currentIndex < functionsModel.count) {
var parameters = model.getParameters(transactionIndex, functionsModel.get(functionComboBox.currentIndex).text);
for (var p = 0; p < parameters.length; p++) {
paramsModel.append({ name: parameters[p].name, type: parameters[p].type, value: parameters[p].value });
}
}
}
GridLayout {
columns: 2
anchors.fill: parent
anchors.margins: 10
rowSpacing: 10
columnSpacing: 10
Label {
text: qsTr("Title")
}
TextField {
id: titleField
focus: true
Layout.fillWidth: true
}
Label {
text: qsTr("Function")
}
ComboBox {
id: functionComboBox
Layout.fillWidth: true
currentIndex: -1
textRole: "text"
editable: false
model: ListModel {
id: functionsModel
}
onCurrentIndexChanged: {
loadParameters();
}
}
Label {
text: qsTr("Value")
}
TextField {
id: valueField
Layout.fillWidth: true
}
Label {
text: qsTr("Gas")
}
TextField {
id: gasField
Layout.fillWidth: true
}
Label {
text: qsTr("Gas price")
}
TextField {
id: gasPriceField
Layout.fillWidth: true
}
Label {
text: qsTr("Parameters")
}
TableView {
model: paramsModel
Layout.fillWidth: true
TableViewColumn {
role: "name"
title: "Name"
width: 120
}
TableViewColumn {
role: "type"
title: "Type"
width: 120
}
TableViewColumn {
role: "value"
title: "Value"
width: 120
}
itemDelegate: {
return editableDelegate;
}
}
}
ListModel {
id: paramsModel
}
Component {
id: editableDelegate
Item {
Text {
width: parent.width
anchors.margins: 4
anchors.left: parent.left
anchors.verticalCenter: parent.verticalCenter
elide: styleData.elideMode
text: styleData.value !== undefined ? styleData.value : ""
color: styleData.textColor
visible: !styleData.selected
}
Loader {
id: loaderEditor
anchors.fill: parent
anchors.margins: 4
Connections {
target: loaderEditor.item
onTextChanged: {
paramsModel.setProperty(styleData.row, styleData.role, loaderEditor.item.text);
}
}
sourceComponent: (styleData.selected /*&& styleData.role === "value"*/) ? editor : null
Component {
id: editor
TextInput {
id: textinput
color: styleData.textColor
text: styleData.value
MouseArea {
id: mouseArea
anchors.fill: parent
hoverEnabled: true
onClicked: textinput.forceActiveFocus()
}
}
}
}
}
}
}

89
mix/qml/TransactionList.qml

@ -0,0 +1,89 @@
import QtQuick 2.2
import QtQuick.Controls.Styles 1.2
import QtQuick.Controls 1.2
import QtQuick.Dialogs 1.2
import QtQuick.Layouts 1.1
Rectangle {
color: "transparent"
id: transactionListContainer
focus: true
anchors.topMargin: 10
anchors.left: parent.left
height: parent.height
width: parent.width
ListView {
anchors.top: parent.top
height: parent.height
width: parent.width
id: transactionList
model: transactionListModel
delegate: renderDelegate
}
Button {
anchors.bottom: parent.bottom
text: qsTr("Add")
onClicked:
{
// Set next id here to work around Qt bug
// https://bugreports.qt-project.org/browse/QTBUG-41327
// Second call to signal handle would just edit the item that was just created, no harm done
transactionDialog.reset(transactionListModel.count, transactionListModel);
transactionDialog.open();
transactionDialog.focus = true;
}
}
TransactionDialog {
id: transactionDialog
onAccepted: {
transactionListModel.edit(transactionDialog);
}
}
Component {
id: renderDelegate
Item {
id: wrapperItem
height: 20
width: parent.width
RowLayout
{
anchors.fill: parent
Text {
//anchors.fill: parent
Layout.fillWidth: true
Layout.fillHeight: true
text: title
font.pointSize: 12
verticalAlignment: Text.AlignBottom
}
ToolButton {
text: qsTr("Edit");
Layout.fillHeight: true
onClicked: {
transactionDialog.reset(index, transactionListModel);
transactionDialog.open();
transactionDialog.focus = true;
}
}
ToolButton {
text: qsTr("Delete");
Layout.fillHeight: true
onClicked: {
}
}
ToolButton {
text: qsTr("Run");
Layout.fillHeight: true
onClicked: {
transactionListModel.runTransaction(index);
}
}
}
}
}
}

10
mix/qml/main.qml

@ -9,8 +9,6 @@ import CodeEditorExtensionManager 1.0
ApplicationWindow { ApplicationWindow {
id: mainApplication id: mainApplication
visible: true visible: true
x: Screen.width / 2 - width / 2
y: Screen.height / 2 - height / 2
width: 1200 width: 1200
height: 600 height: 600
minimumWidth: 400 minimumWidth: 400
@ -26,13 +24,15 @@ ApplicationWindow {
} }
} }
} }
Component.onCompleted: {
setX(Screen.width / 2 - width / 2);
setY(Screen.height / 2 - height / 2);
}
MainContent { MainContent {
} }
Dialog { Dialog {
x: mainApplication.x + (mainApplication.width - width) / 2
y: mainApplication.y + (mainApplication.height - height) / 2
objectName: "dialog" objectName: "dialog"
id: dialog id: dialog
height: 400 height: 400
@ -44,8 +44,6 @@ ApplicationWindow {
} }
Dialog { Dialog {
x: mainApplication.x + (mainApplication.width - width) / 2
y: mainApplication.y + (mainApplication.height - height) / 2
objectName: "messageDialog" objectName: "messageDialog"
id: messageDialog id: messageDialog
height: 150 height: 150

Loading…
Cancel
Save