settings.py 45 KB

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