You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

459 lines
10 KiB

import QtQuick 2.0
import QtQuick.Window 2.0
import QtQuick.Layouts 1.0
import QtQuick.Controls 1.0
import QtQuick.Controls.Styles 1.1
10 years ago
import QtWebEngine 1.0
import QtWebEngine.experimental 1.0
import HttpServer 1.0
import "."
Item {
id: webPreview
10 years ago
property string pendingPageUrl: ""
property bool initialized: false
property alias urlInput: urlInput
property alias webView: webView
property string webContent; //for testing
10 years ago
signal javaScriptMessage(var _level, string _sourceId, var _lineNb, string _content)
signal webContentReady
signal ready
10 years ago
function setPreviewUrl(url) {
if (!initialized)
pendingPageUrl = url;
else {
pendingPageUrl = "";
updateContract();
10 years ago
webView.runJavaScript("loadPage(\"" + url + "\")");
}
}
function reload() {
10 years ago
if (initialized) {
updateContract();
//webView.runJavaScript("reloadPage()");
setPreviewUrl(urlInput.text);
10 years ago
}
}
function updateContract() {
var contracts = {};
for (var c in codeModel.contracts) {
var contract = codeModel.contracts[c];
var address = clientModel.contractAddresses[contract.contract.name];
if (address) {
contracts[c] = {
name: contract.contract.name,
address: address,
interface: JSON.parse(contract.contractInterface),
};
}
}
webView.runJavaScript("updateContracts(" + JSON.stringify(contracts) + ")");
}
function reloadOnSave() {
if (autoReloadOnSave.checked)
reload();
}
function updateDocument(documentId, action) {
for (var i = 0; i < pageListModel.count; i++)
if (pageListModel.get(i).documentId === documentId)
action(i);
}
function getContent() {
webView.runJavaScript("getContent()", function(result) {
webContent = result;
webContentReady();
});
}
function changePage() {
setPreviewUrl(urlInput.text);
10 years ago
}
WebPreviewStyle {
id: webPreviewStyle
}
10 years ago
Connections {
target: mainApplication
onLoaded: {
10 years ago
//We need to load the container using file scheme so that web security would allow loading local files in iframe
var containerPage = fileIo.readFile("qrc:///qml/html/WebContainer.html");
webView.loadHtml(containerPage, httpServer.url + "/WebContainer.html")
}
}
Connections {
target: codeModel
onContractInterfaceChanged: reload();
}
Connections {
10 years ago
target: projectModel
onDocumentAdded: {
10 years ago
var document = projectModel.getDocument(documentId)
if (document.isHtml)
pageListModel.append(document);
}
onDocumentRemoved: {
updateDocument(documentId, function(i) { pageListModel.remove(i) } )
}
onDocumentUpdated: {
var document = projectModel.getDocument(documentId);
for (var i = 0; i < pageListModel.count; i++)
if (pageListModel.get(i).documentId === documentId)
{
pageListModel.set(i, document);
break;
}
}
10 years ago
onProjectLoading: {
for (var i = 0; i < target.listModel.count; i++) {
var document = target.listModel.get(i);
if (document.isHtml) {
pageListModel.append(document);
if (pageListModel.count === 1) //first page added
{
urlInput.text = httpServer.url + "/" + document.documentId;
setPreviewUrl(httpServer.url + "/" + document.documentId);
}
}
}
}
onDocumentSaved:
{
if (!projectModel.getDocument(documentId).isContract)
reloadOnSave();
}
onProjectClosed: {
pageListModel.clear();
}
}
ListModel {
id: pageListModel
}
HttpServer {
id: httpServer
listen: true
accept: true
onClientConnected: {
var urlPath = _request.url.toString();
if (urlPath.indexOf("/rpc/") === 0)
{
//jsonrpc request
//filter polling requests //TODO: do it properly
var log = _request.content.indexOf("eth_changed") < 0;
if (log)
console.log(_request.content);
var response = clientModel.apiCall(_request.content);
if (log)
console.log(response);
_request.setResponse(response);
}
else
{
//document request
if (urlPath === "/")
urlPath = "/index.html";
10 years ago
var documentName = urlPath.substr(urlPath.lastIndexOf("/") + 1);
var documentId = projectModel.getDocumentIdByName(documentName);
var content = "";
if (projectModel.codeEditor.isDocumentOpen(documentId))
content = projectModel.codeEditor.getDocumentText(documentId);
else
{
var doc = projectModel.getDocument(documentId);
10 years ago
if (doc)
content = fileIo.readFile(doc.path);
}
var accept = _request.headers["accept"];
if (accept && accept.indexOf("text/html") >= 0 && !_request.headers["http_x_requested_with"])
{
//navigate to page request, inject deployment script
content = "<script>web3=parent.web3;BigNumber=parent.BigNumber;contracts=parent.contracts;</script>\n" + content;
_request.setResponseContentType("text/html");
}
_request.setResponse(content);
}
}
}
ColumnLayout {
anchors.fill: parent
spacing: 0
Rectangle
{
anchors.leftMargin: 4
color: webPreviewStyle.general.headerBackgroundColor
Layout.preferredWidth: parent.width
Layout.preferredHeight: 32
Row {
anchors.top: parent.top
anchors.fill: parent
anchors.leftMargin: 3
spacing: 3
DefaultTextField
{
id: urlInput
anchors.verticalCenter: parent.verticalCenter
height: 21
width: 300
Keys.onEnterPressed:
{
setPreviewUrl(text);
}
Keys.onReturnPressed:
{
setPreviewUrl(text);
}
focus: true
}
Action {
tooltip: qsTr("Reload")
id: buttonReloadAction
onTriggered: {
reload();
}
}
Button {
iconSource: "qrc:/qml/img/available_updates.png"
action: buttonReloadAction
anchors.verticalCenter: parent.verticalCenter
width: 21
height: 21
10 years ago
focus: true
}
10 years ago
Rectangle
{
width: 1
height: parent.height - 10
color: webPreviewStyle.general.separatorColor
anchors.verticalCenter: parent.verticalCenter
}
CheckBox {
id: autoReloadOnSave
checked: true
height: 21
anchors.verticalCenter: parent.verticalCenter
style: CheckBoxStyle {
label: DefaultLabel {
text: qsTr("Auto reload on save")
}
}
10 years ago
focus: true
}
Rectangle
{
width: 1
height: parent.height - 10
color: webPreviewStyle.general.separatorColor
anchors.verticalCenter: parent.verticalCenter
}
Button
{
height: 28
anchors.verticalCenter: parent.verticalCenter
action: expressionAction
iconSource: "qrc:/qml/img/console.png"
}
Action {
id: expressionAction
tooltip: qsTr("Expressions")
onTriggered:
{
expressionPanel.visible = !expressionPanel.visible;
if (expressionPanel.visible)
{
webView.width = webView.parent.width - 350
expressionInput.forceActiveFocus();
}
else
webView.width = webView.parent.width
}
}
}
}
Rectangle
10 years ago
{
Layout.preferredHeight: 1
Layout.preferredWidth: parent.width
color: webPreviewStyle.general.separatorColor
10 years ago
}
Splitter
{
Layout.preferredWidth: parent.width
10 years ago
Layout.fillHeight: true
WebEngineView {
Layout.fillHeight: true
width: parent.width
Layout.preferredWidth: parent.width
id: webView
experimental.settings.localContentCanAccessRemoteUrls: true
onJavaScriptConsoleMessage: {
console.log(sourceID + ":" + lineNumber + ": " + message);
webPreview.javaScriptMessage(level, sourceID, lineNumber - 1, message);
}
onLoadingChanged: {
if (!loading) {
initialized = true;
webView.runJavaScript("init(\"" + httpServer.url + "/rpc/\")");
if (pendingPageUrl)
setPreviewUrl(pendingPageUrl);
ready();
}
}
}
Column {
id: expressionPanel
width: 350
Layout.preferredWidth: 350
Layout.fillHeight: true
spacing: 0
visible: false
function addExpression()
{
if (expressionInput.text === "")
return;
expressionInput.history.unshift(expressionInput.text);
expressionInput.index = -1;
webView.runJavaScript("executeJavaScript(\"" + expressionInput.text.replace(/"/g, '\\"') + "\")", function(result) {
10 years ago
resultTextArea.text = "> " + result + "\n\n" + resultTextArea.text;
expressionInput.text = "";
});
}
Row
{
id: rowConsole
width: parent.width
Button
{
height: 22
width: 22
action: clearAction
iconSource: "qrc:/qml/img/cleariconactive.png"
}
Action {
id: clearAction
10 years ago
enabled: resultTextArea.text !== ""
tooltip: qsTr("Clear")
onTriggered: {
resultTextArea.text = "";
}
}
DefaultTextField {
id: expressionInput
width: parent.width - 15
height: 20
font.family: webPreviewStyle.general.fontName
font.italic: true
font.pointSize: appStyle.absoluteSize(-3)
anchors.verticalCenter: parent.verticalCenter
property bool active: false
property var history: []
property int index: -1
function displayCache(incr)
{
index = index + incr;
if (history.length - 1 < index || index < 0)
{
if (incr === 1)
index = 0;
else
index = history.length - 1;
}
expressionInput.text = history[index];
}
onTextChanged: {
active = text !== "";
if (!active)
index = -1;
}
Keys.onDownPressed: {
if (active)
displayCache(-1);
}
Keys.onUpPressed: {
displayCache(1);
active = true;
}
Keys.onEnterPressed:
{
expressionPanel.addExpression();
}
Keys.onReturnPressed:
{
expressionPanel.addExpression();
}
onFocusChanged:
{
if (!focus && text == "")
text = qsTr("Expression");
10 years ago
if (focus && text === qsTr("Expression"))
text = "";
}
style: TextFieldStyle {
background: Rectangle {
color: "transparent"
}
}
}
}
TextArea {
Layout.fillHeight: true
height: parent.height - rowConsole.height
readOnly: true
id: resultTextArea
width: expressionPanel.width
wrapMode: Text.Wrap
textFormat: Text.RichText
font.family: webPreviewStyle.general.fontName
font.pointSize: appStyle.absoluteSize(-3)
backgroundVisible: true
style: TextAreaStyle {
backgroundColor: "#f0f0f0"
}
}
}
}
}
}