forked from AuroraMiddleware/gtk
File filter objects.
Wed Jul 23 11:23:43 2003 Owen Taylor <otaylor@redhat.com> * gtkfilefilter.[ch]: File filter objects. * gtkfilechooser.[ch] gtkfilechooserutils.[ch]: Add file filtering to API. * gtkfilechooserimpldefault.c: Implement file filters. * testfilechooser.c: Try out the filter functionality. * gtkfilesystemmodel.c: Add _gtk_file_system_model_set_filter() to set a callback function for filtering. * gtkfilechooserutils.c: Propagate property notification to the receiver. * fnmatch.c: Copy this from GTK+ temporarily to get UTF-8 pattern matching functionality.
This commit is contained in:
parent
96ba7bb65e
commit
733f4489ad
@ -91,6 +91,12 @@ gtk_file_chooser_base_init (gpointer g_iface)
|
||||
_("File system object to use"),
|
||||
GTK_TYPE_FILE_SYSTEM,
|
||||
G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
|
||||
g_object_interface_install_property (g_iface,
|
||||
g_param_spec_object ("filter",
|
||||
_("Filter"),
|
||||
_("The current filter for selecting which files are displayed"),
|
||||
GTK_TYPE_FILE_FILTER,
|
||||
G_PARAM_READWRITE));
|
||||
g_object_interface_install_property (g_iface,
|
||||
g_param_spec_boolean ("folder-mode",
|
||||
_("Folder Mode"),
|
||||
@ -932,6 +938,13 @@ gtk_file_chooser_get_preview_widget (GtkFileChooser *chooser)
|
||||
g_return_val_if_fail (GTK_IS_FILE_CHOOSER (chooser), NULL);
|
||||
|
||||
g_object_get (chooser, "preview-widget", &preview_widget, NULL);
|
||||
|
||||
/* Horrid hack; g_object_get() refs returned objects but
|
||||
* that contradicts the memory management conventions
|
||||
* for accessors.
|
||||
*/
|
||||
if (preview_widget)
|
||||
g_object_unref (preview_widget);
|
||||
|
||||
return preview_widget;
|
||||
}
|
||||
@ -1046,3 +1059,107 @@ gtk_file_chooser_get_preview_uri (GtkFileChooser *chooser)
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_file_chooser_add_filter:
|
||||
* @chooser: a #GtkFileChooser
|
||||
* @filter: a #GtkFileFilter
|
||||
*
|
||||
* Adds @filter to the list of filters that the user can select between.
|
||||
* When a filter is selected, only files that are passed by that
|
||||
* filter are displayed.
|
||||
**/
|
||||
void
|
||||
gtk_file_chooser_add_filter (GtkFileChooser *chooser,
|
||||
GtkFileFilter *filter)
|
||||
{
|
||||
g_return_if_fail (GTK_IS_FILE_CHOOSER (chooser));
|
||||
|
||||
GTK_FILE_CHOOSER_GET_IFACE (chooser)->add_filter (chooser, filter);
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_file_chooser_add_filter:
|
||||
* @chooser: a #GtkFileChooser
|
||||
* @filter: a #GtkFileFilter
|
||||
*
|
||||
* Removes @filter from the list of filters that the user can select between.
|
||||
**/
|
||||
void
|
||||
gtk_file_chooser_remove_filter (GtkFileChooser *chooser,
|
||||
GtkFileFilter *filter)
|
||||
{
|
||||
g_return_if_fail (GTK_IS_FILE_CHOOSER (chooser));
|
||||
|
||||
GTK_FILE_CHOOSER_GET_IFACE (chooser)->remove_filter (chooser, filter);
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_file_chooser_list_filters:
|
||||
* @choooser: a #GtkFileChooser
|
||||
*
|
||||
* Lists the current set of user-selectable filters; see
|
||||
* gtk_file_chooser_add_filter(), gtk_file_chooser_remove_filter().
|
||||
*
|
||||
* Return value: a #GSList containing the current set of
|
||||
* user selectable filters. The contents of the list are
|
||||
* owned by GTK+, but you must free the list itself with
|
||||
* g_slist_free() when you are done with it.
|
||||
**/
|
||||
GSList *
|
||||
gtk_file_chooser_list_filters (GtkFileChooser *chooser)
|
||||
{
|
||||
g_return_val_if_fail (GTK_IS_FILE_CHOOSER (chooser), NULL);
|
||||
|
||||
return GTK_FILE_CHOOSER_GET_IFACE (chooser)->list_filters (chooser);
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_file_chooser_set_filter:
|
||||
* @chooser: a #GtkFileChooser
|
||||
* @filter: a #GtkFileFilter
|
||||
*
|
||||
* Sets the current filter; only the files that pass the
|
||||
* filter will be displayed. If the user-selectable list of filters
|
||||
* is non-empty, then the filter should be one of the filters
|
||||
* in that list. Setting the current filter when the list of
|
||||
* filters is empty is useful if you want to restrict the displayed
|
||||
* set of files without letting the user change it.
|
||||
**/
|
||||
void
|
||||
gtk_file_chooser_set_filter (GtkFileChooser *chooser,
|
||||
GtkFileFilter *filter)
|
||||
{
|
||||
g_return_if_fail (GTK_IS_FILE_CHOOSER (chooser));
|
||||
g_return_if_fail (GTK_IS_FILE_FILTER (filter));
|
||||
|
||||
g_object_set (chooser, "filter", filter, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_file_chooser_get_filter:
|
||||
* @chooser: a #GtkFileChooser
|
||||
*
|
||||
* Gets the current filter; see gtk_file_chooser_set_filter().
|
||||
*
|
||||
* Return value: the current filter, or %NULL
|
||||
**/
|
||||
GtkFileFilter *
|
||||
gtk_file_chooser_get_filter (GtkFileChooser *chooser)
|
||||
{
|
||||
GtkFileFilter *filter;
|
||||
|
||||
g_return_val_if_fail (GTK_IS_FILE_CHOOSER (chooser), NULL);
|
||||
|
||||
g_object_get (chooser, "filter", &filter, NULL);
|
||||
/* Horrid hack; g_object_get() refs returned objects but
|
||||
* that contradicts the memory management conventions
|
||||
* for accessors.
|
||||
*/
|
||||
if (filter)
|
||||
g_object_unref (filter);
|
||||
|
||||
return filter;
|
||||
}
|
||||
|
||||
|
||||
|
@ -21,6 +21,7 @@
|
||||
#ifndef __GTK_FILE_CHOOSER_H__
|
||||
#define __GTK_FILE_CHOOSER_H__
|
||||
|
||||
#include "gtkfilefilter.h"
|
||||
#include <gtk/gtkwidget.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
@ -100,29 +101,19 @@ gboolean gtk_file_chooser_get_preview_widget_active (GtkFileChooser *chooser);
|
||||
const char *gtk_file_chooser_get_preview_filename (GtkFileChooser *file_chooser);
|
||||
const char *gtk_file_chooser_get_preview_uri (GtkFileChooser *file_chooser);
|
||||
|
||||
|
||||
#if 0
|
||||
/* Filters
|
||||
/* List of user selectable filters
|
||||
*/
|
||||
void gtk_file_chooser_add_filter (GtkFileChooser *chooser,
|
||||
GtkFileFilter *filter);
|
||||
void gtk_file_chooser_remove_filter (GtkFileChooser *chooser,
|
||||
GtkFileFilter *filter);
|
||||
GList *gtk_file_chooser_get_filters (GtkFileChooser *chooser);
|
||||
void gtk_file_chooser_add_filter (GtkFileChooser *chooser,
|
||||
GtkFileFilter *filter);
|
||||
void gtk_file_chooser_remove_filter (GtkFileChooser *chooser,
|
||||
GtkFileFilter *filter);
|
||||
GSList *gtk_file_chooser_list_filters (GtkFileChooser *chooser);
|
||||
|
||||
|
||||
/************************************************/
|
||||
|
||||
static gboolean (*GtkFileFilterFunc) (const char *uri,
|
||||
const char *filename,
|
||||
gpointer data);
|
||||
|
||||
GtkFileFilter *gtk_file_filter_new_pattern (const char *pattern);
|
||||
GtkFileFilter *gtk_file_filter_new_mime_type (const char *mime_type);
|
||||
GtkFileFilter *gtk_file_filter_new_callback (GtkFileFilterFunction *func,
|
||||
gpointer data,
|
||||
GDestroyNotify notify);
|
||||
#endif
|
||||
/* Current filter
|
||||
*/
|
||||
void gtk_file_chooser_set_filter (GtkFileChooser *chooser,
|
||||
GtkFileFilter *filter);
|
||||
GtkFileFilter *gtk_file_chooser_get_filter (GtkFileChooser *chooser);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include "gtkfilechooser.h"
|
||||
#include "gtkfilesystemmodel.h"
|
||||
|
||||
#include <gtk/gtkalignment.h>
|
||||
#include <gtk/gtkcellrendererpixbuf.h>
|
||||
#include <gtk/gtkcellrenderertext.h>
|
||||
#include <gtk/gtkentry.h>
|
||||
@ -32,6 +33,8 @@
|
||||
#include <gtk/gtkhpaned.h>
|
||||
#include <gtk/gtkicontheme.h>
|
||||
#include <gtk/gtklabel.h>
|
||||
#include <gtk/gtkmenuitem.h>
|
||||
#include <gtk/gtkoptionmenu.h>
|
||||
#include <gtk/gtkscrolledwindow.h>
|
||||
#include <gtk/gtktreeview.h>
|
||||
#include <gtk/gtktreemodelsort.h>
|
||||
@ -62,6 +65,9 @@ struct _GtkFileChooserImplDefault
|
||||
|
||||
GtkFileChooserAction action;
|
||||
|
||||
GtkFileFilter *current_filter;
|
||||
GSList *filters;
|
||||
|
||||
GtkFilePath *current_folder;
|
||||
|
||||
guint folder_mode : 1;
|
||||
@ -70,6 +76,8 @@ struct _GtkFileChooserImplDefault
|
||||
guint select_multiple : 1;
|
||||
guint show_hidden : 1;
|
||||
|
||||
GtkWidget *filter_alignment;
|
||||
GtkWidget *filter_option_menu;
|
||||
GtkWidget *tree_scrollwin;
|
||||
GtkWidget *tree;
|
||||
GtkWidget *list_scrollwin;
|
||||
@ -94,6 +102,7 @@ static void gtk_file_chooser_impl_default_get_property (GObject
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec);
|
||||
static void gtk_file_chooser_impl_default_show_all (GtkWidget *widget);
|
||||
|
||||
static void gtk_file_chooser_impl_default_set_current_folder (GtkFileChooser *chooser,
|
||||
const GtkFilePath *path);
|
||||
@ -108,13 +117,23 @@ static void gtk_file_chooser_impl_default_select_all (GtkFileC
|
||||
static void gtk_file_chooser_impl_default_unselect_all (GtkFileChooser *chooser);
|
||||
static GSList * gtk_file_chooser_impl_default_get_paths (GtkFileChooser *chooser);
|
||||
static GtkFileSystem *gtk_file_chooser_impl_default_get_file_system (GtkFileChooser *chooser);
|
||||
static void gtk_file_chooser_impl_default_add_filter (GtkFileChooser *chooser,
|
||||
GtkFileFilter *filter);
|
||||
static void gtk_file_chooser_impl_default_remove_filter (GtkFileChooser *chooser,
|
||||
GtkFileFilter *filter);
|
||||
static GSList * gtk_file_chooser_impl_default_list_filters (GtkFileChooser *chooser);
|
||||
|
||||
static void tree_selection_changed (GtkTreeSelection *tree_selection,
|
||||
GtkFileChooserImplDefault *impl);
|
||||
static void list_selection_changed (GtkTreeSelection *tree_selection,
|
||||
GtkFileChooserImplDefault *impl);
|
||||
static void entry_activate (GtkEntry *entry,
|
||||
GtkFileChooserImplDefault *impl);
|
||||
static void set_current_filter (GtkFileChooserImplDefault *impl,
|
||||
GtkFileFilter *filter);
|
||||
|
||||
static void filter_option_menu_changed (GtkOptionMenu *option_menu,
|
||||
GtkFileChooserImplDefault *impl);
|
||||
static void tree_selection_changed (GtkTreeSelection *tree_selection,
|
||||
GtkFileChooserImplDefault *impl);
|
||||
static void list_selection_changed (GtkTreeSelection *tree_selection,
|
||||
GtkFileChooserImplDefault *impl);
|
||||
static void entry_activate (GtkEntry *entry,
|
||||
GtkFileChooserImplDefault *impl);
|
||||
|
||||
static void tree_name_data_func (GtkTreeViewColumn *tree_column,
|
||||
GtkCellRenderer *cell,
|
||||
@ -180,6 +199,7 @@ static void
|
||||
gtk_file_chooser_impl_default_class_init (GtkFileChooserImplDefaultClass *class)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (class);
|
||||
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
|
||||
|
||||
parent_class = g_type_class_peek_parent (class);
|
||||
|
||||
@ -188,6 +208,8 @@ gtk_file_chooser_impl_default_class_init (GtkFileChooserImplDefaultClass *class)
|
||||
gobject_class->set_property = gtk_file_chooser_impl_default_set_property;
|
||||
gobject_class->get_property = gtk_file_chooser_impl_default_get_property;
|
||||
|
||||
widget_class->show_all = gtk_file_chooser_impl_default_show_all;
|
||||
|
||||
_gtk_file_chooser_install_properties (gobject_class);
|
||||
}
|
||||
|
||||
@ -203,6 +225,9 @@ gtk_file_chooser_impl_default_iface_init (GtkFileChooserIface *iface)
|
||||
iface->set_current_folder = gtk_file_chooser_impl_default_set_current_folder;
|
||||
iface->get_current_folder = gtk_file_chooser_impl_default_get_current_folder;
|
||||
iface->set_current_name = gtk_file_chooser_impl_default_set_current_name;
|
||||
iface->add_filter = gtk_file_chooser_impl_default_add_filter;
|
||||
iface->remove_filter = gtk_file_chooser_impl_default_remove_filter;
|
||||
iface->list_filters = gtk_file_chooser_impl_default_list_filters;
|
||||
}
|
||||
|
||||
static void
|
||||
@ -274,6 +299,30 @@ gtk_file_chooser_impl_default_constructor (GType type,
|
||||
|
||||
gtk_widget_push_composite_child ();
|
||||
|
||||
impl->filter_alignment = gtk_alignment_new (0.0, 0.5, 0.0, 1.0);
|
||||
gtk_alignment_set_padding (GTK_ALIGNMENT (impl->filter_alignment), 0, 6, 0, 0);
|
||||
gtk_box_pack_start (GTK_BOX (impl), impl->filter_alignment, FALSE, FALSE, 0);
|
||||
/* Don't show filter initially */
|
||||
|
||||
hbox = gtk_hbox_new (FALSE, 6);
|
||||
gtk_container_add (GTK_CONTAINER (impl->filter_alignment), hbox);
|
||||
gtk_widget_show (hbox);
|
||||
|
||||
label = gtk_label_new_with_mnemonic ("Files of _type:");
|
||||
gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
|
||||
gtk_widget_show (label);
|
||||
|
||||
impl->filter_option_menu = gtk_option_menu_new ();
|
||||
gtk_option_menu_set_menu (GTK_OPTION_MENU (impl->filter_option_menu),
|
||||
gtk_menu_new ());
|
||||
gtk_box_pack_start (GTK_BOX (hbox), impl->filter_option_menu, FALSE, FALSE, 0);
|
||||
gtk_widget_show (impl->filter_option_menu);
|
||||
|
||||
gtk_label_set_mnemonic_widget (GTK_LABEL (label), impl->filter_option_menu);
|
||||
|
||||
g_signal_connect (impl->filter_option_menu, "changed",
|
||||
G_CALLBACK (filter_option_menu_changed), impl);
|
||||
|
||||
hpaned = gtk_hpaned_new ();
|
||||
gtk_box_pack_start (GTK_BOX (impl), hpaned, TRUE, TRUE, 0);
|
||||
gtk_widget_show (hpaned);
|
||||
@ -415,6 +464,9 @@ gtk_file_chooser_impl_default_set_property (GObject *object,
|
||||
}
|
||||
}
|
||||
break;
|
||||
case GTK_FILE_CHOOSER_PROP_FILTER:
|
||||
set_current_filter (impl, g_value_get_object (value));
|
||||
break;
|
||||
case GTK_FILE_CHOOSER_PROP_FOLDER_MODE:
|
||||
{
|
||||
gboolean folder_mode = g_value_get_boolean (value);
|
||||
@ -481,6 +533,9 @@ gtk_file_chooser_impl_default_get_property (GObject *object,
|
||||
case GTK_FILE_CHOOSER_PROP_ACTION:
|
||||
g_value_set_enum (value, impl->action);
|
||||
break;
|
||||
case GTK_FILE_CHOOSER_PROP_FILTER:
|
||||
g_value_set_object (value, impl->current_filter);
|
||||
break;
|
||||
case GTK_FILE_CHOOSER_PROP_FOLDER_MODE:
|
||||
g_value_set_boolean (value, impl->folder_mode);
|
||||
break;
|
||||
@ -505,6 +560,16 @@ gtk_file_chooser_impl_default_get_property (GObject *object,
|
||||
}
|
||||
}
|
||||
|
||||
/* We override show-all since we have internal widgets that
|
||||
* shouldn't be shown when you call show_all(), like the filter
|
||||
* option menu.
|
||||
*/
|
||||
static void
|
||||
gtk_file_chooser_impl_default_show_all (GtkWidget *widget)
|
||||
{
|
||||
gtk_widget_show (widget);
|
||||
}
|
||||
|
||||
static void
|
||||
expand_and_select_func (GtkFileSystemModel *model,
|
||||
GtkTreePath *path,
|
||||
@ -587,7 +652,7 @@ gtk_file_chooser_impl_default_select_path (GtkFileChooser *chooser,
|
||||
_gtk_file_chooser_set_current_folder_path (chooser, parent_path);
|
||||
gtk_file_path_free (parent_path);
|
||||
_gtk_file_system_model_path_do (impl->list_model, path,
|
||||
select_func, impl);
|
||||
select_func, impl);
|
||||
}
|
||||
}
|
||||
|
||||
@ -691,6 +756,209 @@ gtk_file_chooser_impl_default_get_file_system (GtkFileChooser *chooser)
|
||||
return impl->file_system;
|
||||
}
|
||||
|
||||
static GtkWidget *
|
||||
find_filter_menu_item (GtkFileChooserImplDefault *impl,
|
||||
GtkFileFilter *filter,
|
||||
gint *index_return)
|
||||
{
|
||||
GtkWidget *menu = gtk_option_menu_get_menu (GTK_OPTION_MENU (impl->filter_option_menu));
|
||||
GList *children = gtk_container_get_children (GTK_CONTAINER (menu));
|
||||
GList *tmp_list;
|
||||
int index = 0;
|
||||
|
||||
if (index_return)
|
||||
*index_return = -1;
|
||||
|
||||
for (tmp_list = children; tmp_list; tmp_list = tmp_list->next)
|
||||
{
|
||||
if (g_object_get_data (tmp_list->data, "gtk-file-filter") == filter)
|
||||
{
|
||||
if (index_return)
|
||||
*index_return = index;
|
||||
return tmp_list->data;
|
||||
}
|
||||
index++;
|
||||
}
|
||||
|
||||
g_list_free (children);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_file_chooser_impl_default_add_filter (GtkFileChooser *chooser,
|
||||
GtkFileFilter *filter)
|
||||
{
|
||||
GtkFileChooserImplDefault *impl = GTK_FILE_CHOOSER_IMPL_DEFAULT (chooser);
|
||||
GtkWidget *menu;
|
||||
GtkWidget *menu_item;
|
||||
const gchar *name;
|
||||
|
||||
if (g_slist_find (impl->filters, filter))
|
||||
{
|
||||
g_warning ("gtk_file_chooser_add_filter() called on filter already in list\n");
|
||||
return;
|
||||
}
|
||||
|
||||
g_object_ref (filter);
|
||||
gtk_object_sink (GTK_OBJECT (filter));
|
||||
impl->filters = g_slist_append (impl->filters, filter);
|
||||
|
||||
name = gtk_file_filter_get_name (filter);
|
||||
if (!name)
|
||||
name = "Untitled filter"; /* Place-holder, doesn't need to be marked for translation */
|
||||
|
||||
menu_item = gtk_menu_item_new_with_label (name);
|
||||
g_object_set_data (G_OBJECT (menu_item), "gtk-file-filter", filter);
|
||||
gtk_widget_show (menu_item);
|
||||
|
||||
menu = gtk_option_menu_get_menu (GTK_OPTION_MENU (impl->filter_option_menu));
|
||||
gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item);
|
||||
/* Option menus don't react to menu size changes properly */
|
||||
gtk_widget_size_request (menu, NULL);
|
||||
|
||||
if (!g_slist_find (impl->filters, impl->current_filter))
|
||||
set_current_filter (impl, filter);
|
||||
|
||||
gtk_widget_show (impl->filter_alignment);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_file_chooser_impl_default_remove_filter (GtkFileChooser *chooser,
|
||||
GtkFileFilter *filter)
|
||||
{
|
||||
GtkFileChooserImplDefault *impl = GTK_FILE_CHOOSER_IMPL_DEFAULT (chooser);
|
||||
GtkWidget *menu;
|
||||
GtkWidget *menu_item;
|
||||
|
||||
if (!g_slist_find (impl->filters, filter))
|
||||
{
|
||||
g_warning ("gtk_file_chooser_remove_filter() called on filter not in list\n");
|
||||
return;
|
||||
}
|
||||
|
||||
impl->filters = g_slist_remove (impl->filters, filter);
|
||||
|
||||
if (filter == impl->current_filter)
|
||||
{
|
||||
if (impl->filters)
|
||||
set_current_filter (impl, impl->filters->data);
|
||||
else
|
||||
set_current_filter (impl, NULL);
|
||||
}
|
||||
|
||||
menu = gtk_option_menu_get_menu (GTK_OPTION_MENU (impl->filter_option_menu));
|
||||
menu_item = find_filter_menu_item (impl, filter, NULL);
|
||||
g_assert (menu_item);
|
||||
gtk_widget_destroy (menu_item);
|
||||
/* Option menus don't react to menu size changes properly */
|
||||
gtk_widget_size_request (menu, NULL);
|
||||
|
||||
g_object_unref (filter);
|
||||
|
||||
if (!impl->filters)
|
||||
gtk_widget_hide (impl->filter_alignment);
|
||||
}
|
||||
|
||||
static GSList *
|
||||
gtk_file_chooser_impl_default_list_filters (GtkFileChooser *chooser)
|
||||
{
|
||||
GtkFileChooserImplDefault *impl = GTK_FILE_CHOOSER_IMPL_DEFAULT (chooser);
|
||||
|
||||
return g_slist_copy (impl->filters);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
list_model_filter_func (GtkFileSystemModel *model,
|
||||
GtkFilePath *path,
|
||||
const GtkFileInfo *file_info,
|
||||
gpointer user_data)
|
||||
{
|
||||
GtkFileChooserImplDefault *impl = user_data;
|
||||
GtkFileFilterInfo filter_info;
|
||||
GtkFileFilterFlags needed;
|
||||
gboolean result;
|
||||
|
||||
if (!impl->current_filter)
|
||||
return TRUE;
|
||||
|
||||
filter_info.contains = GTK_FILE_FILTER_DISPLAY_NAME | GTK_FILE_FILTER_MIME_TYPE;
|
||||
|
||||
needed = gtk_file_filter_get_needed (impl->current_filter);
|
||||
|
||||
filter_info.display_name = gtk_file_info_get_display_name (file_info);
|
||||
filter_info.mime_type = gtk_file_info_get_mime_type (file_info);
|
||||
|
||||
if (needed & GTK_FILE_FILTER_FILENAME)
|
||||
{
|
||||
filter_info.filename = gtk_file_system_path_to_filename (impl->file_system, path);
|
||||
if (filter_info.filename)
|
||||
filter_info.contains |= GTK_FILE_FILTER_FILENAME;
|
||||
}
|
||||
else
|
||||
filter_info.filename = NULL;
|
||||
|
||||
if (needed & GTK_FILE_FILTER_URI)
|
||||
{
|
||||
filter_info.uri = gtk_file_system_path_to_uri (impl->file_system, path);
|
||||
if (filter_info.filename)
|
||||
filter_info.contains |= GTK_FILE_FILTER_URI;
|
||||
}
|
||||
else
|
||||
filter_info.uri = NULL;
|
||||
|
||||
result = gtk_file_filter_filter (impl->current_filter, &filter_info);
|
||||
|
||||
if (filter_info.filename)
|
||||
g_free ((gchar *)filter_info.filename);
|
||||
if (filter_info.uri)
|
||||
g_free ((gchar *)filter_info.uri);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void
|
||||
install_list_model_filter (GtkFileChooserImplDefault *impl)
|
||||
{
|
||||
if (impl->current_filter)
|
||||
_gtk_file_system_model_set_filter (impl->list_model,
|
||||
list_model_filter_func,
|
||||
impl);
|
||||
}
|
||||
|
||||
static void
|
||||
set_current_filter (GtkFileChooserImplDefault *impl,
|
||||
GtkFileFilter *filter)
|
||||
{
|
||||
if (impl->current_filter != filter)
|
||||
{
|
||||
int menu_item_index;
|
||||
|
||||
/* If we have filters, new filter must be one of them
|
||||
*/
|
||||
find_filter_menu_item (impl, filter, &menu_item_index);
|
||||
if (impl->filters && menu_item_index < 0)
|
||||
return;
|
||||
|
||||
if (impl->current_filter)
|
||||
g_object_unref (impl->current_filter);
|
||||
impl->current_filter = filter;
|
||||
if (impl->current_filter)
|
||||
{
|
||||
g_object_ref (impl->current_filter);
|
||||
gtk_object_sink (GTK_OBJECT (filter));
|
||||
}
|
||||
|
||||
if (impl->filters)
|
||||
gtk_option_menu_set_history (GTK_OPTION_MENU (impl->filter_option_menu),
|
||||
menu_item_index);
|
||||
|
||||
install_list_model_filter (impl);
|
||||
|
||||
g_object_notify (G_OBJECT (impl), "filter");
|
||||
}
|
||||
}
|
||||
|
||||
static gint
|
||||
name_sort_func (GtkTreeModel *model,
|
||||
GtkTreeIter *a,
|
||||
@ -797,6 +1065,16 @@ update_chooser_entry (GtkFileChooserImplDefault *impl)
|
||||
gtk_file_info_get_display_name (info));
|
||||
}
|
||||
|
||||
static void
|
||||
filter_option_menu_changed (GtkOptionMenu *option_menu,
|
||||
GtkFileChooserImplDefault *impl)
|
||||
{
|
||||
gint new_index = gtk_option_menu_get_history (GTK_OPTION_MENU (option_menu));
|
||||
GtkFileFilter *new_filter = g_slist_nth_data (impl->filters, new_index);
|
||||
|
||||
set_current_filter (impl, new_filter);
|
||||
}
|
||||
|
||||
static void
|
||||
tree_selection_changed (GtkTreeSelection *selection,
|
||||
GtkFileChooserImplDefault *impl)
|
||||
@ -843,6 +1121,7 @@ tree_selection_changed (GtkTreeSelection *selection,
|
||||
GTK_FILE_INFO_DISPLAY_NAME |
|
||||
GTK_FILE_INFO_SIZE);
|
||||
_gtk_file_system_model_set_show_folders (impl->list_model, FALSE);
|
||||
install_list_model_filter (impl);
|
||||
|
||||
impl->sort_model = (GtkTreeModelSort *)gtk_tree_model_sort_new_with_model (GTK_TREE_MODEL (impl->list_model));
|
||||
gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (impl->sort_model), 0, name_sort_func, impl, NULL);
|
||||
|
@ -34,18 +34,6 @@ struct _GtkFileChooserIface
|
||||
{
|
||||
GTypeInterface base_iface;
|
||||
|
||||
/* GtkFileChooser interface has the following properties:
|
||||
*
|
||||
* action: GtkFileChooserAction
|
||||
* folder_mode: boolean
|
||||
* select_multiple: boolean
|
||||
* show_hidden: boolean
|
||||
* local_only: boolean
|
||||
*
|
||||
* preview_widget: GtkWidget
|
||||
* preview_widget_active: boolean
|
||||
*/
|
||||
|
||||
/* Methods
|
||||
*/
|
||||
void (*set_current_folder) (GtkFileChooser *chooser,
|
||||
@ -61,6 +49,12 @@ struct _GtkFileChooserIface
|
||||
void (*unselect_all) (GtkFileChooser *chooser);
|
||||
GSList * (*get_paths) (GtkFileChooser *chooser);
|
||||
GtkFileSystem *(*get_file_system) (GtkFileChooser *chooser);
|
||||
void (*add_filter) (GtkFileChooser *chooser,
|
||||
GtkFileFilter *filter);
|
||||
void (*remove_filter) (GtkFileChooser *chooser,
|
||||
GtkFileFilter *filter);
|
||||
GSList * (*list_filters) (GtkFileChooser *chooser);
|
||||
|
||||
|
||||
/* Signals
|
||||
*/
|
||||
|
@ -37,6 +37,14 @@ static void delegate_select_all (GtkFileChooser *choose
|
||||
static void delegate_unselect_all (GtkFileChooser *chooser);
|
||||
static GSList * delegate_get_paths (GtkFileChooser *chooser);
|
||||
static GtkFileSystem *delegate_get_file_system (GtkFileChooser *chooser);
|
||||
static void delegate_add_filter (GtkFileChooser *chooser,
|
||||
GtkFileFilter *filter);
|
||||
static void delegate_remove_filter (GtkFileChooser *chooser,
|
||||
GtkFileFilter *filter);
|
||||
static GSList * delegate_list_filters (GtkFileChooser *chooser);
|
||||
static void delegate_notify (GObject *object,
|
||||
GParamSpec *pspec,
|
||||
gpointer data);
|
||||
static void delegate_current_folder_changed (GtkFileChooser *chooser,
|
||||
gpointer data);
|
||||
static void delegate_selection_changed (GtkFileChooser *chooser,
|
||||
@ -66,6 +74,11 @@ _gtk_file_chooser_install_properties (GObjectClass *klass)
|
||||
g_param_spec_override ("file-system",
|
||||
GTK_TYPE_FILE_SYSTEM,
|
||||
G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
|
||||
g_object_class_install_property (klass,
|
||||
GTK_FILE_CHOOSER_PROP_FILTER,
|
||||
g_param_spec_override ("filter",
|
||||
GTK_TYPE_FILE_FILTER,
|
||||
G_PARAM_READWRITE));
|
||||
g_object_class_install_property (klass,
|
||||
GTK_FILE_CHOOSER_PROP_FOLDER_MODE,
|
||||
g_param_spec_override ("folder-mode",
|
||||
@ -121,6 +134,9 @@ _gtk_file_chooser_delegate_iface_init (GtkFileChooserIface *iface)
|
||||
iface->unselect_all = delegate_unselect_all;
|
||||
iface->get_paths = delegate_get_paths;
|
||||
iface->get_file_system = delegate_get_file_system;
|
||||
iface->add_filter = delegate_add_filter;
|
||||
iface->remove_filter = delegate_remove_filter;
|
||||
iface->list_filters = delegate_list_filters;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -143,6 +159,8 @@ _gtk_file_chooser_set_delegate (GtkFileChooser *receiver,
|
||||
|
||||
g_object_set_data (G_OBJECT (receiver), "gtk-file-chooser-delegate", delegate);
|
||||
|
||||
g_signal_connect (delegate, "notify",
|
||||
G_CALLBACK (delegate_notify), receiver);
|
||||
g_signal_connect (delegate, "current-folder-changed",
|
||||
G_CALLBACK (delegate_current_folder_changed), receiver);
|
||||
g_signal_connect (delegate, "selection-changed",
|
||||
@ -193,6 +211,26 @@ delegate_get_file_system (GtkFileChooser *chooser)
|
||||
return _gtk_file_chooser_get_file_system (get_delegate (chooser));
|
||||
}
|
||||
|
||||
static void
|
||||
delegate_add_filter (GtkFileChooser *chooser,
|
||||
GtkFileFilter *filter)
|
||||
{
|
||||
gtk_file_chooser_add_filter (get_delegate (chooser), filter);
|
||||
}
|
||||
|
||||
static void
|
||||
delegate_remove_filter (GtkFileChooser *chooser,
|
||||
GtkFileFilter *filter)
|
||||
{
|
||||
gtk_file_chooser_remove_filter (get_delegate (chooser), filter);
|
||||
}
|
||||
|
||||
static GSList *
|
||||
delegate_list_filters (GtkFileChooser *chooser)
|
||||
{
|
||||
return gtk_file_chooser_list_filters (get_delegate (chooser));
|
||||
}
|
||||
|
||||
static void
|
||||
delegate_set_current_folder (GtkFileChooser *chooser,
|
||||
const GtkFilePath *path)
|
||||
@ -213,6 +251,18 @@ delegate_set_current_name (GtkFileChooser *chooser,
|
||||
gtk_file_chooser_set_current_name (get_delegate (chooser), name);
|
||||
}
|
||||
|
||||
static void
|
||||
delegate_notify (GObject *object,
|
||||
GParamSpec *pspec,
|
||||
gpointer data)
|
||||
{
|
||||
if (pspec->param_id >= GTK_FILE_CHOOSER_PROP_FIRST &&
|
||||
pspec->param_id <= GTK_FILE_CHOOSER_PROP_LAST)
|
||||
{
|
||||
g_object_notify (data, pspec->name);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
delegate_selection_changed (GtkFileChooser *chooser,
|
||||
gpointer data)
|
||||
|
@ -27,14 +27,17 @@
|
||||
G_BEGIN_DECLS
|
||||
|
||||
typedef enum {
|
||||
GTK_FILE_CHOOSER_PROP_ACTION = 0x1000,
|
||||
GTK_FILE_CHOOSER_PROP_FIRST = 0x1000,
|
||||
GTK_FILE_CHOOSER_PROP_ACTION = GTK_FILE_CHOOSER_PROP_FIRST,
|
||||
GTK_FILE_CHOOSER_PROP_FILE_SYSTEM,
|
||||
GTK_FILE_CHOOSER_PROP_FILTER,
|
||||
GTK_FILE_CHOOSER_PROP_FOLDER_MODE,
|
||||
GTK_FILE_CHOOSER_PROP_LOCAL_ONLY,
|
||||
GTK_FILE_CHOOSER_PROP_PREVIEW_WIDGET,
|
||||
GTK_FILE_CHOOSER_PROP_PREVIEW_WIDGET_ACTIVE,
|
||||
GTK_FILE_CHOOSER_PROP_SELECT_MULTIPLE,
|
||||
GTK_FILE_CHOOSER_PROP_SHOW_HIDDEN
|
||||
GTK_FILE_CHOOSER_PROP_SHOW_HIDDEN,
|
||||
GTK_FILE_CHOOSER_PROP_LAST = GTK_FILE_CHOOSER_PROP_SHOW_HIDDEN,
|
||||
} GtkFileChooserProp;
|
||||
|
||||
void _gtk_file_chooser_install_properties (GObjectClass *klass);
|
||||
|
372
gtk/gtkfilefilter.c
Normal file
372
gtk/gtkfilefilter.c
Normal file
@ -0,0 +1,372 @@
|
||||
/* GTK - The GIMP Toolkit
|
||||
* gtkfilefilter.c: Filters for selecting a file subset
|
||||
* Copyright (C) 2003, Red Hat, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include "gtkfilefilter.h"
|
||||
|
||||
#include <gtk/gtkobject.h>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
typedef struct _GtkFileFilterClass GtkFileFilterClass;
|
||||
typedef struct _FilterRule FilterRule;
|
||||
|
||||
#define GTK_FILE_FILTER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_FILE_FILTER, GtkFileFilterClass))
|
||||
#define GTK_IS_FILE_FILTER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_FILE_FILTER))
|
||||
#define GTK_FILE_FILTER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_FILE_FILTER, GtkFileFilterClass))
|
||||
|
||||
typedef enum {
|
||||
FILTER_RULE_PATTERN,
|
||||
FILTER_RULE_MIME_TYPE,
|
||||
FILTER_RULE_CUSTOM,
|
||||
} FilterRuleType;
|
||||
|
||||
struct _GtkFileFilterClass
|
||||
{
|
||||
GtkObjectClass parent_class;
|
||||
};
|
||||
|
||||
struct _GtkFileFilter
|
||||
{
|
||||
GtkObject parent_instance;
|
||||
|
||||
gchar *name;
|
||||
GSList *rules;
|
||||
|
||||
GtkFileFilterFlags needed;
|
||||
};
|
||||
|
||||
struct _FilterRule
|
||||
{
|
||||
FilterRuleType type;
|
||||
GtkFileFilterFlags needed;
|
||||
|
||||
union {
|
||||
gchar *pattern;
|
||||
gchar *mime_type;
|
||||
struct {
|
||||
GtkFileFilterFunc func;
|
||||
gpointer data;
|
||||
GDestroyNotify notify;
|
||||
} custom;
|
||||
} u;
|
||||
};
|
||||
|
||||
static void gtk_file_filter_class_init (GtkFileFilterClass *class);
|
||||
static void gtk_file_filter_finalize (GObject *object);
|
||||
|
||||
static GObjectClass *parent_class;
|
||||
|
||||
GType
|
||||
gtk_file_filter_get_type (void)
|
||||
{
|
||||
static GType file_filter_type = 0;
|
||||
|
||||
if (!file_filter_type)
|
||||
{
|
||||
static const GTypeInfo file_filter_info =
|
||||
{
|
||||
sizeof (GtkFileFilterClass),
|
||||
NULL, /* base_init */
|
||||
NULL, /* base_finalize */
|
||||
(GClassInitFunc) gtk_file_filter_class_init,
|
||||
NULL, /* class_finalize */
|
||||
NULL, /* class_data */
|
||||
sizeof (GtkFileFilter),
|
||||
0, /* n_preallocs */
|
||||
NULL /* init */
|
||||
};
|
||||
|
||||
file_filter_type = g_type_register_static (GTK_TYPE_OBJECT, "GtkFileFilter",
|
||||
&file_filter_info, 0);
|
||||
}
|
||||
|
||||
return file_filter_type;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_file_filter_class_init (GtkFileFilterClass *class)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (class);
|
||||
|
||||
parent_class = g_type_class_peek_parent (class);
|
||||
|
||||
gobject_class->finalize = gtk_file_filter_finalize;
|
||||
}
|
||||
|
||||
static void
|
||||
filter_rule_free (FilterRule *rule)
|
||||
{
|
||||
switch (rule->type)
|
||||
{
|
||||
case FILTER_RULE_MIME_TYPE:
|
||||
g_free (rule->u.mime_type);
|
||||
break;
|
||||
case FILTER_RULE_PATTERN:
|
||||
g_free (rule->u.pattern);
|
||||
break;
|
||||
case FILTER_RULE_CUSTOM:
|
||||
if (rule->u.custom.notify)
|
||||
rule->u.custom.notify (rule->u.custom.data);
|
||||
break;
|
||||
}
|
||||
|
||||
g_free (rule);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_file_filter_finalize (GObject *object)
|
||||
{
|
||||
GtkFileFilter *filter = GTK_FILE_FILTER (filter);
|
||||
|
||||
g_slist_foreach (filter->rules, (GFunc)filter_rule_free, NULL);
|
||||
|
||||
parent_class->finalize (object);
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_file_filter_new:
|
||||
*
|
||||
* Creates a new #GtkFileFilter with no rules added to it.
|
||||
* Such a filter doesn't accept any files, so is not
|
||||
* particularly useful until you add rules with
|
||||
* gtk_file_filter_add_mime_type(), gtk_file_filter_add_pattern(),
|
||||
* or gtk_file_filter_add_custom(). To create a filter
|
||||
* that accepts any file, use:
|
||||
*
|
||||
* <informalexample><programlisting>
|
||||
* GtkFileFilter *filter = gtk_file_filter_new ();
|
||||
* gtk_file_filter_add_pattern (filter, "*");
|
||||
* </programlisting></programlisting>
|
||||
*
|
||||
* Return value: a new #GtkFileFilter
|
||||
**/
|
||||
GtkFileFilter *
|
||||
gtk_file_filter_new (void)
|
||||
{
|
||||
return g_object_new (GTK_TYPE_FILE_FILTER, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_file_filter_set_name:
|
||||
* @filter: a #GtkFileFilter
|
||||
* @name: the human-readable-name for the filter, or %NULL
|
||||
* to remove any existing name.
|
||||
*
|
||||
* Sets the human-readable name of the filter; this is the string
|
||||
* that will be displayed in the file selector user interface if
|
||||
* there is a selectable list of filters.
|
||||
**/
|
||||
void
|
||||
gtk_file_filter_set_name (GtkFileFilter *filter,
|
||||
const gchar *name)
|
||||
{
|
||||
g_return_if_fail (GTK_IS_FILE_FILTER (filter));
|
||||
|
||||
if (filter->name)
|
||||
g_free (filter->name);
|
||||
|
||||
filter->name = g_strdup (name);
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_file_filter_get_name:
|
||||
* @filter: a #GtkFileFilter
|
||||
*
|
||||
* Gets the human-readable name for the filter. See gtk_file_filter_set_name().
|
||||
*
|
||||
* Return value: The human-readable name of the filter,
|
||||
* or %NULL. This value is owned by GTK+ and must not
|
||||
* be modified or freed.
|
||||
**/
|
||||
G_CONST_RETURN gchar *
|
||||
gtk_file_filter_get_name (GtkFileFilter *filter)
|
||||
{
|
||||
g_return_val_if_fail (GTK_IS_FILE_FILTER (filter), NULL);
|
||||
|
||||
return filter->name;
|
||||
}
|
||||
|
||||
static void
|
||||
file_filter_add_rule (GtkFileFilter *filter,
|
||||
FilterRule *rule)
|
||||
{
|
||||
filter->needed |= rule->needed;
|
||||
filter->rules = g_slist_append (filter->rules, rule);
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_file_filter_add_mime_type:
|
||||
* @filter: A #GtkFileFilter
|
||||
* @mime_type: name of a MIME type
|
||||
*
|
||||
* Adds a rule allowing a given mime type to @filter.
|
||||
**/
|
||||
void
|
||||
gtk_file_filter_add_mime_type (GtkFileFilter *filter,
|
||||
const gchar *mime_type)
|
||||
{
|
||||
FilterRule *rule;
|
||||
|
||||
g_return_if_fail (GTK_IS_FILE_FILTER (filter));
|
||||
g_return_if_fail (mime_type != NULL);
|
||||
|
||||
rule = g_new (FilterRule, 1);
|
||||
rule->type = FILTER_RULE_MIME_TYPE;
|
||||
rule->needed = GTK_FILE_FILTER_MIME_TYPE;
|
||||
rule->u.mime_type = g_strdup (mime_type);
|
||||
|
||||
file_filter_add_rule (filter, rule);
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_file_filter_add_pattern:
|
||||
* @filter: a #GtkFileFilter
|
||||
* @pattern: a shell style glob
|
||||
*
|
||||
* Adds a rule allowing a shell style glob to a filter.
|
||||
**/
|
||||
void
|
||||
gtk_file_filter_add_pattern (GtkFileFilter *filter,
|
||||
const gchar *pattern)
|
||||
{
|
||||
FilterRule *rule;
|
||||
|
||||
g_return_if_fail (GTK_IS_FILE_FILTER (filter));
|
||||
g_return_if_fail (pattern != NULL);
|
||||
|
||||
rule = g_new (FilterRule, 1);
|
||||
rule->type = FILTER_RULE_PATTERN;
|
||||
rule->needed = GTK_FILE_FILTER_DISPLAY_NAME;
|
||||
rule->u.pattern = g_strdup (pattern);
|
||||
|
||||
file_filter_add_rule (filter, rule);
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_file_filter_add_custom:
|
||||
* @filter: a #GtkFileFilter
|
||||
* @needed: bitfield of flags indicating the information that the custom
|
||||
* filter function needs.
|
||||
* @func: callback function; if the function returns %TRUE, then
|
||||
* the file will be displayed.
|
||||
* @data: data to pass to @func
|
||||
* @notify: function to call to free @data when it is no longer needed.
|
||||
*
|
||||
* Adds rule to a filter that allows files based on a custom callback
|
||||
* function. The bitfield @needed which is passed in provides information
|
||||
* about what sorts of information that the filter function needs;
|
||||
* this allows GTK+ to avoid retrieving expensive information when
|
||||
* it isn't needed by the filter.
|
||||
**/
|
||||
void
|
||||
gtk_file_filter_add_custom (GtkFileFilter *filter,
|
||||
GtkFileFilterFlags needed,
|
||||
GtkFileFilterFunc func,
|
||||
gpointer data,
|
||||
GDestroyNotify notify)
|
||||
{
|
||||
FilterRule *rule;
|
||||
|
||||
g_return_if_fail (GTK_IS_FILE_FILTER (filter));
|
||||
g_return_if_fail (func != NULL);
|
||||
|
||||
rule = g_new (FilterRule, 1);
|
||||
rule->type = FILTER_RULE_CUSTOM;
|
||||
rule->needed = needed;
|
||||
rule->u.custom.func = func;
|
||||
rule->u.custom.data = data;
|
||||
rule->u.custom.notify = notify;
|
||||
|
||||
file_filter_add_rule (filter, rule);
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_file_filter_get_needed:
|
||||
* @filter: a #GtkFileFilter
|
||||
*
|
||||
* Gets the fields that need to be filled in for the structure
|
||||
* passed to gtk_file_filter_filter()
|
||||
*
|
||||
* This function will not typically be used by applications; it
|
||||
* is intended principally for use in the implementation of
|
||||
* #GtkFileChooser.
|
||||
*
|
||||
* Return value: bitfield of flags indicating needed fields when
|
||||
* calling gtk_file_filter_filter()
|
||||
**/
|
||||
GtkFileFilterFlags
|
||||
gtk_file_filter_get_needed (GtkFileFilter *filter)
|
||||
{
|
||||
return filter->needed;
|
||||
}
|
||||
|
||||
/* Remove once we merge into GTK+ and use _gtk_fnmatch().
|
||||
*/
|
||||
gboolean _gtk_file_chooser_fnmatch (const char *pattern,
|
||||
const char *string);
|
||||
|
||||
/**
|
||||
* gtk_file_filter_filter:
|
||||
* @filter: a #GtkFileFilter
|
||||
* @filter_info: a #GtkFileFilterInfo structure containing information
|
||||
* about a file.
|
||||
*
|
||||
* Tests whether a file should be displayed according to @filter.
|
||||
* The #GtkFileFilterInfo structure @filter_info should include
|
||||
* the fields returned feom gtk_file_filter_get_needed().
|
||||
*
|
||||
* This function will not typically be used by applications; it
|
||||
* is intended principally for use in the implementation of
|
||||
* #GtkFileChooser.
|
||||
*
|
||||
* Return value: %TRUE if the file should be displayed
|
||||
**/
|
||||
gboolean
|
||||
gtk_file_filter_filter (GtkFileFilter *filter,
|
||||
const GtkFileFilterInfo *filter_info)
|
||||
{
|
||||
GSList *tmp_list;
|
||||
|
||||
for (tmp_list = filter->rules; tmp_list; tmp_list = tmp_list->next)
|
||||
{
|
||||
FilterRule *rule = tmp_list->data;
|
||||
|
||||
if ((filter_info->contains & rule->needed) != rule->needed)
|
||||
continue;
|
||||
|
||||
switch (rule->type)
|
||||
{
|
||||
case FILTER_RULE_MIME_TYPE:
|
||||
if (strcmp (rule->u.mime_type, filter_info->mime_type) == 0)
|
||||
return TRUE;
|
||||
break;
|
||||
case FILTER_RULE_PATTERN:
|
||||
if (_gtk_file_chooser_fnmatch (rule->u.pattern, filter_info->display_name))
|
||||
return TRUE;
|
||||
break;
|
||||
case FILTER_RULE_CUSTOM:
|
||||
if (rule->u.custom.func (filter_info, rule->u.custom.data))
|
||||
return TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
78
gtk/gtkfilefilter.h
Normal file
78
gtk/gtkfilefilter.h
Normal file
@ -0,0 +1,78 @@
|
||||
/* GTK - The GIMP Toolkit
|
||||
* gtkfilefilter.h: Filters for selecting a file subset
|
||||
* Copyright (C) 2003, Red Hat, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef __GTK_FILE_FILTER_H__
|
||||
#define __GTK_FILE_FILTER_H__
|
||||
|
||||
#include <glib-object.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GTK_TYPE_FILE_FILTER (gtk_file_filter_get_type ())
|
||||
#define GTK_FILE_FILTER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_FILE_FILTER, GtkFileFilter))
|
||||
#define GTK_IS_FILE_FILTER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_FILE_FILTER))
|
||||
|
||||
typedef struct _GtkFileFilter GtkFileFilter;
|
||||
typedef struct _GtkFileFilterInfo GtkFileFilterInfo;
|
||||
|
||||
typedef enum {
|
||||
GTK_FILE_FILTER_FILENAME = 1 << 0,
|
||||
GTK_FILE_FILTER_URI = 1 << 1,
|
||||
GTK_FILE_FILTER_DISPLAY_NAME = 1 << 2,
|
||||
GTK_FILE_FILTER_MIME_TYPE = 1 << 3
|
||||
} GtkFileFilterFlags;
|
||||
|
||||
typedef gboolean (*GtkFileFilterFunc) (const GtkFileFilterInfo *filter_info,
|
||||
gpointer data);
|
||||
|
||||
struct _GtkFileFilterInfo
|
||||
{
|
||||
GtkFileFilterFlags contains;
|
||||
|
||||
const gchar *filename;
|
||||
const gchar *uri;
|
||||
const gchar *display_name;
|
||||
const gchar *mime_type;
|
||||
};
|
||||
|
||||
GType gtk_file_filter_get_type (void);
|
||||
|
||||
GtkFileFilter * gtk_file_filter_new (void);
|
||||
void gtk_file_filter_set_name (GtkFileFilter *filter,
|
||||
const gchar *name);
|
||||
G_CONST_RETURN gchar *gtk_file_filter_get_name (GtkFileFilter *filter);
|
||||
|
||||
void gtk_file_filter_add_mime_type (GtkFileFilter *filter,
|
||||
const gchar *mime_type);
|
||||
void gtk_file_filter_add_pattern (GtkFileFilter *filter,
|
||||
const gchar *pattern);
|
||||
void gtk_file_filter_add_custom (GtkFileFilter *filter,
|
||||
GtkFileFilterFlags needed,
|
||||
GtkFileFilterFunc func,
|
||||
gpointer data,
|
||||
GDestroyNotify notify);
|
||||
|
||||
GtkFileFilterFlags gtk_file_filter_get_needed (GtkFileFilter *filter);
|
||||
gboolean gtk_file_filter_filter (GtkFileFilter *filter,
|
||||
const GtkFileFilterInfo *filter_info);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GTK_FILE_FILTER_H__ */
|
@ -44,6 +44,9 @@ struct _GtkFileSystemModel
|
||||
FileModelNode *roots;
|
||||
GtkFileFolder *root_folder;
|
||||
|
||||
GtkFileSystemModelFilter filter_func;
|
||||
gpointer filter_data;
|
||||
|
||||
GSList *idle_clears;
|
||||
GSource *idle_clear_source;
|
||||
|
||||
@ -561,7 +564,8 @@ _gtk_file_system_model_new (GtkFileSystem *file_system,
|
||||
GtkFileInfoType types)
|
||||
{
|
||||
GtkFileSystemModel *model;
|
||||
GSList *roots, *tmp_list;
|
||||
GSList *roots = NULL;
|
||||
GSList *tmp_list;
|
||||
|
||||
g_return_val_if_fail (GTK_IS_FILE_SYSTEM (file_system), NULL);
|
||||
|
||||
@ -686,6 +690,16 @@ model_refilter_recurse (GtkFileSystemModel *model,
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
model_refilter_all (GtkFileSystemModel *model)
|
||||
{
|
||||
GtkTreePath *path;
|
||||
|
||||
path = gtk_tree_path_new ();
|
||||
model_refilter_recurse (model, NULL, path);
|
||||
gtk_tree_path_free (path);
|
||||
}
|
||||
|
||||
/**
|
||||
* _gtk_file_system_model_set_show_hidden:
|
||||
* @model: a #GtkFileSystemModel
|
||||
@ -702,13 +716,8 @@ _gtk_file_system_model_set_show_hidden (GtkFileSystemModel *model,
|
||||
|
||||
if (show_hidden != model->show_hidden)
|
||||
{
|
||||
GtkTreePath *path;
|
||||
|
||||
model->show_hidden = show_hidden;
|
||||
|
||||
path = gtk_tree_path_new ();
|
||||
model_refilter_recurse (model, NULL, path);
|
||||
gtk_tree_path_free (path);
|
||||
model_refilter_all (model);
|
||||
}
|
||||
}
|
||||
|
||||
@ -728,13 +737,8 @@ _gtk_file_system_model_set_show_folders (GtkFileSystemModel *model,
|
||||
|
||||
if (show_folders != model->show_folders)
|
||||
{
|
||||
GtkTreePath *path;
|
||||
|
||||
model->show_folders = show_folders;
|
||||
|
||||
path = gtk_tree_path_new ();
|
||||
model_refilter_recurse (model, NULL, path);
|
||||
gtk_tree_path_free (path);
|
||||
model_refilter_all (model);
|
||||
}
|
||||
}
|
||||
|
||||
@ -755,13 +759,8 @@ _gtk_file_system_model_set_show_files (GtkFileSystemModel *model,
|
||||
|
||||
if (show_files != model->show_files)
|
||||
{
|
||||
GtkTreePath *path;
|
||||
|
||||
model->show_files = show_files;
|
||||
|
||||
path = gtk_tree_path_new ();
|
||||
model_refilter_recurse (model, NULL, path);
|
||||
gtk_tree_path_free (path);
|
||||
model_refilter_all (model);
|
||||
}
|
||||
}
|
||||
|
||||
@ -897,6 +896,29 @@ find_and_ref_path (GtkFileSystemModel *model,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* _gtk_file_system_model_set_filter:
|
||||
* @mode: a #GtkFileSystemModel
|
||||
* @filter: function to be called for each file
|
||||
* @user_data: data to pass to @filter
|
||||
*
|
||||
* Sets a callback called for each file/directory to see whether
|
||||
* it should be included in model. If this function was made
|
||||
* public, we'd want to include a GDestroyNotify as well.
|
||||
**/
|
||||
void
|
||||
_gtk_file_system_model_set_filter (GtkFileSystemModel *model,
|
||||
GtkFileSystemModelFilter filter,
|
||||
gpointer user_data)
|
||||
{
|
||||
g_return_if_fail (GTK_IS_FILE_SYSTEM_MODEL (model));
|
||||
|
||||
model->filter_func = filter;
|
||||
model->filter_data = user_data;
|
||||
|
||||
model_refilter_all (model);
|
||||
}
|
||||
|
||||
/**
|
||||
* _gtk_file_system_model_path_do:
|
||||
* @model: a #GtkFileSystemModel
|
||||
@ -1024,6 +1046,8 @@ file_model_node_is_visible (GtkFileSystemModel *model,
|
||||
return FALSE;
|
||||
if (!model->show_hidden && gtk_file_info_get_is_hidden (info))
|
||||
return FALSE;
|
||||
if (model->filter_func && !model->filter_func (model, node->path, info, model->filter_data))
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
@ -56,6 +56,14 @@ void _gtk_file_system_model_set_show_folders (GtkFileSystemModel
|
||||
void _gtk_file_system_model_set_show_files (GtkFileSystemModel *model,
|
||||
gboolean show_files);
|
||||
|
||||
typedef gboolean (*GtkFileSystemModelFilter) (GtkFileSystemModel *model,
|
||||
GtkFilePath *path,
|
||||
const GtkFileInfo *info,
|
||||
gpointer user_data);
|
||||
|
||||
void _gtk_file_system_model_set_filter (GtkFileSystemModel *model,
|
||||
GtkFileSystemModelFilter filter,
|
||||
gpointer user_data);
|
||||
|
||||
typedef void (*GtkFileSystemModelPathFunc) (GtkFileSystemModel *model,
|
||||
GtkTreePath *path,
|
||||
|
@ -1,3 +1,5 @@
|
||||
#include <string.h>
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
#include "gtkfilechooserdialog.h"
|
||||
#include "gtkfilechooser.h"
|
||||
@ -43,6 +45,17 @@ response_cb (GtkDialog *dialog,
|
||||
gtk_main_quit ();
|
||||
}
|
||||
|
||||
static gboolean
|
||||
no_backup_files_filter (const GtkFileFilterInfo *filter_info,
|
||||
gpointer data)
|
||||
{
|
||||
gsize len = strlen (filter_info->display_name);
|
||||
if (len > 0 && filter_info->display_name[len - 1] == '~')
|
||||
return 0;
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
@ -52,6 +65,7 @@ main (int argc, char **argv)
|
||||
GtkWidget *dialog;
|
||||
GtkWidget *prop_editor;
|
||||
GtkFileSystem *file_system;
|
||||
GtkFileFilter *filter;
|
||||
|
||||
gtk_init (&argc, &argv);
|
||||
|
||||
@ -79,9 +93,32 @@ main (int argc, char **argv)
|
||||
G_CALLBACK (print_current_folder), NULL);
|
||||
g_signal_connect (dialog, "response",
|
||||
G_CALLBACK (response_cb), NULL);
|
||||
|
||||
/* Filters */
|
||||
filter = gtk_file_filter_new ();
|
||||
gtk_file_filter_set_name (filter, "All Files");
|
||||
gtk_file_filter_add_pattern (filter, "*");
|
||||
gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
|
||||
|
||||
filter = gtk_file_filter_new ();
|
||||
gtk_file_filter_set_name (filter, "No backup files");
|
||||
gtk_file_filter_add_custom (filter, GTK_FILE_FILTER_DISPLAY_NAME,
|
||||
no_backup_files_filter, NULL, NULL);
|
||||
gtk_file_filter_add_mime_type (filter, "image/png");
|
||||
gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
|
||||
|
||||
/* Make this filter the default */
|
||||
gtk_file_chooser_set_filter (GTK_FILE_CHOOSER (dialog), filter);
|
||||
|
||||
filter = gtk_file_filter_new ();
|
||||
gtk_file_filter_set_name (filter, "PNG and JPEG");
|
||||
gtk_file_filter_add_mime_type (filter, "image/jpeg");
|
||||
gtk_file_filter_add_mime_type (filter, "image/png");
|
||||
gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
|
||||
|
||||
gtk_window_set_default_size (GTK_WINDOW (dialog), 600, 400);
|
||||
gtk_widget_show (dialog);
|
||||
/* show_all() to reveal bugs in composite widget handling */
|
||||
gtk_widget_show_all (dialog);
|
||||
|
||||
prop_editor = create_prop_editor (G_OBJECT (dialog), GTK_TYPE_FILE_CHOOSER);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user