Commit 4b90654f authored by Dan Pascu's avatar Dan Pascu

Simplified MWI code and improved its user interface

parent 056e27f6
...@@ -10,7 +10,7 @@ from functools import partial ...@@ -10,7 +10,7 @@ from functools import partial
from PyQt4 import uic from PyQt4 import uic
from PyQt4.QtCore import Qt, QUrl, QVariant from PyQt4.QtCore import Qt, QUrl, QVariant
from PyQt4.QtGui import QAction, QActionGroup, QDesktopServices, QShortcut from PyQt4.QtGui import QAction, QActionGroup, QDesktopServices, QShortcut
from PyQt4.QtGui import QBrush, QColor, QFontMetrics, QPainter, QPen, QPixmap, QStyle, QStyleOptionComboBox, QStyleOptionFrameV2 from PyQt4.QtGui import QBrush, QColor, QFontMetrics, QIcon, QPainter, QPen, QPixmap, QStyle, QStyleOptionComboBox, QStyleOptionFrameV2
from application.notification import IObserver, NotificationCenter from application.notification import IObserver, NotificationCenter
from application.python.util import Null from application.python.util import Null
...@@ -19,6 +19,7 @@ from zope.interface import implements ...@@ -19,6 +19,7 @@ from zope.interface import implements
from sipsimple.account import Account, AccountManager, BonjourAccount from sipsimple.account import Account, AccountManager, BonjourAccount
from sipsimple.application import SIPApplication from sipsimple.application import SIPApplication
from sipsimple.configuration.settings import SIPSimpleSettings from sipsimple.configuration.settings import SIPSimpleSettings
from sipsimple.util import limit
from blink.aboutpanel import AboutPanel from blink.aboutpanel import AboutPanel
from blink.accounts import AccountModel, ActiveAccountModel, AddAccountDialog, ServerToolsAccountModel, ServerToolsWindow from blink.accounts import AccountModel, ActiveAccountModel, AddAccountDialog, ServerToolsAccountModel, ServerToolsWindow
...@@ -42,6 +43,11 @@ class MainWindow(base_class, ui_class): ...@@ -42,6 +43,11 @@ class MainWindow(base_class, ui_class):
notification_center = NotificationCenter() notification_center = NotificationCenter()
notification_center.add_observer(self, name='SIPApplicationWillStart') notification_center.add_observer(self, name='SIPApplicationWillStart')
notification_center.add_observer(self, name='SIPApplicationDidStart') notification_center.add_observer(self, name='SIPApplicationDidStart')
notification_center.add_observer(self, name='SIPAccountMWIDidGetSummary')
notification_center.add_observer(self, sender=AccountManager())
self.mwi_icons = [QIcon(Resources.get('icons/mwi-%d.png' % i)) for i in xrange(0, 11)]
self.mwi_icons.append(QIcon(Resources.get('icons/mwi-many.png')))
with Resources.directory: with Resources.directory:
self.setupUi() self.setupUi()
...@@ -331,11 +337,9 @@ class MainWindow(base_class, ui_class): ...@@ -331,11 +337,9 @@ class MainWindow(base_class, ui_class):
self.server_tools_window.open_buy_pstn_access_page(account) self.server_tools_window.open_buy_pstn_access_page(account)
def _AH_VoicemailActionTriggered(self, action, checked): def _AH_VoicemailActionTriggered(self, action, checked):
account, received_voicemail_uri = action.data().toPyObject() account = action.data().toPyObject()
voicemail_uri = account.message_summary.voicemail_uri or received_voicemail_uri voicemail_uri = account.message_summary.uri
if voicemail_uri: SessionManager().start_call("Voicemail", voicemail_uri, account=account)
session_manager = SessionManager()
session_manager.start_call(voicemail_uri, voicemail_uri, account=account)
def _SH_AddContactButtonClicked(self, clicked): def _SH_AddContactButtonClicked(self, clicked):
model = self.contact_model model = self.contact_model
...@@ -514,6 +518,7 @@ class MainWindow(base_class, ui_class): ...@@ -514,6 +518,7 @@ class MainWindow(base_class, ui_class):
handler(notification) handler(notification)
def _NH_SIPApplicationWillStart(self, notification): def _NH_SIPApplicationWillStart(self, notification):
account_manager = AccountManager()
settings = SIPSimpleSettings() settings = SIPSimpleSettings()
self.silent_action.setChecked(settings.audio.silent) self.silent_action.setChecked(settings.audio.silent)
self.silent_button.setChecked(settings.audio.silent) self.silent_button.setChecked(settings.audio.silent)
...@@ -522,28 +527,11 @@ class MainWindow(base_class, ui_class): ...@@ -522,28 +527,11 @@ class MainWindow(base_class, ui_class):
else: else:
self.google_contacts_action.setText(u'Disable Google Contacts') self.google_contacts_action.setText(u'Disable Google Contacts')
self.google_contacts_action.triggered.connect(self._AH_GoogleContactsActionTriggered) self.google_contacts_action.triggered.connect(self._AH_GoogleContactsActionTriggered)
account_manager = AccountManager()
notification_center = NotificationCenter()
notification_center.add_observer(self, sender=account_manager)
if not any(account.enabled for account in account_manager.iter_accounts()): if not any(account.enabled for account in account_manager.iter_accounts()):
self.display_name.setEnabled(False) self.display_name.setEnabled(False)
self.activity_note.setEnabled(False) self.activity_note.setEnabled(False)
self.status.setEnabled(False) self.status.setEnabled(False)
self.status.setCurrentIndex(self.status.findText(u'Offline')) self.status.setCurrentIndex(self.status.findText(u'Offline'))
for account in account_manager.iter_accounts():
action = QAction(account.id if account is not BonjourAccount() else u'Bonjour', None)
action.setCheckable(True)
action.setEnabled(True if account is not BonjourAccount() else BonjourAccount.mdns_available)
action.setData(QVariant(account))
action.setChecked(account.enabled)
action.triggered.connect(partial(self._AH_AccountActionTriggered, action))
self.accounts_menu.addAction(action)
if isinstance(account, Account) and account.enabled and account.message_summary.enabled:
vm_action = QAction(u'%s - No new messages' % account.id, None)
vm_action.setData(QVariant((account, None)))
vm_action.setEnabled(account.message_summary.voicemail_uri is not None)
vm_action.triggered.connect(partial(self._AH_VoicemailActionTriggered, vm_action))
self.voicemail_menu.addAction(vm_action)
def _NH_SIPApplicationDidStart(self, notification): def _NH_SIPApplicationDidStart(self, notification):
self.load_audio_devices() self.load_audio_devices()
...@@ -571,7 +559,6 @@ class MainWindow(base_class, ui_class): ...@@ -571,7 +559,6 @@ class MainWindow(base_class, ui_class):
settings.audio.input_device = new_device settings.audio.input_device = new_device
settings.audio.output_device = new_device settings.audio.output_device = new_device
settings.save() settings.save()
# TODO: Add a confirmation window when no active sessions
self.load_audio_devices() self.load_audio_devices()
def _NH_CFGSettingsObjectDidChange(self, notification): def _NH_CFGSettingsObjectDidChange(self, notification):
...@@ -602,53 +589,33 @@ class MainWindow(base_class, ui_class): ...@@ -602,53 +589,33 @@ class MainWindow(base_class, ui_class):
if 'enabled' in notification.data.modified: if 'enabled' in notification.data.modified:
action = (action for action in self.accounts_menu.actions() if action.data().toPyObject() is account).next() action = (action for action in self.accounts_menu.actions() if action.data().toPyObject() is account).next()
action.setChecked(account.enabled) action.setChecked(account.enabled)
if account.enabled and account.message_summary.enabled: if set(['enabled', 'message_summary.enabled', 'message_summary.voicemail_uri']).intersection(notification.data.modified):
vm_action = QAction(u'%s - No new messages' % account.id, None) action = (action for action in self.voicemail_menu.actions() if action.data().toPyObject() is account).next()
vm_action.setData(QVariant((account, None))) action.setVisible(False if account is BonjourAccount() else account.enabled and account.message_summary.enabled)
vm_action.setEnabled(account.message_summary.voicemail_uri is not None) action.setEnabled(False if account is BonjourAccount() else account.message_summary.uri is not None)
vm_action.triggered.connect(partial(self._AH_VoicemailActionTriggered, vm_action))
self.voicemail_menu.addAction(vm_action)
else:
try:
vm_action = (action for action in self.voicemail_menu.actions() if action.data().toPyObject()[0] is account).next()
except StopIteration:
pass
else:
self.voicemail_menu.removeAction(vm_action)
if 'message_summary.enabled' in notification.data.modified:
if account.message_summary.enabled:
vm_action = QAction(u'%s - No new messages' % account.id, None)
vm_action.setData(QVariant((account, None)))
vm_action.setEnabled(account.message_summary.voicemail_uri is not None)
vm_action.triggered.connect(partial(self._AH_VoicemailActionTriggered, vm_action))
self.voicemail_menu.addAction(vm_action)
else:
vm_action = (action for action in self.voicemail_menu.actions() if action.data().toPyObject()[0] is account).next()
self.voicemail_menu.removeAction(action)
if 'message_summary.voicemail_uri' in notification.data.modified:
if account.message_summary.enabled:
vm_action = (action for action in self.voicemail_menu.actions() if action.data().toPyObject()[0] is account).next()
vm_action.setEnabled(account.message_summary.voicemail_uri is not None)
def _NH_SIPAccountManagerWillStart(self, notification):
notification_center = NotificationCenter()
notification_center.add_observer(self, name='SIPAccountMWIDidGetSummary')
def _NH_SIPAccountManagerDidAddAccount(self, notification): def _NH_SIPAccountManagerDidAddAccount(self, notification):
account = notification.data.account account = notification.data.account
action = QAction(account.id, None) action = QAction(account.id if account is not BonjourAccount() else u'Bonjour', None)
action.setEnabled(True if account is not BonjourAccount() else BonjourAccount.mdns_available)
action.setCheckable(True) action.setCheckable(True)
action.setChecked(account.enabled)
action.setData(QVariant(account)) action.setData(QVariant(account))
action.triggered.connect(partial(self._AH_AccountActionTriggered, action)) action.triggered.connect(partial(self._AH_AccountActionTriggered, action))
self.accounts_menu.addAction(action) self.accounts_menu.addAction(action)
action = QAction(self.mwi_icons[0], account.id, None)
action.setVisible(False if account is BonjourAccount() else account.enabled and account.message_summary.enabled)
action.setEnabled(False if account is BonjourAccount() else account.message_summary.uri is not None)
action.setData(QVariant(account))
action.triggered.connect(partial(self._AH_VoicemailActionTriggered, action))
self.voicemail_menu.addAction(action)
def _NH_SIPAccountManagerDidRemoveAccount(self, notification): def _NH_SIPAccountManagerDidRemoveAccount(self, notification):
account = notification.data.account account = notification.data.account
action = (action for action in self.accounts_menu.actions() if action.data().toPyObject() is account).next() action = (action for action in self.accounts_menu.actions() if action.data().toPyObject() is account).next()
self.accounts_menu.removeAction(action) self.accounts_menu.removeAction(action)
if isinstance(account, Account) and account.enabled and account.message_summary.enabled: action = (action for action in self.voicemail_menu.actions() if action.data().toPyObject() is account).next()
action = (action for action in self.voicemail_menu.actions() if action.data().toPyObject()[0] is account).next() self.voicemail_menu.removeAction(action)
self.voicemail_menu.removeAction(action)
def _NH_SIPAccountManagerDidChangeDefaultAccount(self, notification): def _NH_SIPAccountManagerDidChangeDefaultAccount(self, notification):
if notification.data.account is None: if notification.data.account is None:
...@@ -660,15 +627,16 @@ class MainWindow(base_class, ui_class): ...@@ -660,15 +627,16 @@ class MainWindow(base_class, ui_class):
def _NH_SIPAccountMWIDidGetSummary(self, notification): def _NH_SIPAccountMWIDidGetSummary(self, notification):
account = notification.sender account = notification.sender
summary = notification.data.message_summary summary = notification.data.message_summary
action = (action for action in self.voicemail_menu.actions() if action.data().toPyObject()[0] is account).next() action = (action for action in self.voicemail_menu.actions() if action.data().toPyObject() is account).next()
action.setData(QVariant((account, summary.message_account))) action.setEnabled(account.message_summary.uri is not None)
action.setEnabled(True if account.message_summary.voicemail_uri is not None or summary.message_account is not None else False) if summary.messages_waiting:
if summary.messages_waiting and summary.summaries.get('voice-message') is not None: try:
new_messages = int(summary.summaries.get('voice-message').get('new_messages', 0)) new_messages = limit(int(summary.summaries['voice-message']['new_messages']), min=0, max=11)
vm_text = u'%d new messages' % new_messages if new_messages > 0 else u'No new messages' except (KeyError, ValueError):
new_messages = 0
else: else:
vm_text = u'No new messages' new_messages = 0
action.setText(u'%s - %s' % (account.id, vm_text)) action.setIcon(self.mwi_icons[new_messages])
del ui_class, base_class del ui_class, base_class
......
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="16px"
height="16px"
id="svg2816"
version="1.1"
inkscape:version="0.47 r22583"
sodipodi:docname="drawing-1.png">
<defs
id="defs2818">
<inkscape:perspective
sodipodi:type="inkscape:persp3d"
inkscape:vp_x="0 : 8 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_z="16 : 8 : 1"
inkscape:persp3d-origin="8 : 5.3333333 : 1"
id="perspective2824" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="8.7173008"
inkscape:cx="38.878553"
inkscape:cy="12.659164"
inkscape:current-layer="layer1"
showgrid="true"
inkscape:grid-bbox="true"
inkscape:document-units="px"
inkscape:window-width="1209"
inkscape:window-height="763"
inkscape:window-x="367"
inkscape:window-y="230"
inkscape:window-maximized="0" />
<metadata
id="metadata2821">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
id="layer1"
inkscape:label="Layer 1"
inkscape:groupmode="layer">
<path
sodipodi:type="arc"
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:#c70000;stroke-width:0.99800003;stroke-linecap:butt;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
id="path2826"
sodipodi:cx="10.316337"
sodipodi:cy="10.07599"
sodipodi:rx="5.6762376"
sodipodi:ry="6.0141091"
d="m 15.992574,10.07599 a 5.6762376,6.0141091 0 1 1 -11.352475,0 5.6762376,6.0141091 0 1 1 11.352475,0 z"
transform="matrix(1.2984867,0,0,1.2255379,-5.3956259,-4.3485073)" />
<text
xml:space="preserve"
style="font-size:9.39675713px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Trebuchet MS;-inkscape-font-specification:Trebuchet MS"
x="1.8998702"
y="10.112906"
id="text3600"
transform="scale(0.84227997,1.1872537)"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan3602"
x="1.8998702"
y="10.112906">999</tspan></text>
</g>
</svg>
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