~ubuntu-branches/ubuntu/lucid/thuban/lucid

« back to all changes in this revision

Viewing changes to Thuban/UI/mainwindow.py

  • Committer: Bazaar Package Importer
  • Author(s): Francesco Paolo Lovergine
  • Date: 2007-04-07 21:03:28 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20070407210328-9a20n4dmbim3c3yc
Tags: 1.2.0-1
* New upstream release.
* Patchset updated.
* Policy bumped to 3.7.2 (no changes).
* Updated for current Python Policy by using python-support.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2001, 2002, 2003, 2004 by Intevation GmbH
 
1
# Copyright (C) 2001, 2002, 2003, 2004, 2005 by Intevation GmbH
2
2
# Authors:
3
3
# Jan-Oliver Wagner <jan@intevation.de>
4
4
# Bernhard Herzog <bh@intevation.de>
11
11
The main window
12
12
"""
13
13
 
14
 
__version__ = "$Revision: 1.128 $"
15
 
# $Source: /thubanrepository/thuban/Thuban/UI/mainwindow.py,v $
16
 
# $Id: mainwindow.py,v 1.128 2004/02/13 10:46:44 bh Exp $
 
14
__version__ = "$Revision: 2700 $"
 
15
# $Source$
 
16
# $Id: mainwindow.py 2700 2006-09-18 14:27:02Z dpinte $
17
17
 
18
18
import os
19
19
import copy
20
20
 
21
 
from wxPython.wx import *
 
21
import wx
22
22
 
23
23
import Thuban
24
24
 
25
25
from Thuban import _
26
 
from Thuban.Model.messages import TITLE_CHANGED
 
26
from Thuban.Model.messages import TITLE_CHANGED, LAYER_PROJECTION_CHANGED, \
 
27
     MAP_PROJECTION_CHANGED, MAP_LAYERS_ADDED, MAP_LAYERS_REMOVED
 
28
 
27
29
from Thuban.Model.session import create_empty_session
28
30
from Thuban.Model.layer import Layer, RasterLayer
29
31
from Thuban.Model.postgisdb import PostGISShapeStore, has_postgis_support
30
 
# XXX: replace this by
31
 
# from wxPython.lib.dialogs import wxMultipleChoiceDialog
32
 
# when Thuban does not support wxPython 2.4.0 any more.
33
 
from Thuban.UI.multiplechoicedialog import wxMultipleChoiceDialog
 
32
from wx.lib.dialogs import MultipleChoiceDialog
34
33
 
35
34
import view
36
35
import tree
37
36
import tableview, identifyview
38
 
from Thuban.UI.classifier import Classifier
39
37
import legend
40
38
from menu import Menu
41
39
 
53
51
 
54
52
import projdialog
55
53
 
 
54
from Thuban.UI.classifier import Classifier
 
55
from Thuban.UI.rasterlayerproperties import RasterLayerProperties
 
56
from Thuban.Model.layer import RasterLayer
 
57
 
 
58
from Thuban.Lib.classmapper import ClassMapper
 
59
 
 
60
layer_properties_dialogs = ClassMapper()
 
61
layer_properties_dialogs.add(RasterLayer, RasterLayerProperties)
 
62
layer_properties_dialogs.add(Layer, Classifier)
56
63
 
57
64
class MainWindow(DockFrame):
58
65
 
73
80
                         "SelectedShapes": "canvas",
74
81
                         }
75
82
 
 
83
    # Messages from the canvas that may require a status bar update.
 
84
    # The update_status_bar method will be subscribed to these messages.
 
85
    update_status_bar_messages = (VIEW_POSITION, LAYER_PROJECTION_CHANGED,
 
86
                                  MAP_PROJECTION_CHANGED, MAP_LAYERS_ADDED,
 
87
                                  MAP_LAYERS_REMOVED)
 
88
 
76
89
    def __init__(self, parent, ID, title, application, interactor,
77
 
                 initial_message = None, size = wxSize(-1, -1)):
78
 
        DockFrame.__init__(self, parent, ID, title, wxDefaultPosition, size)
 
90
                 initial_message = None, size = wx.Size(-1, -1)):
 
91
        DockFrame.__init__(self, parent, ID, title, wx.DefaultPosition, size)
79
92
        #wxFrame.__init__(self, parent, ID, title, wxDefaultPosition, size)
80
93
 
81
94
        self.application = application
99
112
 
100
113
        # Create the map canvas
101
114
        canvas = view.MapCanvas(self, -1)
102
 
        canvas.Subscribe(VIEW_POSITION, self.view_position_changed)
103
115
        canvas.Subscribe(SHAPES_SELECTED, self.identify_view_on_demand)
104
116
        self.canvas = canvas
105
117
        self.canvas.Subscribe(TITLE_CHANGED, self.title_changed)
106
118
 
 
119
        for channel in self.update_status_bar_messages:
 
120
            self.canvas.Subscribe(channel, self.update_status_bar)
 
121
 
107
122
        self.SetMainWindow(self.canvas)
108
123
 
109
124
        self.SetAutoLayout(True)
112
127
 
113
128
        self.ShowLegend()
114
129
 
115
 
        EVT_CLOSE(self, self.OnClose)
 
130
        self.Bind(wx.EVT_CLOSE, self.OnClose)
116
131
 
117
132
    def Subscribe(self, channel, *args):
118
133
        """Subscribe a function to a message channel.
136
151
            object = getattr(self, self.delegated_messages[channel])
137
152
            try:
138
153
                object.Unsubscribe(channel, *args)
139
 
            except wxPyDeadObjectError:
 
154
            except wx.PyDeadObjectError:
140
155
                # The object was a wxObject and has already been
141
156
                # destroyed. Hopefully it has unsubscribed all its
142
157
                # subscribers already so that it's OK if we do nothing
175
190
        """Bind the necessary events for the given command and ID"""
176
191
        if not self.events_bound.has_key(ID):
177
192
            # the events haven't been bound yet
178
 
            EVT_MENU(self, ID, self.invoke_command)
 
193
            self.Bind(wx.EVT_MENU, self.invoke_command, id=ID)
179
194
            if command.IsDynamic():
180
 
                EVT_UPDATE_UI(self, ID, self.update_command_ui)
 
195
                self.Bind(wx.EVT_UPDATE_UI, self.update_command_ui, id=ID)
181
196
 
182
197
    def build_menu_bar(self, menudesc):
183
198
        """Build and return the menu bar from the menu description"""
184
 
        menu_bar = wxMenuBar()
 
199
        menu_bar = wx.MenuBar()
185
200
 
186
201
        for item in menudesc.items:
187
202
            # here the items must all be Menu instances themselves
191
206
 
192
207
    def build_menu(self, menudesc):
193
208
        """Return a wxMenu built from the menu description menudesc"""
194
 
        wxmenu = wxMenu()
 
209
        wxmenu = wx.Menu()
195
210
        last = None
196
211
        for item in menudesc.items:
197
212
            if item is None:
201
216
                    wxmenu.AppendSeparator()
202
217
            elif isinstance(item, Menu):
203
218
                # a submenu
204
 
                wxmenu.AppendMenu(wxNewId(), item.title, self.build_menu(item))
 
219
                wxmenu.AppendMenu(wx.NewId(), item.title, self.build_menu(item))
205
220
            else:
206
221
                # must the name the name of a command
207
222
                self.add_menu_command(wxmenu, item)
214
229
        The parameter should be an instance of the Menu class but it
215
230
        should not contain submenus.
216
231
        """
217
 
        toolbar = self.CreateToolBar(wxTB_3DBUTTONS)
 
232
        toolbar = self.CreateToolBar(wx.TB_3DBUTTONS)
218
233
 
219
234
        # set the size of the tools' bitmaps. Not needed on wxGTK, but
220
235
        # on Windows, although it doesn't work very well there. It seems
221
236
        # that only 16x16 icons are really supported on windows.
222
237
        # We probably shouldn't hardwire the bitmap size here.
223
 
        toolbar.SetToolBitmapSize(wxSize(24, 24))
 
238
        toolbar.SetToolBitmapSize(wx.Size(24, 24))
224
239
 
225
240
        for item in toolbardesc.items:
226
241
            if item is None:
261
276
            command = registry.Command(name)
262
277
            if command is not None:
263
278
                ID = self.get_id(name)
264
 
                bitmap = resource.GetBitmapResource(command.Icon(), 
265
 
                                                    wxBITMAP_TYPE_XPM)
 
279
                bitmap = resource.GetBitmapResource(command.Icon(),
 
280
                                                    wx.BITMAP_TYPE_XPM)
266
281
                toolbar.AddTool(ID, bitmap,
267
282
                                shortHelpString = command.HelpText(),
268
283
                                isToggle = command.IsCheckCommand())
302
317
            if command.IsCheckCommand():
303
318
                    event.Check(command.Checked(context))
304
319
 
305
 
    def RunMessageBox(self, title, text, flags = wxOK | wxICON_INFORMATION):
 
320
    def RunMessageBox(self, title, text, flags = wx.OK | wx.ICON_INFORMATION):
306
321
        """Run a modal message box with the given text, title and flags
307
322
        and return the result"""
308
 
        dlg = wxMessageDialog(self, text, title, flags)
 
323
        dlg = wx.MessageDialog(self, text, title, flags)
309
324
        dlg.CenterOnParent()
310
325
        result = dlg.ShowModal()
311
326
        dlg.Destroy()
332
347
    def get_open_dialog(self, name):
333
348
        return self.dialogs.get(name)
334
349
 
335
 
    def view_position_changed(self):
 
350
    def update_status_bar(self, *args):
 
351
        """Handler for a bunch of messages that may require a status bar update
 
352
 
 
353
        Currently this handles the canvas' VIEW_POSITION_CHANGED
 
354
        messages as well as several messages about changes in the map
 
355
        which may affect whether and how projections are used.
 
356
 
 
357
        These messages affect the text in the status bar in the following way:
 
358
 
 
359
        When VIEW_POSITION_CHANGED messages are sent and the mouse is
 
360
        actually in the canvas window, display the current mouse
 
361
        coordinates as defined by the canvas' CurrentPosition method.
 
362
 
 
363
        If there is no current position to show, check whether there is
 
364
        a potential problem with the map and layer projections and
 
365
        display a message about it.  Otherwise the status bar will
 
366
        become empty.
 
367
 
 
368
        The text is displayed in the status bar using the
 
369
        set_position_text method.
 
370
        """
 
371
        # Implementation note: We do not really have to know which
 
372
        # message was sent.  We can simply call the canvas'
 
373
        # CurrentPosition method and if that returns a tuple, it was a
 
374
        # VIEW_POSITION_CHANGED message and we have to display it.
 
375
        # Otherwise it was a VIEW_POSITION_CHANGED message where the
 
376
        # mouse has left the canvas or it was a message about a change
 
377
        # to the map, in which case we check the projections.
 
378
        #
 
379
        # When changing this method, keep in mind that the
 
380
        # VIEW_POSITION_CHANGED message are sent for every mouse move in
 
381
        # the canvas window, that is they happen very often, so the path
 
382
        # taken in that case has to be fast.
 
383
        text = ""
336
384
        pos = self.canvas.CurrentPosition()
337
385
        if pos is not None:
338
386
            text = "(%10.10g, %10.10g)" % pos
339
387
        else:
340
 
            text = ""
 
388
            for layer in self.canvas.Map().Layers():
 
389
                bbox = layer.LatLongBoundingBox()
 
390
                if bbox:
 
391
                    left, bottom, right, top = bbox
 
392
                    if not (-180 <= left <= 180 and
 
393
                            -180 <= right <= 180 and
 
394
                            -90 <= top <= 90 and
 
395
                            -90 <= bottom <= 90):
 
396
                        text = _("Select layer '%s' and pick a projection "
 
397
                                 "using Layer/Projection...") % layer.title
 
398
                        break
 
399
 
341
400
        self.set_position_text(text)
342
401
 
343
402
    def set_position_text(self, text):
344
 
        """Set the statusbar text showing the current position.
 
403
        """Set the statusbar text to that created by update_status_bar
345
404
 
346
405
        By default the text is shown in field 0 of the status bar.
347
406
        Override this method in derived classes to put it into a
348
407
        different field of the statusbar.
 
408
 
 
409
        For historical reasons this method is called set_position_text
 
410
        because at first the text was always either the current position
 
411
        or the empty string.  Now it can contain other messages as well.
 
412
        The method will be renamed at one point.
349
413
        """
 
414
        # Note: If this method is renamed we should perhaps think about
 
415
        # some backwards compatibility measures for projects like
 
416
        # GREAT-ER which override this method.
350
417
        self.SetStatusText(text)
351
418
 
 
419
    def OpenOrRaiseDialog(self, name, dialog_class, *args, **kw):
 
420
        """
 
421
        Open or raise a dialog.
 
422
 
 
423
        If a dialog with the denoted name does already exist it is
 
424
        raised.  Otherwise a new dialog, an instance of dialog_class,
 
425
        is created, inserted into the main list and displayed.
 
426
        """
 
427
        dialog = self.get_open_dialog(name)
 
428
 
 
429
        if dialog is None:
 
430
            dialog = dialog_class(self, name, *args, **kw)
 
431
            self.add_dialog(name, dialog)
 
432
            dialog.Show(True)
 
433
        else:
 
434
            dialog.Raise()
 
435
 
352
436
    def save_modified_session(self, can_veto = 1):
353
437
        """If the current session has been modified, ask the user
354
438
        whether to save it and do so if requested. Return the outcome of
359
443
        a cancel button, otherwise not.
360
444
        """
361
445
        if self.application.session.WasModified():
362
 
            flags = wxYES_NO | wxICON_QUESTION
 
446
            flags = wx.YES_NO | wx.ICON_QUESTION
363
447
            if can_veto:
364
 
                flags = flags | wxCANCEL
 
448
                flags = flags | wx.CANCEL
365
449
            result = self.RunMessageBox(_("Exit"),
366
450
                                        _("The session has been modified."
367
451
                                         " Do you want to save it?"),
368
452
                                        flags)
369
 
            if result == wxID_YES:
 
453
            if result == wx.ID_YES:
370
454
                self.SaveSession()
371
455
        else:
372
 
            result = wxID_NO
 
456
            result = wx.ID_NO
373
457
        return result
374
458
 
375
459
    def NewSession(self):
376
 
        if self.save_modified_session() != wxID_CANCEL:
 
460
        if self.save_modified_session() != wx.ID_CANCEL:
377
461
            self.application.SetSession(create_empty_session())
378
462
 
379
463
    def OpenSession(self):
380
 
        if self.save_modified_session() != wxID_CANCEL:
381
 
            dlg = wxFileDialog(self, _("Open Session"),
382
 
                               self.application.Path("data"), "", 
383
 
                               "Thuban Session File (*.thuban)|*.thuban", 
384
 
                               wxOPEN)
385
 
            if dlg.ShowModal() == wxID_OK:
 
464
        if self.save_modified_session() != wx.ID_CANCEL:
 
465
            dlg = wx.FileDialog(self, _("Open Session"),
 
466
                               self.application.Path("data"), "",
 
467
                               "Thuban Session File (*.thuban)|*.thuban",
 
468
                               wx.OPEN)
 
469
            if dlg.ShowModal() == wx.ID_OK:
386
470
                self.application.OpenSession(dlg.GetPath(),
387
471
                                             self.run_db_param_dialog)
388
472
                self.application.SetPath("data", dlg.GetPath())
400
484
            self.application.SaveSession()
401
485
 
402
486
    def SaveSessionAs(self):
403
 
        dlg = wxFileDialog(self, _("Save Session As"),
 
487
        dlg = wx.FileDialog(self, _("Save Session As"),
404
488
                           self.application.Path("data"), "",
405
 
                           "Thuban Session File (*.thuban)|*.thuban", 
406
 
                           wxSAVE|wxOVERWRITE_PROMPT)
407
 
        if dlg.ShowModal() == wxID_OK:
 
489
                           "Thuban Session File (*.thuban)|*.thuban",
 
490
                           wx.SAVE|wx.OVERWRITE_PROMPT)
 
491
        if dlg.ShowModal() == wx.ID_OK:
408
492
            self.application.session.SetFilename(dlg.GetPath())
409
493
            self.application.SaveSession()
410
494
            self.application.SetPath("data",dlg.GetPath())
415
499
 
416
500
    def OnClose(self, event):
417
501
        result = self.save_modified_session(can_veto = event.CanVeto())
418
 
        if result == wxID_CANCEL:
 
502
        if result == wx.ID_CANCEL:
419
503
            event.Veto()
420
504
        else:
421
505
            # FIXME: it would be better to tie the unsubscription to
422
506
            # wx's destroy event, but that isn't implemented for wxGTK
423
507
            # yet.
424
 
            self.canvas.Unsubscribe(VIEW_POSITION, self.view_position_changed)
 
508
            for channel in self.update_status_bar_messages:
 
509
                self.canvas.Unsubscribe(channel, self.update_status_bar)
 
510
 
425
511
            DockFrame.OnClose(self, event)
426
512
            for dlg in self.dialogs.values():
427
513
                dlg.Destroy()
472
558
        dialog.Raise()
473
559
 
474
560
    def AddLayer(self):
475
 
        dlg = wxFileDialog(self, _("Select one or more data files"), 
 
561
        dlg = wx.FileDialog(self, _("Select one or more data files"),
476
562
                           self.application.Path("data"), "",
477
563
                           _("Shapefiles (*.shp)") + "|*.shp;*.SHP|" +
478
564
                           _("All Files (*.*)") + "|*.*",
479
 
                           wxOPEN | wxMULTIPLE)
480
 
        if dlg.ShowModal() == wxID_OK:
 
565
                           wx.OPEN | wx.MULTIPLE)
 
566
        if dlg.ShowModal() == wx.ID_OK:
481
567
            filenames = dlg.GetPaths()
482
568
            for filename in filenames:
483
569
                title = os.path.splitext(os.path.basename(filename))[0]
500
586
        dlg.Destroy()
501
587
 
502
588
    def AddRasterLayer(self):
503
 
        dlg = wxFileDialog(self, _("Select an image file"), 
 
589
        dlg = wx.FileDialog(self, _("Select an image file"),
504
590
                           self.application.Path("data"), "", "*.*",
505
 
                           wxOPEN)
506
 
        if dlg.ShowModal() == wxID_OK:
 
591
                           wx.OPEN)
 
592
        if dlg.ShowModal() == wx.ID_OK:
507
593
            filename = dlg.GetPath()
508
594
            title = os.path.splitext(os.path.basename(filename))[0]
509
595
            map = self.canvas.Map()
528
614
        session = self.application.Session()
529
615
        dlg = ChooseDBTableDialog(self, self.application.Session())
530
616
 
531
 
        if dlg.ShowModal() == wxID_OK:
532
 
            dbconn, dbtable = dlg.GetTable()
 
617
        if dlg.ShowModal() == wx.ID_OK:
 
618
            dbconn, dbtable, id_column, geo_column = dlg.GetTable()
533
619
            try:
534
620
                title = str(dbtable)
535
621
 
536
622
                # Chose the correct Interface for the database type
537
 
                store = PostGISShapeStore(dbconn, dbtable)
538
 
                session.AddShapeStore(store)
 
623
                store = session.OpenDBShapeStore(dbconn, dbtable,
 
624
                                                 id_column = id_column,
 
625
                                                 geometry_column = geo_column)
539
626
                layer = Layer(title, store)
540
627
            except:
541
628
                # Some error occured while initializing the layer
571
658
            return self.canvas.Map().CanRemoveLayer(layer)
572
659
        return False
573
660
 
 
661
    def LayerToTop(self):
 
662
        layer = self.current_layer()
 
663
        if layer is not None:
 
664
            self.canvas.Map().MoveLayerToTop(layer)
 
665
 
574
666
    def RaiseLayer(self):
575
667
        layer = self.current_layer()
576
668
        if layer is not None:
581
673
        if layer is not None:
582
674
            self.canvas.Map().LowerLayer(layer)
583
675
 
 
676
    def LayerToBottom(self):
 
677
        layer = self.current_layer()
 
678
        if layer is not None:
 
679
            self.canvas.Map().MoveLayerToBottom(layer)
 
680
 
584
681
    def current_layer(self):
585
682
        """Return the currently selected layer.
586
683
 
603
700
    def HideLayer(self):
604
701
        layer = self.current_layer()
605
702
        if layer is not None:
606
 
            layer.SetVisible(0)
 
703
            layer.SetVisible(False)
607
704
 
608
705
    def ShowLayer(self):
609
706
        layer = self.current_layer()
610
707
        if layer is not None:
611
 
            layer.SetVisible(1)
 
708
            layer.SetVisible(True)
 
709
 
 
710
    def ToggleLayerVisibility(self):
 
711
        layer = self.current_layer()
 
712
        layer.SetVisible(not layer.Visible())
612
713
 
613
714
    def DuplicateLayer(self):
614
715
        """Ceate a new layer above the selected layer with the same shapestore
619
720
                              layer.ShapeStore(),
620
721
                              projection = layer.GetProjection())
621
722
            new_classification = copy.deepcopy(layer.GetClassification())
 
723
            new_layer.SetClassificationColumn(
 
724
                    layer.GetClassificationColumn())
622
725
            new_layer.SetClassification(new_classification)
623
726
            self.Map().AddLayer(new_layer)
624
727
 
628
731
        return layer is not None and hasattr(layer, "ShapeStore")
629
732
 
630
733
    def LayerShowTable(self):
 
734
        """
 
735
        Present a TableView Window for the current layer.
 
736
        In case the window is already open, bring it to the front.
 
737
        In case, there is no active layer, do nothing.
 
738
        In case, the layer has no ShapeStore, do nothing.
 
739
        """
631
740
        layer = self.current_layer()
632
741
        if layer is not None:
 
742
            if not hasattr(layer, "ShapeStore"):
 
743
                return
633
744
            table = layer.ShapeStore().Table()
634
745
            name = "table_view" + str(id(table))
635
746
            dialog = self.get_open_dialog(name)
640
751
                self.add_dialog(name, dialog)
641
752
                dialog.Show(True)
642
753
            else:
643
 
                # FIXME: bring dialog to front here
644
 
                pass
 
754
                dialog.Raise()
645
755
 
646
756
    def MapProjection(self):
647
757
 
650
760
 
651
761
        if dialog is None:
652
762
            map = self.canvas.Map()
653
 
            dialog = projdialog.ProjFrame(self, name, 
 
763
            dialog = projdialog.ProjFrame(self, name,
654
764
                     _("Map Projection: %s") % map.Title(), map)
655
765
            self.add_dialog(name, dialog)
656
766
            dialog.Show()
665
775
 
666
776
        if dialog is None:
667
777
            map = self.canvas.Map()
668
 
            dialog = projdialog.ProjFrame(self, name, 
 
778
            dialog = projdialog.ProjFrame(self, name,
669
779
                     _("Layer Projection: %s") % layer.Title(), layer)
670
780
            self.add_dialog(name, dialog)
671
781
            dialog.Show()
683
793
        self.OpenLayerProperties(layer)
684
794
 
685
795
    def OpenLayerProperties(self, layer, group = None):
686
 
        name = "layer_properties" + str(id(layer))
687
 
        dialog = self.get_open_dialog(name)
688
 
 
689
 
        if dialog is None:
690
 
            dialog = Classifier(self, name, self.Map(), layer, group)
691
 
            self.add_dialog(name, dialog)
692
 
            dialog.Show()
693
 
        dialog.Raise()
 
796
        """
 
797
        Open or raise the properties dialog.
 
798
 
 
799
        This method opens or raises the properties dialog for the
 
800
        currently selected layer if one is defined for this layer
 
801
        type.
 
802
        """
 
803
        dialog_class = layer_properties_dialogs.get(layer)
 
804
 
 
805
        if dialog_class is not None:
 
806
            name = "layer_properties" + str(id(layer))
 
807
            self.OpenOrRaiseDialog(name, dialog_class, layer, group = group)
694
808
 
695
809
    def LayerJoinTable(self):
696
810
        layer = self.canvas.SelectedLayer()
717
831
        dialog = self.FindRegisteredDock(name)
718
832
 
719
833
        if dialog is None:
720
 
            dialog = self.CreateDock(name, -1, _("Legend"), wxLAYOUT_LEFT)
 
834
            dialog = self.CreateDock(name, -1, _("Legend"), wx.LAYOUT_LEFT)
721
835
            legend.LegendPanel(dialog, None, self)
722
836
            dialog.Dock()
723
837
            dialog.GetPanel().SetMap(self.Map())
727
841
 
728
842
    def LegendShown(self):
729
843
        """Return true iff the legend is currently open"""
730
 
        dialog = self.FindRegisteredDock("legend") 
 
844
        dialog = self.FindRegisteredDock("legend")
731
845
        return dialog is not None and dialog.IsShown()
732
846
 
733
847
    def TableOpen(self):
734
 
        dlg = wxFileDialog(self, _("Open Table"), 
735
 
                           self.application.Path("data"), "", 
736
 
                           _("DBF Files (*.dbf)") + "|*.dbf|" + 
 
848
        dlg = wx.FileDialog(self, _("Open Table"),
 
849
                           self.application.Path("data"), "",
 
850
                           _("DBF Files (*.dbf)") + "|*.dbf|" +
737
851
                           #_("CSV Files (*.csv)") + "|*.csv|" + 
738
 
                           _("All Files (*.*)") + "|*.*", 
739
 
                           wxOPEN)
740
 
        if dlg.ShowModal() == wxID_OK:
 
852
                           _("All Files (*.*)") + "|*.*",
 
853
                           wx.OPEN)
 
854
        if dlg.ShowModal() == wx.ID_OK:
741
855
            filename = dlg.GetPath()
742
856
            dlg.Destroy()
743
857
            try:
756
870
        lst = [(t.Title(), t) for t in tables]
757
871
        lst.sort()
758
872
        titles = [i[0] for i in lst]
759
 
        dlg = wxMultipleChoiceDialog(self, _("Pick the tables to close:"),
 
873
        dlg = MultipleChoiceDialog(self, _("Pick the tables to close:"),
760
874
                                     _("Close Table"), titles,
761
875
                                     size = (400, 300),
762
 
                                     style = wxDEFAULT_DIALOG_STYLE | 
763
 
                                             wxRESIZE_BORDER)
764
 
        if dlg.ShowModal() == wxID_OK:
 
876
                                     style = wx.DEFAULT_DIALOG_STYLE |
 
877
                                             wx.RESIZE_BORDER)
 
878
        if dlg.ShowModal() == wx.ID_OK:
765
879
            for i in dlg.GetValue():
766
880
                self.application.session.RemoveTable(lst[i][1])
767
881
 
777
891
        lst = [(t.Title(), t) for t in tables]
778
892
        lst.sort()
779
893
        titles = [i[0] for i in lst]
780
 
        dlg = wxMultipleChoiceDialog(self, _("Pick the table to show:"),
 
894
        dlg = MultipleChoiceDialog(self, _("Pick the table to show:"),
781
895
                                     _("Show Table"), titles,
782
 
                                     size = (400,300), 
783
 
                                     style = wxDEFAULT_DIALOG_STYLE | 
784
 
                                             wxRESIZE_BORDER)
785
 
        if (dlg.ShowModal() == wxID_OK):
 
896
                                     size = (400,300),
 
897
                                     style = wx.DEFAULT_DIALOG_STYLE |
 
898
                                             wx.RESIZE_BORDER)
 
899
        if (dlg.ShowModal() == wx.ID_OK):
786
900
            for i in dlg.GetValue():
787
901
                # XXX: if the table belongs to a layer, open a
788
902
                # LayerTableFrame instead of QueryTableFrame
812
926
        lst = [(t.Title(), t) for t in tables]
813
927
        lst.sort()
814
928
        titles = [i[0] for i in lst]
815
 
        dlg = wxMultipleChoiceDialog(self, _("Pick the table to rename:"),
 
929
        dlg = MultipleChoiceDialog(self, _("Pick the table to rename:"),
816
930
                                     _("Rename Table"), titles,
817
 
                                     size = (400,300), 
818
 
                                     style = wxDEFAULT_DIALOG_STYLE | 
819
 
                                             wxRESIZE_BORDER)
820
 
        if (dlg.ShowModal() == wxID_OK):
 
931
                                     size = (400,300),
 
932
                                     style = wx.DEFAULT_DIALOG_STYLE |
 
933
                                             wx.RESIZE_BORDER)
 
934
        if (dlg.ShowModal() == wx.ID_OK):
821
935
            to_rename = [lst[i][1] for i in dlg.GetValue()]
822
936
            dlg.Destroy()
823
937
        else:
825
939
 
826
940
        # Second, let the user rename the layers
827
941
        for table in to_rename:
828
 
            dlg = wxTextEntryDialog(self, _("Table Title:"), _("Rename Table"),
 
942
            dlg = wx.TextEntryDialog(self, _("Table Title:"), _("Rename Table"),
829
943
                                    table.Title())
830
944
            try:
831
 
                if dlg.ShowModal() == wxID_OK:
 
945
                if dlg.ShowModal() == wx.ID_OK:
832
946
                    title = dlg.GetValue()
833
947
                    if title != "":
834
948
                        table.SetTitle(title)
874
988
        self.canvas.Print()
875
989
 
876
990
    def RenameMap(self):
877
 
        dlg = wxTextEntryDialog(self, _("Map Title:"), _("Rename Map"),
 
991
        dlg = wx.TextEntryDialog(self, _("Map Title:"), _("Rename Map"),
878
992
                                self.Map().Title())
879
 
        if dlg.ShowModal() == wxID_OK:
 
993
        if dlg.ShowModal() == wx.ID_OK:
880
994
            title = dlg.GetValue()
881
995
            if title != "":
882
996
                self.Map().SetTitle(title)
887
1001
        """Let the user rename the currently selected layer"""
888
1002
        layer = self.current_layer()
889
1003
        if layer is not None:
890
 
            dlg = wxTextEntryDialog(self, _("Layer Title:"), _("Rename Layer"),
 
1004
            dlg = wx.TextEntryDialog(self, _("Layer Title:"), _("Rename Layer"),
891
1005
                                    layer.Title())
892
1006
            try:
893
 
                if dlg.ShowModal() == wxID_OK:
 
1007
                if dlg.ShowModal() == wx.ID_OK:
894
1008
                    title = dlg.GetValue()
895
1009
                    if title != "":
896
1010
                        layer.SetTitle(title)
986
1100
    """Return true if a layer is selected in the context"""
987
1101
    return context.mainwindow.has_selected_layer()
988
1102
 
 
1103
def _has_selected_layer_visible(context):
 
1104
    """Return true if a layer is selected in the context which is
 
1105
    visible."""
 
1106
    if context.mainwindow.has_selected_layer():
 
1107
        layer = context.mainwindow.current_layer()
 
1108
        if layer.Visible(): return True
 
1109
    return False
 
1110
 
989
1111
def _has_selected_shape_layer(context):
990
1112
    """Return true if a shape layer is selected in the context"""
991
1113
    return context.mainwindow.has_selected_shape_layer()
1009
1131
    if map is not None:
1010
1132
        for layer in map.Layers():
1011
1133
            if layer.Visible():
1012
 
                return 1
1013
 
    return 0
 
1134
                return True
 
1135
    return False
1014
1136
 
1015
1137
def _has_legend_shown(context):
1016
1138
    """Return true if the legend window is shown"""
1134
1256
                sensitive = _has_selected_shape_layer,
1135
1257
                helptext = _("Join and attach a table to the selected layer"))
1136
1258
 
 
1259
# further layer methods:
 
1260
_method_command("layer_to_top", _("&Top"), "LayerToTop",
 
1261
                helptext = _("Put selected layer to the top"),
 
1262
                sensitive = _has_selected_layer)
 
1263
_method_command("layer_to_bottom", _("&Bottom"), "LayerToBottom",
 
1264
                helptext = _("Put selected layer to the bottom"),
 
1265
                sensitive = _has_selected_layer)
 
1266
_method_command("layer_visibility", _("&Visible"), "ToggleLayerVisibility",
 
1267
                checked = _has_selected_layer_visible,
 
1268
                helptext = _("Toggle visibility of selected layer"),
 
1269
                sensitive = _has_selected_layer)
 
1270
 
1137
1271
def _can_unjoin(context):
1138
1272
    """Return whether the Layer/Unjoin command can be executed.
1139
1273
 
1188
1322
                        None,
1189
1323
                        "toggle_legend",
1190
1324
                        None]
1191
 
if wxPlatform == '__WXMSW__':
 
1325
if wx.Platform == '__WXMSW__':
1192
1326
    map_menu.append("map_export")
1193
1327
map_menu.append("map_print")
1194
1328
 
1227
1361
# the main toolbar
1228
1362
 
1229
1363
main_toolbar = Menu("<toolbar>", "<toolbar>",
1230
 
                    ["map_zoom_in_tool", "map_zoom_out_tool", "map_pan_tool", 
1231
 
                     "map_full_extent", 
1232
 
                     "layer_full_extent", 
1233
 
                     "selected_full_extent", 
1234
 
                     None, 
 
1364
                    ["map_zoom_in_tool", "map_zoom_out_tool", "map_pan_tool",
 
1365
                     "map_full_extent",
 
1366
                     "layer_full_extent",
 
1367
                     "selected_full_extent",
 
1368
                     None,
1235
1369
                     "map_identify_tool", "map_label_tool"])
1236
1370