Logo Search packages:      
Sourcecode: kazehakase version File versions

kz-prefs-win.c

/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */

/*
 *  Copyright (C) 2003 Takuro Ashie
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2, or (at your option)
 *  any later version.
 *
 *  This program 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 General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */

#include "kz-prefs-win.h"

#include <string.h>
#include <gdk/gdkkeysyms.h>
#include <glib/gi18n.h>

#include "gobject-utils.h"
#include "kazehakase.h"
#include "kz-icons.h"

/* preference UI */
#include "prefs_ui/prefs_general.h"
#include "prefs_ui/prefs_lang.h"
#include "prefs_ui/prefs_font.h"
#include "prefs_ui/prefs_tab.h"
#include "prefs_ui/prefs_key_accel.h"
#include "prefs_ui/prefs_gesture.h"
#include "prefs_ui/prefs_entry.h"
#include "prefs_ui/prefs_proxy.h"
#include "prefs_ui/prefs_ui_editor.h"
#include "prefs_ui/prefs_privacy.h"
#include "prefs_ui/prefs_external_program.h"
#include "prefs_ui/prefs_history.h"
#include "prefs_ui/prefs_bookmark.h"


enum {
      COLUMN_TERMINATOR = -1,
      COLUMN_ICON_OPEN,
      COLUMN_ICON_CLOSE,
      COLUMN_NAME,
      COLUMN_PRIV_DATA,
      N_COLUMN
};

struct _KzPrefsWinPriv
{
      GList *page_list;
};

typedef struct _KzPrefsWinPagePriv
{
      KzPrefsWinPageEntry *entry;
      GtkWidget           *widget;
} KzPrefsWinPagePriv; 


static void       kz_prefs_win_class_init        (KzPrefsWinClass *klass);
static void       kz_prefs_win_init              (KzPrefsWin      *win);
static void       kz_prefs_win_dispose           (GObject         *object);
static void       kz_prefs_win_finalize          (GObject         *finalize);
static void       kz_prefs_win_response          (GtkDialog       *dialog,
                                      gint             arg);
static gboolean   kz_prefs_win_delete_event      (GtkWidget        *widget,
                                      GdkEventAny      *event);

static GtkWidget *kz_prefs_win_create_nav_tree   (KzPrefsWin *win);
static void       kz_prefs_win_reset_nav_tree    (KzPrefsWin *win);
static void       kz_prefs_win_set_ui_level      (KzPrefsWin *win);
static void       kz_prefs_win_restore_state     (KzPrefsWin *win);
static void       kz_prefs_win_store_state       (KzPrefsWin *win);

static void       cb_profile_global_changed      (KzProfile   *profile,
                                      const gchar *section,
                                      const gchar *key,
                                      const gchar *old_value,
                                      KzPrefsWin  *win);
static gboolean   cb_tree_key_press              (GtkWidget *widget,
                                      GdkEventKey *event,
                                      gpointer data);
static void       cb_tree_cursor_changed         (GtkTreeView *treeview,
                                      gpointer data);


static KzPrefsWin *kz_prefs_win_single = NULL;

static GtkDialogClass *parent_class = NULL;
static GList *prefs_page_entries = NULL;


#define ADD_PAGE_ENTRY(func)                                \
{                                                     \
      KzPrefsWinPageEntry *entry;                           \
      gint i;                                               \
      for (i = 0; (entry = func(i)); i++)                   \
            prefs_page_entries = g_list_append(prefs_page_entries,      \
                                       entry);        \
}


KZ_OBJECT_GET_TYPE(kz_prefs_win, "KzPrefsWin", KzPrefsWin,
               kz_prefs_win_class_init, kz_prefs_win_init,
               GTK_TYPE_DIALOG)
KZ_OBJECT_FINALIZE(kz_prefs_win, KzPrefsWin)


static void
kz_prefs_win_class_init (KzPrefsWinClass *klass)
{
      GObjectClass *object_class;
      GtkDialogClass *dialog_class;
      GtkWidgetClass *widget_class;

      parent_class = g_type_class_peek_parent(klass);
      object_class = (GObjectClass *) klass;
      dialog_class = (GtkDialogClass *) klass;
      widget_class = (GtkWidgetClass *) klass;

      object_class->dispose      = kz_prefs_win_dispose;
      object_class->finalize     = kz_prefs_win_finalize;

      dialog_class->response     = kz_prefs_win_response;
      
      widget_class->delete_event = kz_prefs_win_delete_event;
      
      ADD_PAGE_ENTRY(prefs_general_get_entry);
      ADD_PAGE_ENTRY(prefs_lang_get_entry);
      ADD_PAGE_ENTRY(prefs_font_get_entry);
      ADD_PAGE_ENTRY(prefs_tab_get_entry);
      ADD_PAGE_ENTRY(prefs_entry_get_entry);
      ADD_PAGE_ENTRY(prefs_bookmark_get_entry);
      ADD_PAGE_ENTRY(prefs_key_accel_get_entry);
      ADD_PAGE_ENTRY(prefs_gesture_get_entry);
      ADD_PAGE_ENTRY(prefs_proxy_get_entry);
      ADD_PAGE_ENTRY(prefs_privacy_get_entry); 
      /* ADD_PAGE_ENTRY(prefs_ui_editor_get_entry); */
      ADD_PAGE_ENTRY(prefs_external_program_get_entry);
      ADD_PAGE_ENTRY(prefs_history_get_entry);
}


static void
kz_prefs_win_init (KzPrefsWin *win)
{
      GtkWidget *paned, *scrwin, *tree, *notebook;

      win->priv = g_new0(KzPrefsWinPriv, 1);
      win->priv->page_list   = NULL;

      gtk_window_set_default_size(GTK_WINDOW(win), 600, 450);
      gtk_window_set_icon(GTK_WINDOW(win), kz_icon);

      gtk_dialog_add_buttons(GTK_DIALOG(win),
                         GTK_STOCK_APPLY,  GTK_RESPONSE_APPLY,
                         GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT,
                         GTK_STOCK_OK,     GTK_RESPONSE_ACCEPT,
                         NULL);

      /* paned */
      paned = gtk_hpaned_new();
      gtk_container_set_border_width(GTK_CONTAINER (paned), 5);
      gtk_box_pack_start(GTK_BOX(GTK_DIALOG(win)->vbox), 
                     paned, TRUE, TRUE, 0);
      gtk_widget_show(paned);

      /* scrolled window */
      scrwin = gtk_scrolled_window_new(NULL, NULL);
      gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrwin),
                               GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
        gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrwin),
                                  GTK_SHADOW_IN);
      gtk_widget_set_size_request(scrwin, 170, -1);
      gtk_widget_show(scrwin);

      /* navtree */
      tree = kz_prefs_win_create_nav_tree(win);
      gtk_container_add(GTK_CONTAINER(scrwin), tree);
      gtk_widget_show(tree);

      /* notebook */
      notebook = gtk_notebook_new();
      gtk_notebook_set_tab_pos(GTK_NOTEBOOK(notebook), GTK_POS_TOP);
      gtk_notebook_set_scrollable(GTK_NOTEBOOK(notebook), TRUE);
      gtk_notebook_set_show_tabs(GTK_NOTEBOOK(notebook), FALSE);
      gtk_notebook_set_show_border(GTK_NOTEBOOK(notebook), FALSE);
      gtk_widget_show(notebook);

      gtk_paned_add1(GTK_PANED(paned), scrwin);
      gtk_paned_add2(GTK_PANED(paned), notebook);

      /* initialize member */
      win->paned           = paned;
      win->scrolled_window = scrwin;
      win->tree_view       = tree;
      win->notebook        = notebook;

      /* set default state */
      kz_prefs_win_restore_state(win);
      kz_prefs_win_reset_nav_tree(win);

      /* observe UI Level */
      g_signal_connect(kz_global_profile,
                   "changed::Global",
                   G_CALLBACK(cb_profile_global_changed), win);
}

static void
kz_prefs_win_dispose (GObject *object)
{
      KzPrefsWin *win = KZ_PREFS_WIN(object);

      g_signal_handlers_disconnect_by_func
            (kz_global_profile,
             G_CALLBACK(cb_profile_global_changed), win);

      if (win->priv->page_list)
      {
            g_list_foreach (win->priv->page_list, (GFunc) g_free, NULL);
            g_list_free(win->priv->page_list);
            win->priv->page_list = NULL;
      }

      if (kz_prefs_win_single && kz_prefs_win_single == win)
            kz_prefs_win_single = NULL;

      if (G_OBJECT_CLASS(parent_class)->dispose)
            G_OBJECT_CLASS(parent_class)->dispose(object);
}


static void
kz_prefs_win_response (GtkDialog *dialog, gint arg)
{
      GList *node = KZ_PREFS_WIN(dialog)->priv->page_list;

      for (; node; node = g_list_next(node))
      {
            KzPrefsWinPagePriv *page = node->data;

            if (page->widget && page->entry && page->entry->response)
                  page->entry->response(page->widget, arg);
      }

      switch (arg)
      {
      case GTK_RESPONSE_ACCEPT:
      case GTK_RESPONSE_REJECT:
            kz_prefs_win_store_state(KZ_PREFS_WIN(dialog));
            gtk_widget_destroy(GTK_WIDGET(dialog));
            break;
      case GTK_RESPONSE_APPLY:
            break;
      case KZ_RESPONSE_UI_LEVEL_MEDIUM:
            break;
      case KZ_RESPONSE_UI_LEVEL_EXPERT:
            break;
      case KZ_RESPONSE_UI_LEVEL_CUSTOM:
            break;
      default:
            break;
      }
}

static gboolean 
kz_prefs_win_delete_event (GtkWidget *widget, GdkEventAny *event)
{
      kz_prefs_win_store_state(KZ_PREFS_WIN(widget));
      
      return FALSE;
}

GtkWidget *
kz_prefs_win_new (void)
{
      GObject *obj;
      KzPrefsWin *win;

      obj = g_object_new(KZ_TYPE_PREFS_WIN,
                     "title", _("Preference - Kazehakase"),
                     NULL);
      win = KZ_PREFS_WIN(obj);

      return GTK_WIDGET(win);
}

GtkWidget *
kz_prefs_win_get_instance (void)
{
      if (kz_prefs_win_single)
            gtk_widget_show(GTK_WIDGET(kz_prefs_win_single));
      else
            kz_prefs_win_single = KZ_PREFS_WIN(kz_prefs_win_new());

      return GTK_WIDGET(kz_prefs_win_single);
}

static void
kz_prefs_win_create_page (KzPrefsWin *win, KzPrefsWinPagePriv *priv)
{
      gchar *title = NULL;
      GtkWidget *widget, *label;

      if (!priv || !priv->entry) return;
      if (priv->widget) return;

      /* translate page title */
      if (priv->entry->path)
            title = g_path_get_basename (_(priv->entry->path));

      /* create page */
      if (priv->entry->create) {
            widget = priv->entry->create();
            label = gtk_label_new(title);
            gtk_notebook_append_page(GTK_NOTEBOOK(win->notebook), widget, label);
            priv->widget = widget;
            kz_prefs_win_set_ui_level(win);
      }

      g_free(title);
}

void
kz_prefs_win_set_page (KzPrefsWin *win, const gchar *path)
{
      KzPrefsWinPagePriv *priv = NULL;
      GList *node;
      gint num;

      if (!path || !*path)
      {
            if (!win->priv->page_list) return;
            priv = win->priv->page_list->data;
      }
      else
      {
            for (node = win->priv->page_list; node; node = g_list_next(node))
            {
                  priv = node->data;
                  if (priv->entry && !strcmp(path, priv->entry->path)) 
                        break;
                  priv = NULL;
            }
      }

      if (!priv)
      {
            if (!win->priv->page_list) return;
            priv = win->priv->page_list->data;
      }

      if (!priv->widget)
            kz_prefs_win_create_page(win, priv);

      if (priv->widget)
            gtk_widget_show(priv->widget);
      else
            return;

      num = gtk_notebook_page_num (GTK_NOTEBOOK(win->notebook),
                             priv->widget);
      if (num >= 0)
            gtk_notebook_set_current_page(GTK_NOTEBOOK(win->notebook), num);
}


static GtkWidget *
kz_prefs_win_create_nav_tree (KzPrefsWin *win)
{
      GtkWidget *tree;
      GtkTreeStore *store;
      GtkTreeViewColumn *col;
      GtkCellRenderer *render;
      GList *node;

      store = gtk_tree_store_new(N_COLUMN,
                           GDK_TYPE_PIXBUF, GDK_TYPE_PIXBUF,
                           G_TYPE_STRING, G_TYPE_POINTER);

      tree = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store));
      gtk_tree_view_set_rules_hint (GTK_TREE_VIEW (tree), TRUE);
      gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (tree), FALSE);

      g_signal_connect (tree, "key_press_event",
                    G_CALLBACK (cb_tree_key_press), win);
      g_signal_connect (tree, "cursor_changed",
                    G_CALLBACK (cb_tree_cursor_changed), win);

      /* name column */
      col = gtk_tree_view_column_new();

      render = gtk_cell_renderer_pixbuf_new ();
      gtk_tree_view_column_pack_start (col, render, FALSE);
      gtk_tree_view_column_add_attribute (col, render,
                                  "pixbuf",
                                  COLUMN_ICON_CLOSE);
      gtk_tree_view_column_add_attribute (col, render,
                                  "pixbuf_expander_open",
                                  COLUMN_ICON_OPEN);
      gtk_tree_view_column_add_attribute (col, render,
                                  "pixbuf_expander_closed",
                                  COLUMN_ICON_CLOSE);

      render = gtk_cell_renderer_text_new ();
      gtk_tree_view_column_pack_start (col, render, TRUE);
      gtk_tree_view_column_add_attribute (col, render, "text", COLUMN_NAME);

      gtk_tree_view_append_column (GTK_TREE_VIEW (tree), col);
      gtk_tree_view_set_expander_column (GTK_TREE_VIEW (tree), col);

      /* set tree */
      gtk_tree_store_clear(store);
      for (node = prefs_page_entries; node; node = g_list_next(node))
      {
            KzPrefsWinPagePriv *priv;
            KzPrefsWinPageEntry *entry = node->data;
            GtkTreeIter iter;
            gchar *title;

            /* set private data */
            priv = g_new0(KzPrefsWinPagePriv, 1);
            priv->entry  = entry;
            priv->widget = NULL;
            win->priv->page_list = g_list_append (win->priv->page_list, priv);

#if 0
            if (kz_prefs_win_ensure_parent (priv, &parent_iter))
            {
                  gtk_tree_store_append (store, &iter, &parent_iter);
            }
            else
            {
                  gtk_tree_store_append (store, &iter, NULL);
            }
#else
            gtk_tree_store_append (store, &iter, NULL);
#endif

            title = g_path_get_basename(_(entry->path));
            gtk_tree_store_set(store, &iter,
#if 0
                           COLUMN_ICON_CLOSE,      pixbuf,
                           COLUMN_ICON_OPEN,       pixbuf_open,
#endif
                           COLUMN_NAME,            title,
                           COLUMN_PRIV_DATA,       priv,
                           COLUMN_TERMINATOR);
            g_free(title);
      }
      
      g_object_unref(store);
      return tree;
}


static gint
compare_page_entry (gconstpointer a, gconstpointer b)
{
      const KzPrefsWinPagePriv *priv = a;
      const KzPrefsWinPageEntry *entry = b;

      return priv->entry - entry;
}


static void
kz_prefs_win_reset_nav_tree (KzPrefsWin *win)
{
      GtkTreeView *treeview;
      GtkTreeStore *store;
      GList *node;

      g_return_if_fail(KZ_IS_PREFS_WIN(win));

      treeview = GTK_TREE_VIEW(win->tree_view);
      store = GTK_TREE_STORE(gtk_tree_view_get_model(treeview));

      gtk_tree_store_clear(store);
      for (node = prefs_page_entries; node; node = g_list_next(node))
      {
            KzPrefsWinPagePriv *priv;
            KzPrefsWinPageEntry *entry = node->data;
            GtkTreeIter iter;
            gchar *title;
            GList *node;

            /* set private data */
            node = g_list_find_custom(win->priv->page_list, entry,
                                compare_page_entry);
            if (node)
            {
                  priv = node->data;
            }
            else
            {
                  priv = g_new0(KzPrefsWinPagePriv, 1);
                  priv->entry  = entry;
                  priv->widget = NULL;
                  win->priv->page_list = g_list_append(win->priv->page_list, priv);
            }

            if (!(priv->entry->ui_level & kz_ui_level()))
            {
                  if (priv->widget)
                        gtk_widget_destroy(priv->widget);
                  priv->widget = NULL;
                  continue;
            }
#if 0
            if (kz_prefs_win_ensure_parent (priv, &parent_iter))
            {
                  gtk_tree_store_append (store, &iter, &parent_iter);
            }
            else
            {
                  gtk_tree_store_append (store, &iter, NULL);
            }
#else
            gtk_tree_store_append (store, &iter, NULL);
#endif

            title = g_path_get_basename(_(entry->path));
            gtk_tree_store_set(store, &iter,
#if 0
                           COLUMN_ICON_CLOSE,      pixbuf,
                           COLUMN_ICON_OPEN,       pixbuf_open,
#endif
                           COLUMN_NAME,            title,
                           COLUMN_PRIV_DATA,       priv,
                           COLUMN_TERMINATOR);
            g_free(title);
      }

      /* FIXME: set cursor */
}

static void
kz_prefs_win_store_state (KzPrefsWin *win)
{
      gint client_x, client_y, width, height;

      g_return_if_fail(KZ_IS_PREFS_WIN(win));

      gdk_window_get_geometry (GTK_WIDGET(win)->window,
                         &client_x, &client_y,
                         &width, &height, NULL);

      KZ_CONF_SET("PreferenceWindow", "width",  width,  INT);
      KZ_CONF_SET("PreferenceWindow", "height", height, INT);
}


static void
kz_prefs_win_restore_state (KzPrefsWin *win)
{
      gint width = 600, height = 450;

      g_return_if_fail(KZ_IS_PREFS_WIN(win));

      KZ_CONF_GET("PreferenceWindow", "width",  width, INT);
      KZ_CONF_GET("PreferenceWindow", "height", height, INT);

      /* size */
      gtk_window_set_default_size(GTK_WINDOW(win), width, height);
}


GtkWidget *
kz_prefs_ui_utils_create_title(const gchar *title)
{
      GtkWidget *vbox, *hbox, *label, *hsep;
      gchar buf[256];
      gint buflen = sizeof(buf) / sizeof(gchar);

      vbox = gtk_vbox_new(FALSE, 0);
      gtk_container_set_border_width(GTK_CONTAINER(vbox), 5);

      hbox = gtk_hbox_new(FALSE, 0);
      gtk_container_set_border_width(GTK_CONTAINER(hbox), 5);
      gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
      gtk_widget_show(hbox);

      g_snprintf(buf, buflen,
               "<span weight=\"bold\" size=\"x-large\">%s</span>",
               title);
      label = gtk_label_new(buf);
      gtk_label_set_use_markup(GTK_LABEL(label), TRUE);
      gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
      gtk_widget_show(label);

      hsep = gtk_hseparator_new();
      gtk_box_pack_start(GTK_BOX(vbox), hsep, FALSE, FALSE, 0);
      gtk_widget_show(hsep);

      return vbox;
}


static void
kz_prefs_win_set_ui_level (KzPrefsWin *win)
{
      gint response;

      switch (kz_ui_level())
      {
      case KZ_UI_LEVEL_BEGINNER:
            response = KZ_RESPONSE_UI_LEVEL_BEGINNER;
            break;
      case KZ_UI_LEVEL_MEDIUM:
            response = KZ_RESPONSE_UI_LEVEL_MEDIUM;
            break;
      case KZ_UI_LEVEL_EXPERT:
            response = KZ_RESPONSE_UI_LEVEL_EXPERT;
            break;
      case KZ_UI_LEVEL_CUSTOM:
            response = KZ_RESPONSE_UI_LEVEL_CUSTOM;
            break;
      default:
            g_warning("Invalid UI Level: %d", kz_ui_level());
            response = KZ_RESPONSE_UI_LEVEL_BEGINNER;
            break;
      }
      g_signal_emit_by_name(win, "response",
                        response);
}


static gboolean
cb_tree_key_press (GtkWidget *widget, GdkEventKey *event, gpointer data)
{
      GtkTreeSelection *selection;
      GtkTreeModel *model;
      GtkTreeIter iter;
      GtkTreePath *treepath;
      gboolean success, retval = FALSE;

      selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (widget));
      if (!selection) return FALSE;
      success = gtk_tree_selection_get_selected (selection, &model, &iter);
      if (!success) return FALSE;
      treepath = gtk_tree_model_get_path (model, &iter);
      if (!treepath) return FALSE;

      switch (event->keyval) {
      case GDK_KP_Enter:
      case GDK_Return:
      case GDK_ISO_Enter:
      case GDK_space:
            if (gtk_tree_view_row_expanded (GTK_TREE_VIEW (widget), treepath))
                  gtk_tree_view_collapse_row (GTK_TREE_VIEW (widget), treepath);
            else
                  gtk_tree_view_expand_row (GTK_TREE_VIEW (widget), treepath, FALSE);
            retval = TRUE;
            break;
      case GDK_Right:
            gtk_tree_view_expand_row (GTK_TREE_VIEW (widget), treepath, FALSE);
            retval = TRUE;
            break;
      case GDK_Left:
            gtk_tree_view_collapse_row (GTK_TREE_VIEW (widget), treepath);
            retval = TRUE;
            break;
      default:
            break;
      }

      gtk_tree_path_free(treepath);

      return retval;
}


static void
cb_tree_cursor_changed (GtkTreeView *treeview, gpointer data)
{
      KzPrefsWin *win;
      GtkTreeSelection *selection;
      GtkTreeModel *model;
      GtkTreeIter iter;
      KzPrefsWinPagePriv *priv;

      g_return_if_fail(KZ_IS_PREFS_WIN(data));

      win = KZ_PREFS_WIN(data);

      selection = gtk_tree_view_get_selection (treeview);
      gtk_tree_selection_get_selected (selection, &model, &iter);

      gtk_tree_model_get (model, &iter,
                      COLUMN_PRIV_DATA, &priv,
                      COLUMN_TERMINATOR);

      g_return_if_fail (priv);
      g_return_if_fail (priv->entry);

      kz_prefs_win_set_page (win, priv->entry->path);
}


static void
cb_profile_global_changed (KzProfile *profile,
                     const gchar *section, const gchar *key,
                     const gchar *old_value,
                     KzPrefsWin *win)
{
      g_return_if_fail(KZ_IS_PREFS_WIN(win));

      kz_prefs_win_reset_nav_tree(win);

      if (key && !strcmp(key, "ui_level"))
      {
            kz_prefs_win_set_ui_level(win);
      }
}

Generated by  Doxygen 1.6.0   Back to index