location_wizard.py 99 KB

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