implement autotools

This commit is contained in:
Bilal Elmoussaoui 2016-05-27 03:27:28 +02:00
parent bf3a4d95ac
commit 15b9fe44b1
23 changed files with 431 additions and 278 deletions

View file

@ -1,6 +0,0 @@
[default]
name=Configuration par défaut
device=local
runtime=xdg-app:org.gnome.Platform/3.20/x86_64
prefix=/app
default=true

View file

@ -1,4 +1,2 @@
SUBDIRS = src \
data \
plugins
data

View file

@ -1,18 +0,0 @@
import sqlite3
conn = sqlite3.connect('example.db')
c = conn.cursor()
# Create table
c.execute('''CREATE TABLE providers
(date text, trans text, symbol text, qty real, price real)''')
# Insert a row of data
c.execute("INSERT INTO stocks VALUES ('2006-01-05','BUY','RHAT',100,35.14)")
# Save (commit) the changes
conn.commit()
# We can also close the connection if we are done with it.
# Just be sure any changes have been committed or they will be lost.
conn.close()

View file

@ -1,15 +1,26 @@
desktopdir = $(DATADIR)/applications
desktop_DATA = two-factor.desktop
desktop_DATA = twofactorauth.desktop
UPDATE_DESKTOP = update-desktop-database $(datadir)/applications || :
uidir = $(pkgdatadir)/data
ui_DATA = about.glade
ui_DATA = about.glade \
shortcuts.glade \
menu.glade \
style.css
logodir = $(pkgdatadir)/data
logo_DATA = about.glade \
shortcuts.glade \
menu.glade \
style.css
appdatadir = $(DATADIR)/appdata
appdata_DATA = \
two-factor.appdata.xml
EXTRA_DIST = \
$(logo_DATA) \
$(ui_DATA) \
$(appdata_DATA)

View file

@ -25,7 +25,13 @@
<property name="accelerator">&lt;Primary&gt;C</property>
</object>
</child>
<child>
<object class="GtkShortcutsShortcut">
<property name="visible">True</property>
<property name="title" translatable="yes" context="shortcut window">Add a new provider</property>
<property name="accelerator">&lt;Primary&gt;N</property>
</object>
</child>
<child>
<object class="GtkShortcutsShortcut">
<property name="visible">True</property>

View file

@ -2,7 +2,7 @@
background-color: @theme_bg_color;
}
.application-list-row:selected * {
.application-list-row:selected GtkImage {
color: @theme_fg_selected_color;
}
@ -12,13 +12,13 @@
}
.provider-logo-add {
margin-left: 15px;
margin-bottom: 15px;
margin-right: 5px;
margin-bottom: 10px;
}
.application-secret-code {
font-size: 10px;
margin-top: 0;
margin-bottom: 5px;
margin-left: 70px;
margin-left: 65px;
}

View file

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<application>
<id type="desktop">two-factor.desktop</id>
<id type="desktop">twofactorauth.desktop</id>
<licence>CC0</licence>
<name>Two-factor Auth</name>
<summary>Two Factor Authentication code generator</summary>

Binary file not shown.

View file

@ -1,14 +1,14 @@
SUBDIRS = unitsconverter
SUBDIRS = twofactorauth
bin_SCRIPTS = units-converter
bin_SCRIPTS = twofactorauth
CLEANFILES = $(bin_SCRIPTS)
EXTRA_DIST = unit-converter.in
EXTRA_DIST = twofactorauth.in
do_substitution = sed -e 's,[@]pythondir[@],$(pythondir),g' \
-e 's,[@]pkgdatadir[@],$(pkgdatadir),g' \
-e 's,[@]PACKAGE[@],$(PACKAGE),g' \
-e 's,[@]VERSION[@],$(VERSION),g'
-e 's,[@]VERSION[@],$(VERSION),g'
units-converter: units-converter.in Makefile
$(do_substitution) < $(srcdir)/units-converter.in > units-converter
chmod +x units-converter
units-converter: twofactorauth.in Makefile
$(do_substitution) < $(srcdir)/twofactorauth.in > twofactorauth
chmod +x twofactorauth

View file

@ -20,10 +20,10 @@
"""
import sys
sys.path.insert(1, '@pythondir@')
from twofactor import application
from twofactorauth import application
if __name__ == "__main__":
app = application.UnitsConverter(package="@PACKAGE@",
app = application.TwoFactor(package="@PACKAGE@",
version="@VERSION@",
pkgdatadir="@pkgdatadir@")
app.run(None)

View file

@ -0,0 +1,8 @@
SUBDIRS = models \
ui
app_PYTHON = \
application.py \
__init__.py
appdir = $(pythondir)/TwoFactorAuth

View file

View file

@ -1,6 +1,6 @@
from gi import require_version
require_version("Gtk", "3.0")
from gi.repository import Gtk, GLib, Gio, Gdk
from gi.repository import Gtk, GLib, Gio, Gdk, GObject
from ui.window import TwoFactorWindow
import logging
from models.provider import Provider
@ -9,19 +9,19 @@ logging.basicConfig(level=logging.DEBUG,
format='[%(levelname)s] %(message)s',
)
# TODO : https://pypi.python.org/pypi/pyotp
class TwoFactor(Gtk.Application):
win = None
def __init__(self):
def __init__(self, *args, **kwargs):
for key in kwargs:
setattr(self, key, kwargs[key])
Gtk.Application.__init__(self,
application_id='org.gnome.twofactor',
application_id='org.gnome.twofactorauth',
flags=Gio.ApplicationFlags.FLAGS_NONE)
GLib.set_application_name("Two-factor")
GLib.set_prgname('twofactor')
GLib.set_application_name("Two-Factor Auth")
GLib.set_prgname('two_factor_auth')
GObject.threads_init()
provider = Gtk.CssProvider()
css_file = "/home/bilal/Projects/Two-factor-gtk/data/style.css"
try:
@ -29,10 +29,10 @@ class TwoFactor(Gtk.Application):
Gtk.StyleContext.add_provider_for_screen(Gdk.Screen.get_default(),
provider,
Gtk.STYLE_PROVIDER_PRIORITY_USER)
logging.debug("[CSS]: Loading css file %s" % css_file)
logging.debug("Loading css file %s" % css_file)
except Exception as e:
logging.debug("[CSS]: File not found %s" % css_file)
logging.debug("[CSS]: Error message %s" % str(e))
logging.debug("File not found %s" % css_file)
logging.debug("Error message %s" % str(e))
def do_startup(self):
Gtk.Application.do_startup(self)
@ -60,6 +60,7 @@ class TwoFactor(Gtk.Application):
TwoFactorWindow(self)
self.win.show()
self.add_window(self.win)
self.get_active_window().present()
def on_shortcuts(self, *args):
logging.debug("Shortcuts window")
@ -70,11 +71,12 @@ class TwoFactor(Gtk.Application):
self.win.show_about()
def on_quit(self, *args):
Gtk.main_quit()
self.win.destroy()
# Clear the clipboard once the application is closed, for safety resasons
try:
clipboard = Gtk.Clipboard.get(Gdk.SELECTION_CLIPBOARD)
clipboard.clear()
except Exception as e:
logging.error(str(e))
for win in self.get_windows():
win.destroy()
self.quit()
app = TwoFactor()
app.run(None)

View file

@ -0,0 +1,5 @@
app_PYTHON = \
code.py \
provider.py
appdir = $(pythondir)/TwoFactorAuth/models

View file

@ -0,0 +1,34 @@
from pyotp import TOTP
import logging
logging.basicConfig(level=logging.DEBUG,
format='[%(levelname)s] %(message)s',
)
class Code:
password = None
label = None
def __init__(self, secret_code):
self.secret_code = secret_code
self.create()
def create(self):
try:
self.totp = TOTP(self.secret_code)
self.password = self.totp.now()
except Exception as e:
logging.error("Canno't generate a two-factor auth code")
logging.error(str(e))
def update(self):
self.password = self.totp.now()
def get_secret_code(self):
try:
if self.password:
return self.password
else:
raise AttributeError
except AttributeError as e:
logging.error("Couldn't generate the code")
logging.error(str(e))
return None

View file

@ -15,7 +15,6 @@ class Provider:
try:
self.conn.execute(query, t)
self.conn.commit()
logging.debug("Proivder '%s' added to the database" % name)
except Exception as e:
logging.error(query)
logging.error("Couldn't add a new provider to database")
@ -25,7 +24,7 @@ class Provider:
query = "DELETE FROM providers WHERE id=?"
try:
self.conn.execute(query, (id,))
self.conn.commit()
self.conn.commit()
except Exception as e:
logging.error("Couldn't remove the application with id : %s", id)
logging.error(str(e))
@ -35,7 +34,6 @@ class Provider:
query = "SELECT COUNT(id) AS count FROM providers"
try:
data = c.execute(query)
logging.debug("Providers list fetched successfully")
return data.fetchone()[0]
except Exception as e:
logging.error(query)
@ -48,7 +46,6 @@ class Provider:
query = "SELECT * FROM providers"
try:
data = c.execute(query)
logging.debug("Providers list fetched successfully")
return data.fetchall()
except Exception as e:
logging.error(query)
@ -59,12 +56,16 @@ class Provider:
def get_provider_image(self, image):
img = Gtk.Image(xalign=0)
directory = "/home/bilal/Projects/Two-factor-gtk/data/logos/"
image = directory + image
if path.exists(image):
theme = Gtk.IconTheme.get_default()
if path.isfile(directory + image) and path.exists(directory + image):
img.set_from_file(directory + image)
elif path.isfile(image) and path.exists(image):
img.set_from_file(image)
elif theme.has_icon(path.splitext(image)[0]):
img.set_from_icon_name(path.splitext(image)[0],
Gtk.IconSize.DIALOG)
else:
img.set_from_icon_name(image,
Gtk.IconSize.DIALOG)
img.set_from_icon_name("image-missing", Gtk.IconSize.DIALOG)
return img
def get_latest_id(self):

View file

@ -0,0 +1,8 @@
app_PYTHON = \
add_provider.py \
confirmation.py \
listrow.py \
logo_provider.py \
window.py
appdir = $(pythondir)/TwoFactorAuth/ui

View file

@ -30,9 +30,9 @@ class AddProviderWindow(Gtk.Window):
Gtk.Window.__init__(self, title="Add a new provider", modal=True,
destroy_with_parent=True)
self.connect("delete-event", lambda x, y: self.destroy())
self.resize(350, 100)
self.resize(300, 100)
self.set_border_width(18)
self.set_size_request(350, 100)
self.set_size_request(300, 100)
self.set_position(Gtk.WindowPosition.CENTER)
self.set_resizable(False)
self.set_transient_for(self.parent)
@ -55,7 +55,11 @@ class AddProviderWindow(Gtk.Window):
secret_entry,
image_entry)
id = self.parent.app.provider.get_latest_id()
self.parent.refresh_window()
print()
if self.parent.app.provider.count_providers() == 1:
self.parent.refresh_window(True)
else:
self.parent.update_list(id, name_entry, secret_entry, image_entry)
self.close_window()
except Exception as e:
logging.error("Error in adding a new provider")
@ -82,10 +86,8 @@ class AddProviderWindow(Gtk.Window):
hbox_two_factor.pack_end(two_factor_entry, False, True, 0)
logo_event = Gtk.EventBox()
logo_image = Gtk.Image()
logo_image.set_from_icon_name("image-missing",
Gtk.IconSize.DIALOG)
logo_event.get_style_context().add_class("provider-logo-add")
logo_image = self.parent.app.provider.get_provider_image("image-missing")
logo_image.get_style_context().add_class("provider-logo-add")
logo_event.add(logo_image)
logo_event.connect("button-press-event", self.select_logo)
logo_box.pack_start(logo_event, False, False, 6)

View file

@ -0,0 +1,155 @@
from gi import require_version
require_version("Gtk", "3.0")
from gi.repository import Gtk, GLib, Gio, Gdk, GObject
from models.code import Code
from threading import Thread
import time
import logging
from math import pi
class ListBoxRow(Thread):
counter_max = 30
counter = 30
code = None
code_generated = True
def __init__(self, parent, id, name, secret_code, logo):
Thread.__init__(self)
self.parent = parent
self.id = id
self.name = name
self.secret_code = secret_code
self.code = Code(secret_code)
self.logo = logo
self.create_row()
self.start()
GObject.timeout_add_seconds(1, self.refresh_listbox)
def on_button_press_event(self, widget, event) :
if event.button == Gdk.EventType._2BUTTON_PRESS:
#data = widget.get_path_at_pos(int(event.x), int(event.y))
print("helloooo")
def create_row(self):
self.row = Gtk.ListBoxRow()
self.row.get_style_context().add_class("application-list-row")
self.row.connect("button-press-event", self.on_button_press_event)
vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
hbox = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL)
pass_box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL)
pass_box.set_visible(False)
vbox.pack_start(hbox, True, True, 6)
vbox.pack_start(pass_box, True, True, 6)
# ID
label_id = Gtk.Label()
label_id.set_text(str(self.id))
label_id.set_visible(False)
label_id.set_no_show_all(True)
vbox.pack_end(label_id, False, False, 0)
# Checkbox
checkbox = Gtk.CheckButton()
checkbox.set_visible(False)
checkbox.set_no_show_all(True)
checkbox.connect("toggled", self.parent.select_application)
hbox.pack_start(checkbox, False, True, 6)
# Provider logo
provider_logo = self.parent.app.provider.get_provider_image(self.logo)
hbox.pack_start(provider_logo, False, True, 6)
# Provider name
application_name = Gtk.Label(xalign=0)
application_name.get_style_context().add_class("application-name")
application_name.set_text(self.name)
hbox.pack_start(application_name, True, True, 6)
# Copy button
copy_event = Gtk.EventBox()
copy_button = Gtk.Image(xalign=0)
copy_button.set_from_icon_name("edit-copy-symbolic",
Gtk.IconSize.SMALL_TOOLBAR)
copy_button.set_tooltip_text("Copy the generated code..")
copy_event.connect("button-press-event", self.parent.copy_code)
copy_event.add(copy_button)
hbox.pack_end(copy_event, False, True, 6)
# Remove button
remove_event = Gtk.EventBox()
remove_button = Gtk.Image(xalign=0)
remove_button.set_from_icon_name("list-remove-symbolic",
Gtk.IconSize.SMALL_TOOLBAR)
remove_button.set_tooltip_text("Remove the source..")
remove_event.add(remove_button)
remove_event.connect("button-press-event", self.parent.remove_provider)
hbox.pack_end(remove_event, False, True, 6)
self.darea = Gtk.DrawingArea()
self.darea.set_size_request(24, 24)
code_label = Gtk.Label(xalign=0)
code_label.get_style_context().add_class("application-secret-code")
# TODO : show the real secret code
self.update_code(code_label)
pass_box.set_no_show_all(True)
pass_box.pack_end(self.darea, False, True, 6)
pass_box.pack_start(code_label, False, True, 6)
self.row.add(vbox)
def get_counter(self):
return self.counter
def run(self):
while self.code_generated:
self.counter -= 1
if self.counter < 0:
self.counter = self.counter_max
self.regenerate_code()
self.darea.connect("draw", self.expose)
self.row.changed()
time.sleep(1)
def get_listrow(self):
return self.row
def refresh_listbox(self):
self.parent.listbox.hide()
self.parent.listbox.show_all()
return self.code_generated
def regenerate_code(self):
label = self.row.get_children()[0].get_children()[1].get_children()[0]
if label:
self.code.update()
self.update_code(label)
def update_code(self, label):
try:
label.set_text(self.code.get_secret_code())
except TypeError as e:
logging.error("Canno't generate secret code")
logging.error(str(e))
label.set_text("Couldn't generate the secret code")
self.code_generated = False
def expose(self, darea, cairo):
try:
if self.code_generated:
cairo.arc(12, 12, 12, 0, (self.counter*2*pi/self.counter_max))
cairo.set_source_rgba(0, 0, 0, 0.4)
cairo.fill_preserve()
if self.counter < self.counter_max/2:
cairo.set_source_rgb(0, 0, 0)
else:
cairo.set_source_rgb(1, 1, 1)
cairo.move_to(8, 15)
cairo.show_text(str(self.counter))
# self.draw(cairo)
except Exception as e:
logging.error(str(e))
return False

View file

@ -9,6 +9,9 @@ logging.basicConfig(level=logging.DEBUG,
class LogoProviderWindow(Gtk.Window):
def __init__(self, window):
directory = "/home/bilal/Projects/Two-factor-gtk/data/logos/"
self.logos = listdir(directory)
self.logos.sort()
self.window = window
self.generate_window()
self.genereate_searchbar()
@ -31,7 +34,7 @@ class LogoProviderWindow(Gtk.Window):
def filter_func(self, row, data, notify_destroy):
provider_label = row.get_children()[0].get_children()[0].get_children()
data = data.strip()
data = data.strip().lower()
if len(data) > 0:
return data in provider_label[1].get_text().lower()
else:
@ -39,6 +42,12 @@ class LogoProviderWindow(Gtk.Window):
def filter_providers(self, entry):
data = entry.get_text()
if len(data) != 0:
entry.set_icon_from_icon_name(Gtk.EntryIconPosition.SECONDARY,
"edit-clear-symbolic")
else:
entry.set_icon_from_icon_name(Gtk.EntryIconPosition.SECONDARY,
None)
self.listbox.set_filter_func(self.filter_func, data, False)
def on_key_press(self, provider, keyevent):
@ -54,7 +63,7 @@ class LogoProviderWindow(Gtk.Window):
search_box.set_visible(is_visible)
search_box.show_all()
if is_visible:
search_box.get_children()[1].grab_focus_without_selecting()
search_box.get_children()[0].grab_focus_without_selecting()
else:
self.listbox.set_filter_func(lambda x,y,z : True, None, False)
elif keypressed == "return":
@ -62,40 +71,29 @@ class LogoProviderWindow(Gtk.Window):
def genereate_searchbar(self):
hbox = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL)
hbox.set_margin_left(40)
search_image = Gtk.Image(xalign=0)
search_image.set_from_icon_name("system-search-symbolic",
Gtk.IconSize.SMALL_TOOLBAR)
search_image.set_tooltip_text("Type to search")
hbox.set_margin_left(60)
search_entry = Gtk.Entry()
search_entry.connect("changed", self.filter_providers)
search_entry.set_icon_from_icon_name(Gtk.EntryIconPosition.PRIMARY,
"system-search-symbolic")
hbox.pack_start(search_image, False, True, 6)
hbox.pack_start(search_entry, False, True, 6)
hbox.set_visible(False)
self.get_children()[0].pack_start(hbox, False, True, 0)
self.get_children()[0].pack_start(hbox, False, True, 6)
self.get_children()[0].get_children()[0].set_no_show_all(True)
def select_logo(self, *args):
index = self.listbox.get_selected_row().get_index()
directory = "/home/bilal/Projects/Two-factor-gtk/data/logos/"
files = listdir(directory)
files.sort()
count = len(files)
if count > 0:
img_path = files[index]
if len(self.logos) > 0:
img_path = self.logos[index]
self.window.update_logo(img_path)
self.close_window()
def generate_compenents(self):
box_outer = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=6)
directory = "/home/bilal/Projects/Two-factor-gtk/data/logos/"
files = listdir(directory)
files.sort()
count = len(files)
if count > 0:
if len(self.logos) > 0:
# Create a ScrolledWindow for installed applications
scrolled_win = Gtk.ScrolledWindow()
scrolled_win.add_with_viewport(box_outer)
@ -107,8 +105,8 @@ class LogoProviderWindow(Gtk.Window):
self.listbox.set_selection_mode(Gtk.SelectionMode.SINGLE)
box_outer.pack_start(self.listbox, True, True, 0)
i = 0
while i < count:
logo = files[i]
while i < len(self.logos):
logo = self.logos[i]
provider_name = path.splitext(logo)[0].strip(".").title()
row = Gtk.ListBoxRow()
row.get_style_context().add_class("application-list-row")
@ -116,11 +114,8 @@ class LogoProviderWindow(Gtk.Window):
hbox = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL)
# Provider logo
provider_logo = Gtk.Image(xalign=0)
provider_logo.set_from_file(directory + logo)
#provider_logo.scale_simple(Gtk.IconSize.DIALOG,
# Gtk.IconSize.DIALOG,
# GdkPixbuf.InterpType.BILINEAR)
provider = self.window.parent.app.provider
provider_logo = provider.get_provider_image(logo)
hbox.pack_start(provider_logo, False, True, 6)
# Provider name

View file

@ -1,19 +1,21 @@
from gi import require_version
require_version("Gtk", "3.0")
from gi.repository import Gtk, GLib, Gio, Gdk
from gi.repository import Gtk, GLib, Gio, Gdk, GObject
from ui.add_provider import AddProviderWindow
from ui.confirmation import ConfirmationMessage
import logging
from ui.listrow import ListBoxRow
from threading import Thread
import logging
from math import pi
logging.basicConfig(level=logging.DEBUG,
format='[%(levelname)s] %(message)s',
)
class TwoFactorWindow(Gtk.Window):
class TwoFactorWindow(Gtk.ApplicationWindow):
app = None
selected_app_idx = None
checkboxes = []
def __init__(self, application):
self.app = application
@ -24,15 +26,16 @@ class TwoFactorWindow(Gtk.Window):
self.get_children()[0].get_children()[0].set_visible(False)
def generate_window(self, *args):
Gtk.Window.__init__(self, application=self.app)
self.connect("delete-event", lambda x, y: self.app.quit())
Gtk.ApplicationWindow.__init__(self, Gtk.WindowType.TOPLEVEL,
application=self.app)
self.set_position(Gtk.WindowPosition.CENTER)
self.set_wmclass("twofactor", "Two-Factor")
self.set_wmclass("two_factor_auth", "Two-Factor Auth")
self.resize(350, 500)
self.set_size_request(350, 500)
self.set_resizable(False)
self.connect("key_press_event", self.on_key_press)
self.app.win = self
self.connect("delete-event", lambda x, y: self.app.on_quit())
self.add(Gtk.Box(orientation=Gtk.Orientation.VERTICAL))
def on_key_press(self, provider, keyevent):
@ -44,17 +47,20 @@ class TwoFactorWindow(Gtk.Window):
elif keypressed == "f":
if keyevent.state == CONTROL_MASK:
if self.app.provider.count_providers() > 0:
search_box = self.get_children()[0].get_children()[0]
search_box = self.get_children()[0].get_children()[0].get_children()[0]
is_visible = search_box.get_no_show_all()
search_box.set_no_show_all(not is_visible)
search_box.set_visible(is_visible)
search_box.show_all()
if is_visible:
search_box.get_children()[1].grab_focus_without_selecting()
search_box.get_children()[0].grab_focus_without_selecting()
else:
self.listbox.set_filter_func(lambda x,y,z : True, None, False)
elif keypressed == "n":
if keyevent.state == CONTROL_MASK:
self.add_provider()
elif keypressed == "delete":
self.remove_application()
self.remove_provider()
elif keypressed == "return":
if self.app.provider.count_providers() > 0:
if self.listbox.get_selected_row():
@ -71,40 +77,42 @@ class TwoFactorWindow(Gtk.Window):
def filter_providers(self, entry):
data = entry.get_text()
if len(data) != 0:
entry.set_icon_from_icon_name(Gtk.EntryIconPosition.SECONDARY,
"edit-clear-symbolic")
else:
entry.set_icon_from_icon_name(Gtk.EntryIconPosition.SECONDARY,
None)
self.listbox.set_filter_func(self.filter_func, data, False)
def genereate_searchbar(self):
hbox = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL)
hbox.set_margin_left(40)
search_image = Gtk.Image(xalign=0)
search_image.set_from_icon_name("system-search-symbolic",
Gtk.IconSize.SMALL_TOOLBAR)
search_image.set_tooltip_text("Type to search")
hbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
search_box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL)
search_entry = Gtk.Entry()
search_box.set_margin_left(60)
search_entry.set_width_chars(21)
search_entry.connect("changed", self.filter_providers)
search_entry.set_icon_from_icon_name(Gtk.EntryIconPosition.PRIMARY,
"system-search-symbolic")
hbox.pack_start(search_image, False, True, 6)
hbox.pack_start(search_entry, False, True, 6)
search_box.pack_start(search_entry, False, True, 0)
hbox.pack_start(search_box, False, True, 6)
hbox.set_visible(False)
self.get_children()[0].pack_start(hbox, False, True, 6)
self.get_children()[0].get_children()[0].set_no_show_all(True)
self.get_children()[0].pack_start(hbox, True, True, 0)
search_box.set_no_show_all(True)
def remove_selected(self, *args):
i = 0
confirmation = ConfirmationMessage(self, "Are you sure??")
message = "Do you really want to remove the two-factor auth provider?"
confirmation = ConfirmationMessage(self, message)
confirmation.show()
if confirmation.get_confirmation():
while i < len(self.checkboxes):
if self.checkboxes[i].get_active():
selected_row = self.listbox.get_row_at_index(i)
label_id = selected_row.get_children()[0].get_children()[2]
self.app.provider.remove_from_database(int(label_id.get_text()))
self.listbox.remove(selected_row)
del self.checkboxes[i]
i += 1
for row in self.listbox.get_children():
checkbox = self.get_checkbox_from_row(row)
if checkbox.get_active():
label_id = row.get_children()[0].get_children()[2]
label_id = int(label_id.get_text())
self.app.provider.remove_from_database(label_id)
self.listbox.remove(row)
self.listbox.unselect_all()
confirmation.destroy()
self.refresh_window()
@ -174,14 +182,14 @@ class TwoFactorWindow(Gtk.Window):
listrow_box = self.listbox.get_row_at_index(index)
self.listbox.select_row(listrow_box)
while i < len(self.checkboxes):
visible = self.checkboxes[i].get_visible()
selected = self.checkboxes[i].get_active()
for row in self.listbox.get_children():
checkbox = self.get_checkbox_from_row(row)
visible = checkbox.get_visible()
selected = checkbox.get_active()
if not button_visible:
self.select_application(self.checkboxes[i])
self.checkboxes[i].set_visible(not visible)
self.checkboxes[i].set_no_show_all(visible)
i += 1
self.select_application(checkbox)
checkbox.set_visible(not visible)
checkbox.set_no_show_all(visible)
def select_application(self, checkbutton):
is_active = checkbutton.get_active()
@ -199,135 +207,84 @@ class TwoFactorWindow(Gtk.Window):
else:
return True
def get_checkbox_from_row(self, row):
if row:
return row.get_children()[0].get_children()[0].get_children()[0]
else:
return None
def select_row(self, listbox, listbox_row):
index = listbox_row.get_index()
button_visible = self.remove_button.get_visible()
if self.checkboxes[index]:
if button_visible:
clicked = self.checkboxes[index].get_active()
self.checkboxes[index].set_active(not clicked)
else:
if self.selected_app_idx:
listrow_box = self.listbox.get_row_at_index(
self.selected_app_idx)
self.listbox.unselect_row(listbox_row)
self.selected_app_idx = index
listrow_box = self.listbox.get_row_at_index(index)
self.listbox.select_row(listbox_row)
checkbox = self.get_checkbox_from_row(listbox_row)
if button_visible:
checkbox.set_active(not checkbox.get_active())
else:
if self.selected_app_idx:
listrow_box = self.listbox.get_row_at_index(
self.selected_app_idx)
self.listbox.unselect_row(listbox_row)
self.selected_app_idx = index
listrow_box = self.listbox.get_row_at_index(index)
self.listbox.select_row(listbox_row)
# TODO : show a nice message when no application is added
def generate_applications_list(self):
box_outer = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=6)
list_box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=6)
count = self.app.provider.count_providers()
if count > 0:
# Create a ScrolledWindow for installed applications
scrolled_win = Gtk.ScrolledWindow()
scrolled_win.add_with_viewport(box_outer)
self.get_children()[0].pack_start(scrolled_win, True, True, 0)
# Create a ScrolledWindow for installed applications
self.listbox = Gtk.ListBox()
self.listbox.get_style_context().add_class("applications-list")
self.listbox.set_adjustment()
self.listbox.connect("row_activated", self.select_row)
self.listbox.set_selection_mode(Gtk.SelectionMode.SINGLE)
list_box.pack_start(self.listbox, True, True, 0)
self.listbox = Gtk.ListBox()
self.listbox.get_style_context().add_class("applications-list")
self.listbox.set_adjustment()
self.listbox.connect("row_activated", self.select_row)
self.listbox.set_selection_mode(Gtk.SelectionMode.SINGLE)
box_outer.pack_start(self.listbox, True, True, 0)
providers = self.app.provider.fetch_providers()
i = 0
while i < count:
row = self.generate_listrow(providers[i][0], providers[i][1],
providers[i][2], providers[i][3])
self.listbox.add(row)
i += 1
scrolled_win = Gtk.ScrolledWindow()
scrolled_win.add_with_viewport(list_box)
self.get_children()[0].get_children()[0].pack_start(scrolled_win, True, True, 0)
providers = self.app.provider.fetch_providers()
i = 0
while i < len(providers):
row = ListBoxRow(self, providers[i][0], providers[i][1],
providers[i][2], providers[i][3])
self.listbox.add(row.get_listrow())
i += 1
nolist_box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=6)
vbox = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL)
logo_image = Gtk.Image()
logo_image.set_from_icon_name("dialog-information-symbolic",
Gtk.IconSize.DIALOG)
vbox.pack_start(logo_image, False, False, 6)
no_proivders_label = Gtk.Label()
no_proivders_label.set_text("There's no providers at the moment")
vbox.pack_start(no_proivders_label, False, False, 6)
nolist_box.pack_start(vbox, True, True, 0)
self.get_children()[0].pack_start(nolist_box, True, True, 0)
if len(providers) == 0:
self.get_children()[0].get_children()[0].set_no_show_all(True)
self.get_children()[0].get_children()[0].set_visible(False)
else:
vbox = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL)
self.get_children()[0].get_children()[1].set_no_show_all(True)
self.get_children()[0].get_children()[1].set_visible(False)
logo_image = Gtk.Image()
logo_image.set_from_icon_name("dialog-information-symbolic",
Gtk.IconSize.DIALOG)
vbox.pack_start(logo_image, False, False, 6)
no_proivders_label = Gtk.Label()
no_proivders_label.set_text("There's no providers at the moment")
vbox.pack_start(no_proivders_label, False, False, 6)
box_outer.pack_start(vbox, True, True, 0)
self.get_children()[0].pack_start(box_outer, True, True, 0)
def update_list(self, id, name, secret_code, image):
row = self.generate_listrow(id, name, secret_code, image)
self.listbox.add(row)
row = ListBoxRow(self, id, name, secret_code, image)
self.listbox.add(row.get_listrow())
self.listbox.show_all()
def generate_listrow(self, id, name, secret_code, logo):
row = Gtk.ListBoxRow()
row.get_style_context().add_class("application-list-row")
vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
hbox = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL)
pass_box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL)
pass_box.set_visible(False)
vbox.pack_start(hbox, True, True, 6)
vbox.pack_start(pass_box, True, True, 6)
# ID
label_id = Gtk.Label()
label_id.set_text(str(id))
label_id.set_visible(False)
label_id.set_no_show_all(True)
vbox.pack_end(label_id, False, False, 0)
# Checkbox
checkbox = Gtk.CheckButton()
checkbox.set_visible(False)
checkbox.set_no_show_all(True)
checkbox.connect("toggled", self.select_application)
hbox.pack_start(checkbox, False, True, 6)
self.checkboxes.append(checkbox)
# Provider logo
provider_logo = self.app.provider.get_provider_image(logo)
hbox.pack_start(provider_logo, False, True, 6)
# Provider name
application_name = Gtk.Label(xalign=0)
application_name.get_style_context().add_class("application-name")
application_name.set_text(name)
hbox.pack_start(application_name, True, True, 6)
# Copy button
copy_event = Gtk.EventBox()
copy_button = Gtk.Image(xalign=0)
copy_button.set_from_icon_name("edit-copy-symbolic",
Gtk.IconSize.SMALL_TOOLBAR)
copy_button.set_tooltip_text("Copy the generated code..")
copy_event.connect("button-press-event", self.copy_code)
copy_event.add(copy_button)
hbox.pack_end(copy_event, False, True, 6)
# Remove button
remove_event = Gtk.EventBox()
remove_button = Gtk.Image(xalign=0)
remove_button.set_from_icon_name("list-remove-symbolic",
Gtk.IconSize.SMALL_TOOLBAR)
remove_button.set_tooltip_text("Remove the source..")
remove_event.add(remove_button)
remove_event.connect("button-press-event", self.remove_application)
hbox.pack_end(remove_event, False, True, 6)
code_label = Gtk.Label(xalign=0)
code_label.get_style_context().add_class("application-secret-code")
# TODO : show the real secret code
code_label.set_text(secret_code)
pass_box.set_no_show_all(True)
pass_box.pack_start(code_label, False, True, 0)
row.add(vbox)
return row
def copy_code(self, *args):
if len(args) > 0:
row = args[0].get_parent().get_parent().get_parent()
self.listbox.select_row(row)
selected_row = self.listbox.get_selected_row()
label = selected_row.get_children()[0].get_children()[1].get_children()
code = label[0].get_text()
@ -338,40 +295,35 @@ class TwoFactorWindow(Gtk.Window):
except Exception as e:
logging.error(str(e))
def refresh_window(self, *args):
def refresh_window(self, force_refresh=False):
mainbox = self.get_children()[0]
self.checkboxes = []
count = self.app.provider.count_providers()
for widget in mainbox:
mainbox.remove(widget)
self.genereate_searchbar()
self.generate_applications_list()
if count == 0:
self.get_children()[0].get_children()[0].set_no_show_all(True)
self.get_children()[0].get_children()[0].set_visible(False)
else:
self.get_children()[0].get_children()[1].set_no_show_all(True)
self.get_children()[0].get_children()[1].set_visible(False)
headerbar = self.get_children()[1]
left_box = headerbar.get_children()[0]
right_box = headerbar.get_children()[1]
right_box.get_children()[0].set_visible(count > 0)
if count == 0:
self.listbox.set_selection_mode(Gtk.SelectionMode.SINGLE)
if count > 0 and self.listbox:
if self.listbox.get_selection_mode() == Gtk.SelectionMode.MULTIPLE:
left_box.get_children()[0].set_visible(count > 0)
else:
left_box.get_children()[0].set_visible(False)
self.get_children()[0].show_all()
self.listbox.set_selection_mode(Gtk.SelectionMode.SINGLE)
left_box.get_children()[0].set_visible(False)
# TODO : add remove from database
def remove_application(self, *args):
confirmation = ConfirmationMessage(self, "Are you sure??")
def remove_provider(self, *args):
if len(args) > 0:
row = args[0].get_parent().get_parent().get_parent()
self.listbox.select_row(row)
message = "Do you really want to remove the two-factor auth provider?"
confirmation = ConfirmationMessage(self, message)
confirmation.show()
if confirmation.get_confirmation():
if self.listbox.get_selected_row():
selected_row = self.listbox.get_selected_row()
del self.checkboxes[selected_row.get_index()]
index = selected_row.get_index() + 1
if index > len(self.listbox.get_children()) - 1:
index = selected_row.get_index() - 1
self.listbox.select_row(self.listbox.get_row_at_index(index))
self.listbox.remove(selected_row)
label_id = selected_row.get_children()[0].get_children()[2]
self.app.provider.remove_from_database(int(label_id.get_text()))