/[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 6 by bh, Tue Aug 28 15:41:52 2001 UTC revision 1219 by bh, Mon Jun 16 17:42:54 2003 UTC
# Line 1  Line 1 
1  # Copyright (c) 2001 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 13  Functions to save a session to a file Line 14  Functions to save a session to a file
14  __version__ = "$Revision$"  __version__ = "$Revision$"
15    
16  import os  import os
 import string  
17    
18  from Thuban.Lib.fileutil import relative_filename  import Thuban.Lib.fileutil
19    
20  def escape(data):  from Thuban.Model.color import Color
21      """Escape &, \", ', <, and > in a string of data.  from Thuban.Model.layer import Layer, RasterLayer
22    
23    from Thuban.Model.classification import \
24        ClassGroupDefault, ClassGroupSingleton, ClassGroupRange, ClassGroupMap
25    
26    from Thuban.Model.xmlwriter import XMLWriter
27    
28    def relative_filename(dir, filename):
29        """Return a filename relative to dir for the absolute file name absname.
30    
31        This is almost the same as the function in fileutil, except that dir
32        can be an empty string in which case filename will be returned
33        unchanged.
34      """      """
35      data = string.replace(data, "&", "&amp;")      if dir:
36      data = string.replace(data, "<", "&lt;")          return Thuban.Lib.fileutil.relative_filename(dir, filename)
37      data = string.replace(data, ">", "&gt;")      else:
38      data = string.replace(data, '"', "&quot;")          return filename
39      data = string.replace(data, "'", "&apos;")  
40      return data  class SessionSaver(XMLWriter):
41    
42  def save_session(session, filename):      """Class to serialize a session into an XML file.
43      """Save the session session to the file given by filename"""  
44      dir = os.path.dirname(filename)      Applications built on top of Thuban may derive from this class and
45      file = open(filename, 'w')      override or extend the methods to save additional information. This
46      write = file.write      additional information should take the form of additional attributes
47      write('<?xml version="1.0" encoding="UTF-8"?>\n')      or elements whose names are prefixed with a namespace. To define a
48      write('<!DOCTYPE session SYSTEM "thuban.dtd">\n')      namespace derived classes should extend the write_session method to
49      write('<session title="%s">\n' % escape(session.title))      pass the namespaces to the default implementation.
50      for map in session.Maps():      """
51          write('\t<map title="%s">\n' % escape(map.title))  
         if map.projection and len(map.projection.params) > 0:  
             write('\t\t<projection>\n')  
             for param in map.projection.params:  
                 write('\t\t\t<parameter value="%s"/>\n' % escape(param))  
             write('\t\t</projection>\n')  
52    
53        def __init__(self, session):
54            XMLWriter.__init__(self)
55            self.session = session
56    
57        def write(self, file_or_filename):
58            XMLWriter.write(self, file_or_filename)
59    
60            self.write_header("session", "thuban.dtd")
61            self.write_session(self.session)
62            self.close()
63    
64        def write_session(self, session, attrs = None, namespaces = ()):
65            """Write the session and its contents
66    
67            By default, write a session element with the title attribute and
68            call write_map for each map contained in the session.
69    
70            The optional argument attrs is for additional attributes and, if
71            given, should be a mapping from attribute names to attribute
72            values. The values should not be XML-escaped yet.
73    
74            The optional argument namespaces, if given, should be a sequence
75            of (name, URI) pairs. The namespaces are written as namespace
76            attributes into the session element. This is mainly useful for
77            derived classes that need to store additional information in a
78            thuban session file.
79            """
80            if attrs is None:
81                attrs = {}
82            attrs["title"] = session.title
83            for name, uri in namespaces:
84                attrs["xmlns:" + name] = uri
85            self.open_element("session", attrs)
86            for map in session.Maps():
87                self.write_map(map)
88            self.close_element("session")
89    
90        def write_map(self, map):
91            """Write the map and its contents.
92    
93            By default, write a map element element with the title
94            attribute, call write_projection to write the projection
95            element, call write_layer for each layer contained in the map
96            and finally call write_label_layer to write the label layer.
97            """
98            self.open_element('map title="%s"' % self.encode(map.title))
99            self.write_projection(map.projection)
100          for layer in map.Layers():          for layer in map.Layers():
101              fill = layer.fill              self.write_layer(layer)
102              if fill is None:          self.write_label_layer(map.LabelLayer())
103                  fill = "None"          self.close_element('map')
104              else:  
105                  fill = fill.hex()      def write_projection(self, projection):
106              stroke = layer.stroke          """Write the projection.
107              if stroke is None:          """
108                  stroke = "None"          if projection and len(projection.params) > 0:
109              else:              self.open_element("projection", {"name": projection.GetName()})
110                  stroke = stroke.hex()              for param in projection.params:
111              write(('\t\t<layer title="%s" filename="%s"'                  self.write_element('parameter value="%s"' %
112                     ' fill="%s" stroke="%s"/>\n') %                                     self.encode(param))
113                    (escape(layer.title),              self.close_element("projection")
114                     escape(relative_filename(dir, layer.filename)),  
115                     fill, stroke))      def write_layer(self, layer, attrs = None):
116          labels = map.LabelLayer().Labels()          """Write the layer.
117    
118            The optional argument attrs is for additional attributes and, if
119            given, should be a mapping from attribute names to attribute
120            values. The values should not be XML-escaped yet.
121            """
122    
123            if attrs is None:
124                attrs = {}
125    
126            attrs["title"]        = layer.title
127            attrs["visible"]      = ("false", "true")[int(layer.Visible())]
128    
129            if isinstance(layer, Layer):
130                attrs["filename"] = relative_filename(self.dir,
131                                                    layer.ShapeStore().FileName())
132    
133                lc = layer.GetClassification()
134                attrs["stroke"]       = lc.GetDefaultLineColor().hex()
135                attrs["stroke_width"] = str(lc.GetDefaultLineWidth())
136                attrs["fill"]         = lc.GetDefaultFill().hex()
137    
138                self.open_element("layer", attrs)
139                self.write_projection(layer.GetProjection())
140                self.write_classification(layer)
141                self.close_element("layer")
142    
143            elif isinstance(layer, RasterLayer):
144                attrs["filename"] = relative_filename(self.dir, layer.filename)
145                self.open_element("rasterlayer", attrs)
146                self.write_projection(layer.GetProjection())
147                self.close_element("rasterlayer")
148    
149        def write_classification(self, layer, attrs = None):
150            if attrs is None:
151                attrs = {}
152    
153            lc = layer.GetClassification()
154    
155            field = lc.GetField()
156    
157            #
158            # there isn't a classification of anything
159            # so don't do anything
160            #
161            if field is None: return
162    
163            attrs["field"] = field
164            attrs["field_type"] = str(lc.GetFieldType())
165            self.open_element("classification", attrs)
166    
167    
168            types = [[lambda p: 'clnull label="%s"' % self.encode(p.GetLabel()),
169                      lambda p: 'clnull'],
170                     [lambda p: 'clpoint label="%s" value="%s"' %
171                                 (self.encode(p.GetLabel()), str(p.GetValue())),
172                      lambda p: 'clpoint'],
173                     [lambda p: 'clrange label="%s" range="%s"' %
174                                 (self.encode(p.GetLabel()),
175                                  str(p.GetRange())),
176                      lambda p: 'clrange']]
177    
178            def write_class_group(group):
179                type = -1
180                if isinstance(group, ClassGroupDefault): type = 0
181                elif isinstance(group, ClassGroupSingleton): type = 1
182                elif isinstance(group, ClassGroupRange): type = 2
183                elif isinstance(group, ClassGroupMap):   type = 3
184                assert type >= 0
185    
186                if type <= 2:
187                    data = group.GetProperties()
188                    dict = {'stroke'      : data.GetLineColor().hex(),
189                            'stroke_width': str(data.GetLineWidth()),
190                            'fill'        : data.GetFill().hex()}
191    
192                    self.open_element(types[type][0](group))
193                    self.write_element("cldata", dict)
194                    self.close_element(types[type][1](group))
195                else: pass # XXX: we need to handle maps
196    
197            for i in lc:
198                write_class_group(i)
199    
200            self.close_element("classification")
201    
202        def write_label_layer(self, layer):
203            """Write the label layer.
204            """
205            labels = layer.Labels()
206          if labels:          if labels:
207              write('\t\t<labellayer>\n')              self.open_element('labellayer')
208              for label in labels:              for label in labels:
209                  write(('\t\t\t<label x="%g" y="%g" text="%s"'                  self.write_element(('label x="%g" y="%g" text="%s"'
210                         ' halign="%s" valign="%s"/>\n')                                      ' halign="%s" valign="%s"')
211                        % (label.x, label.y, label.text, label.halign,                                  % (label.x, label.y,
212                           label.valign))                                     self.encode(label.text),
213              write('\t\t</labellayer>\n')                                     label.halign,
214          write('\t</map>\n')                                     label.valign))
215      write('</session>\n')              self.close_element('labellayer')
216    
217    
218    
219    def save_session(session, file, saver_class = None):
220        """Save the session session to a file.
221    
222        The file argument may either be a filename or an open file object.
223    
224        The optional argument saver_class is the class to use to serialize
225        the session. By default or if it's None, the saver class will be
226        SessionSaver.
227    
228        If writing the session is successful call the session's
229        UnsetModified method
230        """
231        if saver_class is None:
232            saver_class = SessionSaver
233        saver = saver_class(session)
234        saver.write(file)
235    
236      # after a successful save consider the session unmodified.      # after a successful save consider the session unmodified.
237      session.UnsetModified()      session.UnsetModified()

Legend:
Removed from v.6  
changed lines
  Added in v.1219

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26