/[thuban]/branches/WIP-pyshapelib-bramz/Thuban/UI/tableview.py
ViewVC logotype

Diff of /branches/WIP-pyshapelib-bramz/Thuban/UI/tableview.py

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1027 by frank, Mon May 26 11:47:17 2003 UTC revision 1892 by bh, Thu Oct 30 18:16:53 2003 UTC
# Line 17  from wxPython.grid import * Line 17  from wxPython.grid import *
17  from Thuban.Lib.connector import Publisher  from Thuban.Lib.connector import Publisher
18  from Thuban.Model.table import FIELDTYPE_INT, FIELDTYPE_DOUBLE, \  from Thuban.Model.table import FIELDTYPE_INT, FIELDTYPE_DOUBLE, \
19       FIELDTYPE_STRING, table_to_dbf, table_to_csv       FIELDTYPE_STRING, table_to_dbf, table_to_csv
20  import view  from dialogs import ThubanFrame
21  from dialogs import NonModalDialog  
22  from messages import SHAPES_SELECTED  from messages import SHAPES_SELECTED, SESSION_REPLACED
23    from Thuban.Model.messages import TABLE_REMOVED, MAP_LAYERS_REMOVED
24    from Thuban.UI.common import ThubanBeginBusyCursor, ThubanEndBusyCursor
25    
26  wx_value_type_map = {FIELDTYPE_INT: wxGRID_VALUE_NUMBER,  wx_value_type_map = {FIELDTYPE_INT: wxGRID_VALUE_NUMBER,
27                       FIELDTYPE_DOUBLE: wxGRID_VALUE_FLOAT,                       FIELDTYPE_DOUBLE: wxGRID_VALUE_FLOAT,
# Line 69  class DataTable(wxPyGridTableBase): Line 71  class DataTable(wxPyGridTableBase):
71      # Renderer understands the type too,) not just strings as in the      # Renderer understands the type too,) not just strings as in the
72      # C++ version.      # C++ version.
73      def GetValue(self, row, col):      def GetValue(self, row, col):
74          record = self.table.ReadRowAsDict(row)          record = self.table.ReadRowAsDict(row, row_is_ordinal = 1)
75          return record[self.columns[col][0]]          return record[self.columns[col][0]]
76    
77      def SetValue(self, row, col, value):      def SetValue(self, row, col, value):
# Line 100  class DataTable(wxPyGridTableBase): Line 102  class DataTable(wxPyGridTableBase):
102          return self.CanGetValueAs(row, col, typeName)          return self.CanGetValueAs(row, col, typeName)
103    
104    
105        #
106        def RowIdToOrdinal(self, rowid):
107            """Return the ordinal of the row given by its id"""
108            return self.table.RowIdToOrdinal(rowid)
109    
110        def RowOrdinalToId(self, ordinal):
111            """Return the id of the row given by its ordinal"""
112            return self.table.RowOrdinalToId(ordinal)
113    
114    
115    class NullRenderer(wxPyGridCellRenderer):
116    
117        """Renderer that draws NULL as a gray rectangle
118    
119        Other values are delegated to a normal renderer which is given as
120        the parameter to the constructor.
121        """
122    
123        def __init__(self, non_null_renderer):
124            wxPyGridCellRenderer.__init__(self)
125            self.non_null_renderer = non_null_renderer
126    
127        def Draw(self, grid, attr, dc, rect, row, col, isSelected):
128            value = grid.table.GetValue(row, col)
129            if value is None:
130                dc.SetBackgroundMode(wxSOLID)
131                dc.SetBrush(wxBrush(wxColour(192, 192, 192), wxSOLID))
132                dc.SetPen(wxTRANSPARENT_PEN)
133                dc.DrawRectangle(rect.x, rect.y, rect.width, rect.height)
134            else:
135                self.non_null_renderer.Draw(grid, attr, dc, rect, row, col,
136                                            isSelected)
137    
138        def GetBestSize(self, grid, attr, dc, row, col):
139            self.non_null_renderer.GetBestSize(grid, attr, dc, row, col)
140    
141        def Clone(self):
142            return NullRenderer(self.non_null_renderer)
143    
144    
145  class TableGrid(wxGrid, Publisher):  class TableGrid(wxGrid, Publisher):
146    
147      """A grid view for a Thuban table      """A grid view for a Thuban table
# Line 117  class TableGrid(wxGrid, Publisher): Line 159  class TableGrid(wxGrid, Publisher):
159    
160          self.allow_messages_count = 0          self.allow_messages_count = 0
161    
162            # keep track of which rows are selected.
163            self.rows = {}
164    
165          self.table = DataTable(table)          self.table = DataTable(table)
166    
167          # The second parameter means that the grid is to take ownership          # The second parameter means that the grid is to take ownership
168          # of the table and will destroy it when done. Otherwise you          # of the table and will destroy it when done. Otherwise you
169          # would need to keep a reference to it and call its Destroy          # would need to keep a reference to it and call its Destroy
170          # method later.          # method later.
171          self.SetTable(self.table, true)          self.SetTable(self.table, True)
172    
173          #self.SetMargins(0,0)          #self.SetMargins(0,0)
174    
# Line 131  class TableGrid(wxGrid, Publisher): Line 176  class TableGrid(wxGrid, Publisher):
176          # column widths automatically but it would cause a traversal of          # column widths automatically but it would cause a traversal of
177          # the entire table which for large .dbf files can take a very          # the entire table which for large .dbf files can take a very
178          # long time.          # long time.
179          #self.AutoSizeColumns(false)          #self.AutoSizeColumns(False)
180    
181          self.SetSelectionMode(wxGrid.wxGridSelectRows)          self.SetSelectionMode(wxGrid.wxGridSelectRows)
182    
         #EVT_GRID_RANGE_SELECT(self, None)  
         #EVT_GRID_SELECT_CELL(self, None)  
         #EVT_GRID_RANGE_SELECT(self, self.OnRangeSelect)  
         #EVT_GRID_SELECT_CELL(self, self.OnSelectCell)  
   
183          self.ToggleEventListeners(True)          self.ToggleEventListeners(True)
184            EVT_GRID_RANGE_SELECT(self, self.OnRangeSelect)
185            EVT_GRID_SELECT_CELL(self, self.OnSelectCell)
186    
187            # Replace the normal renderers with our own versions which
188            # render NULL/None values specially
189            self.RegisterDataType(wxGRID_VALUE_STRING,
190                                  NullRenderer(wxGridCellStringRenderer()), None)
191            self.RegisterDataType(wxGRID_VALUE_NUMBER,
192                                  NullRenderer(wxGridCellNumberRenderer()), None)
193            self.RegisterDataType(wxGRID_VALUE_FLOAT,
194                                  NullRenderer(wxGridCellFloatRenderer()), None)
195    
196      def SetTableObject(self, table):      def SetTableObject(self, table):
197          self.table.SetTable(table)          self.table.SetTable(table)
198    
199      def OnRangeSelect(self, event):      def OnRangeSelect(self, event):
200          rows = dict([(i, 0) for i in self.GetSelectedRows()])          to_id = self.table.RowOrdinalToId
201            if self.handleSelectEvents:
202                self.rows = dict([(to_id(i), 0) for i in self.GetSelectedRows()])
203    
204                # if we're selecting we need to include the selected range and
205                # make sure that the current row is also included, which may
206                # not be the case if you just click on a single row!
207                if event.Selecting():
208                    for i in range(event.GetTopRow(), event.GetBottomRow() + 1):
209                        self.rows[to_id(i)] = 0
210                    self.rows[to_id(event.GetTopLeftCoords().GetRow())] = 0
211    
212          # if we're selecting we need to include the selected range and              self.issue(ROW_SELECTED, self.rows.keys())
         # make sure that the current row is also included, which may  
         # not be the case if you just click on a single row!  
         if event.Selecting():  
             for i in range(event.GetTopRow(), event.GetBottomRow() + 1):  
                 rows[i] = 0  
             rows[event.GetTopLeftCoords().GetRow()] = 0  
213    
         self.issue(ROW_SELECTED, rows.keys())  
214          event.Skip()          event.Skip()
215    
216      def OnSelectCell(self, event):      def OnSelectCell(self, event):
217          self.issue(ROW_SELECTED, self.GetSelectedRows())          to_id = self.table.RowOrdinalToId
218            if self.handleSelectEvents:
219                self.issue(ROW_SELECTED,
220                           [to_id(i) for i in self.GetSelectedRows()])
221          event.Skip()          event.Skip()
222    
223      def ToggleEventListeners(self, on):      def ToggleEventListeners(self, on):
224          if on:          self.handleSelectEvents = on
225              EVT_GRID_RANGE_SELECT(self, self.OnRangeSelect)  
226              EVT_GRID_SELECT_CELL(self, self.OnSelectCell)      def GetNumberSelected(self):
227          else:          return len(self.rows)
228              EVT_GRID_RANGE_SELECT(self, None)  
             EVT_GRID_SELECT_CELL(self, None)  
               
229      def disallow_messages(self):      def disallow_messages(self):
230          """Disallow messages to be send.          """Disallow messages to be send.
231    
# Line 197  class TableGrid(wxGrid, Publisher): Line 252  class TableGrid(wxGrid, Publisher):
252          if self.allow_messages_count == 0:          if self.allow_messages_count == 0:
253              Publisher.issue(self, *args)              Publisher.issue(self, *args)
254    
255        def SelectRowById(self, rowid, do_select):
256            """Select row with the id rowid"""
257            self.SelectRow(self.table.RowIdToOrdinal(rowid), do_select)
258    
259    
260  class LayerTableGrid(TableGrid):  class LayerTableGrid(TableGrid):
261    
# Line 213  class LayerTableGrid(TableGrid): Line 272  class LayerTableGrid(TableGrid):
272          nothing. If shape or layer is None also do nothing.          nothing. If shape or layer is None also do nothing.
273          """          """
274          if layer is not None \          if layer is not None \
275              and layer.table is self.table.table:              and layer.ShapeStore().Table() is self.table.table:
276    
277              self.disallow_messages()              self.disallow_messages()
278              try:              try:
279                  self.ClearSelection()                  self.ClearSelection()
280                  if len(shapes) > 0:                  if len(shapes) > 0:
281                      #                      # keep track of the lowest id so we can make it the
282                      # keep track of the lowest id so we can make it                      # first visible item
283                      # the first visible item                      first = -1
                     #  
                     first = shapes[0]  
284    
285                        to_ordinal = self.table.RowIdToOrdinal
286                      for shape in shapes:                      for shape in shapes:
287                          self.SelectRow(shape, True)                          row = to_ordinal(shape)
288                          if shape < first:                          self.SelectRow(row, True)
289                              first = shape                          if row < first:
290                                first = row
291    
292                      self.SetGridCursor(first, 0)                      self.SetGridCursor(first, 0)
293                      self.MakeCellVisible(first, 0)                      self.MakeCellVisible(first, 0)
# Line 236  class LayerTableGrid(TableGrid): Line 295  class LayerTableGrid(TableGrid):
295                  self.allow_messages()                  self.allow_messages()
296    
297    
298  class TableFrame(NonModalDialog):  class TableFrame(ThubanFrame):
299    
300      """Frame that displays a Thuban table in a grid view"""      """Frame that displays a Thuban table in a grid view"""
301    
302      def __init__(self, parent, name, title, table):      def __init__(self, parent, name, title, table):
303          NonModalDialog.__init__(self, parent, name, title)          ThubanFrame.__init__(self, parent, name, title)
304            self.panel = wxPanel(self, -1)
305    
306          self.table = table          self.table = table
307          self.grid = self.make_grid(self.table)          self.grid = self.make_grid(self.table)
308            self.app = self.parent.application
309            self.app.Subscribe(SESSION_REPLACED, self.close_on_session_replaced)
310            self.session = self.app.Session()
311            self.session.Subscribe(TABLE_REMOVED, self.close_on_table_removed)
312    
313        def OnDestroy(self, event):
314            """Extend inherited method to unsubscribe messages"""
315            self.app.Unsubscribe(SESSION_REPLACED, self.close_on_session_replaced)
316            self.session.Unsubscribe(TABLE_REMOVED, self.close_on_table_removed)
317            ThubanFrame.OnDestroy(self, event)
318    
319      def make_grid(self, table):      def make_grid(self, table):
320          """Return the table grid to use in the frame.          """Return the table grid to use in the frame.
# Line 253  class TableFrame(NonModalDialog): Line 324  class TableFrame(NonModalDialog):
324          """          """
325          return TableGrid(self, table)          return TableGrid(self, table)
326    
327        def close_on_session_replaced(self, *args):
328            """Subscriber for the SESSION_REPLACED messages.
329    
330            The table frame is tied to a session so close the window when
331            the session changes.
332            """
333            self.Close()
334    
335        def close_on_table_removed(self, table):
336            """Subscriber for the TABLE_REMOVED messages.
337    
338            The table frame is tied to a particular table so close the
339            window when the table is removed.
340            """
341            if table is self.table:
342                self.Close()
343    
344    
345  ID_QUERY = 4001  ID_QUERY = 4001
346  ID_EXPORT = 4002  ID_EXPORT = 4002
347    ID_COMBOVALUE = 4003
348    ID_EXPORTSEL = 4004
349    
350  class QueryTableFrame(TableFrame):  class QueryTableFrame(TableFrame):
351    
352      """Frame that displays a table in a grid view and offers user actions      """Frame that displays a table in a grid view and offers user actions
353      selection and export      selection and export
354    
355      A LayerTableFrame is TableFrame whose selection is connected to the      A QueryTableFrame is TableFrame whose selection is connected to the
356      selected object in a map.      selected object in a map.
357      """      """
358    
359      def __init__(self, parent, name, title, table):      def __init__(self, parent, name, title, table):
360          TableFrame.__init__(self, parent, name, title, table)          TableFrame.__init__(self, parent, name, title, table)
361    
362          self.combo_fields = wxComboBox(self, -1, style=wxCB_READONLY)          self.combo_fields = wxComboBox(self.panel, -1, style=wxCB_READONLY)
363          self.choice_comp = wxChoice(self, -1,          self.choice_comp = wxChoice(self.panel, -1,
364                                choices=["<", "<=", "==", "!=", ">=", ">"])                                choices=["<", "<=", "==", "!=", ">=", ">"])
365          self.combo_value = wxComboBox(self, -1)          self.combo_value = wxComboBox(self.panel, ID_COMBOVALUE)
366          self.choice_action = wxChoice(self, -1,          self.choice_action = wxChoice(self.panel, -1,
367                                  choices=[_("Replace Selection"),                                  choices=[_("Replace Selection"),
368                                          _("Refine Selection"),                                          _("Refine Selection"),
369                                          _("Add to Selection")])                                          _("Add to Selection")])
370    
371          button_query = wxButton(self, ID_QUERY, _("Query"))          button_query = wxButton(self.panel, ID_QUERY, _("Query"))
372          button_saveas = wxButton(self, ID_EXPORT, _("Export"))          button_export = wxButton(self.panel, ID_EXPORT, _("Export"))
373            button_exportSel = wxButton(self.panel, ID_EXPORTSEL, _("Export Selection"))
374            button_close = wxButton(self.panel, wxID_CLOSE, _("Close"))
375    
376            self.CreateStatusBar()
377    
378          self.grid.SetSize((400, 200))          self.grid.SetSize((400, 200))
379    
# Line 292  class QueryTableFrame(TableFrame): Line 386  class QueryTableFrame(TableFrame):
386          # assume at least one field?          # assume at least one field?
387          self.combo_fields.SetSelection(0)          self.combo_fields.SetSelection(0)
388          self.combo_value.SetSelection(0)          self.combo_value.SetSelection(0)
389            self.choice_action.SetSelection(0)
390            self.choice_comp.SetSelection(0)
391    
392            self.grid.Reparent(self.panel)
393    
394            self.UpdateStatusText()
395    
396          topBox = wxBoxSizer(wxVERTICAL)          topBox = wxBoxSizer(wxVERTICAL)
397    
398          sizer = wxStaticBoxSizer(wxStaticBox(self, -1, _("Selection")),          sizer = wxStaticBoxSizer(wxStaticBox(self.panel, -1,
399                                      _("Selection")),
400                                    wxHORIZONTAL)                                    wxHORIZONTAL)
401          sizer.Add(self.combo_fields, 1, wxEXPAND|wxALL, 4)          sizer.Add(self.combo_fields, 1, wxEXPAND|wxALL, 4)
402          sizer.Add(self.choice_comp, 0, wxALL, 4)          sizer.Add(self.choice_comp, 0, wxALL, 4)
# Line 303  class QueryTableFrame(TableFrame): Line 404  class QueryTableFrame(TableFrame):
404          sizer.Add(self.choice_action, 0, wxALL, 4)          sizer.Add(self.choice_action, 0, wxALL, 4)
405          sizer.Add(button_query, 0, wxALL | wxALIGN_CENTER_VERTICAL, 4)          sizer.Add(button_query, 0, wxALL | wxALIGN_CENTER_VERTICAL, 4)
406          sizer.Add(40, 20, 0, wxALL, 4)          sizer.Add(40, 20, 0, wxALL, 4)
         sizer.Add(button_saveas, 0, wxALL | wxALIGN_CENTER_VERTICAL, 4)  
407    
408          topBox.Add(sizer, 0, wxEXPAND|wxALL, 4)          topBox.Add(sizer, 0, wxEXPAND|wxALL, 4)
409          topBox.Add(self.grid, 1, wxEXPAND|wxALL, 0)          topBox.Add(self.grid, 1, wxEXPAND|wxALL, 0)
410    
411            sizer = wxBoxSizer(wxHORIZONTAL)
412            sizer.Add(button_export, 0, wxALL, 4)
413            sizer.Add(button_exportSel, 0, wxALL, 4)
414            sizer.Add(60, 20, 1, wxALL|wxEXPAND, 4)
415            sizer.Add(button_close, 0, wxALL|wxALIGN_RIGHT, 4)
416            topBox.Add(sizer, 0, wxALL | wxEXPAND, 4)
417    
418            self.panel.SetAutoLayout(True)
419            self.panel.SetSizer(topBox)
420            topBox.Fit(self.panel)
421            topBox.SetSizeHints(self.panel)
422    
423            panelSizer = wxBoxSizer(wxVERTICAL)
424            panelSizer.Add(self.panel, 1, wxEXPAND, 0)
425          self.SetAutoLayout(True)          self.SetAutoLayout(True)
426          self.SetSizer(topBox)          self.SetSizer(panelSizer)
427          topBox.Fit(self)          panelSizer.Fit(self)
428          topBox.SetSizeHints(self)          panelSizer.SetSizeHints(self)
429    
430          self.grid.SetFocus()          self.grid.SetFocus()
431    
432          EVT_BUTTON(self, ID_QUERY, self.OnQuery)          EVT_BUTTON(self, ID_QUERY, self.OnQuery)
433          EVT_BUTTON(self, ID_EXPORT, self.OnSaveAs)          EVT_BUTTON(self, ID_EXPORT, self.OnExport)
434            EVT_BUTTON(self, ID_EXPORTSEL, self.OnExportSel)
435            EVT_BUTTON(self, wxID_CLOSE, self.OnClose)
436          EVT_KEY_DOWN(self.grid, self.OnKeyDown)          EVT_KEY_DOWN(self.grid, self.OnKeyDown)
437    
438            self.grid.Subscribe(ROW_SELECTED, self.UpdateStatusText)
439    
440        def UpdateStatusText(self, rows=None):
441            self.SetStatusText(_("%i rows (%i selected), %i columns")
442                % (self.grid.GetNumberRows(),
443                   self.grid.GetNumberSelected(),
444                   self.grid.GetNumberCols()))
445    
446      def OnKeyDown(self, event):      def OnKeyDown(self, event):
447          """Catch query key from grid"""          """Catch query key from grid"""
448          if event.AltDown() and event.GetKeyCode() == ord(QUERY_KEY):          if event.AltDown() and event.GetKeyCode() == ord(QUERY_KEY):
# Line 326  class QueryTableFrame(TableFrame): Line 451  class QueryTableFrame(TableFrame):
451          else:          else:
452              event.Skip()              event.Skip()
453    
   
454      def OnQuery(self, event):      def OnQuery(self, event):
455          wxBeginBusyCursor()          ThubanBeginBusyCursor()
456            try:
         if self.combo_value.GetSelection() < 1:  
             value = self.combo_value.GetValue()  
         else:  
             value = self.table.Column(self.combo_value.GetValue())  
457    
458          ids = self.table.SimpleQuery(              text = self.combo_value.GetValue()
459                  self.table.Column(self.combo_fields.GetStringSelection()),              if self.combo_value.GetSelection() < 1 \
460                  self.choice_comp.GetStringSelection(),                  or self.combo_value.FindString(text) == -1:
461                  value)                  value = text
   
         choice = self.choice_action.GetSelection()  
               
         #  
         # what used to be nice code got became a bit ugly because  
         # each time we select a row a message is sent to the grid  
         # which we are listening for and then we send further  
         # messages.  
         #  
         # now, we disable those listeners select everything but  
         # the first item, reenable the listeners, and select  
         # the first element, which causes everything to be  
         # updated properly.  
         #  
         self.grid.ToggleEventListeners(False)  
   
         if choice == 0:  
             # Replace Selection  
             self.grid.ClearSelection()  
         elif choice == 1:  
             # Refine Selection  
             sel = self.get_selected()  
             self.grid.ClearSelection()  
             ids = filter(sel.has_key, ids)  
         elif choice == 2:  
             # Add to Selection  
             pass  
   
         #  
         # select the rows (all but the first)  
         #  
         firsttime = True  
         for id in ids:  
             if firsttime:  
                 firsttime = False  
462              else:              else:
463                  self.grid.SelectRow(id, True)                  value = self.table.Column(text)
464    
465          self.grid.ToggleEventListeners(True)              ids = self.table.SimpleQuery(
466                        self.table.Column(self.combo_fields.GetStringSelection()),
467                        self.choice_comp.GetStringSelection(),
468                        value)
469    
470          #              choice = self.choice_action.GetSelection()
471          # select the first row              
472          #              #
473          if ids:              # what used to be nice code got became a bit ugly because
474              self.grid.SelectRow(ids[0], True)              # each time we select a row a message is sent to the grid
475                # which we are listening for and then we send further
476                # messages.
477                #
478                # now, we disable those listeners select everything but
479                # the first item, reenable the listeners, and select
480                # the first element, which causes everything to be
481                # updated properly.
482                #
483                if ids:
484                    self.grid.ToggleEventListeners(False)
485    
486                if choice == 0:
487                    # Replace Selection
488                    self.grid.ClearSelection()
489                elif choice == 1:
490                    # Refine Selection
491                    sel = self.get_selected()
492                    self.grid.ClearSelection()
493                    ids = filter(sel.has_key, ids)
494                elif choice == 2:
495                    # Add to Selection
496                    pass
497    
498                #
499                # select the rows (all but the first)
500                #
501                firsttime = True
502                for id in ids:
503                    if firsttime:
504                        firsttime = False
505                    else:
506                        self.grid.SelectRowById(id, True)
507    
508                self.grid.ToggleEventListeners(True)
509    
510                #
511                # select the first row
512                #
513                if ids:
514                    self.grid.SelectRowById(ids[0], True)
515    
516          wxEndBusyCursor()          finally:
517                ThubanEndBusyCursor()
518            
519        def doExport(self, onlySelected):
520                    
     def OnSaveAs(self, event):  
521          dlg = wxFileDialog(self, _("Export Table To"), ".", "",          dlg = wxFileDialog(self, _("Export Table To"), ".", "",
522                             _("DBF Files (*.dbf)|*.dbf|") +                             _("DBF Files (*.dbf)|*.dbf|") +
523                             _("CSV Files (*.csv)|*.csv|") +                             _("CSV Files (*.csv)|*.csv|") +
# Line 397  class QueryTableFrame(TableFrame): Line 527  class QueryTableFrame(TableFrame):
527              filename = dlg.GetPath()              filename = dlg.GetPath()
528              type = os.path.basename(filename).split('.')[-1:][0]              type = os.path.basename(filename).split('.')[-1:][0]
529              dlg.Destroy()              dlg.Destroy()
530    
531                if onlySelected:
532                    records = self.grid.GetSelectedRows()
533                else:
534                    records = None
535    
536              if type.upper() == "DBF":              if type.upper() == "DBF":
537                  table_to_dbf(self.table, filename)                  table_to_dbf(self.table, filename, records)
538              elif type.upper() == 'CSV':              elif type.upper() == 'CSV':
539                  table_to_csv(self.table, filename)                  table_to_csv(self.table, filename, records)
540              else:              else:
541                  dlg = wxMessageDialog(None, "Unsupported format: %s" % type,                  dlg = wxMessageDialog(None, "Unsupported format: %s" % type,
542                                        "Table Export", wxOK|wxICON_WARNING)                                        "Table Export", wxOK|wxICON_WARNING)
# Line 409  class QueryTableFrame(TableFrame): Line 545  class QueryTableFrame(TableFrame):
545          else:          else:
546              dlg.Destroy()              dlg.Destroy()
547    
548        def OnExport(self, event):
549            self.doExport(False)
550    
551        def OnExportSel(self, event):
552            self.doExport(True)
553    
554      def OnClose(self, event):      def OnClose(self, event):
555          TableFrame.OnClose(self, event)          TableFrame.OnClose(self, event)
556    
557      def get_selected(self):      def get_selected(self):
558          """Return a dictionary of the selected rows.          """Return a dictionary of the selected rows.
559            
560          The dictionary has sthe indexes as keys."""          The dictionary has the indexes as keys."""
561          return dict([(i, 0) for i in self.grid.GetSelectedRows()])          to_id = self.table.RowOrdinalToId
562            return dict([(to_id(i), 0) for i in self.grid.GetSelectedRows()])
563    
564    
565  class LayerTableFrame(QueryTableFrame):  class LayerTableFrame(QueryTableFrame):
566    
# Line 431  class LayerTableFrame(QueryTableFrame): Line 575  class LayerTableFrame(QueryTableFrame):
575          self.layer = layer          self.layer = layer
576          self.grid.Subscribe(ROW_SELECTED, self.rows_selected)          self.grid.Subscribe(ROW_SELECTED, self.rows_selected)
577          self.parent.Subscribe(SHAPES_SELECTED, self.select_shapes)          self.parent.Subscribe(SHAPES_SELECTED, self.select_shapes)
578            self.map = self.parent.Map()
579            self.map.Subscribe(MAP_LAYERS_REMOVED, self.map_layers_removed)
580    
581            # if there is already a selection present, update the grid
582            # accordingly
583            sel = self.get_selected().keys()
584            for i in sel:
585                self.grid.SelectRowById(i, True)
586    
587        def OnDestroy(self, event):
588            """Extend inherited method to unsubscribe messages"""
589            self.parent.Unsubscribe(SHAPES_SELECTED, self.select_shapes)
590            self.grid.Unsubscribe(ROW_SELECTED, self.rows_selected)
591            self.map.Unsubscribe(MAP_LAYERS_REMOVED, self.map_layers_removed)
592            QueryTableFrame.OnDestroy(self, event)
593    
594      def make_grid(self, table):      def make_grid(self, table):
595          """Override the derived method to return a LayerTableGrid.          """Override the derived method to return a LayerTableGrid.
# Line 443  class LayerTableFrame(QueryTableFrame): Line 602  class LayerTableFrame(QueryTableFrame):
602          """          """
603          return dict([(i, 0) for i in self.parent.SelectedShapes()])          return dict([(i, 0) for i in self.parent.SelectedShapes()])
604    
     def OnClose(self, event):  
         """Override the derived method to first unsubscribed."""  
         self.parent.Unsubscribe(SHAPES_SELECTED, self.select_shapes)  
         QueryTableFrame.OnClose(self, event)  
   
605      def select_shapes(self, layer, shapes):      def select_shapes(self, layer, shapes):
606          """Subscribed to the SHAPES_SELECTED message.          """Subscribed to the SHAPES_SELECTED message.
607    
# Line 462  class LayerTableFrame(QueryTableFrame): Line 616  class LayerTableFrame(QueryTableFrame):
616          """          """
617          if self.layer is not None:          if self.layer is not None:
618              self.parent.SelectShapes(self.layer, rows)              self.parent.SelectShapes(self.layer, rows)
619    
620        def map_layers_removed(self, *args):
621            """Receiver for the map's MAP_LAYERS_REMOVED message
622    
623            Close the dialog if the layer whose table we're showing is not
624            in the map anymore.
625            """
626            if self.layer not in self.map.Layers():
627                self.Close()
628    

Legend:
Removed from v.1027  
changed lines
  Added in v.1892

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26