Commit 0aaa9c41 authored by Philipp Hörist's avatar Philipp Hörist

Make change password dialog an Assistant

parent f5ea6686
Pipeline #4678 passed with stages
in 2 minutes and 36 seconds
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.22.1 -->
<interface>
<requires lib="gtk+" version="3.12"/>
<object class="GtkBox" id="change_password_box">
<property name="width_request">220</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_bottom">12</property>
<property name="orientation">vertical</property>
<property name="spacing">6</property>
<child>
<object class="GtkEntry" id="password1_entry">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="visibility">False</property>
<property name="placeholder_text" translatable="yes">New Password</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkEntry" id="password2_entry">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="visibility">False</property>
<property name="activates_default">True</property>
<property name="placeholder_text" translatable="yes">Confirm New Password</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="error_label">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="wrap">True</property>
<property name="xalign">0</property>
<style>
<class name="error-color"/>
</style>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">2</property>
</packing>
</child>
</object>
</interface>
# This file is part of Gajim.
#
# Gajim is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published
# by the Free Software Foundation; version 3 only.
#
# Gajim is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Gajim. If not, see <http://www.gnu.org/licenses/>.
import logging
from gi.repository import Gtk
from nbxmpp.util import is_error_result
from gajim.common import app
from gajim.common.i18n import _
from gajim.common import passwords
from gajim.common.helpers import to_user_string
from gajim.gtk.assistant import Assistant
from gajim.gtk.assistant import Page
from gajim.gtk.dataform import DataFormWidget
from gajim.gtk.util import ensure_not_destroyed
log = logging.getLogger('gajim.gtk.change_password')
class ChangePassword(Assistant):
def __init__(self, account):
Assistant.__init__(self)
self.account = account
self._con = app.connections.get(account)
self._destroyed = False
self.add_button('apply', _('Change'), 'suggested-action',
complete=True)
self.add_button('close', _('Close'))
self.add_button('back', _('Back'))
self.add_pages({'password': EnterPassword(),
'next_stage': NextStage()})
progress = self.add_default_page('progress')
progress.set_title(_('Changing Password...'))
progress.set_text(_('Trying to change password...'))
success = self.add_default_page('success')
success.set_title(_('Password Changed'))
success.set_heading(_('Password Changed'))
success.set_text(_('Your password has successfully been changed.'))
error = self.add_default_page('error')
error.set_title(_('Password Change Failed'))
error.set_heading(_('Password Change Failed'))
error.set_text(
_('An error occured while trying to change your password.'))
self.set_button_visible_func(self._visible_func)
self.connect('button-clicked', self._on_button_clicked)
self.connect('page-changed', self._on_page_changed)
self.connect('destroy', self._on_destroy)
self.show_all()
@staticmethod
def _visible_func(_assistant, page_name):
if page_name in ('password', 'next_stage'):
return ['apply']
if page_name == 'progress':
return None
if page_name == 'error':
return ['back']
if page_name == 'success':
return ['close']
raise ValueError('page %s unknown' % page_name)
def _on_button_clicked(self, _assistant, button_name):
page = self.get_current_page()
if button_name == 'apply':
self.show_page('progress', Gtk.StackTransitionType.SLIDE_LEFT)
self._on_apply(next_stage=page == 'next_stage')
elif button_name == 'back':
self.show_page('password', Gtk.StackTransitionType.SLIDE_RIGHT)
elif button_name == 'close':
self.destroy()
def _on_page_changed(self, _assistant, page_name):
if page_name in ('password', 'next_stage'):
self.set_default_button('apply')
elif page_name == 'success':
password = self.get_page('password').get_password()
passwords.save_password(self.account, password)
self.set_default_button('close')
elif page_name == 'error':
self.set_default_button('back')
def _on_apply(self, next_stage=False):
register = self._con.connection.get_module('Register')
if next_stage:
form = self.get_page('next_stage').get_submit_form()
register.change_password_with_form(
form, callback=self._on_change_password)
else:
password = self.get_page('password').get_password()
register.change_password(password,
callback=self._on_change_password)
@ensure_not_destroyed
def _on_change_password(self, result):
if is_error_result(result):
error_text = to_user_string(result)
self.get_page('error').set_text(error_text)
self.show_page('error', Gtk.StackTransitionType.SLIDE_LEFT)
elif result.successful:
self.show_page('success')
else:
self.get_page('next_stage').set_form(result.form)
self.show_page('next_stage', Gtk.StackTransitionType.SLIDE_LEFT)
def _on_destroy(self, *args):
self._destroyed = True
class EnterPassword(Page):
def __init__(self):
Page.__init__(self)
self.complete = False
self.title = _('Change Password')
heading = Gtk.Label(label=_('Change Password'))
heading.get_style_context().add_class('large-header')
heading.set_max_width_chars(30)
heading.set_line_wrap(True)
heading.set_halign(Gtk.Align.CENTER)
heading.set_justify(Gtk.Justification.CENTER)
label = Gtk.Label(label=_('Please enter your new password.'))
label.set_max_width_chars(50)
label.set_line_wrap(True)
label.set_halign(Gtk.Align.CENTER)
label.set_justify(Gtk.Justification.CENTER)
label.set_margin_bottom(12)
self._password1_entry = Gtk.Entry()
self._password1_entry.set_input_purpose(Gtk.InputPurpose.PASSWORD)
self._password1_entry.set_visibility(False)
self._password1_entry.set_invisible_char('•')
self._password1_entry.set_valign(Gtk.Align.END)
self._password1_entry.set_placeholder_text(
_('Enter new password...'))
self._password1_entry.connect('changed', self._on_changed)
self._password2_entry = Gtk.Entry()
self._password2_entry.set_input_purpose(Gtk.InputPurpose.PASSWORD)
self._password2_entry.set_visibility(False)
self._password2_entry.set_invisible_char('•')
self._password2_entry.set_activates_default(True)
self._password2_entry.set_valign(Gtk.Align.START)
self._password2_entry.set_placeholder_text(
_('Confirm new password...'))
self._password2_entry.connect('changed', self._on_changed)
self.pack_start(heading, False, True, 0)
self.pack_start(label, False, True, 0)
self.pack_start(self._password1_entry, True, True, 0)
self.pack_start(self._password2_entry, True, True, 0)
self._show_icon(False)
self.show_all()
def _show_icon(self, show):
if show:
self._password2_entry.set_icon_from_icon_name(
Gtk.EntryIconPosition.SECONDARY, 'dialog-warning-symbolic')
self._password2_entry.set_icon_tooltip_text(
Gtk.EntryIconPosition.SECONDARY, _('Passwords do not match'))
else:
self._password2_entry.set_icon_from_icon_name(
Gtk.EntryIconPosition.SECONDARY, None)
def _on_changed(self, _entry):
password1 = self._password1_entry.get_text()
if not password1:
self._show_icon(True)
self._set_complete(False)
return
password2 = self._password2_entry.get_text()
if password1 != password2:
self._show_icon(True)
self._set_complete(False)
return
self._show_icon(False)
self._set_complete(True)
def _set_complete(self, state):
self.complete = state
self.get_toplevel().update_page_complete()
def get_password(self):
return self._password1_entry.get_text()
class NextStage(Page):
def __init__(self):
Page.__init__(self)
self.set_valign(Gtk.Align.FILL)
self.complete = False
self.title = _('Change Password')
self._current_form = None
self.show_all()
def _on_is_valid(self, _widget, is_valid):
self.complete = is_valid
self.get_toplevel().update_page_complete()
def set_form(self, form):
if self._current_form is not None:
self.remove(self._current_form)
self._current_form.destroy()
self._current_form = DataFormWidget(form)
self._current_form.connect('is-valid', self._on_is_valid)
self._current_form.validate()
self.pack_start(self._current_form, True, True, 0)
self._current_form.show_all()
def get_submit_form(self):
return self._current_form.get_submit_form()
......@@ -130,4 +130,5 @@ WINDOW_MODULES = {
'CertificateDialog': 'gajim.gtk.dialogs',
'SubscriptionRequest': 'gajim.gtk.subscription_request',
'RemoveAccount': 'gajim.gtk.remove_account',
'ChangePassword': 'gajim.gtk.change_password',
}
......@@ -258,59 +258,6 @@ class CertificateDialog(Gtk.ApplicationWindow):
self._clipboard.set_text(clipboard_text, -1)
class ChangePasswordDialog(Gtk.Dialog):
def __init__(self, account, success_cb, transient_for):
super().__init__(title=_('Change Password'),
transient_for=transient_for,
destroy_with_parent=True)
self._account = account
self._success_cb = success_cb
self._builder = get_builder('change_password_dialog.ui')
self.get_content_area().add(
self._builder.get_object('change_password_box'))
self._password1_entry = self._builder.get_object('password1_entry')
self._password2_entry = self._builder.get_object('password2_entry')
self._error_label = self._builder.get_object('error_label')
self.add_button(_('_OK'), Gtk.ResponseType.OK)
self.set_default_response(Gtk.ResponseType.OK)
self.get_style_context().add_class('dialog-margin')
self.connect('response', self._on_dialog_response)
self.show_all()
def _on_dialog_response(self, dialog, response):
if response != Gtk.ResponseType.OK:
self.destroy()
return
password1 = self._password1_entry.get_text()
if not password1:
self._error_label.set_text(_('You must enter a password'))
return
password2 = self._password2_entry.get_text()
if password1 != password2:
self._error_label.set_text(_('Passwords do not match'))
return
self._password1_entry.set_sensitive(False)
self._password2_entry.set_sensitive(False)
con = app.connections[self._account]
con.get_module('Register').change_password(
password1, self._on_success, self._on_error)
def _on_success(self):
self._success_cb(self._password1_entry.get_text())
self.destroy()
def _on_error(self, error_text):
self._error_label.set_text(error_text)
self._password1_entry.set_sensitive(True)
self._password2_entry.set_sensitive(True)
class InvitationReceivedDialog(Gtk.ApplicationWindow):
def __init__(self, account, event):
Gtk.ApplicationWindow.__init__(self)
......
......@@ -28,9 +28,9 @@ from gajim.common.exceptions import GajimGeneralException
from gajim import gtkgui_helpers
from gajim.gtk.dialogs import ChangePasswordDialog
from gajim.gtk.util import get_image_button
from gajim.gtk.util import MaxWidthComboBoxText
from gajim.gtk.util import open_window
from gajim.gtk.const import SettingKind
from gajim.gtk.const import SettingType
......@@ -635,18 +635,10 @@ class CutstomHostnameSetting(DialogSetting):
class ChangePasswordSetting(DialogSetting):
def __init__(self, *args, **kwargs):
DialogSetting.__init__(self, *args, **kwargs)
self.change_dialog = None
def show_dialog(self, parent):
try:
self.change_dialog = ChangePasswordDialog(
self.account, self.on_changed, parent)
except GajimGeneralException:
return
self.change_dialog.set_modal(True)
def on_changed(self, new_password):
self.set_value(new_password)
parent.destroy()
open_window('ChangePassword', account=self.account)
def update_activatable(self, name, value):
activatable = False
......
from functools import partial
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
from nbxmpp.modules.dataforms import create_field
from nbxmpp.modules.dataforms import SimpleDataForm
from gajim.common.const import CSSPriority
from gajim.gtk.change_password import ChangePassword
from test.gtk import util
util.load_style('gajim.css', CSSPriority.APPLICATION)
fields = [
create_field(typ='text-single', label='Username', var='username'),
create_field(typ='text-single', label='Old Password', var='old_password'),
create_field(typ='text-single', label='Mothers name', var='mother', required=True),
]
form = SimpleDataForm(type_='form', fields=fields)
def _apply(self, next_stage=False):
if next_stage:
print(self.get_page('next_stage').get_submit_form())
else:
self.get_page('next_stage').set_form(form)
self.show_page('next_stage', Gtk.StackTransitionType.SLIDE_LEFT)
win = ChangePassword(None)
win._on_apply = partial(_apply, win)
win.connect('destroy', Gtk.main_quit)
win.show_all()
Gtk.main()
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