def createLabelAndList(labelText): widget, label = _createLabelInWidget(labelText, QGridLayout) buttonGroup = QButtonGroup(widget) buttonGroup.setObjectName('buttonGroup') buttonGroup.setExclusive(False) return (widget, label, buttonGroup)
class AddAccountDialog(base_class, ui_class): __metaclass__ = QSingleton implements(IObserver) def __init__(self, parent=None): super(AddAccountDialog, self).__init__(parent) with Resources.directory: self.setupUi(self) self.background_frame.setStyleSheet("") self.button_group = QButtonGroup(self) self.button_group.setObjectName("button_group") self.button_group.addButton(self.add_account_button, self.panel_view.indexOf(self.add_account_panel)) self.button_group.addButton(self.create_account_button, self.panel_view.indexOf(self.create_account_panel)) font = self.title_label.font() font.setPointSizeF(self.info_label.fontInfo().pointSizeF() + 3) 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 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.add_account_button.setChecked(True) self.panel_view.setCurrentWidget(self.add_account_panel) self.new_password_editor.textChanged.connect(self._SH_PasswordTextChanged) self.button_group.buttonClicked[int].connect(self._SH_PanelChangeRequest) self.accept_button.clicked.connect(self._SH_AcceptButtonClicked) self.display_name_editor.statusChanged.connect(self._SH_ValidityStatusChanged) self.name_editor.statusChanged.connect(self._SH_ValidityStatusChanged) self.username_editor.statusChanged.connect(self._SH_ValidityStatusChanged) self.sip_address_editor.statusChanged.connect(self._SH_ValidityStatusChanged) self.password_editor.statusChanged.connect(self._SH_ValidityStatusChanged) self.new_password_editor.statusChanged.connect(self._SH_ValidityStatusChanged) self.verify_password_editor.statusChanged.connect(self._SH_ValidityStatusChanged) 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.sip_address_editor.regexp = re.compile("^[^@\s]+@[^@\s]+$") self.password_editor.regexp = re.compile("^.*$") self.new_password_editor.regexp = re.compile("^.{8,}$") self.verify_password_editor.regexp = re.compile("^$") self.email_address_editor.regexp = re.compile("^[^@\s]+@[^@\s]+$") account_manager = AccountManager() notification_center = NotificationCenter() notification_center.add_observer(self, sender=account_manager) def _get_display_name(self): if self.panel_view.currentWidget() is self.add_account_panel: return unicode(self.display_name_editor.text()) else: return unicode(self.name_editor.text()) def _set_display_name(self, value): self.display_name_editor.setText(value) self.name_editor.setText(value) def _get_username(self): return unicode(self.username_editor.text()) def _set_username(self, value): self.username_editor.setText(value) def _get_sip_address(self): return unicode(self.sip_address_editor.text()) def _set_sip_address(self, value): self.sip_address_editor.setText(value) def _get_password(self): if self.panel_view.currentWidget() is self.add_account_panel: return unicode(self.password_editor.text()) else: return unicode(self.new_password_editor.text()) def _set_password(self, value): self.password_editor.setText(value) self.new_password_editor.setText(value) def _get_verify_password(self): return unicode(self.verify_password_editor.text()) def _set_verify_password(self, value): self.verify_password_editor.setText(value) def _get_email_address(self): return unicode(self.email_address_editor.text()) def _set_email_address(self, value): self.email_address_editor.setText(value) display_name = property(_get_display_name, _set_display_name) username = property(_get_username, _set_username) sip_address = property(_get_sip_address, _set_sip_address) password = property(_get_password, _set_password) verify_password = property(_get_verify_password, _set_verify_password) email_address = property(_get_email_address, _set_email_address) del _get_display_name, _set_display_name, _get_username, _set_username del _get_sip_address, _set_sip_address, _get_email_address, _set_email_address del _get_password, _set_password, _get_verify_password, _set_verify_password def _SH_AcceptButtonClicked(self): if self.panel_view.currentWidget() is self.add_account_panel: account = Account(self.sip_address) account.enabled = True account.display_name = self.display_name account.auth.password = self.password call_in_auxiliary_thread(account.save) account_manager = AccountManager() account_manager.default_account = account self.accept() else: self.setEnabled(False) self.create_status_label.value = Status("Creating account on server...") self._create_sip_account(self.username, self.password, self.email_address, self.display_name) def _SH_PanelChangeRequest(self, index): self.panel_view.setCurrentIndex(index) if self.panel_view.currentWidget() is self.add_account_panel: inputs = [self.display_name_editor, self.sip_address_editor, self.password_editor] else: inputs = [ self.name_editor, self.username_editor, self.new_password_editor, self.verify_password_editor, self.email_address_editor, ] self.accept_button.setEnabled(all(input.text_valid for input in inputs)) def _SH_PasswordTextChanged(self, text): self.verify_password_editor.regexp = re.compile(u"^%s$" % re.escape(unicode(text))) def _SH_ValidityStatusChanged(self): red = "#cc0000" # validate the add panel if not self.display_name_editor.text_valid: self.add_status_label.value = Status("Display name cannot be empty", color=red) elif not self.sip_address_editor.text_correct: self.add_status_label.value = Status("SIP address should be specified as user@domain", color=red) elif not self.sip_address_editor.text_allowed: self.add_status_label.value = Status("An account with this SIP address was already added", color=red) elif not self.password_editor.text_valid: self.add_status_label.value = Status("Password cannot be empty", color=red) else: self.add_status_label.value = None # validate the create panel if not self.name_editor.text_valid: self.create_status_label.value = Status("Name cannot be empty", color=red) elif not self.username_editor.text_correct: self.create_status_label.value = Status( "Username should have 5 to 32 characters, start with a letter or non-zero digit, contain only letters, digits or .-_ and end with a letter or digit", color=red, ) elif not self.username_editor.text_allowed: self.create_status_label.value = Status( "The username you requested is already taken. Please choose another one and try again.", color=red ) elif not self.new_password_editor.text_valid: self.create_status_label.value = Status("Password should contain at least 8 characters", color=red) elif not self.verify_password_editor.text_valid: self.create_status_label.value = Status("Passwords do not match", color=red) elif not self.email_address_editor.text_valid: self.create_status_label.value = Status("E-mail address should be specified as user@domain", color=red) else: self.create_status_label.value = None # enable the accept button if everything is valid in the current panel if self.panel_view.currentWidget() is self.add_account_panel: inputs = [self.display_name_editor, self.sip_address_editor, self.password_editor] else: inputs = [ self.name_editor, self.username_editor, self.new_password_editor, self.verify_password_editor, self.email_address_editor, ] self.accept_button.setEnabled(all(input.text_valid for input in inputs)) def _initialize(self): self.display_name = user_info.fullname self.username = user_info.username.lower().replace(" ", ".") self.sip_address = u"" self.password = u"" self.verify_password = u"" self.email_address = u"" @run_in_auxiliary_thread def _create_sip_account(self, username, password, email_address, display_name, timezone=None): red = "#cc0000" if timezone is None and sys.platform != "win32": try: timezone = open("/etc/timezone").read().strip() except (OSError, IOError): try: timezone = "/".join(os.readlink("/etc/localtime").split("/")[-2:]) except (OSError, IOError): pass enrollment_data = dict( username=username.lower().encode("utf-8"), password=password.encode("utf-8"), email=email_address.encode("utf-8"), display_name=display_name.encode("utf-8"), tzinfo=timezone, ) try: settings = SIPSimpleSettings() response = urllib2.urlopen(settings.server.enrollment_url, urllib.urlencode(dict(enrollment_data))) response_data = cjson.decode(response.read().replace(r"\/", "/")) response_data = defaultdict(lambda: None, response_data) if response_data["success"]: from blink import Blink try: certificate_path = None passport = response_data["passport"] if passport is not None: certificate_path = Blink().save_certificates( response_data["sip_address"], passport["crt"], passport["key"], passport["ca"] ) except (GNUTLSError, IOError, OSError): pass account_manager = AccountManager() try: account = Account(response_data["sip_address"]) except AccountExists: account = account_manager.get_account(response_data["sip_address"]) account.enabled = True account.display_name = display_name account.auth.password = password account.sip.outbound_proxy = response_data["outbound_proxy"] account.nat_traversal.msrp_relay = response_data["msrp_relay"] account.xcap.xcap_root = response_data["xcap_root"] account.tls.certificate = certificate_path account.server.settings_url = response_data["settings_url"] account.save() account_manager.default_account = account call_in_gui_thread(self.accept) elif response_data["error"] == "user_exists": call_in_gui_thread(self.username_editor.addException, username) else: call_in_gui_thread( setattr, self.create_status_label, "value", Status(response_data["error_message"], color=red) ) except (cjson.DecodeError, KeyError): call_in_gui_thread(setattr, self.create_status_label, "value", Status("Illegal server response", color=red)) except urllib2.URLError, e: call_in_gui_thread( setattr, self.create_status_label, "value", Status("Failed to contact server: %s" % e.reason, color=red) ) finally:
class AddAccountDialog(base_class, ui_class): __metaclass__ = QSingleton implements(IObserver) def __init__(self, parent=None): super(AddAccountDialog, self).__init__(parent) with Resources.directory: self.setupUi(self) self.background_frame.setStyleSheet("") self.button_group = QButtonGroup(self) self.button_group.setObjectName("button_group") self.button_group.addButton( self.add_account_button, self.panel_view.indexOf(self.add_account_panel)) self.button_group.addButton( self.create_account_button, self.panel_view.indexOf(self.create_account_panel)) font = self.title_label.font() font.setPointSizeF(self.info_label.fontInfo().pointSizeF() + 3) 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 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.add_account_button.setChecked(True) self.panel_view.setCurrentWidget(self.add_account_panel) self.new_password_editor.textChanged.connect( self._SH_PasswordTextChanged) self.button_group.buttonClicked[int].connect( self._SH_PanelChangeRequest) self.accept_button.clicked.connect(self._SH_AcceptButtonClicked) self.display_name_editor.statusChanged.connect( self._SH_ValidityStatusChanged) self.name_editor.statusChanged.connect(self._SH_ValidityStatusChanged) self.username_editor.statusChanged.connect( self._SH_ValidityStatusChanged) self.sip_address_editor.statusChanged.connect( self._SH_ValidityStatusChanged) self.password_editor.statusChanged.connect( self._SH_ValidityStatusChanged) self.new_password_editor.statusChanged.connect( self._SH_ValidityStatusChanged) self.verify_password_editor.statusChanged.connect( self._SH_ValidityStatusChanged) 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.sip_address_editor.regexp = re.compile('^[^@\s]+@[^@\s]+$') self.password_editor.regexp = re.compile('^.*$') self.new_password_editor.regexp = re.compile('^.{8,}$') self.verify_password_editor.regexp = re.compile('^$') self.email_address_editor.regexp = re.compile('^[^@\s]+@[^@\s]+$') account_manager = AccountManager() notification_center = NotificationCenter() notification_center.add_observer(self, sender=account_manager) def _get_display_name(self): if self.panel_view.currentWidget() is self.add_account_panel: return self.display_name_editor.text() else: return self.name_editor.text() def _set_display_name(self, value): self.display_name_editor.setText(value) self.name_editor.setText(value) def _get_username(self): return self.username_editor.text() def _set_username(self, value): self.username_editor.setText(value) def _get_sip_address(self): return self.sip_address_editor.text() def _set_sip_address(self, value): self.sip_address_editor.setText(value) def _get_password(self): if self.panel_view.currentWidget() is self.add_account_panel: return self.password_editor.text() else: return self.new_password_editor.text() def _set_password(self, value): self.password_editor.setText(value) self.new_password_editor.setText(value) def _get_verify_password(self): return self.verify_password_editor.text() def _set_verify_password(self, value): self.verify_password_editor.setText(value) def _get_email_address(self): return self.email_address_editor.text() def _set_email_address(self, value): self.email_address_editor.setText(value) display_name = property(_get_display_name, _set_display_name) username = property(_get_username, _set_username) sip_address = property(_get_sip_address, _set_sip_address) password = property(_get_password, _set_password) verify_password = property(_get_verify_password, _set_verify_password) email_address = property(_get_email_address, _set_email_address) del _get_display_name, _set_display_name, _get_username, _set_username del _get_sip_address, _set_sip_address, _get_email_address, _set_email_address del _get_password, _set_password, _get_verify_password, _set_verify_password def _SH_AcceptButtonClicked(self): if self.panel_view.currentWidget() is self.add_account_panel: account = Account(self.sip_address) account.enabled = True account.display_name = self.display_name or None account.auth.password = self.password account.save() account_manager = AccountManager() account_manager.default_account = account self.accept() else: self.setEnabled(False) self.create_status_label.value = Status( 'Creating account on server...') self._create_sip_account(self.username, self.password, self.email_address, self.display_name) def _SH_PanelChangeRequest(self, index): self.panel_view.setCurrentIndex(index) if self.panel_view.currentWidget() is self.add_account_panel: inputs = [ self.display_name_editor, self.sip_address_editor, self.password_editor ] else: inputs = [ self.name_editor, self.username_editor, self.new_password_editor, self.verify_password_editor, self.email_address_editor ] self.accept_button.setEnabled(all(input.text_valid for input in inputs)) def _SH_PasswordTextChanged(self, text): self.verify_password_editor.regexp = re.compile(u'^%s$' % re.escape(text)) def _SH_ValidityStatusChanged(self): red = '#cc0000' # validate the add panel if not self.display_name_editor.text_valid: self.add_status_label.value = Status( "Display name cannot be empty", color=red) elif not self.sip_address_editor.text_correct: self.add_status_label.value = Status( "SIP address should be specified as user@domain", color=red) elif not self.sip_address_editor.text_allowed: self.add_status_label.value = Status( "An account with this SIP address was already added", color=red) elif not self.password_editor.text_valid: self.add_status_label.value = Status("Password cannot be empty", color=red) else: self.add_status_label.value = None # validate the create panel if not self.name_editor.text_valid: self.create_status_label.value = Status("Name cannot be empty", color=red) elif not self.username_editor.text_correct: self.create_status_label.value = Status( "Username should have 5 to 32 characters, start with a letter or non-zero digit, contain only letters, digits or .-_ and end with a letter or digit", color=red) elif not self.username_editor.text_allowed: self.create_status_label.value = Status( "The username you requested is already taken. Please choose another one and try again.", color=red) elif not self.new_password_editor.text_valid: self.create_status_label.value = Status( "Password should contain at least 8 characters", color=red) elif not self.verify_password_editor.text_valid: self.create_status_label.value = Status("Passwords do not match", color=red) elif not self.email_address_editor.text_valid: self.create_status_label.value = Status( "E-mail address should be specified as user@domain", color=red) else: self.create_status_label.value = None # enable the accept button if everything is valid in the current panel if self.panel_view.currentWidget() is self.add_account_panel: inputs = [ self.display_name_editor, self.sip_address_editor, self.password_editor ] else: inputs = [ self.name_editor, self.username_editor, self.new_password_editor, self.verify_password_editor, self.email_address_editor ] self.accept_button.setEnabled(all(input.text_valid for input in inputs)) def _initialize(self): self.display_name = user_info.fullname self.username = user_info.username.lower().replace(u' ', u'.') self.sip_address = u'' self.password = u'' self.verify_password = u'' self.email_address = u'' @run_in_thread('network-io') def _create_sip_account(self, username, password, email_address, display_name, timezone=None): red = '#cc0000' if timezone is None and sys.platform != 'win32': try: timezone = open('/etc/timezone').read().strip() except (OSError, IOError): try: timezone = '/'.join( os.readlink('/etc/localtime').split('/')[-2:]) except (OSError, IOError): pass enrollment_data = dict(username=username.lower().encode('utf-8'), password=password.encode('utf-8'), email=email_address.encode('utf-8'), display_name=display_name.encode('utf-8'), tzinfo=timezone) try: settings = SIPSimpleSettings() response = urllib2.urlopen(settings.server.enrollment_url, urllib.urlencode(dict(enrollment_data))) response_data = cjson.decode(response.read().replace(r'\/', '/')) response_data = defaultdict(lambda: None, response_data) if response_data['success']: from blink import Blink try: certificate_path = None passport = response_data['passport'] if passport is not None: certificate_path = Blink().save_certificates( response_data['sip_address'], passport['crt'], passport['key'], passport['ca']) except (GNUTLSError, IOError, OSError): pass account_manager = AccountManager() try: account = Account(response_data['sip_address']) except DuplicateIDError: account = account_manager.get_account( response_data['sip_address']) account.enabled = True account.display_name = display_name or None account.auth.password = password account.sip.outbound_proxy = response_data['outbound_proxy'] account.nat_traversal.msrp_relay = response_data['msrp_relay'] account.xcap.xcap_root = response_data['xcap_root'] account.tls.certificate = certificate_path account.server.conference_server = response_data[ 'conference_server'] account.server.settings_url = response_data['settings_url'] account.save() account_manager.default_account = account call_in_gui_thread(self.accept) elif response_data['error'] == 'user_exists': call_in_gui_thread(self.username_editor.addException, username) else: call_in_gui_thread( setattr, self.create_status_label, 'value', Status(response_data['error_message'], color=red)) except (cjson.DecodeError, KeyError): call_in_gui_thread(setattr, self.create_status_label, 'value', Status('Illegal server response', color=red)) except urllib2.URLError, e: call_in_gui_thread( setattr, self.create_status_label, 'value', Status('Failed to contact server: %s' % e.reason, color=red)) finally: