diff --git a/README.md b/README.md index cfa223a56..7b9a78e6c 100644 --- a/README.md +++ b/README.md @@ -1,14 +1,11 @@ ## Ethereum C++ Client. -[![Build -Status](http://build.ethdev.com/buildstatusimage?builder=Linux%20C%2B%2B%20master%20branch)](http://build.ethdev.com/builders/Linux%20C%2B%2B%20master%20branch/builds/-1) master [![Build -Status](http://build.ethdev.com/buildstatusimage?builder=Linux%20C%2B%2B%20develop%20branch)](http://build.ethdev.com/builders/Linux%20C%2B%2B%20develop%20branch/builds/-1) develop - By Gav Wood, 2014. -[![Build -+Status](http://build.ethdev.com/buildstatusimage?builder=Linux%20C%2B%2B%20master%20branch)](http://build.ethdev.com/builders/Linux%20C%2B%2B%20master%20branch/builds/-1) master [![Build -+Status](http://build.ethdev.com/buildstatusimage?builder=Linux%20C%2B%2B%20develop%20branch)](http://build.ethdev.com/builders/Linux%20C%2B%2B%20develop%20branch/builds/-1) develop + | Linux | OSX | Windows +----------|---------|-----|-------- +develop | [![Build+Status](http://build.ethdev.com/buildstatusimage?builder=Linux%20C%2B%2B%20develop%20branch)](http://build.ethdev.com/builders/Linux%20C%2B%2B%20develop%20branch/builds/-1) | [![Build+Status](http://build.ethdev.com/buildstatusimage?builder=OSX%20C%2B%2B%20develop%20branch)](http://build.ethdev.com/builders/OSX%20C%2B%2B%20develop%20branch/builds/-1) | [![Build+Status](http://build.ethdev.com/buildstatusimage?builder=Windows%20C%2B%2B%20develop%20branch)](http://build.ethdev.com/builders/Windows%20C%2B%2B%20develop%20branch/builds/-1) +master | [![Build+Status](http://build.ethdev.com/buildstatusimage?builder=Linux%20C%2B%2B%20master%20branch)](http://build.ethdev.com/builders/Linux%20C%2B%2B%20master%20branch/builds/-1) | [![Build+Status](http://build.ethdev.com/buildstatusimage?builder=OSX%20C%2B%2B%20master%20branch)](http://build.ethdev.com/builders/OSX%20C%2B%2B%20master%20branch/builds/-1) | [![Build+Status](http://build.ethdev.com/buildstatusimage?builder=Windows%20C%2B%2B%20master%20branch)](http://build.ethdev.com/builders/Windows%20C%2B%2B%20master%20branch/builds/-1) [![Stories in Ready](https://badge.waffle.io/ethereum/cpp-ethereum.png?label=ready&title=Ready)](http://waffle.io/ethereum/cpp-ethereum) diff --git a/alethzero/Main.ui b/alethzero/Main.ui index 2ce00b0e3..97ed31aa9 100644 --- a/alethzero/Main.ui +++ b/alethzero/Main.ui @@ -95,8 +95,8 @@ - - + + about:blank @@ -1212,8 +1212,8 @@ 0 - - + + about:blank @@ -2035,7 +2035,7 @@ font-size: 14pt - false + true Claim Ether Presale &Wallet... diff --git a/alethzero/MainWin.cpp b/alethzero/MainWin.cpp index 73e7f2765..cf3411fdc 100644 --- a/alethzero/MainWin.cpp +++ b/alethzero/MainWin.cpp @@ -755,7 +755,7 @@ void Main::on_importKey_triggered() void Main::on_importKeyFile_triggered() { - QString s = QFileDialog::getOpenFileName(this, "Import Account", QDir::homePath(), "JSON Files (*.json);;All Files (*)"); + QString s = QFileDialog::getOpenFileName(this, "Claim Account Contents", QDir::homePath(), "JSON Files (*.json);;All Files (*)"); try { js::mValue val; @@ -785,8 +785,12 @@ void Main::on_importKeyFile_triggered() if (std::find(m_myKeys.begin(), m_myKeys.end(), k) == m_myKeys.end()) { - m_myKeys.append(k); - keysChanged(); + if (m_myKeys.empty()) + { + m_myKeys.push_back(KeyPair::create()); + keysChanged(); + } + ethereum()->transact(k.sec(), ethereum()->balanceAt(k.address()) - gasPrice() * c_txGas, m_myKeys.back().address(), {}, c_txGas, gasPrice()); } else QMessageBox::warning(this, "Already Have Key", "Could not import the secret key: we already own this account."); @@ -1093,7 +1097,7 @@ void Main::refreshBlockChain() auto b = bc.block(h); for (auto const& i: RLP(b)[1]) { - Transaction t(i.data()); + Transaction t(i.data(), CheckSignature::Sender); if (bm || transactionMatch(filter, t)) { QString s = t.receiveAddress() ? @@ -1381,7 +1385,7 @@ void Main::on_blocks_currentItemChanged() else { unsigned txi = item->data(Qt::UserRole + 1).toInt(); - Transaction tx(block[1][txi].data()); + Transaction tx(block[1][txi].data(), CheckSignature::Sender); auto ss = tx.safeSender(); h256 th = sha3(rlpList(ss, tx.nonce())); TransactionReceipt receipt = ethereum()->blockChain().receipts(h).receipts[txi]; @@ -1644,13 +1648,18 @@ static shh::Topic topicFromText(QString _s) return ret; } - bool Main::sourceIsSolidity(string const& _source) { // TODO: Improve this heuristic return (_source.substr(0, 8) == "contract" || _source.substr(0, 5) == "//sol"); } +static bool sourceIsSerpent(string const& _source) +{ + // TODO: Improve this heuristic + return (_source.substr(0, 5) == "//ser"); +} + string const Main::getFunctionHashes(dev::solidity::CompilerStack const &_compiler, string const& _contractName) { @@ -1685,6 +1694,7 @@ void Main::on_data_textChanged() dev::solidity::CompilerStack compiler; try { +// compiler.addSources(dev::solidity::StandardSources); m_data = compiler.compile(src, m_enableOptimizer); solidity = "

Solidity

"; solidity += "
" + QString::fromStdString(compiler.getInterface()).replace(QRegExp("\\s"), "").toHtmlEscaped() + "
"; @@ -1702,23 +1712,23 @@ void Main::on_data_textChanged() solidity = "

Solidity

Uncaught exception.
"; } } - else + else if (sourceIsSerpent(src)) { - m_data = compileLLL(src, m_enableOptimizer, &errors); - if (errors.size()) + try { - try - { - m_data = dev::asBytes(::compile(src)); - for (auto& i: errors) - i = "(LLL " + i + ")"; - } - catch (string err) - { - errors.push_back("Serpent " + err); - } + m_data = dev::asBytes(::compile(src)); + for (auto& i: errors) + i = "(LLL " + i + ")"; } - else + catch (string err) + { + errors.push_back("Serpent " + err); + } + } + else + { + m_data = compileLLL(src, m_enableOptimizer, &errors); + if (errors.empty()) { auto asmcode = compileLLLToAsm(src, false); lll = "

Pre

" + QString::fromStdString(asmcode).toHtmlEscaped() + "
"; @@ -1969,9 +1979,24 @@ void Main::on_debug_clicked() } } +bool beginsWith(Address _a, bytes const& _b) +{ + for (unsigned i = 0; i < min(20, _b.size()); ++i) + if (_a[i] != _b[i]) + return false; + return true; +} + void Main::on_create_triggered() { - m_myKeys.append(KeyPair::create()); + bool ok = true; + QString s = QInputDialog::getText(this, "Special Beginning?", "If you want a special key, enter some hex digits that it should begin with.\nNOTE: The more you enter, the longer generation will take.", QLineEdit::Normal, QString(), &ok); + if (!ok) + return; + KeyPair p; + while (!beginsWith(p.address(), asBytes(s.toStdString()))) + p = KeyPair::create(); + m_myKeys.append(p); keysChanged(); } diff --git a/libethereum/Client.cpp b/libethereum/Client.cpp index 41f0bcfbc..fcc18c2d1 100644 --- a/libethereum/Client.cpp +++ b/libethereum/Client.cpp @@ -642,7 +642,7 @@ Transaction Client::transaction(h256 _blockHash, unsigned _i) const { auto bl = m_bc.block(_blockHash); RLP b(bl); - return Transaction(b[1][_i].data()); + return Transaction(b[1][_i].data(), CheckSignature::Range); } BlockInfo Client::uncle(h256 _blockHash, unsigned _i) const diff --git a/libethereum/Executive.cpp b/libethereum/Executive.cpp index 6f6776493..dc2e62824 100644 --- a/libethereum/Executive.cpp +++ b/libethereum/Executive.cpp @@ -53,7 +53,7 @@ void Executive::accrueSubState(SubState& _parentContext) bool Executive::setup(bytesConstRef _rlp) { // Entry point for a user-executed transaction. - m_t = Transaction(_rlp); + m_t = Transaction(_rlp, CheckSignature::Sender); // Avoid invalid transactions. auto nonceReq = m_s.transactionsFrom(m_t.sender()); diff --git a/libethereum/State.cpp b/libethereum/State.cpp index 9ed9a3a3a..5232144c2 100644 --- a/libethereum/State.cpp +++ b/libethereum/State.cpp @@ -395,7 +395,7 @@ bool State::cull(TransactionQueue& _tq) const { try { - Transaction t(i.second); + Transaction t(i.second, CheckSignature::Sender); if (t.nonce() <= transactionsFrom(t.sender())) { _tq.drop(i.first); diff --git a/libethereum/Transaction.cpp b/libethereum/Transaction.cpp index 24c56930e..345e379af 100644 --- a/libethereum/Transaction.cpp +++ b/libethereum/Transaction.cpp @@ -30,7 +30,7 @@ using namespace dev::eth; #define ETH_ADDRESS_DEBUG 0 -Transaction::Transaction(bytesConstRef _rlpData, bool _checkSender) +Transaction::Transaction(bytesConstRef _rlpData, CheckSignature _checkSig) { int field = 0; RLP rlp(_rlpData); @@ -46,8 +46,14 @@ Transaction::Transaction(bytesConstRef _rlpData, bool _checkSender) byte v = rlp[field = 6].toInt() - 27; h256 r = rlp[field = 7].toInt(); h256 s = rlp[field = 8].toInt(); + + if (rlp.itemCount() > 9) + BOOST_THROW_EXCEPTION(BadRLP() << errinfo_comment("to many fields in the transaction RLP")); + m_vrs = SignatureStruct{ r, s, v }; - if (_checkSender) + if (_checkSig >= CheckSignature::Range && !m_vrs.isValid()) + BOOST_THROW_EXCEPTION(InvalidSignature()); + if (_checkSig == CheckSignature::Sender) m_sender = sender(); } catch (Exception& _e) diff --git a/libethereum/Transaction.h b/libethereum/Transaction.h index 490a2ac68..0f88a4bc0 100644 --- a/libethereum/Transaction.h +++ b/libethereum/Transaction.h @@ -37,6 +37,13 @@ enum IncludeSignature WithSignature = 1, ///< Do include a signature. }; +enum class CheckSignature +{ + None, + Range, + Sender +}; + /// Encodes a transaction, ready to be exported to or freshly imported from RLP. class Transaction { @@ -57,10 +64,10 @@ public: Transaction(u256 _value, u256 _gasPrice, u256 _gas, bytes const& _data): m_type(ContractCreation), m_value(_value), m_gasPrice(_gasPrice), m_gas(_gas), m_data(_data) {} /// Constructs a transaction from the given RLP. - explicit Transaction(bytesConstRef _rlp, bool _checkSender = false); + explicit Transaction(bytesConstRef _rlp, CheckSignature _checkSig); /// Constructs a transaction from the given RLP. - explicit Transaction(bytes const& _rlp, bool _checkSender = false): Transaction(&_rlp, _checkSender) {} + explicit Transaction(bytes const& _rlp, CheckSignature _checkSig): Transaction(&_rlp, _checkSig) {} /// Checks equality of transactions. diff --git a/libethereum/TransactionQueue.cpp b/libethereum/TransactionQueue.cpp index 6248f38c9..5701fc4a5 100644 --- a/libethereum/TransactionQueue.cpp +++ b/libethereum/TransactionQueue.cpp @@ -42,7 +42,7 @@ bool TransactionQueue::import(bytesConstRef _transactionRLP) // Check validity of _transactionRLP as a transaction. To do this we just deserialise and attempt to determine the sender. // If it doesn't work, the signature is bad. // The transaction's nonce may yet be invalid (or, it could be "valid" but we may be missing a marginally older transaction). - Transaction t(_transactionRLP, true); + Transaction t(_transactionRLP, CheckSignature::Sender); UpgradeGuard ul(l); // If valid, append to blocks. @@ -69,14 +69,14 @@ void TransactionQueue::setFuture(std::pair const& _t) if (m_current.count(_t.first)) { m_current.erase(_t.first); - m_unknown.insert(make_pair(Transaction(_t.second).sender(), _t)); + m_unknown.insert(make_pair(Transaction(_t.second, CheckSignature::Sender).sender(), _t)); } } void TransactionQueue::noteGood(std::pair const& _t) { WriteGuard l(m_lock); - auto r = m_unknown.equal_range(Transaction(_t.second).sender()); + auto r = m_unknown.equal_range(Transaction(_t.second, CheckSignature::Sender).sender()); for (auto it = r.first; it != r.second; ++it) m_current.insert(it->second); m_unknown.erase(r.first, r.second); diff --git a/liblll/CodeFragment.cpp b/liblll/CodeFragment.cpp index 2c200caa5..1e7766434 100644 --- a/liblll/CodeFragment.cpp +++ b/liblll/CodeFragment.cpp @@ -266,7 +266,6 @@ void CodeFragment::constructOperation(sp::utree const& _t, CompilerState& _s) } ++ii; } - } else if (us == "LIT") { diff --git a/liblll/CodeFragment.h b/liblll/CodeFragment.h index b24b474da..554f90b46 100644 --- a/liblll/CodeFragment.h +++ b/liblll/CodeFragment.h @@ -61,3 +61,4 @@ static const CodeFragment NullCodeFragment; } } + diff --git a/libsolidity/CompilerStack.cpp b/libsolidity/CompilerStack.cpp index 790eb983a..c05756167 100644 --- a/libsolidity/CompilerStack.cpp +++ b/libsolidity/CompilerStack.cpp @@ -21,6 +21,7 @@ * Full-stack compiler that converts a source code string to bytecode. */ +#include #include #include #include @@ -123,9 +124,49 @@ void CompilerStack::compile(bool _optimize) } } +string CompilerStack::expanded(string const& _sourceCode) +{ + // TODO: populate some nicer way. + static const map c_requires = { + { "Config", "contract Config{function lookup(uint256 service)constant returns(address a){}function kill(){}function unregister(uint256 id){}function register(uint256 id,address service){}}" }, + { "owned", "contract owned{function owned(){owner = msg.sender;}address owner;}" }, + { "mortal", "#require owned\ncontract mortal is owned {function kill() { if (msg.sender == owner) suicide(owner); }}" }, + { "NameReg", "contract NameReg{function register(string32 name){}function addressOf(string32 name)constant returns(address addr){}function unregister(){}function nameOf(address addr)constant returns(string32 name){}}" }, + { "named", "#require Config NameReg\ncontract named is mortal, owned {function named(string32 name) {NameReg(Config().lookup(1)).register(name);}" }, + { "std", "#require owned mortal Config NameReg named" }, + }; + string sub; + set got; + function localExpanded; + localExpanded = [&](string const& s) -> string + { + string ret = s; + for (size_t p = 0; p != string::npos;) + if ((p = ret.find("#require ")) != string::npos) + { + string n = ret.substr(p + 9, ret.find_first_of('\n', p + 9) - p - 9); + ret.replace(p, n.size() + 9, ""); + vector rs; + boost::split(rs, n, boost::is_any_of(" \t,"), boost::token_compress_on); + for (auto const& r: rs) + if (!got.count(r)) + { + if (c_requires.count(r)) + sub.append("\n" + localExpanded(c_requires.at(r)) + "\n"); + got.insert(r); + } + } + // TODO: remove once we have genesis contracts. + else if ((p = ret.find("Config()")) != string::npos) + ret.replace(p, 8, "Config(0x661005d2720d855f1d9976f88bb10c1a3398c77f)"); + return ret; + }; + return sub + localExpanded(_sourceCode); +} + bytes const& CompilerStack::compile(string const& _sourceCode, bool _optimize) { - parse(_sourceCode); + parse(expanded(_sourceCode)); compile(_optimize); return getBytecode(); } diff --git a/libsolidity/CompilerStack.h b/libsolidity/CompilerStack.h index aa55abe50..68c82a350 100644 --- a/libsolidity/CompilerStack.h +++ b/libsolidity/CompilerStack.h @@ -138,6 +138,10 @@ private: Contract(); }; + /// Expand source code with preprocessor-like includes. + /// @todo Replace with better framework. + std::string expanded(std::string const& _sourceCode); + void reset(bool _keepSources = false); void resolveImports(); diff --git a/mix/AssemblyDebuggerControl.cpp b/mix/AssemblyDebuggerControl.cpp index f68ddc792..f52245450 100644 --- a/mix/AssemblyDebuggerControl.cpp +++ b/mix/AssemblyDebuggerControl.cpp @@ -49,5 +49,5 @@ void AssemblyDebuggerControl::start() const void AssemblyDebuggerControl::showDebugger() { QObject* debugPanel = m_view->findChild("debugPanel", Qt::FindChildrenRecursively); - QMetaObject::invokeMethod(debugPanel, "update"); + QMetaObject::invokeMethod(debugPanel, "update", Q_ARG(QVariant, true)); } diff --git a/mix/ClientModel.cpp b/mix/ClientModel.cpp index 6412e347c..0b3d44d64 100644 --- a/mix/ClientModel.cpp +++ b/mix/ClientModel.cpp @@ -103,7 +103,10 @@ void ClientModel::debugState(QVariantMap _state) TransactionSettings transactionSettings(functionId, value, gas, gasPrice); for (auto p = params.cbegin(); p != params.cend(); ++p) - transactionSettings.parameterValues.insert(std::make_pair(p.key(), (qvariant_cast(p.value()))->toU256Wei())); + { + QBigInt* param = qvariant_cast(p.value()); + transactionSettings.parameterValues.insert(std::make_pair(p.key(), boost::get(param->internalValue()))); + } transactionSequence.push_back(transactionSettings); } diff --git a/mix/CodeModel.cpp b/mix/CodeModel.cpp index 90326601c..9a33e18ee 100644 --- a/mix/CodeModel.cpp +++ b/mix/CodeModel.cpp @@ -61,7 +61,7 @@ CompilationResult::CompilationResult(const dev::solidity::CompilerStack& _compil m_bytes = _compiler.getBytecode(); m_assemblyCode = QString::fromStdString(dev::eth::disassemble(m_bytes)); dev::solidity::InterfaceHandler interfaceHandler; - m_contractDefinition = QString::fromStdString(*interfaceHandler.getABIInterface(contractDefinition)); + m_contractInterface = QString::fromStdString(*interfaceHandler.getABIInterface(contractDefinition)); } else m_contract.reset(new QContractDefinition()); @@ -75,7 +75,7 @@ CompilationResult::CompilationResult(CompilationResult const& _prev, QString con m_compilerMessage(_compilerMessage), m_bytes(_prev.m_bytes), m_assemblyCode(_prev.m_assemblyCode), - m_contractDefinition(_prev.m_contractDefinition), + m_contractInterface(_prev.m_contractInterface), m_codeHighlighter(_prev.m_codeHighlighter) {} @@ -164,7 +164,7 @@ void CodeModel::runCompilationJob(int _jobId, QString const& _code) void CodeModel::onCompilationComplete(CompilationResult* _newResult) { m_compiling = false; - bool contractChanged = m_result->contractDefinition() != _newResult->contractDefinition(); + bool contractChanged = m_result->contractInterface() != _newResult->contractInterface(); m_result.reset(_newResult); emit compilationComplete(); emit stateChanged(); @@ -172,7 +172,7 @@ void CodeModel::onCompilationComplete(CompilationResult* _newResult) { emit codeChanged(); if (contractChanged) - emit contractDefinitionChanged(); + emit contractInterfaceChanged(); } } diff --git a/mix/CodeModel.h b/mix/CodeModel.h index d747c530b..365d2d580 100644 --- a/mix/CodeModel.h +++ b/mix/CodeModel.h @@ -67,7 +67,7 @@ class CompilationResult: public QObject Q_PROPERTY(QContractDefinition* contract READ contract) Q_PROPERTY(QString compilerMessage READ compilerMessage CONSTANT) Q_PROPERTY(bool successful READ successful CONSTANT) - Q_PROPERTY(QString contractDefinition READ contractDefinition CONSTANT) + Q_PROPERTY(QString contractInterface READ contractInterface CONSTANT) public: /// Empty compilation result constructor @@ -90,7 +90,7 @@ public: /// @returns contract bytecode in human-readable form QString assemblyCode() const { return m_assemblyCode; } /// @returns contract definition in JSON format - QString contractDefinition() const { return m_contractDefinition; } + QString contractInterface() const { return m_contractInterface; } /// Get code highlighter std::shared_ptr codeHighlighter() { return m_codeHighlighter; } @@ -101,7 +101,7 @@ private: QString m_compilerMessage; ///< @todo: use some structure here dev::bytes m_bytes; QString m_assemblyCode; - QString m_contractDefinition; + QString m_contractInterface; std::shared_ptr m_codeHighlighter; friend class CodeModel; @@ -142,7 +142,7 @@ signals: /// Emitted if there are any changes in the code model void codeChanged(); /// Emitted if there are any changes in the contract interface - void contractDefinitionChanged(); + void contractInterfaceChanged(); /// Emitted on compilation complete. Internal void compilationCompleteInternal(CompilationResult* _newResult); diff --git a/mix/DebuggingStateWrapper.cpp b/mix/DebuggingStateWrapper.cpp index 69f5c2ee5..1eacac120 100644 --- a/mix/DebuggingStateWrapper.cpp +++ b/mix/DebuggingStateWrapper.cpp @@ -86,9 +86,8 @@ QBigInt* DebuggingStateWrapper::newMemSize() QStringList DebuggingStateWrapper::debugStack() { QStringList stack; - for (auto i: m_state.stack) - stack.append(QString::fromStdString(prettyU256(i))); - + for (std::vector::reverse_iterator i = m_state.stack.rbegin(); i != m_state.stack.rend(); ++i) + stack.append(QString::fromStdString(prettyU256(*i))); return fillList(stack, ""); } diff --git a/mix/main.cpp b/mix/main.cpp index 69bb9df4a..f7213f0fc 100644 --- a/mix/main.cpp +++ b/mix/main.cpp @@ -21,6 +21,7 @@ */ #include +#include #include "MixApplication.h" #include "Exceptions.h" using namespace dev::mix; @@ -29,6 +30,11 @@ int main(int _argc, char* _argv[]) { #ifdef ETH_HAVE_WEBENGINE Q_INIT_RESOURCE(js); +#endif +#if __linux + //work around ubuntu appmenu-qt5 bug + //https://bugs.launchpad.net/ubuntu/+source/appmenu-qt5/+bug/1323853 + putenv((char*)"QT_QPA_PLATFORMTHEME="); #endif try { diff --git a/mix/qml.qrc b/mix/qml.qrc index e8ed9bb64..1c7bb2d17 100644 --- a/mix/qml.qrc +++ b/mix/qml.qrc @@ -41,5 +41,6 @@ qml/Ether.qml qml/EtherValue.qml qml/BigIntValue.qml + qml/Splitter.qml diff --git a/mix/qml/DebugBasicInfo.qml b/mix/qml/DebugBasicInfo.qml index 3e28aa4c1..d92390ec2 100644 --- a/mix/qml/DebugBasicInfo.qml +++ b/mix/qml/DebugBasicInfo.qml @@ -5,8 +5,6 @@ import QtQuick.Controls.Styles 1.1 RowLayout { property string titleStr - width: parent.width - height: parent.height / 4 function update(_value) { @@ -14,7 +12,7 @@ RowLayout { } Rectangle { - width: parent.width / 2 + width: 120 height: parent.height color: "#e5e5e5" Text diff --git a/mix/qml/DebugInfoList.qml b/mix/qml/DebugInfoList.qml index 6f65cc30d..cad2a4c9e 100644 --- a/mix/qml/DebugInfoList.qml +++ b/mix/qml/DebugInfoList.qml @@ -9,6 +9,23 @@ ColumnLayout { property bool collapsible; property Component itemDelegate spacing: 0 + + function collapse() + { + storageContainer.state = "collapsed"; + } + + function show() + { + storageContainer.state = ""; + } + + Component.onCompleted: + { + if (storageContainer.parent.parent.height === 25) + storageContainer.state = "collapsed"; + } + RowLayout { height: 25 id: header @@ -17,7 +34,6 @@ ColumnLayout { width: 15 sourceSize.width: 15 id: storageImgArrow - visible: collapsible } Text { @@ -32,52 +48,50 @@ ColumnLayout { enabled: collapsible anchors.fill: parent onClicked: { - if (storageContainer.state == "collapsed") - storageContainer.state = ""; - else - storageContainer.state = "collapsed"; + if (collapsible) + { + if (storageContainer.state == "collapsed") + { + storageContainer.state = ""; + storageContainer.parent.parent.height = storageContainer.parent.parent.Layout.maximumHeight; + } + else + storageContainer.state = "collapsed"; + } } } } - - RowLayout + Rectangle { - height: parent.height - header.height - clip: true - Rectangle - { - height: parent.height - border.width: 3 - border.color: "#deddd9" - Layout.fillWidth: true - states: [ - State { - name: "collapsed" - PropertyChanges { - target: storageContainer.parent - height: 0 - visible: false - } - PropertyChanges { - target: storageImgArrow - source: "qrc:/qml/img/closedtriangleindicator.png" - } + border.width: 3 + border.color: "#deddd9" + Layout.fillWidth: true + Layout.fillHeight: true + states: [ + State { + name: "collapsed" + PropertyChanges { + target: storageImgArrow + source: "qrc:/qml/img/closedtriangleindicator.png" + } + PropertyChanges { + target: storageContainer.parent.parent + height: 25 } - ] - id: storageContainer - width: parent.width - ListView { - clip: true; - anchors.top: parent.top - anchors.left: parent.left - anchors.topMargin: 3 - anchors.leftMargin: 3 - width: parent.width - 3 - height: parent.height - 6 - id: storageList - model: listModel - delegate: itemDelegate } + ] + id: storageContainer + ListView { + clip: true; + anchors.top: parent.top + anchors.left: parent.left + anchors.topMargin: 3 + anchors.leftMargin: 3 + width: parent.width - 3 + height: parent.height - 6 + id: storageList + model: listModel + delegate: itemDelegate } } } diff --git a/mix/qml/Debugger.qml b/mix/qml/Debugger.qml index ac449065b..47975db83 100644 --- a/mix/qml/Debugger.qml +++ b/mix/qml/Debugger.qml @@ -3,6 +3,7 @@ import QtQuick.Controls.Styles 1.1 import QtQuick.Controls 1.1 import QtQuick.Dialogs 1.1 import QtQuick.Layouts 1.1 +import Qt.labs.settings 1.0 import "js/Debugger.js" as Debugger import "js/ErrorLocationFormater.js" as ErrorLocationFormater @@ -20,7 +21,13 @@ Rectangle { Debugger.moveSelection(-1); } - function update() + onVisibleChanged: + { + if (visible) + forceActiveFocus(); + } + + function update(giveFocus) { if (statusPane.result.successful) { @@ -39,11 +46,13 @@ Rectangle { errorDetail.text = errorInfo.errorDetail; errorLine.text = errorInfo.errorLine; } + if (giveFocus) + forceActiveFocus(); } Connections { target: codeModel - onCompilationComplete: update() + onCompilationComplete: update(false) } Rectangle @@ -95,413 +104,452 @@ Rectangle { } } - Flickable { - property int firstColumnWidth: 170 + property int firstColumnWidth: 180 property int secondColumnWidth: 250 id: debugScrollArea flickableDirection: Flickable.VerticalFlick anchors.fill: parent - contentHeight: machineStates.height + 300 - contentWidth: machineStates.width - - GridLayout + contentHeight: 4000 + contentWidth: parent.width + Rectangle { - property int sideMargin: 10 - id: machineStates - anchors.top: parent.top - anchors.topMargin: 15 - anchors.left: parent.left; - anchors.leftMargin: machineStates.sideMargin - anchors.right: parent.right; - anchors.rightMargin: machineStates.sideMargin - flow: GridLayout.TopToBottom - rowSpacing: 15 - RowLayout { - // step button + slider - spacing: machineStates.sideMargin - height: 27 - width: debugPanel.width - Rectangle - { - height: parent.height - color: "transparent" - width: debugScrollArea.firstColumnWidth - RowLayout { - anchors.horizontalCenter: parent.horizontalCenter - id: jumpButtons - spacing: 3 - StepActionImage - { - id: jumpOutBackAction; - enabledStateImg: "qrc:/qml/img/jumpoutback.png" - disableStateImg: "qrc:/qml/img/jumpoutbackdisabled.png" - onClicked: Debugger.stepOutBack() - width: 25 - height: 27 - } + anchors.fill: parent + ColumnLayout + { + property int sideMargin: 10 + id: machineStates + anchors.top: parent.top + anchors.topMargin: 15 + anchors.left: parent.left; + anchors.leftMargin: machineStates.sideMargin + anchors.right: parent.right; + anchors.rightMargin: machineStates.sideMargin + anchors.fill: parent + Layout.fillWidth: true + Layout.fillHeight: true + RowLayout { + // step button + slider + id: buttonRow + spacing: machineStates.sideMargin + height: 27 + Layout.fillWidth: true - StepActionImage - { - id: jumpIntoBackAction - enabledStateImg: "qrc:/qml/img/jumpintoback.png" - disableStateImg: "qrc:/qml/img/jumpintobackdisabled.png" - onClicked: Debugger.stepIntoBack() - width: 25 - height: 27 - } + Rectangle + { + height: parent.height + color: "transparent" + width: debugScrollArea.firstColumnWidth + RowLayout { + anchors.horizontalCenter: parent.horizontalCenter + id: jumpButtons + spacing: 3 + StepActionImage + { + id: jumpOutBackAction; + enabledStateImg: "qrc:/qml/img/jumpoutback.png" + disableStateImg: "qrc:/qml/img/jumpoutbackdisabled.png" + onClicked: Debugger.stepOutBack() + width: 28 + height: 30 + buttonTooltip: qsTr("Step Out Back") + } - StepActionImage - { - id: jumpOverBackAction - enabledStateImg: "qrc:/qml/img/jumpoverback.png" - disableStateImg: "qrc:/qml/img/jumpoverbackdisabled.png" - onClicked: Debugger.stepOverBack() - width: 25 - height: 27 - } + StepActionImage + { + id: jumpIntoBackAction + enabledStateImg: "qrc:/qml/img/jumpintoback.png" + disableStateImg: "qrc:/qml/img/jumpintobackdisabled.png" + onClicked: Debugger.stepIntoBack() + width: 28 + height: 30 + buttonTooltip: qsTr("Step Into Back") + } - StepActionImage - { - id: jumpOverForwardAction - enabledStateImg: "qrc:/qml/img/jumpoverforward.png" - disableStateImg: "qrc:/qml/img/jumpoverforwarddisabled.png" - onClicked: Debugger.stepOverForward() - width: 25 - height: 27 - } + StepActionImage + { + id: jumpOverBackAction + enabledStateImg: "qrc:/qml/img/jumpoverback.png" + disableStateImg: "qrc:/qml/img/jumpoverbackdisabled.png" + onClicked: Debugger.stepOverBack() + width: 28 + height: 30 + buttonTooltip: qsTr("Step Over Back") + } - StepActionImage - { - id: jumpIntoForwardAction - enabledStateImg: "qrc:/qml/img/jumpintoforward.png" - disableStateImg: "qrc:/qml/img/jumpintoforwarddisabled.png" - onClicked: Debugger.stepIntoForward() - width: 25 - height: 27 - } + StepActionImage + { + id: jumpOverForwardAction + enabledStateImg: "qrc:/qml/img/jumpoverforward.png" + disableStateImg: "qrc:/qml/img/jumpoverforwarddisabled.png" + onClicked: Debugger.stepOverForward() + width: 28 + height: 30 + buttonTooltip: qsTr("Step Over Forward") + } - StepActionImage - { - id: jumpOutForwardAction - enabledStateImg: "qrc:/qml/img/jumpoutforward.png" - disableStateImg: "qrc:/qml/img/jumpoutforwarddisabled.png" - onClicked: Debugger.stepOutForward() - width: 25 - height: 27 + StepActionImage + { + id: jumpIntoForwardAction + enabledStateImg: "qrc:/qml/img/jumpintoforward.png" + disableStateImg: "qrc:/qml/img/jumpintoforwarddisabled.png" + onClicked: Debugger.stepIntoForward() + width: 28 + height: 30 + buttonTooltip: qsTr("Step Into Forward") + } + + StepActionImage + { + id: jumpOutForwardAction + enabledStateImg: "qrc:/qml/img/jumpoutforward.png" + disableStateImg: "qrc:/qml/img/jumpoutforwarddisabled.png" + onClicked: Debugger.stepOutForward() + width: 28 + height: 30 + buttonTooltip: qsTr("Step Out Forward") + } } } - } - Rectangle { - color: "transparent" - width: debugScrollArea.secondColumnWidth - height: parent.height - Slider { - id: statesSlider - anchors.fill: parent - tickmarksEnabled: true - stepSize: 1.0 - onValueChanged: Debugger.jumpTo(value); - style: SliderStyle { - groove: Rectangle { - implicitHeight: 3 - color: "#7da4cd" - radius: 8 - } - handle: Rectangle { - anchors.centerIn: parent - color: control.pressed ? "white" : "lightgray" - border.color: "gray" - border.width: 2 - implicitWidth: 10 - implicitHeight: 10 - radius: 12 + + Rectangle { + color: "transparent" + Layout.fillWidth: true + height: parent.height + Slider { + id: statesSlider + anchors.fill: parent + tickmarksEnabled: true + stepSize: 1.0 + onValueChanged: Debugger.jumpTo(value); + style: SliderStyle { + groove: Rectangle { + implicitHeight: 3 + color: "#7da4cd" + radius: 8 + } + handle: Rectangle { + anchors.centerIn: parent + color: control.pressed ? "white" : "lightgray" + border.color: "gray" + border.width: 2 + implicitWidth: 10 + implicitHeight: 10 + radius: 12 + } } } } } - } - RowLayout { - // Assembly code - width: debugPanel.width - height: 405 - spacing: machineStates.sideMargin + RowLayout { + // Assembly code + id: assemblyCodeRow + Layout.fillWidth: true + height: 405 + implicitHeight: 405 + spacing: machineStates.sideMargin - Rectangle - { - width: debugScrollArea.firstColumnWidth - height: parent.height - border.width: 3 - border.color: "#deddd9" - color: "white" - anchors.top: parent.top - ListView { - anchors.fill: parent - anchors.leftMargin: 3 - anchors.rightMargin: 3 - anchors.topMargin: 3 - anchors.bottomMargin: 3 - clip: true - id: statesList - delegate: renderDelegate - highlight: highlightBar - highlightFollowsCurrentItem: true - } - - Component { - id: highlightBar - Rectangle { - radius: 4 - height: statesList.currentItem.height - width: statesList.currentItem.width; - color: "#4A90E2" - Behavior on y { SpringAnimation { spring: 2; damping: 0.1 } } + Rectangle + { + id: stateListContainer + width: debugScrollArea.firstColumnWidth + height: parent.height + border.width: 3 + border.color: "#deddd9" + color: "white" + anchors.top: parent.top + ListView { + anchors.fill: parent + anchors.leftMargin: 3 + anchors.rightMargin: 3 + anchors.topMargin: 3 + anchors.bottomMargin: 3 + clip: true + id: statesList + delegate: renderDelegate + highlight: highlightBar + highlightFollowsCurrentItem: false } - } - Component { - id: renderDelegate - RowLayout { - id: wrapperItem - height: 20 - width: parent.width - spacing: 5 - Text { - anchors.left: parent.left - anchors.leftMargin: 10 - width: 15 - color: "#b2b3ae" - text: line.split(' ')[0] - font.pointSize: 9 - id: id - wrapMode: Text.NoWrap + Component { + id: highlightBar + Rectangle { + radius: 4 + height: statesList.currentItem.height + width: statesList.currentItem.width; + y: statesList.currentItem.y + color: "#4A90E2" + Behavior on y { + PropertyAnimation { properties: "y"; easing.type: Easing.InOutQuad; duration: 50} + } } - Text { - wrapMode: Text.NoWrap - color: parent.ListView.isCurrentItem ? "white" : "black" - text: line.replace(line.split(' ')[0], '') - anchors.left: id.right - font.pointSize: 9 + } + + Component { + id: renderDelegate + RowLayout { + id: wrapperItem + height: 20 + width: parent.width + spacing: 5 + Text { + anchors.left: parent.left + anchors.leftMargin: 10 + width: 15 + color: "#b2b3ae" + text: line.split(' ')[0] + font.pointSize: 9 + id: id + wrapMode: Text.NoWrap + } + Text { + wrapMode: Text.NoWrap + color: parent.ListView.isCurrentItem ? "white" : "black" + text: line.replace(line.split(' ')[0], '') + anchors.left: id.right + font.pointSize: 9 + } } } } - } - ColumnLayout { - width: debugScrollArea.secondColumnWidth - height: parent.height Rectangle { - // Info - width: parent.width - id: basicInfoColumn - height: 125 - color: "transparent" - ColumnLayout { - spacing: 0 + Layout.fillWidth: true + height: parent.height //- 2 * stateListContainer.border.width + + ColumnLayout + { width: parent.width - height: parent.height + anchors.fill: parent + spacing: 0 DebugBasicInfo { id: currentStep - titleStr: qsTr("Current step") + titleStr: qsTr("Current Step") + Layout.fillWidth: true + height: 30 } DebugBasicInfo { id: mem - titleStr: qsTr("Adding memory") + titleStr: qsTr("Adding Memory") + Layout.fillWidth: true + height: 30 } DebugBasicInfo { id: stepCost - titleStr: qsTr("Step cost") + titleStr: qsTr("Step Cost") + Layout.fillWidth: true + height: 30 } DebugBasicInfo { id: gasSpent - titleStr: qsTr("Total gas spent") + titleStr: qsTr("Total Gas Spent") + Layout.fillWidth: true + height: 30 + } + DebugInfoList + { + Layout.fillHeight: true + Layout.fillWidth: true + id: stack + collapsible: false + title : qsTr("Stack") + itemDelegate: Item { + id: renderedItem + height: 25 + width: parent.width + RowLayout + { + anchors.fill: parent + Rectangle + { + id: indexColumn + color: "#f7f7f7" + Layout.fillWidth: true + Layout.minimumWidth: 30 + Layout.preferredWidth: 30 + Layout.maximumWidth: 30 + Layout.minimumHeight: parent.height + Text { + anchors.centerIn: parent + anchors.leftMargin: 5 + font.family: "monospace" + color: "#4a4a4a" + text: model.index; + font.pointSize: 9 + } + } + + Rectangle + { + anchors.left: indexColumn.right + Layout.fillWidth: true + Layout.minimumWidth: 15 + Layout.preferredWidth: 15 + Layout.maximumWidth: 60 + Layout.minimumHeight: parent.height + Text { + anchors.left: parent.left + anchors.leftMargin: 5 + font.family: "monospace" + anchors.verticalCenter: parent.verticalCenter + color: "#4a4a4a" + text: modelData + font.pointSize: 9 + } + } + } + + Rectangle { + id: separator + width: parent.width; + height: 1; + color: "#cccccc" + anchors.bottom: parent.bottom + } + } } } } + } - Rectangle { - // Stack - height: 275 - width: parent.width - color: "transparent" + SplitView + { + id: splitInfoList + Layout.fillHeight: true + Layout.fillWidth: true + + Settings { + id: splitSettings + property alias storageHeightSettings: storageRect.height + property alias memoryDumpHeightSettings: memoryRect.height + property alias callDataHeightSettings: callDataRect.height + } + orientation: Qt.Vertical + width: debugPanel.width - 2 * machineStates.sideMargin + Rectangle + { + id: storageRect + width: parent.width + Layout.minimumHeight: 25 + Layout.maximumHeight: 223 + height: 25 DebugInfoList { - id: stack - width: parent.width - height: parent.height - collapsible: false - title : qsTr("Stack") - itemDelegate: Item { - id: renderedItem + id: storage + anchors.fill: parent + collapsible: true + title : qsTr("Storage") + itemDelegate: + Item { height: 27 - width: parent.width + width: parent.width; RowLayout { - anchors.fill: parent + id: row + width: parent.width + height: 26 Rectangle { - id: indexColumn color: "#f7f7f7" Layout.fillWidth: true - Layout.minimumWidth: 30 - Layout.preferredWidth: 30 - Layout.maximumWidth: 30 + Layout.minimumWidth: parent.width / 2 + Layout.preferredWidth: parent.width / 2 + Layout.maximumWidth: parent.width / 2 Layout.minimumHeight: parent.height + Layout.maximumHeight: parent.height Text { - anchors.centerIn: parent + anchors.verticalCenter: parent.verticalCenter + anchors.left: parent.left + font.family: "monospace" anchors.leftMargin: 5 - color: "#8b8b8b" - text: model.index; + color: "#4a4a4a" + text: modelData.split(' ')[0].substring(0, 10); font.pointSize: 9 } } - Rectangle { - anchors.left: indexColumn.right + color: "transparent" Layout.fillWidth: true - Layout.minimumWidth: 15 - Layout.preferredWidth: 15 - Layout.maximumWidth: 60 + Layout.minimumWidth: parent.width / 2 + Layout.preferredWidth: parent.width / 2 + Layout.maximumWidth: parent.width / 2 Layout.minimumHeight: parent.height + Layout.maximumHeight: parent.height Text { - anchors.left: parent.left anchors.leftMargin: 5 + width: parent.width - 5 + wrapMode: Text.Wrap + anchors.left: parent.left + font.family: "monospace" anchors.verticalCenter: parent.verticalCenter - color: "#8b8b8b" - text: modelData + color: "#4a4a4a" + text: modelData.split(' ')[1].substring(0, 10); font.pointSize: 9 } } } Rectangle { - id: separator - width: parent.width; - height: 1; - color: "#cccccc" - anchors.bottom: parent.bottom - } + anchors.top: row.bottom + width: parent.width; + height: 1; + color: "#cccccc" + anchors.bottom: parent.bottom + } } } } - } - } - - Rectangle { - width: debugPanel.width - 2 * machineStates.sideMargin - height: 2; - color: "#e3e3e3" - radius: 3 - } - DebugInfoList - { - id: storage - width: debugPanel.width - 2 * machineStates.sideMargin - height: 223 - collapsible: true - title : qsTr("Storage") - itemDelegate: - Item { - height: 27 - width: parent.width; - RowLayout + Rectangle { - id: row + id: memoryRect; + height: 25 width: parent.width - height: 26 - Rectangle - { - color: "#f7f7f7" - Layout.fillWidth: true - Layout.minimumWidth: parent.width / 2 - Layout.preferredWidth: parent.width / 2 - Layout.maximumWidth: parent.width / 2 - Layout.minimumHeight: parent.height - Layout.maximumHeight: parent.height - Text { - anchors.verticalCenter: parent.verticalCenter - anchors.left: parent.left - anchors.leftMargin: 5 - color: "#8b8b8b" - text: modelData.split(' ')[0].substring(0, 10); - font.pointSize: 9 + Layout.minimumHeight: 25 + Layout.maximumHeight: 223 + DebugInfoList { + id: memoryDump + anchors.fill: parent + collapsible: true + title: qsTr("Memory Dump") + itemDelegate: + Item { + height: 29 + width: parent.width - 3; + ItemDelegateDataDump {} } } - Rectangle - { - color: "transparent" - Layout.fillWidth: true - Layout.minimumWidth: parent.width / 2 - Layout.preferredWidth: parent.width / 2 - Layout.maximumWidth: parent.width / 2 - Layout.minimumHeight: parent.height - Layout.maximumHeight: parent.height - Text { - anchors.leftMargin: 5 - width: parent.width - 5 - wrapMode: Text.Wrap - anchors.left: parent.left - anchors.verticalCenter: parent.verticalCenter - color: "#8b8b8b" - text: modelData.split(' ')[1].substring(0, 10); - font.pointSize: 9 + } + + Rectangle + { + id: callDataRect + height: 25 + width: parent.width + Layout.minimumHeight: 25 + Layout.maximumHeight: 223 + DebugInfoList { + id: callDataDump + anchors.fill: parent + collapsible: true + title: qsTr("Call Data") + itemDelegate: + Item { + height: 29 + width: parent.width - 3; + ItemDelegateDataDump {} } } } - - Rectangle { - anchors.top: row.bottom - width: parent.width; - height: 1; - color: "#cccccc" - anchors.bottom: parent.bottom - } - } - } - - Rectangle { - width: debugPanel.width - 2 * machineStates.sideMargin - height: 2; - color: "#e3e3e3" - radius: 3 - } - - DebugInfoList { - id: memoryDump - width: debugPanel.width - 2 * machineStates.sideMargin - height: 223 - collapsible: true - title: qsTr("Memory Dump") - itemDelegate: - Item { - height: 29 - width: parent.width - 3; - ItemDelegateDataDump {} - } - } - - Rectangle { - width: debugPanel.width - 2 * machineStates.sideMargin - height: 2; - color: "#e3e3e3" - radius: 3 - } - - DebugInfoList { - id: callDataDump - width: debugPanel.width - 2 * machineStates.sideMargin - height: 223 - collapsible: true - title: qsTr("Call data") - itemDelegate: - Item { - height: 29 - width: parent.width - 3; - ItemDelegateDataDump {} + Rectangle + { + width: parent.width + Layout.minimumHeight: 25 + color: "transparent" + } } } } diff --git a/mix/qml/ItemDelegateDataDump.qml b/mix/qml/ItemDelegateDataDump.qml index d8513ac20..1c0ea183e 100644 --- a/mix/qml/ItemDelegateDataDump.qml +++ b/mix/qml/ItemDelegateDataDump.qml @@ -20,29 +20,33 @@ Rectangle { Layout.maximumWidth: 35 Layout.minimumHeight: parent.height Text { - anchors.centerIn: parent - anchors.leftMargin: 5 - color: "#8b8b8b" + anchors.verticalCenter: parent.verticalCenter + anchors.left: parent.left + anchors.leftMargin: 3 + font.family: "monospace" + font.bold: true + color: "#4a4a4a" text: modelData[0] - font.pointSize: 9; + font.pointSize: 8; } } Rectangle { - anchors.left: firstCol.right Layout.fillWidth: true - Layout.minimumWidth: 90 - Layout.preferredWidth: 90 - Layout.maximumWidth: 90 + Layout.minimumWidth: 110 + Layout.preferredWidth: 110 + Layout.maximumWidth: 110 Layout.minimumHeight: parent.height Text { - anchors.left: parent.left - anchors.leftMargin: 7 + font.family: "monospace" + font.bold: true anchors.verticalCenter: parent.verticalCenter - color: "#8b8b8b" + anchors.left: parent.left + anchors.leftMargin: 4 + color: "#4a4a4a" text: modelData[1] - font.pointSize: 9 + font.pointSize: 8 } } @@ -52,12 +56,12 @@ Rectangle { Layout.minimumWidth: 50 Layout.minimumHeight: parent.height Text { - anchors.left: parent.left anchors.verticalCenter: parent.verticalCenter - color: "#ededed" - font.bold: true + anchors.horizontalCenter: parent.horizontalCenter + font.family: "monospace" + color: "#4a4a4a" text: modelData[2] - font.pointSize: 10 + font.pointSize: 8 } } } diff --git a/mix/qml/MainContent.qml b/mix/qml/MainContent.qml index 145a38cea..8ea145536 100644 --- a/mix/qml/MainContent.qml +++ b/mix/qml/MainContent.qml @@ -3,6 +3,7 @@ import QtQuick.Controls 1.1 import QtQuick.Layouts 1.0 import QtQuick.Controls.Styles 1.1 import CodeEditorExtensionManager 1.0 +import Qt.labs.settings 1.0 Rectangle { @@ -20,6 +21,14 @@ Rectangle { property alias rightViewVisible : rightView.visible property alias webViewVisible : webPreview.visible + onWidthChanged: + { + if (rightView.visible) + contentView.width = parent.width - projectList.width - rightView.width; + else + contentView.width = parent.width - projectList.width; + } + function toggleRightView() { if (!rightView.visible) rightView.show(); @@ -41,6 +50,10 @@ Rectangle { webPreview.visible = !webPreview.visible; } + function rightViewVisible() { + return rightView.visible; + } + CodeEditorExtensionManager { headerView: headerPaneTabs; rightView: rightPaneTabs; @@ -82,21 +95,37 @@ Rectangle { } } - SplitView { - resizing: false - Layout.row: 1 - orientation: Qt.Horizontal; + Rectangle { Layout.fillWidth: true Layout.preferredHeight: root.height - headerView.height; + Settings { + id: splitSettings + property alias projectWidth: projectList.width + property alias contentViewWidth: contentView.width + property alias rightViewWidth: rightView.width + } + ProjectList { + anchors.left: parent.left id: projectList width: 200 height: parent.height Layout.minimumWidth: 200 } + Splitter + { + id: resizeLeft + itemToStick: projectList + itemMinimumWidth: projectList.Layout.minimumWidth + direction: "right" + brother: contentView + color: "#a2a2a2" + } + Rectangle { + anchors.left: projectList.right id: contentView width: parent.width - projectList.width height: parent.height @@ -117,28 +146,39 @@ Rectangle { } } + Splitter + { + id: resizeRight + visible: false; + itemToStick: rightView + itemMinimumWidth: rightView.Layout.minimumWidth + direction: "left" + brother: contentView + color: "#a2a2a2" + } + Rectangle { visible: false; id: rightView; - Keys.onEscapePressed: - { - hide(); - } + Keys.onEscapePressed: hide() function show() { visible = true; + resizeRight.visible = true; contentView.width = parent.width - projectList.width - rightView.width; } function hide() { + resizeRight.visible = false; visible = false; contentView.width = parent.width - projectList.width; } height: parent.height; - width: 450 - Layout.minimumWidth: 450 + width: 515 + Layout.minimumWidth: 515 + anchors.right: parent.right Rectangle { anchors.fill: parent; id: rightPaneView diff --git a/mix/qml/NewProjectDialog.qml b/mix/qml/NewProjectDialog.qml index 9f88d5238..64d91341d 100644 --- a/mix/qml/NewProjectDialog.qml +++ b/mix/qml/NewProjectDialog.qml @@ -64,7 +64,7 @@ Window { Button { enabled: titleField.text != "" && pathField.text != "" - text: qsTr("Ok"); + text: qsTr("OK"); onClicked: { close(); accepted(); diff --git a/mix/qml/ProjectModel.qml b/mix/qml/ProjectModel.qml index e03959132..3c67ca35e 100644 --- a/mix/qml/ProjectModel.qml +++ b/mix/qml/ProjectModel.qml @@ -89,7 +89,7 @@ Item { FileDialog { id: openProjectFileDialog visible: false - title: qsTr("Open a project") + title: qsTr("Open a Project") selectFolder: true onAccepted: { var path = openProjectFileDialog.fileUrl.toString(); @@ -101,7 +101,7 @@ Item { FileDialog { id: addExistingFileDialog visible: false - title: qsTr("Add a file") + title: qsTr("Add a File") selectFolder: false onAccepted: { var paths = addExistingFileDialog.fileUrls; diff --git a/mix/qml/Splitter.qml b/mix/qml/Splitter.qml new file mode 100644 index 000000000..341dc4450 --- /dev/null +++ b/mix/qml/Splitter.qml @@ -0,0 +1,47 @@ +import QtQuick 2.2 + +Rectangle { + property variant itemToStick; + property int itemMinimumWidth; + property string direction; + property variant brother; + + Component.onCompleted: + { + if (direction === "left") + anchors.right = itemToStick.left; + else if (direction === "right") + anchors.left = itemToStick.right; + } + + width: 5 + height: parent.height + anchors.top: parent.top; + MouseArea + { + property int startX: 0; + anchors.fill: parent + onPressed: startX = mouseX; + onPositionChanged: + { + parent.x += mouseX; + var diff = 0; + if (direction == "left") + diff = mouseX - startX; + else if (direction == "right") + diff = -(mouseX - startX); + + if (itemMinimumWidth > itemToStick.width - diff) + { + brother.width = brother.width + diff; + itemToStick.width = itemMinimumWidth; + } + else + { + brother.width = brother.width + diff; + itemToStick.width = itemToStick.width - diff; + } + } + cursorShape: Qt.SizeHorCursor + } +} diff --git a/mix/qml/StateDialog.qml b/mix/qml/StateDialog.qml index 4b2fc099e..5fd5a9271 100644 --- a/mix/qml/StateDialog.qml +++ b/mix/qml/StateDialog.qml @@ -99,7 +99,7 @@ Window { anchors.right: parent.right; Button { - text: qsTr("Ok"); + text: qsTr("OK"); onClicked: { close(); accepted(); diff --git a/mix/qml/StatusPane.qml b/mix/qml/StatusPane.qml index af4f6949e..c6c531a80 100644 --- a/mix/qml/StatusPane.qml +++ b/mix/qml/StatusPane.qml @@ -14,6 +14,7 @@ Rectangle { status.state = ""; status.text = qsTr("Compile without errors."); logslink.visible = false; + debugImg.state = "active"; } else { @@ -21,6 +22,7 @@ Rectangle { var errorInfo = ErrorLocationFormater.extractErrorInfo(statusPane.result.compilerMessage, true); status.text = errorInfo.errorLocation + " " + errorInfo.errorDetail; logslink.visible = true; + debugImg.state = ""; } debugRunActionIcon.enabled = statusPane.result.successful; } @@ -65,7 +67,7 @@ Rectangle { visible: false font.pointSize: 9 height: 9 - text: qsTr("See log.") + text: qsTr("See Log.") font.family: "Monospace" objectName: "status" id: logslink @@ -96,17 +98,24 @@ Rectangle { Button { anchors.right: parent.right - anchors.rightMargin: 7 + anchors.rightMargin: 9 anchors.verticalCenter: parent.verticalCenter id: debugImg iconSource: "qrc:/qml/img/bugiconinactive.png" action: debugRunActionIcon + states: [ + State{ + name: "active" + PropertyChanges { target: debugImg; iconSource: "qrc:/qml/img/bugiconactive.png"} + } + ] } Action { id: debugRunActionIcon onTriggered: { - mainContent.ensureRightView(); - clientModel.debugDeployment(); + mainContent.toggleRightView(); + if (mainContent.rightViewVisible()) + clientModel.debugDeployment(); } enabled: false } diff --git a/mix/qml/StepActionImage.qml b/mix/qml/StepActionImage.qml index fd6a46521..64440aa83 100644 --- a/mix/qml/StepActionImage.qml +++ b/mix/qml/StepActionImage.qml @@ -8,6 +8,7 @@ Rectangle { id: buttonActionContainer property string disableStateImg property string enabledStateImg + property string buttonTooltip signal clicked function enabled(state) @@ -19,7 +20,6 @@ Rectangle { debugImg.iconSource = disableStateImg; } - color: "transparent" Button { anchors.fill: parent @@ -31,6 +31,7 @@ Rectangle { } Action { + tooltip: buttonTooltip id: buttonAction onTriggered: { buttonActionContainer.clicked(); diff --git a/mix/qml/TransactionDialog.qml b/mix/qml/TransactionDialog.qml index 22995d66b..46fe997f0 100644 --- a/mix/qml/TransactionDialog.qml +++ b/mix/qml/TransactionDialog.qml @@ -136,7 +136,7 @@ Window { } Label { - text: qsTr("Gas price") + text: qsTr("Gas Price") } Rectangle { @@ -183,7 +183,7 @@ Window { anchors.right: parent.right; Button { - text: qsTr("Ok"); + text: qsTr("OK"); onClicked: { close(); accepted(); diff --git a/mix/qml/WebPreview.qml b/mix/qml/WebPreview.qml index 9407d9961..1cf64eae6 100644 --- a/mix/qml/WebPreview.qml +++ b/mix/qml/WebPreview.qml @@ -27,10 +27,10 @@ Item { } function updateContract() { - var contractDefinition = codeModel.code.contractDefinition; - if (contractDefinition === "") - contractDefinition = "[]" - webView.runJavaScript("updateContract(\"" + clientModel.contractAddress + "\", " + contractDefinition + ")"); + var contractInterface = codeModel.code.contractInterface; + if (contractInterface === "") + contractInterface = "[]" + webView.runJavaScript("updateContract(\"" + clientModel.contractAddress + "\", " + contractInterface + ")"); } function reloadOnSave() { @@ -68,7 +68,7 @@ Item { Connections { target: codeModel - onContractDefinitionChanged: reload(); + onContractInterfaceChanged: reload(); } Connections { diff --git a/mix/qml/html/codeeditor.html b/mix/qml/html/codeeditor.html index 1a3f736ec..ea278983f 100644 --- a/mix/qml/html/codeeditor.html +++ b/mix/qml/html/codeeditor.html @@ -12,5 +12,5 @@ - + diff --git a/mix/qml/js/Debugger.js b/mix/qml/js/Debugger.js index da3928105..9078befdb 100644 --- a/mix/qml/js/Debugger.js +++ b/mix/qml/js/Debugger.js @@ -7,7 +7,7 @@ var currentSelectedState = null; var jumpStartingPoint = null; function init() { - if (debugStates === undefined) + if (typeof(debugStates) === "undefined") return; statesSlider.maximumValue = debugStates.length - 1; @@ -24,6 +24,9 @@ function init() function moveSelection(incr) { + if (typeof(debugStates) === "undefined") + return; + if (currentSelectedState + incr >= 0) { if (currentSelectedState + incr < debugStates.length) @@ -34,6 +37,9 @@ function moveSelection(incr) function select(stateIndex) { + if (typeof(debugStates) === "undefined") + return; + var codeLine = codeStr(stateIndex); var state = debugStates[stateIndex]; highlightSelection(codeLine); @@ -53,6 +59,9 @@ function select(stateIndex) function codeStr(stateIndex) { + if (typeof(debugStates) === "undefined") + return; + var state = debugStates[stateIndex]; return bytesCodeMapping.getValue(state.curPC); } @@ -64,6 +73,9 @@ function highlightSelection(index) function completeCtxInformation(state) { + if (typeof(debugStates) === "undefined") + return; + currentStep.update(state.step); mem.update(state.newMemSize.value() + " " + qsTr("words")); stepCost.update(state.gasCost.value()); @@ -83,6 +95,9 @@ function displayReturnValue() function stepOutBack() { + if (typeof(debugStates) === "undefined") + return; + if (jumpStartingPoint != null) { select(jumpStartingPoint); @@ -99,6 +114,9 @@ function stepIntoBack() function stepOverBack() { + if (typeof(debugStates) === "undefined") + return; + var state = debugStates[currentSelectedState]; if (state.instruction === "JUMPDEST") { @@ -118,6 +136,9 @@ function stepOverBack() function stepOverForward() { + if (typeof(debugStates) === "undefined") + return; + var state = debugStates[currentSelectedState]; if (state.instruction === "JUMP") { @@ -137,6 +158,9 @@ function stepOverForward() function stepIntoForward() { + if (typeof(debugStates) === "undefined") + return; + var state = debugStates[currentSelectedState]; if (state.instruction === "JUMP") { diff --git a/mix/qml/main.qml b/mix/qml/main.qml index 6baa6fa76..7970c4027 100644 --- a/mix/qml/main.qml +++ b/mix/qml/main.qml @@ -40,6 +40,7 @@ ApplicationWindow { Menu { title: qsTr("Windows") MenuItem { action: showHideRightPanel } + MenuItem { action: toggleWebPreview } } } @@ -90,7 +91,7 @@ ApplicationWindow { Action { id: toggleWebPreview - text: "Show/Hide web view" + text: "Show Web View" shortcut: "F2" checkable: true checked: mainContent.webViewVisible @@ -99,7 +100,7 @@ ApplicationWindow { Action { id: showHideRightPanel - text: "Show right view" + text: "Show Right View" shortcut: "F7" checkable: true checked: mainContent.rightViewVisible @@ -108,7 +109,7 @@ ApplicationWindow { Action { id: createProjectAction - text: qsTr("&New project") + text: qsTr("&New Project") shortcut: "Ctrl+N" enabled: true; onTriggered: projectModel.createProject(); @@ -116,7 +117,7 @@ ApplicationWindow { Action { id: openProjectAction - text: qsTr("&Open project") + text: qsTr("&Open Project") shortcut: "Ctrl+O" enabled: true; onTriggered: projectModel.browseProject(); @@ -124,7 +125,7 @@ ApplicationWindow { Action { id: addNewJsFileAction - text: qsTr("New JavaScript file") + text: qsTr("New JavaScript File") shortcut: "Ctrl+Alt+J" enabled: !projectModel.isEmpty onTriggered: projectModel.newJsFile(); @@ -132,7 +133,7 @@ ApplicationWindow { Action { id: addNewHtmlFileAction - text: qsTr("New HTML file") + text: qsTr("New HTML File") shortcut: "Ctrl+Alt+H" enabled: !projectModel.isEmpty onTriggered: projectModel.newHtmlFile(); @@ -140,7 +141,7 @@ ApplicationWindow { Action { id: addNewContractAction - text: qsTr("New contract") + text: qsTr("New Contract") shortcut: "Ctrl+Alt+C" enabled: !projectModel.isEmpty onTriggered: projectModel.newContract(); @@ -148,7 +149,7 @@ ApplicationWindow { Action { id: addExistingFileAction - text: qsTr("Add existing file") + text: qsTr("Add Existing File") shortcut: "Ctrl+Alt+A" enabled: !projectModel.isEmpty onTriggered: projectModel.addExistingFile(); @@ -156,7 +157,7 @@ ApplicationWindow { Action { id: saveAllFilesAction - text: qsTr("Save all") + text: qsTr("Save All") shortcut: "Ctrl+S" enabled: !projectModel.isEmpty onTriggered: projectModel.saveAll(); @@ -164,7 +165,7 @@ ApplicationWindow { Action { id: closeProjectAction - text: qsTr("Close project") + text: qsTr("Close Project") shortcut: "Ctrl+W" enabled: !projectModel.isEmpty onTriggered: projectModel.closeProject(); diff --git a/neth/main.cpp b/neth/main.cpp index 2c9e7ec97..abd045b1c 100644 --- a/neth/main.cpp +++ b/neth/main.cpp @@ -886,7 +886,7 @@ int main(int argc, char** argv) auto b = bc.block(h); for (auto const& i: RLP(b)[1]) { - Transaction t(i.data()); + Transaction t(i.data(), CheckSignature::Sender); auto s = t.receiveAddress() ? boost::format(" %1% %2%> %3%: %4% [%5%]") % toString(t.safeSender()) %