From d8673daa5bdc3059cd52222299399c8a3c72a3e4 Mon Sep 17 00:00:00 2001 From: arkpar Date: Wed, 11 Mar 2015 11:14:37 +0100 Subject: [PATCH 1/9] style --- mix/ClientModel.cpp | 7 +-- mix/CodeModel.cpp | 143 ++++++++++++++++++++++---------------------- mix/CodeModel.h | 5 +- 3 files changed, 76 insertions(+), 79 deletions(-) diff --git a/mix/ClientModel.cpp b/mix/ClientModel.cpp index 4e099b05b..3949c78e1 100644 --- a/mix/ClientModel.cpp +++ b/mix/ClientModel.cpp @@ -387,21 +387,20 @@ void ClientModel::showDebuggerForTransaction(ExecutionResult const& _t) } //format solidity context values - QStringList locals; + QStringList locals; 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])); - QStringList storage; + QStringList storage; for(auto st: s.storage) - { if (st.first < std::numeric_limits::max()) { auto storageIter = contract->storage().find(static_cast(st.first)); if (storageIter != contract->storage().end()) storage.push_back(storageIter.value().name + "\t" + formatValue(storageIter.value().type, st.second)); } - } + prevInstructionIndex = instructionIndex; solState = new QSolState(debugData, storage, solCallStack, locals, instruction.getLocation().start, instruction.getLocation().end); } diff --git a/mix/CodeModel.cpp b/mix/CodeModel.cpp index bb258334c..35029aa86 100644 --- a/mix/CodeModel.cpp +++ b/mix/CodeModel.cpp @@ -49,86 +49,87 @@ const std::set c_predefinedContracts = namespace { - using namespace dev::solidity; - class CollectDeclarationsVisitor: public ASTConstVisitor +using namespace dev::solidity; +class CollectDeclarationsVisitor: public ASTConstVisitor +{ +public: + CollectDeclarationsVisitor(QHash* _functions, QHash* _locals, QHash* _storage): + m_functions(_functions), m_locals(_locals), m_storage(_storage), m_functionScope(false), m_storageSlot(0) {} +private: + LocationPair nodeLocation(ASTNode const& _node) { - public: - CollectDeclarationsVisitor(QHash* _functions, QHash* _locals, QHash* _storage): - m_functions(_functions), m_locals(_locals), m_storage(_storage), m_functionScope(false), m_storageSlot(0) {} - private: - QHash* m_functions; - QHash* m_locals; - QHash* m_storage; - bool m_functionScope; - uint m_storageSlot; - - LocationPair nodeLocation(ASTNode const& _node) - { - return LocationPair(_node.getLocation().start, _node.getLocation().end); - } + return LocationPair(_node.getLocation().start, _node.getLocation().end); + } - SolidityType nodeType(Type const* _type) + SolidityType nodeType(Type const* _type) + { + if (!_type) + return SolidityType { SolidityType::Type::UnsignedInteger, 32 }; + switch (_type->getCategory()) { - if (!_type) - return SolidityType { SolidityType::Type::UnsignedInteger, 32 }; - switch (_type->getCategory()) + case Type::Category::Integer: { - case Type::Category::Integer: - { - IntegerType const* it = dynamic_cast(_type); - unsigned size = it->getNumBits() / 8; - SolidityType::Type typeCode = it->isAddress() ? SolidityType::Type::Address : it->isHash() ? SolidityType::Type::Hash : it->isSigned() ? SolidityType::Type::SignedInteger : SolidityType::Type::UnsignedInteger; - return SolidityType { typeCode, size }; - } - case Type::Category::Bool: - return SolidityType { SolidityType::Type::Bool, _type->getSizeOnStack() * 32 }; - case Type::Category::String: - { - StaticStringType const* s = dynamic_cast(_type); - return SolidityType { SolidityType::Type::String, static_cast(s->getNumBytes()) }; - } - case Type::Category::Contract: - return SolidityType { SolidityType::Type::Address, _type->getSizeOnStack() * 32 }; - case Type::Category::Array: - case Type::Category::Enum: - case Type::Category::Function: - case Type::Category::IntegerConstant: - case Type::Category::Magic: - case Type::Category::Mapping: - case Type::Category::Modifier: - case Type::Category::Real: - case Type::Category::Struct: - case Type::Category::TypeType: - case Type::Category::Void: - default: - return SolidityType { SolidityType::Type::UnsignedInteger, 32 }; + IntegerType const* it = dynamic_cast(_type); + unsigned size = it->getNumBits() / 8; + SolidityType::Type typeCode = it->isAddress() ? SolidityType::Type::Address : it->isHash() ? SolidityType::Type::Hash : it->isSigned() ? SolidityType::Type::SignedInteger : SolidityType::Type::UnsignedInteger; + return SolidityType { typeCode, size }; } + case Type::Category::Bool: + return SolidityType { SolidityType::Type::Bool, _type->getSizeOnStack() * 32 }; + case Type::Category::String: + { + StaticStringType const* s = dynamic_cast(_type); + return SolidityType { SolidityType::Type::String, static_cast(s->getNumBytes()) }; + } + case Type::Category::Contract: + return SolidityType { SolidityType::Type::Address, _type->getSizeOnStack() * 32 }; + case Type::Category::Array: + case Type::Category::Enum: + case Type::Category::Function: + case Type::Category::IntegerConstant: + case Type::Category::Magic: + case Type::Category::Mapping: + case Type::Category::Modifier: + case Type::Category::Real: + case Type::Category::Struct: + case Type::Category::TypeType: + case Type::Category::Void: + default: + return SolidityType { SolidityType::Type::UnsignedInteger, 32 }; } + } - virtual bool visit(FunctionDefinition const& _node) - { - m_functions->insert(nodeLocation(_node), QString::fromStdString(_node.getName())); - m_functionScope = true; - return true; - } + virtual bool visit(FunctionDefinition const& _node) + { + m_functions->insert(nodeLocation(_node), QString::fromStdString(_node.getName())); + m_functionScope = true; + return true; + } - virtual void endVisit(FunctionDefinition const&) - { - m_functionScope = false; - } + virtual void endVisit(FunctionDefinition const&) + { + m_functionScope = false; + } - virtual bool visit(VariableDeclaration const& _node) - { - SolidityDeclaration decl; - decl.type = nodeType(_node.getType().get()); - decl.name = QString::fromStdString(_node.getName()); - if (m_functionScope) - m_locals->insert(nodeLocation(_node), decl); - else - m_storage->insert(m_storageSlot++, decl); - return true; - } - }; + virtual bool visit(VariableDeclaration const& _node) + { + SolidityDeclaration decl; + decl.type = nodeType(_node.getType().get()); + decl.name = QString::fromStdString(_node.getName()); + if (m_functionScope) + m_locals->insert(nodeLocation(_node), decl); + else + m_storage->insert(m_storageSlot++, decl); + return true; + } + +private: + QHash* m_functions; + QHash* m_locals; + QHash* m_storage; + bool m_functionScope; + uint m_storageSlot; +}; } void BackgroundWorker::queueCodeChange(int _jobId) diff --git a/mix/CodeModel.h b/mix/CodeModel.h index 92111996c..f274917c4 100644 --- a/mix/CodeModel.h +++ b/mix/CodeModel.h @@ -37,10 +37,7 @@ class QTextDocument; namespace dev { -namespace solidity -{ - class CompilerStack; -} +namespace solidity { class CompilerStack; } namespace mix { From 34f13c59206230d36a82c0acfe74dac916b53a84 Mon Sep 17 00:00:00 2001 From: arkpar Date: Sun, 15 Mar 2015 17:54:45 +0100 Subject: [PATCH 2/9] struct editor --- mix/AppContext.cpp | 6 +- mix/ClientModel.cpp | 16 +-- mix/CodeModel.cpp | 107 ++++++++++------ mix/CodeModel.h | 30 ++--- mix/ContractCallDataEncoder.cpp | 90 ++++++++++--- mix/ContractCallDataEncoder.h | 13 +- mix/QBasicNodeDefinition.h | 6 +- mix/QContractDefinition.cpp | 10 +- mix/QContractDefinition.h | 3 +- mix/QFunctionDefinition.cpp | 10 +- mix/QFunctionDefinition.h | 5 +- mix/QVariableDeclaration.cpp | 65 ++++++++++ mix/QVariableDeclaration.h | 63 +++++++-- mix/QVariableDefinition.cpp | 17 +-- mix/QVariableDefinition.h | 86 ------------- mix/SolidityType.h | 65 ++++++++++ mix/qml/QBoolType.qml | 7 - mix/qml/QBoolTypeView.qml | 10 +- mix/qml/QHashType.qml | 7 - mix/qml/QHashTypeView.qml | 6 +- mix/qml/QIntType.qml | 7 - mix/qml/QIntTypeView.qml | 7 +- mix/qml/QRealType.qml | 7 - mix/qml/QStringType.qml | 7 - mix/qml/QStringTypeView.qml | 6 +- mix/qml/SolidityTypeConverter.qml | 10 ++ mix/qml/StateDialog.qml | 2 +- mix/qml/StateListModel.qml | 38 +----- mix/qml/StructView.qml | 182 ++++++++++++++++++++++++++ mix/qml/TransactionDialog.qml | 204 +++++------------------------- mix/res.qrc | 7 +- 31 files changed, 613 insertions(+), 486 deletions(-) create mode 100644 mix/QVariableDeclaration.cpp create mode 100644 mix/SolidityType.h delete mode 100644 mix/qml/QBoolType.qml delete mode 100644 mix/qml/QHashType.qml delete mode 100644 mix/qml/QIntType.qml delete mode 100644 mix/qml/QRealType.qml delete mode 100644 mix/qml/QStringType.qml create mode 100644 mix/qml/SolidityTypeConverter.qml create mode 100644 mix/qml/StructView.qml diff --git a/mix/AppContext.cpp b/mix/AppContext.cpp index 991fd334a..9e8f15b68 100644 --- a/mix/AppContext.cpp +++ b/mix/AppContext.cpp @@ -68,14 +68,10 @@ void AppContext::load() m_applicationEngine->rootContext()->setContextProperty("fileIo", m_fileIo.get()); qmlRegisterType("org.ethereum.qml.QEther", 1, 0, "QEther"); qmlRegisterType("org.ethereum.qml.QBigInt", 1, 0, "QBigInt"); - qmlRegisterType("org.ethereum.qml.QIntType", 1, 0, "QIntType"); - qmlRegisterType("org.ethereum.qml.QRealType", 1, 0, "QRealType"); - qmlRegisterType("org.ethereum.qml.QStringType", 1, 0, "QStringType"); - qmlRegisterType("org.ethereum.qml.QHashType", 1, 0, "QHashType"); - qmlRegisterType("org.ethereum.qml.QBoolType", 1, 0, "QBoolType"); qmlRegisterType("org.ethereum.qml.QVariableDeclaration", 1, 0, "QVariableDeclaration"); qmlRegisterType("org.ethereum.qml.RecordLogEntry", 1, 0, "RecordLogEntry"); qmlRegisterType("org.ethereum.qml.SortFilterProxyModel", 1, 0, "SortFilterProxyModel"); + qmlRegisterType("org.ethereum.qml.QSolidityType", 1, 0, "QSolidityType"); QQmlComponent projectModelComponent(m_applicationEngine, QUrl("qrc:/qml/ProjectModel.qml")); QObject* projectModel = projectModelComponent.create(); if (projectModelComponent.isError()) diff --git a/mix/ClientModel.cpp b/mix/ClientModel.cpp index 3949c78e1..2523a0d91 100644 --- a/mix/ClientModel.cpp +++ b/mix/ClientModel.cpp @@ -71,16 +71,11 @@ ClientModel::ClientModel(AppContext* _context): m_context(_context), m_running(false), m_rpcConnector(new RpcConnector()) { qRegisterMetaType("QBigInt*"); - qRegisterMetaType("QIntType*"); - qRegisterMetaType("QStringType*"); - qRegisterMetaType("QRealType*"); - qRegisterMetaType("QHashType*"); - qRegisterMetaType("QEther*"); qRegisterMetaType("QVariableDefinition*"); - qRegisterMetaType("QVariableDefinitionList*"); qRegisterMetaType>("QList"); qRegisterMetaType>("QList"); qRegisterMetaType("QVariableDeclaration*"); + qRegisterMetaType("QSolidityType*"); qRegisterMetaType("QMachineState"); qRegisterMetaType("QInstruction"); qRegisterMetaType("QCode"); @@ -191,7 +186,7 @@ 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("qType").toList(); + QVariantList qParams = transaction.value("parameters").toList(); TransactionSettings transactionSettings(contractId, functionId, value, gas, gasPrice, Secret(sender.toStdString())); for (QVariant const& variant: qParams) @@ -525,9 +520,10 @@ void ClientModel::onNewTransaction() { function = funcDef->name(); ContractCallDataEncoder encoder; - QList returnValues = encoder.decode(funcDef->returnParameters(), tr.returnValue); - for (auto const& var: returnValues) - returned += var->value() + " | "; + QStringList returnValues = encoder.decode(funcDef->returnParameters(), tr.returnValue); + returned += "("; + returned += returnValues.join(", "); + returned += ")"; } } } diff --git a/mix/CodeModel.cpp b/mix/CodeModel.cpp index 35029aa86..ff1cb9839 100644 --- a/mix/CodeModel.cpp +++ b/mix/CodeModel.cpp @@ -61,44 +61,6 @@ private: return LocationPair(_node.getLocation().start, _node.getLocation().end); } - SolidityType nodeType(Type const* _type) - { - if (!_type) - return SolidityType { SolidityType::Type::UnsignedInteger, 32 }; - switch (_type->getCategory()) - { - case Type::Category::Integer: - { - IntegerType const* it = dynamic_cast(_type); - unsigned size = it->getNumBits() / 8; - SolidityType::Type typeCode = it->isAddress() ? SolidityType::Type::Address : it->isHash() ? SolidityType::Type::Hash : it->isSigned() ? SolidityType::Type::SignedInteger : SolidityType::Type::UnsignedInteger; - return SolidityType { typeCode, size }; - } - case Type::Category::Bool: - return SolidityType { SolidityType::Type::Bool, _type->getSizeOnStack() * 32 }; - case Type::Category::String: - { - StaticStringType const* s = dynamic_cast(_type); - return SolidityType { SolidityType::Type::String, static_cast(s->getNumBytes()) }; - } - case Type::Category::Contract: - return SolidityType { SolidityType::Type::Address, _type->getSizeOnStack() * 32 }; - case Type::Category::Array: - case Type::Category::Enum: - case Type::Category::Function: - case Type::Category::IntegerConstant: - case Type::Category::Magic: - case Type::Category::Mapping: - case Type::Category::Modifier: - case Type::Category::Real: - case Type::Category::Struct: - case Type::Category::TypeType: - case Type::Category::Void: - default: - return SolidityType { SolidityType::Type::UnsignedInteger, 32 }; - } - } - virtual bool visit(FunctionDefinition const& _node) { m_functions->insert(nodeLocation(_node), QString::fromStdString(_node.getName())); @@ -114,7 +76,7 @@ private: virtual bool visit(VariableDeclaration const& _node) { SolidityDeclaration decl; - decl.type = nodeType(_node.getType().get()); + decl.type = CodeModel::nodeType(_node.getType().get()); decl.name = QString::fromStdString(_node.getName()); if (m_functionScope) m_locals->insert(nodeLocation(_node), decl); @@ -143,7 +105,7 @@ CompiledContract::CompiledContract(const dev::solidity::CompilerStack& _compiler { std::string name = _contractName.toStdString(); auto const& contractDefinition = _compiler.getContractDefinition(name); - m_contract.reset(new QContractDefinition(&contractDefinition)); + m_contract.reset(new QContractDefinition(nullptr, &contractDefinition)); QQmlEngine::setObjectOwnership(m_contract.get(), QQmlEngine::CppOwnership); m_bytes = _compiler.getBytecode(_contractName.toStdString()); m_assemblyItems = _compiler.getRuntimeAssemblyItems(name); @@ -345,3 +307,68 @@ dev::bytes const& CodeModel::getStdContractCode(const QString& _contractName, co return m_compiledContracts.at(_contractName); } +SolidityType CodeModel::nodeType(solidity::Type const* _type) +{ + SolidityType r { SolidityType::Type::UnsignedInteger, 32, false, false, QString::fromStdString(_type->toString()), std::vector(), std::vector() }; + if (!_type) + return r; + switch (_type->getCategory()) + { + case Type::Category::Integer: + { + IntegerType const* it = dynamic_cast(_type); + r.size = it->getNumBits() / 8; + r.type = it->isAddress() ? SolidityType::Type::Address : it->isHash() ? SolidityType::Type::Hash : it->isSigned() ? SolidityType::Type::SignedInteger : SolidityType::Type::UnsignedInteger; + } + break; + case Type::Category::Bool: + r.type = SolidityType::Type::Bool; + break; + case Type::Category::String: + { + StaticStringType const* s = dynamic_cast(_type); + r.type = SolidityType::Type::String; + r.size = static_cast(s->getNumBytes()); + } + case Type::Category::Contract: + r.type = SolidityType::Type::Address; + break; + case Type::Category::Array: + { + ArrayType const* array = dynamic_cast(_type); + SolidityType elementType = nodeType(array->getBaseType().get()); + r = elementType; + r.array = true; + } + break; + case Type::Category::Enum: + { + r.type = SolidityType::Type::Enum; + EnumType const* e = dynamic_cast(_type); + for(auto const& enumValue: e->getEnumDefinition().getMembers()) + r.enumNames.push_back(QString::fromStdString(enumValue->getName())); + } + break; + case Type::Category::Struct: + { + r.type = SolidityType::Type::Struct; + StructType const* s = dynamic_cast(_type); + for(auto const& structMember: s->getMembers()) + r.members.push_back(SolidityDeclaration { QString::fromStdString(structMember.first), nodeType(structMember.second.get()) }); + } + break; + case Type::Category::Function: + case Type::Category::IntegerConstant: + case Type::Category::Magic: + case Type::Category::Mapping: + case Type::Category::Modifier: + case Type::Category::Real: + case Type::Category::TypeType: + case Type::Category::Void: + default: + break; + //BOOST_THROW_EXCEPTION(dev::Exception() << errinfo_comment("Unsupported solidityType: " + _type->toString())); + } + return r; +} + diff --git a/mix/CodeModel.h b/mix/CodeModel.h index f274917c4..758cef48a 100644 --- a/mix/CodeModel.h +++ b/mix/CodeModel.h @@ -31,13 +31,18 @@ #include #include #include +#include "SolidityType.h" class QTextDocument; namespace dev { -namespace solidity { class CompilerStack; } +namespace solidity +{ +class CompilerStack; +class Type; +} namespace mix { @@ -63,27 +68,6 @@ private: using LocationPair = QPair; -struct SolidityType -{ - enum class Type //TODO: arrays and structs - { - SignedInteger, - UnsignedInteger, - Hash, - Bool, - Address, - String, - }; - Type type; - unsigned size; //bytes -}; - -struct SolidityDeclaration -{ - QString name; - SolidityType type; -}; - ///Compilation result model. Contains all the compiled contract data required by UI class CompiledContract: public QObject { @@ -163,6 +147,8 @@ public: Q_INVOKABLE CompiledContract* contractByDocumentId(QString _documentId) const; /// Reset code model Q_INVOKABLE void reset() { reset(QVariantMap()); } + /// Convert solidity type info to mix type + static SolidityType nodeType(solidity::Type const* _type); signals: /// Emited on compilation state change diff --git a/mix/ContractCallDataEncoder.cpp b/mix/ContractCallDataEncoder.cpp index e31f79e9f..54f828566 100644 --- a/mix/ContractCallDataEncoder.cpp +++ b/mix/ContractCallDataEncoder.cpp @@ -49,33 +49,85 @@ void ContractCallDataEncoder::push(bytes const& _b) m_encodedData.insert(m_encodedData.end(), _b.begin(), _b.end()); } -QList ContractCallDataEncoder::decode(QList const& _returnParameters, bytes _value) +bigint ContractCallDataEncoder::decodeInt(dev::bytes const& _rawValue) +{ + dev::u256 un = dev::fromBigEndian(_rawValue); + if (un >> 255) + return (-s256(~un + 1)); + 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; + str << std::dec << _int; + return QString::fromStdString(str.str()); +} + +dev::bytes ContractCallDataEncoder::encodeBool(QString const& _str) +{ + bytes b(1); + b[0] = _str == "1" || _str.toLower() == "true " ? 1 : 0; + return padded(b, 32); +} + +bool ContractCallDataEncoder::decodeBool(dev::bytes const& _rawValue) +{ + byte ret = _rawValue.at(_rawValue.size() - 1); + return (ret != 0); +} + +QString ContractCallDataEncoder::toString(bool _b) +{ + return _b ? "true" : "false"; +} + +dev::bytes ContractCallDataEncoder::encodeBytes(QString const& _str) +{ + QByteArray bytesAr = _str.toLocal8Bit(); + bytes r = bytes(bytesAr.begin(), bytesAr.end()); + return padded(r, 32); +} + +dev::bytes ContractCallDataEncoder::decodeBytes(dev::bytes const& _rawValue) +{ + return _rawValue; +} + +QString ContractCallDataEncoder::toString(dev::bytes const& _b) +{ + return QString::fromStdString(dev::toJS(_b)); +} + +QStringList ContractCallDataEncoder::decode(QList const& _returnParameters, bytes _value) { bytesConstRef value(&_value); bytes rawParam(32); - QList r; + QStringList r; for (int k = 0; k <_returnParameters.length(); k++) { + value.populate(&rawParam); + value = value.cropped(32); QVariableDeclaration* dec = static_cast(_returnParameters.at(k)); - QVariableDefinition* def = nullptr; - if (dec->type().contains("int")) - def = new QIntType(dec, QString()); - else if (dec->type().contains("real")) - def = new QRealType(dec, QString()); - else if (dec->type().contains("bool")) - def = new QBoolType(dec, QString()); - else if (dec->type().contains("string") || dec->type().contains("text")) - def = new QStringType(dec, QString()); - else if (dec->type().contains("hash") || dec->type().contains("address")) - def = new QHashType(dec, QString()); + 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::String || 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")); - - value.populate(&rawParam); - def->decodeValue(rawParam); - r.push_back(def); - value = value.cropped(32); - qDebug() << "decoded return value : " << dec->type() << " " << def->value(); } return r; } diff --git a/mix/ContractCallDataEncoder.h b/mix/ContractCallDataEncoder.h index 718beb8e0..9b5f8355b 100644 --- a/mix/ContractCallDataEncoder.h +++ b/mix/ContractCallDataEncoder.h @@ -44,12 +44,23 @@ public: /// Encode hash of the function to call. void encode(QFunctionDefinition const* _function); /// Decode variable in order to be sent to QML view. - QList decode(QList const& _dec, bytes _value); + QStringList decode(QList const& _dec, bytes _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: + bigint decodeInt(dev::bytes const& _rawValue); + dev::bytes encodeInt(QString const& _str); + QString toString(dev::bigint const& _int); + dev::bytes encodeBool(QString const& _str); + bool decodeBool(dev::bytes const& _rawValue); + QString toString(bool _b); + dev::bytes encodeBytes(QString const& _str); + dev::bytes decodeBytes(dev::bytes const& _rawValue); + QString toString(dev::bytes const& _b); + private: bytes m_encodedData; }; diff --git a/mix/QBasicNodeDefinition.h b/mix/QBasicNodeDefinition.h index d276d0eb2..42f8ac15d 100644 --- a/mix/QBasicNodeDefinition.h +++ b/mix/QBasicNodeDefinition.h @@ -35,10 +35,10 @@ class QBasicNodeDefinition: public QObject Q_PROPERTY(QString name READ name CONSTANT) public: - QBasicNodeDefinition(): QObject() {} + QBasicNodeDefinition(QObject* _parent = nullptr): QObject(_parent) {} ~QBasicNodeDefinition() {} - QBasicNodeDefinition(solidity::Declaration const* _d): QObject(), m_name(QString::fromStdString(_d->getName())) {} - QBasicNodeDefinition(std::string const& _name): QObject(), m_name(QString::fromStdString(_name)) {} + QBasicNodeDefinition(QObject* _parent, solidity::Declaration const* _d): QObject(_parent), m_name(QString::fromStdString(_d->getName())) {} + QBasicNodeDefinition(QObject* _parent, std::string const& _name): QObject(_parent), m_name(QString::fromStdString(_name)) {} /// Get the name of the node. QString name() const { return m_name; } diff --git a/mix/QContractDefinition.cpp b/mix/QContractDefinition.cpp index 27779ce11..b08979ae4 100644 --- a/mix/QContractDefinition.cpp +++ b/mix/QContractDefinition.cpp @@ -32,16 +32,16 @@ using namespace dev::solidity; using namespace dev::mix; -QContractDefinition::QContractDefinition(dev::solidity::ContractDefinition const* _contract): QBasicNodeDefinition(_contract) +QContractDefinition::QContractDefinition(QObject* _parent, dev::solidity::ContractDefinition const* _contract): QBasicNodeDefinition(_parent, _contract) { if (_contract->getConstructor() != nullptr) - m_constructor = new QFunctionDefinition(ContractType(*_contract).getConstructorType()); + m_constructor = new QFunctionDefinition(_parent, ContractType(*_contract).getConstructorType()); else - m_constructor = new QFunctionDefinition(); + m_constructor = new QFunctionDefinition(_parent); for (auto const& it: _contract->getInterfaceFunctions()) - m_functions.append(new QFunctionDefinition(it.second));} - + m_functions.append(new QFunctionDefinition(_parent, it.second)); +} QFunctionDefinition const* QContractDefinition::getFunction(dev::FixedHash<4> _hash) const { diff --git a/mix/QContractDefinition.h b/mix/QContractDefinition.h index 4d586a239..ff0df1f15 100644 --- a/mix/QContractDefinition.h +++ b/mix/QContractDefinition.h @@ -39,8 +39,7 @@ class QContractDefinition: public QBasicNodeDefinition Q_PROPERTY(dev::mix::QFunctionDefinition* constructor READ constructor CONSTANT) public: - QContractDefinition() {} - QContractDefinition(solidity::ContractDefinition const* _contract); + QContractDefinition(QObject* _parent, solidity::ContractDefinition const* _contract); /// Get all the functions of the contract. QQmlListProperty functions() const { return QQmlListProperty(const_cast(this), const_cast(this)->m_functions); } /// Get the constructor of the contract. diff --git a/mix/QFunctionDefinition.cpp b/mix/QFunctionDefinition.cpp index 20dbe070b..fed4e8add 100644 --- a/mix/QFunctionDefinition.cpp +++ b/mix/QFunctionDefinition.cpp @@ -28,15 +28,15 @@ using namespace dev::solidity; using namespace dev::mix; -QFunctionDefinition::QFunctionDefinition(dev::solidity::FunctionTypePointer const& _f): QBasicNodeDefinition(&_f->getDeclaration()), m_hash(dev::sha3(_f->getCanonicalSignature())) +QFunctionDefinition::QFunctionDefinition(QObject* _parent, dev::solidity::FunctionTypePointer const& _f): QBasicNodeDefinition(_parent, &_f->getDeclaration()), m_hash(dev::sha3(_f->getCanonicalSignature())) { auto paramNames = _f->getParameterNames(); - auto paramTypes = _f->getParameterTypeNames(); + auto paramTypes = _f->getParameterTypes(); auto returnNames = _f->getReturnParameterNames(); - auto returnTypes = _f->getReturnParameterTypeNames(); + auto returnTypes = _f->getReturnParameterTypes(); for (unsigned i = 0; i < paramNames.size(); ++i) - m_parameters.append(new QVariableDeclaration(paramNames[i], paramTypes[i])); + m_parameters.append(new QVariableDeclaration(_parent, paramNames[i], paramTypes[i].get())); for (unsigned i = 0; i < returnNames.size(); ++i) - m_returnParameters.append(new QVariableDeclaration(returnNames[i], returnTypes[i])); + m_returnParameters.append(new QVariableDeclaration(_parent, returnNames[i], returnTypes[i].get())); } diff --git a/mix/QFunctionDefinition.h b/mix/QFunctionDefinition.h index 0bbf093b5..18f2d911b 100644 --- a/mix/QFunctionDefinition.h +++ b/mix/QFunctionDefinition.h @@ -38,8 +38,9 @@ class QFunctionDefinition: public QBasicNodeDefinition Q_PROPERTY(QQmlListProperty parameters READ parameters) public: - QFunctionDefinition() {} - QFunctionDefinition(solidity::FunctionTypePointer const& _f); + QFunctionDefinition(){} + QFunctionDefinition(QObject* _parent): QBasicNodeDefinition(_parent) {} + QFunctionDefinition(QObject* _parent, solidity::FunctionTypePointer const& _f); /// Get all input parameters of this function. QList const& parametersList() const { return m_parameters; } /// Get all input parameters of this function as QML property. diff --git a/mix/QVariableDeclaration.cpp b/mix/QVariableDeclaration.cpp new file mode 100644 index 000000000..b2245e295 --- /dev/null +++ b/mix/QVariableDeclaration.cpp @@ -0,0 +1,65 @@ +/* + 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 . +*/ +/** @file QVariableDeclaration.h + * @author Yann yann@ethdev.com + * @date 2015 + */ + +#include "QVariableDeclaration.h" +#include "CodeModel.h" + +namespace dev +{ +namespace mix +{ + +QVariableDeclaration::QVariableDeclaration(QObject* _parent, solidity::VariableDeclaration const* _v): + QBasicNodeDefinition(_parent, _v), + m_type(new QSolidityType(this, CodeModel::nodeType(_v->getType().get()))) +{ +} + +QVariableDeclaration::QVariableDeclaration(QObject* _parent, std::string const& _name, SolidityType const& _type): + QBasicNodeDefinition(_parent, _name), + m_type(new QSolidityType(_parent, _type)) +{ +} + +QVariableDeclaration::QVariableDeclaration(QObject* _parent, std::string const& _name, solidity::Type const* _type): + QBasicNodeDefinition(_parent, _name), + m_type(new QSolidityType(this, CodeModel::nodeType(_type))) +{ +} + +QSolidityType::QSolidityType(QObject* _parent, SolidityType const& _type): + QObject(_parent), + m_type(_type.type), + m_size(_type.size), + m_name(_type.name) +{ + 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)); +} + +} +} + diff --git a/mix/QVariableDeclaration.h b/mix/QVariableDeclaration.h index fcd83cb30..e50832e52 100644 --- a/mix/QVariableDeclaration.h +++ b/mix/QVariableDeclaration.h @@ -20,34 +20,77 @@ */ #include -#include -#include +#include #include "QBasicNodeDefinition.h" +#include "SolidityType.h" #pragma once +namespace solidity +{ +class Type; +class VariableDeclaration; +} + namespace dev { namespace mix { +class QSolidityType: public QObject +{ + Q_OBJECT + Q_PROPERTY(int type READ type 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) + +public: + QSolidityType() {} + QSolidityType(QObject* _parent, SolidityType const& _type); + using Type = SolidityType::Type; + enum QmlType //TODO: arrays and structs + { + SignedInteger, + UnsignedInteger, + Hash, + Bool, + Address, + String, + 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; } + +private: + Type m_type; + int m_size; + QString m_name; + QVariantList m_members; +}; + class QVariableDeclaration: public QBasicNodeDefinition { Q_OBJECT - Q_PROPERTY(QString type READ type WRITE setType) + Q_PROPERTY(QSolidityType* type READ type CONSTANT) public: QVariableDeclaration() {} - QVariableDeclaration(solidity::VariableDeclaration const* _v): QBasicNodeDefinition(_v), m_type(QString::fromStdString(_v->getType()->toString())) {} - QVariableDeclaration(std::string const& _name, std::string const& _type): QBasicNodeDefinition(_name), m_type(QString::fromStdString(_type)) {} - QString type() const { return m_type; } - void setType(QString _type) { m_type = _type; } + QVariableDeclaration(QObject* _parent, solidity::VariableDeclaration const* _v); + QVariableDeclaration(QObject* _parent, std::string const& _name, SolidityType const& _type); + QVariableDeclaration(QObject* _parent, std::string const& _name, solidity::Type const* _type); + QSolidityType* type() const { return m_type; } + void setType(QSolidityType* _type) { m_type = _type; } private: - QString m_type; + QSolidityType* m_type; }; + } } - -Q_DECLARE_METATYPE(dev::mix::QVariableDeclaration*) diff --git a/mix/QVariableDefinition.cpp b/mix/QVariableDefinition.cpp index c78273f99..471fdd280 100644 --- a/mix/QVariableDefinition.cpp +++ b/mix/QVariableDefinition.cpp @@ -24,6 +24,7 @@ #include "QVariableDefinition.h" using namespace dev::mix; +/* int QVariableDefinitionList::rowCount(const QModelIndex& _parent) const { Q_UNUSED(_parent); @@ -56,9 +57,6 @@ QVariableDefinition* QVariableDefinitionList::val(int _idx) return m_def.at(_idx); } -/* - * QIntType - */ void QIntType::setValue(dev::bigint _value) { m_bigIntvalue = _value; @@ -84,9 +82,6 @@ void QIntType::decodeValue(dev::bytes const& _rawValue) setValue(un); } -/* - * QHashType - */ dev::bytes QHashType::encodeValue() { QByteArray bytesAr = value().toLocal8Bit(); @@ -100,9 +95,6 @@ void QHashType::decodeValue(dev::bytes const& _rawValue) setValue(QString::fromStdString(_ret)); } -/* - * QRealType - */ dev::bytes QRealType::encodeValue() { return bytes(); @@ -113,9 +105,6 @@ void QRealType::decodeValue(dev::bytes const& _rawValue) Q_UNUSED(_rawValue); } -/* - * QStringType - */ dev::bytes QStringType::encodeValue() { QByteArray b = value().toUtf8(); @@ -128,9 +117,6 @@ void QStringType::decodeValue(dev::bytes const& _rawValue) setValue(QString::fromUtf8((char*)_rawValue.data())); } -/* - * QBoolType - */ dev::bytes QBoolType::encodeValue() { return padded(jsToBytes(value().toStdString()), 32); @@ -143,3 +129,4 @@ void QBoolType::decodeValue(dev::bytes const& _rawValue) m_boolValue = boolRet; m_value = m_boolValue ? "1" : "0"; } +*/ diff --git a/mix/QVariableDefinition.h b/mix/QVariableDefinition.h index 8d890539b..70a663ee3 100644 --- a/mix/QVariableDefinition.h +++ b/mix/QVariableDefinition.h @@ -63,95 +63,9 @@ private: QVariableDeclaration* m_dec; }; -class QVariableDefinitionList: public QAbstractListModel -{ - Q_OBJECT - -public: - QVariableDefinitionList(QList _def): m_def(_def) {} - int rowCount(const QModelIndex& parent = QModelIndex()) const override; - QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; - QHash roleNames() const override; - /// Return the variable definition at index _idx. - QVariableDefinition* val(int _idx); - /// Return the list of variables. - QList def() { return m_def; } - -private: - QList m_def; -}; - -class QIntType: public QVariableDefinition -{ - Q_OBJECT -public: - QIntType() {} - QIntType(QVariableDeclaration* _def, QString _value): QVariableDefinition(_def, _value) {} - dev::bytes encodeValue() override; - void decodeValue(dev::bytes const& _rawValue) override; - /// @returns an instance of QBigInt for the current value. - QBigInt* toBigInt() { return new QBigInt(m_bigIntvalue); } - dev::bigint bigInt() { return m_bigIntvalue; } - void setValue(dev::bigint _value); - -private: - dev::bigint m_bigIntvalue; -}; - -class QRealType: public QVariableDefinition -{ - Q_OBJECT - -public: - QRealType() {} - QRealType(QVariableDeclaration* _def, QString _value): QVariableDefinition(_def, _value) {} - dev::bytes encodeValue() override; - void decodeValue(dev::bytes const& _rawValue) override; -}; -class QStringType: public QVariableDefinition -{ - Q_OBJECT - -public: - QStringType() {} - QStringType(QVariableDeclaration* _def, QString _value): QVariableDefinition(_def, _value) {} - dev::bytes encodeValue() override; - void decodeValue(dev::bytes const& _rawValue) override; -}; - -class QHashType: public QVariableDefinition -{ - Q_OBJECT - -public: - QHashType() {} - QHashType(QVariableDeclaration* _def, QString _value): QVariableDefinition(_def, _value) {} - dev::bytes encodeValue() override; - void decodeValue(dev::bytes const& _rawValue) override; -}; - -class QBoolType: public QVariableDefinition -{ - Q_OBJECT - -public: - QBoolType(): m_boolValue(false) {} - QBoolType(QVariableDeclaration* _def, QString _value): QVariableDefinition(_def, _value), m_boolValue(false) {} - dev::bytes encodeValue() override; - void decodeValue(dev::bytes const& _rawValue) override; - /// @returns the boolean value for the current definition. - bool toBool() { return m_boolValue; } - -private: - bool m_boolValue; -}; } } -Q_DECLARE_METATYPE(dev::mix::QIntType*) -Q_DECLARE_METATYPE(dev::mix::QStringType*) -Q_DECLARE_METATYPE(dev::mix::QHashType*) -Q_DECLARE_METATYPE(dev::mix::QBoolType*) diff --git a/mix/SolidityType.h b/mix/SolidityType.h new file mode 100644 index 000000000..7a0215cf5 --- /dev/null +++ b/mix/SolidityType.h @@ -0,0 +1,65 @@ +/* +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 . +*/ +/** @file SolidityType.h +* @author Yann yann@ethdev.com +* @author Arkadiy Paronyan arkadiy@ethdev.com +* @date 2015 +* Ethereum IDE client. +*/ + +#pragma once + +#include +#include + +namespace dev +{ +namespace mix +{ + +struct SolidityDeclaration; + +struct SolidityType +{ + enum Type //TODO: arrays and structs + { + SignedInteger, + UnsignedInteger, + Hash, + Bool, + Address, + String, + Enum, + Struct + }; + Type type; + unsigned size; //bytes, + bool array; + bool dynamicSize; + QString name; + std::vector members; + std::vector enumNames; +}; + +struct SolidityDeclaration +{ + QString name; + SolidityType type; +}; + +} +} diff --git a/mix/qml/QBoolType.qml b/mix/qml/QBoolType.qml deleted file mode 100644 index 9f5fe6fd7..000000000 --- a/mix/qml/QBoolType.qml +++ /dev/null @@ -1,7 +0,0 @@ -import QtQuick 2.0 -import org.ethereum.qml.QBoolType 1.0 - -QBoolType -{ -} - diff --git a/mix/qml/QBoolTypeView.qml b/mix/qml/QBoolTypeView.qml index a52601bdb..9911d4549 100644 --- a/mix/qml/QBoolTypeView.qml +++ b/mix/qml/QBoolTypeView.qml @@ -4,8 +4,10 @@ import QtQuick.Controls 1.3 Item { id: editRoot - property string text + property string value property string defaultValue + height: 20 + width: 150 Rectangle { anchors.fill: parent @@ -14,10 +16,10 @@ Item property bool inited: false Component.onCompleted: { - if (text === "") + if (value === "") currentIndex = parseInt(defaultValue); else - currentIndex = parseInt(text); + currentIndex = parseInt(value); inited = true } @@ -26,7 +28,7 @@ Item onCurrentIndexChanged: { if (inited) - text = comboModel.get(currentIndex).value; + value = comboModel.get(currentIndex).value; } model: ListModel { diff --git a/mix/qml/QHashType.qml b/mix/qml/QHashType.qml deleted file mode 100644 index cbd2618cf..000000000 --- a/mix/qml/QHashType.qml +++ /dev/null @@ -1,7 +0,0 @@ -import QtQuick 2.0 -import org.ethereum.qml.QHashType 1.0 - -QHashType -{ -} - diff --git a/mix/qml/QHashTypeView.qml b/mix/qml/QHashTypeView.qml index 73678f953..77da45365 100644 --- a/mix/qml/QHashTypeView.qml +++ b/mix/qml/QHashTypeView.qml @@ -2,8 +2,10 @@ import QtQuick 2.0 Item { - property alias text: textinput.text + property alias value: textinput.text id: editRoot + height: 20 + width: 150 SourceSansProBold { @@ -16,7 +18,7 @@ Item color: "#f7f7f7" TextInput { id: textinput - text: text + text: value anchors.fill: parent wrapMode: Text.WrapAnywhere clip: true diff --git a/mix/qml/QIntType.qml b/mix/qml/QIntType.qml deleted file mode 100644 index 241bd4a12..000000000 --- a/mix/qml/QIntType.qml +++ /dev/null @@ -1,7 +0,0 @@ -import QtQuick 2.0 -import org.ethereum.qml.QIntType 1.0 - -QIntType -{ -} - diff --git a/mix/qml/QIntTypeView.qml b/mix/qml/QIntTypeView.qml index 98344dd8b..206b641f3 100644 --- a/mix/qml/QIntTypeView.qml +++ b/mix/qml/QIntTypeView.qml @@ -1,9 +1,12 @@ import QtQuick 2.0 +import QtQuick.Layouts 1.1 Item { - property alias text: textinput.text + property alias value: textinput.text id: editRoot + height: 20 + width: 150 SourceSansProBold { @@ -16,7 +19,7 @@ Item color: "#f7f7f7" TextInput { id: textinput - text: text + text: value anchors.fill: parent font.family: boldFont.name clip: true diff --git a/mix/qml/QRealType.qml b/mix/qml/QRealType.qml deleted file mode 100644 index 9a015b1c7..000000000 --- a/mix/qml/QRealType.qml +++ /dev/null @@ -1,7 +0,0 @@ -import QtQuick 2.0 -import org.ethereum.qml.QRealType 1.0 - -QRealType -{ -} - diff --git a/mix/qml/QStringType.qml b/mix/qml/QStringType.qml deleted file mode 100644 index 4113fec20..000000000 --- a/mix/qml/QStringType.qml +++ /dev/null @@ -1,7 +0,0 @@ -import QtQuick 2.0 -import org.ethereum.qml.QStringType 1.0 - -QStringType -{ -} - diff --git a/mix/qml/QStringTypeView.qml b/mix/qml/QStringTypeView.qml index 016206e6d..0cde9b662 100644 --- a/mix/qml/QStringTypeView.qml +++ b/mix/qml/QStringTypeView.qml @@ -2,8 +2,10 @@ import QtQuick 2.0 Item { - property alias text: textinput.text + property alias value: textinput.text id: editRoot + height: 20 + width: 150 SourceSansProBold { @@ -16,7 +18,7 @@ Item color: "#f7f7f7" TextInput { id: textinput - text: text + text: value clip: true anchors.fill: parent wrapMode: Text.WrapAnywhere diff --git a/mix/qml/SolidityTypeConverter.qml b/mix/qml/SolidityTypeConverter.qml new file mode 100644 index 000000000..e70c7c201 --- /dev/null +++ b/mix/qml/SolidityTypeConverter.qml @@ -0,0 +1,10 @@ +import QtQuick 2.0 + +Item +{ + function toJson(value) + { + if ( + } +} + diff --git a/mix/qml/StateDialog.qml b/mix/qml/StateDialog.qml index 4d890fe18..b229ed433 100644 --- a/mix/qml/StateDialog.qml +++ b/mix/qml/StateDialog.qml @@ -373,7 +373,7 @@ Window { { iconSource: "qrc:/qml/img/edit.png" action: editAction - visible: !stdContract + visible: stdContract === false width: 10 height: 10 Action { diff --git a/mix/qml/StateListModel.qml b/mix/qml/StateListModel.qml index 6deeb9790..faa0af26f 100644 --- a/mix/qml/StateListModel.qml +++ b/mix/qml/StateListModel.qml @@ -41,38 +41,13 @@ Item { value: QEtherHelper.createEther(t.value.value, t.value.unit), gas: QEtherHelper.createBigInt(t.gas.value), gasPrice: QEtherHelper.createEther(t.gasPrice.value, t.gasPrice.unit), - stdContract: t.stdContract, + stdContract: t.stdContract ? true : false, parameters: {}, sender: t.sender }; - var qType = []; for (var key in t.parameters) - { - r.parameters[key] = t.parameters[key].value; - var type = t.parameters[key].type; - var varComponent; - if (type.indexOf("int") !== -1) - varComponent = Qt.createComponent("qrc:/qml/QIntType.qml"); - else if (type.indexOf("real") !== -1) - varComponent = Qt.createComponent("qrc:/qml/QRealType.qml"); - else if (type.indexOf("string") !== -1 || type.indexOf("text") !== -1) - varComponent = Qt.createComponent("qrc:/qml/QStringType.qml"); - else if (type.indexOf("hash") !== -1 || type.indexOf("address") !== -1) - varComponent = Qt.createComponent("qrc:/qml/QHashType.qml"); - else if (type.indexOf("bool") !== -1) - varComponent = Qt.createComponent("qrc:/qml/QBoolType.qml"); - else { - console.log("Unknown parameter type: " + type); - continue; - } + r.parameters[key] = t.parameters[key]; - var param = varComponent.createObject(stateListModel); - var dec = Qt.createComponent("qrc:/qml/QVariableDeclaration.qml"); - param.setDeclaration(dec.createObject(stateListModel, { "type": type })); - param.setValue(r.parameters[key]); - qType.push(param); - } - r.qType = qType; return r; } @@ -118,14 +93,7 @@ Item { parameters: {} }; for (var key in t.parameters) - { - var param = { - name: key, - value: t.parameters[key], - type: getParamType(key, t.qType) - } - r.parameters[key] = param; - } + r.parameters[key] = t.parameters[key]; return r; } diff --git a/mix/qml/StructView.qml b/mix/qml/StructView.qml new file mode 100644 index 000000000..98b840096 --- /dev/null +++ b/mix/qml/StructView.qml @@ -0,0 +1,182 @@ +import QtQuick 2.0 +import QtQuick.Controls 1.1 +import QtQuick.Layouts 1.1 +import org.ethereum.qml.QSolidityType 1.0 + +Item +{ + id: editRoot + property alias membersModel: repeater.model //js array + property var value + property int level: 0 + Column + { + id: paramRepeater + Layout.fillWidth: true + Layout.fillHeight: true + spacing: 3 + + Repeater + { + 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 + } + + DefaultLabel { + id: nameLabel + text: modelData.name + Layout.preferredWidth: 80 + } + + DefaultLabel { + id: equalLabel + text: "=" + Layout.preferredWidth: 15 + } + /* + Component.onCompleted: { + var t = type.type; + var src = undefined; + if (t === QSolidityType.SignedInteger || t === QSolidityType.UnsignedInteger) + src = "qrc:/qml/QIntTypeView.qml" + else if (t === QSolidityType.Bool) + src = "qrc:/qml/QBoolTypeView.qml" + else if (t === QSolidityType.String) + src = "qrc:/qml/QStringTypeView.qml" + else if (t === QSolidityType.Hash || t === QSolidityType.Address) + src = "qrc:/qml/QHashTypeView.qml" + else if (t === QSolidityType.Struct) + src = "qrc:/qml/StructView.qml"; + else + return null; + + typeLoader.setSource(src, { + height: 20, + width: 150, + value: typeLoader.getCurrent().value + }); + console.log(src); + } + */ + Loader + { + id: typeLoader + Layout.preferredWidth: 150 + + /* + Binding { + target: typeLoader.item + property: "membersModel" + value: type.members + when: typeLoader.status === Loader.Ready + }*/ + + + 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.String) + 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; + } + 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(); + }); + + } + + function getValue() + { + if (value && value[modelData.name]) + return value[modelData.name]; + else if (modelData.type.type === QSolidityType.Struct) + return {}; + return ""; + } + + Component + { + id: intViewComp + QIntTypeView + { + height: 20 + width: 150 + id: intView + } + } + + Component + { + id: boolViewComp + QBoolTypeView + { + height: 20 + width: 150 + id: boolView + defaultValue: "1" + Component.onCompleted: + { + var current = getValue() + (current === "" ? text = defaultValue : text = current); + } + } + } + + Component + { + id: stringViewComp + QStringTypeView + { + height: 20 + width: 150 + id: stringView + } + } + + Component + { + id: hashViewComp + QHashTypeView + { + height: 20 + width: 150 + id: hashView + } + } + + } + } + } + } +} diff --git a/mix/qml/TransactionDialog.qml b/mix/qml/TransactionDialog.qml index 997f78779..0686cf201 100644 --- a/mix/qml/TransactionDialog.qml +++ b/mix/qml/TransactionDialog.qml @@ -11,26 +11,24 @@ Window { id: modalTransactionDialog modality: Qt.ApplicationModal width: 520 - height: (paramsModel.count > 0 ? 500 : 300) + height: 500;//(paramsModel.count > 0 ? 500 : 300) visible: false color: StateDialogStyle.generic.backgroundColor title: qsTr("Edit Transaction") property int transactionIndex - property alias transactionParams: paramsModel; property alias gas: gasValueEdit.gasValue; property alias gasPrice: gasPriceField.value; property alias transactionValue: valueField.value; property string contractId: contractComboBox.currentValue(); property alias functionId: functionComboBox.currentText; - property var itemParams; + property var paramValues; + property var paramsModel: []; property bool useTransactionDefaultValue: false - property var qType; property alias stateAccounts: senderComboBox.model signal accepted; function open(index, item) { - qType = []; rowFunction.visible = !useTransactionDefaultValue; rowValue.visible = !useTransactionDefaultValue; rowGas.visible = !useTransactionDefaultValue; @@ -44,7 +42,7 @@ Window { var functionId = item.functionId; rowFunction.visible = true; - itemParams = item.parameters !== undefined ? item.parameters : {}; + paramValues = item.parameters !== undefined ? item.parameters : {}; if (item.sender) senderComboBox.select(item.sender); @@ -73,15 +71,15 @@ Window { functionComboBox.currentIndex = functionIndex; - paramsModel.clear(); + paramsModel = []; if (functionId !== contractComboBox.currentValue()) loadParameters(); else { var contract = codeModel.contracts[contractId]; if (contract) { - var parameters = contract.contract.constructor.parameters; - for (var p = 0; p < parameters.length; p++) - loadParameter(parameters[p]); + var params = contract.contract.constructor.params; + for (var p = 0; p < params.length; p++) + loadParameter(params[p]); } } modalTransactionDialog.setX((Screen.width - width) / 2); @@ -110,32 +108,11 @@ Window { { var type = parameter.type; var pname = parameter.name; - var varComponent; - - if (type.indexOf("int") !== -1) - varComponent = Qt.createComponent("qrc:/qml/QIntType.qml"); - else if (type.indexOf("real") !== -1) - varComponent = Qt.createComponent("qrc:/qml/QRealType.qml"); - else if (type.indexOf("string") !== -1 || type.indexOf("text") !== -1) - varComponent = Qt.createComponent("qrc:/qml/QStringType.qml"); - else if (type.indexOf("hash") !== -1 || type.indexOf("address") !== -1) - varComponent = Qt.createComponent("qrc:/qml/QHashType.qml"); - else if (type.indexOf("bool") !== -1) - varComponent = Qt.createComponent("qrc:/qml/QBoolType.qml"); - - var param = varComponent.createObject(modalTransactionDialog); - var value = itemParams[pname] !== undefined ? itemParams[pname] : ""; - - param.setValue(value); - param.setDeclaration(parameter); - qType.push({ name: pname, value: param }); - paramsModel.append({ name: pname, type: type, value: value }); + paramsModel.push({ name: pname, type: type }); } function loadParameters() { - paramsModel.clear(); - if (!paramsModel) - return; + paramsModel = [] if (functionComboBox.currentIndex >= 0 && functionComboBox.currentIndex < functionsModel.count) { var contract = codeModel.contracts[contractComboBox.currentValue()]; if (contract) { @@ -147,31 +124,29 @@ Window { } } } + typeLoader.value = {} + typeLoader.membersModel = [] + typeLoader.value = paramValues; + typeLoader.membersModel = paramsModel; + } + /* function param(name) { - for (var k = 0; k < paramsModel.count; k++) + for (var k = 0; k < paramsModel.length; k++) { - if (paramsModel.get(k).name === name) - return paramsModel.get(k); + if (paramsModel[k].name === name) + return paramsModel[k]; } } + */ function close() { visible = false; } - function qTypeParam(name) - { - for (var k in qType) - { - if (qType[k].name === name) - return qType[k].value; - } - } - function getItem() { var item; @@ -194,15 +169,7 @@ Window { } item.sender = senderComboBox.model[senderComboBox.currentIndex].secret; - var orderedQType = []; - for (var p = 0; p < transactionDialog.transactionParams.count; p++) { - var parameter = transactionDialog.transactionParams.get(p); - var qtypeParam = qTypeParam(parameter.name); - qtypeParam.setValue(parameter.value); - orderedQType.push(qtypeParam); - item.parameters[parameter.name] = parameter.value; - } - item.qType = orderedQType; + item.parameters = paramValues; return item; } @@ -370,7 +337,7 @@ Window { id: paramLabel text: qsTr("Parameters:") Layout.preferredWidth: 75 - visible: paramsModel.count > 0 + visible: true;//paramsModel.length > 0 } ScrollView @@ -379,128 +346,19 @@ Window { anchors.topMargin: 10 Layout.preferredWidth: 350 Layout.fillHeight: true - visible: paramsModel.count > 0 + visible: true;//paramsModel.length > 0 Column { id: paramRepeater Layout.fillWidth: true Layout.fillHeight: true spacing: 3 - Repeater - { - height: 20 * paramsModel.count - model: paramsModel - visible: paramsModel.count > 0 - RowLayout - { - id: row - Layout.fillWidth: true - height: 20 - DefaultLabel { - id: typeLabel - text: type - Layout.preferredWidth: 50 - } - DefaultLabel { - id: nameLabel - text: name - Layout.preferredWidth: 80 - } - - DefaultLabel { - id: equalLabel - text: "=" - Layout.preferredWidth: 15 - } - - Loader - { - id: typeLoader - Layout.preferredWidth: 150 - function getCurrent() - { - return modalTransactionDialog.param(name); - } - - Connections { - target: typeLoader.item - onTextChanged: { - typeLoader.getCurrent().value = typeLoader.item.text; - } - } - - sourceComponent: - { - if (type.indexOf("int") !== -1) - return intViewComp; - else if (type.indexOf("bool") !== -1) - return boolViewComp; - else if (type.indexOf("string") !== -1) - return stringViewComp; - else if (type.indexOf("hash") !== -1 || type.indexOf("address") !== -1) - return hashViewComp; - else - return null; - } - - Component - { - id: intViewComp - QIntTypeView - { - height: 20 - width: 150 - id: intView - text: typeLoader.getCurrent().value - } - } - - Component - { - id: boolViewComp - QBoolTypeView - { - height: 20 - width: 150 - id: boolView - defaultValue: "1" - Component.onCompleted: - { - var current = typeLoader.getCurrent().value; - (current === "" ? text = defaultValue : text = current); - } - } - } - - Component - { - id: stringViewComp - QStringTypeView - { - height: 20 - width: 150 - id: stringView - text: - { - return typeLoader.getCurrent().value - } - } - } - - Component - { - id: hashViewComp - QHashTypeView - { - height: 20 - width: 150 - id: hashView - text: typeLoader.getCurrent().value - } - } - } - } + StructView + { + id: typeLoader + Layout.preferredWidth: 150 + membersModel: paramsModel; } } } @@ -508,7 +366,7 @@ Window { CommonSeparator { Layout.fillWidth: true - visible: paramsModel.count > 0 + visible: paramsModel.length > 0 } } @@ -530,8 +388,4 @@ Window { } } } - - ListModel { - id: paramsModel - } } diff --git a/mix/res.qrc b/mix/res.qrc index e953b3e35..9cca4a859 100644 --- a/mix/res.qrc +++ b/mix/res.qrc @@ -44,13 +44,8 @@ qml/EtherValue.qml qml/BigIntValue.qml qml/QVariableDefinition.qml - qml/QBoolType.qml - qml/QHashType.qml - qml/QIntType.qml - qml/QRealType.qml qml/js/QEtherHelper.js qml/js/TransactionHelper.js - qml/QStringType.qml qml/QBoolTypeView.qml qml/QIntTypeView.qml qml/QRealTypeView.qml @@ -115,5 +110,7 @@ qml/img/copy.png qml/img/broom.png qml/LogsPaneStyle.qml + qml/SolidityTypeConverter.qml + qml/StructView.qml From ddc3ddb21ed0111dbcc13401b8a0edb0d65ca35e Mon Sep 17 00:00:00 2001 From: arkpar Date: Sun, 15 Mar 2015 18:05:23 +0100 Subject: [PATCH 3/9] merged latest develop --- mix/ContractCallDataEncoder.cpp | 2 +- mix/SolidityType.h | 2 +- mix/qml/StructView.qml | 88 +-------------------------------- 3 files changed, 3 insertions(+), 89 deletions(-) diff --git a/mix/ContractCallDataEncoder.cpp b/mix/ContractCallDataEncoder.cpp index 54f828566..4e8b808b1 100644 --- a/mix/ContractCallDataEncoder.cpp +++ b/mix/ContractCallDataEncoder.cpp @@ -122,7 +122,7 @@ QStringList ContractCallDataEncoder::decode(QList const& r.append(toString(decodeInt(rawParam))); else if (type == QSolidityType::Type::Bool) r.append(toString(decodeBool(rawParam))); - else if (type == QSolidityType::Type::String || type == QSolidityType::Type::Hash) + 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 diff --git a/mix/SolidityType.h b/mix/SolidityType.h index 7a0215cf5..c35f4285d 100644 --- a/mix/SolidityType.h +++ b/mix/SolidityType.h @@ -42,7 +42,7 @@ struct SolidityType Hash, Bool, Address, - String, + Bytes, Enum, Struct }; diff --git a/mix/qml/StructView.qml b/mix/qml/StructView.qml index 98b840096..ba3c1847f 100644 --- a/mix/qml/StructView.qml +++ b/mix/qml/StructView.qml @@ -42,45 +42,10 @@ Item text: "=" Layout.preferredWidth: 15 } - /* - Component.onCompleted: { - var t = type.type; - var src = undefined; - if (t === QSolidityType.SignedInteger || t === QSolidityType.UnsignedInteger) - src = "qrc:/qml/QIntTypeView.qml" - else if (t === QSolidityType.Bool) - src = "qrc:/qml/QBoolTypeView.qml" - else if (t === QSolidityType.String) - src = "qrc:/qml/QStringTypeView.qml" - else if (t === QSolidityType.Hash || t === QSolidityType.Address) - src = "qrc:/qml/QHashTypeView.qml" - else if (t === QSolidityType.Struct) - src = "qrc:/qml/StructView.qml"; - else - return null; - - typeLoader.setSource(src, { - height: 20, - width: 150, - value: typeLoader.getCurrent().value - }); - console.log(src); - } - */ Loader { id: typeLoader Layout.preferredWidth: 150 - - /* - Binding { - target: typeLoader.item - property: "membersModel" - value: type.members - when: typeLoader.status === Loader.Ready - }*/ - - sourceComponent: { var t = modelData.type.type; @@ -88,7 +53,7 @@ Item return Qt.createComponent("qrc:/qml/QIntTypeView.qml"); else if (t === QSolidityType.Bool) return Qt.createComponent("qrc:/qml/QBoolTypeView.qml"); - else if (t === QSolidityType.String) + 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"); @@ -124,57 +89,6 @@ Item return {}; return ""; } - - Component - { - id: intViewComp - QIntTypeView - { - height: 20 - width: 150 - id: intView - } - } - - Component - { - id: boolViewComp - QBoolTypeView - { - height: 20 - width: 150 - id: boolView - defaultValue: "1" - Component.onCompleted: - { - var current = getValue() - (current === "" ? text = defaultValue : text = current); - } - } - } - - Component - { - id: stringViewComp - QStringTypeView - { - height: 20 - width: 150 - id: stringView - } - } - - Component - { - id: hashViewComp - QHashTypeView - { - height: 20 - width: 150 - id: hashView - } - } - } } } From 2da3c83f2e2729597cd5853e59f645e86bac0570 Mon Sep 17 00:00:00 2001 From: arkpar Date: Sun, 15 Mar 2015 18:33:13 +0100 Subject: [PATCH 4/9] adopted new ethereum.js and solidity types --- mix/qml/html/WebContainer.html | 3 ++- mix/stdc/std.sol | 32 ++++++++++++++++---------------- 2 files changed, 18 insertions(+), 17 deletions(-) diff --git a/mix/qml/html/WebContainer.html b/mix/qml/html/WebContainer.html index 8cd65a55a..fb716507f 100644 --- a/mix/qml/html/WebContainer.html +++ b/mix/qml/html/WebContainer.html @@ -20,7 +20,8 @@ updateContracts = function(contracts) { window.web3.reset(); window.contracts = {}; for (var c in contracts) { - var contract = window.web3.eth.contract(contracts[c].address, contracts[c].interface); + var contractProto = window.web3.eth.contract(contracts[c].interface); + var contract = new contractProto(contracts[c].address); window.contracts[c] = { address: c.address, interface: c.interface, diff --git a/mix/stdc/std.sol b/mix/stdc/std.sol index 97a74ac56..b482db67e 100644 --- a/mix/stdc/std.sol +++ b/mix/stdc/std.sol @@ -13,14 +13,14 @@ contract Config is mortal { if (tx.origin != owner) return; services[id] = service; - log1(0, id); + log1(0, bytes32(id)); } function unregister(uint id) { if (msg.sender != owner && services[id] != msg.sender) return; services[id] = address(0); - log1(0, id); + log1(0, bytes32(id)); } function lookup(uint service) constant returns(address a) { @@ -56,8 +56,8 @@ web3.eth.contract(addrConfig, abiConfig).lookup(1).call().then(function(r){ addr // Gav Wood contract NameRegister { - function getAddress(string32 _name) constant returns (address o_owner) {} - function getName(address _owner) constant returns (string32 o_name) {} + function getAddress(bytes32 _name) constant returns (address o_owner) {} + function getName(address _owner) constant returns (bytes32 o_name) {} } contract NameReg is owned, NameRegister { @@ -68,11 +68,11 @@ contract NameReg is owned, NameRegister { toName[this] = "NameReg"; toAddress["NameReg"] = this; Config(addrConfig).register(1, this); - log1(0, hash256(addrConfig)); - log1(0, hash256(this)); + //log1(0, bytes32(addrConfig)); + //log1(0, bytes32(this)); } - function register(string32 name) { + function register(bytes32 name) { // Don't allow the same name to be overwritten. if (toAddress[name] != address(0)) return; @@ -82,41 +82,41 @@ contract NameReg is owned, NameRegister { toName[msg.sender] = name; toAddress[name] = msg.sender; - log1(0, hash256(msg.sender)); + //log1(0, bytes32(msg.sender)); } function unregister() { - string32 n = toName[msg.sender]; + bytes32 n = toName[msg.sender]; if (n == "") return; - log1(0, hash256(toAddress[n])); + //log1(0, bytes32(toAddress[n])); toName[msg.sender] = ""; toAddress[n] = address(0); } - function addressOf(string32 name) constant returns (address addr) { + function addressOf(bytes32 name) constant returns (address addr) { return toAddress[name]; } - function nameOf(address addr) constant returns (string32 name) { + function nameOf(address addr) constant returns (bytes32 name) { return toName[addr]; } - mapping (address => string32) toName; - mapping (string32 => address) toAddress; + mapping (address => bytes32) toName; + mapping (bytes32 => address) toAddress; } /* // Solidity Interface: -contract NameReg{function kill(){}function register(string32 name){}function addressOf(string32 name)constant returns(address addr){}function unregister(){}function nameOf(address addr)constant returns(string32 name){}} +contract NameReg{function kill(){}function register(bytes32 name){}function addressOf(bytes32 name)constant returns(address addr){}function unregister(){}function nameOf(address addr)constant returns(bytes32 name){}} // Example Solidity use: NameReg(addrNameReg).register("Some Contract"); // JS Interface: -var abiNameReg = [{"constant":true,"inputs":[{"name":"name","type":"string32"}],"name":"addressOf","outputs":[{"name":"addr","type":"address"}]},{"constant":false,"inputs":[],"name":"kill","outputs":[]},{"constant":true,"inputs":[{"name":"addr","type":"address"}],"name":"nameOf","outputs":[{"name":"name","type":"string32"}]},{"constant":false,"inputs":[{"name":"name","type":"string32"}],"name":"register","outputs":[]},{"constant":false,"inputs":[],"name":"unregister","outputs":[]}]; +var abiNameReg = [{"constant":true,"inputs":[{"name":"name","type":"bytes32"}],"name":"addressOf","outputs":[{"name":"addr","type":"address"}]},{"constant":false,"inputs":[],"name":"kill","outputs":[]},{"constant":true,"inputs":[{"name":"addr","type":"address"}],"name":"nameOf","outputs":[{"name":"name","type":"bytes32"}]},{"constant":false,"inputs":[{"name":"name","type":"bytes32"}],"name":"register","outputs":[]},{"constant":false,"inputs":[],"name":"unregister","outputs":[]}]; // Example JS use: web3.eth.contract(addrNameReg, abiNameReg).register("My Name").transact(); From f994da400f57c945e328c67b40fe89d9c6d177f4 Mon Sep 17 00:00:00 2001 From: arkpar Date: Mon, 16 Mar 2015 15:21:38 +0100 Subject: [PATCH 5/9] debug formatting for structs and arrays --- mix/ClientModel.cpp | 82 ++++++++++------- mix/ClientModel.h | 4 +- mix/CodeModel.cpp | 8 +- mix/ContractCallDataEncoder.cpp | 103 ++++++++++++++++----- mix/ContractCallDataEncoder.h | 7 ++ mix/DebuggingStateWrapper.h | 14 +-- mix/QContractDefinition.cpp | 7 +- mix/QVariableDeclaration.cpp | 21 +++-- mix/QVariableDeclaration.h | 18 ++-- mix/QVariableDefinition.cpp | 132 --------------------------- mix/qml/DebugInfoList.qml | 69 ++++++++------ mix/qml/Debugger.qml | 4 +- mix/qml/SolidityTypeConverter.qml | 10 --- mix/qml/StructView.qml | 144 +++++++++++++++--------------- mix/qml/TransactionDialog.qml | 35 ++------ mix/qml/VariablesView.qml | 39 ++++++++ mix/qml/js/Debugger.js | 8 +- mix/res.qrc | 2 +- 18 files changed, 342 insertions(+), 365 deletions(-) delete mode 100644 mix/QVariableDefinition.cpp delete mode 100644 mix/qml/SolidityTypeConverter.qml create mode 100644 mix/qml/VariablesView.qml diff --git a/mix/ClientModel.cpp b/mix/ClientModel.cpp index 2523a0d91..450f28433 100644 --- a/mix/ClientModel.cpp +++ b/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(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 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 solLocals; // - QList returnStack; + QVariantList solCallStack; + std::map solLocals; // + std::map storageDeclarations; // 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::max()) { auto storageIter = contract->storage().find(static_cast(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() diff --git a/mix/ClientModel.h b/mix/ClientModel.h index a12fe22e6..5c3615a2b 100644 --- a/mix/ClientModel.h +++ b/mix/ClientModel.h @@ -63,7 +63,7 @@ struct TransactionSettings /// Gas price u256 gasPrice; /// Mapping from contract function parameter name to value - QList 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 m_running; diff --git a/mix/CodeModel.cpp b/mix/CodeModel.cpp index 72359c130..8af9e465c 100644 --- a/mix/CodeModel.cpp +++ b/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(), std::vector() }; 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(_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; diff --git a/mix/ContractCallDataEncoder.cpp b/mix/ContractCallDataEncoder.cpp index 4e8b808b1..fc5dcee03 100644 --- a/mix/ContractCallDataEncoder.cpp +++ b/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(_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 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(_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; } diff --git a/mix/ContractCallDataEncoder.h b/mix/ContractCallDataEncoder.h index 9b5f8355b..3fa165d3f 100644 --- a/mix/ContractCallDataEncoder.h +++ b/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 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; }; } diff --git a/mix/DebuggingStateWrapper.h b/mix/DebuggingStateWrapper.h index 7eb8c932c..b9eea9365 100644 --- a/mix/DebuggingStateWrapper.h +++ b/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; }; diff --git a/mix/QContractDefinition.cpp b/mix/QContractDefinition.cpp index b08979ae4..899e804c5 100644 --- a/mix/QContractDefinition.cpp +++ b/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 diff --git a/mix/QVariableDeclaration.cpp b/mix/QVariableDeclaration.cpp index b2245e295..7a08da116 100644 --- a/mix/QVariableDeclaration.cpp +++ b/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; } } diff --git a/mix/QVariableDeclaration.h b/mix/QVariableDeclaration.h index e50832e52..3fcc00dcc 100644 --- a/mix/QVariableDeclaration.h +++ b/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 diff --git a/mix/QVariableDefinition.cpp b/mix/QVariableDefinition.cpp deleted file mode 100644 index 471fdd280..000000000 --- a/mix/QVariableDefinition.cpp +++ /dev/null @@ -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 . -*/ -/** @file QVariableDefinition.h - * @author Yann yann@ethdev.com - * @date 2014 - */ - -#include -#include -#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 QVariableDefinitionList::roleNames() const -{ - QHash 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(_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"; -} -*/ diff --git a/mix/qml/DebugInfoList.qml b/mix/qml/DebugInfoList.qml index ae7e6fabe..721d5540b 100644 --- a/mix/qml/DebugInfoList.qml +++ b/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 + } } } } diff --git a/mix/qml/Debugger.qml b/mix/qml/Debugger.qml index 732d02f75..e73f8d668 100644 --- a/mix/qml/Debugger.qml +++ b/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 diff --git a/mix/qml/SolidityTypeConverter.qml b/mix/qml/SolidityTypeConverter.qml deleted file mode 100644 index e70c7c201..000000000 --- a/mix/qml/SolidityTypeConverter.qml +++ /dev/null @@ -1,10 +0,0 @@ -import QtQuick 2.0 - -Item -{ - function toJson(value) - { - if ( - } -} - diff --git a/mix/qml/StructView.qml b/mix/qml/StructView.qml index ba3c1847f..cbd457947 100644 --- a/mix/qml/StructView.qml +++ b/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 ""; } } } diff --git a/mix/qml/TransactionDialog.qml b/mix/qml/TransactionDialog.qml index 0686cf201..64d62de69 100644 --- a/mix/qml/TransactionDialog.qml +++ b/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; } } diff --git a/mix/qml/VariablesView.qml b/mix/qml/VariablesView.qml new file mode 100644 index 000000000..36105da9e --- /dev/null +++ b/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; + } +} + diff --git a/mix/qml/js/Debugger.js b/mix/qml/js/Debugger.js index 23aa81844..3f5742fde 100644 --- a/mix/qml/js/Debugger.js +++ b/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 = []; } } diff --git a/mix/res.qrc b/mix/res.qrc index f20332eec..fa50d6dd8 100644 --- a/mix/res.qrc +++ b/mix/res.qrc @@ -110,8 +110,8 @@ qml/img/copy.png qml/img/broom.png qml/LogsPaneStyle.qml - qml/SolidityTypeConverter.qml qml/StructView.qml qml/img/console.png + qml/VariablesView.qml From 534bd2a2f3546ec1edc8a81432cd6b8de045fdac Mon Sep 17 00:00:00 2001 From: arkpar Date: Mon, 16 Mar 2015 15:29:16 +0100 Subject: [PATCH 6/9] fixed msvc build: --- mix/CodeModel.cpp | 3 ++- mix/CodeModel.h | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/mix/CodeModel.cpp b/mix/CodeModel.cpp index f033c3405..51c91c3bf 100644 --- a/mix/CodeModel.cpp +++ b/mix/CodeModel.cpp @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -308,7 +309,7 @@ dev::bytes const& CodeModel::getStdContractCode(const QString& _contractName, co return m_compiledContracts.at(_contractName); } -SolidityType CodeModel::nodeType(solidity::Type const* _type) +SolidityType CodeModel::nodeType(dev::solidity::Type const* _type) { SolidityType r { SolidityType::Type::UnsignedInteger, 32, false, false, QString::fromStdString(_type->toString()), std::vector(), std::vector() }; if (!_type) diff --git a/mix/CodeModel.h b/mix/CodeModel.h index 758cef48a..8f84b103d 100644 --- a/mix/CodeModel.h +++ b/mix/CodeModel.h @@ -148,7 +148,7 @@ public: /// Reset code model Q_INVOKABLE void reset() { reset(QVariantMap()); } /// Convert solidity type info to mix type - static SolidityType nodeType(solidity::Type const* _type); + static SolidityType nodeType(dev::solidity::Type const* _type); signals: /// Emited on compilation state change From 6fd6d296626bd13bcde85d50a90672eef2bc0600 Mon Sep 17 00:00:00 2001 From: arkpar Date: Mon, 16 Mar 2015 15:44:05 +0100 Subject: [PATCH 7/9] style --- mix/ClientModel.cpp | 2 -- mix/CodeModel.cpp | 1 - mix/QVariableDeclaration.cpp | 3 ++- mix/QVariableDeclaration.h | 4 +++- mix/SolidityType.h | 11 ++++++----- mix/qml/StructView.qml | 2 -- mix/qml/TransactionDialog.qml | 9 +++++---- mix/qml/VariablesView.qml | 2 +- 8 files changed, 17 insertions(+), 17 deletions(-) diff --git a/mix/ClientModel.cpp b/mix/ClientModel.cpp index 450f28433..f12bcc1d8 100644 --- a/mix/ClientModel.cpp +++ b/mix/ClientModel.cpp @@ -355,9 +355,7 @@ 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()] = new QVariableDeclaration(debugData, localIter.value().name.toStdString(), localIter.value().type); - } } if (instruction.type() == dev::eth::Tag) diff --git a/mix/CodeModel.cpp b/mix/CodeModel.cpp index 8af9e465c..f033c3405 100644 --- a/mix/CodeModel.cpp +++ b/mix/CodeModel.cpp @@ -371,7 +371,6 @@ SolidityType CodeModel::nodeType(solidity::Type const* _type) case Type::Category::Void: default: break; - //BOOST_THROW_EXCEPTION(dev::Exception() << errinfo_comment("Unsupported solidityType: " + _type->toString())); } return r; } diff --git a/mix/QVariableDeclaration.cpp b/mix/QVariableDeclaration.cpp index 7a08da116..391d26c04 100644 --- a/mix/QVariableDeclaration.cpp +++ b/mix/QVariableDeclaration.cpp @@ -14,8 +14,9 @@ You should have received a copy of the GNU General Public License along with cpp-ethereum. If not, see . */ -/** @file QVariableDeclaration.h +/** @file QVariableDeclaration.app * @author Yann yann@ethdev.com + * @author Arkadiy Paronyan arkadiy@ethdev.com * @date 2015 */ diff --git a/mix/QVariableDeclaration.h b/mix/QVariableDeclaration.h index 3fcc00dcc..cf9345061 100644 --- a/mix/QVariableDeclaration.h +++ b/mix/QVariableDeclaration.h @@ -37,6 +37,7 @@ namespace dev namespace mix { +/// UI wrapper around solidity type class QSolidityType: public QObject { Q_OBJECT @@ -49,7 +50,7 @@ public: QSolidityType() {} QSolidityType(QObject* _parent, SolidityType const& _type); using Type = SolidityType::Type; - enum QmlType //TODO: arrays and structs + enum QmlType //TODO: Q_ENUMS does not support enum forwarding. Keep in sync with SolidityType::Type { SignedInteger, UnsignedInteger, @@ -72,6 +73,7 @@ private: SolidityType m_type; }; +/// UI wrapper around declaration (name + type) class QVariableDeclaration: public QBasicNodeDefinition { Q_OBJECT diff --git a/mix/SolidityType.h b/mix/SolidityType.h index c35f4285d..9990e2e7f 100644 --- a/mix/SolidityType.h +++ b/mix/SolidityType.h @@ -33,13 +33,14 @@ namespace mix struct SolidityDeclaration; +//Type info extracted from solidity AST struct SolidityType { - enum Type //TODO: arrays and structs + enum Type //keep in sync with QSolidity::Type { SignedInteger, UnsignedInteger, - Hash, + Hash, //TODO: remove Bool, Address, Bytes, @@ -47,12 +48,12 @@ struct SolidityType Struct }; Type type; - unsigned size; //bytes, + unsigned size; //in bytes, bool array; bool dynamicSize; QString name; - std::vector members; - std::vector enumNames; + std::vector members; //for struct + std::vector enumNames; //for enum }; struct SolidityDeclaration diff --git a/mix/qml/StructView.qml b/mix/qml/StructView.qml index cbd457947..021365ac8 100644 --- a/mix/qml/StructView.qml +++ b/mix/qml/StructView.qml @@ -8,7 +8,6 @@ Column id: root property alias members: repeater.model //js array property var value : { x: "333" } - property int level: 0 Layout.fillWidth: true Repeater @@ -65,7 +64,6 @@ Column 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; } diff --git a/mix/qml/TransactionDialog.qml b/mix/qml/TransactionDialog.qml index 64d62de69..5d98d3dbd 100644 --- a/mix/qml/TransactionDialog.qml +++ b/mix/qml/TransactionDialog.qml @@ -11,7 +11,7 @@ Window { id: modalTransactionDialog modality: Qt.ApplicationModal width: 520 - height: 500;//(paramsModel.count > 0 ? 500 : 300) + height: 500; visible: false color: StateDialogStyle.generic.backgroundColor title: qsTr("Edit Transaction") @@ -25,7 +25,6 @@ Window { property var paramsModel: []; property bool useTransactionDefaultValue: false property alias stateAccounts: senderComboBox.model - signal accepted; function open(index, item) { @@ -87,6 +86,9 @@ Window { visible = true; valueField.focus = true; + modalTransactionDialog.height = (paramsModel.length > 0 ? 500 : 300); + paramLabel.visible = paramsModel.length > 0; + paramScroll.visible = paramsModel.length > 0; } function loadFunctions(contractId) @@ -326,16 +328,15 @@ Window { id: paramLabel text: qsTr("Parameters:") Layout.preferredWidth: 75 - visible: true;//paramsModel.length > 0 } ScrollView { + id: paramScroll anchors.top: paramLabel.bottom anchors.topMargin: 10 Layout.fillWidth: true Layout.fillHeight: true - visible: true;//paramsModel.length > 0 StructView { id: typeLoader diff --git a/mix/qml/VariablesView.qml b/mix/qml/VariablesView.qml index 36105da9e..191ec52af 100644 --- a/mix/qml/VariablesView.qml +++ b/mix/qml/VariablesView.qml @@ -32,7 +32,7 @@ DebugInfoList function setData(members, values) { storage.item.value = {}; storage.item.members = []; - storage.item.value = values; + storage.item.value = values; //TODO: use a signal for this? storage.item.members = members; } } From 735ddacaa03792a64048c8a89a86ccc5c4904340 Mon Sep 17 00:00:00 2001 From: arkpar Date: Mon, 16 Mar 2015 15:44:20 +0100 Subject: [PATCH 8/9] removed logs from std contracts --- mix/stdc/std.sol | 6 ------ 1 file changed, 6 deletions(-) diff --git a/mix/stdc/std.sol b/mix/stdc/std.sol index b482db67e..3e9755e6a 100644 --- a/mix/stdc/std.sol +++ b/mix/stdc/std.sol @@ -13,14 +13,12 @@ contract Config is mortal { if (tx.origin != owner) return; services[id] = service; - log1(0, bytes32(id)); } function unregister(uint id) { if (msg.sender != owner && services[id] != msg.sender) return; services[id] = address(0); - log1(0, bytes32(id)); } function lookup(uint service) constant returns(address a) { @@ -68,8 +66,6 @@ contract NameReg is owned, NameRegister { toName[this] = "NameReg"; toAddress["NameReg"] = this; Config(addrConfig).register(1, this); - //log1(0, bytes32(addrConfig)); - //log1(0, bytes32(this)); } function register(bytes32 name) { @@ -82,14 +78,12 @@ contract NameReg is owned, NameRegister { toName[msg.sender] = name; toAddress[name] = msg.sender; - //log1(0, bytes32(msg.sender)); } function unregister() { bytes32 n = toName[msg.sender]; if (n == "") return; - //log1(0, bytes32(toAddress[n])); toName[msg.sender] = ""; toAddress[n] = address(0); } From f9fdbb186121354aee7ecc79b84c6648c7724b4c Mon Sep 17 00:00:00 2001 From: arkpar Date: Mon, 16 Mar 2015 17:08:30 +0100 Subject: [PATCH 9/9] removed default value --- mix/qml/StructView.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mix/qml/StructView.qml b/mix/qml/StructView.qml index 021365ac8..2935e6c72 100644 --- a/mix/qml/StructView.qml +++ b/mix/qml/StructView.qml @@ -7,7 +7,7 @@ Column { id: root property alias members: repeater.model //js array - property var value : { x: "333" } + property var value : { } Layout.fillWidth: true Repeater