location_wizard.py 99 KB

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