app.py 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. #!/usr/bin/python
  2. # -*- coding: utf-8 -*-
  3. # @Author: Bachir Soussi Chiadmi <bach>
  4. # @Date: 23-05-2017
  5. # @Email: bachir@figureslibres.io
  6. # @Last modified by: bach
  7. # @Last modified time: 21-04-2017
  8. # @License: GPL-V3
  9. import sys, os
  10. from socket import socket
  11. import socketserver
  12. import http.server
  13. import threading
  14. from PyQt5 import QtCore
  15. from PyQt5.QtCore import QCoreApplication, QUrl, QFileSystemWatcher, pyqtSlot, QSettings
  16. from PyQt5.QtGui import QKeySequence
  17. from PyQt5.QtWidgets import QMainWindow, QWidget, QApplication, QShortcut, QGridLayout, QLabel, QTabWidget, QHBoxLayout, QVBoxLayout, QSplitter, QSplitterHandle
  18. # from PyQt5.QtNetwork import QNetworkProxyFactory, QNetworkRequest
  19. from PyQt5.QtWebKit import QWebSettings
  20. from PyQt5.QtWebKitWidgets import QWebPage, QWebView, QWebInspector
  21. import sass
  22. class Core():
  23. def __init__(self, parent=None):
  24. self.server = Server()
  25. self.compiler = Compiler()
  26. self.settings = QSettings('FiguresLibres', 'Cascade')
  27. class Server():
  28. def __init__(self, parent=None):
  29. # find free port
  30. sock = socket()
  31. sock.bind(('', 0))
  32. self._port = sock.getsockname()[1]
  33. sock.close()
  34. self.httpd = http.server.HTTPServer(('', self.port), http.server.SimpleHTTPRequestHandler)
  35. self.thread = threading.Thread(target=self.httpd.serve_forever)
  36. self.thread.start()
  37. print("serving at port", self._port)
  38. @property
  39. def port(self):
  40. return self._port
  41. class Compiler():
  42. def __init__(self,parent=None):
  43. paths = [
  44. 'assets',
  45. 'assets/scss',
  46. 'assets/scss/styles.scss'
  47. ]
  48. self.fs_watcher = QFileSystemWatcher(paths)
  49. # self.fs_watcher.directoryChanged.connect(self.directory_changed)
  50. self.fs_watcher.fileChanged.connect(self.compile_scss)
  51. self.compile_scss()
  52. # def directory_changed(path):
  53. # print("Directory changed : %s" % path)
  54. def compile_scss(path = ""):
  55. print("compiling sass : %s" % path)
  56. scss = sass.compile_file(b'assets/scss/main.scss')
  57. with open('assets/scss/main.css', 'w') as fp:
  58. fp.write(scss.decode('utf8'))
  59. class WebkitView(QWebView):
  60. def __init__(self, port):
  61. self.port = port
  62. self.view = QWebView.__init__(self)
  63. self.load(QUrl('http://localhost:'+str(self.port)))
  64. self.settings().setAttribute(QWebSettings.DeveloperExtrasEnabled, True)
  65. # self.settings().setAttribute(QWebSettings.PluginsEnabled, True)
  66. class WebkitInspector(QWebInspector):
  67. def __init__(self, webkitview):
  68. super().__init__()
  69. self.webkitview = webkitview
  70. self.setPage(self.webkitview.page())
  71. # TODO: webkitinspector is disappearing when chaging tabs
  72. class ViewTab(QWidget):
  73. def __init__(self, core):
  74. super(ViewTab, self).__init__()
  75. # self.grid = QGridLayout()
  76. hbox = QHBoxLayout()
  77. self.setLayout(hbox)
  78. # webviewbox = QVBoxLayout()
  79. vsplitter = QSplitter(QtCore.Qt.Vertical)
  80. self.webkitview = WebkitView(core.server.port)
  81. vsplitter.addWidget(self.webkitview)
  82. self.webkitinspector = WebkitInspector(self.webkitview)
  83. vsplitter.addWidget(self.webkitinspector)
  84. hsplitter = QSplitter(QtCore.Qt.Horizontal)
  85. hsplitter.addWidget(vsplitter)
  86. self.codeeditor = QLabel("Code Editor (SCSS & JS)")
  87. hsplitter.addWidget(self.codeeditor)
  88. hbox.addWidget(hsplitter)
  89. def onChanged(self, text):
  90. print("ViewTba Layout Changed")
  91. self.lbl.setText(text)
  92. self.lbl.adjustSize()
  93. class MainWindow(QMainWindow):
  94. def __init__(self, core):
  95. super(MainWindow, self).__init__()
  96. self.core = core
  97. self.restorePreferences()
  98. # self.setWindowFlags(QtCore.Qt.WindowTitleHint)
  99. # QtCore.Qt.CustomizeWindowHint
  100. # | QtCore.Qt.Tool
  101. # | QtCore.Qt.FramelessWindowHint
  102. # | QtCore.Qt.WindowTitleHint
  103. # | QtCore.Qt.WindowStaysOnTopHint
  104. self.tabwidget = QTabWidget()
  105. # self.tabwidget.setStyleSheet("""
  106. # .QWidget {
  107. # border: 1px solid black;
  108. # margin:0;
  109. # padding:0;
  110. # }
  111. # """)
  112. self.viewtab = ViewTab(core)
  113. self.contenttab = QLabel("Content (markdown editor).")
  114. self.versiontab = QLabel("Version (git).")
  115. self.tabwidget.addTab(self.viewtab, "View")
  116. self.tabwidget.addTab(self.contenttab, "Content")
  117. self.tabwidget.addTab(self.versiontab, "Version")
  118. self.setCentralWidget(self.tabwidget)
  119. self.shortcut = QShortcut(QKeySequence("Ctrl+Q"), self)
  120. self.shortcut.activated.connect(self.on_quit)
  121. self.show()
  122. def restorePreferences(self):
  123. try:
  124. self.resize(self.core.settings.value('mainwindow/size', QtCore.QSize(1024, 768)))
  125. self.move(self.core.settings.value('mainwindow/pos', QtCore.QPoint(0, 0)))
  126. except:
  127. pass
  128. def savePreferences(self):
  129. self.core.settings.beginGroup("mainwindow")
  130. self.core.settings.setValue('size', self.size())
  131. self.core.settings.setValue('pos', self.pos())
  132. self.core.settings.endGroup()
  133. @pyqtSlot()
  134. def on_quit(self):
  135. print("Quit!")
  136. self.savePreferences()
  137. QCoreApplication.instance().quit()
  138. def main():
  139. app = QApplication(sys.argv)
  140. core = Core()
  141. mainappwindow = MainWindow(core)
  142. sys.exit(app.exec_())
  143. if __name__ == "__main__":
  144. main()