##// END OF EJS Templates
Patch by Nik Tautenhahn: Close help window if...
walter.doerwald -
Show More

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

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