[gthumb] filter: added a custom control for selecting aspect ratios
- From: Paolo Bacchilega <paobac src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gthumb] filter: added a custom control for selecting aspect ratios
- Date: Mon, 1 May 2017 14:50:30 +0000 (UTC)
commit ec091e85aedd0dcea5f77dc2044184b62ab4e4ff
Author: Paolo Bacchilega <paobac src gnome org>
Date: Mon May 1 15:24:12 2017 +0200
filter: added a custom control for selecting aspect ratios
gthumb/Makefile.am | 2 +
gthumb/gth-main-default-tests.c | 27 +--
gthumb/gth-test-aspect-ratio.c | 467 +++++++++++++++++++++++++++++++++++++++
gthumb/gth-test-aspect-ratio.h | 52 +++++
4 files changed, 523 insertions(+), 25 deletions(-)
---
diff --git a/gthumb/Makefile.am b/gthumb/Makefile.am
index 445aaa3..9c3f087 100644
--- a/gthumb/Makefile.am
+++ b/gthumb/Makefile.am
@@ -105,6 +105,7 @@ PUBLIC_HEADER_FILES = \
gth-tags-file.h \
gth-task.h \
gth-test.h \
+ gth-test-aspect-ratio.h \
gth-test-category.h \
gth-test-chain.h \
gth-test-selector.h \
@@ -255,6 +256,7 @@ gthumb_SOURCES = \
gth-tags-file.c \
gth-task.c \
gth-test.c \
+ gth-test-aspect-ratio.c \
gth-test-category.c \
gth-test-chain.c \
gth-test-selector.c \
diff --git a/gthumb/gth-main-default-tests.c b/gthumb/gth-main-default-tests.c
index 0cb30ba..5d5294c 100644
--- a/gthumb/gth-main-default-tests.c
+++ b/gthumb/gth-main-default-tests.c
@@ -24,6 +24,7 @@
#include <glib/gi18n.h>
#include "glib-utils.h"
#include "gth-main.h"
+#include "gth-test-aspect-ratio.h"
#include "gth-test-category.h"
#include "gth-test-simple.h"
#include "gth-time.h"
@@ -275,27 +276,6 @@ get_embedded_rating_for_test (GthTest *test,
}
-static gint64
-get_aspect_ratio_for_test (GthTest *test,
- GthFileData *file,
- gconstpointer *data,
- GDestroyNotify *data_destroy_func)
-{
- int width;
- int height;
- gdouble ratio;
-
- width = g_file_info_get_attribute_int32(file->info, "frame::width");
- height = g_file_info_get_attribute_int32(file->info, "frame::height");
- if (height == 0)
- height = 1;
-
- ratio = (gdouble)width / (gdouble)height;
- *(gdouble*)data = ratio;
- return 0;
-}
-
-
void
gth_main_register_default_tests (void)
{
@@ -420,11 +400,8 @@ gth_main_register_default_tests (void)
NULL);
gth_main_register_object (GTH_TYPE_TEST,
"frame::aspect-ratio",
- GTH_TYPE_TEST_SIMPLE,
+ GTH_TYPE_TEST_ASPECT_RATIO,
"attributes", "frame::width, frame::height",
"display-name", _("Aspect ratio"),
- "data-type", GTH_TEST_DATA_TYPE_FRACTIONAL,
- "get-data-func", get_aspect_ratio_for_test,
- "max-int", 100,
NULL);
}
diff --git a/gthumb/gth-test-aspect-ratio.c b/gthumb/gth-test-aspect-ratio.c
new file mode 100644
index 0000000..0cbd9e2
--- /dev/null
+++ b/gthumb/gth-test-aspect-ratio.c
@@ -0,0 +1,467 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+/*
+ * GThumb
+ *
+ * Copyright (C) 2017 Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+#include <glib/gi18n.h>
+#include <glib.h>
+#include <gtk/gtk.h>
+#include "dom.h"
+#include "glib-utils.h"
+#include "gth-duplicable.h"
+#include "gth-enum-types.h"
+#include "gth-main.h"
+#include "gth-monitor.h"
+#include "gth-test.h"
+#include "gth-test-aspect-ratio.h"
+#include "gtk-utils.h"
+
+
+#define RATIO_EQUAL(a, b) (fabs((a) - (b)) < 0.005)
+
+
+static struct {
+ const char *name;
+ double value;
+} aspect_ratio_values[] = {
+ { N_("Square"), 1.0 },
+ { N_("5:4"), 5.0 / 4.0 },
+ { N_("4:3 (DVD, Book)"), 4.0 / 3.0 },
+ { N_("7:5"), 7.0 / 5.0 },
+ { N_("3:2 (Postcard)"), 3.0 / 2.0 },
+ { N_("16:10"), 16.0 / 10.0 },
+ { N_("16:9 (DVD)"), 16.0 / 9.0 },
+ { N_("1.85:1"), 1.85 },
+ { N_("2.39:1"), 2.39 }
+};
+
+
+typedef struct {
+ char *name;
+ GthTestOp op;
+ gboolean negative;
+} GthOpData;
+
+
+GthOpData aspect_ratio_op_data[] = {
+ { N_("is lower than"), GTH_TEST_OP_LOWER, FALSE },
+ { N_("is greater than"), GTH_TEST_OP_GREATER, FALSE },
+ { N_("is equal to"), GTH_TEST_OP_EQUAL, FALSE },
+ { N_("is greater than or equal to"), GTH_TEST_OP_LOWER, TRUE },
+ { N_("is lower than or equal to"), GTH_TEST_OP_GREATER, TRUE }
+};
+
+
+struct _GthTestAspectRatioPrivate
+{
+ GthTestOp op;
+ gboolean negative;
+ double aspect_ratio;
+ int custom_ratio_idx;
+ GtkWidget *op_combo_box;
+ GtkWidget *ratio_combobox;
+ GtkWidget *ratio_spinbutton;
+ GtkWidget *custom_ratio_box;
+};
+
+
+static DomDomizableInterface *dom_domizable_parent_iface = NULL;
+static GthDuplicableInterface *gth_duplicable_parent_iface = NULL;
+
+
+static void gth_test_aspect_ratio_dom_domizable_interface_init (DomDomizableInterface * iface);
+static void gth_test_aspect_ratio_gth_duplicable_interface_init (GthDuplicableInterface *iface);
+
+
+G_DEFINE_TYPE_WITH_CODE (GthTestAspectRatio,
+ gth_test_aspect_ratio,
+ GTH_TYPE_TEST,
+ G_IMPLEMENT_INTERFACE (DOM_TYPE_DOMIZABLE,
+ gth_test_aspect_ratio_dom_domizable_interface_init)
+ G_IMPLEMENT_INTERFACE (GTH_TYPE_DUPLICABLE,
+ gth_test_aspect_ratio_gth_duplicable_interface_init))
+
+
+static void
+gth_test_aspect_ratio_finalize (GObject *object)
+{
+ GthTestAspectRatio *test;
+
+ test = GTH_TEST_ASPECT_RATIO (object);
+
+ if (test->priv != NULL) {
+ g_free (test->priv);
+ test->priv = NULL;
+ }
+
+ G_OBJECT_CLASS (gth_test_aspect_ratio_parent_class)->finalize (object);
+}
+
+
+static void
+update_visibility (GthTestAspectRatio *self)
+{
+ if (gtk_combo_box_get_active (GTK_COMBO_BOX (self->priv->ratio_combobox)) ==
self->priv->custom_ratio_idx) {
+ gtk_widget_show (self->priv->custom_ratio_box);
+ gtk_widget_hide (self->priv->ratio_combobox);
+ }
+ else {
+ gtk_widget_hide (self->priv->custom_ratio_box);
+ gtk_widget_show (self->priv->ratio_combobox);
+ }
+}
+
+
+static void
+combo_box_changed_cb (GtkComboBox *widget,
+ GthTestAspectRatio *self)
+{
+ gth_test_update_from_control (GTH_TEST (self), NULL);
+ gth_test_changed (GTH_TEST (self));
+ update_visibility (self);
+}
+
+
+static void
+spinbutton_changed_cb (GtkSpinButton *spinbutton,
+ GthTestAspectRatio *self)
+{
+ gth_test_update_from_control (GTH_TEST (self), NULL);
+ gth_test_changed (GTH_TEST (self));
+}
+
+
+static void
+reset_button_clicked_cb (GtkButton *button,
+ GthTestAspectRatio *self)
+{
+ gtk_combo_box_set_active (GTK_COMBO_BOX (self->priv->ratio_combobox), 0);
+}
+
+
+static GtkWidget *
+gth_test_aspect_ratio_real_create_control (GthTest *base)
+{
+ GthTestAspectRatio *self;
+ GtkWidget *control;
+ GtkWidget *reset_button;
+ int i, active_idx, current_idx;
+
+ self = (GthTestAspectRatio *) base;
+
+ control = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
+
+ /* operation combo box */
+
+ self->priv->op_combo_box = gtk_combo_box_text_new ();
+ gtk_widget_show (self->priv->op_combo_box);
+
+ active_idx = 0;
+ for (i = 0; i < G_N_ELEMENTS (aspect_ratio_op_data); i++) {
+ gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (self->priv->op_combo_box),
+ _(aspect_ratio_op_data[i].name));
+ if ((aspect_ratio_op_data[i].op == self->priv->op) && (aspect_ratio_op_data[i].negative ==
self->priv->negative))
+ active_idx = i;
+ }
+ gtk_combo_box_set_active (GTK_COMBO_BOX (self->priv->op_combo_box), active_idx);
+
+ g_signal_connect (G_OBJECT (self->priv->op_combo_box),
+ "changed",
+ G_CALLBACK (combo_box_changed_cb),
+ self);
+
+ /* aspect ratio list combo box */
+
+ self->priv->ratio_combobox = gtk_combo_box_text_new ();
+ gtk_widget_show (self->priv->ratio_combobox);
+
+ current_idx = -1;
+ active_idx = -1;
+
+ for (i = 0; i < G_N_ELEMENTS (aspect_ratio_values); i++) {
+ gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (self->priv->ratio_combobox),
+ _(aspect_ratio_values[i].name));
+ current_idx++;
+ if ((active_idx == -1) && RATIO_EQUAL (aspect_ratio_values[i].value,
self->priv->aspect_ratio))
+ active_idx = current_idx;
+ }
+
+ gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (self->priv->ratio_combobox), _("Custom"));
+ current_idx++;
+ self->priv->custom_ratio_idx = current_idx;
+
+ if (active_idx == -1)
+ active_idx = self->priv->custom_ratio_idx;
+
+ gtk_combo_box_set_active (GTK_COMBO_BOX (self->priv->ratio_combobox), active_idx);
+
+ g_signal_connect (G_OBJECT (self->priv->ratio_combobox),
+ "changed",
+ G_CALLBACK (combo_box_changed_cb),
+ self);
+
+ /* custom ratio widgets */
+
+ self->priv->custom_ratio_box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
+ gtk_widget_show (self->priv->custom_ratio_box);
+
+ self->priv->ratio_spinbutton = gtk_spin_button_new_with_range (0, 10.0, 0.01);
+ gtk_spin_button_set_value (GTK_SPIN_BUTTON (self->priv->ratio_spinbutton), self->priv->aspect_ratio);
+ gtk_widget_show (self->priv->ratio_spinbutton);
+
+ reset_button = gtk_button_new_from_icon_name ("edit-undo-symbolic", GTK_ICON_SIZE_BUTTON);
+ gtk_button_set_relief (GTK_BUTTON (reset_button), GTK_RELIEF_NONE);
+ gtk_widget_set_tooltip_text (reset_button, _("Reset"));
+ gtk_widget_show (reset_button);
+
+ g_signal_connect (G_OBJECT (reset_button),
+ "clicked",
+ G_CALLBACK (reset_button_clicked_cb),
+ self);
+
+ gtk_box_pack_start (GTK_BOX (self->priv->custom_ratio_box), self->priv->ratio_spinbutton, FALSE,
FALSE, 0);
+ gtk_box_pack_start (GTK_BOX (self->priv->custom_ratio_box), reset_button, FALSE, FALSE, 0);
+
+ g_signal_connect (G_OBJECT (self->priv->ratio_spinbutton),
+ "value-changed",
+ G_CALLBACK (spinbutton_changed_cb),
+ self);
+
+ /**/
+
+ gtk_box_pack_start (GTK_BOX (control), self->priv->op_combo_box, FALSE, FALSE, 0);
+ gtk_box_pack_start (GTK_BOX (control), self->priv->ratio_combobox, FALSE, FALSE, 0);
+ gtk_box_pack_start (GTK_BOX (control), self->priv->custom_ratio_box, FALSE, FALSE, 0);
+ update_visibility (self);
+
+ return control;
+}
+
+
+static GthMatch
+gth_test_aspect_ratio_real_match (GthTest *test,
+ GthFileData *file)
+{
+ GthTestAspectRatio *self;
+ int width, height;
+ double ratio;
+ gboolean result = FALSE;
+
+ self = GTH_TEST_ASPECT_RATIO (test);
+
+ width = g_file_info_get_attribute_int32 (file->info, "frame::width");
+ height = g_file_info_get_attribute_int32 (file->info, "frame::height");
+ ratio = (height > 0) ? (double) width / height : 0;
+
+ switch (self->priv->op) {
+ case GTH_TEST_OP_EQUAL:
+ result = RATIO_EQUAL (ratio, self->priv->aspect_ratio);
+ break;
+
+ case GTH_TEST_OP_LOWER:
+ result = (ratio < self->priv->aspect_ratio);
+ break;
+
+ case GTH_TEST_OP_GREATER:
+ result = (ratio > self->priv->aspect_ratio);
+ break;
+
+ default:
+ break;
+ }
+
+ if (self->priv->negative)
+ result = ! result;
+
+ return result ? GTH_MATCH_YES : GTH_MATCH_NO;
+}
+
+
+static DomElement*
+gth_test_aspect_ratio_real_create_element (DomDomizable *base,
+ DomDocument *doc)
+{
+ GthTestAspectRatio *self;
+ DomElement *element;
+ char *value;
+
+ g_return_val_if_fail (DOM_IS_DOCUMENT (doc), NULL);
+
+ self = GTH_TEST_ASPECT_RATIO (base);
+
+ element = dom_document_create_element (doc, "test",
+ "id", gth_test_get_id (GTH_TEST (self)),
+ NULL);
+
+ if (! gth_test_is_visible (GTH_TEST (self)))
+ dom_element_set_attribute (element, "display", "none");
+
+ dom_element_set_attribute (element, "op", _g_enum_type_get_value (GTH_TYPE_TEST_OP,
self->priv->op)->value_nick);
+ if (self->priv->negative)
+ dom_element_set_attribute (element, "negative", self->priv->negative ? "true" : "false");
+
+ value = g_strdup_printf ("%f", self->priv->aspect_ratio);
+ dom_element_set_attribute (element, "value", value);
+ g_free (value);
+
+ return element;
+}
+
+
+static void
+gth_test_aspect_ratio_set_aspect_ratio (GthTestAspectRatio *self,
+ double value)
+{
+ self->priv->aspect_ratio = value;
+}
+
+
+static void
+gth_test_aspect_ratio_real_load_from_element (DomDomizable *base,
+ DomElement *element)
+{
+ GthTestAspectRatio *self;
+ const char *value;
+
+ g_return_if_fail (DOM_IS_ELEMENT (element));
+
+ self = GTH_TEST_ASPECT_RATIO (base);
+
+ g_object_set (self, "visible", (g_strcmp0 (dom_element_get_attribute (element, "display"), "none") !=
0), NULL);
+
+ value = dom_element_get_attribute (element, "op");
+ if (value != NULL)
+ self->priv->op = _g_enum_type_get_value_by_nick (GTH_TYPE_TEST_OP, value)->value;
+
+ self->priv->negative = g_strcmp0 (dom_element_get_attribute (element, "negative"), "true") == 0;
+
+ value = dom_element_get_attribute (element, "value");
+ gth_test_aspect_ratio_set_aspect_ratio (self, (value != NULL) ? atof (value) : 0.0);
+}
+
+
+static gboolean
+gth_test_aspect_ratio_real_update_from_control (GthTest *base,
+ GError **error)
+{
+ GthTestAspectRatio *self;
+ GthOpData op_data;
+ int active_idx;
+
+ self = GTH_TEST_ASPECT_RATIO (base);
+
+ op_data = aspect_ratio_op_data[gtk_combo_box_get_active (GTK_COMBO_BOX (self->priv->op_combo_box))];
+ self->priv->op = op_data.op;
+ self->priv->negative = op_data.negative;
+
+ active_idx = gtk_combo_box_get_active (GTK_COMBO_BOX (self->priv->ratio_combobox));
+ if (active_idx == self->priv->custom_ratio_idx)
+ self->priv->aspect_ratio = gtk_spin_button_get_value (GTK_SPIN_BUTTON
(self->priv->ratio_spinbutton));
+ else
+ self->priv->aspect_ratio = aspect_ratio_values[active_idx].value;
+
+ if (self->priv->aspect_ratio == 0) {
+ if (error != NULL)
+ *error = g_error_new (GTH_TEST_ERROR, 0, _("The test definition is incomplete"));
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
+static void
+gth_test_aspect_ratio_real_focus_control (GthTest *base)
+{
+ GthTestAspectRatio *self;
+
+ self = GTH_TEST_ASPECT_RATIO (base);
+ if (gtk_combo_box_get_active (GTK_COMBO_BOX (self->priv->ratio_combobox)) ==
self->priv->custom_ratio_idx)
+ gtk_widget_grab_focus (self->priv->ratio_spinbutton);
+ else
+ gtk_widget_grab_focus (self->priv->ratio_combobox);
+}
+
+
+static GObject *
+gth_test_aspect_ratio_real_duplicate (GthDuplicable *duplicable)
+{
+ GthTestAspectRatio *test = GTH_TEST_ASPECT_RATIO (duplicable);
+ GthTestAspectRatio *new_test;
+
+ new_test = g_object_new (GTH_TYPE_TEST_ASPECT_RATIO,
+ "id", gth_test_get_id (GTH_TEST (test)),
+ "attributes", gth_test_get_attributes (GTH_TEST (test)),
+ "display-name", gth_test_get_display_name (GTH_TEST (test)),
+ "visible", gth_test_is_visible (GTH_TEST (test)),
+ NULL);
+ new_test->priv->op = test->priv->op;
+ new_test->priv->negative = test->priv->negative;
+ gth_test_aspect_ratio_set_aspect_ratio (new_test, test->priv->aspect_ratio);
+
+ return (GObject *) new_test;
+}
+
+
+static void
+gth_test_aspect_ratio_class_init (GthTestAspectRatioClass *class)
+{
+ GObjectClass *object_class;
+ GthTestClass *test_class;
+
+ object_class = (GObjectClass*) class;
+ object_class->finalize = gth_test_aspect_ratio_finalize;
+
+ test_class = (GthTestClass *) class;
+ test_class->create_control = gth_test_aspect_ratio_real_create_control;
+ test_class->update_from_control = gth_test_aspect_ratio_real_update_from_control;
+ test_class->focus_control = gth_test_aspect_ratio_real_focus_control;
+ test_class->match = gth_test_aspect_ratio_real_match;
+}
+
+
+static void
+gth_test_aspect_ratio_dom_domizable_interface_init (DomDomizableInterface * iface)
+{
+ dom_domizable_parent_iface = g_type_interface_peek_parent (iface);
+ iface->create_element = gth_test_aspect_ratio_real_create_element;
+ iface->load_from_element = gth_test_aspect_ratio_real_load_from_element;
+}
+
+
+static void
+gth_test_aspect_ratio_gth_duplicable_interface_init (GthDuplicableInterface *iface)
+{
+ gth_duplicable_parent_iface = g_type_interface_peek_parent (iface);
+ iface->duplicate = gth_test_aspect_ratio_real_duplicate;
+}
+
+
+static void
+gth_test_aspect_ratio_init (GthTestAspectRatio *self)
+{
+ self->priv = g_new0 (GthTestAspectRatioPrivate, 1);
+ self->priv->aspect_ratio = 1.0;
+ self->priv->op = GTH_TEST_OP_EQUAL;
+ self->priv->negative = FALSE;
+}
diff --git a/gthumb/gth-test-aspect-ratio.h b/gthumb/gth-test-aspect-ratio.h
new file mode 100644
index 0000000..0e2e565
--- /dev/null
+++ b/gthumb/gth-test-aspect-ratio.h
@@ -0,0 +1,52 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+/*
+ * GThumb
+ *
+ * Copyright (C) 2017 Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GTH_TEST_ASPECT_RATIO_H
+#define GTH_TEST_ASPECT_RATIO_H
+
+#include <glib-object.h>
+#include <gtk/gtk.h>
+
+#define GTH_TYPE_TEST_ASPECT_RATIO (gth_test_aspect_ratio_get_type ())
+#define GTH_TEST_ASPECT_RATIO(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GTH_TYPE_TEST_ASPECT_RATIO,
GthTestAspectRatio))
+#define GTH_TEST_ASPECT_RATIO_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), GTH_TYPE_TEST_ASPECT_RATIO,
GthTestAspectRatioClass))
+#define GTH_IS_TEST_ASPECT_RATIO(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GTH_TYPE_TEST_ASPECT_RATIO))
+#define GTH_IS_TEST_ASPECT_RATIO_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GTH_TYPE_TEST_ASPECT_RATIO))
+#define GTH_TEST_ASPECT_RATIO_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS((o), GTH_TYPE_TEST_ASPECT_RATIO,
GthTestAspectRatioClass))
+
+typedef struct _GthTestAspectRatio GthTestAspectRatio;
+typedef struct _GthTestAspectRatioPrivate GthTestAspectRatioPrivate;
+typedef struct _GthTestAspectRatioClass GthTestAspectRatioClass;
+
+struct _GthTestAspectRatio
+{
+ GthTest __parent;
+ GthTestAspectRatioPrivate *priv;
+};
+
+struct _GthTestAspectRatioClass
+{
+ GthTestClass __parent_class;
+};
+
+GType gth_test_aspect_ratio_get_type (void) G_GNUC_CONST;
+
+#endif /* GTH_TEST_ASPECT_RATIO_H */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]