|
@@ -55,6 +55,7 @@ import time
|
|
|
import copy
|
|
|
import locale
|
|
|
from threading import Thread
|
|
|
+import Queue
|
|
|
|
|
|
### i18N
|
|
|
import gettext
|
|
@@ -70,6 +71,7 @@ import wx.lib.flatnotebook as FN
|
|
|
import wx.lib.colourselect as csel
|
|
|
import wx.lib.filebrowsebutton as filebrowse
|
|
|
from wx.lib.expando import ExpandoTextCtrl, EVT_ETC_LAYOUT_NEEDED
|
|
|
+from wx.lib.newevent import NewEvent
|
|
|
|
|
|
# Do the python 2.0 standard xml thing and map it on the old names
|
|
|
import xml.sax
|
|
@@ -105,6 +107,8 @@ except:
|
|
|
|
|
|
utils.reexec_with_pythonw()
|
|
|
|
|
|
+wxUpdateDialog, EVT_DIALOG_UPDATE = NewEvent()
|
|
|
+
|
|
|
# From lib/gis/col_str.c, except purple which is mentioned
|
|
|
# there but not given RGB values
|
|
|
str2rgb = {'aqua': (100, 128, 255),
|
|
@@ -164,16 +168,18 @@ def escape_ampersand(text):
|
|
|
|
|
|
class UpdateThread(Thread):
|
|
|
"""Update dialog widgets in the thread"""
|
|
|
- def __init__(self, parent, eventId, task):
|
|
|
+ def __init__(self, parent, event, eventId, task):
|
|
|
Thread.__init__(self)
|
|
|
-
|
|
|
+
|
|
|
self.parent = parent
|
|
|
+ self.event = event
|
|
|
self.eventId = eventId
|
|
|
self.task = task
|
|
|
self.setDaemon(True)
|
|
|
-
|
|
|
- self.start()
|
|
|
-
|
|
|
+
|
|
|
+ # list of functions which updates the dialog
|
|
|
+ self.data = {}
|
|
|
+
|
|
|
def run(self):
|
|
|
# get widget id
|
|
|
if not self.eventId:
|
|
@@ -209,17 +215,14 @@ class UpdateThread(Thread):
|
|
|
else:
|
|
|
map = None
|
|
|
|
|
|
- # avoid multiple updating
|
|
|
- columns = []
|
|
|
-
|
|
|
# update reference widgets
|
|
|
for uid in p['wxId-bind']:
|
|
|
win = self.parent.FindWindowById(uid)
|
|
|
name = win.GetName()
|
|
|
|
|
|
if name == 'LayerSelect':
|
|
|
- win.InsertLayers(map)
|
|
|
-
|
|
|
+ self.data[win.InsertLayers] = { 'vector' : map }
|
|
|
+
|
|
|
elif name == 'TableSelect':
|
|
|
pDriver = self.task.get_param('dbdriver', element='prompt', raiseError=False)
|
|
|
driver = db = None
|
|
@@ -229,40 +232,76 @@ class UpdateThread(Thread):
|
|
|
if pDb:
|
|
|
db = pDb['value']
|
|
|
|
|
|
- win.InsertTables(driver, db)
|
|
|
-
|
|
|
+ self.data[win.InsertTables] = { 'driver' : driver,
|
|
|
+ 'database' : db }
|
|
|
+
|
|
|
elif name == 'ColumnSelect':
|
|
|
- if not columns:
|
|
|
- pLayer = self.task.get_param('layer', element='element', raiseError=False)
|
|
|
- if pLayer:
|
|
|
- if pLayer.get('value', '') != '':
|
|
|
- layer = int(pLayer.get('value', 1))
|
|
|
- else:
|
|
|
- layer = int(pLayer.get('default', 1))
|
|
|
+ pLayer = self.task.get_param('layer', element='element', raiseError=False)
|
|
|
+ if pLayer:
|
|
|
+ if pLayer.get('value', '') != '':
|
|
|
+ layer = int(pLayer.get('value', 1))
|
|
|
else:
|
|
|
- layer = 1
|
|
|
-
|
|
|
- if map:
|
|
|
- win.InsertColumns(map, layer)
|
|
|
- columns = win.GetItems()
|
|
|
- else: # table
|
|
|
- pDriver = self.task.get_param('dbdriver', element='prompt', raiseError=False)
|
|
|
- if pDriver:
|
|
|
- driver = pDriver.get('value', None)
|
|
|
- pDb = self.task.get_param('dbname', element='prompt', raiseError=False)
|
|
|
- if pDb:
|
|
|
- db = pDb.get('value', None)
|
|
|
- pTable = self.task.get_param('dbtable', element='element', raiseError=False)
|
|
|
- if pTable and \
|
|
|
- pTable.get('value', '') != '':
|
|
|
- if driver and db:
|
|
|
- win.InsertTableColumns(pTable.get('value'), driver, db)
|
|
|
- else:
|
|
|
- win.InsertTableColumns(pTable.get('value'))
|
|
|
- columns = win.GetItems()
|
|
|
+ layer = int(pLayer.get('default', 1))
|
|
|
else:
|
|
|
- win.SetItems(columns)
|
|
|
+ layer = 1
|
|
|
+
|
|
|
+ if map:
|
|
|
+ self.data[win.InsertColumns] = { 'vector' : map, 'layer' : layer }
|
|
|
+ else: # table
|
|
|
+ pDriver = self.task.get_param('dbdriver', element='prompt', raiseError=False)
|
|
|
+ if pDriver:
|
|
|
+ driver = pDriver.get('value', None)
|
|
|
+ pDb = self.task.get_param('dbname', element='prompt', raiseError=False)
|
|
|
+ if pDb:
|
|
|
+ db = pDb.get('value', None)
|
|
|
+ pTable = self.task.get_param('dbtable', element='element', raiseError=False)
|
|
|
+ if pTable and \
|
|
|
+ pTable.get('value', '') != '':
|
|
|
+ if driver and db:
|
|
|
+ self.data[win.InsertTableColumns] = { 'table' : pTable.get('value'),
|
|
|
+ 'driver' : driver,
|
|
|
+ 'database' : db }
|
|
|
+ else:
|
|
|
+ self.data[win.InsertTableColumns] = { 'table' : pTable.get('value') }
|
|
|
+
|
|
|
+def UpdateDialog(parent, event, eventId, task):
|
|
|
+ return UpdateThread(parent, event, eventId, task)
|
|
|
+
|
|
|
+class UpdateQThread(Thread):
|
|
|
+ """Update dialog widgets in the thread"""
|
|
|
+ requestId = 0
|
|
|
+ def __init__(self, parent, requestQ, resultQ, **kwds):
|
|
|
+ Thread.__init__(self, **kwds)
|
|
|
+
|
|
|
+ self.parent = parent # cmdPanel
|
|
|
+ self.setDaemon(True)
|
|
|
+
|
|
|
+ self.requestQ = requestQ
|
|
|
+ self.resultQ = resultQ
|
|
|
+
|
|
|
+ self.start()
|
|
|
+
|
|
|
+ def Update(self, callable, *args, **kwds):
|
|
|
+ UpdateQThread.requestId += 1
|
|
|
+
|
|
|
+ self.request = None
|
|
|
+ self.requestQ.put((UpdateQThread.requestId, callable, args, kwds))
|
|
|
+
|
|
|
+ return UpdateQThread.requestId
|
|
|
+
|
|
|
+ def run(self):
|
|
|
+ while True:
|
|
|
+ requestId, callable, args, kwds = self.requestQ.get()
|
|
|
+
|
|
|
+ requestTime = time.time()
|
|
|
|
|
|
+ self.request = callable(*args, **kwds)
|
|
|
+
|
|
|
+ self.resultQ.put((requestId, self.request.run()))
|
|
|
+
|
|
|
+ event = wxUpdateDialog(data = self.request.data)
|
|
|
+ wx.PostEvent(self.parent, event)
|
|
|
+
|
|
|
class testSAXContentHandler(HandlerBase):
|
|
|
# SAX compliant
|
|
|
def characters(self, ch, start, length):
|
|
@@ -857,6 +896,12 @@ class mainFrame(wx.Frame):
|
|
|
self.notebookpanel.constrained_size[1] -
|
|
|
self.notebookpanel.panelMinHeight))
|
|
|
|
|
|
+ # thread to update dialog
|
|
|
+ # create queues
|
|
|
+ self.requestQ = Queue.Queue()
|
|
|
+ self.resultQ = Queue.Queue()
|
|
|
+ self.updateThread = UpdateQThread(self.notebookpanel, self.requestQ, self.resultQ)
|
|
|
+
|
|
|
self.Layout()
|
|
|
|
|
|
def updateValuesHook(self):
|
|
@@ -1517,6 +1562,12 @@ class cmdPanel(wx.Panel):
|
|
|
|
|
|
self.hasMain = tab.has_key( _('Required') ) # publish, to enclosing Frame for instance
|
|
|
|
|
|
+ self.Bind(EVT_DIALOG_UPDATE, self.OnUpdateDialog)
|
|
|
+
|
|
|
+ def OnUpdateDialog(self, event):
|
|
|
+ for fn, kwargs in event.data.iteritems():
|
|
|
+ fn(**kwargs)
|
|
|
+
|
|
|
def OnVerbosity(self, event):
|
|
|
"""Verbosity level changed"""
|
|
|
verbose = self.FindWindowById(self.task.get_flag('verbose')['wxId'])
|
|
@@ -1636,10 +1687,18 @@ class cmdPanel(wx.Panel):
|
|
|
Update dialog (layers, tables, columns, etc.)
|
|
|
"""
|
|
|
if event:
|
|
|
- UpdateThread(self, event.GetId(), self.task)
|
|
|
+ self.parent.updateThread.Update(UpdateDialog,
|
|
|
+ self,
|
|
|
+ event,
|
|
|
+ event.GetId(),
|
|
|
+ self.task)
|
|
|
else:
|
|
|
- UpdateThread(self, None, self.task)
|
|
|
-
|
|
|
+ self.parent.updateThread.Update(UpdateDialog,
|
|
|
+ self,
|
|
|
+ None,
|
|
|
+ None,
|
|
|
+ self.task)
|
|
|
+
|
|
|
def createCmd( self, ignoreErrors = False ):
|
|
|
"""
|
|
|
Produce a command line string (list) or feeding into GRASS.
|