BIM: Fixed project creation and refactored status bar toggle system
This commit is contained in:
committed by
Yorik van Havre
parent
f7ec184f32
commit
d48a47f120
@@ -22,8 +22,8 @@
|
||||
|
||||
# add import/export types
|
||||
|
||||
FreeCAD.addImportType("Industry Foundation Classes (*.ifc)","importers.exportIFC")
|
||||
# FreeCAD.addExportType("Industry Foundation Classes (*.ifc)","importIFC")
|
||||
FreeCAD.addExportType("Industry Foundation Classes (*.ifc)","importers.exportIFC")
|
||||
# FreeCAD.addImportType("Industry Foundation Classes (*.ifc)","importIFC")
|
||||
FreeCAD.addImportType("Industry Foundation Classes (*.ifc)", "nativeifc.ifc_import")
|
||||
FreeCAD.addExportType("Industry Foundation Classes - IFCJSON (*.ifcJSON)","importers.exportIFC")
|
||||
FreeCAD.addImportType("Wavefront OBJ - Arch module (*.obj *.OBJ)","importers.importOBJ")
|
||||
|
||||
@@ -41,6 +41,9 @@ class BIM_Project:
|
||||
"Create an empty NativeIFC project"),
|
||||
}
|
||||
|
||||
def IsActive(self):
|
||||
return not hasattr(FreeCAD.ActiveDocument, "IfcFilePath")
|
||||
|
||||
def Activated(self):
|
||||
from nativeifc import ifc_tools
|
||||
project = ifc_tools.create_document(FreeCAD.ActiveDocument)
|
||||
|
||||
@@ -190,9 +190,8 @@ class IFC_Save:
|
||||
|
||||
def IsActive(self):
|
||||
doc = FreeCAD.ActiveDocument
|
||||
if getattr(doc, "IfcFilePath", None):
|
||||
if getattr(getattr(doc, "Proxy", None), "ifcfile", None):
|
||||
return True
|
||||
if hasattr(doc, "IfcFilePath"):
|
||||
return True
|
||||
return False
|
||||
|
||||
def Activated(self):
|
||||
@@ -223,9 +222,8 @@ class IFC_SaveAs:
|
||||
|
||||
def IsActive(self):
|
||||
doc = FreeCAD.ActiveDocument
|
||||
if getattr(doc, "IfcFilePath", None):
|
||||
if getattr(getattr(doc, "Proxy", None), "ifcfile", None):
|
||||
return True
|
||||
if hasattr(doc, "IfcFilePath"):
|
||||
return True
|
||||
return False
|
||||
|
||||
def Activated(self):
|
||||
|
||||
@@ -36,7 +36,7 @@ if FreeCAD.GuiUp:
|
||||
import Arch_rc
|
||||
|
||||
|
||||
params = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/NativeIFC")
|
||||
PARAMS = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/NativeIFC")
|
||||
|
||||
|
||||
def open(filename):
|
||||
@@ -78,7 +78,7 @@ def insert(
|
||||
except:
|
||||
document = FreeCAD.newDocument()
|
||||
if singledoc is None:
|
||||
singledoc = params.GetBool("SingleDoc", False)
|
||||
singledoc = PARAMS.GetBool("SingleDoc", False)
|
||||
if singledoc:
|
||||
prj_obj = ifc_tools.convert_document(document, filename, shapemode, strategy)
|
||||
QtCore.QTimer.singleShot(100, toggle_lock_on)
|
||||
@@ -87,17 +87,17 @@ def insert(
|
||||
document, filename, shapemode, strategy
|
||||
)
|
||||
QtCore.QTimer.singleShot(100, toggle_lock_off)
|
||||
if params.GetBool("LoadOrphans", True):
|
||||
if PARAMS.GetBool("LoadOrphans", True):
|
||||
ifc_tools.load_orphans(prj_obj)
|
||||
if not silent and params.GetBool("LoadMaterials", False):
|
||||
if not silent and PARAMS.GetBool("LoadMaterials", False):
|
||||
ifc_materials.load_materials(prj_obj)
|
||||
if params.GetBool("LoadLayers", False):
|
||||
if PARAMS.GetBool("LoadLayers", False):
|
||||
ifc_layers.load_layers(prj_obj)
|
||||
if params.GetBool("LoadPsets", False):
|
||||
if PARAMS.GetBool("LoadPsets", False):
|
||||
ifc_psets.load_psets(prj_obj)
|
||||
document.recompute()
|
||||
# print a reference to the IFC file on the console
|
||||
if FreeCAD.GuiUp and params.GetBool("IfcFileToConsole", False):
|
||||
if FreeCAD.GuiUp and PARAMS.GetBool("IfcFileToConsole", False):
|
||||
if isinstance(prj_obj, FreeCAD.DocumentObject):
|
||||
pstr = "FreeCAD.getDocument('{}').{}.Proxy.ifcfile"
|
||||
pstr = pstr.format(prj_obj.Document.Name, prj_obj.Name)
|
||||
@@ -128,19 +128,19 @@ def get_options(strategy=None, shapemode=None, switchwb=None, silent=False):
|
||||
2 = all children
|
||||
"""
|
||||
|
||||
psets = params.GetBool("LoadPsets", False)
|
||||
materials = params.GetBool("LoadMaterials", False)
|
||||
layers = params.GetBool("LoadLayers", False)
|
||||
singledoc = params.GetBool("SingleDoc", False)
|
||||
psets = PARAMS.GetBool("LoadPsets", False)
|
||||
materials = PARAMS.GetBool("LoadMaterials", False)
|
||||
layers = PARAMS.GetBool("LoadLayers", False)
|
||||
singledoc = PARAMS.GetBool("SingleDoc", False)
|
||||
if strategy is None:
|
||||
strategy = params.GetInt("ImportStrategy", 0)
|
||||
strategy = PARAMS.GetInt("ImportStrategy", 0)
|
||||
if shapemode is None:
|
||||
shapemode = params.GetInt("ShapeMode", 0)
|
||||
shapemode = PARAMS.GetInt("ShapeMode", 0)
|
||||
if switchwb is None:
|
||||
switchwb = params.GetBool("SwitchWB", True)
|
||||
switchwb = PARAMS.GetBool("SwitchWB", True)
|
||||
if silent:
|
||||
return strategy, shapemode, switchwb
|
||||
ask = params.GetBool("AskAgain", False)
|
||||
ask = PARAMS.GetBool("AskAgain", False)
|
||||
if ask and FreeCAD.GuiUp:
|
||||
import FreeCADGui
|
||||
from PySide import QtGui
|
||||
@@ -166,22 +166,22 @@ def get_options(strategy=None, shapemode=None, switchwb=None, silent=False):
|
||||
materials = dlg.checkLoadMaterials.isChecked()
|
||||
layers = dlg.checkLoadLayers.isChecked()
|
||||
singledoc = dlg.comboSingleDoc.currentIndex()
|
||||
params.SetInt("ImportStrategy", strategy)
|
||||
params.SetInt("ShapeMode", shapemode)
|
||||
params.SetBool("SwitchWB", switchwb)
|
||||
params.SetBool("AskAgain", ask)
|
||||
params.SetBool("LoadPsets", psets)
|
||||
params.SetBool("LoadMaterials", materials)
|
||||
params.SetBool("LoadLayers", layers)
|
||||
params.SetBool("SingleDoc", bool(1 - singledoc))
|
||||
PARAMS.SetInt("ImportStrategy", strategy)
|
||||
PARAMS.SetInt("ShapeMode", shapemode)
|
||||
PARAMS.SetBool("SwitchWB", switchwb)
|
||||
PARAMS.SetBool("AskAgain", ask)
|
||||
PARAMS.SetBool("LoadPsets", psets)
|
||||
PARAMS.SetBool("LoadMaterials", materials)
|
||||
PARAMS.SetBool("LoadLayers", layers)
|
||||
PARAMS.SetBool("SingleDoc", bool(1 - singledoc))
|
||||
return strategy, shapemode, switchwb
|
||||
|
||||
|
||||
def get_project_type(silent=False):
|
||||
"""Gets the type of project to make"""
|
||||
|
||||
ask = params.GetBool("ProjectAskAgain", True)
|
||||
ptype = params.GetBool("ProjectFull", False)
|
||||
ask = PARAMS.GetBool("ProjectAskAgain", True)
|
||||
ptype = PARAMS.GetBool("ProjectFull", False)
|
||||
if silent:
|
||||
return ptype
|
||||
if ask and FreeCAD.GuiUp:
|
||||
@@ -192,8 +192,8 @@ def get_project_type(silent=False):
|
||||
result = dlg.exec_()
|
||||
ask = not (dlg.checkBox.isChecked())
|
||||
ptype = bool(result)
|
||||
params.SetBool("ProjectAskAgain", ask)
|
||||
params.SetBool("ProjectFull", ptype)
|
||||
PARAMS.SetBool("ProjectAskAgain", ask)
|
||||
PARAMS.SetBool("ProjectFull", ptype)
|
||||
return ptype
|
||||
|
||||
|
||||
@@ -201,11 +201,11 @@ def get_project_type(silent=False):
|
||||
|
||||
def toggle_lock_on():
|
||||
|
||||
ifc_status.toggle_lock(True)
|
||||
ifc_status.on_toggle_lock(True, noconvert=True, setchecked=True)
|
||||
|
||||
def toggle_lock_off():
|
||||
|
||||
ifc_status.toggle_lock(False)
|
||||
ifc_status.on_toggle_lock(False, noconvert=True, setchecked=True)
|
||||
|
||||
def unset_modified():
|
||||
|
||||
|
||||
@@ -32,14 +32,16 @@ params = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/NativeIFC")
|
||||
def add_observer():
|
||||
"""Adds an observer to the running FreeCAD instance"""
|
||||
|
||||
observer = ifc_observer()
|
||||
FreeCAD.addDocumentObserver(observer)
|
||||
FreeCAD.BIMobserver = ifc_observer()
|
||||
FreeCAD.addDocumentObserver(FreeCAD.BIMobserver)
|
||||
|
||||
|
||||
def remove_observer():
|
||||
"""Removes this observer if present"""
|
||||
|
||||
pass # TODO implement this!!
|
||||
if hasattr(FreeCAD, "BIMobserver"):
|
||||
FreeCAD.removeDocumentObserver(FreeCAD.BIMobserver)
|
||||
del FreeCAD.BIMobserver
|
||||
|
||||
|
||||
class ifc_observer:
|
||||
@@ -99,9 +101,6 @@ class ifc_observer:
|
||||
]
|
||||
if len(child) == 1:
|
||||
child[0].StepId = new_id
|
||||
ifc_status.toggle_lock(True)
|
||||
else:
|
||||
ifc_status.toggle_lock(False)
|
||||
|
||||
def slotCreatedObject(self, obj):
|
||||
"""If this is an IFC document, turn the object into IFC"""
|
||||
@@ -119,16 +118,9 @@ class ifc_observer:
|
||||
def slotActivateDocument(self, doc):
|
||||
"""Check if we need to lock"""
|
||||
|
||||
from PySide2 import QtCore # lazy loading
|
||||
from nativeifc import ifc_status
|
||||
ifc_status.on_activate()
|
||||
|
||||
if hasattr(doc, "IfcFilePath"):
|
||||
ifc_status.toggle_lock(True)
|
||||
else:
|
||||
ifc_status.toggle_lock(False)
|
||||
if not hasattr(doc, "Proxy"):
|
||||
# this is a new file, wait a bit to make sure all components are populated
|
||||
QtCore.QTimer.singleShot(1000, self.propose_conversion)
|
||||
|
||||
# implementation methods
|
||||
|
||||
@@ -207,67 +199,3 @@ class ifc_observer:
|
||||
newobj = ifc_tools.aggregate(obj, doc)
|
||||
ifc_geometry.add_geom_properties(newobj)
|
||||
doc.recompute()
|
||||
|
||||
def propose_conversion(self):
|
||||
"""Propose a conversion of the current document"""
|
||||
|
||||
from nativeifc import ifc_status # lazy loading
|
||||
|
||||
doc = FreeCAD.ActiveDocument
|
||||
if not getattr(FreeCAD, "IsOpeningIFC", False):
|
||||
if not hasattr(doc, "Proxy"):
|
||||
if not getattr(doc, "Objects", True):
|
||||
if not doc.FileName:
|
||||
if not hasattr(doc, "IfcFilePath"):
|
||||
# this is really a new, empty document
|
||||
import FreeCADGui
|
||||
import Arch_rc
|
||||
from PySide import QtCore, QtGui # lazy loading
|
||||
|
||||
if FreeCADGui.activeWorkbench().name() != "BIMWorkbench":
|
||||
return
|
||||
if not params.GetBool("SingleDocAskAgain", True):
|
||||
if params.GetBool("SingleDoc", True):
|
||||
self.full = params.GetBool("ProjectFull", False)
|
||||
QtCore.QTimer.singleShot(
|
||||
1000, self.convert_document
|
||||
)
|
||||
return
|
||||
else:
|
||||
ifc_status.toggle_lock(False)
|
||||
return
|
||||
d = os.path.dirname(__file__)
|
||||
dlg = FreeCADGui.PySideUic.loadUi(
|
||||
os.path.join(d, "ui", "dialogConvertDocument.ui")
|
||||
)
|
||||
dlg.checkStructure.setChecked(
|
||||
params.GetBool("ProjectFull", False)
|
||||
)
|
||||
result = dlg.exec_()
|
||||
self.full = dlg.checkStructure.isChecked()
|
||||
params.SetBool(
|
||||
"SingleDocAskAgain", not dlg.checkAskAgain.isChecked()
|
||||
)
|
||||
if result:
|
||||
params.SetBool("SingleDoc", True)
|
||||
params.SetBool("ProjectFull", self.full)
|
||||
QtCore.QTimer.singleShot(1000, self.convert_document)
|
||||
else:
|
||||
params.SetBool("SingleDoc", False)
|
||||
|
||||
def convert_document(self):
|
||||
"""Converts the active document"""
|
||||
|
||||
from nativeifc import ifc_tools # lazy loading
|
||||
from nativeifc import ifc_status
|
||||
|
||||
doc = FreeCAD.ActiveDocument
|
||||
ifc_tools.convert_document(doc, strategy=2, silent=True)
|
||||
if self.full:
|
||||
import Arch
|
||||
|
||||
site = ifc_tools.aggregate(Arch.makeSite(), doc)
|
||||
building = ifc_tools.aggregate(Arch.makeBuilding(), site)
|
||||
storey = ifc_tools.aggregate(Arch.makeFloor(), building)
|
||||
ifc_status.toggle_lock(True)
|
||||
doc.recompute()
|
||||
|
||||
@@ -46,20 +46,63 @@ def set_status_widget(statuswidget):
|
||||
lock_button.setIcon(icon)
|
||||
lock_button.setCheckable(True)
|
||||
doc = FreeCAD.ActiveDocument
|
||||
statuswidget.addAction(lock_button)
|
||||
statuswidget.lock_button = lock_button
|
||||
if doc and "IfcFilePath" in doc.PropertiesList:
|
||||
checked = True
|
||||
else:
|
||||
checked = params.GetBool("SingleDoc", False)
|
||||
toggle_lock(checked)
|
||||
set_button(lock_button, checked)
|
||||
lock_button.triggered.connect(do_lock)
|
||||
lock_button.triggered.connect(toggle_lock)
|
||||
statuswidget.addAction(lock_button)
|
||||
statuswidget.lock_button = lock_button
|
||||
checked = False
|
||||
# set the button first, without converting the document
|
||||
lock_button.setChecked(checked)
|
||||
on_toggle_lock(checked, noconvert=True)
|
||||
lock_button.triggered.connect(on_toggle_lock)
|
||||
|
||||
|
||||
def toggle_lock(checked=False):
|
||||
"""Sets the lock button on/off"""
|
||||
def on_toggle_lock(checked=None, noconvert=False, setchecked=False):
|
||||
"""When the toolbar button is pressed"""
|
||||
|
||||
if checked is None:
|
||||
checked = get_lock_status()
|
||||
set_menu(checked)
|
||||
set_button(checked, setchecked)
|
||||
if not noconvert:
|
||||
if checked:
|
||||
lock_document()
|
||||
else:
|
||||
unlock_document()
|
||||
|
||||
|
||||
def on_open():
|
||||
"""What happens when opening an existing document"""
|
||||
|
||||
pass # TODO implement
|
||||
|
||||
|
||||
def on_activate():
|
||||
"""What happens when activating a document"""
|
||||
|
||||
from PySide import QtGui # lazy import
|
||||
|
||||
doc = FreeCAD.ActiveDocument
|
||||
if doc and "IfcFilePath" in doc.PropertiesList:
|
||||
checked = True
|
||||
else:
|
||||
checked = False
|
||||
mw = FreeCADGui.getMainWindow()
|
||||
statuswidget = mw.findChild(QtGui.QToolBar, "BIMStatusWidget")
|
||||
if hasattr(statuswidget, "lock_button"):
|
||||
statuswidget.lock_button.setChecked(checked)
|
||||
on_toggle_lock(checked, noconvert=True)
|
||||
|
||||
|
||||
def on_new():
|
||||
"""What happens when creating a new document"""
|
||||
|
||||
pass # TODO implement
|
||||
|
||||
|
||||
def set_menu(locked=False):
|
||||
"""Sets the File menu items"""
|
||||
|
||||
from PySide import QtCore, QtGui # lazy loading
|
||||
|
||||
@@ -67,7 +110,7 @@ def toggle_lock(checked=False):
|
||||
mw = FreeCADGui.getMainWindow()
|
||||
wb = FreeCADGui.activeWorkbench()
|
||||
save_action = mw.findChild(QtGui.QAction, "Std_Save")
|
||||
if checked and "IFC_Save" in FreeCADGui.listCommands():
|
||||
if locked and "IFC_Save" in FreeCADGui.listCommands():
|
||||
if not hasattr(FreeCADGui,"IFC_WBManipulator"):
|
||||
FreeCADGui.IFC_WBManipulator = IFC_WBManipulator()
|
||||
# we need to void the shortcut otherwise it keeps active
|
||||
@@ -84,40 +127,33 @@ def toggle_lock(checked=False):
|
||||
FreeCADGui.removeWorkbenchManipulator(FreeCADGui.IFC_WBManipulator)
|
||||
del FreeCADGui.IFC_WBManipulator
|
||||
wb.reloadActive()
|
||||
# set the lock button
|
||||
statuswidget = mw.findChild(QtGui.QToolBar, "BIMStatusWidget")
|
||||
if hasattr(statuswidget, "lock_button"):
|
||||
set_button(statuswidget.lock_button, checked)
|
||||
|
||||
|
||||
def set_button(lock_button, checked):
|
||||
def set_button(checked=False, setchecked=False):
|
||||
"""Sets the lock button"""
|
||||
|
||||
from PySide import QtGui # lazy loading
|
||||
|
||||
if checked:
|
||||
lock_button.setChecked(True)
|
||||
lock_button.setToolTip(text_on)
|
||||
icon = QtGui.QIcon(":/icons/IFC.svg")
|
||||
lock_button.setIcon(icon)
|
||||
else:
|
||||
lock_button.setChecked(False)
|
||||
lock_button.setToolTip(text_off)
|
||||
image = QtGui.QImage(":/icons/IFC.svg")
|
||||
grayscale = image.convertToFormat(QtGui.QImage.Format_Grayscale8)
|
||||
grayscale = grayscale.convertToFormat(image.format())
|
||||
grayscale.setAlphaChannel(image)
|
||||
icon = QtGui.QIcon(QtGui.QPixmap.fromImage(grayscale))
|
||||
lock_button.setIcon(icon)
|
||||
|
||||
|
||||
def do_lock(checked):
|
||||
"""Locks or unlocks the document"""
|
||||
|
||||
if checked:
|
||||
lock_document()
|
||||
else:
|
||||
unlock_document()
|
||||
mw = FreeCADGui.getMainWindow()
|
||||
statuswidget = mw.findChild(QtGui.QToolBar, "BIMStatusWidget")
|
||||
if hasattr(statuswidget, "lock_button"):
|
||||
lock_button = statuswidget.lock_button
|
||||
if checked:
|
||||
lock_button.setToolTip(text_on)
|
||||
icon = QtGui.QIcon(":/icons/IFC.svg")
|
||||
lock_button.setIcon(icon)
|
||||
if setchecked:
|
||||
lock_button.setChecked(True)
|
||||
else:
|
||||
lock_button.setToolTip(text_off)
|
||||
image = QtGui.QImage(":/icons/IFC.svg")
|
||||
grayscale = image.convertToFormat(QtGui.QImage.Format_Grayscale8)
|
||||
grayscale = grayscale.convertToFormat(image.format())
|
||||
grayscale.setAlphaChannel(image)
|
||||
icon = QtGui.QIcon(QtGui.QPixmap.fromImage(grayscale))
|
||||
lock_button.setIcon(icon)
|
||||
if setchecked:
|
||||
lock_button.setChecked(False)
|
||||
|
||||
|
||||
def unlock_document():
|
||||
@@ -203,7 +239,7 @@ def lock_document():
|
||||
FreeCAD.Console.PrintError(
|
||||
"Unable to lock this document because it contains several IFC documents\n"
|
||||
)
|
||||
QtCore.QTimer.singleShot(100, toggle_lock)
|
||||
QtCore.QTimer.singleShot(100, on_toggle_lock)
|
||||
elif doc.Objects:
|
||||
# 3 there is no project but objects
|
||||
doc.openTransaction("Lock document")
|
||||
@@ -220,7 +256,10 @@ def lock_document():
|
||||
doc.recompute()
|
||||
else:
|
||||
# 4 this is an empty document
|
||||
ifc_tools.convert_document(doc, silent=True)
|
||||
doc.openTransaction("Create IFC document")
|
||||
ifc_tools.convert_document(doc)
|
||||
doc.commitTransaction()
|
||||
doc.recompute()
|
||||
|
||||
|
||||
def find_toplevel(objs):
|
||||
@@ -248,6 +287,20 @@ def find_toplevel(objs):
|
||||
return nobjs
|
||||
|
||||
|
||||
def get_lock_status():
|
||||
"""Returns the status of the IFC lock button"""
|
||||
|
||||
if not FreeCAD.GuiUp:
|
||||
return PARAMS.GetBool("SingleDoc")
|
||||
from PySide import QtGui
|
||||
mw = FreeCADGui.getMainWindow()
|
||||
statuswidget = mw.findChild(QtGui.QToolBar, "BIMStatusWidget")
|
||||
if hasattr(statuswidget, "lock_button"):
|
||||
return statuswidget.lock_button.isChecked()
|
||||
else:
|
||||
return False
|
||||
|
||||
|
||||
# add entry to File menu
|
||||
# https://github.com/FreeCAD/FreeCAD/pull/10933
|
||||
class IFC_WBManipulator:
|
||||
|
||||
@@ -45,6 +45,7 @@ from nativeifc import ifc_objects
|
||||
from nativeifc import ifc_viewproviders
|
||||
from nativeifc import ifc_import
|
||||
from nativeifc import ifc_layers
|
||||
from nativeifc import ifc_status
|
||||
|
||||
SCALE = 1000.0 # IfcOpenShell works in meters, FreeCAD works in mm
|
||||
SHORT = False # If True, only Step ID attribute is created
|
||||
@@ -55,7 +56,7 @@ PARAMS = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/NativeIFC")
|
||||
|
||||
def create_document(document, filename=None, shapemode=0, strategy=0, silent=False):
|
||||
"""Creates a IFC document object in the given FreeCAD document or converts that
|
||||
document into an IFC document, depending on the value of SingleDoc preference.
|
||||
document into an IFC document, depending on the state of the statusbar lock button.
|
||||
|
||||
filename: If not given, a blank IFC document is created
|
||||
shapemode: 0 = full shape
|
||||
@@ -66,7 +67,7 @@ def create_document(document, filename=None, shapemode=0, strategy=0, silent=Fal
|
||||
2 = all children
|
||||
"""
|
||||
|
||||
if PARAMS.GetBool("SingleDoc", False):
|
||||
if ifc_status.get_lock_status():
|
||||
return convert_document(document, filename, shapemode, strategy, silent)
|
||||
else:
|
||||
return create_document_object(document, filename, shapemode, strategy, silent)
|
||||
|
||||
Reference in New Issue
Block a user