Commit f411d3a4 authored by sumpfralle's avatar sumpfralle

mainly fixed the filename/URI conversion - some testing is still required


git-svn-id: https://pycam.svn.sourceforge.net/svnroot/pycam/trunk@1025 bbaffbd6-741e-11dd-a85d-61de82d9cad9
parent 2976c8b8
......@@ -41,7 +41,6 @@ from pycam.Gui.OpenGLTools import ModelViewWindowGL
from pycam.Geometry.Letters import TEXT_ALIGN_LEFT, TEXT_ALIGN_CENTER, \
TEXT_ALIGN_RIGHT
import pycam.Geometry.Model
from pycam.Utils import check_uri_exists
from pycam.Toolpath import Bounds
import pycam.Utils.FontCache
from pycam import VERSION
......@@ -301,16 +300,16 @@ class ProjectGui:
self.recent_manager = None
# file loading
self.last_dirname = None
self.last_task_settings_file = None
self.last_model_filename = None
self.last_task_settings_uri = None
self.last_model_uri = None
self.last_toolpath_file = None
# define callbacks and accelerator keys for the menu actions
for objname, callback, data, accel_key in (
("LoadTaskSettings", self.load_task_settings_file, None, "<Control>t"),
("SaveTaskSettings", self.save_task_settings_file, lambda: self.last_task_settings_file, None),
("SaveTaskSettings", self.save_task_settings_file, lambda: self.last_task_settings_uri, None),
("SaveAsTaskSettings", self.save_task_settings_file, None, None),
("OpenModel", self.load_model_file, None, "<Control>o"),
("SaveModel", self.save_model, lambda: self.last_model_filename, "<Control>s"),
("SaveModel", self.save_model, lambda: self.last_model_uri, "<Control>s"),
("SaveAsModel", self.save_model, None, "<Control><Shift>s"),
("ExportGCodeAll", self.save_toolpath, False, "<Control><Shift>e"),
("ExportGCodeVisible", self.save_toolpath, True, None),
......@@ -1120,7 +1119,8 @@ class ProjectGui:
autoload_task_filename = self.settings.get("default_task_settings_file")
if autoload_task_filename:
self.load_task_settings_file(filename=autoload_task_filename)
self.last_task_settings_file = autoload_task_filename
self.last_task_settings_uri = pycam.Utils.URIHandler(
autoload_task_filename)
self.update_all_controls()
self.no_dialog = no_dialog
if not self.no_dialog:
......@@ -1287,23 +1287,29 @@ class ProjectGui:
Additionally the window's title is adjusted and the "save" buttons are
updated.
"""
self.last_model_filename = filename
if self.last_model_filename is None:
uri = pycam.Utils.URIHandler(filename)
self.last_model_uri = uri
if self.last_model_uri:
self.window.set_title("PyCAM")
else:
short_name = os.path.basename(filename)
short_name = os.path.basename(uri.get_path())
self.window.set_title("%s - PyCAM" % short_name)
self.update_save_actions()
def update_save_actions(self):
self.gui.get_object("SaveTaskSettings").set_sensitive(not self.last_task_settings_file is None)
self.gui.get_object("SaveTaskSettings").set_sensitive(
bool(self.last_task_settings_uri and \
self.last_task_settings_uri.is_writable()))
save_as_possible = (not self.model is None) \
and self.model.is_export_supported()
self.gui.get_object("SaveAsModel").set_sensitive(save_as_possible)
save_possible = (not self.last_model_filename is None) and 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_filename)[-1].lower()
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
......@@ -2732,7 +2738,7 @@ class ProjectGui:
if "SVG" in name.upper()]
filename = self.get_filename_via_dialog("Save model to ...",
mode_load=False, type_filter=type_filter,
filename_templates=(self.last_model_filename,))
filename_templates=(self.last_model_uri,))
if filename:
self.set_model_filename(filename)
# no filename given -> exit
......@@ -3076,7 +3082,7 @@ class ProjectGui:
if not filename:
filename = self.get_filename_via_dialog("Exporting EMC tool definition ...",
mode_load=False, type_filter=FILTER_EMC_TOOL,
filename_templates=(self.last_model_filename,))
filename_templates=(self.last_model_uri,))
if filename:
export = pycam.Exporters.EMCToolExporter.EMCToolExporter(self.tool_list)
text = export.get_tool_definition_string()
......@@ -3091,7 +3097,7 @@ class ProjectGui:
def open_task_settings_file(self, filename):
""" This function is used by the commandline handler """
self.last_task_settings_file = filename
self.last_task_settings_uri = pycam.Utils.URIHandler(filename)
self.load_task_settings_file(filename=filename)
self.update_save_actions()
......@@ -3104,7 +3110,8 @@ class ProjectGui:
mode_load=True, type_filter=FILTER_CONFIG)
# Only update the last_task_settings attribute if the task file was
# loaded interactively. E.g. ignore the initial task file loading.
self.last_task_settings_file = filename
if filename:
self.last_task_settings_uri = pycam.Utils.URIHandler(filename)
if filename:
log.info("Loading task settings file: %s" % str(filename))
self.load_task_settings(filename)
......@@ -3114,6 +3121,7 @@ class ProjectGui:
def _update_all_model_attributes(self):
self.append_to_queue(self.update_model_dimensions)
self.append_to_queue(self.update_model_type_related_controls)
self.append_to_queue(self.update_save_actions)
self.append_to_queue(self.update_support_controls)
self.append_to_queue(self.toggle_3d_view, value=True)
self.append_to_queue(self.update_view)
......@@ -3123,6 +3131,7 @@ class ProjectGui:
if not model is None:
self._store_undo_state()
self.model = model
self.last_model_uri = None
# do some initialization
self._update_all_model_attributes()
if self.model and self.view3d and self.view3d.enabled:
......@@ -3605,9 +3614,9 @@ class ProjectGui:
# we open a dialog
filename = self.get_filename_via_dialog("Save settings to ...",
mode_load=False, type_filter=FILTER_CONFIG,
filename_templates=(self.last_task_settings_file, self.last_model_filename))
filename_templates=(self.last_task_settings_uri, self.last_model_uri))
if filename:
self.last_task_settings_file = filename
self.last_task_settings_uri = pycam.Utils.URIHandler(filename)
self.update_save_actions()
# no filename given -> exit
if not filename:
......@@ -4037,10 +4046,13 @@ class ProjectGui:
for file_filter in get_filters_from_list(type_filter):
dialog.add_filter(file_filter)
# guess the export filename based on the model's filename
if filename_templates is None:
valid_templates = []
if filename_templates:
for template in filename_templates:
if hasattr(template, "get_local_path"):
valid_templates.append(template.get_local_path())
else:
valid_templates = [t for t in filename_templates if t]
valid_templates.append(template)
if valid_templates:
filename_template = valid_templates[0]
# remove the extension
......@@ -4075,6 +4087,7 @@ class ProjectGui:
dialog.set_filter(dialog.list_filters()[0])
response = dialog.run()
filename = dialog.get_filename()
uri = pycam.Utils.URIHandler(filename)
dialog.hide()
if response != gtk.RESPONSE_OK:
dialog.destroy()
......@@ -4090,7 +4103,7 @@ class ProjectGui:
response = overwrite_window.run()
overwrite_window.destroy()
done = (response == gtk.RESPONSE_YES)
elif mode_load and not check_uri_exists(filename):
elif mode_load and not uri.exists():
not_found_window = gtk.MessageDialog(self.window, type=gtk.MESSAGE_ERROR,
buttons=gtk.BUTTONS_OK,
message_format="This file does not exist. Please choose a different filename.")
......@@ -4109,30 +4122,19 @@ class ProjectGui:
def add_to_recent_file_list(self, filename):
# Add the item to the recent files list - if it already exists.
# Otherwise it will be added later after writing the file.
if check_uri_exists(filename):
uri = pycam.Utils.URIHandler(filename)
if uri.exists():
# skip this, if the recent manager is not available (e.g. GTK 2.12.1 on Windows)
if self.recent_manager:
if os.path.exists(filename):
# This is a local file.
# Convert the local path to a URI filename style. This is
# specifically necessary under Windows (due to backslashs).
filename_url_local = urllib.pathname2url(
os.path.abspath(filename))
# join the "file:" scheme with the url
filename_url = urlparse.urlunparse(("file", None,
filename_url_local, None, None, None))
else:
# this is a remote file - or it already contains "file://"
filename_url = filename
if self.recent_manager.has_item(filename_url):
if self.recent_manager.has_item(uri.get_url()):
try:
self.recent_manager.remove_item(filename_url)
self.recent_manager.remove_item(uri.get_url())
except gobject.GError:
pass
self.recent_manager.add_item(filename_url)
self.recent_manager.add_item(uri.get_url())
# store the directory of the last loaded file
# TODO: make sure that the filename is not a URL
self.last_dirname = os.path.dirname(os.path.abspath(filename))
if uri.is_local():
self.last_dirname = os.path.dirname(uri.get_local_path())
@gui_activity_guard
def save_toolpath(self, widget=None, only_visible=False):
......@@ -4150,7 +4152,7 @@ class ProjectGui:
filename_extension = None
filename = self.get_filename_via_dialog("Save toolpath to ...",
mode_load=False, type_filter=FILTER_GCODE,
filename_templates=(self.last_toolpath_file, self.last_model_filename),
filename_templates=(self.last_toolpath_file, self.last_model_uri),
filename_extension=filename_extension)
if filename:
self.last_toolpath_file = filename
......@@ -4230,7 +4232,7 @@ class ProjectGui:
self.add_to_recent_file_list(filename)
def get_meta_data(self):
filename = "Filename: %s" % str(self.last_model_filename)
filename = "Filename: %s" % str(self.last_model_uri)
timestamp = "Timestamp: %s" % str(datetime.datetime.now())
version = "Version: %s" % VERSION
result = []
......
......@@ -23,6 +23,7 @@ along with PyCAM. If not, see <http://www.gnu.org/licenses/>.
from pycam.Toolpath import Bounds
import pycam.Cutters
import pycam.Utils.log
import pycam.Utils
import pycam.Toolpath
import ConfigParser
import StringIO
......@@ -331,17 +332,19 @@ process: 3
self.config.readfp(config_text)
def load_file(self, filename):
uri = pycam.Utils.URIHandler(filename)
try:
content = file(filename).read()
handle = uri.open()
content = handle.read()
except IOError, err_msg:
log.error("Settings: Failed to read config file '%s': %s" \
% (filename, err_msg))
% (uri, err_msg))
return False
try:
self.reset(content)
except ConfigParser.ParsingError, err_msg:
log.error("Settings: Failed to parse config file '%s': %s" \
% (filename, err_msg))
% (uri, err_msg))
return False
return True
......@@ -357,9 +360,10 @@ process: 3
def write_to_file(self, filename, tools=None, processes=None, bounds=None,
tasks=None):
uri = pycam.Utils.URIHandler(filename)
text = self.get_config_text(tools, processes, bounds, tasks)
try:
handle = open(filename, "w")
handle = open(uri.get_local_path(), "w")
handle.write(text)
handle.close()
except IOError, err_msg:
......
......@@ -25,7 +25,7 @@ from pycam.Geometry.Line import Line
from pycam.Geometry.Point import Point
from pycam.Geometry import get_points_of_arc
import pycam.Utils.log
from pycam.Utils import open_url
import pycam.Utils
log = pycam.Utils.log.get_logger()
......@@ -174,7 +174,7 @@ class CXFParser(object):
def import_font(filename, callback=None):
try:
infile = open_url(filename)
infile = pycam.Utils.URIHandler(filename).open()
except IOError, err_msg:
log.error("CXFImporter: Failed to read file (%s): %s" \
% (filename, err_msg))
......
......@@ -27,7 +27,7 @@ import pycam.Geometry.Model
import pycam.Geometry.Matrix
import pycam.Geometry
import pycam.Utils.log
from pycam.Utils import open_url
import pycam.Utils
import math
import re
import os
......@@ -852,8 +852,9 @@ def import_model(filename, color_as_height=False, fonts_cache=None,
infile = filename
else:
try:
infile = open_url(filename)
infile = pycam.Utils.URIHandler(filename).open()
except IOError, err_msg:
print pycam.Utils.URIHandler(filename)
log.error("DXFImporter: Failed to read file (%s): %s" \
% (filename, err_msg))
return None
......
......@@ -22,7 +22,7 @@ along with PyCAM. If not, see <http://www.gnu.org/licenses/>.
from pycam.Importers.SVGImporter import convert_eps2dxf
import pycam.Importers.DXFImporter
from pycam.Utils import check_uri_exists, retrieve_uri
import pycam.Utils
import tempfile
import os
......@@ -45,17 +45,17 @@ def import_model(filename, program_locations=None, unit="mm", callback=None,
return
filename = ps_file_name
else:
if not check_uri_exists(filename):
uri = pycam.Utils.URIHandler(filename)
if not uri.exists():
log.error("PSImporter: file (%s) does not exist" % filename)
return None
if not os.path.isfile(filename):
if not uri.is_local():
# non-local file - write it to a temporary file first
uri = filename
ps_file_handle, ps_file_name = tempfile.mkstemp(suffix=".ps")
os.close(ps_file_handle)
log.debug("Retrieving PS file for local access: %s -> %s" % \
(uri, ps_file_name))
if not retrieve_uri(uri, ps_file_name, callback=callback):
if not uri.retrieve_remote_file(ps_file_name, callback=callback):
log.error("PSImporter: Failed to retrieve the PS model file: " + \
"%s -> %s" % (uri, ps_file_name))
return
......
......@@ -27,7 +27,7 @@ from pycam.Geometry.PointKdtree import PointKdtree
from pycam.Geometry.utils import epsilon
from pycam.Geometry.Model import Model
import pycam.Utils.log
from pycam.Utils import open_url
import pycam.Utils
from struct import unpack
import StringIO
......@@ -63,10 +63,10 @@ def ImportModel(filename, use_kdtree=True, callback=None, **kwargs):
if hasattr(filename, "read"):
f = filename
# useful for later error messages
filename = "input data"
filename = "input stream"
else:
try:
url_file = open_url(filename)
url_file = pycam.Utils.URIHandler(filename).open()
# urllib.urlopen objects do not support "seek" - so we need to read
# the whole file at once. This is ugly - anyone with a better idea?
f = StringIO.StringIO(url_file.read())
......
......@@ -21,7 +21,7 @@ along with PyCAM. If not, see <http://www.gnu.org/licenses/>.
"""
import pycam.Importers.DXFImporter
from pycam.Utils import check_uri_exists, retrieve_uri
import pycam.Utils
import tempfile
import subprocess
import os
......@@ -97,17 +97,17 @@ def import_model(filename, program_locations=None, unit="mm", callback=None,
return
filename = svg_file_name
else:
if not check_uri_exists(filename):
uri = pycam.Utils.URIHandler(filename)
if not uri.exists():
log.error("SVGImporter: file (%s) does not exist" % filename)
return None
if not os.path.isfile(filename):
if not uri.is_local():
# non-local file - write it to a temporary file first
uri = filename
svg_file_handle, svg_file_name = tempfile.mkstemp(suffix=".svg")
os.close(svg_file_handle)
log.debug("Retrieving SVG file for local access: %s -> %s" % \
(uri, svg_file_name))
if not retrieve_uri(uri, svg_file_name, callback=callback):
if not uri.retrieve_remote_file(svg_file_name, callback=callback):
log.error("SVGImporter: Failed to retrieve the SVG model " + \
"file: %s -> %s" % (uri, svg_file_name))
filename = svg_file_name
......
......@@ -23,7 +23,7 @@ along with PyCAM. If not, see <http://www.gnu.org/licenses/>.
import pycam.Gui.Settings
import pycam.Gui.Project
import pycam.Utils.log
from pycam.Utils import open_url
import pycam.Utils
import re
import os
import sys
......@@ -59,7 +59,7 @@ def parse_toolpath_settings(filename):
else:
# open the file
try:
infile = open_url(filename)
infile = pycam.Utils.URIHandler(filename).open()
except IOError, err_msg:
log.warn("ToolpathSettingsParser: Failed to read file (%s): %s" % \
(filename, err_msg))
......
......@@ -21,13 +21,15 @@ along with PyCAM. If not, see <http://www.gnu.org/licenses/>.
"""
__all__ = ["iterators", "polynomials", "ProgressCounter", "threading",
"get_platform", "get_external_program_location", "PLATFORM_WINDOWS",
"PLATFORM_MACOS", "PLATFORM_LINUX", "PLATFORM_UNKNOWN"]
"get_platform", "get_external_program_location", "URIHandler",
"PLATFORM_WINDOWS", "PLATFORM_MACOS", "PLATFORM_LINUX",
"PLATFORM_UNKNOWN"]
import sys
import os
import socket
import urllib
import urlparse
# this is imported below on demand
#import win32com
#import win32api
......@@ -56,34 +58,103 @@ def get_platform():
return PLATFORM_UNKNOWN
def open_url(uri):
if (get_platform() == PLATFORM_WINDOWS) and (uri[1:3] == ":\\"):
# We are on Windows and a local path is given. Open the file
# normally. Otherwise "C:\\" is misinterpreted as a protocol.
return open(uri)
class URIHandler(object):
DEFAULT_PREFIX = "file://"
def __init__(self, location):
self._uri = None
self.set_location(location)
def __str__(self):
url = self._uri.geturl()
if url.startswith(self.DEFAULT_PREFIX):
return url[len(self.DEFAULT_PREFIX):]
else:
return urllib.urlopen(uri)
return url
def set_location(self, location):
if isinstance(location, URIHandler):
self._uri = location._uri
elif (get_platform() == PLATFORM_WINDOWS) and (location[1:3] == ":\\"):
self._uri = urlparse.urlparse(self.DEFAULT_PREFIX + location)
else:
self._uri = urlparse.urlparse(location)
if not self._uri.scheme:
# always fill the "scheme" field - some functions expect this
self._uri = urlparse.urlparse(self.DEFAULT_PREFIX + \
os.path.realpath(os.path.abspath(location)))
def is_local(self):
return bool(self and not self._uri.scheme or \
(self._uri.scheme == "file"))
def get_local_path(self):
if self.is_local():
print "LOCAL:", self._uri.path
return self._uri.path
else:
return None
def check_uri_exists(uri):
def get_path(self):
return self._uri.path
def get_url(self):
return self._uri.geturl()
def open(self):
if self.is_local():
return open(self.get_local_path())
else:
return urllib.urlopen(self._uri.geturl())
def retrieve_remote_file(uri, destination, callback=None):
if callback:
download_callback = lambda current_blocks, block_size, \
num_of_blocks: callback()
else:
download_callback = None
try:
handle = open_url(uri)
handle.close()
urllib.urlretrieve(uri, destination, download_callback)
return True
except IOError:
return False
def retrieve_uri(uri, filename, callback=None):
if callback:
download_callback = lambda current_blocks, block_size, num_of_blocks: \
callback()
def __eq__(self, other):
if isinstance(other, basestring):
return self == URIHandler(other)
elif self.__class__ == other.__class__:
if self.is_local() and other.is_local():
return self._uri.path == other._uri.path
else:
return tuple(self) == tuple(other)
else:
return hash(self) == hash(other)
def __ne__(self, other):
return not self == other
def __nonzero__(self):
return self.get_url() != self.DEFAULT_PREFIX
def exists(self):
if not self:
return False
elif self.is_local():
return os.path.exists(self._uri.path)
else:
download_callback = None
try:
urllib.urlretrieve(uri, filename, download_callback)
handle = self.open()
handle.close()
return True
except IOError:
return False
def is_writable(self):
return bool(self.is_local() and os.path.isfile(self._uri.path) and \
os.access(self._uri.path, os.W_OK))
def get_all_ips():
""" try to get all IPs of this machine
......
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