# -*- coding: utf-8 -*-
# Author: Ruslan Krenzler.
# Date: 16 December 2017
# Create a tee-fitting.
# Version 0.1

import math

from PySide import QtCore, QtGui
import FreeCAD
import Spreadsheet
import Sketcher
import Part


document = App.activeDocument()
tu = FreeCAD.Units.parseQuantity

# The value RELATIVE_EPSILON is used to slightly change the size of a subtracted part
# to prevent problems with boolean operations.
# This value does not change the appearance of part and can be large.
# If the original value is L then we often use the value L*(1+RELATIVE_EPSILON) instead.
# The relative deviation is then (L*(1+RELATIVE_EPSILON)-L)/L = RELATIVE_EPSILON.
# That is why the constant has "relative" in its name.
RELATIVE_EPSILON = 0.1

NPS_NAME_COLUMN_INDEX = 0
NPS_SCHEDULE_COLUMN_INDEX = 1
NPS_OUTER_DIAMETER_COLUMN_INDEX = 2
NPS_INNER_DIAMETER_COLUMN_INDEX = 3

NPS_PVC_TABLE = [
	['1/8"', 40, 0.405,0.249,0.068,0.051,810],
	['1/4"', 40, 0.540,0.344,0.088, 0.086, 780],
	['3/8"', 40, 0.675, 0.473, 0.091, 0.115, 620],
	['1/2"', 40, 0.840, 0.602, 0.109, 0.170, 600],
	['3/4"', 40, 1.050, 0.804, 0.113, 0.226, 480],
	['1"', 40, 1.315, 1.029, 0.133, 0.333, 450],
	['1-1/4"', 40, 1.660, 1.360, 0.140, 0.450, 370],
	['1-1/2"', 40, 1.900, 1.590, 0.145, 0.537, 330],
	['2"', 40, 2.375, 2.047, 0.154, 0.720, 280],
	['2-1/2"', 40, 2.875, 2.445, 0.203, 1.136, 300],
	['3"', 40, 3.500, 3.042, 0.216, 1.488, 260],
	['3-1/2"', 40, 4.000, 3.521, 0.226, 1.789, 240],
	['4"', 40, 4.500, 3.998, 0.237, 2.118, 220],
	['5"', 40, 5.563, 5.016, 0.258, 2.874, 190],
	['6"', 40, 6.625, 6.031, 0.280, 3.733, 180],
	['8"', 40, 8.625, 7.942, 0.322, 5.619, 160],
	['10"', 40, 10.750, 9.976, 0.365, 7.966, 140],
	['12"', 40, 12.750, 11.889, 0.406, 10.534, 130],
	['1/8"',80, .405, .195, 0.095, 0.063, 1230],
	['1/4"',80, .540, .282, 0.119, 0.105, 1130],
	['3/8"',80, .675, .403, 0.126, 0.146, 920],
	['1/2"',80, .840, .526, 0.147, 0.213, 850],
	['3/4"',80, 1.050, .722, 0.154, 0.289, 690],
	['1"',80, 1.315, .936, 0.179, 0.424, 630],
	['1-1/4"',80, 1.660, 1.255, 0.191, 0.586, 520],
	['1-1/2"',80, 1.900, 1.476, 0.200, 0.711, 470],
	['2"',80, 2.375,1.913, 0.218, 0.984, 400],
	['2-1/2"',80, 2.875, 2.290, 0.276, 1.500, 420],
	['3"',80, 3.500, 2.864, 0.300, 2.010, 370],
	['3-1/2"',80, 4.000, 3.326, 0.318, 2.452, 350],
	['4"',80, 4.500, 3.786, 0.337, 2.938, 320],
	['5"',80, 5.563, 4.768, 0.375, 4.078, 290],
	['6"',80, 6.625, 5.709, 0.432, 5.610, 280],
	['8"',80, 8.625, 7.565, 0.500, 8.522, 250],
	['10"',80, 10.750, 9.493, 0.593, 12.635, 230],
	['12"',80 ,12.750, 11.294, 0.687, 17.384, 230]]

TEE_NAME_COLUMN_INDEX = 0
TEE_PIPE_SIZE_NAME_COLUMN_INDEX = 1
TEE_SCHEDULE_COLUMN_INDEX = 2
TEE_G_COLUMN_INDEX = 3
TEE_G1_COLUMN_INDEX = 4
TEE_H_COLUMN_INDEX = 5
TEE_H1_COLUMN_INDEX = 6
TEE_L_COLUMN_INDEX = 7
TEE_M_COLUMN_INDEX = 8
TEE_WEIGHT_COLUMN_INDEX = 9 # LBS, Not used now

# The headers are used by the GUI.
TEE_TABLE_HEADERS =["Part name", "Size", "Schedule", "G", "G1", "H", "H1", "M", "Weights LBS"]

TEE_TABLE = [['401-003', '3/8"', 40, 3/8.0, 3/8.0, 1+1/8.0, 1+1/8.0, 2+1/4.0, 31/32.0, .04],
['401-005', '1/2"', 40, 1/2.0, 1/2.0, 1+1/4.0, 1+1/4.0, 2+1/2.0, 1+3/32.0, .06],
['401-007', '3/4"', 40, 9/16.0, 9/16.0, 1+9/16.0, 1+9/16.0, 3+1/8.0, 1+5/16.0, .10],
['401-010', '1"', 40, 11/16.0, 11/16.0, 1+3/4.0, 1+3/4.0, 3+1/2.0, 1+5/8.0, .16],
['401-012', '1-1/4"', 40, 7/8.0, 7/8.0, 2+1/8.0, 2+1/8.0, 4+1/4.0, 2, .25],
['401-015', '1-1/2"', 40, 1+1/16.0, 1+1/16.0, 2+3/8.0, 2+3/8.0, 4+3/4.0, 2+1/4.0, .33],
['401-020', '2"', 40, 1+3/8.0, 1+3/8.0, 2+3/4.0, 2+3/4.0, 5+1/2.0, 2+3/4.0, .51],
['401-025', '2-1/2"', 40, 1+21/32.0, 1+21/32.0, 3+13/32.0, 3+13/32.0, 6+13/16.0, 3+11/32.0, 1.03],
['401-030', '3"', 40, 1+15/16.0, 1+15/16.0, 3+27/32.0, 3+27/32.0, 7+11/16.0, 4, 1.43],
['401-040', '4"', 40, 2+13/32.0, 2+13/32.0, 4+7/16.0, 4+7/16.0, 8+7/8.0, 5+1/32.0, 2.22],
['401-050', '5"', 40, 3, 3, 6, 6, 12, 6+5/32.0, 4.59],
['401-060', '6"', 40, 3+5/8.0, 3+5/8.0, 6+21/32.0, 6+21/32.0, 13+5/16.0, 7+9/32.0, 6.00],
['401-080', '8"', 40, 4+1/2.0, 4+1/2.0, 8+17/32.0, 8+17/32.0, 17+1/16.0, 9+3/8.0, 11.81],
['401-100', '10"', 40, 5+13/16.0, 5+13/16.0, 10+27/32.0, 10+27/32.0, 21+11/16.0, 11+21/32.0, 24.25],
['401-100F', '10"', 40, 9+7/8.0, 9+3/8.0, 15+1/8.0, 14+5/8.0, 30+1/4.0, 11+1/2.0, 36.21],
['401-120', '12"', 40, 6+27/32.0, 6+27/32.0, 12+27/32.0, 12+27/32.0, 25+11/16.0, 13+3/4.0, 37.94],
['401-120F', '12"', 40, 10+3/4.0, 10+3/16.0, 17, 16+7/16.0, 34, 13+9/16.0, 56.32],
# For following lines there are no pipe dimensions.
#['401-140', '14"', 40, 7+1/32.0, 7+1/32.0, 14+7/32.0, 14+1/32.0, 28+7/16.0, 15+21/32.0, 64.02],
#['401-140F', '14"', 40, 11+3/8.0, 11, 18+3/8.0, 18, 36+3/4.0, 14+7/8.0, 75.11],
#['401-160F', '16"', 40, 15, 12+7/8.0, 23, 20+7/8.0, 46, 17, 111.00],
#['401-180F', '18"', 40, 15+7/8.0, 13+3/8.0, 24+7/8.0, 22+3/8.0, 49+3/4.0, 19+1/8.0, 151.26],
#['401-200F', '20"', 40, 18+1/4.0, 15+1/2.0, 28+1/4.0, 25+1/2.0, 56+1/2.0, 21+3/16.0, 206.74],
#['401-240F', '24"', 40, 21+1/8.0, 17+1/2.0, 33+1/8.0, 29+1/2.0, 66+1/4.0, 25+3/8.0, 337.03],
['801-002', '1/4"', 80, 5/16.0, 5/16.0, 31/32.0, 31/32.0, 1+15/16.0, 27/32.0, .04],
['801-003', '3/8"', 80, 15/32.0, 15/32.0, 1+1/4.0, 1+1/4.0, 2+1/2.0, 31/32.0, .06],
['801-005', '1/2"', 80, 19/32.0, 19/32.0, 1+15/32.0, 1+15/32.0, 2+15/16.0, 1+3/16.0, .11],
['801-007', '3/4"', 80, 21/32.0, 21/32.0, 1+11/16.0, 1+11/16.0, 3+13/32.0, 1+13/32.0, .16],
['801-010', '1"', 80, 7/8.0, 7/8.0, 2, 2, 4, 1+3/4.0, .27],
['801-012', '1-1/4"', 80, 1+1/32.0, 1+1/32.0, 2+9/32.0, 2+9/32.0, 4+19/32.0, 2+3/32.0, .39],
['801-015', '1-1/2"', 80, 1+3/16.0, 1+3/16.0, 2+9/32.0, 2+9/32.0, 5+1/8.0, 2+3/8.0, .52],
['801-020', '2"', 80, 1+7/16.0, 1+7/16.0, 2+15/16.0, 2+15/16.0, 5+7/8.0, 2+7/8.0, .80],
['801-025', '2-1/2"', 80, 1+3/4.0, 1+3/4.0, 3+1/2.0, 3+1/2.0, 7+1/32.0, 3+15/32.0, 1.46],
['801-030', '3"', 80, 2+1/16.0, 2+1/16.0, 3+31/32.0, 3+31/32.0, 7+15/16.0, 4+5/32.0, 2.16],
['801-040', '4"', 80, 2+1/2.0, 2+1/2.0, 4+3/4.0, 4+3/4.0, 9+1/2.0, 5+1/4.0, 3.52],
['801-050', '5"', 80, 3+1/8.0, 3+1/8.0, 5+25/32.0, 5+25/32.0, 11+5/8.0, 6+13/32.0, 6.03],
['801-050F', '5"', 80, 5+1/2.0, 5+1/2.0, 8+1/2.0, 8+1/2.0, 17, 6+5/16.0, 13.26],
['801-060', '6"', 80, 3+25/32.0, 3+25/32.0, 6+13/16.0, 6+13/16.0, 13+5/8.0, 7+5/8.0, 10.78],
['801-080', '8"', 80, 4+13/16.0, 4+13/16.0, 8+7/8.0, 8+7/8.0, 17+3/4.0, 9+23/32.0, 21.21],
['801-080F', '8"', 80, 7+5/8.0, 7+5/8.0, 11+7/8.0, 11+7/8.0, 23+3/4.0, 9+5/8.0, 22.84],
['801-100', '10"', 80, 5+15/16.0, 5+29/32.0, 10+29/32.0, 10+29/32.0, 21+13/16.0, 12+13/16.0, 35.83],
['801-100F', '10"', 80, 9, 9, 14+1/4.0, 14+1/4.0, 28+1/2.0, 11+15/16.0, 39.82],
['801-120', '12"', 80, 6+15/16.0, 6+15/16.0, 12+15/16.0, 12+15/16.0, 25+7/8.0, 14+1/4.0, 54.45],
['801-120F', '12"', 80, 11+1/4.0, 11+1/4.0, 17+1/2.0, 17+1/2.0, 35, 14+1/8.0, 67.13]]
# For following lines there are no pipe dimensions.
#['801-140', '14"', 80, 7+1/32.0, 7+1/32.0, 14+7/32.0, 14+1/32.0, 28+7/16.0, 15+21/32.0, 63.61],
#['801-140F', '14"', 80, 12+1/4.0, 12+1/4.0, 19+1/4.0, 19+1/4.0, 38+1/2.0, 15+1/2.0, 103.37],
#['801-160F', '16"', 80, 13, 13, 21, 21, 42, 17+11/16.0, 144.87],
#['801-180F', '18"', 80, 13+3/4.0, 13+3/4.0, 22+3/4.0, 22+3/4.0, 45+1/2.0, 19+7/8.0, 182.75],
#['801-200F', '20"', 80, 16+3/8.0, 16+3/8.0, 26+3/8.0, 26+3/8.0, 52+3/4.0, 22+1/16.0, 284.24],
#['801-240F', '24"', 80, 20+1/4.0, 20+1/4.0, 32+1/4.0, 32+1/4.0, 64+1/2.0, 26+7/16.0, 335.00]]
class Tee:
	def __init__(self, document):
		self.document = document
		# fill data with test values
		self.G = tu("3/8 in")
		self.G1 = tu("3/8 in")
		self.H = tu("1+1/8 in") # It is L/2 for symetrical Tee. Why extra dimension?
		self.H1 = tu("1+1/8 in")
		self.L = tu("2+1/4 in")
		self.M = tu("31/32 in")
		self.innerD =  tu("0.473 in")
		self.socketD = tu("0.675 in")

	@staticmethod
	def toSolid(document, part, name):
		"""Convert object to a solid.
			Basically those are commands, which FreeCAD runs when user converts a part to a solid.
		"""
		s = part.Shape.Faces
		s = Part.Solid(Part.Shell(s))
		o = document.addObject("Part::Feature", name)
		o.Label=name
		o.Shape=s
		return o
	@staticmethod
	def NestedObjects(group):
		res = []
		if group.OutList == []:
			res.append(group)
		else:
			# Append children first.
			for o in group.OutList:
				res += Tee.NestedObjects(o)
			res.append(group)
		return res

	def create(self, convertToSolid):
		vertical_outer_cylinder = self.document.addObject("Part::Cylinder","VerticalOuterCynlider")
		vertical_outer_cylinder.Radius = self.M/2
		vertical_outer_cylinder.Height = self.H1
		vertical_inner_cylinder = self.document.addObject("Part::Cylinder","VerticalInnerCynlider")
		vertical_inner_cylinder.Radius = self.innerD/2
		vertical_inner_cylinder.Height =self.H1 * (1+RELATIVE_EPSILON)
		
		horizontal_outer_cylinder = self.document.addObject("Part::Cylinder","HorizontalOuterCynlider")
		horizontal_outer_cylinder.Radius = self.M/2
		horizontal_outer_cylinder.Height = self.L
		# I do not understand the logic here. Why when I use GUI the vector is App.Vector(0,0,-L/2)
		# and with the macros it is App.Vector(-L/2,0,0). Differne systems?
		horizontal_outer_cylinder.Placement = App.Placement(App.Vector(-horizontal_outer_cylinder.Height/2,0,0), App.Rotation(App.Vector(0,1,0),90), App.Vector(0,0,0))
		horizontal_inner_cylinder = self.document.addObject("Part::Cylinder","HorizontalInnerCynlider")
		horizontal_inner_cylinder.Radius = self.innerD/2
		horizontal_inner_cylinder.Height = self.L*(1+2*RELATIVE_EPSILON)
		horizontal_inner_cylinder.Placement = App.Placement(App.Vector(-horizontal_inner_cylinder.Height/2,0,0), App.Rotation(App.Vector(0,1,0),90), App.Vector(0,0,0))
		
		# Fuse outer parts to a tee, fuse inner parts to a tee, substract both parts
		outer_fusion = self.document.addObject("Part::MultiFuse","OuterTeeFusion")
		outer_fusion.Shapes = [vertical_outer_cylinder,horizontal_outer_cylinder]
		inner_fusion = self.document.addObject("Part::MultiFuse","InnerTeeFusion")
		inner_fusion.Shapes = [vertical_inner_cylinder,horizontal_inner_cylinder]
		basic_tee = self.document.addObject("Part::Cut","Cut")
		basic_tee.Base = outer_fusion
		basic_tee.Tool = inner_fusion
		
		# Remove place for suckets
		socket_left = self.document.addObject("Part::Cylinder","SocketLeft")
		socket_left.Radius = self.socketD /2
		socket_left.Height = (self.L/2 - self.G)*(1+RELATIVE_EPSILON)
		socket_left.Placement = App.Placement(App.Vector(-socket_left.Height - self.G,0,0), App.Rotation(App.Vector(0,1,0),90), App.Vector(0,0,0))
		
		socket_right = self.document.addObject("Part::Cylinder","SocketRight")
		socket_right.Radius = self.socketD /2
		socket_right.Height = (self.L/2 - self.G)*(1+RELATIVE_EPSILON)
		socket_right.Placement = App.Placement(App.Vector(self.G,0,0), App.Rotation(App.Vector(0,1,0),90), App.Vector(0,0,0))
		
		socket_top = self.document.addObject("Part::Cylinder","SocketTop")
		socket_top.Radius = self.socketD /2
		socket_top.Height = (self.H1 - self.G1)*(1+RELATIVE_EPSILON)
		socket_top.Placement = App.Placement(App.Vector(0,0,self.G1), App.Rotation(App.Vector(0,1,0),0), App.Vector(0,0,0))
		
		sockets_fusion = self.document.addObject("Part::MultiFuse","Sockets")
		sockets_fusion.Shapes = [socket_left,socket_right,socket_top]
		#document.recompute()
		# remove sockets from the basic tee
		tee = self.document.addObject("Part::Cut","Tee")
		tee.Base = basic_tee
		tee.Tool = sockets_fusion
		if convertToSolid:
			# Before making a solid recompute documents. Otherwise there will be
			#    s = Part.Solid(Part.Shell(s))
			#    <class 'Part.OCCError'>: Shape is null
			# exception.
			document.recompute()
			# Now convert all parts to solid, and remove intermediate data.
			solid = self.toSolid(document, tee, "tee (solid)")
			# Remove previous (intermediate parts).
			parts = Tee.NestedObjects(tee)
			# Document.removeObjects can remove multple objects, when we use
			# parts directly. To prevent exceptions with deleted objects,
			# use the name list instead.
			names_to_remove = []
			for part in parts:
				if part.Name not in names_to_remove:
					names_to_remove.append(part.Name)
			for name in names_to_remove:
				print("Deleting temporary objects %s."%name)
				document.removeObject(name)
			return solid
		return tee

# Create a part following from the dimensions from NPS_PVC_TABLE and TEE_TABLE.
class TeeFromTable:
	def __init__ (self, document):
		self.document = document
	@staticmethod
	def findPipeDimensions(npsPipeSizeName, schedule):
		"""Returns single row or None"""
		for row in NPS_PVC_TABLE:
			if row[NPS_NAME_COLUMN_INDEX]==npsPipeSizeName	and row[NPS_SCHEDULE_COLUMN_INDEX]==schedule:
				return row
		return None

	@staticmethod
	def findPart(partName):
		for row in TEE_TABLE:
			if row[TEE_NAME_COLUMN_INDEX]==partName:
				return row
		return row

	def create(self, partName, convertToSolid = True):
		tee = Tee(self.document)
		row = TeeFromTable.findPart(partName)
		if row is None:
			print("Part not found")
			return
		tee.G = tu("%f in"%row[TEE_G_COLUMN_INDEX])
		tee.G1 = tu("%f in"%row[TEE_G1_COLUMN_INDEX])
		tee.H = tu("%f in"%row[TEE_H_COLUMN_INDEX]) # It is L/2 for symetrical Tee. Why extra dimension?
		tee.H1 = tu("%f in"%row[TEE_H1_COLUMN_INDEX])
		tee.L = tu("%f in"%row[TEE_L_COLUMN_INDEX])
		tee.M = tu("%f in"%row[TEE_M_COLUMN_INDEX])


		# get pipe dimensions
		pipe_dims =TeeFromTable.findPipeDimensions(row[TEE_PIPE_SIZE_NAME_COLUMN_INDEX],row[TEE_SCHEDULE_COLUMN_INDEX])

		if pipe_dims is None:
			print("No pipe dimensions found")
			return

		tee.socketD = tu("%f in"%pipe_dims[NPS_OUTER_DIAMETER_COLUMN_INDEX])
		tee.innerD = tu("%f in"%pipe_dims[NPS_INNER_DIAMETER_COLUMN_INDEX])
		return tee.create(convertToSolid)


class PartTableModel(QtCore.QAbstractTableModel): 
	def __init__(self, parent=None, *args): 
		QtCore.QAbstractTableModel.__init__(self, parent, *args) 
	
	def rowCount(self, parent): 
		return len(TEE_TABLE) 
 
	def columnCount(self, parent):
		return len(TEE_TABLE_HEADERS) 
 
	def data(self, index, role):
		if not index.isValid(): 
			#return QtCore.QVariant() 
			return None
		elif role != QtCore.Qt.DisplayRole: 
			#return QtCore.QVariant() 
			return None
		#return QtCore.QVariant(ELBOW_90_TABLE[index.row()][index.column()]) 
		return TEE_TABLE[index.row()][index.column()] 

	def getPartName(self, rowIndex):
		return TEE_TABLE_HEADERS[rowIndex][0]

	def headerData(self, col, orientation, role):
		if orientation ==QtCore. Qt.Horizontal and role == QtCore.Qt.DisplayRole:
			return TEE_TABLE_HEADERS[col]
		return None

class GuiTee(QtGui.QDialog):
	"""Return index of the row in the NPC_PVC library.
		Return -1 if nothing is selected.
	"""
	def __init__(self):
		super(GuiTee, self).__init__()
		self.initUi()
	def initUi(self): 
		Dialog = self # Added 
		self.result = -1 
		self.setupUi(self)
		# Fill table with dimensions.
		self.initTable()
		self.show()
# The next lines are from QtDesigner .ui-file processed by pyside-uic
# pyside-uic --indent=0 ycreate-tee.ui -o tmp.py
	def setupUi(self, Dialog):
	# This code is from tmp.py.
		Dialog.setObjectName("Dialog")
		Dialog.resize(619, 277)
		self.buttonBox = QtGui.QDialogButtonBox(Dialog)
		self.buttonBox.setGeometry(QtCore.QRect(310, 240, 301, 32))
		self.buttonBox.setOrientation(QtCore.Qt.Horizontal)
		self.buttonBox.setStandardButtons(QtGui.QDialogButtonBox.Cancel|QtGui.QDialogButtonBox.Ok)
		self.buttonBox.setObjectName("buttonBox")
		self.tableViewParts = QtGui.QTableView(Dialog)
		self.tableViewParts.setGeometry(QtCore.QRect(10, 40, 601, 192))
		self.tableViewParts.setSelectionMode(QtGui.QAbstractItemView.SingleSelection)
		self.tableViewParts.setSelectionBehavior(QtGui.QAbstractItemView.SelectRows)
		self.tableViewParts.setObjectName("tableViewParts")
		self.checkBoxCreateSolid = QtGui.QCheckBox(Dialog)
		self.checkBoxCreateSolid.setGeometry(QtCore.QRect(10, 10, 171, 22))
		self.checkBoxCreateSolid.setChecked(True)
		self.checkBoxCreateSolid.setObjectName("checkBoxCreateSolid")

		self.retranslateUi(Dialog)
		QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL("accepted()"), Dialog.accept)
		QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL("rejected()"), Dialog.reject)
		QtCore.QMetaObject.connectSlotsByName(Dialog)

	def retranslateUi(self, Dialog):
		# Add data from tmp.py here.
		Dialog.setWindowTitle(QtGui.QApplication.translate("Dialog", "Create Tee", None, QtGui.QApplication.UnicodeUTF8))
		self.checkBoxCreateSolid.setText(QtGui.QApplication.translate("Dialog", "Create Solid", None, QtGui.QApplication.UnicodeUTF8))

	def initTable(self):
		model = PartTableModel()
		self.tableViewParts.setModel(model)

	def getSelectedName(self):
		sel = form.tableViewParts.selectionModel()
		if sel.isSelected:
			if len(sel.selectedRows())> 0:
				rowIndex = sel.selectedRows()[0].row()
				#return model.getPartName(rowIndex) # This does not work. Why?
				return TEE_TABLE_HEADERS[rowIndex][0]
		return None

	def accept(self):
		"""User clicked OK"""
		# Get suitable row from the the table.
		partName = self.getSelectedName()
		createSolid = self.checkBoxCreateSolid.isChecked()
		if partName is not None:
			#self.storeInput()
			tee = TeeFromTable(document)
			tee.create(partName, createSolid)
			document.recompute()
			# Call parent class.
			super(GuiTee, self).accept()
		else:
			msgBox = QtGui.QMessageBox()
			msgBox.setText("Select part")
			msgBox.exec_()

# Create all objects from the TEE_TABLE to test parameters.
def TestTable():
	tee = TeeFromTable(document)
	for row in TEE_TABLE:
		partName = row[TEE_NAME_COLUMN_INDEX]
		print("Creating part %s",partName)
		tee.create(partName, True)
		document.recompute()

#TestTable()
form = GuiTee()
document.recompute()
