Commit 989d52e8 authored by sumpfralle's avatar sumpfralle

moved tool handling to a separate plugin


git-svn-id: https://pycam.svn.sourceforge.net/svnroot/pycam/trunk@1116 bbaffbd6-741e-11dd-a85d-61de82d9cad9
parent c2f9b155
......@@ -82,6 +82,10 @@
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkVBox" id="vbox1">
<property name="visible">True</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkVButtonBox" id="vbuttonbox1">
<property name="visible">True</property>
......@@ -93,7 +97,6 @@
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="tooltip_text" translatable="yes">Remove the selected models</property>
<property name="use_stock">True</property>
</object>
<packing>
......@@ -108,7 +111,6 @@
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="tooltip_text" translatable="yes">Remove all models</property>
<property name="use_stock">True</property>
</object>
<packing>
......@@ -122,7 +124,6 @@
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="tooltip_text" translatable="yes">Change the color of the selected models</property>
<property name="use_alpha">True</property>
<property name="color">#000000000000</property>
</object>
......@@ -160,6 +161,11 @@
<property name="position">4</property>
</packing>
</child>
</object>
<packing>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkLinkButton" id="ModelTransformationsHelp">
<property name="label">gtk-help</property>
......@@ -173,7 +179,7 @@
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">5</property>
<property name="position">1</property>
</packing>
</child>
</object>
......@@ -184,7 +190,7 @@
</child>
</object>
<packing>
<property name="resize">False</property>
<property name="resize">True</property>
<property name="shrink">False</property>
</packing>
</child>
......@@ -195,7 +201,7 @@
<property name="tab_pos">left</property>
</object>
<packing>
<property name="resize">True</property>
<property name="resize">False</property>
<property name="shrink">False</property>
</packing>
</child>
......
This source diff could not be displayed because it is too large. You can view the blob instead.
<?xml version="1.0"?>
<interface>
<!-- interface-requires gtk+ 2.12 -->
<!-- interface-naming-policy project-wide -->
<object class="GtkAdjustment" id="torusdiameter">
<property name="lower">0.0001</property>
<property name="upper">500</property>
<property name="step_increment">0.050000000000000003</property>
</object>
<object class="GtkAdjustment" id="tooldiameter">
<property name="lower">0.0001</property>
<property name="upper">500</property>
<property name="step_increment">0.10000000000000001</property>
</object>
<object class="GtkListStore" id="ToolList">
<columns>
<!-- column-name object_ref -->
<column type="guint"/>
<!-- column-name tool_id -->
<column type="guint"/>
<!-- column-name name -->
<column type="gchararray"/>
</columns>
<data>
<row>
<col id="0">0</col>
<col id="1">0</col>
<col id="2" translatable="yes">test</col>
</row>
</data>
</object>
<object class="GtkVPaned" id="ToolBox">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkHBox" id="hbox9">
<property name="visible">True</property>
<property name="spacing">4</property>
<child>
<object class="GtkScrolledWindow" id="scrolledwindow6">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="hscrollbar_policy">automatic</property>
<property name="vscrollbar_policy">automatic</property>
<property name="shadow_type">etched-in</property>
<child>
<object class="GtkTreeView" id="ToolEditorTable">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="model">ToolList</property>
<property name="headers_clickable">False</property>
<property name="search_column">0</property>
<child>
<object class="GtkTreeViewColumn" id="ToolTableIDColumn">
<property name="title">Tool ID</property>
<child>
<object class="GtkCellRendererText" id="ToolTableIDCell">
<property name="editable">True</property>
</object>
<attributes>
<attribute name="text">1</attribute>
</attributes>
</child>
</object>
</child>
<child>
<object class="GtkTreeViewColumn" id="ToolTableNameColumn">
<property name="title">Name</property>
<property name="expand">True</property>
<child>
<object class="GtkCellRendererText" id="ToolTableNameCell">
<property name="editable">True</property>
</object>
<attributes>
<attribute name="text">2</attribute>
</attributes>
</child>
</object>
</child>
<child>
<object class="GtkTreeViewColumn" id="ToolTableShapeColumn">
<property name="title">Shape</property>
<child>
<object class="GtkCellRendererText" id="ToolTableShapeCell">
<property name="alignment">right</property>
</object>
</child>
</object>
</child>
</object>
</child>
</object>
<packing>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkVBox" id="vbox16">
<property name="visible">True</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkVButtonBox" id="vbuttonbox1">
<property name="visible">True</property>
<property name="orientation">vertical</property>
<property name="layout_style">center</property>
<child>
<object class="GtkButton" id="ToolNew">
<property name="label">gtk-new</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="use_stock">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkButton" id="ToolDelete">
<property name="label">gtk-delete</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="use_stock">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkButton" id="ToolMoveUp">
<property name="label">gtk-go-up</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="use_stock">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">2</property>
</packing>
</child>
<child>
<object class="GtkButton" id="ToolMoveDown">
<property name="label">gtk-go-down</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="use_stock">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">3</property>
</packing>
</child>
</object>
<packing>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkLinkButton" id="ToolHelp">
<property name="label">gtk-help</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="relief">none</property>
<property name="use_stock">True</property>
<property name="uri">http://sourceforge.net/apps/mediawiki/pycam/index.php?title=ToolTypes</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="resize">True</property>
<property name="shrink">False</property>
</packing>
</child>
<child>
<object class="GtkVBox" id="ToolSettingsControlsBox">
<property name="visible">True</property>
<property name="orientation">vertical</property>
<property name="spacing">4</property>
<child>
<object class="GtkHBox" id="hbox3">
<property name="visible">True</property>
<property name="spacing">3</property>
<child>
<object class="GtkFrame" id="frame6">
<property name="visible">True</property>
<property name="label_xalign">0</property>
<property name="shadow_type">none</property>
<child>
<object class="GtkAlignment" id="alignment14">
<property name="visible">True</property>
<property name="yalign">0</property>
<property name="yscale">0</property>
<property name="top_padding">3</property>
<property name="bottom_padding">3</property>
<property name="left_padding">12</property>
<child>
<object class="GtkVBox" id="vbox19">
<property name="visible">True</property>
<property name="orientation">vertical</property>
<property name="spacing">4</property>
<property name="homogeneous">True</property>
<child>
<object class="GtkRadioButton" id="CylindricalCutter">
<property name="label" translatable="yes">Flat end</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="draw_indicator">True</property>
<property name="group">SphericalCutter</property>
</object>
<packing>
<property name="expand">False</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkRadioButton" id="SphericalCutter">
<property name="label" translatable="yes">Ball nose</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="active">True</property>
<property name="draw_indicator">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkRadioButton" id="ToroidalCutter">
<property name="label" translatable="yes">Bull nose</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="draw_indicator">True</property>
<property name="group">SphericalCutter</property>
</object>
<packing>
<property name="expand">False</property>
<property name="position">2</property>
</packing>
</child>
</object>
</child>
</object>
</child>
<child type="label">
<object class="GtkLabel" id="ToolTypeLabel">
<property name="visible">True</property>
<property name="label" translatable="yes">&lt;b&gt;Shape&lt;/b&gt;</property>
<property name="use_markup">True</property>
</object>
</child>
</object>
<packing>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkVSeparator" id="vseparator5">
<property name="visible">True</property>
<property name="orientation">vertical</property>
</object>
<packing>
<property name="expand">False</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkFrame" id="frame10">
<property name="visible">True</property>
<property name="label_xalign">0</property>
<property name="shadow_type">none</property>
<child>
<object class="GtkAlignment" id="alignment18">
<property name="visible">True</property>
<property name="yalign">0</property>
<property name="yscale">0</property>
<property name="top_padding">3</property>
<property name="bottom_padding">3</property>
<property name="left_padding">12</property>
<child>
<object class="GtkTable" id="table3">
<property name="visible">True</property>
<property name="n_rows">2</property>
<property name="n_columns">2</property>
<property name="column_spacing">2</property>
<property name="row_spacing">4</property>
<child>
<object class="GtkLabel" id="ToolDiameterLabel">
<property name="visible">True</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">Tool Diameter:</property>
</object>
<packing>
<property name="x_options">GTK_FILL</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="TorusDiameterLabel">
<property name="visible">True</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">Torus Diameter:</property>
</object>
<packing>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
<property name="x_options">GTK_FILL</property>
</packing>
</child>
<child>
<object class="GtkSpinButton" id="ToolDiameterControl">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="invisible_char">&#x25CF;</property>
<property name="adjustment">tooldiameter</property>
<property name="digits">4</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options">GTK_FILL</property>
</packing>
</child>
<child>
<object class="GtkSpinButton" id="TorusDiameterControl">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="invisible_char">&#x25CF;</property>
<property name="adjustment">torusdiameter</property>
<property name="digits">4</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options">GTK_FILL</property>
</packing>
</child>
</object>
</child>
</object>
</child>
<child type="label">
<object class="GtkLabel" id="DimensionsLabel">
<property name="visible">True</property>
<property name="label" translatable="yes">&lt;b&gt;Dimensions&lt;/b&gt;</property>
<property name="use_markup">True</property>
</object>
</child>
</object>
<packing>
<property name="position">2</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="position">0</property>
</packing>
</child>
</object>
<packing>
<property name="resize">True</property>
<property name="shrink">False</property>
</packing>
</child>
</object>
</interface>
......@@ -425,6 +425,10 @@ class ProjectGui(object):
self.settings.register_event("model-change-after", self.update_view)
self.settings.register_event("visual-item-updated", self.update_view)
self.settings.register_event("visual-item-updated", self.update_model_dimensions)
def update_emc_tool_button():
tool_num = len(self.settings.get("tools"))
self.gui.get_object("ExportEMCToolDefinition").set_sensitive(tool_num > 0)
self.settings.register_event("tool-selection-changed", update_emc_tool_button)
self.settings.set("load_model", self.load_model)
self.settings.register_event("boundary-updated", self.update_view)
# configure drag-n-drop for config files and models
......@@ -469,7 +473,6 @@ class ProjectGui(object):
# set defaults
self.toolpath = pycam.Toolpath.ToolpathList()
self.cutter = None
self.tool_list = []
self.process_list = []
self.bounds_list = []
self.task_list = []
......@@ -485,7 +488,7 @@ class ProjectGui(object):
def add_main_tab_item(item, name):
main_tab.append_page(item, gtk.Label(name))
# TODO: move these to plugins, as well
tab_names = ("Tools", "Processes", "Bounds", "Tasks", "Toolpaths")
tab_names = ("Processes", "Bounds", "Tasks", "Toolpaths")
for name in tab_names:
item = self.gui.get_object(name + "Tab")
item.unparent()
......@@ -493,7 +496,7 @@ class ProjectGui(object):
clear_main_tab)
for name in tab_names:
item = self.gui.get_object(name + "Tab")
self.settings.register_ui("main", name, item, tab_names.index(name))
self.settings.register_ui("main", name, item, tab_names.index(name) + 100)
main_window = self.gui.get_object("WindowBox")
def clear_main_window():
main_window.foreach(lambda x: main_window.remove(x))
......@@ -668,13 +671,6 @@ class ProjectGui(object):
self.settings.add_item("drill_progress_max_fps", skip_obj.get_value, skip_obj.set_value)
sim_detail_obj = self.gui.get_object("SimulationDetailsValue")
self.settings.add_item("simulation_details_level", sim_detail_obj.get_value, sim_detail_obj.set_value)
# drill settings
for objname in ("ToolDiameterControl", "TorusDiameterControl",
"FeedrateControl", "SpindleSpeedControl"):
self.gui.get_object(objname).connect("value-changed", self.handle_tool_settings_change)
for name in ("SphericalCutter", "CylindricalCutter", "ToroidalCutter"):
self.gui.get_object(name).connect("clicked", self.handle_tool_settings_change)
self.gui.get_object("ToolName").connect("changed", self.handle_tool_settings_change)
# connect the "consistency check" and the update-handler with all toolpath settings
for objname in ("PushRemoveStrategy", "ContourPolygonStrategy",
"ContourFollowStrategy", "SurfaceStrategy",
......@@ -714,9 +710,7 @@ class ProjectGui(object):
else:
self._treeview_set_active_index(table, new_index)
# update all controls related the (possibly changed) item
if item_list is self.tool_list:
self.append_to_queue(self.switch_tool_table_selection)
elif item_list is self.process_list:
if item_list is self.process_list:
self.append_to_queue(self.switch_process_table_selection)
elif item_list is self.task_list:
self.append_to_queue(self.switch_tasklist_table_selection)
......@@ -793,16 +787,6 @@ class ProjectGui(object):
self.simulation_window.connect("delete-event", self.finish_toolpath_simulation)
# store the original content (for adding the number of current toolpaths in "update_toolpath_table")
self._original_toolpath_tab_label = self.gui.get_object("ToolpathsTabLabel").get_text()
# tool editor
self.settings.add_item("current_tool",
lambda: get_current_item(self.tool_editor_table, self.tool_list),
lambda tool: set_current_item(self.tool_editor_table, self.tool_list, tool))
self.tool_editor_table = self.gui.get_object("ToolEditorTable")
self.tool_editor_table.get_selection().connect("changed", self.switch_tool_table_selection)
self.gui.get_object("ToolListMoveUp").connect("clicked", self._tool_editor_button_event, "move_up")
self.gui.get_object("ToolListMoveDown").connect("clicked", self._tool_editor_button_event, "move_down")
self.gui.get_object("ToolListAdd").connect("clicked", self._tool_editor_button_event, "add")
self.gui.get_object("ToolListDelete").connect("clicked", self._tool_editor_button_event, "delete")
# the task list manager
self.settings.add_item("current_task",
lambda: get_current_item(self.tasklist_table, self.task_list),
......@@ -1033,7 +1017,6 @@ class ProjectGui(object):
def update_all_controls(self):
self.update_toolpath_table()
self.update_tool_table()
self.update_process_controls()
self.update_process_table()
self.update_bounds_table()
......@@ -1389,7 +1372,7 @@ class ProjectGui(object):
self.gui.get_object("GenerateToolPathButton").set_sensitive(selection_active)
# "add" is only allowed, if there are any tools, processes and bounds
self.gui.get_object("TaskListAdd").set_sensitive(
(len(self.tool_list) > 0) \
(len(self.settings.get("tools")) > 0) \
and (len(self.process_list) > 0) \
and (len(self.bounds_list) > 0))
details_box = self.gui.get_object("TaskDetails")
......@@ -1414,7 +1397,7 @@ class ProjectGui(object):
obj.handler_block(signal_handler)
self.gui.get_object("TaskNameControl").set_text(task["name"])
tool = task["tool"]
self.gui.get_object("TaskToolSelector").set_active(self.tool_list.index(tool))
self.gui.get_object("TaskToolSelector").set_active(self.settings.get("tools").index(tool))
process = task["process"]
self.gui.get_object("TaskProcessSelector").set_active(self.process_list.index(process))
bounds = task["bounds"]
......@@ -1454,7 +1437,7 @@ class ProjectGui(object):
tasklist_model.clear()
# remove broken tasks from the list (tool or process was deleted)
self.task_list = [task for task in self.task_list
if (task["tool"] in self.tool_list) \
if (task["tool"] in self.settings.get("tools")) \
and (task["process"] in self.process_list) \
and (task["bounds"] in self.bounds_list)]
counter = 0
......@@ -1468,8 +1451,7 @@ class ProjectGui(object):
def switch_tasklist_table_selection(self, widget=None):
current_task = self.settings.get("current_task")
if not current_task is None:
self.settings.set("current_tool", current_task["tool"])
self.update_tool_table(skip_model_update=True)
self.settings.get("tools").select(current_task["tool"])
self.settings.set("current_process", current_task["process"])
self.update_process_table(skip_model_update=True)
self.settings.set("current_bounds", current_task["bounds"])
......@@ -1488,7 +1470,7 @@ class ProjectGui(object):
if old_name != new_name:
task["name"] = new_name
tool_id = self.gui.get_object("TaskToolSelector").get_active()
task["tool"] = self.tool_list[tool_id]
task["tool"] = self.settings.get("tools")[tool_id]
process_id = self.gui.get_object("TaskProcessSelector").get_active()
task["process"] = self.process_list[process_id]
bounds_id = self.gui.get_object("TaskBoundsSelector").get_active()
......@@ -1523,7 +1505,7 @@ class ProjectGui(object):
while [True for task in self.task_list if task["name"] == "%s%d" % (prefix, index)]:
index += 1
new_task["name"] = "%s%d" % (prefix, index)
new_task["tool"] = self.tool_list[0]
new_task["tool"] = self.settings.get("tools")[0]
new_task["process"] = self.process_list[0]
new_task["bounds"] = self.bounds_list[0]
new_task["enabled"] = True
......@@ -1620,24 +1602,6 @@ class ProjectGui(object):
for one_control in all_controls:
get_obj(one_control).set_sensitive(one_control in active_controls[strategy])
def update_tool_controls(self, widget=None, data=None):
# disable the toroidal radius if the toroidal cutter is not enabled
if self.gui.get_object("ToroidalCutter").get_active():
self.gui.get_object("TorusDiameterControl").show()
self.gui.get_object("TorusDiameterLabel").show()
else:
self.gui.get_object("TorusDiameterControl").hide()
self.gui.get_object("TorusDiameterLabel").hide()
for objname, default_value in (("ToolDiameterControl", 1.0),
("TorusDiameterControl", 0.25),
("SpindleSpeedControl", 1000),
("FeedrateControl", 200)):
obj = self.gui.get_object(objname)
if obj.get_value() == 0:
# set the value to the configured minimum
obj.set_value(default_value)
self.gui.get_object("ExportEMCToolDefinition").set_sensitive(len(self.tool_list) > 0)
@gui_activity_guard
def toggle_about_window(self, widget=None, event=None, state=None):
# only "delete-event" uses four arguments
......@@ -1819,8 +1783,7 @@ class ProjectGui(object):
item = datalist[index]
# Check if we need to remove items that depended on the currently
# deleted one.
if not datalist in (self.tool_list, self.process_list,
self.bounds_list):
if not datalist in (self.process_list, self.bounds_list):
# tasks do not depend on this list - just continue
pass
elif len(datalist) == 1:
......@@ -1836,7 +1799,7 @@ class ProjectGui(object):
# Replace all references to the to-be-deleted item with the
# alternative.
for task in self.task_list:
for sublist in ("tool", "process", "bounds"):
for sublist in ("process", "bounds"):
if item is task[sublist]:
task[sublist] = alternative
# Delete the object. Maybe this is not necessary, if it was the
......@@ -1852,12 +1815,10 @@ class ProjectGui(object):
future_selection_index = len(datalist) - 1
# update the tasklist table (maybe we removed some items)
self.update_tasklist_table()
# also update the specific description of the tool/process/bounds
# also update the specific description of the process/bounds
if not future_selection_index is None:
if datalist is self.tool_list:
self.settings.set("current_tool",
self.tool_list[future_selection_index])
self.switch_tool_table_selection()
if datalist is self.settings.get("tools"):
self.settings.get("tools").select(future_selection_index)
elif datalist is self.process_list:
self.settings.set("current_process",
self.process_list[future_selection_index])
......@@ -1875,111 +1836,6 @@ class ProjectGui(object):
update_func(new_index=future_selection_index,
skip_model_update=skip_model_update)
def _put_tool_settings_to_gui(self, settings):
self.gui.get_object("ToolName").set_text(settings["name"])
# cutter shapes
def set_cutter_shape_name(value):
self.gui.get_object(value).set_active(True)
set_cutter_shape_name(settings["shape"])
for objname, key in (
("FeedrateControl", "feedrate"),
("SpindleSpeedControl", "speed")):
self.gui.get_object(objname).set_value(settings[key])
# radius -> diameter
for objname, key in (
("ToolDiameterControl", "tool_radius"),
("TorusDiameterControl", "torus_radius")):
self.gui.get_object(objname).set_value(2 * settings[key])
def _load_tool_settings_from_gui(self, settings=None):
if settings is None:
settings = {}
settings["name"] = self.gui.get_object("ToolName").get_text()
def get_cutter_shape_name():
for name in ("SphericalCutter", "CylindricalCutter", "ToroidalCutter"):
if self.gui.get_object(name).get_active():
return name
settings["shape"] = get_cutter_shape_name()
for objname, key in (
("FeedrateControl", "feedrate"),
("SpindleSpeedControl", "speed")):
settings[key] = self.gui.get_object(objname).get_value()
# diameter -> radius
for objname, key in (
("ToolDiameterControl", "tool_radius"),
("TorusDiameterControl", "torus_radius")):
settings[key] = 0.5 * self.gui.get_object(objname).get_value()
return settings
@gui_activity_guard
def handle_tool_settings_change(self, widget=None, data=None):
current_tool = self.settings.get("current_tool")
if not current_tool is None:
self._load_tool_settings_from_gui(current_tool)
self.update_tool_table()
self.update_tool_controls()
@gui_activity_guard
def switch_tool_table_selection(self, widget=None, data=None):
current_tool = self.settings.get("current_tool")
# hide all controls if no process is defined
if not current_tool is None:
self.gui.get_object("ToolSettingsControlsBox").show()
self._put_tool_settings_to_gui(current_tool)
self.update_tool_table()
else:
self.gui.get_object("ToolSettingsControlsBox").hide()
@gui_activity_guard
def _tool_editor_button_event(self, widget, data, action=None):
# "toggle" uses two parameters - all other actions have only one
if action is None:
action = data
self._treeview_button_event(self.tool_editor_table, self.tool_list, action, self.update_tool_table)
if action == "add":
# look for the first unused default name
prefix = "New Tool "
index = 1
# loop while the current name is in use
while [True for process in self.tool_list if process["name"] == "%s%d" % (prefix, index)]:
index += 1
new_settings = self._load_tool_settings_from_gui()
new_settings["name"] = "%s%d" % (prefix, index)
self.tool_list.append(new_settings)
self.update_tool_table(self.tool_list.index(new_settings))
self._put_tool_settings_to_gui(new_settings)
elif action == "delete":
self.append_to_queue(self.switch_tool_table_selection)
def update_tool_table(self, new_index=None, skip_model_update=False):
tool_model = self.gui.get_object("ToolList")
if new_index is None:
# keep the old selection - this may return "None" if nothing is selected
new_index = self._treeview_get_active_index(self.tool_editor_table, self.tool_list)
if not skip_model_update:
tool_model.clear()
counter = 0
for tool in self.tool_list:
# add the tool size to the descriptive text
description = "%s (d=%s)" % (tool["name"], 2 * tool["tool_radius"])
tool_model.append((counter, counter + 1, description))
counter += 1
if not new_index is None:
self._treeview_set_active_index(self.tool_editor_table, new_index)
# en/disable some buttons
selection_active = not new_index is None
self.gui.get_object("ToolListDelete").set_sensitive(selection_active)
self.gui.get_object("ToolListMoveUp").set_sensitive(selection_active and new_index > 0)
self.gui.get_object("ToolListMoveDown").set_sensitive(selection_active and new_index < len(self.tool_list) - 1)
# hide all controls if no process is defined
if new_index is None:
self.gui.get_object("ToolSettingsControlsBox").hide()
else:
self.gui.get_object("ToolSettingsControlsBox").show()
# remove any broken tasks and update changed names
self.update_tool_controls()
self.update_task_description()
def change_unit_init(self, widget=None):
new_unit = self.gui.get_object("unit_control").get_active_text()
if self._last_unit is None:
......@@ -2063,8 +1919,9 @@ class ProjectGui(object):
pass
if self.gui.get_object("UnitChangeTools").get_active():
# scale all tool dimensions
for tool in self.tool_list:
for tool in self.settings.get("tools"):
for key in ("tool_radius", "torus_radius"):
# TODO: fix this invalid access
tool[key] *= factor
self.unit_change_window.hide()
# store the current unit (for the next run of this function)
......@@ -2072,7 +1929,6 @@ class ProjectGui(object):
# update all labels containing the unit size
self.update_unit_labels()
# update all controls and redraw the boundaries
self.switch_tool_table_selection()
self.switch_process_table_selection()
self.switch_bounds_table_selection()
self.switch_tasklist_table_selection()
......@@ -2339,7 +2195,6 @@ class ProjectGui(object):
log.error("Failed to detect filetype!")
return False
@gui_activity_guard
def export_emc_tools(self, widget=None, filename=None):
if callable(filename):
filename = filename()
......@@ -2348,7 +2203,7 @@ class ProjectGui(object):
mode_load=False, type_filter=FILTER_EMC_TOOL,
filename_templates=(self.last_model_uri,))
if filename:
export = pycam.Exporters.EMCToolExporter.EMCToolExporter(self.tool_list)
export = pycam.Exporters.EMCToolExporter.EMCToolExporter(self.settings.get("tools"))
text = export.get_tool_definition_string()
try:
out = file(filename, "w")
......@@ -2410,14 +2265,13 @@ class ProjectGui(object):
if not filename is None:
settings.load_file(filename)
# flush all tables (without re-assigning new objects)
for one_list in (self.tool_list, self.process_list, self.bounds_list, self.task_list):
for one_list in (self.settings.get("tools"), self.process_list, self.bounds_list, self.task_list):
while len(one_list) > 0:
one_list.pop()
self.tool_list.extend(settings.get_tools())
#self.settings.get("tools").extend(settings.get_tools())
self.process_list.extend(settings.get_processes())
self.bounds_list.extend(settings.get_bounds())
self.task_list.extend(settings.get_tasks())
self.update_tool_table()
self.update_process_table()
self.update_bounds_table()
self.update_tasklist_table()
......@@ -2882,7 +2736,7 @@ class ProjectGui(object):
if not filename:
return
settings = pycam.Gui.Settings.ProcessSettings()
if not settings.write_to_file(filename, self.tool_list,
if not settings.write_to_file(filename, self.settings.get("tools"),
self.process_list, self.bounds_list, self.task_list):
log.error("Failed to save settings file")
else:
......@@ -3155,7 +3009,8 @@ class ProjectGui(object):
toolpath_settings.set_bounds(processing_bounds)
# put the tool settings together
tool_id = self.tool_list.index(tool_settings) + 1
tools = self.settings.get("tools")
tool_id = tools.get_attr("id")
toolpath_settings.set_tool(tool_id, tool_settings["shape"],
tool_settings["tool_radius"], tool_settings["torus_radius"],
tool_settings["speed"], tool_settings["feedrate"])
......
......@@ -32,7 +32,7 @@ class Models(pycam.Plugins.ListPluginBase):
UI_FILE = "models.ui"
COLUMN_ID, COLUMN_NAME, COLUMN_VISIBLE, COLUMN_COLOR, COLUMN_ALPHA = range(5)
ATTRIBUTE_MAP = {"name": COLUMN_NAME, "visible": COLUMN_VISIBLE,
LIST_ATTRIBUTE_MAP = {"name": COLUMN_NAME, "visible": COLUMN_VISIBLE,
"color": COLUMN_COLOR, "alpha": COLUMN_ALPHA}
ICONS = {"visible": "visible.svg", "hidden": "visible_off.svg"}
# TODO: move this to the preferences dialog
......@@ -75,7 +75,7 @@ class Models(pycam.Plugins.ListPluginBase):
selection.connect("changed",
lambda widget, event: self.core.emit_event(event),
"model-selection-changed")
selection.set_mode(gtk.SELECTION_MULTIPLE)
selection.set_mode(self._gtk.SELECTION_MULTIPLE)
self._treemodel = self.gui.get_object("ModelList")
self._treemodel.clear()
def update_model():
......@@ -96,30 +96,9 @@ class Models(pycam.Plugins.ListPluginBase):
int(self.DEFAULT_COLOR[3] * _GTK_COLOR_MAX)))
self._get_colors_of_selected_models()
self.register_model_update(update_model)
self.core.add_item("models", lambda: self)
self.core.set("models", self)
return True
def get_attr(self, model, attr):
return self.__get_set_attr(model, attr, write=False)
def set_attr(self, model, attr, value):
return self.__get_set_attr(model, attr, value=value, write=True)
def __get_set_attr(self, model, attr, value=None, write=True):
if attr in self.ATTRIBUTE_MAP:
col = self.ATTRIBUTE_MAP[attr]
for index in range(len(self)):
if self._treemodel[index][self.COLUMN_ID] == id(model):
if write:
self._treemodel[index][col] = value
return
else:
return self._treemodel[index][col]
raise IndexError("Model not found: %s" % str(model))
else:
raise KeyError("Attribute '%s' is not part of this list: %s" % \
(attr, ", ".join(self.ATTRIBUTE_MAP.keys())))
def _get_colors_of_selected_models(self, widget=None):
color_button = self.gui.get_object("ModelColorButton")
models = self.get_selected()
......@@ -144,7 +123,8 @@ class Models(pycam.Plugins.ListPluginBase):
def _edit_model_name(self, cell, path, new_text):
path = int(path)
if new_text != self._treemodel[path][self.COLUMN_NAME]:
if (new_text != self._treemodel[path][self.COLUMN_NAME]) and \
new_text:
self._treemodel[path][self.COLUMN_NAME] = new_text
def _visualize_visible_state(self, column, cell, model, m_iter):
......
# -*- coding: utf-8 -*-
"""
$Id$
Copyright 2011 Lars Kruse <devel@sumpfralle.de>
This file is part of PyCAM.
PyCAM is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
PyCAM is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with PyCAM. If not, see <http://www.gnu.org/licenses/>.
"""
import pycam.Plugins
from pycam.Cutters.CylindricalCutter import CylindricalCutter
from pycam.Cutters.SphericalCutter import SphericalCutter
from pycam.Cutters.ToroidalCutter import ToroidalCutter
class Tools(pycam.Plugins.ListPluginBase):
UI_FILE = "tools.ui"
COLUMN_REF, COLUMN_ID, COLUMN_NAME = range(3)
LIST_ATTRIBUTE_MAP = {"id": COLUMN_ID, "name": COLUMN_NAME}
SHAPE_MAP = {CylindricalCutter: ("CylindricalCutter", "Flat end"),
SphericalCutter: ("SphericalCutter", "Ball nose"),
ToroidalCutter: ("ToroidalCutter", "Bull nose")}
def setup(self):
if self.gui:
tool_frame = self.gui.get_object("ToolBox")
tool_frame.unparent()
self.core.register_ui("main", "Tools", tool_frame, weight=10)
self._modelview = self.gui.get_object("ToolEditorTable")
for action, obj_name in ((self.ACTION_UP, "ToolMoveUp"),
(self.ACTION_DOWN, "ToolMoveDown"),
(self.ACTION_DELETE, "ToolDelete")):
self.register_list_action_button(action, self._modelview,
self.gui.get_object(obj_name))
self.gui.get_object("ToolNew").connect("clicked", self._tool_new)
selection = self._modelview.get_selection()
selection.connect("changed",
lambda widget, event: self.core.emit_event(event),
"tool-selection-changed")
cell = self.gui.get_object("ToolTableShapeCell")
self.gui.get_object("ToolTableShapeColumn").set_cell_data_func(
cell, self._visualize_tool_size)
self.gui.get_object("ToolTableIDCell").connect("edited",
self._edit_tool_id)
self.gui.get_object("ToolTableNameCell").connect("edited",
self._edit_tool_name)
self._treemodel = self.gui.get_object("ToolList")
self._treemodel.clear()
def update_model():
if not hasattr(self, "_model_cache"):
self._model_cache = {}
cache = self._model_cache
for row in self._treemodel:
cache[row[self.COLUMN_ID]] = list(row)
self._treemodel.clear()
for index, item in enumerate(self):
if id(item) in cache:
self._treemodel.append(cache[id(item)])
else:
self._treemodel.append((id(item), index + 1,
"Tool #%d" % index))
self.register_model_update(update_model)
# drill settings
self._detail_handlers = []
for objname in ("ToolDiameterControl", "TorusDiameterControl"):
obj = self.gui.get_object(objname)
handler = obj.connect("value-changed",
lambda *args: self.core.emit_event(args[-1]),
"tool-changed")
self._detail_handlers.append((obj, handler))
for objname in ("SphericalCutter", "CylindricalCutter",
"ToroidalCutter"):
obj = self.gui.get_object(objname)
handler = obj.connect("toggled",
lambda *args: self.core.emit_event(args[-1]),
"tool-changed")
self._detail_handlers.append((obj, handler))
self.core.register_event("tool-selection-changed",
self._tool_change)
self.core.register_event("tool-changed",
self._update_tool_controls)
self._update_tool_controls()
self.core.set("tools", self)
return True
def teardown(self):
if self.gui:
self.core.unregister_ui("main", self.gui.get_object("ToolBox"))
self.core.set("tools", None)
return True
def get_selected(self, index=False):
return self._get_selected(self._modelview, index=index)
def select(self, tool):
if tool in self:
selection = self._modelview.get_selection()
index = self.index(tool)
selection.unselect_all()
selection.select_path((index,))
def _visualize_tool_size(self, column, cell, model, m_iter):
path = model.get_path(m_iter)
tool = self[path[0]]
for cutter_class, (objname, desc) in self.SHAPE_MAP.iteritems():
if isinstance(tool, cutter_class):
break
text = "%s (%g%s)" % (desc, 2 * tool.radius, self.core.get("unit"))
cell.set_property("text", text)
def _edit_tool_name(self, cell, path, new_text):
path = int(path)
if (new_text != self._treemodel[path][self.COLUMN_NAME]) and \
new_text:
self._treemodel[path][self.COLUMN_NAME] = new_text
def _edit_tool_id(self, cell, path, new_text):
path = int(path)
try:
new_value = int(new_text)
except ValueError:
return
if str(new_value) != self._treemodel[path][self.COLUMN_ID]:
self._treemodel[path][self.COLUMN_ID] = new_value
def _update_tool_controls(self):
tool_index = self.get_selected(index=True)
if tool_index is None:
self.gui.get_object("ToolSettingsControlsBox").hide()
return
# disable the toroidal radius if the toroidal cutter is not enabled
if self.gui.get_object("ToroidalCutter").get_active():
self.gui.get_object("TorusDiameterControl").show()
self.gui.get_object("TorusDiameterLabel").show()
else:
self.gui.get_object("TorusDiameterControl").hide()
self.gui.get_object("TorusDiameterLabel").hide()
for objname, default_value in (("ToolDiameterControl", 1.0),
("TorusDiameterControl", 0.25)):
obj = self.gui.get_object(objname)
if obj.get_value() == 0:
# set the value to the configured minimum
obj.set_value(default_value)
# update the tool object
for cutter_class, (objname, desc) in self.SHAPE_MAP.iteritems():
if self.gui.get_object(objname).get_active():
break
radius = 0.5 * self.gui.get_object("ToolDiameterControl").get_value()
if cutter_class is ToroidalCutter:
args = [0.5 * self.gui.get_object("TorusDiameterControl").get_value()]
else:
args = []
new_tool = cutter_class(radius, *args)
self.pop(tool_index)
self.insert(tool_index, new_tool)
self.select(new_tool)
def _tool_change(self, widget=None, data=None):
tool = self.get_selected()
control_box = self.gui.get_object("ToolSettingsControlsBox")
if not tool:
control_box.hide()
else:
for obj, handler in self._detail_handlers:
obj.handler_block(handler)
# cutter shapes
for cutter_class, (objname, desc) in self.SHAPE_MAP.iteritems():
if isinstance(tool, cutter_class):
self.gui.get_object(objname).set_active(True)
# radius -> diameter
self.gui.get_object("ToolDiameterControl").set_value(2 * tool.radius)
torus_control = self.gui.get_object("TorusDiameterControl")
torus_label = self.gui.get_object("TorusDiameterLabel")
if hasattr(tool, "minorradius"):
torus_control.set_value(2 * tool.minorradius)
torus_control.show()
torus_label.show()
else:
torus_control.set_value(0.25)
torus_control.hide()
torus_label.hide()
for obj, handler in self._detail_handlers:
obj.handler_unblock(handler)
control_box.show()
def _tool_new(self, *args):
current_tool_index = self.get_selected(index=True)
if current_tool_index is None:
current_tool_index = 0
new_tool = CylindricalCutter(1.0)
self.insert(current_tool_index, new_tool)
self.select(new_tool)
......@@ -150,13 +150,14 @@ class PluginManager(object):
class ListPluginBase(PluginBase, list):
ACTION_UP, ACTION_DOWN, ACTION_DELETE, ACTION_CLEAR = range(4)
LIST_ATTRIBUTE_MAP = {}
def __init__(self, *args, **kwargs):
super(ListPluginBase, self).__init__(*args, **kwargs)
self._update_model_funcs = []
def get_function(func_name):
return lambda *args, **kwargs: self._change_wrapper(func_name, *args, **kwargs)
for name in "append", "insert", "pop", "reverse", "sort":
for name in ("append", "insert", "pop", "reverse", "sort"):
setattr(self, name, get_function(name))
def _change_wrapper(self, func_name, *args, **kwargs):
......@@ -279,3 +280,24 @@ class ListPluginBase(PluginBase, list):
modelview, action, button)
button.connect("clicked", self._list_action, modelview, action)
def get_attr(self, model, attr):
return self.__get_set_attr(model, attr, write=False)
def set_attr(self, model, attr, value):
return self.__get_set_attr(model, attr, value=value, write=True)
def __get_set_attr(self, model, attr, value=None, write=True):
if attr in self.LIST_ATTRIBUTE_MAP:
col = self.LIST_ATTRIBUTE_MAP[attr]
for index in range(len(self)):
if self._treemodel[index][self.COLUMN_ID] == id(model):
if write:
self._treemodel[index][col] = value
return
else:
return self._treemodel[index][col]
raise IndexError("Model not found: %s" % str(model))
else:
raise KeyError("Attribute '%s' is not part of this list: %s" % \
(attr, ", ".join(self.LIST_ATTRIBUTE_MAP.keys())))
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment