Commit 1752d1af authored by Dan Pascu's avatar Dan Pascu

Added chat preferences

parent 2ca9570e
......@@ -24,7 +24,7 @@ from zope.interface import implements
from sipsimple.account import AccountManager
from sipsimple.configuration.settings import SIPSimpleSettings
from blink.configuration.datatypes import FileURL
from blink.configuration.datatypes import FileURL, GraphTimeScale
from blink.configuration.settings import BlinkSettings
from blink.contacts import URIUtils
from blink.resources import IconManager, Resources
......@@ -476,24 +476,22 @@ ui_class, base_class = uic.loadUiType(Resources.get('chat_widget.ui'))
class ChatWidget(base_class, ui_class):
default_user_icon = IconDescriptor(Resources.get('icons/default-avatar.png'))
chat_template = open(Resources.get('chat/template.html')).read()
def __init__(self, session, parent=None):
super(ChatWidget, self).__init__(parent)
with Resources.directory:
self.setupUi(self)
self.session = session
self.style = ChatMessageStyle('Stockholm')
self.style_variant = self.style.default_variant
#self.style_variant = 'Blue - Red'
#self.style = ChatMessageStyle('Smooth Operator')
#self.style_variant = self.style.default_variant
#self.style_variant = 'Classic'
#self.style_variant = 'Time-Icon'
chat_template = open(Resources.get('chat/template.html')).read()
self.chat_view.setChatFont(self.style.font_family, self.style.font_size)
self.chat_view.setHtml(chat_template.format(base_url=FileURL(self.style.path)+'/', style_url=self.style_variant+'.style'))
blink_settings = BlinkSettings()
self.style = ChatMessageStyle(blink_settings.chat_window.style)
self.style_variant = blink_settings.chat_window.style_variant or self.style.default_variant
self.user_icons_css_class = 'show-icons' if blink_settings.chat_window.show_user_icons else 'hide-icons'
self.chat_view.setChatFont(blink_settings.chat_window.font or self.style.font_family, blink_settings.chat_window.font_size or self.style.font_size)
self.chat_view.setHtml(self.chat_template.format(base_url=FileURL(self.style.path)+'/', style_url=self.style_variant+'.style'))
self.chat_element = self.chat_view.page().mainFrame().findFirstElement('#chat')
self.composing_timer = QTimer()
self.last_message = None
self.session = session
# connect to signals
self.chat_input.textChanged.connect(self._SH_ChatInputTextChanged)
self.chat_input.textEntered.connect(self._SH_ChatInputTextEntered)
......@@ -505,10 +503,10 @@ class ChatWidget(base_class, ui_class):
insertion_point = self.chat_element.findFirst('#insert')
if message.is_related_to(self.last_message):
message.consecutive = True
insertion_point.replace(message.to_html(self.style, user_icons='show-icons'))
insertion_point.replace(message.to_html(self.style, user_icons=self.user_icons_css_class))
else:
insertion_point.removeFromDocument()
self.chat_element.appendInside(message.to_html(self.style, user_icons='show-icons'))
self.chat_element.appendInside(message.to_html(self.style, user_icons=self.user_icons_css_class))
self.last_message = message
def _align_chat(self, scroll=False):
......@@ -657,6 +655,10 @@ class ChatWindow(base_class, ui_class, ColorHelperMixin):
self.session_widget.installEventFilter(self)
self.state_label.installEventFilter(self)
self.latency_graph.installEventFilter(self)
self.packet_loss_graph.installEventFilter(self)
self.traffic_graph.installEventFilter(self)
self.mute_button.clicked.connect(self._SH_MuteButtonClicked)
self.hold_button.clicked.connect(self._SH_HoldButtonClicked)
self.record_button.clicked.connect(self._SH_RecordButtonClicked)
......@@ -708,9 +710,6 @@ class ChatWindow(base_class, ui_class, ColorHelperMixin):
self.lock_grey_icon = QIcon(Resources.get('icons/lock-grey-12.svg'))
self.lock_green_icon = QIcon(Resources.get('icons/lock-green-12.svg'))
# re-apply the stylesheet for self.session_info_container_widget to account for all its subwidget role properties that were set after it
self.info_panel_container_widget.setStyleSheet(self.info_panel_container_widget.styleSheet())
# fix the SVG icons as the generated code loads them as pixmaps, losing their ability to scale -Dan
def svg_icon(filename_off, filename_on):
icon = QIcon()
......@@ -764,18 +763,16 @@ class ChatWindow(base_class, ui_class, ColorHelperMixin):
self.traffic_graph.add_graph(self.incoming_traffic_graph)
self.traffic_graph.add_graph(self.outgoing_traffic_graph)
self.info_panel_files_button.hide()
self.info_panel_participants_button.hide()
self.participants_panel_files_button.hide()
self.dummy_tab = None # will be replaced by a dummy ChatWidget during SIPApplicationDidStart (creating a ChatWidget needs access to settings)
self.tab_widget.clear() # remove the tab(s) added in designer
self.tab_widget.tabBar().hide()
self.dummy_tab = ChatWidget(None, self.tab_widget)
self.dummy_tab.setDisabled(True)
self.tab_widget.addTab(self.dummy_tab, "Dummy")
self.tab_widget.setCurrentWidget(self.dummy_tab)
self.session_list.hide()
self.info_panel_files_button.hide()
self.info_panel_participants_button.hide()
self.participants_panel_files_button.hide()
self.new_messages_button.hide()
self.hold_button.hide()
self.record_button.hide()
......@@ -996,6 +993,15 @@ class ChatWindow(base_class, ui_class, ColorHelperMixin):
watched.event(event)
self.drawSessionWidgetIndicators()
return True
elif watched in (self.latency_graph, self.packet_loss_graph, self.traffic_graph):
if event_type == QEvent.Wheel and event.modifiers() == Qt.ControlModifier:
settings = BlinkSettings()
if event.delta() > 0 and settings.chat_window.session_info.graph_time_scale > GraphTimeScale.min_value:
settings.chat_window.session_info.graph_time_scale -= 1
settings.save()
elif event.delta() < 0 and settings.chat_window.session_info.graph_time_scale < GraphTimeScale.max_value:
settings.chat_window.session_info.graph_time_scale += 1
settings.save()
return False
def drawSessionWidgetIndicators(self):
......@@ -1065,9 +1071,33 @@ class ChatWindow(base_class, ui_class, ColorHelperMixin):
handler = getattr(self, '_NH_%s' % notification.name, Null)
handler(notification)
def _NH_SIPApplicationDidStart(self, notification): # this should not run in the gui thread -Dan
def _NH_SIPApplicationDidStart(self, notification):
notification.center.add_observer(self, name='CFGSettingsObjectDidChange')
blink_settings = BlinkSettings()
if blink_settings.chat_window.session_info.alternate_style:
title_role = 'alt-title'
value_role = 'alt-value'
else:
title_role = 'title'
value_role = 'value'
for label in (attr for name, attr in vars(self).iteritems() if name.endswith('_title_label') and attr.property('role') is not None):
label.setProperty('role', title_role)
for label in (attr for name, attr in vars(self).iteritems() if name.endswith('_value_label') or name.endswith('_value_widget') and attr.property('role') is not None):
label.setProperty('role', value_role)
self.info_panel_container_widget.setStyleSheet(self.info_panel_container_widget.styleSheet())
self.latency_graph.horizontalPixelsPerUnit = blink_settings.chat_window.session_info.graph_time_scale
self.packet_loss_graph.horizontalPixelsPerUnit = blink_settings.chat_window.session_info.graph_time_scale
self.traffic_graph.horizontalPixelsPerUnit = blink_settings.chat_window.session_info.graph_time_scale
self.latency_graph.update()
self.packet_loss_graph.update()
self.traffic_graph.update()
self.dummy_tab = ChatWidget(None, self.tab_widget)
self.dummy_tab.setDisabled(True)
self.tab_widget.addTab(self.dummy_tab, "Dummy")
self.tab_widget.setCurrentWidget(self.dummy_tab)
def _NH_CFGSettingsObjectDidChange(self, notification):
settings = SIPSimpleSettings()
blink_settings = BlinkSettings()
......@@ -1077,6 +1107,27 @@ class ChatWindow(base_class, ui_class, ColorHelperMixin):
elif notification.sender is blink_settings:
if 'presence.icon' in notification.data.modified:
QWebSettings.clearMemoryCaches()
if 'chat_window.session_info.alternate_style' in notification.data.modified:
if blink_settings.chat_window.session_info.alternate_style:
title_role = 'alt-title'
value_role = 'alt-value'
else:
title_role = 'title'
value_role = 'value'
for label in (attr for name, attr in vars(self).iteritems() if name.endswith('_title_label') and attr.property('role') is not None):
label.setProperty('role', title_role)
for label in (attr for name, attr in vars(self).iteritems() if name.endswith('_value_label') or name.endswith('_value_widget') and attr.property('role') is not None):
label.setProperty('role', value_role)
self.info_panel_container_widget.setStyleSheet(self.info_panel_container_widget.styleSheet())
if 'chat_window.session_info.bytes_per_second' in notification.data.modified:
self.traffic_graph.update()
if 'chat_window.session_info.graph_time_scale' in notification.data.modified:
self.latency_graph.horizontalPixelsPerUnit = blink_settings.chat_window.session_info.graph_time_scale
self.packet_loss_graph.horizontalPixelsPerUnit = blink_settings.chat_window.session_info.graph_time_scale
self.traffic_graph.horizontalPixelsPerUnit = blink_settings.chat_window.session_info.graph_time_scale
self.latency_graph.update()
self.packet_loss_graph.update()
self.traffic_graph.update()
def _NH_BlinkSessionNewIncoming(self, notification):
if 'chat' in notification.sender.streams.types:
......@@ -1263,8 +1314,11 @@ class ChatWindow(base_class, ui_class, ColorHelperMixin):
self.packet_loss_label.setText(u'Packet Loss: %.1f%%, max=%.1f%%' % (max(self.audio_packet_loss_graph.last_value, self.video_packet_loss_graph.last_value), self.packet_loss_graph.max_value))
def _SH_TrafficGraphUpdated(self):
#incoming_traffic = TrafficNormalizer.normalize(self.incoming_traffic_graph.last_value)
#outgoing_traffic = TrafficNormalizer.normalize(self.outgoing_traffic_graph.last_value)
blink_settings = BlinkSettings()
if blink_settings.chat_window.session_info.bytes_per_second:
incoming_traffic = TrafficNormalizer.normalize(self.incoming_traffic_graph.last_value)
outgoing_traffic = TrafficNormalizer.normalize(self.outgoing_traffic_graph.last_value)
else:
incoming_traffic = TrafficNormalizer.normalize(self.incoming_traffic_graph.last_value*8, bits_per_second=True)
outgoing_traffic = TrafficNormalizer.normalize(self.outgoing_traffic_graph.last_value*8, bits_per_second=True)
self.traffic_label.setText(u"""<p>Traffic: <span style="color: #d70000;">\u2193</span> %s <span style="color: #0064d7;">\u2191</span> %s</p>""" % (incoming_traffic, outgoing_traffic))
......
......@@ -3,7 +3,8 @@
"""Definitions for datatypes used in configuration extensions."""
__all__ = ['ApplicationDataPath', 'DefaultPath', 'SoundFile', 'CustomSoundFile', 'HTTPURL', 'FileURL', 'AuthorizationToken', 'InvalidToken', 'IconDescriptor', 'PresenceState', 'PresenceStateList']
__all__ = ['ApplicationDataPath', 'DefaultPath', 'SoundFile', 'CustomSoundFile', 'HTTPURL', 'FileURL', 'AuthorizationToken', 'InvalidToken',
'IconDescriptor', 'PresenceState', 'PresenceStateList', 'GraphTimeScale']
import os
import re
......@@ -223,3 +224,14 @@ class PresenceStateList(List):
type = PresenceState
class GraphTimeScale(int):
min_value = 2
max_value = 4
def __new__(cls, value):
value = int(value)
if not (cls.min_value <= value <= cls.max_value):
raise ValueError("expected an integer number between %d and %d, found %d" % (cls.min_value, cls.max_value, value))
return value
......@@ -14,7 +14,7 @@ from sipsimple.configuration.datatypes import AudioCodecList, NonNegativeInteger
from sipsimple.configuration.settings import AudioSettings, ChatSettings, EchoCancellerSettings, FileTransferSettings, LogsSettings, RTPSettings, TLSSettings
from blink import __version__
from blink.configuration.datatypes import ApplicationDataPath, AuthorizationToken, HTTPURL, IconDescriptor, SoundFile, PresenceState, PresenceStateList
from blink.configuration.datatypes import ApplicationDataPath, AuthorizationToken, GraphTimeScale, HTTPURL, IconDescriptor, SoundFile, PresenceState, PresenceStateList
from blink.resources import Resources
......@@ -98,6 +98,22 @@ class SIPSimpleSettingsExtension(SettingsObjectExtension):
user_agent = Setting(type=str, default='Blink %s (%s)' % (__version__, platform.system() if sys.platform!='darwin' else 'MacOSX Qt'))
class SessionInfoSettings(SettingsGroup):
alternate_style = Setting(type=bool, default=False)
bytes_per_second = Setting(type=bool, default=False)
graph_time_scale = Setting(type=GraphTimeScale, default=3)
class ChatWindowSettings(SettingsGroup):
session_info = SessionInfoSettings
style = Setting(type=str, default='Stockholm')
style_variant = Setting(type=str, default=None, nillable=True)
show_user_icons = Setting(type=bool, default=True)
font = Setting(type=str, default=None, nillable=True)
font_size = Setting(type=int, default=None, nillable=True)
class BlinkPresenceSettings(SettingsGroup):
current_state = Setting(type=PresenceState, default=PresenceState('Available'))
state_history = Setting(type=PresenceStateList, default=PresenceStateList())
......@@ -108,5 +124,6 @@ class BlinkPresenceSettings(SettingsGroup):
class BlinkSettings(SettingsObject):
__id__ = 'BlinkSettings'
chat_window = ChatWindowSettings
presence = BlinkPresenceSettings
......@@ -8,7 +8,7 @@ import urlparse
from PyQt4 import uic
from PyQt4.QtCore import Qt, QRegExp
from PyQt4.QtGui import QActionGroup, QButtonGroup, QFileDialog, QListView, QListWidgetItem, QMessageBox, QRegExpValidator, QSpinBox, QStyle, QStyleOptionComboBox, QValidator
from PyQt4.QtGui import QActionGroup, QButtonGroup, QFileDialog, QFont, QListView, QListWidgetItem, QMessageBox, QRegExpValidator, QSpinBox, QStyle, QStyleOptionComboBox, QValidator
from application import log
from application.notification import IObserver, NotificationCenter
......@@ -25,6 +25,9 @@ from sipsimple.configuration.settings import SIPSimpleSettings
from sipsimple.threading import run_in_thread
from blink.accounts import AddAccountDialog
from blink.chatwindow import ChatMessageStyle, ChatStyleError, ChatMessage, ChatEvent, ChatSender
from blink.configuration.datatypes import FileURL
from blink.configuration.settings import BlinkSettings
from blink.resources import ApplicationData, Resources
from blink.logging import LogManager
from blink.util import QSingleton, call_in_gui_thread, run_in_gui_thread
......@@ -257,8 +260,23 @@ class PreferencesWindow(base_class, ui_class):
self.max_recording.valueChanged[int].connect(self._SH_MaxRecordingValueChanged)
# Chat and SMS
self.style_view.sizeChanged.connect(self._SH_StyleViewSizeChanged)
self.style_view.page().mainFrame().contentsSizeChanged.connect(self._SH_StyleViewFrameContentsSizeChanged)
self.style_button.activated[int].connect(self._SH_StyleButtonActivated)
self.style_variant_button.activated[str].connect(self._SH_StyleVariantButtonActivated)
self.style_show_icons_button.clicked.connect(self._SH_StyleShowIconsButtonClicked)
self.style_font_button.currentIndexChanged[str].connect(self._SH_StyleFontButtonCurrentIndexChanged)
self.style_font_size.valueChanged[int].connect(self._SH_StyleFontSizeValueChanged)
self.style_default_font_button.clicked.connect(self._SH_StyleDefaultFontButtonClicked)
self.auto_accept_chat_button.clicked.connect(self._SH_AutoAcceptChatButtonClicked)
self.sms_replication_button.clicked.connect(self._SH_SMSReplicationButtonClicked)
self.chat_message_alert_button.clicked.connect(self._SH_ChatMessageAlertButtonClicked)
self.session_info_style_button.clicked.connect(self._SH_SessionInfoStyleButtonClicked)
self.traffic_units_button.clicked.connect(self._SH_TrafficUnitsButtonClicked)
# File transfer
self.download_directory_editor.locationCleared.connect(self._SH_DownloadDirectoryEditorLocationCleared)
......@@ -266,7 +284,6 @@ class PreferencesWindow(base_class, ui_class):
# Alerts
self.silence_alerts_button.clicked.connect(self._SH_SilenceAlertsButtonClicked)
self.message_alerts_button.clicked.connect(self._SH_MessageAlertsButtonClicked)
self.file_alerts_button.clicked.connect(self._SH_FileAlertsButtonClicked)
# File logging
......@@ -305,8 +322,23 @@ class PreferencesWindow(base_class, ui_class):
self.tail_length_slider.hide()
self.tail_length_value_label.hide()
# Hide the answering machine section for now as it's not implemented -Dan
# Hide the controls for the features that are not yet implemented -Dan
self.answering_machine_group_box.hide()
self.sms_replication_button.hide()
self.style_view.template = open(Resources.get('chat/template.html')).read()
self.style_button.clear()
self.style_variant_button.clear()
styles_path = Resources.get('chat/styles')
for style_name in os.listdir(styles_path):
try:
style = ChatMessageStyle(style_name)
except ChatStyleError:
pass
else:
self.style_button.addItem(style_name, style)
self.section_group = QActionGroup(self)
self.section_group.setExclusive(True)
......@@ -495,6 +527,7 @@ class PreferencesWindow(base_class, ui_class):
def load_settings(self):
"""Load settings from configuration into the UI controls"""
settings = SIPSimpleSettings()
blink_settings = BlinkSettings()
# Audio devices
self.load_audio_devices()
......@@ -522,15 +555,44 @@ class PreferencesWindow(base_class, ui_class):
# TODO: load unavailable message -Dan
# Chat and SMS settings
style_index = self.style_button.findText(blink_settings.chat_window.style)
if style_index == -1:
style_index = 0
blink_settings.chat_window.style = self.style_button.itemText(style_index)
blink_settings.chat_window.style_variant = None
blink_settings.save()
style = self.style_button.itemData(style_index)
self.style_button.setCurrentIndex(style_index)
self.style_variant_button.clear()
for variant in style.variants:
self.style_variant_button.addItem(variant)
variant_index = self.style_variant_button.findText(blink_settings.chat_window.style_variant or style.default_variant)
if variant_index == -1:
variant_index = self.style_variant_button.findText(style.default_variant)
blink_settings.chat_window.style_variant = None
blink_settings.save()
self.style_variant_button.setCurrentIndex(variant_index)
self.style_show_icons_button.setChecked(blink_settings.chat_window.show_user_icons)
self.update_chat_preview()
with blocked_qt_signals(self.style_font_button):
self.style_font_button.setCurrentFont(QFont(blink_settings.chat_window.font or style.font_family))
with blocked_qt_signals(self.style_font_size):
self.style_font_size.setValue(blink_settings.chat_window.font_size or style.font_size)
self.style_default_font_button.setEnabled(blink_settings.chat_window.font is not None or blink_settings.chat_window.font_size is not None)
self.auto_accept_chat_button.setChecked(settings.chat.auto_accept)
self.sms_replication_button.setChecked(settings.chat.sms_replication)
self.chat_message_alert_button.setChecked(settings.sounds.play_message_alerts)
self.session_info_style_button.setChecked(blink_settings.chat_window.session_info.alternate_style)
self.traffic_units_button.setChecked(blink_settings.chat_window.session_info.bytes_per_second)
# File transfer settings
self.download_directory_editor.setText(settings.file_transfer.directory or u'')
# Alert settings
self.silence_alerts_button.setChecked(settings.audio.silent)
self.message_alerts_button.setChecked(settings.sounds.play_message_alerts)
self.file_alerts_button.setChecked(settings.sounds.play_file_alerts)
# File logging settings
......@@ -658,6 +720,45 @@ class PreferencesWindow(base_class, ui_class):
self.account_tls_cert_file_editor.setText(account.tls.certificate or u'')
self.account_tls_verify_server_button.setChecked(account.tls.verify_server)
def update_chat_preview(self):
blink_settings = BlinkSettings()
style = self.style_button.itemData(self.style_button.currentIndex())
style_variant = self.style_variant_button.itemText(self.style_variant_button.currentIndex())
user_icons = 'show-icons' if blink_settings.chat_window.show_user_icons else 'hide-icons'
self.style_view.setChatFont(blink_settings.chat_window.font or style.font_family, blink_settings.chat_window.font_size or style.font_size)
self.style_view.setHtml(self.style_view.template.format(base_url=FileURL(style.path)+'/', style_url=style_variant+'.style'))
chat_element = self.style_view.page().mainFrame().findFirstElement('#chat')
chat_element.last_message = None
def add_message(message):
insertion_point = chat_element.findFirst('#insert')
if message.is_related_to(chat_element.last_message):
message.consecutive = True
insertion_point.replace(message.to_html(style, user_icons=user_icons))
else:
insertion_point.removeFromDocument()
chat_element.appendInside(message.to_html(style, user_icons=user_icons))
chat_element.last_message = message
ruby = ChatSender("Ruby", 'ruby@example.com', Resources.get('icons/avatar-ruby.png'))
nate = ChatSender("Nate", 'nate@example.net', Resources.get('icons/avatar-nate.png'))
messages = [ChatMessage("Andrew stepped into the room cautiously. The air was stale as if the place has not been visited in years and he had an acute feeling of being watched. "
"Was this the place he was looking for, the place holding the answers he looked for so long? He was hopeful but felt uneasy about it.", ruby, 'incoming'),
ChatMessage("Hey Ruby. Is this from the new book you're working on? Looks like it will be another interesting story to read :)", nate, 'outgoing'),
ChatMessage("Yeah. But I'm kind of lacking inspiration right now and the book needs to be finished in a month :(", ruby, 'incoming'),
ChatMessage("I think you put too much pressure on yourself. What about we get out for a bit? Watch a movie, chat about everyday events for a bit...", nate, 'outgoing'),
ChatMessage("It could help you take your mind off of things and relax. We can meet at the usual spot in an hour if you want.", nate, 'outgoing'),
ChatMessage("You may be right. Maybe that's what I need indeed. See you there.", ruby, 'incoming'),
ChatEvent("Ruby has left the conversation")]
for message in messages:
add_message(message)
del chat_element.last_message
def show(self):
selection_model = self.account_list.selectionModel()
if not selection_model.selectedIndexes():
......@@ -718,6 +819,21 @@ class PreferencesWindow(base_class, ui_class):
idd_prefix = self.idd_prefix_button.currentText()
self.pstn_example_transformed_label.setText(u"%s%s442079460000" % ('' if prefix=='None' else prefix, idd_prefix))
def _align_style_preview(self, scroll=False):
chat_element = self.style_view.page().mainFrame().findFirstElement('#chat')
widget_height = self.style_view.size().height()
content_height = chat_element.geometry().height()
if widget_height > content_height:
chat_element.setStyleProperty('position', 'relative')
chat_element.setStyleProperty('top', '%dpx' % (widget_height-content_height))
else:
chat_element.setStyleProperty('position', 'static')
chat_element.setStyleProperty('top', None)
frame = self.style_view.page().mainFrame()
if scroll or frame.scrollBarMaximum(Qt.Vertical) - frame.scrollBarValue(Qt.Vertical) <= widget_height*0.2:
frame = self.style_view.page().mainFrame()
frame.setScrollBarValue(Qt.Vertical, frame.scrollBarMaximum(Qt.Vertical))
# Signal handlers
#
def _SH_ToolbarActionTriggered(self, action):
......@@ -1098,6 +1214,58 @@ class PreferencesWindow(base_class, ui_class):
settings.save()
# Chat and SMS signal handlers
def _SH_StyleViewSizeChanged(self):
self._align_style_preview(scroll=True)
def _SH_StyleViewFrameContentsSizeChanged(self, size):
self._align_style_preview(scroll=True)
def _SH_StyleButtonActivated(self, index):
style = self.style_button.itemData(index)
settings = BlinkSettings()
if style.name != settings.chat_window.style:
self.style_variant_button.clear()
for variant in style.variants:
self.style_variant_button.addItem(variant)
self.style_variant_button.setCurrentIndex(self.style_variant_button.findText(style.default_variant))
settings.chat_window.style = style.name
settings.chat_window.style_variant = None
settings.save()
def _SH_StyleVariantButtonActivated(self, style_variant):
style = self.style_button.itemData(self.style_button.currentIndex())
settings = BlinkSettings()
current_variant = settings.chat_window.style_variant or style.default_variant
if style_variant != current_variant:
settings.chat_window.style_variant = style_variant
settings.save()
def _SH_StyleShowIconsButtonClicked(self, checked):
settings = BlinkSettings()
settings.chat_window.show_user_icons = checked
settings.save()
def _SH_StyleFontButtonCurrentIndexChanged(self, font):
settings = BlinkSettings()
settings.chat_window.font = font
settings.save()
def _SH_StyleFontSizeValueChanged(self, size):
settings = BlinkSettings()
settings.chat_window.font_size = size
settings.save()
def _SH_StyleDefaultFontButtonClicked(self, checked):
settings = BlinkSettings()
settings.chat_window.font = DefaultValue
settings.chat_window.font_size = DefaultValue
settings.save()
style = self.style_button.itemData(self.style_button.currentIndex())
with blocked_qt_signals(self.style_font_button):
self.style_font_button.setCurrentFont(QFont(style.font_family))
with blocked_qt_signals(self.style_font_size):
self.style_font_size.setValue(style.font_size)
def _SH_AutoAcceptChatButtonClicked(self, checked):
settings = SIPSimpleSettings()
settings.chat.auto_accept = checked
......@@ -1108,6 +1276,21 @@ class PreferencesWindow(base_class, ui_class):
settings.chat.sms_replication = checked
settings.save()
def _SH_ChatMessageAlertButtonClicked(self, checked):
settings = SIPSimpleSettings()
settings.sounds.play_message_alerts = checked
settings.save()
def _SH_SessionInfoStyleButtonClicked(self, checked):
settings = BlinkSettings()
settings.chat_window.session_info.alternate_style = checked
settings.save()
def _SH_TrafficUnitsButtonClicked(self, checked):
settings = BlinkSettings()
settings.chat_window.session_info.bytes_per_second = checked
settings.save()
# File transfer signal handlers
def _SH_DownloadDirectoryEditorLocationCleared(self):
settings = SIPSimpleSettings()
......@@ -1132,11 +1315,6 @@ class PreferencesWindow(base_class, ui_class):
settings.audio.silent = checked
settings.save()
def _SH_MessageAlertsButtonClicked(self, checked):
settings = SIPSimpleSettings()
settings.sounds.play_message_alerts = checked
settings.save()
def _SH_FileAlertsButtonClicked(self, checked):
settings = SIPSimpleSettings()
settings.sounds.play_file_alerts = checked
......@@ -1299,7 +1477,14 @@ class PreferencesWindow(base_class, ui_class):
def _NH_CFGSettingsObjectDidChange(self, notification):
settings = SIPSimpleSettings()
if notification.sender is settings:
blink_settings = BlinkSettings()
if notification.sender is blink_settings:
if {'chat_window.style', 'chat_window.style_variant', 'chat_window.show_user_icons'}.intersection(notification.data.modified):
self.update_chat_preview()
if {'chat_window.font', 'chat_window.font_size'}.intersection(notification.data.modified):
self.update_chat_preview()
self.style_default_font_button.setEnabled(blink_settings.chat_window.font is not None or blink_settings.chat_window.font_size is not None)
elif notification.sender is settings:
if 'audio.silent' in notification.data.modified:
self.silence_alerts_button.setChecked(settings.audio.silent)
if 'audio.alert_device' in notification.data.modified:
......
......@@ -31,7 +31,7 @@
<item row="0" column="0">
<widget class="QStackedWidget" name="pages">
<property name="currentIndex">
<number>0</number>
<number>2</number>
</property>
<widget class="QWidget" name="accounts_page">
<layout class="QGridLayout" name="accounts_layout">
......@@ -1908,16 +1908,152 @@
</layout>
</widget>
<widget class="QWidget" name="chat_page">
<layout class="QVBoxLayout" name="chat_layout">
<layout class="QGridLayout" name="chat_layout" rowstretch="1,0" rowminimumheight="0,150">
<property name="margin">
<number>0</number>
</property>
<item row="0" column="0" colspan="2">
<widget class="QGroupBox" name="messages_group_box">
<property name="title">
<string>Messages</string>
</property>
<layout class="QGridLayout" name="messages_layout">
<item row="1" column="1">
<widget class="QComboBox" name="style_button">
<item>
<widget class="QGroupBox" name="chat_group_box">
<property name="text">
<string>Smooth Operator</string>
</property>
</item>
<item>
<property name="text">
<string>Stockholm</string>
</property>
</item>
</widget>
</item>
<item row="1" column="3">
<spacer name="messages_spacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Expanding</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="2" column="1">
<widget class="QComboBox" name="style_variant_button">
<property name="maxVisibleItems">
<number>20</number>
</property>
<item>
<property name="text">
<string>Blue - Grey</string>
</property>
</item>
</widget>
</item>
<item row="1" column="6">
<widget class="QSpinBox" name="style_font_size">
<property name="correctionMode">
<enum>QAbstractSpinBox::CorrectToNearestValue</enum>
</property>
<property name="suffix">
<string> px</string>
</property>
<property name="minimum">
<number>9</number>
</property>
<property name="maximum">
<number>20</number>
</property>
<property name="value">
<number>11</number>
</property>
</widget>
</item>
<item row="1" column="5">
<widget class="QFontComboBox" name="style_font_button"/>
</item>
<item row="1" column="0">
<widget class="QLabel" name="style_label">
<property name="text">
<string>Style:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="0" column="0" colspan="8">
<widget class="ChatWebView" name="style_view">
<property name="url">
<url>
<string>about:blank</string>
</url>
</property>
</widget>
</item>
<item row="1" column="7">
<widget class="QPushButton" name="style_default_font_button">
<property name="text">
<string>Default</string>
</property>
</widget>
</item>
<item row="1" column="4">
<widget class="QLabel" name="style_font_label">
<property name="text">
<string>Font:</string>
</property>
</widget>
</item>
<item row="2" column="3" colspan="5">
<widget class="QLabel" name="style_note_label">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Style changes take effect for new sessions</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QCheckBox" name="style_show_icons_button">
<property name="text">
<string>Show user icons</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="style_variant_label">
<property name="text">
<string>Variant:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="1" column="0">
<widget class="QGroupBox" name="chat_sessions_group_box">
<property name="title">
<string>Chat and SMS Settings</string>
<string>Chat Sessions</string>
</property>
<layout class="QVBoxLayout" name="chat_group_box_layout">
<layout class="QVBoxLayout" name="chat_sessions_group_box_layout">
<item>
<widget class="QCheckBox" name="auto_accept_chat_button">
<property name="text">
......@@ -1933,14 +2069,57 @@
</widget>
</item>
<item>
<spacer name="chat_spacer">
<widget class="QCheckBox" name="chat_message_alert_button">
<property name="text">
<string>Play a sound when a chat message is received</string>
</property>
</widget>
</item>
<item>
<spacer name="chat_sessions_spacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
<item row="1" column="1">
<widget class="QGroupBox" name="chat_window_group_box">
<property name="title">
<string>Chat Window</string>
</property>
<layout class="QVBoxLayout" name="chat_window_group_box_layout">
<item>
<widget class="QCheckBox" name="session_info_style_button">
<property name="text">
<string>Use alternate style for the session information panel</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="traffic_units_button">
<property name="text">
<string>Show traffic in bytes per second</string>
</property>
</widget>
</item>
<item>
<spacer name="chat_window_spacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>20</height>
</size>
</property>
</spacer>
......@@ -2017,28 +2196,7 @@
<string>Alert Settings</string>
</property>
<layout class="QGridLayout" name="alerts_group_box_layout">
<item row="0" column="0">
<widget class="QCheckBox" name="silence_alerts_button">
<property name="text">
<string>Silence all alerts (incoming ringtones, text message notifications and file transfer notifications)</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QCheckBox" name="message_alerts_button">
<property name="text">
<string>Play a sound when a chat or SMS message is sent or received</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QCheckBox" name="file_alerts_button">
<property name="text">
<string>Play a sound when a file transfer finishes</string>
</property>
</widget>
</item>
<item row="3" column="0">
<spacer name="alerts_spacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
......@@ -2051,6 +2209,20 @@
</property>
</spacer>
</item>
<item row="1" column="0">
<widget class="QCheckBox" name="file_alerts_button">
<property name="text">
<string>Play a sound when a file transfer finishes</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QCheckBox" name="silence_alerts_button">
<property name="text">
<string>Silence all alerts (incoming ringtones, text message notifications and file transfer notifications)</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
......@@ -2740,6 +2912,16 @@
</action>
</widget>
<customwidgets>
<customwidget>
<class>QWebView</class>
<extends>QWidget</extends>
<header>QtWebKit/QWebView</header>
</customwidget>
<customwidget>
<class>ChatWebView</class>
<extends>QWebView</extends>
<header>blink.chatwindow</header>
</customwidget>
<customwidget>
<class>LineEdit</class>
<extends>QLineEdit</extends>
......@@ -2770,12 +2952,12 @@
<slot>setNum(int)</slot>
<hints>
<hint type="sourcelabel">
<x>228</x>
<y>229</y>
<x>147</x>
<y>245</y>
</hint>
<hint type="destinationlabel">
<x>364</x>
<y>238</y>
<x>382</x>
<y>245</y>
</hint>
</hints>
</connection>
......
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