# HG changeset patch # User nadvornik # Date 1234641054 0 # Node ID 50ae02a4a675b8dd932560cb6ae1ddbfa533002c # Parent 0c918f8b1f51928a9eb6353c145875ea7d4313d4 replaced bar_info with an universal bar, restored the original functionality (more or less) bar configuration is not yet saved diff -r 0c918f8b1f51 -r 50ae02a4a675 src/Makefile.am --- a/src/Makefile.am Mon Feb 09 09:02:04 2009 +0000 +++ b/src/Makefile.am Sat Feb 14 19:50:54 2009 +0000 @@ -76,8 +76,14 @@ $(module_SLIK) \ ClayRGB1998.icc \ ClayRGB1998_icc.h \ + bar.c \ + bar.h \ + bar_comment.c \ + bar_comment.h \ bar_info.c \ bar_info.h \ + bar_keywords.c \ + bar_keywords.h \ bar_exif.c \ bar_exif.h \ bar_sort.c \ diff -r 0c918f8b1f51 -r 50ae02a4a675 src/bar.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/bar.c Sat Feb 14 19:50:54 2009 +0000 @@ -0,0 +1,352 @@ +/* + * Geeqie + * (C) 2004 John Ellis + * Copyright (C) 2008 - 2009 The Geeqie Team + * + * Author: Vladimir Nadvornik + * + * 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.h" + +#include "filedata.h" +#include "history_list.h" +#include "info.h" +#include "metadata.h" +#include "misc.h" +#include "ui_fileops.h" +#include "ui_misc.h" +#include "ui_utildlg.h" + +#include "ui_menu.h" +#include "bar_comment.h" +#include "bar_keywords.h" + +#define BAR_SIZE_INCREMENT 48 +#define BAR_ARROW_SIZE 7 + + +typedef struct _BarData BarData; +struct _BarData +{ + GtkWidget *widget; + GtkWidget *vbox; + FileData *fd; + GtkWidget *label_file_name; + + GList *(*list_func)(gpointer); + gpointer list_data; +}; + +static void bar_expander_move(GtkWidget *widget, gpointer data, gboolean up) +{ + GtkWidget *expander = data; + GtkWidget *box; + gint pos; + if (!expander) return; + box = gtk_widget_get_ancestor(expander, GTK_TYPE_BOX); + if (!box) return; + + gtk_container_child_get(GTK_CONTAINER(box), expander, "position", &pos, NULL); + + pos = up ? (pos - 1) : (pos + 1); + if (pos < 0) pos = 0; + + gtk_box_reorder_child(GTK_BOX(box), expander, pos); +} + + +static void bar_expander_move_up_cb(GtkWidget *widget, gpointer data) +{ + bar_expander_move(widget, data, TRUE); +} + +static void bar_expander_move_down_cb(GtkWidget *widget, gpointer data) +{ + bar_expander_move(widget, data, FALSE); +} + + +static void bar_expander_menu_popup(GtkWidget *data) +{ + GtkWidget *menu; + + menu = popup_menu_short_lived(); + + menu_item_add_stock(menu, _("Move _up"), GTK_STOCK_GO_UP, G_CALLBACK(bar_expander_move_up_cb), data); + menu_item_add_stock(menu, _("Move _down"), GTK_STOCK_GO_DOWN, G_CALLBACK(bar_expander_move_down_cb), data); + gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, data, 0, GDK_CURRENT_TIME); +} + + +static gboolean bar_expander_menu_cb(GtkWidget *widget, GdkEventButton *bevent, gpointer data) +{ + if (bevent->button == MOUSE_BUTTON_RIGHT) + { + bar_expander_menu_popup(widget); + return TRUE; + } + return FALSE; +} + + +void bar_pane_set_fd_cb(GtkWidget *expander, gpointer data) +{ + GtkWidget *widget = gtk_bin_get_child(GTK_BIN(expander)); + PaneData *pd = g_object_get_data(G_OBJECT(widget), "pane_data"); + if (!pd) return; + if (pd->pane_set_fd) pd->pane_set_fd(widget, data); +} + +void bar_set_fd(GtkWidget *bar, FileData *fd) +{ + BarData *bd; + bd = g_object_get_data(G_OBJECT(bar), "bar_data"); + if (!bd) return; + + file_data_unref(bd->fd); + bd->fd = file_data_ref(fd); + + gtk_container_foreach(GTK_CONTAINER(bd->vbox), bar_pane_set_fd_cb, fd); + + gtk_label_set_text(GTK_LABEL(bd->label_file_name), (bd->fd) ? bd->fd->name : ""); + +} + +gint bar_event(GtkWidget *bar, GdkEvent *event) +{ + BarData *bd; + GList *list, *work; + gint ret = FALSE; + bd = g_object_get_data(G_OBJECT(bar), "bar_data"); + if (!bd) return FALSE; + + list = gtk_container_get_children(GTK_CONTAINER(bd->vbox)); + + work = list; + while (work) + { + GtkWidget *widget = gtk_bin_get_child(GTK_BIN(work->data)); + PaneData *pd = g_object_get_data(G_OBJECT(widget), "pane_data"); + if (!pd) continue; + + if (pd->pane_event && pd->pane_event(widget, event)) + { + ret = TRUE; + break; + } + work = work->next; + } + g_list_free(list); + return ret; +} + +void bar_pane_set_selection_func(GtkWidget *pane, GList *(*list_func)(gpointer data), gpointer data) +{ + PaneData *pd; + + pd = g_object_get_data(G_OBJECT(pane), "pane_data"); + if (!pd) return; + + pd->list_func = list_func; + pd->list_data = data; +} + +void bar_set_selection_func(GtkWidget *bar, GList *(*list_func)(gpointer data), gpointer data) +{ + BarData *bd; + GList *list, *work; + bd = g_object_get_data(G_OBJECT(bar), "bar_data"); + if (!bd) return; + + bd->list_func = list_func; + bd->list_data = data; + + list = gtk_container_get_children(GTK_CONTAINER(bd->vbox)); + + work = list; + while (work) + { + GtkWidget *widget = gtk_bin_get_child(GTK_BIN(work->data)); + + bar_pane_set_selection_func(widget, list_func, data); + + work = work->next; + } + g_list_free(list); + return; +} + + + + + +static void bar_add(GtkWidget *bar, GtkWidget *pane) +{ + GtkWidget *expander; + GtkWidget *label; + BarData *bd = g_object_get_data(G_OBJECT(bar), "bar_data"); + PaneData *pd = g_object_get_data(G_OBJECT(pane), "pane_data"); + + + if (!bd) return; + + expander = gtk_expander_new(pd ? pd->title : ""); + gtk_box_pack_start(GTK_BOX(bd->vbox), expander, FALSE, TRUE, 0); + + g_signal_connect(expander, "button_press_event", G_CALLBACK(bar_expander_menu_cb), bd); + + label = gtk_expander_get_label_widget(GTK_EXPANDER(expander)); +// gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5); + pref_label_bold(label, TRUE, FALSE); + + gtk_container_add(GTK_CONTAINER(expander), pane); + + gtk_expander_set_expanded(GTK_EXPANDER(expander), TRUE); + + gtk_widget_show(expander); + + if (bd->list_func) bar_pane_set_selection_func(pane, bd->list_func, bd->list_data); + if (bd->fd && pd && pd->pane_set_fd) pd->pane_set_fd(pane, bd->fd); + +} + +static void bar_width(BarData *bd, gint val) +{ + gint size; + + size = bd->widget->allocation.width; + size = CLAMP(size + val, BAR_SIZE_INCREMENT * 2, BAR_SIZE_INCREMENT * 16); + + gtk_widget_set_size_request(bd->widget, size, -1); + options->panels.info.width = bd->widget->allocation.width; +} + +static void bar_larger(GtkWidget *widget, gpointer data) +{ + BarData *bd = data; + + bar_width(bd, BAR_SIZE_INCREMENT); +} + +static void bar_smaller(GtkWidget *widget, gpointer data) +{ + BarData *bd = data; + + bar_width(bd, -BAR_SIZE_INCREMENT); +} + +void bar_close(GtkWidget *bar) +{ + BarData *bd; + + bd = g_object_get_data(G_OBJECT(bar), "bar_data"); + if (!bd) return; + + gtk_widget_destroy(bd->widget); +} + +static void bar_destroy(GtkWidget *widget, gpointer data) +{ + BarData *bd = data; + + file_data_unref(bd->fd); + g_free(bd); +} + +GtkWidget *bar_new(GtkWidget *bounding_widget) +{ + BarData *bd; + GtkWidget *box; + GtkWidget *sizer; + GtkWidget *label; + GtkWidget *button; + GtkWidget *arrow; + GtkWidget *scrolled; + GtkWidget *widget; + + bd = g_new0(BarData, 1); + + bd->widget = gtk_vbox_new(FALSE, PREF_PAD_GAP); + g_object_set_data(G_OBJECT(bd->widget), "bar_data", bd); + g_signal_connect(G_OBJECT(bd->widget), "destroy", + G_CALLBACK(bar_destroy), bd); + + box = gtk_hbox_new(FALSE, 0); + + sizer = sizer_new(bd->widget, bounding_widget, SIZER_POS_LEFT); + sizer_set_limits(sizer, BAR_SIZE_INCREMENT * 2, -1, -1 , -1); + gtk_box_pack_start(GTK_BOX(box), sizer, FALSE, FALSE, 0); + gtk_widget_show(sizer); + + label = gtk_label_new(_("Filename:")); + gtk_misc_set_alignment(GTK_MISC(label), 1.0, 0.0); + gtk_box_pack_start(GTK_BOX(box), label, TRUE, TRUE, 0); + gtk_widget_show(label); + + bd->label_file_name = gtk_label_new(""); + pref_label_bold(bd->label_file_name, TRUE, FALSE); + gtk_misc_set_alignment(GTK_MISC(bd->label_file_name), 0.0, 0.0); + gtk_box_pack_start(GTK_BOX(box), bd->label_file_name, TRUE, TRUE, 0); + gtk_widget_show(bd->label_file_name); + + button = gtk_button_new(); + gtk_button_set_relief(GTK_BUTTON(button), GTK_RELIEF_NONE); + g_signal_connect(G_OBJECT(button), "clicked", + G_CALLBACK(bar_smaller), bd); + gtk_box_pack_end(GTK_BOX(box), button, FALSE, FALSE, 0); + arrow = gtk_arrow_new(GTK_ARROW_RIGHT, GTK_SHADOW_NONE); + gtk_widget_set_size_request(arrow, BAR_ARROW_SIZE, BAR_ARROW_SIZE); + gtk_container_add(GTK_CONTAINER(button), arrow); + gtk_widget_show(arrow); + gtk_widget_show(button); + + button = gtk_button_new(); + gtk_button_set_relief(GTK_BUTTON(button), GTK_RELIEF_NONE); + g_signal_connect(G_OBJECT(button), "clicked", + G_CALLBACK(bar_larger), bd); + gtk_box_pack_end(GTK_BOX(box), button, FALSE, FALSE, 0); + arrow = gtk_arrow_new(GTK_ARROW_LEFT, GTK_SHADOW_NONE); + gtk_widget_set_size_request(arrow, BAR_ARROW_SIZE, BAR_ARROW_SIZE); + gtk_container_add(GTK_CONTAINER(button), arrow); + gtk_widget_show(arrow); + gtk_widget_show(button); + + gtk_box_pack_start(GTK_BOX(bd->widget), box, FALSE, FALSE, 0); + gtk_widget_show(box); + + scrolled = gtk_scrolled_window_new(NULL, NULL); + gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled), + GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); + gtk_box_pack_start(GTK_BOX(bd->widget), scrolled, TRUE, TRUE, 0); + gtk_widget_show(scrolled); + + + bd->vbox = gtk_vbox_new(FALSE, 0); + gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scrolled), bd->vbox); + gtk_viewport_set_shadow_type(GTK_VIEWPORT(gtk_bin_get_child(GTK_BIN(scrolled))), GTK_SHADOW_NONE); + + gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_NONE); + gtk_widget_show(bd->vbox); + + + widget = bar_pane_comment_new(_("Title"), "Xmp.dc.title", 40); + bar_add(bd->widget, widget); + + widget = bar_pane_keywords_new(_("Keywords"), KEYWORD_KEY); + bar_add(bd->widget, widget); + + widget = bar_pane_comment_new(_("Comment"), "Xmp.dc.description", 150); + bar_add(bd->widget, widget); + + return bd->widget; +} + + + +/* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */ diff -r 0c918f8b1f51 -r 50ae02a4a675 src/bar.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/bar.h Sat Feb 14 19:50:54 2009 +0000 @@ -0,0 +1,43 @@ +/* + * Geeqie + * (C) 2004 John Ellis + * Copyright (C) 2008 - 2009 The Geeqie Team + * + * Author: Vladimir Nadvornik + * + * 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_H +#define BAR_H + +typedef struct _PaneData PaneData; + +struct _PaneData { + void (*pane_set_fd)(GtkWidget *pane, FileData *fd); + gint (*pane_event)(GtkWidget *pane, GdkEvent *event); + gchar *title; + + GList *(*list_func)(gpointer); + gpointer list_data; + +}; + + + +GtkWidget *bar_new(GtkWidget *bounding_widget); +void bar_close(GtkWidget *bar); + +void bar_set_fd(GtkWidget *bar, FileData *fd); +gint bar_event(GtkWidget *bar, GdkEvent *event); + +void bar_set_selection_func(GtkWidget *bar, GList *(*list_func)(gpointer data), gpointer data); + +/* following functions are common for all panes */ +void bar_pane_set_selection_func(GtkWidget *pane, GList *(*list_func)(gpointer data), gpointer data); + +#endif +/* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */ diff -r 0c918f8b1f51 -r 50ae02a4a675 src/bar_comment.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/bar_comment.c Sat Feb 14 19:50:54 2009 +0000 @@ -0,0 +1,240 @@ +/* + * Geeqie + * (C) 2004 John Ellis + * Copyright (C) 2008 - 2009 The Geeqie Team + * + * Author: John Ellis + * + * 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_comment.h" + +#include "bar.h" +#include "metadata.h" +#include "filedata.h" +#include "ui_menu.h" +#include "ui_misc.h" + +static void bar_pane_comment_changed(GtkTextBuffer *buffer, gpointer data); + +/* + *------------------------------------------------------------------- + * keyword / comment utils + *------------------------------------------------------------------- + */ + + + +typedef struct _PaneCommentData PaneCommentData; +struct _PaneCommentData +{ + PaneData pane; + GtkWidget *widget; + GtkWidget *comment_view; + FileData *fd; + gchar *key; +}; + + +static void bar_pane_comment_write(PaneCommentData *pcd) +{ + gchar *comment; + + if (!pcd->fd) return; + + comment = text_widget_text_pull(pcd->comment_view); + + metadata_write_string(pcd->fd, pcd->key, comment); + g_free(comment); +} + + +static void bar_pane_comment_update(PaneCommentData *pcd) +{ + gchar *comment = NULL; + GtkTextBuffer *comment_buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(pcd->comment_view)); + + g_signal_handlers_block_by_func(comment_buffer, bar_pane_comment_changed, pcd); + + comment = metadata_read_string(pcd->fd, pcd->key, METADATA_PLAIN); + gtk_text_buffer_set_text(comment_buffer, + (comment) ? comment : "", -1); + g_free(comment); + + g_signal_handlers_unblock_by_func(comment_buffer, bar_pane_comment_changed, pcd); + + gtk_widget_set_sensitive(pcd->comment_view, (pcd->fd != NULL)); +} + +static void bar_pane_comment_set_selection(PaneCommentData *pcd, gboolean append) +{ + GList *list = NULL; + GList *work; + gchar *comment = NULL; + + if (!pcd->pane.list_func) return; + + comment = text_widget_text_pull(pcd->comment_view); + + list = pcd->pane.list_func(pcd->pane.list_data); + work = list; + while (work) + { + FileData *fd = work->data; + work = work->next; + + if (append) + { + metadata_append_string(fd, pcd->key, comment); + } + else + { + metadata_write_string(fd, pcd->key, comment); + } + } + + filelist_free(list); + g_free(comment); +} + +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_comment_set_fd(GtkWidget *bar, FileData *fd) +{ + PaneCommentData *pcd; + + pcd = g_object_get_data(G_OBJECT(bar), "pane_data"); + if (!pcd) return; + + file_data_unref(pcd->fd); + pcd->fd = file_data_ref(fd); + + bar_pane_comment_update(pcd); +} + +gint bar_pane_comment_event(GtkWidget *bar, GdkEvent *event) +{ + PaneCommentData *pcd; + + pcd = g_object_get_data(G_OBJECT(bar), "pane_data"); + if (!pcd) return FALSE; + + if (GTK_WIDGET_HAS_FOCUS(pcd->comment_view)) return gtk_widget_event(pcd->comment_view, event); + + return FALSE; +} + +static void bar_pane_comment_notify_cb(FileData *fd, NotifyType type, gpointer data) +{ + PaneCommentData *pcd = data; + if (fd == pcd->fd) bar_pane_comment_update(pcd); +} + +static void bar_pane_comment_changed(GtkTextBuffer *buffer, gpointer data) +{ + PaneCommentData *pcd = data; + + file_data_unregister_notify_func(bar_pane_comment_notify_cb, pcd); + bar_pane_comment_write(pcd); + file_data_register_notify_func(bar_pane_comment_notify_cb, pcd, NOTIFY_PRIORITY_LOW); +} + + +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), data); + 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); +} + + +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); +} + +static void bar_pane_comment_destroy(GtkWidget *widget, gpointer data) +{ + PaneCommentData *pcd = data; + + file_data_unregister_notify_func(bar_pane_comment_notify_cb, pcd); + + file_data_unref(pcd->fd); + g_free(pcd->pane.title); + g_free(pcd->key); + + + g_free(pcd); +} + + +GtkWidget *bar_pane_comment_new(const gchar *title, const gchar *key, gint height) +{ + PaneCommentData *pcd; + GtkWidget *scrolled; + GtkTextBuffer *buffer; + + pcd = g_new0(PaneCommentData, 1); + + pcd->pane.pane_set_fd = bar_pane_comment_set_fd; + pcd->pane.pane_event = bar_pane_comment_event; + pcd->pane.title = g_strdup(title); + + pcd->key = g_strdup(key); + + scrolled = gtk_scrolled_window_new(NULL, NULL); + + pcd->widget = scrolled; + g_object_set_data(G_OBJECT(pcd->widget), "pane_data", pcd); + g_signal_connect(G_OBJECT(pcd->widget), "destroy", + G_CALLBACK(bar_pane_comment_destroy), pcd); + + gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN); + gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled), + GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); + + gtk_widget_set_size_request(scrolled, -1, height); + gtk_widget_show(scrolled); + + pcd->comment_view = gtk_text_view_new(); + gtk_container_add(GTK_CONTAINER(scrolled), pcd->comment_view); + g_signal_connect(G_OBJECT(pcd->comment_view), "populate-popup", + G_CALLBACK(bar_pane_comment_populate_popup), pcd); + gtk_widget_show(pcd->comment_view); + + buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(pcd->comment_view)); + g_signal_connect(G_OBJECT(buffer), "changed", + G_CALLBACK(bar_pane_comment_changed), pcd); + + + file_data_register_notify_func(bar_pane_comment_notify_cb, pcd, NOTIFY_PRIORITY_LOW); + + return pcd->widget; +} + +/* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */ diff -r 0c918f8b1f51 -r 50ae02a4a675 src/bar_comment.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/bar_comment.h Sat Feb 14 19:50:54 2009 +0000 @@ -0,0 +1,20 @@ +/* + * Geeqie + * (C) 2004 John Ellis + * Copyright (C) 2008 - 2009 The Geeqie Team + * + * Author: Vladimir Nadvornik + * + * 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_COMMENT_H +#define BAR_COMMENT_H + +GtkWidget *bar_pane_comment_new(const gchar *title, const gchar *key, gint height); + +#endif +/* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */ diff -r 0c918f8b1f51 -r 50ae02a4a675 src/bar_keywords.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/bar_keywords.c Sat Feb 14 19:50:54 2009 +0000 @@ -0,0 +1,814 @@ +/* + * Geeqie + * (C) 2004 John Ellis + * Copyright (C) 2008 - 2009 The Geeqie Team + * + * Author: John Ellis + * + * 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_keywords.h" + +#include "filedata.h" +#include "history_list.h" +#include "info.h" +#include "metadata.h" +#include "misc.h" +#include "ui_fileops.h" +#include "ui_misc.h" +#include "ui_utildlg.h" +#include "utilops.h" +#include "bar.h" +#include "ui_menu.h" + +static const gchar *keyword_favorite_defaults[] = { + N_("Favorite"), + N_("Todo"), + N_("People"), + N_("Places"), + N_("Art"), + N_("Nature"), + N_("Possessions"), + NULL +}; + + +static void bar_pane_keywords_keyword_update_all(void); +static void bar_pane_keywords_changed(GtkTextBuffer *buffer, gpointer data); + +/* + *------------------------------------------------------------------- + * keyword / comment utils + *------------------------------------------------------------------- + */ + + +static GList *keyword_list_pull(GtkWidget *text_widget) +{ + GList *list; + gchar *text; + + text = text_widget_text_pull(text_widget); + list = string_to_keywords_list(text); + + g_free(text); + + return list; +} + +static void keyword_list_push(GtkWidget *textview, GList *list) +{ + GtkTextBuffer *buffer; + GtkTextIter start, end; + + buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(textview)); + gtk_text_buffer_get_bounds(buffer, &start, &end); + gtk_text_buffer_delete(buffer, &start, &end); + + while (list) + { + const gchar *word = list->data; + GtkTextIter iter; + + gtk_text_buffer_get_end_iter(buffer, &iter); + if (word) gtk_text_buffer_insert(buffer, &iter, word, -1); + gtk_text_buffer_get_end_iter(buffer, &iter); + gtk_text_buffer_insert(buffer, &iter, "\n", -1); + + list = list->next; + } +} + + +/* + *------------------------------------------------------------------- + * keyword list dialog + *------------------------------------------------------------------- + */ + +#define KEYWORD_DIALOG_WIDTH 200 +#define KEYWORD_DIALOG_HEIGHT 250 + +typedef struct _KeywordDlg KeywordDlg; +struct _KeywordDlg +{ + GenericDialog *gd; + GtkWidget *treeview; +}; + +static KeywordDlg *keyword_dialog = NULL; + + +static void keyword_dialog_cancel_cb(GenericDialog *gd, gpointer data) +{ + g_free(keyword_dialog); + keyword_dialog = NULL; +} + +static void keyword_dialog_ok_cb(GenericDialog *gd, gpointer data) +{ + KeywordDlg *kd = data; + GtkTreeModel *store; + GtkTreeIter iter; + gint valid; + + history_list_free_key("keywords"); + + store = gtk_tree_view_get_model(GTK_TREE_VIEW(kd->treeview)); + valid = gtk_tree_model_get_iter_first(store, &iter); + while (valid) + { + gchar *key; + + gtk_tree_model_get(store, &iter, 0, &key, -1); + valid = gtk_tree_model_iter_next(store, &iter); + + history_list_add_to_key("keywords", key, 0); + } + + keyword_dialog_cancel_cb(gd, data); + + bar_pane_keywords_keyword_update_all(); +} + +static void keyword_dialog_add_cb(GtkWidget *button, gpointer data) +{ + KeywordDlg *kd = data; + GtkTreeSelection *selection; + GtkTreeModel *store; + GtkTreeIter sibling; + GtkTreeIter iter; + GtkTreePath *tpath; + + selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(kd->treeview)); + if (gtk_tree_selection_get_selected(selection, &store, &sibling)) + { + gtk_list_store_insert_before(GTK_LIST_STORE(store), &iter, &sibling); + } + else + { + store = gtk_tree_view_get_model(GTK_TREE_VIEW(kd->treeview)); + gtk_list_store_append(GTK_LIST_STORE(store), &iter); + } + + gtk_list_store_set(GTK_LIST_STORE(store), &iter, 1, TRUE, -1); + + tpath = gtk_tree_model_get_path(store, &iter); + gtk_tree_view_set_cursor(GTK_TREE_VIEW(kd->treeview), tpath, + gtk_tree_view_get_column(GTK_TREE_VIEW(kd->treeview), 0), TRUE); + gtk_tree_path_free(tpath); +} + +static void keyword_dialog_remove_cb(GtkWidget *button, gpointer data) +{ + KeywordDlg *kd = data; + GtkTreeSelection *selection; + GtkTreeModel *store; + GtkTreeIter iter; + GtkTreeIter next; + GtkTreePath *tpath; + + selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(kd->treeview)); + if (!gtk_tree_selection_get_selected(selection, &store, &iter)) return; + + tpath = NULL; + next = iter; + if (gtk_tree_model_iter_next(store, &next)) + { + tpath = gtk_tree_model_get_path(store, &next); + } + else + { + tpath = gtk_tree_model_get_path(store, &iter); + if (!gtk_tree_path_prev(tpath)) + { + gtk_tree_path_free(tpath); + tpath = NULL; + } + } + if (tpath) + { + gtk_tree_view_set_cursor(GTK_TREE_VIEW(kd->treeview), tpath, + gtk_tree_view_get_column(GTK_TREE_VIEW(kd->treeview), 0), FALSE); + gtk_tree_path_free(tpath); + } + + gtk_list_store_remove(GTK_LIST_STORE(store), &iter); +} + +static void keyword_dialog_edit_cb(GtkCellRendererText *renderer, const gchar *path, + const gchar *new_text, gpointer data) +{ + KeywordDlg *kd = data; + GtkTreeModel *store; + GtkTreeIter iter; + GtkTreePath *tpath; + + if (!new_text || strlen(new_text) == 0) return; + + store = gtk_tree_view_get_model(GTK_TREE_VIEW(kd->treeview)); + + tpath = gtk_tree_path_new_from_string(path); + gtk_tree_model_get_iter(store, &iter, tpath); + gtk_tree_path_free(tpath); + + gtk_list_store_set(GTK_LIST_STORE(store), &iter, 0, new_text, -1); +} + +static void keyword_dialog_populate(KeywordDlg *kd) +{ + GtkListStore *store; + GList *list; + + store = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(kd->treeview))); + gtk_list_store_clear(store); + + list = history_list_get_by_key("keywords"); + list = g_list_last(list); + while (list) + { + GtkTreeIter iter; + + gtk_list_store_append(store, &iter); + gtk_list_store_set(store, &iter, 0, list->data, + 1, TRUE, -1); + + list = list->prev; + } +} + +static void keyword_dialog_show(void) +{ + GtkWidget *scrolled; + GtkListStore *store; + GtkTreeViewColumn *column; + GtkCellRenderer *renderer; + GtkWidget *hbox; + GtkWidget *button; + + if (keyword_dialog) + { + gtk_window_present(GTK_WINDOW(keyword_dialog->gd->dialog)); + return; + } + + keyword_dialog = g_new0(KeywordDlg, 1); + + keyword_dialog->gd = generic_dialog_new(_("Keyword Presets"), + "keyword_presets", NULL, TRUE, + keyword_dialog_cancel_cb, keyword_dialog); + generic_dialog_add_message(keyword_dialog->gd, NULL, _("Favorite keywords list"), NULL); + + generic_dialog_add_button(keyword_dialog->gd, GTK_STOCK_OK, NULL, + keyword_dialog_ok_cb, TRUE); + + scrolled = gtk_scrolled_window_new(NULL, NULL); + gtk_widget_set_size_request(scrolled, KEYWORD_DIALOG_WIDTH, KEYWORD_DIALOG_HEIGHT); + gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN); + gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled), + GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); + gtk_box_pack_start(GTK_BOX(keyword_dialog->gd->vbox), scrolled, TRUE, TRUE, 5); + gtk_widget_show(scrolled); + + store = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_BOOLEAN); + keyword_dialog->treeview = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store)); + g_object_unref(store); + + gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(keyword_dialog->treeview), FALSE); + gtk_tree_view_set_search_column(GTK_TREE_VIEW(keyword_dialog->treeview), 0); + gtk_tree_view_set_reorderable(GTK_TREE_VIEW(keyword_dialog->treeview), TRUE); + + column = gtk_tree_view_column_new(); + gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_AUTOSIZE); + renderer = gtk_cell_renderer_text_new(); + g_signal_connect(G_OBJECT(renderer), "edited", + G_CALLBACK(keyword_dialog_edit_cb), keyword_dialog); + gtk_tree_view_column_pack_start(column, renderer, TRUE); + gtk_tree_view_column_add_attribute(column, renderer, "text", 0); + gtk_tree_view_column_add_attribute(column, renderer, "editable", 1); + gtk_tree_view_append_column(GTK_TREE_VIEW(keyword_dialog->treeview), column); + + gtk_container_add(GTK_CONTAINER(scrolled), keyword_dialog->treeview); + gtk_widget_show(keyword_dialog->treeview); + + hbox = gtk_hbox_new(FALSE, 5); + gtk_box_pack_start(GTK_BOX(keyword_dialog->gd->vbox), hbox, FALSE, FALSE, 0); + gtk_widget_show(hbox); + + button = gtk_button_new_from_stock(GTK_STOCK_ADD); + g_signal_connect(G_OBJECT(button), "clicked", + G_CALLBACK(keyword_dialog_add_cb), keyword_dialog); + gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0); + gtk_widget_show(button); + + button = gtk_button_new_from_stock(GTK_STOCK_REMOVE); + g_signal_connect(G_OBJECT(button), "clicked", + G_CALLBACK(keyword_dialog_remove_cb), keyword_dialog); + gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0); + gtk_widget_show(button); + + keyword_dialog_populate(keyword_dialog); + + gtk_widget_show(keyword_dialog->gd->dialog); +} + + +static void bar_keyword_edit_cb(GtkWidget *button, gpointer data) +{ + keyword_dialog_show(); +} + + +/* + *------------------------------------------------------------------- + * info bar + *------------------------------------------------------------------- + */ + +enum { + KEYWORD_COLUMN_TOGGLE = 0, + KEYWORD_COLUMN_TEXT, + KEYWORD_COLUMN_MARK +}; + +typedef struct _PaneKeywordsData PaneKeywordsData; +struct _PaneKeywordsData +{ + PaneData pane; + GtkWidget *widget; + + GtkWidget *keyword_view; + GtkWidget *keyword_treeview; + + FileData *fd; + gchar *key; +}; + + +static GList *bar_list = NULL; + + +static void bar_pane_keywords_write(PaneKeywordsData *pkd) +{ + GList *list; + + if (!pkd->fd) return; + + list = keyword_list_pull(pkd->keyword_view); + + metadata_write_list(pkd->fd, KEYWORD_KEY, list); + + string_list_free(list); +} + +static gchar *bar_pane_keywords_get_mark_text(const gchar *key) +{ + gint i; + static gchar buf[10]; + + for (i = 0; i < FILEDATA_MARKS_SIZE; i++) + { + FileDataGetMarkFunc get_mark_func; + FileDataSetMarkFunc set_mark_func; + gpointer data; + file_data_get_registered_mark_func(i, &get_mark_func, &set_mark_func, &data); + if (get_mark_func == meta_data_get_keyword_mark && strcmp(data, key) == 0) + { + sprintf(buf, " %d ", i + 1); + return buf; + } + } + return " ... "; +} + +static void bar_keyword_list_sync(PaneKeywordsData *pkd, GList *keywords) +{ + GList *list; + GtkListStore *store; + GtkTreeIter iter; + + list = history_list_get_by_key("keywords"); + if (!list) + { + /* blank? set up a few example defaults */ + + gint i = 0; + + while (keyword_favorite_defaults[i] != NULL) + { + history_list_add_to_key("keywords", _(keyword_favorite_defaults[i]), 0); + i++; + } + + list = history_list_get_by_key("keywords"); + } + + store = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(pkd->keyword_treeview))); + + gtk_list_store_clear(store); + + list = g_list_last(list); + while (list) + { + gchar *key = list->data; + + gtk_list_store_append(store, &iter); + gtk_list_store_set(store, &iter, KEYWORD_COLUMN_TOGGLE, find_string_in_list(keywords, key), + KEYWORD_COLUMN_TEXT, key, + KEYWORD_COLUMN_MARK, bar_pane_keywords_get_mark_text(key), -1); + + list = list->prev; + } +} + +static void bar_pane_keywords_keyword_update_all(void) +{ + GList *work; + + work = bar_list; + while (work) + { + PaneKeywordsData *pkd; + GList *keywords; + + pkd = work->data; + work = work->next; + + keywords = keyword_list_pull(pkd->keyword_view); + bar_keyword_list_sync(pkd, keywords); + string_list_free(keywords); + } +} + +static void bar_pane_keywords_update(PaneKeywordsData *pkd) +{ + GList *keywords = NULL; + GtkTextBuffer *keyword_buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(pkd->keyword_view)); + + g_signal_handlers_block_by_func(keyword_buffer, bar_pane_keywords_changed, pkd); + + keywords = metadata_read_list(pkd->fd, KEYWORD_KEY, METADATA_PLAIN); + keyword_list_push(pkd->keyword_view, keywords); + bar_keyword_list_sync(pkd, keywords); + string_list_free(keywords); + + g_signal_handlers_unblock_by_func(keyword_buffer, bar_pane_keywords_changed, pkd); + +} + +void bar_pane_keywords_set_fd(GtkWidget *pane, FileData *fd) +{ + PaneKeywordsData *pkd; + + pkd = g_object_get_data(G_OBJECT(pane), "pane_data"); + if (!pkd) return; + + file_data_unref(pkd->fd); + pkd->fd = file_data_ref(fd); + + bar_pane_keywords_update(pkd); +} + +gint bar_pane_keywords_event(GtkWidget *bar, GdkEvent *event) +{ + PaneKeywordsData *pkd; + + pkd = g_object_get_data(G_OBJECT(bar), "pane_data"); + if (!pkd) return FALSE; + + if (GTK_WIDGET_HAS_FOCUS(pkd->keyword_view)) return gtk_widget_event(pkd->keyword_view, event); + + return FALSE; +} + +static void bar_pane_keywords_keyword_set(PaneKeywordsData *pkd, const gchar *keyword, gint active) +{ + GList *list; + gint found; + + if (!keyword) return; + + list = keyword_list_pull(pkd->keyword_view); + found = find_string_in_list(list, keyword); + + if (active != found) + { + if (found) + { + GList *work = list; + + while (work) + { + gchar *key = work->data; + work = work->next; + + if (key && keyword && strcmp(key, keyword) == 0) + { + list = g_list_remove(list, key); + g_free(key); + } + } + } + else + { + list = g_list_append(list, g_strdup(keyword)); + } + + keyword_list_push(pkd->keyword_view, list); + } + + string_list_free(list); +} + +static void bar_pane_keywords_keyword_toggle(GtkCellRendererToggle *toggle, const gchar *path, gpointer data) +{ + PaneKeywordsData *pkd = data; + GtkTreeModel *store; + GtkTreeIter iter; + GtkTreePath *tpath; + gchar *key = NULL; + gboolean active; + + store = gtk_tree_view_get_model(GTK_TREE_VIEW(pkd->keyword_treeview)); + + tpath = gtk_tree_path_new_from_string(path); + gtk_tree_model_get_iter(store, &iter, tpath); + gtk_tree_path_free(tpath); + + gtk_tree_model_get(store, &iter, KEYWORD_COLUMN_TOGGLE, &active, + KEYWORD_COLUMN_TEXT, &key, -1); + active = (!active); + gtk_list_store_set(GTK_LIST_STORE(store), &iter, KEYWORD_COLUMN_TOGGLE, active, -1); + + bar_pane_keywords_keyword_set(pkd, key, active); + g_free(key); +} + +static void bar_pane_keywords_set_selection(PaneKeywordsData *pkd, gboolean append) +{ + GList *keywords = NULL; + GList *list = NULL; + GList *work; + + if (!pkd->pane.list_func) return; + + keywords = keyword_list_pull(pkd->keyword_view); + + list = pkd->pane.list_func(pkd->pane.list_data); + work = list; + while (work) + { + FileData *fd = work->data; + work = work->next; + + if (append) + { + metadata_append_list(fd, KEYWORD_KEY, keywords); + } + else + { + metadata_write_list(fd, KEYWORD_KEY, keywords); + } + } + + filelist_free(list); + string_list_free(keywords); +} + +static void bar_pane_keywords_sel_add_cb(GtkWidget *button, gpointer data) +{ + PaneKeywordsData *pkd = data; + + bar_pane_keywords_set_selection(pkd, TRUE); +} + +static void bar_pane_keywords_sel_replace_cb(GtkWidget *button, gpointer data) +{ + PaneKeywordsData *pkd = data; + + bar_pane_keywords_set_selection(pkd, FALSE); +} + +static void bar_pane_keywords_populate_popup_cb(GtkTextView *textview, GtkMenu *menu, gpointer data) +{ + PaneKeywordsData *pkd = data; + + menu_item_add_divider(GTK_WIDGET(menu)); + menu_item_add_stock(GTK_WIDGET(menu), _("Add keywords to selected files"), GTK_STOCK_ADD, G_CALLBACK(bar_pane_keywords_sel_add_cb), data); + menu_item_add_stock(GTK_WIDGET(menu), _("Replace existing keywords in selected files"), GTK_STOCK_CONVERT, G_CALLBACK(bar_pane_keywords_sel_replace_cb), data); +} + + +static void bar_pane_keywords_notify_cb(FileData *fd, NotifyType type, gpointer data) +{ + PaneKeywordsData *pkd = data; + if (fd == pkd->fd) bar_pane_keywords_update(pkd); +} + +static void bar_pane_keywords_changed(GtkTextBuffer *buffer, gpointer data) +{ + PaneKeywordsData *pkd = data; + + file_data_unregister_notify_func(bar_pane_keywords_notify_cb, pkd); + bar_pane_keywords_write(pkd); + file_data_register_notify_func(bar_pane_keywords_notify_cb, pkd, NOTIFY_PRIORITY_LOW); +} + +static void bar_pane_keywords_mark_edited (GtkCellRendererText *cell, const gchar *path, const gchar *text, gpointer data) +{ + PaneKeywordsData *pkd = data; + GtkTreeModel *store; + GtkTreeIter iter; + GtkTreePath *tpath; + gchar *key = NULL; + gint i; + FileDataGetMarkFunc get_mark_func; + FileDataSetMarkFunc set_mark_func; + gpointer mark_func_data; + + file_data_unregister_notify_func(bar_pane_keywords_notify_cb, pkd); + + store = gtk_tree_view_get_model(GTK_TREE_VIEW(pkd->keyword_treeview)); + + tpath = gtk_tree_path_new_from_string(path); + gtk_tree_model_get_iter(store, &iter, tpath); + gtk_tree_path_free(tpath); + + gtk_tree_model_get(store, &iter, KEYWORD_COLUMN_TEXT, &key, -1); + + for (i = 0; i < FILEDATA_MARKS_SIZE; i++) + { + file_data_get_registered_mark_func(i, &get_mark_func, &set_mark_func, &mark_func_data); + if (get_mark_func == meta_data_get_keyword_mark && strcmp(mark_func_data, key) == 0) + { + g_free(mark_func_data); + file_data_register_mark_func(i, NULL, NULL, NULL); + } + } + + if (sscanf(text, " %d ", &i) &&i >=1 && i <= FILEDATA_MARKS_SIZE) + { + i--; + file_data_get_registered_mark_func(i, &get_mark_func, &set_mark_func, &mark_func_data); + if (get_mark_func == meta_data_get_keyword_mark && mark_func_data) g_free(mark_func_data); + file_data_register_mark_func(i, meta_data_get_keyword_mark, meta_data_set_keyword_mark, g_strdup(key)); + } + + g_free(key); + + file_data_register_notify_func(bar_pane_keywords_notify_cb, pkd, NOTIFY_PRIORITY_LOW); + bar_pane_keywords_update(pkd); +} + +void bar_pane_keywords_close(GtkWidget *bar) +{ + PaneKeywordsData *pkd; + + pkd = g_object_get_data(G_OBJECT(bar), "pane_data"); + if (!pkd) return; + + gtk_widget_destroy(pkd->widget); +} + +static void bar_pane_keywords_destroy(GtkWidget *widget, gpointer data) +{ + PaneKeywordsData *pkd = data; + + file_data_unregister_notify_func(bar_pane_keywords_notify_cb, pkd); + + file_data_unref(pkd->fd); + g_free(pkd->key); + + g_free(pkd); +} + +static GtkTreeModel *create_marks_list(void) +{ + GtkListStore *model; + GtkTreeIter iter; + gint i; + + /* create list store */ + model = gtk_list_store_new (1, G_TYPE_STRING); + for (i = 0; i < FILEDATA_MARKS_SIZE; i++) + { + char str[10]; + sprintf(str, " %d ", i + 1); + gtk_list_store_append (model, &iter); + gtk_list_store_set(model, &iter, 0, str, -1); + } + gtk_list_store_append (model, &iter); + gtk_list_store_set(model, &iter, 0, " ... ", -1); + return GTK_TREE_MODEL (model); +} + +GtkWidget *bar_pane_keywords_new(const gchar *title, const gchar *key) +{ + PaneKeywordsData *pkd; + GtkWidget *box; + GtkWidget *hbox; + GtkWidget *table; + GtkWidget *scrolled; + GtkTextBuffer *buffer; + GtkWidget *label; + GtkWidget *tbar; + GtkListStore *store; + GtkTreeViewColumn *column; + GtkCellRenderer *renderer; + + pkd = g_new0(PaneKeywordsData, 1); + + pkd->pane.pane_set_fd = bar_pane_keywords_set_fd; + pkd->pane.pane_event = bar_pane_keywords_event; + pkd->pane.title = g_strdup(title); + + pkd->key = g_strdup(key); + + + hbox = gtk_hbox_new(FALSE, PREF_PAD_GAP); + + pkd->widget = hbox; + g_object_set_data(G_OBJECT(pkd->widget), "pane_data", pkd); + g_signal_connect(G_OBJECT(pkd->widget), "destroy", + G_CALLBACK(bar_pane_keywords_destroy), pkd); + gtk_widget_show(hbox); + + scrolled = gtk_scrolled_window_new(NULL, NULL); + gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN); + gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled), + GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); + gtk_box_pack_start(GTK_BOX(hbox), scrolled, TRUE, TRUE, 0); + gtk_widget_show(scrolled); + + pkd->keyword_view = gtk_text_view_new(); + gtk_container_add(GTK_CONTAINER(scrolled), pkd->keyword_view); + g_signal_connect(G_OBJECT(pkd->keyword_view), "populate-popup", + G_CALLBACK(bar_pane_keywords_populate_popup_cb), pkd); + gtk_widget_show(pkd->keyword_view); + + buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(pkd->keyword_view)); + g_signal_connect(G_OBJECT(buffer), "changed", + G_CALLBACK(bar_pane_keywords_changed), pkd); + + scrolled = gtk_scrolled_window_new(NULL, NULL); + gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN); + gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled), + GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); + gtk_box_pack_start(GTK_BOX(hbox), scrolled, TRUE, TRUE, 0); + gtk_widget_show(scrolled); + + store = gtk_list_store_new(3, G_TYPE_BOOLEAN, G_TYPE_STRING, G_TYPE_STRING); + pkd->keyword_treeview = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store)); + g_object_unref(store); + + gtk_widget_set_size_request(pkd->keyword_treeview, -1, 400); + + gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(pkd->keyword_treeview), FALSE); + + gtk_tree_view_set_search_column(GTK_TREE_VIEW(pkd->keyword_treeview), KEYWORD_COLUMN_TEXT); + + column = gtk_tree_view_column_new(); + gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_AUTOSIZE); + + renderer = gtk_cell_renderer_toggle_new(); + gtk_tree_view_column_pack_start(column, renderer, FALSE); + gtk_tree_view_column_add_attribute(column, renderer, "active", KEYWORD_COLUMN_TOGGLE); + g_signal_connect(G_OBJECT(renderer), "toggled", + G_CALLBACK(bar_pane_keywords_keyword_toggle), pkd); + + renderer = gtk_cell_renderer_text_new(); + gtk_tree_view_column_pack_start(column, renderer, TRUE); + gtk_tree_view_column_add_attribute(column, renderer, "text", KEYWORD_COLUMN_TEXT); + + gtk_tree_view_append_column(GTK_TREE_VIEW(pkd->keyword_treeview), column); + + column = gtk_tree_view_column_new(); + gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_GROW_ONLY); + + renderer = gtk_cell_renderer_combo_new(); + g_object_set(G_OBJECT(renderer), "editable", (gboolean)TRUE, + "model", create_marks_list(), + "text-column", 0, + "has-entry", FALSE, + NULL); + + gtk_tree_view_column_pack_start(column, renderer, TRUE); + gtk_tree_view_column_add_attribute(column, renderer, "text", KEYWORD_COLUMN_MARK); + g_signal_connect (renderer, "edited", + G_CALLBACK (bar_pane_keywords_mark_edited), pkd); + gtk_tree_view_append_column(GTK_TREE_VIEW(pkd->keyword_treeview), column); + + + gtk_container_add(GTK_CONTAINER(scrolled), pkd->keyword_treeview); + gtk_widget_show(pkd->keyword_treeview); + + file_data_register_notify_func(bar_pane_keywords_notify_cb, pkd, NOTIFY_PRIORITY_LOW); + + return pkd->widget; +} +/* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */ diff -r 0c918f8b1f51 -r 50ae02a4a675 src/bar_keywords.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/bar_keywords.h Sat Feb 14 19:50:54 2009 +0000 @@ -0,0 +1,20 @@ +/* + * Geeqie + * (C) 2004 John Ellis + * Copyright (C) 2008 - 2009 The Geeqie Team + * + * Author: Vladimir Nadvornik + * + * 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_KEYWORDS_H +#define BAR_KEYWORDS_H + +GtkWidget *bar_pane_keywords_new(const gchar *title, const gchar *key); + +#endif +/* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */ diff -r 0c918f8b1f51 -r 50ae02a4a675 src/layout.c --- a/src/layout.c Mon Feb 09 09:02:04 2009 +0000 +++ b/src/layout.c Sat Feb 14 19:50:54 2009 +0000 @@ -1979,8 +1979,8 @@ lw->bar_exif_enabled = options->panels.exif.enabled; lw->bar_exif_advanced = FALSE; - lw->bar_info = NULL; - lw->bar_info_enabled = options->panels.info.enabled; + lw->bar = NULL; + lw->bar_enabled = options->panels.info.enabled; /* default layout */ @@ -1999,7 +1999,7 @@ lw->div_v = options->layout.main_window.vdivider_pos; lw->div_float = options->layout.float_window.vdivider_pos; lw->bar_exif_width = options->panels.exif.width; - lw->bar_info_width = options->panels.info.width; + lw->bar_width = options->panels.info.width; } else { @@ -2007,7 +2007,7 @@ lw->div_v = MAIN_WINDOW_DIV_VPOS; lw->div_float = MAIN_WINDOW_DIV_VPOS; lw->bar_exif_width = PANEL_DEFAULT_WIDTH; - lw->bar_info_width = PANEL_DEFAULT_WIDTH; + lw->bar_width = PANEL_DEFAULT_WIDTH; } /* window */ diff -r 0c918f8b1f51 -r 50ae02a4a675 src/layout_util.c --- a/src/layout_util.c Mon Feb 09 09:02:04 2009 +0000 +++ b/src/layout_util.c Sat Feb 14 19:50:54 2009 +0000 @@ -15,8 +15,8 @@ #include "layout_util.h" #include "bar_exif.h" -#include "bar_info.h" #include "bar_sort.h" +#include "bar.h" #include "cache_maint.h" #include "collect.h" #include "collect-dlg.h" @@ -104,8 +104,8 @@ { return TRUE; } - if (lw->bar_info && - bar_info_event(lw->bar_info, (GdkEvent *)event)) + if (lw->bar && + bar_event(lw->bar, (GdkEvent *)event)) { return TRUE; } @@ -677,14 +677,14 @@ layout_toolbar_toggle(lw); } -static void layout_menu_bar_info_cb(GtkToggleAction *action, gpointer data) +static void layout_menu_bar_cb(GtkToggleAction *action, gpointer data) { LayoutWindow *lw = data; layout_exit_fullscreen(lw); - if (lw->bar_info_enabled == gtk_toggle_action_get_active(action)) return; - layout_bar_info_toggle(lw); + if (lw->bar_enabled == gtk_toggle_action_get_active(action)) return; + layout_bar_toggle(lw); } static void layout_menu_bar_exif_cb(GtkToggleAction *action, gpointer data) @@ -1225,7 +1225,7 @@ { "ShowMarks", NULL, N_("Show _Marks"), "M", NULL, CB(layout_menu_marks_cb), FALSE }, { "FloatTools", NULL, N_("_Float file list"), "L", NULL, CB(layout_menu_float_cb), FALSE }, { "HideToolbar", NULL, N_("Hide tool_bar"), NULL, NULL, CB(layout_menu_toolbar_cb), FALSE }, - { "SBarKeywords", NULL, N_("_Keywords"), "K", NULL, CB(layout_menu_bar_info_cb), FALSE }, + { "SBar", NULL, N_("_Info"), "K", NULL, CB(layout_menu_bar_cb), FALSE }, { "SBarExif", NULL, N_("E_xif data"), "E", NULL, CB(layout_menu_bar_exif_cb), FALSE }, { "SBarSort", NULL, N_("Sort _manager"), "S", NULL, CB(layout_menu_bar_sort_cb), FALSE }, { "SlideShow", NULL, N_("Toggle _slideshow"),"S", NULL, CB(layout_menu_slideshow_cb), FALSE }, @@ -1383,7 +1383,7 @@ " " " " " " -" " +" " " " " " " " @@ -1878,8 +1878,8 @@ action = gtk_action_group_get_action(lw->action_group, "FloatTools"); gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), lw->tools_float); - action = gtk_action_group_get_action(lw->action_group, "SBarKeywords"); - gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), lw->bar_info_enabled); + action = gtk_action_group_get_action(lw->action_group, "SBar"); + gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), lw->bar_enabled); action = gtk_action_group_get_action(lw->action_group, "SBarExif"); gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), lw->bar_exif_enabled); @@ -1957,96 +1957,97 @@ *----------------------------------------------------------------------------- */ -static void layout_bar_info_destroyed(GtkWidget *widget, gpointer data) +static void layout_bar_destroyed(GtkWidget *widget, gpointer data) { LayoutWindow *lw = data; - lw->bar_info = NULL; + lw->bar = NULL; if (lw->utility_box) { /* destroyed from within itself */ - lw->bar_info_enabled = FALSE; + lw->bar_enabled = FALSE; layout_util_sync_views(lw); } } -static GList *layout_bar_info_list_cb(gpointer data) +static GList *layout_bar_list_cb(gpointer data) { LayoutWindow *lw = data; return layout_selection_list(lw); } -static void layout_bar_info_sized(GtkWidget *widget, GtkAllocation *allocation, gpointer data) +static void layout_bar_sized(GtkWidget *widget, GtkAllocation *allocation, gpointer data) { LayoutWindow *lw = data; - if (!lw->bar_info) return; + if (!lw->bar) return; - options->panels.info.width = lw->bar_info_width = allocation->width; + options->panels.info.width = lw->bar_width = allocation->width; } -static void layout_bar_info_new(LayoutWindow *lw) +static void layout_bar_new(LayoutWindow *lw) { if (!lw->utility_box) return; - lw->bar_info = bar_info_new(layout_image_get_fd(lw), FALSE, lw->utility_box); - bar_info_set_selection_func(lw->bar_info, layout_bar_info_list_cb, lw); - bar_info_selection(lw->bar_info, layout_selection_count(lw, NULL) - 1); - g_signal_connect(G_OBJECT(lw->bar_info), "destroy", - G_CALLBACK(layout_bar_info_destroyed), lw); - g_signal_connect(G_OBJECT(lw->bar_info), "size_allocate", - G_CALLBACK(layout_bar_info_sized), lw); + lw->bar = bar_new(lw->utility_box); + bar_set_selection_func(lw->bar, layout_bar_list_cb, lw); + g_signal_connect(G_OBJECT(lw->bar), "destroy", + G_CALLBACK(layout_bar_destroyed), lw); + g_signal_connect(G_OBJECT(lw->bar), "size_allocate", + G_CALLBACK(layout_bar_sized), lw); - options->panels.info.enabled = lw->bar_info_enabled = TRUE; - gtk_widget_set_size_request(lw->bar_info, lw->bar_info_width, -1); + options->panels.info.enabled = lw->bar_enabled = TRUE; + gtk_widget_set_size_request(lw->bar, lw->bar_width, -1); - gtk_box_pack_start(GTK_BOX(lw->utility_box), lw->bar_info, FALSE, FALSE, 0); - gtk_widget_show(lw->bar_info); + gtk_box_pack_start(GTK_BOX(lw->utility_box), lw->bar, FALSE, FALSE, 0); + + bar_set_fd(lw->bar, layout_image_get_fd(lw)); + gtk_widget_show(lw->bar); } -static void layout_bar_info_close(LayoutWindow *lw) +static void layout_bar_close(LayoutWindow *lw) { - if (lw->bar_info) + if (lw->bar) { - bar_info_close(lw->bar_info); - lw->bar_info = NULL; + bar_close(lw->bar); + lw->bar = NULL; } - options->panels.info.enabled = lw->bar_info_enabled = FALSE; + options->panels.info.enabled = lw->bar_enabled = FALSE; } -void layout_bar_info_toggle(LayoutWindow *lw) +void layout_bar_toggle(LayoutWindow *lw) { - if (lw->bar_info_enabled) + if (lw->bar_enabled) { - layout_bar_info_close(lw); + layout_bar_close(lw); } else { - layout_bar_info_new(lw); + layout_bar_new(lw); } } -static void layout_bar_info_new_image(LayoutWindow *lw) +static void layout_bar_new_image(LayoutWindow *lw) { - if (!lw->bar_info || !lw->bar_info_enabled) return; + if (!lw->bar || !lw->bar_enabled) return; - bar_info_set(lw->bar_info, layout_image_get_fd(lw)); + bar_set_fd(lw->bar, layout_image_get_fd(lw)); } -static void layout_bar_info_new_selection(LayoutWindow *lw, gint count) +static void layout_bar_new_selection(LayoutWindow *lw, gint count) { - if (!lw->bar_info || !lw->bar_info_enabled) return; + if (!lw->bar || !lw->bar_enabled) return; - bar_info_selection(lw->bar_info, count - 1); +// bar_info_selection(lw->bar_info, count - 1); } -static void layout_bar_info_maint_renamed(LayoutWindow *lw) +static void layout_bar_maint_renamed(LayoutWindow *lw) { - if (!lw->bar_info || !lw->bar_info_enabled) return; + if (!lw->bar || !lw->bar_enabled) return; - bar_info_maint_renamed(lw->bar_info, layout_image_get_fd(lw)); +// bar_maint_renamed(lw->bar_info, layout_image_get_fd(lw)); } static void layout_bar_exif_destroyed(GtkWidget *widget, gpointer data) @@ -2091,7 +2092,7 @@ gtk_widget_set_size_request(lw->bar_exif, lw->bar_exif_width, -1); gtk_box_pack_start(GTK_BOX(lw->utility_box), lw->bar_exif, FALSE, FALSE, 0); - if (lw->bar_info) gtk_box_reorder_child(GTK_BOX(lw->utility_box), lw->bar_exif, 1); + if (lw->bar) gtk_box_reorder_child(GTK_BOX(lw->utility_box), lw->bar_exif, 1); gtk_widget_show(lw->bar_exif); } @@ -2176,7 +2177,7 @@ void layout_bars_new_image(LayoutWindow *lw) { - layout_bar_info_new_image(lw); + layout_bar_new_image(lw); layout_bar_exif_new_image(lw); /* this should be called here to handle the metadata edited in bars */ @@ -2186,7 +2187,7 @@ void layout_bars_new_selection(LayoutWindow *lw, gint count) { - layout_bar_info_new_selection(lw, count); + layout_bar_new_selection(lw, count); } GtkWidget *layout_bars_prepare(LayoutWindow *lw, GtkWidget *image) @@ -2200,9 +2201,9 @@ layout_bar_sort_new(lw); } - if (lw->bar_info_enabled) + if (lw->bar_enabled) { - layout_bar_info_new(lw); + layout_bar_new(lw); } if (lw->bar_exif_enabled) @@ -2217,11 +2218,11 @@ { layout_bar_sort_close(lw); layout_bar_exif_close(lw); - layout_bar_info_close(lw); + layout_bar_close(lw); } void layout_bars_maint_renamed(LayoutWindow *lw) { - layout_bar_info_maint_renamed(lw); + layout_bar_maint_renamed(lw); } /* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */ diff -r 0c918f8b1f51 -r 50ae02a4a675 src/layout_util.h --- a/src/layout_util.h Mon Feb 09 09:02:04 2009 +0000 +++ b/src/layout_util.h Sat Feb 14 19:50:54 2009 +0000 @@ -44,7 +44,7 @@ void folder_icons_free(PixmapFolders *pf); -void layout_bar_info_toggle(LayoutWindow *lw); +void layout_bar_toggle(LayoutWindow *lw); void layout_bar_exif_toggle(LayoutWindow *lw); void layout_bar_sort_toggle(LayoutWindow *lw); diff -r 0c918f8b1f51 -r 50ae02a4a675 src/remote.c --- a/src/remote.c Mon Feb 09 09:02:04 2009 +0000 +++ b/src/remote.c Sat Feb 14 19:50:54 2009 +0000 @@ -235,6 +235,8 @@ rc->clients = NULL; channel = g_io_channel_unix_new(rc->fd); + g_io_channel_set_flags(channel, G_IO_FLAG_NONBLOCK, NULL); + rc->channel_id = g_io_add_watch_full(channel, G_PRIORITY_DEFAULT, G_IO_IN, remote_server_read_cb, rc, NULL); g_io_channel_unref(channel); diff -r 0c918f8b1f51 -r 50ae02a4a675 src/typedefs.h --- a/src/typedefs.h Mon Feb 09 09:02:04 2009 +0000 +++ b/src/typedefs.h Sat Feb 14 19:50:54 2009 +0000 @@ -568,15 +568,15 @@ GtkWidget *utility_box; GtkWidget *bar_sort; GtkWidget *bar_exif; - GtkWidget *bar_info; + GtkWidget *bar; gint bar_sort_enabled; gint bar_exif_enabled; - gint bar_info_enabled; + gint bar_enabled; gint bar_exif_width; gint bar_exif_advanced; - gint bar_info_width; + gint bar_width; }; struct _ViewDir diff -r 0c918f8b1f51 -r 50ae02a4a675 src/ui_misc.c --- a/src/ui_misc.c Mon Feb 09 09:02:04 2009 +0000 +++ b/src/ui_misc.c Sat Feb 14 19:50:54 2009 +0000 @@ -1678,4 +1678,34 @@ return button; } + +/* + *----------------------------------------------------------------------------- + * text widget + *----------------------------------------------------------------------------- + */ + +gchar *text_widget_text_pull(GtkWidget *text_widget) +{ + if (GTK_IS_TEXT_VIEW(text_widget)) + { + GtkTextBuffer *buffer; + GtkTextIter start, end; + + buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_widget)); + gtk_text_buffer_get_bounds(buffer, &start, &end); + + return gtk_text_buffer_get_text(buffer, &start, &end, FALSE); + } + else if (GTK_IS_ENTRY(text_widget)) + { + return g_strdup(gtk_entry_get_text(GTK_ENTRY(text_widget))); + } + else + { + return NULL; + } + +} + /* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */ diff -r 0c918f8b1f51 -r 50ae02a4a675 src/ui_misc.h --- a/src/ui_misc.h Mon Feb 09 09:02:04 2009 +0000 +++ b/src/ui_misc.h Sat Feb 14 19:50:54 2009 +0000 @@ -185,6 +185,7 @@ const gchar *title, const GdkColor *color, GCallback func, gpointer data); +gchar *text_widget_text_pull(GtkWidget *text_widget); #endif /* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */ diff -r 0c918f8b1f51 -r 50ae02a4a675 src/view_file_icon.c --- a/src/view_file_icon.c Mon Feb 09 09:02:04 2009 +0000 +++ b/src/view_file_icon.c Sat Feb 14 19:50:54 2009 +0000 @@ -14,6 +14,7 @@ #include "view_file_icon.h" #include "bar_info.h" +#include "bar.h" #include "cellrenderericon.h" #include "collect.h" #include "collect-io.h" @@ -571,9 +572,12 @@ metadata_append_list(fd, KEYWORD_KEY, kw_list); string_list_free(kw_list); g_free(str); +/* +file notification should handle this automatically if (vf->layout && vf->layout->bar_info) { - bar_info_set(vf->layout->bar_info, id->fd); + bar_set_fd(vf->layout->bar_info, id->fd); } +*/ } } } diff -r 0c918f8b1f51 -r 50ae02a4a675 src/view_file_list.c --- a/src/view_file_list.c Mon Feb 09 09:02:04 2009 +0000 +++ b/src/view_file_list.c Sat Feb 14 19:50:54 2009 +0000 @@ -14,6 +14,7 @@ #include "view_file_list.h" #include "bar_info.h" +#include "bar.h" #include "cache_maint.h" #include "dnd.h" #include "editors.h" @@ -326,9 +327,12 @@ metadata_append_list(fd, KEYWORD_KEY, kw_list); string_list_free(kw_list); g_free(str); +/* +file notification should handle this automatically if (vf->layout && vf->layout->bar_info) { - bar_info_set(vf->layout->bar_info, fd); + bar_set_fd(vf->layout->bar_info, fd); } +*/ } } }