Commit 8114f95b authored by sumpfralle's avatar sumpfralle

moved model export to separate plugins


git-svn-id: https://pycam.svn.sourceforge.net/svnroot/pycam/trunk@1179 bbaffbd6-741e-11dd-a85d-61de82d9cad9
parent 83e435f3
...@@ -3,8 +3,6 @@ ...@@ -3,8 +3,6 @@
<menu action="FileMenu"> <menu action="FileMenu">
<menuitem action="OpenModel"/> <menuitem action="OpenModel"/>
<menuitem action="OpenRecentModel" name="OpenRecentModelMenu"/> <menuitem action="OpenRecentModel" name="OpenRecentModelMenu"/>
<menuitem action="SaveModel"/>
<menuitem action="SaveAsModel"/>
<separator /> <separator />
<menu action="ExportMenu" /> <menu action="ExportMenu" />
<separator /> <separator />
......
<?xml version="1.0"?>
<interface>
<!-- interface-requires gtk+ 2.12 -->
<!-- interface-naming-policy project-wide -->
<object class="GtkAction" id="SaveAsModel">
<property name="label">Save Model _as ...</property>
<property name="short_label">Save Model as ...</property>
<property name="tooltip">Save the current model to a new STL file.</property>
<property name="stock_id">gtk-save-as</property>
</object>
<object class="GtkAction" id="SaveModel">
<property name="label">_Save Model</property>
<property name="short_label">_Save Model</property>
<property name="tooltip">Save the current model to the STL file.</property>
</object>
</interface>
...@@ -107,19 +107,9 @@ ...@@ -107,19 +107,9 @@
<property name="tooltip">Exit PyCAM</property> <property name="tooltip">Exit PyCAM</property>
<property name="stock_id">gtk-quit</property> <property name="stock_id">gtk-quit</property>
</object> </object>
<object class="GtkAction" id="SaveModel">
<property name="label">_Save Model</property>
<property name="tooltip">Save the current model to the STL file.</property>
</object>
<object class="GtkAction" id="ViewMenu"> <object class="GtkAction" id="ViewMenu">
<property name="label">_View</property> <property name="label">_View</property>
</object> </object>
<object class="GtkAction" id="SaveAsModel">
<property name="label">Save Model _as ...</property>
<property name="short_label">Save Model as ...</property>
<property name="tooltip">Save the current model to a new STL file.</property>
<property name="stock_id">gtk-save-as</property>
</object>
<object class="GtkDialog" id="GeneralSettingsWindow"> <object class="GtkDialog" id="GeneralSettingsWindow">
<property name="border_width">5</property> <property name="border_width">5</property>
<property name="title" translatable="yes">PyCAM Preferences</property> <property name="title" translatable="yes">PyCAM Preferences</property>
......
...@@ -356,8 +356,6 @@ class ProjectGui(object): ...@@ -356,8 +356,6 @@ class ProjectGui(object):
("SaveTaskSettings", self.save_task_settings_file, lambda: self.last_task_settings_uri, None), ("SaveTaskSettings", self.save_task_settings_file, lambda: self.last_task_settings_uri, None),
("SaveAsTaskSettings", self.save_task_settings_file, None, None), ("SaveAsTaskSettings", self.save_task_settings_file, None, None),
("OpenModel", self.load_model_file, None, "<Control>o"), ("OpenModel", self.load_model_file, None, "<Control>o"),
("SaveModel", self.save_model, lambda: self.last_model_uri, "<Control>s"),
("SaveAsModel", self.save_model, None, "<Control><Shift>s"),
("Quit", self.destroy, None, "<Control>q"), ("Quit", self.destroy, None, "<Control>q"),
("GeneralSettings", self.toggle_preferences_window, None, "<Control>p"), ("GeneralSettings", self.toggle_preferences_window, None, "<Control>p"),
("UndoButton", self._restore_undo_state, None, "<Control>z"), ("UndoButton", self._restore_undo_state, None, "<Control>z"),
...@@ -401,10 +399,6 @@ class ProjectGui(object): ...@@ -401,10 +399,6 @@ class ProjectGui(object):
self.gui.get_object("UndoButton").set_sensitive(False) self.gui.get_object("UndoButton").set_sensitive(False)
self.settings.register_event("model-change-before", self.settings.register_event("model-change-before",
self._store_undo_state) self._store_undo_state)
self.settings.register_event("model-change-after",
self.update_save_actions)
self.settings.register_event("model-selection-changed",
self.update_save_actions)
self.settings.register_event("model-change-after", self.settings.register_event("model-change-after",
lambda: self.settings.emit_event("visual-item-updated")) lambda: self.settings.emit_event("visual-item-updated"))
# set the availability of ODE # set the availability of ODE
...@@ -736,7 +730,6 @@ class ProjectGui(object): ...@@ -736,7 +730,6 @@ class ProjectGui(object):
self.window.show() self.window.show()
def update_all_controls(self): def update_all_controls(self):
self.update_save_actions()
self.update_gcode_controls() self.update_gcode_controls()
self.update_ode_settings() self.update_ode_settings()
...@@ -849,27 +842,6 @@ class ProjectGui(object): ...@@ -849,27 +842,6 @@ class ProjectGui(object):
self.window.set_title("%s - PyCAM" % short_name) self.window.set_title("%s - PyCAM" % short_name)
self.settings.emit_event("model-change-after") self.settings.emit_event("model-change-after")
def update_save_actions(self):
self.gui.get_object("SaveTaskSettings").set_sensitive(
bool(self.last_task_settings_uri and \
self.last_task_settings_uri.is_writable()))
# TODO: choose all models
models = self.settings.get("models") and \
self.settings.get("models").get_selected()
save_as_possible = bool(models) and models[0].is_export_supported()
self.gui.get_object("SaveAsModel").set_sensitive(save_as_possible)
save_possible = bool(self.last_model_uri and save_as_possible and \
self.last_model_uri.is_writable())
#TODO: fix this dirty hack to avoid silent overwrites of PS/DXF files as SVG
if save_possible:
extension = os.path.splitext(self.last_model_uri.get_path(
))[-1].lower()
# TODO: fix these hard-coded file extensions
if extension[1:] in ("eps", "ps", "dxf"):
# can't save 2D formats except SVG
save_possible = False
self.gui.get_object("SaveModel").set_sensitive(save_possible)
def _browse_external_program_location(self, widget=None, key=None): def _browse_external_program_location(self, widget=None, key=None):
location = self.settings.get("get_filename_func")(title="Select the executable " \ location = self.settings.get("get_filename_func")(title="Select the executable " \
+ "for '%s'" % key, mode_load=True, + "for '%s'" % key, mode_load=True,
...@@ -921,61 +893,6 @@ class ProjectGui(object): ...@@ -921,61 +893,6 @@ class ProjectGui(object):
# don't close the window - just hide it (for "delete-event") # don't close the window - just hide it (for "delete-event")
return True return True
def save_model(self, widget=None, filename=None, model=None,
store_filename=True):
if model is None:
# TODO: merge multiple models
model = self.settings.get("models").get_selected()[0]
if not model.is_export_supported():
log.warn(("Saving this type of model (%s) is currently not " \
+ "implemented!") % str(type(model)))
return
# get the filename
if callable(filename):
filename = filename()
uri = None
if not isinstance(filename, (basestring, pycam.Utils.URIHandler)):
# we open a dialog
# determine the file type
# TODO: this needs to be decided by the exporter code
if isinstance(model, pycam.Geometry.Model.Model):
# TODO: fix this extremely fragile filter
type_filter = [(name, patterns)
for name, patterns in FILTER_MODEL
if "STL" in name.upper()]
elif isinstance(model, pycam.Geometry.Model.ContourModel):
type_filter = [(name, patterns)
for name, patterns in FILTER_MODEL
if "SVG" in name.upper()]
filename = self.settings.get("get_filename_func")("Save model to ...",
mode_load=False, type_filter=type_filter,
filename_templates=(self.last_model_uri,))
if filename:
uri = pycam.Utils.URIHandler(filename)
if uri.is_local() and store_filename:
self.set_model_filename(filename)
else:
uri = pycam.Utils.URIHandler(filename)
# no filename given -> exit
if not uri:
return
if not uri.is_local():
log.error("Unable to write file to a non-local " + \
"destination: %s" % uri)
else:
try:
file_in = open(uri.get_local_path(), "w")
model.export(comment=self.get_meta_data(),
unit=self.settings.get("unit")).write(file_in)
file_in.close()
except IOError, err_msg:
log.error("Failed to save model file: %s" % err_msg)
else:
log.info("Successfully stored the current model as '%s'." % \
str(filename))
self.update_save_actions()
self.add_to_recent_file_list(filename)
@gui_activity_guard @gui_activity_guard
def reset_preferences(self, widget=None): def reset_preferences(self, widget=None):
""" reset all preferences to their default values """ """ reset all preferences to their default values """
...@@ -1134,7 +1051,6 @@ class ProjectGui(object): ...@@ -1134,7 +1051,6 @@ class ProjectGui(object):
""" This function is used by the commandline handler """ """ This function is used by the commandline handler """
self.last_task_settings_uri = pycam.Utils.URIHandler(filename) self.last_task_settings_uri = pycam.Utils.URIHandler(filename)
self.load_task_settings_file(filename=filename) self.load_task_settings_file(filename=filename)
self.update_save_actions()
@gui_activity_guard @gui_activity_guard
def load_task_settings_file(self, widget=None, filename=None): def load_task_settings_file(self, widget=None, filename=None):
...@@ -1151,7 +1067,6 @@ class ProjectGui(object): ...@@ -1151,7 +1067,6 @@ class ProjectGui(object):
log.info("Loading task settings file: %s" % str(filename)) log.info("Loading task settings file: %s" % str(filename))
self.load_task_settings(filename) self.load_task_settings(filename)
self.add_to_recent_file_list(filename) self.add_to_recent_file_list(filename)
self.update_save_actions()
def load_model(self, model): def load_model(self, model):
# load the new model only if the import worked # load the new model only if the import worked
...@@ -1185,7 +1100,6 @@ class ProjectGui(object): ...@@ -1185,7 +1100,6 @@ class ProjectGui(object):
filename_templates=(self.last_task_settings_uri, self.last_model_uri)) filename_templates=(self.last_task_settings_uri, self.last_model_uri))
if filename: if filename:
self.last_task_settings_uri = pycam.Utils.URIHandler(filename) self.last_task_settings_uri = pycam.Utils.URIHandler(filename)
self.update_save_actions()
# no filename given -> exit # no filename given -> exit
if not filename: if not filename:
return return
...@@ -1197,7 +1111,6 @@ class ProjectGui(object): ...@@ -1197,7 +1111,6 @@ class ProjectGui(object):
else: else:
log.info("Task settings written to %s" % filename) log.info("Task settings written to %s" % filename)
self.add_to_recent_file_list(filename) self.add_to_recent_file_list(filename)
self.update_save_actions()
def add_to_recent_file_list(self, filename): def add_to_recent_file_list(self, filename):
# Add the item to the recent files list - if it already exists. # Add the item to the recent files list - if it already exists.
......
# -*- 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
import pycam.Utils
class ModelExport(pycam.Plugins.PluginBase):
UI_FILE = "model_export.ui"
DEPENDS = ["Models"]
CATEGORIES = ["Model", "Export"]
def setup(self):
if self.gui:
self._gtk_handlers = []
save_action = self.gui.get_object("SaveModel")
self.register_gtk_accelerator("model", save_action,
"<Control>s", "SaveModel")
self._gtk_handlers.append((save_action, "activate",
self.save_model))
self.core.register_ui("file_menu", "SaveModel",
save_action, 20)
save_as_action = self.gui.get_object("SaveAsModel")
self.register_gtk_accelerator("model", save_as_action,
"<Control><Shift>s", "SaveAsModel")
self._gtk_handlers.append((save_as_action, "activate",
self.save_as_model))
self.core.register_ui("file_menu", "SaveAsModel",
save_as_action, 25)
self._event_handlers = (("model-selection-changed",
self._update_widgets), )
self.register_gtk_handlers(self._gtk_handlers)
self.register_event_handlers(self._event_handlers)
self._update_widgets()
self.core.register_chain("model_export", self._fallback_model_export,
weight=1000)
return True
def teardown(self):
if self.gui:
self.unregister_gtk_handlers(self._gtk_handlers)
self.unregister_event_handlers(self._event_handlers)
def _fallback_model_export(self, models):
if models:
self.log.info("Failed to export %d model(s)" % len(models))
def save_model(self, widget=None):
# TODO: add "filename" property to models
pass
def save_as_model(self, widget=None, filename=None):
self.core.call_chain("model_export", self.core.get("models").get_selected())
def _update_widgets(self):
models = self.core.get("models").get_selected()
save_as_possible = len(models) > 0
self.gui.get_object("SaveAsModel").set_sensitive(save_as_possible)
# TODO: fix this
save_possible = False and bool(self.last_model_uri and save_as_possible and \
self.last_model_uri.is_writable())
#TODO: fix this dirty hack to avoid silent overwrites of PS/DXF files as SVG
if save_possible:
extension = os.path.splitext(self.last_model_uri.get_path(
))[-1].lower()
# TODO: fix these hard-coded file extensions
if extension[1:] in ("eps", "ps", "dxf"):
# can't save 2D formats except SVG
save_possible = False
self.gui.get_object("SaveModel").set_sensitive(save_possible)
class ModelExportTrimesh(pycam.Plugins.PluginBase):
DEPENDS = ["ModelExport"]
def setup(self):
self.core.register_chain("model_export", self.export_trimesh, weight=30)
return True
def teardown(self):
self.core.unregister_chain("model_export", self.export_trimesh)
def export_trimesh(self, models):
removal_list = []
for index, model in enumerate(models):
if not hasattr(model, "triangles"):
continue
# determine the file type
# TODO: this needs to be decided by the exporter code
type_filter = [("STL models", "*.stl")]
model_name = self.core.get("models").get_attr(model, "name")
filename = self.core.get("get_filename_func")(
"Save model '%s' to ..." % model_name,
mode_load=False, type_filter=type_filter,
filename_templates=[])
if not filename:
continue
uri = pycam.Utils.URIHandler(filename)
if not uri:
continue
if not uri.is_local():
self.log.error("Unable to write file to a non-local " + \
"destination: %s" % uri)
continue
try:
file_in = open(uri.get_local_path(), "w")
# TODO: fill in "comment" with "meta_data"
# TODO: call a specific exporter
model.export(unit=self.core.get("unit")).write(file_in)
file_in.close()
removal_list.append(index)
except IOError, err_msg:
self.log.error("Failed to save model file: %s" % err_msg)
else:
self.log.info(("Successfully stored '%s' as " + \
"'%s'.") % (filename, model_name))
removal_list.reverse()
for index in removal_list:
models.pop(index)
class ModelExportContour(pycam.Plugins.PluginBase):
DEPENDS = ["ModelExport"]
def setup(self):
self.core.register_chain("model_export", self.export_contour, weight=40)
return True
def export_contour(self, models):
removal_list = []
for index, model in enumerate(models):
if not hasattr(model, "get_polygons"):
continue
# determine the file type
# TODO: this needs to be decided by the exporter code
type_filter = [("SVG models", "*.svg")]
model_name = self.core.get("models").get_attr(model, "name")
filename = self.core.get("get_filename_func")(
"Save model '%s' to ..." % model_name,
mode_load=False, type_filter=type_filter,
filename_templates=[])
if not filename:
continue
uri = pycam.Utils.URIHandler(filename)
if not uri:
continue
if not uri.is_local():
self.log.error("Unable to write file to a non-local " + \
"destination: %s" % uri)
continue
try:
file_in = open(uri.get_local_path(), "w")
# TODO: fill in "comment" with "meta_data"
# TODO: call a specific exporter
model.export(unit=self.core.get("unit")).write(file_in)
file_in.close()
removal_list.append(index)
except IOError, err_msg:
self.log.error("Failed to save model file: %s" % err_msg)
else:
self.log.info(("Successfully stored '%s' as " + \
"'%s'.") % (filename, model_name))
removal_list.reverse()
for index in removal_list:
models.pop(index)
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