New portion of doc-string refactoring
This commit is contained in:
parent
18fc83c1e8
commit
7316d00766
10 changed files with 614 additions and 293 deletions
388
src/disco.py
388
src/disco.py
|
@ -124,16 +124,21 @@ _cat_to_descr = {
|
||||||
|
|
||||||
|
|
||||||
class CacheDictionary:
|
class CacheDictionary:
|
||||||
'''A dictionary that keeps items around for only a specific time.
|
"""
|
||||||
Lifetime is in minutes. Getrefresh specifies whether to refresh when
|
A dictionary that keeps items around for only a specific time. Lifetime is
|
||||||
an item is merely accessed instead of set aswell.'''
|
in minutes. Getrefresh specifies whether to refresh when an item is merely
|
||||||
|
accessed instead of set aswell
|
||||||
|
"""
|
||||||
|
|
||||||
def __init__(self, lifetime, getrefresh = True):
|
def __init__(self, lifetime, getrefresh = True):
|
||||||
self.lifetime = lifetime * 1000 * 60
|
self.lifetime = lifetime * 1000 * 60
|
||||||
self.getrefresh = getrefresh
|
self.getrefresh = getrefresh
|
||||||
self.cache = {}
|
self.cache = {}
|
||||||
|
|
||||||
class CacheItem:
|
class CacheItem:
|
||||||
'''An object to store cache items and their timeouts.'''
|
"""
|
||||||
|
An object to store cache items and their timeouts
|
||||||
|
"""
|
||||||
def __init__(self, value):
|
def __init__(self, value):
|
||||||
self.value = value
|
self.value = value
|
||||||
self.source = None
|
self.source = None
|
||||||
|
@ -149,13 +154,17 @@ class CacheDictionary:
|
||||||
del self.cache[key]
|
del self.cache[key]
|
||||||
|
|
||||||
def _expire_timeout(self, key):
|
def _expire_timeout(self, key):
|
||||||
'''The timeout has expired, remove the object.'''
|
"""
|
||||||
|
The timeout has expired, remove the object
|
||||||
|
"""
|
||||||
if key in self.cache:
|
if key in self.cache:
|
||||||
del self.cache[key]
|
del self.cache[key]
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def _refresh_timeout(self, key):
|
def _refresh_timeout(self, key):
|
||||||
'''The object was accessed, refresh the timeout.'''
|
"""
|
||||||
|
The object was accessed, refresh the timeout
|
||||||
|
"""
|
||||||
item = self.cache[key]
|
item = self.cache[key]
|
||||||
if item.source:
|
if item.source:
|
||||||
gobject.source_remove(item.source)
|
gobject.source_remove(item.source)
|
||||||
|
@ -187,20 +196,25 @@ class CacheDictionary:
|
||||||
_icon_cache = CacheDictionary(15)
|
_icon_cache = CacheDictionary(15)
|
||||||
|
|
||||||
def get_agent_address(jid, node = None):
|
def get_agent_address(jid, node = None):
|
||||||
'''Returns an agent's address for displaying in the GUI.'''
|
"""
|
||||||
|
Get an agent's address for displaying in the GUI
|
||||||
|
"""
|
||||||
if node:
|
if node:
|
||||||
return '%s@%s' % (node, str(jid))
|
return '%s@%s' % (node, str(jid))
|
||||||
else:
|
else:
|
||||||
return str(jid)
|
return str(jid)
|
||||||
|
|
||||||
class Closure(object):
|
class Closure(object):
|
||||||
'''A weak reference to a callback with arguments as an object.
|
"""
|
||||||
|
A weak reference to a callback with arguments as an object
|
||||||
|
|
||||||
Weak references to methods immediatly die, even if the object is still
|
Weak references to methods immediatly die, even if the object is still
|
||||||
alive. Besides a handy way to store a callback, this provides a workaround
|
alive. Besides a handy way to store a callback, this provides a workaround
|
||||||
that keeps a reference to the object instead.
|
that keeps a reference to the object instead.
|
||||||
|
|
||||||
Userargs and removeargs must be tuples.'''
|
Userargs and removeargs must be tuples.
|
||||||
|
"""
|
||||||
|
|
||||||
def __init__(self, cb, userargs = (), remove = None, removeargs = ()):
|
def __init__(self, cb, userargs = (), remove = None, removeargs = ()):
|
||||||
self.userargs = userargs
|
self.userargs = userargs
|
||||||
self.remove = remove
|
self.remove = remove
|
||||||
|
@ -229,8 +243,11 @@ class Closure(object):
|
||||||
|
|
||||||
|
|
||||||
class ServicesCache:
|
class ServicesCache:
|
||||||
'''Class that caches our query results. Each connection will have it's own
|
"""
|
||||||
ServiceCache instance.'''
|
Class that caches our query results. Each connection will have it's own
|
||||||
|
ServiceCache instance
|
||||||
|
"""
|
||||||
|
|
||||||
def __init__(self, account):
|
def __init__(self, account):
|
||||||
self.account = account
|
self.account = account
|
||||||
self._items = CacheDictionary(0, getrefresh = False)
|
self._items = CacheDictionary(0, getrefresh = False)
|
||||||
|
@ -256,7 +273,9 @@ class ServicesCache:
|
||||||
del self._cbs[cbkey]
|
del self._cbs[cbkey]
|
||||||
|
|
||||||
def get_icon(self, identities = []):
|
def get_icon(self, identities = []):
|
||||||
'''Return the icon for an agent.'''
|
"""
|
||||||
|
Return the icon for an agent
|
||||||
|
"""
|
||||||
# Grab the first identity with an icon
|
# Grab the first identity with an icon
|
||||||
for identity in identities:
|
for identity in identities:
|
||||||
try:
|
try:
|
||||||
|
@ -284,7 +303,9 @@ class ServicesCache:
|
||||||
return pix
|
return pix
|
||||||
|
|
||||||
def get_browser(self, identities=[], features=[]):
|
def get_browser(self, identities=[], features=[]):
|
||||||
'''Return the browser class for an agent.'''
|
"""
|
||||||
|
Return the browser class for an agent
|
||||||
|
"""
|
||||||
# First pass, we try to find a ToplevelAgentBrowser
|
# First pass, we try to find a ToplevelAgentBrowser
|
||||||
for identity in identities:
|
for identity in identities:
|
||||||
try:
|
try:
|
||||||
|
@ -316,7 +337,9 @@ class ServicesCache:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def get_info(self, jid, node, cb, force = False, nofetch = False, args = ()):
|
def get_info(self, jid, node, cb, force = False, nofetch = False, args = ()):
|
||||||
'''Get info for an agent.'''
|
"""
|
||||||
|
Get info for an agent
|
||||||
|
"""
|
||||||
addr = get_agent_address(jid, node)
|
addr = get_agent_address(jid, node)
|
||||||
# Check the cache
|
# Check the cache
|
||||||
if addr in self._info:
|
if addr in self._info:
|
||||||
|
@ -338,7 +361,9 @@ class ServicesCache:
|
||||||
gajim.connections[self.account].discoverInfo(jid, node)
|
gajim.connections[self.account].discoverInfo(jid, node)
|
||||||
|
|
||||||
def get_items(self, jid, node, cb, force = False, nofetch = False, args = ()):
|
def get_items(self, jid, node, cb, force = False, nofetch = False, args = ()):
|
||||||
'''Get a list of items in an agent.'''
|
"""
|
||||||
|
Get a list of items in an agent
|
||||||
|
"""
|
||||||
addr = get_agent_address(jid, node)
|
addr = get_agent_address(jid, node)
|
||||||
# Check the cache
|
# Check the cache
|
||||||
if addr in self._items:
|
if addr in self._items:
|
||||||
|
@ -360,7 +385,9 @@ class ServicesCache:
|
||||||
gajim.connections[self.account].discoverItems(jid, node)
|
gajim.connections[self.account].discoverItems(jid, node)
|
||||||
|
|
||||||
def agent_info(self, jid, node, identities, features, data):
|
def agent_info(self, jid, node, identities, features, data):
|
||||||
'''Callback for when we receive an agent's info.'''
|
"""
|
||||||
|
Callback for when we receive an agent's info
|
||||||
|
"""
|
||||||
addr = get_agent_address(jid, node)
|
addr = get_agent_address(jid, node)
|
||||||
|
|
||||||
# Store in cache
|
# Store in cache
|
||||||
|
@ -376,7 +403,9 @@ class ServicesCache:
|
||||||
del self._cbs[cbkey]
|
del self._cbs[cbkey]
|
||||||
|
|
||||||
def agent_items(self, jid, node, items):
|
def agent_items(self, jid, node, items):
|
||||||
'''Callback for when we receive an agent's items.'''
|
"""
|
||||||
|
Callback for when we receive an agent's items
|
||||||
|
"""
|
||||||
addr = get_agent_address(jid, node)
|
addr = get_agent_address(jid, node)
|
||||||
|
|
||||||
# Store in cache
|
# Store in cache
|
||||||
|
@ -392,8 +421,10 @@ class ServicesCache:
|
||||||
del self._cbs[cbkey]
|
del self._cbs[cbkey]
|
||||||
|
|
||||||
def agent_info_error(self, jid):
|
def agent_info_error(self, jid):
|
||||||
'''Callback for when a query fails. (even after the browse and agents
|
"""
|
||||||
namespaces)'''
|
Callback for when a query fails. Even after the browse and agents
|
||||||
|
namespaces
|
||||||
|
"""
|
||||||
addr = get_agent_address(jid)
|
addr = get_agent_address(jid)
|
||||||
|
|
||||||
# Call callbacks
|
# Call callbacks
|
||||||
|
@ -406,8 +437,10 @@ class ServicesCache:
|
||||||
del self._cbs[cbkey]
|
del self._cbs[cbkey]
|
||||||
|
|
||||||
def agent_items_error(self, jid):
|
def agent_items_error(self, jid):
|
||||||
'''Callback for when a query fails. (even after the browse and agents
|
"""
|
||||||
namespaces)'''
|
Callback for when a query fails. Even after the browse and agents
|
||||||
|
namespaces
|
||||||
|
"""
|
||||||
addr = get_agent_address(jid)
|
addr = get_agent_address(jid)
|
||||||
|
|
||||||
# Call callbacks
|
# Call callbacks
|
||||||
|
@ -421,7 +454,10 @@ class ServicesCache:
|
||||||
|
|
||||||
# object is needed so that @property works
|
# object is needed so that @property works
|
||||||
class ServiceDiscoveryWindow(object):
|
class ServiceDiscoveryWindow(object):
|
||||||
'''Class that represents the Services Discovery window.'''
|
"""
|
||||||
|
Class that represents the Services Discovery window
|
||||||
|
"""
|
||||||
|
|
||||||
def __init__(self, account, jid = '', node = '',
|
def __init__(self, account, jid = '', node = '',
|
||||||
address_entry = False, parent = None):
|
address_entry = False, parent = None):
|
||||||
self.account = account
|
self.account = account
|
||||||
|
@ -510,8 +546,10 @@ _('Without a connection, you can not browse available services'))
|
||||||
self.browser.account = value
|
self.browser.account = value
|
||||||
|
|
||||||
def _initial_state(self):
|
def _initial_state(self):
|
||||||
'''Set some initial state on the window. Separated in a method because
|
"""
|
||||||
it's handy to use within browser's cleanup method.'''
|
Set some initial state on the window. Separated in a method because it's
|
||||||
|
handy to use within browser's cleanup method
|
||||||
|
"""
|
||||||
self.progressbar.hide()
|
self.progressbar.hide()
|
||||||
title_text = _('Service Discovery using account %s') % self.account
|
title_text = _('Service Discovery using account %s') % self.account
|
||||||
self.window.set_title(title_text)
|
self.window.set_title(title_text)
|
||||||
|
@ -550,7 +588,9 @@ _('Without a connection, you can not browse available services'))
|
||||||
self.banner.set_markup(markup)
|
self.banner.set_markup(markup)
|
||||||
|
|
||||||
def paint_banner(self):
|
def paint_banner(self):
|
||||||
'''Repaint the banner with theme color'''
|
"""
|
||||||
|
Repaint the banner with theme color
|
||||||
|
"""
|
||||||
theme = gajim.config.get('roster_theme')
|
theme = gajim.config.get('roster_theme')
|
||||||
bgcolor = gajim.config.get_per('themes', theme, 'bannerbgcolor')
|
bgcolor = gajim.config.get_per('themes', theme, 'bannerbgcolor')
|
||||||
textcolor = gajim.config.get_per('themes', theme, 'bannertextcolor')
|
textcolor = gajim.config.get_per('themes', theme, 'bannertextcolor')
|
||||||
|
@ -584,10 +624,11 @@ _('Without a connection, you can not browse available services'))
|
||||||
self._on_style_set_event, set_fg, set_bg)
|
self._on_style_set_event, set_fg, set_bg)
|
||||||
|
|
||||||
def _on_style_set_event(self, widget, style, *opts):
|
def _on_style_set_event(self, widget, style, *opts):
|
||||||
''' set style of widget from style class *.Frame.Eventbox
|
"""
|
||||||
|
Set style of widget from style class *.Frame.Eventbox
|
||||||
opts[0] == True -> set fg color
|
opts[0] == True -> set fg color
|
||||||
opts[1] == True -> set bg color '''
|
opts[1] == True -> set bg color
|
||||||
|
"""
|
||||||
self.disconnect_style_event()
|
self.disconnect_style_event()
|
||||||
if opts[1]:
|
if opts[1]:
|
||||||
bg_color = widget.style.bg[gtk.STATE_SELECTED]
|
bg_color = widget.style.bg[gtk.STATE_SELECTED]
|
||||||
|
@ -599,9 +640,11 @@ _('Without a connection, you can not browse available services'))
|
||||||
self.connect_style_event(opts[0], opts[1])
|
self.connect_style_event(opts[0], opts[1])
|
||||||
|
|
||||||
def destroy(self, chain = False):
|
def destroy(self, chain = False):
|
||||||
'''Close the browser. This can optionally close its children and
|
"""
|
||||||
propagate to the parent. This should happen on actions like register,
|
Close the browser. This can optionally close its children and propagate
|
||||||
or join to kill off the entire browser chain.'''
|
to the parent. This should happen on actions like register, or join to
|
||||||
|
kill off the entire browser chain
|
||||||
|
"""
|
||||||
if self.dying:
|
if self.dying:
|
||||||
return
|
return
|
||||||
self.dying = True
|
self.dying = True
|
||||||
|
@ -632,7 +675,9 @@ _('Without a connection, you can not browse available services'))
|
||||||
self.cache.cleanup()
|
self.cache.cleanup()
|
||||||
|
|
||||||
def travel(self, jid, node):
|
def travel(self, jid, node):
|
||||||
'''Travel to an agent within the current services window.'''
|
"""
|
||||||
|
Travel to an agent within the current services window
|
||||||
|
"""
|
||||||
if self.browser:
|
if self.browser:
|
||||||
self.browser.cleanup()
|
self.browser.cleanup()
|
||||||
self.browser = None
|
self.browser = None
|
||||||
|
@ -649,7 +694,9 @@ _('Without a connection, you can not browse available services'))
|
||||||
self.cache.get_info(jid, node, self._travel)
|
self.cache.get_info(jid, node, self._travel)
|
||||||
|
|
||||||
def _travel(self, jid, node, identities, features, data):
|
def _travel(self, jid, node, identities, features, data):
|
||||||
'''Continuation of travel.'''
|
"""
|
||||||
|
Continuation of travel
|
||||||
|
"""
|
||||||
if self.dying or jid != self.jid or node != self.node:
|
if self.dying or jid != self.jid or node != self.node:
|
||||||
return
|
return
|
||||||
if not identities:
|
if not identities:
|
||||||
|
@ -671,7 +718,9 @@ _('This type of service does not contain any items to browse.'))
|
||||||
self.browser.browse()
|
self.browser.browse()
|
||||||
|
|
||||||
def open(self, jid, node):
|
def open(self, jid, node):
|
||||||
'''Open an agent. By default, this happens in a new window.'''
|
"""
|
||||||
|
Open an agent. By default, this happens in a new window
|
||||||
|
"""
|
||||||
try:
|
try:
|
||||||
win = gajim.interface.instances[self.account]['disco']\
|
win = gajim.interface.instances[self.account]['disco']\
|
||||||
[get_agent_address(jid, node)]
|
[get_agent_address(jid, node)]
|
||||||
|
@ -737,10 +786,13 @@ _('This type of service does not contain any items to browse.'))
|
||||||
|
|
||||||
|
|
||||||
class AgentBrowser:
|
class AgentBrowser:
|
||||||
'''Class that deals with browsing agents and appearance of the browser
|
"""
|
||||||
window. This class and subclasses should basically be treated as "part"
|
Class that deals with browsing agents and appearance of the browser window.
|
||||||
of the ServiceDiscoveryWindow class, but had to be separated because this part
|
This class and subclasses should basically be treated as "part" of the
|
||||||
is dynamic.'''
|
ServiceDiscoveryWindow class, but had to be separated because this part is
|
||||||
|
dynamic
|
||||||
|
"""
|
||||||
|
|
||||||
def __init__(self, account, jid, node):
|
def __init__(self, account, jid, node):
|
||||||
self.account = account
|
self.account = account
|
||||||
self.jid = jid
|
self.jid = jid
|
||||||
|
@ -751,20 +803,26 @@ class AgentBrowser:
|
||||||
self.active = False
|
self.active = False
|
||||||
|
|
||||||
def _get_agent_address(self):
|
def _get_agent_address(self):
|
||||||
'''Returns the agent's address for displaying in the GUI.'''
|
"""
|
||||||
|
Get the agent's address for displaying in the GUI
|
||||||
|
"""
|
||||||
return get_agent_address(self.jid, self.node)
|
return get_agent_address(self.jid, self.node)
|
||||||
|
|
||||||
def _set_initial_title(self):
|
def _set_initial_title(self):
|
||||||
'''Set the initial window title based on agent address.'''
|
"""
|
||||||
|
Set the initial window title based on agent address
|
||||||
|
"""
|
||||||
self.window.window.set_title(_('Browsing %(address)s using account '
|
self.window.window.set_title(_('Browsing %(address)s using account '
|
||||||
'%(account)s') % {'address': self._get_agent_address(),
|
'%(account)s') % {'address': self._get_agent_address(),
|
||||||
'account': self.account})
|
'account': self.account})
|
||||||
self.window._set_window_banner_text(self._get_agent_address())
|
self.window._set_window_banner_text(self._get_agent_address())
|
||||||
|
|
||||||
def _create_treemodel(self):
|
def _create_treemodel(self):
|
||||||
'''Create the treemodel for the services treeview. When subclassing,
|
"""
|
||||||
note that the first two columns should ALWAYS be of type string and
|
Create the treemodel for the services treeview. When subclassing, note
|
||||||
contain the JID and node of the item respectively.'''
|
that the first two columns should ALWAYS be of type string and contain
|
||||||
|
the JID and node of the item respectively
|
||||||
|
"""
|
||||||
# JID, node, name, address
|
# JID, node, name, address
|
||||||
self.model = gtk.ListStore(str, str, str, str)
|
self.model = gtk.ListStore(str, str, str, str)
|
||||||
self.model.set_sort_column_id(3, gtk.SORT_ASCENDING)
|
self.model.set_sort_column_id(3, gtk.SORT_ASCENDING)
|
||||||
|
@ -792,8 +850,10 @@ class AgentBrowser:
|
||||||
self.window.services_treeview.set_headers_visible(False)
|
self.window.services_treeview.set_headers_visible(False)
|
||||||
|
|
||||||
def _add_actions(self):
|
def _add_actions(self):
|
||||||
'''Add the action buttons to the buttonbox for actions the browser can
|
"""
|
||||||
perform.'''
|
Add the action buttons to the buttonbox for actions the browser can
|
||||||
|
perform
|
||||||
|
"""
|
||||||
self.browse_button = gtk.Button()
|
self.browse_button = gtk.Button()
|
||||||
image = gtk.image_new_from_stock(gtk.STOCK_OPEN, gtk.ICON_SIZE_BUTTON)
|
image = gtk.image_new_from_stock(gtk.STOCK_OPEN, gtk.ICON_SIZE_BUTTON)
|
||||||
label = gtk.Label(_('_Browse'))
|
label = gtk.Label(_('_Browse'))
|
||||||
|
@ -807,13 +867,17 @@ class AgentBrowser:
|
||||||
self.browse_button.show_all()
|
self.browse_button.show_all()
|
||||||
|
|
||||||
def _clean_actions(self):
|
def _clean_actions(self):
|
||||||
'''Remove the action buttons specific to this browser.'''
|
"""
|
||||||
|
Remove the action buttons specific to this browser
|
||||||
|
"""
|
||||||
if self.browse_button:
|
if self.browse_button:
|
||||||
self.browse_button.destroy()
|
self.browse_button.destroy()
|
||||||
self.browse_button = None
|
self.browse_button = None
|
||||||
|
|
||||||
def _set_title(self, jid, node, identities, features, data):
|
def _set_title(self, jid, node, identities, features, data):
|
||||||
'''Set the window title based on agent info.'''
|
"""
|
||||||
|
Set the window title based on agent info
|
||||||
|
"""
|
||||||
# Set the banner and window title
|
# Set the banner and window title
|
||||||
if 'name' in identities[0]:
|
if 'name' in identities[0]:
|
||||||
name = identities[0]['name']
|
name = identities[0]['name']
|
||||||
|
@ -830,8 +894,10 @@ class AgentBrowser:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def prepare_window(self, window):
|
def prepare_window(self, window):
|
||||||
'''Prepare the service discovery window. Called when a browser is hooked
|
"""
|
||||||
up with a ServiceDiscoveryWindow instance.'''
|
Prepare the service discovery window. Called when a browser is hooked up
|
||||||
|
with a ServiceDiscoveryWindow instance
|
||||||
|
"""
|
||||||
self.window = window
|
self.window = window
|
||||||
self.cache = window.cache
|
self.cache = window.cache
|
||||||
|
|
||||||
|
@ -852,7 +918,9 @@ class AgentBrowser:
|
||||||
self.cache.get_info(self.jid, self.node, self._set_title)
|
self.cache.get_info(self.jid, self.node, self._set_title)
|
||||||
|
|
||||||
def cleanup(self):
|
def cleanup(self):
|
||||||
'''Cleanup when the window intends to switch browsers.'''
|
"""
|
||||||
|
Cleanup when the window intends to switch browsers
|
||||||
|
"""
|
||||||
self.active = False
|
self.active = False
|
||||||
|
|
||||||
self._clean_actions()
|
self._clean_actions()
|
||||||
|
@ -862,12 +930,16 @@ class AgentBrowser:
|
||||||
self.window._initial_state()
|
self.window._initial_state()
|
||||||
|
|
||||||
def update_theme(self):
|
def update_theme(self):
|
||||||
'''Called when the default theme is changed.'''
|
"""
|
||||||
|
Called when the default theme is changed
|
||||||
|
"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def on_browse_button_clicked(self, widget = None):
|
def on_browse_button_clicked(self, widget = None):
|
||||||
'''When we want to browse an agent:
|
"""
|
||||||
Open a new services window with a browser for the agent type.'''
|
When we want to browse an agent: open a new services window with a
|
||||||
|
browser for the agent type
|
||||||
|
"""
|
||||||
model, iter_ = self.window.services_treeview.get_selection().get_selected()
|
model, iter_ = self.window.services_treeview.get_selection().get_selected()
|
||||||
if not iter_:
|
if not iter_:
|
||||||
return
|
return
|
||||||
|
@ -877,8 +949,9 @@ class AgentBrowser:
|
||||||
self.window.open(jid, node)
|
self.window.open(jid, node)
|
||||||
|
|
||||||
def update_actions(self):
|
def update_actions(self):
|
||||||
'''When we select a row:
|
"""
|
||||||
activate action buttons based on the agent's info.'''
|
When we select a row: activate action buttons based on the agent's info
|
||||||
|
"""
|
||||||
if self.browse_button:
|
if self.browse_button:
|
||||||
self.browse_button.set_sensitive(False)
|
self.browse_button.set_sensitive(False)
|
||||||
model, iter_ = self.window.services_treeview.get_selection().get_selected()
|
model, iter_ = self.window.services_treeview.get_selection().get_selected()
|
||||||
|
@ -890,7 +963,9 @@ class AgentBrowser:
|
||||||
self.cache.get_info(jid, node, self._update_actions, nofetch = True)
|
self.cache.get_info(jid, node, self._update_actions, nofetch = True)
|
||||||
|
|
||||||
def _update_actions(self, jid, node, identities, features, data):
|
def _update_actions(self, jid, node, identities, features, data):
|
||||||
'''Continuation of update_actions.'''
|
"""
|
||||||
|
Continuation of update_actions
|
||||||
|
"""
|
||||||
if not identities or not self.browse_button:
|
if not identities or not self.browse_button:
|
||||||
return
|
return
|
||||||
klass = self.cache.get_browser(identities, features)
|
klass = self.cache.get_browser(identities, features)
|
||||||
|
@ -898,8 +973,10 @@ class AgentBrowser:
|
||||||
self.browse_button.set_sensitive(True)
|
self.browse_button.set_sensitive(True)
|
||||||
|
|
||||||
def default_action(self):
|
def default_action(self):
|
||||||
'''When we double-click a row:
|
"""
|
||||||
perform the default action on the selected item.'''
|
When we double-click a row: perform the default action on the selected
|
||||||
|
item
|
||||||
|
"""
|
||||||
model, iter_ = self.window.services_treeview.get_selection().get_selected()
|
model, iter_ = self.window.services_treeview.get_selection().get_selected()
|
||||||
if not iter_:
|
if not iter_:
|
||||||
return
|
return
|
||||||
|
@ -909,7 +986,9 @@ class AgentBrowser:
|
||||||
self.cache.get_info(jid, node, self._default_action, nofetch = True)
|
self.cache.get_info(jid, node, self._default_action, nofetch = True)
|
||||||
|
|
||||||
def _default_action(self, jid, node, identities, features, data):
|
def _default_action(self, jid, node, identities, features, data):
|
||||||
'''Continuation of default_action.'''
|
"""
|
||||||
|
Continuation of default_action
|
||||||
|
"""
|
||||||
if self.cache.get_browser(identities, features):
|
if self.cache.get_browser(identities, features):
|
||||||
# Browse if we can
|
# Browse if we can
|
||||||
self.on_browse_button_clicked()
|
self.on_browse_button_clicked()
|
||||||
|
@ -917,7 +996,9 @@ class AgentBrowser:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
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
|
||||||
|
"""
|
||||||
self.model.clear()
|
self.model.clear()
|
||||||
self._total_items = self._progress = 0
|
self._total_items = self._progress = 0
|
||||||
self.window.progressbar.show()
|
self.window.progressbar.show()
|
||||||
|
@ -926,15 +1007,19 @@ class AgentBrowser:
|
||||||
force = force, args = (force,))
|
force = force, args = (force,))
|
||||||
|
|
||||||
def _pulse_timeout_cb(self, *args):
|
def _pulse_timeout_cb(self, *args):
|
||||||
'''Simple callback to keep the progressbar pulsing.'''
|
"""
|
||||||
|
Simple callback to keep the progressbar pulsing
|
||||||
|
"""
|
||||||
if not self.active:
|
if not self.active:
|
||||||
return False
|
return False
|
||||||
self.window.progressbar.pulse()
|
self.window.progressbar.pulse()
|
||||||
return True
|
return True
|
||||||
|
|
||||||
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
|
"""
|
||||||
if so, None otherwise.'''
|
Check if an item is already in the treeview. Return an iter to it if so,
|
||||||
|
None otherwise
|
||||||
|
"""
|
||||||
iter_ = self.model.get_iter_root()
|
iter_ = self.model.get_iter_root()
|
||||||
while iter_:
|
while iter_:
|
||||||
cjid = self.model.get_value(iter_, 0).decode('utf-8')
|
cjid = self.model.get_value(iter_, 0).decode('utf-8')
|
||||||
|
@ -947,7 +1032,9 @@ class AgentBrowser:
|
||||||
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
|
||||||
|
"""
|
||||||
self.model.clear()
|
self.model.clear()
|
||||||
self._total_items = 0
|
self._total_items = 0
|
||||||
gobject.source_remove(self._pulse_timeout)
|
gobject.source_remove(self._pulse_timeout)
|
||||||
|
@ -973,7 +1060,9 @@ _('This service does not contain any items to browse.'))
|
||||||
self.window.services_treeview.set_model(self.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
|
||||||
|
"""
|
||||||
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
|
||||||
|
@ -987,21 +1076,27 @@ _('This service does not contain any items to browse.'))
|
||||||
self.update_actions()
|
self.update_actions()
|
||||||
|
|
||||||
def _add_item(self, jid, node, parent_node, item, force):
|
def _add_item(self, jid, node, parent_node, item, force):
|
||||||
'''Called when an item should be added to the model. The result of a
|
"""
|
||||||
disco#items query.'''
|
Called when an item should be added to the model. The result of a
|
||||||
|
disco#items query
|
||||||
|
"""
|
||||||
self.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)))
|
||||||
self.cache.get_info(jid, node, self._agent_info, force = force)
|
self.cache.get_info(jid, node, self._agent_info, force = force)
|
||||||
|
|
||||||
def _update_item(self, 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
|
"""
|
||||||
disco#items query. (seldom)'''
|
Called when an item should be updated in the model. The result of a
|
||||||
|
disco#items query
|
||||||
|
"""
|
||||||
if 'name' in item:
|
if 'name' in item:
|
||||||
self.model[iter_][2] = item['name']
|
self.model[iter_][2] = item['name']
|
||||||
|
|
||||||
def _update_info(self, 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.
|
"""
|
||||||
The result of a disco#info query.'''
|
Called when an item should be updated in the model with further info.
|
||||||
|
The result of a disco#info query
|
||||||
|
"""
|
||||||
name = identities[0].get('name', '')
|
name = identities[0].get('name', '')
|
||||||
if name:
|
if name:
|
||||||
self.model[iter_][2] = name
|
self.model[iter_][2] = name
|
||||||
|
@ -1012,8 +1107,11 @@ _('This service does not contain any items to browse.'))
|
||||||
|
|
||||||
|
|
||||||
class ToplevelAgentBrowser(AgentBrowser):
|
class ToplevelAgentBrowser(AgentBrowser):
|
||||||
'''This browser is used at the top level of a jabber server to browse
|
"""
|
||||||
services such as transports, conference servers, etc.'''
|
This browser is used at the top level of a jabber server to browse services
|
||||||
|
such as transports, conference servers, etc
|
||||||
|
"""
|
||||||
|
|
||||||
def __init__(self, *args):
|
def __init__(self, *args):
|
||||||
AgentBrowser.__init__(self, *args)
|
AgentBrowser.__init__(self, *args)
|
||||||
self._progressbar_sourceid = None
|
self._progressbar_sourceid = None
|
||||||
|
@ -1029,7 +1127,9 @@ class ToplevelAgentBrowser(AgentBrowser):
|
||||||
self._scroll_signal = None
|
self._scroll_signal = None
|
||||||
|
|
||||||
def _pixbuf_renderer_data_func(self, col, cell, model, iter_):
|
def _pixbuf_renderer_data_func(self, col, cell, model, iter_):
|
||||||
'''Callback for setting the pixbuf renderer's properties.'''
|
"""
|
||||||
|
Callback for setting the pixbuf renderer's properties
|
||||||
|
"""
|
||||||
jid = model.get_value(iter_, 0)
|
jid = model.get_value(iter_, 0)
|
||||||
if jid:
|
if jid:
|
||||||
pix = model.get_value(iter_, 2)
|
pix = model.get_value(iter_, 2)
|
||||||
|
@ -1039,7 +1139,9 @@ class ToplevelAgentBrowser(AgentBrowser):
|
||||||
cell.set_property('visible', False)
|
cell.set_property('visible', False)
|
||||||
|
|
||||||
def _text_renderer_data_func(self, col, cell, model, iter_):
|
def _text_renderer_data_func(self, col, cell, model, iter_):
|
||||||
'''Callback for setting the text renderer's properties.'''
|
"""
|
||||||
|
Callback for setting the text renderer's properties
|
||||||
|
"""
|
||||||
jid = model.get_value(iter_, 0)
|
jid = model.get_value(iter_, 0)
|
||||||
markup = model.get_value(iter_, 3)
|
markup = model.get_value(iter_, 3)
|
||||||
state = model.get_value(iter_, 4)
|
state = model.get_value(iter_, 4)
|
||||||
|
@ -1060,7 +1162,9 @@ class ToplevelAgentBrowser(AgentBrowser):
|
||||||
cell.set_property('foreground_set', False)
|
cell.set_property('foreground_set', False)
|
||||||
|
|
||||||
def _treemodel_sort_func(self, model, iter1, iter2):
|
def _treemodel_sort_func(self, model, iter1, iter2):
|
||||||
'''Sort function for our treemodel.'''
|
"""
|
||||||
|
Sort function for our treemode
|
||||||
|
"""
|
||||||
# Compare state
|
# Compare state
|
||||||
statecmp = cmp(model.get_value(iter1, 4), model.get_value(iter2, 4))
|
statecmp = cmp(model.get_value(iter1, 4), model.get_value(iter2, 4))
|
||||||
if statecmp == 0:
|
if statecmp == 0:
|
||||||
|
@ -1120,8 +1224,9 @@ class ToplevelAgentBrowser(AgentBrowser):
|
||||||
self._show_tooltip, state)
|
self._show_tooltip, state)
|
||||||
|
|
||||||
def on_treeview_event_hide_tooltip(self, widget, event):
|
def on_treeview_event_hide_tooltip(self, widget, event):
|
||||||
''' This happens on scroll_event, key_press_event
|
"""
|
||||||
and button_press_event '''
|
This happens on scroll_event, key_press_event and button_press_event
|
||||||
|
"""
|
||||||
self.tooltip.hide_tooltip()
|
self.tooltip.hide_tooltip()
|
||||||
|
|
||||||
def _create_treemodel(self):
|
def _create_treemodel(self):
|
||||||
|
@ -1236,8 +1341,9 @@ class ToplevelAgentBrowser(AgentBrowser):
|
||||||
AgentBrowser._clean_actions(self)
|
AgentBrowser._clean_actions(self)
|
||||||
|
|
||||||
def on_search_button_clicked(self, widget = None):
|
def on_search_button_clicked(self, widget = None):
|
||||||
'''When we want to search something:
|
"""
|
||||||
open search window'''
|
When we want to search something: open search window
|
||||||
|
"""
|
||||||
model, iter_ = self.window.services_treeview.get_selection().get_selected()
|
model, iter_ = self.window.services_treeview.get_selection().get_selected()
|
||||||
if not iter_:
|
if not iter_:
|
||||||
return
|
return
|
||||||
|
@ -1261,8 +1367,9 @@ class ToplevelAgentBrowser(AgentBrowser):
|
||||||
self.window.services_treeview.queue_draw()
|
self.window.services_treeview.queue_draw()
|
||||||
|
|
||||||
def on_execute_button_clicked(self, widget=None):
|
def on_execute_button_clicked(self, widget=None):
|
||||||
'''When we want to execute a command:
|
"""
|
||||||
open adhoc command window'''
|
When we want to execute a command: open adhoc command window
|
||||||
|
"""
|
||||||
model, iter_ = self.window.services_treeview.get_selection().get_selected()
|
model, iter_ = self.window.services_treeview.get_selection().get_selected()
|
||||||
if not iter_:
|
if not iter_:
|
||||||
return
|
return
|
||||||
|
@ -1271,9 +1378,10 @@ class ToplevelAgentBrowser(AgentBrowser):
|
||||||
adhoc_commands.CommandWindow(self.account, service, commandnode=node)
|
adhoc_commands.CommandWindow(self.account, service, commandnode=node)
|
||||||
|
|
||||||
def on_register_button_clicked(self, widget = None):
|
def on_register_button_clicked(self, widget = None):
|
||||||
'''When we want to register an agent:
|
"""
|
||||||
request information about registering with the agent and close the
|
When we want to register an agent: request information about registering
|
||||||
window.'''
|
with the agent and close the window
|
||||||
|
"""
|
||||||
model, iter_ = self.window.services_treeview.get_selection().get_selected()
|
model, iter_ = self.window.services_treeview.get_selection().get_selected()
|
||||||
if not iter_:
|
if not iter_:
|
||||||
return
|
return
|
||||||
|
@ -1283,8 +1391,10 @@ class ToplevelAgentBrowser(AgentBrowser):
|
||||||
self.window.destroy(chain = True)
|
self.window.destroy(chain = True)
|
||||||
|
|
||||||
def on_join_button_clicked(self, widget):
|
def on_join_button_clicked(self, widget):
|
||||||
'''When we want to join an IRC room or create a new MUC room:
|
"""
|
||||||
Opens the join_groupchat_window.'''
|
When we want to join an IRC room or create a new MUC room: Opens the
|
||||||
|
join_groupchat_window
|
||||||
|
"""
|
||||||
model, iter_ = self.window.services_treeview.get_selection().get_selected()
|
model, iter_ = self.window.services_treeview.get_selection().get_selected()
|
||||||
if not iter_:
|
if not iter_:
|
||||||
return
|
return
|
||||||
|
@ -1375,7 +1485,9 @@ class ToplevelAgentBrowser(AgentBrowser):
|
||||||
AgentBrowser.browse(self, force = force)
|
AgentBrowser.browse(self, force = force)
|
||||||
|
|
||||||
def _expand_all(self):
|
def _expand_all(self):
|
||||||
'''Expand all items in the treeview'''
|
"""
|
||||||
|
Expand all items in the treeview
|
||||||
|
"""
|
||||||
# GTK apparently screws up here occasionally. :/
|
# GTK apparently screws up here occasionally. :/
|
||||||
#def expand_all(*args):
|
#def expand_all(*args):
|
||||||
# self.window.services_treeview.expand_all()
|
# self.window.services_treeview.expand_all()
|
||||||
|
@ -1386,7 +1498,9 @@ class ToplevelAgentBrowser(AgentBrowser):
|
||||||
self.window.services_treeview.expand_all()
|
self.window.services_treeview.expand_all()
|
||||||
|
|
||||||
def _update_progressbar(self):
|
def _update_progressbar(self):
|
||||||
'''Update the progressbar.'''
|
"""
|
||||||
|
Update the progressbar
|
||||||
|
"""
|
||||||
# Refresh this every update
|
# Refresh this every update
|
||||||
if self._progressbar_sourceid:
|
if self._progressbar_sourceid:
|
||||||
gobject.source_remove(self._progressbar_sourceid)
|
gobject.source_remove(self._progressbar_sourceid)
|
||||||
|
@ -1408,13 +1522,17 @@ class ToplevelAgentBrowser(AgentBrowser):
|
||||||
self.window.progressbar.set_fraction(fraction)
|
self.window.progressbar.set_fraction(fraction)
|
||||||
|
|
||||||
def _hide_progressbar_cb(self, *args):
|
def _hide_progressbar_cb(self, *args):
|
||||||
'''Simple callback to hide the progressbar a second after we finish.'''
|
"""
|
||||||
|
Simple callback to hide the progressbar a second after we finish
|
||||||
|
"""
|
||||||
if self.active:
|
if self.active:
|
||||||
self.window.progressbar.hide()
|
self.window.progressbar.hide()
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def _friendly_category(self, category, type_=None):
|
def _friendly_category(self, category, type_=None):
|
||||||
'''Get the friendly category name and priority.'''
|
"""
|
||||||
|
Get the friendly category name and priority
|
||||||
|
"""
|
||||||
cat = None
|
cat = None
|
||||||
if type_:
|
if type_:
|
||||||
# Try type-specific override
|
# Try type-specific override
|
||||||
|
@ -1430,12 +1548,16 @@ class ToplevelAgentBrowser(AgentBrowser):
|
||||||
return cat, prio
|
return cat, prio
|
||||||
|
|
||||||
def _create_category(self, 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 self.model.append(None, ('', '', None, cat, prio))
|
return self.model.append(None, ('', '', None, cat, prio))
|
||||||
|
|
||||||
def _find_category(self, 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 = self._friendly_category(cat, type_)[0]
|
cat = self._friendly_category(cat, type_)[0]
|
||||||
iter_ = self.model.get_iter_root()
|
iter_ = self.model.get_iter_root()
|
||||||
while iter_:
|
while iter_:
|
||||||
|
@ -1670,8 +1792,10 @@ class MucBrowser(AgentBrowser):
|
||||||
_('You can manage your bookmarks via Actions menu in your roster.'))
|
_('You can manage your bookmarks via Actions menu in your roster.'))
|
||||||
|
|
||||||
def on_join_button_clicked(self, *args):
|
def on_join_button_clicked(self, *args):
|
||||||
'''When we want to join a conference:
|
"""
|
||||||
Ask specific informations about the selected agent and close the window'''
|
When we want to join a conference: ask specific informations about the
|
||||||
|
selected agent and close the window
|
||||||
|
"""
|
||||||
model, iter_ = self.window.services_treeview.get_selection().get_selected()
|
model, iter_ = self.window.services_treeview.get_selection().get_selected()
|
||||||
if not iter_:
|
if not iter_:
|
||||||
return
|
return
|
||||||
|
@ -1697,18 +1821,24 @@ class MucBrowser(AgentBrowser):
|
||||||
self.on_join_button_clicked()
|
self.on_join_button_clicked()
|
||||||
|
|
||||||
def _start_info_query(self):
|
def _start_info_query(self):
|
||||||
'''Idle callback to start checking for visible rows.'''
|
"""
|
||||||
|
Idle callback to start checking for visible rows
|
||||||
|
"""
|
||||||
self._fetch_source = None
|
self._fetch_source = None
|
||||||
self._query_visible()
|
self._query_visible()
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def on_scroll(self, *args):
|
def on_scroll(self, *args):
|
||||||
'''Scrollwindow callback to trigger new queries on scolling.'''
|
"""
|
||||||
|
Scrollwindow callback to trigger new queries on scolling
|
||||||
|
"""
|
||||||
# This apparently happens when inactive sometimes
|
# This apparently happens when inactive sometimes
|
||||||
self._query_visible()
|
self._query_visible()
|
||||||
|
|
||||||
def _query_visible(self):
|
def _query_visible(self):
|
||||||
'''Query the next visible row for info.'''
|
"""
|
||||||
|
Query the next visible row for info
|
||||||
|
"""
|
||||||
if self._fetch_source:
|
if self._fetch_source:
|
||||||
# We're already fetching
|
# We're already fetching
|
||||||
return
|
return
|
||||||
|
@ -1751,9 +1881,10 @@ class MucBrowser(AgentBrowser):
|
||||||
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):
|
||||||
'''Callback for the alternate disco#items query. We try to atleast get
|
"""
|
||||||
the amount of users in the room if the service does not support MUC
|
Callback for the alternate disco#items query. We try to atleast get the
|
||||||
dataforms.'''
|
amount of users in the room if the service does not support MUC dataforms
|
||||||
|
"""
|
||||||
if items == 0:
|
if items == 0:
|
||||||
# The server returned an error
|
# The server returned an error
|
||||||
self._broken += 1
|
self._broken += 1
|
||||||
|
@ -1816,15 +1947,20 @@ class MucBrowser(AgentBrowser):
|
||||||
self.cache.get_items(jid, node, self._channel_altinfo)
|
self.cache.get_items(jid, node, self._channel_altinfo)
|
||||||
|
|
||||||
def PubSubBrowser(account, jid, node):
|
def PubSubBrowser(account, jid, node):
|
||||||
''' Returns an AgentBrowser subclass that will display service discovery
|
"""
|
||||||
for particular pubsub service. Different pubsub services may need to
|
Return an AgentBrowser subclass that will display service discovery for
|
||||||
present different data during browsing. '''
|
particular pubsub service. Different pubsub services may need to present
|
||||||
|
different data during browsing
|
||||||
|
"""
|
||||||
# for now, only discussion groups are supported...
|
# for now, only discussion groups are supported...
|
||||||
# TODO: check if it has appropriate features to be such kind of service
|
# TODO: check if it has appropriate features to be such kind of service
|
||||||
return DiscussionGroupsBrowser(account, jid, node)
|
return DiscussionGroupsBrowser(account, jid, node)
|
||||||
|
|
||||||
class DiscussionGroupsBrowser(AgentBrowser):
|
class DiscussionGroupsBrowser(AgentBrowser):
|
||||||
''' For browsing pubsub-based discussion groups service. '''
|
"""
|
||||||
|
For browsing pubsub-based discussion groups service
|
||||||
|
"""
|
||||||
|
|
||||||
def __init__(self, account, jid, node):
|
def __init__(self, account, jid, node):
|
||||||
AgentBrowser.__init__(self, account, jid, node)
|
AgentBrowser.__init__(self, account, jid, node)
|
||||||
|
|
||||||
|
@ -1840,7 +1976,9 @@ class DiscussionGroupsBrowser(AgentBrowser):
|
||||||
gajim.connections[account].send_pb_subscription_query(jid, self._subscriptionsCB)
|
gajim.connections[account].send_pb_subscription_query(jid, self._subscriptionsCB)
|
||||||
|
|
||||||
def _create_treemodel(self):
|
def _create_treemodel(self):
|
||||||
''' Create treemodel for the window. '''
|
"""
|
||||||
|
Create treemodel for the window
|
||||||
|
"""
|
||||||
# JID, node, name (with description) - pango markup, dont have info?, subscribed?
|
# JID, node, name (with description) - pango markup, dont have info?, subscribed?
|
||||||
self.model = gtk.TreeStore(str, str, str, bool, bool)
|
self.model = gtk.TreeStore(str, str, str, bool, bool)
|
||||||
# sort by name
|
# sort by name
|
||||||
|
@ -1891,8 +2029,10 @@ class DiscussionGroupsBrowser(AgentBrowser):
|
||||||
return self.in_list
|
return self.in_list
|
||||||
|
|
||||||
def _add_item(self, jid, node, parent_node, item, force):
|
def _add_item(self, jid, node, parent_node, item, force):
|
||||||
''' Called when we got basic information about new node from query.
|
"""
|
||||||
Show the item. '''
|
Called when we got basic information about new node from query. Show the
|
||||||
|
item
|
||||||
|
"""
|
||||||
name = item.get('name', '')
|
name = item.get('name', '')
|
||||||
|
|
||||||
if self.subscriptions is not None:
|
if self.subscriptions is not None:
|
||||||
|
@ -1962,8 +2102,10 @@ class DiscussionGroupsBrowser(AgentBrowser):
|
||||||
self.unsubscribe_button = None
|
self.unsubscribe_button = None
|
||||||
|
|
||||||
def update_actions(self):
|
def update_actions(self):
|
||||||
'''Called when user selected a row. Make subscribe/unsubscribe buttons
|
"""
|
||||||
sensitive appropriatelly.'''
|
Called when user selected a row. Make subscribe/unsubscribe buttons
|
||||||
|
sensitive appropriatelly
|
||||||
|
"""
|
||||||
# we have nothing to do if we don't have buttons...
|
# we have nothing to do if we don't have buttons...
|
||||||
if self.subscribe_button is None: return
|
if self.subscribe_button is None: return
|
||||||
|
|
||||||
|
@ -1980,7 +2122,9 @@ class DiscussionGroupsBrowser(AgentBrowser):
|
||||||
self.unsubscribe_button.set_sensitive(subscribed)
|
self.unsubscribe_button.set_sensitive(subscribed)
|
||||||
|
|
||||||
def on_post_button_clicked(self, widget):
|
def on_post_button_clicked(self, widget):
|
||||||
'''Called when 'post' button is pressed. Open window to create post'''
|
"""
|
||||||
|
Called when 'post' button is pressed. Open window to create post
|
||||||
|
"""
|
||||||
model, iter_ = self.window.services_treeview.get_selection().get_selected()
|
model, iter_ = self.window.services_treeview.get_selection().get_selected()
|
||||||
if iter_ is None: return
|
if iter_ is None: return
|
||||||
|
|
||||||
|
@ -1989,7 +2133,9 @@ class DiscussionGroupsBrowser(AgentBrowser):
|
||||||
groups.GroupsPostWindow(self.account, self.jid, groupnode)
|
groups.GroupsPostWindow(self.account, self.jid, groupnode)
|
||||||
|
|
||||||
def on_subscribe_button_clicked(self, widget):
|
def on_subscribe_button_clicked(self, widget):
|
||||||
'''Called when 'subscribe' button is pressed. Send subscribtion request.'''
|
"""
|
||||||
|
Called when 'subscribe' button is pressed. Send subscribtion request
|
||||||
|
"""
|
||||||
model, iter_ = self.window.services_treeview.get_selection().get_selected()
|
model, iter_ = self.window.services_treeview.get_selection().get_selected()
|
||||||
if iter_ is None: return
|
if iter_ is None: return
|
||||||
|
|
||||||
|
@ -1998,7 +2144,9 @@ class DiscussionGroupsBrowser(AgentBrowser):
|
||||||
gajim.connections[self.account].send_pb_subscribe(self.jid, groupnode, self._subscribeCB, groupnode)
|
gajim.connections[self.account].send_pb_subscribe(self.jid, groupnode, self._subscribeCB, groupnode)
|
||||||
|
|
||||||
def on_unsubscribe_button_clicked(self, widget):
|
def on_unsubscribe_button_clicked(self, widget):
|
||||||
'''Called when 'unsubscribe' button is pressed. Send unsubscription request.'''
|
"""
|
||||||
|
Called when 'unsubscribe' button is pressed. Send unsubscription request
|
||||||
|
"""
|
||||||
model, iter_ = self.window.services_treeview.get_selection().get_selected()
|
model, iter_ = self.window.services_treeview.get_selection().get_selected()
|
||||||
if iter_ is None: return
|
if iter_ is None: return
|
||||||
|
|
||||||
|
@ -2007,8 +2155,10 @@ class DiscussionGroupsBrowser(AgentBrowser):
|
||||||
gajim.connections[self.account].send_pb_unsubscribe(self.jid, groupnode, self._unsubscribeCB, groupnode)
|
gajim.connections[self.account].send_pb_unsubscribe(self.jid, groupnode, self._unsubscribeCB, groupnode)
|
||||||
|
|
||||||
def _subscriptionsCB(self, conn, request):
|
def _subscriptionsCB(self, conn, request):
|
||||||
''' We got the subscribed groups list stanza. Now, if we already
|
"""
|
||||||
have items on the list, we should actualize them. '''
|
We got the subscribed groups list stanza. Now, if we already have items
|
||||||
|
on the list, we should actualize them
|
||||||
|
"""
|
||||||
try:
|
try:
|
||||||
subscriptions = request.getTag('pubsub').getTag('subscriptions')
|
subscriptions = request.getTag('pubsub').getTag('subscriptions')
|
||||||
except Exception:
|
except Exception:
|
||||||
|
@ -2036,7 +2186,9 @@ class DiscussionGroupsBrowser(AgentBrowser):
|
||||||
raise xmpp.NodeProcessed
|
raise xmpp.NodeProcessed
|
||||||
|
|
||||||
def _subscribeCB(self, conn, request, groupnode):
|
def _subscribeCB(self, conn, request, groupnode):
|
||||||
'''We have just subscribed to a node. Update UI'''
|
"""
|
||||||
|
We have just subscribed to a node. Update UI
|
||||||
|
"""
|
||||||
self.subscriptions.add(groupnode)
|
self.subscriptions.add(groupnode)
|
||||||
|
|
||||||
model = self.window.services_treeview.get_model()
|
model = self.window.services_treeview.get_model()
|
||||||
|
@ -2050,7 +2202,9 @@ class DiscussionGroupsBrowser(AgentBrowser):
|
||||||
raise xmpp.NodeProcessed
|
raise xmpp.NodeProcessed
|
||||||
|
|
||||||
def _unsubscribeCB(self, conn, request, groupnode):
|
def _unsubscribeCB(self, conn, request, groupnode):
|
||||||
'''We have just unsubscribed from a node. Update UI'''
|
"""
|
||||||
|
We have just unsubscribed from a node. Update UI
|
||||||
|
"""
|
||||||
self.subscriptions.remove(groupnode)
|
self.subscriptions.remove(groupnode)
|
||||||
|
|
||||||
model = self.window.services_treeview.get_model()
|
model = self.window.services_treeview.get_model()
|
||||||
|
|
|
@ -33,7 +33,9 @@ from common import helpers
|
||||||
from common import kwalletbinding
|
from common import kwalletbinding
|
||||||
|
|
||||||
class FeaturesWindow:
|
class FeaturesWindow:
|
||||||
'''Class for features window'''
|
"""
|
||||||
|
Class for features window
|
||||||
|
"""
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.xml = gtkgui_helpers.get_glade('features_window.glade')
|
self.xml = gtkgui_helpers.get_glade('features_window.glade')
|
||||||
|
|
|
@ -134,7 +134,9 @@ class FileTransfersWindow:
|
||||||
self.xml.signal_autoconnect(self)
|
self.xml.signal_autoconnect(self)
|
||||||
|
|
||||||
def find_transfer_by_jid(self, account, jid):
|
def find_transfer_by_jid(self, account, jid):
|
||||||
''' find all transfers with peer 'jid' that belong to 'account' '''
|
"""
|
||||||
|
Find all transfers with peer 'jid' that belong to 'account'
|
||||||
|
"""
|
||||||
active_transfers = [[],[]] # ['senders', 'receivers']
|
active_transfers = [[],[]] # ['senders', 'receivers']
|
||||||
|
|
||||||
# 'account' is the sender
|
# 'account' is the sender
|
||||||
|
@ -155,7 +157,9 @@ class FileTransfersWindow:
|
||||||
return active_transfers
|
return active_transfers
|
||||||
|
|
||||||
def show_completed(self, jid, file_props):
|
def show_completed(self, jid, file_props):
|
||||||
''' show a dialog saying that file (file_props) has been transferred'''
|
"""
|
||||||
|
Show a dialog saying that file (file_props) has been transferred
|
||||||
|
"""
|
||||||
def on_open(widget, file_props):
|
def on_open(widget, file_props):
|
||||||
dialog.destroy()
|
dialog.destroy()
|
||||||
if 'file-name' not in file_props:
|
if 'file-name' not in file_props:
|
||||||
|
@ -207,14 +211,16 @@ class FileTransfersWindow:
|
||||||
dialog.show_all()
|
dialog.show_all()
|
||||||
|
|
||||||
def show_request_error(self, file_props):
|
def show_request_error(self, file_props):
|
||||||
''' show error dialog to the recipient saying that transfer
|
"""
|
||||||
has been canceled'''
|
Show error dialog to the recipient saying that transfer has been canceled
|
||||||
|
"""
|
||||||
dialogs.InformationDialog(_('File transfer cancelled'), _('Connection with peer cannot be established.'))
|
dialogs.InformationDialog(_('File transfer cancelled'), _('Connection with peer cannot be established.'))
|
||||||
self.tree.get_selection().unselect_all()
|
self.tree.get_selection().unselect_all()
|
||||||
|
|
||||||
def show_send_error(self, file_props):
|
def show_send_error(self, file_props):
|
||||||
''' show error dialog to the sender saying that transfer
|
"""
|
||||||
has been canceled'''
|
Show error dialog to the sender saying that transfer has been canceled
|
||||||
|
"""
|
||||||
dialogs.InformationDialog(_('File transfer cancelled'),
|
dialogs.InformationDialog(_('File transfer cancelled'),
|
||||||
_('Connection with peer cannot be established.'))
|
_('Connection with peer cannot be established.'))
|
||||||
self.tree.get_selection().unselect_all()
|
self.tree.get_selection().unselect_all()
|
||||||
|
@ -273,7 +279,9 @@ _('Connection with peer cannot be established.'))
|
||||||
desc_hbox.show_all()
|
desc_hbox.show_all()
|
||||||
|
|
||||||
def send_file(self, account, contact, file_path, file_desc=''):
|
def send_file(self, account, contact, file_path, file_desc=''):
|
||||||
''' start the real transfer(upload) of the file '''
|
"""
|
||||||
|
Start the real transfer(upload) of the file
|
||||||
|
"""
|
||||||
if gtkgui_helpers.file_is_locked(file_path):
|
if gtkgui_helpers.file_is_locked(file_path):
|
||||||
pritext = _('Gajim cannot access this file')
|
pritext = _('Gajim cannot access this file')
|
||||||
sextext = _('This file is being used by another process.')
|
sextext = _('This file is being used by another process.')
|
||||||
|
@ -303,8 +311,10 @@ _('Connection with peer cannot be established.'))
|
||||||
gajim.connections[account].send_file_approval(file_props)
|
gajim.connections[account].send_file_approval(file_props)
|
||||||
|
|
||||||
def show_file_request(self, account, contact, file_props):
|
def show_file_request(self, account, contact, file_props):
|
||||||
''' show dialog asking for comfirmation and store location of new
|
"""
|
||||||
file requested by a contact'''
|
Show dialog asking for comfirmation and store location of new file
|
||||||
|
requested by a contact
|
||||||
|
"""
|
||||||
if file_props is None or 'name' not in file_props:
|
if file_props is None or 'name' not in file_props:
|
||||||
return
|
return
|
||||||
sec_text = '\t' + _('File: %s') % gobject.markup_escape_text(
|
sec_text = '\t' + _('File: %s') % gobject.markup_escape_text(
|
||||||
|
@ -394,7 +404,9 @@ _('Connection with peer cannot be established.'))
|
||||||
self.window.render_icon(self.icons[ident], gtk.ICON_SIZE_MENU))
|
self.window.render_icon(self.icons[ident], gtk.ICON_SIZE_MENU))
|
||||||
|
|
||||||
def set_status(self, typ, sid, status):
|
def set_status(self, typ, sid, status):
|
||||||
''' change the status of a transfer to state 'status' '''
|
"""
|
||||||
|
Change the status of a transfer to state 'status'
|
||||||
|
"""
|
||||||
iter_ = self.get_iter_by_sid(typ, sid)
|
iter_ = self.get_iter_by_sid(typ, sid)
|
||||||
if iter_ is None:
|
if iter_ is None:
|
||||||
return
|
return
|
||||||
|
@ -409,8 +421,10 @@ _('Connection with peer cannot be established.'))
|
||||||
self.select_func(path)
|
self.select_func(path)
|
||||||
|
|
||||||
def _format_percent(self, percent):
|
def _format_percent(self, percent):
|
||||||
''' add extra spaces from both sides of the percent, so that
|
"""
|
||||||
progress string has always a fixed size'''
|
Add extra spaces from both sides of the percent, so that progress string
|
||||||
|
has always a fixed size
|
||||||
|
"""
|
||||||
_str = ' '
|
_str = ' '
|
||||||
if percent != 100.:
|
if percent != 100.:
|
||||||
_str += ' '
|
_str += ' '
|
||||||
|
@ -481,7 +495,9 @@ _('Connection with peer cannot be established.'))
|
||||||
del(file_props)
|
del(file_props)
|
||||||
|
|
||||||
def set_progress(self, typ, sid, transfered_size, iter_ = None):
|
def set_progress(self, typ, sid, transfered_size, iter_ = None):
|
||||||
''' change the progress of a transfer with new transfered size'''
|
"""
|
||||||
|
Change the progress of a transfer with new transfered size
|
||||||
|
"""
|
||||||
if sid not in self.files_props[typ]:
|
if sid not in self.files_props[typ]:
|
||||||
return
|
return
|
||||||
file_props = self.files_props[typ][sid]
|
file_props = self.files_props[typ][sid]
|
||||||
|
@ -546,8 +562,10 @@ _('Connection with peer cannot be established.'))
|
||||||
self.select_func(path)
|
self.select_func(path)
|
||||||
|
|
||||||
def get_iter_by_sid(self, typ, sid):
|
def get_iter_by_sid(self, typ, sid):
|
||||||
'''returns iter to the row, which holds file transfer, identified by the
|
"""
|
||||||
session id'''
|
Return iter to the row, which holds file transfer, identified by the
|
||||||
|
session id
|
||||||
|
"""
|
||||||
iter_ = self.model.get_iter_root()
|
iter_ = self.model.get_iter_root()
|
||||||
while iter_:
|
while iter_:
|
||||||
if typ + sid == self.model[iter_][C_SID].decode('utf-8'):
|
if typ + sid == self.model[iter_][C_SID].decode('utf-8'):
|
||||||
|
@ -556,8 +574,9 @@ _('Connection with peer cannot be established.'))
|
||||||
|
|
||||||
def get_send_file_props(self, account, contact, file_path, file_name,
|
def get_send_file_props(self, account, contact, file_path, file_name,
|
||||||
file_desc=''):
|
file_desc=''):
|
||||||
''' create new file_props dict and set initial file transfer
|
"""
|
||||||
properties in it'''
|
Create new file_props dict and set initial file transfer properties in it
|
||||||
|
"""
|
||||||
file_props = {'file-name' : file_path, 'name' : file_name,
|
file_props = {'file-name' : file_path, 'name' : file_name,
|
||||||
'type' : 's', 'desc' : file_desc}
|
'type' : 's', 'desc' : file_desc}
|
||||||
if os.path.isfile(file_path):
|
if os.path.isfile(file_path):
|
||||||
|
@ -582,7 +601,9 @@ _('Connection with peer cannot be established.'))
|
||||||
return file_props
|
return file_props
|
||||||
|
|
||||||
def add_transfer(self, account, contact, file_props):
|
def add_transfer(self, account, contact, file_props):
|
||||||
''' add new transfer to FT window and show the FT window '''
|
"""
|
||||||
|
Add new transfer to FT window and show the FT window
|
||||||
|
"""
|
||||||
self.on_transfers_list_leave_notify_event(None)
|
self.on_transfers_list_leave_notify_event(None)
|
||||||
if file_props is None:
|
if file_props is None:
|
||||||
return
|
return
|
||||||
|
@ -686,15 +707,19 @@ _('Connection with peer cannot be established.'))
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def set_cleanup_sensitivity(self):
|
def set_cleanup_sensitivity(self):
|
||||||
''' check if there are transfer rows and set cleanup_button
|
"""
|
||||||
sensitive, or insensitive if model is empty'''
|
Check if there are transfer rows and set cleanup_button sensitive, or
|
||||||
|
insensitive if model is empty
|
||||||
|
"""
|
||||||
if len(self.model) == 0:
|
if len(self.model) == 0:
|
||||||
self.cleanup_button.set_sensitive(False)
|
self.cleanup_button.set_sensitive(False)
|
||||||
else:
|
else:
|
||||||
self.cleanup_button.set_sensitive(True)
|
self.cleanup_button.set_sensitive(True)
|
||||||
|
|
||||||
def set_all_insensitive(self):
|
def set_all_insensitive(self):
|
||||||
''' make all buttons/menuitems insensitive '''
|
"""
|
||||||
|
Make all buttons/menuitems insensitive
|
||||||
|
"""
|
||||||
self.pause_button.set_sensitive(False)
|
self.pause_button.set_sensitive(False)
|
||||||
self.pause_menuitem.set_sensitive(False)
|
self.pause_menuitem.set_sensitive(False)
|
||||||
self.continue_menuitem.set_sensitive(False)
|
self.continue_menuitem.set_sensitive(False)
|
||||||
|
@ -705,8 +730,10 @@ _('Connection with peer cannot be established.'))
|
||||||
self.set_cleanup_sensitivity()
|
self.set_cleanup_sensitivity()
|
||||||
|
|
||||||
def set_buttons_sensitive(self, path, is_row_selected):
|
def set_buttons_sensitive(self, path, is_row_selected):
|
||||||
''' make buttons/menuitems sensitive as appropriate to
|
"""
|
||||||
the state of file transfer located at path 'path' '''
|
Make buttons/menuitems sensitive as appropriate to the state of file
|
||||||
|
transfer located at path 'path'
|
||||||
|
"""
|
||||||
if path is None:
|
if path is None:
|
||||||
self.set_all_insensitive()
|
self.set_all_insensitive()
|
||||||
return
|
return
|
||||||
|
@ -743,8 +770,9 @@ _('Connection with peer cannot be established.'))
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def selection_changed(self, args):
|
def selection_changed(self, args):
|
||||||
''' selection has changed - change the sensitivity of the
|
"""
|
||||||
buttons/menuitems'''
|
Selection has changed - change the sensitivity of the buttons/menuitems
|
||||||
|
"""
|
||||||
selection = args
|
selection = args
|
||||||
selected = selection.get_selected_rows()
|
selected = selection.get_selected_rows()
|
||||||
if selected[1] != []:
|
if selected[1] != []:
|
||||||
|
@ -881,7 +909,9 @@ _('Connection with peer cannot be established.'))
|
||||||
event_button, event.time)
|
event_button, event.time)
|
||||||
|
|
||||||
def on_transfers_list_key_press_event(self, widget, event):
|
def on_transfers_list_key_press_event(self, widget, event):
|
||||||
'''when a key is pressed in the treeviews'''
|
"""
|
||||||
|
When a key is pressed in the treeviews
|
||||||
|
"""
|
||||||
self.tooltip.hide_tooltip()
|
self.tooltip.hide_tooltip()
|
||||||
iter_ = None
|
iter_ = None
|
||||||
try:
|
try:
|
||||||
|
@ -963,5 +993,4 @@ _('Connection with peer cannot be established.'))
|
||||||
if event.keyval == gtk.keysyms.Escape: # ESCAPE
|
if event.keyval == gtk.keysyms.Escape: # ESCAPE
|
||||||
self.window.hide()
|
self.window.hide()
|
||||||
|
|
||||||
|
|
||||||
# vim: se ts=3:
|
# vim: se ts=3:
|
||||||
|
|
|
@ -60,7 +60,6 @@ INTERFACE = 'org.gajim.dbus.RemoteInterface'
|
||||||
SERVICE = 'org.gajim.dbus'
|
SERVICE = 'org.gajim.dbus'
|
||||||
BASENAME = 'gajim-remote'
|
BASENAME = 'gajim-remote'
|
||||||
|
|
||||||
|
|
||||||
class GajimRemote:
|
class GajimRemote:
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
@ -327,7 +326,9 @@ class GajimRemote:
|
||||||
self.print_result(res)
|
self.print_result(res)
|
||||||
|
|
||||||
def print_result(self, res):
|
def print_result(self, res):
|
||||||
''' Print retrieved result to the output '''
|
"""
|
||||||
|
Print retrieved result to the output
|
||||||
|
"""
|
||||||
if res is not None:
|
if res is not None:
|
||||||
if self.command in ('open_chat', 'send_chat_message', 'send_single_message', 'start_chat'):
|
if self.command in ('open_chat', 'send_chat_message', 'send_single_message', 'start_chat'):
|
||||||
if self.command in ('send_message', 'send_single_message'):
|
if self.command in ('send_message', 'send_single_message'):
|
||||||
|
@ -382,8 +383,9 @@ class GajimRemote:
|
||||||
return test
|
return test
|
||||||
|
|
||||||
def init_connection(self):
|
def init_connection(self):
|
||||||
''' create the onnection to the session dbus,
|
"""
|
||||||
or exit if it is not possible '''
|
Create the onnection to the session dbus, or exit if it is not possible
|
||||||
|
"""
|
||||||
try:
|
try:
|
||||||
self.sbus = dbus.SessionBus()
|
self.sbus = dbus.SessionBus()
|
||||||
except Exception:
|
except Exception:
|
||||||
|
@ -398,8 +400,10 @@ class GajimRemote:
|
||||||
self.method = interface.__getattr__(self.command)
|
self.method = interface.__getattr__(self.command)
|
||||||
|
|
||||||
def make_arguments_row(self, args):
|
def make_arguments_row(self, args):
|
||||||
''' return arguments list. Mandatory arguments are enclosed with:
|
"""
|
||||||
'<', '>', optional arguments - with '[', ']' '''
|
Return arguments list. Mandatory arguments are enclosed with:
|
||||||
|
'<', '>', optional arguments - with '[', ']'
|
||||||
|
"""
|
||||||
s = ''
|
s = ''
|
||||||
for arg in args:
|
for arg in args:
|
||||||
if arg[2]:
|
if arg[2]:
|
||||||
|
@ -409,7 +413,9 @@ class GajimRemote:
|
||||||
return s
|
return s
|
||||||
|
|
||||||
def help_on_command(self, command):
|
def help_on_command(self, command):
|
||||||
''' return help message for a given command '''
|
"""
|
||||||
|
Return help message for a given command
|
||||||
|
"""
|
||||||
if command in self.commands:
|
if command in self.commands:
|
||||||
command_props = self.commands[command]
|
command_props = self.commands[command]
|
||||||
arguments_str = self.make_arguments_row(command_props[1])
|
arguments_str = self.make_arguments_row(command_props[1])
|
||||||
|
@ -424,7 +430,9 @@ class GajimRemote:
|
||||||
send_error(_('%s not found') % command)
|
send_error(_('%s not found') % command)
|
||||||
|
|
||||||
def compose_help(self):
|
def compose_help(self):
|
||||||
''' print usage, and list available commands '''
|
"""
|
||||||
|
Print usage, and list available commands
|
||||||
|
"""
|
||||||
s = _('Usage: %s command [arguments]\nCommand is one of:\n' ) % BASENAME
|
s = _('Usage: %s command [arguments]\nCommand is one of:\n' ) % BASENAME
|
||||||
for command in sorted(self.commands):
|
for command in sorted(self.commands):
|
||||||
s += ' ' + command
|
s += ' ' + command
|
||||||
|
@ -437,7 +445,9 @@ class GajimRemote:
|
||||||
return s
|
return s
|
||||||
|
|
||||||
def print_info(self, level, prop_dict, encode_return = False):
|
def print_info(self, level, prop_dict, encode_return = False):
|
||||||
''' return formated string from data structure '''
|
"""
|
||||||
|
Return formated string from data structure
|
||||||
|
"""
|
||||||
if prop_dict is None or not isinstance(prop_dict, (dict, list, tuple)):
|
if prop_dict is None or not isinstance(prop_dict, (dict, list, tuple)):
|
||||||
return ''
|
return ''
|
||||||
ret_str = ''
|
ret_str = ''
|
||||||
|
@ -486,7 +496,9 @@ class GajimRemote:
|
||||||
return ret_str
|
return ret_str
|
||||||
|
|
||||||
def check_arguments(self):
|
def check_arguments(self):
|
||||||
''' Make check if all necessary arguments are given '''
|
"""
|
||||||
|
Make check if all necessary arguments are given
|
||||||
|
"""
|
||||||
argv_len = self.argv_len - 2
|
argv_len = self.argv_len - 2
|
||||||
args = self.commands[self.command][1]
|
args = self.commands[self.command][1]
|
||||||
if len(args) < argv_len:
|
if len(args) < argv_len:
|
||||||
|
@ -559,7 +571,9 @@ class GajimRemote:
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
|
|
||||||
def call_remote_method(self):
|
def call_remote_method(self):
|
||||||
''' calls self.method with arguments from sys.argv[2:] '''
|
"""
|
||||||
|
Calls self.method with arguments from sys.argv[2:]
|
||||||
|
"""
|
||||||
args = [i.decode(PREFERRED_ENCODING) for i in self.arguments]
|
args = [i.decode(PREFERRED_ENCODING) for i in self.arguments]
|
||||||
args = [dbus.String(i) for i in args]
|
args = [dbus.String(i) for i in args]
|
||||||
try:
|
try:
|
||||||
|
|
|
@ -275,7 +275,9 @@ class GajimThemesWindow:
|
||||||
self._set_font()
|
self._set_font()
|
||||||
|
|
||||||
def _set_color(self, state, widget, option):
|
def _set_color(self, state, widget, option):
|
||||||
''' set color value in prefs and update the UI '''
|
"""
|
||||||
|
Set color value in prefs and update the UI
|
||||||
|
"""
|
||||||
if state:
|
if state:
|
||||||
color = widget.get_color()
|
color = widget.get_color()
|
||||||
color_string = gtkgui_helpers.make_color_string(color)
|
color_string = gtkgui_helpers.make_color_string(color)
|
||||||
|
@ -297,7 +299,9 @@ class GajimThemesWindow:
|
||||||
gajim.interface.save_config()
|
gajim.interface.save_config()
|
||||||
|
|
||||||
def _set_font(self):
|
def _set_font(self):
|
||||||
''' set font value in prefs and update the UI '''
|
"""
|
||||||
|
Set font value in prefs and update the UI
|
||||||
|
"""
|
||||||
state = self.textfont_checkbutton.get_active()
|
state = self.textfont_checkbutton.get_active()
|
||||||
if state:
|
if state:
|
||||||
font_string = self.text_fontbutton.get_font_name()
|
font_string = self.text_fontbutton.get_font_name()
|
||||||
|
@ -317,13 +321,16 @@ class GajimThemesWindow:
|
||||||
gajim.interface.save_config()
|
gajim.interface.save_config()
|
||||||
|
|
||||||
def _toggle_font_widgets(self, font_props):
|
def _toggle_font_widgets(self, font_props):
|
||||||
''' toggle font buttons with the bool values of font_props tuple'''
|
"""
|
||||||
|
Toggle font buttons with the bool values of font_props tuple
|
||||||
|
"""
|
||||||
self.bold_togglebutton.set_active(font_props[0])
|
self.bold_togglebutton.set_active(font_props[0])
|
||||||
self.italic_togglebutton.set_active(font_props[1])
|
self.italic_togglebutton.set_active(font_props[1])
|
||||||
|
|
||||||
def _get_font_description(self):
|
def _get_font_description(self):
|
||||||
''' return a FontDescription from togglebuttons
|
"""
|
||||||
states'''
|
Return a FontDescription from togglebuttons states
|
||||||
|
"""
|
||||||
fd = pango.FontDescription()
|
fd = pango.FontDescription()
|
||||||
if self.bold_togglebutton.get_active():
|
if self.bold_togglebutton.get_active():
|
||||||
fd.set_weight(pango.WEIGHT_BOLD)
|
fd.set_weight(pango.WEIGHT_BOLD)
|
||||||
|
@ -332,8 +339,10 @@ class GajimThemesWindow:
|
||||||
return fd
|
return fd
|
||||||
|
|
||||||
def _set_font_widgets(self, font_attrs):
|
def _set_font_widgets(self, font_attrs):
|
||||||
''' set the correct toggle state of font style buttons by
|
"""
|
||||||
a font string of type 'BI' '''
|
Set the correct toggle state of font style buttons by a font string of
|
||||||
|
type 'BI'
|
||||||
|
"""
|
||||||
font_props = [False, False, False]
|
font_props = [False, False, False]
|
||||||
if font_attrs:
|
if font_attrs:
|
||||||
if font_attrs.find('B') != -1:
|
if font_attrs.find('B') != -1:
|
||||||
|
@ -343,7 +352,9 @@ class GajimThemesWindow:
|
||||||
self._toggle_font_widgets(font_props)
|
self._toggle_font_widgets(font_props)
|
||||||
|
|
||||||
def _get_font_attrs(self):
|
def _get_font_attrs(self):
|
||||||
''' get a string with letters of font attribures: 'BI' '''
|
"""
|
||||||
|
Get a string with letters of font attribures: 'BI'
|
||||||
|
"""
|
||||||
attrs = ''
|
attrs = ''
|
||||||
if self.bold_togglebutton.get_active():
|
if self.bold_togglebutton.get_active():
|
||||||
attrs += 'B'
|
attrs += 'B'
|
||||||
|
@ -353,7 +364,9 @@ class GajimThemesWindow:
|
||||||
|
|
||||||
|
|
||||||
def _get_font_props(self, font_name):
|
def _get_font_props(self, font_name):
|
||||||
''' get tuple of font properties: Weight, Style '''
|
"""
|
||||||
|
Get tuple of font properties: weight, style
|
||||||
|
"""
|
||||||
font_props = [False, False, False]
|
font_props = [False, False, False]
|
||||||
font_description = pango.FontDescription(font_name)
|
font_description = pango.FontDescription(font_name)
|
||||||
if font_description.get_weight() != pango.WEIGHT_NORMAL:
|
if font_description.get_weight() != pango.WEIGHT_NORMAL:
|
||||||
|
|
|
@ -26,7 +26,10 @@ import gtkgui_helpers
|
||||||
|
|
||||||
class GroupsPostWindow:
|
class GroupsPostWindow:
|
||||||
def __init__(self, account, servicejid, groupid):
|
def __init__(self, account, servicejid, groupid):
|
||||||
'''Open new 'create post' window to create message for groupid on servicejid service.'''
|
"""
|
||||||
|
Open new 'create post' window to create message for groupid on servicejid
|
||||||
|
service
|
||||||
|
"""
|
||||||
assert isinstance(servicejid, basestring)
|
assert isinstance(servicejid, basestring)
|
||||||
assert isinstance(groupid, basestring)
|
assert isinstance(groupid, basestring)
|
||||||
|
|
||||||
|
@ -43,11 +46,15 @@ class GroupsPostWindow:
|
||||||
self.window.show_all()
|
self.window.show_all()
|
||||||
|
|
||||||
def on_cancel_button_clicked(self, w):
|
def on_cancel_button_clicked(self, w):
|
||||||
'''Close window.'''
|
"""
|
||||||
|
Close window
|
||||||
|
"""
|
||||||
self.window.destroy()
|
self.window.destroy()
|
||||||
|
|
||||||
def on_send_button_clicked(self, w):
|
def on_send_button_clicked(self, w):
|
||||||
'''Gather info from widgets and send it as a message.'''
|
"""
|
||||||
|
Gather info from widgets and send it as a message
|
||||||
|
"""
|
||||||
# constructing item to publish... that's atom:entry element
|
# constructing item to publish... that's atom:entry element
|
||||||
item = xmpp.Node('entry', {'xmlns':'http://www.w3.org/2005/Atom'})
|
item = xmpp.Node('entry', {'xmlns':'http://www.w3.org/2005/Atom'})
|
||||||
author = item.addChild('author')
|
author = item.addChild('author')
|
||||||
|
|
|
@ -67,8 +67,10 @@ def get_glade(file_name, root = None):
|
||||||
return gtk.glade.XML(file_path, root=root, domain=i18n.APP)
|
return gtk.glade.XML(file_path, root=root, domain=i18n.APP)
|
||||||
|
|
||||||
def get_completion_liststore(entry):
|
def get_completion_liststore(entry):
|
||||||
''' create a completion model for entry widget
|
"""
|
||||||
completion list consists of (Pixbuf, Text) rows'''
|
Create a completion model for entry widget completion list consists of
|
||||||
|
(Pixbuf, Text) rows
|
||||||
|
"""
|
||||||
completion = gtk.EntryCompletion()
|
completion = gtk.EntryCompletion()
|
||||||
liststore = gtk.ListStore(gtk.gdk.Pixbuf, str)
|
liststore = gtk.ListStore(gtk.gdk.Pixbuf, str)
|
||||||
|
|
||||||
|
@ -86,7 +88,9 @@ def get_completion_liststore(entry):
|
||||||
|
|
||||||
|
|
||||||
def popup_emoticons_under_button(menu, button, parent_win):
|
def popup_emoticons_under_button(menu, button, parent_win):
|
||||||
''' pops emoticons menu under button, which is in parent_win'''
|
"""
|
||||||
|
Popup the emoticons menu under button, which is in parent_win
|
||||||
|
"""
|
||||||
window_x1, window_y1 = parent_win.get_origin()
|
window_x1, window_y1 = parent_win.get_origin()
|
||||||
def position_menu_under_button(menu):
|
def position_menu_under_button(menu):
|
||||||
# inline function, which will not keep refs, when used as CB
|
# inline function, which will not keep refs, when used as CB
|
||||||
|
@ -115,8 +119,9 @@ def popup_emoticons_under_button(menu, button, parent_win):
|
||||||
menu.popup(None, None, position_menu_under_button, 1, 0)
|
menu.popup(None, None, position_menu_under_button, 1, 0)
|
||||||
|
|
||||||
def get_theme_font_for_option(theme, option):
|
def get_theme_font_for_option(theme, option):
|
||||||
'''return string description of the font, stored in
|
"""
|
||||||
theme preferences'''
|
Return string description of the font, stored in theme preferences
|
||||||
|
"""
|
||||||
font_name = gajim.config.get_per('themes', theme, option)
|
font_name = gajim.config.get_per('themes', theme, option)
|
||||||
font_desc = pango.FontDescription()
|
font_desc = pango.FontDescription()
|
||||||
font_prop_str = gajim.config.get_per('themes', theme, option + 'attrs')
|
font_prop_str = gajim.config.get_per('themes', theme, option + 'attrs')
|
||||||
|
@ -130,10 +135,10 @@ def get_theme_font_for_option(theme, option):
|
||||||
return fd.to_string()
|
return fd.to_string()
|
||||||
|
|
||||||
def get_default_font():
|
def get_default_font():
|
||||||
'''Get the desktop setting for application font
|
"""
|
||||||
first check for GNOME, then Xfce and last KDE
|
Get the desktop setting for application font first check for GNOME, then
|
||||||
it returns None on failure or else a string 'Font Size' '''
|
Xfce and last KDE it returns None on failure or else a string 'Font Size'
|
||||||
|
"""
|
||||||
try:
|
try:
|
||||||
import gconf
|
import gconf
|
||||||
# in try because daemon may not be there
|
# in try because daemon may not be there
|
||||||
|
@ -206,7 +211,9 @@ def user_runs_xfce():
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def get_running_processes():
|
def get_running_processes():
|
||||||
'''returns running processes or None (if not /proc exists)'''
|
"""
|
||||||
|
Return running processes or None (if /proc does not exist)
|
||||||
|
"""
|
||||||
if os.path.isdir('/proc'):
|
if os.path.isdir('/proc'):
|
||||||
# under Linux: checking if 'gnome-session' or
|
# under Linux: checking if 'gnome-session' or
|
||||||
# 'startkde' programs were run before gajim, by
|
# 'startkde' programs were run before gajim, by
|
||||||
|
@ -241,7 +248,9 @@ def get_running_processes():
|
||||||
return []
|
return []
|
||||||
|
|
||||||
def move_window(window, x, y):
|
def move_window(window, x, y):
|
||||||
'''moves the window but also checks if out of screen'''
|
"""
|
||||||
|
Move the window, but also check if out of screen
|
||||||
|
"""
|
||||||
if x < 0:
|
if x < 0:
|
||||||
x = 0
|
x = 0
|
||||||
if y < 0:
|
if y < 0:
|
||||||
|
@ -254,7 +263,9 @@ def move_window(window, x, y):
|
||||||
window.move(x, y)
|
window.move(x, y)
|
||||||
|
|
||||||
def resize_window(window, w, h):
|
def resize_window(window, w, h):
|
||||||
'''resizes window but also checks if huge window or negative values'''
|
"""
|
||||||
|
Resize window, but also checks if huge window or negative values
|
||||||
|
"""
|
||||||
if not w or not h:
|
if not w or not h:
|
||||||
return
|
return
|
||||||
if w > screen_w:
|
if w > screen_w:
|
||||||
|
@ -354,8 +365,10 @@ def parse_server_xml(path_to_file):
|
||||||
print >> sys.stderr, _('Error parsing file:'), message
|
print >> sys.stderr, _('Error parsing file:'), message
|
||||||
|
|
||||||
def set_unset_urgency_hint(window, unread_messages_no):
|
def set_unset_urgency_hint(window, unread_messages_no):
|
||||||
'''sets/unsets urgency hint in window argument
|
"""
|
||||||
depending if we have unread messages or not'''
|
Sets/unset urgency hint in window argument depending if we have unread
|
||||||
|
messages or not
|
||||||
|
"""
|
||||||
if gajim.config.get('use_urgency_hint'):
|
if gajim.config.get('use_urgency_hint'):
|
||||||
if unread_messages_no > 0:
|
if unread_messages_no > 0:
|
||||||
window.props.urgency_hint = True
|
window.props.urgency_hint = True
|
||||||
|
@ -363,8 +376,10 @@ def set_unset_urgency_hint(window, unread_messages_no):
|
||||||
window.props.urgency_hint = False
|
window.props.urgency_hint = False
|
||||||
|
|
||||||
def get_abspath_for_script(scriptname, want_type = False):
|
def get_abspath_for_script(scriptname, want_type = False):
|
||||||
'''checks if we are svn or normal user and returns abspath to asked script
|
"""
|
||||||
if want_type is True we return 'svn' or 'install' '''
|
Check if we are svn or normal user and return abspath to asked script if
|
||||||
|
want_type is True we return 'svn' or 'install'
|
||||||
|
"""
|
||||||
if os.path.isdir('.svn'): # we are svn user
|
if os.path.isdir('.svn'): # we are svn user
|
||||||
type_ = 'svn'
|
type_ = 'svn'
|
||||||
cwd = os.getcwd() # it's always ending with src
|
cwd = os.getcwd() # it's always ending with src
|
||||||
|
@ -403,8 +418,10 @@ def get_abspath_for_script(scriptname, want_type = False):
|
||||||
return path_to_script
|
return path_to_script
|
||||||
|
|
||||||
def get_pixbuf_from_data(file_data, want_type = False):
|
def get_pixbuf_from_data(file_data, want_type = False):
|
||||||
'''Gets image data and returns gtk.gdk.Pixbuf
|
"""
|
||||||
if want_type is True it also returns 'jpeg', 'png' etc'''
|
Get image data and returns gtk.gdk.Pixbuf if want_type is True it also
|
||||||
|
returns 'jpeg', 'png' etc
|
||||||
|
"""
|
||||||
pixbufloader = gtk.gdk.PixbufLoader()
|
pixbufloader = gtk.gdk.PixbufLoader()
|
||||||
try:
|
try:
|
||||||
pixbufloader.write(file_data)
|
pixbufloader.write(file_data)
|
||||||
|
@ -431,8 +448,11 @@ def get_invisible_cursor():
|
||||||
return cursor
|
return cursor
|
||||||
|
|
||||||
def get_current_desktop(window):
|
def get_current_desktop(window):
|
||||||
'''returns the current virtual desktop for given window
|
"""
|
||||||
NOTE: window is GDK window'''
|
Return the current virtual desktop for given window
|
||||||
|
|
||||||
|
NOTE: Window is a GDK window.
|
||||||
|
"""
|
||||||
prop = window.property_get('_NET_CURRENT_DESKTOP')
|
prop = window.property_get('_NET_CURRENT_DESKTOP')
|
||||||
if prop is None: # it means it's normal window (not root window)
|
if prop is None: # it means it's normal window (not root window)
|
||||||
# so we look for it's current virtual desktop in another property
|
# so we look for it's current virtual desktop in another property
|
||||||
|
@ -444,9 +464,12 @@ def get_current_desktop(window):
|
||||||
return current_virtual_desktop_no
|
return current_virtual_desktop_no
|
||||||
|
|
||||||
def possibly_move_window_in_current_desktop(window):
|
def possibly_move_window_in_current_desktop(window):
|
||||||
'''moves GTK window to current virtual desktop if it is not in the
|
"""
|
||||||
current virtual desktop
|
Moves GTK window to current virtual desktop if it is not in the current
|
||||||
window is GTK window'''
|
virtual desktop
|
||||||
|
|
||||||
|
NOTE: Window is a GDK window.
|
||||||
|
"""
|
||||||
if os.name == 'nt':
|
if os.name == 'nt':
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
@ -468,7 +491,11 @@ def possibly_move_window_in_current_desktop(window):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def file_is_locked(path_to_file):
|
def file_is_locked(path_to_file):
|
||||||
'''returns True if file is locked (WINDOWS ONLY)'''
|
"""
|
||||||
|
Return True if file is locked
|
||||||
|
|
||||||
|
NOTE: Windows only.
|
||||||
|
"""
|
||||||
if os.name != 'nt': # just in case
|
if os.name != 'nt': # just in case
|
||||||
return
|
return
|
||||||
|
|
||||||
|
@ -496,8 +523,10 @@ def file_is_locked(path_to_file):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def _get_fade_color(treeview, selected, focused):
|
def _get_fade_color(treeview, selected, focused):
|
||||||
'''get a gdk color that is between foreground and background in 0.3
|
"""
|
||||||
0.7 respectively colors of the cell for the given treeview'''
|
Get a gdk color that is between foreground and background in 0.3
|
||||||
|
0.7 respectively colors of the cell for the given treeview
|
||||||
|
"""
|
||||||
style = treeview.style
|
style = treeview.style
|
||||||
if selected:
|
if selected:
|
||||||
if focused: # is the window focused?
|
if focused: # is the window focused?
|
||||||
|
@ -516,9 +545,10 @@ def _get_fade_color(treeview, selected, focused):
|
||||||
int(bg.blue*p + fg.blue*q))
|
int(bg.blue*p + fg.blue*q))
|
||||||
|
|
||||||
def get_scaled_pixbuf(pixbuf, kind):
|
def get_scaled_pixbuf(pixbuf, kind):
|
||||||
'''returns scaled pixbuf, keeping ratio etc or None
|
"""
|
||||||
kind is either "chat", "roster", "notification", "tooltip", "vcard"'''
|
Return scaled pixbuf, keeping ratio etc or None kind is either "chat",
|
||||||
|
"roster", "notification", "tooltip", "vcard"
|
||||||
|
"""
|
||||||
# resize to a width / height for the avatar not to have distortion
|
# resize to a width / height for the avatar not to have distortion
|
||||||
# (keep aspect ratio)
|
# (keep aspect ratio)
|
||||||
width = gajim.config.get(kind + '_avatar_width')
|
width = gajim.config.get(kind + '_avatar_width')
|
||||||
|
@ -544,12 +574,14 @@ def get_scaled_pixbuf(pixbuf, kind):
|
||||||
return scaled_buf
|
return scaled_buf
|
||||||
|
|
||||||
def get_avatar_pixbuf_from_cache(fjid, is_fake_jid = False, use_local = True):
|
def get_avatar_pixbuf_from_cache(fjid, is_fake_jid = False, use_local = True):
|
||||||
'''checks if jid has cached avatar and if that avatar is valid image
|
"""
|
||||||
(can be shown)
|
Check if jid has cached avatar and if that avatar is valid image (can be
|
||||||
returns None if there is no image in vcard
|
shown)
|
||||||
returns 'ask' if cached vcard should not be used (user changed his vcard,
|
|
||||||
so we have new sha) or if we don't have the vcard'''
|
|
||||||
|
|
||||||
|
Returns None if there is no image in vcard/
|
||||||
|
Returns 'ask' if cached vcard should not be used (user changed his vcard, so
|
||||||
|
we have new sha) or if we don't have the vcard
|
||||||
|
"""
|
||||||
jid, nick = gajim.get_room_and_nick_from_fjid(fjid)
|
jid, nick = gajim.get_room_and_nick_from_fjid(fjid)
|
||||||
if gajim.config.get('hide_avatar_of_transport') and\
|
if gajim.config.get('hide_avatar_of_transport') and\
|
||||||
gajim.jid_is_transport(jid):
|
gajim.jid_is_transport(jid):
|
||||||
|
@ -588,16 +620,21 @@ def get_avatar_pixbuf_from_cache(fjid, is_fake_jid = False, use_local = True):
|
||||||
return pixbuf
|
return pixbuf
|
||||||
|
|
||||||
def make_gtk_month_python_month(month):
|
def make_gtk_month_python_month(month):
|
||||||
'''gtk start counting months from 0, so January is 0
|
"""
|
||||||
but python's time start from 1, so align to python
|
GTK starts counting months from 0, so January is 0 but Python's time start
|
||||||
month MUST be integer'''
|
from 1, so align to Python
|
||||||
|
|
||||||
|
NOTE: Month MUST be an integer.
|
||||||
|
"""
|
||||||
return month + 1
|
return month + 1
|
||||||
|
|
||||||
def make_python_month_gtk_month(month):
|
def make_python_month_gtk_month(month):
|
||||||
return month - 1
|
return month - 1
|
||||||
|
|
||||||
def make_color_string(color):
|
def make_color_string(color):
|
||||||
'''create #aabbcc color string from gtk color'''
|
"""
|
||||||
|
Create #aabbcc color string from gtk color
|
||||||
|
"""
|
||||||
col = '#'
|
col = '#'
|
||||||
for i in ('red', 'green', 'blue'):
|
for i in ('red', 'green', 'blue'):
|
||||||
h = hex(getattr(color, i) / (16*16)).split('x')[1]
|
h = hex(getattr(color, i) / (16*16)).split('x')[1]
|
||||||
|
@ -612,10 +649,12 @@ def make_pixbuf_grayscale(pixbuf):
|
||||||
return pixbuf2
|
return pixbuf2
|
||||||
|
|
||||||
def get_path_to_generic_or_avatar(generic, jid = None, suffix = None):
|
def get_path_to_generic_or_avatar(generic, jid = None, suffix = None):
|
||||||
'''Chooses between avatar image and default image.
|
"""
|
||||||
Returns full path to the avatar image if it exists,
|
Choose between avatar image and default image
|
||||||
otherwise returns full path to the image.
|
|
||||||
generic must be with extension and suffix without'''
|
Returns full path to the avatar image if it exists, otherwise returns full
|
||||||
|
path to the image. generic must be with extension and suffix without
|
||||||
|
"""
|
||||||
if jid:
|
if jid:
|
||||||
# we want an avatar
|
# we want an avatar
|
||||||
puny_jid = helpers.sanitize_filename(jid)
|
puny_jid = helpers.sanitize_filename(jid)
|
||||||
|
@ -632,9 +671,10 @@ def get_path_to_generic_or_avatar(generic, jid = None, suffix = None):
|
||||||
return os.path.abspath(generic)
|
return os.path.abspath(generic)
|
||||||
|
|
||||||
def decode_filechooser_file_paths(file_paths):
|
def decode_filechooser_file_paths(file_paths):
|
||||||
'''decode as UTF-8 under Windows and
|
"""
|
||||||
ask sys.getfilesystemencoding() in POSIX
|
Decode as UTF-8 under Windows and ask sys.getfilesystemencoding() in POSIX
|
||||||
file_paths MUST be LIST'''
|
file_paths MUST be LIST
|
||||||
|
"""
|
||||||
file_paths_list = list()
|
file_paths_list = list()
|
||||||
|
|
||||||
if os.name == 'nt': # decode as UTF-8 under Windows
|
if os.name == 'nt': # decode as UTF-8 under Windows
|
||||||
|
@ -655,7 +695,9 @@ def decode_filechooser_file_paths(file_paths):
|
||||||
return file_paths_list
|
return file_paths_list
|
||||||
|
|
||||||
def possibly_set_gajim_as_xmpp_handler():
|
def possibly_set_gajim_as_xmpp_handler():
|
||||||
'''registers (by default only the first time) xmmp: to Gajim.'''
|
"""
|
||||||
|
Register (by default only the first time) 'xmmp:' to Gajim
|
||||||
|
"""
|
||||||
path_to_dot_kde = os.path.expanduser('~/.kde')
|
path_to_dot_kde = os.path.expanduser('~/.kde')
|
||||||
if os.path.exists(path_to_dot_kde):
|
if os.path.exists(path_to_dot_kde):
|
||||||
path_to_kde_file = os.path.join(path_to_dot_kde,
|
path_to_kde_file = os.path.join(path_to_dot_kde,
|
||||||
|
@ -737,8 +779,10 @@ Description=xmpp
|
||||||
dlg.checkbutton.set_active(True)
|
dlg.checkbutton.set_active(True)
|
||||||
|
|
||||||
def escape_underscore(s):
|
def escape_underscore(s):
|
||||||
'''Escape underlines to prevent them from being interpreted
|
"""
|
||||||
as keyboard accelerators'''
|
Escape underlines to prevent them from being interpreted as keyboard
|
||||||
|
accelerators
|
||||||
|
"""
|
||||||
return s.replace('_', '__')
|
return s.replace('_', '__')
|
||||||
|
|
||||||
def get_state_image_from_file_path_show(file_path, show):
|
def get_state_image_from_file_path_show(file_path, show):
|
||||||
|
@ -756,7 +800,9 @@ def get_state_image_from_file_path_show(file_path, show):
|
||||||
return image
|
return image
|
||||||
|
|
||||||
def get_possible_button_event(event):
|
def get_possible_button_event(event):
|
||||||
'''mouse or keyboard caused the event?'''
|
"""
|
||||||
|
Mouse or keyboard caused the event?
|
||||||
|
"""
|
||||||
if event.type == gtk.gdk.KEY_PRESS:
|
if event.type == gtk.gdk.KEY_PRESS:
|
||||||
return 0 # no event.button so pass 0
|
return 0 # no event.button so pass 0
|
||||||
# BUTTON_PRESS event, so pass event.button
|
# BUTTON_PRESS event, so pass event.button
|
||||||
|
@ -847,7 +893,9 @@ def on_bm_header_changed_state(widget, event):
|
||||||
widget.set_state(gtk.STATE_NORMAL) #do not allow selected_state
|
widget.set_state(gtk.STATE_NORMAL) #do not allow selected_state
|
||||||
|
|
||||||
def create_combobox(value_list, selected_value = None):
|
def create_combobox(value_list, selected_value = None):
|
||||||
'''Value_list is [(label1, value1), ]'''
|
"""
|
||||||
|
Value_list is [(label1, value1)]
|
||||||
|
"""
|
||||||
liststore = gtk.ListStore(str, str)
|
liststore = gtk.ListStore(str, str)
|
||||||
combobox = gtk.ComboBox(liststore)
|
combobox = gtk.ComboBox(liststore)
|
||||||
cell = gtk.CellRendererText()
|
cell = gtk.CellRendererText()
|
||||||
|
@ -864,7 +912,9 @@ def create_combobox(value_list, selected_value = None):
|
||||||
return combobox
|
return combobox
|
||||||
|
|
||||||
def create_list_multi(value_list, selected_values=None):
|
def create_list_multi(value_list, selected_values=None):
|
||||||
'''Value_list is [(label1, value1), ]'''
|
"""
|
||||||
|
Value_list is [(label1, value1)]
|
||||||
|
"""
|
||||||
liststore = gtk.ListStore(str, str)
|
liststore = gtk.ListStore(str, str)
|
||||||
treeview = gtk.TreeView(liststore)
|
treeview = gtk.TreeView(liststore)
|
||||||
treeview.get_selection().set_mode(gtk.SELECTION_MULTIPLE)
|
treeview.get_selection().set_mode(gtk.SELECTION_MULTIPLE)
|
||||||
|
@ -882,8 +932,10 @@ def create_list_multi(value_list, selected_values=None):
|
||||||
return treeview
|
return treeview
|
||||||
|
|
||||||
def load_iconset(path, pixbuf2=None, transport=False):
|
def load_iconset(path, pixbuf2=None, transport=False):
|
||||||
'''load full iconset from the given path, and add
|
"""
|
||||||
pixbuf2 on top left of each static images'''
|
Load full iconset from the given path, and add pixbuf2 on top left of each
|
||||||
|
static images
|
||||||
|
"""
|
||||||
path += '/'
|
path += '/'
|
||||||
if transport:
|
if transport:
|
||||||
list_ = ('online', 'chat', 'away', 'xa', 'dnd', 'offline',
|
list_ = ('online', 'chat', 'away', 'xa', 'dnd', 'offline',
|
||||||
|
@ -898,21 +950,27 @@ def load_iconset(path, pixbuf2=None, transport=False):
|
||||||
return _load_icon_list(list_, path, pixbuf2)
|
return _load_icon_list(list_, path, pixbuf2)
|
||||||
|
|
||||||
def load_icon(icon_name):
|
def load_icon(icon_name):
|
||||||
'''load an icon from the iconset in 16x16'''
|
"""
|
||||||
|
Load an icon from the iconset in 16x16
|
||||||
|
"""
|
||||||
iconset = gajim.config.get('iconset')
|
iconset = gajim.config.get('iconset')
|
||||||
path = os.path.join(helpers.get_iconset_path(iconset), '16x16', '')
|
path = os.path.join(helpers.get_iconset_path(iconset), '16x16', '')
|
||||||
icon_list = _load_icon_list([icon_name], path)
|
icon_list = _load_icon_list([icon_name], path)
|
||||||
return icon_list[icon_name]
|
return icon_list[icon_name]
|
||||||
|
|
||||||
def load_mood_icon(icon_name):
|
def load_mood_icon(icon_name):
|
||||||
'''load an icon from the mood iconset in 16x16'''
|
"""
|
||||||
|
Load an icon from the mood iconset in 16x16
|
||||||
|
"""
|
||||||
iconset = gajim.config.get('mood_iconset')
|
iconset = gajim.config.get('mood_iconset')
|
||||||
path = os.path.join(helpers.get_mood_iconset_path(iconset), '')
|
path = os.path.join(helpers.get_mood_iconset_path(iconset), '')
|
||||||
icon_list = _load_icon_list([icon_name], path)
|
icon_list = _load_icon_list([icon_name], path)
|
||||||
return icon_list[icon_name]
|
return icon_list[icon_name]
|
||||||
|
|
||||||
def load_activity_icon(category, activity = None):
|
def load_activity_icon(category, activity = None):
|
||||||
'''load an icon from the activity iconset in 16x16'''
|
"""
|
||||||
|
Load an icon from the activity iconset in 16x16
|
||||||
|
"""
|
||||||
iconset = gajim.config.get('activity_iconset')
|
iconset = gajim.config.get('activity_iconset')
|
||||||
path = os.path.join(helpers.get_activity_iconset_path(iconset),
|
path = os.path.join(helpers.get_activity_iconset_path(iconset),
|
||||||
category, '')
|
category, '')
|
||||||
|
@ -922,8 +980,10 @@ def load_activity_icon(category, activity = None):
|
||||||
return icon_list[activity]
|
return icon_list[activity]
|
||||||
|
|
||||||
def load_icons_meta():
|
def load_icons_meta():
|
||||||
'''load and return - AND + small icons to put on top left of an icon
|
"""
|
||||||
for meta contacts.'''
|
Load and return - AND + small icons to put on top left of an icon for meta
|
||||||
|
contacts
|
||||||
|
"""
|
||||||
iconset = gajim.config.get('iconset')
|
iconset = gajim.config.get('iconset')
|
||||||
path = os.path.join(helpers.get_iconset_path(iconset), '16x16')
|
path = os.path.join(helpers.get_iconset_path(iconset), '16x16')
|
||||||
# try to find opened_meta.png file, else opened.png else nopixbuf merge
|
# try to find opened_meta.png file, else opened.png else nopixbuf merge
|
||||||
|
@ -945,8 +1005,10 @@ def load_icons_meta():
|
||||||
return pixo, pixc
|
return pixo, pixc
|
||||||
|
|
||||||
def _load_icon_list(icons_list, path, pixbuf2 = None):
|
def _load_icon_list(icons_list, path, pixbuf2 = None):
|
||||||
'''load icons in icons_list from the given path,
|
"""
|
||||||
and add pixbuf2 on top left of each static images'''
|
Load icons in icons_list from the given path, and add pixbuf2 on top left of
|
||||||
|
each static images
|
||||||
|
"""
|
||||||
imgs = {}
|
imgs = {}
|
||||||
for icon in icons_list:
|
for icon in icons_list:
|
||||||
# try to open a pixfile with the correct method
|
# try to open a pixfile with the correct method
|
||||||
|
@ -972,7 +1034,9 @@ def _load_icon_list(icons_list, path, pixbuf2 = None):
|
||||||
return imgs
|
return imgs
|
||||||
|
|
||||||
def make_jabber_state_images():
|
def make_jabber_state_images():
|
||||||
'''initialise jabber_state_images dict'''
|
"""
|
||||||
|
Initialize jabber_state_images dictionary
|
||||||
|
"""
|
||||||
iconset = gajim.config.get('iconset')
|
iconset = gajim.config.get('iconset')
|
||||||
if iconset:
|
if iconset:
|
||||||
if helpers.get_iconset_path(iconset):
|
if helpers.get_iconset_path(iconset):
|
||||||
|
@ -1002,8 +1066,10 @@ def reload_jabber_state_images():
|
||||||
gajim.interface.roster.update_jabber_state_images()
|
gajim.interface.roster.update_jabber_state_images()
|
||||||
|
|
||||||
def label_set_autowrap(widget):
|
def label_set_autowrap(widget):
|
||||||
'''Make labels automatically re-wrap if their containers are resized.
|
"""
|
||||||
Accepts label or container widgets.'''
|
Make labels automatically re-wrap if their containers are resized.
|
||||||
|
Accepts label or container widgets
|
||||||
|
"""
|
||||||
if isinstance (widget, gtk.Container):
|
if isinstance (widget, gtk.Container):
|
||||||
children = widget.get_children()
|
children = widget.get_children()
|
||||||
for i in xrange (len (children)):
|
for i in xrange (len (children)):
|
||||||
|
@ -1013,7 +1079,9 @@ def label_set_autowrap(widget):
|
||||||
widget.connect_after('size-allocate', __label_size_allocate)
|
widget.connect_after('size-allocate', __label_size_allocate)
|
||||||
|
|
||||||
def __label_size_allocate(widget, allocation):
|
def __label_size_allocate(widget, allocation):
|
||||||
'''Callback which re-allocates the size of a label.'''
|
"""
|
||||||
|
Callback which re-allocates the size of a label
|
||||||
|
"""
|
||||||
layout = widget.get_layout()
|
layout = widget.get_layout()
|
||||||
|
|
||||||
lw_old, lh_old = layout.get_size()
|
lw_old, lh_old = layout.get_size()
|
||||||
|
|
|
@ -54,7 +54,6 @@ if dbus_support.supported:
|
||||||
|
|
||||||
import gtkgui_helpers
|
import gtkgui_helpers
|
||||||
|
|
||||||
|
|
||||||
import dialogs
|
import dialogs
|
||||||
import notify
|
import notify
|
||||||
import message_control
|
import message_control
|
||||||
|
@ -92,7 +91,6 @@ config_filename = gajimpaths['CONFIG_FILE']
|
||||||
from common import optparser
|
from common import optparser
|
||||||
parser = optparser.OptionsParser(config_filename)
|
parser = optparser.OptionsParser(config_filename)
|
||||||
|
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
log = logging.getLogger('gajim.interface')
|
log = logging.getLogger('gajim.interface')
|
||||||
|
|
||||||
|
@ -265,10 +263,10 @@ class Interface:
|
||||||
|
|
||||||
def handle_event_new_jid(self, account, data):
|
def handle_event_new_jid(self, account, data):
|
||||||
#('NEW_JID', account, (old_jid, new_jid))
|
#('NEW_JID', account, (old_jid, new_jid))
|
||||||
'''
|
"""
|
||||||
This event is raised when our JID changed (most probably because we use
|
This event is raised when our JID changed (most probably because we use
|
||||||
anonymous account. We update contact and roster entry in this case.
|
anonymous account. We update contact and roster entry in this case
|
||||||
'''
|
"""
|
||||||
self.roster.rename_self_contact(data[0], data[1], account)
|
self.roster.rename_self_contact(data[0], data[1], account)
|
||||||
|
|
||||||
def edit_own_details(self, account):
|
def edit_own_details(self, account):
|
||||||
|
@ -1521,7 +1519,9 @@ class Interface:
|
||||||
contact.resource)
|
contact.resource)
|
||||||
|
|
||||||
def handle_event_signed_in(self, account, empty):
|
def handle_event_signed_in(self, account, empty):
|
||||||
'''SIGNED_IN event is emitted when we sign in, so handle it'''
|
"""
|
||||||
|
SIGNED_IN event is emitted when we sign in, so handle it
|
||||||
|
"""
|
||||||
# ('SIGNED_IN', account, ())
|
# ('SIGNED_IN', account, ())
|
||||||
# block signed in notifications for 30 seconds
|
# block signed in notifications for 30 seconds
|
||||||
gajim.block_signed_in_notifications[account] = True
|
gajim.block_signed_in_notifications[account] = True
|
||||||
|
@ -1828,7 +1828,9 @@ class Interface:
|
||||||
dialogs.RosterItemExchangeWindow(account, data[0], data[1], data[2])
|
dialogs.RosterItemExchangeWindow(account, data[0], data[1], data[2])
|
||||||
|
|
||||||
def handle_event_unique_room_id_supported(self, account, data):
|
def handle_event_unique_room_id_supported(self, account, data):
|
||||||
'''Receive confirmation that unique_room_id are supported'''
|
"""
|
||||||
|
Receive confirmation that unique_room_id are supported
|
||||||
|
"""
|
||||||
# ('UNIQUE_ROOM_ID_SUPPORTED', server, instance, room_id)
|
# ('UNIQUE_ROOM_ID_SUPPORTED', server, instance, room_id)
|
||||||
instance = data[1]
|
instance = data[1]
|
||||||
instance.unique_room_id_supported(data[0], data[2])
|
instance.unique_room_id_supported(data[0], data[2])
|
||||||
|
@ -2115,11 +2117,10 @@ class Interface:
|
||||||
}
|
}
|
||||||
|
|
||||||
def dispatch(self, event, account, data):
|
def dispatch(self, event, account, data):
|
||||||
'''
|
"""
|
||||||
Dispatches an network event to the event handlers of this class.
|
Dispatch an network event to the event handlers of this class. Return
|
||||||
|
true if it could be dispatched to alteast one handler
|
||||||
Return true if it could be dispatched to alteast one handler.
|
"""
|
||||||
'''
|
|
||||||
if event not in self.handlers:
|
if event not in self.handlers:
|
||||||
log.warning('Unknown event %s dispatched to GUI: %s' % (event, data))
|
log.warning('Unknown event %s dispatched to GUI: %s' % (event, data))
|
||||||
return False
|
return False
|
||||||
|
@ -2135,7 +2136,9 @@ class Interface:
|
||||||
################################################################################
|
################################################################################
|
||||||
|
|
||||||
def add_event(self, account, jid, type_, event_args):
|
def add_event(self, account, jid, type_, event_args):
|
||||||
'''add an event to the gajim.events var'''
|
"""
|
||||||
|
Add an event to the gajim.events var
|
||||||
|
"""
|
||||||
# We add it to the gajim.events queue
|
# We add it to the gajim.events queue
|
||||||
# Do we have a queue?
|
# Do we have a queue?
|
||||||
jid = gajim.get_jid_without_resource(jid)
|
jid = gajim.get_jid_without_resource(jid)
|
||||||
|
@ -2464,7 +2467,9 @@ class Interface:
|
||||||
self.invalid_XML_chars = u'[\x00-\x08]|[\x0b-\x0c]|[\x0e-\x19]|[\ud800-\udfff]|[\ufffe-\uffff]'
|
self.invalid_XML_chars = u'[\x00-\x08]|[\x0b-\x0c]|[\x0e-\x19]|[\ud800-\udfff]|[\ufffe-\uffff]'
|
||||||
|
|
||||||
def popup_emoticons_under_button(self, button, parent_win):
|
def popup_emoticons_under_button(self, button, parent_win):
|
||||||
''' pops emoticons menu under button, located in parent_win'''
|
"""
|
||||||
|
Popup the emoticons menu under button, located in parent_win
|
||||||
|
"""
|
||||||
gtkgui_helpers.popup_emoticons_under_button(self.emoticons_menu,
|
gtkgui_helpers.popup_emoticons_under_button(self.emoticons_menu,
|
||||||
button, parent_win)
|
button, parent_win)
|
||||||
|
|
||||||
|
@ -2573,7 +2578,9 @@ class Interface:
|
||||||
|
|
||||||
def join_gc_room(self, account, room_jid, nick, password, minimize=False,
|
def join_gc_room(self, account, room_jid, nick, password, minimize=False,
|
||||||
is_continued=False):
|
is_continued=False):
|
||||||
'''joins the room immediately'''
|
"""
|
||||||
|
Join the room immediately
|
||||||
|
"""
|
||||||
if not nick:
|
if not nick:
|
||||||
nick = gajim.nicks[account]
|
nick = gajim.nicks[account]
|
||||||
|
|
||||||
|
@ -2841,7 +2848,9 @@ class Interface:
|
||||||
return (bg_str, fg_str)
|
return (bg_str, fg_str)
|
||||||
|
|
||||||
def read_sleepy(self):
|
def read_sleepy(self):
|
||||||
'''Check idle status and change that status if needed'''
|
"""
|
||||||
|
Check idle status and change that status if needed
|
||||||
|
"""
|
||||||
if not self.sleeper.poll():
|
if not self.sleeper.poll():
|
||||||
# idle detection is not supported in that OS
|
# idle detection is not supported in that OS
|
||||||
return False # stop looping in vain
|
return False # stop looping in vain
|
||||||
|
@ -2895,7 +2904,9 @@ class Interface:
|
||||||
return True # renew timeout (loop for ever)
|
return True # renew timeout (loop for ever)
|
||||||
|
|
||||||
def autoconnect(self):
|
def autoconnect(self):
|
||||||
'''auto connect at startup'''
|
"""
|
||||||
|
Auto connect at startup
|
||||||
|
"""
|
||||||
# dict of account that want to connect sorted by status
|
# dict of account that want to connect sorted by status
|
||||||
shows = {}
|
shows = {}
|
||||||
for a in gajim.connections:
|
for a in gajim.connections:
|
||||||
|
@ -2934,7 +2945,9 @@ class Interface:
|
||||||
helpers.launch_browser_mailer(kind, url)
|
helpers.launch_browser_mailer(kind, url)
|
||||||
|
|
||||||
def process_connections(self):
|
def process_connections(self):
|
||||||
''' Called each foo (200) miliseconds. Check for idlequeue timeouts. '''
|
"""
|
||||||
|
Called each foo (200) miliseconds. Check for idlequeue timeouts
|
||||||
|
"""
|
||||||
try:
|
try:
|
||||||
gajim.idlequeue.process()
|
gajim.idlequeue.process()
|
||||||
except Exception:
|
except Exception:
|
||||||
|
@ -2958,7 +2971,11 @@ class Interface:
|
||||||
sys.exit()
|
sys.exit()
|
||||||
|
|
||||||
def save_avatar_files(self, jid, photo, puny_nick = None, local = False):
|
def save_avatar_files(self, jid, photo, puny_nick = None, local = False):
|
||||||
'''Saves an avatar to a separate file, and generate files for dbus notifications. An avatar can be given as a pixmap directly or as an decoded image.'''
|
"""
|
||||||
|
Save an avatar to a separate file, and generate files for dbus
|
||||||
|
notifications. An avatar can be given as a pixmap directly or as an
|
||||||
|
decoded image
|
||||||
|
"""
|
||||||
puny_jid = helpers.sanitize_filename(jid)
|
puny_jid = helpers.sanitize_filename(jid)
|
||||||
path_to_file = os.path.join(gajim.AVATAR_PATH, puny_jid)
|
path_to_file = os.path.join(gajim.AVATAR_PATH, puny_jid)
|
||||||
if puny_nick:
|
if puny_nick:
|
||||||
|
@ -3011,7 +3028,9 @@ class Interface:
|
||||||
(path_to_original_file, str(e)))
|
(path_to_original_file, str(e)))
|
||||||
|
|
||||||
def remove_avatar_files(self, jid, puny_nick = None, local = False):
|
def remove_avatar_files(self, jid, puny_nick = None, local = False):
|
||||||
'''remove avatar files of a jid'''
|
"""
|
||||||
|
Remove avatar files of a jid
|
||||||
|
"""
|
||||||
puny_jid = helpers.sanitize_filename(jid)
|
puny_jid = helpers.sanitize_filename(jid)
|
||||||
path_to_file = os.path.join(gajim.AVATAR_PATH, puny_jid)
|
path_to_file = os.path.join(gajim.AVATAR_PATH, puny_jid)
|
||||||
if puny_nick:
|
if puny_nick:
|
||||||
|
@ -3028,7 +3047,9 @@ class Interface:
|
||||||
os.remove(path_to_file + '_notif_size_bw' + ext)
|
os.remove(path_to_file + '_notif_size_bw' + ext)
|
||||||
|
|
||||||
def auto_join_bookmarks(self, account):
|
def auto_join_bookmarks(self, account):
|
||||||
'''autojoin bookmarked GCs that have 'auto join' on for this account'''
|
"""
|
||||||
|
Autojoin bookmarked GCs that have 'auto join' on for this account
|
||||||
|
"""
|
||||||
for bm in gajim.connections[account].bookmarks:
|
for bm in gajim.connections[account].bookmarks:
|
||||||
if bm['autojoin'] in ('1', 'true'):
|
if bm['autojoin'] in ('1', 'true'):
|
||||||
jid = bm['jid']
|
jid = bm['jid']
|
||||||
|
@ -3047,7 +3068,9 @@ class Interface:
|
||||||
|
|
||||||
def add_gc_bookmark(self, account, name, jid, autojoin, minimize, password,
|
def add_gc_bookmark(self, account, name, jid, autojoin, minimize, password,
|
||||||
nick):
|
nick):
|
||||||
'''add a bookmark for this account, sorted in bookmark list'''
|
"""
|
||||||
|
Add a bookmark for this account, sorted in bookmark list
|
||||||
|
"""
|
||||||
bm = {
|
bm = {
|
||||||
'name': name,
|
'name': name,
|
||||||
'jid': jid,
|
'jid': jid,
|
||||||
|
@ -3475,13 +3498,9 @@ class PassphraseRequest:
|
||||||
|
|
||||||
class ThreadInterface:
|
class ThreadInterface:
|
||||||
def __init__(self, func, func_args, callback, callback_args):
|
def __init__(self, func, func_args, callback, callback_args):
|
||||||
'''Call a function in a thread
|
"""
|
||||||
|
Call a function in a thread
|
||||||
:param func: the function to call in the thread
|
"""
|
||||||
:param func_args: list or arguments for this function
|
|
||||||
:param callback: callback to call once function is finished
|
|
||||||
:param callback_args: list of arguments for this callback
|
|
||||||
'''
|
|
||||||
def thread_function(func, func_args, callback, callback_args):
|
def thread_function(func, func_args, callback, callback_args):
|
||||||
output = func(*func_args)
|
output = func(*func_args)
|
||||||
gobject.idle_add(callback, output, *callback_args)
|
gobject.idle_add(callback, output, *callback_args)
|
||||||
|
|
|
@ -28,9 +28,11 @@ from common import helpers
|
||||||
from common.xmpp.protocol import NS_COMMANDS, NS_FILE, NS_MUC, NS_ESESSION
|
from common.xmpp.protocol import NS_COMMANDS, NS_FILE, NS_MUC, NS_ESESSION
|
||||||
|
|
||||||
def build_resources_submenu(contacts, account, action, room_jid=None,
|
def build_resources_submenu(contacts, account, action, room_jid=None,
|
||||||
room_account=None, cap=None):
|
room_account=None, cap=None):
|
||||||
''' Build a submenu with contact's resources.
|
"""
|
||||||
room_jid and room_account are for action self.on_invite_to_room '''
|
Build a submenu with contact's resources. room_jid and room_account are for
|
||||||
|
action self.on_invite_to_room
|
||||||
|
"""
|
||||||
roster = gajim.interface.roster
|
roster = gajim.interface.roster
|
||||||
sub_menu = gtk.Menu()
|
sub_menu = gtk.Menu()
|
||||||
|
|
||||||
|
@ -61,7 +63,9 @@ room_account=None, cap=None):
|
||||||
return sub_menu
|
return sub_menu
|
||||||
|
|
||||||
def build_invite_submenu(invite_menuitem, list_):
|
def build_invite_submenu(invite_menuitem, list_):
|
||||||
'''list_ in a list of (contact, account)'''
|
"""
|
||||||
|
list_ in a list of (contact, account)
|
||||||
|
"""
|
||||||
roster = gajim.interface.roster
|
roster = gajim.interface.roster
|
||||||
# used if we invite only one contact with several resources
|
# used if we invite only one contact with several resources
|
||||||
contact_list = []
|
contact_list = []
|
||||||
|
@ -145,10 +149,12 @@ def build_invite_submenu(invite_menuitem, list_):
|
||||||
invite_to_submenu.append(menuitem)
|
invite_to_submenu.append(menuitem)
|
||||||
|
|
||||||
def get_contact_menu(contact, account, use_multiple_contacts=True,
|
def get_contact_menu(contact, account, use_multiple_contacts=True,
|
||||||
show_start_chat=True, show_encryption=False, show_buttonbar_items=True,
|
show_start_chat=True, show_encryption=False, show_buttonbar_items=True,
|
||||||
control=None):
|
control=None):
|
||||||
''' Build contact popup menu for roster and chat window.
|
"""
|
||||||
If control is not set, we hide invite_contacts_menuitem'''
|
Build contact popup menu for roster and chat window. If control is not set,
|
||||||
|
we hide invite_contacts_menuitem
|
||||||
|
"""
|
||||||
if not contact:
|
if not contact:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
|
@ -290,11 +290,13 @@ class HistoryManager:
|
||||||
self._fill_logs_listview(jid)
|
self._fill_logs_listview(jid)
|
||||||
|
|
||||||
def _get_jid_id(self, jid):
|
def _get_jid_id(self, jid):
|
||||||
'''jids table has jid and jid_id
|
"""
|
||||||
|
jids table has jid and jid_id
|
||||||
logs table has log_id, jid_id, contact_name, time, kind, show, message
|
logs table has log_id, jid_id, contact_name, time, kind, show, message
|
||||||
so to ask logs we need jid_id that matches our jid in jids table
|
|
||||||
this method wants jid and returns the jid_id for later sql-ing on logs
|
So to ask logs we need jid_id that matches our jid in jids table this
|
||||||
'''
|
method wants jid and returns the jid_id for later sql-ing on logs
|
||||||
|
"""
|
||||||
if jid.find('/') != -1: # if it has a /
|
if jid.find('/') != -1: # if it has a /
|
||||||
jid_is_from_pm = self._jid_is_from_pm(jid)
|
jid_is_from_pm = self._jid_is_from_pm(jid)
|
||||||
if not jid_is_from_pm: # it's normal jid with resource
|
if not jid_is_from_pm: # it's normal jid with resource
|
||||||
|
@ -304,22 +306,24 @@ class HistoryManager:
|
||||||
return str(jid_id)
|
return str(jid_id)
|
||||||
|
|
||||||
def _get_jid_from_jid_id(self, jid_id):
|
def _get_jid_from_jid_id(self, jid_id):
|
||||||
'''jids table has jid and jid_id
|
"""
|
||||||
this method accepts jid_id and returns the jid for later sql-ing on logs
|
jids table has jid and jid_id
|
||||||
'''
|
|
||||||
|
This method accepts jid_id and returns the jid for later sql-ing on logs
|
||||||
|
"""
|
||||||
self.cur.execute('SELECT jid FROM jids WHERE jid_id = ?', (jid_id,))
|
self.cur.execute('SELECT jid FROM jids WHERE jid_id = ?', (jid_id,))
|
||||||
jid = self.cur.fetchone()[0]
|
jid = self.cur.fetchone()[0]
|
||||||
return jid
|
return jid
|
||||||
|
|
||||||
def _jid_is_from_pm(self, jid):
|
def _jid_is_from_pm(self, jid):
|
||||||
'''if jid is gajim@conf/nkour it's likely a pm one, how we know
|
"""
|
||||||
gajim@conf is not a normal guy and nkour is not his resource?
|
If jid is gajim@conf/nkour it's likely a pm one, how we know gajim@conf
|
||||||
we ask if gajim@conf is already in jids (with type room jid)
|
is not a normal guy and nkour is not his resource? We ask if gajim@conf
|
||||||
this fails if user disables logging for room and only enables for
|
is already in jids (with type room jid). This fails if user disables
|
||||||
pm (so higly unlikely) and if we fail we do not go chaos
|
logging for room and only enables for pm (so higly unlikely) and if we
|
||||||
(user will see the first pm as if it was message in room's public chat)
|
fail we do not go chaos (user will see the first pm as if it was message
|
||||||
and after that all okay'''
|
in room's public chat) and after that everything is ok
|
||||||
|
"""
|
||||||
possible_room_jid = jid.split('/', 1)[0]
|
possible_room_jid = jid.split('/', 1)[0]
|
||||||
|
|
||||||
self.cur.execute('SELECT jid_id FROM jids WHERE jid = ? AND type = ?',
|
self.cur.execute('SELECT jid_id FROM jids WHERE jid = ? AND type = ?',
|
||||||
|
@ -331,8 +335,9 @@ class HistoryManager:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def _jid_is_room_type(self, jid):
|
def _jid_is_room_type(self, jid):
|
||||||
'''returns True/False if given id is room type or not
|
"""
|
||||||
eg. if it is room'''
|
Return True/False if given id is room type or not eg. if it is room
|
||||||
|
"""
|
||||||
self.cur.execute('SELECT type FROM jids WHERE jid = ?', (jid,))
|
self.cur.execute('SELECT type FROM jids WHERE jid = ?', (jid,))
|
||||||
row = self.cur.fetchone()
|
row = self.cur.fetchone()
|
||||||
if row is None:
|
if row is None:
|
||||||
|
@ -343,8 +348,10 @@ class HistoryManager:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def _fill_logs_listview(self, jid):
|
def _fill_logs_listview(self, jid):
|
||||||
'''fill the listview with all messages that user sent to or
|
"""
|
||||||
received from JID'''
|
Fill the listview with all messages that user sent to or received from
|
||||||
|
JID
|
||||||
|
"""
|
||||||
# no need to lower jid in this context as jid is already lowered
|
# no need to lower jid in this context as jid is already lowered
|
||||||
# as we use those jids from db
|
# as we use those jids from db
|
||||||
jid_id = self._get_jid_id(jid)
|
jid_id = self._get_jid_id(jid)
|
||||||
|
@ -403,7 +410,9 @@ class HistoryManager:
|
||||||
subject, nickname))
|
subject, nickname))
|
||||||
|
|
||||||
def _fill_search_results_listview(self, text):
|
def _fill_search_results_listview(self, text):
|
||||||
'''ask db and fill listview with results that match text'''
|
"""
|
||||||
|
Ask db and fill listview with results that match text
|
||||||
|
"""
|
||||||
self.search_results_liststore.clear()
|
self.search_results_liststore.clear()
|
||||||
like_sql = '%' + text + '%'
|
like_sql = '%' + text + '%'
|
||||||
self.cur.execute('''
|
self.cur.execute('''
|
||||||
|
|
Loading…
Add table
Reference in a new issue