settings.py 45 KB

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