Commit dd65b1cf authored by Dan Pascu's avatar Dan Pascu

Implemented presence state based on the AccountState widget

parent 6ddd6758
...@@ -8,9 +8,9 @@ __all__ = ['MainWindow'] ...@@ -8,9 +8,9 @@ __all__ = ['MainWindow']
from functools import partial from functools import partial
from PyQt4 import uic from PyQt4 import uic
from PyQt4.QtCore import Qt, QUrl from PyQt4.QtCore import QUrl
from PyQt4.QtGui import QAction, QActionGroup, QDesktopServices, QShortcut from PyQt4.QtGui import QAction, QActionGroup, QDesktopServices, QShortcut
from PyQt4.QtGui import QBrush, QColor, QFontMetrics, QIcon, QPainter, QPen, QPixmap, QStyle, QStyleOptionComboBox, QStyleOptionFrameV2 from PyQt4.QtGui import QIcon, QStyle, QStyleOptionComboBox, QStyleOptionFrameV2
from application.notification import IObserver, NotificationCenter from application.notification import IObserver, NotificationCenter
from application.python import Null, limit from application.python import Null, limit
...@@ -28,7 +28,7 @@ from blink.sessions import ConferenceDialog, SessionManager, SessionModel ...@@ -28,7 +28,7 @@ from blink.sessions import ConferenceDialog, SessionManager, SessionModel
from blink.configuration.datatypes import InvalidToken from blink.configuration.datatypes import InvalidToken
from blink.resources import Resources from blink.resources import Resources
from blink.util import run_in_gui_thread from blink.util import run_in_gui_thread
from blink.widgets.buttons import SwitchViewButton from blink.widgets.buttons import AccountState, SwitchViewButton
ui_class, base_class = uic.loadUiType(Resources.get('blink.ui')) ui_class, base_class = uic.loadUiType(Resources.get('blink.ui'))
...@@ -38,7 +38,7 @@ class MainWindow(base_class, ui_class): ...@@ -38,7 +38,7 @@ class MainWindow(base_class, ui_class):
def __init__(self, parent=None): def __init__(self, parent=None):
super(MainWindow, self).__init__(parent) super(MainWindow, self).__init__(parent)
self.idle_status_index = 0 self.saved_account_state = None
notification_center = NotificationCenter() notification_center = NotificationCenter()
notification_center.add_observer(self, name='SIPApplicationWillStart') notification_center.add_observer(self, name='SIPApplicationWillStart')
...@@ -54,7 +54,7 @@ class MainWindow(base_class, ui_class): ...@@ -54,7 +54,7 @@ class MainWindow(base_class, ui_class):
self.setWindowTitle('Blink') self.setWindowTitle('Blink')
self.setWindowIconText('Blink') self.setWindowIconText('Blink')
self.set_user_icon(Resources.get("icons/default-avatar.png")) # ":/resources/icons/default-avatar.png" self.set_user_icon(Resources.get("icons/avatar.jpg")) # ":/resources/icons/avatar.png"
self.active_sessions_label.hide() self.active_sessions_label.hide()
self.enable_call_buttons(False) self.enable_call_buttons(False)
...@@ -95,6 +95,8 @@ class MainWindow(base_class, ui_class): ...@@ -95,6 +95,8 @@ class MainWindow(base_class, ui_class):
self.server_tools_window = ServerToolsWindow(self.server_tools_account_model, None) self.server_tools_window = ServerToolsWindow(self.server_tools_account_model, None)
# Signals # Signals
self.account_state.stateChanged.connect(self._SH_AccountStateChanged)
self.activity_note.editingFinished.connect(self._SH_ActivityNoteEditingFinished)
self.add_contact_button.clicked.connect(self._SH_AddContactButtonClicked) self.add_contact_button.clicked.connect(self._SH_AddContactButtonClicked)
self.add_search_contact_button.clicked.connect(self._SH_AddContactButtonClicked) self.add_search_contact_button.clicked.connect(self._SH_AddContactButtonClicked)
self.audio_call_button.clicked.connect(self._SH_AudioCallButtonClicked) self.audio_call_button.clicked.connect(self._SH_AudioCallButtonClicked)
...@@ -129,7 +131,6 @@ class MainWindow(base_class, ui_class): ...@@ -129,7 +131,6 @@ class MainWindow(base_class, ui_class):
self.session_model.structureChanged.connect(self._SH_SessionModelChangedStructure) self.session_model.structureChanged.connect(self._SH_SessionModelChangedStructure)
self.silent_button.clicked.connect(self._SH_SilentButtonClicked) self.silent_button.clicked.connect(self._SH_SilentButtonClicked)
self.status.activated[int].connect(self._SH_StatusChanged)
self.switch_view_button.viewChanged.connect(self._SH_SwitchViewButtonChangedView) self.switch_view_button.viewChanged.connect(self._SH_SwitchViewButtonChangedView)
# Blink menu actions # Blink menu actions
...@@ -184,29 +185,10 @@ class MainWindow(base_class, ui_class): ...@@ -184,29 +185,10 @@ class MainWindow(base_class, ui_class):
if frame_width < 4: if frame_width < 4:
search_box.setMinimumHeight(20 + 2*frame_width) search_box.setMinimumHeight(20 + 2*frame_width)
# adjust status combo-box font size to fit the combo-box
option = QStyleOptionComboBox()
self.status.initStyleOption(option)
frame_width = self.status.style().pixelMetric(QStyle.PM_DefaultFrameWidth, option, self.status)
font = self.status.font()
font.setFamily('Sans Serif')
font.setPointSize(font.pointSize() - 1) # make it 1 point smaller then the default font size
font_metrics = QFontMetrics(font)
if font_metrics.height() > self.status.maximumHeight() - 2*frame_width:
pixel_size = 11 - (frame_width - 2) # subtract 1 pixel for every frame pixel over 2 pixels
font.setPixelSize(pixel_size)
self.status.setFont(font)
# adjust the combo boxes for themes with too much padding (like the default theme on Ubuntu 10.04) # adjust the combo boxes for themes with too much padding (like the default theme on Ubuntu 10.04)
option = QStyleOptionComboBox() option = QStyleOptionComboBox()
self.status.initStyleOption(option) self.identity.initStyleOption(option)
font_metrics = self.status.fontMetrics() wide_padding = self.identity.style().subControlRect(QStyle.CC_ComboBox, option, QStyle.SC_ComboBoxEditField, self.identity).height() < 10
text_width = max(font_metrics.width(self.status.itemText(index)) for index in xrange(self.status.count()))
frame_width = self.status.style().pixelMetric(QStyle.PM_ComboBoxFrameWidth, option, self.status)
arrow_width = self.status.style().subControlRect(QStyle.CC_ComboBox, option, QStyle.SC_ComboBoxArrow, self.status).width()
wide_padding = self.status.style().subControlRect(QStyle.CC_ComboBox, option, QStyle.SC_ComboBoxEditField, self.status).height() < 10
self.status.setFixedWidth(text_width + arrow_width + 2*frame_width + 30) # 30? Don't ask.
self.status.setStyleSheet("""QComboBox { padding: 0px 3px 0px 3px; }""" if wide_padding else "")
self.identity.setStyleSheet("""QComboBox { padding: 0px 4px 0px 4px; }""" if wide_padding else "") self.identity.setStyleSheet("""QComboBox { padding: 0px 4px 0px 4px; }""" if wide_padding else "")
def closeEvent(self, event): def closeEvent(self, event):
...@@ -219,21 +201,7 @@ class MainWindow(base_class, ui_class): ...@@ -219,21 +201,7 @@ class MainWindow(base_class, ui_class):
self.server_tools_window.close() self.server_tools_window.close()
def set_user_icon(self, image_file_name): def set_user_icon(self, image_file_name):
pixmap = QPixmap(32, 32) self.account_state.setIcon(QIcon(image_file_name))
pixmap.fill(QColor(Qt.transparent))
painter = QPainter(pixmap)
painter.setRenderHint(QPainter.Antialiasing, True)
painter.setBrush(QBrush(Qt.white))
painter.setPen(QPen(painter.brush(), 0, Qt.NoPen))
#painter.drawRoundedRect(0, 0, 32, 32, 6, 6)
painter.drawRoundedRect(0, 0, 32, 32, 0, 0)
icon = QPixmap()
if icon.load(image_file_name):
icon = icon.scaled(32, 32, Qt.KeepAspectRatio, Qt.SmoothTransformation)
painter.setCompositionMode(QPainter.CompositionMode_SourceOver)
painter.drawPixmap(0, 0, icon)
painter.end()
self.image.setPixmap(pixmap)
def enable_call_buttons(self, enabled): def enable_call_buttons(self, enabled):
self.audio_call_button.setEnabled(enabled) self.audio_call_button.setEnabled(enabled)
...@@ -364,6 +332,15 @@ class MainWindow(base_class, ui_class): ...@@ -364,6 +332,15 @@ class MainWindow(base_class, ui_class):
account = action.data() account = action.data()
SessionManager().start_call("Voicemail", account.voicemail_uri, account=account) SessionManager().start_call("Voicemail", account.voicemail_uri, account=account)
def _SH_AccountStateChanged(self, action):
self.activity_note.setText(action.note)
self.saved_account_state = None
def _SH_ActivityNoteEditingFinished(self):
self.activity_note.clearFocus()
self.account_state.setState(self.account_state.state, self.activity_note.text())
self.saved_account_state = None
def _SH_AddContactButtonClicked(self, clicked): def _SH_AddContactButtonClicked(self, clicked):
model = self.contact_model model = self.contact_model
selected_items = ((index.row(), model.data(index)) for index in self.contact_list.selectionModel().selectedIndexes()) selected_items = ((index.row(), model.data(index)) for index in self.contact_list.selectionModel().selectedIndexes())
...@@ -440,15 +417,14 @@ class MainWindow(base_class, ui_class): ...@@ -440,15 +417,14 @@ class MainWindow(base_class, ui_class):
self.display_name.setText(account.display_name or u'') self.display_name.setText(account.display_name or u'')
self.display_name.setEnabled(True) self.display_name.setEnabled(True)
self.activity_note.setEnabled(True) self.activity_note.setEnabled(True)
self.status.setEnabled(True) self.account_state.setEnabled(True)
if not self.session_model.active_sessions:
self.status.setCurrentIndex(self.idle_status_index)
else: else:
self.display_name.clear() self.display_name.clear()
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.account_state.setEnabled(False)
self.status.setCurrentIndex(self.status.findText(u'Offline')) self.account_state.setState(AccountState.Invisible)
self.saved_account_state = None
def _SH_MakeConference(self): def _SH_MakeConference(self):
self.session_model.conferenceSessions([session for session in self.session_model.active_sessions if session.conference is None]) self.session_model.conferenceSessions([session for session in self.session_model.active_sessions if session.conference is None])
...@@ -519,19 +495,23 @@ class MainWindow(base_class, ui_class): ...@@ -519,19 +495,23 @@ class MainWindow(base_class, ui_class):
else: else:
self.conference_button.setEnabled(len([session for session in active_sessions if session.conference is None]) > 1) self.conference_button.setEnabled(len([session for session in active_sessions if session.conference is None]) > 1)
self.conference_button.setChecked(False) self.conference_button.setChecked(False)
if active_sessions and self.status.currentText() != u'Offline': if active_sessions:
self.status.setCurrentIndex(self.status.findText(u'On the phone')) if self.account_state.state is not AccountState.Invisible:
else: if self.saved_account_state is None:
self.status.setCurrentIndex(self.idle_status_index) self.saved_account_state = self.account_state.state, self.activity_note.text()
self.account_state.setState(AccountState.Busy)
self.activity_note.setText(u'On the phone')
elif self.saved_account_state is not None:
state, note = self.saved_account_state
self.saved_account_state = None
self.activity_note.setText(note)
self.account_state.setState(state, note)
def _SH_SilentButtonClicked(self, silent): def _SH_SilentButtonClicked(self, silent):
settings = SIPSimpleSettings() settings = SIPSimpleSettings()
settings.audio.silent = silent settings.audio.silent = silent
settings.save() settings.save()
def _SH_StatusChanged(self, index):
self.idle_status_index = index
def _SH_SwitchViewButtonChangedView(self, view): def _SH_SwitchViewButtonChangedView(self, view):
self.main_view.setCurrentWidget(self.contacts_panel if view is SwitchViewButton.ContactView else self.sessions_panel) self.main_view.setCurrentWidget(self.contacts_panel if view is SwitchViewButton.ContactView else self.sessions_panel)
...@@ -556,8 +536,9 @@ class MainWindow(base_class, ui_class): ...@@ -556,8 +536,9 @@ class MainWindow(base_class, ui_class):
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.account_state.setEnabled(False)
self.status.setCurrentIndex(self.status.findText(u'Offline')) else:
self.account_state.setState(AccountState.Available)
def _NH_SIPApplicationDidStart(self, notification): def _NH_SIPApplicationDidStart(self, notification):
self.load_audio_devices() self.load_audio_devices()
......
...@@ -42,12 +42,6 @@ ...@@ -42,12 +42,6 @@
</property> </property>
<item> <item>
<widget class="AccountSelector" name="identity"> <widget class="AccountSelector" name="identity">
<property name="minimumSize">
<size>
<width>0</width>
<height>20</height>
</size>
</property>
<property name="maximumSize"> <property name="maximumSize">
<size> <size>
<width>16777215</width> <width>16777215</width>
...@@ -90,33 +84,19 @@ ...@@ -90,33 +84,19 @@
<number>1</number> <number>1</number>
</property> </property>
<item> <item>
<widget class="QLabel" name="image"> <widget class="AccountState" name="account_state">
<property name="minimumSize"> <property name="icon">
<size> <iconset>
<width>36</width> <normaloff>icons/avatar.jpg</normaloff>icons/avatar.jpg</iconset>
<height>36</height>
</size>
</property> </property>
<property name="maximumSize"> <property name="iconSize">
<size> <size>
<width>36</width> <width>32</width>
<height>36</height> <height>32</height>
</size> </size>
</property> </property>
<property name="toolTip"> <property name="popupMode">
<string>Click to change your picture</string> <enum>QToolButton::MenuButtonPopup</enum>
</property>
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Sunken</enum>
</property>
<property name="pixmap">
<pixmap>icons/default-avatar.png</pixmap>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property> </property>
</widget> </widget>
</item> </item>
...@@ -125,11 +105,6 @@ ...@@ -125,11 +105,6 @@
<property name="spacing"> <property name="spacing">
<number>0</number> <number>0</number>
</property> </property>
<item>
<layout class="QHBoxLayout" name="name_status_layout">
<property name="spacing">
<number>4</number>
</property>
<item> <item>
<widget class="LineEdit" name="display_name"> <widget class="LineEdit" name="display_name">
<property name="maximumSize"> <property name="maximumSize">
...@@ -158,75 +133,6 @@ ...@@ -158,75 +133,6 @@
</property> </property>
</widget> </widget>
</item> </item>
<item>
<widget class="QComboBox" name="status">
<property name="minimumSize">
<size>
<width>0</width>
<height>18</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>18</height>
</size>
</property>
<property name="iconSize">
<size>
<width>10</width>
<height>10</height>
</size>
</property>
<item>
<property name="text">
<string>Available</string>
</property>
<property name="icon">
<iconset>
<normaloff>icons/green-dot.svg</normaloff>icons/green-dot.svg</iconset>
</property>
</item>
<item>
<property name="text">
<string>Away</string>
</property>
<property name="icon">
<iconset>
<normaloff>icons/yellow-dot.svg</normaloff>icons/yellow-dot.svg</iconset>
</property>
</item>
<item>
<property name="text">
<string>Busy</string>
</property>
<property name="icon">
<iconset>
<normaloff>icons/red-dot.svg</normaloff>icons/red-dot.svg</iconset>
</property>
</item>
<item>
<property name="text">
<string>On the phone</string>
</property>
<property name="icon">
<iconset>
<normaloff>icons/red-dot.svg</normaloff>icons/red-dot.svg</iconset>
</property>
</item>
<item>
<property name="text">
<string>Offline</string>
</property>
<property name="icon">
<iconset>
<normaloff>icons/grey-dot.svg</normaloff>icons/grey-dot.svg</iconset>
</property>
</item>
</widget>
</item>
</layout>
</item>
<item> <item>
<widget class="LineEdit" name="activity_note"> <widget class="LineEdit" name="activity_note">
<property name="maximumSize"> <property name="maximumSize">
...@@ -235,6 +141,124 @@ ...@@ -235,6 +141,124 @@
<height>18</height> <height>18</height>
</size> </size>
</property> </property>
<property name="palette">
<palette>
<active>
<colorrole role="Button">
<brush brushstyle="SolidPattern">
<color alpha="0">
<red>0</red>
<green>0</green>
<blue>0</blue>
</color>
</brush>
</colorrole>
<colorrole role="Text">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>70</red>
<green>70</green>
<blue>70</blue>
</color>
</brush>
</colorrole>
<colorrole role="Base">
<brush brushstyle="SolidPattern">
<color alpha="0">
<red>0</red>
<green>0</green>
<blue>0</blue>
</color>
</brush>
</colorrole>
<colorrole role="Window">
<brush brushstyle="SolidPattern">
<color alpha="0">
<red>0</red>
<green>0</green>
<blue>0</blue>
</color>
</brush>
</colorrole>
</active>
<inactive>
<colorrole role="Button">
<brush brushstyle="SolidPattern">
<color alpha="0">
<red>0</red>
<green>0</green>
<blue>0</blue>
</color>
</brush>
</colorrole>
<colorrole role="Text">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>70</red>
<green>70</green>
<blue>70</blue>
</color>
</brush>
</colorrole>
<colorrole role="Base">
<brush brushstyle="SolidPattern">
<color alpha="0">
<red>0</red>
<green>0</green>
<blue>0</blue>
</color>
</brush>
</colorrole>
<colorrole role="Window">
<brush brushstyle="SolidPattern">
<color alpha="0">
<red>0</red>
<green>0</green>
<blue>0</blue>
</color>
</brush>
</colorrole>
</inactive>
<disabled>
<colorrole role="Button">
<brush brushstyle="SolidPattern">
<color alpha="0">
<red>0</red>
<green>0</green>
<blue>0</blue>
</color>
</brush>
</colorrole>
<colorrole role="Text">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>166</red>
<green>165</green>
<blue>165</blue>
</color>
</brush>
</colorrole>
<colorrole role="Base">
<brush brushstyle="SolidPattern">
<color alpha="0">
<red>0</red>
<green>0</green>
<blue>0</blue>
</color>
</brush>
</colorrole>
<colorrole role="Window">
<brush brushstyle="SolidPattern">
<color alpha="0">
<red>0</red>
<green>0</green>
<blue>0</blue>
</color>
</brush>
</colorrole>
</disabled>
</palette>
</property>
<property name="styleSheet"> <property name="styleSheet">
<string>QLineEdit { <string>QLineEdit {
background-color: transparent; background-color: transparent;
...@@ -889,7 +913,7 @@ padding: 2px;</string> ...@@ -889,7 +913,7 @@ padding: 2px;</string>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>285</width> <width>285</width>
<height>22</height> <height>20</height>
</rect> </rect>
</property> </property>
<widget class="QMenu" name="blink_menu"> <widget class="QMenu" name="blink_menu">
...@@ -1322,23 +1346,28 @@ padding: 2px;</string> ...@@ -1322,23 +1346,28 @@ padding: 2px;</string>
<extends>QToolButton</extends> <extends>QToolButton</extends>
<header>blink.widgets.buttons</header> <header>blink.widgets.buttons</header>
</customwidget> </customwidget>
<customwidget>
<class>AccountState</class>
<extends>QToolButton</extends>
<header>blink.widgets.buttons</header>
</customwidget>
</customwidgets> </customwidgets>
<tabstops> <tabstops>
<tabstop>search_box</tabstop> <tabstop>search_box</tabstop>
<tabstop>search_list</tabstop> <tabstop>account_state</tabstop>
<tabstop>activity_note</tabstop>
<tabstop>status</tabstop>
<tabstop>display_name</tabstop> <tabstop>display_name</tabstop>
<tabstop>activity_note</tabstop>
<tabstop>switch_view_button</tabstop> <tabstop>switch_view_button</tabstop>
<tabstop>contact_list</tabstop> <tabstop>contact_list</tabstop>
<tabstop>back_to_contacts_button</tabstop>
<tabstop>add_search_contact_button</tabstop>
<tabstop>identity</tabstop>
<tabstop>add_contact_button</tabstop> <tabstop>add_contact_button</tabstop>
<tabstop>audio_call_button</tabstop> <tabstop>audio_call_button</tabstop>
<tabstop>im_session_button</tabstop> <tabstop>im_session_button</tabstop>
<tabstop>ds_session_button</tabstop> <tabstop>ds_session_button</tabstop>
<tabstop>silent_button</tabstop> <tabstop>silent_button</tabstop>
<tabstop>identity</tabstop>
<tabstop>add_search_contact_button</tabstop>
<tabstop>back_to_contacts_button</tabstop>
<tabstop>search_list</tabstop>
<tabstop>session_list</tabstop> <tabstop>session_list</tabstop>
<tabstop>hangup_all_button</tabstop> <tabstop>hangup_all_button</tabstop>
<tabstop>conference_button</tabstop> <tabstop>conference_button</tabstop>
......
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