settings.py 39 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082
  1. """!
  2. @package core.settings
  3. @brief Default GUI settings
  4. List of classes:
  5. - settings::Settings
  6. Usage:
  7. @code
  8. from core.settings import UserSettings
  9. @endcode
  10. (C) 2007-2011 by the GRASS Development Team
  11. This program is free software under the GNU General Public License
  12. (>=v2). Read the file COPYING that comes with GRASS for details.
  13. @author Martin Landa <landa.martin gmail.com>
  14. @author Luca Delucchi <lucadeluge gmail.com> (language choice)
  15. """
  16. import os
  17. import sys
  18. import copy
  19. import types
  20. import locale
  21. from core import globalvar
  22. from core.gcmd import GException, GError
  23. from core.utils import GetSettingsPath, PathJoin
  24. class Settings:
  25. """!Generic class where to store settings"""
  26. def __init__(self):
  27. # settings file
  28. self.filePath = os.path.join(GetSettingsPath(), 'wx')
  29. # key/value separator
  30. self.sep = ';'
  31. # define default settings
  32. self._defaultSettings() # -> self.defaultSettings
  33. # read settings from the file
  34. self.userSettings = copy.deepcopy(self.defaultSettings)
  35. try:
  36. self.ReadSettingsFile()
  37. except GException, e:
  38. print >> sys.stderr, e.value
  39. # define internal settings
  40. self._internalSettings() # -> self.internalSettings
  41. def _generateLocale(self):
  42. """!Generate locales
  43. """
  44. loc = list(locale.getdefaultlocale())
  45. if loc[1] == 'UTF8':
  46. loc[1] = 'UTF-8'
  47. code_loc = "%s.%s" % (loc[0],loc[1])
  48. self.locs = list(set(locale.locale_alias.values()))
  49. self.locs.append('en_GB.UTF-8')
  50. self.locs.sort()
  51. try:
  52. return locs.index(code_loc)
  53. except:
  54. pass
  55. return None
  56. def _defaultSettings(self):
  57. """!Define default settings
  58. """
  59. try:
  60. projFile = PathJoin(os.environ["GRASS_PROJSHARE"], 'epsg')
  61. except KeyError:
  62. projFile = ''
  63. id_loc = self._generateLocale()
  64. self.defaultSettings = {
  65. #
  66. # general
  67. #
  68. 'general': {
  69. # use default window layout (layer manager, displays, ...)
  70. 'defWindowPos' : {
  71. 'enabled' : True,
  72. 'dim' : '0,0,%d,%d,%d,0,%d,%d' % \
  73. (globalvar.GM_WINDOW_SIZE[0],
  74. globalvar.GM_WINDOW_SIZE[1],
  75. globalvar.GM_WINDOW_SIZE[0],
  76. globalvar.MAP_WINDOW_SIZE[0],
  77. globalvar.MAP_WINDOW_SIZE[1])
  78. },
  79. # workspace
  80. 'workspace' : {
  81. 'posDisplay' : {
  82. 'enabled' : False
  83. },
  84. 'posManager' : {
  85. 'enabled' : False
  86. },
  87. },
  88. },
  89. 'manager' : {
  90. # show opacity level widget
  91. 'changeOpacityLevel' : {
  92. 'enabled' : False
  93. },
  94. # ask when removing layer from layer tree
  95. 'askOnRemoveLayer' : {
  96. 'enabled' : True
  97. },
  98. # ask when quiting wxGUI or closing display
  99. 'askOnQuit' : {
  100. 'enabled' : True
  101. },
  102. # hide tabs
  103. 'hideTabs' : {
  104. 'search' : False,
  105. 'pyshell' : False,
  106. },
  107. 'copySelectedTextToClipboard' : {
  108. 'enabled' : False
  109. },
  110. },
  111. #
  112. # appearance
  113. #
  114. 'appearance': {
  115. 'outputfont' : {
  116. 'type' : 'Courier New',
  117. 'size': '10',
  118. },
  119. # expand/collapse element list
  120. 'elementListExpand' : {
  121. 'selection' : 0
  122. },
  123. 'menustyle' : {
  124. 'selection' : 1
  125. },
  126. 'gSelectPopupHeight' : {
  127. 'value' : 200
  128. },
  129. 'iconTheme' : {
  130. 'type' : 'grass'
  131. },
  132. },
  133. #
  134. # language
  135. #
  136. 'language': {
  137. 'locale': {
  138. 'lc_all' : id_loc
  139. }
  140. },
  141. #
  142. # display
  143. #
  144. 'display': {
  145. 'font' : {
  146. 'type' : '',
  147. 'encoding': 'ISO-8859-1',
  148. },
  149. 'driver': {
  150. 'type': 'cairo'
  151. },
  152. 'alignExtent' : {
  153. 'enabled' : True
  154. },
  155. 'compResolution' : {
  156. 'enabled' : False
  157. },
  158. 'autoRendering': {
  159. 'enabled' : True
  160. },
  161. 'autoZooming' : {
  162. 'enabled' : False
  163. },
  164. 'statusbarMode': {
  165. 'selection' : 0
  166. },
  167. 'bgcolor': {
  168. 'color' : (255, 255, 255, 255),
  169. },
  170. },
  171. #
  172. # projection
  173. #
  174. 'projection' : {
  175. 'statusbar' : {
  176. 'proj4' : '',
  177. 'epsg' : '',
  178. 'projFile' : projFile,
  179. },
  180. 'format' : {
  181. 'll' : 'DMS',
  182. 'precision' : 2,
  183. },
  184. },
  185. #
  186. # Attribute Table Manager
  187. #
  188. 'atm' : {
  189. 'highlight' : {
  190. 'color' : (255, 255, 0, 255),
  191. 'width' : 2
  192. },
  193. 'leftDbClick' : {
  194. 'selection' : 1 # draw selected
  195. },
  196. 'askOnDeleteRec' : {
  197. 'enabled' : True
  198. },
  199. 'keycolumn' : {
  200. 'value' : 'cat'
  201. },
  202. 'encoding' : {
  203. 'value' : '',
  204. }
  205. },
  206. #
  207. # Command
  208. #
  209. 'cmd': {
  210. 'overwrite' : {
  211. 'enabled' : False
  212. },
  213. 'closeDlg' : {
  214. 'enabled' : False
  215. },
  216. 'verbosity' : {
  217. 'selection' : 'grassenv'
  218. },
  219. # d.rast
  220. 'rasterOpaque' : {
  221. 'enabled' : False
  222. },
  223. 'rasterColorTable' : {
  224. 'enabled' : False,
  225. 'selection' : 'rainbow',
  226. },
  227. # d.vect
  228. 'showType': {
  229. 'point' : {
  230. 'enabled' : True
  231. },
  232. 'line' : {
  233. 'enabled' : True
  234. },
  235. 'centroid' : {
  236. 'enabled' : True
  237. },
  238. 'boundary' : {
  239. 'enabled' : True
  240. },
  241. 'area' : {
  242. 'enabled' : True
  243. },
  244. 'face' : {
  245. 'enabled' : True
  246. },
  247. },
  248. 'addNewLayer' : {
  249. 'enabled' : True,
  250. },
  251. 'interactiveInput' : {
  252. 'enabled' : True,
  253. },
  254. },
  255. #
  256. # vdigit
  257. #
  258. 'vdigit' : {
  259. # symbology
  260. 'symbol' : {
  261. 'highlight' : {
  262. 'enabled' : None,
  263. 'color' : (255, 255, 0, 255)
  264. }, # yellow
  265. 'highlightDupl' : {
  266. 'enabled' : None,
  267. 'color' : (255, 72, 0, 255)
  268. }, # red
  269. 'point' : {
  270. 'enabled' : True,
  271. 'color' : (0, 0, 0, 255)
  272. }, # black
  273. 'line' : {
  274. 'enabled' : True,
  275. 'color' : (0, 0, 0, 255)
  276. }, # black
  277. 'boundaryNo' : {
  278. 'enabled' : True,
  279. 'color' : (126, 126, 126, 255)
  280. }, # grey
  281. 'boundaryOne' : {
  282. 'enabled' : True,
  283. 'color' : (0, 255, 0, 255)
  284. }, # green
  285. 'boundaryTwo' : {
  286. 'enabled' : True,
  287. 'color' : (255, 135, 0, 255)
  288. }, # orange
  289. 'centroidIn' : {
  290. 'enabled' : True,
  291. 'color' : (0, 0, 255, 255)
  292. }, # blue
  293. 'centroidOut' : {
  294. 'enabled' : True,
  295. 'color' : (165, 42, 42, 255)
  296. }, # brown
  297. 'centroidDup' : {
  298. 'enabled' : True,
  299. 'color' : (156, 62, 206, 255)
  300. }, # violet
  301. 'nodeOne' : {
  302. 'enabled' : True,
  303. 'color' : (255, 0, 0, 255)
  304. }, # red
  305. 'nodeTwo' : {
  306. 'enabled' : True,
  307. 'color' : (0, 86, 45, 255)
  308. }, # dark green
  309. 'vertex' : {
  310. 'enabled' : False,
  311. 'color' : (255, 20, 147, 255)
  312. }, # deep pink
  313. 'area' : {
  314. 'enabled' : False,
  315. 'color' : (217, 255, 217, 255)
  316. }, # green
  317. 'direction' : {
  318. 'enabled' : False,
  319. 'color' : (255, 0, 0, 255)
  320. }, # red
  321. },
  322. # display
  323. 'lineWidth' : {
  324. 'value' : 2,
  325. 'units' : 'screen pixels'
  326. },
  327. # snapping
  328. 'snapping' : {
  329. 'value' : 10,
  330. 'units' : 'screen pixels'
  331. },
  332. 'snapToVertex' : {
  333. 'enabled' : False
  334. },
  335. # digitize new record
  336. 'addRecord' : {
  337. 'enabled' : True
  338. },
  339. 'layer' :{
  340. 'value' : 1
  341. },
  342. 'category' : {
  343. 'value' : 1
  344. },
  345. 'categoryMode' : {
  346. 'selection' : 0
  347. },
  348. # delete existing feature(s)
  349. 'delRecord' : {
  350. 'enabled' : True
  351. },
  352. # query tool
  353. 'query' : {
  354. 'selection' : 0,
  355. 'box' : True
  356. },
  357. 'queryLength' : {
  358. 'than-selection' : 0,
  359. 'thresh' : 0
  360. },
  361. 'queryDangle' : {
  362. 'than-selection' : 0,
  363. 'thresh' : 0
  364. },
  365. # select feature (point, line, centroid, boundary)
  366. 'selectType': {
  367. 'point' : {
  368. 'enabled' : True
  369. },
  370. 'line' : {
  371. 'enabled' : True
  372. },
  373. 'centroid' : {
  374. 'enabled' : True
  375. },
  376. 'boundary' : {
  377. 'enabled' : True
  378. },
  379. },
  380. 'selectThresh' : {
  381. 'value' : 10,
  382. 'units' : 'screen pixels'
  383. },
  384. 'checkForDupl' : {
  385. 'enabled' : False
  386. },
  387. 'selectInside' : {
  388. 'enabled' : False
  389. },
  390. # exit
  391. 'saveOnExit' : {
  392. 'enabled' : False,
  393. },
  394. # break lines on intersection
  395. 'breakLines' : {
  396. 'enabled' : False,
  397. },
  398. },
  399. #
  400. # plots for profiles, histograms, and scatterplots
  401. #
  402. 'profile': {
  403. 'raster' : {
  404. 'pcolor' : (0, 0, 255, 255), # line color
  405. 'pwidth' : 1, # line width
  406. 'pstyle' : 'solid', # line pen style
  407. 'datatype' : 'cell', # raster type
  408. },
  409. 'font' : {
  410. 'titleSize' : 12,
  411. 'axisSize' : 11,
  412. 'legendSize' : 10,
  413. },
  414. 'marker' : {
  415. 'color' : (0, 0, 0, 255),
  416. 'fill' : 'transparent',
  417. 'size' : 2,
  418. 'type' : 'triangle',
  419. 'legend' : _('Segment break'),
  420. },
  421. 'grid' : {
  422. 'color' : (200, 200, 200, 255),
  423. 'enabled' : True,
  424. },
  425. 'x-axis' : {
  426. 'type' : 'auto', # axis format
  427. 'min' : 0, # axis min for custom axis range
  428. 'max': 0, # axis max for custom axis range
  429. 'log' : False,
  430. },
  431. 'y-axis' : {
  432. 'type' : 'auto', # axis format
  433. 'min' : 0, # axis min for custom axis range
  434. 'max': 0, # axis max for custom axis range
  435. 'log' : False,
  436. },
  437. 'legend' : {
  438. 'enabled' : True
  439. },
  440. },
  441. 'histogram': {
  442. 'raster' : {
  443. 'pcolor' : (0, 0, 255, 255), # line color
  444. 'pwidth' : 1, # line width
  445. 'pstyle' : 'solid', # line pen style
  446. 'datatype' : 'cell', # raster type
  447. },
  448. 'font' : {
  449. 'titleSize' : 12,
  450. 'axisSize' : 11,
  451. 'legendSize' : 10,
  452. },
  453. 'grid' : {
  454. 'color' : (200, 200, 200, 255),
  455. 'enabled' : True,
  456. },
  457. 'x-axis' : {
  458. 'type' : 'auto', # axis format
  459. 'min' : 0, # axis min for custom axis range
  460. 'max' : 0, # axis max for custom axis range
  461. 'log' : False,
  462. },
  463. 'y-axis' : {
  464. 'type' : 'auto', # axis format
  465. 'min' : 0, # axis min for custom axis range
  466. 'max' : 0, # axis max for custom axis range
  467. 'log' : False,
  468. },
  469. 'legend' : {
  470. 'enabled' : True
  471. },
  472. },
  473. 'scatter': {
  474. 'rasters' : {
  475. 'pcolor' : (0, 0, 255, 255),
  476. 'pfill' : 'solid',
  477. 'psize' : 1,
  478. 'ptype' : 'dot',
  479. 'plegend' : _('Data point'),
  480. 0 : {'datatype' : 'CELL'},
  481. 1 : {'datatype' : 'CELL'},
  482. },
  483. 'font' : {
  484. 'titleSize' : 12,
  485. 'axisSize' : 11,
  486. 'legendSize' : 10,
  487. },
  488. 'grid' : {
  489. 'color' : (200, 200, 200, 255),
  490. 'enabled' : True,
  491. },
  492. 'x-axis' : {
  493. 'type' : 'auto', # axis format
  494. 'min' : 0, # axis min for custom axis range
  495. 'max' : 0, # axis max for custom axis range
  496. 'log' : False,
  497. },
  498. 'y-axis' : {
  499. 'type' : 'auto', # axis format
  500. 'min' : 0, # axis min for custom axis range
  501. 'max' : 0, # axis max for custom axis range
  502. 'log' : False,
  503. },
  504. 'legend' : {
  505. 'enabled' : True
  506. },
  507. },
  508. 'gcpman' : {
  509. 'rms' : {
  510. 'highestonly' : True,
  511. 'sdfactor' : 1,
  512. },
  513. 'symbol' : {
  514. 'color' : (0, 0, 255, 255),
  515. 'hcolor' : (255, 0, 0, 255),
  516. 'scolor' : (0, 255, 0, 255),
  517. 'ucolor' : (255, 165, 0, 255),
  518. 'unused' : True,
  519. 'size' : 8,
  520. 'width' : 2,
  521. },
  522. },
  523. 'nviz' : {
  524. 'view' : {
  525. 'persp' : {
  526. 'value' : 20,
  527. 'step' : 2,
  528. },
  529. 'position' : {
  530. 'x' : 0.84,
  531. 'y' : 0.16,
  532. },
  533. 'twist' : {
  534. 'value' : 0,
  535. },
  536. 'z-exag' : {
  537. 'min' : 0,
  538. 'max' : 10,
  539. 'value': 1,
  540. },
  541. 'background' : {
  542. 'color' : (255, 255, 255, 255), # white
  543. },
  544. },
  545. 'fly' : {
  546. 'exag' : {
  547. 'move' : 5,
  548. 'turn' : 5,
  549. }
  550. },
  551. 'animation' : {
  552. 'fps' : 24,
  553. 'prefix' : _("animation")
  554. },
  555. 'surface' : {
  556. 'shine': {
  557. 'map' : False,
  558. 'value' : 60.0,
  559. },
  560. 'color' : {
  561. 'map' : True,
  562. 'value' : (100, 100, 100, 255), # constant: grey
  563. },
  564. 'draw' : {
  565. 'wire-color' : (136, 136, 136, 255),
  566. 'mode' : 1, # fine
  567. 'style' : 1, # surface
  568. 'shading' : 1, # gouraud
  569. 'res-fine' : 6,
  570. 'res-coarse' : 9,
  571. },
  572. 'position' : {
  573. 'x' : 0,
  574. 'y' : 0,
  575. 'z' : 0,
  576. },
  577. },
  578. 'constant' : {
  579. 'color' : (100, 100, 100, 255),
  580. 'value' : 0.0,
  581. 'transp' : 0,
  582. 'resolution': 6
  583. },
  584. 'vector' : {
  585. 'lines' : {
  586. 'show' : False,
  587. 'width' : 2,
  588. 'color' : (0, 0, 255, 255), # blue
  589. 'flat' : False,
  590. 'height' : 0,
  591. 'rgbcolumn': None,
  592. 'sizecolumn': None,
  593. },
  594. 'points' : {
  595. 'show' : False,
  596. 'size' : 100,
  597. 'width' : 2,
  598. 'marker' : 2,
  599. 'color' : (0, 0, 255, 255), # blue
  600. 'height' : 0,
  601. 'rgbcolumn': None,
  602. 'sizecolumn': None,
  603. }
  604. },
  605. 'volume' : {
  606. 'color' : {
  607. 'map' : True,
  608. 'value' : (100, 100, 100, 255), # constant: grey
  609. },
  610. 'draw' : {
  611. 'mode' : 0, # isosurfaces
  612. 'shading' : 1, # gouraud
  613. 'resolution' : 3, # polygon resolution
  614. },
  615. 'shine': {
  616. 'map' : False,
  617. 'value' : 60,
  618. },
  619. 'topo': {
  620. 'map' : None,
  621. 'value' : 0.0
  622. },
  623. 'transp': {
  624. 'map' : None,
  625. 'value': 0
  626. },
  627. 'mask': {
  628. 'map' : None,
  629. 'value': ''
  630. },
  631. 'slice_position': {
  632. 'x1' : 0,
  633. 'x2' : 1,
  634. 'y1' : 0,
  635. 'y2' : 1,
  636. 'z1' : 0,
  637. 'z2' : 1,
  638. 'axis' : 0,
  639. }
  640. },
  641. 'cplane' : {
  642. 'shading': 4,
  643. 'rotation':{
  644. 'rot': 0,
  645. 'tilt': 0
  646. },
  647. 'position':{
  648. 'x' : 0,
  649. 'y' : 0,
  650. 'z' : 0
  651. }
  652. },
  653. 'light' : {
  654. 'position' : {
  655. 'x' : 0.68,
  656. 'y' : -0.68,
  657. 'z' : 80,
  658. },
  659. 'bright' : 80,
  660. 'color' : (255, 255, 255, 255), # white
  661. 'ambient' : 20,
  662. },
  663. 'fringe' : {
  664. 'elev' : 55,
  665. 'color' : (128, 128, 128, 255), # grey
  666. },
  667. 'arrow': {
  668. 'color': (0, 0, 0),
  669. },
  670. 'scalebar': {
  671. 'color': (0, 0, 0),
  672. }
  673. },
  674. 'modeler' : {
  675. 'disabled': {
  676. 'color': (211, 211, 211, 255), # light grey
  677. },
  678. 'action' : {
  679. 'color' : {
  680. 'valid' : (180, 234, 154, 255), # light green
  681. 'invalid' : (255, 255, 255, 255), # white
  682. 'running' : (255, 0, 0, 255), # red
  683. },
  684. 'size' : {
  685. 'width' : 100,
  686. 'height' : 50,
  687. },
  688. 'width': {
  689. 'parameterized' : 2,
  690. 'default' : 1,
  691. },
  692. },
  693. 'data' : {
  694. 'color': {
  695. 'raster' : (215, 215, 248, 255), # light blue
  696. 'raster3d' : (215, 248, 215, 255), # light green
  697. 'vector' : (248, 215, 215, 255), # light red
  698. },
  699. 'size' : {
  700. 'width' : 175,
  701. 'height' : 50,
  702. },
  703. },
  704. 'loop' : {
  705. 'color' : {
  706. 'valid' : (234, 226, 154, 255), # light yellow
  707. },
  708. 'size' : {
  709. 'width' : 175,
  710. 'height' : 40,
  711. },
  712. },
  713. 'if-else' : {
  714. 'size' : {
  715. 'width' : 150,
  716. 'height' : 40,
  717. },
  718. },
  719. },
  720. }
  721. # quick fix, http://trac.osgeo.org/grass/ticket/1233
  722. # TODO
  723. if sys.platform == 'darwin':
  724. self.defaultSettings['general']['defWindowPos']['enabled'] = False
  725. def _internalSettings(self):
  726. """!Define internal settings (based on user settings)
  727. """
  728. self.internalSettings = {}
  729. for group in self.userSettings.keys():
  730. self.internalSettings[group] = {}
  731. for key in self.userSettings[group].keys():
  732. self.internalSettings[group][key] = {}
  733. # self.internalSettings['general']["mapsetPath"]['value'] = self.GetMapsetPath()
  734. self.internalSettings['appearance']['elementListExpand']['choices'] = \
  735. (_("Collapse all except PERMANENT and current"),
  736. _("Collapse all except PERMANENT"),
  737. _("Collapse all except current"),
  738. _("Collapse all"),
  739. _("Expand all"))
  740. self.internalSettings['language']['locale']['choices'] = tuple(self.locs)
  741. self.internalSettings['atm']['leftDbClick']['choices'] = (_('Edit selected record'),
  742. _('Display selected'))
  743. self.internalSettings['cmd']['verbosity']['choices'] = ('grassenv',
  744. 'verbose',
  745. 'quiet')
  746. self.internalSettings['appearance']['iconTheme']['choices'] = ('grass',)
  747. self.internalSettings['appearance']['menustyle']['choices'] = \
  748. (_("Classic (labels only)"),
  749. _("Combined (labels and module names)"),
  750. _("Professional (module names only)"))
  751. self.internalSettings['appearance']['gSelectPopupHeight']['min'] = 50
  752. # there is also maxHeight given to TreeCtrlComboPopup.GetAdjustedSize
  753. self.internalSettings['appearance']['gSelectPopupHeight']['max'] = 1000
  754. self.internalSettings['display']['driver']['choices'] = ['cairo', 'png']
  755. self.internalSettings['display']['statusbarMode']['choices'] = None # set during MapFrame init
  756. self.internalSettings['nviz']['view'] = {}
  757. self.internalSettings['nviz']['view']['twist'] = {}
  758. self.internalSettings['nviz']['view']['twist']['min'] = -180
  759. self.internalSettings['nviz']['view']['twist']['max'] = 180
  760. self.internalSettings['nviz']['view']['persp'] = {}
  761. self.internalSettings['nviz']['view']['persp']['min'] = 1
  762. self.internalSettings['nviz']['view']['persp']['max'] = 100
  763. self.internalSettings['nviz']['view']['height'] = {}
  764. self.internalSettings['nviz']['view']['height']['value'] = -1
  765. self.internalSettings['nviz']['view']['z-exag'] = {}
  766. self.internalSettings['nviz']['view']['z-exag']['original'] = 1
  767. self.internalSettings['nviz']['view']['rotation'] = None
  768. self.internalSettings['nviz']['view']['focus'] = {}
  769. self.internalSettings['nviz']['view']['focus']['x'] = -1
  770. self.internalSettings['nviz']['view']['focus']['y'] = -1
  771. self.internalSettings['nviz']['view']['focus']['z'] = -1
  772. self.internalSettings['nviz']['view']['dir'] = {}
  773. self.internalSettings['nviz']['view']['dir']['x'] = -1
  774. self.internalSettings['nviz']['view']['dir']['y'] = -1
  775. self.internalSettings['nviz']['view']['dir']['z'] = -1
  776. self.internalSettings['nviz']['view']['dir']['use'] = False
  777. for decor in ('arrow', 'scalebar'):
  778. self.internalSettings['nviz'][decor] = {}
  779. self.internalSettings['nviz'][decor]['position'] = {}
  780. self.internalSettings['nviz'][decor]['position']['x'] = 0
  781. self.internalSettings['nviz'][decor]['position']['y'] = 0
  782. self.internalSettings['nviz'][decor]['size'] = 100
  783. self.internalSettings['nviz']['vector'] = {}
  784. self.internalSettings['nviz']['vector']['points'] = {}
  785. self.internalSettings['nviz']['vector']['points']['marker'] = ("x",
  786. _("box"),
  787. _("sphere"),
  788. _("cube"),
  789. _("diamond"),
  790. _("dtree"),
  791. _("ctree"),
  792. _("aster"),
  793. _("gyro"),
  794. _("histogram"))
  795. self.internalSettings['vdigit']['bgmap'] = {}
  796. self.internalSettings['vdigit']['bgmap']['value'] = ''
  797. def ReadSettingsFile(self, settings = None):
  798. """!Reads settings file (mapset, location, gisdbase)"""
  799. if settings is None:
  800. settings = self.userSettings
  801. self._readFile(self.filePath, settings)
  802. # set environment variables
  803. font = self.Get(group = 'display', key = 'font', subkey = 'type')
  804. enc = self.Get(group = 'display', key = 'font', subkey = 'encoding')
  805. if font:
  806. os.environ["GRASS_FONT"] = font
  807. if enc:
  808. os.environ["GRASS_ENCODING"] = enc
  809. def _readFile(self, filename, settings = None):
  810. """!Read settings from file to dict
  811. @param filename settings file path
  812. @param settings dict where to store settings (None for self.userSettings)
  813. """
  814. if settings is None:
  815. settings = self.userSettings
  816. if not os.path.exists(filename):
  817. return
  818. try:
  819. fd = open(filename, "r")
  820. except IOError:
  821. sys.stderr.write(_("Unable to read settings file <%s>\n") % filename)
  822. return
  823. try:
  824. line = ''
  825. for line in fd.readlines():
  826. line = line.rstrip('%s' % os.linesep)
  827. group, key = line.split(self.sep)[0:2]
  828. kv = line.split(self.sep)[2:]
  829. subkeyMaster = None
  830. if len(kv) % 2 != 0: # multiple (e.g. nviz)
  831. subkeyMaster = kv[0]
  832. del kv[0]
  833. idx = 0
  834. while idx < len(kv):
  835. if subkeyMaster:
  836. subkey = [subkeyMaster, kv[idx]]
  837. else:
  838. subkey = kv[idx]
  839. value = kv[idx+1]
  840. value = self._parseValue(value, read = True)
  841. self.Append(settings, group, key, subkey, value)
  842. idx += 2
  843. except ValueError, e:
  844. print >> sys.stderr, _("Error: Reading settings from file <%(file)s> failed.\n"
  845. "\t\tDetails: %(detail)s\n"
  846. "\t\tLine: '%(line)s'\n") % { 'file' : filename,
  847. 'detail' : e,
  848. 'line' : line }
  849. fd.close()
  850. fd.close()
  851. def SaveToFile(self, settings = None):
  852. """!Save settings to the file"""
  853. if settings is None:
  854. settings = self.userSettings
  855. dirPath = GetSettingsPath()
  856. if not os.path.exists(dirPath):
  857. try:
  858. os.mkdir(dirPath)
  859. except:
  860. GError(_('Unable to create settings directory'))
  861. return
  862. try:
  863. file = open(self.filePath, "w")
  864. for group in settings.keys():
  865. for key in settings[group].keys():
  866. subkeys = settings[group][key].keys()
  867. file.write('%s%s%s%s' % (group, self.sep, key, self.sep))
  868. for idx in range(len(subkeys)):
  869. value = settings[group][key][subkeys[idx]]
  870. if type(value) == types.DictType:
  871. if idx > 0:
  872. file.write('%s%s%s%s%s' % (os.linesep, group, self.sep, key, self.sep))
  873. file.write('%s%s' % (subkeys[idx], self.sep))
  874. kvalues = settings[group][key][subkeys[idx]].keys()
  875. srange = range(len(kvalues))
  876. for sidx in srange:
  877. svalue = self._parseValue(settings[group][key][subkeys[idx]][kvalues[sidx]])
  878. file.write('%s%s%s' % (kvalues[sidx], self.sep,
  879. svalue))
  880. if sidx < len(kvalues) - 1:
  881. file.write('%s' % self.sep)
  882. else:
  883. if idx > 0 and \
  884. type(settings[group][key][subkeys[idx - 1]]) == types.DictType:
  885. file.write('%s%s%s%s%s' % (os.linesep, group, self.sep, key, self.sep))
  886. value = self._parseValue(settings[group][key][subkeys[idx]])
  887. file.write('%s%s%s' % (subkeys[idx], self.sep, value))
  888. if idx < len(subkeys) - 1 and \
  889. type(settings[group][key][subkeys[idx + 1]]) != types.DictType:
  890. file.write('%s' % self.sep)
  891. file.write(os.linesep)
  892. except IOError, e:
  893. raise GException(e)
  894. except StandardError, e:
  895. raise GException(_('Writing settings to file <%(file)s> failed.'
  896. '\n\nDetails: %(detail)s') % { 'file' : self.filePath,
  897. 'detail' : e })
  898. file.close()
  899. def _parseValue(self, value, read = False):
  900. """!Parse value to be store in settings file"""
  901. if read: # -> read settings (cast values)
  902. if value == 'True':
  903. value = True
  904. elif value == 'False':
  905. value = False
  906. elif value == 'None':
  907. value = None
  908. elif ':' in value: # -> color
  909. try:
  910. value = tuple(map(int, value.split(':')))
  911. except ValueError: # -> string
  912. pass
  913. else:
  914. try:
  915. value = int(value)
  916. except ValueError:
  917. try:
  918. value = float(value)
  919. except ValueError:
  920. pass
  921. else: # -> write settings
  922. if type(value) == type(()): # -> color
  923. value = str(value[0]) + ':' +\
  924. str(value[1]) + ':' + \
  925. str(value[2])
  926. return value
  927. def Get(self, group, key = None, subkey = None, internal = False):
  928. """!Get value by key/subkey
  929. Raise KeyError if key is not found
  930. @param group settings group
  931. @param key (value, None)
  932. @param subkey (value, list or None)
  933. @param internal use internal settings instead
  934. @return value
  935. """
  936. if internal is True:
  937. settings = self.internalSettings
  938. else:
  939. settings = self.userSettings
  940. try:
  941. if subkey is None:
  942. if key is None:
  943. return settings[group]
  944. else:
  945. return settings[group][key]
  946. else:
  947. if type(subkey) == type(tuple()) or \
  948. type(subkey) == type(list()):
  949. return settings[group][key][subkey[0]][subkey[1]]
  950. else:
  951. return settings[group][key][subkey]
  952. except KeyError:
  953. print >> sys.stderr, "Settings: unable to get value '%s:%s:%s'\n" % \
  954. (group, key, subkey)
  955. def Set(self, group, value, key = None, subkey = None, internal = False):
  956. """!Set value of key/subkey
  957. Raise KeyError if group/key is not found
  958. @param group settings group
  959. @param key key (value, None)
  960. @param subkey subkey (value, list or None)
  961. @param value value
  962. @param internal use internal settings instead
  963. """
  964. if internal is True:
  965. settings = self.internalSettings
  966. else:
  967. settings = self.userSettings
  968. try:
  969. if subkey is None:
  970. if key is None:
  971. settings[group] = value
  972. else:
  973. settings[group][key] = value
  974. else:
  975. if type(subkey) == type(tuple()) or \
  976. type(subkey) == type(list()):
  977. settings[group][key][subkey[0]][subkey[1]] = value
  978. else:
  979. settings[group][key][subkey] = value
  980. except KeyError:
  981. raise GException("%s '%s:%s:%s'" % (_("Unable to set "), group, key, subkey))
  982. def Append(self, dict, group, key, subkey, value):
  983. """!Set value of key/subkey
  984. Create group/key/subkey if not exists
  985. @param dict settings dictionary to use
  986. @param group settings group
  987. @param key key
  988. @param subkey subkey (value or list)
  989. @param value value
  990. """
  991. if group not in dict:
  992. dict[group] = {}
  993. if key not in dict[group]:
  994. dict[group][key] = {}
  995. if type(subkey) == types.ListType:
  996. # TODO: len(subkey) > 2
  997. if subkey[0] not in dict[group][key]:
  998. dict[group][key][subkey[0]] = {}
  999. try:
  1000. dict[group][key][subkey[0]][subkey[1]] = value
  1001. except TypeError:
  1002. print >> sys.stderr, _("Unable to parse settings '%s'") % value + \
  1003. ' (' + group + ':' + key + ':' + subkey[0] + ':' + subkey[1] + ')'
  1004. else:
  1005. try:
  1006. dict[group][key][subkey] = value
  1007. except TypeError:
  1008. print >> sys.stderr, _("Unable to parse settings '%s'") % value + \
  1009. ' (' + group + ':' + key + ':' + subkey + ')'
  1010. def GetDefaultSettings(self):
  1011. """!Get default user settings"""
  1012. return self.defaultSettings
  1013. def Reset(self, key = None):
  1014. """!Reset to default settings
  1015. @key key in settings dict (None for all keys)
  1016. """
  1017. if not key:
  1018. self.userSettings = copy.deepcopy(self.defaultSettings)
  1019. else:
  1020. self.userSettings[key] = copy.deepcopy(self.defaultSettings[key])
  1021. UserSettings = Settings()