/[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 429 - (hide annotations)
Mon Feb 24 18:46:51 2003 UTC (22 years ago) by jonathan
Original Path: trunk/thuban/Thuban/Model/save.py
File MIME type: text/x-python
File size: 11648 byte(s)
(Saver.write_classificaton): Uses
        the new iterator to save the 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 jonathan 414 # Jonathan Coles <[email protected]>
6 bh 6 #
7     # This program is free software under the GPL (>=v2)
8     # Read the file COPYING coming with Thuban for details.
9    
10     """
11     Functions to save a session to a file
12     """
13    
14     __version__ = "$Revision$"
15    
16     import os
17     import string
18    
19 bh 201 import Thuban.Lib.fileutil
20 bh 6
21 jonathan 366 from Thuban.Model.color import Color
22    
23 jonathan 429 from Thuban.Model.classification import *
24    
25 jonathan 366 #
26     # one level of indention
27     #
28     TAB = " "
29    
30 bh 201 def relative_filename(dir, filename):
31     """Return a filename relative to dir for the absolute file name absname.
32    
33     This is almost the same as the function in fileutil, except that dir
34     can be an empty string in which case filename will be returned
35     unchanged.
36     """
37     if dir:
38     return Thuban.Lib.fileutil.relative_filename(dir, filename)
39     else:
40     return filename
41    
42 bh 6 def escape(data):
43     """Escape &, \", ', <, and > in a string of data.
44     """
45     data = string.replace(data, "&", "&amp;")
46     data = string.replace(data, "<", "&lt;")
47     data = string.replace(data, ">", "&gt;")
48     data = string.replace(data, '"', "&quot;")
49     data = string.replace(data, "'", "&apos;")
50     return data
51    
52 bh 268 class Saver:
53    
54     """Class to serialize a session into an XML file.
55    
56     Applications built on top of Thuban may derive from this class and
57     override or extend the methods to save additinal information. This
58     additional information should take the form of additional attributes
59     or elements whose names are prefixed with a namespace. To define a
60     namespace derived classes should extend the write_session method to
61     pass the namespaces to the default implementation.
62     """
63    
64 jonathan 366
65 bh 268 def __init__(self, session):
66     self.session = session
67    
68     def write(self, file_or_filename):
69     """Write the session to a file.
70    
71     The argument may be either a file object or a filename. If it's
72     a filename, the file will be opened for writing. Files of
73     shapefiles will be stored as filenames relative to the directory
74     the file is stored in (as given by os.path.dirname(filename)) if
75     they have a common parent directory other than the root
76     directory.
77    
78     If the argument is a file object (which is determined by the
79     presence of a write method) all filenames will be absolut
80     filenames.
81     """
82 jonathan 366
83 jonathan 391 # keep track of how many levels of indentation to write
84     self.indent_level = 0
85     # track whether an element is currently open. see open_element().
86     self.element_open = 0
87 jonathan 366
88 bh 268 if hasattr(file_or_filename, "write"):
89     # it's a file object
90     self.file = file_or_filename
91     self.dir = ""
92     else:
93     filename = file_or_filename
94     self.dir = os.path.dirname(filename)
95     self.file = open(filename, 'w')
96     self.write_header()
97     self.write_session(self.session)
98    
99 jonathan 429 assert(self.indent_level == 0)
100 jonathan 366
101     def write_attribs(self, attrs):
102 bh 268 for name, value in attrs.items():
103 jonathan 429 self.file.write(' %s="%s"' % (escape(name), value))
104 jonathan 366
105     def open_element(self, element, attrs = {}):
106 jonathan 391
107     #
108     # we note when an element is opened so that if two open_element()
109     # calls are made successively we can end the currently open
110     # tag and will later write a proper close tag. otherwise,
111     # if a close_element() call is made directly after an open_element()
112     # call we will close the tag with a />
113     #
114     if self.element_open == 1:
115     self.file.write(">\n")
116    
117     self.element_open = 1
118    
119 jonathan 366 # 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 bh 268
123 jonathan 366 self.indent_level += 1
124    
125     def close_element(self, element):
126     self.indent_level -= 1
127 jonathan 429 assert(self.indent_level >= 0)
128 jonathan 366
129 jonathan 391 # see open_element() for an explanation
130     if self.element_open == 1:
131     self.element_open = 0
132     self.file.write("/>\n")
133     else:
134     self.file.write("%s</%s>\n" % (TAB*self.indent_level, element))
135    
136 jonathan 366 def write_element(self, element, attrs = {}):
137 jonathan 391 """write an element that won't need a closing tag"""
138     self.open_element(element, attrs)
139     self.close_element(element)
140 jonathan 366
141 bh 268 def write_header(self):
142     """Write the XML header"""
143 jonathan 366 self.file.write('<?xml version="1.0" encoding="UTF-8"?>\n')
144     self.file.write('<!DOCTYPE session SYSTEM "thuban.dtd">\n')
145 bh 268
146     def write_session(self, session, attrs = None, namespaces = ()):
147     """Write the session and its contents
148    
149     By default, write a session element with the title attribute and
150     call write_map for each map contained in the session.
151    
152     The optional argument attrs is for additional attributes and, if
153     given, should be a mapping from attribute names to attribute
154     values. The values should not be XML-escaped yet.
155    
156     The optional argument namespaces, if given, should be a sequence
157     of (name, URI) pairs. The namespaces are written as namespace
158     attributes into the session element. This is mainly useful for
159     derived classes that need to store additional information in a
160     thuban session file.
161     """
162     if attrs is None:
163     attrs = {}
164     attrs["title"] = session.title
165     for name, uri in namespaces:
166     attrs["xmlns:" + name] = uri
167 jonathan 366 self.open_element("session", attrs)
168 bh 268 for map in session.Maps():
169     self.write_map(map)
170 jonathan 366 self.close_element("session")
171 bh 268
172     def write_map(self, map):
173     """Write the map and its contents.
174    
175     By default, write a map element element with the title
176     attribute, call write_projection to write the projection
177     element, call write_layer for each layer contained in the map
178     and finally call write_label_layer to write the label layer.
179     """
180     write = self.file.write
181 jonathan 366 self.open_element('map title="%s"' % escape(map.title))
182 bh 268 self.write_projection(map.projection)
183     for layer in map.Layers():
184     self.write_layer(layer)
185     self.write_label_layer(map.LabelLayer())
186 jonathan 366 self.close_element('map')
187 bh 6
188 bh 268 def write_projection(self, projection):
189     """Write the projection.
190     """
191     if projection and len(projection.params) > 0:
192 jonathan 366 self.open_element("projection")
193 bh 268 for param in projection.params:
194 jonathan 366 self.write_element('parameter value="%s"' % escape(param))
195     self.close_element("projection")
196 bh 268
197     def write_layer(self, layer, attrs = None):
198     """Write the layer.
199    
200     The optional argument attrs is for additional attributes and, if
201     given, should be a mapping from attribute names to attribute
202     values. The values should not be XML-escaped yet.
203     """
204 jonathan 414 lc = layer.GetClassification()
205 jonathan 391
206 bh 268 if attrs is None:
207     attrs = {}
208 jonathan 429
209     attrs["title"] = layer.title
210     attrs["filename"] = relative_filename(self.dir, layer.filename)
211     attrs["stroke"] = lc.GetDefaultStroke().hex()
212 jonathan 391 attrs["stroke_width"] = str(lc.GetDefaultStrokeWidth())
213 jonathan 429 attrs["fill"] = lc.GetDefaultFill().hex()
214 bh 268
215 jonathan 366 self.open_element("layer", attrs)
216     self.write_classification(layer)
217     self.close_element("layer")
218    
219     def write_classification(self, layer, attrs = None):
220     if attrs is None:
221     attrs = {}
222    
223 jonathan 414 lc = layer.GetClassification()
224 jonathan 366
225 jonathan 429 field = lc.GetField()
226 jonathan 366
227     #
228     # there isn't a classification of anything
229     # so don't do anything
230     #
231     if field is None: return
232    
233     attrs["field"] = field
234     self.open_element("classification", attrs)
235    
236 jonathan 429
237     # self.open_element("clnull")
238     # write_class_data(lc.GetDefaultData())
239     # self.close_element("clnull")
240    
241     # just playing now with lambdas and dictionaries
242    
243     types = {ClassData.DEFAULT:
244     [lambda p: 'clnull',
245     lambda p: 'clnull'],
246     ClassData.POINT:
247     [lambda p: 'clpoint value="%s"' %
248     str(p.GetValue()),
249     lambda p: 'clpoint'],
250     ClassData.RANGE:
251     [lambda p: 'clrange min="%s" max="%s"' %
252     (str(p.GetMin()),
253     (str(p.GetMax()))),
254     lambda p: 'clrange']}
255    
256 jonathan 391 def write_class_data(data):
257 jonathan 414 dict = {'stroke' : data.GetStroke().hex(),
258     'stroke_width': str(data.GetStrokeWidth()),
259     'fill' : data.GetFill().hex()}
260 jonathan 429 t = data.GetType()
261     self.open_element(types[t][0](data))
262 jonathan 391 self.write_element("cldata", dict)
263 jonathan 429 self.close_element(types[t][1](data))
264 jonathan 366
265 jonathan 429 for i in lc:
266     write_class_data(i)
267    
268     # for i in lc:
269     # t = i.GetType()
270     # self.open_element(types[t][0](i))
271     # write_class_data(i)
272     # self.close_element(types[t][1](i))
273    
274     # for p in lc:
275     # type = p.GetType()
276     # if p == ClassData.DEFAULT:
277     # lopen = lclose = 'clnull'
278     # elif p == ClassData.POINTS:
279     # lopen = 'clpoint value="%s"' % escape(str(p.GetValue()))
280     # lclose = 'clpoint'
281     # elif p == ClassData.RANGES:
282     # lopen = 'clrange min="%s" max="%s"'
283     # % (escape(str(p.GetMin())), escape(str(p.GetMax()))))
284     # lclose = 'clrange'
285    
286     # self.open_element(lopen)
287     # write_class_data(p)
288     # self.close_element(lclose)
289 jonathan 391
290 jonathan 429 # if lc.points != {}:
291     # for p in lc.points.values():
292     # self.open_element('clpoint value="%s"' %
293     # (escape(str(p.GetValue()))))
294     # write_class_data(p)
295     # self.close_element('clpoint')
296     #
297     # if lc.ranges != []:
298     # for p in lc.ranges:
299     # self.open_element('clrange min="%s" max="%s"'
300     # % (escape(str(p.GetMin())), escape(str(p.GetMax()))))
301     # write_class_data(p)
302     # self.close_element('clrange')
303 jonathan 366
304     self.close_element("classification")
305    
306 bh 268 def write_label_layer(self, layer):
307     """Write the label layer.
308     """
309     labels = layer.Labels()
310 bh 6 if labels:
311 jonathan 366 self.open_element('labellayer')
312 bh 6 for label in labels:
313 jonathan 366 self.write_element(('label x="%g" y="%g" text="%s"'
314     ' halign="%s" valign="%s"')
315 bh 268 % (label.x, label.y, label.text, label.halign,
316     label.valign))
317 jonathan 366 self.close_element('labellayer')
318 bh 6
319 bh 268
320    
321     def save_session(session, file, saver_class = None):
322     """Save the session session to a file.
323    
324     The file argument may either be a filename or an open file object.
325    
326     The optional argument saver_class is the class to use to serialize
327     the session. By default or if it's None, the saver class will be
328     Saver.
329    
330     If writing the session is successful call the session's
331     UnsetModified method
332     """
333     if saver_class is None:
334     saver_class = Saver
335     saver = saver_class(session)
336     saver.write(file)
337    
338 bh 6 # after a successful save consider the session unmodified.
339     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