Philipp Hörist pushed to branch master at gajim / gajim
Commits: e3066fb5 by Philipp Hörist at 2018-04-15T23:36:34+02:00 Improve AccountsWindow design
Fixes #8940
- - - - - 53b38bd5 by Philipp Hörist at 2018-04-15T23:36:34+02:00 Use JID as default account name
Fixes #8939
- - - - -
6 changed files:
- gajim/accounts_window.py - gajim/common/helpers.py - gajim/config.py - gajim/data/gui/accounts_window.ui - gajim/data/style/gajim.css - gajim/options_dialog.py
Changes:
===================================== gajim/accounts_window.py ===================================== --- a/gajim/accounts_window.py +++ b/gajim/accounts_window.py @@ -1,15 +1,15 @@ from functools import partial
-from gi.repository import Gtk, Gio, GLib, Gdk +from gi.repository import Gtk, GLib, Gdk
from gajim.common import app -from gajim.gtkgui_helpers import get_image_button from gajim import gtkgui_helpers from gajim import gui_menu_builder from gajim.common import passwords from gajim import dialogs from gajim import config from gajim.common import helpers +from gajim.common import ged from gajim.common.connection import Connection from gajim.common.zeroconf.connection_zeroconf import ConnectionZeroconf from gajim.options_dialog import OptionsDialog, OptionsBox @@ -23,27 +23,20 @@ class AccountsWindow(Gtk.ApplicationWindow): self.set_position(Gtk.WindowPosition.CENTER) self.set_show_menubar(False) self.set_name('AccountsWindow') - self.set_size_request(500, -1) + self.set_default_size(700, 550) self.set_resizable(False) + self.set_title(_('Accounts')) self.need_relogin = {}
- glade_objects = [ - 'stack', 'box', 'actionbar', 'headerbar', 'back_button', - 'menu_button', 'account_page', 'account_list'] + glade_objects = ['stack', 'box', 'account_list'] self.builder = gtkgui_helpers.get_gtk_builder('accounts_window.ui') for obj in glade_objects: setattr(self, obj, self.builder.get_object(obj))
- self.set_titlebar(self.headerbar) - - menu = Gio.Menu() - menu.append(_('Merge Accounts'), 'app.merge') - menu.append(_('Use PGP Agent'), 'app.agent') - self.menu_button.set_menu_model(menu) - - button = get_image_button('list-add-symbolic', _('Add')) - button.set_action_name('app.add-account') - self.actionbar.pack_start(button) + self.account_list.add(Preferences(self)) + account_item = AddAccount() + self.account_list.add(account_item) + account_item.set_activatable()
accounts = app.config.get_per('accounts') accounts.sort() @@ -58,40 +51,37 @@ class AccountsWindow(Gtk.ApplicationWindow):
self.connect('destroy', self.on_destroy) self.connect('key-press-event', self.on_key_press) + + self._activate_preferences_page() self.show_all()
+ app.ged.register_event_handler( + 'our-show', ged.GUI2, self._nec_our_status) + + def _nec_our_status(self, event): + self.update_accounts() + + def _activate_preferences_page(self): + row = self.account_list.get_row_at_index(0) + self.account_list.select_row(row) + self.account_list.emit('row-activated', row) + def on_key_press(self, widget, event): if event.keyval == Gdk.KEY_Escape: self.destroy()
def on_destroy(self, *args): self.check_relogin() + app.ged.remove_event_handler( + 'our-show', ged.GUI2, self._nec_our_status) del app.interface.instances['accounts']
def on_child_visible(self, stack, *args): page = stack.get_visible_child_name() if page is None: return - if page == 'main': - self.menu_button.show() - self.back_button.hide() - self.check_relogin() - else: - self.back_button.show() - self.menu_button.hide() - - def on_back_button(self, *args): - page = self.stack.get_visible_child_name() - child = self.stack.get_visible_child() - self.remove_all_pages() if page == 'account': - child.toggle.set_active(False) - self.stack.add_named(self.account_page, 'main') - self.stack.set_visible_child_name('main') - self.update_accounts() - else: - self.stack.add_named(child.parent, 'account') - self.stack.set_visible_child_name('account') + self.check_relogin()
def update_accounts(self): for row in self.account_list.get_children(): @@ -222,6 +212,7 @@ class AccountsWindow(Gtk.ApplicationWindow): self.account_list.remove(row) del self.need_relogin[account] break + self._activate_preferences_page()
def add_account(self, account): account_item = Account(account, self) @@ -312,61 +303,92 @@ class AccountsWindow(Gtk.ApplicationWindow): gui_menu_builder.build_accounts_menu()
+class AddAccount(Gtk.Box): + def __init__(self): + Gtk.Box.__init__(self, orientation=Gtk.Orientation.HORIZONTAL, + spacing=12) + + self.account = None + + self.label = Gtk.Label(_('Add Account…')) + self.label.set_halign(Gtk.Align.START) + self.label.set_hexpand(True) + + self.image = Gtk.Image.new_from_icon_name( + 'list-add-symbolic', Gtk.IconSize.MENU) + + self.add(self.image) + self.add(self.label) + + def set_activatable(self): + self.get_parent().set_selectable(False) + + def on_row_activated(self): + app.app.activate_action('add-account') + + def update(self): + pass + + +class Preferences(Gtk.Box): + def __init__(self, parent): + Gtk.Box.__init__(self, orientation=Gtk.Orientation.HORIZONTAL, + spacing=12) + + self.options = PreferencesPage() + self.parent = parent + self.account = None + + self.label = Gtk.Label(_('Preferences')) + self.label.set_halign(Gtk.Align.START) + self.label.set_hexpand(True) + + self.image = Gtk.Image.new_from_icon_name( + 'system-run-symbolic', Gtk.IconSize.MENU) + + self.add(self.image) + self.add(self.label) + + def set_activatable(self): + pass + + def on_row_activated(self): + self.options.update_states() + self.parent.set_page(self.options, 'pref') + + def update(self): + pass + + class Account(Gtk.Box): def __init__(self, account, parent): Gtk.Box.__init__(self, orientation=Gtk.Orientation.HORIZONTAL, spacing=12) self.account = account if account == app.ZEROCONF_ACC_NAME: - self.options = ZeroConfPage(account) + self.options = ZeroConfPage(account, parent) else: - self.options = AccountPage(account) + self.options = AccountPage(account, parent) self.parent = parent
- switch = Gtk.Switch() - switch.set_active(app.config.get_per('accounts', account, 'active')) - switch.set_vexpand(False) - switch.set_valign(Gtk.Align.CENTER) - switch.set_halign(Gtk.Align.START) - if account == app.ZEROCONF_ACC_NAME and not app.HAVE_ZEROCONF: - switch.set_sensitive(False) - switch.set_active(False) - switch.connect('notify::active', self.on_switch, self.account) - account_label = app.config.get_per('accounts', account, 'account_label') self.label = Gtk.Label(label=account_label or account) self.label.set_halign(Gtk.Align.START) self.label.set_hexpand(True)
- self.add(switch) - self.add(self.label) + self.image = Gtk.Image() + self._update_image()
- if account != app.ZEROCONF_ACC_NAME: - button = get_image_button('list-remove-symbolic', _('Remove')) - button.connect('clicked', parent.on_remove_account, account) - self.add(button) + self.add(self.image) + self.add(self.label)
def set_activatable(self): if self.account == app.ZEROCONF_ACC_NAME: self.get_parent().set_activatable(app.HAVE_ZEROCONF) - - def on_switch(self, switch, param, account): - old_state = app.config.get_per('accounts', account, 'active') - state = switch.get_active() - if old_state == state: - return - - if (account in app.connections and - app.connections[account].connected > 0): - # connecting or connected - app.interface.raise_dialog('connected-on-disable-account') - switch.set_active(not state) - return - if state: - self.parent.enable_account(account) - else: - self.parent.disable_account(account) - app.config.set_per('accounts', account, 'active', state) + self.get_parent().set_sensitive(app.HAVE_ZEROCONF) + if not app.HAVE_ZEROCONF: + self.get_parent().set_tooltip_text( + _('Please check if Avahi or Bonjour is installed.'))
def on_row_activated(self): self.options.update_states() @@ -376,6 +398,12 @@ class Account(Gtk.Box): account_label = app.config.get_per( 'accounts', self.account, 'account_label') self.label.set_text(account_label or self.account) + self._update_image() + + def _update_image(self): + show = helpers.get_current_show(self.account) + icon = gtkgui_helpers.get_iconset_name_for(show) + self.image.set_from_icon_name(icon, Gtk.IconSize.MENU)
class GenericOptionPage(Gtk.Box): @@ -384,37 +412,37 @@ class GenericOptionPage(Gtk.Box): self.account = account self.parent = parent
- self.toggle = get_image_button('document-edit-symbolic', - _('Rename account label'), toggle=True) - self.toggle.connect('toggled', self.set_entry_text) - - self.entry = Gtk.Entry() - self.entry.set_sensitive(False) - self.entry.set_name('AccountNameEntry') - self.set_entry_text(self.toggle, update=True) - - box = Gtk.Box() - if isinstance(self, AccountPage): - box.pack_start(self.toggle, False, True, 0) - box.pack_start(self.entry, True, True, 0) + button = Gtk.Button.new_from_icon_name( + 'go-previous-symbolic', Gtk.IconSize.MENU) + button.set_halign(Gtk.Align.START) + button.connect('clicked', self._on_back_button) + if not isinstance(self, (AccountPage, PreferencesPage, ZeroConfPage)): + self.pack_start(button, False, True, 0)
self.listbox = OptionsBox(account) self.listbox.set_selection_mode(Gtk.SelectionMode.NONE) + self.listbox.set_vexpand(False) + self.listbox.set_valign(Gtk.Align.END)
for option in options: self.listbox.add_option(option) self.listbox.update_states()
- self.pack_start(box, False, False, 0) - self.pack_start(self.listbox, True, True, 0) + self.pack_end(self.listbox, True, True, 0)
self.listbox.connect('row-activated', self.on_row_activated)
+ def _on_back_button(self, *args): + account_window = self.get_toplevel() + child = account_window.stack.get_visible_child() + account_window.remove_all_pages() + account_window.stack.add_named(child.parent, 'account') + account_window.stack.set_visible_child_name('account') + def update_states(self): self.listbox.update_states()
def on_row_activated(self, listbox, row): - self.toggle.set_active(False) row.get_child().on_row_activated()
def set_entry_text(self, toggle, update=False): @@ -438,12 +466,70 @@ class GenericOptionPage(Gtk.Box): gui_menu_builder.build_accounts_menu()
def update(self): - self.set_entry_text(self.toggle, update=True) + pass
def set_page(self, options, name): options.update_states() self.get_toplevel().set_page(options, name)
+ def _add_top_buttons(self, parent): + # This adds the Account enable switch and the back button + box = Gtk.Box() + box.set_hexpand(True) + box.set_halign(Gtk.Align.FILL) + switch = Gtk.Switch() + switch.set_active(app.config.get_per('accounts', self.account, 'active')) + switch.set_vexpand(False) + switch.set_valign(Gtk.Align.CENTER) + switch.set_halign(Gtk.Align.END) + if self.account == app.ZEROCONF_ACC_NAME and not app.HAVE_ZEROCONF: + switch.set_sensitive(False) + switch.set_active(False) + + switch.connect('notify::active', self._on_enable_switch, self.account) + box.pack_start(switch, False, False, 0) + if self.account != app.ZEROCONF_ACC_NAME: + button = Gtk.Button(label=_('Remove')) + button.connect( + 'clicked', parent.on_remove_account, self.account) + button.get_style_context().add_class('destructive-action') + button.set_halign(Gtk.Align.END) + switch.set_vexpand(False) + box.pack_end(button, False, False, 0) + self.pack_start(box, True, True, 0) + + def _on_enable_switch(self, switch, param, account): + old_state = app.config.get_per('accounts', account, 'active') + state = switch.get_active() + if old_state == state: + return + + if (account in app.connections and + app.connections[account].connected > 0): + # connecting or connected + app.interface.raise_dialog('connected-on-disable-account') + switch.set_active(not state) + return + if state: + self.parent.enable_account(account) + else: + self.parent.disable_account(account) + app.config.set_per('accounts', account, 'active', state) + + +class PreferencesPage(GenericOptionPage): + def __init__(self): + + options = [ + Option(OptionKind.SWITCH, _('Merge Accounts'), + OptionType.ACTION, 'merge'), + + Option(OptionKind.SWITCH, _('Use PGP Agent'), + OptionType.ACTION, 'agent'), + ] + + GenericOptionPage.__init__(self, None, None, options) +
class AccountPage(GenericOptionPage): def __init__(self, account, parent=None): @@ -454,6 +540,10 @@ class AccountPage(GenericOptionPage): self.set_page, ConnectionPage(account, self), 'connection')
options = [ + Option(OptionKind.ENTRY, _('Label'), + OptionType.ACCOUNT_CONFIG, 'account_label', + callback=self._on_account_name_change), + Option(OptionKind.LOGIN, _('Login'), OptionType.DIALOG, props={'dialog': LoginDialog}),
@@ -477,6 +567,10 @@ class AccountPage(GenericOptionPage): ]
GenericOptionPage.__init__(self, account, parent, options) + self._add_top_buttons(parent) + + def _on_account_name_change(self, account_name, *args): + self.parent.update_accounts()
class GeneralPage(GenericOptionPage): @@ -572,6 +666,7 @@ class ZeroConfPage(GenericOptionPage): ]
GenericOptionPage.__init__(self, account, parent, options) + self._add_top_buttons(None)
class ZeroconfProfileDialog(OptionsDialog):
===================================== gajim/common/helpers.py ===================================== --- a/gajim/common/helpers.py +++ b/gajim/common/helpers.py @@ -1244,6 +1244,11 @@ def get_accounts_info(): 'show': status, 'message': message}) return accounts
+def get_current_show(account): + if account not in app.connections: + return 'offline' + status = app.connections[account].connected + return app.SHOW_LIST[status]
def get_iconset_path(iconset): if os.path.isdir(os.path.join(app.DATA_DIR, 'iconsets', iconset)):
===================================== gajim/config.py ===================================== --- a/gajim/config.py +++ b/gajim/config.py @@ -2750,6 +2750,7 @@ class AccountCreationWizardWindow: def get_config(self, login, server, savepass, password, anonymous=False): config = {} config['name'] = login + config['account_label'] = '%s@%s' % (login, server) config['hostname'] = server config['savepass'] = savepass config['password'] = password
===================================== gajim/data/gui/accounts_window.ui ===================================== --- a/gajim/data/gui/accounts_window.ui +++ b/gajim/data/gui/accounts_window.ui @@ -1,67 +1,54 @@ <?xml version="1.0" encoding="UTF-8"?> -<!-- Generated with glade 3.20.0 --> +<!-- Generated with glade 3.21.0 --> <interface> <requires lib="gtk+" version="3.18"/> <object class="GtkBox" id="box"> <property name="visible">True</property> <property name="can_focus">False</property> - <property name="orientation">vertical</property> <child> - <object class="GtkStack" id="stack"> + <object class="GtkBox"> <property name="visible">True</property> <property name="can_focus">False</property> - <signal name="notify::visible-child-name" handler="on_child_visible" swapped="no"/> + <property name="halign">start</property> + <property name="orientation">vertical</property> + <child> + <placeholder/> + </child> <child> - <object class="GtkBox" id="account_page"> + <object class="GtkScrolledWindow"> <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="orientation">vertical</property> + <property name="can_focus">True</property> + <property name="halign">start</property> + <property name="hscrollbar_policy">never</property> + <property name="shadow_type">in</property> + <property name="max_content_height">400</property> + <property name="propagate_natural_height">True</property> <child> - <object class="GtkScrolledWindow"> + <object class="GtkViewport"> <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="hscrollbar_policy">never</property> - <property name="shadow_type">in</property> - <property name="max_content_height">400</property> - <property name="propagate_natural_height">True</property> + <property name="can_focus">False</property> <child> - <object class="GtkViewport"> + <object class="GtkListBox" id="account_list"> + <property name="name">OptionsBox1</property> + <property name="width_request">170</property> <property name="visible">True</property> <property name="can_focus">False</property> - <child> - <object class="GtkListBox" id="account_list"> - <property name="name">OptionsBox</property> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="selection_mode">none</property> - <signal name="row-activated" handler="on_row_activated" swapped="no"/> - </object> - </child> + <property name="halign">start</property> + <property name="hexpand">False</property> + <property name="vexpand">True</property> + <signal name="row-activated" handler="on_row_activated" swapped="no"/> + <style> + <class name="account-list"/> + </style> </object> </child> </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">0</property> - </packing> - </child> - <child> - <object class="GtkActionBar" id="actionbar"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="vexpand">False</property> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">1</property> - </packing> </child> </object> <packing> - <property name="name">main</property> - <property name="title">page0</property> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">1</property> </packing> </child> </object> @@ -71,42 +58,21 @@ <property name="position">0</property> </packing> </child> - </object> - <object class="GtkHeaderBar" id="headerbar"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="title" translatable="yes">Accounts</property> - <property name="show_close_button">True</property> - <property name="decoration_layout">:close</property> - <child> - <object class="GtkButton" id="back_button"> - <property name="can_focus">True</property> - <property name="receives_default">True</property> - <property name="no_show_all">True</property> - <signal name="clicked" handler="on_back_button" swapped="no"/> - <child> - <object class="GtkImage"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="icon_name">go-previous-symbolic</property> - </object> - </child> - </object> - </child> <child> - <object class="GtkMenuButton" id="menu_button"> + <object class="GtkStack" id="stack"> <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">True</property> + <property name="can_focus">False</property> + <property name="valign">start</property> + <property name="hhomogeneous">False</property> + <property name="vhomogeneous">False</property> + <signal name="notify::visible-child-name" handler="on_child_visible" swapped="no"/> <child> - <object class="GtkImage"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="icon_name">open-menu-symbolic</property> - </object> + <placeholder/> </child> </object> <packing> + <property name="expand">True</property> + <property name="fill">True</property> <property name="position">1</property> </packing> </child>
===================================== gajim/data/style/gajim.css ===================================== --- a/gajim/data/style/gajim.css +++ b/gajim/data/style/gajim.css @@ -75,16 +75,13 @@ popover#EmoticonPopover flowboxchild { padding-top: 5px; padding-bottom: 5px; } .PopoverButtonListbox > list > row.activatable:active { box-shadow: none; background-color: @theme_selected_bg_color }
/* Accounts Window */ -#AccountsWindow > box { padding:30px 30px 30px 30px;} +#AccountsWindow > box > stack { padding:30px 30px 30px 30px;} #AccountsWindow scrolledwindow {border: none;} -#AccountsWindow list {border: 1px solid; border-color: @borders;} -#AccountsWindow > box actionbar box {border: none;} - -#AccountNameEntry:disabled { font-size: 16px; - font-weight: bold; - border: none; - background-color: @theme_unfocused_bg_color; - color: @theme_text_color; } +#AccountsWindow stack list {border: 1px solid; border-color: @borders;} + +#AccountsWindow > box > box { border-right: 1px solid; border-color: @borders; } + +.account-list > row { padding: 20px 20px 20px 10px; }
/* StartChatListBox */ #StartChatListBox > row { border-bottom: 1px solid; border-color: @theme_unfocused_bg_color; }
===================================== gajim/options_dialog.py ===================================== --- a/gajim/options_dialog.py +++ b/gajim/options_dialog.py @@ -239,7 +239,12 @@ class SwitchOption(GenericOption): GenericOption.__init__(self, *args)
self.switch = Gtk.Switch() - self.switch.set_active(self.option_value) + if self.type_ == OptionType.ACTION: + self.switch.set_action_name('app.%s' % self.option_value) + state = app.app.get_action_state(self.option_value) + self.switch.set_active(state.get_boolean()) + else: + self.switch.set_active(self.option_value) self.switch.connect('notify::active', self.on_switch) self.switch.set_hexpand(True) self.switch.set_halign(Gtk.Align.END) @@ -271,6 +276,7 @@ class EntryOption(GenericOption): self.entry.set_text(str(self.option_value)) self.entry.connect('notify::text', self.on_text_change) self.entry.set_valign(Gtk.Align.CENTER) + self.entry.set_alignment(1)
if self.value == 'password': self.entry.set_invisible_char('*')
View it on GitLab: https://dev.gajim.org/gajim/gajim/compare/e93ab408ec9da69da767bbea52383045e8...
--- View it on GitLab: https://dev.gajim.org/gajim/gajim/compare/e93ab408ec9da69da767bbea52383045e8... You're receiving this email because of your account on dev.gajim.org.