1 |
# Copyright (C) 2001, 2002, 2003 by Intevation GmbH |
# Copyright (C) 2001, 2002, 2003, 2004 by Intevation GmbH |
2 |
# Authors: |
# Authors: |
3 |
# Jan-Oliver Wagner <[email protected]> |
# Jan-Oliver Wagner <[email protected]> |
4 |
# Bernhard Herzog <[email protected]> |
# Bernhard Herzog <[email protected]> |
19 |
import copy |
import copy |
20 |
|
|
21 |
from wxPython.wx import * |
from wxPython.wx import * |
|
from wxPython.wx import __version__ as wxPython_version |
|
22 |
|
|
23 |
import Thuban |
import Thuban |
|
import Thuban.version |
|
24 |
|
|
25 |
from Thuban import _ |
from Thuban import _ |
26 |
|
from Thuban.Model.messages import TITLE_CHANGED |
27 |
from Thuban.Model.session import create_empty_session |
from Thuban.Model.session import create_empty_session |
28 |
from Thuban.Model.layer import Layer, RasterLayer |
from Thuban.Model.layer import Layer, RasterLayer |
29 |
from Thuban.Model.postgisdb import PostGISShapeStore, has_postgis_support |
from Thuban.Model.postgisdb import PostGISShapeStore, has_postgis_support |
35 |
import view |
import view |
36 |
import tree |
import tree |
37 |
import tableview, identifyview |
import tableview, identifyview |
|
from Thuban.UI.classifier import Classifier |
|
38 |
import legend |
import legend |
39 |
from menu import Menu |
from menu import Menu |
40 |
|
|
46 |
|
|
47 |
from Thuban.UI.dock import DockFrame |
from Thuban.UI.dock import DockFrame |
48 |
from Thuban.UI.join import JoinDialog |
from Thuban.UI.join import JoinDialog |
49 |
from Thuban.UI.dbdialog import DBFrame, ChooseDBTableDialog |
from Thuban.UI.dbdialog import DBFrame, DBDialog, ChooseDBTableDialog |
50 |
import resource |
import resource |
51 |
import Thuban.Model.resource |
import Thuban.Model.resource |
52 |
|
|
53 |
import projdialog |
import projdialog |
54 |
|
|
55 |
|
from Thuban.Lib.classmapper import ClassMapper |
56 |
|
|
57 |
|
layer_properties_dialogs = ClassMapper() |
58 |
|
|
59 |
class MainWindow(DockFrame): |
class MainWindow(DockFrame): |
60 |
|
|
104 |
canvas.Subscribe(VIEW_POSITION, self.view_position_changed) |
canvas.Subscribe(VIEW_POSITION, self.view_position_changed) |
105 |
canvas.Subscribe(SHAPES_SELECTED, self.identify_view_on_demand) |
canvas.Subscribe(SHAPES_SELECTED, self.identify_view_on_demand) |
106 |
self.canvas = canvas |
self.canvas = canvas |
107 |
|
self.canvas.Subscribe(TITLE_CHANGED, self.title_changed) |
108 |
|
|
109 |
self.SetMainWindow(self.canvas) |
self.SetMainWindow(self.canvas) |
110 |
|
|
136 |
""" |
""" |
137 |
if channel in self.delegated_messages: |
if channel in self.delegated_messages: |
138 |
object = getattr(self, self.delegated_messages[channel]) |
object = getattr(self, self.delegated_messages[channel]) |
139 |
object.Unsubscribe(channel, *args) |
try: |
140 |
|
object.Unsubscribe(channel, *args) |
141 |
|
except wxPyDeadObjectError: |
142 |
|
# The object was a wxObject and has already been |
143 |
|
# destroyed. Hopefully it has unsubscribed all its |
144 |
|
# subscribers already so that it's OK if we do nothing |
145 |
|
# here |
146 |
|
pass |
147 |
|
|
148 |
def __getattr__(self, attr): |
def __getattr__(self, attr): |
149 |
"""If attr is one of the delegated methods return that method |
"""If attr is one of the delegated methods return that method |
335 |
return self.dialogs.get(name) |
return self.dialogs.get(name) |
336 |
|
|
337 |
def view_position_changed(self): |
def view_position_changed(self): |
338 |
|
"""Put current position in status bar after a mouse move.""" |
339 |
pos = self.canvas.CurrentPosition() |
pos = self.canvas.CurrentPosition() |
340 |
if pos is not None: |
if pos is not None: |
341 |
text = "(%10.10g, %10.10g)" % pos |
text = "(%10.10g, %10.10g)" % pos |
342 |
else: |
else: |
343 |
text = "" |
text = "" |
344 |
|
# XXX This is a hack until we find a better place for this code. |
345 |
|
# (BER 20050120) |
346 |
|
# BH wrote (20050120): |
347 |
|
# this branch is only executed when the mouse |
348 |
|
# leaves the canvas window, so it's not that often [..] |
349 |
|
# [Here] not the right place to put this code. |
350 |
|
# I don't have a better solution at hand, |
351 |
|
# but the view_position_changed is only there to update |
352 |
|
# the current position. If other information is to |
353 |
|
# be shown in the status bar it should |
354 |
|
# be handled in a different way and |
355 |
|
# by other methods. |
356 |
|
# |
357 |
|
# The status bar widget supports some kind of stack of texts. |
358 |
|
# maybe that can be used to distinguis |
359 |
|
# between short-lived information such as the mouse position |
360 |
|
# and more permanent information such as the hint |
361 |
|
# about the projections. |
362 |
|
map = self.canvas.Map() |
363 |
|
for layer in map.layers: |
364 |
|
bbox = layer.LatLongBoundingBox() |
365 |
|
if bbox: |
366 |
|
left, bottom, right, top = bbox |
367 |
|
if not (-180 <= left <= 180 and |
368 |
|
-180 <= right <= 180 and |
369 |
|
-90 <= top <= 90 and |
370 |
|
-90 <= bottom <= 90): |
371 |
|
text = _("Select layer '%s' and pick a projection " |
372 |
|
"using Layer/Projection...") % layer.title |
373 |
|
break |
374 |
|
|
375 |
self.set_position_text(text) |
self.set_position_text(text) |
376 |
|
|
377 |
def set_position_text(self, text): |
def set_position_text(self, text): |
383 |
""" |
""" |
384 |
self.SetStatusText(text) |
self.SetStatusText(text) |
385 |
|
|
386 |
|
def OpenOrRaiseDialog(self, name, dialog_class, *args, **kw): |
387 |
|
""" |
388 |
|
Open or raise a dialog. |
389 |
|
|
390 |
|
If a dialog with the denoted name does already exist it is |
391 |
|
raised. Otherwise a new dialog, an instance of dialog_class, |
392 |
|
is created, inserted into the main list and displayed. |
393 |
|
""" |
394 |
|
dialog = self.get_open_dialog(name) |
395 |
|
|
396 |
|
if dialog is None: |
397 |
|
dialog = dialog_class(self, name, *args, **kw) |
398 |
|
self.add_dialog(name, dialog) |
399 |
|
dialog.Show(True) |
400 |
|
else: |
401 |
|
dialog.Raise() |
402 |
|
|
403 |
def save_modified_session(self, can_veto = 1): |
def save_modified_session(self, can_veto = 1): |
404 |
"""If the current session has been modified, ask the user |
"""If the current session has been modified, ask the user |
405 |
whether to save it and do so if requested. Return the outcome of |
whether to save it and do so if requested. Return the outcome of |
429 |
|
|
430 |
def OpenSession(self): |
def OpenSession(self): |
431 |
if self.save_modified_session() != wxID_CANCEL: |
if self.save_modified_session() != wxID_CANCEL: |
432 |
dlg = wxFileDialog(self, _("Open Session"), ".", "", |
dlg = wxFileDialog(self, _("Open Session"), |
433 |
|
self.application.Path("data"), "", |
434 |
"Thuban Session File (*.thuban)|*.thuban", |
"Thuban Session File (*.thuban)|*.thuban", |
435 |
wxOPEN) |
wxOPEN) |
436 |
if dlg.ShowModal() == wxID_OK: |
if dlg.ShowModal() == wxID_OK: |
437 |
self.application.OpenSession(dlg.GetPath()) |
self.application.OpenSession(dlg.GetPath(), |
438 |
|
self.run_db_param_dialog) |
439 |
|
self.application.SetPath("data", dlg.GetPath()) |
440 |
dlg.Destroy() |
dlg.Destroy() |
441 |
|
|
442 |
|
def run_db_param_dialog(self, parameters, message): |
443 |
|
dlg = DBDialog(self, _("DB Connection Parameters"), parameters, |
444 |
|
message) |
445 |
|
return dlg.RunDialog() |
446 |
|
|
447 |
def SaveSession(self): |
def SaveSession(self): |
448 |
if self.application.session.filename == None: |
if self.application.session.filename == None: |
449 |
self.SaveSessionAs() |
self.SaveSessionAs() |
451 |
self.application.SaveSession() |
self.application.SaveSession() |
452 |
|
|
453 |
def SaveSessionAs(self): |
def SaveSessionAs(self): |
454 |
dlg = wxFileDialog(self, _("Save Session As"), ".", "", |
dlg = wxFileDialog(self, _("Save Session As"), |
455 |
|
self.application.Path("data"), "", |
456 |
"Thuban Session File (*.thuban)|*.thuban", |
"Thuban Session File (*.thuban)|*.thuban", |
457 |
wxSAVE|wxOVERWRITE_PROMPT) |
wxSAVE|wxOVERWRITE_PROMPT) |
458 |
if dlg.ShowModal() == wxID_OK: |
if dlg.ShowModal() == wxID_OK: |
459 |
self.application.session.SetFilename(dlg.GetPath()) |
self.application.session.SetFilename(dlg.GetPath()) |
460 |
self.application.SaveSession() |
self.application.SaveSession() |
461 |
|
self.application.SetPath("data",dlg.GetPath()) |
462 |
dlg.Destroy() |
dlg.Destroy() |
463 |
|
|
464 |
def Exit(self): |
def Exit(self): |
481 |
|
|
482 |
def SetMap(self, map): |
def SetMap(self, map): |
483 |
self.canvas.SetMap(map) |
self.canvas.SetMap(map) |
484 |
self.__SetTitle(map.Title()) |
self.update_title() |
485 |
|
|
486 |
dialog = self.FindRegisteredDock("legend") |
dialog = self.FindRegisteredDock("legend") |
487 |
if dialog is not None: |
if dialog is not None: |
523 |
dialog.Raise() |
dialog.Raise() |
524 |
|
|
525 |
def AddLayer(self): |
def AddLayer(self): |
526 |
dlg = wxFileDialog(self, _("Select one or more data files"), ".", "", |
dlg = wxFileDialog(self, _("Select one or more data files"), |
527 |
_("Shapefiles (*.shp)") + "|*.shp|" + |
self.application.Path("data"), "", |
528 |
_("All Files (*.*)") + "|*.*", |
_("Shapefiles (*.shp)") + "|*.shp;*.SHP|" + |
529 |
|
_("All Files (*.*)") + "|*.*", |
530 |
wxOPEN | wxMULTIPLE) |
wxOPEN | wxMULTIPLE) |
531 |
if dlg.ShowModal() == wxID_OK: |
if dlg.ShowModal() == wxID_OK: |
532 |
filenames = dlg.GetPaths() |
filenames = dlg.GetPaths() |
547 |
# if we're adding a layer to an empty map, fit the |
# if we're adding a layer to an empty map, fit the |
548 |
# new map to the window |
# new map to the window |
549 |
self.canvas.FitMapToWindow() |
self.canvas.FitMapToWindow() |
550 |
|
self.application.SetPath("data",filename) |
551 |
dlg.Destroy() |
dlg.Destroy() |
552 |
|
|
553 |
def AddRasterLayer(self): |
def AddRasterLayer(self): |
554 |
dlg = wxFileDialog(self, _("Select an image file"), ".", "", "*.*", |
dlg = wxFileDialog(self, _("Select an image file"), |
555 |
|
self.application.Path("data"), "", "*.*", |
556 |
wxOPEN) |
wxOPEN) |
557 |
if dlg.ShowModal() == wxID_OK: |
if dlg.ShowModal() == wxID_OK: |
558 |
filename = dlg.GetPath() |
filename = dlg.GetPath() |
571 |
# if we're adding a layer to an empty map, fit the |
# if we're adding a layer to an empty map, fit the |
572 |
# new map to the window |
# new map to the window |
573 |
self.canvas.FitMapToWindow() |
self.canvas.FitMapToWindow() |
574 |
|
self.application.SetPath("data", filename) |
575 |
dlg.Destroy() |
dlg.Destroy() |
576 |
|
|
577 |
def AddDBLayer(self): |
def AddDBLayer(self): |
578 |
"""Add a layer read from a database""" |
"""Add a layer read from a database""" |
579 |
session = self.application.Session() |
session = self.application.Session() |
580 |
dlg = ChooseDBTableDialog(self.application.Session(), self,-1, "") |
dlg = ChooseDBTableDialog(self, self.application.Session()) |
581 |
|
|
582 |
if dlg.ShowModal() == wxID_OK: |
if dlg.ShowModal() == wxID_OK: |
583 |
dbconn, dbtable = dlg.GetTable() |
dbconn, dbtable, id_column, geo_column = dlg.GetTable() |
584 |
try: |
try: |
585 |
title = str(dbtable) |
title = str(dbtable) |
586 |
|
|
587 |
# Chose the correct Interface for the database type |
# Chose the correct Interface for the database type |
588 |
store = PostGISShapeStore(dbconn, dbtable) |
store = session.OpenDBShapeStore(dbconn, dbtable, |
589 |
session.AddShapeStore(store) |
id_column = id_column, |
590 |
|
geometry_column = geo_column) |
591 |
layer = Layer(title, store) |
layer = Layer(title, store) |
592 |
except: |
except: |
593 |
# Some error occured while initializing the layer |
# Some error occured while initializing the layer |
594 |
self.RunMessageBox(_("Add Layer from database"), |
self.RunMessageBox(_("Add Layer from database"), |
595 |
_("Can't open the database table '%s'") |
_("Can't open the database table '%s'") |
596 |
% dbtable) |
% dbtable) |
597 |
|
return |
598 |
|
|
599 |
map = self.canvas.Map() |
map = self.canvas.Map() |
600 |
|
|
623 |
return self.canvas.Map().CanRemoveLayer(layer) |
return self.canvas.Map().CanRemoveLayer(layer) |
624 |
return False |
return False |
625 |
|
|
626 |
|
def LayerToTop(self): |
627 |
|
layer = self.current_layer() |
628 |
|
if layer is not None: |
629 |
|
self.canvas.Map().MoveLayerToTop(layer) |
630 |
|
|
631 |
def RaiseLayer(self): |
def RaiseLayer(self): |
632 |
layer = self.current_layer() |
layer = self.current_layer() |
633 |
if layer is not None: |
if layer is not None: |
638 |
if layer is not None: |
if layer is not None: |
639 |
self.canvas.Map().LowerLayer(layer) |
self.canvas.Map().LowerLayer(layer) |
640 |
|
|
641 |
|
def LayerToBottom(self): |
642 |
|
layer = self.current_layer() |
643 |
|
if layer is not None: |
644 |
|
self.canvas.Map().MoveLayerToBottom(layer) |
645 |
|
|
646 |
def current_layer(self): |
def current_layer(self): |
647 |
"""Return the currently selected layer. |
"""Return the currently selected layer. |
648 |
|
|
654 |
"""Return true if a layer is currently selected""" |
"""Return true if a layer is currently selected""" |
655 |
return self.canvas.HasSelectedLayer() |
return self.canvas.HasSelectedLayer() |
656 |
|
|
657 |
|
def has_selected_shape_layer(self): |
658 |
|
"""Return true if a shape layer is currently selected""" |
659 |
|
return isinstance(self.current_layer(), Layer) |
660 |
|
|
661 |
def has_selected_shapes(self): |
def has_selected_shapes(self): |
662 |
"""Return true if a shape is currently selected""" |
"""Return true if a shape is currently selected""" |
663 |
return self.canvas.HasSelectedShapes() |
return self.canvas.HasSelectedShapes() |
665 |
def HideLayer(self): |
def HideLayer(self): |
666 |
layer = self.current_layer() |
layer = self.current_layer() |
667 |
if layer is not None: |
if layer is not None: |
668 |
layer.SetVisible(0) |
layer.SetVisible(False) |
669 |
|
|
670 |
def ShowLayer(self): |
def ShowLayer(self): |
671 |
layer = self.current_layer() |
layer = self.current_layer() |
672 |
if layer is not None: |
if layer is not None: |
673 |
layer.SetVisible(1) |
layer.SetVisible(True) |
674 |
|
|
675 |
|
def ToggleLayerVisibility(self): |
676 |
|
layer = self.current_layer() |
677 |
|
layer.SetVisible(not layer.Visible()) |
678 |
|
|
679 |
def DuplicateLayer(self): |
def DuplicateLayer(self): |
680 |
"""Ceate a new layer above the selected layer with the same shapestore |
"""Ceate a new layer above the selected layer with the same shapestore |
685 |
layer.ShapeStore(), |
layer.ShapeStore(), |
686 |
projection = layer.GetProjection()) |
projection = layer.GetProjection()) |
687 |
new_classification = copy.deepcopy(layer.GetClassification()) |
new_classification = copy.deepcopy(layer.GetClassification()) |
688 |
|
new_layer.SetClassificationColumn( |
689 |
|
layer.GetClassificationColumn()) |
690 |
new_layer.SetClassification(new_classification) |
new_layer.SetClassification(new_classification) |
691 |
self.Map().AddLayer(new_layer) |
self.Map().AddLayer(new_layer) |
692 |
|
|
696 |
return layer is not None and hasattr(layer, "ShapeStore") |
return layer is not None and hasattr(layer, "ShapeStore") |
697 |
|
|
698 |
def LayerShowTable(self): |
def LayerShowTable(self): |
699 |
|
""" |
700 |
|
Present a TableView Window for the current layer. |
701 |
|
In case the window is already open, bring it to the front. |
702 |
|
In case, there is no active layer, do nothing. |
703 |
|
In case, the layer has no ShapeStore, do nothing. |
704 |
|
""" |
705 |
layer = self.current_layer() |
layer = self.current_layer() |
706 |
if layer is not None: |
if layer is not None: |
707 |
|
if not hasattr(layer, "ShapeStore"): |
708 |
|
return |
709 |
table = layer.ShapeStore().Table() |
table = layer.ShapeStore().Table() |
710 |
name = "table_view" + str(id(table)) |
name = "table_view" + str(id(table)) |
711 |
dialog = self.get_open_dialog(name) |
dialog = self.get_open_dialog(name) |
716 |
self.add_dialog(name, dialog) |
self.add_dialog(name, dialog) |
717 |
dialog.Show(True) |
dialog.Show(True) |
718 |
else: |
else: |
719 |
# FIXME: bring dialog to front here |
dialog.Raise() |
|
pass |
|
720 |
|
|
721 |
def MapProjection(self): |
def MapProjection(self): |
722 |
|
|
758 |
self.OpenLayerProperties(layer) |
self.OpenLayerProperties(layer) |
759 |
|
|
760 |
def OpenLayerProperties(self, layer, group = None): |
def OpenLayerProperties(self, layer, group = None): |
761 |
name = "layer_properties" + str(id(layer)) |
""" |
762 |
dialog = self.get_open_dialog(name) |
Open or raise the properties dialog. |
763 |
|
|
764 |
if dialog is None: |
This method opens or raises the properties dialog for the |
765 |
dialog = Classifier(self, name, self.Map(), layer, group) |
currently selected layer if one is defined for this layer |
766 |
self.add_dialog(name, dialog) |
type. |
767 |
dialog.Show() |
""" |
768 |
dialog.Raise() |
dialog_class = layer_properties_dialogs.get(layer) |
769 |
|
|
770 |
|
if dialog_class is not None: |
771 |
|
name = "layer_properties" + str(id(layer)) |
772 |
|
self.OpenOrRaiseDialog(name, dialog_class, layer, group = group) |
773 |
|
|
774 |
def LayerJoinTable(self): |
def LayerJoinTable(self): |
775 |
layer = self.canvas.SelectedLayer() |
layer = self.canvas.SelectedLayer() |
810 |
return dialog is not None and dialog.IsShown() |
return dialog is not None and dialog.IsShown() |
811 |
|
|
812 |
def TableOpen(self): |
def TableOpen(self): |
813 |
dlg = wxFileDialog(self, _("Open Table"), ".", "", |
dlg = wxFileDialog(self, _("Open Table"), |
814 |
|
self.application.Path("data"), "", |
815 |
_("DBF Files (*.dbf)") + "|*.dbf|" + |
_("DBF Files (*.dbf)") + "|*.dbf|" + |
816 |
#_("CSV Files (*.csv)") + "|*.csv|" + |
#_("CSV Files (*.csv)") + "|*.csv|" + |
817 |
_("All Files (*.*)") + "|*.*", |
_("All Files (*.*)") + "|*.*", |
827 |
_("Can't open the file '%s'.") % filename) |
_("Can't open the file '%s'.") % filename) |
828 |
else: |
else: |
829 |
self.ShowTableView(table) |
self.ShowTableView(table) |
830 |
|
self.application.SetPath("data",filename) |
831 |
|
|
832 |
def TableClose(self): |
def TableClose(self): |
833 |
tables = self.application.session.UnreferencedTables() |
tables = self.application.session.UnreferencedTables() |
904 |
|
|
905 |
# Second, let the user rename the layers |
# Second, let the user rename the layers |
906 |
for table in to_rename: |
for table in to_rename: |
907 |
dlg = wxTextEntryDialog(self, "Table Title: ", "Rename Table", |
dlg = wxTextEntryDialog(self, _("Table Title:"), _("Rename Table"), |
908 |
table.Title()) |
table.Title()) |
909 |
try: |
try: |
910 |
if dlg.ShowModal() == wxID_OK: |
if dlg.ShowModal() == wxID_OK: |
953 |
self.canvas.Print() |
self.canvas.Print() |
954 |
|
|
955 |
def RenameMap(self): |
def RenameMap(self): |
956 |
dlg = wxTextEntryDialog(self, "Map Title: ", "Rename Map", |
dlg = wxTextEntryDialog(self, _("Map Title:"), _("Rename Map"), |
957 |
self.Map().Title()) |
self.Map().Title()) |
958 |
if dlg.ShowModal() == wxID_OK: |
if dlg.ShowModal() == wxID_OK: |
959 |
title = dlg.GetValue() |
title = dlg.GetValue() |
960 |
if title != "": |
if title != "": |
961 |
self.Map().SetTitle(title) |
self.Map().SetTitle(title) |
|
self.__SetTitle(title) |
|
962 |
|
|
963 |
dlg.Destroy() |
dlg.Destroy() |
964 |
|
|
966 |
"""Let the user rename the currently selected layer""" |
"""Let the user rename the currently selected layer""" |
967 |
layer = self.current_layer() |
layer = self.current_layer() |
968 |
if layer is not None: |
if layer is not None: |
969 |
dlg = wxTextEntryDialog(self, "Layer Title: ", "Rename Layer", |
dlg = wxTextEntryDialog(self, _("Layer Title:"), _("Rename Layer"), |
970 |
layer.Title()) |
layer.Title()) |
971 |
try: |
try: |
972 |
if dlg.ShowModal() == wxID_OK: |
if dlg.ShowModal() == wxID_OK: |
1000 |
# FIXME: bring dialog to front? |
# FIXME: bring dialog to front? |
1001 |
pass |
pass |
1002 |
|
|
1003 |
def __SetTitle(self, title): |
def title_changed(self, map): |
1004 |
self.SetTitle("Thuban - " + title) |
"""Subscribed to the canvas' TITLE_CHANGED messages""" |
1005 |
|
self.update_title() |
1006 |
|
|
1007 |
|
def update_title(self): |
1008 |
|
"""Update the window's title according to it's current state. |
1009 |
|
|
1010 |
|
In this default implementation the title is 'Thuban - ' followed |
1011 |
|
by the map's title or simply 'Thuban' if there is not map. |
1012 |
|
Derived classes should override this method to get different |
1013 |
|
titles. |
1014 |
|
|
1015 |
|
This method is called automatically by other methods when the |
1016 |
|
title may have to change. For the methods implemented in this |
1017 |
|
class this usually only means that a different map has been set |
1018 |
|
or the current map's title has changed. |
1019 |
|
""" |
1020 |
|
map = self.Map() |
1021 |
|
if map is not None: |
1022 |
|
title = _("Thuban - %s") % (map.Title(),) |
1023 |
|
else: |
1024 |
|
title = _("Thuban") |
1025 |
|
self.SetTitle(title) |
1026 |
|
|
1027 |
|
|
1028 |
# |
# |
1029 |
# Define all the commands available in the main window |
# Define all the commands available in the main window |
1065 |
"""Return true if a layer is selected in the context""" |
"""Return true if a layer is selected in the context""" |
1066 |
return context.mainwindow.has_selected_layer() |
return context.mainwindow.has_selected_layer() |
1067 |
|
|
1068 |
|
def _has_selected_layer_visible(context): |
1069 |
|
"""Return true if a layer is selected in the context which is |
1070 |
|
visible.""" |
1071 |
|
if context.mainwindow.has_selected_layer(): |
1072 |
|
layer = context.mainwindow.current_layer() |
1073 |
|
if layer.Visible(): return True |
1074 |
|
return False |
1075 |
|
|
1076 |
|
def _has_selected_shape_layer(context): |
1077 |
|
"""Return true if a shape layer is selected in the context""" |
1078 |
|
return context.mainwindow.has_selected_shape_layer() |
1079 |
|
|
1080 |
def _has_selected_shapes(context): |
def _has_selected_shapes(context): |
1081 |
"""Return true if a layer is selected in the context""" |
"""Return true if a layer is selected in the context""" |
1082 |
return context.mainwindow.has_selected_shapes() |
return context.mainwindow.has_selected_shapes() |
1096 |
if map is not None: |
if map is not None: |
1097 |
for layer in map.Layers(): |
for layer in map.Layers(): |
1098 |
if layer.Visible(): |
if layer.Visible(): |
1099 |
return 1 |
return True |
1100 |
return 0 |
return False |
1101 |
|
|
1102 |
def _has_legend_shown(context): |
def _has_legend_shown(context): |
1103 |
"""Return true if the legend window is shown""" |
"""Return true if the legend window is shown""" |
1213 |
sensitive = _has_selected_layer) |
sensitive = _has_selected_layer) |
1214 |
_method_command("layer_show_table", _("Show Ta&ble"), "LayerShowTable", |
_method_command("layer_show_table", _("Show Ta&ble"), "LayerShowTable", |
1215 |
helptext = _("Show the selected layer's table"), |
helptext = _("Show the selected layer's table"), |
1216 |
sensitive = _has_selected_layer) |
sensitive = _has_selected_shape_layer) |
1217 |
_method_command("layer_properties", _("&Properties..."), "LayerEditProperties", |
_method_command("layer_properties", _("&Properties..."), "LayerEditProperties", |
1218 |
sensitive = _has_selected_layer, |
sensitive = _has_selected_layer, |
1219 |
helptext = _("Edit the properties of the selected layer")) |
helptext = _("Edit the properties of the selected layer")) |
1220 |
_method_command("layer_jointable", _("&Join Table..."), "LayerJoinTable", |
_method_command("layer_jointable", _("&Join Table..."), "LayerJoinTable", |
1221 |
sensitive = _has_selected_layer, |
sensitive = _has_selected_shape_layer, |
1222 |
helptext = _("Join and attach a table to the selected layer")) |
helptext = _("Join and attach a table to the selected layer")) |
1223 |
|
|
1224 |
|
# further layer methods: |
1225 |
|
_method_command("layer_to_top", _("&Top"), "LayerToTop", |
1226 |
|
helptext = _("Put selected layer to the top"), |
1227 |
|
sensitive = _has_selected_layer) |
1228 |
|
_method_command("layer_to_bottom", _("&Bottom"), "LayerToBottom", |
1229 |
|
helptext = _("Put selected layer to the bottom"), |
1230 |
|
sensitive = _has_selected_layer) |
1231 |
|
_method_command("layer_visibility", _("&Visible"), "ToggleLayerVisibility", |
1232 |
|
checked = _has_selected_layer_visible, |
1233 |
|
helptext = _("Toggle visibility of selected layer"), |
1234 |
|
sensitive = _has_selected_layer) |
1235 |
|
|
1236 |
def _can_unjoin(context): |
def _can_unjoin(context): |
1237 |
"""Return whether the Layer/Unjoin command can be executed. |
"""Return whether the Layer/Unjoin command can be executed. |
1238 |
|
|