/* iconsel_interface.c
 * Copyright (C) 2002-2004 Pascal Eberhard <pascal.ebo@netcourrier.com>
 *
 * 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 of the
 * License, 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 <stdlib.h>
#include <dirent.h>
#include <string.h>

#include "common.h"
#include "iconsel_private.h"

//void              iconsel_reload(icon_selection_t *iconsel);
//void              iconsel_build_interface(icon_selection_t *iconsel);
static void       iconsel_build_iconsel(icon_selection_t *iconsel);
static void       iconsel_build_iconsel_pref(icon_selection_t *iconsel);

static void       iconsel_48_toggled(GtkToggleButton *chk,
                                     icon_selection_t *iconsel);
static void       iconsel_lt48_toggled(GtkToggleButton *chk,
                                       icon_selection_t *iconsel);
static void       iconsel_gt48_toggled(GtkToggleButton *chk,
                                       icon_selection_t *iconsel);
static void       iconsel_sort_name_clicked(GtkRadioButton *chk,
                                            icon_selection_t *iconsel);
static void       iconsel_sort_path_clicked(GtkRadioButton *chk,
                                            icon_selection_t *iconsel);
static void       iconsel_path_toggled(GtkCellRendererToggle *cell,
                                       gchar *path_str,
                                       icon_selection_t *iconsel);
static void       iconsel_path_toggled_rec(GtkCellRendererToggle *cell,
                                       gchar *path_str,
                                       icon_selection_t *iconsel);
static void       iconsel_exts_toggled(GtkCellRendererToggle *cell,
                                       gchar *path_str,
                                       icon_selection_t *iconsel);
static void       iconsel_path_edited(GtkCellRendererText *cell,
                                       gchar *path_str, gchar *newtext,
                                       icon_selection_t *iconsel);
static void       iconsel_exts_edited(GtkCellRendererText *cell,
                                       gchar *path_str, gchar *newtext,
                                       icon_selection_t *iconsel);
static void       iconsel_path_refresh_rec(icon_selection_t *iconsel,
                                           GtkTreeModel *model,
                                           icodir_t *dir,
                                           GtkTreeIter *parent_iter);
static void       iconsel_exts_refresh(icon_selection_t *iconsel);
static GtkWidget *iconsel_tree_path_new(icon_selection_t *iconsel);
static GtkWidget *iconsel_tree_exts_new(icon_selection_t *iconsel);
static gboolean   iconsel_is_dblclick(icon_selection_t *iconsel,
                                      gint x, gint y);
static gboolean   iconsel_release_event(GtkWidget *widget,
                                        GdkEventButton *event,
                                        icon_selection_t *iconsel);
static gboolean   iconsel_selected_is_dblclick(icon_selection_t *iconsel);
static gboolean   iconsel_selected_release_event(GtkWidget *widget,
                                                 GdkEventButton *event,
                                                 icon_selection_t *iconsel);
void iconsel_selected_apply_btn_clicked(GtkButton *widget,
                                        icon_selection_t *iconsel);
static void       iconsel_filter_entry_changed(GtkWidget *entry,
                                               icon_selection_t *iconsel);
static void       iconsel_path_add_clicked(GtkWidget *button,
                                           icon_selection_t *iconsel);
static void       iconsel_exts_add_clicked(GtkWidget *button,
                                           icon_selection_t *iconsel);
static void iconsel_path_col_clicked(GtkWidget *button,
                                     icon_selection_t *iconsel);
static void iconsel_path_exp_clicked(GtkWidget *button,
                                     icon_selection_t *iconsel);
static void iconsel_path_cereimg_clicked(Cereimg *cell, gchar *path_str,
                                         icon_selection_t *iconsel);
static void tree_column_set_label_and_tooltips(icon_selection_t *iconsel,
                                               GtkTreeViewColumn *colunm,
                                               char *title,
                                               char *tooltips);
void iconsel_filter_reset_clicked(GtkButton *widget,
                                  icon_selection_t *iconsel);
void iconsel_scroll_size_allocate(GtkWidget *scroll, GtkAllocation *alloc,
                                  icon_selection_t *iconsel);

void iconsel_filesel_compute(const char *olddir, const char *newdir, void *data);

// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
void iconsel_refresh(icon_selection_t *iconsel)
{
  g_assert(iconsel != NULL);
  TRACE("%s", "");
  iconsel_reload(iconsel);
  iconsel_refresh_selected(iconsel);
  iconsel_exts_refresh(iconsel);
  iconsel_path_refresh(iconsel);
}
// ----------------------------------------------------------------------------
void iconsel_refresh_selected(icon_selection_t *iconsel)
{
  gchar      res[256];
  ico_t     *ico;
  g_assert(iconsel != NULL);
  TRACE("%s", "");

  ico = icon_list_get_selected_icon(iconsel->icons);
  if (ico != NULL)
  {
    gtk_widget_set_sensitive(iconsel->selected_frame, TRUE);
    gtk_image_set_from_pixbuf(GTK_IMAGE(iconsel->selected_image), ico->pixbuf);
    gtk_label_set_text(GTK_LABEL(iconsel->selected_file_label), ico->name);
    gtk_label_set_text(GTK_LABEL(iconsel->selected_path_label), ico->dir->path);
    sprintf(res, "initial size: %d x %d", ico->width, ico->height);
    gtk_label_set_text(GTK_LABEL(iconsel->selected_res_label), res);
  }
  else                                          // no app selected
  {
    gtk_widget_set_sensitive(iconsel->selected_frame, FALSE);
    gtk_image_set_from_pixbuf(GTK_IMAGE(iconsel->selected_image),
                              iconsel->transparent_pixbuf);
    gtk_label_set_text(GTK_LABEL(iconsel->selected_file_label), "");
    gtk_label_set_text(GTK_LABEL(iconsel->selected_path_label), "");
    gtk_label_set_text(GTK_LABEL(iconsel->selected_res_label), "");
  }
}
// ----------------------------------------------------------------------------
void iconsel_reload(icon_selection_t *iconsel)
{
  GdkPixbuf *pixbuf;
  g_assert(iconsel != NULL);
  TRACE("%s", "");
  icon_list_select(iconsel->icons, iconsel_select_func, iconsel);
  pixbuf = icon_list_pixbuf(iconsel->icons);
  gtk_image_set_from_pixbuf(GTK_IMAGE(iconsel->image), pixbuf);
}
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
void iconsel_build_interface(icon_selection_t *iconsel)
{
//         *notebook;
//            *iconsel_frame;
//            *iconsel_pref_frame;
  GdkPixbuf *pix1;
  g_assert(iconsel != NULL);
  TRACE("%s", "");

  iconsel->transparent_pixbuf =
                    gdk_pixbuf_new_from_apwal("transparent", NULL, NULL);
  iconsel->pixbuf_open = gdk_pixbuf_new_from_apwal("relief", NULL, NULL);
  pix1 = gtk_widget_render_icon(iconsel->apwal->window, "gtk-open",
                                GTK_ICON_SIZE_MENU, NULL);
  gdk_pixbuf_append(iconsel->pixbuf_open, pix1);


  iconsel_build_iconsel(iconsel);
  iconsel_build_iconsel_pref(iconsel);
  iconsel_exts_refresh(iconsel);
  //iconsel_refresh(iconsel);
  //gtk_entry_set_text(GTK_ENTRY(iconsel->filter_entry), "");
}
// ----------------------------------------------------------------------------
static void iconsel_build_iconsel(icon_selection_t *iconsel)
{
  GtkWidget *iconsel_vbox;
//GtkWidget   *iconsel->selected_frame;
  GtkWidget     *info_hbox;
  GtkWidget       *info_event_box;
//GtkWidget         *iconsel->selected_image;
  GtkWidget       *info_lbl_vbox;
//GtkWidget         *iconsel->selected_file_label;
//GtkWidget         *iconsel->selected_path_label;
//GtkWidget         *iconsel->selected_res_label;
  GtkWidget         *info_apply_vbox;
//GtkWidget         *iconsel->selected_apply_btn;
  GtkWidget   *filter_frame;
  GtkWidget   *filter_hbox;
//GtkWidget     *filter_entry;
//GtkSizeGroup  *size_group;
  GtkWidget   *scroll;
  GtkWidget     *event_box;
//GtkWidget       *image;
  GtkSizeGroup *sizegrp;        // for 'apply' and 'reset' button

  GtkRequisition requisition;

  g_assert(iconsel != NULL);
  g_assert(iconsel->apwal != NULL);
  g_assert(iconsel->apwal->iconsel_frame != NULL);
  TRACE("%s", "");

  //sizegrp = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
  sizegrp = gtk_size_group_new(GTK_SIZE_GROUP_BOTH);
  
  // vertical box iconsel
  iconsel_vbox = gtk_vbox_new(FALSE, 0);
  gtk_container_add(GTK_CONTAINER(iconsel->apwal->iconsel_frame),
                    iconsel_vbox);
  gtk_container_set_border_width(GTK_CONTAINER(iconsel_vbox), 4);
  gtk_widget_show(iconsel_vbox);

  // info frame
  iconsel->selected_frame = gtk_frame_new(" Selected Icon ");
  gtk_container_set_border_width(GTK_CONTAINER(iconsel->selected_frame), 4);
  gtk_box_pack_start(GTK_BOX(iconsel_vbox), iconsel->selected_frame,
                             FALSE, FALSE, 0);
  gtk_widget_show(iconsel->selected_frame);
  
  // info horizontal box
  info_hbox = gtk_hbox_new(FALSE, 0);
  gtk_container_set_border_width(GTK_CONTAINER(info_hbox), 4);
  gtk_box_set_spacing(GTK_BOX(info_hbox), 4);
  gtk_container_add(GTK_CONTAINER(iconsel->selected_frame), info_hbox);
  gtk_widget_show(info_hbox);

  // event box selected image
  info_event_box = gtk_event_box_new();
  g_signal_connect(G_OBJECT(info_event_box), "button-release-event",
                          G_CALLBACK(iconsel_selected_release_event), iconsel);
  gtk_box_pack_start(GTK_BOX(info_hbox), info_event_box, FALSE, FALSE, 0);
  gtk_widget_show(info_event_box);

  // info image
  iconsel->selected_image = gtk_image_new();
  gtk_container_add(GTK_CONTAINER(info_event_box), iconsel->selected_image);
  gtk_widget_show(iconsel->selected_image);

  // info label vertical box
  info_lbl_vbox = gtk_vbox_new(FALSE, 0);
  gtk_container_set_border_width(GTK_CONTAINER(info_lbl_vbox), 4);
  gtk_box_pack_start(GTK_BOX(info_hbox), info_lbl_vbox, FALSE, FALSE, 0);
  gtk_widget_show(info_lbl_vbox);

  // info label filename
  iconsel->selected_file_label = gtk_label_new(NULL);
  gtk_misc_set_alignment(GTK_MISC(iconsel->selected_file_label), 0.0, 0.5);
  gtk_box_pack_start(GTK_BOX(info_lbl_vbox), iconsel->selected_file_label,
                     TRUE, TRUE, 0);
  gtk_widget_show(iconsel->selected_file_label);

  // info label path
  iconsel->selected_path_label = gtk_label_new(NULL);
  gtk_misc_set_alignment(GTK_MISC(iconsel->selected_path_label), 0.0, 0.5);
  gtk_box_pack_start(GTK_BOX(info_lbl_vbox), iconsel->selected_path_label,
                     TRUE, TRUE, 0);
  gtk_widget_show(iconsel->selected_path_label);

  // info label res
  iconsel->selected_res_label = gtk_label_new(NULL);
  gtk_misc_set_alignment(GTK_MISC(iconsel->selected_res_label), 0.0, 0.5);
  gtk_box_pack_start(GTK_BOX(info_lbl_vbox), iconsel->selected_res_label,
                     TRUE, TRUE, 0);
  gtk_widget_show(iconsel->selected_res_label);

  // info label vertical box
  info_apply_vbox = gtk_vbox_new(FALSE, 0);
  //gtk_container_set_border_width(GTK_CONTAINER(info_apply_vbox), 4);
  gtk_box_pack_end(GTK_BOX(info_hbox), info_apply_vbox, FALSE, FALSE, 0);
  gtk_widget_show(info_apply_vbox);

  // button apply
  iconsel->selected_apply_btn = gtk_button_new_from_stock(GTK_STOCK_APPLY);
  g_signal_connect(G_OBJECT(iconsel->selected_apply_btn), "clicked",
                   G_CALLBACK(iconsel_selected_apply_btn_clicked), iconsel);
  gtk_size_group_add_widget(sizegrp, iconsel->selected_apply_btn);
  gtk_box_pack_end(GTK_BOX(info_apply_vbox), iconsel->selected_apply_btn,
                   FALSE, FALSE, 0);
  gtk_tooltips_set_tip(iconsel->apwal->tips, iconsel->selected_apply_btn, "Set the icon for the current selected application", NULL);
  if (iconsel->apwal->apwal_pref->iconsel_in_a_separate_window == FALSE)
    gtk_widget_show(iconsel->selected_apply_btn);
  

  // filter frame
  filter_frame = gtk_frame_new(" Filename Filter ");
  gtk_container_set_border_width(GTK_CONTAINER(filter_frame), 4);
  gtk_box_pack_start(GTK_BOX(iconsel_vbox), filter_frame, FALSE, FALSE, 0);
  gtk_widget_show(filter_frame);
  
  // horizontal box 'filter'
  filter_hbox = gtk_hbox_new(FALSE, 0);
  gtk_container_set_border_width(GTK_CONTAINER(filter_hbox), 4);
  gtk_box_set_spacing(GTK_BOX(filter_hbox), 4);
  gtk_container_add(GTK_CONTAINER(filter_frame), filter_hbox);
  //gtk_box_pack_start(GTK_BOX(iconsel_vbox), filter_hbox, FALSE, FALSE, 0);
  gtk_widget_show(filter_hbox);
  // entry 'filter'
  iconsel->filter_entry = gtk_entry_new();
  gtk_entry_set_text(GTK_ENTRY(iconsel->filter_entry), iconsel->filter);
  g_signal_connect(iconsel->filter_entry, "changed",
                   G_CALLBACK(iconsel_filter_entry_changed), iconsel);
  gtk_box_pack_start(GTK_BOX(filter_hbox), iconsel->filter_entry,
                     TRUE, TRUE, 0);
  gtk_tooltips_set_tip(iconsel->apwal->tips, iconsel->filter_entry, "Filter the icons displayed, you can use the wildcard '*'.\nFor example 'gnome*' will display the majority of Gnome icons", NULL);
  gtk_widget_show(iconsel->filter_entry);

  // button reset filter
  iconsel->filter_btn = gtk_button_new_with_label("All Icons");
  g_signal_connect(G_OBJECT(iconsel->filter_btn), "clicked",
                   G_CALLBACK(iconsel_filter_reset_clicked), iconsel);
  gtk_size_group_add_widget(sizegrp, iconsel->filter_btn);
  gtk_box_pack_end(GTK_BOX(filter_hbox), iconsel->filter_btn, FALSE, FALSE, 0);
  gtk_tooltips_set_tip(iconsel->apwal->tips, iconsel->filter_btn, "Reset the filter and show all the icons are visible", NULL);
  gtk_widget_show(iconsel->filter_btn);

  // scrolled window
  scroll = gtk_scrolled_window_new(NULL, NULL);
  //gtk_container_set_border_width(GTK_CONTAINER(scroll), 4);
  gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll),
                                  GTK_POLICY_NEVER, GTK_POLICY_ALWAYS);
  g_signal_connect(G_OBJECT(scroll), "size-allocate",
                   G_CALLBACK(iconsel_scroll_size_allocate), iconsel);
  gtk_box_pack_start(GTK_BOX(iconsel_vbox), scroll, TRUE, TRUE, 0);
  
  // ./!\.IMPORTANT./!\.
  // the scrolled windows is NOT showed before the image loaded
  // because of a problem with the vertical scrollbar :(
  // so the scrolled window is actually show with the gtk_widget_show_all
  // of the main window in apwalapp.c
  if (iconsel->apwal->apwal_pref->iconsel_in_a_separate_window)
    gtk_widget_show(scroll);

  // event box
  event_box = gtk_event_box_new();
  gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scroll),
                                        event_box);
  g_signal_connect(G_OBJECT(event_box), "button-release-event",
                          G_CALLBACK(iconsel_release_event), iconsel);
  gtk_widget_show(event_box);

  // image
  iconsel->image = gtk_image_new();
  gtk_misc_set_alignment(GTK_MISC(iconsel->image), 0.0, 0.0);
  gtk_container_add(GTK_CONTAINER(event_box), iconsel->image);
  gtk_widget_show(iconsel->image);
 
  // get the size of the scoll widget. it is the size of it border.
  gtk_widget_size_request(scroll, &requisition);
  iconsel->scroll_border_width = requisition.width;
  TRACE("scroll_border_width: %d", iconsel->scroll_border_width);

}
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
static void iconsel_build_iconsel_pref(icon_selection_t *iconsel)
{
  GtkWidget *selpref_vbox;
  GtkWidget   *path_frame;
  GtkWidget     *path_vbox;
  GtkWidget       *path_scroll;
//GtkWidget         *path_tree;
  GtkWidget       *path_hbox;
  GtkSizeGroup    *sizegrp;
  GtkWidget         *path_btn_add;
  GtkWidget         *path_btn_col;
  GtkWidget         *path_btn_exp;
//GtkWidget         *path_btn_notsel;
  GtkWidget   *hbox;
  GtkWidget     *vbox;
  GtkWidget       *option_frame;
  GtkWidget         *option_vbox;
  GtkWidget           *chk0;
  GtkWidget           *chk1;
  GtkWidget           *chk2;
  GtkWidget       *sort_frame;
  GtkWidget         *sort_vbox;
  GSList            *sort_grp;
  GtkWidget         *sort_chk0;
  GtkWidget         *sort_chk1;
  GtkWidget     *vbox2;
  GtkWidget       *exts_frame;
  GtkWidget         *exts_vbox;
  GtkWidget           *exts_scroll;
//GtkWidget             *exts_tree;
  GtkWidget           *exts_btn_add;

  g_assert(iconsel != NULL);
  g_assert(iconsel->apwal != NULL);
  g_assert(iconsel->apwal->iconsel_pref_frame != NULL);
  TRACE("%s", "");
  
  // horizontal box
  selpref_vbox = gtk_vbox_new(FALSE, 0);
  gtk_container_add(GTK_CONTAINER(iconsel->apwal->iconsel_pref_frame),
                    selpref_vbox);
  gtk_widget_show(selpref_vbox);

  // pixmap path frame
  path_frame = gtk_frame_new(" Pixmap Path ");
  gtk_container_set_border_width(GTK_CONTAINER(path_frame), 4);
  gtk_box_pack_end(GTK_BOX(selpref_vbox), path_frame, TRUE, TRUE, 0);
  gtk_widget_show(path_frame);
  
  // vertical box 'path'
  path_vbox = gtk_vbox_new(FALSE, 0);
  gtk_container_add(GTK_CONTAINER(path_frame), path_vbox);
  gtk_container_set_border_width(GTK_CONTAINER(path_vbox), 4);
  gtk_widget_show(path_vbox);

  // scrolled for path treeview
  path_scroll = gtk_scrolled_window_new(NULL, NULL);
  //gtk_container_set_border_width(GTK_CONTAINER(path_scroll), 4);
  gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(path_scroll),
                                  GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
  gtk_box_pack_start(GTK_BOX(path_vbox), path_scroll, TRUE, TRUE, 0);
  gtk_widget_show(path_scroll);

  // treeview 'pixmap path'
  iconsel->path_tree = iconsel_tree_path_new(iconsel);
  //gtk_box_pack_start(GTK_BOX(path_vbox), iconsel->path_tree, FALSE, FALSE, 0);
  gtk_container_add(GTK_CONTAINER(path_scroll), iconsel->path_tree);
  gtk_widget_show(iconsel->path_tree);

  // vertical box 'exts'
  path_hbox = gtk_hbox_new(FALSE, 0);
  gtk_container_set_border_width(GTK_CONTAINER(path_hbox), 4);
  gtk_box_set_spacing(GTK_BOX(path_hbox), 4);
  gtk_box_pack_start(GTK_BOX(path_vbox), path_hbox, FALSE, FALSE, 0);
  gtk_widget_show(path_hbox);

  sizegrp = gtk_size_group_new(GTK_SIZE_GROUP_BOTH);
  
  // button add path
  path_btn_add = gtk_button_new_from_stock(GTK_STOCK_ADD);
  g_signal_connect(G_OBJECT(path_btn_add), "clicked",
                   G_CALLBACK(iconsel_path_add_clicked), iconsel);
  gtk_box_pack_start(GTK_BOX(path_hbox), path_btn_add, TRUE, TRUE, 0);
  gtk_widget_show(path_btn_add);
  gtk_size_group_add_widget(sizegrp,path_btn_add);
  
  // path button collapse
  path_btn_col = gtk_button_new_with_label("Collapse All");
  g_signal_connect(G_OBJECT(path_btn_col), "clicked",
                   G_CALLBACK(iconsel_path_col_clicked), iconsel);
  gtk_box_pack_start(GTK_BOX(path_hbox), path_btn_col, TRUE, TRUE, 0);
  gtk_widget_show(path_btn_col);
  gtk_size_group_add_widget(sizegrp, path_btn_col);
  
  // path button expand
  path_btn_exp = gtk_button_new_with_label("Expand All");
  g_signal_connect(G_OBJECT(path_btn_exp), "clicked",
                   G_CALLBACK(iconsel_path_exp_clicked), iconsel);
  gtk_box_pack_start(GTK_BOX(path_hbox), path_btn_exp, TRUE, TRUE, 0);
  gtk_widget_show(path_btn_exp);
  gtk_size_group_add_widget(sizegrp, path_btn_exp);
  
#if 0 /* DEBUG SELECTED */
  // path button not selected
  path_btn_notsel = gtk_button_new_with_label("Print !selected");
  g_signal_connect(G_OBJECT(path_btn_notsel), "clicked",
                   G_CALLBACK(iconsel_path_notsel_clicked), iconsel);
  gtk_box_pack_start(GTK_BOX(path_hbox), path_btn_notsel, TRUE, TRUE, 0);
  gtk_widget_show(path_btn_notsel);
#endif 
  
  // horizontal box option and sort on the left, extension on the right
  hbox = gtk_hbox_new(FALSE, 0);
  gtk_box_pack_start(GTK_BOX(selpref_vbox), hbox, FALSE, FALSE, 0);
  gtk_widget_show(hbox);

  // vertical box option and sort
  vbox = gtk_vbox_new(FALSE, 0);
  gtk_box_pack_start(GTK_BOX(hbox), vbox, TRUE, TRUE, 0);
  gtk_widget_show(vbox);

  // options frame
  option_frame = gtk_frame_new(" Icon Resolution ");
  gtk_container_set_border_width(GTK_CONTAINER(option_frame), 6);
  gtk_box_pack_start(GTK_BOX(vbox), option_frame, TRUE, TRUE, 0);
  gtk_widget_show(option_frame);

  // option vbox
  option_vbox = gtk_vbox_new(FALSE, 0);
  gtk_container_set_border_width(GTK_CONTAINER(option_vbox), 4);
  gtk_container_add(GTK_CONTAINER(option_frame), option_vbox);
  gtk_widget_show(option_vbox);

  // check button
  chk0 = gtk_check_button_new_with_label("48x48 icons");
  gtk_box_pack_start(GTK_BOX(option_vbox), chk0, FALSE, FALSE, 0);
  gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(chk0), iconsel->apwal->iconsel_pref->select_48);
  g_signal_connect(G_OBJECT(chk0), "toggled",
                   G_CALLBACK(iconsel_48_toggled), iconsel);
  gtk_tooltips_set_tip(iconsel->apwal->tips, chk0, "Filter icons when there are loaded from disk.\nSelect 48x48 pixels icons (Strongly recommanded)", NULL);
  gtk_widget_show(chk0);

  // check button
  chk1 = gtk_check_button_new_with_label("Smaller than 48x48 icons");
  gtk_box_pack_start(GTK_BOX(option_vbox), chk1, FALSE, FALSE, 0);
  gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(chk1), iconsel->apwal->iconsel_pref->select_lt48);
  g_signal_connect(G_OBJECT(chk1), "toggled",
                   G_CALLBACK(iconsel_lt48_toggled), iconsel);
  gtk_tooltips_set_tip(iconsel->apwal->tips, chk1, "Filter icons when there are loaded from disk.\nSelect icons smaller that 48x48 pixels", NULL);
  gtk_widget_show(chk1);

  // check button
  chk2 = gtk_check_button_new_with_label("Bigger than 48x48 icons");
  gtk_box_pack_start(GTK_BOX(option_vbox), chk2, FALSE, FALSE, 0);
  gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(chk2), iconsel->apwal->iconsel_pref->select_gt48);
  g_signal_connect(G_OBJECT(chk2), "toggled", 
                   G_CALLBACK(iconsel_gt48_toggled), iconsel);
  gtk_tooltips_set_tip(iconsel->apwal->tips, chk2, "Filter icons when there are loaded from disk. Select icons bigger that 48x48 pixels", NULL);
  gtk_widget_show(chk2);

  // sort frame
  sort_frame = gtk_frame_new(" Sort Order ");
  gtk_container_set_border_width(GTK_CONTAINER(sort_frame), 6);
  gtk_box_pack_start(GTK_BOX(vbox), sort_frame, TRUE, TRUE, 0);
  gtk_widget_show(sort_frame);

  // sort vbox
  sort_vbox = gtk_vbox_new(FALSE, 0);
  gtk_container_set_border_width(GTK_CONTAINER(sort_vbox), 4);
  gtk_container_add(GTK_CONTAINER(sort_frame), sort_vbox);
  gtk_widget_show(sort_vbox);

  // radio button
  sort_chk0 = gtk_radio_button_new_with_label(NULL, "Sort by Name");
  sort_grp = gtk_radio_button_get_group(GTK_RADIO_BUTTON(sort_chk0));
  gtk_box_pack_start(GTK_BOX(sort_vbox), sort_chk0, FALSE, FALSE, 0);
  gtk_tooltips_set_tip(iconsel->apwal->tips, sort_chk0, "Order of the icons displayed in the 'Icon Selection' tab.\nIn this case icons are only sorted by name", NULL);
  gtk_widget_show(sort_chk0);

  // radio button
  sort_chk1 = gtk_radio_button_new_with_label(sort_grp, "Sort by Path, Name");
  gtk_box_pack_start(GTK_BOX(sort_vbox), sort_chk1, FALSE, FALSE, 0);
  gtk_tooltips_set_tip(iconsel->apwal->tips, sort_chk1, "Order of the icons displayed in the 'Icon Selection' tab.\nIcons will be sorted by directory then by name in each directory", NULL);
  gtk_widget_show(sort_chk1);

  // set the sort toggle button AND connect the signals. signals are executed
  // by set_active() and the interface is not currently fully loaded
  if (iconsel->apwal->iconsel_pref->sort_mode == ICONSEL_SORT_NAME)
    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(sort_chk0), TRUE);
  else if (iconsel->apwal->iconsel_pref->sort_mode == ICONSEL_SORT_PATH)
    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(sort_chk1), TRUE);

  g_signal_connect(G_OBJECT(sort_chk0), "toggled",
                   G_CALLBACK(iconsel_sort_name_clicked), iconsel);
  g_signal_connect(G_OBJECT(sort_chk1), "toggled",
                   G_CALLBACK(iconsel_sort_path_clicked), iconsel);

  // vertical box extension frame
  vbox2 = gtk_vbox_new(FALSE, 0);
  gtk_box_pack_start(GTK_BOX(hbox), vbox2, TRUE, TRUE, 0);
  gtk_widget_show(vbox2);

  // pixmap exts frame
  exts_frame = gtk_frame_new(" File Extensions ");
  gtk_container_set_border_width(GTK_CONTAINER(exts_frame), 4);
  gtk_box_pack_start(GTK_BOX(vbox2), exts_frame, TRUE, TRUE, 0);
  gtk_widget_show(exts_frame);

  // vertical box 'exts'
  exts_vbox = gtk_vbox_new(FALSE, 0);
  gtk_container_add(GTK_CONTAINER(exts_frame), exts_vbox);
  gtk_container_set_border_width(GTK_CONTAINER(exts_vbox), 4);
  gtk_widget_show(exts_vbox);

  // scrolled for exts treeview
  exts_scroll = gtk_scrolled_window_new(NULL, NULL);
  //gtk_container_set_border_width(GTK_CONTAINER(exts_scroll), 4);
  gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(exts_scroll),
                                  GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
  gtk_box_pack_start(GTK_BOX(exts_vbox), exts_scroll, TRUE, TRUE, 0);
  gtk_widget_show(exts_scroll);

  // treeview 'extension'
  iconsel->exts_tree = iconsel_tree_exts_new(iconsel);
  //gtk_box_pack_start(GTK_BOX(exts_vbox), iconsel->exts_tree, FALSE, FALSE, 0);
  gtk_container_add(GTK_CONTAINER(exts_scroll), iconsel->exts_tree);
  gtk_widget_show(iconsel->exts_tree);

  // extension button add
  exts_btn_add = gtk_button_new_from_stock(GTK_STOCK_ADD);
  g_signal_connect(G_OBJECT(exts_btn_add), "clicked",
                   G_CALLBACK(iconsel_exts_add_clicked), iconsel);
  gtk_box_pack_start(GTK_BOX(exts_vbox), exts_btn_add, FALSE, FALSE, 0);
  gtk_tooltips_set_tip(iconsel->apwal->tips, exts_btn_add, "Filter icons when there are loaded from disk.\nOnly icons which match one of this extension will be loaded", NULL);
  gtk_widget_show(exts_btn_add);

}
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
static void iconsel_48_toggled(GtkToggleButton *chk, icon_selection_t *iconsel)
{
  g_assert((chk != NULL) && (iconsel != NULL));
  g_assert(iconsel->apwal->iconsel_pref);
  TRACE("%s", "");
  iconsel->apwal->iconsel_pref->select_48 = gtk_toggle_button_get_active(chk);
  TRACE("bool:%d", iconsel->apwal->iconsel_pref->select_48);
  icon_list_reload_all_with_splash(iconsel->icons);
  iconsel_refresh(iconsel);
}
// ----------------------------------------------------------------------------
static void iconsel_lt48_toggled(GtkToggleButton *chk,
                                 icon_selection_t *iconsel)
{
  g_assert((chk != NULL) && (iconsel != NULL));
  g_assert(iconsel->apwal->iconsel_pref);
  TRACE("%s", "");
  iconsel->apwal->iconsel_pref->select_lt48 = gtk_toggle_button_get_active(chk);
  TRACE("bool:%d", iconsel->apwal->iconsel_pref->select_lt48);
  icon_list_reload_all_with_splash(iconsel->icons);
  iconsel_refresh(iconsel);
}
// ----------------------------------------------------------------------------
static void iconsel_gt48_toggled(GtkToggleButton *chk,
                                 icon_selection_t *iconsel)
{
  g_assert((chk != NULL) && (iconsel != NULL));
  g_assert(iconsel->apwal->iconsel_pref);
  TRACE("%s", "");
  iconsel->apwal->iconsel_pref->select_gt48 = gtk_toggle_button_get_active(chk);
  TRACE("bool:%d", iconsel->apwal->iconsel_pref->select_gt48);
  icon_list_reload_all_with_splash(iconsel->icons);
  iconsel_refresh(iconsel);
}
// ----------------------------------------------------------------------------
static void iconsel_sort_name_clicked(GtkRadioButton *chk,
                                      icon_selection_t *iconsel)
{
  g_assert((chk != NULL) && (iconsel != NULL));
  g_assert(iconsel->apwal->iconsel_pref);
  TRACE("%s", "");
  iconsel->apwal->iconsel_pref->sort_mode = ICONSEL_SORT_NAME;
  TRACE("sort:%d", iconsel->apwal->iconsel_pref->sort_mode);
  icon_list_set_sortmode(iconsel->icons, iconsel->apwal->iconsel_pref->sort_mode);
  iconsel_refresh(iconsel);
}
// ----------------------------------------------------------------------------
static void iconsel_sort_path_clicked(GtkRadioButton *chk,
                                      icon_selection_t *iconsel)
{
  g_assert((chk != NULL) && (iconsel != NULL));
  g_assert(iconsel->apwal->iconsel_pref);
  TRACE("%s", "");
  iconsel->apwal->iconsel_pref->sort_mode = ICONSEL_SORT_PATH;
  TRACE("sort:%d", iconsel->apwal->iconsel_pref->sort_mode);
  icon_list_set_sortmode(iconsel->icons, iconsel->apwal->iconsel_pref->sort_mode);
  iconsel_refresh(iconsel);
}
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
static void iconsel_path_toggled(GtkCellRendererToggle *cell,
                                gchar *path_str, icon_selection_t *iconsel)
{
  GtkTreeModel *model;
  GtkTreePath  *path;
  GtkTreeIter iter;
  //gboolean cell_active;
  gboolean selected;
  char *dirname;
  GList *hamster;
  icon_dir_t *dir1;

  g_assert(cell != NULL && path_str != NULL && iconsel != NULL);
  TRACE("%s", "");
  model = gtk_tree_view_get_model(GTK_TREE_VIEW(iconsel->path_tree));
  
  path = gtk_tree_path_new_from_string(path_str);
  gtk_tree_model_get_iter(model, &iter, path);
  gtk_tree_path_free(path);

  gtk_tree_model_get(model, &iter, 0, &dirname, 1, &selected, -1);
  TRACE("path:%s, dir:%s, old selected:%d, new selected:%d",
         path_str, dirname, selected, !selected);
  selected = ! selected;
  
  hamster = g_list_first(iconsel->apwal->iconsel_pref->icon_dirs);
  while (hamster != NULL)
  {
    dir1 = hamster->data;
    if (strcmp(dir1->path, dirname) == 0)
    {
      dir1->selected = selected;
      break;
    }
    hamster = g_list_next(hamster);
  }
  if (hamster == NULL)
    ERR("dir:%s not found in iconsel->apwal->iconsel_pref->icon_dirs", dirname);

  icon_list_set_selected(iconsel->icons, dirname, selected);
  iconsel_refresh(iconsel);
}
// ----------------------------------------------------------------------------
static void iconsel_path_toggled_rec(GtkCellRendererToggle *cell,
                                     gchar *path_str, icon_selection_t *iconsel)
{
  GtkTreeModel *model;
  GtkTreePath  *path;
  GtkTreeIter iter;
  //gboolean cell_active;
  gboolean recursive;
  char *dirname;
  GList *hamster;
  icon_dir_t *dir1;

  // Deactivate this signal during the processing of this function
  // It will be reactivated at the end of the function.
  // The problem is that if someone click too quicly he may be able
  // to launche twice the function and ask for something wrong
  // (ask for recusive path a path which is still recusive because
  // the current processing of the function is making it not recursive
  // for example).
  g_signal_handlers_block_by_func(cell, iconsel_path_toggled_rec, iconsel);

  g_assert(cell != NULL && path_str != NULL && iconsel != NULL);
  TRACE("%s", "");
  model = gtk_tree_view_get_model(GTK_TREE_VIEW(iconsel->path_tree));
  
  path = gtk_tree_path_new_from_string(path_str);
  gtk_tree_model_get_iter(model, &iter, path);
  gtk_tree_path_free(path);

  gtk_tree_model_get(model, &iter, 0, &dirname, 2, &recursive, -1);
  TRACE("path:%s, dir:%s, old recursive:%d, new recursive:%d",
         path_str, dirname, recursive, !recursive);
  recursive = ! recursive;
  
  hamster = g_list_first(iconsel->apwal->iconsel_pref->icon_dirs);
  while (hamster != NULL)
  {
    dir1 = hamster->data;
    if (strcmp(dir1->path, dirname) == 0)
    {
      dir1->recursive = recursive;
      break;
    }
    hamster = g_list_next(hamster);
  }
  if (hamster == NULL)
    ERR("dir:%s not found in iconsel->apwal->iconsel_pref->icon_dirs", dirname);

  if (recursive == FALSE)  // it is very quick so no need of splash screen
    icon_list_set_recursive(iconsel->icons, dirname, recursive);
  else
    icon_list_set_recursive_with_splash(iconsel->icons, dirname, recursive);
  g_free(dirname);
  iconsel_refresh(iconsel);

  g_signal_handlers_unblock_by_func(cell, iconsel_path_toggled_rec, iconsel);
}
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
static void iconsel_exts_toggled(GtkCellRendererToggle *cell,
                                gchar *path_str, icon_selection_t *iconsel)
{
  GtkTreeModel *model;
  GtkTreePath  *path;
  GtkTreeIter iter;
  gboolean selected;
  char *extension;
  GList *hamster;
  file_ext_t *ext;

  g_assert(cell != NULL && path_str != NULL && iconsel != NULL);
  TRACE("%s", "");
  model = gtk_tree_view_get_model(GTK_TREE_VIEW(iconsel->exts_tree));
  
  path = gtk_tree_path_new_from_string(path_str);
  gtk_tree_model_get_iter(model, &iter, path);
  gtk_tree_path_free(path);

  gtk_tree_model_get(model, &iter, 0, &extension, 1, &selected, -1);
  TRACE("path:%s, extension:%s, old selected:%d, new selected:%d",
        path_str, extension, selected, !selected);
  selected = ! selected;
  
  hamster = g_list_first(iconsel->apwal->iconsel_pref->file_exts);
  while (hamster != NULL)
  {
    ext = hamster->data;
    if (strcmp(ext->extension, extension) == 0)
    {
      ext->selected = selected;
      break;
    }
    hamster = g_list_next(hamster);
  }
  if (hamster == NULL)
    ERR("extension:%s not found", extension);

  icon_list_reload_all_with_splash(iconsel->icons);
  iconsel_refresh(iconsel);
}

// ----------------------------------------------------------------------------
static void iconsel_path_edited(GtkCellRendererText *cell,
                                gchar *path_str, gchar *newtext,
                                icon_selection_t *iconsel)
{
  GtkTreeModel *model;
  GtkTreePath  *path;
  GtkTreeIter  iter;
  gboolean     selected;
  char        *dirname, *newdir;
  icodir_t    *icodir;

  g_assert(cell != NULL && path_str != NULL && newtext != NULL &&
           iconsel != NULL);
  TRACE("path:%s, newtext:%s", path_str, newtext);

  model = gtk_tree_view_get_model(GTK_TREE_VIEW(iconsel->path_tree));
  
  path = gtk_tree_path_new_from_string(path_str);
  gtk_tree_model_get_iter(model, &iter, path);
  gtk_tree_path_free(path);

  gtk_tree_model_get(model, &iter, 0, &dirname, 1, &selected, -1);
  TRACE("path:%s, dirname:%s, new:%s, selected:%d",
          path_str, dirname, newtext, selected);
  

  // if the newtext is empty, remove the line
  if (strcmp("", newtext) == 0)
  {
    icon_dir_list_remove(&iconsel->apwal->iconsel_pref->icon_dirs, dirname);
    icon_list_remove(iconsel->icons, dirname);
  }
  else
  {
    newdir = g_strdup(newtext);
    make_path_uniq(&newdir);
    icodir = icon_list_find_path(iconsel->icons, newdir);
    if (icodir != NULL)
    {
      if (icodir->parent == NULL)
      {
        TRACE("dir:%s already exist and is a parent dir, nothing to do",
              newdir);
        g_free(newdir);
        g_free(dirname);
        return;
      }
    }
    icon_dir_list_modify(&iconsel->apwal->iconsel_pref->icon_dirs, dirname, newdir);
    icon_list_modify_with_splash(iconsel->icons, dirname, newdir);
    g_free(newdir);
  }
  g_free(dirname);
  iconsel_refresh(iconsel);
}
// ----------------------------------------------------------------------------
static void iconsel_exts_edited(GtkCellRendererText *cell,
 gchar *path_str, gchar *newtext, icon_selection_t *iconsel)
{
  GtkTreeModel *model;
  GtkTreePath  *path;
  GtkTreeIter iter;
  gboolean selected;
  char *extension;

  g_assert(cell != NULL && path_str != NULL && newtext != NULL &&
           iconsel != NULL);
  TRACE("path:%s, newtext:%s", path_str, newtext);
  model = gtk_tree_view_get_model(GTK_TREE_VIEW(iconsel->exts_tree));
  path = gtk_tree_path_new_from_string(path_str);
  gtk_tree_model_get_iter(model, &iter, path);
  gtk_tree_path_free(path);

  gtk_tree_model_get(model, &iter, 0, &extension, 1, &selected, -1);
  TRACE("path:%s, extension:%s, new:%s, selected:%d",
          path_str, extension, newtext, selected);
  
  // if the newtext is empty, remove the line
  if (strcmp("", newtext) == 0)
    file_ext_list_remove(&iconsel->apwal->iconsel_pref->file_exts, extension);
  else
    file_ext_list_modify(&iconsel->apwal->iconsel_pref->file_exts, extension, newtext);

  icon_list_reload_all_with_splash(iconsel->icons);
  iconsel_refresh(iconsel);
}
// ----------------------------------------------------------------------------
static void iconsel_path_refresh_rec(icon_selection_t *iconsel,
                                    GtkTreeModel *model,
                                    icodir_t *dir,
                                    GtkTreeIter   *parent_iter)
{
  GList        *hamster;
  GtkTreeIter   iter;
  icodir_t     *child;
  gboolean      activatable;
  gint          total_rec, total_sel;
  GdkPixbuf    *pixbuf;

  g_assert(iconsel != NULL && model != NULL && dir != NULL);
  //TRACE("%s", "");
  
  activatable = (dir->parent == NULL) ? TRUE : FALSE;
  total_rec = icodir_count_total_rec(dir);
  total_sel = icodir_count_selected_rec(dir);
  pixbuf = (activatable == TRUE) ? iconsel->pixbuf_open : NULL ;
  gtk_tree_store_append(GTK_TREE_STORE(model), &iter, parent_iter);
  gtk_tree_store_set(GTK_TREE_STORE(model), &iter, 0, dir->path,
                                                   1, dir->selected,
                                                   2, dir->recursive,
                                                   3, total_rec,
                                                   4, total_sel,
                                                   5, activatable,
                                                   6, pixbuf,
                                                  -1);
  if (dir->recursive)
  {
    hamster = g_list_first(dir->children);
    while (hamster)
    {
      child = hamster->data;
      iconsel_path_refresh_rec(iconsel, model, child, &iter);
      hamster = g_list_next(hamster);
    }
  }
}
// ----------------------------------------------------------------------------
void iconsel_path_refresh(icon_selection_t *iconsel)
{
  GtkTreeModel *model;
  GList        *hamster;
  icodir_t     *icodir;
  g_assert(iconsel != NULL);
  TRACE("%s", "");
  model = gtk_tree_view_get_model(GTK_TREE_VIEW(iconsel->path_tree));
  gtk_tree_store_clear(GTK_TREE_STORE(model));
  hamster = iconsel->icons->dirs;
  while (hamster != NULL)
  {
    icodir = hamster->data;
    if (icodir->parent == NULL)
      iconsel_path_refresh_rec(iconsel, model, icodir, NULL);
    hamster = g_list_next(hamster);
  }
}
// ----------------------------------------------------------------------------
static void iconsel_exts_refresh(icon_selection_t *iconsel)
{
  GtkTreeModel *model;
  GtkTreeIter  iter1;
  GList        *hamster;
  file_ext_t   *file_ext;

  g_assert(iconsel != NULL);
  g_assert(iconsel->apwal->iconsel_pref != NULL);
  TRACE("%s", "");
  model = gtk_tree_view_get_model(GTK_TREE_VIEW(iconsel->exts_tree));
  gtk_tree_store_clear(GTK_TREE_STORE(model));
  hamster = iconsel->apwal->iconsel_pref->file_exts;
  while (hamster != NULL)
  {
    file_ext = hamster->data;
    //TRACE("ext:%s", file_ext->extension);
    gtk_tree_store_append(GTK_TREE_STORE(model), &iter1, NULL);
    gtk_tree_store_set(GTK_TREE_STORE(model), &iter1, 0, file_ext->extension,
                                                      1, file_ext->selected,
                                                      -1);
    hamster = g_list_next(hamster);
  }
}
// ----------------------------------------------------------------------------
static GtkWidget *iconsel_tree_path_new(icon_selection_t *iconsel)
{
  GtkTreeStore      *store;
  GtkWidget         *treeview;
  GtkTreeSelection  *select;
  GtkCellRenderer   *renderer;
  GtkTreeViewColumn *column;
  
  g_assert(iconsel != NULL);
  g_assert(iconsel->apwal->iconsel_pref != NULL);
  TRACE("%s", "");
  store = gtk_tree_store_new(7, G_TYPE_STRING, G_TYPE_BOOLEAN, G_TYPE_BOOLEAN,
                                G_TYPE_INT, G_TYPE_INT, G_TYPE_BOOLEAN,
                                GDK_TYPE_PIXBUF);
  
  treeview = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store));
  g_object_unref(G_OBJECT(store));
  gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(treeview), TRUE);
  gtk_tree_view_set_headers_clickable(GTK_TREE_VIEW(treeview), TRUE);
  gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(treeview), TRUE);
  
  select = gtk_tree_view_get_selection(GTK_TREE_VIEW(treeview));
  gtk_tree_selection_set_mode(select, GTK_SELECTION_SINGLE);


  // cereimg for file selction
  renderer = cereimg_new();
  g_object_set(renderer, 
                         "activatable", TRUE,
//                       "pixbuf", pixbuf_open,
//                       "background", "#ccccff",
//                       "active", TRUE,
                         NULL);
  g_signal_connect(G_OBJECT(renderer), "clicked",
                   G_CALLBACK(iconsel_path_cereimg_clicked), iconsel);
  column = gtk_tree_view_column_new_with_attributes(
             NULL, renderer, "pixbuf", 6, NULL);
  gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column);
  tree_column_set_label_and_tooltips(iconsel, column, "", "Launch the File Selection Dialog Box to select a new Pixmap Path");

    
  // selected
  renderer = gtk_cell_renderer_toggle_new();
  //g_object_set(renderer, "activatable", TRUE, NULL);
  g_signal_connect(G_OBJECT(renderer), "toggled",
                    G_CALLBACK(iconsel_path_toggled), iconsel);
  column = gtk_tree_view_column_new_with_attributes(
             NULL, renderer, "active", 1, "activatable", 5, NULL);
  gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column);
  tree_column_set_label_and_tooltips(iconsel, column, "Act", "If toggled, all icons selected in this directory will appear on 'Icon Selection' tab");

  // recursive
  renderer = gtk_cell_renderer_toggle_new();
  g_signal_connect(G_OBJECT(renderer), "toggled",
                    G_CALLBACK(iconsel_path_toggled_rec), iconsel);
  column = gtk_tree_view_column_new_with_attributes(
             NULL, renderer, "active", 2,  "activatable", 5, NULL);
  gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column);
  tree_column_set_label_and_tooltips(iconsel, column, "Rec", 
      "Starts a recursive scan; be wise...\n"
      "Don't launch it on '/' unless you have some time to spend.\n"
      "If 2 paths cross each other the parent will stop its recursive scan at the child directory location."
    );

  // total
  renderer = gtk_cell_renderer_text_new();
  g_object_set(renderer, "editable", FALSE, NULL);
  column = gtk_tree_view_column_new_with_attributes(
             NULL, renderer, "text", 3, NULL);
  gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column);
  tree_column_set_label_and_tooltips(iconsel, column, "Total", "Icons potentialy selectable");

  // selected
  renderer = gtk_cell_renderer_text_new();
  g_object_set(renderer, "editable", FALSE, NULL);
  column = gtk_tree_view_column_new_with_attributes(
            NULL, renderer, "text", 4, NULL);
  gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column);
  tree_column_set_label_and_tooltips(iconsel, column, "Selected", "Icons which match the filter in the 'Icon Selection' tab (0 if 'Act' is not set)");

  // path
  renderer = gtk_cell_renderer_text_new();
  //g_object_set(renderer, "editable", TRUE, NULL);
  g_signal_connect(G_OBJECT(renderer), "edited",
                    G_CALLBACK(iconsel_path_edited), iconsel);
  column = gtk_tree_view_column_new_with_attributes(
             NULL, renderer, "text", 0, "editable", 5, NULL);
  gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column);
  gtk_tree_view_set_expander_column(GTK_TREE_VIEW(treeview), column);
  tree_column_set_label_and_tooltips(iconsel, column, "Pixmap Path", "Directory in which you want to search for icons");

  return treeview;
}
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
static GtkWidget *iconsel_tree_exts_new(icon_selection_t *iconsel)
{
  GtkTreeStore      *store;
  GtkWidget         *treeview;
  GtkTreeSelection  *select;
  GtkCellRenderer   *renderer;
  GtkTreeViewColumn *column;
  
  g_assert(iconsel != NULL);
  g_assert(iconsel->apwal->iconsel_pref != NULL);
  TRACE("%s", "");

  store = gtk_tree_store_new(2, G_TYPE_STRING, G_TYPE_BOOLEAN);
  
  treeview = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store));
  g_object_unref(G_OBJECT(store));
  gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(treeview), FALSE);
  gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(treeview), TRUE);
  
  select = gtk_tree_view_get_selection(GTK_TREE_VIEW(treeview));
  gtk_tree_selection_set_mode(select, GTK_SELECTION_SINGLE);

  renderer = gtk_cell_renderer_toggle_new();
  g_object_set(renderer, "activatable", TRUE, NULL);
  g_signal_connect(G_OBJECT(renderer), "toggled",
                    G_CALLBACK(iconsel_exts_toggled), iconsel);
  column = gtk_tree_view_column_new_with_attributes(
             "selected", renderer, "active", 1, NULL);
  gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column);

  renderer = gtk_cell_renderer_text_new();
  g_object_set(renderer, "editable", TRUE, NULL);
  g_signal_connect(G_OBJECT(renderer), "edited",
                    G_CALLBACK(iconsel_exts_edited), iconsel);
  column = gtk_tree_view_column_new_with_attributes(
             "extension", renderer, "text", 0, NULL);
  gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column);

  return treeview;
}
// -----------------------------------------------------------------------------
static gboolean iconsel_is_dblclick(icon_selection_t *iconsel, gint x, gint y)
{
  gint elapse;
  g_assert(iconsel != NULL);
  TRACE("%s", "");
  if (iconsel->dblclick_timer == NULL)
  {
    iconsel->dblclick_timer = g_timer_new();
    iconsel->dblclick_last_x = x;
    iconsel->dblclick_last_y = y;
    return FALSE;
  }
  elapse = (int)(g_timer_elapsed(iconsel->dblclick_timer, NULL) * 1000);
  g_timer_start(iconsel->dblclick_timer);
  if (iconsel->dblclick_last_x != x || iconsel->dblclick_last_y != y)
  {
    iconsel->dblclick_last_x = x;
    iconsel->dblclick_last_y = y;
    return FALSE;
  }
  if (elapse > DBLCLICK)
    return FALSE;

  return TRUE;
}
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
static gboolean iconsel_release_event(GtkWidget *widget,
                                      GdkEventButton *event,
                                      icon_selection_t *iconsel)
{
  gint   x, y;
  g_assert(widget != NULL && iconsel != NULL && event != NULL);
  TRACE("%s", "");

  x = (int) (event->x / 48);
  y = (int) (event->y / 48);
  
  if (iconsel_is_dblclick(iconsel, x, y))
  {
    TRACE("dblclick x:%d y:%d, app:%p", x, y, iconsel->apwal->selected_app);
    if (iconsel->apwal->selected_app != NULL)
    {
      apwalapp_selected_icon_modified(iconsel->apwal);
      apwalapp_goto_editor(iconsel->apwal);
     }
  }
  else
  {
    TRACE("click x:%d y:%d", x, y);
    icon_list_set_selected_icon_from_xy(iconsel->icons, x, y);
    iconsel_refresh_selected(iconsel);
  }

  return TRUE;
}

// -----------------------------------------------------------------------------
static gboolean iconsel_selected_is_dblclick(icon_selection_t *iconsel)
{
  gint elapse;
  g_assert(iconsel != NULL);
  TRACE("%s", "");
  if (iconsel->dblclick_selected_timer == NULL)
  {
    iconsel->dblclick_selected_timer = g_timer_new();
    return FALSE;
  }
  elapse = (int) (g_timer_elapsed(iconsel->dblclick_selected_timer, NULL)
           * 1000);
  g_timer_start(iconsel->dblclick_selected_timer);
  if (elapse > DBLCLICK)
    return FALSE;

  return TRUE;
}
// ----------------------------------------------------------------------------
static gboolean iconsel_selected_release_event(GtkWidget *widget,
                                               GdkEventButton *event,
                                               icon_selection_t *iconsel)
{
  g_assert(widget != NULL && iconsel != NULL && event != NULL);
  TRACE("%s", "");
  if (icon_list_get_selected_icon(iconsel->icons) == NULL)
  {
    WARN("%s","no icon selected");
    return TRUE;
  }
  if (iconsel_selected_is_dblclick(iconsel))
  {
    if (iconsel->apwal->selected_app != NULL)
    {
      apwalapp_selected_icon_modified(iconsel->apwal);
      apwalapp_goto_editor(iconsel->apwal);
     }
  }
  return TRUE;
}
// ----------------------------------------------------------------------------
void iconsel_selected_apply_btn_clicked(GtkButton *widget,
                                        icon_selection_t *iconsel)
{
  g_assert(widget != NULL && iconsel != NULL);
  TRACE("%s", "");
  if (icon_list_get_selected_icon(iconsel->icons) == NULL)
  {
    TRACE("%s", "no icon selected");
    return;
  }
  if (iconsel->apwal->selected_app != NULL)
  {
    apwalapp_selected_icon_modified(iconsel->apwal);
    apwalapp_goto_editor(iconsel->apwal);
   }
}
// ----------------------------------------------------------------------------
static void iconsel_filter_entry_changed(GtkWidget *entry,
                                         icon_selection_t *iconsel)
{
  const gchar *newfilter;
  g_assert(entry != NULL && iconsel != NULL);
  TRACE("%s", "");
  newfilter = gtk_entry_get_text(GTK_ENTRY(iconsel->filter_entry));
  if (newfilter == NULL)
    ERR("%s", "newfilter NULL, i didn't known that it was possible...");
  TRACE("newfilter:%s", newfilter);
  if (iconsel->filter != NULL)
    g_free(iconsel->filter);
  iconsel->filter = g_strdup(newfilter);
  iconsel_refresh(iconsel);
}
// ----------------------------------------------------------------------------
static void iconsel_path_add_clicked(GtkWidget *button,
                                     icon_selection_t *iconsel)
{
  icon_dir_t *icon_dir;
  //icodir_t   *icodir;
  g_assert((button != NULL) && (iconsel != NULL));
  TRACE("%s", "");
  if (icon_list_find_path(iconsel->icons, "") == NULL)
  {
    TRACE("%s", "add empty icon_dir");
    icon_list_append(iconsel->icons, "", FALSE, FALSE);
    //icodir = icodir_new("", TRUE/*sel*/, FALSE/*rec*/);
    //icodir_list_append(&iconsel->dirlist, icodir, &iconsel->icons->icos);
    icon_dir = icon_dir_new(g_strdup(""), TRUE/*sel*/, FALSE/*rec*/);
    iconsel->apwal->iconsel_pref->icon_dirs = g_list_append(iconsel->apwal->iconsel_pref->icon_dirs,
                                               icon_dir);
    iconsel_refresh(iconsel);
  }
}
// ----------------------------------------------------------------------------
static void iconsel_exts_add_clicked(GtkWidget *button,
                                     icon_selection_t *iconsel)
{
  file_ext_t *ext;
  g_assert((button != NULL) && (iconsel != NULL));
  TRACE("%s", "");
  if (file_ext_list_find(iconsel->apwal->iconsel_pref->file_exts, "") == NULL)
  {
    TRACE("%s", "add empty file_ext");
    ext = file_ext_new(g_strdup(""), TRUE);
    iconsel->apwal->iconsel_pref->file_exts = g_list_append(iconsel->apwal->iconsel_pref->file_exts, ext);
    icon_list_reload_all_with_splash(iconsel->icons);
    iconsel_refresh(iconsel);
  }
}
// ----------------------------------------------------------------------------
static void iconsel_path_col_clicked(GtkWidget *button,
                                     icon_selection_t *iconsel)
{
  g_assert((button != NULL) && (iconsel != NULL));
  TRACE("%s", "");
  gtk_tree_view_collapse_all(GTK_TREE_VIEW(iconsel->path_tree));
  gtk_widget_queue_draw(iconsel->path_tree);
}
// ----------------------------------------------------------------------------
static void iconsel_path_exp_clicked(GtkWidget *button,
                                     icon_selection_t *iconsel)
{
  g_assert((button != NULL) && (iconsel != NULL));
  TRACE("%s", "");
  gtk_tree_view_expand_all(GTK_TREE_VIEW(iconsel->path_tree));
  gtk_widget_queue_draw(iconsel->path_tree);
}
// ----------------------------------------------------------------------------
#if 0 /* DEBUG SELECTED */
static void iconsel_path_notsel_clicked(GtkWidget *button,
                                        icon_selection_t *iconsel);
static void iconsel_path_notsel_clicked(GtkWidget *button,
                                        icon_selection_t *iconsel)
{
  g_assert((button != NULL) && (iconsel != NULL));
  TRACE("%s", "");
  icon_list_print_not_selected(iconsel->icons);
}
#endif
// ----------------------------------------------------------------------------
static void iconsel_path_cereimg_clicked(Cereimg *cell, gchar *path_str,
                                         icon_selection_t *iconsel)
{
  GtkTreeModel *model;
  GtkTreePath  *path;
  GtkTreeIter  iter;
  gboolean     selected;
  icodir_t    *icodir;
  char        *olddir;
  
  g_assert(cell != NULL && path_str != NULL && iconsel != NULL);
  TRACE("path:%s", path_str);

  model = gtk_tree_view_get_model(GTK_TREE_VIEW(iconsel->path_tree));
  
  path = gtk_tree_path_new_from_string(path_str);
  gtk_tree_model_get_iter(model, &iter, path);
  gtk_tree_path_free(path);

  gtk_tree_model_get(model, &iter, 0, &olddir, 1, &selected, -1);
  TRACE("path:%s, olddir:%s, selected:%d",
          path_str, olddir, selected);
  
  icodir = icon_list_find_path(iconsel->icons, olddir);
  if (icodir == NULL)
    ERR("icon_list_find_path return NULL, olddir:%s", olddir);
  if (icodir->parent == NULL)
    filesel_select(iconsel->apwal->filesel, olddir, TRUE/*dir_only*/,
                  iconsel_filesel_compute, iconsel);
}
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
void iconsel_filesel_compute(const char *oldd, const char *newd, void *data)
{
  icon_selection_t *iconsel = (icon_selection_t *)data;
  //FIXME: modify icon_dir_list_modify & cie with const char* to avoid cast.
  char *olddir = (char*) oldd;
  char *newdir = (char*) newd;
  icodir_t *icodir;
  g_assert(iconsel != NULL);
  TRACE("newdir:%s", newdir);

  // NULL if user cancel the dir sel box
  if (newdir == NULL)
    return;

  // if the newdir is empty, remove the line
  if (strcmp("", newdir) == 0)
  {
    icon_dir_list_remove(&iconsel->apwal->iconsel_pref->icon_dirs, olddir);
    icon_list_remove(iconsel->icons, olddir);
  }
  else
  {
    icodir = icon_list_find_path(iconsel->icons, newdir);
    if (icodir != NULL)
    {
      if (icodir->parent == NULL)
      {
        TRACE("dir:%s already exist and is a parent dir, nothing to do",
              newdir);
      }
      else
      {
        icon_dir_list_modify(&iconsel->apwal->iconsel_pref->icon_dirs, olddir, newdir);
        icon_list_modify_with_splash(iconsel->icons, olddir, newdir);
      }
    }
    else
    {
      icon_dir_list_modify(&iconsel->apwal->iconsel_pref->icon_dirs, olddir, newdir);
      icon_list_modify_with_splash(iconsel->icons, olddir, newdir);
    }
  }
  iconsel_refresh(iconsel);
}
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
void tree_column_set_label_and_tooltips(icon_selection_t *iconsel,
                                        GtkTreeViewColumn *column,
                                        char *title,
                                        char *tooltips)
{
  GtkWidget *label;
  GtkWidget *button;
  g_assert(column);
  if (!title)
  {
    TRACE("%s", "no title, nothing to do");
    return;
  }
  label = gtk_label_new(title);
  gtk_widget_show(label);
  gtk_tree_view_column_set_widget(column, label);
//gtk_tree_view_column_set_clickable(column, TRUE);
  label = gtk_tree_view_column_get_widget(column);
  if (label == NULL)
    ERR("gtk_tree_view_column_get_widget, label == %p", label);

  button = gtk_widget_get_ancestor(label, GTK_TYPE_BUTTON);
  if (button != NULL)
  {
    gtk_tooltips_set_tip(iconsel->apwal->tips, button, tooltips, NULL );
  }
  else
  {
    WARN("gtk_widget_get_ancestor, button not found, no tooltips for column:%s",
         title);
  }
}
// ----------------------------------------------------------------------------
void iconsel_filter_reset_clicked(GtkButton *widget,
                                  icon_selection_t *iconsel)
{
  g_assert(iconsel != NULL);
  TRACE("%s", "");
  gtk_entry_set_text(GTK_ENTRY(iconsel->filter_entry), "*");
}
// ----------------------------------------------------------------------------
void iconsel_scroll_size_allocate(GtkWidget *scroll, GtkAllocation *alloc,
                                  icon_selection_t *iconsel)
{
  int new_width;
  new_width = (alloc->width - iconsel->scroll_border_width) / ICON_WIDTH;
  if (new_width != iconsel->icons->icon_per_row)
  {
    TRACE("new_width:%d", new_width);
    icon_list_set_width(iconsel->icons, new_width);
    iconsel_reload(iconsel);
  }
}
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
