~ubuntu-branches/ubuntu/vivid/grass/vivid-proposed

« back to all changes in this revision

Viewing changes to gui/wxpython/gui_core/forms.py

  • Committer: Package Import Robot
  • Author(s): Bas Couwenberg
  • Date: 2015-02-20 23:12:08 UTC
  • mfrom: (8.2.6 experimental)
  • Revision ID: package-import@ubuntu.com-20150220231208-1u6qvqm84v430b10
Tags: 7.0.0-1~exp1
* New upstream release.
* Update python-ctypes-ternary.patch to use if/else instead of and/or.
* Drop check4dev patch, rely on upstream check.
* Add build dependency on libpq-dev to grass-dev for libpq-fe.h.
* Drop patches applied upstream, refresh remaining patches.
* Update symlinks for images switched from jpg to png.

Show diffs side-by-side

added added

removed removed

Lines of Context:
29
29
make it callable by gui.  Method added to automatically re-run with
30
30
pythonw on a Mac.
31
31
 
32
 
@todo
33
 
 - verify option value types
 
32
.. todo::
 
33
    verify option value types
34
34
 
35
 
Copyright(C) 2000-2012 by the GRASS Development Team
 
35
Copyright(C) 2000-2013 by the GRASS Development Team
36
36
 
37
37
This program is free software under the GPL(>=v2) Read the file
38
38
COPYING coming with GRASS for details.
43
43
@author Daniel Calvelo <dca.gis@gmail.com>
44
44
@author Martin Landa <landa.martin@gmail.com>
45
45
@author Luca Delucchi <lucadeluge@gmail.com>
 
46
@author Stepan Turek <stepan.turek seznam.cz> (CoordinatesSelect)
46
47
"""
47
48
 
48
49
import sys
49
50
import string
50
51
import textwrap
51
52
import os
52
 
import time
53
53
import copy
54
54
import locale
55
 
from threading import Thread
56
55
import Queue
57
56
import re
58
 
 
59
 
gisbase = os.getenv("GISBASE")
60
 
if gisbase is None:
61
 
    print >>sys.stderr, "We don't seem to be properly installed, or we are being run outside GRASS. Expect glitches."
 
57
import codecs
 
58
 
 
59
from threading import Thread
 
60
 
 
61
if not os.getenv("GISBASE"):
 
62
    sys.write("We don't seem to be properly installed, or we are being run "
 
63
              "outside GRASS. Expect glitches.\n")
62
64
    gisbase = os.path.join(os.path.dirname(sys.argv[0]), os.path.pardir)
63
 
    wxbase = gisbase
64
 
else:
65
 
    wxbase = os.path.join(gisbase, 'etc', 'wxpython')
66
 
 
67
 
sys.path.append(wxbase)
68
 
 
69
 
from core import globalvar
 
65
 
70
66
import wx
71
67
try:
72
68
    import wx.lib.agw.flatnotebook as FN
81
77
except ImportError:
82
78
    import elementtree.ElementTree as etree # Python <= 2.4
83
79
 
 
80
from grass.pydispatch.signal import Signal
 
81
 
84
82
from grass.script import core as grass
85
83
from grass.script import task as gtask
86
84
 
87
 
from gui_core.widgets import StaticWrapText, ScrolledPanel
 
85
from core import globalvar
 
86
from gui_core.widgets import StaticWrapText, ScrolledPanel, ColorTablesComboBox, \
 
87
                             BarscalesComboBox, NArrowsComboBox
88
88
from gui_core.ghelp   import HelpPanel
89
89
from gui_core         import gselect
90
90
from core             import gcmd
91
91
from core             import utils
 
92
from core.utils import _
92
93
from core.settings    import UserSettings
93
 
from gui_core.widgets import FloatValidator, GNotebook
 
94
from gui_core.widgets import FloatValidator, GNotebook, FormNotebook, FormListbook
 
95
from core.giface import Notification
94
96
 
95
97
wxUpdateDialog, EVT_DIALOG_UPDATE = NewEvent()
96
98
 
97
 
# From lib/gis/col_str.c, except purple which is mentioned
98
 
# there but not given RGB values
99
 
str2rgb = {'aqua': (100, 128, 255),
100
 
           'black': (0, 0, 0),
101
 
           'blue': (0, 0, 255),
102
 
           'brown': (180, 77, 25),
103
 
           'cyan': (0, 255, 255),
104
 
           'gray': (128, 128, 128),
105
 
           'green': (0, 255, 0),
106
 
           'grey': (128, 128, 128),
107
 
           'indigo': (0, 128, 255),
108
 
           'magenta': (255, 0, 255),
109
 
           'orange': (255, 128, 0),
110
 
           'purple': (128, 0, 128),
111
 
           'red': (255, 0, 0),
112
 
           'violet': (128, 0, 255),
113
 
           'white': (255, 255, 255),
114
 
           'yellow': (255, 255, 0)}
115
 
rgb2str = {}
116
 
for (s,r) in str2rgb.items():
117
 
    rgb2str[ r ] = s
118
99
 
119
 
"""!Hide some options in the GUI"""
 
100
"""Hide some options in the GUI"""
 
101
#_blackList = { 'enabled' : False,
 
102
#               'items'   : { 'r.buffer' : {'params' : ['input', 'output'],
 
103
#                                           'flags' : ['z', 'overwrite']}}}
120
104
_blackList = { 'enabled' : False,
121
 
               'items'   : { 'd.legend' : { 'flags' : ['m'] } }
122
 
               }
 
105
               'items'   : {} }
123
106
 
124
 
def color_resolve(color):
125
 
    if len(color) > 0 and color[0] in "0123456789":
126
 
        rgb = tuple(map(int, color.split(':')))
127
 
        label = color
128
 
    else:
129
 
        # Convert color names to RGB
130
 
        try:
131
 
            rgb = str2rgb[ color ]
132
 
            label = color
133
 
        except KeyError:
134
 
            rgb = (200,200,200)
135
 
            label = _('Select Color')
136
 
    return (rgb, label)
137
107
 
138
108
def text_beautify(someString , width = 70):
139
 
    """
140
 
    Make really long texts shorter, clean up whitespace and
141
 
    remove trailing punctuation.
 
109
    """Make really long texts shorter, clean up whitespace and remove
 
110
    trailing punctuation.
142
111
    """
143
112
    if width > 0:
144
113
        return escape_ampersand(string.strip(
148
117
        return escape_ampersand(string.strip(utils.normalize_whitespace(someString), ".,;:"))
149
118
    
150
119
def escape_ampersand(text):
151
 
    """!Escapes ampersands with additional ampersand for GUI"""
 
120
    """Escapes ampersands with additional ampersand for GUI"""
152
121
    return string.replace(text, "&", "&&")
153
122
 
154
123
class UpdateThread(Thread):
155
 
    """!Update dialog widgets in the thread"""
 
124
    """Update dialog widgets in the thread"""
156
125
    def __init__(self, parent, event, eventId, task):
157
126
        Thread.__init__(self)
158
127
        
182
151
        p = self.task.get_param(self.eventId, element = 'wxId', raiseError = False)
183
152
        if not p or 'wxId-bind' not in p:
184
153
            return
185
 
        
 
154
 
 
155
        # is this check necessary?
186
156
        # get widget prompt
187
 
        pType = p.get('prompt', '')
188
 
        if not pType:
189
 
            return
 
157
        # pType = p.get('prompt', '')
 
158
        # if not pType:
 
159
        #     return
190
160
        
191
161
        # check for map/input parameter
192
162
        pMap = self.task.get_param('map', raiseError = False)
193
163
        
194
164
        if not pMap:
195
165
            pMap = self.task.get_param('input', raiseError = False)
196
 
 
 
166
        
197
167
        if pMap:
198
168
            map = pMap.get('value', '')
199
169
        else:
200
170
            map = None
201
 
 
 
171
        
202
172
        # avoid running db.describe several times
203
173
        cparams = dict()
204
174
        cparams[map] = { 'dbInfo' : None,
211
181
                continue
212
182
            
213
183
            name = win.GetName()
 
184
            
 
185
            ### @todo: replace name by isinstance() and signals
 
186
 
214
187
            pBind = self.task.get_param(uid, element = 'wxId', raiseError = False)
215
188
            if pBind:
216
189
                pBind['value'] = ''
217
190
            
 
191
            # set appropriate types in t.* modules and g.list/remove element selections
 
192
            if name == 'Select':
 
193
                type_param = self.task.get_param('type', element='name', raiseError=False)
 
194
 
 
195
                if 'all' in type_param.get('value'):
 
196
                    etype = type_param.get('values')
 
197
                    if 'all' in etype:
 
198
                        etype.remove('all')
 
199
                    etype = ','.join(etype)
 
200
                else:
 
201
                    etype = type_param.get('value')
 
202
 
 
203
                if globalvar.CheckWxVersion([3]):
 
204
                    self.data[win.SetElementList] = {'type': etype}
 
205
                else:
 
206
                    self.data[win.GetParent().SetElementList] = {'type': etype}
 
207
 
 
208
                # t.(un)register has one type for 'input', 'maps'
 
209
                maps_param = self.task.get_param('maps', element='name', raiseError=False)
 
210
                if self.task.get_name().startswith('t') and maps_param is not None:
 
211
                    if maps_param['wxId'][0] != uid:
 
212
                        element_dict = {'raster': 'strds', 'vector': 'stvds', 'raster_3d': 'str3ds'}
 
213
                        self.data[win.GetParent().SetType] = {'etype': element_dict[type_param.get('value')]}
 
214
 
 
215
            map = layer = None
 
216
            driver = db = None
 
217
            if name in ('LayerSelect', 'ColumnSelect'):
 
218
                if p.get('element', '') == 'vector': # -> vector
 
219
                    # get map name
 
220
                    map = p.get('value', '')
 
221
                    
 
222
                    # get layer
 
223
                    for bid in p['wxId-bind']:
 
224
                        p = self.task.get_param(bid, element = 'wxId', raiseError = False)
 
225
                        if not p:
 
226
                            continue
 
227
                        
 
228
                        if p.get('element', '') in ['layer', 'layer_all']:
 
229
                            layer = p.get('value', '')
 
230
                            if layer != '':
 
231
                                layer = p.get('value', '')
 
232
                            else:
 
233
                                layer = p.get('default', '')
 
234
                            break
 
235
                        
 
236
                elif p.get('element', '') in ['layer', 'layer_all']: # -> layer
 
237
                    # get layer
 
238
                    layer = p.get('value', '')
 
239
                    if layer != '':
 
240
                        layer = p.get('value', '')
 
241
                    else:
 
242
                        layer = p.get('default', '')
 
243
                    
 
244
                    # get map name
 
245
                    pMapL = self.task.get_param(p['wxId'][0], element = 'wxId-bind', raiseError = False)
 
246
                    if pMapL:
 
247
                        map = pMapL.get('value', '')
 
248
            
 
249
            if name == 'TableSelect' or \
 
250
                    (name == 'ColumnSelect' and not map):
 
251
                pDriver = self.task.get_param('dbdriver', element = 'prompt', raiseError = False)
 
252
                if pDriver:
 
253
                    driver = pDriver.get('value', '')
 
254
                pDb = self.task.get_param('dbname', element = 'prompt', raiseError = False)
 
255
                if pDb:
 
256
                    db = pDb.get('value', '')
 
257
                if name == 'ColumnSelect':
 
258
                    pTable = self.task.get_param('dbtable', element = 'element', raiseError = False)
 
259
                    if pTable:
 
260
                        table = pTable.get('value', '')
 
261
 
218
262
            if name == 'LayerSelect':
219
 
                if map in cparams and not cparams[map]['layers']:
220
 
                    win.InsertLayers(vector = map)
221
 
                    cparams[map]['layers'] = win.GetItems()
 
263
                # determine format
 
264
                native = True
 
265
                
 
266
                for id in pMap['wxId']:
 
267
                    winVec  = self.parent.FindWindowById(id)
 
268
                    if winVec.GetName() == 'VectorFormat' and \
 
269
                            winVec.GetSelection() != 0:
 
270
                        native = False
 
271
                        break
 
272
                # TODO: update only if needed
 
273
                if native:
 
274
                    if map:
 
275
                        self.data[win.InsertLayers] = { 'vector' : map }
 
276
                    else:
 
277
                        self.data[win.InsertLayers] = { }
 
278
                else:
 
279
                    if map:
 
280
                        self.data[win.InsertLayers] = { 'dsn' : map.rstrip('@OGR') }
 
281
                    else:
 
282
                        self.data[win.InsertLayers] = { }
222
283
            
223
284
            elif name == 'TableSelect':
224
 
                pDriver = self.task.get_param('dbdriver', element='prompt', raiseError=False)
225
 
                driver = db = None
226
 
                if pDriver:
227
 
                    driver = pDriver['value']
228
 
                pDb = self.task.get_param('dbname', element='prompt', raiseError=False)
229
 
                if pDb:
230
 
                    db = pDb['value']
231
 
                
232
285
                self.data[win.InsertTables] = { 'driver' : driver,
233
286
                                                'database' : db }
234
287
                
235
288
            elif name == 'ColumnSelect':
236
 
                pLayer = self.task.get_param('layer', element='element', raiseError=False)
237
 
                if pLayer:
238
 
                    if pLayer.get('value', '') != '':
239
 
                        layer = pLayer.get('value', '')
240
 
                    else:
241
 
                        layer = pLayer.get('default', '')
242
 
                else:
243
 
                    layer = 1
244
 
                
245
289
                if map:
246
290
                    if map in cparams:
247
291
                        if not cparams[map]['dbInfo']:
248
292
                            cparams[map]['dbInfo'] = gselect.VectorDBInfo(map)
249
 
                        self.data[win.InsertColumns] = { 'vector' : map, 'layer' : layer,
250
 
                                                         'dbInfo' : cparams[map]['dbInfo'] }
 
293
                        self.data[win.GetParent().InsertColumns] = { 'vector' : map, 'layer' : layer,
 
294
                                                                     'dbInfo' : cparams[map]['dbInfo'] }
251
295
                else: # table
252
 
                    driver = db = None
253
 
                    pDriver = self.task.get_param('dbdriver', element='prompt', raiseError=False)
254
 
                    if pDriver:
255
 
                        driver = pDriver.get('value', None)
256
 
                    pDb = self.task.get_param('dbname', element='prompt', raiseError=False)
257
 
                    if pDb:
258
 
                        db = pDb.get('value', None)
259
 
                    pTable = self.task.get_param('dbtable', element='element', raiseError=False)
260
 
                    if pTable and \
261
 
                            pTable.get('value', '') != '':
262
 
                        if driver and db:
263
 
                            self.data[win.InsertTableColumns] = { 'table' : pTable.get('value'),
264
 
                                                                  'driver' : driver,
265
 
                                                                  'database' : db }
266
 
                        else:
267
 
                            self.data[win.InsertTableColumns] = { 'table'  : pTable.get('value') }
 
296
                    if driver and db:
 
297
                        self.data[win.GetParent().InsertTableColumns] = { 'table' : pTable.get('value'),
 
298
                                                                          'driver' : driver,
 
299
                                                                          'database' : db }
 
300
                    elif pTable:
 
301
                        self.data[win.GetParent().InsertTableColumns] = { 'table'  : pTable.get('value') }
268
302
            
269
303
            elif name == 'SubGroupSelect':
270
304
                self.data[win.Insert] = { 'group' : p.get('value', '')}
271
 
            
 
305
 
 
306
            elif name == 'SignatureSelect':
 
307
                if p.get('prompt', 'group') == 'group':
 
308
                    group = p.get('value', '')
 
309
                    pSubGroup = self.task.get_param('subgroup', element = 'prompt', raiseError = False)
 
310
                    if pSubGroup:
 
311
                        subgroup = pSubGroup.get('value', '')
 
312
                    else:
 
313
                        subgroup = None
 
314
                else:
 
315
                    subgroup = p.get('value', '')
 
316
                    pGroup = self.task.get_param('group', element = 'prompt', raiseError = False)
 
317
                    if pGroup:
 
318
                        group = pGroup.get('value', '')
 
319
                    else:
 
320
                        group = None
 
321
                
 
322
                self.data[win.Insert] = { 'group' : group,
 
323
                                          'subgroup' : subgroup}
 
324
                
272
325
            elif name == 'LocationSelect':
273
326
                pDbase = self.task.get_param('dbase', element = 'element', raiseError = False)
274
327
                if pDbase:
281
334
                    self.data[win.UpdateItems] = { 'dbase' : pDbase.get('value', ''),
282
335
                                                   'location' : pLocation.get('value', '')}
283
336
 
284
 
            elif name ==  'ProjSelect':
 
337
            elif name == 'ProjSelect':
285
338
                pDbase = self.task.get_param('dbase', element = 'element', raiseError = False)
286
339
                pLocation = self.task.get_param('location', element = 'element', raiseError = False)
287
340
                pMapset = self.task.get_param('mapset', element = 'element', raiseError = False)
289
342
                    self.data[win.UpdateItems] = { 'dbase' : pDbase.get('value', ''),
290
343
                                                   'location' : pLocation.get('value', ''),
291
344
                                                   'mapset' : pMapset.get('value', '')}
292
 
            
 
345
 
293
346
def UpdateDialog(parent, event, eventId, task):
294
347
    return UpdateThread(parent, event, eventId, task)
295
348
 
296
349
class UpdateQThread(Thread):
297
 
    """!Update dialog widgets in the thread"""
 
350
    """Update dialog widgets in the thread"""
298
351
    requestId = 0
299
352
    def __init__(self, parent, requestQ, resultQ, **kwds):
300
353
        Thread.__init__(self, **kwds)
301
354
        
302
 
        self.parent = parent # CmdPanel
 
355
        self.parent = parent # cmdPanel
303
356
        self.setDaemon(True)
304
357
        
305
358
        self.requestQ = requestQ
319
372
        while True:
320
373
            requestId, callable, args, kwds = self.requestQ.get()
321
374
            
322
 
            requestTime = time.time()
323
 
            
324
375
            self.request = callable(*args, **kwds)
325
376
 
326
377
            self.resultQ.put((requestId, self.request.run()))
328
379
            if self.request:
329
380
                event = wxUpdateDialog(data = self.request.data)
330
381
                wx.PostEvent(self.parent, event)
331
 
    
 
382
 
332
383
class TaskFrame(wx.Frame):
333
 
    """!This is the Frame containing the dialog for options input.
 
384
    """This is the Frame containing the dialog for options input.
334
385
 
335
386
    The dialog is organized in a notebook according to the guisections
336
387
    defined by each GRASS command.
343
394
    The command is checked and sent to the clipboard when clicking
344
395
    'Copy'.
345
396
    """
346
 
    def __init__(self, parent, ID, task_description,
347
 
                 get_dcmd = None, layer = None):
 
397
    def __init__(self, parent, giface, task_description, id = wx.ID_ANY,
 
398
                 get_dcmd = None, layer = None,
 
399
                 style = wx.DEFAULT_FRAME_STYLE | wx.TAB_TRAVERSAL, **kwargs):
348
400
        self.get_dcmd = get_dcmd
349
401
        self.layer    = layer
350
402
        self.task     = task_description
351
 
        self.parent   = parent            # LayerTree | Modeler | None | ...
352
 
        if parent and parent.GetName() ==  'Modeler':
353
 
            self.modeler = self.parent
354
 
        else:
355
 
            self.modeler = None
 
403
        self.parent   = parent             # LayerTree | Modeler | None | ...
 
404
        self._giface  = giface
 
405
 
 
406
        self.dialogClosing = Signal('TaskFrame.dialogClosing')
356
407
        
357
408
        # module name + keywords
358
 
        if self.task.name.split('.')[-1] in ('py', 'sh'):
359
 
            title = str(self.task.name.rsplit('.',1)[0])
360
 
        else:
361
 
            title = self.task.name
 
409
        title = self.task.get_name()
362
410
        try:
363
411
            if self.task.keywords !=  ['']:
364
412
                title +=   " [" + ', '.join(self.task.keywords) + "]"
365
413
        except ValueError:
366
414
            pass
367
415
        
368
 
        wx.Frame.__init__(self, parent = parent, id = ID, title = title,
369
 
                          pos = wx.DefaultPosition, style = wx.DEFAULT_FRAME_STYLE | wx.TAB_TRAVERSAL,
370
 
                          name = "MainFrame")
 
416
        wx.Frame.__init__(self, parent = parent, id = id, title = title,
 
417
                          name = "MainFrame", style = style, **kwargs)
371
418
        
372
419
        self.locale = wx.Locale(language = wx.LANGUAGE_DEFAULT)
373
420
        
377
424
        self.CreateStatusBar()
378
425
        
379
426
        # icon
380
 
        self.SetIcon(wx.Icon(os.path.join(globalvar.ETCICONDIR, 'grass_dialog.ico'), wx.BITMAP_TYPE_ICO))
 
427
        self.SetIcon(wx.Icon(os.path.join(globalvar.ICONDIR, 'grass_dialog.ico'), wx.BITMAP_TYPE_ICO))
381
428
        
382
429
        guisizer = wx.BoxSizer(wx.VERTICAL)
383
430
        
392
439
        
393
440
        # GRASS logo
394
441
        self.logo = wx.StaticBitmap(parent = self.panel,
395
 
                                    bitmap = wx.Bitmap(name = os.path.join(globalvar.ETCIMGDIR,
 
442
                                    bitmap = wx.Bitmap(name = os.path.join(globalvar.IMGDIR,
396
443
                                                                           'grass_form.png'),
397
444
                                                     type = wx.BITMAP_TYPE_PNG))
398
445
        topsizer.Add(item = self.logo, proportion = 0, border = 3,
403
450
            module_desc = self.task.label + ' ' + self.task.description
404
451
        else:
405
452
            module_desc = self.task.description
406
 
        self.description = StaticWrapText(parent = self.panel,
407
 
                                          label = module_desc)
 
453
        
 
454
        self.description = StaticWrapText(parent=self.panel,
 
455
                                          label=module_desc)
408
456
        topsizer.Add(item = self.description, proportion = 1, border = 5,
409
457
                     flag = wx.ALL | wx.ALIGN_CENTER_VERTICAL | wx.EXPAND)
410
458
        
414
462
        self.Layout()
415
463
        
416
464
        # notebooks
417
 
        self.notebookpanel = CmdPanel(parent = self.panel, task = self.task,
 
465
        self.notebookpanel = CmdPanel(parent = self.panel, giface = self._giface, task = self.task,
418
466
                                      frame = self)
 
467
        self._gconsole = self.notebookpanel._gconsole
 
468
        if self._gconsole:
 
469
            self._gconsole.mapCreated.connect(self.OnMapCreated)
 
470
            self._gconsole.updateMap.connect(lambda: self._giface.updateMap.emit())
419
471
        self.goutput = self.notebookpanel.goutput
 
472
        if self.goutput:
 
473
            self.goutput.showNotification.connect(lambda message: self.SetStatusText(message))
 
474
        
420
475
        self.notebookpanel.OnUpdateValues = self.updateValuesHook
421
476
        guisizer.Add(item = self.notebookpanel, proportion = 1, flag = wx.EXPAND)
422
477
        
435
490
        self.btn_cancel.SetToolTipString(_("Close this window without executing the command (Ctrl+Q)"))
436
491
        btnsizer.Add(item = self.btn_cancel, proportion = 0, flag = wx.ALL | wx.ALIGN_CENTER, border = 10)
437
492
        self.btn_cancel.Bind(wx.EVT_BUTTON, self.OnCancel)
 
493
        # bind closing to ESC and CTRL+Q
 
494
        self.Bind(wx.EVT_MENU, self.OnCancel, id=wx.ID_CLOSE)
 
495
        accelTableList = [(wx.ACCEL_NORMAL, wx.WXK_ESCAPE, wx.ID_CLOSE)]
 
496
        accelTableList = [(wx.ACCEL_CTRL, ord('Q'), wx.ID_CLOSE)]
 
497
        # TODO: bind Ctrl-t for tile windows here (trac #2004)
438
498
 
439
499
        if self.get_dcmd is not None: # A callback has been set up
440
500
            btn_apply = wx.Button(parent = self.panel, id = wx.ID_APPLY)
459
519
            
460
520
            # copy
461
521
            self.btn_clipboard = wx.Button(parent = self.panel, id = wx.ID_COPY)
462
 
            self.btn_clipboard.SetToolTipString(_("Copy the current command string to the clipboard (Ctrl+C)"))
 
522
            self.btn_clipboard.SetToolTipString(_("Copy the current command string to the clipboard"))
463
523
            
464
524
            btnsizer.Add(item = self.btn_run, proportion = 0,
465
525
                         flag = wx.ALL | wx.ALIGN_CENTER,
470
530
                         border = 10)
471
531
            
472
532
            self.btn_run.Bind(wx.EVT_BUTTON, self.OnRun)
 
533
            self.Bind(wx.EVT_MENU, self.OnRun, id=wx.ID_OK)
 
534
            accelTableList.append((wx.ACCEL_CTRL, ord('R'), wx.ID_OK))
473
535
            self.btn_clipboard.Bind(wx.EVT_BUTTON, self.OnCopy)
474
536
        # help
475
537
        self.btn_help = wx.Button(parent = self.panel, id = wx.ID_HELP)
476
538
        self.btn_help.SetToolTipString(_("Show manual page of the command (Ctrl+H)"))
477
539
        self.btn_help.Bind(wx.EVT_BUTTON, self.OnHelp)
 
540
        self.Bind(wx.EVT_MENU, self.OnHelp, id=wx.ID_HELP)
 
541
        accelTableList.append((wx.ACCEL_CTRL, ord('H'), wx.ID_HELP))
 
542
 
478
543
        if self.notebookpanel.notebook.GetPageIndexByName('manual') < 0:
479
544
            self.btn_help.Hide()
480
545
        
483
548
        
484
549
        guisizer.Add(item = btnsizer, proportion = 0, flag = wx.ALIGN_CENTER | wx.LEFT | wx.RIGHT,
485
550
                     border = 30)
 
551
        # abort key bindings
 
552
        abortId = wx.NewId()
 
553
        self.Bind(wx.EVT_MENU, self.OnAbort, id=abortId)
 
554
        accelTableList.append((wx.ACCEL_CTRL, ord('S'), abortId))
 
555
        # set accelerator table
 
556
        accelTable = wx.AcceleratorTable(accelTableList)
 
557
        self.SetAcceleratorTable(accelTable)
486
558
        
487
 
        if self.parent and not self.modeler:
 
559
        if self._giface and self._giface.GetLayerTree():
488
560
            addLayer = False
489
561
            for p in self.task.params:
490
 
                if p.get('age', 'old') ==  'new' and \
 
562
                if p.get('age', 'old') == 'new' and \
491
563
                   p.get('prompt', '') in ('raster', 'vector', '3d-raster'):
492
564
                    addLayer = True
493
565
            
502
574
        
503
575
        hasNew = False
504
576
        for p in self.task.params:
505
 
            if p.get('age', 'old') ==  'new':
 
577
            if p.get('age', 'old') == 'new':
506
578
                hasNew = True
507
579
                break
508
580
        
516
588
            guisizer.Add(item = self.closebox, proportion = 0,
517
589
                         flag = wx.EXPAND | wx.LEFT | wx.RIGHT | wx.BOTTOM,
518
590
                         border = 5)
519
 
        
 
591
        # bindings
520
592
        self.Bind(wx.EVT_CLOSE,  self.OnCancel)
521
 
        self.Bind(wx.EVT_KEY_UP, self.OnKeyUp)
522
593
        
523
594
        # do layout
524
595
        # called automatically by SetSizer()
527
598
        
528
599
        sizeFrame = self.GetBestSize()
529
600
        self.SetMinSize(sizeFrame)
530
 
        self.SetSize(wx.Size(sizeFrame[0], sizeFrame[1] + 0.33 * max(self.notebookpanel.panelMinHeight,
531
 
                                                                     self.notebookpanel.constrained_size[1])))
 
601
        
 
602
        if hasattr(self, "closebox"):
 
603
            scale = 0.33
 
604
        else:
 
605
            scale = 0.50
 
606
        self.SetSize(wx.Size(sizeFrame[0], sizeFrame[1] + scale * max(self.notebookpanel.panelMinHeight,
 
607
                                                                      self.notebookpanel.constrained_size[1])))
532
608
        
533
609
        # thread to update dialog
534
610
        # create queues
544
620
                             min(height, 500)))
545
621
        
546
622
        # fix goutput's pane size (required for Mac OSX)
547
 
        if self.goutput:                 
 
623
        if self.goutput:
548
624
            self.goutput.SetSashPosition(int(self.GetSize()[1] * .75))
549
625
        
550
626
    def updateValuesHook(self, event = None):
551
 
        """!Update status bar data"""
 
627
        """Update status bar data"""
552
628
        self.SetStatusText(' '.join(self.notebookpanel.createCmd(ignoreErrors = True)))
553
629
        if event:
554
630
            event.Skip()
555
 
        
556
 
    def OnKeyUp(self, event):
557
 
        """!Key released (check hot-keys)"""
558
 
        try:
559
 
            kc = chr(event.GetKeyCode())
560
 
        except ValueError:
561
 
            event.Skip()
562
 
            return
563
 
        
564
 
        if not event.ControlDown():
565
 
            event.Skip()
566
 
            return
567
 
        
568
 
        if kc ==  'Q':
569
 
            self.OnCancel(None)
570
 
        elif kc ==  'S':
571
 
            self.OnAbort(None)
572
 
        elif kc ==  'H':
573
 
            self.OnHelp(None)
574
 
        elif kc ==  'R':
575
 
            self.OnRun(None)
576
 
        elif kc ==  'C':
577
 
            self.OnCopy(None)
578
 
        
579
 
        event.Skip()
580
631
 
581
632
    def OnDone(self, cmd, returncode):
582
 
        """!This function is launched from OnRun() when command is
 
633
        """This function is launched from OnRun() when command is
583
634
        finished
584
635
 
585
 
        @param returncode command's return code (0 for success)
586
 
        """
587
 
        if not self.parent or returncode !=  0:
588
 
            return
589
 
        if self.parent.GetName() not in ('LayerTree', 'LayerManager'):
590
 
            return
591
 
        
592
 
        if self.parent.GetName() ==  'LayerTree':
593
 
            display = self.parent.GetMapDisplay()
594
 
        else: # Layer Manager
595
 
            display = None
596
 
            tree = self.parent.GetLayerTree()
597
 
            if tree:
598
 
                display = tree.GetMapDisplay()
599
 
            
600
 
        if not display or not display.IsAutoRendered():
601
 
            return
602
 
        
603
 
        mapLayers = map(lambda x: x.GetName(),
604
 
                        display.GetMap().GetListOfLayers(l_type = 'raster') +
605
 
                        display.GetMap().GetListOfLayers(l_type = 'vector'))
606
 
        
607
 
        task = GUI(show = None).ParseCommand(cmd)
608
 
        for p in task.get_options()['params']:
609
 
            if p.get('prompt', '') not in ('raster', 'vector'):
610
 
                continue
611
 
            mapName = p.get('value', '')
612
 
            if '@' not in mapName:
613
 
                mapName = mapName + '@' + grass.gisenv()['MAPSET']
614
 
            if mapName in mapLayers:
615
 
                display.GetWindow().UpdateMap(render = True)
616
 
                return
617
 
        
 
636
        :param returncode: command's return code (0 for success)
 
637
        """
 
638
 
 
639
        if hasattr(self, "btn_cancel"):
 
640
            self.btn_cancel.Enable(True)
 
641
 
 
642
        if hasattr(self, "btn_clipboard"):
 
643
            self.btn_clipboard.Enable(True)
 
644
 
 
645
        if hasattr(self, "btn_help"):
 
646
            self.btn_help.Enable(True)
 
647
 
 
648
        if hasattr(self, "btn_run"):
 
649
            self.btn_run.Enable(True)
 
650
 
 
651
        if hasattr(self, "get_dcmd") and \
 
652
                    self.get_dcmd is None and \
 
653
                    hasattr(self, "closebox") and \
 
654
                    self.closebox.IsChecked() and \
 
655
                    (returncode == 0):
 
656
            # was closed also when aborted but better is leave it open
 
657
            wx.FutureCall(2000, self.Close)
 
658
 
 
659
    def OnMapCreated(self, name, ltype):
 
660
        """Map created or changed
 
661
 
 
662
        :param name: map name
 
663
        :param ltype: layer type (prompt value)
 
664
        """
 
665
        if hasattr(self, "addbox") and self.addbox.IsChecked():
 
666
            add = True
 
667
        else:
 
668
            add = False
 
669
        
 
670
        if self._giface:
 
671
            self._giface.mapCreated.emit(name=name, ltype=ltype, add=add)
 
672
    
618
673
    def OnOK(self, event):
619
 
        """!OK button pressed"""
 
674
        """OK button pressed"""
620
675
        cmd = self.OnApply(event)
621
676
        if cmd is not None and self.get_dcmd is not None:
622
677
            self.OnCancel(event)
623
678
 
624
679
    def OnApply(self, event):
625
 
        """!Apply the command"""
626
 
        if self.modeler:
 
680
        """Apply the command"""
 
681
        if self._giface and hasattr(self._giface, "_model"):
627
682
            cmd = self.createCmd(ignoreErrors = True, ignoreRequired = True)
628
683
        else:
629
684
            cmd = self.createCmd()
639
694
        return cmd
640
695
 
641
696
    def OnRun(self, event):
642
 
        """!Run the command"""
 
697
        """Run the command"""
643
698
        cmd = self.createCmd()
644
699
        
645
700
        if not cmd or len(cmd) < 1:
646
701
            return
647
702
        
 
703
        ret = 0
648
704
        if self.standalone or cmd[0][0:2] !=  "d.":
649
705
            # Send any non-display command to parent window (probably wxgui.py)
650
706
            # put to parents switch to 'Command output'
651
707
            self.notebookpanel.notebook.SetSelectionByName('output')
652
708
            
653
709
            try:
 
710
                if self.task.path:
 
711
                    cmd[0] = self.task.path # full path
654
712
                
655
 
                self.goutput.RunCmd(cmd, onDone = self.OnDone)
656
 
            except AttributeError, e:
 
713
                ret = self._gconsole.RunCmd(cmd, onDone = self.OnDone)
 
714
            except AttributeError as e:
657
715
                print >> sys.stderr, "%s: Probably not running in wxgui.py session?" % (e)
658
716
                print >> sys.stderr, "parent window is: %s" % (str(self.parent))
659
717
        else:
660
718
            gcmd.Command(cmd)
661
719
        
 
720
        if ret != 0:
 
721
            self.notebookpanel.notebook.SetSelection(0)
 
722
            return
 
723
        
662
724
        # update buttons status
663
725
        for btn in (self.btn_run,
664
726
                    self.btn_cancel,
667
729
            btn.Enable(False)
668
730
        
669
731
    def OnAbort(self, event):
670
 
        """!Abort running command"""
671
 
        from gui_core.goutput import wxCmdAbort
 
732
        """Abort running command"""
 
733
        from core.gconsole import wxCmdAbort
672
734
        event = wxCmdAbort(aborted = True)
673
 
        wx.PostEvent(self.goutput, event)
 
735
        wx.PostEvent(self._gconsole, event)
674
736
 
675
737
    def OnCopy(self, event):
676
 
        """!Copy the command"""
 
738
        """Copy the command"""
677
739
        cmddata = wx.TextDataObject()
678
740
        # list -> string
679
 
        cmdstring = ' '.join(self.createCmd(ignoreErrors = True))
 
741
        cmdlist = self.createCmd(ignoreErrors = True)
 
742
        # TODO: better protect whitespace with quotes
 
743
        for i in range(1, len(cmdlist)):
 
744
            if ' ' in cmdlist[i]:
 
745
                optname, val =  cmdlist[i].split("=", 1)
 
746
                cmdlist[i] = '%s="%s"' % (optname, val)
 
747
        cmdstring = ' '.join(cmdlist)
680
748
        cmddata.SetText(cmdstring)
681
749
        if wx.TheClipboard.Open():
682
750
#            wx.TheClipboard.UsePrimarySelection(True)
686
754
                                    (cmdstring))
687
755
 
688
756
    def OnCancel(self, event):
689
 
        """!Cancel button pressed"""
 
757
        """Cancel button pressed"""
690
758
        self.MakeModal(False)
691
 
        
 
759
        self.dialogClosing.emit()
692
760
        if self.get_dcmd and \
693
761
                self.parent and \
694
762
                self.parent.GetName() in ('LayerTree',
695
763
                                          'MapWindow'):
696
764
            # display decorations and 
697
765
            # pressing OK or cancel after setting layer properties
698
 
            if self.task.name in ['d.barscale','d.legend','d.histogram'] \
699
 
                or len(self.parent.GetPyData(self.layer)[0]['cmd']) >=  1:
 
766
            if self.task.name in ['d.barscale','d.legend', 'd.northarrow', 'd.histogram'] \
 
767
                or len(self.parent.GetLayerInfo(self.layer, key = 'cmd')) >=  1:
700
768
                self.Hide()
701
769
            # canceled layer with nothing set
702
 
            elif len(self.parent.GetPyData(self.layer)[0]['cmd']) < 1:
703
 
                self.parent.Delete(self.layer)
 
770
            elif len(self.parent.GetLayerInfo(self.layer, key = 'cmd')) < 1:
 
771
                try:
 
772
                    self.parent.Delete(self.layer)
 
773
                except ValueError:
 
774
                    # happens when closing dialog of a new layer which was removed from tree
 
775
                    pass
704
776
                self.Destroy()
705
777
        else:
706
778
            # cancel for non-display commands
707
779
            self.Destroy()
708
780
 
709
781
    def OnHelp(self, event):
710
 
        """!Show manual page (switch to the 'Manual' notebook page)"""
 
782
        """Show manual page (switch to the 'Manual' notebook page)"""
711
783
        if self.notebookpanel.notebook.GetPageIndexByName('manual') > -1:
712
784
            self.notebookpanel.notebook.SetSelectionByName('manual')
713
785
            self.notebookpanel.OnPageChange(None)
716
788
            event.Skip()
717
789
        
718
790
    def createCmd(self, ignoreErrors = False, ignoreRequired = False):
719
 
        """!Create command string (python list)"""
 
791
        """Create command string (python list)"""
720
792
        return self.notebookpanel.createCmd(ignoreErrors = ignoreErrors,
721
793
                                            ignoreRequired = ignoreRequired)
722
794
 
723
795
class CmdPanel(wx.Panel):
724
 
    """!A panel containing a notebook dividing in tabs the different
 
796
    """A panel containing a notebook dividing in tabs the different
725
797
    guisections of the GRASS cmd.
726
798
    """
727
 
    def __init__(self, parent, task, id = wx.ID_ANY, frame = None, *args, **kwargs):
 
799
    def __init__(self, parent, giface, task, id = wx.ID_ANY, frame = None, *args, **kwargs):
728
800
        if frame:
729
801
            self.parent = frame
730
802
        else:
731
803
            self.parent = parent
732
804
        self.task = task
 
805
        self._giface = giface
733
806
        
734
807
        wx.Panel.__init__(self, parent, id = id, *args, **kwargs)
735
 
        
 
808
 
 
809
        self.mapCreated = Signal
 
810
        self.updateMap  = Signal
 
811
 
736
812
        # Determine tab layout
737
813
        sections = []
738
814
        is_section = {}
739
 
        not_hidden = [ p for p in self.task.params + self.task.flags if not p.get('hidden', False) ==  True ]
 
815
        not_hidden = [ p for p in self.task.params + self.task.flags if not p.get('hidden', False) == True ]
740
816
 
741
817
        self.label_id = [] # wrap titles on resize
742
818
 
743
819
        self.Bind(wx.EVT_SIZE, self.OnSize)
744
820
        
745
821
        for task in not_hidden:
746
 
            if task.get('required', False):
 
822
            if task.get('required', False) and not task.get('guisection', ''):
747
823
                # All required go into Main, even if they had defined another guisection
748
824
                task['guisection'] = _('Required')
749
 
            if task.get('guisection','') ==  '':
 
825
            if task.get('guisection','') == '':
750
826
                # Undefined guisections end up into Options
751
827
                task['guisection'] = _('Optional')
752
828
            if task['guisection'] not in is_section:
766
842
 
767
843
        panelsizer = wx.BoxSizer(orient = wx.VERTICAL)
768
844
 
769
 
        # Build notebook
770
 
        self.notebook = GNotebook(self, style = globalvar.FNPageStyle | FN.FNB_NO_X_BUTTON )
771
 
        self.notebook.SetTabAreaColour(globalvar.FNPageColor)
772
 
        self.notebook.Bind(FN.EVT_FLATNOTEBOOK_PAGE_CHANGED, self.OnPageChange)
 
845
        # build notebook
 
846
        style = UserSettings.Get(group = 'appearance', key = 'commandNotebook', subkey = 'selection')
 
847
        if style == 0: # basic top
 
848
            self.notebook = FormNotebook(self, style = wx.BK_TOP)
 
849
            self.notebook.Bind(wx.EVT_NOTEBOOK_PAGE_CHANGED, self.OnPageChange)
 
850
        elif style == 1: # basic left
 
851
            self.notebook = FormNotebook(self, style = wx.BK_LEFT)
 
852
            self.notebook.Bind(wx.EVT_NOTEBOOK_PAGE_CHANGED, self.OnPageChange)
 
853
        elif style == 2: # fancy green
 
854
            self.notebook = GNotebook(self, style = globalvar.FNPageStyle | FN.FNB_NO_X_BUTTON )
 
855
            self.notebook.SetTabAreaColour(globalvar.FNPageColor)
 
856
            self.notebook.Bind(FN.EVT_FLATNOTEBOOK_PAGE_CHANGED, self.OnPageChange)
 
857
        elif style == 3:
 
858
            self.notebook = FormListbook(self, style = wx.BK_LEFT)
 
859
            self.notebook.Bind(wx.EVT_LISTBOOK_PAGE_CHANGED, self.OnPageChange)
 
860
        self.notebook.Refresh()
773
861
 
774
862
        tab = {}
775
863
        tabsizer = {}
777
865
            tab[section] = ScrolledPanel(parent = self.notebook)
778
866
            tab[section].SetScrollRate(10, 10)
779
867
            tabsizer[section] = wx.BoxSizer(orient = wx.VERTICAL)
780
 
            self.notebook.AddPage(page = tab[section], text = section)
781
 
        
782
 
        # are we running from command line?
783
 
        ### add 'command output' tab regardless standalone dialog
784
 
        if self.parent.GetName() ==  "MainFrame" and self.parent.get_dcmd is None:
785
 
            from gui_core.goutput import GMConsole
786
 
            self.goutput = GMConsole(parent = self, margin = False)
787
 
            self.outpage = self.notebook.AddPage(page = self.goutput, text = _("Command output"), name = 'output')
788
 
        else:
789
 
            self.goutput = None
790
 
        
791
 
        self.manual_tab = HelpPanel(parent = self, grass_command = self.task.name)
792
 
        if not self.manual_tab.GetFile():
793
 
            self.manual_tab.Hide()
794
 
        else:
795
 
            self.notebook.AddPage(page = self.manual_tab, text = _("Manual"), name = 'manual')
796
 
        
797
 
        self.notebook.SetSelection(0)
798
 
 
799
 
        panelsizer.Add(item = self.notebook, proportion = 1, flag = wx.EXPAND)
 
868
        
800
869
 
801
870
        #
802
871
        # flags
803
872
        #
804
 
        text_style = wx.FONTWEIGHT_NORMAL
805
 
        visible_flags = [ f for f in self.task.flags if not f.get('hidden', False) ==  True ]
 
873
        visible_flags = [ f for f in self.task.flags if not f.get('hidden', False) == True ]
806
874
        for f in visible_flags:
 
875
            # we don't want another help (checkbox appeared in r58783)
 
876
            if f['name'] == 'help':
 
877
                continue
807
878
            which_sizer = tabsizer[ f['guisection'] ]
808
879
            which_panel = tab[ f['guisection'] ]
809
880
            # if label is given: description -> tooltip
830
901
            f['wxId'] = [ chk.GetId(), ]
831
902
            chk.Bind(wx.EVT_CHECKBOX, self.OnSetValue)
832
903
            
833
 
            if self.parent.GetName() ==  'MainFrame' and self.parent.modeler:
 
904
            if self.parent.GetName() == 'MainFrame' and (self._giface and hasattr(self._giface, "_model")):
834
905
                parChk = wx.CheckBox(parent = which_panel, id = wx.ID_ANY,
835
906
                                     label = _("Parameterized in model"))
836
907
                parChk.SetName('ModelParam')
846
917
            if f['name'] in ('verbose', 'quiet'):
847
918
                chk.Bind(wx.EVT_CHECKBOX, self.OnVerbosity)
848
919
                vq = UserSettings.Get(group = 'cmd', key = 'verbosity', subkey = 'selection')
849
 
                if f['name'] ==  vq:
 
920
                if f['name'] == vq:
850
921
                    chk.SetValue(True)
851
922
                    f['value'] = True
852
 
            elif f['name'] ==  'overwrite' and 'value' not in f:
853
 
                chk.SetValue(UserSettings.Get(group = 'cmd', key = 'overwrite', subkey = 'enabled'))
 
923
            
 
924
            if f['name'] == 'overwrite':
854
925
                f['value'] = UserSettings.Get(group = 'cmd', key = 'overwrite', subkey = 'enabled')
 
926
                chk.SetValue(f['value'])
855
927
                
856
928
        #
857
929
        # parameters
858
930
        #
859
 
        visible_params = [ p for p in self.task.params if not p.get('hidden', False) ==  True ]
 
931
        visible_params = [ p for p in self.task.params if not p.get('hidden', False) == True ]
860
932
        
861
933
        try:
862
934
            first_param = visible_params[0]
864
936
            first_param = None
865
937
        
866
938
        for p in visible_params:
867
 
            which_sizer = tabsizer[ p['guisection'] ]
868
 
            which_panel = tab[ p['guisection'] ]
 
939
            which_sizer = tabsizer[p['guisection']]
 
940
            which_panel = tab[p['guisection']]
869
941
            # if label is given -> label and description -> tooltip
870
942
            # otherwise description -> lavel
871
943
            if p.get('label','') !=  '':
874
946
            else:
875
947
                title = text_beautify(p['description'])
876
948
                tooltip = None
877
 
            txt = None
878
 
 
879
 
            # text style (required -> bold)
880
 
            if not p.get('required', False):
881
 
                text_style = wx.FONTWEIGHT_NORMAL
882
 
            else:
883
 
                text_style = wx.FONTWEIGHT_BOLD
 
949
            
 
950
            prompt = p.get('prompt', '')
884
951
 
885
952
            # title sizer (description, name, type)
886
953
            if (len(p.get('values', [])) > 0) and \
887
954
                    p.get('multiple', False) and \
888
 
                    p.get('gisprompt',False) ==  False and \
889
 
                    p.get('type', '') ==  'string':
 
955
                    p.get('gisprompt', False) == False and \
 
956
                    p.get('type', '') == 'string':
890
957
                title_txt = wx.StaticBox(parent = which_panel, id = wx.ID_ANY)
891
958
            else:
892
959
                title_sizer = wx.BoxSizer(wx.HORIZONTAL)
895
962
                    ltype = ','.join(p['key_desc'])
896
963
                else:
897
964
                    ltype = p['type']
 
965
                # red star for required options
 
966
                if p.get('required', False):
 
967
                    required_txt = wx.StaticText(parent=which_panel, label="*")
 
968
                    required_txt.SetForegroundColour(wx.RED)
 
969
                    required_txt.SetToolTipString(_("This option is required"))
 
970
                else:
 
971
                    required_txt = wx.StaticText(parent=which_panel, label="")
898
972
                rtitle_txt = wx.StaticText(parent = which_panel,
899
973
                                           label = '(' + p['name'] + '=' + ltype + ')')
900
 
                title_sizer.Add(item = title_txt, proportion = 1,
 
974
                title_sizer.Add(item = title_txt, proportion = 0,
901
975
                                flag = wx.LEFT | wx.TOP | wx.EXPAND, border = 5)
 
976
                title_sizer.Add(item = required_txt, proportion=1,
 
977
                                flag = wx.EXPAND, border=0)
902
978
                title_sizer.Add(item = rtitle_txt, proportion = 0,
903
979
                                flag = wx.ALIGN_RIGHT | wx.RIGHT | wx.TOP, border = 5)
904
980
                which_sizer.Add(item = title_sizer, proportion = 0,
906
982
            self.label_id.append(title_txt.GetId())
907
983
 
908
984
            # title expansion
909
 
            if p.get('multiple', False) and len(p.get('values','')) ==  0:
 
985
            if p.get('multiple', False) and len(p.get('values','')) == 0:
910
986
                title = _("[multiple]") + " " + title
911
 
                if p.get('value','') ==   '' :
 
987
                if p.get('value','') ==  '' :
912
988
                    p['value'] = p.get('default','')
913
989
 
914
990
            if (len(p.get('values', [])) > 0):
915
991
                valuelist      = map(str, p.get('values',[]))
916
992
                valuelist_desc = map(unicode, p.get('values_desc',[]))
917
 
 
 
993
                required_text = "*" if p.get('required', False) else ""
918
994
                if p.get('multiple', False) and \
919
 
                        p.get('gisprompt',False) ==  False and \
920
 
                        p.get('type', '') ==  'string':
921
 
                    title_txt.SetLabel(" %s: (%s, %s) " % (title, p['name'], p['type']))
 
995
                        p.get('gisprompt',False) == False and \
 
996
                        p.get('type', '') == 'string':
 
997
                    title_txt.SetLabel(" %s:%s  (%s=%s) " % (title, required_text, p['name'], p['type']))
 
998
                    stSizer = wx.StaticBoxSizer(box = title_txt, orient = wx.VERTICAL)
922
999
                    if valuelist_desc:
923
 
                        hSizer = wx.StaticBoxSizer(box = title_txt, orient = wx.VERTICAL)
 
1000
                        hSizer = wx.FlexGridSizer(cols = 1, vgap = 1)
924
1001
                    else:
925
 
                        hSizer = wx.StaticBoxSizer(box = title_txt, orient = wx.HORIZONTAL)
 
1002
                        hSizer = wx.FlexGridSizer(cols = 6, vgap = 1, hgap = 1)
926
1003
                    isEnabled = {}
927
1004
                    # copy default values
928
 
                    if p['value'] ==  '':
 
1005
                    if p['value'] == '':
929
1006
                        p['value'] = p.get('default', '')
930
1007
                        
931
1008
                    for defval in p.get('value', '').split(','):
932
1009
                        isEnabled[ defval ] = 'yes'
933
1010
                        # for multi checkboxes, this is an array of all wx IDs
934
1011
                        # for each individual checkbox
935
 
                        p['wxId'] = list()
 
1012
                        p[ 'wxId' ] = list()
936
1013
                    idx = 0
937
1014
                    for val in valuelist:
938
1015
                        try:
945
1022
                        p[ 'wxId' ].append(chkbox.GetId())
946
1023
                        if val in isEnabled:
947
1024
                            chkbox.SetValue(True)
948
 
                        hSizer.Add(item = chkbox, proportion = 0,
949
 
                                    flag = wx.ADJUST_MINSIZE | wx.ALL, border = 1)
 
1025
                        hSizer.Add(item = chkbox, proportion = 0)
 
1026
                        chkbox.Bind(wx.EVT_CHECKBOX, self.OnUpdateSelection)
950
1027
                        chkbox.Bind(wx.EVT_CHECKBOX, self.OnCheckBoxMulti)
951
1028
                        idx +=  1
952
1029
                        
953
 
                    which_sizer.Add(item = hSizer, proportion = 0,
 
1030
                    stSizer.Add(item = hSizer, proportion = 0,
 
1031
                                flag = wx.ADJUST_MINSIZE | wx.ALL, border = 1)
 
1032
                    which_sizer.Add(item = stSizer, proportion = 0,
954
1033
                                    flag = wx.EXPAND | wx.TOP | wx.RIGHT | wx.LEFT, border = 5)
955
 
                elif p.get('gisprompt', False) ==  False:
956
 
                    if len(valuelist) ==  1: # -> textctrl
 
1034
                elif p.get('gisprompt', False) is False:
 
1035
                    if len(valuelist) == 1: # -> textctrl
957
1036
                        title_txt.SetLabel("%s (%s %s):" % (title, _('valid range'),
958
1037
                                                            str(valuelist[0])))
959
 
                        
960
 
                        if p.get('type', '') ==  'integer' and \
 
1038
                        if p.get('type', '') == 'integer' and \
961
1039
                                not p.get('multiple', False):
962
1040
 
963
1041
                            # for multiple integers use textctrl instead of spinsctrl
964
1042
                            try:
965
 
                                minValue, maxValue = map(int, valuelist[0].split('-'))
 
1043
                                minValue, maxValue = map(int, valuelist[0].rsplit('-', 1))
966
1044
                            except ValueError:
967
1045
                                minValue = -1e6
968
1046
                                maxValue = 1e6
969
1047
                            txt2 = wx.SpinCtrl(parent = which_panel, id = wx.ID_ANY, size = globalvar.DIALOG_SPIN_SIZE,
970
1048
                                               min = minValue, max = maxValue)
971
 
                            txt2.SetName("SpinCtrl")
972
1049
                            style = wx.BOTTOM | wx.LEFT
973
1050
                        else:
974
1051
                            txt2 = wx.TextCtrl(parent = which_panel, value = p.get('default',''))
975
 
                            txt2.SetName("TextCtrl")
976
1052
                            style = wx.EXPAND | wx.BOTTOM | wx.LEFT
977
1053
                        
978
1054
                        value = self._getValue(p)
979
1055
                        # parameter previously set
980
1056
                        if value:
981
 
                            if txt2.GetName() ==  "SpinCtrl":
982
 
                                txt2.SetValue(int(value))
 
1057
                            if isinstance(txt2, wx.SpinCtrl):
 
1058
                                txt2.SetValue(int(value)) 
983
1059
                            else:
984
1060
                                txt2.SetValue(value)
985
1061
                        
989
1065
                        p['wxId'] = [ txt2.GetId(), ]
990
1066
                        txt2.Bind(wx.EVT_TEXT, self.OnSetValue)
991
1067
                    else:
 
1068
                        
992
1069
                        title_txt.SetLabel(title + ':')
993
1070
                        value = self._getValue(p)
994
1071
                        
995
1072
                        if p['name'] == 'icon': # symbols
996
 
                            bitmap = wx.Bitmap(os.path.join(globalvar.ETCSYMBOLDIR, value) + '.png')
 
1073
                            bitmap = wx.Bitmap(os.path.join(globalvar.SYMBDIR, value) + '.png')
997
1074
                            bb = wx.BitmapButton(parent = which_panel, id = wx.ID_ANY,
998
1075
                                                 bitmap = bitmap)
999
1076
                            iconLabel = wx.StaticText(parent = which_panel, id = wx.ID_ANY)
1010
1087
                                            flag = wx.ADJUST_MINSIZE, border = 0)
1011
1088
                        else:
1012
1089
                            # list of values (combo)
1013
 
                            cb = wx.ComboBox(parent = which_panel, id = wx.ID_ANY, value = p.get('default',''),
1014
 
                                             size = globalvar.DIALOG_COMBOBOX_SIZE,
1015
 
                                             choices = valuelist, style = wx.CB_DROPDOWN)
 
1090
                            cb = wx.ComboBox(parent=which_panel, id=wx.ID_ANY, value=p.get('default',''),
 
1091
                                             size=globalvar.DIALOG_COMBOBOX_SIZE,
 
1092
                                             choices=valuelist, style=wx.CB_DROPDOWN)
1016
1093
                            if value:
1017
1094
                                cb.SetValue(value) # parameter previously set
1018
1095
                            which_sizer.Add(item = cb, proportion = 0,
1020
1097
                            p['wxId'] = [cb.GetId(),]
1021
1098
                            cb.Bind(wx.EVT_COMBOBOX, self.OnSetValue)
1022
1099
                            cb.Bind(wx.EVT_TEXT, self.OnSetValue)
 
1100
                            if p.get('guidependency', ''):
 
1101
                                cb.Bind(wx.EVT_COMBOBOX, self.OnUpdateSelection)
1023
1102
            
1024
1103
            # text entry
1025
1104
            if (p.get('type','string') in ('string','integer','float')
1026
 
                and len(p.get('values',[])) ==  0
1027
 
                and p.get('gisprompt',False) ==  False
 
1105
                and len(p.get('values',[])) == 0
 
1106
                and p.get('gisprompt',False) == False
1028
1107
                and p.get('prompt','') !=  'color'):
1029
1108
 
1030
1109
                title_txt.SetLabel(title + ':')
1031
1110
                if p.get('multiple', False) or \
1032
 
                        p.get('type', 'string') ==  'string' or \
 
1111
                        p.get('type', 'string') == 'string' or \
1033
1112
                        len(p.get('key_desc', [])) > 1:
1034
1113
                    txt3 = wx.TextCtrl(parent = which_panel, value = p.get('default',''))
1035
1114
                    
1040
1119
                    
1041
1120
                    txt3.Bind(wx.EVT_TEXT, self.OnSetValue)
1042
1121
                    style = wx.EXPAND | wx.BOTTOM | wx.LEFT | wx.RIGHT
1043
 
                else:
 
1122
                elif p.get('type', '') == 'integer':
1044
1123
                    minValue = -1e9
1045
1124
                    maxValue = 1e9
1046
 
                    if p.get('type', '') ==  'integer':
1047
 
                        txt3 = wx.SpinCtrl(parent = which_panel, value = p.get('default',''),
1048
 
                                           size = globalvar.DIALOG_SPIN_SIZE,
1049
 
                                           min = minValue, max = maxValue)
1050
 
                        style = wx.BOTTOM | wx.LEFT | wx.RIGHT
1051
 
                        
1052
 
                        value = self._getValue(p)
1053
 
                        if value:
1054
 
                            txt3.SetValue(int(value)) # parameter previously set
1055
 
                        
 
1125
                    value = self._getValue(p)
 
1126
                    
 
1127
                    txt3 = wx.SpinCtrl(parent = which_panel, value = p.get('default', ''),
 
1128
                                       size = globalvar.DIALOG_SPIN_SIZE,
 
1129
                                       min = minValue, max = maxValue)
 
1130
                    if value:
 
1131
                        txt3.SetValue(int(value)) # parameter previously set
1056
1132
                        txt3.Bind(wx.EVT_SPINCTRL, self.OnSetValue)
1057
 
                    else:
1058
 
                        txt3 = wx.TextCtrl(parent = which_panel, value = p.get('default',''),
1059
 
                                           validator = FloatValidator())
1060
 
                        style = wx.EXPAND | wx.BOTTOM | wx.LEFT | wx.RIGHT
1061
 
                        
1062
 
                        value = self._getValue(p)
1063
 
                        if value:
1064
 
                            txt3.SetValue(str(value)) # parameter previously set
 
1133
 
 
1134
                    style = wx.BOTTOM | wx.LEFT | wx.RIGHT
 
1135
                else: # float
 
1136
                    txt3 = wx.TextCtrl(parent = which_panel, value = p.get('default',''),
 
1137
                                       validator = FloatValidator())
 
1138
                    style = wx.EXPAND | wx.BOTTOM | wx.LEFT | wx.RIGHT
1065
1139
                    
 
1140
                    value = self._getValue(p)
 
1141
                    if value:
 
1142
                        txt3.SetValue(str(value)) # parameter previously set
 
1143
                
1066
1144
                txt3.Bind(wx.EVT_TEXT, self.OnSetValue)
1067
1145
                
1068
1146
                which_sizer.Add(item = txt3, proportion = 0,
1072
1150
            #
1073
1151
            # element selection tree combobox (maps, icons, regions, etc.)
1074
1152
            #
1075
 
            if p.get('gisprompt', False) ==  True:
 
1153
            if p.get('gisprompt', False):
1076
1154
                title_txt.SetLabel(title + ':')
1077
1155
                # GIS element entry
1078
1156
                if p.get('prompt','') not in ('color',
1079
 
                                              'color_none',
1080
1157
                                              'subgroup',
 
1158
                                              'sigfile',
 
1159
                                              'separator',
1081
1160
                                              'dbdriver',
1082
1161
                                              'dbname',
1083
1162
                                              'dbtable',
1084
1163
                                              'dbcolumn',
1085
1164
                                              'layer',
1086
 
                                              'layer_all',
1087
 
                                              'layer_zero',
1088
1165
                                              'location',
1089
1166
                                              'mapset',
1090
 
                                              'dbase') and \
1091
 
                       p.get('element', '') !=  'file':
 
1167
                                              'dbase',
 
1168
                                              'coords',
 
1169
                                              'file',
 
1170
                                              'dir',
 
1171
                                              'colortable',
 
1172
                                              'barscale',
 
1173
                                              'northarrow'):
1092
1174
                    multiple = p.get('multiple', False)
1093
 
                    if p.get('age', '') ==  'new':
 
1175
                    if p.get('age', '') == 'new':
1094
1176
                        mapsets = [grass.gisenv()['MAPSET'],]
1095
1177
                    else:
1096
1178
                        mapsets = None
1097
1179
                    if self.task.name in ('r.proj', 'v.proj') \
1098
 
                            and p.get('name', '') ==  'input':
1099
 
                        if self.task.name ==  'r.proj':
 
1180
                            and p.get('name', '') == 'input':
 
1181
                        if self.task.name == 'r.proj':
1100
1182
                            isRaster = True
1101
1183
                        else:
1102
1184
                            isRaster = False
1106
1188
                        selection.Bind(wx.EVT_COMBOBOX, self.OnSetValue)
1107
1189
                        selection.Bind(wx.EVT_TEXT, self.OnUpdateSelection)
1108
1190
                    else:
 
1191
                        elem = p.get('element', None)
 
1192
                        # hack for t.* modules
 
1193
                        if elem in ('stds', 'map'):
 
1194
                            orig_elem = elem
 
1195
                            type_param = self.task.get_param('type', element = 'name', raiseError = False)
 
1196
                            if type_param:
 
1197
                                elem = type_param.get('default', None)
 
1198
                                # for t.(un)register:
 
1199
                                maps_param = self.task.get_param('maps', element = 'name', raiseError = False)
 
1200
                                if maps_param and orig_elem == 'stds':
 
1201
                                    element_dict = {'raster': 'strds', 'vector': 'stvds', 'raster_3d': 'str3ds'}
 
1202
                                    elem = element_dict[type_param.get('default')]
 
1203
                        
 
1204
                        if self._giface and hasattr(self._giface, "_model"):
 
1205
                            extraItems = {_('Graphical Modeler') : self._giface.GetLayerList(p.get('prompt'))}
 
1206
                        else:
 
1207
                            extraItems = None
1109
1208
                        selection = gselect.Select(parent = which_panel, id = wx.ID_ANY,
1110
1209
                                                   size = globalvar.DIALOG_GSELECT_SIZE,
1111
 
                                                   type = p.get('element', ''),
1112
 
                                                   multiple = multiple, mapsets = mapsets,
1113
 
                                                   fullyQualified = p.get('age', 'old') == 'old')
1114
 
                        
1115
 
                        
1116
 
                        # A select.Select is a combobox with two children: a textctl and a popupwindow;
 
1210
                                                   type = elem, multiple = multiple, nmaps = len(p.get('key_desc', [])),
 
1211
                                                   mapsets = mapsets, fullyQualified = p.get('age', 'old') == 'old',
 
1212
                                                   extraItems = extraItems)
 
1213
                        
 
1214
                        value = self._getValue(p)
 
1215
                        if value:
 
1216
                            selection.SetValue(value)
 
1217
                        
 
1218
                        formatSelector = True
 
1219
                        # A gselect.Select is a combobox with two children: a textctl and a popupwindow;
1117
1220
                        # we target the textctl here
1118
1221
                        textWin = selection.GetTextCtrl()
1119
 
                        p['wxId'] = [ textWin.GetId(), ]
1120
 
                        textWin.Bind(wx.EVT_TEXT, self.OnSetValue)
1121
 
                    
1122
 
                    value = self._getValue(p)
1123
 
                    if value:
1124
 
                        selection.SetValue(value) # parameter previously set
1125
 
 
1126
 
                    which_sizer.Add(item=selection, proportion=0,
1127
 
                                    flag=wx.ADJUST_MINSIZE| wx.BOTTOM | wx.LEFT | wx.RIGHT, border=5)
1128
 
                    
1129
 
                    if p.get('prompt', '') in ('vector', 'group'):
1130
 
                        selection.Bind(wx.EVT_TEXT, self.OnUpdateSelection)
 
1222
                        if globalvar.CheckWxVersion([3]):
 
1223
                            p['wxId'] = [selection.GetId(), ]
 
1224
                        else:
 
1225
                            p['wxId'] = [textWin.GetId(), ]
 
1226
                        if prompt != 'vector':
 
1227
                            self.FindWindowById(p['wxId'][0]).Bind(wx.EVT_TEXT, self.OnSetValue)
 
1228
 
 
1229
                    if prompt == 'vector':
 
1230
                        win = self.FindWindowById(p['wxId'][0])
 
1231
                        # handlers should be bound in this order
 
1232
                        # OnUpdateSelection depends on calling OnSetValue first which is bad
 
1233
                        win.Bind(wx.EVT_TEXT, self.OnUpdateSelection)
 
1234
                        win.Bind(wx.EVT_TEXT, self.OnSetValue)
 
1235
 
 
1236
                        # if formatSelector and p.get('age', 'old') == 'old':
 
1237
                        #     # OGR supported (read-only)
 
1238
                        #     self.hsizer = wx.BoxSizer(wx.HORIZONTAL)
 
1239
                            
 
1240
                        #     self.hsizer.Add(item = selection,
 
1241
                        #                     flag = wx.ADJUST_MINSIZE | wx.BOTTOM | wx.LEFT | wx.RIGHT | wx.TOP | wx.ALIGN_TOP,
 
1242
                        #                     border = 5)
 
1243
                            
 
1244
                        #     # format (native / ogr)
 
1245
                        #     rbox = wx.RadioBox(parent = which_panel, id = wx.ID_ANY,
 
1246
                        #                        label = " %s " % _("Format"),
 
1247
                        #                        style = wx.RA_SPECIFY_ROWS,
 
1248
                        #                        choices = [_("Native / Linked OGR"), _("Direct OGR")])
 
1249
                        #     if p.get('value', '').lower().rfind('@ogr') > -1:
 
1250
                        #         rbox.SetSelection(1)
 
1251
                        #     rbox.SetName('VectorFormat')
 
1252
                        #     rbox.Bind(wx.EVT_RADIOBOX, self.OnVectorFormat)
 
1253
                            
 
1254
                        #     self.hsizer.Add(item = rbox,
 
1255
                        #                     flag = wx.ADJUST_MINSIZE | wx.BOTTOM | wx.LEFT |
 
1256
                        #                     wx.RIGHT | wx.ALIGN_TOP,
 
1257
                        #                     border = 5)
 
1258
                            
 
1259
                        #     ogrSelection = gselect.GdalSelect(parent = self, panel = which_panel, ogr = True,
 
1260
                        #                                       default = 'dir',
 
1261
                        #                                       exclude = ['file'])
 
1262
                        #     self.Bind(gselect.EVT_GDALSELECT, self.OnUpdateSelection)
 
1263
                        #     self.Bind(gselect.EVT_GDALSELECT, self.OnSetValue)
 
1264
                            
 
1265
                        #     ogrSelection.SetName('OgrSelect')
 
1266
                        #     ogrSelection.Hide()
 
1267
                            
 
1268
                        #     which_sizer.Add(item = self.hsizer, proportion = 0)
 
1269
                            
 
1270
                        #     p['wxId'].append(rbox.GetId())
 
1271
                        #     p['wxId'].append(ogrSelection.GetId())
 
1272
                        #     for win in ogrSelection.GetDsnWin():
 
1273
                        #         p['wxId'].append(win.GetId())
 
1274
                        # else:
 
1275
                        which_sizer.Add(item = selection, proportion = 0,
 
1276
                                        flag = wx.ADJUST_MINSIZE | wx.BOTTOM | wx.LEFT | wx.RIGHT | wx.TOP | wx.ALIGN_CENTER_VERTICAL,
 
1277
                                        border = 5)
 
1278
                    elif prompt == 'group':
 
1279
                        win = self.FindWindowById(p['wxId'][0])
 
1280
                        win.Bind(wx.EVT_TEXT, self.OnUpdateSelection)
 
1281
                        win.Bind(wx.EVT_TEXT, self.OnSetValue)
 
1282
                        which_sizer.Add(item = selection, proportion = 0,
 
1283
                                        flag = wx.ADJUST_MINSIZE | wx.BOTTOM | wx.LEFT | wx.RIGHT | wx.TOP | wx.ALIGN_CENTER_VERTICAL,
 
1284
                                        border = 5)
 
1285
                    else:
 
1286
                        if prompt in ('stds', 'strds', 'stvds', 'str3ds'):
 
1287
                            showButton = True
 
1288
                            try:
 
1289
                                # if matplotlib is there
 
1290
                                from timeline import frame
 
1291
                                showButton = True
 
1292
                            except ImportError:
 
1293
                                showButton = False
 
1294
                        else:
 
1295
                            showButton = False
 
1296
                        if showButton:
 
1297
                            iconTheme = UserSettings.Get(group='appearance', key='iconTheme', subkey='type')
 
1298
                            bitmap = wx.Bitmap(os.path.join(globalvar.ICONDIR, iconTheme, 'map-info.png'))
 
1299
                            bb = wx.BitmapButton(parent=which_panel, bitmap=bitmap)
 
1300
                            bb.Bind(wx.EVT_BUTTON, self.OnTimelineTool)
 
1301
                            bb.SetToolTipString(_("Show graphical representation of temporal extent of dataset(s) ."))
 
1302
                            p['wxId'].append(bb.GetId())
 
1303
 
 
1304
                            hSizer = wx.BoxSizer(wx.HORIZONTAL)
 
1305
                            hSizer.Add(item=selection, proportion=0,
 
1306
                                       flag=wx.ADJUST_MINSIZE | wx.BOTTOM | wx.LEFT | wx.RIGHT | wx.TOP | wx.ALIGN_CENTER_VERTICAL,
 
1307
                                       border=5)
 
1308
                            hSizer.Add(item=bb, proportion=0,
 
1309
                                       flag=wx.EXPAND|wx.BOTTOM | wx.RIGHT | wx.TOP | wx.ALIGN_CENTER_VERTICAL,
 
1310
                                       border=5)
 
1311
                            which_sizer.Add(hSizer)
 
1312
                        else:
 
1313
                            which_sizer.Add(item=selection, proportion=0,
 
1314
                                            flag=wx.ADJUST_MINSIZE | wx.BOTTOM | wx.LEFT | wx.RIGHT | wx.TOP | wx.ALIGN_CENTER_VERTICAL,
 
1315
                                            border=5)
 
1316
 
1131
1317
                # subgroup
1132
 
                elif p.get('prompt', '') ==  'subgroup':
 
1318
                elif prompt == 'subgroup':
1133
1319
                    selection = gselect.SubGroupSelect(parent = which_panel)
1134
1320
                    p['wxId'] = [ selection.GetId() ]
1135
 
                    selection.Bind(wx.EVT_COMBOBOX, self.OnSetValue)
1136
 
                    selection.Bind(wx.EVT_TEXT,     self.OnSetValue)
1137
 
                    which_sizer.Add(item = selection, proportion = 0,
 
1321
                    selection.Bind(wx.EVT_TEXT, self.OnUpdateSelection)
 
1322
                    selection.Bind(wx.EVT_TEXT, self.OnSetValue)
 
1323
                    which_sizer.Add(item = selection, proportion = 0,
 
1324
                                    flag = wx.ADJUST_MINSIZE | wx.BOTTOM | wx.LEFT | wx.RIGHT | wx.TOP | wx.ALIGN_CENTER_VERTICAL,
 
1325
                                    border = 5)
 
1326
 
 
1327
                # sigrature file
 
1328
                elif prompt == 'sigfile':
 
1329
                    selection = gselect.SignatureSelect(parent = which_panel, element = p.get('element', 'sig'))
 
1330
                    p['wxId'] = [ selection.GetId() ]
 
1331
                    selection.Bind(wx.EVT_TEXT, self.OnSetValue)
 
1332
                    which_sizer.Add(item = selection, proportion = 0,
 
1333
                                    flag = wx.ADJUST_MINSIZE | wx.BOTTOM | wx.LEFT | wx.RIGHT | wx.TOP | wx.ALIGN_CENTER_VERTICAL,
 
1334
                                    border = 5)
 
1335
 
 
1336
                # separator
 
1337
                elif prompt == 'separator':
 
1338
                    win = gselect.SeparatorSelect(parent = which_panel)
 
1339
                    value = self._getValue(p)
 
1340
                    win.SetValue(value)
 
1341
                    p['wxId'] = [ win.GetId() ]
 
1342
                    win.Bind(wx.EVT_TEXT, self.OnSetValue)
 
1343
                    which_sizer.Add(item = win, proportion = 0,
1138
1344
                                    flag = wx.ADJUST_MINSIZE | wx.BOTTOM | wx.LEFT | wx.RIGHT | wx.TOP | wx.ALIGN_CENTER_VERTICAL,
1139
1345
                                    border = 5)
1140
1346
                
1141
1347
                # layer, dbdriver, dbname, dbcolumn, dbtable entry
1142
 
                elif p.get('prompt', '') in ('dbdriver',
1143
 
                                             'dbname',
1144
 
                                             'dbtable',
1145
 
                                             'dbcolumn',
1146
 
                                             'layer',
1147
 
                                             'layer_all',
1148
 
                                             'layer_zero',
1149
 
                                             'location',
1150
 
                                             'mapset',
1151
 
                                             'dbase'):
1152
 
                    if p.get('multiple', 'no') ==  'yes':
 
1348
                elif prompt in ('dbdriver',
 
1349
                                'dbname',
 
1350
                                'dbtable',
 
1351
                                'dbcolumn',
 
1352
                                'layer',
 
1353
                                'location',
 
1354
                                'mapset',
 
1355
                                'dbase'):
 
1356
                    if p.get('multiple', 'no') == 'yes':
1153
1357
                        win = wx.TextCtrl(parent = which_panel, value = p.get('default',''),
1154
1358
                                          size = globalvar.DIALOG_TEXTCTRL_SIZE)
1155
1359
                        win.Bind(wx.EVT_TEXT, self.OnSetValue)
1156
1360
                    else:
1157
1361
                        value = self._getValue(p)
1158
1362
                        
1159
 
                        if p.get('prompt', '') in ('layer',
1160
 
                                                   'layer_all',
1161
 
                                                   'layer_zero'):
1162
 
                            
1163
 
                            if p.get('age', 'old_layer') == 'old_layer':
1164
 
                                initial = list()
1165
 
                                if p.get('prompt', '') ==  'layer_all':
1166
 
                                    initial.insert(0, '-1')
1167
 
                                elif p.get('prompt', '') == 'layer_zero':
1168
 
                                    initial.insert(0, '0')
1169
 
                                lyrvalue = p.get('default')
1170
 
                                if lyrvalue != '':
1171
 
                                    if lyrvalue not in initial:
1172
 
                                        initial.append(str(lyrvalue))
1173
 
                                lyrvalue = p.get('value')
1174
 
                                if lyrvalue != '':
1175
 
                                    if lyrvalue not in initial:
1176
 
                                        initial.append(str(lyrvalue))
1177
 
 
 
1363
                        if prompt == 'layer':
 
1364
                            if p.get('element', 'layer') == 'layer_all':
 
1365
                                all = True
 
1366
                            else:
 
1367
                                all = False
 
1368
                            if p.get('age', 'old') == 'old':
1178
1369
                                win = gselect.LayerSelect(parent = which_panel,
1179
 
                                                          initial = initial,
 
1370
                                                          all = all,
1180
1371
                                                          default = p['default'])
1181
 
                                p['wxGetValue'] = win.GetStringSelection
1182
1372
                                win.Bind(wx.EVT_TEXT, self.OnUpdateSelection)
1183
1373
                                win.Bind(wx.EVT_TEXT, self.OnSetValue)
1184
1374
                                win.SetValue(str(value))    # default or previously set value
1188
1378
                                win.Bind(wx.EVT_SPINCTRL, self.OnSetValue)
1189
1379
                                win.SetValue(int(value))    # default or previously set value
1190
1380
 
1191
 
                        elif p.get('prompt', '') ==  'dbdriver':
 
1381
                            p['wxId'] = [ win.GetId() ]
 
1382
 
 
1383
                        elif prompt == 'dbdriver':
1192
1384
                            win = gselect.DriverSelect(parent = which_panel,
1193
1385
                                                       choices = p.get('values', []),
1194
1386
                                                       value = value)
1195
 
                            p['wxGetValue'] = win.GetStringSelection
1196
1387
                            win.Bind(wx.EVT_COMBOBOX, self.OnUpdateSelection)
1197
1388
                            win.Bind(wx.EVT_COMBOBOX, self.OnSetValue)
1198
 
                        elif p.get('prompt', '') ==  'dbname':
 
1389
                        elif prompt == 'dbname':
1199
1390
                            win = gselect.DatabaseSelect(parent = which_panel,
1200
1391
                                                         value = value)
1201
1392
                            win.Bind(wx.EVT_TEXT, self.OnUpdateSelection)
1202
1393
                            win.Bind(wx.EVT_TEXT, self.OnSetValue)
1203
 
                        
1204
 
                        elif p.get('prompt', '') == 'dbtable':
1205
 
                            if p.get('age', 'old_dbtable') == 'old_dbtable':
1206
 
                                win = gselect.TableSelect(parent=which_panel)
1207
 
                                
1208
 
                                p['wxGetValue'] = win.GetStringSelection
 
1394
                        elif prompt == 'dbtable':
 
1395
                            if p.get('age', 'old') == 'old':
 
1396
                                win = gselect.TableSelect(parent = which_panel)
1209
1397
                                win.Bind(wx.EVT_COMBOBOX, self.OnUpdateSelection)
1210
1398
                                win.Bind(wx.EVT_COMBOBOX, self.OnSetValue)
1211
1399
                            else:
1212
1400
                                win = wx.TextCtrl(parent = which_panel, value = p.get('default',''),
1213
1401
                                                  size = globalvar.DIALOG_TEXTCTRL_SIZE)
1214
1402
                                win.Bind(wx.EVT_TEXT, self.OnSetValue)
1215
 
                        elif p.get('prompt', '') ==  'dbcolumn':
 
1403
                        elif prompt == 'dbcolumn':
1216
1404
                            win = gselect.ColumnSelect(parent = which_panel,
1217
1405
                                                       value = value,
1218
 
                                                       param = p)
1219
 
                            win.Bind(wx.EVT_COMBOBOX, self.OnSetValue)
1220
 
                            win.Bind(wx.EVT_TEXT,     self.OnSetValue)
 
1406
                                                       param = p,
 
1407
                                                       multiple =  p.get('multiple', False))
 
1408
                        
 
1409
                            # A gselect.ColumnSelect is a combobox
 
1410
                            # with two children: a textctl and a
 
1411
                            # popupwindow; we target the textctl here
 
1412
                            textWin = win.GetTextCtrl()
 
1413
                            p['wxId'] = [ textWin.GetId(), ]
 
1414
                            
 
1415
                            textWin.Bind(wx.EVT_TEXT, self.OnSetValue)
 
1416
                            win.Bind(wx.EVT_TEXT, self.OnUpdateSelection)
1221
1417
 
1222
 
                        elif p.get('prompt', '') ==  'location':
 
1418
                        elif prompt == 'location':
1223
1419
                            win = gselect.LocationSelect(parent = which_panel,
1224
1420
                                                         value = value)
1225
1421
                            win.Bind(wx.EVT_COMBOBOX,     self.OnUpdateSelection)
1226
1422
                            win.Bind(wx.EVT_COMBOBOX,     self.OnSetValue)
1227
1423
                        
1228
 
                        elif p.get('prompt', '') ==  'mapset':
 
1424
                        elif prompt == 'mapset':
 
1425
                            if p.get('age', 'old') == 'old':
 
1426
                                new = False
 
1427
                            else:
 
1428
                                new = True
 
1429
                            
1229
1430
                            win = gselect.MapsetSelect(parent = which_panel,
1230
 
                                                       value = value)
1231
 
                            win.Bind(wx.EVT_COMBOBOX,     self.OnUpdateSelection)
1232
 
                            win.Bind(wx.EVT_COMBOBOX,     self.OnSetValue)
1233
 
                            
1234
 
                        elif p.get('prompt', '') ==  'dbase':
 
1431
                                                       value = value, new = new,
 
1432
                                                       multiple = p.get('multiple', False))
 
1433
                            textWin = win.GetTextCtrl()
 
1434
                            p['wxId'] = [ textWin.GetId(), win.GetId() ]
 
1435
                            
 
1436
                            textWin.Bind(wx.EVT_TEXT, self.OnSetValue)
 
1437
                            win.Bind(wx.EVT_TEXT, self.OnUpdateSelection)
 
1438
                            
 
1439
                        elif prompt == 'dbase':
1235
1440
                            win = gselect.DbaseSelect(parent = which_panel,
1236
1441
                                                      changeCallback = self.OnSetValue)
1237
1442
                            win.Bind(wx.EVT_TEXT, self.OnUpdateSelection)
1243
1448
                        except AttributeError:
1244
1449
                            pass
1245
1450
                    
 
1451
                    flags = wx.BOTTOM | wx.LEFT | wx.RIGHT
 
1452
                    if prompt == 'dbname':
 
1453
                        flags |= wx.EXPAND
1246
1454
                    which_sizer.Add(item = win, proportion = 0,
1247
 
                                    flag = wx.ADJUST_MINSIZE | wx.BOTTOM | wx.LEFT, border = 5)
 
1455
                                    flag = flags, border = 5)
1248
1456
                # color entry
1249
 
                elif p.get('prompt', '') in ('color',
1250
 
                                             'color_none'):
 
1457
                elif prompt == 'color':
1251
1458
                    default_color = (200,200,200)
1252
1459
                    label_color = _("Select Color")
1253
1460
                    if p.get('default','') !=  '':
1254
 
                        default_color, label_color = color_resolve(p['default'])
 
1461
                        default_color, label_color = utils.color_resolve(p['default'])
1255
1462
                    if p.get('value','') !=  '' and p.get('value','') != 'none': # parameter previously set
1256
 
                        default_color, label_color = color_resolve(p['value'])
1257
 
                    if p.get('prompt', '') ==  'color_none' or p.get('multiple', False):
 
1463
                        default_color, label_color = utils.color_resolve(p['value'])
 
1464
                    if p.get('element', '') == 'color_none' or p.get('multiple', False):
1258
1465
                        this_sizer = wx.BoxSizer(orient = wx.HORIZONTAL)
1259
1466
                    else:
1260
1467
                        this_sizer = which_sizer
1275
1482
 
1276
1483
                    btn_colour = csel.ColourSelect(parent = which_panel, id = wx.ID_ANY,
1277
1484
                                                   label = label_color, colour = default_color,
1278
 
                                                   pos = wx.DefaultPosition, size = (colorSize,-1))
 
1485
                                                   pos = wx.DefaultPosition, size = (colorSize, 32))
1279
1486
                    this_sizer.Add(item = btn_colour, proportion = 0,
1280
1487
                                   flag = wx.ADJUST_MINSIZE | wx.BOTTOM | wx.LEFT, border = 5)
1281
1488
                    btn_colour.Bind(csel.EVT_COLOURSELECT,  self.OnColorChange)
1282
1489
                    p['wxId'][0] = btn_colour.GetId()
1283
1490
 
1284
 
                    if p.get('prompt', '') ==  'color_none':
 
1491
                    if p.get('element', '') == 'color_none':
1285
1492
                        none_check = wx.CheckBox(which_panel, wx.ID_ANY, _("Transparent"))
1286
 
                        if p.get('value','') !=  '' and p.get('value',[''])[0] ==  "none":
 
1493
                        if p.get('value','')  == "none":
1287
1494
                            none_check.SetValue(True)
1288
1495
                        else:
1289
1496
                            none_check.SetValue(False)
1293
1500
                        none_check.Bind(wx.EVT_CHECKBOX, self.OnColorChange)
1294
1501
                        p['wxId'][2] = none_check.GetId()
1295
1502
 
 
1503
 
1296
1504
                # file selector
1297
 
                elif p.get('prompt','') !=  'color' and p.get('element', '') ==  'file':
1298
 
                    if p.get('age', 'new_file') == 'new_file':
 
1505
                elif p.get('prompt','') !=  'color' and p.get('prompt', '') == 'file':
 
1506
                    if p.get('age', 'new') == 'new':
1299
1507
                        fmode = wx.FD_SAVE
1300
1508
                    else:
1301
1509
                        fmode = wx.FD_OPEN
1302
 
                    fbb = filebrowse.FileBrowseButton(parent = which_panel, id = wx.ID_ANY, fileMask = '*',
 
1510
                    # check wildcard
 
1511
                    try:
 
1512
                        fExt = os.path.splitext(p.get('key_desc', ['*.*'])[0])[1]
 
1513
                    except:
 
1514
                        fExt = None
 
1515
                    if not fExt:
 
1516
                        fMask = '*'
 
1517
                    else:
 
1518
                        fMask = '%s files (*%s)|*%s|Files (*)|*' % (fExt[1:].upper(), fExt, fExt)
 
1519
                    fbb = filebrowse.FileBrowseButton(parent = which_panel, id = wx.ID_ANY, fileMask = fMask,
1303
1520
                                                      size = globalvar.DIALOG_GSELECT_SIZE, labelText = '',
1304
1521
                                                      dialogTitle = _('Choose %s') % \
1305
 
                                                          p.get('description',_('File')),
 
1522
                                                          p.get('description', _('file')).lower(),
1306
1523
                                                      buttonText = _('Browse'),
1307
1524
                                                      startDirectory = os.getcwd(), fileMode = fmode,
1308
1525
                                                      changeCallback = self.OnSetValue)
1316
1533
                    # a textctl and a button;
1317
1534
                    # we have to target the button here
1318
1535
                    p['wxId'] = [ fbb.GetChildren()[1].GetId() ]
1319
 
                    if p.get('age', 'new_file') == 'old_file' and \
1320
 
                            UserSettings.Get(group='cmd', key='interactiveInput', subkey='enabled'):
 
1536
                    if p.get('age', 'new') == 'old' and \
 
1537
                            p.get('prompt', '') == 'file' and p.get('element', '') == 'file' and \
 
1538
                            UserSettings.Get(group = 'cmd', key = 'interactiveInput', subkey = 'enabled'):
1321
1539
                        # widget for interactive input
1322
1540
                        ifbb = wx.TextCtrl(parent = which_panel, id = wx.ID_ANY,
1323
1541
                                           style = wx.TE_MULTILINE,
1330
1548
                        ifbb.Bind(wx.EVT_TEXT, self.OnFileText)
1331
1549
                        
1332
1550
                        btnLoad = wx.Button(parent = which_panel, id = wx.ID_ANY, label = _("&Load"))
 
1551
                        btnLoad.SetToolTipString(_("Load and edit content of a file"))
1333
1552
                        btnLoad.Bind(wx.EVT_BUTTON, self.OnFileLoad)
1334
 
                        btnSave = wx.Button(parent = which_panel, id = wx.ID_SAVEAS)
 
1553
                        btnSave = wx.Button(parent = which_panel, id = wx.ID_ANY, label = _("&Save as"))
 
1554
                        btnSave.SetToolTipString(_("Save content to a file for further use"))
1335
1555
                        btnSave.Bind(wx.EVT_BUTTON, self.OnFileSave)
1336
1556
                        
1337
 
                        which_sizer.Add(item = wx.StaticText(parent = which_panel, id = wx.ID_ANY,
1338
 
                                                             label = _('or enter values interactively')),
 
1557
                        fileContentLabel = wx.StaticText(parent=which_panel,
 
1558
                            id=wx.ID_ANY,
 
1559
                            label=_('or enter values directly:'))
 
1560
                        fileContentLabel.SetToolTipString(
 
1561
                            _("Enter file content directly instead of specifying"
 
1562
                              " a file."
 
1563
                              " Temporary file will be automatically created."))
 
1564
                        which_sizer.Add(item=fileContentLabel,
1339
1565
                                        proportion = 0,
1340
1566
                                        flag = wx.EXPAND | wx.RIGHT | wx.LEFT | wx.BOTTOM, border = 5)
1341
1567
                        which_sizer.Add(item = ifbb, proportion = 1,
1352
1578
                        p['wxId'].append(btnLoad.GetId())
1353
1579
                        p['wxId'].append(btnSave.GetId())
1354
1580
                
1355
 
            if self.parent.GetName() == 'MainFrame' and self.parent.modeler:
 
1581
                # directory selector
 
1582
                elif p.get('prompt','') != 'color' and p.get('prompt', '') == 'dir':
 
1583
                    fbb = filebrowse.DirBrowseButton(parent = which_panel, id = wx.ID_ANY,
 
1584
                                                     size = globalvar.DIALOG_GSELECT_SIZE, labelText = '',
 
1585
                                                     dialogTitle = _('Choose %s') % \
 
1586
                                                         p.get('description', _('Directory')),
 
1587
                                                     buttonText = _('Browse'),
 
1588
                                                     startDirectory = os.getcwd(),
 
1589
                                                     changeCallback = self.OnSetValue)
 
1590
                    value = self._getValue(p)
 
1591
                    if value:
 
1592
                        fbb.SetValue(value) # parameter previously set
 
1593
                    which_sizer.Add(item = fbb, proportion = 0,
 
1594
                                    flag = wx.EXPAND | wx.RIGHT, border = 5)
 
1595
                    
 
1596
                    # A file browse button is a combobox with two children:
 
1597
                    # a textctl and a button;
 
1598
                    # we have to target the button here
 
1599
                    p['wxId'] = [ fbb.GetChildren()[1].GetId() ]
 
1600
                    
 
1601
                # interactive inserting of coordinates from map window
 
1602
                elif prompt == 'coords':
 
1603
                    # interactive inserting if layer manager is accessible
 
1604
                    if self._giface:
 
1605
                        win = gselect.CoordinatesSelect(parent = which_panel,
 
1606
                                                        giface = self._giface,
 
1607
                                                        multiple =  p.get('multiple', False),
 
1608
                                                        param = p)
 
1609
                        p['wxId'] = [win.GetTextWin().GetId()]
 
1610
                        win.GetTextWin().Bind(wx.EVT_TEXT, self.OnSetValue)
 
1611
                        # bind closing event because destructor is not working properly
 
1612
                        if hasattr(self.parent, 'dialogClosing'):
 
1613
                            self.parent.dialogClosing.connect(win.OnClose)
 
1614
                    
 
1615
                    # normal text field
 
1616
                    else:
 
1617
                        win = wx.TextCtrl(parent = which_panel)
 
1618
                        p['wxId'] = [win.GetId()]
 
1619
                        win.Bind(wx.EVT_TEXT, self.OnSetValue)
 
1620
                    
 
1621
                    which_sizer.Add(item = win, 
 
1622
                                    proportion = 0,
 
1623
                                    flag = wx.EXPAND | wx.BOTTOM | wx.LEFT | wx.RIGHT, 
 
1624
                                    border = 5)
 
1625
                elif prompt in ('colortable', 'barscale', 'northarrow'):
 
1626
                    if prompt == 'colortable':
 
1627
                        cb = ColorTablesComboBox(parent=which_panel, value=p.get('default',''),
 
1628
                                                 size=globalvar.DIALOG_COMBOBOX_SIZE,
 
1629
                                                 choices=valuelist)
 
1630
                    elif prompt == 'barscale':
 
1631
                        cb = BarscalesComboBox(parent=which_panel, value=p.get('default',''),
 
1632
                                               size=globalvar.DIALOG_COMBOBOX_SIZE,
 
1633
                                               choices=valuelist)
 
1634
                    elif prompt == 'northarrow':
 
1635
                        cb = NArrowsComboBox(parent=which_panel, value=p.get('default',''),
 
1636
                                             size=globalvar.DIALOG_COMBOBOX_SIZE,
 
1637
                                             choices=valuelist)
 
1638
                    
 
1639
                    value = self._getValue(p)
 
1640
                    if value:
 
1641
                        cb.SetValue(value) # parameter previously set
 
1642
                    which_sizer.Add(item = cb, proportion = 0,
 
1643
                                    flag = wx.ADJUST_MINSIZE | wx.BOTTOM | wx.LEFT, border = 5)
 
1644
                    p['wxId'] = [cb.GetId(), cb.GetTextCtrl().GetId()]
 
1645
                    cb.Bind(wx.EVT_COMBOBOX, self.OnSetValue)
 
1646
                    cb.GetTextCtrl().Bind(wx.EVT_TEXT, self.OnSetValue)
 
1647
                    if p.get('guidependency', ''):
 
1648
                        cb.Bind(wx.EVT_COMBOBOX, self.OnUpdateSelection)
 
1649
 
 
1650
            if self.parent.GetName() == 'MainFrame' and (self._giface and hasattr(self._giface, "_model")):
1356
1651
                parChk = wx.CheckBox(parent = which_panel, id = wx.ID_ANY,
1357
1652
                                     label = _("Parameterized in model"))
1358
1653
                parChk.SetName('ModelParam')
1372
1667
                        tooltip +=  2 * os.linesep
1373
1668
                    else:
1374
1669
                        tooltip = ''
1375
 
                    if len(p['values']) ==  len(p['values_desc']):
 
1670
                    if len(p['values']) == len(p['values_desc']):
1376
1671
                        for i in range(len(p['values'])):
1377
1672
                            tooltip +=  p['values'][i] + ': ' + p['values_desc'][i] + os.linesep
1378
1673
                    tooltip.strip(os.linesep)
1379
1674
                if tooltip:
1380
1675
                    title_txt.SetToolTipString(tooltip)
1381
1676
 
1382
 
            if p ==  first_param:
 
1677
            if p == first_param:
1383
1678
                if 'wxId' in p and len(p['wxId']) > 0:
1384
1679
                    win = self.FindWindowById(p['wxId'][0])
1385
1680
                    win.SetFocus()
1395
1690
        pColumn = []
1396
1691
        pGroup = None
1397
1692
        pSubGroup = None
 
1693
        pSigFile = []
1398
1694
        pDbase = None
1399
1695
        pLocation = None
1400
1696
        pMapset = None
1401
1697
        for p in self.task.params:
1402
 
            if p.get('gisprompt', False) ==  False:
1403
 
                continue
1404
 
            
1405
 
            prompt = p.get('element', '')
1406
 
            if prompt in ('cell', 'vector'):
 
1698
            guidep = p.get('guidependency', '')
 
1699
            
 
1700
            if guidep:
 
1701
                # fixed options dependency defined
 
1702
                options = guidep.split(',')
 
1703
                for opt in options:
 
1704
                    pOpt = self.task.get_param(opt, element = 'name', raiseError = False)
 
1705
                    if pOpt and id:
 
1706
                        if 'wxId-bind' not in p:
 
1707
                            p['wxId-bind'] = list()
 
1708
                        p['wxId-bind'] +=  pOpt['wxId']
 
1709
                continue
 
1710
            if p.get('gisprompt', False) == False:
 
1711
                continue
 
1712
            
 
1713
            prompt = p.get('prompt', '')
 
1714
            if prompt in ('raster', 'vector'):
1407
1715
                name = p.get('name', '')
1408
1716
                if name in ('map', 'input'):
1409
1717
                    pMap = p
1410
 
            elif prompt ==  'layer':
 
1718
            elif prompt == 'layer':
1411
1719
                pLayer.append(p)
1412
 
            elif prompt ==  'dbcolumn':
 
1720
            elif prompt == 'dbcolumn':
1413
1721
                pColumn.append(p)
1414
 
            elif prompt ==  'dbdriver':
 
1722
            elif prompt == 'dbdriver':
1415
1723
                pDriver = p
1416
 
            elif prompt ==  'dbname':
 
1724
            elif prompt == 'dbname':
1417
1725
                pDatabase = p
1418
 
            elif prompt ==  'dbtable':
 
1726
            elif prompt == 'dbtable':
1419
1727
                pTable = p
1420
 
            elif prompt ==  'group':
 
1728
            elif prompt == 'group':
1421
1729
                pGroup = p
1422
 
            elif prompt ==  'subgroup':
 
1730
            elif prompt == 'subgroup':
1423
1731
                pSubGroup = p
1424
 
            elif prompt ==  'dbase':
 
1732
            elif prompt == 'sigfile':
 
1733
                pSigFile.append(p)
 
1734
            elif prompt == 'dbase':
1425
1735
                pDbase = p
1426
 
            elif prompt ==  'location':
 
1736
            elif prompt == 'location':
1427
1737
                pLocation = p
1428
 
            elif prompt ==  'mapset':
 
1738
            elif prompt == 'mapset':
1429
1739
                pMapset = p
1430
1740
        
 
1741
        # collect ids
1431
1742
        pColumnIds = []
1432
1743
        for p in pColumn:
1433
 
            pColumnIds +=  p['wxId']
 
1744
            pColumnIds += p['wxId']
1434
1745
        pLayerIds = []
1435
1746
        for p in pLayer:
1436
 
            pLayerIds +=  p['wxId']
 
1747
            pLayerIds += p['wxId']
 
1748
        pSigFileIds = []
 
1749
        for p in pSigFile:
 
1750
            pSigFileIds += p['wxId']
1437
1751
        
 
1752
        # set wxId-bindings
1438
1753
        if pMap:
1439
 
            pMap['wxId-bind'] = copy.copy(pColumnIds)
 
1754
            pMap['wxId-bind'] = []
1440
1755
            if pLayer:
1441
1756
                pMap['wxId-bind'] +=  pLayerIds
 
1757
            pMap['wxId-bind'] += copy.copy(pColumnIds)
1442
1758
        if pLayer:
1443
1759
            for p in pLayer:
1444
1760
                p['wxId-bind'] = copy.copy(pColumnIds)
1453
1769
            pTable['wxId-bind'] = pColumnIds
1454
1770
        
1455
1771
        if pGroup and pSubGroup:
1456
 
            pGroup['wxId-bind'] = pSubGroup['wxId']
1457
 
 
 
1772
            if pSigFile:
 
1773
                pGroup['wxId-bind'] = pSigFileIds + pSubGroup['wxId']
 
1774
                pSubGroup['wxId-bind'] = pSigFileIds
 
1775
            else:
 
1776
                pGroup['wxId-bind'] = pSubGroup['wxId']
 
1777
        
1458
1778
        if pDbase and pLocation:
1459
1779
            pDbase['wxId-bind'] = pLocation['wxId']
1460
1780
 
1464
1784
        if pLocation and pMapset and pMap:
1465
1785
            pLocation['wxId-bind'] +=  pMap['wxId']
1466
1786
            pMapset['wxId-bind'] = pMap['wxId']
1467
 
        
1468
 
        #
1469
 
        # determine panel size
1470
 
        #
 
1787
        #
 
1788
        # determine panel size
 
1789
        #
1471
1790
        maxsizes = (0, 0)
1472
1791
        for section in sections:
1473
1792
            tab[section].SetSizer(tabsizer[section])
1482
1801
        for section in sections:
1483
1802
            tab[section].SetMinSize((self.constrained_size[0], self.panelMinHeight))
1484
1803
        
1485
 
        if self.manual_tab.IsLoaded():
1486
 
            self.manual_tab.SetMinSize((self.constrained_size[0], self.panelMinHeight))
1487
 
        
 
1804
        
 
1805
        # add pages to notebook
 
1806
        imageList = wx.ImageList(16, 16)
 
1807
        self.notebook.AssignImageList(imageList)
 
1808
 
 
1809
        for section in sections:
 
1810
            self.notebook.AddPage(page = tab[section], text = section, name = section)
 
1811
            index = self.AddBitmapToImageList(section, imageList)
 
1812
            if index >= 0:
 
1813
                self.notebook.SetPageImage(section, index)
 
1814
 
 
1815
        # are we running from command line?
 
1816
        ### add 'command output' tab regardless standalone dialog
 
1817
        if self.parent.GetName() == "MainFrame" and self.parent.get_dcmd is None:
 
1818
            from core.gconsole import GConsole, EVT_CMD_RUN, EVT_CMD_DONE
 
1819
            from gui_core.goutput import GConsoleWindow
 
1820
            self._gconsole = GConsole(guiparent = self.notebook, giface = self._giface)
 
1821
            self.goutput = GConsoleWindow(parent = self.notebook, gconsole = self._gconsole, margin = False)
 
1822
            self._gconsole.Bind(EVT_CMD_RUN,
 
1823
                                lambda event:
 
1824
                                    self._switchPageHandler(event=event, notification=Notification.MAKE_VISIBLE))
 
1825
            self._gconsole.Bind(EVT_CMD_DONE,
 
1826
                                lambda event:
 
1827
                                    self._switchPageHandler(event = event, notification=Notification.RAISE_WINDOW))
 
1828
            self.outpage = self.notebook.AddPage(page = self.goutput, text = _("Command output"), name = 'output')
 
1829
        else:
 
1830
            self.goutput = None
 
1831
            self._gconsole = None
 
1832
 
 
1833
        self.manualTab = HelpPanel(parent = self.notebook, command = self.task.get_name())
 
1834
        if not self.manualTab.GetFile():
 
1835
            self.manualTab.Hide()
 
1836
        else:
 
1837
            self.notebook.AddPage(page = self.manualTab, text = _("Manual"), name = 'manual')
 
1838
            index = self.AddBitmapToImageList(section = 'manual', imageList = imageList)
 
1839
            if index >= 0:
 
1840
                self.notebook.SetPageImage('manual', index)
 
1841
        
 
1842
        if self.manualTab.IsLoaded():
 
1843
            self.manualTab.SetMinSize((self.constrained_size[0], self.panelMinHeight))
 
1844
 
 
1845
        self.notebook.SetSelection(0)
 
1846
 
 
1847
        panelsizer.Add(item = self.notebook, proportion = 1, flag = wx.EXPAND)
1488
1848
        self.SetSizer(panelsizer)
1489
1849
        panelsizer.Fit(self.notebook)
1490
1850
        
1491
1851
        self.Bind(EVT_DIALOG_UPDATE, self.OnUpdateDialog)
1492
1852
 
1493
1853
    def _getValue(self, p):
1494
 
        """!Get value or default value of given parameter
 
1854
        """Get value or default value of given parameter
1495
1855
 
1496
 
        @param p parameter directory
 
1856
        :param p: parameter directory
1497
1857
        """
1498
1858
        if p.get('value', '') !=  '':
1499
1859
            return p['value']
1500
1860
        return p.get('default', '')
1501
1861
        
1502
1862
    def OnFileLoad(self, event):
1503
 
        """!Load file to interactive input"""
 
1863
        """Load file to interactive input"""
1504
1864
        me = event.GetId()
1505
1865
        win = dict()
1506
1866
        for p in self.task.params:
1519
1879
            return
1520
1880
        
1521
1881
        data = ''
1522
 
        f = open(path, "r")
 
1882
        try:
 
1883
            f = open(path, "r")
 
1884
        except IOError as e:
 
1885
            gcmd.GError(parent = self, showTraceback = False,
 
1886
                        message = _("Unable to load file.\n\nReason: %s") % e)
 
1887
            return
 
1888
        
1523
1889
        try:
1524
1890
            data = f.read()
1525
1891
        finally:
1528
1894
        win['text'].SetValue(data)
1529
1895
        
1530
1896
    def OnFileSave(self, event):
1531
 
        """!Save interactive input to the file"""
 
1897
        """Save interactive input to the file"""
1532
1898
        wId = event.GetId()
1533
1899
        win = {}
1534
1900
        for p in self.task.params:
1553
1919
 
1554
1920
        if dlg.ShowModal() == wx.ID_OK:
1555
1921
            path = dlg.GetPath()
1556
 
            f = open(path, "w")
 
1922
            enc = locale.getdefaultlocale()[1]
 
1923
            f = codecs.open(path, encoding = enc, mode = 'w', errors='replace')
1557
1924
            try:
1558
1925
                f.write(text + os.linesep)
1559
1926
            finally:
1572
1939
        win = self.FindWindowById(p['wxId'][0])
1573
1940
        if text:
1574
1941
            filename = win.GetValue()
1575
 
            if not filename:
1576
 
                # outFile = tempfile.NamedTemporaryFile(mode = 'w+b')
 
1942
            if not filename or filename == p['default']:  # m.proj has - as default
1577
1943
                filename = grass.tempfile()
1578
1944
                win.SetValue(filename)
1579
1945
                
1580
 
            f = open(filename, "w")
 
1946
            enc = locale.getdefaultlocale()[1]
 
1947
            f = codecs.open(filename, encoding = enc, mode = 'w', errors='replace')
1581
1948
            try:
1582
1949
                f.write(text)
1583
1950
                if text[-1] != os.linesep:
1587
1954
        else:
1588
1955
            win.SetValue('')
1589
1956
        
 
1957
    def OnVectorFormat(self, event):
 
1958
        """Change vector format (native / ogr).
 
1959
 
 
1960
        Currently unused.        
 
1961
        """
 
1962
        sel = event.GetSelection()
 
1963
        idEvent = event.GetId()
 
1964
        p = self.task.get_param(value = idEvent, element = 'wxId', raiseError = False)
 
1965
        if not p:
 
1966
            return # should not happen
 
1967
        
 
1968
        # detect windows
 
1969
        winNative = None
 
1970
        winOgr = None
 
1971
        for id in p['wxId']:
 
1972
            if id == idEvent:
 
1973
                continue
 
1974
            name = self.FindWindowById(id).GetName()
 
1975
            if name == 'Select':
 
1976
                winNative = self.FindWindowById(id + 1)  # fix the mystery (also in nviz_tools.py)
 
1977
            elif name == 'OgrSelect':
 
1978
                winOgr = self.FindWindowById(id)
 
1979
        
 
1980
        # enable / disable widgets & update values
 
1981
        rbox = self.FindWindowByName('VectorFormat')
 
1982
        self.hsizer.Remove(rbox)
 
1983
        if sel == 0:   # -> native
 
1984
            winOgr.Hide()
 
1985
            self.hsizer.Remove(winOgr)
 
1986
            
 
1987
            self.hsizer.Add(item = winNative,
 
1988
                            flag = wx.ADJUST_MINSIZE | wx.BOTTOM | wx.LEFT | wx.RIGHT | wx.TOP | wx.ALIGN_TOP,
 
1989
                            border = 5)
 
1990
            winNative.Show()
 
1991
            p['value'] = winNative.GetValue()
 
1992
        
 
1993
        elif sel == 1: # -> OGR
 
1994
            sizer = wx.BoxSizer(wx.VERTICAL)
 
1995
            
 
1996
            winNative.Hide()
 
1997
            self.hsizer.Remove(winNative)
 
1998
 
 
1999
            sizer.Add(item = winOgr)
 
2000
            winOgr.Show()
 
2001
            p['value'] = winOgr.GetDsn()
 
2002
            
 
2003
            self.hsizer.Add(item = sizer,
 
2004
                            flag = wx.ADJUST_MINSIZE | wx.BOTTOM | wx.LEFT | wx.RIGHT | wx.TOP | wx.ALIGN_TOP,
 
2005
                            border = 5)
 
2006
        
 
2007
        self.hsizer.Add(item = rbox,
 
2008
                        flag = wx.ADJUST_MINSIZE | wx.BOTTOM | wx.LEFT |
 
2009
                        wx.RIGHT | wx.ALIGN_TOP,
 
2010
                        border = 5)
 
2011
        
 
2012
        self.hsizer.Layout()
 
2013
        self.Layout()
 
2014
        self.OnUpdateValues()
 
2015
        self.OnUpdateSelection(event)
 
2016
        
1590
2017
    def OnUpdateDialog(self, event):
1591
2018
        for fn, kwargs in event.data.iteritems():
1592
2019
            fn(**kwargs)
1594
2021
        self.parent.updateValuesHook()
1595
2022
        
1596
2023
    def OnVerbosity(self, event):
1597
 
        """!Verbosity level changed"""
 
2024
        """Verbosity level changed"""
1598
2025
        verbose = self.FindWindowById(self.task.get_flag('verbose')['wxId'][0])
1599
2026
        quiet = self.FindWindowById(self.task.get_flag('quiet')['wxId'][0])
1600
2027
        if event.IsChecked():
1601
 
            if event.GetId() ==  verbose.GetId():
 
2028
            if event.GetId() == verbose.GetId():
1602
2029
                if quiet.IsChecked():
1603
2030
                    quiet.SetValue(False)
1604
2031
                    self.task.get_flag('quiet')['value'] = False
1616
2043
            sel = event.GetSelection()
1617
2044
        
1618
2045
        idx = self.notebook.GetPageIndexByName('manual')
1619
 
        if idx > -1 and sel ==  idx:
 
2046
        if idx > -1 and sel == idx:
1620
2047
            # calling LoadPage() is strangely time-consuming (only first call)
1621
2048
            # FIXME: move to helpPage.__init__()
1622
 
            if not self.manual_tab.IsLoaded():
 
2049
            if not self.manualTab.IsLoaded():
1623
2050
                wx.Yield()
1624
 
                self.manual_tab.LoadPage()
 
2051
                self.manualTab.LoadPage()
1625
2052
 
1626
2053
        self.Layout()
1627
2054
 
 
2055
        if event:
 
2056
            # skip is needed for wx.Notebook on Windows
 
2057
            event.Skip()
 
2058
            # this is needed for dialogs launched from layer manager
 
2059
            # event is somehow propagated?
 
2060
            event.StopPropagation()
 
2061
 
 
2062
    def _switchPageHandler(self, event, notification):
 
2063
        self._switchPage(notification=notification)
 
2064
        event.Skip()
 
2065
 
 
2066
    def _switchPage(self, notification):
 
2067
        """Manages @c 'output' notebook page according to event notification."""
 
2068
        if notification == Notification.HIGHLIGHT:
 
2069
            self.notebook.HighlightPageByName('output')
 
2070
        if notification == Notification.MAKE_VISIBLE:
 
2071
            self.notebook.SetSelectionByName('output')
 
2072
        if notification == Notification.RAISE_WINDOW:
 
2073
            self.notebook.SetSelectionByName('output')
 
2074
            self.SetFocus()
 
2075
            self.Raise()
 
2076
 
1628
2077
    def OnColorChange(self, event):
1629
2078
        myId = event.GetId()
1630
2079
        for p in self.task.params:
1631
2080
            if 'wxId' in p and myId in p['wxId']:
1632
2081
                multiple = p['wxId'][1] is not None # multiple colors
1633
 
                hasTransp = p['wxId'][2] is not None
 
2082
                hasTansp = p['wxId'][2] is not None
1634
2083
                if multiple:
1635
2084
                    # selected color is added at the end of textCtrl
1636
2085
                    colorchooser = wx.FindWindowById(p['wxId'][0])
1637
2086
                    new_color = colorchooser.GetValue()[:]
1638
 
                    new_label = rgb2str.get(new_color, ':'.join(map(str, new_color)))
 
2087
                    new_label = utils.rgb2str.get(new_color, ':'.join(map(str, new_color)))
1639
2088
                    textCtrl = wx.FindWindowById(p['wxId'][1])
1640
2089
                    val = textCtrl.GetValue()
1641
2090
                    sep = ','
1644
2093
                    val += new_label
1645
2094
                    textCtrl.SetValue(val)
1646
2095
                    p[ 'value' ] = val
1647
 
                elif hasTransp and wx.FindWindowById(p['wxId'][2]).GetValue():
 
2096
                elif hasTansp and wx.FindWindowById(p['wxId'][2]).GetValue():
1648
2097
                    p[ 'value' ] = 'none'
1649
2098
                else:
1650
2099
                    colorchooser = wx.FindWindowById(p['wxId'][0])
1651
2100
                    new_color = colorchooser.GetValue()[:]
1652
2101
                    # This is weird: new_color is a 4-tuple and new_color[:] is a 3-tuple
1653
2102
                    # under wx2.8.1
1654
 
                    new_label = rgb2str.get(new_color, ':'.join(map(str,new_color)))
 
2103
                    new_label = utils.rgb2str.get(new_color, ':'.join(map(str,new_color)))
1655
2104
                    colorchooser.SetLabel(new_label)
1656
2105
                    colorchooser.SetColour(new_color)
1657
2106
                    colorchooser.Refresh()
1659
2108
        self.OnUpdateValues()
1660
2109
 
1661
2110
    def OnUpdateValues(self, event = None):
1662
 
        """!If we were part of a richer interface, report back the
 
2111
        """If we were part of a richer interface, report back the
1663
2112
        current command being built.
1664
2113
 
1665
2114
        This method should be set by the parent of this panel if
1669
2118
        pass
1670
2119
 
1671
2120
    def OnCheckBoxMulti(self, event):
1672
 
        """!Fill the values as a ','-separated string according to
 
2121
        """Fill the values as a ','-separated string according to
1673
2122
        current status of the checkboxes.
1674
2123
        """
1675
2124
        me = event.GetId()
1700
2149
        theParam['value'] = ','.join(currentValueList)
1701
2150
 
1702
2151
        self.OnUpdateValues()
 
2152
        event.Skip()
1703
2153
 
1704
2154
    def OnSetValue(self, event):
1705
 
        """!Retrieve the widget value and set the task value field
 
2155
        """Retrieve the widget value and set the task value field
1706
2156
        accordingly.
1707
 
        
 
2157
 
1708
2158
        Use for widgets that have a proper GetValue() method, i.e. not
1709
2159
        for selectors.
1710
2160
        """
1723
2173
        if not found:
1724
2174
            return
1725
2175
        
1726
 
        if name in ('DriverSelect', 'TableSelect',
1727
 
                    'LocationSelect', 'MapsetSelect', 'ProjSelect'):
1728
 
            porf['value'] = me.GetStringSelection()
1729
 
        elif name ==  'GdalSelect':
 
2176
        if name == 'GdalSelect':
1730
2177
            porf['value'] = event.dsn
1731
 
        elif name ==  'ModelParam':
 
2178
        elif name == 'ModelParam':
1732
2179
            porf['parameterized'] = me.IsChecked()
1733
 
        elif name ==  'LayerSelect':
1734
 
            porf['value'] = me.GetValue()
1735
2180
        else:
1736
 
            porf['value'] = me.GetValue()
 
2181
            if isinstance(me, wx.SpinCtrl):
 
2182
                porf['value'] = str(me.GetValue())
 
2183
            else:
 
2184
                porf['value'] = me.GetValue()
1737
2185
        
1738
2186
        self.OnUpdateValues(event)
1739
2187
        
1740
2188
        event.Skip()
1741
2189
        
1742
2190
    def OnSetSymbol(self, event):
1743
 
        """!Shows dialog for symbol selection"""
 
2191
        """Shows dialog for symbol selection"""
1744
2192
        myId = event.GetId()
1745
2193
        
1746
2194
        for p in self.task.params:
1747
2195
            if 'wxId' in p and myId in p['wxId']:
1748
2196
                from gui_core.dialogs import SymbolDialog
1749
 
                dlg = SymbolDialog(self, symbolPath = globalvar.ETCSYMBOLDIR,
 
2197
                dlg = SymbolDialog(self, symbolPath = globalvar.SYMBDIR,
1750
2198
                                   currentSymbol = p['value'])
1751
2199
                if dlg.ShowModal() == wx.ID_OK:
1752
2200
                    img = dlg.GetSelectedSymbolPath()
1761
2209
                    self.OnUpdateValues(event)
1762
2210
                    
1763
2211
                dlg.Destroy()
1764
 
 
 
2212
 
 
2213
    def OnTimelineTool(self, event):
 
2214
        """Show Timeline Tool with dataset(s) from gselect.
 
2215
 
 
2216
        .. todo::
 
2217
            update from gselect automatically        
 
2218
        """
 
2219
        myId = event.GetId()
 
2220
 
 
2221
        for p in self.task.params:
 
2222
            if 'wxId' in p and myId in p['wxId']:
 
2223
                select = self.FindWindowById(p['wxId'][0])
 
2224
                if not select.GetValue():
 
2225
                    gcmd.GMessage(parent=self, message=_("No dataset given."))
 
2226
                    return
 
2227
                datasets = select.GetValue().split(',')
 
2228
                from timeline import frame
 
2229
                frame.run(parent=self, datasets=datasets)
 
2230
 
1765
2231
    def OnUpdateSelection(self, event):
1766
 
        """!Update dialog (layers, tables, columns, etc.)
 
2232
        """Update dialog (layers, tables, columns, etc.)
1767
2233
        """
1768
2234
        if not hasattr(self.parent, "updateThread"):
1769
2235
            if event:
1783
2249
                                            self.task)
1784
2250
            
1785
2251
    def createCmd(self, ignoreErrors = False, ignoreRequired = False):
1786
 
        """!Produce a command line string (list) or feeding into GRASS.
 
2252
        """Produce a command line string (list) or feeding into GRASS.
1787
2253
 
1788
 
        @param ignoreErrors True then it will return whatever has been
1789
 
        built so far, even though it would not be a correct command
1790
 
        for GRASS
 
2254
        :param ignoreErrors: True then it will return whatever has been
 
2255
                             built so far, even though it would not be
 
2256
                             a correct command for GRASS
1791
2257
        """
1792
2258
        try:
1793
2259
            cmd = self.task.get_cmd(ignoreErrors = ignoreErrors,
1794
2260
                                   ignoreRequired = ignoreRequired)
1795
 
        except ValueError, err:
 
2261
        except ValueError as err:
1796
2262
            dlg = wx.MessageDialog(parent = self,
1797
2263
                                   message = unicode(err),
1798
2264
                                   caption = _("Error in %s") % self.task.name,
1816
2282
            
1817
2283
        event.Skip()
1818
2284
        
 
2285
    def AddBitmapToImageList(self, section, imageList):
 
2286
        iconTheme = UserSettings.Get(group = 'appearance', key = 'iconTheme', subkey = 'type')
 
2287
        iconSectionDict = {'manual': os.path.join(globalvar.ICONDIR, iconTheme, 'help.png')}
 
2288
        if section in iconSectionDict.keys():
 
2289
            image = wx.Image(iconSectionDict[section]).Scale(16, 16, wx.IMAGE_QUALITY_HIGH)
 
2290
            idx = imageList.Add(wx.BitmapFromImage(image))
 
2291
            return idx
 
2292
 
 
2293
        return -1
 
2294
 
 
2295
 
1819
2296
class GUI:
1820
 
    def __init__(self, parent = None, show = True, modal = False,
 
2297
    def __init__(self, parent = None, giface = None, show = True, modal = False,
1821
2298
                 centreOnParent = False, checkError = False):
1822
 
        """!Parses GRASS commands when module is imported and used from
 
2299
        """Parses GRASS commands when module is imported and used from
1823
2300
        Layer Manager.
1824
2301
        """
1825
2302
        self.parent = parent
1826
2303
        self.show   = show
1827
2304
        self.modal  = modal
 
2305
        self._giface = giface
1828
2306
        self.centreOnParent = centreOnParent
1829
2307
        self.checkError     = checkError
1830
2308
        
1838
2316
            _blackList['enabled'] = False
1839
2317
        
1840
2318
    def GetCmd(self):
1841
 
        """!Get validated command"""
 
2319
        """Get validated command"""
1842
2320
        return self.cmd
1843
2321
    
1844
 
    def ParseCommand(self, cmd, gmpath = None, completed = None):
1845
 
        """!Parse command
 
2322
    def ParseCommand(self, cmd, completed = None):
 
2323
        """Parse command
1846
2324
        
1847
2325
        Note: cmd is given as list
1848
2326
        
1850
2328
         - add key name for first parameter if not given
1851
2329
         - change mapname to mapname@mapset
1852
2330
        """
1853
 
        start = time.time()
1854
2331
        dcmd_params = {}
1855
2332
        if completed == None:
1856
2333
            get_dcmd = None
1865
2342
        # parse the interface decription
1866
2343
        try:
1867
2344
            global _blackList
1868
 
            self.grass_task = gtask.parse_interface(gcmd.GetRealCmd(cmd[0]),
 
2345
            self.grass_task = gtask.parse_interface(cmd[0],
1869
2346
                                                    blackList = _blackList)
1870
 
        except (grass.ScriptError, ValueError), e:
 
2347
        except (grass.ScriptError, ValueError) as e:
1871
2348
            raise gcmd.GException(e.value)
1872
2349
        
1873
2350
        # if layer parameters previously set, re-insert them into dialog
1883
2360
            i = 0
1884
2361
            cmd_validated = [cmd[0]]
1885
2362
            for option in cmd[1:]:
1886
 
                if option[0] ==  '-': # flag
1887
 
                    if option[1] ==  '-':
 
2363
                if option[0] == '-': # flag
 
2364
                    if option[1] == '-':
1888
2365
                        self.grass_task.set_flag(option[2:], True)
1889
2366
                    else:
1890
2367
                        self.grass_task.set_flag(option[1], True)
1892
2369
                else: # parameter
1893
2370
                    try:
1894
2371
                        key, value = option.split('=', 1)
1895
 
                    except:
1896
 
                        params = self.grass_task.get_options()['params']
1897
 
                        if params:
 
2372
                    except ValueError:
 
2373
                        if self.grass_task.firstParam:
1898
2374
                            if i == 0: # add key name of first parameter if not given
1899
 
                                key = params[0]['name']
 
2375
                                key = self.grass_task.firstParam
1900
2376
                                value = option
1901
2377
                            else:
1902
2378
                                raise gcmd.GException, _("Unable to parse command '%s'") % ' '.join(cmd)
1903
2379
                        else:
1904
2380
                            continue
1905
2381
                    
1906
 
                    element = self.grass_task.get_param(key, raiseError = False)
1907
 
                    if not element:
 
2382
                    task = self.grass_task.get_param(key, raiseError = False)
 
2383
                    if not task:
1908
2384
                        err.append(_("%(cmd)s: parameter '%(key)s' not available") % \
1909
2385
                                       { 'cmd' : cmd[0],
1910
2386
                                         'key' : key })
1911
2387
                        continue
1912
 
                    element = element['element']
1913
 
                    
1914
 
                    if element in ['cell', 'vector']:
 
2388
                    multiple = task['multiple']
 
2389
                    element = task['element']
 
2390
                    # to filter out g.copy, g.rename
 
2391
                    key_desc = task['key_desc']
 
2392
                    # do we need to find mapset for each of multiple maps?
 
2393
                    if element in ['cell', 'vector'] and not multiple and len(key_desc) != 2:
1915
2394
                        # mapname -> mapname@mapset
1916
 
                        if '@' not in value:
 
2395
                        try:
 
2396
                            name, mapset = value.split('@')
 
2397
                        except ValueError:
1917
2398
                            mapset = grass.find_file(value, element)['mapset']
1918
2399
                            curr_mapset = grass.gisenv()['MAPSET']
1919
2400
                            if mapset and mapset !=  curr_mapset:
1927
2408
            cmd = cmd_validated
1928
2409
        
1929
2410
        if self.show is not None:
1930
 
            self.mf = TaskFrame(parent = self.parent, ID = wx.ID_ANY,
 
2411
            self.mf = TaskFrame(parent = self.parent, giface = self._giface,
1931
2412
                                task_description = self.grass_task,
1932
2413
                                get_dcmd = get_dcmd, layer = layer)
1933
2414
        else:
1958
2439
            return self.grass_task
1959
2440
    
1960
2441
    def GetCommandInputMapParamKey(self, cmd):
1961
 
        """!Get parameter key for input raster/vector map
1962
 
        
1963
 
        @param cmd module name
1964
 
        
1965
 
        @return parameter key
1966
 
        @return None on failure
 
2442
        """Get parameter key for input raster/vector map
 
2443
        
 
2444
        :param cmd: module name
 
2445
        
 
2446
        :return: parameter key
 
2447
        :return: None on failure
1967
2448
        """
1968
2449
        # parse the interface decription
1969
2450
        if not self.grass_task:
1970
 
            enc = locale.getdefaultlocale()[1]
1971
 
            if enc and enc.lower() == "cp932":
1972
 
                p = re.compile('encoding="' + enc + '"', re.IGNORECASE)
1973
 
                tree = etree.fromstring(p.sub('encoding="utf-8"',
1974
 
                                              gtask.get_interface_description(cmd).decode(enc).encode('utf-8')))
1975
 
            else:
1976
 
                tree = etree.fromstring(gtask.get_interface_description(cmd))
 
2451
            tree = etree.fromstring(gtask.get_interface_description(cmd))
1977
2452
            self.grass_task = gtask.processTask(tree).get_task()
1978
2453
            
1979
2454
            for p in self.grass_task.params:
1981
2456
                    age = p.get('age', '')
1982
2457
                    prompt = p.get('prompt', '')
1983
2458
                    element = p.get('element', '') 
1984
 
                    if age ==  'old' and \
 
2459
                    if age == 'old' and \
1985
2460
                            element in ('cell', 'grid3', 'vector') and \
1986
2461
                            prompt in ('raster', '3d-raster', 'vector'):
1987
2462
                        return p.get('name', None)
1988
2463
        return None
1989
2464
 
1990
2465
class GrassGUIApp(wx.App):
1991
 
    """!Stand-alone GRASS command GUI
 
2466
    """Stand-alone GRASS command GUI
1992
2467
    """
1993
2468
    def __init__(self, grass_task):
1994
2469
        self.grass_task = grass_task
1997
2472
    def OnInit(self):
1998
2473
        msg = self.grass_task.get_error_msg()
1999
2474
        if msg:
2000
 
            gcmd.GError(msg + '\n\nTry to set up GRASS_ADDON_PATH variable.')
 
2475
            gcmd.GError(msg + '\n\n' +
 
2476
                        _('Try to set up GRASS_ADDON_PATH or GRASS_ADDON_BASE variable.'))
2001
2477
            return True
2002
2478
        
2003
 
        self.mf = TaskFrame(parent = None, ID = wx.ID_ANY, task_description = self.grass_task)
 
2479
        self.mf = TaskFrame(parent = None, giface = None, task_description = self.grass_task)
2004
2480
        self.mf.CentreOnScreen()
2005
2481
        self.mf.Show(True)
2006
2482
        self.SetTopWindow(self.mf)
2007
2483
        
2008
2484
        return True
2009
2485
 
2010
 
if __name__ ==  "__main__":
2011
 
    import gettext
2012
 
    gettext.install('grasswxpy', os.path.join(os.getenv("GISBASE"), 'locale'), unicode = True)
2013
 
    
2014
 
    if len(sys.argv) ==  1:
2015
 
        sys.exit(_("usage: %s <grass command>") % sys.argv[0])
2016
 
    
 
2486
 
 
2487
USAGE_MESSAGE = """Usage:
 
2488
    {name} <grass module>
 
2489
    {name} <full path to file>
 
2490
    python {name} <grass module>
 
2491
Test:
 
2492
    python {name} test
 
2493
    python {name} g.region
 
2494
    python {name} "g.region -p"
 
2495
    python {name} temporal/t.list/t.list.py"""
 
2496
 
 
2497
 
 
2498
if __name__ == "__main__":
 
2499
    
 
2500
    if len(sys.argv) == 1:
 
2501
        sys.exit(_(USAGE_MESSAGE).format(name=sys.argv[0]))
 
2502
 
2017
2503
    if sys.argv[1] !=  'test':
2018
 
        q = wx.LogNull()
 
2504
        q = wx.LogNull()        
 
2505
        from core.debug import Debug
 
2506
        Debug.msg(1, "forms.py called using command: %s" % sys.argv[1])
2019
2507
        cmd = utils.split(sys.argv[1])
2020
 
        task = gtask.grassTask(gcmd.GetRealCmd(cmd[0]))
 
2508
        task = gtask.grassTask(cmd[0])
2021
2509
        task.set_options(cmd[1:])
 
2510
        Debug.msg(1, "forms.py opening form for: %s" % task.get_cmd(ignoreErrors=True))
2022
2511
        app = GrassGUIApp(task)
2023
2512
        app.MainLoop()
2024
2513
    else: #Test
2026
2515
        if os.getenv("GISBASE") is not None:
2027
2516
            task = gtask.grassTask("d.vect")
2028
2517
            task.get_param('map')['value'] = "map_name"
2029
 
            task.get_flag('v')['value'] = True
 
2518
            task.get_flag('i')['value'] = True
2030
2519
            task.get_param('layer')['value'] = 1
2031
 
            task.get_param('bcolor')['value'] = "red"
2032
 
            assert ' '.join(task.get_cmd()) ==  "d.vect -v map = map_name layer = 1 bcolor = red"
 
2520
            task.get_param('label_bcolor')['value'] = "red"
 
2521
            # the default parameter display is added automatically
 
2522
            assert ' '.join(task.get_cmd()) == "d.vect -i map=map_name layer=1 display=shape label_bcolor=red"
 
2523
            print "Creation of task successful"
2033
2524
        # Test interface building with handmade grassTask,
2034
2525
        # possibly outside of a GRASS session.
 
2526
        print "Now creating a module dialog (task frame)"
2035
2527
        task = gtask.grassTask()
2036
2528
        task.name = "TestTask"
2037
2529
        task.description = "This is an artificial grassTask() object intended for testing purposes."
2041
2533
            "name" : "text",
2042
2534
            "description" : "Descriptions go into tooltips if labels are present, like this one",
2043
2535
            "label" : "Enter some text",
 
2536
            "key_desc": ["value"],
 
2537
            "values_desc": []
2044
2538
            },{
2045
2539
            "name" : "hidden_text",
2046
2540
            "description" : "This text should not appear in the form",
2047
 
            "hidden" : True
 
2541
            "hidden" : True,
 
2542
            "key_desc": ["value"],
 
2543
            "values_desc": []
2048
2544
            },{
2049
2545
            "name" : "text_default",
2050
2546
            "description" : "Enter text to override the default",
2051
 
            "default" : "default text"
 
2547
            "default" : "default text",
 
2548
            "key_desc": ["value"],
 
2549
            "values_desc": []
2052
2550
            },{
2053
2551
            "name" : "text_prefilled",
2054
2552
            "description" : "You should see a friendly welcome message here",
2055
 
            "value" : "hello, world"
 
2553
            "value" : "hello, world",
 
2554
            "key_desc": ["value"],
 
2555
            "values_desc": []
2056
2556
            },{
2057
2557
            "name" : "plain_color",
2058
2558
            "description" : "This is a plain color, and it is a compulsory parameter",
2059
2559
            "required" : False,
2060
2560
            "gisprompt" : True,
2061
 
            "prompt" : "color"
 
2561
            "prompt" : "color",
 
2562
            "key_desc": ["value"],
 
2563
            "values_desc": []
2062
2564
            },{
2063
2565
            "name" : "transparent_color",
2064
2566
            "description" : "This color becomes transparent when set to none",
2065
2567
            "guisection" : "tab",
2066
2568
            "gisprompt" : True,
2067
 
            "prompt" : "color"
 
2569
            "prompt" : "color",
 
2570
            "key_desc": ["value"],
 
2571
            "values_desc": []
2068
2572
            },{
2069
2573
            "name" : "multi",
2070
2574
            "description" : "A multiple selection",
2074
2578
            'multiple': u'yes',
2075
2579
            'type': u'string',
2076
2580
            'value': '',
2077
 
            'values': ['red', 'green', u'yellow', u'blue', u'purple', u'other']
 
2581
            'values': ['red', 'green', u'yellow', u'blue', u'purple', u'other'],
 
2582
            "key_desc": ["value"],
 
2583
            "values_desc": []
2078
2584
            },{
2079
2585
            "name" : "single",
2080
2586
            "description" : "A single multiple-choice selection",
2081
2587
            'values': ['red', 'green', u'yellow', u'blue', u'purple', u'other'],
2082
 
            "guisection" : "tab"
 
2588
            "guisection" : "tab",
 
2589
            "key_desc": ["value"],
 
2590
            "values_desc": []
2083
2591
            },{
2084
2592
            "name" : "large_multi",
2085
2593
            "description" : "A large multiple selection",
2086
2594
            "gisprompt" : False,
2087
2595
            "multiple" : "yes",
2088
2596
            # values must be an array of strings
2089
 
            "values" : str2rgb.keys() + map(str, str2rgb.values())
 
2597
            "values" : utils.str2rgb.keys() + map(str, utils.str2rgb.values()),
 
2598
            "key_desc": ["value"],
 
2599
            "values_desc": []
2090
2600
            },{
2091
2601
            "name" : "a_file",
2092
2602
            "description" : "A file selector",
2093
2603
            "gisprompt" : True,
2094
 
            "element" : "file"
 
2604
            "element" : "file",
 
2605
            "key_desc": ["value"],
 
2606
            "values_desc": []
2095
2607
            }
2096
2608
            ]
2097
2609
        task.flags = [
2098
2610
            {
2099
2611
            "name" : "a",
2100
2612
            "description" : "Some flag, will appear in Main since it is required",
2101
 
            "required" : True
 
2613
            "required" : True,
 
2614
            "value" : False,
 
2615
            "suppress_required": False
2102
2616
            },{
2103
2617
            "name" : "b",
2104
2618
            "description" : "pre-filled flag, will appear in options since it is not required",
2105
 
            "value" : True
 
2619
            "value" : True,
 
2620
            "suppress_required": False
2106
2621
            },{
2107
2622
            "name" : "hidden_flag",
2108
2623
            "description" : "hidden flag, should not be changeable",
2109
2624
            "hidden" : "yes",
2110
 
            "value" : True
 
2625
            "value" : True,
 
2626
            "suppress_required": False
2111
2627
            }
2112
2628
            ]
2113
2629
        q = wx.LogNull()