1 /* -*- Mode: C; tab-width: 3; indent-tabs-mode: nil; c-basic-offset: 3 -*- */
2 
3 /*
4  * GImageView
5  * Copyright (C) 2001 Takuro Ashie
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20  *
21  * $Id: gimv_prefs_win.c,v 1.8 2004/09/22 15:37:11 makeinu Exp $
22  */
23 
24 #include "gimv_prefs_win.h"
25 
26 #include <stdlib.h>
27 #include <string.h>
28 
29 #include "gimageview.h"
30 
31 #include "gimv_hpaned.h"
32 #include "gtk2-compat.h"
33 #include "gimv_cell_pixmap.h"
34 #include "gimv_icon_stock.h"
35 #include "help.h"
36 #include "prefs.h"
37 #include "prefs_ui/prefs_ui_common.h"
38 #include "prefs_ui/prefs_ui_etc.h"
39 #include "prefs_ui/prefs_ui_movie.h"
40 #include "prefs_ui/prefs_ui_plugin.h"
41 #include "prefs_ui/prefs_ui_progs.h"
42 #include "prefs_ui/prefs_ui_imagewin.h"
43 #include "prefs_ui/prefs_ui_thumbalbum.h"
44 #include "prefs_ui/prefs_ui_thumbwin.h"
45 
46 
47 typedef struct PrefsWin_Tag {
48    GtkWidget *notebook;
49    GtkWidget *tree;
50    gboolean   ok_pressed;
51 } PrefsWin;
52 
53 
54 typedef struct GimvPrefsWinPagePrivate_Tag
55 {
56    GimvPrefsWinPage *page;
57    GtkWidget    *widget;
58 #ifndef ENABLE_TREEVIEW
59    GtkCTreeNode *node;
60 #endif /* ENABLE_TREEVIEW */
61 } GimvPrefsWinPagePrivate;
62 
63 
64 static GimvPrefsWinPage prefs_pages[] = {
65    {N_("/Infomation"),                 0, NULL, NULL, gimvhelp_create_info_widget,  NULL},
66    {N_("/Common"),                     0, NULL, NULL, prefs_common_page,            NULL},
67    {N_("/Common/Filtering"),           0, NULL, NULL, prefs_filter_page,            prefs_filter_apply},
68    {N_("/Common/Character set"),       0, NULL, NULL, prefs_charset_page,           prefs_charset_apply},
69 
70    {N_("/Image Window"),               0, NULL, NULL, prefs_imagewin_page,          NULL},
71    {N_("/Image Window/Image"),         0, NULL, NULL, prefs_imagewin_image_page,    prefs_ui_imagewin_image_apply},
72    {N_("/Image Window/Mouse Buttton"), 0, NULL, NULL, prefs_imagewin_mouse_page,    NULL},
73 
74    {N_("/Thumbnail Window"),           0, NULL, NULL, prefs_thumbwin_page,          prefs_ui_thumbwin_apply},
75    /*
76    {N_("/Thumbnail Window/Toolbar"),   0, NULL, NULL, prefs_thumbview_toolbar_page, NULL},
77    */
78    {N_("/Thumbnail Window/Tab"),                            0, NULL, NULL, prefs_thumbwin_tab_page,      prefs_ui_thumbwin_tab_apply},
79    {N_("/Thumbnail Window/Thumbnail View"),                 0, NULL, NULL, prefs_thumbview_page,         NULL},
80    {N_("/Thumbnail Window/Thumbnail View/Mouse Buttton"),   0, NULL, NULL, prefs_thumbview_mouse_page,   NULL},
81    {N_("/Thumbnail Window/Thumbnail View/Album"),           0, NULL, NULL, prefs_ui_thumbalbum,          NULL},
82 
83    {N_("/Thumbnail Window/Directory View"),                 0, NULL, NULL, prefs_dirview_page,           prefs_ui_dirview_apply},
84    {N_("/Thumbnail Window/Directory View/Mouse Buttton"),   0, NULL, NULL, prefs_dirview_mouse_page,     NULL},
85    {N_("/Thumbnail Window/Preview"),                        0, NULL, NULL, prefs_preview_page,           prefs_ui_preview_apply},
86    {N_("/Thumbnail Window/Preview/Mouse Buttton"),          0, NULL, NULL, prefs_preview_mouse_page,     NULL},
87 
88    {N_("/Movie and Audio"),            0, NULL, NULL, prefs_movie_page,               NULL},
89 
90    {N_("/Slide Show"),                 0, NULL, NULL, prefs_slideshow_page,           NULL},
91    {N_("/Thumbnail Cache"),            0, NULL, NULL, prefs_cache_page,               NULL},
92    {N_("/Comment"),                    0, NULL, NULL, prefs_comment_page,             prefs_comment_apply},
93    {N_("/Search"),                     0, NULL, NULL, prefs_search_page,              NULL},
94    {N_("/Drag and Drop"),              0, NULL, NULL, prefs_dnd_page,                 NULL},
95    {N_("/External Program"),           0, NULL, NULL, prefs_progs_page,               NULL},
96    {N_("/External Program/Scripts"),   0, NULL, NULL, prefs_scripts_page,             NULL},
97 
98    {N_("/Plugin"),                     0, NULL, NULL, prefs_ui_plugin,              prefs_ui_plugin_apply},
99    {N_("/Plugin/Image Loader"),        0, NULL, NULL, prefs_ui_plugin_image_loader, NULL},
100    {N_("/Plugin/Image Saver"),         0, NULL, NULL, prefs_ui_plugin_image_saver,  NULL},
101    {N_("/Plugin/IO Stream"),           0, NULL, NULL, prefs_ui_plugin_io_stream,    NULL},
102    {N_("/Plugin/Archiver"),            0, NULL, NULL, prefs_ui_plugin_archiver,     NULL},
103    {N_("/Plugin/Thumbnail"),           0, NULL, NULL, prefs_ui_plugin_thumbnail,    NULL},
104    {N_("/Plugin/Image View"),          0, NULL, NULL, prefs_ui_plugin_imageview,    NULL},
105    {N_("/Plugin/Thumbnail View"),      0, NULL, NULL, prefs_ui_plugin_thumbview,    NULL},
106 };
107 static gint prefs_pages_num = sizeof (prefs_pages) / sizeof (prefs_pages[0]);
108 
109 GList *prefs_pages_list = NULL;
110 
111 Config *config_changed    = NULL;
112 Config *config_prechanged = NULL;
113 
114 
115 static GtkWidget *prefs_window;
116 static PrefsWin   prefs_win = {
117    notebook:   NULL,
118    tree:       NULL,
119    ok_pressed: FALSE,
120 };
121 static GList *priv_page_list = NULL;
122 
123 
124 static GList *
get_page_entries_list(void)125 get_page_entries_list (void)
126 {
127    if (!prefs_pages_list) {
128       gint i;
129 
130       for (i = 0; i < prefs_pages_num; i++)
131          prefs_pages_list = g_list_append (prefs_pages_list, &prefs_pages[i]);
132    }
133 
134    return prefs_pages_list;
135 }
136 
137 
138 gboolean
gimv_prefs_win_add_page_entry(GimvPrefsWinPage * page)139 gimv_prefs_win_add_page_entry (GimvPrefsWinPage *page)
140 {
141    g_return_val_if_fail (page, FALSE);
142 
143    get_page_entries_list ();
144 #warning FIXME: check path
145    prefs_pages_list = g_list_append (prefs_pages_list, page);
146    return TRUE;
147 }
148 
149 
150 /*******************************************************************************
151  *
152  *   Private functions
153  *
154  *******************************************************************************/
155 static void
prefs_win_apply_config(GimvPrefsWinAction action)156 prefs_win_apply_config (GimvPrefsWinAction action)
157 {
158    GList *node;
159 
160    for (node = priv_page_list; node; node = g_list_next (node)) {
161       GimvPrefsWinPagePrivate *priv = node->data;
162       if (priv && priv->widget && priv->page && priv->page->apply_fn)
163          priv->page->apply_fn (action);
164    }
165 }
166 
167 
168 /* FIXME!! too stupid ;-( */
169 /* Damn Damn Damn XD */
170 static void
prefs_win_free_strings(gboolean value_changed)171 prefs_win_free_strings (gboolean value_changed)
172 {
173    gint i;
174    gchar **strings[] = {
175       &conf.text_viewer,
176       &conf.web_browser,
177       &conf.plugin_search_dir_list,
178       &conf.scripts_search_dir_list,
179       &conf.imgview_mouse_button,
180       &conf.preview_mouse_button,
181       &conf.imgtype_disables,
182       &conf.imgtype_user_defs,
183       &conf.comment_key_list,
184       &conf.charset_locale,
185       &conf.charset_internal,
186    };
187    gint num1 = sizeof (strings) / sizeof (gchar **);
188    gint num2 = sizeof (conf.progs) / sizeof (gchar *);
189 
190    for (i = 0; i < num1 + num2; i++) {
191       gchar **src, **dest, **member;
192       gulong offset;
193 
194       if (i < num1)
195          member = strings[i];
196       else if (i < num1 + num2)
197          member = &conf.progs[i - num1];
198       else
199          break;
200 
201       offset = (gchar *) member - (gchar *) &conf;
202       src  = G_STRUCT_MEMBER_P (config_prechanged, offset);
203       dest = G_STRUCT_MEMBER_P (config_changed, offset);
204 
205       if (*src == *dest) continue;
206 
207       if (value_changed) {
208          g_free (*src);
209       } else {
210          g_free (*dest);
211       }
212    }
213 }
214 /* END FIXME!! */
215 
216 
217 static void
prefs_win_create_page(GimvPrefsWinPagePrivate * priv)218 prefs_win_create_page (GimvPrefsWinPagePrivate *priv)
219 {
220    const gchar *title = NULL;
221    GtkWidget *vbox, *label;
222 
223    if (!priv || !priv->page) return;
224    if (priv->widget) return;
225 
226    /* translate page title */
227    if (priv->page->path)
228       title = g_basename (_(priv->page->path));
229 
230    /* create page */
231    if (priv->page->create_page_fn) {
232       vbox = priv->page->create_page_fn ();
233       label = gtk_label_new (title);
234       gtk_notebook_append_page (GTK_NOTEBOOK(prefs_win.notebook),
235                                 vbox, label);
236       priv->widget = vbox;
237    }
238 }
239 
240 
241 static void
prefs_win_set_page(const gchar * path)242 prefs_win_set_page (const gchar *path)
243 {
244    GimvPrefsWinPagePrivate *priv = NULL;
245    GList *node;
246    gint num;
247 
248    if (!path || !*path) {
249       if (!priv_page_list) return;
250       priv = priv_page_list->data;
251    } else {
252       for (node = priv_page_list; node; node = g_list_next (node)) {
253          priv = node->data;
254          if (priv->page && !strcmp (path, priv->page->path))
255             break;
256          priv = NULL;
257       }
258    }
259 
260    if (!priv) {
261       if (!priv_page_list) return;
262       priv = priv_page_list->data;
263    }
264 
265    if (!priv->widget) {
266       prefs_win_create_page (priv);
267    }
268    if (priv->widget)
269       gtk_widget_show (priv->widget);
270    else
271       return;
272 
273    num = gtk_notebook_page_num (GTK_NOTEBOOK (prefs_win.notebook),
274                                 priv->widget);
275    if (num >= 0)
276       gtk_notebook_set_page (GTK_NOTEBOOK (prefs_win.notebook), num);
277 
278 #ifdef ENABLE_TREEVIEW
279 #else /* ENABLE_TREEVIEW */
280    /* gtk_ctree_select (GTK_CTREE (prefs_win.tree), priv->node); */
281 #endif /* ENABLE_TREEVIEW */
282 }
283 
284 
285 
286 /*******************************************************************************
287  *
288  *  functions for creating navigate tree
289  *
290  *******************************************************************************/
291 static void
get_icon(const gchar * name,GdkPixmap ** pixmap,GdkBitmap ** mask)292 get_icon (const gchar *name, GdkPixmap **pixmap, GdkBitmap **mask)
293 {
294    GimvIcon *icon;
295 
296    if (!name || !*name) return;
297 
298    icon  = gimv_icon_stock_get_icon (name);
299    if (icon) {
300       if (pixmap)
301          *pixmap = icon->pixmap;
302       if (mask)
303          *mask = icon->mask;
304    } else {
305       if (pixmap)
306          *pixmap = NULL;
307       if (mask)
308          *mask = NULL;
309    }
310 }
311 
312 
313 #ifdef ENABLE_TREEVIEW
314 
315 typedef enum {
316    COLUMN_TERMINATOR = -1,
317    COLUMN_ICON_OPEN,
318    COLUMN_ICON_OPEN_MASK,
319    COLUMN_ICON_CLOSE,
320    COLUMN_ICON_CLOSE_MASK,
321    COLUMN_NAME,
322    COLUMN_PRIV_DATA,
323    N_COLUMN
324 } TreeStoreColumn;
325 
326 
327 struct FindNode {
328    gchar               *path;
329    GimvPrefsWinPagePrivate *priv;
330    GtkTreeIter         iter;
331 };
332 
333 
334 static gboolean
find_node_by_path(GtkTreeModel * model,GtkTreePath * path,GtkTreeIter * iter,gpointer data)335 find_node_by_path (GtkTreeModel *model,
336                    GtkTreePath *path, GtkTreeIter *iter,
337                    gpointer data)
338 {
339    struct FindNode *node = data;
340    GimvPrefsWinPagePrivate *priv;
341 
342    gtk_tree_model_get (model, iter,
343                        COLUMN_PRIV_DATA, &priv,
344                        COLUMN_TERMINATOR);
345    if (priv && !strcmp (priv->page->path, node->path)) {
346       node->priv = priv;
347       node->iter = *iter;
348       return TRUE;
349    }
350 
351    return FALSE;
352 }
353 
354 
355 static gboolean
prefs_win_navtree_get_parent(GimvPrefsWinPagePrivate * priv,GtkTreeIter * iter)356 prefs_win_navtree_get_parent (GimvPrefsWinPagePrivate *priv, GtkTreeIter *iter)
357 {
358    GtkTreeModel *model;
359    struct FindNode node;
360 
361    g_return_val_if_fail (priv, FALSE);
362    g_return_val_if_fail (priv->page, FALSE);
363    g_return_val_if_fail (priv->page->path, FALSE);
364 
365    node.path = g_dirname (priv->page->path);
366    node.priv  = NULL;
367 
368    model = gtk_tree_view_get_model (GTK_TREE_VIEW (prefs_win.tree));
369    gtk_tree_model_foreach (model, find_node_by_path, &node);
370 
371    g_free (node.path);
372 
373    if (node.priv) {
374       *iter = node.iter;
375       return TRUE;
376    }
377 
378    return FALSE;
379 }
380 
381 
382 static gboolean
cb_tree_key_press(GtkWidget * widget,GdkEventKey * event,gpointer data)383 cb_tree_key_press (GtkWidget *widget, GdkEventKey *event, gpointer data)
384 {
385    GtkTreeSelection *selection;
386    GtkTreeModel *model;
387    GtkTreeIter iter;
388    GtkTreePath *treepath;
389    gboolean success, retval = FALSE;
390 
391    g_return_val_if_fail (GTK_IS_TREE_VIEW (widget), FALSE);
392 
393    selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (widget));
394    if (!selection) return FALSE;
395    success = gtk_tree_selection_get_selected (selection, &model, &iter);
396    if (!success) return FALSE;
397    treepath = gtk_tree_model_get_path (model, &iter);
398    if (!treepath) return FALSE;
399 
400    switch (event->keyval) {
401    case GDK_KP_Enter:
402    case GDK_Return:
403    case GDK_ISO_Enter:
404    case GDK_space:
405       if (gtk_tree_view_row_expanded (GTK_TREE_VIEW (widget), treepath))
406          gtk_tree_view_collapse_row (GTK_TREE_VIEW (widget), treepath);
407       else
408          gtk_tree_view_expand_row (GTK_TREE_VIEW (widget), treepath, FALSE);
409       retval = TRUE;
410       break;
411    case GDK_Right:
412       gtk_tree_view_expand_row (GTK_TREE_VIEW (widget), treepath, FALSE);
413       retval = TRUE;
414       break;
415    case GDK_Left:
416       gtk_tree_view_collapse_row (GTK_TREE_VIEW (widget), treepath);
417       retval = TRUE;
418       break;
419    default:
420       break;
421    }
422 
423    gtk_tree_path_free(treepath);
424 
425    return retval;
426 }
427 
428 
429 static void
cb_tree_cursor_changed(GtkTreeView * treeview,gpointer data)430 cb_tree_cursor_changed (GtkTreeView *treeview, gpointer data)
431 {
432    GtkTreeSelection *selection;
433    GtkTreeModel *model;
434    GtkTreeIter iter;
435    GimvPrefsWinPagePrivate *priv;
436 
437    g_return_if_fail (treeview);
438 
439    selection = gtk_tree_view_get_selection (treeview);
440    gtk_tree_selection_get_selected (selection, &model, &iter);
441    gtk_tree_model_get (model, &iter,
442                        COLUMN_PRIV_DATA, &priv,
443                        COLUMN_TERMINATOR);
444 
445    g_return_if_fail (priv);
446    g_return_if_fail (priv->page);
447 
448    prefs_win_set_page (priv->page->path);
449 }
450 
451 
452 static GtkWidget *
prefs_win_create_navtree(void)453 prefs_win_create_navtree (void)
454 {
455    GtkTreeStore *store;
456    GtkTreeViewColumn *col;
457    GtkCellRenderer *render;
458    GtkWidget *tree;
459    GList *node;
460 
461    store = gtk_tree_store_new (N_COLUMN,
462                                GDK_TYPE_PIXMAP,
463                                GDK_TYPE_PIXMAP,
464                                GDK_TYPE_PIXMAP,
465                                GDK_TYPE_PIXMAP,
466                                G_TYPE_STRING,
467                                G_TYPE_POINTER);
468    tree = gtk_tree_view_new_with_model (GTK_TREE_MODEL (store));
469    prefs_win.tree = tree;
470    gtk_tree_view_set_rules_hint (GTK_TREE_VIEW (tree), TRUE);
471    gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (tree), FALSE);
472 
473    g_signal_connect (G_OBJECT (tree), "key_press_event",
474                      G_CALLBACK (cb_tree_key_press), NULL);
475    g_signal_connect (G_OBJECT (tree), "cursor_changed",
476                      G_CALLBACK (cb_tree_cursor_changed), NULL);
477 
478    /* name column */
479    col = gtk_tree_view_column_new();
480 
481    render = gimv_cell_renderer_pixmap_new ();
482    gtk_tree_view_column_pack_start (col, render, FALSE);
483    gtk_tree_view_column_add_attribute (col, render, "pixmap",
484                                        COLUMN_ICON_CLOSE);
485    gtk_tree_view_column_add_attribute (col, render, "mask",
486                                        COLUMN_ICON_CLOSE_MASK);
487    gtk_tree_view_column_add_attribute (col, render, "pixmap_expander_open",
488                                        COLUMN_ICON_OPEN);
489    gtk_tree_view_column_add_attribute (col, render, "mask_expander_open",
490                                        COLUMN_ICON_OPEN_MASK);
491    gtk_tree_view_column_add_attribute (col, render, "pixmap_expander_closed",
492                                        COLUMN_ICON_CLOSE);
493    gtk_tree_view_column_add_attribute (col, render, "mask_expander_closed",
494                                        COLUMN_ICON_CLOSE_MASK);
495 
496    render = gtk_cell_renderer_text_new ();
497    gtk_tree_view_column_pack_start (col, render, TRUE);
498    gtk_tree_view_column_add_attribute (col, render, "text", COLUMN_NAME);
499 
500    gtk_tree_view_append_column (GTK_TREE_VIEW (tree), col);
501    gtk_tree_view_set_expander_column (GTK_TREE_VIEW (tree), col);
502 
503    /* create pages */
504    for (node = get_page_entries_list(); node; node = g_list_next (node)) {
505       GimvPrefsWinPage *page = node->data;
506       const gchar *title;
507       GdkPixmap *pixmap = NULL, *opixmap = NULL;
508       GdkBitmap *mask = NULL, *omask = NULL;
509       GimvPrefsWinPagePrivate *priv;
510       GtkTreeIter iter, parent_iter;
511 
512       if (!page || !page->path) continue;
513 
514       /* translate page title */
515       title = g_basename (_(page->path));
516 
517       /* get node icon */
518       get_icon (page->icon,      &pixmap,  &mask);
519       get_icon (page->icon_open, &opixmap, &omask);
520 
521       /* set private data */
522       priv = g_new0 (GimvPrefsWinPagePrivate, 1);
523       priv->page   = page;
524       priv->widget = NULL;
525 
526       priv_page_list = g_list_append (priv_page_list, priv);
527 
528       if (prefs_win_navtree_get_parent (priv, &parent_iter)) {
529          gtk_tree_store_append (store, &iter, &parent_iter);
530       } else {
531          gtk_tree_store_append (store, &iter, NULL);
532       }
533       gtk_tree_store_set (store, &iter,
534                           COLUMN_ICON_CLOSE,      pixmap,
535                           COLUMN_ICON_CLOSE_MASK, mask,
536                           COLUMN_ICON_OPEN,       opixmap,
537                           COLUMN_ICON_OPEN_MASK,  omask,
538                           COLUMN_NAME,            title,
539                           COLUMN_PRIV_DATA,       priv,
540                           COLUMN_TERMINATOR);
541    }
542 
543    return tree;
544 }
545 
546 #else /* ENABLE_TREEVIEW */
547 
548 static gboolean
cb_ctree_key_press(GtkWidget * widget,GdkEventKey * event,gpointer data)549 cb_ctree_key_press (GtkWidget *widget, GdkEventKey *event, gpointer data)
550 {
551    GList *sel;
552    GtkCTreeNode *node;
553 
554    g_return_val_if_fail (GTK_IS_CLIST (widget), FALSE);
555 
556    sel = GTK_CLIST (widget)->selection;
557    if (!sel) return FALSE;
558    node = sel->data;
559 
560    switch (event->keyval) {
561    case GDK_KP_Enter:
562    case GDK_Return:
563    case GDK_ISO_Enter:
564    case GDK_space:
565       gtk_ctree_toggle_expansion (GTK_CTREE (widget), node);
566       break;
567    case GDK_Right:
568       gtk_ctree_expand (GTK_CTREE (widget), node);
569       return TRUE;
570       break;
571    case GDK_Left:
572       gtk_ctree_collapse (GTK_CTREE (widget), node);
573       return TRUE;
574       break;
575    default:
576       break;
577    }
578 
579    return FALSE;
580 }
581 
582 
583 static void
cb_ctree_select_row(GtkWidget * widget,gint row,gint column,GdkEventButton * event,gpointer data)584 cb_ctree_select_row (GtkWidget *widget, gint row, gint column,
585                      GdkEventButton *event, gpointer data)
586 {
587    GtkCTreeNode *node;
588    GimvPrefsWinPagePrivate *priv;
589 
590    node = gtk_ctree_node_nth (GTK_CTREE (widget), row);
591    if (!node) return;
592 
593    priv = gtk_ctree_node_get_row_data (GTK_CTREE (widget), node);
594    if (priv->page)
595       prefs_win_set_page (priv->page->path);
596 }
597 
598 
599 static GtkCTreeNode *
prefs_win_navtree_get_parent(GimvPrefsWinPage * page)600 prefs_win_navtree_get_parent (GimvPrefsWinPage *page)
601 {
602    GList *node = NULL;
603    gchar *parent;
604 
605    g_return_val_if_fail (page, NULL);
606    g_return_val_if_fail (page->path, NULL);
607 
608    if (!page->path) return NULL;
609    parent = g_dirname (page->path);
610 
611    for (node = priv_page_list; node; node = g_list_next (node)) {
612       GimvPrefsWinPagePrivate *priv = node->data;
613       if (priv && priv->page && !strcmp (parent, priv->page->path)) {
614          g_free (parent);
615          return priv->node;
616       }
617    }
618 
619    g_free (parent);
620 
621    return NULL;
622 }
623 
624 
625 static GtkWidget *
prefs_win_create_navtree(void)626 prefs_win_create_navtree (void)
627 {
628    GtkWidget *ctree;
629    GtkCTreeNode *node, *parent = NULL;
630    GList *lnode;
631 
632    /* create tree */
633    ctree = prefs_win.tree = gtk_ctree_new (1,0);
634    prefs_win.tree = ctree;
635    gtk_clist_set_column_auto_resize (GTK_CLIST (ctree), 0, TRUE);
636    gtk_clist_set_selection_mode (GTK_CLIST (ctree), GTK_SELECTION_BROWSE);
637    gtk_ctree_set_line_style (GTK_CTREE (ctree), conf.dirview_line_style);
638    gtk_ctree_set_expander_style (GTK_CTREE (ctree), conf.dirview_expander_style);
639    gtk_clist_set_row_height (GTK_CLIST (ctree), 18);
640 
641    gtk_signal_connect (GTK_OBJECT (ctree), "key_press_event",
642                        GTK_SIGNAL_FUNC (cb_ctree_key_press), NULL);
643    gtk_signal_connect (GTK_OBJECT (ctree), "select-row",
644                        GTK_SIGNAL_FUNC (cb_ctree_select_row), NULL);
645 
646    /* create pages */
647    for (lnode = get_page_entries_list(); lnode; lnode = g_list_next (lnode)) {
648       GimvPrefsWinPage *page = lnode->data;
649       const gchar *title;
650       GdkPixmap *pixmap = NULL, *opixmap = NULL;
651       GdkBitmap *mask = NULL, *omask = NULL;
652       GimvPrefsWinPagePrivate *priv;
653 
654       if (!page || !page->path) continue;
655 
656       /* translate page title */
657       title = g_basename (_(page->path));
658 
659       /* get node icon */
660       get_icon (page->icon,      &pixmap,  &mask);
661       get_icon (page->icon_open, &opixmap, &omask);
662 
663       /* insert node */
664       parent = prefs_win_navtree_get_parent (page);
665       node = gtk_ctree_insert_node (GTK_CTREE (ctree), parent, NULL,
666                                     (gchar **) &title, 4,
667                                     pixmap, mask,
668                                     opixmap, omask,
669                                     FALSE, FALSE);
670 
671       /* set private data */
672       priv = g_new0 (GimvPrefsWinPagePrivate, 1);
673       priv->page   = page;
674       priv->widget = NULL;
675       priv->node   = node;
676 
677       priv_page_list = g_list_append (priv_page_list, priv);
678 
679       gtk_ctree_node_set_row_data (GTK_CTREE(ctree), node, priv);
680    }
681 
682    return ctree;
683 }
684 
685 #endif /* ENABLE_TREEVIEW */
686 
687 
688 
689 /*******************************************************************************
690  *
691  *   Callback functions for preference window.
692  *
693  *******************************************************************************/
694 static void
cb_prefs_win_destroy()695 cb_prefs_win_destroy ()
696 {
697    if (prefs_win.ok_pressed) {
698       prefs_win_free_strings (TRUE);
699       conf = *config_changed;
700       prefs_win_apply_config (GIMV_PREFS_WIN_ACTION_OK);
701    } else {
702       prefs_win_free_strings (FALSE);
703       conf = *config_prechanged;
704       prefs_win_apply_config (GIMV_PREFS_WIN_ACTION_CANCEL);
705    }
706 
707    g_free (config_changed);
708    g_free (config_prechanged);
709    config_changed       = NULL;
710    config_prechanged    = NULL;
711 
712    prefs_window         = NULL;
713    prefs_win.notebook   = NULL;
714    prefs_win.tree       = NULL;
715    prefs_win.ok_pressed = FALSE;
716 
717    g_list_foreach (priv_page_list, (GFunc) g_free, NULL);
718    g_list_free (priv_page_list);
719    priv_page_list = NULL;
720 
721    prefs_save_config ();
722 }
723 
724 
725 #ifdef USE_GTK2
726 
727 static void
cb_dialog_response(GtkDialog * dialog,gint arg,gpointer data)728 cb_dialog_response (GtkDialog *dialog, gint arg, gpointer data)
729 {
730    switch (arg) {
731    case GTK_RESPONSE_ACCEPT:
732       prefs_win.ok_pressed = TRUE;
733       gtk_widget_destroy (prefs_window);
734       break;
735    case GTK_RESPONSE_APPLY:
736       memcpy (&conf, config_changed, sizeof(Config));
737       prefs_win_apply_config (GIMV_PREFS_WIN_ACTION_APPLY);
738       break;
739    case GTK_RESPONSE_REJECT:
740       gtk_widget_destroy (prefs_window);
741       break;
742    default:
743       break;
744    }
745 }
746 
747 #else
748 
749 static void
cb_prefs_ok_button()750 cb_prefs_ok_button ()
751 {
752    prefs_win.ok_pressed = TRUE;
753    gtk_widget_destroy (prefs_window);
754 }
755 
756 
757 static void
cb_prefs_apply_button()758 cb_prefs_apply_button ()
759 {
760    memcpy (&conf, config_changed, sizeof(Config));
761    prefs_win_apply_config (GIMV_PREFS_WIN_ACTION_APPLY);
762 }
763 
764 
765 static void
cb_prefs_cancel_button()766 cb_prefs_cancel_button ()
767 {
768    gtk_widget_destroy (prefs_window);
769 }
770 
771 #endif
772 
773 
774 
775 /*******************************************************************************
776  *
777  *   prefs_open_window:
778  *      @ Create preference window. If already opened, raise it and return.
779  *
780  *   GtkWidget *prefs_window (global variable):
781  *      Pointer to preference window.
782  *
783  *   Static PrefsWin prefs_win (local variable):
784  *      store pointer to eache widget;
785  *
786  *******************************************************************************/
787 GtkWidget *
gimv_prefs_win_open(const gchar * path,GtkWindow * parent)788 gimv_prefs_win_open (const gchar *path, GtkWindow *parent)
789 {
790    GtkWidget *notebook, *pane, *scrolledwin, *navtree;
791 
792    /* if preference window is alredy opend, raise it and return */
793    if (prefs_window) {
794       gdk_window_raise (prefs_window->window);
795       return prefs_window;
796    }
797 
798    prefs_win.ok_pressed = FALSE;
799 
800    /* allocate buffer for new config */
801    config_prechanged = g_memdup (&conf, sizeof(Config));
802    config_changed = g_memdup (&conf, sizeof(Config));
803 
804    /* create config window */
805    prefs_window = gtk_dialog_new ();
806    if (parent)
807       gtk_window_set_transient_for (GTK_WINDOW (prefs_window), parent);
808    gtk_window_set_wmclass(GTK_WINDOW(prefs_window), "prefs", GIMV_PROG_NAME);
809    gtk_window_set_default_size (GTK_WINDOW(prefs_window), 600, 450);
810    gtk_window_set_title (GTK_WINDOW (prefs_window), _("Preference"));
811    gtk_signal_connect (GTK_OBJECT(prefs_window), "destroy",
812                        GTK_SIGNAL_FUNC(cb_prefs_win_destroy), NULL);
813 
814    /* pane */
815    pane = gimv_hpaned_new ();
816    gtk_container_set_border_width (GTK_CONTAINER (pane), 5);
817    gtk_box_pack_start (GTK_BOX (GTK_DIALOG (prefs_window)->vbox),
818                        pane, TRUE, TRUE, 0);
819    gtk_widget_show (pane);
820 
821    notebook = prefs_win.notebook = gtk_notebook_new ();
822    gtk_notebook_set_tab_pos (GTK_NOTEBOOK (notebook), GTK_POS_TOP);
823    gtk_notebook_set_scrollable (GTK_NOTEBOOK (notebook), TRUE);
824    /* gtk_notebook_popup_enable (GTK_NOTEBOOK (notebook)); */
825    gtk_notebook_set_show_tabs (GTK_NOTEBOOK (notebook), FALSE);
826    gtk_notebook_set_show_border (GTK_NOTEBOOK (notebook), FALSE);
827    gtk_widget_show (notebook);
828 
829    /* scrolled window */
830    scrolledwin = gtk_scrolled_window_new (NULL, NULL);
831    gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW(scrolledwin),
832                                    GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
833 #ifdef USE_GTK2
834    gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolledwin),
835                                        GTK_SHADOW_IN);
836 #endif /* USE_GTK2 */
837    gtk_widget_set_usize (scrolledwin, 170, -1);
838    gtk_widget_show (scrolledwin);
839 
840    /* navigation tree */
841    navtree = prefs_win_create_navtree ();
842    gtk_container_add (GTK_CONTAINER (scrolledwin), navtree);
843    gtk_widget_show (navtree);
844 
845    gimv_paned_add1 (GIMV_PANED (pane), scrolledwin);
846    gimv_paned_add2 (GIMV_PANED (pane), notebook);
847 
848    /* button */
849 #ifdef USE_GTK2
850    gtk_dialog_add_buttons (GTK_DIALOG (prefs_window),
851                            GTK_STOCK_APPLY,  GTK_RESPONSE_APPLY,
852                            GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT,
853                            GTK_STOCK_OK,     GTK_RESPONSE_ACCEPT,
854                            NULL);
855    gtk_signal_connect_object (GTK_OBJECT (prefs_window), "response",
856                               GTK_SIGNAL_FUNC (cb_dialog_response),
857                               NULL);
858 #else
859 {
860    GtkWidget *button;
861 
862    /* dialog buttons */
863    button = gtk_button_new_with_label (_("OK"));
864    gtk_box_pack_start (GTK_BOX (GTK_DIALOG (prefs_window)->action_area),
865                        button, TRUE, TRUE, 0);
866    gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
867                               GTK_SIGNAL_FUNC (cb_prefs_ok_button),
868                               GTK_OBJECT (prefs_window));
869    GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
870    gtk_widget_show (button);
871 
872    gtk_widget_grab_focus (button);
873 
874    button = gtk_button_new_with_label (_("Apply"));
875    gtk_box_pack_start (GTK_BOX (GTK_DIALOG (prefs_window)->action_area),
876                        button, FALSE, TRUE, 0);
877    gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
878                               GTK_SIGNAL_FUNC (cb_prefs_apply_button),
879                               GTK_OBJECT (prefs_window));
880    GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
881    gtk_widget_show (button);
882 
883    button = gtk_button_new_with_label (_("Cancel"));
884    gtk_box_pack_start (GTK_BOX (GTK_DIALOG (prefs_window)->action_area),
885                        button, FALSE, TRUE, 0);
886    gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
887                               GTK_SIGNAL_FUNC (cb_prefs_cancel_button),
888                               GTK_OBJECT (prefs_window));
889    GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
890    gtk_widget_show (button);
891 }
892 #endif
893 
894    gtk_window_set_position (GTK_WINDOW (prefs_window), GTK_WIN_POS_CENTER);
895    gtk_widget_show (prefs_window);
896    gimv_icon_stock_set_window_icon (prefs_window->window, "prefs");
897 
898    prefs_win_set_page (NULL);
899 
900    return prefs_window;
901 }
902 
903 
904 static GtkWindow *auauauau_window = NULL;
905 
906 static gboolean
idle_prefs_win_open(gpointer data)907 idle_prefs_win_open (gpointer data)
908 {
909    gchar *path = data;
910    gimv_prefs_win_open (path, auauauau_window);
911    auauauau_window = NULL;
912    g_free (path);
913    return FALSE;
914 }
915 
916 
917 void
gimv_prefs_win_open_idle(const gchar * path,GtkWindow * parent)918 gimv_prefs_win_open_idle (const gchar *path, GtkWindow *parent)
919 {
920    gchar *str = NULL;
921 
922    if (path)
923       str = g_strdup (path);
924 
925    auauauau_window = parent;
926 
927    gtk_idle_add (idle_prefs_win_open, str);
928 }
929 
930 
931 gboolean
gimv_prefs_win_is_opened(void)932 gimv_prefs_win_is_opened (void)
933 {
934    if (prefs_window)
935       return TRUE;
936    else
937       return FALSE;
938 }
939 
940 
941 GtkWidget *
gimv_prefs_win_get(void)942 gimv_prefs_win_get (void)
943 {
944    return prefs_window;
945 }
946