Commit e6145b72 authored by Dan Pascu's avatar Dan Pascu

Modernized code and improved PEP-8 compliance

parent 8c6e300f
#
# Boring file regular expresions
# Boring file regular expressions
#
~$
......
__all__ = ['Blink']
__version__ = '1.4.2'
__date__ = 'December 4th 2015'
import os
import sys
import sip
......@@ -42,6 +38,7 @@ try:
from blink import branding
except ImportError:
branding = Null
from blink.chatwindow import ChatWindow
from blink.configuration.account import AccountExtension, BonjourAccountExtension
from blink.configuration.addressbook import ContactExtension, GroupExtension
......@@ -56,6 +53,9 @@ from blink.update import UpdateManager
from blink.util import QSingleton, run_in_gui_thread
__all__ = ['Blink']
if hasattr(sys, 'frozen'):
output = sys.stdout
makedirs(ApplicationData.get('logs'))
......@@ -293,7 +293,7 @@ class Blink(QApplication):
self.main_window.show()
settings = SIPSimpleSettings()
accounts = AccountManager().get_accounts()
if not accounts or (self.first_run and accounts==[BonjourAccount()]):
if not accounts or (self.first_run and accounts == [BonjourAccount()]):
self.main_window.preferences_window.show_create_account_dialog()
if settings.google_contacts.authorization_token is InvalidToken:
self.main_window.google_contacts_dialog.open_for_incorrect_password()
......
__all__ = ['AboutPanel']
from PyQt4 import uic
from blink import __date__, __version__
......@@ -8,6 +6,9 @@ from blink.resources import Resources
from blink.util import QSingleton
__all__ = ['AboutPanel']
credits_text = """
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
<html>
......@@ -32,6 +33,7 @@ credits_text = """
ui_class, base_class = uic.loadUiType(Resources.get('about_panel.ui'))
class AboutPanel(base_class, ui_class):
__metaclass__ = QSingleton
......@@ -43,16 +45,16 @@ class AboutPanel(base_class, ui_class):
self.version.setText(u'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.document().documentLayout().documentSizeChanged.connect(self._credits_size_changed)
self.credits_text.setHtml(credits_text)
def _credits_size_changed(self, size):
self.credits_text.document().documentLayout().documentSizeChanged.disconnect(self._credits_size_changed)
self.setFixedSize(self.minimumSize().width(), self.minimumSize().width()*1.40) # set a fixed aspect ratio
row_height = self.credits_text.fontMetrics().height() + 2 # +2 for cellspacing
max_credits_height = 8*row_height + 2 + 14 # allow for maximum 8 rows; +2 for cellspacing and +14 for top/bottom margins
self.setFixedSize(self.minimumSize().width(), self.minimumSize().width()*1.40) # set a fixed aspect ratio
row_height = self.credits_text.fontMetrics().height() + 2 # +2 for cellspacing
max_credits_height = 8*row_height + 2 + 14 # allow for maximum 8 rows; +2 for cellspacing and +14 for top/bottom margins
if self.credits_text.height() > max_credits_height:
self.setFixedHeight(self.height() - (self.credits_text.height() - max_credits_height))
......
__all__ = ['AccountModel', 'ActiveAccountModel', 'AccountSelector', 'AddAccountDialog', 'ServerToolsAccountModel', 'ServerToolsWindow']
import os
import re
import sys
......@@ -10,9 +8,9 @@ from collections import defaultdict
from PyQt4 import uic
from PyQt4.QtCore import Qt, QAbstractListModel, QModelIndex, QUrl
from PyQt4.QtGui import QAction, QButtonGroup, QComboBox, QIcon, QMenu, QMovie, QSortFilterProxyModel
from PyQt4.QtGui import QAction, QButtonGroup, QComboBox, QIcon, QMenu, QMovie, QSortFilterProxyModel
from PyQt4.QtNetwork import QNetworkAccessManager
from PyQt4.QtWebKit import QWebView
from PyQt4.QtWebKit import QWebView
import cjson
from application.notification import IObserver, NotificationCenter
......@@ -31,17 +29,23 @@ from blink.widgets.labels import Status
from blink.util import QSingleton, call_in_gui_thread, run_in_gui_thread
__all__ = ['AccountModel', 'ActiveAccountModel', 'AccountSelector', 'AddAccountDialog', 'ServerToolsAccountModel', 'ServerToolsWindow']
class IconDescriptor(object):
def __init__(self, filename):
self.filename = filename
self.icon = None
def __get__(self, obj, objtype):
def __get__(self, instance, owner):
if self.icon is None:
self.icon = QIcon(self.filename)
self.icon.filename = self.filename
return self.icon
def __set__(self, obj, value):
raise AttributeError("attribute cannot be set")
def __delete__(self, obj):
raise AttributeError("attribute cannot be deleted")
......@@ -222,6 +226,7 @@ class AccountSelector(QComboBox):
ui_class, base_class = uic.loadUiType(Resources.get('add_account.ui'))
class AddAccountDialog(base_class, ui_class):
__metaclass__ = QSingleton
......@@ -241,9 +246,9 @@ class AddAccountDialog(base_class, ui_class):
font.setFamily("Sans Serif")
self.title_label.setFont(font)
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()
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(u'The E-mail address is used when sending voicemail')) # hack to make text justification look nice everywhere
self.add_account_button.setChecked(True)
self.panel_view.setCurrentWidget(self.add_account_panel)
self.new_password_editor.textChanged.connect(self._SH_PasswordTextChanged)
......@@ -259,7 +264,7 @@ class AddAccountDialog(base_class, ui_class):
self.email_address_editor.statusChanged.connect(self._SH_ValidityStatusChanged)
self.display_name_editor.regexp = re.compile('^.*$')
self.name_editor.regexp = re.compile('^.+$')
self.username_editor.regexp = re.compile('^\w(?<=[^0_])[\w.-]{4,31}(?<=[^_.-])$', re.IGNORECASE) # in order to enable unicode characters add re.UNICODE to flags
self.username_editor.regexp = re.compile('^\w(?<=[^0_])[\w.-]{4,31}(?<=[^_.-])$', re.IGNORECASE) # in order to enable unicode characters add re.UNICODE to flags
self.sip_address_editor.regexp = re.compile('^[^@\s]+@[^@\s]+$')
self.password_editor.regexp = re.compile('^.*$')
self.new_password_editor.regexp = re.compile('^.{8,}$')
......@@ -587,6 +592,7 @@ class ServerToolsWebView(QWebView):
ui_class, base_class = uic.loadUiType(Resources.get('server_tools.ui'))
class ServerToolsWindow(base_class, ui_class):
__metaclass__ = QSingleton
......@@ -599,7 +605,7 @@ class ServerToolsWindow(base_class, ui_class):
self.spinner_label.hide()
self.progress_bar.hide()
while self.tab_widget.count():
self.tab_widget.removeTab(0) # remove the tab(s) added in designer
self.tab_widget.removeTab(0) # remove the tab(s) added in designer
self.tab_widget.tabBar().hide()
self.account_button.setMenu(QMenu(self.account_button))
self.setWindowTitle('Blink Server Tools')
......@@ -629,7 +635,7 @@ class ServerToolsWindow(base_class, ui_class):
self.spinner_label.show()
self.spinner_movie.start()
self.progress_bar.setValue(0)
#self.progress_bar.show()
# self.progress_bar.show()
def _SH_WebViewLoadFinished(self, load_ok):
self.spinner_movie.stop()
......
This diff is collapsed.
......@@ -176,7 +176,7 @@ class IconDescriptor(object):
def __eq__(self, other):
if isinstance(other, IconDescriptor):
return self.url==other.url and self.etag==other.etag
return self.url == other.url and self.etag == other.etag
return NotImplemented
def __ne__(self, other):
......@@ -208,7 +208,7 @@ class PresenceState(object):
def __eq__(self, other):
if isinstance(other, PresenceState):
return self.state==other.state and self.note==other.note
return self.state == other.state and self.note == other.note
return NotImplemented
def __ne__(self, other):
......
......@@ -83,7 +83,7 @@ class SIPSimpleSettingsExtension(SettingsObjectExtension):
sounds = SoundSettings
tls = TLSSettingsExtension
user_agent = Setting(type=str, default='Blink %s (%s)' % (__version__, platform.system() if sys.platform!='darwin' else 'MacOSX Qt'))
user_agent = Setting(type=str, default='Blink %s (%s)' % (__version__, platform.system() if sys.platform != 'darwin' else 'MacOSX Qt'))
class SessionInfoSettings(SettingsGroup):
......
This diff is collapsed.
__all__ = ['CallFunctionEvent']
from PyQt4.QtCore import QEvent
from application.python.descriptor import classproperty
__all__ = ['CallFunctionEvent']
class EventMeta(type(QEvent)):
def __init__(cls, name, bases, dct):
super(EventMeta, cls).__init__(name, bases, dct)
......@@ -35,4 +36,3 @@ class CallFunctionEvent(EventBase):
self.args = args
self.kw = kw
__all__ = ['FileTransferWindow']
import os
from PyQt4 import uic
......@@ -18,8 +16,12 @@ from blink.sessions import FileTransferDelegate, FileTransferModel
from blink.widgets.util import ContextMenuActions
__all__ = ['FileTransferWindow']
ui_class, base_class = uic.loadUiType(Resources.get('filetransfer_window.ui'))
class FileTransferWindow(base_class, ui_class):
implements(IObserver)
......@@ -63,7 +65,7 @@ class FileTransferWindow(base_class, ui_class):
def update_status(self):
total = len(self.model.items)
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 = u'%d %s' % (total, 'transfer' if total == 1 else 'transfers')
if active > 0:
text += u' (%d active)' % active
self.status_label.setText(text)
......
__all__ = ['HistoryManager']
import bisect
import cPickle as pickle
import re
......@@ -23,6 +21,9 @@ from blink.resources import ApplicationData, Resources
from blink.util import run_in_gui_thread
__all__ = ['HistoryManager']
class HistoryManager(object):
__metaclass__ = Singleton
implements(IObserver)
......@@ -86,13 +87,16 @@ class IconDescriptor(object):
def __init__(self, filename):
self.filename = filename
self.icon = None
def __get__(self, obj, objtype):
def __get__(self, instance, owner):
if self.icon is None:
self.icon = QIcon(self.filename)
self.icon.filename = self.filename
return self.icon
def __set__(self, obj, value):
raise AttributeError("attribute cannot be set")
def __delete__(self, obj):
raise AttributeError("attribute cannot be deleted")
......@@ -116,7 +120,7 @@ class HistoryEntry(object):
self.reason = reason
def __reduce__(self):
return (self.__class__, (self.direction, self.name, self.uri, self.account_id, self.call_time, self.duration, self.failed, self.reason))
return self.__class__, (self.direction, self.name, self.uri, self.account_id, self.call_time, self.duration, self.failed, self.reason)
def __eq__(self, other):
return self is other
......@@ -174,7 +178,7 @@ class HistoryEntry(object):
@classmethod
def from_session(cls, session):
if session.start_time is None and session.end_time is not None:
# Session may have anded before it fully started
# Session may have ended before it fully started
session.start_time = session.end_time
call_time = session.start_time or ISOTimestamp.now()
if session.start_time and session.end_time:
......
__all__ = ['LogManager']
import os
import sys
......@@ -21,6 +19,9 @@ from sipsimple.configuration.settings import SIPSimpleSettings
from blink.resources import ApplicationData
__all__ = ['LogManager']
class NotificationQueue(object):
implements(IObserver)
......@@ -161,10 +162,10 @@ class LogManager(object):
direction = "RECEIVED"
else:
direction = "SENDING"
buf = ["%s: Packet %d, +%s" % (direction, self._siptrace_packet_count, (notification.datetime - self._siptrace_start_time))]
buf.append("%(source_ip)s:%(source_port)d -(SIP over %(transport)s)-> %(destination_ip)s:%(destination_port)d" % notification.data.__dict__)
buf.append(notification.data.data)
buf.append('--')
buf = ["%s: Packet %d, +%s" % (direction, self._siptrace_packet_count, (notification.datetime - self._siptrace_start_time)),
"%(source_ip)s:%(source_port)d -(SIP over %(transport)s)-> %(destination_ip)s:%(destination_port)d" % notification.data.__dict__,
notification.data.data,
'--']
message = '\n'.join(buf)
try:
self.siptrace_file.write('%s [%s %d]: %s\n' % (notification.datetime, self.name, self.pid, message))
......@@ -236,4 +237,3 @@ class LogManager(object):
except Exception:
pass
This diff is collapsed.
This diff is collapsed.
__all__ = ['PresenceManager', 'PendingWatcherDialog']
import base64
import hashlib
import re
......@@ -36,6 +34,9 @@ from blink.resources import IconManager, Resources
from blink.util import run_in_gui_thread
__all__ = ['PresenceManager', 'PendingWatcherDialog']
epoch = datetime.fromtimestamp(0, tzutc())
......@@ -50,7 +51,7 @@ class BlinkPresenceState(object):
state = blink_settings.presence.current_state.state
note = blink_settings.presence.current_state.note
state = 'offline' if state=='Invisible' else state.lower()
state = 'offline' if state == 'Invisible' else state.lower()
if self.account is BonjourAccount():
return BonjourPresenceState(state, note)
......@@ -182,10 +183,10 @@ class PresencePublicationHandler(object):
account.presence_state = BlinkPresenceState(account).online_state
else:
account = notification.sender
if set(['xcap.enabled', 'xcap.xcap_root']).intersection(notification.data.modified):
if {'xcap.enabled', 'xcap.xcap_root'}.intersection(notification.data.modified):
account.xcap.icon = None
account.save()
elif set(['presence.enabled', 'display_name', 'xcap.icon']).intersection(notification.data.modified) and account.presence.enabled:
elif {'presence.enabled', 'display_name', 'xcap.icon'}.intersection(notification.data.modified) and account.presence.enabled:
account.presence_state = BlinkPresenceState(account).online_state
def _NH_SIPAccountWillActivate(self, notification):
......@@ -219,11 +220,11 @@ class PresencePublicationHandler(object):
blink_settings.presence.current_state = new_state
if new_state.note:
try:
next(state for state in blink_settings.presence.state_history if state==new_state)
next(state for state in blink_settings.presence.state_history if state == new_state)
except StopIteration:
blink_settings.presence.state_history = [new_state] + blink_settings.presence.state_history
else:
blink_settings.presence.state_history = [new_state] + [state for state in blink_settings.presence.state_history if state!=new_state]
blink_settings.presence.state_history = [new_state] + [state for state in blink_settings.presence.state_history if state != new_state]
blink_settings.save()
def _NH_SIPAccountDidDiscoverXCAPSupport(self, notification):
......@@ -334,11 +335,11 @@ class PresenceSubscriptionHandler(object):
def service_sort_key(service):
timestamp = service.timestamp.value if service.timestamp else epoch
if service.status.extended is not None:
return (100, timestamp)
return 100, timestamp
elif service.status.basic == 'open':
return (10, timestamp)
return 10, timestamp
else:
return (0, timestamp)
return 0, timestamp
current_pidf_map = {}
contact_pidf_map = {}
......@@ -365,7 +366,7 @@ class PresenceSubscriptionHandler(object):
if service.status.extended:
state = unicode(service.status.extended)
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
icon_url = unicode(service.icon) if service.icon else None
......@@ -406,7 +407,7 @@ class PresenceSubscriptionHandler(object):
self._winfo_map.pop(old_id, None)
self._process_presence_data()
return
if set(['enabled', 'presence.enabled']).intersection(notification.data.modified):
if {'enabled', 'presence.enabled'}.intersection(notification.data.modified):
if not account.enabled or not account.presence.enabled:
self._pidf_map.pop(account.id, None)
self._winfo_map.pop(account.id, None)
......
"""Provide access to Blink's resources"""
__all__ = ['ApplicationData', 'Resources', 'IconManager']
import __main__
import imghdr
import os
......@@ -21,10 +19,14 @@ from sipsimple.configuration.datatypes import Path
from blink.util import run_in_gui_thread
__all__ = ['ApplicationData', 'Resources', 'IconManager']
class DirectoryContextManager(unicode):
def __enter__(self):
self.directory = os.getcwdu()
os.chdir(self)
def __exit__(self, type, value, traceback):
os.chdir(self.directory)
......
__all__ = ['ScreensharingWindow', 'VNCViewer', 'VNCClient', 'RFBSettings', 'ServerDefault', 'TrueColor', 'HighColor', 'LowColor']
from blink.screensharing.vncclient import VNCClient, RFBSettings, ServerDefault, TrueColor, HighColor, LowColor
from blink.screensharing.vncviewer import ScreensharingWindow, VNCViewer
__all__ = ['ScreensharingWindow', 'VNCViewer', 'VNCClient', 'RFBSettings', 'ServerDefault', 'TrueColor', 'HighColor', 'LowColor']
__all__ = ['RFBClient', 'RFBClientError']
from sip import voidptr
from PyQt4.QtCore import QThread
from PyQt4.QtGui import QImage
......@@ -12,6 +10,9 @@ from libc.stdlib cimport calloc, malloc, free
from libc.string cimport memcpy, strlen
__all__ = ['RFBClient', 'RFBClientError']
# external declarations
#
......
__all__ = ['VNCClient', 'RFBSettings', 'ServerDefault', 'TrueColor', 'HighColor', 'LowColor']
from PyQt4.QtCore import QObject, QSize, QSocketNotifier, QThread, pyqtSignal
from PyQt4.QtGui import QApplication
......@@ -10,7 +7,10 @@ from application.python import Null
from application.python.descriptor import WriteOnceAttribute
from blink.event import EventBase
from blink.screensharing._rfb import RFBClient, RFBClientError
from blink.screensharing._rfb import RFBClient, RFBClientError
__all__ = ['VNCClient', 'RFBSettings', 'ServerDefault', 'TrueColor', 'HighColor', 'LowColor']
class RFBSettings(object):
......@@ -101,6 +101,7 @@ class VNCClient(QObject):
def _get_settings(self):
return self.__dict__['settings']
def _set_settings(self, settings):
old_settings = self.__dict__.get('settings', None)
if settings == old_settings:
......@@ -108,6 +109,7 @@ class VNCClient(QObject):
self.__dict__['settings'] = settings
if self.thread.isRunning():
QApplication.postEvent(self, RFBConfigureClientEvent())
settings = property(_get_settings, _set_settings)
del _get_settings, _set_settings
......
This diff is collapsed.
This diff is collapsed.
__all__ = ['IUpdateManager', 'UpdateManager']
import sys
from application.python import Null
from zope.interface import Interface
__all__ = ['IUpdateManager', 'UpdateManager']
class IUpdateManager(Interface):
def initialize(self):
pass
def shutdown(self):
pass
def check_for_updates(self):
pass
......@@ -23,4 +26,3 @@ if sys.platform == 'win32':
UpdateManager = Null
else:
UpdateManager = Null
......@@ -19,14 +19,13 @@ def library_locations(name):
for path in additional_paths:
yield os.path.join(path, library_name)
def load_library(name):
for library in library_locations(name):
try:
return CDLL(library)
except OSError:
pass
else:
break
else:
raise RuntimeError('cannot find %s on this system' % name)
......
__all__ = ['QSingleton', 'call_in_gui_thread', 'call_later', 'run_in_gui_thread']
from PyQt4.QtCore import QObject, QThread, QTimer
from PyQt4.QtGui import QApplication
from application.python.decorator import decorator, preserve_signature
......@@ -9,6 +7,9 @@ from application.python.types import Singleton
from blink.event import CallFunctionEvent
__all__ = ['QSingleton', 'call_in_gui_thread', 'call_later', 'run_in_gui_thread']
class QSingleton(Singleton, type(QObject)):
"""A metaclass for making Qt objects singletons"""
......
__all__ = ['ToolButton', 'ConferenceButton', 'StreamButton', 'SegmentButton', 'SingleSegment', 'LeftSegment', 'MiddleSegment', 'RightSegment', 'RecordButton', 'SwitchViewButton',
'StateButton', 'AccountState']
from PyQt4.QtCore import Qt, QLineF, QPointF, QRectF, QSize, QTimer, pyqtSignal, pyqtSignature
from PyQt4.QtGui import QAction, QBrush, QColor, QCommonStyle, QLinearGradient, QIcon, QMenu, QPainter, QPainterPath, QPalette, QPen, QPixmap
from PyQt4.QtGui import QPolygonF, QPushButton, QStyle, QStyleOptionToolButton, QStylePainter, QToolButton
......@@ -10,8 +7,13 @@ from blink.resources import Resources
from blink.widgets.color import ColorScheme, ColorUtils, ColorHelperMixin
__all__ = ['ToolButton', 'ConferenceButton', 'StreamButton', 'SegmentButton', 'SingleSegment', 'LeftSegment', 'MiddleSegment', 'RightSegment',
'RecordButton', 'SwitchViewButton', 'StateButton', 'AccountState']
class ToolButton(QToolButton):
"""A custom QToolButton that doesn't show a menu indicator arrow"""
def paintEvent(self, event):
painter = QStylePainter(self)
option = QStyleOptionToolButton()
......@@ -102,10 +104,12 @@ class SegmentTypeMeta(type):
def __repr__(cls):
return cls.__name__
class SegmentType(object):
__metaclass__ = SegmentTypeMeta
style_sheet = ''
class SingleSegment(SegmentType):
style_sheet = """
QToolButton {
......@@ -122,6 +126,7 @@ class SingleSegment(SegmentType):
}
"""
class LeftSegment(SegmentType):
style_sheet = """
QToolButton {
......@@ -139,6 +144,7 @@ class LeftSegment(SegmentType):
}
"""
class MiddleSegment(SegmentType):
style_sheet = """
QToolButton {
......@@ -155,6 +161,7 @@ class MiddleSegment(SegmentType):
}
"""
class RightSegment(SegmentType):
style_sheet = """
QToolButton {
......@@ -285,7 +292,7 @@ class SwitchViewButton(QPushButton):
self.setAcceptDrops(True)
self.__dict__['dnd_active'] = False
self.view = self.ContactView
self.original_height = 20 # used to restore button size after DND
self.original_height = 20 # used to restore button size after DND
self.dnd_timer = QTimer(self)
self.dnd_timer.setInterval(100)
self.dnd_timer.timeout.connect(self._update_dnd)
......@@ -355,16 +362,16 @@ class SwitchViewButton(QPushButton):
def dragLeaveEvent(self, event):
if self.dnd_active:
self.dnd_timer.stop()
self.dnd_timer.phase = 0
self.setStyleSheet(self.dnd_style_sheet1)
self.dnd_timer.stop()
self.dnd_timer.phase = 0
self.setStyleSheet(self.dnd_style_sheet1)
super(SwitchViewButton, self).dragLeaveEvent(event)
def dropEvent(self, event):
if self.dnd_active:
self.dnd_timer.stop()
self.dnd_timer.phase = 0
self.setStyleSheet(self.dnd_style_sheet1)
self.dnd_timer.stop()
self.dnd_timer.phase = 0
self.setStyleSheet(self.dnd_style_sheet1)
event.ignore()
......@@ -387,7 +394,7 @@ class StateButtonStyle(QCommonStyle, ColorHelperMixin):
return super(StateButtonStyle, self).sizeFromContents(element, option, size, widget)
def toolButtonSizeFromContents(self, option, size, widget):
# Make width >= height to avoid super-skiny buttons
# Make width >= height to avoid super-skinny buttons
margin = 2 * (self._pixel_metrics[QStyle.PM_DefaultFrameWidth] + self._pixel_metrics[QStyle.PM_ButtonMargin])
if option.features & QStyleOptionToolButton.MenuButtonPopup:
margin_size = QSize(margin+1, margin)
......@@ -448,12 +455,12 @@ class StateButtonStyle(QCommonStyle, ColorHelperMixin):
blend.setColorAt(0.9, self.color_with_alpha(focus_color, 0x45))
blend.setColorAt(1.0, self.color_with_alpha(ColorUtils.mix(focus_color, shadow_color, 0.4), 0x55))
else:
blend.setColorAt(0.0, Qt.transparent) # or @0.5
blend.setColorAt(0.0, Qt.transparent) # or @0.5
blend.setColorAt(0.9, self.color_with_alpha(shadow_color, 0x10))
#blend.setColorAt(1-4.0/glow_rect.height(), self.color_with_alpha(shadow_color, 0x10)) # this is for exactly 4 pixels from bottom
# blend.setColorAt(1-4.0/glow_rect.height(), self.color_with_alpha(shadow_color, 0x10)) # this is for exactly 4 pixels from bottom
blend.setColorAt(1.0, self.color_with_alpha(shadow_color, 0x30)) # 0x25, 0x30 or 0x35
painter.setBrush(blend)
painter.drawRoundedRect(glow_rect, 5, 5) # 5 or 6
painter.drawRoundedRect(glow_rect, 5, 5) # 5 or 6
# shadow
painter.setCompositionMode(QPainter.CompositionMode_SourceOver)
......@@ -466,7 +473,7 @@ class StateButtonStyle(QCommonStyle, ColorHelperMixin):
blend.setColorAt(0.00, self.color_with_alpha(shadow_color, 0x10))
blend.setColorAt(1.00, self.color_with_alpha(shadow_color, 0x80))
painter.setBrush(blend)
painter.drawRoundedRect(shadow_rect, 4, 4) # 4 or 5
painter.drawRoundedRect(shadow_rect, 4, 4) # 4 or 5
# border
painter.setCompositionMode(QPainter.CompositionMode_Source)
......@@ -510,12 +517,12 @@ class StateButtonStyle(QCommonStyle, ColorHelperMixin):
blend.setColorAt(0.0, self.color_with_alpha(shadow_color, 0x80))
blend.setColorAt(1.0, self.color_with_alpha(shadow_color, 0x20))
painter.setBrush(blend)
painter.drawRoundedRect(hole_rect, 4, 4) # 4 or 5
painter.drawRoundedRect(hole_rect, 4, 4) # 4 or 5
# shadow
painter.setCompositionMode(QPainter.CompositionMode_Source)
painter.setBrush(content_grad)
painter.drawRoundedRect(shadow_rect, 4, 4) # 5 or 6
painter.drawRoundedRect(shadow_rect, 4, 4) # 5 or 6
painter.setCompositionMode(QPainter.CompositionMode_SourceOver)
blend = QLinearGradient(shadow_rect.topLeft(), shadow_rect.bottomLeft())
blend.setColorAt(0.0, self.color_with_alpha(shadow_color, 0x40))
......@@ -523,7 +530,7 @@ class StateButtonStyle(QCommonStyle, ColorHelperMixin):
blend.setColorAt(0.9, self.color_with_alpha(shadow_color, 0x07))
blend.setColorAt(1.0, shade_color)
painter.setBrush(blend)
painter.drawRoundedRect(shadow_rect, 4, 4) # 5 or 6
painter.drawRoundedRect(shadow_rect, 4, 4) # 5 or 6
# content
painter.setCompositionMode(QPainter.CompositionMode_Source)
......@@ -685,6 +692,7 @@ class AccountState(StateButton):
def _get_history(self):
return [(action.state.name, action.note) for action in self.menu().actions()[5:]]
def _set_history(self, values):
menu = self.menu()
for action in menu.actions()[5:]:
......@@ -698,6 +706,7 @@ class AccountState(StateButton):
action.state = state
action.note = note
menu.addAction(action)
history = property(_get_history, _set_history)
del _get_history, _set_history
......
__all__ = ['ColorScheme', 'ColorUtils', 'ColorHelperMixin']
from PyQt4.QtCore import Qt
from PyQt4.QtGui import QColor
from application.python import limit
......@@ -8,8 +6,11 @@ from application.python.decorator import decorator, preserve_signature
from math import fmod, isnan
__all__ = ['ColorScheme', 'ColorUtils', 'ColorHelperMixin']
class HCYColor(object):
"""Hue/chroma/luma colorspace"""
"""Hue/chroma/luma color space"""
luma_r = 0.2126
luma_g = 0.7152
......@@ -202,9 +203,11 @@ class ColorUtils(object):
def color_key(instance, color):
return color.rgba()
def color_ratio_key(instance, color, ratio):
return color.rgba() << 32 | int(ratio*512)
def background_color_key(instance, background, color):
return background.rgba() << 32 | color.rgba()
......@@ -276,7 +279,7 @@ class ColorHelperMixin(object):
shadow_color = ColorUtils.mix(Qt.black, color, color.alphaF())
else:
shadow_color = ColorScheme.shade(ColorUtils.mix(Qt.black, color, color.alphaF()), ColorScheme.ShadowShade, self._contrast)
shadow_color.setAlpha(color.alpha()) # make sure shadow color has the same alpha channel as the input
shadow_color.setAlpha(color.alpha()) # make sure shadow color has the same alpha channel as the input
return shadow_color
@cache_result(color_ratio_key)
......
__all__ = ['SlidingStackedWidget']
from PyQt4.QtCore import QEasingCurve, QParallelAnimationGroup, QPropertyAnimation, QPoint, pyqtSignal
from PyQt4.QtGui import QStackedWidget
from blink.widgets.util import QtDynamicProperty
__all__ = ['SlidingStackedWidget']
class SlidingStackedWidget(QStackedWidget):
animationEasingCurve = QtDynamicProperty('animationEasingCurve', int)
animationDuration = QtDynamicProperty('animationDuration', int)
......@@ -65,9 +66,9 @@ class SlidingStackedWidget(QStackedWidget):
next_widget.setGeometry(0, 0, width, height)
if direction in (self.TopToBottom, self.BottomToTop):
offset = QPoint(0, height if direction==self.TopToBottom else -height)
offset = QPoint(0, height if direction == self.TopToBottom else -height)
elif direction in (self.LeftToRight, self.RightToLeft):
offset = QPoint(width if direction==self.LeftToRight else -width, 0)
offset = QPoint(width if direction == self.LeftToRight else -width, 0)
# re-position the next widget outside of the display area
prev_widget_position = prev_widget.pos()
......@@ -100,8 +101,8 @@ class SlidingStackedWidget(QStackedWidget):
prev_widget = prev_widget_animation.targetObject()
next_widget = next_widget_animation.targetObject()
self.setCurrentWidget(next_widget)
prev_widget.hide() # this may have been done already by QStackedWidget when changing the current widget above -Dan
prev_widget.move(prev_widget_animation.startValue()) # move the outshifted widget back to its original position
prev_widget.hide() # this may have been done already by QStackedWidget when changing the current widget above -Dan
prev_widget.move(prev_widget_animation.startValue()) # move the out-shifted widget back to its original position
self._animation_group.clear()
self._active = False
self.animationFinished.emit()
......
__all__ = ['BackgroundFrame']
from PyQt4.QtCore import Qt, QEvent, QPoint, QRect, QSize
from PyQt4.QtGui import QColor, QFrame, QPainter, QPixmap
......@@ -8,6 +6,9 @@ from blink.resources import Resources
from blink.widgets.util import QtDynamicProperty
__all__ = ['BackgroundFrame']
class BackgroundFrame(QFrame):
backgroundColor = QtDynamicProperty('backgroundColor', unicode)
backgroundImage = QtDynamicProperty('backgroundImage', unicode)
......@@ -28,7 +29,7 @@ class BackgroundFrame(QFrame):
@property
def image_size(self):
if self.imageGeometry is not None:
size = self.imageGeometry.size().expandedTo(QSize(0, 0)) # requested size with negative values turned to 0
size = self.imageGeometry.size().expandedTo(QSize(0, 0)) # requested size with negative values turned to 0
if size.isNull():
return size if self.pixmap is None else self.pixmap.size()
elif size.width() == 0:
......@@ -70,4 +71,3 @@ class BackgroundFrame(QFrame):
painter.drawPixmap(self.image_position, self.scaled_pixmap)
painter.end()
__all__ = ['Graph', 'GraphWidget', 'HeightScaler', 'LogarithmicScaler', 'MaxScaler', 'SoftScaler']
from PyQt4.QtCore import Qt, QLine, QPointF, QMetaObject, pyqtSignal
from PyQt4.QtGui import QColor, QLinearGradient, QPainterPath, QPen, QPolygonF, QStyle, QStyleOption, QStylePainter, QWidget
......@@ -14,6 +12,9 @@ from blink.widgets.color import ColorHelperMixin
from blink.widgets.util import QtDynamicProperty
__all__ = ['Graph', 'GraphWidget', 'HeightScaler', 'LogarithmicScaler', 'MaxScaler', 'SoftScaler']
class HeightScaler(object):
__metaclass__ = ABCMeta
......@@ -140,7 +141,7 @@ class GraphWidget(QWidget, ColorHelperMixin):
option = QStyleOption()
option.initFrom(self)
contents_rect = self.style().subElementRect(QStyle.SE_FrameContents, option, self) or self.contentsRect() # the SE_FrameContents rect is Null unless the stylesheet defines decorations
contents_rect = self.style().subElementRect(QStyle.SE_FrameContents, option, self) or self.contentsRect() # the SE_FrameContents rect is Null unless the stylesheet defines decorations
if self.graphStyle == self.BarStyle:
graph_width = self.__dict__['graph_width'] = int(ceil(float(contents_rect.width()) / self.horizontalPixelsPerUnit))
......@@ -196,18 +197,18 @@ class GraphWidget(QWidget, ColorHelperMixin):
cx_offset = self.horizontalPixelsPerUnit / 3.0
smoothness = self.smoothFactor
last_values = deque(3*[dataset.next() * height_scaling], maxlen=3) # last 3 values: 0 last, 1 previous, 2 previous previous
last_values = deque(3*[next(dataset) * height_scaling], maxlen=3) # last 3 values: 0 last, 1 previous, 2 previous previous
envelope = QPainterPath()
envelope.moveTo(0, last_values[0])
for x, y in enumerate(dataset, 1):
x = x * self.horizontalPixelsPerUnit
y = y * height_scaling * (1 - smoothness) + last_values[0] * smoothness
x *= self.horizontalPixelsPerUnit
y *= height_scaling * (1 - smoothness) + last_values[0] * smoothness
last_values.appendleft(y)
c1x = x - cx_offset * 2
c2x = x - cx_offset
c1y = limit((1 + smoothness) * last_values[1] - smoothness * last_values[2], min_value, max_value) # same gradient as previous previous value to previous value
c2y = limit((1 - smoothness) * last_values[0] + smoothness * last_values[1], min_value, max_value) # same gradient as previous value to last value
c1y = limit((1 + smoothness) * last_values[1] - smoothness * last_values[2], min_value, max_value) # same gradient as previous previous value to previous value
c2y = limit((1 - smoothness) * last_values[0] + smoothness * last_values[1], min_value, max_value) # same gradient as previous value to last value
envelope.cubicTo(c1x, c1y, c2x, c2y, x, y)
else:
envelope = QPainterPath()
......@@ -236,7 +237,7 @@ class GraphWidget(QWidget, ColorHelperMixin):
painter.restore()
# queue the 'updated' signal to be emited after returning to the main loop
# queue the 'updated' signal to be emitted after returning to the main loop
QMetaObject.invokeMethod(self, 'updated', Qt.QueuedConnection)
def add_graph(self, graph):
......@@ -254,4 +255,3 @@ class GraphWidget(QWidget, ColorHelperMixin):
self.graphs = []
self.update()
__all__ = ['DurationLabel', 'IconSelector', 'LatencyLabel', 'PacketLossLabel', 'Status', 'StatusLabel', 'StreamInfoLabel', 'ElidedLabel', 'ContactState']
import os
from datetime import timedelta
......@@ -16,6 +14,9 @@ from blink.widgets.color import ColorHelperMixin
from blink.widgets.util import QtDynamicProperty, ContextMenuActions
__all__ = ['DurationLabel', 'IconSelector', 'LatencyLabel', 'PacketLossLabel', 'Status', 'StatusLabel', 'StreamInfoLabel', 'ElidedLabel', 'ContactState']
class IconSelector(QLabel):
default_icon = QtDynamicProperty('default_icon', QIcon)
icon_size = QtDynamicProperty('icon_size', int)
......@@ -283,6 +284,7 @@ class StateColor(QColor):
def stroke(self):
return self.darker(200)
class StateColorMapping(dict):
def __missing__(self, key):
if key == 'offline':
......@@ -294,7 +296,7 @@ class StateColorMapping(dict):
elif key == 'busy':
return self.setdefault(key, StateColor('#ff0000'))
else:
return StateColor(Qt.transparent) #StateColor('#d0d0d0')
return StateColor(Qt.transparent) # StateColor('#d0d0d0')
class ContactState(QLabel, ColorHelperMixin):
......@@ -323,4 +325,3 @@ class ContactState(QLabel, ColorHelperMixin):
painter.setPen(QPen(QBrush(gradient), 1))
painter.drawRoundedRect(-4, 0, self.width()+4, self.height(), 3.7, 3.7)
__all__ = ['LineEdit', 'ValidatingLineEdit', 'SearchBox', 'LocationBar']
import re
from PyQt4.QtCore import Qt, QEvent, pyqtSignal
......@@ -10,6 +8,9 @@ from blink.resources import Resources
from blink.widgets.util import QtDynamicProperty
__all__ = ['LineEdit', 'ValidatingLineEdit', 'SearchBox', 'LocationBar']
class SideWidget(QWidget):
sizeHintChanged = pyqtSignal()
......@@ -64,7 +65,7 @@ class LineEdit(QLineEdit):
spacing = self.right_layout.spacing()
text_rect = self.style().subElementRect(QStyle.SE_LineEditContents, option, self)
text_rect.adjust(spacing, 0, -spacing, 0)
mid_height = text_rect.center().y() + 1 - (text_rect.height() % 2) # need -1 correction for odd heights -Dan
mid_height = text_rect.center().y() + 1 - (text_rect.height() % 2) # need -1 correction for odd heights -Dan
if self.left_layout.count() > 0:
left_height = mid_height - self.left_widget.height()/2
left_width = self.left_widget.width()
......@@ -244,7 +245,7 @@ class ClearButton(QAbstractButton):
# Mid is darker than Dark. Go figure... -Dan
bg_color = palette.color(QPalette.Mid) if self.isDown() else palette.color(QPalette.Dark)
fg_color = palette.color(QPalette.Window) # or QPalette.Base for white
fg_color = palette.color(QPalette.Window) # or QPalette.Base for white
painter.setRenderHint(QPainter.Antialiasing, True)
painter.setBrush(bg_color)
......@@ -307,4 +308,3 @@ class LocationBar(LineEdit):
def _SH_TextChanged(self, text):
self.clear_button.setVisible(bool(text))
__all__ = ['QtDynamicProperty', 'ContextMenuActions']
from PyQt4.QtCore import QPyNullVariant
__all__ = ['QtDynamicProperty', 'ContextMenuActions']
class QtDynamicProperty(object):
def __init__(self, name, type=unicode):
self.name = name
self.type = type
def __get__(self, obj, objtype):
if obj is None:
def __get__(self, instance, owner):
if instance is None:
return self
value = obj.property(self.name)
value = instance.property(self.name)
if isinstance(value, QPyNullVariant):
value = self.type()
return value
def __set__(self, obj, value):
if value is not None and not isinstance(value, self.type):
value = self.type(value)
obj.setProperty(self.name, value)
def __delete__(self, obj):
raise AttributeError("attribute cannot be deleted")
......
from __future__ import division
__all__ = ['VideoSurface']
from PyQt4.QtCore import Qt, QMetaObject, QPoint, QRect, QTimer, pyqtSignal
from PyQt4.QtGui import QColor, QCursor, QIcon, QImage, QPainter, QPixmap, QTransform, QWidget
......@@ -16,7 +12,11 @@ from sipsimple.core import FrameBufferVideoRenderer
from blink.resources import Resources
class Container(object): pass
__all__ = ['VideoSurface']
class Container(object):
pass
class InteractionState(object):
......@@ -41,7 +41,7 @@ class VideoSurface(QWidget):
class BottomLeftCorner: __metaclass__ = MarkerType
class BottomRightCorner: __metaclass__ = MarkerType
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)
interactive = False # if the widget can be interacted with (moved, resized)
mirror = False # mirror the image horizontally
......@@ -197,13 +197,13 @@ class VideoSurface(QWidget):
delta_x = -(self.width_for_height(geometry.height() - delta_y) - geometry.width())
geometry.setTopLeft(geometry.topLeft() + QPoint(delta_x, delta_y))
elif self._interaction.resize_corner is self.TopRightCorner:
delta_x = (self.width_for_height(geometry.height() - delta_y) - geometry.width())
delta_x = +(self.width_for_height(geometry.height() - delta_y) - geometry.width())
geometry.setTopRight(geometry.topRight() + QPoint(delta_x, delta_y))
elif self._interaction.resize_corner is self.BottomLeftCorner:
delta_x = -(self.width_for_height(geometry.height() + delta_y) - geometry.width())
geometry.setBottomLeft(geometry.bottomLeft() + QPoint(delta_x, delta_y))
else:
delta_x = (self.width_for_height(geometry.height() + delta_y) - geometry.width())
delta_x = +(self.width_for_height(geometry.height() + delta_y) - geometry.width())
geometry.setBottomRight(geometry.bottomRight() + QPoint(delta_x, delta_y))
if self.minimumHeight() <= geometry.height() <= self.maximumHeight() and (self.parent() is None or self.parent().rect().contains(geometry)):
......@@ -224,4 +224,3 @@ class VideoSurface(QWidget):
super(VideoSurface, self).closeEvent(event)
self.stop()
__all__ = ['ZRTPWidget']
from PyQt4 import uic
from PyQt4.QtCore import Qt, pyqtSignal
from PyQt4.QtGui import QStyle, QStyleOption, QStylePainter
......@@ -9,8 +6,12 @@ from PyQt4.QtGui import QStyle, QStyleOption, QStylePainter
from blink.resources import Resources
__all__ = ['ZRTPWidget']
ui_class, base_class = uic.loadUiType(Resources.get('zrtp_widget.ui'))
class ZRTPWidget(base_class, ui_class):
closed = pyqtSignal()
nameChanged = pyqtSignal()
......
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