def __init__(self, model): super(BaseProfileController, self).__init__(model) self.suggested_name = None # XXX: One day this could live in the glade file, we need to add # it as a custom widget to glade3 self.dns1_entry = ValidatedEntry(v_ip) self.dns2_entry = ValidatedEntry(v_ip)
class NewSmsController(Controller): """Controller for the new sms dialog""" def __init__(self, model, parent_ctrl = None): super(NewSmsController, self).__init__(model) self.parent_ctrl = parent_ctrl self.max_length = MAX_LENGTH_7BIT self.numbers_entry = ValidatedEntry(v_phone) self.sms = None try: self.numbers_entry.set_tooltip_text(SMS_TOOLTIP) except AttributeError, e: # This fails on Ubuntu Feisty, we can live without it pass
class AddContactController(Controller): """Controller for the add contact dialog""" def __init__(self, model, parent_ctrl): super(AddContactController, self).__init__(model) self.parent_ctrl = parent_ctrl self.name_entry = ValidatedEntry(v_ucs2_name) self.number_entry = ValidatedEntry(v_phone) def register_view(self, view): super(AddContactController, self).register_view(view) if not self.model.get_device(): self.view['mobile_radio_button'].set_sensitive(False) self.view['computer_radio_button'].set_active(True) def on_add_contact_ok_button_clicked(self, widget): if not self.name_entry.isvalid() or not self.number_entry.isvalid(): return name = self.name_entry.get_text() number = self.number_entry.get_text() save_in_sim = self.view['mobile_radio_button'].get_active() phonebook = get_phonebook(self.parent_ctrl.model.get_sconn()) contact = Contact(name, number) def add_callback(contact): # add it to the treeview model model = self.parent_ctrl.view['contacts_treeview'].get_model() model.add_contact(contact) self._hide_me() d = phonebook.add_contact(contact, sim=save_in_sim) d.addCallback(add_callback) def on_add_contact_cancel_button_clicked(self, widget): self._hide_me() def _hide_me(self): self.view.hide() self.model.unregister_observer(self)
class AddContactController(Controller): """Controller for the add contact dialog""" def __init__(self, model, parent_ctrl): super(AddContactController, self).__init__(model) self.parent_ctrl = parent_ctrl self.name_entry = ValidatedEntry(v_ucs2_name) self.number_entry = ValidatedEntry(v_phone) self.group_entry = ValidatedEntry(v_ucs2_name) def register_view(self, view): super(AddContactController, self).register_view(view) def on_add_contact_ok_button_clicked(self, widget): if not self.name_entry.isvalid() or not self.number_entry.isvalid(): return name = self.name_entry.get_text() number = self.number_entry.get_text() group = self.group_entry.get_text() or 'default' phonebook = get_phonebook(self.parent_ctrl.model.get_sconn()) contact = Contact(name, number, group=group) def add_callback(contact): # add it to the treeview model model = self.parent_ctrl.view['contacts_treeview'].get_model() model.add_contact(contact) self._hide_me() d = phonebook.add_contact(contact, sim=False) d.addCallback(add_callback) def on_add_contact_cancel_button_clicked(self, widget): self._hide_me() def _hide_me(self): self.view.hide() self.model.unregister_observer(self)
class BaseProfileController(Controller): def __init__(self, model, quiet=False): super(BaseProfileController, self).__init__(model) self.suggested_name = None self.quiet = quiet # XXX: One day this could live in the glade file, we need to add # it as a custom widget to glade3 self.dns1_entry = ValidatedEntry(v_ip) self.dns2_entry = ValidatedEntry(v_ip) def register_view(self, view): super(BaseProfileController, self).register_view(view) # prepare everythin self.view['vbox3'].set_sensitive(False) # now attach the dns entries to the vbox vbox = self.view['vbox3'] vbox.pack_start(self.dns1_entry) vbox.pack_start(self.dns2_entry) # get device model name = self.model.get_device().name self.view['device_model_label'].set_text(name) if not self.quiet: self.try_to_load_profile_from_imsi_prefix() def propose_profile_name(self): self.suggested_name = '-'.join( [self.model.get_device().name, self.get_connection_combobox_opt()]).replace(' ', '') self.view['profile_name_entry'].set_text(self.suggested_name) def is_profile_name_insane(self): """ Returns True if the profile name has invalid characters """ text = self.view['profile_name_entry'].get_text() for char in INVALID_CHARS: if char in text: return True return False def try_to_load_profile_from_imsi_prefix(self): def get_profile_cb(profile): if profile: message = _('Configuration details found for Operator!') details = _("""Do you want to load stored settings for %s?""" ) % profile.get_full_name() resp = dialogs.open_confirm_action_dialog( _('Load'), message, details) if resp: self.load_network_profile(profile) self.propose_profile_name() self.model.get_profile_from_imsi_prefix().addCallback(get_profile_cb) def load_mobile_profile(self, profile): CON = 'connection' self.view['profile_name_entry'].set_text(profile.name) self.view['username_entry'].set_text(profile.get(CON, 'username')) self.view['password_entry'].set_text(profile.get(CON, 'username')) self.view['apn_entry'].set_text(profile.get(CON, 'apn')) if profile.get(CON, 'dns1') or profile.get(CON, 'dns2'): self.view['dns_checkbutton'].set_active(True) self.dns1_entry.set_text(profile.get(CON, 'dns1')) self.dns2_entry.set_text(profile.get(CON, 'dns2')) # now set auth and combobox self.set_auth_combobox_opt(profile.get(CON, 'dialer_profile')) self.set_connection_combobox_opt(profile.get(CON, CON)) def load_network_profile(self, profile): self.view['username_entry'].set_text(profile.username) self.view['password_entry'].set_text(profile.password) self.view['apn_entry'].set_text(profile.apn) if profile.dns1 or profile.dns2: self.view['dns_checkbutton'].set_active(True) self.dns1_entry.set_text(profile.dns1) self.dns2_entry.set_text(profile.dns2) def get_auth_combobox_opt(self): model = self.view['auth_combobox'].get_model() index = self.view['auth_combobox'].get_active() if index < 0: # no auth selected on combobox return None else: return unicode(model[index][0], 'utf8') def set_auth_combobox_opt(self, opt): model = self.view['auth_combobox'].get_model() for i, row in enumerate(model): if row[0] == AUTH_OPTS_DICT_REV[opt]: self.view['auth_combobox'].set_active(i) break def get_connection_combobox_opt(self): model = self.view['connection_combobox'].get_model() index = self.view['connection_combobox'].get_active() if index < 0: # no connection selected on combobox return None else: return unicode(model[index][0], 'utf8') def set_connection_combobox_opt(self, opt): model = self.view['connection_combobox'].get_model() for i, row in enumerate(model): if row[0] == CONN_OPTS_DICT_REV[opt]: self.view['connection_combobox'].set_active(i) break def get_profile_settings(self): conn = self.get_connection_combobox_opt() auth = self.get_auth_combobox_opt() if not conn or not auth: return None return dict(profile_name=self.view['profile_name_entry'].get_text(), username=self.view['username_entry'].get_text(), password=self.view['password_entry'].get_text(), connection=CONN_OPTS_DICT[conn], apn=self.view['apn_entry'].get_text(), dialer_profile=AUTH_OPTS_DICT[auth], staticdns=self.view['dns_checkbutton'].get_active(), dns1=self.dns1_entry.get_text(), dns2=self.dns2_entry.get_text()) def on_cancel_button_clicked(self, widget): self.hide_ourselves() if hasattr(self, 'startup') and self.startup: shutdown_core() def on_dns_checkbutton_toggled(self, widget): self.view['vbox3'].set_sensitive(widget.get_active()) def on_connection_combobox_changed(self, combobox): if not self.view: # we have to load first the view and then register it with it with # the controller, however if we register the view before building # it, the combobox models wont be ready. If we do it this way, # the models will be ready, but when we propose the combobox opts # while creating a new profile, self.view will be == None, it's # all good thou return if not self.the_name_is_custom(): self.propose_profile_name() def the_name_is_custom(self): name = self.view['profile_name_entry'].get_text() return name != self.suggested_name def hide_ourselves(self): self.model.unregister_observer(self) self.view.get_top_widget().destroy() self.view = None self.model = None
def __init__(self, model): Controller.__init__(self, model) self.initial_smsc = None self.smsc_entry = ValidatedEntry(v_phone)
class SMSPreferencesController(Controller): """ Controller for the SMS preferences window """ def __init__(self, model): Controller.__init__(self, model) self.initial_smsc = None self.smsc_entry = ValidatedEntry(v_phone) def register_view(self, view): Controller.register_view(self, view) self._setup() def _setup(self): d = self.model.get_smsc() def get_smsc_cb(smsc): if not smsc: # XXX: return self.smsc_entry.set_text(smsc) self.initial_smsc = smsc self._check_smsc(smsc) d.addCallback(get_smsc_cb) self._setup_message_options() def _check_smsc(self, smsc): d = self.model.get_imsi() def get_imsi_cb(imsi): # we will setup the combobox options here items = [] network = net_manager.get_network_by_id(imsi) if not network: # we dont know anything about this network operator, we will # just show 'Unknown' in the combobox, giving no options to # the user items.append(SMSCItem(_("Unknown"))) else: if network.smsc: # we know the network and we have its SMSC if smsc != network.smsc: # as the SMSC is different that the stored one, # we are gonna append "Custom" too items.append(SMSCItem(_("Custom"))) items.append( SMSCItem(network.get_full_name(), network.smsc, active=False)) else: items.append( SMSCItem(network.get_full_name(), network.smsc)) else: # we dont know the SMSC of this network items.append(SMSCItem(_("Unknown"))) self.view.populate_smsc_combobox(items) d.addCallback(get_imsi_cb) def _setup_message_options(self): validity = config.get('sms', 'validity') if not validity: config.set('sms', 'validity', 'maximum') config.write() validity = 'maximum' combobox = self.view['validity_combobox'] model = combobox.get_model() for i, row in enumerate(model): option = row[0] if validity == VALIDITY_DICT[option]: combobox.set_active(i) break def _hide_myself(self): self.view.hide() self.model.unregister_observer(self) def on_combobox1_changed(self, combobox): smscobj = self._get_active_combobox_item('combobox1') if smscobj and smscobj.number: self.smsc_entry.set_text(smscobj.number) def _get_active_combobox_item(self, comboname): combobox = self.view[comboname] model = combobox.get_model() active = combobox.get_active() if active < 0: return None return model[active][0] def on_ok_button_clicked(self, widget): # save message options validity = self._get_active_combobox_item('validity_combobox') if validity: validity_key = VALIDITY_DICT[validity] config.set('sms', 'validity', validity_key) config.write() # check that we have changed the SMSC info if self.smsc_entry.isvalid(): smscnumber = self.smsc_entry.get_text() if self.initial_smsc != smscnumber: d = self.model.set_smsc(smscnumber) d.addCallback(lambda x: self._hide_myself()) else: self._hide_myself() def on_cancel_button_clicked(self, widget): self._hide_myself()
class SMSPreferencesController(Controller): """ Controller for the SMS preferences window """ def __init__(self, model): Controller.__init__(self, model) self.initial_smsc = None self.smsc_entry = ValidatedEntry(v_phone) def register_view(self, view): Controller.register_view(self, view) self._setup() def _setup(self): d = self.model.get_smsc() def get_smsc_cb(smsc): if not smsc: # XXX: return self.smsc_entry.set_text(smsc) self.initial_smsc = smsc self._check_smsc(smsc) d.addCallback(get_smsc_cb) self._setup_message_options() def _check_smsc(self, smsc): d = self.model.get_imsi() def get_imsi_cb(imsi): # we will setup the combobox options here items = [] network = net_manager.get_network_by_id(imsi[:5]) if not network: # we dont know anything about this network operator, we will # just show 'Unknown' in the combobox, giving no options to # the user items.append(SMSCItem(_("Unknown"))) else: if network.smsc: # we know the network and we have its SMSC if smsc != network.smsc: # as the SMSC is different that the stored one, # we are gonna append "Custom" too items.append(SMSCItem(_("Custom"))) items.append(SMSCItem(network.get_full_name(), network.smsc, active=False)) else: items.append(SMSCItem(network.get_full_name(), network.smsc)) else: # we dont know the SMSC of this network items.append(SMSCItem(_("Unknown"))) self.view.populate_smsc_combobox(items) d.addCallback(get_imsi_cb) def _setup_message_options(self): validity = config.get('sms', 'validity') if not validity: config.set('sms', 'validity', 'maximum') config.write() validity = 'maximum' combobox = self.view['validity_combobox'] model = combobox.get_model() for i, row in enumerate(model): option = row[0] if validity == VALIDITY_DICT[option]: combobox.set_active(i) break def _hide_myself(self): self.view.hide() self.model.unregister_observer(self) def on_combobox1_changed(self, combobox): smscobj = self._get_active_combobox_item('combobox1') if smscobj and smscobj.number: self.smsc_entry.set_text(smscobj.number) def _get_active_combobox_item(self, comboname): combobox = self.view[comboname] model = combobox.get_model() active = combobox.get_active() if active < 0: return None return model[active][0] def on_ok_button_clicked(self, widget): # save message options validity = self._get_active_combobox_item('validity_combobox') if validity: validity_key = VALIDITY_DICT[validity] config.set('sms', 'validity', validity_key) config.write() # check that we have changed the SMSC info if self.smsc_entry.isvalid(): smscnumber = self.smsc_entry.get_text() if self.initial_smsc != smscnumber: d = self.model.set_smsc(smscnumber) d.addCallback(lambda x: self._hide_myself()) else: self._hide_myself() def on_cancel_button_clicked(self, widget): self._hide_myself()
def __init__(self, model, parent_ctrl): super(AddContactController, self).__init__(model) self.parent_ctrl = parent_ctrl self.name_entry = ValidatedEntry(v_ucs2_name) self.number_entry = ValidatedEntry(v_phone) self.group_entry = ValidatedEntry(v_ucs2_name)
class BaseProfileController(Controller): def __init__(self, model, quiet=False): super(BaseProfileController, self).__init__(model) self.suggested_name = None self.quiet = quiet # XXX: One day this could live in the glade file, we need to add # it as a custom widget to glade3 self.dns1_entry = ValidatedEntry(v_ip) self.dns2_entry = ValidatedEntry(v_ip) def register_view(self, view): super(BaseProfileController, self).register_view(view) # prepare everythin self.view['vbox3'].set_sensitive(False) # now attach the dns entries to the vbox vbox = self.view['vbox3'] vbox.pack_start(self.dns1_entry) vbox.pack_start(self.dns2_entry) # get device model name = self.model.get_device().name self.view['device_model_label'].set_text(name) if not self.quiet: self.try_to_load_profile_from_imsi_prefix() def propose_profile_name(self): self.suggested_name = '-'.join([self.model.get_device().name, self.get_connection_combobox_opt()]).replace(' ', '') self.view['profile_name_entry'].set_text(self.suggested_name) def is_profile_name_insane(self): """ Returns True if the profile name has invalid characters """ text = self.view['profile_name_entry'].get_text() for char in INVALID_CHARS: if char in text: return True return False def try_to_load_profile_from_imsi_prefix(self): def get_profile_cb(profile): if profile: message = _('Configuration details found for Operator!') details = _( """Do you want to load stored settings for %s?""") % profile.get_full_name() resp = dialogs.open_confirm_action_dialog(_('Load'), message, details) if resp: self.load_network_profile(profile) self.propose_profile_name() self.model.get_profile_from_imsi_prefix().addCallback(get_profile_cb) def load_mobile_profile(self, profile): CON = 'connection' self.view['profile_name_entry'].set_text(profile.name) self.view['username_entry'].set_text(profile.get(CON, 'username')) self.view['password_entry'].set_text(profile.get(CON, 'username')) self.view['apn_entry'].set_text(profile.get(CON, 'apn')) if profile.get(CON, 'dns1') or profile.get(CON, 'dns2'): self.view['dns_checkbutton'].set_active(True) self.dns1_entry.set_text(profile.get(CON, 'dns1')) self.dns2_entry.set_text(profile.get(CON, 'dns2')) # now set auth and combobox self.set_auth_combobox_opt(profile.get(CON, 'dialer_profile')) self.set_connection_combobox_opt(profile.get(CON, CON)) def load_network_profile(self, profile): self.view['username_entry'].set_text(profile.username) self.view['password_entry'].set_text(profile.password) self.view['apn_entry'].set_text(profile.apn) if profile.dns1 or profile.dns2: self.view['dns_checkbutton'].set_active(True) self.dns1_entry.set_text(profile.dns1) self.dns2_entry.set_text(profile.dns2) def get_auth_combobox_opt(self): model = self.view['auth_combobox'].get_model() index = self.view['auth_combobox'].get_active() if index < 0: # no auth selected on combobox return None else: return unicode(model[index][0], 'utf8') def set_auth_combobox_opt(self, opt): model = self.view['auth_combobox'].get_model() for i, row in enumerate(model): if row[0] == AUTH_OPTS_DICT_REV[opt]: self.view['auth_combobox'].set_active(i) break def get_connection_combobox_opt(self): model = self.view['connection_combobox'].get_model() index = self.view['connection_combobox'].get_active() if index < 0: # no connection selected on combobox return None else: return unicode(model[index][0], 'utf8') def set_connection_combobox_opt(self, opt): model = self.view['connection_combobox'].get_model() for i, row in enumerate(model): if row[0] == CONN_OPTS_DICT_REV[opt]: self.view['connection_combobox'].set_active(i) break def get_profile_settings(self): conn = self.get_connection_combobox_opt() auth = self.get_auth_combobox_opt() if not conn or not auth: return None return dict(profile_name=self.view['profile_name_entry'].get_text(), username=self.view['username_entry'].get_text(), password=self.view['password_entry'].get_text(), connection=CONN_OPTS_DICT[conn], apn=self.view['apn_entry'].get_text(), dialer_profile=AUTH_OPTS_DICT[auth], staticdns=self.view['dns_checkbutton'].get_active(), dns1=self.dns1_entry.get_text(), dns2=self.dns2_entry.get_text()) def on_cancel_button_clicked(self, widget): self.hide_ourselves() if hasattr(self, 'startup') and self.startup: shutdown_core() def on_dns_checkbutton_toggled(self, widget): self.view['vbox3'].set_sensitive(widget.get_active()) def on_connection_combobox_changed(self, combobox): if not self.view: # we have to load first the view and then register it with it with # the controller, however if we register the view before building # it, the combobox models wont be ready. If we do it this way, # the models will be ready, but when we propose the combobox opts # while creating a new profile, self.view will be == None, it's # all good thou return if not self.the_name_is_custom(): self.propose_profile_name() def the_name_is_custom(self): name = self.view['profile_name_entry'].get_text() return name != self.suggested_name def hide_ourselves(self): self.model.unregister_observer(self) self.view.get_top_widget().destroy() self.view = None self.model = None
class BaseProfileController(Controller): def __init__(self, model): super(BaseProfileController, self).__init__(model) self.suggested_name = None # XXX: One day this could live in the glade file, we need to add # it as a custom widget to glade3 self.dns1_entry = ValidatedEntry(v_ip) self.dns2_entry = ValidatedEntry(v_ip) def register_view(self, view): super(BaseProfileController, self).register_view(view) # prepare everythin self.view['vbox3'].set_sensitive(False) # now attach the dns entries to the vbox vbox = self.view['vbox3'] vbox.pack_start(self.dns1_entry) vbox.pack_start(self.dns2_entry) # get device model name = self.model.get_device().name self.view['device_model_label'].set_text(name) self.pop_connection_combobox_opt() def set_profile_name(self, name): self.view['profile_name_entry'].set_text(name) def propose_profile_name(self): device = self.model.get_device().name bearer = self.get_connection_combobox_opt() if not bearer: self.suggested_name = device.replace(' ', '') else: self.suggested_name = '-'.join([device,bearer]).replace(' ', '') self.view['profile_name_entry'].set_text(self.suggested_name) def is_profile_name_insane(self): """ Returns True if the profile name has invalid characters """ text = self.view['profile_name_entry'].get_text() for char in INVALID_CHARS: if char in text: return True return False def load_mobile_profile(self, profile): CON = 'connection' self.view['profile_name_entry'].set_text(profile.name) self.view['username_entry'].set_text(profile.get(CON, 'username')) self.view['password_entry'].set_text(profile.get(CON, 'username')) self.view['apn_entry'].set_text(profile.get(CON, 'apn')) self.view['dns_checkbutton'].set_active(profile.getboolean(CON, 'staticdns')) self.dns1_entry.set_text(profile.get(CON, 'dns1')) self.dns2_entry.set_text(profile.get(CON, 'dns2')) # now set auth and combobox self.set_auth_combobox_opt(profile.get(CON, 'dialer_profile')) self.set_connection_combobox_opt(profile.get(CON, CON)) def load_network_profile(self, profile): self.view['username_entry'].set_text(profile.username) self.view['password_entry'].set_text(profile.password) self.view['apn_entry'].set_text(profile.apn) if profile.dns1 or profile.dns2: self.view['dns_checkbutton'].set_active(True) self.dns1_entry.set_text(profile.dns1) self.dns2_entry.set_text(profile.dns2) def get_auth_combobox_opt(self): model = self.view['auth_combobox'].get_model() index = self.view['auth_combobox'].get_active() if index < 0: # no auth selected on combobox return None else: return unicode(model[index][0], 'utf8') def set_auth_combobox_opt(self, opt): model = self.view['auth_combobox'].get_model() for i, row in enumerate(model): if row[0] == AUTH_OPTS_DICT_REV[opt]: self.view['auth_combobox'].set_active(i) break def pop_connection_combobox_opt(self): model = self.view['connection_combobox'].get_model() conn_dict = self.model.get_device().custom.conn_dict model.clear() for item in conn_dict: if conn_dict[item] != None: opt = CONN_OPTS_DICT_REV[item] model.append([opt]) for i, row in enumerate(model): if row[0] == CONN_OPTS_DICT_REV['3GPREF']: self.view['connection_combobox'].set_active(i) break if not len(model): self.view['connection_combobox'].set_sensitive(0) def get_connection_combobox_opt(self): model = self.view['connection_combobox'].get_model() index = self.view['connection_combobox'].get_active() if index < 0: # no connection selected on combobox return None else: return unicode(model[index][0], 'utf8') def set_connection_combobox_opt(self, opt): model = self.view['connection_combobox'].get_model() for i, row in enumerate(model): if row[0] == CONN_OPTS_DICT_REV[opt]: self.view['connection_combobox'].set_active(i) break def get_profile_settings(self): conn = self.get_connection_combobox_opt() connection = conn and CONN_OPTS_DICT[conn] or None auth = self.get_auth_combobox_opt() dialer_profile = auth and AUTH_OPTS_DICT[auth] or None return dict(profile_name=self.view['profile_name_entry'].get_text(), username=self.view['username_entry'].get_text(), password=self.view['password_entry'].get_text(), connection=connection, apn=self.view['apn_entry'].get_text(), dialer_profile=dialer_profile, staticdns=self.view['dns_checkbutton'].get_active(), dns1=self.dns1_entry.get_text(), dns2=self.dns2_entry.get_text()) def on_cancel_button_clicked(self, widget): self.hide_ourselves() if hasattr(self, 'startup') and self.startup: shutdown_core() def on_dns_checkbutton_toggled(self, widget): self.view['vbox3'].set_sensitive(widget.get_active()) def on_connection_combobox_changed(self, combobox): if not self.view: # we have to load first the view and then register it with it with # the controller, however if we register the view before building # it, the combobox models wont be ready. If we do it this way, # the models will be ready, but when we propose the combobox opts # while creating a new profile, self.view will be == None, it's # all good thou return if not self.the_name_is_custom(): self.propose_profile_name() def the_name_is_custom(self): name = self.view['profile_name_entry'].get_text() return name != self.suggested_name def hide_ourselves(self): self.model.unregister_observer(self) self.view.get_top_widget().destroy() self.view = None self.model = None def settings_valid(self,settings): class Problem(Exception): def __init__(self,detail): self.detail = detail def __str__(self): return repr(self.detail) try: if not settings: raise Problem("Profile settings are Null") if settings['staticdns']: if self.dns1_entry.get_text() == '' and self.dns2_entry.get_text() == '': raise Problem("If static DNS is enabled, you must define at least one address") if not self.dns1_entry.isvalid() and not self.dns1_entry.get_text() == '': raise Problem("Primary DNS address is invalid") if not self.dns2_entry.isvalid() and not self.dns2_entry.get_text() == '': raise Problem("Secondary DNS address is invalid") if settings['apn'] == '': raise Problem("You must specify an APN") if not settings['profile_name'] or settings['profile_name'] == '': self.view['profile_name_entry'].grab_focus() raise Problem("profile name is invalid") if self.is_profile_name_insane(): raise Problem(_("""The following characters are not allowed in a profile name: %s""") % ' '.join(INVALID_CHARS)) except Problem, (instance): message = _('Invalid value in profile') dialogs.open_warning_dialog(message, instance.detail) return False return True