~ubuntu-branches/ubuntu/natty/bluefish/natty-proposed

« back to all changes in this revision

Viewing changes to src/filefilter.c

  • Committer: Bazaar Package Importer
  • Author(s): Daniel Leidert (dale)
  • Date: 2010-06-29 21:40:10 UTC
  • mfrom: (1.1.6 upstream) (5.1.2 sid)
  • Revision ID: james.westby@ubuntu.com-20100629214010-2oxygudqcstn3zc6
Tags: 2.0.1-1
* New upstream release - the first release of the 2.0 series for Debian
  (closes: #570731; LP: #540126). This release fixes these reported issues:
  - Better settings handling (closes: #548272).
  - Improved filebrowser (LP: #45927).
  - Improved syntax highlighting engine (LP: #108628).
  - Improved file operations (LP: #181110).
  - Translated menu descriptions (LP: #371318, #371322). The chosen menu
    name is fine.
  - Improved browser commands and handling (LP: #158891, #348408).
* Updated and adjusted packaging files.
* debian/bluefish_icon.xpm: Renamed to debian/bluefish.xpm.
* debian/bluefish.install: Adjusted.
* debian/bluefish.menu (icon): Adjusted.
* debian/bluefish-data.install, debian/bluefish-plugins.install: Added.
* debian/control: Added bluefish-data, bluefish-dbg and bluefish-plugins.
  (Build-Depends): Dropped deprecated build-dependencies libaspell-dev,
  libgnomeui-dev, libgnomevfs2-dev, libpcre3-dev and dpatch. Added intltool,
  libtool, libenchant-dev and libgucharmap2-dev.
  (Standards-Version): Bumped to 3.8.4.
  (Depends, Suggests): Adjusted. Added gvfs-backends as dependency.
* debian/copyright: Updated.
* debian/rules: Rewritten. Dropped dpatch.
  (LDFLAGS): Dropped -Wl,-z,defs because of plugins.
  (config.status:): Adjusted configure switches.
  (install): Install to debian/tmp and list missing files.
  (binary-indep): Added for bluefish-data.
  (binary-arch): Adjusted. Put debugging symbols into bluefish-dbg.
* debian/watch: Added support for RCs.
* debian/README.Debian: Dropped (useless with 2.0).
* debian/README.source: Dropped together with dpatch.
* debian/patches/: Dropped (obsolete).
* debian/reportbug/: Dropped.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Bluefish HTML Editor
 
2
 * filefilter.c - 
 
3
 *
 
4
 * Copyright (C) 2002,2003,2004,2005,2006,2007 Olivier Sessink
 
5
 *
 
6
 * This program is free software; you can redistribute it and/or modify
 
7
 * it under the terms of the GNU General Public License as published by
 
8
 * the Free Software Foundation; either version 2 of the License, or
 
9
 * (at your option) any later version.
 
10
 *
 
11
 * This program is distributed in the hope that it will be useful,
 
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
14
 * GNU General Public License for more details.
 
15
 *
 
16
 * You should have received a copy of the GNU General Public License
 
17
 * along with this program; if not, write to the Free Software
 
18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
19
 */
 
20
 
 
21
/* #define DEBUG */
 
22
 
 
23
 
 
24
#include <gtk/gtk.h>
 
25
#include <string.h>
 
26
#include <stdlib.h>
 
27
 
 
28
#include "bluefish.h"
 
29
#include "filebrowser2.h"
 
30
#include "bf_lib.h"
 
31
#include "dialog_utils.h"
 
32
#include "document.h"
 
33
#include "file.h"
 
34
#include "file_dialogs.h"
 
35
#include "gtk_easy.h"        /* destroy_disposable_menu_cb() */
 
36
#include "stringlist.h"      /* count_array() */
 
37
 
 
38
typedef struct {
 
39
        gchar *pattern;
 
40
        GPatternSpec* patspec;
 
41
} Tfilterpattern;
 
42
 
 
43
static Tfilterpattern *new_pattern(gchar *name) {
 
44
        Tfilterpattern *pat = g_new(Tfilterpattern,1);                  
 
45
        pat->pattern = g_strdup(name);
 
46
        pat->patspec = g_pattern_spec_new(name);
 
47
        return pat;
 
48
}
 
49
 
 
50
 
 
51
static GList *remove_pattern_from_list(GList *list, const gchar *pattern) {
 
52
        GList *tmplist = g_list_first(list);
 
53
        while (tmplist) {
 
54
                Tfilterpattern *pat = (Tfilterpattern *)tmplist->data;
 
55
                if (strcmp(pat->pattern, pattern)==0) {
 
56
                        g_free(pat->pattern);
 
57
                        g_pattern_spec_free(pat->patspec);
 
58
                        g_free(pat);
 
59
                        list = g_list_delete_link(list, tmplist);
 
60
                        return list;
 
61
                }
 
62
                
 
63
                tmplist = g_list_next(tmplist);
 
64
        }
 
65
        return list;
 
66
}
 
67
 
 
68
static gboolean filename_match(Tfilter *filter, const gchar *string) {
 
69
        GList *tmplist;
 
70
        guint len = strlen(string);     
 
71
        const gchar *reversed = g_utf8_strreverse(string,-1);
 
72
        for (tmplist = g_list_first(filter->patterns) ; tmplist ; tmplist = g_list_next(tmplist)) {
 
73
                if (g_pattern_match(((Tfilterpattern *)tmplist->data)->patspec,len,string,reversed))
 
74
                        return TRUE;
 
75
        }
 
76
        return FALSE;
 
77
}
 
78
 
 
79
gboolean file_visible_in_filter(Tfilter *filter, const gchar *mime_type, const gchar *filename) {
 
80
 
 
81
        if (filter)     
 
82
                return (((mime_type && GPOINTER_TO_INT(g_hash_table_lookup(filter->filetypes,mime_type))) 
 
83
                                || (filter->patterns && filename && filename_match(filter, filename))) ? filter->mode : !filter->mode);
 
84
        return TRUE;
 
85
}
 
86
 
 
87
 
 
88
Tfilter *find_filter_by_name(const gchar *name) {
 
89
        GList *tmplist = g_list_first(main_v->filefilters);
 
90
        while(tmplist) {
 
91
                Tfilter *filter = (Tfilter *)tmplist->data;
 
92
                if (strcmp(filter->name, name)==0) {
 
93
                        return filter;
 
94
                }
 
95
                tmplist = g_list_next(tmplist);
 
96
        }
 
97
        return NULL;
 
98
}
 
99
 
 
100
static GHashTable *hashtable_from_string(const gchar *mimetypes) {
 
101
        GHashTable *filetypes = g_hash_table_new_full(g_str_hash,g_str_equal,g_free,NULL);
 
102
        if (mimetypes){
 
103
                gchar **types = g_strsplit(mimetypes, ":", 127);
 
104
                gchar **type = types;
 
105
                while (*type) {
 
106
                        g_hash_table_replace(filetypes, g_strdup(*type), GINT_TO_POINTER(1));
 
107
                        type++;
 
108
                }
 
109
                g_strfreev(types);
 
110
        }
 
111
        return filetypes;
 
112
}
 
113
 
 
114
static GList *patternlist_from_string(const gchar *patterns) {
 
115
        if (patterns){
 
116
                GList *list=NULL;
 
117
                gchar **pats = g_strsplit(patterns, ":", 127);
 
118
                gchar **pattern = pats;
 
119
                while (*pattern) {
 
120
                        /* do something */
 
121
                        if (strlen(*pattern)>0) {
 
122
                                list = g_list_append(list, new_pattern(*pattern));
 
123
                        } 
 
124
                        pattern++;
 
125
                }
 
126
                g_strfreev(pats);
 
127
                return list;
 
128
        }
 
129
        return NULL;
 
130
}
 
131
 
 
132
static Tfilter *new_filter(const gchar *name, const gchar *mode, const gchar *mimetypes, const gchar *patterns) {
 
133
        Tfilter *filter = g_new(Tfilter,1);
 
134
        filter->name = g_strdup(name);
 
135
        filter->refcount = 1;
 
136
        filter->mode = atoi(mode);
 
137
        filter->filetypes = hashtable_from_string(mimetypes);
 
138
        filter->patterns = patternlist_from_string(patterns);
 
139
        return filter;
 
140
}
 
141
 
 
142
static void filter_destroy(Tfilter *filter) {
 
143
        GList *tmplist;
 
144
        g_free(filter->name);
 
145
        g_hash_table_destroy(filter->filetypes);
 
146
        for (tmplist=g_list_first(filter->patterns);tmplist;tmplist=g_list_next(tmplist)) {
 
147
                Tfilterpattern *pat = tmplist->data;
 
148
                g_pattern_spec_free(pat->patspec);
 
149
                g_free(pat->pattern);
 
150
        }
 
151
        g_list_free(filter->patterns);
 
152
        g_free(filter);
 
153
}
 
154
 
 
155
void filter_unref(Tfilter *filter) {
 
156
        filter->refcount++;
 
157
        if (filter->refcount <= 0) {
 
158
                filter_destroy(filter);
 
159
        }
 
160
}
 
161
 
 
162
void filter_ref(Tfilter *filter) {
 
163
        filter->refcount++;
 
164
}
 
165
 
 
166
void filter_delete(Tfilter *filter) {
 
167
        GList *tmplist;
 
168
        gchar **strarr;
 
169
        /* delete from config */
 
170
        tmplist = g_list_first(main_v->globses.filefilters);
 
171
        while (tmplist) {
 
172
                strarr = (gchar **) tmplist->data;
 
173
                if (strarr && strcmp(strarr[0],filter->name)==0) {
 
174
                        /* config string found */
 
175
                        main_v->globses.filefilters = g_list_remove(main_v->globses.filefilters, strarr);
 
176
                        break;
 
177
                }
 
178
                tmplist = g_list_next(tmplist);
 
179
        }
 
180
        /* delete from current list of filters, but we need to 
 
181
        make sure no window is actually using this filter! */
 
182
        tmplist = g_list_first(main_v->bfwinlist);
 
183
        while (tmplist) {
 
184
                Tbfwin *bfwin = BFWIN(tmplist->data);
 
185
                /* test if the filter is named in the current session */
 
186
                if (bfwin->session->last_filefilter && strcmp(bfwin->session->last_filefilter,filter->name)==0) {
 
187
                        g_free(bfwin->session->last_filefilter);
 
188
                        bfwin->session->last_filefilter = NULL;
 
189
                }
 
190
                if (bfwin->fb2) {
 
191
                        fb2_unset_filter(bfwin, filter);
 
192
                }
 
193
                tmplist = g_list_next(tmplist);
 
194
        }
 
195
        /* now really remove the filter */
 
196
        main_v->filefilters = g_list_remove(main_v->filefilters, filter);
 
197
        filter_unref(filter);
 
198
}
 
199
 
 
200
/* 
 
201
 * WARNING: these filter are also used in the filechooser dialog (file->open in the menu)
 
202
 */
 
203
void filters_rebuild(void) {
 
204
        GList *tmplist;
 
205
        /* free any existing filters */
 
206
        tmplist = g_list_first(main_v->filefilters);
 
207
        while (tmplist) {
 
208
                filter_unref(tmplist->data);
 
209
                tmplist = g_list_next(tmplist);
 
210
        }
 
211
        g_list_free(main_v->filefilters);
 
212
        main_v->filefilters = NULL;
 
213
 
 
214
        /* build a list of filters */
 
215
        main_v->filefilters = g_list_prepend(NULL, new_filter(_("All files"), "0", NULL, NULL));
 
216
        tmplist = g_list_first(main_v->globses.filefilters);
 
217
        while (tmplist) {
 
218
                gchar **strarr = (gchar **) tmplist->data;
 
219
                Tfilter *filter = new_filter(strarr[0], strarr[1], strarr[2], strarr[3]);
 
220
                main_v->filefilters = g_list_prepend(main_v->filefilters, filter);
 
221
                tmplist = g_list_next(tmplist);
 
222
        }
 
223
}
 
224
 
 
225
static void restore_filter_from_config(Tfilter *filter, const gchar *origname) {
 
226
        GList *tmplist;
 
227
        gchar **strarr=NULL;
 
228
        gint mode;
 
229
        
 
230
        if (!origname) return;
 
231
        
 
232
        tmplist = g_list_first(main_v->globses.filefilters);
 
233
        while (tmplist) {
 
234
                strarr = (gchar **) tmplist->data;
 
235
                if (strarr && strcmp(strarr[0],origname)==0) {
 
236
                        /* config string found */
 
237
                        break;
 
238
                }
 
239
                tmplist = g_list_next(tmplist);
 
240
        }
 
241
        if (!strarr) return;
 
242
        
 
243
        if (strcmp(filter->name,origname)!=0) {
 
244
                g_free(filter->name);
 
245
                filter->name = g_strdup(origname);
 
246
        }
 
247
        mode = atoi(strarr[1]);
 
248
        if (mode != filter->mode) {
 
249
                filter->mode = mode;
 
250
        }
 
251
        
 
252
        g_hash_table_destroy(filter->filetypes);
 
253
        filter->filetypes = hashtable_from_string(strarr[2]);
 
254
        filter->patterns =  patternlist_from_string(strarr[3]);
 
255
}
 
256
 
 
257
static void hashtable_to_string_lcb(gpointer key, gpointer value, gpointer data) {
 
258
        g_string_append((GString *)data, (gchar *)key);
 
259
        g_string_append_c((GString *)data,':');
 
260
}
 
261
 
 
262
static void apply_filter_to_config(Tfilter *filter, const gchar *origname) {
 
263
        GList *tmplist;
 
264
        gchar **strarr = NULL;
 
265
        GString *gstr;
 
266
        if (origname) {
 
267
                /* find the config string, if it existed before */
 
268
                tmplist = g_list_first(main_v->globses.filefilters);
 
269
                while (tmplist) {
 
270
                        strarr = (gchar **) tmplist->data;
 
271
                        if (strarr && strcmp(strarr[0],origname)==0) {
 
272
                                /* config string found */
 
273
                                break;
 
274
                        }
 
275
                        tmplist = g_list_next(tmplist);
 
276
                }
 
277
        }
 
278
        if (strarr == NULL) {
 
279
                DEBUG_MSG("apply_filter_to_config, prepending new entry in config list\n");
 
280
                /* no config string with this name, */
 
281
                strarr = (gchar **)g_new0(gpointer, 5);
 
282
                main_v->globses.filefilters = g_list_prepend(main_v->globses.filefilters, strarr);
 
283
        }
 
284
        if (origname == NULL) {
 
285
                main_v->filefilters = g_list_prepend(main_v->filefilters, filter);
 
286
        }
 
287
        /* the config string has three entries: the name, inverse filtering, filetypes */
 
288
        if (strarr[0]) g_free(strarr[0]);
 
289
        strarr[0] = g_strdup(filter->name);
 
290
        if (strarr[1]) g_free(strarr[1]);
 
291
        strarr[1] = g_strdup_printf("%d",filter->mode);
 
292
        gstr = g_string_new("");
 
293
        g_hash_table_foreach(filter->filetypes,hashtable_to_string_lcb,gstr);
 
294
        if (strarr[2]) g_free(strarr[2]);
 
295
        strarr[2] = g_string_free(gstr,FALSE);
 
296
        if (strarr[3]) g_free(strarr[3]);
 
297
        gstr = g_string_new("");
 
298
        {
 
299
                GList *tmplist;
 
300
                for (tmplist = g_list_first(filter->patterns) ; tmplist ; tmplist = g_list_next(tmplist)) {
 
301
                        Tfilterpattern *pat = tmplist->data;
 
302
                        g_string_append(gstr, pat->pattern);
 
303
                        g_string_append_c(gstr,':');
 
304
                }
 
305
                strarr[3] = g_string_free(gstr,FALSE);
 
306
        }
 
307
}
 
308
 
 
309
/*
 
310
the filefilter gui has one listmodel with all filetypes currently known in bluefish, 
 
311
and two filtermodels, in_model shows all types in the filter, out_model shows all other filetypes
 
312
and two treeviews.
 
313
 
 
314
*/
 
315
 
 
316
typedef struct {
 
317
        GtkWidget *win;
 
318
        GtkListStore *lstore;
 
319
        GtkTreeModel *in_model; /* shows all the types IN the filter */
 
320
        GtkTreeModel *out_model; /* shows all types OUTside the filter */
 
321
        GtkWidget *in_view;
 
322
        GtkWidget *out_view;
 
323
        GtkWidget *nameentry;
 
324
        GtkWidget *inversecheck;
 
325
        GtkWidget *patentry;
 
326
        
 
327
        Tfilter *curfilter;
 
328
        gchar *origname;
 
329
} Tfilefiltergui;
 
330
 
 
331
static void filefiltergui_destroy_lcb(GtkWidget *widget, Tfilefiltergui *ffg) {
 
332
        g_free(ffg->origname);
 
333
        g_object_unref(ffg->lstore);
 
334
        window_destroy(ffg->win);
 
335
        g_free(ffg);
 
336
        DEBUG_MSG("filefiltergui_destroy_lcb, done\n"); 
 
337
}
 
338
 
 
339
static void filefiltergui_cancel_clicked(GtkWidget *widget, Tfilefiltergui *ffg) {
 
340
        restore_filter_from_config(ffg->curfilter, ffg->origname);
 
341
        filefiltergui_destroy_lcb(widget, ffg);
 
342
}
 
343
 
 
344
static void filefiltergui_ok_clicked(GtkWidget *widget, Tfilefiltergui *ffg) {
 
345
        g_free(ffg->curfilter->name);
 
346
        ffg->curfilter->name = gtk_editable_get_chars(GTK_EDITABLE(ffg->nameentry),0,-1);
 
347
        ffg->curfilter->mode = !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ffg->inversecheck));
 
348
        DEBUG_MSG("filefiltergui_ok_clicked, filter '%s' has mode %d\n",ffg->curfilter->name,ffg->curfilter->mode);
 
349
        apply_filter_to_config(ffg->curfilter, ffg->origname);
 
350
        filefiltergui_destroy_lcb(widget, ffg);
 
351
}
 
352
 
 
353
static gboolean filefiltergui_infilter_visiblefunc(GtkTreeModel *model,GtkTreeIter *iter,gpointer data) {
 
354
        Tfilefiltergui *ffg = data;
 
355
        gboolean retval = FALSE;
 
356
        gboolean type;
 
357
        gchar *name=NULL;
 
358
        gtk_tree_model_get(model, iter, 0, &name, 2, &type, -1);
 
359
        if (name) {
 
360
                if (type == 0) {
 
361
                        retval = (g_hash_table_lookup(ffg->curfilter->filetypes, name) != NULL);
 
362
                } else { /* type == 1*/
 
363
                        GList *tmplist;
 
364
                        for (tmplist = g_list_first(ffg->curfilter->patterns) ; tmplist ; tmplist = g_list_next(tmplist)) {
 
365
                                Tfilterpattern *pat = tmplist->data;
 
366
                                if (strcmp(pat->pattern, name)==0) {
 
367
                                        retval = TRUE;
 
368
                                        break;
 
369
                                }
 
370
                        }
 
371
                }
 
372
                g_free(name);
 
373
        }
 
374
        return retval;
 
375
}
 
376
static gboolean filefiltergui_outfilter_visiblefunc(GtkTreeModel *model,GtkTreeIter *iter,gpointer data) {
 
377
        return !filefiltergui_infilter_visiblefunc(model,iter,data);
 
378
}
 
379
/*
 
380
static void filefiltergui_add_filetypes(gpointer key,gpointer value,gpointer data) {
 
381
        Tfilefiltergui *ffg = data;
 
382
        
 
383
        if (strlen(key)>0 && g_hash_table_lookup(main_v->filetypetable, key) == NULL) {
 
384
                GtkTreeIter it;
 
385
                gtk_list_store_prepend(ffg->lstore,&it);
 
386
                gtk_list_store_set(ffg->lstore,&it,0,key,2,0,-1);
 
387
        }
 
388
}
 
389
*/
 
390
static void filefiltergui_2right_clicked(GtkWidget *widget, Tfilefiltergui *ffg) {
 
391
        GtkTreeIter iter;
 
392
        GtkTreeSelection *select;
 
393
        GtkTreeModel *model;
 
394
 
 
395
        /* get the selection */
 
396
        select = gtk_tree_view_get_selection(GTK_TREE_VIEW(ffg->out_view));
 
397
        if (gtk_tree_selection_get_selected(select, &model, &iter)) {
 
398
                gchar *name;
 
399
                gint type;
 
400
                gtk_tree_model_get(model, &iter, 0, &name, 2, &type, -1);
 
401
                /* add the selection to the filter */
 
402
                DEBUG_MSG("filefiltergui_2right_clicked, adding %s\n",name);
 
403
                if (type == 0) {
 
404
                        g_hash_table_replace(ffg->curfilter->filetypes, name, GINT_TO_POINTER(1));
 
405
                } else {
 
406
                        ffg->curfilter->patterns = g_list_append(ffg->curfilter->patterns, new_pattern(name));
 
407
                }
 
408
 
 
409
                DEBUG_MSG("filefiltergui_2right_clicked, refilter\n");
 
410
                /* refilter */
 
411
                gtk_tree_model_filter_refilter(GTK_TREE_MODEL_FILTER(ffg->in_model));
 
412
                gtk_tree_model_filter_refilter(GTK_TREE_MODEL_FILTER(ffg->out_model));
 
413
        } else {
 
414
                DEBUG_MSG("filefiltergui_2right_clicked, nothing selected\n");
 
415
        }
 
416
}
 
417
 
 
418
static void filefiltergui_2left_clicked(GtkWidget *widget, Tfilefiltergui *ffg) {
 
419
        GtkTreeIter iter;
 
420
        GtkTreeSelection *select;
 
421
        GtkTreeModel *model;
 
422
 
 
423
        /* get the selection */
 
424
        select = gtk_tree_view_get_selection(GTK_TREE_VIEW (ffg->in_view));
 
425
        if (gtk_tree_selection_get_selected(select, &model, &iter)) {
 
426
                gchar *name;
 
427
                gboolean type;
 
428
                gtk_tree_model_get(model, &iter, 0, &name,2,&type, -1);
 
429
                /* add the selection to the filter */
 
430
                if (type == 0) {
 
431
                        DEBUG_MSG("filefiltergui_2left_clicked, removing %s\n",name);
 
432
                        g_hash_table_remove(ffg->curfilter->filetypes, name);
 
433
                } else {
 
434
                        /* remove from the list of the filter */
 
435
                        ffg->curfilter->patterns = remove_pattern_from_list(ffg->curfilter->patterns, name);
 
436
                }
 
437
                g_free (name);
 
438
                DEBUG_MSG("filefiltergui_2left_clicked, refilter\n");
 
439
                /* refilter */
 
440
                gtk_tree_model_filter_refilter(GTK_TREE_MODEL_FILTER(ffg->in_model));
 
441
                gtk_tree_model_filter_refilter(GTK_TREE_MODEL_FILTER(ffg->out_model));
 
442
        } else {
 
443
                DEBUG_MSG("filefiltergui_2left_clicked, nothing selected\n");
 
444
        }
 
445
}
 
446
 
 
447
static void filefiltergui_addpattern_clicked_lcb(GtkWidget *widget, Tfilefiltergui *ffg) {
 
448
        Tfilterpattern *pat;
 
449
        GtkTreeIter it;
 
450
        pat = g_new(Tfilterpattern,1);
 
451
        pat->pattern = g_strdup(gtk_entry_get_text(GTK_ENTRY(ffg->patentry)));
 
452
        pat->patspec = g_pattern_spec_new(pat->pattern);
 
453
        ffg->curfilter->patterns = g_list_append(ffg->curfilter->patterns, pat);
 
454
        gtk_list_store_prepend(ffg->lstore,&it);
 
455
        gtk_list_store_set(ffg->lstore,&it,0,pat->pattern,1,NULL,2,1,-1);
 
456
}
 
457
 
 
458
void filefilter_gui(Tfilter *filter) {
 
459
        GtkCellRenderer *renderer;
 
460
        GtkTreeViewColumn *column;
 
461
        GList *tmplist, *reglist;
 
462
        GtkWidget *table,*hbox,*but,*vbox,*scrolwin;
 
463
#ifdef WIN32
 
464
        GList *mimelist=NULL;
 
465
        gchar *last_mime=NULL;
 
466
#endif
 
467
 
 
468
        Tfilefiltergui *ffg = g_new0(Tfilefiltergui,1);
 
469
        ffg->curfilter = filter;
 
470
        if (filter) {
 
471
                ffg->origname = g_strdup(filter->name);
 
472
        }
 
473
        if (!filter) {
 
474
                ffg->curfilter = g_new0(Tfilter,1);
 
475
                ffg->curfilter->name = g_strdup(_("New filter"));
 
476
                ffg->curfilter->filetypes = g_hash_table_new_full(g_str_hash,g_str_equal,g_free,NULL);
 
477
        }
 
478
        
 
479
        DEBUG_MSG("filefilter_gui, editing filter %p\n",ffg->curfilter); 
 
480
        ffg->win = window_full2(_("Edit filter"), GTK_WIN_POS_MOUSE, 10, G_CALLBACK(filefiltergui_destroy_lcb),ffg, TRUE, NULL);
 
481
        gtk_window_set_default_size(GTK_WINDOW(ffg->win),400,400);
 
482
        ffg->lstore = gtk_list_store_new(3, G_TYPE_STRING, GDK_TYPE_PIXBUF, G_TYPE_BOOLEAN);
 
483
        
 
484
        /* fill the list model from the currently known filetypes */
 
485
        reglist = g_content_types_get_registered();
 
486
 
 
487
#ifdef WIN32
 
488
        tmplist = g_list_first(reglist);
 
489
        while (tmplist) {
 
490
                mimelist = g_list_prepend(mimelist, g_content_type_get_mime_type(tmplist->data));
 
491
                tmplist = g_list_next(tmplist);
 
492
        }
 
493
        mimelist = g_list_reverse(g_list_sort(mimelist, (GCompareFunc) g_strcmp0));
 
494
        tmplist = g_list_first(mimelist);
 
495
        while (tmplist) {
 
496
                if (!last_mime || g_strcmp0(last_mime, tmplist->data)!=0) {
 
497
                        GtkTreeIter it;
 
498
                        last_mime=tmplist->data;
 
499
                        if (MIME_ISDIR(tmplist->data)) {
 
500
                                gtk_list_store_prepend(ffg->lstore,&it);
 
501
                                gtk_list_store_set(ffg->lstore,&it,0,tmplist->data,2,0, -1);
 
502
                        }
 
503
                }
 
504
                tmplist = g_list_next(tmplist);
 
505
        }
 
506
/*      GList *winlist = NULL;
 
507
        gchar *mimetype;
 
508
        gint llen, lpos;
 
509
        while(reglist) {
 
510
                mimetype = g_content_type_get_mime_type(reglist->data);
 
511
                if ((llen = g_list_length(winlist))) {
 
512
                        tmplist = g_list_copy(winlist);
 
513
                        for (lpos = 0; llen != -1 && lpos < llen; lpos++) {
 
514
                                if (!g_strcmp0(mimetype, tmplist->data))
 
515
                                        llen = -1;
 
516
                                else
 
517
                                        tmplist = g_list_next(tmplist);
 
518
                        }
 
519
                        g_list_free(tmplist);
 
520
                }
 
521
                if (llen != -1)
 
522
                        winlist = g_list_append(winlist, mimetype);
 
523
                reglist = g_list_next(reglist);
 
524
        }
 
525
        tmplist = g_list_first(g_list_reverse(g_list_sort(winlist, (GCompareFunc) g_strcmp0)));*/
 
526
        free_stringlist(mimelist);
 
527
#else
 
528
        tmplist = g_list_first(g_list_sort(reglist, (GCompareFunc) g_strcmp0)); 
 
529
        while (tmplist) {
 
530
                GtkTreeIter it;
 
531
                if (MIME_ISDIR(tmplist->data)) {
 
532
                        gtk_list_store_prepend(ffg->lstore,&it);
 
533
                        gtk_list_store_set(ffg->lstore,&it,0,tmplist->data,2,0, -1);
 
534
                }
 
535
                tmplist = g_list_next(tmplist);
 
536
        }
 
537
#endif
 
538
        g_list_free(reglist);
 
539
        /* make sure that all filetypes that exist in the current filter are shown */
 
540
        /*g_hash_table_foreach(ffg->curfilter->filetypes,filefiltergui_add_filetypes,ffg);*/
 
541
        /* add the patterns from the current filter */
 
542
        tmplist = g_list_first(ffg->curfilter->patterns);
 
543
        while (tmplist) {
 
544
                GtkTreeIter it;
 
545
                Tfilterpattern *pat = (Tfilterpattern *)tmplist->data;
 
546
                gtk_list_store_prepend(ffg->lstore,&it);
 
547
                gtk_list_store_set(ffg->lstore,&it,0,pat->pattern,1,NULL,2,1,-1);
 
548
                tmplist = g_list_next(tmplist);
 
549
        }
 
550
        
 
551
        ffg->in_model = gtk_tree_model_filter_new(GTK_TREE_MODEL(ffg->lstore), NULL);
 
552
        gtk_tree_model_filter_set_visible_func(GTK_TREE_MODEL_FILTER(ffg->in_model),filefiltergui_infilter_visiblefunc,ffg,NULL);
 
553
        ffg->out_model = gtk_tree_model_filter_new(GTK_TREE_MODEL(ffg->lstore), NULL);
 
554
        gtk_tree_model_filter_set_visible_func(GTK_TREE_MODEL_FILTER(ffg->out_model),filefiltergui_outfilter_visiblefunc,ffg,NULL);
 
555
 
 
556
        table = gtk_table_new(5,4,FALSE);
 
557
        gtk_table_set_row_spacings(GTK_TABLE(table), 5);
 
558
        
 
559
        ffg->nameentry = entry_with_text(ffg->curfilter->name, 50);
 
560
        gtk_table_attach(GTK_TABLE(table),ffg->nameentry,0,1,0,1,GTK_FILL,GTK_FILL,0,0);
 
561
        
 
562
        ffg->inversecheck = checkbut_with_value(_("Hide files that match the filter"), !ffg->curfilter->mode);
 
563
        gtk_table_attach(GTK_TABLE(table),ffg->inversecheck,0,1,1,2,GTK_FILL,GTK_FILL,0,0);
 
564
        
 
565
        ffg->patentry = entry_with_text("*.*", 20);
 
566
        gtk_table_attach(GTK_TABLE(table),ffg->patentry,2,3,1,2,GTK_FILL,GTK_FILL,0,0);
 
567
        but = gtk_button_new_with_label(_("Add pattern"));
 
568
        g_signal_connect(but,"clicked",G_CALLBACK(filefiltergui_addpattern_clicked_lcb),ffg);
 
569
        gtk_table_attach(GTK_TABLE(table),but,3,4,1,2,GTK_FILL,GTK_FILL,0,0);
 
570
        
 
571
        ffg->in_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(ffg->in_model));
 
572
        renderer = gtk_cell_renderer_text_new();
 
573
        column = gtk_tree_view_column_new_with_attributes(_("Mime type"),renderer,"text", 0,NULL);
 
574
        gtk_tree_view_append_column (GTK_TREE_VIEW(ffg->in_view), column);
 
575
        renderer = gtk_cell_renderer_pixbuf_new();
 
576
        column = gtk_tree_view_column_new_with_attributes(_("Icon"),renderer,"pixbuf", 1,NULL);
 
577
        gtk_tree_view_append_column (GTK_TREE_VIEW(ffg->in_view), column);
 
578
        scrolwin =      gtk_scrolled_window_new(NULL, NULL);
 
579
        gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolwin), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
 
580
        gtk_container_add(GTK_CONTAINER(scrolwin),ffg->in_view);
 
581
        gtk_table_attach_defaults(GTK_TABLE(table),scrolwin,2,4,2,3);
 
582
        
 
583
        ffg->out_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(ffg->out_model));
 
584
        renderer = gtk_cell_renderer_text_new();
 
585
        column = gtk_tree_view_column_new_with_attributes(_("Mime type"),renderer,"text", 0,NULL);
 
586
        gtk_tree_view_append_column (GTK_TREE_VIEW(ffg->out_view), column);
 
587
        renderer = gtk_cell_renderer_pixbuf_new();
 
588
        column = gtk_tree_view_column_new_with_attributes(_("Icon"),renderer,"pixbuf", 1,NULL);
 
589
        gtk_tree_view_append_column (GTK_TREE_VIEW(ffg->out_view), column);
 
590
        scrolwin = gtk_scrolled_window_new(NULL, NULL);
 
591
        gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolwin), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
 
592
        gtk_container_add(GTK_CONTAINER(scrolwin),ffg->out_view);
 
593
        gtk_table_attach_defaults(GTK_TABLE(table),scrolwin,0,1,2,3);
 
594
        
 
595
        vbox = gtk_vbox_new(TRUE,5);
 
596
        but = gtk_button_new_with_label("->");
 
597
        g_signal_connect(but,"clicked",G_CALLBACK(filefiltergui_2right_clicked),ffg);
 
598
        gtk_box_pack_start(GTK_BOX(vbox),but,TRUE,TRUE,0);
 
599
        but = gtk_button_new_with_label("<-");
 
600
        g_signal_connect(but,"clicked",G_CALLBACK(filefiltergui_2left_clicked),ffg);
 
601
        gtk_box_pack_start(GTK_BOX(vbox),but,TRUE,TRUE,0);
 
602
        gtk_table_attach(GTK_TABLE(table),vbox,1,2,2,3,GTK_EXPAND|GTK_FILL,GTK_EXPAND,5,5);
 
603
        
 
604
        hbox = gtk_hbutton_box_new();
 
605
        gtk_hbutton_box_set_layout_default(GTK_BUTTONBOX_END);
 
606
        gtk_button_box_set_spacing(GTK_BUTTON_BOX(hbox), 12);
 
607
        but = bf_stock_cancel_button(G_CALLBACK(filefiltergui_cancel_clicked), ffg);
 
608
   gtk_box_pack_start(GTK_BOX(hbox),but, FALSE, FALSE, 0);      
 
609
        but = bf_stock_ok_button(G_CALLBACK(filefiltergui_ok_clicked), ffg);
 
610
        gtk_box_pack_start(GTK_BOX(hbox),but, FALSE, FALSE, 0);
 
611
        
 
612
        gtk_table_attach(GTK_TABLE(table), hbox, 0, 3, 4, 5,GTK_FILL,GTK_FILL,0,0);
 
613
 
 
614
        gtk_container_add(GTK_CONTAINER(ffg->win), table);
 
615
        gtk_widget_show_all(ffg->win);  
 
616
}