From 44ad3d257b9594674604fa82215e72759b40de11 Mon Sep 17 00:00:00 2001 From: Jim Evins Date: Wed, 10 Mar 2010 22:38:28 -0500 Subject: [PATCH] Created new "New label dialog" Created a new re-designed "New label dialog." The dialog now shows meta-data for the selected template, including hyperlinks to vendor and product websites, if available. The new dialog is more compact and thus should be usable on small displays such as netbooks (probably not hand-helds). The menu is somewhat clumbsy to navigate still -- will need to reorganize to make navigation easier and more intuitive. --- data/builder/Makefile.am | 2 +- data/builder/media-select.builder | 229 ------- data/builder/new-label-dialog.builder | 362 ++++++++++ libglabels/db.c | 75 ++- libglabels/db.h | 4 + libglabels/str.c | 41 +- libglabels/str.h | 10 +- libglabels/template.c | 232 ++++++- libglabels/template.h | 31 +- src/Makefile.am | 8 +- src/media-combo-menu-item.c | 178 +++++ src/media-combo-menu-item.h | 75 +++ src/media-combo-menu.c | 332 +++++++++ src/media-combo-menu.h | 83 +++ src/media-combo.c | 345 ++++++++++ src/media-combo.h | 84 +++ src/media-select.c | 937 -------------------------- src/media-select.h | 87 --- src/mini-preview.c | 90 ++- src/mini-preview.h | 6 + src/new-label-dialog.c | 342 +++++++--- src/rotate-label-button.c | 10 +- src/str-util.c | 37 - src/str-util.h | 2 - 24 files changed, 2196 insertions(+), 1406 deletions(-) delete mode 100644 data/builder/media-select.builder create mode 100644 data/builder/new-label-dialog.builder create mode 100644 src/media-combo-menu-item.c create mode 100644 src/media-combo-menu-item.h create mode 100644 src/media-combo-menu.c create mode 100644 src/media-combo-menu.h create mode 100644 src/media-combo.c create mode 100644 src/media-combo.h delete mode 100644 src/media-select.c delete mode 100644 src/media-select.h diff --git a/data/builder/Makefile.am b/data/builder/Makefile.am index a4cf3f3f..4b48a699 100644 --- a/data/builder/Makefile.am +++ b/data/builder/Makefile.am @@ -5,7 +5,7 @@ builderdir = $(datadir)/$(GLABELS_BRANCH)/builder/ builder_DATA = \ property-bar.builder \ print-op-dialog-custom-widget.builder \ - media-select.builder \ + new-label-dialog.builder \ merge-properties-dialog.builder \ template-designer.builder \ prefs-dialog.builder \ diff --git a/data/builder/media-select.builder b/data/builder/media-select.builder deleted file mode 100644 index 707057af..00000000 --- a/data/builder/media-select.builder +++ /dev/null @@ -1,229 +0,0 @@ - - - - - - True - window1 - - - True - - - True - 12 - - - 320 - True - 6 - vertical - - - True - vertical - - - - - - False - False - 0 - - - - - True - True - automatic - automatic - in - - - True - False - - - - - 1 - - - - - - - True - Recent templates - - - False - - - - - True - 6 - vertical - - - True - 12 - - - True - 6 - - - True - Brand: - - - False - False - 0 - - - - - True - False - - - False - 1 - - - - - False - False - 0 - - - - - True - 6 - - - True - Page size: - - - False - False - 0 - - - - - True - False - - - False - 1 - - - - - False - 1 - - - - - True - 6 - - - True - Category: - - - False - False - 0 - - - - - True - False - - - False - 1 - - - - - False - 2 - - - - - False - 6 - 0 - - - - - True - vertical - - - - - - False - False - 1 - - - - - True - True - automatic - automatic - in - - - True - False - - - - - 2 - - - - - 1 - - - - - True - Search all templates - - - 1 - False - - - - - 0 - - - - - - diff --git a/data/builder/new-label-dialog.builder b/data/builder/new-label-dialog.builder new file mode 100644 index 00000000..9cb16a56 --- /dev/null +++ b/data/builder/new-label-dialog.builder @@ -0,0 +1,362 @@ + + + + + + + + True + 6 + 18 + + + True + vertical + 6 + + + True + 0 + none + + + True + 12 + + + True + 2 + 2 + 12 + 6 + + + True + 0 + Template: + + + GTK_FILL + + + + + True + + + + + + 1 + 2 + + + + + True + 0 + 0 + Orientation: + + + 1 + 2 + GTK_FILL + + + + + True + + + + + + 1 + 2 + 1 + 2 + GTK_FILL + + + + + + + + + True + <b>Select media</b> + True + + + + + False + False + 0 + + + + + True + 0 + none + + + True + 12 + + + True + 7 + 2 + 12 + 6 + + + True + 0 + Description: + + + 2 + 3 + GTK_FILL + + + + + True + 0 + Page size: + + + 3 + 4 + GTK_FILL + + + + + True + 0 + Label size: + + + 4 + 5 + GTK_FILL + + + + + True + 0 + Layout: + + + 5 + 6 + GTK_FILL + + + + + True + 0 + 0 + Similar products: + + + 6 + 7 + GTK_FILL + + + + + True + 0 + + + 1 + 2 + 2 + 3 + + + + + True + 0 + + + 1 + 2 + 3 + 4 + + + + + True + 0 + + + 1 + 2 + 4 + 5 + + + + + True + 0 + + + 1 + 2 + 5 + 6 + + + + + True + 0 + Vendor: + + + GTK_FILL + + + + + True + 0 + + + 1 + 2 + + + + + True + 0 + Part #: + + + 1 + 2 + GTK_FILL + + + + + True + 0 + + + 1 + 2 + 1 + 2 + + + + + 77 + True + True + never + automatic + in + + + True + queue + none + + + True + 0 + 0 + 1 +2 +3 +4 + + + + + + + 1 + 2 + 6 + 7 + + + + + + + + + + True + <b>Information</b> + True + + + + + False + False + 1 + + + + + 0 + + + + + True + 0 + none + + + True + 12 + + + True + vertical + + + + + + + + + + True + <b>Preview</b> + True + + + + + 1 + + + + + + diff --git a/libglabels/db.c b/libglabels/db.c index b43ff6b3..af2adcae 100644 --- a/libglabels/db.c +++ b/libglabels/db.c @@ -1149,7 +1149,7 @@ read_vendor_files_from_dir (GList *vendors, if (extension != NULL) { - if ( ASCII_EQUAL (filename, "vendor-sizes.xml") ) + if ( ASCII_EQUAL (filename, "vendors.xml") ) { full_filename = @@ -1555,6 +1555,77 @@ lgl_db_get_template_name_list_all (const gchar *brand, } +/** + * lgl_db_get_similar_template_name_list: + * @name: Name of template under test. + * + * Get a list of all valid names and aliases of templates in the template database that + * have the same size and layout characteristics as the given template. + * + * Returns: a list of template names and aliases. + */ +GList * +lgl_db_get_similar_template_name_list (const gchar *name) +{ + GList *p_tmplt, *p_alias; + lglTemplate *template1; + lglTemplate *template2; + lglTemplateAlias *alias; + gchar *name2; + GList *names = NULL; + + if (!templates) + { + lgl_db_init (); + } + + if ( !name ) + { + return NULL; + } + + template1 = lgl_db_lookup_template_from_name (name); + if ( !template1 ) + { + return NULL; + } + + for (p_alias = template1->aliases; p_alias != NULL; p_alias = p_alias->next) + { + alias = (lglTemplateAlias *)p_alias->data; + + name2 = g_strdup_printf ("%s %s", alias->brand, alias->part); + if ( !UTF8_EQUAL (name2, name) ) + { + names = g_list_insert_sorted (names, name2, + (GCompareFunc)lgl_str_part_name_cmp); + } + } + + for (p_tmplt = templates; p_tmplt != NULL; p_tmplt = p_tmplt->next) + { + template2 = (lglTemplate *) p_tmplt->data; + + if ( lgl_template_are_templates_identical (template1, template2) ) + { + for (p_alias = template2->aliases; p_alias != NULL; p_alias = p_alias->next) + { + alias = (lglTemplateAlias *)p_alias->data; + + name2 = g_strdup_printf ("%s %s", alias->brand, alias->part); + if ( !UTF8_EQUAL (name2, name) ) + { + names = g_list_insert_sorted (names, name2, + (GCompareFunc)lgl_str_part_name_cmp); + } + } + } + } + + return names; +} + + /** * lgl_db_free_template_name_list: * @names: List of template name strings to be freed. @@ -1819,7 +1890,7 @@ template_full_page (const gchar *paper_id) } part = g_strdup_printf ("%s-Full-Page", paper->id); - desc = g_strdup_printf (_("Generic %s full page template"), paper->name); + desc = g_strdup_printf (_("%s full page label"), paper->name); template = lgl_template_new ("Generic", part, desc, paper_id, paper->width, paper->height); diff --git a/libglabels/db.h b/libglabels/db.h index 3fd9f3a8..343573eb 100644 --- a/libglabels/db.h +++ b/libglabels/db.h @@ -130,6 +130,8 @@ GList *lgl_db_get_template_name_list_all (const gchar *brand const gchar *paper_id, const gchar *category_id); +GList *lgl_db_get_similar_template_name_list (const gchar *name); + void lgl_db_free_template_name_list (GList *names); lglTemplate *lgl_db_lookup_template_from_name (const gchar *name); @@ -149,6 +151,8 @@ void lgl_db_print_known_templates (void); void lgl_db_print_aliases (const lglTemplate *template); +void lgl_db_print_known_vendors (void); + G_END_DECLS diff --git a/libglabels/str.c b/libglabels/str.c index e93a9913..0f0339ba 100644 --- a/libglabels/str.c +++ b/libglabels/str.c @@ -18,11 +18,15 @@ * along with libglabels. If not, see . */ -//#include +#include #include "str.h" #include +#include + +#define FRAC_EPSILON 0.00005 + /*===========================================*/ /* Private types */ @@ -217,6 +221,41 @@ span_non_digits (gchar **p) } +/****************************************************************************/ +/* Create fractional representation of number, if possible. */ +/****************************************************************************/ +gchar * +lgl_str_format_fraction (gdouble x) +{ + static gdouble denom[] = { 1., 2., 3., 4., 8., 16., 32., 0. }; + gint i; + gdouble product, remainder; + gint n, d; + + for ( i=0; denom[i] != 0.0; i++ ) { + product = x * denom[i]; + remainder = fabs(product - ((gint)(product+0.5))); + if ( remainder < FRAC_EPSILON ) break; + } + + if ( denom[i] == 0.0 ) { + /* None of our denominators work. */ + return g_strdup_printf ("%.5g", x); + } + if ( denom[i] == 1.0 ) { + /* Simple integer. */ + return g_strdup_printf ("%d", (gint)x); + } + n = (gint)( x * denom[i] + 0.5 ); + d = (gint)denom[i]; + if ( n > d ) { + return g_strdup_printf ("%d_%d/%d", (n/d), (n%d), d); + } else { + return g_strdup_printf ("%d/%d", (n%d), d); + } +} + + /* * Local Variables: -- emacs diff --git a/libglabels/str.h b/libglabels/str.h index 2675029d..b22f13b5 100644 --- a/libglabels/str.h +++ b/libglabels/str.h @@ -25,11 +25,13 @@ G_BEGIN_DECLS -gint lgl_str_utf8_casecmp (const gchar *s1, - const gchar *s2); +gint lgl_str_utf8_casecmp (const gchar *s1, + const gchar *s2); -gint lgl_str_part_name_cmp (const gchar *s1, - const gchar *s2); +gint lgl_str_part_name_cmp (const gchar *s1, + const gchar *s2); + +gchar *lgl_str_format_fraction (gdouble x); G_END_DECLS diff --git a/libglabels/template.c b/libglabels/template.c index 0af4e5de..50271fbb 100644 --- a/libglabels/template.c +++ b/libglabels/template.c @@ -180,7 +180,7 @@ lgl_template_get_name (const lglTemplate *template) * This function tests if the given templates match. This is a simple test that only tests * the brand and part name/number. It does not test if they are actually identical. * - * Returns: TRUE if the two template matche. + * Returns: TRUE if the two templates match. * */ gboolean @@ -283,6 +283,108 @@ lgl_template_does_category_match (const lglTemplate *template, } +/** + * lgl_template_are_templates_identical: + * @template1: Pointer to 1st template structure to test + * @template2: Pointer to 2nd template structure to test + * + * This function tests if the given templates have identical size and layout properties. + * + * Returns: TRUE if the two templates are identical. + * + */ +gboolean +lgl_template_are_templates_identical (const lglTemplate *template1, + const lglTemplate *template2) +{ + lglTemplateFrame *frame1; + lglTemplateFrame *frame2; + GList *p1; + GList *p2; + lglTemplateLayout *layout1; + lglTemplateLayout *layout2; + gboolean match_found; + + + if (!UTF8_EQUAL (template1->paper_id, template2->paper_id) || + (template1->page_width != template2->page_width) || + (template1->page_height != template2->page_height)) + { + return FALSE; + } + + frame1 = (lglTemplateFrame *)template1->frames->data; + frame2 = (lglTemplateFrame *)template2->frames->data; + + if ( frame1->shape != frame2->shape ) + { + return FALSE; + } + + switch ( frame1->shape ) + { + + case LGL_TEMPLATE_FRAME_SHAPE_RECT: + if ((frame1->rect.w != frame2->rect.w) || + (frame1->rect.h != frame2->rect.h)) + { + return FALSE; + } + break; + + case LGL_TEMPLATE_FRAME_SHAPE_ELLIPSE: + if ((frame1->ellipse.w != frame2->ellipse.w) || + (frame1->ellipse.h != frame2->ellipse.h)) + { + return FALSE; + } + break; + + case LGL_TEMPLATE_FRAME_SHAPE_ROUND: + if ((frame1->round.r != frame2->round.r)) + { + return FALSE; + } + break; + + case LGL_TEMPLATE_FRAME_SHAPE_CD: + if ((frame1->cd.r1 != frame2->cd.r1) || + (frame1->cd.r2 != frame2->cd.r2)) + { + return FALSE; + } + } + + for ( p1 = frame1->all.layouts; p1; p1 = p1->next ) + { + layout1 = (lglTemplateLayout *)p1->data; + + match_found = FALSE; + for ( p2 = frame2->all.layouts; p2 && !match_found; p2 = p2->next ) + { + layout2 = (lglTemplateLayout *)p2->data; + + if ( (layout1->nx == layout2->nx) && + (layout1->ny == layout2->ny) && + (layout1->x0 == layout2->x0) && + (layout1->y0 == layout2->y0) && + (layout1->dx == layout2->dx) && + (layout1->dy == layout2->dy) ) + { + match_found = TRUE; + } + + } + if ( !match_found ) + { + return FALSE; + } + } + + return TRUE; +} + + /** * lgl_template_alias_new: * @brand: Alias brand @@ -588,6 +690,134 @@ lgl_template_frame_get_n_labels (const lglTemplateFrame *frame) } +/** + * lgl_template_frame_get_layout_description + * @frame: #lglTemplateFrame structure to query + * + * Get a description of the label layout including number of labels per sheet. + * + * Returns: a newly allocation description string. + * + */ +gchar * +lgl_template_frame_get_layout_description (const lglTemplateFrame *frame) +{ + gint n_labels; + gchar *string; + lglTemplateLayout *layout; + + n_labels = lgl_template_frame_get_n_labels (frame); + + if ( frame->all.layouts && (frame->all.layouts->next == NULL) ) + { + layout = (lglTemplateLayout *)frame->all.layouts->data; + string = g_strdup_printf ("%d × %d (%d %s)", layout->nx, layout->ny, n_labels, _("per sheet")); + } + else + { + string = g_strdup_printf (_("%d %s"), n_labels, _("per sheet")); + } + + return string; +} + + +/** + * lgl_template_frame_get_size_description + * @frame: #lglTemplateFrame structure to query + * @units: #lglUnits + * + * Get a description of the label size. + * + * Returns: a newly allocation description string. + * + */ +gchar * +lgl_template_frame_get_size_description (const lglTemplateFrame *frame, + lglUnits units) +{ + const gchar *units_string; + gdouble units_per_point; + gchar *string = NULL; + + units_string = lgl_units_get_name (units); + units_per_point = lgl_units_get_units_per_point (units); + + switch (frame->shape) { + case LGL_TEMPLATE_FRAME_SHAPE_RECT: + if ( units == LGL_UNITS_INCH ) { + gchar *xstr, *ystr; + + xstr = lgl_str_format_fraction (frame->rect.w*units_per_point); + ystr = lgl_str_format_fraction (frame->rect.h*units_per_point); + string = g_strdup_printf ("%s × %s %s", + xstr, ystr, units_string); + g_free (xstr); + g_free (ystr); + } else { + string = g_strdup_printf ("%.5g × %.5g %s", + frame->rect.w*units_per_point, + frame->rect.h*units_per_point, + units_string); + } + break; + case LGL_TEMPLATE_FRAME_SHAPE_ELLIPSE: + if ( units == LGL_UNITS_INCH ) { + gchar *xstr, *ystr; + + xstr = lgl_str_format_fraction (frame->ellipse.w*units_per_point); + ystr = lgl_str_format_fraction (frame->ellipse.h*units_per_point); + string = g_strdup_printf ("%s × %s %s", + xstr, ystr, units_string); + g_free (xstr); + g_free (ystr); + } else { + string = g_strdup_printf ("%.5g × %.5g %s", + frame->ellipse.w*units_per_point, + frame->ellipse.h*units_per_point, + units_string); + } + break; + case LGL_TEMPLATE_FRAME_SHAPE_ROUND: + if ( units == LGL_UNITS_INCH ) { + gchar *dstr; + + dstr = lgl_str_format_fraction (2.0*frame->round.r*units_per_point); + string = g_strdup_printf ("%s %s %s", + dstr, units_string, + _("diameter")); + g_free (dstr); + } else { + string = g_strdup_printf ("%.5g %s %s", + 2.0*frame->round.r*units_per_point, + units_string, + _("diameter")); + } + break; + case LGL_TEMPLATE_FRAME_SHAPE_CD: + if ( units == LGL_UNITS_INCH ) { + gchar *dstr; + + dstr = lgl_str_format_fraction (2.0*frame->cd.r1*units_per_point); + string = g_strdup_printf ("%s %s %s", + dstr, units_string, + _("diameter")); + g_free (dstr); + } else { + string = g_strdup_printf ("%.5g %s %s", + 2.0*frame->cd.r1*units_per_point, + units_string, + _("diameter")); + } + break; + default: + break; + } + + return string; +} + + /** * lgl_template_frame_get_origins: * @frame: #lglTemplateFrame structure to query diff --git a/libglabels/template.h b/libglabels/template.h index 6adfa83e..a3c01115 100644 --- a/libglabels/template.h +++ b/libglabels/template.h @@ -22,6 +22,7 @@ #define __LGL_TEMPLATE_H__ #include +#include "units.h" G_BEGIN_DECLS @@ -285,19 +286,24 @@ struct _lglTemplateOrigin { /* * Template query functions */ -gchar *lgl_template_get_name (const lglTemplate *template); +gchar *lgl_template_get_name (const lglTemplate *template); -gboolean lgl_template_do_templates_match (const lglTemplate *template1, - const lglTemplate *template2); +gboolean lgl_template_do_templates_match (const lglTemplate *template1, + const lglTemplate *template2); -gboolean lgl_template_does_brand_match (const lglTemplate *template, - const gchar *brand); +gboolean lgl_template_does_brand_match (const lglTemplate *template, + const gchar *brand); + +gboolean lgl_template_does_page_size_match (const lglTemplate *template, + const gchar *paper_id); + +gboolean lgl_template_does_category_match (const lglTemplate *template, + const gchar *category_id); + +gboolean lgl_template_are_templates_identical (const lglTemplate *template1, + const lglTemplate *template2); -gboolean lgl_template_does_page_size_match (const lglTemplate *template, - const gchar *paper_id); -gboolean lgl_template_does_category_match (const lglTemplate *template, - const gchar *category_id); /* @@ -311,6 +317,13 @@ gint lgl_template_frame_get_n_labels (const lglTemplateFrame lglTemplateOrigin *lgl_template_frame_get_origins (const lglTemplateFrame *frame); +gchar *lgl_template_frame_get_layout_description (const lglTemplateFrame *frame); + +gchar *lgl_template_frame_get_size_description (const lglTemplateFrame *frame, + lglUnits units); + + + /* * Template Construction diff --git a/src/Makefile.am b/src/Makefile.am index cf0b81a5..49e6e0ef 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -162,8 +162,12 @@ glabels_3_SOURCES = \ mini-preview-pixbuf.h \ mini-preview-pixbuf-cache.c \ mini-preview-pixbuf-cache.h \ - media-select.c \ - media-select.h \ + media-combo.c \ + media-combo.h \ + media-combo-menu.c \ + media-combo-menu.h \ + media-combo-menu-item.c \ + media-combo-menu-item.h \ message-bar.c \ message-bar.h \ template-history.c \ diff --git a/src/media-combo-menu-item.c b/src/media-combo-menu-item.c new file mode 100644 index 00000000..0c3225fc --- /dev/null +++ b/src/media-combo-menu-item.c @@ -0,0 +1,178 @@ +/* + * media-combo-menu-item.c + * Copyright (C) 2010 Jim Evins . + * + * This file is part of gLabels. + * + * gLabels 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 3 of the License, or + * (at your option) any later version. + * + * gLabels 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 gLabels. If not, see . + */ + +#include + +#include "media-combo-menu-item.h" + +#include +#include + +#include +#include "mini-preview-pixbuf-cache.h" +#include "prefs.h" +#include "str-util.h" +#include "marshal.h" + + + +/*===========================================*/ +/* Private macros and constants. */ +/*===========================================*/ + + +/*===========================================*/ +/* Private types */ +/*===========================================*/ + +struct _glMediaComboMenuItemPrivate { + + gchar *name; + +}; + + +/*===========================================*/ +/* Private globals */ +/*===========================================*/ + + +/*===========================================*/ +/* Local function prototypes */ +/*===========================================*/ + +static void gl_media_combo_menu_item_finalize (GObject *object); + + +/****************************************************************************/ +/* Boilerplate Object stuff. */ +/****************************************************************************/ +G_DEFINE_TYPE (glMediaComboMenuItem, gl_media_combo_menu_item, GTK_TYPE_MENU_ITEM); + + +/*****************************************************************************/ +/* Class Init Function. */ +/*****************************************************************************/ +static void +gl_media_combo_menu_item_class_init (glMediaComboMenuItemClass *class) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (class); + + gl_media_combo_menu_item_parent_class = g_type_class_peek_parent (class); + + gobject_class->finalize = gl_media_combo_menu_item_finalize; +} + + +/*****************************************************************************/ +/* Object Instance Init Function. */ +/*****************************************************************************/ +static void +gl_media_combo_menu_item_init (glMediaComboMenuItem *this) +{ + this->priv = g_new0 (glMediaComboMenuItemPrivate, 1); +} + + +/*****************************************************************************/ +/* Finalize Method. */ +/*****************************************************************************/ +static void +gl_media_combo_menu_item_finalize (GObject *object) +{ + glMediaComboMenuItem *this = GL_MEDIA_COMBO_MENU_ITEM (object); + + g_return_if_fail (object != NULL); + g_return_if_fail (GL_IS_MEDIA_COMBO_MENU_ITEM (object)); + + g_free (this->priv->name); + g_free (this->priv); + + G_OBJECT_CLASS (gl_media_combo_menu_item_parent_class)->finalize (object); +} + + +/*****************************************************************************/ +/** New Object Generator. */ +/*****************************************************************************/ +GtkWidget * +gl_media_combo_menu_item_new (gchar *name) +{ + glMediaComboMenuItem *this; + GtkWidget *hbox; + GtkWidget *preview; + GtkWidget *label; + GdkPixbuf *pixbuf; + lglTemplate *template; + lglTemplateFrame *frame; + gchar *size_string; + gchar *layout_string; + gchar *label_markup; + + this = g_object_new (GL_TYPE_MEDIA_COMBO_MENU_ITEM, NULL); + + this->priv->name = g_strdup (name); + + hbox = gtk_hbox_new (FALSE, 6); + gtk_container_add (GTK_CONTAINER (this), hbox); + + pixbuf = gl_mini_preview_pixbuf_cache_get_pixbuf (name); + preview = gtk_image_new_from_pixbuf (pixbuf); + gtk_box_pack_start (GTK_BOX (hbox), preview, FALSE, FALSE, 0); + g_object_unref (G_OBJECT (pixbuf)); + + template = lgl_db_lookup_template_from_name (name); + frame = (lglTemplateFrame *)template->frames->data; + size_string = lgl_template_frame_get_size_description (frame, gl_prefs_model_get_units (gl_prefs)); + layout_string = lgl_template_frame_get_layout_description (frame); + label_markup = g_strdup_printf ("%s: %s\n%s\n%s", + name, template->description, size_string, layout_string); + g_free (size_string); + g_free (layout_string); + lgl_template_free (template); + + label = gtk_label_new (NULL); + gtk_label_set_markup (GTK_LABEL (label), label_markup); + g_free (label_markup); + gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0); + + return GTK_WIDGET (this); +} + + +/*****************************************************************************/ +/* Get family. */ +/*****************************************************************************/ +gchar * +gl_media_combo_menu_item_get_name (glMediaComboMenuItem *this) +{ + return g_strdup (this->priv->name); +} + + + +/* + * Local Variables: -- emacs + * mode: C -- emacs + * c-basic-offset: 8 -- emacs + * tab-width: 8 -- emacs + * indent-tabs-mode: nil -- emacs + * End: -- emacs + */ diff --git a/src/media-combo-menu-item.h b/src/media-combo-menu-item.h new file mode 100644 index 00000000..4aa6ad42 --- /dev/null +++ b/src/media-combo-menu-item.h @@ -0,0 +1,75 @@ +/* + * media-combo-menu-item.h + * Copyright (C) 2010 Jim Evins . + * + * This file is part of gLabels. + * + * gLabels 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 3 of the License, or + * (at your option) any later version. + * + * gLabels 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 gLabels. If not, see . + */ + +#ifndef __MEDIA_COMBO_MENU_ITEM_H__ +#define __MEDIA_COMBO_MENU_ITEM_H__ + + +#include + + +G_BEGIN_DECLS + +#define GL_TYPE_MEDIA_COMBO_MENU_ITEM (gl_media_combo_menu_item_get_type ()) +#define GL_MEDIA_COMBO_MENU_ITEM(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), GL_TYPE_MEDIA_COMBO_MENU_ITEM, glMediaComboMenuItem )) +#define GL_MEDIA_COMBO_MENU_ITEM_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), GL_TYPE_MEDIA_COMBO_MENU_ITEM, glMediaComboMenuItemClass)) +#define GL_IS_MEDIA_COMBO_MENU_ITEM(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GL_TYPE_MEDIA_COMBO_MENU_ITEM)) +#define GL_IS_MEDIA_COMBO_MENU_ITEM_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), GL_TYPE_MEDIA_COMBO_MENU_ITEM)) + +typedef struct _glMediaComboMenuItem glMediaComboMenuItem; +typedef struct _glMediaComboMenuItemPrivate glMediaComboMenuItemPrivate; +typedef struct _glMediaComboMenuItemClass glMediaComboMenuItemClass; + +struct _glMediaComboMenuItem { + GtkMenuItem parent_widget; + + glMediaComboMenuItemPrivate *priv; +}; + +struct _glMediaComboMenuItemClass { + GtkMenuItemClass parent_class; +}; + + +GType gl_media_combo_menu_item_get_type (void) G_GNUC_CONST; + +GtkWidget *gl_media_combo_menu_item_new (gchar *name); + +gchar *gl_media_combo_menu_item_get_name (glMediaComboMenuItem *this); + + +G_END_DECLS + +#endif /* __MEDIA_COMBO_MENU_ITEM_H__ */ + + + +/* + * Local Variables: -- emacs + * mode: C -- emacs + * c-basic-offset: 8 -- emacs + * tab-width: 8 -- emacs + * indent-tabs-mode: nil -- emacs + * End: -- emacs + */ diff --git a/src/media-combo-menu.c b/src/media-combo-menu.c new file mode 100644 index 00000000..4f117d50 --- /dev/null +++ b/src/media-combo-menu.c @@ -0,0 +1,332 @@ +/* + * media-combo-menu.c + * Copyright (C) 2010 Jim Evins . + * + * This file is part of gLabels. + * + * gLabels 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 3 of the License, or + * (at your option) any later version. + * + * gLabels 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 gLabels. If not, see . + */ + +#include + +#include "media-combo-menu.h" + +#include +#include + +#include +#include "media-combo-menu-item.h" +#include "template-history.h" +#include "marshal.h" + + +/*===========================================*/ +/* Private macros and constants. */ +/*===========================================*/ + + +/*===========================================*/ +/* Private types */ +/*===========================================*/ + +struct _glMediaComboMenuPrivate { + + gchar *media; + + GtkWidget *recent_menu_item; + GtkWidget *recent_sub_menu; + +}; + +enum { + MEDIA_CHANGED, + LAST_SIGNAL +}; + + +/*===========================================*/ +/* Private globals */ +/*===========================================*/ + +static guint signals[LAST_SIGNAL] = {0}; + + +/*===========================================*/ +/* Local function prototypes */ +/*===========================================*/ + +static void gl_media_combo_menu_finalize (GObject *object); + +static void menu_item_activate_cb (glMediaComboMenuItem *item, + glMediaComboMenu *this); + +static GtkWidget *new_brand_sub_menu (glMediaComboMenu *this, + const gchar *paper_id, + const GList *brand_list); + +static GtkWidget *new_part_sub_menu (glMediaComboMenu *this, + const GList *part_list); + +static void media_history_changed_cb (glMediaComboMenu *this); + + + +/****************************************************************************/ +/* Boilerplate Object stuff. */ +/****************************************************************************/ +G_DEFINE_TYPE (glMediaComboMenu, gl_media_combo_menu, GTK_TYPE_MENU); + + +/*****************************************************************************/ +/* Class Init Function. */ +/*****************************************************************************/ +static void +gl_media_combo_menu_class_init (glMediaComboMenuClass *class) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (class); + + gl_media_combo_menu_parent_class = g_type_class_peek_parent (class); + + gobject_class->finalize = gl_media_combo_menu_finalize; + + signals[MEDIA_CHANGED] = + g_signal_new ("media_changed", + G_OBJECT_CLASS_TYPE (gobject_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (glMediaComboMenuClass, media_changed), + NULL, NULL, + gl_marshal_VOID__VOID, + G_TYPE_NONE, 0); +} + + +/*****************************************************************************/ +/* Object Instance Init Function. */ +/*****************************************************************************/ +static void +gl_media_combo_menu_init (glMediaComboMenu *this) +{ + GtkWidget *menu_item; + GtkWidget *sub_menu; + const GList *list; + GList *paper_id_list, *p_id; + gchar *paper_id, *paper_name; + GList *brand_list; + + this->priv = g_new0 (glMediaComboMenuPrivate, 1); + + + menu_item = gtk_menu_item_new_with_label (_("Recent templates")); + gtk_menu_shell_append (GTK_MENU_SHELL (this), menu_item); + + list = gl_template_history_model_get_name_list (gl_template_history); + sub_menu = new_part_sub_menu (this, list); + gtk_menu_item_set_submenu (GTK_MENU_ITEM (menu_item), sub_menu); + gtk_widget_set_sensitive (menu_item, list != NULL); + + this->priv->recent_menu_item = menu_item; + this->priv->recent_sub_menu = sub_menu; + + menu_item = gtk_separator_menu_item_new (); + gtk_menu_shell_append (GTK_MENU_SHELL (this), menu_item); + + paper_id_list = lgl_db_get_paper_id_list (); + + for ( p_id = paper_id_list; p_id; p_id = p_id->next ) + { + paper_id = p_id->data; + paper_name = lgl_db_lookup_paper_name_from_id (paper_id); + + brand_list = lgl_db_get_brand_list (paper_id, NULL); + if ( brand_list ) + { + menu_item = gtk_menu_item_new_with_label (paper_name); + gtk_menu_shell_append (GTK_MENU_SHELL (this), menu_item); + + sub_menu = new_brand_sub_menu (this, paper_id, brand_list); + gtk_menu_item_set_submenu (GTK_MENU_ITEM (menu_item), sub_menu); + } + lgl_db_free_brand_list ( brand_list ); + } + + lgl_db_free_paper_id_list (paper_id_list); + + g_signal_connect_swapped (gl_template_history, "changed", + G_CALLBACK (media_history_changed_cb), this); + +} + + +/*****************************************************************************/ +/* Finalize Method. */ +/*****************************************************************************/ +static void +gl_media_combo_menu_finalize (GObject *object) +{ + glMediaComboMenu *this = GL_MEDIA_COMBO_MENU (object); + + g_return_if_fail (object != NULL); + g_return_if_fail (GL_IS_MEDIA_COMBO_MENU (object)); + + g_free (this->priv); + + G_OBJECT_CLASS (gl_media_combo_menu_parent_class)->finalize (object); +} + + +/*****************************************************************************/ +/** New Object Generator. */ +/*****************************************************************************/ +GtkWidget * +gl_media_combo_menu_new (void) +{ + glMediaComboMenu *this; + + this = g_object_new (gl_media_combo_menu_get_type (), NULL); + + return GTK_WIDGET (this); +} + + +/*****************************************************************************/ +/* menu_item activate callback. */ +/*****************************************************************************/ +static void menu_item_activate_cb (glMediaComboMenuItem *item, + glMediaComboMenu *this) +{ + this->priv->media = gl_media_combo_menu_item_get_name (item); + + g_signal_emit (this, signals[MEDIA_CHANGED], 0); + + gtk_widget_hide (GTK_WIDGET (this)); +} + + +/*****************************************************************************/ +/* Get media name. */ +/*****************************************************************************/ +gchar * +gl_media_combo_menu_get_name (glMediaComboMenu *this) +{ + return g_strdup (this->priv->media); +} + + +/*****************************************************************************/ +/* Create a new brand sub menu from media list. */ +/*****************************************************************************/ +static GtkWidget * +new_brand_sub_menu (glMediaComboMenu *this, + const gchar *paper_id, + const GList *brand_list) +{ + GtkWidget *menu; + GtkWidget *menu_item; + GtkWidget *sub_menu; + GList *p_brand; + gchar *brand; + GList *part_list; + + menu = gtk_menu_new (); + + for ( p_brand = (GList *)brand_list; p_brand; p_brand = p_brand->next ) + { + brand = p_brand->data; + + part_list = lgl_db_get_template_name_list_all (brand, paper_id, NULL); + if ( part_list ) + { + menu_item = gtk_menu_item_new_with_label (brand); + gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item); + + sub_menu = new_part_sub_menu (this, part_list); + gtk_menu_item_set_submenu (GTK_MENU_ITEM (menu_item), sub_menu); + } + lgl_db_free_brand_list ( part_list ); + } + + gtk_widget_show (menu); + + return menu; +} + + +/*****************************************************************************/ +/* Create a new part sub menu from part list. */ +/*****************************************************************************/ +static GtkWidget * +new_part_sub_menu (glMediaComboMenu *this, + const GList *part_list) +{ + GtkWidget *menu; + GtkWidget *menu_item; + GList *p; + + menu = gtk_menu_new (); + + for ( p = (GList *)part_list; p != NULL; p = p->next ) + { + menu_item = gl_media_combo_menu_item_new (p->data); + gtk_widget_show_all (menu_item); + gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item); + g_signal_connect (menu_item, "activate", + G_CALLBACK (menu_item_activate_cb), this); + } + + gtk_widget_show (menu); + return menu; +} + + +/*****************************************************************************/ +/* Media history changed callback. */ +/*****************************************************************************/ +static void +media_history_changed_cb (glMediaComboMenu *this) +{ + GList *list; + + /* + * Remove old sub menu + */ + gtk_menu_item_set_submenu (GTK_MENU_ITEM (this->priv->recent_menu_item), + NULL); + + /* + * Build new sub menu + */ + list = gl_template_history_model_get_name_list (gl_template_history); + this->priv->recent_sub_menu = new_part_sub_menu (this, list); + + /* + * Attach to top-level menu item + */ + gtk_menu_item_set_submenu (GTK_MENU_ITEM (this->priv->recent_menu_item), + this->priv->recent_sub_menu); + gtk_widget_set_sensitive (this->priv->recent_menu_item, list != NULL); + + gl_template_history_model_free_name_list (list); +} + + + + +/* + * Local Variables: -- emacs + * mode: C -- emacs + * c-basic-offset: 8 -- emacs + * tab-width: 8 -- emacs + * indent-tabs-mode: nil -- emacs + * End: -- emacs + */ diff --git a/src/media-combo-menu.h b/src/media-combo-menu.h new file mode 100644 index 00000000..5c83e587 --- /dev/null +++ b/src/media-combo-menu.h @@ -0,0 +1,83 @@ +/* + * media-combo-menu.h + * Copyright (C) 2010 Jim Evins . + * + * This file is part of gLabels. + * + * gLabels 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 3 of the License, or + * (at your option) any later version. + * + * gLabels 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 gLabels. If not, see . + */ + +#ifndef __MEDIA_COMBO_MENU_H__ +#define __MEDIA_COMBO_MENU_H__ + +#include + + +G_BEGIN_DECLS + +#define GL_TYPE_MEDIA_COMBO_MENU (gl_media_combo_menu_get_type ()) +#define GL_MEDIA_COMBO_MENU(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), GL_TYPE_MEDIA_COMBO_MENU, glMediaComboMenu )) +#define GL_MEDIA_COMBO_MENU_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), GL_TYPE_MEDIA_COMBO_MENU, glMediaComboMenuClass)) +#define GL_IS_MEDIA_COMBO_MENU(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GL_TYPE_MEDIA_COMBO_MENU)) +#define GL_IS_MEDIA_COMBO_MENU_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), GL_TYPE_MEDIA_COMBO_MENU)) + +typedef struct _glMediaComboMenu glMediaComboMenu; +typedef struct _glMediaComboMenuPrivate glMediaComboMenuPrivate; +typedef struct _glMediaComboMenuClass glMediaComboMenuClass; + +struct _glMediaComboMenu { + GtkMenu parent_widget; + + glMediaComboMenuPrivate *priv; +}; + +struct _glMediaComboMenuClass { + GtkMenuClass parent_class; + + /* + * Signals + */ + void (*media_changed) (glMediaComboMenu *object, + gpointer user_data); + +}; + + +GType gl_media_combo_menu_get_type (void) G_GNUC_CONST; + +GtkWidget *gl_media_combo_menu_new (void); + +gchar *gl_media_combo_menu_get_name (glMediaComboMenu *this); + + +G_END_DECLS + + +#endif /* __MEDIA_COMBO_MENU_H__ */ + + + +/* + * Local Variables: -- emacs + * mode: C -- emacs + * c-basic-offset: 8 -- emacs + * tab-width: 8 -- emacs + * indent-tabs-mode: nil -- emacs + * End: -- emacs + */ + diff --git a/src/media-combo.c b/src/media-combo.c new file mode 100644 index 00000000..6c7104e8 --- /dev/null +++ b/src/media-combo.c @@ -0,0 +1,345 @@ +/* + * media-combo.c + * Copyright (C) 2010 Jim Evins . + * + * This file is part of gLabels. + * + * gLabels 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 3 of the License, or + * (at your option) any later version. + * + * gLabels 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 gLabels. If not, see . + */ + +#include + +#include "media-combo.h" + +#include +#include + +#include "media-combo-menu.h" +#include "marshal.h" + + + +/*========================================================*/ +/* Private types. */ +/*========================================================*/ + +/** GL_MEDIA_COMBO Private fields */ +struct _glMediaComboPrivate { + + gchar *name; + + GtkWidget *label; + + GtkWidget *menu; +}; + +enum { + CHANGED, + LAST_SIGNAL +}; + + +/*========================================================*/ +/* Private globals. */ +/*========================================================*/ + +static guint signals[LAST_SIGNAL] = {0}; + + +/*========================================================*/ +/* Private function prototypes. */ +/*========================================================*/ + +static void gl_media_combo_finalize (GObject *object); + +static gboolean +button_press_event_cb (GtkWidget *widget, + GdkEventButton *event, + glMediaCombo *this); + +static void +menu_media_changed_cb (glMediaComboMenu *menu, + glMediaCombo *this); + +static void +menu_selection_done_cb (GtkMenuShell *object, + glMediaCombo *this); + + +/*****************************************************************************/ +/* Object infrastructure. */ +/*****************************************************************************/ +G_DEFINE_TYPE (glMediaCombo, gl_media_combo, GTK_TYPE_TOGGLE_BUTTON); + + +/*****************************************************************************/ +/* Class Init Function. */ +/*****************************************************************************/ +static void +gl_media_combo_class_init (glMediaComboClass *class) +{ + GObjectClass *gobject_class = (GObjectClass *) class; + + gl_media_combo_parent_class = g_type_class_peek_parent (class); + + gobject_class->finalize = gl_media_combo_finalize; + + signals[CHANGED] = + g_signal_new ("changed", + G_OBJECT_CLASS_TYPE (gobject_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (glMediaComboClass, changed), + NULL, NULL, + gl_marshal_VOID__VOID, + G_TYPE_NONE, 0); +} + + +/*****************************************************************************/ +/* Object Instance Init Function. */ +/*****************************************************************************/ +static void +gl_media_combo_init (glMediaCombo *this) +{ + GtkWidget *hbox; + GtkWidget *arrow; + + this->priv = g_new0 (glMediaComboPrivate, 1); + + hbox = gtk_hbox_new (FALSE, 3); + gtk_container_add (GTK_CONTAINER (this), hbox); + + this->priv->label = gtk_label_new (""); + gtk_misc_set_alignment (GTK_MISC (this->priv->label), 0.0, 0.5); + gtk_widget_set_size_request (this->priv->label, 180, -1); + gtk_box_pack_start (GTK_BOX (hbox), this->priv->label, TRUE, TRUE, 0); + + arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_IN); + gtk_box_pack_end (GTK_BOX (hbox), arrow, FALSE, FALSE, 0); + + g_signal_connect (this, "button_press_event", + G_CALLBACK(button_press_event_cb), this); +} + + +/*****************************************************************************/ +/* Finalize Method. */ +/*****************************************************************************/ +static void +gl_media_combo_finalize (GObject *object) +{ + glMediaCombo *this; + + g_return_if_fail (object && IS_GL_MEDIA_COMBO (object)); + this = GL_MEDIA_COMBO (object); + + g_free (this->priv->name); + g_object_ref_sink (this->priv->menu); + g_free (this->priv); + + G_OBJECT_CLASS (gl_media_combo_parent_class)->finalize (object); +} + + +/*****************************************************************************/ +/** New Object Generator. */ +/*****************************************************************************/ +GtkWidget * +gl_media_combo_new (void) +{ + glMediaCombo *this; + + this = g_object_new (TYPE_GL_MEDIA_COMBO, NULL); + + this->priv->menu = gl_media_combo_menu_new (); + + gtk_widget_show_all (this->priv->menu); + + g_signal_connect (this->priv->menu, "media_changed", + G_CALLBACK (menu_media_changed_cb), this); + g_signal_connect (this->priv->menu, "selection_done", + G_CALLBACK (menu_selection_done_cb), this); + + return GTK_WIDGET (this); +} + + +/*****************************************************************************/ +/* Set media name. */ +/*****************************************************************************/ +void +gl_media_combo_set_name (glMediaCombo *this, + const gchar *name) +{ + + g_free (this->priv->name); + this->priv->name = g_strdup (name); + + gtk_label_set_text (GTK_LABEL (this->priv->label), this->priv->name); +} + + +/*****************************************************************************/ +/* Get media name. */ +/*****************************************************************************/ +gchar * +gl_media_combo_get_name (glMediaCombo *this) +{ + return g_strdup (this->priv->name); +} + + +/*****************************************************************************/ +/* Menu positioning function. */ +/*****************************************************************************/ +static void +menu_position_function (GtkMenu *menu, + gint *x, + gint *y, + gboolean *push_in, + glMediaCombo *this) +{ + GdkScreen *screen; + gint w_screen, h_screen; + GdkWindow *window; + gint x_window, y_window; + GtkAllocation allocation; + gint x_this, y_this, h_this; + GtkRequisition menu_requisition; + gint h_menu, w_menu; + + /* + * Screen size + */ + screen = gtk_widget_get_screen (GTK_WIDGET (this)); + w_screen = gdk_screen_get_width (screen); + h_screen = gdk_screen_get_height (screen); + + /* + * Absolute position of "this" window on screen. + */ + window = gtk_widget_get_window (GTK_WIDGET (this)); + gdk_window_get_origin (window, &x_window, &y_window); + + /* + * Position and size of "this" inside window + */ + gtk_widget_get_allocation (GTK_WIDGET (this), &allocation); + x_this = allocation.x; + y_this = allocation.y; + h_this = allocation.height; + + /* + * Size of menu. + */ + gtk_widget_size_request (this->priv->menu, &menu_requisition); + h_menu = menu_requisition.height; + w_menu = menu_requisition.width; + + /* + * Default position anchored to lower left corner of "this". + */ + *x = x_window + x_this; + *y = y_window + y_this + h_this; + + /* + * Adjust vertical position if menu if extends past bottom of screen. + */ + if ( (*y + h_menu) > h_screen ) + { + *y = y_window + y_this - h_menu; + + if ( *y < 0 ) + { + *y = h_screen - h_menu; + } + } + + /* + * Adjust horizontal position if menu if extends past edge of screen. + */ + if ( (*x + w_menu) > w_screen ) + { + *x = w_screen - w_menu; + } + + + *push_in = TRUE; +} + + +/*****************************************************************************/ +/* Button "button_press_event" callback. */ +/*****************************************************************************/ +static gboolean +button_press_event_cb (GtkWidget *widget, + GdkEventButton *event, + glMediaCombo *this) +{ + switch (event->button) + { + + case 1: + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (this), TRUE); + + gtk_menu_popup (GTK_MENU (this->priv->menu), + NULL, NULL, + (GtkMenuPositionFunc)menu_position_function, this, + event->button, event->time); + break; + + default: + break; + + } + + return FALSE; +} + + +/*****************************************************************************/ +/* Menu "media changed" callback. */ +/*****************************************************************************/ +static void +menu_media_changed_cb (glMediaComboMenu *menu, + glMediaCombo *this) +{ + this->priv->name = gl_media_combo_menu_get_name (menu); + + gtk_label_set_text (GTK_LABEL (this->priv->label), this->priv->name); + + g_signal_emit (this, signals[CHANGED], 0); +} + + +/*****************************************************************************/ +/* Menu "selection done" callback. */ +/*****************************************************************************/ +static void +menu_selection_done_cb (GtkMenuShell *object, + glMediaCombo *this) +{ + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (this), FALSE); +} + + + +/* + * Local Variables: -- emacs + * mode: C -- emacs + * c-basic-offset: 8 -- emacs + * tab-width: 8 -- emacs + * indent-tabs-mode: nil -- emacs + * End: -- emacs + */ diff --git a/src/media-combo.h b/src/media-combo.h new file mode 100644 index 00000000..c413d14b --- /dev/null +++ b/src/media-combo.h @@ -0,0 +1,84 @@ +/* + * media-combo.h + * Copyright (C) 2009 Jim Evins . + * + * This file is part of gLabels. + * + * gLabels 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 3 of the License, or + * (at your option) any later version. + * + * gLabels 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 gLabels. If not, see . + */ + +#ifndef __GL_MEDIA_COMBO_H__ +#define __GL_MEDIA_COMBO_H__ + + +#include + + +G_BEGIN_DECLS + +#define TYPE_GL_MEDIA_COMBO (gl_media_combo_get_type ()) +#define GL_MEDIA_COMBO(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_GL_MEDIA_COMBO, glMediaCombo)) +#define GL_MEDIA_COMBO_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_GL_MEDIA_COMBO, glMediaComboClass)) +#define IS_GL_MEDIA_COMBO(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_GL_MEDIA_COMBO)) +#define IS_GL_MEDIA_COMBO_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_GL_MEDIA_COMBO)) +#define GL_MEDIA_COMBO_GET_CLASS(object) (G_TYPE_INSTANCE_GET_CLASS ((object), TYPE_GL_MEDIA_COMBO, glMediaComboClass)) + + +typedef struct _glMediaCombo glMediaCombo; +typedef struct _glMediaComboPrivate glMediaComboPrivate; +typedef struct _glMediaComboClass glMediaComboClass; + + +struct _glMediaCombo { + GtkToggleButton parent; + + glMediaComboPrivate *priv; +}; + +struct _glMediaComboClass { + GtkToggleButtonClass parent_class; + + /* + * Signals + */ + void (*changed) (glMediaCombo *object, + gpointer user_data); + +}; + + +GType gl_media_combo_get_type (void) G_GNUC_CONST; + +GtkWidget *gl_media_combo_new (void); + +void gl_media_combo_set_name (glMediaCombo *this, + const gchar *name); + +gchar *gl_media_combo_get_name (glMediaCombo *this); + + +G_END_DECLS + +#endif /* __GL_COLOR_COMBO_H__ */ + + + +/* + * Local Variables: -- emacs + * mode: C -- emacs + * c-basic-offset: 8 -- emacs + * tab-width: 8 -- emacs + * indent-tabs-mode: nil -- emacs + * End: -- emacs + */ diff --git a/src/media-select.c b/src/media-select.c deleted file mode 100644 index 98dc8446..00000000 --- a/src/media-select.c +++ /dev/null @@ -1,937 +0,0 @@ -/* - * media-select.c - * Copyright (C) 2001-2009 Jim Evins . - * - * This file is part of gLabels. - * - * gLabels 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 3 of the License, or - * (at your option) any later version. - * - * gLabels 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 gLabels. If not, see . - */ - -#include - -#include "media-select.h" - -#include -#include -#include - -#include -#include "mini-preview-pixbuf-cache.h" -#include "prefs.h" -#include "message-bar.h" -#include "template-history.h" -#include "str-util.h" -#include "combo-util.h" -#include "builder-util.h" -#include "color.h" -#include "marshal.h" - -#include "debug.h" - - -#define HISTORY_SIZE 5 - -/*===========================================*/ -/* Private types */ -/*===========================================*/ - -enum { - NAME_COLUMN, - PREVIEW_COLUMN, - PREVIEW_COLUMN_STOCK, - PREVIEW_COLUMN_STOCK_SIZE, - DESCRIPTION_COLUMN, - N_COLUMNS -}; - -struct _glMediaSelectPrivate { - - GtkBuilder *builder; - - GtkWidget *notebook; - guint current_page_num; - - gint recent_page_num; - GtkWidget *recent_tab_vbox; - GtkWidget *recent_info_vbox; - GtkWidget *recent_info_bar; - GtkWidget *recent_treeview; - GtkListStore *recent_store; - - gint search_all_page_num; - GtkWidget *search_all_tab_vbox; - GtkWidget *search_all_info_vbox; - GtkWidget *search_all_info_bar; - GtkWidget *brand_combo; - GtkWidget *page_size_combo; - GtkWidget *category_combo; - GtkWidget *search_all_treeview; - GtkListStore *search_all_store; - - /* Prevent recursion */ - gboolean stop_signals; -}; - -enum { - CHANGED, - LAST_SIGNAL -}; - - -/*===========================================*/ -/* Private globals */ -/*===========================================*/ - -static gint media_select_signals[LAST_SIGNAL] = { 0 }; - - -/*===========================================*/ -/* Local function prototypes */ -/*===========================================*/ - -static void gl_media_select_finalize (GObject *object); - -static void gl_media_select_construct (glMediaSelect *this); - -static void filter_changed_cb (GtkComboBox *combo, - gpointer user_data); - -static void selection_changed_cb (GtkTreeSelection *selection, - gpointer user_data); - -static void page_changed_cb (GtkNotebook *notebook, - GtkNotebookPage *page, - guint page_num, - gpointer user_data); - -static gchar *get_layout_desc (const lglTemplate *template); - -static gchar *get_label_size_desc (const lglTemplate *template); - -static void load_recent_list (glMediaSelect *this, - GtkListStore *store, - GtkTreeSelection *selection, - GList *list); - -static void load_search_all_list (glMediaSelect *this, - GtkListStore *store, - GtkTreeSelection *selection, - GList *list); - - -/****************************************************************************/ -/* Boilerplate Object stuff. */ -/****************************************************************************/ -G_DEFINE_TYPE (glMediaSelect, gl_media_select, GTK_TYPE_VBOX); - - -static void -gl_media_select_class_init (glMediaSelectClass *class) -{ - GObjectClass *object_class = G_OBJECT_CLASS (class); - - gl_debug (DEBUG_MEDIA_SELECT, "START"); - - gl_media_select_parent_class = g_type_class_peek_parent (class); - - object_class->finalize = gl_media_select_finalize; - - media_select_signals[CHANGED] = - g_signal_new ("changed", - G_OBJECT_CLASS_TYPE(object_class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (glMediaSelectClass, changed), - NULL, NULL, - gl_marshal_VOID__VOID, - G_TYPE_NONE, 0); - - gl_debug (DEBUG_MEDIA_SELECT, "END"); -} - - -static void -gl_media_select_init (glMediaSelect *this) -{ - gl_debug (DEBUG_MEDIA_SELECT, "START"); - - this->priv = g_new0 (glMediaSelectPrivate, 1); - - gl_debug (DEBUG_MEDIA_SELECT, "END"); -} - - -static void -gl_media_select_finalize (GObject *object) -{ - glMediaSelect *this = GL_MEDIA_SELECT (object); - - gl_debug (DEBUG_MEDIA_SELECT, "START"); - - g_return_if_fail (object != NULL); - g_return_if_fail (GL_IS_MEDIA_SELECT (object)); - - if (this->priv->builder) - { - g_object_unref (this->priv->builder); - } - g_object_unref (this->priv->recent_store); - g_object_unref (this->priv->search_all_store); - g_free (this->priv); - - G_OBJECT_CLASS (gl_media_select_parent_class)->finalize (object); - - gl_debug (DEBUG_MEDIA_SELECT, "END"); -} - - -GtkWidget * -gl_media_select_new (void) -{ - glMediaSelect *this; - - gl_debug (DEBUG_MEDIA_SELECT, "START"); - - this = g_object_new (gl_media_select_get_type (), NULL); - - gl_media_select_construct (this); - - gl_debug (DEBUG_MEDIA_SELECT, "END"); - - return GTK_WIDGET (this); -} - - -/*--------------------------------------------------------------------------*/ -/* PRIVATE. Construct composite widget. */ -/*--------------------------------------------------------------------------*/ -static void -gl_media_select_construct (glMediaSelect *this) -{ - gchar *builder_filename; - GtkBuilder *builder; - static gchar *object_ids[] = { "media_select_hbox", NULL }; - GError *error = NULL; - GtkWidget *hbox; - GList *recent_list = NULL; - GList *brands = NULL; - GList *page_sizes = NULL; - GList *categories = NULL; - GList *search_all_names = NULL; - const gchar *page_size_id; - gchar *page_size_name; - GtkCellRenderer *renderer; - GtkTreeViewColumn *column; - GtkTreeSelection *recent_selection; - GtkTreeSelection *search_all_selection; - - gl_debug (DEBUG_MEDIA_SELECT, "START"); - - g_return_if_fail (GL_IS_MEDIA_SELECT (this)); - g_return_if_fail (this->priv != NULL); - - builder = gtk_builder_new (); - builder_filename = g_build_filename (GLABELS_DATA_DIR, "builder", "media-select.builder", NULL); - gtk_builder_add_objects_from_file (builder, builder_filename, object_ids, &error); - g_free (builder_filename); - if (error) { - g_critical ("%s\n\ngLabels may not be installed correctly!", error->message); - g_error_free (error); - return; - } - - gl_builder_util_get_widgets (builder, - "media_select_hbox", &hbox, - "notebook", &this->priv->notebook, - "recent_tab_vbox", &this->priv->recent_tab_vbox, - "recent_info_vbox", &this->priv->recent_info_vbox, - "recent_treeview", &this->priv->recent_treeview, - "search_all_tab_vbox", &this->priv->search_all_tab_vbox, - "brand_combo", &this->priv->brand_combo, - "page_size_combo", &this->priv->page_size_combo, - "category_combo", &this->priv->category_combo, - "search_all_info_vbox", &this->priv->search_all_info_vbox, - "search_all_treeview", &this->priv->search_all_treeview, - NULL); - - gtk_container_add (GTK_CONTAINER (this), hbox); - this->priv->builder = builder; - - this->priv->recent_page_num = - gtk_notebook_page_num (GTK_NOTEBOOK (this->priv->notebook), - this->priv->recent_tab_vbox); - this->priv->search_all_page_num = - gtk_notebook_page_num (GTK_NOTEBOOK (this->priv->notebook), - this->priv->search_all_tab_vbox); - - gtk_widget_show_all (GTK_WIDGET (this)); - - /* Recent templates treeview */ - this->priv->recent_store = gtk_list_store_new (N_COLUMNS, G_TYPE_STRING, GDK_TYPE_PIXBUF, G_TYPE_STRING, G_TYPE_UINT, G_TYPE_STRING); - gtk_tree_view_set_model (GTK_TREE_VIEW (this->priv->recent_treeview), - GTK_TREE_MODEL (this->priv->recent_store)); - renderer = gtk_cell_renderer_pixbuf_new (); - column = gtk_tree_view_column_new_with_attributes ("", renderer, - "pixbuf", PREVIEW_COLUMN, - "stock-id", PREVIEW_COLUMN_STOCK, - "stock-size", PREVIEW_COLUMN_STOCK_SIZE, - NULL); - gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_AUTOSIZE); - gtk_tree_view_append_column (GTK_TREE_VIEW (this->priv->recent_treeview), column); - renderer = gtk_cell_renderer_text_new (); - column = gtk_tree_view_column_new_with_attributes ("", renderer, - "markup", DESCRIPTION_COLUMN, - NULL); - gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_AUTOSIZE); - gtk_tree_view_append_column (GTK_TREE_VIEW (this->priv->recent_treeview), column); - recent_selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (this->priv->recent_treeview)); - recent_list = gl_template_history_model_get_name_list (gl_template_history); - load_recent_list (this, this->priv->recent_store, recent_selection, recent_list); - - page_size_id = gl_prefs_model_get_default_page_size (gl_prefs); - page_size_name = lgl_db_lookup_paper_name_from_id (page_size_id); - - /* Brand selection control */ - gl_combo_util_add_text_model (GTK_COMBO_BOX (this->priv->brand_combo)); - brands = lgl_db_get_brand_list (NULL, NULL); - brands = g_list_prepend (brands, g_strdup (_("Any"))); - gl_combo_util_set_strings (GTK_COMBO_BOX (this->priv->brand_combo), brands); - lgl_db_free_brand_list (brands); - gl_combo_util_set_active_text (GTK_COMBO_BOX (this->priv->brand_combo), - _("Any")); - - /* Page size selection control */ - gl_combo_util_add_text_model (GTK_COMBO_BOX (this->priv->page_size_combo)); - page_sizes = lgl_db_get_paper_name_list (); - page_sizes = g_list_prepend (page_sizes, g_strdup (_("Any"))); - gl_combo_util_set_strings (GTK_COMBO_BOX (this->priv->page_size_combo), page_sizes); - lgl_db_free_paper_name_list (page_sizes); - gl_combo_util_set_active_text (GTK_COMBO_BOX (this->priv->page_size_combo), - page_size_name); - - /* Category selection control */ - gl_combo_util_add_text_model (GTK_COMBO_BOX (this->priv->category_combo)); - categories = lgl_db_get_category_name_list (); - categories = g_list_prepend (categories, g_strdup (_("Any"))); - gl_combo_util_set_strings (GTK_COMBO_BOX (this->priv->category_combo), categories); - gl_combo_util_set_active_text (GTK_COMBO_BOX (this->priv->category_combo), - _("Any")); - lgl_db_free_category_name_list (categories); - - /* Search all treeview */ - this->priv->search_all_store = gtk_list_store_new (N_COLUMNS, G_TYPE_STRING, GDK_TYPE_PIXBUF, G_TYPE_STRING, G_TYPE_UINT, G_TYPE_STRING); - gtk_tree_view_set_model (GTK_TREE_VIEW (this->priv->search_all_treeview), - GTK_TREE_MODEL (this->priv->search_all_store)); - renderer = gtk_cell_renderer_pixbuf_new (); - column = gtk_tree_view_column_new_with_attributes ("", renderer, - "pixbuf", PREVIEW_COLUMN, - "stock-id", PREVIEW_COLUMN_STOCK, - "stock-size", PREVIEW_COLUMN_STOCK_SIZE, - NULL); - gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_AUTOSIZE); - gtk_tree_view_append_column (GTK_TREE_VIEW (this->priv->search_all_treeview), column); - renderer = gtk_cell_renderer_text_new (); - column = gtk_tree_view_column_new_with_attributes ("", renderer, - "markup", DESCRIPTION_COLUMN, - NULL); - gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_AUTOSIZE); - gtk_tree_view_append_column (GTK_TREE_VIEW (this->priv->search_all_treeview), column); - search_all_selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (this->priv->search_all_treeview)); - search_all_names = lgl_db_get_template_name_list_all (NULL, page_size_id, NULL); - load_search_all_list (this, this->priv->search_all_store, search_all_selection, search_all_names); - lgl_db_free_template_name_list (search_all_names); - - /* Connect signals to controls */ - g_signal_connect (G_OBJECT (this->priv->brand_combo), "changed", - G_CALLBACK (filter_changed_cb), - this); - g_signal_connect (G_OBJECT (this->priv->page_size_combo), "changed", - G_CALLBACK (filter_changed_cb), - this); - g_signal_connect (G_OBJECT (this->priv->category_combo), "changed", - G_CALLBACK (filter_changed_cb), - this); - g_signal_connect (G_OBJECT (recent_selection), "changed", - G_CALLBACK (selection_changed_cb), - this); - g_signal_connect (G_OBJECT (search_all_selection), "changed", - G_CALLBACK (selection_changed_cb), - this); - g_signal_connect (G_OBJECT (this->priv->notebook), "switch-page", - G_CALLBACK (page_changed_cb), - this); - - g_free (page_size_name); - - if ( recent_list ) - { - gtk_notebook_set_current_page (GTK_NOTEBOOK (this->priv->notebook), - this->priv->recent_page_num); - } - else - { - gtk_notebook_set_current_page (GTK_NOTEBOOK (this->priv->notebook), - this->priv->search_all_page_num); - } - gl_template_history_model_free_name_list (recent_list); - - gl_debug (DEBUG_MEDIA_SELECT, "END"); -} - - -/*--------------------------------------------------------------------------*/ -/* PRIVATE. modify widget due to change in selection */ -/*--------------------------------------------------------------------------*/ -static void -filter_changed_cb (GtkComboBox *combo, - gpointer user_data) -{ - glMediaSelect *this = GL_MEDIA_SELECT (user_data); - gchar *brand; - gchar *page_size_name, *page_size_id; - gchar *category_name, *category_id; - GList *search_all_names; - GtkTreeSelection *selection; - - gl_debug (DEBUG_MEDIA_SELECT, "START"); - - - this->priv->stop_signals = TRUE; - - /* Update template selections for new filter settings */ - brand = gtk_combo_box_get_active_text (GTK_COMBO_BOX (this->priv->brand_combo)); - page_size_name = gtk_combo_box_get_active_text (GTK_COMBO_BOX (this->priv->page_size_combo)); - category_name = gtk_combo_box_get_active_text (GTK_COMBO_BOX (this->priv->category_combo)); - if ( brand && strlen(brand) && - page_size_name && strlen(page_size_name) && - category_name && strlen(category_name) ) - { - gl_debug (DEBUG_MEDIA_SELECT, "brand = \"%s\"", brand); - gl_debug (DEBUG_MEDIA_SELECT, "page_size_name = \"%s\"", page_size_name); - gl_debug (DEBUG_MEDIA_SELECT, "category_name = \"%s\"", category_name); - if (!g_utf8_collate (brand, _("Any"))) - { - g_free (brand); - brand = NULL; - } - page_size_id = lgl_db_lookup_paper_id_from_name (page_size_name); - category_id = lgl_db_lookup_category_id_from_name (category_name); - gl_debug (DEBUG_MEDIA_SELECT, "page_size_id = \"%s\"", page_size_id); - gl_debug (DEBUG_MEDIA_SELECT, "category_id = \"%s\"", category_id); - search_all_names = lgl_db_get_template_name_list_all (brand, page_size_id, category_id); - selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (this->priv->search_all_treeview)); - load_search_all_list (this, this->priv->search_all_store, selection, search_all_names); - lgl_db_free_template_name_list (search_all_names); - g_free (page_size_id); - g_free (category_id); - - /* Emit our "changed" signal */ - g_signal_emit (G_OBJECT (user_data), - media_select_signals[CHANGED], 0); - } - g_free (brand); - g_free (page_size_name); - g_free (category_name); - - - this->priv->stop_signals = FALSE; - - gl_debug (DEBUG_MEDIA_SELECT, "END"); -} - - -/*--------------------------------------------------------------------------*/ -/* PRIVATE. modify widget due to change in selection */ -/*--------------------------------------------------------------------------*/ -static void -selection_changed_cb (GtkTreeSelection *selection, - gpointer user_data) -{ - glMediaSelect *this = GL_MEDIA_SELECT (user_data); - - if (this->priv->stop_signals) return; - - gl_debug (DEBUG_MEDIA_SELECT, "START"); - - /* Emit our "changed" signal */ - g_signal_emit (G_OBJECT (user_data), - media_select_signals[CHANGED], 0); - - gl_debug (DEBUG_MEDIA_SELECT, "END"); -} - - -/*--------------------------------------------------------------------------*/ -/* PRIVATE. modify widget due to change in selection */ -/*--------------------------------------------------------------------------*/ -static void -page_changed_cb (GtkNotebook *notebook, - GtkNotebookPage *page, - guint page_num, - gpointer user_data) -{ - glMediaSelect *this = GL_MEDIA_SELECT (user_data); - - if (this->priv->stop_signals) return; - - gl_debug (DEBUG_MEDIA_SELECT, "START"); - - /* - * Store new current page, because this signal is emitted before the actual page change. - */ - this->priv->current_page_num = page_num; - - /* Emit our "changed" signal */ - g_signal_emit (G_OBJECT (user_data), - media_select_signals[CHANGED], 0); - - gl_debug (DEBUG_MEDIA_SELECT, "END"); -} - - -/****************************************************************************/ -/* query selected label template name. */ -/****************************************************************************/ -gchar * -gl_media_select_get_name (glMediaSelect *this) -{ - gint page_num; - GtkTreeSelection *selection; - GtkTreeIter iter; - GtkTreeModel *model; - gchar *name; - - gl_debug (DEBUG_MEDIA_SELECT, "START"); - - page_num = this->priv->current_page_num; - if (page_num == this->priv->recent_page_num) - { - selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (this->priv->recent_treeview)); - } - else if (page_num == this->priv->search_all_page_num) - { - selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (this->priv->search_all_treeview)); - } - else - { - g_print ("notebook page = %d\n", page_num); - g_assert_not_reached (); - } - - if (gtk_tree_selection_get_mode (selection) == GTK_SELECTION_NONE) - { - name = NULL; - } - else - { - gtk_tree_selection_get_selected (selection, &model, &iter); - gtk_tree_model_get (model, &iter, NAME_COLUMN, &name, -1); - } - - gl_debug (DEBUG_MEDIA_SELECT, "END"); - return name; -} - - -/****************************************************************************/ -/* set selected label template name. */ -/****************************************************************************/ -void -gl_media_select_set_name (glMediaSelect *this, - gchar *name) -{ - GtkTreeSelection *selection; - GtkTreeModel *model; - GtkTreeIter iter; - GtkTreePath *path; - gchar *name_i; - gboolean flag; - - gl_debug (DEBUG_MEDIA_SELECT, "START"); - - selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (this->priv->search_all_treeview)); - g_return_if_fail (GTK_IS_TREE_SELECTION (selection)); - - model = GTK_TREE_MODEL (this->priv->search_all_store); - - for ( flag = gtk_tree_model_get_iter_first (model, &iter); - flag; - flag = gtk_tree_model_iter_next(model, &iter) ) - { - gtk_tree_model_get (model, &iter, NAME_COLUMN, &name_i, -1); - if (strcasecmp(name, name_i) == 0) - { - gtk_tree_selection_select_iter (selection, &iter); - path = gtk_tree_model_get_path (model, &iter); - gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (this->priv->search_all_treeview), - path, - NULL, - TRUE, 0.5, 0.0); - gtk_tree_path_free (path); - break; - } - } - - gl_debug (DEBUG_MEDIA_SELECT, "END"); -} - - -/****************************************************************************/ -/* query current filter parameters. */ -/****************************************************************************/ -void -gl_media_select_get_filter_parameters (glMediaSelect *this, - gchar **page_size_id, - gchar **category_id) -{ - gchar *page_size_name, *category_name; - - gl_debug (DEBUG_MEDIA_SELECT, ""); - - g_free (*page_size_id); - g_free (*category_id); - - page_size_name = - gtk_combo_box_get_active_text (GTK_COMBO_BOX (this->priv->page_size_combo)); - - *page_size_id = lgl_db_lookup_paper_id_from_name (page_size_name); - - category_name = - gtk_combo_box_get_active_text (GTK_COMBO_BOX (this->priv->category_combo)); - - *category_id = lgl_db_lookup_category_id_from_name (category_name); - - g_free (page_size_name); - g_free (category_name); -} - - -/****************************************************************************/ -/* set filter parameters. */ -/****************************************************************************/ -void -gl_media_select_set_filter_parameters (glMediaSelect *this, - const gchar *page_size_id, - const gchar *category_id) -{ - gchar *page_size_name; - gchar *category_name; - - gl_debug (DEBUG_MEDIA_SELECT, "START"); - - page_size_name = lgl_db_lookup_paper_name_from_id (page_size_id); - if (page_size_name == NULL) - { - page_size_name = g_strdup (_("Any")); - } - - gl_combo_util_set_active_text (GTK_COMBO_BOX (this->priv->page_size_combo), - page_size_name); - - category_name = lgl_db_lookup_category_name_from_id (category_id); - if (category_name == NULL) - { - category_name = g_strdup (_("Any")); - } - - gl_combo_util_set_active_text (GTK_COMBO_BOX (this->priv->category_combo), - category_name); - g_free (page_size_name); - g_free (category_name); - - gl_debug (DEBUG_MEDIA_SELECT, "END"); -} - - -/*--------------------------------------------------------------------------*/ -/* PRIVATE. Get a description of the layout and number of labels. */ -/*--------------------------------------------------------------------------*/ -static gchar * -get_layout_desc (const lglTemplate *template) -{ - const lglTemplateFrame *frame; - gint n_labels; - gchar *string; - - frame = (lglTemplateFrame *)template->frames->data; - - n_labels = lgl_template_frame_get_n_labels (frame); - - string = g_strdup_printf (_("%d per sheet"), n_labels); - - return string; -} - - -/*--------------------------------------------------------------------------*/ -/* PRIVATE. Get label size description. */ -/*--------------------------------------------------------------------------*/ -static gchar * -get_label_size_desc (const lglTemplate *template) -{ - lglUnits units; - const gchar *units_string; - gdouble units_per_point; - const lglTemplateFrame *frame; - gchar *string = NULL; - - units = gl_prefs_model_get_units (gl_prefs); - units_string = lgl_units_get_name (units); - units_per_point = lgl_units_get_units_per_point (units); - - frame = (lglTemplateFrame *)template->frames->data; - - switch (frame->shape) { - case LGL_TEMPLATE_FRAME_SHAPE_RECT: - if ( units == LGL_UNITS_INCH ) { - gchar *xstr, *ystr; - - xstr = gl_str_util_fraction_to_string (frame->rect.w*units_per_point); - ystr = gl_str_util_fraction_to_string (frame->rect.h*units_per_point); - string = g_strdup_printf ("%s × %s %s", - xstr, ystr, units_string); - g_free (xstr); - g_free (ystr); - } else { - string = g_strdup_printf ("%.5g × %.5g %s", - frame->rect.w*units_per_point, - frame->rect.h*units_per_point, - units_string); - } - break; - case LGL_TEMPLATE_FRAME_SHAPE_ROUND: - if ( units == LGL_UNITS_INCH ) { - gchar *dstr; - - dstr = gl_str_util_fraction_to_string (2.0*frame->round.r*units_per_point); - string = g_strdup_printf ("%s %s %s", - dstr, units_string, - _("diameter")); - g_free (dstr); - } else { - string = g_strdup_printf ("%.5g %s %s", - 2.0*frame->round.r*units_per_point, - units_string, - _("diameter")); - } - break; - case LGL_TEMPLATE_FRAME_SHAPE_CD: - if ( units == LGL_UNITS_INCH ) { - gchar *dstr; - - dstr = gl_str_util_fraction_to_string (2.0*frame->cd.r1*units_per_point); - string = g_strdup_printf ("%s %s %s", - dstr, units_string, - _("diameter")); - g_free (dstr); - } else { - string = g_strdup_printf ("%.5g %s %s", - 2.0*frame->cd.r1*units_per_point, - units_string, - _("diameter")); - } - break; - default: - break; - } - - return string; -} - - -/*--------------------------------------------------------------------------*/ -/* PRIVATE. Load list store from template name list. */ -/*--------------------------------------------------------------------------*/ -static void -load_recent_list (glMediaSelect *this, - GtkListStore *store, - GtkTreeSelection *selection, - GList *list) -{ - GList *p; - GtkTreeIter iter; - lglTemplate *template; - GdkPixbuf *pixbuf; - gchar *size; - gchar *layout; - gchar *description; - - gl_debug (DEBUG_MEDIA_SELECT, "START"); - - gtk_list_store_clear (store); - - - if ( this->priv->recent_info_bar ) - { - gtk_container_remove (GTK_CONTAINER (this->priv->recent_info_vbox), - this->priv->recent_info_bar); - this->priv->recent_info_bar = NULL; - } - - if (list) - { - - for ( p=list; p!=NULL; p=p->next ) - { - - gl_debug (DEBUG_MEDIA_SELECT, "p->data = \"%s\"", p->data); - - template = lgl_db_lookup_template_from_name (p->data); - pixbuf = gl_mini_preview_pixbuf_cache_get_pixbuf (p->data); - - size = get_label_size_desc (template); - layout = get_layout_desc (template); - description = g_strdup_printf ("%s: %s\n%s\n%s", - (gchar *)p->data, - template->description, - size, - layout); - g_free (size); - g_free (layout); - - lgl_template_free (template); - - gtk_list_store_append (store, &iter); - gtk_list_store_set (store, &iter, - NAME_COLUMN, p->data, - PREVIEW_COLUMN, pixbuf, - DESCRIPTION_COLUMN, description, - -1); - - g_object_unref (G_OBJECT (pixbuf)); - g_free (description); - } - - gtk_tree_selection_set_mode (selection, GTK_SELECTION_BROWSE); - gtk_tree_model_get_iter_first (GTK_TREE_MODEL (store), &iter); - gtk_tree_selection_select_iter (selection, &iter); - - } - else - { - this->priv->recent_info_bar = gl_message_bar_new (GTK_MESSAGE_INFO, - GTK_BUTTONS_NONE, - "%s", _("No recent templates found.")); - gl_message_bar_format_secondary_text (GL_MESSAGE_BAR (this->priv->recent_info_bar), - "%s", _("Try selecting a template from the \"Search all templates\" page.")); - - gtk_box_pack_start (GTK_BOX (this->priv->recent_info_vbox), - this->priv->recent_info_bar, - FALSE, FALSE, 0); - gtk_widget_show_all (this->priv->recent_info_bar); - - gtk_tree_selection_set_mode (selection, GTK_SELECTION_NONE); - - } - - gl_debug (DEBUG_MEDIA_SELECT, "END"); -} - - -/*--------------------------------------------------------------------------*/ -/* PRIVATE. Load list store from template name list. */ -/*--------------------------------------------------------------------------*/ -static void -load_search_all_list (glMediaSelect *this, - GtkListStore *store, - GtkTreeSelection *selection, - GList *list) -{ - GList *p; - GtkTreeIter iter; - lglTemplate *template; - GdkPixbuf *pixbuf; - gchar *size; - gchar *layout; - gchar *description; - - gl_debug (DEBUG_MEDIA_SELECT, "START"); - - gtk_list_store_clear (store); - - if ( this->priv->search_all_info_bar ) - { - gtk_container_remove (GTK_CONTAINER (this->priv->search_all_info_vbox), - this->priv->search_all_info_bar); - this->priv->search_all_info_bar = NULL; - } - - if (list) - { - - for ( p=list; p!=NULL; p=p->next ) - { - - gl_debug (DEBUG_MEDIA_SELECT, "p->data = \"%s\"", p->data); - - template = lgl_db_lookup_template_from_name (p->data); - pixbuf = gl_mini_preview_pixbuf_cache_get_pixbuf (p->data); - - size = get_label_size_desc (template); - layout = get_layout_desc (template); - description = g_strdup_printf ("%s: %s\n%s\n%s", - (gchar *)p->data, - template->description, - size, - layout); - g_free (size); - g_free (layout); - - lgl_template_free (template); - - gtk_list_store_append (store, &iter); - gtk_list_store_set (store, &iter, - NAME_COLUMN, p->data, - PREVIEW_COLUMN, pixbuf, - DESCRIPTION_COLUMN, description, - -1); - - g_object_unref (G_OBJECT (pixbuf)); - g_free (description); - } - - gtk_tree_selection_set_mode (selection, GTK_SELECTION_BROWSE); - gtk_tree_model_get_iter_first (GTK_TREE_MODEL (store), &iter); - gtk_tree_selection_select_iter (selection, &iter); - - } - else - { - this->priv->search_all_info_bar = gl_message_bar_new (GTK_MESSAGE_INFO, - GTK_BUTTONS_NONE, - "%s", _("No match.")); - gl_message_bar_format_secondary_text (GL_MESSAGE_BAR (this->priv->search_all_info_bar), - "%s", _("Try selecting a different brand, page size or category.")); - - gtk_box_pack_start (GTK_BOX (this->priv->search_all_info_vbox), - this->priv->search_all_info_bar, - FALSE, FALSE, 0); - gtk_widget_show_all (this->priv->search_all_info_bar); - - gtk_tree_selection_set_mode (selection, GTK_SELECTION_NONE); - - } - - gl_debug (DEBUG_MEDIA_SELECT, "END"); -} - - - -/* - * Local Variables: -- emacs - * mode: C -- emacs - * c-basic-offset: 8 -- emacs - * tab-width: 8 -- emacs - * indent-tabs-mode: nil -- emacs - * End: -- emacs - */ diff --git a/src/media-select.h b/src/media-select.h deleted file mode 100644 index 6d086ea5..00000000 --- a/src/media-select.h +++ /dev/null @@ -1,87 +0,0 @@ -/* - * media-select.h - * Copyright (C) 2001-2009 Jim Evins . - * - * This file is part of gLabels. - * - * gLabels 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 3 of the License, or - * (at your option) any later version. - * - * gLabels 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 gLabels. If not, see . - */ - -#ifndef __MEDIA_SELECT_H__ -#define __MEDIA_SELECT_H__ - -#include - - -G_BEGIN_DECLS - -#define GL_TYPE_MEDIA_SELECT (gl_media_select_get_type ()) -#define GL_MEDIA_SELECT(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj), GL_TYPE_MEDIA_SELECT, glMediaSelect )) -#define GL_MEDIA_SELECT_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST ((klass), GL_TYPE_MEDIA_SELECT, glMediaSelectClass)) -#define GL_IS_MEDIA_SELECT(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GL_TYPE_MEDIA_SELECT)) -#define GL_IS_MEDIA_SELECT_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE ((klass), GL_TYPE_MEDIA_SELECT)) - -typedef struct _glMediaSelect glMediaSelect; -typedef struct _glMediaSelectClass glMediaSelectClass; - -typedef struct _glMediaSelectPrivate glMediaSelectPrivate; - -struct _glMediaSelect { - GtkVBox parent_widget; - - glMediaSelectPrivate *priv; -}; - -struct _glMediaSelectClass { - GtkVBoxClass parent_class; - - void (*changed) (glMediaSelect * media_select, gpointer user_data); -}; - - -GType gl_media_select_get_type (void) G_GNUC_CONST; - -GtkWidget *gl_media_select_new (void); - -gchar *gl_media_select_get_name (glMediaSelect *this); - -void gl_media_select_set_name (glMediaSelect *this, - gchar *name); - -void gl_media_select_get_filter_parameters (glMediaSelect *this, - gchar **page_size_id, - gchar **category_id); - -void gl_media_select_set_filter_parameters (glMediaSelect *this, - const gchar *page_size_id, - const gchar *category_id); - -G_END_DECLS - -#endif - - - -/* - * Local Variables: -- emacs - * mode: C -- emacs - * c-basic-offset: 8 -- emacs - * tab-width: 8 -- emacs - * indent-tabs-mode: nil -- emacs - * End: -- emacs - */ diff --git a/src/mini-preview.c b/src/mini-preview.c index 2b7984e2..abbc1046 100644 --- a/src/mini-preview.c +++ b/src/mini-preview.c @@ -40,6 +40,8 @@ #define MARGIN 2 #define SHADOW_OFFSET 3 +#define ARROW_SCALE 0.35 +#define ARROW_RGBA_ARGS 1.0, 0.0, 0.0, 0.05 /*===========================================*/ /* Private types */ @@ -73,6 +75,9 @@ struct _glMiniPreviewPrivate { gint last_i; gint prev_i; + gboolean draw_arrow_flag; + gboolean rotate_flag; + gboolean update_scheduled_flag; glLabel *label; @@ -139,6 +144,11 @@ static void draw_labels (glMiniPreview *this, cairo_t *cr, lglTemplate *template, gdouble line_width); +static void draw_arrow (glMiniPreview *this, + cairo_t *cr, + gdouble width, + gdouble height); + static void draw_rich_preview (glMiniPreview *this, cairo_t *cr); @@ -397,6 +407,36 @@ gl_mini_preview_highlight_range (glMiniPreview *this, } +/****************************************************************************/ +/* Set draw arrow. */ +/****************************************************************************/ +void +gl_mini_preview_set_draw_arrow (glMiniPreview *this, + gboolean draw_arrow_flag) +{ + if ( draw_arrow_flag != this->priv->draw_arrow_flag ) + { + this->priv->draw_arrow_flag = draw_arrow_flag; + redraw (this); + } +} + + +/****************************************************************************/ +/* Set rotate flag. */ +/****************************************************************************/ +void +gl_mini_preview_set_rotate (glMiniPreview *this, + gboolean rotate_flag) +{ + if ( rotate_flag != this->priv->rotate_flag ) + { + this->priv->rotate_flag = rotate_flag; + redraw (this); + } +} + + /****************************************************************************/ /* Set label. */ /****************************************************************************/ @@ -858,7 +898,13 @@ draw (glMiniPreview *this, template->page_width, template->page_height, 1.0/scale); - draw_labels (this, cr, template, 1.0/scale); + draw_labels (this, cr, template, 2.0/scale); + + if (this->priv->draw_arrow_flag) + { + draw_arrow (this, cr, + template->page_width, template->page_height); + } if (this->priv->label) { @@ -971,7 +1017,7 @@ draw_labels (glMiniPreview *this, if (this->priv->label) { /* Outlines are more subtle when doing a rich preview. */ - outline_color = gl_color_set_opacity (base_color, 0.05); + outline_color = gl_color_set_opacity (base_color, 0.25); } else { @@ -1007,6 +1053,46 @@ draw_labels (glMiniPreview *this, } +/*--------------------------------------------------------------------------*/ +/* Draw arrow to indicate top of labels. */ +/*--------------------------------------------------------------------------*/ +static void +draw_arrow (glMiniPreview *this, + cairo_t *cr, + gdouble width, + gdouble height) +{ + gdouble min; + + cairo_save (cr); + + min = MIN (width, height); + + cairo_translate (cr, width/2, height/2); + cairo_scale (cr, 1, -1); + if ( this->priv->rotate_flag ) + { + cairo_rotate (cr, -M_PI/2.0); + } + + cairo_new_path (cr); + cairo_move_to (cr, 0, -min*ARROW_SCALE/2); + cairo_line_to (cr, 0, min*ARROW_SCALE); + + cairo_new_sub_path (cr); + cairo_move_to (cr, -min*ARROW_SCALE/2, min*ARROW_SCALE/2); + cairo_line_to (cr, 0, min*ARROW_SCALE); + cairo_line_to (cr, min*ARROW_SCALE/2, min*ARROW_SCALE/2); + + cairo_set_line_width (cr, 0.25*min*ARROW_SCALE); + cairo_set_source_rgba (cr, ARROW_RGBA_ARGS); + + cairo_stroke (cr); + + cairo_restore (cr); +} + + /*--------------------------------------------------------------------------*/ /* Draw rich preview using print renderers. */ /*--------------------------------------------------------------------------*/ diff --git a/src/mini-preview.h b/src/mini-preview.h index caf77ebb..d2d9210f 100644 --- a/src/mini-preview.h +++ b/src/mini-preview.h @@ -83,6 +83,12 @@ void gl_mini_preview_highlight_range (glMiniPreview *this, gint first_label, gint last_label); +void gl_mini_preview_set_draw_arrow (glMiniPreview *this, + gboolean draw_arrow_flag); + +void gl_mini_preview_set_rotate (glMiniPreview *this, + gboolean rotate_flag); + /* * If label is set, the preview will be rich. diff --git a/src/new-label-dialog.c b/src/new-label-dialog.c index f01d0fb6..ffea6dc0 100644 --- a/src/new-label-dialog.c +++ b/src/new-label-dialog.c @@ -26,21 +26,43 @@ #include #include "hig.h" -#include "media-select.h" +#include "builder-util.h" +#include "prefs.h" +#include "template-history.h" +#include "mini-preview.h" +#include "media-combo.h" #include "rotate-label-button.h" #include "debug.h" +#define MINI_PREVIEW_MIN_HEIGHT 300 +#define MINI_PREVIEW_MIN_WIDTH 256 + + /*===========================================*/ /* Private data types */ /*===========================================*/ struct _glNewLabelDialogPrivate { - GtkWidget *media_select; - GtkWidget *rotate_label; + GtkBuilder *builder; + + GtkWidget *preview_vbox; + GtkWidget *combo_hbox; + GtkWidget *rotate_hbox; + GtkWidget *desc_label; + GtkWidget *page_size_label; + GtkWidget *label_size_label; + GtkWidget *layout_label; + GtkWidget *vendor_label; + GtkWidget *part_label; + GtkWidget *similar_label; + + GtkWidget *preview; + GtkWidget *combo; + GtkWidget *rotate_button; }; @@ -55,8 +77,13 @@ struct _glNewLabelDialogPrivate { static void gl_new_label_dialog_finalize (GObject *object); -static void template_changed_cb (glMediaSelect *select, - gpointer data); +static void combo_changed_cb (glNewLabelDialog *this); +static void rotate_toggled_cb (glNewLabelDialog *this); + +static gchar *get_default_name (void); + +static void set_info (glNewLabelDialog *this, + const gchar *name); /*****************************************************************************/ @@ -77,7 +104,7 @@ gl_new_label_dialog_class_init (glNewLabelDialogClass *class) gl_new_label_dialog_parent_class = g_type_class_peek_parent (class); - object_class->finalize = gl_new_label_dialog_finalize; + object_class->finalize = gl_new_label_dialog_finalize; } @@ -85,59 +112,84 @@ gl_new_label_dialog_class_init (glNewLabelDialogClass *class) /* Object Instance Init Function. */ /*****************************************************************************/ static void -gl_new_label_dialog_init (glNewLabelDialog *dialog) +gl_new_label_dialog_init (glNewLabelDialog *this) { GtkWidget *vbox; - GtkWidget *label; - GtkWidget *frame; - gchar *name; + GtkBuilder *builder; + gchar *builder_filename; + static gchar *object_ids[] = { "new_label_dialog_hbox", NULL }; + GError *error = NULL; + GtkWidget *new_label_dialog_hbox; + gchar *name; gl_debug (DEBUG_FILE, "START"); - g_return_if_fail (GL_IS_NEW_LABEL_DIALOG (dialog)); + g_return_if_fail (GL_IS_NEW_LABEL_DIALOG (this)); - dialog->priv = g_new0 (glNewLabelDialogPrivate, 1); + this->priv = g_new0 (glNewLabelDialogPrivate, 1); - gtk_container_set_border_width (GTK_CONTAINER (dialog), GL_HIG_PAD1); + gtk_container_set_border_width (GTK_CONTAINER (this), GL_HIG_PAD1); - gtk_dialog_set_has_separator (GTK_DIALOG (dialog), FALSE); - gtk_dialog_add_buttons (GTK_DIALOG (dialog), + gtk_dialog_set_has_separator (GTK_DIALOG (this), FALSE); + gtk_dialog_add_buttons (GTK_DIALOG (this), GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_OK, GTK_RESPONSE_OK, NULL); - gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK); - gtk_window_set_destroy_with_parent (GTK_WINDOW (dialog), TRUE); - gtk_window_set_modal (GTK_WINDOW (dialog), TRUE); - - vbox = gtk_dialog_get_content_area (GTK_DIALOG (dialog)); - - label = gtk_label_new (_("Media type")); - gtk_label_set_use_markup (GTK_LABEL (label), TRUE); - frame = gtk_frame_new (""); - gtk_frame_set_label_widget (GTK_FRAME (frame), label); - gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_NONE); - gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, GL_HIG_PAD1); - - dialog->priv->media_select = gl_media_select_new (); - gtk_container_add (GTK_CONTAINER (frame), dialog->priv->media_select); - - label = gtk_label_new (_("Label orientation")); - gtk_label_set_use_markup (GTK_LABEL (label), TRUE); - frame = gtk_frame_new (""); - gtk_frame_set_label_widget (GTK_FRAME (frame), label); - gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_NONE); - gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0); - - dialog->priv->rotate_label = gl_rotate_label_button_new (); - gtk_container_add (GTK_CONTAINER (frame), dialog->priv->rotate_label); - - /* Sync template name from media select with rotate widget. */ - name = gl_media_select_get_name (GL_MEDIA_SELECT (dialog->priv->media_select)); - gl_rotate_label_button_set_template_name (GL_ROTATE_LABEL_BUTTON (dialog->priv->rotate_label), - name); - - g_signal_connect (G_OBJECT (dialog->priv->media_select), "changed", - G_CALLBACK (template_changed_cb), dialog); + gtk_dialog_set_default_response (GTK_DIALOG (this), GTK_RESPONSE_OK); + gtk_window_set_destroy_with_parent (GTK_WINDOW (this), TRUE); + gtk_window_set_modal (GTK_WINDOW (this), TRUE); + + vbox = gtk_dialog_get_content_area (GTK_DIALOG (this)); + + + builder = gtk_builder_new (); + builder_filename = g_build_filename (GLABELS_DATA_DIR, "builder", "new-label-dialog.builder", NULL); + gtk_builder_add_objects_from_file (builder, builder_filename, object_ids, &error); + g_free (builder_filename); + if (error) { + g_critical ("%s\n\ngLabels may not be installed correctly!", error->message); + g_error_free (error); + return; + } + + gl_builder_util_get_widgets (builder, + "new_label_dialog_hbox", &new_label_dialog_hbox, + "preview_vbox", &this->priv->preview_vbox, + "combo_hbox", &this->priv->combo_hbox, + "rotate_hbox", &this->priv->rotate_hbox, + "desc_label", &this->priv->desc_label, + "page_size_label", &this->priv->page_size_label, + "label_size_label", &this->priv->label_size_label, + "layout_label", &this->priv->layout_label, + "vendor_label", &this->priv->vendor_label, + "part_label", &this->priv->part_label, + "similar_label", &this->priv->similar_label, + NULL); + + gtk_container_add (GTK_CONTAINER (vbox), new_label_dialog_hbox); + this->priv->builder = builder; + + this->priv->preview = gl_mini_preview_new (MINI_PREVIEW_MIN_HEIGHT, MINI_PREVIEW_MIN_WIDTH); + gl_mini_preview_set_draw_arrow (GL_MINI_PREVIEW (this->priv->preview), TRUE); + gl_mini_preview_set_rotate (GL_MINI_PREVIEW (this->priv->preview), FALSE); + gtk_container_add (GTK_CONTAINER (this->priv->preview_vbox), this->priv->preview); + + this->priv->combo = gl_media_combo_new (); + gtk_container_add (GTK_CONTAINER (this->priv->combo_hbox), this->priv->combo); + + this->priv->rotate_button = gl_rotate_label_button_new (); + gtk_container_add (GTK_CONTAINER (this->priv->rotate_hbox), this->priv->rotate_button); + + g_signal_connect_swapped (G_OBJECT (this->priv->combo), "changed", + G_CALLBACK (combo_changed_cb), this); + g_signal_connect_swapped (G_OBJECT (this->priv->rotate_button), "changed", + G_CALLBACK (rotate_toggled_cb), this); + + name = get_default_name (); + gl_media_combo_set_name (GL_MEDIA_COMBO (this->priv->combo), name); + gl_rotate_label_button_set_template_name (GL_ROTATE_LABEL_BUTTON (this->priv->rotate_button), name); + g_free (name); + combo_changed_cb (this); gl_debug (DEBUG_FILE, "END"); } @@ -149,15 +201,16 @@ gl_new_label_dialog_init (glNewLabelDialog *dialog) static void gl_new_label_dialog_finalize (GObject *object) { - glNewLabelDialog* dialog = GL_NEW_LABEL_DIALOG (object);; + glNewLabelDialog* this = GL_NEW_LABEL_DIALOG (object);; gl_debug (DEBUG_FILE, "START"); g_return_if_fail (object != NULL); - g_return_if_fail (GL_IS_NEW_LABEL_DIALOG (dialog)); - g_return_if_fail (dialog->priv != NULL); + g_return_if_fail (GL_IS_NEW_LABEL_DIALOG (this)); + g_return_if_fail (this->priv != NULL); - g_free (dialog->priv); + g_object_unref (G_OBJECT (this->priv->builder)); + g_free (this->priv); G_OBJECT_CLASS (gl_new_label_dialog_parent_class)->finalize (object); @@ -172,38 +225,33 @@ gl_new_label_dialog_finalize (GObject *object) GtkWidget * gl_new_label_dialog_new (GtkWindow *win) { - GtkWidget *dialog; + GtkWidget *this; gl_debug (DEBUG_FILE, ""); - dialog = GTK_WIDGET (g_object_new (GL_TYPE_NEW_LABEL_DIALOG, NULL)); + this = GTK_WIDGET (g_object_new (GL_TYPE_NEW_LABEL_DIALOG, NULL)); - gtk_window_set_transient_for (GTK_WINDOW (dialog), win); + gtk_window_set_transient_for (GTK_WINDOW (this), win); - return dialog; + return this; } /*---------------------------------------------------------------------------*/ -/* PRIVATE. New template changed callback. */ +/* PRIVATE. Template changed callback. */ /*---------------------------------------------------------------------------*/ static void -template_changed_cb (glMediaSelect *select, - gpointer data) +combo_changed_cb (glNewLabelDialog *this) { - glNewLabelDialog *dialog = GL_NEW_LABEL_DIALOG (data); gchar *name; gl_debug (DEBUG_FILE, "START"); - name = gl_media_select_get_name (GL_MEDIA_SELECT (select)); + name = gl_media_combo_get_name (GL_MEDIA_COMBO (this->priv->combo)); - gl_rotate_label_button_set_template_name (GL_ROTATE_LABEL_BUTTON (dialog->priv->rotate_label), - name); - - gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), - GTK_RESPONSE_OK, - (name != NULL)); + gl_mini_preview_set_by_name (GL_MINI_PREVIEW (this->priv->preview), name); + gl_rotate_label_button_set_template_name (GL_ROTATE_LABEL_BUTTON (this->priv->rotate_button), name); + set_info (this, name); g_free (name); @@ -211,15 +259,144 @@ template_changed_cb (glMediaSelect *select, } +/*---------------------------------------------------------------------------*/ +/* PRIVATE. Rotate toggled callback. */ +/*---------------------------------------------------------------------------*/ +static void +rotate_toggled_cb (glNewLabelDialog *this) +{ + gboolean state; + + gl_debug (DEBUG_FILE, "START"); + + state = gl_rotate_label_button_get_state (GL_ROTATE_LABEL_BUTTON (this->priv->rotate_button)); + gl_mini_preview_set_rotate (GL_MINI_PREVIEW (this->priv->preview), state); + + gl_debug (DEBUG_FILE, "END"); +} + + +/*---------------------------------------------------------------------------*/ +/* PRIVATE. Get default template name. */ +/*---------------------------------------------------------------------------*/ +static gchar * +get_default_name (void) +{ + gchar *name = NULL; + GList *list; + + list = gl_template_history_model_get_name_list (gl_template_history); + + if ( list ) + { + name = g_strdup (list->data); + gl_template_history_model_free_name_list (list); + } + else + { + gchar *page_size; + + page_size = gl_prefs_model_get_default_page_size (gl_prefs); + list = lgl_db_get_template_name_list_all (NULL, page_size, NULL); + g_free (page_size); + + if ( list ) + { + name = g_strdup (list->data); + lgl_db_free_template_name_list (list); + } + } + + return name; +} + + +/*---------------------------------------------------------------------------*/ +/* PRIVATE. Set information labels. */ +/*---------------------------------------------------------------------------*/ +static void +set_info (glNewLabelDialog *this, + const gchar *name) +{ + lglTemplate *template; + lglTemplateFrame *frame; + lglVendor *vendor; + lglUnits units; + gchar *page_size_string; + gchar *label_size_string; + gchar *layout_string; + GList *list, *p; + GString *list_string; + + template = lgl_db_lookup_template_from_name (name); + frame = template->frames->data; + vendor = lgl_db_lookup_vendor_from_name (template->brand); + + units = gl_prefs_model_get_units (gl_prefs); + + page_size_string = lgl_db_lookup_paper_name_from_id (template->paper_id); + label_size_string = lgl_template_frame_get_size_description (frame, units); + layout_string = lgl_template_frame_get_layout_description (frame); + + gtk_label_set_text (GTK_LABEL (this->priv->desc_label), template->description); + gtk_label_set_text (GTK_LABEL (this->priv->page_size_label), page_size_string); + gtk_label_set_text (GTK_LABEL (this->priv->label_size_label), label_size_string); + gtk_label_set_text (GTK_LABEL (this->priv->layout_label), layout_string); + + if ( vendor && vendor->url ) + { + gchar *markup; + + markup = g_strdup_printf ("%s", vendor->url, vendor->name); + gtk_label_set_markup (GTK_LABEL (this->priv->vendor_label), markup); + g_free (markup); + } + else + { + /* FIXME: Using set_markup instead of set_text to clear out previous link. */ + gtk_label_set_markup (GTK_LABEL (this->priv->vendor_label), template->brand); + } + + if ( template->product_url ) + { + gchar *markup; + + markup = g_strdup_printf ("%s", template->product_url, template->part); + gtk_label_set_markup (GTK_LABEL (this->priv->part_label), markup); + g_free (markup); + } + else + { + /* FIXME: Using set_markup instead of set_text to clear out previous link. */ + gtk_label_set_markup (GTK_LABEL (this->priv->part_label), template->part); + } + + list = lgl_db_get_similar_template_name_list (name); + list_string = g_string_new (""); + for ( p = list; p; p = p->next ) + { + g_string_append_printf (list_string, "%s\n", (char *)p->data); + } + gtk_label_set_text (GTK_LABEL (this->priv->similar_label), list_string->str); + + lgl_db_free_template_name_list (list); + g_string_free (list_string, TRUE); + + g_free (page_size_string); + g_free (label_size_string); + g_free (layout_string); +} + + /*****************************************************************************/ /* Get template name. */ /*****************************************************************************/ gchar * -gl_new_label_dialog_get_template_name (glNewLabelDialog *dialog) +gl_new_label_dialog_get_template_name (glNewLabelDialog *this) { gchar *name; - name = gl_media_select_get_name (GL_MEDIA_SELECT (dialog->priv->media_select)); + name = gl_media_combo_get_name (GL_MEDIA_COMBO (this->priv->combo)); return name; } @@ -229,10 +406,12 @@ gl_new_label_dialog_get_template_name (glNewLabelDialog *dialog) /* Set template name. */ /*****************************************************************************/ void -gl_new_label_dialog_set_template_name (glNewLabelDialog *dialog, +gl_new_label_dialog_set_template_name (glNewLabelDialog *this, gchar *name) { - gl_media_select_set_name (GL_MEDIA_SELECT (dialog->priv->media_select), name); + gl_mini_preview_set_by_name (GL_MINI_PREVIEW (this->priv->preview), name); + gl_media_combo_set_name (GL_MEDIA_COMBO (this->priv->combo), name); + set_info (this, name); } @@ -240,13 +419,10 @@ gl_new_label_dialog_set_template_name (glNewLabelDialog *dialog, /* Get current filter parameters. */ /*****************************************************************************/ void -gl_new_label_dialog_get_filter_parameters (glNewLabelDialog *dialog, +gl_new_label_dialog_get_filter_parameters (glNewLabelDialog *this, gchar **page_size_id, gchar **category_id) { - gl_media_select_get_filter_parameters ( - GL_MEDIA_SELECT (dialog->priv->media_select), - page_size_id, category_id); } @@ -254,13 +430,10 @@ gl_new_label_dialog_get_filter_parameters (glNewLabelDialog *dialog, /* Set current filter parameters. */ /*****************************************************************************/ void -gl_new_label_dialog_set_filter_parameters (glNewLabelDialog *dialog, +gl_new_label_dialog_set_filter_parameters (glNewLabelDialog *this, const gchar *page_size_id, const gchar *category_id) { - gl_media_select_set_filter_parameters ( - GL_MEDIA_SELECT (dialog->priv->media_select), - page_size_id, category_id); } @@ -268,10 +441,9 @@ gl_new_label_dialog_set_filter_parameters (glNewLabelDialog *dialog, /* Get rotate state. */ /*****************************************************************************/ gboolean -gl_new_label_dialog_get_rotate_state (glNewLabelDialog *dialog) +gl_new_label_dialog_get_rotate_state (glNewLabelDialog *this) { - return gl_rotate_label_button_get_state ( - GL_ROTATE_LABEL_BUTTON (dialog->priv->rotate_label)); + return gl_rotate_label_button_get_state (GL_ROTATE_LABEL_BUTTON (this->priv->rotate_button)); } @@ -279,11 +451,11 @@ gl_new_label_dialog_get_rotate_state (glNewLabelDialog *dialog) /* Set rotate state. */ /*****************************************************************************/ void -gl_new_label_dialog_set_rotate_state (glNewLabelDialog *dialog, +gl_new_label_dialog_set_rotate_state (glNewLabelDialog *this, gboolean state) { - gl_rotate_label_button_set_state ( - GL_ROTATE_LABEL_BUTTON (dialog->priv->rotate_label), state); + gl_rotate_label_button_set_state (GL_ROTATE_LABEL_BUTTON (this->priv->rotate_button), state); + gl_mini_preview_set_rotate (GL_MINI_PREVIEW (this->priv->preview), state); } diff --git a/src/rotate-label-button.c b/src/rotate-label-button.c index d477edf5..cf65db06 100644 --- a/src/rotate-label-button.c +++ b/src/rotate-label-button.c @@ -111,7 +111,7 @@ gl_rotate_label_button_init (glRotateLabelButton *this) this->priv = g_new0 (glRotateLabelButtonPrivate, 1); - gtk_container_set_border_width (GTK_CONTAINER (this), GL_HIG_PAD2); + gtk_box_set_spacing (GTK_BOX (this), GL_HIG_PAD2); this->priv->no_rotate_radio = gtk_radio_button_new (NULL); gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (this->priv->no_rotate_radio), @@ -134,12 +134,8 @@ gl_rotate_label_button_init (glRotateLabelButton *this) gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0); gtk_container_add (GTK_CONTAINER (this->priv->rotate_radio), vbox); - gtk_box_pack_start (GTK_BOX (this), - this->priv->no_rotate_radio, - FALSE, FALSE, GL_HIG_PAD1); - gtk_box_pack_start (GTK_BOX (this), - this->priv->rotate_radio, - FALSE, FALSE, GL_HIG_PAD1); + gtk_box_pack_start (GTK_BOX (this), this->priv->no_rotate_radio, FALSE, FALSE, 0); + gtk_box_pack_start (GTK_BOX (this), this->priv->rotate_radio, FALSE, FALSE, 0); /* Connect signals to controls */ g_signal_connect (G_OBJECT (this->priv->no_rotate_radio), diff --git a/src/str-util.c b/src/str-util.c index d48ec007..6aa2dd1f 100644 --- a/src/str-util.c +++ b/src/str-util.c @@ -25,43 +25,6 @@ #include #include -#define FRAC_EPSILON 0.00005 - - -/****************************************************************************/ -/* Create fractional representation of number, if possible. */ -/****************************************************************************/ -gchar * -gl_str_util_fraction_to_string (gdouble x) -{ - static gdouble denom[] = { 1., 2., 3., 4., 8., 16., 32., 0. }; - gint i; - gdouble product, remainder; - gint n, d; - - for ( i=0; denom[i] != 0.0; i++ ) { - product = x * denom[i]; - remainder = fabs(product - ((gint)(product+0.5))); - if ( remainder < FRAC_EPSILON ) break; - } - - if ( denom[i] == 0.0 ) { - /* None of our denominators work. */ - return g_strdup_printf ("%.5g", x); - } - if ( denom[i] == 1.0 ) { - /* Simple integer. */ - return g_strdup_printf ("%d", (gint)x); - } - n = (gint)( x * denom[i] + 0.5 ); - d = (gint)denom[i]; - if ( n > d ) { - return g_strdup_printf ("%d_%d/%d", (n/d), (n%d), d); - } else { - return g_strdup_printf ("%d/%d", (n%d), d); - } -} - /****************************************************************************/ /* Utilities to deal with PangoAlignment types. */ diff --git a/src/str-util.h b/src/str-util.h index 0253392b..76dda779 100644 --- a/src/str-util.h +++ b/src/str-util.h @@ -26,8 +26,6 @@ G_BEGIN_DECLS -gchar *gl_str_util_fraction_to_string (gdouble x); - const gchar *gl_str_util_align_to_string (PangoAlignment align); PangoAlignment gl_str_util_string_to_align (const gchar *string); -- 2.39.5