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

Contents of /branches/WIP-pyshapelib-bramz/Thuban/Model/load.py

Parent Directory Parent Directory | Revision Log Revision Log


Revision 772 - (show annotations)
Tue Apr 29 14:34:11 2003 UTC (21 years, 10 months ago) by jonathan
Original Path: trunk/thuban/Thuban/Model/load.py
File MIME type: text/x-python
File size: 12776 byte(s)
(SessionLoader.start_layer): Read visible parameter.

1 # Copyright (C) 2001, 2002, 2003 by Intevation GmbH
2 # Authors:
3 # Jan-Oliver Wagner <[email protected]>
4 # Bernhard Herzog <[email protected]>
5 # Jonathan Coles <[email protected]>
6 #
7 # This program is free software under the GPL (>=v2)
8 # Read the file COPYING coming with GRASS for details.
9
10 """
11 Parser for thuban session files.
12 """
13
14 __version__ = "$Revision$"
15
16 import string, os
17
18 import xml.sax
19 import xml.sax.handler
20 from xml.sax import make_parser, ErrorHandler, SAXNotRecognizedException
21
22 from Thuban import _
23 from Thuban.common import *
24
25 from Thuban.Model.table import FIELDTYPE_INT, FIELDTYPE_DOUBLE, \
26 FIELDTYPE_STRING
27
28 from Thuban.Model.session import Session
29 from Thuban.Model.map import Map
30 from Thuban.Model.layer import Layer
31 from Thuban.Model.color import Color
32 from Thuban.Model.proj import Projection
33 from Thuban.Model.classification import Classification, \
34 ClassGroupDefault, ClassGroupSingleton, ClassGroupRange, ClassGroupMap, \
35 ClassGroupProperties
36
37
38 def parse_color(color):
39 """Return the color object for the string color.
40
41 Color may be either 'None' or of the form '#RRGGBB' in the usual
42 HTML color notation
43 """
44 color = string.strip(color)
45 if color == "None":
46 result = Color.Transparent
47 elif color[0] == '#':
48 if len(color) == 7:
49 r = string.atoi(color[1:3], 16) / 255.0
50 g = string.atoi(color[3:5], 16) / 255.0
51 b = string.atoi(color[5:7], 16) / 255.0
52 result = Color(r, g, b)
53 else:
54 raise ValueError(_("Invalid hexadecimal color specification %s")
55 % color)
56 else:
57 raise ValueError(_("Invalid color specification %s") % color)
58 return result
59
60
61 class XMLReader(xml.sax.handler.ContentHandler):
62
63 # Dictionary mapping element names (or (URI, element name) pairs for
64 # documents using namespaces) to method names. The methods should
65 # accept the same parameters as the startElement (or startElementNS)
66 # methods. The start_dispatcher is used by the default startElement
67 # and startElementNS methods to call a method for the open tag of an
68 # element.
69 start_dispatcher = {}
70
71 # end_dispatcher works just like start_dispatcher but it's used by
72 # endElement and endElementNS. The method whose names it maps to
73 # should accept the same parameters as endElement and endElementNS.
74 end_dispatcher = {}
75
76
77 def __init__(self):
78 self.chars = ''
79 self.__directory = ""
80 self.__dispatchers = {}
81
82 def read(self, file_or_filename):
83
84 if hasattr(file_or_filename, "read"):
85 # it's a file object
86 self.__directory = ""
87 self.__file = file_or_filename
88 else:
89 filename = file_or_filename
90 self.__directory = os.path.dirname(filename)
91 self.__file = open(filename)
92
93 parser = make_parser()
94 parser.setContentHandler(self)
95 parser.setErrorHandler(ErrorHandler())
96 parser.setFeature(xml.sax.handler.feature_namespaces, 1)
97
98 #
99 # Well, this isn't pretty, but it appears that if you
100 # use Python 2.2 without the site-package _xmlplus then
101 # the following will fail, and without them it will work.
102 # However, if you do have the site-package and you don't
103 # call these functions, the reader raises an exception
104 #
105 # The reason we set these to 0 in the first place is
106 # because there is an unresolved issue with external
107 # entities causing an exception in the reader
108 #
109 try:
110 parser.setFeature(xml.sax.handler.feature_validation,0)
111 parser.setFeature(xml.sax.handler.feature_external_ges,0)
112 parser.setFeature(xml.sax.handler.feature_external_pes,0)
113 except SAXNotRecognizedException:
114 pass
115
116 parser.parse(self.__file)
117
118 self.close()
119
120 def close(self):
121 self.__file.close()
122
123 def GetFilename(self):
124 if hasattr(self.__file, "name"):
125 return self.__file.name
126
127 return ""
128
129 def GetDirectory(self):
130 return self.__directory
131
132
133 def AddDispatchers(self, dict):
134 """Add the function names that should be used to process XML tags.
135
136 dict -- a dictionary whose keys are XML tag strings and whose values
137 are pairs of strings such that the first string is
138 the name of the function that should be called when the
139 XML tag opens and the second string is the name of the
140 function that should be called when the XML tag closes.
141 If a pair element is None, no function is called.
142 """
143
144 self.__dispatchers.update(dict)
145
146 def startElementNS(self, name, qname, attrs):
147 """Call the method given for name in self.start_dispatcher
148 """
149 if name[0] is None:
150 method_name = self.__dispatchers.get(name[1])
151 else:
152 # Dispatch with namespace
153 method_name = self.__dispatchers.get(name)
154 if method_name is not None and method_name[0] is not None:
155 getattr(self, method_name[0])(name, qname, attrs)
156
157 def endElementNS(self, name, qname):
158 """Call the method given for name in self.end_dispatcher
159 """
160 if name[0] is None:
161 method_name = self.__dispatchers.get(name[1])
162 else:
163 # Dispatch with namespace
164 method_name = self.__dispatchers.get(name)
165 if method_name is not None and method_name[1] is not None:
166 getattr(self, method_name[1])(name, qname)
167
168 class SessionLoader(XMLReader):
169
170 def __init__(self):
171 """Inititialize the Sax handler."""
172 XMLReader.__init__(self)
173
174 self.theSession = None
175 self.aMap = None
176 self.aLayer = None
177
178 XMLReader.AddDispatchers(self,
179 {'session' : ("start_session", "end_session"),
180 'map' : ("start_map", "end_map"),
181 'projection' : ("start_projection", "end_projection"),
182 'parameter' : ("start_parameter", None),
183 'layer' : ("start_layer", "end_layer"),
184 'classification': ("start_classification", "end_classification"),
185 'clnull' : ("start_clnull", "end_clnull"),
186 'clpoint' : ("start_clpoint", "end_clpoint"),
187 'clrange' : ("start_clrange", "end_clrange"),
188 'cldata' : ("start_cldata", "end_cldata"),
189 'table' : ("start_table", "end_table"),
190 'labellayer' : ("start_labellayer", None),
191 'label' : ("start_label", None)})
192
193 def start_session(self, name, qname, attrs):
194 self.theSession = Session(attrs.get((None, 'title'), None))
195
196 def end_session(self, name, qname):
197 pass
198
199 def start_map(self, name, qname, attrs):
200 """Start a map."""
201 self.aMap = Map(attrs.get((None, 'title'), None))
202 self.__projReceiver = self.aMap
203
204 def end_map(self, name, qname):
205 self.theSession.AddMap(self.aMap)
206 self.__projReceiver = None
207
208 def start_projection(self, name, qname, attrs):
209 self.ProjectionName = attrs.get((None, 'name'), None)
210 self.ProjectionParams = [ ]
211
212 def end_projection(self, name, qname):
213 self.__projReceiver.SetProjection(
214 Projection(self.ProjectionParams, self.ProjectionName))
215
216 def start_parameter(self, name, qname, attrs):
217 s = attrs.get((None, 'value'))
218 s = str(s) # we can't handle unicode in proj
219 self.ProjectionParams.append(s)
220
221 def start_layer(self, name, qname, attrs, layer_class = Layer):
222 """Start a layer
223
224 Instantiate a layer of class layer_class from the attributes in
225 attrs which may be a dictionary as well as the normal SAX attrs
226 object and bind it to self.aLayer.
227 """
228 title = attrs.get((None, 'title'), "")
229 filename = attrs.get((None, 'filename'), "")
230 filename = os.path.join(self.GetDirectory(), filename)
231 visible = attrs.get((None, 'visible'), "true")
232 fill = parse_color(attrs.get((None, 'fill'), "None"))
233 stroke = parse_color(attrs.get((None, 'stroke'), "#000000"))
234 stroke_width = int(attrs.get((None, 'stroke_width'), "1"))
235 self.aLayer = layer_class(title,
236 self.theSession.OpenShapefile(filename),
237 fill = fill, stroke = stroke,
238 lineWidth = stroke_width,
239 visible = visible != "false")
240
241 self.__projReceiver = self.aLayer
242
243 def end_layer(self, name, qname):
244 self.aMap.AddLayer(self.aLayer)
245 self.__projReceiver = None
246
247 def start_classification(self, name, qname, attrs):
248 field = attrs.get((None, 'field'), None)
249
250 fieldType = attrs.get((None, 'field_type'), None)
251 dbFieldType = self.aLayer.GetFieldType(field)
252
253 if fieldType != dbFieldType:
254 raise ValueError(_("xml field type differs from database!"))
255
256 # setup conversion routines depending on the kind of data
257 # we will be seeing later on
258 if fieldType == FIELDTYPE_STRING:
259 self.conv = str
260 elif fieldType == FIELDTYPE_INT:
261 self.conv = lambda p: int(float(p))
262 elif fieldType == FIELDTYPE_DOUBLE:
263 self.conv = float
264
265 self.aLayer.GetClassification().SetField(field)
266
267
268 def end_classification(self, name, qname):
269 pass
270
271 def start_clnull(self, name, qname, attrs):
272 self.cl_group = ClassGroupDefault()
273 self.cl_group.SetLabel(attrs.get((None, 'label'), ""))
274 self.cl_prop = ClassGroupProperties()
275
276 def end_clnull(self, name, qname):
277 self.cl_group.SetProperties(self.cl_prop)
278 self.aLayer.GetClassification().SetDefaultGroup(self.cl_group)
279 del self.cl_group, self.cl_prop
280
281 def start_clpoint(self, name, qname, attrs):
282 attrib_value = attrs.get((None, 'value'), "0")
283
284 #try:
285 #value = Str2Num(attrib_value)
286 #except:
287 #value = attrib_value
288
289 value = self.conv(attrib_value)
290
291 self.cl_group = ClassGroupSingleton(value)
292 self.cl_group.SetLabel(attrs.get((None, 'label'), ""))
293 self.cl_prop = ClassGroupProperties()
294
295
296 def end_clpoint(self, name, qname):
297 self.cl_group.SetProperties(self.cl_prop)
298 self.aLayer.GetClassification().AppendGroup(self.cl_group)
299 del self.cl_group, self.cl_prop
300
301 def start_clrange(self, name, qname, attrs):
302
303 try:
304 min = self.conv(attrs.get((None, 'min'), "0"))
305 max = self.conv(attrs.get((None, 'max'), "0"))
306 #min = Str2Num(attrs.get((None, 'min'), "0"))
307 #max = Str2Num(attrs.get((None, 'max'), "0"))
308 except ValueError:
309 raise ValueError(_("Classification range is not a number!"))
310
311 self.cl_group = ClassGroupRange(min, max)
312 self.cl_group.SetLabel(attrs.get((None, 'label'), ""))
313 self.cl_prop = ClassGroupProperties()
314
315
316 def end_clrange(self, name, qname):
317 self.cl_group.SetProperties(self.cl_prop)
318 self.aLayer.GetClassification().AppendGroup(self.cl_group)
319 del self.cl_group, self.cl_prop
320
321 def start_cldata(self, name, qname, attrs):
322 self.cl_prop.SetLineColor(
323 parse_color(attrs.get((None, 'stroke'), "None")))
324 self.cl_prop.SetLineWidth(
325 int(attrs.get((None, 'stroke_width'), "0")))
326 self.cl_prop.SetFill(parse_color(attrs.get((None, 'fill'), "None")))
327
328 def end_cldata(self, name, qname):
329 pass
330
331 def start_table(self, name, qname, attrs):
332 #print "table title: %s" % attrs.get('title', None)
333 pass
334
335 def end_table(self, name, qname):
336 pass
337
338 def start_labellayer(self, name, qname, attrs):
339 self.aLayer = self.aMap.LabelLayer()
340
341 def start_label(self, name, qname, attrs):
342 x = float(attrs[(None, 'x')])
343 y = float(attrs[(None, 'y')])
344 text = attrs[(None, 'text')]
345 halign = attrs[(None, 'halign')]
346 valign = attrs[(None, 'valign')]
347 self.aLayer.AddLabel(x, y, text, halign = halign, valign = valign)
348
349 def characters(self, chars):
350 pass
351
352
353 def load_session(filename):
354 """Load a Thuban session from the file object file"""
355
356 handler = SessionLoader()
357 handler.read(filename)
358
359 session = handler.theSession
360 # Newly loaded session aren't modified
361 session.UnsetModified()
362
363 return session
364

Properties

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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26