location_wizard.py 91 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470
  1. """
  2. MODULE: location_wizard.py
  3. CLASSES:
  4. * BaseClass
  5. * TitledPage
  6. * DatabasePage
  7. * CoordinateSystemPage
  8. * ProjectionsPage
  9. * ItemList
  10. * ProjTypePage
  11. * DatumPage
  12. * EllipsePage
  13. * GeoreferencedFilePage
  14. * EPSGPage
  15. * CustomPage
  16. * SummaryPage
  17. * RegionDef
  18. * LocationWizard
  19. PURPOSE: Create a new GRASS Location. User can choose from multiple methods.
  20. AUTHORS: The GRASS Development Team
  21. Michael Barton
  22. Jachym Cepicky
  23. Martin Landa <landa.martin gmail.com>
  24. COPYRIGHT: (C) 2006-2007 by the GRASS Development Team
  25. This program is free software under the GNU General Public
  26. License (>=v2). Read the file COPYING that comes with GRASS
  27. for details.
  28. """
  29. import os
  30. import shutil
  31. import re
  32. import string
  33. import sys
  34. import locale
  35. import wx
  36. import wx.lib.mixins.listctrl as listmix
  37. import wx.wizard as wiz
  38. import gcmd
  39. import globalvar
  40. try:
  41. import subprocess
  42. except:
  43. CompatPath = os.path.join(globalvar.ETCWXDIR)
  44. sys.path.append(CompatPath)
  45. from compat import subprocess
  46. global coordsys
  47. global north
  48. global south
  49. global east
  50. global west
  51. global resolution
  52. global wizerror
  53. coordsys = ''
  54. north = ''
  55. south = ''
  56. east = ''
  57. west = ''
  58. resolution = ''
  59. class BaseClass(wx.Object):
  60. """Base class providing basic methods"""
  61. def __init__(self):
  62. pass
  63. def MakeLabel(self, text="", style=wx.ALIGN_LEFT):
  64. """Make aligned label"""
  65. return wx.StaticText(parent=self, id=wx.ID_ANY, label=text,
  66. style=style)
  67. def MakeTextCtrl(self, text='', size=(100,-1), style=0):
  68. """Generic text control"""
  69. return wx.TextCtrl(parent=self, id=wx.ID_ANY, value=text,
  70. size=size, style=style)
  71. def MakeButton(self, text, id=wx.ID_ANY, size=(-1,-1)):
  72. """Generic button"""
  73. return wx.Button(parent=self, id=id, label=text,
  74. size=size)
  75. class TitledPage(BaseClass, wiz.WizardPageSimple):
  76. """
  77. Class to make wizard pages. Generic methods to make
  78. labels, text entries, and buttons.
  79. """
  80. def __init__(self, parent, title):
  81. self.page = wiz.WizardPageSimple.__init__(self, parent)
  82. # page title
  83. self.title = wx.StaticText(parent=self, id=wx.ID_ANY, label=title)
  84. self.title.SetFont(wx.Font(13, wx.SWISS, wx.NORMAL, wx.BOLD))
  85. # main sizer
  86. self.sizer = wx.GridBagSizer(vgap=0, hgap=0)
  87. def DoLayout(self):
  88. """Do page layout"""
  89. tmpsizer = wx.BoxSizer(wx.VERTICAL)
  90. tmpsizer.Add(item=self.title, proportion=0,
  91. flag=wx.ALIGN_CENTRE | wx.ALL,
  92. border=5)
  93. tmpsizer.Add(item=wx.StaticLine(self, -1), proportion=0,
  94. flag=wx.EXPAND | wx.ALL,
  95. border=0)
  96. tmpsizer.Add(item=self.sizer, proportion=1,
  97. flag=wx.EXPAND | wx.ALL,
  98. border=5)
  99. self.SetAutoLayout(True)
  100. self.SetSizer(tmpsizer)
  101. # tmpsizer.Fit(self)
  102. self.Layout()
  103. class DatabasePage(TitledPage):
  104. """
  105. Wizard page for setting GIS data directory and location name
  106. """
  107. def __init__(self, wizard, parent, grassdatabase):
  108. TitledPage.__init__(self, wizard, _("Define GRASS Database and Location Name"))
  109. self.grassdatabase = grassdatabase
  110. self.location = ''
  111. # buttons
  112. self.bbrowse = self.MakeButton(_("Browse"))
  113. # text controls
  114. self.tgisdbase = self.MakeTextCtrl(grassdatabase, size=(300, -1))
  115. self.tlocation = self.MakeTextCtrl("newLocation", size=(300, -1))
  116. # layout
  117. self.sizer.AddGrowableCol(3)
  118. self.sizer.Add(item=self.MakeLabel(_("GIS Data Directory:")),
  119. flag=wx.ALIGN_RIGHT |
  120. wx.ALIGN_CENTER_VERTICAL |
  121. wx.ALL, border=5,
  122. pos=(1, 1))
  123. self.sizer.Add(item=self.tgisdbase,
  124. flag=wx.ALIGN_LEFT |
  125. wx.ALIGN_CENTER_VERTICAL |
  126. wx.ALL, border=5,
  127. pos=(1, 2))
  128. self.sizer.Add(item=self.bbrowse,
  129. flag=wx.ALIGN_LEFT |
  130. wx.ALIGN_CENTER_VERTICAL |
  131. wx.ALL, border=5,
  132. pos=(1, 3))
  133. #
  134. self.sizer.Add(item=self.MakeLabel("%s:" % _("Project Location")),
  135. flag=wx.ALIGN_RIGHT |
  136. wx.ALIGN_CENTER_VERTICAL |
  137. wx.ALL, border=5,
  138. pos=(2, 1))
  139. self.sizer.Add(item=self.tlocation,
  140. flag=wx.ALIGN_LEFT |
  141. wx.ALIGN_CENTER_VERTICAL |
  142. wx.ALL, border=5,
  143. pos=(2, 2))
  144. # self.sizer.Add(item=self.MakeLabel(_("(projection/coordinate system)")),
  145. # flag=wx.ALIGN_LEFT |
  146. # wx.ALIGN_CENTER_VERTICAL |
  147. # wx.ALL, border=5,
  148. # pos=(2, 4))
  149. # bindings
  150. self.Bind(wx.EVT_BUTTON, self.OnBrowse, self.bbrowse)
  151. self.Bind(wiz.EVT_WIZARD_PAGE_CHANGING, self.OnPageChanging)
  152. self.Bind(wiz.EVT_WIZARD_PAGE_CHANGED, self.OnEnterPage)
  153. self.tgisdbase.Bind(wx.EVT_TEXT, self.OnChangeName)
  154. self.tlocation.Bind(wx.EVT_TEXT, self.OnChangeName)
  155. # do page layout
  156. # self.DoLayout()
  157. def OnChangeName(self, event):
  158. """Name for new location was changed"""
  159. nextButton = wx.FindWindowById(wx.ID_FORWARD)
  160. if len(event.GetString()) > 0:
  161. if not nextButton.IsEnabled():
  162. nextButton.Enable()
  163. else:
  164. nextButton.Disable()
  165. event.Skip()
  166. def OnBrowse(self, event):
  167. dlg = wx.DirDialog(self, _("Choose GRASS data directory:"),
  168. os.getcwd(), wx.DD_DEFAULT_STYLE)
  169. if dlg.ShowModal() == wx.ID_OK:
  170. self.grassdatabase = dlg.GetPath()
  171. self.tgisdbase.SetValue(self.grassdatabase)
  172. dlg.Destroy()
  173. def OnPageChanging(self,event=None):
  174. error = ''
  175. if os.path.isdir(os.path.join(self.tgisdbase.GetValue(), self.tlocation.GetValue())):
  176. error = _("Location already exists in GRASS Database.")
  177. if error != '':
  178. dlg = wx.MessageDialog(parent=self, message="%s <%s>.%s%s" % (_("Unable to create location"),
  179. str(self.tlocation.GetValue()),
  180. os.linesep,
  181. error),
  182. caption=_("Error"), style=wx.OK | wx.ICON_ERROR)
  183. dlg.ShowModal()
  184. dlg.Destroy()
  185. event.Veto()
  186. return
  187. self.location = self.tlocation.GetValue()
  188. self.grassdatabase = self.tgisdbase.GetValue()
  189. def OnEnterPage(self, event):
  190. """Wizard page changed"""
  191. self.grassdatabase = self.tgisdbase.GetValue()
  192. self.location = self.tlocation.GetValue()
  193. event.Skip()
  194. class CoordinateSystemPage(TitledPage):
  195. """
  196. Wizard page for choosing method for location creation
  197. """
  198. def __init__(self, wizard, parent):
  199. TitledPage.__init__(self, wizard, _("Choose method for creating a new location"))
  200. self.parent = parent
  201. global coordsys
  202. # toggles
  203. self.radio1 = wx.RadioButton(parent=self, id=wx.ID_ANY,
  204. label=_("Select coordinate system"),
  205. style = wx.RB_GROUP)
  206. self.radio2 = wx.RadioButton(parent=self, id=wx.ID_ANY,
  207. label=_("Select EPSG code of coordinate system"))
  208. self.radio3 = wx.RadioButton(parent=self, id=wx.ID_ANY,
  209. label=_("Use coordinate system of selected "
  210. "georeferenced file"))
  211. self.radio4 = wx.RadioButton(parent=self, id=wx.ID_ANY,
  212. label=_("Create custom PROJ.4 parameters "
  213. "string for coordinate system"))
  214. self.radio5 = wx.RadioButton(parent=self, id=wx.ID_ANY,
  215. label=_("Use arbitrary non-earth "
  216. "coordinate system (XY)"))
  217. # layout
  218. self.sizer.AddGrowableCol(1)
  219. self.sizer.Add(item=self.radio1,
  220. flag=wx.ALIGN_LEFT, pos=(1, 1))
  221. self.sizer.Add(item=self.radio2,
  222. flag=wx.ALIGN_LEFT, pos=(2, 1))
  223. self.sizer.Add(item=self.radio3,
  224. flag=wx.ALIGN_LEFT, pos=(3, 1))
  225. self.sizer.Add(item=self.radio4,
  226. flag=wx.ALIGN_LEFT, pos=(4, 1))
  227. self.sizer.Add(item=self.radio5,
  228. flag=wx.ALIGN_LEFT, pos=(5, 1))
  229. # bindings
  230. self.Bind(wx.EVT_RADIOBUTTON, self.SetVal, id=self.radio1.GetId())
  231. self.Bind(wx.EVT_RADIOBUTTON, self.SetVal, id=self.radio2.GetId())
  232. self.Bind(wx.EVT_RADIOBUTTON, self.SetVal, id=self.radio3.GetId())
  233. self.Bind(wx.EVT_RADIOBUTTON, self.SetVal, id=self.radio4.GetId())
  234. self.Bind(wx.EVT_RADIOBUTTON, self.SetVal, id=self.radio5.GetId())
  235. self.Bind(wiz.EVT_WIZARD_PAGE_CHANGED, self.OnEnterPage)
  236. # do page layout
  237. # self.DoLayout()
  238. def OnEnterPage(self, event):
  239. global coordsys
  240. if event.GetDirection() and not coordsys:
  241. coordsys = "proj"
  242. self.SetNext(self.parent.projpage)
  243. self.parent.sumpage.SetPrev(self.parent.datumpage)
  244. if not wx.FindWindowById(wx.ID_FORWARD).IsEnabled():
  245. wx.FindWindowById(wx.ID_FORWARD).Enable()
  246. def SetVal(self, event):
  247. """Choose method"""
  248. global coordsys
  249. if event.GetId() == self.radio1.GetId():
  250. coordsys = "proj"
  251. self.SetNext(self.parent.projpage)
  252. self.parent.sumpage.SetPrev(self.parent.datumpage)
  253. elif event.GetId() == self.radio2.GetId():
  254. coordsys = "epsg"
  255. self.SetNext(self.parent.epsgpage)
  256. self.parent.sumpage.SetPrev(self.parent.epsgpage)
  257. elif event.GetId() == self.radio3.GetId():
  258. coordsys = "file"
  259. self.SetNext(self.parent.filepage)
  260. self.parent.sumpage.SetPrev(self.parent.filepage)
  261. elif event.GetId() == self.radio4.GetId():
  262. coordsys = "custom"
  263. self.SetNext(self.parent.custompage)
  264. self.parent.sumpage.SetPrev(self.parent.custompage)
  265. elif event.GetId() == self.radio5.GetId():
  266. coordsys = "xy"
  267. self.SetNext(self.parent.sumpage)
  268. self.parent.sumpage.SetPrev(self.parent.csystemspage)
  269. class ProjectionsPage(TitledPage):
  270. """
  271. Wizard page for selecting projection (select coordinate system option)
  272. """
  273. def __init__(self, wizard, parent):
  274. TitledPage.__init__(self, wizard, _("Choose projection"))
  275. self.parent = parent
  276. self.proj = ''
  277. self.projdesc = ''
  278. # text input
  279. self.tproj = self.MakeTextCtrl("", size=(200,-1))
  280. # search box
  281. self.searchb = wx.SearchCtrl(self, size=(200,-1),
  282. style=wx.TE_PROCESS_ENTER)
  283. # projection list
  284. self.projlist = ItemList(self, data=self.parent.projections.items(),
  285. columns=[_('Code'), _('Description')])
  286. # layout
  287. self.sizer.AddGrowableCol(3)
  288. self.sizer.Add(item=self.MakeLabel(_("Projection code:")),
  289. flag=wx.ALIGN_LEFT |
  290. wx.ALIGN_CENTER_VERTICAL |
  291. wx.ALL, border=5, pos=(1, 1))
  292. self.sizer.Add(item=self.tproj,
  293. flag=wx.ALIGN_RIGHT | wx.EXPAND | wx.ALL,
  294. border=5, pos=(1, 2))
  295. self.sizer.Add(item=self.MakeLabel(_("Search in description:")),
  296. flag=wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL | wx.ALL,
  297. border=5, pos=(2, 1))
  298. self.sizer.Add(item=self.searchb,
  299. flag=wx.ALIGN_RIGHT | wx.EXPAND | wx.ALL,
  300. border=5, pos=(2, 2))
  301. self.sizer.AddGrowableRow(3)
  302. self.sizer.Add(item=self.projlist,
  303. flag=wx.EXPAND |
  304. wx.ALIGN_LEFT |
  305. wx.ALL, border=5, pos=(3, 1), span=(1, 3))
  306. # events
  307. self.tproj.Bind(wx.EVT_TEXT, self.OnText)
  308. self.tproj.Bind(wx.EVT_TEXT_ENTER, self.OnText)
  309. self.searchb.Bind(wx.EVT_TEXT_ENTER, self.OnSearch)
  310. self.projlist.Bind(wx.EVT_LIST_ITEM_SELECTED, self.OnItemSelected)
  311. self.Bind(wiz.EVT_WIZARD_PAGE_CHANGING, self.OnPageChanging)
  312. self.Bind(wiz.EVT_WIZARD_PAGE_CHANGED, self.OnEnterPage)
  313. # do layout
  314. # self.Layout()
  315. def OnPageChanging(self,event):
  316. if event.GetDirection() and self.proj not in self.parent.projections:
  317. event.Veto()
  318. if self.proj == 'utm':
  319. self.parent.projtypepage.text_utm.SetEditable(True)
  320. self.parent.projtypepage.hemischoices = ['north','south']
  321. else:
  322. self.parent.projtypepage.text_utm.SetValue('')
  323. self.parent.projtypepage.text_utm.SetEditable(False)
  324. self.parent.projtypepage.hemischoices = []
  325. def OnText(self, event):
  326. """Projection name changed"""
  327. self.proj = event.GetString()
  328. nextButton = wx.FindWindowById(wx.ID_FORWARD)
  329. if len(self.proj) == 0 and nextButton.IsEnabled():
  330. nextButton.Enable(False)
  331. if self.proj in self.parent.projections:
  332. self.projdesc = self.parent.projections[self.proj]
  333. if not nextButton.IsEnabled():
  334. nextButton.Enable()
  335. def OnEnterPage(self, event):
  336. if len(self.proj) == 0:
  337. # disable 'next' button by default
  338. wx.FindWindowById(wx.ID_FORWARD).Enable(False)
  339. else:
  340. wx.FindWindowById(wx.ID_FORWARD).Enable(True)
  341. event.Skip()
  342. def OnSearch(self, event):
  343. """Search projection by desc"""
  344. str = event.GetString()
  345. try:
  346. self.proj, self.projdesc = self.projlist.Search(index=1, str=event.GetString())
  347. except:
  348. self.proj = self.projdesc = ''
  349. self.tproj.SetValue(self.proj)
  350. event.Skip()
  351. def OnItemSelected(self, event):
  352. """Projection selected"""
  353. index = event.m_itemIndex
  354. # set values
  355. self.proj = self.projlist.GetItem(index, 0).GetText()
  356. self.projdesc = self.projlist.GetItem(index, 0).GetText()
  357. self.tproj.SetValue(self.proj)
  358. class ItemList(wx.ListCtrl,
  359. listmix.ListCtrlAutoWidthMixin,
  360. listmix.ColumnSorterMixin):
  361. """Generic list (for projections, ellipsoids, etc.)"""
  362. def __init__(self, parent, columns, data=None):
  363. wx.ListCtrl.__init__(self, parent=parent, id=wx.ID_ANY,
  364. style=wx.LC_REPORT |
  365. wx.LC_VIRTUAL |
  366. wx.LC_HRULES |
  367. wx.LC_VRULES |
  368. wx.LC_SINGLE_SEL |
  369. wx.LC_SORT_ASCENDING, size=(400, 100))
  370. # original data or None
  371. self.sourceData = data
  372. #
  373. # insert columns
  374. #
  375. i = 0
  376. for column in columns:
  377. self.InsertColumn(i, column)
  378. i += 1
  379. if self.sourceData:
  380. self.Populate()
  381. else:
  382. for i in range(self.GetColumnCount()):
  383. self.SetColumnWidth(i, wx.LIST_AUTOSIZE_USEHEADER)
  384. #
  385. # listmix
  386. #
  387. listmix.ListCtrlAutoWidthMixin.__init__(self)
  388. listmix.ColumnSorterMixin.__init__(self, self.GetColumnCount())
  389. #
  390. # add some attributes
  391. #
  392. self.attr1 = wx.ListItemAttr()
  393. self.attr1.SetBackgroundColour(wx.Colour(238,238,238))
  394. self.attr2 = wx.ListItemAttr()
  395. self.attr2.SetBackgroundColour("white")
  396. self.il = wx.ImageList(16, 16)
  397. self.sm_up = self.il.Add(wx.ArtProvider_GetBitmap(wx.ART_GO_UP, wx.ART_TOOLBAR,
  398. (16,16)))
  399. self.sm_dn = self.il.Add(wx.ArtProvider_GetBitmap(wx.ART_GO_DOWN, wx.ART_TOOLBAR,
  400. (16,16)))
  401. self.SetImageList(self.il, wx.IMAGE_LIST_SMALL)
  402. #
  403. # sort by first column
  404. #
  405. if self.sourceData:
  406. self.SortListItems(col=0, ascending=True)
  407. #
  408. # bindings
  409. #
  410. self.Bind(wx.EVT_LIST_COL_CLICK, self.OnColumnClick)
  411. def Populate(self, data=None, update=False):
  412. """Populate list"""
  413. self.itemDataMap = {}
  414. self.itemIndexMap = []
  415. if data is None:
  416. data = self.sourceData
  417. elif update:
  418. self.sourceData = data
  419. try:
  420. data.sort()
  421. self.DeleteAllItems()
  422. row = 0
  423. for value in data:
  424. # index = self.InsertStringItem(sys.maxint, str(value[0]))
  425. self.itemDataMap[row] = [value[0]]
  426. for i in range(1, len(value)):
  427. # try:
  428. # self.SetStringItem(index, i, str(value[i]))
  429. # except:
  430. # self.SetStringItem(index, i, unicode(str(value[i]), 'latin1'))
  431. self.itemDataMap[row].append(value[i])
  432. # self.SetItemData(index, row)
  433. self.itemIndexMap.append(row)
  434. row += 1
  435. self.SetItemCount(row)
  436. # set column width
  437. # for i in range(self.GetColumnCount()):
  438. # self.SetColumnWidth(i, wx.LIST_AUTOSIZE)
  439. # for i in range(self.GetColumnCount()):
  440. # if self.GetColumnWidth(i) < 80:
  441. # self.SetColumnWidth(i, 80)
  442. self.SetColumnWidth(0, 80)
  443. self.SetColumnWidth(1, 300)
  444. self.SendSizeEvent()
  445. except StandardError, e:
  446. wx.MessageBox(parent=self,
  447. message=_("Unable to read list: %s") % e,
  448. caption=_("Error"), style=wx.OK | wx.ICON_ERROR)
  449. def OnColumnClick(self, event):
  450. """Sort by column"""
  451. self._col = event.GetColumn()
  452. # remove duplicated arrow symbol from column header
  453. # FIXME: should be done automatically
  454. info = wx.ListItem()
  455. info.m_mask = wx.LIST_MASK_TEXT | wx.LIST_MASK_IMAGE
  456. info.m_image = -1
  457. for column in range(self.GetColumnCount()):
  458. info.m_text = self.GetColumn(column).GetText()
  459. self.SetColumn(column, info)
  460. event.Skip()
  461. def GetSortImages(self):
  462. """Used by the ColumnSorterMixin, see wx/lib/mixins/listctrl.py"""
  463. return (self.sm_dn, self.sm_up)
  464. def OnGetItemText(self, item, col):
  465. """Get item text"""
  466. index = self.itemIndexMap[item]
  467. s = str(self.itemDataMap[index][col])
  468. return s
  469. def OnGetItemAttr(self, item):
  470. """Get item attributes"""
  471. index = self.itemIndexMap[item]
  472. if ( index % 2) == 0:
  473. return self.attr2
  474. else:
  475. return self.attr1
  476. def SortItems(self, sorter=cmp):
  477. """Sort items"""
  478. items = list(self.itemDataMap.keys())
  479. items.sort(self.Sorter)
  480. self.itemIndexMap = items
  481. # redraw the list
  482. self.Refresh()
  483. def Sorter(self, key1, key2):
  484. colName = self.GetColumn(self._col).GetText()
  485. ascending = self._colSortFlag[self._col]
  486. # convert always string
  487. item1 = self.itemDataMap[key1][self._col]
  488. item2 = self.itemDataMap[key2][self._col]
  489. if type(item1) == type('') or type(item2) == type(''):
  490. cmpVal = locale.strcoll(str(item1), str(item2))
  491. else:
  492. cmpVal = cmp(item1, item2)
  493. # If the items are equal then pick something else to make the sort value unique
  494. if cmpVal == 0:
  495. cmpVal = apply(cmp, self.GetSecondarySortValues(self._col, key1, key2))
  496. if ascending:
  497. return cmpVal
  498. else:
  499. return -cmpVal
  500. def GetListCtrl(self):
  501. """Used by listmix.ColumnSorterMixin"""
  502. return self
  503. def Search (self, index, str):
  504. """Search projection by description
  505. Return first found item or None
  506. """
  507. if str == '':
  508. self.Populate(self.sourceData)
  509. return None
  510. data = []
  511. for i in range(len(self.sourceData)):
  512. value = self.sourceData[i][index]
  513. if str.lower() in value.lower():
  514. data.append(self.sourceData[i])
  515. self.Populate(data)
  516. if len(data) > 0:
  517. return data[0]
  518. else:
  519. return None
  520. class ProjTypePage(TitledPage):
  521. """
  522. Wizard page for selecting method of setting coordinate system parameters
  523. (select coordinate system option)
  524. """
  525. def __init__(self, wizard, parent):
  526. TitledPage.__init__(self, wizard, _("Choose method of specifying georeferencing parameters"))
  527. global coordsys
  528. self.utmzone = ''
  529. self.utmhemisphere = ''
  530. self.hemischoices = ["north","south"]
  531. self.parent = parent
  532. self.radio1 = wx.RadioButton(parent=self, id=wx.ID_ANY, label=_("Select datum with associated ellipsoid"),
  533. style = wx.RB_GROUP)
  534. self.radio2 = wx.RadioButton(parent=self, id=wx.ID_ANY,
  535. label=_("Select ellipsoid"))
  536. self.title_utm = self.MakeLabel(_("Set zone for UTM projection:"))
  537. self.text_utm = self.MakeTextCtrl(size=(100,-1))
  538. self.label_utm = self.MakeLabel(_("Zone:"))
  539. self.hemisphere = wx.Choice(parent=self, id=wx.ID_ANY, size=(100, -1),
  540. choices=self.hemischoices)
  541. self.label_hemisphere = self.MakeLabel(_("Hemisphere for zone:"))
  542. # layout
  543. self.sizer.AddGrowableCol(2)
  544. self.sizer.Add(item=self.radio1,
  545. flag=wx.ALIGN_LEFT, pos=(1, 1), span=(1, 2))
  546. self.sizer.Add(item=self.radio2,
  547. flag=wx.ALIGN_LEFT, pos=(2, 1), span=(1, 2))
  548. self.sizer.Add(item=self.title_utm,
  549. flag=wx.ALIGN_LEFT | wx.ALL,
  550. border=5, pos=(4, 1), span=(1, 2))
  551. self.sizer.Add(item=self.label_utm,
  552. flag=wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL | wx.ALL,
  553. border=5, pos=(5, 1))
  554. self.sizer.Add(item=self.text_utm,
  555. flag=wx.ALIGN_LEFT | wx.ALL, border=5,
  556. pos=(5, 2))
  557. self.sizer.Add(item=self.label_hemisphere,
  558. flag=wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL | wx.ALL,
  559. border=5, pos=(6, 1))
  560. self.sizer.Add(item=self.hemisphere,
  561. flag=wx.ALIGN_LEFT|wx.ALL,
  562. border=5, pos=(6, 2))
  563. self.title_utm.Hide()
  564. self.text_utm.Hide()
  565. self.label_utm.Hide()
  566. self.hemisphere.Hide()
  567. self.label_hemisphere.Hide()
  568. # bindings
  569. self.Bind(wx.EVT_RADIOBUTTON, self.SetVal, id=self.radio1.GetId())
  570. self.Bind(wx.EVT_RADIOBUTTON, self.SetVal, id=self.radio2.GetId())
  571. self.Bind(wiz.EVT_WIZARD_PAGE_CHANGING, self.OnPageChange)
  572. self.Bind(wiz.EVT_WIZARD_PAGE_CHANGED, self.OnEnterPage)
  573. # do page layout
  574. # self.DoLayout()
  575. def OnPageChange(self,event=None):
  576. if event.GetDirection() and self.parent.projpage.proj == 'utm' and self.utmzone == '':
  577. wx.MessageBox('You must set a zone for a UTM projection')
  578. event.Veto()
  579. self.title_utm.Hide()
  580. self.text_utm.Hide()
  581. self.label_utm.Hide()
  582. self.hemisphere.Hide()
  583. self.label_hemisphere.Hide()
  584. def OnEnterPage(self,event):
  585. if self.parent.projpage.proj == 'utm':
  586. self.title_utm.Show()
  587. self.text_utm.Show()
  588. self.label_utm.Show()
  589. self.hemisphere.Show()
  590. self.label_hemisphere.Show()
  591. self.Bind(wx.EVT_CHOICE, self.OnHemisphere, self.hemisphere)
  592. self.Bind(wx.EVT_TEXT, self.GetUTM, self.text_utm)
  593. if not wx.FindWindowById(wx.ID_FORWARD).IsEnabled():
  594. wx.FindWindowById(wx.ID_FORWARD).Enable()
  595. event.Skip()
  596. def SetVal(self, event):
  597. global coordsys
  598. if event.GetId() == self.radio1.GetId():
  599. self.SetNext(self.parent.datumpage)
  600. self.parent.sumpage.SetPrev(self.parent.datumpage)
  601. elif event.GetId() == self.radio2.GetId():
  602. self.SetNext(self.parent.ellipsepage)
  603. self.parent.sumpage.SetPrev(self.parent.ellipsepage)
  604. def GetUTM(self, event):
  605. self.utmzone = event.GetString()
  606. def OnHemisphere(self, event):
  607. self.utmhemisphere = event.GetString()
  608. class DatumPage(TitledPage):
  609. """
  610. Wizard page for selecting datum (with associated ellipsoid)
  611. and datum transformation parameters (select coordinate system option)
  612. """
  613. def __init__(self, wizard, parent):
  614. TitledPage.__init__(self, wizard, _("Specify geodetic datum"))
  615. self.parent = parent
  616. self.datum = ''
  617. self.datumdesc = ''
  618. self.ellipsoid = ''
  619. self.datumparams = ''
  620. self.transform = ''
  621. self.transregion = ''
  622. self.transparams = ''
  623. self.hastransform = False
  624. self.proj4params = ''
  625. # text input
  626. self.tdatum = self.MakeTextCtrl("", size=(200,-1))
  627. self.ttrans = self.MakeTextCtrl("", size=(200,-1))
  628. # search box
  629. self.searchb = wx.SearchCtrl(self, size=(200,-1),
  630. style=wx.TE_PROCESS_ENTER)
  631. # create list control for datum/elipsoid list
  632. data = []
  633. for key in self.parent.datums.keys():
  634. data.append([key, self.parent.datums[key][0], self.parent.datums[key][1]])
  635. self.datumlist = ItemList(self,
  636. data=data,
  637. columns=[_('Code'), _('Description'), _('Ellipsoid')])
  638. # create list control for datum transformation parameters list
  639. data = []
  640. for key in self.parent.transforms.keys():
  641. data.append([key, self.parent.transforms[key][0], self.parent.transforms[key][1]])
  642. self.transformlist = ItemList(self,
  643. data=None,
  644. columns=[_('Code'), _('Datum'), _('Description')])
  645. self.transformlist.sourceData = data
  646. # layout
  647. self.sizer.AddGrowableCol(4)
  648. self.sizer.Add(item=self.MakeLabel(_("Datum code:")),
  649. flag=wx.ALIGN_LEFT |
  650. wx.ALIGN_CENTER_VERTICAL |
  651. wx.ALL, border=5, pos=(1, 1))
  652. self.sizer.Add(item=self.tdatum,
  653. flag=wx.ALIGN_LEFT |
  654. wx.ALIGN_CENTER_VERTICAL |
  655. wx.ALL, border=5, pos=(1, 2))
  656. self.sizer.Add(item=self.MakeLabel(_("Search in description:")),
  657. flag=wx.ALIGN_LEFT |
  658. wx.ALIGN_CENTER_VERTICAL |
  659. wx.ALL, border=5, pos=(2, 1))
  660. self.sizer.Add(item=self.searchb,
  661. flag=wx.ALIGN_LEFT |
  662. wx.ALIGN_CENTER_VERTICAL |
  663. wx.ALL, border=5, pos=(2, 2))
  664. self.sizer.AddGrowableRow(3)
  665. self.sizer.Add(item=self.datumlist,
  666. flag=wx.EXPAND |
  667. wx.ALIGN_LEFT |
  668. wx.ALL, border=5, pos=(3, 1), span=(1, 4))
  669. self.sizer.Add(item=self.MakeLabel(_("Transformation parameters:")),
  670. flag=wx.ALIGN_RIGHT |
  671. wx.ALIGN_CENTER_VERTICAL |
  672. wx.ALL, border=5, pos=(5, 1))
  673. self.sizer.Add(item=self.ttrans,
  674. flag=wx.ALIGN_LEFT |
  675. wx.ALIGN_CENTER_VERTICAL |
  676. wx.ALL, border=5, pos=(5, 2))
  677. self.sizer.Add(item=self.transformlist,
  678. flag=wx.EXPAND |
  679. wx.ALIGN_LEFT |
  680. wx.ALL, border=5, pos=(6, 1), span=(1, 4))
  681. # events
  682. self.datumlist.Bind(wx.EVT_LIST_ITEM_SELECTED, self.OnDatumSelected)
  683. self.transformlist.Bind(wx.EVT_LIST_ITEM_SELECTED, self.OnTransformSelected)
  684. self.searchb.Bind(wx.EVT_TEXT_ENTER, self.OnDSearch)
  685. self.tdatum.Bind(wx.EVT_TEXT, self.OnDText)
  686. self.tdatum.Bind(wx.EVT_TEXT_ENTER, self.OnDText)
  687. self.ttrans.Bind(wx.EVT_TEXT, self.OnTText)
  688. self.ttrans.Bind(wx.EVT_TEXT_ENTER, self.OnTText)
  689. self.Bind(wiz.EVT_WIZARD_PAGE_CHANGING, self.OnPageChanging)
  690. self.Bind(wiz.EVT_WIZARD_PAGE_CHANGED, self.OnEnterPage)
  691. # do page layout
  692. # self.DoLayout()
  693. def OnPageChanging(self, event):
  694. self.proj4params = ''
  695. if event.GetDirection() and self.datum not in self.parent.datums:
  696. event.Veto()
  697. if self.hastransform == True and self.transform == '':
  698. event.Veto()
  699. self.GetNext().SetPrev(self)
  700. self.parent.ellipsepage.ellipseparams = self.parent.ellipsoids[self.ellipsoid][1]
  701. def OnEnterPage(self,event):
  702. if len(self.datum) == 0 or \
  703. (self.hastransform == True and self.transform == ''):
  704. # disable 'next' button by default
  705. wx.FindWindowById(wx.ID_FORWARD).Enable(False)
  706. else:
  707. wx.FindWindowById(wx.ID_FORWARD).Enable(True)
  708. event.Skip()
  709. def OnDText(self, event):
  710. self.datum = event.GetString()
  711. self.transformlist.Search(index=1, str=self.datum)
  712. if self.transformlist.GetItemCount() > 0:
  713. self.hastransform = True
  714. else:
  715. self.hastransform = False
  716. nextButton = wx.FindWindowById(wx.ID_FORWARD)
  717. if len(self.datum) == 0 and nextButton.IsEnabled():
  718. nextButton.Enable(False)
  719. elif self.datum in self.parent.datums:
  720. self.datumdesc = self.parent.datums[self.datum][0]
  721. self.ellipsoid = self.parent.datums[self.datum][1]
  722. self.datumparams = self.parent.datums[self.datum][2]
  723. if self.hastransform == False or \
  724. (self.hastransform == True and self.transform != ''):
  725. if not nextButton.IsEnabled():
  726. nextButton.Enable(True)
  727. else:
  728. if nextButton.IsEnabled():
  729. nextButton.Enable(False)
  730. event.Skip()
  731. def OnTText(self, event):
  732. if self.hastransform == False:
  733. event.Skip()
  734. return
  735. self.transform = event.GetString()
  736. nextButton = wx.FindWindowById(wx.ID_FORWARD)
  737. if len(self.transform) == 0 and nextButton.IsEnabled():
  738. nextButton.Enable(False)
  739. elif self.transform in self.parent.transforms:
  740. self.transdatum = self.parent.transforms[self.transform][0]
  741. self.transregion = self.parent.transforms[self.transform][1]
  742. self.transparams = self.parent.transforms[self.transform][2]
  743. if not nextButton.IsEnabled():
  744. nextButton.Enable()
  745. def OnDSearch(self, event):
  746. str = self.searchb.GetValue()
  747. try:
  748. self.datum, self.datumdesc, self.ellipsoid = self.datumlist.Search(index=1, str=str)
  749. self.transformlist.Search(index=1, str=self.datum)
  750. except:
  751. self.datum = self.datumdesc = self.ellipsoid = ''
  752. if str == '' or self.datum == '':
  753. self.transformlist.DeleteAllItems()
  754. self.transformlist.Refresh()
  755. self.tdatum.SetValue(self.datum)
  756. event.Skip()
  757. def OnTransformSelected(self,event):
  758. index = event.m_itemIndex
  759. item = event.GetItem()
  760. self.transform = self.transformlist.GetItem(index, 0).GetText()
  761. self.transdatum = self.parent.transforms[self.transform][0]
  762. self.transregion = self.parent.transforms[self.transform][1]
  763. self.transparams = self.parent.transforms[self.transform][2]
  764. self.ttrans.SetValue(str(self.transform))
  765. def OnDatumSelected(self,event):
  766. index = event.m_itemIndex
  767. item = event.GetItem()
  768. self.datum = self.datumlist.GetItem(index, 0).GetText()
  769. self.datumdesc = self.parent.datums[self.datum][0]
  770. self.ellipsoid = self.parent.datums[self.datum][1]
  771. self.datumparams = self.parent.datums[self.datum][2]
  772. self.tdatum.SetValue(self.datum)
  773. event.Skip()
  774. class EllipsePage(TitledPage):
  775. """
  776. Wizard page for selecting ellipsoid (select coordinate system option)
  777. """
  778. def __init__(self, wizard, parent):
  779. TitledPage.__init__(self, wizard, _("Specify ellipsoid"))
  780. self.parent = parent
  781. self.ellipse = ''
  782. self.ellipsedesc = ''
  783. self.ellipseparams = ''
  784. self.proj4params = ''
  785. # text input
  786. self.tellipse = self.MakeTextCtrl("", size=(200,-1))
  787. # search box
  788. self.searchb = wx.SearchCtrl(self, size=(200,-1),
  789. style=wx.TE_PROCESS_ENTER)
  790. # create list control for ellipse list
  791. data = []
  792. # extract code, desc
  793. for key in self.parent.ellipsoids.keys():
  794. data.append([key, self.parent.ellipsoids[key][0]])
  795. self.ellipselist = ItemList(self, data=data,
  796. columns=[_('Code'), _('Description')])
  797. # layout
  798. self.sizer.AddGrowableCol(4)
  799. self.sizer.Add(item=self.MakeLabel(_("Ellipsoid code:")),
  800. flag=wx.ALIGN_RIGHT |
  801. wx.ALIGN_CENTER_VERTICAL |
  802. wx.ALL, border=5, pos=(1, 1))
  803. self.sizer.Add(item=self.tellipse,
  804. flag=wx.ALIGN_LEFT |
  805. wx.ALIGN_CENTER_VERTICAL |
  806. wx.ALL, border=5, pos=(1, 2))
  807. self.sizer.Add(item=self.MakeLabel(_("Search in description:")),
  808. flag=wx.ALIGN_RIGHT |
  809. wx.ALIGN_CENTER_VERTICAL |
  810. wx.ALL, border=5, pos=(2, 1))
  811. self.sizer.Add(item=self.searchb,
  812. flag=wx.ALIGN_LEFT |
  813. wx.ALIGN_CENTER_VERTICAL |
  814. wx.ALL, border=5, pos=(2, 2))
  815. self.sizer.AddGrowableRow(3)
  816. self.sizer.Add(item=self.ellipselist,
  817. flag=wx.EXPAND |
  818. wx.ALIGN_LEFT |
  819. wx.ALL, border=5, pos=(3, 1), span=(1, 4))
  820. # events
  821. self.ellipselist.Bind(wx.EVT_LIST_ITEM_SELECTED, self.OnItemSelected)
  822. self.tellipse.Bind(wx.EVT_TEXT, self.OnText)
  823. self.tellipse.Bind(wx.EVT_TEXT_ENTER, self.OnText)
  824. self.searchb.Bind(wx.EVT_TEXT_ENTER, self.OnSearch)
  825. self.Bind(wiz.EVT_WIZARD_PAGE_CHANGED, self.OnEnterPage)
  826. self.Bind(wiz.EVT_WIZARD_PAGE_CHANGING, self.OnPageChanging)
  827. # do page layout
  828. # self.DoLayout()
  829. def OnEnterPage(self,event):
  830. if len(self.ellipse) == 0:
  831. # disable 'next' button by default
  832. wx.FindWindowById(wx.ID_FORWARD).Enable(False)
  833. else:
  834. wx.FindWindowById(wx.ID_FORWARD).Enable(True)
  835. event.Skip()
  836. def OnPageChanging(self, event):
  837. if event.GetDirection() and self.ellipse not in self.parent.ellipsoids:
  838. event.Veto()
  839. self.proj4params = ''
  840. self.GetNext().SetPrev(self)
  841. self.parent.datumpage.datumparams = ''
  842. self.parent.datumpage.transparams = ''
  843. # self.GetNext().SetPrev(self) (???)
  844. def OnText(self, event):
  845. """Ellipspoid code changed"""
  846. self.ellipse = event.GetString()
  847. nextButton = wx.FindWindowById(wx.ID_FORWARD)
  848. if len(self.ellipse) == 0 and nextButton.IsEnabled():
  849. nextButton.Enable(False)
  850. self.ellipsedesc = ''
  851. self.ellipseparams = ''
  852. self.proj4params = ''
  853. elif self.ellipse in self.parent.ellipsoids:
  854. self.ellipsedesc = self.parent.ellipsoids[self.ellipse][0]
  855. self.ellipseparams = self.parent.ellipsoids[self.ellipse][1]
  856. if not nextButton.IsEnabled():
  857. nextButton.Enable()
  858. def OnSearch(self, event):
  859. """Search ellipsoid by desc"""
  860. str = event.GetString()
  861. try:
  862. self.ellipse, self.ellipsedesc = \
  863. self.ellipselist.Search(index=1, str=event.GetString())
  864. self.ellipseparams = self.parent.ellipsoids[self.ellipse][1]
  865. self.proj4params = self.parent.ellipsoids[self.ellipse][2]
  866. except:
  867. self.ellipse = self.ellipsedesc = ''
  868. self.ellipseparams = self.proj4params = ''
  869. self.tellipse.SetValue(self.ellipse)
  870. event.Skip()
  871. def OnItemSelected(self,event):
  872. index = event.m_itemIndex
  873. item = event.GetItem()
  874. self.ellipse = self.ellipselist.GetItem(index, 0).GetText()
  875. self.ellipsedesc = self.parent.ellipsoids[self.ellipse][0]
  876. self.ellipseparams = self.parent.ellipsoids[self.ellipse][1]
  877. self.tellipse.SetValue(self.ellipse)
  878. class GeoreferencedFilePage(TitledPage):
  879. """
  880. Wizard page for selecting georeferenced file to use
  881. for setting coordinate system parameters
  882. """
  883. def __init__(self, wizard, parent):
  884. TitledPage.__init__(self, wizard, _("Select georeferenced file"))
  885. self.georeffile = ''
  886. # create controls
  887. self.lfile= self.MakeLabel(_("Georeferenced file:"))
  888. self.tfile = self.MakeTextCtrl(size=(300,-1))
  889. self.bbrowse = self.MakeButton(_("Browse"))
  890. # do layout
  891. self.sizer.AddGrowableCol(3)
  892. self.sizer.Add(item=self.lfile, flag=wx.ALIGN_LEFT |
  893. wx.ALIGN_CENTRE_VERTICAL |
  894. wx.ALL, border=5, pos=(1, 1))
  895. self.sizer.Add(item=self.tfile, flag=wx.ALIGN_LEFT |
  896. wx.ALIGN_CENTRE_VERTICAL |
  897. wx.ALL, border=5, pos=(1, 2))
  898. self.sizer.Add(item=self.bbrowse, flag=wx.ALIGN_LEFT |
  899. wx.ALL, border=5, pos=(1, 3))
  900. self.bbrowse.Bind(wx.EVT_BUTTON, self.OnBrowse)
  901. self.tfile.Bind(wx.EVT_TEXT, self.OnText)
  902. self.Bind(wiz.EVT_WIZARD_PAGE_CHANGING, self.OnPageChanging)
  903. self.Bind(wiz.EVT_WIZARD_PAGE_CHANGED, self.OnEnterPage)
  904. # do page layout
  905. # self.DoLayout()
  906. def OnEnterPage(self, event):
  907. if len(self.georeffile) == 0:
  908. # disable 'next' button by default
  909. wx.FindWindowById(wx.ID_FORWARD).Enable(False)
  910. else:
  911. wx.FindWindowById(wx.ID_FORWARD).Enable(True)
  912. event.Skip()
  913. def OnPageChanging(self, event):
  914. if event.GetDirection() and self.georeffile == '':
  915. event.Veto()
  916. self.GetNext().SetPrev(self)
  917. event.Skip()
  918. def OnText(self, event):
  919. self.georeffile = event.GetString()
  920. nextButton = wx.FindWindowById(wx.ID_FORWARD)
  921. if len(self.georeffile) > 0 and os.path.isfile(self.georeffile):
  922. if not nextButton.IsEnabled():
  923. nextButton.Enable(True)
  924. else:
  925. if nextButton.IsEnabled():
  926. nextButton.Enable(False)
  927. event.Skip()
  928. def OnBrowse(self, event):
  929. """Choose file"""
  930. dlg = wx.FileDialog(self,
  931. _("Select georeferenced file"),
  932. os.getcwd(), "", "*.*", wx.OPEN)
  933. if dlg.ShowModal() == wx.ID_OK:
  934. path = dlg.GetPath()
  935. self.tfile.SetValue(path)
  936. dlg.Destroy()
  937. event.Skip()
  938. def OnCreate(self, event):
  939. pass
  940. class EPSGPage(TitledPage):
  941. """
  942. Wizard page for selecting EPSG code for
  943. setting coordinate system parameters
  944. """
  945. def __init__(self, wizard, parent):
  946. TitledPage.__init__(self, wizard, _("Choose EPSG Code"))
  947. self.parent = parent
  948. self.epsgCodeDict = {}
  949. self.epsgcode = None
  950. self.epsgdesc = ''
  951. self.epsgparams = ''
  952. # labels
  953. self.lfile= self.MakeLabel(_("Path to the EPSG-codes file:"),
  954. style=wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL)
  955. self.lcode= self.MakeLabel(_("EPSG code:"),
  956. style=wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL)
  957. self.lsearch = self.MakeLabel(_("Search in description:"),
  958. style=wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL)
  959. # text input
  960. epsgdir = os.path.join(os.environ["GRASS_PROJSHARE"], 'epsg')
  961. self.tfile = self.MakeTextCtrl(text=epsgdir, size=(200,-1))
  962. self.tcode = self.MakeTextCtrl(size=(200,-1))
  963. # buttons
  964. self.bbrowse = self.MakeButton(_("Browse"))
  965. self.bbcodes = self.MakeButton(_("Browse EPSG Codes"))
  966. # search box
  967. self.searchb = wx.SearchCtrl(self, size=(200,-1),
  968. style=wx.TE_PROCESS_ENTER)
  969. self.epsglist = ItemList(self, data=None,
  970. columns=[_('Code'), _('Description'), _('Parameters')])
  971. # layout
  972. self.sizer.AddGrowableCol(3)
  973. self.sizer.Add(item=self.lfile,
  974. flag=wx.ALIGN_LEFT |
  975. wx.ALIGN_CENTER_VERTICAL |
  976. wx.ALL, border=5, pos=(1, 1))
  977. self.sizer.Add(item=self.tfile,
  978. flag=wx.ALIGN_LEFT |
  979. wx.ALIGN_CENTER_VERTICAL |
  980. wx.ALL, border=5, pos=(1, 2))
  981. self.sizer.Add(item=self.bbrowse,
  982. flag=wx.ALIGN_LEFT |
  983. wx.ALIGN_CENTER_VERTICAL |
  984. wx.ALL, border=5, pos=(1, 3))
  985. self.sizer.Add(item=self.lcode,
  986. flag=wx.ALIGN_LEFT |
  987. wx.ALIGN_CENTER_VERTICAL |
  988. wx.ALL, border=5, pos=(2, 1))
  989. self.sizer.Add(item=self.tcode,
  990. flag=wx.ALIGN_LEFT |
  991. wx.ALIGN_CENTER_VERTICAL |
  992. wx.ALL, border=5, pos=(2, 2))
  993. self.sizer.Add(item=self.lsearch,
  994. flag=wx.ALIGN_LEFT |
  995. wx.ALIGN_CENTER_VERTICAL |
  996. wx.ALL, border=5, pos=(3, 1))
  997. self.sizer.Add(item=self.searchb,
  998. flag=wx.ALIGN_LEFT |
  999. wx.ALIGN_CENTER_VERTICAL |
  1000. wx.ALL, border=5, pos=(3, 2))
  1001. self.sizer.Add(item=self.bbcodes,
  1002. flag=wx.ALIGN_LEFT |
  1003. wx.ALIGN_CENTER_VERTICAL |
  1004. wx.ALL, border=5, pos=(3, 3))
  1005. self.sizer.AddGrowableRow(4)
  1006. self.sizer.Add(item=self.epsglist,
  1007. flag=wx.ALIGN_LEFT | wx.EXPAND, pos=(4, 1),
  1008. span=(1, 3))
  1009. # events
  1010. self.bbrowse.Bind(wx.EVT_BUTTON, self.OnBrowse)
  1011. self.bbcodes.Bind(wx.EVT_BUTTON, self.OnBrowseCodes)
  1012. self.tcode.Bind(wx.EVT_TEXT, self.OnText)
  1013. self.tcode.Bind(wx.EVT_TEXT_ENTER, self.OnText)
  1014. self.epsglist.Bind(wx.EVT_LIST_ITEM_SELECTED, self.OnItemSelected)
  1015. self.searchb.Bind(wx.EVT_TEXT_ENTER, self.OnSearch)
  1016. self.Bind(wiz.EVT_WIZARD_PAGE_CHANGING, self.OnPageChanging)
  1017. self.Bind(wiz.EVT_WIZARD_PAGE_CHANGED, self.OnEnterPage)
  1018. # do page layout
  1019. # self.DoLayout()
  1020. def OnEnterPage(self, event):
  1021. if not self.epsgcode:
  1022. # disable 'next' button by default
  1023. wx.FindWindowById(wx.ID_FORWARD).Enable(False)
  1024. else:
  1025. wx.FindWindowById(wx.ID_FORWARD).Enable(True)
  1026. # load default epsg database file
  1027. self.OnBrowseCodes(None)
  1028. event.Skip()
  1029. def OnPageChanging(self, event):
  1030. if event.GetDirection() and not self.epsgcode:
  1031. event.Veto()
  1032. self.GetNext().SetPrev(self)
  1033. def OnText(self, event):
  1034. self.epsgcode = event.GetString()
  1035. try:
  1036. self.epsgcode = int(self.epsgcode)
  1037. except:
  1038. self.epsgcode = None
  1039. nextButton = wx.FindWindowById(wx.ID_FORWARD)
  1040. if self.epsgcode and self.epsgcode in self.epsgCodeDict.keys():
  1041. self.epsgdesc = self.epsgCodeDict[self.epsgcode][0]
  1042. self.epsgparams = self.epsgCodeDict[self.epsgcode][1]
  1043. if not nextButton.IsEnabled():
  1044. nextButton.Enable(True)
  1045. else:
  1046. if nextButton.IsEnabled():
  1047. nextButton.Enable(False)
  1048. self.epsgdesc = self.epsgparams = ''
  1049. def OnSearch(self, event):
  1050. str = self.searchb.GetValue()
  1051. if self.epsglist.GetItemCount() == 0:
  1052. event.Skip()
  1053. return
  1054. try:
  1055. self.epsgcode = self.epsglist.Search(index=1, str=str)[0]
  1056. self.tcode.SetValue(str(self.epsgcode))
  1057. except:
  1058. self.epsgcode = None
  1059. self.tcode.SetValue('')
  1060. event.Skip()
  1061. def OnBrowse(self, event):
  1062. """Define path for EPSG code file"""
  1063. path = os.path.dirname(self.tfile.GetValue())
  1064. if not path:
  1065. path = os.getcwd()
  1066. dlg = wx.FileDialog(parent=self, message=_("Choose EPSG codes file"),
  1067. defaultDir=path, defaultFile="", wildcard="*", style=wx.OPEN)
  1068. if dlg.ShowModal() == wx.ID_OK:
  1069. path = dlg.GetPath()
  1070. self.tfile.SetValue(path)
  1071. self.OnBrowseCodes(None)
  1072. dlg.Destroy()
  1073. event.Skip()
  1074. def OnItemSelected(self, event):
  1075. """EPSG code selected from the list"""
  1076. index = event.m_itemIndex
  1077. item = event.GetItem()
  1078. self.epsgcode = int(self.epsglist.GetItem(index, 0).GetText())
  1079. self.epsgdesc = self.epsglist.GetItem(index, 1).GetText()
  1080. self.tcode.SetValue(str(self.epsgcode))
  1081. event.Skip()
  1082. def OnBrowseCodes(self, event, search=None):
  1083. """Browse EPSG codes"""
  1084. try:
  1085. data = []
  1086. self.epsgCodeDict = {}
  1087. f = open(self.tfile.GetValue(), "r")
  1088. i = 0
  1089. code = None
  1090. for line in f.readlines():
  1091. line = line.strip()
  1092. if line[0] == '#':
  1093. descr = line[1:].strip()
  1094. elif line[0] == '<':
  1095. code, params = line.split(" ", 1)
  1096. code = int(code.replace('<', '').replace('>', ''))
  1097. if code is not None:
  1098. data.append((code, descr, params))
  1099. self.epsgCodeDict[code] = (descr, params)
  1100. code = None
  1101. i += 1
  1102. f.close()
  1103. self.epsglist.Populate(data, update=True)
  1104. except StandardError, e:
  1105. wx.MessageBox(parent=self,
  1106. message=_("Unable to read EPGS codes: %s") % e,
  1107. caption=_("Error"), style=wx.OK | wx.ICON_ERROR | wx.CENTRE)
  1108. self.epsglist.Populate([], update=True)
  1109. class CustomPage(TitledPage):
  1110. """
  1111. Wizard page for entering custom PROJ.4 string
  1112. for setting coordinate system parameters
  1113. """
  1114. def __init__(self, wizard, parent):
  1115. TitledPage.__init__(self, wizard,
  1116. _("Choose method of specifying georeferencing parameters"))
  1117. global coordsys
  1118. self.customstring = ''
  1119. self.parent = parent
  1120. # widgets
  1121. self.text_proj4string = self.MakeTextCtrl(size=(400, 200),
  1122. style=wx.TE_MULTILINE)
  1123. self.label_proj4string = self.MakeLabel(_("Enter PROJ.4 parameters string:"))
  1124. # layout
  1125. self.sizer.AddGrowableCol(2)
  1126. self.sizer.Add(self.label_proj4string,
  1127. flag=wx.ALIGN_LEFT | wx.ALL,
  1128. border=5, pos=(1, 1))
  1129. self.sizer.AddGrowableRow(2)
  1130. self.sizer.Add(self.text_proj4string,
  1131. flag=wx.ALIGN_LEFT | wx.ALL | wx.EXPAND,
  1132. border=5, pos=(2, 1), span=(1, 2))
  1133. self.text_proj4string.Bind(wx.EVT_TEXT, self.GetProjstring)
  1134. self.Bind(wiz.EVT_WIZARD_PAGE_CHANGING, self.OnPageChanging)
  1135. self.Bind(wiz.EVT_WIZARD_PAGE_CHANGED, self.OnEnterPage)
  1136. # do page layout
  1137. # self.DoLayout()
  1138. def OnEnterPage(self, event):
  1139. if len(self.customstring) == 0:
  1140. # disable 'next' button by default
  1141. wx.FindWindowById(wx.ID_FORWARD).Enable(False)
  1142. else:
  1143. wx.FindWindowById(wx.ID_FORWARD).Enable(True)
  1144. event.Skip()
  1145. def OnPageChanging(self, event):
  1146. if event.GetDirection() and not self.customstring:
  1147. event.Veto()
  1148. self.GetNext().SetPrev(self)
  1149. def GetProjstring(self, event):
  1150. """Change proj string"""
  1151. # TODO: check PROJ.4 syntax
  1152. self.customstring = event.GetString()
  1153. nextButton = wx.FindWindowById(wx.ID_FORWARD)
  1154. if len(self.customstring) == 0:
  1155. if nextButton.IsEnabled():
  1156. nextButton.Enable(False)
  1157. else:
  1158. if not nextButton.IsEnabled():
  1159. nextButton.Enable()
  1160. class SummaryPage(TitledPage):
  1161. """
  1162. Shows summary result of choosing coordinate system parameters
  1163. prior to creating location
  1164. """
  1165. def __init__(self, wizard, parent):
  1166. TitledPage.__init__(self, wizard, _("Summary"))
  1167. self.parent = parent
  1168. # labels
  1169. self.ldatabase = self.MakeLabel("")
  1170. self.llocation = self.MakeLabel("")
  1171. self.lprojection = self.MakeLabel("")
  1172. self.lproj4string = self.MakeLabel("")
  1173. self.lproj4stringLabel = self.MakeLabel("")
  1174. self.lprojection.Wrap(400)
  1175. self.Bind(wiz.EVT_WIZARD_PAGE_CHANGED, self.OnEnterPage)
  1176. # self.Bind(wx.EVT_BUTTON, self.OnFinish, wx.ID_FINISH)
  1177. # do sub-page layout
  1178. self.__DoLayout()
  1179. def __DoLayout(self):
  1180. """Do page layout"""
  1181. self.sizer.AddGrowableCol(1)
  1182. self.sizer.Add(item=self.MakeLabel(_("GRASS Database:")),
  1183. flag=wx.ALIGN_LEFT | wx.ALL,
  1184. border=5, pos=(1, 0))
  1185. self.sizer.Add(item=self.ldatabase,
  1186. flag=wx.ALIGN_LEFT | wx.ALL,
  1187. border=5, pos=(1, 1))
  1188. self.sizer.Add(item=self.MakeLabel(_("Location Name:")),
  1189. flag=wx.ALIGN_LEFT | wx.ALL,
  1190. border=5, pos=(2, 0))
  1191. self.sizer.Add(item=self.llocation,
  1192. flag=wx.ALIGN_LEFT | wx.ALL,
  1193. border=5, pos=(2, 1))
  1194. self.sizer.Add(item=self.MakeLabel(_("Projection:")),
  1195. flag=wx.ALIGN_LEFT | wx.ALL,
  1196. border=5, pos=(3, 0))
  1197. self.sizer.Add(item=self.lprojection,
  1198. flag=wx.ALIGN_LEFT | wx.ALL,
  1199. border=5, pos=(3, 1))
  1200. self.sizer.Add(item=self.lproj4stringLabel,
  1201. flag=wx.ALIGN_LEFT | wx.ALL,
  1202. border=5, pos=(4, 0))
  1203. self.sizer.Add(item=self.lproj4string,
  1204. flag=wx.ALIGN_LEFT | wx.ALL,
  1205. border=5, pos=(4, 1))
  1206. self.sizer.Add(item=(10,20),
  1207. flag=wx.ALIGN_CENTER_HORIZONTAL | wx.ALL,
  1208. border=5, pos=(5, 0), span=(1, 2))
  1209. # self.sizer.AddGrowableRow(6)
  1210. #self.sizer.Add(item=self.MakeLabel(_("You can set the default extents "
  1211. # "and resolution after creating new location%s"
  1212. # "or you can set them during a working session.") % os.linesep,
  1213. # style=wx.ALIGN_CENTER),
  1214. # flag=wx.ALIGN_CENTRE | wx.ALL, border=5, pos=(6, 0),
  1215. # span=(1, 2))
  1216. def OnEnterPage(self,event):
  1217. """
  1218. Insert values into text controls for summary of location creation options
  1219. """
  1220. database = self.parent.startpage.grassdatabase
  1221. location = self.parent.startpage.location
  1222. global coordsys
  1223. if coordsys not in ['proj', 'epsg']:
  1224. self.lproj4stringLabel.Hide()
  1225. self.lproj4string.Hide()
  1226. self.lproj4stringLabel.SetLabel('')
  1227. self.lproj4string.SetLabel('')
  1228. else:
  1229. self.lproj4string.Show()
  1230. self.lproj4stringLabel.SetLabel(_("PROJ.4 definition:"))
  1231. if coordsys == 'proj':
  1232. self.lproj4string.SetLabel(self.parent.CreateProj4String())
  1233. else:
  1234. self.lproj4string.SetLabel(self.parent.epsgpage.epsgCodeDict[self.parent.epsgpage.epsgcode][1])
  1235. self.lproj4string.Wrap(400)
  1236. projection = self.parent.projpage.proj
  1237. projdesc = self.parent.projpage.projdesc
  1238. utmzone = self.parent.projtypepage.utmzone
  1239. utmhemisphere = self.parent.projtypepage.utmhemisphere
  1240. ellipse = self.parent.ellipsepage.ellipse
  1241. ellipsedesc = self.parent.ellipsepage.ellipsedesc
  1242. datum = self.parent.datumpage.datum
  1243. datumdesc = self.parent.datumpage.datumdesc
  1244. ellipsoid = self.parent.datumpage.ellipsoid
  1245. datumparams = self.parent.datumpage.datumparams
  1246. transform = self.parent.datumpage.transform
  1247. transregion = self.parent.datumpage.transregion
  1248. transparams = self.parent.datumpage.transparams
  1249. self.ldatabase.SetLabel(str(database))
  1250. self.llocation.SetLabel(str(location))
  1251. label = ''
  1252. if coordsys == 'epsg':
  1253. label = 'EPSG code %s (%s)' % (self.parent.epsgpage.epsgcode, self.parent.epsgpage.epsgdesc)
  1254. self.lprojection.SetLabel(label)
  1255. elif coordsys == 'file':
  1256. label = 'matches file %s' % self.parent.filepage.georeffile
  1257. self.lprojection.SetLabel(label)
  1258. elif coordsys == 'proj':
  1259. label = ('%s, %s%s' % (projdesc, datumdesc, ellipsedesc))
  1260. self.lprojection.SetLabel(label)
  1261. elif coordsys == 'xy':
  1262. label = ('XY coordinate system (not projected).')
  1263. self.lprojection.SetLabel(label)
  1264. elif coordsys == 'custom':
  1265. label = ('%s' % self.parent.custompage.customstring)
  1266. self.lprojection.SetLabel(label)
  1267. def OnFinish(self, event):
  1268. dlg = wx.MessageDialog(parent=self.wizard,
  1269. message=_("Do you want to create GRASS location <%s>?") % location,
  1270. caption=_("Create new location?"),
  1271. style=wx.YES_NO | wx.YES_DEFAULT | wx.ICON_QUESTION)
  1272. if dlg.ShowModal() == wx.ID_NO:
  1273. dlg.Destroy()
  1274. event.Veto()
  1275. else:
  1276. dlg.Destroy()
  1277. event.Skip()
  1278. class LocationWizard(wx.Object):
  1279. """
  1280. Start wizard here and finish wizard here
  1281. """
  1282. def __init__(self, parent, grassdatabase):
  1283. global coordsys
  1284. self.parent = parent
  1285. #
  1286. # define wizard image
  1287. #
  1288. # file = "loc_wizard.png"
  1289. file = "loc_wizard_qgis.png"
  1290. imagePath = os.path.join(globalvar.ETCWXDIR, "images", file)
  1291. wizbmp = wx.Image(imagePath, wx.BITMAP_TYPE_PNG)
  1292. # wizbmp.Rescale(250,600)
  1293. wizbmp = wizbmp.ConvertToBitmap()
  1294. #
  1295. # get georeferencing information from tables in $GISBASE/etc
  1296. #
  1297. self.__readData()
  1298. #
  1299. # define wizard pages
  1300. #
  1301. self.wizard = wiz.Wizard(parent, id=wx.ID_ANY, title=_("Define new GRASS Location"),
  1302. bitmap=wizbmp)
  1303. self.startpage = DatabasePage(self.wizard, self, grassdatabase)
  1304. self.csystemspage = CoordinateSystemPage(self.wizard, self)
  1305. self.projpage = ProjectionsPage(self.wizard, self)
  1306. self.datumpage = DatumPage(self.wizard, self)
  1307. self.projtypepage = ProjTypePage(self.wizard,self)
  1308. self.epsgpage = EPSGPage(self.wizard, self)
  1309. self.filepage = GeoreferencedFilePage(self.wizard, self)
  1310. self.ellipsepage = EllipsePage(self.wizard, self)
  1311. self.custompage = CustomPage(self.wizard, self)
  1312. self.sumpage = SummaryPage(self.wizard, self)
  1313. #
  1314. # set the initial order of the pages
  1315. # (should follow the epsg line)
  1316. #
  1317. self.startpage.SetNext(self.csystemspage)
  1318. self.csystemspage.SetPrev(self.startpage)
  1319. self.csystemspage.SetNext(self.sumpage)
  1320. self.projpage.SetPrev(self.csystemspage)
  1321. self.projpage.SetNext(self.projtypepage)
  1322. self.projtypepage.SetPrev(self.projpage)
  1323. self.projtypepage.SetNext(self.datumpage)
  1324. self.datumpage.SetPrev(self.projtypepage)
  1325. self.datumpage.SetNext(self.sumpage)
  1326. self.ellipsepage.SetPrev(self.projtypepage)
  1327. self.ellipsepage.SetNext(self.sumpage)
  1328. self.epsgpage.SetPrev(self.csystemspage)
  1329. self.epsgpage.SetNext(self.sumpage)
  1330. self.filepage.SetPrev(self.csystemspage)
  1331. self.filepage.SetNext(self.sumpage)
  1332. self.custompage.SetPrev(self.csystemspage)
  1333. self.custompage.SetNext(self.sumpage)
  1334. self.sumpage.SetPrev(self.csystemspage)
  1335. #
  1336. # do pages layout
  1337. #
  1338. self.startpage.DoLayout()
  1339. self.csystemspage.DoLayout()
  1340. self.projpage.DoLayout()
  1341. self.datumpage.DoLayout()
  1342. self.projtypepage.DoLayout()
  1343. self.epsgpage.DoLayout()
  1344. self.filepage.DoLayout()
  1345. self.ellipsepage.DoLayout()
  1346. self.custompage.DoLayout()
  1347. self.sumpage.DoLayout()
  1348. self.wizard.FitToPage(self.datumpage)
  1349. # new location created?
  1350. self.location = None
  1351. success = False
  1352. #
  1353. # run wizard...
  1354. #
  1355. if self.wizard.RunWizard(self.startpage):
  1356. success = self.OnWizFinished()
  1357. if success == True:
  1358. self.wizard.Destroy()
  1359. self.location = self.startpage.location
  1360. dlg = wx.MessageDialog(parent=self.parent,
  1361. message=_("Do you want to set the default "
  1362. "region extents and resolution now?"),
  1363. caption=_("Location <%s> created") % self.location,
  1364. style=wx.YES_NO | wx.YES_DEFAULT | wx.ICON_QUESTION)
  1365. dlg.CenterOnScreen()
  1366. if dlg.ShowModal() == wx.ID_YES:
  1367. dlg.Destroy()
  1368. defineRegion = RegionDef(self.parent, location=self.location)
  1369. defineRegion.Centre()
  1370. defineRegion.Show()
  1371. else:
  1372. dlg.Destroy()
  1373. elif success == False:
  1374. dlg = wx.MessageDialog(parent=self.wizard,
  1375. message="%s." % _("Unable to create new location"),
  1376. caption=_("Error"),
  1377. style=wx.OK | wx.ICON_ERROR | wx.CENTRE)
  1378. if dlg.ShowModal() == wx.ID_OK:
  1379. self.wizard.Destroy()
  1380. else: # None
  1381. pass
  1382. else:
  1383. win = wx.MessageBox(parent=self.parent,
  1384. message=_("Location wizard canceled. "
  1385. "Location not created."),
  1386. caption=_("Location wizard"))
  1387. def __readData(self):
  1388. """Get georeferencing information from tables in $GISBASE/etc"""
  1389. # read projection definitions
  1390. f = open(os.path.join(globalvar.ETCDIR, "projections"), "r")
  1391. self.projections = {}
  1392. for line in f.readlines():
  1393. line = line.expandtabs(1)
  1394. line = line.strip()
  1395. if line == '' or line[0] == "#":
  1396. continue
  1397. proj, projdesc = line.split(":", 1)
  1398. self.projections[proj.strip()] = projdesc.strip()
  1399. f.close()
  1400. # read datum definitions
  1401. f = open(os.path.join(globalvar.ETCDIR, "datum.table"), "r")
  1402. self.datums = {}
  1403. paramslist = []
  1404. for line in f.readlines():
  1405. line = line.expandtabs(1)
  1406. line = line.strip()
  1407. if line == '' or line[0] == "#":
  1408. continue
  1409. datum, info = line.split(" ", 1)
  1410. info = info.strip()
  1411. datumdesc, params = info.split(" ", 1)
  1412. datumdesc = datumdesc.strip('"')
  1413. paramlist = params.split()
  1414. ellipsoid = paramlist.pop(0)
  1415. self.datums[datum] = (datumdesc.replace('_', ' '), ellipsoid, paramlist)
  1416. f.close()
  1417. # read datum transforms parameters
  1418. f = open(os.path.join(globalvar.ETCDIR, "datumtransform.table"), "r")
  1419. self.transforms = {}
  1420. j = 1
  1421. for line in f.readlines():
  1422. if j < 10:
  1423. transcode = 'T0' + str(j)
  1424. else:
  1425. transcode = 'T' + str(j)
  1426. line = line.expandtabs(1)
  1427. line = line.strip()
  1428. if line == '' or line[0] == "#":
  1429. continue
  1430. datum, rest = line.split(" ", 1)
  1431. rest = rest.strip('" ')
  1432. params, rest = rest.split('"', 1)
  1433. params = params.strip()
  1434. rest = rest.strip('" ')
  1435. try:
  1436. region, info = rest.split('"', 1)
  1437. info = info.strip('" ')
  1438. info = region + ': ' + info
  1439. except:
  1440. info = rest
  1441. self.transforms[transcode] = (datum, info, params)
  1442. j += 1
  1443. f.close()
  1444. # read ellipsiod definitions
  1445. f = open(os.path.join(globalvar.ETCDIR, "ellipse.table"), "r")
  1446. self.ellipsoids = {}
  1447. for line in f.readlines():
  1448. line = line.expandtabs(1)
  1449. line = line.strip()
  1450. if line == '' or line[0] == "#":
  1451. continue
  1452. ellipse, rest = line.split(" ", 1)
  1453. rest = rest.strip('" ')
  1454. desc, params = rest.split('"', 1)
  1455. desc = desc.strip('" ')
  1456. paramslist = params.split()
  1457. self.ellipsoids[ellipse] = (desc, paramslist)
  1458. f.close()
  1459. def OnWizFinished(self):
  1460. database = self.startpage.grassdatabase
  1461. location = self.startpage.location
  1462. global coordsys
  1463. success = False
  1464. # location already exists?
  1465. if os.path.isdir(os.path.join(database,location)):
  1466. dlg = wx.MessageDialog(parent=self.wizard,
  1467. message="%s <%s>: %s" % \
  1468. (_("Unable to create new location"),
  1469. os.path.join(database, location),
  1470. _("Location already exists in GRASS Database.")),
  1471. caption=_("Error"),
  1472. style=wx.OK | wx.ICON_ERROR)
  1473. dlg.ShowModal()
  1474. dlg.Destroy()
  1475. return False
  1476. if coordsys == "xy":
  1477. success = self.XYCreate()
  1478. elif coordsys == "latlong":
  1479. rows = int(round((float(north) - float(south)) / float(resolution)))
  1480. cols = int(round((float(east) - float(west)) / float(resolution)))
  1481. cells = int(rows * cols)
  1482. success = self.LatlongCreate()
  1483. elif coordsys == "proj":
  1484. proj4string = self.CreateProj4String()
  1485. success = self.Proj4Create(proj4string)
  1486. elif coordsys == 'custom':
  1487. success = self.CustomCreate()
  1488. elif coordsys == "epsg":
  1489. success = self.EPSGCreate()
  1490. elif coordsys == "file":
  1491. success = self.FileCreate()
  1492. return success
  1493. def XYCreate(self):
  1494. """Create an XY location"""
  1495. database = self.startpage.grassdatabase
  1496. location = self.startpage.location
  1497. # create location directory and PERMANENT mapset
  1498. try:
  1499. os.mkdir(os.path.join(database, location))
  1500. os.mkdir(os.path.join(database, location, 'PERMANENT'))
  1501. # create DEFAULT_WIND and WIND files
  1502. regioninfo = ['proj: 0',
  1503. 'zone: 0',
  1504. 'north: 1',
  1505. 'south: 0',
  1506. 'east: 1',
  1507. 'west: 0',
  1508. 'cols: 1',
  1509. 'rows: 1',
  1510. 'e-w resol: 1',
  1511. 'n-s resol: 1',
  1512. 'top: 1',
  1513. 'bottom: 0',
  1514. 'cols3: 1',
  1515. 'rows3: 1',
  1516. 'depths: 1',
  1517. 'e-w resol3: 1',
  1518. 'n-s resol3: 1',
  1519. 't-b resol: 1']
  1520. defwind = open(os.path.join(database, location,
  1521. "PERMANENT", "DEFAULT_WIND"), 'w')
  1522. for param in regioninfo:
  1523. defwind.write(param + '%s' % os.linesep)
  1524. defwind.close()
  1525. shutil.copy(os.path.join(database, location, "PERMANENT", "DEFAULT_WIND"),
  1526. os.path.join(database, location, "PERMANENT", "WIND"))
  1527. # create MYNAME file
  1528. myname = open(os.path.join(database, location, "PERMANENT",
  1529. "MYNAME"), 'w')
  1530. myname.write('%s' % os.linesep)
  1531. myname.close()
  1532. return True
  1533. except OSError, e:
  1534. dlg = wx.MessageDialog(parent=self.wizard,
  1535. message="%s: %s" % (_("Unable to create new location"), e),
  1536. caption=_("Error"),
  1537. style=wx.OK | wx.ICON_ERROR)
  1538. dlg.ShowModal()
  1539. dlg.Destroy()
  1540. return False
  1541. def CreateProj4String(self):
  1542. """Constract PROJ.4 string"""
  1543. location = self.startpage.location
  1544. proj = self.projpage.proj
  1545. projdesc = self.projpage.projdesc
  1546. utmzone = self.projtypepage.utmzone
  1547. utmhemisphere = self.projtypepage.utmhemisphere
  1548. datum = self.datumpage.datum
  1549. if self.datumpage.datumdesc:
  1550. datumdesc = self.datumpage.datumdesc +' - ' + self.datumpage.ellipsoid
  1551. else:
  1552. datumdesc = ''
  1553. datumparams = self.datumpage.datumparams
  1554. transparams = self.datumpage.transparams
  1555. ellipse = self.ellipsepage.ellipse
  1556. ellipsedesc = self.ellipsepage.ellipsedesc
  1557. ellipseparams = self.ellipsepage.ellipseparams
  1558. #
  1559. # creating PROJ.4 string
  1560. #
  1561. if proj == 'll':
  1562. proj = 'longlat'
  1563. elif proj == 'utm':
  1564. proj4string = '+proj=%s +zone=%s' % (proj, utmzone)
  1565. if utmhemisphere == 'south':
  1566. proj4string += '+south'
  1567. else:
  1568. proj4string = '+proj=%s ' % (proj)
  1569. proj4params = ''
  1570. # set ellipsoid parameters
  1571. for item in ellipseparams:
  1572. if item[:4] == 'f=1/':
  1573. item = '+rf='+item[4:]
  1574. else:
  1575. item = '+'+item
  1576. proj4params = '%s %s' % (proj4params, item)
  1577. # set datum and transform parameters if relevant
  1578. if datumparams:
  1579. for item in datumparams:
  1580. proj4params = '%s +%s' % (proj4params,item)
  1581. if transparams:
  1582. proj4params = '%s +no_defs +%s' % (proj4params,transparams)
  1583. else:
  1584. proj4params = '%s +no_defs' % proj4params
  1585. else:
  1586. proj4params = '%s +no_defs' % proj4params
  1587. return '%s %s' % (proj4string, proj4params)
  1588. def Proj4Create(self, proj4string):
  1589. """
  1590. Create a new location for selected projection
  1591. """
  1592. # creating location from PROJ.4 string passed to g.proj
  1593. cmdlist = ['g.proj', '-c',
  1594. 'proj4=%s' % proj4string,
  1595. 'location=%s' % self.startpage.location]
  1596. p = gcmd.Command(cmdlist)
  1597. if p.returncode == 0:
  1598. return True
  1599. return False
  1600. def CustomCreate(self):
  1601. """Create a new location based on given proj4 string"""
  1602. proj4string = self.custompage.customstring
  1603. location = self.startpage.location
  1604. cmdlist = ['g.proj', '-c',
  1605. 'proj4=%s' % proj4string,
  1606. 'location=%s' % location]
  1607. p = gcmd.Command(cmdlist)
  1608. if p.returncode == 0:
  1609. return True
  1610. return False
  1611. def EPSGCreate(self):
  1612. """
  1613. Create a new location from an EPSG code.
  1614. """
  1615. epsgcode = self.epsgpage.epsgcode
  1616. epsgdesc = self.epsgpage.epsgdesc
  1617. location = self.startpage.location
  1618. cmdlist = []
  1619. # should not happend
  1620. if epsgcode == '':
  1621. wx.MessageBox(parent=self,
  1622. message="%s: %s" % (_("Unable to create new location"), _("EPSG code missing.")),
  1623. caption=_("Error"), style=wx.OK | wx.ICON_ERROR)
  1624. return False
  1625. # creating location
  1626. cmdlist = ['g.proj',
  1627. 'epsg=%s' % epsgcode,
  1628. 'datumtrans=-1']
  1629. p = gcmd.Command(cmdlist)
  1630. try:
  1631. dtoptions = p.ReadStdOutput()[0]
  1632. except:
  1633. dtoptions = None
  1634. if dtoptions != None:
  1635. dtrans = ''
  1636. # open a dialog to select datum transform number
  1637. dlg = wx.TextEntryDialog(self.wizard, dtoptions,
  1638. caption=_('Select datum transformation'),
  1639. defaultValue='1',
  1640. style=wx.TE_WORDWRAP | wx.MINIMIZE_BOX | wx.MAXIMIZE_BOX|
  1641. wx.RESIZE_BORDER |wx.VSCROLL |
  1642. wx.OK | wx.CANCEL)
  1643. if dlg.ShowModal() == wx.ID_CANCEL:
  1644. dlg.Destroy()
  1645. return False
  1646. else:
  1647. dtrans = dlg.GetValue()
  1648. if dtrans != '':
  1649. dlg.Destroy()
  1650. else:
  1651. wx.MessageBox(_('Datum transform is required.'))
  1652. return False
  1653. cmdlist = ['g.proj', '-c',
  1654. 'epsg=%s' % epsgcode,
  1655. 'location=%s' % location,
  1656. 'datumtrans=%s' % dtrans]
  1657. else:
  1658. cmdlist = ['g.proj','-c',
  1659. 'epsg=%s' % epsgcode,
  1660. 'location=%s' % location,
  1661. 'datumtrans=1']
  1662. p = gcmd.Command(cmdlist)
  1663. if p.returncode == 0:
  1664. return True
  1665. return False
  1666. def FileCreate(self):
  1667. """
  1668. Create a new location from a georeferenced file
  1669. """
  1670. georeffile = self.filepage.georeffile
  1671. location = self.startpage.location
  1672. cmdlist = []
  1673. # this should not happen
  1674. if not georeffile or not os.path.isfile(georeffile):
  1675. dlg = wx.MessageBox(parent=self.wizard,
  1676. message="%s: %s ('%s')" % \
  1677. (_("Unable to create new location"),
  1678. _("file not found"),
  1679. georeffile),
  1680. caption=("Error"), style=wx.OK | wx.ICON_ERROR)
  1681. return False
  1682. # creating location
  1683. cmdlist = ['g.proj', '-c',
  1684. 'georef=%s' % georeffile,
  1685. 'location=%s' % location]
  1686. p = gcmd.Command(cmdlist)
  1687. if p.returncode == 0:
  1688. return True
  1689. return False
  1690. class RegionDef(BaseClass, wx.Frame):
  1691. """
  1692. Page for setting default region extents and resolution
  1693. """
  1694. def __init__(self, parent, id=wx.ID_ANY,
  1695. title=_("Set default region extent and resolution"), location=None):
  1696. wx.Frame.__init__(self, parent, id, title, size=(650,300))
  1697. self.parent = parent
  1698. self.location = location
  1699. #
  1700. # values
  1701. #
  1702. # 2D
  1703. self.north = 1.0
  1704. self.south = 0.0
  1705. self.east = 1.0
  1706. self.west = 0.0
  1707. self.nsres = 1.0
  1708. self.ewres = 1.0
  1709. # 3D
  1710. self.top = 1.0
  1711. self.bottom = 0.0
  1712. # self.nsres3 = 1.0
  1713. # self.ewres3 = 1.0
  1714. self.tbres = 1.0
  1715. #
  1716. # inputs
  1717. #
  1718. # 2D
  1719. self.tnorth = self.MakeTextCtrl(str(self.north), size=(150, -1))
  1720. self.tsouth = self.MakeTextCtrl(str(self.south), size=(150, -1))
  1721. self.twest = self.MakeTextCtrl(str(self.west), size=(150, -1))
  1722. self.teast = self.MakeTextCtrl(str(self.east), size=(150, -1))
  1723. self.tnsres = self.MakeTextCtrl(str(self.nsres), size=(150, -1))
  1724. self.tewres = self.MakeTextCtrl(str(self.ewres), size=(150, -1))
  1725. #
  1726. # labels
  1727. #
  1728. self.lrows = self.MakeLabel("")
  1729. self.lcols = self.MakeLabel("")
  1730. self.lcells = self.MakeLabel("")
  1731. #
  1732. # buttons
  1733. #
  1734. self.bset = self.MakeButton(_("&Set region"), id=wx.ID_OK)
  1735. self.bcancel = wx.Button(self, id=wx.ID_CANCEL)
  1736. self.bset.SetDefault()
  1737. #
  1738. # image
  1739. #
  1740. self.img = wx.Image(os.path.join(globalvar.ETCWXDIR, "images",
  1741. "qgis_world.png"), wx.BITMAP_TYPE_PNG).ConvertToBitmap()
  1742. #
  1743. # set current working environment to PERMANENT mapset
  1744. # in selected location in order to set default region (WIND)
  1745. #
  1746. envval = {}
  1747. cmdlist = ['g.gisenv']
  1748. p = gcmd.Command(cmdlist)
  1749. if p.returncode == 0:
  1750. output = p.ReadStdOutput()
  1751. for line in output:
  1752. line = line.strip()
  1753. if '=' in line:
  1754. key, val = line.split('=')
  1755. envval[key] = val
  1756. self.currlocation = envval['LOCATION_NAME'].strip("';")
  1757. self.currmapset = envval['MAPSET'].strip("';")
  1758. if self.currlocation != self.location or self.currmapset != 'PERMANENT':
  1759. # cmdlist = ['g.mapset', 'location=%s' % self.location, 'mapset=PERMANENT']
  1760. # gcmd.Command(cmdlist
  1761. gcmd.Command(["g.gisenv",
  1762. "set=LOCATION_NAME=%s" % self.location])
  1763. gcmd.Command(["g.gisenv",
  1764. "set=MAPSET=PERMANENT"])
  1765. else:
  1766. dlg = wx.MessageBox(parent=self,
  1767. message=_('Invalid location selected.'),
  1768. caption=_("Error"), style=wx.ID_OK | wx.ICON_ERROR)
  1769. return
  1770. #
  1771. # get current region settings
  1772. #
  1773. region = {}
  1774. cmdlist = ['g.region', '-gp3']
  1775. p = gcmd.Command(cmdlist)
  1776. if p.returncode == 0:
  1777. output = p.ReadStdOutput()
  1778. for line in output:
  1779. line = line.strip()
  1780. if '=' in line:
  1781. key, val = line.split('=')
  1782. region[key] = float(val)
  1783. else:
  1784. dlg = wx.MessageBox(parent=self,
  1785. message=_("Invalid region"),
  1786. caption=_("Error"), style=wx.ID_OK | wx.ICON_ERROR)
  1787. dlg.ShowModal()
  1788. dlg.Destroy()
  1789. return
  1790. #
  1791. # update values
  1792. # 2D
  1793. self.north = float(region['n'])
  1794. self.south = float(region['s'])
  1795. self.east = float(region['e'])
  1796. self.west = float(region['w'])
  1797. self.nsres = float(region['nsres'])
  1798. self.ewres = float(region['ewres'])
  1799. self.rows = int(region['rows'])
  1800. self.cols = int(region['cols'])
  1801. self.cells = int(region['cells'])
  1802. # 3D
  1803. self.top = float(region['t'])
  1804. self.bottom = float(region['b'])
  1805. # self.nsres3 = float(region['nsres3'])
  1806. # self.ewres3 = float(region['ewres3'])
  1807. self.tbres = float(region['tbres'])
  1808. self.depth = int(region['depths'])
  1809. self.cells3 = int(region['3dcells'])
  1810. #
  1811. # 3D box collapsable
  1812. #
  1813. self.infoCollapseLabelExp = _("Click here to show 3D settings")
  1814. self.infoCollapseLabelCol = _("Click here to hide 3D settings")
  1815. self.settings3D = wx.CollapsiblePane(parent=self,
  1816. label=self.infoCollapseLabelExp,
  1817. style=wx.CP_DEFAULT_STYLE |
  1818. wx.CP_NO_TLW_RESIZE | wx.EXPAND)
  1819. self.MakeSettings3DPaneContent(self.settings3D.GetPane())
  1820. self.settings3D.Collapse(False) # FIXME
  1821. self.Bind(wx.EVT_COLLAPSIBLEPANE_CHANGED, self.OnSettings3DPaneChanged, self.settings3D)
  1822. #
  1823. # set current region settings
  1824. #
  1825. self.tnorth.SetValue(str(self.north))
  1826. self.tsouth.SetValue(str(self.south))
  1827. self.twest.SetValue(str(self.west))
  1828. self.teast.SetValue(str(self.east))
  1829. self.tnsres.SetValue(str(self.nsres))
  1830. self.tewres.SetValue(str(self.ewres))
  1831. self.ttop.SetValue(str(self.top))
  1832. self.tbottom.SetValue(str(self.bottom))
  1833. # self.tnsres3.SetValue(str(self.nsres3))
  1834. # self.tewres3.SetValue(str(self.ewres3))
  1835. self.ttbres.SetValue(str(self.tbres))
  1836. self.lrows.SetLabel(_("Rows: %d" % self.rows))
  1837. self.lcols.SetLabel(_("Cols: %d" % self.cols))
  1838. self.lcells.SetLabel(_("Cells: %d" % self.cells))
  1839. #
  1840. # bindings
  1841. #
  1842. self.Bind(wx.EVT_BUTTON, self.OnSetButton, self.bset)
  1843. self.Bind(wx.EVT_BUTTON, self.OnCancel, self.bcancel)
  1844. self.tnorth.Bind(wx.EVT_TEXT, self.OnValue)
  1845. self.tsouth.Bind(wx.EVT_TEXT, self.OnValue)
  1846. self.teast.Bind(wx.EVT_TEXT, self.OnValue)
  1847. self.twest.Bind(wx.EVT_TEXT, self.OnValue)
  1848. self.tnsres.Bind(wx.EVT_TEXT, self.OnValue)
  1849. self.tewres.Bind(wx.EVT_TEXT, self.OnValue)
  1850. self.ttop.Bind(wx.EVT_TEXT, self.OnValue)
  1851. self.tbottom.Bind(wx.EVT_TEXT, self.OnValue)
  1852. # self.tnsres3.Bind(wx.EVT_TEXT, self.OnValue)
  1853. # self.tewres3.Bind(wx.EVT_TEXT, self.OnValue)
  1854. self.ttbres.Bind(wx.EVT_TEXT, self.OnValue)
  1855. self.__DoLayout()
  1856. self.SetMinSize(self.GetBestSize())
  1857. self.minWindowSize = self.GetMinSize()
  1858. def MakeSettings3DPaneContent(self, pane):
  1859. """Create 3D region settings pane"""
  1860. border = wx.BoxSizer(wx.VERTICAL)
  1861. gridSizer = wx.GridBagSizer(vgap=0, hgap=0)
  1862. # inputs
  1863. self.ttop = wx.TextCtrl(parent=pane, id=wx.ID_ANY, value=str(self.top),
  1864. size=(150, -1))
  1865. self.tbottom = wx.TextCtrl(parent=pane, id=wx.ID_ANY, value=str(self.bottom),
  1866. size=(150, -1))
  1867. self.ttbres = wx.TextCtrl(parent=pane, id=wx.ID_ANY, value=str(self.tbres),
  1868. size=(150, -1))
  1869. # self.tnsres3 = wx.TextCtrl(parent=pane, id=wx.ID_ANY, value=str(self.nsres3),
  1870. # size=(150, -1))
  1871. # self.tewres3 = wx.TextCtrl(parent=pane, id=wx.ID_ANY, value=str(self.ewres3),
  1872. # size=(150, -1))
  1873. #labels
  1874. self.ldepth = wx.StaticText(parent=pane, label=_("Depth: %d") % self.depth)
  1875. self.lcells3 = wx.StaticText(parent=pane, label=_("3D Cells: %d") % self.cells3)
  1876. # top
  1877. gridSizer.Add(item=wx.StaticText(parent=pane, label=_("Top")),
  1878. flag=wx.ALIGN_CENTER |
  1879. wx.LEFT | wx.RIGHT | wx.TOP, border=5,
  1880. pos=(0, 1))
  1881. gridSizer.Add(item=self.ttop,
  1882. flag=wx.ALIGN_CENTER_HORIZONTAL |
  1883. wx.ALL, border=5, pos=(1, 1))
  1884. # bottom
  1885. gridSizer.Add(item=wx.StaticText(parent=pane, label=_("Bottom")),
  1886. flag=wx.ALIGN_CENTER |
  1887. wx.LEFT | wx.RIGHT | wx.TOP, border=5,
  1888. pos=(0, 2))
  1889. gridSizer.Add(item=self.tbottom,
  1890. flag=wx.ALIGN_CENTER_HORIZONTAL |
  1891. wx.ALL, border=5, pos=(1, 2))
  1892. # tbres
  1893. gridSizer.Add(item=wx.StaticText(parent=pane, label=_("T-B resolution")),
  1894. flag=wx.ALIGN_CENTER |
  1895. wx.LEFT | wx.RIGHT | wx.TOP, border=5,
  1896. pos=(0, 3))
  1897. gridSizer.Add(item=self.ttbres,
  1898. flag=wx.ALIGN_CENTER_HORIZONTAL |
  1899. wx.ALL, border=5, pos=(1, 3))
  1900. # res
  1901. # gridSizer.Add(item=wx.StaticText(parent=pane, label=_("3D N-S resolution")),
  1902. # flag=wx.ALIGN_CENTER |
  1903. # wx.LEFT | wx.RIGHT | wx.TOP, border=5,
  1904. # pos=(2, 1))
  1905. # gridSizer.Add(item=self.tnsres3,
  1906. # flag=wx.ALIGN_CENTER_HORIZONTAL |
  1907. # wx.ALL, border=5, pos=(3, 1))
  1908. # gridSizer.Add(item=wx.StaticText(parent=pane, label=_("3D E-W resolution")),
  1909. # flag=wx.ALIGN_CENTER |
  1910. # wx.LEFT | wx.RIGHT | wx.TOP, border=5,
  1911. # pos=(2, 3))
  1912. # gridSizer.Add(item=self.tewres3,
  1913. # flag=wx.ALIGN_CENTER_HORIZONTAL |
  1914. # wx.ALL, border=5, pos=(3, 3))
  1915. # rows/cols/cells
  1916. gridSizer.Add(item=self.ldepth,
  1917. flag=wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_CENTER |
  1918. wx.ALL, border=5, pos=(2, 1))
  1919. gridSizer.Add(item=self.lcells3,
  1920. flag=wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_CENTER |
  1921. wx.ALL, border=5, pos=(2, 2))
  1922. border.Add(item=gridSizer, proportion=1,
  1923. flag=wx.ALL | wx.ALIGN_CENTER | wx.EXPAND, border=5)
  1924. pane.SetSizer(border)
  1925. border.Fit(pane)
  1926. def OnSettings3DPaneChanged(self, event):
  1927. """Collapse 3D settings box"""
  1928. if self.settings3D.IsExpanded():
  1929. self.settings3D.SetLabel(self.infoCollapseLabelCol)
  1930. self.Layout()
  1931. self.SetSize(self.GetBestSize())
  1932. self.SetMinSize(self.GetSize())
  1933. else:
  1934. self.settings3D.SetLabel(self.infoCollapseLabelExp)
  1935. self.Layout()
  1936. self.SetSize(self.minWindowSize)
  1937. self.SetMinSize(self.minWindowSize)
  1938. self.SendSizeEvent()
  1939. def __DoLayout(self):
  1940. """Window layout"""
  1941. frameSizer = wx.BoxSizer(wx.VERTICAL)
  1942. gridSizer = wx.GridBagSizer(vgap=0, hgap=0)
  1943. settings3DSizer = wx.BoxSizer(wx.VERTICAL)
  1944. buttonSizer = wx.BoxSizer(wx.HORIZONTAL)
  1945. # north
  1946. gridSizer.Add(item=self.MakeLabel(_("North")),
  1947. flag=wx.ALIGN_BOTTOM | wx.ALIGN_CENTER_HORIZONTAL |
  1948. wx.TOP | wx.LEFT | wx.RIGHT, border=5, pos=(0, 2))
  1949. gridSizer.Add(item=self.tnorth,
  1950. flag=wx.ALIGN_CENTER_HORIZONTAL |
  1951. wx.ALIGN_CENTER_VERTICAL |
  1952. wx.ALL, border=5, pos=(1, 2))
  1953. # west
  1954. gridSizer.Add(item=self.MakeLabel(_("West")),
  1955. flag=wx.ALIGN_RIGHT |
  1956. wx.ALIGN_CENTER_VERTICAL |
  1957. wx.LEFT | wx.TOP | wx.BOTTOM, border=5, pos=(2, 0))
  1958. gridSizer.Add(item=self.twest,
  1959. flag=wx.ALIGN_RIGHT |
  1960. wx.ALIGN_CENTER_VERTICAL |
  1961. wx.ALL, border=5, pos=(2, 1))
  1962. gridSizer.Add(item=wx.StaticBitmap(self, wx.ID_ANY, self.img, (-1, -1),
  1963. (self.img.GetWidth(), self.img.GetHeight())),
  1964. flag=wx.ALIGN_CENTER |
  1965. wx.ALIGN_CENTER_VERTICAL |
  1966. wx.ALL, border=5, pos=(2, 2))
  1967. # east
  1968. gridSizer.Add(item=self.teast,
  1969. flag=wx.ALIGN_CENTER_HORIZONTAL |
  1970. wx.ALIGN_CENTER_VERTICAL |
  1971. wx.ALL, border=5, pos=(2, 3))
  1972. gridSizer.Add(item=self.MakeLabel(_("East")),
  1973. flag=wx.ALIGN_LEFT |
  1974. wx.ALIGN_CENTER_VERTICAL |
  1975. wx.RIGHT | wx.TOP | wx.BOTTOM, border=5, pos=(2, 4))
  1976. # south
  1977. gridSizer.Add(item=self.tsouth,
  1978. flag=wx.ALIGN_CENTER_HORIZONTAL |
  1979. wx.ALIGN_CENTER_VERTICAL |
  1980. wx.ALL, border=5, pos=(3, 2))
  1981. gridSizer.Add(item=self.MakeLabel(_("South")),
  1982. flag=wx.ALIGN_TOP | wx.ALIGN_CENTER_HORIZONTAL |
  1983. wx.LEFT | wx.RIGHT | wx.BOTTOM, border=5, pos=(4, 2))
  1984. # ns-res
  1985. gridSizer.Add(item=self.MakeLabel(_("N-S resolution")),
  1986. flag=wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_CENTER |
  1987. wx.TOP | wx.LEFT | wx.RIGHT, border=5, pos=(5, 1))
  1988. gridSizer.Add(item=self.tnsres,
  1989. flag=wx.ALIGN_RIGHT |
  1990. wx.ALIGN_CENTER_VERTICAL |
  1991. wx.ALL, border=5, pos=(6, 1))
  1992. # ew-res
  1993. gridSizer.Add(item=self.MakeLabel(_("E-W resolution")),
  1994. flag=wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_CENTER |
  1995. wx.TOP | wx.LEFT | wx.RIGHT, border=5, pos=(5, 3))
  1996. gridSizer.Add(item=self.tewres,
  1997. flag=wx.ALIGN_RIGHT |
  1998. wx.ALIGN_CENTER_VERTICAL |
  1999. wx.ALL, border=5, pos=(6, 3))
  2000. # rows/cols/cells
  2001. gridSizer.Add(item=self.lrows,
  2002. flag=wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_CENTER |
  2003. wx.ALL, border=5, pos=(7, 1))
  2004. gridSizer.Add(item=self.lcells,
  2005. flag=wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_CENTER |
  2006. wx.ALL, border=5, pos=(7, 2))
  2007. gridSizer.Add(item=self.lcols,
  2008. flag=wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_CENTER |
  2009. wx.ALL, border=5, pos=(7, 3))
  2010. # 3D
  2011. settings3DSizer.Add(item=self.settings3D,
  2012. flag=wx.ALL,
  2013. border=5)
  2014. # buttons
  2015. buttonSizer.Add(item=self.bcancel, proportion=1,
  2016. flag=wx.ALIGN_RIGHT |
  2017. wx.ALIGN_CENTER_VERTICAL |
  2018. wx.ALL, border=10)
  2019. buttonSizer.Add(item=self.bset, proportion=1,
  2020. flag=wx.ALIGN_CENTER |
  2021. wx.ALIGN_CENTER_VERTICAL |
  2022. wx.ALL, border=10)
  2023. frameSizer.Add(item=gridSizer, proportion=1,
  2024. flag=wx.ALL | wx.ALIGN_CENTER, border=5)
  2025. frameSizer.Add(item=settings3DSizer, proportion=0,
  2026. flag=wx.ALL | wx.ALIGN_CENTER, border=5)
  2027. frameSizer.Add(item=buttonSizer, proportion=0,
  2028. flag=wx.ALL | wx.ALIGN_RIGHT, border=5)
  2029. self.SetAutoLayout(True)
  2030. self.SetSizer(frameSizer)
  2031. frameSizer.Fit(self)
  2032. self.Layout()
  2033. def OnValue(self, event):
  2034. """Set given value"""
  2035. try:
  2036. if event.GetId() == self.tnorth.GetId():
  2037. self.north = float(event.GetString())
  2038. elif event.GetId() == self.tsouth.GetId():
  2039. self.south = float(event.GetString())
  2040. elif event.GetId() == self.teast.GetId():
  2041. self.east = float(event.GetString())
  2042. elif event.GetId() == self.twest.GetId():
  2043. self.west = float(event.GetString())
  2044. elif event.GetId() == self.tnsres.GetId():
  2045. self.nsres = float(event.GetString())
  2046. elif event.GetId() == self.tewres.GetId():
  2047. self.ewres = float(event.GetString())
  2048. elif event.GetId() == self.ttop.GetId():
  2049. self.top = float(event.GetString())
  2050. elif event.GetId() == self.tbottom.GetId():
  2051. self.bottom = float(event.GetString())
  2052. # elif event.GetId() == self.tnsres3.GetId():
  2053. # self.nsres3 = float(event.GetString())
  2054. # elif event.GetId() == self.tewres3.GetId():
  2055. # self.ewres3 = float(event.GetString())
  2056. elif event.GetId() == self.ttbres.GetId():
  2057. self.tbres = float(event.GetString())
  2058. self.__UpdateInfo()
  2059. except ValueError, e:
  2060. if len(event.GetString()) > 0 and event.GetString() != '-':
  2061. dlg = wx.MessageBox(parent=self,
  2062. message=_("Invalid value: %s") % e,
  2063. caption=_("Error"),
  2064. style=wx.OK | wx.ICON_ERROR)
  2065. # reset values
  2066. self.tnorth.SetValue(str(self.north))
  2067. self.tsouth.SetValue(str(self.south))
  2068. self.teast.SetValue(str(self.east))
  2069. self.twest.SetValue(str(self.west))
  2070. self.tnsres.SetValue(str(self.nsres))
  2071. self.tewres.SetValue(str(self.ewres))
  2072. self.ttop.SetValue(str(self.top))
  2073. self.tbottom.SetValue(str(self.bottom))
  2074. self.ttbres.SetValue(str(self.tbres))
  2075. # self.tnsres3.SetValue(str(self.nsres3))
  2076. # self.tewres3.SetValue(str(self.ewres3))
  2077. event.Skip()
  2078. def __UpdateInfo(self):
  2079. """Update number of rows/cols/cells"""
  2080. self.rows = int((self.north - self.south) / self.nsres)
  2081. self.cols = int((self.east - self.west) / self.ewres)
  2082. self.cells = self.rows * self.cols
  2083. self.depth = int((self.top - self.bottom) / self.tbres)
  2084. self.cells3 = self.rows * self.cols * self.depth
  2085. # 2D
  2086. self.lrows.SetLabel(_("Rows: %d") % self.rows)
  2087. self.lcols.SetLabel(_("Cols: %d") % self.cols)
  2088. self.lcells.SetLabel(_("Cells: %d") % self.cells)
  2089. # 3D
  2090. self.ldepth.SetLabel(_("Depth: %d" % self.depth))
  2091. self.lcells3.SetLabel(_("3D Cells: %d" % self.cells3))
  2092. def OnSetButton(self, event=None):
  2093. """Set default region"""
  2094. cmdlist = ['g.region', '-sgpa',
  2095. 'n=%f' % self.north,
  2096. 's=%f' % self.south,
  2097. 'e=%f' % self.east,
  2098. 'w=%f' % self.west,
  2099. 'nsres=%f' % self.nsres,
  2100. 'ewres=%f' % self.ewres,
  2101. 't=%f' % self.top,
  2102. 'b=%f' % self.bottom,
  2103. 'tbres=%f' % self.tbres]
  2104. p = gcmd.Command(cmdlist)
  2105. if p.returncode == 0:
  2106. self.Destroy()
  2107. def OnCancel(self, event):
  2108. self.Destroy()
  2109. if __name__ == "__main__":
  2110. app = wx.PySimpleApp()
  2111. # gWizard = LocationWizard(None, "")
  2112. gWizard = RegionDef(None)
  2113. gWizzard.Show()
  2114. app.MainLoop()