1 |
# Copyright (c) 2003 by Intevation GmbH |
# Copyright (c) 2003, 2004 by Intevation GmbH |
2 |
# Authors: |
# Authors: |
3 |
# Jonathan Coles <[email protected]> |
# Jonathan Coles <[email protected]> |
4 |
# Frank Koormann <[email protected]> |
# Frank Koormann <[email protected]> |
21 |
from Thuban.Model.proj import Projection, ProjFile |
from Thuban.Model.proj import Projection, ProjFile |
22 |
|
|
23 |
from Thuban.Model.resource import get_user_proj_file, get_system_proj_file, \ |
from Thuban.Model.resource import get_user_proj_file, get_system_proj_file, \ |
24 |
read_proj_file, write_proj_file |
read_proj_file, write_proj_file, \ |
25 |
|
DEFAULT_PROJ_FILE, EPSG_PROJ_FILE, \ |
26 |
|
EPSG_DEPRECATED_PROJ_FILE |
27 |
from Thuban.UI.dialogs import NonModalNonParentDialog |
from Thuban.UI.dialogs import NonModalNonParentDialog |
28 |
|
|
29 |
from common import ThubanBeginBusyCursor, ThubanEndBusyCursor |
from common import ThubanBeginBusyCursor, ThubanEndBusyCursor |
62 |
("tmerc", _("Transverse Mercator"), TMPanel), |
("tmerc", _("Transverse Mercator"), TMPanel), |
63 |
("utm", _("Universal Transverse Mercator"), UTMPanel), |
("utm", _("Universal Transverse Mercator"), UTMPanel), |
64 |
("lcc", _("Lambert Conic Conformal"), LCCPanel), |
("lcc", _("Lambert Conic Conformal"), LCCPanel), |
65 |
("latlong", _("Geographic"), GeoPanel)] |
("latlong", _("Geographic"), GeoPanel), |
66 |
|
("longlat", _("Geographic"), GeoPanel)]#longlat is an alias of proj |
67 |
self.receiver = receiver |
self.receiver = receiver |
68 |
self.haveTried = False |
self.haveTried = False |
69 |
self.curProjPanel = None |
self.curProjPanel = None |
70 |
self.__usrProjFile = None |
self.__usrProjFile = None |
71 |
self.__sysProjFile = None |
self._sys_proj_files = {} |
72 |
|
|
73 |
self.build_dialog() |
self.build_dialog() |
74 |
self.Layout() |
self.Layout() |
76 |
self.originalProjection = self.receiver.GetProjection() |
self.originalProjection = self.receiver.GetProjection() |
77 |
|
|
78 |
self.projection_list.SelectProjection(self.originalProjection) |
self.projection_list.SelectProjection(self.originalProjection) |
|
self.button_ok.SetFocus() |
|
79 |
self.projection_list.SetFocus() |
self.projection_list.SetFocus() |
80 |
|
|
81 |
def build_dialog(self): |
def build_dialog(self): |
96 |
|
|
97 |
hbox = wxBoxSizer(wxHORIZONTAL) |
hbox = wxBoxSizer(wxHORIZONTAL) |
98 |
vbox.Add(hbox, 1, wxALL|wxEXPAND) |
vbox.Add(hbox, 1, wxALL|wxEXPAND) |
99 |
self.projection_list = ProjectionList(self, self.load_system_proj(), |
proj_files = [self.load_user_proj(), |
100 |
self.load_user_proj(), |
self.load_system_proj(DEFAULT_PROJ_FILE)] |
101 |
|
self.projection_list = ProjectionList(self, proj_files, |
102 |
self.receiver.GetProjection()) |
self.receiver.GetProjection()) |
103 |
hbox.Add(self.projection_list, 1, wxALL|wxEXPAND|wxADJUST_MINSIZE, 4) |
hbox.Add(self.projection_list, 1, wxALL|wxEXPAND|wxADJUST_MINSIZE, 4) |
104 |
self.projection_list.Subscribe(PROJ_SELECTION_CHANGED, |
self.projection_list.Subscribe(PROJ_SELECTION_CHANGED, |
113 |
self.button_export = wxButton(self, ID_PROJ_EXPORT, _("Export...")) |
self.button_export = wxButton(self, ID_PROJ_EXPORT, _("Export...")) |
114 |
EVT_BUTTON(self, ID_PROJ_EXPORT, self._OnExport) |
EVT_BUTTON(self, ID_PROJ_EXPORT, self._OnExport) |
115 |
buttons.Add(self.button_export, 1, wxALL|wxEXPAND, 4) |
buttons.Add(self.button_export, 1, wxALL|wxEXPAND, 4) |
116 |
buttons.Add(20, 20, 0, wxEXPAND, 0) |
buttons.Add( (20, 20), 0, wxEXPAND, 0) |
117 |
self.button_remove = wxButton(self, ID_PROJ_REMOVE, _("Remove")) |
self.button_remove = wxButton(self, ID_PROJ_REMOVE, _("Remove")) |
118 |
EVT_BUTTON(self, ID_PROJ_REMOVE, self._OnRemove) |
EVT_BUTTON(self, ID_PROJ_REMOVE, self._OnRemove) |
119 |
buttons.Add(self.button_remove, 1, wxALL|wxEXPAND, 4) |
buttons.Add(self.button_remove, 1, wxALL|wxEXPAND, 4) |
120 |
|
|
121 |
|
buttons.Add( (20, 20), 0, wxEXPAND, 0) |
122 |
|
label = wxStaticText(self, -1, _("Show EPSG:")) |
123 |
|
buttons.Add(label, 0, wxLEFT|wxRIGHT|wxTOP, 4) |
124 |
|
self.check_epsg = wxCheckBox(self, -1, _("Normal")) |
125 |
|
EVT_CHECKBOX(self, self.check_epsg.GetId(), self._OnShowEPSG) |
126 |
|
buttons.Add(self.check_epsg, 1, wxALL|wxEXPAND, 4) |
127 |
|
self.check_epsg_depr = wxCheckBox(self, -1, _("Deprecated")) |
128 |
|
EVT_CHECKBOX(self, self.check_epsg_depr.GetId(), self._OnShowEPSG) |
129 |
|
buttons.Add(self.check_epsg_depr, 1, wxALL|wxEXPAND, 4) |
130 |
|
|
131 |
# The file path |
# The file path |
132 |
self.projfilepath = wxStaticText(self, -1, "") |
self.projfilepath = wxStaticText(self, -1, "") |
133 |
vbox.Add(self.projfilepath, 0, wxALL|wxEXPAND) |
vbox.Add(self.projfilepath, 0, wxALL|wxEXPAND) |
186 |
self.button_add = wxButton(self, ID_PROJ_ADDTOLIST, _("Add to List")) |
self.button_add = wxButton(self, ID_PROJ_ADDTOLIST, _("Add to List")) |
187 |
EVT_BUTTON(self, ID_PROJ_ADDTOLIST, self._OnAddToList) |
EVT_BUTTON(self, ID_PROJ_ADDTOLIST, self._OnAddToList) |
188 |
buttons.Add(self.button_add, 0, wxEXPAND|wxALL, 4) |
buttons.Add(self.button_add, 0, wxEXPAND|wxALL, 4) |
189 |
buttons.Add(20, 20, 0, wxEXPAND, 0) |
buttons.Add( (20, 20), 0, wxEXPAND, 0) |
190 |
self.button_save = wxButton(self, ID_PROJ_SAVE,_("Update")) |
self.button_save = wxButton(self, ID_PROJ_SAVE,_("Update")) |
191 |
EVT_BUTTON(self, ID_PROJ_SAVE, self._OnSave) |
EVT_BUTTON(self, ID_PROJ_SAVE, self._OnSave) |
192 |
buttons.Add(self.button_save, 0, wxEXPAND|wxALL|wxALIGN_BOTTOM, 4) |
buttons.Add(self.button_save, 0, wxEXPAND|wxALL|wxALIGN_BOTTOM, 4) |
222 |
def OnClose(self, event): |
def OnClose(self, event): |
223 |
self.projection_list.Unsubscribe(PROJ_SELECTION_CHANGED, |
self.projection_list.Unsubscribe(PROJ_SELECTION_CHANGED, |
224 |
self.proj_selection_changed) |
self.proj_selection_changed) |
225 |
|
# Destroy the projection list explicitly so that it properly |
226 |
|
# unsubscribes everything. It would be cleaner if the projection |
227 |
|
# could do this by itself but wx doesn't always send destroy |
228 |
|
# events for non-top-level widgets |
229 |
|
self.projection_list.Destroy() |
230 |
NonModalNonParentDialog.OnClose(self, event) |
NonModalNonParentDialog.OnClose(self, event) |
231 |
|
|
232 |
def OnApply(self, event): |
def OnApply(self, event): |
303 |
add them to the user ProjFile object and write the user file |
add them to the user ProjFile object and write the user file |
304 |
back to disk. |
back to disk. |
305 |
""" |
""" |
306 |
dlg = wxFileDialog(self, _("Import"), style = wxOPEN) |
dlg = wxFileDialog(self, _("Import"), |
307 |
|
self.parent.application.Path("projection"), style = wxOPEN) |
308 |
|
|
309 |
if dlg.ShowModal() == wxID_OK: |
if dlg.ShowModal() == wxID_OK: |
310 |
path = dlg.GetPath() |
path = dlg.GetPath() |
320 |
for proj in projFile.GetProjections(): |
for proj in projFile.GetProjections(): |
321 |
self.__usrProjFile.Add(proj) |
self.__usrProjFile.Add(proj) |
322 |
self.write_proj_file(self.__usrProjFile) |
self.write_proj_file(self.__usrProjFile) |
323 |
|
self.parent.application.SetPath("projection", path) |
324 |
finally: |
finally: |
325 |
ThubanEndBusyCursor() |
ThubanEndBusyCursor() |
326 |
dlg.Destroy() |
dlg.Destroy() |
334 |
sel = self.projection_list.selected_projections() |
sel = self.projection_list.selected_projections() |
335 |
assert len(sel) != 0, "button should be disabled" |
assert len(sel) != 0, "button should be disabled" |
336 |
|
|
337 |
dlg = wxFileDialog(self, _("Export"), style=wxSAVE|wxOVERWRITE_PROMPT) |
dlg = wxFileDialog(self, _("Export"), |
338 |
|
self.parent.application.Path("projection"), |
339 |
|
style=wxSAVE|wxOVERWRITE_PROMPT) |
340 |
|
|
341 |
if dlg.ShowModal() == wxID_OK: |
if dlg.ShowModal() == wxID_OK: |
342 |
proj_file = ProjFile(dlg.GetPath()) |
proj_file = ProjFile(dlg.GetPath()) |
344 |
if proj is not None: |
if proj is not None: |
345 |
proj_file.Add(proj) |
proj_file.Add(proj) |
346 |
self.write_proj_file(proj_file) |
self.write_proj_file(proj_file) |
347 |
|
self.parent.application.SetPath("projection", dlg.GetPath()) |
348 |
|
|
349 |
dlg.Destroy() |
dlg.Destroy() |
350 |
|
|
367 |
if modified: |
if modified: |
368 |
self.write_proj_file(self.__usrProjFile) |
self.write_proj_file(self.__usrProjFile) |
369 |
|
|
370 |
|
def _OnShowEPSG(self, event): |
371 |
|
"""Handler for the EVT_CHECKBOX events from the EPSG check button |
372 |
|
|
373 |
|
If the button is checked add the EPSG_PROJ_FILE to the list of |
374 |
|
projfiles shown by the projection list. Otherwise remove it |
375 |
|
""" |
376 |
|
proj_files = [self.load_user_proj(), |
377 |
|
self.load_system_proj(DEFAULT_PROJ_FILE)] |
378 |
|
if self.check_epsg.IsChecked(): |
379 |
|
proj_files.append(self.load_system_proj(EPSG_PROJ_FILE)) |
380 |
|
if self.check_epsg_depr.IsChecked(): |
381 |
|
proj_files.append(self.load_system_proj(EPSG_DEPRECATED_PROJ_FILE)) |
382 |
|
self.projection_list.SetProjFiles(proj_files) |
383 |
|
|
384 |
def _OnProjName(self, event): |
def _OnProjName(self, event): |
385 |
self.__VerifyButtons() |
self.__VerifyButtons() |
386 |
|
|
496 |
self.projchoice.Select(0) |
self.projchoice.Select(0) |
497 |
self.projchoice.Disable() |
self.projchoice.Disable() |
498 |
self._show_proj_panel(UnknownProjPanel) |
self._show_proj_panel(UnknownProjPanel) |
499 |
|
assert self.curProjPanel is not None |
500 |
|
self.curProjPanel.SetProjection(proj) |
501 |
else: |
else: |
502 |
self.projfilepath.SetLabel(_("Multiple Projections selected")) |
self.projfilepath.SetLabel(_("Multiple Projections selected")) |
503 |
|
|
530 |
def _show_proj_panel(self, panel_class): |
def _show_proj_panel(self, panel_class): |
531 |
"""Show the panel as the projection panel""" |
"""Show the panel as the projection panel""" |
532 |
if panel_class is UnknownProjPanel: |
if panel_class is UnknownProjPanel: |
533 |
|
self.button_ok.Disable() |
534 |
|
self.button_try.Disable() |
535 |
self.edit_box.Disable() |
self.edit_box.Disable() |
536 |
self.nbsizer.Activate(self.unknown_projection_panel) |
self.nbsizer.Activate(self.unknown_projection_panel) |
537 |
self.curProjPanel = self.unknown_projection_panel |
self.curProjPanel = self.unknown_projection_panel |
538 |
else: |
else: |
539 |
|
self.button_ok.Enable(True) |
540 |
|
self.button_try.Enable(True) |
541 |
self.edit_box.Enable(True) |
self.edit_box.Enable(True) |
542 |
self.unknown_projection_panel.Hide() |
self.unknown_projection_panel.Hide() |
543 |
for panel in self.projection_panels: |
for panel in self.projection_panels: |
573 |
# self.curProjPanel should always contain the most relevant data |
# self.curProjPanel should always contain the most relevant data |
574 |
# for a projection |
# for a projection |
575 |
if self.curProjPanel is not None: |
if self.curProjPanel is not None: |
576 |
return Projection(self.curProjPanel.GetParameters(), |
parameters = self.curProjPanel.GetParameters() |
577 |
self.projname.GetValue()) |
if parameters is not None: |
578 |
|
return Projection(parameters, self.projname.GetValue()) |
579 |
|
|
580 |
return None |
return None |
581 |
|
|
582 |
def load_user_proj(self): |
def load_user_proj(self): |
583 |
ThubanBeginBusyCursor() |
"""Return the user's ProjFile |
584 |
try: |
|
585 |
if self.__usrProjFile is None: |
If the file has not yet been loaded by the dialog, load it first |
586 |
|
with get_user_proj_file and cache it in self.__usrProjFile. |
587 |
|
|
588 |
|
Show a busy cursor while loading the file. |
589 |
|
|
590 |
|
If the file is not available, leave a note to the console. |
591 |
|
""" |
592 |
|
if self.__usrProjFile is None: |
593 |
|
ThubanBeginBusyCursor() |
594 |
|
try: |
595 |
projfile, warnings = get_user_proj_file() |
projfile, warnings = get_user_proj_file() |
596 |
self.show_warnings(_("Warnings"), projfile.GetFilename(), |
if warnings: |
597 |
warnings) |
sys.stderr.write("".join(warnings)) |
598 |
|
sys.stderr.write("\n") |
599 |
self.__usrProjFile = projfile |
self.__usrProjFile = projfile |
600 |
return self.__usrProjFile |
finally: |
601 |
finally: |
ThubanEndBusyCursor() |
602 |
ThubanEndBusyCursor() |
return self.__usrProjFile |
603 |
|
|
604 |
def load_system_proj(self): |
def load_system_proj(self, name): |
605 |
ThubanBeginBusyCursor() |
"""Load the system ProjFile with the given name. |
606 |
try: |
|
607 |
if self.__sysProjFile is None: |
If the file has not been loaded yet, load it first with |
608 |
projfile, warnings = get_system_proj_file() |
get_system_proj_file and put it into the cache. The name is |
609 |
|
simply forwarded to get_system_proj_file. |
610 |
|
|
611 |
|
Show a busy cursor while loading the file. |
612 |
|
""" |
613 |
|
if name not in self._sys_proj_files: |
614 |
|
ThubanBeginBusyCursor() |
615 |
|
try: |
616 |
|
projfile, warnings = get_system_proj_file(name) |
617 |
self.show_warnings(_("Warnings"), projfile.GetFilename(), |
self.show_warnings(_("Warnings"), projfile.GetFilename(), |
618 |
warnings) |
warnings) |
619 |
self.__sysProjFile = projfile |
self._sys_proj_files[name] = projfile |
620 |
return self.__sysProjFile |
finally: |
621 |
finally: |
ThubanEndBusyCursor() |
622 |
ThubanEndBusyCursor() |
return self._sys_proj_files[name] |
623 |
|
|
624 |
def write_proj_file(self, proj_file): |
def write_proj_file(self, proj_file): |
625 |
"""Write the ProjFile object proj_file back to its file |
"""Write the ProjFile object proj_file back to its file |
713 |
def __init__(self, parent, receiver): |
def __init__(self, parent, receiver): |
714 |
ProjPanel.__init__(self, parent) |
ProjPanel.__init__(self, parent) |
715 |
|
|
716 |
|
self.__text = _("Thuban does not know the parameters\n" |
717 |
|
"for the current projection and cannot\n" |
718 |
|
"display a configuration panel.\n\n" |
719 |
|
"The unidentified set of parameters is:\n\n") |
720 |
|
|
721 |
|
self.__textbox = wxTextCtrl(self, -1, self.__text, size=(100,200), |
722 |
|
style=wxTE_READONLY|wxTE_MULTILINE|wxTE_LINEWRAP) |
723 |
self._DoLayout() |
self._DoLayout() |
724 |
|
|
725 |
def _DoLayout(self): |
def _DoLayout(self): |
726 |
sizer = wxBoxSizer(wxVERTICAL) |
sizer = wxBoxSizer(wxVERTICAL) |
727 |
|
|
728 |
sizer.Add(wxStaticText(self, -1, |
sizer.Add(self.__textbox, 0, wxALL|wxEXPAND, 4) |
|
_("Thuban does not know the parameters\n" |
|
|
"for the current projection and cannot\n" |
|
|
"display a configuration panel."))) |
|
729 |
|
|
730 |
ProjPanel._DoLayout(self, sizer) |
ProjPanel._DoLayout(self, sizer) |
731 |
|
|
733 |
return "Unknown" |
return "Unknown" |
734 |
|
|
735 |
def SetProjection(self, proj): |
def SetProjection(self, proj): |
736 |
pass |
"""Append the available parameters to the info text.""" |
737 |
|
text = self.__text |
738 |
|
for param in proj.GetAllParameters(): |
739 |
|
text = text + '%s\n' % param |
740 |
|
self.__textbox.SetValue(text) |
741 |
|
|
742 |
def GetParameters(self): |
def GetParameters(self): |
743 |
return None |
return None |