##// END OF EJS Templates
Add new commands refresh and refresh_timer (mapped to "R"/"F5"...
walter.doerwald -
Show More
@@ -1,6 +1,7 b''
1 1 # -*- coding: iso-8859-1 -*-
2 2
3 3 import ipipe, os, webbrowser, urllib
4 from IPython import ipapi
4 5 import wx
5 6 import wx.grid, wx.html
6 7
@@ -36,10 +37,16 b' help = """'
36 37 <p>Pick the attribute under the cursor</p>
37 38
38 39 <h3>pickallattrs (Shift-C)</h3>
39 <p>Pick' the complete column under the cursor (i.e. the attribute under the
40 <p>Pick the complete column under the cursor (i.e. the attribute under the
40 41 cursor) from all currently fetched objects. These attributes will be returned
41 42 as a list.</p>
42 43
44 <h3>pickinput (I)</h3>
45 <p>Pick the current row as next input line in IPython. Additionally the row is stored as "_"</p>
46
47 <h3>pickinputattr (Shift-I)</h3>
48 <p>Pick the attribute under the cursor as next input line in IPython. Additionally the row is stored as "_"</p>
49
43 50 <h3>enter (E)</h3>
44 51 <p>Enter the object under the cursor. (what this mean depends on the object
45 52 itself, i.e. how it implements iteration). This opens a new browser 'level'.</p>
@@ -64,11 +71,14 b' attributes than in the list view, depending on the object).</p>'
64 71 <h3>find (CTRL-F)</h3>
65 72 <p>Find text</p>
66 73
74 <h3>find_expression (CTRL-Shift-F)</h3>
75 <p>Find entries matching an expression</p>
76
67 77 <h3>find_next (F3)</h3>
68 <p>Find next occurrence of the searchtext</p>
78 <p>Find next occurrence</p>
69 79
70 80 <h3>find_previous (Shift-F3)</h3>
71 <p>Find previous occurrence of the searchtext </p>
81 <p>Find previous occurrence</p>
72 82
73 83 <h3>sortattrasc (V)</h3>
74 84 <p>Sort the objects (in ascending order) using the attribute under the cursor as the sort key.</p>
@@ -76,6 +86,18 b' attributes than in the list view, depending on the object).</p>'
76 86 <h3>sortattrdesc (Shift-V)</h3>
77 87 <p>Sort the objects (in descending order) using the attribute under the cursor as the sort key.</p>
78 88
89 <h3>refresh_once (R, F5)</h3>
90 <p>Refreshes the display by restarting the iterator</p>
91
92 <h3>refresh_every_second</h3>
93 <p>Refreshes the display by restarting the iterator every second until stopped by stop_refresh.</p>
94
95 <h3>refresh_interval</h3>
96 <p>Refreshes the display by restarting the iterator every X ms (X is a custom interval set by the user) until stopped by stop_refresh.</p>
97
98 <h3>stop_refresh</h3>
99 <p>Stops all refresh timers.</p>
100
79 101 <h3>leave (Backspace, DEL, X)</h3>
80 102 <p>Close current tab (and all the tabs to the right of the current one).</h3>
81 103
@@ -100,6 +122,7 b' attributes than in the list view, depending on the object).</p>'
100 122
101 123 </body>
102 124 </html>
125
103 126 """
104 127
105 128
@@ -216,9 +239,10 b' class IGridTable(wx.grid.PyGridTableBase):'
216 239 self.attrs = [ipipe.upgradexattr(attr) for attr in attrs]
217 240 self._displayattrs = self.attrs[:]
218 241 self._displayattrset = set(self.attrs)
219 self._sizing = False
220 242 self.fontsize = fontsize
221 243 self._fetch(1)
244 self.timer = wx.Timer()
245 self.timer.Bind(wx.EVT_TIMER, self.refresh_content)
222 246
223 247 def GetAttr(self, *args):
224 248 attr = wx.grid.GridCellAttr()
@@ -277,28 +301,49 b' class IGridTable(wx.grid.PyGridTableBase):'
277 301 # some kind of dummy-function: does not return anything but "";
278 302 # (The value isn't use anyway)
279 303 # its main task is to trigger the fetch of new objects
280 had_cols = self._displayattrs[:]
304 sizing_needed = False
305 had_cols = len(self._displayattrs)
281 306 had_rows = len(self.items)
282 if row == had_rows - 1 and self.iterator is not None and not self._sizing:
307 if row == had_rows - 1 and self.iterator is not None:
283 308 self._fetch(row + 20)
309 sizing_needed = True
284 310 have_rows = len(self.items)
285 311 have_cols = len(self._displayattrs)
286 312 if have_rows > had_rows:
287 313 msg = wx.grid.GridTableMessage(self, wx.grid.GRIDTABLE_NOTIFY_ROWS_APPENDED, have_rows - had_rows)
288 314 self.GetView().ProcessTableMessage(msg)
289 self._sizing = True
290 self.GetView().AutoSizeColumns(False)
291 self._sizing = False
315 sizing_needed = True
292 316 if row >= have_rows:
293 317 return ""
294 if self._displayattrs != had_cols:
295 msg = wx.grid.GridTableMessage(self, wx.grid.GRIDTABLE_NOTIFY_COLS_APPENDED, have_cols - len(had_cols))
318 if have_cols != had_cols:
319 msg = wx.grid.GridTableMessage(self, wx.grid.GRIDTABLE_NOTIFY_COLS_APPENDED, have_cols - had_cols)
296 320 self.GetView().ProcessTableMessage(msg)
321 sizing_needed = True
322 if sizing_needed:
323 self.GetView().AutoSizeColumns(False)
297 324 return ""
298 325
299 326 def SetValue(self, row, col, value):
300 327 pass
301 328
329 def refresh_content(self, event):
330 msg = wx.grid.GridTableMessage(self, wx.grid.GRIDTABLE_NOTIFY_ROWS_DELETED, 0, self.GetNumberRows())
331 self.GetView().ProcessTableMessage(msg)
332 self.iterator = ipipe.xiter(self.input)
333 self.items = []
334 self.attrs = [] # _append will calculate new displayattrs
335 self._fetch(1) # fetch one...
336 if self.items:
337 msg = wx.grid.GridTableMessage(self, wx.grid.GRIDTABLE_NOTIFY_ROWS_APPENDED, 1)
338 self.GetView().ProcessTableMessage(msg)
339 self.GetValue(0, 0) # and trigger "fetch next 20"
340 item = self.items[0]
341 self.GetView().AutoSizeColumns(False)
342 panel = self.GetView().GetParent()
343 nb = panel.GetParent()
344 current = nb.GetSelection()
345 if nb.GetPage(current) == panel:
346 self.GetView().set_footer(item)
302 347
303 348 class IGridGrid(wx.grid.Grid):
304 349 # The actual grid
@@ -328,7 +373,7 b' class IGridGrid(wx.grid.Grid):'
328 373 def error_output(self, text):
329 374 wx.Bell()
330 375 frame = self.GetParent().GetParent().GetParent()
331 frame.SetStatusText(text)
376 frame.SetStatusText(str(text))
332 377
333 378 def _on_selected_range(self, event):
334 379 # Internal update to the selection tracking lists
@@ -337,7 +382,7 b' class IGridGrid(wx.grid.Grid):'
337 382 self.current_selection.update(xrange(event.GetTopRow(), event.GetBottomRow()+1))
338 383 else:
339 384 # removal from list
340 for index in xrange( event.GetTopRow(), event.GetBottomRow()+1):
385 for index in xrange(event.GetTopRow(), event.GetBottomRow()+1):
341 386 self.current_selection.discard(index)
342 387 event.Skip()
343 388
@@ -433,14 +478,77 b' class IGridGrid(wx.grid.Grid):'
433 478 (align, width, text) = ipipe.xformat(exc, "cell", self.maxchars)
434 479 return text
435 480
436 def search(self, searchtext, startrow=0, startcol=0, search_forward=True):
481 def searchexpression(self, searchexp, startrow=None, search_forward=True ):
482 """
483 Find by expression
484 """
485 frame = self.GetParent().GetParent().GetParent()
486 if searchexp:
487 if search_forward:
488 if not startrow:
489 row = self.GetGridCursorRow()+1
490 else:
491 row = startrow + 1
492 while True:
493 try:
494 foo = self.table.GetValue(row, 0)
495 item = self.table.items[row]
496 try:
497 globals = ipipe.getglobals(None)
498 if eval(searchexp, globals, ipipe.AttrNamespace(item)):
499 self.SetGridCursor(row, 0) # found something
500 self.MakeCellVisible(row, 0)
501 break
502 except (KeyboardInterrupt, SystemExit):
503 raise
504 except Exception, exc:
505 frame.SetStatusText(str(exc))
506 wx.Bell()
507 break # break on error
508 except IndexError:
509 return
510 row += 1
511 else:
512 if not startrow:
513 row = self.GetGridCursorRow() - 1
514 else:
515 row = startrow - 1
516 while True:
517 try:
518 foo = self.table.GetValue(row, 0)
519 item = self.table.items[row]
520 try:
521 globals = ipipe.getglobals(None)
522 if eval(searchexp, globals, ipipe.AttrNamespace(item)):
523 self.SetGridCursor(row, 0) # found something
524 self.MakeCellVisible(row, 0)
525 break
526 except (KeyboardInterrupt, SystemExit):
527 raise
528 except Exception, exc:
529 frame.SetStatusText(str(exc))
530 wx.Bell()
531 break # break on error
532 except IndexError:
533 return
534 row -= 1
535
536
537 def search(self, searchtext, startrow=None, startcol=None, search_forward=True):
437 538 """
438 539 search for ``searchtext``, starting in ``(startrow, startcol)``;
439 540 if ``search_forward`` is true the direction is "forward"
440 541 """
441 row = startrow
442 542 searchtext = searchtext.lower()
443 543 if search_forward:
544 if startrow is not None and startcol is not None:
545 row = startrow
546 else:
547 startcol = self.GetGridCursorCol() + 1
548 row = self.GetGridCursorRow()
549 if startcol >= self.GetNumberCols():
550 startcol = 0
551 row += 1
444 552 while True:
445 553 for col in xrange(startcol, self.table.GetNumberCols()):
446 554 try:
@@ -455,6 +563,14 b' class IGridGrid(wx.grid.Grid):'
455 563 startcol = 0
456 564 row += 1
457 565 else:
566 if startrow is not None and startcol is not None:
567 row = startrow
568 else:
569 startcol = self.GetGridCursorCol() - 1
570 row = self.GetGridCursorRow()
571 if startcol < 0:
572 startcol = self.GetNumberCols() - 1
573 row -= 1
458 574 while True:
459 575 for col in xrange(startcol, -1, -1):
460 576 try:
@@ -535,7 +651,10 b' class IGridGrid(wx.grid.Grid):'
535 651 else:
536 652 self.detail_attr(row, col)
537 653 elif keycode == ord("F") and ctrl:
538 frame.enter_searchtext(event)
654 if sh:
655 frame.enter_searchexpression(event)
656 else:
657 frame.enter_searchtext(event)
539 658 elif keycode == wx.WXK_F3:
540 659 if sh:
541 660 frame.find_previous(event)
@@ -561,7 +680,7 b' class IGridGrid(wx.grid.Grid):'
561 680 else:
562 681 item = self.table.items[row]
563 682 self.set_footer(item)
564 event.Skip()
683 event.Skip()
565 684 elif keycode == wx.WXK_RIGHT:
566 685 row = self.GetGridCursorRow()
567 686 item = self.table.items[row]
@@ -572,6 +691,15 b' class IGridGrid(wx.grid.Grid):'
572 691 item = self.table.items[row]
573 692 self.set_footer(item)
574 693 event.Skip()
694 elif keycode == ord("R") or keycode == wx.WXK_F5:
695 self.table.refresh_content(event)
696 elif keycode == ord("I"):
697 row = self.GetGridCursorRow()
698 if not sh:
699 self.pickinput(row)
700 else:
701 col = self.GetGridCursorCol()
702 self.pickinputattr(row, col)
575 703 else:
576 704 event.Skip()
577 705
@@ -625,7 +753,7 b' class IGridGrid(wx.grid.Grid):'
625 753
626 754 def set_footer(self, item):
627 755 frame = self.GetParent().GetParent().GetParent()
628 frame.SetStatusText(" ".join([str(text) for (style, text) in ipipe.xformat(item, "footer", 20)[2]]))
756 frame.SetStatusText(" ".join([str(text) for (style, text) in ipipe.xformat(item, "footer", 20)[2]]), 0)
629 757
630 758 def enter(self, row):
631 759 try:
@@ -680,7 +808,7 b' class IGridGrid(wx.grid.Grid):'
680 808 item = self.table.items[row]
681 809 self.set_footer(item)
682 810 event.Skip()
683
811
684 812 def pick(self, row):
685 813 """
686 814 pick a single row and return to the IPython prompt
@@ -692,6 +820,27 b' class IGridGrid(wx.grid.Grid):'
692 820 else:
693 821 self.quit(value)
694 822
823 def pickinput(self, row):
824 try:
825 value = self.table.items[row]
826 except Exception, exc:
827 self.error_output(str(exc))
828 else:
829 api = ipapi.get()
830 api.set_next_input(str(value))
831 self.quit(value)
832
833 def pickinputattr(self, row, col):
834 try:
835 attr = self.table._displayattrs[col]
836 value = attr.value(self.table.items[row])
837 except Exception, exc:
838 self.error_output(str(exc))
839 else:
840 api = ipapi.get()
841 api.set_next_input(str(value))
842 self.quit(value)
843
695 844 def pickrows(self, rows):
696 845 """
697 846 pick multiple rows and return to the IPython prompt
@@ -737,6 +886,7 b' class IGridPanel(wx.Panel):'
737 886 def __init__(self, parent, input, *attrs):
738 887 wx.Panel.__init__(self, parent, -1)
739 888 self.grid = IGridGrid(self, input, *attrs)
889 self.grid.FitInside()
740 890 sizer = wx.BoxSizer(wx.VERTICAL)
741 891 sizer.Add(self.grid, proportion=1, flag=wx.EXPAND | wx.ALL, border=10)
742 892 self.SetSizer(sizer)
@@ -764,25 +914,66 b' class IGridFrame(wx.Frame):'
764 914 self.m_help = wx.Menu()
765 915 self.m_search = wx.Menu()
766 916 self.m_sort = wx.Menu()
917 self.m_refresh = wx.Menu()
767 918 self.notebook = wx.Notebook(self, -1, style=0)
768 919 self.statusbar = self.CreateStatusBar(1, wx.ST_SIZEGRIP)
920 self.statusbar.SetFieldsCount(2)
921 self.SetStatusWidths([-1, 200])
769 922 self.parent = parent
770 923 self._add_notebook(input)
771 924 self.Bind(wx.EVT_CLOSE, self.OnCloseWindow)
772 self.makemenu(self.m_sort, "&Sort (asc)", "Sort ascending", self.sortasc)
773 self.makemenu(self.m_sort, "Sort (&desc)", "Sort descending", self.sortdesc)
774 self.makemenu(self.m_help, "&Help", "Help", self.display_help)
775 self.makemenu(self.m_help, "&Show help in browser", "Show help in browser", self.display_help_in_browser)
776 self.makemenu(self.m_search, "&Find text", "Find text", self.enter_searchtext)
777 self.makemenu(self.m_search, "Find by &expression", "Find by expression", self.enter_searchexpression)
778 self.makemenu(self.m_search, "Find &next", "Find next", self.find_next)
779 self.makemenu(self.m_search, "Find &previous", "Find previous", self.find_previous)
925 self.makemenu(self.m_sort, "&Sort (asc)\tV", "Sort ascending", self.sortasc)
926 self.makemenu(self.m_sort, "Sort (&desc)\tShift-V", "Sort descending", self.sortdesc)
927 self.makemenu(self.m_help, "&Help\tF1", "Help", self.display_help)
928 # self.makemenu(self.m_help, "&Show help in browser", "Show help in browser", self.display_help_in_browser)
929 self.makemenu(self.m_search, "&Find text\tCTRL-F", "Find text", self.enter_searchtext)
930 self.makemenu(self.m_search, "Find by &expression\tCTRL-Shift-F", "Find by expression", self.enter_searchexpression)
931 self.makemenu(self.m_search, "Find &next\tF3", "Find next", self.find_next)
932 self.makemenu(self.m_search, "Find &previous\tShift-F3", "Find previous", self.find_previous)
933 self.makemenu(self.m_refresh, "&Refresh once \tF5", "Refresh once", self.refresh_once)
934 self.makemenu(self.m_refresh, "Refresh every &1s", "Refresh every second", self.refresh_every_second)
935 self.makemenu(self.m_refresh, "Refresh every &X seconds", "Refresh every X seconds", self.refresh_interval)
936 self.makemenu(self.m_refresh, "&Stop all refresh timers", "Stop refresh timers", self.stop_refresh)
780 937 self.menubar.Append(self.m_search, "&Find")
781 938 self.menubar.Append(self.m_sort, "&Sort")
939 self.menubar.Append(self.m_refresh, "&Refresh")
782 940 self.menubar.Append(self.m_help, "&Help")
783 941 self.SetMenuBar(self.menubar)
784 942 self.searchtext = ""
943 self.searchexpression = ""
785 944 self.helpdialog = None
945 self.refresh_interval = 1000
946 self.SetStatusText("Refreshing inactive", 1)
947
948 def refresh_once(self, event):
949 table = self.notebook.GetPage(self.notebook.GetSelection()).grid.table
950 table.refresh_content(event)
951
952 def refresh_interval(self, event):
953 table = self.notebook.GetPage(self.notebook.GetSelection()).grid.table
954 dlg = wx.TextEntryDialog(self, "Enter refresh interval (milliseconds):", "Refresh timer:", defaultValue=str(self.refresh_interval))
955 if dlg.ShowModal() == wx.ID_OK:
956 try:
957 milliseconds = int(dlg.GetValue())
958 except ValueError, exc:
959 self.SetStatusText(str(exc))
960 else:
961 table.timer.Start(milliseconds=milliseconds, oneShot=False)
962 self.SetStatusText("Refresh timer set to %s ms" % milliseconds)
963 self.SetStatusText("Refresh interval: %s ms" % milliseconds, 1)
964 self.refresh_interval = milliseconds
965 dlg.Destroy()
966
967 def stop_refresh(self, event):
968 for i in xrange(self.notebook.GetPageCount()):
969 nb = self.notebook.GetPage(i)
970 nb.grid.table.timer.Stop()
971 self.SetStatusText("Refreshing inactive", 1)
972
973 def refresh_every_second(self, event):
974 table = self.notebook.GetPage(self.notebook.GetSelection()).grid.table
975 table.timer.Start(milliseconds=1000, oneShot=False)
976 self.SetStatusText("Refresh interval: 1000 ms", 1)
786 977
787 978 def sortasc(self, event):
788 979 grid = self.notebook.GetPage(self.notebook.GetSelection()).grid
@@ -796,31 +987,39 b' class IGridFrame(wx.Frame):'
796 987 """
797 988 find previous occurrences
798 989 """
990 grid = self.notebook.GetPage(self.notebook.GetSelection()).grid
799 991 if self.searchtext:
800 grid = self.notebook.GetPage(self.notebook.GetSelection()).grid
801 992 row = grid.GetGridCursorRow()
802 993 col = grid.GetGridCursorCol()
994 self.SetStatusText('Search mode: text; looking for %s' % self.searchtext)
803 995 if col-1 >= 0:
804 996 grid.search(self.searchtext, row, col-1, False)
805 997 else:
806 998 grid.search(self.searchtext, row-1, grid.table.GetNumberCols()-1, False)
999 elif self.searchexpression:
1000 self.SetStatusText("Search mode: expression; looking for %s" % repr(self.searchexpression)[2:-1])
1001 grid.searchexpression(searchexp=self.searchexpression, search_forward=False)
807 1002 else:
808 self.enter_searchtext(event)
1003 self.SetStatusText("No search yet: please enter search-text or -expression")
809 1004
810 1005 def find_next(self, event):
811 1006 """
812 1007 find the next occurrence
813 1008 """
814 if self.searchtext:
815 grid = self.notebook.GetPage(self.notebook.GetSelection()).grid
1009 grid = self.notebook.GetPage(self.notebook.GetSelection()).grid
1010 if self.searchtext != "":
816 1011 row = grid.GetGridCursorRow()
817 1012 col = grid.GetGridCursorCol()
1013 self.SetStatusText('Search mode: text; looking for %s' % self.searchtext)
818 1014 if col+1 < grid.table.GetNumberCols():
819 1015 grid.search(self.searchtext, row, col+1)
820 1016 else:
821 1017 grid.search(self.searchtext, row+1, 0)
1018 elif self.searchexpression != "":
1019 self.SetStatusText('Search mode: expression; looking for %s' % repr(self.searchexpression)[2:-1])
1020 grid.searchexpression(searchexp=self.searchexpression)
822 1021 else:
823 self.enter_searchtext(event)
1022 self.SetStatusText("No search yet: please enter search-text or -expression")
824 1023
825 1024 def display_help(self, event):
826 1025 """
@@ -842,7 +1041,13 b' class IGridFrame(wx.Frame):'
842 1041 webbrowser.open(filename, new=1, autoraise=True)
843 1042
844 1043 def enter_searchexpression(self, event):
845 pass
1044 dlg = wx.TextEntryDialog(self, "Find:", "Find matching expression:", defaultValue=self.searchexpression)
1045 if dlg.ShowModal() == wx.ID_OK:
1046 self.searchexpression = dlg.GetValue()
1047 self.searchtext = ""
1048 self.SetStatusText('Search mode: expression; looking for %s' % repr(self.searchexpression)[2:-1])
1049 self.notebook.GetPage(self.notebook.GetSelection()).grid.searchexpression(self.searchexpression)
1050 dlg.Destroy()
846 1051
847 1052 def makemenu(self, menu, label, help, cmd):
848 1053 menu.Append(self.menucounter, label, help)
@@ -864,10 +1069,12 b' class IGridFrame(wx.Frame):'
864 1069
865 1070 def enter_searchtext(self, event):
866 1071 # Displays a dialog asking for the searchtext
867 dlg = wx.TextEntryDialog(self, "Find:", "Find in list")
1072 dlg = wx.TextEntryDialog(self, "Find:", "Find in list", defaultValue=self.searchtext)
868 1073 if dlg.ShowModal() == wx.ID_OK:
869 1074 self.searchtext = dlg.GetValue()
870 self.notebook.GetPage(self.notebook.GetSelection()).grid.search(self.searchtext, 0, 0)
1075 self.searchexpression = ""
1076 self.SetStatusText('Search mode: text; looking for %s' % self.searchtext)
1077 self.notebook.GetPage(self.notebook.GetSelection()).grid.search(self.searchtext)
871 1078 dlg.Destroy()
872 1079
873 1080
General Comments 0
You need to be logged in to leave comments. Login now