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

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

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 268 by bh, Thu Aug 22 10:25:43 2002 UTC revision 605 by jonathan, Fri Apr 4 12:16:13 2003 UTC
# Line 1  Line 1 
1  # Copyright (c) 2001, 2002 by Intevation GmbH  # Copyright (c) 2001, 2002, 2003 by Intevation GmbH
2  # Authors:  # Authors:
3  # Jan-Oliver Wagner <[email protected]>  # Jan-Oliver Wagner <[email protected]>
4  # Bernhard Herzog <[email protected]>  # Bernhard Herzog <[email protected]>
5    # Jonathan Coles <[email protected]>
6  #  #
7  # This program is free software under the GPL (>=v2)  # This program is free software under the GPL (>=v2)
8  # Read the file COPYING coming with Thuban for details.  # Read the file COPYING coming with Thuban for details.
# Line 12  Functions to save a session to a file Line 13  Functions to save a session to a file
13    
14  __version__ = "$Revision$"  __version__ = "$Revision$"
15    
16    # fix for people using python2.1
17    from __future__ import nested_scopes
18    
19  import os  import os
20  import string  import string
21    
22  import Thuban.Lib.fileutil  import Thuban.Lib.fileutil
23    
24    from Thuban.Model.color import Color
25    
26    from Thuban.Model.classification import *
27    
28    #
29    # one level of indention
30    #
31    TAB = "    "
32    
33  def relative_filename(dir, filename):  def relative_filename(dir, filename):
34      """Return a filename relative to dir for the absolute file name absname.      """Return a filename relative to dir for the absolute file name absname.
35    
# Line 44  class Saver: Line 57  class Saver:
57      """Class to serialize a session into an XML file.      """Class to serialize a session into an XML file.
58    
59      Applications built on top of Thuban may derive from this class and      Applications built on top of Thuban may derive from this class and
60      override or extend the methods to save additinal information. This      override or extend the methods to save additional information. This
61      additional information should take the form of additional attributes      additional information should take the form of additional attributes
62      or elements whose names are prefixed with a namespace. To define a      or elements whose names are prefixed with a namespace. To define a
63      namespace derived classes should extend the write_session method to      namespace derived classes should extend the write_session method to
64      pass the namespaces to the default implementation.      pass the namespaces to the default implementation.
65      """      """
66    
67    
68      def __init__(self, session):      def __init__(self, session):
69          self.session = session          self.session = session
70    
# Line 68  class Saver: Line 82  class Saver:
82          presence of a write method) all filenames will be absolut          presence of a write method) all filenames will be absolut
83          filenames.          filenames.
84          """          """
85    
86            # keep track of how many levels of indentation to write
87            self.indent_level = 0
88            # track whether an element is currently open. see open_element().
89            self.element_open = 0
90    
91          if hasattr(file_or_filename, "write"):          if hasattr(file_or_filename, "write"):
92              # it's a file object              # it's a file object
93              self.file = file_or_filename              self.file = file_or_filename
# Line 79  class Saver: Line 99  class Saver:
99          self.write_header()          self.write_header()
100          self.write_session(self.session)          self.write_session(self.session)
101    
102      def write_element(self, element, attrs, empty = 0, indentation = ""):          assert self.indent_level == 0
103          # Helper function to write an element open tag with attributes  
104          self.file.write("%s<%s" % (indentation, element))      def write_attribs(self, attrs):
105          for name, value in attrs.items():          for name, value in attrs.items():
106              self.file.write(' %s="%s"' % (escape(name), escape(value)))              self.file.write(' %s="%s"' % (escape(name), escape(value)))
107          if empty:      
108        def open_element(self, element, attrs = {}):
109    
110            #
111            # we note when an element is opened so that if two open_element()
112            # calls are made successively we can end the currently open
113            # tag and will later write a proper close tag. otherwise,
114            # if a close_element() call is made directly after an open_element()
115            # call we will close the tag with a />
116            #
117            if self.element_open == 1:
118                self.file.write(">\n")
119    
120            self.element_open = 1
121    
122            # Helper function to write an element open tag with attributes
123            self.file.write("%s<%s" % (TAB*self.indent_level, element))
124            self.write_attribs(attrs)
125    
126            self.indent_level += 1
127    
128        def close_element(self, element):
129            self.indent_level -= 1
130            assert self.indent_level >= 0
131    
132            # see open_element() for an explanation
133            if self.element_open == 1:
134                self.element_open = 0
135              self.file.write("/>\n")              self.file.write("/>\n")
136          else:          else:
137              self.file.write(">\n")              self.file.write("%s</%s>\n" % (TAB*self.indent_level, element))
138    
139        def write_element(self, element, attrs = {}):
140            """write an element that won't need a closing tag"""
141            self.open_element(element, attrs)
142            self.close_element(element)
143    
144      def write_header(self):      def write_header(self):
145          """Write the XML header"""          """Write the XML header"""
146          write = self.file.write          self.file.write('<?xml version="1.0" encoding="UTF-8"?>\n')
147          write('<?xml version="1.0" encoding="UTF-8"?>\n')          self.file.write('<!DOCTYPE session SYSTEM "thuban.dtd">\n')
         write('<!DOCTYPE session SYSTEM "thuban.dtd">\n')  
148    
149      def write_session(self, session, attrs = None, namespaces = ()):      def write_session(self, session, attrs = None, namespaces = ()):
150          """Write the session and its contents          """Write the session and its contents
# Line 116  class Saver: Line 167  class Saver:
167          attrs["title"] = session.title          attrs["title"] = session.title
168          for name, uri in namespaces:          for name, uri in namespaces:
169              attrs["xmlns:" + name] = uri              attrs["xmlns:" + name] = uri
170          self.write_element("session", attrs)          self.open_element("session", attrs)
171          for map in session.Maps():          for map in session.Maps():
172              self.write_map(map)              self.write_map(map)
173          self.file.write('</session>\n')          self.close_element("session")
174    
175      def write_map(self, map):      def write_map(self, map):
176          """Write the map and its contents.          """Write the map and its contents.
# Line 129  class Saver: Line 180  class Saver:
180          element, call write_layer for each layer contained in the map          element, call write_layer for each layer contained in the map
181          and finally call write_label_layer to write the label layer.          and finally call write_label_layer to write the label layer.
182          """          """
183          write = self.file.write          #write = self.file.write
184          write('\t<map title="%s">\n' % escape(map.title))          self.open_element('map title="%s"' % escape(map.title))
185          self.write_projection(map.projection)          self.write_projection(map.projection)
186          for layer in map.Layers():          for layer in map.Layers():
187              self.write_layer(layer)              self.write_layer(layer)
188          self.write_label_layer(map.LabelLayer())          self.write_label_layer(map.LabelLayer())
189          write('\t</map>\n')          self.close_element('map')
190    
191      def write_projection(self, projection):      def write_projection(self, projection):
192          """Write the projection.          """Write the projection.
193          """          """
194          if projection and len(projection.params) > 0:          if projection and len(projection.params) > 0:
195              self.file.write('\t\t<projection>\n')              self.open_element("projection")
196              for param in projection.params:              for param in projection.params:
197                  self.file.write('\t\t\t<parameter value="%s"/>\n'                  self.write_element('parameter value="%s"' % escape(param))
198                                  % escape(param))              self.close_element("projection")
             self.file.write('\t\t</projection>\n')  
199    
200      def write_layer(self, layer, attrs = None):      def write_layer(self, layer, attrs = None):
201          """Write the layer.          """Write the layer.
# Line 154  class Saver: Line 204  class Saver:
204          given, should be a mapping from attribute names to attribute          given, should be a mapping from attribute names to attribute
205          values. The values should not be XML-escaped yet.          values. The values should not be XML-escaped yet.
206          """          """
207            lc = layer.GetClassification()
208    
209          if attrs is None:          if attrs is None:
210              attrs = {}              attrs = {}
211          attrs["title"] = layer.title  
212          attrs["filename"] = relative_filename(self.dir, layer.filename)          attrs["title"]        = layer.title
213          attrs["stroke_width"] = str(layer.stroke_width)          attrs["filename"]     = relative_filename(self.dir, layer.filename)
214          fill = layer.fill          attrs["stroke"]       = lc.GetDefaultLineColor().hex()
215          if fill is None:          attrs["stroke_width"] = str(lc.GetDefaultLineWidth())
216              attrs["fill"] = "None"          attrs["fill"]         = lc.GetDefaultFill().hex()
217          else:  
218              attrs["fill"] = fill.hex()          self.open_element("layer", attrs)
219          stroke = layer.stroke          self.write_classification(layer)
220          if stroke is None:          self.close_element("layer")
221              attrs["stroke"] = "None"  
222          else:      def write_classification(self, layer, attrs = None):
223              attrs["stroke"] = stroke.hex()          if attrs is None:
224          self.write_element("layer", attrs, empty = 1, indentation = "\t\t")              attrs = {}
225    
226            lc = layer.GetClassification()
227    
228            field = lc.GetField()
229    
230            #
231            # there isn't a classification of anything
232            # so don't do anything
233            #
234            if field is None: return
235    
236            attrs["field"] = field
237            attrs["field_type"] = str(lc.GetFieldType())
238            self.open_element("classification", attrs)
239    
240    
241    #       self.open_element("clnull")
242    #       write_class_data(lc.GetDefaultData())
243    #       self.close_element("clnull")
244                
245            # just playing now with lambdas and dictionaries
246    
247            types = [[lambda p: 'clnull',
248                      lambda p: 'clnull'],
249                     [lambda p: 'clpoint value="%s"' %
250                                 str(p.GetValue()),
251                      lambda p: 'clpoint'],
252                     [lambda p: 'clrange min="%s" max="%s"' %
253                                 (str(p.GetMin()),
254                                  (str(p.GetMax()))),
255                      lambda p: 'clrange']]
256    
257            def write_class_group(group):
258                type = -1
259                if isinstance(group, ClassGroupDefault): type = 0
260                elif isinstance(group, ClassGroupSingleton): type = 1
261                elif isinstance(group, ClassGroupRange): type = 2
262                elif isinstance(group, ClassGroupMap):   type = 3
263                assert type >= 0
264    
265                if type <= 2:
266                    data = group.GetProperties()
267                    dict = {'stroke'      : data.GetLineColor().hex(),
268                            'stroke_width': str(data.GetLineWidth()),
269                            'fill'        : data.GetFill().hex()}
270    
271                    self.open_element(types[type][0](group))
272                    self.write_element("cldata", dict)
273                    self.close_element(types[type][1](group))
274                else: pass # XXX: we need to handle maps
275    
276            for i in lc:
277                write_class_group(i)
278    
279    #       for i in lc:
280    #           t = i.GetType()
281    #           self.open_element(types[t][0](i))
282    #           write_class_data(i)
283    #           self.close_element(types[t][1](i))
284    
285    #       for p in lc:
286    #           type = p.GetType()
287    #           if p == ClassData.DEFAULT:
288    #               lopen = lclose = 'clnull'
289    #           elif p == ClassData.POINTS:
290    #               lopen = 'clpoint value="%s"' % escape(str(p.GetValue()))
291    #               lclose = 'clpoint'
292    #           elif p == ClassData.RANGES:
293    #               lopen = 'clrange min="%s" max="%s"'
294    #                   % (escape(str(p.GetMin())), escape(str(p.GetMax()))))
295    #               lclose = 'clrange'
296    
297    #           self.open_element(lopen)
298    #           write_class_data(p)
299    #           self.close_element(lclose)
300                
301    #       if lc.points != {}:
302    #           for p in lc.points.values():
303    #               self.open_element('clpoint value="%s"' %
304    #                   (escape(str(p.GetValue()))))
305    #               write_class_data(p)
306    #               self.close_element('clpoint')
307    #          
308    #       if lc.ranges != []:
309    #           for p in lc.ranges:
310    #               self.open_element('clrange min="%s" max="%s"'
311    #                   % (escape(str(p.GetMin())), escape(str(p.GetMax()))))
312    #               write_class_data(p)
313    #               self.close_element('clrange')
314    
315            self.close_element("classification")
316    
317      def write_label_layer(self, layer):      def write_label_layer(self, layer):
318          """Write the label layer.          """Write the label layer.
319          """          """
320          labels = layer.Labels()          labels = layer.Labels()
321          if labels:          if labels:
322              self.file.write('\t\t<labellayer>\n')              self.open_element('labellayer')
323              for label in labels:              for label in labels:
324                  self.file.write(('\t\t\t<label x="%g" y="%g" text="%s"'                  self.write_element(('label x="%g" y="%g" text="%s"'
325                                   ' halign="%s" valign="%s"/>\n')                                      ' halign="%s" valign="%s"')
326                                  % (label.x, label.y, label.text, label.halign,                                  % (label.x, label.y, label.text, label.halign,
327                                     label.valign))                                     label.valign))
328              self.file.write('\t\t</labellayer>\n')              self.close_element('labellayer')
329    
330    
331    

Legend:
Removed from v.268  
changed lines
  Added in v.605

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26