Browse Source

Merge remote-tracking branch 'up/develop' into ui_improvement

Conflicts:
	mix/qml/StateListModel.qml
	mix/qml/main.qml
cl-refactor
yann300 10 years ago
parent
commit
49173feb8f
  1. 7
      alethzero/MainWin.cpp
  2. 22
      libdevcore/CommonJS.cpp
  3. 8
      libdevcore/CommonJS.h
  4. 21
      libethcore/CommonEth.cpp
  5. 2
      libethcore/CommonEth.h
  6. 7
      libethereum/Client.cpp
  7. 41
      libethereum/State.cpp
  8. 10
      libethereum/State.h
  9. 6
      mix/AppContext.cpp
  10. 1
      mix/AssemblyDebuggerControl.cpp
  11. 37
      mix/ClientModel.cpp
  12. 3
      mix/ClientModel.h
  13. 22
      mix/CodeHighlighter.cpp
  14. 98
      mix/ContractCallDataEncoder.cpp
  15. 16
      mix/ContractCallDataEncoder.h
  16. 1
      mix/Exceptions.h
  17. 79
      mix/MachineStates.h
  18. 15
      mix/MixClient.cpp
  19. 42
      mix/MixClient.h
  20. 3
      mix/QBigInt.h
  21. 8
      mix/QVariableDeclaration.h
  22. 90
      mix/QVariableDefinition.cpp
  23. 90
      mix/QVariableDefinition.h
  24. 1
      mix/main.cpp
  25. 215
      mix/qml/MainContent.qml
  26. 3
      mix/qml/ProjectModel.qml
  27. 7
      mix/qml/QBoolType.qml
  28. 42
      mix/qml/QBoolTypeView.qml
  29. 7
      mix/qml/QHashType.qml
  30. 22
      mix/qml/QHashTypeView.qml
  31. 7
      mix/qml/QIntType.qml
  32. 24
      mix/qml/QIntTypeView.qml
  33. 7
      mix/qml/QRealType.qml
  34. 15
      mix/qml/QRealTypeView.qml
  35. 7
      mix/qml/QStringType.qml
  36. 25
      mix/qml/QStringTypeView.qml
  37. 7
      mix/qml/QVariableDeclaration.qml
  38. 13
      mix/qml/QVariableDefinition.qml
  39. 47
      mix/qml/Splitter.qml
  40. 49
      mix/qml/StateListModel.qml
  41. 155
      mix/qml/TransactionDialog.qml
  42. 2
      mix/qml/WebPreview.qml
  43. 1
      mix/qml/html/codeeditor.js
  44. 3
      mix/qml/js/ProjectModel.js
  45. 39
      mix/qml/main.qml
  46. 13
      mix/res.qrc
  47. 7
      test/stateOriginal.cpp

7
alethzero/MainWin.cpp

@ -1209,8 +1209,9 @@ string Main::renderDiff(StateDiff const& _d) const
if (ad.balance) if (ad.balance)
{ {
s << "<br/>" << indent << "Balance " << dec << formatBalance(ad.balance.to()); s << "<br/>" << indent << "Balance " << dec << ad.balance.to() << " [=" << formatBalance(ad.balance.to()) << "]";
s << " <b>" << showpos << (((dev::bigint)ad.balance.to()) - ((dev::bigint)ad.balance.from())) << noshowpos << "</b>"; auto d = (((dev::bigint)ad.balance.to()) - ((dev::bigint)ad.balance.from()));
s << " <b>" << showpos << dec << d << " [=" << formatBalance(d) << "]" << noshowpos << "</b>";
} }
if (ad.nonce) if (ad.nonce)
{ {
@ -1219,7 +1220,7 @@ string Main::renderDiff(StateDiff const& _d) const
} }
if (ad.code) if (ad.code)
{ {
s << "<br/>" << indent << "Code " << hex << ad.code.to().size() << " bytes"; s << "<br/>" << indent << "Code " << dec << ad.code.to().size() << " bytes";
if (ad.code.from().size()) if (ad.code.from().size())
s << " (" << ad.code.from().size() << " bytes)"; s << " (" << ad.code.from().size() << " bytes)";
} }

22
libdevcore/CommonJS.cpp

@ -45,6 +45,12 @@ bytes padded(bytes _b, unsigned _l)
return asBytes(asString(_b).substr(_b.size() - std::max(_l, _l))); return asBytes(asString(_b).substr(_b.size() - std::max(_l, _l)));
} }
bytes paddedRight(bytes _b, unsigned _l)
{
_b.resize(_l);
return _b;
}
bytes unpadded(bytes _b) bytes unpadded(bytes _b)
{ {
auto p = asString(_b).find_last_not_of((char)0); auto p = asString(_b).find_last_not_of((char)0);
@ -52,12 +58,18 @@ bytes unpadded(bytes _b)
return _b; return _b;
} }
std::string unpadLeft(std::string _b) bytes unpadLeft(bytes _b)
{ {
auto p = _b.find_first_not_of('0'); unsigned int i = 0;
if (p == std::string::npos) if (_b.size() == 0)
return "0"; return _b;
return _b.substr(p, _b.length() - 1);
while (i < _b.size() && _b[i] == byte(0))
i++;
if (i != 0)
_b.erase(_b.begin(), _b.begin() + i);
return _b;
} }
std::string prettyU256(u256 _n) std::string prettyU256(u256 _n)

8
libdevcore/CommonJS.h

@ -48,12 +48,14 @@ inline std::string toJS(dev::bytes const& _n)
/// Convert string to byte array. Input parameters can be hex or dec. Returns empty array if invalid input e.g neither dec or hex. /// Convert string to byte array. Input parameters can be hex or dec. Returns empty array if invalid input e.g neither dec or hex.
bytes jsToBytes(std::string const& _s); bytes jsToBytes(std::string const& _s);
/// Add '0' on the head of _b until _l. /// Add '0' on the head of @a _b until @a _l.
bytes padded(bytes _b, unsigned _l); bytes padded(bytes _b, unsigned _l);
/// Add '0' on the queue of @a _b until @a _l.
bytes paddedRight(bytes _b, unsigned _l);
/// Removing all trailing '0'. Returns empty array if input contains only '0' char. /// Removing all trailing '0'. Returns empty array if input contains only '0' char.
bytes unpadded(bytes _s); bytes unpadded(bytes _s);
/// Remove all '0' on the head of _s. Returns 0 if _s contains only '0'. /// Remove all 0 byte on the head of @a _s.
std::string unpadLeft(std::string _s); bytes unpadLeft(bytes _s);
/// Convert u256 into user-readable string. Returns int/hex value of 64 bits int, hex of 160 bits FixedHash. As a fallback try to handle input as h256. /// Convert u256 into user-readable string. Returns int/hex value of 64 bits int, hex of 160 bits FixedHash. As a fallback try to handle input as h256.
std::string prettyU256(u256 _n); std::string prettyU256(u256 _n);
/// Convert h256 into user-readable string (by directly using std::string constructor). /// Convert h256 into user-readable string (by directly using std::string constructor).

21
libethcore/CommonEth.cpp

@ -63,22 +63,31 @@ vector<pair<u256, string>> const& units()
return g_units; return g_units;
} }
std::string formatBalance(u256 _b) std::string formatBalance(bigint const& _b)
{ {
ostringstream ret; ostringstream ret;
if (_b > g_units[0].first * 10000) u256 b;
if (_b < 0)
{ {
ret << (_b / g_units[0].first) << " " << g_units[0].second; ret << "-";
b = (u256)-_b;
}
else
b = (u256)_b;
if (b > g_units[0].first * 10000)
{
ret << (b / g_units[0].first) << " " << g_units[0].second;
return ret.str(); return ret.str();
} }
ret << setprecision(5); ret << setprecision(5);
for (auto const& i: g_units) for (auto const& i: g_units)
if (i.first != 1 && _b >= i.first * 100) if (i.first != 1 && b >= i.first * 100)
{ {
ret << (double(_b / (i.first / 1000)) / 1000.0) << " " << i.second; ret << (double(b / (i.first / 1000)) / 1000.0) << " " << i.second;
return ret.str(); return ret.str();
} }
ret << _b << " wei"; ret << b << " wei";
return ret.str(); return ret.str();
} }

2
libethcore/CommonEth.h

@ -39,7 +39,7 @@ extern const unsigned c_protocolVersion;
extern const unsigned c_databaseVersion; extern const unsigned c_databaseVersion;
/// User-friendly string representation of the amount _b in wei. /// User-friendly string representation of the amount _b in wei.
std::string formatBalance(u256 _b); std::string formatBalance(bigint const& _b);
/// Get information concerning the currency denominations. /// Get information concerning the currency denominations.
std::vector<std::pair<u256, std::string>> const& units(); std::vector<std::pair<u256, std::string>> const& units();

7
libethereum/Client.cpp

@ -226,7 +226,7 @@ void Client::uninstallWatch(unsigned _i)
void Client::noteChanged(h256Set const& _filters) void Client::noteChanged(h256Set const& _filters)
{ {
Guard l(m_filterLock); Guard l(m_filterLock);
cnote << "noteChanged(" << _filters << ")"; // cnote << "noteChanged(" << _filters << ")";
// accrue all changes left in each filter into the watches. // accrue all changes left in each filter into the watches.
for (auto& i: m_watches) for (auto& i: m_watches)
if (_filters.count(i.second.id)) if (_filters.count(i.second.id))
@ -361,13 +361,12 @@ void Client::setupState(State& _s)
cwork << "SETUP MINE"; cwork << "SETUP MINE";
_s = m_postMine; _s = m_postMine;
} }
_s.setUncles(m_bc);
if (m_paranoia) if (m_paranoia)
{ {
if (_s.amIJustParanoid(m_bc)) if (_s.amIJustParanoid(m_bc))
{ {
cnote << "I'm just paranoid. Block is fine."; cnote << "I'm just paranoid. Block is fine.";
_s.commitToMine(); _s.commitToMine(m_bc);
} }
else else
{ {
@ -375,7 +374,7 @@ void Client::setupState(State& _s)
} }
} }
else else
_s.commitToMine(); _s.commitToMine(m_bc);
} }
void Client::transact(Secret _secret, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice) void Client::transact(Secret _secret, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice)

41
libethereum/State.cpp

@ -639,8 +639,7 @@ void State::uncommitToMine()
bool State::amIJustParanoid(BlockChain const& _bc) bool State::amIJustParanoid(BlockChain const& _bc)
{ {
setUncles(_bc); commitToMine(_bc);
commitToMine();
// Update difficulty according to timestamp. // Update difficulty according to timestamp.
m_currentBlock.difficulty = m_currentBlock.calculateDifficulty(m_previousBlock); m_currentBlock.difficulty = m_currentBlock.calculateDifficulty(m_previousBlock);
@ -683,8 +682,20 @@ LogBloom State::logBloom() const
return ret; return ret;
} }
void State::setUncles(BlockChain const& _bc) void State::commitToMine(BlockChain const& _bc)
{ {
uncommitToMine();
// cnote << "Committing to mine on block" << m_previousBlock.hash.abridged();
#ifdef ETH_PARANOIA
commit();
cnote << "Pre-reward stateRoot:" << m_state.root();
#endif
m_lastTx = m_db;
Addresses uncleAddresses;
RLPStream unclesData; RLPStream unclesData;
unsigned unclesCount = 0; unsigned unclesCount = 0;
if (m_previousBlock != BlockChain::genesis()) if (m_previousBlock != BlockChain::genesis())
@ -703,26 +714,11 @@ void State::setUncles(BlockChain const& _bc)
BlockInfo ubi(_bc.block(u)); BlockInfo ubi(_bc.block(u));
ubi.streamRLP(unclesData, WithNonce); ubi.streamRLP(unclesData, WithNonce);
++unclesCount; ++unclesCount;
uncleAddresses.push_back(ubi.coinbaseAddress);
} }
} }
} }
RLPStream(unclesCount).appendRaw(unclesData.out(), unclesCount).swapOut(m_currentUncles);
m_currentBlock.sha3Uncles = sha3(m_currentUncles);
}
void State::commitToMine()
{
uncommitToMine();
// cnote << "Committing to mine on block" << m_previousBlock.hash.abridged();
#ifdef ETH_PARANOIA
commit();
cnote << "Pre-reward stateRoot:" << m_state.root();
#endif
m_lastTx = m_db;
MemoryDB tm; MemoryDB tm;
GenericTrieDB<MemoryDB> transactionsTrie(&tm); GenericTrieDB<MemoryDB> transactionsTrie(&tm);
transactionsTrie.init(); transactionsTrie.init();
@ -752,13 +748,12 @@ void State::commitToMine()
txs.swapOut(m_currentTxs); txs.swapOut(m_currentTxs);
RLPStream(unclesCount).appendRaw(unclesData.out(), unclesCount).swapOut(m_currentUncles);
m_currentBlock.transactionsRoot = transactionsTrie.root(); m_currentBlock.transactionsRoot = transactionsTrie.root();
m_currentBlock.receiptsRoot = receiptsTrie.root(); m_currentBlock.receiptsRoot = receiptsTrie.root();
m_currentBlock.logBloom = logBloom(); m_currentBlock.logBloom = logBloom();
m_currentBlock.sha3Uncles = sha3(m_currentUncles);
Addresses uncleAddresses;
for (const auto& r: RLP(m_currentUncles))
uncleAddresses.push_back(BlockInfo::fromHeader(r.data()).coinbaseAddress);
// Apply rewards last of all. // Apply rewards last of all.
applyRewards(uncleAddresses); applyRewards(uncleAddresses);

10
libethereum/State.h

@ -105,16 +105,13 @@ public:
/// @returns true if all is ok. If it's false, worry. /// @returns true if all is ok. If it's false, worry.
bool amIJustParanoid(BlockChain const& _bc); bool amIJustParanoid(BlockChain const& _bc);
/// @brief Loads current block uncles from blockchain
void setUncles(BlockChain const& _bc);
/// Prepares the current state for mining. /// Prepares the current state for mining.
/// Commits all transactions into the trie, compiles uncles and transactions list, applies all /// Commits all transactions into the trie, compiles uncles and transactions list, applies all
/// rewards and populates the current block header with the appropriate hashes. /// rewards and populates the current block header with the appropriate hashes.
/// The only thing left to do after this is to actually mine(). /// The only thing left to do after this is to actually mine().
/// ///
/// This may be called multiple times and without issue. /// This may be called multiple times and without issue.
void commitToMine(); void commitToMine(BlockChain const& _bc);
/// Attempt to find valid nonce for block that this state represents. /// Attempt to find valid nonce for block that this state represents.
/// This function is thread-safe. You can safely have other interactions with this object while it is happening. /// This function is thread-safe. You can safely have other interactions with this object while it is happening.
@ -125,11 +122,14 @@ public:
/** Commit to DB and build the final block if the previous call to mine()'s result is completion. /** Commit to DB and build the final block if the previous call to mine()'s result is completion.
* Typically looks like: * Typically looks like:
* @code * @code
* while (notYetMined)
* {
* // lock * // lock
* commitToMine(); * commitToMine(_blockChain); // will call uncommitToMine if a repeat.
* // unlock * // unlock
* MineInfo info; * MineInfo info;
* for (info.complete = false; !info.complete; info = mine()) {} * for (info.complete = false; !info.complete; info = mine()) {}
* }
* // lock * // lock
* completeMine(); * completeMine();
* // unlock * // unlock

6
mix/AppContext.cpp

@ -63,6 +63,12 @@ void AppContext::load()
m_applicationEngine->rootContext()->setContextProperty("fileIo", m_fileIo.get()); m_applicationEngine->rootContext()->setContextProperty("fileIo", m_fileIo.get());
qmlRegisterType<QEther>("org.ethereum.qml.QEther", 1, 0, "QEther"); qmlRegisterType<QEther>("org.ethereum.qml.QEther", 1, 0, "QEther");
qmlRegisterType<QBigInt>("org.ethereum.qml.QBigInt", 1, 0, "QBigInt"); qmlRegisterType<QBigInt>("org.ethereum.qml.QBigInt", 1, 0, "QBigInt");
qmlRegisterType<QIntType>("org.ethereum.qml.QIntType", 1, 0, "QIntType");
qmlRegisterType<QRealType>("org.ethereum.qml.QRealType", 1, 0, "QRealType");
qmlRegisterType<QStringType>("org.ethereum.qml.QStringType", 1, 0, "QStringType");
qmlRegisterType<QHashType>("org.ethereum.qml.QHashType", 1, 0, "QHashType");
qmlRegisterType<QBoolType>("org.ethereum.qml.QBoolType", 1, 0, "QBoolType");
qmlRegisterType<QVariableDeclaration>("org.ethereum.qml.QVariableDeclaration", 1, 0, "QVariableDeclaration");
QQmlComponent projectModelComponent(m_applicationEngine, QUrl("qrc:/qml/ProjectModel.qml")); QQmlComponent projectModelComponent(m_applicationEngine, QUrl("qrc:/qml/ProjectModel.qml"));
QObject* projectModel = projectModelComponent.create(); QObject* projectModel = projectModelComponent.create();
if (projectModelComponent.isError()) if (projectModelComponent.isError())

1
mix/AssemblyDebuggerControl.cpp

@ -20,7 +20,6 @@
#include <QDebug> #include <QDebug>
#include <QQmlContext> #include <QQmlContext>
#include <QQmlApplicationEngine> #include <QQmlApplicationEngine>
#include "AppContext.h"
#include "ClientModel.h" #include "ClientModel.h"
#include "AssemblyDebuggerControl.h" #include "AssemblyDebuggerControl.h"

37
mix/ClientModel.cpp

@ -66,6 +66,10 @@ ClientModel::ClientModel(AppContext* _context):
m_context(_context), m_running(false), m_rpcConnector(new RpcConnector()), m_contractAddress(Address()) m_context(_context), m_running(false), m_rpcConnector(new RpcConnector()), m_contractAddress(Address())
{ {
qRegisterMetaType<QBigInt*>("QBigInt*"); qRegisterMetaType<QBigInt*>("QBigInt*");
qRegisterMetaType<QIntType*>("QIntType*");
qRegisterMetaType<QStringType*>("QStringType*");
qRegisterMetaType<QRealType*>("QRealType*");
qRegisterMetaType<QHashType*>("QHashType*");
qRegisterMetaType<QEther*>("QEther*"); qRegisterMetaType<QEther*>("QEther*");
qRegisterMetaType<QVariableDefinition*>("QVariableDefinition*"); qRegisterMetaType<QVariableDefinition*>("QVariableDefinition*");
qRegisterMetaType<QVariableDefinitionList*>("QVariableDefinitionList*"); qRegisterMetaType<QVariableDefinitionList*>("QVariableDefinitionList*");
@ -146,13 +150,13 @@ void ClientModel::setupState(QVariantMap _state)
} }
else else
{ {
QVariantMap params = transaction.value("parameters").toMap(); QVariantList qParams = transaction.value("qType").toList();
TransactionSettings transactionSettings(functionId, value, gas, gasPrice); TransactionSettings transactionSettings(functionId, value, gas, gasPrice);
for (auto p = params.cbegin(); p != params.cend(); ++p) for (QVariant const& variant: qParams)
{ {
QBigInt* param = qvariant_cast<QBigInt*>(p.value()); QVariableDefinition* param = qvariant_cast<QVariableDefinition*>(variant);
transactionSettings.parameterValues.insert(std::make_pair(p.key(), boost::get<dev::u256>(param->internalValue()))); transactionSettings.parameterValues.push_back(param);
} }
if (transaction.value("executeConstructor").toBool()) if (transaction.value("executeConstructor").toBool())
@ -212,14 +216,11 @@ void ClientModel::executeSequence(std::vector<TransactionSettings> const& _seque
BOOST_THROW_EXCEPTION(FunctionNotFoundException() << FunctionName(transaction.functionId.toStdString())); BOOST_THROW_EXCEPTION(FunctionNotFoundException() << FunctionName(transaction.functionId.toStdString()));
encoder.encode(f); encoder.encode(f);
for (int p = 0; p < f->parametersList().size(); p++) for (int p = 0; p < transaction.parameterValues.size(); p++)
{ {
QVariableDeclaration* var = f->parametersList().at(p); if (f->parametersList().at(p)->type() != transaction.parameterValues.at(p)->declaration()->type())
u256 value = 0; BOOST_THROW_EXCEPTION(ParameterChangedException() << FunctionName(f->parametersList().at(p)->type().toStdString()));
auto v = transaction.parameterValues.find(var->name()); encoder.push(transaction.parameterValues.at(p)->encodeValue());
if (v != transaction.parameterValues.cend())
value = v->second;
encoder.encode(var, value);
} }
if (transaction.functionId.isEmpty()) if (transaction.functionId.isEmpty())
@ -330,11 +331,6 @@ void ClientModel::onNewTransaction()
bool creation = tr.contractAddress != 0; bool creation = tr.contractAddress != 0;
if (creation)
returned = QString::fromStdString(toJS(tr.contractAddress));
else
returned = QString::fromStdString(toJS(tr.returnValue));
//TODO: handle value transfer //TODO: handle value transfer
FixedHash<4> functionHash; FixedHash<4> functionHash;
bool call = false; bool call = false;
@ -363,6 +359,9 @@ void ClientModel::onNewTransaction()
function = QObject::tr("<none>"); function = QObject::tr("<none>");
} }
if (creation)
returned = QString::fromStdString(toJS(tr.contractAddress));
if (m_contractAddress != 0 && (tr.address == m_contractAddress || tr.contractAddress == m_contractAddress)) if (m_contractAddress != 0 && (tr.address == m_contractAddress || tr.contractAddress == m_contractAddress))
{ {
auto compilerRes = m_context->codeModel()->code(); auto compilerRes = m_context->codeModel()->code();
@ -372,7 +371,13 @@ void ClientModel::onNewTransaction()
{ {
QFunctionDefinition* funcDef = def->getFunction(functionHash); QFunctionDefinition* funcDef = def->getFunction(functionHash);
if (funcDef) if (funcDef)
{
function = funcDef->name(); function = funcDef->name();
ContractCallDataEncoder encoder;
QList<QVariableDefinition*> returnValues = encoder.decode(funcDef->returnParameters(), tr.returnValue);
for (auto const& var: returnValues)
returned += var->value() + " | ";
}
} }
} }

3
mix/ClientModel.h

@ -27,6 +27,7 @@
#include <map> #include <map>
#include <QString> #include <QString>
#include "MixClient.h" #include "MixClient.h"
#include "QVariableDefinition.h"
namespace dev namespace dev
{ {
@ -59,7 +60,7 @@ struct TransactionSettings
/// Gas price /// Gas price
u256 gasPrice; u256 gasPrice;
/// Mapping from contract function parameter name to value /// Mapping from contract function parameter name to value
std::map<QString, u256> parameterValues; QList<QVariableDefinition*> parameterValues;
/// Standard contract url /// Standard contract url
QString stdContractUrl; QString stdContractUrl;
}; };

22
mix/CodeHighlighter.cpp

@ -1,18 +1,18 @@
/* /*
This file is part of cpp-ethereum. This file is part of cpp-ethereum.
cpp-ethereum is free software: you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
cpp-ethereum is distributed in the hope that it will be useful, cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>. along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/ */
/** @file CodeHighlighter.cpp /** @file CodeHighlighter.cpp
* @author Arkadiy Paronyan arkadiy@ethdev.com * @author Arkadiy Paronyan arkadiy@ethdev.com

98
mix/ContractCallDataEncoder.cpp

@ -44,89 +44,37 @@ void ContractCallDataEncoder::encode(QFunctionDefinition const* _function)
m_encodedData.insert(m_encodedData.end(), hash.begin(), hash.end()); m_encodedData.insert(m_encodedData.end(), hash.begin(), hash.end());
} }
void ContractCallDataEncoder::encode(QVariableDeclaration const* _dec, bool _value) void ContractCallDataEncoder::push(bytes const& _b)
{ {
return encode(_dec, QString(formatBool(_value))); m_encodedData.insert(m_encodedData.end(), _b.begin(), _b.end());
} }
void ContractCallDataEncoder::encode(QVariableDeclaration const* _dec, QString _value) QList<QVariableDefinition*> ContractCallDataEncoder::decode(QList<QVariableDeclaration*> const& _returnParameters, bytes _value)
{
int padding = this->padding(_dec->type());
bytes data = padded(jsToBytes(_value.toStdString()), padding);
m_encodedData.insert(m_encodedData.end(), data.begin(), data.end());
}
void ContractCallDataEncoder::encode(QVariableDeclaration const* _dec, u256 _value)
{
int padding = this->padding(_dec->type());
std::ostringstream s;
s << std::hex << "0x" << _value;
bytes data = padded(jsToBytes(s.str()), padding);
m_encodedData.insert(m_encodedData.end(), data.begin(), data.end());
encodedData();
}
QList<QVariableDefinition*> ContractCallDataEncoder::decode(QList<QVariableDeclaration*> _returnParameters, bytes _value)
{ {
QList<QVariableDefinition*> r; QList<QVariableDefinition*> r;
std::string returnValue = toJS(_value);
returnValue = returnValue.substr(2, returnValue.length() - 1);
for (int k = 0; k <_returnParameters.length(); k++) for (int k = 0; k <_returnParameters.length(); k++)
{ {
QVariableDeclaration* dec = (QVariableDeclaration*)_returnParameters.at(k); QVariableDeclaration* dec = (QVariableDeclaration*)_returnParameters.at(k);
int padding = this->padding(dec->type()); QVariableDefinition* def = nullptr;
std::string rawParam = returnValue.substr(0, padding * 2); if (dec->type().contains("int"))
r.append(new QVariableDefinition(dec, convertToReadable(unpadLeft(rawParam), dec))); def = new QIntType(dec, QString());
returnValue = returnValue.substr(rawParam.length(), returnValue.length() - 1); else if (dec->type().contains("real"))
def = new QRealType(dec, QString());
else if (dec->type().contains("bool"))
def = new QBoolType(dec, QString());
else if (dec->type().contains("string") || dec->type().contains("text"))
def = new QStringType(dec, QString());
else if (dec->type().contains("hash") || dec->type().contains("address"))
def = new QHashType(dec, QString());
else
BOOST_THROW_EXCEPTION(Exception() << errinfo_comment("Parameter declaration not found"));
bytes rawParam(_value.begin(), _value.begin() + 32);
def->decodeValue(rawParam);
r.push_back(def);
if (_value.size() > 32)
_value = bytes(_value.begin() + 32, _value.end());
qDebug() << "decoded return value : " << dec->type() << " " << def->value();
} }
return r; return r;
} }
int ContractCallDataEncoder::padding(QString type)
{
// TODO : to be improved (load types automatically from solidity library).
if (type.indexOf("uint") != -1)
return integerPadding(type.remove("uint").toInt());
else if (type.indexOf("int") != -1)
return integerPadding(type.remove("int").toInt());
else if (type.indexOf("bool") != -1)
return 1;
else if ((type.indexOf("address") != -1))
return 32;
else
return 0;
}
int ContractCallDataEncoder::integerPadding(int bitValue)
{
return bitValue / 8;
}
QString ContractCallDataEncoder::formatBool(bool _value)
{
return (_value ? "1" : "0");
}
QString ContractCallDataEncoder::convertToReadable(std::string _v, QVariableDeclaration* _dec)
{
if (_dec->type().indexOf("int") != -1)
return convertToInt(_v);
else if (_dec->type().indexOf("bool") != -1)
return convertToBool(_v);
else
return QString::fromStdString(_v);
}
QString ContractCallDataEncoder::convertToBool(std::string _v)
{
return _v == "1" ? "true" : "false";
}
QString ContractCallDataEncoder::convertToInt(std::string _v)
{
//TO DO to be improve to manage all int, uint size (128, 256, ...) in ethereum QML types task #612.
int x = std::stol(_v, nullptr, 16);
std::stringstream ss;
ss << std::dec << x;
return QString::fromStdString(ss.str());
}

16
mix/ContractCallDataEncoder.h

@ -41,27 +41,17 @@ class ContractCallDataEncoder
{ {
public: public:
ContractCallDataEncoder() {} ContractCallDataEncoder() {}
/// Encode variable in order to be sent as parameter.
void encode(QVariableDeclaration const* _dec, QString _value);
/// Encode variable in order to be sent as parameter.
void encode(QVariableDeclaration const* _dec, u256 _value);
/// Encode variable in order to be sent as parameter.
void encode(QVariableDeclaration const* _dec, bool _value);
/// Encode hash of the function to call. /// Encode hash of the function to call.
void encode(QFunctionDefinition const* _function); void encode(QFunctionDefinition const* _function);
/// Decode variable in order to be sent to QML view. /// Decode variable in order to be sent to QML view.
QList<QVariableDefinition*> decode(QList<QVariableDeclaration*> _dec, bytes _value); QList<QVariableDefinition*> decode(QList<QVariableDeclaration*> const& _dec, bytes _value);
/// Get all encoded data encoded by encode function. /// Get all encoded data encoded by encode function.
bytes encodedData(); bytes encodedData();
/// Push the given @a _b to the current param context.
void push(bytes const& _b);
private: private:
int padding(QString _type);
bytes m_encodedData; bytes m_encodedData;
static QString convertToReadable(std::string _v, QVariableDeclaration* _dec);
static QString convertToBool(std::string _v);
static QString convertToInt(std::string _v);
static int integerPadding(int _bitValue);
static QString formatBool(bool _value);
}; };
} }

1
mix/Exceptions.h

@ -38,6 +38,7 @@ struct FileIoException: virtual Exception {};
struct InvalidBlockException: virtual Exception {}; struct InvalidBlockException: virtual Exception {};
struct FunctionNotFoundException: virtual Exception {}; struct FunctionNotFoundException: virtual Exception {};
struct ExecutionStateException: virtual Exception {}; struct ExecutionStateException: virtual Exception {};
struct ParameterChangedException: virtual Exception {};
typedef boost::error_info<struct tagQmlError, QQmlError> QmlErrorInfo; typedef boost::error_info<struct tagQmlError, QQmlError> QmlErrorInfo;
typedef boost::error_info<struct tagFileError, std::string> FileError; typedef boost::error_info<struct tagFileError, std::string> FileError;

79
mix/MachineStates.h

@ -0,0 +1,79 @@
/*
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 MixClient.h
* @author Yann yann@ethdev.com
* @author Arkadiy Paronyan arkadiy@ethdev.com
* @date 2015
* Ethereum IDE client.
*/
#pragma once
#include <vector>
#include <map>
#include <stdint.h>
#include <libdevcore/Common.h>
#include <libdevcrypto/Common.h>
#include <libevmcore/Instruction.h>
#include <libethereum/TransactionReceipt.h>
namespace dev
{
namespace mix
{
/**
* @brief Store information about a machine state.
*/
struct MachineState
{
uint64_t steps;
dev::Address address;
dev::u256 curPC;
dev::eth::Instruction inst;
dev::bigint newMemSize;
dev::u256 gas;
dev::u256s stack;
dev::bytes memory;
dev::bigint gasCost;
std::map<dev::u256, dev::u256> storage;
std::vector<unsigned> levels;
unsigned codeIndex;
unsigned dataIndex;
};
/**
* @brief Store information about a machine states.
*/
struct ExecutionResult
{
ExecutionResult() : receipt(dev::h256(), dev::h256(), dev::eth::LogEntries()) {}
std::vector<MachineState> machineStates;
std::vector<bytes> transactionData;
std::vector<bytes> executionCode;
bytes returnValue;
dev::Address address;
dev::Address sender;
dev::Address contractAddress;
dev::u256 value;
dev::eth::TransactionReceipt receipt;
};
using ExecutionResults = std::vector<ExecutionResult>;
}
}

15
mix/MixClient.cpp

@ -56,16 +56,15 @@ void MixClient::resetState(u256 _balance)
genesis.state = m_state; genesis.state = m_state;
Block open; Block open;
m_blocks = Blocks { genesis, open }; //last block contains a list of pending transactions to be finalized m_blocks = Blocks { genesis, open }; //last block contains a list of pending transactions to be finalized
m_lastHashes.clear(); // m_lastHashes.clear();
m_lastHashes.resize(256); // m_lastHashes.resize(256);
m_lastHashes[0] = genesis.hash; // m_lastHashes[0] = genesis.hash;
} }
void MixClient::executeTransaction(Transaction const& _t, State& _state) void MixClient::executeTransaction(Transaction const& _t, State& _state)
{ {
bytes rlp = _t.rlp(); bytes rlp = _t.rlp();
Executive execution(_state, LastHashes(), 0);
Executive execution(_state, m_lastHashes, 0);
execution.setup(&rlp); execution.setup(&rlp);
std::vector<MachineState> machineStates; std::vector<MachineState> machineStates;
std::vector<unsigned> levels; std::vector<unsigned> levels;
@ -165,14 +164,12 @@ void MixClient::mine()
Block& block = m_blocks.back(); Block& block = m_blocks.back();
m_state.mine(0, true); m_state.mine(0, true);
m_state.completeMine(); m_state.completeMine();
m_state.commitToMine(); m_state.commitToMine(BlockChain());
m_state.cleanup(true);
block.state = m_state; block.state = m_state;
block.info = m_state.info(); block.info = m_state.info();
block.hash = block.info.hash; block.hash = block.info.hash;
m_state.cleanup(true);
m_blocks.push_back(Block()); m_blocks.push_back(Block());
m_lastHashes.insert(m_lastHashes.begin(), block.hash);
m_lastHashes.resize(256);
h256Set changed { dev::eth::PendingChangedFilter, dev::eth::ChainChangedFilter }; h256Set changed { dev::eth::PendingChangedFilter, dev::eth::ChainChangedFilter };
noteChanged(changed); noteChanged(changed);

42
mix/MixClient.h

@ -26,52 +26,13 @@
#include <vector> #include <vector>
#include <libethereum/Interface.h> #include <libethereum/Interface.h>
#include <libethereum/Client.h> #include <libethereum/Client.h>
#include "MachineStates.h"
namespace dev namespace dev
{ {
namespace mix namespace mix
{ {
/**
* @brief Store information about a machine state.
*/
struct MachineState
{
uint64_t steps;
dev::Address address;
dev::u256 curPC;
dev::eth::Instruction inst;
dev::bigint newMemSize;
dev::u256 gas;
dev::u256s stack;
dev::bytes memory;
dev::bigint gasCost;
std::map<dev::u256, dev::u256> storage;
std::vector<unsigned> levels;
unsigned codeIndex;
unsigned dataIndex;
};
/**
* @brief Store information about a machine states.
*/
struct ExecutionResult
{
ExecutionResult(): receipt(dev::h256(), dev::h256(), dev::eth::LogEntries()) {}
std::vector<MachineState> machineStates;
std::vector<bytes> transactionData;
std::vector<bytes> executionCode;
bytes returnValue;
dev::Address address;
dev::Address sender;
dev::Address contractAddress;
dev::u256 value;
dev::eth::TransactionReceipt receipt;
};
using ExecutionResults = std::vector<ExecutionResult>;
struct Block struct Block
{ {
ExecutionResults transactions; ExecutionResults transactions;
@ -145,7 +106,6 @@ private:
std::map<h256, dev::eth::InstalledFilter> m_filters; std::map<h256, dev::eth::InstalledFilter> m_filters;
std::map<unsigned, dev::eth::ClientWatch> m_watches; std::map<unsigned, dev::eth::ClientWatch> m_watches;
Blocks m_blocks; Blocks m_blocks;
eth::LastHashes m_lastHashes;
}; };
} }

3
mix/QBigInt.h

@ -36,7 +36,7 @@ namespace dev
namespace mix namespace mix
{ {
using BigIntVariant = boost::variant<dev::u256, dev::bigint>; using BigIntVariant = boost::variant<dev::u256, dev::bigint, dev::s256>;
struct add: public boost::static_visitor<BigIntVariant> struct add: public boost::static_visitor<BigIntVariant>
{ {
@ -75,6 +75,7 @@ public:
QBigInt(dev::u256 const& _value, QObject* _parent = 0): QObject(_parent), m_internalValue(_value) { QQmlEngine::setObjectOwnership(this, QQmlEngine::JavaScriptOwnership); } QBigInt(dev::u256 const& _value, QObject* _parent = 0): QObject(_parent), m_internalValue(_value) { QQmlEngine::setObjectOwnership(this, QQmlEngine::JavaScriptOwnership); }
QBigInt(dev::bigint const& _value, QObject* _parent = 0): QObject(_parent), m_internalValue(_value) { QQmlEngine::setObjectOwnership(this, QQmlEngine::JavaScriptOwnership); } QBigInt(dev::bigint const& _value, QObject* _parent = 0): QObject(_parent), m_internalValue(_value) { QQmlEngine::setObjectOwnership(this, QQmlEngine::JavaScriptOwnership); }
QBigInt(BigIntVariant const& _value, QObject* _parent = 0): QObject(_parent), m_internalValue(_value){ QQmlEngine::setObjectOwnership(this, QQmlEngine::JavaScriptOwnership); } QBigInt(BigIntVariant const& _value, QObject* _parent = 0): QObject(_parent), m_internalValue(_value){ QQmlEngine::setObjectOwnership(this, QQmlEngine::JavaScriptOwnership); }
QBigInt(dev::s256 const& _value, QObject* _parent = 0): QObject(_parent), m_internalValue(_value) { QQmlEngine::setObjectOwnership(this, QQmlEngine::JavaScriptOwnership); }
~QBigInt() {} ~QBigInt() {}
/// @returns the current used big integer. /// @returns the current used big integer.

8
mix/QVariableDeclaration.h

@ -19,6 +19,8 @@
* @date 2014 * @date 2014
*/ */
#include <QDebug>
#include <QStringList>
#include <libsolidity/AST.h> #include <libsolidity/AST.h>
#include "QBasicNodeDefinition.h" #include "QBasicNodeDefinition.h"
@ -32,16 +34,20 @@ namespace mix
class QVariableDeclaration: public QBasicNodeDefinition class QVariableDeclaration: public QBasicNodeDefinition
{ {
Q_OBJECT Q_OBJECT
Q_PROPERTY(QString type READ type CONSTANT) Q_PROPERTY(QString type READ type WRITE setType)
public: public:
QVariableDeclaration() {} QVariableDeclaration() {}
QVariableDeclaration(solidity::VariableDeclaration const* _v): QBasicNodeDefinition(_v), m_type(QString::fromStdString(_v->getType()->toString())) {} QVariableDeclaration(solidity::VariableDeclaration const* _v): QBasicNodeDefinition(_v), m_type(QString::fromStdString(_v->getType()->toString())) {}
QVariableDeclaration(std::string const& _name, std::string const& _type): QBasicNodeDefinition(_name), m_type(QString::fromStdString(_type)) {} QVariableDeclaration(std::string const& _name, std::string const& _type): QBasicNodeDefinition(_name), m_type(QString::fromStdString(_type)) {}
QString type() const { return m_type; } QString type() const { return m_type; }
void setType(QString _type) { m_type = _type; }
private: private:
QString m_type; QString m_type;
}; };
} }
} }
Q_DECLARE_METATYPE(dev::mix::QVariableDeclaration*)

90
mix/QVariableDefinition.cpp

@ -19,6 +19,8 @@
* @date 2014 * @date 2014
*/ */
#include <libdevcore/CommonData.h>
#include <libdevcore/CommonJS.h>
#include "QVariableDefinition.h" #include "QVariableDefinition.h"
using namespace dev::mix; using namespace dev::mix;
@ -53,3 +55,91 @@ QVariableDefinition* QVariableDefinitionList::val(int _idx)
return nullptr; return nullptr;
return m_def.at(_idx); return m_def.at(_idx);
} }
/*
* QIntType
*/
void QIntType::setValue(dev::bigint _value)
{
m_bigIntvalue = _value;
std::stringstream str;
str << std::dec << m_bigIntvalue;
m_value = QString::fromStdString(str.str());
}
dev::bytes QIntType::encodeValue()
{
dev::bigint i(value().toStdString());
bytes ret(32);
toBigEndian((u256)i, ret);
return ret;
}
void QIntType::decodeValue(dev::bytes const& _rawValue)
{
dev::u256 un = dev::fromBigEndian<dev::u256>(_rawValue);
if (un >> 255)
setValue(-s256(~un + 1));
else
setValue(un);
}
/*
* QHashType
*/
dev::bytes QHashType::encodeValue()
{
QByteArray bytesAr = value().toLocal8Bit();
bytes r = bytes(bytesAr.begin(), bytesAr.end());
return padded(r, 32);
}
void QHashType::decodeValue(dev::bytes const& _rawValue)
{
std::string _ret = asString(unpadLeft(_rawValue));
setValue(QString::fromStdString(_ret));
}
/*
* QRealType
*/
dev::bytes QRealType::encodeValue()
{
return bytes();
}
void QRealType::decodeValue(dev::bytes const& _rawValue)
{
Q_UNUSED(_rawValue);
}
/*
* QStringType
*/
dev::bytes QStringType::encodeValue()
{
QByteArray b = value().toUtf8();
bytes r = bytes(b.begin(), b.end());
return paddedRight(r, 32);
}
void QStringType::decodeValue(dev::bytes const& _rawValue)
{
setValue(QString::fromUtf8((char*)_rawValue.data()));
}
/*
* QBoolType
*/
dev::bytes QBoolType::encodeValue()
{
return padded(jsToBytes(value().toStdString()), 32);
}
void QBoolType::decodeValue(dev::bytes const& _rawValue)
{
byte ret = _rawValue.at(_rawValue.size() - 1);
bool boolRet = (ret == byte(1));
m_boolValue = boolRet;
m_value = m_boolValue ? "1" : "0";
}

90
mix/QVariableDefinition.h

@ -22,6 +22,7 @@
#pragma once #pragma once
#include <QAbstractListModel> #include <QAbstractListModel>
#include "QBigInt.h"
#include "QVariableDeclaration.h" #include "QVariableDeclaration.h"
namespace dev namespace dev
@ -37,15 +38,26 @@ class QVariableDefinition: public QObject
Q_PROPERTY(QVariableDeclaration* declaration READ declaration CONSTANT) Q_PROPERTY(QVariableDeclaration* declaration READ declaration CONSTANT)
public: public:
QVariableDefinition() {}
QVariableDefinition(QVariableDeclaration* _def, QString _value): QObject(), m_value(_value), m_dec(_def) {} QVariableDefinition(QVariableDeclaration* _def, QString _value): QObject(), m_value(_value), m_dec(_def) {}
/// Return the associated declaration of this variable definition. /// Return the associated declaration of this variable definition. Invokable from QML.
QVariableDeclaration* declaration() const { return m_dec; } Q_INVOKABLE QVariableDeclaration* declaration() const { return m_dec; }
/// Return the variable value. /// Return the variable value.
QString value() const { return m_value; } QString value() const { return m_value; }
/// Set a new value for this instance. Invokable from QML.
Q_INVOKABLE void setValue(QString _value) { m_value = _value; }
/// Set a new Declaration for this instance. Invokable from QML.
Q_INVOKABLE void setDeclaration(QVariableDeclaration* _dec) { m_dec = _dec; }
/// Encode the current value in order to be used as function parameter.
virtual bytes encodeValue() = 0;
/// Decode the return value @a _rawValue.
virtual void decodeValue(dev::bytes const& _rawValue) = 0;
protected:
QString m_value;
private: private:
QString m_value;
QVariableDeclaration* m_dec; QVariableDeclaration* m_dec;
}; };
@ -67,7 +79,77 @@ private:
QList<QVariableDefinition*> m_def; QList<QVariableDefinition*> m_def;
}; };
class QIntType: public QVariableDefinition
{
Q_OBJECT
public:
QIntType() {}
QIntType(QVariableDeclaration* _def, QString _value): QVariableDefinition(_def, _value) {}
dev::bytes encodeValue() override;
void decodeValue(dev::bytes const& _rawValue) override;
/// @returns an instance of QBigInt for the current value.
QBigInt* toBigInt() { return new QBigInt(m_bigIntvalue); }
dev::bigint bigInt() { return m_bigIntvalue; }
void setValue(dev::bigint _value);
private:
dev::bigint m_bigIntvalue;
};
class QRealType: public QVariableDefinition
{
Q_OBJECT
public:
QRealType() {}
QRealType(QVariableDeclaration* _def, QString _value): QVariableDefinition(_def, _value) {}
dev::bytes encodeValue() override;
void decodeValue(dev::bytes const& _rawValue) override;
};
class QStringType: public QVariableDefinition
{
Q_OBJECT
public:
QStringType() {}
QStringType(QVariableDeclaration* _def, QString _value): QVariableDefinition(_def, _value) {}
dev::bytes encodeValue() override;
void decodeValue(dev::bytes const& _rawValue) override;
};
class QHashType: public QVariableDefinition
{
Q_OBJECT
public:
QHashType() {}
QHashType(QVariableDeclaration* _def, QString _value): QVariableDefinition(_def, _value) {}
dev::bytes encodeValue() override;
void decodeValue(dev::bytes const& _rawValue) override;
};
class QBoolType: public QVariableDefinition
{
Q_OBJECT
public:
QBoolType() {}
QBoolType(QVariableDeclaration* _def, QString _value): QVariableDefinition(_def, _value) {}
dev::bytes encodeValue() override;
void decodeValue(dev::bytes const& _rawValue) override;
/// @returns the boolean value for the current definition.
bool toBool() { return m_boolValue; }
private:
bool m_boolValue;
};
} }
} }
Q_DECLARE_METATYPE(dev::mix::QVariableDefinition*) Q_DECLARE_METATYPE(dev::mix::QIntType*)
Q_DECLARE_METATYPE(dev::mix::QStringType*)
Q_DECLARE_METATYPE(dev::mix::QHashType*)
Q_DECLARE_METATYPE(dev::mix::QBoolType*)

1
mix/main.cpp

@ -35,6 +35,7 @@ int main(int _argc, char* _argv[])
//work around ubuntu appmenu-qt5 bug //work around ubuntu appmenu-qt5 bug
//https://bugs.launchpad.net/ubuntu/+source/appmenu-qt5/+bug/1323853 //https://bugs.launchpad.net/ubuntu/+source/appmenu-qt5/+bug/1323853
putenv((char*)"QT_QPA_PLATFORMTHEME="); putenv((char*)"QT_QPA_PLATFORMTHEME=");
putenv((char*)"QSG_RENDER_LOOP=threaded");
#endif #endif
try try
{ {

215
mix/qml/MainContent.qml

@ -23,14 +23,20 @@ Rectangle {
property alias rightViewVisible : rightView.visible property alias rightViewVisible : rightView.visible
property alias webViewVisible : webPreview.visible property alias webViewVisible : webPreview.visible
property alias projectViewVisible : projectList.visible
property alias runOnProjectLoad : mainSettings.runOnProjectLoad
property bool webViewHorizontal : codeWebSplitter.orientation === Qt.Vertical //vertical splitter positions elements vertically, splits screen horizontally property bool webViewHorizontal : codeWebSplitter.orientation === Qt.Vertical //vertical splitter positions elements vertically, splits screen horizontally
property bool firstCompile: true
onWidthChanged:
{ Connections {
if (rightView.visible) target: codeModel
contentView.width = parent.width - projectList.width - rightView.width; onCompilationComplete: {
else if (firstCompile) {
contentView.width = parent.width - projectList.width; firstCompile = false;
if (codeModel.code.successful && runOnProjectLoad)
startQuickDebugging();
}
}
} }
function startQuickDebugging() function startQuickDebugging()
@ -40,15 +46,11 @@ Rectangle {
} }
function toggleRightView() { function toggleRightView() {
if (!rightView.visible) rightView.visible = !rightView.visible;
rightView.show();
else
rightView.hide();
} }
function ensureRightView() { function ensureRightView() {
if (!rightView.visible) rightView.visible = true;
rightView.show();
} }
function rightViewIsVisible() function rightViewIsVisible()
@ -65,6 +67,10 @@ Rectangle {
webPreview.visible = !webPreview.visible; webPreview.visible = !webPreview.visible;
} }
function toggleProjectView() {
projectList.visible = !projectList.visible;
}
function toggleWebPreviewOrientation() { function toggleWebPreviewOrientation() {
codeWebSplitter.orientation = (codeWebSplitter.orientation === Qt.Vertical ? Qt.Horizontal : Qt.Vertical); codeWebSplitter.orientation = (codeWebSplitter.orientation === Qt.Vertical ? Qt.Horizontal : Qt.Vertical);
} }
@ -75,19 +81,18 @@ Rectangle {
} }
Settings { Settings {
id: mainLayoutSettings id: mainSettings
property alias codeWebOrientation: codeWebSplitter.orientation property alias codeWebOrientation: codeWebSplitter.orientation
property alias webWidth: webPreview.width property alias webWidth: webPreview.width
property alias webHeight: webPreview.height property alias webHeight: webPreview.height
property alias showProjectView: projectList.visible
property bool runOnProjectLoad: false
} }
GridLayout ColumnLayout
{ {
anchors.fill: parent anchors.fill: parent
rows: 2 spacing: 0
flow: GridLayout.TopToBottom
columnSpacing: 0
rowSpacing: 0
Rectangle { Rectangle {
width: parent.width width: parent.width
height: 50 height: 50
@ -128,116 +133,90 @@ Rectangle {
property alias rightViewWidth: rightView.width property alias rightViewWidth: rightView.width
} }
ProjectList { SplitView
anchors.left: parent.left
id: projectList
width: 200
height: parent.height
Layout.minimumWidth: 200
}
Splitter
{ {
id: resizeLeft anchors.fill: parent
itemToStick: projectList handleDelegate: Rectangle {
itemMinimumWidth: projectList.Layout.minimumWidth width: 4
direction: "right" height: 4
brother: contentView color: "#cccccc"
color: "#a2a2a2"
}
Rectangle {
anchors.left: projectList.right
id: contentView
width: parent.width - projectList.width
height: parent.height
SplitView {
handleDelegate: Rectangle {
width: 4
height: 4
color: "#cccccc"
}
id: codeWebSplitter
anchors.fill: parent
orientation: Qt.Vertical
CodeEditorView {
height: parent.height * 0.6
anchors.top: parent.top
Layout.fillWidth: true
Layout.fillHeight: true
}
WebPreview {
id: webPreview
height: parent.height * 0.4
Layout.fillWidth: codeWebSplitter.orientation === Qt.Vertical
Layout.fillHeight: codeWebSplitter.orientation === Qt.Horizontal
Layout.minimumHeight: 200
Layout.minimumWidth: 200
}
} }
} orientation: Qt.Horizontal
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() ProjectList {
id: projectList
function show() { width: 200
visible = true; Layout.minimumWidth: 180
resizeRight.visible = true; Layout.fillHeight: true
contentView.width = parent.width - projectList.width - rightView.width;
} }
Rectangle {
function hide() { id: contentView
resizeRight.visible = false; Layout.fillHeight: true
visible = false; Layout.fillWidth: true
contentView.width = parent.width - projectList.width; SplitView {
handleDelegate: Rectangle {
width: 4
height: 4
color: "#cccccc"
}
id: codeWebSplitter
anchors.fill: parent
orientation: Qt.Vertical
CodeEditorView {
height: parent.height * 0.6
anchors.top: parent.top
Layout.fillWidth: true
Layout.fillHeight: true
}
WebPreview {
id: webPreview
height: parent.height * 0.4
Layout.fillWidth: codeWebSplitter.orientation === Qt.Vertical
Layout.fillHeight: codeWebSplitter.orientation === Qt.Horizontal
Layout.minimumHeight: 200
Layout.minimumWidth: 200
}
}
} }
height: parent.height;
width: 515
Layout.minimumWidth: 515
anchors.right: parent.right
Rectangle { Rectangle {
anchors.fill: parent; visible: false;
id: rightPaneView id: rightView;
TabView { Layout.fillHeight: true
id: rightPaneTabs Keys.onEscapePressed: visible = false
tabsVisible: true height: parent.height;
antialiasing: true width: 515
anchors.fill: parent Layout.minimumWidth: 515
style: TabViewStyle { anchors.right: parent.right
frameOverlap: 1 Rectangle {
tabBar: anchors.fill: parent;
Rectangle { id: rightPaneView
TabView {
id: rightPaneTabs
tabsVisible: true
antialiasing: true
anchors.fill: parent
style: TabViewStyle {
frameOverlap: 1
tabBar:
Rectangle {
color: "#ededed"
id: background
}
tab: Rectangle {
color: "#ededed" color: "#ededed"
id: background implicitWidth: 80
implicitHeight: 20
radius: 2
Text {
anchors.centerIn: parent
text: styleData.title
color: styleData.selected ? "#7da4cd" : "#202020"
}
} }
tab: Rectangle { frame: Rectangle {
color: "#ededed"
implicitWidth: 80
implicitHeight: 20
radius: 2
Text {
anchors.centerIn: parent
text: styleData.title
color: styleData.selected ? "#7da4cd" : "#202020"
} }
} }
frame: Rectangle {
}
} }
} }
} }

3
mix/qml/ProjectModel.qml

@ -10,7 +10,8 @@ Item {
id: projectModel id: projectModel
signal projectClosed signal projectClosed
signal projectLoaded(var projectData) signal projectLoading(var projectData)
signal projectLoaded()
signal documentOpened(var document) signal documentOpened(var document)
signal documentRemoved(var documentId) signal documentRemoved(var documentId)
signal documentUpdated(var documentId) //renamed signal documentUpdated(var documentId) //renamed

7
mix/qml/QBoolType.qml

@ -0,0 +1,7 @@
import QtQuick 2.0
import org.ethereum.qml.QBoolType 1.0
QBoolType
{
}

42
mix/qml/QBoolTypeView.qml

@ -0,0 +1,42 @@
import QtQuick 2.0
import QtQuick.Controls 1.3
Item
{
id: editRoot
property string text
property string defaultValue
Rectangle {
anchors.fill: parent
ComboBox
{
property bool inited: false
Component.onCompleted:
{
if (text === "")
currentIndex = parseInt(defaultValue);
else
currentIndex = parseInt(text);
inited = true
}
id: boolCombo
anchors.fill: parent
onCurrentIndexChanged:
{
if (inited)
text = comboModel.get(currentIndex).value;
}
model: ListModel
{
id: comboModel
ListElement { text: qsTr("False"); value: "0" }
ListElement { text: qsTr("True"); value: "1" }
}
}
}
}

7
mix/qml/QHashType.qml

@ -0,0 +1,7 @@
import QtQuick 2.0
import org.ethereum.qml.QHashType 1.0
QHashType
{
}

22
mix/qml/QHashTypeView.qml

@ -0,0 +1,22 @@
import QtQuick 2.0
Item
{
property alias text: textinput.text
id: editRoot
Rectangle {
anchors.fill: parent
TextInput {
id: textinput
text: text
anchors.fill: parent
wrapMode: Text.WrapAnywhere
MouseArea {
id: mouseArea
anchors.fill: parent
hoverEnabled: true
onClicked: textinput.forceActiveFocus()
}
}
}
}

7
mix/qml/QIntType.qml

@ -0,0 +1,7 @@
import QtQuick 2.0
import org.ethereum.qml.QIntType 1.0
QIntType
{
}

24
mix/qml/QIntTypeView.qml

@ -0,0 +1,24 @@
import QtQuick 2.0
Item
{
property alias text: textinput.text
id: editRoot
Rectangle {
anchors.fill: parent
TextInput {
id: textinput
text: text
anchors.fill: parent
MouseArea {
id: mouseArea
anchors.fill: parent
hoverEnabled: true
onClicked: textinput.forceActiveFocus()
}
}
}
}

7
mix/qml/QRealType.qml

@ -0,0 +1,7 @@
import QtQuick 2.0
import org.ethereum.qml.QRealType 1.0
QRealType
{
}

15
mix/qml/QRealTypeView.qml

@ -0,0 +1,15 @@
import QtQuick 2.0
Component
{
Rectangle {
anchors.fill: parent
Text{
anchors.fill: parent
text: qsTr("Real")
}
}
}

7
mix/qml/QStringType.qml

@ -0,0 +1,7 @@
import QtQuick 2.0
import org.ethereum.qml.QStringType 1.0
QStringType
{
}

25
mix/qml/QStringTypeView.qml

@ -0,0 +1,25 @@
import QtQuick 2.0
Item
{
property alias text: textinput.text
id: editRoot
Rectangle {
anchors.fill: parent
TextInput {
id: textinput
text: text
anchors.fill: parent
wrapMode: Text.WrapAnywhere
MouseArea {
id: mouseArea
anchors.fill: parent
hoverEnabled: true
onClicked: textinput.forceActiveFocus()
}
}
}
}

7
mix/qml/QVariableDeclaration.qml

@ -0,0 +1,7 @@
import QtQuick 2.0
import org.ethereum.qml.QVariableDeclaration 1.0
QVariableDeclaration
{
}

13
mix/qml/QVariableDefinition.qml

@ -0,0 +1,13 @@
/*
* Used to instanciate a QVariableDefinition obj using Qt.createComponent function.
*/
import QtQuick 2.2
import QtQuick.Controls 1.1
import QtQuick.Layouts 1.1
import QtQuick.Controls.Styles 1.1
import org.ethereum.qml.QVariableDefinition 1.0
QVariableDefinition
{
id: qVariableDefinition
}

47
mix/qml/Splitter.qml

@ -1,47 +0,0 @@
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
}
}

49
mix/qml/StateListModel.qml

@ -31,12 +31,30 @@ Item {
stdContract: t.stdContract, stdContract: t.stdContract,
parameters: {} parameters: {}
}; };
for (var key in t.parameters) { var qType = [];
var intComponent = Qt.createComponent("qrc:/qml/BigIntValue.qml"); for (var key in t.parameters)
var param = intComponent.createObject(); {
param.setValue(t.parameters[key]); r.parameters[key] = t.parameters[key].value;
r.parameters[key] = param; var type = t.parameters[key].type;
var varComponent;
if (type.indexOf("int") !== -1)
varComponent = Qt.createComponent("qrc:/qml/QIntType.qml");
else if (type.indexOf("real") !== -1)
varComponent = Qt.createComponent("qrc:/qml/QRealType.qml");
else if (type.indexOf("string") !== -1 || type.indexOf("text") !== -1)
varComponent = Qt.createComponent("qrc:/qml/QStringType.qml");
else if (type.indexOf("hash") !== -1 || type.indexOf("address") !== -1)
varComponent = Qt.createComponent("qrc:/qml/QHashType.qml");
else if (type.indexOf("bool") !== -1)
varComponent = Qt.createComponent("qrc:/qml/QBoolType.qml");
var param = varComponent.createObject(stateListModel);
var dec = Qt.createComponent("qrc:/qml/QVariableDeclaration.qml");
param.setDeclaration(dec.createObject(stateListModel, { "type": type }));
param.setValue(r.parameters[key]);
qType.push(param);
} }
r.qType = qType;
return r; return r;
} }
@ -48,6 +66,16 @@ Item {
}; };
} }
function getParamType(param, params)
{
for (var k in params)
{
if (params[k].declaration.name === param)
return params[k].declaration.type;
}
return '';
}
function toPlainTransactionItem(t) { function toPlainTransactionItem(t) {
var r = { var r = {
functionId: t.functionId, functionId: t.functionId,
@ -60,7 +88,14 @@ Item {
parameters: {} parameters: {}
}; };
for (var key in t.parameters) for (var key in t.parameters)
r.parameters[key] = t.parameters[key].value(); {
var param = {
name: key,
value: t.parameters[key],
type: getParamType(key, t.qType)
}
r.parameters[key] = param;
}
return r; return r;
} }
@ -70,7 +105,7 @@ Item {
stateListModel.clear(); stateListModel.clear();
stateList = []; stateList = [];
} }
onProjectLoaded: stateListModel.loadStatesFromProject(projectData); onProjectLoading: stateListModel.loadStatesFromProject(projectData);
onProjectSaving: { onProjectSaving: {
projectData.states = [] projectData.states = []
for(var i = 0; i < stateListModel.count; i++) { for(var i = 0; i < stateListModel.count; i++) {

155
mix/qml/TransactionDialog.qml

@ -9,7 +9,7 @@ Window {
id: modalTransactionDialog id: modalTransactionDialog
modality: Qt.WindowModal modality: Qt.WindowModal
width:640 width:640
height:480 height:640
visible: false visible: false
property int transactionIndex property int transactionIndex
@ -21,10 +21,12 @@ Window {
property var itemParams; property var itemParams;
property bool isConstructorTransaction; property bool isConstructorTransaction;
property bool useTransactionDefaultValue: false property bool useTransactionDefaultValue: false
property var qType;
signal accepted; signal accepted;
function open(index, item) { function open(index, item) {
qType = [];
rowFunction.visible = !useTransactionDefaultValue; rowFunction.visible = !useTransactionDefaultValue;
rowValue.visible = !useTransactionDefaultValue; rowValue.visible = !useTransactionDefaultValue;
rowGas.visible = !useTransactionDefaultValue; rowGas.visible = !useTransactionDefaultValue;
@ -68,6 +70,7 @@ Window {
} }
function loadParameters() { function loadParameters() {
paramsModel.clear();
if (!paramsModel) if (!paramsModel)
return; return;
if (functionComboBox.currentIndex >= 0 && functionComboBox.currentIndex < functionsModel.count) { if (functionComboBox.currentIndex >= 0 && functionComboBox.currentIndex < functionsModel.count) {
@ -75,7 +78,27 @@ Window {
var parameters = func.parameters; var parameters = func.parameters;
for (var p = 0; p < parameters.length; p++) { for (var p = 0; p < parameters.length; p++) {
var pname = parameters[p].name; var pname = parameters[p].name;
paramsModel.append({ name: pname, type: parameters[p].type, value: itemParams[pname] !== undefined ? itemParams[pname].value() : "" }); var varComponent;
var type = parameters[p].type;
if (type.indexOf("int") !== -1)
varComponent = Qt.createComponent("qrc:/qml/QIntType.qml");
else if (type.indexOf("real") !== -1)
varComponent = Qt.createComponent("qrc:/qml/QRealType.qml");
else if (type.indexOf("string") !== -1 || type.indexOf("text") !== -1)
varComponent = Qt.createComponent("qrc:/qml/QStringType.qml");
else if (type.indexOf("hash") !== -1 || type.indexOf("address") !== -1)
varComponent = Qt.createComponent("qrc:/qml/QHashType.qml");
else if (type.indexOf("bool") !== -1)
varComponent = Qt.createComponent("qrc:/qml/QBoolType.qml");
var param = varComponent.createObject(modalTransactionDialog);
var value = itemParams[pname] !== undefined ? itemParams[pname] : "";
param.setValue(value);
param.setDeclaration(parameters[p]);
qType.push({ name: pname, value: param });
paramsModel.append({ name: pname, type: parameters[p].type, value: value });
} }
} }
} }
@ -85,6 +108,15 @@ Window {
visible = false; visible = false;
} }
function qTypeParam(name)
{
for (var k in qType)
{
if (qType[k].name === name)
return qType[k].value;
}
}
function getItem() function getItem()
{ {
var item; var item;
@ -109,14 +141,15 @@ Window {
if (isConstructorTransaction) if (isConstructorTransaction)
item.functionId = qsTr("Constructor"); item.functionId = qsTr("Constructor");
var orderedQType = [];
for (var p = 0; p < transactionDialog.transactionParams.count; p++) { for (var p = 0; p < transactionDialog.transactionParams.count; p++) {
var parameter = transactionDialog.transactionParams.get(p); var parameter = transactionDialog.transactionParams.get(p);
var intComponent = Qt.createComponent("qrc:/qml/BigIntValue.qml"); var qtypeParam = qTypeParam(parameter.name);
var param = intComponent.createObject(modalTransactionDialog); qtypeParam.setValue(parameter.value);
orderedQType.push(qtypeParam);
param.setValue(parameter.value); item.parameters[parameter.name] = parameter.value;
item.parameters[parameter.name] = param;
} }
item.qType = orderedQType;
return item; return item;
} }
@ -219,8 +252,10 @@ Window {
} }
TableView { TableView {
model: paramsModel model: paramsModel
Layout.fillWidth: true Layout.preferredWidth: 120 * 2 + 240
Layout.minimumHeight: 150
Layout.preferredHeight: 400
Layout.maximumHeight: 600
TableViewColumn { TableViewColumn {
role: "name" role: "name"
title: qsTr("Name") title: qsTr("Name")
@ -234,12 +269,11 @@ Window {
TableViewColumn { TableViewColumn {
role: "value" role: "value"
title: qsTr("Value") title: qsTr("Value")
width: 120 width: 240
} }
itemDelegate: { rowDelegate: rowDelegate
return editableDelegate; itemDelegate: editableDelegate
}
} }
} }
} }
@ -268,19 +302,15 @@ Window {
} }
Component { Component {
id: editableDelegate id: rowDelegate
Item { Item {
height: 100
}
}
Text { Component {
width: parent.width id: editableDelegate
anchors.margins: 4 Item {
anchors.left: parent.left
anchors.verticalCenter: parent.verticalCenter
elide: styleData.elideMode
text: styleData.value !== undefined ? styleData.value : ""
color: styleData.textColor
visible: !styleData.selected
}
Loader { Loader {
id: loaderEditor id: loaderEditor
anchors.fill: parent anchors.fill: parent
@ -289,14 +319,87 @@ Window {
target: loaderEditor.item target: loaderEditor.item
onTextChanged: { onTextChanged: {
if (styleData.role === "value" && styleData.row < paramsModel.count) if (styleData.role === "value" && styleData.row < paramsModel.count)
paramsModel.setProperty(styleData.row, styleData.role, loaderEditor.item.text); loaderEditor.updateValue(styleData.row, styleData.role, loaderEditor.item.text);
} }
} }
sourceComponent: (styleData.selected) ? editor : null
function updateValue(row, role, value)
{
paramsModel.setProperty(styleData.row, styleData.role, value);
}
sourceComponent:
{
if (styleData.role === "value")
{
if (paramsModel.get(styleData.row) === undefined)
return null;
if (paramsModel.get(styleData.row).type.indexOf("int") !== -1)
return intViewComp;
else if (paramsModel.get(styleData.row).type.indexOf("bool") !== -1)
return boolViewComp;
else if (paramsModel.get(styleData.row).type.indexOf("string") !== -1)
return stringViewComp;
else if (paramsModel.get(styleData.row).type.indexOf("hash") !== -1)
return hashViewComp;
}
else
return editor;
}
Component
{
id: intViewComp
QIntTypeView
{
id: intView
text: styleData.value
}
}
Component
{
id: boolViewComp
QBoolTypeView
{
id: boolView
defaultValue: "1"
Component.onCompleted:
{
loaderEditor.updateValue(styleData.row, styleData.role,
(paramsModel.get(styleData.row).value === "" ? defaultValue :
paramsModel.get(styleData.row).value));
text = (paramsModel.get(styleData.row).value === "" ? defaultValue : paramsModel.get(styleData.row).value);
}
}
}
Component
{
id: stringViewComp
QStringTypeView
{
id: stringView
text: styleData.value
}
}
Component
{
id: hashViewComp
QHashTypeView
{
id: hashView
text: styleData.value
}
}
Component { Component {
id: editor id: editor
TextInput { TextInput {
id: textinput id: textinput
readOnly: true
color: styleData.textColor color: styleData.textColor
text: styleData.value text: styleData.value
MouseArea { MouseArea {

2
mix/qml/WebPreview.qml

@ -86,7 +86,7 @@ Item {
updateDocument(documentId, function(i) { pageListModel.set(i, projectModel.getDocument(documentId)) } ) updateDocument(documentId, function(i) { pageListModel.set(i, projectModel.getDocument(documentId)) } )
} }
onProjectLoaded: { onProjectLoading: {
for (var i = 0; i < target.listModel.count; i++) { for (var i = 0; i < target.listModel.count; i++) {
var document = target.listModel.get(i); var document = target.listModel.get(i);
if (document.isHtml) { if (document.isHtml) {

1
mix/qml/html/codeeditor.js

@ -31,6 +31,7 @@ getText = function() {
setTextBase64 = function(text) { setTextBase64 = function(text) {
editor.setValue(window.atob(text)); editor.setValue(window.atob(text));
editor.getDoc().clearHistory();
editor.focus(); editor.focus();
}; };

3
mix/qml/js/ProjectModel.js

@ -73,7 +73,8 @@ function loadProject(path) {
addFile(projectData.files[i]); addFile(projectData.files[i]);
} }
projectSettings.lastProjectPath = path; projectSettings.lastProjectPath = path;
projectLoaded(projectData); projectLoading(projectData);
projectLoaded()
} }
function addExistingFile() { function addExistingFile() {

39
mix/qml/main.qml

@ -36,14 +36,16 @@ ApplicationWindow {
Menu { Menu {
title: qsTr("Deploy") title: qsTr("Deploy")
MenuItem { action: debugRunAction } MenuItem { action: debugRunAction }
MenuItem { action: debugResetStateAction }
MenuItem { action: mineAction } MenuItem { action: mineAction }
MenuSeparator {}
MenuItem { action: toggleRunOnLoadAction }
} }
Menu { Menu {
title: qsTr("Windows") title: qsTr("Windows")
MenuItem { action: openNextDocumentAction } MenuItem { action: openNextDocumentAction }
MenuItem { action: openPrevDocumentAction } MenuItem { action: openPrevDocumentAction }
MenuSeparator {} MenuSeparator {}
MenuItem { action: toggleProjectNavigatorAction }
MenuItem { action: showHideRightPanelAction } MenuItem { action: showHideRightPanelAction }
MenuItem { action: toggleWebPreviewAction } MenuItem { action: toggleWebPreviewAction }
MenuItem { action: toggleWebPreviewOrientationAction } MenuItem { action: toggleWebPreviewOrientationAction }
@ -82,7 +84,7 @@ ApplicationWindow {
Action { Action {
id: mineAction id: mineAction
text: "Mine" text: qsTr("Mine")
shortcut: "Ctrl+M" shortcut: "Ctrl+M"
onTriggered: clientModel.mine(); onTriggered: clientModel.mine();
enabled: codeModel.hasContract && !clientModel.running enabled: codeModel.hasContract && !clientModel.running
@ -102,40 +104,51 @@ ApplicationWindow {
Action { Action {
id: debugRunAction id: debugRunAction
text: "&Deploy" text: qsTr("Deploy")
shortcut: "F5" shortcut: "F5"
onTriggered: mainContent.startQuickDebugging() onTriggered: mainContent.startQuickDebugging()
enabled: codeModel.hasContract && !clientModel.running enabled: codeModel.hasContract && !clientModel.running
} }
Action {
id: debugResetStateAction
text: "Reset &State"
shortcut: "F6"
onTriggered: clientModel.resetState();
}
Action { Action {
id: toggleWebPreviewAction id: toggleWebPreviewAction
text: "Show Web View" text: qsTr("Show Web View")
shortcut: "F2" shortcut: "F2"
checkable: true checkable: true
checked: mainContent.webViewVisible checked: mainContent.webViewVisible
onTriggered: mainContent.toggleWebPreview(); onTriggered: mainContent.toggleWebPreview();
} }
Action {
id: toggleProjectNavigatorAction
text: qsTr("Show Project Navigator")
shortcut: "Alt+0"
checkable: true
checked: mainContent.projectViewVisible
onTriggered: mainContent.toggleProjectView();
}
Action { Action {
id: toggleWebPreviewOrientationAction id: toggleWebPreviewOrientationAction
text: "Horizontal Web View" text: qsTr("Horizontal Web View")
shortcut: "" shortcut: ""
checkable: true checkable: true
checked: mainContent.webViewHorizontal checked: mainContent.webViewHorizontal
onTriggered: mainContent.toggleWebPreviewOrientation(); onTriggered: mainContent.toggleWebPreviewOrientation();
} }
Action {
id: toggleRunOnLoadAction
text: qsTr("Load State on Startup")
shortcut: ""
checkable: true
checked: mainContent.runOnProjectLoad
onTriggered: mainContent.runOnProjectLoad = !mainContent.runOnProjectLoad
}
Action { Action {
id: showHideRightPanelAction id: showHideRightPanelAction
text: "Show Right View" text: qsTr("Show Right View")
shortcut: "F7" shortcut: "F7"
checkable: true checkable: true
checked: mainContent.rightViewVisible checked: mainContent.rightViewVisible

13
mix/res.qrc

@ -42,9 +42,19 @@
<file>qml/Ether.qml</file> <file>qml/Ether.qml</file>
<file>qml/EtherValue.qml</file> <file>qml/EtherValue.qml</file>
<file>qml/BigIntValue.qml</file> <file>qml/BigIntValue.qml</file>
<file>qml/QVariableDefinition.qml</file>
<file>qml/QBoolType.qml</file>
<file>qml/QHashType.qml</file>
<file>qml/QIntType.qml</file>
<file>qml/QRealType.qml</file>
<file>qml/js/QEtherHelper.js</file> <file>qml/js/QEtherHelper.js</file>
<file>qml/js/TransactionHelper.js</file> <file>qml/js/TransactionHelper.js</file>
<file>qml/Splitter.qml</file> <file>qml/QStringType.qml</file>
<file>qml/QBoolTypeView.qml</file>
<file>qml/QIntTypeView.qml</file>
<file>qml/QRealTypeView.qml</file>
<file>qml/QStringTypeView.qml</file>
<file>qml/QHashTypeView.qml</file>
<file>qml/ContractLibrary.qml</file> <file>qml/ContractLibrary.qml</file>
<file>stdc/config.sol</file> <file>stdc/config.sol</file>
<file>stdc/namereg.sol</file> <file>stdc/namereg.sol</file>
@ -52,5 +62,6 @@
<file>qml/TransactionLog.qml</file> <file>qml/TransactionLog.qml</file>
<file>res/mix_256x256x32.png</file> <file>res/mix_256x256x32.png</file>
<file>qml/CallStack.qml</file> <file>qml/CallStack.qml</file>
<file>qml/QVariableDeclaration.qml</file>
</qresource> </qresource>
</RCC> </RCC>

7
test/stateOriginal.cpp

@ -51,7 +51,7 @@ int stateTest()
cout << s; cout << s;
// Mine to get some ether! // Mine to get some ether!
s.commitToMine(); s.commitToMine(bc);
while (!s.mine(100).completed) {} while (!s.mine(100).completed) {}
s.completeMine(); s.completeMine();
bc.attemptImport(s.blockData(), stateDB); bc.attemptImport(s.blockData(), stateDB);
@ -74,8 +74,9 @@ int stateTest()
cout << s; cout << s;
// Mine to get some ether and set in stone. // Mine to get some ether and set in stone.
s.commitToMine(); s.commitToMine(bc);
while (!s.mine(100).completed) {} s.commitToMine(bc);
while (!s.mine(50).completed) { s.commitToMine(bc); }
s.completeMine(); s.completeMine();
bc.attemptImport(s.blockData(), stateDB); bc.attemptImport(s.blockData(), stateDB);

Loading…
Cancel
Save