location_wizard.py 100 KB

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