603 lines
26 KiB
Python
603 lines
26 KiB
Python
# SPDX-License-Identifier: LGPL-2.1-or-later
|
|
|
|
# ***************************************************************************
|
|
# * *
|
|
# * Copyright (c) 2024 Yorik van Havre <yorik@uncreated.net> *
|
|
# * *
|
|
# * This file is part of FreeCAD. *
|
|
# * *
|
|
# * FreeCAD is free software: you can redistribute it and/or modify it *
|
|
# * under the terms of the GNU Lesser General Public License as *
|
|
# * published by the Free Software Foundation, either version 2.1 of the *
|
|
# * License, or (at your option) any later version. *
|
|
# * *
|
|
# * FreeCAD is distributed in the hope that it will be useful, but *
|
|
# * WITHOUT ANY WARRANTY; without even the implied warranty of *
|
|
# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
|
# * Lesser General Public License for more details. *
|
|
# * *
|
|
# * You should have received a copy of the GNU Lesser General Public *
|
|
# * License along with FreeCAD. If not, see *
|
|
# * <https://www.gnu.org/licenses/>. *
|
|
# * *
|
|
# ***************************************************************************
|
|
|
|
"""BIM window command"""
|
|
|
|
import os
|
|
|
|
import FreeCAD
|
|
import FreeCADGui
|
|
|
|
QT_TRANSLATE_NOOP = FreeCAD.Qt.QT_TRANSLATE_NOOP
|
|
translate = FreeCAD.Qt.translate
|
|
|
|
PARAMS = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/BIM")
|
|
ALLOWEDHOSTS = ["Wall", "Structure", "Roof"]
|
|
|
|
|
|
class Arch_Window:
|
|
"the Arch Window command definition"
|
|
|
|
def __init__(self):
|
|
|
|
self.doormode = False
|
|
|
|
def GetResources(self):
|
|
|
|
return {
|
|
"Pixmap": "Arch_Window",
|
|
"MenuText": QT_TRANSLATE_NOOP("Arch_Window", "Window"),
|
|
"Accel": "W, N",
|
|
"ToolTip": QT_TRANSLATE_NOOP(
|
|
"Arch_Window",
|
|
"Creates a window object from a selected object (wire, rectangle or sketch)",
|
|
),
|
|
}
|
|
|
|
def IsActive(self):
|
|
|
|
v = hasattr(FreeCADGui.getMainWindow().getActiveWindow(), "getSceneGraph")
|
|
return v
|
|
|
|
def Activated(self):
|
|
|
|
from draftutils import params
|
|
import Draft
|
|
import WorkingPlane
|
|
import draftguitools.gui_trackers as DraftTrackers
|
|
|
|
self.doc = FreeCAD.ActiveDocument
|
|
self.sel = FreeCADGui.Selection.getSelection()
|
|
self.W1 = params.get_param_arch("WindowW1") # thickness of the fixed frame
|
|
if self.doormode:
|
|
self.Width = params.get_param_arch("DoorWidth")
|
|
self.Height = params.get_param_arch("DoorHeight")
|
|
else:
|
|
self.Width = params.get_param_arch("WindowWidth")
|
|
self.Height = params.get_param_arch("WindowHeight")
|
|
self.RemoveExternal = params.get_param_arch("archRemoveExternal")
|
|
self.Preset = 0
|
|
self.LibraryPreset = 0
|
|
self.SillHeight = 0
|
|
self.Include = True
|
|
self.baseFace = None
|
|
self.wparams = ["Width", "Height", "H1", "H2", "H3", "W1", "W2", "O1", "O2"]
|
|
self.wp = None
|
|
|
|
# autobuild mode
|
|
if FreeCADGui.Selection.getSelectionEx():
|
|
FreeCADGui.draftToolBar.offUi()
|
|
obj = self.sel[0]
|
|
if hasattr(obj, "Shape"):
|
|
if obj.Shape.Wires and (not obj.Shape.Solids) and (not obj.Shape.Shells):
|
|
FreeCADGui.Control.closeDialog()
|
|
host = None
|
|
if hasattr(obj, "AttachmentSupport"):
|
|
if obj.AttachmentSupport:
|
|
if isinstance(obj.AttachmentSupport, tuple):
|
|
host = obj.AttachmentSupport[0]
|
|
elif isinstance(obj.AttachmentSupport, list):
|
|
host = obj.AttachmentSupport[0][0]
|
|
else:
|
|
host = obj.AttachmentSupport
|
|
obj.AttachmentSupport = None # remove
|
|
elif Draft.isClone(obj, "Window"):
|
|
if obj.Objects[0].Inlist:
|
|
host = obj.Objects[0].Inlist[0]
|
|
|
|
self.doc.openTransaction(translate("Arch", "Create Window"))
|
|
FreeCADGui.addModule("Arch")
|
|
FreeCADGui.doCommand(
|
|
"win = Arch.makeWindow(FreeCAD.ActiveDocument." + obj.Name + ")"
|
|
)
|
|
if host and self.Include:
|
|
FreeCADGui.doCommand(
|
|
"win.Hosts = [FreeCAD.ActiveDocument." + host.Name + "]"
|
|
)
|
|
siblings = host.Proxy.getSiblings(host)
|
|
sibs = [host]
|
|
for sibling in siblings:
|
|
if not sibling in sibs:
|
|
sibs.append(sibling)
|
|
FreeCADGui.doCommand(
|
|
"win.Hosts = win.Hosts+[FreeCAD.ActiveDocument."
|
|
+ sibling.Name
|
|
+ "]"
|
|
)
|
|
self.doc.commitTransaction()
|
|
self.doc.recompute()
|
|
return
|
|
|
|
# Try to detect an object to use as a window type - TODO we must make this safer
|
|
|
|
elif obj.Shape.Solids and (Draft.getType(obj) not in ["Wall", "Structure", "Roof"]):
|
|
# we consider the selected object as a type
|
|
self.doc.openTransaction(translate("Arch", "Create Window"))
|
|
FreeCADGui.addModule("Arch")
|
|
FreeCADGui.doCommand("Arch.makeWindow(FreeCAD.ActiveDocument." + obj.Name + ")")
|
|
self.doc.commitTransaction()
|
|
self.doc.recompute()
|
|
return
|
|
|
|
# interactive mode
|
|
|
|
FreeCAD.activeDraftCommand = self # register as a Draft command for auto grid on/off
|
|
self.wp = WorkingPlane.get_working_plane()
|
|
self.tracker = DraftTrackers.boxTracker()
|
|
self.tracker.length(self.Width)
|
|
self.tracker.width(self.W1)
|
|
self.tracker.height(self.Height)
|
|
self.tracker.on()
|
|
FreeCAD.Console.PrintMessage(
|
|
translate("Arch", "Choose a face on an existing object or select a preset") + "\n"
|
|
)
|
|
FreeCADGui.Snapper.getPoint(
|
|
callback=self.getPoint, movecallback=self.update, extradlg=self.taskbox()
|
|
)
|
|
# FreeCADGui.Snapper.setSelectMode(True)
|
|
|
|
def has_width_and_height_constraint(self, sketch):
|
|
width_found = False
|
|
height_found = False
|
|
|
|
for constr in sketch.Constraints:
|
|
if constr.Name == "Width":
|
|
width_found = True
|
|
elif constr.Name == "Height":
|
|
height_found = True
|
|
elif width_found and height_found:
|
|
break
|
|
|
|
return width_found and height_found
|
|
|
|
def getPoint(self, point=None, obj=None):
|
|
"this function is called by the snapper when it has a 3D point"
|
|
|
|
import Draft
|
|
from draftutils import gui_utils
|
|
from draftutils.messages import _wrn
|
|
from ArchWindowPresets import WindowPresets
|
|
|
|
SketchArch = False
|
|
|
|
FreeCAD.activeDraftCommand = None
|
|
FreeCADGui.Snapper.off()
|
|
self.tracker.off()
|
|
if point is None:
|
|
return
|
|
# if something was selected, override the underlying object
|
|
if self.sel:
|
|
obj = self.sel[0]
|
|
point = point.add(FreeCAD.Vector(0, 0, self.SillHeight))
|
|
self.doc.openTransaction(translate("Arch", "Create Window"))
|
|
|
|
FreeCADGui.doCommand("import FreeCAD, Arch, DraftGeomUtils, WorkingPlane")
|
|
FreeCADGui.doCommand("wp = WorkingPlane.get_working_plane()")
|
|
|
|
if self.baseFace is not None:
|
|
FreeCADGui.doCommand(
|
|
"face = FreeCAD.ActiveDocument."
|
|
+ self.baseFace[0].Name
|
|
+ ".Shape.Faces["
|
|
+ str(self.baseFace[1])
|
|
+ "]"
|
|
)
|
|
FreeCADGui.doCommand("pl = DraftGeomUtils.placement_from_face(face, vec_z = wp.axis)")
|
|
else:
|
|
FreeCADGui.doCommand("pl = FreeCAD.Placement()")
|
|
FreeCADGui.doCommand("pl.Rotation = FreeCAD.Rotation(wp.u, wp.axis, -wp.v, 'XZY')")
|
|
|
|
FreeCADGui.doCommand(
|
|
"pl.Base = FreeCAD.Vector("
|
|
+ str(point.x)
|
|
+ ", "
|
|
+ str(point.y)
|
|
+ ", "
|
|
+ str(point.z)
|
|
+ ")"
|
|
)
|
|
|
|
if self.baseFace is not None:
|
|
host = self.baseFace[0]
|
|
elif obj:
|
|
host = obj
|
|
else:
|
|
host = None
|
|
|
|
if self.Preset >= len(WindowPresets):
|
|
preset = False
|
|
# library object
|
|
col = self.doc.Objects
|
|
path = self.librarypresets[self.Preset - len(WindowPresets)][1]
|
|
FreeCADGui.doCommand("FreeCADGui.ActiveDocument.mergeProject('" + path + "')")
|
|
# find the latest added window
|
|
nol = self.doc.Objects
|
|
for o in nol[len(col) :]:
|
|
if Draft.getType(o) == "Window":
|
|
if Draft.getType(o.Base) != "Sketcher::SketchObject":
|
|
_wrn(
|
|
translate(
|
|
"Arch", "Window not based on sketch. Window not aligned or resized."
|
|
)
|
|
)
|
|
self.Include = False
|
|
break
|
|
FreeCADGui.doCommand("win = FreeCAD.ActiveDocument.getObject('" + o.Name + "')")
|
|
FreeCADGui.doCommand("win.Base.Placement = pl")
|
|
# Historically, this normal was deduced by the orientation of the Base Sketch and hardcoded in the Normal property.
|
|
# Now with the new AutoNormalReversed property/flag, set True as default, the auto Normal previously in opposite direction to is now consistent with that previously hardcoded.
|
|
# With the normal set to 'auto', window object would not suffer weird shape if the Base Sketch is rotated by some reason.
|
|
# Keep the property be 'auto' (0,0,0) here.
|
|
# FreeCADGui.doCommand("win.Normal = pl.Rotation.multVec(FreeCAD.Vector(0, 0, -1))")
|
|
FreeCADGui.doCommand("win.Width = " + str(self.Width))
|
|
FreeCADGui.doCommand("win.Height = " + str(self.Height))
|
|
FreeCADGui.doCommand("win.Base.recompute()")
|
|
if not self.has_width_and_height_constraint(o.Base):
|
|
_wrn(
|
|
translate(
|
|
"Arch",
|
|
"No Width and/or Height constraint in window sketch. Window not resized.",
|
|
)
|
|
)
|
|
break
|
|
else:
|
|
_wrn(translate("Arch", "No window found. Cannot continue."))
|
|
self.Include = False
|
|
|
|
else:
|
|
# preset
|
|
preset = True
|
|
wp = ""
|
|
for p in self.wparams:
|
|
wp += ", " + p.lower() + "=" + str(getattr(self, p))
|
|
import ArchSketchObject
|
|
|
|
if (
|
|
host
|
|
and hasattr(host, "Base")
|
|
and Draft.getType(host.Base) == "ArchSketch"
|
|
and hasattr(ArchSketchObject, "attachToHost")
|
|
and hasattr(FreeCAD, "ArchSketchLock")
|
|
and FreeCAD.ArchSketchLock
|
|
):
|
|
if self.Include:
|
|
# Window base sketch's placement stay at origin is good if addon exists and self.Include
|
|
#
|
|
# Put Sketch in 'upright' position to ensure the opening symbol on plan (SymbolPlan enabled) is correct
|
|
# - see https://github.com/FreeCAD/FreeCAD/issues/24903#issuecomment-3475455946
|
|
# placement = FreeCAD.Placement(App.Vector(0,0,0),App.Rotation(App.Vector(1,0,0),90))
|
|
# TODO 2025.11.1 : To improve the algorithm to be more robust to allow the Base Sketch in any orientation but without problem
|
|
#
|
|
# Window object triggers onChanged() upon setting/changing Window.SillHeight to move Window's z position
|
|
# For Window with SketchArch add-on, attachToHost() is to be run below to set the 'initial' Window's placement prior to triggering onChanged() below,
|
|
# so window_sill parameter is not used here at the moment, see 'if self.Include' below.
|
|
# FreeCADGui.doCommand("win = Arch.makeWindowPreset('" + WindowPresets[self.Preset] + "' " + wp + ", window_sill=" + str(self.SillHeight.Value) + ")")
|
|
FreeCADGui.doCommand(
|
|
"pl90 = FreeCAD.Placement(App.Vector(0,0,0),App.Rotation(App.Vector(1,0,0),90))"
|
|
)
|
|
FreeCADGui.doCommand(
|
|
"win = Arch.makeWindowPreset('"
|
|
+ WindowPresets[self.Preset]
|
|
+ "' "
|
|
+ wp
|
|
+ ", placement=pl90"
|
|
+ ")"
|
|
)
|
|
else:
|
|
# Window base sketch's placement follow getPoint placement if addon exists but NOT self.Include
|
|
FreeCADGui.doCommand(
|
|
"win = Arch.makeWindowPreset('"
|
|
+ WindowPresets[self.Preset]
|
|
+ "' "
|
|
+ wp
|
|
+ ", placement=pl, window_sill="
|
|
+ str(self.SillHeight.Value)
|
|
+ ")"
|
|
)
|
|
FreeCADGui.doCommand("win.AttachToAxisOrSketch = 'None'")
|
|
FreeCADGui.doCommand("FreeCADGui.Selection.addSelection(win)")
|
|
w = FreeCADGui.Selection.getSelection()[0]
|
|
FreeCADGui.doCommand("FreeCAD.SketchArchPl = pl")
|
|
wPl = FreeCAD.SketchArchPl
|
|
SketchArch = True
|
|
else:
|
|
FreeCADGui.doCommand(
|
|
"win = Arch.makeWindowPreset('"
|
|
+ WindowPresets[self.Preset]
|
|
+ "' "
|
|
+ wp
|
|
+ ", placement=pl, window_sill="
|
|
+ str(self.SillHeight.Value)
|
|
+ ")"
|
|
)
|
|
SketchArch = False
|
|
|
|
if self.Include:
|
|
if Draft.getType(host) in ALLOWEDHOSTS:
|
|
FreeCADGui.doCommand("win.Hosts = [FreeCAD.ActiveDocument." + host.Name + "]")
|
|
siblings = host.Proxy.getSiblings(host)
|
|
for sibling in siblings:
|
|
FreeCADGui.doCommand(
|
|
"win.Hosts = win.Hosts + [FreeCAD.ActiveDocument." + sibling.Name + "]"
|
|
)
|
|
if SketchArch:
|
|
ArchSketchObject.attachToHost(w, target=host, pl=wPl)
|
|
# Trigger onChanged() in the window object by setting Window.SillHeight, after setting the Window's 'initial' placement by attachToHost() above
|
|
FreeCADGui.doCommand("win.SillHeight = " + str(self.SillHeight.Value))
|
|
|
|
self.doc.commitTransaction()
|
|
self.doc.recompute()
|
|
# gui_utils.end_all_events() # Causes a crash on Linux.
|
|
self.tracker.finalize()
|
|
return
|
|
|
|
def update(self, point, info):
|
|
"this function is called by the Snapper when the mouse is moved"
|
|
|
|
delta = FreeCAD.Vector(self.Width / 2, self.W1 / 2, self.Height / 2)
|
|
delta = delta.add(FreeCAD.Vector(0, 0, self.SillHeight))
|
|
|
|
if self.baseFace is None:
|
|
rot = FreeCAD.Rotation(self.wp.u, self.wp.v, -self.wp.axis, "XZY")
|
|
self.tracker.setRotation(rot)
|
|
if info:
|
|
if "Face" in info["Component"]:
|
|
import DraftGeomUtils
|
|
|
|
o = self.doc.getObject(info["Object"])
|
|
self.baseFace = [o, int(info["Component"][4:]) - 1]
|
|
# print("switching to ",o.Label," face ",self.baseFace[1])
|
|
f = o.Shape.Faces[self.baseFace[1]]
|
|
p = DraftGeomUtils.placement_from_face(f, vec_z=self.wp.axis, rotated=True)
|
|
rot = p.Rotation
|
|
self.tracker.setRotation(rot)
|
|
r = self.tracker.trans.rotation.getValue().getValue()
|
|
if r != (0, 0, 0, 1):
|
|
delta = FreeCAD.Rotation(r[0], r[1], r[2], r[3]).multVec(
|
|
FreeCAD.Vector(delta.x, -delta.y, -delta.z)
|
|
)
|
|
self.tracker.pos(point.add(delta))
|
|
|
|
def taskbox(self):
|
|
"sets up a taskbox widget"
|
|
|
|
from draftutils import params
|
|
from PySide import QtCore, QtGui, QtSvgWidgets
|
|
from ArchWindowPresets import WindowPresets
|
|
|
|
w = QtGui.QWidget()
|
|
ui = FreeCADGui.UiLoader()
|
|
w.setWindowTitle(translate("Arch", "Window options"))
|
|
grid = QtGui.QGridLayout(w)
|
|
|
|
# include box
|
|
include = QtGui.QCheckBox(translate("Arch", "Auto include in host object"))
|
|
include.setChecked(True)
|
|
grid.addWidget(include, 0, 0, 1, 2)
|
|
if hasattr(include, "checkStateChanged"): # Qt version >= 6.7.0
|
|
include.checkStateChanged.connect(self.setInclude)
|
|
else: # Qt version < 6.7.0
|
|
include.stateChanged.connect(self.setInclude)
|
|
|
|
# sill height
|
|
labels = QtGui.QLabel(translate("Arch", "Sill height"))
|
|
values = ui.createWidget("Gui::InputField")
|
|
grid.addWidget(labels, 1, 0, 1, 1)
|
|
grid.addWidget(values, 1, 1, 1, 1)
|
|
values.valueChanged.connect(self.setSillHeight)
|
|
|
|
# check for Parts library and Arch presets
|
|
|
|
# because of the use of FreeCADGui.doCommand() backslashes in the
|
|
# paths in librarypresets need to be double escaped "\\\\", so let's
|
|
# use forward slashes instead...
|
|
self.librarypresets = []
|
|
librarypath = FreeCAD.ParamGet("User parameter:Plugins/parts_library").GetString(
|
|
"destination", ""
|
|
)
|
|
# librarypath should have only forward slashes already, but let's use replace() anyway just to be sure:
|
|
librarypath = librarypath.replace("\\", "/") + "/Architectural Parts"
|
|
presetdir = FreeCAD.getUserAppDataDir().replace("\\", "/") + "/Arch"
|
|
for path in [librarypath, presetdir]:
|
|
if os.path.isdir(path):
|
|
for wtype in ["Windows", "Doors"]:
|
|
wdir = path + "/" + wtype
|
|
if os.path.isdir(wdir):
|
|
for subtype in os.listdir(wdir):
|
|
subdir = wdir + "/" + subtype
|
|
if os.path.isdir(subdir):
|
|
for subfile in os.listdir(subdir):
|
|
if os.path.isfile(
|
|
subdir + "/" + subfile
|
|
) and subfile.lower().endswith(".fcstd"):
|
|
self.librarypresets.append(
|
|
[
|
|
wtype + " - " + subtype + " - " + subfile[:-6],
|
|
subdir + "/" + subfile,
|
|
]
|
|
)
|
|
|
|
# presets box
|
|
labelp = QtGui.QLabel(translate("Arch", "Preset"))
|
|
valuep = QtGui.QComboBox()
|
|
valuep.setMinimumContentsLength(6)
|
|
valuep.setSizeAdjustPolicy(QtGui.QComboBox.AdjustToContents)
|
|
valuep.addItems(WindowPresets)
|
|
valuep.setCurrentIndex(self.Preset)
|
|
grid.addWidget(labelp, 2, 0, 1, 1)
|
|
grid.addWidget(valuep, 2, 1, 1, 1)
|
|
valuep.currentIndexChanged.connect(self.setPreset)
|
|
for it in self.librarypresets:
|
|
valuep.addItem(it[0])
|
|
|
|
# image display
|
|
self.pic = QtGui.QLabel()
|
|
grid.addWidget(self.pic, 3, 0, 1, 2)
|
|
self.pic.setFixedHeight(128)
|
|
self.pic.hide()
|
|
|
|
# SVG display
|
|
self.im = QtSvgWidgets.QSvgWidget(":/ui/ParametersWindowFixed.svg")
|
|
self.im.setMaximumWidth(200)
|
|
self.im.setMinimumHeight(120)
|
|
grid.addWidget(self.im, 4, 0, 1, 2)
|
|
# self.im.hide()
|
|
|
|
# parameters
|
|
i = 5
|
|
for param in self.wparams:
|
|
lab = QtGui.QLabel(translate("Arch", param))
|
|
setattr(self, "val" + param, ui.createWidget("Gui::InputField"))
|
|
wid = getattr(self, "val" + param)
|
|
if param == "W1":
|
|
wid.setText(FreeCAD.Units.Quantity(self.W1, FreeCAD.Units.Length).UserString)
|
|
elif param == "Width":
|
|
wid.setText(FreeCAD.Units.Quantity(self.Width, FreeCAD.Units.Length).UserString)
|
|
elif param == "Height":
|
|
wid.setText(FreeCAD.Units.Quantity(self.Height, FreeCAD.Units.Length).UserString)
|
|
else:
|
|
n = params.get_param_arch("Window" + param)
|
|
wid.setText(FreeCAD.Units.Quantity(n, FreeCAD.Units.Length).UserString)
|
|
setattr(self, param, n)
|
|
grid.addWidget(lab, i, 0, 1, 1)
|
|
grid.addWidget(wid, i, 1, 1, 1)
|
|
i += 1
|
|
valueChanged = self.getValueChanged(param)
|
|
FreeCAD.wid = wid
|
|
QtCore.QObject.connect(
|
|
getattr(self, "val" + param), QtCore.SIGNAL("valueChanged(double)"), valueChanged
|
|
)
|
|
|
|
# restore saved states
|
|
if self.doormode:
|
|
i = params.get_param_arch("DoorPreset")
|
|
d = params.get_param_arch("DoorSill")
|
|
else:
|
|
i = params.get_param_arch("WindowPreset")
|
|
d = params.get_param_arch("WindowSill")
|
|
if i < valuep.count():
|
|
valuep.setCurrentIndex(i)
|
|
values.setText(FreeCAD.Units.Quantity(d, FreeCAD.Units.Length).UserString)
|
|
|
|
return w
|
|
|
|
def getValueChanged(self, p):
|
|
|
|
return lambda d: self.setParams(p, d)
|
|
|
|
def setSillHeight(self, d):
|
|
|
|
from draftutils import params
|
|
|
|
self.SillHeight = d
|
|
if self.doormode:
|
|
params.set_param_arch("DoorSill", d)
|
|
else:
|
|
params.set_param_arch("WindowSill", d)
|
|
|
|
def setInclude(self, i):
|
|
|
|
self.Include = bool(getattr(i, "value", i))
|
|
|
|
def setParams(self, param, d):
|
|
|
|
from draftutils import params
|
|
|
|
setattr(self, param, d)
|
|
self.tracker.length(self.Width)
|
|
self.tracker.height(self.Height)
|
|
self.tracker.width(self.W1)
|
|
prefix = "Door" if self.doormode and param in ("Width", "Height") else "Window"
|
|
params.set_param_arch(prefix + param, d)
|
|
|
|
def setPreset(self, i):
|
|
|
|
from PySide import QtGui
|
|
from draftutils import params
|
|
from ArchWindowPresets import WindowPresets
|
|
|
|
self.Preset = i
|
|
if self.doormode:
|
|
params.set_param_arch("DoorPreset", i)
|
|
else:
|
|
params.set_param_arch("WindowPreset", i)
|
|
if i >= 0:
|
|
FreeCADGui.Snapper.setSelectMode(False)
|
|
self.tracker.length(self.Width)
|
|
self.tracker.height(self.Height)
|
|
self.tracker.width(self.W1)
|
|
self.tracker.on()
|
|
self.pic.hide()
|
|
self.im.show()
|
|
if i == 0:
|
|
self.im.load(":/ui/ParametersWindowFixed.svg")
|
|
elif i in [1, 8]:
|
|
self.im.load(":/ui/ParametersWindowSimple.svg")
|
|
elif i in [2, 4, 7]:
|
|
self.im.load(":/ui/ParametersWindowDouble.svg")
|
|
elif i == 3:
|
|
self.im.load(":/ui/ParametersWindowStash.svg")
|
|
elif i == 5:
|
|
self.im.load(":/ui/ParametersDoorSimple.svg")
|
|
elif i == 6:
|
|
self.im.load(":/ui/ParametersDoorGlass.svg")
|
|
elif i == 9:
|
|
self.im.load(":/ui/ParametersOpening.svg")
|
|
else:
|
|
# From Library
|
|
self.im.hide()
|
|
path = self.librarypresets[i - len(WindowPresets)][1]
|
|
if path.lower().endswith(".fcstd"):
|
|
try:
|
|
import tempfile
|
|
import zipfile
|
|
except Exception:
|
|
pass
|
|
else:
|
|
zfile = zipfile.ZipFile(path)
|
|
files = zfile.namelist()
|
|
# check for meta-file if it's really a FreeCAD document
|
|
if files[0] == "Document.xml":
|
|
image = "thumbnails/Thumbnail.png"
|
|
if image in files:
|
|
image = zfile.read(image)
|
|
thumbfile = tempfile.mkstemp(suffix=".png")[1]
|
|
thumb = open(thumbfile, "wb")
|
|
thumb.write(image)
|
|
thumb.close()
|
|
im = QtGui.QPixmap(thumbfile)
|
|
self.pic.setPixmap(im)
|
|
self.pic.show()
|
|
# for param in self.wparams:
|
|
# getattr(self,"val"+param).setEnabled(True)
|
|
else:
|
|
FreeCADGui.Snapper.setSelectMode(True)
|
|
self.tracker.off()
|
|
self.im.hide()
|
|
for param in self.wparams:
|
|
getattr(self, "val" + param).setEnabled(False)
|
|
|
|
|
|
FreeCADGui.addCommand("Arch_Window", Arch_Window())
|