Initial import to Tizen
[profile/ivi/python-twisted.git] / twisted / manhole / gladereactor.py
1 # Copyright (c) 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, interface)
44
45     def connectSSL(self, host, port, factory, contextFactory, timeout=30, bindAddress=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