Browse Source

Merge pull request #1483 from yann300/ui

mix - Logs window redesign
cl-refactor
Arkadiy Paronyan 10 years ago
parent
commit
6f5636e490
  1. 565
      mix/qml/LogsPane.qml
  2. 20
      mix/qml/LogsPaneStyle.qml
  3. 65
      mix/qml/StatusPane.qml
  4. BIN
      mix/qml/img/broom.png
  5. BIN
      mix/qml/img/clearicon.png
  6. BIN
      mix/qml/img/cleariconactive.png
  7. BIN
      mix/qml/img/copyicon.png
  8. BIN
      mix/qml/img/copyiconactive.png
  9. 5
      mix/res.qrc

565
mix/qml/LogsPane.qml

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

20
mix/qml/LogsPaneStyle.qml

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

65
mix/qml/StatusPane.qml

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

BIN
mix/qml/img/broom.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 501 B

BIN
mix/qml/img/clearicon.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

BIN
mix/qml/img/cleariconactive.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

BIN
mix/qml/img/copyicon.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 871 B

BIN
mix/qml/img/copyiconactive.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 875 B

5
mix/res.qrc

@ -17,7 +17,6 @@
<file>qml/fonts/SourceSerifPro-Semibold.ttf</file>
<file>qml/img/available_updates.png</file>
<file>qml/img/b64.png</file>
<file>qml/img/broom.png</file>
<file>qml/img/bugiconactive.png</file>
<file>qml/img/bugiconinactive.png</file>
<file>qml/img/closedtriangleindicator.png</file>
@ -53,5 +52,9 @@
<file>stdc/config.sol</file>
<file>stdc/namereg.sol</file>
<file>stdc/std.sol</file>
<file>qml/img/clearicon.png</file>
<file>qml/img/cleariconactive.png</file>
<file>qml/img/copyicon.png</file>
<file>qml/img/copyiconactive.png</file>
</qresource>
</RCC>

Loading…
Cancel
Save