Commit c213eda5 authored by sumpfralle's avatar sumpfralle

r676@erker: lars | 2010-02-17 05:13:08 +0100

 load and save processing settings
 multiple processing templates are stored one file (for now: rough, semi-finish, finish)


git-svn-id: https://pycam.svn.sourceforge.net/svnroot/pycam/trunk@134 bbaffbd6-741e-11dd-a85d-61de82d9cad9
parent f815f022
......@@ -248,11 +248,24 @@ class ProjectGui:
self.gui.add_from_file(GTKBUILD_FILE)
self.window = self.gui.get_object("ProjectWindow")
# file loading
self.file_selector = self.gui.get_object("File chooser")
self.file_selector.connect("file-set",
self.load_model_file, self.file_selector.get_filename)
self.model_file_selector = self.gui.get_object("ModelFileChooser")
self.model_file_selector.connect("file-set",
self.load_model_file, self.model_file_selector.get_filename)
self.processing_file_selector = self.gui.get_object("ProcessingSettingsLoad")
self.processing_file_selector.connect("file-set",
self.load_processing_file, self.processing_file_selector.get_filename)
self.window.connect("destroy", self.destroy)
self.gui.get_object("SaveModel").connect("clicked", self.save_model)
model_file_chooser = self.gui.get_object("ModelFileChooser")
filter = gtk.FileFilter()
filter.set_name("All files")
filter.add_pattern("*")
model_file_chooser.add_filter(filter)
filter = gtk.FileFilter()
filter.set_name("STL files")
filter.add_pattern("*.stl")
model_file_chooser.add_filter(filter)
model_file_chooser.set_filter(filter)
self.window.show()
self.model = None
self.toolpath = None
......@@ -309,6 +322,8 @@ class ProjectGui:
# add tool radius for experimental ODE collisions
obj = self.gui.get_object("ToolRadiusControl")
self.settings.add_item("tool_radius", obj.get_value, obj.set_value)
obj = self.gui.get_object("TorusRadiusControl")
self.settings.add_item("torus_radius", obj.get_value, obj.set_value)
# visual settings
self.gui.get_object("Toggle3dView").connect("toggled", self.toggle_3d_view)
for name, objname in (("show_model", "ShowModelCheckBox"),
......@@ -327,6 +342,60 @@ class ProjectGui:
skip_obj = self.gui.get_object("DrillProgressFrameSkipControl")
self.settings.add_item("drill_progress_frame_skip", skip_obj.get_value, skip_obj.set_value)
self.settings.set("drill_progress_frame_skip", 20)
# cutter shapes
def get_cutter_shape_name():
for name in ("SphericalCutter", "CylindricalCutter", "ToroidalCutter"):
if self.gui.get_object(name).get_active():
return name
def set_cutter_shape_name(value):
self.gui.get_object(value).set_active(True)
self.settings.add_item("cutter_shape", get_cutter_shape_name, set_cutter_shape_name)
# path generator
def get_path_generator():
for name in ("DropCutter", "PushCutter"):
if self.gui.get_object(name).get_active():
return name
def set_path_generator(value):
self.gui.get_object(value).set_active(True)
self.settings.add_item("path_generator", get_path_generator, set_path_generator)
# path postprocessor
def get_path_postprocessor():
for name in ("PathAccumulator", "SimpleCutter", "ZigZagCutter", "PolygonCutter", "ContourCutter"):
if self.gui.get_object(name).get_active():
return name
def set_path_postprocessor(value):
self.gui.get_object(value).set_active(True)
self.settings.add_item("path_postprocessor", get_path_postprocessor, set_path_postprocessor)
# path direction (combined get/set function)
def set_get_path_direction(input=None):
for obj, value in [("PathDirectionX", "x"), ("PathDirectionY", "y"), ("PathDirectionXY", "xy")]:
if value == input:
self.gui.get_object(obj).set_active(True)
return
if self.gui.get_object(obj).get_active():
return value
self.settings.add_item("path_direction", set_get_path_direction, set_get_path_direction)
# load a processing configuration object
self.processing_settings = pycam.Gui.Settings.ProcessingSettings(self.settings)
self.processing_config_selection = self.gui.get_object("ProcessingTemplatesList")
self.processing_config_selection.connect("changed",
self.switch_processing_config, self.processing_config_selection.get_active_text)
self.gui.get_object("ProcessingTemplateDelete").connect("clicked",
self.delete_processing_config, self.processing_config_selection.get_active_text)
self.gui.get_object("ProcessingTemplateSave").connect("clicked",
self.save_processing_config, self.processing_config_selection.get_active_text)
self.load_processing_settings()
self.gui.get_object("ProcessingSettingsSaveToFile").connect("clicked", self.save_processing_settings_file)
load_processing_settings_file_control = self.gui.get_object("ProcessingSettingsLoad")
filter = gtk.FileFilter()
filter.set_name("All files")
filter.add_pattern("*")
load_processing_settings_file_control.add_filter(filter)
filter = gtk.FileFilter()
filter.set_name("Config files")
filter.add_pattern("*.conf")
load_processing_settings_file_control.add_filter(filter)
load_processing_settings_file_control.set_filter(filter)
def gui_activity_guard(func):
def wrapper(self, *args, **kwargs):
......@@ -458,7 +527,7 @@ class ProjectGui:
gtk.main_quit()
def open(self, filename):
self.file_selector.set_filename(filename)
self.model_file_selector.set_filename(filename)
self.load_model_file(filename=filename)
def append_to_queue(self, func, *args, **kwargs):
......@@ -474,11 +543,18 @@ class ProjectGui:
def load_model_file(self, widget=None, filename=None):
if not filename:
return
# evaluate "filename" after showing the dialog above - then we will get the new value
if callable(filename):
filename = filename()
self.load_model(pycam.Importers.STLImporter.ImportModel(filename))
@gui_activity_guard
def load_processing_file(self, widget=None, filename=None):
if not filename:
return
if callable(filename):
filename = filename()
self.load_processing_settings(filename)
def load_model(self, model):
self.model = model
# do some initialization
......@@ -486,6 +562,69 @@ class ProjectGui:
self.append_to_queue(self.toggle_3d_view, True)
self.append_to_queue(self.update_view)
def load_processing_settings(self, filename=None):
if not filename is None:
self.processing_settings.load_file(filename)
# load the default config
self.processing_settings.enable_config()
# reset the combobox
self.processing_config_selection.set_active(0)
while self.processing_config_selection.get_active() >= 0:
self.processing_config_selection.remove_text(0)
self.processing_config_selection.set_active(0)
for config_name in self.processing_settings.get_config_list():
self.processing_config_selection.append_text(config_name)
def switch_processing_config(self, widget=None, section=None):
if callable(section):
section = section()
if not section:
return
if section in self.processing_settings.get_config_list():
self.processing_settings.enable_config(section)
def delete_processing_config(self, widget=None, section=None):
if callable(section):
section = section()
if not section:
return
if section in self.processing_settings.get_config_list():
self.processing_settings.delete_config(section)
self.load_processing_settings()
def save_processing_config(self, widget=None, section=None):
if callable(section):
section = section()
if not section:
return
self.processing_settings.store_config(section)
self.load_processing_settings()
# try to select the previously stored entry
index = 0
self.processing_config_selection.set_active(0)
while self.processing_config_selection.get_active() >= 0:
if self.processing_config_selection.get_active_text() == section:
# we found the right entry
break
index += 1
self.processing_config_selection.set_active(index)
@gui_activity_guard
def save_processing_settings_file(self, widget=None, section=None):
no_dialog = False
if isinstance(widget, basestring):
filename = widget
no_dialog = True
else:
# we open a dialog
filename = self.get_save_filename("Save processing settings to ...", ("Config files", "*.conf"))
# no filename given -> exit
if not filename:
return
if not self.processing_settings.write_to_file(filename) and not no_dialog:
self.show_error_dialog("Failed to save processing settings file")
@gui_activity_guard
def generate_toolpath(self, widget, data=None):
start_time = time.time()
......@@ -502,30 +641,18 @@ class ProjectGui:
draw_callback = UpdateView(self.update_view, self.settings.get("drill_progress_frame_skip")).update
else:
draw_callback = None
radius = float(self.gui.get_object("ToolRadiusControl").get_value())
cuttername = None
for name in ("SphericalCutter", "CylindricalCutter", "ToroidalCutter"):
if self.gui.get_object(name).get_active():
cuttername = name
pathgenerator = None
for name in ("DropCutter", "PushCutter"):
if self.gui.get_object(name).get_active():
pathgenerator = name
pathprocessor = None
for name in ("PathAccumulator", "SimpleCutter", "ZigZagCutter", "PolygonCutter", "ContourCutter"):
if self.gui.get_object(name).get_active():
pathprocessor = name
direction = None
for obj, value in [("PathDirectionX", "x"), ("PathDirectionY", "y"), ("PathDirectionXY", "xy")]:
if self.gui.get_object(obj).get_active():
direction = value
radius = self.settings.get("tool_radius")
cuttername = self.settings.get("cutter_shape")
pathgenerator = self.settings.get("path_generator")
pathprocessor = self.settings.get("path_postprocessor")
direction = self.settings.get("path_direction")
cutter_height = 2 * (self.settings.get("maxz") - self.settings.get("minz"))
if cuttername == "SphericalCutter":
self.cutter = pycam.Cutters.SphericalCutter(radius, height=cutter_height)
elif cuttername == "CylindricalCutter":
self.cutter = pycam.Cutters.CylindricalCutter(radius, height=cutter_height)
elif cuttername == "ToroidalCutter":
toroid = float(self.gui.get_object("TorusRadiusControl").get_value())
toroid = self.settings.get("torus_radius")
self.cutter = pycam.Cutters.ToroidalCutter(radius, toroid, height=cutter_height)
self.update_physics()
......
import ConfigParser
import StringIO
import sys
import os
GET_INDEX = 0
SET_INDEX = 1
VALUE_INDEX = 2
......@@ -48,3 +53,122 @@ class Settings:
result[key] = self.get(key)
return str(result)
class ProcessingSettings:
DEFAULT_CONFIG = """
[DEFAULT]
cutter_shape: SphericalCutter
path_direction: x
path_generator: DropCutter
path_postprocessor: PathAccumulator
# the dimensions of the bounding box are disabled to keep the previous values
#minx: -7
#miny: -7
#minz: 0
#maxx: 7
#maxy: 7
#maxz: 3
tool_radius: 1.0
torus_radius: 0.25
[Rough]
cutter_shape: CylindricalCutter
path_generator: PushCutter
path_postprocessor: PolygonCutter
tool_radius: 1.0
[Semi-finish]
cutter_shape: ToroidalCutter
path_generator: PushCutter
path_postprocessor: ContourCutter
tool_radius: 0.5
[Finish]
cutter_shape: SphericalCutter
path_generator: DropCutter
path_postprocessor: ZigZagCutter
tool_radius: 0.1
"""
SETTING_TYPES = {
"cutter_shape": str,
"path_direction": str,
"path_generator": str,
"path_postprocessor": str,
"minx": float,
"miny": float,
"minz": float,
"maxx": float,
"maxy": float,
"maxz": float,
"tool_radius": float,
"torus_radius": float,
}
def __init__(self, settings):
self.settings = settings
self.config = None
self.reset()
def reset(self):
self.config = ConfigParser.SafeConfigParser()
self.config.readfp(StringIO.StringIO(self.DEFAULT_CONFIG))
def load_file(self, filename):
try:
self.config.read([filename])
except ConfigParser.ParsingError, err_msg:
print sys.stderr, "Failed to parse config file '%s': %s" % (filename, err_msg)
return False
return True
def load_from_string(self, config_text):
input_text = StringIO.StringIO(config_text)
try:
self.config.readfp(input_text)
except ConfigParser.ParsingError, err_msg:
print sys.stderr, "Failed to parse config data: %s" % str(err_msg)
return False
return True
def write_to_file(self, filename):
try:
fi = open(filename, "w")
self.config.write(fi)
fi.close()
except IOError, err_msg:
print sys.stderr, "Failed to write configuration to file (%s): %s" % (filename, err_msg)
return False
return True
def enable_config(self, section="DEFAULT"):
for key, value_type in self.SETTING_TYPES.items():
try:
value = value_type(self.config.get(section, key))
except ConfigParser.NoOptionError:
# we can safely ignore it and keep the original
try:
value = value_type(self.config.get("DEFAULT", key))
except ConfigParser.NoOptionError:
value = None
except ValueError, err_msg:
print sys.stderr, "Invalid config value for '%s = %s': %s" % (key, self.config.get(section, key), err_msg)
value = None
if not value is None:
self.settings.set(key, value)
def get_config_list(self):
return self.config.sections()
def store_config(self, section="DEFAULT"):
if not self.config.has_section(section):
self.config.add_section(section)
for key, value_type in self.SETTING_TYPES.items():
self.config.set(section, key, str(self.settings.get(key)))
def delete_config(self, section=None):
if self.config.has_section(section):
self.config.remove_section(section)
......@@ -26,7 +26,7 @@
<property name="visible">True</property>
<property name="left_padding">12</property>
<child>
<object class="GtkFileChooserButton" id="File chooser">
<object class="GtkFileChooserButton" id="ModelFileChooser">
<property name="visible">True</property>
<property name="create_folders">False</property>
<property name="width_chars">30</property>
......@@ -1482,6 +1482,159 @@
<object class="GtkVBox" id="vbox9">
<property name="visible">True</property>
<property name="orientation">vertical</property>
<property name="spacing">3</property>
<child>
<object class="GtkHSeparator" id="hseparator8">
<property name="visible">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkHBox" id="hbox9">
<property name="visible">True</property>
<property name="spacing">3</property>
<child>
<object class="GtkFrame" id="LoadProcessingSettingsFromFileFrame">
<property name="visible">True</property>
<property name="label_xalign">0</property>
<property name="shadow_type">none</property>
<child>
<object class="GtkAlignment" id="alignment22">
<property name="visible">True</property>
<property name="left_padding">12</property>
<child>
<object class="GtkHBox" id="hbox10">
<property name="visible">True</property>
<property name="spacing">3</property>
<child>
<object class="GtkFileChooserButton" id="ProcessingSettingsLoad">
<property name="visible">True</property>
</object>
<packing>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkButton" id="ProcessingSettingsSaveToFile">
<property name="label" translatable="yes">Save</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="position">1</property>
</packing>
</child>
</object>
</child>
</object>
</child>
<child type="label">
<object class="GtkLabel" id="LoadProcessingSettingsFromFileFrameLabel">
<property name="visible">True</property>
<property name="label" translatable="yes">&lt;b&gt;Load and Save File&lt;/b&gt;</property>
<property name="use_markup">True</property>
</object>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkVSeparator" id="vseparator8">
<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="ProcessingSettingsTemplatesFrame">
<property name="visible">True</property>
<property name="label_xalign">0</property>
<property name="shadow_type">none</property>
<child>
<object class="GtkAlignment" id="alignment23">
<property name="visible">True</property>
<property name="left_padding">12</property>
<child>
<object class="GtkHBox" id="hbox11">
<property name="visible">True</property>
<property name="spacing">3</property>
<child>
<object class="GtkComboBoxEntry" id="ProcessingTemplatesList">
<property name="visible">True</property>
<property name="model">ProcessingConfigs</property>
<property name="text_column">0</property>
</object>
<packing>
<property name="expand">False</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkButton" id="ProcessingTemplateSave">
<property name="label" translatable="yes">Save</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkButton" id="ProcessingTemplateDelete">
<property name="label" translatable="yes">Delete</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
</object>
<packing>
<property name="position">2</property>
</packing>
</child>
</object>
</child>
</object>
</child>
<child type="label">
<object class="GtkLabel" id="ProcessingSettingsTemplatesFrameLabel">
<property name="visible">True</property>
<property name="label" translatable="yes">&lt;b&gt;Load and Save Template&lt;/b&gt;</property>
<property name="use_markup">True</property>
</object>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="position">2</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkHSeparator" id="hseparator10">
<property name="visible">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="position">2</property>
</packing>
</child>
<child>
<object class="GtkTable" id="table4">
<property name="visible">True</property>
......@@ -1882,21 +2035,22 @@
</object>
<packing>
<property name="expand">False</property>
<property name="position">0</property>
<property name="position">3</property>
</packing>
</child>
<child>
<object class="GtkHSeparator" id="hseparator8">
<object class="GtkHSeparator" id="hseparator9">
<property name="visible">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="position">1</property>
<property name="position">4</property>
</packing>
</child>
<child>
<object class="GtkHBox" id="hbox8">
<property name="visible">True</property>
<property name="spacing">3</property>
<child>
<object class="GtkButton" id="GenerateToolPathButton">
<property name="label" translatable="yes">Generate Toolpath</property>
......@@ -1922,7 +2076,7 @@
</object>
<packing>
<property name="expand">False</property>
<property name="position">2</property>
<property name="position">5</property>
</packing>
</child>
</object>
......@@ -2088,6 +2242,8 @@
<child>
<object class="GtkAlignment" id="alignment20">
<property name="visible">True</property>
<property name="yalign">0</property>
<property name="yscale">0</property>
<property name="left_padding">12</property>
<child>
<object class="GtkToggleButton" id="Toggle3dView">
......@@ -2354,4 +2510,10 @@
<property name="page_increment">10</property>
<property name="page_size">10</property>
</object>
<object class="GtkListStore" id="ProcessingConfigs">
<columns>
<!-- column-name Name -->
<column type="gchararray"/>
</columns>
</object>
</interface>
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