diff --git a/mix/qml/MainContent.qml b/mix/qml/MainContent.qml index 2b0b50ce5..42a780288 100644 --- a/mix/qml/MainContent.qml +++ b/mix/qml/MainContent.qml @@ -96,11 +96,19 @@ Rectangle { id: contentView width: parent.width - projectList.width height: parent.height - CodeEditorView { - height: parent.height - anchors.top: parent.top - width: parent.width - } + SplitView { + anchors.fill: parent + orientation: Qt.Vertical + CodeEditorView { + height: parent.height * 0.6 + anchors.top: parent.top + width: parent.width + } + WebPreview { + height: parent.height * 0.4 + width: parent.width + } + } } Rectangle { diff --git a/mix/qml/ProjectModel.qml b/mix/qml/ProjectModel.qml index 5337e2780..d1942a671 100644 --- a/mix/qml/ProjectModel.qml +++ b/mix/qml/ProjectModel.qml @@ -13,18 +13,21 @@ Item { id: projectModel signal projectClosed - signal projectLoaded + signal projectLoaded(var projectData) signal documentOpened(var document) signal documentRemoved(var documentId) signal documentUpdated(var documentId) //renamed + signal documentAdded(var documentId) signal projectSaving(var projectData) + signal projectSaved() + signal documentSaved(var documentId) - property bool isEmpty: (projectData === null) + property bool isEmpty: (projectPath === "") readonly property string projectFileName: ".mix" property bool haveUnsavedChanges: false property string projectPath: "" - property var projectData: null + property string projectTitle: "" property var listModel: projectListModel //interface @@ -41,6 +44,7 @@ Item { function openDocument(documentId) { ProjectModelCode.openDocument(documentId); } function renameDocument(documentId, newName) { ProjectModelCode.renameDocument(documentId, newName); } function removeDocument(documentId) { ProjectModelCode.removeDocument(documentId); } + function getDocument(documentId) { return ProjectModelCode.getDocument(documentId); } Connections { target: appContext diff --git a/mix/qml/StateList.qml b/mix/qml/StateList.qml index 519e533d5..4a53d46ef 100644 --- a/mix/qml/StateList.qml +++ b/mix/qml/StateList.qml @@ -21,9 +21,9 @@ Rectangle { stateListModel.clear(); } onProjectLoaded: { - if (!target.projectData.states) - target.projectData.states = []; - var items = target.projectData.states; + if (!projectData.states) + projectData.states = []; + var items = projectData.states; for(var i = 0; i < items.length; i++) { stateListModel.append(items[i]); stateList.push(items[i]) diff --git a/mix/qml/WebPreview.qml b/mix/qml/WebPreview.qml index 77e60ee66..fc2302540 100644 --- a/mix/qml/WebPreview.qml +++ b/mix/qml/WebPreview.qml @@ -3,79 +3,170 @@ import QtQuick.Window 2.0 import QtQuick.Layouts 1.0 import QtQuick.Controls 1.0 import QtQuick.Controls.Styles 1.1 +import QtWebKit 3.0 +import QtWebKit.experimental 1.0 +import org.ethereum.qml.ProjectModel 1.0 -Component { - Item { - signal editorTextChanged +Item { + id: webPreview - function setText(text) { - codeEditor.text = text; + function reload() { + + + + webView.reload(); + } + + function reloadOnSave() { + if (autoReloadOnSave.checked) + reload(); + } + + function updateDocument(documentId, action) { + for (var i = 0; i < pageListModel.count; i++) + if (pageListModel.get(i).documentId === i) + action(i); + } + + function changePage() { + if (pageCombo.currentIndex >=0 && pageCombo.currentIndex < pageListModel.count) { + webView.url = pageListModel.get(pageCombo.currentIndex).path; + reload(); + } else { + webView.loadHtml(""); } + } - function getText() { - return codeEditor.text; + Connections { + target: ProjectModel + onProjectSaved : reloadOnSave(); + onDocumentSaved: reloadOnSave(); + onDocumentAdded: { + console.log("added") + console.log(documentId) + var document = ProjectModel.getDocument(documentId) + if (document.isHtml) + pageListModel.append(document); + } + onDocumentRemoved: { + updateDocument(documentId, function(i) { pageListModel.remove(i) } ) + } + onDocumentUpdated: { + updateDocument(documentId, function(i) { pageListModel.set(i, ProjectModel.getDocument(documentId)) } ) } - anchors.fill: parent - id: contentView - width: parent.width - height: parent.height * 0.7 - Rectangle { - id: lineColumn - property int rowHeight: codeEditor.font.pixelSize + 3 - color: "#202020" - width: 50 - height: parent.height - Column { - y: -codeEditor.flickableItem.contentY + 4 - width: parent.width - Repeater { - model: Math.max(codeEditor.lineCount + 2, (lineColumn.height/lineColumn.rowHeight)) - delegate: Text { - id: text - color: codeEditor.textColor - font: codeEditor.font - width: lineColumn.width - 4 - horizontalAlignment: Text.AlignRight - verticalAlignment: Text.AlignVCenter - height: lineColumn.rowHeight - renderType: Text.NativeRendering - text: index + 1 - } - } + onProjectLoaded: { + 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 + changePage(); } } + } - TextArea { - id: codeEditor - textColor: "#EEE8D5" - style: TextAreaStyle { - backgroundColor: "#002B36" - } + onProjectClosed: { + pageListModel.clear(); + } + } - anchors.left: lineColumn.right - anchors.right: parent.right - anchors.top: parent.top - anchors.bottom: parent.bottom - wrapMode: TextEdit.NoWrap - frameVisible: false - - height: parent.height - font.family: "Monospace" - font.pointSize: 12 - width: parent.width - - tabChangesFocus: false - Keys.onPressed: { - if (event.key === Qt.Key_Tab) { - codeEditor.insert(codeEditor.cursorPosition, "\t"); - event.accepted = true; - } + ListModel { + id: pageListModel + } + + ColumnLayout { + anchors.fill: parent + RowLayout { + Layout.fillWidth: true; + Text { + text: qsTr("Page"); + } + ComboBox { + id: pageCombo + model: pageListModel + textRole: "name" + currentIndex: -1 + onCurrentIndexChanged: changePage() + } + Button { + text: qsTr("Reload"); + onClicked: reload() } - onTextChanged: { - editorTextChanged(); + CheckBox { + id: autoReloadOnSave + checked: true + text: qsTr("Auto reload on save"); } + } + + ScrollView { + Layout.fillWidth: true; + Layout.fillHeight: true; + WebView { + id: webView + url: "http://google.com" + anchors.fill: parent + experimental.preferences.developerExtrasEnabled: true + experimental.itemSelector: itemSelector + } + } + } + Component { + id: itemSelector + MouseArea { + // To avoid conflicting with ListView.model when inside ListView context. + property QtObject selectorModel: model + anchors.fill: parent + onClicked: selectorModel.reject() + Rectangle { + clip: true + width: 200 + height: Math.min(listView.contentItem.height + listView.anchors.topMargin + listView.anchors.bottomMargin + , Math.max(selectorModel.elementRect.y, parent.height - selectorModel.elementRect.y - selectorModel.elementRect.height)) + x: (selectorModel.elementRect.x + 200 > parent.width) ? parent.width - 200 : selectorModel.elementRect.x + y: (selectorModel.elementRect.y + selectorModel.elementRect.height + height < parent.height ) ? selectorModel.elementRect.y + selectorModel.elementRect.height + : selectorModel.elementRect.y - height; + radius: 5 + color: "gainsboro" + opacity: 0.8 + ListView { + id: listView + anchors.fill: parent + anchors.margins: 10 + spacing: 5 + model: selectorModel.items + delegate: Rectangle { + color: model.selected ? "gold" : "silver" + height: 50 + width: parent.width + Text { + anchors.centerIn: parent + text: model.text + color: model.enabled ? "black" : "gainsboro" + } + MouseArea { + anchors.fill: parent + enabled: model.enabled + onClicked: selectorModel.accept(model.index) + } + } + section.property: "group" + section.delegate: Rectangle { + height: 30 + width: parent.width + color: "silver" + Text { + anchors.centerIn: parent + text: section + font.bold: true + } + } + } + } } + } + } diff --git a/mix/qml/js/ProjectModel.js b/mix/qml/js/ProjectModel.js index 836b75e13..5b5571cad 100644 --- a/mix/qml/js/ProjectModel.js +++ b/mix/qml/js/ProjectModel.js @@ -43,10 +43,14 @@ function closeProject() { function saveProject() { if (!isEmpty) { + var projectData = { files: [] }; + for (var i = 0; i < projectListModel.count; i++) + projectData.files.push(projectListModel.get(i).fileName) projectSaving(projectData); var json = JSON.stringify(projectData); var projectFile = projectPath + projectFileName; fileIo.writeFile(projectFile, json); + projectSaved(); } } @@ -55,11 +59,12 @@ function loadProject(path) { console.log("loading project at " + path); var projectFile = path + projectFileName; var json = fileIo.readFile(projectFile); - projectData = JSON.parse(json); + var projectData = JSON.parse(json); if (!projectData.title) { var parts = path.split("/"); projectData.title = parts[parts.length - 2]; } + projectTitle = projectData.title; projectPath = path; if (!projectData.files) projectData.files = []; @@ -68,32 +73,31 @@ function loadProject(path) { addFile(projectData.files[i]); } projectSettings.lastProjectPath = path; - projectLoaded(); + projectLoaded(projectData); } function addExistingFile() { addExistingFileDialog.open(); } -function addProjectFiles(files) { - for(var i = 0; i < files.length; i++) - addFile(files[i]); -} - function addFile(fileName) { var p = projectPath + fileName; - var extension = fileName.substring(fileName.length - 4, fileName.length); + var extension = fileName.substring(fileName.lastIndexOf("."), fileName.length); var isContract = extension === ".sol"; - var fileData = { + var isHtml = extension === ".html"; + var docData = { contract: false, path: p, + fileName: fileName, name: isContract ? "Contract" : fileName, documentId: fileName, - isText: isContract || extension === ".html" || extension === ".js", + isText: isContract || isHtml || extension === ".js", isContract: isContract, + isHtml: isHtml, }; - projectListModel.append(fileData); + projectListModel.append(docData); + return docData.documentId; } function findDocument(documentId) @@ -143,14 +147,12 @@ function doCreateProject(title, path) { function doAddExistingFiles(files) { for(var i = 0; i < files.length; i++) { var sourcePath = files[i]; - console.log(sourcePath); var sourceFileName = sourcePath.substring(sourcePath.lastIndexOf("/") + 1, sourcePath.length); - console.log(sourceFileName); var destPath = projectPath + sourceFileName; - console.log(destPath); if (sourcePath !== destPath) fileIo.copyFile(sourcePath, destPath); - addFile(sourceFileName); + var id = addFile(sourceFileName); + documentAdded(id) } } @@ -168,12 +170,17 @@ function renameDocument(documentId, newName) { } } +function getDocument(documentId) { + var i = findDocument(documentId); + return projectListModel.get(i); +} + function removeDocument(documentId) { var i = findDocument(documentId); var document = projectListModel.get(i); if (!document.isContract) { projectListModel.remove(i); - documentUpdated(documentId); + documentRemoved(documentId); } } @@ -189,7 +196,8 @@ function createAndAddFile(name, extension, content) { var fileName = generateFileName(name, extension); var filePath = projectPath + fileName; fileIo.writeFile(filePath, content); - addFile(fileName); + var id = addFile(fileName); + documentAdded(id); } function generateFileName(name, extension) {