##// END OF EJS Templates
Map the return key to enter() and shift-return to enterattr().
walter.doerwald -
Show More

The requested changes are too big and content was truncated. Show full diff

@@ -1,825 +1,825 b''
1 # -*- coding: iso-8859-1 -*-
1 # -*- coding: iso-8859-1 -*-
2
2
3 import ipipe, os, webbrowser, urllib
3 import ipipe, os, webbrowser, urllib
4 import wx
4 import wx
5 import wx.grid, wx.html
5 import wx.grid, wx.html
6
6
7 try:
7 try:
8 sorted
8 sorted
9 except NameError:
9 except NameError:
10 from ipipe import sorted
10 from ipipe import sorted
11
11
12
12
13 __all__ = ["igrid"]
13 __all__ = ["igrid"]
14
14
15
15
16 class IGridRenderer(wx.grid.PyGridCellRenderer):
16 class IGridRenderer(wx.grid.PyGridCellRenderer):
17 """
17 """
18 This is a custom renderer for our IGridGrid
18 This is a custom renderer for our IGridGrid
19 """
19 """
20 def __init__(self, table):
20 def __init__(self, table):
21 self.maxchars = 200
21 self.maxchars = 200
22 self.table = table
22 self.table = table
23 self.colormap = (
23 self.colormap = (
24 ( 0, 0, 0),
24 ( 0, 0, 0),
25 (174, 0, 0),
25 (174, 0, 0),
26 ( 0, 174, 0),
26 ( 0, 174, 0),
27 (174, 174, 0),
27 (174, 174, 0),
28 ( 0, 0, 174),
28 ( 0, 0, 174),
29 (174, 0, 174),
29 (174, 0, 174),
30 ( 0, 174, 174),
30 ( 0, 174, 174),
31 ( 64, 64, 64)
31 ( 64, 64, 64)
32 )
32 )
33
33
34 wx.grid.PyGridCellRenderer.__init__(self)
34 wx.grid.PyGridCellRenderer.__init__(self)
35
35
36 def _getvalue(self, row, col):
36 def _getvalue(self, row, col):
37 try:
37 try:
38 value = self.table._displayattrs[col].value(self.table.items[row])
38 value = self.table._displayattrs[col].value(self.table.items[row])
39 (align, width, text) = ipipe.xformat(value, "cell", self.maxchars)
39 (align, width, text) = ipipe.xformat(value, "cell", self.maxchars)
40 except Exception, exc:
40 except Exception, exc:
41 (align, width, text) = ipipe.xformat(exc, "cell", self.maxchars)
41 (align, width, text) = ipipe.xformat(exc, "cell", self.maxchars)
42 return (align, text)
42 return (align, text)
43
43
44 def GetBestSize(self, grid, attr, dc, row, col):
44 def GetBestSize(self, grid, attr, dc, row, col):
45 text = grid.GetCellValue(row, col)
45 text = grid.GetCellValue(row, col)
46 (align, text) = self._getvalue(row, col)
46 (align, text) = self._getvalue(row, col)
47 dc.SetFont(attr.GetFont())
47 dc.SetFont(attr.GetFont())
48 (w, h) = dc.GetTextExtent(str(text))
48 (w, h) = dc.GetTextExtent(str(text))
49 return wx.Size(min(w+2, 600), h+2) # add border
49 return wx.Size(min(w+2, 600), h+2) # add border
50
50
51 def Draw(self, grid, attr, dc, rect, row, col, isSelected):
51 def Draw(self, grid, attr, dc, rect, row, col, isSelected):
52 """
52 """
53 Takes care of drawing everything in the cell; aligns the text
53 Takes care of drawing everything in the cell; aligns the text
54 """
54 """
55 text = grid.GetCellValue(row, col)
55 text = grid.GetCellValue(row, col)
56 (align, text) = self._getvalue(row, col)
56 (align, text) = self._getvalue(row, col)
57 if isSelected:
57 if isSelected:
58 bg = grid.GetSelectionBackground()
58 bg = grid.GetSelectionBackground()
59 else:
59 else:
60 bg = ["white", (240, 240, 240)][row%2]
60 bg = ["white", (240, 240, 240)][row%2]
61 dc.SetTextBackground(bg)
61 dc.SetTextBackground(bg)
62 dc.SetBrush(wx.Brush(bg, wx.SOLID))
62 dc.SetBrush(wx.Brush(bg, wx.SOLID))
63 dc.SetPen(wx.TRANSPARENT_PEN)
63 dc.SetPen(wx.TRANSPARENT_PEN)
64 dc.SetFont(attr.GetFont())
64 dc.SetFont(attr.GetFont())
65 dc.DrawRectangleRect(rect)
65 dc.DrawRectangleRect(rect)
66 dc.SetClippingRect(rect)
66 dc.SetClippingRect(rect)
67 # Format the text
67 # Format the text
68 if align == -1: # left alignment
68 if align == -1: # left alignment
69 (width, height) = dc.GetTextExtent(str(text))
69 (width, height) = dc.GetTextExtent(str(text))
70 x = rect[0]+1
70 x = rect[0]+1
71 y = rect[1]+0.5*(rect[3]-height)
71 y = rect[1]+0.5*(rect[3]-height)
72
72
73 for (style, part) in text:
73 for (style, part) in text:
74 if isSelected:
74 if isSelected:
75 fg = grid.GetSelectionForeground()
75 fg = grid.GetSelectionForeground()
76 else:
76 else:
77 fg = self.colormap[style.fg]
77 fg = self.colormap[style.fg]
78 dc.SetTextForeground(fg)
78 dc.SetTextForeground(fg)
79 (w, h) = dc.GetTextExtent(part)
79 (w, h) = dc.GetTextExtent(part)
80 dc.DrawText(part, x, y)
80 dc.DrawText(part, x, y)
81 x += w
81 x += w
82 elif align == 0: # center alignment
82 elif align == 0: # center alignment
83 (width, height) = dc.GetTextExtent(str(text))
83 (width, height) = dc.GetTextExtent(str(text))
84 x = rect[0]+0.5*(rect[2]-width)
84 x = rect[0]+0.5*(rect[2]-width)
85 y = rect[1]+0.5*(rect[3]-height)
85 y = rect[1]+0.5*(rect[3]-height)
86 for (style, part) in text:
86 for (style, part) in text:
87 if isSelected:
87 if isSelected:
88 fg = grid.GetSelectionForeground()
88 fg = grid.GetSelectionForeground()
89 else:
89 else:
90 fg = self.colormap[style.fg]
90 fg = self.colormap[style.fg]
91 dc.SetTextForeground(fg)
91 dc.SetTextForeground(fg)
92 (w, h) = dc.GetTextExtent(part)
92 (w, h) = dc.GetTextExtent(part)
93 dc.DrawText(part, x, y)
93 dc.DrawText(part, x, y)
94 x += w
94 x += w
95 else: # right alignment
95 else: # right alignment
96 (width, height) = dc.GetTextExtent(str(text))
96 (width, height) = dc.GetTextExtent(str(text))
97 x = rect[0]+rect[2]-1
97 x = rect[0]+rect[2]-1
98 y = rect[1]+0.5*(rect[3]-height)
98 y = rect[1]+0.5*(rect[3]-height)
99 for (style, part) in reversed(text):
99 for (style, part) in reversed(text):
100 (w, h) = dc.GetTextExtent(part)
100 (w, h) = dc.GetTextExtent(part)
101 x -= w
101 x -= w
102 if isSelected:
102 if isSelected:
103 fg = grid.GetSelectionForeground()
103 fg = grid.GetSelectionForeground()
104 else:
104 else:
105 fg = self.colormap[style.fg]
105 fg = self.colormap[style.fg]
106 dc.SetTextForeground(fg)
106 dc.SetTextForeground(fg)
107 dc.DrawText(part, x, y)
107 dc.DrawText(part, x, y)
108 dc.DestroyClippingRegion()
108 dc.DestroyClippingRegion()
109
109
110 def Clone(self):
110 def Clone(self):
111 return IGridRenderer(self.table)
111 return IGridRenderer(self.table)
112
112
113
113
114 class IGridTable(wx.grid.PyGridTableBase):
114 class IGridTable(wx.grid.PyGridTableBase):
115 # The data table for the ``IGridGrid``. Some dirty tricks were used here:
115 # The data table for the ``IGridGrid``. Some dirty tricks were used here:
116 # ``GetValue()`` does not get any values (or at least it does not return
116 # ``GetValue()`` does not get any values (or at least it does not return
117 # anything, accessing the values is done by the renderer)
117 # anything, accessing the values is done by the renderer)
118 # but rather tries to fetch the objects which were requested into the table.
118 # but rather tries to fetch the objects which were requested into the table.
119 # General behaviour is: Fetch the first X objects. If the user scrolls down
119 # General behaviour is: Fetch the first X objects. If the user scrolls down
120 # to the last object another bunch of X objects is fetched (if possible)
120 # to the last object another bunch of X objects is fetched (if possible)
121 def __init__(self, input, fontsize, *attrs):
121 def __init__(self, input, fontsize, *attrs):
122 wx.grid.PyGridTableBase.__init__(self)
122 wx.grid.PyGridTableBase.__init__(self)
123 self.input = input
123 self.input = input
124 self.iterator = ipipe.xiter(input)
124 self.iterator = ipipe.xiter(input)
125 self.items = []
125 self.items = []
126 self.attrs = [ipipe.upgradexattr(attr) for attr in attrs]
126 self.attrs = [ipipe.upgradexattr(attr) for attr in attrs]
127 self._displayattrs = self.attrs[:]
127 self._displayattrs = self.attrs[:]
128 self._displayattrset = set(self.attrs)
128 self._displayattrset = set(self.attrs)
129 self._sizing = False
129 self._sizing = False
130 self.fontsize = fontsize
130 self.fontsize = fontsize
131 self._fetch(1)
131 self._fetch(1)
132
132
133 def GetAttr(self, *args):
133 def GetAttr(self, *args):
134 attr = wx.grid.GridCellAttr()
134 attr = wx.grid.GridCellAttr()
135 attr.SetFont(wx.Font(self.fontsize, wx.TELETYPE, wx.NORMAL, wx.NORMAL))
135 attr.SetFont(wx.Font(self.fontsize, wx.TELETYPE, wx.NORMAL, wx.NORMAL))
136 return attr
136 return attr
137
137
138 def GetNumberRows(self):
138 def GetNumberRows(self):
139 return len(self.items)
139 return len(self.items)
140
140
141 def GetNumberCols(self):
141 def GetNumberCols(self):
142 return len(self._displayattrs)
142 return len(self._displayattrs)
143
143
144 def GetColLabelValue(self, col):
144 def GetColLabelValue(self, col):
145 if col < len(self._displayattrs):
145 if col < len(self._displayattrs):
146 return self._displayattrs[col].name()
146 return self._displayattrs[col].name()
147 else:
147 else:
148 return ""
148 return ""
149
149
150 def GetRowLabelValue(self, row):
150 def GetRowLabelValue(self, row):
151 return str(row)
151 return str(row)
152
152
153 def IsEmptyCell(self, row, col):
153 def IsEmptyCell(self, row, col):
154 return False
154 return False
155
155
156 def _append(self, item):
156 def _append(self, item):
157 self.items.append(item)
157 self.items.append(item)
158 # Nothing to do if the set of attributes has been fixed by the user
158 # Nothing to do if the set of attributes has been fixed by the user
159 if not self.attrs:
159 if not self.attrs:
160 for attr in ipipe.xattrs(item):
160 for attr in ipipe.xattrs(item):
161 attr = ipipe.upgradexattr(attr)
161 attr = ipipe.upgradexattr(attr)
162 if attr not in self._displayattrset:
162 if attr not in self._displayattrset:
163 self._displayattrs.append(attr)
163 self._displayattrs.append(attr)
164 self._displayattrset.add(attr)
164 self._displayattrset.add(attr)
165
165
166 def _fetch(self, count):
166 def _fetch(self, count):
167 # Try to fill ``self.items`` with at least ``count`` objects.
167 # Try to fill ``self.items`` with at least ``count`` objects.
168 have = len(self.items)
168 have = len(self.items)
169 while self.iterator is not None and have < count:
169 while self.iterator is not None and have < count:
170 try:
170 try:
171 item = self.iterator.next()
171 item = self.iterator.next()
172 except StopIteration:
172 except StopIteration:
173 self.iterator = None
173 self.iterator = None
174 break
174 break
175 except (KeyboardInterrupt, SystemExit):
175 except (KeyboardInterrupt, SystemExit):
176 raise
176 raise
177 except Exception, exc:
177 except Exception, exc:
178 have += 1
178 have += 1
179 self._append(item)
179 self._append(item)
180 self.iterator = None
180 self.iterator = None
181 break
181 break
182 else:
182 else:
183 have += 1
183 have += 1
184 self._append(item)
184 self._append(item)
185
185
186 def GetValue(self, row, col):
186 def GetValue(self, row, col):
187 # some kind of dummy-function: does not return anything but "";
187 # some kind of dummy-function: does not return anything but "";
188 # (The value isn't use anyway)
188 # (The value isn't use anyway)
189 # its main task is to trigger the fetch of new objects
189 # its main task is to trigger the fetch of new objects
190 had_cols = self._displayattrs[:]
190 had_cols = self._displayattrs[:]
191 had_rows = len(self.items)
191 had_rows = len(self.items)
192 if row == had_rows - 1 and self.iterator is not None and not self._sizing:
192 if row == had_rows - 1 and self.iterator is not None and not self._sizing:
193 self._fetch(row + 20)
193 self._fetch(row + 20)
194 have_rows = len(self.items)
194 have_rows = len(self.items)
195 have_cols = len(self._displayattrs)
195 have_cols = len(self._displayattrs)
196 if have_rows > had_rows:
196 if have_rows > had_rows:
197 msg = wx.grid.GridTableMessage(self, wx.grid.GRIDTABLE_NOTIFY_ROWS_APPENDED, have_rows - had_rows)
197 msg = wx.grid.GridTableMessage(self, wx.grid.GRIDTABLE_NOTIFY_ROWS_APPENDED, have_rows - had_rows)
198 self.GetView().ProcessTableMessage(msg)
198 self.GetView().ProcessTableMessage(msg)
199 self._sizing = True
199 self._sizing = True
200 self.GetView().AutoSizeColumns(False)
200 self.GetView().AutoSizeColumns(False)
201 self._sizing = False
201 self._sizing = False
202 if row >= have_rows:
202 if row >= have_rows:
203 return ""
203 return ""
204 if self._displayattrs != had_cols:
204 if self._displayattrs != had_cols:
205 msg = wx.grid.GridTableMessage(self, wx.grid.GRIDTABLE_NOTIFY_COLS_APPENDED, have_cols - len(had_cols))
205 msg = wx.grid.GridTableMessage(self, wx.grid.GRIDTABLE_NOTIFY_COLS_APPENDED, have_cols - len(had_cols))
206 self.GetView().ProcessTableMessage(msg)
206 self.GetView().ProcessTableMessage(msg)
207 return ""
207 return ""
208
208
209 def SetValue(self, row, col, value):
209 def SetValue(self, row, col, value):
210 pass
210 pass
211
211
212
212
213 class IGridGrid(wx.grid.Grid):
213 class IGridGrid(wx.grid.Grid):
214 # The actual grid
214 # The actual grid
215 # all methods for selecting/sorting/picking/... data are implemented here
215 # all methods for selecting/sorting/picking/... data are implemented here
216 def __init__(self, panel, input, *attrs):
216 def __init__(self, panel, input, *attrs):
217 wx.grid.Grid.__init__(self, panel)
217 wx.grid.Grid.__init__(self, panel)
218 fontsize = 9
218 fontsize = 9
219 self.input = input
219 self.input = input
220 self.table = IGridTable(self.input, fontsize, *attrs)
220 self.table = IGridTable(self.input, fontsize, *attrs)
221 self.SetTable(self.table, True)
221 self.SetTable(self.table, True)
222 self.SetSelectionMode(wx.grid.Grid.wxGridSelectRows)
222 self.SetSelectionMode(wx.grid.Grid.wxGridSelectRows)
223 self.SetDefaultRenderer(IGridRenderer(self.table))
223 self.SetDefaultRenderer(IGridRenderer(self.table))
224 self.EnableEditing(False)
224 self.EnableEditing(False)
225 self.Bind(wx.EVT_KEY_DOWN, self.key_pressed)
225 self.Bind(wx.EVT_KEY_DOWN, self.key_pressed)
226 self.Bind(wx.grid.EVT_GRID_CELL_LEFT_DCLICK, self.cell_doubleclicked)
226 self.Bind(wx.grid.EVT_GRID_CELL_LEFT_DCLICK, self.cell_doubleclicked)
227 self.Bind(wx.grid.EVT_GRID_CELL_LEFT_CLICK, self.cell_leftclicked)
227 self.Bind(wx.grid.EVT_GRID_CELL_LEFT_CLICK, self.cell_leftclicked)
228 self.Bind(wx.grid.EVT_GRID_LABEL_LEFT_DCLICK, self.label_doubleclicked)
228 self.Bind(wx.grid.EVT_GRID_LABEL_LEFT_DCLICK, self.label_doubleclicked)
229 self.Bind(wx.grid.EVT_GRID_LABEL_LEFT_CLICK, self.on_label_leftclick)
229 self.Bind(wx.grid.EVT_GRID_LABEL_LEFT_CLICK, self.on_label_leftclick)
230 self.Bind(wx.grid.EVT_GRID_RANGE_SELECT, self._on_selected_range)
230 self.Bind(wx.grid.EVT_GRID_RANGE_SELECT, self._on_selected_range)
231 self.Bind(wx.grid.EVT_GRID_SELECT_CELL, self._on_selected_cell)
231 self.Bind(wx.grid.EVT_GRID_SELECT_CELL, self._on_selected_cell)
232 self.current_selection = set()
232 self.current_selection = set()
233 self.maxchars = 200
233 self.maxchars = 200
234
234
235 def on_label_leftclick(self, event):
235 def on_label_leftclick(self, event):
236 event.Skip()
236 event.Skip()
237
237
238 def error_output(self, text):
238 def error_output(self, text):
239 wx.Bell()
239 wx.Bell()
240 frame = self.GetParent().GetParent().GetParent()
240 frame = self.GetParent().GetParent().GetParent()
241 frame.SetStatusText(text)
241 frame.SetStatusText(text)
242
242
243 def _on_selected_range(self, event):
243 def _on_selected_range(self, event):
244 # Internal update to the selection tracking lists
244 # Internal update to the selection tracking lists
245 if event.Selecting():
245 if event.Selecting():
246 # adding to the list...
246 # adding to the list...
247 self.current_selection.update(xrange(event.GetTopRow(), event.GetBottomRow()+1))
247 self.current_selection.update(xrange(event.GetTopRow(), event.GetBottomRow()+1))
248 else:
248 else:
249 # removal from list
249 # removal from list
250 for index in xrange( event.GetTopRow(), event.GetBottomRow()+1):
250 for index in xrange( event.GetTopRow(), event.GetBottomRow()+1):
251 self.current_selection.discard(index)
251 self.current_selection.discard(index)
252 event.Skip()
252 event.Skip()
253
253
254 def _on_selected_cell(self, event):
254 def _on_selected_cell(self, event):
255 # Internal update to the selection tracking list
255 # Internal update to the selection tracking list
256 self.current_selection = set([event.GetRow()])
256 self.current_selection = set([event.GetRow()])
257 event.Skip()
257 event.Skip()
258
258
259 def sort(self, key, reverse=False):
259 def sort(self, key, reverse=False):
260 """
260 """
261 Sort the current list of items using the key function ``key``. If
261 Sort the current list of items using the key function ``key``. If
262 ``reverse`` is true the sort order is reversed.
262 ``reverse`` is true the sort order is reversed.
263 """
263 """
264 row = self.GetGridCursorRow()
264 row = self.GetGridCursorRow()
265 col = self.GetGridCursorCol()
265 col = self.GetGridCursorCol()
266 curitem = self.table.items[row] # Remember where the cursor is now
266 curitem = self.table.items[row] # Remember where the cursor is now
267 # Sort items
267 # Sort items
268 def realkey(item):
268 def realkey(item):
269 try:
269 try:
270 return key(item)
270 return key(item)
271 except (KeyboardInterrupt, SystemExit):
271 except (KeyboardInterrupt, SystemExit):
272 raise
272 raise
273 except Exception:
273 except Exception:
274 return None
274 return None
275 try:
275 try:
276 self.table.items = ipipe.deque(sorted(self.table.items, key=realkey, reverse=reverse))
276 self.table.items = ipipe.deque(sorted(self.table.items, key=realkey, reverse=reverse))
277 except TypeError, exc:
277 except TypeError, exc:
278 self.error_output("Exception encountered: %s" % exc)
278 self.error_output("Exception encountered: %s" % exc)
279 return
279 return
280 # Find out where the object under the cursor went
280 # Find out where the object under the cursor went
281 for (i, item) in enumerate(self.table.items):
281 for (i, item) in enumerate(self.table.items):
282 if item is curitem:
282 if item is curitem:
283 self.SetGridCursor(i,col)
283 self.SetGridCursor(i,col)
284 self.MakeCellVisible(i,col)
284 self.MakeCellVisible(i,col)
285 self.Refresh()
285 self.Refresh()
286
286
287 def sortattrasc(self):
287 def sortattrasc(self):
288 """
288 """
289 Sort in ascending order; sorting criteria is the current attribute
289 Sort in ascending order; sorting criteria is the current attribute
290 """
290 """
291 col = self.GetGridCursorCol()
291 col = self.GetGridCursorCol()
292 attr = self.table._displayattrs[col]
292 attr = self.table._displayattrs[col]
293 frame = self.GetParent().GetParent().GetParent()
293 frame = self.GetParent().GetParent().GetParent()
294 if attr is ipipe.noitem:
294 if attr is ipipe.noitem:
295 self.error_output("no column under cursor")
295 self.error_output("no column under cursor")
296 return
296 return
297 frame.SetStatusText("sort by %s (ascending)" % attr.name())
297 frame.SetStatusText("sort by %s (ascending)" % attr.name())
298 def key(item):
298 def key(item):
299 try:
299 try:
300 return attr.value(item)
300 return attr.value(item)
301 except (KeyboardInterrupt, SystemExit):
301 except (KeyboardInterrupt, SystemExit):
302 raise
302 raise
303 except Exception:
303 except Exception:
304 return None
304 return None
305 self.sort(key)
305 self.sort(key)
306
306
307 def sortattrdesc(self):
307 def sortattrdesc(self):
308 """
308 """
309 Sort in descending order; sorting criteria is the current attribute
309 Sort in descending order; sorting criteria is the current attribute
310 """
310 """
311 col = self.GetGridCursorCol()
311 col = self.GetGridCursorCol()
312 attr = self.table._displayattrs[col]
312 attr = self.table._displayattrs[col]
313 frame = self.GetParent().GetParent().GetParent()
313 frame = self.GetParent().GetParent().GetParent()
314 if attr is ipipe.noitem:
314 if attr is ipipe.noitem:
315 self.error_output("no column under cursor")
315 self.error_output("no column under cursor")
316 return
316 return
317 frame.SetStatusText("sort by %s (descending)" % attr.name())
317 frame.SetStatusText("sort by %s (descending)" % attr.name())
318 def key(item):
318 def key(item):
319 try:
319 try:
320 return attr.value(item)
320 return attr.value(item)
321 except (KeyboardInterrupt, SystemExit):
321 except (KeyboardInterrupt, SystemExit):
322 raise
322 raise
323 except Exception:
323 except Exception:
324 return None
324 return None
325 self.sort(key, reverse=True)
325 self.sort(key, reverse=True)
326
326
327 def label_doubleclicked(self, event):
327 def label_doubleclicked(self, event):
328 row = event.GetRow()
328 row = event.GetRow()
329 col = event.GetCol()
329 col = event.GetCol()
330 if col == -1:
330 if col == -1:
331 self.enter(row)
331 self.enter(row)
332
332
333 def _getvalue(self, row, col):
333 def _getvalue(self, row, col):
334 """
334 """
335 Gets the text which is displayed at ``(row, col)``
335 Gets the text which is displayed at ``(row, col)``
336 """
336 """
337 try:
337 try:
338 value = self.table._displayattrs[col].value(self.table.items[row])
338 value = self.table._displayattrs[col].value(self.table.items[row])
339 (align, width, text) = ipipe.xformat(value, "cell", self.maxchars)
339 (align, width, text) = ipipe.xformat(value, "cell", self.maxchars)
340 except IndexError:
340 except IndexError:
341 raise IndexError
341 raise IndexError
342 except Exception, exc:
342 except Exception, exc:
343 (align, width, text) = ipipe.xformat(exc, "cell", self.maxchars)
343 (align, width, text) = ipipe.xformat(exc, "cell", self.maxchars)
344 return text
344 return text
345
345
346 def search(self, searchtext, startrow=0, startcol=0, search_forward=True):
346 def search(self, searchtext, startrow=0, startcol=0, search_forward=True):
347 """
347 """
348 search for ``searchtext``, starting in ``(startrow, startcol)``;
348 search for ``searchtext``, starting in ``(startrow, startcol)``;
349 if ``search_forward`` is true the direction is "forward"
349 if ``search_forward`` is true the direction is "forward"
350 """
350 """
351 row = startrow
351 row = startrow
352 searchtext = searchtext.lower()
352 searchtext = searchtext.lower()
353 if search_forward:
353 if search_forward:
354 while True:
354 while True:
355 for col in xrange(startcol, self.table.GetNumberCols()):
355 for col in xrange(startcol, self.table.GetNumberCols()):
356 try:
356 try:
357 foo = self.table.GetValue(row, col)
357 foo = self.table.GetValue(row, col)
358 text = self._getvalue(row, col)
358 text = self._getvalue(row, col)
359 if searchtext in text.string().lower():
359 if searchtext in text.string().lower():
360 self.SetGridCursor(row, col)
360 self.SetGridCursor(row, col)
361 self.MakeCellVisible(row, col)
361 self.MakeCellVisible(row, col)
362 return
362 return
363 except IndexError:
363 except IndexError:
364 return
364 return
365 startcol = 0
365 startcol = 0
366 row += 1
366 row += 1
367 else:
367 else:
368 while True:
368 while True:
369 for col in xrange(startcol, -1, -1):
369 for col in xrange(startcol, -1, -1):
370 try:
370 try:
371 foo = self.table.GetValue(row, col)
371 foo = self.table.GetValue(row, col)
372 text = self._getvalue(row, col)
372 text = self._getvalue(row, col)
373 if searchtext in text.string().lower():
373 if searchtext in text.string().lower():
374 self.SetGridCursor(row, col)
374 self.SetGridCursor(row, col)
375 self.MakeCellVisible(row, col)
375 self.MakeCellVisible(row, col)
376 return
376 return
377 except IndexError:
377 except IndexError:
378 return
378 return
379 startcol = self.table.GetNumberCols()-1
379 startcol = self.table.GetNumberCols()-1
380 row -= 1
380 row -= 1
381
381
382 def key_pressed(self, event):
382 def key_pressed(self, event):
383 """
383 """
384 Maps pressed keys to functions
384 Maps pressed keys to functions
385 """
385 """
386 frame = self.GetParent().GetParent().GetParent()
386 frame = self.GetParent().GetParent().GetParent()
387 frame.SetStatusText("")
387 frame.SetStatusText("")
388 sh = event.ShiftDown()
388 sh = event.ShiftDown()
389 ctrl = event.ControlDown()
389 ctrl = event.ControlDown()
390
390
391 keycode = event.GetKeyCode()
391 keycode = event.GetKeyCode()
392 if keycode == ord("P"):
392 if keycode == ord("P"):
393 row = self.GetGridCursorRow()
393 row = self.GetGridCursorRow()
394 if event.ShiftDown():
394 if sh:
395 col = self.GetGridCursorCol()
395 col = self.GetGridCursorCol()
396 self.pickattr(row, col)
396 self.pickattr(row, col)
397 else:
397 else:
398 self.pick(row)
398 self.pick(row)
399 elif keycode == ord("M"):
399 elif keycode == ord("M"):
400 if ctrl:
400 if ctrl:
401 col = self.GetGridCursorCol()
401 col = self.GetGridCursorCol()
402 self.pickrowsattr(sorted(self.current_selection), col)
402 self.pickrowsattr(sorted(self.current_selection), col)
403 else:
403 else:
404 self.pickrows(sorted(self.current_selection))
404 self.pickrows(sorted(self.current_selection))
405 elif keycode in (wx.WXK_BACK, wx.WXK_DELETE, ord("X")) and not (ctrl or sh):
405 elif keycode in (wx.WXK_BACK, wx.WXK_DELETE, ord("X")) and not (ctrl or sh):
406 self.delete_current_notebook()
406 self.delete_current_notebook()
407 elif keycode == ord("E") and not (ctrl or sh):
407 elif keycode in (ord("E"), ord("\r")):
408 row = self.GetGridCursorRow()
409 self.enter(row)
410 elif keycode == ord("E") and sh and not ctrl:
411 row = self.GetGridCursorRow()
408 row = self.GetGridCursorRow()
412 col = self.GetGridCursorCol()
409 if sh:
413 self.enterattr(row, col)
410 col = self.GetGridCursorCol()
411 self.enterattr(row, col)
412 else:
413 self.enter(row)
414 elif keycode == ord("E") and ctrl:
414 elif keycode == ord("E") and ctrl:
415 row = self.GetGridCursorRow()
415 row = self.GetGridCursorRow()
416 self.SetGridCursor(row, self.GetNumberCols()-1)
416 self.SetGridCursor(row, self.GetNumberCols()-1)
417 elif keycode == wx.WXK_HOME or (keycode == ord("A") and ctrl):
417 elif keycode == wx.WXK_HOME or (keycode == ord("A") and ctrl):
418 row = self.GetGridCursorRow()
418 row = self.GetGridCursorRow()
419 self.SetGridCursor(row, 0)
419 self.SetGridCursor(row, 0)
420 elif keycode == ord("C") and sh:
420 elif keycode == ord("C") and sh:
421 col = self.GetGridCursorCol()
421 col = self.GetGridCursorCol()
422 attr = self.table._displayattrs[col]
422 attr = self.table._displayattrs[col]
423 result = []
423 result = []
424 for i in xrange(self.GetNumberRows()):
424 for i in xrange(self.GetNumberRows()):
425 result.append(self.table._displayattrs[col].value(self.table.items[i]))
425 result.append(self.table._displayattrs[col].value(self.table.items[i]))
426 self.quit(result)
426 self.quit(result)
427 elif keycode in (wx.WXK_ESCAPE, ord("Q")) and not (ctrl or sh):
427 elif keycode in (wx.WXK_ESCAPE, ord("Q")) and not (ctrl or sh):
428 self.quit()
428 self.quit()
429 elif keycode == ord("<"):
429 elif keycode == ord("<"):
430 row = self.GetGridCursorRow()
430 row = self.GetGridCursorRow()
431 col = self.GetGridCursorCol()
431 col = self.GetGridCursorCol()
432 if not event.ShiftDown():
432 if not event.ShiftDown():
433 newcol = col - 1
433 newcol = col - 1
434 if newcol >= 0:
434 if newcol >= 0:
435 self.SetGridCursor(row, col - 1)
435 self.SetGridCursor(row, col - 1)
436 else:
436 else:
437 newcol = col + 1
437 newcol = col + 1
438 if newcol < self.GetNumberCols():
438 if newcol < self.GetNumberCols():
439 self.SetGridCursor(row, col + 1)
439 self.SetGridCursor(row, col + 1)
440 elif keycode == ord("D"):
440 elif keycode == ord("D"):
441 col = self.GetGridCursorCol()
441 col = self.GetGridCursorCol()
442 row = self.GetGridCursorRow()
442 row = self.GetGridCursorRow()
443 if not sh:
443 if not sh:
444 self.detail(row, col)
444 self.detail(row, col)
445 else:
445 else:
446 self.detail_attr(row, col)
446 self.detail_attr(row, col)
447 elif keycode == ord("F") and ctrl:
447 elif keycode == ord("F") and ctrl:
448 frame.enter_searchtext(event)
448 frame.enter_searchtext(event)
449 elif keycode == wx.WXK_F3:
449 elif keycode == wx.WXK_F3:
450 if sh:
450 if sh:
451 frame.find_previous(event)
451 frame.find_previous(event)
452 else:
452 else:
453 frame.find_next(event)
453 frame.find_next(event)
454 elif keycode == ord("V"):
454 elif keycode == ord("V"):
455 if sh:
455 if sh:
456 self.sortattrdesc()
456 self.sortattrdesc()
457 else:
457 else:
458 self.sortattrasc()
458 self.sortattrasc()
459 elif keycode == wx.WXK_DOWN:
459 elif keycode == wx.WXK_DOWN:
460 row = self.GetGridCursorRow()
460 row = self.GetGridCursorRow()
461 try:
461 try:
462 item = self.table.items[row+1]
462 item = self.table.items[row+1]
463 except IndexError:
463 except IndexError:
464 item = self.table.items[row]
464 item = self.table.items[row]
465 self.set_footer(item)
465 self.set_footer(item)
466 event.Skip()
466 event.Skip()
467 elif keycode == wx.WXK_UP:
467 elif keycode == wx.WXK_UP:
468 row = self.GetGridCursorRow()
468 row = self.GetGridCursorRow()
469 if row >= 1:
469 if row >= 1:
470 item = self.table.items[row-1]
470 item = self.table.items[row-1]
471 else:
471 else:
472 item = self.table.items[row]
472 item = self.table.items[row]
473 self.set_footer(item)
473 self.set_footer(item)
474 event.Skip()
474 event.Skip()
475 elif keycode == wx.WXK_RIGHT:
475 elif keycode == wx.WXK_RIGHT:
476 row = self.GetGridCursorRow()
476 row = self.GetGridCursorRow()
477 item = self.table.items[row]
477 item = self.table.items[row]
478 self.set_footer(item)
478 self.set_footer(item)
479 event.Skip()
479 event.Skip()
480 elif keycode == wx.WXK_LEFT:
480 elif keycode == wx.WXK_LEFT:
481 row = self.GetGridCursorRow()
481 row = self.GetGridCursorRow()
482 item = self.table.items[row]
482 item = self.table.items[row]
483 self.set_footer(item)
483 self.set_footer(item)
484 event.Skip()
484 event.Skip()
485 else:
485 else:
486 event.Skip()
486 event.Skip()
487
487
488 def delete_current_notebook(self):
488 def delete_current_notebook(self):
489 """
489 """
490 deletes the current notebook tab
490 deletes the current notebook tab
491 """
491 """
492 panel = self.GetParent()
492 panel = self.GetParent()
493 nb = panel.GetParent()
493 nb = panel.GetParent()
494 current = nb.GetSelection()
494 current = nb.GetSelection()
495 count = nb.GetPageCount()
495 count = nb.GetPageCount()
496 if count > 1:
496 if count > 1:
497 for i in xrange(count-1, current-1, -1):
497 for i in xrange(count-1, current-1, -1):
498 nb.DeletePage(i)
498 nb.DeletePage(i)
499 nb.GetCurrentPage().grid.SetFocus()
499 nb.GetCurrentPage().grid.SetFocus()
500 else:
500 else:
501 frame = nb.GetParent()
501 frame = nb.GetParent()
502 frame.SetStatusText("This is the last level!")
502 frame.SetStatusText("This is the last level!")
503
503
504 def _doenter(self, value, *attrs):
504 def _doenter(self, value, *attrs):
505 """
505 """
506 "enter" a special item resulting in a new notebook tab
506 "enter" a special item resulting in a new notebook tab
507 """
507 """
508 panel = self.GetParent()
508 panel = self.GetParent()
509 nb = panel.GetParent()
509 nb = panel.GetParent()
510 frame = nb.GetParent()
510 frame = nb.GetParent()
511 current = nb.GetSelection()
511 current = nb.GetSelection()
512 count = nb.GetPageCount()
512 count = nb.GetPageCount()
513 try: # if we want to enter something non-iterable, e.g. a function
513 try: # if we want to enter something non-iterable, e.g. a function
514 if current + 1 == count and value is not self.input: # we have an event in the last tab
514 if current + 1 == count and value is not self.input: # we have an event in the last tab
515 frame._add_notebook(value, *attrs)
515 frame._add_notebook(value, *attrs)
516 elif value != self.input: # we have to delete all tabs newer than [panel] first
516 elif value != self.input: # we have to delete all tabs newer than [panel] first
517 for i in xrange(count-1, current, -1): # some tabs don't close if we don't close in *reverse* order
517 for i in xrange(count-1, current, -1): # some tabs don't close if we don't close in *reverse* order
518 nb.DeletePage(i)
518 nb.DeletePage(i)
519 frame._add_notebook(value)
519 frame._add_notebook(value)
520 except TypeError, exc:
520 except TypeError, exc:
521 if exc.__class__.__module__ == "exceptions":
521 if exc.__class__.__module__ == "exceptions":
522 msg = "%s: %s" % (exc.__class__.__name__, exc)
522 msg = "%s: %s" % (exc.__class__.__name__, exc)
523 else:
523 else:
524 msg = "%s.%s: %s" % (exc.__class__.__module__, exc.__class__.__name__, exc)
524 msg = "%s.%s: %s" % (exc.__class__.__module__, exc.__class__.__name__, exc)
525 frame.SetStatusText(msg)
525 frame.SetStatusText(msg)
526
526
527 def enterattr(self, row, col):
527 def enterattr(self, row, col):
528 try:
528 try:
529 attr = self.table._displayattrs[col]
529 attr = self.table._displayattrs[col]
530 value = attr.value(self.table.items[row])
530 value = attr.value(self.table.items[row])
531 except Exception, exc:
531 except Exception, exc:
532 self.error_output(str(exc))
532 self.error_output(str(exc))
533 else:
533 else:
534 self._doenter(value)
534 self._doenter(value)
535
535
536 def set_footer(self, item):
536 def set_footer(self, item):
537 frame = self.GetParent().GetParent().GetParent()
537 frame = self.GetParent().GetParent().GetParent()
538 frame.SetStatusText(" ".join([str(text) for (style, text) in ipipe.xformat(item, "footer", 20)[2]]))
538 frame.SetStatusText(" ".join([str(text) for (style, text) in ipipe.xformat(item, "footer", 20)[2]]))
539
539
540 def enter(self, row):
540 def enter(self, row):
541 try:
541 try:
542 value = self.table.items[row]
542 value = self.table.items[row]
543 except Exception, exc:
543 except Exception, exc:
544 self.error_output(str(exc))
544 self.error_output(str(exc))
545 else:
545 else:
546 self._doenter(value)
546 self._doenter(value)
547
547
548 def detail(self, row, col):
548 def detail(self, row, col):
549 """
549 """
550 shows a detail-view of the current cell
550 shows a detail-view of the current cell
551 """
551 """
552 try:
552 try:
553 attr = self.table._displayattrs[col]
553 attr = self.table._displayattrs[col]
554 item = self.table.items[row]
554 item = self.table.items[row]
555 except Exception, exc:
555 except Exception, exc:
556 self.error_output(str(exc))
556 self.error_output(str(exc))
557 else:
557 else:
558 attrs = [ipipe.AttributeDetail(item, attr) for attr in ipipe.xattrs(item, "detail")]
558 attrs = [ipipe.AttributeDetail(item, attr) for attr in ipipe.xattrs(item, "detail")]
559 self._doenter(attrs)
559 self._doenter(attrs)
560
560
561 def detail_attr(self, row, col):
561 def detail_attr(self, row, col):
562 try:
562 try:
563 attr = self.table._displayattrs[col]
563 attr = self.table._displayattrs[col]
564 item = attr.value(self.table.items[row])
564 item = attr.value(self.table.items[row])
565 except Exception, exc:
565 except Exception, exc:
566 self.error_output(str(exc))
566 self.error_output(str(exc))
567 else:
567 else:
568 attrs = [ipipe.AttributeDetail(item, attr) for attr in ipipe.xattrs(item, "detail")]
568 attrs = [ipipe.AttributeDetail(item, attr) for attr in ipipe.xattrs(item, "detail")]
569 self._doenter(attrs)
569 self._doenter(attrs)
570
570
571 def quit(self, result=None):
571 def quit(self, result=None):
572 """
572 """
573 quit
573 quit
574 """
574 """
575 frame = self.GetParent().GetParent().GetParent()
575 frame = self.GetParent().GetParent().GetParent()
576 if frame.helpdialog:
576 if frame.helpdialog:
577 frame.helpdialog.Destroy()
577 frame.helpdialog.Destroy()
578 app = frame.parent
578 app = frame.parent
579 if app is not None:
579 if app is not None:
580 app.result = result
580 app.result = result
581 frame.Close()
581 frame.Close()
582 frame.Destroy()
582 frame.Destroy()
583
583
584 def cell_doubleclicked(self, event):
584 def cell_doubleclicked(self, event):
585 self.enterattr(event.GetRow(), event.GetCol())
585 self.enterattr(event.GetRow(), event.GetCol())
586 event.Skip()
586 event.Skip()
587
587
588 def cell_leftclicked(self, event):
588 def cell_leftclicked(self, event):
589 row = event.GetRow()
589 row = event.GetRow()
590 item = self.table.items[row]
590 item = self.table.items[row]
591 self.set_footer(item)
591 self.set_footer(item)
592 event.Skip()
592 event.Skip()
593
593
594 def pick(self, row):
594 def pick(self, row):
595 """
595 """
596 pick a single row and return to the IPython prompt
596 pick a single row and return to the IPython prompt
597 """
597 """
598 try:
598 try:
599 value = self.table.items[row]
599 value = self.table.items[row]
600 except Exception, exc:
600 except Exception, exc:
601 self.error_output(str(exc))
601 self.error_output(str(exc))
602 else:
602 else:
603 self.quit(value)
603 self.quit(value)
604
604
605 def pickrows(self, rows):
605 def pickrows(self, rows):
606 """
606 """
607 pick multiple rows and return to the IPython prompt
607 pick multiple rows and return to the IPython prompt
608 """
608 """
609 try:
609 try:
610 value = [self.table.items[row] for row in rows]
610 value = [self.table.items[row] for row in rows]
611 except Exception, exc:
611 except Exception, exc:
612 self.error_output(str(exc))
612 self.error_output(str(exc))
613 else:
613 else:
614 self.quit(value)
614 self.quit(value)
615
615
616 def pickrowsattr(self, rows, col):
616 def pickrowsattr(self, rows, col):
617 """"
617 """"
618 pick one column from multiple rows
618 pick one column from multiple rows
619 """
619 """
620 values = []
620 values = []
621 try:
621 try:
622 attr = self.table._displayattrs[col]
622 attr = self.table._displayattrs[col]
623 for row in rows:
623 for row in rows:
624 try:
624 try:
625 values.append(attr.value(self.table.items[row]))
625 values.append(attr.value(self.table.items[row]))
626 except (SystemExit, KeyboardInterrupt):
626 except (SystemExit, KeyboardInterrupt):
627 raise
627 raise
628 except Exception:
628 except Exception:
629 raise #pass
629 raise #pass
630 except Exception, exc:
630 except Exception, exc:
631 self.error_output(str(exc))
631 self.error_output(str(exc))
632 else:
632 else:
633 self.quit(values)
633 self.quit(values)
634
634
635 def pickattr(self, row, col):
635 def pickattr(self, row, col):
636 try:
636 try:
637 attr = self.table._displayattrs[col]
637 attr = self.table._displayattrs[col]
638 value = attr.value(self.table.items[row])
638 value = attr.value(self.table.items[row])
639 except Exception, exc:
639 except Exception, exc:
640 self.error_output(str(exc))
640 self.error_output(str(exc))
641 else:
641 else:
642 self.quit(value)
642 self.quit(value)
643
643
644
644
645 class IGridPanel(wx.Panel):
645 class IGridPanel(wx.Panel):
646 # Each IGridPanel contains an IGridGrid
646 # Each IGridPanel contains an IGridGrid
647 def __init__(self, parent, input, *attrs):
647 def __init__(self, parent, input, *attrs):
648 wx.Panel.__init__(self, parent, -1)
648 wx.Panel.__init__(self, parent, -1)
649 self.grid = IGridGrid(self, input, *attrs)
649 self.grid = IGridGrid(self, input, *attrs)
650 sizer = wx.BoxSizer(wx.VERTICAL)
650 sizer = wx.BoxSizer(wx.VERTICAL)
651 sizer.Add(self.grid, proportion=1, flag=wx.EXPAND | wx.ALL, border=10)
651 sizer.Add(self.grid, proportion=1, flag=wx.EXPAND | wx.ALL, border=10)
652 self.SetSizer(sizer)
652 self.SetSizer(sizer)
653 sizer.Fit(self)
653 sizer.Fit(self)
654 sizer.SetSizeHints(self)
654 sizer.SetSizeHints(self)
655
655
656
656
657 class IGridHTMLHelp(wx.Frame):
657 class IGridHTMLHelp(wx.Frame):
658 def __init__(self, parent, title, filename, size):
658 def __init__(self, parent, title, filename, size):
659 wx.Frame.__init__(self, parent, -1, title, size=size)
659 wx.Frame.__init__(self, parent, -1, title, size=size)
660 html = wx.html.HtmlWindow(self)
660 html = wx.html.HtmlWindow(self)
661 if "gtk2" in wx.PlatformInfo:
661 if "gtk2" in wx.PlatformInfo:
662 html.SetStandardFonts()
662 html.SetStandardFonts()
663 html.LoadFile(filename)
663 html.LoadFile(filename)
664
664
665
665
666 class IGridFrame(wx.Frame):
666 class IGridFrame(wx.Frame):
667 maxtitlelen = 30
667 maxtitlelen = 30
668
668
669 def __init__(self, parent, input):
669 def __init__(self, parent, input):
670 title = " ".join([str(text) for (style, text) in ipipe.xformat(input, "header", 20)[2]])
670 title = " ".join([str(text) for (style, text) in ipipe.xformat(input, "header", 20)[2]])
671 wx.Frame.__init__(self, None, title=title, size=(640, 480))
671 wx.Frame.__init__(self, None, title=title, size=(640, 480))
672 self.menubar = wx.MenuBar()
672 self.menubar = wx.MenuBar()
673 self.menucounter = 100
673 self.menucounter = 100
674 self.m_help = wx.Menu()
674 self.m_help = wx.Menu()
675 self.m_search = wx.Menu()
675 self.m_search = wx.Menu()
676 self.m_sort = wx.Menu()
676 self.m_sort = wx.Menu()
677 self.notebook = wx.Notebook(self, -1, style=0)
677 self.notebook = wx.Notebook(self, -1, style=0)
678 self.statusbar = self.CreateStatusBar(1, wx.ST_SIZEGRIP)
678 self.statusbar = self.CreateStatusBar(1, wx.ST_SIZEGRIP)
679 self.parent = parent
679 self.parent = parent
680 self._add_notebook(input)
680 self._add_notebook(input)
681 self.Bind(wx.EVT_CLOSE, self.OnCloseWindow)
681 self.Bind(wx.EVT_CLOSE, self.OnCloseWindow)
682 self.makemenu(self.m_sort, "&Sort (asc)", "Sort ascending", self.sortasc)
682 self.makemenu(self.m_sort, "&Sort (asc)", "Sort ascending", self.sortasc)
683 self.makemenu(self.m_sort, "Sort (&desc)", "Sort descending", self.sortdesc)
683 self.makemenu(self.m_sort, "Sort (&desc)", "Sort descending", self.sortdesc)
684 self.makemenu(self.m_help, "&Help", "Help", self.display_help)
684 self.makemenu(self.m_help, "&Help", "Help", self.display_help)
685 self.makemenu(self.m_help, "&Show help in browser", "Show help in browser", self.display_help_in_browser)
685 self.makemenu(self.m_help, "&Show help in browser", "Show help in browser", self.display_help_in_browser)
686 self.makemenu(self.m_search, "&Find text", "Find text", self.enter_searchtext)
686 self.makemenu(self.m_search, "&Find text", "Find text", self.enter_searchtext)
687 self.makemenu(self.m_search, "Find by &expression", "Find by expression", self.enter_searchexpression)
687 self.makemenu(self.m_search, "Find by &expression", "Find by expression", self.enter_searchexpression)
688 self.makemenu(self.m_search, "Find &next", "Find next", self.find_next)
688 self.makemenu(self.m_search, "Find &next", "Find next", self.find_next)
689 self.makemenu(self.m_search, "Find &previous", "Find previous", self.find_previous)
689 self.makemenu(self.m_search, "Find &previous", "Find previous", self.find_previous)
690 self.menubar.Append(self.m_search, "&Find")
690 self.menubar.Append(self.m_search, "&Find")
691 self.menubar.Append(self.m_sort, "&Sort")
691 self.menubar.Append(self.m_sort, "&Sort")
692 self.menubar.Append(self.m_help, "&Help")
692 self.menubar.Append(self.m_help, "&Help")
693 self.SetMenuBar(self.menubar)
693 self.SetMenuBar(self.menubar)
694 self.searchtext = ""
694 self.searchtext = ""
695 self.helpdialog = None
695 self.helpdialog = None
696
696
697 def sortasc(self, event):
697 def sortasc(self, event):
698 grid = self.notebook.GetPage(self.notebook.GetSelection()).grid
698 grid = self.notebook.GetPage(self.notebook.GetSelection()).grid
699 grid.sortattrasc()
699 grid.sortattrasc()
700
700
701 def sortdesc(self, event):
701 def sortdesc(self, event):
702 grid = self.notebook.GetPage(self.notebook.GetSelection()).grid
702 grid = self.notebook.GetPage(self.notebook.GetSelection()).grid
703 grid.sortattrdesc()
703 grid.sortattrdesc()
704
704
705 def find_previous(self, event):
705 def find_previous(self, event):
706 """
706 """
707 find previous occurrences
707 find previous occurrences
708 """
708 """
709 if self.searchtext:
709 if self.searchtext:
710 grid = self.notebook.GetPage(self.notebook.GetSelection()).grid
710 grid = self.notebook.GetPage(self.notebook.GetSelection()).grid
711 row = grid.GetGridCursorRow()
711 row = grid.GetGridCursorRow()
712 col = grid.GetGridCursorCol()
712 col = grid.GetGridCursorCol()
713 if col-1 >= 0:
713 if col-1 >= 0:
714 grid.search(self.searchtext, row, col-1, False)
714 grid.search(self.searchtext, row, col-1, False)
715 else:
715 else:
716 grid.search(self.searchtext, row-1, grid.table.GetNumberCols()-1, False)
716 grid.search(self.searchtext, row-1, grid.table.GetNumberCols()-1, False)
717 else:
717 else:
718 self.enter_searchtext(event)
718 self.enter_searchtext(event)
719
719
720 def find_next(self, event):
720 def find_next(self, event):
721 """
721 """
722 find the next occurrence
722 find the next occurrence
723 """
723 """
724 if self.searchtext:
724 if self.searchtext:
725 grid = self.notebook.GetPage(self.notebook.GetSelection()).grid
725 grid = self.notebook.GetPage(self.notebook.GetSelection()).grid
726 row = grid.GetGridCursorRow()
726 row = grid.GetGridCursorRow()
727 col = grid.GetGridCursorCol()
727 col = grid.GetGridCursorCol()
728 if col+1 < grid.table.GetNumberCols():
728 if col+1 < grid.table.GetNumberCols():
729 grid.search(self.searchtext, row, col+1)
729 grid.search(self.searchtext, row, col+1)
730 else:
730 else:
731 grid.search(self.searchtext, row+1, 0)
731 grid.search(self.searchtext, row+1, 0)
732 else:
732 else:
733 self.enter_searchtext(event)
733 self.enter_searchtext(event)
734
734
735 def display_help(self, event):
735 def display_help(self, event):
736 """
736 """
737 Display a help dialog
737 Display a help dialog
738 """
738 """
739 if self.helpdialog:
739 if self.helpdialog:
740 self.helpdialog.Destroy()
740 self.helpdialog.Destroy()
741 filename = os.path.join(os.path.dirname(__file__), "igrid_help.html")
741 filename = os.path.join(os.path.dirname(__file__), "igrid_help.html")
742 self.helpdialog = IGridHTMLHelp(None, title="Help", filename=filename, size=wx.Size(600,400))
742 self.helpdialog = IGridHTMLHelp(None, title="Help", filename=filename, size=wx.Size(600,400))
743 self.helpdialog.Show()
743 self.helpdialog.Show()
744
744
745 def display_help_in_browser(self, event):
745 def display_help_in_browser(self, event):
746 """
746 """
747 Show the help-HTML in a browser (as a ``HtmlWindow`` does not understand
747 Show the help-HTML in a browser (as a ``HtmlWindow`` does not understand
748 CSS this looks better)
748 CSS this looks better)
749 """
749 """
750 filename = urllib.pathname2url(os.path.abspath(os.path.join(os.path.dirname(__file__), "igrid_help.html")))
750 filename = urllib.pathname2url(os.path.abspath(os.path.join(os.path.dirname(__file__), "igrid_help.html")))
751 if not filename.startswith("file"):
751 if not filename.startswith("file"):
752 filename = "file:" + filename
752 filename = "file:" + filename
753 webbrowser.open(filename, new=1, autoraise=True)
753 webbrowser.open(filename, new=1, autoraise=True)
754
754
755 def enter_searchexpression(self, event):
755 def enter_searchexpression(self, event):
756 pass
756 pass
757
757
758 def makemenu(self, menu, label, help, cmd):
758 def makemenu(self, menu, label, help, cmd):
759 menu.Append(self.menucounter, label, help)
759 menu.Append(self.menucounter, label, help)
760 self.Bind(wx.EVT_MENU, cmd, id=self.menucounter)
760 self.Bind(wx.EVT_MENU, cmd, id=self.menucounter)
761 self.menucounter += 1
761 self.menucounter += 1
762
762
763 def _add_notebook(self, input, *attrs):
763 def _add_notebook(self, input, *attrs):
764 # Adds another notebook which has the starting object ``input``
764 # Adds another notebook which has the starting object ``input``
765 panel = IGridPanel(self.notebook, input, *attrs)
765 panel = IGridPanel(self.notebook, input, *attrs)
766 text = str(ipipe.xformat(input, "header", self.maxtitlelen)[2])
766 text = str(ipipe.xformat(input, "header", self.maxtitlelen)[2])
767 if len(text) >= self.maxtitlelen:
767 if len(text) >= self.maxtitlelen:
768 text = text[:self.maxtitlelen].rstrip(".") + "..."
768 text = text[:self.maxtitlelen].rstrip(".") + "..."
769 self.notebook.AddPage(panel, text, True)
769 self.notebook.AddPage(panel, text, True)
770 panel.grid.SetFocus()
770 panel.grid.SetFocus()
771 self.Layout()
771 self.Layout()
772
772
773 def OnCloseWindow(self, event):
773 def OnCloseWindow(self, event):
774 self.Destroy()
774 self.Destroy()
775
775
776 def enter_searchtext(self, event):
776 def enter_searchtext(self, event):
777 # Displays a dialog asking for the searchtext
777 # Displays a dialog asking for the searchtext
778 dlg = wx.TextEntryDialog(self, "Find:", "Find in list")
778 dlg = wx.TextEntryDialog(self, "Find:", "Find in list")
779 if dlg.ShowModal() == wx.ID_OK:
779 if dlg.ShowModal() == wx.ID_OK:
780 self.searchtext = dlg.GetValue()
780 self.searchtext = dlg.GetValue()
781 self.notebook.GetPage(self.notebook.GetSelection()).grid.search(self.searchtext, 0, 0)
781 self.notebook.GetPage(self.notebook.GetSelection()).grid.search(self.searchtext, 0, 0)
782 dlg.Destroy()
782 dlg.Destroy()
783
783
784
784
785 class App(wx.App):
785 class App(wx.App):
786 def __init__(self, input):
786 def __init__(self, input):
787 self.input = input
787 self.input = input
788 self.result = None # Result to be returned to IPython. Set by quit().
788 self.result = None # Result to be returned to IPython. Set by quit().
789 wx.App.__init__(self)
789 wx.App.__init__(self)
790
790
791 def OnInit(self):
791 def OnInit(self):
792 frame = IGridFrame(self, self.input)
792 frame = IGridFrame(self, self.input)
793 frame.Show()
793 frame.Show()
794 self.SetTopWindow(frame)
794 self.SetTopWindow(frame)
795 frame.Raise()
795 frame.Raise()
796 return True
796 return True
797
797
798
798
799 class igrid(ipipe.Display):
799 class igrid(ipipe.Display):
800 """
800 """
801 This is a wx-based display object that can be used instead of ``ibrowse``
801 This is a wx-based display object that can be used instead of ``ibrowse``
802 (which is curses-based) or ``idump`` (which simply does a print).
802 (which is curses-based) or ``idump`` (which simply does a print).
803 """
803 """
804 if wx.VERSION < (2, 7):
804 if wx.VERSION < (2, 7):
805 def display(self):
805 def display(self):
806 try:
806 try:
807 # Try to create a "standalone" from. If this works we're probably
807 # Try to create a "standalone" from. If this works we're probably
808 # running with -wthread.
808 # running with -wthread.
809 # Note that this sets the parent of the frame to None, but we can't
809 # Note that this sets the parent of the frame to None, but we can't
810 # pass a result object back to the shell anyway.
810 # pass a result object back to the shell anyway.
811 frame = IGridFrame(None, self.input)
811 frame = IGridFrame(None, self.input)
812 frame.Show()
812 frame.Show()
813 frame.Raise()
813 frame.Raise()
814 except wx.PyNoAppError:
814 except wx.PyNoAppError:
815 # There's no wx application yet => create one.
815 # There's no wx application yet => create one.
816 app = App(self.input)
816 app = App(self.input)
817 app.MainLoop()
817 app.MainLoop()
818 return app.result
818 return app.result
819 else:
819 else:
820 # With wx 2.7 it gets simpler.
820 # With wx 2.7 it gets simpler.
821 def display(self):
821 def display(self):
822 app = App(self.input)
822 app = App(self.input)
823 app.MainLoop()
823 app.MainLoop()
824 return app.result
824 return app.result
825
825
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
General Comments 0
You need to be logged in to leave comments. Login now