[GRASS-SVN] r50006 - in grass/trunk/gui/wxpython: . dbmgr gui_core
svn_grass at osgeo.org
svn_grass at osgeo.org
Sat Dec 31 09:16:46 EST 2011
Author: martinl
Date: 2011-12-31 06:16:46 -0800 (Sat, 31 Dec 2011)
New Revision: 50006
Modified:
grass/trunk/gui/wxpython/dbmgr/dialogs.py
grass/trunk/gui/wxpython/dbmgr/manager.py
grass/trunk/gui/wxpython/gui_core/widgets.py
grass/trunk/gui/wxpython/wxpythonlib.dox
Log:
wxGUI: modify attribute records - better error tracking (validators + don't close on errors)
Modified: grass/trunk/gui/wxpython/dbmgr/dialogs.py
===================================================================
--- grass/trunk/gui/wxpython/dbmgr/dialogs.py 2011-12-31 13:43:47 UTC (rev 50005)
+++ grass/trunk/gui/wxpython/dbmgr/dialogs.py 2011-12-31 14:16:46 UTC (rev 50006)
@@ -16,15 +16,17 @@
"""
import os
+import types
from core import globalvar
import wx
import wx.lib.scrolledpanel as scrolled
-from core.gcmd import RunCommand
-from core.debug import Debug
-from core.settings import UserSettings
-from dbmgr.vinfo import VectorDBInfo
+from core.gcmd import RunCommand, GError
+from core.debug import Debug
+from core.settings import UserSettings
+from dbmgr.vinfo import VectorDBInfo
+from gui_core.widgets import IntegerValidator, FloatValidator
class DisplayAttributesDialog(wx.Dialog):
def __init__(self, parent, map,
@@ -158,11 +160,12 @@
# set min size for dialog
w, h = self.GetBestSize()
+ w += 50
if h < 200:
self.SetMinSize((w, 200))
else:
- self.SetMinSize(self.GetBestSize())
-
+ self.SetMinSize((w, h))
+
if self.notebook.GetPageCount() == 0:
Debug.msg(2, "DisplayAttributesDialog(): Nothing found!")
### self.mapDBInfo = None
@@ -182,6 +185,8 @@
def GetSQLString(self, updateValues = False):
"""!Create SQL statement string based on self.sqlStatement
+ Show error message when invalid values are entered.
+
If updateValues is True, update dataFrame according to values
in textfields.
"""
@@ -198,26 +203,38 @@
if name == key:
cat = columns[name]['values'][idx]
continue
- type = columns[name]['type']
+ ctype = columns[name]['ctype']
value = columns[name]['values'][idx]
id = columns[name]['ids'][idx]
try:
newvalue = self.FindWindowById(id).GetValue()
except:
newvalue = self.FindWindowById(id).GetLabel()
-
- if newvalue == '':
- newvalue = None
+ try:
+ if ctype == int:
+ newvalue = int(newvalue)
+ elif ctype == float:
+ newvalue = float(newvalue)
+ except ValueError:
+ GError(parent = self,
+ message = _("Column <%(col)s>: Value '%(value)s' needs to be entered as %(type)s.") % \
+ {'col' : name,
+ 'value' : str(newvalue),
+ 'type' : columns[name]['type'].lower()},
+ showTraceback = False)
+ sqlCommands.append(None)
+ continue
+
if newvalue != value:
updatedColumns.append(name)
if newvalue is None:
updatedValues.append('NULL')
else:
- if type != 'character':
- updatedValues.append(newvalue)
+ if ctype != str:
+ updatedValues.append(str(newvalue))
else:
- updatedValues.append("'" + newvalue + "'")
+ updatedValues.append("'" + str(newvalue) + "'")
columns[name]['values'][idx] = newvalue
if self.action != "add" and len(updatedValues) == 0:
@@ -289,13 +306,18 @@
def OnSubmit(self, event):
"""!Submit records"""
layer = 1
+ close = True
+ enc = UserSettings.Get(group = 'atm', key = 'encoding', subkey = 'value')
+ if not enc and 'GRASS_DB_ENCODING' in os.environ:
+ enc = os.environ['GRASS_DB_ENCODING']
+
for sql in self.GetSQLString(updateValues = True):
- enc = UserSettings.Get(group = 'atm', key = 'encoding', subkey = 'value')
- if not enc and 'GRASS_DB_ENCODING' in os.environ:
- enc = os.environ['GRASS_DB_ENCODING']
+ if not sql:
+ close = False
+ continue
if enc:
sql = sql.encode(enc)
-
+
driver, database = self.mapDBInfo.GetDbSettings(layer)
Debug.msg(1, "SQL: %s" % sql)
RunCommand('db.execute',
@@ -308,7 +330,7 @@
layer += 1
- if self.closeDialog.IsChecked():
+ if close and self.closeDialog.IsChecked():
self.OnCancel(event)
def OnFeature(self, event):
@@ -462,8 +484,8 @@
# notebook body
border = wx.BoxSizer(wx.VERTICAL)
- flexSizer = wx.FlexGridSizer (cols = 4, hgap = 3, vgap = 3)
- flexSizer.AddGrowableCol(3)
+ flexSizer = wx.FlexGridSizer (cols = 3, hgap = 3, vgap = 3)
+ flexSizer.AddGrowableCol(2)
# columns (sorted by index)
names = [''] * len(columns.keys())
for name in columns.keys():
@@ -473,10 +495,11 @@
if name == key: # skip key column (category)
continue
- vtype = columns[name]['type']
+ vtype = columns[name]['type'].lower()
+ ctype = columns[name]['ctype']
if columns[name]['values'][idx] is not None:
- if columns[name]['ctype'] != type(''):
+ if columns[name]['ctype'] != types.StringType:
value = str(columns[name]['values'][idx])
else:
value = columns[name]['values'][idx]
@@ -486,21 +509,22 @@
colName = wx.StaticText(parent = panel, id = wx.ID_ANY,
label = name)
colType = wx.StaticText(parent = panel, id = wx.ID_ANY,
- label = "[" + vtype.lower() + "]")
- delimiter = wx.StaticText(parent = panel, id = wx.ID_ANY, label = ":")
-
+ label = "[%s]:" % vtype)
colValue = wx.TextCtrl(parent = panel, id = wx.ID_ANY, value = value)
colValue.SetName(name)
+ if ctype == int:
+ colValue.SetValidator(IntegerValidator())
+ elif ctype == float:
+ colValue.SetValidator(FloatValidator())
+
self.Bind(wx.EVT_TEXT, self.OnSQLStatement, colValue)
if self.action == 'display':
colValue.SetWindowStyle(wx.TE_READONLY)
flexSizer.Add(colName, proportion = 0,
- flag = wx.FIXED_MINSIZE | wx.ALIGN_CENTER_VERTICAL)
+ flag = wx.ALIGN_CENTER_VERTICAL)
flexSizer.Add(colType, proportion = 0,
- flag = wx.FIXED_MINSIZE | wx.ALIGN_CENTER_VERTICAL)
- flexSizer.Add(delimiter, proportion = 0,
- flag = wx.FIXED_MINSIZE | wx.ALIGN_CENTER_VERTICAL)
+ flag = wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT)
flexSizer.Add(colValue, proportion = 1,
flag = wx.EXPAND | wx.ALIGN_CENTER_VERTICAL)
# add widget reference to self.columns
@@ -568,7 +592,7 @@
self.cat = None
winFocus = False
- for column, ctype, value in data:
+ for column, ctype, ctypeStr, value in data:
if self.keyId == cId:
self.cat = int(value)
if not keyEditable[1]:
@@ -584,6 +608,10 @@
else:
valueWin = wx.TextCtrl(parent = self.dataPanel, id = wx.ID_ANY,
value = value, size = (250, -1))
+ if ctype == int:
+ valueWin.SetValidator(IntegerValidator())
+ elif ctype == float:
+ valueWin.SetValidator(FloatValidator())
if not winFocus:
wx.CallAfter(valueWin.SetFocus)
winFocus = True
@@ -591,7 +619,7 @@
label = wx.StaticText(parent = self.dataPanel, id = wx.ID_ANY,
label = column)
ctype = wx.StaticText(parent = self.dataPanel, id = wx.ID_ANY,
- label = "[%s]:" % ctype)
+ label = "[%s]:" % ctypeStr.lower())
self.widgets.append((label.GetId(), ctype.GetId(), valueWin.GetId()))
cId += 1
Modified: grass/trunk/gui/wxpython/dbmgr/manager.py
===================================================================
--- grass/trunk/gui/wxpython/dbmgr/manager.py 2011-12-31 13:43:47 UTC (rev 50005)
+++ grass/trunk/gui/wxpython/dbmgr/manager.py 2011-12-31 14:16:46 UTC (rev 50006)
@@ -499,7 +499,7 @@
item1 = self.itemDataMap[key1][self._col]
item2 = self.itemDataMap[key2][self._col]
- if type(item1) == type('') or type(item2) == type(''):
+ if type(item1) == types.StringType or type(item2) == types.StringTypes:
cmpVal = locale.strcoll(str(item1), str(item2))
else:
cmpVal = cmp(item1, item2)
@@ -1352,13 +1352,14 @@
colIdx = 0
keyId = -1
for col in columnName:
- ctype = self.mapDBInfo.tables[table][col]['type']
+ ctype = self.mapDBInfo.tables[table][col]['ctype']
+ ctypeStr = self.mapDBInfo.tables[table][col]['type']
if col == keyColumn: # key
if missingKey is False:
- data.append((col, ctype, str(maxCat + 1)))
+ data.append((col, ctype, ctypeStr, str(maxCat + 1)))
keyId = colIdx
else:
- data.append((col, ctype, ''))
+ data.append((col, ctype, ctypeStr, ''))
colIdx += 1
@@ -1409,10 +1410,11 @@
except ValueError, err:
GError(parent = self,
- message = "%s%s%s" % (_("Unable to insert new record."),
- os.linesep, err))
+ message = _("Unable to insert new record.\n%s") % err,
+ showTraceback = False)
+ self.OnDataItemAdd(event)
return
-
+
# remove category if need
if missingKey is True:
del values[0]
@@ -1465,17 +1467,18 @@
# add other visible columns
for i in range(len(columnName)):
- ctype = self.mapDBInfo.tables[table][columnName[i]]['type']
+ ctype = self.mapDBInfo.tables[table][columnName[i]]['ctype']
+ ctypeStr = self.mapDBInfo.tables[table][columnName[i]]['type']
if columnName[i] == keyColumn: # key
if missingKey is False:
- data.append((columnName[i], ctype, str(cat)))
+ data.append((columnName[i], ctype, ctypeStr, str(cat)))
keyId = i
else:
if missingKey is True:
value = tlist.GetItem(item, i-1).GetText()
else:
value = tlist.GetItem(item, i).GetText()
- data.append((columnName[i], ctype, value))
+ data.append((columnName[i], ctype, ctypeStr, value))
dlg = ModifyTableRecord(parent = self,
title = _("Update existing record"),
@@ -1495,7 +1498,7 @@
idx = i - 1
else:
idx = i
- if tlist.columns[columnName[i]]['ctype'] != type(''):
+ if tlist.columns[columnName[i]]['ctype'] != types.StringType:
if tlist.columns[columnName[i]]['ctype'] == int:
value = float(values[i])
else:
@@ -1518,8 +1521,9 @@
except ValueError, err:
GError(parent = self,
- message = "%s%s%s" % (_("Unable to update existing record."),
- os.linesep, err))
+ message = _("Unable to update existing record.\n%s") % err,
+ showTraceback = False)
+ self.OnDataItemEdit(event)
return
if len(updateString) > 0:
Modified: grass/trunk/gui/wxpython/gui_core/widgets.py
===================================================================
--- grass/trunk/gui/wxpython/gui_core/widgets.py 2011-12-31 13:43:47 UTC (rev 50005)
+++ grass/trunk/gui/wxpython/gui_core/widgets.py 2011-12-31 14:16:46 UTC (rev 50006)
@@ -6,11 +6,12 @@
Classes:
- widgets::GNotebook
- widgets::ScrolledPanel
- - widgets::NTCValidator
- widgets::NumTextCtrl
- widgets::FloatSlider
- widgets::SymbolButton
- widgets::StaticWrapText
+ - widgets::BaseValidator
+ - widgets::IntegerValidator
- widgets::FloatValidator
- widgets::ItemTree
@@ -97,31 +98,6 @@
def OnChildFocus(self, event):
pass
-
-class NTCValidator(wx.PyValidator):
- """!validates input in textctrls, taken from wxpython demo"""
- def __init__(self, flag = None):
- wx.PyValidator.__init__(self)
- self.flag = flag
- self.Bind(wx.EVT_CHAR, self.OnChar)
-
- def Clone(self):
- return NTCValidator(self.flag)
-
- def OnChar(self, event):
- key = event.GetKeyCode()
- if key < wx.WXK_SPACE or key == wx.WXK_DELETE or key > 255:
- event.Skip()
- return
- if self.flag == 'DIGIT_ONLY' and chr(key) in string.digits + '.-':
- event.Skip()
- return
- if not wx.Validator_IsSilent():
- wx.Bell()
- # Returning without calling even.Skip eats the event before it
- # gets to the text control
- return
-
class NumTextCtrl(wx.TextCtrl):
"""!Class derived from wx.TextCtrl for numerical values only"""
def __init__(self, parent, **kwargs):
@@ -271,17 +247,18 @@
self.SetSize(self.wrappedSize)
del self.resizing
-class FloatValidator(wx.PyValidator):
- """!Validator for floating-point input"""
+class BaseValidator(wx.PyValidator):
def __init__(self):
wx.PyValidator.__init__(self)
self.Bind(wx.EVT_TEXT, self.OnText)
+
+ def OnText(self, event):
+ """!Do validation"""
+ self.Validate()
- def Clone(self):
- """!Clone validator"""
- return FloatValidator()
-
+ event.Skip()
+
def Validate(self):
"""Validate input"""
textCtrl = self.GetWindow()
@@ -289,7 +266,7 @@
if text:
try:
- float(text)
+ self.type(text)
except ValueError:
textCtrl.SetBackgroundColour("grey")
textCtrl.SetFocus()
@@ -303,18 +280,56 @@
return True
- def OnText(self, event):
- """!Do validation"""
- self.Validate()
-
- event.Skip()
-
def TransferToWindow(self):
return True # Prevent wxDialog from complaining.
def TransferFromWindow(self):
return True # Prevent wxDialog from complaining.
+class IntegerValidator(BaseValidator):
+ """!Validator for floating-point input"""
+ def __init__(self):
+ BaseValidator.__init__(self)
+ self.type = int
+
+ def Clone(self):
+ """!Clone validator"""
+ return IntegerValidator()
+
+class FloatValidator(BaseValidator):
+ """!Validator for floating-point input"""
+ def __init__(self):
+ BaseValidator.__init__(self)
+ self.type = float
+
+ def Clone(self):
+ """!Clone validator"""
+ return FloatValidator()
+
+class NTCValidator(wx.PyValidator):
+ """!validates input in textctrls, taken from wxpython demo"""
+ def __init__(self, flag = None):
+ wx.PyValidator.__init__(self)
+ self.flag = flag
+ self.Bind(wx.EVT_CHAR, self.OnChar)
+
+ def Clone(self):
+ return NTCValidator(self.flag)
+
+ def OnChar(self, event):
+ key = event.GetKeyCode()
+ if key < wx.WXK_SPACE or key == wx.WXK_DELETE or key > 255:
+ event.Skip()
+ return
+ if self.flag == 'DIGIT_ONLY' and chr(key) in string.digits + '.-':
+ event.Skip()
+ return
+ if not wx.Validator_IsSilent():
+ wx.Bell()
+ # Returning without calling even.Skip eats the event before it
+ # gets to the text control
+ return
+
class ItemTree(CT.CustomTreeCtrl):
def __init__(self, parent, id = wx.ID_ANY,
ctstyle = CT.TR_HIDE_ROOT | CT.TR_FULL_ROW_HIGHLIGHT | CT.TR_HAS_BUTTONS |
Modified: grass/trunk/gui/wxpython/wxpythonlib.dox
===================================================================
--- grass/trunk/gui/wxpython/wxpythonlib.dox 2011-12-31 13:43:47 UTC (rev 50005)
+++ grass/trunk/gui/wxpython/wxpythonlib.dox 2011-12-31 14:16:46 UTC (rev 50006)
@@ -168,7 +168,10 @@
- widgets::FloatSlider
- widgets::SymbolButton
- widgets::StaticWrapText
+ - widgets::BaseValidator
+ - widgets::IntegerValidator
- widgets::FloatValidator
+ - widgets::NTCValidator
- widgets::ItemTree
\subsection lmgr Layer Manager
More information about the grass-commit
mailing list