mirror of
https://github.com/jdegenstein/jmwright-CQ-Editor.git
synced 2025-12-21 15:04:25 +01:00
from jmwright 72b67da
This commit is contained in:
341
cq_editor/main_window.py
Normal file
341
cq_editor/main_window.py
Normal file
@@ -0,0 +1,341 @@
|
||||
import sys
|
||||
|
||||
from PyQt5.QtWidgets import (QLabel, QMainWindow, QToolBar, QDockWidget, QAction)
|
||||
|
||||
import cadquery as cq
|
||||
|
||||
from .widgets.editor import Editor
|
||||
from .widgets.viewer import OCCViewer
|
||||
from .widgets.console import ConsoleWidget
|
||||
from .widgets.object_tree import ObjectTree
|
||||
from .widgets.traceback_viewer import TracebackPane
|
||||
from .widgets.debugger import Debugger, LocalsView
|
||||
from .widgets.cq_object_inspector import CQObjectInspector
|
||||
from .widgets.log import LogViewer
|
||||
|
||||
from . import __version__
|
||||
from .utils import dock, add_actions, open_url, about_dialog, check_gtihub_for_updates, confirm
|
||||
from .mixins import MainMixin
|
||||
from .icons import icon
|
||||
from .preferences import PreferencesWidget
|
||||
|
||||
|
||||
class MainWindow(QMainWindow,MainMixin):
|
||||
|
||||
name = 'CQ-Editor'
|
||||
org = 'CadQuery'
|
||||
|
||||
def __init__(self,parent=None, filename=None):
|
||||
|
||||
super(MainWindow,self).__init__(parent)
|
||||
MainMixin.__init__(self)
|
||||
|
||||
self.setWindowIcon(icon('app'))
|
||||
|
||||
self.viewer = OCCViewer(self)
|
||||
self.setCentralWidget(self.viewer.canvas)
|
||||
|
||||
self.prepare_panes()
|
||||
self.registerComponent('viewer',self.viewer)
|
||||
self.prepare_toolbar()
|
||||
self.prepare_menubar()
|
||||
|
||||
self.prepare_statusbar()
|
||||
self.prepare_actions()
|
||||
|
||||
self.components['object_tree'].addLines()
|
||||
|
||||
self.prepare_console()
|
||||
|
||||
self.fill_dummy()
|
||||
|
||||
self.setup_logging()
|
||||
|
||||
self.restorePreferences()
|
||||
self.restoreWindow()
|
||||
|
||||
if filename:
|
||||
self.components['editor'].load_from_file(filename)
|
||||
|
||||
self.restoreComponentState()
|
||||
|
||||
def closeEvent(self,event):
|
||||
|
||||
self.saveWindow()
|
||||
self.savePreferences()
|
||||
self.saveComponentState()
|
||||
|
||||
if self.components['editor'].document().isModified():
|
||||
|
||||
rv = confirm(self, 'Confirm close', 'Close without saving?')
|
||||
|
||||
if rv:
|
||||
event.accept()
|
||||
super(MainWindow,self).closeEvent(event)
|
||||
else:
|
||||
event.ignore()
|
||||
else:
|
||||
super(MainWindow,self).closeEvent(event)
|
||||
|
||||
def prepare_panes(self):
|
||||
|
||||
self.registerComponent('editor',
|
||||
Editor(self),
|
||||
lambda c : dock(c,
|
||||
'Editor',
|
||||
self,
|
||||
defaultArea='left'))
|
||||
|
||||
self.registerComponent('object_tree',
|
||||
ObjectTree(self),
|
||||
lambda c: dock(c,
|
||||
'Objects',
|
||||
self,
|
||||
defaultArea='right'))
|
||||
|
||||
self.registerComponent('console',
|
||||
ConsoleWidget(self),
|
||||
lambda c: dock(c,
|
||||
'Console',
|
||||
self,
|
||||
defaultArea='bottom'))
|
||||
|
||||
self.registerComponent('traceback_viewer',
|
||||
TracebackPane(self),
|
||||
lambda c: dock(c,
|
||||
'Current traceback',
|
||||
self,
|
||||
defaultArea='bottom'))
|
||||
|
||||
self.registerComponent('debugger',Debugger(self))
|
||||
|
||||
self.registerComponent('variables_viewer',LocalsView(self),
|
||||
lambda c: dock(c,
|
||||
'Variables',
|
||||
self,
|
||||
defaultArea='right'))
|
||||
|
||||
self.registerComponent('cq_object_inspector',
|
||||
CQObjectInspector(self),
|
||||
lambda c: dock(c,
|
||||
'CQ object inspector',
|
||||
self,
|
||||
defaultArea='right'))
|
||||
self.registerComponent('log',
|
||||
LogViewer(self),
|
||||
lambda c: dock(c,
|
||||
'Log viewer',
|
||||
self,
|
||||
defaultArea='bottom'))
|
||||
|
||||
for d in self.docks.values():
|
||||
d.show()
|
||||
|
||||
def prepare_menubar(self):
|
||||
|
||||
menu = self.menuBar()
|
||||
|
||||
menu_file = menu.addMenu('&File')
|
||||
menu_edit = menu.addMenu('&Edit')
|
||||
menu_tools = menu.addMenu('&Tools')
|
||||
menu_run = menu.addMenu('&Run')
|
||||
menu_view = menu.addMenu('&View')
|
||||
menu_help = menu.addMenu('&Help')
|
||||
|
||||
#per component menu elements
|
||||
menus = {'File' : menu_file,
|
||||
'Edit' : menu_edit,
|
||||
'Run' : menu_run,
|
||||
'Tools': menu_tools,
|
||||
'View' : menu_view,
|
||||
'Help' : menu_help}
|
||||
|
||||
for comp in self.components.values():
|
||||
self.prepare_menubar_component(menus,
|
||||
comp.menuActions())
|
||||
|
||||
#global menu elements
|
||||
menu_view.addSeparator()
|
||||
for d in self.findChildren(QDockWidget):
|
||||
menu_view.addAction(d.toggleViewAction())
|
||||
|
||||
menu_view.addSeparator()
|
||||
for t in self.findChildren(QToolBar):
|
||||
menu_view.addAction(t.toggleViewAction())
|
||||
|
||||
menu_edit.addAction( \
|
||||
QAction(icon('preferences'),
|
||||
'Preferences',
|
||||
self,triggered=self.edit_preferences))
|
||||
|
||||
menu_help.addAction( \
|
||||
QAction(icon('help'),
|
||||
'Documentation',
|
||||
self,triggered=self.documentation))
|
||||
|
||||
menu_help.addAction( \
|
||||
QAction('CQ documentation',
|
||||
self,triggered=self.cq_documentation))
|
||||
|
||||
menu_help.addAction( \
|
||||
QAction(icon('about'),
|
||||
'About',
|
||||
self,triggered=self.about))
|
||||
|
||||
menu_help.addAction( \
|
||||
QAction('Check for CadQuery updates',
|
||||
self,triggered=self.check_for_cq_updates))
|
||||
|
||||
def prepare_menubar_component(self,menus,comp_menu_dict):
|
||||
|
||||
for name,action in comp_menu_dict.items():
|
||||
menus[name].addActions(action)
|
||||
|
||||
def prepare_toolbar(self):
|
||||
|
||||
self.toolbar = QToolBar('Main toolbar',self,objectName='Main toolbar')
|
||||
|
||||
for c in self.components.values():
|
||||
add_actions(self.toolbar,c.toolbarActions())
|
||||
|
||||
self.addToolBar(self.toolbar)
|
||||
|
||||
def prepare_statusbar(self):
|
||||
|
||||
self.status_label = QLabel('',parent=self)
|
||||
self.statusBar().insertPermanentWidget(0, self.status_label)
|
||||
|
||||
def prepare_actions(self):
|
||||
|
||||
self.components['debugger'].sigRendered\
|
||||
.connect(self.components['object_tree'].addObjects)
|
||||
self.components['debugger'].sigTraceback\
|
||||
.connect(self.components['traceback_viewer'].addTraceback)
|
||||
self.components['debugger'].sigLocals\
|
||||
.connect(self.components['variables_viewer'].update_frame)
|
||||
self.components['debugger'].sigLocals\
|
||||
.connect(self.components['console'].push_vars)
|
||||
|
||||
self.components['object_tree'].sigObjectsAdded[list]\
|
||||
.connect(self.components['viewer'].display_many)
|
||||
self.components['object_tree'].sigObjectsAdded[list,bool]\
|
||||
.connect(self.components['viewer'].display_many)
|
||||
self.components['object_tree'].sigItemChanged.\
|
||||
connect(self.components['viewer'].update_item)
|
||||
self.components['object_tree'].sigObjectsRemoved\
|
||||
.connect(self.components['viewer'].remove_items)
|
||||
self.components['object_tree'].sigCQObjectSelected\
|
||||
.connect(self.components['cq_object_inspector'].setObject)
|
||||
self.components['object_tree'].sigObjectPropertiesChanged\
|
||||
.connect(self.components['viewer'].redraw)
|
||||
self.components['object_tree'].sigAISObjectsSelected\
|
||||
.connect(self.components['viewer'].set_selected)
|
||||
|
||||
self.components['viewer'].sigObjectSelected\
|
||||
.connect(self.components['object_tree'].handleGraphicalSelection)
|
||||
|
||||
self.components['traceback_viewer'].sigHighlightLine\
|
||||
.connect(self.components['editor'].go_to_line)
|
||||
|
||||
self.components['cq_object_inspector'].sigDisplayObjects\
|
||||
.connect(self.components['viewer'].display_many)
|
||||
self.components['cq_object_inspector'].sigRemoveObjects\
|
||||
.connect(self.components['viewer'].remove_items)
|
||||
self.components['cq_object_inspector'].sigShowPlane\
|
||||
.connect(self.components['viewer'].toggle_grid)
|
||||
self.components['cq_object_inspector'].sigShowPlane[bool,float]\
|
||||
.connect(self.components['viewer'].toggle_grid)
|
||||
self.components['cq_object_inspector'].sigChangePlane\
|
||||
.connect(self.components['viewer'].set_grid_orientation)
|
||||
|
||||
self.components['debugger'].sigLocalsChanged\
|
||||
.connect(self.components['variables_viewer'].update_frame)
|
||||
self.components['debugger'].sigLineChanged\
|
||||
.connect(self.components['editor'].go_to_line)
|
||||
self.components['debugger'].sigDebugging\
|
||||
.connect(self.components['object_tree'].stashObjects)
|
||||
self.components['debugger'].sigCQChanged\
|
||||
.connect(self.components['object_tree'].addObjects)
|
||||
self.components['debugger'].sigTraceback\
|
||||
.connect(self.components['traceback_viewer'].addTraceback)
|
||||
|
||||
# trigger re-render when file is modified externally or saved
|
||||
self.components['editor'].triggerRerender \
|
||||
.connect(self.components['debugger'].render)
|
||||
self.components['editor'].sigFilenameChanged\
|
||||
.connect(self.handle_filename_change)
|
||||
|
||||
def prepare_console(self):
|
||||
|
||||
console = self.components['console']
|
||||
obj_tree = self.components['object_tree']
|
||||
|
||||
#application related items
|
||||
console.push_vars({'self' : self})
|
||||
|
||||
#CQ related items
|
||||
console.push_vars({'show' : obj_tree.addObject,
|
||||
'show_object' : obj_tree.addObject,
|
||||
'cq' : cq})
|
||||
|
||||
def fill_dummy(self):
|
||||
|
||||
self.components['editor']\
|
||||
.set_text('import cadquery as cq\nresult = cq.Workplane("XY" ).box(3, 3, 0.5).edges("|Z").fillet(0.125)')
|
||||
|
||||
def setup_logging(self):
|
||||
|
||||
from logbook.compat import redirect_logging
|
||||
from logbook import INFO, Logger
|
||||
|
||||
redirect_logging()
|
||||
self.components['log'].handler.level = INFO
|
||||
self.components['log'].handler.push_application()
|
||||
|
||||
self._logger = Logger(self.name)
|
||||
|
||||
def handle_exception(exc_type, exc_value, exc_traceback):
|
||||
|
||||
if issubclass(exc_type, KeyboardInterrupt):
|
||||
sys.__excepthook__(exc_type, exc_value, exc_traceback)
|
||||
return
|
||||
|
||||
self._logger.error("Uncaught exception occurred",
|
||||
exc_info=(exc_type, exc_value, exc_traceback))
|
||||
|
||||
sys.excepthook = handle_exception
|
||||
|
||||
|
||||
def edit_preferences(self):
|
||||
|
||||
prefs = PreferencesWidget(self,self.components)
|
||||
prefs.exec_()
|
||||
|
||||
def about(self):
|
||||
|
||||
about_dialog(
|
||||
self,
|
||||
f'About CQ-editor',
|
||||
f'PyQt GUI for CadQuery.\nVersion: {__version__}.\nSource Code: https://github.com/CadQuery/CQ-editor',
|
||||
)
|
||||
|
||||
def check_for_cq_updates(self):
|
||||
|
||||
check_gtihub_for_updates(self,cq)
|
||||
|
||||
def documentation(self):
|
||||
|
||||
open_url('https://github.com/CadQuery')
|
||||
|
||||
def cq_documentation(self):
|
||||
|
||||
open_url('https://cadquery.readthedocs.io/en/latest/')
|
||||
|
||||
def handle_filename_change(self, fname):
|
||||
|
||||
new_title = fname if fname else "*"
|
||||
self.setWindowTitle(f"{self.name}: {new_title}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
pass
|
||||
Reference in New Issue
Block a user