diff --git a/src/Mod/Path/Gui/Resources/panels/ToolBitEditor.ui b/src/Mod/Path/Gui/Resources/panels/ToolBitEditor.ui index 1ffb408a8a..42a5e98364 100644 --- a/src/Mod/Path/Gui/Resources/panels/ToolBitEditor.ui +++ b/src/Mod/Path/Gui/Resources/panels/ToolBitEditor.ui @@ -15,20 +15,12 @@ - + 0 - - - - 0 - 0 - 559 - 626 - - - + + Shape @@ -61,7 +53,7 @@ - Type + Shape File @@ -180,16 +172,8 @@ - - - - 0 - 0 - 559 - 626 - - - + + Attributes @@ -228,6 +212,8 @@
Gui/InputField.h
- + + + diff --git a/src/Mod/Path/Gui/Resources/panels/ToolBitLibraryEdit.ui b/src/Mod/Path/Gui/Resources/panels/ToolBitLibraryEdit.ui index b5cfdae83c..f9cdfec269 100644 --- a/src/Mod/Path/Gui/Resources/panels/ToolBitLibraryEdit.ui +++ b/src/Mod/Path/Gui/Resources/panels/ToolBitLibraryEdit.ui @@ -6,17 +6,17 @@ 0 0 - 958 - 508 + 954 + 587 ToolBit Library - - - - + + + + 0 @@ -30,247 +30,339 @@ 0 - - - <html><head/><body><p>Create a new library with an empty list of Tool Bits.</p></body></html> + + + 0 - - ... - - - - :/icons/document-new.svg:/icons/document-new.svg - - - - - - - <html><head/><body><p>Open an existing Tool Bit library.</p></body></html> - - - ... - - - - :/icons/document-open.svg:/icons/document-open.svg - - - - - - - <html><head/><body><p>Save Tool Bit library.</p></body></html> - - - ... - - - - :/icons/document-save.svg:/icons/document-save.svg - - - - - - - <html><head/><body><p>Save Tool Bit library under new name.</p></body></html> - - - ... - - - - :/icons/document-save-as.svg:/icons/document-save-as.svg - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - <html><head/><body><p>Edit Tool Bit library editor settings.</p></body></html> - - - ... - - - - :/icons/preferences-system.svg:/icons/preferences-system.svg - - + + + + + 226 + 16777215 + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + 0 + + + + + Tool Libraries + + + + + + + + 32 + 32 + + + + <html><head/><body><p>Rename Tool Table</p></body></html> + + + + + + + :/icons/edit-edit.svg:/icons/edit-edit.svg + + + + + + + + 32 + 32 + + + + <html><head/><body><p>Add New Tool Table</p></body></html> + + + + + + + :/icons/list-add.svg:/icons/list-add.svg + + + + + + + + 32 + 32 + + + + <html><head/><body><p>Remove Tool Table from Disc</p></body></html> + + + + + + + :/icons/list-remove.svg:/icons/list-remove.svg + + + + + + + + + QFrame::Box + + + + + + + + + + 0 + + + 0 + + + + + true + + + <html><head/><body><p>Table of Tool Bits of the library.</p></body></html> + + + QFrame::Box + + + QFrame::Sunken + + + 1 + + + 0 + + + true + + + QAbstractItemView::InternalMove + + + Qt::MoveAction + + + QAbstractItemView::SelectRows + + + true + + + false + + + + + + + + + Add Tool Controller(s) to Job + + + + :/icons/edit_OK.svg:/icons/edit_OK.svg + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 140 + 20 + + + + + + + + <html><head/><body><p>Close the Tool Bit Library Editor</p></body></html> + + + Cancel + + + + :/icons/button_invalid.svg:/icons/button_invalid.svg + + + + + + + <html><head/><body><p>Save the current Library</p></body></html> + + + Save Table + + + + :/icons/document-save.svg:/icons/document-save.svg + + + + + + + <html><head/><body><p>Save the library to a new file</p></body></html> + + + Save Table As... + + + + :/icons/document-save-as.svg:/icons/document-save-as.svg + + + + + + + + - - - - - 0 - - - 0 - - - - - true - - - <html><head/><body><p>Table of Tool Bits of the library.</p></body></html> - - - true - - - QAbstractItemView::InternalMove - - - Qt::MoveAction - - - QAbstractItemView::SelectRows - - - true - - - false - - - - - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - <html><head/><body><p>Add another Tool Bit to this library.</p><p><br/></p></body></html> - - - Add ... - - - - :/icons/list-add.svg:/icons/list-add.svg - - - - - - - <html><head/><body><p>Delete selected Tool Bit(s) from the library.</p><p><br/></p></body></html> - - - Delete - - - - :/icons/list-remove.svg:/icons/list-remove.svg - - - - - - - <html><head/><body><p>Assigned numbers to each Tool Bit according to its current position in the library. The first Tool Bit is assigned the ID 1.</p></body></html> - - - Enumerate - - - - - - - Qt::Vertical - - - - 20 - 115 - - - - - - - - - - - - - - Qt::Horizontal - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - + + + + + + + 0 + 0 + + + + + 420 + 0 + + + + true + + + + + + + <html><head/><body><p>Select the folder with the tool libraries to load.</p></body></html> + + + + + + + :/icons/document-open.svg:/icons/document-open.svg + + + + + + + Qt::Horizontal + + + + 20 + 20 + + + + + + + + <html><head/><body><p>Add existing Tool Bit to this library.</p><p><br/></p></body></html> + + + Add Toolbit + + + + :/icons/list-add.svg:/icons/list-add.svg + + + + + + + <html><head/><body><p>Delete selected Tool Bit(s) from the library.</p><p><br/></p></body></html> + + + Remove + + + + :/icons/list-remove.svg:/icons/list-remove.svg + + + + + + + <html><head/><body><p>Assigne numbers to each Tool Bit according to its current position in the library. The first Tool Bit is assigned the ID 1.</p></body></html> + + + Enumerate + + + + :/icons/button_sort.svg:/icons/button_sort.svg + + + +
- - - buttonBox - accepted() - Dialog - accept() - - - 248 - 254 - - - 157 - 274 - - - - - buttonBox - rejected() - Dialog - reject() - - - 316 - 260 - - - 286 - 274 - - - - + diff --git a/src/Mod/Path/Gui/Resources/preferences/PathJob.ui b/src/Mod/Path/Gui/Resources/preferences/PathJob.ui index 4b458788e5..9e1b6f7fcc 100644 --- a/src/Mod/Path/Gui/Resources/preferences/PathJob.ui +++ b/src/Mod/Path/Gui/Resources/preferences/PathJob.ui @@ -24,8 +24,8 @@ 0 0 - 467 - 448 + 424 + 537 @@ -142,8 +142,8 @@ 0 0 - 665 - 449 + 424 + 537 @@ -348,8 +348,8 @@ 0 0 - 431 - 718 + 407 + 570 @@ -625,8 +625,8 @@ 0 0 - 412 - 461 + 424 + 537 @@ -653,6 +653,13 @@
+ + + + Remember last library + + + diff --git a/src/Mod/Path/PathScripts/PathPreferences.py b/src/Mod/Path/PathScripts/PathPreferences.py index 0525a3b3f5..65eeefad59 100644 --- a/src/Mod/Path/PathScripts/PathPreferences.py +++ b/src/Mod/Path/PathScripts/PathPreferences.py @@ -44,9 +44,11 @@ PostProcessorOutputPolicy = "PostProcessorOutputPolicy" LastPathToolBit = "LastPathToolBit" LastPathToolLibrary = "LastPathToolLibrary" LastPathToolShape = "LastPathToolShape" +LastPathToolTable ="LastPathToolTable" UseLegacyTools = "UseLegacyTools" UseAbsoluteToolPaths = "UseAbsoluteToolPaths" +OpenLastLibrary = "OpenLastLibrary" # Linear tolerance to use when generating Paths, eg when tessellating geometry GeometryTolerance = "GeometryTolerance" @@ -83,7 +85,6 @@ def allEnabledPostProcessors(include = None): return l return enabled - def defaultPostProcessor(): pref = preferences() return pref.GetString(PostProcessorDefault, "") @@ -158,10 +159,14 @@ def toolsReallyUseLegacyTools(): def toolsStoreAbsolutePaths(): return preferences().GetBool(UseAbsoluteToolPaths, False) -def setToolsSettings(legacy, relative): +def toolsOpenLastLibrary(): + return preferences().GetBool(OpenLastLibrary, False) + +def setToolsSettings(legacy, relative, lastlibrary): pref = preferences() pref.SetBool(UseLegacyTools, legacy) pref.SetBool(UseAbsoluteToolPaths, relative) + pref.SetBool(OpenLastLibrary, lastlibrary) def defaultJobTemplate(): template = preferences().GetString(DefaultJobTemplate) @@ -190,7 +195,6 @@ def setPostProcessorDefaults(processor, args, blacklist): pref.SetString(PostProcessorDefaultArgs, args) pref.SetString(PostProcessorBlacklist, "%s" % (blacklist)) - def setOutputFileDefaults(fileName, policy): pref = preferences() pref.SetString(PostProcessorOutputFile, fileName) @@ -206,11 +210,13 @@ def defaultOutputPolicy(): def defaultStockTemplate(): return preferences().GetString(DefaultStockTemplate, "") + def setDefaultStockTemplate(template): preferences().SetString(DefaultStockTemplate, template) def defaultTaskPanelLayout(): return preferences().GetInt(DefaultTaskPanelLayout, 0) + def setDefaultTaskPanelLayout(style): preferences().SetInt(DefaultTaskPanelLayout, style) @@ -219,16 +225,24 @@ def experimentalFeaturesEnabled(): def lastPathToolBit(): return preferences().GetString(LastPathToolBit, pathDefaultToolsPath('Bit')) + def setLastPathToolBit(path): return preferences().SetString(LastPathToolBit, path) def lastPathToolLibrary(): return preferences().GetString(LastPathToolLibrary, pathDefaultToolsPath('Library')) + def setLastPathToolLibrary(path): return preferences().SetString(LastPathToolLibrary, path) def lastPathToolShape(): return preferences().GetString(LastPathToolShape, pathDefaultToolsPath('Shape')) + def setLastPathToolShape(path): return preferences().SetString(LastPathToolShape, path) +def lastPathToolTable(): + return preferences().GetString(LastPathToolTable, "") + +def setLastPathToolTable(table): + return preferences().SetString(LastPathToolTable, table) diff --git a/src/Mod/Path/PathScripts/PathPreferencesPathJob.py b/src/Mod/Path/PathScripts/PathPreferencesPathJob.py index 0782efd67b..a6d1a392e1 100644 --- a/src/Mod/Path/PathScripts/PathPreferencesPathJob.py +++ b/src/Mod/Path/PathScripts/PathPreferencesPathJob.py @@ -109,7 +109,9 @@ class JobPreferencesPage: PathPreferences.setDefaultStockTemplate('') def saveToolsSettings(self): - PathPreferences.setToolsSettings(self.form.toolsUseLegacy.isChecked(), self.form.toolsAbsolutePaths.isChecked()) + PathPreferences.setToolsSettings(self.form.toolsUseLegacy.isChecked(), + self.form.toolsAbsolutePaths.isChecked(), + self.form.toolsOpenLastLibrary.isChecked()) def selectComboEntry(self, widget, text): index = widget.findText(text, QtCore.Qt.MatchFixedString) diff --git a/src/Mod/Path/PathScripts/PathSetupSheetOpPrototype.py b/src/Mod/Path/PathScripts/PathSetupSheetOpPrototype.py index d089dd7f7a..a162bb4e04 100644 --- a/src/Mod/Path/PathScripts/PathSetupSheetOpPrototype.py +++ b/src/Mod/Path/PathScripts/PathSetupSheetOpPrototype.py @@ -142,6 +142,13 @@ class PropertyString(Property): def typeString(self): return "String" +class PropertyMap(Property): + def typeString(self): + return "Map" + + def displayString(self, value): + return str(value) + class OpPrototype(object): PropertyType = { @@ -159,6 +166,7 @@ class OpPrototype(object): 'App::PropertyLink': Property, 'App::PropertyLinkList': Property, 'App::PropertyLinkSubListGlobal': Property, + 'App::PropertyMap': PropertyMap, 'App::PropertyPercent': PropertyPercent, 'App::PropertyString': PropertyString, 'App::PropertyStringList': Property, diff --git a/src/Mod/Path/PathScripts/PathToolBit.py b/src/Mod/Path/PathScripts/PathToolBit.py index 7863e31df7..1286349fd4 100644 --- a/src/Mod/Path/PathScripts/PathToolBit.py +++ b/src/Mod/Path/PathScripts/PathToolBit.py @@ -44,8 +44,8 @@ __author__ = "sliptonic (Brad Collette)" __url__ = "http://www.freecadweb.org" __doc__ = "Class to deal with and represent a tool bit." -#PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule()) -#PathLog.trackModule() +# PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule()) +# PathLog.trackModule() def translate(context, text, disambig=None): return PySide.QtCore.QCoreApplication.translate(context, text, disambig) @@ -198,6 +198,7 @@ class ToolBit(object): def onDelete(self, obj, arg2=None): PathLog.track(obj.Label) self.unloadBitBody(obj) + obj.Document.removeObject(obj.Name) def _updateBitShape(self, obj, properties=None): if not obj.BitBody is None: @@ -233,6 +234,7 @@ class ToolBit(object): return (doc, docOpened) def _removeBitBody(self, obj): + print('in _removebitbody') if obj.BitBody: obj.BitBody.removeObjectsFromDocument() obj.Document.removeObject(obj.BitBody.Name) @@ -305,6 +307,7 @@ class ToolBit(object): return None def saveToFile(self, obj, path, setFile=True): + print('were saving now') try: with open(path, 'w') as fp: json.dump(self.shapeAttrs(obj), fp, indent=' ') @@ -329,7 +332,12 @@ class ToolBit(object): attrs['parameter'] = params params = {} for name in self.propertyNamesAttribute(obj): - params[name] = PathUtil.getPropertyValueString(obj, name) + #print(f"shapeattr {name}") + if name == "UserAttributes": + for key, value in obj.UserAttributes.items(): + params[key] = value + else: + params[name] = PathUtil.getPropertyValueString(obj, name) attrs['attribute'] = params return attrs @@ -346,6 +354,7 @@ class AttributePrototype(PathSetupSheetOpPrototype.OpPrototype): self.addProperty('App::PropertyDistance', 'LengthOffset', PropertyGroupAttribute, translate('PathToolBit', 'Length offset in Z direction')) self.addProperty('App::PropertyInteger', 'Flutes', PropertyGroupAttribute, translate('PathToolBit', 'The number of flutes')) self.addProperty('App::PropertyDistance', 'ChipLoad', PropertyGroupAttribute, translate('PathToolBit', 'Chipload as per manufacturer')) + self.addProperty('App::PropertyMap', 'UserAttributes', PropertyGroupAttribute, translate('PathTooolBit', 'User Defined Values')) class ToolBitFactory(object): @@ -361,11 +370,25 @@ class ToolBitFactory(object): obj.Proxy.unloadBitBody(obj) params = attrs['attribute'] proto = AttributePrototype() + uservals = {} for pname in params: - prop = proto.getProperty(pname) - val = prop.valueFromString(params[pname]) - print("prop[%s] = %s (%s)" % (pname, params[pname], type(val))) - prop.setupProperty(obj, pname, PropertyGroupAttribute, prop.valueFromString(params[pname])) + #print(f"pname: {pname}") + try: + prop = proto.getProperty(pname) + val = prop.valueFromString(params[pname]) + prop.setupProperty(obj, pname, PropertyGroupAttribute, prop.valueFromString(params[pname])) + except: + # prop = obj.addProperty('App::PropertyString', pname, "Attribute", translate('PathTooolBit', 'User Defined Value')) + # setattr(obj, pname, params[pname]) + prop = proto.getProperty("UserAttributes") + uservals.update({pname: params[pname]}) + #prop.setupProperty(obj, pname, "UserAttributes", prop.valueFromString(params[pname])) + + if len(uservals.items()) > 0: + prop.setupProperty(obj, "UserAttributes", PropertyGroupAttribute, uservals) + + # print("prop[%s] = %s (%s)" % (pname, params[pname], type(val))) + #prop.setupProperty(obj, pname, PropertyGroupAttribute, prop.valueFromString(params[pname])) return obj def CreateFrom(self, path, name='ToolBit'): diff --git a/src/Mod/Path/PathScripts/PathToolBitEdit.py b/src/Mod/Path/PathScripts/PathToolBitEdit.py index fdea4e672a..d6928b8bf5 100644 --- a/src/Mod/Path/PathScripts/PathToolBitEdit.py +++ b/src/Mod/Path/PathScripts/PathToolBitEdit.py @@ -84,32 +84,59 @@ class ToolBitEditor(object): self.proto = PathToolBit.AttributePrototype() self.props = sorted(self.proto.properties) self.delegate = PathSetupSheetGui.Delegate(self.form) - self.model = QtGui.QStandardItemModel(len(self.props), 3, self.form) + self.model = QtGui.QStandardItemModel(len(self.props)-1, 3, self.form) self.model.setHorizontalHeaderLabels(['Set', 'Property', 'Value']) + for i, name in enumerate(self.props): + print(f"propname: {name}") + prop = self.proto.getProperty(name) isset = hasattr(tool, name) + if isset: prop.setValue(getattr(tool, name)) - self.model.setData(self.model.index(i, 0), isset, QtCore.Qt.EditRole) - self.model.setData(self.model.index(i, 1), name, QtCore.Qt.EditRole) - self.model.setData(self.model.index(i, 2), prop, PathSetupSheetGui.Delegate.PropertyRole) - self.model.setData(self.model.index(i, 2), prop.displayString(), QtCore.Qt.DisplayRole) + if name == "UserAttributes": + continue - self.model.item(i, 0).setCheckable(True) - self.model.item(i, 0).setText('') - self.model.item(i, 1).setEditable(False) - self.model.item(i, 1).setToolTip(prop.info) - self.model.item(i, 2).setToolTip(prop.info) - - if isset: - self.model.item(i, 0).setCheckState(QtCore.Qt.Checked) else: - self.model.item(i, 0).setCheckState(QtCore.Qt.Unchecked) - self.model.item(i, 1).setEnabled(False) - self.model.item(i, 2).setEnabled(False) + + self.model.setData(self.model.index(i, 0), isset, QtCore.Qt.EditRole) + self.model.setData(self.model.index(i, 1), name, QtCore.Qt.EditRole) + self.model.setData(self.model.index(i, 2), prop, PathSetupSheetGui.Delegate.PropertyRole) + self.model.setData(self.model.index(i, 2), prop.displayString(), QtCore.Qt.DisplayRole) + + self.model.item(i, 0).setCheckable(True) + self.model.item(i, 0).setText('') + self.model.item(i, 1).setEditable(False) + self.model.item(i, 1).setToolTip(prop.info) + self.model.item(i, 2).setToolTip(prop.info) + + if isset: + self.model.item(i, 0).setCheckState(QtCore.Qt.Checked) + else: + self.model.item(i, 0).setCheckState(QtCore.Qt.Unchecked) + self.model.item(i, 1).setEnabled(False) + self.model.item(i, 2).setEnabled(False) + + if hasattr(tool, "UserAttributes"): + for key, value in tool.UserAttributes.items(): + print(key, value) + c1 = QtGui.QStandardItem() + c1.setCheckable(False) + c1.setEditable(False) + c1.setCheckState(QtCore.Qt.CheckState.Checked) + + c1.setText('') + c2 = QtGui.QStandardItem(key) + c2.setEditable(False) + c3 = QtGui.QStandardItem(value) + c3.setEditable(False) + + self.model.appendRow([c1, c2, c3]) + #QtGui.QStandardItem([True, key, value])) + self.form.attrTable.setModel(self.model) self.form.attrTable.setItemDelegateForColumn(2, self.delegate) diff --git a/src/Mod/Path/PathScripts/PathToolBitLibraryCmd.py b/src/Mod/Path/PathScripts/PathToolBitLibraryCmd.py index ae5573013b..e418192b60 100644 --- a/src/Mod/Path/PathScripts/PathToolBitLibraryCmd.py +++ b/src/Mod/Path/PathScripts/PathToolBitLibraryCmd.py @@ -25,6 +25,7 @@ import FreeCAD import FreeCADGui import PySide.QtCore as QtCore +import PathScripts.PathPreferences as PathPreferences class CommandToolBitLibraryOpen: ''' @@ -45,7 +46,13 @@ class CommandToolBitLibraryOpen: def Activated(self): import PathScripts.PathToolBitLibraryGui as PathToolBitLibraryGui library = PathToolBitLibraryGui.ToolBitLibrary() - library.open() + + lastlib = PathPreferences.lastPathToolLibrary() + + if PathPreferences.toolsOpenLastLibrary(): + library.open(lastlib) + else: + library.open() class CommandToolBitLibraryLoad: ''' @@ -83,7 +90,8 @@ class CommandToolBitLibraryLoad: import PathScripts.PathToolControllerGui as PathToolControllerGui library = PathToolBitLibraryGui.ToolBitLibrary() - if 1 == library.open(dialog=True) and job: + + if 1 == library.open() and job: for nr, tool in library.selectedOrAllTools(): tc = PathToolControllerGui.Create("TC: {}".format(tool.Label), tool, nr) job.Proxy.addToolController(tc) diff --git a/src/Mod/Path/PathScripts/PathToolBitLibraryGui.py b/src/Mod/Path/PathScripts/PathToolBitLibraryGui.py index 17b12638a2..455183cf04 100644 --- a/src/Mod/Path/PathScripts/PathToolBitLibraryGui.py +++ b/src/Mod/Path/PathScripts/PathToolBitLibraryGui.py @@ -3,6 +3,7 @@ # *************************************************************************** # * * # * Copyright (c) 2019 sliptonic * +# * Copyright (c) 2020 Schildkroet * # * * # * This program is free software; you can redistribute it and/or modify * # * it under the terms of the GNU Lesser General Public License (LGPL) * @@ -23,16 +24,22 @@ # *************************************************************************** +import FreeCAD import FreeCADGui import PathScripts.PathLog as PathLog import PathScripts.PathPreferences as PathPreferences import PathScripts.PathToolBit as PathToolBit import PathScripts.PathToolBitGui as PathToolBitGui +import PathScripts.PathToolBitEdit as PathToolBitEdit +import PathScripts.PathToolControllerGui as PathToolControllerGui +import PathScripts.PathUtilsGui as PathUtilsGui +from PySide import QtCore, QtGui import PySide import json import os import traceback import uuid as UUID +from functools import partial #PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule()) #PathLog.trackModule(PathLog.thisModule()) @@ -40,6 +47,9 @@ import uuid as UUID _UuidRole = PySide.QtCore.Qt.UserRole + 1 _PathRole = PySide.QtCore.Qt.UserRole + 2 +def translate(context, text, disambig=None): + return PySide.QtCore.QCoreApplication.translate(context, text, disambig) + class _TableView(PySide.QtGui.QTableView): '''Subclass of QTableView to support rearrange and copying of ToolBits''' @@ -134,8 +144,13 @@ class ToolBitLibrary(object): self.form.toolTable.hide() self.setupUI() self.title = self.form.windowTitle() + self.LibFiles = [] if path: self.libraryLoad(path) + + self.form.addToolController.setEnabled(False) + self.form.ButtonRemoveToolTable.setEnabled(False) + self.form.ButtonRenameToolTable.setEnabled(False) def _toolAdd(self, nr, tool, path): toolNr = PySide.QtGui.QStandardItem() @@ -187,11 +202,30 @@ class ToolBitLibrary(object): tools.append((toolNr, PathToolBit.Factory.CreateFrom(toolPath))) return tools + def selectedOrAllToolControllers(self): + tools = self.selectedOrAllTools() + + userinput = PathUtilsGui.PathUtilsUserInput() + job = userinput.chooseJob(PathUtilsGui.PathUtils.GetJobs()) + for tool in tools: + print(tool) + tc = PathToolControllerGui.Create(tool[1].Label, tool[1], tool[0]) + job.Proxy.addToolController(tc) + FreeCAD.ActiveDocument.recompute() + def toolDelete(self): PathLog.track() selectedRows = set([index.row() for index in self.toolTableView.selectedIndexes()]) for row in sorted(list(selectedRows), key = lambda r: -r): self.model.removeRows(row, 1) + + def libraryDelete(self): + PathLog.track() + reply = QtGui.QMessageBox.question(self.form, 'Warning', "Delete " + os.path.basename(self.path) + "?", QtGui.QMessageBox.Yes | QtGui.QMessageBox.Cancel) + if reply == QtGui.QMessageBox.Yes and len(self.path) > 0: + os.remove(self.path) + PathPreferences.setLastPathToolTable("") + self.libraryOpen(filedialog=False) def toolEnumerate(self): PathLog.track() @@ -200,19 +234,30 @@ class ToolBitLibrary(object): def toolSelect(self, selected, deselected): # pylint: disable=unused-argument - self.form.toolDelete.setEnabled(len(self.toolTableView.selectedIndexes()) > 0) + sel = len(self.toolTableView.selectedIndexes()) > 0 + self.form.toolDelete.setEnabled(sel) + + if sel: + self.form.addToolController.setEnabled(True) + else: + self.form.addToolController.setEnabled(False) + + def tableSelected(self, index): + ''' loads the tools for the selected tool table ''' + name = self.form.TableList.itemWidget(self.form.TableList.itemFromIndex(index)).getTableName() + self.libraryLoad(PathPreferences.lastPathToolLibrary() + '/' + name) + self.form.ButtonRemoveToolTable.setEnabled(True) + self.form.ButtonRenameToolTable.setEnabled(True) def open(self, path=None, dialog=False): '''open(path=None, dialog=False) ... load library stored in path and bring up ui. Returns 1 if user pressed OK, 0 otherwise.''' if path: - fullPath = PathToolBit.findLibrary(path) - if fullPath: - self.libraryLoad(fullPath) - else: - self.libraryOpen() + self.libraryOpen(path, filedialog=False) elif dialog: - self.libraryOpen() + self.libraryOpen(None, True) + else: + self.libraryOpen(None, False) return self.form.exec_() def updateToolbar(self): @@ -221,21 +266,78 @@ class ToolBitLibrary(object): else: self.form.librarySave.setEnabled(False) - def libraryOpen(self): + def libraryOpen(self, path = None, filedialog=True): + import glob PathLog.track() - foo = PySide.QtGui.QFileDialog.getOpenFileName(self.form, 'Tool Library', PathPreferences.lastPathToolLibrary(), '*.fctl') - if foo and foo[0]: - path = foo[0] - PathPreferences.setLastPathToolLibrary(os.path.dirname(path)) - self.libraryLoad(path) + + # Load default search path + path = PathPreferences.lastPathToolLibrary() + + if filedialog or len(path) == 0: + path = PySide.QtGui.QFileDialog.getExistingDirectory(self.form, 'Tool Library Path', PathPreferences.lastPathToolLibrary()) + if len(path) > 0: + PathPreferences.setLastPathToolLibrary(path) + else: + return + + # Clear view + self.form.TableList.clear() + self.LibFiles.clear() + self.form.lineLibPath.clear() + self.form.lineLibPath.insert(path) + + # Find all tool tables in directory + for file in glob.glob(path + '/*.fctl'): + self.LibFiles.append(file) + + self.LibFiles.sort() + + # Add all tables to list + for table in self.LibFiles: + listWidgetItem = QtGui.QListWidgetItem() + listItem = ToolTableListWidgetItem() + listItem.setTableName(os.path.basename(table)) + listItem.setIcon(QtGui.QPixmap(':/icons/Path-ToolTable.svg')) + #listItem.toolMoved.connect(self.reloadReset) + listWidgetItem.setSizeHint(QtCore.QSize(0,40)) + self.form.TableList.addItem(listWidgetItem) + self.form.TableList.setItemWidget(listWidgetItem, listItem) + + self.path = [] + self.form.ButtonRemoveToolTable.setEnabled(False) + self.form.ButtonRenameToolTable.setEnabled(False) + + self.toolTableView.setUpdatesEnabled(False) + self.model.clear() + self.model.setHorizontalHeaderLabels(self.columnNames()) + self.toolTableView.resizeColumnsToContents() + self.toolTableView.setUpdatesEnabled(True) + + # Search last selected table + if len(self.LibFiles) > 0: + for idx in range(len(self.LibFiles)): + if PathPreferences.lastPathToolTable() == os.path.basename(self.LibFiles[idx]): + break + # Not found, select first entry + if idx >= len(self.LibFiles): + idx = 0 + + # Load selected table + self.libraryLoad(self.LibFiles[idx]) + self.form.TableList.setCurrentRow(idx) + self.form.ButtonRemoveToolTable.setEnabled(True) + self.form.ButtonRenameToolTable.setEnabled(True) def libraryLoad(self, path): self.toolTableView.setUpdatesEnabled(False) self.model.clear() self.model.setHorizontalHeaderLabels(self.columnNames()) + if path: with open(path) as fp: + PathPreferences.setLastPathToolTable(os.path.basename(path)) library = json.load(fp) + for toolBit in library['tools']: nr = toolBit['nr'] bit = PathToolBit.findBit(toolBit['path']) @@ -245,7 +347,9 @@ class ToolBitLibrary(object): self._toolAdd(nr, tool, bit) else: PathLog.error("Could not find tool #{}: {}".format(nr, library['tools'][nr])) + self.toolTableView.resizeColumnsToContents() + self.toolTableView.setUpdatesEnabled(True) self.form.setWindowTitle("{} - {}".format(self.title, os.path.basename(path) if path else '')) @@ -254,6 +358,29 @@ class ToolBitLibrary(object): def libraryNew(self): self.libraryLoad(None) + self.librarySaveAs() + + def renameLibrary(self): + name = self.form.TableList.itemWidget(self.form.TableList.currentItem()).getTableName() + newName, ok = QtGui.QInputDialog.getText(None, translate("TooltableEditor","Rename Tooltable"),translate("TooltableEditor","Enter Name:"),QtGui.QLineEdit.Normal,name) + if ok and newName: + os.rename(PathPreferences.lastPathToolLibrary() + '/' + name, PathPreferences.lastPathToolLibrary() + '/' + newName) + self.libraryOpen(filedialog=False) + + #def createToolBit(self): + # tool = PathToolBit.ToolBitFactory().Create() + + # #self.dialog = PySide.QtGui.QDialog(self.form) + # #layout = PySide.QtGui.QVBoxLayout(self.dialog) + # self.editor = PathToolBitEdit.ToolBitEditor(tool, self.form.toolTableGroup) + # self.editor.setupUI() + # self.buttons = PySide.QtGui.QDialogButtonBox( + # PySide.QtGui.QDialogButtonBox.Ok | PySide.QtGui.QDialogButtonBox.Cancel, + # PySide.QtCore.Qt.Horizontal, self.dialog) + # layout.addWidget(self.buttons) + # #self.buttons.accepted.connect(accept) + # #self.buttons.rejected.connect(reject) + # print(self.dialog.exec_()) def librarySave(self): library = {} @@ -271,18 +398,94 @@ class ToolBitLibrary(object): with open(self.path, 'w') as fp: json.dump(library, fp, sort_keys=True, indent=2) + def libararySaveLinuxCNC(self, path): + with open(path, 'w') as fp: + fp.write(";\n") + + for row in range(self.model.rowCount()): + toolNr = self.model.data(self.model.index(row, 0), PySide.QtCore.Qt.EditRole) + toolPath = self.model.data(self.model.index(row, 0), _PathRole) + + bit = PathToolBit.Factory.CreateFrom(toolPath) + if bit: + PathLog.track(bit) + + pocket = bit.Pocket if hasattr(bit, "Pocket") else "" + xoffset = bit.Xoffset if hasattr(bit, "Xoffset") else "0" + yoffset = bit.Yoffset if hasattr(bit, "Yoffset") else "0" + zoffset = bit.Zoffset if hasattr(bit, "Zoffset") else "0" + aoffset = bit.Aoffset if hasattr(bit, "Aoffset") else "0" + boffset = bit.Boffset if hasattr(bit, "Boffset") else "0" + coffset = bit.Coffset if hasattr(bit, "Coffset") else "0" + uoffset = bit.Uoffset if hasattr(bit, "Uoffset") else "0" + voffset = bit.Voffset if hasattr(bit, "Voffset") else "0" + woffset = bit.Woffset if hasattr(bit, "Woffset") else "0" + + diameter = bit.Diameter if hasattr(bit, "Diameter") else "0" + frontangle = bit.FrontAngle if hasattr(bit, "FrontAngle") else "0" + backangle = bit.BackAngle if hasattr(bit, "BackAngle") else "0" + orientation = bit.Orientation if hasattr(bit, "Orientation") else "0" + remark = bit.Label + + fp.write(f"T{toolNr} "\ + f"P{pocket} "\ + f"X{xoffset} "\ + f"Y{yoffset} "\ + f"Z{zoffset} "\ + f"A{aoffset} "\ + f"B{boffset} "\ + f"C{coffset} "\ + f"U{uoffset} "\ + f"V{voffset} "\ + f"W{woffset} "\ + f"D{diameter} "\ + f"I{frontangle} "\ + f"J{backangle} "\ + f"Q{orientation} ;"\ + f"{remark}\n") + + FreeCAD.ActiveDocument.removeObject(bit.Name) + + else: + PathLog.error("Could not find tool #{}: {}".format(nr, library['tools'][nr])) + def librarySaveAs(self): - foo = PySide.QtGui.QFileDialog.getSaveFileName(self.form, 'Tool Library', PathPreferences.lastPathToolLibrary(), '*.fctl') - if foo and foo[0]: - path = foo[0] if foo[0].endswith('.fctl') else "{}.fctl".format(foo[0]) - PathPreferences.setLastPathToolLibrary(os.path.dirname(path)) - self.path = path - self.librarySave() - self.updateToolbar() + TooltableTypeJSON = translate("PathToolLibraryManager", "Tooltable JSON (*.fctl)") + TooltableTypeLinuxCNC = translate("PathToolLibraryManager", "LinuxCNC tooltable (*.tbl)") + + filename = PySide.QtGui.QFileDialog.getSaveFileName(self.form, \ + translate("TooltableEditor", "Save toolbit library", None), \ + PathPreferences.lastPathToolLibrary(), "{};;{}".format(TooltableTypeJSON, \ + TooltableTypeLinuxCNC)) + # filename = PySide.QtGui.QFileDialog.getSaveFileName(self.form, \ + # 'Tool Library', PathPreferences.lastPathToolLibrary(), '*.fctl') + if filename and filename[0]: + if filename[1] == TooltableTypeLinuxCNC: + path = filename[0] if filename[0].endswith('.tbl') else "{}.tbl".format(filename[0]) + self.libararySaveLinuxCNC(path) + else: + path = filename[0] if filename[0].endswith('.fctl') else "{}.fctl".format(filename[0]) + PathPreferences.setLastPathToolLibrary(os.path.dirname(path)) + self.path = path + self.librarySave() + self.updateToolbar() + PathPreferences.setLastPathToolTable(os.path.basename(path)) + self.libraryOpen(None, False) + + def libraryCancel(self): + self.form.close() def columnNames(self): return ['Nr', 'Tool', 'Shape', 'Diameter'] + def toolEdit(self, selected): + print('here') + print(selected) + if selected.column() == 0: + print('nope') + else: + print('yep') + def setupUI(self): PathLog.track('+') self.model = PySide.QtGui.QStandardItemModel(0, len(self.columnNames()), self.toolTableView) @@ -291,16 +494,73 @@ class ToolBitLibrary(object): self.toolTableView.setModel(self.model) self.toolTableView.resizeColumnsToContents() self.toolTableView.selectionModel().selectionChanged.connect(self.toolSelect) + self.toolTableView.doubleClicked.connect(self.toolEdit) self.form.toolAdd.clicked.connect(self.toolAdd) self.form.toolDelete.clicked.connect(self.toolDelete) self.form.toolEnumerate.clicked.connect(self.toolEnumerate) + # self.form.createToolBit.clicked.connect(self.createToolBit) - self.form.libraryNew.clicked.connect(self.libraryNew) - self.form.libraryOpen.clicked.connect(self.libraryOpen) + self.form.ButtonAddToolTable.clicked.connect(self.libraryNew) + self.form.ButtonRemoveToolTable.clicked.connect(self.libraryDelete) + self.form.ButtonRenameToolTable.clicked.connect(self.renameLibrary) + + #self.form.libraryNew.clicked.connect(self.libraryNew) + self.form.libraryOpen.clicked.connect(partial(self.libraryOpen, filedialog=True)) self.form.librarySave.clicked.connect(self.librarySave) self.form.librarySaveAs.clicked.connect(self.librarySaveAs) + self.form.libraryCancel.clicked.connect(self.libraryCancel) + + self.form.addToolController.clicked.connect(self.selectedOrAllToolControllers) + + self.form.TableList.clicked.connect(self.tableSelected) self.toolSelect([], []) self.updateToolbar() PathLog.track('-') + + +class ToolTableListWidgetItem(QtGui.QWidget): + toolMoved = QtCore.Signal() + + def __init__(self): + super(ToolTableListWidgetItem, self).__init__() + + #self.tlm = TLM + self.setAcceptDrops(True) + + self.mainLayout = QtGui.QHBoxLayout() + self.iconQLabel = QtGui.QLabel() + self.tableNameLabel = QtGui.QLabel() + self.mainLayout.addWidget(self.iconQLabel, 0) + self.mainLayout.addWidget(self.tableNameLabel, 1) + self.setLayout(self.mainLayout) + + def setTableName (self, text): + self.tableNameLabel.setText(text) + + def getTableName(self): + return self.tableNameLabel.text() + + def setIcon (self, icon): + icon = icon.scaled(22, 22) + self.iconQLabel.setPixmap(icon) + + def dragEnterEvent(self, e): + #currentToolTable = self.tlm.getCurrentTableName() + thisToolTable = self.getTableName() + + #if not currentToolTable == thisToolTable: + # e.accept() + #else: + # e.ignore() + + def dropEvent(self, e): + selectedTools = e.source().selectedIndexes() + print("Drop: {}, {}".format(selectedTools, selectedTools[1].data())) + #if selectedTools: + #toolData = selectedTools[1].data() + + #if toolData: + #self.tlm.moveToTable(int(toolData), self.getTableName()) + #self.toolMoved.emit()