settings.py 44 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295
  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-2017 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. from __future__ import print_function
  17. import os
  18. import sys
  19. import copy
  20. from core import globalvar
  21. from core.gcmd import GException, GError
  22. from core.utils import GetSettingsPath, PathJoin, rgb2str, _
  23. class Settings:
  24. """Generic class where to store settings"""
  25. def __init__(self):
  26. # settings file
  27. self.filePath = os.path.join(GetSettingsPath(), 'wx')
  28. # key/value separator
  29. self.sep = ';'
  30. # define default settings
  31. self._defaultSettings() # -> self.defaultSettings
  32. # read settings from the file
  33. self.userSettings = copy.deepcopy(self.defaultSettings)
  34. try:
  35. self.ReadSettingsFile()
  36. except GException as e:
  37. print(e.value, file=sys.stderr)
  38. # define internal settings
  39. self._internalSettings() # -> self.internalSettings
  40. def _generateLocale(self):
  41. """Generate locales
  42. """
  43. try:
  44. self.locs = os.listdir(
  45. os.path.join(
  46. os.environ['GISBASE'],
  47. 'locale'))
  48. self.locs.append('en') # GRASS doesn't ship EN po files
  49. self.locs.sort()
  50. # Add a default choice to not override system locale
  51. self.locs.insert(0, 'system')
  52. except:
  53. # No NLS
  54. self.locs = ['system']
  55. return 'system'
  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' : '1,1,%d,%d,%d,1,%d,%d' % \
  73. (globalvar.GM_WINDOW_SIZE[0],
  74. globalvar.GM_WINDOW_SIZE[1],
  75. globalvar.GM_WINDOW_SIZE[0] + 1,
  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. # region
  89. 'region': {
  90. 'resAlign': {
  91. 'enabled' : False
  92. },
  93. },
  94. },
  95. 'manager': {
  96. # show opacity level widget
  97. 'changeOpacityLevel': {
  98. 'enabled': False
  99. },
  100. # ask when removing layer from layer tree
  101. 'askOnRemoveLayer': {
  102. 'enabled': True
  103. },
  104. # ask when quiting wxGUI or closing display
  105. 'askOnQuit': {
  106. 'enabled': True
  107. },
  108. # hide tabs
  109. 'hideTabs': {
  110. 'search': False,
  111. 'pyshell': False,
  112. },
  113. 'copySelectedTextToClipboard': {
  114. 'enabled': False
  115. },
  116. },
  117. #
  118. # appearance
  119. #
  120. 'appearance': {
  121. 'outputfont': {
  122. 'type': 'Courier New',
  123. 'size': '10',
  124. },
  125. # expand/collapse element list
  126. 'elementListExpand': {
  127. 'selection': 0
  128. },
  129. 'menustyle': {
  130. 'selection': 1
  131. },
  132. 'gSelectPopupHeight': {
  133. 'value': 200
  134. },
  135. 'iconTheme': {
  136. 'type': 'grass'
  137. },
  138. 'commandNotebook': {
  139. 'selection': 0 if sys.platform in ('win32', 'darwin') else 1
  140. },
  141. },
  142. #
  143. # language
  144. #
  145. 'language': {
  146. 'locale': {
  147. 'lc_all': id_loc
  148. }
  149. },
  150. #
  151. # display
  152. #
  153. 'display': {
  154. 'font': {
  155. 'type': '',
  156. 'encoding': 'UTF-8',
  157. },
  158. 'driver': {
  159. 'type': 'cairo'
  160. },
  161. 'alignExtent': {
  162. 'enabled': True
  163. },
  164. 'compResolution': {
  165. 'enabled': False
  166. },
  167. 'autoRendering': {
  168. 'enabled': True
  169. },
  170. 'autoZooming': {
  171. 'enabled': False
  172. },
  173. 'statusbarMode': {
  174. 'selection': 0
  175. },
  176. 'bgcolor': {
  177. 'color': (255, 255, 255, 255),
  178. },
  179. 'mouseWheelZoom': {
  180. 'selection': 1,
  181. },
  182. 'scrollDirection': {
  183. 'selection': 0,
  184. },
  185. 'nvizDepthBuffer': {
  186. 'value': '16',
  187. },
  188. },
  189. #
  190. # projection
  191. #
  192. 'projection': {
  193. 'statusbar': {
  194. 'proj4': '',
  195. 'epsg': '',
  196. 'projFile': projFile,
  197. },
  198. 'format': {
  199. 'll': 'DMS',
  200. 'precision': 2,
  201. },
  202. },
  203. #
  204. # Attribute Table Manager
  205. #
  206. 'atm': {
  207. 'highlight': {
  208. 'color': (255, 255, 0, 255),
  209. 'width': 2,
  210. 'auto': True,
  211. },
  212. 'leftDbClick': {
  213. 'selection': 1 # draw selected
  214. },
  215. 'askOnDeleteRec': {
  216. 'enabled': True
  217. },
  218. 'keycolumn': {
  219. 'value': 'cat'
  220. },
  221. 'encoding': {
  222. 'value': '',
  223. }
  224. },
  225. #
  226. # Command
  227. #
  228. 'cmd': {
  229. 'overwrite': {
  230. 'enabled': False
  231. },
  232. 'closeDlg': {
  233. 'enabled': False
  234. },
  235. 'verbosity': {
  236. 'selection': 'grassenv'
  237. },
  238. 'addNewLayer': {
  239. 'enabled': True,
  240. },
  241. 'interactiveInput': {
  242. 'enabled': True,
  243. },
  244. },
  245. #
  246. # d.rast
  247. #
  248. 'rasterLayer': {
  249. 'opaque': {
  250. 'enabled': False
  251. },
  252. 'colorTable': {
  253. 'enabled': False,
  254. 'selection': 'rainbow'
  255. },
  256. },
  257. #
  258. # d.vect
  259. #
  260. 'vectorLayer': {
  261. 'featureColor': {
  262. 'color': (0, 0, 0),
  263. 'transparent': {
  264. 'enabled': False
  265. }
  266. },
  267. 'areaFillColor': {
  268. 'color': (200, 200, 200),
  269. 'transparent': {
  270. 'enabled': False
  271. }
  272. },
  273. 'line': {
  274. 'width': 0,
  275. },
  276. 'point': {
  277. 'symbol': 'basic/x',
  278. 'size': 5,
  279. },
  280. 'showType': {
  281. 'point': {
  282. 'enabled': True
  283. },
  284. 'line': {
  285. 'enabled': True
  286. },
  287. 'centroid': {
  288. 'enabled': False
  289. },
  290. 'boundary': {
  291. 'enabled': False
  292. },
  293. 'area': {
  294. 'enabled': True
  295. },
  296. 'face': {
  297. 'enabled': True
  298. },
  299. },
  300. },
  301. #
  302. # vdigit
  303. #
  304. 'vdigit': {
  305. # symbology
  306. 'symbol': {
  307. 'newSegment': {
  308. 'enabled': None,
  309. 'color': (255, 0, 0, 255)
  310. }, # red
  311. 'newLine': {
  312. 'enabled': None,
  313. 'color': (0, 86, 45, 255)
  314. }, # dark green
  315. 'highlight': {
  316. 'enabled': None,
  317. 'color': (255, 255, 0, 255)
  318. }, # yellow
  319. 'highlightDupl': {
  320. 'enabled': None,
  321. 'color': (255, 72, 0, 255)
  322. }, # red
  323. 'point': {
  324. 'enabled': True,
  325. 'color': (0, 0, 0, 255)
  326. }, # black
  327. 'line': {
  328. 'enabled': True,
  329. 'color': (0, 0, 0, 255)
  330. }, # black
  331. 'boundaryNo': {
  332. 'enabled': True,
  333. 'color': (126, 126, 126, 255)
  334. }, # grey
  335. 'boundaryOne': {
  336. 'enabled': True,
  337. 'color': (0, 255, 0, 255)
  338. }, # green
  339. 'boundaryTwo': {
  340. 'enabled': True,
  341. 'color': (255, 135, 0, 255)
  342. }, # orange
  343. 'centroidIn': {
  344. 'enabled': True,
  345. 'color': (0, 0, 255, 255)
  346. }, # blue
  347. 'centroidOut': {
  348. 'enabled': True,
  349. 'color': (165, 42, 42, 255)
  350. }, # brown
  351. 'centroidDup': {
  352. 'enabled': True,
  353. 'color': (156, 62, 206, 255)
  354. }, # violet
  355. 'nodeOne': {
  356. 'enabled': True,
  357. 'color': (255, 0, 0, 255)
  358. }, # red
  359. 'nodeTwo': {
  360. 'enabled': True,
  361. 'color': (0, 86, 45, 255)
  362. }, # dark green
  363. 'vertex': {
  364. 'enabled': False,
  365. 'color': (255, 20, 147, 255)
  366. }, # deep pink
  367. 'area': {
  368. 'enabled': True,
  369. 'color': (217, 255, 217, 255)
  370. }, # green
  371. 'direction': {
  372. 'enabled': False,
  373. 'color': (255, 0, 0, 255)
  374. }, # red
  375. },
  376. # display
  377. 'lineWidth': {
  378. 'value': 2,
  379. 'units': 'screen pixels'
  380. },
  381. # snapping
  382. 'snapping': {
  383. 'value': 10,
  384. 'unit': 0, # new
  385. 'units': 'screen pixels' # old for backwards comp.
  386. },
  387. 'snapToVertex': {
  388. 'enabled': True
  389. },
  390. # digitize new record
  391. 'addRecord': {
  392. 'enabled': True
  393. },
  394. 'layer': {
  395. 'value': 1
  396. },
  397. 'category': {
  398. 'value': 1
  399. },
  400. 'categoryMode': {
  401. 'selection': 0
  402. },
  403. # delete existing feature(s)
  404. 'delRecord': {
  405. 'enabled': True
  406. },
  407. # query tool
  408. 'query': {
  409. 'selection': 0,
  410. 'box': True
  411. },
  412. 'queryLength': {
  413. 'than-selection': 0,
  414. 'thresh': 0
  415. },
  416. 'queryDangle': {
  417. 'than-selection': 0,
  418. 'thresh': 0
  419. },
  420. # select feature (point, line, centroid, boundary)
  421. 'selectType': {
  422. 'point': {
  423. 'enabled': True
  424. },
  425. 'line': {
  426. 'enabled': True
  427. },
  428. 'centroid': {
  429. 'enabled': True
  430. },
  431. 'boundary': {
  432. 'enabled': True
  433. },
  434. },
  435. 'selectThresh': {
  436. 'value': 10,
  437. 'unit': 0, # new
  438. 'units': 'screen pixels' # old for backwards comp.
  439. },
  440. 'checkForDupl': {
  441. 'enabled': False
  442. },
  443. 'selectInside': {
  444. 'enabled': False
  445. },
  446. # exit
  447. 'saveOnExit': {
  448. 'enabled': False,
  449. },
  450. # break lines on intersection
  451. 'breakLines': {
  452. 'enabled': True,
  453. },
  454. # close boundary (snap to the first node)
  455. 'closeBoundary': {
  456. 'enabled': False,
  457. }
  458. },
  459. #
  460. # plots for profiles, histograms, and scatterplots
  461. #
  462. 'profile': {
  463. 'raster': {
  464. 'pcolor': (0, 0, 255, 255), # line color
  465. 'pwidth': 1, # line width
  466. 'pstyle': 'solid', # line pen style
  467. 'datatype': 'cell', # raster type
  468. },
  469. 'font': {
  470. 'titleSize': 12,
  471. 'axisSize': 11,
  472. 'legendSize': 10,
  473. },
  474. 'marker': {
  475. 'color': (0, 0, 0, 255),
  476. 'fill': 'transparent',
  477. 'size': 2,
  478. 'type': 'triangle',
  479. 'legend': _('Segment break'),
  480. },
  481. 'grid': {
  482. 'color': (200, 200, 200, 255),
  483. 'enabled': True,
  484. },
  485. 'x-axis': {
  486. 'type': 'auto', # axis format
  487. 'min': 0, # axis min for custom axis range
  488. 'max': 0, # axis max for custom axis range
  489. 'log': False,
  490. },
  491. 'y-axis': {
  492. 'type': 'auto', # axis format
  493. 'min': 0, # axis min for custom axis range
  494. 'max': 0, # axis max for custom axis range
  495. 'log': False,
  496. },
  497. 'legend': {
  498. 'enabled': True
  499. },
  500. },
  501. 'histogram': {
  502. 'raster': {
  503. 'pcolor': (0, 0, 255, 255), # line color
  504. 'pwidth': 1, # line width
  505. 'pstyle': 'solid', # line pen style
  506. 'datatype': 'cell', # raster type
  507. },
  508. 'font': {
  509. 'titleSize': 12,
  510. 'axisSize': 11,
  511. 'legendSize': 10,
  512. },
  513. 'grid': {
  514. 'color': (200, 200, 200, 255),
  515. 'enabled': True,
  516. },
  517. 'x-axis': {
  518. 'type': 'auto', # axis format
  519. 'min': 0, # axis min for custom axis range
  520. 'max': 0, # axis max for custom axis range
  521. 'log': False,
  522. },
  523. 'y-axis': {
  524. 'type': 'auto', # axis format
  525. 'min': 0, # axis min for custom axis range
  526. 'max': 0, # axis max for custom axis range
  527. 'log': False,
  528. },
  529. 'legend': {
  530. 'enabled': True
  531. },
  532. },
  533. 'scatter': {
  534. 'raster': {
  535. 'pcolor': (0, 0, 255, 255),
  536. 'pfill': 'solid',
  537. 'psize': 1,
  538. 'ptype': 'dot',
  539. # FIXME: this is only a quick fix
  540. # using also names used in a base class for compatibility
  541. # probably used only for initialization
  542. # base should be rewritten to not require this
  543. 'pwidth': 1, # required by wxplot/base, maybe useless here
  544. 'pstyle': 'dot', # line pen style
  545. 'plegend': _('Data point'),
  546. 0: {'datatype': 'CELL'},
  547. 1: {'datatype': 'CELL'},
  548. },
  549. 'font': {
  550. 'titleSize': 12,
  551. 'axisSize': 11,
  552. 'legendSize': 10,
  553. },
  554. 'grid': {
  555. 'color': (200, 200, 200, 255),
  556. 'enabled': True,
  557. },
  558. 'x-axis': {
  559. 'type': 'auto', # axis format
  560. 'min': 0, # axis min for custom axis range
  561. 'max': 0, # axis max for custom axis range
  562. 'log': False,
  563. },
  564. 'y-axis': {
  565. 'type': 'auto', # axis format
  566. 'min': 0, # axis min for custom axis range
  567. 'max': 0, # axis max for custom axis range
  568. 'log': False,
  569. },
  570. 'legend': {
  571. 'enabled': True
  572. },
  573. },
  574. 'gcpman': {
  575. 'rms': {
  576. 'highestonly': True,
  577. 'sdfactor': 1,
  578. },
  579. 'symbol': {
  580. 'color': (0, 0, 255, 255),
  581. 'hcolor': (255, 0, 0, 255),
  582. 'scolor': (0, 255, 0, 255),
  583. 'ucolor': (255, 165, 0, 255),
  584. 'unused': True,
  585. 'size': 8,
  586. 'width': 2,
  587. },
  588. },
  589. 'nviz': {
  590. 'view': {
  591. 'persp': {
  592. 'value': 20,
  593. 'step': 2,
  594. },
  595. 'position': {
  596. 'x': 0.84,
  597. 'y': 0.16,
  598. },
  599. 'twist': {
  600. 'value': 0,
  601. },
  602. 'z-exag': {
  603. 'min': 0,
  604. 'max': 10,
  605. 'value': 1,
  606. },
  607. 'background': {
  608. 'color': (255, 255, 255, 255), # white
  609. },
  610. },
  611. 'fly': {
  612. 'exag': {
  613. 'move': 5,
  614. 'turn': 5,
  615. }
  616. },
  617. 'animation': {
  618. 'fps': 24,
  619. 'prefix': _("animation")
  620. },
  621. 'surface': {
  622. 'shine': {
  623. 'map': False,
  624. 'value': 60.0,
  625. },
  626. 'color': {
  627. 'map': True,
  628. 'value': (100, 100, 100, 255), # constant: grey
  629. },
  630. 'draw': {
  631. 'wire-color': (136, 136, 136, 255),
  632. 'mode': 1, # fine
  633. 'style': 1, # surface
  634. 'shading': 1, # gouraud
  635. 'res-fine': 6,
  636. 'res-coarse': 9,
  637. },
  638. 'position': {
  639. 'x': 0,
  640. 'y': 0,
  641. 'z': 0,
  642. },
  643. },
  644. 'constant': {
  645. 'color': (100, 100, 100, 255),
  646. 'value': 0.0,
  647. 'transp': 0,
  648. 'resolution': 6
  649. },
  650. 'vector': {
  651. 'lines': {
  652. 'show': False,
  653. 'width': 2,
  654. 'color': (0, 0, 0, 255),
  655. 'flat': False,
  656. 'height': 0,
  657. 'rgbcolumn': None,
  658. 'sizecolumn': None,
  659. },
  660. 'points': {
  661. 'show': False,
  662. 'size': 100,
  663. 'autosize': True,
  664. 'width': 2,
  665. 'marker': 2,
  666. 'color': (0, 0, 0, 255),
  667. 'height': 0,
  668. 'rgbcolumn': None,
  669. 'sizecolumn': None,
  670. }
  671. },
  672. 'volume': {
  673. 'color': {
  674. 'map': True,
  675. 'value': (100, 100, 100, 255), # constant: grey
  676. },
  677. 'draw': {
  678. 'mode': 0, # isosurfaces
  679. 'shading': 1, # gouraud
  680. 'resolution': 3, # polygon resolution
  681. 'box': False # draw wire box
  682. },
  683. 'shine': {
  684. 'map': False,
  685. 'value': 60,
  686. },
  687. 'topo': {
  688. 'map': None,
  689. 'value': 0.0
  690. },
  691. 'transp': {
  692. 'map': None,
  693. 'value': 0
  694. },
  695. 'mask': {
  696. 'map': None,
  697. 'value': ''
  698. },
  699. 'slice_position': {
  700. 'x1': 0,
  701. 'x2': 1,
  702. 'y1': 0,
  703. 'y2': 1,
  704. 'z1': 0,
  705. 'z2': 1,
  706. 'axis': 0,
  707. }
  708. },
  709. 'cplane': {
  710. 'shading': 4,
  711. 'rotation': {
  712. 'rot': 180,
  713. 'tilt': 0
  714. },
  715. 'position': {
  716. 'x': 0,
  717. 'y': 0,
  718. 'z': 0
  719. }
  720. },
  721. 'light': {
  722. 'position': {
  723. 'x': 0.68,
  724. 'y': -0.68,
  725. 'z': 80,
  726. },
  727. 'bright': 80,
  728. 'color': (255, 255, 255, 255), # white
  729. 'ambient': 20,
  730. },
  731. 'fringe': {
  732. 'elev': 55,
  733. 'color': (128, 128, 128, 255), # grey
  734. },
  735. 'arrow': {
  736. 'color': (0, 0, 0),
  737. },
  738. 'scalebar': {
  739. 'color': (0, 0, 0),
  740. }
  741. },
  742. 'modeler': {
  743. 'disabled': {
  744. 'color': (211, 211, 211, 255), # light grey
  745. },
  746. 'action': {
  747. 'color': {
  748. 'valid': (180, 234, 154, 255), # light green
  749. 'invalid': (255, 255, 255, 255), # white
  750. 'running': (255, 0, 0, 255), # red
  751. },
  752. 'size': {
  753. 'width': 125,
  754. 'height': 50,
  755. },
  756. 'width': {
  757. 'parameterized': 2,
  758. 'default': 1,
  759. },
  760. },
  761. 'data': {
  762. 'color': {
  763. 'raster': (215, 215, 248, 255), # light blue
  764. 'raster3d': (215, 248, 215, 255), # light green
  765. 'vector': (248, 215, 215, 255), # light red
  766. 'dbtable': (255, 253, 194, 255), # light yellow
  767. },
  768. 'size': {
  769. 'width': 175,
  770. 'height': 50,
  771. },
  772. },
  773. 'loop': {
  774. 'color': {
  775. 'valid': (234, 226, 154, 255), # dark yellow
  776. },
  777. 'size': {
  778. 'width': 175,
  779. 'height': 40,
  780. },
  781. },
  782. 'if-else': {
  783. 'size': {
  784. 'width': 150,
  785. 'height': 40,
  786. },
  787. },
  788. 'comment': {
  789. 'color': (255, 233, 208, 255), # light yellow
  790. 'size': {
  791. 'width': 200,
  792. 'height': 100,
  793. },
  794. },
  795. },
  796. 'mapswipe': {
  797. 'cursor': {
  798. 'color': (0, 0, 0, 255),
  799. 'size': 12,
  800. 'width': 1,
  801. 'type': {
  802. 'selection': 0,
  803. }
  804. },
  805. },
  806. 'animation': {
  807. 'bgcolor': {
  808. 'color': (255, 255, 255, 255),
  809. },
  810. 'nprocs': {
  811. 'value': -1,
  812. },
  813. 'font': {
  814. 'bgcolor': (255, 255, 255, 255),
  815. 'fgcolor': (0, 0, 0, 255),
  816. },
  817. 'temporal': {
  818. 'format': '%Y-%m-%d %H:%M:%S',
  819. 'nodata': {
  820. 'enable': False
  821. },
  822. },
  823. },
  824. }
  825. # quick fix, http://trac.osgeo.org/grass/ticket/1233
  826. # TODO
  827. if sys.platform == 'darwin':
  828. self.defaultSettings['general']['defWindowPos']['enabled'] = False
  829. def _internalSettings(self):
  830. """Define internal settings (based on user settings)
  831. """
  832. self.internalSettings = {}
  833. for group in self.userSettings.keys():
  834. self.internalSettings[group] = {}
  835. for key in self.userSettings[group].keys():
  836. self.internalSettings[group][key] = {}
  837. # self.internalSettings['general']["mapsetPath"]['value'] = self.GetMapsetPath()
  838. self.internalSettings['appearance']['elementListExpand']['choices'] = \
  839. (_("Collapse all except PERMANENT and current"),
  840. _("Collapse all except PERMANENT"),
  841. _("Collapse all except current"),
  842. _("Collapse all"),
  843. _("Expand all"))
  844. self.internalSettings['language'][
  845. 'locale']['choices'] = tuple(self.locs)
  846. self.internalSettings['atm']['leftDbClick']['choices'] = (
  847. _('Edit selected record'), _('Display selected'))
  848. self.internalSettings['cmd']['verbosity']['choices'] = ('grassenv',
  849. 'verbose',
  850. 'quiet')
  851. self.internalSettings['appearance'][
  852. 'iconTheme']['choices'] = ('grass',)
  853. self.internalSettings['appearance']['menustyle']['choices'] = \
  854. (_("Classic (labels only)"),
  855. _("Combined (labels and module names)"),
  856. _("Expert (module names only)"))
  857. self.internalSettings['appearance']['gSelectPopupHeight']['min'] = 50
  858. # there is also maxHeight given to TreeCtrlComboPopup.GetAdjustedSize
  859. self.internalSettings['appearance']['gSelectPopupHeight']['max'] = 1000
  860. self.internalSettings['appearance']['commandNotebook']['choices'] = \
  861. (_("Basic top"),
  862. _("Basic left"),
  863. _("Fancy green"),
  864. _("List left"))
  865. self.internalSettings['display'][
  866. 'driver']['choices'] = ['cairo', 'png']
  867. self.internalSettings['display']['statusbarMode'][
  868. 'choices'] = None # set during MapFrame init
  869. self.internalSettings['display']['mouseWheelZoom']['choices'] = (
  870. _('Zoom and recenter'), _('Zoom to mouse cursor'), _('Nothing'))
  871. self.internalSettings['display']['scrollDirection']['choices'] = (
  872. _('Scroll forward to zoom in'), _('Scroll back to zoom in'))
  873. self.internalSettings['nviz']['view'] = {}
  874. self.internalSettings['nviz']['view']['twist'] = {}
  875. self.internalSettings['nviz']['view']['twist']['min'] = -180
  876. self.internalSettings['nviz']['view']['twist']['max'] = 180
  877. self.internalSettings['nviz']['view']['persp'] = {}
  878. self.internalSettings['nviz']['view']['persp']['min'] = 1
  879. self.internalSettings['nviz']['view']['persp']['max'] = 100
  880. self.internalSettings['nviz']['view']['height'] = {}
  881. self.internalSettings['nviz']['view']['height']['value'] = -1
  882. self.internalSettings['nviz']['view']['z-exag'] = {}
  883. self.internalSettings['nviz']['view']['z-exag']['llRatio'] = 1
  884. self.internalSettings['nviz']['view']['rotation'] = None
  885. self.internalSettings['nviz']['view']['focus'] = {}
  886. self.internalSettings['nviz']['view']['focus']['x'] = -1
  887. self.internalSettings['nviz']['view']['focus']['y'] = -1
  888. self.internalSettings['nviz']['view']['focus']['z'] = -1
  889. self.internalSettings['nviz']['view']['dir'] = {}
  890. self.internalSettings['nviz']['view']['dir']['x'] = -1
  891. self.internalSettings['nviz']['view']['dir']['y'] = -1
  892. self.internalSettings['nviz']['view']['dir']['z'] = -1
  893. self.internalSettings['nviz']['view']['dir']['use'] = False
  894. for decor in ('arrow', 'scalebar'):
  895. self.internalSettings['nviz'][decor] = {}
  896. self.internalSettings['nviz'][decor]['position'] = {}
  897. self.internalSettings['nviz'][decor]['position']['x'] = 0
  898. self.internalSettings['nviz'][decor]['position']['y'] = 0
  899. self.internalSettings['nviz'][decor]['size'] = 100
  900. self.internalSettings['nviz']['vector'] = {}
  901. self.internalSettings['nviz']['vector']['points'] = {}
  902. self.internalSettings['nviz']['vector']['points']['marker'] = ("x",
  903. _("box"),
  904. _("sphere"),
  905. _("cube"),
  906. _("diamond"),
  907. _("aster"),
  908. _("gyro"),
  909. _("histogram"))
  910. self.internalSettings['vdigit']['bgmap'] = {}
  911. self.internalSettings['vdigit']['bgmap']['value'] = ''
  912. self.internalSettings['mapswipe']['cursor']['type'] = {}
  913. self.internalSettings['mapswipe']['cursor']['type'][
  914. 'choices'] = (_("cross"), _("box"), _("circle"))
  915. def ReadSettingsFile(self, settings=None):
  916. """Reads settings file (mapset, location, gisdbase)"""
  917. if settings is None:
  918. settings = self.userSettings
  919. self._readFile(self.filePath, settings)
  920. # set environment variables
  921. font = self.Get(group='display', key='font', subkey='type')
  922. enc = self.Get(group='display', key='font', subkey='encoding')
  923. if font:
  924. os.environ["GRASS_FONT"] = font
  925. if enc:
  926. os.environ["GRASS_ENCODING"] = enc
  927. def _readFile(self, filename, settings=None):
  928. """Read settings from file to dict
  929. :param filename: settings file path
  930. :param settings: dict where to store settings (None for self.userSettings)
  931. """
  932. if settings is None:
  933. settings = self.userSettings
  934. if not os.path.exists(filename):
  935. return
  936. try:
  937. fd = open(filename, "r")
  938. except IOError:
  939. sys.stderr.write(
  940. _("Unable to read settings file <%s>\n") %
  941. filename)
  942. return
  943. try:
  944. line = ''
  945. for line in fd.readlines():
  946. line = line.rstrip('%s' % os.linesep)
  947. group, key = line.split(self.sep)[0:2]
  948. kv = line.split(self.sep)[2:]
  949. subkeyMaster = None
  950. if len(kv) % 2 != 0: # multiple (e.g. nviz)
  951. subkeyMaster = kv[0]
  952. del kv[0]
  953. idx = 0
  954. while idx < len(kv):
  955. if subkeyMaster:
  956. subkey = [subkeyMaster, kv[idx]]
  957. else:
  958. subkey = kv[idx]
  959. value = kv[idx + 1]
  960. value = self._parseValue(value, read=True)
  961. self.Append(settings, group, key, subkey, value)
  962. idx += 2
  963. except ValueError as e:
  964. print(_(
  965. "Error: Reading settings from file <%(file)s> failed.\n"
  966. "\t\tDetails: %(detail)s\n"
  967. "\t\tLine: '%(line)s'\n") % {
  968. 'file': filename, 'detail': e, 'line': line},
  969. file=sys.stderr)
  970. fd.close()
  971. fd.close()
  972. def SaveToFile(self, settings=None):
  973. """Save settings to the file"""
  974. if settings is None:
  975. settings = self.userSettings
  976. dirPath = GetSettingsPath()
  977. if not os.path.exists(dirPath):
  978. try:
  979. os.mkdir(dirPath)
  980. except:
  981. GError(_('Unable to create settings directory'))
  982. return
  983. try:
  984. file = open(self.filePath, "w")
  985. for group in settings.keys():
  986. for key in settings[group].keys():
  987. subkeys = settings[group][key].keys()
  988. file.write('%s%s%s%s' % (group, self.sep, key, self.sep))
  989. for idx in range(len(subkeys)):
  990. value = settings[group][key][subkeys[idx]]
  991. if isinstance(value, dict):
  992. if idx > 0:
  993. file.write(
  994. '%s%s%s%s%s' %
  995. (os.linesep, group, self.sep, key, self.sep))
  996. file.write('%s%s' % (subkeys[idx], self.sep))
  997. kvalues = settings[group][key][subkeys[idx]].keys()
  998. srange = range(len(kvalues))
  999. for sidx in srange:
  1000. svalue = self._parseValue(
  1001. settings[group][key][
  1002. subkeys[idx]][
  1003. kvalues[sidx]])
  1004. file.write('%s%s%s' % (kvalues[sidx], self.sep,
  1005. svalue))
  1006. if sidx < len(kvalues) - 1:
  1007. file.write('%s' % self.sep)
  1008. else:
  1009. if idx > 0 and isinstance(
  1010. settings[group][key][subkeys[idx - 1]],
  1011. dict):
  1012. file.write(
  1013. '%s%s%s%s%s' %
  1014. (os.linesep, group, self.sep, key, self.sep))
  1015. value = self._parseValue(
  1016. settings[group][key][subkeys[idx]])
  1017. file.write(
  1018. '%s%s%s' %
  1019. (subkeys[idx], self.sep, value))
  1020. if idx < len(subkeys) - 1 and not isinstance(
  1021. settings[group][key][subkeys[idx + 1]],
  1022. dict):
  1023. file.write('%s' % self.sep)
  1024. file.write(os.linesep)
  1025. except IOError as e:
  1026. raise GException(e)
  1027. except Exception as e:
  1028. raise GException(_('Writing settings to file <%(file)s> failed.'
  1029. '\n\nDetails: %(detail)s') %
  1030. {'file': self.filePath, 'detail': e})
  1031. file.close()
  1032. return self.filePath
  1033. def _parseValue(self, value, read=False):
  1034. """Parse value to be store in settings file"""
  1035. if read: # -> read settings (cast values)
  1036. if value == 'True':
  1037. value = True
  1038. elif value == 'False':
  1039. value = False
  1040. elif value == 'None':
  1041. value = None
  1042. elif ':' in value: # -> color
  1043. try:
  1044. value = tuple(map(int, value.split(':')))
  1045. except ValueError: # -> string
  1046. pass
  1047. else:
  1048. try:
  1049. value = int(value)
  1050. except ValueError:
  1051. try:
  1052. value = float(value)
  1053. except ValueError:
  1054. pass
  1055. else: # -> write settings
  1056. if isinstance(value, type(())): # -> color
  1057. value = str(value[0]) + ':' +\
  1058. str(value[1]) + ':' + \
  1059. str(value[2])
  1060. return value
  1061. def Get(self, group, key=None, subkey=None, settings_type='user'):
  1062. """Get value by key/subkey
  1063. Raise KeyError if key is not found
  1064. :param group: settings group
  1065. :param key: (value, None)
  1066. :param subkey: (value, list or None)
  1067. :param settings_type: 'user', 'internal', 'default'
  1068. :return: value
  1069. """
  1070. if settings_type == 'user':
  1071. settings = self.userSettings
  1072. elif settings_type == 'internal':
  1073. settings = self.internalSettings
  1074. else:
  1075. settings = self.defaultSettings
  1076. try:
  1077. if subkey is None:
  1078. if key is None:
  1079. return settings[group]
  1080. else:
  1081. return settings[group][key]
  1082. else:
  1083. if isinstance(subkey, type(tuple())) or \
  1084. isinstance(subkey, type(list())):
  1085. return settings[group][key][subkey[0]][subkey[1]]
  1086. else:
  1087. return settings[group][key][subkey]
  1088. except KeyError:
  1089. print("Settings: unable to get value '%s:%s:%s'\n" % (
  1090. group, key, subkey), file=sys.stderr)
  1091. def Set(self, group, value, key=None, subkey=None, settings_type='user'):
  1092. """Set value of key/subkey
  1093. Raise KeyError if group/key is not found
  1094. :param group: settings group
  1095. :param key: key (value, None)
  1096. :param subkey: subkey (value, list or None)
  1097. :param value: value
  1098. :param settings_type: 'user', 'internal', 'default'
  1099. """
  1100. if settings_type == 'user':
  1101. settings = self.userSettings
  1102. elif settings_type == 'internal':
  1103. settings = self.internalSettings
  1104. else:
  1105. settings = self.defaultSettings
  1106. try:
  1107. if subkey is None:
  1108. if key is None:
  1109. settings[group] = value
  1110. else:
  1111. settings[group][key] = value
  1112. else:
  1113. if isinstance(subkey, type(tuple())) or \
  1114. isinstance(subkey, type(list())):
  1115. settings[group][key][subkey[0]][subkey[1]] = value
  1116. else:
  1117. settings[group][key][subkey] = value
  1118. except KeyError:
  1119. raise GException("%s '%s:%s:%s'" %
  1120. (_("Unable to set "), group, key, subkey))
  1121. def Append(self, dict, group, key, subkey, value, overwrite=True):
  1122. """Set value of key/subkey
  1123. Create group/key/subkey if not exists
  1124. :param dict: settings dictionary to use
  1125. :param group: settings group
  1126. :param key: key
  1127. :param subkey: subkey (value or list)
  1128. :param value: value
  1129. :param overwrite: True to overwrite existing value
  1130. """
  1131. hasValue = True
  1132. if group not in dict:
  1133. dict[group] = {}
  1134. hasValue = False
  1135. if key not in dict[group]:
  1136. dict[group][key] = {}
  1137. hasValue = False
  1138. if isinstance(subkey, list):
  1139. # TODO: len(subkey) > 2
  1140. if subkey[0] not in dict[group][key]:
  1141. dict[group][key][subkey[0]] = {}
  1142. hasValue = False
  1143. if subkey[1] not in dict[group][key][subkey[0]]:
  1144. hasValue = False
  1145. try:
  1146. if overwrite or (not overwrite and not hasValue):
  1147. dict[group][key][subkey[0]][subkey[1]] = value
  1148. except TypeError:
  1149. print(_("Unable to parse settings '%s'") % value +
  1150. ' (' + group + ':' + key + ':' + subkey[0] +
  1151. ':' + subkey[1] + ')', file=sys.stderr)
  1152. else:
  1153. if subkey not in dict[group][key]:
  1154. hasValue = False
  1155. try:
  1156. if overwrite or (not overwrite and not hasValue):
  1157. dict[group][key][subkey] = value
  1158. except TypeError:
  1159. print(_("Unable to parse settings '%s'") % value +
  1160. ' (' + group + ':' + key + ':' + subkey + ')',
  1161. file=sys.stderr)
  1162. def GetDefaultSettings(self):
  1163. """Get default user settings"""
  1164. return self.defaultSettings
  1165. def Reset(self, key=None):
  1166. """Reset to default settings
  1167. :param key: key in settings dict (None for all keys)
  1168. """
  1169. if not key:
  1170. self.userSettings = copy.deepcopy(self.defaultSettings)
  1171. else:
  1172. self.userSettings[key] = copy.deepcopy(self.defaultSettings[key])
  1173. UserSettings = Settings()
  1174. def GetDisplayVectSettings():
  1175. settings = list()
  1176. if not UserSettings.Get(
  1177. group='vectorLayer', key='featureColor',
  1178. subkey=['transparent', 'enabled']):
  1179. featureColor = UserSettings.Get(
  1180. group='vectorLayer',
  1181. key='featureColor',
  1182. subkey='color')
  1183. settings.append('color=%s' % rgb2str.get(
  1184. featureColor, ':'.join(map(str, featureColor))))
  1185. else:
  1186. settings.append('color=none')
  1187. if not UserSettings.Get(
  1188. group='vectorLayer', key='areaFillColor',
  1189. subkey=['transparent', 'enabled']):
  1190. fillColor = UserSettings.Get(
  1191. group='vectorLayer',
  1192. key='areaFillColor',
  1193. subkey='color')
  1194. settings.append('fcolor=%s' %
  1195. rgb2str.get(fillColor, ':'.join(map(str, fillColor))))
  1196. else:
  1197. settings.append('fcolor=none')
  1198. settings.append(
  1199. 'width=%s' %
  1200. UserSettings.Get(
  1201. group='vectorLayer',
  1202. key='line',
  1203. subkey='width'))
  1204. settings.append(
  1205. 'icon=%s' %
  1206. UserSettings.Get(
  1207. group='vectorLayer',
  1208. key='point',
  1209. subkey='symbol'))
  1210. settings.append(
  1211. 'size=%s' %
  1212. UserSettings.Get(
  1213. group='vectorLayer',
  1214. key='point',
  1215. subkey='size'))
  1216. types = []
  1217. for ftype in ['point', 'line', 'boundary', 'centroid', 'area', 'face']:
  1218. if UserSettings.Get(group='vectorLayer',
  1219. key='showType', subkey=[ftype, 'enabled']):
  1220. types.append(ftype)
  1221. settings.append('type=%s' % ','.join(types))
  1222. return settings