preferences.py 69 KB

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