settings.py 44 KB

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