Browse Source

Merge pull request #757 from yann300/ide_m25_uidesign

Ide m25 uidesign
cl-refactor
Gav Wood 10 years ago
parent
commit
9706694747
  1. 20
      libdevcore/CommonIO.cpp
  2. 3
      libdevcore/CommonIO.h
  3. 7
      mix/AssemblyDebuggerControl.cpp
  4. 6
      mix/AssemblyDebuggerControl.h
  5. 2
      mix/ClientModel.cpp
  6. 21
      mix/CodeEditorExtensionManager.cpp
  7. 14
      mix/CodeEditorExtensionManager.h
  8. 24
      mix/CodeModel.cpp
  9. 24
      mix/CodeModel.h
  10. 94
      mix/ConstantCompilationControl.cpp
  11. 118
      mix/DebuggingStateWrapper.cpp
  12. 30
      mix/DebuggingStateWrapper.h
  13. 4
      mix/Extension.h
  14. 24
      mix/StateListView.cpp
  15. 66
      mix/StatusPane.cpp
  16. 13
      mix/StatusPane.h
  17. 21
      mix/qml.qrc
  18. 35
      mix/qml/DebugBasicInfo.qml
  19. 83
      mix/qml/DebugInfoList.qml
  20. 689
      mix/qml/Debugger.qml
  21. 71
      mix/qml/ItemDelegateDataDump.qml
  22. 196
      mix/qml/MainContent.qml
  23. 7
      mix/qml/StateList.qml
  24. 116
      mix/qml/StatusPane.qml
  25. 39
      mix/qml/StepActionImage.qml
  26. BIN
      mix/qml/img/bugiconactive.png
  27. BIN
      mix/qml/img/bugiconinactive.png
  28. BIN
      mix/qml/img/closedtriangleindicator.png
  29. BIN
      mix/qml/img/jumpintoback.png
  30. BIN
      mix/qml/img/jumpintobackdisabled.png
  31. BIN
      mix/qml/img/jumpintoforward.png
  32. BIN
      mix/qml/img/jumpintoforwarddisabled.png
  33. BIN
      mix/qml/img/jumpoutback.png
  34. BIN
      mix/qml/img/jumpoutbackdisabled.png
  35. BIN
      mix/qml/img/jumpoutforward.png
  36. BIN
      mix/qml/img/jumpoutforwarddisabled.png
  37. BIN
      mix/qml/img/jumpoverback.png
  38. BIN
      mix/qml/img/jumpoverbackdisabled.png
  39. BIN
      mix/qml/img/jumpoverforward.png
  40. BIN
      mix/qml/img/opentriangleindicator.png
  41. 147
      mix/qml/js/Debugger.js
  42. 27
      mix/qml/js/ErrorLocationFormater.js
  43. 19
      mix/qml/main.qml

20
libdevcore/CommonIO.cpp

@ -26,30 +26,30 @@
using namespace std; using namespace std;
using namespace dev; using namespace dev;
string dev::memDump(bytes const& _b, unsigned _w, bool _html) string dev::memDump(bytes const& _bytes, unsigned _width, bool _html)
{ {
stringstream ret; stringstream ret;
if (_html) if (_html)
ret << "<pre style=\"font-family: Monospace,Lucida Console,Courier,Courier New,sans-serif; font-size: small\">"; ret << "<pre style=\"font-family: Monospace,Lucida Console,Courier,Courier New,sans-serif; font-size: small\">";
for (unsigned i = 0; i < _b.size(); i += _w) for (unsigned i = 0; i < _bytes.size(); i += _width)
{ {
ret << hex << setw(4) << setfill('0') << i << " "; ret << hex << setw(4) << setfill('0') << i << " ";
for (unsigned j = i; j < i + _w; ++j) for (unsigned j = i; j < i + _width; ++j)
if (j < _b.size()) if (j < _bytes.size())
if (_b[j] >= 32 && _b[j] < 127) if (_bytes[j] >= 32 && _bytes[j] < 127)
if ((char)_b[j] == '<' && _html) if ((char)_bytes[j] == '<' && _html)
ret << "&lt;"; ret << "&lt;";
else if ((char)_b[j] == '&' && _html) else if ((char)_bytes[j] == '&' && _html)
ret << "&amp;"; ret << "&amp;";
else else
ret << (char)_b[j]; ret << (char)_bytes[j];
else else
ret << '?'; ret << '?';
else else
ret << ' '; ret << ' ';
ret << " "; ret << " ";
for (unsigned j = i; j < i + _w && j < _b.size(); ++j) for (unsigned j = i; j < i + _width && j < _bytes.size(); ++j)
ret << setfill('0') << setw(2) << hex << (unsigned)_b[j] << " "; ret << setfill('0') << setw(2) << hex << (unsigned)_bytes[j] << " ";
ret << "\n"; ret << "\n";
} }
if (_html) if (_html)

3
libdevcore/CommonIO.h

@ -47,7 +47,8 @@ bytes contents(std::string const& _file);
void writeFile(std::string const& _file, bytes const& _data); void writeFile(std::string const& _file, bytes const& _data);
/// Nicely renders the given bytes to a string, optionally as HTML. /// Nicely renders the given bytes to a string, optionally as HTML.
std::string memDump(bytes const& _b, unsigned _w = 8, bool _html = false); /// @a _bytes: bytes array to be rendered as string. @a _width of a bytes line.
std::string memDump(bytes const& _bytes, unsigned _width = 8, bool _html = false);
// Stream I/O functions. // Stream I/O functions.
// Provides templated stream I/O for all STL collections so they can be shifted on to any iostream-like interface. // Provides templated stream I/O for all STL collections so they can be shifted on to any iostream-like interface.

7
mix/AssemblyDebuggerControl.cpp

@ -26,8 +26,8 @@
using namespace dev::mix; using namespace dev::mix;
AssemblyDebuggerControl::AssemblyDebuggerControl(dev::mix::AppContext* _context): AssemblyDebuggerControl::AssemblyDebuggerControl(AppContext* _context):
Extension(_context, ExtensionDisplayBehavior::ModalDialog) Extension(_context, ExtensionDisplayBehavior::RightView)
{ {
connect(_context->clientModel(), &ClientModel::showDebuggerWindow, this, &AssemblyDebuggerControl::showDebugger, Qt::QueuedConnection); connect(_context->clientModel(), &ClientModel::showDebuggerWindow, this, &AssemblyDebuggerControl::showDebugger, Qt::QueuedConnection);
} }
@ -48,5 +48,6 @@ void AssemblyDebuggerControl::start() const
void AssemblyDebuggerControl::showDebugger() void AssemblyDebuggerControl::showDebugger()
{ {
this->addContentOn(this); QObject* debugPanel = m_view->findChild<QObject*>("debugPanel", Qt::FindChildrenRecursively);
QMetaObject::invokeMethod(debugPanel, "update");
} }

6
mix/AssemblyDebuggerControl.h

@ -22,13 +22,13 @@
#include <atomic> #include <atomic>
#include "Extension.h" #include "Extension.h"
class AppContext;
namespace dev namespace dev
{ {
namespace mix namespace mix
{ {
class AppContext;
/** /**
* @brief Extension which display transaction creation or transaction call debugging. * @brief Extension which display transaction creation or transaction call debugging.
*/ */
@ -44,7 +44,7 @@ public:
QString contentUrl() const override; QString contentUrl() const override;
private slots: private slots:
/// Update UI with machine states result. Display a modal dialog. /// Update UI with machine states result. Displayed in the right side tab.
void showDebugger(); void showDebugger();
}; };

2
mix/ClientModel.cpp

@ -116,7 +116,7 @@ void ClientModel::executeSequence(std::vector<TransactionSettings> const& _seque
{ {
bytes contractCode = compilerRes->bytes(); bytes contractCode = compilerRes->bytes();
std::vector<dev::bytes> transactonData; std::vector<dev::bytes> transactonData;
QFunctionDefinition* f; QFunctionDefinition* f = nullptr;
ContractCallDataEncoder c; ContractCallDataEncoder c;
//encode data for all transactions //encode data for all transactions
for (auto const& t: _sequence) for (auto const& t: _sequence)

21
mix/CodeEditorExtensionManager.cpp

@ -25,7 +25,7 @@
#include <QQmlEngine> #include <QQmlEngine>
#include <QQmlComponent> #include <QQmlComponent>
#include <QQuickTextDocument> #include <QQuickTextDocument>
#include "ConstantCompilationControl.h" #include "StatusPane.h"
#include "AssemblyDebuggerControl.h" #include "AssemblyDebuggerControl.h"
#include "StateListView.h" #include "StateListView.h"
#include "AppContext.h" #include "AppContext.h"
@ -56,10 +56,9 @@ void CodeEditorExtensionManager::loadEditor(QQuickItem* _editor)
void CodeEditorExtensionManager::initExtensions() void CodeEditorExtensionManager::initExtensions()
{ {
std::shared_ptr<ConstantCompilationControl> output = std::make_shared<ConstantCompilationControl>(m_appContext); std::shared_ptr<StatusPane> output = std::make_shared<StatusPane>(m_appContext);
std::shared_ptr<AssemblyDebuggerControl> debug = std::make_shared<AssemblyDebuggerControl>(m_appContext); std::shared_ptr<AssemblyDebuggerControl> debug = std::make_shared<AssemblyDebuggerControl>(m_appContext);
std::shared_ptr<StateListView> stateList = std::make_shared<StateListView>(m_appContext); std::shared_ptr<StateListView> stateList = std::make_shared<StateListView>(m_appContext);
QObject::connect(m_appContext->clientModel(), &ClientModel::runFailed, output.get(), &ConstantCompilationControl::displayError);
QObject::connect(m_appContext->codeModel(), &CodeModel::compilationComplete, this, &CodeEditorExtensionManager::applyCodeHighlight); QObject::connect(m_appContext->codeModel(), &CodeModel::compilationComplete, this, &CodeEditorExtensionManager::applyCodeHighlight);
initExtension(output); initExtension(output);
@ -73,10 +72,10 @@ void CodeEditorExtensionManager::initExtension(std::shared_ptr<Extension> _ext)
{ {
try try
{ {
if (_ext->getDisplayBehavior() == ExtensionDisplayBehavior::Tab) if (_ext->getDisplayBehavior() == ExtensionDisplayBehavior::RightView)
_ext->addTabOn(m_tabView); _ext->addTabOn(m_rightView);
else if (_ext->getDisplayBehavior() == ExtensionDisplayBehavior::RightTab) if (_ext->getDisplayBehavior() == ExtensionDisplayBehavior::HeaderView)
_ext->addTabOn(m_rightTabView); _ext->addTabOn(m_headerView);
} }
catch (...) catch (...)
{ {
@ -93,13 +92,13 @@ void CodeEditorExtensionManager::applyCodeHighlight()
//TODO: reimplement //TODO: reimplement
} }
void CodeEditorExtensionManager::setRightTabView(QQuickItem* _tabView) void CodeEditorExtensionManager::setRightView(QQuickItem* _rightView)
{ {
m_rightTabView = _tabView; m_rightView = _rightView;
initExtensions(); //TODO: move this to a proper place initExtensions(); //TODO: move this to a proper place
} }
void CodeEditorExtensionManager::setTabView(QQuickItem* _tabView) void CodeEditorExtensionManager::setHeaderView(QQuickItem* _headerView)
{ {
m_tabView = _tabView; m_headerView = _headerView;
} }

14
mix/CodeEditorExtensionManager.h

@ -26,7 +26,7 @@
#include <QQuickItem> #include <QQuickItem>
#include <QTextDocument> #include <QTextDocument>
#include <QVector> #include <QVector>
#include "ConstantCompilationControl.h" #include "StatusPane.h"
namespace dev namespace dev
{ {
@ -43,8 +43,8 @@ class CodeEditorExtensionManager: public QObject
{ {
Q_OBJECT Q_OBJECT
Q_PROPERTY(QQuickItem* tabView MEMBER m_tabView WRITE setTabView) Q_PROPERTY(QQuickItem* headerView MEMBER m_headerView WRITE setHeaderView)
Q_PROPERTY(QQuickItem* rightTabView MEMBER m_rightTabView WRITE setRightTabView) Q_PROPERTY(QQuickItem* rightView MEMBER m_rightView WRITE setRightView)
public: public:
CodeEditorExtensionManager(); CodeEditorExtensionManager();
@ -54,17 +54,17 @@ public:
/// Initialize extension. /// Initialize extension.
void initExtension(std::shared_ptr<Extension>); void initExtension(std::shared_ptr<Extension>);
/// Set current tab view /// Set current tab view
void setTabView(QQuickItem*); void setHeaderView(QQuickItem*);
/// Set current right tab view. /// Set current right tab view.
void setRightTabView(QQuickItem*); void setRightView(QQuickItem*);
private slots: private slots:
void applyCodeHighlight(); void applyCodeHighlight();
private: private:
QVector<std::shared_ptr<Extension>> m_features; QVector<std::shared_ptr<Extension>> m_features;
QQuickItem* m_tabView; QQuickItem* m_headerView;
QQuickItem* m_rightTabView; QQuickItem* m_rightView;
AppContext* m_appContext; AppContext* m_appContext;
void loadEditor(QQuickItem* _editor); void loadEditor(QQuickItem* _editor);
}; };

24
mix/CodeModel.cpp

@ -1,18 +1,18 @@
/* /*
This file is part of cpp-ethereum. This file is part of cpp-ethereum.
cpp-ethereum is free software: you can redistribute it and/or modify cpp-ethereum is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
cpp-ethereum is distributed in the hope that it will be useful, cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>. along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/ */
/** @file CodeModel.cpp /** @file CodeModel.cpp
* @author Arkadiy Paronyan arkadiy@ethdev.com * @author Arkadiy Paronyan arkadiy@ethdev.com
@ -168,7 +168,7 @@ void CodeModel::onCompilationComplete(CompilationResult*_newResult)
bool CodeModel::hasContract() const bool CodeModel::hasContract() const
{ {
return m_result->contract()->functionsList().size() > 0; return m_result->successful();
} }
void CodeModel::updateFormatting(QTextDocument* _document) void CodeModel::updateFormatting(QTextDocument* _document)

24
mix/CodeModel.h

@ -1,18 +1,18 @@
/* /*
This file is part of cpp-ethereum. This file is part of cpp-ethereum.
cpp-ethereum is free software: you can redistribute it and/or modify cpp-ethereum is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
cpp-ethereum is distributed in the hope that it will be useful, cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>. along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/ */
/** @file CodeModel.h /** @file CodeModel.h
* @author Arkadiy Paronyan arkadiy@ethdev.com * @author Arkadiy Paronyan arkadiy@ethdev.com
@ -65,6 +65,8 @@ class CompilationResult: public QObject
{ {
Q_OBJECT Q_OBJECT
Q_PROPERTY(QContractDefinition* contract READ contract) Q_PROPERTY(QContractDefinition* contract READ contract)
Q_PROPERTY(QString compilerMessage READ compilerMessage CONSTANT)
Q_PROPERTY(bool successful READ successful CONSTANT)
public: public:
/// Empty compilation result constructor /// Empty compilation result constructor

94
mix/ConstantCompilationControl.cpp

@ -1,94 +0,0 @@
/*
This file is part of cpp-ethereum.
cpp-ethereum is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file ConstantCompilationControl.cpp
* @author Yann yann@ethdev.com
* @date 2014
* Ethereum IDE client.
*/
#include <QQmlContext>
#include <QQuickItem>
#include <QtCore/QFileInfo>
#include <QApplication>
#include <QQmlApplicationEngine>
#include <QtCore/QtCore>
#include <QDebug>
#include "ConstantCompilationControl.h"
#include "QContractDefinition.h"
#include "AppContext.h"
#include "CodeModel.h"
using namespace dev::mix;
ConstantCompilationControl::ConstantCompilationControl(AppContext* _context): Extension(_context, ExtensionDisplayBehavior::Tab)
{
connect(_context->codeModel(), &CodeModel::compilationComplete, this, &ConstantCompilationControl::update);
connect(_context->codeModel(), &CodeModel::compilationComplete, this, &ConstantCompilationControl::update);
}
QString ConstantCompilationControl::contentUrl() const
{
return QStringLiteral("qrc:/qml/BasicContent.qml");
}
QString ConstantCompilationControl::title() const
{
return QApplication::tr("compiler");
}
void ConstantCompilationControl::start() const
{
}
void ConstantCompilationControl::update()
{
auto result = m_ctx->codeModel()->code();
QObject* status = m_view->findChild<QObject*>("status", Qt::FindChildrenRecursively);
QObject* content = m_view->findChild<QObject*>("content", Qt::FindChildrenRecursively);
if (result->successful())
{
status->setProperty("text", "succeeded");
status->setProperty("color", "green");
content->setProperty("text", result->assemblyCode());
}
else
{
status->setProperty("text", "failure");
status->setProperty("color", "red");
content->setProperty("text", result->compilerMessage());
}
}
void ConstantCompilationControl::resetOutPut()
{
QObject* status = m_view->findChild<QObject*>("status", Qt::FindChildrenRecursively);
QObject* content = m_view->findChild<QObject*>("content", Qt::FindChildrenRecursively);
status->setProperty("text", "");
content->setProperty("text", "");
}
void ConstantCompilationControl::displayError(QString const& _error)
{
QObject* status = m_view->findChild<QObject*>("status", Qt::FindChildrenRecursively);
QObject* content = m_view->findChild<QObject*>("content", Qt::FindChildrenRecursively);
status->setProperty("text", "failure");
status->setProperty("color", "red");
content->setProperty("text", _error);
}

118
mix/DebuggingStateWrapper.cpp

@ -66,55 +66,134 @@ std::tuple<QList<QObject*>, QQMLMap*> DebuggingStateWrapper::getHumanReadableCod
return std::make_tuple(codeStr, QPointer<QQMLMap>(new QQMLMap(codeMapping))); return std::make_tuple(codeStr, QPointer<QQMLMap>(new QQMLMap(codeMapping)));
} }
QString DebuggingStateWrapper::gasLeft() QString DebuggingStateWrapper::gasCost()
{ {
std::ostringstream ss; std::ostringstream ss;
ss << std::dec << (m_state.gas - m_state.gasCost); ss << std::dec << m_state.gasCost;
return QString::fromStdString(ss.str()); return QString::fromStdString(ss.str());
} }
QString DebuggingStateWrapper::gasCost() QString DebuggingStateWrapper::gas()
{ {
std::ostringstream ss; std::ostringstream ss;
ss << std::dec << m_state.gasCost; ss << std::dec << m_state.gas;
return QString::fromStdString(ss.str()); return QString::fromStdString(ss.str());
} }
QString DebuggingStateWrapper::gas() QString DebuggingStateWrapper::newMemSize()
{ {
std::ostringstream ss; std::ostringstream ss;
ss << std::dec << m_state.gas; ss << std::dec << m_state.newMemSize;
return QString::fromStdString(ss.str()); return QString::fromStdString(ss.str());
} }
QString DebuggingStateWrapper::debugStack() QStringList DebuggingStateWrapper::debugStack()
{ {
QString stack; QStringList stack;
for (auto i: m_state.stack) for (auto i: m_state.stack)
stack.prepend(QString::fromStdString(prettyU256(i)) + "\n"); stack.append(QString::fromStdString(prettyU256(i)));
return stack; return fillList(stack, "");
} }
QString DebuggingStateWrapper::debugStorage() QStringList DebuggingStateWrapper::debugStorage()
{ {
std::stringstream s; QStringList storage;
for (auto const& i: m_state.storage) for (auto const& i: m_state.storage)
{
std::stringstream s;
s << "@" << prettyU256(i.first) << " " << prettyU256(i.second); s << "@" << prettyU256(i.first) << " " << prettyU256(i.second);
storage.append(QString::fromStdString(s.str()));
}
return fillList(storage, "@ -");
}
return QString::fromStdString(s.str()); QVariantList DebuggingStateWrapper::debugMemory()
{
std::vector<std::vector<std::string>> dump = memDumpToList(m_state.memory, 16);
QStringList filled;
filled.append(" ");
filled.append(" ");
filled.append(" ");
return fillList(qVariantDump(dump), QVariant(filled));
} }
QString DebuggingStateWrapper::debugMemory() QVariantList DebuggingStateWrapper::debugCallData()
{ {
return QString::fromStdString(memDump(m_state.memory, 16, false)); std::vector<std::vector<std::string>> dump = memDumpToList(m_data, 16);
QStringList filled;
filled.append(" ");
filled.append(" ");
filled.append(" ");
return fillList(qVariantDump(dump), QVariant(filled));
} }
QString DebuggingStateWrapper::debugCallData() std::vector<std::vector<std::string>> DebuggingStateWrapper::memDumpToList(bytes const& _bytes, unsigned _width)
{ {
return QString::fromStdString(memDump(m_data, 16, false)); std::vector<std::vector<std::string>> dump;
for (unsigned i = 0; i < _bytes.size(); i += _width)
{
std::stringstream ret;
std::vector<std::string> dumpLine;
ret << std::hex << std::setw(4) << std::setfill('0') << i << " ";
dumpLine.push_back(ret.str());
ret.str(std::string());
ret.clear();
for (unsigned j = i; j < i + _width; ++j)
if (j < _bytes.size())
if (_bytes[j] >= 32 && _bytes[j] < 127)
ret << (char)_bytes[j];
else
ret << '?';
else
ret << ' ';
dumpLine.push_back(ret.str());
ret.str(std::string());
ret.clear();
for (unsigned j = i; j < i + _width && j < _bytes.size(); ++j)
ret << std::setfill('0') << std::setw(2) << std::hex << (unsigned)_bytes[j] << " ";
dumpLine.push_back(ret.str());
dump.push_back(dumpLine);
}
return dump;
} }
QVariantList DebuggingStateWrapper::qVariantDump(std::vector<std::vector<std::string>> const& _dump)
{
QVariantList ret;
for (std::vector<std::string> const& line: _dump)
{
QStringList qLine;
for (std::string const& cell: line)
qLine.push_back(QString::fromStdString(cell));
ret.append(QVariant(qLine));
}
return ret;
}
QStringList DebuggingStateWrapper::fillList(QStringList& _list, QString const& _emptyValue)
{
if (_list.size() < 20)
{
for (int k = _list.size(); k < 20 - _list.size(); k++)
_list.append(_emptyValue);
}
return _list;
}
QVariantList DebuggingStateWrapper::fillList(QVariantList _list, QVariant const& _emptyValue)
{
if (_list.size() < 20)
{
for (int k = _list.size(); k < 20 - _list.size(); k++)
_list.append(_emptyValue);
}
return _list;
}
QStringList DebuggingStateWrapper::levels() QStringList DebuggingStateWrapper::levels()
{ {
QStringList levelsStr; QStringList levelsStr;
@ -136,6 +215,11 @@ QString DebuggingStateWrapper::headerInfo()
return QString::fromStdString(ss.str()); return QString::fromStdString(ss.str());
} }
QString DebuggingStateWrapper::instruction()
{
return QString::fromStdString(dev::eth::instructionInfo(m_state.inst).name);
}
QString DebuggingStateWrapper::endOfDebug() QString DebuggingStateWrapper::endOfDebug()
{ {
if (m_state.gasCost > m_state.gas) if (m_state.gasCost > m_state.gas)

30
mix/DebuggingStateWrapper.h

@ -83,13 +83,14 @@ class DebuggingStateWrapper: public QObject
Q_PROPERTY(int curPC READ curPC CONSTANT) Q_PROPERTY(int curPC READ curPC CONSTANT)
Q_PROPERTY(QString gasCost READ gasCost CONSTANT) Q_PROPERTY(QString gasCost READ gasCost CONSTANT)
Q_PROPERTY(QString gas READ gas CONSTANT) Q_PROPERTY(QString gas READ gas CONSTANT)
Q_PROPERTY(QString gasLeft READ gasLeft CONSTANT) Q_PROPERTY(QString instruction READ instruction CONSTANT)
Q_PROPERTY(QString debugStack READ debugStack CONSTANT) Q_PROPERTY(QStringList debugStack READ debugStack CONSTANT)
Q_PROPERTY(QString debugStorage READ debugStorage CONSTANT) Q_PROPERTY(QStringList debugStorage READ debugStorage CONSTANT)
Q_PROPERTY(QString debugMemory READ debugMemory CONSTANT) Q_PROPERTY(QVariantList debugMemory READ debugMemory CONSTANT)
Q_PROPERTY(QString debugCallData READ debugCallData CONSTANT) Q_PROPERTY(QVariantList debugCallData READ debugCallData CONSTANT)
Q_PROPERTY(QString headerInfo READ headerInfo CONSTANT) Q_PROPERTY(QString headerInfo READ headerInfo CONSTANT)
Q_PROPERTY(QString endOfDebug READ endOfDebug CONSTANT) Q_PROPERTY(QString endOfDebug READ endOfDebug CONSTANT)
Q_PROPERTY(QString newMemSize READ newMemSize CONSTANT)
Q_PROPERTY(QStringList levels READ levels CONSTANT) Q_PROPERTY(QStringList levels READ levels CONSTANT)
public: public:
@ -105,17 +106,21 @@ public:
/// Get gas used. /// Get gas used.
QString gas(); QString gas();
/// Get stack. /// Get stack.
QString debugStack(); QStringList debugStack();
/// Get storage. /// Get storage.
QString debugStorage(); QStringList debugStorage();
/// Get memory. /// Get memory.
QString debugMemory(); QVariantList debugMemory();
/// Get call data. /// Get call data.
QString debugCallData(); QVariantList debugCallData();
/// Get info to be displayed in the header. /// Get info to be displayed in the header.
QString headerInfo(); QString headerInfo();
/// get end of debug information. /// get end of debug information.
QString endOfDebug(); QString endOfDebug();
/// Get the new memory size.
QString newMemSize();
/// Get current instruction
QString instruction();
/// Get all previous steps. /// Get all previous steps.
QStringList levels(); QStringList levels();
/// Get the current processed machine state. /// Get the current processed machine state.
@ -129,6 +134,13 @@ private:
MachineState m_state; MachineState m_state;
bytes m_code; bytes m_code;
bytes m_data; bytes m_data;
QStringList fillList(QStringList& _list, QString const& _emptyValue);
QVariantList fillList(QVariantList _list, QVariant const& _emptyValue);
QVariantList qVariantDump(std::vector<std::vector<std::string>> const& _dump);
/// Nicely renders the given bytes to a string, store the content in an array.
/// @a _bytes: bytes array to be rendered as string. @a _width of a bytes line.
std::vector<std::vector<std::string>> memDumpToList(bytes const& _bytes, unsigned _width);
}; };
} }

4
mix/Extension.h

@ -33,8 +33,8 @@ class AppContext;
enum ExtensionDisplayBehavior enum ExtensionDisplayBehavior
{ {
Tab, HeaderView,
RightTab, RightView,
ModalDialog ModalDialog
}; };

24
mix/StateListView.cpp

@ -1,18 +1,18 @@
/* /*
This file is part of cpp-ethereum. This file is part of cpp-ethereum.
cpp-ethereum is free software: you can redistribute it and/or modify cpp-ethereum is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
cpp-ethereum is distributed in the hope that it will be useful, cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>. along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/ */
/** @file StateListView.cpp /** @file StateListView.cpp
* @author Arkadiy Paronyan arkadiy@ethdev.com * @author Arkadiy Paronyan arkadiy@ethdev.com
@ -29,7 +29,7 @@
using namespace dev::mix; using namespace dev::mix;
StateListView::StateListView(AppContext* _context): Extension(_context, ExtensionDisplayBehavior::RightTab) StateListView::StateListView(AppContext* _context): Extension(_context, ExtensionDisplayBehavior::RightView)
{ {
} }

66
mix/StatusPane.cpp

@ -0,0 +1,66 @@
/*
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 ConstantCompilationControl.cpp
* @author Yann yann@ethdev.com
* @date 2014
* Ethereum IDE client.
*/
#include <QQmlContext>
#include <QQuickItem>
#include <QtCore/QFileInfo>
#include <QApplication>
#include <QQmlApplicationEngine>
#include <QtCore/QtCore>
#include <QDebug>
#include "StatusPane.h"
#include "QContractDefinition.h"
#include "AppContext.h"
#include "CodeModel.h"
using namespace dev::mix;
StatusPane::StatusPane(AppContext* _context): Extension(_context, ExtensionDisplayBehavior::HeaderView)
{
connect(_context->codeModel(), &CodeModel::compilationComplete, this, &StatusPane::update);
_context->appEngine()->rootContext()->setContextProperty("statusPane", this);
}
QString StatusPane::contentUrl() const
{
return QStringLiteral("qrc:/qml/StatusPane.qml");
}
QString StatusPane::title() const
{
return QApplication::tr("compiler");
}
void StatusPane::start() const
{
}
CompilationResult* StatusPane::result() const
{
return m_ctx->codeModel()->code();
}
void StatusPane::update()
{
QObject* ctrl = m_view->findChild<QObject*>("statusPane", Qt::FindChildrenRecursively);
QMetaObject::invokeMethod(ctrl, "updateStatus");
}

13
mix/ConstantCompilationControl.h → mix/StatusPane.h

@ -20,6 +20,7 @@
#pragma once #pragma once
#include "Extension.h" #include "Extension.h"
#include "CodeModel.h"
namespace dev namespace dev
{ {
@ -29,23 +30,21 @@ namespace mix
/** /**
* @brief Extension which display assembly code of the contract being edited. * @brief Extension which display assembly code of the contract being edited.
*/ */
class ConstantCompilationControl: public Extension class StatusPane: public Extension
{ {
Q_OBJECT Q_OBJECT
Q_PROPERTY(CompilationResult* result READ result CONSTANT)
public: public:
ConstantCompilationControl(AppContext* _appContext); StatusPane(AppContext* _appContext);
~ConstantCompilationControl() {} ~StatusPane() {}
void start() const override; void start() const override;
QString title() const override; QString title() const override;
QString contentUrl() const override; QString contentUrl() const override;
CompilationResult* result() const;
private:
void resetOutPut();
public slots: public slots:
void update(); void update();
void displayError(QString const& _error);
}; };
} }

21
mix/qml.qrc

@ -10,6 +10,27 @@
<file>qml/ProjectList.qml</file> <file>qml/ProjectList.qml</file>
<file>qml/StateDialog.qml</file> <file>qml/StateDialog.qml</file>
<file>qml/StateList.qml</file> <file>qml/StateList.qml</file>
<file>qml/img/jumpintoback.png</file>
<file>qml/img/jumpintoforward.png</file>
<file>qml/img/jumpoutback.png</file>
<file>qml/img/jumpoutforward.png</file>
<file>qml/img/jumpoverback.png</file>
<file>qml/img/jumpoverforward.png</file>
<file>qml/StepActionImage.qml</file>
<file>qml/img/jumpintobackdisabled.png</file>
<file>qml/img/jumpintoforwarddisabled.png</file>
<file>qml/img/jumpoutbackdisabled.png</file>
<file>qml/img/jumpoutforwarddisabled.png</file>
<file>qml/img/jumpoverbackdisabled.png</file>
<file>qml/DebugBasicInfo.qml</file>
<file>qml/js/ErrorLocationFormater.js</file>
<file>qml/img/closedtriangleindicator.png</file>
<file>qml/img/opentriangleindicator.png</file>
<file>qml/img/bugiconactive.png</file>
<file>qml/img/bugiconinactive.png</file>
<file>qml/DebugInfoList.qml</file>
<file>qml/ItemDelegateDataDump.qml</file>
<file>qml/StatusPane.qml</file>
<file>qml/TabStyle.qml</file> <file>qml/TabStyle.qml</file>
<file>qml/TransactionDialog.qml</file> <file>qml/TransactionDialog.qml</file>
<file>qml/js/Debugger.js</file> <file>qml/js/Debugger.js</file>

35
mix/qml/DebugBasicInfo.qml

@ -0,0 +1,35 @@
import QtQuick 2.2
import QtQuick.Controls 1.1
import QtQuick.Layouts 1.0
import QtQuick.Controls.Styles 1.1
RowLayout {
property string titleStr
width: parent.width
height: parent.height / 4
function update(_value)
{
currentStepValue.text = _value;
}
Rectangle {
width: parent.width / 2
height: parent.height
color: "#e5e5e5"
Text
{
id: title
font.pixelSize: 12
anchors.centerIn: parent
color: "#a2a2a2"
font.family: "Sans Serif"
text: titleStr
}
}
Text
{
font.pixelSize: 13
id: currentStepValue
}
}

83
mix/qml/DebugInfoList.qml

@ -0,0 +1,83 @@
import QtQuick 2.2
import QtQuick.Controls 1.1
import QtQuick.Layouts 1.0
import QtQuick.Controls.Styles 1.1
ColumnLayout {
property string title
property variant listModel;
property bool collapsible;
property Component itemDelegate
spacing: 0
RowLayout {
height: 25
id: header
Image {
source: "qrc:/qml/img/opentriangleindicator.png"
width: 15
sourceSize.width: 15
id: storageImgArrow
visible: collapsible
}
Text {
anchors.left: storageImgArrow.right
color: "#8b8b8b"
text: title
id: storageListTitle
}
MouseArea
{
enabled: collapsible
anchors.fill: parent
onClicked: {
if (storageContainer.state == "collapsed")
storageContainer.state = "";
else
storageContainer.state = "collapsed";
}
}
}
RowLayout
{
height: parent.height - header.height
clip: true
Rectangle
{
height: parent.height
border.width: 3
border.color: "#deddd9"
Layout.fillWidth: true
states: [
State {
name: "collapsed"
PropertyChanges {
target: storageContainer.parent
height: 0
visible: false
}
PropertyChanges {
target: storageImgArrow
source: "qrc:/qml/img/closedtriangleindicator.png"
}
}
]
id: storageContainer
width: parent.width
ListView {
clip: true;
anchors.top: parent.top
anchors.left: parent.left
anchors.topMargin: 3
anchors.leftMargin: 3
width: parent.width - 3
height: parent.height - 6
id: storageList
model: listModel
delegate: itemDelegate
}
}
}
}

689
mix/qml/Debugger.qml

@ -4,266 +4,505 @@ import QtQuick.Controls 1.1
import QtQuick.Dialogs 1.1 import QtQuick.Dialogs 1.1
import QtQuick.Layouts 1.1 import QtQuick.Layouts 1.1
import "js/Debugger.js" as Debugger import "js/Debugger.js" as Debugger
import "js/ErrorLocationFormater.js" as ErrorLocationFormater
Rectangle { Rectangle {
id: debugPanel
objectName: "debugPanel"
anchors.fill: parent; anchors.fill: parent;
color: "lightgrey" color: "#ededed"
Component.onCompleted: Debugger.init(); clip: true
Rectangle { Keys.onPressed:
color: "transparent" {
id: headerInfo
anchors.horizontalCenter: parent.horizontalCenter
width: parent.width
height: 60
anchors.top: parent.top
Column {
width: parent.width
height: parent.height
Rectangle {
color: "transparent"
width: parent.width
height: 30
Label {
anchors.centerIn: parent
font.family: "Verdana"
font.pointSize: 9
font.italic: true
id: headerInfoLabel
}
}
Rectangle {
color: "transparent"
width: parent.width
anchors.horizontalCenter: parent.horizontalCenter
height: 30
ListView {
orientation: ListView.Horizontal
anchors.centerIn: parent;
width: parent.width
id: headerReturnList
delegate: renderDelegateReturnValues
}
Component {
id: renderDelegateReturnValues
Item {
id: wrapperItem
width: 80
Text {
anchors.centerIn: parent
text: variable.declaration.name + " = " + variable.value
font.pointSize: 9
}
}
}
}
}
}
Keys.onPressed: {
if (event.key === Qt.Key_F10) if (event.key === Qt.Key_F10)
Debugger.moveSelection(1); Debugger.moveSelection(1);
else if (event.key === Qt.Key_F9) else if (event.key === Qt.Key_F9)
Debugger.moveSelection(-1); Debugger.moveSelection(-1);
} }
Rectangle { function update()
color: "transparent" {
id: stateListContainer if (statusPane.result.successful)
focus: true {
anchors.topMargin: 10 Debugger.init();
anchors.top: headerInfo.bottom debugScrollArea.visible = true;
anchors.left: parent.left compilationErrorArea.visible = false;
height: parent.height - 70 machineStates.visible = true;
width: parent.width * 0.5 }
else
{
debugScrollArea.visible = false;
compilationErrorArea.visible = true;
machineStates.visible = false;
var errorInfo = ErrorLocationFormater.extractErrorInfo(statusPane.result.compilerMessage, false);
errorLocation.text = errorInfo.errorLocation;
errorDetail.text = errorInfo.errorDetail;
errorLine.text = errorInfo.errorLine;
}
}
Connections {
target: codeModel
onCompilationComplete: update()
}
ListView { Rectangle
{
visible: false;
id: compilationErrorArea
width: parent.width - 20
height: 500
color: "#ededed"
anchors.left: parent.left
anchors.top: parent.top
anchors.margins: 10
ColumnLayout
{
width: parent.width
anchors.top: parent.top anchors.top: parent.top
height: parent.height * 0.60 spacing: 25
width: 200 RowLayout
anchors.horizontalCenter: parent.horizontalCenter {
id: statesList height: 100
model: humanReadableExecutionCode ColumnLayout
delegate: renderDelegate {
highlight: highlightBar Text {
highlightFollowsCurrentItem: true color: "red"
} id: errorLocation
}
Text {
color: "#4a4a4a"
id: errorDetail
}
}
}
Component { Rectangle
id: highlightBar {
Rectangle { width: parent.width - 6
height: statesList.currentItem.height height: 2
width: statesList.currentItem.width color: "#d0d0d0"
border.color: "orange"
border.width: 1
Behavior on y { SpringAnimation { spring: 2; damping: 0.1 } }
} }
}
Component { RowLayout
id: renderDelegate {
Item { Text
id: wrapperItem {
height: 20 color: "#4a4a4a"
width: parent.width id: errorLine
Text {
anchors.centerIn: parent
text: line
font.pointSize: 9
} }
} }
} }
}
Rectangle {
id: callStackPanel Flickable {
anchors.top: statesList.bottom property int firstColumnWidth: 170
height: parent.height * 0.35 property int secondColumnWidth: 250
width: parent.width id: debugScrollArea
flickableDirection: Flickable.VerticalFlick
anchors.fill: parent
contentHeight: machineStates.height + 300
contentWidth: machineStates.width
GridLayout
{
property int sideMargin: 10
id: machineStates
anchors.top: parent.top
anchors.topMargin: 15 anchors.topMargin: 15
color: "transparent" anchors.left: parent.left;
Label { anchors.leftMargin: machineStates.sideMargin
id: callStackLabel anchors.right: parent.right;
anchors.bottomMargin: 10 anchors.rightMargin: machineStates.sideMargin
horizontalAlignment: "AlignHCenter" flow: GridLayout.TopToBottom
font.family: "Verdana" rowSpacing: 15
font.pointSize: 8 RowLayout {
font.letterSpacing: 2 // step button + slider
width: parent.width spacing: machineStates.sideMargin
height: 15 height: 27
text: qsTr("callstack") width: debugPanel.width
} Rectangle
{
height: parent.height
color: "transparent"
width: debugScrollArea.firstColumnWidth
RowLayout {
anchors.horizontalCenter: parent.horizontalCenter
id: jumpButtons
spacing: 3
StepActionImage
{
id: jumpOutBackAction;
enabledStateImg: "qrc:/qml/img/jumpoutback.png"
disableStateImg: "qrc:/qml/img/jumpoutbackdisabled.png"
onClicked: Debugger.stepOutBack()
width: 25
height: 27
}
ListView { StepActionImage
height: parent.height - 15 {
width: 200 id: jumpIntoBackAction
anchors.top: callStackLabel.bottom enabledStateImg: "qrc:/qml/img/jumpintoback.png"
anchors.horizontalCenter: parent.horizontalCenter disableStateImg: "qrc:/qml/img/jumpintobackdisabled.png"
id: levelList onClicked: Debugger.stepIntoBack()
delegate: Component { width: 25
Item { height: 27
Text { }
font.family: "Verdana"
font.pointSize: 8 StepActionImage
text: modelData {
id: jumpOverBackAction
enabledStateImg: "qrc:/qml/img/jumpoverback.png"
disableStateImg: "qrc:/qml/img/jumpoverbackdisabled.png"
onClicked: Debugger.stepOverBack()
width: 25
height: 27
}
StepActionImage
{
id: jumpOverForwardAction
enabledStateImg: "qrc:/qml/img/jumpoverforward.png"
disableStateImg: "qrc:/qml/img/jumpoverforwarddisabled.png"
onClicked: Debugger.stepOverForward()
width: 25
height: 27
}
StepActionImage
{
id: jumpIntoForwardAction
enabledStateImg: "qrc:/qml/img/jumpintoforward.png"
disableStateImg: "qrc:/qml/img/jumpintoforwarddisabled.png"
onClicked: Debugger.stepIntoForward()
width: 25
height: 27
}
StepActionImage
{
id: jumpOutForwardAction
enabledStateImg: "qrc:/qml/img/jumpoutforward.png"
disableStateImg: "qrc:/qml/img/jumpoutforwarddisabled.png"
onClicked: Debugger.stepOutForward()
width: 25
height: 27
}
}
}
Rectangle {
color: "transparent"
width: debugScrollArea.secondColumnWidth
height: parent.height
Slider {
id: statesSlider
anchors.fill: parent
tickmarksEnabled: true
stepSize: 1.0
onValueChanged: Debugger.jumpTo(value);
style: SliderStyle {
groove: Rectangle {
implicitHeight: 3
color: "#7da4cd"
radius: 8
}
handle: Rectangle {
anchors.centerIn: parent
color: control.pressed ? "white" : "lightgray"
border.color: "gray"
border.width: 2
implicitWidth: 10
implicitHeight: 10
radius: 12
}
} }
} }
} }
} }
}
}
Rectangle { RowLayout {
color: "transparent" // Assembly code
anchors.topMargin: 5 width: debugPanel.width
anchors.bottomMargin: 10 height: 405
anchors.rightMargin: 10 spacing: machineStates.sideMargin
height: parent.height - 30
width: parent.width * 0.5
anchors.right: parent.right
anchors.top: headerInfo.bottom
anchors.bottom: parent.bottom
Rectangle { Rectangle
id: debugStack {
anchors.top: parent.top width: debugScrollArea.firstColumnWidth
width: parent.width height: parent.height
height: parent.height * 0.25 border.width: 3
color: "transparent" border.color: "#deddd9"
Label { color: "white"
horizontalAlignment: "AlignHCenter" anchors.top: parent.top
font.family: "Verdana" ListView {
font.pointSize: 8 anchors.fill: parent
width: parent.width anchors.leftMargin: 3
height: 15 anchors.rightMargin: 3
anchors.top : parent.top anchors.topMargin: 3
text: qsTr("debug stack") anchors.bottomMargin: 3
} clip: true
TextArea { id: statesList
anchors.bottom: parent.bottom delegate: renderDelegate
width: parent.width highlight: highlightBar
font.family: "Verdana" highlightFollowsCurrentItem: true
font.pointSize: 8 }
height: parent.height - 15
id: debugStackTxt Component {
readOnly: true; id: highlightBar
Rectangle {
radius: 4
height: statesList.currentItem.height
width: statesList.currentItem.width;
color: "#4A90E2"
Behavior on y { SpringAnimation { spring: 2; damping: 0.1 } }
}
}
Component {
id: renderDelegate
RowLayout {
id: wrapperItem
height: 20
width: parent.width
spacing: 5
Text {
anchors.left: parent.left
anchors.leftMargin: 10
width: 15
color: "#b2b3ae"
text: line.split(' ')[0]
font.pointSize: 9
id: id
wrapMode: Text.NoWrap
}
Text {
wrapMode: Text.NoWrap
color: parent.ListView.isCurrentItem ? "white" : "black"
text: line.replace(line.split(' ')[0], '')
anchors.left: id.right
font.pointSize: 9
}
}
}
}
ColumnLayout {
width: debugScrollArea.secondColumnWidth
height: parent.height
Rectangle {
// Info
width: parent.width
id: basicInfoColumn
height: 125
color: "transparent"
ColumnLayout {
spacing: 0
width: parent.width
height: parent.height
DebugBasicInfo {
id: currentStep
titleStr: qsTr("Current step")
}
DebugBasicInfo {
id: mem
titleStr: qsTr("Adding memory")
}
DebugBasicInfo {
id: stepCost
titleStr: qsTr("Step cost")
}
DebugBasicInfo {
id: gasSpent
titleStr: qsTr("Total gas spent")
}
}
}
Rectangle {
// Stack
height: 275
width: parent.width
color: "transparent"
DebugInfoList
{
id: stack
width: parent.width
height: parent.height
collapsible: false
title : qsTr("Stack")
itemDelegate: Item {
id: renderedItem
height: 27
width: parent.width
RowLayout
{
anchors.fill: parent
Rectangle
{
id: indexColumn
color: "#f7f7f7"
Layout.fillWidth: true
Layout.minimumWidth: 30
Layout.preferredWidth: 30
Layout.maximumWidth: 30
Layout.minimumHeight: parent.height
Text {
anchors.centerIn: parent
anchors.leftMargin: 5
color: "#8b8b8b"
text: model.index;
font.pointSize: 9
}
}
Rectangle
{
anchors.left: indexColumn.right
Layout.fillWidth: true
Layout.minimumWidth: 15
Layout.preferredWidth: 15
Layout.maximumWidth: 60
Layout.minimumHeight: parent.height
Text {
anchors.left: parent.left
anchors.leftMargin: 5
anchors.verticalCenter: parent.verticalCenter
color: "#8b8b8b"
text: modelData
font.pointSize: 9
}
}
}
Rectangle {
id: separator
width: parent.width;
height: 1;
color: "#cccccc"
anchors.bottom: parent.bottom
}
}
}
}
}
} }
}
Rectangle { Rectangle {
id: debugMemory width: debugPanel.width - 2 * machineStates.sideMargin
anchors.top: debugStack.bottom height: 2;
width: parent.width color: "#e3e3e3"
height: parent.height * 0.25 radius: 3
color: "transparent"
Label {
horizontalAlignment: "AlignHCenter"
font.family: "Verdana"
font.pointSize: 8
width: parent.width
height: 15
anchors.top : parent.top
text: qsTr("debug memory")
} }
TextArea {
anchors.bottom: parent.bottom DebugInfoList
width: parent.width {
font.family: "Verdana" id: storage
font.pointSize: 8 width: debugPanel.width - 2 * machineStates.sideMargin
height: parent.height - 15 height: 223
id: debugMemoryTxt collapsible: true
readOnly: true; title : qsTr("Storage")
itemDelegate:
Item {
height: 27
width: parent.width;
RowLayout
{
id: row
width: parent.width
height: 26
Rectangle
{
color: "#f7f7f7"
Layout.fillWidth: true
Layout.minimumWidth: parent.width / 2
Layout.preferredWidth: parent.width / 2
Layout.maximumWidth: parent.width / 2
Layout.minimumHeight: parent.height
Layout.maximumHeight: parent.height
Text {
anchors.verticalCenter: parent.verticalCenter
anchors.left: parent.left
anchors.leftMargin: 5
color: "#8b8b8b"
text: modelData.split(' ')[0].substring(0, 10);
font.pointSize: 9
}
}
Rectangle
{
color: "transparent"
Layout.fillWidth: true
Layout.minimumWidth: parent.width / 2
Layout.preferredWidth: parent.width / 2
Layout.maximumWidth: parent.width / 2
Layout.minimumHeight: parent.height
Layout.maximumHeight: parent.height
Text {
anchors.leftMargin: 5
width: parent.width - 5
wrapMode: Text.Wrap
anchors.left: parent.left
anchors.verticalCenter: parent.verticalCenter
color: "#8b8b8b"
text: modelData.split(' ')[1].substring(0, 10);
font.pointSize: 9
}
}
}
Rectangle {
anchors.top: row.bottom
width: parent.width;
height: 1;
color: "#cccccc"
anchors.bottom: parent.bottom
}
}
} }
}
Rectangle { Rectangle {
id: debugStorage width: debugPanel.width - 2 * machineStates.sideMargin
anchors.top: debugMemory.bottom height: 2;
width: parent.width color: "#e3e3e3"
height: parent.height * 0.25 radius: 3
color: "transparent"
Label {
horizontalAlignment: "AlignHCenter"
font.family: "Verdana"
font.pointSize: 8
width: parent.width
height: 15
anchors.top : parent.top
text: qsTr("debug storage")
} }
TextArea {
anchors.bottom: parent.bottom DebugInfoList {
width: parent.width id: memoryDump
font.family: "Verdana" width: debugPanel.width - 2 * machineStates.sideMargin
font.pointSize: 8 height: 223
height: parent.height - 15 collapsible: true
id: debugStorageTxt title: qsTr("Memory Dump")
readOnly: true; itemDelegate:
Item {
height: 29
width: parent.width - 3;
ItemDelegateDataDump {}
}
} }
}
Rectangle { Rectangle {
id: debugCallData width: debugPanel.width - 2 * machineStates.sideMargin
anchors.top: debugStorage.bottom height: 2;
width: parent.width color: "#e3e3e3"
height: parent.height * 0.25 radius: 3
color: "transparent"
Label {
horizontalAlignment: "AlignHCenter"
font.family: "Verdana"
font.pointSize: 8
width: parent.width
height: 15
anchors.top : parent.top
text: qsTr("debug calldata")
} }
TextArea {
anchors.bottom: parent.bottom DebugInfoList {
width: parent.width id: callDataDump
height: parent.height - 15 width: debugPanel.width - 2 * machineStates.sideMargin
font.family: "Verdana" height: 223
font.pointSize: 8 collapsible: true
font.letterSpacing: 2 title: qsTr("Call data")
id: debugCallDataTxt itemDelegate:
readOnly: true; Item {
height: 29
width: parent.width - 3;
ItemDelegateDataDump {}
}
} }
} }
} }

71
mix/qml/ItemDelegateDataDump.qml

@ -0,0 +1,71 @@
import QtQuick 2.2
import QtQuick.Controls 1.1
import QtQuick.Layouts 1.0
import QtQuick.Controls.Styles 1.1
Rectangle {
anchors.fill: parent
RowLayout
{
id: row;
anchors.fill: parent
spacing: 2
Rectangle
{
id: firstCol;
color: "#f7f7f7"
Layout.fillWidth: true
Layout.minimumWidth: 35
Layout.preferredWidth: 35
Layout.maximumWidth: 35
Layout.minimumHeight: parent.height
Text {
anchors.centerIn: parent
anchors.leftMargin: 5
color: "#8b8b8b"
text: modelData[0]
font.pointSize: 9;
}
}
Rectangle
{
anchors.left: firstCol.right
Layout.fillWidth: true
Layout.minimumWidth: 90
Layout.preferredWidth: 90
Layout.maximumWidth: 90
Layout.minimumHeight: parent.height
Text {
anchors.left: parent.left
anchors.leftMargin: 7
anchors.verticalCenter: parent.verticalCenter
color: "#8b8b8b"
text: modelData[1]
font.pointSize: 9
}
}
Rectangle
{
Layout.fillWidth: true
Layout.minimumWidth: 50
Layout.minimumHeight: parent.height
Text {
anchors.left: parent.left
anchors.verticalCenter: parent.verticalCenter
color: "#ededed"
font.bold: true
text: modelData[2]
font.pointSize: 10
}
}
}
Rectangle {
width: parent.width;
height: 1;
color: "#cccccc"
anchors.bottom: parent.bottom
}
}

196
mix/qml/MainContent.qml

@ -5,6 +5,7 @@ import QtQuick.Controls.Styles 1.1
import CodeEditorExtensionManager 1.0 import CodeEditorExtensionManager 1.0
Rectangle { Rectangle {
objectName: "mainContent" objectName: "mainContent"
signal keyPressed(variant event) signal keyPressed(variant event)
focus: true focus: true
@ -14,59 +15,152 @@ Rectangle {
root.keyPressed(event.key); root.keyPressed(event.key);
} }
anchors.fill: parent anchors.fill: parent
height: parent.height id: root
width: parent.width;
id:root function toggleRightView()
SplitView { {
orientation: Qt.Horizontal if (!rightView.visible)
anchors.fill: parent rightView.show();
else
ProjectList { rightView.hide();
width: parent.width * 0.2 }
height: parent.height
Layout.minimumWidth: 200 function ensureRightView()
{
if (!rightView.visible)
rightView.show();
}
function hideRightView()
{
if (rightView.visible)
rightView.hide();
}
CodeEditorExtensionManager {
headerView: headerPaneTabs;
rightView: rightPaneTabs;
}
GridLayout
{
anchors.fill: parent
rows: 2
flow: GridLayout.TopToBottom
columnSpacing: 0
rowSpacing: 0
Rectangle {
width: parent.width
height: 50
Layout.row: 0
Layout.fillWidth: true
Layout.preferredHeight: 50
id: headerView
Rectangle
{
gradient: Gradient {
GradientStop { position: 0.0; color: "#f1f1f1" }
GradientStop { position: 1.0; color: "#d9d7da" }
}
id: headerPaneContainer
anchors.fill: parent
TabView {
id: headerPaneTabs
tabsVisible: false
antialiasing: true
anchors.fill: parent
style: TabViewStyle {
frameOverlap: 1
tab: Rectangle {}
frame: Rectangle { color: "transparent" }
}
}
}
} }
SplitView { SplitView {
//anchors.fill: parent resizing: false
width: parent.width * 0.6 Layout.row: 1
orientation: Qt.Vertical orientation: Qt.Horizontal;
CodeEditorView { Layout.fillWidth: true
height: parent.height * 0.7 Layout.preferredHeight: root.height - headerView.height;
anchors.top: parent.top
width: parent.width ProjectList {
id: projectList
width: 200
height: parent.height
Layout.minimumWidth: 200
}
Rectangle {
id: contentView
width: parent.width - projectList.width
height: parent.height
CodeEditorView {
height: parent.height
anchors.top: parent.top
width: parent.width
}
} }
Rectangle { Rectangle {
anchors.bottom: parent.bottom visible: false;
id: contextualView id: rightView;
width: parent.width
Layout.minimumHeight: 20 Keys.onEscapePressed:
height: parent.height * 0.3 {
TabView { hide();
id: contextualTabs }
antialiasing: true
anchors.fill: parent function show() {
style: TabStyle {} visible = true;
} contentView.width = parent.width - projectList.width - rightView.width;
} }
}
Rectangle { function hide() {
anchors.right: parent.right visible = false;
id: rightPaneView contentView.width = parent.width - projectList.width;
width: parent.width * 0.2 }
height: parent.height
Layout.minimumWidth: 20 height: parent.height;
TabView { width: 450
id: rightPaneTabs Layout.minimumWidth: 450
antialiasing: true Rectangle {
anchors.fill: parent anchors.fill: parent;
//style: TabStyle {} id: rightPaneView
} TabView {
} id: rightPaneTabs
CodeEditorExtensionManager { tabsVisible: true
tabView: contextualTabs antialiasing: true
rightTabView: rightPaneTabs anchors.fill: parent
} style: TabViewStyle {
} frameOverlap: 1
tabBar:
Rectangle {
color: "#ededed"
id: background
}
tab: Rectangle {
color: "#ededed"
implicitWidth: 80
implicitHeight: 20
radius: 2
Text {
anchors.centerIn: parent
text: styleData.title
color: styleData.selected ? "#7da4cd" : "#202020"
}
}
frame: Rectangle {
}
}
}
}
}
}
}
} }

7
mix/qml/StateList.qml

@ -6,7 +6,7 @@ import QtQuick.Layouts 1.1
import org.ethereum.qml.ProjectModel 1.0 import org.ethereum.qml.ProjectModel 1.0
Rectangle { Rectangle {
color: "transparent" color: "#ededed"
id: stateListContainer id: stateListContainer
focus: true focus: true
anchors.topMargin: 10 anchors.topMargin: 10
@ -123,7 +123,10 @@ Rectangle {
ToolButton { ToolButton {
text: qsTr("Run"); text: qsTr("Run");
Layout.fillHeight: true Layout.fillHeight: true
onClicked: stateListModel.runState(index); onClicked:
{
stateListModel.runState(index)
}
} }
} }
} }

116
mix/qml/StatusPane.qml

@ -0,0 +1,116 @@
import QtQuick 2.2
import QtQuick.Controls 1.1
import QtQuick.Layouts 1.1
import "js/ErrorLocationFormater.js" as ErrorLocationFormater
Rectangle {
id: statusHeader
objectName: "statusPane"
function updateStatus()
{
if (statusPane.result.successful)
{
status.state = "";
status.text = qsTr("Compile without errors.");
logslink.visible = false;
}
else
{
status.state = "error";
var errorInfo = ErrorLocationFormater.extractErrorInfo(statusPane.result.compilerMessage, true);
status.text = errorInfo.errorLocation + " " + errorInfo.errorDetail;
logslink.visible = true;
}
debugRunActionIcon.enabled = statusPane.result.successful;
}
color: "transparent"
anchors.fill: parent
Rectangle {
id: statusContainer
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
radius: 3
width: 500
height: 30
color: "#fcfbfc"
RowLayout {
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
spacing: 5
Text {
font.pointSize: 10
height: 9
font.family: "sans serif"
objectName: "status"
id: status
states:[
State {
name: "error"
PropertyChanges {
target: status
color: "red"
}
PropertyChanges {
target: statusContainer
color: "#fffcd5"
}
}
]
}
Text {
visible: false
font.pointSize: 9
height: 9
text: qsTr("See log.")
font.family: "Monospace"
objectName: "status"
id: logslink
color: "#8c8a74"
MouseArea {
anchors.fill: parent
onClicked: {
mainContent.ensureRightView();
}
}
}
}
}
Rectangle
{
color: "transparent"
width: 100
height: parent.height
anchors.top: statusHeader.top
anchors.right: statusHeader.right
RowLayout
{
anchors.fill: parent
Rectangle {
color: "transparent"
anchors.fill: parent
Button
{
anchors.right: parent.right
anchors.rightMargin: 7
anchors.verticalCenter: parent.verticalCenter
id: debugImg
iconSource: "qrc:/qml/img/bugiconinactive.png"
action: debugRunActionIcon
}
Action {
id: debugRunActionIcon
onTriggered: {
mainContent.ensureRightView();
clientModel.debugDeployment();
}
enabled: false
}
}
}
}
}

39
mix/qml/StepActionImage.qml

@ -0,0 +1,39 @@
import QtQuick 2.2
import QtQuick.Controls 1.1
import QtQuick.Layouts 1.0
import QtQuick.Controls.Styles 1.1
Rectangle {
id: buttonActionContainer
property string disableStateImg
property string enabledStateImg
signal clicked
function enabled(state)
{
buttonAction.enabled = state;
if (state)
debugImg.iconSource = enabledStateImg;
else
debugImg.iconSource = disableStateImg;
}
color: "transparent"
Button
{
anchors.fill: parent
id: debugImg
iconSource: enabledStateImg
action: buttonAction
width: buttonActionContainer.width - 3
height: buttonActionContainer.height
}
Action {
id: buttonAction
onTriggered: {
buttonActionContainer.clicked();
}
}
}

BIN
mix/qml/img/bugiconactive.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

BIN
mix/qml/img/bugiconinactive.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

BIN
mix/qml/img/closedtriangleindicator.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 422 B

BIN
mix/qml/img/jumpintoback.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 762 B

BIN
mix/qml/img/jumpintobackdisabled.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 678 B

BIN
mix/qml/img/jumpintoforward.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 785 B

BIN
mix/qml/img/jumpintoforwarddisabled.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 695 B

BIN
mix/qml/img/jumpoutback.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 700 B

BIN
mix/qml/img/jumpoutbackdisabled.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 634 B

BIN
mix/qml/img/jumpoutforward.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 674 B

BIN
mix/qml/img/jumpoutforwarddisabled.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 580 B

BIN
mix/qml/img/jumpoverback.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 692 B

BIN
mix/qml/img/jumpoverbackdisabled.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 532 B

BIN
mix/qml/img/jumpoverforward.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 717 B

BIN
mix/qml/img/opentriangleindicator.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 425 B

147
mix/qml/js/Debugger.js

@ -4,11 +4,22 @@
//statesList => ListView //statesList => ListView
var currentSelectedState = null; var currentSelectedState = null;
var jumpStartingPoint = null;
function init() function init()
{ {
if (debugStates === undefined)
return;
statesSlider.maximumValue = debugStates.length - 1;
statesSlider.value = 0;
statesList.model = humanReadableExecutionCode;
currentSelectedState = 0; currentSelectedState = 0;
select(currentSelectedState); select(currentSelectedState);
displayReturnValue();
jumpOutBackAction.enabled(false);
jumpIntoBackAction.enabled(false);
jumpIntoForwardAction.enabled(false);
jumpOutForwardAction.enabled(false);
} }
function moveSelection(incr) function moveSelection(incr)
@ -16,25 +27,34 @@ function moveSelection(incr)
if (currentSelectedState + incr >= 0) if (currentSelectedState + incr >= 0)
{ {
if (currentSelectedState + incr < debugStates.length) if (currentSelectedState + incr < debugStates.length)
{
select(currentSelectedState + incr); select(currentSelectedState + incr);
} statesSlider.value = currentSelectedState;
else
{
endOfDebug();
}
} }
} }
function select(stateIndex) function select(stateIndex)
{ {
var codeLine = codeStr(stateIndex);
var state = debugStates[stateIndex]; var state = debugStates[stateIndex];
var codeStr = bytesCodeMapping.getValue(state.curPC); highlightSelection(codeLine);
highlightSelection(codeStr);
currentSelectedState = stateIndex; currentSelectedState = stateIndex;
completeCtxInformation(state); completeCtxInformation(state);
levelList.model = state.levels;
levelList.update(); if (state.instruction === "JUMP")
jumpIntoForwardAction.enabled(true);
else
jumpIntoForwardAction.enabled(false);
if (state.instruction === "JUMPDEST")
jumpIntoBackAction.enabled(true);
else
jumpIntoBackAction.enabled(false);
}
function codeStr(stateIndex)
{
var state = debugStates[stateIndex];
return bytesCodeMapping.getValue(state.curPC);
} }
function highlightSelection(index) function highlightSelection(index)
@ -44,21 +64,15 @@ function highlightSelection(index)
function completeCtxInformation(state) function completeCtxInformation(state)
{ {
debugStackTxt.text = state.debugStack; currentStep.update(state.step);
debugStorageTxt.text = state.debugStorage; mem.update(state.newMemSize + " " + qsTr("words"));
debugMemoryTxt.text = state.debugMemory; stepCost.update(state.gasCost);
debugCallDataTxt.text = state.debugCallData; gasSpent.update(debugStates[0].gas - state.gas);
headerInfoLabel.text = state.headerInfo
}
function endOfDebug() stack.listModel = state.debugStack;
{ storage.listModel = state.debugStorage;
var state = debugStates[debugStates.length - 1]; memoryDump.listModel = state.debugMemory;
debugStorageTxt.text = ""; callDataDump.listModel = state.debugCallData;
debugCallDataTxt.text = "";
debugStackTxt.text = "";
debugMemoryTxt.text = state.endOfDebug;
headerInfoLabel.text = "EXIT | GAS: " + state.gasLeft;
} }
function displayReturnValue() function displayReturnValue()
@ -66,3 +80,86 @@ function displayReturnValue()
headerReturnList.model = contractCallReturnParameters; headerReturnList.model = contractCallReturnParameters;
headerReturnList.update(); headerReturnList.update();
} }
function stepOutBack()
{
if (jumpStartingPoint != null)
{
select(jumpStartingPoint);
jumpStartingPoint = null;
jumpOutBackAction.enabled(false);
jumpOutForwardAction.enabled(false);
}
}
function stepIntoBack()
{
moveSelection(-1);
}
function stepOverBack()
{
var state = debugStates[currentSelectedState];
if (state.instruction === "JUMPDEST")
{
for (var k = currentSelectedState; k > 0; k--)
{
var line = bytesCodeMapping.getValue(debugStates[k].curPC);
if (line === statesList.currentIndex - 2)
{
select(k);
break;
}
}
}
else
moveSelection(-1);
}
function stepOverForward()
{
var state = debugStates[currentSelectedState];
if (state.instruction === "JUMP")
{
for (var k = currentSelectedState; k < debugStates.length; k++)
{
var line = bytesCodeMapping.getValue(debugStates[k].curPC);
if (line === statesList.currentIndex + 2)
{
select(k);
break;
}
}
}
else
moveSelection(1);
}
function stepIntoForward()
{
var state = debugStates[currentSelectedState];
if (state.instruction === "JUMP")
{
jumpStartingPoint = currentSelectedState;
moveSelection(1);
jumpOutBackAction.enabled(true);
jumpOutForwardAction.enabled(true);
}
}
function stepOutForward()
{
if (jumpStartingPoint != null)
{
stepOutBack();
stepOverForward();
jumpOutBackAction.enabled(false);
jumpOutForwardAction.enabled(false);
}
}
function jumpTo(value)
{
currentSelectedState = value;
select(currentSelectedState);
}

27
mix/qml/js/ErrorLocationFormater.js

@ -0,0 +1,27 @@
function formatLocation(raw, shortMessage)
{
var splitted = raw.split(':');
if (!shortMessage)
return qsTr("Error in line ") + splitted[1] + ", " + qsTr("character ") + splitted[2];
else
return "L" + splitted[1] + "," + "C" + splitted[2];
}
function extractErrorInfo(raw, shortMessage)
{
var _return = {};
var detail = raw.split('\n')[0];
var reg = detail.match(/:\d+:\d+:/g);
if (reg !== null)
{
_return.errorLocation = ErrorLocationFormater.formatLocation(reg[0], shortMessage);
_return.errorDetail = detail.replace(reg[0], "");
}
else
{
_return.errorLocation = "";
_return.errorDetail = detail;
}
_return.errorLine = raw.split('\n')[1];
return _return;
}

19
mix/qml/main.qml

@ -38,13 +38,20 @@ ApplicationWindow {
MenuItem { action: debugRunAction } MenuItem { action: debugRunAction }
MenuItem { action: debugResetStateAction } MenuItem { action: debugResetStateAction }
} }
Menu {
title: qsTr("Windows")
MenuItem { action: showHideRightPanel }
}
} }
Component.onCompleted: { Component.onCompleted: {
setX(Screen.width / 2 - width / 2); setX(Screen.width / 2 - width / 2);
setY(Screen.height / 2 - height / 2); setY(Screen.height / 2 - height / 2);
} }
MainContent { MainContent {
id: mainContent;
anchors.fill: parent
} }
ModalDialog { ModalDialog {
@ -68,8 +75,11 @@ ApplicationWindow {
id: debugRunAction id: debugRunAction
text: "&Run" text: "&Run"
shortcut: "F5" shortcut: "F5"
onTriggered: {
mainContent.ensureRightView();
clientModel.debugDeployment();
}
enabled: codeModel.hasContract && !clientModel.running; enabled: codeModel.hasContract && !clientModel.running;
onTriggered: clientModel.debugDeployment();
} }
Action { Action {
@ -79,6 +89,13 @@ ApplicationWindow {
onTriggered: clientModel.resetState(); onTriggered: clientModel.resetState();
} }
Action {
id: showHideRightPanel
text: "Show/Hide right view"
shortcut: "F7"
onTriggered: mainContent.toggleRightView();
}
Action { Action {
id: createProjectAction id: createProjectAction
text: qsTr("&New project") text: qsTr("&New project")

Loading…
Cancel
Save