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

user_clist.c

/* dc_gui2 - a GTK+2 GUI for DCTC
 * Copyright (C) 2002 Eric Prevoteau
 *
 * user_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_clist.c,v 1.12 2004/01/11 16:46:05 ericprev 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_clist.h"
#include "main.h"
#include "gui_define.h"
#include "macro.h"
#include "global_user.h"

#if 0
/************************************************/
/* update user information using GLOB_USER data */
/************************************************/
static void user_clist_user_info_update_row(GtkTreeModel *gtm, GtkTreePath *gtp, GtkTreeIter *gti, gpointer user_data)
{

      GLOB_USER *gu;
      /* get GLOB_USER entry to use */
      gtk_tree_model_get(gtm,gti,UCC_LST_USER_POINTER,&gu,-1);

      /* block the update signal on this function */
      g_signal_handlers_block_matched (G_OBJECT(gtm),G_SIGNAL_MATCH_FUNC,0,0,NULL,user_clist_user_info_update_row,NULL);

      /* update user info */
      gtk_list_store_set(GTK_LIST_STORE(gtm),gti,
                                                                        UCC_TYPE_COL,gu->cnx_type,
                                                                        UCC_NICK_COL,gu->fmt_nick,
                                                                        UCC_SIZE_COL,gu->fmt_size,
                                                                        UCC_EMAIL_COL,gu->fmt_email,
                                                                        UCC_DESCRIPTION_COL,gu->fmt_desc,
                                                                        UCC_LINE_BACKGROUND,gu->back_color,
                                                                        UCC_LINE_FOREGROUND,gu->front_color,
                                                                        UCC_TYPE_CNX_BACKGROUND,gu->fast_color,
                                                                        -1);

      /* unblock the update signal on this function */
      g_signal_handlers_unblock_matched (G_OBJECT(gtm),G_SIGNAL_MATCH_FUNC,0,0,NULL,user_clist_user_info_update_row,NULL);
}
#endif

/* ========================================================================================================================= */
/* ========================================================================================================================= */
static void ucc_type_cell_data_func(GtkTreeViewColumn *tree_column, GtkCellRenderer *cell, GtkTreeModel *tree_model, GtkTreeIter *iter, gpointer data)
{
      GLOB_USER *gu;

      /* get GLOB_USER entry to use */
      gtk_tree_model_get(tree_model,iter,UCC_LST_USER_POINTER,&gu,-1);

      g_object_set(cell,"text",gu->cnx_type,"background",gu->fast_color,"foreground",gu->front_color,NULL);
}

/* ========================================================================================================================= */
static gint ucc_type_sort_func(GtkTreeModel *model, GtkTreeIter *a, GtkTreeIter *b, gpointer user_data)
{
      GLOB_USER *gua,*gub;

      /* get GLOB_USER entry to use */
      gtk_tree_model_get(model,a,UCC_LST_USER_POINTER,&gua,-1);
      gtk_tree_model_get(model,b,UCC_LST_USER_POINTER,&gub,-1);

      if(gua->cnx_type==NULL)
      {
            if(gub->cnx_type==NULL)
                  return 0;
            else
                  return -1;
      }
      else
      {
            if(gub->cnx_type==NULL)
                  return 1;
            return strcmp(gua->cnx_type,gub->cnx_type);
      }
}

/* ========================================================================================================================= */
/* ========================================================================================================================= */
static void ucc_nick_cell_data_func(GtkTreeViewColumn *tree_column, GtkCellRenderer *cell, GtkTreeModel *tree_model, GtkTreeIter *iter, gpointer data)
{
      GLOB_USER *gu;

      /* get GLOB_USER entry to use */
      gtk_tree_model_get(tree_model,iter,UCC_LST_USER_POINTER,&gu,-1);

      g_object_set(cell,"text",gu->fmt_nick,"background",gu->back_color,"foreground",gu->front_color,NULL);
}

/* ========================================================================================================================= */
static gint ucc_nick_sort_func(GtkTreeModel *model, GtkTreeIter *a, GtkTreeIter *b, gpointer user_data)
{
      GLOB_USER *gua,*gub;

      /* get GLOB_USER entry to use */
      gtk_tree_model_get(model,a,UCC_LST_USER_POINTER,&gua,-1);
      gtk_tree_model_get(model,b,UCC_LST_USER_POINTER,&gub,-1);

      /* unlike other fields, fmt_nick is never NULL */
      return strcmp(gua->fmt_nick,gub->fmt_nick);
}

/* ========================================================================================================================= */
/* ========================================================================================================================= */
static void ucc_size_cell_data_func(GtkTreeViewColumn *tree_column, GtkCellRenderer *cell, GtkTreeModel *tree_model, GtkTreeIter *iter, gpointer data)
{
      GLOB_USER *gu;

      /* get GLOB_USER entry to use */
      gtk_tree_model_get(tree_model,iter,UCC_LST_USER_POINTER,&gu,-1);

      g_object_set(cell,"text",gu->fmt_size,"background",gu->back_color,"foreground",gu->front_color,NULL);
}

/* ========================================================================================================================= */
static gint ucc_size_sort_func(GtkTreeModel *model, GtkTreeIter *a, GtkTreeIter *b, gpointer user_data)
{
      GLOB_USER *gua,*gub;

      /* get GLOB_USER entry to use */
      gtk_tree_model_get(model,a,UCC_LST_USER_POINTER,&gua,-1);
      gtk_tree_model_get(model,b,UCC_LST_USER_POINTER,&gub,-1);

      /* DON'T replace this by "return gua->unfmt_size-gub->unfmt_size;" because values are unsigned */
      if(gua->unfmt_size<gub->unfmt_size)
            return -1;
      if(gua->unfmt_size>gub->unfmt_size)
            return 1;
      return 0;
}

/* ========================================================================================================================= */
/* ========================================================================================================================= */
static void ucc_mail_cell_data_func(GtkTreeViewColumn *tree_column, GtkCellRenderer *cell, GtkTreeModel *tree_model, GtkTreeIter *iter, gpointer data)
{
      GLOB_USER *gu;

      /* get GLOB_USER entry to use */
      gtk_tree_model_get(tree_model,iter,UCC_LST_USER_POINTER,&gu,-1);

      g_object_set(cell,"text",gu->fmt_email,"background",gu->back_color,"foreground",gu->front_color,NULL);
}

/* ========================================================================================================================= */
static gint ucc_mail_sort_func(GtkTreeModel *model, GtkTreeIter *a, GtkTreeIter *b, gpointer user_data)
{
      GLOB_USER *gua,*gub;

      /* get GLOB_USER entry to use */
      gtk_tree_model_get(model,a,UCC_LST_USER_POINTER,&gua,-1);
      gtk_tree_model_get(model,b,UCC_LST_USER_POINTER,&gub,-1);

      if(gua->fmt_email==NULL)
      {
            if(gub->fmt_email==NULL)
                  return 0;
            else
                  return -1;
      }
      else
      {
            if(gub->fmt_email==NULL)
                  return 1;
            return strcmp(gua->fmt_email,gub->fmt_email);
      }
}

/* ========================================================================================================================= */
/* ========================================================================================================================= */
static void ucc_desc_cell_data_func(GtkTreeViewColumn *tree_column, GtkCellRenderer *cell, GtkTreeModel *tree_model, GtkTreeIter *iter, gpointer data)
{
      GLOB_USER *gu;

      /* get GLOB_USER entry to use */
      gtk_tree_model_get(tree_model,iter,UCC_LST_USER_POINTER,&gu,-1);

      g_object_set(cell,"text",gu->fmt_desc,"background",gu->back_color,"foreground",gu->front_color,NULL);
}

/* ========================================================================================================================= */
static gint ucc_desc_sort_func(GtkTreeModel *model, GtkTreeIter *a, GtkTreeIter *b, gpointer user_data)
{
      GLOB_USER *gua,*gub;

      /* get GLOB_USER entry to use */
      gtk_tree_model_get(model,a,UCC_LST_USER_POINTER,&gua,-1);
      gtk_tree_model_get(model,b,UCC_LST_USER_POINTER,&gub,-1);

      if(gua->fmt_desc==NULL)
      {
            if(gub->fmt_desc==NULL)
                  return 0;
            else
                  return -1;
      }
      else
      {
            if(gub->fmt_desc==NULL)
                  return 1;
            return strcmp(gua->fmt_desc,gub->fmt_desc);
      }
}

/*******************************************/
/* build model and view for the user clist */
/*******************************************/
void bmav4_user_clist(void)
{
      GtkListStore *model;
      GtkWidget *view;
      GtkCellRenderer *rend;
      GtkTreeSelection *slc;

      /* the user_clist store contains nearly no column. The columns of the treeview are populated */
      /* on-the-fly using the GLOB_USER entry of the list store and a set of custom cell_data_func */
      model=gtk_list_store_new(NB_UCC_LST_COL, G_TYPE_POINTER);
#if 0
      g_signal_connect_after(G_OBJECT(model),"row-changed",G_CALLBACK(user_clist_user_info_update_row),NULL);
#endif
      view=get_widget_by_widget_name(main_window,"user_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_SINGLE);

      /* 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_RSCD_gtk_tree_view_insert_column_with_attributes(model,GTK_TREE_VIEW(view),UCC_TVC_TYPE_COL,ucc_type_cell_data_func,ucc_type_sort_func,_("Spd"),rend,NULL);

      /* because the nick is always visible, we can switch its resize policy to FIXED */
      rend=gtk_cell_renderer_textx_new();
      g_object_set(rend,"rowspacing",TRUE,NULL);
      MY_RSCD2_gtk_tree_view_insert_column_with_attributes(model,GTK_TREE_VIEW(view),UCC_TVC_NICK_COL,ucc_nick_cell_data_func,ucc_nick_sort_func,_("Nick"),rend,NULL);

      rend=gtk_cell_renderer_textx_new();
      g_object_set(rend,"rowspacing",TRUE,"xalign",1.0,NULL);
      MY_RSCD_gtk_tree_view_insert_column_with_attributes(model,GTK_TREE_VIEW(view),UCC_TVC_SIZE_COL,ucc_size_cell_data_func,ucc_size_sort_func,_("Size"),rend,NULL);

      rend=gtk_cell_renderer_textx_new();
      g_object_set(rend,"rowspacing",TRUE,NULL);
      MY_RSCD_gtk_tree_view_insert_column_with_attributes(model,GTK_TREE_VIEW(view),UCC_TVC_EMAIL_COL,ucc_mail_cell_data_func,ucc_mail_sort_func,_("e-mail"),rend,NULL);

      rend=gtk_cell_renderer_textx_new();
      g_object_set(rend,"rowspacing",TRUE,NULL);
      MY_RSCD_gtk_tree_view_insert_column_with_attributes(model,GTK_TREE_VIEW(view),UCC_TVC_DESCRIPTION_COL,ucc_desc_cell_data_func,ucc_desc_sort_func,_("description"),rend,NULL);

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

/* ------------------------------------------------------------------------------ */
typedef struct
{
      int fnd;
      GString *fnd_nick;
      int nick_len;
      const char *nick_to_found;
} TMP_NICKCOMP;

/**************************************************/
/* compare a given row with the searched nickname */
/**************************************************/
static gboolean search_completion(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
{
      TMP_NICKCOMP *tn=data;
      gboolean ret=FALSE;
      GLOB_USER *gu;

      gtk_tree_model_get(model,iter,UCC_LST_USER_POINTER,&gu,-1);
      /* it is an exception because we complete a nickname in UTF8, not an ASCII one */
      if(!strncmp(gu->fmt_nick,tn->nick_to_found,tn->nick_len))
      {
            /* the pattern matchs */
            if(tn->fnd==-1)
            {
                  /* not found yet */
                  g_string_assign(tn->fnd_nick,gu->fmt_nick);
                  tn->fnd=0;
                  /* keep searching */
            }
            else if(tn->fnd==0)
            {
                  /* already found */
                  g_string_assign(tn->fnd_nick,"");
                  tn->fnd=-2;
                  ret=TRUE;         /* abort search */
            }
      }
      return ret;
}

/*********************************************************************************************/
/* this function search in the user_clist to find a nick matching the partially provided one */
/*********************************************************************************************/
/* output: a Gstring containing the full nick or NULL if none or more than one match */
/*************************************************************************************/
GString *complete_a_nick(const char *partial_nick)
{
      TMP_NICKCOMP tn;
      GtkWidget *w;
      GtkTreeModel *gtm;

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

      gtm=gtk_tree_view_get_model(GTK_TREE_VIEW(w));

      tn.fnd=-1;    /* not found */
      tn.fnd_nick=g_string_new("");
      tn.nick_to_found=partial_nick;
      tn.nick_len=strlen(tn.nick_to_found);

      gtk_tree_model_foreach(gtm,search_completion,&tn);

      if(tn.fnd_nick->len>0)
      {
            return tn.fnd_nick;
      }
      g_string_free(tn.fnd_nick,TRUE);
      return NULL;
}
/* ------------------------------------------------------------------------------ */
/*****************************************************************/
/* remove the user having the given nickname from the user_clist */
/*********************************************************************/
/* gtm is the TreeModel of the 'user_clist' widget                   */
/* (NULL can be provided to let the function found it automatically) */
/* (mainly here for speed)                                           */
/*********************************************************************/
void remove_user(GLOB_USER *gu, GtkTreeModel *gtm)
{
      GtkWidget *w;
      GtkListStore *gls;
      GtkTreeIter iter;
      GtkTreeRowReference *gtrr;

      if(gtm==NULL)
      {
            w=get_widget_by_widget_name(main_window,"user_clist");
            if(w==NULL)
                  return;
            gtm=gtk_tree_view_get_model(GTK_TREE_VIEW(w));
      }
      gls=GTK_LIST_STORE(gtm);

      /* check the reference for this list */
      gtrr=gu_user_get_reference_for_model(gu,gtm);
      if(gtrr!=NULL)
      {
            /* we need a row reference on this model but a valid one */
            if(gtk_tree_row_reference_valid(gtrr)==FALSE)
            {
                  /* unref it because the entry will be deleted */
                  gu_unref(gu,gtm,gtrr);
            }
            else
            {
                  GtkTreePath *gtp;
                  gtp=gtk_tree_row_reference_get_path(gtrr);
                  if(gtk_tree_model_get_iter(gtm,&iter,gtp))
                  {
                        gtk_list_store_remove(gls,&iter);
                  }
                  gtk_tree_path_free(gtp);
            }
      }

      /* unconnected with display update */
      gu_set_is_connected(gu,FALSE,TRUE);
}

/* ------------------------------------------------------------------------------------- */
/*******************************************************************/
/* this function adds the nickname to the user_clist or updates it */
/*******************************************************************/
/* output: modified/created GLOB_USER entry */
/*********************************************************************/
/* gtm is the TreeModel of the 'user_clist' widget                   */
/* (NULL can be provided to let the function found it automatically) */
/* (mainly here for speed)                                           */
/* email can be NULL                                                 */
/*********************************************************************/
GLOB_USER *add_or_update_user(char *cnx_type, char *nickname, unsigned long long share_size,char *email, char *description, unsigned int flag, GtkTreeModel *gtm,gboolean online_flag, gboolean op_flag)
{
      GtkWidget *w;
      GtkListStore *gls;
      GtkTreeIter iter;
      GLOB_USER *gu;
      gboolean was_updated;

      if(gtm==NULL)
      {
            w=get_widget_by_widget_name(main_window,"user_clist");
            if(w==NULL)
                  return NULL;
            gtm=gtk_tree_view_get_model(GTK_TREE_VIEW(w));
      }

      gls=GTK_LIST_STORE(gtm);

      /* find or create user */
      gu=gu_add_user(nickname,TRUE,NULL);

      was_updated=FALSE;
      was_updated|=gu_set_cnx_type(gu,cnx_type,FALSE);
      was_updated|=gu_set_email(gu,email,FALSE);
      was_updated|=gu_set_desc(gu,description,FALSE);
      was_updated|=gu_set_size(gu,share_size,FALSE);
      was_updated|=gu_set_flags(gu,flag,FALSE);
      was_updated|=gu_set_is_connected(gu,online_flag,FALSE);
      was_updated|=gu_set_op_flag(gu,op_flag,FALSE);

      if(was_updated)
            gu_do_user_row_update(gu);

      if(gu_user_get_reference_for_model(gu,gtm)==NULL)
      {
            /* if the entry was created, add it to the list and reference the list */
            gtk_list_store_append(gls,&iter);
            gtk_list_store_set(gls,&iter,UCC_LST_USER_POINTER,gu,
                                                                    -1);
            gu_ref_from_iter(gu,gtm,&iter);
      }

      /* a newly created entry has no reference and does not need update */
      return gu;
}

/* ------------------------------------------------------------------------------------- */
void update_users_info(void)
{
      guint32 nb_users;
      guint64 share_size;
      double amount;
      char buf[1024];
      GtkWidget *w;

      nb_users=compute_online_nb_users_and_share_size(&share_size);

      amount=share_size;

#ifndef NO_PRINTF_LOCALE
      if( (amount/(1024.0*1024.0*1024.0)) > 1024.0)
            sprintf(buf,"%'u users (%'.2lfTB)",nb_users,amount/(1024.0*1024.0*1024.0*1024.0));  /* NO_PRINTF_LOCAL support added */
      else
            sprintf(buf,"%'u users (%'.2lfGB)",nb_users,amount/(1024.0*1024.0*1024.0));                     /* NO_PRINTF_LOCAL support added */
#else
      if( (amount/(1024.0*1024.0*1024.0)) > 1024.0)
            sprintf(buf,"%u users (%.2lfTB)",nb_users,amount/(1024.0*1024.0*1024.0*1024.0));
      else
            sprintf(buf,"%u users (%.2lfGB)",nb_users,amount/(1024.0*1024.0*1024.0));
#endif
      w=get_widget_by_widget_name(main_window,"users_info_label");
      if(w==NULL)
            return;
      gtk_label_set(GTK_LABEL(w),buf);
}


Generated by  Doxygen 1.6.0   Back to index