location_wizard.py 98 KB

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