Commit 5ed83e04 authored by Bilal Elmoussaoui's avatar Bilal Elmoussaoui

ui improvements and fix #5

parent cc3d46e9
......@@ -12,13 +12,17 @@ import signal
from gettext import gettext as _
from os import environ as env
class Application(Gtk.Application):
win = None
alive = True
locked = False
menu = Gio.Menu()
auth = Authenticator()
use_GMenu = None
use_GMenu = True
settings_window = None
settings_action = None
def __init__(self, *args, **kwargs):
for key in kwargs:
......@@ -61,25 +65,28 @@ class Application(Gtk.Application):
logging.debug("Adding gnome shell menu")
def generate_menu(self):
pass_enabled = self.cfg.read("state", "login")
if pass_enabled:
if self.locked:
self.menu.append(_("Unlock the Application"), "app.lock")
else:
self.menu.append(_("Lock the Application"), "app.lock")
# Settings section
settings_content = Gio.Menu.new()
settings_content.append_item(Gio.MenuItem.new(_("Settings"), "app.settings"))
settings_section = Gio.MenuItem.new_section(None, settings_content)
self.menu.append_item(settings_section)
# Help section
help_content = Gio.Menu.new()
if Gtk.get_major_version() >= 3 and Gtk.get_minor_version() >= 20:
help_content.append_item(Gio.MenuItem.new(_("Shortcuts"), "app.shortcuts"))
if not self.locked:
self.menu.append(_("Settings"), "app.settings")
help_content.append_item(Gio.MenuItem.new(_("About"), "app.about"))
help_content.append_item(Gio.MenuItem.new(_("Quit"), "app.quit"))
help_section = Gio.MenuItem.new_section(None, help_content)
self.menu.append_item(help_section)
if Gtk.get_major_version() >= 3 and Gtk.get_minor_version() >= 20:
self.menu.append(_("Shortcuts"), "app.shortcuts")
self.menu.append(_("About"), "app.about")
self.menu.append(_("Quit"), "app.quit")
self.set_app_menu(self.menu)
action = Gio.SimpleAction.new("settings", None)
action.connect("activate", self.on_settings)
self.add_action(action)
self.settings_action = Gio.SimpleAction.new("settings", None)
self.settings_action.connect("activate", self.on_settings)
self.settings_action.set_enabled(not self.locked)
self.add_action(self.settings_action)
if Gtk.get_major_version() >= 3 and Gtk.get_minor_version() >= 20:
action = Gio.SimpleAction.new("shortcuts", None)
......@@ -90,10 +97,6 @@ class Application(Gtk.Application):
action.connect("activate", self.on_about)
self.add_action(action)
action = Gio.SimpleAction.new("lock", None)
action.connect("activate", self.on_toggle_lock)
self.add_action(action)
action = Gio.SimpleAction.new("quit", None)
action.connect("activate", self.on_quit)
self.add_action(action)
......@@ -103,29 +106,9 @@ class Application(Gtk.Application):
self.win.show_all()
self.add_window(self.win)
def toggle_settings_menu(self):
if self.locked:
self.menu.remove(1)
else:
self.menu.insert(1, _("Settings"), "app.settings")
def refresh_menu(self):
if self.use_GMenu:
self.menu.remove_all()
shortcuts_enabled = Gtk.get_major_version() >= 3 and Gtk.get_minor_version() >= 20
pass_enabled = self.cfg.read("state", "login")
can_be_locked = not self.app.locked and pass_enabled
if can_be_locked:
self.menu.append(_("Lock the Application"), "app.lock")
if shortcuts_enabled:
self.menu.append(_("Shortcuts"), "app.shortcuts")
if not self.locked:
self.menu.insert(1, _("Settings"), "app.settings")
self.menu.append(_("About"), "app.about")
self.menu.append(_("Quit"), "app.quit")
self.settings_action.set_enabled(not self.settings_action.get_enabled())
def on_toggle_lock(self, *args):
if not self.locked:
......@@ -144,7 +127,10 @@ class Application(Gtk.Application):
"""
Shows settings window
"""
SettingsWindow(self.win)
if not self.settings_window:
self.settings_window = SettingsWindow(self.win)
else:
self.settings_window.show()
def on_quit(self, *args):
"""
......
......@@ -18,6 +18,8 @@ class AddAuthenticator(Gtk.Window):
secret_code = Gtk.Entry()
name_entry = Gtk.Entry()
logo_finder_window = None
def __init__(self, window):
self.parent = window
self.generate_window()
......@@ -42,7 +44,7 @@ class AddAuthenticator(Gtk.Window):
Keyboard Listener handler
"""
if Gdk.keyval_name(key_event.keyval) == "Escape":
self.destroy()
self.close_window()
def update_logo(self, image):
"""
......@@ -179,7 +181,10 @@ class AddAuthenticator(Gtk.Window):
Shows icon finder window
select icon by icon name
"""
IconFinderWindow(self)
if not self.logo_finder_window:
self.logo_finder_window = IconFinderWindow(self)
else:
self.logo_finder_window.show()
def add_filters(self, dialog):
"""
......
......@@ -152,4 +152,5 @@ class PasswordWindow(Gtk.Window):
"""
Close the window
"""
self.destroy()
self.hide()
return True
......@@ -28,6 +28,14 @@ class IconFinderWindow(Gtk.Window):
self.set_position(Gtk.WindowPosition.CENTER)
self.set_resizable(False)
self.set_transient_for(self.parent)
self.connect("key_press_event", self.on_key_press)
def on_key_press(self, key, key_event):
"""
Keyboard Listener handler
"""
if Gdk.keyval_name(key_event.keyval) == "Escape":
self.close_window()
def generate_components(self):
"""
......@@ -100,4 +108,5 @@ class IconFinderWindow(Gtk.Window):
"""
Close the window
"""
self.destroy()
self.hide()
return True
from gi import require_version
require_version("Gtk", "3.0")
from gi.repository import Gtk
from gi.repository import Gtk, Gdk
from TwoFactorAuth.models.settings import SettingsReader
from TwoFactorAuth.widgets.change_password import PasswordWindow
from gettext import gettext as _
......@@ -9,9 +9,13 @@ from gettext import gettext as _
class SettingsWindow(Gtk.Window):
notebook = Gtk.Notebook()
time_spin_button = Gtk.SpinButton()
auto_lock_time = Gtk.SpinButton()
enable_switch = Gtk.Switch()
auto_lock_switch = Gtk.Switch()
password_button = Gtk.Button()
password_window = None
def __init__(self, parent):
self.parent = parent
self.cfg = SettingsReader()
......@@ -20,14 +24,22 @@ class SettingsWindow(Gtk.Window):
self.show_all()
def generate_window(self):
Gtk.Window.__init__(self, title=_("Settings"), modal=True,
Gtk.Window.__init__(self, title=_("Settings"),
destroy_with_parent=True)
self.connect("delete-event", self.close_window)
self.resize(300, 300)
self.set_size_request(300, 300)
self.resize(400, 300)
self.set_size_request(400, 300)
self.set_resizable(False)
self.set_position(Gtk.WindowPosition.CENTER)
self.set_transient_for(self.parent)
self.connect("key_press_event", self.on_key_press)
def on_key_press(self, key, key_event):
"""
Keyboard Listener handler
"""
if Gdk.keyval_name(key_event.keyval) == "Escape":
self.close_window()
def generate_components(self):
"""
......@@ -91,21 +103,53 @@ class SettingsWindow(Gtk.Window):
time_box.pack_start(time_label, False, True, 0)
time_box.pack_end(self.time_spin_button, False, True, 0)
is_auto_lock_active = bool(self.cfg.read("auto-lock", "preferences"))
auto_lock_box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL)
auto_lock_label = Gtk.Label(_("Auto-lock the Application"))
self.auto_lock_switch.set_active(is_auto_lock_active)
self.auto_lock_switch.connect("notify::active", self.on_auto_lock_activated)
auto_lock_box.pack_start(auto_lock_label, False, True, 0)
auto_lock_box.pack_end(self.auto_lock_switch, False, True, 0)
auto_lock_time_box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL)
auto_lock_time_label = Gtk.Label(_("Auto-lock time (m): "))
default_value = self.cfg.read("auto-lock-time", "preferences")
if default_value < 1 or default_value > 10:
default_value = 3
adjustment = Gtk.Adjustment(default_value, 1, 10, 1, 1, 0)
self.auto_lock_time.connect("value-changed", self.on_auto_lock_time_changed)
self.auto_lock_time.set_adjustment(adjustment)
self.auto_lock_time.set_sensitive(is_auto_lock_active)
self.auto_lock_time.set_value(default_value)
auto_lock_time_box.pack_start(auto_lock_time_label, False, True, 0)
auto_lock_time_box.pack_end(self.auto_lock_time, False, True, 0)
main_box.pack_start(time_box, False, True, 6)
main_box.pack_start(auto_lock_box, False, True, 6)
main_box.pack_start(auto_lock_time_box, False, True, 6)
return main_box
def new_password_window(self, *args):
"""
Show a new password window
"""
PasswordWindow(self)
if not self.password_window:
self.password_window = PasswordWindow(self)
else:
self.password_window.show()
def on_time_changed(self, spin_button):
"""
Update time tog generate a new secret code
"""
self.cfg.update("refresh-time", spin_button.get_value_as_int(),
"preferences")
self.cfg.update("refresh-time", spin_button.get_value_as_int(), "preferences")
def on_auto_lock_time_changed(self, spin_button):
"""
Update time tog generate a new secret code
"""
self.cfg.update("auto-lock-time", spin_button.get_value_as_int(), "preferences")
def on_switch_activated(self, switch, *args):
"""
......@@ -113,11 +157,19 @@ class SettingsWindow(Gtk.Window):
"""
self.password_button.set_sensitive(switch.get_active())
self.cfg.update("state", switch.get_active(), "login")
self.parent.app.refresh_menu()
self.parent.refresh_menu_popover()
self.parent.refresh_window()
def on_auto_lock_activated(self, switch, *args):
"""
Update auto-lock state : enabled/disabled
"""
self.auto_lock_time.set_sensitive(switch.get_active())
self.cfg.update("auto-lock", switch.get_active(), "preferences")
def close_window(self, *args):
"""
Close the window
"""
self.destroy()
\ No newline at end of file
self.hide()
return True
\ No newline at end of file
from gi import require_version
require_version("Gtk", "3.0")
from gi.repository import Gtk, Gio, Gdk
from gi.repository import Gtk, Gio, Gdk, GObject
from TwoFactorAuth.widgets.add_authenticator import AddAuthenticator
from TwoFactorAuth.widgets.confirmation import ConfirmationMessage
from TwoFactorAuth.widgets.listrow import ListBoxRow
......@@ -13,6 +13,7 @@ class Window(Gtk.ApplicationWindow):
app = None
selected_app_idx = None
selected_count = 0
counter = 0
hb = Gtk.HeaderBar()
main_box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
......@@ -29,12 +30,11 @@ class Window(Gtk.ApplicationWindow):
remove_button = Gtk.Button()
cancel_button = Gtk.Button()
select_button = Gtk.Button()
lock_button = Gtk.Button()
popover = Gtk.PopoverMenu().new()
pop_unlock = Gtk.ModelButton.new()
settings_box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL)
unlock_box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL)
pop_settings = Gtk.ModelButton.new()
password_entry = Gtk.Entry()
search_entry = Gtk.Entry()
......@@ -47,6 +47,7 @@ class Window(Gtk.ApplicationWindow):
self.generate_no_apps_box()
self.generate_login_form()
self.refresh_window()
GObject.timeout_add_seconds(60, self.refresh_counter)
def generate_window(self, *args):
"""
......@@ -99,10 +100,25 @@ class Window(Gtk.ApplicationWindow):
elif keypress == "escape":
if self.search_box.get_visible():
self.toggle_search_box()
if not self.select_button.get_visible():
self.toggle_select()
else:
if keypress == "return":
self.on_unlock_clicked()
def refresh_counter(self):
"""
Add a value to the counter each 60 seconds
"""
print(self.counter)
if not self.app.locked:
self.counter += 1
if self.app.cfg.read("auto-lock", "preferences"):
if self.counter == self.app.cfg.read("auto-lock-time", "preferences") - 1:
self.counter = 0
self.toggle_app_lock()
return True
def filter_applications(self, entry):
data = entry.get_text().strip()
if len(data) != 0:
......@@ -174,11 +190,7 @@ class Window(Gtk.ApplicationWindow):
if password == self.app.cfg.read("password", "login"):
self.password_entry.set_icon_from_icon_name(Gtk.EntryIconPosition.SECONDARY, None)
self.toggle_app_lock()
self.app.locked = False
self.app.toggle_settings_menu()
self.password_entry.set_text("")
self.app.refresh_menu()
else:
self.password_entry.set_icon_from_icon_name(Gtk.EntryIconPosition.SECONDARY, "dialog-error-symbolic")
......@@ -209,7 +221,7 @@ class Window(Gtk.ApplicationWindow):
"""
Hide all buttons on the header bar
"""
self.toggle_hb_buttons(False, False, False, False, False, False)
self.toggle_hb_buttons(False, False, False, False, False, False, False)
def generate_header_bar(self):
"""
......@@ -254,9 +266,21 @@ class Window(Gtk.ApplicationWindow):
self.cancel_button.set_label(_("Cancel"))
self.cancel_button.connect("clicked", self.toggle_select)
self.cancel_button.set_no_show_all(True)
pass_enabled = self.app.cfg.read("state", "login")
can_be_locked = not self.app.locked and pass_enabled
lock_icon = Gio.ThemedIcon(name="changes-prevent-symbolic")
lock_image = Gtk.Image.new_from_gicon(lock_icon, Gtk.IconSize.BUTTON)
self.lock_button.set_tooltip_text(_("Lock the Application"))
self.lock_button.set_image(lock_image)
self.lock_button.connect("clicked", self.app.on_toggle_lock)
self.lock_button.set_no_show_all(not can_be_locked)
self.lock_button.set_visible(can_be_locked)
right_box.add(self.search_button)
right_box.add(self.select_button)
right_box.add(self.cancel_button)
right_box.add(self.lock_button)
if not self.app.use_GMenu:
self.generate_popover(right_box)
......@@ -281,32 +305,16 @@ class Window(Gtk.ApplicationWindow):
self.popover.add(popover_box)
shortcuts_enabled = Gtk.get_major_version() >= 3 and Gtk.get_minor_version() >= 20
pass_enabled = self.app.cfg.read("state", "login")
unlock_section_box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
self.pop_unlock.connect("clicked", self.app.on_toggle_lock)
self.pop_unlock.get_style_context().add_class("flat")
self.pop_unlock.set_label(_("Lock the Application"))
unlock_section_box.pack_start(self.pop_unlock, False, False, 0)
unlock_section_box.pack_start(Gtk.Separator(), False, False, 0)
can_be_locked = not self.app.locked and pass_enabled
self.unlock_box.set_no_show_all(not can_be_locked)
self.unlock_box.set_visible(can_be_locked)
self.unlock_box.pack_start(unlock_section_box, True, True, 0)
popover_box.pack_start(self.unlock_box, True, True, 0)
settings = Gtk.ModelButton.new()
settings.set_label(_("Settings"))
settings.get_style_context().add_class("flat")
settings.connect("clicked", self.app.on_settings)
self.pop_settings.set_label(_("Settings"))
self.pop_settings.get_style_context().add_class("flat")
self.pop_settings.connect("clicked", self.app.on_settings)
self.pop_settings.set_sensitive(not self.app.locked)
settings_section_box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
settings_section_box.pack_start(settings, False, False, 0)
settings_section_box.pack_start(self.pop_settings, False, False, 0)
settings_section_box.pack_start(Gtk.Separator(), False, False, 0)
self.settings_box.set_visible(not self.app.locked)
self.settings_box.set_no_show_all(self.app.locked)
self.settings_box.pack_start(settings_section_box, True, True, 0)
popover_box.pack_start(self.settings_box, True, True, 0)
......@@ -332,17 +340,6 @@ class Window(Gtk.ApplicationWindow):
box.add(self.settings_button)
def refresh_menu_popover(self):
if not self.app.use_GMenu:
pass_enabled = self.app.cfg.read("state", "login")
can_be_locked = not self.app.locked and pass_enabled
self.settings_box.set_visible(not self.app.locked)
self.unlock_box.set_visible(can_be_locked)
self.unlock_box.set_no_show_all(not can_be_locked)
self.settings_box.set_no_show_all(self.app.locked)
self.unlock_box.show_all()
self.settings_box.show_all()
def toggle_popover(self, *args):
if self.popover:
if self.popover.get_visible():
......@@ -385,6 +382,9 @@ class Window(Gtk.ApplicationWindow):
self.remove_button.set_visible(not is_visible)
if not self.app.use_GMenu:
self.settings_button.set_visible(is_visible)
pass_enabled = self.app.cfg.read("state", "login")
self.lock_button.set_visible( is_visible and pass_enabled)
self.add_button.set_visible(is_visible)
self.select_button.set_visible(is_visible)
......@@ -540,30 +540,33 @@ class Window(Gtk.ApplicationWindow):
"""
count = self.app.auth.count()
is_locked = self.app.locked
pass_enabled = self.app.cfg.read("state", "login")
can_be_locked = not is_locked and pass_enabled
if is_locked:
self.toggle_boxes(False, False, True)
self.hide_header_bar()
else:
if count == 0:
self.toggle_boxes(False, True, False)
self.toggle_hb_buttons(False, True, False, False, False, True)
self.toggle_hb_buttons(False, True, False, False, False, True, can_be_locked)
else:
self.toggle_boxes(True, False, False)
self.toggle_hb_buttons(False, True, True, True, False, True)
self.toggle_hb_buttons(False, True, True, True, False, True, can_be_locked)
self.pop_settings.set_sensitive(not is_locked)
self.main_box.show_all()
self.refresh_menu_popover()
self.list_box.set_selection_mode(Gtk.SelectionMode.SINGLE)
def toggle_hb_buttons(self, remove, add, search, select, cancel, settings):
def toggle_hb_buttons(self, remove, add, search, select, cancel, settings, lock):
"""
Toggle header bar buttons visibilty
Toggle header bar buttons visibility
:param remove: (bool)
:param add: (bool)
:param search: (bool)
:param select: (bool)
:param cancel: (bool)
:param settings: (bool)
:param lock: (bool)
"""
self.add_button.set_visible(add)
self.add_button.set_no_show_all(not add)
......@@ -575,6 +578,8 @@ class Window(Gtk.ApplicationWindow):
self.select_button.set_no_show_all(not select)
self.search_button.set_visible(search)
self.search_button.set_no_show_all(not search)
self.lock_button.set_visible(lock)
self.lock_button.set_no_show_all(not lock)
if not self.app.use_GMenu:
self.search_button.set_visible(settings)
self.search_button.set_no_show_all(not settings)
......
......@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2016-05-30 18:00+0200\n"
"POT-Creation-Date: 2016-05-31 17:36+0200\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
......@@ -68,48 +68,69 @@ msgid ""
"later</a> for details."
msgstr ""
#: TwoFactorAuth/widgets/window.py:129
#: TwoFactorAuth/widgets/window.py:151
msgid "Do you really want to remove selected applications?"
msgstr ""
#: TwoFactorAuth/widgets/window.py:150
#: TwoFactorAuth/widgets/window.py:172
msgid "Enter your password"
msgstr ""
#: TwoFactorAuth/widgets/window.py:154
#: TwoFactorAuth/widgets/window.py:176
msgid "Unlock"
msgstr ""
#: TwoFactorAuth/widgets/window.py:218
#: TwoFactorAuth/widgets/window.py:237
msgid "Remove selected two factor auth sources"
msgstr ""
#: TwoFactorAuth/widgets/window.py:226
#: TwoFactorAuth/widgets/add_authenticator.py:28
#: TwoFactorAuth/widgets/window.py:245
#: TwoFactorAuth/widgets/add_authenticator.py:31
msgid "Add a new application"
msgstr ""
#: TwoFactorAuth/widgets/window.py:235
#: TwoFactorAuth/widgets/window.py:254
msgid "Select mode"
msgstr ""
#: TwoFactorAuth/widgets/window.py:242
#: TwoFactorAuth/widgets/window.py:261
msgid "Search"
msgstr ""
#: TwoFactorAuth/widgets/window.py:247
#: TwoFactorAuth/widgets/window.py:266
#: TwoFactorAuth/widgets/change_password.py:137
#: TwoFactorAuth/widgets/icon_finder.py:85
#: TwoFactorAuth/widgets/icon_finder.py:93
#: TwoFactorAuth/widgets/authenticator_logo.py:139
#: TwoFactorAuth/widgets/add_authenticator.py:204
#: TwoFactorAuth/widgets/add_authenticator.py:210
msgid "Cancel"
msgstr ""
#: TwoFactorAuth/widgets/window.py:399
#: TwoFactorAuth/widgets/window.py:274
msgid "Lock the Application"
msgstr ""
#: TwoFactorAuth/widgets/window.py:295 TwoFactorAuth/widgets/window.py:309
#: TwoFactorAuth/widgets/settings.py:27 TwoFactorAuth/application.py:70
msgid "Settings"
msgstr ""
#: TwoFactorAuth/widgets/window.py:323 TwoFactorAuth/application.py:77
msgid "Shortcuts"
msgstr ""
#: TwoFactorAuth/widgets/window.py:331 TwoFactorAuth/application.py:79
msgid "About"
msgstr ""
#: TwoFactorAuth/widgets/window.py:336 TwoFactorAuth/application.py:80
msgid "Quit"
msgstr ""
#: TwoFactorAuth/widgets/window.py:500
msgid "There's no application at the moment"
msgstr ""
#: TwoFactorAuth/widgets/window.py:484
#: TwoFactorAuth/widgets/window.py:595
msgid "Do you really want to remove the application?"
msgstr ""
......@@ -137,94 +158,74 @@ msgstr ""
msgid "Choose"
msgstr ""
#: TwoFactorAuth/widgets/settings.py:23 TwoFactorAuth/application.py:62
#: TwoFactorAuth/application.py:102 TwoFactorAuth/application.py:119
msgid "Settings"
msgstr ""
#: TwoFactorAuth/widgets/settings.py:39
#: TwoFactorAuth/widgets/settings.py:51
msgid "Preferences"
msgstr ""
#: TwoFactorAuth/widgets/settings.py:43
#: TwoFactorAuth/widgets/settings.py:55
msgid "Account"
msgstr ""
#: TwoFactorAuth/widgets/settings.py:53
#: TwoFactorAuth/widgets/settings.py:65
msgid "Enable password: "
msgstr ""
#: TwoFactorAuth/widgets/settings.py:61
#: TwoFactorAuth/widgets/settings.py:73
msgid "Password: "