[geany/geany-plugins] c4a2dc: pohelper: Add a stats dialog
Colomban Wendling
git-noreply at xxxxx
Mon Feb 16 22:59:17 UTC 2015
Branch: refs/heads/master
Author: Colomban Wendling <ban at herbesfolles.org>
Committer: Colomban Wendling <ban at herbesfolles.org>
Date: Mon, 17 Jun 2013 15:06:36 UTC
Commit: c4a2dc18d85fb694a5b21bec54781b5cfaec265b
https://github.com/geany/geany-plugins/commit/c4a2dc18d85fb694a5b21bec54781b5cfaec265b
Log Message:
-----------
pohelper: Add a stats dialog
Modified Paths:
--------------
po/POTFILES.in
pohelper/data/Makefile.am
pohelper/data/menus.ui
pohelper/data/stats.ui
pohelper/src/gph-plugin.c
Modified: po/POTFILES.in
3 lines changed, 2 insertions(+), 1 deletions(-)
===================================================================
@@ -211,11 +211,12 @@ gproject/src/gproject-sidebar.c
markdown/src/conf.c
markdown/src/plugin.c
-
# Pairtaghighlighter
pairtaghighlighter/src/pair_tag_highlighter.c
+
# PoHelper
[type: gettext/glade]pohelper/data/menus.ui
+[type: gettext/glade]pohelper/data/stats.ui
pohelper/src/gph-plugin.c
# Pretty-printer
Modified: pohelper/data/Makefile.am
2 lines changed, 1 insertions(+), 1 deletions(-)
===================================================================
@@ -1,4 +1,4 @@
include $(top_srcdir)/build/vars.docs.mk
plugin = pohelper
-dist_plugindata_DATA = menus.ui
+dist_plugindata_DATA = menus.ui stats.ui
Modified: pohelper/data/menus.ui
16 lines changed, 16 insertions(+), 0 deletions(-)
===================================================================
@@ -224,6 +224,22 @@
</object>
</child>
<child>
+ <object class="GtkMenuItem" id="show_stats">
+ <property name="use_action_appearance">False</property>
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="tooltip_text" translatable="yes">Show statistics of the current document</property>
+ <property name="label" translatable="yes">_Show stats</property>
+ <property name="use_underline">True</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkSeparatorMenuItem" id="separator6">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ </object>
+ </child>
+ <child>
<object class="GtkCheckMenuItem" id="update_headers_upon_save">
<property name="use_action_appearance">False</property>
<property name="visible">True</property>
Modified: pohelper/data/stats.ui
222 lines changed, 222 insertions(+), 0 deletions(-)
===================================================================
@@ -0,0 +1,222 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <requires lib="gtk+" version="2.16"/>
+ <!-- interface-naming-policy toplevel-contextual -->
+ <object class="GtkDialog" id="dialog">
+ <property name="can_focus">False</property>
+ <property name="border_width">5</property>
+ <property name="title" translatable="yes">Translation statistics</property>
+ <property name="modal">True</property>
+ <property name="type_hint">dialog</property>
+ <child internal-child="vbox">
+ <object class="GtkVBox" id="dialog-vbox1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="spacing">2</property>
+ <child internal-child="action_area">
+ <object class="GtkHButtonBox" id="dialog-action_area1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="layout_style">end</property>
+ <child>
+ <object class="GtkButton" id="button1">
+ <property name="label">gtk-close</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="has_focus">True</property>
+ <property name="can_default">True</property>
+ <property name="receives_default">True</property>
+ <property name="use_stock">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="pack_type">end</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkVBox" id="vbox1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="border_width">6</property>
+ <property name="spacing">5</property>
+ <child>
+ <object class="GtkDrawingArea" id="drawing_area">
+ <property name="height_request">24</property>
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkTable" id="table1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="n_rows">3</property>
+ <property name="n_columns">3</property>
+ <property name="column_spacing">6</property>
+ <child>
+ <object class="GtkColorButton" id="color_translated">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="relief">none</property>
+ <property name="title" translatable="yes">Choose a color for translated strings</property>
+ <property name="color">#7373d2d21616</property>
+ </object>
+ <packing>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options">GTK_FILL</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkColorButton" id="color_fuzzy">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="relief">none</property>
+ <property name="title" translatable="yes">Choose a color for fuzzily translated strings</property>
+ <property name="color">#ededd4d40000</property>
+ </object>
+ <packing>
+ <property name="top_attach">1</property>
+ <property name="bottom_attach">2</property>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options">GTK_FILL</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkColorButton" id="color_untranslated">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="relief">none</property>
+ <property name="title" translatable="yes">Choose a color for untranslated strings</property>
+ <property name="color">#cccc00000000</property>
+ </object>
+ <packing>
+ <property name="top_attach">2</property>
+ <property name="bottom_attach">3</property>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options">GTK_FILL</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">Translated:</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="y_options">GTK_FILL</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">Fuzzy:</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">1</property>
+ <property name="bottom_attach">2</property>
+ <property name="y_options">GTK_FILL</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label3">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">Untranslated:</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">2</property>
+ <property name="bottom_attach">3</property>
+ <property name="y_options">GTK_FILL</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="n_translated">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">0</property>
+ <property name="label">0</property>
+ </object>
+ <packing>
+ <property name="left_attach">2</property>
+ <property name="right_attach">3</property>
+ <property name="y_options">GTK_FILL</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="n_fuzzy">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">0</property>
+ <property name="label">0</property>
+ </object>
+ <packing>
+ <property name="left_attach">2</property>
+ <property name="right_attach">3</property>
+ <property name="top_attach">1</property>
+ <property name="bottom_attach">2</property>
+ <property name="y_options">GTK_FILL</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="n_untranslated">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">0</property>
+ <property name="label">0</property>
+ </object>
+ <packing>
+ <property name="left_attach">2</property>
+ <property name="right_attach">3</property>
+ <property name="top_attach">2</property>
+ <property name="bottom_attach">3</property>
+ <property name="y_options">GTK_FILL</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <action-widgets>
+ <action-widget response="-7">button1</action-widget>
+ </action-widgets>
+ </object>
+</interface>
Modified: pohelper/src/gph-plugin.c
388 lines changed, 387 insertions(+), 1 deletions(-)
===================================================================
@@ -57,16 +57,24 @@ enum {
GPH_KB_PASTE_UNTRANSLATED,
GPH_KB_REFLOW,
GPH_KB_TOGGLE_FUZZY,
+ GPH_KB_SHOW_STATS,
GPH_KB_COUNT
};
static struct Plugin {
gboolean update_headers;
+ /* stats dialog colors */
+ GdkColor color_translated;
+ GdkColor color_fuzzy;
+ GdkColor color_untranslated;
GtkWidget *menu_item;
} plugin = {
TRUE,
+ { 0, 0x7373, 0xd2d2, 0x1616 }, /* tango mid green */
+ { 0, 0xeded, 0xd4d4, 0x0000 }, /* tango mid yellow */
+ { 0, 0xcccc, 0x0000, 0x0000 }, /* tango mid red */
NULL
};
@@ -724,6 +732,70 @@ get_msgstr_text_at (GeanyDocument *doc,
return NULL;
}
+/* finds the start of the msgid text at @pos. the returned position is the
+ * start of the msgid text style, so it's on the first opening quote. Returns
+ * -1 if none found */
+static gint
+find_msgid_start_at (GeanyDocument *doc,
+ gint pos)
+{
+ if (doc_is_po (doc)) {
+ ScintillaObject *sci = doc->editor->sci;
+ gint style = sci_get_style_at (sci, pos);
+
+ /* find the previous non-default style */
+ while (pos > 0 && style == SCE_PO_DEFAULT) {
+ style = sci_get_style_at (sci, --pos);
+ }
+
+ /* if a msgid or msgstr, go to the msgstr keyword */
+ if (style == SCE_PO_MSGID_TEXT ||
+ style == SCE_PO_MSGSTR ||
+ style == SCE_PO_MSGSTR_TEXT) {
+ pos = find_style (sci, SCE_PO_MSGID, pos, 0);
+ if (pos >= 0)
+ style = SCE_PO_MSGID;
+ }
+
+ if (style == SCE_PO_MSGID) {
+ return find_style (sci, SCE_PO_MSGID_TEXT, pos, sci_get_length (sci));
+ }
+ }
+
+ return -1;
+}
+
+static GString *
+get_msgid_text_at (GeanyDocument *doc,
+ gint pos)
+{
+ pos = find_msgid_start_at (doc, pos);
+
+ if (pos >= 0) {
+ ScintillaObject *sci = doc->editor->sci;
+ GString *msgid = g_string_new (NULL);
+ gint length = sci_get_length (sci);
+
+ while (sci_get_style_at (sci, pos) == SCE_PO_MSGID_TEXT) {
+ pos++; /* skip opening quote */
+ while (sci_get_style_at (sci, pos + 1) == SCE_PO_MSGID_TEXT) {
+ g_string_append_c (msgid, sci_get_char_at (sci, pos));
+ pos++;
+ }
+ pos++; /* skip closing quote */
+
+ /* skip until next non-default style */
+ while (pos < length && sci_get_style_at (sci, pos) == SCE_PO_DEFAULT) {
+ pos++;
+ }
+ }
+
+ return msgid;
+ }
+
+ return NULL;
+}
+
/* cuts @str in human-readable chunks for max @len.
* cuts first at \n, then at spaces and punctuation */
static gchar **
@@ -948,6 +1020,21 @@ find_flags_line_at (GeanyDocument *doc,
return line;
}
+static GPtrArray *
+get_flags_at (GeanyDocument *doc,
+ gint pos)
+{
+ GPtrArray *flags = NULL;
+ gint line = find_flags_line_at (doc, pos);
+
+ if (line >= 0) {
+ flags = g_ptr_array_new ();
+ parse_flags_line (doc->editor->sci, line, flags);
+ }
+
+ return flags;
+}
+
/* adds or remove @flag from @flags. returns whether the flag was added */
static gboolean
toggle_flag (GPtrArray *flags,
@@ -1041,6 +1128,255 @@ on_kb_toggle_fuzziness (guint key_id)
}
}
+typedef struct {
+ gdouble translated;
+ gdouble fuzzy;
+ gdouble untranslated;
+} StatsGraphData;
+
+/*
+ * rounded_rectangle:
+ * @cr: a Cairo context
+ * @x: X coordinate of the top-left corner of the rectangle
+ * @y: Y coordinate of the top-left corner of the rectangle
+ * @width: width of the rectangle
+ * @height: height of the rectangle
+ * @r1: radius of the top-left corner
+ * @r2: radius of the top-right corner
+ * @r3: radius of the bottom-right corner
+ * @r4: radius of the bottom-left corner
+ *
+ * Creates a rectangle path with rounded corners.
+ *
+ * Warning: The rectangle should be big enough to include the corners,
+ * otherwise the result will be weird. For example, if all corners
+ * radius are set to 5, the rectangle should be at least 10x10.
+ */
+static void
+rounded_rectangle (cairo_t *cr,
+ gdouble x,
+ gdouble y,
+ gdouble width,
+ gdouble height,
+ gdouble r1,
+ gdouble r2,
+ gdouble r3,
+ gdouble r4)
+{
+ cairo_move_to (cr, x + r1, y);
+ cairo_arc (cr, x + width - r2, y + r2, r2, -G_PI/2.0, 0);
+ cairo_arc (cr, x + width - r3, y + height - r3, r3, 0, G_PI/2.0);
+ cairo_arc (cr, x + r4, y + height - r4, r4, G_PI/2.0, -G_PI);
+ cairo_arc (cr, x + r1, y + r1, r1, -G_PI, -G_PI/2.0);
+ cairo_close_path (cr);
+}
+
+#if ! GTK_CHECK_VERSION (3, 0, 0) && ! defined (gtk_widget_get_allocated_width)
+# define gtk_widget_get_allocated_width(w) (GTK_WIDGET (w)->allocation.width)
+#endif
+#if ! GTK_CHECK_VERSION (3, 0, 0) && ! defined (gtk_widget_get_allocated_height)
+# define gtk_widget_get_allocated_height(w) (GTK_WIDGET (w)->allocation.height)
+#endif
+
+static gboolean
+stats_graph_draw (GtkWidget *widget,
+ cairo_t *cr,
+ gpointer user_data)
+{
+ const StatsGraphData *data = user_data;
+ const gint width = gtk_widget_get_allocated_width (widget);
+ const gint height = gtk_widget_get_allocated_height (widget);
+ const gdouble translated = width * data->translated;
+ const gdouble fuzzy = width * data->fuzzy;
+ const gdouble untranslated = width * data->untranslated;
+ const gdouble r = MIN (width / 4, height / 4);
+ cairo_pattern_t *pat;
+
+ rounded_rectangle (cr, 0, 0, width, height, r, r, r, r);
+ cairo_clip (cr);
+
+ gdk_cairo_set_source_color (cr, &plugin.color_translated);
+ cairo_rectangle (cr, 0, 0, translated, height);
+ cairo_fill (cr);
+
+ gdk_cairo_set_source_color (cr, &plugin.color_fuzzy);
+ cairo_rectangle (cr, translated, 0, fuzzy, height);
+ cairo_fill (cr);
+
+ gdk_cairo_set_source_color (cr, &plugin.color_untranslated);
+ cairo_rectangle (cr, translated + fuzzy, 0, untranslated, height);
+ cairo_fill (cr);
+
+ /* draw a nice thin border */
+ cairo_set_line_width (cr, 1.0);
+ cairo_set_source_rgba (cr, 0, 0, 0, 0.2);
+ rounded_rectangle (cr, 0.5, 0.5, width - 1, height - 1, r, r, r, r);
+ cairo_stroke (cr);
+
+ /* draw a gradient to give the graph a little depth */
+ pat = cairo_pattern_create_linear (0, 0, 0, height);
+ cairo_pattern_add_color_stop_rgba (pat, 0, 1, 1, 1, 0.2);
+ cairo_pattern_add_color_stop_rgba (pat, height, 0, 0, 0, 0.2);
+ cairo_set_source (cr, pat);
+ cairo_pattern_destroy (pat);
+ cairo_rectangle (cr, 0, 0, width, height);
+ cairo_paint (cr);
+
+ return TRUE;
+}
+
+#if ! GTK_CHECK_VERSION (3, 0, 0)
+static gboolean
+on_stats_graph_expose_event (GtkWidget *widget,
+ GdkEvent *event,
+ gpointer data)
+{
+ cairo_t *cr = gdk_cairo_create (GDK_DRAWABLE (widget->window));
+ gboolean ret = stats_graph_draw (widget, cr, data);
+
+ cairo_destroy (cr);
+
+ return ret;
+}
+#endif
+
+static void
+on_color_button_color_notify (GtkWidget *widget,
+ GParamSpec *pspec,
+ gpointer user_data)
+{
+ gtk_color_button_get_color (GTK_COLOR_BUTTON (widget), user_data);
+}
+
+static void
+show_stats_dialog (guint all,
+ guint translated,
+ guint untranslated,
+ guint fuzzy)
+{
+ GError *error = NULL;
+ GtkBuilder *builder = gtk_builder_new ();
+
+ gtk_builder_set_translation_domain (builder, GETTEXT_PACKAGE);
+ if (! gtk_builder_add_from_file (builder, PKGDATADIR"/pohelper/stats.ui",
+ &error)) {
+ g_critical (_("Failed to load UI definition, please check your "
+ "installation. The error was: %s"), error->message);
+ g_error_free (error);
+ } else {
+ StatsGraphData data;
+ GObject *dialog;
+ GObject *drawing_area;
+
+ data.translated = all ? (translated * 1.0 / all) : 0;
+ data.fuzzy = all ? (fuzzy * 1.0 / all) : 0;
+ data.untranslated = all ? (untranslated * 1.0 / all) : 0;
+
+ drawing_area = gtk_builder_get_object (builder, "drawing_area");
+#if ! GTK_CHECK_VERSION (3, 0, 0)
+ g_signal_connect (drawing_area,
+ "expose-event", G_CALLBACK (on_stats_graph_expose_event),
+ &data);
+#else
+ g_signal_connect (drawing_area,
+ "draw", G_CALLBACK (stats_graph_draw),
+ &data);
+#endif
+
+ #define SET_LABEL_N(id, value) \
+ do { \
+ GObject *obj__ = gtk_builder_get_object (builder, (id)); \
+ \
+ if (! obj__) { \
+ g_warning ("Object \"%s\" is missing from the UI definition", (id)); \
+ } else { \
+ gchar *text__ = g_strdup_printf (_("%u (%.1f%%)"), \
+ (value), \
+ all ? ((value) * 100.0 / all) : 0); \
+ \
+ gtk_label_set_text (GTK_LABEL (obj__), text__); \
+ g_free (text__); \
+ } \
+ } while (0)
+
+ SET_LABEL_N ("n_translated", translated);
+ SET_LABEL_N ("n_fuzzy", fuzzy);
+ SET_LABEL_N ("n_untranslated", untranslated);
+
+ #undef SET_LABEL_N
+
+ #define BIND_COLOR_BTN(id, color) \
+ do { \
+ GObject *obj__ = gtk_builder_get_object (builder, (id)); \
+ \
+ if (! obj__) { \
+ g_warning ("Object \"%s\" is missing from the UI definition", (id)); \
+ } else { \
+ gtk_color_button_set_color (GTK_COLOR_BUTTON (obj__), (color)); \
+ g_signal_connect (obj__, "notify::color", \
+ G_CALLBACK (on_color_button_color_notify), \
+ (color)); \
+ /* queue a redraw on the drawing area so it uses the new color */ \
+ g_signal_connect_swapped (obj__, "notify::color", \
+ G_CALLBACK (gtk_widget_queue_draw), \
+ drawing_area); \
+ } \
+ } while (0)
+
+ BIND_COLOR_BTN ("color_translated", &plugin.color_translated);
+ BIND_COLOR_BTN ("color_fuzzy", &plugin.color_fuzzy);
+ BIND_COLOR_BTN ("color_untranslated", &plugin.color_untranslated);
+
+ #undef BIND_COLOR_BTN
+
+ dialog = gtk_builder_get_object (builder, "dialog");
+ gtk_window_set_transient_for (GTK_WINDOW (dialog),
+ GTK_WINDOW (geany_data->main_widgets->window));
+ gtk_dialog_run (GTK_DIALOG (dialog));
+ gtk_widget_destroy (GTK_WIDGET (dialog));
+ }
+ g_object_unref (builder);
+}
+
+static void
+on_kb_show_stats (guint key_id)
+{
+ GeanyDocument *doc = document_get_current ();
+
+ if (doc_is_po (doc)) {
+ const gint len = sci_get_length (doc->editor->sci);
+ gint pos = 0;
+ guint all = 0;
+ guint untranslated = 0;
+ guint fuzzy = 0;
+
+ while ((pos = find_message (doc, pos, len)) >= 0) {
+ GString *msgid = get_msgid_text_at (doc, pos);
+ GString *msgstr = get_msgstr_text_at (doc, pos);
+
+ if (msgid->len > 0) {
+ all++;
+ if (msgstr->len < 1) {
+ untranslated++;
+ } else {
+ GPtrArray *flags = get_flags_at (doc, pos);
+
+ if (flags) {
+ fuzzy += ! toggle_flag (flags, "fuzzy");
+
+ g_ptr_array_foreach (flags, (GFunc) g_free, NULL);
+ g_ptr_array_free (flags, TRUE);
+ }
+ }
+ }
+ g_string_free (msgstr, TRUE);
+ g_string_free (msgid, TRUE);
+ }
+
+ show_stats_dialog (all, all - untranslated - fuzzy, fuzzy, untranslated);
+ }
+}
+
static const struct Action {
guint id;
const gchar *name;
@@ -1083,7 +1419,10 @@ static const struct Action {
N_("Reflow the current translation string"), "reflow_translation" },
{ GPH_KB_TOGGLE_FUZZY, "toggle-fuzziness",
on_kb_toggle_fuzziness,
- N_("Toggle current translation fuzziness"), "toggle_fuzziness" }
+ N_("Toggle current translation fuzziness"), "toggle_fuzziness" },
+ { GPH_KB_SHOW_STATS, "show-stats",
+ on_kb_show_stats,
+ N_("Show statistics of the current document"), "show_stats" }
};
static void
@@ -1157,6 +1496,47 @@ write_keyfile (GKeyFile *kf,
return success;
}
+/*
+ * get_setting_color:
+ * @kf: a #GKeyFile from which load the color
+ * @group: the key file group
+ * @key: the key file key
+ * @color: (out): the color to fill with the read value. If the key is not
+ * found, the color isn't updated
+ *
+ * Loads a color from a key file entry.
+ *
+ * Returns: %TRUE if the color was loaded, %FALSE otherwise.
+ */
+static gboolean
+get_setting_color (GKeyFile *kf,
+ const gchar *group,
+ const gchar *key,
+ GdkColor *color)
+{
+ gboolean success = FALSE;
+ gchar *value = g_key_file_get_value (kf, group, key, NULL);
+
+ if (value) {
+ success = gdk_color_parse (value, color);
+ g_free (value);
+ }
+
+ return success;
+}
+
+static void
+set_setting_color (GKeyFile *kf,
+ const gchar *group,
+ const gchar *key,
+ const GdkColor *color)
+{
+ gchar *value = gdk_color_to_string (color);
+
+ g_key_file_set_value (kf, group, key, value);
+ g_free (value);
+}
+
static void
load_config (void)
{
@@ -1167,6 +1547,9 @@ load_config (void)
plugin.update_headers = utils_get_setting_boolean (kf, "general",
"update-headers",
plugin.update_headers);
+ get_setting_color (kf, "colors", "translated", &plugin.color_translated);
+ get_setting_color (kf, "colors", "fuzzy", &plugin.color_fuzzy);
+ get_setting_color (kf, "colors", "untranslated", &plugin.color_untranslated);
}
g_key_file_free (kf);
g_free (filename);
@@ -1181,6 +1564,9 @@ save_config (void)
load_keyfile (kf, filename, G_KEY_FILE_KEEP_COMMENTS);
g_key_file_set_boolean (kf, "general", "update-headers",
plugin.update_headers);
+ set_setting_color (kf, "colors", "translated", &plugin.color_translated);
+ set_setting_color (kf, "colors", "fuzzy", &plugin.color_fuzzy);
+ set_setting_color (kf, "colors", "untranslated", &plugin.color_untranslated);
write_keyfile (kf, filename);
g_key_file_free (kf);
--------------
This E-Mail was brought to you by github_commit_mail.py (Source: https://github.com/geany/infrastructure).
More information about the Plugins-Commits
mailing list