preferences.py 69 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773
  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. import globalvar
  31. from debug import Debug as Debug
  32. class Settings:
  33. """Generic class where to store settings"""
  34. def __init__(self):
  35. #
  36. # settings filename
  37. #
  38. self.fileName = ".grasswx7"
  39. self.filePath = None
  40. #
  41. # key/value separator
  42. #
  43. self.sep = ';'
  44. #
  45. # default settings
  46. #
  47. self.defaultSettings = {
  48. #
  49. # general
  50. #
  51. 'general': {
  52. # use default window layout (layer manager, displays, ...)
  53. 'defWindowPos' : {
  54. 'enabled' : False,
  55. 'dim' : ''
  56. },
  57. # expand/collapse element list
  58. 'elementListExpand' : {
  59. 'selection' : 0
  60. },
  61. },
  62. 'manager' : {
  63. # show opacity level widget
  64. 'changeOpacityLevel' : {
  65. 'enabled' : False
  66. },
  67. # ask when removing layer from layer tree
  68. 'askOnRemoveLayer' : {
  69. 'enabled' : True
  70. },
  71. },
  72. #
  73. # display
  74. #
  75. 'display': {
  76. 'displayFont' : {
  77. 'value' : ''
  78. },
  79. 'driver': {
  80. 'type': 'cairo'
  81. },
  82. 'compResolution' : {
  83. 'enabled' : False
  84. },
  85. 'autoRendering': {
  86. 'enabled' : False
  87. },
  88. 'statusbarMode': {
  89. 'selection' : 0
  90. },
  91. },
  92. #
  93. # advanced
  94. #
  95. 'advanced' : {
  96. 'settingsFile' : {
  97. 'type' : 'home'
  98. }, # home, gisdbase, location, mapset
  99. 'digitInterface' : {
  100. 'type' : 'vdigit'
  101. }, # vedit, vdigit
  102. 'iconTheme' : {
  103. 'type' : 'grass'
  104. }, # grass, silk
  105. },
  106. #
  107. # Attribute Table Manager
  108. #
  109. 'atm' : {
  110. 'highlight' : {
  111. 'color' : (255, 255, 0, 255),
  112. 'width' : 2
  113. },
  114. 'leftDbClick' : {
  115. 'selection' : 0
  116. },
  117. 'askOnDeleteRec' : {
  118. 'enabled' : True
  119. },
  120. 'keycolumn' : {
  121. 'value' : 'cat'
  122. },
  123. },
  124. #
  125. # Command
  126. #
  127. 'cmd': {
  128. 'overwrite' : {
  129. 'enabled' : False
  130. },
  131. 'closeDlg' : {
  132. 'enabled' : False
  133. },
  134. 'verbosity' : {
  135. 'selection' : 'grassenv'
  136. },
  137. # d.rast
  138. 'rasterOpaque' : {
  139. 'enabled' : False
  140. },
  141. # d.vect
  142. 'showType': {
  143. 'point' : {
  144. 'enabled' : True
  145. },
  146. 'line' : {
  147. 'enabled' : True
  148. },
  149. 'centroid' : {
  150. 'enabled' : True
  151. },
  152. 'boundary' : {
  153. 'enabled' : True
  154. },
  155. 'area' : {
  156. 'enabled' : True
  157. },
  158. 'face' : {
  159. 'enabled' : True
  160. },
  161. },
  162. 'addNewLayer' : {
  163. 'enabled' : False
  164. },
  165. },
  166. #
  167. # Workspace
  168. #
  169. 'workspace' : {
  170. 'posDisplay' : {
  171. 'enabled' : False
  172. },
  173. 'posManager' : {
  174. 'enabled' : False
  175. },
  176. },
  177. #
  178. # vdigit
  179. #
  180. 'vdigit' : {
  181. # symbology
  182. 'symbol' : {
  183. 'highlight' : {
  184. 'enabled' : None,
  185. 'color' : (255, 255, 0, 255)
  186. }, # yellow
  187. 'highlightDupl' : {
  188. 'enabled' : None,
  189. 'color' : (255, 72, 0, 255)
  190. }, # red
  191. 'point' : {
  192. 'enabled' : True,
  193. 'color' : (0, 0, 0, 255)
  194. }, # black
  195. 'line' : {
  196. 'enabled' : True,
  197. 'color' : (0, 0, 0, 255)
  198. }, # black
  199. 'boundaryNo' : {
  200. 'enabled' : True,
  201. 'color' : (126, 126, 126, 255)
  202. }, # grey
  203. 'boundaryOne' : {
  204. 'enabled' : True,
  205. 'color' : (0, 255, 0, 255)
  206. }, # green
  207. 'boundaryTwo' : {
  208. 'enabled' : True,
  209. 'color' : (255, 135, 0, 255)
  210. }, # orange
  211. 'centroidIn' : {
  212. 'enabled' : True,
  213. 'color' : (0, 0, 255, 255)
  214. }, # blue
  215. 'centroidOut' : {
  216. 'enabled' : True,
  217. 'color' : (165, 42, 42, 255)
  218. }, # brown
  219. 'centroidDup' : {
  220. 'enabled' : True,
  221. 'color' : (156, 62, 206, 255)
  222. }, # violet
  223. 'nodeOne' : {
  224. 'enabled' : True,
  225. 'color' : (255, 0, 0, 255)
  226. }, # red
  227. 'nodeTwo' : {
  228. 'enabled' : True,
  229. 'color' : (0, 86, 45, 255)
  230. }, # dark green
  231. 'vertex' : {
  232. 'enabled' : False,
  233. 'color' : (255, 20, 147, 255)
  234. }, # deep pink
  235. 'area' : {
  236. 'enabled' : False,
  237. 'color' : (217, 255, 217, 255)
  238. }, # green
  239. 'direction' : {
  240. 'enabled' : False,
  241. 'color' : (255, 0, 0, 255)
  242. }, # red
  243. },
  244. # display
  245. 'lineWidth' : {
  246. 'value' : 2,
  247. 'units' : 'screen pixels'
  248. },
  249. # snapping
  250. 'snapping' : {
  251. 'value' : 10,
  252. 'units' : 'screen pixels'
  253. },
  254. 'snapToVertex' : {
  255. 'enabled' : False
  256. },
  257. 'backgroundMap' : {
  258. 'value' : ''
  259. },
  260. # digitize new record
  261. 'addRecord' : {
  262. 'enabled' : True
  263. },
  264. 'layer' :{
  265. 'value' : 1
  266. },
  267. 'category' : {
  268. 'value' : 1
  269. },
  270. 'categoryMode' : {
  271. 'selection' : 0
  272. },
  273. # delete existing feature(s)
  274. 'delRecord' : {
  275. 'enabled' : True
  276. },
  277. # query tool
  278. 'query' : {
  279. 'selection' : 0,
  280. 'box' : True
  281. },
  282. 'queryLength' : {
  283. 'than-selection' : 0,
  284. 'thresh' : 0
  285. },
  286. 'queryDangle' : {
  287. 'than-selection' : 0,
  288. 'thresh' : 0
  289. },
  290. # select feature (point, line, centroid, boundary)
  291. 'selectType': {
  292. 'point' : {
  293. 'enabled' : True
  294. },
  295. 'line' : {
  296. 'enabled' : True
  297. },
  298. 'centroid' : {
  299. 'enabled' : True
  300. },
  301. 'boundary' : {
  302. 'enabled' : True
  303. },
  304. },
  305. 'selectThresh' : {
  306. 'value' : 10,
  307. 'units' : 'screen pixels'
  308. },
  309. 'checkForDupl' : {
  310. 'enabled' : False
  311. },
  312. 'selectInside' : {
  313. 'enabled' : False
  314. },
  315. # exit
  316. 'saveOnExit' : {
  317. 'enabled' : True
  318. },
  319. # break lines on intersection
  320. 'breakLines' : {
  321. 'enabled' : False,
  322. },
  323. },
  324. 'profile': {
  325. 'raster0' : {
  326. 'pcolor' : (0, 0, 255, 255), # profile line color
  327. 'pwidth' : 1, # profile line width
  328. 'pstyle' : 'solid', # profile line pen style
  329. },
  330. 'raster1' : {
  331. 'pcolor' : (255, 0, 0, 255),
  332. 'pwidth' : 1,
  333. 'pstyle' : 'solid',
  334. },
  335. 'raster2' : {
  336. 'pcolor' : (0, 255, 0, 255),
  337. 'pwidth' : 1,
  338. 'pstyle' : 'solid',
  339. },
  340. 'font' : {
  341. 'titleSize' : 12,
  342. 'axisSize' : 11,
  343. 'legendSize' : 10,
  344. },
  345. 'marker' : {
  346. 'color' : (0, 0, 0, 255),
  347. 'fill' : 'transparent',
  348. 'size' : 2,
  349. 'type' : 'triangle',
  350. 'legend' : _('Segment break'),
  351. },
  352. 'grid' : {
  353. 'color' : (200, 200, 200, 255),
  354. 'enabled' : True,
  355. },
  356. 'x-axis' : {
  357. 'type' : 'auto', # axis format
  358. 'min' : 0, # axis min for custom axis range
  359. 'max': 0, # axis max for custom axis range
  360. 'log' : False,
  361. },
  362. 'y-axis' : {
  363. 'type' : 'auto', # axis format
  364. 'min' : 0, # axis min for custom axis range
  365. 'max': 0, # axis max for custom axis range
  366. 'log' : False,
  367. },
  368. 'legend' : {
  369. 'enabled' : True
  370. },
  371. },
  372. 'georect' : {
  373. 'symbol' : {
  374. 'color' : (0, 0, 255, 255),
  375. 'width' : 2,
  376. },
  377. },
  378. 'nviz' : {
  379. 'view' : {
  380. 'persp' : {
  381. 'value' : 40,
  382. 'step' : 5,
  383. },
  384. 'pos' : {
  385. 'x' : 0.85,
  386. 'y' : 0.85,
  387. },
  388. 'height' : {
  389. 'step' : 100,
  390. },
  391. 'twist' : {
  392. 'value' : 0,
  393. 'step' : 5,
  394. },
  395. 'z-exag' : {
  396. 'value': 1,
  397. 'step' : 1,
  398. },
  399. },
  400. 'surface' : {
  401. 'shine': {
  402. 'map' : False,
  403. 'value' : 60.0,
  404. },
  405. 'color' : {
  406. 'map' : True,
  407. 'value' : (0, 0, 0, 255), # constant: black
  408. },
  409. 'draw' : {
  410. 'wire-color' : (136, 136, 136, 255),
  411. 'mode' : 1, # fine
  412. 'style' : 1, # surface
  413. 'shading' : 1, # gouraud
  414. 'res-fine' : 6,
  415. 'res-coarse' : 9,
  416. },
  417. 'position' : {
  418. 'x' : 0,
  419. 'y' : 0,
  420. 'z' : 0,
  421. },
  422. },
  423. 'vector' : {
  424. 'lines' : {
  425. 'show' : False,
  426. 'width' : 2,
  427. 'color' : (0, 0, 255, 255), # blue
  428. 'flat' : False,
  429. 'height' : 0,
  430. },
  431. 'points' : {
  432. 'show' : False,
  433. 'size' : 100,
  434. 'width' : 2,
  435. 'marker' : 2,
  436. 'color' : (0, 0, 255, 255), # blue
  437. 'height' : 0,
  438. }
  439. },
  440. 'volume' : {
  441. 'color' : {
  442. 'map' : True,
  443. 'value' : (0, 0, 0, 255), # constant: black
  444. },
  445. 'draw' : {
  446. 'mode' : 0, # isosurfaces
  447. 'shading' : 1, # gouraud
  448. 'resolution' : 3, # polygon resolution
  449. },
  450. 'shine': {
  451. 'map' : False,
  452. 'value' : 60.0,
  453. },
  454. },
  455. 'settings': {
  456. 'general' : {
  457. 'bgcolor' : (255, 255, 255, 255), # white
  458. },
  459. },
  460. },
  461. }
  462. #
  463. # user settings
  464. #
  465. self.userSettings = copy.deepcopy(self.defaultSettings)
  466. try:
  467. self.ReadSettingsFile()
  468. except gcmd.SettingsError, e:
  469. print >> sys.stderr, e.message
  470. #
  471. # internal settings (based on user settings)
  472. #
  473. self.internalSettings = {}
  474. for group in self.userSettings.keys():
  475. if group == 'vdigit':
  476. continue # skip digitization settings (separate window frame)
  477. self.internalSettings[group] = {}
  478. for key in self.userSettings[group].keys():
  479. self.internalSettings[group][key] = {}
  480. # self.internalSettings['general']["mapsetPath"]['value'] = self.GetMapsetPath()
  481. self.internalSettings['general']['elementListExpand']['choices'] = (_("Collapse all except PERMANENT and current"),
  482. _("Collapse all except PERMANENT"),
  483. _("Collapse all"),
  484. _("Expand all"))
  485. self.internalSettings['atm']['leftDbClick']['choices'] = (_('Edit selected record'),
  486. _('Display selected'))
  487. self.internalSettings['advanced']['settingsFile']['choices'] = ('home',
  488. 'gisdbase',
  489. 'location',
  490. 'mapset')
  491. self.internalSettings['advanced']['iconTheme']['choices'] = ('grass',
  492. 'silk')
  493. self.internalSettings['advanced']['digitInterface']['choices'] = ('vedit',
  494. 'vdigit')
  495. self.internalSettings['cmd']['verbosity']['choices'] = ('grassenv',
  496. 'verbose',
  497. 'quiet')
  498. self.internalSettings['display']['driver']['choices'] = ['cairo', 'png']
  499. self.internalSettings['display']['statusbarMode']['choices'] = globalvar.MAP_DISPLAY_STATUSBAR_MODE
  500. self.internalSettings['nviz']['view'] = {}
  501. self.internalSettings['nviz']['view']['twist'] = {}
  502. self.internalSettings['nviz']['view']['twist']['min'] = -180
  503. self.internalSettings['nviz']['view']['twist']['max'] = 180
  504. self.internalSettings['nviz']['view']['persp'] = {}
  505. self.internalSettings['nviz']['view']['persp']['min'] = 1
  506. self.internalSettings['nviz']['view']['persp']['max'] = 100
  507. self.internalSettings['nviz']['view']['height'] = {}
  508. self.internalSettings['nviz']['view']['height']['value'] = -1
  509. self.internalSettings['nviz']['vector'] = {}
  510. self.internalSettings['nviz']['vector']['points'] = {}
  511. self.internalSettings['nviz']['vector']['points']['marker'] = ("x",
  512. _("box"),
  513. _("sphere"),
  514. _("cube"),
  515. _("diamond"),
  516. _("dtree"),
  517. _("ctree"),
  518. _("aster"),
  519. _("gyro"),
  520. _("histogram"))
  521. def ReadSettingsFile(self, settings=None):
  522. """Reads settings file (mapset, location, gisdbase)"""
  523. if settings is None:
  524. settings = self.userSettings
  525. # look for settings file
  526. # -> mapser
  527. # -> location
  528. # -> gisdbase
  529. gisdbase = grassenv.GetGRASSVariable("GISDBASE")
  530. location_name = grassenv.GetGRASSVariable("LOCATION_NAME")
  531. mapset_name = grassenv.GetGRASSVariable("MAPSET")
  532. mapset_file = os.path.join(gisdbase, location_name, mapset_name, self.fileName)
  533. location_file = os.path.join(gisdbase, location_name, self.fileName)
  534. gisdbase_file = os.path.join(gisdbase, self.fileName)
  535. home_file = os.path.join(os.path.expanduser("~"), self.fileName) # MS Windows fix ?
  536. if os.path.isfile(mapset_file):
  537. self.filePath = mapset_file
  538. elif os.path.isfile(location_file):
  539. self.filePath = location_file
  540. elif os.path.isfile(gisdbase_file):
  541. self.filePath = gisdbase_file
  542. elif os.path.isfile(home_file):
  543. self.filePath = home_file
  544. if self.filePath:
  545. self.__ReadFile(self.filePath, settings)
  546. def __ReadFile(self, filename, settings=None):
  547. """Read settings from file to dict"""
  548. if settings is None:
  549. settings = self.userSettings
  550. try:
  551. file = open(filename, "r")
  552. line = ''
  553. for line in file.readlines():
  554. line = line.rstrip('%s' % os.linesep)
  555. group, key = line.split(self.sep)[0:2]
  556. kv = line.split(self.sep)[2:]
  557. subkeyMaster = None
  558. if len(kv) % 2 != 0: # multiple (e.g. nviz)
  559. subkeyMaster = kv[0]
  560. del kv[0]
  561. idx = 0
  562. while idx < len(kv):
  563. if subkeyMaster:
  564. subkey = [subkeyMaster, kv[idx]]
  565. else:
  566. subkey = kv[idx]
  567. value = kv[idx+1]
  568. value = self.__parseValue(value, read=True)
  569. self.Append(settings, group, key, subkey, value)
  570. idx += 2
  571. except ValueError, e:
  572. print >> sys.stderr, _("Error: Reading settings from file <%(file)s> failed.\n"
  573. " Details: %(detail)s\n"
  574. " Line: '%(line)s'") % { 'file' : filename,
  575. 'detail' : e,
  576. 'line' : line }
  577. file.close()
  578. file.close()
  579. def SaveToFile(self, settings=None):
  580. """Save settings to the file"""
  581. if settings is None:
  582. settings = self.userSettings
  583. loc = self.Get(group='advanced', key='settingsFile', subkey='type')
  584. home = os.path.expanduser("~") # MS Windows fix ?
  585. gisdbase = grassenv.GetGRASSVariable("GISDBASE")
  586. location_name = grassenv.GetGRASSVariable("LOCATION_NAME")
  587. mapset_name = grassenv.GetGRASSVariable("MAPSET")
  588. filePath = None
  589. if loc == 'home':
  590. filePath = os.path.join(home, self.fileName)
  591. elif loc == 'gisdbase':
  592. filePath = os.path.join(gisdbase, self.fileName)
  593. elif loc == 'location':
  594. filePath = os.path.join(gisdbase, location_name, self.fileName)
  595. elif loc == 'mapset':
  596. filePath = os.path.join(gisdbase, location_name, mapset_name, self.fileName)
  597. if filePath is None:
  598. raise gcmd.SettingsError(_('Uknown settings file location.'))
  599. try:
  600. file = open(filePath, "w")
  601. for group in settings.keys():
  602. for key in settings[group].keys():
  603. file.write('%s%s%s%s' % (group, self.sep, key, self.sep))
  604. subkeys = settings[group][key].keys()
  605. for idx in range(len(subkeys)):
  606. value = settings[group][key][subkeys[idx]]
  607. if type(value) == type({}):
  608. if idx > 0:
  609. file.write('%s%s%s%s%s' % (os.linesep, group, self.sep, key, self.sep))
  610. file.write('%s%s' % (subkeys[idx], self.sep))
  611. kvalues = settings[group][key][subkeys[idx]].keys()
  612. srange = range(len(kvalues))
  613. for sidx in srange:
  614. svalue = self.__parseValue(settings[group][key][subkeys[idx]][kvalues[sidx]])
  615. file.write('%s%s%s' % (kvalues[sidx], self.sep,
  616. svalue))
  617. if sidx < len(kvalues) - 1:
  618. file.write('%s' % self.sep)
  619. else:
  620. value = self.__parseValue(settings[group][key][subkeys[idx]])
  621. file.write('%s%s%s' % (subkeys[idx], self.sep, value))
  622. if idx < len(subkeys) - 1:
  623. file.write('%s' % self.sep)
  624. file.write('%s' % os.linesep)
  625. except IOError, e:
  626. raise gcmd.SettingsError(message=e)
  627. except StandardError, e:
  628. raise gcmd.SettingsError(message=_('Writing settings to file <%(file)s> failed.'
  629. '\n\nDetails: %(detail)s') % { 'file' : filePath,
  630. 'detail' : e })
  631. file.close()
  632. return filePath
  633. def __parseValue(self, value, read=False):
  634. """Parse value to be store in settings file"""
  635. if read: # -> read settings (cast values)
  636. if value == 'True':
  637. value = True
  638. elif value == 'False':
  639. value = False
  640. elif value == 'None':
  641. value = None
  642. elif ':' in value: # -> color
  643. value = tuple(map(int, value.split(':')))
  644. else:
  645. try:
  646. value = int(value)
  647. except ValueError:
  648. try:
  649. value = float(value)
  650. except ValueError:
  651. pass
  652. else: # -> write settings
  653. if type(value) == type(wx.Colour(0, 0, 0, 0)):
  654. print value, type(value)
  655. if type(value) == type(()): # -> color
  656. value = str(value[0]) + ':' +\
  657. str(value[1]) + ':' + \
  658. str(value[2])
  659. return value
  660. def Get(self, group, key=None, subkey=None, internal=False):
  661. """Get value by key/subkey
  662. Raise KeyError if key is not found
  663. @param group settings group
  664. @param key (value, None)
  665. @param subkey (value, list or None)
  666. @param internal use internal settings instead
  667. @return value
  668. """
  669. if internal is True:
  670. settings = self.internalSettings
  671. else:
  672. settings = self.userSettings
  673. try:
  674. if subkey is None:
  675. if key is None:
  676. return settings[group]
  677. else:
  678. return settings[group][key]
  679. else:
  680. if type(subkey) == type([]) or \
  681. type(subkey) == type(()):
  682. return settings[group][key][subkey[0]][subkey[1]]
  683. else:
  684. return settings[group][key][subkey]
  685. except KeyError:
  686. #raise gcmd.SettingsError("%s %s:%s:%s." % (_("Unable to get value"),
  687. # group, key, subkey))
  688. print >> sys.stderr, "Settings: unable to get value '%s:%s:%s'\n" % \
  689. (group, key, subkey)
  690. def Set(self, group, value, key=None, subkey=None, internal=False):
  691. """Set value of key/subkey
  692. Raise KeyError if group/key is not found
  693. @param group settings group
  694. @param key key (value, None)
  695. @param subkey subkey (value, list or None)
  696. @param value value
  697. @param internal use internal settings instead
  698. """
  699. if internal is True:
  700. settings = self.internalSettings
  701. else:
  702. settings = self.userSettings
  703. try:
  704. if subkey is None:
  705. if key is None:
  706. settings[group] = value
  707. else:
  708. settings[group][key] = value
  709. else:
  710. if type(subkey) == type([]):
  711. settings[group][key][subkey[0]][subkey[1]] = value
  712. else:
  713. settings[group][key][subkey] = value
  714. except KeyError:
  715. raise gcmd.SettingsError("%s '%s:%s:%s'" % (_("Unable to set "), group, key, subkey))
  716. def Append(self, dict, group, key, subkey, value):
  717. """Set value of key/subkey
  718. Create group/key/subkey if not exists
  719. @param dict settings dictionary to use
  720. @param group settings group
  721. @param key key
  722. @param subkey subkey (value or list)
  723. @param value value
  724. """
  725. if not dict.has_key(group):
  726. dict[group] = {}
  727. if not dict[group].has_key(key):
  728. dict[group][key] = {}
  729. if type(subkey) == type([]):
  730. # TODO: len(subkey) > 2
  731. if not dict[group][key].has_key(subkey[0]):
  732. dict[group][key][subkey[0]] = {}
  733. dict[group][key][subkey[0]][subkey[1]] = value
  734. else:
  735. dict[group][key][subkey] = value
  736. def GetDefaultSettings(self):
  737. """Get default user settings"""
  738. return self.defaultSettings
  739. globalSettings = Settings()
  740. class PreferencesDialog(wx.Dialog):
  741. """User preferences dialog"""
  742. def __init__(self, parent, title=_("User GUI settings"),
  743. settings=globalSettings,
  744. style=wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER):
  745. self.parent = parent # GMFrame
  746. self.title = title
  747. wx.Dialog.__init__(self, parent=parent, id=wx.ID_ANY, title=title,
  748. style=style, size=(-1, -1))
  749. self.settings = settings
  750. # notebook
  751. notebook = wx.Notebook(parent=self, id=wx.ID_ANY, style=wx.BK_DEFAULT)
  752. # dict for window ids
  753. self.winId = {}
  754. # create notebook pages
  755. self.__CreateGeneralPage(notebook)
  756. self.__CreateDisplayPage(notebook)
  757. self.__CreateCmdPage(notebook)
  758. self.__CreateAttributeManagerPage(notebook)
  759. self.__CreateWorkspacePage(notebook)
  760. self.__CreateAdvancedPage(notebook)
  761. # buttons
  762. btnDefault = wx.Button(self, wx.ID_ANY, _("Set to default"))
  763. btnSave = wx.Button(self, wx.ID_SAVE)
  764. btnApply = wx.Button(self, wx.ID_APPLY)
  765. btnCancel = wx.Button(self, wx.ID_CANCEL)
  766. btnSave.SetDefault()
  767. # bindigs
  768. btnDefault.Bind(wx.EVT_BUTTON, self.OnDefault)
  769. btnDefault.SetToolTipString(_("Revert settings to default and apply changes"))
  770. btnApply.Bind(wx.EVT_BUTTON, self.OnApply)
  771. btnApply.SetToolTipString(_("Apply changes for the current session"))
  772. btnSave.Bind(wx.EVT_BUTTON, self.OnSave)
  773. btnSave.SetToolTipString(_("Apply and save changes to user settings file (default for next sessions)"))
  774. btnSave.SetDefault()
  775. btnCancel.Bind(wx.EVT_BUTTON, self.OnCancel)
  776. btnCancel.SetToolTipString(_("Close dialog and ignore changes"))
  777. # sizers
  778. btnSizer = wx.BoxSizer(wx.HORIZONTAL)
  779. btnSizer.Add(item=btnDefault, proportion=1,
  780. flag=wx.ALL, border=5)
  781. btnStdSizer = wx.StdDialogButtonSizer()
  782. btnStdSizer.AddButton(btnCancel)
  783. btnStdSizer.AddButton(btnSave)
  784. btnStdSizer.AddButton(btnApply)
  785. btnStdSizer.Realize()
  786. mainSizer = wx.BoxSizer(wx.VERTICAL)
  787. mainSizer.Add(item=notebook, proportion=1, flag=wx.EXPAND | wx.ALL, border=5)
  788. mainSizer.Add(item=btnSizer, proportion=0,
  789. flag=wx.EXPAND, border=0)
  790. mainSizer.Add(item=btnStdSizer, proportion=0,
  791. flag=wx.EXPAND | wx.ALL | wx.ALIGN_RIGHT, border=5)
  792. self.SetSizer(mainSizer)
  793. mainSizer.Fit(self)
  794. self.SetMinSize(self.GetBestSize())
  795. self.SetSize((500, 375))
  796. def __CreateGeneralPage(self, notebook):
  797. """Create notebook page for general settings"""
  798. panel = wx.Panel(parent=notebook, id=wx.ID_ANY)
  799. notebook.AddPage(page=panel, text=_("General"))
  800. border = wx.BoxSizer(wx.VERTICAL)
  801. box = wx.StaticBox (parent=panel, id=wx.ID_ANY, label=" %s " % _("General settings"))
  802. sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
  803. gridSizer = wx.GridBagSizer (hgap=3, vgap=3)
  804. gridSizer.AddGrowableCol(0)
  805. #
  806. # expand element list
  807. #
  808. row = 0
  809. gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  810. label=_("Element list:")),
  811. flag=wx.ALIGN_LEFT |
  812. wx.ALIGN_CENTER_VERTICAL,
  813. pos=(row, 0))
  814. elementList = wx.Choice(parent=panel, id=wx.ID_ANY,
  815. choices=self.settings.Get(group='general', key='elementListExpand',
  816. subkey='choices', internal=True),
  817. name="GetSelection")
  818. elementList.SetSelection(self.settings.Get(group='general', key='elementListExpand',
  819. subkey='selection'))
  820. self.winId['general:elementListExpand:selection'] = elementList.GetId()
  821. gridSizer.Add(item=elementList,
  822. flag=wx.ALIGN_RIGHT |
  823. wx.ALIGN_CENTER_VERTICAL,
  824. pos=(row, 1))
  825. #
  826. # default window layout
  827. #
  828. row += 1
  829. defaultPos = wx.CheckBox(parent=panel, id=wx.ID_ANY,
  830. label=_("Save current window layout as default"),
  831. name='IsChecked')
  832. defaultPos.SetValue(self.settings.Get(group='general', key='defWindowPos', subkey='enabled'))
  833. defaultPos.SetToolTip(wx.ToolTip (_("Save current position and size of Layer Manager window and opened "
  834. "Map Display window(s) and use as default for next sessions.")))
  835. self.winId['general:defWindowPos:enabled'] = defaultPos.GetId()
  836. gridSizer.Add(item=defaultPos,
  837. pos=(row, 0), span=(1, 2))
  838. sizer.Add(item=gridSizer, proportion=1, flag=wx.ALL | wx.EXPAND, border=5)
  839. border.Add(item=sizer, proportion=0, flag=wx.ALL | wx.EXPAND, border=3)
  840. #
  841. # Layer Manager settings
  842. #
  843. box = wx.StaticBox (parent=panel, id=wx.ID_ANY, label=" %s " % _("Layer Manager settings"))
  844. sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
  845. gridSizer = wx.GridBagSizer (hgap=3, vgap=3)
  846. gridSizer.AddGrowableCol(0)
  847. #
  848. # ask when removing map layer from layer tree
  849. #
  850. row = 0
  851. askOnRemoveLayer = wx.CheckBox(parent=panel, id=wx.ID_ANY,
  852. label=_("Ask when removing map layer from layer tree"),
  853. name='IsChecked')
  854. askOnRemoveLayer.SetValue(self.settings.Get(group='manager', key='askOnRemoveLayer', subkey='enabled'))
  855. self.winId['manager:askOnRemoveLayer:enabled'] = askOnRemoveLayer.GetId()
  856. gridSizer.Add(item=askOnRemoveLayer,
  857. pos=(row, 0), span=(1, 2))
  858. sizer.Add(item=gridSizer, proportion=1, flag=wx.ALL | wx.EXPAND, border=5)
  859. border.Add(item=sizer, proportion=0, flag=wx.LEFT | wx.RIGHT | wx.BOTTOM | wx.EXPAND, border=3)
  860. panel.SetSizer(border)
  861. return panel
  862. def __CreateDisplayPage(self, notebook):
  863. """Create notebook page for display settings"""
  864. panel = wx.Panel(parent=notebook, id=wx.ID_ANY)
  865. notebook.AddPage(page=panel, text=_("Display"))
  866. border = wx.BoxSizer(wx.VERTICAL)
  867. box = wx.StaticBox (parent=panel, id=wx.ID_ANY, label=" %s " % _("Font settings"))
  868. sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
  869. gridSizer = wx.GridBagSizer (hgap=3, vgap=3)
  870. gridSizer.AddGrowableCol(0)
  871. #
  872. # font settings
  873. #
  874. row = 0
  875. gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  876. label=_("Default font for GRASS displays:")),
  877. flag=wx.ALIGN_LEFT |
  878. wx.ALIGN_CENTER_VERTICAL,
  879. pos=(row, 0))
  880. fontButton = wx.Button(parent=panel, id=wx.ID_ANY,
  881. label=_("Set font"), size=(100, -1))
  882. gridSizer.Add(item=fontButton,
  883. flag=wx.ALIGN_RIGHT |
  884. wx.ALIGN_CENTER_VERTICAL,
  885. pos=(row, 1))
  886. sizer.Add(item=gridSizer, proportion=1, flag=wx.ALL | wx.EXPAND, border=5)
  887. border.Add(item=sizer, proportion=0, flag=wx.ALL | wx.EXPAND, border=3)
  888. box = wx.StaticBox (parent=panel, id=wx.ID_ANY, label=" %s " % _("Default display settings"))
  889. sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
  890. gridSizer = wx.GridBagSizer (hgap=3, vgap=3)
  891. gridSizer.AddGrowableCol(0)
  892. #
  893. # display driver
  894. #
  895. row = 0
  896. gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  897. label=_("Display driver:")),
  898. flag=wx.ALIGN_LEFT |
  899. wx.ALIGN_CENTER_VERTICAL,
  900. pos=(row, 0))
  901. listOfDrivers = self.settings.Get(group='display', key='driver', subkey='choices', internal=True)
  902. driver = wx.Choice(parent=panel, id=wx.ID_ANY, size=(150, -1),
  903. choices=listOfDrivers,
  904. name="GetStringSelection")
  905. driver.SetStringSelection(self.settings.Get(group='display', key='driver', subkey='type'))
  906. self.winId['display:driver:type'] = driver.GetId()
  907. gridSizer.Add(item=driver,
  908. flag=wx.ALIGN_RIGHT,
  909. pos=(row, 1))
  910. #
  911. # Statusbar mode
  912. #
  913. row += 1
  914. gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  915. label=_("Statusbar mode:")),
  916. flag=wx.ALIGN_LEFT |
  917. wx.ALIGN_CENTER_VERTICAL,
  918. pos=(row, 0))
  919. listOfModes = self.settings.Get(group='display', key='statusbarMode', subkey='choices', internal=True)
  920. statusbarMode = wx.Choice(parent=panel, id=wx.ID_ANY, size=(150, -1),
  921. choices=listOfModes,
  922. name="GetSelection")
  923. statusbarMode.SetSelection(self.settings.Get(group='display', key='statusbarMode', subkey='selection'))
  924. self.winId['display:statusbarMode:selection'] = statusbarMode.GetId()
  925. gridSizer.Add(item=statusbarMode,
  926. flag=wx.ALIGN_RIGHT,
  927. pos=(row, 1))
  928. #
  929. # Use computation resolution
  930. #
  931. row += 1
  932. compResolution = wx.CheckBox(parent=panel, id=wx.ID_ANY,
  933. label=_("Constrain display resolution to computational settings"),
  934. name="IsChecked")
  935. compResolution.SetValue(self.settings.Get(group='display', key='compResolution', subkey='enabled'))
  936. self.winId['display:compResolution:enabled'] = compResolution.GetId()
  937. gridSizer.Add(item=compResolution,
  938. pos=(row, 0), span=(1, 2))
  939. #
  940. # auto-rendering
  941. #
  942. row += 1
  943. autoRendering = wx.CheckBox(parent=panel, id=wx.ID_ANY,
  944. label=_("Enable auto-rendering"),
  945. name="IsChecked")
  946. autoRendering.SetValue(self.settings.Get(group='display', key='autoRendering', subkey='enabled'))
  947. self.winId['display:autoRendering:enabled'] = autoRendering.GetId()
  948. gridSizer.Add(item=autoRendering,
  949. pos=(row, 0), span=(1, 2))
  950. sizer.Add(item=gridSizer, proportion=1, flag=wx.ALL | wx.EXPAND, border=5)
  951. border.Add(item=sizer, proportion=0, flag=wx.LEFT | wx.RIGHT | wx.BOTTOM | wx.EXPAND, border=3)
  952. panel.SetSizer(border)
  953. # bindings
  954. fontButton.Bind(wx.EVT_BUTTON, self.OnSetFont)
  955. return panel
  956. def __CreateCmdPage(self, notebook):
  957. """Create notebook page for commad dialog settings"""
  958. panel = wx.Panel(parent=notebook, id=wx.ID_ANY)
  959. notebook.AddPage(page=panel, text=_("Command"))
  960. border = wx.BoxSizer(wx.VERTICAL)
  961. box = wx.StaticBox (parent=panel, id=wx.ID_ANY, label=" %s " % _("Command dialog settings"))
  962. sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
  963. gridSizer = wx.GridBagSizer (hgap=3, vgap=3)
  964. gridSizer.AddGrowableCol(0)
  965. #
  966. # command dialog settings
  967. #
  968. row = 0
  969. # overwrite
  970. overwrite = wx.CheckBox(parent=panel, id=wx.ID_ANY,
  971. label=_("Allow output files to overwrite existing files"),
  972. name="IsChecked")
  973. overwrite.SetValue(self.settings.Get(group='cmd', key='overwrite', subkey='enabled'))
  974. self.winId['cmd:overwrite:enabled'] = overwrite.GetId()
  975. gridSizer.Add(item=overwrite,
  976. pos=(row, 0), span=(1, 2))
  977. row += 1
  978. # close
  979. close = wx.CheckBox(parent=panel, id=wx.ID_ANY,
  980. label=_("Close dialog on finish"),
  981. name="IsChecked")
  982. close.SetValue(self.settings.Get(group='cmd', key='closeDlg', subkey='enabled'))
  983. self.winId['cmd:closeDlg:enabled'] = close.GetId()
  984. gridSizer.Add(item=close,
  985. pos=(row, 0), span=(1, 2))
  986. row += 1
  987. # add layer
  988. add = wx.CheckBox(parent=panel, id=wx.ID_ANY,
  989. label=_("Add created map into layer tree"),
  990. name="IsChecked")
  991. add.SetValue(self.settings.Get(group='cmd', key='addNewLayer', subkey='enabled'))
  992. self.winId['cmd:addNewLayer:enabled'] = add.GetId()
  993. gridSizer.Add(item=add,
  994. pos=(row, 0), span=(1, 2))
  995. row += 1
  996. # verbosity
  997. gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  998. label=_("Verbosity level:")),
  999. flag=wx.ALIGN_LEFT |
  1000. wx.ALIGN_CENTER_VERTICAL,
  1001. pos=(row, 0))
  1002. verbosity = wx.Choice(parent=panel, id=wx.ID_ANY, size=(200, -1),
  1003. choices=self.settings.Get(group='cmd', key='verbosity', subkey='choices', internal=True),
  1004. name="GetStringSelection")
  1005. verbosity.SetStringSelection(self.settings.Get(group='cmd', key='verbosity', subkey='selection'))
  1006. self.winId['cmd:verbosity:selection'] = verbosity.GetId()
  1007. gridSizer.Add(item=verbosity,
  1008. pos=(row, 1))
  1009. sizer.Add(item=gridSizer, proportion=1, flag=wx.ALL | wx.EXPAND, border=5)
  1010. border.Add(item=sizer, proportion=0, flag=wx.ALL | wx.EXPAND, border=3)
  1011. #
  1012. # raster settings
  1013. #
  1014. box = wx.StaticBox (parent=panel, id=wx.ID_ANY, label=" %s " % _("Raster settings"))
  1015. sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
  1016. gridSizer = wx.GridBagSizer (hgap=3, vgap=3)
  1017. gridSizer.AddGrowableCol(0)
  1018. #
  1019. # raster overlay
  1020. #
  1021. row = 0
  1022. rasterOpaque = wx.CheckBox(parent=panel, id=wx.ID_ANY,
  1023. label=_("Make null cells opaque"),
  1024. name='IsChecked')
  1025. rasterOpaque.SetValue(self.settings.Get(group='cmd', key='rasterOpaque', subkey='enabled'))
  1026. self.winId['cmd:rasterOpaque:enabled'] = rasterOpaque.GetId()
  1027. gridSizer.Add(item=rasterOpaque,
  1028. pos=(row, 0), span=(1, 2))
  1029. sizer.Add(item=gridSizer, proportion=1, flag=wx.ALL | wx.EXPAND, border=5)
  1030. border.Add(item=sizer, proportion=0, flag=wx.LEFT | wx.RIGHT | wx.BOTTOM | wx.EXPAND, border=3)
  1031. #
  1032. # vector settings
  1033. #
  1034. box = wx.StaticBox (parent=panel, id=wx.ID_ANY, label=" %s " % _("Vector settings"))
  1035. sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
  1036. gridSizer = wx.FlexGridSizer (cols=7, hgap=3, vgap=3)
  1037. gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  1038. label=_("Display:")),
  1039. flag=wx.ALIGN_CENTER_VERTICAL)
  1040. for type in ('point', 'line', 'centroid', 'boundary',
  1041. 'area', 'face'):
  1042. chkbox = wx.CheckBox(parent=panel, label=type)
  1043. checked = self.settings.Get(group='cmd', key='showType',
  1044. subkey=[type, 'enabled'])
  1045. chkbox.SetValue(checked)
  1046. self.winId['cmd:showType:%s:enabled' % type] = chkbox.GetId()
  1047. gridSizer.Add(item=chkbox)
  1048. sizer.Add(item=gridSizer, proportion=1, flag=wx.ALL | wx.EXPAND, border=5)
  1049. border.Add(item=sizer, proportion=0, flag=wx.LEFT | wx.RIGHT | wx.BOTTOM | wx.EXPAND, border=3)
  1050. panel.SetSizer(border)
  1051. return panel
  1052. def __CreateAttributeManagerPage(self, notebook):
  1053. """Create notebook page for 'Attribute Table Manager' settings"""
  1054. panel = wx.Panel(parent=notebook, id=wx.ID_ANY)
  1055. notebook.AddPage(page=panel, text=_("Attributes"))
  1056. pageSizer = wx.BoxSizer(wx.VERTICAL)
  1057. #
  1058. # highlighting
  1059. #
  1060. highlightBox = wx.StaticBox(parent=panel, id=wx.ID_ANY,
  1061. label=" %s " % _("Highlighting"))
  1062. highlightSizer = wx.StaticBoxSizer(highlightBox, wx.VERTICAL)
  1063. flexSizer = wx.FlexGridSizer (cols=2, hgap=5, vgap=5)
  1064. flexSizer.AddGrowableCol(0)
  1065. label = wx.StaticText(parent=panel, id=wx.ID_ANY, label="Color")
  1066. hlColor = csel.ColourSelect(parent=panel, id=wx.ID_ANY,
  1067. colour=self.settings.Get(group='atm', key='highlight', subkey='color'),
  1068. size=(25, 25))
  1069. hlColor.SetName('GetColour')
  1070. self.winId['atm:highlight:color'] = hlColor.GetId()
  1071. flexSizer.Add(label, proportion=0, flag=wx.ALIGN_CENTER_VERTICAL)
  1072. flexSizer.Add(hlColor, proportion=0, flag=wx.ALIGN_RIGHT | wx.FIXED_MINSIZE)
  1073. label = wx.StaticText(parent=panel, id=wx.ID_ANY, label=_("Line width (in pixels)"))
  1074. hlWidth = wx.SpinCtrl(parent=panel, id=wx.ID_ANY, size=(50, -1),
  1075. initial=self.settings.Get(group='atm', key='highlight',subkey='width'),
  1076. min=1, max=1e6)
  1077. self.winId['atm:highlight:width'] = hlWidth.GetId()
  1078. flexSizer.Add(label, proportion=0, flag=wx.ALIGN_CENTER_VERTICAL)
  1079. flexSizer.Add(hlWidth, proportion=0, flag=wx.ALIGN_RIGHT | wx.FIXED_MINSIZE)
  1080. highlightSizer.Add(item=flexSizer,
  1081. proportion=0,
  1082. flag=wx.ALL | wx.EXPAND,
  1083. border=5)
  1084. pageSizer.Add(item=highlightSizer,
  1085. proportion=0,
  1086. flag=wx.ALL | wx.EXPAND,
  1087. border=5)
  1088. #
  1089. # data browser related settings
  1090. #
  1091. dataBrowserBox = wx.StaticBox(parent=panel, id=wx.ID_ANY,
  1092. label=" %s " % _("Data browser"))
  1093. dataBrowserSizer = wx.StaticBoxSizer(dataBrowserBox, wx.VERTICAL)
  1094. flexSizer = wx.FlexGridSizer (cols=2, hgap=5, vgap=5)
  1095. flexSizer.AddGrowableCol(0)
  1096. label = wx.StaticText(parent=panel, id=wx.ID_ANY, label=_("Left mouse double click"))
  1097. leftDbClick = wx.Choice(parent=panel, id=wx.ID_ANY,
  1098. choices=self.settings.Get(group='atm', key='leftDbClick', subkey='choices', internal=True),
  1099. name="GetSelection")
  1100. leftDbClick.SetSelection(self.settings.Get(group='atm', key='leftDbClick', subkey='selection'))
  1101. self.winId['atm:leftDbClick:selection'] = leftDbClick.GetId()
  1102. flexSizer.Add(label, proportion=0, flag=wx.ALIGN_CENTER_VERTICAL)
  1103. flexSizer.Add(leftDbClick, proportion=0, flag=wx.ALIGN_RIGHT | wx.FIXED_MINSIZE)
  1104. # ask on delete record
  1105. askOnDeleteRec = wx.CheckBox(parent=panel, id=wx.ID_ANY,
  1106. label=_("Ask when deleting data record(s) from table"),
  1107. name='IsChecked')
  1108. askOnDeleteRec.SetValue(self.settings.Get(group='atm', key='askOnDeleteRec', subkey='enabled'))
  1109. self.winId['atm:askOnDeleteRec:enabled'] = askOnDeleteRec.GetId()
  1110. flexSizer.Add(askOnDeleteRec, proportion=0)
  1111. dataBrowserSizer.Add(item=flexSizer,
  1112. proportion=0,
  1113. flag=wx.ALL | wx.EXPAND,
  1114. border=5)
  1115. pageSizer.Add(item=dataBrowserSizer,
  1116. proportion=0,
  1117. flag=wx.LEFT | wx.RIGHT | wx.BOTTOM | wx.EXPAND,
  1118. border=3)
  1119. #
  1120. # create table
  1121. #
  1122. createTableBox = wx.StaticBox(parent=panel, id=wx.ID_ANY,
  1123. label=" %s " % _("Create table"))
  1124. createTableSizer = wx.StaticBoxSizer(createTableBox, wx.VERTICAL)
  1125. flexSizer = wx.FlexGridSizer (cols=2, hgap=5, vgap=5)
  1126. flexSizer.AddGrowableCol(0)
  1127. label = wx.StaticText(parent=panel, id=wx.ID_ANY,
  1128. label=_("Key column"))
  1129. keyColumn = wx.TextCtrl(parent=panel, id=wx.ID_ANY,
  1130. size=(250, -1))
  1131. keyColumn.SetValue(self.settings.Get(group='atm', key='keycolumn', subkey='value'))
  1132. self.winId['atm:keycolumn:value'] = keyColumn.GetId()
  1133. flexSizer.Add(label, proportion=0, flag=wx.ALIGN_CENTER_VERTICAL)
  1134. flexSizer.Add(keyColumn, proportion=0, flag=wx.ALIGN_RIGHT | wx.FIXED_MINSIZE)
  1135. createTableSizer.Add(item=flexSizer,
  1136. proportion=0,
  1137. flag=wx.ALL | wx.EXPAND,
  1138. border=5)
  1139. pageSizer.Add(item=createTableSizer,
  1140. proportion=0,
  1141. flag=wx.LEFT | wx.RIGHT | wx.BOTTOM | wx.EXPAND,
  1142. border=3)
  1143. panel.SetSizer(pageSizer)
  1144. return panel
  1145. def __CreateWorkspacePage(self, notebook):
  1146. """Create notebook page for workspace settings"""
  1147. panel = wx.Panel(parent=notebook, id=wx.ID_ANY)
  1148. notebook.AddPage(page=panel, text=_("Workspace"))
  1149. border = wx.BoxSizer(wx.VERTICAL)
  1150. box = wx.StaticBox (parent=panel, id=wx.ID_ANY, label=" %s " % _("Loading workspace"))
  1151. sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
  1152. gridSizer = wx.GridBagSizer (hgap=3, vgap=3)
  1153. gridSizer.AddGrowableCol(0)
  1154. row = 0
  1155. #
  1156. # positioning
  1157. #
  1158. posDisplay = wx.CheckBox(parent=panel, id=wx.ID_ANY,
  1159. label=_("Suppress positioning Map Display Window(s)"),
  1160. name='IsChecked')
  1161. posDisplay.SetValue(self.settings.Get(group='workspace', key='posDisplay', subkey='enabled'))
  1162. self.winId['workspace:posDisplay:enabled'] = posDisplay.GetId()
  1163. gridSizer.Add(item=posDisplay,
  1164. pos=(row, 0), span=(1, 2))
  1165. row +=1
  1166. posManager = wx.CheckBox(parent=panel, id=wx.ID_ANY,
  1167. label=_("Suppress positioning Layer Manager window"),
  1168. name='IsChecked')
  1169. posManager.SetValue(self.settings.Get(group='workspace', key='posManager', subkey='enabled'))
  1170. self.winId['workspace:posManager:enabled'] = posManager.GetId()
  1171. gridSizer.Add(item=posManager,
  1172. pos=(row, 0), span=(1, 2))
  1173. sizer.Add(item=gridSizer, proportion=1, flag=wx.ALL | wx.EXPAND, border=5)
  1174. border.Add(item=sizer, proportion=0, flag=wx.ALL | wx.EXPAND, border=3)
  1175. panel.SetSizer(border)
  1176. return panel
  1177. def __CreateAdvancedPage(self, notebook):
  1178. """Create notebook page for advanced settings"""
  1179. panel = wx.Panel(parent=notebook, id=wx.ID_ANY)
  1180. notebook.AddPage(page=panel, text=_("Advanced"))
  1181. border = wx.BoxSizer(wx.VERTICAL)
  1182. box = wx.StaticBox (parent=panel, id=wx.ID_ANY, label=" %s " % _("Advanced settings"))
  1183. sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
  1184. gridSizer = wx.GridBagSizer (hgap=3, vgap=3)
  1185. gridSizer.AddGrowableCol(0)
  1186. row = 0
  1187. #
  1188. # place where to store settings
  1189. #
  1190. gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  1191. label=_("Place where to store settings:")),
  1192. flag=wx.ALIGN_LEFT |
  1193. wx.ALIGN_CENTER_VERTICAL,
  1194. pos=(row, 0))
  1195. settingsFile = wx.Choice(parent=panel, id=wx.ID_ANY, size=(125, -1),
  1196. choices=self.settings.Get(group='advanced', key='settingsFile',
  1197. subkey='choices', internal=True),
  1198. name='GetStringSelection')
  1199. settingsFile.SetStringSelection(self.settings.Get(group='advanced', key='settingsFile', subkey='type'))
  1200. self.winId['advanced:settingsFile:type'] = settingsFile.GetId()
  1201. gridSizer.Add(item=settingsFile,
  1202. flag=wx.ALIGN_RIGHT |
  1203. wx.ALIGN_CENTER_VERTICAL,
  1204. pos=(row, 1))
  1205. row += 1
  1206. #
  1207. # icon theme
  1208. #
  1209. gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  1210. label=_("Icon theme:")),
  1211. flag=wx.ALIGN_LEFT |
  1212. wx.ALIGN_CENTER_VERTICAL,
  1213. pos=(row, 0))
  1214. iconTheme = wx.Choice(parent=panel, id=wx.ID_ANY, size=(125, -1),
  1215. choices=self.settings.Get(group='advanced', key='iconTheme',
  1216. subkey='choices', internal=True),
  1217. name="GetStringSelection")
  1218. iconTheme.SetStringSelection(self.settings.Get(group='advanced', key='iconTheme', subkey='type'))
  1219. self.winId['advanced:iconTheme:type'] = iconTheme.GetId()
  1220. gridSizer.Add(item=iconTheme,
  1221. flag=wx.ALIGN_RIGHT |
  1222. wx.ALIGN_CENTER_VERTICAL,
  1223. pos=(row, 1))
  1224. row += 1
  1225. iconNote = wordwrap(_("Note: Requires GUI restart."),
  1226. self.GetSize()[0]-50, wx.ClientDC(self))
  1227. gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  1228. label=iconNote),
  1229. flag=wx.ALIGN_LEFT |
  1230. wx.ALIGN_CENTER_VERTICAL,
  1231. pos=(row, 0), span=(1, 2))
  1232. row += 1
  1233. #
  1234. # digitization interface
  1235. #
  1236. gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  1237. label=_("Vector digitizer interface:")),
  1238. flag=wx.ALIGN_LEFT |
  1239. wx.ALIGN_CENTER_VERTICAL,
  1240. pos=(row, 0))
  1241. digitInterface = wx.Choice(parent=panel, id=wx.ID_ANY, size=(125, -1),
  1242. choices=self.settings.Get(group='advanced', key='digitInterface',
  1243. subkey='choices', internal=True),
  1244. name="GetStringSelection")
  1245. digitInterface.SetStringSelection(self.settings.Get(group='advanced', key='digitInterface',
  1246. subkey='type'))
  1247. self.winId['advanced:digitInterface:type'] = digitInterface.GetId()
  1248. gridSizer.Add(item=digitInterface,
  1249. flag=wx.ALIGN_RIGHT |
  1250. wx.ALIGN_CENTER_VERTICAL,
  1251. pos=(row, 1))
  1252. row += 1
  1253. digitNote = wordwrap(_("Note: User can choose from two interfaces for digitization. "
  1254. "The simple one uses v.edit command on the background. "
  1255. "Map topology is rebuild on each operation which can "
  1256. "significantly slow-down response. The vdigit is a native "
  1257. "interface which uses v.edit functionality, but doesn't "
  1258. "call the module itself."),
  1259. self.GetSize()[0]-50, wx.ClientDC(self))
  1260. gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  1261. label=digitNote),
  1262. flag=wx.ALIGN_LEFT |
  1263. wx.ALIGN_CENTER_VERTICAL,
  1264. pos=(row, 0), span=(1, 2))
  1265. sizer.Add(item=gridSizer, proportion=1, flag=wx.ALL | wx.EXPAND, border=5)
  1266. border.Add(item=sizer, proportion=1, flag=wx.ALL | wx.EXPAND, border=3)
  1267. panel.SetSizer(border)
  1268. return panel
  1269. def OnSetFont(self, event):
  1270. """'Set font' button pressed"""
  1271. dlg = SetDefaultFont(parent=self, id=wx.ID_ANY,
  1272. title=_('Select default display font'),
  1273. pos=wx.DefaultPosition, size=wx.DefaultSize,
  1274. style=wx.DEFAULT_DIALOG_STYLE,
  1275. encoding=self.parent.encoding)
  1276. if dlg.ShowModal() == wx.ID_CANCEL:
  1277. dlg.Destroy()
  1278. return
  1279. # set default font type, font, and encoding to whatever selected in dialog
  1280. if dlg.font != None:
  1281. self.font = dlg.font
  1282. if dlg.encoding != None:
  1283. self.encoding = dlg.encoding
  1284. dlg.Destroy()
  1285. # set default font and encoding environmental variables
  1286. os.environ["GRASS_FONT"] = self.font
  1287. if self.encoding != None and self.encoding != "ISO-8859-1":
  1288. os.environ["GRASS_ENCODING"] = self.encoding
  1289. event.Skip()
  1290. def OnSave(self, event):
  1291. """Button 'Save' pressed"""
  1292. if self.__UpdateSettings():
  1293. file = self.settings.SaveToFile()
  1294. self.parent.goutput.WriteLog(_('Settings saved to file \'%s\'.') % file)
  1295. self.Close()
  1296. def OnApply(self, event):
  1297. """Button 'Apply' pressed"""
  1298. if self.__UpdateSettings():
  1299. self.Close()
  1300. def OnCancel(self, event):
  1301. """Button 'Cancel' pressed"""
  1302. self.Close()
  1303. def OnDefault(self, event):
  1304. """Button 'Set to default' pressed"""
  1305. self.settings.userSettings = copy.deepcopy(self.settings.defaultSettings)
  1306. # update widgets
  1307. for gks in self.winId.keys():
  1308. try:
  1309. group, key, subkey = gks.split(':')
  1310. value = self.settings.Get(group, key, subkey)
  1311. except ValueError:
  1312. group, key, subkey, subkey1 = gks.split(':')
  1313. value = self.settings.Get(group, key, [subkey, subkey1])
  1314. win = self.FindWindowById(self.winId[gks])
  1315. if win.GetName() in ('GetValue', 'IsChecked'):
  1316. value = win.SetValue(value)
  1317. elif win.GetName() == 'GetSelection':
  1318. value = win.SetSelection(value)
  1319. elif win.GetName() == 'GetStringSelection':
  1320. value = win.SetStringSelection(value)
  1321. else:
  1322. value = win.SetValue(value)
  1323. def __UpdateSettings(self):
  1324. """Update user settings"""
  1325. for item in self.winId.keys():
  1326. try:
  1327. group, key, subkey = item.split(':')
  1328. subkey1 = None
  1329. except ValueError:
  1330. group, key, subkey, subkey1 = item.split(':')
  1331. id = self.winId[item]
  1332. win = self.FindWindowById(id)
  1333. if win.GetName() == 'GetValue':
  1334. value = win.GetValue()
  1335. elif win.GetName() == 'GetSelection':
  1336. value = win.GetSelection()
  1337. elif win.GetName() == 'IsChecked':
  1338. value = win.IsChecked()
  1339. elif win.GetName() == 'GetStringSelection':
  1340. value = win.GetStringSelection()
  1341. elif win.GetName() == 'GetColour':
  1342. value = tuple(win.GetValue())
  1343. else:
  1344. value = win.GetValue()
  1345. if key == 'keycolumn' and value == '':
  1346. wx.MessageBox(parent=self,
  1347. message=_("Key column cannot be empty string."),
  1348. caption=_("Error"), style=wx.OK | wx.ICON_ERROR)
  1349. win.SetValue(self.settings.Get(group='atm', key='keycolumn', subkey='value'))
  1350. return False
  1351. if subkey1:
  1352. self.settings.Set(group, value, key, [subkey, subkey1])
  1353. else:
  1354. self.settings.Set(group, value, key, subkey)
  1355. #
  1356. # update default window dimension
  1357. #
  1358. if self.settings.Get(group='general', key='defWindowPos', subkey='enabled') is True:
  1359. dim = ''
  1360. # layer manager
  1361. pos = self.parent.GetPosition()
  1362. size = self.parent.GetSize()
  1363. dim = '%d,%d,%d,%d' % (pos[0], pos[1], size[0], size[1])
  1364. # opened displays
  1365. for page in range(0, self.parent.gm_cb.GetPageCount()):
  1366. pos = self.parent.gm_cb.GetPage(page).maptree.mapdisplay.GetPosition()
  1367. size = self.parent.gm_cb.GetPage(page).maptree.mapdisplay.GetSize()
  1368. dim += ',%d,%d,%d,%d' % (pos[0], pos[1], size[0], size[1])
  1369. self.settings.Set(group='general', key='defWindowPos', subkey='dim', value=dim)
  1370. else:
  1371. self.settings.Set(group='general', key='defWindowPos', subkey='dim', value='')
  1372. return True
  1373. class SetDefaultFont(wx.Dialog):
  1374. """
  1375. Opens a file selection dialog to select default font
  1376. to use in all GRASS displays
  1377. """
  1378. def __init__(self, parent, id, title, pos=wx.DefaultPosition, size=wx.DefaultSize,
  1379. style=wx.DEFAULT_DIALOG_STYLE, encoding='ISO-8859-1'):
  1380. wx.Dialog.__init__(self, parent, id, title, pos, size, style)
  1381. if "GRASS_FONT" in os.environ:
  1382. self.font = os.environ["GRASS_FONT"]
  1383. else:
  1384. self.font = None
  1385. self.fontlist = self.GetFonts()
  1386. self.encoding = encoding
  1387. sizer = wx.BoxSizer(wx.VERTICAL)
  1388. box = wx.BoxSizer(wx.HORIZONTAL)
  1389. label = wx.StaticText(self, -1, "Select Font:", (15, 50))
  1390. box.Add(label, 0, wx.EXPAND|wx.GROW|wx.ALIGN_TOP|wx.RIGHT, 5)
  1391. self.fontlb = wx.ListBox(self, wx.ID_ANY, pos=wx.DefaultPosition,
  1392. size=(280,150), choices=self.fontlist,
  1393. style=wx.LB_SINGLE|wx.LB_SORT)
  1394. self.Bind(wx.EVT_LISTBOX, self.EvtListBox, self.fontlb)
  1395. self.Bind(wx.EVT_LISTBOX_DCLICK, self.EvtListBoxDClick, self.fontlb)
  1396. if self.font:
  1397. self.fontlb.SetStringSelection(self.font, True)
  1398. box.Add(self.fontlb, 0, wx.EXPAND|wx.GROW|wx.ALIGN_RIGHT)
  1399. sizer.Add(box, 0, wx.EXPAND|wx.GROW|wx.ALIGN_RIGHT|wx.ALL, 8)
  1400. box = wx.BoxSizer(wx.HORIZONTAL)
  1401. label = wx.StaticText(self, -1, "Character encoding:")
  1402. box.Add(label, 0, wx.ALIGN_RIGHT|wx.RIGHT, 5)
  1403. self.textentry = wx.TextCtrl(self, -1, "", size=(200,-1))
  1404. self.textentry.SetValue(self.encoding)
  1405. box.Add(self.textentry, 0, wx.ALIGN_LEFT)
  1406. self.textentry.Bind(wx.EVT_TEXT, self.OnEncoding)
  1407. sizer.Add(box, 0, wx.GROW|wx.ALIGN_CENTER_VERTICAL|wx.ALL, 8)
  1408. line = wx.StaticLine(self, -1, size=(20,-1), style=wx.LI_HORIZONTAL)
  1409. sizer.Add(line, 0, wx.GROW|wx.ALIGN_CENTER_VERTICAL|wx.ALL, 10)
  1410. btnsizer = wx.StdDialogButtonSizer()
  1411. btn = wx.Button(self, wx.ID_OK)
  1412. btn.SetDefault()
  1413. btnsizer.AddButton(btn)
  1414. btn = wx.Button(self, wx.ID_CANCEL)
  1415. btnsizer.AddButton(btn)
  1416. btnsizer.Realize()
  1417. sizer.Add(btnsizer, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5)
  1418. self.SetSizer(sizer)
  1419. sizer.Fit(self)
  1420. def EvtRadioBox(self, event):
  1421. if event.GetInt() == 0:
  1422. self.fonttype = 'grassfont'
  1423. elif event.GetInt() == 1:
  1424. self.fonttype = 'truetype'
  1425. self.fontlist = self.GetFonts(self.fonttype)
  1426. self.fontlb.SetItems(self.fontlist)
  1427. def OnEncoding(self, event):
  1428. self.encoding = event.GetString()
  1429. def EvtListBox(self, event):
  1430. self.font = event.GetString()
  1431. event.Skip()
  1432. def EvtListBoxDClick(self, event):
  1433. self.font = event.GetString()
  1434. event.Skip()
  1435. def GetFonts(self):
  1436. """
  1437. parses fonts directory or fretypecap file to get a list of fonts for the listbox
  1438. """
  1439. fontlist = []
  1440. cmd = ["d.font", "-l"]
  1441. p = gcmd.Command(cmd, stderr=None)
  1442. dfonts = p.ReadStdOutput()
  1443. dfonts.sort(lambda x,y: cmp(x.lower(), y.lower()))
  1444. for item in range(len(dfonts)):
  1445. # ignore duplicate fonts and those starting with #
  1446. if not dfonts[item].startswith('#') and \
  1447. dfonts[item] != dfonts[item-1]:
  1448. fontlist.append(dfonts[item])
  1449. return fontlist
  1450. class MapsetAccess(wx.Dialog):
  1451. """
  1452. Controls setting options and displaying/hiding map overlay decorations
  1453. """
  1454. def __init__(self, parent, id, title=_('Set/unset access to mapsets in current location'),
  1455. pos=wx.DefaultPosition, size=(350, 400),
  1456. style=wx.DEFAULT_DIALOG_STYLE|wx.RESIZE_BORDER):
  1457. wx.Dialog.__init__(self, parent, id, title, pos, size, style)
  1458. self.all_mapsets = utils.ListOfMapsets(all=True)
  1459. self.accessible_mapsets = utils.ListOfMapsets(all=False)
  1460. self.curr_mapset = grassenv.GetGRASSVariable('MAPSET')
  1461. # make a checklistbox from available mapsets and check those that are active
  1462. sizer = wx.BoxSizer(wx.VERTICAL)
  1463. label = wx.StaticText(parent=self, id=wx.ID_ANY,
  1464. label=_("Check mapset to make it accessible, uncheck it to hide it.%s"
  1465. "Note: PERMANENT and current mapset are always accessible.") % os.linesep)
  1466. sizer.Add(item=label, proportion=0,
  1467. flag=wx.ALL, border=5)
  1468. self.mapsetlb = CheckListMapset(parent=self)
  1469. self.mapsetlb.LoadData(self.all_mapsets)
  1470. sizer.Add(item=self.mapsetlb, proportion=1,
  1471. flag=wx.ALL | wx.EXPAND, border=5)
  1472. # check all accessible mapsets
  1473. for mset in self.accessible_mapsets:
  1474. self.mapsetlb.CheckItem(self.all_mapsets.index(mset), True)
  1475. # dialog buttons
  1476. line = wx.StaticLine(parent=self, id=wx.ID_ANY,
  1477. style=wx.LI_HORIZONTAL)
  1478. sizer.Add(item=line, proportion=0,
  1479. flag=wx.EXPAND | wx.ALIGN_CENTRE | wx.ALL, border=5)
  1480. btnsizer = wx.StdDialogButtonSizer()
  1481. okbtn = wx.Button(self, wx.ID_OK)
  1482. okbtn.SetDefault()
  1483. btnsizer.AddButton(okbtn)
  1484. cancelbtn = wx.Button(self, wx.ID_CANCEL)
  1485. btnsizer.AddButton(cancelbtn)
  1486. btnsizer.Realize()
  1487. sizer.Add(item=btnsizer, proportion=0,
  1488. flag=wx.EXPAND | wx.ALIGN_RIGHT | wx.ALL, border=5)
  1489. # do layout
  1490. self.Layout()
  1491. self.SetSizer(sizer)
  1492. sizer.Fit(self)
  1493. self.SetMinSize(size)
  1494. def GetMapsets(self):
  1495. """Get list of checked mapsets"""
  1496. ms = []
  1497. i = 0
  1498. for mset in self.all_mapsets:
  1499. if self.mapsetlb.IsChecked(i):
  1500. ms.append(mset)
  1501. i += 1
  1502. return ms
  1503. class CheckListMapset(wx.ListCtrl, listmix.ListCtrlAutoWidthMixin, listmix.CheckListCtrlMixin):
  1504. """List of mapset/owner/group"""
  1505. def __init__(self, parent, pos=wx.DefaultPosition,
  1506. log=None):
  1507. self.parent = parent
  1508. wx.ListCtrl.__init__(self, parent, wx.ID_ANY,
  1509. style=wx.LC_REPORT)
  1510. listmix.CheckListCtrlMixin.__init__(self)
  1511. self.log = log
  1512. # setup mixins
  1513. listmix.ListCtrlAutoWidthMixin.__init__(self)
  1514. def LoadData(self, mapsets):
  1515. """Load data into list"""
  1516. self.InsertColumn(0, _('Mapset'))
  1517. self.InsertColumn(1, _('Owner'))
  1518. self.InsertColumn(2, _('Group'))
  1519. locationPath = os.path.join(grassenv.GetGRASSVariable('GISDBASE'),
  1520. grassenv.GetGRASSVariable('LOCATION_NAME'))
  1521. for mapset in mapsets:
  1522. index = self.InsertStringItem(sys.maxint, mapset)
  1523. mapsetPath = os.path.join(locationPath,
  1524. mapset)
  1525. stat_info = os.stat(mapsetPath)
  1526. if os.name in ('posix', 'mac'):
  1527. self.SetStringItem(index, 1, "%s" % pwd.getpwuid(stat_info.st_uid)[0])
  1528. # FIXME: get group name
  1529. self.SetStringItem(index, 2, "%-8s" % stat_info.st_gid)
  1530. else:
  1531. # FIXME: no pwd under MS Windows (owner: 0, group: 0)
  1532. self.SetStringItem(index, 1, "%-8s" % stat_info.st_uid)
  1533. self.SetStringItem(index, 2, "%-8s" % stat_info.st_gid)
  1534. self.SetColumnWidth(col=0, width=wx.LIST_AUTOSIZE)
  1535. self.SetColumnWidth(col=1, width=wx.LIST_AUTOSIZE)
  1536. def OnCheckItem(self, index, flag):
  1537. """Mapset checked/unchecked"""
  1538. mapset = self.parent.all_mapsets[index]
  1539. if mapset == 'PERMANENT' or mapset == self.parent.curr_mapset:
  1540. self.CheckItem(index, True)