root/trunk/umit/gui/radialnet/NodeNotebook.py @ 4938

Revision 4938, 26.3 kB (checked in by ignotus, 4 years ago)

Merged revisions 4734,4928-4929,4936 via svnmerge from
http://svn.umitproject.org/svnroot/umit/branch/radialnet

........

r4734 | ignotus | 2009-05-01 21:51:19 -0300 (Fri, 01 May 2009) | 3 lines


Applied the patch named `ticket_316.5.diff' from ticket #316.

........

r4928 | ignotus | 2009-06-26 00:28:54 -0300 (Fri, 26 Jun 2009) | 3 lines


Added SaveDialog?.py file to SVN (I forgot it).

........

r4929 | ignotus | 2009-06-26 00:40:23 -0300 (Fri, 26 Jun 2009) | 3 lines


Allow user to hide ScanHostsView? left panel.

........

r4936 | ignotus | 2009-06-28 00:09:45 -0300 (Sun, 28 Jun 2009) | 3 lines


Fix accents in header.

........

Line 
1# vim: set encoding=utf-8 :
2
3# Copyright (C) 2007 Adriano Monteiro Marques
4#
5# Author: João Paulo de Souza Medeiros <ignotus21@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
21import gtk
22import pango
23import gobject
24
25#import bestwidgets as bw
26
27from higwidgets.higboxes import HIGBox, HIGHBox, HIGVBox, HIGScrolledWindow
28from higwidgets.higexpanders import HIGExpanderRNet
29from higwidgets.higlabels import HIGLabel, HIGSectionLabel
30from higwidgets.higtables import HIGTableRNet
31from higwidgets.higtextviewers import HIGTextEditor
32
33PORTS_HEADER = ['Port', 'Protocol', 'State', 'Service', 'Method']
34EXTRAPORTS_HEADER = ['Count', 'State', 'Reasons']
35
36SERVICE_COLORS = {'open'            : '#ffd5d5',
37                  'closed'          : '#d5ffd5',
38                  'filtered'        : '#ffffd5',
39                  'unfiltered'      : '#ffd5d5',
40                  'open|filtered'   : '#ffd5d5',
41                  'closed|filtered' : '#d5ffd5'}
42
43TRACE_HEADER = ['TTL', 'RTT', 'IP', 'Hostname']
44
45TRACE_TEXT = """\
46Traceroute on port <b>%s/%s</b> totalized <b>%d</b> known hops.\
47"""
48
49NO_TRACE_TEXT = "No traceroute information available."
50
51HOP_COLOR = {'known'   : '#ffffff',
52             'unknown' : '#cccccc'}
53
54SYSTEM_ADDRESS_TEXT = "[%s] %s"
55
56OSMATCH_HEADER = ['%', 'Name', 'DB Line']
57OSCLASS_HEADER = ['%', 'Vendor', 'Type', 'Family', 'Version']
58
59USED_PORTS_TEXT = "%d/%s %s"
60
61TCP_SEQ_NOTE = """\
62<b>*</b> TCP sequence <i>index</i> equal to %d and <i>difficulty</i> is "%s".\
63"""
64
65
66
67class NodeNotebook(gtk.Notebook):
68    """
69    """
70    def __init__(self, node):
71        """
72        """
73        gtk.Notebook.__init__(self)
74        self.set_tab_pos(gtk.POS_TOP)
75
76        self.__node = node
77
78        self.__create_widgets()
79
80
81    def __create_widgets(self):
82        """
83        """
84        # create body elements
85        self.__services_page = ServicesPage(self.__node)
86        self.__system_page = SystemPage(self.__node)
87        self.__trace_page = TraceroutePage(self.__node)
88
89        # packing notebook elements
90        self.append_page(self.__system_page, HIGLabel('General'))
91        self.append_page(self.__services_page, HIGLabel('Services'))
92        self.append_page(self.__trace_page, HIGLabel('Traceroute'))
93
94
95
96class ServicesPage(gtk.Notebook):
97    """
98    """
99    def __init__(self, node):
100        """
101        """
102        gtk.Notebook.__init__(self)
103        self.set_border_width(6)
104        self.set_tab_pos(gtk.POS_TOP)
105
106        self.__node = node
107        self.__font = pango.FontDescription('Monospace')
108
109        self.__create_widgets()
110
111
112    def __create_widgets(self):
113        """
114        """
115        self.__cell = gtk.CellRendererText()
116
117        # texteditor widgets
118        self.__texteditor = HIGTextEditor()
119        self.__texteditor._modify_font(self.__font)
120        self.__texteditor._set_editable(False)
121        self.__texteditor.set_border_width(0)
122
123        self.__select_combobox = gtk.combo_box_new_text()
124        self.__select_combobox.connect('changed', self.__change_text_value)
125
126        self.__viewer = HIGVBox(spacing=6)
127        self.__viewer.set_border_width(6)
128
129        self.__viewer._pack_noexpand_nofill(self.__select_combobox)
130        self.__viewer._pack_expand_fill(self.__texteditor)
131
132        self.__text = list()
133
134        # ports information
135        number_of_ports = len(self.__node.get_info('ports'))
136        self.__ports_label = HIGLabel('Ports (%s)' % number_of_ports)
137
138        self.__ports_scroll = HIGScrolledWindow()
139
140        self.__ports_store = gtk.TreeStore(gobject.TYPE_INT,
141                                           gobject.TYPE_STRING,
142                                           gobject.TYPE_STRING,
143                                           gobject.TYPE_STRING,
144                                           gobject.TYPE_STRING,
145                                           gobject.TYPE_STRING,
146                                           gobject.TYPE_BOOLEAN)
147
148        self.__ports_treeview = gtk.TreeView(self.__ports_store)
149
150        for port in self.__node.get_info('ports'):
151            pstate = port['state']['state']
152            if pstate:
153                color = SERVICE_COLORS[port['state']['state']]
154            else:
155                # XXX port state is not always available
156                color = '#fff'
157
158            if port['service'].has_key('name'):
159                service_name = port['service']['name']
160
161            else:
162                service_name = '<unknown>'
163
164            if port['service'].has_key('method'):
165                service_method = port['service']['method']
166
167            else:
168                service_method = '<none>'
169
170            reference = self.__ports_store.append(None,
171                                                  [port['id'],
172                                                   port['protocol'],
173                                                   port['state']['state'],
174                                                   service_name,
175                                                   service_method,
176                                                   color,
177                                                   True])
178
179            for key in port['state']:
180                self.__ports_store.append(reference,
181                                          [port['id'],
182                                           'state',
183                                           key,
184                                           port['state'][key],
185                                           '',
186                                           'white',
187                                           True])
188
189            for key in port['service']:
190
191                if key in ['servicefp', 'extrainfo']:
192
193                    text = '[%d] service: %s' % (port['id'], key)
194
195                    self.__select_combobox.append_text(text)
196                    self.__text.append(port['service'][key])
197
198                    value = '<special field>'
199
200                else:
201                    value = port['service'][key]
202
203                self.__ports_store.append(reference,
204                                          [port['id'],
205                                           'service',
206                                           key,
207                                           value,
208                                           '',
209                                           'white',
210                                           True])
211
212            for script in port['scripts']:
213
214                text = '[%d] script: %s' % (port['id'], script['id'])
215
216                self.__select_combobox.append_text(text)
217                self.__text.append(script['output'])
218
219                self.__ports_store.append(reference,
220                                          [port['id'],
221                                           'script',
222                                           'id',
223                                           script['id'],
224                                           '<special field>',
225                                           'white',
226                                           True])
227
228        self.__ports_column = list()
229
230        for i in range(len(PORTS_HEADER)):
231
232            column = gtk.TreeViewColumn(PORTS_HEADER[i],
233                                        self.__cell,
234                                        text = i)
235
236            self.__ports_column.append(column)
237
238            self.__ports_column[i].set_reorderable(True)
239            self.__ports_column[i].set_resizable(True)
240            self.__ports_column[i].set_sort_column_id(i)
241            self.__ports_column[i].set_attributes(self.__cell,
242                                                  text = i,
243                                                  background = 5,
244                                                  editable = 6)
245
246            self.__ports_treeview.append_column(self.__ports_column[i])
247
248        self.__ports_scroll.add_with_viewport(self.__ports_treeview)
249
250        # extraports information
251        number_of_xports = 0
252
253        self.__xports_scroll = HIGScrolledWindow()
254
255        self.__xports_store = gtk.TreeStore(gobject.TYPE_INT,
256                                            gobject.TYPE_STRING,
257                                            gobject.TYPE_STRING,
258                                            gobject.TYPE_STRING,
259                                            gobject.TYPE_BOOLEAN)
260
261        self.__xports_treeview = gtk.TreeView(self.__xports_store)
262
263        for xports in self.__node.get_info('extraports'):
264
265            color = SERVICE_COLORS[xports['state']]
266            number_of_xports += xports['count']
267
268            reference = self.__xports_store.append(None,
269                                                   [xports['count'],
270                                                    xports['state'],
271                                                    ", ".join(xports['reason']),
272                                                    color,
273                                                    True])
274
275            for xreason in xports['all_reason']:
276                self.__xports_store.append(reference,
277                                           [xreason['count'],
278                                            xports['state'],
279                                            xreason['reason'],
280                                            'white',
281                                            True])
282
283        self.__xports_column = list()
284
285        for i in range(len(EXTRAPORTS_HEADER)):
286
287            column = gtk.TreeViewColumn(EXTRAPORTS_HEADER[i],
288                                        self.__cell,
289                                        text = i)
290
291            self.__xports_column.append(column)
292
293            self.__xports_column[i].set_reorderable(True)
294            self.__xports_column[i].set_resizable(True)
295            self.__xports_column[i].set_sort_column_id(i)
296            self.__xports_column[i].set_attributes(self.__cell,
297                                                   text = i,
298                                                   background = 3,
299                                                   editable = 4)
300
301            self.__xports_treeview.append_column(self.__xports_column[i])
302
303        xports_label_text = 'Extraports (%s)' % number_of_xports
304        self.__xports_label = HIGLabel(xports_label_text)
305
306        self.__xports_scroll.add_with_viewport(self.__xports_treeview)
307
308        self.append_page(self.__ports_scroll, self.__ports_label)
309        self.append_page(self.__xports_scroll, self.__xports_label)
310        self.append_page(self.__viewer, HIGLabel('Special fields'))
311
312        if len(self.__text) > 0:
313            self.__select_combobox.set_active(0)
314
315
316    def __change_text_value(self, widget):
317        """
318        """
319        id = self.__select_combobox.get_active()
320
321        self.__texteditor._set_text(self.__text[id])
322
323
324
325class SystemPage(HIGScrolledWindow):
326    """
327    """
328    def __init__(self, node):
329        """
330        """
331        HIGScrolledWindow.__init__(self)
332
333        self.__node = node
334        self.__font = pango.FontDescription('Monospace')
335
336        self.__create_widgets()
337
338
339    def __create_widgets(self):
340        """
341        """
342        self.__vbox = HIGVBox()
343        self.__vbox.set_border_width(6)
344
345        self.__cell = gtk.CellRendererText()
346
347        self.__general_frame = HIGExpanderRNet('General information')
348        self.__sequences_frame = HIGExpanderRNet('Sequences')
349        self.__os_frame = HIGExpanderRNet('Operating System')
350
351        self.__sequences_frame._add(gtk.Label('No sequence information.'))
352        self.__os_frame._add(gtk.Label('No OS information.'))
353
354        # general information widgets
355        self.__general = HIGTableRNet(3, 2)
356
357        self.__address_label = HIGSectionLabel('Address:')
358        self.__address_list = gtk.combo_box_entry_new_text()
359        self.__address_list.child.set_editable(False)
360
361        for address in self.__node.get_info('addresses'):
362
363            params = address['addrtype'], address['addr']
364            address_text = SYSTEM_ADDRESS_TEXT % params
365
366            if address.get('vendor', None):
367                address_text += " (%s)" % address['vendor']
368
369            self.__address_list.append_text(address_text)
370
371        self.__address_list.set_active(0)
372
373        self.__general._attach_next(self.__address_label,
374                                    yoptions=gtk.FILL,
375                                    xoptions=gtk.FILL)
376        self.__general._attach_next(self.__address_list, yoptions=gtk.FILL)
377
378        if self.__node.get_info('hostnames') is not None:
379
380            self.__hostname_label = HIGSectionLabel('Hostname:')
381            self.__hostname_list = gtk.combo_box_entry_new_text()
382            self.__hostname_list.child.set_editable(False)
383
384            for hostname in self.__node.get_info('hostnames'):
385
386                params = hostname['type'], hostname['name']
387                self.__hostname_list.append_text(SYSTEM_ADDRESS_TEXT % params)
388
389            self.__hostname_list.set_active(0)
390
391            self.__general._attach_next(self.__hostname_label,
392                                        yoptions=gtk.FILL,
393                                        xoptions=gtk.FILL)
394            self.__general._attach_next(self.__hostname_list,
395                                        yoptions=gtk.FILL)
396
397        if self.__node.get_info('uptime') is not None:
398
399            self.__uptime_label = HIGSectionLabel('Last boot:')
400
401            seconds = self.__node.get_info('uptime')['seconds']
402            lastboot = self.__node.get_info('uptime')['lastboot']
403
404            text = '%s (%s seconds).' % (lastboot, seconds)
405
406            self.__uptime_value = HIGLabel(text)
407            self.__uptime_value.set_selectable(True)
408            self.__uptime_value.set_line_wrap(False)
409
410            self.__general._attach_next(self.__uptime_label,
411                                        yoptions=gtk.FILL,
412                                        xoptions=gtk.FILL)
413            self.__general._attach_next(self.__uptime_value,
414                                        yoptions=gtk.FILL)
415
416        self.__general_frame._add(self.__general)
417        self.__general_frame.set_expanded(True)
418
419        # sequences information widgets
420        self.__sequences = HIGTableRNet(5, 3)
421
422        sequences = self.__node.get_info('sequences')
423
424        if len(sequences) > 0:
425
426            self.__sequences.attach(HIGSectionLabel('Class'), 1, 2, 0, 1)
427            self.__sequences.attach(HIGSectionLabel('Values'), 2, 3, 0, 1)
428
429            self.__sequences.attach(HIGSectionLabel('TCP *'), 0, 1, 1, 2)
430            self.__sequences.attach(HIGSectionLabel('IP ID'), 0, 1, 2, 3)
431            self.__sequences.attach(HIGSectionLabel('TCP Timestamp'),
432                                    0,
433                                    1,
434                                    3,
435                                    4)
436
437            # tcp sequence values
438            tcp = sequences['tcp']
439
440            tcp_class = HIGLabel(tcp.get('class', ''))
441            tcp_class.set_selectable(True)
442
443            self.__sequences.attach(tcp_class, 1, 2, 1, 2)
444
445            tcp_values = gtk.combo_box_entry_new_text()
446
447            for value in tcp['values']:
448                tcp_values.append_text(value)
449
450            tcp_values.set_active(0)
451
452            self.__sequences.attach(tcp_values, 2, 3, 1, 2)
453
454            tcp_note = HIGLabel()
455            tcp_note.set_selectable(True)
456            tcp_note.set_line_wrap(False)
457            tcp_note.set_alignment(1.0, 0.5)
458            if tcp['index']:
459                tcp_note.set_markup(
460                        TCP_SEQ_NOTE % (tcp['index'], tcp['difficulty']))
461
462            self.__sequences.attach(tcp_note, 0, 3, 4, 5)
463
464            # ip id sequence values
465            ip_id = sequences['ip_id']
466
467            ip_id_class = HIGLabel(ip_id['class'])
468            ip_id_class.set_selectable(True)
469
470            self.__sequences.attach(ip_id_class, 1, 2, 2, 3)
471
472            ip_id_values = gtk.combo_box_entry_new_text()
473
474            for value in ip_id['values']:
475                ip_id_values.append_text(value)
476
477            ip_id_values.set_active(0)
478
479            self.__sequences.attach(ip_id_values, 2, 3, 2, 3)
480
481            # tcp sequence values
482            tcp_ts = sequences['tcp_ts']
483
484            tcp_ts_class = HIGLabel(tcp_ts['class'])
485            tcp_ts_class.set_selectable(True)
486
487            self.__sequences.attach(tcp_ts_class, 1, 2, 3, 4)
488
489            if tcp_ts.get('values', None) is not None:
490
491                tcp_ts_values = gtk.combo_box_entry_new_text()
492
493                for value in tcp_ts['values']:
494                    tcp_ts_values.append_text(value)
495
496                tcp_ts_values.set_active(0)
497
498                self.__sequences.attach(tcp_ts_values, 2, 3, 3, 4)
499
500            self.__sequences_frame._add(self.__sequences)
501
502        # operating system information widgets
503        self.__os = gtk.Notebook()
504        # XXX Setting this custom positioning causes a hard gtk bug (verified
505        # on Windows 7 at least, likely to happen under Vista too. Used
506        # gtk 2.14.7 and gtk 2.12.9 both with pygtk 2.12.1).
507        #self.__os.set_tab_pos(gtk.POS_LEFT)
508
509        os = self.__node.get_info('os')
510
511        if os is not None:
512
513            if os.has_key('matches'):
514
515                self.__match_scroll = HIGScrolledWindow()
516
517                self.__match_store = gtk.ListStore(gobject.TYPE_INT,
518                                                   gobject.TYPE_STRING,
519                                                   gobject.TYPE_INT,
520                                                   gobject.TYPE_BOOLEAN)
521
522                self.__match_treeview = gtk.TreeView(self.__match_store)
523
524                for os_match in os['matches']:
525                    if 'accuracy' not in os_match:
526                        # this may happen with older .usr
527                        continue
528                    self.__match_store.append([os_match['accuracy'],
529                                               os_match['name'],
530                                               os_match['db_line'],
531                                               True])
532
533                self.__match_column = list()
534
535                for i in range(len(OSMATCH_HEADER)):
536
537                    column = gtk.TreeViewColumn(OSMATCH_HEADER[i],
538                                                self.__cell,
539                                                text = i)
540
541                    self.__match_column.append(column)
542
543                    self.__match_column[i].set_reorderable(True)
544                    self.__match_column[i].set_resizable(True)
545                    self.__match_column[i].set_attributes(self.__cell,
546                                                          text = i,
547                                                          editable = 3)
548
549                    self.__match_column[i].set_sort_column_id(i)
550                    self.__match_treeview.append_column(self.__match_column[i])
551
552                self.__match_scroll.add_with_viewport(self.__match_treeview)
553
554                self.__os.append_page(self.__match_scroll, HIGLabel('Match'))
555
556            if os.has_key('classes'):
557
558                self.__class_scroll = HIGScrolledWindow()
559
560                self.__class_store = gtk.ListStore(gobject.TYPE_INT,
561                                                   gobject.TYPE_STRING,
562                                                   gobject.TYPE_STRING,
563                                                   gobject.TYPE_STRING,
564                                                   gobject.TYPE_STRING,
565                                                   gobject.TYPE_BOOLEAN)
566
567                self.__class_treeview = gtk.TreeView(self.__class_store)
568
569                for os_class in os['classes']:
570
571                    os_gen = ''
572
573                    if os_class.has_key('os_gen'):
574                        os_gen = os_class['os_gen']
575
576                    self.__class_store.append([os_class['accuracy'],
577                                               os_class['vendor'],
578                                               os_class['type'],
579                                               os_class['os_family'],
580                                               os_gen,
581                                               True])
582
583                self.__class_column = list()
584
585                for i in range(len(OSCLASS_HEADER)):
586
587                    column = gtk.TreeViewColumn(OSCLASS_HEADER[i],
588                                                self.__cell,
589                                                text = i)
590
591                    self.__class_column.append(column)
592
593                    self.__class_column[i].set_reorderable(True)
594                    self.__class_column[i].set_resizable(True)
595                    self.__class_column[i].set_attributes(self.__cell,
596                                                          text = i,
597                                                          editable = 5)
598
599                    self.__class_column[i].set_sort_column_id(i)
600                    self.__class_treeview.append_column(self.__class_column[i])
601
602                self.__class_scroll.add_with_viewport(self.__class_treeview)
603
604                self.__os.append_page(self.__class_scroll, HIGLabel('Class'))
605
606            self.__fp_viewer = HIGTextEditor()
607            self.__fp_viewer._modify_font(self.__font)
608            self.__fp_viewer._set_editable(False)
609            self.__fp_viewer._set_text(os['fingerprint'])
610
611            self.__fp_ports = HIGHBox()
612            self.__fp_label = HIGSectionLabel('Used ports:')
613
614            self.__fp_ports_list = gtk.combo_box_entry_new_text()
615            self.__fp_ports_list.child.set_editable(False)
616
617            self.__fp_vbox = HIGVBox()
618
619            if os.has_key('used_ports'):
620
621                used_ports = os['used_ports']
622
623                for port in used_ports:
624
625                    params = port['id'], port['protocol'], port['state']
626                    self.__fp_ports_list.append_text(USED_PORTS_TEXT % params)
627
628                self.__fp_ports_list.set_active(0)
629
630                self.__fp_ports._pack_noexpand_nofill(self.__fp_label)
631                self.__fp_ports._pack_expand_fill(self.__fp_ports_list)
632
633                self.__fp_vbox._pack_noexpand_nofill(self.__fp_ports)
634
635            self.__os.append_page(self.__fp_viewer, HIGLabel('Fingerprint'))
636            self.__fp_vbox._pack_expand_fill(self.__os)
637
638            self.__os_frame._add(self.__fp_vbox)
639            self.__os_frame.set_expanded(True)
640
641        self.__vbox._pack_noexpand_nofill(self.__general_frame)
642        self.__vbox._pack_expand_fill(self.__os_frame)
643        self.__vbox._pack_noexpand_nofill(self.__sequences_frame)
644
645        self.add_with_viewport(self.__vbox)
646
647
648
649class TraceroutePage(HIGVBox):
650    """
651    """
652    def __init__(self, node):
653        """
654        """
655        HIGVBox.__init__(self)
656        self.set_border_width(6)
657
658        self.__node = node
659
660        self.__create_widgets()
661
662
663    def __create_widgets(self):
664        """
665        """
666        if self.__node.get_info('trace') is None:
667
668            self.__trace_label = gtk.Label(NO_TRACE_TEXT)
669            self.pack_start(self.__trace_label, True, True)
670
671        else:
672
673            # add hops
674            hops = self.__node.get_info('trace')['hops']
675            ttls = [int(i['ttl']) for i in hops]
676
677            self.__cell = gtk.CellRendererText()
678
679            self.__trace_scroll = HIGScrolledWindow()
680            self.__trace_scroll.set_border_width(0)
681
682            self.__trace_store = gtk.ListStore(gobject.TYPE_INT,
683                                               gobject.TYPE_STRING,
684                                               gobject.TYPE_STRING,
685                                               gobject.TYPE_STRING,
686                                               gobject.TYPE_STRING,
687                                               gobject.TYPE_BOOLEAN)
688
689            self.__trace_treeview = gtk.TreeView(self.__trace_store)
690
691            count = 0
692
693            for i in range(1, max(ttls) + 1):
694
695                if i in ttls:
696
697                    hop = hops[count]
698                    count += 1
699
700                    self.__trace_store.append([hop['ttl'],
701                                               hop['rtt'],
702                                               hop['ip'],
703                                               hop['hostname'],
704                                               HOP_COLOR['known'],
705                                               True])
706
707                else:
708                    self.__trace_store.append([i,
709                                               '',
710                                               '<unknown>',
711                                               '',
712                                               HOP_COLOR['unknown'],
713                                               True])
714
715
716            self.__trace_column = list()
717
718            for i in range(len(TRACE_HEADER)):
719
720                column = gtk.TreeViewColumn(TRACE_HEADER[i],
721                                            self.__cell,
722                                            text = i)
723
724                self.__trace_column.append(column)
725
726                self.__trace_column[i].set_reorderable(True)
727                self.__trace_column[i].set_resizable(True)
728                self.__trace_column[i].set_attributes(self.__cell,
729                                                      text = i,
730                                                      background = 4,
731                                                      editable = 5)
732
733                self.__trace_treeview.append_column(self.__trace_column[i])
734
735            self.__trace_column[0].set_sort_column_id(0)
736
737            self.__trace_scroll.add_with_viewport(self.__trace_treeview)
738
739            self.__trace_info = (self.__node.get_info('trace')['port'],
740                                 self.__node.get_info('trace')['protocol'],
741                                 len(self.__node.get_info('trace')['hops']))
742
743            self.__trace_label = HIGLabel(TRACE_TEXT % self.__trace_info)
744            self.__trace_label.set_use_markup(True)
745
746            self._pack_expand_fill(self.__trace_scroll)
747            self._pack_noexpand_nofill(self.__trace_label)
Note: See TracBrowser for help on using the browser.