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 list(self.userSettings.keys()):
  840. self.internalSettings[group] = {}
  841. for key in list(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 list(settings.keys()):
  992. for key in list(settings[group].keys()):
  993. subkeys = list(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 = list(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