Commit 916e542f authored by Luci Stanescu's avatar Luci Stanescu

Improved contact matching capabilities

parent c5af3468
...@@ -1124,7 +1124,7 @@ class ContactListView(QListView): ...@@ -1124,7 +1124,7 @@ class ContactListView(QListView):
if not isinstance(contact, Contact): if not isinstance(contact, Contact):
return return
session_manager = SessionManager() session_manager = SessionManager()
session_manager.start_call(contact.name, contact.uri, account=BonjourAccount() if isinstance(contact, BonjourNeighbour) else None) session_manager.start_call(contact.name, contact.uri, contact=contact, account=BonjourAccount() if isinstance(contact, BonjourNeighbour) else None)
else: else:
super(ContactListView, self).keyPressEvent(event) super(ContactListView, self).keyPressEvent(event)
...@@ -1177,7 +1177,7 @@ class ContactListView(QListView): ...@@ -1177,7 +1177,7 @@ class ContactListView(QListView):
def _AH_StartAudioCall(self): def _AH_StartAudioCall(self):
contact = self.model().data(self.selectionModel().selectedIndexes()[0]) contact = self.model().data(self.selectionModel().selectedIndexes()[0])
session_manager = SessionManager() session_manager = SessionManager()
session_manager.start_call(contact.name, contact.uri, account=BonjourAccount() if isinstance(contact, BonjourNeighbour) else None) session_manager.start_call(contact.name, contact.uri, contact=contact, account=BonjourAccount() if isinstance(contact, BonjourNeighbour) else None)
def _AH_StartChatSession(self): def _AH_StartChatSession(self):
contact = self.model().data(self.selectionModel().selectedIndexes()[0]) contact = self.model().data(self.selectionModel().selectedIndexes()[0])
...@@ -1451,7 +1451,7 @@ class ContactSearchListView(QListView): ...@@ -1451,7 +1451,7 @@ class ContactSearchListView(QListView):
if not isinstance(contact, Contact): if not isinstance(contact, Contact):
return return
session_manager = SessionManager() session_manager = SessionManager()
session_manager.start_call(contact.name, contact.uri, account=BonjourAccount() if isinstance(contact, BonjourNeighbour) else None) session_manager.start_call(contact.name, contact.uri, contact=contact, account=BonjourAccount() if isinstance(contact, BonjourNeighbour) else None)
else: else:
super(ContactSearchListView, self).keyPressEvent(event) super(ContactSearchListView, self).keyPressEvent(event)
...@@ -1474,7 +1474,7 @@ class ContactSearchListView(QListView): ...@@ -1474,7 +1474,7 @@ class ContactSearchListView(QListView):
def _AH_StartAudioCall(self): def _AH_StartAudioCall(self):
contact = self.model().data(self.selectionModel().selectedIndexes()[0]) contact = self.model().data(self.selectionModel().selectedIndexes()[0])
session_manager = SessionManager() session_manager = SessionManager()
session_manager.start_call(contact.name, contact.uri, account=BonjourAccount() if isinstance(contact, BonjourNeighbour) else None) session_manager.start_call(contact.name, contact.uri, contact=contact, account=BonjourAccount() if isinstance(contact, BonjourNeighbour) else None)
def _AH_StartChatSession(self): def _AH_StartChatSession(self):
contact = self.model().data(self.selectionModel().selectedIndexes()[0]) contact = self.model().data(self.selectionModel().selectedIndexes()[0])
......
...@@ -167,7 +167,7 @@ class MainWindow(base_class, ui_class): ...@@ -167,7 +167,7 @@ class MainWindow(base_class, ui_class):
address = contact.uri or unicode(self.search_box.text()) address = contact.uri or unicode(self.search_box.text())
name = contact.name or None name = contact.name or None
session_manager = SessionManager() session_manager = SessionManager()
session_manager.start_call(name, address, account=BonjourAccount() if isinstance(contact, BonjourNeighbour) else None) session_manager.start_call(name, address, contact=contact, account=BonjourAccount() if isinstance(contact, BonjourNeighbour) else None)
def _SH_BreakConference(self): def _SH_BreakConference(self):
active_session = self.session_model.data(self.session_list.selectionModel().selectedIndexes()[0]) active_session = self.session_model.data(self.session_list.selectionModel().selectedIndexes()[0])
...@@ -178,7 +178,7 @@ class MainWindow(base_class, ui_class): ...@@ -178,7 +178,7 @@ class MainWindow(base_class, ui_class):
if not isinstance(contact, Contact): if not isinstance(contact, Contact):
return return
session_manager = SessionManager() session_manager = SessionManager()
session_manager.start_call(contact.name, contact.uri, account=BonjourAccount() if isinstance(contact, BonjourNeighbour) else None) session_manager.start_call(contact.name, contact.uri, contact=contact, account=BonjourAccount() if isinstance(contact, BonjourNeighbour) else None)
def _SH_ContactListSelectionChanged(self, selected, deselected): def _SH_ContactListSelectionChanged(self, selected, deselected):
account_manager = AccountManager() account_manager = AccountManager()
......
...@@ -51,13 +51,14 @@ class SessionItem(QObject): ...@@ -51,13 +51,14 @@ class SessionItem(QObject):
deactivated = pyqtSignal() deactivated = pyqtSignal()
ended = pyqtSignal() ended = pyqtSignal()
def __init__(self, name, uri, session, audio_stream=None, video_stream=None): def __init__(self, name, uri, session, contact=None, audio_stream=None, video_stream=None):
super(SessionItem, self).__init__() super(SessionItem, self).__init__()
if (audio_stream, video_stream) == (None, None): if (audio_stream, video_stream) == (None, None):
raise ValueError('SessionItem must represent at least one audio or video stream') raise ValueError('SessionItem must represent at least one audio or video stream')
self.name = name self.name = name
self.uri = uri self.uri = uri
self.session = session self.session = session
self.contact = contact
self.audio_stream = audio_stream self.audio_stream = audio_stream
self.video_stream = video_stream self.video_stream = video_stream
self.widget = Null self.widget = Null
...@@ -80,12 +81,7 @@ class SessionItem(QObject): ...@@ -80,12 +81,7 @@ class SessionItem(QObject):
if self.audio_stream is None: if self.audio_stream is None:
self.hold_tone = Null self.hold_tone = Null
from blink import Blink self.remote_party_name = contact.name if contact else None
self.remote_party_name = None
for contact in Blink().main_window.contact_model.iter_contacts():
if uri.matches(contact.uri) or any(uri.matches(alias) for alias in contact.sip_aliases):
self.remote_party_name = contact.name
break
if not self.remote_party_name: if not self.remote_party_name:
address = '%s@%s' % (uri.user, uri.host) address = '%s@%s' % (uri.user, uri.host)
match = re.match(r'^(?P<number>(\+|00)[1-9][0-9]\d{5,15})@(\d{1,3}\.){3}\d{1,3}$', address) match = re.match(r'^(?P<number>(\+|00)[1-9][0-9]\d{5,15})@(\d{1,3}\.){3}\d{1,3}$', address)
...@@ -1108,7 +1104,7 @@ class SessionModel(QAbstractListModel): ...@@ -1108,7 +1104,7 @@ class SessionModel(QAbstractListModel):
contacts = pickle.loads(str(mime_data.data('application/x-blink-contact-list'))) contacts = pickle.loads(str(mime_data.data('application/x-blink-contact-list')))
session_manager = SessionManager() session_manager = SessionManager()
for contact in contacts: for contact in contacts:
session_manager.start_call(contact.name, contact.uri, conference_sibling=session) session_manager.start_call(contact.name, contact.uri, contact=contact, conference_sibling=session)
return True return True
def _add_session(self, session): def _add_session(self, session):
...@@ -1546,10 +1542,11 @@ class IncomingSession(QObject): ...@@ -1546,10 +1542,11 @@ class IncomingSession(QObject):
accepted = pyqtSignal() accepted = pyqtSignal()
rejected = pyqtSignal(str) rejected = pyqtSignal(str)
def __init__(self, dialog, session, proposal=False, audio_stream=None, video_stream=None, chat_stream=None, desktopsharing_stream=None): def __init__(self, dialog, session, contact=None, proposal=False, audio_stream=None, video_stream=None, chat_stream=None, desktopsharing_stream=None):
super(IncomingSession, self).__init__() super(IncomingSession, self).__init__()
self.dialog = dialog self.dialog = dialog
self.session = session self.session = session
self.contact = contact
self.proposal = proposal self.proposal = proposal
self.audio_stream = audio_stream self.audio_stream = audio_stream
self.video_stream = video_stream self.video_stream = video_stream
...@@ -1563,14 +1560,11 @@ class IncomingSession(QObject): ...@@ -1563,14 +1560,11 @@ class IncomingSession(QObject):
else: else:
self.dialog.setWindowTitle(u'Incoming session request') self.dialog.setWindowTitle(u'Incoming session request')
self.dialog.setWindowIconText(u'Incoming session request') self.dialog.setWindowIconText(u'Incoming session request')
from blink import Blink
address = u'%s@%s' % (session.remote_identity.uri.user, session.remote_identity.uri.host) address = u'%s@%s' % (session.remote_identity.uri.user, session.remote_identity.uri.host)
self.dialog.uri_label.setText(address) self.dialog.uri_label.setText(address)
for contact in Blink().main_window.contact_model.iter_contacts(): if self.contact:
if session.remote_identity.uri.matches(contact.uri) or any(session.remote_identity.uri.matches(alias) for alias in contact.sip_aliases):
self.dialog.username_label.setText(contact.name or session.remote_identity.display_name or address) self.dialog.username_label.setText(contact.name or session.remote_identity.display_name or address)
self.dialog.user_icon.setPixmap(contact.icon) self.dialog.user_icon.setPixmap(contact.icon)
break
else: else:
self.dialog.username_label.setText(session.remote_identity.display_name or address) self.dialog.username_label.setText(session.remote_identity.display_name or address)
if self.audio_stream: if self.audio_stream:
...@@ -1680,6 +1674,8 @@ class SessionManager(object): ...@@ -1680,6 +1674,8 @@ class SessionManager(object):
implements(IObserver) implements(IObserver)
number_strip_re = re.compile(r'\(\s?0\s?\)|[-() ]')
def __init__(self): def __init__(self):
self.main_window = None self.main_window = None
self.session_model = None self.session_model = None
...@@ -1699,7 +1695,7 @@ class SessionManager(object): ...@@ -1699,7 +1695,7 @@ class SessionManager(object):
notification_center.add_observer(self, name='SIPSessionGotRejectProposal') notification_center.add_observer(self, name='SIPSessionGotRejectProposal')
notification_center.add_observer(self, name='SIPSessionDidRenegotiateStreams') notification_center.add_observer(self, name='SIPSessionDidRenegotiateStreams')
def start_call(self, name, address, account=None, conference_sibling=None, audio=True, video=False): def start_call(self, name, address, contact=None, account=None, conference_sibling=None, audio=True, video=False):
account_manager = AccountManager() account_manager = AccountManager()
account = account or account_manager.default_account account = account or account_manager.default_account
if account is None or not account.enabled: if account is None or not account.enabled:
...@@ -1710,9 +1706,15 @@ class SessionManager(object): ...@@ -1710,9 +1706,15 @@ class SessionManager(object):
print 'Invalid URI: %s' % e # Replace with pop-up print 'Invalid URI: %s' % e # Replace with pop-up
else: else:
session = Session(account) session = Session(account)
if contact is None:
for contact in self.main_window.contact_model.iter_contacts():
if remote_uri.matches(self.normalize_number(account, contact.uri)) or any(remote_uri.matches(self.normalize_number(account, alias)) for alias in contact.sip_aliases):
break
else:
contact = None
audio_stream = self.create_stream(account, 'audio') if audio else None audio_stream = self.create_stream(account, 'audio') if audio else None
video_stream = self.create_stream(account, 'vidoe') if video else None video_stream = self.create_stream(account, 'vidoe') if video else None
session_item = SessionItem(name, remote_uri, session, audio_stream=audio_stream, video_stream=video_stream) session_item = SessionItem(name, remote_uri, session, contact, audio_stream=audio_stream, video_stream=video_stream)
session_item.activated.connect(partial(self._SH_SessionActivated, session_item)) session_item.activated.connect(partial(self._SH_SessionActivated, session_item))
session_item.deactivated.connect(partial(self._SH_SessionDeactivated, session_item)) session_item.deactivated.connect(partial(self._SH_SessionDeactivated, session_item))
session_item.ended.connect(partial(self._SH_SessionEnded, session_item)) session_item.ended.connect(partial(self._SH_SessionEnded, session_item))
...@@ -1767,11 +1769,9 @@ class SessionManager(object): ...@@ -1767,11 +1769,9 @@ class SessionManager(object):
else: else:
raise ValueError('unknown stream type: %s' % type) raise ValueError('unknown stream type: %s' % type)
@staticmethod @classmethod
def create_uri(account, address): def create_uri(cls, account, address):
address = re.sub(r'\(\s?0\s?\)|[-() ]', '', address) address = cls.normalize_number(account, address)
if isinstance(account, Account) and account.pstn.idd_prefix is not None:
address = re.sub(r'^\+', account.pstn.idd_prefix, address)
if not address.startswith('sip:') and not address.startswith('sips:'): if not address.startswith('sip:') and not address.startswith('sips:'):
address = 'sip:' + address address = 'sip:' + address
if '@' not in address: if '@' not in address:
...@@ -1781,6 +1781,13 @@ class SessionManager(object): ...@@ -1781,6 +1781,13 @@ class SessionManager(object):
raise ValueError('SIP address without domain') raise ValueError('SIP address without domain')
return SIPURI.parse(str(address)) return SIPURI.parse(str(address))
@classmethod
def normalize_number(cls, account, address):
address = cls.number_strip_re.sub('', address)
if isinstance(account, Account) and account.pstn.idd_prefix is not None:
address = re.sub(r'^\+', account.pstn.idd_prefix, address)
return address
def _remove_session(self, session): def _remove_session(self, session):
session_list = self.session_model.session_list session_list = self.session_model.session_list
selection_mode = session_list.selectionMode() selection_mode = session_list.selectionMode()
...@@ -1804,19 +1811,19 @@ class SessionManager(object): ...@@ -1804,19 +1811,19 @@ class SessionManager(object):
self.update_ringtone() self.update_ringtone()
session = incoming_session.session session = incoming_session.session
if incoming_session.audio_accepted and incoming_session.video_accepted: if incoming_session.audio_accepted and incoming_session.video_accepted:
session_item = SessionItem(session.remote_identity.display_name, session.remote_identity.uri, session, audio_stream=incoming_session.audio_stream, video_stream=incoming_session.video_stream) session_item = SessionItem(session.remote_identity.display_name, session.remote_identity.uri, session, incoming_session.contact, audio_stream=incoming_session.audio_stream, video_stream=incoming_session.video_stream)
elif incoming_session.audio_accepted: elif incoming_session.audio_accepted:
try: try:
session_item = (session_item for session_item in self.session_model.active_sessions if session_item.session is session and session_item.audio_stream is None).next() session_item = (session_item for session_item in self.session_model.active_sessions if session_item.session is session and session_item.audio_stream is None).next()
session_item.audio_stream = incoming_session.audio_stream session_item.audio_stream = incoming_session.audio_stream
except StopIteration: except StopIteration:
session_item = SessionItem(session.remote_identity.display_name, session.remote_identity.uri, session, audio_stream=incoming_session.audio_stream) session_item = SessionItem(session.remote_identity.display_name, session.remote_identity.uri, session, incoming_session.contact, audio_stream=incoming_session.audio_stream)
elif incoming_session.video_accepted: elif incoming_session.video_accepted:
try: try:
session_item = (session_item for session_item in self.session_model.active_sessions if session_item.session is session and session_item.video_stream is None).next() session_item = (session_item for session_item in self.session_model.active_sessions if session_item.session is session and session_item.video_stream is None).next()
session_item.video_stream = incoming_session.video_stream session_item.video_stream = incoming_session.video_stream
except StopIteration: except StopIteration:
session_item = SessionItem(session.remote_identity.display_name, session.remote_identity.uri, session, video_stream=incoming_session.video_stream) session_item = SessionItem(session.remote_identity.display_name, session.remote_identity.uri, session, incoming_session.contact, video_stream=incoming_session.video_stream)
else: # Handle other streams -Luci else: # Handle other streams -Luci
if incoming_session.proposal: if incoming_session.proposal:
session.reject_proposal(488) session.reject_proposal(488)
...@@ -1907,6 +1914,12 @@ class SessionManager(object): ...@@ -1907,6 +1914,12 @@ class SessionManager(object):
session.reject(488) session.reject(488)
return return
session.send_ring_indication() session.send_ring_indication()
uri = session.remote_identity.uri
for contact in self.main_window.contact_model.iter_contacts():
if uri.matches(self.normalize_number(session.account, contact.uri)) or any(uri.matches(self.normalize_number(session.account, alias)) for alias in contact.sip_aliases):
break
else:
contact = None
if filetransfer_streams: if filetransfer_streams:
filetransfer_stream = filetransfer_streams[0] filetransfer_stream = filetransfer_streams[0]
else: else:
...@@ -1915,7 +1928,7 @@ class SessionManager(object): ...@@ -1915,7 +1928,7 @@ class SessionManager(object):
chat_stream = chat_streams[0] if chat_streams else None chat_stream = chat_streams[0] if chat_streams else None
desktopsharing_stream = desktopsharing_streams[0] if desktopsharing_streams else None desktopsharing_stream = desktopsharing_streams[0] if desktopsharing_streams else None
dialog = IncomingDialog() dialog = IncomingDialog()
incoming_session = IncomingSession(dialog, session, proposal=False, audio_stream=audio_stream, video_stream=video_stream, chat_stream=chat_stream, desktopsharing_stream=desktopsharing_stream) incoming_session = IncomingSession(dialog, session, contact, proposal=False, audio_stream=audio_stream, video_stream=video_stream, chat_stream=chat_stream, desktopsharing_stream=desktopsharing_stream)
bisect.insort_right(self.incoming_sessions, incoming_session) bisect.insort_right(self.incoming_sessions, incoming_session)
incoming_session.accepted.connect(partial(self._SH_IncomingSessionAccepted, incoming_session)) incoming_session.accepted.connect(partial(self._SH_IncomingSessionAccepted, incoming_session))
incoming_session.rejected.connect(partial(self._SH_IncomingSessionRejected, incoming_session)) incoming_session.rejected.connect(partial(self._SH_IncomingSessionRejected, incoming_session))
...@@ -1941,6 +1954,12 @@ class SessionManager(object): ...@@ -1941,6 +1954,12 @@ class SessionManager(object):
session.reject_proposal(488) session.reject_proposal(488)
return return
session.send_ring_indication() session.send_ring_indication()
uri = session.remote_identity.uri
for contact in self.main_window.contact_model.iter_contacts():
if uri.matches(self.normalize_number(session.account, contact.uri)) or any(uri.matches(self.normalize_number(session.account, alias)) for alias in contact.sip_aliases):
break
else:
contact = None
if filetransfer_streams: if filetransfer_streams:
filetransfer_stream = filetransfer_streams[0] filetransfer_stream = filetransfer_streams[0]
else: else:
...@@ -1949,7 +1968,7 @@ class SessionManager(object): ...@@ -1949,7 +1968,7 @@ class SessionManager(object):
chat_stream = chat_streams[0] if chat_streams else None chat_stream = chat_streams[0] if chat_streams else None
desktopsharing_stream = desktopsharing_streams[0] if desktopsharing_streams else None desktopsharing_stream = desktopsharing_streams[0] if desktopsharing_streams else None
dialog = IncomingDialog() dialog = IncomingDialog()
incoming_session = IncomingSession(dialog, session, proposal=True, audio_stream=audio_stream, video_stream=video_stream, chat_stream=chat_stream, desktopsharing_stream=desktopsharing_stream) incoming_session = IncomingSession(dialog, session, contact, proposal=True, audio_stream=audio_stream, video_stream=video_stream, chat_stream=chat_stream, desktopsharing_stream=desktopsharing_stream)
bisect.insort_right(self.incoming_sessions, incoming_session) bisect.insort_right(self.incoming_sessions, incoming_session)
incoming_session.accepted.connect(partial(self._SH_IncomingSessionAccepted, incoming_session)) incoming_session.accepted.connect(partial(self._SH_IncomingSessionAccepted, incoming_session))
incoming_session.rejected.connect(partial(self._SH_IncomingSessionRejected, incoming_session)) incoming_session.rejected.connect(partial(self._SH_IncomingSessionRejected, incoming_session))
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment