root/branch/PacketManipulator/PM/Gui/Pages/PacketPage.py @ 3619

Revision 3619, 8.8 kB (checked in by nopper, 5 years ago)

implemented a reset layer

Line 
1#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3# Copyright (C) 2008 Adriano Monteiro Marques
4#
5# Author: Francesco Piccinno <stack.box@gmail.com>
6#
7# This program is free software; you can redistribute it and/or modify
8# it under the terms of the GNU General Public License as published by
9# the Free Software Foundation; either version 2 of the License, or
10# (at your option) any later version.
11#
12# This program is distributed in the hope that it will be useful,
13# but WITHOUT ANY WARRANTY; without even the implied warranty of
14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15# GNU General Public License for more details.
16#
17# You should have received a copy of the GNU General Public License
18# along with this program; if not, write to the Free Software
19# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20
21"""
22A perspective to show and edit packets
23"""
24
25import gtk
26
27from PM import Backend
28from PM.Core.I18N import _
29from PM.Manager.PreferenceManager import Prefs
30
31from PM.Gui.Core.App import PMApp
32from PM.Gui.Core.Icons import get_pixbuf
33from PM.Gui.Widgets.HexView import HexView
34from PM.Gui.Widgets.Plotter import Plotter
35from PM.Gui.Tabs.OperationsTab import SendOperation, SendReceiveOperation
36
37class ProtocolHierarchy(gtk.ScrolledWindow):
38    def __init__(self, parent):
39        gtk.ScrolledWindow.__init__(self)
40
41        self.__create_widgets()
42        self.__pack_widgets()
43        self.__connect_signals()
44
45        self.session = parent
46        self.proto_icon = get_pixbuf('protocol_small')
47
48        self.reload()
49
50    def reload(self):
51        self.store.clear()
52
53        if not self.session.packet:
54            return
55
56        root = None
57
58        # We pray to be ordered :(
59        for proto in Backend.get_packet_protos(self.session.packet):
60            root = self.store.append(root, [self.proto_icon, Backend.get_proto_name(proto), proto])
61
62        self.tree.expand_all()
63        self.tree.get_selection().select_path((0, ))
64
65    def __create_widgets(self):
66        # Icon / string (like TCP packet with some info?) / hidden
67        self.store = gtk.TreeStore(gtk.gdk.Pixbuf, str, object)
68        self.tree = gtk.TreeView(self.store)
69
70        pix = gtk.CellRendererPixbuf()
71        txt = gtk.CellRendererText()
72
73        col = gtk.TreeViewColumn(_('Protocol'))
74
75        col.pack_start(pix, False)
76        col.pack_start(txt, True)
77
78        col.set_attributes(pix, pixbuf=0)
79        col.set_attributes(txt, text=1)
80
81        self.tree.append_column(col)
82
83        self.tree.set_grid_lines(gtk.TREE_VIEW_GRID_LINES_BOTH)
84        self.tree.set_rules_hint(True)
85
86    def __pack_widgets(self):
87        self.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
88        self.set_shadow_type(gtk.SHADOW_ETCHED_IN)
89
90        self.add(self.tree)
91
92    def __connect_signals(self):
93        self.tree.enable_model_drag_dest([('text/plain', 0, 0)], gtk.gdk.ACTION_COPY)
94        self.tree.connect('drag-data-received', self.__on_drag_data)
95
96    def __on_drag_data(self, widget, ctx, x, y, data, info, time):
97        if not self.session.packet:
98            ctx.finish(False, False, time)
99
100        if data and data.format == 8:
101            ret = self.tree.get_dest_row_at_pos(x, y)
102
103            try:
104                # Try to construct an empty packet
105                packet = Backend.get_proto(data.data)()
106                packet = Backend.MetaPacket(packet)
107            except Exception:
108                ctx.finish(False, False, time)
109                return
110
111            # We append as default
112            where = -1
113
114            if ret:
115                path, pos = ret
116                where = len(path) # because it's a treeview with only one child for row
117
118                if pos == gtk.TREE_VIEW_DROP_BEFORE or \
119                   pos == gtk.TREE_VIEW_DROP_INTO_OR_BEFORE:
120                    where -= 1
121           
122            # Now try to insert this stuff into the packet
123
124            if self.session.packet.insert(packet, where):
125                ctx.finish(True, False, time)
126
127                self.session.reload_container(self.session.packet)
128                self.session.reload_editor()
129
130            else:
131                ctx.finish(False, False, time)
132
133        else:
134            ctx.finish(False, False, time)
135
136    def get_active_protocol(self):
137        """
138        Return the selected protocol or the most
139        important protocol if no selection.
140
141        @return a tuple Packet, Protocol or None, None
142        """
143
144        model, iter = self.tree.get_selection().get_selected()
145
146        if not iter:
147            return None, None
148
149        obj = model.get_value(iter, 2)
150       
151        assert (Backend.is_proto(obj), "Should be a Protocol instance.")
152
153        return self.session.packet, obj
154
155
156class PacketPage(gtk.VBox):
157    def __init__(self, parent):
158        super(PacketPage, self).__init__(False, 4)
159
160        self.session = parent
161
162        # Create the toolbar for sending selected packet
163        self.toolbar = gtk.Toolbar()
164        self.toolbar.set_style(gtk.TOOLBAR_ICONS)
165
166        stocks = (
167            gtk.STOCK_EDIT,
168            gtk.STOCK_DELETE,
169            gtk.STOCK_CLEAR,
170            gtk.STOCK_SELECT_COLOR
171        )
172
173        tooltips = (
174            _('Complete layers'),
175            _('Remove selected layer'),
176            _('Reset layer to default'),
177            _('Graph packet')
178        )
179
180        callbacks = (
181            self.__on_complete,
182            self.__on_remove,
183            self.__on_reset,
184            self.__on_graph
185        )
186
187        for tooltip, stock, callback in zip(tooltips, stocks, callbacks):
188            action = gtk.Action(None, None, tooltip, stock)
189            action.connect('activate', callback)
190            self.toolbar.insert(action.create_tool_item(), -1)
191
192        self.pack_start(self.toolbar, False, False)
193
194        self.proto_hierarchy = ProtocolHierarchy(self.session)
195        self.hexview = HexView()
196
197        vpaned = gtk.VPaned()
198        vpaned.pack1(self.proto_hierarchy, True, False)
199        vpaned.pack2(self.hexview, True, False)
200       
201        self.pack_start(vpaned)
202
203        Prefs()['gui.maintab.hexview.font'].connect(self.hexview.modify_font)
204        Prefs()['gui.maintab.hexview.bpl'].connect(self.hexview.set_bpl)
205
206    def redraw_hexview(self):
207        """
208        Redraws the hexview
209        """
210        if self.session.packet:
211            self.hexview.payload = Backend.get_packet_raw(self.session.packet)
212        else:
213            self.hexview.payload = ""
214
215    def reload(self):
216        # Hide the toolbar while merging fields
217
218        # FIXME: cyclic
219        #if isinstance(self.session, SequenceSession) and \
220        if getattr(self.session, 'sequence_page', None) and \
221           self.session.sequence_page.merging:
222            self.toolbar.hide()
223            self.proto_hierarchy.hide()
224        else:
225            self.toolbar.show()
226            self.proto_hierarchy.show()
227
228        self.redraw_hexview()
229        self.proto_hierarchy.reload()
230
231    def __on_remove(self, action):
232        packet, protocol = self.proto_hierarchy.get_active_protocol()
233
234        if not packet:
235            return
236
237        if packet.remove(protocol):
238            self.session.reload_container(packet)
239            self.reload()
240
241    def __on_reset(self, action):
242        packet, protocol = self.proto_hierarchy.get_active_protocol()
243
244        if not packet:
245            return
246
247        if packet.reset(protocol):
248            self.session.reload_container(packet)
249            self.reload()
250
251    def __on_complete(self, action):
252        packet, protocol = self.proto_hierarchy.get_active_protocol()
253
254        if not packet:
255            return
256
257        if packet.complete():
258            self.session.reload_container(packet)
259            self.reload()
260
261    def __on_graph(self, action):
262        if not self.session.packet:
263            return
264
265        dialog = gtk.Dialog(
266                _('Graph for %s') % self.session.packet.get_protocol_str(),
267                self.get_toplevel(), 0, (gtk.STOCK_CLOSE, gtk.RESPONSE_REJECT,
268                                         gtk.STOCK_SAVE, gtk.RESPONSE_ACCEPT))
269
270        dialog.plotter = Plotter(self.session.packet)
271        dialog.vbox.pack_start(dialog.plotter)
272        dialog.set_size_request(900, 600)
273        dialog.show_all()
274
275        dialog.connect('response', self.__on_graph_response)
276
277    def __on_graph_response(self, dialog, id):
278        if id == gtk.RESPONSE_REJECT:
279            dialog.hide()
280            dialog.destroy()
281        elif id == gtk.RESPONSE_ACCEPT:
282            chooser = gtk.FileChooserDialog(_('Save graph to'), dialog,
283                         gtk.FILE_CHOOSER_ACTION_SAVE,
284                         (gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT,
285                          gtk.STOCK_SAVE, gtk.RESPONSE_ACCEPT))
286 
287            if chooser.run() == gtk.RESPONSE_ACCEPT:
288                fname = chooser.get_filename()
289                dialog.plotter.export_to(fname)
290 
291            chooser.hide()
292            chooser.destroy()
Note: See TracBrowser for help on using the browser.