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

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

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

trunk/thuban/Thuban/Model/load.py revision 1930 by bh, Tue Nov 11 13:24:41 2003 UTC branches/WIP-pyshapelib-bramz/Thuban/Model/load.py revision 2734 by bramz, Thu Mar 1 12:42:59 2007 UTC
# Line 1  Line 1 
1  # Copyright (C) 2001, 2002, 2003 by Intevation GmbH  # Copyright (C) 2001, 2002, 2003, 2004, 2005 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]>  # Jonathan Coles <[email protected]>
6    # Frank Koormann <[email protected]>
7  #  #
8  # This program is free software under the GPL (>=v2)  # This program is free software under the GPL (>=v2)
9  # Read the file COPYING coming with GRASS for details.  # Read the file COPYING coming with GRASS for details.
# Line 32  from Thuban.Model.layer import Layer, Ra Line 33  from Thuban.Model.layer import Layer, Ra
33  from Thuban.Model.proj import Projection  from Thuban.Model.proj import Projection
34  from Thuban.Model.range import Range  from Thuban.Model.range import Range
35  from Thuban.Model.classification import Classification, \  from Thuban.Model.classification import Classification, \
36      ClassGroupDefault, ClassGroupSingleton, ClassGroupRange, ClassGroupMap, \      ClassGroupDefault, ClassGroupSingleton, ClassGroupRange, \
37        ClassGroupPattern, ClassGroupMap, \
38      ClassGroupProperties      ClassGroupProperties
39  from Thuban.Model.data import DerivedShapeStore, ShapefileStore  from Thuban.Model.data import DerivedShapeStore, ShapefileStore
40  from Thuban.Model.table import DBFTable  from Thuban.Model.table import DBFTable
# Line 100  class AttrDesc: Line 102  class AttrDesc:
102    
103  class SessionLoader(XMLReader):  class SessionLoader(XMLReader):
104    
105      def __init__(self, db_connection_callback = None):      def __init__(self, db_connection_callback = None,
106                           shapefile_callback = None):
107          """Inititialize the Sax handler."""          """Inititialize the Sax handler."""
108          XMLReader.__init__(self)          XMLReader.__init__(self)
109    
110          self.db_connection_callback = db_connection_callback          self.db_connection_callback = db_connection_callback
111            self.shapefile_callback = shapefile_callback
112          self.theSession = None          self.theSession = None
113          self.aMap = None          self.aMap = None
114          self.aLayer = None          self.aLayer = None
# Line 134  class SessionLoader(XMLReader): Line 137  class SessionLoader(XMLReader):
137              'clnull'        : ("start_clnull",         "end_clnull"),              'clnull'        : ("start_clnull",         "end_clnull"),
138              'clpoint'       : ("start_clpoint",        "end_clpoint"),              'clpoint'       : ("start_clpoint",        "end_clpoint"),
139              'clrange'       : ("start_clrange",        "end_clrange"),              'clrange'       : ("start_clrange",        "end_clrange"),
140                'clpattern'     : ("start_clpattern",      "end_clpattern"),
141              'cldata'        : ("start_cldata",         "end_cldata"),              'cldata'        : ("start_cldata",         "end_cldata"),
142              'table'         : ("start_table",          "end_table"),              'table'         : ("start_table",          "end_table"),
143              'labellayer'    : ("start_labellayer",     None),              'labellayer'    : ("start_labellayer",     None),
# Line 143  class SessionLoader(XMLReader): Line 147  class SessionLoader(XMLReader):
147          for xmlns in ("http://thuban.intevation.org/dtds/thuban-0.8.dtd",          for xmlns in ("http://thuban.intevation.org/dtds/thuban-0.8.dtd",
148                        "http://thuban.intevation.org/dtds/thuban-0.9-dev.dtd",                        "http://thuban.intevation.org/dtds/thuban-0.9-dev.dtd",
149                        "http://thuban.intevation.org/dtds/thuban-0.9.dtd",                        "http://thuban.intevation.org/dtds/thuban-0.9.dtd",
150                        "http://thuban.intevation.org/dtds/thuban-1.0-dev.dtd"):                        "http://thuban.intevation.org/dtds/thuban-1.0-dev.dtd",
151                          "http://thuban.intevation.org/dtds/thuban-1.0rc1.dtd",
152                          "http://thuban.intevation.org/dtds/thuban-1.0.0.dtd",
153                          "http://thuban.intevation.org/dtds/thuban-1.1-dev.dtd"):
154              for key, value in dispatchers.items():              for key, value in dispatchers.items():
155                  dispatchers[(xmlns, key)] = value                  dispatchers[(xmlns, key)] = value
156    
# Line 186  class SessionLoader(XMLReader): Line 193  class SessionLoader(XMLReader):
193          If the attribute has a default value and it is not present in          If the attribute has a default value and it is not present in
194          attrs, use that default value as the value in the returned dict.          attrs, use that default value as the value in the returned dict.
195    
196          If a conversion is specified, convert the value before putting          The value is converted before putting it into the returned dict.
197          it into the returned dict. The following conversions are          The following conversions are available:
         available:  
198    
199             'filename' -- The attribute is a filename.             'filename' -- The attribute is a filename.
200    
# Line 212  class SessionLoader(XMLReader): Line 218  class SessionLoader(XMLReader):
218                        ascii encoding.                        ascii encoding.
219    
220             a callable -- The attribute value is passed to the callable             a callable -- The attribute value is passed to the callable
221                           and the return value is used a as the converted                           and the return value is used as the converted
222                           value                           value
223    
224            If no conversion is specified for an attribute it is converted
225            with self.encode.
226          """          """
227          normalized = {}          normalized = {}
228    
# Line 241  class SessionLoader(XMLReader): Line 250  class SessionLoader(XMLReader):
250                                      % (element, d.name))                                      % (element, d.name))
251              elif d.conversion == "filename":              elif d.conversion == "filename":
252                  value = os.path.abspath(os.path.join(self.GetDirectory(),                  value = os.path.abspath(os.path.join(self.GetDirectory(),
253                                                       value))                                                       self.encode(value)))
254              elif d.conversion == "ascii":              elif d.conversion == "ascii":
255                  value = value.encode("ascii")                  value = value.encode("ascii")
256              elif d.conversion:              elif d.conversion:
257                  # Assume it's a callable                  # Assume it's a callable
258                  value = d.conversion(value)                  value = d.conversion(value)
259                else:
260                   value = self.encode(value)
261    
262              normalized[d.name] = value              normalized[d.name] = value
263          return normalized          return normalized
264    
265        def open_shapefile(self, filename):
266            """Open shapefile, with alternative path handling.
267            
268               If a shapefile cannot be opened and an IOError is raised, check for
269               an alternative. This alternative can be specified interactively by
270               the user or taken from a list of (potential) locations, depending on
271               the callback implementation.
272                
273               The alternative is rechecked. If taken from a list the user
274               has to confirm the alternative.
275            """
276    
277            # Flag if the alternative path was specified interactively / from list.
278            from_list = 0
279            while 1:
280                try:
281                    store = self.theSession.OpenShapefile(filename)
282                    if from_list:
283                        # A valid path has been guessed from a list
284                        # Let the user confirm - or select an alternative.
285                        filename, from_list = self.shapefile_callback(
286                                                filename, "check")
287                        if filename is None:
288                            # Selection cancelled
289                            raise LoadCancelled
290                        elif store.FileName() == filename:
291                            # Proposed file has been accepted
292                            break
293                        else:
294                            # the filename has been changed, try the new file
295                            pass
296                    else:
297                        break
298                except IOError:
299                    if self.shapefile_callback is not None:
300                        filename, from_list = self.shapefile_callback(
301                                                filename,
302                                                mode = "search",
303                                                second_try = from_list)
304                        if filename is None:
305                            raise LoadCancelled
306                    else:
307                        raise
308            return store
309    
310      def start_dbconnection(self, name, qname, attrs):      def start_dbconnection(self, name, qname, attrs):
311          attrs = self.check_attrs(name, attrs,          attrs = self.check_attrs(name, attrs,
312                                   [AttrDesc("id", True),                                   [AttrDesc("id", True),
# Line 294  class SessionLoader(XMLReader): Line 350  class SessionLoader(XMLReader):
350                                    AttrDesc("dbconn", True,                                    AttrDesc("dbconn", True,
351                                             conversion = "idref"),                                             conversion = "idref"),
352                                    AttrDesc("tablename", True,                                    AttrDesc("tablename", True,
353                                               conversion = "ascii"),
354                                      # id_column and geometry_column were
355                                      # newly introduced with thuban-1.1.dtd
356                                      # where they're required.  Since we
357                                      # support the older formats too we
358                                      # have them optional here.
359                                      AttrDesc("id_column", False, "gid",
360                                               conversion = "ascii"),
361                                      AttrDesc("geometry_column", False,
362                                             conversion = "ascii")])                                             conversion = "ascii")])
363          ID = attrs["id"]          # The default value of geometry_column to use when instantiating
364          db = attrs["dbconn"]          # the db shapestore is None which we currently can't easily use
365          tablename = attrs["tablename"]          # in check_attrs
366          self.idmap[ID] = self.theSession.OpenDBShapeStore(db, tablename)          geometry_column = attrs["geometry_column"]
367            if not geometry_column:
368                geometry_column = None
369            dbopen = self.theSession.OpenDBShapeStore
370            self.idmap[attrs["id"]] = dbopen(attrs["dbconn"], attrs["tablename"],
371                                             id_column = attrs["id_column"],
372                                             geometry_column=geometry_column)
373    
374      def start_fileshapesource(self, name, qname, attrs):      def start_fileshapesource(self, name, qname, attrs):
375          attrs = self.check_attrs(name, attrs,          attrs = self.check_attrs(name, attrs,
# Line 311  class SessionLoader(XMLReader): Line 382  class SessionLoader(XMLReader):
382          filetype = attrs["filetype"]          filetype = attrs["filetype"]
383          if filetype != "shapefile":          if filetype != "shapefile":
384              raise LoadError("shapesource filetype %r not supported" % filetype)              raise LoadError("shapesource filetype %r not supported" % filetype)
385          self.idmap[ID] = self.theSession.OpenShapefile(filename)          self.idmap[ID] = self.open_shapefile(filename)
386    
387      def start_derivedshapesource(self, name, qname, attrs):      def start_derivedshapesource(self, name, qname, attrs):
388          attrs = self.check_attrs(name, attrs,          attrs = self.check_attrs(name, attrs,
# Line 422  class SessionLoader(XMLReader): Line 493  class SessionLoader(XMLReader):
493          if attrs.has_key((None, "shapestore")):          if attrs.has_key((None, "shapestore")):
494              store = self.idmap[attrs[(None, "shapestore")]]              store = self.idmap[attrs[(None, "shapestore")]]
495          else:          else:
496              store = self.theSession.OpenShapefile(filename)              store = self.open_shapefile(filename)
497    
498          self.aLayer = layer_class(title, store,          self.aLayer = layer_class(title, store,
499                                    fill = fill, stroke = stroke,                                    fill = fill, stroke = stroke,
500                                    lineWidth = stroke_width,                                    lineWidth = stroke_width,
# Line 438  class SessionLoader(XMLReader): Line 510  class SessionLoader(XMLReader):
510          filename = os.path.join(self.GetDirectory(), filename)          filename = os.path.join(self.GetDirectory(), filename)
511          filename = self.encode(filename)          filename = self.encode(filename)
512          visible  = self.encode(attrs.get((None, 'visible'), "true")) != "false"          visible  = self.encode(attrs.get((None, 'visible'), "true")) != "false"
513            opacity  = float(attrs.get((None, 'opacity'), "1"))
514            masktype = str(attrs.get((None, 'masktype'), "bit"))
515    
516          self.aLayer = layer_class(title, filename, visible = visible)          masktypes = {"none": layer_class.MASK_NONE,
517                         "bit":  layer_class.MASK_BIT,
518                         "alpha": layer_class.MASK_ALPHA}
519    
520            self.aLayer = layer_class(title, filename,
521                                      visible = visible,
522                                      opacity = opacity,
523                                      masktype = masktypes[masktype])
524    
525      def end_rasterlayer(self, name, qname):      def end_rasterlayer(self, name, qname):
526          self.aMap.AddLayer(self.aLayer)          self.aMap.AddLayer(self.aLayer)
527          self.aLayer = None          self.aLayer = None
528    
529      def start_classification(self, name, qname, attrs):      def start_classification(self, name, qname, attrs):
530          field = attrs.get((None, 'field'), None)          # field and field_type are optional because the classification
531            # can also be empty, ie. have only a default.
532            attrs = self.check_attrs(name, attrs,
533                                     [AttrDesc("field", False),
534                                      AttrDesc("field_type", False)])
535    
536            field = attrs["field"]
537            fieldType = attrs["field_type"]
538    
539            if field == "": return # no need to set classification column.
540    
         fieldType = attrs.get((None, 'field_type'), None)  
541          dbFieldType = self.aLayer.GetFieldType(field)          dbFieldType = self.aLayer.GetFieldType(field)
542    
543          if fieldType != dbFieldType:          if fieldType != dbFieldType:
# Line 497  class SessionLoader(XMLReader): Line 586  class SessionLoader(XMLReader):
586          del self.cl_group, self.cl_prop          del self.cl_group, self.cl_prop
587    
588      def start_clrange(self, name, qname, attrs):      def start_clrange(self, name, qname, attrs):
589            attrs = self.check_attrs(name, attrs,
590                                     [AttrDesc("range", False, None),
591                                      AttrDesc("min", False, None),
592                                      AttrDesc("max", False, None)])
593    
594          range = attrs.get((None, 'range'), None)          range = attrs['range']
595          # for backward compatibility (min/max are not saved)          # for backward compatibility (min/max are not saved)
596          min   = attrs.get((None, 'min'), None)          min   = attrs['min']
597          max   = attrs.get((None, 'max'), None)          max   = attrs['max']
598    
599          try:          try:
600              if range is not None:              if range is not None:
# Line 524  class SessionLoader(XMLReader): Line 617  class SessionLoader(XMLReader):
617          self.aLayer.GetClassification().AppendGroup(self.cl_group)          self.aLayer.GetClassification().AppendGroup(self.cl_group)
618          del self.cl_group, self.cl_prop          del self.cl_group, self.cl_prop
619    
620    
621        def start_clpattern(self, name, qname, attrs):
622            pattern = attrs.get((None, 'pattern'), "")
623    
624            self.cl_group = ClassGroupPattern(self.encode(pattern))
625            self.cl_group.SetLabel(self.encode(attrs.get((None, 'label'), "")))
626            self.cl_prop = ClassGroupProperties()
627    
628        def end_clpattern(self, name, qname):
629            self.cl_group.SetProperties(self.cl_prop)
630            self.aLayer.GetClassification().AppendGroup(self.cl_group)
631            del self.cl_group, self.cl_prop
632    
633    
634      def start_cldata(self, name, qname, attrs):      def start_cldata(self, name, qname, attrs):
635          self.cl_prop.SetLineColor(          self.cl_prop.SetLineColor(
636              parse_color(attrs.get((None, 'stroke'), "None")))              parse_color(attrs.get((None, 'stroke'), "None")))
637          self.cl_prop.SetLineWidth(          self.cl_prop.SetLineWidth(
638              int(attrs.get((None, 'stroke_width'), "0")))              int(attrs.get((None, 'stroke_width'), "0")))
639            self.cl_prop.SetSize(int(attrs.get((None, 'size'), "5")))
640          self.cl_prop.SetFill(parse_color(attrs.get((None, 'fill'), "None")))          self.cl_prop.SetFill(parse_color(attrs.get((None, 'fill'), "None")))
641    
642      def end_cldata(self, name, qname):      def end_cldata(self, name, qname):
# Line 538  class SessionLoader(XMLReader): Line 646  class SessionLoader(XMLReader):
646          self.aLayer = self.aMap.LabelLayer()          self.aLayer = self.aMap.LabelLayer()
647    
648      def start_label(self, name, qname, attrs):      def start_label(self, name, qname, attrs):
649          x = float(attrs[(None, 'x')])          attrs = self.check_attrs(name, attrs,
650          y = float(attrs[(None, 'y')])                                   [AttrDesc("x", True, conversion = float),
651          text = self.encode(attrs[(None, 'text')])                                    AttrDesc("y", True, conversion = float),
652          halign = attrs[(None, 'halign')]                                    AttrDesc("text", True),
653          valign = attrs[(None, 'valign')]                                    AttrDesc("halign", True,
654                                               conversion = "ascii"),
655                                      AttrDesc("valign", True,
656                                               conversion = "ascii")])
657            x = attrs['x']
658            y = attrs['y']
659            text = attrs['text']
660            halign = attrs['halign']
661            valign = attrs['valign']
662            if halign not in ("left", "center", "right"):
663                raise LoadError("Unsupported halign value %r" % halign)
664            if valign not in ("top", "center", "bottom"):
665                raise LoadError("Unsupported valign value %r" % valign)
666          self.aLayer.AddLabel(x, y, text, halign = halign, valign = valign)          self.aLayer.AddLabel(x, y, text, halign = halign, valign = valign)
667    
668      def characters(self, chars):      def characters(self, chars):
669          pass          pass
670    
671    
672  def load_session(filename, db_connection_callback = None):  def load_session(filename, db_connection_callback = None,
673                               shapefile_callback = None):
674      """Load a Thuban session from the file object file      """Load a Thuban session from the file object file
675    
676      The db_connection_callback, if given should be a callable object      The db_connection_callback, if given should be a callable object
# Line 562  def load_session(filename, db_connection Line 683  def load_session(filename, db_connection
683      corrected and perhaps additional parameters like a password or None      corrected and perhaps additional parameters like a password or None
684      to indicate that the user cancelled.      to indicate that the user cancelled.
685      """      """
686      handler = SessionLoader(db_connection_callback)      handler = SessionLoader(db_connection_callback, shapefile_callback)
687      handler.read(filename)      handler.read(filename)
688    
689      session = handler.theSession      session = handler.theSession

Legend:
Removed from v.1930  
changed lines
  Added in v.2734

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26