File filter - include Clear icon
[geeqie.git] / src / view_file / view_file.c
index ed5c5f0..46d823d 100644 (file)
@@ -28,6 +28,7 @@
 #include "history_list.h"
 #include "layout.h"
 #include "menu.h"
+#include "misc.h"
 #include "pixbuf_util.h"
 #include "thumb.h"
 #include "ui_menu.h"
@@ -77,11 +78,16 @@ FileData *vf_index_get_data(ViewFile *vf, gint row)
 
 gint vf_index_by_fd(ViewFile *vf, FileData *fd)
 {
+       gint ret;
+
        switch (vf->type)
        {
-       case FILEVIEW_LIST: return vflist_index_by_fd(vf, fd);
-       case FILEVIEW_ICON: return vficon_index_by_fd(vf, fd);
+       case FILEVIEW_LIST: ret = vflist_index_by_fd(vf, fd); break;
+       case FILEVIEW_ICON: ret = vficon_index_by_fd(vf, fd); break;
+       default: ret = 0;
        }
+
+       return ret;
 }
 
 guint vf_count(ViewFile *vf, gint64 *bytes)
@@ -128,12 +134,16 @@ GList *vf_get_list(ViewFile *vf)
 static gboolean vf_press_key_cb(GtkWidget *widget, GdkEventKey *event, gpointer data)
 {
        ViewFile *vf = data;
+       gboolean ret;
 
        switch (vf->type)
        {
-       case FILEVIEW_LIST: return vflist_press_key_cb(widget, event, data);
-       case FILEVIEW_ICON: return vficon_press_key_cb(widget, event, data);
+       case FILEVIEW_LIST: ret = vflist_press_key_cb(widget, event, data); break;
+       case FILEVIEW_ICON: ret = vficon_press_key_cb(widget, event, data); break;
+       default: ret = FALSE;
        }
+
+       return ret;
 }
 
 /*
@@ -145,23 +155,31 @@ static gboolean vf_press_key_cb(GtkWidget *widget, GdkEventKey *event, gpointer
 static gboolean vf_press_cb(GtkWidget *widget, GdkEventButton *bevent, gpointer data)
 {
        ViewFile *vf = data;
+       gboolean ret;
 
        switch (vf->type)
        {
-       case FILEVIEW_LIST: return vflist_press_cb(widget, bevent, data);
-       case FILEVIEW_ICON: return vficon_press_cb(widget, bevent, data);
+       case FILEVIEW_LIST: ret = vflist_press_cb(widget, bevent, data); break;
+       case FILEVIEW_ICON: ret = vficon_press_cb(widget, bevent, data); break;
+       default: ret = FALSE;
        }
+
+       return ret;
 }
 
 static gboolean vf_release_cb(GtkWidget *widget, GdkEventButton *bevent, gpointer data)
 {
        ViewFile *vf = data;
+       gboolean ret;
 
        switch (vf->type)
        {
-       case FILEVIEW_LIST: return vflist_release_cb(widget, bevent, data);
-       case FILEVIEW_ICON: return vficon_release_cb(widget, bevent, data);
+       case FILEVIEW_LIST: ret = vflist_release_cb(widget, bevent, data); break;
+       case FILEVIEW_ICON: ret = vficon_release_cb(widget, bevent, data); break;
+       default: ret = FALSE;
        }
+
+       return ret;
 }
 
 
@@ -173,29 +191,44 @@ static gboolean vf_release_cb(GtkWidget *widget, GdkEventButton *bevent, gpointe
 
 guint vf_selection_count(ViewFile *vf, gint64 *bytes)
 {
+       guint ret;
+
        switch (vf->type)
        {
-       case FILEVIEW_LIST: return vflist_selection_count(vf, bytes);
-       case FILEVIEW_ICON: return vficon_selection_count(vf, bytes);
+       case FILEVIEW_LIST: ret = vflist_selection_count(vf, bytes); break;
+       case FILEVIEW_ICON: ret = vficon_selection_count(vf, bytes); break;
+       default: ret = 0;
        }
+
+       return ret;
 }
 
 GList *vf_selection_get_list(ViewFile *vf)
 {
+       GList *ret;
+
        switch (vf->type)
        {
-       case FILEVIEW_LIST: return vflist_selection_get_list(vf);
-       case FILEVIEW_ICON: return vficon_selection_get_list(vf);
+       case FILEVIEW_LIST: ret = vflist_selection_get_list(vf); break;
+       case FILEVIEW_ICON: ret = vficon_selection_get_list(vf); break;
+       default: ret = NULL;
        }
+
+       return ret;
 }
 
 GList *vf_selection_get_list_by_index(ViewFile *vf)
 {
+       GList *ret;
+
        switch (vf->type)
        {
-       case FILEVIEW_LIST: return vflist_selection_get_list_by_index(vf);
-       case FILEVIEW_ICON: return vficon_selection_get_list_by_index(vf);
+       case FILEVIEW_LIST: ret = vflist_selection_get_list_by_index(vf); break;
+       case FILEVIEW_ICON: ret = vficon_selection_get_list_by_index(vf); break;
+       default: ret = NULL;
        }
+
+       return ret;
 }
 
 void vf_select_all(ViewFile *vf)
@@ -234,6 +267,15 @@ void vf_select_by_fd(ViewFile *vf, FileData *fd)
        }
 }
 
+void vf_select_list(ViewFile *vf, GList *list)
+{
+       switch (vf->type)
+       {
+       case FILEVIEW_LIST: vflist_select_list(vf, list); break;
+       case FILEVIEW_ICON: vficon_select_list(vf, list); break;
+       }
+}
+
 void vf_mark_to_selection(ViewFile *vf, gint mark, MarkToSelectionMode mode)
 {
        switch (vf->type)
@@ -276,20 +318,30 @@ static void vf_dnd_init(ViewFile *vf)
 
 GList *vf_pop_menu_file_list(ViewFile *vf)
 {
+       GList *ret;
+
        switch (vf->type)
        {
-       case FILEVIEW_LIST: return vflist_pop_menu_file_list(vf);
-       case FILEVIEW_ICON: return vficon_pop_menu_file_list(vf);
+       case FILEVIEW_LIST: ret = vflist_pop_menu_file_list(vf); break;
+       case FILEVIEW_ICON: ret = vficon_pop_menu_file_list(vf); break;
+       default: ret = NULL;
        }
+
+       return ret;
 }
 
 GList *vf_selection_get_one(ViewFile *vf, FileData *fd)
 {
+       GList *ret;
+
        switch (vf->type)
        {
-       case FILEVIEW_LIST: return vflist_selection_get_one(vf, fd);
-       case FILEVIEW_ICON: return vficon_selection_get_one(vf, fd);
+       case FILEVIEW_LIST: ret = vflist_selection_get_one(vf, fd); break;
+       case FILEVIEW_ICON: ret = vficon_selection_get_one(vf, fd); break;
+       default: ret = NULL;
        }
+
+       return ret;
 }
 
 static void vf_pop_menu_edit_cb(GtkWidget *widget, gpointer data)
@@ -315,6 +367,36 @@ static void vf_pop_menu_view_cb(GtkWidget *widget, gpointer data)
        }
 }
 
+static void vf_pop_menu_open_archive_cb(GtkWidget *widget, gpointer data)
+{
+       ViewFile *vf = data;
+       LayoutWindow *lw_new;
+       FileData *fd;
+       gchar *dest_dir;
+
+       switch (vf->type)
+       {
+       case FILEVIEW_LIST:
+               fd = (VFLIST(vf)->click_fd);
+               break;
+       case FILEVIEW_ICON:
+               fd = (VFICON(vf)->click_fd);
+               break;
+       }
+
+       dest_dir = open_archive(fd);
+       if (dest_dir)
+               {
+               lw_new = layout_new_from_default();
+               layout_set_path(lw_new, dest_dir);
+               g_free(dest_dir);
+               }
+       else
+               {
+               warning_dialog(_("Cannot open archive file"), _("See the Log Window"), GTK_STOCK_DIALOG_WARNING, NULL);
+               }
+}
+
 static void vf_pop_menu_copy_cb(GtkWidget *widget, gpointer data)
 {
        ViewFile *vf = data;
@@ -485,23 +567,6 @@ static void vf_pop_menu_toggle_view_type_cb(GtkWidget *widget, gpointer data)
        layout_views_set(vf->layout, vf->layout->options.dir_view_type, new_type);
 }
 
-static void vf_pop_menu_toggle_star_rating(ViewFile *vf)
-{
-       GtkAllocation allocation;
-
-       options->show_star_rating = !options->show_star_rating;
-
-       gtk_widget_get_allocation(vf->listview, &allocation);
-       vf_star_rating_set(vf, options->show_star_rating);
-}
-
-static void vf_pop_menu_show_star_rating_cb(GtkWidget *widget, gpointer data)
-{
-       ViewFile *vf = data;
-
-       vf_pop_menu_toggle_star_rating(vf);
-}
-
 static void vf_pop_menu_refresh_cb(GtkWidget *widget, gpointer data)
 {
        ViewFile *vf = data;
@@ -552,20 +617,30 @@ GtkWidget *vf_pop_menu(ViewFile *vf)
        GtkWidget *item;
        GtkWidget *submenu;
        gboolean active = FALSE;
+       gboolean class_archive = FALSE;
+       GtkAccelGroup *accel_group;
 
        switch (vf->type)
        {
        case FILEVIEW_LIST:
                vflist_color_set(vf, VFLIST(vf)->click_fd, TRUE);
                active = (VFLIST(vf)->click_fd != NULL);
+               class_archive = (VFLIST(vf)->click_fd != NULL && VFLIST(vf)->click_fd->format_class == FORMAT_CLASS_ARCHIVE);
                break;
        case FILEVIEW_ICON:
                active = (VFICON(vf)->click_fd != NULL);
+               class_archive = (VFICON(vf)->click_fd != NULL && VFICON(vf)->click_fd->format_class == FORMAT_CLASS_ARCHIVE);
                break;
        }
 
        menu = popup_menu_short_lived();
 
+       accel_group = gtk_accel_group_new();
+       gtk_menu_set_accel_group(GTK_MENU(menu), accel_group);
+
+       g_object_set_data(G_OBJECT(menu), "window_keys", NULL);
+       g_object_set_data(G_OBJECT(menu), "accel_group", accel_group);
+
        g_signal_connect(G_OBJECT(menu), "destroy",
                         G_CALLBACK(vf_popup_destroy_cb), vf);
 
@@ -623,6 +698,8 @@ GtkWidget *vf_pop_menu(ViewFile *vf)
        menu_item_add_stock_sensitive(menu, _("View in _new window"), GTK_STOCK_NEW, active,
                                      G_CALLBACK(vf_pop_menu_view_cb), vf);
 
+       menu_item_add_stock_sensitive(menu, _("Open archive"), GTK_STOCK_OPEN, active & class_archive, G_CALLBACK(vf_pop_menu_open_archive_cb), vf);
+
        menu_item_add_divider(menu);
        menu_item_add_stock_sensitive(menu, _("_Copy..."), GTK_STOCK_COPY, active,
                                      G_CALLBACK(vf_pop_menu_copy_cb), vf);
@@ -630,9 +707,9 @@ GtkWidget *vf_pop_menu(ViewFile *vf)
                                G_CALLBACK(vf_pop_menu_move_cb), vf);
        menu_item_add_sensitive(menu, _("_Rename..."), active,
                                G_CALLBACK(vf_pop_menu_rename_cb), vf);
-       menu_item_add_sensitive(menu, _("_Copy path"), active,
+       menu_item_add_sensitive(menu, _("_Copy path to clipboard"), active,
                                G_CALLBACK(vf_pop_menu_copy_path_cb), vf);
-       menu_item_add_sensitive(menu, _("_Copy path unquoted"), active,
+       menu_item_add_sensitive(menu, _("_Copy path unquoted to clipboard"), active,
                                G_CALLBACK(vf_pop_menu_copy_path_unquoted_cb), vf);
        menu_item_add_divider(menu);
        menu_item_add_stock_sensitive(menu,
@@ -669,10 +746,10 @@ GtkWidget *vf_pop_menu(ViewFile *vf)
        item = menu_item_add(menu, _("_Sort"), NULL, NULL);
        gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), submenu);
 
-       item = menu_item_add_radio(menu, _("View as _List"), GINT_TO_POINTER(FILEVIEW_LIST), vf->type == FILEVIEW_LIST,
+       item = menu_item_add_radio(menu, _("Images as List"), GINT_TO_POINTER(FILEVIEW_LIST), vf->type == FILEVIEW_LIST,
                                            G_CALLBACK(vf_pop_menu_toggle_view_type_cb), vf);
 
-       item = menu_item_add_radio(menu, _("View as _Icons"), GINT_TO_POINTER(FILEVIEW_ICON), vf->type == FILEVIEW_ICON,
+       item = menu_item_add_radio(menu, _("Images as Icons"), GINT_TO_POINTER(FILEVIEW_ICON), vf->type == FILEVIEW_ICON,
                                            G_CALLBACK(vf_pop_menu_toggle_view_type_cb), vf);
 
        switch (vf->type)
@@ -706,20 +783,30 @@ GtkWidget *vf_pop_menu(ViewFile *vf)
 
 gboolean vf_refresh(ViewFile *vf)
 {
+       gboolean ret;
+
        switch (vf->type)
        {
-       case FILEVIEW_LIST: return vflist_refresh(vf);
-       case FILEVIEW_ICON: return vficon_refresh(vf);
+       case FILEVIEW_LIST: ret = vflist_refresh(vf); break;
+       case FILEVIEW_ICON: ret = vficon_refresh(vf); break;
+       default: ret = FALSE;
        }
+
+       return ret;
 }
 
 gboolean vf_set_fd(ViewFile *vf, FileData *dir_fd)
 {
+       gboolean ret;
+
        switch (vf->type)
        {
-       case FILEVIEW_LIST: return vflist_set_fd(vf, dir_fd);
-       case FILEVIEW_ICON: return vficon_set_fd(vf, dir_fd);
+       case FILEVIEW_LIST: ret = vflist_set_fd(vf, dir_fd); break;
+       case FILEVIEW_ICON: ret = vficon_set_fd(vf, dir_fd); break;
+       default: ret = FALSE;
        }
+
+       return ret;
 }
 
 static void vf_destroy_cb(GtkWidget *widget, gpointer data)
@@ -1068,6 +1155,15 @@ static void case_sensitive_cb(GtkWidget *widget, gpointer data)
        vf_refresh(vf);
 }
 
+static void file_filter_clear_cb(GtkEntry *entry, GtkEntryIconPosition pos, GdkEvent *event, gpointer userdata)
+{
+       if (pos == GTK_ENTRY_ICON_SECONDARY)
+               {
+               gtk_entry_set_text(GTK_ENTRY(userdata), "");
+               gtk_widget_grab_focus(GTK_WIDGET(userdata));
+               }
+}
+
 static GtkWidget *vf_file_filter_init(ViewFile *vf)
 {
        GtkWidget *frame = gtk_frame_new(NULL);
@@ -1078,12 +1174,19 @@ static GtkWidget *vf_file_filter_init(ViewFile *vf)
        GtkWidget *menubar;
        GtkWidget *menuitem;
        GtkWidget *case_sensitive;
+       GtkWidget *box;
+       GtkWidget *icon;
+       GtkWidget *label;
 
        vf->file_filter.combo = gtk_combo_box_text_new_with_entry();
        combo_entry = gtk_bin_get_child(GTK_BIN(vf->file_filter.combo));
        gtk_widget_show(gtk_bin_get_child(GTK_BIN(vf->file_filter.combo)));
        gtk_widget_show((GTK_WIDGET(vf->file_filter.combo)));
-       gtk_widget_set_tooltip_text(GTK_WIDGET(vf->file_filter.combo), "Use regular expressions");
+       gtk_widget_set_tooltip_text(GTK_WIDGET(vf->file_filter.combo), _("Use regular expressions"));
+
+       gtk_entry_set_icon_from_stock(GTK_ENTRY(combo_entry), GTK_ENTRY_ICON_SECONDARY, GTK_STOCK_CLEAR);
+       gtk_entry_set_icon_tooltip_text (GTK_ENTRY(combo_entry), GTK_ENTRY_ICON_SECONDARY, _("Clear"));
+       g_signal_connect(GTK_ENTRY(combo_entry), "icon-press", G_CALLBACK(file_filter_clear_cb), combo_entry);
 
        work = history_list_get_by_key("file_filter");
        while (work)
@@ -1109,7 +1212,7 @@ static GtkWidget *vf_file_filter_init(ViewFile *vf)
        gtk_container_add(GTK_CONTAINER(frame), hbox);
        gtk_widget_show(hbox);
 
-       case_sensitive = gtk_check_button_new_with_label("Case");
+       case_sensitive = gtk_check_button_new_with_label(_("Case"));
        gtk_box_pack_start(GTK_BOX(hbox), case_sensitive, FALSE, FALSE, 0);
        gtk_widget_set_tooltip_text(GTK_WIDGET(case_sensitive), _("Case sensitive"));
        g_signal_connect(G_OBJECT(case_sensitive), "clicked", G_CALLBACK(case_sensitive_cb), vf);
@@ -1119,13 +1222,20 @@ static GtkWidget *vf_file_filter_init(ViewFile *vf)
        gtk_box_pack_start(GTK_BOX(hbox), menubar, FALSE, TRUE, 0);
        gtk_widget_show(menubar);
 
-       menuitem = gtk_menu_item_new_with_label(_("Class"));
-       gtk_widget_set_tooltip_text(GTK_WIDGET(menuitem), _("Select Class filter"));
-       gtk_menu_item_set_submenu(GTK_MENU_ITEM (menuitem), class_filter_menu(vf));
-       gtk_menu_shell_append(GTK_MENU_SHELL (menubar), menuitem);
-       gtk_widget_show(menuitem);
+       box = gtk_hbox_new(GTK_ORIENTATION_HORIZONTAL, PREF_PAD_GAP);
+       icon = gtk_image_new_from_icon_name("pan-down", GTK_ICON_SIZE_MENU);
+       label = gtk_label_new(_("Class"));
 
-       gtk_widget_show(menuitem);
+       gtk_box_pack_start(GTK_BOX(box), label, FALSE, FALSE, 0);
+       gtk_box_pack_end(GTK_BOX(box), icon, FALSE, FALSE, 0);
+
+       menuitem = gtk_menu_item_new();
+
+       gtk_widget_set_tooltip_text(GTK_WIDGET(menuitem), _("Select Class filter"));
+       gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuitem), class_filter_menu(vf));
+       gtk_menu_shell_append(GTK_MENU_SHELL(menubar), menuitem);
+       gtk_container_add(GTK_CONTAINER(menuitem), box);
+       gtk_widget_show_all(menuitem);
 
        return frame;
 }
@@ -1384,6 +1494,97 @@ void vf_thumb_update(ViewFile *vf)
        while (vf_thumb_next(vf));
 }
 
+void vf_star_cleanup(ViewFile *vf)
+{
+       if (vf->stars_id != 0)
+               {
+               g_source_remove(vf->stars_id);
+               }
+
+       vf->stars_id = 0;
+       vf->stars_filedata = NULL;
+}
+
+void vf_star_stop(ViewFile *vf)
+{
+        vf_star_cleanup(vf);
+}
+
+static void vf_set_star_fd(ViewFile *vf, FileData *fd)
+{
+       switch (vf->type)
+               {
+               case FILEVIEW_LIST: vflist_set_star_fd(vf, fd); break;
+               case FILEVIEW_ICON: vficon_set_star_fd(vf, fd); break;
+               default: break;
+               }
+}
+
+static void vf_star_do(ViewFile *vf, FileData *fd)
+{
+       if (!fd) return;
+
+       vf_set_star_fd(vf, fd);
+}
+
+static gboolean vf_star_next(ViewFile *vf)
+{
+       FileData *fd = NULL;
+
+       switch (vf->type)
+               {
+               case FILEVIEW_LIST: fd = vflist_star_next_fd(vf); break;
+               case FILEVIEW_ICON: fd = vficon_star_next_fd(vf); break;
+               default: break;
+               }
+
+       if (!fd)
+               {
+               /* done */
+               vf_star_cleanup(vf);
+               return FALSE;
+               }
+
+       return TRUE;
+}
+
+gboolean vf_stars_cb(gpointer data)
+{
+       ViewFile *vf = data;
+       FileData *fd = vf->stars_filedata;
+
+       if (fd)
+               {
+               read_rating_data(fd);
+
+               vf_star_do(vf, fd);
+
+               if (vf_star_next(vf))
+                       {
+                       return TRUE;
+                       }
+               else
+                       {
+                       vf->stars_filedata = NULL;
+                       vf->stars_id = 0;
+                       return FALSE;
+                       }
+               }
+
+       return FALSE;
+}
+
+void vf_star_update(ViewFile *vf)
+{
+       vf_star_stop(vf);
+
+       if (!options->show_star_rating)
+               {
+               return;
+               }
+
+       vf_star_next(vf);
+}
 
 void vf_marks_set(ViewFile *vf, gboolean enable)
 {
@@ -1542,7 +1743,7 @@ void vf_notify_cb(FileData *fd, NotifyType type, gpointer data)
 
        NotifyType interested = NOTIFY_CHANGE | NOTIFY_REREAD | NOTIFY_GROUPING;
        if (vf->marks_enabled) interested |= NOTIFY_MARKS | NOTIFY_METADATA;
-       /* FIXME: NOTIFY_METADATA should be checked by the keyword-to-mark functions and converted to NOTIFY_MARKS only if there was a change */
+       /** @FIXME NOTIFY_METADATA should be checked by the keyword-to-mark functions and converted to NOTIFY_MARKS only if there was a change */
 
        if (!(type & interested) || vf->refresh_idle_id || !vf->dir_fd) return;
 
@@ -1583,7 +1784,6 @@ static gboolean vf_read_metadata_in_idle_cb(gpointer data)
 {
        FileData *fd;
        ViewFile *vf = data;
-       GList *list_entry;
        GList *work;
 
        vf_thumb_status(vf, vf_read_metadata_in_idle_progress(vf), _("Loading meta..."));
@@ -1630,9 +1830,6 @@ static void vf_read_metadata_in_idle_finished_cb(gpointer data)
 
 void vf_read_metadata_in_idle(ViewFile *vf)
 {
-       GList *work;
-       FileData *fd;
-
        if (!vf) return;
 
        if (vf->read_metadata_in_idle_id)