diff --git a/howdy-gtk/src/authsticky.py b/howdy-gtk/src/authsticky.py
index 3f21d07..2c0c590 100644
--- a/howdy-gtk/src/authsticky.py
+++ b/howdy-gtk/src/authsticky.py
@@ -50,6 +50,7 @@ class StickyWindow(gtk.Window):
self.connect("draw", self.draw)
# Listen for a force close or click event and exit
self.connect("destroy", self.exit)
+ self.connect("delete_event", self.exit)
self.connect("button-press-event", self.exit)
# Create a GDK drawing, restricts the window size
diff --git a/howdy-gtk/src/i18n.py b/howdy-gtk/src/i18n.py
new file mode 100644
index 0000000..2b3afb2
--- /dev/null
+++ b/howdy-gtk/src/i18n.py
@@ -0,0 +1,12 @@
+# Support file for translations
+
+# Import modules
+import gettext
+import os
+
+# Get the right translation based on locale, falling back to base if none found
+translation = gettext.translation("gtk", localedir=os.path.join(os.path.dirname(__file__), "locales"), fallback=True)
+translation.install()
+
+# Export translation function as _
+_ = translation.gettext
diff --git a/howdy-gtk/src/ui.glade b/howdy-gtk/src/ui.glade
index 778db5c..9f8cf9c 100644
--- a/howdy-gtk/src/ui.glade
+++ b/howdy-gtk/src/ui.glade
@@ -58,6 +58,7 @@
True
True
bottom
+
False
diff --git a/howdy-gtk/src/window.py b/howdy-gtk/src/window.py
index 010bff9..89e413e 100644
--- a/howdy-gtk/src/window.py
+++ b/howdy-gtk/src/window.py
@@ -7,6 +7,8 @@ import os
import elevate
import subprocess
+from i18n import _
+
# Make sure we have the libs we need
gi.require_version("Gtk", "3.0")
gi.require_version("Gdk", "3.0")
@@ -23,6 +25,7 @@ class MainWindow(gtk.Window):
gtk.Window.__init__(self)
self.connect("destroy", self.exit)
+ self.connect("delete_event", self.exit)
self.builder = gtk.Builder()
self.builder.add_from_file("./ui.glade")
@@ -34,9 +37,10 @@ class MainWindow(gtk.Window):
# Create a treeview that will list the model data
self.treeview = gtk.TreeView()
+ self.treeview.set_vexpand(True)
# Set the coloums
- for i, column in enumerate(["ID", "Created", "Label"]):
+ for i, column in enumerate([_("ID"), _("Created"), _("Label")]):
cell = gtk.CellRendererText()
col = gtk.TreeViewColumn(column, cell, text=i)
@@ -48,8 +52,11 @@ class MainWindow(gtk.Window):
filelist = os.listdir("/lib/security/howdy/models")
self.active_user = ""
+ self.userlist.items = 0
+
for file in filelist:
self.userlist.append_text(file[:-4])
+ self.userlist.items += 1
if not self.active_user:
self.active_user = file[:-4]
@@ -66,19 +73,22 @@ class MainWindow(gtk.Window):
"""(Re)load the model list"""
# Execute the list commond to get the models
- # output = subprocess.check_output(["howdy", "list", "--plain", "-U", self.active_user])
+ # status, output = subprocess.getstatusoutput(["howdy list --plain -U " + self.active_user])
+ status = 0
output = "1,2020-12-05 14:10:22,sd\n2,2020-12-05 14:22:41,\n3,2020-12-05 14:57:37,Model #3" + self.active_user
- # Split the output per line
- # lines = output.decode("utf-8").split("\n")
- lines = output.split("\n")
-
# Create a datamodel
self.listmodel = gtk.ListStore(str, str, str)
- # Add the models to the datamodel
- for i in range(len(lines)):
- self.listmodel.append(lines[i].split(","))
+ # If there was no error
+ if status == 0:
+ # Split the output per line
+ # lines = output.decode("utf-8").split("\n")
+ lines = output.split("\n")
+
+ # Add the models to the datamodel
+ for i in range(len(lines)):
+ self.listmodel.append(lines[i].split(","))
self.treeview.set_model(self.listmodel)
@@ -95,7 +105,7 @@ class MainWindow(gtk.Window):
def exit(self, widget, context):
"""Cleanly exit"""
gtk.main_quit()
- sys.exit()
+ sys.exit(0)
# Make sure we quit on a SIGINT
@@ -104,7 +114,9 @@ signal.signal(signal.SIGINT, signal.SIG_DFL)
# Make sure we run as sudo
elevate.elevate()
+# Class is split so it isn't too long, import split functions
import window_tab_models
+MainWindow.on_user_add = window_tab_models.on_user_add
MainWindow.on_user_change = window_tab_models.on_user_change
MainWindow.on_model_add = window_tab_models.on_model_add
MainWindow.on_model_delete = window_tab_models.on_model_delete
diff --git a/howdy-gtk/src/window_tab_models.py b/howdy-gtk/src/window_tab_models.py
index a79ab8a..fe61619 100644
--- a/howdy-gtk/src/window_tab_models.py
+++ b/howdy-gtk/src/window_tab_models.py
@@ -1,5 +1,7 @@
import subprocess
+import time
+from i18n import _
from gi.repository import Gtk as gtk
@@ -8,48 +10,87 @@ def on_user_change(self, select):
self.load_model_list()
-def on_model_add(self, select):
+def on_user_add(self, button):
+ # Open question dialog
dialog = gtk.MessageDialog(parent=self, flags=gtk.DialogFlags.MODAL, type=gtk.MessageType.QUESTION, buttons=gtk.ButtonsType.OK_CANCEL)
- dialog.props.text = "Please enter a name for the new model, 24 characters max"
- dialog.set_title("Confirm Model Creation")
- # create the text input field
+ dialog.set_title(_("Confirm User Creation"))
+ dialog.props.text = _("Please enter the username of the user you want to add to Howdy")
+
+ # Create the input field
entry = gtk.Entry()
- # create a horizontal box to pack the entry and a label
+
+ # Add a label to ask for a model name
hbox = gtk.HBox()
- hbox.pack_start(gtk.Label("Model name:"), False, 5, 5)
+ hbox.pack_start(gtk.Label(_("Username:")), False, 5, 5)
hbox.pack_end(entry, True, True, 5)
- # some secondary text
- # add it and show it
+
+ # Add the box and show the dialog
dialog.vbox.pack_end(hbox, True, True, 0)
dialog.show_all()
- # go go go
+
+ # Show dialog
response = dialog.run()
- text = entry.get_text()
+ entered_user = entry.get_text()
+ dialog.destroy()
+
+ if response == gtk.ResponseType.OK:
+ self.userlist.append_text(entered_user)
+ self.userlist.set_active(self.userlist.items)
+ self.userlist.items += 1
+
+ self.active_user = entered_user
+ self.load_model_list()
+
+
+def on_model_add(self, button):
+ # Open question dialog
+ dialog = gtk.MessageDialog(parent=self, flags=gtk.DialogFlags.MODAL, type=gtk.MessageType.QUESTION, buttons=gtk.ButtonsType.OK_CANCEL)
+ dialog.set_title(_("Confirm Model Creation"))
+ dialog.props.text = _("Please enter a name for the new model, 24 characters max")
+
+ # Create the input field
+ entry = gtk.Entry()
+
+ # Add a label to ask for a model name
+ hbox = gtk.HBox()
+ hbox.pack_start(gtk.Label(_("Model name:")), False, 5, 5)
+ hbox.pack_end(entry, True, True, 5)
+
+ # Add the box and show the dialog
+ dialog.vbox.pack_end(hbox, True, True, 0)
+ dialog.show_all()
+
+ # Show dialog
+ response = dialog.run()
+
+ entered_name = entry.get_text()
dialog.destroy()
if response == gtk.ResponseType.OK:
dialog = gtk.MessageDialog(parent=self, flags=gtk.DialogFlags.MODAL)
- dialog.props.text = "Please look directly into the camera"
- dialog.set_title("Creating Model")
+ dialog.set_title(_("Creating Model"))
+ dialog.props.text = _("Please look directly into the camera")
dialog.show_all()
- status, output = subprocess.getstatusoutput(["howdy add -y -U " + self.active_user])
+ time.sleep(1)
+
+ status, output = subprocess.getstatusoutput(["howdy add -y -U " + self.active_user + " '" + entered_name + "'"])
dialog.destroy()
- if status != 1:
+ if status != 0:
dialog = gtk.MessageDialog(parent=self, flags=gtk.DialogFlags.MODAL, type=gtk.MessageType.ERROR, buttons=gtk.ButtonsType.CLOSE)
- dialog.props.text = "Error while adding model, error code " + str(status) + ": \n\n"
+ dialog.set_title(_("Howdy Error"))
+ dialog.props.text = _("Error while adding model, error code {}: \n\n").format(str(status))
dialog.format_secondary_text(output)
- dialog.set_title("Howdy Error")
dialog.run()
dialog.destroy()
self.load_model_list()
-def on_model_delete(self, select):
+def on_model_delete(self, button):
selection = self.treeview.get_selection()
(listmodel, rowlist) = selection.get_selected_rows()
@@ -58,8 +99,8 @@ def on_model_delete(self, select):
name = listmodel.get_value(listmodel.get_iter(rowlist[0]), 2)
dialog = gtk.MessageDialog(parent=self, flags=gtk.DialogFlags.MODAL, buttons=gtk.ButtonsType.OK_CANCEL)
- dialog.props.text = "Are you sure you want to delete model " + id + " (" + name + ")?"
- dialog.set_title("Confirm Model Deletion")
+ dialog.set_title(_("Confirm Model Deletion"))
+ dialog.props.text = _("Are you sure you want to delete model {id} ({name})?").format(id=id, name=name)
response = dialog.run()
dialog.destroy()
@@ -68,9 +109,9 @@ def on_model_delete(self, select):
if status != 0:
dialog = gtk.MessageDialog(parent=self, flags=gtk.DialogFlags.MODAL, type=gtk.MessageType.ERROR, buttons=gtk.ButtonsType.CLOSE)
- dialog.props.text = "Error while deleting model, error code " + str(status) + ": \n\n"
+ dialog.set_title(_("Howdy Error"))
+ dialog.props.text = _("Error while deleting model, error code {}: \n\n").format(status)
dialog.format_secondary_text(output)
- dialog.set_title("Howdy Error")
dialog.run()
dialog.destroy()