appDatabase.py 155 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555
  1. from PyQt5 import QtGui, QtCore, QtWidgets
  2. from appGUI.GUIElements import FCEntry, FCButton, FCDoubleSpinner, FCComboBox, FCCheckBox, FCSpinner, \
  3. FCTree, RadioSet, FCFileSaveDialog, FCLabel, FCComboBox2
  4. from camlib import to_dict
  5. import sys
  6. import json
  7. from copy import deepcopy
  8. from datetime import datetime
  9. import math
  10. import gettext
  11. import appTranslation as fcTranslate
  12. import builtins
  13. fcTranslate.apply_language('strings')
  14. if '_' not in builtins.__dict__:
  15. _ = gettext.gettext
  16. class ToolsDB2UI:
  17. def __init__(self, app, grid_layout):
  18. self.app = app
  19. self.decimals = self.app.decimals
  20. self.offset_item_options = ["Path", "In", "Out", "Custom"]
  21. self.type_item_options = ['Iso', 'Rough', 'Finish']
  22. self.tool_type_item_options = ["C1", "C2", "C3", "C4", "B", "V"]
  23. settings = QtCore.QSettings("Open Source", "FlatCAM")
  24. if settings.contains("machinist"):
  25. self.machinist_setting = settings.value('machinist', type=int)
  26. else:
  27. self.machinist_setting = 0
  28. self.g_lay = grid_layout
  29. tree_layout = QtWidgets.QVBoxLayout()
  30. self.g_lay.addLayout(tree_layout, 0, 0)
  31. self.tree_widget = FCTree(columns=2, header_hidden=False, protected_column=[0])
  32. self.tree_widget.setHeaderLabels([_("ID"), _("Tool Name")])
  33. self.tree_widget.setIndentation(0)
  34. self.tree_widget.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
  35. self.tree_widget.setSelectionMode(QtWidgets.QAbstractItemView.ExtendedSelection)
  36. # set alternating colors
  37. # self.tree_widget.setAlternatingRowColors(True)
  38. # p = QtGui.QPalette()
  39. # p.setColor(QtGui.QPalette.AlternateBase, QtGui.QColor(226, 237, 253) )
  40. # self.tree_widget.setPalette(p)
  41. self.tree_widget.setSizePolicy(QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.MinimumExpanding)
  42. tree_layout.addWidget(self.tree_widget)
  43. param_hlay = QtWidgets.QHBoxLayout()
  44. param_area = QtWidgets.QScrollArea()
  45. param_widget = QtWidgets.QWidget()
  46. param_widget.setLayout(param_hlay)
  47. param_area.setWidget(param_widget)
  48. param_area.setWidgetResizable(True)
  49. self.g_lay.addWidget(param_area, 0, 1)
  50. # ###########################################################################
  51. # ############## The UI form ################################################
  52. # ###########################################################################
  53. # Tool description box
  54. self.tool_description_box = QtWidgets.QGroupBox()
  55. self.tool_description_box.setStyleSheet("""
  56. QGroupBox
  57. {
  58. font-size: 16px;
  59. font-weight: bold;
  60. }
  61. """)
  62. self.description_vlay = QtWidgets.QVBoxLayout()
  63. self.tool_description_box.setTitle(_("Tool Description"))
  64. self.tool_description_box.setMinimumWidth(250)
  65. # Milling box
  66. self.milling_box = QtWidgets.QGroupBox()
  67. self.milling_box.setStyleSheet("""
  68. QGroupBox
  69. {
  70. font-size: 16px;
  71. font-weight: bold;
  72. }
  73. """)
  74. self.milling_vlay = QtWidgets.QVBoxLayout()
  75. self.milling_box.setTitle(_("Milling Parameters"))
  76. self.milling_box.setMinimumWidth(250)
  77. # NCC TOOL BOX
  78. self.ncc_box = QtWidgets.QGroupBox()
  79. self.ncc_box.setStyleSheet("""
  80. QGroupBox
  81. {
  82. font-size: 16px;
  83. font-weight: bold;
  84. }
  85. """)
  86. self.ncc_vlay = QtWidgets.QVBoxLayout()
  87. self.ncc_box.setTitle(_("NCC Parameters"))
  88. self.ncc_box.setMinimumWidth(250)
  89. # PAINT TOOL BOX
  90. self.paint_box = QtWidgets.QGroupBox()
  91. self.paint_box.setStyleSheet("""
  92. QGroupBox
  93. {
  94. font-size: 16px;
  95. font-weight: bold;
  96. }
  97. """)
  98. self.paint_vlay = QtWidgets.QVBoxLayout()
  99. self.paint_box.setTitle(_("Paint Parameters"))
  100. self.paint_box.setMinimumWidth(250)
  101. # ISOLATION TOOL BOX
  102. self.iso_box = QtWidgets.QGroupBox()
  103. self.iso_box.setStyleSheet("""
  104. QGroupBox
  105. {
  106. font-size: 16px;
  107. font-weight: bold;
  108. }
  109. """)
  110. self.iso_vlay = QtWidgets.QVBoxLayout()
  111. self.iso_box.setTitle(_("Isolation Parameters"))
  112. self.iso_box.setMinimumWidth(250)
  113. # DRILLING TOOL BOX
  114. self.drill_box = QtWidgets.QGroupBox()
  115. self.drill_box.setStyleSheet("""
  116. QGroupBox
  117. {
  118. font-size: 16px;
  119. font-weight: bold;
  120. }
  121. """)
  122. self.drill_vlay = QtWidgets.QVBoxLayout()
  123. self.drill_box.setTitle(_("Drilling Parameters"))
  124. self.drill_box.setMinimumWidth(250)
  125. # CUTOUT TOOL BOX
  126. self.cutout_box = QtWidgets.QGroupBox()
  127. self.cutout_box.setStyleSheet("""
  128. QGroupBox
  129. {
  130. font-size: 16px;
  131. font-weight: bold;
  132. }
  133. """)
  134. self.cutout_vlay = QtWidgets.QVBoxLayout()
  135. self.cutout_box.setTitle(_("Cutout Parameters"))
  136. self.cutout_box.setMinimumWidth(250)
  137. # Layout Constructor
  138. self.tool_description_box.setLayout(self.description_vlay)
  139. self.milling_box.setLayout(self.milling_vlay)
  140. self.ncc_box.setLayout(self.ncc_vlay)
  141. self.paint_box.setLayout(self.paint_vlay)
  142. self.iso_box.setLayout(self.iso_vlay)
  143. self.drill_box.setLayout(self.drill_vlay)
  144. self.cutout_box.setLayout(self.cutout_vlay)
  145. tools_vlay = QtWidgets.QVBoxLayout()
  146. tools_vlay.addWidget(self.iso_box)
  147. tools_vlay.addWidget(self.paint_box)
  148. tools_vlay.addWidget(self.ncc_box)
  149. tools_vlay.addWidget(self.cutout_box)
  150. tools_vlay.addStretch()
  151. descript_vlay = QtWidgets.QVBoxLayout()
  152. descript_vlay.addWidget(self.tool_description_box)
  153. descript_vlay.addLayout(tools_vlay)
  154. descript_vlay.addStretch()
  155. mill_vlay = QtWidgets.QVBoxLayout()
  156. mill_vlay.addWidget(self.milling_box)
  157. mill_vlay.addStretch()
  158. drilling_vlay = QtWidgets.QVBoxLayout()
  159. drilling_vlay.addWidget(self.drill_box)
  160. param_hlay.addLayout(descript_vlay)
  161. param_hlay.addLayout(drilling_vlay)
  162. param_hlay.addLayout(tools_vlay)
  163. # always visible, always to be included last
  164. param_hlay.addLayout(mill_vlay)
  165. param_hlay.addStretch()
  166. # ###########################################################################
  167. # ################ Tool UI form #############################################
  168. # ###########################################################################
  169. self.grid_tool = QtWidgets.QGridLayout()
  170. self.description_vlay.addLayout(self.grid_tool)
  171. self.grid_tool.setColumnStretch(0, 0)
  172. self.grid_tool.setColumnStretch(1, 1)
  173. self.description_vlay.addStretch()
  174. # Tool Name
  175. self.name_label = FCLabel('<span style="color:red;"><b>%s:</b></span>' % _('Name'))
  176. self.name_label.setToolTip(
  177. _("Tool name.\n"
  178. "This is not used in the app, it's function\n"
  179. "is to serve as a note for the user."))
  180. self.name_entry = FCEntry()
  181. self.name_entry.setObjectName('gdb_name')
  182. self.grid_tool.addWidget(self.name_label, 0, 0)
  183. self.grid_tool.addWidget(self.name_entry, 0, 1)
  184. # Tool Dia
  185. self.dia_label = FCLabel('%s:' % _('Diameter'))
  186. self.dia_label.setToolTip(
  187. _("Tool Diameter."))
  188. self.dia_entry = FCDoubleSpinner()
  189. self.dia_entry.set_range(-10000.0000, 10000.0000)
  190. self.dia_entry.set_precision(self.decimals)
  191. self.dia_entry.setObjectName('gdb_dia')
  192. self.grid_tool.addWidget(self.dia_label, 1, 0)
  193. self.grid_tool.addWidget(self.dia_entry, 1, 1)
  194. # Tool Tolerance
  195. self.tol_label = FCLabel("<b>%s:</b>" % _("Diameter Tolerance"))
  196. self.tol_label.setToolTip(
  197. _("Tool tolerance. This tool will be used if the desired tool diameter\n"
  198. "is within the tolerance specified here.")
  199. )
  200. self.grid_tool.addWidget(self.tol_label, 2, 0, 1, 2)
  201. # Tolerance Min Limit
  202. self.min_limit_label = FCLabel('%s:' % _("Min"))
  203. self.min_limit_label.setToolTip(
  204. _("Set the tool tolerance minimum.")
  205. )
  206. self.tol_min_entry = FCDoubleSpinner(callback=self.confirmation_message)
  207. self.tol_min_entry.set_precision(self.decimals)
  208. self.tol_min_entry.set_range(0, 10000.0000)
  209. self.tol_min_entry.setSingleStep(0.1)
  210. self.tol_min_entry.setObjectName("gdb_tol_min")
  211. self.grid_tool.addWidget(self.min_limit_label, 4, 0)
  212. self.grid_tool.addWidget(self.tol_min_entry, 4, 1)
  213. # Tolerance Min Limit
  214. self.max_limit_label = FCLabel('%s:' % _("Max"))
  215. self.max_limit_label.setToolTip(
  216. _("Set the tool tolerance maximum.")
  217. )
  218. self.tol_max_entry = FCDoubleSpinner(callback=self.confirmation_message)
  219. self.tol_max_entry.set_precision(self.decimals)
  220. self.tol_max_entry.set_range(0, 10000.0000)
  221. self.tol_max_entry.setSingleStep(0.1)
  222. self.tol_max_entry.setObjectName("gdb_tol_max")
  223. self.grid_tool.addWidget(self.max_limit_label, 6, 0)
  224. self.grid_tool.addWidget(self.tol_max_entry, 6, 1)
  225. # Tool Object Type
  226. self.tool_op_label = FCLabel('<b>%s:</b>' % _('Operation'))
  227. self.tool_op_label.setToolTip(
  228. _("The kind of Application Tool where this tool is to be used."))
  229. self.tool_op_combo = FCComboBox2()
  230. self.tool_op_combo.addItems(
  231. [_("General"), _("Milling"), _("Drilling"), _('Isolation'), _('Paint'), _('NCC'), _('Cutout')])
  232. self.tool_op_combo.setObjectName('gdb_tool_target')
  233. self.grid_tool.addWidget(self.tool_op_label, 8, 0)
  234. self.grid_tool.addWidget(self.tool_op_combo, 8, 1)
  235. # ###########################################################################
  236. # ############### MILLING UI form ###########################################
  237. # ###########################################################################
  238. self.grid0 = QtWidgets.QGridLayout()
  239. self.milling_vlay.addLayout(self.grid0)
  240. self.grid0.setColumnStretch(0, 0)
  241. self.grid0.setColumnStretch(1, 1)
  242. self.milling_vlay.addStretch()
  243. # Tool Shape
  244. self.shape_label = FCLabel('%s:' % _('Shape'))
  245. self.shape_label.setToolTip(
  246. _("Tool Shape. \n"
  247. "Can be:\n"
  248. "C1 ... C4 = circular tool with x flutes\n"
  249. "B = ball tip milling tool\n"
  250. "V = v-shape milling tool"))
  251. self.mill_shape_combo = FCComboBox()
  252. self.mill_shape_combo.addItems(self.tool_type_item_options)
  253. self.mill_shape_combo.setObjectName('gdb_shape')
  254. self.grid0.addWidget(self.shape_label, 2, 0)
  255. self.grid0.addWidget(self.mill_shape_combo, 2, 1)
  256. # V-Dia
  257. self.vdia_label = FCLabel('%s:' % _("V-Dia"))
  258. self.vdia_label.setToolTip(
  259. _("V-Dia.\n"
  260. "Diameter of the tip for V-Shape Tools."))
  261. self.mill_vdia_entry = FCDoubleSpinner()
  262. self.mill_vdia_entry.set_range(0.0000, 10000.0000)
  263. self.mill_vdia_entry.set_precision(self.decimals)
  264. self.mill_vdia_entry.setObjectName('gdb_vdia')
  265. self.grid0.addWidget(self.vdia_label, 4, 0)
  266. self.grid0.addWidget(self.mill_vdia_entry, 4, 1)
  267. # V-Angle
  268. self.vangle_label = FCLabel('%s:' % _("V-Angle"))
  269. self.vangle_label.setToolTip(
  270. _("V-Agle.\n"
  271. "Angle at the tip for the V-Shape Tools."))
  272. self.mill_vangle_entry = FCDoubleSpinner()
  273. self.mill_vangle_entry.set_range(-360.0, 360.0)
  274. self.mill_vangle_entry.set_precision(self.decimals)
  275. self.mill_vangle_entry.setObjectName('gdb_vangle')
  276. self.grid0.addWidget(self.vangle_label, 6, 0)
  277. self.grid0.addWidget(self.mill_vangle_entry, 6, 1)
  278. separator_line = QtWidgets.QFrame()
  279. separator_line.setFrameShape(QtWidgets.QFrame.HLine)
  280. separator_line.setFrameShadow(QtWidgets.QFrame.Sunken)
  281. self.grid0.addWidget(separator_line, 8, 0, 1, 2)
  282. # Tool Type
  283. self.type_label = FCLabel('%s:' % _("Tool Type"))
  284. self.type_label.setToolTip(
  285. _("Tool Type.\n"
  286. "Can be:\n"
  287. "Iso = isolation cut\n"
  288. "Rough = rough cut, low feedrate, multiple passes\n"
  289. "Finish = finishing cut, high feedrate"))
  290. self.mill_type_combo = FCComboBox()
  291. self.mill_type_combo.addItems(self.type_item_options)
  292. self.mill_type_combo.setObjectName('gdb_type')
  293. self.grid0.addWidget(self.type_label, 10, 0)
  294. self.grid0.addWidget(self.mill_type_combo, 10, 1)
  295. # Tool Offset
  296. self.tooloffset_label = FCLabel('%s:' % _('Tool Offset'))
  297. self.tooloffset_label.setToolTip(
  298. _("Tool Offset.\n"
  299. "Can be of a few types:\n"
  300. "Path = zero offset\n"
  301. "In = offset inside by half of tool diameter\n"
  302. "Out = offset outside by half of tool diameter\n"
  303. "Custom = custom offset using the Custom Offset value"))
  304. self.mill_tooloffset_combo = FCComboBox()
  305. self.mill_tooloffset_combo.addItems(self.offset_item_options)
  306. self.mill_tooloffset_combo.setObjectName('gdb_tool_offset')
  307. self.grid0.addWidget(self.tooloffset_label, 12, 0)
  308. self.grid0.addWidget(self.mill_tooloffset_combo, 12, 1)
  309. # Custom Offset
  310. self.custom_offset_label = FCLabel('%s:' % _("Custom Offset"))
  311. self.custom_offset_label.setToolTip(
  312. _("Custom Offset.\n"
  313. "A value to be used as offset from the current path."))
  314. self.mill_custom_offset_entry = FCDoubleSpinner()
  315. self.mill_custom_offset_entry.set_range(-10000.0000, 10000.0000)
  316. self.mill_custom_offset_entry.set_precision(self.decimals)
  317. self.mill_custom_offset_entry.setObjectName('gdb_custom_offset')
  318. self.grid0.addWidget(self.custom_offset_label, 14, 0)
  319. self.grid0.addWidget(self.mill_custom_offset_entry, 14, 1)
  320. separator_line = QtWidgets.QFrame()
  321. separator_line.setFrameShape(QtWidgets.QFrame.HLine)
  322. separator_line.setFrameShadow(QtWidgets.QFrame.Sunken)
  323. self.grid0.addWidget(separator_line, 16, 0, 1, 2)
  324. # Cut Z
  325. self.cutz_label = FCLabel('%s:' % _("Cut Z"))
  326. self.cutz_label.setToolTip(
  327. _("Cutting Depth.\n"
  328. "The depth at which to cut into material."))
  329. self.mill_cutz_entry = FCDoubleSpinner()
  330. self.mill_cutz_entry.set_range(-10000.0000, 10000.0000)
  331. self.mill_cutz_entry.set_precision(self.decimals)
  332. self.mill_cutz_entry.setObjectName('gdb_cutz')
  333. self.grid0.addWidget(self.cutz_label, 18, 0)
  334. self.grid0.addWidget(self.mill_cutz_entry, 18, 1)
  335. # Multi Depth
  336. self.multidepth_label = FCLabel('%s:' % _("MultiDepth"))
  337. self.multidepth_label.setToolTip(
  338. _("Multi Depth.\n"
  339. "Selecting this will allow cutting in multiple passes,\n"
  340. "each pass adding a DPP parameter depth."))
  341. self.mill_multidepth_cb = FCCheckBox()
  342. self.mill_multidepth_cb.setObjectName('gdb_multidepth')
  343. self.grid0.addWidget(self.multidepth_label, 20, 0)
  344. self.grid0.addWidget(self.mill_multidepth_cb, 20, 1)
  345. # Depth Per Pass
  346. self.dpp_label = FCLabel('%s:' % _("DPP"))
  347. self.dpp_label.setToolTip(
  348. _("DPP. Depth per Pass.\n"
  349. "The value used to cut into material on each pass."))
  350. self.mill_multidepth_entry = FCDoubleSpinner()
  351. self.mill_multidepth_entry.set_range(-10000.0000, 10000.0000)
  352. self.mill_multidepth_entry.set_precision(self.decimals)
  353. self.mill_multidepth_entry.setObjectName('gdb_multidepth_entry')
  354. self.grid0.addWidget(self.dpp_label, 22, 0)
  355. self.grid0.addWidget(self.mill_multidepth_entry, 22, 1)
  356. # Travel Z
  357. self.travelz_label = FCLabel('%s:' % _("Travel Z"))
  358. self.travelz_label.setToolTip(
  359. _("Clearance Height.\n"
  360. "Height at which the milling bit will travel between cuts,\n"
  361. "above the surface of the material, avoiding all fixtures."))
  362. self.mill_travelz_entry = FCDoubleSpinner()
  363. self.mill_travelz_entry.set_range(-10000.0000, 10000.0000)
  364. self.mill_travelz_entry.set_precision(self.decimals)
  365. self.mill_travelz_entry.setObjectName('gdb_travelz')
  366. self.grid0.addWidget(self.travelz_label, 24, 0)
  367. self.grid0.addWidget(self.mill_travelz_entry, 24, 1)
  368. # Extra Cut
  369. self.ecut_label = FCLabel('%s:' % _("ExtraCut"))
  370. self.ecut_label.setToolTip(
  371. _("Extra Cut.\n"
  372. "If checked, after a isolation is finished an extra cut\n"
  373. "will be added where the start and end of isolation meet\n"
  374. "such as that this point is covered by this extra cut to\n"
  375. "ensure a complete isolation."))
  376. self.mill_ecut_cb = FCCheckBox()
  377. self.mill_ecut_cb.setObjectName('gdb_ecut')
  378. self.grid0.addWidget(self.ecut_label, 26, 0)
  379. self.grid0.addWidget(self.mill_ecut_cb, 26, 1)
  380. # Extra Cut Length
  381. self.ecut_length_label = FCLabel('%s:' % _("E-Cut Length"))
  382. self.ecut_length_label.setToolTip(
  383. _("Extra Cut length.\n"
  384. "If checked, after a isolation is finished an extra cut\n"
  385. "will be added where the start and end of isolation meet\n"
  386. "such as that this point is covered by this extra cut to\n"
  387. "ensure a complete isolation. This is the length of\n"
  388. "the extra cut."))
  389. self.mill_ecut_length_entry = FCDoubleSpinner()
  390. self.mill_ecut_length_entry.set_range(0.0000, 10000.0000)
  391. self.mill_ecut_length_entry.set_precision(self.decimals)
  392. self.mill_ecut_length_entry.setObjectName('gdb_ecut_length')
  393. self.grid0.addWidget(self.ecut_length_label, 28, 0)
  394. self.grid0.addWidget(self.mill_ecut_length_entry, 28, 1)
  395. separator_line = QtWidgets.QFrame()
  396. separator_line.setFrameShape(QtWidgets.QFrame.HLine)
  397. separator_line.setFrameShadow(QtWidgets.QFrame.Sunken)
  398. self.grid0.addWidget(separator_line, 30, 0, 1, 2)
  399. # Feedrate X-Y
  400. self.frxy_label = FCLabel('%s:' % _("Feedrate X-Y"))
  401. self.frxy_label.setToolTip(
  402. _("Feedrate X-Y. Feedrate\n"
  403. "The speed on XY plane used while cutting into material."))
  404. self.mill_frxy_entry = FCDoubleSpinner()
  405. self.mill_frxy_entry.set_range(-9910000.0000, 9910000.0000)
  406. self.mill_frxy_entry.set_precision(self.decimals)
  407. self.mill_frxy_entry.setObjectName('gdb_frxy')
  408. self.grid0.addWidget(self.frxy_label, 32, 0)
  409. self.grid0.addWidget(self.mill_frxy_entry, 32, 1)
  410. # Feedrate Z
  411. self.frz_label = FCLabel('%s:' % _("Feedrate Z"))
  412. self.frz_label.setToolTip(
  413. _("Feedrate Z\n"
  414. "The speed on Z plane."))
  415. self.mill_frz_entry = FCDoubleSpinner()
  416. self.mill_frz_entry.set_range(-9910000.0000, 9910000.0000)
  417. self.mill_frz_entry.set_precision(self.decimals)
  418. self.mill_frz_entry.setObjectName('gdb_frz')
  419. self.grid0.addWidget(self.frz_label, 34, 0)
  420. self.grid0.addWidget(self.mill_frz_entry, 34, 1)
  421. # Feedrate Rapids
  422. self.frapids_label = FCLabel('%s:' % _("FR Rapids"))
  423. self.frapids_label.setToolTip(
  424. _("FR Rapids. Feedrate Rapids\n"
  425. "Speed used while moving as fast as possible.\n"
  426. "This is used only by some devices that can't use\n"
  427. "the G0 g-code command. Mostly 3D printers."))
  428. self.mill_frapids_entry = FCDoubleSpinner()
  429. self.mill_frapids_entry.set_range(0.0000, 10000.0000)
  430. self.mill_frapids_entry.set_precision(self.decimals)
  431. self.mill_frapids_entry.setObjectName('gdb_frapids')
  432. self.grid0.addWidget(self.frapids_label, 36, 0)
  433. self.grid0.addWidget(self.mill_frapids_entry, 36, 1)
  434. separator_line = QtWidgets.QFrame()
  435. separator_line.setFrameShape(QtWidgets.QFrame.HLine)
  436. separator_line.setFrameShadow(QtWidgets.QFrame.Sunken)
  437. self.grid0.addWidget(separator_line, 38, 0, 1, 2)
  438. # Spindle Spped
  439. self.spindle_label = FCLabel('%s:' % _("Spindle Speed"))
  440. self.spindle_label.setToolTip(
  441. _("Spindle Speed.\n"
  442. "If it's left empty it will not be used.\n"
  443. "The speed of the spindle in RPM."))
  444. self.mill_spindle_entry = FCDoubleSpinner()
  445. self.mill_spindle_entry.set_range(-9910000.0000, 9910000.0000)
  446. self.mill_spindle_entry.set_precision(self.decimals)
  447. self.mill_spindle_entry.setObjectName('gdb_spindle')
  448. self.grid0.addWidget(self.spindle_label, 40, 0)
  449. self.grid0.addWidget(self.mill_spindle_entry, 40, 1)
  450. # Dwell
  451. self.dwell_label = FCLabel('%s:' % _("Dwell"))
  452. self.dwell_label.setToolTip(
  453. _("Dwell.\n"
  454. "Check this if a delay is needed to allow\n"
  455. "the spindle motor to reach its set speed."))
  456. self.mill_dwell_cb = FCCheckBox()
  457. self.mill_dwell_cb.setObjectName('gdb_dwell')
  458. self.grid0.addWidget(self.dwell_label, 42, 0)
  459. self.grid0.addWidget(self.mill_dwell_cb, 42, 1)
  460. # Dwell Time
  461. self.dwelltime_label = FCLabel('%s:' % _("Dwelltime"))
  462. self.dwelltime_label.setToolTip(
  463. _("Dwell Time.\n"
  464. "A delay used to allow the motor spindle reach its set speed."))
  465. self.mill_dwelltime_entry = FCDoubleSpinner()
  466. self.mill_dwelltime_entry.set_range(0.0000, 10000.0000)
  467. self.mill_dwelltime_entry.set_precision(self.decimals)
  468. self.mill_dwelltime_entry.setObjectName('gdb_dwelltime')
  469. self.grid0.addWidget(self.dwelltime_label, 44, 0)
  470. self.grid0.addWidget(self.mill_dwelltime_entry, 44, 1)
  471. # ###########################################################################
  472. # ############### NCC UI form ###############################################
  473. # ###########################################################################
  474. self.grid2 = QtWidgets.QGridLayout()
  475. self.ncc_vlay.addLayout(self.grid2)
  476. self.grid2.setColumnStretch(0, 0)
  477. self.grid2.setColumnStretch(1, 1)
  478. self.ncc_vlay.addStretch()
  479. # Operation
  480. op_label = FCLabel('%s:' % _('Operation'))
  481. op_label.setToolTip(
  482. _("The 'Operation' can be:\n"
  483. "- Isolation -> will ensure that the non-copper clearing is always complete.\n"
  484. "If it's not successful then the non-copper clearing will fail, too.\n"
  485. "- Clear -> the regular non-copper clearing.")
  486. )
  487. self.ncc_op_radio = RadioSet([
  488. {"label": _("Clear"), "value": "clear"},
  489. {"label": _("Isolation"), "value": "iso"}
  490. ], orientation='horizontal', stretch=False)
  491. self.ncc_op_radio.setObjectName("gdb_n_operation")
  492. self.grid2.addWidget(op_label, 13, 0)
  493. self.grid2.addWidget(self.ncc_op_radio, 13, 1)
  494. # Milling Type Radio Button
  495. self.milling_type_label = FCLabel('%s:' % _('Milling Type'))
  496. self.milling_type_label.setToolTip(
  497. _("Milling type when the selected tool is of type: 'iso_op':\n"
  498. "- climb / best for precision milling and to reduce tool usage\n"
  499. "- conventional / useful when there is no backlash compensation")
  500. )
  501. self.ncc_milling_type_radio = RadioSet([{'label': _('Climb'), 'value': 'cl'},
  502. {'label': _('Conventional'), 'value': 'cv'}])
  503. self.ncc_milling_type_radio.setToolTip(
  504. _("Milling type when the selected tool is of type: 'iso_op':\n"
  505. "- climb / best for precision milling and to reduce tool usage\n"
  506. "- conventional / useful when there is no backlash compensation")
  507. )
  508. self.ncc_milling_type_radio.setObjectName("gdb_n_milling_type")
  509. self.grid2.addWidget(self.milling_type_label, 14, 0)
  510. self.grid2.addWidget(self.ncc_milling_type_radio, 14, 1)
  511. # Overlap Entry
  512. nccoverlabel = FCLabel('%s:' % _('Overlap'))
  513. nccoverlabel.setToolTip(
  514. _("How much (percentage) of the tool width to overlap each tool pass.\n"
  515. "Adjust the value starting with lower values\n"
  516. "and increasing it if areas that should be cleared are still \n"
  517. "not cleared.\n"
  518. "Lower values = faster processing, faster execution on CNC.\n"
  519. "Higher values = slow processing and slow execution on CNC\n"
  520. "due of too many paths.")
  521. )
  522. self.ncc_overlap_entry = FCDoubleSpinner(suffix='%')
  523. self.ncc_overlap_entry.set_precision(self.decimals)
  524. self.ncc_overlap_entry.setWrapping(True)
  525. self.ncc_overlap_entry.setRange(0.000, 99.9999)
  526. self.ncc_overlap_entry.setSingleStep(0.1)
  527. self.ncc_overlap_entry.setObjectName("gdb_n_overlap")
  528. self.grid2.addWidget(nccoverlabel, 15, 0)
  529. self.grid2.addWidget(self.ncc_overlap_entry, 15, 1)
  530. # Margin
  531. nccmarginlabel = FCLabel('%s:' % _('Margin'))
  532. nccmarginlabel.setToolTip(
  533. _("Bounding box margin.")
  534. )
  535. self.ncc_margin_entry = FCDoubleSpinner()
  536. self.ncc_margin_entry.set_precision(self.decimals)
  537. self.ncc_margin_entry.set_range(-10000.0000, 10000.0000)
  538. self.ncc_margin_entry.setObjectName("gdb_n_margin")
  539. self.grid2.addWidget(nccmarginlabel, 16, 0)
  540. self.grid2.addWidget(self.ncc_margin_entry, 16, 1)
  541. # Method
  542. methodlabel = FCLabel('%s:' % _('Method'))
  543. methodlabel.setToolTip(
  544. _("Algorithm for copper clearing:\n"
  545. "- Standard: Fixed step inwards.\n"
  546. "- Seed-based: Outwards from seed.\n"
  547. "- Line-based: Parallel lines.")
  548. )
  549. self.ncc_method_combo = FCComboBox2()
  550. self.ncc_method_combo.addItems(
  551. [_("Standard"), _("Seed"), _("Lines"), _("Combo")]
  552. )
  553. self.ncc_method_combo.setObjectName("gdb_n_method")
  554. self.grid2.addWidget(methodlabel, 17, 0)
  555. self.grid2.addWidget(self.ncc_method_combo, 17, 1)
  556. # Connect lines
  557. self.ncc_connect_cb = FCCheckBox('%s' % _("Connect"))
  558. self.ncc_connect_cb.setObjectName("gdb_n_connect")
  559. self.ncc_connect_cb.setToolTip(
  560. _("Draw lines between resulting\n"
  561. "segments to minimize tool lifts.")
  562. )
  563. self.grid2.addWidget(self.ncc_connect_cb, 18, 0)
  564. # Contour
  565. self.ncc_contour_cb = FCCheckBox('%s' % _("Contour"))
  566. self.ncc_contour_cb.setObjectName("gdb_n_contour")
  567. self.ncc_contour_cb.setToolTip(
  568. _("Cut around the perimeter of the polygon\n"
  569. "to trim rough edges.")
  570. )
  571. self.grid2.addWidget(self.ncc_contour_cb, 18, 1)
  572. # ## NCC Offset choice
  573. self.ncc_choice_offset_cb = FCCheckBox('%s' % _("Offset"))
  574. self.ncc_choice_offset_cb.setObjectName("gdb_n_offset")
  575. self.ncc_choice_offset_cb.setToolTip(
  576. _("If used, it will add an offset to the copper features.\n"
  577. "The copper clearing will finish to a distance\n"
  578. "from the copper features.\n"
  579. "The value can be between 0 and 10 FlatCAM units.")
  580. )
  581. self.grid2.addWidget(self.ncc_choice_offset_cb, 19, 0)
  582. # ## NCC Offset Entry
  583. self.ncc_offset_spinner = FCDoubleSpinner()
  584. self.ncc_offset_spinner.set_range(0.00, 10.00)
  585. self.ncc_offset_spinner.set_precision(4)
  586. self.ncc_offset_spinner.setWrapping(True)
  587. self.ncc_offset_spinner.setObjectName("gdb_n_offset_value")
  588. units = self.app.defaults['units'].upper()
  589. if units == 'MM':
  590. self.ncc_offset_spinner.setSingleStep(0.1)
  591. else:
  592. self.ncc_offset_spinner.setSingleStep(0.01)
  593. self.grid2.addWidget(self.ncc_offset_spinner, 19, 1)
  594. # ###########################################################################
  595. # ############### Paint UI form #############################################
  596. # ###########################################################################
  597. self.grid3 = QtWidgets.QGridLayout()
  598. self.paint_vlay.addLayout(self.grid3)
  599. self.grid3.setColumnStretch(0, 0)
  600. self.grid3.setColumnStretch(1, 1)
  601. self.paint_vlay.addStretch()
  602. # Overlap
  603. ovlabel = FCLabel('%s:' % _('Overlap'))
  604. ovlabel.setToolTip(
  605. _("How much (percentage) of the tool width to overlap each tool pass.\n"
  606. "Adjust the value starting with lower values\n"
  607. "and increasing it if areas that should be painted are still \n"
  608. "not painted.\n"
  609. "Lower values = faster processing, faster execution on CNC.\n"
  610. "Higher values = slow processing and slow execution on CNC\n"
  611. "due of too many paths.")
  612. )
  613. self.paint_overlap_entry = FCDoubleSpinner(suffix='%')
  614. self.paint_overlap_entry.set_precision(3)
  615. self.paint_overlap_entry.setWrapping(True)
  616. self.paint_overlap_entry.setRange(0.0000, 99.9999)
  617. self.paint_overlap_entry.setSingleStep(0.1)
  618. self.paint_overlap_entry.setObjectName('gdb_p_overlap')
  619. self.grid3.addWidget(ovlabel, 1, 0)
  620. self.grid3.addWidget(self.paint_overlap_entry, 1, 1)
  621. # Margin
  622. marginlabel = FCLabel('%s:' % _('Offset'))
  623. marginlabel.setToolTip(
  624. _("Distance by which to avoid\n"
  625. "the edges of the polygon to\n"
  626. "be painted.")
  627. )
  628. self.paint_offset_entry = FCDoubleSpinner()
  629. self.paint_offset_entry.set_precision(self.decimals)
  630. self.paint_offset_entry.set_range(-10000.0000, 10000.0000)
  631. self.paint_offset_entry.setObjectName('gdb_p_offset')
  632. self.grid3.addWidget(marginlabel, 2, 0)
  633. self.grid3.addWidget(self.paint_offset_entry, 2, 1)
  634. # Method
  635. methodlabel = FCLabel('%s:' % _('Method'))
  636. methodlabel.setToolTip(
  637. _("Algorithm for painting:\n"
  638. "- Standard: Fixed step inwards.\n"
  639. "- Seed-based: Outwards from seed.\n"
  640. "- Line-based: Parallel lines.\n"
  641. "- Laser-lines: Active only for Gerber objects.\n"
  642. "Will create lines that follow the traces.\n"
  643. "- Combo: In case of failure a new method will be picked from the above\n"
  644. "in the order specified.")
  645. )
  646. self.paint_method_combo = FCComboBox2()
  647. self.paint_method_combo.addItems(
  648. [_("Standard"), _("Seed"), _("Lines"), _("Laser_lines"), _("Combo")]
  649. )
  650. idx = self.paint_method_combo.findText(_("Laser_lines"))
  651. self.paint_method_combo.model().item(idx).setEnabled(False)
  652. self.paint_method_combo.setObjectName('gdb_p_method')
  653. self.grid3.addWidget(methodlabel, 7, 0)
  654. self.grid3.addWidget(self.paint_method_combo, 7, 1)
  655. # Connect lines
  656. self.path_connect_cb = FCCheckBox('%s' % _("Connect"))
  657. self.path_connect_cb.setObjectName('gdb_p_connect')
  658. self.path_connect_cb.setToolTip(
  659. _("Draw lines between resulting\n"
  660. "segments to minimize tool lifts.")
  661. )
  662. self.paint_contour_cb = FCCheckBox('%s' % _("Contour"))
  663. self.paint_contour_cb.setObjectName('gdb_p_contour')
  664. self.paint_contour_cb.setToolTip(
  665. _("Cut around the perimeter of the polygon\n"
  666. "to trim rough edges.")
  667. )
  668. self.grid3.addWidget(self.path_connect_cb, 10, 0)
  669. self.grid3.addWidget(self.paint_contour_cb, 10, 1)
  670. # ###########################################################################
  671. # ############### Isolation UI form #########################################
  672. # ###########################################################################
  673. self.grid4 = QtWidgets.QGridLayout()
  674. self.iso_vlay.addLayout(self.grid4)
  675. self.grid4.setColumnStretch(0, 0)
  676. self.grid4.setColumnStretch(1, 1)
  677. self.iso_vlay.addStretch()
  678. # Passes
  679. passlabel = FCLabel('%s:' % _('Passes'))
  680. passlabel.setToolTip(
  681. _("Width of the isolation gap in\n"
  682. "number (integer) of tool widths.")
  683. )
  684. self.iso_passes_entry = FCSpinner()
  685. self.iso_passes_entry.set_range(1, 999)
  686. self.iso_passes_entry.setObjectName("gdb_i_passes")
  687. self.grid4.addWidget(passlabel, 0, 0)
  688. self.grid4.addWidget(self.iso_passes_entry, 0, 1)
  689. # Overlap Entry
  690. overlabel = FCLabel('%s:' % _('Overlap'))
  691. overlabel.setToolTip(
  692. _("How much (percentage) of the tool width to overlap each tool pass.")
  693. )
  694. self.iso_overlap_entry = FCDoubleSpinner(suffix='%')
  695. self.iso_overlap_entry.set_precision(self.decimals)
  696. self.iso_overlap_entry.setWrapping(True)
  697. self.iso_overlap_entry.set_range(0.0000, 99.9999)
  698. self.iso_overlap_entry.setSingleStep(0.1)
  699. self.iso_overlap_entry.setObjectName("gdb_i_overlap")
  700. self.grid4.addWidget(overlabel, 2, 0)
  701. self.grid4.addWidget(self.iso_overlap_entry, 2, 1)
  702. # Milling Type Radio Button
  703. self.iso_milling_type_label = FCLabel('%s:' % _('Milling Type'))
  704. self.iso_milling_type_label.setToolTip(
  705. _("Milling type when the selected tool is of type: 'iso_op':\n"
  706. "- climb / best for precision milling and to reduce tool usage\n"
  707. "- conventional / useful when there is no backlash compensation")
  708. )
  709. self.iso_milling_type_radio = RadioSet([{'label': _('Climb'), 'value': 'cl'},
  710. {'label': _('Conventional'), 'value': 'cv'}])
  711. self.iso_milling_type_radio.setToolTip(
  712. _("Milling type when the selected tool is of type: 'iso_op':\n"
  713. "- climb / best for precision milling and to reduce tool usage\n"
  714. "- conventional / useful when there is no backlash compensation")
  715. )
  716. self.iso_milling_type_radio.setObjectName("gdb_i_milling_type")
  717. self.grid4.addWidget(self.iso_milling_type_label, 4, 0)
  718. self.grid4.addWidget(self.iso_milling_type_radio, 4, 1)
  719. # Follow
  720. self.follow_label = FCLabel('%s:' % _('Follow'))
  721. self.follow_label.setToolTip(
  722. _("Generate a 'Follow' geometry.\n"
  723. "This means that it will cut through\n"
  724. "the middle of the trace.")
  725. )
  726. self.iso_follow_cb = FCCheckBox()
  727. self.iso_follow_cb.setToolTip(_("Generate a 'Follow' geometry.\n"
  728. "This means that it will cut through\n"
  729. "the middle of the trace."))
  730. self.iso_follow_cb.setObjectName("gdb_i_follow")
  731. self.grid4.addWidget(self.follow_label, 6, 0)
  732. self.grid4.addWidget(self.iso_follow_cb, 6, 1)
  733. # Isolation Type
  734. self.iso_type_label = FCLabel('%s:' % _('Isolation Type'))
  735. self.iso_type_label.setToolTip(
  736. _("Choose how the isolation will be executed:\n"
  737. "- 'Full' -> complete isolation of polygons\n"
  738. "- 'Ext' -> will isolate only on the outside\n"
  739. "- 'Int' -> will isolate only on the inside\n"
  740. "'Exterior' isolation is almost always possible\n"
  741. "(with the right tool) but 'Interior'\n"
  742. "isolation can be done only when there is an opening\n"
  743. "inside of the polygon (e.g polygon is a 'doughnut' shape).")
  744. )
  745. self.iso_type_radio = RadioSet([{'label': _('Full'), 'value': 'full'},
  746. {'label': _('Ext'), 'value': 'ext'},
  747. {'label': _('Int'), 'value': 'int'}])
  748. self.iso_type_radio.setObjectName("gdb_i_iso_type")
  749. self.grid4.addWidget(self.iso_type_label, 8, 0)
  750. self.grid4.addWidget(self.iso_type_radio, 8, 1)
  751. # ###########################################################################
  752. # ################ DRILLING UI form #########################################
  753. # ###########################################################################
  754. self.grid5 = QtWidgets.QGridLayout()
  755. self.drill_vlay.addLayout(self.grid5)
  756. self.grid5.setColumnStretch(0, 0)
  757. self.grid5.setColumnStretch(1, 1)
  758. self.drill_vlay.addStretch()
  759. # Cut Z
  760. self.cutzlabel = FCLabel('%s:' % _('Cut Z'))
  761. self.cutzlabel.setToolTip(
  762. _("Drill depth (negative)\n"
  763. "below the copper surface.")
  764. )
  765. self.drill_cutz_entry = FCDoubleSpinner(callback=self.confirmation_message)
  766. self.drill_cutz_entry.set_precision(self.decimals)
  767. if self.machinist_setting == 0:
  768. self.drill_cutz_entry.set_range(-10000.0000, 0.0000)
  769. else:
  770. self.drill_cutz_entry.set_range(-10000.0000, 10000.0000)
  771. self.drill_cutz_entry.setSingleStep(0.1)
  772. self.drill_cutz_entry.setObjectName("gdb_e_cutz")
  773. self.grid5.addWidget(self.cutzlabel, 4, 0)
  774. self.grid5.addWidget(self.drill_cutz_entry, 4, 1)
  775. # Tool Offset
  776. self.tool_offset_label = FCLabel('%s:' % _('Offset Z'))
  777. self.tool_offset_label.setToolTip(
  778. _("Some drill bits (the larger ones) need to drill deeper\n"
  779. "to create the desired exit hole diameter due of the tip shape.\n"
  780. "The value here can compensate the Cut Z parameter.")
  781. )
  782. self.drill_offset_entry = FCDoubleSpinner(callback=self.confirmation_message)
  783. self.drill_offset_entry.set_precision(self.decimals)
  784. self.drill_offset_entry.set_range(-10000.0000, 10000.0000)
  785. self.drill_offset_entry.setObjectName("gdb_e_offset")
  786. self.grid5.addWidget(self.tool_offset_label, 6, 0)
  787. self.grid5.addWidget(self.drill_offset_entry, 6, 1)
  788. # Multi-Depth
  789. self.multidepth_drill_label = FCLabel('%s:' % _("MultiDepth"))
  790. self.multidepth_drill_label.setToolTip(
  791. _(
  792. "Use multiple passes to limit\n"
  793. "the cut depth in each pass. Will\n"
  794. "cut multiple times until Cut Z is\n"
  795. "reached."
  796. )
  797. )
  798. self.drill_mpass_cb = FCCheckBox()
  799. self.drill_mpass_cb.setObjectName("gdb_e_multidepth")
  800. self.grid5.addWidget(self.multidepth_drill_label, 7, 0)
  801. self.grid5.addWidget(self.drill_mpass_cb, 7, 1)
  802. # Depth Per Pass
  803. self.dpp_drill_label = FCLabel('%s:' % _("DPP"))
  804. self.dpp_drill_label.setToolTip(
  805. _("DPP. Depth per Pass.\n"
  806. "The value used to cut into material on each pass."))
  807. self.drill_maxdepth_entry = FCDoubleSpinner(callback=self.confirmation_message)
  808. self.drill_maxdepth_entry.set_precision(self.decimals)
  809. self.drill_maxdepth_entry.set_range(0, 10000.0000)
  810. self.drill_maxdepth_entry.setSingleStep(0.1)
  811. self.drill_maxdepth_entry.setToolTip(_("Depth of each pass (positive)."))
  812. self.drill_maxdepth_entry.setObjectName("gdb_e_depthperpass")
  813. self.grid5.addWidget(self.dpp_drill_label, 8, 0)
  814. self.grid5.addWidget(self.drill_maxdepth_entry, 8, 1)
  815. # Travel Z (z_move)
  816. self.travelzlabel = FCLabel('%s:' % _('Travel Z'))
  817. self.travelzlabel.setToolTip(
  818. _("Tool height when travelling\n"
  819. "across the XY plane.")
  820. )
  821. self.drill_travelz_entry = FCDoubleSpinner(callback=self.confirmation_message)
  822. self.drill_travelz_entry.set_precision(self.decimals)
  823. if self.machinist_setting == 0:
  824. self.drill_travelz_entry.set_range(0.00001, 10000.0000)
  825. else:
  826. self.drill_travelz_entry.set_range(-10000.0000, 10000.0000)
  827. self.drill_travelz_entry.setSingleStep(0.1)
  828. self.drill_travelz_entry.setObjectName("gdb_e_travelz")
  829. self.grid5.addWidget(self.travelzlabel, 10, 0)
  830. self.grid5.addWidget(self.drill_travelz_entry, 10, 1)
  831. separator_line = QtWidgets.QFrame()
  832. separator_line.setFrameShape(QtWidgets.QFrame.HLine)
  833. separator_line.setFrameShadow(QtWidgets.QFrame.Sunken)
  834. self.grid5.addWidget(separator_line, 12, 0, 1, 2)
  835. # Excellon Feedrate Z
  836. self.frzlabel = FCLabel('%s:' % _('Feedrate Z'))
  837. self.frzlabel.setToolTip(
  838. _("Tool speed while drilling\n"
  839. "(in units per minute).\n"
  840. "So called 'Plunge' feedrate.\n"
  841. "This is for linear move G01.")
  842. )
  843. self.drill_feedrate_z_entry = FCDoubleSpinner(callback=self.confirmation_message)
  844. self.drill_feedrate_z_entry.set_precision(self.decimals)
  845. self.drill_feedrate_z_entry.set_range(0.0, 910000.0000)
  846. self.drill_feedrate_z_entry.setSingleStep(0.1)
  847. self.drill_feedrate_z_entry.setObjectName("gdb_e_feedratez")
  848. self.grid5.addWidget(self.frzlabel, 14, 0)
  849. self.grid5.addWidget(self.drill_feedrate_z_entry, 14, 1)
  850. # Excellon Rapid Feedrate
  851. self.feedrate_rapid_label = FCLabel('%s:' % _('Feedrate Rapids'))
  852. self.feedrate_rapid_label.setToolTip(
  853. _("Tool speed while drilling\n"
  854. "(in units per minute).\n"
  855. "This is for the rapid move G00.\n"
  856. "It is useful only for Marlin,\n"
  857. "ignore for any other cases.")
  858. )
  859. self.drill_feedrate_rapid_entry = FCDoubleSpinner(callback=self.confirmation_message)
  860. self.drill_feedrate_rapid_entry.set_precision(self.decimals)
  861. self.drill_feedrate_rapid_entry.set_range(0.0, 910000.0000)
  862. self.drill_feedrate_rapid_entry.setSingleStep(0.1)
  863. self.drill_feedrate_rapid_entry.setObjectName("gdb_e_fr_rapid")
  864. self.grid5.addWidget(self.feedrate_rapid_label, 16, 0)
  865. self.grid5.addWidget(self.drill_feedrate_rapid_entry, 16, 1)
  866. separator_line = QtWidgets.QFrame()
  867. separator_line.setFrameShape(QtWidgets.QFrame.HLine)
  868. separator_line.setFrameShadow(QtWidgets.QFrame.Sunken)
  869. self.grid5.addWidget(separator_line, 18, 0, 1, 2)
  870. # Spindlespeed
  871. self.spindle_label = FCLabel('%s:' % _('Spindle speed'))
  872. self.spindle_label.setToolTip(
  873. _("Speed of the spindle\n"
  874. "in RPM (optional)")
  875. )
  876. self.drill_spindlespeed_entry = FCSpinner(callback=self.confirmation_message_int)
  877. self.drill_spindlespeed_entry.set_range(0, 1000000)
  878. self.drill_spindlespeed_entry.set_step(100)
  879. self.drill_spindlespeed_entry.setObjectName("gdb_e_spindlespeed")
  880. self.grid5.addWidget(self.spindle_label, 20, 0)
  881. self.grid5.addWidget(self.drill_spindlespeed_entry, 20, 1)
  882. # Dwell
  883. self.dwell_drill_label = FCLabel('%s:' % _("Dwell"))
  884. self.dwell_drill_label.setToolTip(
  885. _("Dwell.\n"
  886. "Check this if a delay is needed to allow\n"
  887. "the spindle motor to reach its set speed."))
  888. self.drill_dwell_cb = FCCheckBox()
  889. self.drill_dwell_cb.setObjectName("gdb_e_dwell")
  890. self.grid5.addWidget(self.dwell_drill_label, 21, 0)
  891. self.grid5.addWidget(self.drill_dwell_cb, 21, 1)
  892. # Dwelltime
  893. self.dwelltime_drill_lbl = FCLabel('%s:' % _('Dwelltime'))
  894. self.dwelltime_drill_lbl.setToolTip(
  895. _("Dwell Time.\n"
  896. "A delay used to allow the motor spindle reach its set speed."))
  897. self.drill_dwelltime_entry = FCDoubleSpinner(callback=self.confirmation_message)
  898. self.drill_dwelltime_entry.set_precision(self.decimals)
  899. self.drill_dwelltime_entry.set_range(0.0, 10000.0000)
  900. self.drill_dwelltime_entry.setSingleStep(0.1)
  901. self.drill_dwelltime_entry.setObjectName("gdb_e_dwelltime")
  902. self.grid5.addWidget(self.dwelltime_drill_lbl, 22, 0)
  903. self.grid5.addWidget(self.drill_dwelltime_entry, 22, 1)
  904. separator_line = QtWidgets.QFrame()
  905. separator_line.setFrameShape(QtWidgets.QFrame.HLine)
  906. separator_line.setFrameShadow(QtWidgets.QFrame.Sunken)
  907. self.grid5.addWidget(separator_line, 24, 0, 1, 2)
  908. # Drill slots
  909. self.drill_slots_drill_lbl = FCLabel('%s:' % _('Drill slots'))
  910. self.drill_slots_drill_lbl.setToolTip(
  911. _("If the selected tool has slots then they will be drilled.")
  912. )
  913. self.drill_slots_cb = FCCheckBox()
  914. self.drill_slots_cb.setObjectName("gdb_e_drill_slots")
  915. self.grid5.addWidget(self.drill_slots_drill_lbl, 26, 0,)
  916. self.grid5.addWidget(self.drill_slots_cb, 26, 1)
  917. # Drill Overlap
  918. self.drill_overlap_label = FCLabel('%s:' % _('Overlap'))
  919. self.drill_overlap_label.setToolTip(
  920. _("How much (percentage) of the tool diameter to overlap previous drill hole.")
  921. )
  922. self.drill_overlap_entry = FCDoubleSpinner(suffix='%', callback=self.confirmation_message)
  923. self.drill_overlap_entry.set_precision(self.decimals)
  924. self.drill_overlap_entry.set_range(0.0, 100.0000)
  925. self.drill_overlap_entry.setSingleStep(0.1)
  926. self.drill_overlap_entry.setObjectName("gdb_e_drill_slots_over")
  927. self.grid5.addWidget(self.drill_overlap_label, 28, 0)
  928. self.grid5.addWidget(self.drill_overlap_entry, 28, 1)
  929. # Last drill in slot
  930. self.last_drill_drill_lbl = FCLabel('%s:' % _('Last drill'))
  931. self.last_drill_drill_lbl.setToolTip(
  932. _("If the slot length is not completely covered by drill holes,\n"
  933. "add a drill hole on the slot end point.")
  934. )
  935. self.drill_last_drill_cb = FCCheckBox()
  936. self.drill_last_drill_cb.setObjectName("gdb_e_drill_last_drill")
  937. self.grid5.addWidget(self.last_drill_drill_lbl, 30, 0, 1, 2)
  938. self.grid5.addWidget(self.drill_last_drill_cb, 30, 1)
  939. # ###########################################################################
  940. # ################### Cutout UI form ########################################
  941. # ###########################################################################
  942. self.grid6 = QtWidgets.QGridLayout()
  943. self.cutout_vlay.addLayout(self.grid6)
  944. self.grid6.setColumnStretch(0, 0)
  945. self.grid6.setColumnStretch(1, 1)
  946. self.cutout_vlay.addStretch()
  947. # Margin
  948. self.cutout_margin_entry = FCDoubleSpinner(callback=self.confirmation_message)
  949. self.cutout_margin_entry.set_range(-10000.0000, 10000.0000)
  950. self.cutout_margin_entry.setSingleStep(0.1)
  951. self.cutout_margin_entry.set_precision(self.decimals)
  952. self.cutout_margin_entry.setObjectName('gdb_ct_margin')
  953. self.cutout_margin_label = FCLabel('%s:' % _("Margin"))
  954. self.cutout_margin_label.setToolTip(
  955. _("Margin over bounds. A positive value here\n"
  956. "will make the cutout of the PCB further from\n"
  957. "the actual PCB border")
  958. )
  959. self.grid6.addWidget(self.cutout_margin_label, 11, 0)
  960. self.grid6.addWidget(self.cutout_margin_entry, 11, 1)
  961. # Gapsize
  962. self.cutout_gapsize = FCDoubleSpinner(callback=self.confirmation_message)
  963. self.cutout_gapsize.set_precision(self.decimals)
  964. self.cutout_gapsize.setObjectName('gdb_ct_gapsize')
  965. self.cutout_gapsize_label = FCLabel('%s:' % _("Gap size"))
  966. self.cutout_gapsize_label.setToolTip(
  967. _("The size of the bridge gaps in the cutout\n"
  968. "used to keep the board connected to\n"
  969. "the surrounding material (the one \n"
  970. "from which the PCB is cutout).")
  971. )
  972. self.grid6.addWidget(self.cutout_gapsize_label, 13, 0)
  973. self.grid6.addWidget(self.cutout_gapsize, 13, 1)
  974. # Gap Type
  975. self.gaptype_label = FCLabel('%s:' % _("Gap type"))
  976. self.gaptype_label.setToolTip(
  977. _("The type of gap:\n"
  978. "- Bridge -> the cutout will be interrupted by bridges\n"
  979. "- Thin -> same as 'bridge' but it will be thinner by partially milling the gap\n"
  980. "- M-Bites -> 'Mouse Bites' - same as 'bridge' but covered with drill holes")
  981. )
  982. self.cutout_gaptype_radio = RadioSet(
  983. [
  984. {'label': _('Bridge'), 'value': 'b'},
  985. {'label': _('Thin'), 'value': 'bt'},
  986. {'label': "M-Bites", 'value': 'mb'}
  987. ],
  988. stretch=True
  989. )
  990. self.cutout_gaptype_radio.setObjectName('gdb_ct_gap_type')
  991. self.grid6.addWidget(self.gaptype_label, 15, 0)
  992. self.grid6.addWidget(self.cutout_gaptype_radio, 15, 1)
  993. # Thin gaps Depth
  994. self.thin_depth_label = FCLabel('%s:' % _("Depth"))
  995. self.thin_depth_label.setToolTip(
  996. _("The depth until the milling is done\n"
  997. "in order to thin the gaps.")
  998. )
  999. self.cutout_thin_depth_entry = FCDoubleSpinner(callback=self.confirmation_message)
  1000. self.cutout_thin_depth_entry.set_precision(self.decimals)
  1001. self.cutout_thin_depth_entry.setObjectName('gdb_ct_gap_depth')
  1002. if self.machinist_setting == 0:
  1003. self.cutout_thin_depth_entry.setRange(-10000.0000, -0.00001)
  1004. else:
  1005. self.cutout_thin_depth_entry.setRange(-10000.0000, 10000.0000)
  1006. self.cutout_thin_depth_entry.setSingleStep(0.1)
  1007. self.grid6.addWidget(self.thin_depth_label, 17, 0)
  1008. self.grid6.addWidget(self.cutout_thin_depth_entry, 17, 1)
  1009. # Mouse Bites Tool Diameter
  1010. self.mb_dia_label = FCLabel('%s:' % _("Tool Diameter"))
  1011. self.mb_dia_label.setToolTip(
  1012. _("The drill hole diameter when doing mouse bites.")
  1013. )
  1014. self.cutout_mb_dia_entry = FCDoubleSpinner(callback=self.confirmation_message)
  1015. self.cutout_mb_dia_entry.set_precision(self.decimals)
  1016. self.cutout_mb_dia_entry.setRange(0, 100.0000)
  1017. self.cutout_mb_dia_entry.setObjectName('gdb_ct_mb_dia')
  1018. self.grid6.addWidget(self.mb_dia_label, 19, 0)
  1019. self.grid6.addWidget(self.cutout_mb_dia_entry, 19, 1)
  1020. # Mouse Bites Holes Spacing
  1021. self.mb_spacing_label = FCLabel('%s:' % _("Spacing"))
  1022. self.mb_spacing_label.setToolTip(
  1023. _("The spacing between drill holes when doing mouse bites.")
  1024. )
  1025. self.cutout_mb_spacing_entry = FCDoubleSpinner(callback=self.confirmation_message)
  1026. self.cutout_mb_spacing_entry.set_precision(self.decimals)
  1027. self.cutout_mb_spacing_entry.setRange(0, 100.0000)
  1028. self.cutout_mb_spacing_entry.setObjectName('gdb_ct_mb_spacing')
  1029. self.grid6.addWidget(self.mb_spacing_label, 21, 0)
  1030. self.grid6.addWidget(self.cutout_mb_spacing_entry, 21, 1)
  1031. # How gaps wil be rendered:
  1032. # lr - left + right
  1033. # tb - top + bottom
  1034. # 4 - left + right +top + bottom
  1035. # 2lr - 2*left + 2*right
  1036. # 2tb - 2*top + 2*bottom
  1037. # 8 - 2*left + 2*right +2*top + 2*bottom
  1038. # Surrounding convex box shape
  1039. self.cutout_convex_box = FCCheckBox('%s' % _("Convex Shape"))
  1040. # self.convex_box_label = FCLabel('%s' % _("Convex Sh."))
  1041. self.cutout_convex_box.setToolTip(
  1042. _("Create a convex shape surrounding the entire PCB.\n"
  1043. "Used only if the source object type is Gerber.")
  1044. )
  1045. self.cutout_convex_box.setObjectName('gdb_ct_convex')
  1046. self.grid6.addWidget(self.cutout_convex_box, 23, 0, 1, 2)
  1047. # Gaps
  1048. self.cutout_gaps_label = FCLabel('%s:' % _('Gaps'))
  1049. self.cutout_gaps_label.setToolTip(
  1050. _("Number of gaps used for the Automatic cutout.\n"
  1051. "There can be maximum 8 bridges/gaps.\n"
  1052. "The choices are:\n"
  1053. "- None - no gaps\n"
  1054. "- lr - left + right\n"
  1055. "- tb - top + bottom\n"
  1056. "- 4 - left + right +top + bottom\n"
  1057. "- 2lr - 2*left + 2*right\n"
  1058. "- 2tb - 2*top + 2*bottom\n"
  1059. "- 8 - 2*left + 2*right +2*top + 2*bottom")
  1060. )
  1061. self.cutout_gaps = FCComboBox()
  1062. gaps_items = ['None', 'LR', 'TB', '4', '2LR', '2TB', '8']
  1063. self.cutout_gaps.addItems(gaps_items)
  1064. self.cutout_gaps.setObjectName('gdb_ct_gaps')
  1065. self.grid6.addWidget(self.cutout_gaps_label, 25, 0)
  1066. self.grid6.addWidget(self.cutout_gaps, 25, 1)
  1067. # ####################################################################
  1068. # ####################################################################
  1069. # GUI for the lower part of the window
  1070. # ####################################################################
  1071. # ####################################################################
  1072. new_vlay = QtWidgets.QVBoxLayout()
  1073. self.g_lay.addLayout(new_vlay, 1, 0, 1, 2)
  1074. self.buttons_frame = QtWidgets.QFrame()
  1075. self.buttons_frame.setContentsMargins(0, 0, 0, 0)
  1076. new_vlay.addWidget(self.buttons_frame)
  1077. self.buttons_box = QtWidgets.QHBoxLayout()
  1078. self.buttons_box.setContentsMargins(0, 0, 0, 0)
  1079. self.buttons_frame.setLayout(self.buttons_box)
  1080. self.buttons_frame.show()
  1081. self.add_entry_btn = FCButton(_("Add Tool in DB"))
  1082. self.add_entry_btn.setIcon(QtGui.QIcon(self.app.resource_location + '/plus16.png'))
  1083. self.add_entry_btn.setToolTip(
  1084. _("Add a new tool in the Tools Database.\n"
  1085. "It will be used in the Geometry UI.\n"
  1086. "You can edit it after it is added.")
  1087. )
  1088. self.buttons_box.addWidget(self.add_entry_btn)
  1089. # add_fct_entry_btn = FCButton(_("Add Paint/NCC Tool in DB"))
  1090. # add_fct_entry_btn.setToolTip(
  1091. # _("Add a new tool in the Tools Database.\n"
  1092. # "It will be used in the Paint/NCC Tools UI.\n"
  1093. # "You can edit it after it is added.")
  1094. # )
  1095. # self.buttons_box.addWidget(add_fct_entry_btn)
  1096. self.remove_entry_btn = FCButton(_("Delete Tool from DB"))
  1097. self.remove_entry_btn.setIcon(QtGui.QIcon(self.app.resource_location + '/trash16.png'))
  1098. self.remove_entry_btn.setToolTip(
  1099. _("Remove a selection of tools in the Tools Database.")
  1100. )
  1101. self.buttons_box.addWidget(self.remove_entry_btn)
  1102. self.export_db_btn = FCButton(_("Export DB"))
  1103. self.export_db_btn.setIcon(QtGui.QIcon(self.app.resource_location + '/export.png'))
  1104. self.export_db_btn.setToolTip(
  1105. _("Save the Tools Database to a custom text file.")
  1106. )
  1107. self.buttons_box.addWidget(self.export_db_btn)
  1108. self.import_db_btn = FCButton(_("Import DB"))
  1109. self.import_db_btn.setIcon(QtGui.QIcon(self.app.resource_location + '/import.png'))
  1110. self.import_db_btn.setToolTip(
  1111. _("Load the Tools Database information's from a custom text file.")
  1112. )
  1113. self.buttons_box.addWidget(self.import_db_btn)
  1114. self.save_db_btn = FCButton(_("Save DB"))
  1115. self.save_db_btn.setIcon(QtGui.QIcon(self.app.resource_location + '/save_as.png'))
  1116. self.save_db_btn.setToolTip(
  1117. _("Save the Tools Database information's.")
  1118. )
  1119. self.buttons_box.addWidget(self.save_db_btn)
  1120. self.add_tool_from_db = FCButton(_("Transfer the Tool"))
  1121. self.add_tool_from_db.setToolTip(
  1122. _("Insert a new tool in the Tools Table of the\n"
  1123. "object/application tool after selecting a tool\n"
  1124. "in the Tools Database.")
  1125. )
  1126. self.add_tool_from_db.setStyleSheet("""
  1127. QPushButton
  1128. {
  1129. font-weight: bold;
  1130. color: green;
  1131. }
  1132. """)
  1133. self.add_tool_from_db.hide()
  1134. self.cancel_tool_from_db = FCButton(_("Cancel"))
  1135. self.cancel_tool_from_db.hide()
  1136. hlay = QtWidgets.QHBoxLayout()
  1137. tree_layout.addLayout(hlay)
  1138. hlay.addWidget(self.add_tool_from_db)
  1139. hlay.addWidget(self.cancel_tool_from_db)
  1140. # hlay.addStretch()
  1141. # ############################ FINSIHED GUI ###################################
  1142. # #############################################################################
  1143. def confirmation_message(self, accepted, minval, maxval):
  1144. if accepted is False:
  1145. self.app.inform[str, bool].emit('[WARNING_NOTCL] %s: [%.*f, %.*f]' % (_("Edited value is out of range"),
  1146. self.decimals,
  1147. minval,
  1148. self.decimals,
  1149. maxval), False)
  1150. else:
  1151. self.app.inform[str, bool].emit('[success] %s' % _("Edited value is within limits."), False)
  1152. def confirmation_message_int(self, accepted, minval, maxval):
  1153. if accepted is False:
  1154. self.app.inform[str, bool].emit('[WARNING_NOTCL] %s: [%d, %d]' %
  1155. (_("Edited value is out of range"), minval, maxval), False)
  1156. else:
  1157. self.app.inform[str, bool].emit('[success] %s' % _("Edited value is within limits."), False)
  1158. class ToolsDB2(QtWidgets.QWidget):
  1159. mark_tools_rows = QtCore.pyqtSignal()
  1160. def __init__(self, app, callback_on_tool_request, parent=None):
  1161. super(ToolsDB2, self).__init__(parent)
  1162. self.app = app
  1163. self.app_ui = self.app.ui
  1164. self.decimals = self.app.decimals
  1165. self.on_tool_request = callback_on_tool_request
  1166. self.tools_db_changed_flag = False
  1167. '''
  1168. dict to hold all the tools in the Tools DB
  1169. format:
  1170. {
  1171. tool_id: {
  1172. 'name': 'new_tool'
  1173. 'tooldia': self.app.defaults["geometry_cnctooldia"]
  1174. 'offset': 'Path'
  1175. 'offset_value': 0.0
  1176. 'type': 'Rough',
  1177. 'tool_type': 'C1'
  1178. 'data': dict()
  1179. }
  1180. }
  1181. '''
  1182. self.db_tool_dict = {}
  1183. self.old_color = QtGui.QColor('black')
  1184. # ##############################################################################
  1185. # ##############################################################################
  1186. # TOOLS DATABASE UI
  1187. # ##############################################################################
  1188. # ##############################################################################
  1189. layout = QtWidgets.QGridLayout()
  1190. layout.setColumnStretch(0, 0)
  1191. layout.setColumnStretch(1, 1)
  1192. self.setLayout(layout)
  1193. self.ui = ToolsDB2UI(app=self.app, grid_layout=layout)
  1194. # ##############################################################################
  1195. # ##############################################################################
  1196. # ########## SETUP THE DICTIONARIES THAT HOLD THE WIDGETS #####################
  1197. # ##############################################################################
  1198. # ##############################################################################
  1199. self.form_fields = {
  1200. "tool_target": self.ui.tool_op_combo,
  1201. "tol_min": self.ui.tol_min_entry,
  1202. "tol_max": self.ui.tol_max_entry,
  1203. "name": self.ui.name_entry,
  1204. "tooldia": self.ui.dia_entry,
  1205. # Milling
  1206. "tool_type": self.ui.mill_shape_combo,
  1207. "cutz": self.ui.mill_cutz_entry,
  1208. "multidepth": self.ui.mill_multidepth_cb,
  1209. "depthperpass": self.ui.mill_multidepth_entry,
  1210. "travelz": self.ui.mill_travelz_entry,
  1211. "feedrate": self.ui.mill_frxy_entry,
  1212. "feedrate_z": self.ui.mill_frz_entry,
  1213. "spindlespeed": self.ui.mill_spindle_entry,
  1214. "dwell": self.ui.mill_dwell_cb,
  1215. "dwelltime": self.ui.mill_dwelltime_entry,
  1216. "type": self.ui.mill_type_combo,
  1217. "offset": self.ui.mill_tooloffset_combo,
  1218. "offset_value": self.ui.mill_custom_offset_entry,
  1219. "vtipdia": self.ui.mill_vdia_entry,
  1220. "vtipangle": self.ui.mill_vangle_entry,
  1221. "feedrate_rapid": self.ui.mill_frapids_entry,
  1222. "extracut": self.ui.mill_ecut_cb,
  1223. "extracut_length": self.ui.mill_ecut_length_entry,
  1224. # NCC
  1225. "tools_ncc_operation": self.ui.ncc_op_radio,
  1226. "tools_ncc_milling_type": self.ui.ncc_milling_type_radio,
  1227. "tools_ncc_overlap": self.ui.ncc_overlap_entry,
  1228. "tools_ncc_margin": self.ui.ncc_margin_entry,
  1229. "tools_ncc_method": self.ui.ncc_method_combo,
  1230. "tools_ncc_connect": self.ui.ncc_connect_cb,
  1231. "tools_ncc_contour": self.ui.ncc_contour_cb,
  1232. "tools_ncc_offset_choice": self.ui.ncc_choice_offset_cb,
  1233. "tools_ncc_offset_value": self.ui.ncc_offset_spinner,
  1234. # Paint
  1235. "tools_paint_overlap": self.ui.paint_overlap_entry,
  1236. "tools_paint_offset": self.ui.paint_offset_entry,
  1237. "tools_paint_method": self.ui.paint_method_combo,
  1238. "tools_paint_connect": self.ui.path_connect_cb,
  1239. "tools_paint_contour": self.ui.paint_contour_cb,
  1240. # Isolation
  1241. "tools_iso_passes": self.ui.iso_passes_entry,
  1242. "tools_iso_overlap": self.ui.iso_overlap_entry,
  1243. "tools_iso_milling_type": self.ui.iso_milling_type_radio,
  1244. "tools_iso_follow": self.ui.iso_follow_cb,
  1245. "tools_iso_isotype": self.ui.iso_type_radio,
  1246. # Drilling
  1247. "tools_drill_cutz": self.ui.drill_cutz_entry,
  1248. "tools_drill_multidepth": self.ui.drill_mpass_cb,
  1249. "tools_drill_depthperpass": self.ui.drill_maxdepth_entry,
  1250. "tools_drill_travelz": self.ui.drill_travelz_entry,
  1251. "tools_drill_feedrate_z": self.ui.drill_feedrate_z_entry,
  1252. "tools_drill_feedrate_rapid": self.ui.drill_feedrate_rapid_entry,
  1253. "tools_drill_spindlespeed": self.ui.drill_spindlespeed_entry,
  1254. "tools_drill_dwell": self.ui.drill_dwell_cb,
  1255. "tools_drill_dwelltime": self.ui.drill_dwelltime_entry,
  1256. "tools_drill_offset": self.ui.drill_offset_entry,
  1257. "tools_drill_drill_slots": self.ui.drill_slots_cb,
  1258. "tools_drill_drill_overlap": self.ui.drill_overlap_entry,
  1259. "tools_drill_last_drill": self.ui.drill_last_drill_cb,
  1260. # Cutout
  1261. "tools_cutout_margin": self.ui.cutout_margin_entry,
  1262. "tools_cutout_gapsize": self.ui.cutout_gapsize,
  1263. "tools_cutout_gaps_ff": self.ui.cutout_gaps,
  1264. "tools_cutout_convexshape": self.ui.cutout_convex_box,
  1265. "tools_cutout_gap_type": self.ui.cutout_gaptype_radio,
  1266. "tools_cutout_gap_depth": self.ui.cutout_thin_depth_entry,
  1267. "tools_cutout_mb_dia": self.ui.cutout_mb_dia_entry,
  1268. "tools_cutout_mb_spacing": self.ui.cutout_mb_spacing_entry,
  1269. }
  1270. self.name2option = {
  1271. "gdb_tool_target": "tool_target",
  1272. "gdb_tol_min": "tol_min",
  1273. "gdb_tol_max": "tol_max",
  1274. "gdb_name": "name",
  1275. "gdb_dia": "tooldia",
  1276. # Milling
  1277. "gdb_shape": "tool_type",
  1278. "gdb_cutz": "cutz",
  1279. "gdb_multidepth": "multidepth",
  1280. "gdb_multidepth_entry": "depthperpass",
  1281. "gdb_travelz": "travelz",
  1282. "gdb_frxy": "feedrate",
  1283. "gdb_frz": "feedrate_z",
  1284. "gdb_spindle": "spindlespeed",
  1285. "gdb_dwell": "dwell",
  1286. "gdb_dwelltime": "dwelltime",
  1287. "gdb_type": "type",
  1288. "gdb_tool_offset": "offset",
  1289. "gdb_custom_offset": "offset_value",
  1290. "gdb_vdia": "vtipdia",
  1291. "gdb_vangle": "vtipangle",
  1292. "gdb_frapids": "feedrate_rapid",
  1293. "gdb_ecut": "extracut",
  1294. "gdb_ecut_length": "extracut_length",
  1295. # NCC
  1296. "gdb_n_operation": "tools_ncc_operation",
  1297. "gdb_n_overlap": "tools_ncc_overlap",
  1298. "gdb_n_margin": "tools_ncc_margin",
  1299. "gdb_n_method": "tools_ncc_method",
  1300. "gdb_n_connect": "tools_ncc_connect",
  1301. "gdb_n_contour": "tools_ncc_contour",
  1302. "gdb_n_offset": "tools_ncc_offset_choice",
  1303. "gdb_n_offset_value": "tools_ncc_offset_value",
  1304. "gdb_n_milling_type": "tools_ncc_milling_type",
  1305. # Paint
  1306. 'gdb_p_overlap': "tools_paint_overlap",
  1307. 'gdb_p_offset': "tools_paint_offset",
  1308. 'gdb_p_method': "tools_paint_method",
  1309. 'gdb_p_connect': "tools_paint_connect",
  1310. 'gdb_p_contour': "tools_paint_contour",
  1311. # Isolation
  1312. "gdb_i_passes": "tools_iso_passes",
  1313. "gdb_i_overlap": "tools_iso_overlap",
  1314. "gdb_i_milling_type": "tools_iso_milling_type",
  1315. "gdb_i_follow": "tools_iso_follow",
  1316. "gdb_i_iso_type": "tools_iso_isotype",
  1317. # Drilling
  1318. "gdb_e_cutz": "tools_drill_cutz",
  1319. "gdb_e_multidepth": "tools_drill_multidepth",
  1320. "gdb_e_depthperpass": "tools_drill_depthperpass",
  1321. "gdb_e_travelz": "tools_drill_travelz",
  1322. "gdb_e_feedratez": "tools_drill_feedrate_z",
  1323. "gdb_e_fr_rapid": "tools_drill_feedrate_rapid",
  1324. "gdb_e_spindlespeed": "tools_drill_spindlespeed",
  1325. "gdb_e_dwell": "tools_drill_dwell",
  1326. "gdb_e_dwelltime": "tools_drill_dwelltime",
  1327. "gdb_e_offset": "tools_drill_offset",
  1328. "gdb_e_drill_slots": "tools_drill_drill_slots",
  1329. "gdb_e_drill_slots_over": "tools_drill_drill_overlap",
  1330. "gdb_e_drill_last_drill": "tools_drill_last_drill",
  1331. # Cutout
  1332. "gdb_ct_margin": "tools_cutout_margin",
  1333. "gdb_ct_gapsize": "tools_cutout_gapsize",
  1334. "gdb_ct_gaps": "tools_cutout_gaps_ff",
  1335. "gdb_ct_convex": "tools_cutout_convexshape",
  1336. "gdb_ct_gap_type": "tools_cutout_gap_type",
  1337. "gdb_ct_gap_depth": "tools_cutout_gap_depth",
  1338. "gdb_ct_mb_dia": "tools_cutout_mb_dia",
  1339. "gdb_ct_mb_spacing": "tools_cutout_mb_spacing"
  1340. }
  1341. self.current_toolid = None
  1342. # variable to show if double clicking and item will trigger adding a tool from DB
  1343. self.ok_to_add = False
  1344. # ##############################################################################
  1345. # ######################## SIGNALS #############################################
  1346. # ##############################################################################
  1347. self.ui.add_entry_btn.clicked.connect(self.on_tool_add)
  1348. self.ui.remove_entry_btn.clicked.connect(self.on_tool_delete)
  1349. self.ui.export_db_btn.clicked.connect(self.on_export_tools_db_file)
  1350. self.ui.import_db_btn.clicked.connect(self.on_import_tools_db_file)
  1351. self.ui.save_db_btn.clicked.connect(self.on_save_db_btn_click)
  1352. # closebtn.clicked.connect(self.accept)
  1353. self.ui.add_tool_from_db.clicked.connect(self.on_tool_requested_from_app)
  1354. self.ui.cancel_tool_from_db.clicked.connect(self.on_cancel_tool)
  1355. # self.ui.tree_widget.selectionModel().selectionChanged.connect(self.on_list_selection_change)
  1356. self.ui.tree_widget.currentItemChanged.connect(self.on_list_selection_change)
  1357. self.ui.tree_widget.itemChanged.connect(self.on_list_item_edited)
  1358. self.ui.tree_widget.customContextMenuRequested.connect(self.on_menu_request)
  1359. self.ui.tree_widget.itemDoubleClicked.connect(self.on_item_double_clicked)
  1360. self.ui.tool_op_combo.currentIndexChanged.connect(self.on_tool_target_changed)
  1361. self.setup_db_ui()
  1362. def on_menu_request(self, pos):
  1363. menu = QtWidgets.QMenu()
  1364. add_tool = menu.addAction(QtGui.QIcon(self.app.resource_location + '/plus16.png'), _("Add to DB"))
  1365. add_tool.triggered.connect(self.on_tool_add)
  1366. copy_tool = menu.addAction(QtGui.QIcon(self.app.resource_location + '/copy16.png'), _("Copy from DB"))
  1367. copy_tool.triggered.connect(self.on_tool_copy)
  1368. delete_tool = menu.addAction(QtGui.QIcon(self.app.resource_location + '/delete32.png'), _("Delete from DB"))
  1369. delete_tool.triggered.connect(self.on_tool_delete)
  1370. # sep = menu.addSeparator()
  1371. save_changes = menu.addAction(QtGui.QIcon(self.app.resource_location + '/save_as.png'), _("Save changes"))
  1372. save_changes.triggered.connect(self.on_save_changes)
  1373. # tree_item = self.ui.tree_widget.itemAt(pos)
  1374. menu.exec(self.ui.tree_widget.viewport().mapToGlobal(pos))
  1375. def on_save_changes(self):
  1376. widget_name = self.app_ui.plot_tab_area.currentWidget().objectName()
  1377. if widget_name == 'database_tab':
  1378. # Tools DB saved, update flag
  1379. self.app.tools_db_changed_flag = False
  1380. self.app.tools_db_tab.on_save_tools_db()
  1381. def on_item_double_clicked(self, item, column):
  1382. if column == 0 and self.ok_to_add is True:
  1383. self.ok_to_add = False
  1384. self.on_tool_requested_from_app()
  1385. def on_list_selection_change(self, current, previous):
  1386. self.ui_disconnect()
  1387. self.current_toolid = int(current.text(0))
  1388. self.storage_to_form(self.db_tool_dict[current.text(0)])
  1389. self.ui_connect()
  1390. def on_list_item_edited(self, item, column):
  1391. if column == 0:
  1392. return
  1393. self.ui.name_entry.set_value(item.text(1))
  1394. def storage_to_form(self, dict_storage):
  1395. self.ui_disconnect()
  1396. for form_key in self.form_fields:
  1397. for storage_key in dict_storage:
  1398. if form_key == storage_key:
  1399. try:
  1400. self.form_fields[form_key].set_value(dict_storage[form_key])
  1401. except Exception as e:
  1402. print(str(e))
  1403. if storage_key == 'data':
  1404. for data_key in dict_storage[storage_key]:
  1405. if form_key == data_key:
  1406. try:
  1407. self.form_fields[form_key].set_value(dict_storage['data'][data_key])
  1408. except Exception as e:
  1409. print(str(e))
  1410. self.ui_connect()
  1411. def form_to_storage(self, tool):
  1412. self.ui_disconnect()
  1413. widget_changed = self.sender()
  1414. wdg_objname = widget_changed.objectName()
  1415. option_changed = self.name2option[wdg_objname]
  1416. tooluid_item = int(tool)
  1417. for tooluid_key, tooluid_val in self.db_tool_dict.items():
  1418. if int(tooluid_key) == tooluid_item:
  1419. new_option_value = self.form_fields[option_changed].get_value()
  1420. if option_changed in tooluid_val:
  1421. tooluid_val[option_changed] = new_option_value
  1422. if option_changed in tooluid_val['data']:
  1423. tooluid_val['data'][option_changed] = new_option_value
  1424. self.ui_connect()
  1425. def setup_db_ui(self):
  1426. # set the old color for the Tools Database Tab
  1427. for idx in range(self.app.ui.plot_tab_area.count()):
  1428. if self.app.ui.plot_tab_area.tabText(idx) == _("Tools Database"):
  1429. self.old_color = self.app.ui.plot_tab_area.tabBar.tabTextColor(idx)
  1430. filename = self.app.tools_database_path()
  1431. # load the database tools from the file
  1432. try:
  1433. with open(filename) as f:
  1434. tools = f.read()
  1435. except IOError:
  1436. self.app.log.error("Could not load tools DB file.")
  1437. self.app.inform.emit('[ERROR] %s' % _("Could not load Tools DB file."))
  1438. return
  1439. try:
  1440. self.db_tool_dict = json.loads(tools)
  1441. except Exception:
  1442. e = sys.exc_info()[0]
  1443. self.app.log.error(str(e))
  1444. self.app.inform.emit('[ERROR] %s' % _("Failed to parse Tools DB file."))
  1445. return
  1446. self.app.inform.emit('[success] %s: %s' % (_("Loaded Tools DB from"), filename))
  1447. self.build_db_ui()
  1448. def build_db_ui(self):
  1449. self.ui_disconnect()
  1450. nr_crt = 0
  1451. parent = self.ui.tree_widget
  1452. self.ui.tree_widget.blockSignals(True)
  1453. self.ui.tree_widget.clear()
  1454. self.ui.tree_widget.blockSignals(False)
  1455. for toolid, dict_val in self.db_tool_dict.items():
  1456. row = nr_crt
  1457. nr_crt += 1
  1458. t_name = dict_val['name']
  1459. try:
  1460. # self.add_tool_table_line(row, name=t_name, tooldict=dict_val)
  1461. self.ui.tree_widget.blockSignals(True)
  1462. try:
  1463. self.ui.tree_widget.addParentEditable(parent=parent, title=[str(row+1), t_name], editable=True)
  1464. except Exception as e:
  1465. print('FlatCAMCoomn.ToolDB2.build_db_ui() -> ', str(e))
  1466. self.ui.tree_widget.blockSignals(False)
  1467. except Exception as e:
  1468. self.app.log.debug("ToolDB.build_db_ui.add_tool_table_line() --> %s" % str(e))
  1469. if self.current_toolid is None or self.current_toolid < 1:
  1470. if self.db_tool_dict:
  1471. self.storage_to_form(self.db_tool_dict['1'])
  1472. # Enable appGUI
  1473. try:
  1474. self.on_tool_target_changed(val=self.db_tool_dict['1']['data']['tool_target'])
  1475. except KeyError:
  1476. self.on_tool_target_changed(val=_("General"))
  1477. self.ui.tree_widget.setCurrentItem(self.ui.tree_widget.topLevelItem(0))
  1478. # self.ui.tree_widget.setFocus()
  1479. else:
  1480. # Disable appGUI
  1481. self.ui.tool_description_box.show()
  1482. self.ui.milling_box.show()
  1483. self.ui.ncc_box.show()
  1484. self.ui.paint_box.show()
  1485. self.ui.iso_box.show()
  1486. self.ui.drill_box.show()
  1487. self.ui.cutout_box.show()
  1488. self.ui.tool_description_box.setEnabled(False)
  1489. self.ui.milling_box.setEnabled(False)
  1490. self.ui.ncc_box.setEnabled(False)
  1491. self.ui.paint_box.setEnabled(False)
  1492. self.ui.iso_box.setEnabled(False)
  1493. self.ui.drill_box.setEnabled(False)
  1494. self.ui.cutout_box.setEnabled(False)
  1495. else:
  1496. self.storage_to_form(self.db_tool_dict[str(self.current_toolid)])
  1497. self.ui_connect()
  1498. def on_tool_target_changed(self, index=None, val=None):
  1499. if val is None:
  1500. tool_target = self.ui.tool_op_combo.get_value()
  1501. else:
  1502. tool_target = val
  1503. self.ui.tool_description_box.setEnabled(True)
  1504. if self.db_tool_dict:
  1505. if tool_target == 0: # _("General")
  1506. self.ui.milling_box.setEnabled(True)
  1507. self.ui.ncc_box.setEnabled(True)
  1508. self.ui.paint_box.setEnabled(True)
  1509. self.ui.iso_box.setEnabled(True)
  1510. self.ui.drill_box.setEnabled(True)
  1511. self.ui.cutout_box.setEnabled(True)
  1512. self.ui.milling_box.show()
  1513. self.ui.ncc_box.show()
  1514. self.ui.paint_box.show()
  1515. self.ui.iso_box.show()
  1516. self.ui.drill_box.show()
  1517. self.ui.cutout_box.show()
  1518. else:
  1519. self.ui.milling_box.hide()
  1520. self.ui.ncc_box.hide()
  1521. self.ui.paint_box.hide()
  1522. self.ui.iso_box.hide()
  1523. self.ui.drill_box.hide()
  1524. self.ui.cutout_box.hide()
  1525. if tool_target == 1: # _("Milling")
  1526. self.ui.milling_box.setEnabled(True)
  1527. self.ui.milling_box.show()
  1528. if tool_target == 2: # _("Drilling")
  1529. self.ui.drill_box.setEnabled(True)
  1530. self.ui.drill_box.show()
  1531. if tool_target == 3: # _("Isolation")
  1532. self.ui.iso_box.setEnabled(True)
  1533. self.ui.iso_box.show()
  1534. self.ui.milling_box.setEnabled(True)
  1535. self.ui.milling_box.show()
  1536. if tool_target == 4: # _("Paint")
  1537. self.ui.paint_box.setEnabled(True)
  1538. self.ui.paint_box.show()
  1539. self.ui.milling_box.setEnabled(True)
  1540. self.ui.milling_box.show()
  1541. if tool_target == 5: # _("NCC")
  1542. self.ui.ncc_box.setEnabled(True)
  1543. self.ui.ncc_box.show()
  1544. self.ui.milling_box.setEnabled(True)
  1545. self.ui.milling_box.show()
  1546. if tool_target == 6: # _("Cutout")
  1547. self.ui.cutout_box.setEnabled(True)
  1548. self.ui.cutout_box.show()
  1549. self.ui.milling_box.setEnabled(True)
  1550. self.ui.milling_box.show()
  1551. def on_tool_add(self):
  1552. """
  1553. Add a tool in the DB Tool Table
  1554. :return: None
  1555. """
  1556. default_data = {}
  1557. default_data.update({
  1558. "plot": True,
  1559. "tool_target": 0, # _("General")
  1560. "tol_min": 0.0,
  1561. "tol_max": 0.0,
  1562. # Milling
  1563. "cutz": float(self.app.defaults["geometry_cutz"]),
  1564. "multidepth": self.app.defaults["geometry_multidepth"],
  1565. "depthperpass": float(self.app.defaults["geometry_depthperpass"]),
  1566. "vtipdia": float(self.app.defaults["geometry_vtipdia"]),
  1567. "vtipangle": float(self.app.defaults["geometry_vtipangle"]),
  1568. "travelz": float(self.app.defaults["geometry_travelz"]),
  1569. "feedrate": float(self.app.defaults["geometry_feedrate"]),
  1570. "feedrate_z": float(self.app.defaults["geometry_feedrate_z"]),
  1571. "feedrate_rapid": float(self.app.defaults["geometry_feedrate_rapid"]),
  1572. "spindlespeed": self.app.defaults["geometry_spindlespeed"],
  1573. "dwell": self.app.defaults["geometry_dwell"],
  1574. "dwelltime": float(self.app.defaults["geometry_dwelltime"]),
  1575. "ppname_g": self.app.defaults["geometry_ppname_g"],
  1576. "extracut": self.app.defaults["geometry_extracut"],
  1577. "extracut_length": float(self.app.defaults["geometry_extracut_length"]),
  1578. "toolchange": self.app.defaults["geometry_toolchange"],
  1579. "toolchangexy": self.app.defaults["geometry_toolchangexy"],
  1580. "toolchangez": float(self.app.defaults["geometry_toolchangez"]),
  1581. "startz": self.app.defaults["geometry_startz"],
  1582. "endz": float(self.app.defaults["geometry_endz"]),
  1583. "endxy": self.app.defaults["geometry_endxy"],
  1584. "search_time": int(self.app.defaults["geometry_search_time"]),
  1585. "z_pdepth": float(self.app.defaults["geometry_z_pdepth"]),
  1586. "f_plunge": float(self.app.defaults["geometry_f_plunge"]),
  1587. "spindledir": self.app.defaults["geometry_spindledir"],
  1588. "optimization_type": self.app.defaults["geometry_optimization_type"],
  1589. "feedrate_probe": self.app.defaults["geometry_feedrate_probe"],
  1590. "segx": self.app.defaults["geometry_segx"],
  1591. "segy": self.app.defaults["geometry_segy"],
  1592. "area_exclusion": self.app.defaults["geometry_area_exclusion"],
  1593. "area_shape": self.app.defaults["geometry_area_shape"],
  1594. "area_strategy": self.app.defaults["geometry_area_strategy"],
  1595. "area_overz": self.app.defaults["geometry_area_overz"],
  1596. "polish": self.app.defaults["geometry_polish"],
  1597. "polish_dia": self.app.defaults["geometry_polish_dia"],
  1598. "polish_pressure": self.app.defaults["geometry_polish_pressure"],
  1599. "polish_travelz": self.app.defaults["geometry_polish_travelz"],
  1600. "polish_margin": self.app.defaults["geometry_polish_margin"],
  1601. "polish_overlap": self.app.defaults["geometry_polish_overlap"],
  1602. "polish_method": self.app.defaults["geometry_polish_method"],
  1603. # NCC
  1604. "tools_ncc_operation": self.app.defaults["tools_ncc_operation"],
  1605. "tools_ncc_milling_type": self.app.defaults["tools_ncc_milling_type"],
  1606. "tools_ncc_overlap": float(self.app.defaults["tools_ncc_overlap"]),
  1607. "tools_ncc_margin": float(self.app.defaults["tools_ncc_margin"]),
  1608. "tools_ncc_method": self.app.defaults["tools_ncc_method"],
  1609. "tools_ncc_connect": self.app.defaults["tools_ncc_connect"],
  1610. "tools_ncc_contour": self.app.defaults["tools_ncc_contour"],
  1611. "tools_ncc_offset_choice": self.app.defaults["tools_ncc_offset_choice"],
  1612. "tools_ncc_offset_value": float(self.app.defaults["tools_ncc_offset_value"]),
  1613. # Paint
  1614. "tools_paint_overlap": float(self.app.defaults["tools_paint_overlap"]),
  1615. "tools_paint_offset": float(self.app.defaults["tools_paint_offset"]),
  1616. "tools_paint_method": self.app.defaults["tools_paint_method"],
  1617. "tools_paint_connect": self.app.defaults["tools_paint_connect"],
  1618. "tools_paint_contour": self.app.defaults["tools_paint_contour"],
  1619. # Isolation
  1620. "tools_iso_passes": int(self.app.defaults["tools_iso_passes"]),
  1621. "tools_iso_overlap": float(self.app.defaults["tools_iso_overlap"]),
  1622. "tools_iso_milling_type": self.app.defaults["tools_iso_milling_type"],
  1623. "tools_iso_follow": self.app.defaults["tools_iso_follow"],
  1624. "tools_iso_isotype": self.app.defaults["tools_iso_isotype"],
  1625. # Drilling
  1626. "tools_drill_cutz": float(self.app.defaults["tools_drill_cutz"]),
  1627. "tools_drill_multidepth": self.app.defaults["tools_drill_multidepth"],
  1628. "tools_drill_depthperpass": float(self.app.defaults["tools_drill_depthperpass"]),
  1629. "tools_drill_travelz": float(self.app.defaults["tools_drill_travelz"]),
  1630. "tools_drill_feedrate_z": float(self.app.defaults["tools_drill_feedrate_z"]),
  1631. "tools_drill_feedrate_rapid": float(self.app.defaults["tools_drill_feedrate_rapid"]),
  1632. "tools_drill_spindlespeed": float(self.app.defaults["tools_drill_spindlespeed"]),
  1633. "tools_drill_dwell": self.app.defaults["tools_drill_dwell"],
  1634. "tools_drill_offset": float(self.app.defaults["tools_drill_offset"]),
  1635. "tools_drill_drill_slots": self.app.defaults["tools_drill_drill_slots"],
  1636. "tools_drill_drill_overlap": float(self.app.defaults["tools_drill_drill_overlap"]),
  1637. "tools_drill_last_drill": self.app.defaults["tools_drill_last_drill"],
  1638. # Cutout
  1639. "tools_cutout_margin": float(self.app.defaults["tools_cutout_margin"]),
  1640. "tools_cutout_gapsize": float(self.app.defaults["tools_cutout_gapsize"]),
  1641. "tools_cutout_gaps_ff": self.app.defaults["tools_cutout_gaps_ff"],
  1642. "tools_cutout_convexshape": self.app.defaults["tools_cutout_convexshape"],
  1643. "tools_cutout_gap_type": self.app.defaults["tools_cutout_gap_type"],
  1644. "tools_cutout_gap_depth": float(self.app.defaults["tools_cutout_gap_depth"]),
  1645. "tools_cutout_mb_dia": float(self.app.defaults["tools_cutout_mb_dia"]),
  1646. "tools_cutout_mb_spacing": float(self.app.defaults["tools_cutout_mb_spacing"])
  1647. })
  1648. temp = []
  1649. for k, v in self.db_tool_dict.items():
  1650. if "new_tool_" in v['name']:
  1651. temp.append(float(v['name'].rpartition('_')[2]))
  1652. if temp:
  1653. new_name = "new_tool_%d" % int(max(temp) + 1)
  1654. else:
  1655. new_name = "new_tool_1"
  1656. dict_elem = {'name': new_name}
  1657. if type(self.app.defaults["geometry_cnctooldia"]) == float:
  1658. dict_elem['tooldia'] = self.app.defaults["geometry_cnctooldia"]
  1659. else:
  1660. try:
  1661. tools_string = self.app.defaults["geometry_cnctooldia"].split(",")
  1662. tools_diameters = [eval(a) for a in tools_string if a != '']
  1663. dict_elem['tooldia'] = tools_diameters[0] if tools_diameters else 0.0
  1664. except Exception as e:
  1665. self.app.log.debug("ToolDB.on_tool_add() --> %s" % str(e))
  1666. return
  1667. dict_elem['offset'] = 'Path'
  1668. dict_elem['offset_value'] = 0.0
  1669. dict_elem['type'] = 'Rough'
  1670. dict_elem['tool_type'] = 'C1'
  1671. dict_elem['data'] = default_data
  1672. new_toolid = len(self.db_tool_dict) + 1
  1673. self.db_tool_dict[str(new_toolid)] = deepcopy(dict_elem)
  1674. # add the new entry to the Tools DB table
  1675. self.update_storage()
  1676. self.build_db_ui()
  1677. # select the last Tree item just added
  1678. nr_items = self.ui.tree_widget.topLevelItemCount()
  1679. if nr_items:
  1680. last_item = self.ui.tree_widget.topLevelItem(nr_items - 1)
  1681. self.ui.tree_widget.setCurrentItem(last_item)
  1682. last_item.setSelected(True)
  1683. self.on_tool_target_changed(val=dict_elem['data']['tool_target'])
  1684. self.app.inform.emit('[success] %s' % _("Tool added to DB."))
  1685. def on_tool_copy(self):
  1686. """
  1687. Copy a selection of Tools in the Tools DB table
  1688. :return:
  1689. """
  1690. new_tool_id = len(self.db_tool_dict)
  1691. for item in self.ui.tree_widget.selectedItems():
  1692. old_tool_id = item.data(0, QtCore.Qt.DisplayRole)
  1693. for toolid, dict_val in list(self.db_tool_dict.items()):
  1694. if int(old_tool_id) == int(toolid):
  1695. new_tool_id += 1
  1696. new_key = str(new_tool_id)
  1697. self.db_tool_dict.update({
  1698. new_key: deepcopy(dict_val)
  1699. })
  1700. self.current_toolid = new_tool_id
  1701. self.update_storage()
  1702. self.build_db_ui()
  1703. # select the last Tree item just added
  1704. nr_items = self.ui.tree_widget.topLevelItemCount()
  1705. if nr_items:
  1706. last_item = self.ui.tree_widget.topLevelItem(nr_items - 1)
  1707. self.ui.tree_widget.setCurrentItem(last_item)
  1708. last_item.setSelected(True)
  1709. self.on_tools_db_edited()
  1710. self.app.inform.emit('[success] %s' % _("Tool copied from Tools DB."))
  1711. def on_tool_delete(self):
  1712. """
  1713. Delete a selection of Tools in the Tools DB table
  1714. :return:
  1715. """
  1716. for item in self.ui.tree_widget.selectedItems():
  1717. toolname_to_remove = item.data(0, QtCore.Qt.DisplayRole)
  1718. for toolid, dict_val in list(self.db_tool_dict.items()):
  1719. if int(toolname_to_remove) == int(toolid):
  1720. # remove from the storage
  1721. self.db_tool_dict.pop(toolid, None)
  1722. self.current_toolid -= 1
  1723. self.update_storage()
  1724. self.build_db_ui()
  1725. # select the first Tree item
  1726. nr_items = self.ui.tree_widget.topLevelItemCount()
  1727. if nr_items:
  1728. first_item = self.ui.tree_widget.topLevelItem(0)
  1729. self.ui.tree_widget.setCurrentItem(first_item)
  1730. first_item.setSelected(True)
  1731. self.app.inform.emit('[success] %s' % _("Tool removed from Tools DB."))
  1732. def on_export_tools_db_file(self):
  1733. self.app.defaults.report_usage("on_export_tools_db_file")
  1734. self.app.log.debug("on_export_tools_db_file()")
  1735. date = str(datetime.today()).rpartition('.')[0]
  1736. date = ''.join(c for c in date if c not in ':-')
  1737. date = date.replace(' ', '_')
  1738. filter__ = "Text File (*.TXT);;All Files (*.*)"
  1739. filename, _f = FCFileSaveDialog.get_saved_filename(
  1740. caption=_("Export Tools Database"),
  1741. directory='{l_save}/FlatCAM_{n}_{date}'.format(l_save=str(self.app.get_last_save_folder()),
  1742. n=_("Tools_Database"),
  1743. date=date),
  1744. ext_filter=filter__)
  1745. filename = str(filename)
  1746. if filename == "":
  1747. self.app.inform.emit('[WARNING_NOTCL] %s' % _("Cancelled."))
  1748. return
  1749. else:
  1750. try:
  1751. f = open(filename, 'w')
  1752. f.close()
  1753. except PermissionError:
  1754. self.app.inform.emit('[WARNING] %s' %
  1755. _("Permission denied, saving not possible.\n"
  1756. "Most likely another app is holding the file open and not accessible."))
  1757. return
  1758. except IOError:
  1759. self.app.log.debug('Creating a new Tools DB file ...')
  1760. f = open(filename, 'w')
  1761. f.close()
  1762. except Exception:
  1763. e = sys.exc_info()[0]
  1764. self.app.log.error("Could not load Tools DB file.")
  1765. self.app.log.error(str(e))
  1766. self.app.inform.emit('[ERROR_NOTCL] %s' % _("Could not load Tools DB file."))
  1767. return
  1768. # Save update options
  1769. try:
  1770. # Save Tools DB in a file
  1771. try:
  1772. with open(filename, "w") as f:
  1773. json.dump(self.db_tool_dict, f, default=to_dict, indent=2)
  1774. except Exception as e:
  1775. self.app.log.debug("App.on_save_tools_db() --> %s" % str(e))
  1776. self.app.inform.emit('[ERROR_NOTCL] %s' % _("Failed to write Tools DB to file."))
  1777. return
  1778. except Exception:
  1779. self.app.inform.emit('[ERROR_NOTCL] %s' % _("Failed to write Tools DB to file."))
  1780. return
  1781. self.app.inform.emit('[success] %s: %s' % (_("Exported Tools DB to"), filename))
  1782. def on_import_tools_db_file(self):
  1783. self.app.defaults.report_usage("on_import_tools_db_file")
  1784. self.app.log.debug("on_import_tools_db_file()")
  1785. filter__ = "Text File (*.TXT);;All Files (*.*)"
  1786. filename, _f = QtWidgets.QFileDialog.getOpenFileName(caption=_("Import FlatCAM Tools DB"), filter=filter__)
  1787. if filename == "":
  1788. self.app.inform.emit('[WARNING_NOTCL] %s' % _("Cancelled."))
  1789. else:
  1790. try:
  1791. with open(filename) as f:
  1792. tools_in_db = f.read()
  1793. except IOError:
  1794. self.app.log.error("Could not load Tools DB file.")
  1795. self.app.inform.emit('[ERROR_NOTCL] %s' % _("Could not load Tools DB file."))
  1796. return
  1797. try:
  1798. self.db_tool_dict = json.loads(tools_in_db)
  1799. except Exception:
  1800. e = sys.exc_info()[0]
  1801. self.app.log.error(str(e))
  1802. self.app.inform.emit('[ERROR] %s' % _("Failed to parse Tools DB file."))
  1803. return
  1804. self.app.inform.emit('[success] %s: %s' % (_("Loaded Tools DB from"), filename))
  1805. self.build_db_ui()
  1806. self.update_storage()
  1807. def on_save_tools_db(self, silent=False):
  1808. self.app.log.debug("ToolsDB.on_save_button() --> Saving Tools Database to file.")
  1809. filename = self.app.tools_database_path()
  1810. # Preferences save, update the color of the Tools DB Tab text
  1811. for idx in range(self.app_ui.plot_tab_area.count()):
  1812. if self.app_ui.plot_tab_area.tabText(idx) == _("Tools Database"):
  1813. self.app_ui.plot_tab_area.tabBar.setTabTextColor(idx, self.old_color)
  1814. self.ui.save_db_btn.setStyleSheet("")
  1815. # clean the dictionary and leave only keys of interest
  1816. for tool_id in self.db_tool_dict.keys():
  1817. if self.db_tool_dict[tool_id]['data']['tool_target'] != _('General'):
  1818. continue
  1819. if self.db_tool_dict[tool_id]['data']['tool_target'] == _('Milling'):
  1820. for k in list(self.db_tool_dict[tool_id]['data'].keys()):
  1821. if str(k).startswith('tools_'):
  1822. self.db_tool_dict[tool_id]['data'].pop(k, None)
  1823. if self.db_tool_dict[tool_id]['data']['tool_target'] == _('Drilling'):
  1824. for k in list(self.db_tool_dict[tool_id]['data'].keys()):
  1825. if str(k).startswith('tools_'):
  1826. if str(k).startswith('tools_drill') or str(k).startswith('tools_mill'):
  1827. pass
  1828. else:
  1829. self.db_tool_dict[tool_id]['data'].pop(k, None)
  1830. if self.db_tool_dict[tool_id]['data']['tool_target'] == _('Isolation'):
  1831. for k in list(self.db_tool_dict[tool_id]['data'].keys()):
  1832. if str(k).startswith('tools_'):
  1833. if str(k).startswith('tools_iso') or str(k).startswith('tools_mill'):
  1834. pass
  1835. else:
  1836. self.db_tool_dict[tool_id]['data'].pop(k, None)
  1837. if self.db_tool_dict[tool_id]['data']['tool_target'] == _('Paint'):
  1838. for k in list(self.db_tool_dict[tool_id]['data'].keys()):
  1839. if str(k).startswith('tools_'):
  1840. if str(k).startswith('tools_paint') or str(k).startswith('tools_mill'):
  1841. pass
  1842. else:
  1843. self.db_tool_dict[tool_id]['data'].pop(k, None)
  1844. if self.db_tool_dict[tool_id]['data']['tool_target'] == _('NCC'):
  1845. for k in list(self.db_tool_dict[tool_id]['data'].keys()):
  1846. if str(k).startswith('tools_'):
  1847. if str(k).startswith('tools_ncc') or str(k).startswith('tools_mill'):
  1848. pass
  1849. else:
  1850. self.db_tool_dict[tool_id]['data'].pop(k, None)
  1851. if self.db_tool_dict[tool_id]['data']['tool_target'] == _('Cutout'):
  1852. for k in list(self.db_tool_dict[tool_id]['data'].keys()):
  1853. if str(k).startswith('tools_'):
  1854. if str(k).startswith('tools_cutout') or str(k).startswith('tools_mill'):
  1855. pass
  1856. else:
  1857. self.db_tool_dict[tool_id]['data'].pop(k, None)
  1858. # Save Tools DB in a file
  1859. try:
  1860. f = open(filename, "w")
  1861. json.dump(self.db_tool_dict, f, default=to_dict, indent=2)
  1862. f.close()
  1863. except Exception as e:
  1864. self.app.log.debug("ToolsDB.on_save_tools_db() --> %s" % str(e))
  1865. self.app.inform.emit('[ERROR_NOTCL] %s' % _("Failed to write Tools DB to file."))
  1866. return
  1867. if not silent:
  1868. self.app.inform.emit('[success] %s' % _("Saved Tools DB."))
  1869. def on_save_db_btn_click(self):
  1870. self.app.tools_db_changed_flag = False
  1871. self.on_save_tools_db()
  1872. def on_calculate_tooldia(self):
  1873. if self.ui.mill_shape_combo.get_value() == 'V':
  1874. tip_dia = float(self.ui.mill_vdia_entry.get_value())
  1875. half_tip_angle = float(self.ui.mill_vangle_entry.get_value()) / 2.0
  1876. cut_z = float(self.ui.mill_cutz_entry.get_value())
  1877. cut_z = -cut_z if cut_z < 0 else cut_z
  1878. # calculated tool diameter so the cut_z parameter is obeyed
  1879. tool_dia = tip_dia + (2 * cut_z * math.tan(math.radians(half_tip_angle)))
  1880. self.ui.dia_entry.set_value(tool_dia)
  1881. def ui_connect(self):
  1882. # make sure that we don't make multiple connections to the widgets
  1883. self.ui_disconnect()
  1884. self.ui.name_entry.editingFinished.connect(self.update_tree_name)
  1885. for key in self.form_fields:
  1886. wdg = self.form_fields[key]
  1887. # FCEntry
  1888. if isinstance(wdg, FCEntry):
  1889. wdg.textChanged.connect(self.update_storage)
  1890. # ComboBox
  1891. if isinstance(wdg, FCComboBox):
  1892. wdg.currentIndexChanged.connect(self.update_storage)
  1893. # CheckBox
  1894. if isinstance(wdg, FCCheckBox):
  1895. wdg.toggled.connect(self.update_storage)
  1896. # FCRadio
  1897. if isinstance(wdg, RadioSet):
  1898. wdg.activated_custom.connect(self.update_storage)
  1899. # SpinBox, DoubleSpinBox
  1900. if isinstance(wdg, FCSpinner) or isinstance(wdg, FCDoubleSpinner):
  1901. wdg.valueChanged.connect(self.update_storage)
  1902. # connect the calculate tooldia method to the controls
  1903. # if the tool shape is 'V' the tool dia will be calculated to obey Cut Z parameter
  1904. self.ui.mill_shape_combo.currentIndexChanged.connect(self.on_calculate_tooldia)
  1905. self.ui.mill_cutz_entry.valueChanged.connect(self.on_calculate_tooldia)
  1906. self.ui.mill_vdia_entry.valueChanged.connect(self.on_calculate_tooldia)
  1907. self.ui.mill_vangle_entry.valueChanged.connect(self.on_calculate_tooldia)
  1908. def ui_disconnect(self):
  1909. try:
  1910. self.ui.name_entry.editingFinished.disconnect(self.update_tree_name)
  1911. except (TypeError, AttributeError):
  1912. pass
  1913. try:
  1914. self.ui.mill_shape_combo.currentIndexChanged.disconnect(self.on_calculate_tooldia)
  1915. except (TypeError, AttributeError):
  1916. pass
  1917. try:
  1918. self.ui.mill_cutz_entry.valueChanged.disconnect(self.on_calculate_tooldia)
  1919. except (TypeError, AttributeError):
  1920. pass
  1921. try:
  1922. self.ui.mill_vdia_entry.valueChanged.disconnect(self.on_calculate_tooldia)
  1923. except (TypeError, AttributeError):
  1924. pass
  1925. try:
  1926. self.ui.mill_vangle_entry.valueChanged.disconnect(self.on_calculate_tooldia)
  1927. except (TypeError, AttributeError):
  1928. pass
  1929. for key in self.form_fields:
  1930. wdg = self.form_fields[key]
  1931. # FCEntry
  1932. if isinstance(wdg, FCEntry):
  1933. try:
  1934. wdg.textChanged.disconnect(self.update_storage)
  1935. except (TypeError, AttributeError):
  1936. pass
  1937. # ComboBox
  1938. if isinstance(wdg, FCComboBox):
  1939. try:
  1940. wdg.currentIndexChanged.disconnect(self.update_storage)
  1941. except (TypeError, AttributeError):
  1942. pass
  1943. # CheckBox
  1944. if isinstance(wdg, FCCheckBox):
  1945. try:
  1946. wdg.toggled.disconnect(self.update_storage)
  1947. except (TypeError, AttributeError):
  1948. pass
  1949. # FCRadio
  1950. if isinstance(wdg, RadioSet):
  1951. try:
  1952. wdg.activated_custom.disconnect(self.update_storage)
  1953. except (TypeError, AttributeError):
  1954. pass
  1955. # SpinBox, DoubleSpinBox
  1956. if isinstance(wdg, FCSpinner) or isinstance(wdg, FCDoubleSpinner):
  1957. try:
  1958. wdg.valueChanged.disconnect(self.update_storage)
  1959. except (TypeError, AttributeError):
  1960. pass
  1961. def update_tree_name(self):
  1962. val = self.ui.name_entry.get_value()
  1963. item = self.ui.tree_widget.currentItem()
  1964. if item is None:
  1965. return
  1966. # I'm setting the value for the second column (designated by 1) because first column holds the ID
  1967. # and second column holds the Name (this behavior is set in the build_ui method)
  1968. item.setData(1, QtCore.Qt.DisplayRole, val)
  1969. def update_storage(self):
  1970. """
  1971. Update the dictionary that is the storage of the tools 'database'
  1972. :return:
  1973. """
  1974. tool_id = str(self.current_toolid)
  1975. try:
  1976. wdg = self.sender()
  1977. assert isinstance(wdg, QtWidgets.QWidget) or isinstance(wdg, QtWidgets.QAction), \
  1978. "Expected a QWidget got %s" % type(wdg)
  1979. if wdg is None:
  1980. return
  1981. if isinstance(wdg, FCButton) or isinstance(wdg, QtWidgets.QAction):
  1982. # this is called when adding a new tool; no need to run the update below since that section is for
  1983. # when editing a tool
  1984. self.on_tools_db_edited()
  1985. return
  1986. wdg_name = wdg.objectName()
  1987. val = wdg.get_value()
  1988. except AttributeError as err:
  1989. self.app.log.debug("ToolsDB2.update_storage() -> %s" % str(err))
  1990. return
  1991. # #############################################################################################################
  1992. # #############################################################################################################
  1993. # ################ EDITING PARAMETERS IN A TOOL SECTION
  1994. # #############################################################################################################
  1995. # #############################################################################################################
  1996. # #############################################################################################################
  1997. # this might change in the future; it makes sense to change values at once for all tools
  1998. # for now change values only for one tool at once
  1999. sel_rows = []
  2000. for item in self.ui.tree_widget.selectedItems():
  2001. sel_rows.append(item.data(0, QtCore.Qt.DisplayRole))
  2002. len_sel_rows = len(sel_rows)
  2003. if len_sel_rows > 1:
  2004. msg = '[ERROR_NOTCL] %s: %s' % \
  2005. (_("To change tool properties select only one tool. Tools currently selected"), str(len_sel_rows))
  2006. self.app.inform.emit(msg)
  2007. old_value = self.db_tool_dict[tool_id]['data'][self.name2option[wdg_name]]
  2008. wdg.set_value(old_value)
  2009. wdg.clearFocus()
  2010. return
  2011. # #############################################################################################################
  2012. if wdg_name == "gdb_name":
  2013. self.db_tool_dict[tool_id]['name'] = val
  2014. elif wdg_name == "gdb_dia":
  2015. self.db_tool_dict[tool_id]['tooldia'] = val
  2016. elif wdg_name == "gdb_tool_offset":
  2017. self.db_tool_dict[tool_id]['offset'] = val
  2018. elif wdg_name == "gdb_custom_offset":
  2019. self.db_tool_dict[tool_id]['offset_value'] = val
  2020. elif wdg_name == "gdb_type":
  2021. self.db_tool_dict[tool_id]['type'] = val
  2022. elif wdg_name == "gdb_shape":
  2023. self.db_tool_dict[tool_id]['tool_type'] = val
  2024. else:
  2025. # Milling Tool
  2026. if wdg_name == "gdb_tool_target":
  2027. self.db_tool_dict[tool_id]['data']['tool_target'] = val
  2028. elif wdg_name == "gdb_tol_min":
  2029. self.db_tool_dict[tool_id]['data']['tol_min'] = val
  2030. elif wdg_name == "gdb_tol_max":
  2031. self.db_tool_dict[tool_id]['data']['tol_max'] = val
  2032. elif wdg_name == "gdb_cutz":
  2033. self.db_tool_dict[tool_id]['data']['cutz'] = val
  2034. elif wdg_name == "gdb_multidepth":
  2035. self.db_tool_dict[tool_id]['data']['multidepth'] = val
  2036. elif wdg_name == "gdb_multidepth_entry":
  2037. self.db_tool_dict[tool_id]['data']['depthperpass'] = val
  2038. elif wdg_name == "gdb_travelz":
  2039. self.db_tool_dict[tool_id]['data']['travelz'] = val
  2040. elif wdg_name == "gdb_frxy":
  2041. self.db_tool_dict[tool_id]['data']['feedrate'] = val
  2042. elif wdg_name == "gdb_frz":
  2043. self.db_tool_dict[tool_id]['data']['feedrate_z'] = val
  2044. elif wdg_name == "gdb_spindle":
  2045. self.db_tool_dict[tool_id]['data']['spindlespeed'] = val
  2046. elif wdg_name == "gdb_dwell":
  2047. self.db_tool_dict[tool_id]['data']['dwell'] = val
  2048. elif wdg_name == "gdb_dwelltime":
  2049. self.db_tool_dict[tool_id]['data']['dwelltime'] = val
  2050. elif wdg_name == "gdb_vdia":
  2051. self.db_tool_dict[tool_id]['data']['vtipdia'] = val
  2052. elif wdg_name == "gdb_vangle":
  2053. self.db_tool_dict[tool_id]['data']['vtipangle'] = val
  2054. elif wdg_name == "gdb_frapids":
  2055. self.db_tool_dict[tool_id]['data']['feedrate_rapid'] = val
  2056. elif wdg_name == "gdb_ecut":
  2057. self.db_tool_dict[tool_id]['data']['extracut'] = val
  2058. elif wdg_name == "gdb_ecut_length":
  2059. self.db_tool_dict[tool_id]['data']['extracut_length'] = val
  2060. # NCC Tool
  2061. elif wdg_name == "gdb_n_operation":
  2062. self.db_tool_dict[tool_id]['data']['tools_ncc_operation'] = val
  2063. elif wdg_name == "gdb_n_overlap":
  2064. self.db_tool_dict[tool_id]['data']['tools_ncc_overlap'] = val
  2065. elif wdg_name == "gdb_n_margin":
  2066. self.db_tool_dict[tool_id]['data']['tools_ncc_margin'] = val
  2067. elif wdg_name == "gdb_n_method":
  2068. self.db_tool_dict[tool_id]['data']['tools_ncc_method'] = val
  2069. elif wdg_name == "gdb_n_connect":
  2070. self.db_tool_dict[tool_id]['data']['tools_ncc_connect'] = val
  2071. elif wdg_name == "gdb_n_contour":
  2072. self.db_tool_dict[tool_id]['data']['tools_ncc_contour'] = val
  2073. elif wdg_name == "gdb_n_offset":
  2074. self.db_tool_dict[tool_id]['data']['tools_ncc_offset_choice'] = val
  2075. elif wdg_name == "gdb_n_offset_value":
  2076. self.db_tool_dict[tool_id]['data']['tools_ncc_offset_value'] = val
  2077. elif wdg_name == "gdb_n_milling_type":
  2078. self.db_tool_dict[tool_id]['data']['tools_ncc_milling_type'] = val
  2079. # Paint Tool
  2080. elif wdg_name == "gdb_p_overlap":
  2081. self.db_tool_dict[tool_id]['data']['tools_paint_overlap'] = val
  2082. elif wdg_name == "gdb_p_offset":
  2083. self.db_tool_dict[tool_id]['data']['tools_paint_offset'] = val
  2084. elif wdg_name == "gdb_p_method":
  2085. self.db_tool_dict[tool_id]['data']['tools_paint_method'] = val
  2086. elif wdg_name == "gdb_p_connect":
  2087. self.db_tool_dict[tool_id]['data']['tools_paint_connect'] = val
  2088. elif wdg_name == "gdb_p_contour":
  2089. self.db_tool_dict[tool_id]['data']['tools_paint_contour'] = val
  2090. # Isolation Tool
  2091. elif wdg_name == "gdb_i_passes":
  2092. self.db_tool_dict[tool_id]['data']['tools_iso_passes'] = val
  2093. elif wdg_name == "gdb_i_overlap":
  2094. self.db_tool_dict[tool_id]['data']['tools_iso_overlap'] = val
  2095. elif wdg_name == "gdb_i_milling_type":
  2096. self.db_tool_dict[tool_id]['data']['tools_iso_milling_type'] = val
  2097. elif wdg_name == "gdb_i_follow":
  2098. self.db_tool_dict[tool_id]['data']['tools_iso_follow'] = val
  2099. elif wdg_name == "gdb_i_iso_type":
  2100. self.db_tool_dict[tool_id]['data']['tools_iso_isotype'] = val
  2101. # Drilling Tool
  2102. elif wdg_name == "gdb_e_cutz":
  2103. self.db_tool_dict[tool_id]['data']['tools_drill_cutz'] = val
  2104. elif wdg_name == "gdb_e_multidepth":
  2105. self.db_tool_dict[tool_id]['data']['tools_drill_multidepth'] = val
  2106. elif wdg_name == "gdb_e_depthperpass":
  2107. self.db_tool_dict[tool_id]['data']['tools_drill_depthperpass'] = val
  2108. elif wdg_name == "gdb_e_travelz":
  2109. self.db_tool_dict[tool_id]['data']['tools_drill_travelz'] = val
  2110. elif wdg_name == "gdb_e_feedratez":
  2111. self.db_tool_dict[tool_id]['data']['tools_drill_feedrate_z'] = val
  2112. elif wdg_name == "gdb_e_fr_rapid":
  2113. self.db_tool_dict[tool_id]['data']['tools_drill_feedrate_rapid'] = val
  2114. elif wdg_name == "gdb_e_spindlespeed":
  2115. self.db_tool_dict[tool_id]['data']['tools_drill_spindlespeed'] = val
  2116. elif wdg_name == "gdb_e_dwell":
  2117. self.db_tool_dict[tool_id]['data']['tools_drill_dwell'] = val
  2118. elif wdg_name == "gdb_e_dwelltime":
  2119. self.db_tool_dict[tool_id]['data']['tools_drill_dwelltime'] = val
  2120. elif wdg_name == "gdb_e_offset":
  2121. self.db_tool_dict[tool_id]['data']['tools_drill_offset'] = val
  2122. elif wdg_name == "gdb_e_drill_slots":
  2123. self.db_tool_dict[tool_id]['data']['tools_drill_drill_slots'] = val
  2124. elif wdg_name == "gdb_e_drill_slots_over":
  2125. self.db_tool_dict[tool_id]['data']['tools_drill_drill_overlap'] = val
  2126. elif wdg_name == "gdb_e_drill_last_drill":
  2127. self.db_tool_dict[tool_id]['data']['tools_drill_last_drill'] = val
  2128. # Cutout Tool
  2129. elif wdg_name == "gdb_ct_margin":
  2130. self.db_tool_dict[tool_id]['data']['tools_cutout_margin'] = val
  2131. elif wdg_name == "gdb_ct_gapsize":
  2132. self.db_tool_dict[tool_id]['data']['tools_cutout_gapsize'] = val
  2133. elif wdg_name == "gdb_ct_gaps":
  2134. self.db_tool_dict[tool_id]['data']['tools_cutout_gaps_ff'] = val
  2135. elif wdg_name == "gdb_ct_convex":
  2136. self.db_tool_dict[tool_id]['data']['tools_cutout_convexshape'] = val
  2137. elif wdg_name == "gdb_ct_gap_type":
  2138. self.db_tool_dict[tool_id]['data']['tools_cutout_gap_type'] = val
  2139. elif wdg_name == "gdb_ct_gap_depth":
  2140. self.db_tool_dict[tool_id]['data']['tools_cutout_gap_depth'] = val
  2141. elif wdg_name == "gdb_ct_mb_dia":
  2142. self.db_tool_dict[tool_id]['data']['tools_cutout_mb_dia'] = val
  2143. elif wdg_name == "gdb_ct_mb_spacing":
  2144. self.db_tool_dict[tool_id]['data']['tools_cutout_mb_spacing'] = val
  2145. self.on_tools_db_edited()
  2146. def on_tool_requested_from_app(self):
  2147. if not self.ui.tree_widget.selectedItems():
  2148. self.app.inform.emit('[WARNING_NOTCL] %s...' % _("No Tool/row selected in the Tools Database table"))
  2149. return
  2150. if not self.db_tool_dict:
  2151. self.app.inform.emit('[ERROR_NOTCL] %s' % _("Tools DB empty."))
  2152. return
  2153. for item in self.ui.tree_widget.selectedItems():
  2154. tool_uid = item.data(0, QtCore.Qt.DisplayRole)
  2155. for key in self.db_tool_dict.keys():
  2156. if str(key) == str(tool_uid):
  2157. selected_tool = self.db_tool_dict[key]
  2158. self.on_tool_request(tool=selected_tool)
  2159. def on_tools_db_edited(self, silent=None):
  2160. """
  2161. Executed whenever a tool is edited in Tools Database.
  2162. Will color the text of the Tools Database tab to Red color.
  2163. :return:
  2164. """
  2165. for idx in range(self.app.ui.plot_tab_area.count()):
  2166. if self.app.ui.plot_tab_area.tabText(idx) == _("Tools Database"):
  2167. self.app.ui.plot_tab_area.tabBar.setTabTextColor(idx, QtGui.QColor('red'))
  2168. self.ui.save_db_btn.setStyleSheet("QPushButton {color: red;}")
  2169. self.tools_db_changed_flag = True
  2170. if silent is None:
  2171. msg = '[WARNING_NOTCL] %s' % _("Tools in Tools Database edited but not saved.")
  2172. self.app.inform[str, bool].emit(msg, False)
  2173. def on_cancel_tool(self):
  2174. for idx in range(self.app_ui.plot_tab_area.count()):
  2175. if self.app_ui.plot_tab_area.tabText(idx) == _("Tools Database"):
  2176. wdg = self.app_ui.plot_tab_area.widget(idx)
  2177. wdg.deleteLater()
  2178. self.app_ui.plot_tab_area.removeTab(idx)
  2179. self.app.inform.emit('%s' % _("Cancelled adding tool from DB."))
  2180. # def resize_new_tool_table_widget(self, min_size, max_size):
  2181. # """
  2182. # Resize the table widget responsible for adding new tool in the Tool Database
  2183. #
  2184. # :param min_size: passed by rangeChanged signal or the self.new_tool_table_widget.horizontalScrollBar()
  2185. # :param max_size: passed by rangeChanged signal or the self.new_tool_table_widget.horizontalScrollBar()
  2186. # :return:
  2187. # """
  2188. # t_height = self.t_height
  2189. # if max_size > min_size:
  2190. # t_height = self.t_height + self.new_tool_table_widget.verticalScrollBar().height()
  2191. #
  2192. # self.new_tool_table_widget.setMaximumHeight(t_height)
  2193. def closeEvent(self, QCloseEvent):
  2194. super().closeEvent(QCloseEvent)
  2195. # class ToolsDB(QtWidgets.QWidget):
  2196. #
  2197. # mark_tools_rows = QtCore.pyqtSignal()
  2198. #
  2199. # def __init__(self, app, callback_on_edited, callback_on_tool_request, parent=None):
  2200. # super(ToolsDB, self).__init__(parent)
  2201. #
  2202. # self.app = app
  2203. # self.decimals = 4
  2204. # self.callback_app = callback_on_edited
  2205. #
  2206. # self.on_tool_request = callback_on_tool_request
  2207. #
  2208. # self.offset_item_options = ["Path", "In", "Out", "Custom"]
  2209. # self.type_item_options = ["Iso", "Rough", "Finish"]
  2210. # self.tool_type_item_options = ["C1", "C2", "C3", "C4", "B", "V"]
  2211. #
  2212. # '''
  2213. # dict to hold all the tools in the Tools DB
  2214. # format:
  2215. # {
  2216. # tool_id: {
  2217. # 'name': 'new_tool'
  2218. # 'tooldia': self.app.defaults["geometry_cnctooldia"]
  2219. # 'offset': 'Path'
  2220. # 'offset_value': 0.0
  2221. # 'type': 'Rough',
  2222. # 'tool_type': 'C1'
  2223. # 'data': dict()
  2224. # }
  2225. # }
  2226. # '''
  2227. # self.db_tool_dict = {}
  2228. #
  2229. # # layouts
  2230. # layout = QtWidgets.QVBoxLayout()
  2231. # self.setLayout(layout)
  2232. #
  2233. # table_hlay = QtWidgets.QHBoxLayout()
  2234. # layout.addLayout(table_hlay)
  2235. #
  2236. # self.table_widget = FCTable(drag_drop=True)
  2237. # self.table_widget.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows)
  2238. # table_hlay.addWidget(self.table_widget)
  2239. #
  2240. # # set the number of columns and the headers tool tips
  2241. # self.configure_table()
  2242. #
  2243. # # pal = QtGui.QPalette()
  2244. # # pal.setColor(QtGui.QPalette.Background, Qt.white)
  2245. #
  2246. # # New Bookmark
  2247. # new_vlay = QtWidgets.QVBoxLayout()
  2248. # layout.addLayout(new_vlay)
  2249. #
  2250. # # new_tool_lbl = FCLabel('<b>%s</b>' % _("New Tool"))
  2251. # # new_vlay.addWidget(new_tool_lbl, alignment=QtCore.Qt.AlignBottom)
  2252. #
  2253. # self.buttons_frame = QtWidgets.QFrame()
  2254. # self.buttons_frame.setContentsMargins(0, 0, 0, 0)
  2255. # layout.addWidget(self.buttons_frame)
  2256. # self.buttons_box = QtWidgets.QHBoxLayout()
  2257. # self.buttons_box.setContentsMargins(0, 0, 0, 0)
  2258. # self.buttons_frame.setLayout(self.buttons_box)
  2259. # self.buttons_frame.show()
  2260. #
  2261. # add_entry_btn = FCButton(_("Add Geometry Tool in DB"))
  2262. # add_entry_btn.setToolTip(
  2263. # _("Add a new tool in the Tools Database.\n"
  2264. # "It will be used in the Geometry UI.\n"
  2265. # "You can edit it after it is added.")
  2266. # )
  2267. # self.buttons_box.addWidget(add_entry_btn)
  2268. #
  2269. # # add_fct_entry_btn = FCButton(_("Add Paint/NCC Tool in DB"))
  2270. # # add_fct_entry_btn.setToolTip(
  2271. # # _("Add a new tool in the Tools Database.\n"
  2272. # # "It will be used in the Paint/NCC Tools UI.\n"
  2273. # # "You can edit it after it is added.")
  2274. # # )
  2275. # # self.buttons_box.addWidget(add_fct_entry_btn)
  2276. #
  2277. # remove_entry_btn = FCButton(_("Delete Tool from DB"))
  2278. # remove_entry_btn.setToolTip(
  2279. # _("Remove a selection of tools in the Tools Database.")
  2280. # )
  2281. # self.buttons_box.addWidget(remove_entry_btn)
  2282. #
  2283. # export_db_btn = FCButton(_("Export DB"))
  2284. # export_db_btn.setToolTip(
  2285. # _("Save the Tools Database to a custom text file.")
  2286. # )
  2287. # self.buttons_box.addWidget(export_db_btn)
  2288. #
  2289. # import_db_btn = FCButton(_("Import DB"))
  2290. # import_db_btn.setToolTip(
  2291. # _("Load the Tools Database information's from a custom text file.")
  2292. # )
  2293. # self.buttons_box.addWidget(import_db_btn)
  2294. #
  2295. # self.add_tool_from_db = FCButton(_("Transfer the Tool"))
  2296. # self.add_tool_from_db.setToolTip(
  2297. # _("Add a new tool in the Tools Table of the\n"
  2298. # "active Geometry object after selecting a tool\n"
  2299. # "in the Tools Database.")
  2300. # )
  2301. # self.add_tool_from_db.hide()
  2302. #
  2303. # self.cancel_tool_from_db = FCButton(_("Cancel"))
  2304. # self.cancel_tool_from_db.hide()
  2305. #
  2306. # hlay = QtWidgets.QHBoxLayout()
  2307. # layout.addLayout(hlay)
  2308. # hlay.addWidget(self.add_tool_from_db)
  2309. # hlay.addWidget(self.cancel_tool_from_db)
  2310. # hlay.addStretch()
  2311. #
  2312. # # ##############################################################################
  2313. # # ######################## SIGNALS #############################################
  2314. # # ##############################################################################
  2315. #
  2316. # add_entry_btn.clicked.connect(self.on_tool_add)
  2317. # remove_entry_btn.clicked.connect(self.on_tool_delete)
  2318. # export_db_btn.clicked.connect(self.on_export_tools_db_file)
  2319. # import_db_btn.clicked.connect(self.on_import_tools_db_file)
  2320. # # closebtn.clicked.connect(self.accept)
  2321. #
  2322. # self.add_tool_from_db.clicked.connect(self.on_tool_requested_from_app)
  2323. # self.cancel_tool_from_db.clicked.connect(self.on_cancel_tool)
  2324. #
  2325. # self.setup_db_ui()
  2326. #
  2327. # def configure_table(self):
  2328. # self.table_widget.setColumnCount(27)
  2329. # # self.table_widget.setColumnWidth(0, 20)
  2330. # self.table_widget.setHorizontalHeaderLabels(
  2331. # [
  2332. # '#',
  2333. # _("Tool Name"),
  2334. # _("Tool Dia"),
  2335. # _("Tool Offset"),
  2336. # _("Custom Offset"),
  2337. # _("Tool Type"),
  2338. # _("Tool Shape"),
  2339. # _("Cut Z"),
  2340. # _("MultiDepth"),
  2341. # _("DPP"),
  2342. # _("V-Dia"),
  2343. # _("V-Angle"),
  2344. # _("Travel Z"),
  2345. # _("FR"),
  2346. # _("FR Z"),
  2347. # _("FR Rapids"),
  2348. # _("Spindle Speed"),
  2349. # _("Dwell"),
  2350. # _("Dwelltime"),
  2351. # _("Preprocessor"),
  2352. # _("ExtraCut"),
  2353. # _("E-Cut Length"),
  2354. # _("Toolchange"),
  2355. # _("Toolchange XY"),
  2356. # _("Toolchange Z"),
  2357. # _("Start Z"),
  2358. # _("End Z"),
  2359. # ]
  2360. # )
  2361. # self.table_widget.horizontalHeaderItem(0).setToolTip(
  2362. # _("Tool Index."))
  2363. # self.table_widget.horizontalHeaderItem(1).setToolTip(
  2364. # _("Tool name.\n"
  2365. # "This is not used in the app, it's function\n"
  2366. # "is to serve as a note for the user."))
  2367. # self.table_widget.horizontalHeaderItem(2).setToolTip(
  2368. # _("Tool Diameter."))
  2369. # self.table_widget.horizontalHeaderItem(3).setToolTip(
  2370. # _("Tool Offset.\n"
  2371. # "Can be of a few types:\n"
  2372. # "Path = zero offset\n"
  2373. # "In = offset inside by half of tool diameter\n"
  2374. # "Out = offset outside by half of tool diameter\n"
  2375. # "Custom = custom offset using the Custom Offset value"))
  2376. # self.table_widget.horizontalHeaderItem(4).setToolTip(
  2377. # _("Custom Offset.\n"
  2378. # "A value to be used as offset from the current path."))
  2379. # self.table_widget.horizontalHeaderItem(5).setToolTip(
  2380. # _("Tool Type.\n"
  2381. # "Can be:\n"
  2382. # "Iso = isolation cut\n"
  2383. # "Rough = rough cut, low feedrate, multiple passes\n"
  2384. # "Finish = finishing cut, high feedrate"))
  2385. # self.table_widget.horizontalHeaderItem(6).setToolTip(
  2386. # _("Tool Shape. \n"
  2387. # "Can be:\n"
  2388. # "C1 ... C4 = circular tool with x flutes\n"
  2389. # "B = ball tip milling tool\n"
  2390. # "V = v-shape milling tool"))
  2391. # self.table_widget.horizontalHeaderItem(7).setToolTip(
  2392. # _("Cutting Depth.\n"
  2393. # "The depth at which to cut into material."))
  2394. # self.table_widget.horizontalHeaderItem(8).setToolTip(
  2395. # _("Multi Depth.\n"
  2396. # "Selecting this will allow cutting in multiple passes,\n"
  2397. # "each pass adding a DPP parameter depth."))
  2398. # self.table_widget.horizontalHeaderItem(9).setToolTip(
  2399. # _("DPP. Depth per Pass.\n"
  2400. # "The value used to cut into material on each pass."))
  2401. # self.table_widget.horizontalHeaderItem(10).setToolTip(
  2402. # _("V-Dia.\n"
  2403. # "Diameter of the tip for V-Shape Tools."))
  2404. # self.table_widget.horizontalHeaderItem(11).setToolTip(
  2405. # _("V-Agle.\n"
  2406. # "Angle at the tip for the V-Shape Tools."))
  2407. # self.table_widget.horizontalHeaderItem(12).setToolTip(
  2408. # _("Clearance Height.\n"
  2409. # "Height at which the milling bit will travel between cuts,\n"
  2410. # "above the surface of the material, avoiding all fixtures."))
  2411. # self.table_widget.horizontalHeaderItem(13).setToolTip(
  2412. # _("FR. Feedrate\n"
  2413. # "The speed on XY plane used while cutting into material."))
  2414. # self.table_widget.horizontalHeaderItem(14).setToolTip(
  2415. # _("FR Z. Feedrate Z\n"
  2416. # "The speed on Z plane."))
  2417. # self.table_widget.horizontalHeaderItem(15).setToolTip(
  2418. # _("FR Rapids. Feedrate Rapids\n"
  2419. # "Speed used while moving as fast as possible.\n"
  2420. # "This is used only by some devices that can't use\n"
  2421. # "the G0 g-code command. Mostly 3D printers."))
  2422. # self.table_widget.horizontalHeaderItem(16).setToolTip(
  2423. # _("Spindle Speed.\n"
  2424. # "If it's left empty it will not be used.\n"
  2425. # "The speed of the spindle in RPM."))
  2426. # self.table_widget.horizontalHeaderItem(17).setToolTip(
  2427. # _("Dwell.\n"
  2428. # "Check this if a delay is needed to allow\n"
  2429. # "the spindle motor to reach its set speed."))
  2430. # self.table_widget.horizontalHeaderItem(18).setToolTip(
  2431. # _("Dwell Time.\n"
  2432. # "A delay used to allow the motor spindle reach its set speed."))
  2433. # self.table_widget.horizontalHeaderItem(19).setToolTip(
  2434. # _("Preprocessor.\n"
  2435. # "A selection of files that will alter the generated G-code\n"
  2436. # "to fit for a number of use cases."))
  2437. # self.table_widget.horizontalHeaderItem(20).setToolTip(
  2438. # _("Extra Cut.\n"
  2439. # "If checked, after a isolation is finished an extra cut\n"
  2440. # "will be added where the start and end of isolation meet\n"
  2441. # "such as that this point is covered by this extra cut to\n"
  2442. # "ensure a complete isolation."))
  2443. # self.table_widget.horizontalHeaderItem(21).setToolTip(
  2444. # _("Extra Cut length.\n"
  2445. # "If checked, after a isolation is finished an extra cut\n"
  2446. # "will be added where the start and end of isolation meet\n"
  2447. # "such as that this point is covered by this extra cut to\n"
  2448. # "ensure a complete isolation. This is the length of\n"
  2449. # "the extra cut."))
  2450. # self.table_widget.horizontalHeaderItem(22).setToolTip(
  2451. # _("Toolchange.\n"
  2452. # "It will create a toolchange event.\n"
  2453. # "The kind of toolchange is determined by\n"
  2454. # "the preprocessor file."))
  2455. # self.table_widget.horizontalHeaderItem(23).setToolTip(
  2456. # _("Toolchange XY.\n"
  2457. # "A set of coordinates in the format (x, y).\n"
  2458. # "Will determine the cartesian position of the point\n"
  2459. # "where the tool change event take place."))
  2460. # self.table_widget.horizontalHeaderItem(24).setToolTip(
  2461. # _("Toolchange Z.\n"
  2462. # "The position on Z plane where the tool change event take place."))
  2463. # self.table_widget.horizontalHeaderItem(25).setToolTip(
  2464. # _("Start Z.\n"
  2465. # "If it's left empty it will not be used.\n"
  2466. # "A position on Z plane to move immediately after job start."))
  2467. # self.table_widget.horizontalHeaderItem(26).setToolTip(
  2468. # _("End Z.\n"
  2469. # "A position on Z plane to move immediately after job stop."))
  2470. #
  2471. # def setup_db_ui(self):
  2472. # filename = self.app.tools_database_path()
  2473. #
  2474. # # load the database tools from the file
  2475. # try:
  2476. # with open(filename) as f:
  2477. # tools = f.read()
  2478. # except IOError:
  2479. # self.app.log.error("Could not load tools DB file.")
  2480. # self.app.inform.emit('[ERROR] %s' % _("Could not load Tools DB file."))
  2481. # return
  2482. #
  2483. # try:
  2484. # self.db_tool_dict = json.loads(tools)
  2485. # except Exception:
  2486. # e = sys.exc_info()[0]
  2487. # self.app.log.error(str(e))
  2488. # self.app.inform.emit('[ERROR] %s' % _("Failed to parse Tools DB file."))
  2489. # return
  2490. #
  2491. # self.app.inform.emit('[success] %s: %s' % (_("Loaded Tools DB from"), filename))
  2492. #
  2493. # self.build_db_ui()
  2494. #
  2495. # self.table_widget.setupContextMenu()
  2496. # self.table_widget.addContextMenu(
  2497. # _("Add to DB"), self.on_tool_add, icon=QtGui.QIcon(self.app.resource_location + "/plus16.png"))
  2498. # self.table_widget.addContextMenu(
  2499. # _("Copy from DB"), self.on_tool_copy, icon=QtGui.QIcon(self.app.resource_location + "/copy16.png"))
  2500. # self.table_widget.addContextMenu(
  2501. # _("Delete from DB"), self.on_tool_delete, icon=QtGui.QIcon(self.app.resource_location + "/delete32.png"))
  2502. #
  2503. # def build_db_ui(self):
  2504. # self.ui_disconnect()
  2505. # self.table_widget.setRowCount(len(self.db_tool_dict))
  2506. #
  2507. # nr_crt = 0
  2508. #
  2509. # for toolid, dict_val in self.db_tool_dict.items():
  2510. # row = nr_crt
  2511. # nr_crt += 1
  2512. #
  2513. # t_name = dict_val['name']
  2514. # try:
  2515. # self.add_tool_table_line(row, name=t_name, widget=self.table_widget, tooldict=dict_val)
  2516. # except Exception as e:
  2517. # self.app.log.debug("ToolDB.build_db_ui.add_tool_table_line() --> %s" % str(e))
  2518. # vertical_header = self.table_widget.verticalHeader()
  2519. # vertical_header.hide()
  2520. #
  2521. # horizontal_header = self.table_widget.horizontalHeader()
  2522. # horizontal_header.setMinimumSectionSize(10)
  2523. # horizontal_header.setDefaultSectionSize(70)
  2524. #
  2525. # self.table_widget.setSizeAdjustPolicy(QtWidgets.QAbstractScrollArea.AdjustToContents)
  2526. # for x in range(27):
  2527. # self.table_widget.resizeColumnToContents(x)
  2528. #
  2529. # horizontal_header.setSectionResizeMode(0, QtWidgets.QHeaderView.Fixed)
  2530. # # horizontal_header.setSectionResizeMode(1, QtWidgets.QHeaderView.Stretch)
  2531. # # horizontal_header.setSectionResizeMode(13, QtWidgets.QHeaderView.Fixed)
  2532. #
  2533. # horizontal_header.resizeSection(0, 20)
  2534. # # horizontal_header.setSectionResizeMode(1, QtWidgets.QHeaderView.ResizeToContents)
  2535. # # horizontal_header.setSectionResizeMode(2, QtWidgets.QHeaderView.Stretch)
  2536. #
  2537. # self.ui_connect()
  2538. #
  2539. # def add_tool_table_line(self, row, name, widget, tooldict):
  2540. # data = tooldict['data']
  2541. #
  2542. # nr_crt = row + 1
  2543. # id_item = QtWidgets.QTableWidgetItem('%d' % int(nr_crt))
  2544. # # id_item.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled)
  2545. # flags = id_item.flags() & ~QtCore.Qt.ItemIsEditable
  2546. # id_item.setFlags(flags)
  2547. # widget.setItem(row, 0, id_item) # Tool name/id
  2548. #
  2549. # tool_name_item = QtWidgets.QTableWidgetItem(name)
  2550. # widget.setItem(row, 1, tool_name_item)
  2551. #
  2552. # dia_item = FCDoubleSpinner()
  2553. # dia_item.set_precision(self.decimals)
  2554. # dia_item.setSingleStep(0.1)
  2555. # dia_item.set_range(0.0, 10000.0000)
  2556. # dia_item.set_value(float(tooldict['tooldia']))
  2557. # widget.setCellWidget(row, 2, dia_item)
  2558. #
  2559. # tool_offset_item = FCComboBox()
  2560. # for item in self.offset_item_options:
  2561. # tool_offset_item.addItem(item)
  2562. # tool_offset_item.set_value(tooldict['offset'])
  2563. # widget.setCellWidget(row, 3, tool_offset_item)
  2564. #
  2565. # c_offset_item = FCDoubleSpinner()
  2566. # c_offset_item.set_precision(self.decimals)
  2567. # c_offset_item.setSingleStep(0.1)
  2568. # c_offset_item.set_range(-10000.0000, 10000.0000)
  2569. # c_offset_item.set_value(float(tooldict['offset_value']))
  2570. # widget.setCellWidget(row, 4, c_offset_item)
  2571. #
  2572. # tt_item = FCComboBox()
  2573. # for item in self.type_item_options:
  2574. # tt_item.addItem(item)
  2575. # tt_item.set_value(tooldict['type'])
  2576. # widget.setCellWidget(row, 5, tt_item)
  2577. #
  2578. # tshape_item = FCComboBox()
  2579. # for item in self.tool_type_item_options:
  2580. # tshape_item.addItem(item)
  2581. # tshape_item.set_value(tooldict['tool_type'])
  2582. # widget.setCellWidget(row, 6, tshape_item)
  2583. #
  2584. # cutz_item = FCDoubleSpinner()
  2585. # cutz_item.set_precision(self.decimals)
  2586. # cutz_item.setSingleStep(0.1)
  2587. # if self.app.defaults['global_machinist_setting']:
  2588. # cutz_item.set_range(-10000.0000, 10000.0000)
  2589. # else:
  2590. # cutz_item.set_range(-10000.0000, -0.0000)
  2591. #
  2592. # cutz_item.set_value(float(data['cutz']))
  2593. # widget.setCellWidget(row, 7, cutz_item)
  2594. #
  2595. # multidepth_item = FCCheckBox()
  2596. # multidepth_item.set_value(data['multidepth'])
  2597. # widget.setCellWidget(row, 8, multidepth_item)
  2598. #
  2599. # # to make the checkbox centered but it can no longer have it's value accessed - needs a fix using findchild()
  2600. # # multidepth_item = QtWidgets.QWidget()
  2601. # # cb = FCCheckBox()
  2602. # # cb.set_value(data['multidepth'])
  2603. # # qhboxlayout = QtWidgets.QHBoxLayout(multidepth_item)
  2604. # # qhboxlayout.addWidget(cb)
  2605. # # qhboxlayout.setAlignment(QtCore.Qt.AlignCenter)
  2606. # # qhboxlayout.setContentsMargins(0, 0, 0, 0)
  2607. # # widget.setCellWidget(row, 8, multidepth_item)
  2608. #
  2609. # depth_per_pass_item = FCDoubleSpinner()
  2610. # depth_per_pass_item.set_precision(self.decimals)
  2611. # depth_per_pass_item.setSingleStep(0.1)
  2612. # depth_per_pass_item.set_range(0.0, 10000.0000)
  2613. # depth_per_pass_item.set_value(float(data['depthperpass']))
  2614. # widget.setCellWidget(row, 9, depth_per_pass_item)
  2615. #
  2616. # vtip_dia_item = FCDoubleSpinner()
  2617. # vtip_dia_item.set_precision(self.decimals)
  2618. # vtip_dia_item.setSingleStep(0.1)
  2619. # vtip_dia_item.set_range(0.0, 10000.0000)
  2620. # vtip_dia_item.set_value(float(data['vtipdia']))
  2621. # widget.setCellWidget(row, 10, vtip_dia_item)
  2622. #
  2623. # vtip_angle_item = FCDoubleSpinner()
  2624. # vtip_angle_item.set_precision(self.decimals)
  2625. # vtip_angle_item.setSingleStep(0.1)
  2626. # vtip_angle_item.set_range(-360.0, 360.0)
  2627. # vtip_angle_item.set_value(float(data['vtipangle']))
  2628. # widget.setCellWidget(row, 11, vtip_angle_item)
  2629. #
  2630. # travelz_item = FCDoubleSpinner()
  2631. # travelz_item.set_precision(self.decimals)
  2632. # travelz_item.setSingleStep(0.1)
  2633. # if self.app.defaults['global_machinist_setting']:
  2634. # travelz_item.set_range(-10000.0000, 10000.0000)
  2635. # else:
  2636. # travelz_item.set_range(0.0000, 10000.0000)
  2637. #
  2638. # travelz_item.set_value(float(data['travelz']))
  2639. # widget.setCellWidget(row, 12, travelz_item)
  2640. #
  2641. # fr_item = FCDoubleSpinner()
  2642. # fr_item.set_precision(self.decimals)
  2643. # fr_item.set_range(0.0, 10000.0000)
  2644. # fr_item.set_value(float(data['feedrate']))
  2645. # widget.setCellWidget(row, 13, fr_item)
  2646. #
  2647. # frz_item = FCDoubleSpinner()
  2648. # frz_item.set_precision(self.decimals)
  2649. # frz_item.set_range(0.0, 10000.0000)
  2650. # frz_item.set_value(float(data['feedrate_z']))
  2651. # widget.setCellWidget(row, 14, frz_item)
  2652. #
  2653. # frrapids_item = FCDoubleSpinner()
  2654. # frrapids_item.set_precision(self.decimals)
  2655. # frrapids_item.set_range(0.0, 10000.0000)
  2656. # frrapids_item.set_value(float(data['feedrate_rapid']))
  2657. # widget.setCellWidget(row, 15, frrapids_item)
  2658. #
  2659. # spindlespeed_item = FCSpinner()
  2660. # spindlespeed_item.set_range(0, 1000000)
  2661. # spindlespeed_item.set_value(int(data['spindlespeed']))
  2662. # spindlespeed_item.set_step(100)
  2663. # widget.setCellWidget(row, 16, spindlespeed_item)
  2664. #
  2665. # dwell_item = FCCheckBox()
  2666. # dwell_item.set_value(data['dwell'])
  2667. # widget.setCellWidget(row, 17, dwell_item)
  2668. #
  2669. # dwelltime_item = FCDoubleSpinner()
  2670. # dwelltime_item.set_precision(self.decimals)
  2671. # dwelltime_item.set_range(0.0000, 10000.0000)
  2672. # dwelltime_item.set_value(float(data['dwelltime']))
  2673. # widget.setCellWidget(row, 18, dwelltime_item)
  2674. #
  2675. # pp_item = FCComboBox()
  2676. # for item in self.app.preprocessors:
  2677. # pp_item.addItem(item)
  2678. # pp_item.set_value(data['ppname_g'])
  2679. # widget.setCellWidget(row, 19, pp_item)
  2680. #
  2681. # ecut_item = FCCheckBox()
  2682. # ecut_item.set_value(data['extracut'])
  2683. # widget.setCellWidget(row, 20, ecut_item)
  2684. #
  2685. # ecut_length_item = FCDoubleSpinner()
  2686. # ecut_length_item.set_precision(self.decimals)
  2687. # ecut_length_item.set_range(0.0000, 10000.0000)
  2688. # ecut_length_item.set_value(data['extracut_length'])
  2689. # widget.setCellWidget(row, 21, ecut_length_item)
  2690. #
  2691. # toolchange_item = FCCheckBox()
  2692. # toolchange_item.set_value(data['toolchange'])
  2693. # widget.setCellWidget(row, 22, toolchange_item)
  2694. #
  2695. # toolchangexy_item = QtWidgets.QTableWidgetItem(str(data['toolchangexy']) if data['toolchangexy'] else '')
  2696. # widget.setItem(row, 23, toolchangexy_item)
  2697. #
  2698. # toolchangez_item = FCDoubleSpinner()
  2699. # toolchangez_item.set_precision(self.decimals)
  2700. # toolchangez_item.setSingleStep(0.1)
  2701. # if self.app.defaults['global_machinist_setting']:
  2702. # toolchangez_item.set_range(-10000.0000, 10000.0000)
  2703. # else:
  2704. # toolchangez_item.set_range(0.0000, 10000.0000)
  2705. #
  2706. # toolchangez_item.set_value(float(data['toolchangez']))
  2707. # widget.setCellWidget(row, 24, toolchangez_item)
  2708. #
  2709. # startz_item = QtWidgets.QTableWidgetItem(str(data['startz']) if data['startz'] else '')
  2710. # widget.setItem(row, 25, startz_item)
  2711. #
  2712. # endz_item = FCDoubleSpinner()
  2713. # endz_item.set_precision(self.decimals)
  2714. # endz_item.setSingleStep(0.1)
  2715. # if self.app.defaults['global_machinist_setting']:
  2716. # endz_item.set_range(-10000.0000, 10000.0000)
  2717. # else:
  2718. # endz_item.set_range(0.0000, 10000.0000)
  2719. #
  2720. # endz_item.set_value(float(data['endz']))
  2721. # widget.setCellWidget(row, 26, endz_item)
  2722. #
  2723. # def on_tool_add(self):
  2724. # """
  2725. # Add a tool in the DB Tool Table
  2726. # :return: None
  2727. # """
  2728. #
  2729. # default_data = {}
  2730. # default_data.update({
  2731. # "cutz": float(self.app.defaults["geometry_cutz"]),
  2732. # "multidepth": self.app.defaults["geometry_multidepth"],
  2733. # "depthperpass": float(self.app.defaults["geometry_depthperpass"]),
  2734. # "vtipdia": float(self.app.defaults["geometry_vtipdia"]),
  2735. # "vtipangle": float(self.app.defaults["geometry_vtipangle"]),
  2736. # "travelz": float(self.app.defaults["geometry_travelz"]),
  2737. # "feedrate": float(self.app.defaults["geometry_feedrate"]),
  2738. # "feedrate_z": float(self.app.defaults["geometry_feedrate_z"]),
  2739. # "feedrate_rapid": float(self.app.defaults["geometry_feedrate_rapid"]),
  2740. # "spindlespeed": self.app.defaults["geometry_spindlespeed"],
  2741. # "dwell": self.app.defaults["geometry_dwell"],
  2742. # "dwelltime": float(self.app.defaults["geometry_dwelltime"]),
  2743. # "ppname_g": self.app.defaults["geometry_ppname_g"],
  2744. # "extracut": self.app.defaults["geometry_extracut"],
  2745. # "extracut_length": float(self.app.defaults["geometry_extracut_length"]),
  2746. # "toolchange": self.app.defaults["geometry_toolchange"],
  2747. # "toolchangexy": self.app.defaults["geometry_toolchangexy"],
  2748. # "toolchangez": float(self.app.defaults["geometry_toolchangez"]),
  2749. # "startz": self.app.defaults["geometry_startz"],
  2750. # "endz": float(self.app.defaults["geometry_endz"])
  2751. # })
  2752. #
  2753. # dict_elem = {}
  2754. # dict_elem['name'] = 'new_tool'
  2755. # if type(self.app.defaults["geometry_cnctooldia"]) == float:
  2756. # dict_elem['tooldia'] = self.app.defaults["geometry_cnctooldia"]
  2757. # else:
  2758. # try:
  2759. # tools_string = self.app.defaults["geometry_cnctooldia"].split(",")
  2760. # tools_diameters = [eval(a) for a in tools_string if a != '']
  2761. # dict_elem['tooldia'] = tools_diameters[0] if tools_diameters else 0.0
  2762. # except Exception as e:
  2763. # self.app.log.debug("ToolDB.on_tool_add() --> %s" % str(e))
  2764. # return
  2765. #
  2766. # dict_elem['offset'] = 'Path'
  2767. # dict_elem['offset_value'] = 0.0
  2768. # dict_elem['type'] = 'Rough'
  2769. # dict_elem['tool_type'] = 'C1'
  2770. # dict_elem['data'] = default_data
  2771. #
  2772. # new_toolid = len(self.db_tool_dict) + 1
  2773. # self.db_tool_dict[new_toolid] = deepcopy(dict_elem)
  2774. #
  2775. # # add the new entry to the Tools DB table
  2776. # self.build_db_ui()
  2777. # self.callback_on_edited()
  2778. # self.app.inform.emit('[success] %s' % _("Tool added to DB."))
  2779. #
  2780. # def on_tool_copy(self):
  2781. # """
  2782. # Copy a selection of Tools in the Tools DB table
  2783. # :return:
  2784. # """
  2785. # new_tool_id = self.table_widget.rowCount() + 1
  2786. # for model_index in self.table_widget.selectionModel().selectedRows():
  2787. # # index = QtCore.QPersistentModelIndex(model_index)
  2788. # old_tool_id = self.table_widget.item(model_index.row(), 0).text()
  2789. # new_tool_id += 1
  2790. #
  2791. # for toolid, dict_val in list(self.db_tool_dict.items()):
  2792. # if int(old_tool_id) == int(toolid):
  2793. # self.db_tool_dict.update({
  2794. # new_tool_id: deepcopy(dict_val)
  2795. # })
  2796. #
  2797. # self.build_db_ui()
  2798. # self.callback_on_edited()
  2799. # self.app.inform.emit('[success] %s' % _("Tool copied from Tools DB."))
  2800. #
  2801. # def on_tool_delete(self):
  2802. # """
  2803. # Delete a selection of Tools in the Tools DB table
  2804. # :return:
  2805. # """
  2806. # for model_index in self.table_widget.selectionModel().selectedRows():
  2807. # # index = QtCore.QPersistentModelIndex(model_index)
  2808. # toolname_to_remove = self.table_widget.item(model_index.row(), 0).text()
  2809. #
  2810. # for toolid, dict_val in list(self.db_tool_dict.items()):
  2811. # if int(toolname_to_remove) == int(toolid):
  2812. # # remove from the storage
  2813. # self.db_tool_dict.pop(toolid, None)
  2814. #
  2815. # self.build_db_ui()
  2816. # self.callback_on_edited()
  2817. # self.app.inform.emit('[success] %s' % _("Tool removed from Tools DB."))
  2818. #
  2819. # def on_export_tools_db_file(self):
  2820. # self.app.defaults.report_usage("on_export_tools_db_file")
  2821. # self.app.log.debug("on_export_tools_db_file()")
  2822. #
  2823. # date = str(datetime.today()).rpartition('.')[0]
  2824. # date = ''.join(c for c in date if c not in ':-')
  2825. # date = date.replace(' ', '_')
  2826. #
  2827. # filter__ = "Text File (*.TXT);;All Files (*.*)"
  2828. # filename, _f = FCFileSaveDialog.get_saved_filename(caption=_("Export Tools Database"),
  2829. # directory='{l_save}/FlatCAM_{n}_{date}'.format(
  2830. # l_save=str(self.app.get_last_save_folder()),
  2831. # n=_("Tools_Database"),
  2832. # date=date),
  2833. # ext_filter=filter__)
  2834. #
  2835. # filename = str(filename)
  2836. #
  2837. # if filename == "":
  2838. # self.app.inform.emit('[WARNING_NOTCL] %s' % _("Cancelled."))
  2839. # return
  2840. # else:
  2841. # try:
  2842. # f = open(filename, 'w')
  2843. # f.close()
  2844. # except PermissionError:
  2845. # self.app.inform.emit('[WARNING] %s' %
  2846. # _("Permission denied, saving not possible.\n"
  2847. # "Most likely another app is holding the file open and not accessible."))
  2848. # return
  2849. # except IOError:
  2850. # self.app.log.debug('Creating a new Tools DB file ...')
  2851. # f = open(filename, 'w')
  2852. # f.close()
  2853. # except Exception:
  2854. # e = sys.exc_info()[0]
  2855. # self.app.log.error("Could not load Tools DB file.")
  2856. # self.app.log.error(str(e))
  2857. # self.app.inform.emit('[ERROR_NOTCL] %s' % _("Could not load Tools DB file."))
  2858. # return
  2859. #
  2860. # # Save update options
  2861. # try:
  2862. # # Save Tools DB in a file
  2863. # try:
  2864. # with open(filename, "w") as f:
  2865. # json.dump(self.db_tool_dict, f, default=to_dict, indent=2)
  2866. # except Exception as e:
  2867. # self.app.log.debug("App.on_save_tools_db() --> %s" % str(e))
  2868. # self.app.inform.emit('[ERROR_NOTCL] %s' % _("Failed to write Tools DB to file."))
  2869. # return
  2870. # except Exception:
  2871. # self.app.inform.emit('[ERROR_NOTCL] %s' % _("Failed to write Tools DB to file."))
  2872. # return
  2873. #
  2874. # self.app.inform.emit('[success] %s: %s' % (_("Exported Tools DB to"), filename))
  2875. #
  2876. # def on_import_tools_db_file(self):
  2877. # self.app.defaults.report_usage("on_import_tools_db_file")
  2878. # self.app.log.debug("on_import_tools_db_file()")
  2879. #
  2880. # filter__ = "Text File (*.TXT);;All Files (*.*)"
  2881. # filename, _f = QtWidgets.QFileDialog.getOpenFileName(caption=_("Import FlatCAM Tools DB"), filter=filter__)
  2882. #
  2883. # if filename == "":
  2884. # self.app.inform.emit('[WARNING_NOTCL] %s' % _("Cancelled."))
  2885. # else:
  2886. # try:
  2887. # with open(filename) as f:
  2888. # tools_in_db = f.read()
  2889. # except IOError:
  2890. # self.app.log.error("Could not load Tools DB file.")
  2891. # self.app.inform.emit('[ERROR_NOTCL] %s' % _("Could not load Tools DB file."))
  2892. # return
  2893. #
  2894. # try:
  2895. # self.db_tool_dict = json.loads(tools_in_db)
  2896. # except Exception:
  2897. # e = sys.exc_info()[0]
  2898. # self.app.log.error(str(e))
  2899. # self.app.inform.emit('[ERROR] %s' % _("Failed to parse Tools DB file."))
  2900. # return
  2901. #
  2902. # self.app.inform.emit('[success] %s: %s' % (_("Loaded Tools DB from"), filename))
  2903. # self.build_db_ui()
  2904. # self.callback_on_edited()
  2905. #
  2906. # def on_save_tools_db(self, silent=False):
  2907. # self.app.log.debug("ToolsDB.on_save_button() --> Saving Tools Database to file.")
  2908. #
  2909. # filename = self.app.tools_database_path()
  2910. #
  2911. # # Preferences save, update the color of the Tools DB Tab text
  2912. # for idx in range(self.app_ui.plot_tab_area.count()):
  2913. # if self.app_ui.plot_tab_area.tabText(idx) == _("Tools Database"):
  2914. # self.app_ui.plot_tab_area.tabBar.setTabTextColor(idx, QtGui.QColor('black'))
  2915. #
  2916. # # Save Tools DB in a file
  2917. # try:
  2918. # f = open(filename, "w")
  2919. # json.dump(self.db_tool_dict, f, default=to_dict, indent=2)
  2920. # f.close()
  2921. # except Exception as e:
  2922. # self.app.log.debug("ToolsDB.on_save_tools_db() --> %s" % str(e))
  2923. # self.app.inform.emit('[ERROR_NOTCL] %s' % _("Failed to write Tools DB to file."))
  2924. # return
  2925. #
  2926. # if not silent:
  2927. # self.app.inform.emit('[success] %s' % _("Saved Tools DB."))
  2928. #
  2929. # def ui_connect(self):
  2930. # try:
  2931. # try:
  2932. # self.table_widget.itemChanged.disconnect(self.callback_on_edited)
  2933. # except (TypeError, AttributeError):
  2934. # pass
  2935. # self.table_widget.itemChanged.connect(self.callback_on_edited)
  2936. # except AttributeError:
  2937. # pass
  2938. #
  2939. # for row in range(self.table_widget.rowCount()):
  2940. # for col in range(self.table_widget.columnCount()):
  2941. # # ComboBox
  2942. # try:
  2943. # try:
  2944. # self.table_widget.cellWidget(row, col).currentIndexChanged.disconnect(self.callback_on_edited)
  2945. # except (TypeError, AttributeError):
  2946. # pass
  2947. # self.table_widget.cellWidget(row, col).currentIndexChanged.connect(self.callback_on_edited)
  2948. # except AttributeError:
  2949. # pass
  2950. #
  2951. # # CheckBox
  2952. # try:
  2953. # try:
  2954. # self.table_widget.cellWidget(row, col).toggled.disconnect(self.callback_on_edited)
  2955. # except (TypeError, AttributeError):
  2956. # pass
  2957. # self.table_widget.cellWidget(row, col).toggled.connect(self.callback_on_edited)
  2958. # except AttributeError:
  2959. # pass
  2960. #
  2961. # # SpinBox, DoubleSpinBox
  2962. # try:
  2963. # try:
  2964. # self.table_widget.cellWidget(row, col).valueChanged.disconnect(self.callback_on_edited)
  2965. # except (TypeError, AttributeError):
  2966. # pass
  2967. # self.table_widget.cellWidget(row, col).valueChanged.connect(self.callback_on_edited)
  2968. # except AttributeError:
  2969. # pass
  2970. #
  2971. # def ui_disconnect(self):
  2972. # try:
  2973. # self.table_widget.itemChanged.disconnect(self.callback_on_edited)
  2974. # except (TypeError, AttributeError):
  2975. # pass
  2976. #
  2977. # for row in range(self.table_widget.rowCount()):
  2978. # for col in range(self.table_widget.columnCount()):
  2979. # # ComboBox
  2980. # try:
  2981. # self.table_widget.cellWidget(row, col).currentIndexChanged.disconnect(self.callback_on_edited)
  2982. # except (TypeError, AttributeError):
  2983. # pass
  2984. #
  2985. # # CheckBox
  2986. # try:
  2987. # self.table_widget.cellWidget(row, col).toggled.disconnect(self.callback_on_edited)
  2988. # except (TypeError, AttributeError):
  2989. # pass
  2990. #
  2991. # # SpinBox, DoubleSpinBox
  2992. # try:
  2993. # self.table_widget.cellWidget(row, col).valueChanged.disconnect(self.callback_on_edited)
  2994. # except (TypeError, AttributeError):
  2995. # pass
  2996. #
  2997. # def callback_on_edited(self):
  2998. #
  2999. # # update the dictionary storage self.db_tool_dict
  3000. # self.db_tool_dict.clear()
  3001. # dict_elem = {}
  3002. # default_data = {}
  3003. #
  3004. # for row in range(self.table_widget.rowCount()):
  3005. # new_toolid = row + 1
  3006. # for col in range(self.table_widget.columnCount()):
  3007. # column_header_text = self.table_widget.horizontalHeaderItem(col).text()
  3008. # if column_header_text == _('Tool Name'):
  3009. # dict_elem['name'] = self.table_widget.item(row, col).text()
  3010. # elif column_header_text == _('Tool Dia'):
  3011. # dict_elem['tooldia'] = self.table_widget.cellWidget(row, col).get_value()
  3012. # elif column_header_text == _('Tool Offset'):
  3013. # dict_elem['offset'] = self.table_widget.cellWidget(row, col).get_value()
  3014. # elif column_header_text == _('Custom Offset'):
  3015. # dict_elem['offset_value'] = self.table_widget.cellWidget(row, col).get_value()
  3016. # elif column_header_text == _('Tool Type'):
  3017. # dict_elem['type'] = self.table_widget.cellWidget(row, col).get_value()
  3018. # elif column_header_text == _('Tool Shape'):
  3019. # dict_elem['tool_type'] = self.table_widget.cellWidget(row, col).get_value()
  3020. # else:
  3021. # if column_header_text == _('Cut Z'):
  3022. # default_data['cutz'] = self.table_widget.cellWidget(row, col).get_value()
  3023. # elif column_header_text == _('MultiDepth'):
  3024. # default_data['multidepth'] = self.table_widget.cellWidget(row, col).get_value()
  3025. # elif column_header_text == _('DPP'):
  3026. # default_data['depthperpass'] = self.table_widget.cellWidget(row, col).get_value()
  3027. # elif column_header_text == _('V-Dia'):
  3028. # default_data['vtipdia'] = self.table_widget.cellWidget(row, col).get_value()
  3029. # elif column_header_text == _('V-Angle'):
  3030. # default_data['vtipangle'] = self.table_widget.cellWidget(row, col).get_value()
  3031. # elif column_header_text == _('Travel Z'):
  3032. # default_data['travelz'] = self.table_widget.cellWidget(row, col).get_value()
  3033. # elif column_header_text == _('FR'):
  3034. # default_data['feedrate'] = self.table_widget.cellWidget(row, col).get_value()
  3035. # elif column_header_text == _('FR Z'):
  3036. # default_data['feedrate_z'] = self.table_widget.cellWidget(row, col).get_value()
  3037. # elif column_header_text == _('FR Rapids'):
  3038. # default_data['feedrate_rapid'] = self.table_widget.cellWidget(row, col).get_value()
  3039. # elif column_header_text == _('Spindle Speed'):
  3040. # default_data['spindlespeed'] = self.table_widget.cellWidget(row, col).get_value()
  3041. # elif column_header_text == _('Dwell'):
  3042. # default_data['dwell'] = self.table_widget.cellWidget(row, col).get_value()
  3043. # elif column_header_text == _('Dwelltime'):
  3044. # default_data['dwelltime'] = self.table_widget.cellWidget(row, col).get_value()
  3045. # elif column_header_text == _('Preprocessor'):
  3046. # default_data['ppname_g'] = self.table_widget.cellWidget(row, col).get_value()
  3047. # elif column_header_text == _('ExtraCut'):
  3048. # default_data['extracut'] = self.table_widget.cellWidget(row, col).get_value()
  3049. # elif column_header_text == _("E-Cut Length"):
  3050. # default_data['extracut_length'] = self.table_widget.cellWidget(row, col).get_value()
  3051. # elif column_header_text == _('Toolchange'):
  3052. # default_data['toolchange'] = self.table_widget.cellWidget(row, col).get_value()
  3053. # elif column_header_text == _('Toolchange XY'):
  3054. # default_data['toolchangexy'] = self.table_widget.item(row, col).text()
  3055. # elif column_header_text == _('Toolchange Z'):
  3056. # default_data['toolchangez'] = self.table_widget.cellWidget(row, col).get_value()
  3057. # elif column_header_text == _('Start Z'):
  3058. # default_data['startz'] = float(self.table_widget.item(row, col).text()) \
  3059. # if self.table_widget.item(row, col).text() != '' else None
  3060. # elif column_header_text == _('End Z'):
  3061. # default_data['endz'] = self.table_widget.cellWidget(row, col).get_value()
  3062. #
  3063. # dict_elem['data'] = default_data
  3064. # self.db_tool_dict.update(
  3065. # {
  3066. # new_toolid: deepcopy(dict_elem)
  3067. # }
  3068. # )
  3069. #
  3070. # self.callback_app()
  3071. #
  3072. # def on_tool_requested_from_app(self):
  3073. # if not self.table_widget.selectionModel().selectedRows():
  3074. # self.app.inform.emit('[WARNING_NOTCL] %s...' % _("No Tool/row selected in the Tools Database table"))
  3075. # return
  3076. #
  3077. # model_index_list = self.table_widget.selectionModel().selectedRows()
  3078. # for model_index in model_index_list:
  3079. # selected_row = model_index.row()
  3080. # tool_uid = selected_row + 1
  3081. # for key in self.db_tool_dict.keys():
  3082. # if str(key) == str(tool_uid):
  3083. # selected_tool = self.db_tool_dict[key]
  3084. # self.on_tool_request(tool=selected_tool)
  3085. #
  3086. # def on_cancel_tool(self):
  3087. # for idx in range(self.app_ui.plot_tab_area.count()):
  3088. # if self.app_ui.plot_tab_area.tabText(idx) == _("Tools Database"):
  3089. # wdg = self.app_ui.plot_tab_area.widget(idx)
  3090. # wdg.deleteLater()
  3091. # self.app_ui.plot_tab_area.removeTab(idx)
  3092. # self.app.inform.emit('%s' % _("Cancelled adding tool from DB."))
  3093. #
  3094. # # def resize_new_tool_table_widget(self, min_size, max_size):
  3095. # # """
  3096. # # Resize the table widget responsible for adding new tool in the Tool Database
  3097. # #
  3098. # # :param min_size: passed by rangeChanged signal or the self.new_tool_table_widget.horizontalScrollBar()
  3099. # # :param max_size: passed by rangeChanged signal or the self.new_tool_table_widget.horizontalScrollBar()
  3100. # # :return:
  3101. # # """
  3102. # # t_height = self.t_height
  3103. # # if max_size > min_size:
  3104. # # t_height = self.t_height + self.new_tool_table_widget.verticalScrollBar().height()
  3105. # #
  3106. # # self.new_tool_table_widget.setMaximumHeight(t_height)
  3107. #
  3108. # def closeEvent(self, QCloseEvent):
  3109. # super().closeEvent(QCloseEvent)