merge default branch to jingle
This commit is contained in:
		
						commit
						01d7be2d61
					
				
					 21 changed files with 1596 additions and 1535 deletions
				
			
		
							
								
								
									
										2587
									
								
								po/pt_BR.po
									
										
									
									
									
								
							
							
						
						
									
										2587
									
								
								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)))
 | 
			
		||||
                elif spec_len == 1:
 | 
			
		||||
                    args = [(arguments, (0, arguments_end))]
 | 
			
		||||
                    opts = []
 | 
			
		||||
                else:
 | 
			
		||||
                    raise InternalError("Raw command must define a collector")
 | 
			
		||||
            else:
 | 
			
		||||
| 
						 | 
				
			
			@ -642,21 +643,21 @@ class CommandProcessor(object):
 | 
			
		|||
        if not text.startswith(self.COMMAND_PREFIX):
 | 
			
		||||
            return False
 | 
			
		||||
 | 
			
		||||
        text = text[len(self.COMMAND_PREFIX):]
 | 
			
		||||
        text = text.strip()
 | 
			
		||||
        body = text[len(self.COMMAND_PREFIX):]
 | 
			
		||||
        body = body.strip()
 | 
			
		||||
 | 
			
		||||
        parts = text.split(' ', 1)
 | 
			
		||||
        parts = body.split(' ', 1)
 | 
			
		||||
        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:
 | 
			
		||||
            return flag
 | 
			
		||||
 | 
			
		||||
        self.execute_command(name, arguments)
 | 
			
		||||
        self.execute_command(text, name, arguments)
 | 
			
		||||
 | 
			
		||||
        return True
 | 
			
		||||
 | 
			
		||||
    def execute_command(self, name, arguments):
 | 
			
		||||
    def execute_command(self, text, name, arguments):
 | 
			
		||||
        command = self.retrieve_command(name)
 | 
			
		||||
 | 
			
		||||
        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()
 | 
			
		||||
        except KeyError:
 | 
			
		||||
            try:
 | 
			
		||||
                dialogs.JoinGroupchatWindow(account=None, room_jid=jid, nick=nick)
 | 
			
		||||
                dialogs.JoinGroupchatWindow(account=self.account, room_jid=jid, nick=nick)
 | 
			
		||||
            except GajimGeneralException:
 | 
			
		||||
                pass
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -31,16 +31,14 @@ class ChatMiddleware(CommandProcessor):
 | 
			
		|||
    Also provides some few basic utilities for the same purpose.
 | 
			
		||||
    """
 | 
			
		||||
 | 
			
		||||
    def process_as_command(self, text):
 | 
			
		||||
    def execute_command(self, text, name, arguments):
 | 
			
		||||
        try:
 | 
			
		||||
            return super(ChatMiddleware, self).process_as_command(text)
 | 
			
		||||
            super(ChatMiddleware, self).execute_command(text, name, arguments)
 | 
			
		||||
        except CommandError, exception:
 | 
			
		||||
            self.echo("%s: %s" %(exception.name, exception.message), 'error')
 | 
			
		||||
            return True
 | 
			
		||||
        except Exception:
 | 
			
		||||
            self.echo("An error occured while trying to execute the command", 'error')
 | 
			
		||||
            print_exc()
 | 
			
		||||
            return True
 | 
			
		||||
        finally:
 | 
			
		||||
            self.add_history(text)
 | 
			
		||||
            self.clear_input()
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1487,6 +1487,11 @@ class Connection(ConnectionHandlers):
 | 
			
		|||
			self.connection.getRoster().setItem(jid = jid, name = name,
 | 
			
		||||
				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):
 | 
			
		||||
		if is_form:
 | 
			
		||||
			# 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')
 | 
			
		||||
		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):
 | 
			
		||||
		'''Get Bookmarks from storage or PubSub if supported as described in
 | 
			
		||||
		XEP 0048
 | 
			
		||||
| 
						 | 
				
			
			@ -1606,11 +1621,11 @@ class Connection(ConnectionHandlers):
 | 
			
		|||
			return
 | 
			
		||||
		if self.pubsub_supported and storage_type != 'xml':
 | 
			
		||||
			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:
 | 
			
		||||
			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)
 | 
			
		||||
			self._request_bookmarks_xml()
 | 
			
		||||
 | 
			
		||||
	def store_bookmarks(self, storage_type=None):
 | 
			
		||||
		''' Send bookmarks to the storage namespace or PubSub if supported
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -183,7 +183,7 @@ else:
 | 
			
		|||
import latex
 | 
			
		||||
HAVE_LATEX = latex.check_for_latex_support()
 | 
			
		||||
 | 
			
		||||
HAVE_INDICATOR = True
 | 
			
		||||
HAVE_INDICATOR = False
 | 
			
		||||
try:
 | 
			
		||||
	import indicate
 | 
			
		||||
except ImportError:
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -170,6 +170,11 @@ def prep(user, server, resource):
 | 
			
		|||
		else:
 | 
			
		||||
			return server
 | 
			
		||||
 | 
			
		||||
def windowsify(s):
 | 
			
		||||
	if os.name == 'nt':
 | 
			
		||||
		return s.capitalize()
 | 
			
		||||
	return s
 | 
			
		||||
 | 
			
		||||
def temp_failure_retry(func, *args, **kwargs):
 | 
			
		||||
	while True:
 | 
			
		||||
		try:
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -5,6 +5,7 @@
 | 
			
		|||
## Copyright (C) 2004 Vincent Hanquez <tab AT snarc.org>
 | 
			
		||||
## Copyright (C) 2004-2007 Yann Leboulanger <asterix AT lagaule.org>
 | 
			
		||||
## 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.
 | 
			
		||||
##
 | 
			
		||||
| 
						 | 
				
			
			@ -25,6 +26,23 @@ import locale
 | 
			
		|||
import gettext
 | 
			
		||||
import os
 | 
			
		||||
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'
 | 
			
		||||
DIR = defs.localedir
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -174,6 +174,16 @@ class NonBlockingRoster(PlugIn):
 | 
			
		|||
		item=query.setTag('item',attrs)
 | 
			
		||||
		for group in groups: item.addChild(node=Node('group',payload=[group]))
 | 
			
		||||
		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):
 | 
			
		||||
		''' Return list of all [bare] JIDs that the roster is currently tracks.'''
 | 
			
		||||
		return self._data.keys()
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -526,6 +526,11 @@ class ConnectionZeroconf(ConnectionHandlersZeroconf):
 | 
			
		|||
			self.connection.getRoster().setItem(jid = jid, name = name,
 | 
			
		||||
				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):
 | 
			
		||||
		gajim.log.debug('This should not happen (new_account)')
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -88,6 +88,10 @@ class Roster:
 | 
			
		|||
		self._data[jid]['status'] = 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):
 | 
			
		||||
		#print 'roster_zeroconf.py: delItem %s' % jid
 | 
			
		||||
		if jid in self._data:
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -954,6 +954,13 @@ class ConversationTextview(gobject.GObject):
 | 
			
		|||
		print_conversation_line()'''
 | 
			
		||||
 | 
			
		||||
		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
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -974,8 +981,7 @@ class ConversationTextview(gobject.GObject):
 | 
			
		|||
				text_before_special_text = otext[index:start]
 | 
			
		||||
				end_iter = buffer_.get_end_iter()
 | 
			
		||||
				# we insert normal text
 | 
			
		||||
				buffer_.insert_with_tags_by_name(end_iter,
 | 
			
		||||
					text_before_special_text, *other_tags)
 | 
			
		||||
				insert_tags_func(end_iter, text_before_special_text, *other_tags)
 | 
			
		||||
			index = end # update index
 | 
			
		||||
 | 
			
		||||
			# now print it
 | 
			
		||||
| 
						 | 
				
			
			@ -984,7 +990,11 @@ class ConversationTextview(gobject.GObject):
 | 
			
		|||
			if specials_limit <= 0:
 | 
			
		||||
				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):
 | 
			
		||||
		'''is called by detect_and_print_special_text and prints
 | 
			
		||||
| 
						 | 
				
			
			@ -1280,22 +1290,17 @@ class ConversationTextview(gobject.GObject):
 | 
			
		|||
			try:
 | 
			
		||||
				if name and (text.startswith('/me ') or text.startswith('/me\n')):
 | 
			
		||||
					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
 | 
			
		||||
			except Exception, e:
 | 
			
		||||
				gajim.log.debug(str('Error processing xhtml') + str(e))
 | 
			
		||||
				gajim.log.debug(str('with |' + xhtml + '|'))
 | 
			
		||||
 | 
			
		||||
		buffer_ = self.tv.get_buffer()
 | 
			
		||||
		# /me is replaced by name if name is given
 | 
			
		||||
		if name and (text.startswith('/me ') or text.startswith('/me\n')):
 | 
			
		||||
			text = '* ' + name + text[3:]
 | 
			
		||||
			text_tags.append('italic')
 | 
			
		||||
		# detect urls formatting and if the user has it on emoticons
 | 
			
		||||
		index = 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)
 | 
			
		||||
		self.detect_and_print_special_text(text, text_tags)
 | 
			
		||||
 | 
			
		||||
# vim: se ts=3:
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2504,6 +2504,16 @@ class SingleMessageWindow:
 | 
			
		|||
 | 
			
		||||
	def on_single_message_window_destroy(self, widget):
 | 
			
		||||
		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):
 | 
			
		||||
		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)
 | 
			
		||||
		if w:
 | 
			
		||||
			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
 | 
			
		||||
			if isinstance(ctrl, ChatControlBase):
 | 
			
		||||
				tv = ctrl.conv_textview
 | 
			
		||||
| 
						 | 
				
			
			@ -3109,8 +3109,8 @@ class Interface:
 | 
			
		|||
			pass
 | 
			
		||||
 | 
			
		||||
	def enable_music_listener(self):
 | 
			
		||||
		listener = MusicTrackListener.get()
 | 
			
		||||
		if not self.music_track_changed_signal:
 | 
			
		||||
			listener = MusicTrackListener.get()
 | 
			
		||||
			self.music_track_changed_signal = listener.connect(
 | 
			
		||||
				'music-track-changed', self.music_track_changed)
 | 
			
		||||
		track = listener.get_playing_track()
 | 
			
		||||
| 
						 | 
				
			
			@ -3452,6 +3452,49 @@ class Interface:
 | 
			
		|||
		view.updateNamespace({'gajim': gajim})
 | 
			
		||||
		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):
 | 
			
		||||
		gajim.interface = self
 | 
			
		||||
		gajim.thread_interface = ThreadInterface
 | 
			
		||||
| 
						 | 
				
			
			@ -3654,9 +3697,6 @@ class Interface:
 | 
			
		|||
			if self.systray_capabilities:
 | 
			
		||||
				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')
 | 
			
		||||
		pix = gtk.gdk.pixbuf_new_from_file(path_to_file)
 | 
			
		||||
		# set the icon to all windows
 | 
			
		||||
| 
						 | 
				
			
			@ -3665,13 +3705,6 @@ class Interface:
 | 
			
		|||
		self.init_emoticons()
 | 
			
		||||
		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
 | 
			
		||||
		gajim.transport_type = gajim.logger.get_transports_type()
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -3699,37 +3732,7 @@ class Interface:
 | 
			
		|||
 | 
			
		||||
		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
 | 
			
		||||
		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__':
 | 
			
		||||
	def sigint_cb(num, stack):
 | 
			
		||||
| 
						 | 
				
			
			@ -3768,7 +3771,8 @@ if __name__ == '__main__':
 | 
			
		|||
 | 
			
		||||
	check_paths.check_and_possibly_create_paths()
 | 
			
		||||
 | 
			
		||||
	Interface()
 | 
			
		||||
	interface = Interface()
 | 
			
		||||
	interface.run()
 | 
			
		||||
 | 
			
		||||
	try:
 | 
			
		||||
		if os.name != 'nt':
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1229,15 +1229,15 @@ class GroupchatControl(ChatControlBase, GroupChatCommands):
 | 
			
		|||
						# Stop all E2E sessions
 | 
			
		||||
						nick_list = gajim.contacts.get_nick_list(self.account,
 | 
			
		||||
							self.room_jid)
 | 
			
		||||
						for nick in nick_list:
 | 
			
		||||
							fjid = self.room_jid + '/' + nick
 | 
			
		||||
							ctrl = gajim.interface.msg_win_mgr.get_control(fjid,
 | 
			
		||||
						for nick_ in nick_list:
 | 
			
		||||
							fjid_ = self.room_jid + '/' + nick_
 | 
			
		||||
							ctrl = gajim.interface.msg_win_mgr.get_control(fjid_,
 | 
			
		||||
								self.account)
 | 
			
		||||
							if ctrl and ctrl.session and \
 | 
			
		||||
							ctrl.session.enable_encryption:
 | 
			
		||||
								thread_id = ctrl.session.thread_id
 | 
			
		||||
								ctrl.session.terminate_e2e()
 | 
			
		||||
								gajim.connections[self.account].delete_session(fjid,
 | 
			
		||||
								gajim.connections[self.account].delete_session(fjid_,
 | 
			
		||||
									thread_id)
 | 
			
		||||
								ctrl.no_autonegotiation = False
 | 
			
		||||
					else:
 | 
			
		||||
| 
						 | 
				
			
			@ -1271,8 +1271,10 @@ class GroupchatControl(ChatControlBase, GroupChatCommands):
 | 
			
		|||
							os.path.join(path, puny_new_nick + ext)
 | 
			
		||||
					for old_file in files:
 | 
			
		||||
						if os.path.exists(old_file) and old_file != files[old_file]:
 | 
			
		||||
							if os.path.exists(files[old_file]):
 | 
			
		||||
								# Windows require this
 | 
			
		||||
							if os.path.exists(files[old_file]) and helpers.windowsify(
 | 
			
		||||
							old_file) != helpers.windowsify(files[old_file]):
 | 
			
		||||
								# Windows require this, but os.remove('test') will also
 | 
			
		||||
								# remove 'TEST'
 | 
			
		||||
								os.remove(files[old_file])
 | 
			
		||||
							os.rename(old_file, files[old_file])
 | 
			
		||||
					self.print_conversation(s, 'info', tim)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -50,6 +50,8 @@ import operator
 | 
			
		|||
 | 
			
		||||
if __name__ == '__main__':
 | 
			
		||||
	from common import i18n
 | 
			
		||||
	import common.configpaths
 | 
			
		||||
	common.configpaths.gajimpaths.init(None)
 | 
			
		||||
from common import gajim
 | 
			
		||||
 | 
			
		||||
import tooltips
 | 
			
		||||
| 
						 | 
				
			
			@ -184,25 +186,6 @@ for name in BLOCK_HEAD:
 | 
			
		|||
													('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):
 | 
			
		||||
	'''_parse_css_color(css_color) -> gtk.gdk.Color'''
 | 
			
		||||
	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)
 | 
			
		||||
	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)
 | 
			
		||||
		self.textbuf = textview.get_buffer()
 | 
			
		||||
		self.textview = textview
 | 
			
		||||
		self.textbuf = conv_textview.tv.get_buffer()
 | 
			
		||||
		self.textview = conv_textview.tv
 | 
			
		||||
		self.iter = startiter
 | 
			
		||||
		self.conv_textview = conv_textview
 | 
			
		||||
		self.text = ''
 | 
			
		||||
		self.starting=True
 | 
			
		||||
		self.preserve = False
 | 
			
		||||
| 
						 | 
				
			
			@ -499,6 +483,7 @@ class HtmlHandler(xml.sax.handler.ContentHandler):
 | 
			
		|||
	def _process_img(self, attrs):
 | 
			
		||||
		'''Process a img tag.
 | 
			
		||||
		'''
 | 
			
		||||
		mem = ''
 | 
			
		||||
		try:
 | 
			
		||||
			# Wait maximum 1s for connection
 | 
			
		||||
			socket.setdefaulttimeout(1)
 | 
			
		||||
| 
						 | 
				
			
			@ -514,40 +499,38 @@ class HtmlHandler(xml.sax.handler.ContentHandler):
 | 
			
		|||
					f.fp._sock.fp._sock.settimeout(0.5)
 | 
			
		||||
				except Exception:
 | 
			
		||||
					pass
 | 
			
		||||
			# Max image size = 2 MB (to try to prevent DoS)
 | 
			
		||||
			mem = ''
 | 
			
		||||
			deadline = time.time() + 3
 | 
			
		||||
			while True:
 | 
			
		||||
				if time.time() > deadline:
 | 
			
		||||
					gajim.log.debug(str('Timeout loading image %s ' % \
 | 
			
		||||
						attrs['src'] + ex))
 | 
			
		||||
					mem = ''
 | 
			
		||||
					alt = attrs.get('alt', '')
 | 
			
		||||
					if alt:
 | 
			
		||||
						alt += '\n'
 | 
			
		||||
					alt += _('Timeout loading image')
 | 
			
		||||
					break
 | 
			
		||||
				try:
 | 
			
		||||
					temp = f.read(100)
 | 
			
		||||
				except socket.timeout, ex:
 | 
			
		||||
					gajim.log.debug('Timeout loading image %s ' % attrs['src'] + \
 | 
			
		||||
						str(ex))
 | 
			
		||||
					mem = ''
 | 
			
		||||
					alt = attrs.get('alt', '')
 | 
			
		||||
					if alt:
 | 
			
		||||
						alt += '\n'
 | 
			
		||||
					alt += _('Timeout loading image')
 | 
			
		||||
					break
 | 
			
		||||
				if temp:
 | 
			
		||||
					mem += temp
 | 
			
		||||
				else:
 | 
			
		||||
					break
 | 
			
		||||
				if len(mem) > 2*1024*1024:
 | 
			
		||||
					alt = attrs.get('alt', '')
 | 
			
		||||
					if alt:
 | 
			
		||||
						alt += '\n'
 | 
			
		||||
					alt += _('Image is too big')
 | 
			
		||||
					break
 | 
			
		||||
				# Max image size = 2 MB (to try to prevent DoS)
 | 
			
		||||
				deadline = time.time() + 3
 | 
			
		||||
				while True:
 | 
			
		||||
					if time.time() > deadline:
 | 
			
		||||
						gajim.log.debug(str('Timeout loading image %s ' % \
 | 
			
		||||
							attrs['src'] + ex))
 | 
			
		||||
						mem = ''
 | 
			
		||||
						alt = attrs.get('alt', '')
 | 
			
		||||
						if alt:
 | 
			
		||||
							alt += '\n'
 | 
			
		||||
						alt += _('Timeout loading image')
 | 
			
		||||
						break
 | 
			
		||||
					try:
 | 
			
		||||
						temp = f.read(100)
 | 
			
		||||
					except socket.timeout, ex:
 | 
			
		||||
						gajim.log.debug('Timeout loading image %s ' % attrs['src'] + \
 | 
			
		||||
							str(ex))
 | 
			
		||||
						alt = attrs.get('alt', '')
 | 
			
		||||
						if alt:
 | 
			
		||||
							alt += '\n'
 | 
			
		||||
						alt += _('Timeout loading image')
 | 
			
		||||
						break
 | 
			
		||||
					if temp:
 | 
			
		||||
						mem += temp
 | 
			
		||||
					else:
 | 
			
		||||
						break
 | 
			
		||||
					if len(mem) > 2*1024*1024:
 | 
			
		||||
						alt = attrs.get('alt', '')
 | 
			
		||||
						if alt:
 | 
			
		||||
							alt += '\n'
 | 
			
		||||
						alt += _('Image is too big')
 | 
			
		||||
						break
 | 
			
		||||
			pixbuf = None
 | 
			
		||||
			if mem:
 | 
			
		||||
				# Caveat: GdkPixbuf is known not to be safe to load
 | 
			
		||||
| 
						 | 
				
			
			@ -672,51 +655,7 @@ class HtmlHandler(xml.sax.handler.ContentHandler):
 | 
			
		|||
		return False
 | 
			
		||||
 | 
			
		||||
	def handle_specials(self, text):
 | 
			
		||||
		index = 0
 | 
			
		||||
		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:])
 | 
			
		||||
		self.iter = self.conv_textview.detect_and_print_special_text(text, 							self._get_style_tags())
 | 
			
		||||
 | 
			
		||||
	def characters(self, content):
 | 
			
		||||
		if self.preserve:
 | 
			
		||||
| 
						 | 
				
			
			@ -870,7 +809,6 @@ class HtmlTextView(gtk.TextView):
 | 
			
		|||
		self.config = gajim.config
 | 
			
		||||
		self.interface = gajim.interface
 | 
			
		||||
		# end big hack
 | 
			
		||||
		build_patterns(self,gajim.config,gajim.interface)
 | 
			
		||||
 | 
			
		||||
	def __destroy_event(self, widget):
 | 
			
		||||
		if self.tooltip.timeout != 0:
 | 
			
		||||
| 
						 | 
				
			
			@ -921,14 +859,14 @@ class HtmlTextView(gtk.TextView):
 | 
			
		|||
			self._changed_cursor = False
 | 
			
		||||
		return False
 | 
			
		||||
 | 
			
		||||
	def display_html(self, html):
 | 
			
		||||
	def display_html(self, html, conv_textview):
 | 
			
		||||
		buffer_ = self.get_buffer()
 | 
			
		||||
		eob = buffer_.get_end_iter()
 | 
			
		||||
		## this works too if libxml2 is not available
 | 
			
		||||
		# parser = xml.sax.make_parser(['drv_libxml2'])
 | 
			
		||||
		# parser.setFeature(xml.sax.handler.feature_validation, True)
 | 
			
		||||
		parser = xml.sax.make_parser()
 | 
			
		||||
		parser.setContentHandler(HtmlHandler(self, eob))
 | 
			
		||||
		parser.setContentHandler(HtmlHandler(conv_textview, eob))
 | 
			
		||||
		parser.parse(StringIO(html))
 | 
			
		||||
 | 
			
		||||
		# too much space after :)
 | 
			
		||||
| 
						 | 
				
			
			@ -942,6 +880,9 @@ change_cursor = None
 | 
			
		|||
if __name__ == '__main__':
 | 
			
		||||
	import os
 | 
			
		||||
 | 
			
		||||
	from conversation_textview import ConversationTextview
 | 
			
		||||
	import gajim as gaj
 | 
			
		||||
 | 
			
		||||
	class log(object):
 | 
			
		||||
 | 
			
		||||
		def debug(self, text):
 | 
			
		||||
| 
						 | 
				
			
			@ -953,33 +894,32 @@ if __name__ == '__main__':
 | 
			
		|||
 | 
			
		||||
	gajim.log=log()
 | 
			
		||||
 | 
			
		||||
	if gajim.config.get('emoticons_theme'):
 | 
			
		||||
		print "emoticons"
 | 
			
		||||
	gaj.Interface()
 | 
			
		||||
 | 
			
		||||
	htmlview = HtmlTextView()
 | 
			
		||||
	htmlview = ConversationTextview(None)
 | 
			
		||||
 | 
			
		||||
	path_to_file = os.path.join(gajim.DATA_DIR, 'pixmaps', 'muc_separator.png')
 | 
			
		||||
	# 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()
 | 
			
		||||
	def on_textview_motion_notify_event(widget, event):
 | 
			
		||||
		'''change the cursor to a hand when we are over a mail or an url'''
 | 
			
		||||
		global change_cursor
 | 
			
		||||
		pointer_x, pointer_y = htmlview.window.get_pointer()[0:2]
 | 
			
		||||
		x, y = htmlview.window_to_buffer_coords(gtk.TEXT_WINDOW_TEXT, pointer_x,
 | 
			
		||||
		pointer_x, pointer_y = htmlview.tv.window.get_pointer()[0:2]
 | 
			
		||||
		x, y = htmlview.tv.window_to_buffer_coords(gtk.TEXT_WINDOW_TEXT, pointer_x,
 | 
			
		||||
								   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:
 | 
			
		||||
			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))
 | 
			
		||||
			change_cursor = None
 | 
			
		||||
		tag_table = htmlview.get_buffer().get_tag_table()
 | 
			
		||||
		tag_table = htmlview.tv.get_buffer().get_tag_table()
 | 
			
		||||
		for tag in tags:
 | 
			
		||||
			try:
 | 
			
		||||
				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))
 | 
			
		||||
					change_cursor = tag
 | 
			
		||||
				elif tag == tag_table.lookup('focus-out-line'):
 | 
			
		||||
| 
						 | 
				
			
			@ -994,32 +934,38 @@ if __name__ == '__main__':
 | 
			
		|||
		#if over_line and not line_tooltip.win:
 | 
			
		||||
		#	line_tooltip.timeout = gobject.timeout_add(500,
 | 
			
		||||
		#		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))
 | 
			
		||||
		#	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):
 | 
			
		||||
		if event.type == gtk.gdk.BUTTON_PRESS:
 | 
			
		||||
			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'
 | 
			
		||||
						  '  <span style="font-size: 500%; font-family: serif">World</span>\n'
 | 
			
		||||
						  '</div>\n')
 | 
			
		||||
	htmlview.display_html('<hr />')
 | 
			
		||||
	htmlview.display_html('''
 | 
			
		||||
	htmlview.print_real_text(None, xhtml='<hr />')
 | 
			
		||||
	htmlview.print_real_text(None, xhtml='''
 | 
			
		||||
	  <p style='font-size:large'>
 | 
			
		||||
		<span style='font-style: italic'>O<span style='font-size:larger'>M</span>G</span>,
 | 
			
		||||
		I'm <span style='color:green'>green</span>
 | 
			
		||||
		with <span style='font-weight: bold'>envy</span>!
 | 
			
		||||
	  </p>
 | 
			
		||||
		''')
 | 
			
		||||
	htmlview.display_html('<hr />')
 | 
			
		||||
	htmlview.display_html('''
 | 
			
		||||
	htmlview.print_real_text(None, xhtml='<hr />')
 | 
			
		||||
	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'>
 | 
			
		||||
	  <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%'>
 | 
			
		||||
| 
						 | 
				
			
			@ -1027,8 +973,8 @@ if __name__ == '__main__':
 | 
			
		|||
	  </p>
 | 
			
		||||
	</body>
 | 
			
		||||
		''')
 | 
			
		||||
	htmlview.display_html('<hr />')
 | 
			
		||||
	htmlview.display_html('''
 | 
			
		||||
	htmlview.print_real_text(None, xhtml='<hr />')
 | 
			
		||||
	htmlview.print_real_text(None, 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:right'><img src='http://www.jabber.org/images/psa-license.jpg'
 | 
			
		||||
| 
						 | 
				
			
			@ -1037,8 +983,8 @@ if __name__ == '__main__':
 | 
			
		|||
			  /></p>
 | 
			
		||||
	</body>
 | 
			
		||||
		''')
 | 
			
		||||
	htmlview.display_html('<hr />')
 | 
			
		||||
	htmlview.display_html('''
 | 
			
		||||
	htmlview.print_real_text(None, xhtml='<hr />')
 | 
			
		||||
	htmlview.print_real_text(None, xhtml='''
 | 
			
		||||
	<body xmlns='http://www.w3.org/1999/xhtml'>
 | 
			
		||||
	  <ul style='background-color:rgb(120,140,100)'>
 | 
			
		||||
	   <li> One </li>
 | 
			
		||||
| 
						 | 
				
			
			@ -1052,8 +998,8 @@ if __name__ == '__main__':
 | 
			
		|||
  return faciter(n,1)</pre>
 | 
			
		||||
	</body>
 | 
			
		||||
		''')
 | 
			
		||||
	htmlview.display_html('<hr />')
 | 
			
		||||
	htmlview.display_html('''
 | 
			
		||||
	htmlview.print_real_text(None, xhtml='<hr />')
 | 
			
		||||
	htmlview.print_real_text(None, xhtml='''
 | 
			
		||||
	<body xmlns='http://www.w3.org/1999/xhtml'>
 | 
			
		||||
	 <ol style='background-color:rgb(120,140,100)'>
 | 
			
		||||
	   <li> One </li>
 | 
			
		||||
| 
						 | 
				
			
			@ -1066,12 +1012,12 @@ if __name__ == '__main__':
 | 
			
		|||
	   <li> Three </li></ol>
 | 
			
		||||
	</body>
 | 
			
		||||
		''')
 | 
			
		||||
	htmlview.show()
 | 
			
		||||
	htmlview.tv.show()
 | 
			
		||||
	sw = gtk.ScrolledWindow()
 | 
			
		||||
	sw.set_property('hscrollbar-policy', gtk.POLICY_AUTOMATIC)
 | 
			
		||||
	sw.set_property('vscrollbar-policy', gtk.POLICY_AUTOMATIC)
 | 
			
		||||
	sw.set_property('border-width', 0)
 | 
			
		||||
	sw.add(htmlview)
 | 
			
		||||
	sw.add(htmlview.tv)
 | 
			
		||||
	sw.show()
 | 
			
		||||
	frame = gtk.Frame()
 | 
			
		||||
	frame.set_shadow_type(gtk.SHADOW_IN)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -98,15 +98,6 @@ class MusicTrackListener(gobject.GObject):
 | 
			
		|||
			'NameOwnerChanged', 'org.freedesktop.DBus',
 | 
			
		||||
			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):
 | 
			
		||||
		if not new:
 | 
			
		||||
			self.emit('music-track-changed', None)
 | 
			
		||||
| 
						 | 
				
			
			@ -211,17 +202,6 @@ class MusicTrackListener(gobject.GObject):
 | 
			
		|||
		info.duration = int(props.get('~#length', 0))
 | 
			
		||||
		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):
 | 
			
		||||
		'''Return a MusicTrackInfo for the currently 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):
 | 
			
		||||
		if 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_list = version.split('.')
 | 
			
		||||
		self.version = []
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -27,6 +27,7 @@
 | 
			
		|||
##
 | 
			
		||||
 | 
			
		||||
import gobject
 | 
			
		||||
import gtk
 | 
			
		||||
import os
 | 
			
		||||
 | 
			
		||||
from common import gajim
 | 
			
		||||
| 
						 | 
				
			
			@ -377,7 +378,7 @@ class SignalObject(dbus.service.Object):
 | 
			
		|||
			win = gajim.interface.msg_win_mgr.get_window(jid,
 | 
			
		||||
				connected_account).window
 | 
			
		||||
			if win.get_property('visible'):
 | 
			
		||||
				win.window.focus()
 | 
			
		||||
				win.window.focus(gtk.get_current_event_time())
 | 
			
		||||
			return DBUS_BOOLEAN(True)
 | 
			
		||||
		return DBUS_BOOLEAN(False)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -507,7 +508,7 @@ class SignalObject(dbus.service.Object):
 | 
			
		|||
			win.present()
 | 
			
		||||
			# preserve the 'steal focus preservation'
 | 
			
		||||
			if self._is_first():
 | 
			
		||||
				win.window.focus()
 | 
			
		||||
				win.window.focus(gtk.get_current_event_time())
 | 
			
		||||
			else:
 | 
			
		||||
				win.window.focus(long(time()))
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -807,6 +807,11 @@ class RosterWindow:
 | 
			
		|||
			gajim.contacts.add_contact(account, contact)
 | 
			
		||||
			self.add_contact(jid, account)
 | 
			
		||||
		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.status = status
 | 
			
		||||
			self.adjust_and_draw_contact_context(jid, account)
 | 
			
		||||
| 
						 | 
				
			
			@ -843,6 +848,51 @@ class RosterWindow:
 | 
			
		|||
		'''Remove transport from roster and redraw account and group.'''
 | 
			
		||||
		self.remove_contact(jid, account, force=True, backend=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):
 | 
			
		||||
		'''Add contact to given groups and redraw them.
 | 
			
		||||
| 
						 | 
				
			
			@ -1108,7 +1158,9 @@ class RosterWindow:
 | 
			
		|||
			if c.show not in ('error', 'offline'):
 | 
			
		||||
				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
 | 
			
		||||
		# in merged mode
 | 
			
		||||
| 
						 | 
				
			
			@ -2704,23 +2756,7 @@ class RosterWindow:
 | 
			
		|||
					win.show_title()
 | 
			
		||||
			elif row_type == 'group':
 | 
			
		||||
				# in C_JID column, we hold the group name (which is not escaped)
 | 
			
		||||
				if 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,])
 | 
			
		||||
				self.rename_group(old_text, new_text)
 | 
			
		||||
 | 
			
		||||
		def on_canceled():
 | 
			
		||||
			if 'rename' in gajim.interface.instances:
 | 
			
		||||
| 
						 | 
				
			
			@ -2919,6 +2955,12 @@ class RosterWindow:
 | 
			
		|||
	def on_groupchat_maximized(self, widget, jid, account):
 | 
			
		||||
		'''When a groupchat is maximised'''
 | 
			
		||||
		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
 | 
			
		||||
		ctrl = gajim.interface.minimized_controls[account][jid]
 | 
			
		||||
		mw = gajim.interface.msg_win_mgr.get_window(jid, account)
 | 
			
		||||
| 
						 | 
				
			
			@ -2928,7 +2970,7 @@ class RosterWindow:
 | 
			
		|||
		ctrl.parent_win = mw
 | 
			
		||||
		mw.new_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)
 | 
			
		||||
 | 
			
		||||
	def on_edit_account(self, widget, account):
 | 
			
		||||
| 
						 | 
				
			
			@ -3977,6 +4019,8 @@ class RosterWindow:
 | 
			
		|||
				return
 | 
			
		||||
			c_dest = gajim.contacts.get_contact_with_highest_priority(account_dest,
 | 
			
		||||
				jid_dest)
 | 
			
		||||
			if not gajim.capscache.is_supported(c_dest, NS_FILE):
 | 
			
		||||
				return
 | 
			
		||||
			uri = data.strip()
 | 
			
		||||
			uri_splitted = uri.split() # we may have more than one file dropped
 | 
			
		||||
			try:
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -250,7 +250,7 @@ class ChatControlSession(stanza_session.EncryptedStanzaSession):
 | 
			
		|||
 | 
			
		||||
		if self.control:
 | 
			
		||||
			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:
 | 
			
		||||
				focused = True
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		
		Reference in a new issue