[GRASS-SVN] r38919 - grass/branches/develbranch_6/gui/wxpython/gui_modules

svn_grass at osgeo.org svn_grass at osgeo.org
Sun Aug 30 14:34:20 EDT 2009


Author: martinl
Date: 2009-08-30 14:34:20 -0400 (Sun, 30 Aug 2009)
New Revision: 38919

Added:
   grass/branches/develbranch_6/gui/wxpython/gui_modules/dbm_base.py
Modified:
   grass/branches/develbranch_6/gui/wxpython/gui_modules/__init__.py
   grass/branches/develbranch_6/gui/wxpython/gui_modules/dbm.py
   grass/branches/develbranch_6/gui/wxpython/gui_modules/dbm_dialogs.py
   grass/branches/develbranch_6/gui/wxpython/gui_modules/gselect.py
   grass/branches/develbranch_6/gui/wxpython/gui_modules/sqlbuilder.py
Log:
wxGUI: sqlbuilder major clean up (part 1)
       (merge from trunk, r38886)


Modified: grass/branches/develbranch_6/gui/wxpython/gui_modules/__init__.py
===================================================================
--- grass/branches/develbranch_6/gui/wxpython/gui_modules/__init__.py	2009-08-30 17:37:35 UTC (rev 38918)
+++ grass/branches/develbranch_6/gui/wxpython/gui_modules/__init__.py	2009-08-30 18:34:20 UTC (rev 38919)
@@ -1,6 +1,7 @@
 all = [
     "colorrules.py",
     "dbm.py",
+    "dbm_base.py",
     "dbm_dialogs.py",
     "debug.py",
     "disp_print.py",

Modified: grass/branches/develbranch_6/gui/wxpython/gui_modules/dbm.py
===================================================================
--- grass/branches/develbranch_6/gui/wxpython/gui_modules/dbm.py	2009-08-30 17:37:35 UTC (rev 38918)
+++ grass/branches/develbranch_6/gui/wxpython/gui_modules/dbm.py	2009-08-30 18:34:20 UTC (rev 38919)
@@ -17,7 +17,6 @@
  - Log
  - VirtualAttributeList
  - AttributeManager
- - VectorDBInfo
 
 (C) 2007-2009 by the GRASS Development Team
 
@@ -51,7 +50,7 @@
 import gcmd
 import utils
 import gdialogs
-import gselect
+import dbm_base
 from debug import Debug
 from dbm_dialogs import ModifyTableRecord
 from preferences import globalSettings as UserSettings
@@ -477,7 +476,7 @@
         self.qlayer = None
 
         # -> layers / tables description
-        self.mapDBInfo = VectorDBInfo(self.vectorName)
+        self.mapDBInfo = dbm_base.VectorDBInfo(self.vectorName)
 
         if len(self.mapDBInfo.layers.keys()) == 0:
             wx.MessageBox(parent=self.parent,
@@ -725,7 +724,7 @@
             dbBox = wx.StaticBox(parent=panel, id=wx.ID_ANY,
                                           label=" %s " % _("Database connection"))
             dbSizer = wx.StaticBoxSizer(dbBox, wx.VERTICAL)
-            dbSizer.Add(item=self.__createDbInfoDesc(panel, layer),
+            dbSizer.Add(item=dbm_base.createDbInfoDesc(panel, self.mapDBInfo, layer),
                         proportion=1,
                         flag=wx.EXPAND | wx.ALL,
                         border=3)
@@ -1853,34 +1852,10 @@
         
         return (cols, where)
     
-    def __createDbInfoDesc(self, panel, layer):
-        """!Create database connection information content"""
-        infoFlexSizer = wx.FlexGridSizer (cols=2, hgap=1, vgap=1)
-        infoFlexSizer.AddGrowableCol(1)
-        
-        infoFlexSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
-                                             label="Driver:"))
-        infoFlexSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
-                                             label=self.mapDBInfo.layers[layer]['driver']))
-        infoFlexSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
-                                             label="Database:"))
-        infoFlexSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
-                                             label=self.mapDBInfo.layers[layer]['database']))
-        infoFlexSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
-                                             label="Table:"))
-        infoFlexSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
-                                             label=self.mapDBInfo.layers[layer]['table']))
-        infoFlexSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
-                                             label="Key:"))
-        infoFlexSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
-                                             label=self.mapDBInfo.layers[layer]['key']))
-
-        return infoFlexSizer
-        
     def OnCloseWindow(self, event):
         """!Cancel button pressed"""
         self.Close()
-        if self.parent.GetName() == 'LayerManager':
+        if self.parent and self.parent.GetName() == 'LayerManager':
             # deregister ATM
             self.parent.dialogs['atm'].remove(self)
         
@@ -2900,129 +2875,6 @@
 
         event.Skip()
 
-class VectorDBInfo(gselect.VectorDBInfo):
-    """!Class providing information about attribute tables
-    linked to the vector map"""
-    def __init__(self, map):
-        gselect.VectorDBInfo.__init__(self, map)
-        
-    def GetColumns(self, table):
-        """!Return list of columns names (based on their index)"""
-        try:
-            names = [''] * len(self.tables[table].keys())
-        except KeyError:
-            return []
-        
-        for name, desc in self.tables[table].iteritems():
-            names[desc['index']] = name
-
-        return names
-
-    def SelectByPoint(self, queryCoords, qdist):
-        """!Get attributes by coordinates (all available layers)
-
-        Return line id or None if no line is found"""
-        line = None
-        nselected = 0
-        
-        if os.environ.has_key("LC_ALL"):
-            locale = os.environ["LC_ALL"]
-            os.environ["LC_ALL"] = "C"
-        
-        ### FIXME (implement script-style output)        
-        ret = gcmd.RunCommand('v.what',
-                              quiet = True,
-                              read = True,
-                              flags = 'a',
-                              map = self.map,
-                              east_north = '%f,%f' % \
-                                  (float(queryCoords[0]), float(queryCoords[1])),
-                              distance = float(qdist))
-        
-        if os.environ.has_key("LC_ALL"):
-            os.environ["LC_ALL"] = locale
-        
-        data = {}
-        if ret:
-            readAttrb = False
-            for item in ret.splitlines():
-                try:
-                    key, value = item.split(':', 1)
-                except ValueError:
-                    continue
-                
-                if key == 'Layer' and readAttrb:
-                    readAttrb = False
-                
-                if readAttrb:
-                    name, value = item.split(':', 1)
-                    name = name.strip()
-                    value = value.strip()
-                    # append value to the column
-                    if len(value) < 1:
-                        value = None
-                    else:
-                        if self.tables[table][name]['ctype'] != type(''):
-                            value = self.tables[table][name]['ctype'] (value.strip())
-                        else:
-                            value = unicodeValue(value.strip())
-                    self.tables[table][name]['values'].append(value)
-                else:
-                    if not data.has_key(key):
-                        data[key] = []
-                    data[key].append(value.strip())
-                    
-                    if key == 'Table':
-                        table = value.strip()
-                        
-                    if key == 'Key column': # skip attributes
-                        readAttrb = True
-
-        return data
-    
-    def SelectFromTable(self, layer, cols='*', where=None):
-        """!Select records from the table
-
-        Return number of selected records, -1 on error
-        """
-        if layer <= 0:
-            return -1
-
-        nselected = 0
-
-        table = self.layers[layer]["table"] # get table desc
-        # select values (only one record)
-        if where is None or where is '':
-            sql="SELECT %s FROM %s" % (cols, table)
-        else:
-            sql="SELECT %s FROM %s WHERE %s" % (cols, table, where)
-
-        ret = gcmd.RunCommand('db.select',
-                              parent = self,
-                              read = True,
-                              quiet = True,
-                              flags = 'v',
-                              sql= sql,
-                              database = self.layers[layer]["database"],
-                              driver = self.layers[layer]["driver"])
-        
-        # self.tables[table][key][1] = str(cat)
-        if ret:
-            for line in ret.splitlines():
-                name, value = line.split('|')
-                # casting ...
-                if value:
-                    if self.tables[table][name]['ctype'] != type(''):
-                        value = self.tables[table][name]['ctype'] (value)
-                    else:
-                        value = unicodeValue(value)
-                else:
-                    value = None
-                self.tables[table][name]['values'].append(value)
-                nselected = 1
-
-        return nselected
-
 def main(argv=None):
     if argv is None:
         argv = sys.argv

Copied: grass/branches/develbranch_6/gui/wxpython/gui_modules/dbm_base.py (from rev 38886, grass/trunk/gui/wxpython/gui_modules/dbm_base.py)
===================================================================
--- grass/branches/develbranch_6/gui/wxpython/gui_modules/dbm_base.py	                        (rev 0)
+++ grass/branches/develbranch_6/gui/wxpython/gui_modules/dbm_base.py	2009-08-30 18:34:20 UTC (rev 38919)
@@ -0,0 +1,170 @@
+"""
+ at package dbm_base.py
+
+ at brief Support classes for dbm.py
+
+List of classes:
+ - VectorDBInfo
+
+(C) 2007-2009 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
+for details.
+
+ at author Martin Landa <landa.martin gmail.com>
+"""
+
+import os
+
+import wx
+
+import gselect
+import gcmd
+
+def createDbInfoDesc(panel, mapDBInfo, layer):
+    """!Create database connection information content"""
+    infoFlexSizer = wx.FlexGridSizer (cols=2, hgap=1, vgap=1)
+    infoFlexSizer.AddGrowableCol(1)
+    
+    infoFlexSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
+                                         label="Driver:"))
+    infoFlexSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
+                                         label=mapDBInfo.layers[layer]['driver']))
+    infoFlexSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
+                                         label="Database:"))
+    infoFlexSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
+                                         label=mapDBInfo.layers[layer]['database']))
+    infoFlexSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
+                                         label="Table:"))
+    infoFlexSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
+                                         label=mapDBInfo.layers[layer]['table']))
+    infoFlexSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
+                                         label="Key:"))
+    infoFlexSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
+                                         label=mapDBInfo.layers[layer]['key']))
+    
+    return infoFlexSizer
+        
+class VectorDBInfo(gselect.VectorDBInfo):
+    """!Class providing information about attribute tables
+    linked to the vector map"""
+    def __init__(self, map):
+        gselect.VectorDBInfo.__init__(self, map)
+        
+    def GetColumns(self, table):
+        """!Return list of columns names (based on their index)"""
+        try:
+            names = [''] * len(self.tables[table].keys())
+        except KeyError:
+            return []
+        
+        for name, desc in self.tables[table].iteritems():
+            names[desc['index']] = name
+        
+        return names
+
+    def SelectByPoint(self, queryCoords, qdist):
+        """!Get attributes by coordinates (all available layers)
+
+        Return line id or None if no line is found"""
+        line = None
+        nselected = 0
+        
+        if os.environ.has_key("LC_ALL"):
+            locale = os.environ["LC_ALL"]
+            os.environ["LC_ALL"] = "C"
+        
+        ### FIXME (implement script-style output)        
+        ret = gcmd.RunCommand('v.what',
+                              quiet = True,
+                              read = True,
+                              flags = 'a',
+                              map = self.map,
+                              east_north = '%f,%f' % \
+                                  (float(queryCoords[0]), float(queryCoords[1])),
+                              distance = float(qdist))
+        
+        if os.environ.has_key("LC_ALL"):
+            os.environ["LC_ALL"] = locale
+        
+        data = {}
+        if ret:
+            readAttrb = False
+            for item in ret.splitlines():
+                try:
+                    key, value = item.split(':', 1)
+                except ValueError:
+                    continue
+                
+                if key == 'Layer' and readAttrb:
+                    readAttrb = False
+                
+                if readAttrb:
+                    name, value = item.split(':', 1)
+                    name = name.strip()
+                    value = value.strip()
+                    # append value to the column
+                    if len(value) < 1:
+                        value = None
+                    else:
+                        if self.tables[table][name]['ctype'] != type(''):
+                            value = self.tables[table][name]['ctype'] (value.strip())
+                        else:
+                            value = unicodeValue(value.strip())
+                    self.tables[table][name]['values'].append(value)
+                else:
+                    if not data.has_key(key):
+                        data[key] = []
+                    data[key].append(value.strip())
+                    
+                    if key == 'Table':
+                        table = value.strip()
+                        
+                    if key == 'Key column': # skip attributes
+                        readAttrb = True
+
+        return data
+    
+    def SelectFromTable(self, layer, cols='*', where=None):
+        """!Select records from the table
+
+        Return number of selected records, -1 on error
+        """
+        if layer <= 0:
+            return -1
+
+        nselected = 0
+
+        table = self.layers[layer]["table"] # get table desc
+        # select values (only one record)
+        if where is None or where is '':
+            sql="SELECT %s FROM %s" % (cols, table)
+        else:
+            sql="SELECT %s FROM %s WHERE %s" % (cols, table, where)
+
+        ret = gcmd.RunCommand('db.select',
+                              parent = self,
+                              read = True,
+                              quiet = True,
+                              flags = 'v',
+                              sql= sql,
+                              database = self.layers[layer]["database"],
+                              driver = self.layers[layer]["driver"])
+        
+        # self.tables[table][key][1] = str(cat)
+        if ret:
+            for line in ret.splitlines():
+                name, value = line.split('|')
+                # casting ...
+                if value:
+                    if self.tables[table][name]['ctype'] != type(''):
+                        value = self.tables[table][name]['ctype'] (value)
+                    else:
+                        value = unicodeValue(value)
+                else:
+                    value = None
+                self.tables[table][name]['values'].append(value)
+                nselected = 1
+
+        return nselected

Modified: grass/branches/develbranch_6/gui/wxpython/gui_modules/dbm_dialogs.py
===================================================================
--- grass/branches/develbranch_6/gui/wxpython/gui_modules/dbm_dialogs.py	2009-08-30 17:37:35 UTC (rev 38918)
+++ grass/branches/develbranch_6/gui/wxpython/gui_modules/dbm_dialogs.py	2009-08-30 18:34:20 UTC (rev 38919)
@@ -25,10 +25,10 @@
 import wx
 import wx.lib.scrolledpanel as scrolled
 
-import dbm
 import gcmd
 from debug import Debug
 from preferences import globalSettings as UserSettings
+from dbm_base    import VectorDBInfo
 
 class DisplayAttributesDialog(wx.Dialog):
     """
@@ -62,7 +62,7 @@
         self.fid = -1 # feature id
         
         # get layer/table/column information
-        self.mapDBInfo = dbm.VectorDBInfo(self.map)
+        self.mapDBInfo = VectorDBInfo(self.map)
         
         layers = self.mapDBInfo.layers.keys() # get available layers
 

Modified: grass/branches/develbranch_6/gui/wxpython/gui_modules/gselect.py
===================================================================
--- grass/branches/develbranch_6/gui/wxpython/gui_modules/gselect.py	2009-08-30 17:37:35 UTC (rev 38918)
+++ grass/branches/develbranch_6/gui/wxpython/gui_modules/gselect.py	2009-08-30 18:34:20 UTC (rev 38919)
@@ -480,6 +480,15 @@
         """
         return self.layers[layer]['table']
     
+    def GetDbSettings(self, layer):
+        """!Get database settins
+
+        @param layer layer number
+        
+        @return (driver, database)
+        """
+        return self.layers[layer]['driver'], self.layers[layer]['database']
+    
     def GetTableDesc(self, table):
         """!Get table columns
 

Modified: grass/branches/develbranch_6/gui/wxpython/gui_modules/sqlbuilder.py
===================================================================
--- grass/branches/develbranch_6/gui/wxpython/gui_modules/sqlbuilder.py	2009-08-30 17:37:35 UTC (rev 38918)
+++ grass/branches/develbranch_6/gui/wxpython/gui_modules/sqlbuilder.py	2009-08-30 18:34:20 UTC (rev 38919)
@@ -1,384 +1,421 @@
-"""
-MODULE:    sqlbuilder.py
+"""!
+ at package sqlbuilder.py
 
-CLASSES:
-    * SQLFrame
+ at brief GRASS SQL Builder
 
-PURPOSE:   GRASS SQL Builder
+Classes:
+ - SQLFrame
 
-           Usage:
-           sqlbuilder.py table_name
+ at todo Various updates are required...
 
-AUTHOR(S): GRASS Development Team
-           Original author: Jachym Cepicky <jachym.cepicky gmail.com>
-           Various updates: Martin Landa <landa.martin gmail.com>,
-                            Hamish Bowman <hamish_b yahoo com>
+Usage:
+ at code
+python sqlbuilder.py vector_map
+ at endcode
 
-COPYRIGHT: (C) 2007-2009 by the GRASS Development Team
+(C) 2007-2009 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
-           for details.
+This program is free software under the GNU General Public
+License (>=v2). Read the file COPYING that comes with GRASS
+for details.
+
+ at author Jachym Cepicky <jachym.cepicky gmail.com> (original author)
+ at author Martin Landa <landa.martin gmail.com>,
+ at author Hamish Bowman <hamish_b yahoo com>
 """
 
-import wx
-import os,sys
+import os
+import sys
 import time
 
-from grass.script import core as grass
+### i18N
+import gettext
+gettext.install('grasswxpy', os.path.join(os.getenv("GISBASE"), 'locale'), unicode=True)
 
-import gcmd
 import globalvar
+if not os.getenv("GRASS_WXBUNDLED"):
+    globalvar.CheckForWx()
 
-imagePath = os.path.join(globalvar.ETCWXDIR)
-sys.path.append(imagePath)
-import images
-imagepath = images.__path__[0]
-sys.path.append(imagepath)
+import wx
 
+import grass.script as grass
+grass.set_fatal_exit(False)
+
+import gcmd
+import dbm_base
+
 class SQLFrame(wx.Frame):
     """!SQL Frame class"""
-    def __init__(self, parent, id, title, vectmap, qtype="select"):
-
+    def __init__(self, parent, title, vectmap, id = wx.ID_ANY,
+                 layer = 1, qtype = "select"):
+        
         wx.Frame.__init__(self, parent, id, title)
+        
+        self.SetIcon(wx.Icon(os.path.join(globalvar.ETCICONDIR, 'grass_sql.ico'),
+                             wx.BITMAP_TYPE_ICO))
+        
+        self.parent = parent
 
-        self.SetTitle(_("GRASS SQL Builder: %s") % (qtype.upper()))
-        self.SetIcon(wx.Icon(os.path.join(globalvar.ETCICONDIR, 'grass_sql.ico'), wx.BITMAP_TYPE_ICO))
-
         #
         # variables
         #
-        self.vectmap = vectmap
+        self.vectmap = vectmap # fullname
         if not "@" in self.vectmap:
             self.vectmap = self.vectmap + "@" + grass.gisenv()['MAPSET']
-
         self.mapname, self.mapset = self.vectmap.split("@")
-
-        #FIXME: pass layer number to v.db.connect ???
-        ret = gcmd.RunCommand('v.db.connect',
-                      quiet = True,
-                      read = True,
-                      flags = 'g',
-                      fs = '|',
-                      map = self.vectmap)
-        for line in ret.splitlines():
-            self.layer,self.tablename, self.column, self.database, self.driver =\
-                line.strip().split("|")
-
+        
+        # db info
+        self.layer = layer
+        self.dbInfo = dbm_base.VectorDBInfo(self.vectmap)
+        self.tablename = self.dbInfo.GetTable(self.layer)
+        self.driver, self.database = self.dbInfo.GetDbSettings(self.layer)
+        
         self.qtype = qtype      # type of the uqery: SELECT, UPDATE, DELETE, ...
-        self.column_names = []  # array with column names
-        self.columns = {}       # array with colum properties
-        self.colvalues = []     # array with uniqe values in selected column
-        self.heading = ""
-        self.parent = parent
+        self.colvalues = []     # array with unique values in selected column
 
-        if self.qtype.lower()=="select":
-            self.heading = "SELECT * FROM %s WHERE" % self.tablename
+        # set dialog title
+        self.SetTitle(_("GRASS SQL Builder (%s): vector map <%s>") % \
+                          (qtype.upper(), self.vectmap))
+        
+        self.panel = wx.Panel(parent = self, id = wx.ID_ANY)
 
-
-        # Init
-        self.GetColumns()
-
-
         #
-        # Buttons
+        # buttons
         #
-        self.btn_clear = wx.Button(self, -1, "Clear")
-        self.btn_verify = wx.Button(self, -1, "Verify")
-        #self.btn_help = wx.Button(self, -1, "Help")
-        # self.btn_load = wx.Button(self, -1, "Load")
-        # self.btn_save = wx.Button(self, -1, "Save")
-        self.btn_apply = wx.Button(self, -1, "Apply")
-        self.btn_close = wx.Button(self, -1, "Close")
-        self.btn_uniqe = wx.Button(self, -1, "Get all values")
-        self.btn_uniqesample = wx.Button(self, -1, "Get sample")
-
-        self.btn_is = wx.Button(self, -1, "=")
-        self.btn_isnot = wx.Button(self, -1, "!=")
-        self.btn_like = wx.Button(self, -1, "LIKE")
-        self.btn_gt = wx.Button(self, -1, ">")
-        self.btn_gtis = wx.Button(self, -1, ">=")
-        self.btn_lt = wx.Button(self, -1, "<")
-        self.btn_ltis = wx.Button(self, -1, "<=")
-        self.btn_or = wx.Button(self, -1, "OR")
-        self.btn_not = wx.Button(self, -1, "NOT")
-        self.btn_and = wx.Button(self, -1, "AND")
-        self.btn_brackets = wx.Button(self, -1, "()")
-        self.btn_prc = wx.Button(self, -1, "%")
-
+        self.btn_clear  = wx.Button(parent = self.panel, id = wx.ID_CLEAR)
+        self.btn_verify = wx.Button(parent = self.panel, id = wx.ID_ANY,
+                                    label = _("Verify"))
+        # self.btn_help = wx.Button(self.panel, -1, "Help")
+        # self.btn_load = wx.Button(self.panel, -1, "Load")
+        # self.btn_save = wx.Button(self.panel, -1, "Save")
+        self.btn_apply  = wx.Button(parent = self.panel, id = wx.ID_APPLY)
+        self.btn_close  = wx.Button(parent = self.panel, id = wx.ID_CLOSE)
+        self.btn_unique = wx.Button(parent = self.panel, id = wx.ID_ANY,
+                                    label = _("Get all values"))
+        self.btn_unique.Enable(False)
+        self.btn_uniquesample = wx.Button(parent = self.panel, id = wx.ID_ANY,
+                                          label = _("Get sample"))
+        self.btn_uniquesample.Enable(False)
+        self.btn_is    = wx.Button(parent = self.panel, id = wx.ID_ANY, label = "=")
+        self.btn_isnot = wx.Button(parent = self.panel, id = wx.ID_ANY, label = "!=")
+        self.btn_like  = wx.Button(parent = self.panel, id = wx.ID_ANY, label = "LIKE")
+        self.btn_gt    = wx.Button(parent = self.panel, id = wx.ID_ANY, label = ">")
+        self.btn_gtis  = wx.Button(parent = self.panel, id = wx.ID_ANY, label = ">=")
+        self.btn_lt    = wx.Button(parent = self.panel, id = wx.ID_ANY, label = "<")
+        self.btn_ltis  = wx.Button(parent = self.panel, id = wx.ID_ANY, label = "<=")
+        self.btn_or    = wx.Button(parent = self.panel, id = wx.ID_ANY, label = "OR")
+        self.btn_not   = wx.Button(parent = self.panel, id = wx.ID_ANY, label = "NOT")
+        self.btn_and   = wx.Button(parent = self.panel, id = wx.ID_ANY, label = "AND")
+        self.btn_brackets = wx.Button(parent = self.panel, id = wx.ID_ANY, label = "()")
+        self.btn_prc   = wx.Button(parent = self.panel, id = wx.ID_ANY, label = "%")
+        
         #
         # Text labels
         #
-        #self.label_headding = wx.StaticText(self, -1, '')
-
+        # self.label_headding = wx.StaticText(self.panel, -1, '')
+        
         #
         # Textareas
         #
-        self.text_sql = wx.TextCtrl(self, -1, '', size=(-1,75),style=wx.TE_MULTILINE)
-
+        self.text_sql = wx.TextCtrl(parent = self.panel, id = wx.ID_ANY,
+                                    value = '', size = (-1, 75),
+                                    style=wx.TE_MULTILINE)
+        if self.qtype.lower() == "select":
+            self.text_sql.SetValue("SELECT * FROM %s" % self.tablename)
+        
         #
         # List Boxes
         #
-        self.list_columns = wx.ListBox(self, -1, wx.DefaultPosition, (-1, -1), self.columns.keys(), wx.LB_MULTIPLE|wx.LB_SORT)
-        self.list_values = wx.ListBox(self, -1, wx.DefaultPosition, (-1, -1), self.colvalues, wx.LB_MULTIPLE|wx.LB_SORT)
-
+        self.list_columns = wx.ListBox(parent = self.panel, id = wx.ID_ANY,
+                                       choices = self.dbInfo.GetColumns(self.tablename),
+                                       style = wx.LB_MULTIPLE)
+        self.list_values = wx.ListBox(parent = self.panel, id = wx.ID_ANY,
+                                      choices = self.colvalues,
+                                      style = wx.LB_MULTIPLE)
+        
         #
         # Bindings
         #
-        self.btn_uniqe.Bind(wx.EVT_BUTTON, self.GetUniqueValues)
-        self.btn_uniqesample.Bind(wx.EVT_BUTTON, self.GetSampleValues)
-        self.btn_is.Bind(wx.EVT_BUTTON, self.AddMark)
-        self.btn_isnot.Bind(wx.EVT_BUTTON, self.AddMark)
-        self.btn_like.Bind(wx.EVT_BUTTON, self.AddMark)
-        self.btn_gt.Bind(wx.EVT_BUTTON, self.AddMark)
-        self.btn_gtis.Bind(wx.EVT_BUTTON, self.AddMark)
-        self.btn_or.Bind(wx.EVT_BUTTON, self.AddMark)
-        self.btn_lt.Bind(wx.EVT_BUTTON, self.AddMark)
-        self.btn_ltis.Bind(wx.EVT_BUTTON, self.AddMark)
-        self.btn_not.Bind(wx.EVT_BUTTON, self.AddMark)
-        self.btn_brackets.Bind(wx.EVT_BUTTON, self.AddMark)
-        self.btn_prc.Bind(wx.EVT_BUTTON, self.AddMark)
-        self.btn_and.Bind(wx.EVT_BUTTON, self.AddMark)
-        self.btn_close.Bind(wx.EVT_BUTTON, self.OnClose)
-        self.btn_clear.Bind(wx.EVT_BUTTON, self.OnClear)
-        self.btn_verify.Bind(wx.EVT_BUTTON, self.OnVerify)
-        self.btn_apply.Bind(wx.EVT_BUTTON, self.OnApply)
+        self.btn_unique.Bind(wx.EVT_BUTTON,       self.GetUniqueValues)
+        self.btn_uniquesample.Bind(wx.EVT_BUTTON, self.GetSampleValues)
+        self.btn_is.Bind(wx.EVT_BUTTON,          self.AddMark)
+        self.btn_isnot.Bind(wx.EVT_BUTTON,       self.AddMark)
+        self.btn_like.Bind(wx.EVT_BUTTON,        self.AddMark)
+        self.btn_gt.Bind(wx.EVT_BUTTON,          self.AddMark)
+        self.btn_gtis.Bind(wx.EVT_BUTTON,        self.AddMark)
+        self.btn_or.Bind(wx.EVT_BUTTON,          self.AddMark)
+        self.btn_lt.Bind(wx.EVT_BUTTON,          self.AddMark)
+        self.btn_ltis.Bind(wx.EVT_BUTTON,        self.AddMark)
+        self.btn_not.Bind(wx.EVT_BUTTON,         self.AddMark)
+        self.btn_brackets.Bind(wx.EVT_BUTTON,    self.AddMark)
+        self.btn_prc.Bind(wx.EVT_BUTTON,         self.AddMark)
+        self.btn_and.Bind(wx.EVT_BUTTON,         self.AddMark)
+        self.btn_close.Bind(wx.EVT_BUTTON,       self.OnClose)
+        self.btn_clear.Bind(wx.EVT_BUTTON,       self.OnClear)
+        self.btn_verify.Bind(wx.EVT_BUTTON,      self.OnVerify)
+        self.btn_apply.Bind(wx.EVT_BUTTON,       self.OnApply)
 
-        self.list_columns.Bind(wx.EVT_LISTBOX, self.AddColumnName)
-        self.list_values.Bind(wx.EVT_LISTBOX, self.AddValue)
-
+        self.list_columns.Bind(wx.EVT_LISTBOX,   self.AddColumnName)
+        self.list_values.Bind(wx.EVT_LISTBOX,    self.AddValue)
+        
+        self.text_sql.Bind(wx.EVT_TEXT,          self.OnText)
+        
         self.__doLayout()
 
     def __doLayout(self):
-        databasebox = wx.StaticBox(self, -1, "Database connection")
-        databaseboxsizer = wx.StaticBoxSizer(databasebox,wx.VERTICAL)
-        dbstr = "Database: %s\n" % (self.database)
-        dbstr += "Driver: %s\n" % (self.driver)
-        dbstr += "Table: %s" % (self.tablename)
-        databaseboxsizer.Add(wx.StaticText(self,-1,dbstr), flag=wx.EXPAND)
+        """!Do dialog layout"""
+      
+        # dbInfo
+        databasebox = wx.StaticBox(parent = self.panel, id = wx.ID_ANY,
+                                   label = " %s " % _("Database connection"))
+        databaseboxsizer = wx.StaticBoxSizer(databasebox, wx.VERTICAL)
+        databaseboxsizer.Add(item=dbm_base.createDbInfoDesc(self.panel, self.dbInfo, layer = self.layer),
+                             proportion=1,
+                             flag=wx.EXPAND | wx.ALL,
+                             border=3)
 
-        sqlbox = wx.StaticBox(self, -1, "%s" % self.heading)
-        sqlboxsizer = wx.StaticBoxSizer(sqlbox,wx.VERTICAL)
-        sqlboxsizer.Add(self.text_sql, flag=wx.EXPAND)
-
-
+        # sql box
+        sqlbox = wx.StaticBox(parent = self.panel, id = wx.ID_ANY,
+                              label = " %s " % _("Query"))
+        sqlboxsizer = wx.StaticBoxSizer(sqlbox, wx.VERTICAL)
+        sqlboxsizer.Add(item = self.text_sql, flag = wx.EXPAND)
+        
         pagesizer = wx.BoxSizer(wx.VERTICAL)
-
-        buttonsizer1 = wx.GridBagSizer(2,2)
-        buttonsizer1.Add(self.btn_clear, (0,0))
-        buttonsizer1.Add(self.btn_verify, (0,1))
-        #buttonsizer1.Add(self.btn_help,  (0,2))
-        #buttonsizer1.Add(self.btn_load,  (0,2))
+        
+        # buttons
+        buttonsizer = wx.FlexGridSizer(cols = 4, hgap = 5, vgap = 5)
+        buttonsizer.Add(item = self.btn_clear)
+        buttonsizer.Add(item = self.btn_verify)
+        # buttonsizer1.Add(self.btn_help,  (0,2))
+        # buttonsizer1.Add(self.btn_load,  (0,2))
         # buttonsizer1.Add(self.btn_save,  (0,3))
-        buttonsizer1.Add(self.btn_apply, (0,2))
+        buttonsizer.Add(item = self.btn_apply)
+        buttonsizer.Add(item = self.btn_close)
+        
+        buttonsizer2 = wx.GridBagSizer(5, 5)
+        buttonsizer2.Add(item = self.btn_is, pos = (0,0))
+        buttonsizer2.Add(item = self.btn_isnot, pos = (1,0))
+        buttonsizer2.Add(item = self.btn_like, pos = (2, 0))
 
-        buttonsizer2 = wx.GridBagSizer(2, 2)
-        buttonsizer2.Add(self.btn_is, (0,0))
-        buttonsizer2.Add(self.btn_isnot, (1,0))
-        buttonsizer2.Add(self.btn_like, (2, 0))
+        buttonsizer2.Add(item = self.btn_gt, pos = (0, 1))
+        buttonsizer2.Add(item = self.btn_gtis, pos = (1, 1))
+        buttonsizer2.Add(item = self.btn_or, pos = (2, 1))
 
-        buttonsizer2.Add(self.btn_gt, (0, 1))
-        buttonsizer2.Add(self.btn_gtis, (1, 1))
-        buttonsizer2.Add(self.btn_or, (2, 1))
+        buttonsizer2.Add(item = self.btn_lt, pos = (0, 2))
+        buttonsizer2.Add(item = self.btn_ltis, pos = (1, 2))
+        buttonsizer2.Add(item = self.btn_not, pos = (2, 2))
 
-        buttonsizer2.Add(self.btn_lt, (0, 2))
-        buttonsizer2.Add(self.btn_ltis, (1, 2))
-        buttonsizer2.Add(self.btn_not, (2, 2))
+        buttonsizer2.Add(item = self.btn_brackets, pos = (0, 3))
+        buttonsizer2.Add(item = self.btn_prc, pos = (1, 3))
+        buttonsizer2.Add(item = self.btn_and, pos = (2, 3))
 
-        buttonsizer2.Add(self.btn_brackets, (0, 3))
-        buttonsizer2.Add(self.btn_prc, (1, 3))
-        buttonsizer2.Add(self.btn_and, (2, 3))
-
-        buttonsizer3 = wx.GridSizer(4, 3, 3, 3)
-        buttonsizer3.Add(self.btn_apply,0,wx.RIGHT,5)
-        buttonsizer3.Add(self.btn_close,0,wx.RIGHT,5)
-
         buttonsizer4 = wx.BoxSizer(wx.HORIZONTAL)
-        buttonsizer4.Add(self.btn_uniqesample,0,flag=wx.ALIGN_CENTER_HORIZONTAL,border=5)
-        buttonsizer4.Add(self.btn_uniqe,0,flag=wx.ALIGN_CENTER_HORIZONTAL,border=5)
-
-        hsizer1 = wx.BoxSizer(wx.HORIZONTAL)
-        #hsizer2 = wx.BoxSizer(wx.HORIZONTAL)
-
-        columnsbox = wx.StaticBox(self,-1,"Columns: ")
-        valuesbox = wx.StaticBox(self,-1,"Values: ")
-        #hsizer1.Add(wx.StaticText(self,-1, "Unique values: "), border=0, proportion=1)
-        columnsizer = wx.StaticBoxSizer(columnsbox,wx.VERTICAL)
-        valuesizer = wx.StaticBoxSizer(valuesbox,wx.VERTICAL)
-        columnsizer.Add(self.list_columns,  flag=wx.EXPAND,)
-        valuesizer.Add(self.list_values,  flag=wx.EXPAND)
-        self.list_columns.SetMinSize((-1,130))
-        self.list_values.SetMinSize((-1,100))
-        valuesizer.Add(buttonsizer4)
-        hsizer1.Add(columnsizer,border=0, proportion=1)
-        hsizer1.Add(valuesizer,border=0, proportion=1)
-
-        pagesizer.Add(databaseboxsizer,flag=wx.EXPAND,border=5)
-        pagesizer.Add(hsizer1, 1,flag=wx.EXPAND,border=5)
-        #pagesizer.Add(self.btn_uniqe,0,wx.ALIGN_LEFT|wx.TOP,border=5)
-        #pagesizer.Add(self.btn_uniqesample,0,wx.ALIGN_LEFT|wx.TOP,border=5)
-        pagesizer.Add(buttonsizer2, 0, wx.ALIGN_CENTER_HORIZONTAL|wx.TOP, border=5)
-        pagesizer.Add(sqlboxsizer, flag=wx.EXPAND,border=5)
-        pagesizer.Add(buttonsizer1, 0, wx.ALIGN_CENTER_HORIZONTAL|wx.TOP, border=5)
-        pagesizer.Add(buttonsizer3, proportion=0, flag=wx.TOP, border=5)
-        self.SetAutoLayout(True)
-        self.SetSizer(pagesizer)
-        pagesizer.Fit(self)
-        #pagesizer.SetSizeHints(self)
+        buttonsizer4.Add(item = self.btn_uniquesample, proportion = 0,
+                         flag = wx.ALIGN_CENTER_HORIZONTAL | wx.RIGHT, border = 5)
+        buttonsizer4.Add(item = self.btn_unique, proportion = 0,
+                         flag = wx.ALIGN_CENTER_HORIZONTAL)
+        
+        hsizer = wx.BoxSizer(wx.HORIZONTAL)
+        
+        columnsbox = wx.StaticBox(parent = self.panel, id = wx.ID_ANY,
+                                  label = " %s " % _("Columns"))
+        valuesbox = wx.StaticBox(parent = self.panel, id = wx.ID_ANY,
+                                 label = " %s " % _("Values"))
+        # hsizer1.Add(wx.StaticText(self.panel,-1, "Unique values: "), border=0, proportion=1)
+        columnsizer = wx.StaticBoxSizer(columnsbox, wx.VERTICAL)
+        valuesizer = wx.StaticBoxSizer(valuesbox, wx.VERTICAL)
+        columnsizer.Add(item = self.list_columns, proportion = 1,
+                        flag = wx.EXPAND)
+        valuesizer.Add(item = self.list_values, proportion = 1,
+                       flag = wx.EXPAND)
+        # self.list_columns.SetMinSize((-1,130))
+        # self.list_values.SetMinSize((-1,100))
+        valuesizer.Add(item = buttonsizer4, proportion = 0,
+                       flag = wx.TOP, border = 5)
+        hsizer.Add(item = columnsizer, proportion = 1,
+                   flag = wx.EXPAND)
+        hsizer.Add(item = valuesizer, proportion = 1,
+                   flag = wx.EXPAND)
+        
+        pagesizer.Add(item = databaseboxsizer,
+                      flag = wx.ALL | wx.EXPAND, border = 5)
+        pagesizer.Add(item = hsizer, proportion = 1,
+                      flag = wx.LEFT | wx.RIGHT | wx.BOTTOM | wx.EXPAND, border = 5)
+        # pagesizer.Add(self.btn_uniqe,0,wx.ALIGN_LEFT|wx.TOP,border=5)
+        # pagesizer.Add(self.btn_uniqesample,0,wx.ALIGN_LEFT|wx.TOP,border=5)
+        pagesizer.Add(item = buttonsizer2, proportion = 0,
+                      flag = wx.ALIGN_CENTER_HORIZONTAL | wx.BOTTOM, border = 5)
+        pagesizer.Add(item = sqlboxsizer, proportion = 0,
+                      flag = wx.EXPAND | wx.LEFT | wx.RIGHT | wx.BOTTOM, border = 5)
+        pagesizer.Add(item = buttonsizer, proportion = 0,
+                      flag = wx.ALIGN_RIGHT | wx.ALL, border = 5)
+        
+        self.panel.SetAutoLayout(True)
+        self.panel.SetSizer(pagesizer)
+        pagesizer.Fit(self.panel)
+        
         self.Layout()
-        self.Show(True)
-
-    def GetColumns(self):
-        """!Get columns"""
-        ret = gcmd.RunCommand('db.describe',
-                              quiet = True,
-                              read = True,
-                              flags = 'c',
-                              table = self.tablename,
-                              database = self.database,
-                              driver = self.driver)
+        self.SetMinSize((660, 480))
         
-        for line in ret.splitlines():
-            # skip ncols and nrows lines
-            linetype = line.strip().split(":")[0]
-            if linetype == "ncols" or linetype == "nrows":
-                continue
-
-            num, name, ctype, length = line.strip().split(":")
-            name.strip()
-            #self.columns_names.append(name)
-            self.columns[name] = {'type' : ctype}
-
-
-    def GetUniqueValues(self,event,justsample=False):
+    def GetUniqueValues(self, event, justsample = False):
+        """!Get unique values"""
         vals = []
         try:
             idx = self.list_columns.GetSelections()[0]
+            column = self.list_columns.GetString(idx)
         except:
+            self.list_values.Clear()
             return
+        
         self.list_values.Clear()
-        column = self.list_columns.GetString(idx)
+        
         i = 0
         querystring = "SELECT %s FROM %s" % (column, self.tablename)
-
-        ret = gcmd.RunCommand('db.select',
-                              read = True,
-                              quiet = True,
-                              flags = 'c',
-                              database = self.database,
-                              driver = self.driver,
-                              sql = querystring)
-
-        for line in ret.splitlines():
+        
+        data = grass.db_select(table = self.tablename,
+                               sql = querystring,
+                               database = self.database,
+                               driver = self.driver)
+        
+        for line in data:
             if justsample and i < 256 or \
                not justsample:
-                self.list_values.Insert(line.strip(),0)
+                self.list_values.Append(line.strip())
             else:
                 break
             i += 1
+    
+    def GetSampleValues(self, event):
+        """!Get sample values"""
+        self.GetUniqueValues(None, True)
 
-    def GetSampleValues(self,event):
-        self.GetUniqueValues(None,True)
-
-    def AddColumnName(self,event):
-        idx = self.list_columns.GetSelections()[0]
-        column = self.list_columns.GetString(idx)
-        self.__addSomething(column)
-
+    def AddColumnName(self, event):
+        """!Add column name to the query"""
+        idx = self.list_columns.GetSelections()
+        for i in idx:
+            column = self.list_columns.GetString(i)
+            self.__Add(element = 'column', value = column)
+        
+        if not self.btn_uniquesample.IsEnabled():
+            self.btn_uniquesample.Enable()
+            self.btn_unique.Enable()
+        
     def AddValue(self,event):
+        """!Add value"""
         idx = self.list_values.GetSelections()[0]
         value = self.list_values.GetString(idx)
         idx = self.list_columns.GetSelections()[0]
         column = self.list_columns.GetString(idx)
-
+        
         if self.columns[column]['type'].lower().find("chara") > -1:
             value = "'%s'" % value
-        self.__addSomething(value)
+        self.__Add(value)
 
     def AddMark(self,event):
-        if event.GetId() == self.btn_is.GetId(): mark = "="
-        elif event.GetId() == self.btn_isnot.GetId(): mark = "!="
-        elif event.GetId() == self.btn_like.GetId(): mark = "LIKE"
-        elif event.GetId() == self.btn_gt.GetId(): mark = ">"
-        elif event.GetId() == self.btn_gtis.GetId(): mark = ">="
-        elif event.GetId() == self.btn_lt.GetId(): mark = "<"
-        elif event.GetId() == self.btn_ltis.GetId(): mark =  "<="
-        elif event.GetId() == self.btn_or.GetId(): mark =  "OR"
-        elif event.GetId() == self.btn_not.GetId(): mark = "NOT"
-        elif event.GetId() == self.btn_and.GetId(): mark = "AND"
-        elif event.GetId() == self.btn_brackets.GetId(): mark = "()"
-        elif event.GetId() == self.btn_prc.GetId(): mark = "%"
-        self.__addSomething(mark)
+        """!Add mark"""
+        if event.GetId() == self.btn_is.GetId():
+            mark = "="
+        elif event.GetId() == self.btn_isnot.GetId():
+            mark = "!="
+        elif event.GetId() == self.btn_like.GetId():
+            mark = "LIKE"
+        elif event.GetId() == self.btn_gt.GetId():
+            mark = ">"
+        elif event.GetId() == self.btn_gtis.GetId():
+            mark = ">="
+        elif event.GetId() == self.btn_lt.GetId():
+            mark = "<"
+        elif event.GetId() == self.btn_ltis.GetId():
+            mark =  "<="
+        elif event.GetId() == self.btn_or.GetId():
+            mark =  "OR"
+        elif event.GetId() == self.btn_not.GetId():
+            mark = "NOT"
+        elif event.GetId() == self.btn_and.GetId():
+            mark = "AND"
+        elif event.GetId() == self.btn_brackets.GetId():
+            mark = "()"
+        elif event.GetId() == self.btn_prc.GetId():
+            mark = "%"
+        self.__Add(mark)
 
 
-    def __addSomething(self,what):
+    def __Add(self, element, value):
+        """!Add element to the query
+
+        @param what what to add
+        """
         sqlstr = self.text_sql.GetValue()
         newsqlstr = ''
-        position = self.text_sql.GetPosition()[0]
-        selection = self.text_sql.GetSelection()
-
-        newsqlstr = sqlstr[:position]
-        try:
-            if newsqlstr[-1] != " ":
-                newsqlstr += " "
-        except:
-            pass
-
-        newsqlstr += what
-        newsqlstr += " "+sqlstr[position:]
-
-        self.text_sql.SetValue(newsqlstr)
-        # FIXME: cursor position is messed up
-        #   see also   http://trac.wxwidgets.org/ticket/10051
-        #DEBUG: print "before: %d" % (position)
-        self.text_sql.SetInsertionPoint(position)
-        #? self.text_sql.SetInsertionPoint(position+len(what))
-        #? self.text_sql.SetInsertionPointEnd()
-        #DEBUG: print "len(what)=%d" % (len(what))
-        #DEBUG: print "after: %d" % (self.text_sql.GetPosition()[0])
-        #DEBUG: print " "
-
-    def OnApply(self,event):
+        if element == 'column':
+            idx1 = len('select')
+            idx2 = sqlstr.lower().find('from')
+            colstr = sqlstr[idx1:idx2].strip()
+            if colstr == '*':
+                cols = []
+            else:
+                cols = colstr.split(',')
+            if value in cols:
+                cols.remove(value)
+            else:
+                cols.append(value)
+            
+            if len(cols) < 1:
+                cols = ['*',]
+            
+            newsqlstr = 'SELECT ' + ','.join(cols) + ' ' + sqlstr[idx2:]
+            
+        if newsqlstr:
+            self.text_sql.SetValue(newsqlstr)
+        
+    def OnText(self, event):
+        """Query string changed"""
+        if len(self.text_sql.GetValue()) > 0:
+            self.btn_verify.Enable(True)
+        else:
+            self.btn_verify.Enable(False)
+        
+    def OnApply(self, event):
+        """Apply button pressed"""
         if self.parent:
             try:
                 self.parent.text_query.SetValue= self.text_sql.GetValue().strip().replace("\n"," ")
             except:
                 pass
+        
+    def OnVerify(self, event):
+        """!Verify button pressed"""
+        ret, msg = gcmd.RunCommand('db.select',
+                                   getErrorMsg = True,
+                                   table = self.tablename,
+                                   sql = self.text_sql.GetValue(),
+                                   flags = 't',
+                                   driver = self.driver,
+                                   database = self.database)
 
-    def OnVerify(self,event):
-        if self.text_sql.GetValue():
-            querystring = "SELECT * FROM %s WHERE %s" % \
-                          (self.tablename,
-                           self.text_sql.GetValue().strip().replace("\n"," "))
-            # FIXME: LOG
-            # print self.text_sql.GetValue().strip().replace("\n"," "), "not correct!"
-
-            print "Testing [%s] ..." % (querystring)
-            ret, msg = gcmd.RunCommand('db.select',
-                                  getErrorMsg = True,
-                                  verbose = True,
-                                  flags = 't',
-                                  driver = self.driver,
-                                  database = self.database,
-                                  sql = querystring)
-            print msg, " "
-            if ret == 0:
-                pass
-
+        if ret != 0 and msg:
+            wx.MessageBox(parent=self,
+                          message=_("SQL statement is not valid.\n\n%s") % msg,
+                          caption=_("Warning"), style=wx.OK | wx.ICON_WARNING | wx.CENTRE)
+        
     def OnClear(self, event):
-        self.text_sql.SetValue("")
-
-    def OnClose(self,event):
+        """!Clear button pressed"""
+        if self.qtype.lower() == "select":
+            self.text_sql.SetValue("SELECT * FROM %s" % self.tablename)
+        else:
+            self.text_sql.SetValue("")
+    
+    def OnClose(self, event):
+        """!Close button pressed"""
         self.Destroy()
 
 if __name__ == "__main__":
-
     if len(sys.argv) != 2:
         print >>sys.stderr, __doc__
         sys.exit()
-
+    
     app = wx.App(0)
-    sqlb = SQLFrame(None, -1, 'SQL Builder',sys.argv[1])
+    sqlb = SQLFrame(parent = None, title = _('SQL Builder'), vectmap = sys.argv[1])
+    sqlb.Show()
+    
     app.MainLoop()
-
-



More information about the grass-commit mailing list