root/branch/ggpolo/umitInventory/ChangesList.py @ 1005

Revision 1005, 8.7 kB (checked in by ggpolo, 6 years ago)

Completed first version for event storing in database, added ballons with values for boundary points in Interactive Timeline Graph

Line 
1# Copyright (C) 2007 Insecure.Com LLC.
2#
3# Authors: Guilherme Polo <ggpolo@gmail.com>
4#
5# This program is free software; you can redistribute it and/or modify
6# it under the terms of the GNU General Public License as published by
7# the Free Software Foundation; either version 2 of the License, or
8# (at your option) any later version.
9#
10# This program is distributed in the hope that it will be useful,
11# but WITHOUT ANY WARRANTY; without even the implied warranty of
12# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13# GNU General Public License for more details.
14#
15# You should have received a copy of the GNU General Public License
16# along with this program; if not, write to the Free Software
17# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
18# USA
19
20import gtk
21import time
22import cairo
23import pango
24import gobject
25
26from umitCore.I18N import _
27from umitCore.Paths import Path
28
29from umitDB.Retrieve import InventoryRetrieve
30
31from umitInventory.TL.Calendar import months
32from umitInventory.TL.Calendar import weekdays
33
34umitdb = Path.umitdb_ng
35
36class ChangesList(gtk.VBox):
37    def __init__(self, inv_name, host_addr, display):
38        """
39        Expects a valid Inventory name and a valid host address for this
40        Inventory and buils a List showing short change descriptions over time.
41        """
42        gtk.VBox.__init__(self)
43
44        self.inventory = inv_name
45        self.hostaddr = host_addr
46        self.display = display
47        self.row_data = { }
48        self.viewing_rows = { }
49        self.invdb = InventoryRetrieve(umitdb)
50        self.model = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_STRING,
51                                   gobject.TYPE_STRING)
52        self.modelfilter = self.model.filter_new()
53        self.tview = gtk.TreeView()
54
55        self._create_columns()
56        self._load_data(self.inventory, self.hostaddr)
57        self.tview.get_selection().connect('changed', self.row_changed)
58
59        self.show_states = self.states[:]
60        self.index_states = [self.show_states.index(i) for i in self.show_states]
61       
62        self.modelfilter.set_visible_func(self.visible_tv, self.show_states)
63        self.tview.set_model(self.modelfilter)
64
65        self.btns_box = self._setup_top_btns()
66        self._setup_columns()
67        self.__layout()
68
69
70    def visible_tv(self, model, iter, data):
71        """
72        Set "visible" items on list.
73        """
74        return model.get_value(iter, 0) in data
75
76
77    def check_buttons(self, tb):
78        """
79        Do filter based on active bottom buttons.
80        """
81        self.index_states = [ ]
82        del self.show_states[:]
83   
84        btns_children = self.btns_box.get_children()
85        for indx, b in enumerate(btns_children[1:len(btns_children)-1]):
86            if b.get_active():
87                self.index_states.append(indx)
88                self.show_states.append(b.get_label())
89   
90        self.modelfilter.refilter()
91        self.viewing_rows = self.filter_rows(self.row_data, self.index_states)
92        self.update_viewing_lbl()
93
94   
95    def filter_rows(self, full, states):
96        """
97        Filter full data to show only partial data based on states.
98        """
99        count = 0
100        partial = { }
101        for key, value in full.items():
102            if value[3] in states:
103                vnew = list(value)
104                vnew[2] = count
105                partial[count] = tuple(vnew)
106               
107                count += 1
108       
109        return partial
110       
111   
112    def row_changed(self, tview):
113        """
114        Load data for selected row.
115        """
116        cdata = self.viewing_rows
117       
118        try:
119            row = tview.get_selected_rows()[1][0][0]
120        except IndexError: # list not filled with data yet
121            return
122
123
124        if cdata[row][0] == -1: # host down
125            self.display.header_empty(self.hostaddr, self.inventory, 
126                                      self.model[row][2])
127            self.display.show_empty_hostid()
128            return
129       
130        if cdata[row][0] == cdata[row][1]:
131            # display complete text for first scan result for this host
132            diff = False
133            self.display.header_newhost(self.hostaddr, self.inventory,
134                                        self.model[row][2])
135        else:
136            diff = True
137            self.display.header_comparison(self.hostaddr, self.inventory,
138                                           self.model[row][2])
139   
140        if self.display:
141            self.display.make_diff(cdata[row][0], cdata[row][1])
142
143
144    def __layout(self):
145        """
146        Layout widgets.
147        """
148        sw = gtk.ScrolledWindow()
149        sw.add(self.tview)
150        sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
151        sw.set_size_request(-1, 220)
152        self.pack_start(self.btns_box, False, False, 0)
153        self.pack_start(sw, True, True, 6)
154        #self.set_border_width(6)
155        self.show_all()
156
157
158    def _create_columns(self):
159        """
160        Create TreeView columns.
161        """
162        self.tview.columns = [None]*3
163        self.tview.columns[0] = gtk.TreeViewColumn(_("Affected"))
164        self.tview.columns[1] = gtk.TreeViewColumn(_("Short description of \
165changes"))
166        self.tview.columns[1].set_min_width(400)
167        self.tview.columns[2] = gtk.TreeViewColumn(_("Date"))
168
169
170    def _setup_columns(self):
171        """
172        Set TreeView properties and etc.
173        """
174        for n in range(3):
175            self.tview.append_column(self.tview.columns[n])
176            self.tview.columns[n].cell = gtk.CellRendererText()
177            self.tview.columns[n].pack_start(self.tview.columns[n].cell, True)
178            self.tview.columns[n].set_attributes(self.tview.columns[n].cell,
179                                                 text=n)
180            if n == 1:
181                self.tview.columns[n].cell.set_property('ellipsize',
182                                                        pango.ELLIPSIZE_END)
183                         
184        self.tview.set_search_column(1)
185
186
187    def _setup_top_btns(self):
188        """
189        Create and connect top buttons.
190        """
191        box = gtk.HBox()
192        box.pack_start(gtk.Label(_("Viewing Categories  ")), False, False, 0)
193        for state in self.states:
194            b = gtk.ToggleButton(state)
195            b.set_active(True)
196            b.connect('toggled', self.check_buttons)
197            box.pack_start(b, False, False, 0)
198
199        # need to change this dinamically!
200        self.viewing_lbl = gtk.Label()
201        self.update_viewing_lbl()
202        box.pack_end(self.viewing_lbl, False, False, 0)
203        return box
204
205
206    def update_viewing_lbl(self):
207        """
208        Update viewing_lbl based on viewing_rows.
209        """
210        if len(self.viewing_rows):
211            self.viewing_lbl.set_label(_("Viewing 1-%d of %d") % (len(self.viewing_rows),
212                                                                  len(self.viewing_rows)))
213        else:
214            self.viewing_lbl.set_label(_("Nothing to view"))
215
216
217    def format_date(self, date):
218        """
219        Format date to be displayed in Date column.
220        """
221        try:
222            date.hour
223        except AttributeError, e:
224            print "Report this as a BUG!, sqlite didn't return column with \
225timestamp format"
226            print date, type(date)
227            return date
228
229        return "%02d:%02d:%02d, %02d %s %s" % (date.hour, date.minute,
230                                               date.second, date.day,
231                                               months[date.month-1][:3],
232                                               date.year)
233   
234
235    def _load_data(self, inventory, host_addr):
236        """
237        Load data for especified inventory and host address.
238        """
239        fk_inventory = self.invdb.get_inventory_id_for_name(inventory)
240        fk_address = self.invdb.get_address_id_for_address_from_db(host_addr)
241       
242        changes = self.invdb.get_inventory_changes(fk_inventory, fk_address)
243       
244        # list of states
245        self.states = [ ]
246       
247        for indx, change in enumerate(changes):
248            entry_date = change[2]
249            affected = change[3]
250            text = change[4]
251       
252            self.model.append([affected, text, self.format_date(entry_date)])
253            if not affected in self.states:
254                self.states.append(affected)
255           
256            self.row_data[indx] = (change[1], change[0], indx,
257                                   self.states.index(affected))
258                       
259        self.viewing_rows = self.row_data.copy()
260       
261
262if __name__ == "__main__":
263    # demo
264    w = gtk.Window()
265    w.add(ChangesList("status fixing", "192.168.254.1", None))
266    w.show_all()
267    w.connect('delete-event', lambda *args:gtk.main_quit())
268    gtk.main()
269
Note: See TracBrowser for help on using the browser.