Browse Source

debug formatting for structs and arrays

cl-refactor
arkpar 10 years ago
parent
commit
f994da400f
  1. 82
      mix/ClientModel.cpp
  2. 4
      mix/ClientModel.h
  3. 8
      mix/CodeModel.cpp
  4. 103
      mix/ContractCallDataEncoder.cpp
  5. 7
      mix/ContractCallDataEncoder.h
  6. 14
      mix/DebuggingStateWrapper.h
  7. 7
      mix/QContractDefinition.cpp
  8. 21
      mix/QVariableDeclaration.cpp
  9. 18
      mix/QVariableDeclaration.h
  10. 132
      mix/QVariableDefinition.cpp
  11. 69
      mix/qml/DebugInfoList.qml
  12. 4
      mix/qml/Debugger.qml
  13. 10
      mix/qml/SolidityTypeConverter.qml
  14. 144
      mix/qml/StructView.qml
  15. 35
      mix/qml/TransactionDialog.qml
  16. 39
      mix/qml/VariablesView.qml
  17. 8
      mix/qml/js/Debugger.js
  18. 2
      mix/res.qrc

82
mix/ClientModel.cpp

@ -186,14 +186,8 @@ void ClientModel::setupState(QVariantMap _state)
{
if (contractId.isEmpty() && m_context->codeModel()->hasContract()) //TODO: This is to support old project files, remove later
contractId = m_context->codeModel()->contracts().keys()[0];
QVariantList qParams = transaction.value("parameters").toList();
TransactionSettings transactionSettings(contractId, functionId, value, gas, gasPrice, Secret(sender.toStdString()));
for (QVariant const& variant: qParams)
{
QVariableDefinition* param = qvariant_cast<QVariableDefinition*>(variant);
transactionSettings.parameterValues.push_back(param);
}
transactionSettings.parameterValues = transaction.value("parameters").toMap();
if (contractId == functionId || functionId == "Constructor")
transactionSettings.functionId.clear();
@ -251,11 +245,11 @@ void ClientModel::executeSequence(std::vector<TransactionSettings> const& _seque
BOOST_THROW_EXCEPTION(FunctionNotFoundException() << FunctionName(transaction.functionId.toStdString()));
if (!transaction.functionId.isEmpty())
encoder.encode(f);
for (int p = 0; p < transaction.parameterValues.size(); p++)
for (QVariableDeclaration const* p: f->parametersList())
{
if (f->parametersList().size() <= p || f->parametersList().at(p)->type() != transaction.parameterValues.at(p)->declaration()->type())
BOOST_THROW_EXCEPTION(ParameterChangedException() << FunctionName(transaction.functionId.toStdString()));
encoder.push(transaction.parameterValues.at(p)->encodeValue());
QSolidityType const* type = p->type();
QVariant value = transaction.parameterValues.value(p->name());
encoder.encode(value, type->type());
}
if (transaction.functionId.isEmpty() || transaction.functionId == transaction.contractId)
@ -342,9 +336,9 @@ void ClientModel::showDebuggerForTransaction(ExecutionResult const& _t)
data.push_back(QMachineState::getDebugCallData(debugData, d));
QVariantList states;
QStringList solCallStack;
std::map<int, SolidityDeclaration> solLocals; //<stack pos, declaration>
QList<int> returnStack;
QVariantList solCallStack;
std::map<int, QVariableDeclaration*> solLocals; //<stack pos, decl>
std::map<QString, QVariableDeclaration*> storageDeclarations; //<name, decl>
unsigned prevInstructionIndex = 0;
for (MachineState const& s: _t.machineStates)
@ -361,43 +355,62 @@ void ClientModel::showDebuggerForTransaction(ExecutionResult const& _t)
//register new local variable initialization
auto localIter = contract->locals().find(LocationPair(instruction.getLocation().start, instruction.getLocation().end));
if (localIter != contract->locals().end())
solLocals[s.stack.size()] = localIter.value();
{
solLocals[s.stack.size()] = new QVariableDeclaration(debugData, localIter.value().name.toStdString(), localIter.value().type);
}
}
if (instruction.type() == dev::eth::Tag) //TODO: use annotations
if (instruction.type() == dev::eth::Tag)
{
//track calls into functions
AssemblyItem const& prevInstruction = codeItems[s.codeIndex][prevInstructionIndex];
auto functionIter = contract->functions().find(LocationPair(instruction.getLocation().start, instruction.getLocation().end));
if (functionIter != contract->functions().end())
{
QString functionName = functionIter.value();
solCallStack.push_back(functionName);
returnStack.push_back(prevInstructionIndex + 1);
}
else if (!returnStack.empty() && instructionIndex == returnStack.back())
{
returnStack.pop_back();
if (functionIter != contract->functions().end() && ((prevInstruction.getJumpType() == AssemblyItem::JumpType::IntoFunction) || solCallStack.empty()))
solCallStack.push_back(QVariant::fromValue(functionIter.value()));
else if (prevInstruction.getJumpType() == AssemblyItem::JumpType::OutOfFunction && !solCallStack.empty())
solCallStack.pop_back();
}
}
//format solidity context values
QStringList locals;
QVariantMap locals;
QVariantList localDeclarations;
QVariantMap localValues;
for(auto l: solLocals)
if (l.first < (int)s.stack.size())
locals.push_back(l.second.name + "\t" + formatValue(l.second.type, s.stack[l.first]));
{
localDeclarations.push_back(QVariant::fromValue(l.second));
localValues[l.second->name()] = formatValue(l.second->type()->type(), s.stack[l.first]);
}
locals["variables"] = localDeclarations;
locals["values"] = localValues;
QStringList storage;
QVariantMap storage;
QVariantList storageDeclarationList;
QVariantMap storageValues;
for(auto st: s.storage)
if (st.first < std::numeric_limits<unsigned>::max())
{
auto storageIter = contract->storage().find(static_cast<unsigned>(st.first));
if (storageIter != contract->storage().end())
storage.push_back(storageIter.value().name + "\t" + formatValue(storageIter.value().type, st.second));
{
QVariableDeclaration* storageDec = nullptr;
auto decIter = storageDeclarations.find(storageIter.value().name);
if (decIter != storageDeclarations.end())
storageDec = decIter->second;
else
{
storageDec = new QVariableDeclaration(debugData, storageIter.value().name.toStdString(), storageIter.value().type);
storageDeclarations[storageDec->name()] = storageDec;
}
storageDeclarationList.push_back(QVariant::fromValue(storageDec));
storageValues[storageDec->name()] = formatValue(storageDec->type()->type(), st.second);
}
}
storage["variables"] = storageDeclarationList;
storage["values"] = storageValues;
prevInstructionIndex = instructionIndex;
solState = new QSolState(debugData, storage, solCallStack, locals, instruction.getLocation().start, instruction.getLocation().end);
solState = new QSolState(debugData, std::move(storage), std::move(solCallStack), std::move(locals), instruction.getLocation().start, instruction.getLocation().end);
}
states.append(QVariant::fromValue(new QMachineState(debugData, instructionIndex, s, codes[s.codeIndex], data[s.dataIndex], solState)));
@ -407,9 +420,12 @@ void ClientModel::showDebuggerForTransaction(ExecutionResult const& _t)
debugDataReady(debugData);
}
QString ClientModel::formatValue(SolidityType const&, dev::u256 const& _value)
QVariant ClientModel::formatValue(SolidityType const& _type, dev::u256 const& _value)
{
return QString::fromStdString(prettyU256(_value));
ContractCallDataEncoder decoder;
bytes val = toBigEndian(_value);
QVariant res = decoder.decode(_type, val);
return res;
}
void ClientModel::emptyRecord()

4
mix/ClientModel.h

@ -63,7 +63,7 @@ struct TransactionSettings
/// Gas price
u256 gasPrice;
/// Mapping from contract function parameter name to value
QList<QVariableDefinition*> parameterValues;
QVariantMap parameterValues;
/// Standard contract url
QString stdContractUrl;
/// Sender
@ -199,7 +199,7 @@ private:
void onNewTransaction();
void onStateReset();
void showDebuggerForTransaction(ExecutionResult const& _t);
QString formatValue(SolidityType const& _type, dev::u256 const& _value);
QVariant formatValue(SolidityType const& _type, dev::u256 const& _value);
AppContext* m_context;
std::atomic<bool> m_running;

8
mix/CodeModel.cpp

@ -107,6 +107,7 @@ CompiledContract::CompiledContract(const dev::solidity::CompilerStack& _compiler
auto const& contractDefinition = _compiler.getContractDefinition(name);
m_contract.reset(new QContractDefinition(nullptr, &contractDefinition));
QQmlEngine::setObjectOwnership(m_contract.get(), QQmlEngine::CppOwnership);
m_contract->moveToThread(QApplication::instance()->thread());
m_bytes = _compiler.getBytecode(_contractName.toStdString());
m_assemblyItems = _compiler.getRuntimeAssemblyItems(name);
m_constructorAssemblyItems = _compiler.getAssemblyItems(name);
@ -312,6 +313,7 @@ SolidityType CodeModel::nodeType(solidity::Type const* _type)
SolidityType r { SolidityType::Type::UnsignedInteger, 32, false, false, QString::fromStdString(_type->toString()), std::vector<SolidityDeclaration>(), std::vector<QString>() };
if (!_type)
return r;
r.dynamicSize = _type->isDynamicallySized();
switch (_type->getCategory())
{
case Type::Category::Integer:
@ -336,8 +338,10 @@ SolidityType CodeModel::nodeType(solidity::Type const* _type)
case Type::Category::Array:
{
ArrayType const* array = dynamic_cast<ArrayType const*>(_type);
SolidityType elementType = nodeType(array->getBaseType().get());
r = elementType;
if (array->isByteArray())
r.type = SolidityType::Type::Bytes;
else
r = nodeType(array->getBaseType().get());
r.array = true;
}
break;

103
mix/ContractCallDataEncoder.cpp

@ -35,7 +35,9 @@ using namespace dev::mix;
bytes ContractCallDataEncoder::encodedData()
{
return m_encodedData;
bytes r(m_encodedData);
r.insert(r.end(), m_dynamicData.begin(), m_dynamicData.end());
return r;
}
void ContractCallDataEncoder::encode(QFunctionDefinition const* _function)
@ -44,6 +46,62 @@ void ContractCallDataEncoder::encode(QFunctionDefinition const* _function)
m_encodedData.insert(m_encodedData.end(), hash.begin(), hash.end());
}
void ContractCallDataEncoder::encode(QVariant const& _data, SolidityType const& _type)
{
if (_type.dynamicSize)
{
u256 count = 0;
if (_type.type == SolidityType::Type::Bytes)
count = encodeSingleItem(_data, _type, m_dynamicData);
else
{
QVariantList list = qvariant_cast<QVariantList>(_data);
for (auto const& item: list)
encodeSingleItem(item, _type, m_dynamicData);
count = list.size();
}
bytes sizeEnc(32);
toBigEndian(count, sizeEnc);
m_encodedData.insert(m_encodedData.end(), sizeEnc.begin(), sizeEnc.end());
}
else
encodeSingleItem(_data, _type, m_encodedData);
}
unsigned ContractCallDataEncoder::encodeSingleItem(QVariant const& _data, SolidityType const& _type, bytes& _dest)
{
if (_type.type == SolidityType::Type::Struct)
BOOST_THROW_EXCEPTION(dev::Exception() << dev::errinfo_comment("Struct parameters are not supported yet"));
unsigned const alignSize = 32;
QString src = _data.toString();
bytes result;
if (src.length() >= 2 && ((src.startsWith("\"") && src.endsWith("\"")) || (src.startsWith("\'") && src.endsWith("\'"))))
{
src = src.remove(src.length() - 1, 1).remove(0, 1);
QByteArray bytesAr = src.toLocal8Bit();
result = bytes(bytesAr.begin(), bytesAr.end());
}
else if (src.startsWith("0x"))
{
result = fromHex(src.toStdString().substr(2));
if (_type.type != SolidityType::Type::Bytes)
result = padded(result, alignSize);
}
else
{
bigint i(src.toStdString());
result = bytes(alignSize);
toBigEndian((u256)i, result);
}
unsigned dataSize = _type.dynamicSize ? result.size() : alignSize;
_dest.insert(_dest.end(), result.begin(), result.end());
if (_dest.size() % alignSize != 0)
_dest.resize((_dest.size() & ~(alignSize - 1)) + alignSize);
return dataSize;
}
void ContractCallDataEncoder::push(bytes const& _b)
{
m_encodedData.insert(m_encodedData.end(), _b.begin(), _b.end());
@ -57,14 +115,6 @@ bigint ContractCallDataEncoder::decodeInt(dev::bytes const& _rawValue)
return un;
}
dev::bytes ContractCallDataEncoder::encodeInt(QString const& _str)
{
dev::bigint i(_str.toStdString());
bytes ret(32);
toBigEndian((u256)i, ret);
return ret;
}
QString ContractCallDataEncoder::toString(dev::bigint const& _int)
{
std::stringstream str;
@ -107,27 +157,38 @@ QString ContractCallDataEncoder::toString(dev::bytes const& _b)
return QString::fromStdString(dev::toJS(_b));
}
QVariant ContractCallDataEncoder::decode(SolidityType const& _type, bytes const& _value)
{
bytesConstRef value(&_value);
bytes rawParam(32);
value.populate(&rawParam);
QSolidityType::Type type = _type.type;
if (type == QSolidityType::Type::SignedInteger || type == QSolidityType::Type::UnsignedInteger || type == QSolidityType::Type::Address)
return QVariant::fromValue(toString(decodeInt(rawParam)));
else if (type == QSolidityType::Type::Bool)
return QVariant::fromValue(toString(decodeBool(rawParam)));
else if (type == QSolidityType::Type::Bytes || type == QSolidityType::Type::Hash)
return QVariant::fromValue(toString(decodeBytes(rawParam)));
else if (type == QSolidityType::Type::Struct)
return QVariant::fromValue(QString("struct")); //TODO
else
BOOST_THROW_EXCEPTION(Exception() << errinfo_comment("Parameter declaration not found"));
}
QStringList ContractCallDataEncoder::decode(QList<QVariableDeclaration*> const& _returnParameters, bytes _value)
{
bytesConstRef value(&_value);
bytes rawParam(32);
QStringList r;
for (int k = 0; k <_returnParameters.length(); k++)
{
value.populate(&rawParam);
value = value.cropped(32);
value = value.cropped(32);
QVariableDeclaration* dec = static_cast<QVariableDeclaration*>(_returnParameters.at(k));
QSolidityType::Type type = dec->type()->type();
if (type == QSolidityType::Type::SignedInteger || type == QSolidityType::Type::UnsignedInteger)
r.append(toString(decodeInt(rawParam)));
else if (type == QSolidityType::Type::Bool)
r.append(toString(decodeBool(rawParam)));
else if (type == QSolidityType::Type::Bytes || type == QSolidityType::Type::Hash)
r.append(toString(decodeBytes(rawParam)));
else if (type == QSolidityType::Type::Struct)
r.append("struct"); //TODO
else
BOOST_THROW_EXCEPTION(Exception() << errinfo_comment("Parameter declaration not found"));
SolidityType const& type = dec->type()->type();
r.append(decode(type, rawParam).toString());
}
return r;
}

7
mix/ContractCallDataEncoder.h

@ -33,6 +33,7 @@ namespace mix
class QFunctionDefinition;
class QVariableDeclaration;
class QVariableDefinition;
class QSolidityType;
/**
* @brief Encode/Decode data to be sent to a transaction or to be displayed in a view.
@ -43,14 +44,19 @@ public:
ContractCallDataEncoder() {}
/// Encode hash of the function to call.
void encode(QFunctionDefinition const* _function);
/// Encode data for corresponding type
void encode(QVariant const& _data, SolidityType const& _type);
/// Decode variable in order to be sent to QML view.
QStringList decode(QList<QVariableDeclaration*> const& _dec, bytes _value);
/// Decode single variable
QVariant decode(SolidityType const& _type, bytes const& _value);
/// Get all encoded data encoded by encode function.
bytes encodedData();
/// Push the given @a _b to the current param context.
void push(bytes const& _b);
private:
unsigned encodeSingleItem(QVariant const& _data, SolidityType const& _type, bytes& _dest);
bigint decodeInt(dev::bytes const& _rawValue);
dev::bytes encodeInt(QString const& _str);
QString toString(dev::bigint const& _int);
@ -63,6 +69,7 @@ private:
private:
bytes m_encodedData;
bytes m_dynamicData;
};
}

14
mix/DebuggingStateWrapper.h

@ -60,21 +60,21 @@ private:
class QSolState: public QObject
{
Q_OBJECT
Q_PROPERTY(QStringList storage MEMBER m_storage CONSTANT)
Q_PROPERTY(QStringList callStack MEMBER m_callStack CONSTANT)
Q_PROPERTY(QStringList locals MEMBER m_locals CONSTANT)
Q_PROPERTY(QVariantMap storage MEMBER m_storage CONSTANT)
Q_PROPERTY(QVariantList callStack MEMBER m_callStack CONSTANT)
Q_PROPERTY(QVariantMap locals MEMBER m_locals CONSTANT)
Q_PROPERTY(int start MEMBER m_start CONSTANT)
Q_PROPERTY(int end MEMBER m_end CONSTANT)
public:
QSolState(QObject* _parent, QStringList const& _storage, QStringList const& _callStack, QStringList const& _locals, int _start, int _end):
QSolState(QObject* _parent, QVariantMap&& _storage, QVariantList&& _callStack, QVariantMap&& _locals, int _start, int _end):
QObject(_parent), m_storage(_storage), m_callStack(_callStack), m_locals(_locals), m_start(_start), m_end(_end)
{ }
private:
QStringList m_storage;
QStringList m_callStack;
QStringList m_locals;
QVariantMap m_storage;
QVariantList m_callStack;
QVariantMap m_locals;
int m_start;
int m_end;
};

7
mix/QContractDefinition.cpp

@ -34,13 +34,14 @@ using namespace dev::mix;
QContractDefinition::QContractDefinition(QObject* _parent, dev::solidity::ContractDefinition const* _contract): QBasicNodeDefinition(_parent, _contract)
{
QObject* parent = _parent ? _parent : this;
if (_contract->getConstructor() != nullptr)
m_constructor = new QFunctionDefinition(_parent, ContractType(*_contract).getConstructorType());
m_constructor = new QFunctionDefinition(parent, ContractType(*_contract).getConstructorType());
else
m_constructor = new QFunctionDefinition(_parent);
m_constructor = new QFunctionDefinition(parent);
for (auto const& it: _contract->getInterfaceFunctions())
m_functions.append(new QFunctionDefinition(_parent, it.second));
m_functions.append(new QFunctionDefinition(parent, it.second));
}
QFunctionDefinition const* QContractDefinition::getFunction(dev::FixedHash<4> _hash) const

21
mix/QVariableDeclaration.cpp

@ -47,17 +47,20 @@ QVariableDeclaration::QVariableDeclaration(QObject* _parent, std::string const&
QSolidityType::QSolidityType(QObject* _parent, SolidityType const& _type):
QObject(_parent),
m_type(_type.type),
m_size(_type.size),
m_name(_type.name)
m_type(_type)
{
if (_type.type == Type::Struct)
for (auto const& structMember: _type.members)
m_members.push_back(QVariant::fromValue(new QVariableDeclaration(_parent, structMember.name.toStdString(), structMember.type)));
}
if (_type.type == Type::Enum)
for (auto const& enumName: _type.enumNames)
m_members.push_back(QVariant::fromValue(enumName));
QVariantList QSolidityType::members() const
{
QVariantList members;
if (m_type.type == Type::Struct)
for (auto const& structMember: m_type.members)
members.push_back(QVariant::fromValue(new QVariableDeclaration(parent(), structMember.name.toStdString(), structMember.type)));
if (m_type.type == Type::Enum)
for (auto const& enumName: m_type.enumNames)
members.push_back(QVariant::fromValue(enumName));
return members;
}
}

18
mix/QVariableDeclaration.h

@ -40,7 +40,7 @@ namespace mix
class QSolidityType: public QObject
{
Q_OBJECT
Q_PROPERTY(int type READ type CONSTANT) //qml does not support enum properties
Q_PROPERTY(int category READ category CONSTANT) //qml does not support enum properties
Q_PROPERTY(int size READ size CONSTANT)
Q_PROPERTY(QString name READ name CONSTANT)
Q_PROPERTY(QVariantList members READ members CONSTANT)
@ -56,22 +56,20 @@ public:
Hash,
Bool,
Address,
String,
Bytes,
Enum,
Struct
};
Q_ENUMS(QmlType)
Type type() const { return m_type; }
int size() const { return m_size; }
QString name() const { return m_name; }
QVariantList members() const { return m_members; }
SolidityType const& type() const { return m_type; }
Type category() const { return m_type.type; }
int size() const { return m_type.size; }
QString name() const { return m_type.name; }
QVariantList members() const;
private:
Type m_type;
int m_size;
QString m_name;
QVariantList m_members;
SolidityType m_type;
};
class QVariableDeclaration: public QBasicNodeDefinition

132
mix/QVariableDefinition.cpp

@ -1,132 +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 QVariableDefinition.h
* @author Yann yann@ethdev.com
* @date 2014
*/
#include <libdevcore/CommonData.h>
#include <libethcore/CommonJS.h>
#include "QVariableDefinition.h"
using namespace dev::mix;
/*
int QVariableDefinitionList::rowCount(const QModelIndex& _parent) const
{
Q_UNUSED(_parent);
return m_def.size();
}
QVariant QVariableDefinitionList::data(const QModelIndex& _index, int _role) const
{
if (_role != Qt::DisplayRole)
return QVariant();
int i = _index.row();
if (i < 0 || i >= m_def.size())
return QVariant(QVariant::Invalid);
return QVariant::fromValue(m_def.at(i));
}
QHash<int, QByteArray> QVariableDefinitionList::roleNames() const
{
QHash<int, QByteArray> roles;
roles[Qt::DisplayRole] = "variable";
return roles;
}
QVariableDefinition* QVariableDefinitionList::val(int _idx)
{
if (_idx < 0 || _idx >= m_def.size())
return nullptr;
return m_def.at(_idx);
}
void QIntType::setValue(dev::bigint _value)
{
m_bigIntvalue = _value;
std::stringstream str;
str << std::dec << m_bigIntvalue;
m_value = QString::fromStdString(str.str());
}
dev::bytes QIntType::encodeValue()
{
dev::bigint i(value().toStdString());
bytes ret(32);
toBigEndian((u256)i, ret);
return ret;
}
void QIntType::decodeValue(dev::bytes const& _rawValue)
{
dev::u256 un = dev::fromBigEndian<dev::u256>(_rawValue);
if (un >> 255)
setValue(-s256(~un + 1));
else
setValue(un);
}
dev::bytes QHashType::encodeValue()
{
QByteArray bytesAr = value().toLocal8Bit();
bytes r = bytes(bytesAr.begin(), bytesAr.end());
return padded(r, 32);
}
void QHashType::decodeValue(dev::bytes const& _rawValue)
{
std::string _ret = asString(unpadLeft(_rawValue));
setValue(QString::fromStdString(_ret));
}
dev::bytes QRealType::encodeValue()
{
return bytes();
}
void QRealType::decodeValue(dev::bytes const& _rawValue)
{
Q_UNUSED(_rawValue);
}
dev::bytes QStringType::encodeValue()
{
QByteArray b = value().toUtf8();
bytes r = bytes(b.begin(), b.end());
return paddedRight(r, 32);
}
void QStringType::decodeValue(dev::bytes const& _rawValue)
{
setValue(QString::fromUtf8((char*)_rawValue.data()));
}
dev::bytes QBoolType::encodeValue()
{
return padded(jsToBytes(value().toStdString()), 32);
}
void QBoolType::decodeValue(dev::bytes const& _rawValue)
{
byte ret = _rawValue.at(_rawValue.size() - 1);
bool boolRet = (ret == byte(1));
m_boolValue = boolRet;
m_value = m_boolValue ? "1" : "0";
}
*/

69
mix/qml/DebugInfoList.qml

@ -11,6 +11,8 @@ ColumnLayout {
property bool enableSelection: false;
property real storedHeight: 0;
property Component itemDelegate
property Component componentDelegate
property alias item: loader.item
signal rowActivated(int index)
spacing: 0
@ -91,43 +93,54 @@ ColumnLayout {
}
}
]
TableView {
clip: true;
alternatingRowColors: false
Loader
{
id: loader
anchors.top: parent.top
anchors.left: parent.left
anchors.topMargin: 3
anchors.leftMargin: 3
width: parent.width - 3
height: parent.height - 6
model: listModel
selectionMode: enableSelection ? SelectionMode.SingleSelection : SelectionMode.NoSelection
headerDelegate: null
itemDelegate: root.itemDelegate
onHeightChanged: {
if (height <= 0 && collapsible) {
if (storedHeight <= 0)
storedHeight = 200;
storageContainer.state = "collapsed";
}
else if (height > 0 && storageContainer.state == "collapsed") {
//TODO: fix increasing size
//storageContainer.state = "";
sourceComponent: componentDelegate ? componentDelegate : table
}
Component
{
id: table
TableView
{
clip: true;
alternatingRowColors: false
anchors.fill: parent
model: listModel
selectionMode: enableSelection ? SelectionMode.SingleSelection : SelectionMode.NoSelection
headerDelegate: null
itemDelegate: root.itemDelegate
onHeightChanged: {
if (height <= 0 && collapsible) {
if (storedHeight <= 0)
storedHeight = 200;
storageContainer.state = "collapsed";
}
else if (height > 0 && storageContainer.state == "collapsed") {
//TODO: fix increasing size
//storageContainer.state = "";
}
}
}
onActivated: rowActivated(row);
Keys.onPressed: {
if ((event.modifiers & Qt.ControlModifier) && event.key === Qt.Key_C && currentRow >=0 && currentRow < listModel.length) {
var str = "";
for (var i = 0; i < listModel.length; i++)
str += listModel[i] + "\n";
appContext.toClipboard(str);
onActivated: rowActivated(row);
Keys.onPressed: {
if ((event.modifiers & Qt.ControlModifier) && event.key === Qt.Key_C && currentRow >=0 && currentRow < listModel.length) {
var str = "";
for (var i = 0; i < listModel.length; i++)
str += listModel[i] + "\n";
appContext.toClipboard(str);
}
}
}
TableViewColumn {
role: "modelData"
width: parent.width
TableViewColumn {
role: "modelData"
width: parent.width
}
}
}
}

4
mix/qml/Debugger.qml

@ -574,7 +574,7 @@ Rectangle {
Layout.maximumHeight: 800
onHeightChanged: machineStates.updateHeight();
visible: !assemblyMode
StorageView {
VariablesView {
title : qsTr("Locals")
anchors.fill: parent
id: solLocals
@ -589,7 +589,7 @@ Rectangle {
Layout.maximumHeight: 800
onHeightChanged: machineStates.updateHeight();
visible: !assemblyMode
StorageView {
VariablesView {
title : qsTr("Members")
anchors.fill: parent
id: solStorage

10
mix/qml/SolidityTypeConverter.qml

@ -1,10 +0,0 @@
import QtQuick 2.0
Item
{
function toJson(value)
{
if (
}
}

144
mix/qml/StructView.qml

@ -3,92 +3,88 @@ import QtQuick.Controls 1.1
import QtQuick.Layouts 1.1
import org.ethereum.qml.QSolidityType 1.0
Item
Column
{
id: editRoot
property alias membersModel: repeater.model //js array
property var value
id: root
property alias members: repeater.model //js array
property var value : { x: "333" }
property int level: 0
Column
Layout.fillWidth: true
Repeater
{
id: paramRepeater
id: repeater
visible: model.length > 0
Layout.fillWidth: true
Layout.fillHeight: true
spacing: 3
Repeater
RowLayout
{
id: repeater
height: 20 * model.length
visible: model.length > 0
RowLayout
{
id: row
Layout.fillWidth: true
DefaultLabel {
id: typeLabel
text: modelData.type.name
Layout.preferredWidth: 50
}
id: row
height: 20 + (members[index].type.category === QSolidityType.Struct ? (20 * members[index].type.members.length) : 0)
Layout.fillWidth: true
DefaultLabel {
height: 20
id: typeLabel
text: modelData.type.name
Layout.preferredWidth: 50
}
DefaultLabel {
id: nameLabel
text: modelData.name
Layout.preferredWidth: 80
}
DefaultLabel {
id: nameLabel
text: modelData.name
Layout.preferredWidth: 80
}
DefaultLabel {
id: equalLabel
text: "="
Layout.preferredWidth: 15
DefaultLabel {
id: equalLabel
text: "="
Layout.preferredWidth: 15
}
Loader
{
id: typeLoader
Layout.preferredWidth: 150
sourceComponent:
{
var t = modelData.type.category;
if (t === QSolidityType.SignedInteger || t === QSolidityType.UnsignedInteger)
return Qt.createComponent("qrc:/qml/QIntTypeView.qml");
else if (t === QSolidityType.Bool)
return Qt.createComponent("qrc:/qml/QBoolTypeView.qml");
else if (t === QSolidityType.Bytes)
return Qt.createComponent("qrc:/qml/QStringTypeView.qml");
else if (t === QSolidityType.Hash || t === QSolidityType.Address)
return Qt.createComponent("qrc:/qml/QHashTypeView.qml");
else if (t === QSolidityType.Struct)
return Qt.createComponent("qrc:/qml/StructView.qml");
else
return undefined;
}
Loader
onLoaded:
{
id: typeLoader
Layout.preferredWidth: 150
sourceComponent:
{
var t = modelData.type.type;
if (t === QSolidityType.SignedInteger || t === QSolidityType.UnsignedInteger)
return Qt.createComponent("qrc:/qml/QIntTypeView.qml");
else if (t === QSolidityType.Bool)
return Qt.createComponent("qrc:/qml/QBoolTypeView.qml");
else if (t === QSolidityType.Bytes)
return Qt.createComponent("qrc:/qml/QStringTypeView.qml");
else if (t === QSolidityType.Hash || t === QSolidityType.Address)
return Qt.createComponent("qrc:/qml/QHashTypeView.qml");
else if (t === QSolidityType.Struct)
return Qt.createComponent("qrc:/qml/StructView.qml");
else
return undefined;
var ptype = members[index].type;
var pname = members[index].name;
var vals = value;
if (ptype.category === QSolidityType.Struct && !item.members) {
item.level = level + 1;
item.value = getValue();
item.members = ptype.members;
}
onLoaded:
{
var ptype = membersModel[index].type;
var pname = membersModel[index].name;
var vals = value;
if (ptype.type === QSolidityType.Struct && !item.membersModel) {
item.level = level + 1;
item.value = getValue();
item.membersModel = ptype.members;
}
else
item.value = getValue();
item.onValueChanged.connect(function() {
vals[pname] = item.value;
valueChanged();
});
else
item.value = getValue();
}
item.onValueChanged.connect(function() {
vals[pname] = item.value;
valueChanged();
});
}
function getValue()
{
if (value && value[modelData.name])
return value[modelData.name];
else if (modelData.type.type === QSolidityType.Struct)
return {};
return "";
}
function getValue()
{
if (value && value[modelData.name] !== undefined)
return value[modelData.name];
else if (modelData.type.category === QSolidityType.Struct)
return {};
return "";
}
}
}

35
mix/qml/TransactionDialog.qml

@ -77,7 +77,7 @@ Window {
else {
var contract = codeModel.contracts[contractId];
if (contract) {
var params = contract.contract.constructor.params;
var params = contract.contract.constructor.parameters;
for (var p = 0; p < params.length; p++)
loadParameter(params[p]);
}
@ -125,23 +125,12 @@ Window {
}
}
typeLoader.value = {}
typeLoader.membersModel = []
typeLoader.members = []
typeLoader.value = paramValues;
typeLoader.membersModel = paramsModel;
typeLoader.members = paramsModel;
}
/*
function param(name)
{
for (var k = 0; k < paramsModel.length; k++)
{
if (paramsModel[k].name === name)
return paramsModel[k];
}
}
*/
function close()
{
visible = false;
@ -344,22 +333,14 @@ Window {
{
anchors.top: paramLabel.bottom
anchors.topMargin: 10
Layout.preferredWidth: 350
Layout.fillWidth: true
Layout.fillHeight: true
visible: true;//paramsModel.length > 0
Column
StructView
{
id: paramRepeater
Layout.fillWidth: true
Layout.fillHeight: true
spacing: 3
StructView
{
id: typeLoader
Layout.preferredWidth: 150
membersModel: paramsModel;
}
id: typeLoader
Layout.preferredWidth: 150
members: paramsModel;
}
}

39
mix/qml/VariablesView.qml

@ -0,0 +1,39 @@
import QtQuick 2.2
import QtQuick.Controls 1.1
import QtQuick.Controls.Styles 1.1
import QtQuick.Layouts 1.1
import "."
DebugInfoList
{
id: storage
collapsible: true
title : qsTr("Storage")
componentDelegate: structComp
Component
{
id: structComp
ScrollView
{
property alias members: typeLoader.members;
property alias value: typeLoader.value;
anchors.fill: parent
StructView
{
id: typeLoader
members: []
value: {}
Layout.preferredWidth: parent.width
}
}
}
function setData(members, values) {
storage.item.value = {};
storage.item.members = [];
storage.item.value = values;
storage.item.members = members;
}
}

8
mix/qml/js/Debugger.js

@ -199,12 +199,12 @@ function completeCtxInformation(state)
storage.listModel = state.debugStorage;
memoryDump.listModel = state.debugMemory;
if (state.solidity) {
solLocals.listModel = state.solidity.locals;
solStorage.listModel = state.solidity.storage;
solLocals.setData(state.solidity.locals.variables, state.solidity.locals.values);
solStorage.setData(state.solidity.storage.variables, state.solidity.storage.values);
solCallStack.listModel = state.solidity.callStack;
} else {
solLocals.listModel = [];
solStorage.listModel = [];
solLocals.setData([], {});
solStorage.setData([], {});
solCallStack.listModel = [];
}
}

2
mix/res.qrc

@ -110,8 +110,8 @@
<file>qml/img/copy.png</file>
<file>qml/img/broom.png</file>
<file>qml/LogsPaneStyle.qml</file>
<file>qml/SolidityTypeConverter.qml</file>
<file>qml/StructView.qml</file>
<file>qml/img/console.png</file>
<file>qml/VariablesView.qml</file>
</qresource>
</RCC>

Loading…
Cancel
Save