Browse Source

Merge branch 'develop' of github.com:ethereum/cpp-ethereum into develop

cl-refactor
Gav Wood 10 years ago
parent
commit
76a2de718c
  1. 2
      libevm/VM.h
  2. 40
      libevmcore/Assembly.cpp
  3. 2
      libevmcore/Assembly.h
  4. 5
      libevmcore/AssemblyItem.h
  5. 75
      libevmcore/CommonSubexpressionEliminator.cpp
  6. 17
      libevmcore/CommonSubexpressionEliminator.h
  7. 107
      libevmcore/SemanticInformation.cpp
  8. 50
      libevmcore/SemanticInformation.h
  9. 16
      libsolidity/AST.cpp
  10. 17
      libsolidity/Types.cpp
  11. 2
      libsolidity/Types.h
  12. 21
      mix/CodeModel.cpp
  13. 1
      mix/qml.qrc
  14. 9
      mix/qml/CodeEditorView.qml
  15. 27
      mix/qml/Debugger.qml
  16. 584
      mix/qml/LogsPane.qml
  17. 18
      mix/qml/LogsPaneStyle.qml
  18. 1
      mix/qml/ProjectModel.qml
  19. 260
      mix/qml/StatesComboBox.qml
  20. 63
      mix/qml/StatusPane.qml
  21. 59
      mix/qml/TransactionLog.qml
  22. 2
      mix/qml/WebPreview.qml
  23. 2
      mix/qml/html/codeeditor.js
  24. BIN
      mix/qml/img/broom.png
  25. BIN
      mix/qml/img/clearicon.png
  26. BIN
      mix/qml/img/cleariconactive.png
  27. BIN
      mix/qml/img/copyicon.png
  28. BIN
      mix/qml/img/copyiconactive.png
  29. BIN
      mix/qml/img/edit_combox.png
  30. BIN
      mix/qml/img/pause_button.png
  31. BIN
      mix/qml/img/pause_button2x.png
  32. BIN
      mix/qml/img/play_button.png
  33. BIN
      mix/qml/img/play_button2x.png
  34. BIN
      mix/qml/img/searchicon.png
  35. BIN
      mix/qml/img/stop_button2x.png
  36. 10
      mix/qml/js/ProjectModel.js
  37. 12
      mix/res.qrc
  38. 14
      test/SolidityNameAndTypeResolution.cpp
  39. 114
      test/stMemoryTestFiller.json

2
libevm/VM.h

@ -56,7 +56,7 @@ public:
virtual bytesConstRef go(ExtVMFace& _ext, OnOpFunc const& _onOp = {}, uint64_t _steps = (uint64_t)-1) override final;
void require(u256 _n, u256 _d) { if (m_stack.size() < _n) { if (m_onFail) m_onFail(); BOOST_THROW_EXCEPTION(StackUnderflow() << RequirementError((bigint)_n, (bigint)m_stack.size())); } if (m_stack.size() - _n + _d >= c_stackLimit) { if (m_onFail) m_onFail(); BOOST_THROW_EXCEPTION(OutOfStack() << RequirementError((bigint)(_d - _n), (bigint)m_stack.size())); } }
void require(u256 _n, u256 _d) { if (m_stack.size() < _n) { if (m_onFail) m_onFail(); BOOST_THROW_EXCEPTION(StackUnderflow() << RequirementError((bigint)_n, (bigint)m_stack.size())); } if (m_stack.size() - _n + _d > c_stackLimit) { if (m_onFail) m_onFail(); BOOST_THROW_EXCEPTION(OutOfStack() << RequirementError((bigint)(_d - _n), (bigint)m_stack.size())); } }
void requireMem(unsigned _n) { if (m_temp.size() < _n) { m_temp.resize(_n); } }
u256 curPC() const { return m_curPC; }

40
libevmcore/Assembly.cpp

@ -34,9 +34,9 @@ void Assembly::append(Assembly const& _a)
for (AssemblyItem i: _a.m_items)
{
if (i.type() == Tag || i.type() == PushTag)
i.m_data += m_usedTags;
i.setData(i.data() + m_usedTags);
else if (i.type() == PushSub || i.type() == PushSubSize)
i.m_data += m_subs.size();
i.setData(i.data() + m_usedTags);
append(i);
}
m_deposit = newDeposit;
@ -106,34 +106,34 @@ ostream& Assembly::stream(ostream& _out, string const& _prefix, StringMap const&
for (AssemblyItem const& i: m_items)
{
_out << _prefix;
switch (i.m_type)
switch (i.type())
{
case Operation:
_out << " " << instructionInfo(i.instruction()).name << "\t" << i.getJumpTypeAsString();
break;
case Push:
_out << " PUSH " << i.m_data;
_out << " PUSH " << i.data();
break;
case PushString:
_out << " PUSH \"" << m_strings.at((h256)i.m_data) << "\"";
_out << " PUSH \"" << m_strings.at((h256)i.data()) << "\"";
break;
case PushTag:
_out << " PUSH [tag" << i.m_data << "]";
_out << " PUSH [tag" << i.data() << "]";
break;
case PushSub:
_out << " PUSH [$" << h256(i.m_data).abridged() << "]";
_out << " PUSH [$" << h256(i.data()).abridged() << "]";
break;
case PushSubSize:
_out << " PUSH #[$" << h256(i.m_data).abridged() << "]";
_out << " PUSH #[$" << h256(i.data()).abridged() << "]";
break;
case PushProgramSize:
_out << " PUSHSIZE";
break;
case Tag:
_out << "tag" << i.m_data << ": " << endl << _prefix << " JUMPDEST";
_out << "tag" << i.data() << ": " << endl << _prefix << " JUMPDEST";
break;
case PushData:
_out << " PUSH [" << hex << (unsigned)i.m_data << "]";
_out << " PUSH [" << hex << (unsigned)i.data() << "]";
break;
default:
BOOST_THROW_EXCEPTION(InvalidOpcode());
@ -189,7 +189,7 @@ Assembly& Assembly::optimise(bool _enable)
return *this;
std::vector<pair<AssemblyItems, function<AssemblyItems(AssemblyItemsConstRef)>>> rules;
// jump to next instruction
rules.push_back({ { PushTag, Instruction::JUMP, Tag }, [](AssemblyItemsConstRef m) -> AssemblyItems { if (m[0].m_data == m[2].m_data) return {m[2]}; else return m.toVector(); }});
rules.push_back({ { PushTag, Instruction::JUMP, Tag }, [](AssemblyItemsConstRef m) -> AssemblyItems { if (m[0].data() == m[2].data()) return {m[2]}; else return m.toVector(); }});
unsigned total = 0;
for (unsigned count = 1; count > 0; total += count)
@ -331,16 +331,16 @@ bytes Assembly::assemble() const
// m_data must not change from here on
for (AssemblyItem const& i: m_items)
switch (i.m_type)
switch (i.type())
{
case Operation:
ret.push_back((byte)i.m_data);
ret.push_back((byte)i.data());
break;
case PushString:
{
ret.push_back((byte)Instruction::PUSH32);
unsigned ii = 0;
for (auto j: m_strings.at((h256)i.m_data))
for (auto j: m_strings.at((h256)i.data()))
if (++ii > 32)
break;
else
@ -351,30 +351,30 @@ bytes Assembly::assemble() const
}
case Push:
{
byte b = max<unsigned>(1, dev::bytesRequired(i.m_data));
byte b = max<unsigned>(1, dev::bytesRequired(i.data()));
ret.push_back((byte)Instruction::PUSH1 - 1 + b);
ret.resize(ret.size() + b);
bytesRef byr(&ret.back() + 1 - b, b);
toBigEndian(i.m_data, byr);
toBigEndian(i.data(), byr);
break;
}
case PushTag:
{
ret.push_back(tagPush);
tagRef[ret.size()] = (unsigned)i.m_data;
tagRef[ret.size()] = (unsigned)i.data();
ret.resize(ret.size() + bytesPerTag);
break;
}
case PushData: case PushSub:
{
ret.push_back(dataRefPush);
dataRef.insert(make_pair((h256)i.m_data, ret.size()));
dataRef.insert(make_pair((h256)i.data(), ret.size()));
ret.resize(ret.size() + bytesPerDataRef);
break;
}
case PushSubSize:
{
auto s = m_data[i.m_data].size();
auto s = m_data[i.data()].size();
byte b = max<unsigned>(1, dev::bytesRequired(s));
ret.push_back((byte)Instruction::PUSH1 - 1 + b);
ret.resize(ret.size() + b);
@ -390,7 +390,7 @@ bytes Assembly::assemble() const
break;
}
case Tag:
tagPos[(unsigned)i.m_data] = ret.size();
tagPos[(unsigned)i.data()] = ret.size();
ret.push_back((byte)Instruction::JUMPDEST);
break;
default:

2
libevmcore/Assembly.h

@ -65,7 +65,7 @@ public:
template <class T> Assembly& operator<<(T const& _d) { append(_d); return *this; }
AssemblyItems const& getItems() const { return m_items; }
AssemblyItem const& back() const { return m_items.back(); }
std::string backString() const { return m_items.size() && m_items.back().m_type == PushString ? m_strings.at((h256)m_items.back().m_data) : std::string(); }
std::string backString() const { return m_items.size() && m_items.back().type() == PushString ? m_strings.at((h256)m_items.back().data()) : std::string(); }
void onePath() { if (asserts(!m_totalDeposit && !m_baseDeposit)) BOOST_THROW_EXCEPTION(InvalidDeposit()); m_baseDeposit = m_deposit; m_totalDeposit = INT_MAX; }
void otherPath() { donePath(); m_totalDeposit = m_deposit; m_deposit = m_baseDeposit; }

5
libevmcore/AssemblyItem.h

@ -40,8 +40,6 @@ class Assembly;
class AssemblyItem
{
friend class Assembly;
public:
enum class JumpType { Ordinary, IntoFunction, OutOfFunction };
@ -54,6 +52,9 @@ public:
AssemblyItemType type() const { return m_type; }
u256 const& data() const { return m_data; }
void setType(AssemblyItemType const _type) { m_type = _type; }
void setData(u256 const& _data) { m_data = _data; }
/// @returns the instruction of this item (only valid if type() == Operation)
Instruction instruction() const { return Instruction(byte(m_data)); }

75
libevmcore/CommonSubexpressionEliminator.cpp

@ -24,7 +24,7 @@
#include <functional>
#include <boost/range/adaptor/reversed.hpp>
#include <libevmcore/CommonSubexpressionEliminator.h>
#include <libevmcore/Assembly.h>
#include <libevmcore/AssemblyItem.h>
using namespace std;
using namespace dev;
@ -248,79 +248,6 @@ ExpressionClasses::Id CommonSubexpressionEliminator::loadFromMemory(ExpressionCl
return m_memoryContent[_slot] = m_expressionClasses.find(Instruction::MLOAD, {_slot}, true, m_sequenceNumber);
}
bool SemanticInformation::breaksBasicBlock(AssemblyItem const& _item)
{
switch (_item.type())
{
default:
case UndefinedItem:
case Tag:
return true;
case Push:
case PushString:
case PushTag:
case PushSub:
case PushSubSize:
case PushProgramSize:
case PushData:
return false;
case Operation:
{
if (isSwapInstruction(_item) || isDupInstruction(_item))
return false;
if (_item.instruction() == Instruction::GAS || _item.instruction() == Instruction::PC)
return true; // GAS and PC assume a specific order of opcodes
if (_item.instruction() == Instruction::MSIZE)
return true; // msize is modified already by memory access, avoid that for now
if (_item.instruction() == Instruction::SHA3)
return true; //@todo: we have to compare sha3's not based on their memory addresses but on the memory content.
InstructionInfo info = instructionInfo(_item.instruction());
if (_item.instruction() == Instruction::SSTORE)
return false;
if (_item.instruction() == Instruction::MSTORE)
return false;
//@todo: We do not handle the following memory instructions for now:
// calldatacopy, codecopy, extcodecopy, mstore8,
// msize (note that msize also depends on memory read access)
// the second requirement will be lifted once it is implemented
return info.sideEffects || info.args > 2;
}
}
}
bool SemanticInformation::isCommutativeOperation(AssemblyItem const& _item)
{
if (_item.type() != Operation)
return false;
switch (_item.instruction())
{
case Instruction::ADD:
case Instruction::MUL:
case Instruction::EQ:
case Instruction::AND:
case Instruction::OR:
case Instruction::XOR:
return true;
default:
return false;
}
}
bool SemanticInformation::isDupInstruction(AssemblyItem const& _item)
{
if (_item.type() != Operation)
return false;
return Instruction::DUP1 <= _item.instruction() && _item.instruction() <= Instruction::DUP16;
}
bool SemanticInformation::isSwapInstruction(AssemblyItem const& _item)
{
if (_item.type() != Operation)
return false;
return Instruction::SWAP1 <= _item.instruction() && _item.instruction() <= Instruction::SWAP16;
}
CSECodeGenerator::CSECodeGenerator(
ExpressionClasses& _expressionClasses,
vector<CSECodeGenerator::StoreOperation> const& _storeOperations

17
libevmcore/CommonSubexpressionEliminator.h

@ -31,6 +31,7 @@
#include <libdevcore/CommonIO.h>
#include <libdevcore/Exceptions.h>
#include <libevmcore/ExpressionClasses.h>
#include <libevmcore/SemanticInformation.h>
namespace dev
{
@ -139,20 +140,6 @@ private:
AssemblyItem const* m_breakingItem = nullptr;
};
/**
* Helper functions to provide context-independent information about assembly items.
*/
struct SemanticInformation
{
/// @returns true if the given items starts a new basic block
static bool breaksBasicBlock(AssemblyItem const& _item);
/// @returns true if the item is a two-argument operation whose value does not depend on the
/// order of its arguments.
static bool isCommutativeOperation(AssemblyItem const& _item);
static bool isDupInstruction(AssemblyItem const& _item);
static bool isSwapInstruction(AssemblyItem const& _item);
};
/**
* Unit that generates code from current stack layout, target stack layout and information about
* the equivalence classes.
@ -230,7 +217,7 @@ _AssemblyItemIterator CommonSubexpressionEliminator::feedItems(
_AssemblyItemIterator _end
)
{
for (; _iterator != _end && !SemanticInformation::breaksBasicBlock(*_iterator); ++_iterator)
for (; _iterator != _end && !SemanticInformation::breaksCSEAnalysisBlock(*_iterator); ++_iterator)
feedItem(*_iterator);
if (_iterator != _end)
m_breakingItem = &(*_iterator++);

107
libevmcore/SemanticInformation.cpp

@ -0,0 +1,107 @@
/*
This file is part of cpp-ethereum.
cpp-ethereum is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file SemanticInformation.cpp
* @author Christian <c@ethdev.com>
* @date 2015
* Helper to provide semantic information about assembly items.
*/
#include <libevmcore/SemanticInformation.h>
#include <libevmcore/AssemblyItem.h>
using namespace std;
using namespace dev;
using namespace dev::eth;
bool SemanticInformation::breaksCSEAnalysisBlock(AssemblyItem const& _item)
{
switch (_item.type())
{
default:
case UndefinedItem:
case Tag:
return true;
case Push:
case PushString:
case PushTag:
case PushSub:
case PushSubSize:
case PushProgramSize:
case PushData:
return false;
case Operation:
{
if (isSwapInstruction(_item) || isDupInstruction(_item))
return false;
if (_item.instruction() == Instruction::GAS || _item.instruction() == Instruction::PC)
return true; // GAS and PC assume a specific order of opcodes
if (_item.instruction() == Instruction::MSIZE)
return true; // msize is modified already by memory access, avoid that for now
if (_item.instruction() == Instruction::SHA3)
return true; //@todo: we have to compare sha3's not based on their memory addresses but on the memory content.
InstructionInfo info = instructionInfo(_item.instruction());
if (_item.instruction() == Instruction::SSTORE)
return false;
if (_item.instruction() == Instruction::MSTORE)
return false;
//@todo: We do not handle the following memory instructions for now:
// calldatacopy, codecopy, extcodecopy, mstore8,
// msize (note that msize also depends on memory read access)
// the second requirement will be lifted once it is implemented
return info.sideEffects || info.args > 2;
}
}
}
bool SemanticInformation::isCommutativeOperation(AssemblyItem const& _item)
{
if (_item.type() != Operation)
return false;
switch (_item.instruction())
{
case Instruction::ADD:
case Instruction::MUL:
case Instruction::EQ:
case Instruction::AND:
case Instruction::OR:
case Instruction::XOR:
return true;
default:
return false;
}
}
bool SemanticInformation::isDupInstruction(AssemblyItem const& _item)
{
if (_item.type() != Operation)
return false;
return Instruction::DUP1 <= _item.instruction() && _item.instruction() <= Instruction::DUP16;
}
bool SemanticInformation::isSwapInstruction(AssemblyItem const& _item)
{
if (_item.type() != Operation)
return false;
return Instruction::SWAP1 <= _item.instruction() && _item.instruction() <= Instruction::SWAP16;
}
bool SemanticInformation::isJumpInstruction(AssemblyItem const& _item)
{
return _item == AssemblyItem(Instruction::JUMP) || _item == AssemblyItem(Instruction::JUMPI);
}

50
libevmcore/SemanticInformation.h

@ -0,0 +1,50 @@
/*
This file is part of cpp-ethereum.
cpp-ethereum is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file SemanticInformation.h
* @author Christian <c@ethdev.com>
* @date 2015
* Helper to provide semantic information about assembly items.
*/
#pragma once
namespace dev
{
namespace eth
{
class AssemblyItem;
/**
* Helper functions to provide context-independent information about assembly items.
*/
struct SemanticInformation
{
/// @returns true if the given items starts a new block for common subexpression analysis.
static bool breaksCSEAnalysisBlock(AssemblyItem const& _item);
/// @returns true if the item is a two-argument operation whose value does not depend on the
/// order of its arguments.
static bool isCommutativeOperation(AssemblyItem const& _item);
static bool isDupInstruction(AssemblyItem const& _item);
static bool isSwapInstruction(AssemblyItem const& _item);
static bool isJumpInstruction(AssemblyItem const& _item);
};
}
}

16
libsolidity/AST.cpp

@ -337,8 +337,14 @@ void FunctionDefinition::checkTypeRequirements()
{
if (!var->getType()->canLiveOutsideStorage())
BOOST_THROW_EXCEPTION(var->createTypeError("Type is required to live outside storage."));
if (!(var->getType()->externalType()) && getVisibility() >= Visibility::Public)
BOOST_THROW_EXCEPTION(var->createTypeError("Internal type is not allowed for function with external visibility"));
if (getVisibility() >= Visibility::Public && !(var->getType()->externalType()))
{
// todo delete when will be implemented arrays as parameter type in internal functions
if (getVisibility() == Visibility::Public && var->getType()->getCategory() == Type::Category::Array)
BOOST_THROW_EXCEPTION(var->createTypeError("Arrays only implemented for external functions."));
else
BOOST_THROW_EXCEPTION(var->createTypeError("Internal type is not allowed for public and external functions."));
}
}
for (ASTPointer<ModifierInvocation> const& modifier: m_functionModifiers)
modifier->checkTypeRequirements(isConstructor() ?
@ -379,7 +385,11 @@ void VariableDeclaration::checkTypeRequirements()
m_value->expectType(*m_type);
if (m_isStateVariable && !m_type->externalType() && getVisibility() >= Visibility::Public)
BOOST_THROW_EXCEPTION(createTypeError("Internal type is not allowed for state variables."));
} else
if (!FunctionType(*this).externalType())
BOOST_THROW_EXCEPTION(createTypeError("Internal type is not allowed for public state variables."));
}
else
{
// no type declared and no previous assignment, infer the type
m_value->checkTypeRequirements();

17
libsolidity/Types.cpp

@ -1103,11 +1103,18 @@ TypePointer FunctionType::externalType() const
TypePointers paramTypes;
TypePointers retParamTypes;
for (auto it = m_parameterTypes.cbegin(); it != m_parameterTypes.cend(); ++it)
paramTypes.push_back((*it)->externalType());
for (auto it = m_returnParameterTypes.cbegin(); it != m_returnParameterTypes.cend(); ++it)
retParamTypes.push_back((*it)->externalType());
for (auto type: m_parameterTypes)
{
if (!type->externalType())
return TypePointer();
paramTypes.push_back(type->externalType());
}
for (auto type: m_returnParameterTypes)
{
if (!type->externalType())
return TypePointer();
retParamTypes.push_back(type->externalType());
}
return make_shared<FunctionType>(paramTypes, retParamTypes, m_location, m_arbitraryParameters);
}

2
libsolidity/Types.h

@ -512,6 +512,8 @@ public:
virtual Category getCategory() const override { return Category::Function; }
/// @returns TypePointer of a new FunctionType object. All input/return parameters are an appropriate external types of input/return parameters of current function.
/// Returns an empty shared pointer if one of the input/return parameters does not have an externaltype.
virtual TypePointer externalType() const override;
explicit FunctionType(FunctionDefinition const& _function, bool _isInternal = true);

21
mix/CodeModel.cpp

@ -93,8 +93,23 @@ private:
bool m_functionScope;
uint m_storageSlot;
};
dev::eth::AssemblyItems filterLocations(dev::eth::AssemblyItems const& _locations, dev::solidity::ContractDefinition const& _contract, QHash<LocationPair, QString> _functions)
{
dev::eth::AssemblyItems result;
result.reserve(_locations.size());
for (dev::eth::AssemblyItem item : _locations)
{
dev::SourceLocation const& l = item.getLocation();
if (_contract.getLocation() == l || _functions.contains(LocationPair(l.start, l.end)))
item.setLocation(dev::SourceLocation(-1, -1, l.sourceName));
result.push_back(item);
}
return result;
}
} //namespace
void BackgroundWorker::queueCodeChange(int _jobId)
{
m_model->runCompilationJob(_jobId);
@ -105,13 +120,11 @@ CompiledContract::CompiledContract(const dev::solidity::CompilerStack& _compiler
m_sourceHash(qHash(_source))
{
std::string name = _contractName.toStdString();
auto const& contractDefinition = _compiler.getContractDefinition(name);
ContractDefinition 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);
dev::solidity::InterfaceHandler interfaceHandler;
m_contractInterface = QString::fromStdString(*interfaceHandler.getABIInterface(contractDefinition));
@ -122,6 +135,8 @@ CompiledContract::CompiledContract(const dev::solidity::CompilerStack& _compiler
CollectDeclarationsVisitor visitor(&m_functions, &m_locals, &m_storage);
contractDefinition.accept(visitor);
m_assemblyItems = filterLocations(_compiler.getRuntimeAssemblyItems(name), contractDefinition, m_functions);
m_constructorAssemblyItems = filterLocations(_compiler.getAssemblyItems(name), contractDefinition, m_functions);
}
QString CompiledContract::codeHex() const

1
mix/qml.qrc

@ -61,5 +61,6 @@
<file>qml/js/TransactionHelper.js</file>
<file>qml/main.qml</file>
<file>qml/qmldir</file>
<file>qml/StatesComboBox.qml</file>
</qresource>
</RCC>

9
mix/qml/CodeEditorView.qml

@ -11,15 +11,6 @@ Item {
signal breakpointsChanged(string documentId)
signal isCleanChanged(var isClean, string documentId)
function getDocumentIdByName(fileName)
{
for (var i = 0; i < editorListModel.count; i++) {
if (editorListModel.get(i).fileName === fileName) {
return editorListModel.get(i).documentId;
}
}
return null;
}
function getDocumentText(documentId) {
for (var i = 0; i < editorListModel.count; i++) {

27
mix/qml/Debugger.qml

@ -219,6 +219,33 @@ Rectangle {
anchors.horizontalCenter: parent.horizontalCenter
id: jumpButtons
spacing: 3
StepActionImage
{
id: playAction
enabledStateImg: "qrc:/qml/img/play_button.png"
disableStateImg: "qrc:/qml/img/play_button.png"
onClicked: projectModel.stateListModel.runState(transactionLog.selectedStateIndex)
width: 30
height: 30
buttonShortcut: "Ctrl+Shift+F8"
buttonTooltip: qsTr("Start Debugging")
visible: true
}
StepActionImage
{
id: pauseAction
enabledStateImg: "qrc:/qml/img/stop_button2x.png"
disableStateImg: "qrc:/qml/img/stop_button2x.png"
onClicked: Debugger.init(null);
width: 30
height: 30
buttonShortcut: "Ctrl+Shift+F9"
buttonTooltip: qsTr("Stop Debugging")
visible: true
}
StepActionImage
{
id: runBackAction;

584
mix/qml/LogsPane.qml

@ -7,81 +7,258 @@ import "."
Rectangle
{
property variant currentStatus;
function push(_level, _type, _content)
{
_content = _content.replace(/\n/g, " ")
logsModel.insert(0, { "type": _type, "date": Qt.formatDateTime(new Date(), "hh:mm:ss dd.MM.yyyy"), "content": _content, "level": _level });
logsModel.insert(0, { "type": _type, "date": Qt.formatDateTime(new Date(), "hh:mm:ss"), "content": _content, "level": _level });
}
onVisibleChanged:
{
if (visible && (logsModel.count === 0 || (logsModel.get(0).date !== currentStatus.date && logsModel.get(0).content !== currentStatus.content)))
logsModel.insert(0, { "type": currentStatus.type, "date": currentStatus.date, "content": currentStatus.content, "level": currentStatus.level });
else if (!visible)
{
for (var k = 0; k < logsModel.count; k++)
{
if (logsModel.get(k).type === "Comp") //do not keep compilation logs.
logsModel.remove(k);
}
}
}
anchors.fill: parent
radius: 5
color: LogsPaneStyle.generic.layout.backgroundColor
border.color: LogsPaneStyle.generic.layout.borderColor
border.width: LogsPaneStyle.generic.layout.borderWidth
ColumnLayout {
radius: 10
color: "transparent"
id: logsPane
Column {
z: 2
height: parent.height
height: parent.height - rowAction.height
width: parent.width
spacing: 0
ListModel {
id: logsModel
}
ScrollView
{
id: scrollView
height: parent.height
width: parent.width
horizontalScrollBarPolicy: Qt.ScrollBarAlwaysOff
Column
{
id: logsRect
spacing: 0
Repeater {
id: logsRepeater
clip: true
property string frontColor: "transparent"
model: SortFilterProxyModel {
id: proxyModel
source: logsModel
property var roles: ["-", "javascript", "run", "state", "comp"]
Component.onCompleted: {
filterType = regEx(proxyModel.roles);
}
function search(_value)
{
filterContent = _value;
}
function toogleFilter(_value)
{
var count = roles.length;
for (var i in roles)
{
if (roles[i] === _value)
{
roles.splice(i, 1);
break;
}
}
if (count === roles.length)
roles.push(_value);
filterType = regEx(proxyModel.roles);
}
function regEx(_value)
{
return "(?:" + roles.join('|') + ")";
}
filterType: "(?:javascript|run|state|comp)"
filterContent: ""
filterSyntax: SortFilterProxyModel.RegExp
filterCaseSensitivity: Qt.CaseInsensitive
}
Rectangle
{
width: LogsPaneStyle.generic.layout.dateWidth + LogsPaneStyle.generic.layout.contentWidth + LogsPaneStyle.generic.layout.typeWidth
height: 30
color:
{
var cl;
if (level === "warning" || level === "error")
cl = LogsPaneStyle.generic.layout.errorColor;
else
cl = index % 2 === 0 ? "transparent" : LogsPaneStyle.generic.layout.logAlternateColor;
if (index === 0)
logsRepeater.frontColor = cl;
return cl;
}
MouseArea
{
anchors.fill: parent
onClicked:
{
if (logContent.elide === Text.ElideNone)
{
logContent.elide = Text.ElideRight;
logContent.wrapMode = Text.NoWrap
parent.height = 30;
}
else
{
logContent.elide = Text.ElideNone;
logContent.wrapMode = Text.WordWrap;
parent.height = logContent.lineCount * 30;
}
}
}
DefaultLabel {
text: date;
font.family: LogsPaneStyle.generic.layout.logLabelFont
width: LogsPaneStyle.generic.layout.dateWidth
font.pointSize: Style.absoluteSize(-1)
anchors.left: parent.left
anchors.leftMargin: 15
anchors.verticalCenter: parent.verticalCenter
color: {
parent.getColor(level);
}
}
DefaultLabel {
text: type;
font.family: LogsPaneStyle.generic.layout.logLabelFont
width: LogsPaneStyle.generic.layout.typeWidth
font.pointSize: Style.absoluteSize(-1)
anchors.left: parent.left
anchors.leftMargin: 100
anchors.verticalCenter: parent.verticalCenter
color: {
parent.getColor(level);
}
}
Text {
id: logContent
text: content;
font.family: LogsPaneStyle.generic.layout.logLabelFont
width: LogsPaneStyle.generic.layout.contentWidth
font.pointSize: Style.absoluteSize(-1)
anchors.verticalCenter: parent.verticalCenter
elide: Text.ElideRight
anchors.left: parent.left
anchors.leftMargin: 230
color: {
parent.getColor(level);
}
}
function getColor()
{
if (level === "error")
return "red";
else if (level === "warning")
return "orange";
else
return "#808080";
}
}
}
}
}
Component {
id: itemDelegate
DefaultLabel {
text: styleData.value;
font.family: LogsPaneStyle.generic.layout.logLabelFont
font.pointSize: Style.absoluteSize(-1)
color: {
if (proxyModel.get(styleData.row).level === "error")
return "red";
else if (proxyModel.get(styleData.row).level === "warning")
return "orange";
else
return "#808080";
}
}
}
}
Rectangle
{
gradient: Gradient {
GradientStop { position: 0.0; color: "#f1f1f1" }
GradientStop { position: 1.0; color: "#d9d7da" }
}
Layout.preferredHeight: LogsPaneStyle.generic.layout.headerHeight
height: LogsPaneStyle.generic.layout.headerHeight
width: logsPane.width
anchors.bottom: parent.bottom
Row
{
id: rowAction
Layout.preferredHeight: LogsPaneStyle.generic.layout.headerHeight
height: LogsPaneStyle.generic.layout.headerHeight
anchors.leftMargin: LogsPaneStyle.generic.layout.leftMargin
anchors.left: parent.left
spacing: LogsPaneStyle.generic.layout.headerButtonSpacing
Button
height: parent.height
Rectangle
{
height: LogsPaneStyle.generic.layout.headerButtonHeight
anchors.verticalCenter: parent.verticalCenter
action: clearAction
iconSource: "qrc:/qml/img/broom.png"
}
Action {
id: clearAction
enabled: logsModel.count > 0
tooltip: qsTr("Clear")
onTriggered: {
logsModel.clear()
color: "transparent"
height: parent.height
width: 40
DefaultLabel
{
anchors.verticalCenter: parent.verticalCenter
color: LogsPaneStyle.generic.layout.logLabelColor
font.pointSize: Style.absoluteSize(-3)
font.family: LogsPaneStyle.generic.layout.logLabelFont
text: qsTr("Show:")
}
}
Button
{
height: LogsPaneStyle.generic.layout.headerButtonHeight
Rectangle {
anchors.verticalCenter: parent.verticalCenter
action: copytoClipBoardAction
iconSource: "qrc:/qml/img/copy.png"
}
Action {
id: copytoClipBoardAction
enabled: logsModel.count > 0
tooltip: qsTr("Copy to Clipboard")
onTriggered: {
var content = "";
for (var k = 0; k < logsModel.count; k++)
{
var log = logsModel.get(k);
content += log.type + "\t" + log.level + "\t" + log.date + "\t" + log.content + "\n";
}
clipboard.text = content;
}
width: 1;
height: parent.height
color: LogsPaneStyle.generic.layout.buttonSeparatorColor1
}
Rectangle {
anchors.verticalCenter: parent.verticalCenter
width: 1;
height: parent.height - 10
color : "#808080"
width: 2;
height: parent.height
color: LogsPaneStyle.generic.layout.buttonSeparatorColor2
}
ToolButton {
id: javascriptButton
checkable: true
height: LogsPaneStyle.generic.layout.headerButtonHeight
width: 20
anchors.verticalCenter: parent.verticalCenter
checked: true
onCheckedChanged: {
@ -97,16 +274,35 @@ Rectangle
font.pointSize: Style.absoluteSize(-3)
color: LogsPaneStyle.generic.layout.logLabelColor
anchors.centerIn: parent
text: qsTr("JavaScript")
text: qsTr("JS")
}
}
background:
Rectangle {
color: javascriptButton.checked ? LogsPaneStyle.generic.layout.buttonSelected : "transparent"
}
}
}
Rectangle {
anchors.verticalCenter: parent.verticalCenter
width: 1;
height: parent.height
color: LogsPaneStyle.generic.layout.buttonSeparatorColor1
}
Rectangle {
anchors.verticalCenter: parent.verticalCenter
width: 2;
height: parent.height
color: LogsPaneStyle.generic.layout.buttonSeparatorColor2
}
ToolButton {
id: runButton
checkable: true
height: LogsPaneStyle.generic.layout.headerButtonHeight
width: 30
anchors.verticalCenter: parent.verticalCenter
checked: true
onCheckedChanged: {
@ -125,14 +321,33 @@ Rectangle
text: qsTr("Run")
}
}
background:
Rectangle {
color: runButton.checked ? LogsPaneStyle.generic.layout.buttonSelected : "transparent"
}
}
}
Rectangle {
anchors.verticalCenter: parent.verticalCenter
width: 1;
height: parent.height
color: LogsPaneStyle.generic.layout.buttonSeparatorColor1
}
Rectangle {
anchors.verticalCenter: parent.verticalCenter
width: 2;
height: parent.height
color: LogsPaneStyle.generic.layout.buttonSeparatorColor2
}
ToolButton {
id: stateButton
checkable: true
height: LogsPaneStyle.generic.layout.headerButtonHeight
anchors.verticalCenter: parent.verticalCenter
width: 35
checked: true
onCheckedChanged: {
proxyModel.toogleFilter("state")
@ -145,133 +360,226 @@ Rectangle
DefaultLabel {
font.family: LogsPaneStyle.generic.layout.logLabelFont
font.pointSize: Style.absoluteSize(-3)
color: "#5391d8"
color: LogsPaneStyle.generic.layout.logLabelColor
anchors.centerIn: parent
text: qsTr("State")
}
}
background:
Rectangle {
color: stateButton.checked ? LogsPaneStyle.generic.layout.buttonSelected : "transparent"
}
}
}
DefaultTextField
{
id: searchBox
height: LogsPaneStyle.generic.layout.headerButtonHeight
Rectangle {
anchors.verticalCenter: parent.verticalCenter
width: LogsPaneStyle.generic.layout.headerInputWidth
font.family: LogsPaneStyle.generic.layout.logLabelFont
font.pointSize: Style.absoluteSize(-3)
font.italic: true
onTextChanged: {
proxyModel.search(text);
}
width: 1;
height: parent.height
color: LogsPaneStyle.generic.layout.buttonSeparatorColor1
}
}
ListModel {
id: logsModel
Rectangle {
anchors.verticalCenter: parent.verticalCenter
width: 2;
height: parent.height
color: LogsPaneStyle.generic.layout.buttonSeparatorColor2
}
}
TableView {
id: logsTable
clip: true
Layout.fillWidth: true
Layout.preferredHeight: parent.height - rowAction.height
headerVisible : false
onDoubleClicked:
Row
{
height: parent.height
anchors.right: parent.right
anchors.rightMargin: 10
spacing: 10
Rectangle
{
var log = logsModel.get(logsTable.currentRow);
if (log)
clipboard.text = (log.type + "\t" + log.level + "\t" + log.date + "\t" + log.content);
}
height: LogsPaneStyle.generic.layout.headerButtonHeight
anchors.verticalCenter: parent.verticalCenter
color: "transparent"
width: 20
Button
{
id: clearButton
action: clearAction
anchors.fill: parent
anchors.verticalCenter: parent.verticalCenter
height: 25
style:
ButtonStyle {
background:
Rectangle {
height: LogsPaneStyle.generic.layout.headerButtonHeight
implicitHeight: LogsPaneStyle.generic.layout.headerButtonHeight
color: "transparent"
}
}
}
model: SortFilterProxyModel {
id: proxyModel
source: logsModel
property var roles: ["-", "javascript", "run", "state"]
Image {
id: clearImage
source: clearAction.enabled ? "qrc:/qml/img/cleariconactive.png" : "qrc:/qml/img/clearicon.png"
anchors.centerIn: parent
fillMode: Image.PreserveAspectFit
width: 20
height: 25
}
Component.onCompleted: {
filterType = regEx(proxyModel.roles);
Action {
id: clearAction
enabled: logsModel.count > 0
tooltip: qsTr("Clear")
onTriggered: {
logsModel.clear();
}
}
}
function search(_value)
Rectangle
{
height: LogsPaneStyle.generic.layout.headerButtonHeight
anchors.verticalCenter: parent.verticalCenter
color: "transparent"
width: 20
Button
{
filterContent = _value;
id: copyButton
action: copyAction
anchors.fill: parent
anchors.verticalCenter: parent.verticalCenter
height: 25
style:
ButtonStyle {
background:
Rectangle {
height: LogsPaneStyle.generic.layout.headerButtonHeight
implicitHeight: LogsPaneStyle.generic.layout.headerButtonHeight
color: "transparent"
}
}
}
function toogleFilter(_value)
{
var count = roles.length;
for (var i in roles)
{
if (roles[i] === _value)
Image {
id: copyImage
source: copyAction.enabled ? "qrc:/qml/img/copyiconactive.png" : "qrc:/qml/img/copyicon.png"
anchors.centerIn: parent
fillMode: Image.PreserveAspectFit
width: 20
height: 25
}
Action {
id: copyAction
enabled: logsModel.count > 0
tooltip: qsTr("Copy to Clipboard")
onTriggered: {
var content = "";
for (var k = 0; k < logsModel.count; k++)
{
roles.splice(i, 1);
break;
var log = logsModel.get(k);
content += log.type + "\t" + log.level + "\t" + log.date + "\t" + log.content + "\n";
}
clipboard.text = content;
}
if (count === roles.length)
roles.push(_value);
filterType = regEx(proxyModel.roles);
}
}
function regEx(_value)
Rectangle
{
width: 120
radius: 10
height: 25
color: "white"
anchors.verticalCenter: parent.verticalCenter
Image
{
return "(?:" + roles.join('|') + ")";
id: searchImg
source: "qrc:/qml/img/searchicon.png"
fillMode: Image.PreserveAspectFit
width: 20
height: 25
z: 3
}
filterType: "(?:javascript|run|state)"
filterContent: ""
filterSyntax: SortFilterProxyModel.RegExp
filterCaseSensitivity: Qt.CaseInsensitive
}
TableViewColumn
{
role: "date"
title: qsTr("date")
width: LogsPaneStyle.generic.layout.dateWidth
delegate: itemDelegate
}
TableViewColumn
{
role: "type"
title: qsTr("type")
width: LogsPaneStyle.generic.layout.typeWidth
delegate: itemDelegate
DefaultTextField
{
id: searchBox
z: 2
width: 100
anchors.left: searchImg.right
anchors.leftMargin: -7
font.family: LogsPaneStyle.generic.layout.logLabelFont
font.pointSize: Style.absoluteSize(-3)
font.italic: true
text: qsTr(" - Search - ")
onFocusChanged:
{
if (!focus && text === "")
text = qsTr(" - Search - ");
else if (focus && text === qsTr(" - Search - "))
text = "";
}
onTextChanged: {
if (text === qsTr(" - Search - "))
proxyModel.search("");
else
proxyModel.search(text);
}
style:
TextFieldStyle {
background: Rectangle {
radius: 10
}
}
}
}
TableViewColumn
Rectangle
{
role: "content"
title: qsTr("content")
width: LogsPaneStyle.generic.layout.contentWidth
delegate: itemDelegate
}
height: LogsPaneStyle.generic.layout.headerButtonHeight
anchors.verticalCenter: parent.verticalCenter
color: "transparent"
width: 20
Button
{
id: hideButton
action: hideAction
anchors.fill: parent
anchors.verticalCenter: parent.verticalCenter
height: 25
style:
ButtonStyle {
background:
Rectangle {
height: LogsPaneStyle.generic.layout.headerButtonHeight
implicitHeight: LogsPaneStyle.generic.layout.headerButtonHeight
color: "transparent"
}
}
}
rowDelegate: Item {
Rectangle {
width: logsTable.width - 4
height: 17
color: styleData.alternate ? "transparent" : LogsPaneStyle.generic.layout.logAlternateColor
Image {
id: hideImage
source: "qrc:/qml/img/exit.png"
anchors.centerIn: parent
fillMode: Image.PreserveAspectFit
width: 20
height: 25
}
}
}
Component {
id: itemDelegate
DefaultLabel {
text: styleData.value;
font.family: LogsPaneStyle.generic.layout.logLabelFont
font.pointSize: Style.absoluteSize(-1)
color: {
if (proxyModel.get(styleData.row).level === "error")
return "red";
else if (proxyModel.get(styleData.row).level === "warning")
return "orange";
else
return "#808080";
Action {
id: hideAction
tooltip: qsTr("Exit")
onTriggered: {
logsPane.parent.toggle();
}
}
}
}
}
}

18
mix/qml/LogsPaneStyle.qml

@ -11,19 +11,21 @@ QtObject {
property QtObject generic: QtObject {
property QtObject layout: QtObject {
property string backgroundColor: "#f7f7f7"
property string borderColor: "#5391d8"
property int borderWidth: 1
property int headerHeight: 35
property int headerButtonSpacing: 5
property int headerHeight: 30
property int headerButtonSpacing: 0
property int leftMargin: 10
property int headerButtonHeight: 30
property string logLabelColor: "#5391d8"
property string logLabelColor: "#4a4a4a"
property string logLabelFont: "sans serif"
property int headerInputWidth: 200
property int dateWidth: 150
property int typeWidth: 80
property int contentWidth: 700
property string logAlternateColor: "#f0f0f0"
property int typeWidth: 150
property int contentWidth: 560
property string logAlternateColor: "#f6f5f6"
property string errorColor: "#fffcd5"
property string buttonSeparatorColor1: "#d3d0d0"
property string buttonSeparatorColor2: "#f2f1f2"
property string buttonSelected: "#dcdcdc"
}
}
}

1
mix/qml/ProjectModel.qml

@ -64,6 +64,7 @@ Item {
function renameDocument(documentId, newName) { ProjectModelCode.renameDocument(documentId, newName); }
function removeDocument(documentId) { ProjectModelCode.removeDocument(documentId); }
function getDocument(documentId) { return ProjectModelCode.getDocument(documentId); }
function getDocumentIdByName(documentName) { return ProjectModelCode.getDocumentIdByName(documentName); }
function getDocumentIndex(documentId) { return ProjectModelCode.getDocumentIndex(documentId); }
function addExistingFiles(paths) { ProjectModelCode.doAddExistingFiles(paths); }
function deployProject() { ProjectModelCode.deployProject(false); }

260
mix/qml/StatesComboBox.qml

@ -0,0 +1,260 @@
/*
This file is part of cpp-ethereum.
cpp-ethereum is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file StatesComboBox.qml
* @author Ali Mashatan ali@ethdev.com
* @date 2015
* Ethereum IDE client.
*/
import QtQuick 2.0
import QtQuick.Controls 1.0
import QtQuick.Layouts 1.1
import QtGraphicalEffects 1.0
Rectangle {
id: statesComboBox
width: 200
height: 23
Component.onCompleted: {
var top = dropDownList
while (top.parent) {
top = top.parent
if (top.objectName == "debugPanel")
break
}
var coordinates = dropDownList.mapToItem(top, 0, 0)
//the order is important
dropDownShowdowList.parent = top
dropDownList.parent = top
dropDownShowdowList.x = coordinates.x
dropDownShowdowList.y = coordinates.y
dropDownList.x = coordinates.x
dropDownList.y = coordinates.y
}
signal selectItem(real item)
signal editItem(real item)
signal selectCreate
property int rowHeight: 25
property variant items
property alias selectedItem: chosenItemText.text
property alias selectedIndex: listView.currentRow
function setSelectedIndex(index) {
listView.currentRow = index
chosenItemText.text = statesComboBox.items.get(index).title
}
signal comboClicked
property variant colorItem
property variant colorSelect
SourceSansProRegular
{
id: regularFont
}
SourceSansProBold
{
id: boldFont
}
smooth: true
Rectangle {
id: chosenItem
width: parent.width
height: statesComboBox.height
color: statesComboBox.color
Text {
id: chosenItemText
anchors.left: parent.left
anchors.leftMargin: 10
anchors.verticalCenter: parent.verticalCenter
color: statesComboBox.colorItem
text: ""
font.family: regularFont.name
}
MouseArea {
anchors.fill: parent
onClicked: {
statesComboBox.state = statesComboBox.state === "dropDown" ? "" : "dropDown"
}
}
}
Rectangle {
id: dropDownShowdowList
width: statesComboBox.width
opacity: 0.3
height: 0
clip: true
radius: 4
anchors.top: chosenItem.top
anchors.margins: 2
color: "gray"
}
//ToDo: We need scrollbar for items
Rectangle {
id: dropDownList
width: statesComboBox.width
height: 0
clip: true
radius: 4
anchors.top: chosenItem.top
anchors.topMargin: 23
color: statesComboBox.color
ColumnLayout {
spacing: 2
TableView {
id: listView
height: 20
implicitHeight: 0
width: statesComboBox.width
model: statesComboBox.items
horizontalScrollBarPolicy: Qt.ScrollBarAlwaysOff
currentRow: -1
headerVisible: false
backgroundVisible: false
alternatingRowColors: false
frameVisible: false
TableViewColumn {
role: "title"
title: ""
width: statesComboBox.width
delegate: mainItemDelegate
}
rowDelegate: Rectangle {
width: statesComboBox.width
height: statesComboBox.rowHeight
}
Component {
id: mainItemDelegate
Rectangle {
id: itemDelegate
width: statesComboBox.width
height: statesComboBox.height
Text {
id: textItemid
text: styleData.value
color: statesComboBox.colorItem
anchors.top: parent.top
anchors.left: parent.left
anchors.leftMargin: 10
anchors.topMargin: 5
font.family: regularFont.name
}
Image {
id: imageItemid
height: 20
width: 20
anchors.right: parent.right
anchors.top: parent.top
anchors.margins: 5
visible: false
fillMode: Image.PreserveAspectFit
source: "img/edit_combox.png"
}
MouseArea {
anchors.fill: parent
hoverEnabled: true
onEntered: {
imageItemid.visible = true
textItemid.color = statesComboBox.colorSelect
}
onExited: {
imageItemid.visible = false
textItemid.color = statesComboBox.colorItem
}
onClicked: {
if (mouseX > imageItemid.x
&& mouseX < imageItemid.x + imageItemid.width
&& mouseY > imageItemid.y
&& mouseY < imageItemid.y + imageItemid.height)
statesComboBox.editItem(styleData.row)
else {
statesComboBox.state = ""
var prevSelection = chosenItemText.text
chosenItemText.text = styleData.value
listView.currentRow = styleData.row
statesComboBox.selectItem(styleData.row)
}
}
}
} //Item
} //Component
} //Table View
RowLayout {
anchors.top: listView.bottom
anchors.topMargin: 4
anchors.left: parent.left
anchors.leftMargin: 10
Text {
id: createStateText
width: statesComboBox.width
height: statesComboBox.height
font.family: boldFont.name
color: "#808080"
text: qsTr("Create State ...")
font.weight: Font.DemiBold
MouseArea {
anchors.fill: parent
hoverEnabled: true
onEntered: {
createStateText.color = statesComboBox.colorSelect
}
onExited: {
createStateText.color = statesComboBox.colorItem
}
onClicked: {
statesComboBox.state = ""
statesComboBox.selectCreate()
}
}
}
}
}
}
states: State {
name: "dropDown"
PropertyChanges {
target: dropDownList
height: (statesComboBox.rowHeight * (statesComboBox.items.count + 1))
}
PropertyChanges {
target: dropDownShowdowList
width: statesComboBox.width + 3
height: (statesComboBox.rowHeight * (statesComboBox.items.count + 1)) + 3
}
PropertyChanges {
target: listView
height: 20
implicitHeight: (statesComboBox.rowHeight * (statesComboBox.items.count))
}
}
}

63
mix/qml/StatusPane.qml

@ -9,7 +9,7 @@ Rectangle {
id: statusHeader
objectName: "statusPane"
property variant webPreview
property alias currentStatus: logPane.currentStatus
function updateStatus(message)
{
if (!message)
@ -17,6 +17,7 @@ Rectangle {
status.state = "";
status.text = qsTr("Compile successfully.");
debugImg.state = "active";
currentStatus = { "type": "Comp", "date": Qt.formatDateTime(new Date(), "hh:mm:ss"), "content": status.text, "level": "info" }
}
else
{
@ -24,6 +25,7 @@ Rectangle {
var errorInfo = ErrorLocationFormater.extractErrorInfo(message, true);
status.text = errorInfo.errorLocation + " " + errorInfo.errorDetail;
debugImg.state = "";
currentStatus = { "type": "Comp", "date": Qt.formatDateTime(new Date(), "hh:mm:ss"), "content": status.text, "level": "error" }
}
debugRunActionIcon.enabled = codeModel.hasContract;
}
@ -33,6 +35,7 @@ Rectangle {
status.state = "";
status.text = text
logPane.push("info", type, text);
currentStatus = { "type": type, "date": Qt.formatDateTime(new Date(), "hh:mm:ss"), "content": text, "level": "info" }
}
function warningMessage(text, type)
@ -40,13 +43,15 @@ Rectangle {
status.state = "warning";
status.text = text
logPane.push("warning", type, text);
currentStatus = { "type": type, "date": Qt.formatDateTime(new Date(), "hh:mm:ss"), "content": text, "level": "warning" }
}
function errorMessage(text, type)
{
status.state = "error";
status.text = text
status.text = text;
logPane.push("error", type, text);
currentStatus = { "type": type, "date": Qt.formatDateTime(new Date(), "hh:mm:ss"), "content": text, "level": "error" }
}
Connections {
@ -76,7 +81,7 @@ Rectangle {
function format(_message)
{
var formatted = _message.match(/(?:<dev::eth::)(.+)(?:>)/);
if (formatted)
if (!formatted)
formatted = _message.match(/(?:<dev::)(.+)(?:>)/);
if (formatted && formatted.length > 1)
formatted = formatted[1];
@ -90,6 +95,7 @@ Rectangle {
return formatted;
}
}
Connections {
target:projectModel
onDeploymentStarted: infoMessage(qsTr("Running deployment..."), "Deployment");
@ -111,32 +117,13 @@ Rectangle {
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
radius: 3
width: 500
width: 600
height: 30
color: "#fcfbfc"
states: [
State {
name: "logsOpened"
PropertyChanges {
target: statusContainer
border.color: "#5391d8"
border.width: 1
}
},
State {
name: "logsClosed"
PropertyChanges {
target: statusContainer
border.color: "#5391d8"
border.width: 0
}
}
]
Text {
anchors.verticalCenter: parent.verticalCenter
anchors.horizontalCenter: parent.horizontalCenter
font.pointSize: StatusPaneStyle.general.statusFontSize
font.pointSize: Style.absoluteSize(-1)
height: 15
font.family: "sans serif"
objectName: "status"
@ -215,40 +202,39 @@ Rectangle {
{
if (logsContainer.state === "opened")
{
statusContainer.state = "logsClosed";
logsContainer.state = "closed"
}
else
{
statusContainer.state = "logsOpened";
logsContainer.state = "opened";
logsContainer.focus = true;
forceActiveFocus();
calCoord();
}
}
id: logsContainer
width: 1000
height: 0
anchors.topMargin: 10
width: 750
anchors.top: statusContainer.bottom
anchors.horizontalCenter: parent.horizontalCenter
anchors.topMargin: 4
visible: false
radius: 5
Component.onCompleted:
radius: 10
function calCoord()
{
var top = logsContainer;
while (top.parent)
top = top.parent
var coordinates = logsContainer.mapToItem(top, 0, 0)
var coordinates = logsContainer.mapToItem(top, 0, 0);
logsContainer.parent = top;
logsContainer.x = coordinates.x
logsContainer.y = coordinates.y
logsContainer.x = status.x + statusContainer.x - LogsPaneStyle.generic.layout.dateWidth - LogsPaneStyle.generic.layout.typeWidth + 70
}
LogsPane
{
id: logPane
id: logPane;
}
states: [
State {
name: "opened";
@ -257,12 +243,13 @@ Rectangle {
State {
name: "closed";
PropertyChanges { target: logsContainer; height: 0; visible: false }
PropertyChanges { target: statusContainer; width: 600; height: 30 }
}
]
transitions: Transition {
NumberAnimation { properties: "height"; easing.type: Easing.InOutQuad; duration: 200 }
NumberAnimation { properties: "visible"; easing.type: Easing.InOutQuad; duration: 200 }
}
NumberAnimation { target: logsContainer; properties: "visible"; easing.type: Easing.InOutQuad; duration: 200 }
}
}
}

59
mix/qml/TransactionLog.qml

@ -6,30 +6,16 @@ import QtQuick.Layouts 1.1
import org.ethereum.qml.RecordLogEntry 1.0
Item {
property ListModel fullModel: ListModel{}
property ListModel transactionModel: ListModel{}
property ListModel callModel: ListModel{}
Action {
id: addStateAction
text: "Add State"
shortcut: "Ctrl+Alt+T"
enabled: codeModel.hasContract && !clientModel.running;
onTriggered: projectModel.stateListModel.addState();
}
Action {
id: editStateAction
text: "Edit State"
shortcut: "Ctrl+Alt+T"
enabled: codeModel.hasContract && !clientModel.running && statesCombo.currentIndex >= 0 && projectModel.stateListModel.count > 0;
onTriggered: projectModel.stateListModel.editState(statesCombo.currentIndex);
}
property int selectedStateIndex: statesCombo.selectedIndex
ColumnLayout {
anchors.fill: parent
RowLayout {
anchors.right: parent.right
anchors.left: parent.left
Connections
{
id: compilationStatus
@ -61,36 +47,24 @@ Item {
}
}
ComboBox {
StatesComboBox
{
id: statesCombo
model: projectModel.stateListModel
width: 150
editable: false
textRole: "title"
onActivated: {
model.runState(index);
}
items: projectModel.stateListModel
onSelectCreate: projectModel.stateListModel.addState();
onEditItem: projectModel.stateListModel.editState(item)
colorItem: "#808080"
colorSelect: "#4a90e2"
color: "white"
Connections {
target: projectModel.stateListModel
onStateRun: {
if (statesCombo.currentIndex !== index)
statesCombo.currentIndex = index;
if (statesCombo.selectedIndex !== index)
statesCombo.setSelectedIndex( index );
}
}
}
Button
{
anchors.rightMargin: 9
anchors.verticalCenter: parent.verticalCenter
action: editStateAction
}
Button
{
anchors.rightMargin: 9
anchors.verticalCenter: parent.verticalCenter
action: addStateAction
}
Button
{
anchors.rightMargin: 9
anchors.verticalCenter: parent.verticalCenter
@ -163,16 +137,11 @@ Item {
Keys.onPressed: {
if ((event.modifiers & Qt.ControlModifier) && event.key === Qt.Key_C && currentRow >=0 && currentRow < logTable.model.count) {
var item = logTable.model.get(currentRow);
clipboard.text = item.returned;
appContext.toClipboard(item.returned);
}
}
}
Rectangle {
height: 6
color: "transparent"
}
}
Connections {
target: clientModel
onStateCleared: {

2
mix/qml/WebPreview.qml

@ -156,7 +156,7 @@ Item {
if (urlPath === "/")
urlPath = "/index.html";
var documentName = urlPath.substr(urlPath.lastIndexOf("/") + 1);
var documentId = projectModel.codeEditor.getDocumentIdByName(documentName);
var documentId = projectModel.getDocumentIdByName(documentName);
var content = "";
if (projectModel.codeEditor.isDocumentOpen(documentId))
content = projectModel.codeEditor.getDocumentText(documentId);

2
mix/qml/html/codeeditor.js

@ -124,8 +124,6 @@ var executionMark;
highlightExecution = function(start, end) {
if (executionMark)
executionMark.clear();
if (start === 0 && end + 1 === editor.getValue().length)
return; // Do not hightlight the whole document.
if (debugWarning)
debugWarning.clear();
executionMark = editor.markText(editor.posFromIndex(start), editor.posFromIndex(end), { className: "CodeMirror-exechighlight" });

BIN
mix/qml/img/broom.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 501 B

BIN
mix/qml/img/clearicon.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

BIN
mix/qml/img/cleariconactive.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

BIN
mix/qml/img/copyicon.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 871 B

BIN
mix/qml/img/copyiconactive.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 875 B

BIN
mix/qml/img/edit_combox.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 406 B

BIN
mix/qml/img/pause_button.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 200 B

BIN
mix/qml/img/pause_button2x.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 414 B

BIN
mix/qml/img/play_button.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 531 B

BIN
mix/qml/img/play_button2x.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 904 B

BIN
mix/qml/img/searchicon.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

BIN
mix/qml/img/stop_button2x.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 235 B

10
mix/qml/js/ProjectModel.js

@ -172,7 +172,7 @@ function getDocumentIndex(documentId)
for (var i = 0; i < projectListModel.count; i++)
if (projectListModel.get(i).documentId === documentId)
return i;
console.error("Cant find document " + documentId);
console.error("Can't find document " + documentId);
return -1;
}
@ -291,6 +291,14 @@ function getDocument(documentId) {
return projectListModel.get(i);
}
function getDocumentIdByName(fileName)
{
for (var i = 0; i < projectListModel.count; i++)
if (projectListModel.get(i).fileName === fileName)
return projectListModel.get(i).documentId;
return null;
}
function removeDocument(documentId) {
var i = getDocumentIndex(documentId);
var document = projectListModel.get(i);

12
mix/res.qrc

@ -17,7 +17,6 @@
<file>qml/fonts/SourceSerifPro-Semibold.ttf</file>
<file>qml/img/available_updates.png</file>
<file>qml/img/b64.png</file>
<file>qml/img/broom.png</file>
<file>qml/img/bugiconactive.png</file>
<file>qml/img/bugiconinactive.png</file>
<file>qml/img/closedtriangleindicator.png</file>
@ -49,9 +48,20 @@
<file>qml/img/projecticon.png</file>
<file>qml/img/run.png</file>
<file>qml/img/search_filled.png</file>
<file>qml/img/play_button2x.png</file>
<file>qml/img/play_button.png</file>
<file>qml/img/pause_button2x.png</file>
<file>qml/img/pause_button.png</file>
<file>res/mix_256x256x32.png</file>
<file>stdc/config.sol</file>
<file>stdc/namereg.sol</file>
<file>stdc/std.sol</file>
<file>qml/img/edit_combox.png</file>
<file>qml/img/clearicon.png</file>
<file>qml/img/cleariconactive.png</file>
<file>qml/img/copyicon.png</file>
<file>qml/img/copyiconactive.png</file>
<file>qml/img/searchicon.png</file>
<file>qml/img/stop_button2x.png</file>
</qresource>
</RCC>

14
test/SolidityNameAndTypeResolution.cpp

@ -460,7 +460,7 @@ BOOST_AUTO_TEST_CASE(function_external_types)
uint a;
}
contract Test {
function boo(uint arg2, bool arg3, bytes8 arg4, bool[2] pairs, uint[] dynamic, C carg) external returns (uint ret) {
function boo(uint arg2, bool arg3, bytes8 arg4, bool[2] pairs, uint[] dynamic, C carg, address[] addresses) external returns (uint ret) {
ret = 5;
}
})";
@ -471,7 +471,7 @@ BOOST_AUTO_TEST_CASE(function_external_types)
auto functions = contract->getDefinedFunctions();
if (functions.empty())
continue;
BOOST_CHECK_EQUAL("boo(uint256,bool,bytes8,bool[2],uint256[],address)", functions[0]->externalSignature());
BOOST_CHECK_EQUAL("boo(uint256,bool,bytes8,bool[2],uint256[],address,address[])", functions[0]->externalSignature());
}
}
@ -503,6 +503,16 @@ BOOST_AUTO_TEST_CASE(function_external_call_not_allowed_conversion)
BOOST_CHECK_THROW(parseTextAndResolveNames(text), TypeError);
}
// todo delete when implemented
BOOST_AUTO_TEST_CASE(arrays_in_internal_functions)
{
char const* text = R"(
contract Test {
function foo(address[] addresses) {}
})";
BOOST_CHECK_THROW(parseTextAndResolveNames(text), TypeError);
}
BOOST_AUTO_TEST_CASE(function_internal_allowed_conversion)
{
char const* text = R"(

114
test/stMemoryTestFiller.json

@ -1461,7 +1461,7 @@
}
},
"stackLimitPush32_1024": {
"stackLimitPush32_1023": {
"env" : {
"previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6",
"currentNumber" : "0",
@ -1495,7 +1495,7 @@
}
},
"stackLimitPush32_1025": {
"stackLimitPush32_1024": {
"env" : {
"previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6",
"currentNumber" : "0",
@ -1529,7 +1529,41 @@
}
},
"stackLimitPush31_1024": {
"stackLimitPush32_1025": {
"env" : {
"previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6",
"currentNumber" : "0",
"currentGasLimit" : "42949672960",
"currentDifficulty" : "256",
"currentTimestamp" : "1",
"currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba"
},
"pre" : {
"0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : {
"balance" : "1000000000000000000",
"nonce" : "0",
"code" : "(asm 1023 0x00 MSTORE JUMPDEST 0x0102030405060708090a0102030405060708090a0102030405060708090a0102 0x01 0x00 MLOAD SUB 0x00 MSTORE 0x00 MLOAD 0x06 JUMPI STOP )",
"storage": {}
},
"a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
"balance" : "429496729600",
"nonce" : "0",
"code" : "",
"storage": {}
}
},
"transaction" : {
"nonce" : "0",
"gasPrice" : "1",
"gasLimit" : "100000",
"to" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6",
"value" : "10",
"secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8",
"data" : ""
}
},
"stackLimitPush31_1023": {
"env" : {
"previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6",
"currentNumber" : "0",
@ -1563,7 +1597,7 @@
}
},
"stackLimitPush31_1025": {
"stackLimitPush31_1024": {
"env" : {
"previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6",
"currentNumber" : "0",
@ -1597,7 +1631,41 @@
}
},
"stackLimitGas_1024": {
"stackLimitPush31_1025": {
"env" : {
"previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6",
"currentNumber" : "0",
"currentGasLimit" : "42949672960",
"currentDifficulty" : "256",
"currentTimestamp" : "1",
"currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba"
},
"pre" : {
"0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : {
"balance" : "1000000000000000000",
"nonce" : "0",
"code" : "(asm 1023 0x00 MSTORE JUMPDEST 0x0102030405060708090a0102030405060708090a0102030405060708090a01 0x01 0x00 MLOAD SUB 0x00 MSTORE 0x00 MLOAD 0x06 JUMPI STOP )",
"storage": {}
},
"a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
"balance" : "429496729600",
"nonce" : "0",
"code" : "",
"storage": {}
}
},
"transaction" : {
"nonce" : "0",
"gasPrice" : "1",
"gasLimit" : "100000",
"to" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6",
"value" : "10",
"secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8",
"data" : ""
}
},
"stackLimitGas_1023": {
"env" : {
"previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6",
"currentNumber" : "0",
@ -1631,7 +1699,7 @@
}
},
"stackLimitGas_1025": {
"stackLimitGas_1024": {
"env" : {
"previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6",
"currentNumber" : "0",
@ -1665,6 +1733,40 @@
}
},
"stackLimitGas_1025": {
"env" : {
"previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6",
"currentNumber" : "0",
"currentGasLimit" : "42949672960",
"currentDifficulty" : "256",
"currentTimestamp" : "1",
"currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba"
},
"pre" : {
"0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : {
"balance" : "1000000000000000000",
"nonce" : "0",
"code" : "(asm 1023 0x00 MSTORE JUMPDEST GAS 0x01 0x00 MLOAD SUB 0x00 MSTORE 0x00 MLOAD 0x06 JUMPI STOP )",
"storage": {}
},
"a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
"balance" : "429496729600",
"nonce" : "0",
"code" : "",
"storage": {}
}
},
"transaction" : {
"nonce" : "0",
"gasPrice" : "1",
"gasLimit" : "100000",
"to" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6",
"value" : "10",
"secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8",
"data" : ""
}
},
"mstroe8_dejavu": {
"env" : {
"previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6",

Loading…
Cancel
Save