save model as private variable in disco.py. Fixes TB in #2426

This commit is contained in:
Yann Leboulanger 2006-09-22 08:49:25 +00:00
parent 15bfa2e095
commit b65745f732
1 changed files with 93 additions and 96 deletions

View File

@ -36,10 +36,10 @@
# - def update_actions(self) # - def update_actions(self)
# - def default_action(self) # - def default_action(self)
# - def _find_item(self, jid, node) # - def _find_item(self, jid, node)
# - def _add_item(self, model, jid, node, item, force) # - def _add_item(self, jid, node, item, force)
# - def _update_item(self, model, iter, jid, node, item) # - def _update_item(self, iter, jid, node, item)
# - def _update_info(self, model, iter, jid, node, identities, features, data) # - def _update_info(self, iter, jid, node, identities, features, data)
# - def _update_error(self, model, iter, jid, node) # - def _update_error(self, iter, jid, node)
# #
# * Should call the super class for this method. # * Should call the super class for this method.
# All others do not have to call back to the super class. (but can if they want # All others do not have to call back to the super class. (but can if they want
@ -422,6 +422,7 @@ _('Without a connection, you can not browse available services'))
self.xml = gtkgui_helpers.get_glade('service_discovery_window.glade') self.xml = gtkgui_helpers.get_glade('service_discovery_window.glade')
self.window = self.xml.get_widget('service_discovery_window') self.window = self.xml.get_widget('service_discovery_window')
self.services_treeview = self.xml.get_widget('services_treeview') self.services_treeview = self.xml.get_widget('services_treeview')
self.model = None
# This is more reliable than the cursor-changed signal. # This is more reliable than the cursor-changed signal.
selection = self.services_treeview.get_selection() selection = self.services_treeview.get_selection()
selection.connect_after('changed', selection.connect_after('changed',
@ -720,9 +721,9 @@ class AgentBrowser:
note that the first two columns should ALWAYS be of type string and note that the first two columns should ALWAYS be of type string and
contain the JID and node of the item respectively.''' contain the JID and node of the item respectively.'''
# JID, node, name, address # JID, node, name, address
model = gtk.ListStore(str, str, str, str) self.model = gtk.ListStore(str, str, str, str)
model.set_sort_column_id(3, gtk.SORT_ASCENDING) self.model.set_sort_column_id(3, gtk.SORT_ASCENDING)
self.window.services_treeview.set_model(model) self.window.services_treeview.set_model(self.model)
# Name column # Name column
col = gtk.TreeViewColumn(_('Name')) col = gtk.TreeViewColumn(_('Name'))
renderer = gtk.CellRendererText() renderer = gtk.CellRendererText()
@ -740,7 +741,7 @@ class AgentBrowser:
self.window.services_treeview.set_headers_visible(True) self.window.services_treeview.set_headers_visible(True)
def _clean_treemodel(self): def _clean_treemodel(self):
self.window.services_treeview.get_model().clear() self.model.clear()
for col in self.window.services_treeview.get_columns(): for col in self.window.services_treeview.get_columns():
self.window.services_treeview.remove_column(col) self.window.services_treeview.remove_column(col)
self.window.services_treeview.set_headers_visible(False) self.window.services_treeview.set_headers_visible(False)
@ -872,8 +873,7 @@ class AgentBrowser:
def browse(self, force = False): def browse(self, force = False):
'''Fill the treeview with agents, fetching the info if necessary.''' '''Fill the treeview with agents, fetching the info if necessary.'''
model = self.window.services_treeview.get_model() self.model.clear()
model.clear()
self._total_items = self._progress = 0 self._total_items = self._progress = 0
self.window.progressbar.show() self.window.progressbar.show()
self._pulse_timeout = gobject.timeout_add(250, self._pulse_timeout_cb) self._pulse_timeout = gobject.timeout_add(250, self._pulse_timeout_cb)
@ -890,22 +890,20 @@ class AgentBrowser:
def _find_item(self, jid, node): def _find_item(self, jid, node):
'''Check if an item is already in the treeview. Return an iter to it '''Check if an item is already in the treeview. Return an iter to it
if so, None otherwise.''' if so, None otherwise.'''
model = self.window.services_treeview.get_model() iter = self.model.get_iter_root()
iter = model.get_iter_root()
while iter: while iter:
cjid = model.get_value(iter, 0).decode('utf-8') cjid = self.model.get_value(iter, 0).decode('utf-8')
cnode = model.get_value(iter, 1).decode('utf-8') cnode = self.model.get_value(iter, 1).decode('utf-8')
if jid == cjid and node == cnode: if jid == cjid and node == cnode:
break break
iter = model.iter_next(iter) iter = self.model.iter_next(iter)
if iter: if iter:
return iter return iter
return None return None
def _agent_items(self, jid, node, items, force): def _agent_items(self, jid, node, items, force):
'''Callback for when we receive a list of agent items.''' '''Callback for when we receive a list of agent items.'''
model = self.window.services_treeview.get_model() self.model.clear()
model.clear()
self._total_items = 0 self._total_items = 0
gobject.source_remove(self._pulse_timeout) gobject.source_remove(self._pulse_timeout)
self.window.progressbar.hide() self.window.progressbar.hide()
@ -923,44 +921,43 @@ _('This service does not contain any items to browse.'))
jid = item['jid'] jid = item['jid']
node = item.get('node', '') node = item.get('node', '')
self._total_items += 1 self._total_items += 1
self._add_item(model, jid, node, item, force) self._add_item(jid, node, item, force)
self.window.services_treeview.set_model(model) self.window.services_treeview.set_model(self.model)
def _agent_info(self, jid, node, identities, features, data): def _agent_info(self, jid, node, identities, features, data):
'''Callback for when we receive info about an agent's item.''' '''Callback for when we receive info about an agent's item.'''
addr = get_agent_address(jid, node) addr = get_agent_address(jid, node)
model = self.window.services_treeview.get_model()
iter = self._find_item(jid, node) iter = self._find_item(jid, node)
if not iter: if not iter:
# Not in the treeview, stop # Not in the treeview, stop
return return
if identities == 0: if identities == 0:
# The server returned an error # The server returned an error
self._update_error(model, iter, jid, node) self._update_error(iter, jid, node)
else: else:
# We got our info # We got our info
self._update_info(model, iter, jid, node, self._update_info(iter, jid, node,
identities, features, data) identities, features, data)
self.update_actions() self.update_actions()
def _add_item(self, model, jid, node, item, force): def _add_item(self, jid, node, item, force):
'''Called when an item should be added to the model. The result of a '''Called when an item should be added to the model. The result of a
disco#items query.''' disco#items query.'''
model.append((jid, node, item.get('name', ''), self.model.append((jid, node, item.get('name', ''),
get_agent_address(jid, node))) get_agent_address(jid, node)))
def _update_item(self, model, iter, jid, node, item): def _update_item(self, iter, jid, node, item):
'''Called when an item should be updated in the model. The result of a '''Called when an item should be updated in the model. The result of a
disco#items query. (seldom)''' disco#items query. (seldom)'''
if item.has_key('name'): if item.has_key('name'):
model[iter][2] = item['name'] self.model[iter][2] = item['name']
def _update_info(self, model, iter, jid, node, identities, features, data): def _update_info(self, iter, jid, node, identities, features, data):
'''Called when an item should be updated in the model with further info. '''Called when an item should be updated in the model with further info.
The result of a disco#info query.''' The result of a disco#info query.'''
model[iter][2] = identities[0].get('name', '') self.model[iter][2] = identities[0].get('name', '')
def _update_error(self, model, iter, jid, node): def _update_error(self, iter, jid, node):
'''Called when a disco#info query failed for an item.''' '''Called when a disco#info query failed for an item.'''
pass pass
@ -1044,14 +1041,12 @@ class ToplevelAgentBrowser(AgentBrowser):
# These are all callbacks to make tooltips work # These are all callbacks to make tooltips work
def on_treeview_leave_notify_event(self, widget, event): def on_treeview_leave_notify_event(self, widget, event):
model = widget.get_model()
props = widget.get_path_at_pos(int(event.x), int(event.y)) props = widget.get_path_at_pos(int(event.x), int(event.y))
if self.tooltip.timeout > 0: if self.tooltip.timeout > 0:
if not props or self.tooltip.id == props[0]: if not props or self.tooltip.id == props[0]:
self.tooltip.hide_tooltip() self.tooltip.hide_tooltip()
def on_treeview_motion_notify_event(self, widget, event): def on_treeview_motion_notify_event(self, widget, event):
model = widget.get_model()
props = widget.get_path_at_pos(int(event.x), int(event.y)) props = widget.get_path_at_pos(int(event.x), int(event.y))
if self.tooltip.timeout > 0: if self.tooltip.timeout > 0:
if not props or self.tooltip.id != props[0]: if not props or self.tooltip.id != props[0]:
@ -1060,12 +1055,12 @@ class ToplevelAgentBrowser(AgentBrowser):
[row, col, x, y] = props [row, col, x, y] = props
iter = None iter = None
try: try:
iter = model.get_iter(row) iter = self.model.get_iter(row)
except: except:
self.tooltip.hide_tooltip() self.tooltip.hide_tooltip()
return return
jid = model[iter][0] jid = self.model[iter][0]
state = model[iter][4] state = self.model[iter][4]
# Not a category, and we have something to say about state # Not a category, and we have something to say about state
if jid and state > 0 and \ if jid and state > 0 and \
(self.tooltip.timeout == 0 or self.tooltip.id != props[0]): (self.tooltip.timeout == 0 or self.tooltip.id != props[0]):
@ -1082,10 +1077,10 @@ class ToplevelAgentBrowser(AgentBrowser):
# JID, node, icon, description, state # JID, node, icon, description, state
# State means 2 when error, 1 when fetching, 0 when succes. # State means 2 when error, 1 when fetching, 0 when succes.
view = self.window.services_treeview view = self.window.services_treeview
model = gtk.TreeStore(str, str, gtk.gdk.Pixbuf, str, int) self.model = gtk.TreeStore(str, str, gtk.gdk.Pixbuf, str, int)
model.set_sort_func(4, self._treemodel_sort_func) self.model.set_sort_func(4, self._treemodel_sort_func)
model.set_sort_column_id(4, gtk.SORT_ASCENDING) self.model.set_sort_column_id(4, gtk.SORT_ASCENDING)
view.set_model(model) view.set_model(self.model)
col = gtk.TreeViewColumn() col = gtk.TreeViewColumn()
# Icon Renderer # Icon Renderer
@ -1325,41 +1320,40 @@ class ToplevelAgentBrowser(AgentBrowser):
cat, prio = _cat_to_descr['other'] cat, prio = _cat_to_descr['other']
return cat, prio return cat, prio
def _create_category(self, model, cat, type=None): def _create_category(self, cat, type=None):
'''Creates a category row.''' '''Creates a category row.'''
cat, prio = self._friendly_category(cat, type) cat, prio = self._friendly_category(cat, type)
return model.append(None, ('', '', None, cat, prio)) return self.model.append(None, ('', '', None, cat, prio))
def _find_category(self, model, cat, type=None): def _find_category(self, cat, type=None):
'''Looks up a category row and returns the iterator to it, or None.''' '''Looks up a category row and returns the iterator to it, or None.'''
cat, prio = self._friendly_category(cat, type) cat, prio = self._friendly_category(cat, type)
iter = model.get_iter_root() iter = self.model.get_iter_root()
while iter: while iter:
if model.get_value(iter, 3).decode('utf-8') == cat: if self.model.get_value(iter, 3).decode('utf-8') == cat:
break break
iter = model.iter_next(iter) iter = self.model.iter_next(iter)
if iter: if iter:
return iter return iter
return None return None
def _find_item(self, jid, node): def _find_item(self, jid, node):
model = self.window.services_treeview.get_model()
iter = None iter = None
cat_iter = model.get_iter_root() cat_iter = self.model.get_iter_root()
while cat_iter and not iter: while cat_iter and not iter:
iter = model.iter_children(cat_iter) iter = self.model.iter_children(cat_iter)
while iter: while iter:
cjid = model.get_value(iter, 0).decode('utf-8') cjid = self.model.get_value(iter, 0).decode('utf-8')
cnode = model.get_value(iter, 1).decode('utf-8') cnode = self.model.get_value(iter, 1).decode('utf-8')
if jid == cjid and node == cnode: if jid == cjid and node == cnode:
break break
iter = model.iter_next(iter) iter = self.model.iter_next(iter)
cat_iter = model.iter_next(cat_iter) cat_iter = self.model.iter_next(cat_iter)
if iter: if iter:
return iter return iter
return None return None
def _add_item(self, model, jid, node, item, force): def _add_item(self, jid, node, item, force):
# Row text # Row text
addr = get_agent_address(jid, node) addr = get_agent_address(jid, node)
if item.has_key('name'): if item.has_key('name'):
@ -1380,24 +1374,24 @@ class ToplevelAgentBrowser(AgentBrowser):
# Set the pixmap for the row # Set the pixmap for the row
pix = self.cache.get_icon(identities) pix = self.cache.get_icon(identities)
# Put it in the right category # Put it in the right category
cat = self._find_category(model, *cat_args) cat = self._find_category(*cat_args)
if not cat: if not cat:
cat = self._create_category(model, *cat_args) cat = self._create_category(*cat_args)
model.append(cat, (item['jid'], item.get('node', ''), pix, descr, 1)) self.model.append(cat, (item['jid'], item.get('node', ''), pix, descr, 1))
self._expand_all() self._expand_all()
# Grab info on the service # Grab info on the service
self.cache.get_info(jid, node, self._agent_info, force = force) self.cache.get_info(jid, node, self._agent_info, force = force)
self._update_progressbar() self._update_progressbar()
def _update_item(self, model, iter, jid, node, item): def _update_item(self, iter, jid, node, item):
addr = get_agent_address(jid, node) addr = get_agent_address(jid, node)
if item.has_key('name'): if item.has_key('name'):
descr = "<b>%s</b>\n%s" % (item['name'], addr) descr = "<b>%s</b>\n%s" % (item['name'], addr)
else: else:
descr = "<b>%s</b>" % addr descr = "<b>%s</b>" % addr
model[iter][3] = descr self.model[iter][3] = descr
def _update_info(self, model, iter, jid, node, identities, features, data): def _update_info(self, iter, jid, node, identities, features, data):
addr = get_agent_address(jid, node) addr = get_agent_address(jid, node)
name = identities[0].get('name', '') name = identities[0].get('name', '')
if name: if name:
@ -1419,32 +1413,32 @@ class ToplevelAgentBrowser(AgentBrowser):
break break
# Check if we have to move categories # Check if we have to move categories
old_cat_iter = model.iter_parent(iter) old_cat_iter = self.model.iter_parent(iter)
old_cat = model.get_value(old_cat_iter, 3).decode('utf-8') old_cat = self.model.get_value(old_cat_iter, 3).decode('utf-8')
if model.get_value(old_cat_iter, 3) == cat: if self.model.get_value(old_cat_iter, 3) == cat:
# Already in the right category, just update # Already in the right category, just update
model[iter][2] = pix self.model[iter][2] = pix
model[iter][3] = descr self.model[iter][3] = descr
model[iter][4] = 0 self.model[iter][4] = 0
return return
# Not in the right category, move it. # Not in the right category, move it.
model.remove(iter) self.model.remove(iter)
# Check if the old category is empty # Check if the old category is empty
if not model.iter_is_valid(old_cat_iter): if not self.model.iter_is_valid(old_cat_iter):
old_cat_iter = self._find_category(model, old_cat) old_cat_iter = self._find_category(old_cat)
if not model.iter_children(old_cat_iter): if not self.model.iter_children(old_cat_iter):
model.remove(old_cat_iter) self.model.remove(old_cat_iter)
cat_iter = self._find_category(model, cat, type) cat_iter = self._find_category(cat, type)
if not cat_iter: if not cat_iter:
cat_iter = self._create_category(model, cat, type) cat_iter = self._create_category(cat, type)
model.append(cat_iter, (jid, node, pix, descr, 0)) self.model.append(cat_iter, (jid, node, pix, descr, 0))
self._expand_all() self._expand_all()
def _update_error(self, model, iter, jid, node): def _update_error(self, iter, jid, node):
addr = get_agent_address(jid, node) addr = get_agent_address(jid, node)
model[iter][4] = 2 self.model[iter][4] = 2
self._progress += 1 self._progress += 1
self._update_progressbar() self._update_progressbar()
@ -1454,13 +1448,18 @@ class MucBrowser(AgentBrowser):
AgentBrowser.__init__(self, *args, **kwargs) AgentBrowser.__init__(self, *args, **kwargs)
self.join_button = None self.join_button = None
def _agent_items(self, jid, node, items, force):
AgentBrowser._agent_items(self, jid, node, items, force)
print 'resize column'
# self.window.services_treeview.get
def _create_treemodel(self): def _create_treemodel(self):
# JID, node, name, users, description, fetched # JID, node, name, users, description, fetched
# This is rather long, I'd rather not use a data_func here though. # This is rather long, I'd rather not use a data_func here though.
# Users is a string, because want to be able to leave it empty. # Users is a string, because want to be able to leave it empty.
model = gtk.ListStore(str, str, str, str, str, bool) self.model = gtk.ListStore(str, str, str, str, str, bool)
model.set_sort_column_id(2, gtk.SORT_ASCENDING) self.model.set_sort_column_id(2, gtk.SORT_ASCENDING)
self.window.services_treeview.set_model(model) self.window.services_treeview.set_model(self.model)
# Name column # Name column
col = gtk.TreeViewColumn(_('Name')) col = gtk.TreeViewColumn(_('Name'))
renderer = gtk.CellRendererText() renderer = gtk.CellRendererText()
@ -1571,7 +1570,6 @@ class MucBrowser(AgentBrowser):
# Prevent a silly warning, try again in a bit. # Prevent a silly warning, try again in a bit.
self._fetch_source = gobject.timeout_add(100, self._start_info_query) self._fetch_source = gobject.timeout_add(100, self._start_info_query)
return return
model = view.get_model()
# We have to do this in a pygtk <2.8 compatible way :/ # We have to do this in a pygtk <2.8 compatible way :/
#start, end = self.window.services_treeview.get_visible_range() #start, end = self.window.services_treeview.get_visible_range()
rect = view.get_visible_rect() rect = view.get_visible_rect()
@ -1580,7 +1578,7 @@ class MucBrowser(AgentBrowser):
try: try:
sx, sy = view.tree_to_widget_coords(rect.x, rect.y) sx, sy = view.tree_to_widget_coords(rect.x, rect.y)
spath = view.get_path_at_pos(sx, sy)[0] spath = view.get_path_at_pos(sx, sy)[0]
iter = model.get_iter(spath) iter = self.model.get_iter(spath)
except TypeError: except TypeError:
self._fetch_source = None self._fetch_source = None
return return
@ -1594,14 +1592,14 @@ class MucBrowser(AgentBrowser):
except TypeError: except TypeError:
# We're at the end of the model, we can leave end=None though. # We're at the end of the model, we can leave end=None though.
pass pass
while iter and model.get_path(iter) != end: while iter and self.model.get_path(iter) != end:
if not model.get_value(iter, 5): if not self.model.get_value(iter, 5):
jid = model.get_value(iter, 0).decode('utf-8') jid = self.model.get_value(iter, 0).decode('utf-8')
node = model.get_value(iter, 1).decode('utf-8') node = self.model.get_value(iter, 1).decode('utf-8')
self.cache.get_info(jid, node, self._agent_info) self.cache.get_info(jid, node, self._agent_info)
self._fetch_source = True self._fetch_source = True
return return
iter = model.iter_next(iter) iter = self.model.iter_next(iter)
self._fetch_source = None self._fetch_source = None
def _channel_altinfo(self, jid, node, items, name = None): def _channel_altinfo(self, jid, node, items, name = None):
@ -1622,22 +1620,21 @@ class MucBrowser(AgentBrowser):
self._fetch_source = None self._fetch_source = None
return return
else: else:
model = self.window.services_treeview.get_model()
iter = self._find_item(jid, node) iter = self._find_item(jid, node)
if iter: if iter:
if name: if name:
model[iter][2] = name self.model[iter][2] = name
model[iter][3] = len(items) # The number of users self.model[iter][3] = len(items) # The number of users
model[iter][5] = True self.model[iter][5] = True
self._fetch_source = None self._fetch_source = None
self._query_visible() self._query_visible()
def _add_item(self, model, jid, node, item, force): def _add_item(self, jid, node, item, force):
model.append((jid, node, item.get('name', ''), '', '', False)) self.model.append((jid, node, item.get('name', ''), '', '', False))
if not self._fetch_source: if not self._fetch_source:
self._fetch_source = gobject.idle_add(self._start_info_query) self._fetch_source = gobject.idle_add(self._start_info_query)
def _update_info(self, model, iter, jid, node, identities, features, data): def _update_info(self, iter, jid, node, identities, features, data):
name = identities[0].get('name', '') name = identities[0].get('name', '')
for form in data: for form in data:
typefield = form.getField('FORM_TYPE') typefield = form.getField('FORM_TYPE')
@ -1647,14 +1644,14 @@ class MucBrowser(AgentBrowser):
users = form.getField('muc#roominfo_occupants') users = form.getField('muc#roominfo_occupants')
descr = form.getField('muc#roominfo_description') descr = form.getField('muc#roominfo_description')
if users: if users:
model[iter][3] = users.getValue() self.model[iter][3] = users.getValue()
if descr: if descr:
model[iter][4] = descr.getValue() self.model[iter][4] = descr.getValue()
# Only set these when we find a form with additional info # Only set these when we find a form with additional info
# Some servers don't support forms and put extra info in # Some servers don't support forms and put extra info in
# the name attribute, so we preserve it in that case. # the name attribute, so we preserve it in that case.
model[iter][2] = name self.model[iter][2] = name
model[iter][5] = True self.model[iter][5] = True
break break
else: else:
# We didn't find a form, switch to alternate query mode # We didn't find a form, switch to alternate query mode
@ -1664,7 +1661,7 @@ class MucBrowser(AgentBrowser):
self._fetch_source = None self._fetch_source = None
self._query_visible() self._query_visible()
def _update_error(self, model, iter, jid, node): def _update_error(self, iter, jid, node):
# switch to alternate query mode # switch to alternate query mode
self.cache.get_items(jid, node, self._channel_altinfo) self.cache.get_items(jid, node, self._channel_altinfo)