diff --git a/app.py b/app.py index 1d1e665..c9b01df 100755 --- a/app.py +++ b/app.py @@ -9,310 +9,19 @@ # @Last modified time: 21-04-2017 # @License: GPL-V3 -import sys, os, shutil, tempfile - -from PyQt5 import QtCore -from PyQt5.QtCore import QCoreApplication, QUrl, pyqtSlot, QSettings -from PyQt5.QtGui import QIcon, QKeySequence, QFont, QSyntaxHighlighter -from PyQt5.QtWidgets import QMainWindow, QAction, QWidget, QApplication, QShortcut, QGridLayout, QLabel, QTabWidget, QStackedWidget, QHBoxLayout, QVBoxLayout, QSplitter, QSplitterHandle, QPlainTextEdit, QInputDialog, QLineEdit, QFileDialog, QMessageBox, QPushButton -# from PyQt5.QtNetwork import QNetworkProxyFactory, QNetworkRequest -from PyQt5.QtWebKit import QWebSettings -from PyQt5.QtWebKitWidgets import QWebPage, QWebView, QWebInspector - -import json -import git - -from classes import server, sasscompiler, design, content, md2html - -class Core(): - def __init__(self, parent=None): - # restore previous preferences - self.appcwd = os.getcwd() - - self.restorePreferences() - self._mw = False - self.temp = tempfile.mkdtemp() - # print(self.temp) - - self.tempcwd = False - # if ther's not current project folder from restorepref - # initaite a new temp project - if(self.cwd == None or not os.path.isdir(self.cwd)): - self.cwd = os.path.join(self.temp, 'cwd') - self.tempcwd = True - self.initnewproject() - - self.server = server.Server(self) - self.sasscompiler = sasscompiler.Compiler(self) - self.contentcompiler = md2html.Compiler(self) - - @property - def mainwindow(self): - return self.mainwindow - - @mainwindow.setter - def mainwindow(self, mw): - if not self._mw: - self._mw = mw - if not self.tempcwd: - self._mw.setWindowTitle("Cascade – "+self.cwd) - - - def restorePreferences(self): - # print("restorePreferences") - settings = QSettings('FiguresLibres', 'Cascade') - # settings.clear() - # print(settings.allKeys()) - - self.cwd = settings.value('core/cwd', None) - self.dialog_path = settings.value('core/dialog_path', os.path.expanduser('~')) - - self.mw_size = settings.value('mainwindow/size', QtCore.QSize(1024, 768)) - self.mw_pos = settings.value('mainwindow/pos', QtCore.QPoint(0, 0)) - self.mw_curstack = int(settings.value('mainwindow/curstack', 0)) - - - def savePreferences(self): - # print("savePreferences") - settings = QSettings('FiguresLibres', 'Cascade') - # print(settings.allKeys()) - - if not self.tempcwd: - settings.setValue('core/cwd', self.cwd) - - settings.setValue('core/dialog_path', self.dialog_path) - - settings.setValue('mainwindow/size', self._mw.size()) - settings.setValue('mainwindow/pos', self._mw.pos()) - settings.setValue('mainwindow/curstack', self._mw.mainstack.currentIndex()) - - def initnewproject(self, cwd = None): - if cwd == None : - cwd = self.cwd - else : - self.changeCWD(cwd) - - shutil.copytree('templates/newproject', cwd) - self.prefs = json.loads(open(os.path.join(cwd,'.config/prefs.json')).read()) - self.summary = json.loads(open(os.path.join(cwd,'.config/summary.json')).read()) - self.repository = git.Repo.init(cwd) - self.repository.index.add(['assets','contents','.config']) - self.repository.index.commit("initial commit") - # TODO: set mdtohtml compiler from project md to app index.html - # TODO: embed project styles.scss to app scss frame work - - def saveproject(self, cwd = None): - if not cwd == None: - shutil.copytree(self.cwd, cwd) - self.tempcwd = False - self.changeCWD(cwd) - - def changeCWD(self, cwd): - self.cwd = cwd - self.server.reload() - self.sasscompiler.reload() - self.contentcompiler.reload() - # if not self.tempcwd: - self._mw.setWindowTitle("Cascade – "+self.cwd) - - def quit(self): - self.savePreferences() - shutil.rmtree(self.temp, ignore_errors=True) - QCoreApplication.instance().quit() - -class MainWindow(QMainWindow): - def __init__(self, core): - super(MainWindow, self).__init__() - - # load core class - self.core = core - - self.setWindowTitle("Cascade") - self.setWindowIcon(QIcon(os.path.join(self.core.appcwd,'assets/images/icon.png'))) - - self.resize(self.core.mw_size) - self.move(self.core.mw_pos) - - self.initMenuBar() - - self.initMainStack() - - self.show() - - def initMenuBar(self): - # menu bar - bar = self.menuBar() - file = bar.addMenu("&File") - - new = QAction("&New Project",self) - new.setShortcut("Ctrl+n") - file.addAction(new) - - open = QAction("&Open",self) - open.setShortcut("Ctrl+o") - file.addAction(open) - - self.save_action = QAction("&Save Project as",self) - self.save_action.setShortcut("Ctrl+Shift+s") - file.addAction(self.save_action) - - quit = QAction("&Quit",self) - quit.setShortcut("Ctrl+q") - file.addAction(quit) - - file.triggered[QAction].connect(self.onfilemenutrigger) - - # edit menu - edit = bar.addMenu("&Edit") - # edit.addAction("©") - # edit.addAction("&paste") - edit.addAction("&build") - - self.reload_action = QAction("&Reload",self) - self.reload_action.setShortcut("Ctrl+r") - edit.addAction(self.reload_action) - - edit.addAction("&preferences") - - edit.triggered[QAction].connect(self.oneditmenutrigger) - - - # view menu - view = bar.addMenu("&View") - - designview = QAction("&Design",self) - designview.setShortcut("F1") - view.addAction(designview) - - contentview = QAction("&Content",self) - contentview.setShortcut("F2") - view.addAction(contentview) - - versionview = QAction("&Version",self) - versionview.setShortcut("F3") - view.addAction(versionview) - - view.triggered[QAction].connect(self.onviewmenutrigger) - - # about menu - about = bar.addMenu("About") - about.addAction("&Website") - - - def onfilemenutrigger(self, q): - print(q.text()+" is triggered") - if q.text() == "&New Project": - self.newprojectdialogue() - elif q.text() == "&Open": - self.openprojectdialogue() - elif q.text() == "&Save Project as": - self.saveprojectdialogue() - elif q.text() == "&Quit": - self.quit() - - def openprojectdialogue(self): - print("open") - - def newprojectdialogue(self): - dialog = QFileDialog() - dialog.setFileMode(QFileDialog.Directory) - dialog.setAcceptMode(QFileDialog.AcceptOpen) - projectname = dialog.getSaveFileName( - self, - 'New Project', - self.core.dialog_path - )[0] - # TODO: no file type - try: - head, tail = os.path.split(projectname) - self.core.dialog_path = head - if not os.path.isdir(projectname): - self.core.initnewproject(projectname) - else: - print("folder already exists") - # TODO: check if is cascade folder - except Exception as e: - print('Exception', e) - pass - - def saveprojectdialogue(self, quit=False): - dialog = QFileDialog() - dialog.setFileMode(QFileDialog.Directory) - dialog.setAcceptMode(QFileDialog.AcceptOpen) - projectname = dialog.getSaveFileName( - self, - 'Save Project', - self.core.dialog_path - )[0] - # TODO: no file type - try: - head, tail = os.path.split(projectname) - self.core.dialog_path = head - if not os.path.isdir(projectname): - self.core.saveproject(projectname) - if quit: - self.quit() - else: - print("folder already exists") - # TODO: check if is cascade folder - except Exception as e: - print('Exception', e) - pass - - def quit(self): - print("Quit") - if self.core.tempcwd: - buttonReply = QMessageBox.question(self, 'Project Not Saved', "Do you want to save your current project before quiting?", QMessageBox.Yes | QMessageBox.No | QMessageBox.Cancel, QMessageBox.Cancel) - if buttonReply == QMessageBox.Yes: - self.saveprojectdialogue(quit=True) - if buttonReply == QMessageBox.No: - self.core.quit() - else: - self.core.quit() - - - def oneditmenutrigger(self, q): - print(q.text()+" is triggered") - if q.text() == "&Reload": - self.designstack.webkitview.reload() - - - def onviewmenutrigger(self, q): - print(q.text()+" is triggered") - if q.text() == "&Design": - self.mainstack.setCurrentIndex(0) - elif q.text() == "&Content": - self.mainstack.setCurrentIndex(1) - elif q.text() == "&Version": - self.mainstack.setCurrentIndex(2) - - - def initMainStack(self): - self.mainstack = QStackedWidget() - - self.designstack = design.DesignStack(self.core) - self.contentstack = content.ContentStack(self.core) - self.versionstack = QLabel("Version (git).") - - self.mainstack.addWidget(self.designstack) - self.mainstack.addWidget(self.contentstack) - self.mainstack.addWidget(self.versionstack) - - self.mainstack.setCurrentIndex(self.core.mw_curstack) - - self.setCentralWidget(self.mainstack) +import sys +from PyQt5.QtWidgets import QApplication +from classes import core, mainwindow def main(): app = QApplication(sys.argv) app.setOrganizationName('figli') app.setApplicationName('Cascade') - core = Core() - mainappwindow = MainWindow(core) - core.mainwindow = mainappwindow + mainappcore = core.Core() + mainappwindow = mainwindow.MainWindow(mainappcore) + mainappcore.mainwindow = mainappwindow sys.exit(app.exec_()) - - if __name__ == "__main__": main() diff --git a/classes/content.py b/classes/content.py index bc52414..9b7116a 100644 --- a/classes/content.py +++ b/classes/content.py @@ -1,15 +1,14 @@ #!/usr/bin/python # -*- coding: utf-8 -*- -import sys, os +import os, re from PyQt5 import QtCore from PyQt5.QtCore import QSettings -from PyQt5.QtGui import QFont, QSyntaxHighlighter, QKeySequence -from PyQt5.QtWidgets import QWidget, QLabel, QHBoxLayout, QVBoxLayout, QSplitter, QListWidget, QListWidgetItem, QAbstractItemView, QButtonGroup, QPushButton, QInputDialog, QPlainTextEdit, QTextEdit,QShortcut +from PyQt5.QtGui import QKeySequence +from PyQt5.QtWidgets import QWidget, QLabel, QHBoxLayout, QVBoxLayout, QSplitter, QListWidget, QListWidgetItem, QAbstractItemView, QPushButton, QInputDialog, QPlainTextEdit, QTextEdit, QShortcut import markdown2 -import re import json diff --git a/classes/core.py b/classes/core.py new file mode 100644 index 0000000..8d87eb3 --- /dev/null +++ b/classes/core.py @@ -0,0 +1,117 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + + +# @Author: Bachir Soussi Chiadmi +# @Date: 23-05-2017 +# @Email: bachir@figureslibres.io +# @Last modified by: bach +# @Last modified time: 21-04-2017 +# @License: GPL-V3 + +import os, shutil, tempfile +# sys, +from PyQt5 import QtCore +from PyQt5.QtCore import QSettings + +import json +import git + +from classes import server, sasscompiler, md2html + + +class Core(): + def __init__(self, parent=None): + # restore previous preferences + self.appcwd = os.getcwd() + + self.restorePreferences() + self._mw = False + self.temp = tempfile.mkdtemp() + # print(self.temp) + + self.tempcwd = False + # if ther's not current project folder from restorepref + # initaite a new temp project + if(self.cwd == None or not os.path.isdir(self.cwd)): + self.cwd = os.path.join(self.temp, 'cwd') + self.tempcwd = True + self.initnewproject() + + self.server = server.Server(self) + self.sasscompiler = sasscompiler.Compiler(self) + self.contentcompiler = md2html.Compiler(self) + + @property + def mainwindow(self): + return self.mainwindow + + @mainwindow.setter + def mainwindow(self, mw): + if not self._mw: + self._mw = mw + if not self.tempcwd: + self._mw.setWindowTitle("Cascade – "+self.cwd) + + + def restorePreferences(self): + # print("restorePreferences") + settings = QSettings('FiguresLibres', 'Cascade') + # settings.clear() + # print(settings.allKeys()) + + self.cwd = settings.value('core/cwd', None) + self.dialog_path = settings.value('core/dialog_path', os.path.expanduser('~')) + + self.mw_size = settings.value('mainwindow/size', QtCore.QSize(1024, 768)) + self.mw_pos = settings.value('mainwindow/pos', QtCore.QPoint(0, 0)) + self.mw_curstack = int(settings.value('mainwindow/curstack', 0)) + + + def savePreferences(self): + # print("savePreferences") + settings = QSettings('FiguresLibres', 'Cascade') + # print(settings.allKeys()) + + if not self.tempcwd: + settings.setValue('core/cwd', self.cwd) + + settings.setValue('core/dialog_path', self.dialog_path) + + settings.setValue('mainwindow/size', self._mw.size()) + settings.setValue('mainwindow/pos', self._mw.pos()) + settings.setValue('mainwindow/curstack', self._mw.mainstack.currentIndex()) + + def initnewproject(self, cwd = None): + if cwd == None : + cwd = self.cwd + else : + self.changeCWD(cwd) + + shutil.copytree('templates/newproject', cwd) + self.prefs = json.loads(open(os.path.join(cwd,'.config/prefs.json')).read()) + self.summary = json.loads(open(os.path.join(cwd,'.config/summary.json')).read()) + self.repository = git.Repo.init(cwd) + self.repository.index.add(['assets','contents','.config']) + self.repository.index.commit("initial commit") + # TODO: set mdtohtml compiler from project md to app index.html + # TODO: embed project styles.scss to app scss frame work + + def saveproject(self, cwd = None): + if not cwd == None: + shutil.copytree(self.cwd, cwd) + self.tempcwd = False + self.changeCWD(cwd) + + def changeCWD(self, cwd): + self.cwd = cwd + self.server.reload() + self.sasscompiler.reload() + self.contentcompiler.reload() + # if not self.tempcwd: + self._mw.setWindowTitle("Cascade – "+self.cwd) + + def quit(self): + self.savePreferences() + shutil.rmtree(self.temp, ignore_errors=True) + QCoreApplication.instance().quit() diff --git a/classes/design.py b/classes/design.py index 92a0d6a..4f51ef0 100644 --- a/classes/design.py +++ b/classes/design.py @@ -1,12 +1,12 @@ #!/usr/bin/python # -*- coding: utf-8 -*- -import sys, os, re - +import os, re +# sys, from PyQt5 import QtCore from PyQt5.QtCore import QUrl, QSettings -from PyQt5.QtGui import QKeySequence, QFont, QSyntaxHighlighter -from PyQt5.QtWidgets import QWidget, QLabel, QTabWidget, QVBoxLayout, QHBoxLayout, QSplitter, QPlainTextEdit, QShortcut, QPushButton, QCheckBox +from PyQt5.QtGui import QKeySequence, QFont +from PyQt5.QtWidgets import QWidget, QTabWidget, QVBoxLayout, QHBoxLayout, QSplitter, QPlainTextEdit, QShortcut, QPushButton, QCheckBox from PyQt5.QtWebKit import QWebSettings from PyQt5.QtWebKitWidgets import QWebView, QWebInspector @@ -76,6 +76,7 @@ class WebViewOptions(QWidget): def onReload(self): print("onReload") + # self.parent.webkitview. def onPreview(self): print('onPreview') diff --git a/classes/mainwindow.py b/classes/mainwindow.py new file mode 100644 index 0000000..f7d92bf --- /dev/null +++ b/classes/mainwindow.py @@ -0,0 +1,201 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + + +# @Author: Bachir Soussi Chiadmi +# @Date: 23-05-2017 +# @Email: bachir@figureslibres.io +# @Last modified by: bach +# @Last modified time: 21-04-2017 +# @License: GPL-V3 + +import os + +from PyQt5.QtGui import QIcon +from PyQt5.QtWidgets import QMainWindow, QAction, QWidget, QLabel, QStackedWidget, QFileDialog, QMessageBox + +from classes import design, content + + + +class MainWindow(QMainWindow): + def __init__(self, core): + super(MainWindow, self).__init__() + + # load core class + self.core = core + + self.setWindowTitle("Cascade") + self.setWindowIcon(QIcon(os.path.join(self.core.appcwd,'assets/images/icon.png'))) + + self.resize(self.core.mw_size) + self.move(self.core.mw_pos) + + self.initMenuBar() + + self.initMainStack() + + self.show() + + def initMenuBar(self): + # menu bar + bar = self.menuBar() + file = bar.addMenu("&File") + + new = QAction("&New Project",self) + new.setShortcut("Ctrl+n") + file.addAction(new) + + open = QAction("&Open",self) + open.setShortcut("Ctrl+o") + file.addAction(open) + + self.save_action = QAction("&Save Project as",self) + self.save_action.setShortcut("Ctrl+Shift+s") + file.addAction(self.save_action) + + quit = QAction("&Quit",self) + quit.setShortcut("Ctrl+q") + file.addAction(quit) + + file.triggered[QAction].connect(self.onfilemenutrigger) + + # edit menu + edit = bar.addMenu("&Edit") + # edit.addAction("©") + # edit.addAction("&paste") + edit.addAction("&build") + + self.reload_action = QAction("&Reload",self) + self.reload_action.setShortcut("Ctrl+r") + edit.addAction(self.reload_action) + + edit.addAction("&preferences") + + edit.triggered[QAction].connect(self.oneditmenutrigger) + + + # view menu + view = bar.addMenu("&View") + + designview = QAction("&Design",self) + designview.setShortcut("F1") + view.addAction(designview) + + contentview = QAction("&Content",self) + contentview.setShortcut("F2") + view.addAction(contentview) + + versionview = QAction("&Version",self) + versionview.setShortcut("F3") + view.addAction(versionview) + + view.triggered[QAction].connect(self.onviewmenutrigger) + + # about menu + about = bar.addMenu("About") + about.addAction("&Website") + + + def onfilemenutrigger(self, q): + print(q.text()+" is triggered") + if q.text() == "&New Project": + self.newprojectdialogue() + elif q.text() == "&Open": + self.openprojectdialogue() + elif q.text() == "&Save Project as": + self.saveprojectdialogue() + elif q.text() == "&Quit": + self.quit() + + def openprojectdialogue(self): + print("open") + + def newprojectdialogue(self): + dialog = QFileDialog() + dialog.setFileMode(QFileDialog.Directory) + dialog.setAcceptMode(QFileDialog.AcceptOpen) + projectname = dialog.getSaveFileName( + self, + 'New Project', + self.core.dialog_path + )[0] + # TODO: no file type + try: + head, tail = os.path.split(projectname) + self.core.dialog_path = head + if not os.path.isdir(projectname): + self.core.initnewproject(projectname) + else: + print("folder already exists") + # TODO: check if is cascade folder + except Exception as e: + print('Exception', e) + pass + + def saveprojectdialogue(self, quit=False): + dialog = QFileDialog() + dialog.setFileMode(QFileDialog.Directory) + dialog.setAcceptMode(QFileDialog.AcceptOpen) + projectname = dialog.getSaveFileName( + self, + 'Save Project', + self.core.dialog_path + )[0] + # TODO: no file type + try: + head, tail = os.path.split(projectname) + self.core.dialog_path = head + if not os.path.isdir(projectname): + self.core.saveproject(projectname) + if quit: + self.quit() + else: + print("folder already exists") + # TODO: check if is cascade folder + except Exception as e: + print('Exception', e) + pass + + def quit(self): + print("Quit") + if self.core.tempcwd: + buttonReply = QMessageBox.question(self, 'Project Not Saved', "Do you want to save your current project before quiting?", QMessageBox.Yes | QMessageBox.No | QMessageBox.Cancel, QMessageBox.Cancel) + if buttonReply == QMessageBox.Yes: + self.saveprojectdialogue(quit=True) + if buttonReply == QMessageBox.No: + self.core.quit() + else: + self.core.quit() + + + def oneditmenutrigger(self, q): + print(q.text()+" is triggered") + if q.text() == "&Reload": + self.designstack.webkitview.reload() + + + def onviewmenutrigger(self, q): + print(q.text()+" is triggered") + if q.text() == "&Design": + self.mainstack.setCurrentIndex(0) + elif q.text() == "&Content": + self.mainstack.setCurrentIndex(1) + elif q.text() == "&Version": + self.mainstack.setCurrentIndex(2) + + + def initMainStack(self): + self.mainstack = QStackedWidget() + + self.designstack = design.DesignStack(self.core) + self.contentstack = content.ContentStack(self.core) + self.versionstack = QLabel("Version (git).") + + self.mainstack.addWidget(self.designstack) + self.mainstack.addWidget(self.contentstack) + self.mainstack.addWidget(self.versionstack) + + self.mainstack.setCurrentIndex(self.core.mw_curstack) + + self.setCentralWidget(self.mainstack) diff --git a/classes/server.py b/classes/server.py index d0a1654..3e305a8 100644 --- a/classes/server.py +++ b/classes/server.py @@ -3,9 +3,7 @@ import sys, os - from socket import socket - import socketserver import http.server import threading