/[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 1160 by jonathan, Thu Jun 12 12:40:43 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["filename"]     = relative_filename(self.dir, layer.filename)
128            attrs["visible"]      = ("false", "true")[int(layer.Visible())]
129    
130            if isinstance(layer, Layer):
131    
132                lc = layer.GetClassification()
133                attrs["stroke"]       = lc.GetDefaultLineColor().hex()
134                attrs["stroke_width"] = str(lc.GetDefaultLineWidth())
135                attrs["fill"]         = lc.GetDefaultFill().hex()
136    
137                self.open_element("layer", attrs)
138                self.write_projection(layer.GetProjection())
139                self.write_classification(layer)
140                self.close_element("layer")
141    
142            elif isinstance(layer, RasterLayer):
143    
144                self.open_element("rasterlayer", attrs)
145                self.write_projection(layer.GetProjection())
146                self.close_element("rasterlayer")
147    
148        def write_classification(self, layer, attrs = None):
149            if attrs is None:
150                attrs = {}
151    
152            lc = layer.GetClassification()
153    
154            field = lc.GetField()
155    
156            #
157            # there isn't a classification of anything
158            # so don't do anything
159            #
160            if field is None: return
161    
162            attrs["field"] = field
163            attrs["field_type"] = str(lc.GetFieldType())
164            self.open_element("classification", attrs)
165    
166    
167            types = [[lambda p: 'clnull label="%s"' % self.encode(p.GetLabel()),
168                      lambda p: 'clnull'],
169                     [lambda p: 'clpoint label="%s" value="%s"' %
170                                 (self.encode(p.GetLabel()), str(p.GetValue())),
171                      lambda p: 'clpoint'],
172                     [lambda p: 'clrange label="%s" range="%s"' %
173                                 (self.encode(p.GetLabel()),
174                                  str(p.GetRange())),
175                      lambda p: 'clrange']]
176    
177            def write_class_group(group):
178                type = -1
179                if isinstance(group, ClassGroupDefault): type = 0
180                elif isinstance(group, ClassGroupSingleton): type = 1
181                elif isinstance(group, ClassGroupRange): type = 2
182                elif isinstance(group, ClassGroupMap):   type = 3
183                assert type >= 0
184    
185                if type <= 2:
186                    data = group.GetProperties()
187                    dict = {'stroke'      : data.GetLineColor().hex(),
188                            'stroke_width': str(data.GetLineWidth()),
189                            'fill'        : data.GetFill().hex()}
190    
191                    self.open_element(types[type][0](group))
192                    self.write_element("cldata", dict)
193                    self.close_element(types[type][1](group))
194                else: pass # XXX: we need to handle maps
195    
196            for i in lc:
197                write_class_group(i)
198    
199            self.close_element("classification")
200    
201        def write_label_layer(self, layer):
202            """Write the label layer.
203            """
204            labels = layer.Labels()
205          if labels:          if labels:
206              write('\t\t<labellayer>\n')              self.open_element('labellayer')
207              for label in labels:              for label in labels:
208                  write(('\t\t\t<label x="%g" y="%g" text="%s"'                  self.write_element(('label x="%g" y="%g" text="%s"'
209                         ' halign="%s" valign="%s"/>\n')                                      ' halign="%s" valign="%s"')
210                        % (label.x, label.y, label.text, label.halign,                                  % (label.x, label.y,
211                           label.valign))                                     self.encode(label.text),
212              write('\t\t</labellayer>\n')                                     label.halign,
213          write('\t</map>\n')                                     label.valign))
214      write('</session>\n')              self.close_element('labellayer')
215    
216    
217    
218    def save_session(session, file, saver_class = None):
219        """Save the session session to a file.
220    
221        The file argument may either be a filename or an open file object.
222    
223        The optional argument saver_class is the class to use to serialize
224        the session. By default or if it's None, the saver class will be
225        SessionSaver.
226    
227        If writing the session is successful call the session's
228        UnsetModified method
229        """
230        if saver_class is None:
231            saver_class = SessionSaver
232        saver = saver_class(session)
233        saver.write(file)
234    
235      # after a successful save consider the session unmodified.      # after a successful save consider the session unmodified.
236      session.UnsetModified()      session.UnsetModified()

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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26