Incorporate console into main app, fallback to QPlainTextEdit, some styling

This commit is contained in:
Thomas Krijnen
2016-11-28 17:00:32 +01:00
parent 90e4f21f29
commit c94ed73b8d
4 changed files with 224 additions and 210 deletions
+137 -37
View File
@@ -1,5 +1,6 @@
from __future__ import print_function from __future__ import print_function
import os
import sys import sys
import time import time
import operator import operator
@@ -7,10 +8,17 @@ import functools
import OCC.AIS import OCC.AIS
from collections import defaultdict, Iterable from collections import defaultdict, Iterable, OrderedDict
os.environ['QT_API'] = 'pyqt4'
try:
from pyqode.qt import QtCore
except: pass
from PyQt4 import QtGui, QtCore from PyQt4 import QtGui, QtCore
from .code_editor_pane import code_edit
try: from OCC.Display.pyqt4Display import qtViewer3d try: from OCC.Display.pyqt4Display import qtViewer3d
except: except:
import OCC.Display import OCC.Display
@@ -27,7 +35,8 @@ except:
from .main import settings, iterator from .main import settings, iterator
from .occ_utils import display_shape from .occ_utils import display_shape
from .. import open, get_supertype from .. import open as open_ifc_file
from .. import get_supertype
# Depending on Python version and what not there may or may not be a QString # Depending on Python version and what not there may or may not be a QString
try: try:
@@ -35,6 +44,65 @@ try:
except ImportError: except ImportError:
QString = str QString = str
class configuration(object):
def __init__(self):
try:
import ConfigParser
Cfg = ConfigParser.RawConfigParser
except:
import configparser
Cfg = configparser.ConfigParser(interpolation=None)
conf_file = os.path.expanduser(os.path.join("~", ".ifcopenshell", "app", "snippets.conf"))
if conf_file.startswith("~"):
conf_file = None
return
self.config_encode = lambda s: s.replace("\\", "\\\\").replace("\n", "\n|")
self.config_decode = lambda s: s.replace("\n|", "\n").replace("\\\\", "\\")
if not os.path.exists(os.path.dirname(conf_file)):
os.makedirs(os.path.dirname(conf_file))
if not os.path.exists(conf_file):
config = Cfg()
config.add_section("snippets")
config.set("snippets", "print all wall ids", self.config_encode("""
###########################################################################
# A simple script that iterates over all walls in the current model #
# and prints their Globally unique IDs (GUIDS) to the console window #
###########################################################################
for wall in model.by_type("IfcWall"):
print ("wall with global id: "+str(wall.GlobalId))
""".lstrip()))
config.set("snippets", "print properties of current selection", self.config_encode("""
###########################################################################
# A simple script that iterates over all IfcPropertySets of the currently #
# selected object and prints them to the console #
###########################################################################
# check if something is selected
if selection:
#get the IfcProduct that is stored in the global variable 'selection'
obj = selection
for relDefinesByProperties in obj.IsDefinedBy:
print("[{0}]".format(relDefinesByProperties.RelatingPropertyDefinition.Name))
for prop in relDefinesByProperties.RelatingPropertyDefinition.HasProperties:
print ("{:<20} :{}".format(prop.Name,prop.NominalValue.wrappedValue))
print ("\\n")
""".lstrip()))
with open(conf_file, 'w') as configfile:
config.write(configfile)
self.config = Cfg()
self.config.read(conf_file)
def options(self, s):
return OrderedDict([(k, self.config_decode(self.config.get(s, k))) for k in self.config.options(s)])
class application(QtGui.QApplication): class application(QtGui.QApplication):
"""A pythonOCC, PyQt based IfcOpenShell application """A pythonOCC, PyQt based IfcOpenShell application
@@ -168,7 +236,7 @@ class application(QtGui.QApplication):
class property_table(QtGui.QWidget): class property_table(QtGui.QWidget):
instanceSelected = QtCore.pyqtSignal([object])
def __init__(self): def __init__(self):
QtGui.QWidget.__init__(self) QtGui.QWidget.__init__(self)
self.layout= QtGui.QVBoxLayout(self) self.layout= QtGui.QVBoxLayout(self)
@@ -184,39 +252,49 @@ class application(QtGui.QApplication):
#triggered by selection event in either component of parent #triggered by selection event in either component of parent
def select(self, product): def select(self, product):
# Clear the old contents if any # Clear the old contents if any
while self.scrollLayout.count(): while self.scrollLayout.count():
child = self.scrollLayout.takeAt(0) child = self.scrollLayout.takeAt(0)
if child is not None: if child is not None:
if child.widget() is not None: if child.widget() is not None:
child.widget().deleteLater() child.widget().deleteLater()
self.scroll = QtGui.QScrollArea() self.scroll = QtGui.QScrollArea()
self.scroll.setWidgetResizable(True) self.scroll.setWidgetResizable(True)
scrollContent = QtGui.QWidget(self.scroll)
# print ("properties for selection {}".format(self.prop_dict.get(str(product))))
prop_sets = self.prop_dict.get(str(product)) prop_sets = self.prop_dict.get(str(product))
if prop_sets is not None: if prop_sets is not None:
for k,v in prop_sets.items(): for k,v in prop_sets:
group_box = QtGui.QGroupBox() group_box = QtGui.QGroupBox()
group_box.setTitle(k) group_box.setTitle(k)
group_layout = QtGui.QVBoxLayout() group_layout = QtGui.QVBoxLayout()
group_box.setLayout(group_layout) group_box.setLayout(group_layout)
for name, value in v.items(): for name, value in v.items():
prop_name = str(name) prop_name = str(name)
value_str = value.wrappedValue
if isinstance(value_str,unicode): value_str = value
if hasattr(value_str, "wrappedValue"):
value_str = value_str.wrappedValue
if isinstance(value_str, unicode):
value_str = value_str.encode('utf-8') value_str = value_str.encode('utf-8')
else: else:
value_str = str(value_str) value_str = str(value_str)
# print (value_str, type(value_str))
type_str = value.is_a() if hasattr(value, "is_a"):
label = QtGui.QLabel(prop_name+" : "+value_str+" : "+type_str) type_str = " <i>(%s)</i>" % value.is_a()
else:
type_str = ""
label = QtGui.QLabel("<b>%s</b>: %s%s" % (prop_name, value_str, type_str))
group_layout.addWidget(label) group_layout.addWidget(label)
group_layout.addStretch() group_layout.addStretch()
self.scrollLayout.addWidget(group_box) self.scrollLayout.addWidget(group_box)
self.scrollLayout.addStretch() self.scrollLayout.addStretch()
else: else:
label = QtGui.QLabel("No IfcPropertySets asscociated with selected entity instance" ) label = QtGui.QLabel("No IfcPropertySets asscociated with selected entity instance" )
@@ -224,31 +302,46 @@ class application(QtGui.QApplication):
def load_file(self, f, **kwargs): def load_file(self, f, **kwargs):
products = list(f.by_type("IfcProduct")) for p in f.by_type("IfcProduct"):
for p in products: propsets = []
propset_dict={}
def process_pset(prop_def):
if prop_def is not None:
prop_set_name = prop_def.Name
props = {}
if prop_def.is_a("IfcElementQuantity"):
for q in prop_def.Quantities:
if q.is_a("IfcPhysicalSimpleQuantity"):
props[q.Name]=q[3]
elif prop_def.is_a("IfcPropertySet"):
for prop in prop_def.HasProperties:
if prop.is_a("IfcPropertySingleValue"):
props[prop.Name]=prop.NominalValue
else:
# Entity introduced in IFC4
# prop_def.is_a("IfcPreDefinedPropertySet"):
for prop in range(4, len(prop_def)):
props[prop_def.attribute_name(prop)]=prop_def[prop]
return prop_set_name, props
try: try:
for is_def_by in p.IsDefinedBy: for is_def_by in p.IsDefinedBy:
if not is_def_by.is_a("IfcRelDefinesByProperties"): continue if is_def_by.is_a("IfcRelDefinesByProperties"):
if is_def_by.RelatingPropertyDefinition is not None: propsets.append(process_pset(is_def_by.RelatingPropertyDefinition))
prop_def=is_def_by.RelatingPropertyDefinition elif is_def_by.is_a("IfcRelDefinesByType"):
prop_set_name = prop_def.Name type_psets = is_def_by.RelatingType.HasPropertySets
props = {} if type_psets is None: continue
if prop_def.is_a("IfcElementQuantity"): for propset in type_psets:
for q in prop_def.Quantities: propsets.append(process_pset(propset))
if q.is_a("IfcPhysicalSimpleQuantity"):
props[q.Name]=q[3]
else:
for prop in prop_def.HasProperties:
if prop.is_a("IfcPropertySingleValue"):
props[prop.Name]=prop.NominalValue
propset_dict[prop_set_name]=props
except Exception, e: except Exception, e:
import traceback
print("failed to load properties: {}".format(e)) print("failed to load properties: {}".format(e))
self.prop_dict[str(p)]=propset_dict traceback.print_exc()
print ("property set dictionary has {} entries".format(len(propset_dict)))
if len(propsets):
self.prop_dict[str(p)] = propsets
print ("property set dictionary has {} entries".format(len(self.prop_dict)))
class viewer(qtViewer3d): class viewer(qtViewer3d):
@@ -436,11 +529,16 @@ class application(QtGui.QApplication):
self.tabs.addTab(self.tree, 'Decomposition') self.tabs.addTab(self.tree, 'Decomposition')
self.tabs.addTab(self.tree2, 'Types') self.tabs.addTab(self.tree2, 'Types')
self.tabs.addTab(self.propview, "Properties") self.tabs.addTab(self.propview, "Properties")
splitter.addWidget(self.canvas) splitter2 = QtGui.QSplitter(QtCore.Qt.Vertical)
splitter2.addWidget(self.canvas)
self.editor = code_edit(self.canvas, configuration().options('snippets'))
splitter2.addWidget(self.editor)
splitter.addWidget(splitter2)
splitter.setSizes([200,600]) splitter.setSizes([200,600])
splitter2.setSizes([400,200])
self.window.setCentralWidget(splitter) self.window.setCentralWidget(splitter)
self.canvas.initialize() self.canvas.initialize()
self.components = [self.tree, self.tree2, self.canvas, self.propview] self.components = [self.tree, self.tree2, self.canvas, self.propview, self.editor]
self.files = {} self.files = {}
self.window.add_menu_item('File', '&Open', self.browse, shortcut='CTRL+O') self.window.add_menu_item('File', '&Open', self.browse, shortcut='CTRL+O')
@@ -450,7 +548,6 @@ class application(QtGui.QApplication):
self.tree.instanceSelected.connect(self.makeSelectionHandler(self.tree)) self.tree.instanceSelected.connect(self.makeSelectionHandler(self.tree))
self.tree2.instanceSelected.connect(self.makeSelectionHandler(self.tree2)) self.tree2.instanceSelected.connect(self.makeSelectionHandler(self.tree2))
self.canvas.instanceSelected.connect(self.makeSelectionHandler(self.canvas)) self.canvas.instanceSelected.connect(self.makeSelectionHandler(self.canvas))
self.propview.instanceSelected.connect(self.makeSelectionHandler(self.propview))
for t in [self.tree, self.tree2]: for t in [self.tree, self.tree2]:
t.instanceVisibilityChanged.connect(functools.partial(self.change_visibility, t)) t.instanceVisibilityChanged.connect(functools.partial(self.change_visibility, t))
t.instanceDisplayModeChanged.connect(functools.partial(self.change_displaymode, t)) t.instanceDisplayModeChanged.connect(functools.partial(self.change_displaymode, t))
@@ -480,7 +577,10 @@ class application(QtGui.QApplication):
def load(self, fn): def load(self, fn):
if fn in self.files: return if fn in self.files: return
f = open(str(fn)) f = open_ifc_file(str(fn))
self.files[fn] = f self.files[fn] = f
for c in self.components: for c in self.components:
c.load_file(f, setting=self.settings) c.load_file(f, setting=self.settings)
if __name__ == "__main__":
application().start()
@@ -1,81 +1,78 @@
from __future__ import print_function
import os import os
import sys import sys
import logging import logging
from pyqode.core.panels import CheckerPanel
logging.basicConfig(level=logging.CRITICAL)
from pyqode.qt import QtCore, QtGui, QtWidgets
print('Qt version:%s' % QtCore.__version__)
from code import InteractiveConsole from code import InteractiveConsole
from pyqode.core import api from PyQt4 import QtCore, QtGui
from pyqode.core import modes
from pyqode.core import panels try:
from pyqode.core.api import CodeEdit, ColorScheme from PyQt4 import QtWidgets
from pyqode.python.modes import PyAutoIndentMode, PythonSH except:
from pyqode.python.backend import server QtWidgets = QtGui
from pyqode.python import modes as pymodes, panels as pypanels, widgets
from pyqode.python.widgets import PyInteractiveConsole try:
from pyqode.core.panels import CheckerPanel
from pyqode.core import api
from pyqode.core import modes
from pyqode.core import panels
from pyqode.core.api import CodeEdit, ColorScheme
from pyqode.python.modes import PyAutoIndentMode, PythonSH
from pyqode.python.backend import server
from pyqode.python import modes as pymodes, panels as pypanels, widgets
from pyqode.python.widgets import PyInteractiveConsole
has_pyqode = True
except:
has_pyqode = False
CodeEdit = QtWidgets.QPlainTextEdit
class StdoutRedirector(object):
class StdoutRedirector(QtGui.QTextEdit):
'''A class for redirecting stdout to this Text widget.''' '''A class for redirecting stdout to this Text widget.'''
def __init__(self, widget): def __init__(self, widget):
self.widget=widget self.widget=widget
self.isError = False self.isError = False
def write(self,str): def write(self,str):
# print(str)
# self.widget.append(str)
self.widget.moveCursor(QtGui.QTextCursor.End) self.widget.moveCursor(QtGui.QTextCursor.End)
if self.isError: if self.isError:
self.widget.setTextColor(QtCore.Qt.red) self.widget.setTextColor(QtCore.Qt.red)
else: else:
self.widget.setTextColor(QtCore.Qt.black) self.widget.setTextColor(QtCore.Qt.white)
self.widget.insertPlainText(str) self.widget.insertPlainText(str)
self.widget.moveCursor(QtGui.QTextCursor.End) self.widget.moveCursor(QtGui.QTextCursor.End)
# scroll = self.widget.verticalScrollBar()
# scroll.setValue(scroll.maximum())
class code_edit(QtGui.QWidget): class code_edit(QtGui.QWidget):
class Console(InteractiveConsole):
def __init__(*args): InteractiveConsole.__init__(*args) class Console(InteractiveConsole):
def __init__(*args):
InteractiveConsole.__init__(*args)
def enter(self, source): def enter(self, source):
source = self.preprocess(source)
self.runcode(source) self.runcode(source)
@staticmethod
def preprocess(source): return source
def runCode(self):
c =self.Console({'model':self.files[0]})
c.enter("print (model.by_type('IfcDoor')")
def runCode(self): def runCode(self):
sys.stdout = StdoutRedirector(self.output) sys.stdout = StdoutRedirector(self.output)
err_redirect= StdoutRedirector(self.output) sys.stderr = StdoutRedirector(self.output)
err_redirect.isError=True sys.stderr.isError=True
sys.stderr = err_redirect
if not self.model: if not self.model:
print("please load a model first") print("please load a model first", file=sys.stderr)
if not self.c:
self.c = self.Console({'model':self.model, 'viewer':self.viewer})
else: else:
# self.console.start_process(sys.executable,args= [ os.path.join(os.getcwd(), 'interactive_process.py')],env={'model':self.model})
self.c.enter(str(self.editor.toPlainText())) self.c.enter(str(self.editor.toPlainText()))
sys.stdout = sys.__stdout__ sys.stdout = sys.__stdout__
sys.stderr = sys.__stderr__ sys.stderr = sys.__stderr__
def select(self,product): def select(self,product):
self.c = self.Console({'model':self.model, 'viewer':self.viewer, 'selection':product}) self.c = self.Console({'model':self.model, 'viewer':self.viewer, 'selection':product})
self.c.enter
def __init__(self,viewer,snippets=None): def __init__(self,viewer,snippets=None):
logging.basicConfig(level=logging.CRITICAL)
self.model=None self.model=None
self.viewer = viewer self.viewer = viewer
QtGui.QWidget.__init__(self) QtGui.QWidget.__init__(self)
@@ -83,80 +80,73 @@ class code_edit(QtGui.QWidget):
self.setLayout(self.layout) self.setLayout(self.layout)
self.c = None self.c = None
self.tools = QtGui.QHBoxLayout(self)
self.layout.addLayout(self.tools)
self.runbutton = QtGui.QPushButton("Run")
width = self.runbutton.fontMetrics().boundingRect("Run").width() + 20
self.runbutton.setMaximumWidth(width)
self.tools.addWidget(self.runbutton)
self.runbutton.clicked.connect(self.runCode)
editor = CodeEdit() editor = CodeEdit()
if has_pyqode:
# start the backend as soon as possible editor.backend.start(server.__file__)
# editor.backend.start('server.py') editor.panels.append(panels.FoldingPanel())
editor.backend.start(server.__file__) editor.panels.append(panels.LineNumberPanel())
#--- core panels editor.panels.append(panels.SearchAndReplacePanel(),
editor.panels.append(panels.FoldingPanel()) panels.SearchAndReplacePanel.Position.BOTTOM)
editor.panels.append(panels.LineNumberPanel()) editor.panels.append(panels.EncodingPanel(), api.Panel.Position.TOP)
# editor.panels.append(panels.CheckerPanel()) editor.add_separator()
editor.panels.append(panels.SearchAndReplacePanel(), editor.panels.append(pypanels.QuickDocPanel(), api.Panel.Position.BOTTOM)
panels.SearchAndReplacePanel.Position.BOTTOM) sh = editor.modes.append(PythonSH(editor.document()))
editor.panels.append(panels.EncodingPanel(), api.Panel.Position.TOP) editor.modes.append(modes.CaretLineHighlighterMode())
# add a context menu separator between editor's editor.modes.append(modes.CodeCompletionMode())
# builtin action and the python specific actions editor.modes.append(modes.ExtendedSelectionMode())
editor.add_separator() editor.modes.append(modes.FileWatcherMode())
editor.modes.append(modes.OccurrencesHighlighterMode())
#--- python specific panels editor.modes.append(modes.RightMarginMode())
editor.panels.append(pypanels.QuickDocPanel(), api.Panel.Position.BOTTOM) editor.modes.append(modes.SmartBackSpaceMode())
sh = editor.modes.append(PythonSH(editor.document())) editor.modes.append(modes.SymbolMatcherMode())
# sh.color_scheme = ColorScheme('monokai') editor.modes.append(modes.ZoomMode())
#--- core modes editor.modes.append(pymodes.CommentsMode())
editor.modes.append(modes.CaretLineHighlighterMode()) editor.modes.append(pymodes.CalltipsMode())
editor.modes.append(modes.CodeCompletionMode()) auto = pymodes.PyAutoCompleteMode()
editor.modes.append(modes.ExtendedSelectionMode()) auto.logger.setLevel(logging.CRITICAL)
editor.modes.append(modes.FileWatcherMode()) editor.modes.append(auto)
editor.modes.append(modes.OccurrencesHighlighterMode()) editor.modes.append(pymodes.PyAutoIndentMode())
editor.modes.append(modes.RightMarginMode()) editor.modes.append(pymodes.PyIndenterMode())
editor.modes.append(modes.SmartBackSpaceMode()) editor.show()
editor.modes.append(modes.SymbolMatcherMode()) else:
editor.modes.append(modes.ZoomMode()) editor.setStyleSheet('font-size: 10pt; font-family: Consolas, Courier;')
#--- python specific modes
editor.modes.append(pymodes.CommentsMode())
editor.modes.append(pymodes.CalltipsMode())
auto = pymodes.PyAutoCompleteMode()
auto.logger.setLevel(logging.CRITICAL)
editor.modes.append(auto)
editor.modes.append(pymodes.PyAutoIndentMode())
editor.modes.append(pymodes.PyIndenterMode())
editor.show()
self.editor = editor self.editor = editor
self.snippets = snippets self.snippets = snippets
if not self.snippets: if self.snippets:
self.editor.setPlainText("""print('hello from console')
for w in model.by_type('IfcWall'):
print ("wall with GlobalId " + str(w.GlobalId))
""","","")
else:
self.editor.setPlainText(self.snippets.values()[0],"","")
self.list = QtWidgets.QComboBox(self) self.list = QtWidgets.QComboBox(self)
self.replace_snippet(0)
for snip_name in self.snippets.keys(): for snip_name in self.snippets.keys():
self.list.addItem(snip_name) self.list.addItem(snip_name)
self.layout.addWidget(self.list) self.tools.addWidget(self.list)
QtCore.QObject.connect(self.list, QtCore.SIGNAL("currentIndexChanged(int)"), self.replace_snippet) QtCore.QObject.connect(self.list, QtCore.SIGNAL("currentIndexChanged(int)"), self.replace_snippet)
# self.textedit = QtGui.QTextEdit()
# self.scrollLayout.addWidget(self.textedit)
self.layout.addWidget(self.editor) self.layout.addWidget(self.editor)
self.output = QtGui.QTextEdit() self.output = QtGui.QTextEdit()
self.output.setReadOnly(False) self.output.setReadOnly(True)
self.output.setStyleSheet('font-size: 10pt; font-family: Consolas,Courier;') self.output.setStyleSheet('font-size: 10pt; font-family: Consolas, Courier; background-color: #444;')
self.layout.addWidget(self.output) self.layout.addWidget(self.output)
def replace_snippet (self,number): def replace_snippet(self, number=None):
self.editor.setPlainText(self.snippets[self.list.currentText()],"","") snip = list(self.snippets.values())[number]
if has_pyqode:
self.editor.setPlainText(snip, "", "")
else:
self.editor.setPlainText(snip)
def load_file(self, f, **kwargs): def load_file(self, f, **kwargs):
output = [] output = []
sys.stdout = StdoutRedirector(self.output) sys.stdout = StdoutRedirector(self.output)
self.model = f self.model = f
self.c = self.Console({'model':self.model}) self.c = self.Console({'model':self.model, 'selection':None, 'viewer':self.viewer})
# c.enter("print (model.by_type('IfcWall'))")
sys.stdout = sys.__stdout__ sys.stdout = sys.__stdout__
@@ -1,25 +0,0 @@
quickload_model = "D:\Project1.ifc"
["snippets"]
'print all wall ids' = """# a simple script that iterates over all walls in the current
# model and prints their Globally unique IDs (GUIDS) to the console
# window
for wall in model.by_type("IfcWall"):
print ("wall with global id: "+str(wall.GlobalId))
"""
'print all properties of current selection' = """# a simple script that iterates over all IfcPropertySets of the currently
# selected object and prints them to the console
#####################################################################
# check if something is selected
if selection:
#get the IfcProduct that is stored in the global variable 'selection'
obj = selection
for relDefinesByProperties in obj.IsDefinedBy:
print("[{0}]".format(relDefinesByProperties.RelatingPropertyDefinition.Name))
for prop in relDefinesByProperties.RelatingPropertyDefinition.HasProperties:
print ("{:<20} :{}".format(prop.Name,prop.NominalValue.wrappedValue))
print ("\n")
"""
@@ -1,51 +0,0 @@
from pyqode.qt import QtCore, QtGui, QtWidgets
from configobj import ConfigObj
from ..geom.app import application
try:
from ..geom.code_editor_pane import code_edit
except ImportError:
print ("code editor or one of its dependencies (pyQode) could not be found. Please make sure to install pyQode")
class my_app(application):
class toolbar(QtGui.QToolBar):
def __init__(self):
QtGui.QToolBar.__init__(self)
self.widget.append()
def __init__(self):
application.__init__(self)
# self.window = my_app.window()
self.window.setWindowTitle("Interactive IfcOpenShell Viewer with REPL-like funcionality")
tb = self.window.addToolBar("File")
self.window.resize(1024,720)
# loadButton = QtGui.QAction(QtGui.QIcon("new.bmp"),"new",self)
loadButton = QtGui.QAction("Quickload",self)
loadButton.triggered.connect(self.loadExampleFile)
loadButton.setShortcut(QtGui.QKeySequence("CTRL+L"))
tb.addAction(loadButton)
# zoomAllButton = QtGui.QAction(QtGui.QIcon("new.bmp"),"new",self)
zoomAllButton = QtGui.QAction("zoom All",self)
zoomAllButton.triggered.connect(self.zoomAll)
tb.addAction(zoomAllButton)
self.config = ConfigObj("snippets.config")
print (self.config["snippets"])
snippets = self.config["snippets"]
self.codeedit= code_edit(self.canvas, snippets )
self.components.append(self.codeedit)
self.window.centralWidget().addWidget(self.codeedit)
self.runButton = QtGui.QAction("execute code (Strg+P)",self)
self.runButton.setShortcut(QtGui.QKeySequence("CTRL+P"))
self.runButton.triggered.connect(self.codeedit.runCode)
tb.addAction(self.runButton)
def loadExampleFile(self):
self.load(self.config["quickload_model"])
def zoomAll(self):
self.canvas._display.FitAll()
my_app().start()