Browse Source

Merge pull request #959 from arkpar/mix_ux

mix: UI tweaks and bugfixes
cl-refactor
Gav Wood 10 years ago
parent
commit
19b9a411d3
  1. 13
      mix/ClientModel.cpp
  2. 9
      mix/ClientModel.h
  3. 3
      mix/MixClient.cpp
  4. 26
      mix/qml/DebugInfoList.qml
  5. 256
      mix/qml/Debugger.qml
  6. 3
      mix/qml/WebPreview.qml
  7. 7
      mix/qml/js/Debugger.js
  8. 1
      mix/qml/js/ProjectModel.js
  9. 2
      mix/qml/main.qml

13
mix/ClientModel.cpp

@ -113,24 +113,27 @@ QString ClientModel::apiCall(QString const& _message)
void ClientModel::mine()
{
if (m_running)
if (m_running || m_mining)
BOOST_THROW_EXCEPTION(ExecutionStateException());
m_running = true;
emit runStarted();
emit runStateChanged();
m_mining = true;
emit miningStarted();
emit miningStateChanged();
QtConcurrent::run([=]()
{
try
{
m_client->mine();
newBlock();
m_mining = false;
emit miningComplete();
}
catch (...)
{
m_mining = false;
std::cerr << boost::current_exception_diagnostic_information();
emit runFailed(QString::fromStdString(boost::current_exception_diagnostic_information()));
}
m_running = false;
emit miningStateChanged();
});
}

9
mix/ClientModel.h

@ -114,6 +114,8 @@ public:
~ClientModel();
/// @returns true if currently executing contract code
Q_PROPERTY(bool running MEMBER m_running NOTIFY runStateChanged)
/// @returns true if currently mining
Q_PROPERTY(bool mining MEMBER m_mining NOTIFY miningStateChanged)
/// @returns address of the last executed contract
Q_PROPERTY(QString contractAddress READ contractAddress NOTIFY contractAddressChanged)
/// ethereum.js RPC request entry point
@ -144,6 +146,12 @@ signals:
void runStarted();
/// Transaction execution completed successfully
void runComplete();
/// Mining has started
void miningStarted();
/// Mined a new block
void miningComplete();
/// Mining stopped or started
void miningStateChanged();
/// Transaction execution completed with error
/// @param _message Error message
void runFailed(QString const& _message);
@ -174,6 +182,7 @@ private:
AppContext* m_context;
std::atomic<bool> m_running;
std::atomic<bool> m_mining;
std::unique_ptr<MixClient> m_client;
std::unique_ptr<RpcConnector> m_rpcConnector;
std::unique_ptr<Web3Server> m_web3Server;

3
mix/MixClient.cpp

@ -91,6 +91,7 @@ void MixClient::resetState(u256 _balance)
m_state.sync(bc());
m_startState = m_state;
m_pendingExecutions.clear();
m_executions.clear();
}
void MixClient::executeTransaction(Transaction const& _t, State& _state)
@ -215,7 +216,7 @@ ExecutionResult const& MixClient::execution(unsigned _block, unsigned _transacti
{
if (_block == bc().number() + 1)
return m_pendingExecutions.at(_transaction);
return m_executions.at(_block).at(_transaction);
return m_executions.at(_block - 1).at(_transaction);
}
ExecutionResult const& MixClient::lastExecution() const

26
mix/qml/DebugInfoList.qml

@ -4,14 +4,19 @@ import QtQuick.Layouts 1.0
import QtQuick.Controls.Styles 1.1
ColumnLayout {
id: root
property string title
property variant listModel;
property bool collapsible;
property bool enableSelection;
property real storedHeight;
property Component itemDelegate
signal rowActivated(int index)
spacing: 0
function collapse()
{
storedHeight = childrenRect.height;
storageContainer.state = "collapsed";
}
@ -32,7 +37,9 @@ ColumnLayout {
Image {
source: "qrc:/qml/img/opentriangleindicator.png"
width: 15
height: 15
sourceSize.width: 15
sourceSize.height: 15
id: storageImgArrow
}
@ -53,16 +60,20 @@ ColumnLayout {
if (storageContainer.state == "collapsed")
{
storageContainer.state = "";
storageContainer.parent.parent.height = storageContainer.parent.parent.Layout.maximumHeight;
storageContainer.parent.parent.height = storedHeight;
}
else
{
storedHeight = root.childrenRect.height;
storageContainer.state = "collapsed";
}
}
}
}
}
Rectangle
{
id: storageContainer
border.width: 3
border.color: "#deddd9"
Layout.fillWidth: true
@ -80,18 +91,23 @@ ColumnLayout {
}
}
]
id: storageContainer
ListView {
TableView {
clip: true;
alternatingRowColors: false
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
selectionMode: enableSelection ? SelectionMode.SingleSelection : SelectionMode.NoSelection
headerDelegate: null
itemDelegate: root.itemDelegate
TableViewColumn {
role: "modelData"
width: parent.width
}
}
}
}

256
mix/qml/Debugger.qml

@ -55,6 +55,15 @@ Rectangle {
onCompilationComplete: update(null, false);
}
Settings {
id: splitSettings
property alias transactionLogHeight: transactionLog.height
property alias callStackHeight: callStackRect.height
property alias storageHeightSettings: storageRect.height
property alias memoryDumpHeightSettings: memoryRect.height
property alias callDataHeightSettings: callDataRect.height
}
Rectangle
{
visible: false;
@ -104,19 +113,11 @@ Rectangle {
}
}
Flickable {
property int firstColumnWidth: 180
property int secondColumnWidth: 250
ScrollView {
id: debugScrollArea
flickableDirection: Flickable.VerticalFlick
anchors.fill: parent
contentHeight: 4000
contentWidth: parent.width
Rectangle
{
color: "transparent"
anchors.fill: parent
ColumnLayout
SplitView
{
property int sideMargin: 10
id: machineStates
@ -124,29 +125,48 @@ Rectangle {
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
width: debugScrollArea.width - machineStates.sideMargin * 2 - 20;
orientation: Qt.Vertical
handleDelegate: Rectangle {
height: machineStates.sideMargin
color: "transparent"
}
function updateHeight() {
machineStates.height = transactionLog.childrenRect.height + buttonRow.childrenRect.height + assemblyCodeRow.childrenRect.height +
callStackRect.childrenRect.height + storageRect.childrenRect.height + memoryRect.childrenRect.height + callDataRect.childrenRect.height + 120;
}
Component.onCompleted: updateHeight();
TransactionLog {
id: transactionLog
Layout.fillWidth: true
Layout.minimumHeight: 60
height: 250
}
RowLayout {
ColumnLayout {
Layout.fillWidth: true
Layout.fillHeight: true
id: statesLayout
spacing: machineStates.sideMargin
Rectangle {
// step button + slider
id: buttonRow
spacing: machineStates.sideMargin
height: 27
Layout.fillWidth: true
color: "transparent"
Rectangle
{
height: parent.height
Rectangle {
anchors.top: parent.top
anchors.bottom: parent.bottom
anchors.left: parent.left
color: "transparent"
width: debugScrollArea.firstColumnWidth
width: stateListContainer.width
RowLayout {
anchors.horizontalCenter: parent.horizontalCenter
id: jumpButtons
@ -226,9 +246,11 @@ Rectangle {
}
Rectangle {
anchors.top: parent.top
anchors.bottom: parent.bottom
anchors.right: parent.right
width: debugInfoContainer.width
color: "transparent"
Layout.fillWidth: true
height: parent.height
Slider {
id: statesSlider
anchors.fill: parent
@ -255,83 +277,99 @@ Rectangle {
}
}
RowLayout {
Rectangle {
// Assembly code
id: assemblyCodeRow
Layout.fillWidth: true
height: 405
implicitHeight: 405
spacing: machineStates.sideMargin
color: "transparent"
Rectangle
{
id: stateListContainer
width: debugScrollArea.firstColumnWidth
anchors.top : parent.top
anchors.bottom: parent.bottom
anchors.left: parent.left
width: parent.width * 0.4
height: parent.height
border.width: 3
border.color: "#deddd9"
color: "white"
anchors.top: parent.top
ListView {
TableView {
id: statesList
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
headerDelegate: null
itemDelegate: renderDelegate
model: ListModel {}
TableViewColumn {
role: "line"
width: parent.width - 10
}
}
Component {
id: highlightBar
Rectangle {
radius: 4
height: statesList.currentItem.height
width: statesList.currentItem.width;
anchors.fill: parent
y: statesList.currentItem.y
color: "#4A90E2"
//Behavior on y {
// PropertyAnimation { properties: "y"; easing.type: Easing.InOutQuad; duration: 50}
//}
}
}
Component {
id: renderDelegate
Item {
Rectangle {
radius: 4
anchors.fill: parent
color: "#4A90E2"
visible: styleData.selected;
}
RowLayout {
id: wrapperItem
height: 20
width: parent.width
anchors.fill: parent
spacing: 5
Text {
anchors.left: parent.left
anchors.leftMargin: 10
width: 15
color: "#b2b3ae"
text: line.split(' ')[0]
text: styleData.value.split(' ')[0]
font.family: "monospace"
font.pointSize: 9
id: id
wrapMode: Text.NoWrap
id: id
}
Text {
anchors.left: id.right;
wrapMode: Text.NoWrap
color: parent.ListView.isCurrentItem ? "white" : "black"
color: styleData.selected ? "white" : "black"
font.family: "monospace"
text: line.replace(line.split(' ')[0], '')
anchors.left: id.right
text: styleData.value.replace(styleData.value.split(' ')[0], '')
font.pointSize: 9
}
}
}
}
}
Rectangle {
Layout.fillWidth: true
id: debugInfoContainer
width: parent.width * 0.6 - machineStates.sideMargin
anchors.top : parent.top
anchors.bottom: parent.bottom
anchors.right: parent.right
height: parent.height //- 2 * stateListContainer.border.width
color: "transparent"
ColumnLayout
@ -372,7 +410,7 @@ Rectangle {
title : qsTr("Stack")
itemDelegate: Item {
id: renderedItem
height: 25
//height: 25
width: parent.width
RowLayout
{
@ -391,7 +429,7 @@ Rectangle {
anchors.leftMargin: 5
font.family: "monospace"
color: "#4a4a4a"
text: model.index;
text: styleData.row;
font.pointSize: 9
}
}
@ -402,7 +440,6 @@ Rectangle {
Layout.fillWidth: true
Layout.minimumWidth: 15
Layout.preferredWidth: 15
Layout.maximumWidth: 60
Layout.minimumHeight: parent.height
Text {
anchors.left: parent.left
@ -410,7 +447,7 @@ Rectangle {
font.family: "monospace"
anchors.verticalCenter: parent.verticalCenter
color: "#4a4a4a"
text: modelData
text: styleData.value
font.pointSize: 9
}
}
@ -434,33 +471,87 @@ Rectangle {
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: callStackRect;
color: "transparent"
height: 120
width: parent.width
Layout.minimumHeight: 120
Layout.maximumHeight: 400
CallStack {
anchors.fill: parent
Layout.minimumHeight: 25
Layout.maximumHeight: 800
onHeightChanged: machineStates.updateHeight();
DebugInfoList
{
id: callStack
onFrameActivated: Debugger.displayFrame(index);
collapsible: true
anchors.fill: parent
title : qsTr("Call Stack")
enableSelection: true
onRowActivated: Debugger.displayFrame(index);
itemDelegate:
Item {
anchors.fill: parent
Rectangle {
anchors.fill: parent
color: "#4A90E2"
visible: styleData.selected;
}
RowLayout
{
id: row
anchors.fill: parent
Rectangle
{
color: "#f7f7f7"
Layout.fillWidth: true
Layout.minimumWidth: 30
Layout.maximumWidth: 30
Text {
anchors.verticalCenter: parent.verticalCenter
anchors.left: parent.left
font.family: "monospace"
anchors.leftMargin: 5
color: "#4a4a4a"
text: styleData.row;
font.pointSize: 9
width: parent.width - 5
elide: Text.ElideRight
}
}
Rectangle
{
color: "transparent"
Layout.fillWidth: true
Layout.minimumWidth: parent.width - 30
Layout.maximumWidth: parent.width - 30
Text {
anchors.leftMargin: 5
width: parent.width - 5
wrapMode: Text.Wrap
anchors.left: parent.left
font.family: "monospace"
anchors.verticalCenter: parent.verticalCenter
color: "#4a4a4a"
text: styleData.value;
elide: Text.ElideRight
font.pointSize: 9
}
}
}
Rectangle {
anchors.top: row.bottom
width: parent.width;
height: 1;
color: "#cccccc"
anchors.bottom: parent.bottom
}
}
}
}
Rectangle
{
@ -468,8 +559,8 @@ Rectangle {
color: "transparent"
width: parent.width
Layout.minimumHeight: 25
Layout.maximumHeight: 223
height: 25
Layout.maximumHeight: 800
onHeightChanged: machineStates.updateHeight();
DebugInfoList
{
id: storage
@ -478,29 +569,24 @@ Rectangle {
title : qsTr("Storage")
itemDelegate:
Item {
height: 27
width: parent.width;
anchors.fill: parent
RowLayout
{
id: row
width: parent.width
height: 26
anchors.fill: parent
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
font.family: "monospace"
anchors.leftMargin: 5
color: "#4a4a4a"
text: modelData.split('\t')[0];
text: styleData.value.split('\t')[0];
font.pointSize: 9
width: parent.width - 5
elide: Text.ElideRight
@ -511,10 +597,7 @@ 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
@ -523,7 +606,7 @@ Rectangle {
font.family: "monospace"
anchors.verticalCenter: parent.verticalCenter
color: "#4a4a4a"
text: modelData.split('\t')[1];
text: styleData.value.split('\t')[1];
elide: Text.ElideRight
font.pointSize: 9
}
@ -545,10 +628,10 @@ Rectangle {
{
id: memoryRect;
color: "transparent"
height: 25
width: parent.width
Layout.minimumHeight: 25
Layout.maximumHeight: 223
Layout.maximumHeight: 800
onHeightChanged: machineStates.updateHeight();
DebugInfoList {
id: memoryDump
anchors.fill: parent
@ -567,10 +650,10 @@ Rectangle {
{
id: callDataRect
color: "transparent"
height: 25
width: parent.width
Layout.minimumHeight: 25
Layout.maximumHeight: 223
Layout.maximumHeight: 800
onHeightChanged: machineStates.updateHeight();
DebugInfoList {
id: callDataDump
anchors.fill: parent
@ -586,8 +669,9 @@ Rectangle {
}
Rectangle
{
id: bottomRect;
width: parent.width
Layout.minimumHeight: 25
Layout.minimumHeight: 20
color: "transparent"
}
}

3
mix/qml/WebPreview.qml

@ -114,7 +114,8 @@ Item {
onClientConnected: {
//filter polling spam
//TODO: do it properly
var log = _request.content.indexOf("eth_changed") < 0;
//var log = _request.content.indexOf("eth_changed") < 0;
var log = true;
if (log)
console.log(_request.content);
var response = clientModel.apiCall(_request.content);

7
mix/qml/js/Debugger.js

@ -107,7 +107,7 @@ function select(stateIndex)
callStackData.push(address);
}
callStackData.push(debugData.states[0].address);
callStack.model = callStackData;
callStack.listModel = callStackData;
}
function codeStr(stateIndex)
@ -118,8 +118,9 @@ function codeStr(stateIndex)
function highlightSelection(index)
{
statesList.currentIndex = index;
statesList.positionViewAtIndex(index, ListView.Center);
statesList.positionViewAtRow(index, ListView.Center);
statesList.selection.clear();
statesList.selection.select(index);
}
function completeCtxInformation(state)

1
mix/qml/js/ProjectModel.js

@ -153,6 +153,7 @@ function doCloseProject() {
console.log("closing project");
projectListModel.clear();
projectPath = "";
currentDocumentId = "";
projectClosed();
}

2
mix/qml/main.qml

@ -88,7 +88,7 @@ ApplicationWindow {
text: qsTr("Mine")
shortcut: "Ctrl+M"
onTriggered: clientModel.mine();
enabled: codeModel.hasContract && !clientModel.running
enabled: codeModel.hasContract && !clientModel.running &&!clientModel.mining
}
Connections {

Loading…
Cancel
Save