| OLD | NEW |
| (Empty) |
| 1 # Copyright (c) 2001-2004 Twisted Matrix Laboratories. | |
| 2 # See LICENSE for details. | |
| 3 | |
| 4 | |
| 5 """ | |
| 6 A modified gtk2 reactor with a Glade dialog in-process that allows you to stop, | |
| 7 suspend, resume and inspect transports interactively. | |
| 8 """ | |
| 9 | |
| 10 __all__ = ['install'] | |
| 11 | |
| 12 # Twisted Imports | |
| 13 from twisted.python import log, threadable, runtime, failure, util, reflect | |
| 14 from twisted.internet.gtk2reactor import Gtk2Reactor as sup | |
| 15 | |
| 16 import gtk | |
| 17 import gobject | |
| 18 import gtk.glade | |
| 19 | |
| 20 COLUMN_DESCRIPTION = 0 | |
| 21 COLUMN_TRANSPORT = 1 | |
| 22 COLUMN_READING = 2 | |
| 23 COLUMN_WRITING = 3 | |
| 24 | |
| 25 | |
| 26 class GladeReactor(sup): | |
| 27 """GTK+-2 event loop reactor with GUI. | |
| 28 """ | |
| 29 | |
| 30 def listenTCP(self, port, factory, backlog=50, interface=''): | |
| 31 from _inspectro import LoggingFactory | |
| 32 factory = LoggingFactory(factory) | |
| 33 return sup.listenTCP(self, port, factory, backlog, interface) | |
| 34 | |
| 35 def connectTCP(self, host, port, factory, timeout=30, bindAddress=None): | |
| 36 from _inspectro import LoggingFactory | |
| 37 factory = LoggingFactory(factory) | |
| 38 return sup.connectTCP(self, host, port, factory, timeout, bindAddress) | |
| 39 | |
| 40 def listenSSL(self, port, factory, contextFactory, backlog=50, interface='')
: | |
| 41 from _inspectro import LoggingFactory | |
| 42 factory = LoggingFactory(factory) | |
| 43 return sup.listenSSL(self, port, factory, contextFactory, backlog, inter
face) | |
| 44 | |
| 45 def connectSSL(self, host, port, factory, contextFactory, timeout=30, bindAd
dress=None): | |
| 46 from _inspectro import LoggingFactory | |
| 47 factory = LoggingFactory(factory) | |
| 48 return sup.connectSSL(self, host, port, factory, contextFactory, timeout
, bindAddress) | |
| 49 | |
| 50 def connectUNIX(self, address, factory, timeout=30): | |
| 51 from _inspectro import LoggingFactory | |
| 52 factory = LoggingFactory(factory) | |
| 53 return sup.connectUNIX(self, address, factory, timeout) | |
| 54 | |
| 55 def listenUNIX(self, address, factory, backlog=50, mode=0666): | |
| 56 from _inspectro import LoggingFactory | |
| 57 factory = LoggingFactory(factory) | |
| 58 return sup.listenUNIX(self, address, factory, backlog, mode) | |
| 59 | |
| 60 def on_disconnect_clicked(self, w): | |
| 61 store, iter = self.servers.get_selection().get_selected() | |
| 62 store[iter][COLUMN_TRANSPORT].loseConnection() | |
| 63 | |
| 64 def on_viewlog_clicked(self, w): | |
| 65 store, iter = self.servers.get_selection().get_selected() | |
| 66 data = store[iter][1] | |
| 67 from _inspectro import LogViewer | |
| 68 if hasattr(data, "protocol") and not data.protocol.logViewer: | |
| 69 LogViewer(data.protocol) | |
| 70 | |
| 71 def on_inspect_clicked(self, w): | |
| 72 store, iter = self.servers.get_selection().get_selected() | |
| 73 data = store[iter] | |
| 74 from _inspectro import Inspectro | |
| 75 Inspectro(data[1]) | |
| 76 | |
| 77 def on_suspend_clicked(self, w): | |
| 78 store, iter = self.servers.get_selection().get_selected() | |
| 79 data = store[iter] | |
| 80 sup.removeReader(self, data[1]) | |
| 81 sup.removeWriter(self, data[1]) | |
| 82 if data[COLUMN_DESCRIPTION].endswith('(suspended)'): | |
| 83 if data[COLUMN_READING]: | |
| 84 sup.addReader(self, data[COLUMN_TRANSPORT]) | |
| 85 if data[COLUMN_WRITING]: | |
| 86 sup.addWriter(self, data[COLUMN_TRANSPORT]) | |
| 87 data[COLUMN_DESCRIPTION] = str(data[COLUMN_TRANSPORT]) | |
| 88 self.toggle_suspend(1) | |
| 89 else: | |
| 90 data[0] += ' (suspended)' | |
| 91 self.toggle_suspend(0) | |
| 92 | |
| 93 def toggle_suspend(self, suspending=0): | |
| 94 stock, nonstock = [('gtk-redo', 'Resume'), | |
| 95 ('gtk-undo', 'Suspend')][suspending] | |
| 96 b = self.xml.get_widget("suspend") | |
| 97 b.set_use_stock(1) | |
| 98 b.set_label(stock) | |
| 99 b.get_child().get_child().get_children()[1].set_label(nonstock) | |
| 100 | |
| 101 def servers_selection_changed(self, w): | |
| 102 store, iter = w.get_selected() | |
| 103 if iter is None: | |
| 104 self.xml.get_widget("suspend").set_sensitive(0) | |
| 105 self.xml.get_widget('disconnect').set_sensitive(0) | |
| 106 else: | |
| 107 data = store[iter] | |
| 108 self.toggle_suspend(not | |
| 109 data[COLUMN_DESCRIPTION].endswith('(suspended)')) | |
| 110 self.xml.get_widget("suspend").set_sensitive(1) | |
| 111 self.xml.get_widget('disconnect').set_sensitive(1) | |
| 112 | |
| 113 def on_quit_clicked(self, w): | |
| 114 self.stop() | |
| 115 | |
| 116 def __init__(self): | |
| 117 self.xml = gtk.glade.XML(util.sibpath(__file__,"gladereactor.glade")) | |
| 118 d = {} | |
| 119 for m in reflect.prefixedMethods(self, "on_"): | |
| 120 d[m.im_func.__name__] = m | |
| 121 self.xml.signal_autoconnect(d) | |
| 122 self.xml.get_widget('window1').connect('destroy', | |
| 123 lambda w: self.stop()) | |
| 124 self.servers = self.xml.get_widget("servertree") | |
| 125 sel = self.servers.get_selection() | |
| 126 sel.set_mode(gtk.SELECTION_SINGLE) | |
| 127 sel.connect("changed", | |
| 128 self.servers_selection_changed) | |
| 129 ## argh coredump: self.servers_selection_changed(sel) | |
| 130 self.xml.get_widget('suspend').set_sensitive(0) | |
| 131 self.xml.get_widget('disconnect').set_sensitive(0) | |
| 132 # setup model, connect it to my treeview | |
| 133 self.model = gtk.ListStore(str, object, gobject.TYPE_BOOLEAN, | |
| 134 gobject.TYPE_BOOLEAN) | |
| 135 self.servers.set_model(self.model) | |
| 136 self.servers.set_reorderable(1) | |
| 137 self.servers.set_headers_clickable(1) | |
| 138 # self.servers.set_headers_draggable(1) | |
| 139 # add a column | |
| 140 for col in [ | |
| 141 gtk.TreeViewColumn('Server', | |
| 142 gtk.CellRendererText(), | |
| 143 text=0), | |
| 144 gtk.TreeViewColumn('Reading', | |
| 145 gtk.CellRendererToggle(), | |
| 146 active=2), | |
| 147 gtk.TreeViewColumn('Writing', | |
| 148 gtk.CellRendererToggle(), | |
| 149 active=3)]: | |
| 150 | |
| 151 self.servers.append_column(col) | |
| 152 col.set_resizable(1) | |
| 153 sup.__init__(self) | |
| 154 | |
| 155 def addReader(self, reader): | |
| 156 sup.addReader(self, reader) | |
| 157 ## gtk docs suggest this - but it's stupid | |
| 158 ## self.model.set(self.model.append(), | |
| 159 ## 0, str(reader), | |
| 160 ## 1, reader) | |
| 161 self._maybeAddServer(reader, read=1) | |
| 162 | |
| 163 def _goAway(self,reader): | |
| 164 for p in range(len(self.model)): | |
| 165 if self.model[p][1] == reader: | |
| 166 self.model.remove(self.model.get_iter_from_string(str(p))) | |
| 167 return | |
| 168 | |
| 169 | |
| 170 def _maybeAddServer(self, reader, read=0, write=0): | |
| 171 p = 0 | |
| 172 for x in self.model: | |
| 173 if x[1] == reader: | |
| 174 if reader == 0: | |
| 175 reader += 1 | |
| 176 x[2] += read | |
| 177 x[3] += write | |
| 178 x[2] = max(x[2],0) | |
| 179 x[3] = max(x[3],0) | |
| 180 | |
| 181 if not (x[2] or x[3]): | |
| 182 x[0] = x[0] + '(disconnected)' | |
| 183 self.callLater(5, self._goAway, reader) | |
| 184 return | |
| 185 p += 1 | |
| 186 else: | |
| 187 read = max(read,0) | |
| 188 write = max(write, 0) | |
| 189 if read or write: | |
| 190 self.model.append((reader,reader,read,write)) | |
| 191 | |
| 192 def addWriter(self, writer): | |
| 193 sup.addWriter(self, writer) | |
| 194 self._maybeAddServer(writer, write=1) | |
| 195 | |
| 196 def removeReader(self, reader): | |
| 197 sup.removeReader(self, reader) | |
| 198 self._maybeAddServer(reader, read=-1) | |
| 199 | |
| 200 def removeWriter(self, writer): | |
| 201 sup.removeWriter(self, writer) | |
| 202 self._maybeAddServer(writer, write=-1) | |
| 203 | |
| 204 def crash(self): | |
| 205 gtk.main_quit() | |
| 206 | |
| 207 def run(self, installSignalHandlers=1): | |
| 208 self.startRunning(installSignalHandlers=installSignalHandlers) | |
| 209 self.simulate() | |
| 210 gtk.main() | |
| 211 | |
| 212 | |
| 213 def install(): | |
| 214 """Configure the twisted mainloop to be run inside the gtk mainloop. | |
| 215 """ | |
| 216 reactor = GladeReactor() | |
| 217 from twisted.internet.main import installReactor | |
| 218 installReactor(reactor) | |
| 219 return reactor | |
| OLD | NEW |