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.
 
 
 
 
 

320 lines
7.4 KiB

import QtQuick 2.0
import QtQuick.Window 2.0
import QtQuick.Layouts 1.0
import QtQuick.Controls 1.0
import QtQuick.Dialogs 1.1
Item {
id: codeEditorView
property string currentDocumentId: ""
property string sourceInError
property int openDocCount: 0
signal documentEdit(string documentId)
signal breakpointsChanged(string documentId)
signal isCleanChanged(var isClean, string documentId)
signal loadComplete
function getDocumentText(documentId) {
for (var i = 0; i < openDocCount; i++) {
if (editorListModel.get(i).documentId === documentId) {
return editors.itemAt(i).item.getText();
}
}
return "";
}
function isDocumentOpen(documentId) {
for (var i = 0; i < openDocCount; i++)
if (editorListModel.get(i).documentId === documentId &&
editors.itemAt(i).item)
return true;
return false;
}
function openDocument(document) {
loadDocument(document);
currentDocumentId = document.documentId;
}
function loadDocument(document) {
for (var i = 0; i < openDocCount; i++)
if (editorListModel.get(i).documentId === document.documentId)
return; //already open
if (editorListModel.count <= openDocCount)
editorListModel.append(document);
else
{
editorListModel.set(openDocCount, document);
doLoadDocument(editors.itemAt(openDocCount).item, editorListModel.get(openDocCount), false)
loadComplete();
}
openDocCount++;
}
function doLoadDocument(editor, document, create) {
var data = fileIo.readFile(document.path);
if (create)
{
editor.onLoadComplete.connect(function() {
codeEditorView.loadComplete();
});
editor.onEditorTextChanged.connect(function() {
documentEdit(editor.document.documentId);
if (editor.document.isContract)
codeModel.registerCodeChange(editor.document.documentId, editor.getText());
});
editor.onBreakpointsChanged.connect(function() {
if (editor.document.isContract)
breakpointsChanged(editor.document.documentId);
});
editor.onIsCleanChanged.connect(function() {
isCleanChanged(editor.isClean, editor.document.documentId);
});
}
editor.document = document;
editor.sourceName = document.documentId;
editor.setText(data, document.syntaxMode);
editor.changeGeneration();
}
function getEditor(documentId) {
for (var i = 0; i < openDocCount; i++)
{
if (editorListModel.get(i).documentId === documentId)
return editors.itemAt(i).item;
}
return null;
}
function highlightExecution(documentId, location)
{
var editor = getEditor(documentId);
if (editor)
{
if (documentId !== location.sourceName)
findAndHightlight(location.start, location.end, location.sourceName)
else
editor.highlightExecution(location);
}
}
// Execution is not in the current document. Try:
// Open targeted document and hightlight (TODO) or
// Warn user that file is not available
function findAndHightlight(start, end, sourceName)
{
var editor = getEditor(currentDocumentId);
if (editor)
editor.showWarning(qsTr("Currently debugging in " + sourceName + ". Source not available."));
}
function editingContract() {
for (var i = 0; i < openDocCount; i++)
if (editorListModel.get(i).documentId === currentDocumentId)
return editorListModel.get(i).isContract;
return false;
}
function getBreakpoints() {
var bpMap = {};
for (var i = 0; i < openDocCount; i++) {
var documentId = editorListModel.get(i).documentId;
var editor = editors.itemAt(i).item;
if (editor) {
bpMap[documentId] = editor.getBreakpoints();
}
}
return bpMap;
}
function toggleBreakpoint() {
var editor = getEditor(currentDocumentId);
if (editor)
editor.toggleBreakpoint();
}
function resetEditStatus(docId) {
var editor = getEditor(docId);
if (editor)
editor.changeGeneration();
}
function goToCompilationError() {
if (sourceInError === "")
return;
if (currentDocumentId !== sourceInError)
projectModel.openDocument(sourceInError);
for (var i = 0; i < openDocCount; i++)
{
var doc = editorListModel.get(i);
if (doc.isContract && doc.documentId === sourceInError)
{
var editor = editors.itemAt(i).item;
if (editor)
editor.goToCompilationError();
break;
}
}
}
Component.onCompleted: projectModel.codeEditor = codeEditorView;
Connections {
target: codeModel
onCompilationError: {
sourceInError = _sourceName;
}
onCompilationComplete: {
sourceInError = "";
}
}
Connections {
target: projectModel
onDocumentOpened: {
openDocument(document);
}
onProjectSaving: {
for (var i = 0; i < openDocCount; i++)
{
var doc = editorListModel.get(i);
var editor = editors.itemAt(i).item;
if (editor)
fileIo.writeFile(doc.path, editor.getText());
}
}
onProjectSaved: {
if (projectModel.appIsClosing || projectModel.projectIsClosing)
return;
for (var i = 0; i < openDocCount; i++)
{
var doc = editorListModel.get(i);
resetEditStatus(doc.documentId);
}
}
onProjectClosed: {
currentDocumentId = "";
openDocCount = 0;
}
onDocumentSaved: {
resetEditStatus(documentId);
}
onContractSaved: {
resetEditStatus(documentId);
}
onDocumentSaving: {
for (var i = 0; i < editorListModel.count; i++)
{
var doc = editorListModel.get(i);
if (doc.path === document.path)
{
fileIo.writeFile(document.path, editors.itemAt(i).item.getText());
break;
}
}
}
}
CodeEditorStyle
{
id: style;
}
MessageDialog
{
id: messageDialog
title: qsTr("File Changed")
text: qsTr("This file has been changed outside of the editor. Do you want to reload it?")
standardButtons: StandardButton.Yes | StandardButton.No
property variant item
property variant doc
onYes: {
doLoadDocument(item, doc, false);
resetEditStatus(doc.documentId);
}
}
Repeater {
id: editors
model: editorListModel
onItemRemoved: {
item.item.unloaded = true;
}
delegate: Loader {
id: loader
active: false
asynchronous: true
anchors.fill: parent
source: appService.haveWebEngine ? "WebCodeEditor.qml" : "CodeEditor.qml"
visible: (index >= 0 && index < openDocCount && currentDocumentId === editorListModel.get(index).documentId)
property bool changed: false
onVisibleChanged: {
loadIfNotLoaded()
if (visible && item)
{
loader.item.setFocus();
if (changed)
{
changed = false;
messageDialog.item = loader.item;
messageDialog.doc = editorListModel.get(index);
messageDialog.open();
}
}
}
Component.onCompleted: {
loadIfNotLoaded()
}
onLoaded: {
doLoadDocument(loader.item, editorListModel.get(index), true)
}
Connections
{
target: projectModel
onDocumentChanged: {
if (!item)
return;
var current = editorListModel.get(index);
if (documentId === current.documentId)
{
if (currentDocumentId === current.documentId)
{
messageDialog.item = loader.item;
messageDialog.doc = editorListModel.get(index);
messageDialog.open();
}
else
changed = true
}
}
onDocumentUpdated: {
var document = projectModel.getDocument(documentId);
for (var i = 0; i < editorListModel.count; i++)
if (editorListModel.get(i).documentId === documentId)
{
editorListModel.set(i, document);
break;
}
}
}
function loadIfNotLoaded () {
if (visible && !active) {
active = true;
}
}
}
}
ListModel {
id: editorListModel
}
}