Browse Source

started project model

cl-refactor
arkpar 10 years ago
parent
commit
9efb644ce4
  1. 11
      mix/AppContext.cpp
  2. 2
      mix/AppContext.h
  3. 3
      mix/CMakeLists.txt
  4. 1
      mix/ConstantCompilationControl.cpp
  5. 68
      mix/FileIo.cpp
  6. 49
      mix/FileIo.h
  7. 17
      mix/qml.qrc
  8. 10
      mix/qml/MainContent.qml
  9. 92
      mix/qml/NewProjectDialog.qml
  10. 39
      mix/qml/ProjectList.qml
  11. 140
      mix/qml/ProjectModel.qml
  12. 14
      mix/qml/StateList.qml

11
mix/AppContext.cpp

@ -32,8 +32,10 @@
#include <QDir>
#include <libdevcrypto/FileSystem.h>
#include <libwebthree/WebThree.h>
#include "AppContext.h"
#include "CodeModel.h"
#include "FileIo.h"
#include "AppContext.h"
using namespace dev;
using namespace dev::eth;
@ -46,8 +48,13 @@ AppContext::AppContext(QQmlApplicationEngine* _engine)
m_applicationEngine = _engine;
//m_webThree = std::unique_ptr<dev::WebThreeDirect>(new WebThreeDirect(std::string("Mix/v") + dev::Version + "/" DEV_QUOTED(ETH_BUILD_TYPE) "/" DEV_QUOTED(ETH_BUILD_PLATFORM), getDataDir() + "/Mix", false, {"eth", "shh"}));
m_codeModel = std::unique_ptr<CodeModel>(new CodeModel(this));
m_applicationEngine->rootContext()->setContextProperty("codeModel", m_codeModel.get());
m_fileIo.reset(new FileIo());
m_applicationEngine->rootContext()->setContextProperty("appContext", this);
qmlRegisterType<FileIo>("org.ethereum.qml", 1, 0, "FileIo");
qmlRegisterSingletonType(QUrl("qrc:/qml/ProjectModel.qml"), "org.ethereum.qml.ProjectModel", 1, 0, "ProjectModel");
m_applicationEngine->rootContext()->setContextProperty("codeModel", m_codeModel.get());
m_applicationEngine->rootContext()->setContextProperty("fileIo", m_fileIo.get());
}
AppContext::~AppContext()

2
mix/AppContext.h

@ -47,6 +47,7 @@ namespace mix
{
class CodeModel;
class FileIo;
/**
* @brief Provides access to application scope variable.
*/
@ -73,6 +74,7 @@ private:
QQmlApplicationEngine* m_applicationEngine; //owned by app
std::unique_ptr<dev::WebThreeDirect> m_webThree;
std::unique_ptr<CodeModel> m_codeModel;
std::unique_ptr<FileIo> m_fileIo;
public slots:
/// Delete the current instance when application quit.

3
mix/CMakeLists.txt

@ -46,3 +46,6 @@ eth_install_executable(${EXECUTABLE}
QMLDIR ${CMAKE_CURRENT_SOURCE_DIR}/qml
)
#add qml files to project tree in Qt creator
file(GLOB_RECURSE QMLFILES "qml/*.*")
add_custom_target(dummy SOURCES ${QMLFILES})

1
mix/ConstantCompilationControl.cpp

@ -34,6 +34,7 @@
using namespace dev::mix;
ConstantCompilationControl::ConstantCompilationControl(AppContext* _context): Extension(_context, ExtensionDisplayBehavior::Tab)
{
connect(_context->codeModel(), &CodeModel::compilationComplete, this, &ConstantCompilationControl::update);

68
mix/FileIo.cpp

@ -0,0 +1,68 @@
/*
This file is part of cpp-ethereum.
cpp-ethereum is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file FileIo.cpp
* @author Arkadiy Paronyan arkadiy@ethdev.com
* @date 2015
* Ethereum IDE client.
*/
#include <stdexcept>
#include <QDir>
#include <QFile>
#include <QFileInfo>
#include <QTextStream>
#include "FileIo.h"
using namespace dev::mix;
void FileIo::makeDir(QString const& _path)
{
QDir dirPath(_path);
if (!dirPath.exists())
dirPath.mkpath(dirPath.path());
}
QString FileIo::readFile(QString const& _path)
{
QFile file(_path);
if(file.open(QIODevice::ReadOnly | QIODevice::Text))
{
QTextStream stream(&file);
QString data = stream.readAll();
return data;
}
else
throw std::runtime_error(tr("Error reading file %1").arg(_path).toStdString());
}
void FileIo::writeFile(QString const& _path, QString const& _data)
{
QFile file(_path);
if(file.open(QIODevice::WriteOnly | QIODevice::Text))
{
QTextStream stream(&file);
stream << _data;
}
else
throw std::runtime_error(tr("Error writing file %1").arg(_path).toStdString());
}
void FileIo::copyFile(QString const& _sourcePath, QString const& _destPath)
{
if (!QFile::copy(_sourcePath, _destPath))
throw std::runtime_error(tr("Error copying file %1 to %2").arg(_sourcePath).arg(_destPath).toStdString());
}

49
mix/FileIo.h

@ -0,0 +1,49 @@
/*
This file is part of cpp-ethereum.
cpp-ethereum is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file FileIo.h
* @author Arkadiy Paronyan arkadiy@ethdev.com
* @date 2015
* Ethereum IDE client.
*/
#pragma once
#include <QObject>
namespace dev
{
namespace mix
{
///File services for QML
class FileIo : public QObject
{
Q_OBJECT
public:
/// Create a directory if it does not exist. Throws on failure.
Q_INVOKABLE void makeDir(QString const& _path);
/// Read file contents to a string. Throws on failure.
Q_INVOKABLE QString readFile(QString const& _path);
/// Write contents to a file. Throws on failure.
Q_INVOKABLE void writeFile(QString const& _path, QString const& _data);
/// Copy a file from _sourcePath to _destPath. Throws on failure.
Q_INVOKABLE void copyFile(QString const& _sourcePath, QString const& _destPath);
};
}
}

17
mix/qml.qrc

@ -1,16 +1,19 @@
<RCC>
<qresource prefix="/">
<file>qml/BasicContent.qml</file>
<file>qml/main.qml</file>
<file>qml/MainContent.qml</file>
<file>qml/TabStyle.qml</file>
<file>qml/Debugger.qml</file>
<file>qml/js/Debugger.js</file>
<file>qml/AlertMessageDialog.qml</file>
<file>qml/BasicContent.qml</file>
<file>qml/BasicMessage.qml</file>
<file>qml/TransactionDialog.qml</file>
<file>qml/Debugger.qml</file>
<file>qml/MainContent.qml</file>
<file>qml/ModalDialog.qml</file>
<file>qml/AlertMessageDialog.qml</file>
<file>qml/ProjectList.qml</file>
<file>qml/StateDialog.qml</file>
<file>qml/StateList.qml</file>
<file>qml/TabStyle.qml</file>
<file>qml/TransactionDialog.qml</file>
<file>qml/js/Debugger.js</file>
<file>qml/NewProjectDialog.qml</file>
<file>qml/ProjectModel.qml</file>
</qresource>
</RCC>

10
mix/qml/MainContent.qml

@ -20,9 +20,17 @@ Rectangle {
SplitView {
orientation: Qt.Horizontal
anchors.fill: parent
ProjectList {
anchors.left: parent.left
width: parent.width * 0.2
height: parent.height
Layout.minimumWidth: 20
}
SplitView {
//anchors.fill: parent
width: parent.width * 0.8
width: parent.width * 0.6
orientation: Qt.Vertical
Rectangle {
anchors.top: parent.top

92
mix/qml/NewProjectDialog.qml

@ -0,0 +1,92 @@
import QtQuick 2.2
import QtQuick.Controls 1.2
import QtQuick.Layouts 1.1
import QtQuick.Window 2.0
import QtQuick.Dialogs 1.2
Window {
modality: Qt.WindowModal
width: 640
height: 280
visible: false
property alias projectTitle : titleField.text
property alias projectPath : pathField.text
signal accepted
function open() {
visible = true;
titleField.focus = true;
}
function close() {
visible = false;
}
GridLayout {
id: dialogContent
columns: 2
anchors.fill: parent
anchors.margins: 10
rowSpacing: 10
columnSpacing: 10
Label {
text: qsTr("Title")
}
TextField {
id: titleField
focus: true
Layout.fillWidth: true
}
Label {
text: qsTr("Path")
}
RowLayout {
TextField {
id: pathField
Layout.fillWidth: true
}
Button {
text: qsTr("Browse")
onClicked: createProjectFileDialog.open()
}
}
RowLayout
{
anchors.bottom: parent.bottom
anchors.right: parent.right;
Button {
enabled: titleField.text != "" && pathField.text != ""
text: qsTr("Ok");
onClicked: {
close();
accepted();
}
}
Button {
text: qsTr("Cancel");
onClicked: close();
}
}
}
FileDialog {
id: createProjectFileDialog
visible: false
title: qsTr("Please choose a path for the project")
selectFolder: true
onAccepted: {
var u = createProjectFileDialog.fileUrl.toString();
if (u.indexOf("file://") == 0)
u = u.substring(7, u.length)
pathField.text = u;
}
}
}

39
mix/qml/ProjectList.qml

@ -0,0 +1,39 @@
import QtQuick 2.0
import QtQuick.Window 2.0
import QtQuick.Layouts 1.0
import QtQuick.Controls 1.0
import org.ethereum.qml.ProjectModel 1.0
Item {
ListView {
model: ProjectModel.listModel
delegate: renderDelegate
}
Component {
id: renderDelegate
Item {
id: wrapperItem
height: 20
width: parent.width
RowLayout {
anchors.fill: parent
Text {
Layout.fillWidth: true
Layout.fillHeight: true
text: title
font.pointSize: 12
verticalAlignment: Text.AlignBottom
}
}
}
}
Action {
id: createProjectAction
text: qsTr("&New project")
shortcut: "Ctrl+N"
enabled: true;
onTriggered: ProjectModel.createProject();
}
}

140
mix/qml/ProjectModel.qml

@ -0,0 +1,140 @@
pragma Singleton
import QtQuick 2.0
import QtQuick.Window 2.0
import QtQuick.Layouts 1.0
import QtQuick.Controls 1.0
import QtQuick.Dialogs 1.1
import Qt.labs.settings 1.0
Item {
id: projectModel
signal projectClosed
signal projectLoaded
property bool isEmpty: projectFile === ""
readonly property string projectFileName: ".mix"
property bool haveUnsavedChanges: false
property string projectFile: ""
property var projectData: null
property var listModel: projectListModel
function saveAll() {
saveProject();
}
function createProject() {
closeProject();
newProjectDialog.open();
}
function closeProject() {
console.log("closing project");
if (haveUnsavedChanges)
saveMessageDialog.open();
else
doCloseProject();
}
function saveProject() {
if (!isEmpty) {
var json = JSON.stringify(projectData);
fileIo.writeFile(projectFile, json)
}
}
function loadProject(path) {
if (!isEmpty)
closeProject();
console.log("loading project at " + path);
var json = fileIo.readFile(path);
projectData = JSON.parse(json);
projectFile = path;
if (!projectData.files)
projectData.files = [];
for(var i = 0; i < projectData.files; i++) {
var p = projectData.files[i];
projectListModel.append({
path: p,
name: p.substring(p.lastIndexOf("/") + 1, p.length)
});
}
onProjectLoaded();
}
function doCloseProject() {
projectListModel.clear();
projectFile = "";
projectData = null;
projectClosed();
}
function doCreateProject(title, path) {
if (!isEmpty)
closeProject();
console.log("creating project " + title + " at " + path);
if (path[path.length - 1] !== "/")
path += "/";
var dirPath = path + title;
fileIo.makeDir(dirPath);
var projectFile = dirPath + "/" + projectFileName;
fileIo.writeFile(projectFile, "");
loadProject(projectFile);
}
NewProjectDialog {
id: newProjectDialog
visible: false
onAccepted: {
var title = newProjectDialog.projectTitle;
var path = newProjectDialog.projectPath;
projectModel.doCreateProject(title, path);
}
}
MessageDialog {
id: saveMessageDialog
title: qsTr("Project")
text: qsTr("Do you want to save changes?")
standardButtons: StandardButton.Ok | StandardButton.Cancel
icon: StandardIcon.Question
onAccepted: {
projectModel.saveAll();
projectModel.doCloseProject();
}
onRejected: {
projectModel.doCloseProject();
}
}
ListModel {
id: projectListModel
}
Component {
id: renderDelegate
Item {
id: wrapperItem
height: 20
width: parent.width
RowLayout {
anchors.fill: parent
Text {
Layout.fillWidth: true
Layout.fillHeight: true
text: title
font.pointSize: 12
verticalAlignment: Text.AlignBottom
}
}
}
}
Settings {
id: projectSettings
property string lastProjectPath;
}
}

14
mix/qml/StateList.qml

@ -3,6 +3,7 @@ import QtQuick.Controls.Styles 1.2
import QtQuick.Controls 1.2
import QtQuick.Dialogs 1.2
import QtQuick.Layouts 1.1
import org.ethereum.qml.ProjectModel 1.0
Rectangle {
color: "transparent"
@ -15,9 +16,12 @@ Rectangle {
property var stateList: []
Connections {
target: appContext
target: ProjectModel
onProjectClosed: {
stateListModel.clear();
}
onProjectLoaded: {
var items = JSON.parse(_json);
var items = target.projectData.states;
for(var i = 0; i < items.length; i++) {
stateListModel.append(items[i]);
stateList.push(items[i])
@ -82,8 +86,8 @@ Rectangle {
}
function save() {
var json = JSON.stringify(stateList);
appContext.saveProject(json);
console.log(parent.id);
ProjectModel.saveProject();
}
}
@ -124,7 +128,7 @@ Rectangle {
Action {
id: addStateAction
text: "&Add State"
shortcut: "Ctrl+N"
shortcut: "Ctrl+T"
enabled: codeModel.hasContract && !debugModel.running;
onTriggered: stateListModel.addState();
}

Loading…
Cancel
Save