On 04/07/2012 08:14 PM, David Vincent-Jones wrote:
Personally, I just use keywords. I predominantly use three keywords named "decent", "top20", and "top10". I use the "Connect keyword to mark" functionality extensively, which lets me trivially toggle and filter on up to six keywords. In particular, this works well for me since I don't have info in geeqie that other apps need to know about.How are users dealing with the lack of a 'star' rating? Is there any way to add to the Windows Rating value?
I had written a partially-completed patch to plumb the EXIF (I think) Rating value through to the UI, but it's bit-rotted a bit; I last touched it 2.5 years ago (wow). It's attached.
That said, even when I had my local geeqie build patched with it, I didn't find it anywhere near as useful as the keywords. Particularly because it wasn't easy to filter by the rating (you could search, but you couldn't just filter like you can with marks).
--xsdg
diff --git a/trunk/src/Makefile.am b/trunk/src/Makefile.am index 144b090..9528d30 100644 --- a/trunk/src/Makefile.am +++ b/trunk/src/Makefile.am @@ -94,6 +94,8 @@ geeqie_SOURCES = \ bar_keywords.h \ bar_exif.c \ bar_exif.h \ + bar_rating.c \ + bar_rating.h \ bar_sort.c \ bar_sort.h \ cache.c \ diff --git a/trunk/src/bar.c b/trunk/src/bar.c index 52d6a54..4d64b71 100644 --- a/trunk/src/bar.c +++ b/trunk/src/bar.c @@ -25,6 +25,7 @@ #include "ui_menu.h" #include "bar_comment.h" #include "bar_keywords.h" +#include "bar_rating.h" #include "bar_exif.h" #include "bar_histogram.h" #include "histogram.h" @@ -76,6 +77,15 @@ static const gchar default_config_comment[] = " </layout>" "</gq>"; +static const gchar default_config_rating[] = +"<gq>" +" <layout id = '_current_'>" +" <bar>" +" <pane_rating id = 'rating' expanded = 'true' key = '" RATING_KEY "' />" +" </bar>" +" </layout>" +"</gq>"; + static const gchar default_config_exif[] = "<gq>" " <layout id = '_current_'>" @@ -178,6 +188,7 @@ static const KnownPanes known_panes[] = { {PANE_GPS, "gps", N_("GPS Map"), default_config_gps}, #endif #endif + {PANE_RATING, "rating", N_("Rating"), default_config_rating}, {PANE_UNDEF, NULL, NULL, NULL} }; diff --git a/trunk/src/bar.h b/trunk/src/bar.h index 61dc4be..d24acf3 100644 --- a/trunk/src/bar.h +++ b/trunk/src/bar.h @@ -20,7 +20,8 @@ typedef enum { PANE_EXIF, PANE_HISTOGRAM, PANE_KEYWORDS, - PANE_GPS + PANE_GPS, + PANE_RATING } PaneType; typedef struct _PaneData PaneData; diff --git a/trunk/src/bar_rating.c b/trunk/src/bar_rating.c new file mode 100644 index 0000000..0898183 --- /dev/null +++ b/trunk/src/bar_rating.c @@ -0,0 +1,401 @@ +/* + * Geeqie + * (C) 2004 John Ellis + * Copyright (C) 2008 - 2009 The Geeqie Team + * + * Author: Omari Stephens + * + * This software is released under the GNU General Public License (GNU GPL). + * Please read the included file COPYING for more information. + * This software comes with no warranty of any kind, use at your own risk! + */ + + +#include "main.h" +#include "bar_rating.h" + +#include "bar.h" +#include "metadata.h" +#include "filedata.h" +#include "ui_menu.h" +#include "ui_misc.h" +#include "rcfile.h" +#include "layout.h" +#include "layout_image.h" + +static void bar_pane_rating_changed(GtkSpinButton *button, gpointer data); + +/* + *------------------------------------------------------------------- + * rating utils + *------------------------------------------------------------------- + */ + + + +typedef struct _PaneRatingData PaneRatingData; +struct _PaneRatingData +{ + PaneData pane; + GtkHBox *container; + GtkSpinButton *spinbutton; + GtkToggleButton *auto_adv; // autoadvance + FileData *fd; + gchar *key; + gint height; +}; + + +static void bar_pane_rating_write(PaneRatingData *prd) +{ + guint value; + + if (!prd->fd) return; + + value = gtk_spin_button_get_value_as_int(prd->spinbutton); + + metadata_write_int(prd->fd, prd->key, value); +} + + +static void bar_pane_rating_update(PaneRatingData *prd) +{ + guint64 value; + + g_signal_handlers_block_by_func(prd->spinbutton, bar_pane_rating_changed, prd); + + value = metadata_read_int(prd->fd, prd->key, (guint64)-1); + + if(value != (guint64)-1) + { + gtk_spin_button_set_value(prd->spinbutton, value); + } + else + { + gtk_spin_button_set_value(prd->spinbutton, 0); + } + + g_signal_handlers_unblock_by_func(prd->spinbutton, bar_pane_rating_changed, prd); + + gtk_widget_set_sensitive((GtkWidget*) prd->spinbutton, (prd->fd != NULL)); +} + +static void bar_pane_rating_set_selection(PaneRatingData *prd, gboolean overwrite) +{ + GList *list = NULL; + GList *work; + gint value = -1; + + value = gtk_spin_button_get_value_as_int(prd->spinbutton); + + list = layout_selection_list(prd->pane.lw); + list = file_data_process_groups_in_selection(list, FALSE, NULL); + + work = list; + while (work) + { + FileData *fd = work->data; + work = work->next; + if (fd == prd->fd) continue; + + if (overwrite || (metadata_read_int(fd, prd->key, -1) == (guint64)-1)) + { + metadata_write_int(fd, prd->key, value); + } + } + + filelist_free(list); +} + +/* +static void bar_pane_comment_sel_add_cb(GtkWidget *button, gpointer data) +{ + PaneCommentData *pcd = data; + + bar_pane_comment_set_selection(pcd, TRUE); +} + + +static void bar_pane_comment_sel_replace_cb(GtkWidget *button, gpointer data) +{ + PaneCommentData *pcd = data; + + bar_pane_comment_set_selection(pcd, FALSE); +} +*/ + +static void bar_pane_rating_set_fd(GtkWidget *bar, FileData *fd) +{ + PaneRatingData *prd; + + prd = g_object_get_data(G_OBJECT(bar), "pane_data"); + if (!prd) return; + + file_data_unref(prd->fd); + prd->fd = file_data_ref(fd); + + bar_pane_rating_update(prd); +} + +static gint bar_pane_rating_event(GtkWidget *bar, GdkEvent *event) +{ + PaneRatingData *prd; + + prd = g_object_get_data(G_OBJECT(bar), "pane_data"); + if (!prd) return FALSE; + + if (GTK_WIDGET_HAS_FOCUS(prd->spinbutton)) + { + return gtk_widget_event((GtkWidget*) prd->spinbutton, event); + } + + return FALSE; +} + +static void bar_pane_rating_write_config(GtkWidget *pane, GString *outstr, gint indent) +{ + PaneRatingData *prd; + + prd = g_object_get_data(G_OBJECT(pane), "pane_data"); + if (!prd) return; + + WRITE_NL(); WRITE_STRING("<pane_rating "); + write_char_option(outstr, indent, "id", prd->pane.id); + write_char_option(outstr, indent, "title", gtk_label_get_text(GTK_LABEL(prd->pane.title))); + WRITE_BOOL(prd->pane, expanded); + WRITE_CHAR(*prd, key); + WRITE_INT(*prd, height); + WRITE_STRING("/>"); +} + +static void bar_pane_rating_notify_cb(FileData *fd, NotifyType type, gpointer data) +{ + PaneRatingData *prd = data; + if ((type & (NOTIFY_REREAD | NOTIFY_CHANGE | NOTIFY_METADATA)) && fd == prd->fd) + { + DEBUG_1("Notify pane_rating: %s %04x", fd->path, type); + + bar_pane_rating_update(prd); + } +} + +static void bar_pane_rating_changed(GtkSpinButton *button, gpointer data) +{ + PaneRatingData *prd = data; + + file_data_unregister_notify_func(bar_pane_rating_notify_cb, prd); + bar_pane_rating_write(prd); + file_data_register_notify_func(bar_pane_rating_notify_cb, prd, NOTIFY_PRIORITY_LOW); +} + +static void bar_pane_rating_inc_value_cb(GtkButton *button, gpointer data) +{ + bar_pane_rating_inc_value(data); +} + +void bar_pane_rating_inc_value(gpointer data) +{ + PaneRatingData *prd = data; + gtk_spin_button_spin(prd->spinbutton, GTK_SPIN_STEP_FORWARD, 1.0); + if(gtk_toggle_button_get_active(prd->auto_adv)) layout_image_next(NULL); +} + +static void bar_pane_rating_dec_value_cb(GtkButton *button, gpointer data) +{ + bar_pane_rating_dec_value(data); +} + +void bar_pane_rating_dec_value(gpointer data) +{ + PaneRatingData *prd = data; + gtk_spin_button_spin(prd->spinbutton, GTK_SPIN_STEP_BACKWARD, 1.0); + if(gtk_toggle_button_get_active(prd->auto_adv)) layout_image_next(NULL); +} + +void bar_pane_rating_set_value(gint value, gpointer data) +{ + PaneRatingData *prd = data; + gtk_spin_button_set_value(prd->spinbutton, value); + if(gtk_toggle_button_get_active(prd->auto_adv)) layout_image_next(NULL); +} + + +/* +static void bar_pane_comment_populate_popup(GtkTextView *textview, GtkMenu *menu, gpointer data) +{ + PaneCommentData *pcd = data; + + menu_item_add_divider(GTK_WIDGET(menu)); + menu_item_add_stock(GTK_WIDGET(menu), _("Add text to selected files"), GTK_STOCK_ADD, G_CALLBACK(bar_pane_comment_sel_add_cb), pcd); + menu_item_add_stock(GTK_WIDGET(menu), _("Replace existing text in selected files"), GTK_STOCK_CONVERT, G_CALLBACK(bar_pane_comment_sel_replace_cb), data); +} +*/ + +#if 0 +static void bar_pane_comment_close(GtkWidget *bar) +{ + PaneCommentData *pcd; + + pcd = g_object_get_data(G_OBJECT(bar), "pane_data"); + if (!pcd) return; + + gtk_widget_destroy(pcd->comment_view); +} +#endif + +static void bar_pane_rating_destroy(GtkWidget *widget, gpointer data) +{ + // FIXME: make sure we free the spinbutton + PaneRatingData *prd = data; + + file_data_unregister_notify_func(bar_pane_rating_notify_cb, prd); + + file_data_unref(prd->fd); + g_free(prd->key); + + g_free(prd->pane.id); + + g_free(prd); +} + + +static GtkWidget *bar_pane_rating_new(const gchar *id, const gchar *title, const gchar *key, + gboolean expanded, gint height) +{ + PaneRatingData *prd; + GtkHBox *hbox; + GtkWidget *tmp; + + prd = g_new0(PaneRatingData, 1); + + prd->pane.pane_set_fd = bar_pane_rating_set_fd; + prd->pane.pane_event = bar_pane_rating_event; + prd->pane.pane_write_config = bar_pane_rating_write_config; + prd->pane.title = bar_pane_expander_title(title); + prd->pane.id = g_strdup(id); + prd->pane.type = PANE_RATING; + + prd->pane.expanded = expanded; + + prd->key = g_strdup(key); + prd->height = height; + + // HBOX + hbox = (GtkHBox*)gtk_hbox_new(FALSE, 0); + + prd->container = hbox; + g_object_set_data(G_OBJECT(prd->container), "pane_data", prd); + g_signal_connect(G_OBJECT(prd->container), "destroy", + G_CALLBACK(bar_pane_rating_destroy), prd); + + gtk_widget_set_size_request((GtkWidget*) prd->container, -1, -1); + gtk_widget_show((GtkWidget*) hbox); + + // AUTOADVANCE CHECKBOX + tmp = gtk_check_button_new_with_label("AA"); + gtk_box_pack_start((GtkBox*) hbox, tmp, TRUE, TRUE, 0); + gtk_widget_show(tmp); + prd->auto_adv = (GtkToggleButton*) tmp; + + // INCREMENT/DECREMENT BUTTONS + tmp = gtk_button_new_with_label(_("↓ Dec.")); + gtk_box_pack_start((GtkBox*) hbox, tmp, TRUE, TRUE, 0); + g_signal_connect(G_OBJECT(tmp), "clicked", G_CALLBACK(bar_pane_rating_dec_value_cb), prd); + gtk_widget_show(tmp); + + tmp = gtk_button_new_with_label(_("↑ Inc.")); + gtk_box_pack_end((GtkBox*) hbox, tmp, TRUE, TRUE, 0); + g_signal_connect(G_OBJECT(tmp), "clicked", G_CALLBACK(bar_pane_rating_inc_value_cb), prd); + gtk_widget_show(tmp); + + + // SPIN BUTTON + prd->spinbutton = (GtkSpinButton*) gtk_spin_button_new_with_range((gdouble) MIN_RATING, + (gdouble) MAX_RATING, 1.0); + gtk_spin_button_set_numeric(prd->spinbutton, TRUE); + gtk_spin_button_set_snap_to_ticks(prd->spinbutton, TRUE); + + gtk_box_pack_start((GtkBox*) hbox, (GtkWidget*) prd->spinbutton, FALSE, TRUE, 0); +// g_signal_connect(G_OBJECT(pcd->comment_view), "populate-popup", +// G_CALLBACK(bar_pane_comment_populate_popup), pcd); + gtk_widget_show((GtkWidget*) prd->spinbutton); + + g_signal_connect(G_OBJECT(prd->spinbutton), "value-changed", + G_CALLBACK(bar_pane_rating_changed), prd); + + + file_data_register_notify_func(bar_pane_rating_notify_cb, prd, NOTIFY_PRIORITY_LOW); + + return (GtkWidget*) prd->container; +} + +GtkWidget *bar_pane_rating_new_from_config(const gchar **attribute_names, + const gchar **attribute_values) +{ + gchar *title = NULL; + gchar *key = g_strdup(RATING_KEY); + gboolean expanded = TRUE; + gint height = 50; + gchar *id = g_strdup("rating"); + GtkWidget *ret; + + while (*attribute_names) + { + const gchar *option = *attribute_names++; + const gchar *value = *attribute_values++; + + if (READ_CHAR_FULL("title", title)) continue; + if (READ_CHAR_FULL("key", key)) continue; + if (READ_BOOL_FULL("expanded", expanded)) continue; + if (READ_INT_FULL("height", height)) continue; + if (READ_CHAR_FULL("id", id)) continue; + + + log_printf("unknown attribute %s = %s\n", option, value); + } + + bar_pane_translate_title(PANE_RATING, id, &title); + ret = bar_pane_rating_new(id, title, key, expanded, height); + g_free(title); + g_free(key); + g_free(id); + return ret; +} + +void bar_pane_rating_update_from_config(GtkWidget *pane, const gchar **attribute_names, + const gchar **attribute_values) +{ + PaneRatingData *prd; + + prd = g_object_get_data(G_OBJECT(pane), "pane_data"); + if (!prd) return; + + gchar *title = NULL; + + while (*attribute_names) + { + const gchar *option = *attribute_names++; + const gchar *value = *attribute_values++; + + if (READ_CHAR_FULL("title", title)) continue; + if (READ_CHAR_FULL("key", prd->key)) continue; + if (READ_BOOL_FULL("expanded", prd->pane.expanded)) continue; + if (READ_INT_FULL("height", prd->height)) continue; + if (READ_CHAR_FULL("id", prd->pane.id)) continue; + + + log_printf("unknown attribute %s = %s\n", option, value); + } + + if (title) + { + bar_pane_translate_title(PANE_RATING, prd->pane.id, &title); + gtk_label_set_text(GTK_LABEL(prd->pane.title), title); + g_free(title); + } + gtk_widget_set_size_request((GtkWidget*) prd->container, -1, -1); + bar_update_expander(pane); + bar_pane_rating_update(prd); +} + +/* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */ diff --git a/trunk/src/bar_rating.h b/trunk/src/bar_rating.h new file mode 100644 index 0000000..1862159 --- /dev/null +++ b/trunk/src/bar_rating.h @@ -0,0 +1,30 @@ +/* + * Geeqie + * (C) 2004 John Ellis + * Copyright (C) 2008 - 2009 The Geeqie Team + * + * Author: Omari Stephens + * + * This software is released under the GNU General Public License (GNU GPL). + * Please read the included file COPYING for more information. + * This software comes with no warranty of any kind, use at your own risk! + */ + + +#ifndef BAR_RATING_H +#define BAR_RATING_H + +GtkWidget *bar_pane_rating_new_from_config(const gchar **attribute_names, + const gchar **attribute_values); +void bar_pane_rating_update_from_config(GtkWidget *pane, const gchar **attribute_names, + const gchar **attribute_values); +void bar_pane_rating_inc_value(gpointer data); +void bar_pane_rating_dec_value(gpointer data); +void bar_pane_rating_set_value(gint value, gpointer data); + +#define MIN_RATING 0 +#define MAX_RATING 10 + + +#endif +/* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */ diff --git a/trunk/src/filedata.c b/trunk/src/filedata.c index 43dc828..97e5ff9 100644 --- a/trunk/src/filedata.c +++ b/trunk/src/filedata.c @@ -230,6 +230,9 @@ static void file_data_set_collate_keys(FileData *fd) g_free(fd->collate_key_name); g_free(fd->collate_key_name_nocase); + g_free(fd->metadata_collate_key); + fd->metadata_collate_key = NULL; + #if GLIB_CHECK_VERSION(2, 8, 0) fd->collate_key_name = g_utf8_collate_key_for_filename(fd->name, -1); fd->collate_key_name_nocase = g_utf8_collate_key_for_filename(caseless_name, -1); diff --git a/trunk/src/layout_util.c b/trunk/src/layout_util.c index b853852..fa09e4f 100644 --- a/trunk/src/layout_util.c +++ b/trunk/src/layout_util.c @@ -17,6 +17,7 @@ #include "advanced_exif.h" #include "bar_sort.h" #include "bar.h" +#include "bar_rating.h" #include "cache_maint.h" #include "collect.h" #include "collect-dlg.h" @@ -750,6 +751,38 @@ static void layout_menu_bar_exif_cb(GtkAction *action, gpointer data) layout_exif_window_new(lw); } +static void layout_menu_bar_rating_cb(GtkAction *action, gpointer data) +{ + LayoutWindow *lw = data; + GtkWidget *pane; + void *prd; + const gchar *action_name; + + if(!lw->bar) return; + + pane = bar_find_pane_by_id(lw->bar, PANE_RATING, "rating"); + if(!pane) return; + + prd = g_object_get_data(G_OBJECT(pane), "pane_data"); + if(!prd) return; + + // Got a pane; now poke at it + action_name = gtk_action_get_name(action); + if(!g_strcmp0(action_name, "IncRating")) bar_pane_rating_inc_value(prd); + else if(!g_strcmp0(action_name, "DecRating")) bar_pane_rating_dec_value(prd); + else if(!g_strcmp0(action_name, "Rating0")) bar_pane_rating_set_value(0, prd); + else if(!g_strcmp0(action_name, "Rating1")) bar_pane_rating_set_value(1, prd); + else if(!g_strcmp0(action_name, "Rating2")) bar_pane_rating_set_value(2, prd); + else if(!g_strcmp0(action_name, "Rating3")) bar_pane_rating_set_value(3, prd); + else if(!g_strcmp0(action_name, "Rating4")) bar_pane_rating_set_value(4, prd); + else if(!g_strcmp0(action_name, "Rating5")) bar_pane_rating_set_value(5, prd); + else if(!g_strcmp0(action_name, "Rating6")) bar_pane_rating_set_value(6, prd); + else if(!g_strcmp0(action_name, "Rating7")) bar_pane_rating_set_value(7, prd); + else if(!g_strcmp0(action_name, "Rating8")) bar_pane_rating_set_value(8, prd); + else if(!g_strcmp0(action_name, "Rating9")) bar_pane_rating_set_value(9, prd); + else if(!g_strcmp0(action_name, "Rating10")) bar_pane_rating_set_value(10, prd); +} + static void layout_menu_float_cb(GtkToggleAction *action, gpointer data) { LayoutWindow *lw = data; @@ -1236,6 +1269,8 @@ static GtkActionEntry menu_entries[] = { { "EditMenu", NULL, N_("_Edit"), NULL, NULL, NULL }, { "SelectMenu", NULL, N_("_Select"), NULL, NULL, NULL }, { "OrientationMenu", NULL, N_("_Orientation"), NULL, NULL, NULL }, + { "MetadataMenu", NULL, N_("_Metadata"), NULL, NULL, NULL }, + { "MetadataRateMenu", NULL, N_("_Set Rating"), NULL, NULL, NULL }, { "ExternalMenu", NULL, N_("E_xternal Editors"), NULL, NULL, NULL }, { "PreferencesMenu", NULL, N_("P_references"), NULL, NULL, NULL }, { "ViewMenu", NULL, N_("_View"), NULL, NULL, NULL }, @@ -1293,6 +1328,19 @@ static GtkActionEntry menu_entries[] = { { "Maintenance", NULL, N_("_Thumbnail maintenance..."), NULL, N_("Thumbnail maintenance..."), CB(layout_menu_remove_thumb_cb) }, { "Wallpaper", NULL, N_("Set as _wallpaper"), NULL, N_("Set as wallpaper"), CB(layout_menu_wallpaper_cb) }, { "SaveMetadata", GTK_STOCK_SAVE, N_("_Save metadata"), "<control>S", N_("Save metadata"), CB(layout_menu_metadata_write_cb) }, + { "IncRating", NULL, N_("_Increment Rating"), "<alt>KP_Add", N_("Increment image rating"), CB(layout_menu_bar_rating_cb) }, + { "DecRating", NULL, N_("_Decrement Rating"), "<alt>KP_Subtract", N_("Decrement image rating"), CB(layout_menu_bar_rating_cb) }, + { "Rating0", NULL, N_("Rate _0"), "<alt>KP_0", N_("Set image rating to 0"), CB(layout_menu_bar_rating_cb) }, + { "Rating1", NULL, N_("Rate _1"), "<alt>KP_1", N_("Set image rating to 1"), CB(layout_menu_bar_rating_cb) }, + { "Rating2", NULL, N_("Rate _2"), "<alt>KP_2", N_("Set image rating to 2"), CB(layout_menu_bar_rating_cb) }, + { "Rating3", NULL, N_("Rate _3"), "<alt>KP_3", N_("Set image rating to 3"), CB(layout_menu_bar_rating_cb) }, + { "Rating4", NULL, N_("Rate _4"), "<alt>KP_4", N_("Set image rating to 4"), CB(layout_menu_bar_rating_cb) }, + { "Rating5", NULL, N_("Rate _5"), "<alt>KP_5", N_("Set image rating to 5"), CB(layout_menu_bar_rating_cb) }, + { "Rating6", NULL, N_("Rate _6"), "<alt>KP_6", N_("Set image rating to 6"), CB(layout_menu_bar_rating_cb) }, + { "Rating7", NULL, N_("Rate _7"), "<alt>KP_7", N_("Set image rating to 7"), CB(layout_menu_bar_rating_cb) }, + { "Rating8", NULL, N_("Rate _8"), "<alt>KP_8", N_("Set image rating to 8"), CB(layout_menu_bar_rating_cb) }, + { "Rating9", NULL, N_("Rate _9"), "<alt>KP_9", N_("Set image rating to 9"), CB(layout_menu_bar_rating_cb) }, + { "Rating10", NULL, N_("Rate _10"), "<alt>KP_Decimal", N_("Set image rating to 10"), CB(layout_menu_bar_rating_cb) }, { "ZoomIn", GTK_STOCK_ZOOM_IN, N_("Zoom _in"), "equal", N_("Zoom in"), CB(layout_menu_zoom_in_cb) }, { "ZoomInAlt1", GTK_STOCK_ZOOM_IN, N_("Zoom _in"), "KP_Add", N_("Zoom in"), CB(layout_menu_zoom_in_cb) }, { "ZoomOut", GTK_STOCK_ZOOM_OUT, N_("Zoom _out"), "minus", N_("Zoom out"), CB(layout_menu_zoom_out_cb) }, @@ -1343,7 +1391,6 @@ static GtkActionEntry menu_entries[] = { { "About", GTK_STOCK_ABOUT, N_("_About"), NULL, N_("About"), CB(layout_menu_about_cb) }, { "LogWindow", NULL, N_("_Log Window"), NULL, N_("Log Window"), CB(layout_menu_log_window_cb) }, { "ExifWin", NULL, N_("_Exif window"), "<control>E", N_("Exif window"), CB(layout_menu_bar_exif_cb) }, - }; static GtkToggleActionEntry menu_toggle_entries[] = { @@ -1469,7 +1516,25 @@ static const gchar *menu_ui_description = " <menuitem action='Flip'/>" " <menuitem action='AlterNone'/>" " </menu>" -" <menuitem action='SaveMetadata'/>" +" <menu action='MetadataMenu'>" +" <menuitem action='SaveMetadata'/>" +" <separator/>" +" <menuitem action='IncRating'/>" +" <menuitem action='DecRating'/>" +" <menu action='MetadataRateMenu'>" +" <menuitem action='Rating0'/>" +" <menuitem action='Rating1'/>" +" <menuitem action='Rating2'/>" +" <menuitem action='Rating3'/>" +" <menuitem action='Rating4'/>" +" <menuitem action='Rating5'/>" +" <menuitem action='Rating6'/>" +" <menuitem action='Rating7'/>" +" <menuitem action='Rating8'/>" +" <menuitem action='Rating9'/>" +" <menuitem action='Rating10'/>" +" </menu>" +" </menu>" " <placeholder name='PropertiesSection'/>" " <separator/>" " <menu action='PreferencesMenu'>" diff --git a/trunk/src/metadata.h b/trunk/src/metadata.h index 639da6d..be265cc 100644 --- a/trunk/src/metadata.h +++ b/trunk/src/metadata.h @@ -17,6 +17,7 @@ #define COMMENT_KEY "Xmp.dc.description" #define KEYWORD_KEY "Xmp.dc.subject" #define ORIENTATION_KEY "Xmp.tiff.Orientation" +#define RATING_KEY "Xmp.xmp.Rating" gboolean metadata_write_queue_remove(FileData *fd); gboolean metadata_write_queue_remove_list(GList *list); diff --git a/trunk/src/rcfile.c b/trunk/src/rcfile.c index 4053b58..babd0a4 100644 --- a/trunk/src/rcfile.c +++ b/trunk/src/rcfile.c @@ -22,6 +22,7 @@ #include "bar_histogram.h" #include "bar_keywords.h" #include "bar_sort.h" +#include "bar_rating.h" #include "editors.h" #include "filefilter.h" #include "misc.h" @@ -918,6 +919,22 @@ static void options_parse_bar(GQParserData *parser_data, GMarkupParseContext *co } options_parse_func_push(parser_data, options_parse_leaf, NULL, NULL); } + else if (g_ascii_strcasecmp(element_name, "pane_rating") == 0) + { + GtkWidget *pane = bar_find_pane_by_id(bar, PANE_RATING, + options_get_id(attribute_names, attribute_values)); + if (pane) + { + bar_pane_rating_update_from_config(pane, attribute_names, + attribute_values); + } + else + { + pane = bar_pane_rating_new_from_config(attribute_names, attribute_values); + bar_add(bar, pane); + } + options_parse_func_push(parser_data, options_parse_leaf, NULL, NULL); + } #ifdef HAVE_LIBCHAMPLAIN #ifdef HAVE_LIBCHAMPLAIN_GTK else if (g_ascii_strcasecmp(element_name, "pane_gps") == 0) diff --git a/trunk/src/search.c b/trunk/src/search.c index 451e091..f99687b 100644 --- a/trunk/src/search.c +++ b/trunk/src/search.c @@ -40,6 +40,7 @@ #include "utilops.h" #include "window.h" #include "bar_keywords.h" +#include "bar_rating.h" #include <gdk/gdkkeysyms.h> /* for keyboard values */ @@ -122,6 +123,11 @@ struct _SearchData GtkWidget *spin_similarity; GtkWidget *entry_similarity; + GtkWidget *check_rating; + GtkWidget *menu_rating; + GtkWidget *spin_rating; + GtkWidget *spin_rating_end; + GtkWidget *check_keywords; GtkWidget *menu_keywords; GtkWidget *entry_keywords; @@ -136,6 +142,8 @@ struct _SearchData gboolean search_name_match_case; gint64 search_size; gint64 search_size_end; + guint64 search_rating; + guint64 search_rating_end; gint search_date_y; gint search_date_m; gint search_date_d; @@ -159,6 +167,7 @@ struct _SearchData MatchType match_size; MatchType match_date; MatchType match_dimensions; + MatchType match_rating; MatchType match_keywords; MatchType match_comment; @@ -167,6 +176,7 @@ struct _SearchData gboolean match_date_enable; gboolean match_dimensions_enable; gboolean match_similarity_enable; + gboolean match_rating_enable; gboolean match_keywords_enable; gboolean match_comment_enable; @@ -233,6 +243,14 @@ static const MatchList text_search_menu_date[] = { { N_("between"), SEARCH_MATCH_BETWEEN } }; +static const MatchList text_search_menu_rating[] = { + { N_("equal to"), SEARCH_MATCH_EQUAL }, + { N_("less than"), SEARCH_MATCH_UNDER }, + { N_("greater than"), SEARCH_MATCH_OVER }, + { N_("between"), SEARCH_MATCH_BETWEEN }, + { N_("unset"), SEARCH_MATCH_NONE }, +}; + static const MatchList text_search_menu_keyword[] = { { N_("match all"), SEARCH_MATCH_ALL }, { N_("match any"), SEARCH_MATCH_ANY }, @@ -1799,6 +1817,36 @@ static gboolean search_file_next(SearchData *sd) } } + if (match && sd->match_rating_enable) + { + tested = TRUE; + match = FALSE; + guint64 rating = metadata_read_int(fd, RATING_KEY, (guint64) -1); + + if (rating == (guint64) -1) + { + /* Files without a rating only match if we're actively looking for them */ + match = (sd->match_rating == SEARCH_MATCH_NONE); + } + else if (sd->match_rating == SEARCH_MATCH_EQUAL) + { + match = (rating == sd->search_rating); + } + else if (sd->match_rating == SEARCH_MATCH_UNDER) + { + match = (rating < sd->search_rating); + } + else if (sd->match_rating == SEARCH_MATCH_OVER) + { + match = (rating > sd->search_rating); + } + else if (sd->match_rating == SEARCH_MATCH_BETWEEN) + { + match = MATCH_IS_BETWEEN(rating, sd->search_rating, + sd->search_rating_end); + } + } + if (match && sd->match_keywords_enable && sd->search_keyword_list) { GList *list; @@ -2427,6 +2475,17 @@ static void menu_choice_dimensions_cb(GtkWidget *combo, gpointer data) (sd->match_dimensions == SEARCH_MATCH_BETWEEN)); } +static void menu_choice_rating_cb(GtkWidget *combo, gpointer data) +{ + SearchData *sd = data; + + if (!menu_choice_get_match_type(combo, &sd->match_rating)) return; + + menu_choice_set_visible(sd->spin_rating, sd->match_rating != SEARCH_MATCH_NONE); + menu_choice_set_visible(gtk_widget_get_parent(sd->spin_rating_end), + (sd->match_rating == SEARCH_MATCH_BETWEEN)); +} + static void menu_choice_keyword_cb(GtkWidget *combo, gpointer data) { SearchData *sd = data; @@ -2623,6 +2682,7 @@ void search_new(FileData *dir_fd, FileData *example_file) sd->match_size = SEARCH_MATCH_EQUAL; sd->match_date = SEARCH_MATCH_EQUAL; sd->match_dimensions = SEARCH_MATCH_EQUAL; + sd->match_rating = SEARCH_MATCH_EQUAL; sd->match_keywords = SEARCH_MATCH_ALL; sd->match_comment = SEARCH_MATCH_CONTAINS; @@ -2762,6 +2822,19 @@ void search_new(FileData *dir_fd, FileData *example_file) gtk_box_pack_start(GTK_BOX(hbox), combo, TRUE, TRUE, 0); gtk_widget_show(combo); + /* Search for rating */ + hbox = menu_choice(sd->box_search, &sd->check_rating, &sd->menu_rating, + _("Rating is"), &sd->match_rating_enable, text_search_menu_rating, + sizeof(text_search_menu_rating) / sizeof(MatchList), + G_CALLBACK(menu_choice_rating_cb), sd); + sd->spin_rating = menu_spin(hbox, MIN_RATING, MAX_RATING, sd->search_rating, + G_CALLBACK(menu_choice_spin_cb), &sd->search_rating); + hbox2 = gtk_hbox_new(FALSE, PREF_PAD_SPACE); + gtk_box_pack_start(GTK_BOX(hbox), hbox2, FALSE, FALSE, 0); + pref_label_new(hbox2, _("and")); + sd->spin_rating_end = menu_spin(hbox2, MIN_RATING, MAX_RATING, sd->search_rating_end, + G_CALLBACK(menu_choice_spin_cb), &sd->search_rating_end); + /* Search for image keywords */ hbox = menu_choice(sd->box_search, &sd->check_keywords, &sd->menu_keywords, _("Keywords"), &sd->match_keywords_enable, diff --git a/trunk/src/typedefs.h b/trunk/src/typedefs.h index 86fc4ea..0691778 100644 --- a/trunk/src/typedefs.h +++ b/trunk/src/typedefs.h @@ -463,6 +463,7 @@ struct _FileData { const gchar *extension; gchar *collate_key_name; gchar *collate_key_name_nocase; + gchar *metadata_collate_key; /* for sorting by metadata tags */ gint64 size; time_t date; mode_t mode; /* this is needed at least for notification in view_dir because it is preserved after the file/directory is deleted */
------------------------------------------------------------------------------ For Developers, A Lot Can Happen In A Second. Boundary is the first to Know...and Tell You. Monitor Your Applications in Ultra-Fine Resolution. Try it FREE! http://p.sf.net/sfu/Boundary-d2dvs2
_______________________________________________ Geeqie-devel mailing list Geeqie-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/geeqie-devel