root/trunk/umit/inventory/TLChangesTree.py @ 4479

Revision 4479, 8.5 kB (checked in by getxsick, 4 years ago)

dict.keys() is no more needed for iterate. fix for #260

Line 
1# Copyright (C) 2007 Adriano Monteiro Marques
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 gobject
22
23from umit.core.I18N import _
24
25from umit.inventory.TLBase import categories
26
27ALLCHANGES = _("View all changes")
28LISTCHANGES = _("Changes listing")
29
30class TLChangesTree(gtk.HBox):
31    """
32    A treeview that holds Inventory Changes in a timerange by category.
33    """
34
35    def __init__(self, connector, datagrabber, db_categories, inventory,
36        hostaddr):
37
38        gtk.HBox.__init__(self)
39
40        self.connector = connector
41        self.datagrabber = datagrabber
42        self.db_categories = db_categories
43        self.inventory = inventory
44        self.hostaddr = hostaddr
45
46        self.treestore = gtk.TreeStore(str)
47        self.treeview = gtk.TreeView(self.treestore)
48        self.tcolumn = gtk.TreeViewColumn("%s (0)" % LISTCHANGES)
49        cell = gtk.CellRendererText()
50        self.tcolumn.pack_start(cell, True)
51        self.tcolumn.add_attribute(cell, 'text', 0)
52        self.treeview.append_column(self.tcolumn)
53
54        self.fulldata = None # all data for current selection
55
56        self.treeview.connect('row-activated', self._row_activated)
57        self.treeview.connect('button-press-event', self._row_clicked)
58        self.connector.connect('selection-update', self._update_tree)
59
60        self._append_categories()
61        self.__layout()
62
63
64    def _append_categories(self):
65        """
66        Append categories to treeview.
67        """
68        # startup situation
69        self.treestore.append(None, [ALLCHANGES])
70        for category in self.db_categories:
71            self.treestore.append(None, ["%s (0)" % categories[category]])
72
73
74    def _row_activated(self, tview, path, tvcolumn):
75        """
76        Some row in treeview was activated.
77        """
78        if path[len(path) - 1] == 0 and len(path) != 3:
79            # clicked on View all changes
80
81            if len(path) == 1:
82                # clicked on "main" View all changes
83                if self.fulldata is not None:
84                    full_load = self.fulldata
85
86                    self.emit('data-update', 'full', full_load)
87
88            elif len(path) == 2:
89                # clicked on "View all changes" inside a category
90                category_id = path[0]
91                category_load = { }
92                category_load[category_id] = self.fulldata[category_id]
93
94                self.emit('data-update', 'category', category_load)
95
96        elif len(path) == 3:
97            # clicked on some host inside inventory
98            category_id = path[0]
99            inventory = self.treestore[path[:2]][0].split('(')[0][:-1]
100            host_addr = self.treestore[path][0].split('(')[0][:-1]
101
102            especific_load = {category_id: (inventory, host_addr)}
103
104            self.emit('data-update', 'especific', especific_load)
105
106        else:
107            # clicked on some other row kind, just expand/collapse
108            if self.treeview.row_expanded(path):
109                self.treeview.collapse_row(path)
110            else:
111                self.treeview.expand_row(path, False)
112
113    def _row_clicked(self, tv, event):
114        """
115        Clicked on treeview, in a row or not.
116        """
117        if event.button == 1: # left click
118            x, y = int(event.x), int(event.y)
119
120            try:
121                path, col, xpos, ypos = tv.get_path_at_pos(x, y)
122            except TypeError:
123                return
124
125            if not path:
126                # didn't click in a row.
127                return
128
129            text_start = tv.get_cell_area(path, col)[0]
130
131            if path[len(path) - 1] != 0 and len(path) != 3:
132                if x >= text_start:
133                    # clicked on some other row kind, just expand/collapse
134                    if self.treeview.row_expanded(path):
135                        self.treeview.collapse_row(path)
136                    else:
137                        self.treeview.expand_row(path, False)
138            else:
139                self._row_activated(self.treeview, path, col)
140
141
142    def _update_tree(self, obj, range_start, range_end):
143        """
144        Grabs changes from range_start to range_end and then update tree.
145        """
146        db_categories = self.datagrabber.get_categories()
147        self.db_categories = [value[1] for key, value in db_categories.items()]
148
149        data = { }
150
151        # grab changes in timerange
152        self.datagrabber.use_dict_cursor()
153        for key in db_categories:
154            if not range_start or not range_end:
155                data[key] = { }
156                continue
157
158            chgs = self.datagrabber.timerange_changes_data_generic(range_start,
159                range_end, key, self.inventory, self.hostaddr)
160            data[key] = chgs
161        self.fulldata = data
162        self.datagrabber.use_standard_cursor()
163
164        clean_data = { }
165        inventories = { }
166        addresses = { }
167
168        for category, entries in data.items():
169            clean_data[category] = { }
170
171            if not entries:
172                # no changes for current category
173                continue
174
175            for entry in entries:
176                fk_address = entry["fk_address"]
177                fk_inventory = entry["fk_inventory"]
178
179                # grab host address
180                if not fk_address in addresses:
181                    adr = self.datagrabber.get_address_for_address_id_from_db(
182                          fk_address)
183
184                    addresses[fk_address] = adr
185
186                # grab inventory name
187                if not fk_inventory in inventories:
188                    inv_name = self.datagrabber.get_inventory_name_for_id(
189                               fk_inventory)
190
191                    inventories[fk_inventory] = inv_name
192
193                # update clean_data
194                if inventories[fk_inventory] in clean_data[category]:
195                    cdata = clean_data[category][inventories[fk_inventory]]
196
197                    if addresses[fk_address] in cdata:
198                        cdata[addresses[fk_address]] += 1
199                    else:
200                        cdata[addresses[fk_address]] = 1
201
202                    clean_data[category][inventories[fk_inventory]] = cdata
203
204                else:
205                    clean_data[category].update(
206                        {inventories[fk_inventory]:
207                            {addresses[fk_address]: 1}}
208                        )
209
210        # write new data into changestree
211        changes_sum = 0
212        self.treestore.clear()
213        self.treestore.append(None, [ALLCHANGES])
214
215        for indx, item in enumerate(self.db_categories):
216            data_length = len(data[indx + 1]) # keys starting at 1
217            changes_sum += data_length
218
219            root = self.treestore.append(None, ["%s (%d)" % (categories[item],
220                data_length)])
221
222            if data_length > 0:
223                self.treestore.append(root, [ALLCHANGES])
224
225            for inventory, entries in clean_data[indx + 1].items():
226
227                inv_root = self.treestore.append(root, ["%s (0)" % inventory])
228                #self.treestore.append(inv_root, [ALLCHANGES])
229
230                curr_changes_sum = 0
231                for address, changes in entries.items():
232                    self.treestore.append(inv_root, ["%s (%d)" % (address,
233                        changes)])
234                    curr_changes_sum += changes
235
236                # set number of changes in inventory title
237                self.treestore[inv_root][0] = "%s (%d)" % (inventory,
238                    curr_changes_sum)
239
240        self.tcolumn.set_title("%s (%d)" % (LISTCHANGES, changes_sum))
241
242
243    def __layout(self):
244        """
245        Layout treeview.
246        """
247        scrollw = gtk.ScrolledWindow()
248        scrollw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
249        scrollw.add_with_viewport(self.treeview)
250        scrollw.set_size_request(170, -1)
251
252        self.add(scrollw)
253
254
255gobject.signal_new("data-update", TLChangesTree, gobject.SIGNAL_RUN_LAST,
256    gobject.TYPE_NONE, (str, object))
Note: See TracBrowser for help on using the browser.