123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823 |
- """
- @package location_wizard.wizard
- @brief Location wizard - creates a new GRASS Location. User can choose
- from multiple methods.
- Classes:
- - wizard::TitledPage
- - wizard::GridBagSizerTitledPage
- - wizard::DatabasePage
- - wizard::CoordinateSystemPage
- - wizard::ProjectionsPage
- - wizard::ItemList
- - wizard::ProjParamsPage
- - wizard::DatumPage
- - wizard::EllipsePage
- - wizard::GeoreferencedFilePage
- - wizard::WKTPage
- - wizard::EPSGPage
- - wizard::IAUPage
- - wizard::CustomPage
- - wizard::SummaryPage
- - wizard::LocationWizard
- - wizard::WizardWithHelpButton
- (C) 2007-2016 by the GRASS Development Team
- This program is free software under the GNU General Public License
- (>=v2). Read the file COPYING that comes with GRASS for details.
- @author Michael Barton
- @author Jachym Cepicky
- @author Martin Landa <landa.martin gmail.com>
- @author Hamish Bowman (planetary ellipsoids)
- """
- import os
- import locale
- import six
- import functools
- import wx
- import wx.lib.mixins.listctrl as listmix
- from core import globalvar
- if globalvar.wxPythonPhoenix:
- from wx import adv as wiz
- from wx.adv import Wizard
- from wx.adv import WizardPageSimple
- else:
- from wx import wizard as wiz
- from wx.wizard import Wizard
- from wx.wizard import WizardPageSimple
- import wx.lib.scrolledpanel as scrolled
- from core import utils
- from core.utils import cmp
- from core.gcmd import RunCommand, GError, GWarning
- from gui_core.widgets import GenericMultiValidator
- from gui_core.wrap import (
- SpinCtrl,
- SearchCtrl,
- StaticText,
- TextCtrl,
- Button,
- CheckBox,
- StaticBox,
- NewId,
- ListCtrl,
- HyperlinkCtrl,
- )
- from location_wizard.dialogs import SelectTransformDialog
- from grass.grassdb.checks import location_exists
- from grass.script import decode
- from grass.script import core as grass
- from grass.exceptions import OpenError
- global coordsys
- global north
- global south
- global east
- global west
- global resolution
- global wizerror
- global translist
- if globalvar.CheckWxVersion(version=[4, 1, 0]):
- search_cancel_evt = wx.EVT_SEARCH_CANCEL
- else:
- search_cancel_evt = wx.EVT_SEARCHCTRL_CANCEL_BTN
- class TitledPage(WizardPageSimple):
- """Class to make wizard pages. Generic methods to make labels,
- text entries, and buttons.
- """
- def __init__(self, parent, title):
- self.page = WizardPageSimple.__init__(self, parent)
- font = wx.Font(13, wx.SWISS, wx.NORMAL, wx.BOLD)
- font_height = font.GetPixelSize()[1]
- # page title
- self.title = StaticText(
- parent=self,
- id=wx.ID_ANY,
- label=title,
- style=wx.ALIGN_CENTRE_HORIZONTAL,
- size=(-1, font_height),
- )
- self.title.SetFont(font)
- # main sizers
- self.pagesizer = wx.BoxSizer(wx.VERTICAL)
- def DoLayout(self):
- """Do page layout"""
- self.pagesizer.Add(self.title, proportion=0, flag=wx.EXPAND | wx.ALL, border=5)
- self.pagesizer.Add(
- wx.StaticLine(self, -1), proportion=0, flag=wx.EXPAND | wx.ALL, border=0
- )
- self.pagesizer.Add(self.sizer, proportion=1, flag=wx.EXPAND)
- self.SetAutoLayout(True)
- self.SetSizer(self.pagesizer)
- self.Layout()
- def MakeLabel(self, text="", style=wx.ALIGN_LEFT, parent=None, tooltip=None):
- """Make aligned label"""
- if not parent:
- parent = self
- label = StaticText(parent=parent, id=wx.ID_ANY, label=text, style=style)
- if tooltip:
- label.SetToolTip(tooltip)
- return label
- def MakeTextCtrl(self, text="", size=(100, -1), style=0, parent=None, tooltip=None):
- """Generic text control"""
- if not parent:
- parent = self
- textCtrl = TextCtrl(
- parent=parent, id=wx.ID_ANY, value=text, size=size, style=style
- )
- if tooltip:
- textCtrl.SetToolTip(tooltip)
- return textCtrl
- def MakeButton(self, text, id=wx.ID_ANY, size=(-1, -1), parent=None, tooltip=None):
- """Generic button"""
- if not parent:
- parent = self
- button = Button(parent=parent, id=id, label=text, size=size)
- if tooltip:
- button.SetToolTip(tooltip)
- return button
- def MakeCheckBox(
- self, text, id=wx.ID_ANY, size=(-1, -1), parent=None, tooltip=None
- ):
- """Generic checkbox"""
- if not parent:
- parent = self
- chbox = CheckBox(parent=parent, id=id, label=text, size=size)
- if tooltip:
- chbox.SetToolTip(tooltip)
- return chbox
- class GridBagSizerTitledPage(TitledPage):
- """GridBagSizer declaration for TitledPage class"""
- def __init__(self, parent, title):
- super().__init__(parent, title)
- self.sizer = wx.GridBagSizer(vgap=0, hgap=0)
- self.sizer.SetCols(5)
- self.sizer.SetRows(8)
- class DatabasePage(TitledPage):
- """Wizard page for setting GIS data directory and location name"""
- def __init__(self, wizard, parent, grassdatabase):
- TitledPage.__init__(self, wizard, _("Define new GRASS Location"))
- # grid definition
- self.sizer = wx.GridBagSizer(vgap=0, hgap=0)
- self.sizer.SetCols(5)
- self.sizer.SetRows(8)
- self.sizer.AddGrowableCol(1)
- # definition of variables
- self.grassdatabase = grassdatabase
- self.location = ""
- self.locTitle = ""
- # browse button
- self.bbrowse = self.MakeButton(_("Change"))
- # text controls
- self.tgisdbase = self.MakeLabel(grassdatabase)
- self.tlocation = self.MakeTextCtrl("newLocation")
- self.tlocation.SetFocus()
- checks = [
- (grass.legal_name, self._nameValidationFailed),
- (self._checkLocationNotExists, self._locationAlreadyExists),
- ]
- self.tlocation.SetValidator(GenericMultiValidator(checks))
- self.tlocTitle = self.MakeTextCtrl()
- # text for required options
- required_txt = self.MakeLabel("*")
- required_txt.SetForegroundColour(wx.RED)
- required_txt.SetToolTip(_("This option is required"))
- # text for optional options
- optional_txt = self.MakeLabel(_("(optional)"))
- italics = wx.Font(10, wx.DEFAULT, wx.ITALIC, wx.NORMAL)
- optional_txt.SetFont(italics)
- optional_txt.SetForegroundColour(
- wx.SystemSettings.GetColour(wx.SYS_COLOUR_GRAYTEXT)
- )
- # layout
- self.sizer.Add(
- self.MakeLabel(
- "%s:" % _("Name"),
- tooltip=_("Name of location directory in GIS Data Directory"),
- ),
- flag=wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL | wx.ALL,
- border=5,
- pos=(1, 1),
- )
- self.sizer.Add(
- self.tlocation,
- flag=wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL | wx.ALL | wx.EXPAND,
- border=5,
- pos=(2, 1),
- )
- self.sizer.Add(
- required_txt,
- flag=wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL | wx.ALL,
- border=5,
- pos=(2, 2),
- )
- self.sizer.Add(
- self.MakeLabel(
- "%s:" % _("Description"),
- tooltip=_("Description of location directory in GIS Data Directory"),
- ),
- flag=wx.ALIGN_LEFT | wx.ALIGN_TOP | wx.ALIGN_CENTER_VERTICAL | wx.ALL,
- border=5,
- pos=(3, 1),
- )
- self.sizer.Add(
- self.tlocTitle,
- flag=wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL | wx.ALL | wx.EXPAND,
- border=5,
- pos=(4, 1),
- )
- self.sizer.Add(
- optional_txt,
- flag=wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL | wx.ALL,
- border=5,
- pos=(4, 2),
- )
- self.sizer.Add(
- self.MakeLabel(_("Location will be created in GRASS database:")),
- flag=wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL | wx.ALL,
- border=2,
- pos=(5, 1),
- )
- self.sizer.Add(
- self.tgisdbase,
- flag=wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL | wx.ALL,
- border=5,
- pos=(6, 1),
- )
- self.sizer.Add(
- self.bbrowse,
- flag=wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL | wx.ALL,
- border=5,
- pos=(6, 2),
- )
- # bindings
- self.Bind(wiz.EVT_WIZARD_PAGE_CHANGING, self.OnPageChanging)
- self.tgisdbase.Bind(wx.EVT_TEXT, self.OnChangeName)
- self.tlocation.Bind(wx.EVT_TEXT, self.OnChangeName)
- self.Bind(wx.EVT_BUTTON, self.OnBrowse, self.bbrowse)
- def _nameValidationFailed(self, ctrl):
- message = _(
- "Name '{}' is not a valid name for location. "
- "Please use only ASCII characters excluding characters {} "
- "and space."
- ).format(ctrl.GetValue(), "/\"'@,=*~")
- GError(parent=self, message=message, caption=_("Invalid name"))
- def _checkLocationNotExists(self, text):
- """Check whether user's input location exists or not."""
- if location_exists(self.tgisdbase.GetLabel(), text):
- return False
- return True
- def _locationAlreadyExists(self, ctrl):
- message = _(
- "Location '{}' already exists. Please consider using "
- "another name for your location."
- ).format(ctrl.GetValue())
- GError(parent=self, message=message, caption=_("Existing location path"))
- def OnChangeName(self, event):
- """Name for new location was changed"""
- nextButton = wx.FindWindowById(wx.ID_FORWARD)
- if len(event.GetString()) > 0:
- if not nextButton.IsEnabled():
- nextButton.Enable()
- else:
- nextButton.Disable()
- event.Skip()
- def OnBrowse(self, event):
- """Choose GRASS data directory"""
- dlg = wx.DirDialog(
- self, _("Choose GRASS data directory:"), os.getcwd(), wx.DD_DEFAULT_STYLE
- )
- if dlg.ShowModal() == wx.ID_OK:
- self.grassdatabase = dlg.GetPath()
- self.tgisdbase.SetLabel(self.grassdatabase)
- dlg.Destroy()
- def OnPageChanging(self, event=None):
- self.location = self.tlocation.GetValue()
- self.grassdatabase = self.tgisdbase.GetLabel()
- self.locTitle = self.tlocTitle.GetValue()
- if os.linesep in self.locTitle or len(self.locTitle) > 255:
- GWarning(
- parent=self,
- message=_(
- "Title of the location is limited only to one line and "
- "256 characters. The rest of the text will be ignored."
- ),
- )
- self.locTitle = self.locTitle.split(os.linesep)[0][:255]
- class CoordinateSystemPage(TitledPage):
- """Wizard page for choosing method for location creation"""
- def __init__(self, wizard, parent):
- TitledPage.__init__(self, wizard, _("Select Coordinate Reference System (CRS)"))
- self.sizer = wx.GridBagSizer(vgap=0, hgap=0)
- self.sizer.SetCols(5)
- self.sizer.SetRows(8)
- self.parent = parent
- global coordsys
- # toggles
- self.radioEpsg = wx.RadioButton(
- parent=self,
- id=wx.ID_ANY,
- label=_("Select CRS from a list by EPSG or description"),
- style=wx.RB_GROUP,
- )
- # self.radioIau = wx.RadioButton(
- # parent=self, id=wx.ID_ANY,
- # label=_("Select IAU code of spatial reference system"))
- self.radioFile = wx.RadioButton(
- parent=self,
- id=wx.ID_ANY,
- label=_("Read CRS from a georeferenced data file"),
- )
- self.radioXy = wx.RadioButton(
- parent=self,
- id=wx.ID_ANY,
- label=_("Create a generic cartesian coordinate system (XY)"),
- )
- self.radioWkt = wx.RadioButton(
- parent=self, id=wx.ID_ANY, label=_("Specify CRS using WKT string")
- )
- self.radioProj = wx.RadioButton(
- parent=self, id=wx.ID_ANY, label=_("Specify CRS using PROJ.4 string")
- )
- self.radioSrs = wx.RadioButton(
- parent=self, id=wx.ID_ANY, label=_("Define custom CRS")
- )
- # layout
- self.sizer.SetVGap(10)
- self.sizer.Add(self.radioEpsg, flag=wx.ALIGN_LEFT, pos=(1, 1))
- # self.sizer.Add(self.radioIau,
- # flag=wx.ALIGN_LEFT, pos=(1, 1))
- self.sizer.Add(self.radioFile, flag=wx.ALIGN_LEFT, pos=(2, 1))
- self.sizer.Add(self.radioXy, flag=wx.ALIGN_LEFT, pos=(3, 1))
- self.sizer.Add(
- StaticText(parent=self, label=_("Additional methods:")),
- flag=wx.ALIGN_LEFT,
- pos=(4, 1),
- )
- self.sizer.Add(self.radioWkt, flag=wx.ALIGN_LEFT, pos=(5, 1))
- self.sizer.Add(self.radioProj, flag=wx.ALIGN_LEFT, pos=(6, 1))
- self.sizer.Add(self.radioSrs, flag=wx.ALIGN_LEFT, pos=(7, 1))
- self.sizer.AddGrowableCol(1)
- # bindings
- self.Bind(wx.EVT_RADIOBUTTON, self.SetVal, id=self.radioEpsg.GetId())
- # self.Bind(wx.EVT_RADIOBUTTON, self.SetVal, id=self.radioIau.GetId())
- self.Bind(wx.EVT_RADIOBUTTON, self.SetVal, id=self.radioFile.GetId())
- self.Bind(wx.EVT_RADIOBUTTON, self.SetVal, id=self.radioWkt.GetId())
- self.Bind(wx.EVT_RADIOBUTTON, self.SetVal, id=self.radioSrs.GetId())
- self.Bind(wx.EVT_RADIOBUTTON, self.SetVal, id=self.radioProj.GetId())
- self.Bind(wx.EVT_RADIOBUTTON, self.SetVal, id=self.radioXy.GetId())
- self.Bind(wiz.EVT_WIZARD_PAGE_CHANGED, self.OnEnterPage)
- def OnEnterPage(self, event):
- global coordsys
- if not coordsys:
- coordsys = "epsg"
- self.radioEpsg.SetValue(True)
- else:
- if coordsys == "proj":
- self.radioSrs.SetValue(True)
- if coordsys == "epsg":
- self.radioEpsg.SetValue(True)
- # if coordsys == "iau":
- # self.radioIau.SetValue(True)
- if coordsys == "file":
- self.radioFile.SetValue(True)
- if coordsys == "wkt":
- self.radioWkt.SetValue(True)
- if coordsys == "custom":
- self.radioProj.SetValue(True)
- if coordsys == "xy":
- self.radioXy.SetValue(True)
- if event.GetDirection():
- if coordsys == "proj":
- self.SetNext(self.parent.projpage)
- self.parent.sumpage.SetPrev(self.parent.datumpage)
- if coordsys == "epsg":
- self.SetNext(self.parent.epsgpage)
- self.parent.sumpage.SetPrev(self.parent.epsgpage)
- # if coordsys == "iau":
- # self.SetNext(self.parent.iaupage)
- # self.parent.sumpage.SetPrev(self.parent.iaupage)
- if coordsys == "file":
- self.SetNext(self.parent.filepage)
- self.parent.sumpage.SetPrev(self.parent.filepage)
- if coordsys == "wkt":
- self.SetNext(self.parent.wktpage)
- self.parent.sumpage.SetPrev(self.parent.wktpage)
- if coordsys == "custom":
- self.SetNext(self.parent.custompage)
- self.parent.sumpage.SetPrev(self.parent.custompage)
- if coordsys == "xy":
- self.SetNext(self.parent.sumpage)
- self.parent.sumpage.SetPrev(self.parent.csystemspage)
- if not wx.FindWindowById(wx.ID_FORWARD).IsEnabled():
- wx.FindWindowById(wx.ID_FORWARD).Enable()
- def SetVal(self, event):
- """Choose method"""
- global coordsys
- if event.GetId() == self.radioSrs.GetId():
- coordsys = "proj"
- self.SetNext(self.parent.projpage)
- self.parent.sumpage.SetPrev(self.parent.datumpage)
- # elif event.GetId() == self.radioIau.GetId():
- # coordsys = "iau"
- # self.SetNext(self.parent.iaupage)
- # self.parent.sumpage.SetPrev(self.parent.iaupage)
- elif event.GetId() == self.radioEpsg.GetId():
- coordsys = "epsg"
- self.SetNext(self.parent.epsgpage)
- self.parent.sumpage.SetPrev(self.parent.epsgpage)
- elif event.GetId() == self.radioFile.GetId():
- coordsys = "file"
- self.SetNext(self.parent.filepage)
- self.parent.sumpage.SetPrev(self.parent.filepage)
- elif event.GetId() == self.radioWkt.GetId():
- coordsys = "wkt"
- self.SetNext(self.parent.wktpage)
- self.parent.sumpage.SetPrev(self.parent.wktpage)
- elif event.GetId() == self.radioProj.GetId():
- coordsys = "custom"
- self.SetNext(self.parent.custompage)
- self.parent.sumpage.SetPrev(self.parent.custompage)
- elif event.GetId() == self.radioXy.GetId():
- coordsys = "xy"
- self.SetNext(self.parent.sumpage)
- self.parent.sumpage.SetPrev(self.parent.csystemspage)
- class ProjectionsPage(TitledPage):
- """Wizard page for defining custom CRS"""
- def __init__(self, wizard, parent):
- TitledPage.__init__(self, wizard, _("Define custom CRS"))
- self.sizer = wx.GridBagSizer(vgap=0, hgap=0)
- self.sizer.SetCols(5)
- self.sizer.SetRows(8)
- self.parent = parent
- self.proj = ""
- self.projdesc = ""
- self.p4proj = ""
- # text input
- self.tproj = self.MakeTextCtrl("", size=(200, -1))
- # search box
- self.searchb = SearchCtrl(self, size=(200, -1), style=wx.TE_PROCESS_ENTER)
- self.searchb.ShowCancelButton(True)
- # projection list
- self.projlist = ItemList(
- self,
- data=list(self.parent.projdesc.items()),
- columns=[_("Code"), _("Description")],
- )
- self.projlist.resizeLastColumn(30)
- # layout
- self.sizer.Add(
- self.MakeLabel(_("Projection code:")),
- flag=wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL | wx.ALL,
- border=5,
- pos=(1, 1),
- )
- self.sizer.Add(
- self.tproj, flag=wx.ALIGN_RIGHT | wx.EXPAND | wx.ALL, border=5, pos=(1, 2)
- )
- self.sizer.Add(
- self.MakeLabel(_("Search in description:")),
- flag=wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL | wx.ALL,
- border=5,
- pos=(2, 1),
- )
- self.sizer.Add(
- self.searchb, flag=wx.ALIGN_RIGHT | wx.EXPAND | wx.ALL, border=5, pos=(2, 2)
- )
- self.sizer.Add(
- self.projlist,
- flag=wx.EXPAND | wx.ALIGN_LEFT | wx.ALL,
- border=5,
- pos=(3, 1),
- span=(1, 3),
- )
- self.sizer.AddGrowableCol(3)
- self.sizer.AddGrowableRow(3)
- # events
- self.tproj.Bind(wx.EVT_TEXT, self.OnText)
- self.searchb.Bind(wx.EVT_TEXT, self.OnSearch)
- self.searchb.Bind(search_cancel_evt, self.OnSearchCancel)
- self.projlist.Bind(wx.EVT_LIST_ITEM_SELECTED, self.OnItemSelected)
- self.Bind(wiz.EVT_WIZARD_PAGE_CHANGING, self.OnPageChanging)
- self.Bind(wiz.EVT_WIZARD_PAGE_CHANGED, self.OnEnterPage)
- def OnPageChanging(self, event):
- if event.GetDirection() and self.proj not in self.parent.projections.keys():
- event.Veto()
- def OnText(self, event):
- """Projection name changed"""
- self.proj = event.GetString().lower()
- self.p4proj = ""
- nextButton = wx.FindWindowById(wx.ID_FORWARD)
- if self.proj not in self.parent.projections.keys() and nextButton.IsEnabled():
- nextButton.Enable(False)
- if self.proj in self.parent.projections.keys():
- if self.proj == "stp":
- wx.MessageBox(
- "Currently State Plane projections must be selected using the "
- "text-based setup (g.setproj), or entered by EPSG code or "
- "custom PROJ.4 terms.",
- "Warning",
- wx.ICON_WARNING,
- )
- self.proj = ""
- self.tproj.SetValue(self.proj)
- nextButton.Enable(False)
- return
- elif self.proj.lower() == "ll":
- self.p4proj = "+proj=longlat"
- else:
- self.p4proj = "+proj=" + self.proj.lower()
- self.projdesc = self.parent.projections[self.proj][0]
- nextButton.Enable()
- def OnEnterPage(self, event):
- if len(self.proj) == 0:
- # disable 'next' button by default
- wx.FindWindowById(wx.ID_FORWARD).Enable(False)
- else:
- wx.FindWindowById(wx.ID_FORWARD).Enable(True)
- event.Skip()
- def OnSearch(self, event):
- """Search projection by desc"""
- search_str = event.GetString()
- try:
- self.proj, self.projdesc = self.projlist.Search(
- index=[0, 1], pattern=search_str
- )
- except:
- self.proj = self.projdesc = ""
- event.Skip()
- def OnSearchCancel(self, event):
- self.projlist.Search(index=None, pattern="")
- event.Skip()
- def OnItemSelected(self, event):
- """Projection selected"""
- index = event.GetIndex()
- # set values
- self.proj = self.projlist.GetItem(index, 0).GetText().lower()
- self.tproj.SetValue(self.proj)
- event.Skip()
- class ItemList(ListCtrl, listmix.ListCtrlAutoWidthMixin, listmix.ColumnSorterMixin):
- """Generic list (for projections, ellipsoids, etc.)"""
- def __init__(self, parent, columns, data=None):
- ListCtrl.__init__(
- self,
- parent=parent,
- id=wx.ID_ANY,
- style=wx.LC_REPORT
- | wx.LC_VIRTUAL
- | wx.LC_HRULES
- | wx.LC_VRULES
- | wx.LC_SINGLE_SEL
- | wx.LC_SORT_ASCENDING,
- size=(550, 125),
- )
- # original data or None
- self.sourceData = data
- #
- # insert columns
- #
- i = 0
- for column in columns:
- self.InsertColumn(i, column)
- i += 1
- self.EnableAlternateRowColours()
- if self.sourceData:
- self.Populate()
- for i in range(self.GetColumnCount()):
- self.SetColumnWidth(i, wx.LIST_AUTOSIZE_USEHEADER)
- if self.GetColumnWidth(i) < 80:
- self.SetColumnWidth(i, 80)
- #
- # listmix
- #
- listmix.ListCtrlAutoWidthMixin.__init__(self)
- listmix.ColumnSorterMixin.__init__(self, self.GetColumnCount())
- self.il = wx.ImageList(16, 16)
- self.sm_up = self.il.Add(
- wx.ArtProvider.GetBitmap(wx.ART_GO_UP, wx.ART_TOOLBAR, (16, 16))
- )
- self.sm_dn = self.il.Add(
- wx.ArtProvider.GetBitmap(wx.ART_GO_DOWN, wx.ART_TOOLBAR, (16, 16))
- )
- self.SetImageList(self.il, wx.IMAGE_LIST_SMALL)
- #
- # sort by first column
- #
- if self.sourceData:
- self.SortListItems(col=0, ascending=True)
- def Populate(self, data=None, update=False):
- """Populate and sort list.
- Returns sorted list."""
- self.itemDataMap = {}
- self.itemIndexMap = []
- if data is None:
- data = self.sourceData
- elif update:
- self.sourceData = data
- try:
- data = sorted(data)
- self.DeleteAllItems()
- row = 0
- for value in data:
- self.itemDataMap[row] = [value[0]]
- for i in range(1, len(value)):
- self.itemDataMap[row].append(value[i])
- self.itemIndexMap.append(row)
- row += 1
- self.SetItemCount(row)
- # set column width
- self.SetColumnWidth(0, 80)
- self.SetColumnWidth(1, 300)
- self.SendSizeEvent()
- return data
- except Exception as e:
- wx.MessageBox(
- parent=self,
- message=_("Unable to read list: %s") % e,
- caption=_("Error"),
- style=wx.OK | wx.ICON_ERROR,
- )
- def GetSortImages(self):
- """Used by the ColumnSorterMixin, see wx/lib/mixins/listctrl.py"""
- return (self.sm_dn, self.sm_up)
- def OnGetItemText(self, item, col):
- """Get item text"""
- index = self.itemIndexMap[item]
- s = str(self.itemDataMap[index][col])
- return s
- def OnGetItemImage(self, item):
- return -1
- def SortItems(self, sorter=cmp):
- """Sort items"""
- items = list(self.itemDataMap.keys())
- items.sort(key=functools.cmp_to_key(self.Sorter))
- self.itemIndexMap = items
- # redraw the list
- self.Refresh()
- def Sorter(self, key1, key2):
- ascending = self._colSortFlag[self._col]
- # convert always string
- item1 = self.itemDataMap[key1][self._col]
- item2 = self.itemDataMap[key2][self._col]
- if isinstance(item1, type("")) or isinstance(item2, type("")):
- cmpVal = locale.strcoll(str(item1), str(item2))
- else:
- cmpVal = cmp(item1, item2)
- # If the items are equal then pick something else to make the sort
- # value unique
- if cmpVal == 0:
- cmpVal = cmp(*self.GetSecondarySortValues(self._col, key1, key2))
- if ascending:
- return cmpVal
- else:
- return -cmpVal
- def GetListCtrl(self):
- """Used by listmix.ColumnSorterMixin"""
- return self
- def Search(self, index, pattern, firstOnly=True):
- """Search projection by description
- Return first found item (or None) if firstOnly is True,
- all data (or empty list) if False
- """
- if pattern == "":
- self.Populate(self.sourceData)
- return None if firstOnly else []
- data = []
- pattern = pattern.lower()
- for i in range(len(self.sourceData)):
- for idx in index:
- try:
- value = str(self.sourceData[i][idx]).lower()
- if pattern in value:
- data.append(self.sourceData[i])
- break
- except UnicodeDecodeError:
- # osgeo4w problem (should be fixed)
- pass
- data = self.Populate(data)
- if len(data) > 0:
- if firstOnly:
- return data[0]
- else:
- return data
- else:
- if firstOnly:
- return None
- else:
- return []
- class ProjParamsPage(TitledPage):
- """Wizard page for selecting method of setting coordinate system
- parameters (select coordinate system option)
- """
- def __init__(self, wizard, parent):
- TitledPage.__init__(self, wizard, _("Choose projection parameters"))
- global coordsys
- self.sizer = wx.GridBagSizer(vgap=0, hgap=0)
- self.sizer.SetCols(5)
- self.sizer.SetRows(8)
- self.parent = parent
- self.panel = None
- self.prjParamSizer = None
- self.pparam = dict()
- self.p4projparams = ""
- self.projdesc = ""
- radioSBox = StaticBox(
- parent=self,
- id=wx.ID_ANY,
- label=" %s " % _("Select datum or ellipsoid (next page)"),
- )
- radioSBSizer = wx.StaticBoxSizer(radioSBox)
- self.sizer.Add(
- radioSBSizer, pos=(0, 1), flag=wx.EXPAND | wx.ALIGN_TOP | wx.TOP, border=10
- )
- self.sizer.AddGrowableCol(1)
- self.radio1 = wx.RadioButton(
- parent=self,
- id=wx.ID_ANY,
- label=_("Datum with associated ellipsoid"),
- style=wx.RB_GROUP,
- )
- self.radioEpsg = wx.RadioButton(
- parent=self, id=wx.ID_ANY, label=_("Ellipsoid only")
- )
- # default button setting
- if self.radio1.GetValue() is False and self.radioEpsg.GetValue() is False:
- self.radio1.SetValue(True)
- self.SetNext(self.parent.datumpage)
- # self.parent.sumpage.SetPrev(self.parent.datumpage)
- radioSBSizer.Add(self.radio1, flag=wx.ALIGN_LEFT | wx.RIGHT, border=20)
- radioSBSizer.Add(self.radioEpsg, flag=wx.ALIGN_LEFT)
- # bindings
- self.Bind(wx.EVT_RADIOBUTTON, self.SetVal, id=self.radio1.GetId())
- self.Bind(wx.EVT_RADIOBUTTON, self.SetVal, id=self.radioEpsg.GetId())
- self.Bind(wiz.EVT_WIZARD_PAGE_CHANGING, self.OnPageChange)
- self.Bind(wiz.EVT_WIZARD_PAGE_CHANGED, self.OnEnterPage)
- def OnParamEntry(self, event):
- """Parameter value changed"""
- id = event.GetId()
- val = event.GetString()
- if id not in self.pparam:
- event.Skip()
- return
- param = self.pparam[id]
- win = self.FindWindowById(id)
- if param["type"] == "zone":
- val = self.FindWindowById(id).GetValue()
- if val < 1:
- win.SetValue(1)
- elif val > 60:
- win.SetValue(60)
- if param["type"] == "bool":
- param["value"] = event.GetSelection()
- else:
- param["value"] = val
- event.Skip()
- def OnPageChange(self, event=None):
- """Go to next page"""
- if event.GetDirection():
- self.p4projparams = ""
- for id, param in six.iteritems(self.pparam):
- if param["type"] == "bool":
- if param["value"] is False:
- continue
- else:
- self.p4projparams += " +" + param["proj4"]
- else:
- if param["value"] is None:
- wx.MessageBox(
- parent=self,
- message=_("You must enter a value for %s") % param["desc"],
- caption=_("Error"),
- style=wx.ICON_ERROR | wx.CENTRE,
- )
- event.Veto()
- else:
- self.p4projparams += (
- " +" + param["proj4"] + "=" + str(param["value"])
- )
- def OnEnterPage(self, event):
- """Page entered"""
- self.projdesc = self.parent.projections[self.parent.projpage.proj][0]
- if self.prjParamSizer is None:
- # entering page for the first time
- self.paramSBox = StaticBox(
- parent=self,
- id=wx.ID_ANY,
- label=_(" Enter parameters for %s projection ") % self.projdesc,
- )
- paramSBSizer = wx.StaticBoxSizer(self.paramSBox)
- self.panel = scrolled.ScrolledPanel(parent=self, id=wx.ID_ANY)
- self.panel.SetupScrolling()
- self.prjParamSizer = wx.GridBagSizer(vgap=0, hgap=0)
- self.sizer.Add(paramSBSizer, pos=(1, 1), flag=wx.EXPAND)
- self.sizer.AddGrowableRow(1)
- paramSBSizer.Add(self.panel, proportion=1, flag=wx.EXPAND)
- paramSBSizer.Fit(self.panel)
- self.panel.SetSizer(self.prjParamSizer)
- if event.GetDirection():
- self.prjParamSizer.Clear(True)
- self.paramSBox.SetLabel(
- _(" Enter parameters for %s projection ") % self.projdesc
- )
- self.pparam = dict()
- row = 0
- for paramgrp in self.parent.projections[self.parent.projpage.proj][1]:
- # get parameters
- id = NewId()
- param = self.pparam[id] = {
- "type": self.parent.paramdesc[paramgrp[0]][0],
- "proj4": self.parent.paramdesc[paramgrp[0]][1],
- "desc": self.parent.paramdesc[paramgrp[0]][2],
- }
- # default values
- if param["type"] == "bool":
- param["value"] = 0
- elif param["type"] == "zone":
- param["value"] = 30
- param["desc"] += " (1-60)"
- else:
- param["value"] = paramgrp[2]
- label = StaticText(
- parent=self.panel,
- id=wx.ID_ANY,
- label=param["desc"],
- style=wx.ALIGN_RIGHT | wx.ST_NO_AUTORESIZE,
- )
- if param["type"] == "bool":
- win = wx.Choice(
- parent=self.panel,
- id=id,
- size=(100, -1),
- choices=[_("No"), _("Yes")],
- )
- win.SetSelection(param["value"])
- win.Bind(wx.EVT_CHOICE, self.OnParamEntry)
- elif param["type"] == "zone":
- win = SpinCtrl(
- parent=self.panel,
- id=id,
- size=(100, -1),
- style=wx.SP_ARROW_KEYS | wx.SP_WRAP,
- min=1,
- max=60,
- )
- win.SetValue(param["value"])
- win.Bind(wx.EVT_SPINCTRL, self.OnParamEntry)
- win.Bind(wx.EVT_TEXT, self.OnParamEntry)
- else:
- win = TextCtrl(
- parent=self.panel, id=id, value=param["value"], size=(100, -1)
- )
- win.Bind(wx.EVT_TEXT, self.OnParamEntry)
- if paramgrp[1] == "noask":
- win.Enable(False)
- self.prjParamSizer.Add(
- label,
- pos=(row, 1),
- flag=wx.ALIGN_RIGHT | wx.ALIGN_CENTER_VERTICAL | wx.RIGHT,
- border=5,
- )
- self.prjParamSizer.Add(
- win,
- pos=(row, 2),
- flag=wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL | wx.LEFT,
- border=5,
- )
- row += 1
- self.panel.SetSize(self.panel.GetBestSize())
- self.panel.Layout()
- self.Layout()
- self.Update()
- if not wx.FindWindowById(wx.ID_FORWARD).IsEnabled():
- wx.FindWindowById(wx.ID_FORWARD).Enable()
- event.Skip()
- def SetVal(self, event):
- """Set value"""
- if event.GetId() == self.radio1.GetId():
- self.SetNext(self.parent.datumpage)
- self.parent.sumpage.SetPrev(self.parent.datumpage)
- elif event.GetId() == self.radioEpsg.GetId():
- self.SetNext(self.parent.ellipsepage)
- self.parent.sumpage.SetPrev(self.parent.ellipsepage)
- class DatumPage(TitledPage):
- """Wizard page for selecting datum (with associated ellipsoid)
- and datum transformation parameters (select coordinate system option)
- """
- def __init__(self, wizard, parent):
- TitledPage.__init__(self, wizard, _("Specify geodetic datum"))
- self.sizer = wx.GridBagSizer(vgap=0, hgap=0)
- self.sizer.SetCols(5)
- self.sizer.SetRows(8)
- self.parent = parent
- self.datum = ""
- self.datumdesc = ""
- self.ellipse = ""
- self.datumparams = ""
- self.proj4params = ""
- # text input
- self.tdatum = self.MakeTextCtrl("", size=(200, -1))
- # search box
- self.searchb = SearchCtrl(self, size=(200, -1), style=wx.TE_PROCESS_ENTER)
- self.searchb.ShowCancelButton(True)
- # create list control for datum/elipsoid list
- data = []
- for key in self.parent.datums.keys():
- data.append([key, self.parent.datums[key][0], self.parent.datums[key][1]])
- self.datumlist = ItemList(
- self, data=data, columns=[_("Code"), _("Ellipsoid"), _("Description")]
- )
- self.datumlist.resizeLastColumn(10)
- # layout
- self.sizer.Add(
- self.MakeLabel(_("Datum code:")),
- flag=wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL | wx.ALL,
- border=5,
- pos=(1, 1),
- )
- self.sizer.Add(
- self.tdatum,
- flag=wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL | wx.ALL,
- border=5,
- pos=(1, 2),
- )
- self.sizer.Add(
- self.MakeLabel(_("Search in description:")),
- flag=wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL | wx.ALL,
- border=5,
- pos=(2, 1),
- )
- self.sizer.Add(
- self.searchb,
- flag=wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL | wx.ALL,
- border=5,
- pos=(2, 2),
- )
- self.sizer.Add(
- self.datumlist,
- flag=wx.EXPAND | wx.ALIGN_LEFT | wx.ALL,
- border=5,
- pos=(3, 1),
- span=(1, 4),
- )
- self.sizer.AddGrowableCol(4)
- self.sizer.AddGrowableRow(3)
- # events
- self.datumlist.Bind(wx.EVT_LIST_ITEM_SELECTED, self.OnDatumSelected)
- self.searchb.Bind(wx.EVT_TEXT, self.OnDSearch)
- self.searchb.Bind(search_cancel_evt, self.OnSearchCancel)
- self.tdatum.Bind(wx.EVT_TEXT, self.OnDText)
- self.Bind(wiz.EVT_WIZARD_PAGE_CHANGING, self.OnPageChanging)
- self.Bind(wiz.EVT_WIZARD_PAGE_CHANGED, self.OnEnterPage)
- # do page layout
- # self.DoLayout()
- def OnPageChanging(self, event):
- self.proj4params = ""
- proj = self.parent.projpage.p4proj
- if event.GetDirection():
- if self.datum not in self.parent.datums:
- event.Veto()
- else:
- # check for datum tranforms
- # proj4string = self.parent.CreateProj4String()
- # + ' +datum=%s' % self.datum
- ret = RunCommand(
- "g.proj",
- read=True,
- proj4="%s" % proj,
- datum="%s" % self.datum,
- datum_trans="-1",
- flags="t",
- )
- # wx.Messagebox('here')
- if ret != "":
- dtrans = ""
- # open a dialog to select datum transform number
- dlg = SelectTransformDialog(self.parent.parent, transforms=ret)
- if dlg.ShowModal() == wx.ID_OK:
- dtrans = dlg.GetTransform()
- if dtrans == "":
- dlg.Destroy()
- event.Veto()
- return "Datum transform is required."
- else:
- dlg.Destroy()
- event.Veto()
- return "Datum transform is required."
- self.parent.datum_trans = dtrans
- self.GetNext().SetPrev(self)
- self.parent.ellipsepage.ellipse = self.ellipse
- self.parent.ellipsepage.ellipseparams = self.parent.ellipsoids[
- self.ellipse
- ][1]
- def OnEnterPage(self, event):
- self.parent.datum_trans = None
- if event.GetDirection():
- if len(self.datum) == 0:
- # disable 'next' button by default when entering from previous
- # page
- wx.FindWindowById(wx.ID_FORWARD).Enable(False)
- else:
- wx.FindWindowById(wx.ID_FORWARD).Enable(True)
- event.Skip()
- def OnDText(self, event):
- """Datum code changed"""
- self.datum = event.GetString()
- nextButton = wx.FindWindowById(wx.ID_FORWARD)
- if len(self.datum) == 0 or self.datum not in self.parent.datums:
- nextButton.Enable(False)
- else:
- self.ellipse = self.parent.datums[self.datum][0]
- self.datumdesc = self.parent.datums[self.datum][1]
- self.datumparams = self.parent.datums[self.datum][2]
- try:
- self.datumparams.remove("dx=0.0")
- except:
- pass
- try:
- self.datumparams.remove("dy=0.0")
- except:
- pass
- try:
- self.datumparams.remove("dz=0.0")
- except:
- pass
- nextButton.Enable(True)
- self.Update()
- event.Skip()
- def OnDSearch(self, event):
- """Search geodetic datum by desc"""
- search_str = self.searchb.GetValue()
- try:
- self.datum, self.ellipsoid, self.datumdesc = self.datumlist.Search(
- index=[0, 1, 2], pattern=search_str
- )
- except:
- self.datum = self.datumdesc = self.ellipsoid = ""
- event.Skip()
- def OnSearchCancel(self, event):
- self.datumlist.Search(index=None, pattern="")
- event.Skip()
- def OnDatumSelected(self, event):
- """Datum selected"""
- index = event.GetIndex()
- self.datum = self.datumlist.GetItem(index, 0).GetText()
- self.tdatum.SetValue(self.datum)
- event.Skip()
- class EllipsePage(TitledPage):
- """Wizard page for selecting ellipsoid (select coordinate system option)"""
- def __init__(self, wizard, parent):
- TitledPage.__init__(self, wizard, _("Specify ellipsoid"))
- self.sizer = wx.GridBagSizer(vgap=0, hgap=0)
- self.sizer.SetCols(5)
- self.sizer.SetRows(8)
- self.parent = parent
- self.ellipse = ""
- self.ellipsedesc = ""
- self.ellipseparams = ""
- self.proj4params = ""
- # text input
- self.tellipse = self.MakeTextCtrl("", size=(200, -1))
- # search box
- self.searchb = SearchCtrl(self, size=(200, -1), style=wx.TE_PROCESS_ENTER)
- self.searchb.ShowCancelButton(True)
- # radio buttons
- self.radio1 = wx.RadioButton(
- parent=self, id=wx.ID_ANY, label=_("Earth based"), style=wx.RB_GROUP
- )
- self.radioEpsg = wx.RadioButton(
- parent=self, id=wx.ID_ANY, label=_("Planetary bodies")
- )
- # create list control for ellipse list
- data = []
- # extract code, desc
- for key in self.parent.ellipsoids.keys():
- data.append([key, self.parent.ellipsoids[key][0]])
- self.ellipselist = ItemList(
- self, data=data, columns=[_("Code"), _("Description")]
- )
- self.ellipselist.resizeLastColumn(30)
- # layout
- self.sizer.Add(
- self.MakeLabel(_("Ellipsoid code:")),
- flag=wx.ALIGN_RIGHT | wx.ALIGN_CENTER_VERTICAL | wx.ALL,
- border=5,
- pos=(1, 1),
- )
- self.sizer.Add(
- self.tellipse,
- flag=wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL | wx.ALL,
- border=5,
- pos=(1, 2),
- )
- self.sizer.Add(
- self.radio1,
- flag=wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL | wx.LEFT,
- border=25,
- pos=(1, 3),
- )
- self.sizer.Add(
- self.MakeLabel(_("Search in description:")),
- flag=wx.ALIGN_RIGHT | wx.ALIGN_CENTER_VERTICAL | wx.ALL,
- border=5,
- pos=(2, 1),
- )
- self.sizer.Add(
- self.searchb,
- flag=wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL | wx.ALL,
- border=5,
- pos=(2, 2),
- )
- self.sizer.Add(
- self.radioEpsg,
- flag=wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL | wx.LEFT,
- border=25,
- pos=(2, 3),
- )
- self.sizer.Add(
- self.ellipselist,
- flag=wx.EXPAND | wx.ALIGN_LEFT | wx.ALL,
- border=5,
- pos=(3, 1),
- span=(1, 4),
- )
- self.sizer.AddGrowableCol(4)
- self.sizer.AddGrowableRow(3)
- # events
- self.ellipselist.Bind(wx.EVT_LIST_ITEM_SELECTED, self.OnItemSelected)
- self.tellipse.Bind(wx.EVT_TEXT, self.OnText)
- self.searchb.Bind(wx.EVT_TEXT, self.OnSearch)
- self.searchb.Bind(search_cancel_evt, self.OnSearchCancel)
- self.radio1.Bind(wx.EVT_RADIOBUTTON, self.SetVal, id=self.radio1.GetId())
- self.radioEpsg.Bind(wx.EVT_RADIOBUTTON, self.SetVal, id=self.radioEpsg.GetId())
- self.Bind(wiz.EVT_WIZARD_PAGE_CHANGED, self.OnEnterPage)
- self.Bind(wiz.EVT_WIZARD_PAGE_CHANGING, self.OnPageChanging)
- def OnEnterPage(self, event):
- if len(self.ellipse) == 0:
- # disable 'next' button by default
- wx.FindWindowById(wx.ID_FORWARD).Enable(False)
- else:
- wx.FindWindowById(wx.ID_FORWARD).Enable(True)
- self.scope = "earth"
- event.Skip()
- def OnPageChanging(self, event):
- if (
- event.GetDirection()
- and self.ellipse not in self.parent.ellipsoids
- and self.ellipse not in self.parent.planetary_ellipsoids
- ):
- event.Veto()
- # print self.ellipse, self.ellipsedesc, self.ellipseparams
- self.proj4params = ""
- self.GetNext().SetPrev(self)
- self.parent.datumpage.datumparams = ""
- # self.GetNext().SetPrev(self) (???)
- # FIXME: index number doesn't translate when you've given a valid name
- # from the other list
- def OnText(self, event):
- """Ellipspoid code changed"""
- self.ellipse = event.GetString()
- nextButton = wx.FindWindowById(wx.ID_FORWARD)
- if len(self.ellipse) == 0 or (
- self.ellipse not in self.parent.ellipsoids
- and self.ellipse not in self.parent.planetary_ellipsoids
- ):
- nextButton.Enable(False)
- self.ellipsedesc = ""
- self.ellipseparams = ""
- self.proj4params = ""
- elif self.ellipse in self.parent.ellipsoids:
- self.ellipsedesc = self.parent.ellipsoids[self.ellipse][0]
- self.ellipseparams = self.parent.ellipsoids[self.ellipse][1]
- nextButton.Enable(True)
- elif self.ellipse in self.parent.planetary_ellipsoids:
- self.ellipsedesc = self.parent.planetary_ellipsoids[self.ellipse][0]
- self.ellipseparams = self.parent.planetary_ellipsoids[self.ellipse][1]
- nextButton.Enable(True)
- # print self.ellipse, self.ellipsedesc, self.ellipseparams
- def OnSearch(self, event):
- """Search ellipsoid by desc"""
- try:
- self.ellipse, self.ellipsedesc = self.ellipselist.Search(
- index=[0, 1], pattern=event.GetString()
- )
- if self.scope == "earth":
- self.ellipseparams = self.parent.ellipsoids[self.ellipse][1]
- else:
- self.ellipseparams = self.parent.planetary_ellipsoids[self.ellipse][1]
- except:
- self.ellipse = self.ellipsedesc = self.ellipseparams = ""
- event.Skip()
- def OnSearchCancel(self, event):
- self.ellipselist.Search(index=None, pattern="")
- event.Skip()
- def OnItemSelected(self, event):
- """Ellipsoid selected"""
- index = event.GetIndex()
- self.ellipse = self.ellipselist.GetItem(index, 0).GetText()
- self.tellipse.SetValue(self.ellipse)
- event.Skip()
- def SetVal(self, event):
- """Choose table to use"""
- self.ellipselist.DeleteAllItems()
- data = []
- if event.GetId() == self.radio1.GetId():
- self.scope = "earth"
- for key in self.parent.ellipsoids.keys():
- data.append([key, self.parent.ellipsoids[key][0]])
- elif event.GetId() == self.radioEpsg.GetId():
- self.scope = "planetary"
- for key in self.parent.planetary_ellipsoids.keys():
- data.append([key, self.parent.planetary_ellipsoids[key][0]])
- self.ellipselist.Populate(data=data, update=True)
- class GeoreferencedFilePage(TitledPage):
- """Wizard page for selecting georeferenced file to use
- for setting coordinate system parameters"""
- def __init__(self, wizard, parent):
- TitledPage.__init__(self, wizard, _("Read CRS from a georeferenced data file"))
- self.sizer = wx.GridBagSizer(vgap=0, hgap=0)
- self.sizer.SetCols(5)
- self.sizer.SetRows(8)
- # create variables
- self.georeffile = ""
- # create controls
- self.lfile = self.MakeLabel(_("Georeferenced file:"))
- self.tfile = self.MakeTextCtrl(size=(300, -1))
- self.bbrowse = self.MakeButton(_("Browse"))
- # do layout
- self.sizer.Add(
- self.lfile,
- flag=wx.ALIGN_LEFT | wx.ALIGN_CENTRE_VERTICAL | wx.ALL,
- border=5,
- pos=(1, 1),
- )
- self.sizer.Add(
- self.tfile,
- flag=wx.ALIGN_LEFT | wx.ALIGN_CENTRE_VERTICAL | wx.ALL,
- border=5,
- pos=(1, 2),
- )
- self.sizer.Add(self.bbrowse, flag=wx.ALIGN_LEFT | wx.ALL, border=5, pos=(1, 3))
- self.sizer.AddGrowableCol(3)
- self.bbrowse.Bind(wx.EVT_BUTTON, self.OnBrowse)
- self.tfile.Bind(wx.EVT_TEXT, self.OnText)
- self.Bind(wiz.EVT_WIZARD_PAGE_CHANGING, self.OnPageChanging)
- self.Bind(wiz.EVT_WIZARD_PAGE_CHANGED, self.OnEnterPage)
- # do page layout
- # self.DoLayout()
- def OnEnterPage(self, event):
- if len(self.georeffile) == 0:
- # disable 'next' button by default
- wx.FindWindowById(wx.ID_FORWARD).Enable(False)
- else:
- wx.FindWindowById(wx.ID_FORWARD).Enable(True)
- event.Skip()
- def OnPageChanging(self, event):
- if event.GetDirection() and not os.path.isfile(self.georeffile):
- event.Veto()
- self.GetNext().SetPrev(self)
- def OnText(self, event):
- """File changed"""
- self.georeffile = event.GetString()
- nextButton = wx.FindWindowById(wx.ID_FORWARD)
- if len(self.georeffile) > 0 and os.path.isfile(self.georeffile):
- if not nextButton.IsEnabled():
- nextButton.Enable(True)
- else:
- if nextButton.IsEnabled():
- nextButton.Enable(False)
- event.Skip()
- def OnBrowse(self, event):
- """Choose file"""
- dlg = wx.FileDialog(
- self, _("Select georeferenced file"), os.getcwd(), "", "*.*", wx.FD_OPEN
- )
- if dlg.ShowModal() == wx.ID_OK:
- path = dlg.GetPath()
- self.tfile.SetValue(path)
- dlg.Destroy()
- event.Skip()
- class WKTPage(TitledPage):
- """Wizard page for selecting WKT file to use
- for setting coordinate system parameters"""
- def __init__(self, wizard, parent):
- TitledPage.__init__(self, wizard, _("Specify CRS using WKT string"))
- self.sizer = wx.GridBagSizer(vgap=0, hgap=0)
- self.sizer.SetCols(5)
- self.sizer.SetRows(8)
- self.wktstring = ""
- self.parent = parent
- # widgets
- self.text_wkt = self.MakeTextCtrl(size=(400, 200), style=wx.TE_MULTILINE)
- self.label_wkt = self.MakeLabel(_("Enter WKT parameters string:"))
- # layout
- self.sizer.Add(
- self.label_wkt, flag=wx.ALIGN_LEFT | wx.ALL, border=5, pos=(1, 1)
- )
- self.sizer.Add(
- self.text_wkt,
- flag=wx.ALIGN_LEFT | wx.ALL | wx.EXPAND,
- border=5,
- pos=(2, 1),
- span=(1, 2),
- )
- self.sizer.AddGrowableRow(2)
- self.sizer.AddGrowableCol(2)
- self.text_wkt.Bind(wx.EVT_TEXT, self.OnText)
- self.Bind(wiz.EVT_WIZARD_PAGE_CHANGING, self.OnPageChanging)
- self.Bind(wiz.EVT_WIZARD_PAGE_CHANGED, self.OnEnterPage)
- def OnEnterPage(self, event):
- if len(self.wktstring) == 0:
- # disable 'next' button by default
- wx.FindWindowById(wx.ID_FORWARD).Enable(False)
- else:
- wx.FindWindowById(wx.ID_FORWARD).Enable(True)
- event.Skip()
- def OnPageChanging(self, event):
- if event.GetDirection() and not self.wktstring.strip():
- event.Veto()
- self.GetNext().SetPrev(self)
- def OnText(self, event):
- """Change WKT string"""
- # TODO: check WKT syntax
- self.wktstring = event.GetString()
- nextButton = wx.FindWindowById(wx.ID_FORWARD)
- if len(self.wktstring) == 0:
- if nextButton.IsEnabled():
- nextButton.Enable(False)
- else:
- if not nextButton.IsEnabled():
- nextButton.Enable()
- class EPSGPage(TitledPage):
- """Wizard page for selecting EPSG code for
- setting coordinate system parameters"""
- def __init__(self, wizard, parent):
- TitledPage.__init__(self, wizard, _("Select CRS from a list"))
- self.sizer = wx.BoxSizer(wx.VERTICAL)
- searchBoxSizer = wx.BoxSizer(wx.HORIZONTAL)
- epsglistBoxSizer = wx.BoxSizer(wx.HORIZONTAL)
- informationBoxSizer = wx.BoxSizer(wx.HORIZONTAL)
- # definition of variables
- self.parent = parent
- self.epsgCodeDict = {}
- self.epsgcode = None
- self.epsgdesc = ""
- self.epsgparams = ""
- # labels
- self.lcode = self.MakeLabel(
- _("Filter by EPSG code or description:"),
- style=wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL,
- )
- self.llink = self.MakeLabel(
- _("Find more information at:"),
- style=wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL,
- )
- # search box
- self.searchb = SearchCtrl(self, size=(-1, 30), style=wx.TE_PROCESS_ENTER)
- self.searchb.ShowCancelButton(True)
- self.epsglist = ItemList(
- self, data=None, columns=[_("Code"), _("Description"), _("Parameters")]
- )
- # epsg.io hyperlink
- self.tlink = HyperlinkCtrl(
- self, id=wx.ID_ANY, label="epsg.io", url="https://epsg.io/"
- )
- self.tlink.SetNormalColour(wx.SystemSettings.GetColour(wx.SYS_COLOUR_GRAYTEXT))
- self.tlink.SetVisitedColour(wx.SystemSettings.GetColour(wx.SYS_COLOUR_GRAYTEXT))
- # layout
- searchBoxSizer.Add(
- self.lcode, proportion=0, flag=wx.ALIGN_CENTER_VERTICAL | wx.ALL, border=5
- )
- searchBoxSizer.Add(
- self.searchb, proportion=1, flag=wx.ALL | wx.EXPAND, border=5
- )
- epsglistBoxSizer.Add(
- self.epsglist, proportion=1, flag=wx.ALL | wx.EXPAND, border=5
- )
- informationBoxSizer.AddStretchSpacer(1)
- informationBoxSizer.Add(
- self.llink, proportion=0, flag=wx.ALIGN_CENTER_VERTICAL | wx.RIGHT, border=5
- )
- informationBoxSizer.Add(self.tlink, proportion=0, flag=wx.ALIGN_CENTER_VERTICAL)
- self.sizer.Add(searchBoxSizer, proportion=0, flag=wx.EXPAND)
- self.sizer.Add(epsglistBoxSizer, proportion=1, flag=wx.EXPAND)
- self.sizer.Add(
- informationBoxSizer, proportion=0, flag=wx.EXPAND | wx.TOP, border=5
- )
- # events
- self.searchb.Bind(wx.EVT_TEXT, self.OnTextChange)
- self.epsglist.Bind(wx.EVT_LIST_ITEM_SELECTED, self.OnItemSelected)
- self.searchb.Bind(search_cancel_evt, self.OnSearchCancel)
- self.Bind(wiz.EVT_WIZARD_PAGE_CHANGING, self.OnPageChanging)
- self.Bind(wiz.EVT_WIZARD_PAGE_CHANGED, self.OnEnterPage)
- def OnEnterPage(self, event):
- self.parent.datum_trans = None
- if event.GetDirection():
- if not self.epsgcode:
- # disable 'next' button by default
- self.EnableNext(False)
- # load default epsg database file
- self.OnBrowseCodes(None)
- else:
- self.EnableNext(True)
- event.Skip()
- def OnPageChanging(self, event):
- if event.GetDirection():
- if not self.epsgcode:
- event.Veto()
- return
- else:
- # check for datum transforms
- ret = RunCommand(
- "g.proj", read=True, epsg=self.epsgcode, datum_trans="-1", flags="t"
- )
- if ret != "":
- dtrans = ""
- # open a dialog to select datum transform number
- dlg = SelectTransformDialog(self.parent.parent, transforms=ret)
- if dlg.ShowModal() == wx.ID_OK:
- dtrans = dlg.GetTransform()
- if dtrans == "":
- dlg.Destroy()
- event.Veto()
- return "Datum transform is required."
- else:
- dlg.Destroy()
- event.Veto()
- return "Datum transform is required."
- self.parent.datum_trans = dtrans
- self.GetNext().SetPrev(self)
- def EnableNext(self, enable=True):
- nextButton = wx.FindWindowById(wx.ID_FORWARD)
- nextButton.Enable(enable)
- def OnTextChange(self, event):
- value = self.searchb.GetValue()
- if value == "":
- self.tlink.SetURL(str("https://epsg.io/"))
- self.epsgcode = None
- self.epsgdesc = self.epsgparams = ""
- self.searchb.ChangeValue("")
- self.OnBrowseCodes(None)
- self.EnableNext(False)
- else:
- self.tlink.SetURL(str("https://epsg.io/?q={0}".format(value)))
- data = self.epsglist.Search(index=[0, 1, 2], pattern=value, firstOnly=False)
- if data:
- index = 0
- # search for the exact epsg code match
- # otherwise just select first item
- try:
- epsg = int(value)
- for i, (code, desc, params) in enumerate(data):
- if code == epsg:
- index = i
- break
- except ValueError:
- pass
- self.epsgcode, self.epsgdesc, self.epsgparams = data[index]
- self.epsglist.Select(index)
- self.epsglist.Focus(index)
- self.EnableNext()
- else:
- self.epsgcode = None
- self.epsgdesc = self.epsgparams = ""
- self.EnableNext(False)
- event.Skip()
- def OnItemSelected(self, event):
- """EPSG code selected from the list"""
- index = event.GetIndex()
- self.epsgcode = int(self.epsglist.GetItem(index, 0).GetText())
- self.epsgdesc = self.epsglist.GetItem(index, 1).GetText()
- self.EnableNext(True)
- event.Skip()
- def OnSearchCancel(self, event):
- self.epsglist.Search(index=None, pattern="")
- event.Skip()
- def OnBrowseCodes(self, event, search=None):
- """Browse EPSG codes"""
- try:
- self.epsgCodeDict = utils.ReadEpsgCodes()
- except OpenError as e:
- GError(
- parent=self,
- message=_("Unable to read EPGS codes: {0}").format(e),
- showTraceback=False,
- )
- self.epsglist.Populate(list(), update=True)
- return
- data = list()
- for code, val in six.iteritems(self.epsgCodeDict):
- if code is not None:
- data.append((code, val[0], val[1]))
- self.epsglist.Populate(data, update=True)
- class IAUPage(TitledPage):
- """Wizard page for selecting IAU code/WKT for
- setting coordinate system parameters"""
- def __init__(self, wizard, parent):
- TitledPage.__init__(self, wizard, _("Choose IAU Code"))
- # grid definition
- self.sizer = wx.GridBagSizer(vgap=0, hgap=0)
- self.sizer.SetCols(5)
- self.sizer.SetRows(8)
- # definition of variables
- self.parent = parent
- self.epsgCodeDict = {}
- self.epsgcode = None
- self.epsgdesc = ""
- self.epsgparams = ""
- # labels
- self.lfile = self.MakeLabel(
- _("Path to the IAU-codes file:"),
- style=wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL,
- )
- self.lcode = self.MakeLabel(
- _("IAU code:"), style=wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL
- )
- # text input
- epsgdir = utils.PathJoin(globalvar.ETCDIR, "proj", "ogr_csv", "iau2009.csv")
- self.tfile = self.MakeTextCtrl(
- text=epsgdir, size=(200, -1), style=wx.TE_PROCESS_ENTER
- )
- self.tcode = self.MakeTextCtrl(size=(200, -1))
- # buttons
- self.bbrowse = self.MakeButton(_("Browse"))
- # search box
- self.searchb = SearchCtrl(self, size=(200, -1), style=wx.TE_PROCESS_ENTER)
- self.searchb.ShowCancelButton(True)
- self.epsglist = ItemList(
- self, data=None, columns=[_("Code"), _("Description"), _("Parameters")]
- )
- # layout
- self.sizer.Add(
- self.lfile,
- flag=wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL | wx.ALL,
- border=5,
- pos=(1, 1),
- span=(1, 2),
- )
- self.sizer.Add(
- self.tfile,
- flag=wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL | wx.ALL,
- border=5,
- pos=(1, 3),
- )
- self.sizer.Add(
- self.bbrowse,
- flag=wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL | wx.ALL,
- border=5,
- pos=(1, 4),
- )
- self.sizer.Add(
- self.lcode,
- flag=wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL | wx.ALL,
- border=5,
- pos=(2, 1),
- span=(1, 2),
- )
- self.sizer.Add(
- self.tcode,
- flag=wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL | wx.ALL,
- border=5,
- pos=(2, 3),
- )
- self.sizer.Add(
- self.searchb,
- flag=wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL | wx.ALL,
- border=5,
- pos=(3, 3),
- )
- self.sizer.Add(
- self.epsglist, flag=wx.ALIGN_LEFT | wx.EXPAND, pos=(4, 1), span=(1, 4)
- )
- self.sizer.AddGrowableCol(3)
- self.sizer.AddGrowableRow(4)
- # events
- self.bbrowse.Bind(wx.EVT_BUTTON, self.OnBrowse)
- self.tfile.Bind(wx.EVT_TEXT_ENTER, self.OnBrowseCodes)
- self.tcode.Bind(wx.EVT_TEXT, self.OnText)
- self.epsglist.Bind(wx.EVT_LIST_ITEM_SELECTED, self.OnItemSelected)
- self.searchb.Bind(wx.EVT_TEXT, self.OnSearch)
- self.searchb.Bind(search_cancel_evt, self.OnSearchCancel)
- self.Bind(wiz.EVT_WIZARD_PAGE_CHANGING, self.OnPageChanging)
- self.Bind(wiz.EVT_WIZARD_PAGE_CHANGED, self.OnEnterPage)
- def OnEnterPage(self, event):
- self.parent.datum_trans = None
- if event.GetDirection():
- if not self.epsgcode:
- # disable 'next' button by default
- wx.FindWindowById(wx.ID_FORWARD).Enable(False)
- else:
- wx.FindWindowById(wx.ID_FORWARD).Enable(True)
- # load default epsg database file
- self.OnBrowseCodes(None)
- event.Skip()
- def OnPageChanging(self, event):
- if event.GetDirection():
- if not self.epsgcode:
- event.Veto()
- return
- else:
- # check for datum transforms
- ret = RunCommand(
- "g.proj",
- read=True,
- proj4=self.epsgparams,
- datum_trans="-1",
- flags="t",
- )
- if ret != "":
- dtrans = ""
- # open a dialog to select datum transform number
- dlg = SelectTransformDialog(self.parent.parent, transforms=ret)
- if dlg.ShowModal() == wx.ID_OK:
- dtrans = dlg.GetTransform()
- if dtrans == "":
- dlg.Destroy()
- event.Veto()
- return "Datum transform is required."
- else:
- dlg.Destroy()
- event.Veto()
- return "Datum transform is required."
- self.parent.datum_trans = dtrans
- self.parent.epsgcode = self.epsgcode
- self.parent.epsgdesc = self.epsgdesc
- # prepare +nadgrids or +towgs84 terms for Summary page. first
- # convert them:
- ret, projlabel, err = RunCommand(
- "g.proj",
- flags="jft",
- proj4=self.epsgparams,
- datum_trans=self.parent.datum_trans,
- getErrorMsg=True,
- read=True,
- )
- # splitting on space alone would break for grid files with
- # space in pathname
- for projterm in projlabel.split(" +"):
- if (
- projterm.find("towgs84=") != -1
- or projterm.find("nadgrids=") != -1
- ):
- self.custom_dtrans_string = " +%s" % projterm
- break
- self.GetNext().SetPrev(self)
- def OnText(self, event):
- self.epsgcode = event.GetString()
- try:
- self.epsgcode = int(self.epsgcode)
- except:
- self.epsgcode = None
- nextButton = wx.FindWindowById(wx.ID_FORWARD)
- # if self.epsgcode and self.epsgcode in self.epsgCodeDict.keys():
- if self.epsgcode:
- self.epsgdesc = self.epsgCodeDict[self.epsgcode][0]
- self.epsgparams = self.epsgCodeDict[self.epsgcode][1]
- if not nextButton.IsEnabled():
- nextButton.Enable(True)
- else:
- self.epsgcode = None # not found
- if nextButton.IsEnabled():
- nextButton.Enable(False)
- self.epsgdesc = self.epsgparams = ""
- def OnSearch(self, event):
- value = self.searchb.GetValue()
- if value == "":
- self.epsgcode = None
- self.epsgdesc = self.epsgparams = ""
- self.tcode.SetValue("")
- self.searchb.SetValue("")
- self.OnBrowseCodes(None)
- else:
- try:
- self.epsgcode, self.epsgdesc, self.epsgparams = self.epsglist.Search(
- index=[0, 1, 2], pattern=value
- )
- except (IndexError, ValueError): # -> no item found
- self.epsgcode = None
- self.epsgdesc = self.epsgparams = ""
- self.tcode.SetValue("")
- event.Skip()
- def OnSearchCancel(self, event):
- self.epsglist.Search(index=None, pattern="")
- event.Skip()
- def OnBrowse(self, event):
- """Define path for IAU code file"""
- path = os.path.dirname(self.tfile.GetValue())
- if not path:
- path = os.getcwd()
- dlg = wx.FileDialog(
- parent=self,
- message=_("Choose IAU codes file"),
- defaultDir=path,
- defaultFile="",
- wildcard="*",
- style=wx.FD_OPEN,
- )
- if dlg.ShowModal() == wx.ID_OK:
- path = dlg.GetPath()
- self.tfile.SetValue(path)
- self.OnBrowseCodes(None)
- dlg.Destroy()
- event.Skip()
- def OnItemSelected(self, event):
- """IAU code selected from the list"""
- index = event.GetIndex()
- self.epsgcode = int(self.epsglist.GetItem(index, 0).GetText())
- # This is here that the index 2 (aka WKT) should be loaded in a
- # variable
- self.epsgdesc = self.epsglist.GetItem(index, 1).GetText()
- self.tcode.SetValue(str(self.epsgcode))
- event.Skip()
- def OnBrowseCodes(self, event, search=None):
- """Browse IAU codes"""
- try:
- self.epsgCodeDict = utils.ReadEpsgCodes()
- except OpenError as e:
- GError(
- parent=self,
- message=_("Unable to read IAU codes: {0}").format(e),
- showTraceback=False,
- )
- self.epsglist.Populate(list(), update=True)
- return
- data = list()
- for code, val in six.iteritems(self.epsgCodeDict):
- if code is not None:
- data.append((code, val[0], val[1]))
- self.epsglist.Populate(data, update=True)
- class CustomPage(TitledPage):
- """Wizard page for entering custom PROJ.4 string
- for setting coordinate system parameters"""
- def __init__(self, wizard, parent):
- TitledPage.__init__(self, wizard, _("Specify CRS using PROJ.4 string"))
- global coordsys
- # grid definition
- self.sizer = wx.GridBagSizer(vgap=0, hgap=0)
- self.sizer.SetCols(5)
- self.sizer.SetRows(8)
- # definition of variables
- self.customstring = ""
- self.parent = parent
- # widgets
- self.text_proj4string = self.MakeTextCtrl(
- size=(400, 200), style=wx.TE_MULTILINE
- )
- self.label_proj4string = self.MakeLabel(_("Enter PROJ.4 parameters string:"))
- # layout
- self.sizer.Add(
- self.label_proj4string, flag=wx.ALIGN_LEFT | wx.ALL, border=5, pos=(1, 1)
- )
- self.sizer.Add(
- self.text_proj4string,
- flag=wx.ALIGN_LEFT | wx.ALL | wx.EXPAND,
- border=5,
- pos=(2, 1),
- span=(1, 2),
- )
- self.sizer.AddGrowableRow(2)
- self.sizer.AddGrowableCol(2)
- self.text_proj4string.Bind(wx.EVT_TEXT, self.GetProjstring)
- self.Bind(wiz.EVT_WIZARD_PAGE_CHANGING, self.OnPageChanging)
- self.Bind(wiz.EVT_WIZARD_PAGE_CHANGED, self.OnEnterPage)
- def OnEnterPage(self, event):
- if len(self.customstring) == 0:
- # disable 'next' button by default
- wx.FindWindowById(wx.ID_FORWARD).Enable(False)
- else:
- wx.FindWindowById(wx.ID_FORWARD).Enable(True)
- def OnPageChanging(self, event):
- if event.GetDirection():
- self.custom_dtrans_string = ""
- if self.customstring.find("+datum=") < 0:
- self.GetNext().SetPrev(self)
- return
- # check for datum tranforms
- # FIXME: -t flag is a hack-around for trac bug #1849
- ret, out, err = RunCommand(
- "g.proj",
- read=True,
- getErrorMsg=True,
- proj4=self.customstring,
- datum_trans="-1",
- flags="t",
- )
- if ret != 0:
- wx.MessageBox(
- parent=self,
- message=err,
- caption=_("Error"),
- style=wx.OK | wx.ICON_ERROR | wx.CENTRE,
- )
- event.Veto()
- return
- if out:
- dtrans = ""
- # open a dialog to select datum transform number
- dlg = SelectTransformDialog(self.parent.parent, transforms=out)
- if dlg.ShowModal() == wx.ID_OK:
- dtrans = dlg.GetTransform()
- if dtrans == "":
- dlg.Destroy()
- event.Veto()
- return _("Datum transform is required.")
- else:
- dlg.Destroy()
- event.Veto()
- return _("Datum transform is required.")
- self.parent.datum_trans = dtrans
- # prepare +nadgrids or +towgs84 terms for Summary page. first
- # convert them:
- ret, projlabel, err = RunCommand(
- "g.proj",
- flags="jft",
- proj4=self.customstring,
- datum_trans=dtrans,
- getErrorMsg=True,
- read=True,
- )
- # splitting on space alone would break for grid files with
- # space in pathname
- for projterm in projlabel.split(" +"):
- if (
- projterm.find("towgs84=") != -1
- or projterm.find("nadgrids=") != -1
- ):
- self.custom_dtrans_string = " +%s" % projterm
- break
- self.GetNext().SetPrev(self)
- def GetProjstring(self, event):
- """Change proj string"""
- # TODO: check PROJ.4 syntax
- self.customstring = event.GetString()
- nextButton = wx.FindWindowById(wx.ID_FORWARD)
- if len(self.customstring) == 0:
- if nextButton.IsEnabled():
- nextButton.Enable(False)
- else:
- if not nextButton.IsEnabled():
- nextButton.Enable()
- class SummaryPage(TitledPage):
- """Shows summary result of choosing coordinate system parameters
- prior to creating location"""
- def __init__(self, wizard, parent):
- TitledPage.__init__(self, wizard, _("Summary"))
- # grid definition
- self.sizer = wx.GridBagSizer(vgap=0, hgap=0)
- self.sizer.SetCols(5)
- self.sizer.SetRows(8)
- # definition of variables
- self.parent = parent
- # panels
- self.panelTitle = scrolled.ScrolledPanel(parent=self, id=wx.ID_ANY)
- self.panelProj4string = scrolled.ScrolledPanel(parent=self, id=wx.ID_ANY)
- self.panelProj = scrolled.ScrolledPanel(parent=self, id=wx.ID_ANY)
- # labels
- self.ldatabase = self.MakeLabel()
- self.llocation = self.MakeLabel()
- self.llocTitle = self.MakeLabel(parent=self.panelTitle)
- self.lprojection = self.MakeLabel(parent=self.panelProj)
- self.lproj4string = self.MakeLabel(parent=self.panelProj4string)
- self.Bind(wiz.EVT_WIZARD_PAGE_CHANGED, self.OnEnterPage)
- # do sub-page layout
- self._doLayout()
- def _doLayout(self):
- """Do page layout"""
- titleSizer = wx.BoxSizer(wx.VERTICAL)
- titleSizer.Add(self.llocTitle, proportion=1, flag=wx.EXPAND | wx.ALL, border=5)
- self.panelTitle.SetSizer(titleSizer)
- projSizer = wx.BoxSizer(wx.VERTICAL)
- projSizer.Add(self.lprojection, proportion=1, flag=wx.EXPAND | wx.ALL, border=5)
- self.panelProj.SetSizer(projSizer)
- proj4stringSizer = wx.BoxSizer(wx.VERTICAL)
- proj4stringSizer.Add(
- self.lproj4string, proportion=1, flag=wx.EXPAND | wx.ALL, border=5
- )
- self.panelProj4string.SetSizer(proj4stringSizer)
- self.panelProj4string.SetupScrolling()
- self.panelProj.SetupScrolling()
- self.panelTitle.SetupScrolling(scroll_y=False)
- self.sizer.Add(
- self.MakeLabel(_("GRASS Database:")),
- flag=wx.ALIGN_LEFT | wx.ALL,
- border=5,
- pos=(1, 0),
- )
- self.sizer.Add(
- self.ldatabase, flag=wx.ALIGN_LEFT | wx.ALL, border=5, pos=(1, 1)
- )
- self.sizer.Add(
- self.MakeLabel(_("Location Name:")),
- flag=wx.ALIGN_LEFT | wx.ALL,
- border=5,
- pos=(2, 0),
- )
- self.sizer.Add(
- self.llocation, flag=wx.ALIGN_LEFT | wx.ALL, border=5, pos=(2, 1)
- )
- self.sizer.Add(
- self.MakeLabel(_("Description:")),
- flag=wx.ALIGN_LEFT | wx.ALL,
- border=5,
- pos=(3, 0),
- )
- self.sizer.Add(
- self.panelTitle,
- flag=wx.ALIGN_LEFT | wx.ALL | wx.EXPAND,
- border=0,
- pos=(3, 1),
- )
- self.sizer.Add(
- self.MakeLabel(_("Projection:")),
- flag=wx.ALIGN_LEFT | wx.ALL,
- border=5,
- pos=(4, 0),
- )
- self.sizer.Add(
- self.panelProj,
- flag=wx.ALIGN_LEFT | wx.ALL | wx.EXPAND,
- border=0,
- pos=(4, 1),
- )
- self.sizer.Add(
- self.MakeLabel(_("PROJ.4 definition:\n (non-definitive)")),
- flag=wx.ALIGN_LEFT | wx.ALL,
- border=5,
- pos=(5, 0),
- )
- self.sizer.Add(
- self.panelProj4string,
- flag=wx.ALIGN_LEFT | wx.ALL | wx.EXPAND,
- border=0,
- pos=(5, 1),
- )
- self.sizer.AddGrowableCol(1)
- self.sizer.AddGrowableRow(4, 1)
- self.sizer.AddGrowableRow(5, 5)
- def OnEnterPage(self, event):
- """Insert values into text controls for summary of location
- creation options
- """
- database = self.parent.startpage.grassdatabase
- location = self.parent.startpage.location
- proj4string = self.parent.CreateProj4String()
- iauproj4string = self.parent.iaupage.epsgparams
- epsgcode = self.parent.epsgpage.epsgcode
- datum = self.parent.datumpage.datum
- dtrans = self.parent.datum_trans
- global coordsys
- # print coordsys,proj4string
- if coordsys in ("proj", "epsg", "iau", "wkt", "file"):
- extra_opts = {}
- extra_opts["location"] = "location"
- extra_opts["getErrorMsg"] = True
- extra_opts["read"] = True
- if coordsys == "proj":
- if len(datum) > 0:
- extra_opts["datum"] = "%s" % datum
- extra_opts["datum_trans"] = dtrans
- ret, projlabel, err = RunCommand(
- "g.proj", flags="jf", proj4=proj4string, **extra_opts
- )
- elif coordsys == "iau":
- if len(datum) > 0:
- extra_opts["datum"] = "%s" % datum
- extra_opts["datum_trans"] = dtrans
- ret, projlabel, err = RunCommand(
- "g.proj", flags="jf", proj4=iauproj4string, **extra_opts
- )
- elif coordsys == "epsg":
- ret, projlabel, err = RunCommand(
- "g.proj",
- flags="jft",
- epsg=epsgcode,
- datum_trans=dtrans,
- **extra_opts,
- )
- elif coordsys == "file":
- ret, projlabel, err = RunCommand(
- "g.proj",
- flags="jft",
- georef=self.parent.filepage.georeffile,
- **extra_opts,
- )
- elif coordsys == "wkt":
- ret, projlabel, err = RunCommand(
- "g.proj",
- flags="jft",
- wkt="-",
- stdin=self.parent.wktpage.wktstring,
- **extra_opts,
- )
- finishButton = wx.FindWindowById(wx.ID_FORWARD)
- if ret == 0:
- if datum != "":
- projlabel = projlabel + "+datum=%s" % datum
- self.lproj4string.SetLabel(projlabel.replace(" +", os.linesep + "+"))
- finishButton.Enable(True)
- else:
- GError(err, parent=self)
- self.lproj4string.SetLabel("")
- finishButton.Enable(False)
- projdesc = self.parent.projpage.projdesc
- ellipsedesc = self.parent.ellipsepage.ellipsedesc
- datumdesc = self.parent.datumpage.datumdesc
- # print projdesc,ellipsedesc,datumdesc
- self.ldatabase.SetLabel(database)
- self.llocation.SetLabel(location)
- self.llocTitle.SetLabel(self.parent.startpage.locTitle)
- label = ""
- if coordsys == "epsg":
- label = "EPSG code %s (%s)" % (
- self.parent.epsgpage.epsgcode,
- self.parent.epsgpage.epsgdesc,
- )
- elif coordsys == "iau":
- label = "IAU code %s (%s)" % (
- self.parent.iaupage.epsgcode,
- self.parent.iaupage.epsgdesc,
- )
- elif coordsys == "file":
- label = "matches file %s" % self.parent.filepage.georeffile
- elif coordsys == "wkt":
- label = "matches WKT string %s" % self.parent.wktpage.wktstring
- elif coordsys == "proj":
- label = "%s, %s %s" % (projdesc, datumdesc, ellipsedesc)
- elif coordsys == "xy":
- label = "XY coordinate system (not projected)."
- self.lproj4string.SetLabel("")
- elif coordsys == "custom":
- label = _("custom")
- combo_str = (
- self.parent.custompage.customstring
- + self.parent.custompage.custom_dtrans_string
- )
- self.lproj4string.SetLabel(
- ("%s" % combo_str.replace(" +", os.linesep + "+"))
- )
- self.lprojection.SetLabel(label)
- class LocationWizard(wx.Object):
- """Start wizard here and finish wizard here"""
- def __init__(self, parent, grassdatabase):
- self.__cleanUp()
- global coordsys
- self.parent = parent
- #
- # get georeferencing information from tables in $GISBASE/etc
- #
- self.__readData()
- #
- # datum transform number and list of datum transforms
- #
- self.datum_trans = None
- self.proj4string = ""
- # file from which new location is created
- self.georeffile = None
- # additional settings
- self.default_region = False
- self.user_mapset = False
- #
- # define wizard pages
- #
- self.wizard = WizardWithHelpButton(
- parent, id=wx.ID_ANY, title=_("Define new GRASS Location")
- )
- self.wizard.Bind(wiz.EVT_WIZARD_HELP, self.OnHelp)
- self.startpage = DatabasePage(self.wizard, self, grassdatabase)
- self.csystemspage = CoordinateSystemPage(self.wizard, self)
- self.projpage = ProjectionsPage(self.wizard, self)
- self.datumpage = DatumPage(self.wizard, self)
- self.paramspage = ProjParamsPage(self.wizard, self)
- self.epsgpage = EPSGPage(self.wizard, self)
- self.iaupage = IAUPage(self.wizard, self)
- self.filepage = GeoreferencedFilePage(self.wizard, self)
- self.wktpage = WKTPage(self.wizard, self)
- self.ellipsepage = EllipsePage(self.wizard, self)
- self.custompage = CustomPage(self.wizard, self)
- self.sumpage = SummaryPage(self.wizard, self)
- #
- # set the initial order of the pages
- # (should follow the epsg line)
- #
- self.startpage.SetNext(self.csystemspage)
- self.csystemspage.SetPrev(self.startpage)
- self.csystemspage.SetNext(self.sumpage)
- self.projpage.SetPrev(self.csystemspage)
- self.projpage.SetNext(self.paramspage)
- self.paramspage.SetPrev(self.projpage)
- self.paramspage.SetNext(self.datumpage)
- self.datumpage.SetPrev(self.paramspage)
- self.datumpage.SetNext(self.sumpage)
- self.ellipsepage.SetPrev(self.paramspage)
- self.ellipsepage.SetNext(self.sumpage)
- self.epsgpage.SetPrev(self.csystemspage)
- self.epsgpage.SetNext(self.sumpage)
- self.iaupage.SetPrev(self.csystemspage)
- self.iaupage.SetNext(self.sumpage)
- self.filepage.SetPrev(self.csystemspage)
- self.filepage.SetNext(self.sumpage)
- self.wktpage.SetPrev(self.csystemspage)
- self.wktpage.SetNext(self.sumpage)
- self.custompage.SetPrev(self.csystemspage)
- self.custompage.SetNext(self.sumpage)
- self.sumpage.SetPrev(self.csystemspage)
- #
- # do pages layout
- #
- self.startpage.DoLayout()
- self.csystemspage.DoLayout()
- self.projpage.DoLayout()
- self.datumpage.DoLayout()
- self.paramspage.DoLayout()
- self.epsgpage.DoLayout()
- self.iaupage.DoLayout()
- self.filepage.DoLayout()
- self.wktpage.DoLayout()
- self.ellipsepage.DoLayout()
- self.custompage.DoLayout()
- self.sumpage.DoLayout()
- self.wizard.FitToPage(self.datumpage)
- size = self.wizard.GetPageSize()
- self.wizard.SetPageSize((size[0], size[1] + 75))
- # new location created?
- self.location = None
- # location created in different GIS database?
- self.altdb = False
- #
- # run wizard...
- #
- if self.wizard.RunWizard(self.startpage):
- msg = self.OnWizFinished()
- if not msg:
- self.wizard.Destroy()
- self.location = self.startpage.location
- self.grassdatabase = self.startpage.grassdatabase
- self.georeffile = self.filepage.georeffile
- # FIXME here was code for setting default region, what for is this if:
- # if self.altdb == False:
- else: # -> error
- self.wizard.Destroy()
- GError(
- parent=self.parent,
- message="%s"
- % _(
- "Unable to create new location. "
- "Location <%(loc)s> not created.\n\n"
- "Details: %(err)s"
- )
- % {"loc": self.startpage.location, "err": msg},
- )
- else: # -> canceled
- self.wizard.Destroy()
- self.__cleanUp()
- def __cleanUp(self):
- global coordsys
- global north
- global south
- global east
- global west
- global resolution
- global wizerror
- global translist
- coordsys = None
- north = None
- south = None
- east = None
- west = None
- resolution = None
- def __readData(self):
- """Get georeferencing information from tables in $GISBASE/etc/proj"""
- # read projection and parameters
- f = open(os.path.join(globalvar.ETCDIR, "proj", "parms.table"), "r")
- self.projections = {}
- self.projdesc = {}
- for line in f.readlines():
- line = line.strip()
- try:
- proj, projdesc, params = line.split(":")
- paramslist = params.split(";")
- plist = []
- for p in paramslist:
- if p == "":
- continue
- p1, pdefault = p.split(",")
- pterm, pask = p1.split("=")
- p = [pterm.strip(), pask.strip(), pdefault.strip()]
- plist.append(p)
- self.projections[proj.lower().strip()] = (projdesc.strip(), plist)
- self.projdesc[proj.lower().strip()] = projdesc.strip()
- except:
- continue
- f.close()
- # read datum definitions
- f = open(os.path.join(globalvar.ETCDIR, "proj", "datum.table"), "r")
- self.datums = {}
- paramslist = []
- for line in f.readlines():
- line = line.expandtabs(1)
- line = line.strip()
- if line == "" or line[0] == "#":
- continue
- datum, info = line.split(" ", 1)
- info = info.strip()
- datumdesc, params = info.split(" ", 1)
- datumdesc = datumdesc.strip('"')
- paramlist = params.split()
- ellipsoid = paramlist.pop(0)
- self.datums[datum] = (ellipsoid, datumdesc.replace("_", " "), paramlist)
- f.close()
- # read Earth-based ellipsiod definitions
- f = open(os.path.join(globalvar.ETCDIR, "proj", "ellipse.table"), "r")
- self.ellipsoids = {}
- for line in f.readlines():
- line = line.expandtabs(1)
- line = line.strip()
- if line == "" or line[0] == "#":
- continue
- ellipse, rest = line.split(" ", 1)
- rest = rest.strip('" ')
- desc, params = rest.split('"', 1)
- desc = desc.strip('" ')
- paramslist = params.split()
- self.ellipsoids[ellipse] = (desc, paramslist)
- f.close()
- # read Planetary ellipsiod definitions
- f = open(
- os.path.join(globalvar.ETCDIR, "proj", "ellipse.table.solar.system"), "r"
- )
- self.planetary_ellipsoids = {}
- for line in f.readlines():
- line = line.expandtabs(1)
- line = line.strip()
- if line == "" or line[0] == "#":
- continue
- ellipse, rest = line.split(" ", 1)
- rest = rest.strip('" ')
- desc, params = rest.split('"', 1)
- desc = desc.strip('" ')
- paramslist = params.split()
- self.planetary_ellipsoids[ellipse] = (desc, paramslist)
- f.close()
- # read projection parameter description and parsing table
- f = open(os.path.join(globalvar.ETCDIR, "proj", "desc.table"), "r")
- self.paramdesc = {}
- for line in f.readlines():
- line = line.strip()
- try:
- pparam, datatype, proj4term, desc = line.split(":")
- self.paramdesc[pparam] = (datatype, proj4term, desc)
- except:
- continue
- f.close()
- def OnWizFinished(self):
- """Wizard finished, create new location
- :return: error message on error
- :return: None on success
- """
- database = self.startpage.grassdatabase
- location = self.startpage.location
- # location already exists?
- if os.path.isdir(os.path.join(database, location)):
- GError(
- parent=self.wizard,
- message="%s <%s>: %s"
- % (
- _("Unable to create new location"),
- os.path.join(database, location),
- _("Location already exists in GRASS Database."),
- ),
- )
- return None
- # current GISDbase or a new one?
- current_gdb = decode(grass.gisenv()["GISDBASE"])
- if current_gdb != database:
- # change to new GISDbase or create new one
- if not os.path.isdir(database):
- # create new directory
- try:
- os.mkdir(database)
- except OSError as error:
- GError(
- parent=self.wizard,
- message=_(
- "Unable to create new GRASS Database <{path}>: {error}"
- ).format(path=database, error=error),
- )
- return None
- # location created in alternate GISDbase
- self.altdb = True
- global coordsys
- try:
- if coordsys == "xy":
- grass.create_location(
- dbase=self.startpage.grassdatabase,
- location=self.startpage.location,
- desc=self.startpage.locTitle,
- )
- elif coordsys == "proj":
- grass.create_location(
- dbase=self.startpage.grassdatabase,
- location=self.startpage.location,
- proj4=self.CreateProj4String(),
- datum=self.datumpage.datum,
- datum_trans=self.datum_trans,
- desc=self.startpage.locTitle,
- )
- elif coordsys == "custom":
- addl_opts = {}
- if self.datum_trans is not None:
- addl_opts["datum_trans"] = self.datum_trans
- grass.create_location(
- dbase=self.startpage.grassdatabase,
- location=self.startpage.location,
- proj4=self.custompage.customstring,
- desc=self.startpage.locTitle,
- **addl_opts,
- )
- elif coordsys == "epsg":
- if not self.epsgpage.epsgcode:
- return _("EPSG code missing.")
- grass.create_location(
- dbase=self.startpage.grassdatabase,
- location=self.startpage.location,
- epsg=self.epsgpage.epsgcode,
- datum=self.datumpage.datum,
- datum_trans=self.datum_trans,
- desc=self.startpage.locTitle,
- )
- elif coordsys == "iau":
- if not self.iaupage.epsgcode:
- return _("IAU code missing.")
- grass.create_location(
- dbase=self.startpage.grassdatabase,
- location=self.startpage.location,
- proj4=self.iaupage.epsgparams,
- datum=self.datumpage.datum,
- datum_trans=self.datum_trans,
- desc=self.startpage.locTitle,
- )
- elif coordsys == "file":
- if not self.filepage.georeffile or not os.path.isfile(
- self.filepage.georeffile
- ):
- return _("File <%s> not found." % self.filepage.georeffile)
- grass.create_location(
- dbase=self.startpage.grassdatabase,
- location=self.startpage.location,
- filename=self.filepage.georeffile,
- desc=self.startpage.locTitle,
- )
- elif coordsys == "wkt":
- if not self.wktpage.wktstring:
- return _("WKT string missing.")
- grass.create_location(
- dbase=self.startpage.grassdatabase,
- location=self.startpage.location,
- wkt=self.wktpage.wktstring,
- desc=self.startpage.locTitle,
- )
- except grass.ScriptError as e:
- return e.value
- return None
- def CreateProj4String(self):
- """Constract PROJ.4 string"""
- proj = self.projpage.p4proj
- proj4params = self.paramspage.p4projparams
- datumparams = self.datumpage.datumparams
- ellipseparams = self.ellipsepage.ellipseparams
- #
- # creating PROJ.4 string
- #
- proj4string = "%s %s" % (proj, proj4params)
- # set ellipsoid parameters
- for item in ellipseparams:
- if item[:4] == "f=1/":
- item = " +rf=" + item[4:]
- else:
- item = " +" + item
- proj4string = "%s %s" % (proj4string, item)
- # set datum transform parameters if relevant
- if datumparams:
- for item in datumparams:
- proj4string = "%s +%s" % (proj4string, item)
- proj4string = "%s +no_defs" % proj4string
- return proj4string
- def OnHelp(self, event):
- """'Help' button clicked"""
- # help text in lib/init/helptext.html
- RunCommand("g.manual", entry="helptext")
- class WizardWithHelpButton(Wizard):
- def __init__(self, parent, id, title):
- if globalvar.wxPythonPhoenix:
- Wizard.__init__(self)
- self.SetExtraStyle(wx.adv.WIZARD_EX_HELPBUTTON)
- self.Create(parent=parent, id=id, title=title)
- else:
- pre = wiz.PreWizard()
- pre.SetExtraStyle(wx.wizard.WIZARD_EX_HELPBUTTON)
- pre.Create(parent=parent, id=id, title=title)
- self.PostCreate(pre)
|