[dkirov] patch to give dbus capabilities to Gajim. /me fixes and cleanups [possible break ups too :P]
This commit is contained in:
		
							parent
							
								
									9f2c75163f
								
							
						
					
					
						commit
						139bb5ac0c
					
				
					 4 changed files with 527 additions and 2 deletions
				
			
		
							
								
								
									
										140
									
								
								scripts/gajim-remote.py
									
										
									
									
									
										Executable file
									
								
							
							
						
						
									
										140
									
								
								scripts/gajim-remote.py
									
										
									
									
									
										Executable file
									
								
							|  | @ -0,0 +1,140 @@ | |||
| #!/usr/bin/env python | ||||
| ##	scripts/gajim-remote.py | ||||
| ## | ||||
| ## Gajim Team: | ||||
| ##	- Yann Le Boulanger <asterix@lagaule.org> | ||||
| ##	- Vincent Hanquez <tab@snarc.org> | ||||
| ##	- Nikos Kouremenos <kourem@gmail.com> | ||||
| ## | ||||
| ## This file was initially written by Dimitur Kirov | ||||
| ## | ||||
| ##	Copyright (C) 2003-2005 Gajim Team | ||||
| ## | ||||
| ## This program is free software; you can redistribute it and/or modify | ||||
| ## it under the terms of the GNU General Public License as published | ||||
| ## by the Free Software Foundation; version 2 only. | ||||
| ## | ||||
| ## This program is distributed in the hope that it will be useful, | ||||
| ## but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
| ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
| ## GNU General Public License for more details. | ||||
| ## | ||||
| 
 | ||||
| # gajim-remote help will show you the 'dbus' api | ||||
| # That api is also usable, and the code to use it follows.. | ||||
| 
 | ||||
| import sys | ||||
| import gtk | ||||
| import gobject | ||||
| 
 | ||||
| def send_error(error_message): | ||||
| 	sys.stderr.write(error_message+'\n') | ||||
| 	sys.stderr.flush() | ||||
| 	sys.exit(1) | ||||
| 
 | ||||
| try: | ||||
| 	import dbus | ||||
| except: | ||||
| 	send_error('Dbus is not supported.\n') | ||||
| 
 | ||||
| _version = getattr(dbus, 'version', (0, 20, 0)) | ||||
| 
 | ||||
| OBJ_PATH = '/org/gajim/dbus/RemoteObject' | ||||
| INTERFACE = 'org.gajim.dbus.RemoteInterface' | ||||
| SERVICE = 'org.gajim.dbus' | ||||
| commands = ['help', 'show_roster', 'show_waiting', 'list_contacts', | ||||
| 	'list_accounts', 'change_status', 'new_message', 'send_message',  | ||||
| 	'contact_info'] | ||||
| 	 | ||||
| if _version[1] >= 41: | ||||
| 	import dbus.service | ||||
| 	import dbus.glib | ||||
| 	 | ||||
| def compose_help(): | ||||
| 	str = 'Usage: '+ sys.argv[0] + ' command [arguments]\n' | ||||
| 	str += 'Command must be one of:\n' | ||||
| 	for command in commands: | ||||
| 		str += '\t' + command +'\n' | ||||
| 	return str | ||||
| 
 | ||||
| def show_vcard_info(*args, **keyword): | ||||
| 	if _version[1] >= 30: | ||||
| 		print args[0] | ||||
| 	else: | ||||
| 		if args and len(args) >= 5: | ||||
| 			print args[4].get_args_list() | ||||
| 
 | ||||
| 	# remove_signal_receiver is broken in lower versions,  | ||||
| 	# so we leave the leak - nothing can be done | ||||
| 	if _version[1] >= 41: | ||||
| 		sbus.remove_signal_receiver(show_vcard_info, 'VcardInfo', INTERFACE,  | ||||
| 			SERVICE, OBJ_PATH) | ||||
| 
 | ||||
| 	gtk.main_quit() | ||||
| 	 | ||||
| def gtk_quit(): | ||||
| 	if _version[1] >= 41: | ||||
| 		sbus.remove_signal_receiver(show_vcard_info, 'VcardInfo', INTERFACE,  | ||||
| 			SERVICE, OBJ_PATH) | ||||
| 	gtk.main_quit() | ||||
| 
 | ||||
| 
 | ||||
| argv_len = len(sys.argv)  | ||||
| 
 | ||||
| if argv_len  < 2: | ||||
| 	send_error('Usage: ' + sys.argv[0] + ' command [arguments]') | ||||
| 
 | ||||
| if sys.argv[1] not in commands: | ||||
| 	send_error(compose_help()) | ||||
| 	 | ||||
| command = sys.argv[1] | ||||
| 
 | ||||
| if command == 'help': | ||||
| 	print compose_help() | ||||
| 	sys.exit() | ||||
| 
 | ||||
| try: | ||||
| 	sbus = dbus.SessionBus() | ||||
| except: | ||||
| 	send_error('Session bus is not available.\n') | ||||
| 
 | ||||
| 
 | ||||
| if _version[1] >= 30 and _version[1] <= 42: | ||||
| 	object = sbus.get_object(SERVICE, OBJ_PATH) | ||||
| 	interface = dbus.Interface(object, INTERFACE) | ||||
| elif _version[1] < 30: | ||||
| 	service = sbus.get_service(SERVICE) | ||||
| 	interface = service.get_object(OBJ_PATH, INTERFACE) | ||||
| else: | ||||
| 	send_error('Unknow dbus version: '+ _version) | ||||
| 
 | ||||
| method = interface.__getattr__(sys.argv[1]) # get the function asked | ||||
| 
 | ||||
| if command == 'contact_info': | ||||
| 	if argv_len < 3: | ||||
| 		send_error("Missing argument \'contact_jid'") | ||||
| 	try: | ||||
| 		id = sbus.add_signal_receiver(show_vcard_info, 'VcardInfo',  | ||||
| 			INTERFACE, SERVICE, OBJ_PATH) | ||||
| 	except: | ||||
| 		send_error('Service not available') | ||||
| 	gobject.timeout_add(5000, gtk_quit) | ||||
| 	gtk.main() | ||||
| 
 | ||||
| #FIXME: gajim-remote.py change_status help to inform what it does with optional arg (account). the same for rest of methods that accept args | ||||
| 
 | ||||
| #FIXME - didn't find more clever way for the below 8 lines of code. | ||||
| # method(sys.argv[2:]) doesn't work, cos sys.argv[2:] is a tuple | ||||
| try: | ||||
| 	if argv_len == 2: | ||||
| 		res = method() | ||||
| 	elif argv_len == 3: | ||||
| 		res = method(str(sys.argv[2])) | ||||
| 	elif argv_len == 4: | ||||
| 		res = method(sys.argv[2], sys.argv[3]) | ||||
| 	elif argv_len == 5: | ||||
| 		res = method(sys.argv[2], sys.argv[3], sys.argv[4]) | ||||
| 	if res: | ||||
| 		print res | ||||
| except: | ||||
| 	send_error('Service not available') | ||||
|  | @ -116,6 +116,7 @@ class Config: | |||
| 		'search_engine': [opt_str, 'http://www.google.com/search?&q='], | ||||
| 		'dictionary_url': [opt_str, 'http://dictionary.reference.com/search?q='], | ||||
| 		'always_english_wikipedia': [opt_bool, False], | ||||
| 		'use_dbus': [opt_bool, False], # allow control via dbus service | ||||
| 	} | ||||
| 
 | ||||
| 	__options_per_key = { | ||||
|  |  | |||
							
								
								
									
										35
									
								
								src/gajim.py
									
										
									
									
									
								
							
							
						
						
									
										35
									
								
								src/gajim.py
									
										
									
									
									
								
							|  | @ -174,6 +174,8 @@ class Interface: | |||
| 		#('ROSTER', account, array) | ||||
| 		self.roster.mklists(data, account) | ||||
| 		self.roster.draw_roster() | ||||
| 		if self.remote: | ||||
| 			self.remote.raise_signal('Roster', (account, data)) | ||||
| 
 | ||||
| 	def handle_event_warning(self, unused, data): | ||||
| 		#('WARNING', account, (title_text, section_text)) | ||||
|  | @ -208,6 +210,8 @@ class Interface: | |||
| 		else: | ||||
| 			self.allow_notifications[account] = False | ||||
| 		self.roster.on_status_changed(account, status) | ||||
| 		if self.remote: | ||||
| 			self.remote.raise_signal('AccountPresence', (status, account)) | ||||
| 	 | ||||
| 	def handle_event_notify(self, account, array): | ||||
| 		#('NOTIFY', account, (jid, status, message, resource, priority, keyID,  | ||||
|  | @ -306,6 +310,8 @@ class Interface: | |||
| 						instance = dialogs.PopupNotificationWindow(self, | ||||
| 														_('Contact Signed In'), jid, account) | ||||
| 						self.roster.popup_notification_windows.append(instance) | ||||
| 				if self.remote: | ||||
| 					self.remote.raise_signal('ContactPresence', (account, array))						 | ||||
| 						 | ||||
| 			elif old_show > 1 and new_show < 2: | ||||
| 				if gajim.config.get_per('soundevents', 'contact_disconnected', | ||||
|  | @ -324,6 +330,8 @@ class Interface: | |||
| 						instance = dialogs.PopupNotificationWindow(self, | ||||
| 											 		_('Contact Signed Out'), jid, account) | ||||
| 						self.roster.popup_notification_windows.append(instance) | ||||
| 				if self.remote: | ||||
| 					self.remote.raise_signal('ContactAbsence', (account, array)) | ||||
| 				 | ||||
| 		elif self.windows[account]['gc'].has_key(ji): | ||||
| 			#it is a groupchat presence | ||||
|  | @ -332,6 +340,8 @@ class Interface: | |||
| 			self.windows[account]['gc'][ji].chg_contact_status(ji, resource, | ||||
| 				array[1], array[2], array[6], array[7], array[8], array[9], | ||||
| 				array[10], array[11], array[12], account) | ||||
| 			if self.remote: | ||||
| 				self.remote.raise_signal('GCPresence', (account, array)) | ||||
| 
 | ||||
| 	def handle_event_msg(self, account, array): | ||||
| 		#('MSG', account, (contact, msg, time, encrypted, msg_type, subject)) | ||||
|  | @ -394,6 +404,8 @@ class Interface: | |||
| 		if gajim.config.get_per('soundevents', 'next_message_received', | ||||
| 			'enabled') and not first: | ||||
| 			self.play_sound('next_message_received') | ||||
| 		if self.remote: | ||||
| 			self.remote.raise_signal('NewMessage', (account, array)) | ||||
| 		 | ||||
| 	def handle_event_msgerror(self, account, array): | ||||
| 		#('MSGERROR', account, (jid, error_code, error_msg, msg, time)) | ||||
|  | @ -438,6 +450,8 @@ class Interface: | |||
| 	def handle_event_subscribe(self, account, array): | ||||
| 		#('SUBSCRIBE', account, (jid, text)) | ||||
| 		dialogs.SubscriptionRequestWindow(self, array[0], array[1], account) | ||||
| 		if self.remote: | ||||
| 			self.remote.raise_signal('Subscribe', (account, array)) | ||||
| 
 | ||||
| 	def handle_event_subscribed(self, account, array): | ||||
| 		#('SUBSCRIBED', account, (jid, resource)) | ||||
|  | @ -466,10 +480,14 @@ class Interface: | |||
| 		dialogs.InformationDialog(_('Authorization accepted'), | ||||
| 				_('The contact "%s" has authorized you to see his status.') | ||||
| 				% jid).get_response() | ||||
| 		if self.remote: | ||||
| 			self.remote.raise_signal('Subscribed', (account, array)) | ||||
| 
 | ||||
| 	def handle_event_unsubscribed(self, account, jid): | ||||
| 		dialogs.InformationDialog(_('Contact "%s" removed subscription from you') % jid, | ||||
| 				_('You will always see him as offline.')).get_response() | ||||
| 		if self.remote: | ||||
| 			self.remote.raise_signal('Unsubscribed', (account, array)) | ||||
| 
 | ||||
| 	def handle_event_agent_info(self, account, array): | ||||
| 		#('AGENT_INFO', account, (agent, identities, features, items)) | ||||
|  | @ -522,6 +540,8 @@ class Interface: | |||
| 		if self.windows.has_key('accounts'): | ||||
| 			self.windows['accounts'].init_accounts() | ||||
| 		self.roster.draw_roster() | ||||
| 		if self.remote: | ||||
| 			self.remote.raise_signal('NewAccount', (account, array)) | ||||
| 
 | ||||
| 	def handle_event_quit(self, p1, p2): | ||||
| 		self.roster.quit_gtkgui_plugin() | ||||
|  | @ -550,6 +570,8 @@ class Interface: | |||
| 		if self.windows[account]['infos'].has_key(array[0]): | ||||
| 			self.windows[account]['infos'][array[0]].set_os_info(array[1], \ | ||||
| 				array[2], array[3]) | ||||
| 		if self.remote: | ||||
| 			self.remote.raise_signal('OsInfo', (account, array)) | ||||
| 
 | ||||
| 	def handle_event_gc_msg(self, account, array): | ||||
| 		#('GC_MSG', account, (jid, msg, time)) | ||||
|  | @ -565,6 +587,8 @@ class Interface: | |||
| 			#message from someone | ||||
| 			self.windows[account]['gc'][jid].print_conversation(array[1], jid, \ | ||||
| 				jids[1], array[2]) | ||||
| 		if self.remote: | ||||
| 			self.remote.raise_signal('GCMessage', (account, array)) | ||||
| 
 | ||||
| 	def handle_event_gc_subject(self, account, array): | ||||
| 		#('GC_SUBJECT', account, (jid, subject)) | ||||
|  | @ -610,6 +634,8 @@ class Interface: | |||
| 			if array[4]: | ||||
| 				user.groups = array[4] | ||||
| 		self.roster.draw_contact(jid, account) | ||||
| 		if self.remote: | ||||
| 			self.remote.raise_signal('RosterInfo', (account, array)) | ||||
| 
 | ||||
| 	def handle_event_bookmarks(self, account, bms): | ||||
| 		#('BOOKMARKS', account, [{name,jid,autojoin,password,nick}, {}]) | ||||
|  | @ -836,7 +862,7 @@ class Interface: | |||
| 		 | ||||
| 		for account in gajim.config.get_per('accounts'): | ||||
| 			gajim.connections[account] = common.connection.Connection(account) | ||||
| 	 | ||||
| 															 | ||||
| 		if gtk.pygtk_version >= (2, 6, 0): | ||||
| 			gtk.about_dialog_set_email_hook(self.on_launch_browser_mailer, 'mail') | ||||
| 			gtk.about_dialog_set_url_hook(self.on_launch_browser_mailer, 'url') | ||||
|  | @ -859,6 +885,12 @@ class Interface: | |||
| 			gajim.last_message_time[a] = {} | ||||
| 
 | ||||
| 		self.roster = roster_window.RosterWindow(self) | ||||
| 		if gajim.config.get('use_dbus'): | ||||
| 			import remote_control | ||||
| 			self.remote = remote_control.Remote(self) | ||||
| 		else: | ||||
| 			self.remote = None | ||||
| 																	 | ||||
| 		path_to_file = os.path.join(gajim.DATA_DIR, 'pixmaps/gajim.png') | ||||
| 		pix = gtk.gdk.pixbuf_new_from_file(path_to_file) | ||||
| 		gtk.window_set_default_icon(pix) # set the icon to all newly opened windows | ||||
|  | @ -882,7 +914,6 @@ class Interface: | |||
| 			self.systray = systray.Systray(self) | ||||
| 		if self.systray_capabilities and gajim.config.get('trayicon'): | ||||
| 			self.show_systray() | ||||
| 
 | ||||
| 		if gajim.config.get('check_for_new_version'): | ||||
| 			check_for_new_version.Check_for_new_version_dialog(self) | ||||
| 
 | ||||
|  |  | |||
							
								
								
									
										353
									
								
								src/remote_control.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										353
									
								
								src/remote_control.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,353 @@ | |||
| ##	roster_window.py | ||||
| ## | ||||
| ## Gajim Team: | ||||
| ##	- Yann Le Boulanger <asterix@lagaule.org> | ||||
| ##	- Vincent Hanquez <tab@snarc.org> | ||||
| ##	- Nikos Kouremenos <kourem@gmail.com> | ||||
| ## | ||||
| ##	Copyright (C) 2003-2005 Gajim Team | ||||
| ## | ||||
| ## This program is free software; you can redistribute it and/or modify | ||||
| ## it under the terms of the GNU General Public License as published | ||||
| ## by the Free Software Foundation; version 2 only. | ||||
| ## | ||||
| ## This program is distributed in the hope that it will be useful, | ||||
| ## but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
| ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
| ## GNU General Public License for more details. | ||||
| ## | ||||
| 
 | ||||
| import gtk | ||||
| import gobject | ||||
| 
 | ||||
| from common import gajim | ||||
| from time import time | ||||
| 
 | ||||
| try: | ||||
| 	import dbus | ||||
| except: | ||||
| 	pass | ||||
| 
 | ||||
| _version = getattr(dbus, 'version', (0, 20, 0))  | ||||
| 
 | ||||
| if _version >= (0, 41, 0): | ||||
| 	import dbus.service | ||||
| 	import dbus.glib # cause dbus 0.35+ doesn't return signal replies without it | ||||
| 	DbusPrototype = dbus.service.Object | ||||
| else: | ||||
| 	DbusPrototype = dbus.Object | ||||
| 
 | ||||
| INTERFACE = 'org.gajim.dbus.RemoteInterface' | ||||
| OBJ_PATH = '/org/gajim/dbus/RemoteObject' | ||||
| SERVICE = 'org.gajim.dbus' | ||||
| 
 | ||||
| class Remote: | ||||
| 	def __init__(self, plugin): | ||||
| 		self.signal_object = None | ||||
| 		if 'dbus' not in globals(): | ||||
| 			print 'DBUS python bindings are missing in this computer.' | ||||
| 			print 'DBUS capabilities of Gajim cannot be used' | ||||
| 			return None | ||||
| 		try: | ||||
| 			session_bus = dbus.SessionBus() | ||||
| 		except: | ||||
| 			# FIXME: some status why remote is not supported | ||||
| 			# When dbus 0.2.x is obsolete | ||||
| 			return None | ||||
| 		 | ||||
| 		if _version[1] >= 41: | ||||
| 			service = dbus.service.BusName(SERVICE, bus=session_bus) | ||||
| 			self.signal_object = SignalObject(service, plugin) | ||||
| 		elif _version[1] <= 40: | ||||
| 			service=dbus.Service(SERVICE, session_bus) | ||||
| 			self.signal_object = SignalObject(service, plugin) | ||||
| 
 | ||||
| 	def raise_signal(self, signal, arg): | ||||
| 		if self.signal_object: | ||||
| 			self.signal_object.raise_signal(signal, repr(arg)) | ||||
| 		 | ||||
| 
 | ||||
| class SignalObject(DbusPrototype): | ||||
| 	_version = getattr(dbus, 'version', (0, 20, 0)) | ||||
| 	 | ||||
| 	def __init__(self, service, plugin): | ||||
| 		self.plugin = plugin | ||||
| 		self.first_show = True | ||||
| 		self.contacts = self.plugin.roster.contacts | ||||
| 		self.vcard_account = None | ||||
| 		 | ||||
| 		# register our dbus API | ||||
| 		if _version[1] >= 41: | ||||
| 			DbusPrototype.__init__(self, service, OBJ_PATH) | ||||
| 		elif _version[1] >= 30: | ||||
| 			DbusPrototype.__init__(self, OBJ_PATH, service) | ||||
| 		else: | ||||
| 			DbusPrototype.__init__(self, OBJ_PATH, service,  | ||||
| 			[	self.show_roster, | ||||
| 				self.show_waiting, | ||||
| 				self.list_contacts, | ||||
| 				self.list_accounts, | ||||
| 				self.change_status, | ||||
| 				self.new_message, | ||||
| 				self.send_message, | ||||
| 				self.contact_info | ||||
| 			]) | ||||
| 
 | ||||
| 	def raise_signal(self, signal, arg): | ||||
| 		''' raise a signal, with a single string message ''' | ||||
| 		if _version[1] >=30: | ||||
| 			from dbus import dbus_bindings | ||||
| 			message = dbus_bindings.Signal(OBJ_PATH, INTERFACE, signal) | ||||
| 			iter = message.get_iter(True) | ||||
| 			iter.append(arg) | ||||
| 			self._connection.send(message) | ||||
| 		else: | ||||
| 			self.emit_signal(INTERFACE, signal, arg) | ||||
| 
 | ||||
| 	 | ||||
| 	# signals  | ||||
| 	def VcardInfo(self, *vcard): | ||||
| 		pass | ||||
| 
 | ||||
| 	def send_message(self, *args): | ||||
| 		''' send_message(jid, message, keyID=None, account=None) | ||||
| 		send 'message' to 'jid', using account (optional) 'account'. | ||||
| 		if keyID is specified, encrypt the message with the pgp key ''' | ||||
| 		jid, message, keyID, account = self._get_real_arguments(args, 4) | ||||
| 		if not jid or not message: | ||||
| 			return None # or raise error | ||||
| 		if not keyID: | ||||
| 			keyID = '' | ||||
| 		if account: | ||||
| 			self.plugin.connections[account].send_message(jid, message, keyID) | ||||
| 		else: | ||||
| 			for account in self.contacts.keys(): | ||||
| 				if self.contacts[account].has_key(jid): | ||||
| 					gajim.connections[account].send_message(jid,  | ||||
| 						message, keyID) | ||||
| 					return True | ||||
| 		return False | ||||
| 
 | ||||
| 	def new_message(self, *args): | ||||
| 		''' new_message(jid, account=None) -> shows the tabbed window for new  | ||||
| 		message to 'jid', using account(optional) 'account ' ''' | ||||
| 		jid, account = self._get_real_arguments(args, 2) | ||||
| 		if not jid: | ||||
| 			# FIXME: raise exception for missing argument (dbus0.3+) | ||||
| 			return None | ||||
| 		if account: | ||||
| 			accounts = [account] | ||||
| 		else: | ||||
| 			accounts = self.contacts.keys() | ||||
| 
 | ||||
| 		for account in accounts: | ||||
| 			if self.plugin.windows[account]['chats'].has_key(jid): | ||||
| 				self.plugin.windows[account]['chats'][jid].set_active_tab(jid) | ||||
| 				break | ||||
| 			elif self.contacts[account].has_key(jid): | ||||
| 				self.plugin.roster.new_chat(self.contacts[account][jid][0],  | ||||
| 					account) | ||||
| 				jid_data = self.plugin.windows[account]['chats'][jid] | ||||
| 				jid_data.set_active_tab(jid) | ||||
| 				jid_data.window.present() | ||||
| 				# preserve the "steal focus preservation" | ||||
| 				if self._is_first(): | ||||
| 					jid_data.window.window.focus() | ||||
| 				else: | ||||
| 					jid_data.window.window.focus(long(time())) | ||||
| 				break | ||||
| 	 | ||||
| 	def change_status(self, *args, **keywords): | ||||
| 		''' change_status(status, message, account). account is optional - | ||||
| 		if not specified status is changed for all accounts. ''' | ||||
| 		status, message, account = self._get_real_arguments(args, 3) | ||||
| 		if status not in ('offline', 'online', 'chat',  | ||||
| 			'away', 'xa', 'dnd', 'invisible'): | ||||
| 			# FIXME: raise exception for bad status (dbus0.3+) | ||||
| 			return None | ||||
| 		if account: | ||||
| 			gobject.idle_add(self.plugin.roster.send_status, account,  | ||||
| 				status, message) | ||||
| 		else: | ||||
| 			# account not specified, so change the status of all accounts | ||||
| 			for acc in self.contacts.keys(): | ||||
| 				gobject.idle_add(self.plugin.roster.send_status, acc,  | ||||
| 					status, message) | ||||
| 		return None | ||||
| 
 | ||||
| 	def show_waiting(self, *args): | ||||
| 		''' Show the window(s) with waiting messages/chats. ''' | ||||
| 		#FIXME: when systray is disabled this method does nothing. | ||||
| 		if len(self.plugin.systray.jids) != 0: | ||||
| 			account = self.plugin.systray.jids[0][0] | ||||
| 			jid = self.plugin.systray.jids[0][1] | ||||
| 			acc = self.plugin.windows[account] | ||||
| 			jid_tab = None | ||||
| 			if acc['gc'].has_key(jid): | ||||
| 				jid_tab = acc['gc'][jid] | ||||
| 			elif acc['chats'].has_key(jid): | ||||
| 				jid_tab = acc['chats'][jid] | ||||
| 			else: | ||||
| 				self.plugin.roster.new_chat( | ||||
| 					self.contacts[account][jid][0], account) | ||||
| 				jid_tab = acc['chats'][jid] | ||||
| 			if jid_tab: | ||||
| 				jid_tab.set_active_tab(jid) | ||||
| 				jid_tab.window.present() | ||||
| 				# preserve the "steal focus preservation" | ||||
| 				if self._is_first(): | ||||
| 					jid_tab.window.window.focus() | ||||
| 				else: | ||||
| 					jid_tab.window.window.focus(long(time())) | ||||
| 				 | ||||
| 
 | ||||
| 	def contact_info(self, *args): | ||||
| 		''' get vcard info for a contact. The second argument is optional and  | ||||
| 		stands for the account, to which this contact belongs. This method  | ||||
| 		return nothing. You have to register the 'VcartInfo' signal to get the  | ||||
| 		real vcard. ''' | ||||
| 		jid, account = self._get_real_arguments(args, 2) | ||||
| 		if not jid: | ||||
| 			# FIXME: raise exception for missing argument (0.3+) | ||||
| 			return None | ||||
| 		if account: | ||||
| 			accounts = [account] | ||||
| 		else: | ||||
| 			accounts = self.contacts.keys() | ||||
| 		iq = None | ||||
| 		 | ||||
| 		for account in accounts: | ||||
| 			if self.contacts[account].has_key(jid): | ||||
| 				self.vcard_account =  account | ||||
| 				gajim.connections[account].register_handler('VCARD',  | ||||
| 					self._receive_vcard) | ||||
| 				iq = gajim.connections[account].request_vcard(jid) | ||||
| 				break | ||||
| 		return None | ||||
| 
 | ||||
| 	def list_accounts(self, *args): | ||||
| 		''' list register accounts ''' | ||||
| 		if self.contacts: | ||||
| 			result = self.contacts.keys() | ||||
| 			if result and len(result) > 0: | ||||
| 				return result | ||||
| 		return None | ||||
| 
 | ||||
| 
 | ||||
| 	def list_contacts(self, *args): | ||||
| 		''' list all contacts in the roster. If the first argument is specified, | ||||
| 		then return the contacts for the specified account ''' | ||||
| 		[for_account] = self._get_real_arguments(args, 1) | ||||
| 		result = [] | ||||
| 		if not self.contacts or len(self.contacts) == 0: | ||||
| 			return None | ||||
| 		if for_account: | ||||
| 			if self.contacts.has_key(for_account): | ||||
| 				for jid in self.contacts[for_account]: | ||||
| 					item = self._serialized_contacts( | ||||
| 						self.contacts[for_account][jid]) | ||||
| 					if item: | ||||
| 						result.append(item) | ||||
| 			else: | ||||
| 				# "for_account: is not recognised:",  | ||||
| 				# FIXME: there can be a return status for this [0.3+] | ||||
| 				return None | ||||
| 		else: | ||||
| 			for account in self.contacts: | ||||
| 				for jid in self.contacts[account]: | ||||
| 					item = self._serialized_contacts(self.contacts[account][jid]) | ||||
| 					if item: | ||||
| 						result.append(item) | ||||
| 		# dbus 0.40 does not support return result as empty list | ||||
| 		if result == []: | ||||
| 			return None | ||||
| 		return result | ||||
| 
 | ||||
| 	def show_roster(self, *args): | ||||
| 		''' shows/hides the roster window ''' | ||||
| 		win = self.plugin.roster.window | ||||
| 		if win.get_property('visible'): | ||||
| 			gobject.idle_add(win.hide) | ||||
| 		else: | ||||
| 			win.present() | ||||
| 			# preserve the "steal focus preservation" | ||||
| 			if self._is_first(): | ||||
| 				win.window.focus() | ||||
| 			else: | ||||
| 				win.window.focus(long(time())) | ||||
| 
 | ||||
| 	def _is_first(self): | ||||
| 		if self.first_show: | ||||
| 			self.first_show = False | ||||
| 			return True | ||||
| 		return False | ||||
| 
 | ||||
| 	def _receive_vcard(self,account, array): | ||||
| 		if self.vcard_account: | ||||
| 			gajim.connections[self.vcard_account].unregister_handler('VCARD',  | ||||
| 				self._receive_vcard) | ||||
| 			self.unregistered_vcard = None | ||||
| 			if _version[1] >=30: | ||||
| 				self.VcardInfo(repr(array)) | ||||
| 			else: | ||||
| 				self.emit_signal(INTERFACE, 'VcardInfo',  | ||||
| 					repr(array)) | ||||
| 
 | ||||
| 	def _get_real_arguments(self, args, desired_length): | ||||
| 		# supresses the first "message" argument, which is set in dbus 0.23 | ||||
| 		if _version[1] == 20: | ||||
| 			args=args[1:] | ||||
| 		if desired_length > 0: | ||||
| 			args = list(args) | ||||
| 			args.extend([None] * (desired_length - len(args))) | ||||
| 			args = args[:desired_length] | ||||
| 		return args | ||||
| 
 | ||||
| 	def _serialized_contacts(self, contacts): | ||||
| 		''' get info from list of Contact objects and create a serialized | ||||
| 		dict for sending it over dbus ''' | ||||
| 		if not contacts: | ||||
| 			return None | ||||
| 		prim_contact = None # primary contact | ||||
| 		for contact in contacts: | ||||
| 			if prim_contact == None or contact.priority > prim_contact.priority: | ||||
| 				prim_contact = contact | ||||
| 		contact_dict = {} | ||||
| 		contact_dict['name'] = prim_contact.name | ||||
| 		contact_dict['show'] = prim_contact.show | ||||
| 		contact_dict['jid'] = prim_contact.jid | ||||
| 		if prim_contact.keyID: | ||||
| 			keyID = None | ||||
| 			if len(prim_contact.keyID) == 8: | ||||
| 				keyID = prim_contact.keyID | ||||
| 			elif len(prim_contact.keyID) == 16: | ||||
| 				keyID = prim_contact.keyID[8:] | ||||
| 			if keyID: | ||||
| 				contact_dict['openpgp'] = keyID | ||||
| 		contact_dict['resources'] = [] | ||||
| 		for contact in contacts: | ||||
| 			contact_dict['resources'].append(tuple([contact.resource,  | ||||
| 				contact.priority, contact.status])) | ||||
| 		return repr(contact_dict) | ||||
| 	 | ||||
| 	 | ||||
| 	if _version[1] >= 30 and _version[1] <= 40: | ||||
| 		method = dbus.method | ||||
| 		signal = dbus.signal | ||||
| 	elif _version[1] >= 41: | ||||
| 		method = dbus.service.method | ||||
| 		signal = dbus.service.signal | ||||
| 
 | ||||
| 	if _version[1] >= 30: | ||||
| 		# prevent using decorators, because they are not supported  | ||||
| 		# on python < 2.4 | ||||
| 		# FIXME: use decorators when python2.3 is OOOOOOLD | ||||
| 		show_roster = method(INTERFACE)(show_roster) | ||||
| 		list_contacts = method(INTERFACE)(list_contacts) | ||||
| 		list_accounts = method(INTERFACE)(list_accounts) | ||||
| 		show_waiting = method(INTERFACE)(show_waiting) | ||||
| 		change_status = method(INTERFACE)(change_status) | ||||
| 		new_message = method(INTERFACE)(new_message) | ||||
| 		contact_info = method(INTERFACE)(contact_info) | ||||
| 		send_message = method(INTERFACE)(send_message) | ||||
| 		VcardInfo = signal(INTERFACE)(VcardInfo) | ||||
		Loading…
	
	Add table
		
		Reference in a new issue