preferences.py 52 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319
  1. """
  2. @package preferences
  3. @brief User preferences dialog
  4. Sets default display font, etc.
  5. Classes:
  6. - PreferencesDialog
  7. - SetDefaultFont
  8. - MapsetAccess
  9. (C) 2007-2008 by the GRASS Development Team
  10. This program is free software under the GNU General Public
  11. License (>=v2). Read the file COPYING that comes with GRASS
  12. for details.
  13. @author Michael Barton (Arizona State University)
  14. Martin Landa <landa.martin gmail.com>
  15. """
  16. import os
  17. import sys
  18. import copy
  19. import stat
  20. if os.name in ('posix', 'mac'):
  21. import pwd
  22. import wx
  23. import wx.lib.filebrowsebutton as filebrowse
  24. import wx.lib.colourselect as csel
  25. import wx.lib.mixins.listctrl as listmix
  26. from wx.lib.wordwrap import wordwrap
  27. import gcmd
  28. import grassenv
  29. import utils
  30. from debug import Debug as Debug
  31. class Settings:
  32. """Generic class where to store settings"""
  33. def __init__(self):
  34. #
  35. # settings filename
  36. #
  37. self.fileName = ".grasswx"
  38. self.filePath = None
  39. #
  40. # default settings
  41. #
  42. self.defaultSettings = {
  43. #
  44. # general
  45. #
  46. 'general': {
  47. # current mapset search path
  48. 'mapsetPath' : { 'selection' : 0 },
  49. # use default window layout (layer manager, displays, ...)
  50. 'defWindowPos' : { 'enabled' : False, 'dim' : '' },
  51. },
  52. 'manager' : {
  53. # show opacity level widget
  54. 'changeOpacityLevel' : { 'enabled' : False },
  55. # ask when removing layer from layer tree
  56. 'askOnRemoveLayer' : { 'enabled' : True },
  57. },
  58. #
  59. # display
  60. #
  61. 'display': {
  62. 'displayFont' : { 'value' : '' },
  63. 'driver': { 'type': 'default' },
  64. 'compResolution' : { 'enabled' : False },
  65. 'autoRendering': { 'enabled' : False },
  66. },
  67. #
  68. # advanced
  69. #
  70. 'advanced' : {
  71. 'settingsFile' : { 'type' : 'gisdbase' }, # gisdbase, location, mapset
  72. 'digitInterface' : { 'type' : 'vdigit' }, # vedit, vdigit
  73. 'iconTheme' : { 'type' : 'silk' }, # grass, silk
  74. },
  75. #
  76. # Attribute Table Manager
  77. #
  78. 'atm' : {
  79. 'highlight' : { 'color' : (255, 255, 0, 255), 'width' : 2},
  80. 'leftDbClick' : { 'selection' : 0 },
  81. },
  82. #
  83. # Command
  84. #
  85. 'cmd': {
  86. 'overwrite' : { 'enabled' : False },
  87. 'closeDlg' : { 'enabled' : False },
  88. 'verbosity' : { 'selection' : 'grassenv' },
  89. 'rasterOverlay' : { 'enabled' : False },
  90. },
  91. #
  92. # Workspace
  93. #
  94. 'workspace' : {
  95. 'posDisplay' : { 'enabled' : False },
  96. 'posManager' : { 'enabled' : False },
  97. },
  98. #
  99. # vdigit
  100. #
  101. 'vdigit' : {
  102. # symbology
  103. 'symbolHighlight' : { 'enabled' : None, 'color' : (255, 255, 0, 255) }, # yellow
  104. 'symbolHighlightDupl' : { 'enabled' : None, 'color' : (255, 72, 0, 255) }, # red
  105. 'symbolPoint' : { 'enabled' : True, 'color' : (0, 0, 0, 255) }, # black
  106. 'symbolLine' : { 'enabled' : True, 'color' : (0, 0, 0, 255) }, # black
  107. 'symbolBoundaryNo' : { 'enabled' : True, 'color' : (126, 126, 126, 255) }, # grey
  108. 'symbolBoundaryOne' : { 'enabled' : True, 'color' : (0, 255, 0, 255) }, # green
  109. 'symbolBoundaryTwo' : { 'enabled' : True, 'color' : (255, 135, 0, 255) }, # orange
  110. 'symbolCentroidIn' : { 'enabled' : True, 'color' : (0, 0, 255, 255) }, # blue
  111. 'symbolCentroidOut' : { 'enabled' : True, 'color' : (165, 42, 42, 255) }, # brown
  112. 'symbolCentroidDup' : { 'enabled' : True, 'color' : (156, 62, 206, 255) }, # violet
  113. 'symbolNodeOne' : { 'enabled' : True, 'color' : (255, 0, 0, 255) }, # red
  114. 'symbolNodeTwo' : { 'enabled' : True, 'color' : (0, 86, 45, 255) }, # dark green
  115. 'symbolVertex' : { 'enabled' : False, 'color' : (255, 20, 147, 255) }, # deep pink
  116. # display
  117. 'lineWidth' : { 'value' : 2, 'units' : 'screen pixels' },
  118. # snapping
  119. 'snapping' : { 'value' : 10, 'units' : 'screen pixels' },
  120. 'snapToVertex' : { 'enabled' : False },
  121. 'backgroundMap' : {'value' : ''},
  122. # digitize new record
  123. 'addRecord' : { 'enabled' : True },
  124. 'layer' : {'value' : 1 },
  125. 'category' : {'value' : 1 },
  126. 'categoryMode' : {'selection' : 0 },
  127. # delete existing feature(s)
  128. 'delRecord' : { 'enabled' : True },
  129. # query tool
  130. 'query' : { 'selection' : 0, 'box' : True },
  131. 'queryLength' : { 'than-selection' : 0, 'thresh' : 0 },
  132. 'queryDangle' : { 'than-selection' : 0, 'thresh' : 0 },
  133. # select feature (point, line, centroid, boundary)
  134. 'selectFeaturePoint' : { 'enabled' : True },
  135. 'selectFeatureLine' : { 'enabled' : True },
  136. 'selectFeatureCentroid' : { 'enabled' : True },
  137. 'selectFeatureBoundary' : { 'enabled' : True },
  138. 'selectThresh' : { 'value' : 10, 'units' : 'screen pixels'},
  139. 'checkForDupl' : { 'enabled' : False },
  140. # exit
  141. 'saveOnExit' : { 'enabled' : False },
  142. },
  143. 'profile': {
  144. 'raster0' : { 'pcolor' : (0, 0, 255, 255), # profile line color
  145. 'pwidth' : 1, # profile line width
  146. 'pstyle' : 'solid', # profile line pen style
  147. },
  148. 'raster1' : { 'pcolor' : (255, 0, 0, 255),
  149. 'pwidth' : 1,
  150. 'pstyle' : 'solid',
  151. },
  152. 'raster2' : { 'pcolor' : (0, 255, 0, 255),
  153. 'pwidth' : 1,
  154. 'pstyle' : 'solid',
  155. },
  156. 'font' : { 'titleSize' : 12,
  157. 'axisSize' : 11,
  158. 'legendSize' : 10,
  159. },
  160. 'marker' : { 'color' : wx.Colour(0, 0, 0),
  161. 'fill' : 'transparent',
  162. 'size' : 2,
  163. 'type' : 'triangle',
  164. 'legend' : _('Segment break'),
  165. },
  166. 'grid' : { 'color' : wx.Colour(200,200,200) ,
  167. 'enabled' : True,
  168. },
  169. 'x-axis' : { 'type' : 'auto', # axis format
  170. 'min' : 0, # axis min for custom axis range
  171. 'max': 0, # axis max for custom axis range
  172. 'log' : False,
  173. },
  174. 'y-axis' : { 'type' : 'auto', # axis format
  175. 'min' : 0, # axis min for custom axis range
  176. 'max': 0, # axis max for custom axis range
  177. 'log' : False,
  178. },
  179. 'legend' : { 'enabled' : True
  180. },
  181. },
  182. 'georect' : {
  183. 'symbol' : { 'color' : (0, 0, 255, 255),
  184. 'width' : 2,
  185. },
  186. },
  187. }
  188. #
  189. # user settings
  190. #
  191. self.userSettings = copy.deepcopy(self.defaultSettings)
  192. try:
  193. self.ReadSettingsFile()
  194. except gcmd.SettingsError, e:
  195. print >> sys.stderr, e.message
  196. #
  197. # internal settings (based on user settings)
  198. #
  199. self.internalSettings = {}
  200. for group in self.userSettings.keys():
  201. if group == 'vdigit':
  202. continue # skip digitization settings (separate window frame)
  203. self.internalSettings[group] = {}
  204. for key in self.userSettings[group].keys():
  205. self.internalSettings[group][key] = {}
  206. self.internalSettings['general']["mapsetPath"]['value'] = self.GetMapsetPath()
  207. self.internalSettings['general']['mapsetPath']['choices'] = [_('Mapset search path'),
  208. _('All available mapsets')]
  209. self.internalSettings['atm']['leftDbClick']['choices'] = [_('Edit selected record'),
  210. _('Display selected')]
  211. self.internalSettings['advanced']['settingsFile']['choices'] = ['gisdbase',
  212. 'location',
  213. 'mapset']
  214. self.internalSettings['advanced']['iconTheme']['choices'] = ['grass',
  215. 'silk']
  216. self.internalSettings['advanced']['digitInterface']['choices'] = ['vedit',
  217. 'vdigit']
  218. self.internalSettings['cmd']['verbosity']['choices'] = ['grassenv',
  219. 'verbose',
  220. 'quiet']
  221. self.internalSettings['display']['driver']['choices'] = ['default']
  222. def GetMapsetPath(self):
  223. """Store mapset search path"""
  224. all, access = utils.ListOfMapsets()
  225. if self.Get(group='general', key='mapsetPath', subkey='selection') == 0:
  226. return access
  227. else:
  228. return all
  229. def ReadSettingsFile(self, settings=None):
  230. """Reads settings file (mapset, location, gisdbase)"""
  231. if settings is None:
  232. settings = self.userSettings
  233. # look for settings file
  234. # -> mapser
  235. # -> location
  236. # -> gisdbase
  237. gisdbase = grassenv.GetGRASSVariable("GISDBASE")
  238. location_name = grassenv.GetGRASSVariable("LOCATION_NAME")
  239. mapset_name = grassenv.GetGRASSVariable("MAPSET")
  240. mapset_file = os.path.join(gisdbase, location_name, mapset_name, self.fileName)
  241. location_file = os.path.join(gisdbase, location_name, self.fileName)
  242. gisdbase_file = os.path.join(gisdbase, self.fileName)
  243. if os.path.isfile(mapset_file):
  244. self.filePath = mapset_file
  245. elif os.path.isfile(location_file):
  246. self.filePath = location_file
  247. elif os.path.isfile(gisdbase_file):
  248. self.filePath = gisdbase_file
  249. if self.filePath:
  250. self.__ReadFile(self.filePath, settings)
  251. def __ReadFile(self, filename, settings=None):
  252. """Read settings from file to dict"""
  253. if settings is None:
  254. settings = self.userSettings
  255. try:
  256. file = open(filename, "r")
  257. for line in file.readlines():
  258. line = line.rstrip('%s' % os.linesep)
  259. group, key = line.split(':')[0:2]
  260. kv = line.split(':')[2:]
  261. idx = 0
  262. while idx < len(kv):
  263. subkey = kv[idx]
  264. value = kv[idx+1]
  265. if len(value) == 0:
  266. self.Append(settings, group, key, subkey, '')
  267. else:
  268. # casting
  269. if value == 'True':
  270. value = True
  271. elif value == 'False':
  272. value = False
  273. elif value == 'None':
  274. value = None
  275. elif value[0] == '(':
  276. tmp = value.replace('(','').replace(')', '').split(',')
  277. try:
  278. value = tuple(map(int, tmp))
  279. except:
  280. value = tuple(tmp)
  281. else:
  282. try:
  283. value = int(value)
  284. except:
  285. pass
  286. self.Append(settings, group, key, subkey, value)
  287. idx += 2
  288. finally:
  289. file.close()
  290. def SaveToFile(self, settings=None):
  291. """Save settings to the file"""
  292. if settings is None:
  293. settings = self.userSettings
  294. loc = self.Get(group='advanced', key='settingsFile', subkey='type')
  295. gisdbase = grassenv.GetGRASSVariable("GISDBASE")
  296. location_name = grassenv.GetGRASSVariable("LOCATION_NAME")
  297. mapset_name = grassenv.GetGRASSVariable("MAPSET")
  298. filePath = None
  299. if loc == 'gisdbase':
  300. filePath = os.path.join(gisdbase, self.fileName)
  301. elif loc == 'location':
  302. filePath = os.path.join(gisdbase, location_name, self.fileName)
  303. elif loc == 'mapset':
  304. filePath = os.path.join(gisdbase, location_name, mapset_name, self.fileName)
  305. if filePath is None:
  306. raise gcmd.SettingsError(_('Uknown settings file location.'))
  307. try:
  308. file = open(filePath, "w")
  309. for group in settings.keys():
  310. for item in settings[group].keys():
  311. file.write('%s:%s:' % (group, item))
  312. items = settings[group][item].keys()
  313. for idx in range(len(items)):
  314. file.write('%s:%s' % (items[idx], settings[group][item][items[idx]]))
  315. if idx < len(items) - 1:
  316. file.write(':')
  317. file.write('%s' % os.linesep)
  318. except IOError, e:
  319. raise gcmd.SettingsError(e)
  320. except:
  321. raise gcmd.SettingsError('Writing settings to file <%s> failed.' % filePath)
  322. file.close()
  323. return filePath
  324. def Get(self, group, key=None, subkey=None, internal=False):
  325. """Get value by key/subkey
  326. Raise KeyError if key is not found
  327. @param group settings group
  328. @param key
  329. @param subkey if not given return dict of key
  330. @return value
  331. """
  332. if internal is True:
  333. settings = self.internalSettings
  334. else:
  335. settings = self.userSettings
  336. try:
  337. if subkey is None:
  338. if key is None:
  339. return settings[group]
  340. else:
  341. return settings[group][key]
  342. else:
  343. return settings[group][key][subkey]
  344. except KeyError:
  345. raise gcmd.SettingsError("%s %s:%s:%s." % (_("Unable to get value"),
  346. group, key, subkey))
  347. def Set(self, group, key, subkey, value, internal=False):
  348. """Set value of key/subkey
  349. Raise KeyError if group/key is not found
  350. @param group settings group
  351. @param key key
  352. @param subkey subkey
  353. @param value value
  354. """
  355. if internal is True:
  356. settings = self.internalSettings
  357. else:
  358. settings = self.userSettings
  359. try:
  360. if not settings[group][key].has_key(subkey):
  361. raise KeyError
  362. settings[group][key][subkey] = value
  363. except KeyError:
  364. raise gcmd.SettingsError("%s '%s:%s:%s'" % (_("Unable to set "), group, key, subkey))
  365. def Append(self, dict, group, key, subkey, value):
  366. """Set value of key/subkey
  367. Create group/key/subkey if not exists
  368. @param dict settings dictionary to use
  369. @param group settings group
  370. @param key key
  371. @param subkey subkey
  372. @param value value
  373. """
  374. if not dict.has_key(group):
  375. dict[group] = {}
  376. if not dict[group].has_key(key):
  377. dict[group][key] = {}
  378. dict[group][key][subkey] = value
  379. def GetDefaultSettings(self):
  380. """Get default user settings"""
  381. return self.defaultSettings
  382. globalSettings = Settings()
  383. class PreferencesDialog(wx.Dialog):
  384. """User preferences dialog"""
  385. def __init__(self, parent, title=_("User GUI settings"),
  386. settings=globalSettings,
  387. style=wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER):
  388. self.parent = parent # GMFrame
  389. self.title = title
  390. wx.Dialog.__init__(self, parent=parent, id=wx.ID_ANY, title=title,
  391. style=style, size=(-1, -1))
  392. self.settings = settings
  393. # notebook
  394. notebook = wx.Notebook(parent=self, id=wx.ID_ANY, style=wx.BK_DEFAULT)
  395. # dict for window ids
  396. self.winId = {}
  397. # create notebook pages
  398. self.__CreateGeneralPage(notebook)
  399. self.__CreateDisplayPage(notebook)
  400. self.__CreateCmdPage(notebook)
  401. self.__CreateAttributeManagerPage(notebook)
  402. self.__CreateWorkspacePage(notebook)
  403. self.__CreateAdvancedPage(notebook)
  404. # buttons
  405. btnDefault = wx.Button(self, wx.ID_ANY, _("Set to default"))
  406. btnSave = wx.Button(self, wx.ID_SAVE)
  407. btnApply = wx.Button(self, wx.ID_APPLY)
  408. btnCancel = wx.Button(self, wx.ID_CANCEL)
  409. btnSave.SetDefault()
  410. # bindigs
  411. btnDefault.Bind(wx.EVT_BUTTON, self.OnDefault)
  412. btnDefault.SetToolTipString(_("Revert settings to default and apply changes"))
  413. btnApply.Bind(wx.EVT_BUTTON, self.OnApply)
  414. btnApply.SetToolTipString(_("Apply changes for the current session"))
  415. btnSave.Bind(wx.EVT_BUTTON, self.OnSave)
  416. btnSave.SetToolTipString(_("Apply and save changes to user settings file (default for next sessions)"))
  417. btnSave.SetDefault()
  418. btnCancel.Bind(wx.EVT_BUTTON, self.OnCancel)
  419. btnCancel.SetToolTipString(_("Close dialog and ignore changes"))
  420. # sizers
  421. btnSizer = wx.BoxSizer(wx.HORIZONTAL)
  422. btnSizer.Add(item=btnDefault, proportion=1,
  423. flag=wx.ALL, border=5)
  424. btnStdSizer = wx.StdDialogButtonSizer()
  425. btnStdSizer.AddButton(btnCancel)
  426. btnStdSizer.AddButton(btnSave)
  427. btnStdSizer.AddButton(btnApply)
  428. btnStdSizer.Realize()
  429. mainSizer = wx.BoxSizer(wx.VERTICAL)
  430. mainSizer.Add(item=notebook, proportion=1, flag=wx.EXPAND | wx.ALL, border=5)
  431. mainSizer.Add(item=btnSizer, proportion=0,
  432. flag=wx.EXPAND, border=0)
  433. mainSizer.Add(item=btnStdSizer, proportion=0,
  434. flag=wx.EXPAND | wx.ALL | wx.ALIGN_RIGHT, border=5)
  435. self.SetSizer(mainSizer)
  436. mainSizer.Fit(self)
  437. self.SetMinSize(self.GetBestSize())
  438. self.SetSize((500, 375))
  439. def __CreateGeneralPage(self, notebook):
  440. """Create notebook page for general settings"""
  441. panel = wx.Panel(parent=notebook, id=wx.ID_ANY)
  442. notebook.AddPage(page=panel, text=_("General"))
  443. border = wx.BoxSizer(wx.VERTICAL)
  444. box = wx.StaticBox (parent=panel, id=wx.ID_ANY, label=" %s " % _("General settings"))
  445. sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
  446. gridSizer = wx.GridBagSizer (hgap=3, vgap=3)
  447. gridSizer.AddGrowableCol(0)
  448. #
  449. # mapsets path
  450. #
  451. row = 0
  452. gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  453. label=_("Mapsets path:")),
  454. flag=wx.ALIGN_LEFT |
  455. wx.ALIGN_CENTER_VERTICAL,
  456. pos=(row, 0))
  457. mapsetPath = wx.Choice(parent=panel, id=wx.ID_ANY, size=(200, -1),
  458. choices=self.settings.Get(group='general', key='mapsetPath',
  459. subkey='choices', internal=True),
  460. name="GetSelection")
  461. mapsetPath.SetSelection(self.settings.Get(group='general', key='mapsetPath', subkey='selection'))
  462. self.winId['general:mapsetPath:selection'] = mapsetPath.GetId()
  463. gridSizer.Add(item=mapsetPath,
  464. flag=wx.ALIGN_RIGHT |
  465. wx.ALIGN_CENTER_VERTICAL,
  466. pos=(row, 1))
  467. #
  468. # default window layout
  469. #
  470. row += 1
  471. defaultPos = wx.CheckBox(parent=panel, id=wx.ID_ANY,
  472. label=_("Save current window layout as default"),
  473. name='IsChecked')
  474. defaultPos.SetValue(self.settings.Get(group='general', key='defWindowPos', subkey='enabled'))
  475. defaultPos.SetToolTip(wx.ToolTip (_("Save current position and size of Layer Manager window and opened "
  476. "Map Display window(s) and use as default for next sessions.")))
  477. self.winId['general:defWindowPos:enabled'] = defaultPos.GetId()
  478. gridSizer.Add(item=defaultPos,
  479. pos=(row, 0), span=(1, 2))
  480. sizer.Add(item=gridSizer, proportion=1, flag=wx.ALL | wx.EXPAND, border=5)
  481. border.Add(item=sizer, proportion=0, flag=wx.ALL | wx.EXPAND, border=3)
  482. #
  483. # Layer Manager settings
  484. #
  485. box = wx.StaticBox (parent=panel, id=wx.ID_ANY, label=" %s " % _("Layer Manager settings"))
  486. sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
  487. gridSizer = wx.GridBagSizer (hgap=3, vgap=3)
  488. gridSizer.AddGrowableCol(0)
  489. #
  490. # show opacily level
  491. #
  492. row = 0
  493. changeOpacityLevel = wx.CheckBox(parent=panel, id=wx.ID_ANY,
  494. label=_("Opacity level editable"),
  495. name='IsChecked')
  496. changeOpacityLevel.SetValue(self.settings.Get(group='manager', key='changeOpacityLevel', subkey='enabled'))
  497. self.winId['manager:changeOpacityLevel:enabled'] = changeOpacityLevel.GetId()
  498. gridSizer.Add(item=changeOpacityLevel,
  499. pos=(row, 0), span=(1, 2))
  500. #
  501. # ask when removing map layer from layer tree
  502. #
  503. row += 1
  504. askOnRemoveLayer = wx.CheckBox(parent=panel, id=wx.ID_ANY,
  505. label=_("Ask when removing map layer from layer tree"),
  506. name='IsChecked')
  507. askOnRemoveLayer.SetValue(self.settings.Get(group='manager', key='askOnRemoveLayer', subkey='enabled'))
  508. self.winId['manager:askOnRemoveLayer:enabled'] = askOnRemoveLayer.GetId()
  509. gridSizer.Add(item=askOnRemoveLayer,
  510. pos=(row, 0), span=(1, 2))
  511. sizer.Add(item=gridSizer, proportion=1, flag=wx.ALL | wx.EXPAND, border=5)
  512. border.Add(item=sizer, proportion=0, flag=wx.LEFT | wx.RIGHT | wx.BOTTOM | wx.EXPAND, border=3)
  513. panel.SetSizer(border)
  514. return panel
  515. def __CreateDisplayPage(self, notebook):
  516. """Create notebook page for display settings"""
  517. panel = wx.Panel(parent=notebook, id=wx.ID_ANY)
  518. notebook.AddPage(page=panel, text=_("Display"))
  519. border = wx.BoxSizer(wx.VERTICAL)
  520. box = wx.StaticBox (parent=panel, id=wx.ID_ANY, label=" %s " % _("Font settings"))
  521. sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
  522. gridSizer = wx.GridBagSizer (hgap=3, vgap=3)
  523. gridSizer.AddGrowableCol(0)
  524. #
  525. # font settings
  526. #
  527. row = 0
  528. gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  529. label=_("Default font for GRASS displays:")),
  530. flag=wx.ALIGN_LEFT |
  531. wx.ALIGN_CENTER_VERTICAL,
  532. pos=(row, 0))
  533. fontButton = wx.Button(parent=panel, id=wx.ID_ANY,
  534. label=_("Set font"), size=(100, -1))
  535. gridSizer.Add(item=fontButton,
  536. flag=wx.ALIGN_RIGHT |
  537. wx.ALIGN_CENTER_VERTICAL,
  538. pos=(row, 1))
  539. sizer.Add(item=gridSizer, proportion=1, flag=wx.ALL | wx.EXPAND, border=5)
  540. border.Add(item=sizer, proportion=0, flag=wx.ALL | wx.EXPAND, border=3)
  541. box = wx.StaticBox (parent=panel, id=wx.ID_ANY, label=" %s " % _("Default display settings"))
  542. sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
  543. gridSizer = wx.GridBagSizer (hgap=3, vgap=3)
  544. gridSizer.AddGrowableCol(0)
  545. #
  546. # display driver
  547. #
  548. row = 0
  549. gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  550. label=_("Display driver:")),
  551. flag=wx.ALIGN_LEFT |
  552. wx.ALIGN_CENTER_VERTICAL,
  553. pos=(row, 0))
  554. listOfDrivers = self.settings.Get(group='display', key='driver', subkey='choices', internal=True)
  555. # check if cairo is available
  556. if 'cairo' not in listOfDrivers:
  557. for line in gcmd.Command(['d.mon', '-l']).ReadStdOutput():
  558. if 'cairo' in line:
  559. listOfDrivers.append('cairo')
  560. break
  561. driver = wx.Choice(parent=panel, id=wx.ID_ANY, size=(150, -1),
  562. choices=listOfDrivers,
  563. name="GetStringSelection")
  564. driver.SetStringSelection(self.settings.Get(group='display', key='driver', subkey='type'))
  565. self.winId['display:driver:type'] = driver.GetId()
  566. gridSizer.Add(item=driver,
  567. flag=wx.ALIGN_RIGHT,
  568. pos=(row, 1))
  569. #
  570. # display mode (use computation resolution?)
  571. #
  572. row += 1
  573. compResolution = wx.CheckBox(parent=panel, id=wx.ID_ANY,
  574. label=_("Constrain display resolution to computational settings"),
  575. name="IsChecked")
  576. compResolution.SetValue(self.settings.Get(group='display', key='compResolution', subkey='enabled'))
  577. self.winId['display:compResolution:enabled'] = compResolution.GetId()
  578. gridSizer.Add(item=compResolution,
  579. pos=(row, 0), span=(1, 2))
  580. #
  581. # auto-rendering
  582. #
  583. row += 1
  584. autoRendering = wx.CheckBox(parent=panel, id=wx.ID_ANY,
  585. label=_("Enable auto-rendering"),
  586. name="IsChecked")
  587. autoRendering.SetValue(self.settings.Get(group='display', key='autoRendering', subkey='enabled'))
  588. self.winId['display:autoRendering:enabled'] = autoRendering.GetId()
  589. gridSizer.Add(item=autoRendering,
  590. pos=(row, 0), span=(1, 2))
  591. sizer.Add(item=gridSizer, proportion=1, flag=wx.ALL | wx.EXPAND, border=5)
  592. border.Add(item=sizer, proportion=0, flag=wx.LEFT | wx.RIGHT | wx.BOTTOM | wx.EXPAND, border=3)
  593. panel.SetSizer(border)
  594. # bindings
  595. fontButton.Bind(wx.EVT_BUTTON, self.OnSetFont)
  596. return panel
  597. def __CreateCmdPage(self, notebook):
  598. """Create notebook page for commad dialog settings"""
  599. panel = wx.Panel(parent=notebook, id=wx.ID_ANY)
  600. notebook.AddPage(page=panel, text=_("Command"))
  601. border = wx.BoxSizer(wx.VERTICAL)
  602. box = wx.StaticBox (parent=panel, id=wx.ID_ANY, label=" %s " % _("Command dialog settings"))
  603. sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
  604. gridSizer = wx.GridBagSizer (hgap=3, vgap=3)
  605. gridSizer.AddGrowableCol(0)
  606. #
  607. # command dialog settings
  608. #
  609. row = 0
  610. # overwrite
  611. overwrite = wx.CheckBox(parent=panel, id=wx.ID_ANY,
  612. label=_("Allow output files to overwrite existing files"),
  613. name="IsChecked")
  614. overwrite.SetValue(self.settings.Get(group='cmd', key='overwrite', subkey='enabled'))
  615. self.winId['cmd:overwrite:enabled'] = overwrite.GetId()
  616. gridSizer.Add(item=overwrite,
  617. pos=(row, 0), span=(1, 2))
  618. row += 1
  619. # close
  620. close = wx.CheckBox(parent=panel, id=wx.ID_ANY,
  621. label=_("Close dialog on finish"),
  622. name="IsChecked")
  623. close.SetValue(self.settings.Get(group='cmd', key='closeDlg', subkey='enabled'))
  624. self.winId['cmd:closeDlg:enabled'] = close.GetId()
  625. gridSizer.Add(item=close,
  626. pos=(row, 0), span=(1, 2))
  627. row += 1
  628. # verbosity
  629. gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  630. label=_("Verbosity level:")),
  631. flag=wx.ALIGN_LEFT |
  632. wx.ALIGN_CENTER_VERTICAL,
  633. pos=(row, 0))
  634. verbosity = wx.Choice(parent=panel, id=wx.ID_ANY, size=(200, -1),
  635. choices=self.settings.Get(group='cmd', key='verbosity', subkey='choices', internal=True),
  636. name="GetStringSelection")
  637. verbosity.SetStringSelection(self.settings.Get(group='cmd', key='verbosity', subkey='selection'))
  638. self.winId['cmd:verbosity:selection'] = verbosity.GetId()
  639. gridSizer.Add(item=verbosity,
  640. pos=(row, 1))
  641. sizer.Add(item=gridSizer, proportion=1, flag=wx.ALL | wx.EXPAND, border=5)
  642. border.Add(item=sizer, proportion=0, flag=wx.ALL | wx.EXPAND, border=3)
  643. #
  644. # raster settings
  645. #
  646. box = wx.StaticBox (parent=panel, id=wx.ID_ANY, label=" %s " % _("Raster settings"))
  647. sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
  648. gridSizer = wx.GridBagSizer (hgap=3, vgap=3)
  649. gridSizer.AddGrowableCol(0)
  650. #
  651. # raster overlay
  652. #
  653. row = 0
  654. rasterOverlay = wx.CheckBox(parent=panel, id=wx.ID_ANY,
  655. label=_("Overlay raster maps"),
  656. name='IsChecked')
  657. rasterOverlay.SetValue(self.settings.Get(group='cmd', key='rasterOverlay', subkey='enabled'))
  658. self.winId['cmd:rasterOverlay:enabled'] = rasterOverlay.GetId()
  659. gridSizer.Add(item=rasterOverlay,
  660. pos=(row, 0), span=(1, 2))
  661. sizer.Add(item=gridSizer, proportion=1, flag=wx.ALL | wx.EXPAND, border=5)
  662. border.Add(item=sizer, proportion=0, flag=wx.LEFT | wx.RIGHT | wx.BOTTOM | wx.EXPAND, border=3)
  663. panel.SetSizer(border)
  664. return panel
  665. def __CreateAttributeManagerPage(self, notebook):
  666. """Create notebook page for 'Attribute Table Manager' settings"""
  667. panel = wx.Panel(parent=notebook, id=wx.ID_ANY)
  668. notebook.AddPage(page=panel, text=_("Attributes"))
  669. pageSizer = wx.BoxSizer(wx.VERTICAL)
  670. #
  671. # highlighting
  672. #
  673. highlightBox = wx.StaticBox(parent=panel, id=wx.ID_ANY,
  674. label=" %s " % _("Highlighting"))
  675. highlightSizer = wx.StaticBoxSizer(highlightBox, wx.VERTICAL)
  676. flexSizer = wx.FlexGridSizer (cols=2, hgap=5, vgap=5)
  677. flexSizer.AddGrowableCol(0)
  678. label = wx.StaticText(parent=panel, id=wx.ID_ANY, label="Color")
  679. hlColor = csel.ColourSelect(parent=panel, id=wx.ID_ANY,
  680. colour=self.settings.Get(group='atm', key='highlight', subkey='color'),
  681. size=(25, 25))
  682. self.winId['atm:highlight:color'] = hlColor.GetId()
  683. flexSizer.Add(label, proportion=0, flag=wx.ALIGN_CENTER_VERTICAL)
  684. flexSizer.Add(hlColor, proportion=0, flag=wx.ALIGN_RIGHT | wx.FIXED_MINSIZE)
  685. label = wx.StaticText(parent=panel, id=wx.ID_ANY, label=_("Line width (in pixels)"))
  686. hlWidth = wx.SpinCtrl(parent=panel, id=wx.ID_ANY, size=(50, -1),
  687. initial=self.settings.Get(group='atm', key='highlight',subkey='width'),
  688. min=1, max=1e6)
  689. self.winId['atm:highlight:width'] = hlWidth.GetId()
  690. flexSizer.Add(label, proportion=0, flag=wx.ALIGN_CENTER_VERTICAL)
  691. flexSizer.Add(hlWidth, proportion=0, flag=wx.ALIGN_RIGHT | wx.FIXED_MINSIZE)
  692. highlightSizer.Add(item=flexSizer,
  693. proportion=0,
  694. flag=wx.ALL | wx.EXPAND,
  695. border=5)
  696. pageSizer.Add(item=highlightSizer,
  697. proportion=0,
  698. flag=wx.ALL | wx.EXPAND,
  699. border=5)
  700. #
  701. # data browser related settings
  702. #
  703. dataBrowserBox = wx.StaticBox(parent=panel, id=wx.ID_ANY,
  704. label=" %s " % _("Data browser"))
  705. dataBrowserSizer = wx.StaticBoxSizer(dataBrowserBox, wx.VERTICAL)
  706. flexSizer = wx.FlexGridSizer (cols=2, hgap=5, vgap=5)
  707. flexSizer.AddGrowableCol(0)
  708. label = wx.StaticText(parent=panel, id=wx.ID_ANY, label=_("Left mouse double click"))
  709. leftDbClick = wx.Choice(parent=panel, id=wx.ID_ANY,
  710. choices=self.settings.Get(group='atm', key='leftDbClick', subkey='choices', internal=True),
  711. name="GetSelection")
  712. leftDbClick.SetSelection(self.settings.Get(group='atm', key='leftDbClick', subkey='selection'))
  713. self.winId['atm:leftDbClick:selection'] = leftDbClick.GetId()
  714. flexSizer.Add(label, proportion=0, flag=wx.ALIGN_CENTER_VERTICAL)
  715. flexSizer.Add(leftDbClick, proportion=0, flag=wx.ALIGN_RIGHT | wx.FIXED_MINSIZE)
  716. dataBrowserSizer.Add(item=flexSizer,
  717. proportion=0,
  718. flag=wx.ALL | wx.EXPAND,
  719. border=5)
  720. pageSizer.Add(item=dataBrowserSizer,
  721. proportion=0,
  722. flag=wx.LEFT | wx.RIGHT | wx.BOTTOM | wx.EXPAND,
  723. border=3)
  724. panel.SetSizer(pageSizer)
  725. return panel
  726. def __CreateWorkspacePage(self, notebook):
  727. """Create notebook page for workspace settings"""
  728. panel = wx.Panel(parent=notebook, id=wx.ID_ANY)
  729. notebook.AddPage(page=panel, text=_("Workspace"))
  730. border = wx.BoxSizer(wx.VERTICAL)
  731. box = wx.StaticBox (parent=panel, id=wx.ID_ANY, label=" %s " % _("Loading workspace"))
  732. sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
  733. gridSizer = wx.GridBagSizer (hgap=3, vgap=3)
  734. gridSizer.AddGrowableCol(0)
  735. row = 0
  736. #
  737. # positioning
  738. #
  739. posDisplay = wx.CheckBox(parent=panel, id=wx.ID_ANY,
  740. label=_("Suppress positioning Map Display Window(s)"),
  741. name='IsChecked')
  742. posDisplay.SetValue(self.settings.Get(group='workspace', key='posDisplay', subkey='enabled'))
  743. self.winId['workspace:posDisplay:enabled'] = posDisplay.GetId()
  744. gridSizer.Add(item=posDisplay,
  745. pos=(row, 0), span=(1, 2))
  746. row +=1
  747. posManager = wx.CheckBox(parent=panel, id=wx.ID_ANY,
  748. label=_("Suppress positioning Layer Manager window"),
  749. name='IsChecked')
  750. posManager.SetValue(self.settings.Get(group='workspace', key='posManager', subkey='enabled'))
  751. self.winId['workspace:posManager:enabled'] = posManager.GetId()
  752. gridSizer.Add(item=posManager,
  753. pos=(row, 0), span=(1, 2))
  754. sizer.Add(item=gridSizer, proportion=1, flag=wx.ALL | wx.EXPAND, border=5)
  755. border.Add(item=sizer, proportion=0, flag=wx.ALL | wx.EXPAND, border=3)
  756. panel.SetSizer(border)
  757. return panel
  758. def __CreateAdvancedPage(self, notebook):
  759. """Create notebook page for advanced settings"""
  760. panel = wx.Panel(parent=notebook, id=wx.ID_ANY)
  761. notebook.AddPage(page=panel, text=_("Advanced"))
  762. border = wx.BoxSizer(wx.VERTICAL)
  763. box = wx.StaticBox (parent=panel, id=wx.ID_ANY, label=" %s " % _("Advanced settings"))
  764. sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
  765. gridSizer = wx.GridBagSizer (hgap=3, vgap=3)
  766. gridSizer.AddGrowableCol(0)
  767. row = 0
  768. #
  769. # place where to store settings
  770. #
  771. gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  772. label=_("Place where to store settings:")),
  773. flag=wx.ALIGN_LEFT |
  774. wx.ALIGN_CENTER_VERTICAL,
  775. pos=(row, 0))
  776. settingsFile = wx.Choice(parent=panel, id=wx.ID_ANY, size=(125, -1),
  777. choices=self.settings.Get(group='advanced', key='settingsFile',
  778. subkey='choices', internal=True),
  779. name='GetStringSelection')
  780. settingsFile.SetStringSelection(self.settings.Get(group='advanced', key='settingsFile', subkey='type'))
  781. self.winId['advanced:settingsFile:type'] = settingsFile.GetId()
  782. gridSizer.Add(item=settingsFile,
  783. flag=wx.ALIGN_RIGHT |
  784. wx.ALIGN_CENTER_VERTICAL,
  785. pos=(row, 1))
  786. row += 1
  787. #
  788. # icon theme
  789. #
  790. gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  791. label=_("Icon theme:")),
  792. flag=wx.ALIGN_LEFT |
  793. wx.ALIGN_CENTER_VERTICAL,
  794. pos=(row, 0))
  795. iconTheme = wx.Choice(parent=panel, id=wx.ID_ANY, size=(125, -1),
  796. choices=self.settings.Get(group='advanced', key='iconTheme',
  797. subkey='choices', internal=True),
  798. name="GetStringSelection")
  799. iconTheme.SetStringSelection(self.settings.Get(group='advanced', key='iconTheme', subkey='type'))
  800. self.winId['advanced:iconTheme:type'] = iconTheme.GetId()
  801. gridSizer.Add(item=iconTheme,
  802. flag=wx.ALIGN_RIGHT |
  803. wx.ALIGN_CENTER_VERTICAL,
  804. pos=(row, 1))
  805. row += 1
  806. iconNote = wordwrap(_("Note: Requires GUI restart."),
  807. self.GetSize()[0]-50, wx.ClientDC(self))
  808. gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  809. label=iconNote),
  810. flag=wx.ALIGN_LEFT |
  811. wx.ALIGN_CENTER_VERTICAL,
  812. pos=(row, 0), span=(1, 2))
  813. row += 1
  814. #
  815. # digitization interface
  816. #
  817. gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  818. label=_("Digitization interface:")),
  819. flag=wx.ALIGN_LEFT |
  820. wx.ALIGN_CENTER_VERTICAL,
  821. pos=(row, 0))
  822. digitInterface = wx.Choice(parent=panel, id=wx.ID_ANY, size=(125, -1),
  823. choices=self.settings.Get(group='advanced', key='digitInterface',
  824. subkey='choices', internal=True),
  825. name="GetStringSelection")
  826. digitInterface.SetStringSelection(self.settings.Get(group='advanced', key='digitInterface',
  827. subkey='type'))
  828. self.winId['advanced:digitInterface:type'] = digitInterface.GetId()
  829. gridSizer.Add(item=digitInterface,
  830. flag=wx.ALIGN_RIGHT |
  831. wx.ALIGN_CENTER_VERTICAL,
  832. pos=(row, 1))
  833. row += 1
  834. digitNote = wordwrap(_("Note: User can choose from two interfaces for digitization. "
  835. "The simple one uses v.edit command on the background. "
  836. "Map topology is rebuild on each operation which can "
  837. "significantly slow-down response. The vdigit is a native "
  838. "interface which uses v.edit functionality, but doesn't "
  839. "call the module itself."),
  840. self.GetSize()[0]-50, wx.ClientDC(self))
  841. gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  842. label=digitNote),
  843. flag=wx.ALIGN_LEFT |
  844. wx.ALIGN_CENTER_VERTICAL,
  845. pos=(row, 0), span=(1, 2))
  846. sizer.Add(item=gridSizer, proportion=1, flag=wx.ALL | wx.EXPAND, border=5)
  847. border.Add(item=sizer, proportion=1, flag=wx.ALL | wx.EXPAND, border=3)
  848. panel.SetSizer(border)
  849. return panel
  850. def OnSetFont(self, event):
  851. """'Set font' button pressed"""
  852. dlg = SetDefaultFont(parent=self, id=wx.ID_ANY,
  853. title=_('Select default display font'),
  854. pos=wx.DefaultPosition, size=wx.DefaultSize,
  855. style=wx.DEFAULT_DIALOG_STYLE,
  856. encoding=self.parent.encoding)
  857. if dlg.ShowModal() == wx.ID_CANCEL:
  858. dlg.Destroy()
  859. return
  860. # set default font type, font, and encoding to whatever selected in dialog
  861. if dlg.font != None:
  862. self.font = dlg.font
  863. if dlg.encoding != None:
  864. self.encoding = dlg.encoding
  865. dlg.Destroy()
  866. # set default font and encoding environmental variables
  867. os.environ["GRASS_FONT"] = self.font
  868. if self.encoding != None and self.encoding != "ISO-8859-1":
  869. os.environ["GRASS_ENCODING"] = self.encoding
  870. event.Skip()
  871. def OnSave(self, event):
  872. """Button 'Save' pressed"""
  873. self.__UpdateSettings()
  874. file = self.settings.SaveToFile()
  875. self.parent.goutput.WriteLog(_('Settings saved to file \'%s\'.') % file)
  876. self.Close()
  877. def OnApply(self, event):
  878. """Button 'Apply' pressed"""
  879. self.__UpdateSettings()
  880. self.Close()
  881. def OnCancel(self, event):
  882. """Button 'Cancel' pressed"""
  883. self.Close()
  884. def OnDefault(self, event):
  885. """Button 'Set to default' pressed"""
  886. self.settings.userSettings = copy.deepcopy(self.settings.defaultSettings)
  887. # update widgets
  888. for gks in self.winId.keys():
  889. group, key, subkey = gks.split(':')
  890. value = self.settings.Get(group, key, subkey)
  891. win = self.FindWindowById(self.winId[gks])
  892. if win.GetName() in ('GetValue', 'IsChecked'):
  893. value = win.SetValue(value)
  894. elif win.GetName() == 'GetSelection':
  895. value = win.SetSelection(value)
  896. elif win.GetName() == 'GetStringSelection':
  897. value = win.SetStringSelection(value)
  898. else:
  899. value = win.SetValue(value)
  900. def __UpdateSettings(self):
  901. """Update user settings"""
  902. for item in self.winId.keys():
  903. group, key, subkey = item.split(':')
  904. id = self.winId[item]
  905. win = self.FindWindowById(id)
  906. if win.GetName() == 'GetValue':
  907. value = win.GetValue()
  908. elif win.GetName() == 'GetSelection':
  909. value = win.GetSelection()
  910. elif win.GetName() == 'IsChecked':
  911. value = win.IsChecked()
  912. elif win.GetName() == 'GetStringSelection':
  913. value = win.GetStringSelection()
  914. else:
  915. value = win.GetValue()
  916. self.settings.Set(group, key, subkey, value)
  917. #
  918. # update default window dimension
  919. #
  920. if self.settings.Get(group='general', key='defWindowPos', subkey='enabled') is True:
  921. dim = ''
  922. # layer manager
  923. pos = self.parent.GetPosition()
  924. size = self.parent.GetSize()
  925. dim = '%d,%d,%d,%d' % (pos[0], pos[1], size[0], size[1])
  926. # opened displays
  927. for page in range(0, self.parent.gm_cb.GetPageCount()):
  928. pos = self.parent.gm_cb.GetPage(page).maptree.mapdisplay.GetPosition()
  929. size = self.parent.gm_cb.GetPage(page).maptree.mapdisplay.GetSize()
  930. dim += ',%d,%d,%d,%d' % (pos[0], pos[1], size[0], size[1])
  931. self.settings.Set(group='general', key='defWindowPos', subkey='dim', value=dim)
  932. else:
  933. self.settings.Set(group='general', key='defWindowPos', subkey='dim', value='')
  934. class SetDefaultFont(wx.Dialog):
  935. """
  936. Opens a file selection dialog to select default font
  937. to use in all GRASS displays
  938. """
  939. def __init__(self, parent, id, title, pos=wx.DefaultPosition, size=wx.DefaultSize,
  940. style=wx.DEFAULT_DIALOG_STYLE, encoding='ISO-8859-1'):
  941. wx.Dialog.__init__(self, parent, id, title, pos, size, style)
  942. if "GRASS_FONT" in os.environ:
  943. self.font = os.environ["GRASS_FONT"]
  944. else:
  945. self.font = None
  946. self.fontlist = self.GetFonts()
  947. self.encoding = encoding
  948. sizer = wx.BoxSizer(wx.VERTICAL)
  949. box = wx.BoxSizer(wx.HORIZONTAL)
  950. label = wx.StaticText(self, -1, "Select Font:", (15, 50))
  951. box.Add(label, 0, wx.EXPAND|wx.GROW|wx.ALIGN_TOP|wx.RIGHT, 5)
  952. self.fontlb = wx.ListBox(self, wx.ID_ANY, pos=wx.DefaultPosition,
  953. size=(280,150), choices=self.fontlist,
  954. style=wx.LB_SINGLE|wx.LB_SORT)
  955. self.Bind(wx.EVT_LISTBOX, self.EvtListBox, self.fontlb)
  956. self.Bind(wx.EVT_LISTBOX_DCLICK, self.EvtListBoxDClick, self.fontlb)
  957. if self.font:
  958. self.fontlb.SetStringSelection(self.font, True)
  959. box.Add(self.fontlb, 0, wx.EXPAND|wx.GROW|wx.ALIGN_RIGHT)
  960. sizer.Add(box, 0, wx.EXPAND|wx.GROW|wx.ALIGN_RIGHT|wx.ALL, 8)
  961. box = wx.BoxSizer(wx.HORIZONTAL)
  962. label = wx.StaticText(self, -1, "Character encoding:")
  963. box.Add(label, 0, wx.ALIGN_RIGHT|wx.RIGHT, 5)
  964. self.textentry = wx.TextCtrl(self, -1, "", size=(200,-1))
  965. self.textentry.SetValue(self.encoding)
  966. box.Add(self.textentry, 0, wx.ALIGN_LEFT)
  967. self.textentry.Bind(wx.EVT_TEXT, self.OnEncoding)
  968. sizer.Add(box, 0, wx.GROW|wx.ALIGN_CENTER_VERTICAL|wx.ALL, 8)
  969. line = wx.StaticLine(self, -1, size=(20,-1), style=wx.LI_HORIZONTAL)
  970. sizer.Add(line, 0, wx.GROW|wx.ALIGN_CENTER_VERTICAL|wx.ALL, 10)
  971. btnsizer = wx.StdDialogButtonSizer()
  972. btn = wx.Button(self, wx.ID_OK)
  973. btn.SetDefault()
  974. btnsizer.AddButton(btn)
  975. btn = wx.Button(self, wx.ID_CANCEL)
  976. btnsizer.AddButton(btn)
  977. btnsizer.Realize()
  978. sizer.Add(btnsizer, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5)
  979. self.SetSizer(sizer)
  980. sizer.Fit(self)
  981. def EvtRadioBox(self, event):
  982. if event.GetInt() == 0:
  983. self.fonttype = 'grassfont'
  984. elif event.GetInt() == 1:
  985. self.fonttype = 'truetype'
  986. self.fontlist = self.GetFonts(self.fonttype)
  987. self.fontlb.SetItems(self.fontlist)
  988. def OnEncoding(self, event):
  989. self.encoding = event.GetString()
  990. def EvtListBox(self, event):
  991. self.font = event.GetString()
  992. event.Skip()
  993. def EvtListBoxDClick(self, event):
  994. self.font = event.GetString()
  995. event.Skip()
  996. def GetFonts(self):
  997. """
  998. parses fonts directory or fretypecap file to get a list of fonts for the listbox
  999. """
  1000. fontlist = []
  1001. cmd = ["d.font", "-l"]
  1002. p = gcmd.Command(cmd, stderr=None)
  1003. dfonts = p.ReadStdOutput()
  1004. dfonts.sort(lambda x,y: cmp(x.lower(), y.lower()))
  1005. for item in range(len(dfonts)):
  1006. # ignore duplicate fonts and those starting with #
  1007. if not dfonts[item].startswith('#') and \
  1008. dfonts[item] != dfonts[item-1]:
  1009. fontlist.append(dfonts[item])
  1010. return fontlist
  1011. class MapsetAccess(wx.Dialog):
  1012. """
  1013. Controls setting options and displaying/hiding map overlay decorations
  1014. """
  1015. def __init__(self, parent, id, title=_('Set/unset access to mapsets in current location'),
  1016. pos=wx.DefaultPosition, size=(350, 400),
  1017. style=wx.DEFAULT_DIALOG_STYLE|wx.RESIZE_BORDER):
  1018. wx.Dialog.__init__(self, parent, id, title, pos, size, style)
  1019. self.all_mapsets, self.accessible_mapsets = utils.ListOfMapsets()
  1020. self.curr_mapset = grassenv.GetGRASSVariable('MAPSET')
  1021. # make a checklistbox from available mapsets and check those that are active
  1022. sizer = wx.BoxSizer(wx.VERTICAL)
  1023. label = wx.StaticText(parent=self, id=wx.ID_ANY,
  1024. label=_("Check mapset to make it accessible, uncheck it to hide it.%s"
  1025. "Note: PERMANENT and current mapset are always accessible.") % os.linesep)
  1026. sizer.Add(item=label, proportion=0,
  1027. flag=wx.ALL, border=5)
  1028. self.mapsetlb = CheckListMapset(parent=self)
  1029. self.mapsetlb.LoadData(self.all_mapsets)
  1030. sizer.Add(item=self.mapsetlb, proportion=1,
  1031. flag=wx.ALL | wx.EXPAND, border=5)
  1032. # check all accessible mapsets
  1033. if globalSettings.Get(group='general', key='mapsetPath', subkey='selection') == 1:
  1034. for mset in self.all_mapsets:
  1035. self.mapsetlb.CheckItem(self.all_mapsets.index(mset), True)
  1036. else:
  1037. for mset in self.accessible_mapsets:
  1038. self.mapsetlb.CheckItem(self.all_mapsets.index(mset), True)
  1039. pass
  1040. # dialog buttons
  1041. line = wx.StaticLine(parent=self, id=wx.ID_ANY,
  1042. style=wx.LI_HORIZONTAL)
  1043. sizer.Add(item=line, proportion=0,
  1044. flag=wx.EXPAND | wx.ALIGN_CENTRE | wx.ALL, border=5)
  1045. btnsizer = wx.StdDialogButtonSizer()
  1046. okbtn = wx.Button(self, wx.ID_OK)
  1047. okbtn.SetDefault()
  1048. btnsizer.AddButton(okbtn)
  1049. cancelbtn = wx.Button(self, wx.ID_CANCEL)
  1050. btnsizer.AddButton(cancelbtn)
  1051. btnsizer.Realize()
  1052. sizer.Add(item=btnsizer, proportion=0,
  1053. flag=wx.EXPAND | wx.ALIGN_RIGHT | wx.ALL, border=5)
  1054. # do layout
  1055. self.Layout()
  1056. self.SetSizer(sizer)
  1057. sizer.Fit(self)
  1058. self.SetMinSize(size)
  1059. def GetMapsets(self):
  1060. """Get list of checked mapsets"""
  1061. ms = []
  1062. i = 0
  1063. for mset in self.all_mapsets:
  1064. if self.mapsetlb.IsChecked(i):
  1065. ms.append(mset)
  1066. i += 1
  1067. return ms
  1068. class CheckListMapset(wx.ListCtrl, listmix.ListCtrlAutoWidthMixin, listmix.CheckListCtrlMixin):
  1069. """List of mapset/owner/group"""
  1070. def __init__(self, parent, pos=wx.DefaultPosition,
  1071. log=None):
  1072. self.parent = parent
  1073. wx.ListCtrl.__init__(self, parent, wx.ID_ANY,
  1074. style=wx.LC_REPORT)
  1075. listmix.CheckListCtrlMixin.__init__(self)
  1076. self.log = log
  1077. # setup mixins
  1078. listmix.ListCtrlAutoWidthMixin.__init__(self)
  1079. def LoadData(self, mapsets):
  1080. """Load data into list"""
  1081. self.InsertColumn(0, _('Mapset'))
  1082. self.InsertColumn(1, _('Owner'))
  1083. self.InsertColumn(2, _('Group'))
  1084. locationPath = os.path.join(grassenv.GetGRASSVariable('GISDBASE'),
  1085. grassenv.GetGRASSVariable('LOCATION_NAME'))
  1086. for mapset in mapsets:
  1087. index = self.InsertStringItem(sys.maxint, mapset)
  1088. mapsetPath = os.path.join(locationPath,
  1089. mapset)
  1090. stat_info = os.stat(mapsetPath)
  1091. if os.name in ('posix', 'mac'):
  1092. self.SetStringItem(index, 1, "%s" % pwd.getpwuid(stat_info.st_uid)[0])
  1093. # FIXME: get group name
  1094. self.SetStringItem(index, 2, "%-8s" % stat_info.st_gid)
  1095. else:
  1096. # FIXME: no pwd under MS Windows (owner: 0, group: 0)
  1097. self.SetStringItem(index, 1, "%-8s" % stat_info.st_uid)
  1098. self.SetStringItem(index, 2, "%-8s" % stat_info.st_gid)
  1099. self.SetColumnWidth(col=0, width=wx.LIST_AUTOSIZE)
  1100. self.SetColumnWidth(col=1, width=wx.LIST_AUTOSIZE)
  1101. def OnCheckItem(self, index, flag):
  1102. """Mapset checked/unchecked"""
  1103. mapset = self.parent.all_mapsets[index]
  1104. if mapset == 'PERMANENT' or mapset == self.parent.curr_mapset:
  1105. self.CheckItem(index, True)