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. 2
      mix/CodeModel.cpp
  9. 2
      mix/CodeModel.h
  10. 94
      mix/ConstantCompilationControl.cpp
  11. 118
      mix/DebuggingStateWrapper.cpp
  12. 30
      mix/DebuggingStateWrapper.h
  13. 4
      mix/Extension.h
  14. 2
      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. 595
      mix/qml/Debugger.qml
  21. 71
      mix/qml/ItemDelegateDataDump.qml
  22. 152
      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);
}; };

2
mix/CodeModel.cpp

@ -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)

2
mix/CodeModel.h

@ -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
}; };

2
mix/StateListView.cpp

@ -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
}
}
}
}

595
mix/qml/Debugger.qml

@ -4,85 +4,246 @@ 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 if (event.key === Qt.Key_F10)
anchors.horizontalCenter: parent.horizontalCenter Debugger.moveSelection(1);
width: parent.width else if (event.key === Qt.Key_F9)
height: 60 Debugger.moveSelection(-1);
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
} }
function update()
{
if (statusPane.result.successful)
{
Debugger.init();
debugScrollArea.visible = true;
compilationErrorArea.visible = false;
machineStates.visible = true;
}
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;
} }
Rectangle { }
color: "transparent"
width: parent.width Connections {
anchors.horizontalCenter: parent.horizontalCenter target: codeModel
height: 30 onCompilationComplete: update()
ListView { }
orientation: ListView.Horizontal
anchors.centerIn: parent; 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 width: parent.width
id: headerReturnList anchors.top: parent.top
delegate: renderDelegateReturnValues spacing: 25
RowLayout
{
height: 100
ColumnLayout
{
Text {
color: "red"
id: errorLocation
} }
Component {
id: renderDelegateReturnValues
Item {
id: wrapperItem
width: 80
Text { Text {
anchors.centerIn: parent color: "#4a4a4a"
text: variable.declaration.name + " = " + variable.value id: errorDetail
font.pointSize: 9 }
} }
} }
Rectangle
{
width: parent.width - 6
height: 2
color: "#d0d0d0"
}
RowLayout
{
Text
{
color: "#4a4a4a"
id: errorLine
} }
} }
} }
} }
Keys.onPressed: {
if (event.key === Qt.Key_F10) Flickable {
Debugger.moveSelection(1); property int firstColumnWidth: 170
else if (event.key === Qt.Key_F9) property int secondColumnWidth: 250
Debugger.moveSelection(-1); 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.left: parent.left;
anchors.leftMargin: machineStates.sideMargin
anchors.right: parent.right;
anchors.rightMargin: machineStates.sideMargin
flow: GridLayout.TopToBottom
rowSpacing: 15
RowLayout {
// step button + slider
spacing: machineStates.sideMargin
height: 27
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
} }
StepActionImage
{
id: jumpIntoBackAction
enabledStateImg: "qrc:/qml/img/jumpintoback.png"
disableStateImg: "qrc:/qml/img/jumpintobackdisabled.png"
onClicked: Debugger.stepIntoBack()
width: 25
height: 27
}
StepActionImage
{
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 { Rectangle {
color: "transparent" color: "transparent"
id: stateListContainer width: debugScrollArea.secondColumnWidth
focus: true height: parent.height
anchors.topMargin: 10 Slider {
anchors.top: headerInfo.bottom id: statesSlider
anchors.left: parent.left anchors.fill: parent
height: parent.height - 70 tickmarksEnabled: true
width: parent.width * 0.5 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
}
}
}
}
}
ListView { RowLayout {
// Assembly code
width: debugPanel.width
height: 405
spacing: machineStates.sideMargin
Rectangle
{
width: debugScrollArea.firstColumnWidth
height: parent.height
border.width: 3
border.color: "#deddd9"
color: "white"
anchors.top: parent.top anchors.top: parent.top
height: parent.height * 0.60 ListView {
width: 200 anchors.fill: parent
anchors.horizontalCenter: parent.horizontalCenter anchors.leftMargin: 3
anchors.rightMargin: 3
anchors.topMargin: 3
anchors.bottomMargin: 3
clip: true
id: statesList id: statesList
model: humanReadableExecutionCode
delegate: renderDelegate delegate: renderDelegate
highlight: highlightBar highlight: highlightBar
highlightFollowsCurrentItem: true highlightFollowsCurrentItem: true
@ -91,179 +252,257 @@ Rectangle {
Component { Component {
id: highlightBar id: highlightBar
Rectangle { Rectangle {
radius: 4
height: statesList.currentItem.height height: statesList.currentItem.height
width: statesList.currentItem.width width: statesList.currentItem.width;
border.color: "orange" color: "#4A90E2"
border.width: 1
Behavior on y { SpringAnimation { spring: 2; damping: 0.1 } } Behavior on y { SpringAnimation { spring: 2; damping: 0.1 } }
} }
} }
Component { Component {
id: renderDelegate id: renderDelegate
Item { RowLayout {
id: wrapperItem id: wrapperItem
height: 20 height: 20
width: parent.width width: parent.width
spacing: 5
Text { Text {
anchors.centerIn: parent anchors.left: parent.left
text: line 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 font.pointSize: 9
} }
} }
} }
}
ColumnLayout {
width: debugScrollArea.secondColumnWidth
height: parent.height
Rectangle { Rectangle {
id: callStackPanel // Info
anchors.top: statesList.bottom
height: parent.height * 0.35
width: parent.width width: parent.width
anchors.topMargin: 15 id: basicInfoColumn
height: 125
color: "transparent" color: "transparent"
Label { ColumnLayout {
id: callStackLabel spacing: 0
anchors.bottomMargin: 10
horizontalAlignment: "AlignHCenter"
font.family: "Verdana"
font.pointSize: 8
font.letterSpacing: 2
width: parent.width width: parent.width
height: 15 height: parent.height
text: qsTr("callstack") DebugBasicInfo {
} id: currentStep
titleStr: qsTr("Current step")
ListView {
height: parent.height - 15
width: 200
anchors.top: callStackLabel.bottom
anchors.horizontalCenter: parent.horizontalCenter
id: levelList
delegate: Component {
Item {
Text {
font.family: "Verdana"
font.pointSize: 8
text: modelData
} }
DebugBasicInfo {
id: mem
titleStr: qsTr("Adding memory")
} }
DebugBasicInfo {
id: stepCost
titleStr: qsTr("Step cost")
} }
DebugBasicInfo {
id: gasSpent
titleStr: qsTr("Total gas spent")
} }
} }
} }
Rectangle { Rectangle {
// Stack
height: 275
width: parent.width
color: "transparent" color: "transparent"
anchors.topMargin: 5
anchors.bottomMargin: 10
anchors.rightMargin: 10
height: parent.height - 30
width: parent.width * 0.5
anchors.right: parent.right
anchors.top: headerInfo.bottom
anchors.bottom: parent.bottom
Rectangle { DebugInfoList
id: debugStack {
anchors.top: parent.top id: stack
width: parent.width width: parent.width
height: parent.height * 0.25 height: parent.height
color: "transparent" collapsible: false
Label { title : qsTr("Stack")
horizontalAlignment: "AlignHCenter" itemDelegate: Item {
font.family: "Verdana" id: renderedItem
font.pointSize: 8 height: 27
width: parent.width width: parent.width
height: 15 RowLayout
anchors.top : parent.top {
text: qsTr("debug stack") 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
}
} }
TextArea { }
Rectangle {
id: separator
width: parent.width;
height: 1;
color: "#cccccc"
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
width: parent.width }
font.family: "Verdana" }
font.pointSize: 8 }
height: parent.height - 15 }
id: debugStackTxt
readOnly: true;
} }
} }
Rectangle { Rectangle {
id: debugMemory width: debugPanel.width - 2 * machineStates.sideMargin
anchors.top: debugStack.bottom height: 2;
color: "#e3e3e3"
radius: 3
}
DebugInfoList
{
id: storage
width: debugPanel.width - 2 * machineStates.sideMargin
height: 223
collapsible: true
title : qsTr("Storage")
itemDelegate:
Item {
height: 27
width: parent.width;
RowLayout
{
id: row
width: parent.width width: parent.width
height: parent.height * 0.25 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" color: "transparent"
Label { Layout.fillWidth: true
horizontalAlignment: "AlignHCenter" Layout.minimumWidth: parent.width / 2
font.family: "Verdana" Layout.preferredWidth: parent.width / 2
font.pointSize: 8 Layout.maximumWidth: parent.width / 2
width: parent.width Layout.minimumHeight: parent.height
height: 15 Layout.maximumHeight: parent.height
anchors.top : parent.top Text {
text: qsTr("debug memory") 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
}
} }
TextArea { }
Rectangle {
anchors.top: row.bottom
width: parent.width;
height: 1;
color: "#cccccc"
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
width: parent.width }
font.family: "Verdana"
font.pointSize: 8
height: parent.height - 15
id: debugMemoryTxt
readOnly: true;
} }
} }
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" DebugInfoList {
font.family: "Verdana" id: callDataDump
font.pointSize: 8 width: debugPanel.width - 2 * machineStates.sideMargin
width: parent.width height: 223
height: 15 collapsible: true
anchors.top : parent.top title: qsTr("Call data")
text: qsTr("debug calldata") itemDelegate:
Item {
height: 29
width: parent.width - 3;
ItemDelegateDataDump {}
} }
TextArea {
anchors.bottom: parent.bottom
width: parent.width
height: parent.height - 15
font.family: "Verdana"
font.pointSize: 8
font.letterSpacing: 2
id: debugCallDataTxt
readOnly: true;
} }
} }
} }

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
}
}

152
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)
rightView.show();
else
rightView.hide();
}
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 anchors.fill: parent
TabView {
id: headerPaneTabs
tabsVisible: false
antialiasing: true
anchors.fill: parent
style: TabViewStyle {
frameOverlap: 1
tab: Rectangle {}
frame: Rectangle { color: "transparent" }
}
}
}
}
SplitView {
resizing: false
Layout.row: 1
orientation: Qt.Horizontal;
Layout.fillWidth: true
Layout.preferredHeight: root.height - headerView.height;
ProjectList { ProjectList {
width: parent.width * 0.2 id: projectList
width: 200
height: parent.height height: parent.height
Layout.minimumWidth: 200 Layout.minimumWidth: 200
} }
SplitView { Rectangle {
//anchors.fill: parent id: contentView
width: parent.width * 0.6 width: parent.width - projectList.width
orientation: Qt.Vertical height: parent.height
CodeEditorView { CodeEditorView {
height: parent.height * 0.7 height: parent.height
anchors.top: parent.top anchors.top: parent.top
width: parent.width 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
style: TabStyle {}
} }
function show() {
visible = true;
contentView.width = parent.width - projectList.width - rightView.width;
} }
function hide() {
visible = false;
contentView.width = parent.width - projectList.width;
} }
height: parent.height;
width: 450
Layout.minimumWidth: 450
Rectangle { Rectangle {
anchors.right: parent.right anchors.fill: parent;
id: rightPaneView id: rightPaneView
width: parent.width * 0.2
height: parent.height
Layout.minimumWidth: 20
TabView { TabView {
id: rightPaneTabs id: rightPaneTabs
tabsVisible: true
antialiasing: true antialiasing: true
anchors.fill: parent anchors.fill: parent
//style: TabStyle {} 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 {
}
}
}
} }
} }
CodeEditorExtensionManager {
tabView: contextualTabs
rightTabView: rightPaneTabs
} }
} }
} }

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