/[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 279 by bh, Mon Aug 26 15:06:01 2002 UTC revision 939 by jonathan, Tue May 20 15:25:22 2003 UTC
# Line 1  Line 1 
1  # Copyright (c) 2001, 2002 by Intevation GmbH  # Copyright (c) 2001, 2002, 2003 by Intevation GmbH
2  # Authors:  # Authors:
3  # Bernhard Herzog <[email protected]>  # Bernhard Herzog <[email protected]>
4  #  #
# 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 15  from Thuban.Model.table import FIELDTYPE Line 17  from Thuban.Model.table import FIELDTYPE
17       FIELDTYPE_STRING       FIELDTYPE_STRING
18  import view  import view
19  from dialogs import NonModalDialog  from dialogs import NonModalDialog
20  from messages import SELECTED_SHAPE  from messages import SHAPES_SELECTED
21    
22  wx_value_type_map = {FIELDTYPE_INT: wxGRID_VALUE_NUMBER,  wx_value_type_map = {FIELDTYPE_INT: wxGRID_VALUE_NUMBER,
23                       FIELDTYPE_DOUBLE: wxGRID_VALUE_FLOAT,                       FIELDTYPE_DOUBLE: wxGRID_VALUE_FLOAT,
# 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 127  class TableGrid(wxGrid, Publisher): Line 139  class TableGrid(wxGrid, Publisher):
139          self.table.SetTable(table)          self.table.SetTable(table)
140    
141      def OnRangeSelect(self, event):      def OnRangeSelect(self, event):
142            rows = dict([(i, 0) for i in self.GetSelectedRows()])
143    
144            # if we're selecting we need to include the selected range and
145            # make sure that the current row is also included, which may
146            # not be the case if you just click on a single row!
147          if event.Selecting():          if event.Selecting():
148              self.issue(ROW_SELECTED, event.GetTopLeftCoords().GetRow())              for i in range(event.GetTopRow(), event.GetBottomRow() + 1):
149                    rows[i] = 0
150                rows[event.GetTopLeftCoords().GetRow()] = 0
151    
152            self.issue(ROW_SELECTED, rows.keys())
153            event.Skip()
154    
155      def OnSelectCell(self, event):      def OnSelectCell(self, event):
156          self.issue(ROW_SELECTED, event.GetRow())          self.issue(ROW_SELECTED, self.GetSelectedRows())
157            event.Skip()
158    
159        def disallow_messages(self):
160            """Disallow messages to be send.
161    
162            This method only increases a counter so that calls to
163            disallow_messages and allow_messages can be nested. Only the
164            outermost calls will actually switch message sending on and off.
165            """
166            self.allow_messages_count += 1
167    
168        def allow_messages(self):
169            """Allow messages to be send.
170    
171            This method only decreases a counter so that calls to
172            disallow_messages and allow_messages can be nested. Only the
173            outermost calls will actually switch message sending on and off.
174            """
175            self.allow_messages_count -= 1
176    
177        def issue(self, *args):
178            """Issue a message unless disallowed.
179    
180            See the allow_messages and disallow_messages methods.
181            """
182            if self.allow_messages_count == 0:
183                Publisher.issue(self, *args)
184    
185    
186  class LayerTableGrid(TableGrid):  class LayerTableGrid(TableGrid):
# Line 142  class LayerTableGrid(TableGrid): Line 191  class LayerTableGrid(TableGrid):
191      selection is usually coupled to the selected object in the map.      selection is usually coupled to the selected object in the map.
192      """      """
193    
194      def select_shape(self, layer, shape):      def select_shapes(self, layer, shapes):
195          """Select the row corresponding to the specified shape and layer          """Select the row corresponding to the specified shape and layer
196    
197          If layer is not the layer the table is associated with do          If layer is not the layer the table is associated with do
198          nothing. If shape or layer is None also do nothing.          nothing. If shape or layer is None also do nothing.
199          """          """
200          if layer is not None and layer.table is self.table.table \          if layer is not None \
201             and shape is not None:              and layer.table is self.table.table:
202              self.SelectRow(shape)  
203              self.SetGridCursor(shape, 0)              self.disallow_messages()
204              self.MakeCellVisible(shape, 0)              try:
205                    self.ClearSelection()
206                    if len(shapes) > 0:
207                        #
208                        # keep track of the lowest id so we can make it
209                        # the first visible item
210                        #
211                        first = shapes[0]
212    
213                        for shape in shapes:
214                            self.SelectRow(shape, True)
215                            if shape < first:
216                                first = shape
217    
218                        self.SetGridCursor(first, 0)
219                        self.MakeCellVisible(first, 0)
220                finally:
221                    self.allow_messages()
222    
223    
224  class TableFrame(NonModalDialog):  class TableFrame(NonModalDialog):
225    
226      """Frame that displays a Thuban table in a grid view"""      """Frame that displays a Thuban table in a grid view"""
227    
228      def __init__(self, parent, interactor, name, title, table):      def __init__(self, parent, name, title, table):
229          NonModalDialog.__init__(self, parent, interactor, name, title)          NonModalDialog.__init__(self, parent, name, title)
230          self.table = table          self.table = table
231          self.grid = self.make_grid(self.table)          self.grid = self.make_grid(self.table)
232    
# Line 173  class TableFrame(NonModalDialog): Line 239  class TableFrame(NonModalDialog):
239          return TableGrid(self, table)          return TableGrid(self, table)
240    
241    
242    ID_QUERY = 4001
243    ID_SAVEAS = 4002
244    
245  class LayerTableFrame(TableFrame):  class LayerTableFrame(TableFrame):
246    
247      """Frame that displays a layer table in a grid view      """Frame that displays a layer table in a grid view
# Line 181  class LayerTableFrame(TableFrame): Line 250  class LayerTableFrame(TableFrame):
250      selected object in a map.      selected object in a map.
251      """      """
252    
253      def __init__(self, parent, interactor, name, title, layer, table):      def __init__(self, parent, name, title, layer, table):
254          TableFrame.__init__(self, parent, interactor, name, title, table)          TableFrame.__init__(self, parent, name, title, table)
255          self.layer = layer          self.layer = layer
256          self.grid.Subscribe(ROW_SELECTED, self.row_selected)          self.grid.Subscribe(ROW_SELECTED, self.rows_selected)
257          self.interactor.Subscribe(SELECTED_SHAPE, self.select_shape)          self.parent.Subscribe(SHAPES_SELECTED, self.select_shapes)
258    
259            self.combo_fields = wxComboBox(self, -1, style=wxCB_READONLY)
260            self.choice_comp = wxChoice(self, -1,
261                                  choices=["<", "<=", "==", "!=", ">=", ">"])
262            self.combo_value = wxComboBox(self, -1)
263            self.choice_action = wxChoice(self, -1,
264                                    choices=[_("Replace Selection"),
265                                            _("Refine Selection"),
266                                            _("Add to Selection")])
267    
268            button_query = wxButton(self, ID_QUERY, _("Query"))
269            button_saveas = wxButton(self, ID_SAVEAS, _("Save As..."))
270    
271            self.grid.SetSize((400, 200))
272    
273            self.combo_value.Append("")
274            for i in range(table.NumColumns()):
275                name = table.Column(i).name
276                self.combo_fields.Append(name)
277                self.combo_value.Append(name)
278    
279            # assume at least one field?
280            self.combo_fields.SetSelection(0)
281            self.combo_value.SetSelection(0)
282    
283            topBox = wxBoxSizer(wxVERTICAL)
284    
285            sizer = wxStaticBoxSizer(wxStaticBox(self, -1, _("Selections")),
286                                      wxHORIZONTAL)
287            sizer.Add(self.combo_fields, 1, wxEXPAND|wxALL, 4)
288            sizer.Add(self.choice_comp, 0, wxALL, 4)
289            sizer.Add(self.combo_value, 1, wxEXPAND|wxALL, 4)
290            sizer.Add(self.choice_action, 0, wxALL, 4)
291            sizer.Add(button_query, 0, wxALL, 4)
292            sizer.Add(40, 20, 0, wxALL, 4)
293            sizer.Add(button_saveas, 0, wxALL, 4)
294    
295            topBox.Add(sizer, 0, wxEXPAND|wxALL, 4)
296            topBox.Add(self.grid, 1, wxEXPAND|wxALL, 0)
297    
298            self.SetAutoLayout(True)
299            self.SetSizer(topBox)
300            topBox.Fit(self)
301            topBox.SetSizeHints(self)
302    
303            EVT_BUTTON(self, ID_QUERY, self.OnQuery)
304            EVT_BUTTON(self, ID_SAVEAS, self.OnSaveAs)
305    
306        def OnQuery(self, event):
307            wxBeginBusyCursor()
308    
309            if self.combo_value.GetSelection() < 1:
310                value = self.combo_value.GetValue()
311            else:
312                value = self.table.Column(self.combo_value.GetValue())
313    
314            ids = self.table.SimpleQuery(
315                    self.table.Column(self.combo_fields.GetStringSelection()),
316                    self.choice_comp.GetStringSelection(),
317                    value)
318    
319            choice = self.choice_action.GetSelection()
320                
321            if choice == 0:
322                # Replace Selection
323                self.grid.ClearSelection()
324                for id in ids:
325                    self.grid.SelectRow(id, True)
326            elif choice == 1:
327                # Refine Selection
328                sel = dict([(i, 0) for i in self.parent.SelectedShapes()])
329                self.grid.ClearSelection()
330                for id in filter(sel.has_key, ids):
331                    self.grid.SelectRow(id, True)
332            elif choice == 2:
333                # Add to Selection
334                for id in ids:
335                    self.grid.SelectRow(id, True)
336    
337            wxEndBusyCursor()
338            
339        def OnSaveAs(self, event):
340            dlg = wxFileDialog(self, _("Save Table As"), ".", "",
341                               "DBF Files (*.dbf)|*.dbf|" +
342                               "CSV Files (*.csv)|*.csv|" +
343                               "All Files (*.*)|*.*",
344                               wxSAVE|wxOVERWRITE_PROMPT)
345            if dlg.ShowModal() == wxID_OK:
346                pass
347                                                                                    
348            dlg.Destroy()
349    
350      def make_grid(self, table):      def make_grid(self, table):
351          """Override the derived method to return a LayerTableGrid.          """Override the derived method to return a LayerTableGrid.
# Line 193  class LayerTableFrame(TableFrame): Line 353  class LayerTableFrame(TableFrame):
353          return LayerTableGrid(self, table)          return LayerTableGrid(self, table)
354    
355      def OnClose(self, event):      def OnClose(self, event):
356          self.interactor.Unsubscribe(SELECTED_SHAPE, self.select_shape)          self.parent.Unsubscribe(SHAPES_SELECTED, self.select_shapes)
357          TableFrame.OnClose(self, event)          TableFrame.OnClose(self, event)
358    
359      def select_shape(self, layer, shape):      def select_shapes(self, layer, shapes):
360          self.grid.select_shape(layer, shape)          """Subscribed to the SHAPES_SELECTED message.
361    
362            If shapes contains exactly one shape id, select that shape in
363            the grid. Otherwise deselect all.
364            """
365            self.grid.select_shapes(layer, shapes)
366    
367      def row_selected(self, row):      def rows_selected(self, rows):
368          if self.layer is not None:          if self.layer is not None:
369              self.interactor.SelectLayerAndShape(self.layer, row)              self.parent.SelectShapes(self.layer, rows)

Legend:
Removed from v.279  
changed lines
  Added in v.939

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26