/[thuban]/branches/WIP-pyshapelib-bramz/Thuban/Model/save.py
ViewVC logotype

Annotation of /branches/WIP-pyshapelib-bramz/Thuban/Model/save.py

Parent Directory Parent Directory | Revision Log Revision Log


Revision 366 - (hide annotations)
Mon Jan 27 11:48:17 2003 UTC (22 years, 1 month ago) by jonathan
Original Path: trunk/thuban/Thuban/Model/save.py
File MIME type: text/x-python
File size: 9419 byte(s)
added support to save classification information

1 bh 74 # Copyright (c) 2001, 2002 by Intevation GmbH
2 bh 6 # Authors:
3     # Jan-Oliver Wagner <[email protected]>
4     # Bernhard Herzog <[email protected]>
5     #
6     # This program is free software under the GPL (>=v2)
7     # Read the file COPYING coming with Thuban for details.
8    
9     """
10     Functions to save a session to a file
11     """
12    
13     __version__ = "$Revision$"
14    
15     import os
16     import string
17    
18 bh 201 import Thuban.Lib.fileutil
19 bh 6
20 jonathan 366 from Thuban.Model.color import Color
21    
22     #
23     # one level of indention
24     #
25     TAB = " "
26    
27 bh 201 def relative_filename(dir, filename):
28     """Return a filename relative to dir for the absolute file name absname.
29    
30     This is almost the same as the function in fileutil, except that dir
31     can be an empty string in which case filename will be returned
32     unchanged.
33     """
34     if dir:
35     return Thuban.Lib.fileutil.relative_filename(dir, filename)
36     else:
37     return filename
38    
39 bh 6 def escape(data):
40     """Escape &, \", ', <, and > in a string of data.
41     """
42     data = string.replace(data, "&", "&amp;")
43     data = string.replace(data, "<", "&lt;")
44     data = string.replace(data, ">", "&gt;")
45     data = string.replace(data, '"', "&quot;")
46     data = string.replace(data, "'", "&apos;")
47     return data
48    
49 bh 268 class Saver:
50    
51     """Class to serialize a session into an XML file.
52    
53     Applications built on top of Thuban may derive from this class and
54     override or extend the methods to save additinal information. This
55     additional information should take the form of additional attributes
56     or elements whose names are prefixed with a namespace. To define a
57     namespace derived classes should extend the write_session method to
58     pass the namespaces to the default implementation.
59     """
60    
61 jonathan 366
62 bh 268 def __init__(self, session):
63     self.session = session
64    
65     def write(self, file_or_filename):
66     """Write the session to a file.
67    
68     The argument may be either a file object or a filename. If it's
69     a filename, the file will be opened for writing. Files of
70     shapefiles will be stored as filenames relative to the directory
71     the file is stored in (as given by os.path.dirname(filename)) if
72     they have a common parent directory other than the root
73     directory.
74    
75     If the argument is a file object (which is determined by the
76     presence of a write method) all filenames will be absolut
77     filenames.
78     """
79 jonathan 366
80     self.indent_level = 0
81    
82 bh 268 if hasattr(file_or_filename, "write"):
83     # it's a file object
84     self.file = file_or_filename
85     self.dir = ""
86     else:
87     filename = file_or_filename
88     self.dir = os.path.dirname(filename)
89     self.file = open(filename, 'w')
90     self.write_header()
91     self.write_session(self.session)
92    
93 jonathan 366 if self.indent_level != 0:
94     raise ValueError("indent_level still positive!")
95    
96     def write_attribs(self, attrs):
97 bh 268 for name, value in attrs.items():
98 jonathan 366 if isinstance(value, Color):
99     value = value.hex()
100     else:
101     value = str(value)
102 bh 268 self.file.write(' %s="%s"' % (escape(name), escape(value)))
103 jonathan 366
104     def open_element(self, element, attrs = {}):
105     # Helper function to write an element open tag with attributes
106     self.file.write("%s<%s" % (TAB*self.indent_level, element))
107     self.write_attribs(attrs)
108     self.file.write(">\n")
109 bh 268
110 jonathan 366 self.indent_level += 1
111    
112     def close_element(self, element):
113     self.indent_level -= 1
114     if self.indent_level < 0:
115     raise ValueError("close_element called too many times!")
116     self.file.write("%s</%s>\n" % (TAB*self.indent_level, element))
117    
118     def write_element(self, element, attrs = {}):
119     # Helper function to write an element open tag with attributes
120     self.file.write("%s<%s" % (TAB*self.indent_level, element))
121     self.write_attribs(attrs)
122     self.file.write("/>\n")
123    
124 bh 268 def write_header(self):
125     """Write the XML header"""
126 jonathan 366 self.file.write('<?xml version="1.0" encoding="UTF-8"?>\n')
127     self.file.write('<!DOCTYPE session SYSTEM "thuban.dtd">\n')
128 bh 268
129     def write_session(self, session, attrs = None, namespaces = ()):
130     """Write the session and its contents
131    
132     By default, write a session element with the title attribute and
133     call write_map for each map contained in the session.
134    
135     The optional argument attrs is for additional attributes and, if
136     given, should be a mapping from attribute names to attribute
137     values. The values should not be XML-escaped yet.
138    
139     The optional argument namespaces, if given, should be a sequence
140     of (name, URI) pairs. The namespaces are written as namespace
141     attributes into the session element. This is mainly useful for
142     derived classes that need to store additional information in a
143     thuban session file.
144     """
145     if attrs is None:
146     attrs = {}
147     attrs["title"] = session.title
148     for name, uri in namespaces:
149     attrs["xmlns:" + name] = uri
150 jonathan 366 self.open_element("session", attrs)
151 bh 268 for map in session.Maps():
152     self.write_map(map)
153 jonathan 366 self.close_element("session")
154 bh 268
155     def write_map(self, map):
156     """Write the map and its contents.
157    
158     By default, write a map element element with the title
159     attribute, call write_projection to write the projection
160     element, call write_layer for each layer contained in the map
161     and finally call write_label_layer to write the label layer.
162     """
163     write = self.file.write
164 jonathan 366 self.open_element('map title="%s"' % escape(map.title))
165 bh 268 self.write_projection(map.projection)
166     for layer in map.Layers():
167     self.write_layer(layer)
168     self.write_label_layer(map.LabelLayer())
169 jonathan 366 self.close_element('map')
170 bh 6
171 bh 268 def write_projection(self, projection):
172     """Write the projection.
173     """
174     if projection and len(projection.params) > 0:
175 jonathan 366 self.open_element("projection")
176 bh 268 for param in projection.params:
177 jonathan 366 self.write_element('parameter value="%s"' % escape(param))
178     self.close_element("projection")
179 bh 268
180     def write_layer(self, layer, attrs = None):
181     """Write the layer.
182    
183     The optional argument attrs is for additional attributes and, if
184     given, should be a mapping from attribute names to attribute
185     values. The values should not be XML-escaped yet.
186     """
187     if attrs is None:
188     attrs = {}
189     attrs["title"] = layer.title
190     attrs["filename"] = relative_filename(self.dir, layer.filename)
191     attrs["stroke_width"] = str(layer.stroke_width)
192     fill = layer.fill
193     if fill is None:
194     attrs["fill"] = "None"
195     else:
196     attrs["fill"] = fill.hex()
197     stroke = layer.stroke
198     if stroke is None:
199     attrs["stroke"] = "None"
200     else:
201     attrs["stroke"] = stroke.hex()
202    
203 jonathan 366 self.open_element("layer", attrs)
204     self.write_classification(layer)
205     self.close_element("layer")
206    
207     def write_classification(self, layer, attrs = None):
208     if attrs is None:
209     attrs = {}
210    
211     lc = layer.classification
212    
213     field = lc.field
214    
215     #
216     # there isn't a classification of anything
217     # so don't do anything
218     #
219     if field is None: return
220    
221     attrs["field"] = field
222     self.open_element("classification", attrs)
223    
224     if lc.NullData is not None:
225     self.open_element("clnull")
226     self.write_element("cldata", lc.NullData)
227     self.close_element("clnull")
228    
229     if lc.points != {}:
230     for value, data in lc.points.items():
231     self.open_element('clpoint value="%s"' % (escape(str(value))))
232     self.write_element("cldata", data)
233     self.close_element('clpoint')
234    
235     if lc.ranges != []:
236     for p in lc.ranges:
237     self.open_element('clrange min="%s" max="%s"'
238     % (escape(str(p[0])), escape(str(p[1]))))
239     self.write_element("cldata", p[2])
240     self.close_element('clrange')
241    
242     self.close_element("classification")
243    
244 bh 268 def write_label_layer(self, layer):
245     """Write the label layer.
246     """
247     labels = layer.Labels()
248 bh 6 if labels:
249 jonathan 366 self.open_element('labellayer')
250 bh 6 for label in labels:
251 jonathan 366 self.write_element(('label x="%g" y="%g" text="%s"'
252     ' halign="%s" valign="%s"')
253 bh 268 % (label.x, label.y, label.text, label.halign,
254     label.valign))
255 jonathan 366 self.close_element('labellayer')
256 bh 6
257 bh 268
258    
259     def save_session(session, file, saver_class = None):
260     """Save the session session to a file.
261    
262     The file argument may either be a filename or an open file object.
263    
264     The optional argument saver_class is the class to use to serialize
265     the session. By default or if it's None, the saver class will be
266     Saver.
267    
268     If writing the session is successful call the session's
269     UnsetModified method
270     """
271     if saver_class is None:
272     saver_class = Saver
273     saver = saver_class(session)
274     saver.write(file)
275    
276 bh 6 # after a successful save consider the session unmodified.
277     session.UnsetModified()

Properties

Name Value
svn:eol-style native
svn:keywords Author Date Id Revision

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26