2 ## src/remote_control.py
4 ## Copyright (C) 2005-2006 Andrew Sayman <lorien420 AT myrealbox.com>
5 ## Dimitur Kirov <dkirov AT gmail.com>
6 ## Nikos Kouremenos <kourem AT gmail.com>
7 ## Copyright (C) 2005-2010 Yann Leboulanger <asterix AT lagaule.org>
8 ## Copyright (C) 2006-2007 Travis Shirk <travis AT pobox.com>
9 ## Copyright (C) 2006-2008 Jean-Marie Traissard <jim AT lapin.org>
10 ## Copyright (C) 2007 Lukas Petrovicky <lukas AT petrovicky.net>
11 ## Julien Pivotto <roidelapluie AT gmail.com>
12 ## Copyright (C) 2008 Jonathan Schleifer <js-gajim AT webkeks.org>
14 ## This file is part of Gajim.
16 ## Gajim is free software; you can redistribute it and/or modify
17 ## it under the terms of the GNU General Public License as published
18 ## by the Free Software Foundation; version 3 only.
20 ## Gajim is distributed in the hope that it will be useful,
21 ## but WITHOUT ANY WARRANTY; without even the implied warranty of
22 ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 ## GNU General Public License for more details.
25 ## You should have received a copy of the GNU General Public License
26 ## along with Gajim. If not, see <http://www.gnu.org/licenses/>.
35 from common
import gajim
36 from common
import helpers
38 from dialogs
import AddNewContactWindow
, NewChatDialog
, JoinGroupchatWindow
39 from common
import ged
41 from common
import dbus_support
42 if dbus_support
.supported
:
48 INTERFACE
= 'org.gajim.dbus.RemoteInterface'
49 OBJ_PATH
= '/org/gajim/dbus/RemoteObject'
50 SERVICE
= 'org.gajim.dbus'
54 # in most cases it is a utf-8 string
55 DBUS_STRING
= dbus
.String
57 # general type (for use in dicts, where all values should have the same type)
58 DBUS_BOOLEAN
= dbus
.Boolean
59 DBUS_DOUBLE
= dbus
.Double
60 DBUS_INT32
= dbus
.Int32
61 # dictionary with string key and binary value
62 DBUS_DICT_SV
= lambda : dbus
.Dictionary({}, signature
="sv")
63 # dictionary with string key and value
64 DBUS_DICT_SS
= lambda : dbus
.Dictionary({}, signature
="ss")
65 # empty type (there is no equivalent of None on D-Bus, but historically gajim
67 DBUS_NONE
= lambda : dbus
.Int32(0)
69 def get_dbus_struct(obj
):
71 Recursively go through all the items and replace them with their casted dbus
76 if isinstance(obj
, (unicode, str)):
77 return DBUS_STRING(obj
)
78 if isinstance(obj
, int):
79 return DBUS_INT32(obj
)
80 if isinstance(obj
, float):
81 return DBUS_DOUBLE(obj
)
82 if isinstance(obj
, bool):
83 return DBUS_BOOLEAN(obj
)
84 if isinstance(obj
, (list, tuple)):
85 result
= dbus
.Array([get_dbus_struct(i
) for i
in obj
],
90 if isinstance(obj
, dict):
91 result
= DBUS_DICT_SV()
92 for key
, value
in obj
.items():
93 result
[DBUS_STRING(key
)] = get_dbus_struct(value
)
102 self
.signal_object
= None
103 session_bus
= dbus_support
.session_bus
.SessionBus()
105 bus_name
= dbus
.service
.BusName(SERVICE
, bus
=session_bus
)
106 self
.signal_object
= SignalObject(bus_name
)
108 gajim
.ged
.register_event_handler('last-result-received', ged
.POSTGUI
,
109 self
.on_last_status_time
)
110 gajim
.ged
.register_event_handler('version-result-received', ged
.POSTGUI
,
112 gajim
.ged
.register_event_handler('time-result-received', ged
.POSTGUI
,
114 gajim
.ged
.register_event_handler('gmail-nofify', ged
.POSTGUI
,
115 self
.on_gmail_notify
)
116 gajim
.ged
.register_event_handler('roster-info', ged
.POSTGUI
,
118 gajim
.ged
.register_event_handler('presence-received', ged
.POSTGUI
,
119 self
.on_presence_received
)
120 gajim
.ged
.register_event_handler('subscribe-presence-received',
121 ged
.POSTGUI
, self
.on_subscribe_presence_received
)
122 gajim
.ged
.register_event_handler('subscribed-presence-received',
123 ged
.POSTGUI
, self
.on_subscribed_presence_received
)
124 gajim
.ged
.register_event_handler('unsubscribed-presence-received',
125 ged
.POSTGUI
, self
.on_unsubscribed_presence_received
)
126 gajim
.ged
.register_event_handler('gc-message-received',
127 ged
.POSTGUI
, self
.on_gc_message_received
)
128 gajim
.ged
.register_event_handler('our-show',
129 ged
.POSTGUI
, self
.on_our_status
)
131 def on_last_status_time(self
, obj
):
132 self
.raise_signal('LastStatusTime', (obj
.conn
.name
, [
133 obj
.jid
, obj
.resource
, obj
.seconds
, obj
.status
]))
135 def on_os_info(self
, obj
):
136 self
.raise_signal('OsInfo', (obj
.conn
.name
, [obj
.jid
, obj
.resource
,
137 obj
.client_info
, obj
.os_info
]))
139 def on_time(self
, obj
):
140 self
.raise_signal('EntityTime', (obj
.conn
.name
, [obj
.jid
, obj
.resource
,
143 def on_gmail_notify(self
, obj
):
144 self
.raise_signal('NewGmail', (obj
.conn
.name
, [obj
.jid
, obj
.newmsgs
,
145 obj
.gmail_messages_list
]))
147 def on_roster_info(self
, obj
):
148 self
.raise_signal('RosterInfo', (obj
.conn
.name
, [obj
.jid
, obj
.nickname
,
149 obj
.sub
, obj
.ask
, obj
.groups
]))
151 def on_presence_received(self
, obj
):
153 if obj
.old_show
< 2 and obj
.new_show
> 1:
154 event
= 'ContactPresence'
155 elif obj
.old_show
> 1 and obj
.new_show
< 2:
156 event
= 'ContactAbsence'
157 elif obj
.new_show
> 1:
158 event
= 'ContactStatus'
160 self
.raise_signal(event
, (obj
.conn
.name
, [obj
.jid
, obj
.show
,
161 obj
.status
, obj
.resource
, obj
.prio
, obj
.keyID
, obj
.timestamp
,
162 obj
.contact_nickname
]))
164 def on_subscribe_presence_received(self
, obj
):
165 self
.raise_signal('Subscribe', (obj
.conn
.name
, [obj
.jid
, obj
.status
,
168 def on_subscribed_presence_received(self
, obj
):
169 self
.raise_signal('Subscribed', (obj
.conn
.name
, [obj
.jid
,
172 def on_unsubscribed_presence_received(self
, obj
):
173 self
.raise_signal('Unsubscribed', (obj
.conn
.name
, obj
.jid
))
175 def on_gc_message_received(self
, obj
):
176 if not hasattr(obj
, 'needs_highlight'):
177 # event has not been handled at GUI level
179 self
.raise_signal('GCMessage', (obj
.conn
.name
, [obj
.fjid
, obj
.msgtxt
,
180 obj
.timestamp
, obj
.has_timestamp
, obj
.xhtml_msgtxt
, obj
.status_code
,
181 obj
.displaymarking
, obj
.captcha_form
, obj
.needs_highlight
]))
183 def on_our_status(self
, obj
):
184 self
.raise_signal('AccountPresence', (obj
.show
, obj
.conn
.name
))
186 def raise_signal(self
, signal
, arg
):
187 if self
.signal_object
:
189 getattr(self
.signal_object
, signal
)(get_dbus_struct(arg
))
190 except UnicodeDecodeError:
191 pass # ignore error when we fail to announce on dbus
194 class SignalObject(dbus
.service
.Object
):
196 Local object definition for /org/gajim/dbus/RemoteObject
198 This docstring is not be visible, because the clients can access only the
202 def __init__(self
, bus_name
):
203 self
.first_show
= True
204 self
.vcard_account
= None
206 # register our dbus API
207 dbus
.service
.Object
.__init
__(self
, bus_name
, OBJ_PATH
)
209 @dbus.service
.signal(INTERFACE
, signature
='av')
210 def Roster(self
, account_and_data
):
213 @dbus.service
.signal(INTERFACE
, signature
='av')
214 def AccountPresence(self
, status_and_account
):
217 @dbus.service
.signal(INTERFACE
, signature
='av')
218 def ContactPresence(self
, account_and_array
):
221 @dbus.service
.signal(INTERFACE
, signature
='av')
222 def ContactAbsence(self
, account_and_array
):
225 @dbus.service
.signal(INTERFACE
, signature
='av')
226 def ContactStatus(self
, account_and_array
):
229 @dbus.service
.signal(INTERFACE
, signature
='av')
230 def NewMessage(self
, account_and_array
):
233 @dbus.service
.signal(INTERFACE
, signature
='av')
234 def Subscribe(self
, account_and_array
):
237 @dbus.service
.signal(INTERFACE
, signature
='av')
238 def Subscribed(self
, account_and_array
):
241 @dbus.service
.signal(INTERFACE
, signature
='av')
242 def Unsubscribed(self
, account_and_jid
):
245 @dbus.service
.signal(INTERFACE
, signature
='av')
246 def NewAccount(self
, account_and_array
):
249 @dbus.service
.signal(INTERFACE
, signature
='av')
250 def VcardInfo(self
, account_and_vcard
):
253 @dbus.service
.signal(INTERFACE
, signature
='av')
254 def LastStatusTime(self
, account_and_array
):
257 @dbus.service
.signal(INTERFACE
, signature
='av')
258 def OsInfo(self
, account_and_array
):
261 @dbus.service
.signal(INTERFACE
, signature
='av')
262 def EntityTime(self
, account_and_array
):
265 @dbus.service
.signal(INTERFACE
, signature
='av')
266 def GCPresence(self
, account_and_array
):
269 @dbus.service
.signal(INTERFACE
, signature
='av')
270 def GCMessage(self
, account_and_array
):
273 @dbus.service
.signal(INTERFACE
, signature
='av')
274 def RosterInfo(self
, account_and_array
):
277 @dbus.service
.signal(INTERFACE
, signature
='av')
278 def NewGmail(self
, account_and_array
):
281 def raise_signal(self
, signal
, arg
):
283 Raise a signal, with a single argument of unspecified type Instead of
284 obj.raise_signal("Foo", bar), use obj.Foo(bar)
286 getattr(self
, signal
)(arg
)
288 @dbus.service
.method(INTERFACE
, in_signature
='s', out_signature
='s')
289 def get_status(self
, account
):
291 Return status (show to be exact) which is the global one unless account is
295 # If user did not ask for account, returns the global status
296 return DBUS_STRING(helpers
.get_global_show())
297 # return show for the given account
298 index
= gajim
.connections
[account
].connected
299 return DBUS_STRING(gajim
.SHOW_LIST
[index
])
301 @dbus.service
.method(INTERFACE
, in_signature
='s', out_signature
='s')
302 def get_status_message(self
, account
):
304 Return status which is the global one unless account is given
307 # If user did not ask for account, returns the global status
308 return DBUS_STRING(str(helpers
.get_global_status()))
309 # return show for the given account
310 status
= gajim
.connections
[account
].status
311 return DBUS_STRING(status
)
313 def _get_account_and_contact(self
, account
, jid
):
315 Get the account (if not given) and contact instance from jid
317 connected_account
= None
319 accounts
= gajim
.contacts
.get_accounts()
320 # if there is only one account in roster, take it as default
321 # if user did not ask for account
322 if not account
and len(accounts
) == 1:
323 account
= accounts
[0]
325 if gajim
.connections
[account
].connected
> 1: # account is connected
326 connected_account
= account
327 contact
= gajim
.contacts
.get_contact_with_highest_priority(account
,
330 for account
in accounts
:
331 contact
= gajim
.contacts
.get_contact_with_highest_priority(account
,
333 if contact
and gajim
.connections
[account
].connected
> 1:
334 # account is connected
335 connected_account
= account
340 return connected_account
, contact
342 def _get_account_for_groupchat(self
, account
, room_jid
):
344 Get the account which is connected to groupchat (if not given)
345 or check if the given account is connected to the groupchat
347 connected_account
= None
348 accounts
= gajim
.contacts
.get_accounts()
349 # if there is only one account in roster, take it as default
350 # if user did not ask for account
351 if not account
and len(accounts
) == 1:
352 account
= accounts
[0]
354 if gajim
.connections
[account
].connected
> 1 and \
355 room_jid
in gajim
.gc_connected
[account
] and \
356 gajim
.gc_connected
[account
][room_jid
]:
357 # account and groupchat are connected
358 connected_account
= account
360 for account
in accounts
:
361 if gajim
.connections
[account
].connected
> 1 and \
362 room_jid
in gajim
.gc_connected
[account
] and \
363 gajim
.gc_connected
[account
][room_jid
]:
364 # account and groupchat are connected
365 connected_account
= account
367 return connected_account
369 @dbus.service
.method(INTERFACE
, in_signature
='sss', out_signature
='b')
370 def send_file(self
, file_path
, jid
, account
):
372 Send file, located at 'file_path' to 'jid', using account (optional)
375 jid
= self
._get
_real
_jid
(jid
, account
)
376 connected_account
, contact
= self
._get
_account
_and
_contact
(account
, jid
)
378 if connected_account
:
379 if file_path
.startswith('file://'):
380 file_path
=file_path
[7:]
381 if os
.path
.isfile(file_path
): # is it file?
382 gajim
.interface
.instances
['file_transfers'].send_file(
383 connected_account
, contact
, file_path
)
384 return DBUS_BOOLEAN(True)
385 return DBUS_BOOLEAN(False)
387 def _send_message(self
, jid
, message
, keyID
, account
, type_
= 'chat',
390 Can be called from send_chat_message (default when send_message) or
393 if not jid
or not message
:
394 return DBUS_BOOLEAN(False)
398 connected_account
, contact
= self
._get
_account
_and
_contact
(account
, jid
)
399 if connected_account
:
400 connection
= gajim
.connections
[connected_account
]
401 connection
.send_message(jid
, message
, keyID
, type_
, subject
)
402 return DBUS_BOOLEAN(True)
403 return DBUS_BOOLEAN(False)
405 @dbus.service
.method(INTERFACE
, in_signature
='ssss', out_signature
='b')
406 def send_chat_message(self
, jid
, message
, keyID
, account
):
408 Send chat 'message' to 'jid', using account (optional) 'account'. If keyID
409 is specified, encrypt the message with the pgp key
411 jid
= self
._get
_real
_jid
(jid
, account
)
412 return self
._send
_message
(jid
, message
, keyID
, account
)
414 @dbus.service
.method(INTERFACE
, in_signature
='sssss', out_signature
='b')
415 def send_single_message(self
, jid
, subject
, message
, keyID
, account
):
417 Send single 'message' to 'jid', using account (optional) 'account'. If
418 keyID is specified, encrypt the message with the pgp key
420 jid
= self
._get
_real
_jid
(jid
, account
)
421 return self
._send
_message
(jid
, message
, keyID
, account
, type, subject
)
423 @dbus.service
.method(INTERFACE
, in_signature
='sss', out_signature
='b')
424 def send_groupchat_message(self
, room_jid
, message
, account
):
426 Send 'message' to groupchat 'room_jid', using account (optional) 'account'
428 if not room_jid
or not message
:
429 return DBUS_BOOLEAN(False)
430 connected_account
= self
._get
_account
_for
_groupchat
(account
, room_jid
)
431 if connected_account
:
432 connection
= gajim
.connections
[connected_account
]
433 connection
.send_gc_message(room_jid
, message
)
434 return DBUS_BOOLEAN(True)
435 return DBUS_BOOLEAN(False)
437 @dbus.service
.method(INTERFACE
, in_signature
='sss', out_signature
='b')
438 def open_chat(self
, jid
, account
, message
):
440 Shows the tabbed window for new message to 'jid', using account (optional)
444 raise dbus_support
.MissingArgument()
445 jid
= self
._get
_real
_jid
(jid
, account
)
447 jid
= helpers
.parse_jid(jid
)
449 # Jid is not conform, ignore it
450 return DBUS_BOOLEAN(False)
455 accounts
= gajim
.connections
.keys()
456 if len(accounts
) == 1:
457 account
= accounts
[0]
458 connected_account
= None
459 first_connected_acct
= None
460 for acct
in accounts
:
461 if gajim
.connections
[acct
].connected
> 1: # account is online
462 contact
= gajim
.contacts
.get_first_contact_from_jid(acct
, jid
)
463 if gajim
.interface
.msg_win_mgr
.has_window(jid
, acct
):
464 connected_account
= acct
468 connected_account
= acct
470 # we send the message to jid not in roster, because account is
471 # specified, or there is only one account
473 connected_account
= acct
474 elif first_connected_acct
is None:
475 first_connected_acct
= acct
477 # if jid is not a conntact, open-chat with first connected account
478 if connected_account
is None and first_connected_acct
:
479 connected_account
= first_connected_acct
481 if connected_account
:
482 gajim
.interface
.new_chat_from_jid(connected_account
, jid
, message
)
483 # preserve the 'steal focus preservation'
484 win
= gajim
.interface
.msg_win_mgr
.get_window(jid
,
485 connected_account
).window
486 if win
.get_property('visible'):
487 win
.window
.focus(gtk
.get_current_event_time())
488 return DBUS_BOOLEAN(True)
489 return DBUS_BOOLEAN(False)
491 @dbus.service
.method(INTERFACE
, in_signature
='sss', out_signature
='b')
492 def change_status(self
, status
, message
, account
):
494 change_status(status, message, account). Account is optional - if not
495 specified status is changed for all accounts
497 if status
not in ('offline', 'online', 'chat',
498 'away', 'xa', 'dnd', 'invisible'):
502 if account
not in gajim
.connections
:
503 return DBUS_BOOLEAN(False)
504 status
= gajim
.SHOW_LIST
[gajim
.connections
[account
].connected
]
505 gobject
.idle_add(gajim
.interface
.roster
.send_status
, account
,
508 # account not specified, so change the status of all accounts
509 for acc
in gajim
.contacts
.get_accounts():
510 if not gajim
.config
.get_per('accounts', acc
,
511 'sync_with_global_status'):
516 if acc
not in gajim
.connections
:
518 status_
= gajim
.SHOW_LIST
[gajim
.connections
[acc
].connected
]
519 gobject
.idle_add(gajim
.interface
.roster
.send_status
, acc
,
521 return DBUS_BOOLEAN(False)
523 @dbus.service
.method(INTERFACE
, in_signature
='ss', out_signature
='')
524 def set_priority(self
, prio
, account
):
526 set_priority(prio, account). Account is optional - if not specified
527 priority is changed for all accounts. That are synced with global status
530 gajim
.config
.set_per('accounts', account
, 'priority', prio
)
531 show
= gajim
.SHOW_LIST
[gajim
.connections
[account
].connected
]
532 status
= gajim
.connections
[account
].status
533 gobject
.idle_add(gajim
.connections
[account
].change_status
, show
,
536 # account not specified, so change prio of all accounts
537 for acc
in gajim
.contacts
.get_accounts():
538 if not gajim
.account_is_connected(acc
):
540 if not gajim
.config
.get_per('accounts', acc
,
541 'sync_with_global_status'):
543 gajim
.config
.set_per('accounts', acc
, 'priority', prio
)
544 show
= gajim
.SHOW_LIST
[gajim
.connections
[acc
].connected
]
545 status
= gajim
.connections
[acc
].status
546 gobject
.idle_add(gajim
.connections
[acc
].change_status
, show
,
549 @dbus.service
.method(INTERFACE
, in_signature
='', out_signature
='')
550 def show_next_pending_event(self
):
552 Show the window(s) with next pending event in tabbed/group chats
554 if gajim
.events
.get_nb_events():
555 gajim
.interface
.systray
.handle_first_event()
557 @dbus.service
.method(INTERFACE
, in_signature
='s', out_signature
='a{sv}')
558 def contact_info(self
, jid
):
560 Get vcard info for a contact. Return cached value of the vcard
562 if not isinstance(jid
, unicode):
565 raise dbus_support
.MissingArgument()
566 jid
= self
._get
_real
_jid
(jid
)
568 cached_vcard
= gajim
.connections
.values()[0].get_cached_vcard(jid
)
570 return get_dbus_struct(cached_vcard
)
573 return DBUS_DICT_SV()
575 @dbus.service
.method(INTERFACE
, in_signature
='', out_signature
='as')
576 def list_accounts(self
):
578 List register accounts
580 result
= gajim
.contacts
.get_accounts()
581 result_array
= dbus
.Array([], signature
='s')
582 if result
and len(result
) > 0:
583 for account
in result
:
584 result_array
.append(DBUS_STRING(account
))
587 @dbus.service
.method(INTERFACE
, in_signature
='s', out_signature
='a{ss}')
588 def account_info(self
, account
):
590 Show info on account: resource, jid, nick, prio, message
592 result
= DBUS_DICT_SS()
593 if account
in gajim
.connections
:
595 con
= gajim
.connections
[account
]
596 index
= con
.connected
597 result
['status'] = DBUS_STRING(gajim
.SHOW_LIST
[index
])
598 result
['name'] = DBUS_STRING(con
.name
)
599 result
['jid'] = DBUS_STRING(gajim
.get_jid_from_account(con
.name
))
600 result
['message'] = DBUS_STRING(con
.status
)
601 result
['priority'] = DBUS_STRING(unicode(con
.priority
))
602 result
['resource'] = DBUS_STRING(unicode(gajim
.config
.get_per(
603 'accounts', con
.name
, 'resource')))
606 @dbus.service
.method(INTERFACE
, in_signature
='s', out_signature
='aa{sv}')
607 def list_contacts(self
, account
):
609 List all contacts in the roster. If the first argument is specified, then
610 return the contacts for the specified account
612 result
= dbus
.Array([], signature
='aa{sv}')
613 accounts
= gajim
.contacts
.get_accounts()
614 if len(accounts
) == 0:
617 accounts_to_search
= [account
]
619 accounts_to_search
= accounts
620 for acct
in accounts_to_search
:
622 for jid
in gajim
.contacts
.get_jid_list(acct
):
623 item
= self
._contacts
_as
_dbus
_structure
(
624 gajim
.contacts
.get_contacts(acct
, jid
))
629 @dbus.service
.method(INTERFACE
, in_signature
='', out_signature
='')
630 def toggle_roster_appearance(self
):
632 Show/hide the roster window
634 win
= gajim
.interface
.roster
.window
635 if win
.get_property('visible'):
636 gobject
.idle_add(win
.hide
)
639 # preserve the 'steal focus preservation'
641 win
.window
.focus(gtk
.get_current_event_time())
643 win
.window
.focus(long(time()))
645 @dbus.service
.method(INTERFACE
, in_signature
='', out_signature
='')
646 def toggle_ipython(self
):
648 Show/hide the ipython window
650 win
= gajim
.ipython_window
652 if win
.window
.is_visible():
653 gobject
.idle_add(win
.hide
)
658 gajim
.interface
.create_ipython_window()
660 @dbus.service
.method(INTERFACE
, in_signature
='', out_signature
='a{ss}')
661 def prefs_list(self
):
662 prefs_dict
= DBUS_DICT_SS()
663 def get_prefs(data
, name
, path
, value
):
671 prefs_dict
[DBUS_STRING(key
)] = DBUS_STRING(value
[1])
672 gajim
.config
.foreach(get_prefs
)
675 @dbus.service
.method(INTERFACE
, in_signature
='', out_signature
='b')
676 def prefs_store(self
):
678 gajim
.interface
.save_config()
680 return DBUS_BOOLEAN(False)
681 return DBUS_BOOLEAN(True)
683 @dbus.service
.method(INTERFACE
, in_signature
='s', out_signature
='b')
684 def prefs_del(self
, key
):
686 return DBUS_BOOLEAN(False)
687 key_path
= key
.split('#', 2)
688 if len(key_path
) != 3:
689 return DBUS_BOOLEAN(False)
690 if key_path
[2] == '*':
691 gajim
.config
.del_per(key_path
[0], key_path
[1])
693 gajim
.config
.del_per(key_path
[0], key_path
[1], key_path
[2])
694 return DBUS_BOOLEAN(True)
696 @dbus.service
.method(INTERFACE
, in_signature
='s', out_signature
='b')
697 def prefs_put(self
, key
):
699 return DBUS_BOOLEAN(False)
700 key_path
= key
.split('#', 2)
701 if len(key_path
) < 3:
702 subname
, value
= key
.split('=', 1)
703 gajim
.config
.set(subname
, value
)
704 return DBUS_BOOLEAN(True)
705 subname
, value
= key_path
[2].split('=', 1)
706 gajim
.config
.set_per(key_path
[0], key_path
[1], subname
, value
)
707 return DBUS_BOOLEAN(True)
709 @dbus.service
.method(INTERFACE
, in_signature
='ss', out_signature
='b')
710 def add_contact(self
, jid
, account
):
712 if account
in gajim
.connections
and \
713 gajim
.connections
[account
].connected
> 1:
714 # if given account is active, use it
715 AddNewContactWindow(account
= account
, jid
= jid
)
718 return DBUS_BOOLEAN(False)
720 # if account is not given, show account combobox
721 AddNewContactWindow(account
= None, jid
= jid
)
722 return DBUS_BOOLEAN(True)
724 @dbus.service
.method(INTERFACE
, in_signature
='ss', out_signature
='b')
725 def remove_contact(self
, jid
, account
):
726 jid
= self
._get
_real
_jid
(jid
, account
)
727 accounts
= gajim
.contacts
.get_accounts()
729 # if there is only one account in roster, take it as default
732 contact_exists
= False
733 for account
in accounts
:
734 contacts
= gajim
.contacts
.get_contacts(account
, jid
)
736 gajim
.connections
[account
].unsubscribe(jid
)
737 for contact
in contacts
:
738 gajim
.interface
.roster
.remove_contact(contact
, account
)
739 gajim
.contacts
.remove_jid(account
, jid
)
740 contact_exists
= True
741 return DBUS_BOOLEAN(contact_exists
)
745 self
.first_show
= False
749 def _get_real_jid(self
, jid
, account
= None):
751 Get the real jid from the given one: removes xmpp: or get jid from nick if
752 account is specified, search only in this account
757 accounts
= gajim
.connections
.keys()
758 if jid
.startswith('xmpp:'):
759 return jid
[5:] # len('xmpp:') = 5
760 nick_in_roster
= None # Is jid a nick ?
761 for account
in accounts
:
762 # Does jid exists in roster of one account ?
763 if gajim
.contacts
.get_contacts(account
, jid
):
765 if not nick_in_roster
:
766 # look in all contact if one has jid as nick
767 for jid_
in gajim
.contacts
.get_jid_list(account
):
768 c
= gajim
.contacts
.get_contacts(account
, jid_
)
770 nick_in_roster
= jid_
773 # We have not found jid in roster, but we found is as a nick
774 return nick_in_roster
775 # We have not found it as jid nor as nick, probably a not in roster jid
778 def _contacts_as_dbus_structure(self
, contacts
):
780 Get info from list of Contact objects and create dbus dict
784 prim_contact
= None # primary contact
785 for contact
in contacts
:
786 if prim_contact
is None or contact
.priority
> prim_contact
.priority
:
787 prim_contact
= contact
788 contact_dict
= DBUS_DICT_SV()
789 contact_dict
['name'] = DBUS_STRING(prim_contact
.name
)
790 contact_dict
['show'] = DBUS_STRING(prim_contact
.show
)
791 contact_dict
['jid'] = DBUS_STRING(prim_contact
.jid
)
792 if prim_contact
.keyID
:
794 if len(prim_contact
.keyID
) == 8:
795 keyID
= prim_contact
.keyID
796 elif len(prim_contact
.keyID
) == 16:
797 keyID
= prim_contact
.keyID
[8:]
799 contact_dict
['openpgp'] = keyID
800 contact_dict
['resources'] = dbus
.Array([], signature
='(sis)')
801 for contact
in contacts
:
802 resource_props
= dbus
.Struct((DBUS_STRING(contact
.resource
),
803 dbus
.Int32(contact
.priority
), DBUS_STRING(contact
.status
)))
804 contact_dict
['resources'].append(resource_props
)
805 contact_dict
['groups'] = dbus
.Array([], signature
='(s)')
806 for group
in prim_contact
.groups
:
807 contact_dict
['groups'].append((DBUS_STRING(group
),))
810 @dbus.service
.method(INTERFACE
, in_signature
='', out_signature
='s')
811 def get_unread_msgs_number(self
):
812 return DBUS_STRING(str(gajim
.events
.get_nb_events()))
814 @dbus.service
.method(INTERFACE
, in_signature
='s', out_signature
='b')
815 def start_chat(self
, account
):
817 # error is shown in gajim-remote check_arguments(..)
818 return DBUS_BOOLEAN(False)
819 NewChatDialog(account
)
820 return DBUS_BOOLEAN(True)
822 @dbus.service
.method(INTERFACE
, in_signature
='ss', out_signature
='')
823 def send_xml(self
, xml
, account
):
825 gajim
.connections
[account
].send_stanza(str(xml
))
827 for acc
in gajim
.contacts
.get_accounts():
828 gajim
.connections
[acc
].send_stanza(str(xml
))
830 @dbus.service
.method(INTERFACE
, in_signature
='ss', out_signature
='')
831 def change_avatar(self
, picture
, account
):
832 filesize
= os
.path
.getsize(picture
)
834 if os
.path
.isfile(picture
):
835 stat
= os
.stat(picture
)
840 if not invalid_file
and filesize
< 16384:
841 fd
= open(picture
, 'rb')
843 avatar
= base64
.encodestring(data
)
844 avatar_mime_type
= mimetypes
.guess_type(picture
)[0]
846 vcard
['PHOTO'] = {'BINVAL': avatar
}
848 vcard
['PHOTO']['TYPE'] = avatar_mime_type
850 gajim
.connections
[account
].send_vcard(vcard
)
852 for acc
in gajim
.connections
:
853 gajim
.connections
[acc
].send_vcard(vcard
)
855 @dbus.service
.method(INTERFACE
, in_signature
='ssss', out_signature
='')
856 def join_room(self
, room_jid
, nick
, password
, account
):
858 # get the first connected account
859 accounts
= gajim
.connections
.keys()
860 for acct
in accounts
:
861 if gajim
.account_is_connected(acct
):
868 gajim
.interface
.instances
[account
]['join_gc'] = \
869 JoinGroupchatWindow(account
, room_jid
, nick
)
871 gajim
.interface
.join_gc_room(account
, room_jid
, nick
, password
)