[gtranslator/dl-workflow: 1/2] gtr-application.c: add upload icon




commit 1e40ad5b2484122fdc1230ea38de14846c6c53da
Author: Amanda Shafack <shafack likhene gmail com>
Date:   Tue Mar 2 07:25:07 2021 +0000

    gtr-application.c: add upload icon
    
    Add an icon to enable po files to be uploaded directly from
    the Translation Editor.
    
    - Add a tool tip to the upload icon
    - Create a keyboard shortcut for the upload icon
    - Activate the icon to respond to click signals

 src/gtr-actions-file.c | 174 ++++++++++++++++++++++++++++++++++++++++++++++++-
 src/gtr-actions.h      |   3 +
 src/gtr-application.c  |  13 ++++
 src/gtr-dl-teams.c     |   4 +-
 src/gtr-notebook.c     |  10 +++
 src/gtr-notebook.h     |   2 +
 src/gtr-notebook.ui    |  22 +++++++
 src/gtr-po.c           |  42 ++++++++++++
 src/gtr-po.h           |  12 ++++
 src/gtr-window.c       |   4 +-
 10 files changed, 281 insertions(+), 5 deletions(-)
---
diff --git a/src/gtr-actions-file.c b/src/gtr-actions-file.c
index fec93d79..d76c9ed7 100644
--- a/src/gtr-actions-file.c
+++ b/src/gtr-actions-file.c
@@ -30,6 +30,7 @@
 #include <string.h>
 #include <gio/gio.h>
 
+#include "gtr-profile-manager.h"
 #include "gtr-close-confirmation-dialog.h"
 #include "gtr-actions.h"
 #include "gtr-application.h"
@@ -44,6 +45,8 @@
 #define GTR_TAB_SAVE_AS    "gtr-tab-save-as"
 #define GTR_IS_CLOSING_ALL "gtr-is-closing-all"
 
+#define API_URL "https://l10n.gnome.org/api/v1/";
+
 static void load_file_list (GtrWindow * window, const GSList * uris);
 static GList * get_modified_documents (GtrWindow * window);
 
@@ -58,6 +61,13 @@ gtr_open (GFile * location, GtrWindow * window, GError ** error)
   GtrTab *tab;
   GList *current;
   GtrView *active_view;
+  GtrHeader *header;
+  GtrNotebook *active_notebook;
+  gchar *dl_team;
+  gchar *dl_module;
+  gchar *dl_branch;
+  gchar *dl_domain;
+  gchar *dl_module_state;
 
   /*
    * If the filename can't be opened, pass the error back to the caller
@@ -77,12 +87,36 @@ gtr_open (GFile * location, GtrWindow * window, GError ** error)
     return FALSE;
   }
 
+  header = gtr_po_get_header (po);
+  dl_team = gtr_header_get_dl_team (header);
+  dl_module = gtr_header_get_dl_module (header);
+  dl_branch = gtr_header_get_dl_branch (header);
+  dl_domain = gtr_header_get_dl_domain (header);
+  dl_module_state = gtr_header_get_dl_state (header);
+
+  /*
+   * Set Damned Lies info when a po file is opened locally
+   */
+  gtr_po_set_dl_info(po,
+                     dl_team,
+                     dl_module,
+                     dl_branch,
+                     dl_domain,
+                     dl_module_state);
+
   /*
    * Create a page to add to our list of open files
    */
   tab = gtr_window_create_tab (window, po);
   gtr_window_set_active_tab (window, GTK_WIDGET (tab));
 
+  /*
+   * Activate the upload file icon if the po file is in the appropriate
+   * state as on the vertimus workflow
+   */
+  active_notebook = gtr_window_get_notebook (window);
+  gtr_notebook_enable_upload (active_notebook, gtr_po_can_dl_upload (po));
+
   /*
    * Show the current message.
    */
@@ -165,7 +199,7 @@ gtr_want_to_save_current_dialog (GtrWindow * window)
   GtrTab *tab;
   GtrPo *po;
 
-  g_autoptr (GtkWidget) dialog = NULL;
+  GtkWidget *dialog;
   g_autoptr (GFile) location = NULL;
   g_autofree gchar *filename = NULL;
   g_autofree gchar *markup = NULL;
@@ -196,6 +230,7 @@ gtr_want_to_save_current_dialog (GtrWindow * window)
                           NULL);
 
   res = gtk_dialog_run (GTK_DIALOG (dialog));
+  gtk_widget_destroy (dialog);
 
   if (res == GTK_RESPONSE_CANCEL)
     return FALSE;
@@ -214,7 +249,6 @@ gtr_open_file_dialog (GtkAction * action, GtrWindow * window)
 {
   GtkWidget *dialog = NULL;
   g_autoptr (GList) list = NULL;
-
   list = get_modified_documents (window);
   if (list != NULL)
     {
@@ -308,6 +342,142 @@ confirm_overwrite_callback (GtkFileChooser * dialog, gpointer data)
   return res;
 }
 
+/*
+ * "Upload file" dialog
+ *
+ */
+void
+gtr_upload_file_dialog (GtkAction * action, GtrWindow * window)
+{
+  GtrTab *tab;
+  GtrPo *po;
+  GtkWidget *dialog, *success_dialog;
+  GtkDialogFlags flags = GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_MODAL;
+  GMappedFile *mapped;
+  GError *error = NULL;
+  GtrProfileManager *pmanager = NULL;
+  GtrNotebook *active_notebook;
+  GtrProfile *profile;
+  GtrHeader *header;
+  g_autoptr (SoupMessage) msg = NULL;
+  g_autoptr (SoupMultipart) mpart = NULL;
+  g_autoptr (SoupBuffer) buffer = NULL;
+  g_autoptr (SoupSession) session = NULL;
+  const gchar *content = NULL;
+  g_autofree gchar *mime_type = NULL;
+  g_autofree gchar *filename = NULL;
+  g_autofree gchar *upload_endpoint = NULL;
+  const char *auth_token = NULL;
+  g_autofree char *auth = NULL;
+  gsize size;
+  const gchar *selected_team;
+  const gchar *selected_module;
+  const gchar *selected_branch;
+  const gchar *selected_domain;
+
+  /* Get file content */
+  tab = gtr_window_get_active_tab (window);
+  po = gtr_tab_get_po (tab);
+  filename = g_file_get_path (gtr_po_get_location (po));
+  mapped = g_mapped_file_new (filename, FALSE, &error);
+  if (error != NULL) {
+    g_warning ("Error opening file %s: %s", filename, (error)->message);
+  }
+  content = g_mapped_file_get_contents (mapped);
+  size = g_mapped_file_get_length (mapped);
+  active_notebook = gtr_window_get_notebook (window);
+  header = gtr_po_get_header (po);
+
+  /* Check mimetype */
+  mime_type = g_strdup (g_content_type_get_mime_type(content));
+
+  /* Get the authentication token from the user profile */
+  pmanager = gtr_profile_manager_get_default ();
+  profile = gtr_profile_manager_get_active_profile (pmanager);
+  auth_token = gtr_profile_get_auth_token (profile);
+  auth = g_strconcat ("Bearer ", auth_token, NULL);
+
+  selected_module = gtr_po_get_dl_module (po);
+  if (selected_module == NULL)
+    selected_module = gtr_header_get_dl_module (header);
+
+  selected_branch = gtr_po_get_dl_branch (po);
+  if (selected_branch == NULL)
+    selected_branch = gtr_header_get_dl_branch (header);
+
+  selected_domain = gtr_po_get_dl_domain (po);
+  if (selected_domain == NULL)
+    selected_domain = gtr_header_get_dl_domain (header);
+
+  selected_team = gtr_po_get_dl_team (po);
+  if (selected_team == NULL)
+    selected_team = gtr_header_get_dl_team (header);
+
+  /* API endpoint: modules/[module]/branches/[branch]/domains/[domain]/languages/[team]/upload */
+  upload_endpoint = g_strconcat((const gchar *)API_URL,
+                                "modules/", selected_module,
+                                "/branches/", selected_branch,
+                                "/domains/", selected_domain,
+                                "/languages/", selected_team,
+                                "/upload", NULL);
+
+  /* Init multipart container */
+  mpart = soup_multipart_new (SOUP_FORM_MIME_TYPE_MULTIPART);
+  buffer = soup_buffer_new (SOUP_MEMORY_COPY, content, size);
+  soup_multipart_append_form_string (mpart, "file", "txt");
+  soup_multipart_append_form_file (mpart, "file", filename,
+                                   mime_type, buffer);
+
+  /* Get the associated message */
+  msg = soup_form_request_new_from_multipart (upload_endpoint, mpart);
+
+  /* Append the authentication header*/
+  soup_message_headers_append (msg->request_headers, "Authentication", auth);
+
+  session = soup_session_new ();
+  soup_session_send_message (session, msg);
+
+  if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code))
+    {
+      if (msg->status_code == 403)
+        {
+          dialog = gtk_message_dialog_new (GTK_WINDOW (window),
+                                           flags,
+                                           GTK_MESSAGE_INFO,
+                                           GTK_BUTTONS_OK,
+                                           _("This file has already been uploaded"));
+          gtk_dialog_run (GTK_DIALOG (dialog));
+          gtk_widget_destroy (dialog);
+          gtr_notebook_enable_upload (active_notebook, FALSE);
+          return;
+        }
+
+      dialog = gtk_message_dialog_new (GTK_WINDOW (window),
+                                       flags,
+                                       GTK_MESSAGE_WARNING,
+                                       GTK_BUTTONS_CLOSE,
+                                       _("An error occurred while uploading the file: %s"),
+                                       soup_status_get_phrase (msg->status_code));
+      gtk_dialog_run (GTK_DIALOG (dialog));
+      gtk_widget_destroy (dialog);
+      return;
+    }
+
+  success_dialog = gtk_message_dialog_new (GTK_WINDOW (window),
+                                           flags,
+                                           GTK_MESSAGE_INFO,
+                                           GTK_BUTTONS_OK,
+                                           _("The file '%s.%s.%s.%s' has been uploaded!"),
+                                           selected_module,
+                                           selected_branch,
+                                           selected_team,
+                                           selected_domain);
+
+  gtk_dialog_run (GTK_DIALOG (success_dialog));
+  gtk_widget_destroy (success_dialog);
+  gtr_notebook_enable_upload (active_notebook, FALSE);
+}
+
 /*
  * "Save as" dialog.
  */
diff --git a/src/gtr-actions.h b/src/gtr-actions.h
index 358b60f5..6af2a9f2 100644
--- a/src/gtr-actions.h
+++ b/src/gtr-actions.h
@@ -24,6 +24,7 @@
 
 #include "gtr-window.h"
 #include "gtr-search-bar.h"
+#include <libsoup/soup.h>
 
 G_BEGIN_DECLS
 /*File*/
@@ -51,6 +52,8 @@ void gtr_save_current_file_dialog (GtkWidget * widget, GtrWindow * window);
 
 void gtr_save_file_as_dialog (GtkAction * action, GtrWindow * window);
 
+void gtr_upload_file_dialog (GtkAction * action, GtrWindow * window);
+
 gboolean gtr_open (GFile * location, GtrWindow * window, GError ** error);
 
 void gtr_close_tab (GtrTab * tab, GtrWindow * window);
diff --git a/src/gtr-application.c b/src/gtr-application.c
index 2612733f..b52202d3 100644
--- a/src/gtr-application.c
+++ b/src/gtr-application.c
@@ -406,6 +406,16 @@ quit_activated (GSimpleAction *action,
   g_application_quit (G_APPLICATION (app));
 }
 
+static void
+upload_file_activated (GSimpleAction *action,
+                GVariant      *parameter,
+                gpointer       user_data)
+{
+  GtrApplication *app = GTR_APPLICATION (user_data);
+  GtrApplicationPrivate *priv = gtr_application_get_instance_private (app);
+  gtr_upload_file_dialog (NULL, priv->active_window);
+}
+
 static void
 saveas_activated (GSimpleAction *action,
                 GVariant      *parameter,
@@ -577,6 +587,8 @@ static GActionEntry app_entries[] = {
   { "save", save_activated, NULL, NULL, NULL },
   { "saveas", saveas_activated, NULL, NULL, NULL },
 
+  { "upload_file", upload_file_activated, NULL, NULL, NULL },
+
   { "open", open_activated, NULL, NULL, NULL },
   { "dl", dl_activated, NULL, NULL, NULL },
 
@@ -665,6 +677,7 @@ gtr_application_startup (GApplication *application)
   set_kb (application, "app.dl", "<Ctrl>d");
   set_kb (application, "app.save", "<Ctrl>s");
   set_kb (application, "app.saveas", "<Ctrl><Shift>s");
+  set_kb (application, "app.upload_file", "<Ctrl>b");
   set_kb (application, "app.preferences", "<Ctrl>p");
   set_kb (application, "app.quit", "<Primary>q");
 
diff --git a/src/gtr-dl-teams.c b/src/gtr-dl-teams.c
index fb22899d..33b8aae6 100644
--- a/src/gtr-dl-teams.c
+++ b/src/gtr-dl-teams.c
@@ -74,7 +74,7 @@ static void team_add_cb (GtkButton *btn, GtrDlTeams *self);
 static void gtr_dl_teams_save_combo_selected (GtkWidget *widget, GtrDlTeams *self);
 static void gtr_dl_teams_load_po_file (GtkButton *button, GtrDlTeams *self);
 static void gtr_dl_teams_get_file_info (GtrDlTeams *self);
-static void gtr_dl_teams_reserve_for_translation(GtkButton *button, GtrDlTeams *self);
+static void gtr_dl_teams_reserve_for_translation (GtkButton *button, GtrDlTeams *self);
 
 static void
 gtr_dl_teams_list_add (JsonArray *array,
@@ -586,7 +586,7 @@ gtr_dl_teams_load_po_file (GtkButton *button, GtrDlTeams *self)
 
 /* Reserve for translation */
 static void
-gtr_dl_teams_reserve_for_translation(GtkButton *button, GtrDlTeams *self)
+gtr_dl_teams_reserve_for_translation (GtkButton *button, GtrDlTeams *self)
 {
   GtrDlTeamsPrivate *priv = gtr_dl_teams_get_instance_private (self);
   GtrProfileManager *pmanager = NULL;
diff --git a/src/gtr-notebook.c b/src/gtr-notebook.c
index 5da45877..80c8eb20 100644
--- a/src/gtr-notebook.c
+++ b/src/gtr-notebook.c
@@ -37,6 +37,7 @@ typedef struct
   GtkWidget *sort_id;
   GtkWidget *order_menu_popover;
   GtkWidget *search;
+  GtkWidget *upload;
 
   GtkWidget *undo;
   GtkWidget *redo;
@@ -148,6 +149,7 @@ gtr_notebook_class_init (GtrNotebookClass * klass)
   gtk_widget_class_bind_template_child_private (widget_class, GtrNotebook, undo);
   gtk_widget_class_bind_template_child_private (widget_class, GtrNotebook, redo);
   gtk_widget_class_bind_template_child_private (widget_class, GtrNotebook, save);
+  gtk_widget_class_bind_template_child_private (widget_class, GtrNotebook, upload);
 }
 
 /***************************** Public funcs ***********************************/
@@ -268,6 +270,13 @@ gtr_notebook_enable_save (GtrNotebook *notebook,
   gtk_widget_set_sensitive (priv->save, enable);
 }
 
+void
+gtr_notebook_enable_upload (GtrNotebook *notebook, gboolean enable)
+{
+  GtrNotebookPrivate *priv = gtr_notebook_get_instance_private (notebook);
+  gtk_widget_set_sensitive (priv->upload, enable);
+}
+
 void
 gtr_notebook_update_undo_buttons (GtrNotebook *notebook,
                                   GtrView     *view)
@@ -312,3 +321,4 @@ gtr_notebook_enable_find_button (GtrNotebook *notebook,
   if (priv->search)
     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (priv->search), enable);
 }
+
diff --git a/src/gtr-notebook.h b/src/gtr-notebook.h
index af579ca8..6f7084b7 100644
--- a/src/gtr-notebook.h
+++ b/src/gtr-notebook.h
@@ -77,6 +77,8 @@ GtkWidget *gtr_notebook_get_header (GtrNotebook *notebook);
 
 void gtr_notebook_enable_save (GtrNotebook *notebook, gboolean enable);
 
+void gtr_notebook_enable_upload (GtrNotebook *notebook, gboolean enable);
+
 void gtr_notebook_update_undo_buttons (GtrNotebook *notebook, GtrView *view);
 
 void gtr_notebook_reset_sort (GtrNotebook *notebook);
diff --git a/src/gtr-notebook.ui b/src/gtr-notebook.ui
index 0b8a8732..62153351 100644
--- a/src/gtr-notebook.ui
+++ b/src/gtr-notebook.ui
@@ -656,6 +656,28 @@
             <property name="position">1</property>
             <property name="non_homogeneous">True</property>
           </packing>
+        </child>
+         <child>
+          <object class="GtkButton" id="upload">
+            <property name="visible">True</property>
+            <property name="can_focus">True</property>
+            <property name="receives_default">True</property>
+            <property name="tooltip_text" translatable="yes">Upload file (&lt;Ctrl&gt;b)</property>
+            <property name="action_name">app.upload_file</property>
+            <child>
+              <object class="GtkImage">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="icon_name">document-send-symbolic</property>
+              </object>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">True</property>
+            <property name="fill">True</property>
+            <property name="position">2</property>
+            <property name="non_homogeneous">True</property>
+          </packing>
         </child>
         <style>
           <class name="horizontal"/>
diff --git a/src/gtr-po.c b/src/gtr-po.c
index 1d3941f5..6b8be9b7 100644
--- a/src/gtr-po.c
+++ b/src/gtr-po.c
@@ -1393,3 +1393,45 @@ gtr_po_check_po_file (GtrPo * po)
 
   return message_error;
 }
+
+const gchar *
+gtr_po_get_dl_team (GtrPo *po)
+{
+  GtrPoPrivate *priv = gtr_po_get_instance_private (po);
+  return priv->dl_team;
+}
+
+const gchar *
+gtr_po_get_dl_module (GtrPo *po)
+{
+  GtrPoPrivate *priv = gtr_po_get_instance_private (po);
+  return priv->dl_module;
+}
+
+const gchar *
+gtr_po_get_dl_branch (GtrPo *po)
+{
+  GtrPoPrivate *priv = gtr_po_get_instance_private (po);
+  return priv->dl_branch;
+}
+
+const gchar *
+gtr_po_get_dl_domain (GtrPo *po)
+{
+  GtrPoPrivate *priv = gtr_po_get_instance_private (po);
+  return priv->dl_domain;
+}
+
+const gchar *
+gtr_po_get_dl_module_state (GtrPo *po)
+{
+  GtrPoPrivate *priv = gtr_po_get_instance_private (po);
+  return priv->dl_state;
+}
+
+gboolean
+gtr_po_can_dl_upload (GtrPo *po)
+{
+  GtrPoPrivate *priv = gtr_po_get_instance_private (po);
+  return g_strcmp0 (priv->dl_state, "Translating") == 0;
+}
diff --git a/src/gtr-po.h b/src/gtr-po.h
index 2f5a9e4d..c710508b 100644
--- a/src/gtr-po.h
+++ b/src/gtr-po.h
@@ -107,6 +107,18 @@ gtr_po_get_type (void)
      void gtr_po_set_dl_info (GtrPo * po, gchar * team, gchar * module_name,
                               gchar * branch, gchar * domain, gchar * module_state);
 
+     const gchar *gtr_po_get_dl_team (GtrPo * po);
+
+     const gchar *gtr_po_get_dl_module (GtrPo * po);
+
+     const gchar *gtr_po_get_dl_branch (GtrPo * po);
+
+     const gchar *gtr_po_get_dl_domain (GtrPo * po);
+
+     const gchar *gtr_po_get_dl_module_state (GtrPo * po);
+
+     gboolean gtr_po_can_dl_upload (GtrPo * po);
+
      GFile *gtr_po_get_location (GtrPo * po);
 
      void gtr_po_set_location (GtrPo * po, GFile * location);
diff --git a/src/gtr-window.c b/src/gtr-window.c
index e5abad1d..ece9c045 100644
--- a/src/gtr-window.c
+++ b/src/gtr-window.c
@@ -243,7 +243,10 @@ update_saved_state (GtrPo *po,
                     GParamSpec *param,
                     gpointer window)
 {
+  GtrNotebook *active_notebook;
+  active_notebook = gtr_window_get_notebook (window);
   set_window_title (GTR_WINDOW (window), TRUE);
+  gtr_notebook_enable_upload (active_notebook, gtr_po_can_dl_upload (po));
 }
 
 static void
@@ -536,7 +539,6 @@ gtr_window_create_tab (GtrWindow * window, GtrPo * po)
                           G_CALLBACK
                           (update_saved_state),
                           window);
-
   return tab;
 }
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]