Logo Search packages:      
Sourcecode: dcgui version File versions  Download package

user_file_list_clist.c

/* dc_gui2 - a GTK+2 GUI for DCTC
 * Copyright (C) 2002 Eric Prevoteau
 *
 * user_file_list_clist.c: Copyright (C) Eric Prevoteau <www@a2pb.gotdns.org>
 *
 * 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.
 */
/*
$Id: user_file_list_clist.c,v 1.5 2003/12/26 14:35:04 uid68112 Exp $
*/

#ifdef HAVE_CONFIG_H
#  include <config.h>
#endif

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <gnome.h>

#include "gtkcellrenderertextx.h"
#include "misc_gtk.h"
#include "user_file_list_clist.h"
#include "main.h"
#include "macro.h"
#include "gui_define.h"
#include "ls_cache.h"
#include "gtk_helper.h"

static void unselect_node_and_offsprings(GtkTreeModel *model, GtkTreeIter *node, GtkTreeSelection *slc)
{
      gboolean valid;
      GtkTreeIter child;

      gtk_tree_selection_unselect_iter(slc,node);
      valid=gtk_tree_model_iter_children(model,&child,node);
      while(valid)
      {
            unselect_node_and_offsprings(model,&child,slc);
            valid=gtk_tree_model_iter_next(model,&child);
      }
}

/****************************************************/
/* for each row, all its descendants are unselected */
/****************************************************/
static void unselect_offsprings(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
{
      GtkTreeSelection *slc=data;
      gboolean valid;
      GtkTreeIter child;
      
      valid=gtk_tree_model_iter_children(model,&child,iter);
      while(valid)
      {
            unselect_node_and_offsprings(model,&child,slc);
            valid=gtk_tree_model_iter_next(model,&child);
      }
}

/************************************************************************/
/* for each selected entry, check if it does not have a selected parent */
/* an entry having a selected parent is unselected.                     */
/************************************************************************/
void keep_selected_lowest_user_file_list_nodes(void)
{
   GtkWidget *w;
      GtkTreeSelection *slc;
      
   w=get_widget_by_widget_name(main_window,"user_file_list_clist");
   if(w==NULL)
      return;

      slc=gtk_tree_view_get_selection(GTK_TREE_VIEW(w));
      gtk_tree_selection_selected_foreach(slc,unselect_offsprings,slc);
}

/*******************************************************************************************/
/* this function calls the given fnc for each selected entry of the "user_file_list" clist */
/*******************************************************************************************/
void generic_selected_user_file_list_calls(GtkTreeSelectionForeachFunc fnc, void *data)
{
   GtkWidget *w;
      GtkTreeSelection *slc;

   w=get_widget_by_widget_name(main_window,"user_file_list_clist");
   if(w==NULL)
      return;

      slc=gtk_tree_view_get_selection(GTK_TREE_VIEW(w));
      gtk_tree_selection_selected_foreach(slc,fnc,data);
}

/******************************************************************/
/* find the UFL_NICK_ROOT_ENTRY of a given entry (DIR|FILE)_ENTRY */
/********************************************************************************/
/* output: FALSE if not found, TRUE if found and uninitialized parent is filled */
/********************************************************************************/
gboolean get_nick_entry_for_user_file_list_from_ufce(GtkTreeModel *gtm, GtkTreeIter *start_iter, GtkTreeIter *parent)
{
      GtkTreeIter iter;

      if(gtk_tree_model_iter_parent(gtm,parent,start_iter)==FALSE)
            return FALSE;

      do
      {
            guint type;

            gtk_tree_model_get(gtm,parent,UFLC_TYPE,&type,-1);

            if(type==UFL_NICK_ROOT_ENTRY)
                  return TRUE;

            iter=*parent;
      }while(gtk_tree_model_iter_parent(gtm,parent,&iter));

      return FALSE;
}

/* ---------------------------------------------------------------------------------------------------- */

/**********************************************************************/
/* search in the root node a subtree for the given user and delete it */
/* ONLY UFL_NICK_ROOT_ENTRY can be found                              */
/**********************************************************************/
/* GTK2: to test */
/*****************/
static void discard_sub_ctree_of_user(GtkTreeStore *gts,GtkTreeModel *gtm,char *nick)
{
      gboolean valid;
      GtkTreeIter iter;

      valid=gtk_tree_model_get_iter_first(gtm,&iter);
      while(valid)
      {
            char *child_nick;

            gtk_tree_model_get(gtm,&iter,UFLC_STR,&child_nick,-1);
            if(!strcmp(nick,child_nick))
            {
                  free(child_nick);
                  gtk_tree_store_remove(gts,&iter);
                  break;
            }
            free(child_nick);
            valid=gtk_tree_model_iter_next(gtm,&iter);
      }
}

/***************************************************************************************************************************/
/* search if an offspring of the last_inserted_node match the wanted dir_string (its first dir_string_len characters only) */
/***************************************************************************************************************************/
/* input: parent_node is ALWAYS an UFL_DIR_ENTRY                                      */
/* output: FALSE= not found, TRUE= found, offspring_iter and offspring_ufce filled */
/**************************************************************************************/
/* GTK2: to test */
/*****************/
static int find_offspring_as_named_dir(GtkTreeStore *gts,GtkTreeModel *gtm,
                                                                              GtkTreeIter **last_inserted_iter,   /* it is the parent base */
                                                                              GtkTreeIter *offspring_iter,
                                                                              char *dir_string, int dir_string_len)
{
      char *dir_name;
      int ret=FALSE;
      gboolean valid;

      dir_name=strdup(dir_string);
      dir_name[dir_string_len]='\0';

      valid=gtk_tree_model_iter_children(gtm,offspring_iter,*last_inserted_iter);
      while(valid)
      {
            guint child_type;
            gtk_tree_model_get(gtm,offspring_iter,UFLC_TYPE,&child_type,-1);

            if(child_type==UFL_DIR_ENTRY)
            {
                  char *child_dir;

                  gtk_tree_model_get(gtm,offspring_iter,UFLC_STR,&child_dir,-1);

                  if(!strcmp(dir_name,child_dir))
                  {     /* we have found our entry */
                        free(child_dir);
                        ret=TRUE;
                        break;
                  }
                  free(child_dir);
            }
            valid=gtk_tree_model_iter_next(gtm,offspring_iter);
      }
      free(dir_name);
      return ret;
}

/****************************************************************************************/
/* recursively go through a tree from the last_inserted_node and try to attach the leaf */
/****************************************************************************************/
/* cur_string_pos is the number of bytes already used in new_leaf->c.file.filename */
/***********************************************************************************/
/* GTK2: to test */
/*****************/
static void recursive_insert_new_user_cl_entry_leaf(GtkTreeStore *gts,GtkTreeModel *gtm, 
                                                                                                      GtkTreeIter **last_inserted_iter,      /* the * value can be freed using gtk_tree_iter_free() */
                                                                                                      int cur_string_pos,
                                                                                                      char *new_path, gulong new_size)
{
      int next_len;
      char *next_sep;
      GtkTreeIter offspring_iter;

      next_sep=strchr(new_path+cur_string_pos,'\\');
      if(next_sep==NULL)
      {
            /* we have reached the leaf position */
            GtkTreeIter iter;
            char bf[64];

#ifndef NO_PRINTF_LOCALE
            sprintf(bf,"%'lu",new_size);  /* NO_PRINTF_LOCAL support added */
#else
            sprintf(bf,"%lu",new_size);
#endif

            gtk_tree_store_append(gts,&iter,*last_inserted_iter);
            if(utf8_mode==TRUE)
            {
                  gtk_tree_store_set(gts,&iter,UFLC_TREE_COL,new_path+cur_string_pos,
                                                                              UFLC_SIZE_COL,bf,
                                                                              UFLC_SIZE_RIGHT_ALIGN,(gfloat)1.0,
                                                                              UFLC_TYPE,(guint)UFL_FILE_ENTRY,
                                                                              UFLC_STR,new_path,
                                                                              UFLC_SIZE_AS_VAL,(gulong)new_size,
                                                                              -1);
            }
            else
            {
                  gchar *utf8_path;
                  utf8_path=g_locale_to_utf8(new_path+cur_string_pos,-1,NULL,NULL,NULL);

                  gtk_tree_store_set(gts,&iter,UFLC_TREE_COL,utf8_path,
                                                                              UFLC_SIZE_COL,bf,
                                                                              UFLC_SIZE_RIGHT_ALIGN,(gfloat)1.0,
                                                                              UFLC_TYPE,(guint)UFL_FILE_ENTRY,
                                                                              UFLC_STR,new_path,
                                                                              UFLC_SIZE_AS_VAL,(gulong)new_size,
                                                                              -1);
                  g_free(utf8_path);
            }
            return;
      }

      next_len=(next_sep-new_path)+1;     /* we always include the '\' in the dir path */
      /* we have not reached the leaf position */
      /* we must find an offspring to (*last_inserted_node) to resume or we must create it */
      if(find_offspring_as_named_dir(gts,gtm,last_inserted_iter, &offspring_iter, new_path, next_len)==FALSE)
      {
            /* the node does not exists */
            GtkTreeIter iter;
            char *t;
            char *t1;

            gtk_tree_store_append(gts,&iter,*last_inserted_iter);

            t=strdup(new_path);
            t[(next_sep-new_path)+1]='\0';

            t1=strdup(new_path+cur_string_pos);
            t1[next_sep-(new_path+cur_string_pos)+1]='\0';        /* keep the '\' at the end */

            if(utf8_mode==TRUE)
            {
                  gtk_tree_store_set(gts,&iter,UFLC_TREE_COL,t1,
                                                                              UFLC_SIZE_COL,"",
                                                                              UFLC_SIZE_RIGHT_ALIGN,(gfloat)1.0,
                                                                              UFLC_TYPE,(guint)UFL_DIR_ENTRY,
                                                                              UFLC_STR,t,
                                                                              UFLC_SIZE_AS_VAL,(gulong)0,
                                                                              -1);
            }
            else
            {
                  gchar *utf8_path;
                  utf8_path=g_locale_to_utf8(t1,-1,NULL,NULL,NULL);

                  gtk_tree_store_set(gts,&iter,UFLC_TREE_COL,utf8_path,
                                                                              UFLC_SIZE_COL,"",
                                                                              UFLC_SIZE_RIGHT_ALIGN,(gfloat)1.0,
                                                                              UFLC_TYPE,(guint)UFL_DIR_ENTRY,
                                                                              UFLC_STR,t,
                                                                              UFLC_SIZE_AS_VAL,(gulong)0,
                                                                              -1);
                  g_free(utf8_path);
            }
            free(t);
            free(t1);
            gtk_tree_iter_free(*last_inserted_iter);
            *last_inserted_iter=gtk_tree_iter_copy(&iter);
      }
      else
      {
            /* a node with this name already exists */
            gtk_tree_iter_free(*last_inserted_iter);
            *last_inserted_iter=gtk_tree_iter_copy(&offspring_iter);
      }
      recursive_insert_new_user_cl_entry_leaf(gts,gtm,last_inserted_iter,next_len,new_path,new_size);
}

/*********************************************************/
/* attach a leaf from a root or from the last known node */
/*********************************************************/
/* GTK2: to test */
/*****************/
static void insert_new_user_file_cl_entry_leaf(GtkTreeStore *gts,GtkTreeModel *gtm,
                                                                                                GtkTreeIter *root_node_iter, /* the root of this user (read only) */
                                                                                                GtkTreeIter **last_inserted_iter,         /* the * value can be freed using gtk_tree_iter_free() */
                                                                                                char *new_path, gulong new_size
                                                                                                )
{
      guint last_type;
      gtk_tree_model_get(gtm,*last_inserted_iter,UFLC_TYPE,&last_type,-1);
      
      if(last_type==UFL_DIR_ENTRY)
      {     /* add from a directory entry */
            int l;
            char *last_path;
            gtk_tree_model_get(gtm,*last_inserted_iter,UFLC_STR,&last_path,-1);

            l=strlen(last_path);
            if( (!strncmp(last_path,new_path,l)) &&
                   (new_path[l]=='\\'))
            {
                  free(last_path);
                  /* we are adding from the last inserted path */
                  recursive_insert_new_user_cl_entry_leaf(gts,gtm, last_inserted_iter, l+1, new_path,new_size);
                  return;
            }
            free(last_path);

            gtk_tree_iter_free(*last_inserted_iter);
            *last_inserted_iter=gtk_tree_iter_copy(root_node_iter);
      }
      recursive_insert_new_user_cl_entry_leaf(gts,gtm, last_inserted_iter, 0, new_path,new_size);
}

/*************************************************************/
/* load the share list of a user in the user file list clist */
/*************************************************************/
void put_nick_ls_into_user_file_list_clist(char *nick)
{
      GtkWidget *w;
      GtkTreeStore *gts;
      GtkTreeModel *gtm;
      GtkTreeIter iter;
      char *cur_lst_ptr;
      char *lst;
      guint64 ttl_size;
      GtkWidget *apbar;
      gfloat last_ap_pos=0;
      unsigned long list_byte_size;
      GtkTreeIter *root_node_iter;
      GtkTreeIter *last_inserted_iter;
      SORT_VARS( )

      w=get_widget_by_widget_name(main_window,"user_file_list_clist");
      if(w==NULL)
            return;

      gts=GTK_TREE_STORE(gtm=gtk_tree_view_get_model(GTK_TREE_VIEW(w)));

      lst=load_ls_file(nick,&ttl_size);
      if(lst==NULL)
            return;

      cur_lst_ptr=lst;

      SORT_SAVE(,gtm,UFLC_SIZE_RIGHT_ALIGN)
      discard_sub_ctree_of_user(gts,gtm, nick);

      /* reset the progress bar */
      apbar=get_widget_by_widget_name(main_window,"appbar1");
      gnome_appbar_set_progress_percentage(GNOME_APPBAR(apbar),0);
      while (gtk_events_pending())
            gtk_main_iteration();

      list_byte_size=strlen(cur_lst_ptr);

      /* create the user root entry */
      gtk_tree_store_append(gts,&iter,NULL);
      if(utf8_mode==TRUE)
      {
            gtk_tree_store_set(gts,&iter,UFLC_TREE_COL,nick,
                                                                  UFLC_SIZE_COL,"",
                                                                  UFLC_SIZE_RIGHT_ALIGN,1.0,
                                                                  UFLC_TYPE,(guint)UFL_NICK_ROOT_ENTRY,
                                                                  UFLC_STR,nick,
                                                                  UFLC_SIZE_AS_VAL,(gulong)0,
                                                                  -1);
      }
      else
      {
            gchar *utf8_path;
            utf8_path=g_locale_to_utf8(nick,-1,NULL,NULL,NULL);

            gtk_tree_store_set(gts,&iter,UFLC_TREE_COL,utf8_path,
                                                                  UFLC_SIZE_COL,"",
                                                                  UFLC_SIZE_RIGHT_ALIGN,1.0,
                                                                  UFLC_TYPE,(guint)UFL_NICK_ROOT_ENTRY,
                                                                  UFLC_STR,nick,
                                                                  UFLC_SIZE_AS_VAL,(gulong)0,
                                                                  -1);
            g_free(utf8_path);
      }
      root_node_iter=gtk_tree_iter_copy(&iter);

      last_inserted_iter=gtk_tree_iter_copy(&iter);

      while(cur_lst_ptr[0]!='\0')
      {
            char *fname, *fsize;
            gulong size;

            /* line format: filename|size\n */
            fname=cur_lst_ptr;
            cur_lst_ptr=strchr(cur_lst_ptr,'|');
            if(cur_lst_ptr==NULL)
                  break;
            *cur_lst_ptr++='\0';
            fsize=cur_lst_ptr;
            cur_lst_ptr=strchr(cur_lst_ptr,'\n');
            if(cur_lst_ptr==NULL)
                  break;
            *cur_lst_ptr++='\0';

            size=strtoul(fsize,NULL,10);

            insert_new_user_file_cl_entry_leaf(gts,gtm,root_node_iter,&last_inserted_iter, fname,size);

            if( ((((gfloat)(cur_lst_ptr-lst))/list_byte_size)-last_ap_pos) > 0.01 ) 
            {
                  last_ap_pos=(((gfloat)(cur_lst_ptr-lst))/list_byte_size);
                  gnome_appbar_set_progress_percentage(GNOME_APPBAR(apbar),last_ap_pos);
                  while (gtk_events_pending())
                        gtk_main_iteration();
            }
      }

      /* free the share list */
      free(lst);
      gtk_tree_iter_free(root_node_iter);
      gtk_tree_iter_free(last_inserted_iter);

      gnome_appbar_set_progress_percentage(GNOME_APPBAR(apbar),1.0);

      /* make the tab label blink if required */
      if(gtk_notebook_get_current_page(GTK_NOTEBOOK(get_widget_by_widget_name(main_window,"main_notebook")))!=USER_FILE_LIST_TAB)
            blink_on("user_file_list_page");
      SORT_RESTORE(,gtm)
}

/* ---------------------------------------------------------------------------------------------------- */

/*****************************************************************/
/* handle special column sorting for user_file_list_clist column */
/*****************************************************************/
static gint ufce_sort(GtkTreeModel *model, GtkTreeIter *a, GtkTreeIter *b, gpointer user_data)
{
      guint typea,typeb;
      
      gint sort_col=GPOINTER_TO_INT(user_data);

      gtk_tree_model_get(model,a,UFLC_TYPE,&typea,-1);
      gtk_tree_model_get(model,b,UFLC_TYPE,&typeb,-1);

      /* type must be comparable */
      if(typea!=typeb)
      {
            if(typea<typeb)
                  return -1;
            return 1;
      }

      switch(sort_col)
      {
            case UFLC_TREE_COL:
                                                      default_sort:
                                                      {
                                                            char *stra,*strb;
                                                            gint ret;
                                                            gtk_tree_model_get(model,a,UFLC_STR,&stra,-1);
                                                            gtk_tree_model_get(model,b,UFLC_STR,&strb,-1);

                                                            ret=strcmp(stra,strb);
                                                            free(stra);
                                                            free(strb);
                                                            return ret;
                                                      }
                                                      break;

            case UFLC_SIZE_COL:
                                                      {
                                                            gulong vala,valb;
                                                            if(typea!=UFL_FILE_ENTRY)
                                                                  goto default_sort;

                                                            gtk_tree_model_get(model,a,UFLC_SIZE_AS_VAL,&vala,-1);
                                                            gtk_tree_model_get(model,b,UFLC_SIZE_AS_VAL,&valb,-1);
                                                            /* warning file_size is unsigned */
                                                            if(vala<valb)
                                                                  return -1;
                                                            if(vala==valb)
                                                                  return 0;
                                                            return 1;
                                                      }
                                                      break;
      }
      return 0;
}

/******************************************************/
/* build modele and view for the user file list clist */
/******************************************************/
void bmav4_user_file_list_clist(void)
{
      GtkTreeStore *model;
      GtkWidget *view;
      GtkCellRenderer *rend;
      GtkTreeSelection *slc;

      model=gtk_tree_store_new(NB_UFLC_COL,G_TYPE_STRING,G_TYPE_STRING,G_TYPE_FLOAT,
                                                                                    G_TYPE_UINT,G_TYPE_STRING,G_TYPE_ULONG);

      gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(model),UFLC_TREE_COL,ufce_sort,GINT_TO_POINTER(UFLC_TREE_COL),NULL);
      gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(model),UFLC_SIZE_COL,ufce_sort,GINT_TO_POINTER(UFLC_SIZE_COL),NULL);

      view=get_widget_by_widget_name(main_window,"user_file_list_clist");

      gtk_tree_view_set_model(GTK_TREE_VIEW(view),GTK_TREE_MODEL(model));
      gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(view),TRUE);

      slc=gtk_tree_view_get_selection(GTK_TREE_VIEW(view));
      gtk_tree_selection_set_mode(slc,GTK_SELECTION_MULTIPLE);

      /* the first column of the view display the first column of the model, and so on. The 4th entry of the model is not displayed */
      rend=gtk_cell_renderer_textx_new();
      g_object_set(rend,"rowspacing",TRUE,NULL);
      MY_RS_gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(view),UFLC_TREE_COL,_("Path"),rend,"text",UFLC_TREE_COL,NULL);

      rend=gtk_cell_renderer_textx_new();
      g_object_set(rend,"rowspacing",TRUE,NULL);
      g_object_set(rend,"xalign",(gfloat)1.0,NULL);
      MY_RS_gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(view),UFLC_SIZE_COL,_("Size"),rend,"text",UFLC_SIZE_COL,"xalign",UFLC_SIZE_RIGHT_ALIGN,NULL);

      /* The view now holds a reference.  We can get rid of our own
       * reference */
      g_object_unref (G_OBJECT (model));
}


Generated by  Doxygen 1.6.0   Back to index