mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-18 06:21:40 +00:00
Interactive scripting pane added to pyQt viewer geom.app
This commit is contained in:
committed by
Thomas Krijnen
parent
3ba2f781d8
commit
90e4f21f29
@@ -480,7 +480,7 @@ 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(fn)
|
f = open(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)
|
||||||
|
|||||||
@@ -0,0 +1,162 @@
|
|||||||
|
import os
|
||||||
|
import sys
|
||||||
|
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 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
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class StdoutRedirector(QtGui.QTextEdit):
|
||||||
|
'''A class for redirecting stdout to this Text widget.'''
|
||||||
|
def __init__(self, widget):
|
||||||
|
self.widget=widget
|
||||||
|
self.isError = False
|
||||||
|
def write(self,str):
|
||||||
|
# print(str)
|
||||||
|
# self.widget.append(str)
|
||||||
|
self.widget.moveCursor(QtGui.QTextCursor.End)
|
||||||
|
if self.isError:
|
||||||
|
self.widget.setTextColor(QtCore.Qt.red)
|
||||||
|
else:
|
||||||
|
self.widget.setTextColor(QtCore.Qt.black)
|
||||||
|
self.widget.insertPlainText(str)
|
||||||
|
self.widget.moveCursor(QtGui.QTextCursor.End)
|
||||||
|
# scroll = self.widget.verticalScrollBar()
|
||||||
|
# scroll.setValue(scroll.maximum())
|
||||||
|
|
||||||
|
|
||||||
|
class code_edit(QtGui.QWidget):
|
||||||
|
class Console(InteractiveConsole):
|
||||||
|
|
||||||
|
def __init__(*args): InteractiveConsole.__init__(*args)
|
||||||
|
|
||||||
|
def enter(self, source):
|
||||||
|
source = self.preprocess(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):
|
||||||
|
|
||||||
|
sys.stdout = StdoutRedirector(self.output)
|
||||||
|
err_redirect= StdoutRedirector(self.output)
|
||||||
|
err_redirect.isError=True
|
||||||
|
sys.stderr = err_redirect
|
||||||
|
|
||||||
|
if not self.model:
|
||||||
|
print("please load a model first")
|
||||||
|
if not self.c:
|
||||||
|
self.c = self.Console({'model':self.model, 'viewer':self.viewer})
|
||||||
|
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()))
|
||||||
|
sys.stdout = sys.__stdout__
|
||||||
|
sys.stderr = sys.__stderr__
|
||||||
|
|
||||||
|
def select(self,product):
|
||||||
|
self.c = self.Console({'model':self.model, 'viewer':self.viewer, 'selection':product})
|
||||||
|
self.c.enter
|
||||||
|
|
||||||
|
def __init__(self,viewer,snippets=None):
|
||||||
|
|
||||||
|
logging.basicConfig(level=logging.CRITICAL)
|
||||||
|
self.model=None
|
||||||
|
self.viewer = viewer
|
||||||
|
QtGui.QWidget.__init__(self)
|
||||||
|
self.layout= QtGui.QVBoxLayout(self)
|
||||||
|
self.setLayout(self.layout)
|
||||||
|
self.c = None
|
||||||
|
|
||||||
|
|
||||||
|
editor = CodeEdit()
|
||||||
|
|
||||||
|
# start the backend as soon as possible
|
||||||
|
# editor.backend.start('server.py')
|
||||||
|
editor.backend.start(server.__file__)
|
||||||
|
#--- core panels
|
||||||
|
editor.panels.append(panels.FoldingPanel())
|
||||||
|
editor.panels.append(panels.LineNumberPanel())
|
||||||
|
# editor.panels.append(panels.CheckerPanel())
|
||||||
|
editor.panels.append(panels.SearchAndReplacePanel(),
|
||||||
|
panels.SearchAndReplacePanel.Position.BOTTOM)
|
||||||
|
editor.panels.append(panels.EncodingPanel(), api.Panel.Position.TOP)
|
||||||
|
# add a context menu separator between editor's
|
||||||
|
# builtin action and the python specific actions
|
||||||
|
editor.add_separator()
|
||||||
|
|
||||||
|
#--- python specific panels
|
||||||
|
editor.panels.append(pypanels.QuickDocPanel(), api.Panel.Position.BOTTOM)
|
||||||
|
sh = editor.modes.append(PythonSH(editor.document()))
|
||||||
|
# sh.color_scheme = ColorScheme('monokai')
|
||||||
|
#--- core modes
|
||||||
|
editor.modes.append(modes.CaretLineHighlighterMode())
|
||||||
|
editor.modes.append(modes.CodeCompletionMode())
|
||||||
|
editor.modes.append(modes.ExtendedSelectionMode())
|
||||||
|
editor.modes.append(modes.FileWatcherMode())
|
||||||
|
editor.modes.append(modes.OccurrencesHighlighterMode())
|
||||||
|
editor.modes.append(modes.RightMarginMode())
|
||||||
|
editor.modes.append(modes.SmartBackSpaceMode())
|
||||||
|
editor.modes.append(modes.SymbolMatcherMode())
|
||||||
|
editor.modes.append(modes.ZoomMode())
|
||||||
|
|
||||||
|
#--- 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.snippets = snippets
|
||||||
|
if not 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)
|
||||||
|
for snip_name in self.snippets.keys():
|
||||||
|
self.list.addItem(snip_name)
|
||||||
|
self.layout.addWidget(self.list)
|
||||||
|
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.output = QtGui.QTextEdit()
|
||||||
|
self.output.setReadOnly(False)
|
||||||
|
self.output.setStyleSheet('font-size: 10pt; font-family: Consolas,Courier;')
|
||||||
|
self.layout.addWidget(self.output)
|
||||||
|
|
||||||
|
def replace_snippet (self,number):
|
||||||
|
self.editor.setPlainText(self.snippets[self.list.currentText()],"","")
|
||||||
|
|
||||||
|
def load_file(self, f, **kwargs):
|
||||||
|
output = []
|
||||||
|
sys.stdout = StdoutRedirector(self.output)
|
||||||
|
self.model = f
|
||||||
|
self.c = self.Console({'model':self.model})
|
||||||
|
# c.enter("print (model.by_type('IfcWall'))")
|
||||||
|
sys.stdout = sys.__stdout__
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
|
||||||
|
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")
|
||||||
|
"""
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
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()
|
||||||
Reference in New Issue
Block a user