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()