[Thuban-commits] r2688 - in trunk/thuban: . Doc/manual Resources/XML Thuban/Model Thuban/UI test
scm-commit@wald.intevation.org
scm-commit at wald.intevation.org
Fri Jun 30 14:27:22 CEST 2006
Author: frank
Date: 2006-06-30 14:27:20 +0200 (Fri, 30 Jun 2006)
New Revision: 2688
Modified:
trunk/thuban/ChangeLog
trunk/thuban/Doc/manual/thuban-manual.xml
trunk/thuban/Resources/XML/thuban-1.1.dtd
trunk/thuban/Thuban/Model/classification.py
trunk/thuban/Thuban/Model/load.py
trunk/thuban/Thuban/Model/save.py
trunk/thuban/Thuban/UI/classifier.py
trunk/thuban/test/test_classification.py
trunk/thuban/test/test_layer.py
trunk/thuban/test/test_load.py
trunk/thuban/test/test_save.py
Log:
New Classification "Pattern": Classify text attributes by regexp.
Modified: trunk/thuban/ChangeLog
===================================================================
--- trunk/thuban/ChangeLog 2006-06-29 13:50:16 UTC (rev 2687)
+++ trunk/thuban/ChangeLog 2006-06-30 12:27:20 UTC (rev 2688)
@@ -1,3 +1,50 @@
+2006-06-27 Frank Koormann <frank at intevation.de>
+
+ New Classification "Pattern": Classify text attributes by regexp.
+
+ * Thuban/Model/classification.py (class ClassGroupPattern):
+ New, group is associated with a regular expression.
+ (Classification._compile_classification): Store compiled regexp and
+ original group for pattern.
+ (Classification.FindGroup): Added pattern.
+
+ * Thuban/UI/classifier.py
+ (ClassGrid._OnLabelRightClicked, ClassGrid.labelPopup):
+ New, add popup to select singleton/pattern.
+ (ClassTable.GetRowLabelValue, ClassTable.GetValueAsCustom,
+ ClassTable.SetValueAsCustom): Added pattern.
+ (ClassTable.__ParseInput): Autodetect singleton/pattern.
+
+ * Thuban/Model/save.py (SessionSaver.write_classification):
+ Added pattern.
+
+ * Thuban/Model/load.py (SessionLoader.start_clpattern,
+ SessionLoader.end_clpattern): New, process pattern elements.
+
+ * test/test_classification.py (class TestClassGroupPattern): New.
+ (TestClassification.test_add_pattern,
+ TestClassification.test_multiple_groups_textual,
+ TestClassification.test_deepcopy_textual): New.
+ (TestClassification.test_multiple_groups_numerical):
+ Renamed test_multiple_groups.
+ (TestClassification.test_deepcopy_numerical): Renamed test_deepcopy.
+
+ * test/test_save.py (SaveSessionTest.testClassifiedLayer):
+ Added pattern.
+
+ * test/test_load.py (ClassificationTest.TestLayers, TestClassification):
+ Added pattern.
+
+ * test/test_layer.py
+ (TestLayerModification.test_set_classification_textual): New
+ (TestLayerModification.test_set_classification_numerical):
+ Renamed test_set_classification.
+
+ * Doc/manual/thuban-manual.xml: Added pattern to layer classification
+ description.
+
+ * Resources/XML/thuban-1.1.dtd: Added clpattern element and attribs.
+
2006-06-29 Didrik Pinte <dpinte at itae.be>
* Thuban/version.py: Bugfix determination of SQLite, the wright one !
Modified: trunk/thuban/Doc/manual/thuban-manual.xml
===================================================================
--- trunk/thuban/Doc/manual/thuban-manual.xml 2006-06-29 13:50:16 UTC (rev 2687)
+++ trunk/thuban/Doc/manual/thuban-manual.xml 2006-06-30 12:27:20 UTC (rev 2688)
@@ -19,13 +19,13 @@
</author>
</authorgroup>
<copyright>
- <year>2003, 2004, 2005</year>
+ <year>2003, 2004, 2005, 2006</year>
<holder>Intevation GmbH</holder>
</copyright>
<revhistory>
<!-- comment this first revision out when releasing a real version -->
<revision>
- <revnumber>CVS version $Id$</revnumber>
+ <revnumber>SVN version $Id$</revnumber>
<date></date>
<revremark>Under development.</revremark>
</revision>
@@ -1192,14 +1192,21 @@
<section><title>Value</title>
<para>
The Value column of the classification table is the value that will
- be matched when the map is being drawn. The type of data that can
+ be matched when the map is being drawn. The type of filter that can
entered into this field depends on the type of data of the
- classification field.
- </para>
+ classification field:
+ </para>
<para>
If the field is of type Text, anything entered
- into the field is valid. The text will be compared literally to the
- value of the shape attribute, including case sensitivity.
+ into the field is valid. By default the text will be compared
+ literally to the
+ value of the shape attribute, including case sensitivity.
+ Alternatively the comparison can be based on regular experessions.
+ Right-click on the row label to open a popup menu with the options
+ <guibutton>Singleton</guibutton> (literal comparison) and
+ <guibutton>Pattern</guibutton> (regular expressions).
+ </para>
+ <para>
If the type is Integer, then any valid integer may be entered. In
addition, with special syntax, a range of values can be entered.
A range from <varname>start</varname> to <varname>end</varname>
@@ -1210,7 +1217,7 @@
Decimal. They represent any rational number and can be used in
ranges as well.
</para>
- </section>
+ </section>
<section><title>Label</title>
<para>
By default, the text that is displayed for a group in the legend
Modified: trunk/thuban/Resources/XML/thuban-1.1.dtd
===================================================================
--- trunk/thuban/Resources/XML/thuban-1.1.dtd 2006-06-29 13:50:16 UTC (rev 2687)
+++ trunk/thuban/Resources/XML/thuban-1.1.dtd 2006-06-30 12:27:20 UTC (rev 2688)
@@ -179,13 +179,14 @@
<!-- Classification data -->
-<!ELEMENT classification (clnull?, clpoint*, clrange*, clcont*)>
+<!ELEMENT classification (clnull?, clpoint*, clrange*, clpattern*, clcont*)>
<!ATTLIST classification field CDATA>
<!ATTLIST classification field_type CDATA>
<!ELEMENT clnull (cldata*)>
<!ELEMENT clpoint (cldata*)>
<!ELEMENT clrange (cldata*)>
+<!ELEMENT clpattern (cldata*)>
<!ELEMENT clcont (cldata*)>
<!ATTLIST clnull label CDATA #IMPLIED>
@@ -198,6 +199,9 @@
<!ATTLIST clrange range CDATA #IMPLIED>
<!ATTLIST clrange label CDATA #IMPLIED>
+<!ATTLIST clpattern pattern CDATA #REQUIRED>
+<!ATTLIST clpattern label CDATA #IMPLIED>
+
<!ATTLIST clcont rmin CDATA #REQUIRED>
<!ATTLIST clcont rmax CDATA #REQUIRED>
<!ATTLIST clcont dmin CDATA #REQUIRED>
Modified: trunk/thuban/Thuban/Model/classification.py
===================================================================
--- trunk/thuban/Thuban/Model/classification.py 2006-06-29 13:50:16 UTC (rev 2687)
+++ trunk/thuban/Thuban/Model/classification.py 2006-06-30 12:27:20 UTC (rev 2688)
@@ -1,7 +1,8 @@
-# Copyright (c) 2001, 2003, 2005 by Intevation GmbH
+# Copyright (c) 2001, 2003, 2005, 2006 by Intevation GmbH
# Authors:
# Jonathan Coles <jonathan at intevation.de>
# Jan-Oliver Wagner <jan at intevation.de> (2005)
+# Frank Koormann <frank at intevation.de> (2006)
#
# This program is free software under the GPL (>=v2)
# Read the file COPYING coming with Thuban for details.
@@ -22,6 +23,7 @@
"""
import copy, operator, types
+import re
from Thuban import _
@@ -109,6 +111,11 @@
is true.
+ 'pattern'
+
+ The tuple contains the compiled regular expression object and
+ the original group object.
+
The compiled classification is bound to
self._compile_classification.
"""
@@ -118,6 +125,9 @@
if not compiled or compiled[-1][0] != "singletons":
compiled.append(("singletons", {}))
compiled[-1][1].setdefault(group.GetValue(), group)
+ elif isinstance(group, ClassGroupPattern):
+ pattern = re.compile(group.GetPattern())
+ compiled.append(("pattern", (pattern, group)))
elif isinstance(group, ClassGroupRange):
left, min, max, right = group.GetRangeTuple()
if left == "[":
@@ -267,6 +277,13 @@
lfunc, min, max, rfunc, g = params
if lfunc(min, value) and rfunc(max, value):
return g
+ elif typ == "pattern":
+ # TODO: make pattern more robust. The following chrashes
+ # if accidently be applied on non-string columns.
+ # Usually the UI prevents this.
+ p, g = params
+ if p.match(value):
+ return g
return self.GetDefaultGroup()
@@ -747,6 +764,64 @@
def __repr__(self):
return "(" + str(self.__range) + ClassGroup.__repr__(self) + ")"
+class ClassGroupPattern(ClassGroup):
+ """A Group that is associated with a reg exp pattern."""
+
+ def __init__(self, pattern = "", props = None, label = "", group = None):
+ """Constructor.
+
+ pattern -- the associated pattern.
+
+ props -- a ClassGroupProperites object. If props is None a default
+ set of properties is created.
+
+ label -- a label for this group.
+ """
+ ClassGroup.__init__(self, label, props, group)
+
+ self.SetPattern(pattern)
+
+ def __copy__(self):
+ return ClassGroupPattern(self.GetPattern(),
+ self.GetProperties(),
+ self.GetLabel())
+
+ def __deepcopy__(self, memo):
+ return ClassGroupPattern(self.GetPattern(), group = self)
+
+ def GetPattern(self):
+ """Return the associated pattern."""
+ return self.__pattern
+
+ def SetPattern(self, pattern):
+ """Associate this Group with the given pattern."""
+ self.__pattern = pattern
+
+ def Matches(self, pattern):
+ """Check if the given pattern matches the associated Group pattern."""
+
+ """Returns True if the value matches, False otherwise."""
+
+ if re.match(self.__pattern, pattern):
+ return True
+ else:
+ return False
+
+ def GetDisplayText(self):
+ label = self.GetLabel()
+
+ if label != "": return label
+
+ return str(self.GetPattern())
+
+ def __eq__(self, other):
+ return ClassGroup.__eq__(self, other) \
+ and isinstance(other, ClassGroupPattern) \
+ and self.__pattern == other.__pattern
+
+ def __repr__(self):
+ return "(" + repr(self.__pattern) + ", " + ClassGroup.__repr__(self) + ")"
+
class ClassGroupMap(ClassGroup):
"""Currently, this class is not used."""
Modified: trunk/thuban/Thuban/Model/load.py
===================================================================
--- trunk/thuban/Thuban/Model/load.py 2006-06-29 13:50:16 UTC (rev 2687)
+++ trunk/thuban/Thuban/Model/load.py 2006-06-30 12:27:20 UTC (rev 2688)
@@ -33,7 +33,8 @@
from Thuban.Model.proj import Projection
from Thuban.Model.range import Range
from Thuban.Model.classification import Classification, \
- ClassGroupDefault, ClassGroupSingleton, ClassGroupRange, ClassGroupMap, \
+ ClassGroupDefault, ClassGroupSingleton, ClassGroupRange, \
+ ClassGroupPattern, ClassGroupMap, \
ClassGroupProperties
from Thuban.Model.data import DerivedShapeStore, ShapefileStore
from Thuban.Model.table import DBFTable
@@ -136,6 +137,7 @@
'clnull' : ("start_clnull", "end_clnull"),
'clpoint' : ("start_clpoint", "end_clpoint"),
'clrange' : ("start_clrange", "end_clrange"),
+ 'clpattern' : ("start_clpattern", "end_clpattern"),
'cldata' : ("start_cldata", "end_cldata"),
'table' : ("start_table", "end_table"),
'labellayer' : ("start_labellayer", None),
@@ -615,6 +617,20 @@
self.aLayer.GetClassification().AppendGroup(self.cl_group)
del self.cl_group, self.cl_prop
+
+ def start_clpattern(self, name, qname, attrs):
+ pattern = attrs.get((None, 'pattern'), "")
+
+ self.cl_group = ClassGroupPattern(self.encode(pattern))
+ self.cl_group.SetLabel(self.encode(attrs.get((None, 'label'), "")))
+ self.cl_prop = ClassGroupProperties()
+
+ def end_clpattern(self, name, qname):
+ self.cl_group.SetProperties(self.cl_prop)
+ self.aLayer.GetClassification().AppendGroup(self.cl_group)
+ del self.cl_group, self.cl_prop
+
+
def start_cldata(self, name, qname, attrs):
self.cl_prop.SetLineColor(
parse_color(attrs.get((None, 'stroke'), "None")))
Modified: trunk/thuban/Thuban/Model/save.py
===================================================================
--- trunk/thuban/Thuban/Model/save.py 2006-06-29 13:50:16 UTC (rev 2687)
+++ trunk/thuban/Thuban/Model/save.py 2006-06-30 12:27:20 UTC (rev 2688)
@@ -23,7 +23,8 @@
from Thuban.Model.layer import Layer, RasterLayer
from Thuban.Model.classification import \
- ClassGroupDefault, ClassGroupSingleton, ClassGroupRange, ClassGroupMap
+ ClassGroupDefault, ClassGroupSingleton, ClassGroupRange, \
+ ClassGroupPattern, ClassGroupMap
from Thuban.Model.transientdb import AutoTransientTable, TransientJoinedTable
from Thuban.Model.table import DBFTable, FIELDTYPE_STRING
from Thuban.Model.data import DerivedShapeStore, FileShapeStore, \
@@ -342,6 +343,11 @@
open_el = 'clrange label="%s" range="%s"' \
% (self.encode(g.GetLabel()), str(g.GetRange()))
close_el = 'clrange'
+ elif isinstance(g, ClassGroupPattern):
+ open_el = 'clpattern label="%s" pattern="%s"' \
+ % (self.encode(g.GetLabel()), str(g.GetPattern()))
+ close_el = 'clpattern'
+
else:
assert False, _("Unsupported group type in classification")
continue
Modified: trunk/thuban/Thuban/UI/classifier.py
===================================================================
--- trunk/thuban/Thuban/UI/classifier.py 2006-06-29 13:50:16 UTC (rev 2687)
+++ trunk/thuban/Thuban/UI/classifier.py 2006-06-30 12:27:20 UTC (rev 2688)
@@ -2,7 +2,7 @@
# Authors:
# Jan-Oliver Wagner <jan at intevation.de> (2003-2004)
# Martin Schulze <joey at infodrom.org> (2004)
-# Frank Koormann <frank at intevation.de> (2003)
+# Frank Koormann <frank at intevation.de> (2003, 2006)
# Bernhard Herzog <bh at intevation.de> (2003)
# Jonathan Coles <jonathan at intevation.de> (2003)
#
@@ -16,6 +16,7 @@
# $Id$
import copy
+import re
from Thuban.Model.table import FIELDTYPE_INT, FIELDTYPE_DOUBLE, \
FIELDTYPE_STRING
@@ -30,7 +31,7 @@
from Thuban.Model.range import Range
from Thuban.Model.classification import \
Classification, ClassGroupDefault, \
- ClassGroupSingleton, ClassGroupRange, ClassGroupMap, \
+ ClassGroupSingleton, ClassGroupPattern, ClassGroupRange, ClassGroupMap, \
ClassGroupProperties
from Thuban.Model.color import Transparent
@@ -84,7 +85,9 @@
EVT_GRID_SELECT_CELL(self, self._OnSelectedCell)
EVT_GRID_COL_SIZE(self, self._OnCellResize)
EVT_GRID_ROW_SIZE(self, self._OnCellResize)
+ EVT_GRID_LABEL_RIGHT_CLICK(self, self._OnLabelRightClicked)
+
#def GetCellAttr(self, row, col):
#print "GetCellAttr ", row, col
#wxGrid.GetCellAttr(self, row, col)
@@ -256,6 +259,58 @@
self.FitInside()
event.Skip()
+ def _OnLabelRightClicked(self, event):
+ """Process right click on label, raise popup for row labels."""
+ row, col = event.GetRow(), event.GetCol()
+ if col == -1:
+ self.labelPopup(event, row)
+
+ def labelPopup(self, event, row):
+ """Raise grid label popup."""
+ # check if row label is Pattern or Singleton
+ label = self.GetRowLabelValue(row)
+ if (label == _("Pattern") or label == _("Singleton")):
+ xe,ye = event.GetPosition()
+ x=self.GetRowSize(row)/2
+ menu = wxMenu()
+ patternID = wxNewId()
+ singletonID = wxNewId()
+
+ def _SetSingleton(event, self=self, row=row):
+ table = self.GetTable()
+ group = table.clazz.GetGroup(row - 1)
+ if not isinstance(group, ClassGroupSingleton):
+ ngroup = ClassGroupSingleton(
+ group.GetPattern(),
+ group.GetProperties(),
+ group.GetLabel()
+ )
+ table.SetClassGroup(row, ngroup)
+
+ def _SetPattern(event, self=self, row=row):
+ table = self.GetTable()
+ group = table.clazz.GetGroup(row - 1)
+ if not isinstance(group, ClassGroupPattern):
+ try:
+ re.compile(group.GetValue())
+ except:
+ pass
+ else:
+ ngroup = ClassGroupPattern(
+ group.GetValue(),
+ group.GetProperties(),
+ group.GetLabel()
+ )
+ table.SetClassGroup(row, ngroup)
+
+ menu.Append(singletonID, _("Singleton"))
+ EVT_MENU(self, singletonID, _SetSingleton)
+ if self.GetTable().fieldType == FIELDTYPE_STRING:
+ menu.Append(patternID, _("Pattern"))
+ EVT_MENU(self, patternID, _SetPattern)
+ self.PopupMenu(menu, wxPoint(x,ye))
+ menu.Destroy()
+
class ClassTable(wxPyGridTableBase):
"""Represents the underlying data structure for the grid."""
@@ -409,6 +464,7 @@
group = self.clazz.GetGroup(row - 1)
if isinstance(group, ClassGroupDefault): return _("Default")
if isinstance(group, ClassGroupSingleton): return _("Singleton")
+ if isinstance(group, ClassGroupPattern): return _("Pattern")
if isinstance(group, ClassGroupRange): return _("Range")
if isinstance(group, ClassGroupMap): return _("Map")
@@ -472,6 +528,8 @@
return _("DEFAULT")
elif isinstance(group, ClassGroupSingleton):
return group.GetValue()
+ elif isinstance(group, ClassGroupPattern):
+ return group.GetPattern()
elif isinstance(group, ClassGroupRange):
return group.GetRange()
@@ -483,13 +541,22 @@
(string, number, or range)
Returns a tuple (type, data) where type is 0 if data is
- a singleton value, or 1 if is a range
+ a singleton value, 1 if is a range or 2 if it is a pattern.
"""
type = self.fieldType
if type == FIELDTYPE_STRING:
- return (0, value)
+ # Approach: if we can compile the value as an expression,
+ # make it a pattern, else a singleton.
+ # This is quite crude, however I don't have a better idea:
+ # How to distinct the singleton "Thuban" from the pattern "Thuban"?
+ try:
+ re.compile(value)
+ except:
+ return (0, value)
+ else:
+ return (2, value)
elif type in (FIELDTYPE_INT, FIELDTYPE_DOUBLE):
if type == FIELDTYPE_INT:
# the float call allows the user to enter 1.0 for 1
@@ -573,6 +640,11 @@
ngroup = ClassGroupRange(props = props)
changed = True
ngroup.SetRange(dataInfo[1])
+ elif dataInfo[0] == 2:
+ if not isinstance(group, ClassGroupPattern):
+ ngroup = ClassGroupPattern(props = props)
+ changed = True
+ ngroup.SetPattern(dataInfo[1])
else:
assert False
pass
Modified: trunk/thuban/test/test_classification.py
===================================================================
--- trunk/thuban/test/test_classification.py 2006-06-29 13:50:16 UTC (rev 2687)
+++ trunk/thuban/test/test_classification.py 2006-06-30 12:27:20 UTC (rev 2688)
@@ -24,7 +24,7 @@
from Thuban.Model.classification import \
Classification, ClassGroup, \
ClassGroupDefault, ClassGroupSingleton, ClassGroupRange,\
- ClassGroupProperties
+ ClassGroupPattern, ClassGroupProperties
from Thuban.Model.messages import CLASS_CHANGED
from Thuban.Model.range import Range
@@ -246,6 +246,55 @@
self.assertEqual(group, groupCopy)
+class TestClassGroupPattern(unittest.TestCase):
+
+ def test(self):
+ """Test ClassGroupPattern"""
+
+ defProps = ClassGroupProperties()
+ newProps = ClassGroupProperties()
+ newProps.SetLineColor(Color(.25, .5, .75))
+ newProps.SetLineWidth(5)
+ newProps.SetFill(Color(.12, .24, .36))
+
+ # test empty constructor
+ group = ClassGroupPattern()
+
+ self.assertEqual(group.GetPattern(), "")
+ self.assertEqual(group.GetProperties(), defProps)
+ self.assertEqual(group.GetLabel(), "")
+
+ # test SetProperties()/GetProperties()
+ group.SetProperties(newProps)
+ self.assertEqual(group.GetProperties(), newProps)
+
+ # test SetPattern()
+ group.SetPattern("A")
+ self.assertEqual(group.GetPattern(), "A")
+
+ # test Matches()
+ self.assertEqual(group.Matches("CBA"), False)
+ self.assertEqual(group.Matches("ABC"), True)
+
+ group.SetPattern("a")
+ self.assertNotEqual(group.GetPattern(), "A")
+
+ # test Matches()
+ self.assertEqual(group.Matches("Abc"), False)
+ self.assertEqual(group.Matches("aBC"), True)
+
+ group.SetPattern("hallo")
+ self.assertEqual(group.GetPattern(), "hallo")
+
+ # test Matches()
+ self.assertEqual(group.Matches("HALLO"), False)
+ self.assertEqual(group.Matches("hallo"), True)
+
+ # test copy
+ groupCopy = copy.copy(group)
+ self.assertEqual(group, groupCopy)
+
+
class TestClassification(unittest.TestCase, support.SubscriberMixin):
"""Test cases for Classification"""
@@ -345,8 +394,20 @@
self.assertEquals(self.clazz.FindGroup(10),
self.clazz.GetDefaultGroup())
- def test_multiple_groups(self):
- """Test Classification with multiple groups"""
+ def test_add_pattern(self):
+ """Test Classification.AppendGroup(ClassGroupPattern())"""
+ self.assertEquals(self.clazz.FindGroup(5),
+ self.clazz.GetDefaultGroup())
+
+ s = ClassGroupPattern("A")
+ self.clazz.AppendGroup(s)
+ self.check_messages([(CLASS_CHANGED,)])
+ self.assertEquals(self.clazz.FindGroup("A"), s)
+ self.assertEquals(self.clazz.FindGroup("B"),
+ self.clazz.GetDefaultGroup())
+
+ def test_multiple_groups_numerical(self):
+ """Test numerical Classification with multiple groups"""
# two singletons matching 1 to test whether they're tested in
# the right order. Use a non default fill on the second to make
# it compare unequal to the first.
@@ -376,6 +437,28 @@
self.assertEquals(self.clazz.FindGroup(10),
self.clazz.GetDefaultGroup())
+ def test_multiple_groups_textual(self):
+ """Test textual Classification with multiple groups"""
+ # A singleton and a pattern matching 'A' to test whether
+ # they're tested in the right order. Use a non default fill
+ # on the pattern to make it compare unequal to the first.
+ s = ClassGroupSingleton("A")
+ p = ClassGroupPattern("A")
+ p.GetProperties().SetFill(blue)
+ # Sanity check: are they considered different?
+ self.assertNotEqual(s, p)
+
+ self.clazz.AppendGroup(s)
+ self.clazz.AppendGroup(p)
+ self.check_messages([(CLASS_CHANGED,), (CLASS_CHANGED,)])
+
+ self.assertEquals(self.clazz.FindGroup("bca"),
+ self.clazz.GetDefaultGroup())
+ self.assertEquals(self.clazz.FindGroup("A"), s)
+ self.assertEquals(self.clazz.FindGroup("Abc"), p)
+ self.assertEquals(self.clazz.FindGroup("abc"),
+ self.clazz.GetDefaultGroup())
+
def test_insert_group(self):
"""Test Classification.InsertGroup()"""
s1 = ClassGroupSingleton(1)
@@ -424,8 +507,8 @@
self.assertEquals(self.clazz.FindGroup(1), s1)
self.check_messages([(CLASS_CHANGED,)])
- def test_deepcopy(self):
- """Test deepcopy(Classification())"""
+ def test_deepcopy_numerical(self):
+ """Test deepcopy(numerical Classification())"""
self.clazz.AppendGroup(ClassGroupSingleton(5))
self.clazz.AppendGroup(ClassGroupRange((-10, 10)))
@@ -436,7 +519,19 @@
for i in range(clazz.GetNumGroups()):
self.assertEquals(clazz.GetGroup(i), self.clazz.GetGroup(i))
+ def test_deepcopy_textual(self):
+ """Test deepcopy(textual Classification())"""
+ self.clazz.AppendGroup(ClassGroupSingleton("A"))
+ self.clazz.AppendGroup(ClassGroupPattern("B"))
+ clazz = copy.deepcopy(self.clazz)
+
+ self.assertEquals(clazz.GetNumGroups(), self.clazz.GetNumGroups())
+
+ for i in range(clazz.GetNumGroups()):
+ self.assertEquals(clazz.GetGroup(i), self.clazz.GetGroup(i))
+
+
def test_iterator(self):
"""Test Classification iteration"""
groups = [ClassGroupSingleton(5), ClassGroupSingleton(5),
Modified: trunk/thuban/test/test_layer.py
===================================================================
--- trunk/thuban/test/test_layer.py 2006-06-29 13:50:16 UTC (rev 2687)
+++ trunk/thuban/test/test_layer.py 2006-06-30 12:27:20 UTC (rev 2688)
@@ -32,7 +32,7 @@
from Thuban.Model.proj import Projection
from Thuban.Model.data import DerivedShapeStore
from Thuban.Model.classification import Classification, ClassGroupSingleton, \
- ClassGroupRange
+ ClassGroupRange, ClassGroupPattern
from Thuban.Model.color import Color
import Thuban.Model.resource
@@ -416,8 +416,8 @@
# the layer.
self.failIf(self.layer.WasModified())
- def test_set_classification(self):
- """Test Layer.SetClassification"""
+ def test_set_classification_numerical(self):
+ """Test Layer.SetClassification numerical"""
classification = Classification()
classification.AppendGroup(ClassGroupRange((0.0, 0.1)))
@@ -438,7 +438,29 @@
self.check_messages([(self.layer, LAYER_CHANGED)])
self.failUnless(self.layer.WasModified())
+ def test_set_classification_textual(self):
+ """Test Layer.SetClassification textual"""
+ classification = Classification()
+ classification.AppendGroup(ClassGroupPattern("I"))
+ self.layer.SetClassification(classification)
+ self.layer.SetClassificationColumn("POPYCOUN")
+
+ self.check_messages([(self.layer, LAYER_CHANGED),
+ (self.layer, LAYER_CHANGED)])
+ self.failUnless(self.layer.WasModified())
+
+ self.clear_messages()
+ self.layer.UnsetModified()
+
+ # change only the classification column. This should issue a
+ # LAYER_CHANGED message as well.
+ self.layer.SetClassificationColumn("POPYREG")
+
+ self.check_messages([(self.layer, LAYER_CHANGED)])
+ self.failUnless(self.layer.WasModified())
+
+
def test_tree_info(self):
"""Test Layer.TreeInfo"""
self.assertEquals(self.layer.TreeInfo(),
Modified: trunk/thuban/test/test_load.py
===================================================================
--- trunk/thuban/test/test_load.py 2006-06-29 13:50:16 UTC (rev 2687)
+++ trunk/thuban/test/test_load.py 2006-06-30 12:27:20 UTC (rev 2688)
@@ -46,7 +46,7 @@
LoadCancelled
from Thuban.Model.color import Transparent
from Thuban.Model.classification import ClassGroupProperties, ClassGroupRange,\
- ClassGroupSingleton, ClassGroupDefault
+ ClassGroupSingleton, ClassGroupPattern, ClassGroupDefault
from Thuban.Model.postgisdb import ConnectionError
from Thuban.Model.table import DBFTable, MemoryTable, \
FIELDTYPE_DOUBLE, FIELDTYPE_INT, FIELDTYPE_STRING, \
@@ -175,6 +175,9 @@
elif data[CLASSES][i][GROUP_TYPE] == "single":
g = ClassGroupSingleton(data[CLASSES][i][GROUP_DATA],
props, data[CLASSES][i][GROUP_LABEL])
+ elif data[CLASSES][i][GROUP_TYPE] == "pattern":
+ g = ClassGroupPattern(data[CLASSES][i][GROUP_DATA],
+ props, data[CLASSES][i][GROUP_LABEL])
eq(group, g)
@@ -456,6 +459,8 @@
filename="../../Data/iceland/political.shp"/>
<fileshapesource filetype="shapefile" id="D138504492"
filename="../../Data/iceland/political.shp"/>
+ <fileshapesource filetype="shapefile" id="D123456789"
+ filename="../../Data/iceland/cultural_landmark-point.shp"/>
<map title="Test Map">
<projection name="">
<parameter value="zone=26"/>
@@ -498,6 +503,19 @@
</clpoint>
</classification>
</layer>
+ <layer shapestore="D123456789" visible="true" title="My Layer 3">
+ <classification field="CLPTLABEL" field_type="string">
+ <clnull label="">
+ <cldata stroke="#000000" size="5" stroke_width="2" fill="None"/>
+ </clnull>
+ <clpoint label="" value="FARM">
+ <cldata stroke="#111111" size="5" stroke_width="1" fill="None"/>
+ </clpoint>
+ <clpattern label="" pattern="BUI">
+ <cldata stroke="#000000" size="5" stroke_width="1" fill="None"/>
+ </clpattern>
+ </classification>
+ </layer>
</map>
</session>
'''
@@ -529,7 +547,15 @@
("range", (-1, 0), "",
("#000000", 1, "None")),
("single", -.5, "",
- ("#000000", 1, "None"))])]
+ ("#000000", 1, "None"))]),
+ ("My Layer 3", 2,
+ [("default", (), "",
+ ("#000000", 2, "None")),
+ ("single", "FARM", "",
+ ("#111111", 1, "None")),
+ ("pattern", "BUI", "",
+ ("#000000", 1, "None"))]),
+ ]
self.TestLayers(map.Layers(), expected)
Modified: trunk/thuban/test/test_save.py
===================================================================
--- trunk/thuban/test/test_save.py 2006-06-29 13:50:16 UTC (rev 2687)
+++ trunk/thuban/test/test_save.py 2006-06-30 12:27:20 UTC (rev 2688)
@@ -37,7 +37,7 @@
from Thuban.Model.data import DerivedShapeStore, SHAPETYPE_ARC
from Thuban.Model.classification import ClassGroupSingleton, ClassGroupRange, \
- ClassGroupProperties
+ ClassGroupPattern, ClassGroupProperties
from Thuban.Model.range import Range
@@ -342,6 +342,9 @@
ClassGroupProperties(),
internal_from_unicode(u'\xdcml\xe4uts'))) # Uemlaeuts
+ # Pattern
+ clazz.AppendGroup(ClassGroupPattern("BUI", ClassGroupProperties(),
+ "pattern"))
filename = self.temp_file_name("%s.thuban" % self.id())
save_session(session, filename)
@@ -390,6 +393,9 @@
label="\xc3\x9cml\xc3\xa4uts">
<cldata fill="None" stroke="#000000" stroke_width="1"/>
</clpoint>
+ <clpattern pattern="BUI" label="pattern">
+ <cldata fill="None" stroke="#000000" stroke_width="1"/>
+ </clpattern>
</classification>
</layer>
</map>
More information about the Thuban-commits
mailing list