From 91df49e00a5404a0c934a19a790112348ee5490b Mon Sep 17 00:00:00 2001 From: afshan ahmed khan Date: Fri, 22 Apr 2022 19:28:32 +0530 Subject: [PATCH 1/4] Fixing npluarals inconsistency issue between file and profile . Fixes #152 --- src/gtr-po.c | 71 +++++++++++++++++++++++++++++++++++++++ src/gtr-po.h | 4 +++ src/gtr-profile-manager.c | 1 - src/gtr-tab.c | 52 +++++++++++++++++++++++++++- 4 files changed, 126 insertions(+), 2 deletions(-) diff --git a/src/gtr-po.c b/src/gtr-po.c index 506d2d76..0355c7ea 100644 --- a/src/gtr-po.c +++ b/src/gtr-po.c @@ -27,6 +27,7 @@ * Gediminas Paulauskas */ +#include "gtr-header.h" #ifdef HAVE_CONFIG_H #include #endif @@ -38,6 +39,7 @@ #include "gtr-msg.h" #include "gtr-enum-types.h" #include "gtr-profile.h" +#include "gtr-profile-manager.h" #include "gtr-utils.h" #include "gtr-message-container.h" #include "gtr-preferences-dialog.h" @@ -129,6 +131,14 @@ enum PROP_STATE }; +enum +{ + FILE_INCONSISTENT_WITH_PROFILE, + NO_OF_SIGNALS +}; + +guint signals[NO_OF_SIGNALS]; + static gchar *message_error = NULL; static void @@ -331,6 +341,13 @@ gtr_po_class_init (GtrPoClass * klass) GTR_TYPE_PO_STATE, GTR_PO_STATE_SAVED, G_PARAM_READABLE)); + /* Signals */ + signals[FILE_INCONSISTENT_WITH_PROFILE] = + g_signal_new ("file-is-inconsistent-with-profile", + G_OBJECT_CLASS_TYPE (klass), + G_SIGNAL_RUN_LAST, + 0,NULL,NULL,g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); } /* @@ -1401,6 +1418,54 @@ gtr_po_check_po_file (GtrPo * po) return message_error; } +/** + * gtr_po_consistent_with_profile + * @po: a #GtrPo + * + * Tests whether the po file is consistent or not with profile values + * Returns: If the po file is not consistent with profile then it returns 0 . + **/ +int gtr_po_consistent_with_profile(GtrPo * po){ + GtrPoPrivate *priv; + GtrProfileManager *prof_manager; + GtrProfile *profile; + gint po_header_nplurals; + gint profile_nplurals; + + priv= gtr_po_get_instance_private(po); + po_message_iterator_t iter = po_message_iterator (priv->gettext_po_file, NULL); + GtrHeader *header = gtr_header_new (iter, po_next_message(iter)); + po_header_nplurals = gtr_header_get_nplurals(header); + + prof_manager = gtr_profile_manager_get_default (); + profile = gtr_profile_manager_get_active_profile (prof_manager); + gchar *pointer = g_strrstr (gtr_profile_get_plural_forms(profile), "nplurals"); + if (pointer != NULL) + { + while (*pointer != '\0' && *pointer != '=') + pointer++; + + if (*pointer != '\0') + { + pointer++; + while (*pointer != '\0' && *pointer == ' ') + pointer++; + + if (*pointer == '\0') + return 0; + } + else + return 0; + + profile_nplurals = g_ascii_digit_value (*pointer); + } + + if (profile_nplurals == po_header_nplurals) + return 1; + else + return 0; +} + const gchar * gtr_po_get_dl_team (GtrPo *po) { @@ -1442,3 +1507,9 @@ gtr_po_can_dl_upload (GtrPo *po) GtrPoPrivate *priv = gtr_po_get_instance_private (po); return g_strcmp0 (priv->dl_state, "Translating") == 0; } + +void +gtr_po_emit_file_not_consistent (GtrPo *po) +{ + g_signal_emit (G_OBJECT(po), signals[FILE_INCONSISTENT_WITH_PROFILE], 0); +} diff --git a/src/gtr-po.h b/src/gtr-po.h index 6d3089e1..27828561 100644 --- a/src/gtr-po.h +++ b/src/gtr-po.h @@ -152,7 +152,11 @@ gtr_po_get_message_position (GtrPo * po); gchar *gtr_po_check_po_file (GtrPo * po); +void +gtr_po_emit_file_not_consistent (GtrPo * po); +int +gtr_po_consistent_with_profile (GtrPo * po); /* Unexported funcs */ void _gtr_po_increase_decrease_translated (GtrPo * po, gboolean increase); diff --git a/src/gtr-profile-manager.c b/src/gtr-profile-manager.c index 81eb1286..7c7b8399 100644 --- a/src/gtr-profile-manager.c +++ b/src/gtr-profile-manager.c @@ -382,7 +382,6 @@ gtr_profile_manager_set_active_profile (GtrProfileManager *manager, priv->active_profile = profile; g_signal_emit (G_OBJECT (manager), signals[ACTIVE_PROFILE_CHANGED], 0, profile); - save_profiles (manager); } diff --git a/src/gtr-tab.c b/src/gtr-tab.c index 93b9059b..04543c1b 100644 --- a/src/gtr-tab.c +++ b/src/gtr-tab.c @@ -28,6 +28,7 @@ * Thomas Ziehmer */ +#include "gtr-profile.h" #ifdef HAVE_CONFIG_H #include #endif @@ -48,6 +49,7 @@ #include "gtr-progress.h" #include "gtr-actions.h" #include "gtr-utils.h" +#include "gtr-profile-manager.h" #include #include @@ -261,6 +263,40 @@ show_hide_revealer (GtkWidget *widget, GdkEvent *ev, GtrTab *tab) return TRUE; } +static void +handle_file_is_inconsistent (GtrPo *po, GtrTab *tab) +{ + GtrTabPrivate *priv = gtr_tab_get_instance_private (tab); + GtrProfileManager *manager = gtr_profile_manager_get_default (); + GtrProfile *active_profile = gtr_profile_manager_get_active_profile (manager); + const gchar* profile_name = gtr_profile_get_name (active_profile); + + gchar* info_msg_primary = g_strdup_printf ("File is not consistent with profile %s",profile_name); + gchar *filename = g_file_get_path (gtr_po_get_location (po)); + gchar* info_msg_secondary = g_strdup_printf ("Kindly go to preferences and select a profile with consistent nplurals values as this file %s",filename); + gtr_tab_set_info (tab, info_msg_primary, info_msg_secondary); + + GtkWidget *nb = priv->trans_notebook; + gtk_widget_set_sensitive (nb, FALSE); +} + +static void +on_active_profile_changed (GtrProfileManager *manager, GtrProfile *profile, GtrTab *tab) +{ + GtrTabPrivate *priv = gtr_tab_get_instance_private (tab); + GtkWidget *nb = priv->trans_notebook; + + GtrPo *po = priv->po; + if (!gtr_po_consistent_with_profile (po)) + { + gtr_po_emit_file_not_consistent (po); + } + else + { + gtk_widget_set_sensitive (nb, TRUE); + } +} + static void install_autosave_timeout (GtrTab * tab) { @@ -688,7 +724,7 @@ update_status (GtrTab * tab, GtrMsg * msg, gpointer useless) else gtk_label_set_text (GTK_LABEL (priv->msgid_tags), ""); - /* We need to update the tab state too if is neccessary */ + /* We need to update the tab state too if is necessary */ if (po_state != GTR_PO_STATE_MODIFIED) gtr_po_set_state (priv->po, GTR_PO_STATE_MODIFIED); } @@ -1033,9 +1069,12 @@ gtr_tab_new (GtrPo * po, { GtrTab *tab; GtrTabPrivate *priv; + GtrProfileManager *manager; g_return_val_if_fail (po != NULL, NULL); + manager = gtr_profile_manager_get_default(); + tab = g_object_new (GTR_TYPE_TAB, NULL); priv = gtr_tab_get_instance_private (tab); @@ -1052,6 +1091,12 @@ gtr_tab_new (GtrPo * po, g_signal_connect (po, "notify::state", G_CALLBACK (on_state_notify), tab); + g_signal_connect (po, "file-is-inconsistent-with-profile", + G_CALLBACK (handle_file_is_inconsistent), tab); + + g_signal_connect (manager, "active-profile-changed", + G_CALLBACK (on_active_profile_changed), tab); + install_autosave_timeout_if_needed (tab); /* Now we have to initialize the number of msgstr tabs */ @@ -1060,6 +1105,11 @@ gtr_tab_new (GtrPo * po, gtr_message_table_populate (GTR_MESSAGE_TABLE (priv->message_table), GTR_MESSAGE_CONTAINER (priv->po)); + if (!gtr_po_consistent_with_profile (po)) + { + gtr_po_emit_file_not_consistent (po); + } + gtk_widget_show (GTK_WIDGET (tab)); return tab; } -- GitLab From 1ec77e118532bef3c5f5ef00935152ab44bee136 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Garc=C3=ADa=20Moreno?= Date: Thu, 2 Jun 2022 16:52:01 +0200 Subject: [PATCH 2/4] Improve nplurals inconsistency code * Move parse_nplurals_header to a new function in utils, to use the same function in the two places it's used * Do not create a new GtrHeader object in gtr_po_consistent_with_profile, use the one existing in the GtrPo. * Some code styling improvements --- src/gtr-header.c | 27 ++------------------------- src/gtr-po.c | 45 ++++++++++++--------------------------------- src/gtr-po.h | 2 +- src/gtr-utils.c | 28 ++++++++++++++++++++++++++++ src/gtr-utils.h | 2 ++ 5 files changed, 45 insertions(+), 59 deletions(-) diff --git a/src/gtr-header.c b/src/gtr-header.c index 02f53776..9a6f4082 100644 --- a/src/gtr-header.c +++ b/src/gtr-header.c @@ -72,7 +72,7 @@ gtr_header_set_field (GtrHeader * header, static void parse_nplurals (GtrHeader * header) { - gchar *pointer, *plural_forms; + gchar *plural_forms; gboolean use_profile_values; GtrHeaderPrivate *priv = gtr_header_get_instance_private (header); @@ -111,30 +111,7 @@ parse_nplurals (GtrHeader * header) return; } - pointer = g_strrstr (plural_forms, "nplurals"); - - if (pointer != NULL) - { - while (*pointer != '\0' && *pointer != '=') - pointer++; - - if (*pointer != '\0') - { - pointer++; - while (*pointer != '\0' && *pointer == ' ') - pointer++; - - if (*pointer == '\0') - return; - } - else - return; - - priv->nplurals = g_ascii_digit_value (*pointer); - } - - /*g_message ("nplurals: %d", priv->nplurals); */ - + priv->nplurals = parse_nplurals_header (plural_forms); g_free (plural_forms); } diff --git a/src/gtr-po.c b/src/gtr-po.c index 0355c7ea..75ebe49a 100644 --- a/src/gtr-po.c +++ b/src/gtr-po.c @@ -27,7 +27,6 @@ * Gediminas Paulauskas */ -#include "gtr-header.h" #ifdef HAVE_CONFIG_H #include #endif @@ -346,7 +345,8 @@ gtr_po_class_init (GtrPoClass * klass) g_signal_new ("file-is-inconsistent-with-profile", G_OBJECT_CLASS_TYPE (klass), G_SIGNAL_RUN_LAST, - 0,NULL,NULL,g_cclosure_marshal_VOID__VOID, + 0, NULL, NULL, + g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); } @@ -1425,45 +1425,24 @@ gtr_po_check_po_file (GtrPo * po) * Tests whether the po file is consistent or not with profile values * Returns: If the po file is not consistent with profile then it returns 0 . **/ -int gtr_po_consistent_with_profile(GtrPo * po){ - GtrPoPrivate *priv; +gboolean +gtr_po_consistent_with_profile (GtrPo * po) +{ GtrProfileManager *prof_manager; GtrProfile *profile; gint po_header_nplurals; - gint profile_nplurals; + gint profile_nplurals = -1; - priv= gtr_po_get_instance_private(po); - po_message_iterator_t iter = po_message_iterator (priv->gettext_po_file, NULL); - GtrHeader *header = gtr_header_new (iter, po_next_message(iter)); - po_header_nplurals = gtr_header_get_nplurals(header); + GtrHeader *header = gtr_po_get_header (po); + po_header_nplurals = gtr_header_get_nplurals (header); prof_manager = gtr_profile_manager_get_default (); profile = gtr_profile_manager_get_active_profile (prof_manager); - gchar *pointer = g_strrstr (gtr_profile_get_plural_forms(profile), "nplurals"); - if (pointer != NULL) - { - while (*pointer != '\0' && *pointer != '=') - pointer++; - - if (*pointer != '\0') - { - pointer++; - while (*pointer != '\0' && *pointer == ' ') - pointer++; - - if (*pointer == '\0') - return 0; - } - else - return 0; - - profile_nplurals = g_ascii_digit_value (*pointer); - } + profile_nplurals = parse_nplurals_header ( + gtr_profile_get_plural_forms (profile) + ); - if (profile_nplurals == po_header_nplurals) - return 1; - else - return 0; + return profile_nplurals == po_header_nplurals; } const gchar * diff --git a/src/gtr-po.h b/src/gtr-po.h index 27828561..520c54e8 100644 --- a/src/gtr-po.h +++ b/src/gtr-po.h @@ -155,7 +155,7 @@ gtr_po_get_message_position (GtrPo * po); void gtr_po_emit_file_not_consistent (GtrPo * po); -int +gboolean gtr_po_consistent_with_profile (GtrPo * po); /* Unexported funcs */ void diff --git a/src/gtr-utils.c b/src/gtr-utils.c index c89d1514..75655019 100644 --- a/src/gtr-utils.c +++ b/src/gtr-utils.c @@ -818,3 +818,31 @@ gtk_list_box_remove (GtkListBox *box, GtkWidget *child) { gtk_container_remove (GTK_CONTAINER (box), child); } + +// TODO: Improve this parser, this string parsing is weak +// It could be better to use GRegex: https://docs.gtk.org/glib/method.Regex.match.html +int +parse_nplurals_header (const gchar * plurals_header) +{ + gchar * pointer = g_strrstr (plurals_header, "nplurals"); + + if (!pointer) + return -1; + + while (*pointer != '\0' && *pointer != '=') + pointer++; + + if (*pointer != '\0') + { + pointer++; + while (*pointer != '\0' && *pointer == ' ') + pointer++; + + if (*pointer == '\0') + return -1; + } + else + return -1; + + return g_ascii_digit_value (*pointer); +} diff --git a/src/gtr-utils.h b/src/gtr-utils.h index 10aea191..78362d6e 100644 --- a/src/gtr-utils.h +++ b/src/gtr-utils.h @@ -86,4 +86,6 @@ void gtr_utils_menu_position_under_tree_view (GtkMenu * menu, void gtk_list_box_append (GtkListBox *box, GtkWidget *child); void gtk_list_box_remove (GtkListBox *box, GtkWidget *child); + + int parse_nplurals_header (const gchar * plurals_header); #endif -- GitLab From 02ff0dbc4cab0d5c80aee369b1397e1b496d1200 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Garc=C3=ADa=20Moreno?= Date: Thu, 2 Jun 2022 17:02:57 +0200 Subject: [PATCH 3/4] Edit profile trigger nplural inconsistency check --- src/gtr-tab.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/gtr-tab.c b/src/gtr-tab.c index 04543c1b..5e7cb5fb 100644 --- a/src/gtr-tab.c +++ b/src/gtr-tab.c @@ -297,6 +297,16 @@ on_active_profile_changed (GtrProfileManager *manager, GtrProfile *profile, GtrT } } +static void +on_profile_modified (GtrProfileManager *manager, + GtrProfile *old_profile, + GtrProfile *new_profile, + GtrTab *tab) +{ + on_active_profile_changed (manager, new_profile, tab); +} + + static void install_autosave_timeout (GtrTab * tab) { @@ -1097,6 +1107,9 @@ gtr_tab_new (GtrPo * po, g_signal_connect (manager, "active-profile-changed", G_CALLBACK (on_active_profile_changed), tab); + g_signal_connect (manager, "profile-modified", + G_CALLBACK (on_profile_modified), tab); + install_autosave_timeout_if_needed (tab); /* Now we have to initialize the number of msgstr tabs */ -- GitLab From a8a77afc619a6cd0ae8e695b88155ae76a1946fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Garc=C3=ADa=20Moreno?= Date: Thu, 2 Jun 2022 17:25:57 +0200 Subject: [PATCH 4/4] Improve memory management in nplural inconsistency check This patch removes some memory leaks in the handle_file_is_inconsistent function. --- src/gtr-po.c | 2 ++ src/gtr-tab.c | 27 ++++++++++++++++++++++----- 2 files changed, 24 insertions(+), 5 deletions(-) diff --git a/src/gtr-po.c b/src/gtr-po.c index 75ebe49a..a894189d 100644 --- a/src/gtr-po.c +++ b/src/gtr-po.c @@ -1442,6 +1442,8 @@ gtr_po_consistent_with_profile (GtrPo * po) gtr_profile_get_plural_forms (profile) ); + g_object_unref (prof_manager); + return profile_nplurals == po_header_nplurals; } diff --git a/src/gtr-tab.c b/src/gtr-tab.c index 5e7cb5fb..1547300c 100644 --- a/src/gtr-tab.c +++ b/src/gtr-tab.c @@ -269,15 +269,32 @@ handle_file_is_inconsistent (GtrPo *po, GtrTab *tab) GtrTabPrivate *priv = gtr_tab_get_instance_private (tab); GtrProfileManager *manager = gtr_profile_manager_get_default (); GtrProfile *active_profile = gtr_profile_manager_get_active_profile (manager); - const gchar* profile_name = gtr_profile_get_name (active_profile); - - gchar* info_msg_primary = g_strdup_printf ("File is not consistent with profile %s",profile_name); - gchar *filename = g_file_get_path (gtr_po_get_location (po)); - gchar* info_msg_secondary = g_strdup_printf ("Kindly go to preferences and select a profile with consistent nplurals values as this file %s",filename); + const char *profile_name = gtr_profile_get_name (active_profile); + int profile_nplurals = -1; + int po_nplurals = -1; + + g_autofree char *info_msg_primary = NULL; + g_autofree char *info_msg_secondary = NULL; + g_autofree char *filename = NULL; + g_autoptr (GFile) po_file = gtr_po_get_location (po); + + filename = g_file_get_path (po_file); + po_nplurals = gtr_header_get_nplurals (gtr_po_get_header (po)); + profile_nplurals = parse_nplurals_header (gtr_profile_get_plural_forms (active_profile)); + + info_msg_primary = g_strdup_printf ("File is not consistent with profile %s", profile_name); + info_msg_secondary = g_strdup_printf ( + "File nplurals: %d, is different from profile nplurals %d.\n" + "Kindly go to preferences and select a profile with consistent nplurals " + "values as this file %s.", + po_nplurals, profile_nplurals, filename + ); gtr_tab_set_info (tab, info_msg_primary, info_msg_secondary); GtkWidget *nb = priv->trans_notebook; gtk_widget_set_sensitive (nb, FALSE); + + g_object_unref (manager); } static void -- GitLab