Commit 50f0b68b authored by Adrian Georgescu's avatar Adrian Georgescu

2to3 run

parent 77035393
#!/usr/bin/python2 #!/usr/bin/python3
import os import os
import sys import sys
......
...@@ -88,9 +88,7 @@ class IPAddressMonitor(object): ...@@ -88,9 +88,7 @@ class IPAddressMonitor(object):
self.greenlet = None self.greenlet = None
class Blink(QApplication): class Blink(QApplication, metaclass=QSingleton):
__metaclass__ = QSingleton
implements(IObserver) implements(IObserver)
def __init__(self): def __init__(self):
...@@ -214,6 +212,6 @@ class Blink(QApplication): ...@@ -214,6 +212,6 @@ class Blink(QApplication):
@run_in_gui_thread @run_in_gui_thread
def _NH_SIPApplicationGotFatalError(self, notification): def _NH_SIPApplicationGotFatalError(self, notification):
log.error('Fatal error:\n{}'.format(notification.data.traceback)) log.error('Fatal error:\n{}'.format(notification.data.traceback))
QMessageBox.critical(self.main_window, u"Fatal Error", u"A fatal error occurred, {} will now exit.".format(self.applicationName())) QMessageBox.critical(self.main_window, "Fatal Error", "A fatal error occurred, {} will now exit.".format(self.applicationName()))
sys.exit(1) sys.exit(1)
...@@ -34,16 +34,14 @@ credits_text = """ ...@@ -34,16 +34,14 @@ credits_text = """
ui_class, base_class = uic.loadUiType(Resources.get('about_panel.ui')) ui_class, base_class = uic.loadUiType(Resources.get('about_panel.ui'))
class AboutPanel(base_class, ui_class): class AboutPanel(base_class, ui_class, metaclass=QSingleton):
__metaclass__ = QSingleton
def __init__(self, parent=None): def __init__(self, parent=None):
super(AboutPanel, self).__init__(parent) super(AboutPanel, self).__init__(parent)
with Resources.directory: with Resources.directory:
self.setupUi(self) self.setupUi(self)
self.version.setText(u'Version %s\n%s' % (__version__, __date__)) self.version.setText('Version %s\n%s' % (__version__, __date__))
credits_width = self.credits_text.fontMetrics().width("NLnet Foundation" + "http://sipsimpleclient.org") + 40 credits_width = self.credits_text.fontMetrics().width("NLnet Foundation" + "http://sipsimpleclient.org") + 40
self.credits_text.setFixedWidth(credits_width) self.credits_text.setFixedWidth(credits_width)
......
...@@ -3,8 +3,8 @@ import cjson ...@@ -3,8 +3,8 @@ import cjson
import os import os
import re import re
import sys import sys
import urllib import urllib.request, urllib.parse, urllib.error
import urllib2 import urllib.request, urllib.error, urllib.parse
from PyQt5 import uic from PyQt5 import uic
from PyQt5.QtCore import Qt, QAbstractListModel, QModelIndex, QSortFilterProxyModel, QUrl, QUrlQuery from PyQt5.QtCore import Qt, QAbstractListModel, QModelIndex, QSortFilterProxyModel, QUrl, QUrlQuery
...@@ -68,7 +68,7 @@ class AccountInfo(object): ...@@ -68,7 +68,7 @@ class AccountInfo(object):
@property @property
def name(self): def name(self):
return u'Bonjour' if self.account is BonjourAccount() else unicode(self.account.id) return 'Bonjour' if self.account is BonjourAccount() else str(self.account.id)
@property @property
def icon(self): def icon(self):
...@@ -80,7 +80,7 @@ class AccountInfo(object): ...@@ -80,7 +80,7 @@ class AccountInfo(object):
return self.inactive_icon return self.inactive_icon
def __eq__(self, other): def __eq__(self, other):
if isinstance(other, basestring): if isinstance(other, str):
return self.name == other return self.name == other
elif isinstance(other, (Account, BonjourAccount)): elif isinstance(other, (Account, BonjourAccount)):
return self.account == other return self.account == other
...@@ -234,9 +234,7 @@ class AccountSelector(QComboBox): ...@@ -234,9 +234,7 @@ class AccountSelector(QComboBox):
ui_class, base_class = uic.loadUiType(Resources.get('add_account.ui')) ui_class, base_class = uic.loadUiType(Resources.get('add_account.ui'))
class AddAccountDialog(base_class, ui_class): class AddAccountDialog(base_class, ui_class, metaclass=QSingleton):
__metaclass__ = QSingleton
implements(IObserver) implements(IObserver)
def __init__(self, parent=None): def __init__(self, parent=None):
...@@ -256,7 +254,7 @@ class AddAccountDialog(base_class, ui_class): ...@@ -256,7 +254,7 @@ class AddAccountDialog(base_class, ui_class):
font_metrics = self.create_status_label.fontMetrics() font_metrics = self.create_status_label.fontMetrics()
self.create_status_label.setMinimumHeight(font_metrics.height() + 2*(font_metrics.height() + font_metrics.leading())) # reserve space for 3 lines self.create_status_label.setMinimumHeight(font_metrics.height() + 2*(font_metrics.height() + font_metrics.leading())) # reserve space for 3 lines
font_metrics = self.email_note_label.fontMetrics() font_metrics = self.email_note_label.fontMetrics()
self.email_note_label.setMinimumWidth(font_metrics.width(u'The E-mail address is used when sending voicemail')) # hack to make text justification look nice everywhere self.email_note_label.setMinimumWidth(font_metrics.width('The E-mail address is used when sending voicemail')) # hack to make text justification look nice everywhere
self.add_account_button.setChecked(True) self.add_account_button.setChecked(True)
self.panel_view.setCurrentWidget(self.add_account_panel) self.panel_view.setCurrentWidget(self.add_account_panel)
self.new_password_editor.textChanged.connect(self._SH_PasswordTextChanged) self.new_password_editor.textChanged.connect(self._SH_PasswordTextChanged)
...@@ -362,7 +360,7 @@ class AddAccountDialog(base_class, ui_class): ...@@ -362,7 +360,7 @@ class AddAccountDialog(base_class, ui_class):
self.accept_button.setEnabled(all(input.text_valid for input in inputs)) self.accept_button.setEnabled(all(input.text_valid for input in inputs))
def _SH_PasswordTextChanged(self, text): def _SH_PasswordTextChanged(self, text):
self.verify_password_editor.regexp = re.compile(u'^%s$' % re.escape(text)) self.verify_password_editor.regexp = re.compile('^%s$' % re.escape(text))
def _SH_ValidityStatusChanged(self): def _SH_ValidityStatusChanged(self):
red = '#cc0000' red = '#cc0000'
...@@ -401,11 +399,11 @@ class AddAccountDialog(base_class, ui_class): ...@@ -401,11 +399,11 @@ class AddAccountDialog(base_class, ui_class):
def _initialize(self): def _initialize(self):
self.display_name = user_info.fullname self.display_name = user_info.fullname
self.username = user_info.username.lower().replace(u' ', u'.') self.username = user_info.username.lower().replace(' ', '.')
self.sip_address = u'' self.sip_address = ''
self.password = u'' self.password = ''
self.verify_password = u'' self.verify_password = ''
self.email_address = u'' self.email_address = ''
@run_in_thread('network-io') @run_in_thread('network-io')
def _create_sip_account(self, username, password, email_address, display_name, timezone=None): def _create_sip_account(self, username, password, email_address, display_name, timezone=None):
...@@ -425,7 +423,7 @@ class AddAccountDialog(base_class, ui_class): ...@@ -425,7 +423,7 @@ class AddAccountDialog(base_class, ui_class):
tzinfo=timezone) tzinfo=timezone)
try: try:
settings = SIPSimpleSettings() settings = SIPSimpleSettings()
response = urllib2.urlopen(settings.server.enrollment_url, urllib.urlencode(dict(enrollment_data))) response = urllib.request.urlopen(settings.server.enrollment_url, urllib.parse.urlencode(dict(enrollment_data)))
response_data = cjson.decode(response.read().replace(r'\/', '/')) response_data = cjson.decode(response.read().replace(r'\/', '/'))
response_data = defaultdict(lambda: None, response_data) response_data = defaultdict(lambda: None, response_data)
if response_data['success']: if response_data['success']:
...@@ -460,7 +458,7 @@ class AddAccountDialog(base_class, ui_class): ...@@ -460,7 +458,7 @@ class AddAccountDialog(base_class, ui_class):
call_in_gui_thread(setattr, self.create_status_label, 'value', Status(response_data['error_message'], color=red)) call_in_gui_thread(setattr, self.create_status_label, 'value', Status(response_data['error_message'], color=red))
except (cjson.DecodeError, KeyError): except (cjson.DecodeError, KeyError):
call_in_gui_thread(setattr, self.create_status_label, 'value', Status('Illegal server response', color=red)) call_in_gui_thread(setattr, self.create_status_label, 'value', Status('Illegal server response', color=red))
except urllib2.URLError, e: except urllib.error.URLError as e:
call_in_gui_thread(setattr, self.create_status_label, 'value', Status('Failed to contact server: %s' % e.reason, color=red)) call_in_gui_thread(setattr, self.create_status_label, 'value', Status('Failed to contact server: %s' % e.reason, color=red))
finally: finally:
call_in_gui_thread(self.setEnabled, True) call_in_gui_thread(self.setEnabled, True)
...@@ -476,7 +474,7 @@ class AddAccountDialog(base_class, ui_class): ...@@ -476,7 +474,7 @@ class AddAccountDialog(base_class, ui_class):
makedirs(ApplicationData.get('tls')) makedirs(ApplicationData.get('tls'))
certificate_path = ApplicationData.get(os.path.join('tls', sip_address+'.crt')) certificate_path = ApplicationData.get(os.path.join('tls', sip_address+'.crt'))
certificate_file = open(certificate_path, 'w') certificate_file = open(certificate_path, 'w')
os.chmod(certificate_path, 0600) os.chmod(certificate_path, 0o600)
certificate_file.write(crt+key) certificate_file.write(crt+key)
certificate_file.close() certificate_file.close()
ca_path = ApplicationData.get(os.path.join('tls', 'ca.crt')) ca_path = ApplicationData.get(os.path.join('tls', 'ca.crt'))
...@@ -585,7 +583,7 @@ class ServerToolsWebView(QWebView): ...@@ -585,7 +583,7 @@ class ServerToolsWebView(QWebView):
@property @property
def query_items(self): def query_items(self):
all_items = ('user_agent', 'tab', 'task', 'realm') all_items = ('user_agent', 'tab', 'task', 'realm')
return [(name, value) for name, value in self.__dict__.iteritems() if name in all_items and value is not None] return [(name, value) for name, value in self.__dict__.items() if name in all_items and value is not None]
def _get_account(self): def _get_account(self):
return self.__dict__['account'] return self.__dict__['account']
...@@ -670,9 +668,7 @@ class ServerToolsWebView(QWebView): ...@@ -670,9 +668,7 @@ class ServerToolsWebView(QWebView):
ui_class, base_class = uic.loadUiType(Resources.get('server_tools.ui')) ui_class, base_class = uic.loadUiType(Resources.get('server_tools.ui'))
class ServerToolsWindow(base_class, ui_class): class ServerToolsWindow(base_class, ui_class, metaclass=QSingleton):
__metaclass__ = QSingleton
implements(IObserver) implements(IObserver)
def __init__(self, model, parent=None): def __init__(self, model, parent=None):
...@@ -755,12 +751,12 @@ class ServerToolsWindow(base_class, ui_class): ...@@ -755,12 +751,12 @@ class ServerToolsWindow(base_class, ui_class):
self._update_navigation_buttons() self._update_navigation_buttons()
def _SH_WebViewTitleChanged(self, title): def _SH_WebViewTitleChanged(self, title):
self.window().setWindowTitle(u'Blink Server Tools: {}'.format(title)) self.window().setWindowTitle('Blink Server Tools: {}'.format(title))
def _SH_ModelChanged(self, parent_index, start, end): def _SH_ModelChanged(self, parent_index, start, end):
menu = self.account_button.menu() menu = self.account_button.menu()
menu.clear() menu.clear()
for row in xrange(self.model.rowCount()): for row in range(self.model.rowCount()):
account_info = self.model.data(self.model.index(row, 0), Qt.UserRole) account_info = self.model.data(self.model.index(row, 0), Qt.UserRole)
action = menu.addAction(account_info.name) action = menu.addAction(account_info.name)
action.setData(account_info.account) action.setData(account_info.account)
......
from __future__ import division
import locale import locale
import os import os
...@@ -116,7 +116,7 @@ class OrderedSet(MutableSet): ...@@ -116,7 +116,7 @@ class OrderedSet(MutableSet):
def __init__(self, iterable=None): def __init__(self, iterable=None):
self.__hardroot = Link() # sentinel node for doubly linked list self.__hardroot = Link() # sentinel node for doubly linked list
self.__root = root = proxy(self.__hardroot) self.__root = root = proxy(self.__hardroot)
root.prev = root.next = root root.prev = root.__next__ = root
self.__map = {} self.__map = {}
if iterable is not None: if iterable is not None:
self |= iterable self |= iterable
...@@ -129,10 +129,10 @@ class OrderedSet(MutableSet): ...@@ -129,10 +129,10 @@ class OrderedSet(MutableSet):
def __iter__(self): def __iter__(self):
root = self.__root root = self.__root
curr = root.next curr = root.__next__
while curr is not root: while curr is not root:
yield curr.key yield curr.key
curr = curr.next curr = curr.__next__
def __reversed__(self): def __reversed__(self):
root = self.__root root = self.__root
...@@ -157,13 +157,13 @@ class OrderedSet(MutableSet): ...@@ -157,13 +157,13 @@ class OrderedSet(MutableSet):
if key in self.__map: if key in self.__map:
link = self.__map.pop(key) link = self.__map.pop(key)
link_prev = link.prev link_prev = link.prev
link_next = link.next link_next = link.__next__
link_prev.next = link_next link_prev.next = link_next
link_next.prev = link_prev link_next.prev = link_prev
def clear(self): def clear(self):
root = self.__root root = self.__root
root.prev = root.next = root root.prev = root.__next__ = root
self.__map.clear() self.__map.clear()
...@@ -188,7 +188,7 @@ class ChatContentBooleanOption(object): ...@@ -188,7 +188,7 @@ class ChatContentBooleanOption(object):
raise AttributeError('attribute cannot be deleted') raise AttributeError('attribute cannot be deleted')
class AnyValue: __metaclass__ = MarkerType class AnyValue(metaclass=MarkerType): pass
class ChatContentStringAttribute(object): class ChatContentStringAttribute(object):
...@@ -219,9 +219,7 @@ class ChatContentStringAttribute(object): ...@@ -219,9 +219,7 @@ class ChatContentStringAttribute(object):
raise AttributeError('attribute cannot be deleted') raise AttributeError('attribute cannot be deleted')
class ChatContent(object): class ChatContent(object, metaclass=ABCMeta):
__metaclass__ = ABCMeta
__cssclasses__ = () __cssclasses__ = ()
continuation_interval = timedelta(0, 5*60) # 5 minutes continuation_interval = timedelta(0, 5*60) # 5 minutes
...@@ -371,7 +369,7 @@ class ChatWebView(QWebView): ...@@ -371,7 +369,7 @@ class ChatWebView(QWebView):
menu.exec_(event.globalPos()) menu.exec_(event.globalPos())
def createWindow(self, window_type): def createWindow(self, window_type):
print "create window of type", window_type print("create window of type", window_type)
return None return None
def dragEnterEvent(self, event): def dragEnterEvent(self, event):
...@@ -409,20 +407,18 @@ class ChatInputLock(base_class, ui_class): ...@@ -409,20 +407,18 @@ class ChatInputLock(base_class, ui_class):
painter.drawPrimitive(QStyle.PE_Widget, option) painter.drawPrimitive(QStyle.PE_Widget, option)
class LockType(object): class LockType(object, metaclass=MarkerType):
__metaclass__ = MarkerType
note_text = None note_text = None
button_text = None button_text = None
class EncryptionLock(LockType): class EncryptionLock(LockType):
note_text = u'Encryption has been terminated by the other party' note_text = 'Encryption has been terminated by the other party'
button_text = u'Confirm' button_text = 'Confirm'
class ChatTextInput(QTextEdit): class ChatTextInput(QTextEdit):
textEntered = pyqtSignal(unicode) textEntered = pyqtSignal(str)
lockEngaged = pyqtSignal(object) lockEngaged = pyqtSignal(object)
lockReleased = pyqtSignal(object) lockReleased = pyqtSignal(object)
...@@ -710,8 +706,8 @@ class ChatWidget(base_class, ui_class): ...@@ -710,8 +706,8 @@ class ChatWidget(base_class, ui_class):
def _print_scrollbar_position(self): def _print_scrollbar_position(self):
frame = self.chat_view.page().mainFrame() frame = self.chat_view.page().mainFrame()
print "%d out of %d, %d+%d=%d (%d)" % (frame.scrollBarValue(Qt.Vertical), frame.scrollBarMaximum(Qt.Vertical), frame.scrollBarValue(Qt.Vertical), self.chat_view.size().height(), print("%d out of %d, %d+%d=%d (%d)" % (frame.scrollBarValue(Qt.Vertical), frame.scrollBarMaximum(Qt.Vertical), frame.scrollBarValue(Qt.Vertical), self.chat_view.size().height(),
frame.scrollBarValue(Qt.Vertical)+self.chat_view.size().height(), frame.contentsSize().height()) frame.scrollBarValue(Qt.Vertical)+self.chat_view.size().height(), frame.contentsSize().height()))
def dragEnterEvent(self, event): def dragEnterEvent(self, event):
mime_data = event.mimeData() mime_data = event.mimeData()
...@@ -742,7 +738,7 @@ class ChatWidget(base_class, ui_class): ...@@ -742,7 +738,7 @@ class ChatWidget(base_class, ui_class):
else: else:
mime_types = set(mime_data.formats()) mime_types = set(mime_data.formats())
if mime_types.issuperset({'text/html', 'text/_moz_htmlcontext'}): if mime_types.issuperset({'text/html', 'text/_moz_htmlcontext'}):
text = unicode(mime_data.data('text/html'), encoding='utf16') text = str(mime_data.data('text/html'), encoding='utf16')
else: else:
text = mime_data.html() or mime_data.text() text = mime_data.html() or mime_data.text()
self._DH_Text(text) self._DH_Text(text)
...@@ -758,10 +754,10 @@ class ChatWidget(base_class, ui_class): ...@@ -758,10 +754,10 @@ class ChatWidget(base_class, ui_class):
for image in image_descriptors: for image in image_descriptors:
try: try:
self.send_message(image.thumbnail.data, content_type=image.thumbnail.type) self.send_message(image.thumbnail.data, content_type=image.thumbnail.type)
except Exception, e: except Exception as e:
self.add_message(ChatStatus("Error sending image '%s': %s" % (os.path.basename(image.filename), e))) # decide what type to use here. -Dan self.add_message(ChatStatus("Error sending image '%s': %s" % (os.path.basename(image.filename), e))) # decide what type to use here. -Dan
else: else:
content = u'''<a href="{}"><img src="data:{};base64,{}" class="scaled-to-fit" /></a>'''.format(image.fileurl, image.thumbnail.type, image.thumbnail.data.encode('base64').rstrip()) content = '''<a href="{}"><img src="data:{};base64,{}" class="scaled-to-fit" /></a>'''.format(image.fileurl, image.thumbnail.type, image.thumbnail.data.encode('base64').rstrip())
sender = ChatSender(blink_session.account.display_name, blink_session.account.id, self.user_icon.filename) sender = ChatSender(blink_session.account.display_name, blink_session.account.id, self.user_icon.filename)
self.add_message(ChatMessage(content, sender, 'outgoing')) self.add_message(ChatMessage(content, sender, 'outgoing'))
...@@ -773,17 +769,17 @@ class ChatWidget(base_class, ui_class): ...@@ -773,17 +769,17 @@ class ChatWidget(base_class, ui_class):
if match is not None: if match is not None:
try: try:
self.send_message(match.group('data').decode('base64'), content_type=match.group('type')) self.send_message(match.group('data').decode('base64'), content_type=match.group('type'))
except Exception, e: except Exception as e:
self.add_message(ChatStatus('Error sending image: %s' % e)) # decide what type to use here. -Dan self.add_message(ChatStatus('Error sending image: %s' % e)) # decide what type to use here. -Dan
else: else:
account = self.session.blink_session.account account = self.session.blink_session.account
content = u'''<img src="{}" class="scaled-to-fit" />'''.format(text) content = '''<img src="{}" class="scaled-to-fit" />'''.format(text)
sender = ChatSender(account.display_name, account.id, self.user_icon.filename) sender = ChatSender(account.display_name, account.id, self.user_icon.filename)
self.add_message(ChatMessage(content, sender, 'outgoing')) self.add_message(ChatMessage(content, sender, 'outgoing'))
else: else:
user_text = self.chat_input.toHtml() user_text = self.chat_input.toHtml()
self.chat_input.setHtml(text) self.chat_input.setHtml(text)
self.chat_input.keyPressEvent(QKeyEvent(QEvent.KeyPress, Qt.Key_Return, Qt.NoModifier, text=u'\r')) self.chat_input.keyPressEvent(QKeyEvent(QEvent.KeyPress, Qt.Key_Return, Qt.NoModifier, text='\r'))
self.chat_input.setHtml(user_text) self.chat_input.setHtml(user_text)
def _SH_ChatViewSizeChanged(self): def _SH_ChatViewSizeChanged(self):
...@@ -832,7 +828,7 @@ class ChatWidget(base_class, ui_class): ...@@ -832,7 +828,7 @@ class ChatWidget(base_class, ui_class):
return return
try: try:
self.send_message(text, content_type='text/html') self.send_message(text, content_type='text/html')
except Exception, e: except Exception as e:
self.add_message(ChatStatus('Error sending message: %s' % e)) # decide what type to use here. -Dan self.add_message(ChatStatus('Error sending message: %s' % e)) # decide what type to use here. -Dan
else: else:
account = self.session.blink_session.account account = self.session.blink_session.account
...@@ -1004,7 +1000,7 @@ class VideoWidget(VideoSurface, ui_class): ...@@ -1004,7 +1000,7 @@ class VideoWidget(VideoSurface, ui_class):
@property @property
def tool_buttons(self): def tool_buttons(self):
return tuple(attr for attr in vars(self).itervalues() if isinstance(attr, VideoToolButton)) return tuple(attr for attr in vars(self).values() if isinstance(attr, VideoToolButton))
@property @property
def active_tool_buttons(self): def active_tool_buttons(self):
...@@ -1508,7 +1504,7 @@ class ChatWindow(base_class, ui_class, ColorHelperMixin): ...@@ -1508,7 +1504,7 @@ class ChatWindow(base_class, ui_class, ColorHelperMixin):
# self.splitter.splitterMoved.connect(self._SH_SplitterMoved) # check this and decide on what size to have in the window (see Notes) -Dan # self.splitter.splitterMoved.connect(self._SH_SplitterMoved) # check this and decide on what size to have in the window (see Notes) -Dan
def _SH_SplitterMoved(self, pos, index): def _SH_SplitterMoved(self, pos, index):
print "-- splitter:", pos, index, self.splitter.sizes() print("-- splitter:", pos, index, self.splitter.sizes())
def setupUi(self): def setupUi(self):
super(ChatWindow, self).setupUi(self) super(ChatWindow, self).setupUi(self)
...@@ -1769,38 +1765,38 @@ class ChatWindow(base_class, ui_class, ColorHelperMixin): ...@@ -1769,38 +1765,38 @@ class ChatWindow(base_class, ui_class, ColorHelperMixin):
if 'session' in elements: if 'session' in elements:
self.account_value_label.setText(blink_session.account.id) self.account_value_label.setText(blink_session.account.id)
self.remote_agent_value_label.setText(session_info.remote_user_agent or u'N/A') self.remote_agent_value_label.setText(session_info.remote_user_agent or 'N/A')
if 'media' in elements: if 'media' in elements:
self.audio_value_label.setText(audio_info.codec or 'N/A') self.audio_value_label.setText(audio_info.codec or 'N/A')
if audio_info.ice_status == 'succeeded': if audio_info.ice_status == 'succeeded':
if 'relay' in {candidate.type.lower() for candidate in (audio_info.local_rtp_candidate, audio_info.remote_rtp_candidate)}: if 'relay' in {candidate.type.lower() for candidate in (audio_info.local_rtp_candidate, audio_info.remote_rtp_candidate)}:
self.audio_connection_label.setPixmap(self.pixmaps.relay_connection) self.audio_connection_label.setPixmap(self.pixmaps.relay_connection)
self.audio_connection_label.setToolTip(u'Using relay') self.audio_connection_label.setToolTip('Using relay')
else: else:
self.audio_connection_label.setPixmap(self.pixmaps.direct_connection) self.audio_connection_label.setPixmap(self.pixmaps.direct_connection)
self.audio_connection_label.setToolTip(u'Peer to peer') self.audio_connection_label.setToolTip('Peer to peer')
elif audio_info.ice_status == 'failed': elif audio_info.ice_status == 'failed':
self.audio_connection_label.setPixmap(self.pixmaps.unknown_connection) self.audio_connection_label.setPixmap(self.pixmaps.unknown_connection)
self.audio_connection_label.setToolTip(u"Couldn't negotiate ICE") self.audio_connection_label.setToolTip("Couldn't negotiate ICE")
elif audio_info.ice_status == 'disabled': elif audio_info.ice_status == 'disabled':
if blink_session.contact.type == 'bonjour': if blink_session.contact.type == 'bonjour':
self.audio_connection_label.setPixmap(self.pixmaps.direct_connection) self.audio_connection_label.setPixmap(self.pixmaps.direct_connection)
self.audio_connection_label.setToolTip(u'Peer to peer') self.audio_connection_label.setToolTip('Peer to peer')
else: else:
self.audio_connection_label.setPixmap(self.pixmaps.unknown_connection) self.audio_connection_label.setPixmap(self.pixmaps.unknown_connection)
self.audio_connection_label.setToolTip(u'ICE is disabled') self.audio_connection_label.setToolTip('ICE is disabled')
elif audio_info.ice_status is None: elif audio_info.ice_status is None:
self.audio_connection_label.setPixmap(self.pixmaps.unknown_connection) self.audio_connection_label.setPixmap(self.pixmaps.unknown_connection)
self.audio_connection_label.setToolTip(u'ICE is unavailable') self.audio_connection_label.setToolTip('ICE is unavailable')
else: else:
self.audio_connection_label.setPixmap(self.pixmaps.unknown_connection) self.audio_connection_label.setPixmap(self.pixmaps.unknown_connection)
self.audio_connection_label.setToolTip(u'Negotiating ICE') self.audio_connection_label.setToolTip('Negotiating ICE')
if audio_info.encryption is not None: if audio_info.encryption is not None:
self.audio_encryption_label.setToolTip(u'Media is encrypted using %s (%s)' % (audio_info.encryption, audio_info.encryption_cipher)) self.audio_encryption_label.setToolTip('Media is encrypted using %s (%s)' % (audio_info.encryption, audio_info.encryption_cipher))
else: else:
self.audio_encryption_label.setToolTip(u'Media is not encrypted') self.audio_encryption_label.setToolTip('Media is not encrypted')
self._update_rtp_encryption_icon(self.audio_encryption_label) self._update_rtp_encryption_icon(self.audio_encryption_label)
self.audio_connection_label.setVisible(audio_info.remote_address is not None) self.audio_connection_label.setVisible(audio_info.remote_address is not None)
...@@ -1810,31 +1806,31 @@ class ChatWindow(base_class, ui_class, ColorHelperMixin): ...@@ -1810,31 +1806,31 @@ class ChatWindow(base_class, ui_class, ColorHelperMixin):
if video_info.ice_status == 'succeeded': if video_info.ice_status == 'succeeded':
if 'relay' in {candidate.type.lower() for candidate in (video_info.local_rtp_candidate, video_info.remote_rtp_candidate)}: if 'relay' in {candidate.type.lower() for candidate in (video_info.local_rtp_candidate, video_info.remote_rtp_candidate)}:
self.video_connection_label.setPixmap(self.pixmaps.relay_connection) self.video_connection_label.setPixmap(self.pixmaps.relay_connection)
self.video_connection_label.setToolTip(u'Using relay') self.video_connection_label.setToolTip('Using relay')
else: else:
self.video_connection_label.setPixmap(self.pixmaps.direct_connection) self.video_connection_label.setPixmap(self.pixmaps.direct_connection)
self.video_connection_label.setToolTip(u'Peer to peer') self.video_connection_label.setToolTip('Peer to peer')
elif video_info.ice_status == 'failed': elif video_info.ice_status == 'failed':
self.video_connection_label.setPixmap(self.pixmaps.unknown_connection) self.video_connection_label.setPixmap(self.pixmaps.unknown_connection)
self.video_connection_label.setToolTip(u"Couldn't negotiate ICE") self.video_connection_label.setToolTip("Couldn't negotiate ICE")
elif video_info.ice_status == 'disabled': elif video_info.ice_status == 'disabled':
if blink_session.contact.type == 'bonjour': if blink_session.contact.type == 'bonjour':
self.video_connection_label.setPixmap(self.pixmaps.direct_connection) self.video_connection_label.setPixmap(self.pixmaps.direct_connection)
self.video_connection_label.setToolTip(u'Peer to peer') self.video_connection_label.setToolTip('Peer to peer')
else: else:
self.video_connection_label.setPixmap(self.pixmaps.unknown_connection) self.video_connection_label.setPixmap(self.pixmaps.unknown_connection)
self.video_connection_label.setToolTip(u'ICE is disabled') self.video_connection_label.setToolTip('ICE is disabled')
elif video_info.ice_status is None: elif video_info.ice_status is None:
self.video_connection_label.setPixmap(self.pixmaps.unknown_connection) self.video_connection_label.setPixmap(self.pixmaps.unknown_connection)
self.video_connection_label.setToolTip(u'ICE is unavailable') self.video_connection_label.setToolTip('ICE is unavailable')
else: else:
self.video_connection_label.setPixmap(self.pixmaps.unknown_connection) self.video_connection_label.setPixmap(self.pixmaps.unknown_connection)
self.video_connection_label.setToolTip(u'Negotiating ICE') self.video_connection_label.setToolTip('Negotiating ICE')
if video_info.encryption is not None: if video_info.encryption is not None:
self.video_encryption_label.setToolTip(u'Media is encrypted using %s (%s)' % (video_info.encryption, video_info.encryption_cipher)) self.video_encryption_label.setToolTip('Media is encrypted using %s (%s)' % (video_info.encryption, video_info.encryption_cipher))
else: else:
self.video_encryption_label.setToolTip(u'Media is not encrypted') self.video_encryption_label.setToolTip('Media is not encrypted')
self._update_rtp_encryption_icon(self.video_encryption_label) self._update_rtp_encryption_icon(self.video_encryption_label)
self.video_connection_label.setVisible(video_info.remote_address is not None) self.video_connection_label.setVisible(video_info.remote_address is not None)
...@@ -1850,24 +1846,24 @@ class ChatWindow(base_class, ui_class, ColorHelperMixin): ...@@ -1850,24 +1846,24 @@ class ChatWindow(base_class, ui_class, ColorHelperMixin):
self.zrtp_widget.show() self.zrtp_widget.show()
if any(len(path) > 1 for path in (chat_info.full_local_path, chat_info.full_remote_path)): if any(len(path) > 1 for path in (chat_info.full_local_path, chat_info.full_remote_path)):
self.chat_value_label.setText(u'Using relay') self.chat_value_label.setText('Using relay')
self.chat_connection_label.setPixmap(self.pixmaps.relay_connection) self.chat_connection_label.setPixmap(self.pixmaps.relay_connection)
self.chat_connection_label.setToolTip(u'Using relay') self.chat_connection_label.setToolTip('Using relay')
elif chat_info.full_local_path and chat_info.full_remote_path: elif chat_info.full_local_path and chat_info.full_remote_path:
self.chat_value_label.setText(u'Peer to peer') self.chat_value_label.setText('Peer to peer')
self.chat_connection_label.setPixmap(self.pixmaps.direct_connection) self.chat_connection_label.setPixmap(self.pixmaps.direct_connection)
self.chat_connection_label.setToolTip(u'Peer to peer') self.chat_connection_label.setToolTip('Peer to peer')
else: else:
self.chat_value_label.setText(u'N/A') self.chat_value_label.setText('N/A')
if chat_info.encryption is not None and chat_info.transport == 'tls': if chat_info.encryption is not None and chat_info.transport == 'tls':
self.chat_encryption_label.setToolTip(u'Media is encrypted using TLS and {0.encryption} ({0.encryption_cipher})'.format(chat_info)) self.chat_encryption_label.setToolTip('Media is encrypted using TLS and {0.encryption} ({0.encryption_cipher})'.format(chat_info))
elif chat_info.encryption is not None: elif chat_info.encryption is not None:
self.chat_encryption_label.setToolTip(u'Media is encrypted using {0.encryption} ({0.encryption_cipher})'.format(chat_info)) self.chat_encryption_label.setToolTip('Media is encrypted using {0.encryption} ({0.encryption_cipher})'.format(chat_info))
elif chat_info.transport == 'tls': elif chat_info.transport == 'tls':
self.chat_encryption_label.setToolTip(u'Media is encrypted using TLS') self.chat_encryption_label.setToolTip('Media is encrypted using TLS')
else: else:
self.chat_encryption_label.setToolTip(u'Media is not encrypted') self.chat_encryption_label.setToolTip('Media is not encrypted')
self._update_chat_encryption_icon() self._update_chat_encryption_icon()
self.chat_connection_label.setVisible(chat_info.remote_address is not None) self.chat_connection_label.setVisible(chat_info.remote_address is not None)
...@@ -1885,20 +1881,20 @@ class ChatWindow(base_class, ui_class, ColorHelperMixin): ...@@ -1885,20 +1881,20 @@ class ChatWindow(base_class, ui_class, ColorHelperMixin):
self.otr_widget.show() self.otr_widget.show()
if screen_info.remote_address is not None and screen_info.mode == 'active': if screen_info.remote_address is not None and screen_info.mode == 'active':
self.screen_value_label.setText(u'Viewing remote') self.screen_value_label.setText('Viewing remote')
elif screen_info.remote_address is not None and screen_info.mode == 'passive': elif screen_info.remote_address is not None and screen_info.mode == 'passive':
self.screen_value_label.setText(u'Sharing local') self.screen_value_label.setText('Sharing local')
else: else:
self.screen_value_label.setText(u'N/A') self.screen_value_label.setText('N/A')
if any(len(path) > 1 for path in (screen_info.full_local_path, screen_info.full_remote_path)): if any(len(path) > 1 for path in (screen_info.full_local_path, screen_info.full_remote_path)):
self.screen_connection_label.setPixmap(self.pixmaps.relay_connection) self.screen_connection_label.setPixmap(self.pixmaps.relay_connection)
self.screen_connection_label.setToolTip(u'Using relay') self.screen_connection_label.setToolTip('Using relay')
elif screen_info.full_local_path and screen_info.full_remote_path: elif screen_info.full_local_path and screen_info.full_remote_path:
self.screen_connection_label.setPixmap(self.pixmaps.direct_connection) self.screen_connection_label.setPixmap(self.pixmaps.direct_connection)
self.screen_connection_label.setToolTip(u'Peer to peer') self.screen_connection_label.setToolTip('Peer to peer')
self.screen_encryption_label.setToolTip(u'Media is encrypted using TLS') self.screen_encryption_label.setToolTip('Media is encrypted using TLS')
self.screen_connection_label.setVisible(screen_info.remote_address is not None) self.screen_connection_label.setVisible(screen_info.remote_address is not None)
self.screen_encryption_label.setVisible(screen_info.remote_address is not None and screen_info.transport == 'tls') self.screen_encryption_label.setVisible(screen_info.remote_address is not None and screen_info.transport == 'tls')
...@@ -2087,9 +2083,9 @@ class ChatWindow(base_class, ui_class, ColorHelperMixin): ...@@ -2087,9 +2083,9 @@ class ChatWindow(base_class, ui_class, ColorHelperMixin):
else: else:
title_role = 'title' title_role = 'title'
value_role = 'value' 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): for label in (attr for name, attr in vars(self).items() if name.endswith('_title_label') and attr.property('role') is not None):
label.setProperty('role', title_role) 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): for label in (attr for name, attr in vars(self).items() if name.endswith('_value_label') or name.endswith('_value_widget') and attr.property('role') is not None):
label.setProperty('role', value_role) label.setProperty('role', value_role)
self.info_panel_container_widget.setStyleSheet(self.info_panel_container_widget.styleSheet()) 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.latency_graph.horizontalPixelsPerUnit = blink_settings.chat_window.session_info.graph_time_scale
...@@ -2120,9 +2116,9 @@ class ChatWindow(base_class, ui_class, ColorHelperMixin): ...@@ -2120,9 +2116,9 @@ class ChatWindow(base_class, ui_class, ColorHelperMixin):
else: else:
title_role = 'title' title_role = 'title'
value_role = 'value' 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): for label in (attr for name, attr in vars(self).items() if name.endswith('_title_label') and attr.property('role') is not None):
label.setProperty('role', title_role) 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): for label in (attr for name, attr in vars(self).items() if name.endswith('_value_label') or name.endswith('_value_widget') and attr.property('role') is not None):
label.setProperty('role', value_role) label.setProperty('role', value_role)
self.info_panel_container_widget.setStyleSheet(self.info_panel_container_widget.styleSheet()) self.info_panel_container_widget.setStyleSheet(self.info_panel_container_widget.styleSheet())
if 'chat_window.session_info.bytes_per_second' in notification.data.modified: if 'chat_window.session_info.bytes_per_second' in notification.data.modified:
...@@ -2212,7 +2208,7 @@ class ChatWindow(base_class, ui_class, ColorHelperMixin): ...@@ -2212,7 +2208,7 @@ class ChatWindow(base_class, ui_class, ColorHelperMixin):
message = notification.data.message message = notification.data.message
if message.content_type.startswith('image/'): if message.content_type.startswith('image/'):
content = u'''<img src="data:{};base64,{}" class="scaled-to-fit" />'''.format(message.content_type, message.content.encode('base64').rstrip()) content = '''<img src="data:{};base64,{}" class="scaled-to-fit" />'''.format(message.content_type, message.content.encode('base64').rstrip())
elif message.content_type.startswith('text/'): elif message.content_type.startswith('text/'):
content = HtmlProcessor.autolink(message.content if message.content_type == 'text/html' else QTextDocument(message.content).toHtml()) content = HtmlProcessor.autolink(message.content if message.content_type == 'text/html' else QTextDocument(message.content).toHtml())
else: else:
...@@ -2352,10 +2348,10 @@ class ChatWindow(base_class, ui_class, ColorHelperMixin): ...@@ -2352,10 +2348,10 @@ class ChatWindow(base_class, ui_class, ColorHelperMixin):
self.selected_session.active_panel = self.participants_panel self.selected_session.active_panel = self.participants_panel
def _SH_LatencyGraphUpdated(self): def _SH_LatencyGraphUpdated(self):
self.latency_label.setText(u'Network Latency: %dms, max=%dms' % (max(self.audio_latency_graph.last_value, self.video_latency_graph.last_value), self.latency_graph.max_value)) self.latency_label.setText('Network Latency: %dms, max=%dms' % (max(self.audio_latency_graph.last_value, self.video_latency_graph.last_value), self.latency_graph.max_value))
def _SH_PacketLossGraphUpdated(self): def _SH_PacketLossGraphUpdated(self):
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)) self.packet_loss_label.setText('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): def _SH_TrafficGraphUpdated(self):
blink_settings = BlinkSettings() blink_settings = BlinkSettings()
...@@ -2365,7 +2361,7 @@ class ChatWindow(base_class, ui_class, ColorHelperMixin): ...@@ -2365,7 +2361,7 @@ class ChatWindow(base_class, ui_class, ColorHelperMixin):
else: else:
incoming_traffic = TrafficNormalizer.normalize(self.incoming_traffic_graph.last_value*8, bits_per_second=True) 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) outgoing_traffic = TrafficNormalizer.normalize(self.outgoing_traffic_graph.last_value*8, bits_per_second=True)
self.traffic_label.setText(u"""<p>Traffic: <span style="font-family: sans-serif; color: #d70000;">\u2193</span> %s <span style="font-family: sans-serif; color: #0064d7;">\u2191</span> %s</p>""" % (incoming_traffic, outgoing_traffic)) self.traffic_label.setText("""<p>Traffic: <span style="font-family: sans-serif; color: #d70000;">\u2193</span> %s <span style="font-family: sans-serif; color: #0064d7;">\u2191</span> %s</p>""" % (incoming_traffic, outgoing_traffic))
def _SH_MuteButtonClicked(self, checked): def _SH_MuteButtonClicked(self, checked):
settings = SIPSimpleSettings() settings = SIPSimpleSettings()
...@@ -2581,7 +2577,7 @@ class HtmlProcessor(object): ...@@ -2581,7 +2577,7 @@ class HtmlProcessor(object):
@classmethod @classmethod
def autolink(cls, content): def autolink(cls, content):
if isinstance(content, basestring): if isinstance(content, str):
doc = html.fromstring(content) doc = html.fromstring(content)
autolink(doc, link_regexes=cls._autolink_re) autolink(doc, link_regexes=cls._autolink_re)
return html.tostring(doc, encoding='unicode') # add method='xml' to get <br/> xhtml style tags and doctype=doc.getroottree().docinfo.doctype for prepending the DOCTYPE line return html.tostring(doc, encoding='unicode') # add method='xml' to get <br/> xhtml style tags and doctype=doc.getroottree().docinfo.doctype for prepending the DOCTYPE line
......
...@@ -34,8 +34,8 @@ class PresenceSettingsExtension(PresenceSettings): ...@@ -34,8 +34,8 @@ class PresenceSettingsExtension(PresenceSettings):
class PSTNSettings(SettingsGroup): class PSTNSettings(SettingsGroup):
idd_prefix = Setting(type=unicode, default=None, nillable=True) idd_prefix = Setting(type=str, default=None, nillable=True)
prefix = Setting(type=unicode, default=None, nillable=True) prefix = Setting(type=str, default=None, nillable=True)
class RTPSettingsExtension(RTPSettings): class RTPSettingsExtension(RTPSettings):
...@@ -71,7 +71,7 @@ class XCAPSettingsExtension(XCAPSettings): ...@@ -71,7 +71,7 @@ class XCAPSettingsExtension(XCAPSettings):
class AccountExtension(SettingsObjectExtension): class AccountExtension(SettingsObjectExtension):
display_name = Setting(type=unicode, default=user_info.fullname, nillable=True) display_name = Setting(type=str, default=user_info.fullname, nillable=True)
message_summary = MessageSummarySettingsExtension message_summary = MessageSummarySettingsExtension
msrp = MSRPSettingsExtension msrp = MSRPSettingsExtension
pstn = PSTNSettings pstn = PSTNSettings
......
...@@ -13,8 +13,8 @@ SharedSetting.set_namespace('ag-projects:blink') ...@@ -13,8 +13,8 @@ SharedSetting.set_namespace('ag-projects:blink')
class PresenceSettingsExtension(PresenceSettings): class PresenceSettingsExtension(PresenceSettings):
state = RuntimeSetting(type=unicode, nillable=True, default=None) state = RuntimeSetting(type=str, nillable=True, default=None)
note = RuntimeSetting(type=unicode, nillable=True, default=None) note = RuntimeSetting(type=str, nillable=True, default=None)
class ContactExtension(ContactExtension): class ContactExtension(ContactExtension):
......
...@@ -3,9 +3,8 @@ ...@@ -3,9 +3,8 @@
import os import os
import re import re
from urllib.request import pathname2url, url2pathname
from urllib import pathname2url, url2pathname from urllib.parse import urlparse
from urlparse import urlparse
from application.python.types import MarkerType from application.python.types import MarkerType
from sipsimple.configuration.datatypes import Hostname, List from sipsimple.configuration.datatypes import Hostname, List
...@@ -16,12 +15,12 @@ from blink.resources import ApplicationData ...@@ -16,12 +15,12 @@ from blink.resources import ApplicationData
__all__ = ['ApplicationDataPath', 'DefaultPath', 'SoundFile', 'CustomSoundFile', 'HTTPURL', 'FileURL', 'IconDescriptor', 'PresenceState', 'PresenceStateList', 'GraphTimeScale'] __all__ = ['ApplicationDataPath', 'DefaultPath', 'SoundFile', 'CustomSoundFile', 'HTTPURL', 'FileURL', 'IconDescriptor', 'PresenceState', 'PresenceStateList', 'GraphTimeScale']
class ApplicationDataPath(unicode): class ApplicationDataPath(str):
def __new__(cls, path): def __new__(cls, path):
path = os.path.normpath(path) path = os.path.normpath(path)
if path.startswith(ApplicationData.directory+os.path.sep): if path.startswith(ApplicationData.directory+os.path.sep):
path = path[len(ApplicationData.directory+os.path.sep):] path = path[len(ApplicationData.directory+os.path.sep):]
return unicode.__new__(cls, path) return str.__new__(cls, path)
@property @property
def normalized(self): def normalized(self):
...@@ -36,11 +35,11 @@ class SoundFile(object): ...@@ -36,11 +35,11 @@ class SoundFile(object):
raise ValueError('illegal volume level: %d' % self.volume) raise ValueError('illegal volume level: %d' % self.volume)
def __getstate__(self): def __getstate__(self):
return u'%s,%s' % (self.__dict__['path'], self.volume) return '%s,%s' % (self.__dict__['path'], self.volume)
def __setstate__(self, state): def __setstate__(self, state):
try: try:
path, volume = state.rsplit(u',', 1) path, volume = state.rsplit(',', 1)
except ValueError: except ValueError:
self.__init__(state) self.__init__(state)
else: else:
...@@ -60,7 +59,7 @@ class SoundFile(object): ...@@ -60,7 +59,7 @@ class SoundFile(object):
del _get_path, _set_path del _get_path, _set_path
class DefaultPath: __metaclass__ = MarkerType class DefaultPath(metaclass=MarkerType): pass
class CustomSoundFile(object): # check if this data type is still needed -Dan class CustomSoundFile(object): # check if this data type is still needed -Dan
...@@ -72,9 +71,9 @@ class CustomSoundFile(object): # check if this data type is still needed -Dan ...@@ -72,9 +71,9 @@ class CustomSoundFile(object): # check if this data type is still needed -Dan
def __getstate__(self): def __getstate__(self):
if self.path is DefaultPath: if self.path is DefaultPath:
return u'default' return 'default'
else: else:
return u'file:%s,%s' % (self.__dict__['path'], self.volume) return 'file:%s,%s' % (self.__dict__['path'], self.volume)
def __setstate__(self, state): def __setstate__(self, state):
match = re.match(r'^(?P<type>default|file:)(?P<path>.+?)?(,(?P<volume>\d+))?$', state) match = re.match(r'^(?P<type>default|file:)(?P<path>.+?)?(,(?P<volume>\d+))?$', state)
...@@ -102,11 +101,11 @@ class CustomSoundFile(object): # check if this data type is still needed -Dan ...@@ -102,11 +101,11 @@ class CustomSoundFile(object): # check if this data type is still needed -Dan
del _get_path, _set_path del _get_path, _set_path
class HTTPURL(unicode): class HTTPURL(str):
def __new__(cls, value): def __new__(cls, value):
value = unicode(value) value = str(value)
url = urlparse(value) url = urlparse(value)
if url.scheme not in (u'http', u'https'): if url.scheme not in ('http', 'https'):
raise ValueError("illegal HTTP URL scheme (http and https only): %s" % url.scheme) raise ValueError("illegal HTTP URL scheme (http and https only): %s" % url.scheme)
Hostname(url.hostname) Hostname(url.hostname)
if url.port is not None and not (0 < url.port < 65536): if url.port is not None and not (0 < url.port < 65536):
...@@ -114,14 +113,14 @@ class HTTPURL(unicode): ...@@ -114,14 +113,14 @@ class HTTPURL(unicode):
return value return value
class FileURL(unicode): class FileURL(str):
def __new__(cls, value): def __new__(cls, value):
if not value.startswith('file:'): if not value.startswith('file:'):
value = 'file:' + pathname2url(os.path.abspath(value).encode('utf-8')).decode('utf-8') value = 'file:' + pathname2url(os.path.abspath(value).encode('utf-8')).decode('utf-8')
return unicode.__new__(cls, value) return str.__new__(cls, value)
class ParsedURL(unicode): class ParsedURL(str):
fragment = property(lambda self: self.__parsed__.fragment) fragment = property(lambda self: self.__parsed__.fragment)
netloc = property(lambda self: self.__parsed__.netloc) netloc = property(lambda self: self.__parsed__.netloc)
params = property(lambda self: self.__parsed__.params) params = property(lambda self: self.__parsed__.params)
...@@ -140,13 +139,13 @@ class IconDescriptor(object): ...@@ -140,13 +139,13 @@ class IconDescriptor(object):
def __getstate__(self): def __getstate__(self):
if self.etag is None: if self.etag is None:
return unicode(self.url) return str(self.url)
else: else:
return u'%s,%s' % (self.url, self.etag) return '%s,%s' % (self.url, self.etag)
def __setstate__(self, state): def __setstate__(self, state):
try: try:
url, etag = state.rsplit(u',', 1) url, etag = state.rsplit(',', 1)
except ValueError: except ValueError:
self.__init__(state) self.__init__(state)
else: else:
...@@ -167,18 +166,18 @@ class IconDescriptor(object): ...@@ -167,18 +166,18 @@ class IconDescriptor(object):
class PresenceState(object): class PresenceState(object):
def __init__(self, state, note=None): def __init__(self, state, note=None):
self.state = unicode(state) self.state = str(state)
self.note = note self.note = note
def __getstate__(self): def __getstate__(self):
if not self.note: if not self.note:
return unicode(self.state) return str(self.state)
else: else:
return u'%s,%s' % (self.state, self.note) return '%s,%s' % (self.state, self.note)
def __setstate__(self, data): def __setstate__(self, data):
try: try:
state, note = data.split(u',', 1) state, note = data.split(',', 1)
except ValueError: except ValueError:
self.__init__(data) self.__init__(data)
else: else:
......
...@@ -41,7 +41,7 @@ class ChatSettingsExtension(ChatSettings): ...@@ -41,7 +41,7 @@ class ChatSettingsExtension(ChatSettings):
class GoogleContactsSettings(SettingsGroup): class GoogleContactsSettings(SettingsGroup):
enabled = Setting(type=bool, default=False) enabled = Setting(type=bool, default=False)
username = Setting(type=unicode, default=None, nillable=True) username = Setting(type=str, default=None, nillable=True)
class LogsSettingsExtension(LogsSettings): class LogsSettingsExtension(LogsSettings):
...@@ -111,7 +111,7 @@ class BlinkScreenSharingSettings(SettingsGroup): ...@@ -111,7 +111,7 @@ class BlinkScreenSharingSettings(SettingsGroup):
class BlinkPresenceSettings(SettingsGroup): class BlinkPresenceSettings(SettingsGroup):
current_state = Setting(type=PresenceState, default=PresenceState('Available')) current_state = Setting(type=PresenceState, default=PresenceState('Available'))
state_history = Setting(type=PresenceStateList, default=PresenceStateList()) state_history = Setting(type=PresenceStateList, default=PresenceStateList())
offline_note = Setting(type=unicode, nillable=True) offline_note = Setting(type=str, nillable=True)
icon = Setting(type=IconDescriptor, nillable=True) icon = Setting(type=IconDescriptor, nillable=True)
......
import cPickle as pickle import pickle as pickle
import locale import locale
import os import os
import re import re
...@@ -55,8 +55,7 @@ from blink.widgets.util import ContextMenuActions ...@@ -55,8 +55,7 @@ from blink.widgets.util import ContextMenuActions
__all__ = ['Group', 'Contact', 'ContactModel', 'ContactSearchModel', 'ContactListView', 'ContactSearchListView', 'ContactEditorDialog', 'URIUtils'] __all__ = ['Group', 'Contact', 'ContactModel', 'ContactSearchModel', 'ContactListView', 'ContactSearchListView', 'ContactEditorDialog', 'URIUtils']
class VirtualGroupManager(object): class VirtualGroupManager(object, metaclass=Singleton):
__metaclass__ = Singleton
implements(IObserver) implements(IObserver)
__groups__ = [] __groups__ = []
...@@ -75,7 +74,7 @@ class VirtualGroupManager(object): ...@@ -75,7 +74,7 @@ class VirtualGroupManager(object):
return self.groups[id] return self.groups[id]
def get_groups(self): def get_groups(self):
return self.groups.values() return list(self.groups.values())
def handle_notification(self, notification): def handle_notification(self, notification):
handler = getattr(self, '_NH_%s' % notification.name, Null) handler = getattr(self, '_NH_%s' % notification.name, Null)
...@@ -97,18 +96,17 @@ class VirtualGroupManager(object): ...@@ -97,18 +96,17 @@ class VirtualGroupManager(object):
class VirtualGroupMeta(SettingsObjectMeta): class VirtualGroupMeta(SettingsObjectMeta):
def __init__(cls, name, bases, dic): def __init__(cls, name, bases, dic):
if not (cls.__id__ is None or isinstance(cls.__id__, basestring)): if not (cls.__id__ is None or isinstance(cls.__id__, str)):
raise TypeError("%s.__id__ must be None or a string" % name) raise TypeError("%s.__id__ must be None or a string" % name)
super(VirtualGroupMeta, cls).__init__(name, bases, dic) super(VirtualGroupMeta, cls).__init__(name, bases, dic)
if cls.__id__ is not None: if cls.__id__ is not None:
VirtualGroupManager.__groups__.append(cls) VirtualGroupManager.__groups__.append(cls)
class VirtualGroup(SettingsState): class VirtualGroup(SettingsState, metaclass=VirtualGroupMeta):
__metaclass__ = VirtualGroupMeta
__id__ = None __id__ = None
name = Setting(type=unicode, default='') name = Setting(type=str, default='')
position = Setting(type=int, default=None, nillable=True) position = Setting(type=int, default=None, nillable=True)
collapsed = Setting(type=bool, default=False) collapsed = Setting(type=bool, default=False)
...@@ -190,7 +188,7 @@ class AllContactsGroup(VirtualGroup): ...@@ -190,7 +188,7 @@ class AllContactsGroup(VirtualGroup):
__id__ = 'all_contacts' __id__ = 'all_contacts'
name = Setting(type=unicode, default='All Contacts') name = Setting(type=str, default='All Contacts')
contacts = WriteOnceAttribute() contacts = WriteOnceAttribute()
def __init__(self): def __init__(self):
...@@ -233,9 +231,9 @@ class BonjourNeighbourID(str): ...@@ -233,9 +231,9 @@ class BonjourNeighbourID(str):
pass pass
class BonjourURI(unicode): class BonjourURI(str):
def __new__(cls, value): def __new__(cls, value):
instance = unicode.__new__(cls, unicode(value).partition(':')[2]) instance = str.__new__(cls, str(value).partition(':')[2])
instance.__uri__ = value instance.__uri__ = value
return instance return instance
...@@ -281,7 +279,7 @@ class BonjourNeighbourURIList(object): ...@@ -281,7 +279,7 @@ class BonjourNeighbourURIList(object):
return id in self._uri_map return id in self._uri_map
def __iter__(self): def __iter__(self):
return iter(self._uri_map.values()) return iter(list(self._uri_map.values()))
def __len__(self): def __len__(self):
return len(self._uri_map) return len(self._uri_map)
...@@ -315,7 +313,7 @@ class BonjourNeighbour(object): ...@@ -315,7 +313,7 @@ class BonjourNeighbour(object):
id = WriteOnceAttribute() id = WriteOnceAttribute()
def __init__(self, id, name, hostname, uris, presence=None): def __init__(self, id, name, hostname, uris, presence=None):
self.id = BonjourNeighbourID(id) if isinstance(id, basestring) else id self.id = BonjourNeighbourID(id) if isinstance(id, str) else id
self.name = name self.name = name
self.hostname = hostname self.hostname = hostname
self.uris = BonjourNeighbourURIList(uris) self.uris = BonjourNeighbourURIList(uris)
...@@ -334,7 +332,7 @@ class BonjourNeighboursList(object): ...@@ -334,7 +332,7 @@ class BonjourNeighboursList(object):
return id in self._contact_map return id in self._contact_map
def __iter__(self): def __iter__(self):
return iter(self._contact_map.values()) return iter(list(self._contact_map.values()))
def __len__(self): def __len__(self):
return len(self._contact_map) return len(self._contact_map)
...@@ -351,8 +349,7 @@ class BonjourNeighboursList(object): ...@@ -351,8 +349,7 @@ class BonjourNeighboursList(object):
return self._contact_map.pop(contact.id, None) return self._contact_map.pop(contact.id, None)
class BonjourNeighboursManager(object): class BonjourNeighboursManager(object, metaclass=Singleton):
__metaclass__ = Singleton
implements(IObserver) implements(IObserver)
contacts = WriteOnceAttribute() contacts = WriteOnceAttribute()
...@@ -407,7 +404,7 @@ class BonjourNeighboursGroup(VirtualGroup): ...@@ -407,7 +404,7 @@ class BonjourNeighboursGroup(VirtualGroup):
__id__ = 'bonjour_neighbours' __id__ = 'bonjour_neighbours'
name = Setting(type=unicode, default='Bonjour Neighbours') name = Setting(type=str, default='Bonjour Neighbours')
contacts = property(lambda self: self.__manager__.contacts) contacts = property(lambda self: self.__manager__.contacts)
def __init__(self): def __init__(self):
...@@ -436,14 +433,14 @@ class BonjourNeighboursGroup(VirtualGroup): ...@@ -436,14 +433,14 @@ class BonjourNeighboursGroup(VirtualGroup):
notification.center.post_notification('VirtualContactDidChange', sender=notification.data.contact) notification.center.post_notification('VirtualContactDidChange', sender=notification.data.contact)
class GoogleContactID(unicode): class GoogleContactID(str):
pass pass
class GoogleContactIconMetadata(object): class GoogleContactIconMetadata(object):
def __init__(self, metadata): def __init__(self, metadata):
metadata = metadata or {'source': {'id': None, 'type': None}} metadata = metadata or {'source': {'id': None, 'type': None}}
self.__dict__.update({name: GoogleContactIconMetadata(value) if isinstance(value, dict) else value for name, value in metadata.iteritems()}) self.__dict__.update({name: GoogleContactIconMetadata(value) if isinstance(value, dict) else value for name, value in metadata.items()})
def __getattr__(self, name): # stop PyCharm from complaining about undefined attributes def __getattr__(self, name): # stop PyCharm from complaining about undefined attributes
raise AttributeError(name) raise AttributeError(name)
...@@ -490,7 +487,7 @@ class GoogleContactIconRetriever(object): ...@@ -490,7 +487,7 @@ class GoogleContactIconRetriever(object):
else: else:
response = content = None response = content = None
except (HttpLib2Error, socket.error) as e: except (HttpLib2Error, socket.error) as e:
log.warning(u'could not retrieve icon for {owner}: {exception!s}'.format(owner=owner, exception=e)) log.warning('could not retrieve icon for {owner}: {exception!s}'.format(owner=owner, exception=e))
else: else:
if response is None: if response is None:
icon_manager = IconManager() icon_manager = IconManager()
...@@ -501,27 +498,27 @@ class GoogleContactIconRetriever(object): ...@@ -501,27 +498,27 @@ class GoogleContactIconRetriever(object):
try: try:
icon_manager.store_data(self.contact.id, content) icon_manager.store_data(self.contact.id, content)
except Exception as e: except Exception as e:
log.error(u'could not store icon for {owner}: {exception!s}'.format(owner=owner, exception=e)) log.error('could not store icon for {owner}: {exception!s}'.format(owner=owner, exception=e))
else: else:
icon.downloaded_url = icon.url icon.downloaded_url = icon.url
elif response['status'] in ('403', '404') and icon.alternate_url: # private or unavailable photo. use old GData protocol if alternate_url is available. elif response['status'] in ('403', '404') and icon.alternate_url: # private or unavailable photo. use old GData protocol if alternate_url is available.
try: try:
response, content = http.request(icon.alternate_url, headers={'GData-Version': '3.0'}) response, content = http.request(icon.alternate_url, headers={'GData-Version': '3.0'})
except (HttpLib2Error, socket.error) as e: except (HttpLib2Error, socket.error) as e:
log.warning(u'could not retrieve icon for {owner}: {exception!s}'.format(owner=owner, exception=e)) log.warning('could not retrieve icon for {owner}: {exception!s}'.format(owner=owner, exception=e))
else: else:
if response['status'] == '200' and response['content-type'].startswith('image/'): if response['status'] == '200' and response['content-type'].startswith('image/'):
icon_manager = IconManager() icon_manager = IconManager()
try: try:
icon_manager.store_data(self.contact.id, content) icon_manager.store_data(self.contact.id, content)
except Exception as e: except Exception as e:
log.error(u'could not store icon for {owner}: {exception!s}'.format(owner=owner, exception=e)) log.error('could not store icon for {owner}: {exception!s}'.format(owner=owner, exception=e))
else: else:
icon.downloaded_url = icon.url icon.downloaded_url = icon.url
else: else:
log.error(u'could not retrieve icon for {} (status={}, content-type={!r})'.format(owner, response['status'], response['content-type'])) log.error('could not retrieve icon for {} (status={}, content-type={!r})'.format(owner, response['status'], response['content-type']))
else: else:
log.error(u'could not retrieve icon for {} (status={}, content-type={!r})'.format(owner, response['status'], response['content-type'])) log.error('could not retrieve icon for {} (status={}, content-type={!r})'.format(owner, response['status'], response['content-type']))
finally: finally:
self._event.set() self._event.set()
...@@ -561,7 +558,7 @@ class GoogleContactURIList(object): ...@@ -561,7 +558,7 @@ class GoogleContactURIList(object):
return id in self._uri_map return id in self._uri_map
def __iter__(self): def __iter__(self):
return iter(self._uri_map.values()) return iter(list(self._uri_map.values()))
def __len__(self): def __len__(self):
return len(self._uri_map) return len(self._uri_map)
...@@ -658,7 +655,7 @@ class GoogleContactsList(object): ...@@ -658,7 +655,7 @@ class GoogleContactsList(object):
return id in self._contact_map return id in self._contact_map
def __iter__(self): def __iter__(self):
return iter(self._contact_map.values()) return iter(list(self._contact_map.values()))
def __len__(self): def __len__(self):
return len(self._contact_map) return len(self._contact_map)
...@@ -678,7 +675,7 @@ class GoogleContactsList(object): ...@@ -678,7 +675,7 @@ class GoogleContactsList(object):
class GoogleAuthorizationView(QWebView): class GoogleAuthorizationView(QWebView):
finished = pyqtSignal() finished = pyqtSignal()
accepted = pyqtSignal(unicode, unicode) # accepted.emit(code, email) accepted = pyqtSignal(str, str) # accepted.emit(code, email)
rejected = pyqtSignal() rejected = pyqtSignal()
success_token = 'Success code=' success_token = 'Success code='
...@@ -778,8 +775,7 @@ class GoogleAuthorization(object): ...@@ -778,8 +775,7 @@ class GoogleAuthorization(object):
notification_center.post_notification('GoogleAuthorizationWasRejected', sender=self) notification_center.post_notification('GoogleAuthorizationWasRejected', sender=self)
class GoogleContactsManager(object): class GoogleContactsManager(object, metaclass=Singleton):
__metaclass__ = Singleton
implements(IObserver) implements(IObserver)
def __init__(self): def __init__(self):
...@@ -866,9 +862,9 @@ class GoogleContactsManager(object): ...@@ -866,9 +862,9 @@ class GoogleContactsManager(object):
self._sync_token = None self._sync_token = None
self.sync_contacts() self.sync_contacts()
return return
log.warning(u'Could not fetch Google contacts: {!s}'.format(e)) log.warning('Could not fetch Google contacts: {!s}'.format(e))
except (HttpLib2Error, socket.error) as e: except (HttpLib2Error, socket.error) as e:
log.warning(u'Could not fetch Google contacts: {!s}'.format(e)) log.warning('Could not fetch Google contacts: {!s}'.format(e))
else: else:
added_contacts = [] added_contacts = []
modified_contacts = [] modified_contacts = []
...@@ -981,7 +977,7 @@ class GoogleContactsGroup(VirtualGroup): ...@@ -981,7 +977,7 @@ class GoogleContactsGroup(VirtualGroup):
__id__ = 'google_contacts' __id__ = 'google_contacts'
name = Setting(type=unicode, default='Google Contacts') name = Setting(type=str, default='Google Contacts')
contacts = property(lambda self: self.__manager__.contacts) contacts = property(lambda self: self.__manager__.contacts)
def __init__(self): def __init__(self):
...@@ -1012,7 +1008,7 @@ class GoogleContactsGroup(VirtualGroup): ...@@ -1012,7 +1008,7 @@ class GoogleContactsGroup(VirtualGroup):
class DummyContactURI(object): class DummyContactURI(object):
id = property(lambda self: self.uri) id = property(lambda self: self.uri)
def __init__(self, uri, type=u'', default=False): def __init__(self, uri, type='', default=False):
self.uri = uri self.uri = uri
self.type = type self.type = type
self.default = default self.default = default
...@@ -1032,7 +1028,7 @@ class DummyContactURIList(object): ...@@ -1032,7 +1028,7 @@ class DummyContactURIList(object):
return id in self._uri_map return id in self._uri_map
def __iter__(self): def __iter__(self):
return iter(self._uri_map.values()) return iter(list(self._uri_map.values()))
def __len__(self): def __len__(self):
return len(self._uri_map) return len(self._uri_map)
...@@ -1266,7 +1262,7 @@ class Contact(object): ...@@ -1266,7 +1262,7 @@ class Contact(object):
self.__dict__.update(state) self.__dict__.update(state)
def __unicode__(self): def __unicode__(self):
return self.name or u'' return self.name or ''
@property @property
def type(self): def type(self):
...@@ -1290,7 +1286,7 @@ class Contact(object): ...@@ -1290,7 +1286,7 @@ class Contact(object):
if self.type == 'bonjour': if self.type == 'bonjour':
return '%s (%s)' % (self.settings.name, self.settings.hostname) return '%s (%s)' % (self.settings.name, self.settings.hostname)
elif self.type == 'google': elif self.type == 'google':
return self.settings.name or self.settings.organization or u'' return self.settings.name or self.settings.organization or ''
else: else:
return self.settings.name return self.settings.name
...@@ -1306,7 +1302,7 @@ class Contact(object): ...@@ -1306,7 +1302,7 @@ class Contact(object):
try: try:
return self.note or ('@' + self.uri.uri.host if self.type == 'bonjour' else self.uri.uri) return self.note or ('@' + self.uri.uri.host if self.type == 'bonjour' else self.uri.uri)
except AttributeError: except AttributeError:
return u'' return ''
@property @property
def uris(self): def uris(self):
...@@ -1422,7 +1418,7 @@ class ContactDetail(object): ...@@ -1422,7 +1418,7 @@ class ContactDetail(object):
self.__dict__.update(state) self.__dict__.update(state)
def __unicode__(self): def __unicode__(self):
return self.name or u'' return self.name or ''
@property @property
def type(self): def type(self):
...@@ -1446,7 +1442,7 @@ class ContactDetail(object): ...@@ -1446,7 +1442,7 @@ class ContactDetail(object):
if self.type == 'bonjour': if self.type == 'bonjour':
return '%s (%s)' % (self.settings.name, self.settings.hostname) return '%s (%s)' % (self.settings.name, self.settings.hostname)
elif self.type == 'google': elif self.type == 'google':
return self.settings.name or self.settings.organization or u'' return self.settings.name or self.settings.organization or ''
else: else:
return self.settings.name return self.settings.name
...@@ -1462,7 +1458,7 @@ class ContactDetail(object): ...@@ -1462,7 +1458,7 @@ class ContactDetail(object):
try: try:
return self.note or ('@' + self.uri.uri.host if self.type == 'bonjour' else self.uri.uri) return self.note or ('@' + self.uri.uri.host if self.type == 'bonjour' else self.uri.uri)
except AttributeError: except AttributeError:
return u'' return ''
@property @property
def uris(self): def uris(self):
...@@ -1583,7 +1579,7 @@ class ContactURI(object): ...@@ -1583,7 +1579,7 @@ class ContactURI(object):
self.__dict__.update(state) self.__dict__.update(state)
def __unicode__(self): def __unicode__(self):
return u'%s (%s)' % (self.uri.uri, self.uri.type) if self.uri.type else unicode(self.uri.uri) return '%s (%s)' % (self.uri.uri, self.uri.type) if self.uri.type else str(self.uri.uri)
def handle_notification(self, notification): def handle_notification(self, notification):
handler = getattr(self, '_NH_%s' % notification.name, Null) handler = getattr(self, '_NH_%s' % notification.name, Null)
...@@ -1811,7 +1807,7 @@ class ContactDelegate(QStyledItemDelegate, ColorHelperMixin): ...@@ -1811,7 +1807,7 @@ class ContactDelegate(QStyledItemDelegate, ColorHelperMixin):
def _update_list_view(self, group, collapsed): def _update_list_view(self, group, collapsed):
list_view = self.parent() list_view = self.parent()
list_items = list_view.model().items list_items = list_view.model().items
for position in xrange(list_items.index(group)+1, len(list_items)): for position in range(list_items.index(group)+1, len(list_items)):
if isinstance(list_items[position], Group): if isinstance(list_items[position], Group):
break break
list_view.setRowHidden(position, collapsed) list_view.setRowHidden(position, collapsed)
...@@ -2114,7 +2110,7 @@ class Operation(object): ...@@ -2114,7 +2110,7 @@ class Operation(object):
__priority__ = None __priority__ = None
def __init__(self, **params): def __init__(self, **params):
for name, value in params.iteritems(): for name, value in params.items():
setattr(self, name, value) setattr(self, name, value)
for param in set(self.__params__).difference(params): for param in set(self.__params__).difference(params):
raise ValueError("missing operation parameter: '%s'" % param) raise ValueError("missing operation parameter: '%s'" % param)
...@@ -2146,7 +2142,7 @@ class RecallState(object): ...@@ -2146,7 +2142,7 @@ class RecallState(object):
def _normalize_state(self, state): def _normalize_state(self, state):
normalized_state = {} normalized_state = {}
for key, value in state.iteritems(): for key, value in state.items():
if isinstance(value, dict): if isinstance(value, dict):
normalized_state[key] = self._normalize_state(value) normalized_state[key] = self._normalize_state(value)
elif value is not DefaultValue: elif value is not DefaultValue:
...@@ -2154,9 +2150,9 @@ class RecallState(object): ...@@ -2154,9 +2150,9 @@ class RecallState(object):
return normalized_state return normalized_state
class GroupList: __metaclass__ = MarkerType class GroupList(metaclass=MarkerType): pass
class GroupElement: __metaclass__ = MarkerType class GroupElement(metaclass=MarkerType): pass
class GroupContacts: __metaclass__ = MarkerType class GroupContacts(metaclass=MarkerType): pass
class GroupContactList(tuple): class GroupContactList(tuple):
...@@ -2169,7 +2165,7 @@ class GroupContactList(tuple): ...@@ -2169,7 +2165,7 @@ class GroupContactList(tuple):
return item in self.__contactmap__ or tuple.__contains__(self, item) return item in self.__contactmap__ or tuple.__contains__(self, item)
def __getitem__(self, index): def __getitem__(self, index):
if isinstance(index, (int, long, slice)): if isinstance(index, (int, slice)):
return tuple.__getitem__(self, index) return tuple.__getitem__(self, index)
else: else:
return self.__contactmap__[index] return self.__contactmap__[index]
...@@ -2319,7 +2315,7 @@ class ContactModel(QAbstractListModel): ...@@ -2319,7 +2315,7 @@ class ContactModel(QAbstractListModel):
elif role == Qt.SizeHintRole: elif role == Qt.SizeHintRole:
return item.size_hint return item.size_hint
elif role == Qt.DisplayRole: elif role == Qt.DisplayRole:
return unicode(item) return str(item)
return None return None
def supportedDropActions(self): def supportedDropActions(self):
...@@ -2638,7 +2634,7 @@ class ContactModel(QAbstractListModel): ...@@ -2638,7 +2634,7 @@ class ContactModel(QAbstractListModel):
contact.name = name contact.name = name
contact.preferred_media = preferred_media contact.preferred_media = preferred_media
contact.uris = [addressbook.ContactURI(uri=uri, type='SIP')] contact.uris = [addressbook.ContactURI(uri=uri, type='SIP')]
contact.icon = IconDescriptor(FileURL(icon), unicode(int(os.stat(icon).st_mtime))) contact.icon = IconDescriptor(FileURL(icon), str(int(os.stat(icon).st_mtime)))
icon_manager = IconManager() icon_manager = IconManager()
icon_manager.store_file(id, icon) icon_manager.store_file(id, icon)
return contact return contact
...@@ -2658,7 +2654,7 @@ class ContactModel(QAbstractListModel): ...@@ -2658,7 +2654,7 @@ class ContactModel(QAbstractListModel):
contact.uris.default = uri contact.uris.default = uri
modified = True modified = True
if 'icon' in data: if 'icon' in data:
icon_descriptor = IconDescriptor(FileURL(data['icon']), unicode(int(os.stat(data['icon']).st_mtime))) icon_descriptor = IconDescriptor(FileURL(data['icon']), str(int(os.stat(data['icon']).st_mtime)))
if contact.icon != icon_descriptor: if contact.icon != icon_descriptor:
icon_manager = IconManager() icon_manager = IconManager()
icon_manager.store_file(contact.id, data['icon']) icon_manager.store_file(contact.id, data['icon'])
...@@ -2674,7 +2670,7 @@ class ContactModel(QAbstractListModel): ...@@ -2674,7 +2670,7 @@ class ContactModel(QAbstractListModel):
next_ok = next_item is None or isinstance(next_item, Group) or next_item >= contact next_ok = next_item is None or isinstance(next_item, Group) or next_item >= contact
if prev_ok and next_ok: if prev_ok and next_ok:
return None return None
for position in xrange(self.items.index(contact.group)+1, len(self.items)): for position in range(self.items.index(contact.group)+1, len(self.items)):
item = self.items[position] item = self.items[position]
if isinstance(item, Group) or item > contact: if isinstance(item, Group) or item > contact:
break break
...@@ -2683,7 +2679,7 @@ class ContactModel(QAbstractListModel): ...@@ -2683,7 +2679,7 @@ class ContactModel(QAbstractListModel):
return position return position
def _find_contact_insertion_point(self, contact): def _find_contact_insertion_point(self, contact):
for position in xrange(self.items.index(contact.group)+1, len(self.items)): for position in range(self.items.index(contact.group)+1, len(self.items)):
item = self.items[position] item = self.items[position]
if isinstance(item, Group) or item > contact: if isinstance(item, Group) or item > contact:
break break
...@@ -2856,7 +2852,7 @@ class ContactSearchModel(QSortFilterProxyModel): ...@@ -2856,7 +2852,7 @@ class ContactSearchModel(QSortFilterProxyModel):
if isinstance(item, Group) or not item.group.virtual: if isinstance(item, Group) or not item.group.virtual:
return False return False
search_tokens = self.filterRegExp().pattern().lower().split() search_tokens = self.filterRegExp().pattern().lower().split()
searched_item = u' '.join([item.name] + [uri.uri for uri in item.uris]).lower() # should we only search in the username part of the uris? -Dan searched_item = ' '.join([item.name] + [uri.uri for uri in item.uris]).lower() # should we only search in the username part of the uris? -Dan
return all(token in searched_item for token in search_tokens) return all(token in searched_item for token in search_tokens)
def lessThan(self, left_index, right_index): def lessThan(self, left_index, right_index):
...@@ -2970,7 +2966,7 @@ class ContactDetailModel(QAbstractListModel): ...@@ -2970,7 +2966,7 @@ class ContactDetailModel(QAbstractListModel):
if role == Qt.UserRole: if role == Qt.UserRole:
return item return item
elif role == Qt.DisplayRole: elif role == Qt.DisplayRole:
return unicode(item) return str(item)
elif role == Qt.SizeHintRole: elif role == Qt.SizeHintRole:
return item.size_hint return item.size_hint
elif role == Qt.CheckStateRole and row > 0: elif role == Qt.CheckStateRole and row > 0:
...@@ -3447,7 +3443,7 @@ class ContactListView(QListView): ...@@ -3447,7 +3443,7 @@ class ContactListView(QListView):
def _AH_SendFiles(self): def _AH_SendFiles(self):
session_manager = SessionManager() session_manager = SessionManager()
contact = self.selectionModel().selectedIndexes()[0].data(Qt.UserRole) contact = self.selectionModel().selectedIndexes()[0].data(Qt.UserRole)
for filename in QFileDialog.getOpenFileNames(self, u'Select File(s)', session_manager.send_file_directory, u'Any file (*.*)')[0]: for filename in QFileDialog.getOpenFileNames(self, 'Select File(s)', session_manager.send_file_directory, 'Any file (*.*)')[0]:
session_manager.send_file(contact, contact.uri, filename) session_manager.send_file(contact, contact.uri, filename)
def _AH_RequestScreen(self): def _AH_RequestScreen(self):
...@@ -3837,7 +3833,7 @@ class ContactSearchListView(QListView): ...@@ -3837,7 +3833,7 @@ class ContactSearchListView(QListView):
def _AH_SendFiles(self): def _AH_SendFiles(self):
session_manager = SessionManager() session_manager = SessionManager()
contact = self.selectionModel().selectedIndexes()[0].data(Qt.UserRole) contact = self.selectionModel().selectedIndexes()[0].data(Qt.UserRole)
for filename in QFileDialog.getOpenFileNames(self, u'Select File(s)', session_manager.send_file_directory, u'Any file (*.*)')[0]: for filename in QFileDialog.getOpenFileNames(self, 'Select File(s)', session_manager.send_file_directory, 'Any file (*.*)')[0]:
session_manager.send_file(contact, contact.uri, filename) session_manager.send_file(contact, contact.uri, filename)
def _AH_RequestScreen(self): def _AH_RequestScreen(self):
...@@ -4145,7 +4141,7 @@ class ContactDetailView(QListView): ...@@ -4145,7 +4141,7 @@ class ContactDetailView(QListView):
selected_uri = item.uri selected_uri = item.uri
else: else:
selected_uri = contact.uri selected_uri = contact.uri
for filename in QFileDialog.getOpenFileNames(self, u'Select File(s)', session_manager.send_file_directory, u'Any file (*.*)')[0]: for filename in QFileDialog.getOpenFileNames(self, 'Select File(s)', session_manager.send_file_directory, 'Any file (*.*)')[0]:
session_manager.send_file(contact, selected_uri, filename) session_manager.send_file(contact, selected_uri, filename)
def _AH_RequestScreen(self): def _AH_RequestScreen(self):
...@@ -4395,12 +4391,12 @@ class ContactURIModel(QAbstractTableModel): ...@@ -4395,12 +4391,12 @@ class ContactURIModel(QAbstractTableModel):
return item return item
elif role == Qt.DisplayRole: elif role == Qt.DisplayRole:
if column == ContactURIModel.AddressColumn: if column == ContactURIModel.AddressColumn:
return 'Edit to add address' if item.ghost else unicode(item.uri or u'') return 'Edit to add address' if item.ghost else str(item.uri or '')
elif role == Qt.EditRole: elif role == Qt.EditRole:
if column == ContactURIModel.AddressColumn: if column == ContactURIModel.AddressColumn:
return unicode(item.uri or u'') return str(item.uri or '')
elif column == ContactURIModel.TypeColumn: elif column == ContactURIModel.TypeColumn:
return item.type or u'' return item.type or ''
elif column == ContactURIModel.DefaultColumn: elif column == ContactURIModel.DefaultColumn:
return item.default return item.default
elif role == Qt.ForegroundRole: elif role == Qt.ForegroundRole:
...@@ -4567,15 +4563,15 @@ class ContactEditorDialog(base_class, ui_class): ...@@ -4567,15 +4563,15 @@ class ContactEditorDialog(base_class, ui_class):
self.preferred_media.setItemData(3, 'audio+chat') self.preferred_media.setItemData(3, 'audio+chat')
self.addresses_table.verticalHeader().setDefaultSectionSize(URITypeComboBox().sizeHint().height()) self.addresses_table.verticalHeader().setDefaultSectionSize(URITypeComboBox().sizeHint().height())
def open_for_add(self, sip_address=u'', target_group=None): def open_for_add(self, sip_address='', target_group=None):
self.edited_contact = None self.edited_contact = None
self.target_group = target_group self.target_group = target_group
self.contact_uri_model.init_with_address(sip_address) self.contact_uri_model.init_with_address(sip_address)
self.name_editor.setText(u'') self.name_editor.setText('')
self.icon_selector.init_with_contact(None) self.icon_selector.init_with_contact(None)
self.presence.setChecked(True) self.presence.setChecked(True)
self.preferred_media.setCurrentIndex(0) self.preferred_media.setCurrentIndex(0)
self.accept_button.setText(u'Add') self.accept_button.setText('Add')
self.accept_button.setEnabled(False) self.accept_button.setEnabled(False)
self.show() self.show()
...@@ -4588,12 +4584,12 @@ class ContactEditorDialog(base_class, ui_class): ...@@ -4588,12 +4584,12 @@ class ContactEditorDialog(base_class, ui_class):
self.icon_selector.init_with_contact(contact) self.icon_selector.init_with_contact(contact)
self.presence.setChecked(contact.presence.subscribe) self.presence.setChecked(contact.presence.subscribe)
self.preferred_media.setCurrentIndex(self.preferred_media.findData(contact.preferred_media)) self.preferred_media.setCurrentIndex(self.preferred_media.findData(contact.preferred_media))
self.accept_button.setText(u'Ok') self.accept_button.setText('Ok')
self.accept_button.setEnabled(True) self.accept_button.setEnabled(True)
self.show() self.show()
def _SH_NameEditorTextChanged(self, text): def _SH_NameEditorTextChanged(self, text):
self.accept_button.setEnabled(text != u'') self.accept_button.setEnabled(text != '')
def _SH_Accepted(self): def _SH_Accepted(self):
if self.edited_contact is not None: if self.edited_contact is not None:
...@@ -4636,7 +4632,7 @@ class ContactEditorDialog(base_class, ui_class): ...@@ -4636,7 +4632,7 @@ class ContactEditorDialog(base_class, ui_class):
icon_manager.remove(contact.id + '_alt') icon_manager.remove(contact.id + '_alt')
contact.alternate_icon = None contact.alternate_icon = None
else: else:
icon_descriptor = IconDescriptor(FileURL(self.icon_selector.filename), unicode(int(os.stat(self.icon_selector.filename).st_mtime))) icon_descriptor = IconDescriptor(FileURL(self.icon_selector.filename), str(int(os.stat(self.icon_selector.filename).st_mtime)))
if contact.alternate_icon != icon_descriptor: if contact.alternate_icon != icon_descriptor:
icon_manager.store_file(contact.id + '_alt', icon_descriptor.url.path) icon_manager.store_file(contact.id + '_alt', icon_descriptor.url.path)
contact.alternate_icon = icon_descriptor contact.alternate_icon = icon_descriptor
......
...@@ -13,9 +13,7 @@ class EventMeta(type(QEvent)): ...@@ -13,9 +13,7 @@ class EventMeta(type(QEvent)):
cls.id = QEvent.registerEventType() if name != 'EventBase' else None cls.id = QEvent.registerEventType() if name != 'EventBase' else None
class EventBase(QEvent): class EventBase(QEvent, metaclass=EventMeta):
__metaclass__ = EventMeta
def __new__(cls, *args, **kw): def __new__(cls, *args, **kw):
if cls is EventBase: if cls is EventBase:
raise TypeError("EventBase cannot be directly instantiated") raise TypeError("EventBase cannot be directly instantiated")
......
...@@ -66,9 +66,9 @@ class FileTransferWindow(base_class, ui_class): ...@@ -66,9 +66,9 @@ class FileTransferWindow(base_class, ui_class):
def update_status(self): def update_status(self):
total = len(self.model.items) total = len(self.model.items)
active = len([item for item in self.model.items if not item.ended]) active = len([item for item in self.model.items if not item.ended])
text = u'%d %s' % (total, 'transfer' if total == 1 else 'transfers') text = '%d %s' % (total, 'transfer' if total == 1 else 'transfers')
if active > 0: if active > 0:
text += u' (%d active)' % active text += ' (%d active)' % active
self.status_label.setText(text) self.status_label.setText(text)
def handle_notification(self, notification): def handle_notification(self, notification):
......
import bisect import bisect
import cPickle as pickle import pickle as pickle
import re import re
from PyQt5.QtGui import QIcon from PyQt5.QtGui import QIcon
...@@ -24,8 +24,7 @@ from blink.util import run_in_gui_thread ...@@ -24,8 +24,7 @@ from blink.util import run_in_gui_thread
__all__ = ['HistoryManager'] __all__ = ['HistoryManager']
class HistoryManager(object): class HistoryManager(object, metaclass=Singleton):
__metaclass__ = Singleton
implements(IObserver) implements(IObserver)
history_size = 20 history_size = 20
...@@ -149,7 +148,7 @@ class HistoryEntry(object): ...@@ -149,7 +148,7 @@ class HistoryEntry(object):
@property @property
def text(self): def text(self):
result = unicode(self.name or self.uri) result = str(self.name or self.uri)
if self.call_time: if self.call_time:
call_time = self.call_time.astimezone(tzlocal()) call_time = self.call_time.astimezone(tzlocal())
call_date = call_time.date() call_date = call_time.date()
...@@ -195,6 +194,6 @@ class HistoryEntry(object): ...@@ -195,6 +194,6 @@ class HistoryEntry(object):
display_name = session.remote_identity.display_name display_name = session.remote_identity.display_name
else: else:
display_name = contact.name display_name = contact.name
return cls(session.direction, display_name, remote_uri, unicode(session.account.id), call_time, duration) return cls(session.direction, display_name, remote_uri, str(session.account.id), call_time, duration)
...@@ -70,9 +70,7 @@ class LogFile(object): ...@@ -70,9 +70,7 @@ class LogFile(object):
file.close() file.close()
class LogManager(object): class LogManager(object, metaclass=Singleton):
__metaclass__ = Singleton
implements(IObserver) implements(IObserver)
def __init__(self): def __init__(self):
......
...@@ -63,7 +63,7 @@ class MainWindow(base_class, ui_class): ...@@ -63,7 +63,7 @@ class MainWindow(base_class, ui_class):
self.pending_watcher_dialogs = [] self.pending_watcher_dialogs = []
self.mwi_icons = [QIcon(Resources.get('icons/mwi-%d.png' % i)) for i in xrange(0, 11)] self.mwi_icons = [QIcon(Resources.get('icons/mwi-%d.png' % i)) for i in range(0, 11)]
self.mwi_icons.append(QIcon(Resources.get('icons/mwi-many.png'))) self.mwi_icons.append(QIcon(Resources.get('icons/mwi-many.png')))
with Resources.directory: with Resources.directory:
...@@ -176,12 +176,12 @@ class MainWindow(base_class, ui_class): ...@@ -176,12 +176,12 @@ class MainWindow(base_class, ui_class):
self.about_action.triggered.connect(self.about_panel.show) self.about_action.triggered.connect(self.about_panel.show)
self.add_account_action.triggered.connect(self.preferences_window.show_add_account_dialog) self.add_account_action.triggered.connect(self.preferences_window.show_add_account_dialog)
self.manage_accounts_action.triggered.connect(self.preferences_window.show_for_accounts) self.manage_accounts_action.triggered.connect(self.preferences_window.show_for_accounts)
self.help_action.triggered.connect(partial(QDesktopServices.openUrl, QUrl(u'http://icanblink.com/help/'))) self.help_action.triggered.connect(partial(QDesktopServices.openUrl, QUrl('http://icanblink.com/help/')))
self.preferences_action.triggered.connect(self.preferences_window.show) self.preferences_action.triggered.connect(self.preferences_window.show)
self.auto_accept_chat_action.triggered.connect(self._AH_AutoAcceptChatActionTriggered) self.auto_accept_chat_action.triggered.connect(self._AH_AutoAcceptChatActionTriggered)
self.received_messages_sound_action.triggered.connect(self._AH_ReceivedMessagesSoundActionTriggered) self.received_messages_sound_action.triggered.connect(self._AH_ReceivedMessagesSoundActionTriggered)
self.answering_machine_action.triggered.connect(self._AH_EnableAnsweringMachineActionTriggered) self.answering_machine_action.triggered.connect(self._AH_EnableAnsweringMachineActionTriggered)
self.release_notes_action.triggered.connect(partial(QDesktopServices.openUrl, QUrl(u'http://icanblink.com/changelog/'))) self.release_notes_action.triggered.connect(partial(QDesktopServices.openUrl, QUrl('http://icanblink.com/changelog/')))
self.quit_action.triggered.connect(self._AH_QuitActionTriggered) self.quit_action.triggered.connect(self._AH_QuitActionTriggered)
# Call menu actions # Call menu actions
...@@ -265,8 +265,8 @@ class MainWindow(base_class, ui_class): ...@@ -265,8 +265,8 @@ class MainWindow(base_class, ui_class):
action_map = {} action_map = {}
action = action_map[u'system_default'] = self.output_device_menu.addAction(u'System default') action = action_map['system_default'] = self.output_device_menu.addAction('System default')
action.setData(u'system_default') action.setData('system_default')
action.setCheckable(True) action.setCheckable(True)
self.output_devices_group.addAction(action) self.output_devices_group.addAction(action)
...@@ -278,7 +278,7 @@ class MainWindow(base_class, ui_class): ...@@ -278,7 +278,7 @@ class MainWindow(base_class, ui_class):
action.setCheckable(True) action.setCheckable(True)
self.output_devices_group.addAction(action) self.output_devices_group.addAction(action)
action = action_map[None] = self.output_device_menu.addAction(u'None') action = action_map[None] = self.output_device_menu.addAction('None')
action.setData(None) action.setData(None)
action.setCheckable(True) action.setCheckable(True)
self.output_devices_group.addAction(action) self.output_devices_group.addAction(action)
...@@ -288,8 +288,8 @@ class MainWindow(base_class, ui_class): ...@@ -288,8 +288,8 @@ class MainWindow(base_class, ui_class):
action_map = {} action_map = {}
action = action_map[u'system_default'] = self.input_device_menu.addAction(u'System default') action = action_map['system_default'] = self.input_device_menu.addAction('System default')
action.setData(u'system_default') action.setData('system_default')
action.setCheckable(True) action.setCheckable(True)
self.input_devices_group.addAction(action) self.input_devices_group.addAction(action)
...@@ -301,7 +301,7 @@ class MainWindow(base_class, ui_class): ...@@ -301,7 +301,7 @@ class MainWindow(base_class, ui_class):
action.setCheckable(True) action.setCheckable(True)
self.input_devices_group.addAction(action) self.input_devices_group.addAction(action)
action = action_map[None] = self.input_device_menu.addAction(u'None') action = action_map[None] = self.input_device_menu.addAction('None')
action.setData(None) action.setData(None)
action.setCheckable(True) action.setCheckable(True)
self.input_devices_group.addAction(action) self.input_devices_group.addAction(action)
...@@ -311,8 +311,8 @@ class MainWindow(base_class, ui_class): ...@@ -311,8 +311,8 @@ class MainWindow(base_class, ui_class):
action_map = {} action_map = {}
action = action_map[u'system_default'] = self.alert_device_menu.addAction(u'System default') action = action_map['system_default'] = self.alert_device_menu.addAction('System default')
action.setData(u'system_default') action.setData('system_default')
action.setCheckable(True) action.setCheckable(True)
self.alert_devices_group.addAction(action) self.alert_devices_group.addAction(action)
...@@ -324,7 +324,7 @@ class MainWindow(base_class, ui_class): ...@@ -324,7 +324,7 @@ class MainWindow(base_class, ui_class):
action.setCheckable(True) action.setCheckable(True)
self.alert_devices_group.addAction(action) self.alert_devices_group.addAction(action)
action = action_map[None] = self.alert_device_menu.addAction(u'None') action = action_map[None] = self.alert_device_menu.addAction('None')
action.setData(None) action.setData(None)
action.setCheckable(True) action.setCheckable(True)
self.alert_devices_group.addAction(action) self.alert_devices_group.addAction(action)
...@@ -337,8 +337,8 @@ class MainWindow(base_class, ui_class): ...@@ -337,8 +337,8 @@ class MainWindow(base_class, ui_class):
action_map = {} action_map = {}
action = action_map[u'system_default'] = self.video_camera_menu.addAction(u'System default') action = action_map['system_default'] = self.video_camera_menu.addAction('System default')
action.setData(u'system_default') action.setData('system_default')
action.setCheckable(True) action.setCheckable(True)
self.video_devices_group.addAction(action) self.video_devices_group.addAction(action)
...@@ -350,7 +350,7 @@ class MainWindow(base_class, ui_class): ...@@ -350,7 +350,7 @@ class MainWindow(base_class, ui_class):
action.setCheckable(True) action.setCheckable(True)
self.video_devices_group.addAction(action) self.video_devices_group.addAction(action)
action = action_map[None] = self.video_camera_menu.addAction(u'None') action = action_map[None] = self.video_camera_menu.addAction('None')
action.setData(None) action.setData(None)
action.setCheckable(True) action.setCheckable(True)
self.video_devices_group.addAction(action) self.video_devices_group.addAction(action)
...@@ -488,11 +488,11 @@ class MainWindow(base_class, ui_class): ...@@ -488,11 +488,11 @@ class MainWindow(base_class, ui_class):
def _SH_AccountStateChanged(self): def _SH_AccountStateChanged(self):
self.activity_note.setText(self.account_state.note) self.activity_note.setText(self.account_state.note)
if self.account_state.state is AccountState.Invisible: if self.account_state.state is AccountState.Invisible:
self.activity_note.inactiveText = u'(invisible)' self.activity_note.inactiveText = '(invisible)'
self.activity_note.setEnabled(False) self.activity_note.setEnabled(False)
else: else:
if not self.activity_note.isEnabled(): if not self.activity_note.isEnabled():
self.activity_note.inactiveText = u'Add an activity note here' self.activity_note.inactiveText = 'Add an activity note here'
self.activity_note.setEnabled(True) self.activity_note.setEnabled(True)
if not self.account_state.state.internal: if not self.account_state.state.internal:
self.saved_account_state = None self.saved_account_state = None
...@@ -502,7 +502,7 @@ class MainWindow(base_class, ui_class): ...@@ -502,7 +502,7 @@ class MainWindow(base_class, ui_class):
blink_settings.save() blink_settings.save()
def _SH_AccountStateClicked(self, checked): def _SH_AccountStateClicked(self, checked):
filename = QFileDialog.getOpenFileName(self, u'Select Icon', self.last_icon_directory, u"Images (*.png *.tiff *.jpg *.xmp *.svg)")[0] filename = QFileDialog.getOpenFileName(self, 'Select Icon', self.last_icon_directory, "Images (*.png *.tiff *.jpg *.xmp *.svg)")[0]
if filename: if filename:
self.last_icon_directory = os.path.dirname(filename) self.last_icon_directory = os.path.dirname(filename)
filename = filename if os.path.realpath(filename) != os.path.realpath(self.default_icon_path) else None filename = filename if os.path.realpath(filename) != os.path.realpath(self.default_icon_path) else None
...@@ -644,7 +644,7 @@ class MainWindow(base_class, ui_class): ...@@ -644,7 +644,7 @@ class MainWindow(base_class, ui_class):
def _SH_IdentityCurrentIndexChanged(self, index): def _SH_IdentityCurrentIndexChanged(self, index):
if index != -1: if index != -1:
account = self.identity.itemData(index).account account = self.identity.itemData(index).account
self.display_name.setText(account.display_name or u'') self.display_name.setText(account.display_name or '')
self.display_name.setEnabled(True) self.display_name.setEnabled(True)
self.activity_note.setEnabled(True) self.activity_note.setEnabled(True)
self.account_state.setEnabled(True) self.account_state.setEnabled(True)
...@@ -720,7 +720,7 @@ class MainWindow(base_class, ui_class): ...@@ -720,7 +720,7 @@ class MainWindow(base_class, ui_class):
def _SH_AudioSessionModelChangedStructure(self): def _SH_AudioSessionModelChangedStructure(self):
active_sessions = self.session_model.active_sessions active_sessions = self.session_model.active_sessions
self.active_sessions_label.setText(u'There is 1 active call' if len(active_sessions) == 1 else u'There are %d active calls' % len(active_sessions)) self.active_sessions_label.setText('There is 1 active call' if len(active_sessions) == 1 else 'There are %d active calls' % len(active_sessions))
self.active_sessions_label.setVisible(any(active_sessions)) self.active_sessions_label.setVisible(any(active_sessions))
self.hangup_all_button.setEnabled(any(active_sessions)) self.hangup_all_button.setEnabled(any(active_sessions))
selected_indexes = self.session_list.selectionModel().selectedIndexes() selected_indexes = self.session_list.selectionModel().selectedIndexes()
...@@ -735,7 +735,7 @@ class MainWindow(base_class, ui_class): ...@@ -735,7 +735,7 @@ class MainWindow(base_class, ui_class):
if self.account_state.state is not AccountState.Invisible: if self.account_state.state is not AccountState.Invisible:
if self.saved_account_state is None: if self.saved_account_state is None:
self.saved_account_state = self.account_state.state, self.activity_note.text() self.saved_account_state = self.account_state.state, self.activity_note.text()
self.account_state.setState(AccountState.Busy.Internal, note=u'On the phone') self.account_state.setState(AccountState.Busy.Internal, note='On the phone')
elif self.saved_account_state is not None: elif self.saved_account_state is not None:
state, note = self.saved_account_state state, note = self.saved_account_state
self.saved_account_state = None self.saved_account_state = None
...@@ -772,9 +772,9 @@ class MainWindow(base_class, ui_class): ...@@ -772,9 +772,9 @@ class MainWindow(base_class, ui_class):
self.auto_accept_chat_action.setChecked(settings.chat.auto_accept) self.auto_accept_chat_action.setChecked(settings.chat.auto_accept)
self.received_messages_sound_action.setChecked(settings.sounds.play_message_alerts) self.received_messages_sound_action.setChecked(settings.sounds.play_message_alerts)
if settings.google_contacts.enabled: if settings.google_contacts.enabled:
self.google_contacts_action.setText(u'Disable &Google Contacts') self.google_contacts_action.setText('Disable &Google Contacts')
else: else:
self.google_contacts_action.setText(u'Enable &Google Contacts...') self.google_contacts_action.setText('Enable &Google Contacts...')
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)
...@@ -846,9 +846,9 @@ class MainWindow(base_class, ui_class): ...@@ -846,9 +846,9 @@ class MainWindow(base_class, ui_class):
self.received_messages_sound_action.setChecked(settings.sounds.play_message_alerts) self.received_messages_sound_action.setChecked(settings.sounds.play_message_alerts)
if 'google_contacts.enabled' in notification.data.modified: if 'google_contacts.enabled' in notification.data.modified:
if notification.sender.google_contacts.enabled: if notification.sender.google_contacts.enabled:
self.google_contacts_action.setText(u'Disable &Google Contacts') self.google_contacts_action.setText('Disable &Google Contacts')
else: else:
self.google_contacts_action.setText(u'Enable &Google Contacts...') self.google_contacts_action.setText('Enable &Google Contacts...')
elif notification.sender is blink_settings: elif notification.sender is blink_settings:
if 'presence.current_state' in notification.data.modified: if 'presence.current_state' in notification.data.modified:
state = getattr(AccountState, blink_settings.presence.current_state.state, AccountState.Available) state = getattr(AccountState, blink_settings.presence.current_state.state, AccountState.Available)
...@@ -865,7 +865,7 @@ class MainWindow(base_class, ui_class): ...@@ -865,7 +865,7 @@ class MainWindow(base_class, ui_class):
action = next(action for action in self.accounts_menu.actions() if action.data() is account) action = next(action for action in self.accounts_menu.actions() if action.data() is account)
action.setChecked(account.enabled) action.setChecked(account.enabled)
if 'display_name' in notification.data.modified and account is account_manager.default_account: if 'display_name' in notification.data.modified and account is account_manager.default_account:
self.display_name.setText(account.display_name or u'') self.display_name.setText(account.display_name or '')
if {'enabled', 'message_summary.enabled', 'message_summary.voicemail_uri'}.intersection(notification.data.modified): if {'enabled', 'message_summary.enabled', 'message_summary.voicemail_uri'}.intersection(notification.data.modified):
action = next(action for action in self.voicemail_menu.actions() if action.data() is account) action = next(action for action in self.voicemail_menu.actions() if action.data() is account)
action.setVisible(False if account is BonjourAccount() else account.enabled and account.message_summary.enabled) action.setVisible(False if account is BonjourAccount() else account.enabled and account.message_summary.enabled)
...@@ -874,7 +874,7 @@ class MainWindow(base_class, ui_class): ...@@ -874,7 +874,7 @@ class MainWindow(base_class, ui_class):
def _NH_SIPAccountManagerDidAddAccount(self, notification): def _NH_SIPAccountManagerDidAddAccount(self, notification):
account = notification.data.account account = notification.data.account
action = self.accounts_menu.addAction(account.id if account is not BonjourAccount() else u'Bonjour') action = self.accounts_menu.addAction(account.id if account is not BonjourAccount() else 'Bonjour')
action.setEnabled(True if account is not BonjourAccount() else BonjourAccount.mdns_available) action.setEnabled(True if account is not BonjourAccount() else BonjourAccount.mdns_available)
action.setCheckable(True) action.setCheckable(True)
action.setChecked(account.enabled) action.setChecked(account.enabled)
......
import os import os
import urlparse import urllib.parse
from PyQt5 import uic from PyQt5 import uic
from PyQt5.QtCore import Qt, QEvent, QRegExp from PyQt5.QtCore import Qt, QEvent, QRegExp
...@@ -37,46 +37,46 @@ __all__ = ['PreferencesWindow', 'AccountListView', 'SIPPortEditor'] ...@@ -37,46 +37,46 @@ __all__ = ['PreferencesWindow', 'AccountListView', 'SIPPortEditor']
# #
class IDDPrefixValidator(QRegExpValidator): class IDDPrefixValidator(QRegExpValidator):
def __init__(self, parent=None): def __init__(self, parent=None):
super(IDDPrefixValidator, self).__init__(QRegExp(u'[0-9+*#]+'), parent) super(IDDPrefixValidator, self).__init__(QRegExp('[0-9+*#]+'), parent)
def fixup(self, input): def fixup(self, input):
return super(IDDPrefixValidator, self).fixup(input or u'+') return super(IDDPrefixValidator, self).fixup(input or '+')
class PrefixValidator(QRegExpValidator): class PrefixValidator(QRegExpValidator):
def __init__(self, parent=None): def __init__(self, parent=None):
super(PrefixValidator, self).__init__(QRegExp(u'(None|[0-9+*#]+)'), parent) super(PrefixValidator, self).__init__(QRegExp('(None|[0-9+*#]+)'), parent)
def fixup(self, input): def fixup(self, input):
return super(PrefixValidator, self).fixup(input or u'None') return super(PrefixValidator, self).fixup(input or 'None')
class HostnameValidator(QRegExpValidator): class HostnameValidator(QRegExpValidator):
def __init__(self, parent=None): def __init__(self, parent=None):
super(HostnameValidator, self).__init__(QRegExp(u'^([\w\-_]+(\.[\w\-_]+)*)?$', Qt.CaseInsensitive), parent) super(HostnameValidator, self).__init__(QRegExp('^([\w\-_]+(\.[\w\-_]+)*)?$', Qt.CaseInsensitive), parent)
class SIPAddressValidator(QRegExpValidator): class SIPAddressValidator(QRegExpValidator):
def __init__(self, parent=None): def __init__(self, parent=None):
super(SIPAddressValidator, self).__init__(QRegExp(u'^([\w\-_+%]+@[\w\-_]+(\.[\w\-_]+)*)?$', Qt.CaseInsensitive), parent) super(SIPAddressValidator, self).__init__(QRegExp('^([\w\-_+%]+@[\w\-_]+(\.[\w\-_]+)*)?$', Qt.CaseInsensitive), parent)
def fixup(self, input): def fixup(self, input):
if input and '@' not in input: if input and '@' not in input:
preferences_window = self.parent() preferences_window = self.parent()
input += u'@%s' % preferences_window.selected_account.id.domain input += '@%s' % preferences_window.selected_account.id.domain
return super(SIPAddressValidator, self).fixup(input) return super(SIPAddressValidator, self).fixup(input)
class WebURLValidator(QRegExpValidator): class WebURLValidator(QRegExpValidator):
def __init__(self, parent=None): def __init__(self, parent=None):
super(WebURLValidator, self).__init__(QRegExp(u'^(https?://[\w\-_]+(\.[\w\-_]+)*(:\d+)?(/.*)?)?$', Qt.CaseInsensitive), parent) super(WebURLValidator, self).__init__(QRegExp('^(https?://[\w\-_]+(\.[\w\-_]+)*(:\d+)?(/.*)?)?$', Qt.CaseInsensitive), parent)
class XCAPRootValidator(WebURLValidator): class XCAPRootValidator(WebURLValidator):
def fixup(self, input): def fixup(self, input):
url = urlparse.urlparse(input) url = urllib.parse.urlparse(input)
if not (url.scheme and url.netloc): if not (url.scheme and url.netloc):
input = u'' input = ''
return super(XCAPRootValidator, self).fixup(input) return super(XCAPRootValidator, self).fixup(input)
def validate(self, input, pos): def validate(self, input, pos):
...@@ -85,7 +85,7 @@ class XCAPRootValidator(WebURLValidator): ...@@ -85,7 +85,7 @@ class XCAPRootValidator(WebURLValidator):
if input.endswith(('?', ';', '&')): if input.endswith(('?', ';', '&')):
state = QValidator.Invalid state = QValidator.Invalid
else: else:
url = urlparse.urlparse(input) url = urllib.parse.urlparse(input)
if url.params or url.query or url.fragment: if url.params or url.query or url.fragment:
state = QValidator.Invalid state = QValidator.Invalid
elif url.port is not None: elif url.port is not None:
...@@ -164,23 +164,21 @@ class blocked_qt_signals(object): ...@@ -164,23 +164,21 @@ class blocked_qt_signals(object):
class UnspecifiedOutboundProxy(object): class UnspecifiedOutboundProxy(object):
host = u'' host = ''
port = 5060 port = 5060
transport = u'UDP' transport = 'UDP'
class UnspecifiedMSRPRelay(object): class UnspecifiedMSRPRelay(object):
host = u'' host = ''
port = 0 port = 0
transport = u'TLS' transport = 'TLS'
ui_class, base_class = uic.loadUiType(Resources.get('preferences.ui')) ui_class, base_class = uic.loadUiType(Resources.get('preferences.ui'))
class PreferencesWindow(base_class, ui_class): class PreferencesWindow(base_class, ui_class, metaclass=QSingleton):
__metaclass__ = QSingleton
implements(IObserver) implements(IObserver)
def __init__(self, account_model, parent=None): def __init__(self, account_model, parent=None):
...@@ -343,10 +341,10 @@ class PreferencesWindow(base_class, ui_class): ...@@ -343,10 +341,10 @@ class PreferencesWindow(base_class, ui_class):
# Accounts # Accounts
self.key_negotiation_button.clear() self.key_negotiation_button.clear()
self.key_negotiation_button.addItem(u'Opportunistic', 'opportunistic') self.key_negotiation_button.addItem('Opportunistic', 'opportunistic')
self.key_negotiation_button.addItem(u'ZRTP', 'zrtp') self.key_negotiation_button.addItem('ZRTP', 'zrtp')
self.key_negotiation_button.addItem(u'SDES optional', 'sdes_optional') self.key_negotiation_button.addItem('SDES optional', 'sdes_optional')
self.key_negotiation_button.addItem(u'SDES mandatory', 'sdes_mandatory') self.key_negotiation_button.addItem('SDES mandatory', 'sdes_mandatory')
# Audio # Audio
...@@ -404,10 +402,10 @@ class PreferencesWindow(base_class, ui_class): ...@@ -404,10 +402,10 @@ class PreferencesWindow(base_class, ui_class):
action.index = index action.index = index
self.section_group.addAction(action) self.section_group.addAction(action)
for index in xrange(self.idd_prefix_button.count()): for index in range(self.idd_prefix_button.count()):
text = self.idd_prefix_button.itemText(index) text = self.idd_prefix_button.itemText(index)
self.idd_prefix_button.setItemData(index, None if text == "+" else text) self.idd_prefix_button.setItemData(index, None if text == "+" else text)
for index in xrange(self.prefix_button.count()): for index in range(self.prefix_button.count()):
text = self.prefix_button.itemText(index) text = self.prefix_button.itemText(index)
self.prefix_button.setItemData(index, None if text == "None" else text) self.prefix_button.setItemData(index, None if text == "None" else text)
...@@ -467,7 +465,7 @@ class PreferencesWindow(base_class, ui_class): ...@@ -467,7 +465,7 @@ class PreferencesWindow(base_class, ui_class):
combo_box.initStyleOption(option) combo_box.initStyleOption(option)
wide_padding = (combo_box.height() - combo_box.style().subControlRect(QStyle.CC_ComboBox, option, QStyle.SC_ComboBoxEditField, combo_box).height() >= 10) wide_padding = (combo_box.height() - combo_box.style().subControlRect(QStyle.CC_ComboBox, option, QStyle.SC_ComboBoxEditField, combo_box).height() >= 10)
if False and wide_padding: # TODO: review later and decide if its worth or not -Dan if False and wide_padding: # TODO: review later and decide if its worth or not -Dan
print "found wide padding" print("found wide padding")
self.audio_alert_device_button.setStyleSheet("""QComboBox { padding: 4px 4px 4px 4px; }""") self.audio_alert_device_button.setStyleSheet("""QComboBox { padding: 4px 4px 4px 4px; }""")
self.audio_input_device_button.setStyleSheet("""QComboBox { padding: 4px 4px 4px 4px; }""") self.audio_input_device_button.setStyleSheet("""QComboBox { padding: 4px 4px 4px 4px; }""")
self.audio_output_device_button.setStyleSheet("""QComboBox { padding: 4px 4px 4px 4px; }""") self.audio_output_device_button.setStyleSheet("""QComboBox { padding: 4px 4px 4px 4px; }""")
...@@ -594,30 +592,30 @@ class PreferencesWindow(base_class, ui_class): ...@@ -594,30 +592,30 @@ class PreferencesWindow(base_class, ui_class):
class Separator: pass class Separator: pass
self.audio_input_device_button.clear() self.audio_input_device_button.clear()
self.audio_input_device_button.addItem(u'System Default', 'system_default') self.audio_input_device_button.addItem('System Default', 'system_default')
self.audio_input_device_button.insertSeparator(1) self.audio_input_device_button.insertSeparator(1)
self.audio_input_device_button.setItemData(1, Separator) # prevent the separator from being selected (must have different itemData than the None device) self.audio_input_device_button.setItemData(1, Separator) # prevent the separator from being selected (must have different itemData than the None device)
for device in SIPApplication.engine.input_devices: for device in SIPApplication.engine.input_devices:
self.audio_input_device_button.addItem(device, device) self.audio_input_device_button.addItem(device, device)
self.audio_input_device_button.addItem(u'None', None) self.audio_input_device_button.addItem('None', None)
self.audio_input_device_button.setCurrentIndex(self.audio_input_device_button.findData(settings.audio.input_device)) self.audio_input_device_button.setCurrentIndex(self.audio_input_device_button.findData(settings.audio.input_device))
self.audio_output_device_button.clear() self.audio_output_device_button.clear()
self.audio_output_device_button.addItem(u'System Default', 'system_default') self.audio_output_device_button.addItem('System Default', 'system_default')
self.audio_output_device_button.insertSeparator(1) self.audio_output_device_button.insertSeparator(1)
self.audio_output_device_button.setItemData(1, Separator) # prevent the separator from being selected (must have different itemData than the None device) self.audio_output_device_button.setItemData(1, Separator) # prevent the separator from being selected (must have different itemData than the None device)
for device in SIPApplication.engine.output_devices: for device in SIPApplication.engine.output_devices:
self.audio_output_device_button.addItem(device, device) self.audio_output_device_button.addItem(device, device)
self.audio_output_device_button.addItem(u'None', None) self.audio_output_device_button.addItem('None', None)
self.audio_output_device_button.setCurrentIndex(self.audio_output_device_button.findData(settings.audio.output_device)) self.audio_output_device_button.setCurrentIndex(self.audio_output_device_button.findData(settings.audio.output_device))
self.audio_alert_device_button.clear() self.audio_alert_device_button.clear()
self.audio_alert_device_button.addItem(u'System Default', 'system_default') self.audio_alert_device_button.addItem('System Default', 'system_default')
self.audio_alert_device_button.insertSeparator(1) self.audio_alert_device_button.insertSeparator(1)
self.audio_alert_device_button.setItemData(1, Separator) # prevent the separator from being selected (must have different itemData than the None device) self.audio_alert_device_button.setItemData(1, Separator) # prevent the separator from being selected (must have different itemData than the None device)
for device in SIPApplication.engine.output_devices: for device in SIPApplication.engine.output_devices:
self.audio_alert_device_button.addItem(device, device) self.audio_alert_device_button.addItem(device, device)
self.audio_alert_device_button.addItem(u'None', None) self.audio_alert_device_button.addItem('None', None)
self.audio_alert_device_button.setCurrentIndex(self.audio_alert_device_button.findData(settings.audio.alert_device)) self.audio_alert_device_button.setCurrentIndex(self.audio_alert_device_button.findData(settings.audio.alert_device))
def load_video_devices(self): def load_video_devices(self):
...@@ -626,12 +624,12 @@ class PreferencesWindow(base_class, ui_class): ...@@ -626,12 +624,12 @@ class PreferencesWindow(base_class, ui_class):
class Separator: pass class Separator: pass
self.video_camera_button.clear() self.video_camera_button.clear()
self.video_camera_button.addItem(u'System Default', 'system_default') self.video_camera_button.addItem('System Default', 'system_default')
self.video_camera_button.insertSeparator(1) self.video_camera_button.insertSeparator(1)
self.video_camera_button.setItemData(1, Separator) # prevent the separator from being selected (must have different itemData than the None device) self.video_camera_button.setItemData(1, Separator) # prevent the separator from being selected (must have different itemData than the None device)
for device in SIPApplication.engine.video_devices: for device in SIPApplication.engine.video_devices:
self.video_camera_button.addItem(device, device) self.video_camera_button.addItem(device, device)
self.video_camera_button.addItem(u'None', None) self.video_camera_button.addItem('None', None)
self.video_camera_button.setCurrentIndex(self.video_camera_button.findData(settings.video.device)) self.video_camera_button.setCurrentIndex(self.video_camera_button.findData(settings.video.device))
def load_settings(self): def load_settings(self):
...@@ -667,7 +665,7 @@ class PreferencesWindow(base_class, ui_class): ...@@ -667,7 +665,7 @@ class PreferencesWindow(base_class, ui_class):
# Video devices # Video devices
self.load_video_devices() self.load_video_devices()
self.video_resolution_button.setCurrentIndex(self.video_resolution_button.findData(unicode(settings.video.resolution))) self.video_resolution_button.setCurrentIndex(self.video_resolution_button.findData(str(settings.video.resolution)))
self.video_framerate_button.setCurrentIndex(self.video_framerate_button.findData(settings.video.framerate)) self.video_framerate_button.setCurrentIndex(self.video_framerate_button.findData(settings.video.framerate))
# Video codecs # Video codecs
...@@ -677,7 +675,7 @@ class PreferencesWindow(base_class, ui_class): ...@@ -677,7 +675,7 @@ class PreferencesWindow(base_class, ui_class):
item = QListWidgetItem(codec, self.video_codecs_list) item = QListWidgetItem(codec, self.video_codecs_list)
item.setCheckState(Qt.Checked if codec in settings.rtp.video_codec_list else Qt.Unchecked) item.setCheckState(Qt.Checked if codec in settings.rtp.video_codec_list else Qt.Unchecked)
self.h264_profile_button.setCurrentIndex(self.h264_profile_button.findData(unicode(settings.video.h264.profile))) self.h264_profile_button.setCurrentIndex(self.h264_profile_button.findData(str(settings.video.h264.profile)))
self.video_codec_bitrate_button.setCurrentIndex(self.video_codec_bitrate_button.findData(settings.video.max_bitrate)) self.video_codec_bitrate_button.setCurrentIndex(self.video_codec_bitrate_button.findData(settings.video.max_bitrate))
# Chat and SMS settings # Chat and SMS settings
...@@ -748,9 +746,9 @@ class PreferencesWindow(base_class, ui_class): ...@@ -748,9 +746,9 @@ class PreferencesWindow(base_class, ui_class):
with blocked_qt_signals(self.media_ports): with blocked_qt_signals(self.media_ports):
self.media_ports.setValue(settings.rtp.port_range.end - settings.rtp.port_range.start) self.media_ports.setValue(settings.rtp.port_range.end - settings.rtp.port_range.start)
self.screenshots_directory_editor.setText(blink_settings.screenshots_directory or u'') self.screenshots_directory_editor.setText(blink_settings.screenshots_directory or '')
self.transfers_directory_editor.setText(blink_settings.transfers_directory or u'') self.transfers_directory_editor.setText(blink_settings.transfers_directory or '')
self.tls_ca_file_editor.setText(settings.tls.ca_list or u'') self.tls_ca_file_editor.setText(settings.tls.ca_list or '')
def load_account_settings(self, account): def load_account_settings(self, account):
"""Load the account settings from configuration into the UI controls""" """Load the account settings from configuration into the UI controls"""
...@@ -760,17 +758,17 @@ class PreferencesWindow(base_class, ui_class): ...@@ -760,17 +758,17 @@ class PreferencesWindow(base_class, ui_class):
# Account information tab # Account information tab
self.account_enabled_button.setChecked(account.enabled) self.account_enabled_button.setChecked(account.enabled)
self.account_enabled_button.setEnabled(True if account is not bonjour_account else BonjourAccount.mdns_available) self.account_enabled_button.setEnabled(True if account is not bonjour_account else BonjourAccount.mdns_available)
self.display_name_editor.setText(account.display_name or u'') self.display_name_editor.setText(account.display_name or '')
if account is not bonjour_account: if account is not bonjour_account:
self.password_editor.setText(account.auth.password) self.password_editor.setText(account.auth.password)
selected_index = self.account_list.selectionModel().selectedIndexes()[0] selected_index = self.account_list.selectionModel().selectedIndexes()[0]
selected_account_info = self.account_list.model().data(selected_index, Qt.UserRole) selected_account_info = self.account_list.model().data(selected_index, Qt.UserRole)
if selected_account_info.registration_state: if selected_account_info.registration_state:
self.account_registration_label.setText(u'Registration %s' % selected_account_info.registration_state.title()) self.account_registration_label.setText('Registration %s' % selected_account_info.registration_state.title())
else: else:
self.account_registration_label.setText(u'Not Registered') self.account_registration_label.setText('Not Registered')
else: else:
self.account_registration_label.setText(u'') self.account_registration_label.setText('')
# Media tab # Media tab
with blocked_qt_signals(self.account_audio_codecs_list): with blocked_qt_signals(self.account_audio_codecs_list):
...@@ -805,7 +803,7 @@ class PreferencesWindow(base_class, ui_class): ...@@ -805,7 +803,7 @@ class PreferencesWindow(base_class, ui_class):
with blocked_qt_signals(self.outbound_proxy_port): with blocked_qt_signals(self.outbound_proxy_port):
self.outbound_proxy_port.setValue(outbound_proxy.port) self.outbound_proxy_port.setValue(outbound_proxy.port)
self.outbound_proxy_transport_button.setCurrentIndex(self.outbound_proxy_transport_button.findText(outbound_proxy.transport.upper())) self.outbound_proxy_transport_button.setCurrentIndex(self.outbound_proxy_transport_button.findText(outbound_proxy.transport.upper()))
self.auth_username_editor.setText(account.auth.username or u'') self.auth_username_editor.setText(account.auth.username or '')
self.always_use_my_msrp_relay_button.setChecked(account.nat_traversal.use_msrp_relay_for_outbound) self.always_use_my_msrp_relay_button.setChecked(account.nat_traversal.use_msrp_relay_for_outbound)
msrp_relay = account.nat_traversal.msrp_relay or UnspecifiedMSRPRelay msrp_relay = account.nat_traversal.msrp_relay or UnspecifiedMSRPRelay
...@@ -814,10 +812,10 @@ class PreferencesWindow(base_class, ui_class): ...@@ -814,10 +812,10 @@ class PreferencesWindow(base_class, ui_class):
self.msrp_relay_port.setValue(msrp_relay.port) self.msrp_relay_port.setValue(msrp_relay.port)
self.msrp_relay_transport_button.setCurrentIndex(self.msrp_relay_transport_button.findText(msrp_relay.transport.upper())) self.msrp_relay_transport_button.setCurrentIndex(self.msrp_relay_transport_button.findText(msrp_relay.transport.upper()))
self.voicemail_uri_editor.setText(account.message_summary.voicemail_uri or u'') self.voicemail_uri_editor.setText(account.message_summary.voicemail_uri or '')
self.xcap_root_editor.setText(account.xcap.xcap_root or u'') self.xcap_root_editor.setText(account.xcap.xcap_root or '')
self.server_tools_url_editor.setText(account.server.settings_url or u'') self.server_tools_url_editor.setText(account.server.settings_url or '')
self.conference_server_editor.setText(account.server.conference_server or u'') self.conference_server_editor.setText(account.server.conference_server or '')
# Network tab # Network tab
self.use_ice_button.setChecked(account.nat_traversal.use_ice) self.use_ice_button.setChecked(account.nat_traversal.use_ice)
...@@ -846,7 +844,7 @@ class PreferencesWindow(base_class, ui_class): ...@@ -846,7 +844,7 @@ class PreferencesWindow(base_class, ui_class):
self._update_pstn_example_label() self._update_pstn_example_label()
self.account_tls_cert_file_editor.setText(account.tls.certificate or u'') self.account_tls_cert_file_editor.setText(account.tls.certificate or '')
self.account_tls_verify_server_button.setChecked(account.tls.verify_server) self.account_tls_verify_server_button.setChecked(account.tls.verify_server)
def update_chat_preview(self): def update_chat_preview(self):
...@@ -942,12 +940,12 @@ class PreferencesWindow(base_class, ui_class): ...@@ -942,12 +940,12 @@ class PreferencesWindow(base_class, ui_class):
logs_size += os.stat(os.path.join(path, name)).st_size logs_size += os.stat(os.path.join(path, name)).st_size
except (OSError, IOError): except (OSError, IOError):
pass pass
self.log_files_size_label.setText(u"There are currently %s of log files" % self._normalize_binary_size(logs_size)) self.log_files_size_label.setText("There are currently %s of log files" % self._normalize_binary_size(logs_size))
def _update_pstn_example_label(self): def _update_pstn_example_label(self):
prefix = self.prefix_button.currentText() prefix = self.prefix_button.currentText()
idd_prefix = self.idd_prefix_button.currentText() idd_prefix = self.idd_prefix_button.currentText()
self.pstn_example_transformed_label.setText(u"%s%s442079460000" % ('' if prefix == 'None' else prefix, idd_prefix)) self.pstn_example_transformed_label.setText("%s%s442079460000" % ('' if prefix == 'None' else prefix, idd_prefix))
def _align_style_preview(self, scroll=False): def _align_style_preview(self, scroll=False):
chat_element = self.style_view.page().mainFrame().findFirstElement('#chat') chat_element = self.style_view.page().mainFrame().findFirstElement('#chat')
...@@ -990,15 +988,15 @@ class PreferencesWindow(base_class, ui_class): ...@@ -990,15 +988,15 @@ class PreferencesWindow(base_class, ui_class):
self.password_editor.hide() self.password_editor.hide()
else: else:
if tab_widget.indexOf(self.server_settings_tab) == -1: if tab_widget.indexOf(self.server_settings_tab) == -1:
tab_widget.addTab(self.server_settings_tab, u"Server Settings") tab_widget.addTab(self.server_settings_tab, "Server Settings")
if tab_widget.indexOf(self.network_tab) == -1: if tab_widget.indexOf(self.network_tab) == -1:
tab_widget.addTab(self.network_tab, u"Network") tab_widget.addTab(self.network_tab, "Network")
if tab_widget.indexOf(self.advanced_tab) == -1: if tab_widget.indexOf(self.advanced_tab) == -1:
tab_widget.addTab(self.advanced_tab, u"Advanced") tab_widget.addTab(self.advanced_tab, "Advanced")
self.password_label.show() self.password_label.show()
self.password_editor.show() self.password_editor.show()
self.voicemail_uri_editor.inactiveText = u"Discovered by subscribing to %s" % selected_account.id self.voicemail_uri_editor.inactiveText = "Discovered by subscribing to %s" % selected_account.id
self.xcap_root_editor.inactiveText = u"Taken from the DNS TXT record for xcap.%s" % selected_account.id.domain self.xcap_root_editor.inactiveText = "Taken from the DNS TXT record for xcap.%s" % selected_account.id.domain
self.load_account_settings(selected_account) self.load_account_settings(selected_account)
def _SH_AccountListDataChanged(self, topLeft, bottomRight): def _SH_AccountListDataChanged(self, topLeft, bottomRight):
...@@ -1011,9 +1009,9 @@ class PreferencesWindow(base_class, ui_class): ...@@ -1011,9 +1009,9 @@ class PreferencesWindow(base_class, ui_class):
selected_account_info = self.account_list.model().data(selected_index, Qt.UserRole) selected_account_info = self.account_list.model().data(selected_index, Qt.UserRole)
if selected_account_info is account_info: if selected_account_info is account_info:
if account_info.registration_state: if account_info.registration_state:
self.account_registration_label.setText(u'Registration %s' % account_info.registration_state.title()) self.account_registration_label.setText('Registration %s' % account_info.registration_state.title())
else: else:
self.account_registration_label.setText(u'Not Registered') self.account_registration_label.setText('Not Registered')
def _SH_DeleteAccountButtonClicked(self): def _SH_DeleteAccountButtonClicked(self):
model = self.account_list.model() model = self.account_list.model()
...@@ -1021,7 +1019,7 @@ class PreferencesWindow(base_class, ui_class): ...@@ -1021,7 +1019,7 @@ class PreferencesWindow(base_class, ui_class):
selected_index = self.account_list.selectionModel().selectedIndexes()[0] selected_index = self.account_list.selectionModel().selectedIndexes()[0]
selected_account = selected_index.data(Qt.UserRole).account selected_account = selected_index.data(Qt.UserRole).account
title, message = u"Remove Account", u"Permanently remove account %s?" % selected_account.id title, message = "Remove Account", "Permanently remove account %s?" % selected_account.id
if QMessageBox.question(self, title, message, QMessageBox.Ok|QMessageBox.Cancel) == QMessageBox.Cancel: if QMessageBox.question(self, title, message, QMessageBox.Ok|QMessageBox.Cancel) == QMessageBox.Cancel:
return return
...@@ -1067,14 +1065,14 @@ class PreferencesWindow(base_class, ui_class): ...@@ -1067,14 +1065,14 @@ class PreferencesWindow(base_class, ui_class):
# Account media settings # Account media settings
def _SH_AccountAudioCodecsListItemChanged(self, item): def _SH_AccountAudioCodecsListItemChanged(self, item):
account = self.selected_account account = self.selected_account
items = [self.account_audio_codecs_list.item(row) for row in xrange(self.account_audio_codecs_list.count())] items = [self.account_audio_codecs_list.item(row) for row in range(self.account_audio_codecs_list.count())]
account.rtp.audio_codec_list = [item.text() for item in items if item.checkState() == Qt.Checked] account.rtp.audio_codec_list = [item.text() for item in items if item.checkState() == Qt.Checked]
account.rtp.audio_codec_order = [item.text() for item in items] account.rtp.audio_codec_order = [item.text() for item in items]
account.save() account.save()
def _SH_AccountAudioCodecsListModelRowsMoved(self, source_parent, source_start, source_end, dest_parent, dest_row): def _SH_AccountAudioCodecsListModelRowsMoved(self, source_parent, source_start, source_end, dest_parent, dest_row):
account = self.selected_account account = self.selected_account
items = [self.account_audio_codecs_list.item(row) for row in xrange(self.account_audio_codecs_list.count())] items = [self.account_audio_codecs_list.item(row) for row in range(self.account_audio_codecs_list.count())]
account.rtp.audio_codec_list = [item.text() for item in items if item.checkState() == Qt.Checked] account.rtp.audio_codec_list = [item.text() for item in items if item.checkState() == Qt.Checked]
account.rtp.audio_codec_order = [item.text() for item in items] account.rtp.audio_codec_order = [item.text() for item in items]
account.save() account.save()
...@@ -1097,14 +1095,14 @@ class PreferencesWindow(base_class, ui_class): ...@@ -1097,14 +1095,14 @@ class PreferencesWindow(base_class, ui_class):
def _SH_AccountVideoCodecsListItemChanged(self, item): def _SH_AccountVideoCodecsListItemChanged(self, item):
account = self.selected_account account = self.selected_account
items = [self.account_video_codecs_list.item(row) for row in xrange(self.account_video_codecs_list.count())] items = [self.account_video_codecs_list.item(row) for row in range(self.account_video_codecs_list.count())]
account.rtp.video_codec_list = [item.text() for item in items if item.checkState() == Qt.Checked] account.rtp.video_codec_list = [item.text() for item in items if item.checkState() == Qt.Checked]
account.rtp.video_codec_order = [item.text() for item in items] account.rtp.video_codec_order = [item.text() for item in items]
account.save() account.save()
def _SH_AccountVideoCodecsListModelRowsMoved(self, source_parent, source_start, source_end, dest_parent, dest_row): def _SH_AccountVideoCodecsListModelRowsMoved(self, source_parent, source_start, source_end, dest_parent, dest_row):
account = self.selected_account account = self.selected_account
items = [self.account_video_codecs_list.item(row) for row in xrange(self.account_video_codecs_list.count())] items = [self.account_video_codecs_list.item(row) for row in range(self.account_video_codecs_list.count())]
account.rtp.video_codec_list = [item.text() for item in items if item.checkState() == Qt.Checked] account.rtp.video_codec_list = [item.text() for item in items if item.checkState() == Qt.Checked]
account.rtp.video_codec_order = [item.text() for item in items] account.rtp.video_codec_order = [item.text() for item in items]
account.save() account.save()
...@@ -1285,7 +1283,7 @@ class PreferencesWindow(base_class, ui_class): ...@@ -1285,7 +1283,7 @@ class PreferencesWindow(base_class, ui_class):
# TODO: open the file selection dialog in non-modal mode (and the error messages boxes as well). -Dan # TODO: open the file selection dialog in non-modal mode (and the error messages boxes as well). -Dan
account = self.selected_account account = self.selected_account
directory = os.path.dirname(account.tls.certificate.normalized) if account.tls.certificate else Path('~').normalized directory = os.path.dirname(account.tls.certificate.normalized) if account.tls.certificate else Path('~').normalized
cert_path = QFileDialog.getOpenFileName(self, u'Select Certificate File', directory, u"TLS certificates (*.crt *.pem)")[0] or None cert_path = QFileDialog.getOpenFileName(self, 'Select Certificate File', directory, "TLS certificates (*.crt *.pem)")[0] or None
if cert_path is not None: if cert_path is not None:
cert_path = os.path.normpath(cert_path) cert_path = os.path.normpath(cert_path)
if cert_path != account.tls.certificate: if cert_path != account.tls.certificate:
...@@ -1293,10 +1291,10 @@ class PreferencesWindow(base_class, ui_class): ...@@ -1293,10 +1291,10 @@ class PreferencesWindow(base_class, ui_class):
contents = open(cert_path).read() contents = open(cert_path).read()
X509Certificate(contents) X509Certificate(contents)
X509PrivateKey(contents) X509PrivateKey(contents)
except (OSError, IOError), e: except (OSError, IOError) as e:
QMessageBox.critical(self, u"TLS Certificate Error", u"The certificate file could not be opened: %s" % e.strerror) QMessageBox.critical(self, "TLS Certificate Error", "The certificate file could not be opened: %s" % e.strerror)
except GNUTLSError, e: except GNUTLSError as e:
QMessageBox.critical(self, u"TLS Certificate Error", u"The certificate file is invalid: %s" % e) QMessageBox.critical(self, "TLS Certificate Error", "The certificate file is invalid: %s" % e)
else: else:
self.account_tls_cert_file_editor.setText(cert_path) self.account_tls_cert_file_editor.setText(cert_path)
account.tls.certificate = cert_path account.tls.certificate = cert_path
...@@ -1344,13 +1342,13 @@ class PreferencesWindow(base_class, ui_class): ...@@ -1344,13 +1342,13 @@ class PreferencesWindow(base_class, ui_class):
# Audio codecs signal handlers # Audio codecs signal handlers
def _SH_AudioCodecsListItemChanged(self, item): def _SH_AudioCodecsListItemChanged(self, item):
settings = SIPSimpleSettings() settings = SIPSimpleSettings()
item_iterator = (self.audio_codecs_list.item(row) for row in xrange(self.audio_codecs_list.count())) item_iterator = (self.audio_codecs_list.item(row) for row in range(self.audio_codecs_list.count()))
settings.rtp.audio_codec_list = [item.text() for item in item_iterator if item.checkState() == Qt.Checked] settings.rtp.audio_codec_list = [item.text() for item in item_iterator if item.checkState() == Qt.Checked]
settings.save() settings.save()
def _SH_AudioCodecsListModelRowsMoved(self, source_parent, source_start, source_end, dest_parent, dest_row): def _SH_AudioCodecsListModelRowsMoved(self, source_parent, source_start, source_end, dest_parent, dest_row):
settings = SIPSimpleSettings() settings = SIPSimpleSettings()
items = [self.audio_codecs_list.item(row) for row in xrange(self.audio_codecs_list.count())] items = [self.audio_codecs_list.item(row) for row in range(self.audio_codecs_list.count())]
settings.rtp.audio_codec_order = [item.text() for item in items] settings.rtp.audio_codec_order = [item.text() for item in items]
settings.rtp.audio_codec_list = [item.text() for item in items if item.checkState() == Qt.Checked] settings.rtp.audio_codec_list = [item.text() for item in items if item.checkState() == Qt.Checked]
settings.save() settings.save()
...@@ -1363,18 +1361,18 @@ class PreferencesWindow(base_class, ui_class): ...@@ -1363,18 +1361,18 @@ class PreferencesWindow(base_class, ui_class):
def _SH_AnswerDelayValueChanged(self, value): def _SH_AnswerDelayValueChanged(self, value):
if value == 0: if value == 0:
self.answer_delay_seconds_label.setText(u'') self.answer_delay_seconds_label.setText('')
elif value == 1: elif value == 1:
self.answer_delay_seconds_label.setText(u'second') self.answer_delay_seconds_label.setText('second')
else: else:
self.answer_delay_seconds_label.setText(u'seconds') self.answer_delay_seconds_label.setText('seconds')
settings = SIPSimpleSettings() settings = SIPSimpleSettings()
if settings.answering_machine.answer_delay != value: if settings.answering_machine.answer_delay != value:
settings.answering_machine.answer_delay = value settings.answering_machine.answer_delay = value
settings.save() settings.save()
def _SH_MaxRecordingValueChanged(self, value): def _SH_MaxRecordingValueChanged(self, value):
self.max_recording_minutes_label.setText(u'minute' if value == 1 else u'minutes') self.max_recording_minutes_label.setText('minute' if value == 1 else 'minutes')
settings = SIPSimpleSettings() settings = SIPSimpleSettings()
if settings.answering_machine.max_recording != value: if settings.answering_machine.max_recording != value:
settings.answering_machine.max_recording = value settings.answering_machine.max_recording = value
...@@ -1403,13 +1401,13 @@ class PreferencesWindow(base_class, ui_class): ...@@ -1403,13 +1401,13 @@ class PreferencesWindow(base_class, ui_class):
# Video codecs signal handlers # Video codecs signal handlers
def _SH_VideoCodecsListItemChanged(self, item): def _SH_VideoCodecsListItemChanged(self, item):
settings = SIPSimpleSettings() settings = SIPSimpleSettings()
item_iterator = (self.video_codecs_list.item(row) for row in xrange(self.video_codecs_list.count())) item_iterator = (self.video_codecs_list.item(row) for row in range(self.video_codecs_list.count()))
settings.rtp.video_codec_list = [item.text() for item in item_iterator if item.checkState() == Qt.Checked] settings.rtp.video_codec_list = [item.text() for item in item_iterator if item.checkState() == Qt.Checked]
settings.save() settings.save()
def _SH_VideoCodecsListModelRowsMoved(self, source_parent, source_start, source_end, dest_parent, dest_row): def _SH_VideoCodecsListModelRowsMoved(self, source_parent, source_start, source_end, dest_parent, dest_row):
settings = SIPSimpleSettings() settings = SIPSimpleSettings()
items = [self.video_codecs_list.item(row) for row in xrange(self.video_codecs_list.count())] items = [self.video_codecs_list.item(row) for row in range(self.video_codecs_list.count())]
settings.rtp.video_codec_order = [item.text() for item in items] settings.rtp.video_codec_order = [item.text() for item in items]
settings.rtp.video_codec_list = [item.text() for item in items if item.checkState() == Qt.Checked] settings.rtp.video_codec_list = [item.text() for item in items if item.checkState() == Qt.Checked]
settings.save() settings.save()
...@@ -1508,7 +1506,7 @@ class PreferencesWindow(base_class, ui_class): ...@@ -1508,7 +1506,7 @@ class PreferencesWindow(base_class, ui_class):
def _SH_ScreenshotsDirectoryBrowseButtonClicked(self, checked): def _SH_ScreenshotsDirectoryBrowseButtonClicked(self, checked):
# TODO: open the file selection dialog in non-modal mode. Same for the one for TLS CA list and the IconSelector from contacts. -Dan # TODO: open the file selection dialog in non-modal mode. Same for the one for TLS CA list and the IconSelector from contacts. -Dan
settings = BlinkSettings() settings = BlinkSettings()
directory = QFileDialog.getExistingDirectory(self, u'Select Screenshots Directory', settings.screenshots_directory.normalized) or None directory = QFileDialog.getExistingDirectory(self, 'Select Screenshots Directory', settings.screenshots_directory.normalized) or None
if directory is not None: if directory is not None:
directory = os.path.normpath(directory) directory = os.path.normpath(directory)
if directory != settings.screenshots_directory: if directory != settings.screenshots_directory:
...@@ -1535,7 +1533,7 @@ class PreferencesWindow(base_class, ui_class): ...@@ -1535,7 +1533,7 @@ class PreferencesWindow(base_class, ui_class):
def _SH_TransfersDirectoryBrowseButtonClicked(self, checked): def _SH_TransfersDirectoryBrowseButtonClicked(self, checked):
# TODO: open the file selection dialog in non-modal mode. Same for the one for TLS CA list and the IconSelector from contacts. -Dan # TODO: open the file selection dialog in non-modal mode. Same for the one for TLS CA list and the IconSelector from contacts. -Dan
settings = BlinkSettings() settings = BlinkSettings()
directory = QFileDialog.getExistingDirectory(self, u'Select Transfers Directory', settings.transfers_directory.normalized) or None directory = QFileDialog.getExistingDirectory(self, 'Select Transfers Directory', settings.transfers_directory.normalized) or None
if directory is not None: if directory is not None:
directory = os.path.normpath(directory) directory = os.path.normpath(directory)
if directory != settings.transfers_directory: if directory != settings.transfers_directory:
...@@ -1643,16 +1641,16 @@ class PreferencesWindow(base_class, ui_class): ...@@ -1643,16 +1641,16 @@ class PreferencesWindow(base_class, ui_class):
# TODO: open the file selection dialog in non-modal mode (and the error messages boxes as well). -Dan # TODO: open the file selection dialog in non-modal mode (and the error messages boxes as well). -Dan
settings = SIPSimpleSettings() settings = SIPSimpleSettings()
directory = os.path.dirname(settings.tls.ca_list.normalized) if settings.tls.ca_list else Path('~').normalized directory = os.path.dirname(settings.tls.ca_list.normalized) if settings.tls.ca_list else Path('~').normalized
ca_path = QFileDialog.getOpenFileName(self, u'Select Certificate Authority File', directory, u"TLS certificates (*.crt *.pem)")[0] or None ca_path = QFileDialog.getOpenFileName(self, 'Select Certificate Authority File', directory, "TLS certificates (*.crt *.pem)")[0] or None
if ca_path is not None: if ca_path is not None:
ca_path = os.path.normpath(ca_path) ca_path = os.path.normpath(ca_path)
if ca_path != settings.tls.ca_list: if ca_path != settings.tls.ca_list:
try: try:
X509Certificate(open(ca_path).read()) X509Certificate(open(ca_path).read())
except (OSError, IOError), e: except (OSError, IOError) as e:
QMessageBox.critical(self, u"TLS Certificate Error", u"The certificate authority file could not be opened: %s" % e.strerror) QMessageBox.critical(self, "TLS Certificate Error", "The certificate authority file could not be opened: %s" % e.strerror)
except GNUTLSError, e: except GNUTLSError as e:
QMessageBox.critical(self, u"TLS Certificate Error", u"The certificate authority file is invalid: %s" % e) QMessageBox.critical(self, "TLS Certificate Error", "The certificate authority file is invalid: %s" % e)
else: else:
self.tls_ca_file_editor.setText(ca_path) self.tls_ca_file_editor.setText(ca_path)
settings.tls.ca_list = ca_path settings.tls.ca_list = ca_path
...@@ -1711,7 +1709,7 @@ class PreferencesWindow(base_class, ui_class): ...@@ -1711,7 +1709,7 @@ class PreferencesWindow(base_class, ui_class):
self.account_enabled_button.setChecked(account.enabled) self.account_enabled_button.setChecked(account.enabled)
self.reregister_button.setEnabled(account.enabled) self.reregister_button.setEnabled(account.enabled)
if 'display_name' in notification.data.modified: if 'display_name' in notification.data.modified:
self.display_name_editor.setText(account.display_name or u'') self.display_name_editor.setText(account.display_name or '')
if 'rtp.audio_codec_list' in notification.data.modified: if 'rtp.audio_codec_list' in notification.data.modified:
self.reset_account_audio_codecs_button.setEnabled(account.rtp.audio_codec_list is not None) self.reset_account_audio_codecs_button.setEnabled(account.rtp.audio_codec_list is not None)
if 'rtp.video_codec_list' in notification.data.modified: if 'rtp.video_codec_list' in notification.data.modified:
......
...@@ -112,7 +112,7 @@ class BlinkPresenceState(object): ...@@ -112,7 +112,7 @@ class BlinkPresenceState(object):
device = pidf.Device('DID-%s' % instance_id, device_id=pidf.DeviceID(instance_id)) device = pidf.Device('DID-%s' % instance_id, device_id=pidf.DeviceID(instance_id))
device.timestamp = timestamp device.timestamp = timestamp
device.notes.add(u'%s at %s' % (settings.user_agent, hostname)) device.notes.add('%s at %s' % (settings.user_agent, hostname))
doc.add(device) doc.add(device)
return doc return doc
...@@ -226,8 +226,8 @@ class PresencePublicationHandler(object): ...@@ -226,8 +226,8 @@ class PresencePublicationHandler(object):
if service.id in ('SID-%s' % uuid.UUID(SIPSimpleSettings().instance_id), 'SID-%s' % hashlib.md5(notification.sender.id).hexdigest()): if service.id in ('SID-%s' % uuid.UUID(SIPSimpleSettings().instance_id), 'SID-%s' % hashlib.md5(notification.sender.id).hexdigest()):
# Our current state is the winning one # Our current state is the winning one
return return
status = unicode(service.status.extended).title() status = str(service.status.extended).title()
note = None if not service.notes else unicode(list(service.notes)[0]) note = None if not service.notes else str(list(service.notes)[0])
if status == 'Offline': if status == 'Offline':
status = 'Invisible' status = 'Invisible'
note = None note = None
...@@ -304,12 +304,12 @@ class ContactIcon(object): ...@@ -304,12 +304,12 @@ class ContactIcon(object):
@classmethod @classmethod
def fetch(cls, url, etag=None, descriptor_etag=None): def fetch(cls, url, etag=None, descriptor_etag=None):
headers = {'If-None-Match': etag} if etag else {} headers = {'If-None-Match': etag} if etag else {}
req = urllib2.Request(url, headers=headers) req = urllib.request.Request(url, headers=headers)
try: try:
response = urllib2.urlopen(req) response = urllib.request.urlopen(req)
content = response.read() content = response.read()
info = response.info() info = response.info()
except (ConnectionLost, urllib2.URLError, urllib2.HTTPError): except (ConnectionLost, urllib.error.URLError, urllib.error.HTTPError):
return None return None
content_type = info.getheader('content-type') content_type = info.getheader('content-type')
etag = info.getheader('etag') etag = info.getheader('etag')
...@@ -352,7 +352,7 @@ class PresenceSubscriptionHandler(object): ...@@ -352,7 +352,7 @@ class PresenceSubscriptionHandler(object):
notification_center.remove_observer(self, name='SIPAccountGotPresenceWinfo') notification_center.remove_observer(self, name='SIPAccountGotPresenceWinfo')
self._pidf_map.clear() self._pidf_map.clear()
self._winfo_map.clear() self._winfo_map.clear()
for timer in self._winfo_timers.values(): for timer in list(self._winfo_timers.values()):
if timer.active(): if timer.active():
timer.cancel() timer.cancel()
self._winfo_timers.clear() self._winfo_timers.clear()
...@@ -375,9 +375,9 @@ class PresenceSubscriptionHandler(object): ...@@ -375,9 +375,9 @@ class PresenceSubscriptionHandler(object):
# If no URIs were provided, process all of them # If no URIs were provided, process all of them
if not uris: if not uris:
uris = list(chain(*(item.iterkeys() for item in self._pidf_map.itervalues()))) uris = list(chain(*(iter(item.keys()) for item in self._pidf_map.values())))
for uri, pidf_list in chain(*(x.iteritems() for x in self._pidf_map.itervalues())): for uri, pidf_list in chain(*(iter(x.items()) for x in self._pidf_map.values())):
current_pidf_map.setdefault(uri, []).extend(pidf_list) current_pidf_map.setdefault(uri, []).extend(pidf_list)
for uri in uris: for uri in uris:
...@@ -385,7 +385,7 @@ class PresenceSubscriptionHandler(object): ...@@ -385,7 +385,7 @@ class PresenceSubscriptionHandler(object):
for contact in (contact for contact in addressbook_manager.get_contacts() if uri in (self.sip_prefix_re.sub('', contact_uri.uri) for contact_uri in contact.uris)): for contact in (contact for contact in addressbook_manager.get_contacts() if uri in (self.sip_prefix_re.sub('', contact_uri.uri) for contact_uri in contact.uris)):
contact_pidf_map.setdefault(contact, []).extend(pidf_list) contact_pidf_map.setdefault(contact, []).extend(pidf_list)
for contact, pidf_list in contact_pidf_map.iteritems(): for contact, pidf_list in contact_pidf_map.items():
if not pidf_list: if not pidf_list:
state = note = icon = None state = note = icon = None
else: else:
...@@ -393,11 +393,11 @@ class PresenceSubscriptionHandler(object): ...@@ -393,11 +393,11 @@ class PresenceSubscriptionHandler(object):
services.sort(key=service_sort_key, reverse=True) services.sort(key=service_sort_key, reverse=True)
service = services[0] service = services[0]
if service.status.extended: if service.status.extended:
state = unicode(service.status.extended) state = str(service.status.extended)
else: else:
state = 'available' if service.status.basic == 'open' else 'offline' state = 'available' if service.status.basic == 'open' else 'offline'
note = unicode(next(iter(service.notes))) if service.notes else None note = str(next(iter(service.notes))) if service.notes else None
icon_url = unicode(service.icon) if service.icon else None icon_url = str(service.icon) if service.icon else None
if icon_url: if icon_url:
url, token, icon_hash = icon_url.partition('#blink-icon') url, token, icon_hash = icon_url.partition('#blink-icon')
...@@ -456,12 +456,12 @@ class PresenceSubscriptionHandler(object): ...@@ -456,12 +456,12 @@ class PresenceSubscriptionHandler(object):
def _NH_SIPAccountGotPresenceState(self, notification): def _NH_SIPAccountGotPresenceState(self, notification):
account = notification.sender account = notification.sender
new_pidf_map = dict((self.sip_prefix_re.sub('', uri), resource.pidf_list) for uri, resource in notification.data.resource_map.iteritems()) new_pidf_map = dict((self.sip_prefix_re.sub('', uri), resource.pidf_list) for uri, resource in notification.data.resource_map.items())
account_map = self._pidf_map.setdefault(account.id, {}) account_map = self._pidf_map.setdefault(account.id, {})
if notification.data.full_state: if notification.data.full_state:
account_map.clear() account_map.clear()
account_map.update(new_pidf_map) account_map.update(new_pidf_map)
self._process_presence_data(new_pidf_map.keys()) self._process_presence_data(list(new_pidf_map.keys()))
def _NH_SIPAccountGotPresenceWinfo(self, notification): def _NH_SIPAccountGotPresenceWinfo(self, notification):
addressbook_manager = addressbook.AddressbookManager() addressbook_manager = addressbook.AddressbookManager()
...@@ -535,7 +535,7 @@ class PendingWatcherDialog(base_class, ui_class): ...@@ -535,7 +535,7 @@ class PendingWatcherDialog(base_class, ui_class):
icon = icon_manager.get(self.contact.id) icon = icon_manager.get(self.contact.id)
if icon is not None: if icon is not None:
self.user_icon.setPixmap(icon.pixmap(48)) self.user_icon.setPixmap(icon.pixmap(48))
self.description_label.setText(u'Wants to subscribe to your availability information at {}'.format(account.id)) self.description_label.setText('Wants to subscribe to your availability information at {}'.format(account.id))
self.name_label.setText(display_name or uri) self.name_label.setText(display_name or uri)
self.uri_label.setText(uri) self.uri_label.setText(uri)
self.accept_button.released.connect(self._accept_watcher) self.accept_button.released.connect(self._accept_watcher)
......
...@@ -21,9 +21,9 @@ from blink.util import run_in_gui_thread ...@@ -21,9 +21,9 @@ from blink.util import run_in_gui_thread
__all__ = ['ApplicationData', 'Resources', 'IconManager'] __all__ = ['ApplicationData', 'Resources', 'IconManager']
class DirectoryContextManager(unicode): class DirectoryContextManager(str):
def __enter__(self): def __enter__(self):
self.directory = os.getcwdu() self.directory = os.getcwd()
os.chdir(self) os.chdir(self)
def __exit__(self, type, value, traceback): def __exit__(self, type, value, traceback):
...@@ -40,11 +40,11 @@ class ApplicationData(object): ...@@ -40,11 +40,11 @@ class ApplicationData(object):
if cls._cached_directory is None: if cls._cached_directory is None:
if platform.system() == 'Darwin': if platform.system() == 'Darwin':
from Foundation import NSApplicationSupportDirectory, NSSearchPathForDirectoriesInDomains, NSUserDomainMask from Foundation import NSApplicationSupportDirectory, NSSearchPathForDirectoriesInDomains, NSUserDomainMask
cls._cached_directory = os.path.join(NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, True)[0], u'Blink') cls._cached_directory = os.path.join(NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, True)[0], 'Blink')
elif platform.system() == 'Windows': elif platform.system() == 'Windows':
cls._cached_directory = os.path.join(os.environ['APPDATA'].decode(sys.getfilesystemencoding()), u'Blink') cls._cached_directory = os.path.join(os.environ['APPDATA'].decode(sys.getfilesystemencoding()), 'Blink')
else: else:
cls._cached_directory = Path(u'~/.blink').normalized cls._cached_directory = Path('~/.blink').normalized
return DirectoryContextManager(cls._cached_directory) return DirectoryContextManager(cls._cached_directory)
@classmethod @classmethod
...@@ -83,9 +83,7 @@ class Resources(object): ...@@ -83,9 +83,7 @@ class Resources(object):
return os.path.join(cls.directory, os.path.normpath(resource)) return os.path.join(cls.directory, os.path.normpath(resource))
class IconManager(object): class IconManager(object, metaclass=Singleton):
__metaclass__ = Singleton
max_size = 256 max_size = 256
def __init__(self): def __init__(self):
......
...@@ -22,7 +22,7 @@ class RFBSettings(object): ...@@ -22,7 +22,7 @@ class RFBSettings(object):
def __init__(self, depth, quality, compression, encodings): def __init__(self, depth, quality, compression, encodings):
if depth not in (8, 16, 24, 32, None): if depth not in (8, 16, 24, 32, None):
raise ValueError("invalid depth value: %r (should be one of 8, 16, 24, 32 or None)" % depth) raise ValueError("invalid depth value: %r (should be one of 8, 16, 24, 32 or None)" % depth)
allowed_levels = range(10) allowed_levels = list(range(10))
if quality not in allowed_levels: if quality not in allowed_levels:
raise ValueError("invalid quality value: %r (should be between 0..9)" % quality) raise ValueError("invalid quality value: %r (should be between 0..9)" % quality)
if compression not in allowed_levels: if compression not in allowed_levels:
...@@ -83,7 +83,7 @@ class VNCClient(QObject): ...@@ -83,7 +83,7 @@ class VNCClient(QObject):
imageSizeChanged = pyqtSignal(QSize) imageSizeChanged = pyqtSignal(QSize)
imageChanged = pyqtSignal(int, int, int, int) imageChanged = pyqtSignal(int, int, int, int)
passwordRequested = pyqtSignal(bool) passwordRequested = pyqtSignal(bool)
textCut = pyqtSignal(unicode) textCut = pyqtSignal(str)
def __init__(self, host, port, settings, parent=None): def __init__(self, host, port, settings, parent=None):
super(VNCClient, self).__init__(parent) super(VNCClient, self).__init__(parent)
......
from __future__ import division
import os import os
import platform import platform
...@@ -401,7 +401,7 @@ class ScreensharingDialog(base_class, ui_class): ...@@ -401,7 +401,7 @@ class ScreensharingDialog(base_class, ui_class):
return False return False
def get_credentials(self): def get_credentials(self):
self.message_label.setText(u'Screen sharing requires authentication') self.message_label.setText('Screen sharing requires authentication')
self.username_label.show() self.username_label.show()
self.username_editor.show() self.username_editor.show()
self.username_editor.clear() self.username_editor.clear()
...@@ -413,7 +413,7 @@ class ScreensharingDialog(base_class, ui_class): ...@@ -413,7 +413,7 @@ class ScreensharingDialog(base_class, ui_class):
return (self.username_editor.text(), self.password_editor.text()) if result == self.Accepted else (None, None) return (self.username_editor.text(), self.password_editor.text()) if result == self.Accepted else (None, None)
def get_password(self): def get_password(self):
self.message_label.setText(u'Screen sharing requires a password') self.message_label.setText('Screen sharing requires a password')
self.username_label.hide() self.username_label.hide()
self.username_editor.hide() self.username_editor.hide()
self.username_editor.clear() self.username_editor.clear()
......
import bisect import bisect
import cPickle as pickle import pickle as pickle
import contextlib import contextlib
import os import os
import re import re
...@@ -61,9 +61,7 @@ class Container(object): ...@@ -61,9 +61,7 @@ class Container(object):
pass pass
class RTPStreamInfo(object): class RTPStreamInfo(object, metaclass=ABCMeta):
__metaclass__ = ABCMeta
dataset_size = 5000 dataset_size = 5000
average_interval = 10 average_interval = 10
...@@ -132,9 +130,7 @@ class RTPStreamInfo(object): ...@@ -132,9 +130,7 @@ class RTPStreamInfo(object):
self.__init__() self.__init__()
class MSRPStreamInfo(object): class MSRPStreamInfo(object, metaclass=ABCMeta):
__metaclass__ = ABCMeta
def __init__(self): def __init__(self):
self.local_address = None self.local_address = None
self.remote_address = None self.remote_address = None
...@@ -270,7 +266,7 @@ class StreamDescription(object): ...@@ -270,7 +266,7 @@ class StreamDescription(object):
def __repr__(self): def __repr__(self):
if self.attributes: if self.attributes:
return "%s(%r, %s)" % (self.__class__.__name__, self.type, ', '.join("%s=%r" % pair for pair in self.attributes.iteritems())) return "%s(%r, %s)" % (self.__class__.__name__, self.type, ', '.join("%s=%r" % pair for pair in self.attributes.items()))
else: else:
return "%s(%r)" % (self.__class__.__name__, self.type) return "%s(%r)" % (self.__class__.__name__, self.type)
...@@ -283,13 +279,13 @@ class StreamSet(object): ...@@ -283,13 +279,13 @@ class StreamSet(object):
return self._stream_map[key] return self._stream_map[key]
def __contains__(self, key): def __contains__(self, key):
return key in self._stream_map or key in self._stream_map.values() return key in self._stream_map or key in list(self._stream_map.values())
def __iter__(self): def __iter__(self):
return iter(sorted(self._stream_map.values(), key=attrgetter('type'))) return iter(sorted(list(self._stream_map.values()), key=attrgetter('type')))
def __reversed__(self): def __reversed__(self):
return iter(sorted(self._stream_map.values(), key=attrgetter('type'), reverse=True)) return iter(sorted(list(self._stream_map.values()), key=attrgetter('type'), reverse=True))
__hash__ = None __hash__ = None
...@@ -320,13 +316,13 @@ class StreamContainerView(object): ...@@ -320,13 +316,13 @@ class StreamContainerView(object):
return self._stream_map[key] return self._stream_map[key]
def __contains__(self, key): def __contains__(self, key):
return key in self._stream_map or key in self._stream_map.values() return key in self._stream_map or key in list(self._stream_map.values())
def __iter__(self): def __iter__(self):
return iter(sorted(self._stream_map.values(), key=attrgetter('type'))) return iter(sorted(list(self._stream_map.values()), key=attrgetter('type')))
def __reversed__(self): def __reversed__(self):
return iter(sorted(self._stream_map.values(), key=attrgetter('type'), reverse=True)) return iter(sorted(list(self._stream_map.values()), key=attrgetter('type'), reverse=True))
__hash__ = None __hash__ = None
...@@ -374,7 +370,7 @@ class StreamContainer(StreamContainerView): ...@@ -374,7 +370,7 @@ class StreamContainer(StreamContainerView):
self.add(item) self.add(item)
def clear(self): def clear(self):
for stream in self._stream_map.values(): for stream in list(self._stream_map.values()):
self.remove(stream) self.remove(stream)
...@@ -401,7 +397,7 @@ class SessionState(str): ...@@ -401,7 +397,7 @@ class SessionState(str):
def __eq__(self, other): def __eq__(self, other):
if isinstance(other, SessionState): if isinstance(other, SessionState):
return self.state == other.state and self.substate == other.substate return self.state == other.state and self.substate == other.substate
elif isinstance(other, basestring): elif isinstance(other, str):
state = other.partition('/')[0] or None state = other.partition('/')[0] or None
substate = other.partition('/')[2] or None substate = other.partition('/')[2] or None
if state == '*': if state == '*':
...@@ -441,9 +437,7 @@ class BlinkSessionType(type): ...@@ -441,9 +437,7 @@ class BlinkSessionType(type):
return instance return instance
class BlinkSessionBase(object): class BlinkSessionBase(object, metaclass=BlinkSessionType):
__metaclass__ = BlinkSessionType
def __establish__(self): def __establish__(self):
pass pass
...@@ -822,8 +816,8 @@ class BlinkSession(BlinkSessionBase): ...@@ -822,8 +816,8 @@ class BlinkSession(BlinkSessionBase):
path = os.path.join(settings.audio.recordings_directory.normalized, self.account.id) path = os.path.join(settings.audio.recordings_directory.normalized, self.account.id)
try: try:
audio_stream.start_recording(os.path.join(path, filename)) audio_stream.start_recording(os.path.join(path, filename))
except (SIPCoreError, IOError, OSError), e: except (SIPCoreError, IOError, OSError) as e:
print 'Failed to record: %s' % e print('Failed to record: %s' % e)
else: else:
self.recording = True self.recording = True
...@@ -926,7 +920,7 @@ class BlinkSession(BlinkSessionBase): ...@@ -926,7 +920,7 @@ class BlinkSession(BlinkSessionBase):
def _sync_chat_peer_name(self): def _sync_chat_peer_name(self):
chat_stream = self.streams.active.get('chat', Null) chat_stream = self.streams.active.get('chat', Null)
if chat_stream.encryption.active and chat_stream.encryption.peer_name == u'': if chat_stream.encryption.active and chat_stream.encryption.peer_name == '':
chat_stream.encryption.peer_name = self.info.streams.audio.zrtp_peer_name chat_stream.encryption.peer_name = self.info.streams.audio.zrtp_peer_name
def _SH_TimerFired(self): def _SH_TimerFired(self):
...@@ -1199,16 +1193,16 @@ class BlinkSession(BlinkSessionBase): ...@@ -1199,16 +1193,16 @@ class BlinkSession(BlinkSessionBase):
class SMPVerification(Enum): class SMPVerification(Enum):
Unavailable = u'Unavailable' Unavailable = 'Unavailable'
InProgress = u'In progress' InProgress = 'In progress'
Succeeded = u'Succeeded' Succeeded = 'Succeeded'
Failed = u'Failed' Failed = 'Failed'
class SMPVerificationHandler(object): class SMPVerificationHandler(object):
implements(IObserver) implements(IObserver)
question = u'What is the ZRTP authentication string?'.encode('utf-8') question = 'What is the ZRTP authentication string?'.encode('utf-8')
def __init__(self, blink_session): def __init__(self, blink_session):
"""@type blink_session: BlinkSession""" """@type blink_session: BlinkSession"""
...@@ -1377,7 +1371,7 @@ class ConferenceParticipant(object): ...@@ -1377,7 +1371,7 @@ class ConferenceParticipant(object):
self.active_media.add(media.media_type.value) self.active_media.add(media.media_type.value)
audio_endpoints = [endpt for endpt in data if any(media.media_type == 'audio' for media in endpt)] audio_endpoints = [endpt for endpt in data if any(media.media_type == 'audio' for media in endpt)]
self.on_hold = all(endpt.status == 'on-hold' for endpt in audio_endpoints) if audio_endpoints else False self.on_hold = all(endpt.status == 'on-hold' for endpt in audio_endpoints) if audio_endpoints else False
for attr, value in old_values.iteritems(): for attr, value in old_values.items():
if value != getattr(self, attr): if value != getattr(self, attr):
NotificationCenter().post_notification('ConferenceParticipantDidChange', sender=self) NotificationCenter().post_notification('ConferenceParticipantDidChange', sender=self)
break break
...@@ -1451,10 +1445,10 @@ class ServerConference(object): ...@@ -1451,10 +1445,10 @@ class ServerConference(object):
from blink.contacts import URIUtils from blink.contacts import URIUtils
users = dict((self.sip_prefix_re.sub('', str(user.entity)), user) for user in notification.data.conference_info.users) users = dict((self.sip_prefix_re.sub('', str(user.entity)), user) for user in notification.data.conference_info.users)
removed_participants = [participant for participant in self.participants.itervalues() if participant.uri not in users and participant not in self.pending_additions] removed_participants = [participant for participant in self.participants.values() if participant.uri not in users and participant not in self.pending_additions]
confirmed_participants = [participant for participant in self.participants.itervalues() if participant in self.pending_additions and participant.uri in users] confirmed_participants = [participant for participant in self.participants.values() if participant in self.pending_additions and participant.uri in users]
updated_participants = [self.participants[uri] for uri in users if uri in self.participants] updated_participants = [self.participants[uri] for uri in users if uri in self.participants]
added_users = set(users.keys()).difference(self.participants.keys()) added_users = set(users.keys()).difference(list(self.participants.keys()))
for participant in removed_participants: for participant in removed_participants:
self.participants.pop(participant.uri) self.participants.pop(participant.uri)
...@@ -1532,9 +1526,9 @@ class ServerConference(object): ...@@ -1532,9 +1526,9 @@ class ServerConference(object):
# #
# positions for sessions in a client conference. # positions for sessions in a client conference.
class Top: __metaclass__ = MarkerType class Top(metaclass=MarkerType): pass
class Middle: __metaclass__ = MarkerType class Middle(metaclass=MarkerType): pass
class Bottom: __metaclass__ = MarkerType class Bottom(metaclass=MarkerType): pass
ui_class, base_class = uic.loadUiType(Resources.get('audio_session.ui')) ui_class, base_class = uic.loadUiType(Resources.get('audio_session.ui'))
...@@ -1789,9 +1783,9 @@ class DraggedAudioSessionWidget(base_class, ui_class): ...@@ -1789,9 +1783,9 @@ class DraggedAudioSessionWidget(base_class, ui_class):
self.address_label.setText(session_widget.address_label.text()) self.address_label.setText(session_widget.address_label.text())
if self.in_conference: if self.in_conference:
self.note_label.setText(u'Drop outside the conference to detach') self.note_label.setText('Drop outside the conference to detach')
else: else:
self.note_label.setText(u'<p><b>Drop</b>:&nbsp;Conference&nbsp; <b>Alt+Drop</b>:&nbsp;Transfer</p>') self.note_label.setText('<p><b>Drop</b>:&nbsp;Conference&nbsp; <b>Alt+Drop</b>:&nbsp;Transfer</p>')
def paintEvent(self, event): def paintEvent(self, event):
painter = QPainter(self) painter = QPainter(self)
...@@ -1864,11 +1858,11 @@ class AudioSessionItem(object): ...@@ -1864,11 +1858,11 @@ class AudioSessionItem(object):
def __unicode__(self): def __unicode__(self):
if self.status is not None: if self.status is not None:
return u'{0.type} call with {0.name} ({0.status})'.format(self) return '{0.type} call with {0.name} ({0.status})'.format(self)
elif self.codec_info: elif self.codec_info:
return u'{0.type} call with {0.name} using {0.codec_info} ({0.duration!s})'.format(self) return '{0.type} call with {0.name} using {0.codec_info} ({0.duration!s})'.format(self)
else: else:
return u'{0.type} call with {0.name}'.format(self) return '{0.type} call with {0.name}'.format(self)
@property @property
def audio_stream(self): def audio_stream(self):
...@@ -2104,9 +2098,9 @@ class AudioSessionItem(object): ...@@ -2104,9 +2098,9 @@ class AudioSessionItem(object):
self.type = 'HD Audio' if audio_info.sample_rate >= 16000 else 'Audio' self.type = 'HD Audio' if audio_info.sample_rate >= 16000 else 'Audio'
self.codec_info = audio_info.codec self.codec_info = audio_info.codec
if audio_info.encryption is not None: if audio_info.encryption is not None:
self.widget.srtp_label.setToolTip(u'Media is encrypted using %s (%s)' % (audio_info.encryption, audio_info.encryption_cipher)) self.widget.srtp_label.setToolTip('Media is encrypted using %s (%s)' % (audio_info.encryption, audio_info.encryption_cipher))
else: else:
self.widget.srtp_label.setToolTip(u'Media is not encrypted') self.widget.srtp_label.setToolTip('Media is not encrypted')
self.widget.update_rtp_encryption_icon() self.widget.update_rtp_encryption_icon()
self.srtp = audio_info.encryption is not None self.srtp = audio_info.encryption is not None
if 'statistics' in notification.data.elements: if 'statistics' in notification.data.elements:
...@@ -2293,7 +2287,7 @@ class AudioSessionModel(QAbstractListModel): ...@@ -2293,7 +2287,7 @@ class AudioSessionModel(QAbstractListModel):
if role == Qt.UserRole: if role == Qt.UserRole:
return item return item
elif role == Qt.DisplayRole: elif role == Qt.DisplayRole:
return unicode(item) return str(item)
return None return None
def supportedDropActions(self): def supportedDropActions(self):
...@@ -2682,7 +2676,7 @@ class AudioSessionListView(QListView): ...@@ -2682,7 +2676,7 @@ class AudioSessionListView(QListView):
char = event.text().upper() char = event.text().upper()
if char and char in string.digits+string.uppercase+'#*': if char and char in string.digits+string.uppercase+'#*':
digit_map = {'2': 'ABC', '3': 'DEF', '4': 'GHI', '5': 'JKL', '6': 'MNO', '7': 'PQRS', '8': 'TUV', '9': 'WXYZ'} digit_map = {'2': 'ABC', '3': 'DEF', '4': 'GHI', '5': 'JKL', '6': 'MNO', '7': 'PQRS', '8': 'TUV', '9': 'WXYZ'}
letter_map = {letter: digit for digit, letter_group in digit_map.iteritems() for letter in letter_group} letter_map = {letter: digit for digit, letter_group in digit_map.items() for letter in letter_group}
for session in (s for s in self.model().sessions if s.active): for session in (s for s in self.model().sessions if s.active):
session.send_dtmf(letter_map.get(char, char)) session.send_dtmf(letter_map.get(char, char))
elif event.key() in (Qt.Key_Up, Qt.Key_Down): elif event.key() in (Qt.Key_Up, Qt.Key_Down):
...@@ -2976,9 +2970,9 @@ class ChatSessionIconLabel(QLabel): ...@@ -2976,9 +2970,9 @@ class ChatSessionIconLabel(QLabel):
ui_class, base_class = uic.loadUiType(Resources.get('chat_session.ui')) ui_class, base_class = uic.loadUiType(Resources.get('chat_session.ui'))
class ChatSessionWidget(base_class, ui_class): class ChatSessionWidget(base_class, ui_class):
class StandardDisplayMode: __metaclass__ = MarkerType class StandardDisplayMode(metaclass=MarkerType): pass
class AlternateDisplayMode: __metaclass__ = MarkerType class AlternateDisplayMode(metaclass=MarkerType): pass
class SelectedDisplayMode: __metaclass__ = MarkerType class SelectedDisplayMode(metaclass=MarkerType): pass
def __init__(self, parent=None): def __init__(self, parent=None):
super(ChatSessionWidget, self).__init__(parent) super(ChatSessionWidget, self).__init__(parent)
...@@ -3375,7 +3369,7 @@ class ChatSessionModel(QAbstractListModel): ...@@ -3375,7 +3369,7 @@ class ChatSessionModel(QAbstractListModel):
elif role == Qt.SizeHintRole: elif role == Qt.SizeHintRole:
return item.size_hint return item.size_hint
elif role == Qt.DisplayRole: elif role == Qt.DisplayRole:
return unicode(item) return str(item)
return None return None
def supportedDropActions(self): def supportedDropActions(self):
...@@ -3788,7 +3782,7 @@ ScreenSharingStream.ViewerHandler = EmbeddedVNCViewerHandler ...@@ -3788,7 +3782,7 @@ ScreenSharingStream.ViewerHandler = EmbeddedVNCViewerHandler
# File transfers # File transfers
# #
class RandomID: __metaclass__ = MarkerType class RandomID(metaclass=MarkerType): pass
class FileSizeFormatter(object): class FileSizeFormatter(object):
...@@ -4092,8 +4086,8 @@ class BlinkFileTransfer(BlinkSessionBase): ...@@ -4092,8 +4086,8 @@ class BlinkFileTransfer(BlinkSessionBase):
class TransferStateLabel(QLabel, ColorHelperMixin): class TransferStateLabel(QLabel, ColorHelperMixin):
class ProgressDisplayMode: __metaclass__ = MarkerType class ProgressDisplayMode(metaclass=MarkerType): pass
class InactiveDisplayMode: __metaclass__ = MarkerType class InactiveDisplayMode(metaclass=MarkerType): pass
def __init__(self, parent=None): def __init__(self, parent=None):
super(TransferStateLabel, self).__init__(parent) super(TransferStateLabel, self).__init__(parent)
...@@ -4226,9 +4220,9 @@ ui_class, base_class = uic.loadUiType(Resources.get('filetransfer_item.ui')) ...@@ -4226,9 +4220,9 @@ ui_class, base_class = uic.loadUiType(Resources.get('filetransfer_item.ui'))
class FileTransferItemWidget(base_class, ui_class): class FileTransferItemWidget(base_class, ui_class):
class StandardDisplayMode: __metaclass__ = MarkerType class StandardDisplayMode(metaclass=MarkerType): pass
class AlternateDisplayMode: __metaclass__ = MarkerType class AlternateDisplayMode(metaclass=MarkerType): pass
class SelectedDisplayMode: __metaclass__ = MarkerType class SelectedDisplayMode(metaclass=MarkerType): pass
def __init__(self, parent=None): def __init__(self, parent=None):
super(FileTransferItemWidget, self).__init__(parent) super(FileTransferItemWidget, self).__init__(parent)
...@@ -4287,10 +4281,10 @@ class FileTransferItemWidget(base_class, ui_class): ...@@ -4287,10 +4281,10 @@ class FileTransferItemWidget(base_class, ui_class):
def update_content(self, item, initial=False): def update_content(self, item, initial=False):
if initial: if initial:
if item.direction == 'outgoing': if item.direction == 'outgoing':
self.name_label.setText(u'To: ' + item.name) self.name_label.setText('To: ' + item.name)
self.icon_label.setPixmap(self.pixmaps.outgoing_transfer) self.icon_label.setPixmap(self.pixmaps.outgoing_transfer)
else: else:
self.name_label.setText(u'From: ' + item.name) self.name_label.setText('From: ' + item.name)
self.icon_label.setPixmap(self.pixmaps.incoming_transfer) self.icon_label.setPixmap(self.pixmaps.incoming_transfer)
self.filename_label.setText(os.path.basename(item.filename)) self.filename_label.setText(os.path.basename(item.filename))
self.status_label.setText(item.status) self.status_label.setText(item.status)
...@@ -4353,7 +4347,7 @@ class FileTransferItem(object): ...@@ -4353,7 +4347,7 @@ class FileTransferItem(object):
@property @property
def filename(self): def filename(self):
return self.transfer.filename or u'' return self.transfer.filename or ''
@property @property
def name(self): def name(self):
...@@ -4375,17 +4369,17 @@ class FileTransferItem(object): ...@@ -4375,17 +4369,17 @@ class FileTransferItem(object):
def _NH_BlinkFileTransferDidChangeState(self, notification): def _NH_BlinkFileTransferDidChangeState(self, notification):
state = notification.data.new_state state = notification.data.new_state
if state == 'connecting/dns_lookup': if state == 'connecting/dns_lookup':
self.status = u'Looking up destination...' self.status = 'Looking up destination...'
elif state == 'connecting': elif state == 'connecting':
self.status = u'Connecting...' self.status = 'Connecting...'
elif state == 'connecting/ringing': elif state == 'connecting/ringing':
self.status = u'Ringing...' self.status = 'Ringing...'
elif state == 'connecting/starting': elif state == 'connecting/starting':
self.status = u'Starting...' self.status = 'Starting...'
elif state == 'connected': elif state == 'connected':
self.status = u'Connected' self.status = 'Connected'
elif state == 'ending': elif state == 'ending':
self.status = u'Ending...' self.status = 'Ending...'
else: else:
self.status = None self.status = None
self.progress = None self.progress = None
...@@ -4394,7 +4388,7 @@ class FileTransferItem(object): ...@@ -4394,7 +4388,7 @@ class FileTransferItem(object):
def _NH_BlinkFileTransferDidInitialize(self, notification): def _NH_BlinkFileTransferDidInitialize(self, notification):
self.progress = None self.progress = None
self.status = u'Connecting...' self.status = 'Connecting...'
self.widget.update_content(self) self.widget.update_content(self)
notification.center.post_notification('FileTransferItemDidChange', sender=self) notification.center.post_notification('FileTransferItemDidChange', sender=self)
...@@ -4402,7 +4396,7 @@ class FileTransferItem(object): ...@@ -4402,7 +4396,7 @@ class FileTransferItem(object):
progress = notification.data.progress progress = notification.data.progress
if self.progress is None or progress > self.progress: if self.progress is None or progress > self.progress:
self.progress = progress self.progress = progress
self.status = u'Computing hash (%s%%)' % notification.data.progress self.status = 'Computing hash (%s%%)' % notification.data.progress
self.widget.update_content(self) self.widget.update_content(self)
notification.center.post_notification('FileTransferItemDidChange', sender=self) notification.center.post_notification('FileTransferItemDidChange', sender=self)
...@@ -4410,7 +4404,7 @@ class FileTransferItem(object): ...@@ -4410,7 +4404,7 @@ class FileTransferItem(object):
self.bytes = notification.data.bytes self.bytes = notification.data.bytes
self.total_bytes = notification.data.total_bytes self.total_bytes = notification.data.total_bytes
progress = int(self.bytes * 100 / self.total_bytes) progress = int(self.bytes * 100 / self.total_bytes)
status = u'Transferring: %s/%s (%s%%)' % (FileSizeFormatter.format(self.bytes), FileSizeFormatter.format(self.total_bytes), progress) status = 'Transferring: %s/%s (%s%%)' % (FileSizeFormatter.format(self.bytes), FileSizeFormatter.format(self.total_bytes), progress)
if self.progress is None or progress > self.progress or status != self.status: if self.progress is None or progress > self.progress or status != self.status:
self.progress = progress self.progress = progress
self.status = status self.status = status
...@@ -4574,7 +4568,7 @@ class FileTransferModel(QAbstractListModel): ...@@ -4574,7 +4568,7 @@ class FileTransferModel(QAbstractListModel):
elif role == Qt.SizeHintRole: elif role == Qt.SizeHintRole:
return item.widget.sizeHint() return item.widget.sizeHint()
elif role == Qt.DisplayRole: elif role == Qt.DisplayRole:
return unicode(item) return str(item)
return None return None
def addItem(self, item): def addItem(self, item):
...@@ -4826,7 +4820,7 @@ class ConferenceParticipantModel(QAbstractListModel): ...@@ -4826,7 +4820,7 @@ class ConferenceParticipantModel(QAbstractListModel):
elif role == Qt.SizeHintRole: elif role == Qt.SizeHintRole:
return item.size_hint return item.size_hint
elif role == Qt.DisplayRole: elif role == Qt.DisplayRole:
return unicode(item) return str(item)
return None return None
def supportedDropActions(self): def supportedDropActions(self):
...@@ -5063,7 +5057,7 @@ class DialogSlots(object): ...@@ -5063,7 +5057,7 @@ class DialogSlots(object):
class IncomingDialogBase(QDialog): class IncomingDialogBase(QDialog):
_slots = DialogSlots(range(1, 100)) _slots = DialogSlots(list(range(1, 100)))
slot = None slot = None
...@@ -5160,22 +5154,22 @@ class IncomingDialog(IncomingDialogBase, ui_class): ...@@ -5160,22 +5154,22 @@ class IncomingDialog(IncomingDialogBase, ui_class):
self.chat_stream.active = True self.chat_stream.active = True
self.screensharing_stream.active = True self.screensharing_stream.active = True
self.video_stream.active = True self.video_stream.active = True
self.note_label.setText(u'To refuse a media type click its icon') self.note_label.setText('To refuse a media type click its icon')
else: else:
self.audio_stream.active = False self.audio_stream.active = False
self.chat_stream.active = False self.chat_stream.active = False
self.screensharing_stream.active = False self.screensharing_stream.active = False
self.video_stream.active = False self.video_stream.active = False
if self.audio_stream.in_use: if self.audio_stream.in_use:
self.note_label.setText(u'Audio call') self.note_label.setText('Audio call')
elif self.chat_stream.in_use: elif self.chat_stream.in_use:
self.note_label.setText(u'Chat session') self.note_label.setText('Chat session')
elif self.video_stream.in_use: elif self.video_stream.in_use:
self.note_label.setText(u'Video call') self.note_label.setText('Video call')
elif self.screensharing_stream.in_use: elif self.screensharing_stream.in_use:
self.note_label.setText(u'Screen sharing request') self.note_label.setText('Screen sharing request')
else: else:
self.note_label.setText(u'') self.note_label.setText('')
self._update_accept_button() self._update_accept_button()
del ui_class, base_class del ui_class, base_class
...@@ -5199,11 +5193,11 @@ class IncomingRequest(QObject): ...@@ -5199,11 +5193,11 @@ class IncomingRequest(QObject):
self.screensharing_stream = screensharing_stream self.screensharing_stream = screensharing_stream
if proposal: if proposal:
self.dialog.setWindowTitle(u'Incoming Session Update') self.dialog.setWindowTitle('Incoming Session Update')
self.dialog.busy_button.hide() self.dialog.busy_button.hide()
else: else:
self.dialog.setWindowTitle(u'Incoming Session Request') self.dialog.setWindowTitle('Incoming Session Request')
address = u'%s@%s' % (session.remote_identity.uri.user, session.remote_identity.uri.host) address = '%s@%s' % (session.remote_identity.uri.user, session.remote_identity.uri.host)
self.dialog.uri_label.setText(address) self.dialog.uri_label.setText(address)
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.pixmap(48)) self.dialog.user_icon.setPixmap(contact.icon.pixmap(48))
...@@ -5213,9 +5207,9 @@ class IncomingRequest(QObject): ...@@ -5213,9 +5207,9 @@ class IncomingRequest(QObject):
self.dialog.screensharing_stream.setVisible(self.screensharing_stream is not None) self.dialog.screensharing_stream.setVisible(self.screensharing_stream is not None)
if self.screensharing_stream is not None: if self.screensharing_stream is not None:
if self.screensharing_stream.handler.type == 'active': if self.screensharing_stream.handler.type == 'active':
self.dialog.screensharing_label.setText(u'is offering to share his screen') self.dialog.screensharing_label.setText('is offering to share his screen')
else: else:
self.dialog.screensharing_label.setText(u'is asking to share your screen') self.dialog.screensharing_label.setText('is asking to share your screen')
# self.dialog.screensharing_stream.accepted = bool(proposal) # self.dialog.screensharing_stream.accepted = bool(proposal)
self.dialog.finished.connect(self._SH_DialogFinished) self.dialog.finished.connect(self._SH_DialogFinished)
...@@ -5278,7 +5272,7 @@ class IncomingRequest(QObject): ...@@ -5278,7 +5272,7 @@ class IncomingRequest(QObject):
elif self.chat_stream: elif self.chat_stream:
return 3 return 3
else: else:
return sys.maxint return sys.maxsize
@property @property
def stream_types(self): def stream_types(self):
...@@ -5343,9 +5337,9 @@ class IncomingFileTransferRequest(QObject): ...@@ -5343,9 +5337,9 @@ class IncomingFileTransferRequest(QObject):
filename = os.path.basename(self.stream.file_selector.name) filename = os.path.basename(self.stream.file_selector.name)
size = self.stream.file_selector.size size = self.stream.file_selector.size
if size: if size:
self.dialog.file_label.setText(u'File: %s (%s)' % (filename, FileSizeFormatter.format(size))) self.dialog.file_label.setText('File: %s (%s)' % (filename, FileSizeFormatter.format(size)))
else: else:
self.dialog.file_label.setText(u'File: %s' % filename) self.dialog.file_label.setText('File: %s' % filename)
self.dialog.finished.connect(self._SH_DialogFinished) self.dialog.finished.connect(self._SH_DialogFinished)
...@@ -5418,7 +5412,7 @@ class IncomingCallTransferRequest(QObject): ...@@ -5418,7 +5412,7 @@ class IncomingCallTransferRequest(QObject):
self.dialog.uri_label.setText(contact_uri.uri) self.dialog.uri_label.setText(contact_uri.uri)
self.dialog.username_label.setText(contact.name) self.dialog.username_label.setText(contact.name)
self.dialog.user_icon.setPixmap(contact.icon.pixmap(48)) self.dialog.user_icon.setPixmap(contact.icon.pixmap(48))
self.dialog.transfer_label.setText(u'transfer requested by {}'.format(blink_session.contact.name or blink_session.contact_uri.uri)) self.dialog.transfer_label.setText('transfer requested by {}'.format(blink_session.contact.name or blink_session.contact_uri.uri))
self.dialog.finished.connect(self._SH_DialogFinished) self.dialog.finished.connect(self._SH_DialogFinished)
...@@ -5462,10 +5456,10 @@ class ConferenceDialog(base_class, ui_class): ...@@ -5462,10 +5456,10 @@ class ConferenceDialog(base_class, ui_class):
self.accepted.connect(self.join_conference) self.accepted.connect(self.join_conference)
def _SH_MediaButtonClicked(self, checked): def _SH_MediaButtonClicked(self, checked):
self.accept_button.setEnabled(self.room_button.currentText() != u'' and any(button.isChecked() for button in (self.audio_button, self.chat_button))) self.accept_button.setEnabled(self.room_button.currentText() != '' and any(button.isChecked() for button in (self.audio_button, self.chat_button)))
def _SH_RoomButtonEditTextChanged(self, text): def _SH_RoomButtonEditTextChanged(self, text):
self.accept_button.setEnabled(text != u'' and any(button.isChecked() for button in (self.audio_button, self.chat_button))) self.accept_button.setEnabled(text != '' and any(button.isChecked() for button in (self.audio_button, self.chat_button)))
def show(self): def show(self):
self.room_button.setCurrentIndex(-1) self.room_button.setCurrentIndex(-1)
...@@ -5487,9 +5481,9 @@ class ConferenceDialog(base_class, ui_class): ...@@ -5487,9 +5481,9 @@ class ConferenceDialog(base_class, ui_class):
session_manager = SessionManager() session_manager = SessionManager()
account = account_manager.default_account account = account_manager.default_account
if account is not BonjourAccount(): if account is not BonjourAccount():
conference_uri = u'%s@%s' % (current_text, account.server.conference_server or 'conference.sip2sip.info') conference_uri = '%s@%s' % (current_text, account.server.conference_server or 'conference.sip2sip.info')
else: else:
conference_uri = u'%s@%s' % (current_text, 'conference.sip2sip.info') conference_uri = '%s@%s' % (current_text, 'conference.sip2sip.info')
contact, contact_uri = URIUtils.find_contact(conference_uri, display_name='Conference') contact, contact_uri = URIUtils.find_contact(conference_uri, display_name='Conference')
streams = [] streams = []
if self.audio_button.isChecked(): if self.audio_button.isChecked():
...@@ -5526,7 +5520,7 @@ class RingtoneDescriptor(object): ...@@ -5526,7 +5520,7 @@ class RingtoneDescriptor(object):
class RequestList(list): class RequestList(list):
def __getitem__(self, key): def __getitem__(self, key):
if isinstance(key, (int, long)): if isinstance(key, int):
return super(RequestList, self).__getitem__(key) return super(RequestList, self).__getitem__(key)
elif isinstance(key, tuple): elif isinstance(key, tuple):
session, item_type = key session, item_type = key
...@@ -5535,13 +5529,11 @@ class RequestList(list): ...@@ -5535,13 +5529,11 @@ class RequestList(list):
return [item for item in self if item.session is key] return [item for item in self if item.session is key]
class SessionManager(object): class SessionManager(object, metaclass=Singleton):
__metaclass__ = Singleton
implements(IObserver) implements(IObserver)
class PrimaryRingtone: __metaclass__ = MarkerType class PrimaryRingtone(metaclass=MarkerType): pass
class SecondaryRingtone: __metaclass__ = MarkerType class SecondaryRingtone(metaclass=MarkerType): pass
inbound_ringtone = RingtoneDescriptor() inbound_ringtone = RingtoneDescriptor()
outbound_ringtone = RingtoneDescriptor() outbound_ringtone = RingtoneDescriptor()
......
...@@ -90,7 +90,7 @@ class FunctionExecutor(object): ...@@ -90,7 +90,7 @@ class FunctionExecutor(object):
def wait(self): def wait(self):
self.event.wait() self.event.wait()
if self.exception is not None: if self.exception is not None:
raise type(self.exception), self.exception, self.traceback raise type(self.exception)(self.exception).with_traceback(self.traceback)
else: else:
return self.result return self.result
......
...@@ -28,8 +28,8 @@ class ConferenceButton(ToolButton): ...@@ -28,8 +28,8 @@ class ConferenceButton(ToolButton):
def __init__(self, parent=None): def __init__(self, parent=None):
super(ConferenceButton, self).__init__(parent) super(ConferenceButton, self).__init__(parent)
self.make_conference_action = QAction(u'Conference all single sessions', self, triggered=self.makeConference.emit) self.make_conference_action = QAction('Conference all single sessions', self, triggered=self.makeConference.emit)
self.break_conference_action = QAction(u'Break selected conference', self, triggered=self.breakConference.emit) self.break_conference_action = QAction('Break selected conference', self, triggered=self.breakConference.emit)
self.toggled.connect(self._SH_Toggled) self.toggled.connect(self._SH_Toggled)
self.addAction(self.make_conference_action) self.addAction(self.make_conference_action)
...@@ -105,8 +105,7 @@ class SegmentTypeMeta(type): ...@@ -105,8 +105,7 @@ class SegmentTypeMeta(type):
return cls.__name__ return cls.__name__
class SegmentType(object): class SegmentType(object, metaclass=SegmentTypeMeta):
__metaclass__ = SegmentTypeMeta
style_sheet = '' style_sheet = ''
...@@ -260,8 +259,8 @@ class SwitchViewButton(QPushButton): ...@@ -260,8 +259,8 @@ class SwitchViewButton(QPushButton):
viewChanged = pyqtSignal(int) viewChanged = pyqtSignal(int)
button_text = {ContactView: u'Switch to Calls', SessionView: u'Switch to Contacts'} button_text = {ContactView: 'Switch to Calls', SessionView: 'Switch to Contacts'}
button_dnd_text = {ContactView: u'Drag here to add to a conference', SessionView: u'Drag here to go back to contacts'} button_dnd_text = {ContactView: 'Drag here to add to a conference', SessionView: 'Drag here to go back to contacts'}
dnd_style_sheet1 = """ dnd_style_sheet1 = """
QPushButton { QPushButton {
......
...@@ -16,7 +16,7 @@ class SlidingStackedWidget(QStackedWidget): ...@@ -16,7 +16,7 @@ class SlidingStackedWidget(QStackedWidget):
animationFinished = pyqtSignal() animationFinished = pyqtSignal()
LeftToRight, RightToLeft, TopToBottom, BottomToTop, Automatic = range(5) LeftToRight, RightToLeft, TopToBottom, BottomToTop, Automatic = list(range(5))
def __init__(self, parent=None): def __init__(self, parent=None):
super(SlidingStackedWidget, self).__init__(parent) super(SlidingStackedWidget, self).__init__(parent)
......
...@@ -11,8 +11,8 @@ __all__ = ['BackgroundFrame'] ...@@ -11,8 +11,8 @@ __all__ = ['BackgroundFrame']
class BackgroundFrame(QFrame): class BackgroundFrame(QFrame):
backgroundColor = QtDynamicProperty('backgroundColor', unicode) backgroundColor = QtDynamicProperty('backgroundColor', str)
backgroundImage = QtDynamicProperty('backgroundImage', unicode) backgroundImage = QtDynamicProperty('backgroundImage', str)
imageGeometry = QtDynamicProperty('imageGeometry', QRect) imageGeometry = QtDynamicProperty('imageGeometry', QRect)
def __init__(self, parent=None): def __init__(self, parent=None):
......
...@@ -16,9 +16,7 @@ from blink.widgets.util import QtDynamicProperty ...@@ -16,9 +16,7 @@ from blink.widgets.util import QtDynamicProperty
__all__ = ['Graph', 'GraphWidget', 'HeightScaler', 'LogarithmicScaler', 'MaxScaler', 'SoftScaler'] __all__ = ['Graph', 'GraphWidget', 'HeightScaler', 'LogarithmicScaler', 'MaxScaler', 'SoftScaler']
class HeightScaler(object): class HeightScaler(object, metaclass=ABCMeta):
__metaclass__ = ABCMeta
@abstractmethod @abstractmethod
def get_height(self, max_value): def get_height(self, max_value):
raise NotImplementedError raise NotImplementedError
...@@ -91,7 +89,7 @@ class GraphWidget(QWidget, ColorHelperMixin): ...@@ -91,7 +89,7 @@ class GraphWidget(QWidget, ColorHelperMixin):
fillEnvelope = QtDynamicProperty('fillEnvelope', type=bool) fillEnvelope = QtDynamicProperty('fillEnvelope', type=bool)
fillTransparency = QtDynamicProperty('fillTransparency', type=int) fillTransparency = QtDynamicProperty('fillTransparency', type=int)
EnvelopeStyle, BarStyle = range(2) EnvelopeStyle, BarStyle = list(range(2))
AutomaticHeight = 0 AutomaticHeight = 0
updated = pyqtSignal() updated = pyqtSignal()
......
...@@ -22,13 +22,13 @@ class IconSelector(QLabel): ...@@ -22,13 +22,13 @@ class IconSelector(QLabel):
default_icon = QtDynamicProperty('default_icon', QIcon) default_icon = QtDynamicProperty('default_icon', QIcon)
icon_size = QtDynamicProperty('icon_size', int) icon_size = QtDynamicProperty('icon_size', int)
class NotSelected: __metaclass__ = MarkerType class NotSelected(metaclass=MarkerType): pass
def __init__(self, parent=None): def __init__(self, parent=None):
super(IconSelector, self).__init__(parent) super(IconSelector, self).__init__(parent)
self.actions = ContextMenuActions() self.actions = ContextMenuActions()
self.actions.select_icon = QAction(u'Select icon...', self, triggered=self._SH_ChangeIconActionTriggered) self.actions.select_icon = QAction('Select icon...', self, triggered=self._SH_ChangeIconActionTriggered)
self.actions.remove_icon = QAction(u'Use contact provided icon', self, triggered=self._SH_RemoveIconActionTriggered) self.actions.remove_icon = QAction('Use contact provided icon', self, triggered=self._SH_RemoveIconActionTriggered)
self.icon_size = 48 self.icon_size = 48
self.default_icon = None self.default_icon = None
self.contact_icon = None self.contact_icon = None
...@@ -107,7 +107,7 @@ class IconSelector(QLabel): ...@@ -107,7 +107,7 @@ class IconSelector(QLabel):
super(IconSelector, self).mouseReleaseEvent(event) super(IconSelector, self).mouseReleaseEvent(event)
def _SH_ChangeIconActionTriggered(self): def _SH_ChangeIconActionTriggered(self):
filename = QFileDialog.getOpenFileName(self, u'Select Icon', self.last_icon_directory, u"Images (*.png *.tiff *.jpg *.xmp *.svg)")[0] filename = QFileDialog.getOpenFileName(self, 'Select Icon', self.last_icon_directory, "Images (*.png *.tiff *.jpg *.xmp *.svg)")[0]
if filename: if filename:
self.filename = filename self.filename = filename
...@@ -147,11 +147,11 @@ class StreamInfoLabel(QLabel): ...@@ -147,11 +147,11 @@ class StreamInfoLabel(QLabel):
def update_content(self): def update_content(self):
if self.session_type and self.codec_info: if self.session_type and self.codec_info:
text = u'%s (%s)' % (self.session_type, self.codec_info) text = '%s (%s)' % (self.session_type, self.codec_info)
if self.width() < QFontMetrics(self.font()).width(text): if self.width() < QFontMetrics(self.font()).width(text):
text = self.session_type text = self.session_type
else: else:
text = self.session_type or u'' text = self.session_type or ''
self.setText(text) self.setText(text)
...@@ -168,7 +168,7 @@ class DurationLabel(QLabel): ...@@ -168,7 +168,7 @@ class DurationLabel(QLabel):
seconds = value.seconds % 60 seconds = value.seconds % 60
minutes = value.seconds // 60 % 60 minutes = value.seconds // 60 % 60
hours = value.seconds//3600 + value.days*24 hours = value.seconds//3600 + value.days*24
self.setText(u'%d:%02d:%02d' % (hours, minutes, seconds)) self.setText('%d:%02d:%02d' % (hours, minutes, seconds))
value = property(_get_value, _set_value) value = property(_get_value, _set_value)
del _get_value, _set_value del _get_value, _set_value
...@@ -186,7 +186,7 @@ class LatencyLabel(QLabel): ...@@ -186,7 +186,7 @@ class LatencyLabel(QLabel):
def _set_value(self, value): def _set_value(self, value):
self.__dict__['value'] = value self.__dict__['value'] = value
if value > self.threshold: if value > self.threshold:
text = u'Latency %sms' % value text = 'Latency %sms' % value
self.setMinimumWidth(QFontMetrics(self.font()).width(text)) self.setMinimumWidth(QFontMetrics(self.font()).width(text))
self.setText(text) self.setText(text)
self.show() self.show()
...@@ -209,7 +209,7 @@ class PacketLossLabel(QLabel): ...@@ -209,7 +209,7 @@ class PacketLossLabel(QLabel):
def _set_value(self, value): def _set_value(self, value):
self.__dict__['value'] = value self.__dict__['value'] = value
if value > self.threshold: if value > self.threshold:
text = u'Packet loss %s%%' % value text = 'Packet loss %s%%' % value
self.setMinimumWidth(QFontMetrics(self.font()).width(text)) self.setMinimumWidth(QFontMetrics(self.font()).width(text))
self.setText(text) self.setText(text)
self.show() self.show()
...@@ -220,7 +220,7 @@ class PacketLossLabel(QLabel): ...@@ -220,7 +220,7 @@ class PacketLossLabel(QLabel):
del _get_value, _set_value del _get_value, _set_value
class Status(unicode): class Status(str):
def __new__(cls, value, color='black', context=None): def __new__(cls, value, color='black', context=None):
instance = super(Status, cls).__new__(cls, value) instance = super(Status, cls).__new__(cls, value)
instance.color = color instance.color = color
...@@ -230,7 +230,7 @@ class Status(unicode): ...@@ -230,7 +230,7 @@ class Status(unicode):
def __eq__(self, other): def __eq__(self, other):
if isinstance(other, Status): if isinstance(other, Status):
return super(Status, self).__eq__(other) and self.color == other.color and self.context == other.context return super(Status, self).__eq__(other) and self.color == other.color and self.context == other.context
elif isinstance(other, basestring): elif isinstance(other, str):
return super(Status, self).__eq__(other) return super(Status, self).__eq__(other)
return NotImplemented return NotImplemented
...@@ -256,9 +256,9 @@ class StatusLabel(QLabel): ...@@ -256,9 +256,9 @@ class StatusLabel(QLabel):
palette.setColor(QPalette.Inactive, QPalette.WindowText, color) palette.setColor(QPalette.Inactive, QPalette.WindowText, color)
palette.setColor(QPalette.Inactive, QPalette.Text, color) palette.setColor(QPalette.Inactive, QPalette.Text, color)
self.setPalette(palette) self.setPalette(palette)
self.setText(unicode(value)) self.setText(str(value))
else: else:
self.setText(u'') self.setText('')
value = property(_get_value, _set_value) value = property(_get_value, _set_value)
del _get_value, _set_value del _get_value, _set_value
...@@ -301,7 +301,7 @@ class StateColorMapping(dict): ...@@ -301,7 +301,7 @@ class StateColorMapping(dict):
class ContactState(QLabel, ColorHelperMixin): class ContactState(QLabel, ColorHelperMixin):
state = QtDynamicProperty('state', unicode) state = QtDynamicProperty('state', str)
def __init__(self, parent=None): def __init__(self, parent=None):
super(ContactState, self).__init__(parent) super(ContactState, self).__init__(parent)
......
...@@ -25,13 +25,13 @@ class SideWidget(QWidget): ...@@ -25,13 +25,13 @@ class SideWidget(QWidget):
class LineEdit(QLineEdit): class LineEdit(QLineEdit):
inactiveText = QtDynamicProperty('inactiveText', unicode) inactiveText = QtDynamicProperty('inactiveText', str)
widgetSpacing = QtDynamicProperty('widgetSpacing', int) widgetSpacing = QtDynamicProperty('widgetSpacing', int)
def __init__(self, parent=None, contents=u""): def __init__(self, parent=None, contents=""):
super(LineEdit, self).__init__(contents, parent) super(LineEdit, self).__init__(contents, parent)
box_direction = QBoxLayout.RightToLeft if self.isRightToLeft() else QBoxLayout.LeftToRight box_direction = QBoxLayout.RightToLeft if self.isRightToLeft() else QBoxLayout.LeftToRight
self.inactiveText = u"" self.inactiveText = ""
self.left_widget = SideWidget(self) self.left_widget = SideWidget(self)
self.left_widget.resize(0, 0) self.left_widget.resize(0, 0)
self.left_layout = QHBoxLayout(self.left_widget) self.left_layout = QHBoxLayout(self.left_widget)
...@@ -211,7 +211,7 @@ class ClearButton(QAbstractButton): ...@@ -211,7 +211,7 @@ class ClearButton(QAbstractButton):
super(ClearButton, self).__init__(parent) super(ClearButton, self).__init__(parent)
self.setCursor(Qt.ArrowCursor) self.setCursor(Qt.ArrowCursor)
self.setFocusPolicy(Qt.NoFocus) self.setFocusPolicy(Qt.NoFocus)
self.setToolTip(u"Clear") self.setToolTip("Clear")
self.setVisible(False) self.setVisible(False)
self.setMinimumSize(size+2, size+2) self.setMinimumSize(size+2, size+2)
pixmap = QPixmap() pixmap = QPixmap()
...@@ -274,7 +274,7 @@ class SearchBox(LineEdit): ...@@ -274,7 +274,7 @@ class SearchBox(LineEdit):
self.clear_button.hide() self.clear_button.hide()
self.clear_button.clicked.connect(self.clear) self.clear_button.clicked.connect(self.clear)
self.textChanged.connect(self._SH_TextChanged) self.textChanged.connect(self._SH_TextChanged)
self.inactiveText = u"Search" self.inactiveText = "Search"
def keyPressEvent(self, event): def keyPressEvent(self, event):
if event.key() == Qt.Key_Escape: if event.key() == Qt.Key_Escape:
......
...@@ -56,10 +56,10 @@ class OTRWidget(base_class, ui_class): ...@@ -56,10 +56,10 @@ class OTRWidget(base_class, ui_class):
@peer_verified.setter @peer_verified.setter
def peer_verified(self, verified): def peer_verified(self, verified):
self.__dict__['peer_verified'] = verified self.__dict__['peer_verified'] = verified
self.validate_button.setText(u'Invalidate' if verified else u'Validate') self.validate_button.setText('Invalidate' if verified else 'Validate')
self.validate_button.setChecked(verified) self.validate_button.setChecked(verified)
self.validate_button.setEnabled(verified or self.verification_stack.currentWidget() is not self.smp_panel or self.smp_status is SMPVerification.Succeeded) self.validate_button.setEnabled(verified or self.verification_stack.currentWidget() is not self.smp_panel or self.smp_status is SMPVerification.Succeeded)
self.peer_fingerprint_value.setStyleSheet(u'QLabel {{ color: {}; }}'.format(self.color_table['green'] if verified else self.color_table['orange'])) self.peer_fingerprint_value.setStyleSheet('QLabel {{ color: {}; }}'.format(self.color_table['green'] if verified else self.color_table['orange']))
self.smp_status_value.setText(self.smp_status_text) self.smp_status_value.setText(self.smp_status_text)
@property @property
...@@ -93,13 +93,13 @@ class OTRWidget(base_class, ui_class): ...@@ -93,13 +93,13 @@ class OTRWidget(base_class, ui_class):
@property @property
def smp_status_text(self): def smp_status_text(self):
if self.peer_verified: if self.peer_verified:
return u'<span style="color: {[green]};">Verified</span>'.format(self.color_table) return '<span style="color: {[green]};">Verified</span>'.format(self.color_table)
elif self.smp_status is SMPVerification.Succeeded: elif self.smp_status is SMPVerification.Succeeded:
return u'<span style="color: {[green]};">Succeeded</span>'.format(self.color_table) return '<span style="color: {[green]};">Succeeded</span>'.format(self.color_table)
elif self.smp_status is SMPVerification.Failed: elif self.smp_status is SMPVerification.Failed:
return u'<span style="color: {[orange]};">Failed</span>'.format(self.color_table) return '<span style="color: {[orange]};">Failed</span>'.format(self.color_table)
else: else:
return u'{}'.format(self.smp_status.value) return '{}'.format(self.smp_status.value)
def hideEvent(self, event): def hideEvent(self, event):
if not event.spontaneous(): if not event.spontaneous():
......
from __future__ import division
from PyQt5.QtCore import QEvent, QRectF, QSize from PyQt5.QtCore import QEvent, QRectF, QSize
from PyQt5.QtSvg import QSvgWidget from PyQt5.QtSvg import QSvgWidget
...@@ -12,7 +12,7 @@ __all__ = ['Spinner'] ...@@ -12,7 +12,7 @@ __all__ = ['Spinner']
class Spinner(QSvgWidget): class Spinner(QSvgWidget):
icon_file = QtDynamicProperty('icon_file', type=unicode) icon_file = QtDynamicProperty('icon_file', type=str)
icon_size = QtDynamicProperty('icon_size', type=QSize) icon_size = QtDynamicProperty('icon_size', type=QSize)
icon_crop = QtDynamicProperty('icon_crop', type=int) icon_crop = QtDynamicProperty('icon_crop', type=int)
......
...@@ -4,7 +4,7 @@ __all__ = ['QtDynamicProperty', 'ContextMenuActions'] ...@@ -4,7 +4,7 @@ __all__ = ['QtDynamicProperty', 'ContextMenuActions']
class QtDynamicProperty(object): class QtDynamicProperty(object):
def __init__(self, name, type=unicode): def __init__(self, name, type=str):
self.name = name self.name = name
self.type = type self.type = type
......
from __future__ import division
from PyQt5.QtCore import Qt, QMetaObject, QPoint, QRect, QTimer, pyqtSignal from PyQt5.QtCore import Qt, QMetaObject, QPoint, QRect, QTimer, pyqtSignal
from PyQt5.QtGui import QColor, QCursor, QIcon, QImage, QPainter, QPixmap, QTransform from PyQt5.QtGui import QColor, QCursor, QIcon, QImage, QPainter, QPixmap, QTransform
...@@ -37,10 +37,10 @@ class InteractionState(object): ...@@ -37,10 +37,10 @@ class InteractionState(object):
class VideoSurface(QWidget): class VideoSurface(QWidget):
class TopLeftCorner: __metaclass__ = MarkerType class TopLeftCorner(metaclass=MarkerType): pass
class TopRightCorner: __metaclass__ = MarkerType class TopRightCorner(metaclass=MarkerType): pass
class BottomLeftCorner: __metaclass__ = MarkerType class BottomLeftCorner(metaclass=MarkerType): pass
class BottomRightCorner: __metaclass__ = MarkerType class BottomRightCorner(metaclass=MarkerType): pass
adjusted = pyqtSignal(QRect, QRect) # the widget was adjusted by the user (if interactive) adjusted = pyqtSignal(QRect, QRect) # the widget was adjusted by the user (if interactive)
......
...@@ -43,11 +43,11 @@ class ZRTPWidget(base_class, ui_class): ...@@ -43,11 +43,11 @@ class ZRTPWidget(base_class, ui_class):
def _set_peer_verified(self, verified): def _set_peer_verified(self, verified):
self.__dict__['peer_verified'] = verified self.__dict__['peer_verified'] = verified
if verified: if verified:
self.validate_button.setText(u'Invalidate') self.validate_button.setText('Invalidate')
self.status_value.setText(u'<span style="color: hsv(100, 85%, 100%);">Verified</span>') self.status_value.setText('<span style="color: hsv(100, 85%, 100%);">Verified</span>')
else: else:
self.validate_button.setText(u'Validate') self.validate_button.setText('Validate')
self.status_value.setText(u'<span style="color: hsv(20, 85%, 100%);">Not verified</span>') self.status_value.setText('<span style="color: hsv(20, 85%, 100%);">Not verified</span>')
self.validate_button.setChecked(verified) self.validate_button.setChecked(verified)
peer_verified = property(_get_peer_verified, _set_peer_verified) peer_verified = property(_get_peer_verified, _set_peer_verified)
......
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