# -*- coding: utf-8 -*- """ $Id$ Copyright 2011 Lars Kruse 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 . """ import pycam.Plugins import pycam.Gui.ControlsGTK class GCodePreferences(pycam.Plugins.PluginBase): DEPENDS = [] CATEGORIES = ["GCode"] UI_FILE = "gcode_preferences.ui" def setup(self): if self.gui: import gtk notebook = self.gui.get_object("GCodePrefsNotebook") self._pref_items = [] def clear_preferences(): for child in notebook.get_children(): notebook.remove(child) # we need to clear the whole path down to the "real" item parent = notebook while not child in self._pref_items: parent.remove(child) parent = child try: child = child.get_children()[0] except (AttributeError, IndexError): # We encountered an invalid item (e.g. a label # without children) or an empty item. break else: # we found a valid child -> remove it parent.remove(child) def add_preferences_item(item, name): if not item in self._pref_items: self._pref_items.append(item) item.unparent() if not isinstance(item, gtk.Frame): # create a simple default frame if none was given frame = gtk.Frame(name) frame.get_label_widget().set_markup("%s" % name) frame.set_shadow_type(gtk.SHADOW_NONE) align = gtk.Alignment() align.set_padding(3, 0, 12, 0) frame.add(align) frame.show() align.add(item) align.show() item.show() item = frame notebook.append_page(item, gtk.Label(name)) self.core.register_ui_section("gcode_preferences", add_preferences_item, clear_preferences) general_widget = pycam.Gui.ControlsGTK.ParameterSection() general_widget.widget.show() self.core.register_ui_section("gcode_general_parameters", general_widget.add_widget, general_widget.clear_widgets) self.core.register_ui("gcode_preferences", "General", general_widget.widget) self.core.register_ui("toolpath_handling", "Settings", self.gui.get_object("PreferencesControls")) self.gui.get_object("PreferencesButton").connect("clicked", self._toggle_window, True) self.gui.get_object("CloseButton").connect("clicked", self._toggle_window, False) self.window = self.gui.get_object("GCodePreferencesWindow") self.window.connect("delete-event", self._toggle_window, False) return True def teardown(self): if self.gui: self._toggle_window(False) def _toggle_window(self, *args): status = args[-1] if status: self.window.show() else: self.window.hide() # don't destroy the window return True class GCodeSafetyHeight(pycam.Plugins.PluginBase): DEPENDS = ["GCodePreferences"] CATEGORIES = ["GCode"] def setup(self): self.safety_height = pycam.Gui.ControlsGTK.InputNumber(digits=0, change_handler=lambda *args: \ self.core.emit_event("visual-item-updated")) # TODO: this should be done via parameter groups based on postprocessors self.safety_height.get_widget().show() self.core.register_ui("gcode_general_parameters", "Safety Height", self.safety_height.get_widget(), weight=20) self.core.add_item("gcode_safety_height", self.safety_height.get_value, self.safety_height.set_value) self.register_state_item("settings/gcode/gcode_safety_height", self.safety_height.get_value, self.safety_height.set_value) return True def teardown(self): self.clear_state_items() del self.core["gcode_safety_height"] self.safety_height.destroy() class GCodeFilenameExtension(pycam.Plugins.PluginBase): DEPENDS = ["GCodePreferences"] CATEGORIES = ["GCode"] def setup(self): self.filename_extension = pycam.Gui.ControlsGTK.InputString( max_length=6) # TODO: this should be done via parameter groups based on postprocessors self.filename_extension.get_widget().show() self.core.register_ui("gcode_general_parameters", "Custom GCode filename extension", self.filename_extension.get_widget(), weight=80) self.core.add_item("gcode_filename_extension", self.filename_extension.get_value, self.filename_extension.set_value) return True def teardown(self): del self.core["gcode_filename_extension"] self.filename_extension.destroy() class GCodeStepWidth(pycam.Plugins.PluginBase): DEPENDS = ["GCodePreferences"] CATEGORIES = ["GCode"] def setup(self): table = pycam.Gui.ControlsGTK.ParameterSection() self.core.register_ui("gcode_preferences", "Step precision", table.widget) self.core.register_ui_section("gcode_step_width", table.add_widget, table.clear_widgets) self.controls = [] for key in "xyz": control = pycam.Gui.ControlsGTK.InputNumber(digits=8, start=0.0001, increment=0.00005) # TODO: this should be done via parameter groups based on postprocessors name = "gcode_minimum_step_%s" % key control.get_widget().show() self.core.add_item(name, control.get_value, control.set_value) self.core.register_ui("gcode_step_width", key.upper(), control.get_widget(), weight="xyz".index(key)) self.register_state_item("settings/gcode/%s" % name, control.get_value, control.set_value) self.controls.append(control) return True def teardown(self): self.clear_state_items() while self.controls: self.core.unregister_ui("gcode_step_width", self.controls.pop()) for key in "xyz": del self.core["gcode_minimum_step_%s" % key] class GCodeSpindle(pycam.Plugins.PluginBase): DEPENDS = ["GCodePreferences"] CATEGORIES = ["GCode"] def setup(self): self._table = pycam.Gui.ControlsGTK.ParameterSection() self.core.register_ui("gcode_preferences", "Spindle control", self._table.widget) self.core.register_ui_section("gcode_spindle", self._table.add_widget, self._table.clear_widgets) self.spindle_delay = pycam.Gui.ControlsGTK.InputNumber(digits=1) # TODO: this should be done via parameter groups based on postprocessors self.spindle_delay.get_widget().show() self.core.register_ui("gcode_spindle", "Delay (in seconds) after start/stop", self.spindle_delay.get_widget(), weight=50) self.core.add_item("gcode_spindle_delay", self.spindle_delay.get_value, self.spindle_delay.set_value) self.spindle_enable = pycam.Gui.ControlsGTK.InputCheckBox( change_handler=self.update_widgets) self.spindle_enable.get_widget().show() self.core.register_ui("gcode_spindle", "Start / Stop Spindle (M3/M5)", self.spindle_enable.get_widget(), weight=10) self.update_widgets() return True def teardown(self): del self.core["gcode_spindle_delay"] self.core.unregister_ui("gcode_spindle", self.spindle_delay.get_widget()) self.core.unregister_ui("gcode_spindle", self.spindle_enable.get_widget()) self.core.unregister_ui_section("gcode_spindle") self.core.unregister_ui("gcode_preferences", self._table.widget) def update_widgets(self, widget=None): widget = self.spindle_delay.get_widget() widget.set_sensitive(self.spindle_enable.get_value()) class GCodeCornerStyle(pycam.Plugins.PluginBase): DEPENDS = ["GCodePreferences"] CATEGORIES = ["GCode"] def setup(self): table = pycam.Gui.ControlsGTK.ParameterSection() self.core.register_ui("gcode_preferences", "Corner style", table.widget) self.core.register_ui_section("gcode_corner_style", table.add_widget, table.clear_widgets) self.motion_tolerance = pycam.Gui.ControlsGTK.InputNumber(digits=3) # TODO: this should be done via parameter groups based on postprocessors self.motion_tolerance.get_widget().show() self.core.register_ui("gcode_corner_style", "Motion blending tolerance", self.motion_tolerance.get_widget(), weight=30) self.naive_tolerance = pycam.Gui.ControlsGTK.InputNumber(digits=3) self.naive_tolerance.get_widget().show() self.core.register_ui("gcode_corner_style", "Naive CAM tolerance", self.naive_tolerance.get_widget(), weight=50) self.path_mode = pycam.Gui.ControlsGTK.InputChoice(( ("Exact path mode (G61)", "exact_path"), ("Exact stop mode (G61.1)", "exact_stop"), ("Continuous with maximum speed (G64)", "optimize_speed"), ("Continuous with tolerance (G64 P/Q)", "optimize_tolerance"))) self.path_mode.get_widget().connect("changed", self.update_widgets) self.core.register_ui("gcode_corner_style", "Path mode", self.path_mode.get_widget(), weight=10) table.widget.show_all() self.update_widgets() return True def teardown(self): self.core.unregister_ui("gcode_corner_style", self.motion_tolerance.get_widget()) self.core.unregister_ui("gcode_corner_style", self.naive_tolerance.get_widget()) self.core.unregister_ui("gcode_corner_style", self.path_mode.get_widget()) self.core.unregister_ui_section("gcode_corner_style") def update_widgets(self, widget=None): enable_tolerances = (self.path_mode.get_value() == "optimize_speed") controls = (self.motion_tolerance, self.naive_tolerance) for control in controls: control.get_widget().set_sensitive(enable_tolerances)