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

« back to all changes in this revision

Viewing changes to gui/wxpython/gis_set.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:
1
 
"""!
 
1
"""
2
2
@package gis_set
3
3
 
4
4
GRASS start-up screen.
11
11
 - gis_set::GListBox
12
12
 - gis_set::StartUp
13
13
 
14
 
(C) 2006-2012 by the GRASS Development Team
 
14
(C) 2006-2014 by the GRASS Development Team
15
15
 
16
16
This program is free software under the GNU General Public License
17
17
(>=v2). Read the file COPYING that comes with GRASS for details.
28
28
import codecs
29
29
import getpass
30
30
 
31
 
### i18N
32
 
import gettext
33
 
gettext.install('grasswxpy', os.path.join(os.getenv("GISBASE"), 'locale'), unicode = True)
34
 
 
35
 
if __name__ == "__main__":
36
 
    sys.path.append(os.path.join(os.getenv('GISBASE'), 'etc', 'gui', 'wxpython'))
37
31
from core import globalvar
 
32
from core.utils import _
38
33
import wx
39
34
import wx.lib.mixins.listctrl as listmix
40
 
import wx.lib.scrolledpanel as scrolled
41
 
 
42
 
from gui_core.ghelp import HelpFrame
43
 
from core.gcmd      import GMessage, GError, DecodeString, RunCommand
44
 
from core.utils     import GetListOfLocations, GetListOfMapsets
 
35
 
 
36
from grass.script import core as grass
 
37
 
 
38
from core.gcmd import GMessage, GError, DecodeString, RunCommand
 
39
from core.utils import GetListOfLocations, GetListOfMapsets
45
40
from location_wizard.dialogs import RegionDef
46
41
from gui_core.dialogs import TextEntryDialog
47
 
from gui_core.widgets import GenericValidator
48
 
 
49
 
from grass.script import core as grass
 
42
from gui_core.widgets import GenericValidator, StaticWrapText
50
43
 
51
44
sys.stderr = codecs.getwriter('utf8')(sys.stderr)
52
45
 
 
46
 
53
47
class GRASSStartup(wx.Frame):
54
 
    """!GRASS start-up screen"""
 
48
    """GRASS start-up screen"""
55
49
    def __init__(self, parent = None, id = wx.ID_ANY, style = wx.DEFAULT_FRAME_STYLE):
56
50
 
57
51
        #
71
65
        wx.Frame.__init__(self, parent = parent, id = id, style = style)
72
66
        
73
67
        self.locale = wx.Locale(language = wx.LANGUAGE_DEFAULT)
74
 
        
75
 
        self.panel = scrolled.ScrolledPanel(parent = self, id = wx.ID_ANY)
76
 
        
 
68
 
 
69
        # scroll panel was used here but not properly and is probably not need
 
70
        # as long as it is not high too much
 
71
        self.panel = wx.Panel(parent=self, id=wx.ID_ANY)
 
72
 
77
73
        # i18N
78
 
        import gettext
79
 
        gettext.install('grasswxpy', os.path.join(os.getenv("GISBASE"), 'locale'), unicode = True)
80
74
 
81
75
        #
82
76
        # graphical elements
83
77
        #
84
78
        # image
85
79
        try:
86
 
            name = os.path.join(globalvar.ETCIMGDIR, "startup_banner.gif")
 
80
            if os.getenv('ISISROOT'):
 
81
                name = os.path.join(globalvar.GUIDIR, "images", "startup_banner_isis.png")
 
82
            else:
 
83
                name = os.path.join(globalvar.GUIDIR, "images", "startup_banner.png")
87
84
            self.hbitmap = wx.StaticBitmap(self.panel, wx.ID_ANY,
88
85
                                           wx.Bitmap(name = name,
89
 
                                                     type = wx.BITMAP_TYPE_GIF))
 
86
                                                     type = wx.BITMAP_TYPE_PNG))
90
87
        except:
91
 
            self.hbitmap = wx.StaticBitmap(self.panel, wx.ID_ANY, wx.EmptyBitmap(530,150))
 
88
            self.hbitmap = wx.StaticBitmap(self.panel, wx.ID_ANY, wx.BitmapFromImage(wx.EmptyImage(530,150)))
92
89
 
93
90
        # labels
94
91
        ### crashes when LOCATION doesn't exist
 
92
        # get version & revision
95
93
        versionFile = open(os.path.join(globalvar.ETCDIR, "VERSIONNUMBER"))
96
 
        grassVersion = versionFile.readline().split(' ')[0].rstrip('\n')
 
94
        versionLine = versionFile.readline().rstrip('\n')
97
95
        versionFile.close()
98
 
        
99
 
        self.select_box = wx.StaticBox (parent = self.panel, id = wx.ID_ANY,
100
 
                                        label = " %s " % _("Choose project location and mapset"))
101
 
 
102
 
        self.manage_box = wx.StaticBox (parent = self.panel, id = wx.ID_ANY,
103
 
                                        label = " %s " % _("Manage"))
104
 
        self.lwelcome = wx.StaticText(parent = self.panel, id = wx.ID_ANY,
105
 
                                      label = _("Welcome to GRASS GIS %s\n"
106
 
                                              "The world's leading open source GIS") % grassVersion,
107
 
                                      style = wx.ALIGN_CENTRE)
108
 
        self.ltitle = wx.StaticText(parent = self.panel, id = wx.ID_ANY,
109
 
                                    label = _("Select an existing project location and mapset\n"
110
 
                                            "or define a new location"),
111
 
                                    style = wx.ALIGN_CENTRE)
112
 
        self.ldbase = wx.StaticText(parent = self.panel, id = wx.ID_ANY,
113
 
                                    label = _("GIS Data Directory:"))
114
 
        self.llocation = wx.StaticText(parent = self.panel, id = wx.ID_ANY,
115
 
                                       label = _("Project location\n(projection/coordinate system)"),
116
 
                                       style = wx.ALIGN_CENTRE)
117
 
        self.lmapset = wx.StaticText(parent = self.panel, id = wx.ID_ANY,
118
 
                                     label = _("Accessible mapsets\n(directories of GIS files)"),
119
 
                                     style = wx.ALIGN_CENTRE)
120
 
        self.lcreate = wx.StaticText(parent = self.panel, id = wx.ID_ANY,
121
 
                                     label = _("Create new mapset\nin selected location"),
122
 
                                     style = wx.ALIGN_CENTRE)
123
 
        self.ldefine = wx.StaticText(parent = self.panel, id = wx.ID_ANY,
124
 
                                     label = _("Define new location"),
125
 
                                     style = wx.ALIGN_CENTRE)
126
 
        self.lmanageloc = wx.StaticText(parent = self.panel, id = wx.ID_ANY,
127
 
                                        label = _("Rename/delete selected\nmapset or location"),
128
 
                                        style = wx.ALIGN_CENTRE)
 
96
        try:
 
97
            grassVersion, grassRevision = versionLine.split(' ', 1)
 
98
            if grassVersion.endswith('svn'):
 
99
                grassRevisionStr = ' (%s)' % grassRevision
 
100
            else:
 
101
                grassRevisionStr = ''
 
102
        except ValueError:
 
103
            grassVersion = versionLine
 
104
            grassRevisionStr = ''
 
105
        
 
106
        self.gisdbase_box = wx.StaticBox(parent=self.panel, id=wx.ID_ANY,
 
107
                                         label=" %s " % _("1. Select GRASS GIS database directory"))
 
108
        self.location_box = wx.StaticBox(parent=self.panel, id=wx.ID_ANY,
 
109
                                         label=" %s " % _("2. Select GRASS Location"))
 
110
        self.mapset_box = wx.StaticBox(parent=self.panel, id=wx.ID_ANY,
 
111
                                         label=" %s " % _("3. Select GRASS Mapset"))
 
112
 
 
113
        self.lmessage = wx.StaticText(parent=self.panel)
 
114
        # It is not clear if all wx versions supports color, so try-except.
 
115
        # The color itself may not be correct for all platforms/system settings
 
116
        # but in http://xoomer.virgilio.it/infinity77/wxPython/Widgets/wx.SystemSettings.html
 
117
        # there is no 'warning' color.
 
118
        try:
 
119
            self.lmessage.SetForegroundColour(wx.Colour(255, 0, 0))
 
120
        except AttributeError:
 
121
            pass
 
122
        
 
123
        self.gisdbase_panel = wx.Panel(parent=self.panel)
 
124
        self.location_panel = wx.Panel(parent=self.panel)
 
125
        self.mapset_panel = wx.Panel(parent=self.panel)
 
126
 
 
127
        self.ldbase = wx.StaticText(
 
128
            parent=self.gisdbase_panel, id=wx.ID_ANY,
 
129
            label=_("GRASS GIS database directory contains Locations."))
 
130
 
 
131
        self.llocation = StaticWrapText(
 
132
            parent=self.location_panel, id=wx.ID_ANY,
 
133
            label=_("All data in one Location is in the same "
 
134
                    " coordinate reference system (projection)."
 
135
                    " One Location can be one project."
 
136
                    " Location contains Mapsets."),
 
137
            style=wx.ALIGN_LEFT)
 
138
 
 
139
        self.lmapset = StaticWrapText(
 
140
            parent=self.mapset_panel, id=wx.ID_ANY,
 
141
            label=_("Mapset contains GIS data related"
 
142
                    " to one project, task within one project,"
 
143
                    " subregion or user."),
 
144
            style=wx.ALIGN_LEFT)
 
145
 
 
146
        try:
 
147
            for label in [self.ldbase, self.llocation, self.lmapset]:
 
148
                label.SetForegroundColour(
 
149
                    wx.SystemSettings_GetColour(wx.SYS_COLOUR_GRAYTEXT))
 
150
        except AttributeError:
 
151
            # for explanation of try-except see above
 
152
            pass
129
153
 
130
154
        # buttons
131
155
        self.bstart = wx.Button(parent = self.panel, id = wx.ID_ANY,
132
 
                                label = _("Start &GRASS"))
 
156
                                label = _("Start &GRASS session"))
133
157
        self.bstart.SetDefault()
134
158
        self.bexit = wx.Button(parent = self.panel, id = wx.ID_EXIT)
135
159
        self.bstart.SetMinSize((180, self.bexit.GetSize()[1]))
136
160
        self.bhelp = wx.Button(parent = self.panel, id = wx.ID_HELP)
137
 
        self.bbrowse = wx.Button(parent = self.panel, id = wx.ID_ANY,
 
161
        self.bbrowse = wx.Button(parent = self.gisdbase_panel, id = wx.ID_ANY,
138
162
                                 label = _("&Browse"))
139
 
        self.bmapset = wx.Button(parent = self.panel, id = wx.ID_ANY,
140
 
                                 label = _("&Create mapset"))
141
 
        self.bwizard = wx.Button(parent = self.panel, id = wx.ID_ANY,
142
 
                                 label = _("&Location wizard"))
143
 
        self.bwizard.SetToolTipString(_("Start location wizard."
 
163
        self.bmapset = wx.Button(parent = self.mapset_panel, id = wx.ID_ANY,
 
164
                                 label = _("&New"))
 
165
        self.bmapset.SetToolTipString(
 
166
            _("Create a new Mapset in selected Location"))
 
167
        self.bwizard = wx.Button(parent = self.location_panel, id = wx.ID_ANY,
 
168
                                 label = _("N&ew"))
 
169
        self.bwizard.SetToolTipString(_("Create a new location using location wizard."
144
170
                                        " After location is created successfully,"
145
171
                                        " GRASS session is started."))
146
 
        self.manageloc = wx.Choice(parent = self.panel, id = wx.ID_ANY,
147
 
                                   choices = [_('Rename mapset'), _('Rename location'),
148
 
                                            _('Delete mapset'), _('Delete location')])
149
 
        self.manageloc.SetSelection(0)
 
172
        self.rename_location_button = wx.Button(parent=self.location_panel, id=wx.ID_ANY,
 
173
                                                label=_("Ren&ame"))
 
174
        self.rename_location_button.SetToolTipString(_("Rename selected location"))
 
175
        self.delete_location_button = wx.Button(parent=self.location_panel, id=wx.ID_ANY,
 
176
                                                label=_("De&lete"))
 
177
        self.delete_location_button.SetToolTipString(_("Delete selected location"))
 
178
        self.rename_mapset_button = wx.Button(parent=self.mapset_panel, id=wx.ID_ANY,
 
179
                                                label=_("&Rename"))
 
180
        self.rename_mapset_button.SetToolTipString(_("Rename selected mapset"))
 
181
        self.delete_mapset_button = wx.Button(parent=self.mapset_panel, id=wx.ID_ANY,
 
182
                                              label=_("&Delete"))
 
183
        self.delete_mapset_button.SetToolTipString(_("Delete selected mapset"))
150
184
 
151
185
        # textinputs
152
 
        self.tgisdbase = wx.TextCtrl(parent = self.panel, id = wx.ID_ANY, value = "", size = (300, -1),
 
186
        self.tgisdbase = wx.TextCtrl(parent = self.gisdbase_panel, id = wx.ID_ANY, value = "", size = (300, -1),
153
187
                                     style = wx.TE_PROCESS_ENTER)
154
188
 
155
189
        # Locations
156
 
        self.lblocations = GListBox(parent = self.panel,
157
 
                                    id = wx.ID_ANY, size = (180, 200),
 
190
        self.lblocations = GListBox(parent = self.location_panel,
 
191
                                    id=wx.ID_ANY, size=(180, 200),
158
192
                                    choices = self.listOfLocations)
159
 
        
160
193
        self.lblocations.SetColumnWidth(0, 180)
161
194
 
162
195
        # TODO: sort; but keep PERMANENT on top of list
163
196
        # Mapsets
164
 
        self.lbmapsets = GListBox(parent = self.panel,
165
 
                                  id = wx.ID_ANY, size = (180, 200),
 
197
        self.lbmapsets = GListBox(parent = self.mapset_panel,
 
198
                                  id=wx.ID_ANY, size=(180, 200),
166
199
                                  choices = self.listOfMapsets)
167
 
        
168
200
        self.lbmapsets.SetColumnWidth(0, 180)
169
201
 
170
 
        # layout & properties
171
 
        self._set_properties()
 
202
        # layout & properties, first do layout so everything is created
172
203
        self._do_layout()
 
204
        self._set_properties(grassVersion, grassRevisionStr)
173
205
 
174
206
        # events
175
207
        self.bbrowse.Bind(wx.EVT_BUTTON,      self.OnBrowse)
178
210
        self.bhelp.Bind(wx.EVT_BUTTON,        self.OnHelp)
179
211
        self.bmapset.Bind(wx.EVT_BUTTON,      self.OnCreateMapset)
180
212
        self.bwizard.Bind(wx.EVT_BUTTON,      self.OnWizard)
181
 
        self.manageloc.Bind(wx.EVT_CHOICE,    self.OnManageLoc)
 
213
        
 
214
        self.rename_location_button.Bind(wx.EVT_BUTTON, self.RenameLocation)
 
215
        self.delete_location_button.Bind(wx.EVT_BUTTON, self.DeleteLocation)
 
216
        self.rename_mapset_button.Bind(wx.EVT_BUTTON, self.RenameMapset)
 
217
        self.delete_mapset_button.Bind(wx.EVT_BUTTON, self.DeleteMapset)
 
218
        
182
219
        self.lblocations.Bind(wx.EVT_LIST_ITEM_SELECTED, self.OnSelectLocation)
183
220
        self.lbmapsets.Bind(wx.EVT_LIST_ITEM_SELECTED,   self.OnSelectMapset)
184
221
        self.lbmapsets.Bind(wx.EVT_LIST_ITEM_ACTIVATED, self.OnStart)
185
222
        self.tgisdbase.Bind(wx.EVT_TEXT_ENTER, self.OnSetDatabase)
186
223
        self.Bind(wx.EVT_CLOSE,               self.OnCloseWindow)
187
224
        
188
 
    def _set_properties(self):
189
 
        """!Set frame properties"""
190
 
        self.SetTitle(_("Welcome to GRASS GIS"))
191
 
        self.SetIcon(wx.Icon(os.path.join(globalvar.ETCICONDIR, "grass.ico"),
 
225
    def _set_properties(self, version, revision):
 
226
        """Set frame properties"""
 
227
        self.SetTitle(_("GRASS GIS %s startup%s") % (version, revision))
 
228
        self.SetIcon(wx.Icon(os.path.join(globalvar.ICONDIR, "grass.ico"),
192
229
                             wx.BITMAP_TYPE_ICO))
193
230
 
194
 
        self.lwelcome.SetForegroundColour(wx.Colour(35, 142, 35))
195
 
        self.lwelcome.SetFont(wx.Font(13, wx.DEFAULT, wx.NORMAL, wx.BOLD, 0, ""))
196
 
 
197
231
        self.bstart.SetForegroundColour(wx.Colour(35, 142, 35))
198
232
        self.bstart.SetToolTipString(_("Enter GRASS session"))
199
233
        self.bstart.Enable(False)
200
234
        self.bmapset.Enable(False)
201
 
        self.manageloc.Enable(False)
 
235
        # this all was originally a choice, perhaps just mapset needed
 
236
        self.rename_location_button.Enable(False)
 
237
        self.delete_location_button.Enable(False)
 
238
        self.rename_mapset_button.Enable(False)
 
239
        self.delete_mapset_button.Enable(False)
202
240
 
203
241
        # set database
204
242
        if not self.gisdbase:
217
255
        
218
256
        self.OnSetDatabase(None)
219
257
        location = self.GetRCValue("LOCATION_NAME")
220
 
        if location == "<UNKNOWN>" or \
221
 
                not os.path.isdir(os.path.join(self.gisdbase, location)):
 
258
        if location == "<UNKNOWN>":
 
259
            return
 
260
        if not os.path.isdir(os.path.join(self.gisdbase, location)):
222
261
            location = None
223
 
 
224
 
        if location:
225
 
            # list of locations
226
 
            self.UpdateLocations(self.gisdbase)
 
262
        
 
263
        # list of locations
 
264
        self.UpdateLocations(self.gisdbase)
 
265
        try:
 
266
            self.lblocations.SetSelection(self.listOfLocations.index(location),
 
267
                                          force = True)
 
268
            self.lblocations.EnsureVisible(self.listOfLocations.index(location))
 
269
        except ValueError:
 
270
            sys.stderr.write(_("ERROR: Location <%s> not found\n") % self.GetRCValue("LOCATION_NAME"))
 
271
            if len(self.listOfLocations) > 0:
 
272
                self.lblocations.SetSelection(0, force = True)
 
273
                self.lblocations.EnsureVisible(0)
 
274
                location = self.listOfLocations[0]
 
275
            else:
 
276
                return
 
277
        
 
278
        # list of mapsets
 
279
        self.UpdateMapsets(os.path.join(self.gisdbase, location))
 
280
        mapset = self.GetRCValue("MAPSET")
 
281
        if mapset:
227
282
            try:
228
 
                self.lblocations.SetSelection(self.listOfLocations.index(location),
229
 
                                              force = True)
230
 
                self.lblocations.EnsureVisible(self.listOfLocations.index(location))
 
283
                self.lbmapsets.SetSelection(self.listOfMapsets.index(mapset),
 
284
                                            force = True)
 
285
                self.lbmapsets.EnsureVisible(self.listOfMapsets.index(mapset))
231
286
            except ValueError:
232
 
                print >> sys.stderr, _("ERROR: Location <%s> not found") % location
233
 
            
234
 
            # list of mapsets
235
 
            self.UpdateMapsets(os.path.join(self.gisdbase, location))
236
 
            mapset = self.GetRCValue("MAPSET")
237
 
            if mapset:
238
 
                try:
239
 
                    self.lbmapsets.SetSelection(self.listOfMapsets.index(mapset),
240
 
                                                force = True)
241
 
                    self.lbmapsets.EnsureVisible(self.listOfMapsets.index(mapset))
242
 
                except ValueError:
243
 
                    self.lbmapsets.Clear()
244
 
                    print >> sys.stderr, _("ERROR: Mapset <%s> not found") % mapset
245
 
                    
 
287
                sys.stderr.write(_("ERROR: Mapset <%s> not found\n") % mapset)
 
288
                self.lbmapsets.SetSelection(0, force = True)
 
289
                self.lbmapsets.EnsureVisible(0)
 
290
        
246
291
    def _do_layout(self):
247
 
        sizer           = wx.BoxSizer(wx.VERTICAL)
 
292
        sizer = wx.BoxSizer(wx.VERTICAL)
 
293
        self.sizer = sizer  # for the layout call after changing message
248
294
        dbase_sizer     = wx.BoxSizer(wx.HORIZONTAL)
249
 
        location_sizer  = wx.BoxSizer(wx.HORIZONTAL)
250
 
        select_boxsizer = wx.StaticBoxSizer(self.select_box, wx.VERTICAL)
251
 
        select_sizer    = wx.FlexGridSizer(rows = 2, cols = 2, vgap = 4, hgap = 4)
252
 
        select_sizer.AddGrowableRow(1)
253
 
        select_sizer.AddGrowableCol(0)
254
 
        select_sizer.AddGrowableCol(1)
255
 
        manage_sizer    = wx.StaticBoxSizer(self.manage_box, wx.VERTICAL)
 
295
        
 
296
        location_mapset_sizer  = wx.BoxSizer(wx.HORIZONTAL)
 
297
 
 
298
        gisdbase_panel_sizer  = wx.BoxSizer(wx.VERTICAL)
 
299
        gisdbase_boxsizer = wx.StaticBoxSizer(self.gisdbase_box, wx.VERTICAL)        
 
300
 
256
301
        btns_sizer      = wx.BoxSizer(wx.HORIZONTAL)
257
302
        
 
303
        self.gisdbase_panel.SetSizer(gisdbase_panel_sizer)
 
304
 
258
305
        # gis data directory
259
 
        dbase_sizer.Add(item = self.ldbase, proportion = 0,
260
 
                        flag = wx.ALIGN_CENTER_VERTICAL |
261
 
                        wx.ALIGN_CENTER_HORIZONTAL | wx.ALL,
262
 
                        border = 3)
 
306
        
 
307
        gisdbase_boxsizer.Add(item=self.gisdbase_panel, proportion=1,
 
308
                              flag=wx.EXPAND | wx.ALL,
 
309
                              border=1)
 
310
        
 
311
        gisdbase_panel_sizer.Add(item=dbase_sizer, proportion=1,
 
312
                                 flag=wx.EXPAND | wx.ALL,
 
313
                                 border=1)
 
314
        gisdbase_panel_sizer.Add(item=self.ldbase, proportion=0,
 
315
                                 flag=wx.EXPAND | wx.ALL,
 
316
                                 border=1)
 
317
 
263
318
        dbase_sizer.Add(item = self.tgisdbase, proportion = 1,
264
319
                        flag = wx.ALIGN_CENTER_VERTICAL | wx.ALL,
265
 
                        border = 3)
 
320
                        border = 1)
266
321
        dbase_sizer.Add(item = self.bbrowse, proportion = 0,
267
322
                        flag = wx.ALIGN_CENTER_VERTICAL | wx.ALL,
268
 
                        border = 3)
269
 
        
270
 
        # select sizer
271
 
        select_sizer.Add(item = self.llocation, proportion = 0,
272
 
                         flag = wx.ALIGN_CENTER_HORIZONTAL | wx.ALL,
273
 
                         border = 3)
274
 
        select_sizer.Add(item = self.lmapset, proportion = 0,
275
 
                         flag = wx.ALIGN_CENTER_HORIZONTAL | wx.ALL,
276
 
                         border = 3)
277
 
        select_sizer.Add(item = self.lblocations, proportion = 1,
278
 
                         flag = wx.EXPAND)
279
 
        select_sizer.Add(item = self.lbmapsets, proportion = 1,
280
 
                         flag = wx.EXPAND)
281
 
        
282
 
        select_boxsizer.Add(item = select_sizer, proportion = 1,
283
 
                            flag = wx.EXPAND)
284
 
        
285
 
        # define new location and mapset
286
 
        manage_sizer.Add(item = self.ldefine, proportion = 0,
287
 
                         flag = wx.ALIGN_CENTER_HORIZONTAL | wx.ALL,
288
 
                         border = 3)
289
 
        manage_sizer.Add(item = self.bwizard, proportion = 0,
290
 
                         flag = wx.ALIGN_CENTER_HORIZONTAL | wx.BOTTOM,
291
 
                         border = 5)
292
 
        manage_sizer.Add(item = self.lcreate, proportion = 0,
293
 
                         flag = wx.ALIGN_CENTER_HORIZONTAL | wx.ALL,
294
 
                         border = 3)
295
 
        manage_sizer.Add(item = self.bmapset, proportion = 0,
296
 
                         flag = wx.ALIGN_CENTER_HORIZONTAL | wx.BOTTOM,
297
 
                         border = 5)
298
 
        manage_sizer.Add(item = self.lmanageloc, proportion = 0,
299
 
                         flag = wx.ALIGN_CENTER_HORIZONTAL | wx.ALL,
300
 
                         border = 3)
301
 
        manage_sizer.Add(item = self.manageloc, proportion = 0,
302
 
                         flag = wx.ALIGN_CENTER_HORIZONTAL | wx.BOTTOM,
303
 
                         border = 5)
304
 
        
305
 
        # location sizer
306
 
        location_sizer.Add(item = select_boxsizer, proportion = 1,
 
323
                        border = 1)
 
324
 
 
325
        gisdbase_panel_sizer.Fit(self.gisdbase_panel)
 
326
 
 
327
        # location and mapset lists
 
328
 
 
329
        def layout_list_box(box, panel, list_box, buttons, description):
 
330
            panel_sizer = wx.BoxSizer(wx.VERTICAL)
 
331
            main_sizer = wx.BoxSizer(wx.HORIZONTAL)
 
332
            box_sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
 
333
            buttons_sizer = wx.BoxSizer(wx.VERTICAL)
 
334
 
 
335
            panel.SetSizer(panel_sizer)
 
336
            panel_sizer.Fit(panel)
 
337
 
 
338
            main_sizer.Add(item=list_box, proportion=1,
 
339
                           flag=wx.EXPAND | wx.ALL,
 
340
                           border=1)
 
341
            main_sizer.Add(item=buttons_sizer, proportion=0,
 
342
                           flag=wx.ALIGN_CENTER_HORIZONTAL | wx.ALL,
 
343
                           border=1)
 
344
            for button in buttons:
 
345
                buttons_sizer.Add(item=button, proportion=0,
 
346
                                  flag=wx.EXPAND | wx.LEFT | wx.RIGHT | wx.BOTTOM,
 
347
                                  border=3)
 
348
            box_sizer.Add(item=panel, proportion=1,
 
349
                          flag=wx.EXPAND | wx.ALL,
 
350
                          border=1)
 
351
            panel_sizer.Add(item=main_sizer, proportion=1,
 
352
                            flag=wx.EXPAND | wx.ALL,
 
353
                            border=1)
 
354
            panel_sizer.Add(item=description, proportion=0,
 
355
                            flag=wx.EXPAND | wx.ALL,
 
356
                            border=1)
 
357
            return box_sizer
 
358
 
 
359
        location_boxsizer = layout_list_box(
 
360
            box=self.location_box,
 
361
            panel=self.location_panel,
 
362
            list_box=self.lblocations,
 
363
            buttons=[self.bwizard, self.rename_location_button,
 
364
                     self.delete_location_button],
 
365
            description=self.llocation)
 
366
        mapset_boxsizer = layout_list_box(
 
367
            box=self.mapset_box,
 
368
            panel=self.mapset_panel,
 
369
            list_box=self.lbmapsets,
 
370
            buttons=[self.bmapset, self.rename_mapset_button,
 
371
                     self.delete_mapset_button],
 
372
            description=self.lmapset)
 
373
 
 
374
        # location and mapset sizer
 
375
        location_mapset_sizer.Add(item=location_boxsizer, proportion=1,
307
376
                           flag = wx.LEFT | wx.RIGHT | wx.EXPAND,
308
377
                           border = 3) 
309
 
        location_sizer.Add(item = manage_sizer, proportion = 0,
 
378
        location_mapset_sizer.Add(item=mapset_boxsizer, proportion=1,
310
379
                           flag = wx.RIGHT | wx.EXPAND,
311
380
                           border = 3)
312
 
        
 
381
 
313
382
        # buttons
314
383
        btns_sizer.Add(item = self.bstart, proportion = 0,
315
384
                       flag = wx.ALIGN_CENTER_HORIZONTAL |
334
403
                  wx.ALIGN_CENTER_HORIZONTAL |
335
404
                  wx.ALL,
336
405
                  border = 3) # image
337
 
        sizer.Add(item = self.lwelcome, # welcome message
338
 
                  proportion = 0,
339
 
                  flag = wx.ALIGN_CENTER_VERTICAL |
340
 
                  wx.ALIGN_CENTER_HORIZONTAL |
341
 
                  wx.BOTTOM,
342
 
                  border=1)
343
 
        sizer.Add(item = self.ltitle, # title
344
 
                  proportion = 0,
345
 
                  flag = wx.ALIGN_CENTER_VERTICAL |
346
 
                  wx.ALIGN_CENTER_HORIZONTAL)
347
 
        sizer.Add(item = dbase_sizer, proportion = 0,
 
406
        sizer.Add(item=gisdbase_boxsizer, proportion=0,
348
407
                  flag = wx.ALIGN_CENTER_HORIZONTAL |
349
 
                  wx.RIGHT | wx.LEFT | wx.EXPAND,
350
 
                  border = 20) # GISDBASE setting
351
 
        sizer.Add(item = location_sizer, proportion = 1,
 
408
                  wx.RIGHT | wx.LEFT | wx.TOP | wx.EXPAND,
 
409
                  border = 3) # GISDBASE setting
 
410
 
 
411
        # warning/error message
 
412
        sizer.Add(item=self.lmessage,
 
413
                  proportion=0,
 
414
                  flag=wx.ALIGN_CENTER_VERTICAL |
 
415
                  wx.ALIGN_LEFT | wx.ALL | wx.EXPAND, border=5)
 
416
        sizer.Add(item=location_mapset_sizer, proportion=1,
352
417
                  flag = wx.RIGHT | wx.LEFT | wx.EXPAND,
353
418
                  border = 1)
354
419
        sizer.Add(item = btns_sizer, proportion = 0,
355
420
                  flag = wx.ALIGN_CENTER_VERTICAL |
356
421
                  wx.ALIGN_CENTER_HORIZONTAL |
357
422
                  wx.RIGHT | wx.LEFT,
358
 
                  border = 1)
359
 
        
 
423
                  border = 3)
 
424
 
360
425
        self.panel.SetAutoLayout(True)
361
426
        self.panel.SetSizer(sizer)
362
427
        sizer.Fit(self.panel)
363
428
        sizer.SetSizeHints(self)
364
 
        
365
429
        self.Layout()
366
430
 
367
431
    def _readGisRC(self):
368
 
        """
369
 
        Read variables from $HOME/.grassrc6 file
370
 
        """
371
 
 
 
432
        """Read variables from $HOME/.grass7/rc file
 
433
        """
372
434
        grassrc = {}
373
435
        
374
436
        gisrc = os.getenv("GISRC")
379
441
                for line in rc.readlines():
380
442
                    try:
381
443
                        key, val = line.split(":", 1)
382
 
                    except ValueError, e:
383
 
                        sys.stderr.write(_('Invalid line in GISRC file (%(e)s):%(l)s\n' % \
384
 
                                               {'e': e, 'l': line}))
 
444
                    except ValueError as e:
 
445
                        sys.stderr.write(_('Invalid line in GISRC file (%s):%s\n' % \
 
446
                                               (e, line)))
385
447
                    grassrc[key.strip()] = DecodeString(val.strip())
386
448
            finally:
387
449
                rc.close()
388
450
        
389
451
        return grassrc
390
452
 
 
453
    def _showWarning(self, text):
 
454
        """Displays a warning, hint or info message to the user.
 
455
 
 
456
        This function can be used for all kinds of messages except for
 
457
        error messages.
 
458
 
 
459
        .. note::
 
460
            There is no cleaning procedure. You should call _hideMessage when
 
461
            you know that there is everything correct now.
 
462
        """
 
463
        self.lmessage.SetLabel(text)
 
464
        self.lmessage.Wrap(self.GetClientSize()[0])
 
465
        self.sizer.Layout()
 
466
 
 
467
    def _showError(self, text):
 
468
        """Displays a error message to the user.
 
469
 
 
470
        This function should be used only when something serious and unexpected
 
471
        happens, otherwise _showWarning should be used.
 
472
 
 
473
        .. note::
 
474
            There is no cleaning procedure. You should call _hideMessage when
 
475
            you know that there is everything correct now.
 
476
        """
 
477
        self.lmessage.SetLabel(_("Error: {text}").format(text=text))
 
478
        self.lmessage.Wrap(self.GetClientSize()[0])
 
479
        self.sizer.Layout()
 
480
 
 
481
    def _hideMessage(self):
 
482
        """Clears/hides the error message."""
 
483
        # we do no hide widget
 
484
        # because we do not want the dialog to change the size
 
485
        self.lmessage.SetLabel("")
 
486
        self.sizer.Layout()
 
487
 
391
488
    def GetRCValue(self, value):
392
 
        """!Return GRASS variable (read from GISRC)
 
489
        """Return GRASS variable (read from GISRC)
393
490
        """
394
491
        if self.grassrc.has_key(value):
395
492
            return self.grassrc[value]
397
494
            return None
398
495
        
399
496
    def OnWizard(self, event):
400
 
        """!Location wizard started"""
 
497
        """Location wizard started"""
401
498
        from location_wizard.wizard import LocationWizard
402
499
        gWizard = LocationWizard(parent = self,
403
500
                                 grassdatabase = self.tgisdbase.GetValue())
409
506
            self.lbmapsets.SetSelection(0)
410
507
            self.SetLocation(self.gisdbase, gWizard.location, 'PERMANENT')
411
508
            if gWizard.georeffile:
412
 
                message = _("Do you want to import data source <%(name)s> to created location?"
413
 
                            " Default region will be set to match imported map.") % {'name': gWizard.georeffile}
 
509
                message = _("Do you want to import <%(name)s> to the newly created location?") % \
 
510
                    {'name': gWizard.georeffile}
414
511
                dlg = wx.MessageDialog(parent = self,
415
512
                                       message = message,
416
 
                                       caption = _("Import data"),
 
513
                                       caption = _("Import data?"),
417
514
                                       style = wx.YES_NO | wx.YES_DEFAULT | wx.ICON_QUESTION)
418
515
                dlg.CenterOnScreen()
419
516
                if dlg.ShowModal() == wx.ID_YES:
437
534
                self.CreateNewMapset(mapsetName)
438
535
 
439
536
    def SetDefaultRegion(self, location):
440
 
        """!Asks to set default region."""
 
537
        """Asks to set default region."""
 
538
        caption = _("Location <%s> created") % location
 
539
        message = _("Do you want to set the default "
 
540
                    "region extents and resolution now?")
441
541
        dlg = wx.MessageDialog(parent = self,
442
 
                               message = _("Do you want to set the default "
443
 
                                           "region extents and resolution now?"),
444
 
                               caption = _("Location <%s> created") % location,
 
542
                               message = "%(caption)s.\n\n%(extent)s" % ({'caption': caption,
 
543
                                                                          'extent': message}),
 
544
                               caption = caption,
445
545
                               style = wx.YES_NO | wx.NO_DEFAULT | wx.ICON_QUESTION)
446
546
        dlg.CenterOnScreen()
447
547
        if dlg.ShowModal() == wx.ID_YES:
454
554
            dlg.Destroy()
455
555
 
456
556
    def ImportFile(self, filePath):
457
 
        """!Tries to import file as vector or raster.
 
557
        """Tries to import file as vector or raster.
458
558
 
459
559
        If successfull sets default region from imported map.
460
560
        """
461
 
        returncode, stdout, messagesIfVector = RunCommand('v.in.ogr', dsn = filePath, flags = 'l',
462
 
                                                  read = True, getErrorMsg = True)
463
 
        if returncode == 0:
464
 
            wx.BeginBusyCursor()
465
 
            wx.Yield()
466
 
            returncode, messages = RunCommand('v.in.ogr', dsn = filePath, 
467
 
                                              output = os.path.splitext(os.path.basename(filePath))[0],
468
 
                                              getErrorMsg = True)
469
 
            wx.EndBusyCursor()
470
 
            if returncode != 0:
471
 
                message = _("Import of vector data source <%(name)s> failed.") % {'name': filePath}
472
 
                message += "\n" + messages
473
 
                GError(message = message)
474
 
            else:
475
 
                GMessage(message = _("Vector data source <%(name)s> imported successfully.") % {'name': filePath})
476
 
                stdout = RunCommand('g.list', type = 'vect', read = True)
477
 
                maps = stdout.splitlines()
478
 
                if maps:
479
 
                    # TODO: what about resolution?
480
 
                    RunCommand('g.region', flags = 's', vect = maps[0])
481
 
                    
482
 
        else:
483
 
            wx.BeginBusyCursor()
484
 
            wx.Yield()
485
 
            returncode, messages = RunCommand('r.in.gdal', input = filePath,
486
 
                                              output = os.path.splitext(os.path.basename(filePath))[0],
487
 
                                              getErrorMsg = True)
488
 
            wx.EndBusyCursor()
489
 
            if returncode != 0:
490
 
                message = _("Attempt to import data source <%(name)s> as raster or vector failed. ") % {'name': filePath}
491
 
                message += "\n\n" +  messagesIfVector + "\n" + messages
492
 
                GError(message = message)
493
 
            else:
494
 
                GMessage(message = _("Raster data source <%(name)s> imported successfully.") % {'name': filePath})
495
 
                stdout = RunCommand('g.list', type = 'rast', read = True)
496
 
                maps = stdout.splitlines()
497
 
                if maps:
498
 
                    RunCommand('g.region', flags = 's', rast = maps[0])
499
 
 
500
 
    def OnManageLoc(self, event):
501
 
        """!Location management choice control handler
502
 
        """
503
 
        sel = event.GetSelection()
504
 
        if sel ==  0:
505
 
            self.RenameMapset()
506
 
        elif sel ==  1:
507
 
            self.RenameLocation()
508
 
        elif sel ==  2:
509
 
            self.DeleteMapset()
510
 
        elif sel ==  3:
511
 
            self.DeleteLocation()
512
 
        
513
 
        event.Skip()
514
 
        
515
 
    def RenameMapset(self):
516
 
        """!Rename selected mapset
 
561
        RunCommand('db.connect', flags='c')
 
562
        mapName = os.path.splitext(os.path.basename(filePath))[0]
 
563
        vectors = RunCommand('v.in.ogr', input = filePath, flags = 'l',
 
564
                             read = True)
 
565
        
 
566
        wx.BeginBusyCursor()
 
567
        wx.Yield()
 
568
        if mapName in vectors:
 
569
            # vector detected
 
570
            returncode, error = RunCommand('v.in.ogr', input=filePath, output=mapName, flags='e',
 
571
                                           getErrorMsg=True)
 
572
        else:
 
573
            returncode, error = RunCommand('r.in.gdal', input=filePath, output=mapName, flags='e',
 
574
                                           getErrorMsg=True)
 
575
        wx.EndBusyCursor()
 
576
 
 
577
        if returncode != 0:
 
578
            GError(parent = self,
 
579
                   message = _("Import of <%(name)s> failed.\n"
 
580
                               "Reason: %(msg)s") % ({'name': filePath, 'msg': error}))
 
581
        else:
 
582
            GMessage(message=_("Data file <%(name)s> imported successfully. "
 
583
                               "The location's default region was set from this imported map.") %
 
584
                               {'name': filePath},
 
585
                     parent=self)
 
586
 
 
587
    # the event can be refactored out by using lambda in bind
 
588
    def RenameMapset(self, event):
 
589
        """Rename selected mapset
517
590
        """
518
591
        location = self.listOfLocations[self.lblocations.GetSelection()]
519
592
        mapset   = self.listOfMapsets[self.lbmapsets.GetSelection()]
546
619
                              os.path.join(self.gisdbase, location, newmapset))
547
620
                    self.OnSelectLocation(None)
548
621
                    self.lbmapsets.SetSelection(self.listOfMapsets.index(newmapset))
549
 
                except StandardError, e:
 
622
                except StandardError as e:
550
623
                    wx.MessageBox(parent = self,
551
624
                                  caption = _('Error'),
552
625
                                  message = _('Unable to rename mapset.\n\n%s') % e,
554
627
            
555
628
        dlg.Destroy()
556
629
 
557
 
    def RenameLocation(self):
558
 
        """!Rename selected location
 
630
    def RenameLocation(self, event):
 
631
        """Rename selected location
559
632
        """
560
633
        location = self.listOfLocations[self.lblocations.GetSelection()]
561
634
 
583
656
                    self.UpdateLocations(self.gisdbase)
584
657
                    self.lblocations.SetSelection(self.listOfLocations.index(newlocation))
585
658
                    self.UpdateMapsets(newlocation)
586
 
                except StandardError, e:
 
659
                except StandardError as e:
587
660
                    wx.MessageBox(parent = self,
588
661
                                  caption = _('Error'),
589
662
                                  message = _('Unable to rename location.\n\n%s') % e,
591
664
        
592
665
        dlg.Destroy()
593
666
 
594
 
    def DeleteMapset(self):
595
 
        """!Delete selected mapset
 
667
    def DeleteMapset(self, event):
 
668
        """Delete selected mapset
596
669
        """
597
670
        location = self.listOfLocations[self.lblocations.GetSelection()]
598
671
        mapset   = self.listOfMapsets[self.lbmapsets.GetSelection()]
620
693
 
621
694
        dlg.Destroy()
622
695
 
623
 
    def DeleteLocation(self):
 
696
    def DeleteLocation(self, event):
624
697
        """
625
698
        Delete selected location
626
699
        """
647
720
        dlg.Destroy()
648
721
 
649
722
    def UpdateLocations(self, dbase):
650
 
        """!Update list of locations"""
 
723
        """Update list of locations"""
651
724
        try:
652
725
            self.listOfLocations = GetListOfLocations(dbase)
653
726
        except UnicodeEncodeError:
654
 
            wx.MessageBox(parent = self, caption = _("Error"),
655
 
                          message = _("Unable to set GRASS database. "
656
 
                                      "Check your locale settings."),
657
 
                          style = wx.OK | wx.ICON_ERROR | wx.CENTRE)
658
 
        
 
727
            GError(parent = self,
 
728
                   message = _("Unable to set GRASS database. "
 
729
                               "Check your locale settings."))
 
730
                
659
731
        self.lblocations.Clear()
660
732
        self.lblocations.InsertItems(self.listOfLocations, 0)
661
733
 
662
734
        if len(self.listOfLocations) > 0:
 
735
            self._hideMessage()
663
736
            self.lblocations.SetSelection(0)
664
737
        else:
665
738
            self.lblocations.SetSelection(wx.NOT_FOUND)
 
739
            self._showWarning(_("No GRASS Location found in '%s'."
 
740
                                " Create a new Location or choose different"
 
741
                                " GRASS database directory.")
 
742
                              % self.gisdbase)
666
743
 
667
744
        return self.listOfLocations
668
745
 
669
746
    def UpdateMapsets(self, location):
670
 
        """!Update list of mapsets"""
 
747
        """Update list of mapsets"""
671
748
        self.FormerMapsetSelection = wx.NOT_FOUND # for non-selectable item
672
749
        
673
750
        self.listOfMapsetsSelectable = list()
712
789
        return self.listOfMapsets
713
790
 
714
791
    def OnSelectLocation(self, event):
715
 
        """!Location selected"""
 
792
        """Location selected"""
716
793
        if event:
717
794
            self.lblocations.SetSelection(event.GetIndex())
718
795
            
745
822
            if locationName:
746
823
                # enable start button when location and mapset is selected
747
824
                self.bstart.Enable()
 
825
                self.bstart.SetFocus()
748
826
                self.bmapset.Enable()
749
 
                self.manageloc.Enable()
 
827
                # replacing disabled choice, perhaps just mapset needed
 
828
                self.rename_location_button.Enable()
 
829
                self.delete_location_button.Enable()
 
830
                self.rename_mapset_button.Enable()
 
831
                self.delete_mapset_button.Enable()
750
832
        else:
751
833
            self.lbmapsets.SetSelection(wx.NOT_FOUND)
752
834
            self.bstart.Enable(False)
753
835
            self.bmapset.Enable(False)
754
 
            self.manageloc.Enable(False)
 
836
            # this all was originally a choice, perhaps just mapset needed
 
837
            self.rename_location_button.Enable(False)
 
838
            self.delete_location_button.Enable(False)
 
839
            self.rename_mapset_button.Enable(False)
 
840
            self.delete_mapset_button.Enable(False)
755
841
        
756
842
    def OnSelectMapset(self, event):
757
 
        """!Mapset selected"""
 
843
        """Mapset selected"""
758
844
        self.lbmapsets.SetSelection(event.GetIndex())
759
845
 
760
846
        if event.GetText() not in self.listOfMapsetsSelectable:
764
850
            event.Skip()
765
851
 
766
852
    def OnSetDatabase(self, event):
767
 
        """!Database set"""
 
853
        """Database set"""
 
854
        gisdbase = self.tgisdbase.GetValue()
 
855
        self._hideMessage()
 
856
        if not os.path.exists(gisdbase):
 
857
            self._showError(_("Path '%s' doesn't exist.") % gisdbase)
 
858
            return
 
859
        
768
860
        self.gisdbase = self.tgisdbase.GetValue()
 
861
        self.UpdateLocations(self.gisdbase)
769
862
        
770
 
        self.UpdateLocations(self.gisdbase)
771
 
 
772
863
        self.OnSelectLocation(None)
773
864
 
774
865
    def OnBrowse(self, event):
789
880
        dlg.Destroy()
790
881
 
791
882
    def OnCreateMapset(self, event):
792
 
        """!Create new mapset"""
793
 
 
 
883
        """Create new mapset"""
794
884
        dlg = TextEntryDialog(parent = self,
795
 
                                 message = _('Enter name for new mapset:'),
796
 
                                 caption = _('Create new mapset'),
797
 
                                 defaultValue = self._getDefaultMapsetName(),
798
 
                                 validator = GenericValidator(grass.legal_name, self._nameValidationFailed))
799
 
 
 
885
                              message = _('Enter name for new mapset:'),
 
886
                              caption = _('Create new mapset'),
 
887
                              defaultValue = self._getDefaultMapsetName(),
 
888
                              validator = GenericValidator(grass.legal_name, self._nameValidationFailed))
800
889
        if dlg.ShowModal() == wx.ID_OK:
801
890
            mapset = dlg.GetValue()
802
891
            return self.CreateNewMapset(mapset = mapset)
808
897
            GMessage(parent = self,
809
898
                     message = _("Mapset <%s> already exists.") % mapset)
810
899
            return False
 
900
 
 
901
        if mapset.lower() == 'ogr':
 
902
            dlg1 = wx.MessageDialog(parent = self,
 
903
                                    message = _("Mapset <%s> is reserved for direct "
 
904
                                                "read access to OGR layers. Please consider to use "
 
905
                                                "another name for your mapset.\n\n"
 
906
                                                "Are you really sure that you want to create this mapset?") % mapset,
 
907
                                    caption = _("Reserved mapset name"),
 
908
                                    style = wx.YES_NO | wx.NO_DEFAULT | wx.ICON_QUESTION)
 
909
            ret = dlg1.ShowModal()
 
910
            dlg1.Destroy()
 
911
            if ret == wx.ID_NO:
 
912
                dlg1.Destroy()
 
913
                return False
811
914
        
812
915
        try:
813
916
            self.gisdbase = self.tgisdbase.GetValue()
820
923
            self.OnSelectLocation(None)
821
924
            self.lbmapsets.SetSelection(self.listOfMapsets.index(mapset))
822
925
            self.bstart.SetFocus()
 
926
 
823
927
            return True
824
 
        except StandardError, e:
 
928
        except StandardError as e:
825
929
            GError(parent = self,
826
930
                   message = _("Unable to create new mapset: %s") % e,
827
931
                   showTraceback = False)
864
968
                if ret == wx.ID_YES:
865
969
                    try:
866
970
                        os.remove(lockfile)
867
 
                    except IOError, e:
 
971
                    except IOError as e:
868
972
                        GError(_("Unable to remove '%(lock)s'.\n\n"
869
973
                                 "Details: %(reason)s") % { 'lock' : lockfile, 'reason' : e})
870
974
                else:
882
986
        RunCommand("g.gisenv",
883
987
                   set = "MAPSET=%s" % mapset)
884
988
 
885
 
 
886
989
    def _getDefaultMapsetName(self):
887
 
        """!Returns default name for mapset."""
 
990
        """Returns default name for mapset."""
888
991
        try:
889
992
            defaultName = getpass.getuser()
890
993
            defaultName.encode('ascii') # raise error if not ascii (not valid mapset name)
900
1003
    def OnExit(self, event):
901
1004
        """'Exit' button clicked"""
902
1005
        self.Destroy()
903
 
        sys.exit (2)
 
1006
        sys.exit(2)
904
1007
 
905
1008
    def OnHelp(self, event):
906
1009
        """'Help' button clicked"""
 
1010
 
907
1011
        # help text in lib/init/helptext.html
908
 
        filePath = os.path.join(self.gisbase, "docs", "html", "helptext.html")
909
 
        import webbrowser
910
 
        webbrowser.open(filePath)
 
1012
        RunCommand('g.manual', entry = 'helptext')
911
1013
 
912
1014
    def OnCloseWindow(self, event):
913
 
        """!Close window event"""
 
1015
        """Close window event"""
914
1016
        event.Skip()
915
1017
        sys.exit(2)
916
1018
 
920
1022
                    "and space.") % {'name': ctrl.GetValue(), 'chars': '/"\'@,=*~'}
921
1023
        GError(parent=self, message=message, caption=_("Invalid name"))
922
1024
 
 
1025
 
923
1026
class GListBox(wx.ListCtrl, listmix.ListCtrlAutoWidthMixin):
924
 
    """!Use wx.ListCtrl instead of wx.ListBox, different style for
 
1027
    """Use wx.ListCtrl instead of wx.ListBox, different style for
925
1028
    non-selectable items (e.g. mapsets with denied permission)"""
926
1029
    def __init__(self, parent, id, size,
927
1030
                 choices, disabled = []):
938
1041
        self._LoadData(choices, disabled)
939
1042
        
940
1043
    def _LoadData(self, choices, disabled = []):
941
 
        """!Load data into list
 
1044
        """Load data into list
942
1045
        
943
 
        @param choices list of item
944
 
        @param disabled list of indeces of non-selectable items
 
1046
        :param choices: list of item
 
1047
        :param disabled: list of indeces of non-selectable items
945
1048
        """
946
1049
        idx = 0
947
1050
        for item in choices:
970
1073
        return self.selected
971
1074
        
972
1075
class StartUp(wx.App):
973
 
    """!Start-up application"""
 
1076
    """Start-up application"""
974
1077
 
975
1078
    def OnInit(self):
976
1079
        if not globalvar.CheckWxVersion([2, 9]):
981
1084
        StartUp.Show()
982
1085
        
983
1086
        if StartUp.GetRCValue("LOCATION_NAME") ==  "<UNKNOWN>":
984
 
            wx.MessageBox(parent = StartUp,
985
 
                          caption = _('Starting GRASS for the first time'),
986
 
                          message = _('GRASS needs a directory in which to store its data. '
987
 
                                    'Create one now if you have not already done so. '
988
 
                                    'A popular choice is "grassdata", located in '
989
 
                                    'your home directory.'),
990
 
                          style = wx.OK | wx.ICON_ERROR | wx.CENTRE)
991
 
            
992
 
            StartUp.OnBrowse(None)
993
 
        
 
1087
            # TODO: This is not ideal, either it should be checked elsewhere
 
1088
            # where other checks are performed or it should use some public
 
1089
            # API. There is no reason for not exposing it.
 
1090
            # TODO: another question is what should be warning, hint or message
 
1091
            StartUp._showWarning(_('GRASS needs a directory (GRASS database) '
 
1092
                                   'in which to store its data. '
 
1093
                                   'Create one now if you have not already done so. '
 
1094
                                   'A popular choice is "grassdata", located in '
 
1095
                                   'your home directory. '
 
1096
                                   'Press Browse button to select the directory.'))
 
1097
 
994
1098
        return 1
995
1099
 
996
1100
if __name__ ==  "__main__":
997
1101
    if os.getenv("GISBASE") is None:
998
1102
        sys.exit("Failed to start GUI, GRASS GIS is not running.")
999
1103
        
1000
 
    import gettext
1001
 
    gettext.install('grasswxpy', os.path.join(os.getenv("GISBASE"), 'locale'), unicode = True)
1002
1104
    
1003
1105
    GRASSStartUp = StartUp(0)
1004
1106
    GRASSStartUp.MainLoop()