/[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 808 by bh, Mon May 5 10:33:47 2003 UTC revision 1013 by jan, Fri May 23 09:18:28 2003 UTC
# Line 7  Line 7 
7    
8  __version__ = "$Revision$"  __version__ = "$Revision$"
9    
10    from Thuban import _
11    
12  from wxPython.wx import *  from wxPython.wx import *
13  from wxPython.grid import *  from wxPython.grid import *
14    
# Line 23  wx_value_type_map = {FIELDTYPE_INT: wxGR Line 25  wx_value_type_map = {FIELDTYPE_INT: wxGR
25    
26  ROW_SELECTED = "ROW_SELECTED"  ROW_SELECTED = "ROW_SELECTED"
27    
28    QUERY_KEY = 'S'
29    
30  class DataTable(wxPyGridTableBase):  class DataTable(wxPyGridTableBase):
31    
# Line 38  class DataTable(wxPyGridTableBase): Line 41  class DataTable(wxPyGridTableBase):
41    
42      def SetTable(self, table):      def SetTable(self, table):
43          self.table = table          self.table = table
44          self.num_cols = table.field_count()          self.num_cols = table.NumColumns()
45          self.num_rows = table.record_count()          self.num_rows = table.NumRows()
46    
47          self.columns = []          self.columns = []
48          for i in range(self.num_cols):          for i in range(self.num_cols):
49              type, name, len, decc = table.field_info(i)              col = table.Column(i)
50              self.columns.append((name, wx_value_type_map[type], len, decc))              self.columns.append((col.name, wx_value_type_map[col.type]))
51    
52      #      #
53      # required methods for the wxPyGridTableBase interface      # required methods for the wxPyGridTableBase interface
# Line 64  class DataTable(wxPyGridTableBase): Line 67  class DataTable(wxPyGridTableBase):
67      # Renderer understands the type too,) not just strings as in the      # Renderer understands the type too,) not just strings as in the
68      # C++ version.      # C++ version.
69      def GetValue(self, row, col):      def GetValue(self, row, col):
70          record = self.table.read_record(row)          record = self.table.ReadRowAsDict(row)
71          return record[self.columns[col][0]]          return record[self.columns[col][0]]
72    
73      def SetValue(self, row, col, value):      def SetValue(self, row, col, value):
# Line 130  class TableGrid(wxGrid, Publisher): Line 133  class TableGrid(wxGrid, Publisher):
133    
134          self.SetSelectionMode(wxGrid.wxGridSelectRows)          self.SetSelectionMode(wxGrid.wxGridSelectRows)
135    
136          EVT_GRID_RANGE_SELECT(self, self.OnRangeSelect)          #EVT_GRID_RANGE_SELECT(self, None)
137          EVT_GRID_SELECT_CELL(self, self.OnSelectCell)          #EVT_GRID_SELECT_CELL(self, None)
138            #EVT_GRID_RANGE_SELECT(self, self.OnRangeSelect)
139            #EVT_GRID_SELECT_CELL(self, self.OnSelectCell)
140    
141            self.ToggleEventListeners(True)
142    
143      def SetTableObject(self, table):      def SetTableObject(self, table):
144          self.table.SetTable(table)          self.table.SetTable(table)
145    
146      def OnRangeSelect(self, event):      def OnRangeSelect(self, event):
147            rows = dict([(i, 0) for i in self.GetSelectedRows()])
148    
149            # if we're selecting we need to include the selected range and
150            # make sure that the current row is also included, which may
151            # not be the case if you just click on a single row!
152          if event.Selecting():          if event.Selecting():
153              self.issue(ROW_SELECTED, event.GetTopLeftCoords().GetRow())              for i in range(event.GetTopRow(), event.GetBottomRow() + 1):
154                    rows[i] = 0
155                rows[event.GetTopLeftCoords().GetRow()] = 0
156    
157            self.issue(ROW_SELECTED, rows.keys())
158            event.Skip()
159    
160      def OnSelectCell(self, event):      def OnSelectCell(self, event):
161          self.issue(ROW_SELECTED, event.GetRow())          self.issue(ROW_SELECTED, self.GetSelectedRows())
162            event.Skip()
163    
164        def ToggleEventListeners(self, on):
165            if on:
166                EVT_GRID_RANGE_SELECT(self, self.OnRangeSelect)
167                EVT_GRID_SELECT_CELL(self, self.OnSelectCell)
168            else:
169                EVT_GRID_RANGE_SELECT(self, None)
170                EVT_GRID_SELECT_CELL(self, None)
171                
172      def disallow_messages(self):      def disallow_messages(self):
173          """Disallow messages to be send.          """Disallow messages to be send.
174    
# Line 178  class LayerTableGrid(TableGrid): Line 204  class LayerTableGrid(TableGrid):
204      selection is usually coupled to the selected object in the map.      selection is usually coupled to the selected object in the map.
205      """      """
206    
207      def select_shape(self, layer, shape):      def select_shapes(self, layer, shapes):
208          """Select the row corresponding to the specified shape and layer          """Select the row corresponding to the specified shape and layer
209    
210          If layer is not the layer the table is associated with do          If layer is not the layer the table is associated with do
211          nothing. If shape or layer is None also do nothing.          nothing. If shape or layer is None also do nothing.
212          """          """
213          if layer is not None and layer.table is self.table.table \          if layer is not None \
214             and shape is not None:              and layer.table is self.table.table:
215    
216              self.disallow_messages()              self.disallow_messages()
217              try:              try:
218                  self.SelectRow(shape)                  self.ClearSelection()
219                  self.SetGridCursor(shape, 0)                  if len(shapes) > 0:
220                  self.MakeCellVisible(shape, 0)                      #
221                        # keep track of the lowest id so we can make it
222                        # the first visible item
223                        #
224                        first = shapes[0]
225    
226                        for shape in shapes:
227                            self.SelectRow(shape, True)
228                            if shape < first:
229                                first = shape
230    
231                        self.SetGridCursor(first, 0)
232                        self.MakeCellVisible(first, 0)
233              finally:              finally:
234                  self.allow_messages()                  self.allow_messages()
235    
# Line 213  class TableFrame(NonModalDialog): Line 252  class TableFrame(NonModalDialog):
252          return TableGrid(self, table)          return TableGrid(self, table)
253    
254    
255  class LayerTableFrame(TableFrame):  ID_QUERY = 4001
256    ID_EXPORT = 4002
257    
258      """Frame that displays a layer table in a grid view  class QueryTableFrame(TableFrame):
259    
260        """Frame that displays a table in a grid view and offers user actions
261        selection and export
262    
263      A LayerTableFrame is TableFrame whose selection is connected to the      A LayerTableFrame is TableFrame whose selection is connected to the
264      selected object in a map.      selected object in a map.
265      """      """
266    
267      def __init__(self, parent, name, title, layer, table):      def __init__(self, parent, name, title, table):
268          TableFrame.__init__(self, parent, name, title, table)          TableFrame.__init__(self, parent, name, title, table)
269    
270            self.combo_fields = wxComboBox(self, -1, style=wxCB_READONLY)
271            self.choice_comp = wxChoice(self, -1,
272                                  choices=["<", "<=", "==", "!=", ">=", ">"])
273            self.combo_value = wxComboBox(self, -1)
274            self.choice_action = wxChoice(self, -1,
275                                    choices=[_("Replace Selection"),
276                                            _("Refine Selection"),
277                                            _("Add to Selection")])
278    
279            button_query = wxButton(self, ID_QUERY, _("Query"))
280            button_saveas = wxButton(self, ID_EXPORT, _("Export"))
281    
282            self.grid.SetSize((400, 200))
283    
284            self.combo_value.Append("")
285            for i in range(table.NumColumns()):
286                name = table.Column(i).name
287                self.combo_fields.Append(name)
288                self.combo_value.Append(name)
289    
290            # assume at least one field?
291            self.combo_fields.SetSelection(0)
292            self.combo_value.SetSelection(0)
293    
294            topBox = wxBoxSizer(wxVERTICAL)
295    
296            sizer = wxStaticBoxSizer(wxStaticBox(self, -1, _("Selection")),
297                                      wxHORIZONTAL)
298            sizer.Add(self.combo_fields, 1, wxEXPAND|wxALL, 4)
299            sizer.Add(self.choice_comp, 0, wxALL, 4)
300            sizer.Add(self.combo_value, 1, wxEXPAND|wxALL, 4)
301            sizer.Add(self.choice_action, 0, wxALL, 4)
302            sizer.Add(button_query, 0, wxALL | wxALIGN_CENTER_VERTICAL, 4)
303            sizer.Add(40, 20, 0, wxALL, 4)
304            sizer.Add(button_saveas, 0, wxALL | wxALIGN_CENTER_VERTICAL, 4)
305    
306            topBox.Add(sizer, 0, wxEXPAND|wxALL, 4)
307            topBox.Add(self.grid, 1, wxEXPAND|wxALL, 0)
308    
309            self.SetAutoLayout(True)
310            self.SetSizer(topBox)
311            topBox.Fit(self)
312            topBox.SetSizeHints(self)
313    
314            self.grid.SetFocus()
315            EVT_BUTTON(self, ID_QUERY, self.OnQuery)
316            EVT_BUTTON(self, ID_EXPORT, self.OnSaveAs)
317            EVT_KEY_DOWN(self.grid, self.OnKeyDown)
318    
319        def OnKeyDown(self, event):
320            """Catch query key from grid"""
321            if event.AltDown() and event.GetKeyCode() == ord(QUERY_KEY):
322                self.combo_fields.SetFocus()
323                self.combo_fields.refocus = True
324            else:
325                event.Skip()
326    
327    
328        def OnQuery(self, event):
329            wxBeginBusyCursor()
330    
331            if self.combo_value.GetSelection() < 1:
332                value = self.combo_value.GetValue()
333            else:
334                value = self.table.Column(self.combo_value.GetValue())
335    
336            ids = self.table.SimpleQuery(
337                    self.table.Column(self.combo_fields.GetStringSelection()),
338                    self.choice_comp.GetStringSelection(),
339                    value)
340    
341            choice = self.choice_action.GetSelection()
342                
343            #
344            # what used to be nice code got became a bit ugly because
345            # each time we select a row a message is sent to the grid
346            # which we are listening for and then we send further
347            # messages.
348            #
349            # now, we disable those listeners select everything but
350            # the first item, reenable the listeners, and select
351            # the first element, which causes everything to be
352            # updated properly.
353            #
354            self.grid.ToggleEventListeners(False)
355    
356            if choice == 0:
357                # Replace Selection
358                self.grid.ClearSelection()
359            elif choice == 1:
360                # Refine Selection
361                sel = self.get_selected()
362                self.grid.ClearSelection()
363                ids = filter(sel.has_key, ids)
364            elif choice == 2:
365                # Add to Selection
366                pass
367    
368            #
369            # select the rows (all but the first)
370            #
371            firsttime = True
372            for id in ids:
373                if firsttime:
374                    firsttime = False
375                else:
376                    self.grid.SelectRow(id, True)
377    
378            self.grid.ToggleEventListeners(True)
379    
380            #
381            # select the first row
382            #
383            if ids:
384                self.grid.SelectRow(ids[0], True)
385    
386            wxEndBusyCursor()
387            
388        def OnSaveAs(self, event):
389            dlg = wxFileDialog(self, _("Export Table To"), ".", "",
390                               _("DBF Files (*.dbf)|*.dbf|") +
391                               _("CSV Files (*.csv)|*.csv|") +
392                               _("All Files (*.*)|*.*"),
393                               wxSAVE|wxOVERWRITE_PROMPT)
394            if dlg.ShowModal() == wxID_OK:
395                pass
396                                                                                    
397            dlg.Destroy()
398    
399        def OnClose(self, event):
400            TableFrame.OnClose(self, event)
401    
402        def get_selected(self):
403            """Return a dictionary of the selected rows.
404            
405            The dictionary has sthe indexes as keys."""
406            return dict([(i, 0) for i in self.grid.GetSelectedRows()])
407    
408    class LayerTableFrame(QueryTableFrame):
409    
410        """Frame that displays a layer table in a grid view
411    
412        A LayerTableFrame is a QueryTableFrame whose selection is connected to the
413        selected object in a map.
414        """
415    
416        def __init__(self, parent, name, title, layer, table):
417            QueryTableFrame.__init__(self, parent, name, title, table)
418          self.layer = layer          self.layer = layer
419          self.grid.Subscribe(ROW_SELECTED, self.row_selected)          self.grid.Subscribe(ROW_SELECTED, self.rows_selected)
420          self.parent.Subscribe(SHAPES_SELECTED, self.select_shape)          self.parent.Subscribe(SHAPES_SELECTED, self.select_shapes)
421    
422      def make_grid(self, table):      def make_grid(self, table):
423          """Override the derived method to return a LayerTableGrid.          """Override the derived method to return a LayerTableGrid.
424          """          """
425          return LayerTableGrid(self, table)          return LayerTableGrid(self, table)
426    
427        def get_selected(self):
428            """Override the derived method to return a dictionary of the selected
429            rows.
430            """
431            return dict([(i, 0) for i in self.parent.SelectedShapes()])
432    
433      def OnClose(self, event):      def OnClose(self, event):
434          self.parent.Unsubscribe(SHAPES_SELECTED, self.select_shape)          """Override the derived method to first unsubscribed."""
435          TableFrame.OnClose(self, event)          self.parent.Unsubscribe(SHAPES_SELECTED, self.select_shapes)
436            QueryTableFrame.OnClose(self, event)
437    
438      def select_shape(self, layer, shapes):      def select_shapes(self, layer, shapes):
439          """Subscribed to the SHAPES_SELECTED message.          """Subscribed to the SHAPES_SELECTED message.
440    
441          If shapes contains exactly one shape id, select that shape in          If shapes contains exactly one shape id, select that shape in
442          the grid. Otherwise deselect all.          the grid. Otherwise deselect all.
443          """          """
444          if len(shapes):          self.grid.select_shapes(layer, shapes)
             shape = shapes[0]  
         else:  
             shape = None  
         self.grid.select_shape(layer, shape)  
445    
446      def row_selected(self, row):      def rows_selected(self, rows):
447            """Return the selected rows of the layer as they are returned
448            by Layer.SelectShapes().
449            """
450          if self.layer is not None:          if self.layer is not None:
451              self.parent.SelectShapes(self.layer, [row])              self.parent.SelectShapes(self.layer, rows)

Legend:
Removed from v.808  
changed lines
  Added in v.1013

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26