/[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 535 by bh, Fri Mar 14 20:42:18 2003 UTC revision 966 by jonathan, Wed May 21 17:24:40 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 38  class DataTable(wxPyGridTableBase): Line 40  class DataTable(wxPyGridTableBase):
40    
41      def SetTable(self, table):      def SetTable(self, table):
42          self.table = table          self.table = table
43          self.num_cols = table.field_count()          self.num_cols = table.NumColumns()
44          self.num_rows = table.record_count()          self.num_rows = table.NumRows()
45    
46          self.columns = []          self.columns = []
47          for i in range(self.num_cols):          for i in range(self.num_cols):
48              type, name, len, decc = table.field_info(i)              col = table.Column(i)
49              self.columns.append((name, wx_value_type_map[type], len, decc))              self.columns.append((col.name, wx_value_type_map[col.type]))
50    
51      #      #
52      # required methods for the wxPyGridTableBase interface      # required methods for the wxPyGridTableBase interface
# Line 64  class DataTable(wxPyGridTableBase): Line 66  class DataTable(wxPyGridTableBase):
66      # Renderer understands the type too,) not just strings as in the      # Renderer understands the type too,) not just strings as in the
67      # C++ version.      # C++ version.
68      def GetValue(self, row, col):      def GetValue(self, row, col):
69          record = self.table.read_record(row)          record = self.table.ReadRowAsDict(row)
70          return record[self.columns[col][0]]          return record[self.columns[col][0]]
71    
72      def SetValue(self, row, col, value):      def SetValue(self, row, col, value):
# Line 97  class DataTable(wxPyGridTableBase): Line 99  class DataTable(wxPyGridTableBase):
99    
100  class TableGrid(wxGrid, Publisher):  class TableGrid(wxGrid, Publisher):
101    
102      """A grid view for a Thuban table"""      """A grid view for a Thuban table
103    
104        When rows are selected by the user the table issues ROW_SELECTED
105        messages. wx sends selection events even when the selection is
106        manipulated by code (instead of by the user) which usually lead to
107        ROW_SELECTED messages being sent in turn. Therefore sending messages
108        can be switched on and off with the allow_messages and
109        disallow_messages methods.
110        """
111    
112      def __init__(self, parent, table = None):      def __init__(self, parent, table = None):
113          wxGrid.__init__(self, parent, -1)          wxGrid.__init__(self, parent, -1)
114    
115            self.allow_messages_count = 0
116    
117          self.table = DataTable(table)          self.table = DataTable(table)
118    
119          # The second parameter means that the grid is to take ownership          # The second parameter means that the grid is to take ownership
# Line 120  class TableGrid(wxGrid, Publisher): Line 132  class TableGrid(wxGrid, Publisher):
132    
133          self.SetSelectionMode(wxGrid.wxGridSelectRows)          self.SetSelectionMode(wxGrid.wxGridSelectRows)
134    
135          EVT_GRID_RANGE_SELECT(self, self.OnRangeSelect)          #EVT_GRID_RANGE_SELECT(self, None)
136          EVT_GRID_SELECT_CELL(self, self.OnSelectCell)          #EVT_GRID_SELECT_CELL(self, None)
137            #EVT_GRID_RANGE_SELECT(self, self.OnRangeSelect)
138            #EVT_GRID_SELECT_CELL(self, self.OnSelectCell)
139    
140            self.ToggleEventListeners(True)
141    
142      def SetTableObject(self, table):      def SetTableObject(self, table):
143          self.table.SetTable(table)          self.table.SetTable(table)
144    
145      def OnRangeSelect(self, event):      def OnRangeSelect(self, event):
146            rows = dict([(i, 0) for i in self.GetSelectedRows()])
147    
148            # if we're selecting we need to include the selected range and
149            # make sure that the current row is also included, which may
150            # not be the case if you just click on a single row!
151          if event.Selecting():          if event.Selecting():
152              self.issue(ROW_SELECTED, event.GetTopLeftCoords().GetRow())              for i in range(event.GetTopRow(), event.GetBottomRow() + 1):
153                    rows[i] = 0
154                rows[event.GetTopLeftCoords().GetRow()] = 0
155    
156            self.issue(ROW_SELECTED, rows.keys())
157            event.Skip()
158    
159      def OnSelectCell(self, event):      def OnSelectCell(self, event):
160          self.issue(ROW_SELECTED, event.GetRow())          self.issue(ROW_SELECTED, self.GetSelectedRows())
161            event.Skip()
162    
163        def ToggleEventListeners(self, on):
164            if on:
165                EVT_GRID_RANGE_SELECT(self, self.OnRangeSelect)
166                EVT_GRID_SELECT_CELL(self, self.OnSelectCell)
167            else:
168                EVT_GRID_RANGE_SELECT(self, None)
169                EVT_GRID_SELECT_CELL(self, None)
170                
171        def disallow_messages(self):
172            """Disallow messages to be send.
173    
174            This method only increases a counter so that calls to
175            disallow_messages and allow_messages can be nested. Only the
176            outermost calls will actually switch message sending on and off.
177            """
178            self.allow_messages_count += 1
179    
180        def allow_messages(self):
181            """Allow messages to be send.
182    
183            This method only decreases a counter so that calls to
184            disallow_messages and allow_messages can be nested. Only the
185            outermost calls will actually switch message sending on and off.
186            """
187            self.allow_messages_count -= 1
188    
189        def issue(self, *args):
190            """Issue a message unless disallowed.
191    
192            See the allow_messages and disallow_messages methods.
193            """
194            if self.allow_messages_count == 0:
195                Publisher.issue(self, *args)
196    
197    
198  class LayerTableGrid(TableGrid):  class LayerTableGrid(TableGrid):
# Line 142  class LayerTableGrid(TableGrid): Line 203  class LayerTableGrid(TableGrid):
203      selection is usually coupled to the selected object in the map.      selection is usually coupled to the selected object in the map.
204      """      """
205    
206      def select_shape(self, layer, shape):      def select_shapes(self, layer, shapes):
207          """Select the row corresponding to the specified shape and layer          """Select the row corresponding to the specified shape and layer
208    
209          If layer is not the layer the table is associated with do          If layer is not the layer the table is associated with do
210          nothing. If shape or layer is None also do nothing.          nothing. If shape or layer is None also do nothing.
211          """          """
212          if layer is not None and layer.table is self.table.table \          if layer is not None \
213             and shape is not None:              and layer.table is self.table.table:
214              self.SelectRow(shape)  
215              self.SetGridCursor(shape, 0)              self.disallow_messages()
216              self.MakeCellVisible(shape, 0)              try:
217                    self.ClearSelection()
218                    if len(shapes) > 0:
219                        #
220                        # keep track of the lowest id so we can make it
221                        # the first visible item
222                        #
223                        first = shapes[0]
224    
225                        for shape in shapes:
226                            self.SelectRow(shape, True)
227                            if shape < first:
228                                first = shape
229    
230                        self.SetGridCursor(first, 0)
231                        self.MakeCellVisible(first, 0)
232                finally:
233                    self.allow_messages()
234    
235    
236  class TableFrame(NonModalDialog):  class TableFrame(NonModalDialog):
# Line 173  class TableFrame(NonModalDialog): Line 251  class TableFrame(NonModalDialog):
251          return TableGrid(self, table)          return TableGrid(self, table)
252    
253    
254    ID_QUERY = 4001
255    ID_SAVEAS = 4002
256    
257  class LayerTableFrame(TableFrame):  class LayerTableFrame(TableFrame):
258    
259      """Frame that displays a layer table in a grid view      """Frame that displays a layer table in a grid view
# Line 184  class LayerTableFrame(TableFrame): Line 265  class LayerTableFrame(TableFrame):
265      def __init__(self, parent, name, title, layer, table):      def __init__(self, parent, name, title, layer, table):
266          TableFrame.__init__(self, parent, name, title, table)          TableFrame.__init__(self, parent, name, title, table)
267          self.layer = layer          self.layer = layer
268          self.grid.Subscribe(ROW_SELECTED, self.row_selected)          self.grid.Subscribe(ROW_SELECTED, self.rows_selected)
269          self.parent.Subscribe(SHAPES_SELECTED, self.select_shape)          self.parent.Subscribe(SHAPES_SELECTED, self.select_shapes)
270    
271            self.combo_fields = wxComboBox(self, -1, style=wxCB_READONLY)
272            self.choice_comp = wxChoice(self, -1,
273                                  choices=["<", "<=", "==", "!=", ">=", ">"])
274            self.combo_value = wxComboBox(self, -1)
275            self.choice_action = wxChoice(self, -1,
276                                    choices=[_("Replace Selection"),
277                                            _("Refine Selection"),
278                                            _("Add to Selection")])
279    
280            button_query = wxButton(self, ID_QUERY, _("Query"))
281            button_saveas = wxButton(self, ID_SAVEAS, _("Save As..."))
282    
283            self.grid.SetSize((400, 200))
284    
285            self.combo_value.Append("")
286            for i in range(table.NumColumns()):
287                name = table.Column(i).name
288                self.combo_fields.Append(name)
289                self.combo_value.Append(name)
290    
291            # assume at least one field?
292            self.combo_fields.SetSelection(0)
293            self.combo_value.SetSelection(0)
294    
295            topBox = wxBoxSizer(wxVERTICAL)
296    
297            sizer = wxStaticBoxSizer(wxStaticBox(self, -1, _("Selections")),
298                                      wxHORIZONTAL)
299            sizer.Add(self.combo_fields, 1, wxEXPAND|wxALL, 4)
300            sizer.Add(self.choice_comp, 0, wxALL, 4)
301            sizer.Add(self.combo_value, 1, wxEXPAND|wxALL, 4)
302            sizer.Add(self.choice_action, 0, wxALL, 4)
303            sizer.Add(button_query, 0, wxALL, 4)
304            sizer.Add(40, 20, 0, wxALL, 4)
305            sizer.Add(button_saveas, 0, wxALL, 4)
306    
307            topBox.Add(sizer, 0, wxEXPAND|wxALL, 4)
308            topBox.Add(self.grid, 1, wxEXPAND|wxALL, 0)
309    
310            self.SetAutoLayout(True)
311            self.SetSizer(topBox)
312            topBox.Fit(self)
313            topBox.SetSizeHints(self)
314    
315            EVT_BUTTON(self, ID_QUERY, self.OnQuery)
316            EVT_BUTTON(self, ID_SAVEAS, self.OnSaveAs)
317    
318        def OnQuery(self, event):
319            wxBeginBusyCursor()
320    
321            if self.combo_value.GetSelection() < 1:
322                value = self.combo_value.GetValue()
323            else:
324                value = self.table.Column(self.combo_value.GetValue())
325    
326            ids = self.table.SimpleQuery(
327                    self.table.Column(self.combo_fields.GetStringSelection()),
328                    self.choice_comp.GetStringSelection(),
329                    value)
330    
331            choice = self.choice_action.GetSelection()
332                
333            #
334            # what used to be nice code got became a bit ugly because
335            # each time we select a row a message is sent to the grid
336            # which we are listening for and then we send further
337            # messages.
338            #
339            # now, we disable those listeners select everything but
340            # the first item, reenable the listeners, and select
341            # the first element, which causes everything to be
342            # updated properly.
343            #
344            self.grid.ToggleEventListeners(False)
345    
346            if choice == 0:
347                # Replace Selection
348                self.grid.ClearSelection()
349            elif choice == 1:
350                # Refine Selection
351                sel = dict([(i, 0) for i in self.parent.SelectedShapes()])
352                self.grid.ClearSelection()
353                ids = filter(sel.has_key, ids)
354            elif choice == 2:
355                # Add to Selection
356                pass
357    
358            #
359            # select the rows (all but the first)
360            #
361            firsttime = True
362            for id in ids:
363                if firsttime:
364                    firsttime = False
365                else:
366                    self.grid.SelectRow(id, True)
367    
368            self.grid.ToggleEventListeners(True)
369    
370            #
371            # select the first row
372            #
373            if ids:
374                self.grid.SelectRow(ids[0], True)
375    
376            wxEndBusyCursor()
377            
378        def OnSaveAs(self, event):
379            dlg = wxFileDialog(self, _("Save Table As"), ".", "",
380                               "DBF Files (*.dbf)|*.dbf|" +
381                               "CSV Files (*.csv)|*.csv|" +
382                               "All Files (*.*)|*.*",
383                               wxSAVE|wxOVERWRITE_PROMPT)
384            if dlg.ShowModal() == wxID_OK:
385                pass
386                                                                                    
387            dlg.Destroy()
388    
389      def make_grid(self, table):      def make_grid(self, table):
390          """Override the derived method to return a LayerTableGrid.          """Override the derived method to return a LayerTableGrid.
# Line 193  class LayerTableFrame(TableFrame): Line 392  class LayerTableFrame(TableFrame):
392          return LayerTableGrid(self, table)          return LayerTableGrid(self, table)
393    
394      def OnClose(self, event):      def OnClose(self, event):
395          self.parent.Unsubscribe(SHAPES_SELECTED, self.select_shape)          self.parent.Unsubscribe(SHAPES_SELECTED, self.select_shapes)
396          TableFrame.OnClose(self, event)          TableFrame.OnClose(self, event)
397    
398      def select_shape(self, layer, shapes):      def select_shapes(self, layer, shapes):
399          """Subscribed to the SHAPES_SELECTED message.          """Subscribed to the SHAPES_SELECTED message.
400    
401          If shapes contains exactly one shape id, select that shape in          If shapes contains exactly one shape id, select that shape in
402          the grid. Otherwise deselect all.          the grid. Otherwise deselect all.
403          """          """
404          if len(shapes):          self.grid.select_shapes(layer, shapes)
             shape = shapes[0]  
         else:  
             shape = None  
         self.grid.select_shape(layer, shape)  
405    
406      def row_selected(self, row):      def rows_selected(self, rows):
407          if self.layer is not None:          if self.layer is not None:
408              self.parent.SelectShapes(self.layer, [row])              self.parent.SelectShapes(self.layer, rows)

Legend:
Removed from v.535  
changed lines
  Added in v.966

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26