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

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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26