preferences.py 40 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112
  1. """
  2. @package vdigit.preferences
  3. @brief wxGUI vector digitizer preferences dialogs
  4. Classes:
  5. - preferences::VDigitSettingsDialog
  6. (C) 2007-2011 by the GRASS Development Team
  7. This program is free software under the GNU General Public License
  8. (>=v2). Read the file COPYING that comes with GRASS for details.
  9. @author Martin Landa <landa.martin gmail.com>
  10. """
  11. import textwrap
  12. import wx
  13. import wx.lib.colourselect as csel
  14. from core import globalvar
  15. from core.debug import Debug
  16. from gui_core.gselect import ColumnSelect
  17. from core.units import Units
  18. from core.settings import UserSettings
  19. from core.utils import _
  20. class VDigitSettingsDialog(wx.Dialog):
  21. def __init__(self, parent, giface, title=_("Digitization settings"),
  22. style=wx.DEFAULT_DIALOG_STYLE):
  23. """Standard settings dialog for digitization purposes
  24. """
  25. wx.Dialog.__init__(
  26. self,
  27. parent=parent,
  28. id=wx.ID_ANY,
  29. title=title,
  30. style=style)
  31. self._giface = giface
  32. self.parent = parent # MapFrame
  33. self.digit = self.parent.MapWindow.digit
  34. # notebook
  35. notebook = wx.Notebook(parent=self, id=wx.ID_ANY, style=wx.BK_DEFAULT)
  36. self._createGeneralPage(notebook)
  37. self._createSymbologyPage(notebook)
  38. self.digit.SetCategory()
  39. self._createAttributesPage(notebook)
  40. self._createQueryPage(notebook)
  41. # buttons
  42. btnApply = wx.Button(self, wx.ID_APPLY)
  43. btnCancel = wx.Button(self, wx.ID_CLOSE)
  44. btnSave = wx.Button(self, wx.ID_SAVE)
  45. btnSave.SetDefault()
  46. # bindigs
  47. btnApply.Bind(wx.EVT_BUTTON, self.OnApply)
  48. btnApply.SetToolTipString(_("Apply changes for this session"))
  49. btnApply.SetDefault()
  50. btnSave.Bind(wx.EVT_BUTTON, self.OnSave)
  51. btnSave.SetToolTipString(
  52. _("Close dialog and save changes to user settings file"))
  53. btnCancel.Bind(wx.EVT_BUTTON, self.OnCancel)
  54. btnCancel.SetToolTipString(_("Close dialog and ignore changes"))
  55. # sizers
  56. btnSizer = wx.wx.BoxSizer(wx.HORIZONTAL)
  57. btnSizer.Add(btnCancel, proportion=0,
  58. flag=wx.ALIGN_RIGHT | wx.ALL, border=5)
  59. btnSizer.Add(btnApply, proportion=0,
  60. flag=wx.ALIGN_RIGHT | wx.ALL, border=5)
  61. btnSizer.Add(btnSave, proportion=0,
  62. flag=wx.ALIGN_RIGHT | wx.ALL, border=5)
  63. mainSizer = wx.BoxSizer(wx.VERTICAL)
  64. mainSizer.Add(
  65. item=notebook,
  66. proportion=1,
  67. flag=wx.EXPAND | wx.ALL,
  68. border=5)
  69. mainSizer.Add(item=btnSizer, proportion=0,
  70. flag=wx.ALIGN_RIGHT, border=5)
  71. self.Bind(wx.EVT_CLOSE, self.OnCancel)
  72. self.SetSizer(mainSizer)
  73. mainSizer.Fit(self)
  74. def _createSymbologyPage(self, notebook):
  75. """Create notebook page concerning symbology settings"""
  76. panel = wx.Panel(parent=notebook, id=wx.ID_ANY)
  77. notebook.AddPage(page=panel, text=_("Symbology"))
  78. sizer = wx.BoxSizer(wx.VERTICAL)
  79. flexSizer = wx.FlexGridSizer(cols=3, hgap=5, vgap=5)
  80. flexSizer.AddGrowableCol(0)
  81. self.symbology = {}
  82. for label, key in self._symbologyData():
  83. textLabel = wx.StaticText(panel, wx.ID_ANY, label)
  84. color = csel.ColourSelect(
  85. panel, id=wx.ID_ANY, colour=UserSettings.Get(
  86. group='vdigit', key='symbol', subkey=[
  87. key, 'color']), size=(
  88. 40, 25))
  89. isEnabled = UserSettings.Get(group='vdigit', key='symbol',
  90. subkey=[key, 'enabled'])
  91. if isEnabled is not None:
  92. enabled = wx.CheckBox(panel, id=wx.ID_ANY, label="")
  93. enabled.SetValue(isEnabled)
  94. self.symbology[key] = (enabled, color)
  95. else:
  96. enabled = (1, 1)
  97. self.symbology[key] = (None, color)
  98. flexSizer.Add(
  99. textLabel,
  100. proportion=0,
  101. flag=wx.ALIGN_CENTER_VERTICAL)
  102. flexSizer.Add(
  103. enabled,
  104. proportion=0,
  105. flag=wx.ALIGN_CENTER | wx.FIXED_MINSIZE)
  106. flexSizer.Add(
  107. color,
  108. proportion=0,
  109. flag=wx.ALIGN_RIGHT | wx.FIXED_MINSIZE)
  110. color.SetName("GetColour")
  111. sizer.Add(
  112. item=flexSizer,
  113. proportion=1,
  114. flag=wx.ALL | wx.EXPAND,
  115. border=10)
  116. panel.SetSizer(sizer)
  117. return panel
  118. def _createGeneralPage(self, notebook):
  119. """Create notebook page concerning general settings"""
  120. panel = wx.Panel(parent=notebook, id=wx.ID_ANY)
  121. notebook.AddPage(page=panel, text=_("General"))
  122. border = wx.BoxSizer(wx.VERTICAL)
  123. #
  124. # display section
  125. #
  126. box = wx.StaticBox(
  127. parent=panel,
  128. id=wx.ID_ANY,
  129. label=" %s " %
  130. _("Display"))
  131. sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
  132. flexSizer = wx.FlexGridSizer(cols=3, hgap=5, vgap=5)
  133. flexSizer.AddGrowableCol(0)
  134. # line width
  135. text = wx.StaticText(parent=panel, id=wx.ID_ANY, label=_("Line width"))
  136. self.lineWidthValue = wx.SpinCtrl(
  137. parent=panel, id=wx.ID_ANY, size=(75, -1),
  138. initial=UserSettings.Get(
  139. group='vdigit', key="lineWidth", subkey='value'),
  140. min=1, max=1e6)
  141. units = wx.StaticText(
  142. parent=panel, id=wx.ID_ANY, size=(115, -1),
  143. label=UserSettings.Get(
  144. group='vdigit', key="lineWidth", subkey='units'),
  145. style=wx.ALIGN_LEFT)
  146. flexSizer.Add(text, proportion=0, flag=wx.ALIGN_CENTER_VERTICAL)
  147. flexSizer.Add(
  148. self.lineWidthValue,
  149. proportion=0,
  150. flag=wx.ALIGN_CENTER | wx.FIXED_MINSIZE)
  151. flexSizer.Add(
  152. units,
  153. proportion=0,
  154. flag=wx.ALIGN_RIGHT | wx.FIXED_MINSIZE | wx.ALIGN_CENTER_VERTICAL | wx.LEFT,
  155. border=10)
  156. sizer.Add(
  157. item=flexSizer,
  158. proportion=1,
  159. flag=wx.ALL | wx.EXPAND,
  160. border=1)
  161. border.Add(item=sizer, proportion=0, flag=wx.ALL | wx.EXPAND, border=5)
  162. #
  163. # snapping section
  164. #
  165. box = wx.StaticBox(
  166. parent=panel,
  167. id=wx.ID_ANY,
  168. label=" %s " %
  169. _("Snapping"))
  170. sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
  171. flexSizer = wx.FlexGridSizer(cols=3, hgap=5, vgap=5)
  172. flexSizer.AddGrowableCol(0)
  173. # snapping
  174. text = wx.StaticText(
  175. parent=panel,
  176. id=wx.ID_ANY,
  177. label=_("Snapping threshold"))
  178. self.snappingValue = wx.SpinCtrl(
  179. parent=panel, id=wx.ID_ANY, size=(75, -1),
  180. initial=UserSettings.Get(
  181. group='vdigit', key="snapping", subkey='value'),
  182. min=-1, max=1e6)
  183. self.snappingValue.Bind(wx.EVT_SPINCTRL, self.OnChangeSnappingValue)
  184. self.snappingValue.Bind(wx.EVT_TEXT, self.OnChangeSnappingValue)
  185. self.snappingUnit = wx.Choice(parent=panel, id=wx.ID_ANY, size=(
  186. 125, -1), choices=[_("screen pixels"), _("map units")])
  187. self.snappingUnit.SetStringSelection(
  188. UserSettings.Get(
  189. group='vdigit',
  190. key="snapping",
  191. subkey='units'))
  192. self.snappingUnit.Bind(wx.EVT_CHOICE, self.OnChangeSnappingUnits)
  193. flexSizer.Add(text, proportion=0, flag=wx.ALIGN_CENTER_VERTICAL)
  194. flexSizer.Add(
  195. self.snappingValue,
  196. proportion=0,
  197. flag=wx.ALIGN_CENTER | wx.FIXED_MINSIZE)
  198. flexSizer.Add(
  199. self.snappingUnit,
  200. proportion=0,
  201. flag=wx.ALIGN_RIGHT | wx.FIXED_MINSIZE)
  202. vertexSizer = wx.BoxSizer(wx.VERTICAL)
  203. self.snapVertex = wx.CheckBox(parent=panel, id=wx.ID_ANY,
  204. label=_("Snap also to vertex"))
  205. self.snapVertex.SetValue(
  206. UserSettings.Get(
  207. group='vdigit',
  208. key="snapToVertex",
  209. subkey='enabled'))
  210. vertexSizer.Add(item=self.snapVertex, proportion=0, flag=wx.EXPAND)
  211. self.mapUnits = self.parent.MapWindow.Map.GetProjInfo()['units']
  212. self.snappingInfo = wx.StaticText(
  213. parent=panel, id=wx.ID_ANY,
  214. label=_("Snapping threshold is %(value).1f %(units)s") %
  215. {'value': self.digit.GetDisplay().GetThreshold(),
  216. 'units': self.mapUnits})
  217. vertexSizer.Add(item=self.snappingInfo, proportion=0,
  218. flag=wx.ALL | wx.EXPAND, border=1)
  219. sizer.Add(item=flexSizer, proportion=1, flag=wx.EXPAND)
  220. sizer.Add(item=vertexSizer, proportion=1, flag=wx.EXPAND)
  221. border.Add(item=sizer, proportion=0, flag=wx.LEFT |
  222. wx.RIGHT | wx.BOTTOM | wx.EXPAND, border=5)
  223. #
  224. # select box
  225. #
  226. box = wx.StaticBox(
  227. parent=panel,
  228. id=wx.ID_ANY,
  229. label=" %s " %
  230. _("Select vector features"))
  231. # feature type
  232. sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
  233. inSizer = wx.BoxSizer(wx.HORIZONTAL)
  234. self.selectFeature = {}
  235. for feature in ('point', 'line',
  236. 'centroid', 'boundary'):
  237. chkbox = wx.CheckBox(parent=panel, label=feature)
  238. self.selectFeature[feature] = chkbox.GetId()
  239. chkbox.SetValue(UserSettings.Get(group='vdigit', key='selectType',
  240. subkey=[feature, 'enabled']))
  241. inSizer.Add(item=chkbox, proportion=0,
  242. flag=wx.EXPAND | wx.ALL, border=5)
  243. sizer.Add(item=inSizer, proportion=0, flag=wx.EXPAND)
  244. # threshold
  245. flexSizer = wx.FlexGridSizer(cols=3, hgap=5, vgap=5)
  246. flexSizer.AddGrowableCol(0)
  247. text = wx.StaticText(
  248. parent=panel,
  249. id=wx.ID_ANY,
  250. label=_("Select threshold"))
  251. self.selectThreshValue = wx.SpinCtrl(
  252. parent=panel, id=wx.ID_ANY, size=(75, -1),
  253. initial=UserSettings.Get(
  254. group='vdigit', key="selectThresh", subkey='value'),
  255. min=1, max=1e6)
  256. units = wx.StaticText(
  257. parent=panel, id=wx.ID_ANY, size=(115, -1),
  258. label=UserSettings.Get(
  259. group='vdigit', key="lineWidth", subkey='units'),
  260. style=wx.ALIGN_LEFT)
  261. flexSizer.Add(text, proportion=0, flag=wx.ALIGN_CENTER_VERTICAL)
  262. flexSizer.Add(self.selectThreshValue, proportion=0,
  263. flag=wx.ALIGN_CENTER | wx.FIXED_MINSIZE)
  264. flexSizer.Add(
  265. units,
  266. proportion=0,
  267. flag=wx.ALIGN_RIGHT | wx.FIXED_MINSIZE | wx.ALIGN_CENTER_VERTICAL | wx.LEFT,
  268. border=10)
  269. self.selectIn = wx.CheckBox(parent=panel, id=wx.ID_ANY, label=_(
  270. "Select only features inside of selection bounding box"))
  271. self.selectIn.SetValue(
  272. UserSettings.Get(
  273. group='vdigit',
  274. key="selectInside",
  275. subkey='enabled'))
  276. self.selectIn.SetToolTipString(
  277. _("By default are selected all features overlapping selection bounding box "))
  278. self.checkForDupl = wx.CheckBox(parent=panel, id=wx.ID_ANY,
  279. label=_("Check for duplicates"))
  280. self.checkForDupl.SetValue(
  281. UserSettings.Get(
  282. group='vdigit',
  283. key="checkForDupl",
  284. subkey='enabled'))
  285. sizer.Add(item=flexSizer, proportion=0, flag=wx.EXPAND)
  286. sizer.Add(
  287. item=self.selectIn,
  288. proportion=0,
  289. flag=wx.EXPAND | wx.ALL,
  290. border=1)
  291. sizer.Add(
  292. item=self.checkForDupl,
  293. proportion=0,
  294. flag=wx.EXPAND | wx.ALL,
  295. border=1)
  296. border.Add(item=sizer, proportion=0, flag=wx.EXPAND |
  297. wx.LEFT | wx.RIGHT | wx.BOTTOM, border=5)
  298. #
  299. # digitize lines box
  300. #
  301. box = wx.StaticBox(
  302. parent=panel, id=wx.ID_ANY, label=" %s " %
  303. _("Digitize lines/boundaries"))
  304. sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
  305. self.intersect = wx.CheckBox(
  306. parent=panel, label=_("Break lines at intersection"))
  307. self.intersect.SetValue(
  308. UserSettings.Get(
  309. group='vdigit',
  310. key='breakLines',
  311. subkey='enabled'))
  312. sizer.Add(
  313. item=self.intersect,
  314. proportion=0,
  315. flag=wx.ALL | wx.EXPAND,
  316. border=1)
  317. border.Add(item=sizer, proportion=0, flag=wx.EXPAND |
  318. wx.LEFT | wx.RIGHT | wx.BOTTOM, border=5)
  319. #
  320. # digitize areas box
  321. #
  322. box = wx.StaticBox(
  323. parent=panel,
  324. id=wx.ID_ANY,
  325. label=" %s " %
  326. _("Digitize areas"))
  327. sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
  328. self.closeBoundary = wx.CheckBox(
  329. parent=panel, label=_("Close boundary (snap to the start node)"))
  330. self.closeBoundary.SetValue(
  331. UserSettings.Get(
  332. group='vdigit',
  333. key='closeBoundary',
  334. subkey='enabled'))
  335. sizer.Add(
  336. item=self.closeBoundary,
  337. proportion=0,
  338. flag=wx.ALL | wx.EXPAND,
  339. border=1)
  340. border.Add(item=sizer, proportion=0, flag=wx.EXPAND |
  341. wx.LEFT | wx.RIGHT | wx.BOTTOM, border=5)
  342. #
  343. # save-on-exit box
  344. #
  345. box = wx.StaticBox(
  346. parent=panel,
  347. id=wx.ID_ANY,
  348. label=" %s " %
  349. _("Save changes"))
  350. # save changes on exit?
  351. sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
  352. self.save = wx.CheckBox(parent=panel, label=_("Save changes on exit"))
  353. self.save.SetValue(
  354. UserSettings.Get(
  355. group='vdigit',
  356. key='saveOnExit',
  357. subkey='enabled'))
  358. sizer.Add(
  359. item=self.save,
  360. proportion=0,
  361. flag=wx.ALL | wx.EXPAND,
  362. border=1)
  363. border.Add(item=sizer, proportion=0, flag=wx.EXPAND |
  364. wx.LEFT | wx.RIGHT | wx.BOTTOM, border=5)
  365. panel.SetSizer(border)
  366. return panel
  367. def _createQueryPage(self, notebook):
  368. """Create notebook page for query tool"""
  369. panel = wx.Panel(parent=notebook, id=wx.ID_ANY)
  370. notebook.AddPage(page=panel, text=_("Query tool"))
  371. border = wx.BoxSizer(wx.VERTICAL)
  372. #
  373. # query tool box
  374. #
  375. box = wx.StaticBox(
  376. parent=panel,
  377. id=wx.ID_ANY,
  378. label=" %s " %
  379. _("Choose query tool"))
  380. sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
  381. LocUnits = self.parent.MapWindow.Map.GetProjInfo()['units']
  382. self.queryBox = wx.CheckBox(
  383. parent=panel,
  384. id=wx.ID_ANY,
  385. label=_("Select by box"))
  386. self.queryBox.SetValue(
  387. UserSettings.Get(
  388. group='vdigit',
  389. key="query",
  390. subkey='box'))
  391. sizer.Add(
  392. item=self.queryBox,
  393. proportion=0,
  394. flag=wx.ALL | wx.EXPAND,
  395. border=1)
  396. sizer.Add((0, 5))
  397. #
  398. # length
  399. #
  400. self.queryLength = wx.RadioButton(
  401. parent=panel, id=wx.ID_ANY, label=_("length"))
  402. self.queryLength.Bind(wx.EVT_RADIOBUTTON, self.OnChangeQuery)
  403. sizer.Add(
  404. item=self.queryLength,
  405. proportion=0,
  406. flag=wx.ALL | wx.EXPAND,
  407. border=1)
  408. flexSizer = wx.FlexGridSizer(cols=4, hgap=5, vgap=5)
  409. flexSizer.AddGrowableCol(0)
  410. txt = wx.StaticText(
  411. parent=panel,
  412. id=wx.ID_ANY,
  413. label=_("Select lines"))
  414. self.queryLengthSL = wx.Choice(
  415. parent=panel, id=wx.ID_ANY, choices=[
  416. _("shorter than"), _("longer than")])
  417. self.queryLengthSL.SetSelection(
  418. UserSettings.Get(
  419. group='vdigit',
  420. key="queryLength",
  421. subkey='than-selection'))
  422. self.queryLengthValue = wx.SpinCtrl(
  423. parent=panel, id=wx.ID_ANY, size=(
  424. 100, -1), initial=1, min=0, max=1e6)
  425. self.queryLengthValue.SetValue(
  426. UserSettings.Get(
  427. group='vdigit',
  428. key="queryLength",
  429. subkey='thresh'))
  430. units = wx.StaticText(
  431. parent=panel,
  432. id=wx.ID_ANY,
  433. label="%s" %
  434. LocUnits)
  435. flexSizer.Add(txt, proportion=0, flag=wx.ALIGN_CENTER_VERTICAL)
  436. flexSizer.Add(
  437. self.queryLengthSL,
  438. proportion=0,
  439. flag=wx.ALIGN_CENTER | wx.FIXED_MINSIZE)
  440. flexSizer.Add(
  441. self.queryLengthValue,
  442. proportion=0,
  443. flag=wx.ALIGN_CENTER | wx.FIXED_MINSIZE)
  444. flexSizer.Add(units, proportion=0, flag=wx.ALIGN_CENTER_VERTICAL)
  445. sizer.Add(
  446. item=flexSizer,
  447. proportion=0,
  448. flag=wx.ALL | wx.EXPAND,
  449. border=1)
  450. #
  451. # dangle
  452. #
  453. self.queryDangle = wx.RadioButton(
  454. parent=panel, id=wx.ID_ANY, label=_("dangle"))
  455. self.queryDangle.Bind(wx.EVT_RADIOBUTTON, self.OnChangeQuery)
  456. sizer.Add(
  457. item=self.queryDangle,
  458. proportion=0,
  459. flag=wx.ALL | wx.EXPAND,
  460. border=1)
  461. flexSizer = wx.FlexGridSizer(cols=4, hgap=5, vgap=5)
  462. flexSizer.AddGrowableCol(0)
  463. txt = wx.StaticText(
  464. parent=panel,
  465. id=wx.ID_ANY,
  466. label=_("Select dangles"))
  467. self.queryDangleSL = wx.Choice(
  468. parent=panel, id=wx.ID_ANY, choices=[
  469. _("shorter than"), _("longer than")])
  470. self.queryDangleSL.SetSelection(
  471. UserSettings.Get(
  472. group='vdigit',
  473. key="queryDangle",
  474. subkey='than-selection'))
  475. self.queryDangleValue = wx.SpinCtrl(
  476. parent=panel, id=wx.ID_ANY, size=(
  477. 100, -1), initial=1, min=0, max=1e6)
  478. self.queryDangleValue.SetValue(
  479. UserSettings.Get(
  480. group='vdigit',
  481. key="queryDangle",
  482. subkey='thresh'))
  483. units = wx.StaticText(
  484. parent=panel,
  485. id=wx.ID_ANY,
  486. label="%s" %
  487. LocUnits)
  488. flexSizer.Add(txt, proportion=0, flag=wx.ALIGN_CENTER_VERTICAL)
  489. flexSizer.Add(
  490. self.queryDangleSL,
  491. proportion=0,
  492. flag=wx.ALIGN_CENTER | wx.FIXED_MINSIZE)
  493. flexSizer.Add(
  494. self.queryDangleValue,
  495. proportion=0,
  496. flag=wx.ALIGN_CENTER | wx.FIXED_MINSIZE)
  497. flexSizer.Add(units, proportion=0, flag=wx.ALIGN_CENTER_VERTICAL)
  498. sizer.Add(
  499. item=flexSizer,
  500. proportion=0,
  501. flag=wx.ALL | wx.EXPAND,
  502. border=1)
  503. if UserSettings.Get(group='vdigit', key="query",
  504. subkey='selection') == 0:
  505. self.queryLength.SetValue(True)
  506. else:
  507. self.queryDangle.SetValue(True)
  508. # enable & disable items
  509. self.OnChangeQuery(None)
  510. border.Add(item=sizer, proportion=0, flag=wx.ALL | wx.EXPAND, border=5)
  511. panel.SetSizer(border)
  512. return panel
  513. def _createAttributesPage(self, notebook):
  514. """Create notebook page for attributes"""
  515. panel = wx.Panel(parent=notebook, id=wx.ID_ANY)
  516. notebook.AddPage(page=panel, text=_("Attributes"))
  517. border = wx.BoxSizer(wx.VERTICAL)
  518. #
  519. # add new record
  520. #
  521. box = wx.StaticBox(
  522. parent=panel,
  523. id=wx.ID_ANY,
  524. label=" %s " %
  525. _("Digitize new feature"))
  526. sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
  527. # checkbox
  528. self.addRecord = wx.CheckBox(parent=panel, id=wx.ID_ANY,
  529. label=_("Add new record into table"))
  530. self.addRecord.SetValue(
  531. UserSettings.Get(
  532. group='vdigit',
  533. key="addRecord",
  534. subkey='enabled'))
  535. sizer.Add(
  536. item=self.addRecord,
  537. proportion=0,
  538. flag=wx.ALL | wx.EXPAND,
  539. border=1)
  540. # settings
  541. flexSizer = wx.FlexGridSizer(cols=2, hgap=3, vgap=3)
  542. flexSizer.AddGrowableCol(0)
  543. settings = ((_("Layer"), 1), (_("Category"), 1),
  544. (_("Mode"), _("Next to use")))
  545. # layer
  546. text = wx.StaticText(parent=panel, id=wx.ID_ANY, label=_("Layer"))
  547. self.layer = wx.SpinCtrl(parent=panel, id=wx.ID_ANY, size=(125, -1),
  548. min=1, max=1e3)
  549. self.layer.SetValue(int(UserSettings.Get(
  550. group='vdigit', key="layer", subkey='value')))
  551. flexSizer.Add(item=text, proportion=0, flag=wx.ALIGN_CENTER_VERTICAL)
  552. flexSizer.Add(item=self.layer, proportion=0,
  553. flag=wx.FIXED_MINSIZE | wx.ALIGN_CENTER_VERTICAL)
  554. # category number
  555. text = wx.StaticText(
  556. parent=panel,
  557. id=wx.ID_ANY,
  558. label=_("Category number"))
  559. self.category = wx.SpinCtrl(
  560. parent=panel, id=wx.ID_ANY, size=(125, -1),
  561. initial=UserSettings.Get(
  562. group='vdigit', key="category", subkey='value'),
  563. min=-1e9, max=1e9)
  564. if UserSettings.Get(group='vdigit', key="categoryMode",
  565. subkey='selection') != 1:
  566. self.category.Enable(False)
  567. flexSizer.Add(item=text, proportion=0, flag=wx.ALIGN_CENTER_VERTICAL)
  568. flexSizer.Add(item=self.category, proportion=0,
  569. flag=wx.FIXED_MINSIZE | wx.ALIGN_CENTER_VERTICAL)
  570. # category mode
  571. text = wx.StaticText(
  572. parent=panel,
  573. id=wx.ID_ANY,
  574. label=_("Category mode"))
  575. self.categoryMode = wx.Choice(parent=panel, id=wx.ID_ANY, size=(
  576. 125, -1), choices=[_("Next to use"), _("Manual entry"), _("No category")])
  577. self.categoryMode.SetSelection(
  578. UserSettings.Get(
  579. group='vdigit',
  580. key="categoryMode",
  581. subkey='selection'))
  582. flexSizer.Add(item=text, proportion=0, flag=wx.ALIGN_CENTER_VERTICAL)
  583. flexSizer.Add(item=self.categoryMode, proportion=0,
  584. flag=wx.FIXED_MINSIZE | wx.ALIGN_CENTER_VERTICAL)
  585. sizer.Add(
  586. item=flexSizer,
  587. proportion=1,
  588. flag=wx.ALL | wx.EXPAND,
  589. border=1)
  590. border.Add(item=sizer, proportion=0,
  591. flag=wx.ALL | wx.EXPAND, border=5)
  592. #
  593. # delete existing record
  594. #
  595. box = wx.StaticBox(
  596. parent=panel, id=wx.ID_ANY, label=" %s " %
  597. _("Delete existing feature(s)"))
  598. sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
  599. # checkbox
  600. self.deleteRecord = wx.CheckBox(parent=panel, id=wx.ID_ANY,
  601. label=_("Delete record from table"))
  602. self.deleteRecord.SetValue(
  603. UserSettings.Get(
  604. group='vdigit',
  605. key="delRecord",
  606. subkey='enabled'))
  607. sizer.Add(
  608. item=self.deleteRecord,
  609. proportion=0,
  610. flag=wx.ALL | wx.EXPAND,
  611. border=1)
  612. border.Add(item=sizer, proportion=0,
  613. flag=wx.LEFT | wx.RIGHT | wx.BOTTOM | wx.EXPAND, border=5)
  614. #
  615. # geometry attributes (currently only length and area are supported)
  616. #
  617. box = wx.StaticBox(parent=panel, id=wx.ID_ANY,
  618. label=" %s " % _("Geometry attributes"))
  619. sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
  620. gridSizer = wx.GridBagSizer(hgap=3, vgap=3)
  621. self.geomAttrb = {'length': {'label': _('length')},
  622. 'area': {'label': _('area')},
  623. 'perimeter': {'label': _('perimeter')}}
  624. digitToolbar = self.parent.toolbars['vdigit']
  625. try:
  626. vectorName = digitToolbar.GetLayer().GetName()
  627. except AttributeError:
  628. vectorName = None # no vector selected for editing
  629. layer = UserSettings.Get(group='vdigit', key="layer", subkey='value')
  630. mapLayer = self.parent.toolbars['vdigit'].GetLayer()
  631. tree = self.parent.tree
  632. if tree:
  633. item = tree.FindItemByData('maplayer', mapLayer)
  634. else:
  635. item = None
  636. row = 0
  637. for attrb in ['length', 'area', 'perimeter']:
  638. # checkbox
  639. check = wx.CheckBox(parent=panel, id=wx.ID_ANY,
  640. label=self.geomAttrb[attrb]['label'])
  641. ### self.deleteRecord.SetValue(UserSettings.Get(group='vdigit', key="delRecord", subkey='enabled'))
  642. check.Bind(wx.EVT_CHECKBOX, self.OnGeomAttrb)
  643. # column (only numeric)
  644. column = ColumnSelect(parent=panel, size=(200, -1))
  645. column.InsertColumns(vector=vectorName,
  646. layer=layer, excludeKey=True,
  647. type=['integer', 'double precision'])
  648. # units
  649. if attrb == 'area':
  650. choices = Units.GetUnitsList('area')
  651. else:
  652. choices = Units.GetUnitsList('length')
  653. win_units = wx.Choice(parent=panel, id=wx.ID_ANY,
  654. choices=choices, size=(120, -1))
  655. # default values
  656. check.SetValue(False)
  657. if item and tree.GetLayerInfo(item, key='vdigit') and \
  658. 'geomAttr' in tree.GetLayerInfo(item, key='vdigit') and \
  659. attrb in tree.GetLayerInfo(item, key='vdigit')['geomAttr']:
  660. check.SetValue(True)
  661. column.SetStringSelection(
  662. tree.GetLayerInfo(item, key='vdigit')['geomAttr']
  663. [attrb]['column'])
  664. if attrb == 'area':
  665. type = 'area'
  666. else:
  667. type = 'length'
  668. unitsIdx = Units.GetUnitsIndex(type, tree.GetLayerInfo(
  669. item, key='vdigit')['geomAttr'][attrb]['units'])
  670. win_units.SetSelection(unitsIdx)
  671. if not vectorName:
  672. check.Enable(False)
  673. column.Enable(False)
  674. if not check.IsChecked():
  675. column.Enable(False)
  676. self.geomAttrb[attrb]['check'] = check.GetId()
  677. self.geomAttrb[attrb]['column'] = column.GetId()
  678. self.geomAttrb[attrb]['units'] = win_units.GetId()
  679. gridSizer.Add(item=check,
  680. flag=wx.ALIGN_CENTER_VERTICAL,
  681. pos=(row, 0))
  682. gridSizer.Add(item=column,
  683. pos=(row, 1))
  684. gridSizer.Add(item=win_units,
  685. pos=(row, 2))
  686. row += 1
  687. note = '\n'.join(textwrap.wrap(_("Note: These settings are stored "
  688. "in the workspace not in the vector digitizer "
  689. "preferences."), 55))
  690. gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
  691. label=note),
  692. pos=(3, 0), span=(1, 3))
  693. gridSizer.AddGrowableCol(0)
  694. sizer.Add(item=gridSizer, proportion=1,
  695. flag=wx.ALL | wx.EXPAND, border=1)
  696. border.Add(item=sizer, proportion=0,
  697. flag=wx.LEFT | wx.RIGHT | wx.BOTTOM | wx.EXPAND, border=5)
  698. # bindings
  699. self.Bind(wx.EVT_CHECKBOX, self.OnChangeAddRecord, self.addRecord)
  700. self.Bind(wx.EVT_CHOICE, self.OnChangeCategoryMode, self.categoryMode)
  701. self.Bind(wx.EVT_SPINCTRL, self.OnChangeLayer, self.layer)
  702. panel.SetSizer(border)
  703. return panel
  704. def _symbologyData(self):
  705. """Data for _createSymbologyPage()
  706. label | checkbox | color
  707. """
  708. return (
  709. (_("Digitize new line segment"), "newSegment"),
  710. (_("Digitize new line/boundary"), "newLine"),
  711. (_("Highlight"), "highlight"),
  712. (_("Highlight (duplicates)"), "highlightDupl"),
  713. (_("Point"), "point"),
  714. (_("Line"), "line"),
  715. (_("Boundary (no area)"), "boundaryNo"),
  716. (_("Boundary (one area)"), "boundaryOne"),
  717. (_("Boundary (two areas)"), "boundaryTwo"),
  718. (_("Centroid (in area)"), "centroidIn"),
  719. (_("Centroid (outside area)"), "centroidOut"),
  720. (_("Centroid (duplicate in area)"), "centroidDup"),
  721. (_("Node (one line)"), "nodeOne"),
  722. (_("Node (two lines)"), "nodeTwo"),
  723. (_("Vertex"), "vertex"),
  724. (_("Area (closed boundary + centroid)"), "area"),
  725. (_("Direction"), "direction"),)
  726. def OnGeomAttrb(self, event):
  727. """Register geometry attributes (enable/disable)
  728. """
  729. checked = event.IsChecked()
  730. id = event.GetId()
  731. key = None
  732. for attrb, val in self.geomAttrb.iteritems():
  733. if val['check'] == id:
  734. key = attrb
  735. break
  736. column = self.FindWindowById(self.geomAttrb[key]['column'])
  737. if checked:
  738. column.Enable()
  739. else:
  740. column.Enable(False)
  741. def OnChangeCategoryMode(self, event):
  742. """Change category mode
  743. """
  744. mode = event.GetSelection()
  745. UserSettings.Set(
  746. group='vdigit',
  747. key="categoryMode",
  748. subkey='selection',
  749. value=mode)
  750. if mode == 1: # manual entry
  751. self.category.Enable(True)
  752. elif self.category.IsEnabled(): # disable
  753. self.category.Enable(False)
  754. if mode == 2 and self.addRecord.IsChecked(): # no category
  755. self.addRecord.SetValue(False)
  756. self.digit.SetCategory()
  757. self.category.SetValue(
  758. UserSettings.Get(
  759. group='vdigit',
  760. key='category',
  761. subkey='value'))
  762. def OnChangeLayer(self, event):
  763. """Layer changed
  764. """
  765. layer = event.GetInt()
  766. if layer > 0:
  767. UserSettings.Set(
  768. group='vdigit',
  769. key='layer',
  770. subkey='value',
  771. value=layer)
  772. self.digit.SetCategory()
  773. self.category.SetValue(
  774. UserSettings.Get(
  775. group='vdigit',
  776. key='category',
  777. subkey='value'))
  778. event.Skip()
  779. def OnChangeAddRecord(self, event):
  780. """Checkbox 'Add new record' status changed
  781. """
  782. pass
  783. # self.category.SetValue(self.digit.SetCategory())
  784. def OnChangeSnappingValue(self, event):
  785. """Change snapping value - update static text
  786. """
  787. value = self.snappingValue.GetValue()
  788. if value < 0:
  789. region = self.parent.MapWindow.Map.GetRegion()
  790. res = (region['nsres'] + region['ewres']) / 2.
  791. threshold = self.digit.GetDisplay().GetThreshold(value=res)
  792. else:
  793. if self.snappingUnit.GetStringSelection() == "map units":
  794. threshold = value
  795. else:
  796. threshold = self.digit.GetDisplay().GetThreshold(value=value)
  797. if value == 0:
  798. self.snappingInfo.SetLabel(_("Snapping disabled"))
  799. elif value < 0:
  800. self.snappingInfo.SetLabel(
  801. _(
  802. "Snapping threshold is %(value).1f %(units)s "
  803. "(based on comp. resolution)") %
  804. {'value': threshold, 'units': self.mapUnits.lower()})
  805. else:
  806. self.snappingInfo.SetLabel(
  807. _("Snapping threshold is %(value).1f %(units)s") %
  808. {'value': threshold, 'units': self.mapUnits.lower()})
  809. event.Skip()
  810. def OnChangeSnappingUnits(self, event):
  811. """Snapping units change -> update static text
  812. """
  813. value = self.snappingValue.GetValue()
  814. units = self.snappingUnit.GetStringSelection()
  815. threshold = self.digit.GetDisplay().GetThreshold(value=value, units=units)
  816. if units == "map units":
  817. self.snappingInfo.SetLabel(
  818. _("Snapping threshold is %(value).1f %(units)s") %
  819. {'value': value, 'units': self.mapUnits})
  820. else:
  821. self.snappingInfo.SetLabel(
  822. _("Snapping threshold is %(value).1f %(units)s") %
  823. {'value': threshold, 'units': self.mapUnits})
  824. event.Skip()
  825. def OnChangeQuery(self, event):
  826. """Change query
  827. """
  828. if self.queryLength.GetValue():
  829. # length
  830. self.queryLengthSL.Enable(True)
  831. self.queryLengthValue.Enable(True)
  832. self.queryDangleSL.Enable(False)
  833. self.queryDangleValue.Enable(False)
  834. else:
  835. # dangle
  836. self.queryLengthSL.Enable(False)
  837. self.queryLengthValue.Enable(False)
  838. self.queryDangleSL.Enable(True)
  839. self.queryDangleValue.Enable(True)
  840. def OnSave(self, event):
  841. """Button 'Save' pressed
  842. """
  843. self.UpdateSettings()
  844. self.parent.toolbars['vdigit'].settingsDialog = None
  845. fileSettings = {}
  846. UserSettings.ReadSettingsFile(settings=fileSettings)
  847. fileSettings['vdigit'] = UserSettings.Get(group='vdigit')
  848. sfile = UserSettings.SaveToFile(fileSettings)
  849. self._giface.WriteLog(
  850. _('Vector digitizer settings saved to file <%s>.') %
  851. sfile)
  852. self.Destroy()
  853. event.Skip()
  854. def OnApply(self, event):
  855. """Button 'Apply' pressed
  856. """
  857. self.UpdateSettings()
  858. def OnCancel(self, event):
  859. """Button 'Cancel' pressed
  860. """
  861. self.parent.toolbars['vdigit'].settingsDialog = None
  862. self.Destroy()
  863. if event:
  864. event.Skip()
  865. def UpdateSettings(self):
  866. """Update digitizer settings
  867. .. todo::
  868. Needs refactoring
  869. """
  870. # TODO: it seems that it needs to be replaced by signal
  871. # but if it makes sense generally for wxGUI it can be added to giface
  872. if self.parent.GetLayerManager():
  873. self.parent.GetLayerManager().WorkspaceChanged() # geometry attributes
  874. # symbology
  875. for key, (enabled, color) in self.symbology.iteritems():
  876. if enabled:
  877. UserSettings.Set(group='vdigit', key='symbol',
  878. subkey=[key, 'enabled'],
  879. value=enabled.IsChecked())
  880. UserSettings.Set(group='vdigit', key='symbol',
  881. subkey=[key, 'color'],
  882. value=tuple(color.GetColour()))
  883. else:
  884. UserSettings.Set(group='vdigit', key='symbol',
  885. subkey=[key, 'color'],
  886. value=tuple(color.GetColour()))
  887. # display
  888. UserSettings.Set(group='vdigit', key="lineWidth", subkey='value',
  889. value=int(self.lineWidthValue.GetValue()))
  890. # snapping
  891. UserSettings.Set(group='vdigit', key="snapping", subkey='value',
  892. value=int(self.snappingValue.GetValue()))
  893. UserSettings.Set(group='vdigit', key="snapping", subkey='units',
  894. value=self.snappingUnit.GetStringSelection())
  895. UserSettings.Set(group='vdigit', key="snapToVertex", subkey='enabled',
  896. value=self.snapVertex.IsChecked())
  897. # digitize new feature
  898. UserSettings.Set(group='vdigit', key="addRecord", subkey='enabled',
  899. value=self.addRecord.IsChecked())
  900. UserSettings.Set(group='vdigit', key="layer", subkey='value',
  901. value=int(self.layer.GetValue()))
  902. UserSettings.Set(group='vdigit', key="category", subkey='value',
  903. value=int(self.category.GetValue()))
  904. UserSettings.Set(
  905. group='vdigit',
  906. key="categoryMode",
  907. subkey='selection',
  908. value=self.categoryMode.GetSelection())
  909. # delete existing feature
  910. UserSettings.Set(group='vdigit', key="delRecord", subkey='enabled',
  911. value=self.deleteRecord.IsChecked())
  912. # geometry attributes (workspace)
  913. mapLayer = self.parent.toolbars['vdigit'].GetLayer()
  914. tree = self._giface.GetLayerTree()
  915. if tree:
  916. item = tree.FindItemByData('maplayer', mapLayer)
  917. else:
  918. item = None
  919. for key, val in self.geomAttrb.iteritems():
  920. checked = self.FindWindowById(val['check']).IsChecked()
  921. column = self.FindWindowById(val['column']).GetValue()
  922. unitsIdx = self.FindWindowById(val['units']).GetSelection()
  923. if item and not tree.GetLayerInfo(item, key='vdigit'):
  924. tree.SetLayerInfo(
  925. item, key='vdigit', value={
  926. 'geomAttr': dict()})
  927. if checked: # enable
  928. if key == 'area':
  929. type = key
  930. else:
  931. type = 'length'
  932. unitsKey = Units.GetUnitsKey(type, unitsIdx)
  933. tree.GetLayerInfo(item, key='vdigit')['geomAttr'][key] = {
  934. 'column': column, 'units': unitsKey}
  935. else:
  936. if item and tree.GetLayerInfo(
  937. item, key='vdigit') and key in tree.GetLayerInfo(
  938. item, key='vdigit')['geomAttr']:
  939. del tree.GetLayerInfo(item, key='vdigit')['geomAttr'][key]
  940. # query tool
  941. if self.queryLength.GetValue():
  942. UserSettings.Set(group='vdigit', key="query", subkey='selection',
  943. value=0)
  944. else:
  945. UserSettings.Set(group='vdigit', key="query", subkey='type',
  946. value=1)
  947. UserSettings.Set(group='vdigit', key="query", subkey='box',
  948. value=self.queryBox.IsChecked())
  949. UserSettings.Set(
  950. group='vdigit',
  951. key="queryLength",
  952. subkey='than-selection',
  953. value=self.queryLengthSL.GetSelection())
  954. UserSettings.Set(group='vdigit', key="queryLength", subkey='thresh',
  955. value=int(self.queryLengthValue.GetValue()))
  956. UserSettings.Set(
  957. group='vdigit',
  958. key="queryDangle",
  959. subkey='than-selection',
  960. value=self.queryDangleSL.GetSelection())
  961. UserSettings.Set(group='vdigit', key="queryDangle", subkey='thresh',
  962. value=int(self.queryDangleValue.GetValue()))
  963. # select features
  964. for feature in ('point', 'line',
  965. 'centroid', 'boundary'):
  966. UserSettings.Set(
  967. group='vdigit', key='selectType', subkey=[
  968. feature, 'enabled'], value=self.FindWindowById(
  969. self.selectFeature[feature]).IsChecked())
  970. UserSettings.Set(group='vdigit', key="selectThresh", subkey='value',
  971. value=int(self.selectThreshValue.GetValue()))
  972. UserSettings.Set(group='vdigit', key="checkForDupl", subkey='enabled',
  973. value=self.checkForDupl.IsChecked())
  974. UserSettings.Set(group='vdigit', key="selectInside", subkey='enabled',
  975. value=self.selectIn.IsChecked())
  976. # on-exit
  977. UserSettings.Set(group='vdigit', key="saveOnExit", subkey='enabled',
  978. value=self.save.IsChecked())
  979. # break lines
  980. UserSettings.Set(group='vdigit', key="breakLines", subkey='enabled',
  981. value=self.intersect.IsChecked())
  982. # close boundary
  983. UserSettings.Set(group='vdigit', key="closeBoundary", subkey='enabled',
  984. value=self.closeBoundary.IsChecked())
  985. self.digit.UpdateSettings()
  986. # redraw map if auto-rendering is enabled
  987. if self.parent.IsAutoRendered():
  988. self.parent.OnRender(None)