merge default branch to jingle
This commit is contained in:
commit
01d7be2d61
2585
po/pt_BR.po
2585
po/pt_BR.po
File diff suppressed because it is too large
Load Diff
|
@ -531,6 +531,7 @@ class CommandProcessor(object):
|
||||||
args.append((raw, (end, arguments_end)))
|
args.append((raw, (end, arguments_end)))
|
||||||
elif spec_len == 1:
|
elif spec_len == 1:
|
||||||
args = [(arguments, (0, arguments_end))]
|
args = [(arguments, (0, arguments_end))]
|
||||||
|
opts = []
|
||||||
else:
|
else:
|
||||||
raise InternalError("Raw command must define a collector")
|
raise InternalError("Raw command must define a collector")
|
||||||
else:
|
else:
|
||||||
|
@ -642,21 +643,21 @@ class CommandProcessor(object):
|
||||||
if not text.startswith(self.COMMAND_PREFIX):
|
if not text.startswith(self.COMMAND_PREFIX):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
text = text[len(self.COMMAND_PREFIX):]
|
body = text[len(self.COMMAND_PREFIX):]
|
||||||
text = text.strip()
|
body = body.strip()
|
||||||
|
|
||||||
parts = text.split(' ', 1)
|
parts = body.split(' ', 1)
|
||||||
name, arguments = parts if len(parts) > 1 else (parts[0], None)
|
name, arguments = parts if len(parts) > 1 else (parts[0], None)
|
||||||
|
|
||||||
flag = self.looks_like_command(text, name, arguments)
|
flag = self.looks_like_command(body, name, arguments)
|
||||||
if flag is not None:
|
if flag is not None:
|
||||||
return flag
|
return flag
|
||||||
|
|
||||||
self.execute_command(name, arguments)
|
self.execute_command(text, name, arguments)
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def execute_command(self, name, arguments):
|
def execute_command(self, text, name, arguments):
|
||||||
command = self.retrieve_command(name)
|
command = self.retrieve_command(name)
|
||||||
|
|
||||||
args, opts = self.parse_command_arguments(arguments) if arguments else ([], [])
|
args, opts = self.parse_command_arguments(arguments) if arguments else ([], [])
|
||||||
|
|
|
@ -192,7 +192,7 @@ class GroupChatCommands(CommonCommands):
|
||||||
gajim.interface.instances[self.account]['join_gc'].window.present()
|
gajim.interface.instances[self.account]['join_gc'].window.present()
|
||||||
except KeyError:
|
except KeyError:
|
||||||
try:
|
try:
|
||||||
dialogs.JoinGroupchatWindow(account=None, room_jid=jid, nick=nick)
|
dialogs.JoinGroupchatWindow(account=self.account, room_jid=jid, nick=nick)
|
||||||
except GajimGeneralException:
|
except GajimGeneralException:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
|
@ -31,16 +31,14 @@ class ChatMiddleware(CommandProcessor):
|
||||||
Also provides some few basic utilities for the same purpose.
|
Also provides some few basic utilities for the same purpose.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def process_as_command(self, text):
|
def execute_command(self, text, name, arguments):
|
||||||
try:
|
try:
|
||||||
return super(ChatMiddleware, self).process_as_command(text)
|
super(ChatMiddleware, self).execute_command(text, name, arguments)
|
||||||
except CommandError, exception:
|
except CommandError, exception:
|
||||||
self.echo("%s: %s" %(exception.name, exception.message), 'error')
|
self.echo("%s: %s" %(exception.name, exception.message), 'error')
|
||||||
return True
|
|
||||||
except Exception:
|
except Exception:
|
||||||
self.echo("An error occured while trying to execute the command", 'error')
|
self.echo("An error occured while trying to execute the command", 'error')
|
||||||
print_exc()
|
print_exc()
|
||||||
return True
|
|
||||||
finally:
|
finally:
|
||||||
self.add_history(text)
|
self.add_history(text)
|
||||||
self.clear_input()
|
self.clear_input()
|
||||||
|
|
|
@ -1487,6 +1487,11 @@ class Connection(ConnectionHandlers):
|
||||||
self.connection.getRoster().setItem(jid = jid, name = name,
|
self.connection.getRoster().setItem(jid = jid, name = name,
|
||||||
groups = groups)
|
groups = groups)
|
||||||
|
|
||||||
|
def update_contacts(self, contacts):
|
||||||
|
'''update multiple roster items on jabber server'''
|
||||||
|
if self.connection:
|
||||||
|
self.connection.getRoster().setItemMulti(contacts)
|
||||||
|
|
||||||
def send_new_account_infos(self, form, is_form):
|
def send_new_account_infos(self, form, is_form):
|
||||||
if is_form:
|
if is_form:
|
||||||
# Get username and password and put them in new_account_info
|
# Get username and password and put them in new_account_info
|
||||||
|
@ -1598,6 +1603,16 @@ class Connection(ConnectionHandlers):
|
||||||
iq2.addChild(name='gajim', namespace='gajim:prefs')
|
iq2.addChild(name='gajim', namespace='gajim:prefs')
|
||||||
self.connection.send(iq)
|
self.connection.send(iq)
|
||||||
|
|
||||||
|
def _request_bookmarks_xml(self):
|
||||||
|
iq = common.xmpp.Iq(typ='get')
|
||||||
|
iq2 = iq.addChild(name='query', namespace=common.xmpp.NS_PRIVATE)
|
||||||
|
iq2.addChild(name='storage', namespace='storage:bookmarks')
|
||||||
|
self.connection.send(iq)
|
||||||
|
|
||||||
|
def _check_bookmarks_received(self):
|
||||||
|
if not self.bookmarks:
|
||||||
|
self._request_bookmarks_xml()
|
||||||
|
|
||||||
def get_bookmarks(self, storage_type=None):
|
def get_bookmarks(self, storage_type=None):
|
||||||
'''Get Bookmarks from storage or PubSub if supported as described in
|
'''Get Bookmarks from storage or PubSub if supported as described in
|
||||||
XEP 0048
|
XEP 0048
|
||||||
|
@ -1606,11 +1621,11 @@ class Connection(ConnectionHandlers):
|
||||||
return
|
return
|
||||||
if self.pubsub_supported and storage_type != 'xml':
|
if self.pubsub_supported and storage_type != 'xml':
|
||||||
self.send_pb_retrieve('', 'storage:bookmarks')
|
self.send_pb_retrieve('', 'storage:bookmarks')
|
||||||
|
# some server (ejabberd) are so slow to answer that we request via XML
|
||||||
|
# if we don't get answer in the next 30 seconds
|
||||||
|
gajim.idlequeue.set_alarm(self._check_bookmarks_received, 30)
|
||||||
else:
|
else:
|
||||||
iq = common.xmpp.Iq(typ='get')
|
self._request_bookmarks_xml()
|
||||||
iq2 = iq.addChild(name='query', namespace=common.xmpp.NS_PRIVATE)
|
|
||||||
iq2.addChild(name='storage', namespace='storage:bookmarks')
|
|
||||||
self.connection.send(iq)
|
|
||||||
|
|
||||||
def store_bookmarks(self, storage_type=None):
|
def store_bookmarks(self, storage_type=None):
|
||||||
''' Send bookmarks to the storage namespace or PubSub if supported
|
''' Send bookmarks to the storage namespace or PubSub if supported
|
||||||
|
|
|
@ -183,7 +183,7 @@ else:
|
||||||
import latex
|
import latex
|
||||||
HAVE_LATEX = latex.check_for_latex_support()
|
HAVE_LATEX = latex.check_for_latex_support()
|
||||||
|
|
||||||
HAVE_INDICATOR = True
|
HAVE_INDICATOR = False
|
||||||
try:
|
try:
|
||||||
import indicate
|
import indicate
|
||||||
except ImportError:
|
except ImportError:
|
||||||
|
|
|
@ -170,6 +170,11 @@ def prep(user, server, resource):
|
||||||
else:
|
else:
|
||||||
return server
|
return server
|
||||||
|
|
||||||
|
def windowsify(s):
|
||||||
|
if os.name == 'nt':
|
||||||
|
return s.capitalize()
|
||||||
|
return s
|
||||||
|
|
||||||
def temp_failure_retry(func, *args, **kwargs):
|
def temp_failure_retry(func, *args, **kwargs):
|
||||||
while True:
|
while True:
|
||||||
try:
|
try:
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
## Copyright (C) 2004 Vincent Hanquez <tab AT snarc.org>
|
## Copyright (C) 2004 Vincent Hanquez <tab AT snarc.org>
|
||||||
## Copyright (C) 2004-2007 Yann Leboulanger <asterix AT lagaule.org>
|
## Copyright (C) 2004-2007 Yann Leboulanger <asterix AT lagaule.org>
|
||||||
## Copyright (C) 2005-2006 Nikos Kouremenos <kourem AT gmail.com>
|
## Copyright (C) 2005-2006 Nikos Kouremenos <kourem AT gmail.com>
|
||||||
|
## Copyright (C) 2009 Benjamin Richter <br AT waldteufel-online.net>
|
||||||
##
|
##
|
||||||
## This file is part of Gajim.
|
## This file is part of Gajim.
|
||||||
##
|
##
|
||||||
|
@ -25,6 +26,23 @@ import locale
|
||||||
import gettext
|
import gettext
|
||||||
import os
|
import os
|
||||||
import defs
|
import defs
|
||||||
|
import unicodedata
|
||||||
|
|
||||||
|
def paragraph_direction_mark(text):
|
||||||
|
"""
|
||||||
|
Determine paragraph writing direction according to
|
||||||
|
http://www.unicode.org/reports/tr9/#The_Paragraph_Level
|
||||||
|
|
||||||
|
Returns either Unicode LTR mark or RTL mark.
|
||||||
|
"""
|
||||||
|
for char in text:
|
||||||
|
bidi = unicodedata.bidirectional(char)
|
||||||
|
if bidi == 'L':
|
||||||
|
return u'\u200E'
|
||||||
|
elif bidi == 'AL' or bidi == 'R':
|
||||||
|
return u'\u200F'
|
||||||
|
|
||||||
|
return u'\u200E'
|
||||||
|
|
||||||
APP = 'gajim'
|
APP = 'gajim'
|
||||||
DIR = defs.localedir
|
DIR = defs.localedir
|
||||||
|
|
|
@ -174,6 +174,16 @@ class NonBlockingRoster(PlugIn):
|
||||||
item=query.setTag('item',attrs)
|
item=query.setTag('item',attrs)
|
||||||
for group in groups: item.addChild(node=Node('group',payload=[group]))
|
for group in groups: item.addChild(node=Node('group',payload=[group]))
|
||||||
self._owner.send(iq)
|
self._owner.send(iq)
|
||||||
|
def setItemMulti(self,items):
|
||||||
|
''' Renames multiple contacts and sets their group lists.'''
|
||||||
|
iq=Iq('set',NS_ROSTER)
|
||||||
|
query=iq.getTag('query')
|
||||||
|
for i in items:
|
||||||
|
attrs={'jid':i['jid']}
|
||||||
|
if i['name']: attrs['name']=i['name']
|
||||||
|
item=query.setTag('item',attrs)
|
||||||
|
for group in i['groups']: item.addChild(node=Node('group',payload=[group]))
|
||||||
|
self._owner.send(iq)
|
||||||
def getItems(self):
|
def getItems(self):
|
||||||
''' Return list of all [bare] JIDs that the roster is currently tracks.'''
|
''' Return list of all [bare] JIDs that the roster is currently tracks.'''
|
||||||
return self._data.keys()
|
return self._data.keys()
|
||||||
|
|
|
@ -526,6 +526,11 @@ class ConnectionZeroconf(ConnectionHandlersZeroconf):
|
||||||
self.connection.getRoster().setItem(jid = jid, name = name,
|
self.connection.getRoster().setItem(jid = jid, name = name,
|
||||||
groups = groups)
|
groups = groups)
|
||||||
|
|
||||||
|
def update_contacts(self, contacts):
|
||||||
|
'''update multiple roster items'''
|
||||||
|
if self.connection:
|
||||||
|
self.connection.getRoster().setItemMulti(contacts)
|
||||||
|
|
||||||
def new_account(self, name, config, sync = False):
|
def new_account(self, name, config, sync = False):
|
||||||
gajim.log.debug('This should not happen (new_account)')
|
gajim.log.debug('This should not happen (new_account)')
|
||||||
|
|
||||||
|
|
|
@ -88,6 +88,10 @@ class Roster:
|
||||||
self._data[jid]['status'] = status
|
self._data[jid]['status'] = status
|
||||||
self._data[jid]['show'] = status
|
self._data[jid]['show'] = status
|
||||||
|
|
||||||
|
def setItemMulti(self, items):
|
||||||
|
for i in items:
|
||||||
|
self.setItem(jid=i['jid'], name=i['name'], groups=i['groups'])
|
||||||
|
|
||||||
def delItem(self, jid):
|
def delItem(self, jid):
|
||||||
#print 'roster_zeroconf.py: delItem %s' % jid
|
#print 'roster_zeroconf.py: delItem %s' % jid
|
||||||
if jid in self._data:
|
if jid in self._data:
|
||||||
|
|
|
@ -955,6 +955,13 @@ class ConversationTextview(gobject.GObject):
|
||||||
|
|
||||||
buffer_ = self.tv.get_buffer()
|
buffer_ = self.tv.get_buffer()
|
||||||
|
|
||||||
|
insert_tags_func = buffer_.insert_with_tags_by_name
|
||||||
|
# detect_and_print_special_text() is also used by
|
||||||
|
# HtmlHandler.handle_specials() and there tags is gtk.TextTag objects,
|
||||||
|
# not strings
|
||||||
|
if len(other_tags) > 0 and isinstance(other_tags[0], gtk.TextTag):
|
||||||
|
insert_tags_func = buffer_.insert_with_tags
|
||||||
|
|
||||||
index = 0
|
index = 0
|
||||||
|
|
||||||
# Too many special elements (emoticons, LaTeX formulas, etc)
|
# Too many special elements (emoticons, LaTeX formulas, etc)
|
||||||
|
@ -974,8 +981,7 @@ class ConversationTextview(gobject.GObject):
|
||||||
text_before_special_text = otext[index:start]
|
text_before_special_text = otext[index:start]
|
||||||
end_iter = buffer_.get_end_iter()
|
end_iter = buffer_.get_end_iter()
|
||||||
# we insert normal text
|
# we insert normal text
|
||||||
buffer_.insert_with_tags_by_name(end_iter,
|
insert_tags_func(end_iter, text_before_special_text, *other_tags)
|
||||||
text_before_special_text, *other_tags)
|
|
||||||
index = end # update index
|
index = end # update index
|
||||||
|
|
||||||
# now print it
|
# now print it
|
||||||
|
@ -984,7 +990,11 @@ class ConversationTextview(gobject.GObject):
|
||||||
if specials_limit <= 0:
|
if specials_limit <= 0:
|
||||||
break
|
break
|
||||||
|
|
||||||
return index # the position after *last* special text
|
# add the rest of text located in the index and after
|
||||||
|
end_iter = buffer_.get_end_iter()
|
||||||
|
insert_tags_func(end_iter, otext[index:], *other_tags)
|
||||||
|
|
||||||
|
return buffer_.get_end_iter()
|
||||||
|
|
||||||
def print_special_text(self, special_text, other_tags):
|
def print_special_text(self, special_text, other_tags):
|
||||||
'''is called by detect_and_print_special_text and prints
|
'''is called by detect_and_print_special_text and prints
|
||||||
|
@ -1280,22 +1290,17 @@ class ConversationTextview(gobject.GObject):
|
||||||
try:
|
try:
|
||||||
if name and (text.startswith('/me ') or text.startswith('/me\n')):
|
if name and (text.startswith('/me ') or text.startswith('/me\n')):
|
||||||
xhtml = xhtml.replace('/me', '<i>* %s</i>' % (name,), 1)
|
xhtml = xhtml.replace('/me', '<i>* %s</i>' % (name,), 1)
|
||||||
self.tv.display_html(xhtml.encode('utf-8'))
|
self.tv.display_html(xhtml.encode('utf-8'), self)
|
||||||
return
|
return
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
gajim.log.debug(str('Error processing xhtml') + str(e))
|
gajim.log.debug(str('Error processing xhtml') + str(e))
|
||||||
gajim.log.debug(str('with |' + xhtml + '|'))
|
gajim.log.debug(str('with |' + xhtml + '|'))
|
||||||
|
|
||||||
buffer_ = self.tv.get_buffer()
|
|
||||||
# /me is replaced by name if name is given
|
# /me is replaced by name if name is given
|
||||||
if name and (text.startswith('/me ') or text.startswith('/me\n')):
|
if name and (text.startswith('/me ') or text.startswith('/me\n')):
|
||||||
text = '* ' + name + text[3:]
|
text = '* ' + name + text[3:]
|
||||||
text_tags.append('italic')
|
text_tags.append('italic')
|
||||||
# detect urls formatting and if the user has it on emoticons
|
# detect urls formatting and if the user has it on emoticons
|
||||||
index = self.detect_and_print_special_text(text, text_tags)
|
self.detect_and_print_special_text(text, text_tags)
|
||||||
|
|
||||||
# add the rest of text located in the index and after
|
|
||||||
end_iter = buffer_.get_end_iter()
|
|
||||||
buffer_.insert_with_tags_by_name(end_iter, text[index:], *text_tags)
|
|
||||||
|
|
||||||
# vim: se ts=3:
|
# vim: se ts=3:
|
||||||
|
|
|
@ -2504,6 +2504,16 @@ class SingleMessageWindow:
|
||||||
|
|
||||||
def on_single_message_window_destroy(self, widget):
|
def on_single_message_window_destroy(self, widget):
|
||||||
self.instances.remove(self)
|
self.instances.remove(self)
|
||||||
|
c = gajim.contacts.get_contact_with_highest_priority(self.account,
|
||||||
|
self.from_whom)
|
||||||
|
if not c:
|
||||||
|
# Groupchat is maybe already destroyed
|
||||||
|
return
|
||||||
|
if c.is_groupchat() and not self.from_whom in \
|
||||||
|
gajim.interface.minimized_controls[self.account] and self.action == \
|
||||||
|
'receive' and gajim.events.get_nb_roster_events(self.account,
|
||||||
|
self.from_whom, types=['chat', 'normal']) == 0:
|
||||||
|
gajim.interface.roster.remove_groupchat(self.from_whom, self.account)
|
||||||
|
|
||||||
def set_cursor_to_end(self):
|
def set_cursor_to_end(self):
|
||||||
end_iter = self.message_tv_buffer.get_end_iter()
|
end_iter = self.message_tv_buffer.get_end_iter()
|
||||||
|
|
90
src/gajim.py
90
src/gajim.py
|
@ -2632,7 +2632,7 @@ class Interface:
|
||||||
gajim.events.remove_events(account, jid, event)
|
gajim.events.remove_events(account, jid, event)
|
||||||
if w:
|
if w:
|
||||||
w.set_active_tab(ctrl)
|
w.set_active_tab(ctrl)
|
||||||
w.window.window.focus()
|
w.window.window.focus(gtk.get_current_event_time())
|
||||||
# Using isinstance here because we want to catch all derived types
|
# Using isinstance here because we want to catch all derived types
|
||||||
if isinstance(ctrl, ChatControlBase):
|
if isinstance(ctrl, ChatControlBase):
|
||||||
tv = ctrl.conv_textview
|
tv = ctrl.conv_textview
|
||||||
|
@ -3109,8 +3109,8 @@ class Interface:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def enable_music_listener(self):
|
def enable_music_listener(self):
|
||||||
if not self.music_track_changed_signal:
|
|
||||||
listener = MusicTrackListener.get()
|
listener = MusicTrackListener.get()
|
||||||
|
if not self.music_track_changed_signal:
|
||||||
self.music_track_changed_signal = listener.connect(
|
self.music_track_changed_signal = listener.connect(
|
||||||
'music-track-changed', self.music_track_changed)
|
'music-track-changed', self.music_track_changed)
|
||||||
track = listener.get_playing_track()
|
track = listener.get_playing_track()
|
||||||
|
@ -3452,6 +3452,49 @@ class Interface:
|
||||||
view.updateNamespace({'gajim': gajim})
|
view.updateNamespace({'gajim': gajim})
|
||||||
gajim.ipython_window = window
|
gajim.ipython_window = window
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
if self.systray_capabilities and gajim.config.get('trayicon') != 'never':
|
||||||
|
self.show_systray()
|
||||||
|
|
||||||
|
self.roster = roster_window.RosterWindow()
|
||||||
|
for account in gajim.connections:
|
||||||
|
gajim.connections[account].load_roster_from_db()
|
||||||
|
|
||||||
|
# get instances for windows/dialogs that will show_all()/hide()
|
||||||
|
self.instances['file_transfers'] = dialogs.FileTransfersWindow()
|
||||||
|
|
||||||
|
gobject.timeout_add(100, self.autoconnect)
|
||||||
|
timeout, in_seconds = gajim.idlequeue.PROCESS_TIMEOUT
|
||||||
|
if in_seconds:
|
||||||
|
gobject.timeout_add_seconds(timeout, self.process_connections)
|
||||||
|
else:
|
||||||
|
gobject.timeout_add(timeout, self.process_connections)
|
||||||
|
gobject.timeout_add_seconds(gajim.config.get(
|
||||||
|
'check_idle_every_foo_seconds'), self.read_sleepy)
|
||||||
|
|
||||||
|
# when using libasyncns we need to process resolver in regular intervals
|
||||||
|
if resolver.USE_LIBASYNCNS:
|
||||||
|
gobject.timeout_add(200, gajim.resolver.process)
|
||||||
|
|
||||||
|
# setup the indicator
|
||||||
|
if gajim.HAVE_INDICATOR:
|
||||||
|
notify.setup_indicator_server()
|
||||||
|
|
||||||
|
def remote_init():
|
||||||
|
if gajim.config.get('remote_control'):
|
||||||
|
try:
|
||||||
|
import remote_control
|
||||||
|
self.remote_ctrl = remote_control.Remote()
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
gobject.timeout_add_seconds(5, remote_init)
|
||||||
|
|
||||||
|
for account in gajim.connections:
|
||||||
|
if gajim.config.get_per('accounts', account, 'publish_tune') and \
|
||||||
|
dbus_support.supported:
|
||||||
|
self.enable_music_listener()
|
||||||
|
break
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
gajim.interface = self
|
gajim.interface = self
|
||||||
gajim.thread_interface = ThreadInterface
|
gajim.thread_interface = ThreadInterface
|
||||||
|
@ -3654,9 +3697,6 @@ class Interface:
|
||||||
if self.systray_capabilities:
|
if self.systray_capabilities:
|
||||||
self.systray = systray.Systray()
|
self.systray = systray.Systray()
|
||||||
|
|
||||||
if self.systray_capabilities and gajim.config.get('trayicon') != 'never':
|
|
||||||
self.show_systray()
|
|
||||||
|
|
||||||
path_to_file = os.path.join(gajim.DATA_DIR, 'pixmaps', 'gajim.png')
|
path_to_file = os.path.join(gajim.DATA_DIR, 'pixmaps', 'gajim.png')
|
||||||
pix = gtk.gdk.pixbuf_new_from_file(path_to_file)
|
pix = gtk.gdk.pixbuf_new_from_file(path_to_file)
|
||||||
# set the icon to all windows
|
# set the icon to all windows
|
||||||
|
@ -3665,13 +3705,6 @@ class Interface:
|
||||||
self.init_emoticons()
|
self.init_emoticons()
|
||||||
self.make_regexps()
|
self.make_regexps()
|
||||||
|
|
||||||
self.roster = roster_window.RosterWindow()
|
|
||||||
for account in gajim.connections:
|
|
||||||
gajim.connections[account].load_roster_from_db()
|
|
||||||
|
|
||||||
# get instances for windows/dialogs that will show_all()/hide()
|
|
||||||
self.instances['file_transfers'] = dialogs.FileTransfersWindow()
|
|
||||||
|
|
||||||
# get transports type from DB
|
# get transports type from DB
|
||||||
gajim.transport_type = gajim.logger.get_transports_type()
|
gajim.transport_type = gajim.logger.get_transports_type()
|
||||||
|
|
||||||
|
@ -3699,37 +3732,7 @@ class Interface:
|
||||||
|
|
||||||
self.last_ftwindow_update = 0
|
self.last_ftwindow_update = 0
|
||||||
|
|
||||||
gobject.timeout_add(100, self.autoconnect)
|
|
||||||
timeout, in_seconds = gajim.idlequeue.PROCESS_TIMEOUT
|
|
||||||
if in_seconds:
|
|
||||||
gobject.timeout_add_seconds(timeout, self.process_connections)
|
|
||||||
else:
|
|
||||||
gobject.timeout_add(timeout, self.process_connections)
|
|
||||||
gobject.timeout_add_seconds(gajim.config.get(
|
|
||||||
'check_idle_every_foo_seconds'), self.read_sleepy)
|
|
||||||
|
|
||||||
# when using libasyncns we need to process resolver in regular intervals
|
|
||||||
if resolver.USE_LIBASYNCNS:
|
|
||||||
gobject.timeout_add(200, gajim.resolver.process)
|
|
||||||
|
|
||||||
# setup the indicator
|
|
||||||
if gajim.HAVE_INDICATOR:
|
|
||||||
notify.setup_indicator_server()
|
|
||||||
|
|
||||||
def remote_init():
|
|
||||||
if gajim.config.get('remote_control'):
|
|
||||||
try:
|
|
||||||
import remote_control
|
|
||||||
self.remote_ctrl = remote_control.Remote()
|
|
||||||
except Exception:
|
|
||||||
pass
|
|
||||||
gobject.timeout_add_seconds(5, remote_init)
|
|
||||||
self.music_track_changed_signal = None
|
self.music_track_changed_signal = None
|
||||||
for account in gajim.connections:
|
|
||||||
if gajim.config.get_per('accounts', account, 'publish_tune') and \
|
|
||||||
dbus_support.supported:
|
|
||||||
self.enable_music_listener()
|
|
||||||
break
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
def sigint_cb(num, stack):
|
def sigint_cb(num, stack):
|
||||||
|
@ -3768,7 +3771,8 @@ if __name__ == '__main__':
|
||||||
|
|
||||||
check_paths.check_and_possibly_create_paths()
|
check_paths.check_and_possibly_create_paths()
|
||||||
|
|
||||||
Interface()
|
interface = Interface()
|
||||||
|
interface.run()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if os.name != 'nt':
|
if os.name != 'nt':
|
||||||
|
|
|
@ -1229,15 +1229,15 @@ class GroupchatControl(ChatControlBase, GroupChatCommands):
|
||||||
# Stop all E2E sessions
|
# Stop all E2E sessions
|
||||||
nick_list = gajim.contacts.get_nick_list(self.account,
|
nick_list = gajim.contacts.get_nick_list(self.account,
|
||||||
self.room_jid)
|
self.room_jid)
|
||||||
for nick in nick_list:
|
for nick_ in nick_list:
|
||||||
fjid = self.room_jid + '/' + nick
|
fjid_ = self.room_jid + '/' + nick_
|
||||||
ctrl = gajim.interface.msg_win_mgr.get_control(fjid,
|
ctrl = gajim.interface.msg_win_mgr.get_control(fjid_,
|
||||||
self.account)
|
self.account)
|
||||||
if ctrl and ctrl.session and \
|
if ctrl and ctrl.session and \
|
||||||
ctrl.session.enable_encryption:
|
ctrl.session.enable_encryption:
|
||||||
thread_id = ctrl.session.thread_id
|
thread_id = ctrl.session.thread_id
|
||||||
ctrl.session.terminate_e2e()
|
ctrl.session.terminate_e2e()
|
||||||
gajim.connections[self.account].delete_session(fjid,
|
gajim.connections[self.account].delete_session(fjid_,
|
||||||
thread_id)
|
thread_id)
|
||||||
ctrl.no_autonegotiation = False
|
ctrl.no_autonegotiation = False
|
||||||
else:
|
else:
|
||||||
|
@ -1271,8 +1271,10 @@ class GroupchatControl(ChatControlBase, GroupChatCommands):
|
||||||
os.path.join(path, puny_new_nick + ext)
|
os.path.join(path, puny_new_nick + ext)
|
||||||
for old_file in files:
|
for old_file in files:
|
||||||
if os.path.exists(old_file) and old_file != files[old_file]:
|
if os.path.exists(old_file) and old_file != files[old_file]:
|
||||||
if os.path.exists(files[old_file]):
|
if os.path.exists(files[old_file]) and helpers.windowsify(
|
||||||
# Windows require this
|
old_file) != helpers.windowsify(files[old_file]):
|
||||||
|
# Windows require this, but os.remove('test') will also
|
||||||
|
# remove 'TEST'
|
||||||
os.remove(files[old_file])
|
os.remove(files[old_file])
|
||||||
os.rename(old_file, files[old_file])
|
os.rename(old_file, files[old_file])
|
||||||
self.print_conversation(s, 'info', tim)
|
self.print_conversation(s, 'info', tim)
|
||||||
|
|
|
@ -50,6 +50,8 @@ import operator
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
from common import i18n
|
from common import i18n
|
||||||
|
import common.configpaths
|
||||||
|
common.configpaths.gajimpaths.init(None)
|
||||||
from common import gajim
|
from common import gajim
|
||||||
|
|
||||||
import tooltips
|
import tooltips
|
||||||
|
@ -184,25 +186,6 @@ for name in BLOCK_HEAD:
|
||||||
('font-weight: bold', 'font-style: oblique')[weigth],
|
('font-weight: bold', 'font-style: oblique')[weigth],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def build_patterns(view, config, interface):
|
|
||||||
# extra, rst does not mark _underline_ or /it/ up
|
|
||||||
# actually <b>, <i> or <u> are not in the JEP-0071, but are seen in the wild
|
|
||||||
basic_pattern = r'(?<!\w|\<|/|:)' r'/[^\s/]' r'([^/]*[^\s/])?' r'/(?!\w|/|:)|'\
|
|
||||||
r'(?<!\w)' r'_[^\s_]' r'([^_]*[^\s_])?' r'_(?!\w)'
|
|
||||||
view.basic_pattern_re = re.compile(basic_pattern)
|
|
||||||
# emoticons
|
|
||||||
emoticons_pattern = ''
|
|
||||||
if config.get('emoticons_theme'):
|
|
||||||
emoticons_pattern = gajim.interface.emot_only
|
|
||||||
|
|
||||||
view.emot_pattern_re = re.compile(emoticons_pattern, re.IGNORECASE)
|
|
||||||
# because emoticons match later (in the string) they need to be after
|
|
||||||
# basic matches that may occur earlier
|
|
||||||
emot_and_basic_pattern = basic_pattern + emoticons_pattern
|
|
||||||
view.emot_and_basic_re = re.compile(emot_and_basic_pattern, re.IGNORECASE)
|
|
||||||
|
|
||||||
|
|
||||||
def _parse_css_color(color):
|
def _parse_css_color(color):
|
||||||
'''_parse_css_color(css_color) -> gtk.gdk.Color'''
|
'''_parse_css_color(css_color) -> gtk.gdk.Color'''
|
||||||
if color.startswith('rgb(') and color.endswith(')'):
|
if color.startswith('rgb(') and color.endswith(')'):
|
||||||
|
@ -222,11 +205,12 @@ class HtmlHandler(xml.sax.handler.ContentHandler):
|
||||||
It keeps a stack of "style spans" (start/end element pairs)
|
It keeps a stack of "style spans" (start/end element pairs)
|
||||||
and a stack of list counters, for nested lists.
|
and a stack of list counters, for nested lists.
|
||||||
"""
|
"""
|
||||||
def __init__(self, textview, startiter):
|
def __init__(self, conv_textview, startiter):
|
||||||
xml.sax.handler.ContentHandler.__init__(self)
|
xml.sax.handler.ContentHandler.__init__(self)
|
||||||
self.textbuf = textview.get_buffer()
|
self.textbuf = conv_textview.tv.get_buffer()
|
||||||
self.textview = textview
|
self.textview = conv_textview.tv
|
||||||
self.iter = startiter
|
self.iter = startiter
|
||||||
|
self.conv_textview = conv_textview
|
||||||
self.text = ''
|
self.text = ''
|
||||||
self.starting=True
|
self.starting=True
|
||||||
self.preserve = False
|
self.preserve = False
|
||||||
|
@ -499,6 +483,7 @@ class HtmlHandler(xml.sax.handler.ContentHandler):
|
||||||
def _process_img(self, attrs):
|
def _process_img(self, attrs):
|
||||||
'''Process a img tag.
|
'''Process a img tag.
|
||||||
'''
|
'''
|
||||||
|
mem = ''
|
||||||
try:
|
try:
|
||||||
# Wait maximum 1s for connection
|
# Wait maximum 1s for connection
|
||||||
socket.setdefaulttimeout(1)
|
socket.setdefaulttimeout(1)
|
||||||
|
@ -515,7 +500,6 @@ class HtmlHandler(xml.sax.handler.ContentHandler):
|
||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
# Max image size = 2 MB (to try to prevent DoS)
|
# Max image size = 2 MB (to try to prevent DoS)
|
||||||
mem = ''
|
|
||||||
deadline = time.time() + 3
|
deadline = time.time() + 3
|
||||||
while True:
|
while True:
|
||||||
if time.time() > deadline:
|
if time.time() > deadline:
|
||||||
|
@ -532,7 +516,6 @@ class HtmlHandler(xml.sax.handler.ContentHandler):
|
||||||
except socket.timeout, ex:
|
except socket.timeout, ex:
|
||||||
gajim.log.debug('Timeout loading image %s ' % attrs['src'] + \
|
gajim.log.debug('Timeout loading image %s ' % attrs['src'] + \
|
||||||
str(ex))
|
str(ex))
|
||||||
mem = ''
|
|
||||||
alt = attrs.get('alt', '')
|
alt = attrs.get('alt', '')
|
||||||
if alt:
|
if alt:
|
||||||
alt += '\n'
|
alt += '\n'
|
||||||
|
@ -672,51 +655,7 @@ class HtmlHandler(xml.sax.handler.ContentHandler):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def handle_specials(self, text):
|
def handle_specials(self, text):
|
||||||
index = 0
|
self.iter = self.conv_textview.detect_and_print_special_text(text, self._get_style_tags())
|
||||||
se = self.textview.config.get('show_ascii_formatting_chars')
|
|
||||||
af = gajim.config.get('ascii_formatting')
|
|
||||||
if self.textview.config.get('emoticons_theme'):
|
|
||||||
if af:
|
|
||||||
iterator = self.textview.emot_and_basic_re.finditer(text)
|
|
||||||
else:
|
|
||||||
iterator = self.textview.emot_pattern_re.finditer(text)
|
|
||||||
elif af:
|
|
||||||
iterator = self.textview.basic_pattern_re.finditer(text)
|
|
||||||
else:
|
|
||||||
iterator = []
|
|
||||||
for match in iterator:
|
|
||||||
start, end = match.span()
|
|
||||||
special_text = text[start:end]
|
|
||||||
if start != 0:
|
|
||||||
self._insert_text(text[index:start])
|
|
||||||
index = end # update index
|
|
||||||
#emoticons
|
|
||||||
possible_emot_ascii_caps = special_text.upper() # emoticons keys are CAPS
|
|
||||||
if self.textview.config.get('emoticons_theme') and \
|
|
||||||
possible_emot_ascii_caps in self.textview.interface.emoticons.keys():
|
|
||||||
#it's an emoticon
|
|
||||||
emot_ascii = possible_emot_ascii_caps
|
|
||||||
anchor = self.textbuf.create_child_anchor(self.iter)
|
|
||||||
img = gtk.Image()
|
|
||||||
img.set_from_file(self.textview.interface.emoticons[emot_ascii])
|
|
||||||
img.show()
|
|
||||||
# TODO: add alt/tooltip with the special_text (a11y)
|
|
||||||
self.textview.add_child_at_anchor(img, anchor)
|
|
||||||
elif af:
|
|
||||||
# now print it
|
|
||||||
if special_text.startswith('/'): # it's explicit italics
|
|
||||||
self.startElement('i', {})
|
|
||||||
elif special_text.startswith('_'): # it's explicit underline
|
|
||||||
self.startElement('u', {})
|
|
||||||
if se: self._insert_text(special_text[0])
|
|
||||||
self.handle_specials(special_text[1:-1])
|
|
||||||
if se: self._insert_text(special_text[0])
|
|
||||||
if special_text.startswith('_'): # it's explicit underline
|
|
||||||
self.endElement('u')
|
|
||||||
if special_text.startswith('/'): # it's explicit italics
|
|
||||||
self.endElement('i')
|
|
||||||
if index < len(text):
|
|
||||||
self._insert_text(text[index:])
|
|
||||||
|
|
||||||
def characters(self, content):
|
def characters(self, content):
|
||||||
if self.preserve:
|
if self.preserve:
|
||||||
|
@ -870,7 +809,6 @@ class HtmlTextView(gtk.TextView):
|
||||||
self.config = gajim.config
|
self.config = gajim.config
|
||||||
self.interface = gajim.interface
|
self.interface = gajim.interface
|
||||||
# end big hack
|
# end big hack
|
||||||
build_patterns(self,gajim.config,gajim.interface)
|
|
||||||
|
|
||||||
def __destroy_event(self, widget):
|
def __destroy_event(self, widget):
|
||||||
if self.tooltip.timeout != 0:
|
if self.tooltip.timeout != 0:
|
||||||
|
@ -921,14 +859,14 @@ class HtmlTextView(gtk.TextView):
|
||||||
self._changed_cursor = False
|
self._changed_cursor = False
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def display_html(self, html):
|
def display_html(self, html, conv_textview):
|
||||||
buffer_ = self.get_buffer()
|
buffer_ = self.get_buffer()
|
||||||
eob = buffer_.get_end_iter()
|
eob = buffer_.get_end_iter()
|
||||||
## this works too if libxml2 is not available
|
## this works too if libxml2 is not available
|
||||||
# parser = xml.sax.make_parser(['drv_libxml2'])
|
# parser = xml.sax.make_parser(['drv_libxml2'])
|
||||||
# parser.setFeature(xml.sax.handler.feature_validation, True)
|
# parser.setFeature(xml.sax.handler.feature_validation, True)
|
||||||
parser = xml.sax.make_parser()
|
parser = xml.sax.make_parser()
|
||||||
parser.setContentHandler(HtmlHandler(self, eob))
|
parser.setContentHandler(HtmlHandler(conv_textview, eob))
|
||||||
parser.parse(StringIO(html))
|
parser.parse(StringIO(html))
|
||||||
|
|
||||||
# too much space after :)
|
# too much space after :)
|
||||||
|
@ -942,6 +880,9 @@ change_cursor = None
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
import os
|
import os
|
||||||
|
|
||||||
|
from conversation_textview import ConversationTextview
|
||||||
|
import gajim as gaj
|
||||||
|
|
||||||
class log(object):
|
class log(object):
|
||||||
|
|
||||||
def debug(self, text):
|
def debug(self, text):
|
||||||
|
@ -953,33 +894,32 @@ if __name__ == '__main__':
|
||||||
|
|
||||||
gajim.log=log()
|
gajim.log=log()
|
||||||
|
|
||||||
if gajim.config.get('emoticons_theme'):
|
gaj.Interface()
|
||||||
print "emoticons"
|
|
||||||
|
|
||||||
htmlview = HtmlTextView()
|
htmlview = ConversationTextview(None)
|
||||||
|
|
||||||
path_to_file = os.path.join(gajim.DATA_DIR, 'pixmaps', 'muc_separator.png')
|
path_to_file = os.path.join(gajim.DATA_DIR, 'pixmaps', 'muc_separator.png')
|
||||||
# use this for hr
|
# use this for hr
|
||||||
htmlview.focus_out_line_pixbuf = gtk.gdk.pixbuf_new_from_file(path_to_file)
|
htmlview.tv.focus_out_line_pixbuf = gtk.gdk.pixbuf_new_from_file(path_to_file)
|
||||||
|
|
||||||
|
|
||||||
tooltip = tooltips.BaseTooltip()
|
tooltip = tooltips.BaseTooltip()
|
||||||
def on_textview_motion_notify_event(widget, event):
|
def on_textview_motion_notify_event(widget, event):
|
||||||
'''change the cursor to a hand when we are over a mail or an url'''
|
'''change the cursor to a hand when we are over a mail or an url'''
|
||||||
global change_cursor
|
global change_cursor
|
||||||
pointer_x, pointer_y = htmlview.window.get_pointer()[0:2]
|
pointer_x, pointer_y = htmlview.tv.window.get_pointer()[0:2]
|
||||||
x, y = htmlview.window_to_buffer_coords(gtk.TEXT_WINDOW_TEXT, pointer_x,
|
x, y = htmlview.tv.window_to_buffer_coords(gtk.TEXT_WINDOW_TEXT, pointer_x,
|
||||||
pointer_y)
|
pointer_y)
|
||||||
tags = htmlview.get_iter_at_location(x, y).get_tags()
|
tags = htmlview.tv.get_iter_at_location(x, y).get_tags()
|
||||||
if change_cursor:
|
if change_cursor:
|
||||||
htmlview.get_window(gtk.TEXT_WINDOW_TEXT).set_cursor(
|
htmlview.tv.get_window(gtk.TEXT_WINDOW_TEXT).set_cursor(
|
||||||
gtk.gdk.Cursor(gtk.gdk.XTERM))
|
gtk.gdk.Cursor(gtk.gdk.XTERM))
|
||||||
change_cursor = None
|
change_cursor = None
|
||||||
tag_table = htmlview.get_buffer().get_tag_table()
|
tag_table = htmlview.tv.get_buffer().get_tag_table()
|
||||||
for tag in tags:
|
for tag in tags:
|
||||||
try:
|
try:
|
||||||
if tag.is_anchor:
|
if tag.is_anchor:
|
||||||
htmlview.get_window(gtk.TEXT_WINDOW_TEXT).set_cursor(
|
htmlview.tv.get_window(gtk.TEXT_WINDOW_TEXT).set_cursor(
|
||||||
gtk.gdk.Cursor(gtk.gdk.HAND2))
|
gtk.gdk.Cursor(gtk.gdk.HAND2))
|
||||||
change_cursor = tag
|
change_cursor = tag
|
||||||
elif tag == tag_table.lookup('focus-out-line'):
|
elif tag == tag_table.lookup('focus-out-line'):
|
||||||
|
@ -994,32 +934,38 @@ if __name__ == '__main__':
|
||||||
#if over_line and not line_tooltip.win:
|
#if over_line and not line_tooltip.win:
|
||||||
# line_tooltip.timeout = gobject.timeout_add(500,
|
# line_tooltip.timeout = gobject.timeout_add(500,
|
||||||
# show_line_tooltip)
|
# show_line_tooltip)
|
||||||
# htmlview.get_window(gtk.TEXT_WINDOW_TEXT).set_cursor(
|
# htmlview.tv.get_window(gtk.TEXT_WINDOW_TEXT).set_cursor(
|
||||||
# gtk.gdk.Cursor(gtk.gdk.LEFT_PTR))
|
# gtk.gdk.Cursor(gtk.gdk.LEFT_PTR))
|
||||||
# change_cursor = tag
|
# change_cursor = tag
|
||||||
|
|
||||||
htmlview.connect('motion_notify_event', on_textview_motion_notify_event)
|
htmlview.tv.connect('motion_notify_event', on_textview_motion_notify_event)
|
||||||
|
|
||||||
def handler(texttag, widget, event, iter_, kind, href):
|
def handler(texttag, widget, event, iter_, kind, href):
|
||||||
if event.type == gtk.gdk.BUTTON_PRESS:
|
if event.type == gtk.gdk.BUTTON_PRESS:
|
||||||
print href
|
print href
|
||||||
|
|
||||||
htmlview.html_hyperlink_handler = handler
|
htmlview.tv.html_hyperlink_handler = handler
|
||||||
|
|
||||||
htmlview.display_html('<div><span style="color: red; text-decoration:underline">Hello</span><br/>\n'
|
htmlview.print_real_text(None, xhtml='<div><span style="color: red; text-decoration:underline">Hello</span><br/>\n'
|
||||||
' <img src="http://images.slashdot.org/topics/topicsoftware.gif"/><br/>\n'
|
' <img src="http://images.slashdot.org/topics/topicsoftware.gif"/><br/>\n'
|
||||||
' <span style="font-size: 500%; font-family: serif">World</span>\n'
|
' <span style="font-size: 500%; font-family: serif">World</span>\n'
|
||||||
'</div>\n')
|
'</div>\n')
|
||||||
htmlview.display_html('<hr />')
|
htmlview.print_real_text(None, xhtml='<hr />')
|
||||||
htmlview.display_html('''
|
htmlview.print_real_text(None, xhtml='''
|
||||||
<p style='font-size:large'>
|
<p style='font-size:large'>
|
||||||
<span style='font-style: italic'>O<span style='font-size:larger'>M</span>G</span>,
|
<span style='font-style: italic'>O<span style='font-size:larger'>M</span>G</span>,
|
||||||
I'm <span style='color:green'>green</span>
|
I'm <span style='color:green'>green</span>
|
||||||
with <span style='font-weight: bold'>envy</span>!
|
with <span style='font-weight: bold'>envy</span>!
|
||||||
</p>
|
</p>
|
||||||
''')
|
''')
|
||||||
htmlview.display_html('<hr />')
|
htmlview.print_real_text(None, xhtml='<hr />')
|
||||||
htmlview.display_html('''
|
htmlview.print_real_text(None, xhtml='''
|
||||||
|
<body xmlns='http://www.w3.org/1999/xhtml'>
|
||||||
|
http://test.com/ testing links autolinkifying
|
||||||
|
</body>
|
||||||
|
''')
|
||||||
|
htmlview.print_real_text(None, xhtml='<hr />')
|
||||||
|
htmlview.print_real_text(None, xhtml='''
|
||||||
<body xmlns='http://www.w3.org/1999/xhtml'>
|
<body xmlns='http://www.w3.org/1999/xhtml'>
|
||||||
<p>As Emerson said in his essay <span style='font-style: italic; background-color:cyan'>Self-Reliance</span>:</p>
|
<p>As Emerson said in his essay <span style='font-style: italic; background-color:cyan'>Self-Reliance</span>:</p>
|
||||||
<p style='margin-left: 5px; margin-right: 2%'>
|
<p style='margin-left: 5px; margin-right: 2%'>
|
||||||
|
@ -1027,8 +973,8 @@ if __name__ == '__main__':
|
||||||
</p>
|
</p>
|
||||||
</body>
|
</body>
|
||||||
''')
|
''')
|
||||||
htmlview.display_html('<hr />')
|
htmlview.print_real_text(None, xhtml='<hr />')
|
||||||
htmlview.display_html('''
|
htmlview.print_real_text(None, xhtml='''
|
||||||
<body xmlns='http://www.w3.org/1999/xhtml'>
|
<body xmlns='http://www.w3.org/1999/xhtml'>
|
||||||
<p style='text-align:center'>Hey, are you licensed to <a href='http://www.jabber.org/'>Jabber</a>?</p>
|
<p style='text-align:center'>Hey, are you licensed to <a href='http://www.jabber.org/'>Jabber</a>?</p>
|
||||||
<p style='text-align:right'><img src='http://www.jabber.org/images/psa-license.jpg'
|
<p style='text-align:right'><img src='http://www.jabber.org/images/psa-license.jpg'
|
||||||
|
@ -1037,8 +983,8 @@ if __name__ == '__main__':
|
||||||
/></p>
|
/></p>
|
||||||
</body>
|
</body>
|
||||||
''')
|
''')
|
||||||
htmlview.display_html('<hr />')
|
htmlview.print_real_text(None, xhtml='<hr />')
|
||||||
htmlview.display_html('''
|
htmlview.print_real_text(None, xhtml='''
|
||||||
<body xmlns='http://www.w3.org/1999/xhtml'>
|
<body xmlns='http://www.w3.org/1999/xhtml'>
|
||||||
<ul style='background-color:rgb(120,140,100)'>
|
<ul style='background-color:rgb(120,140,100)'>
|
||||||
<li> One </li>
|
<li> One </li>
|
||||||
|
@ -1052,8 +998,8 @@ if __name__ == '__main__':
|
||||||
return faciter(n,1)</pre>
|
return faciter(n,1)</pre>
|
||||||
</body>
|
</body>
|
||||||
''')
|
''')
|
||||||
htmlview.display_html('<hr />')
|
htmlview.print_real_text(None, xhtml='<hr />')
|
||||||
htmlview.display_html('''
|
htmlview.print_real_text(None, xhtml='''
|
||||||
<body xmlns='http://www.w3.org/1999/xhtml'>
|
<body xmlns='http://www.w3.org/1999/xhtml'>
|
||||||
<ol style='background-color:rgb(120,140,100)'>
|
<ol style='background-color:rgb(120,140,100)'>
|
||||||
<li> One </li>
|
<li> One </li>
|
||||||
|
@ -1066,12 +1012,12 @@ if __name__ == '__main__':
|
||||||
<li> Three </li></ol>
|
<li> Three </li></ol>
|
||||||
</body>
|
</body>
|
||||||
''')
|
''')
|
||||||
htmlview.show()
|
htmlview.tv.show()
|
||||||
sw = gtk.ScrolledWindow()
|
sw = gtk.ScrolledWindow()
|
||||||
sw.set_property('hscrollbar-policy', gtk.POLICY_AUTOMATIC)
|
sw.set_property('hscrollbar-policy', gtk.POLICY_AUTOMATIC)
|
||||||
sw.set_property('vscrollbar-policy', gtk.POLICY_AUTOMATIC)
|
sw.set_property('vscrollbar-policy', gtk.POLICY_AUTOMATIC)
|
||||||
sw.set_property('border-width', 0)
|
sw.set_property('border-width', 0)
|
||||||
sw.add(htmlview)
|
sw.add(htmlview.tv)
|
||||||
sw.show()
|
sw.show()
|
||||||
frame = gtk.Frame()
|
frame = gtk.Frame()
|
||||||
frame.set_shadow_type(gtk.SHADOW_IN)
|
frame.set_shadow_type(gtk.SHADOW_IN)
|
||||||
|
|
|
@ -98,15 +98,6 @@ class MusicTrackListener(gobject.GObject):
|
||||||
'NameOwnerChanged', 'org.freedesktop.DBus',
|
'NameOwnerChanged', 'org.freedesktop.DBus',
|
||||||
arg0='net.sacredchao.QuodLibet')
|
arg0='net.sacredchao.QuodLibet')
|
||||||
|
|
||||||
## Totem
|
|
||||||
## patched by Lucky <lucky1.data@gmail.com>
|
|
||||||
## used with Totem DBus plugin:
|
|
||||||
## http://lucky.awardspace.co.uk/home/totem-plugins
|
|
||||||
bus.add_signal_receiver(self._totem_playing_started_cb,
|
|
||||||
'playingStarted', 'org.gnome.Totem')
|
|
||||||
bus.add_signal_receiver(self._totem_playing_stopped_cb,
|
|
||||||
'playingStopped', 'org.gnome.Totem')
|
|
||||||
|
|
||||||
def _player_name_owner_changed(self, name, old, new):
|
def _player_name_owner_changed(self, name, old, new):
|
||||||
if not new:
|
if not new:
|
||||||
self.emit('music-track-changed', None)
|
self.emit('music-track-changed', None)
|
||||||
|
@ -211,17 +202,6 @@ class MusicTrackListener(gobject.GObject):
|
||||||
info.duration = int(props.get('~#length', 0))
|
info.duration = int(props.get('~#length', 0))
|
||||||
return info
|
return info
|
||||||
|
|
||||||
def _totem_playing_started_cb(self, title, album, artist, duration):
|
|
||||||
self._last_playing_music = MusicTrackInfo()
|
|
||||||
self._last_playing_music.title = title
|
|
||||||
self._last_playing_music.album = album
|
|
||||||
self._last_playing_music.artist = artist
|
|
||||||
self._last_playing_music.duration = duration
|
|
||||||
self.emit('music-track-changed', self._last_playing_music)
|
|
||||||
|
|
||||||
def _totem_playing_stopped_cb(self):
|
|
||||||
self.emit('music-track-changed', None)
|
|
||||||
|
|
||||||
def get_playing_track(self):
|
def get_playing_track(self):
|
||||||
'''Return a MusicTrackInfo for the currently playing
|
'''Return a MusicTrackInfo for the currently playing
|
||||||
song, or None if no song is playing'''
|
song, or None if no song is playing'''
|
||||||
|
|
|
@ -650,7 +650,7 @@ class DesktopNotification:
|
||||||
def version_reply_handler(self, name, vendor, version, spec_version=None):
|
def version_reply_handler(self, name, vendor, version, spec_version=None):
|
||||||
if spec_version:
|
if spec_version:
|
||||||
version = spec_version
|
version = spec_version
|
||||||
elif vendor == 'Xfce' and version == '0.1.0':
|
elif vendor == 'Xfce' and version.startswith('0.1.0'):
|
||||||
version = '0.9'
|
version = '0.9'
|
||||||
version_list = version.split('.')
|
version_list = version.split('.')
|
||||||
self.version = []
|
self.version = []
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
##
|
##
|
||||||
|
|
||||||
import gobject
|
import gobject
|
||||||
|
import gtk
|
||||||
import os
|
import os
|
||||||
|
|
||||||
from common import gajim
|
from common import gajim
|
||||||
|
@ -377,7 +378,7 @@ class SignalObject(dbus.service.Object):
|
||||||
win = gajim.interface.msg_win_mgr.get_window(jid,
|
win = gajim.interface.msg_win_mgr.get_window(jid,
|
||||||
connected_account).window
|
connected_account).window
|
||||||
if win.get_property('visible'):
|
if win.get_property('visible'):
|
||||||
win.window.focus()
|
win.window.focus(gtk.get_current_event_time())
|
||||||
return DBUS_BOOLEAN(True)
|
return DBUS_BOOLEAN(True)
|
||||||
return DBUS_BOOLEAN(False)
|
return DBUS_BOOLEAN(False)
|
||||||
|
|
||||||
|
@ -507,7 +508,7 @@ class SignalObject(dbus.service.Object):
|
||||||
win.present()
|
win.present()
|
||||||
# preserve the 'steal focus preservation'
|
# preserve the 'steal focus preservation'
|
||||||
if self._is_first():
|
if self._is_first():
|
||||||
win.window.focus()
|
win.window.focus(gtk.get_current_event_time())
|
||||||
else:
|
else:
|
||||||
win.window.focus(long(time()))
|
win.window.focus(long(time()))
|
||||||
|
|
||||||
|
|
|
@ -807,6 +807,11 @@ class RosterWindow:
|
||||||
gajim.contacts.add_contact(account, contact)
|
gajim.contacts.add_contact(account, contact)
|
||||||
self.add_contact(jid, account)
|
self.add_contact(jid, account)
|
||||||
else:
|
else:
|
||||||
|
if jid not in gajim.interface.minimized_controls[account]:
|
||||||
|
# there is a window that we can minimize
|
||||||
|
gc_control = gajim.interface.msg_win_mgr.get_gc_control(jid,
|
||||||
|
account)
|
||||||
|
gajim.interface.minimized_controls[account][jid] = gc_control
|
||||||
contact.show = show
|
contact.show = show
|
||||||
contact.status = status
|
contact.status = status
|
||||||
self.adjust_and_draw_contact_context(jid, account)
|
self.adjust_and_draw_contact_context(jid, account)
|
||||||
|
@ -844,6 +849,51 @@ class RosterWindow:
|
||||||
self.remove_contact(jid, account, force=True, backend=True)
|
self.remove_contact(jid, account, force=True, backend=True)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
def rename_group(self, old_name, new_name):
|
||||||
|
"""
|
||||||
|
rename a roster group
|
||||||
|
"""
|
||||||
|
if old_name == new_name:
|
||||||
|
return
|
||||||
|
|
||||||
|
# Groups may not change name from or to a special groups
|
||||||
|
for g in helpers.special_groups:
|
||||||
|
if g in (new_name, old_name):
|
||||||
|
return
|
||||||
|
|
||||||
|
# update all contacts in the given group
|
||||||
|
if self.regroup:
|
||||||
|
accounts = gajim.connections.keys()
|
||||||
|
else:
|
||||||
|
accounts = [account,]
|
||||||
|
|
||||||
|
for acc in accounts:
|
||||||
|
changed_contacts = []
|
||||||
|
for jid in gajim.contacts.get_jid_list(acc):
|
||||||
|
contact = gajim.contacts.get_first_contact_from_jid(acc, jid)
|
||||||
|
if old_name not in contact.groups:
|
||||||
|
continue
|
||||||
|
|
||||||
|
self.remove_contact(jid, acc, force=True)
|
||||||
|
|
||||||
|
contact.groups.remove(old_name)
|
||||||
|
if new_name not in contact.groups:
|
||||||
|
contact.groups.append(new_name)
|
||||||
|
|
||||||
|
changed_contacts.append({'jid':jid, 'name':contact.name,
|
||||||
|
'groups':contact.groups})
|
||||||
|
|
||||||
|
gajim.connections[acc].update_contacts(changed_contacts)
|
||||||
|
|
||||||
|
for c in changed_contacts:
|
||||||
|
self.add_contact(c['jid'], acc)
|
||||||
|
|
||||||
|
self._adjust_group_expand_collapse_state(new_name, acc)
|
||||||
|
|
||||||
|
self.draw_group(old_name, acc)
|
||||||
|
self.draw_group(new_name, acc)
|
||||||
|
|
||||||
|
|
||||||
def add_contact_to_groups(self, jid, account, groups, update=True):
|
def add_contact_to_groups(self, jid, account, groups, update=True):
|
||||||
'''Add contact to given groups and redraw them.
|
'''Add contact to given groups and redraw them.
|
||||||
|
|
||||||
|
@ -1108,7 +1158,9 @@ class RosterWindow:
|
||||||
if c.show not in ('error', 'offline'):
|
if c.show not in ('error', 'offline'):
|
||||||
nb_connected_contact += 1
|
nb_connected_contact += 1
|
||||||
if nb_connected_contact > 1:
|
if nb_connected_contact > 1:
|
||||||
name += ' (' + unicode(nb_connected_contact) + ')'
|
# switch back to default writing direction
|
||||||
|
name += i18n.paragraph_direction_mark(unicode(name))
|
||||||
|
name += u' (%d)' % nb_connected_contact
|
||||||
|
|
||||||
# show (account_name) if there are 2 contact with same jid
|
# show (account_name) if there are 2 contact with same jid
|
||||||
# in merged mode
|
# in merged mode
|
||||||
|
@ -2704,23 +2756,7 @@ class RosterWindow:
|
||||||
win.show_title()
|
win.show_title()
|
||||||
elif row_type == 'group':
|
elif row_type == 'group':
|
||||||
# in C_JID column, we hold the group name (which is not escaped)
|
# in C_JID column, we hold the group name (which is not escaped)
|
||||||
if old_text == new_text:
|
self.rename_group(old_text, new_text)
|
||||||
return
|
|
||||||
# Groups may not change name from or to a special groups
|
|
||||||
for g in helpers.special_groups:
|
|
||||||
if g in (new_text, old_text):
|
|
||||||
return
|
|
||||||
# update all contacts in the given group
|
|
||||||
if self.regroup:
|
|
||||||
accounts = gajim.connections.keys()
|
|
||||||
else:
|
|
||||||
accounts = [account,]
|
|
||||||
for acc in accounts:
|
|
||||||
for jid in gajim.contacts.get_jid_list(acc):
|
|
||||||
contact = gajim.contacts.get_first_contact_from_jid(acc, jid)
|
|
||||||
if old_text in contact.groups:
|
|
||||||
self.add_contact_to_groups(jid, acc, [new_text,])
|
|
||||||
self.remove_contact_from_groups(jid, acc, [old_text,])
|
|
||||||
|
|
||||||
def on_canceled():
|
def on_canceled():
|
||||||
if 'rename' in gajim.interface.instances:
|
if 'rename' in gajim.interface.instances:
|
||||||
|
@ -2919,6 +2955,12 @@ class RosterWindow:
|
||||||
def on_groupchat_maximized(self, widget, jid, account):
|
def on_groupchat_maximized(self, widget, jid, account):
|
||||||
'''When a groupchat is maximised'''
|
'''When a groupchat is maximised'''
|
||||||
if not jid in gajim.interface.minimized_controls[account]:
|
if not jid in gajim.interface.minimized_controls[account]:
|
||||||
|
# Already opened?
|
||||||
|
gc_control = gajim.interface.msg_win_mgr.get_gc_control(jid, account)
|
||||||
|
if gc_control:
|
||||||
|
mw = gajim.interface.msg_win_mgr.get_window(jid, account)
|
||||||
|
mw.set_active_tab(gc_control)
|
||||||
|
mw.window.window.focus(gtk.get_current_event_time())
|
||||||
return
|
return
|
||||||
ctrl = gajim.interface.minimized_controls[account][jid]
|
ctrl = gajim.interface.minimized_controls[account][jid]
|
||||||
mw = gajim.interface.msg_win_mgr.get_window(jid, account)
|
mw = gajim.interface.msg_win_mgr.get_window(jid, account)
|
||||||
|
@ -2928,7 +2970,7 @@ class RosterWindow:
|
||||||
ctrl.parent_win = mw
|
ctrl.parent_win = mw
|
||||||
mw.new_tab(ctrl)
|
mw.new_tab(ctrl)
|
||||||
mw.set_active_tab(ctrl)
|
mw.set_active_tab(ctrl)
|
||||||
mw.window.window.focus()
|
mw.window.window.focus(gtk.get_current_event_time())
|
||||||
self.remove_groupchat(jid, account)
|
self.remove_groupchat(jid, account)
|
||||||
|
|
||||||
def on_edit_account(self, widget, account):
|
def on_edit_account(self, widget, account):
|
||||||
|
@ -3977,6 +4019,8 @@ class RosterWindow:
|
||||||
return
|
return
|
||||||
c_dest = gajim.contacts.get_contact_with_highest_priority(account_dest,
|
c_dest = gajim.contacts.get_contact_with_highest_priority(account_dest,
|
||||||
jid_dest)
|
jid_dest)
|
||||||
|
if not gajim.capscache.is_supported(c_dest, NS_FILE):
|
||||||
|
return
|
||||||
uri = data.strip()
|
uri = data.strip()
|
||||||
uri_splitted = uri.split() # we may have more than one file dropped
|
uri_splitted = uri.split() # we may have more than one file dropped
|
||||||
try:
|
try:
|
||||||
|
|
|
@ -250,7 +250,7 @@ class ChatControlSession(stanza_session.EncryptedStanzaSession):
|
||||||
|
|
||||||
if self.control:
|
if self.control:
|
||||||
parent_win = self.control.parent_win
|
parent_win = self.control.parent_win
|
||||||
if self.control == parent_win.get_active_control() and \
|
if parent_win and self.control == parent_win.get_active_control() and \
|
||||||
parent_win.window.has_focus:
|
parent_win.window.has_focus:
|
||||||
focused = True
|
focused = True
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue