[GRASS-SVN] r29945 - in grass/trunk/gui/wxpython: gui_modules vdigit

svn_grass at osgeo.org svn_grass at osgeo.org
Mon Feb 4 15:56:26 EST 2008


Author: martinl
Date: 2008-02-04 15:56:20 -0500 (Mon, 04 Feb 2008)
New Revision: 29945

Modified:
   grass/trunk/gui/wxpython/gui_modules/dbm.py
   grass/trunk/gui/wxpython/gui_modules/digit.py
   grass/trunk/gui/wxpython/gui_modules/mapdisp.py
   grass/trunk/gui/wxpython/vdigit/cats.cpp
   grass/trunk/gui/wxpython/vdigit/digit.h
   grass/trunk/gui/wxpython/vdigit/digit.i
Log:
wxGUI/vdigit: C++ vdigit interface upgraded (display cats, attributes).
Some fixes in vedit interface.


Modified: grass/trunk/gui/wxpython/gui_modules/dbm.py
===================================================================
--- grass/trunk/gui/wxpython/gui_modules/dbm.py	2008-02-04 08:19:15 UTC (rev 29944)
+++ grass/trunk/gui/wxpython/gui_modules/dbm.py	2008-02-04 20:56:20 UTC (rev 29945)
@@ -22,7 +22,7 @@
  - ModifyTableRecord
  - NewVectorDialog
 
-(C) 2007 by the GRASS Development Team
+(C) 2007-2008 by the GRASS Development Team
 
 This program is free software under the GNU General Public
 License (>=v2). Read the file COPYING that comes with GRASS
@@ -2638,21 +2638,26 @@
     to the vector map.
 
     Attribute data can be selected based on layer and category number
-    or coordinates"""
+    or coordinates.
+
+    @param parent
+    @param map vector map
+    @param query query coordinates and distance (used for v.edit)
+    @param cats {layer: cats}
+    @param line feature id (requested for cats)
+    @param style
+    @param pos
+    @param action (add, update, display)
+    """
     def __init__(self, parent, map,
-                 layer=-1, cat=-1, # select by layer/cat
-                 queryCoords=None, qdist=-1, # select by point
+                 query=None, cats=None, line=None,
                  style=wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER,
                  pos=wx.DefaultPosition,
                  action="add"):
 
-        self.parent      = parent # mapdisplay.BufferedWindow
-        self.map         = map
-        self.layer       = layer
-        self.action      = action
-        self.cat         = cat
-        self.queryCoords = queryCoords
-        self.qdist       = qdist
+        self.parent = parent # mapdisplay.BufferedWindow
+        self.map    = map
+        self.action = action
 
         # id of selected line
         self.line = None
@@ -2663,14 +2668,9 @@
         layers = self.mapDBInfo.layers.keys() # get available layers
 
         # check if db connection / layer exists
-        if (self.layer == -1 and len(layers) <= 0) or \
-                (self.layer > 0 and self.layer not in layers):
-            if self.layer == -1:
-                label = _("Database connection "
-                          "is not defined in DB file.")
-            else:
-                label = _("Database connection for layer %d "
-                          "is not defined in DB file.") % self.layer
+        if len(layers) <= 0:
+            label = _("Database connection "
+                      "is not defined in DB file.")
 
             wx.MessageBox(parent=self.parent,
                           message=_("No attribute table linked to "
@@ -2689,10 +2689,6 @@
         # dialog body
         mainSizer = wx.BoxSizer(wx.VERTICAL)
 
-        if self.queryCoords: # select by position
-            self.line, nselected = self.mapDBInfo.SelectByPoint(self.queryCoords,
-                                                              self.qdist)
-
         # notebook
         self.notebook = wx.Notebook(parent=self, id=wx.ID_ANY, style=wx.BK_DEFAULT)
 
@@ -2700,7 +2696,7 @@
                                        label=_("Close dialog on submit"))
         self.closeDialog.SetValue(True)
 
-        self.UpdateDialog(cat, queryCoords, qdist)
+        self.UpdateDialog(query, cats, line)
 
         # set title
         if self.action == "update":
@@ -2860,15 +2856,12 @@
         """Get id of selected line or 'None' if no line is selected"""
         return self.line
 
-    def UpdateDialog(self, cat=-1, queryCoords=None, qdist=-1):
+    def UpdateDialog(self, query=None, cats=None, line=None):
         """Update dialog
 
         Return True if updated otherwise False
         """
-        self.cat         = cat
-        self.queryCoords = queryCoords
-        self.qdist       = qdist
-
+        self.line = line
         if not self.mapDBInfo:
             return False
 
@@ -2877,30 +2870,31 @@
         layers = self.mapDBInfo.layers.keys() # get available layers
 
         # id of selected line
-        if self.queryCoords: # select by position
-            self.line, nselected = self.mapDBInfo.SelectByPoint(queryCoords,
-                                                              qdist)
+        if query: # select by position
+            self.line, nselected = self.mapDBInfo.SelectByPoint(query[0],
+                                                                query[1])
         # reset notebook
         self.notebook.DeleteAllPages()
 
         for layer in layers: # for each layer
-            if self.layer > 0 and \
-                    self.layer != layer:
-                continue
+            if not query: # select by layer/cat
+                if cats.has_key(layer): 
+                    for cat in cats[layer]:
+                        nselected = self.mapDBInfo.SelectFromTable(layer, where="cat=%d" % cat)
+                else:
+                    nselected = 0
 
-            if not self.queryCoords: # select using layer/cat
-                nselected = self.mapDBInfo.SelectFromTable(layer, where="cat=%d" % self.cat)
+            # if nselected <= 0 and self.action != "add":
+            #    continue # nothing selected ...
 
-            if nselected <= 0 and self.action != "add":
-                continue # nothing selected ...
-
             if self.action == "add":
-                if nselected <= 0:
+                if nselected <= 0 and cats.has_key(layer):
                     table = self.mapDBInfo.layers[layer]["table"]
                     columns = self.mapDBInfo.tables[table]
                     for name in columns.keys():
                         if name == "cat":
-                            self.mapDBInfo.tables[table][name]['values'].append(self.cat)
+                            for cat in cats[layer]:
+                                self.mapDBInfo.tables[table][name]['values'].append(cat)
                         else:
                             self.mapDBInfo.tables[table][name]['values'].append('')
                 else: # change status 'add' -> 'update'
@@ -2924,7 +2918,7 @@
             if len(columns["cat"]['values']) == 0: # no cats
                 sizer  = wx.BoxSizer(wx.VERTICAL)
                 txt = wx.StaticText(parent=panel, id=wx.ID_ANY,
-                                    label=_("No categories available."))
+                                    label=_("No database record available."))
                 sizer.Add(txt, proportion=1,
                           flag=wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_CENTER | wx.EXPAND)
                 border.Add(item=sizer, proportion=1,
@@ -3079,7 +3073,7 @@
                                     'map=%s' % self.map,
                                     'east_north=%f,%f' % \
                                         (float(queryCoords[0]), float(queryCoords[1])),
-                                    'distance=%f' % qdist])
+                                    'distance=%f' % qdist], stderr=None)
 
         if cmdWhat.returncode == 0:
             read = False

Modified: grass/trunk/gui/wxpython/gui_modules/digit.py
===================================================================
--- grass/trunk/gui/wxpython/gui_modules/digit.py	2008-02-04 08:19:15 UTC (rev 29944)
+++ grass/trunk/gui/wxpython/gui_modules/digit.py	2008-02-04 20:56:20 UTC (rev 29945)
@@ -60,7 +60,15 @@
 # Use v.edit on background or experimental C++ interface (not yet completed)
 #
 USEVEDIT = True
+if USEVEDIT is True:
+    print >> sys.stderr, "%sWARNING: Digitization tool uses v.edit interface by default. " \
+        "This can significantly slow down some operations especially for " \
+        "middle-large vector maps. "\
+        "You can enable experimental vdigit interface by setting " \
+          "USEVEDIT to False in digit.py file." % \
+          os.linesep
 
+
 class AbstractDigit:
     """
     Abstract digitization class
@@ -985,10 +993,23 @@
         
         return ids
 
-    def GetLineCats(self):
-        """Get layer/category pairs from given (selected) line"""
-        return self.digit.GetLineCats()
+    def GetLineCats(self, line=-1):
+        """Get layer/category pairs from given (selected) line
+        
+        @param line feature id (-1 for first selected line)
+        """
+        return self.digit.GetLineCats(line)
 
+    def SetLineCats(self, line, layer, cats, add=True):
+        """Set categories for given line and layer
+
+        @param line feature id
+        @param layer layer number (-1 for first selected line)
+        @param cats list of categories
+        @param add if True to add, otherwise do delete categories
+        """
+        return self.digit.SetLineCats(line, layer, cats, add)
+
     def GetLayers(self):
         """Get list of layers"""
         return self.digit.GetLayers()
@@ -1850,9 +1871,11 @@
                 Debug.msg(3, "DigitCategoryDialog(): nothing found!")
                 return
         else:
-            self.cats = cats
+            # self.cats = dict(cats)
+            for layer in cats.keys():
+                self.cats[layer] = list(cats[layer]) # TODO: tuple to list
             self.line = line
-        
+
         # make copy of cats (used for 'reload')
         self.cats_orig = copy.deepcopy(self.cats)
 
@@ -2118,25 +2141,35 @@
         # add/delete new category
         for action, cats in check.iteritems():
             for layer in cats[0].keys():
-                catList = ""
+                catList = []
                 for cat in cats[0][layer]:
                     if layer not in cats[1].keys() or \
                             cat not in cats[1][layer]:
-                        catList += "%s," % cat
-                if catList != "":
-                    catList = catList[:-1] # remove last comma
-                    vEditCmd = ['v.edit', '--q',
-                                'map=%s' % self.map,
-                                'layer=%d' % layer,
-                                'tool=%s' % action,
-                                'cats=%s' % catList,
-                                'id=%d' % self.line]
+                        catList.append(cat)
+                if catList != []:
+                    if USEVEDIT is True:
+                        vEditCmd = ['v.edit', '--q',
+                                    'map=%s' % self.map,
+                                    'layer=%d' % layer,
+                                    'tool=%s' % action,
+                                    'cats=%s' % ",".join(["%d" % v for v in catList]),
+                                    'id=%d' % self.line]
             
-                    gcmd.Command(vEditCmd)
+                        gcmd.Command(vEditCmd)
+                    else:
+                        if action == 'catadd':
+                            add = True
+                        else:
+                            add = False
+                        self.line = self.parent.parent.digit.SetLineCats(-1, layer,
+                                                                          catList, add)
+                        if self.line < 0:
+                            wx.MessageBox(parent=self, message=_("Unable to update vector map."),
+                                          caption=_("Error"), style=wx.OK | wx.ICON_ERROR)
+        if USEVEDIT is True:           
+            # reload map (needed for v.edit)
+            self.parent.parent.digit.driver.ReloadMap()
 
-        # reload map (needed for v.edit)
-        self.parent.parent.digit.driver.ReloadMap()
-
         self.cats_orig = copy.deepcopy(self.cats)
 
         event.Skip()
@@ -2200,9 +2233,11 @@
         if cats is None:
             ret = self.__GetCategories(query[0], query[1])
         else:
-            self.cats = cats
+            # self.cats = dict(cats)
+            for layer in cats.keys():
+                self.cats[layer] = list(cats[layer]) # TODO: tuple to list
+            self.line = line
             ret = 1
-            self.line = line
         if ret == 0 or not self.line:
             Debug.msg(3, "DigitCategoryDialog(): nothing found!")
             return False

Modified: grass/trunk/gui/wxpython/gui_modules/mapdisp.py
===================================================================
--- grass/trunk/gui/wxpython/gui_modules/mapdisp.py	2008-02-04 08:19:15 UTC (rev 29944)
+++ grass/trunk/gui/wxpython/gui_modules/mapdisp.py	2008-02-04 20:56:20 UTC (rev 29945)
@@ -923,9 +923,10 @@
                     # add new record into atribute table
                     if digitClass.settings["addRecord"]:
                         # select attributes based on layer and category
+                        cats = {}
+                        cats[digitClass.settings["layer"]] = (digitClass.settings["category"],)
                         addRecordDlg = dbm.DisplayAttributesDialog(parent=self, map=map,
-                                                                   layer=digitClass.settings["layer"],
-                                                                   cat=digitClass.settings["category"],
+                                                                   cats=cats,
                                                                    pos=posWindow,
                                                                    action="add")
                         if addRecordDlg.mapDBInfo and \
@@ -970,20 +971,39 @@
 
             elif digitToolbar.action in ["displayAttrs", "displayCats"]:
                 qdist = 10.0 * ((self.Map.region['e'] - self.Map.region['w']) / self.Map.width)
-                redraw = False
+                coords = (east, north)
                 if digitToolbar.action == "displayAttrs":
                     # select attributes based on coordinates (all layers)
                     if digitToolbar.attributesDialog is None:
-                        digitToolbar.attributesDialog = dbm.DisplayAttributesDialog(parent=self, map=map,
-                                                                                    queryCoords=(east,
-                                                                                                 north),
-                                                                                    qdist=qdist,
-                                                                                    pos=posWindow,
-                                                                                    action="update")
+                        if digitClass.type == 'vedit':
+                            digitToolbar.attributesDialog = dbm.DisplayAttributesDialog(parent=self, map=map,
+                                                                                        query=(coords, qdist),
+                                                                                        pos=posWindow,
+                                                                                        action="update")
+                        else:
+                            if digitClass.driver.SelectLineByPoint(coords,
+                                                                   digitClass.GetSelectType()) is not None:
+                                digitToolbar.attributesDialog = dbm.DisplayAttributesDialog(parent=self, map=map,
+                                                                                            cats=digitClass.GetLineCats(),
+                                                                                            line=digitClass.driver.GetSelected()[0],
+                                                                                            action="update")
+
                     else:
                         # update currently open dialog
-                        digitToolbar.attributesDialog.UpdateDialog(queryCoords=(east, north),
-                                                                   qdist=qdist)
+                        if digitClass.type == 'vedit':
+                            digitToolbar.attributesDialog.UpdateDialog(query=(coords, qdist))
+                        else:
+                            # unselect
+                            digitClass.driver.SetSelected([])
+                            # select new feature
+                            if digitClass.driver.SelectLineByPoint(coords,
+                                                                   digitClass.GetSelectType()) is None:
+                                line = None
+                            else:
+                                line = digitClass.driver.GetSelected()[0]
+                            # upgrade dialog
+                            digitToolbar.attributesDialog.UpdateDialog(cats=digitClass.GetLineCats(),
+                                                                       line=line)
 
                     line = digitToolbar.attributesDialog.GetLine()
                     if digitToolbar.attributesDialog.mapDBInfo and line:
@@ -997,7 +1017,6 @@
                             digitToolbar.attributesDialog.Hide()
 
                 else: # displayCats
-                    coords = (east, north)
                     if digitToolbar.categoryDialog is None:
                         # open new dialog
                         if digitClass.type == 'vedit':
@@ -1021,10 +1040,19 @@
                         if digitClass.type == 'vedit':
                             digitToolbar.categoryDialog.UpdateDialog(query=(coords, qdist))
                         else:
-                            digitToolbar.categoryDialog.UpdateDialog(cats=digitClass.GetLineCats())
+                            # unselect
+                            digitClass.driver.SetSelected([])
+                            # select new feature
+                            if digitClass.driver.SelectLineByPoint(coords,
+                                                                   digitClass.GetSelectType()) is None:
+                                line = None
+                            else:
+                                line = digitClass.driver.GetSelected()[0]
+                            # upgrade dialog
+                            digitToolbar.categoryDialog.UpdateDialog(cats=digitClass.GetLineCats(),
+                                                                     line=line)
 
                     line = digitToolbar.categoryDialog.GetLine()
-                    redraw = False
                     if line:
                         # highlight feature & re-draw map
                         digitClass.driver.SetSelected([line])
@@ -1196,9 +1224,14 @@
                     else:
                         # collect ids
                         digitClass.driver.SetSelected([])
-                        # return number of selected features
+                        # return number of selected features (by box/point)
                         nselected = digitClass.driver.SelectLinesByBox(pos1, pos2,
                                                                        digitClass.GetSelectType())
+                        if nselected == 0:
+                            if digitClass.driver.SelectLineByPoint(pos1,
+                                                                   digitClass.GetSelectType()) is not None:
+                                nselected = 1
+
                         if nselected > 0:
                             self.copyCatsIds = digitClass.driver.GetSelected()
 
@@ -1433,9 +1466,10 @@
                                                          position[1] + offset))
 
                         # select attributes based on layer and category
+                        cats = {}
+                        cats[digitClass.settings["layer"]] = (digitClass.settings["category"],)
                         addRecordDlg = dbm.DisplayAttributesDialog(parent=self, map=map,
-                                                                   layer=digitClass.settings["layer"],
-                                                                   cat=digitClass.settings["category"],
+                                                                   cats=cats,
                                                                    pos=posWindow,
                                                                    action="add")
                         if addRecordDlg.mapDBInfo and \

Modified: grass/trunk/gui/wxpython/vdigit/cats.cpp
===================================================================
--- grass/trunk/gui/wxpython/vdigit/cats.cpp	2008-02-04 08:19:15 UTC (rev 29944)
+++ grass/trunk/gui/wxpython/vdigit/cats.cpp	2008-02-04 20:56:20 UTC (rev 29945)
@@ -141,23 +141,31 @@
 }
 
 /**
-   \brief Get list of layer/category(ies) for selected line.
+   \brief Get list of layer/category(ies) for selected feature.
 
+   \param line feature id (-1 for first selected feature)
+
    \return list of layer/cats
 */
-std::map<int, std::vector<int> > Digit::GetLineCats()
+std::map<int, std::vector<int> > Digit::GetLineCats(int line_id)
 {
     std::map<int, std::vector<int> > lc;
     int line, n_dblinks;
     struct line_cats *Cats;
     struct field_info *fi;
 
-    if (!display->mapInfo || display->selected->n_values < 1) {
+    if (!display->mapInfo) {
 	return lc;
     }
 
-    line = display->selected->value[0];
+    if (line_id == -1 && display->selected->n_values < 1) {
+	return lc;
+    }
 
+    if (line_id == -1) {
+	line = display->selected->value[0];
+    }
+
     if (!Vect_line_alive(display->mapInfo, line)) {
 	return lc;
     }
@@ -190,6 +198,73 @@
 }
 
 /**
+   \brief Set categories for given feature/layer
+
+   \param line feature id (-1 for first selected feature)
+   \param layer layer number
+   \param cats list of cats
+   \param add True for add, False for delete
+
+   \return new feature id (feature need to be rewritten)
+   \return -1 on error
+*/
+int Digit::SetLineCats(int line_id, int layer, std::vector<int> cats, bool add)
+{
+    int line, ret, type;
+    struct line_pnts *Points;
+    struct line_cats *Cats;
+
+    if (!display->mapInfo) {
+	return -1;
+    }
+
+    if (line_id == -1 && display->selected->n_values < 1) {
+	return -1;
+    }
+    
+    if (line_id == -1) {
+	line = display->selected->value[0];
+    }
+     
+    if (!Vect_line_alive(display->mapInfo, line)) {
+	return -1;
+    }
+
+    Points = Vect_new_line_struct();
+    Cats = Vect_new_cats_struct();
+    type = Vect_read_line(display->mapInfo, Points, Cats, line);
+    if (type < 0) {
+	Vect_destroy_line_struct(Points);
+	Vect_destroy_cats_struct(Cats);
+	return -1;
+    }
+
+    for (std::vector<int>::const_iterator c = cats.begin(), e = cats.end();
+	 c != e; ++c) {
+	if (add) {
+	    Vect_cat_set(Cats, layer, *c);
+	}
+	else {
+	    Vect_field_cat_del(Cats, layer, *c);
+	}
+	G_debug(3, "Digit.SetLineCats(): layer=%d, cat=%d, add=%d",
+		layer, *c, add);
+    }
+
+    ret = Vect_rewrite_line(display->mapInfo, line, type,
+			    Points, Cats);
+    if (line_id == -1) {
+	/* update line id since the line was rewritten */
+	display->selected->value[0] = ret;
+    }
+
+    Vect_destroy_line_struct(Points);
+    Vect_destroy_cats_struct(Cats);
+
+    return ret;
+}
+
+/**
    \brief Copy categories from one vector feature to other
 
    \param cats  list of layer/category to be copied			       

Modified: grass/trunk/gui/wxpython/vdigit/digit.h
===================================================================
--- grass/trunk/gui/wxpython/vdigit/digit.h	2008-02-04 08:19:15 UTC (rev 29944)
+++ grass/trunk/gui/wxpython/vdigit/digit.h	2008-02-04 20:56:20 UTC (rev 29945)
@@ -50,7 +50,8 @@
 
     int CopyCats(std::vector<std::vector<int> >, std::vector<int>);
     int GetCategory(int);
-    std::map<int, std::vector<int> > GetLineCats();
+    std::map<int, std::vector<int> > GetLineCats(int);
+    int SetLineCats(int, int, std::vector<int>, bool);
     std::vector<int> GetLayers();
 };
 

Modified: grass/trunk/gui/wxpython/vdigit/digit.i
===================================================================
--- grass/trunk/gui/wxpython/vdigit/digit.i	2008-02-04 08:19:15 UTC (rev 29944)
+++ grass/trunk/gui/wxpython/vdigit/digit.i	2008-02-04 20:56:20 UTC (rev 29945)
@@ -10,8 +10,12 @@
 #include "digit.h"
 %}
 
-%include "std_vector.i" 
+%include "std_vector.i"
 namespace std { 
    %template(IntVector) vector<int>;
    %template(DoubleVector) vector<double>;
 }
+%include "std_map.i"
+namespace std { 
+   %template(IntVecIntMap) map<int, vector<int> >;
+}



More information about the grass-commit mailing list