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

baobab.c

/*
 * Initial main.c 
 */

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

#include <pwd.h>
#include <time.h>
#include <gtk/gtk.h>
#include  <glib/gi18n.h>
#include <glib/gprintf.h>
#include <libgnomeui/libgnomeui.h>
#include <libgnomeui/gnome-ui-init.h>
#include <libgnomevfs/gnome-vfs.h>
#include <libgnomevfs/gnome-vfs-mime.h>
#include <libgnomevfs/gnome-vfs-mime-handlers.h>
#include <gconf/gconf-client.h>
#include <glibtop.h>
 
#include "baobab.h"
#include "tv.h"
#include "bbthread.h"
#include "callbacks.h"
#include "props.h"

static GnomeVFSMonitorHandle * handle_mtab;
static GnomeVFSMonitorHandle * handle_home;

static      void prefill_model (struct chan_data* );

static void check_UTF(GString *);
static void  push_iter_in_stack (GtkTreeIter * );
static GtkTreeIter pop_iter_from_stack (void);

static gint currentdepth=0;
static GtkTreeIter currentiter;
static GtkTreeIter firstiter;
static GQueue * iterstack=NULL;
static void prepare_firstcol(GString*, struct BaobabSearchRet* );
static gchar* get_owner(uid_t );
static gchar* get_last_mod(time_t );
gboolean filter_adv_search(struct BaobabSearchRet *);
static void initialize_search_variables(void);
static void baobab_init(void);
static void baobab_close(void);


/* start scanning on a specific directory
*/
void
start_proc_on_dir (gchar *dir)
{
      GdkCursor *cursor = NULL;
      GtkWidget *ck_allocated;

      switch_view(VIEW_TREE);

      if (!baobab_check_dir(dir))
            return;

      g_string_assign(baobab.last_scan_command,dir);
      baobab.STOP_SCANNING=FALSE;
      change_icon("busy.gif");
      check_menu_sens(TRUE);
      gtk_tree_store_clear(baobab.model);
      currentdepth=-1;              /* flag */
      iterstack = g_queue_new ();

      /* check if the file system is local or remote */
      baobab.is_local = bb_scan_is_local(dir);
      ck_allocated = glade_xml_get_widget(baobab.main_xml,"ck_allocated");
      if (!baobab.is_local) {
            gtk_toggle_button_set_active((GtkToggleButton*)ck_allocated,FALSE);
            gtk_widget_set_sensitive (ck_allocated, FALSE);
            baobab.show_allocated = FALSE;                    
      }
      else {
            gtk_widget_set_sensitive (ck_allocated,TRUE);   
      }
      
            
      getDir(dir);

      /* change the cursor */
      if (baobab.window->window) {
            cursor = gdk_cursor_new(GDK_WATCH);
            gdk_window_set_cursor (baobab.window->window, cursor);
                  }
                  
      /* set statusbar, percentage and allocated/normal size */
      set_statusbar( _("Calculating percentage bars..."));
      gtk_tree_model_foreach((GtkTreeModel*)baobab.model,show_bars,NULL);
      change_icon("done.png");
      check_menu_sens(FALSE);
      set_statusbar(_("Ready"));
      
      /* cursor clean up */
      if (baobab.window->window) {
            gdk_window_set_cursor(baobab.window->window,NULL);
            if (cursor) gdk_cursor_unref(cursor);
            }
            
      gtk_tree_view_columns_autosize((GtkTreeView *)baobab.tree_view); 
      baobab.STOP_SCANNING=TRUE;
      g_queue_free (iterstack);
      baobab.CONTENTS_CHANGED_DELAYED=FALSE;

}


void
start_search (gchar * searchname, gchar * dir)
{
      GdkCursor *cursor = NULL;

      switch_view(VIEW_SEARCH);
      initialize_search_variables();
      baobab.STOP_SCANNING=FALSE;
      change_icon("busy.gif");
      check_menu_sens(TRUE);

      /* change the cursor */
      if (baobab.window->window) {
            cursor = gdk_cursor_new(GDK_WATCH);
            gdk_window_set_cursor (baobab.window->window, cursor);
                  }
                  
      gtk_list_store_clear(baobab.model_search);

      if (!dir) {
            searchDir("file:///",searchname);         
      }
      else {
            searchDir(dir,searchname);
      }
      
      /* cursor clean up */
      if (baobab.window->window) {
            gdk_window_set_cursor(baobab.window->window,NULL);
            if (cursor) gdk_cursor_unref(cursor);
            }

      change_icon("done.png");
      check_menu_sens(FALSE);
      set_statusbar(_("Ready"));

      set_label_search(baobab.number_found_files,baobab.size_found_files);
      if (get_NB_page()==VIEW_SEARCH) show_label(VIEW_SEARCH);
      gtk_tree_view_columns_autosize((GtkTreeView *)baobab.tree_search); 
      baobab.STOP_SCANNING=TRUE;
      bbSearchOpt.dont_recurse_dir=FALSE;
}
/* fill the search model
*/

void 
fill_search_model(struct BaobabSearchRet *bbret)
{
      
      GtkTreeIter iter;
      GString * testo1;
      GdkPixbuf * picon;
      char * gicon;
      
      if (!filter_adv_search(bbret)) {
                  return;
      }
      
      gicon=gnome_icon_lookup_sync(gtk_icon_theme_get_default(),NULL,bbret->fullpath,
                                                NULL,GNOME_ICON_LOOKUP_FLAGS_NONE,NULL);
      picon= gtk_icon_theme_load_icon(gtk_icon_theme_get_default(),gicon,36,GTK_ICON_LOOKUP_USE_BUILTIN,NULL);
      
      testo1 = g_string_new(bbret->fullpath);
      prepare_firstcol(testo1, bbret);
      
      
      gtk_list_store_append (baobab.model_search, &iter);
      gtk_list_store_set(baobab.model_search, &iter,
                              COL0_ICON,picon,
                              COL1_STRING,testo1->str,
                              /* COL2_STRING,testo2->str, */
                              COL_FULLPATH,bbret->fullpath,
                              COL_FILETYPE,bbret->mime_type,
                              COL_SIZE, bbret->size,
                              COL_LASTACCESS,bbret->lastacc,
                              COL_OWNER, bbret->owner,    
                              -1);
      baobab.number_found_files++;
      baobab.size_found_files += bbret->size;
      g_object_unref(picon);
      g_string_free(testo1,TRUE);

}

void 
initialize_search_variables(void)
{
      baobab.number_found_files=0;
      baobab.size_found_files=0;
}


gboolean
filter_adv_search(struct BaobabSearchRet *bbret)
{
      gboolean flag = TRUE;
      GDate * filedate, *today;
      gint days;
      gint maxinterval=100;
      
      
      if ((bbSearchOpt.mod_date==NONE) && bbSearchOpt.size_limit==NONE)
      {return TRUE;}
      
      switch (bbSearchOpt.mod_date) {
            
            case LAST_WEEK:
            case LAST_MONTH:
                  filedate=g_date_new();
                  today= g_date_new();
                  g_date_set_time(filedate,(GTime)bbret->lastacc);
                  g_date_set_time(today,time(NULL));
                  days = g_date_days_between(filedate,today);
                  if (bbSearchOpt.mod_date == LAST_WEEK) {
                              maxinterval=7;
                              }
                  if (bbSearchOpt.mod_date == LAST_MONTH) {
                              maxinterval=30;
                              }
                  if (days > maxinterval) {
                        flag = FALSE;
                        }
                        
                  g_date_free(today);
                  g_date_free(filedate);
                  break;
      }
      
      switch (bbSearchOpt.size_limit) {

            case SIZE_SMALL:
                  if (bbret->size >= (guint64)102400) {
                        flag = FALSE;
                  }
                  break;
            
            case SIZE_MEDIUM:
                  if (bbret->size >= (guint64)1048576) {
                        flag = FALSE;
                  }

                  break;            
      }
      
      return flag;
}

void
prepare_firstcol(GString* text,struct BaobabSearchRet* bbret)
{
      
      GString* modlabel, * ownlabel, *fullabel, *alloclabel;
      gchar  *basename, *path, *size, *alloc_size;
      
      check_UTF(text);
      basename = g_path_get_basename(text->str);
      path=strdup(text->str);
      modlabel=g_string_new(_("Last Modification:"));
      ownlabel=g_string_new(_("Owner:"));
      fullabel=g_string_new(_("Full path:"));
      alloclabel=g_string_new(_("Allocated bytes:"));
      size = gnome_vfs_format_file_size_for_display(bbret->size);
      alloc_size = gnome_vfs_format_file_size_for_display(bbret->alloc_size);
      g_string_printf(text,"<big><b>%s</b></big>%c<small>%s %s%c%s %s    %s %s%c%s (%s %s) - %s</small>",
                  basename,
                  '\n',
                  fullabel->str,
                  path,
                  '\n',
                  modlabel->str,
                  get_last_mod(bbret->lastacc),
                  ownlabel->str,
                  get_owner(bbret->owner),
                  '\n',
                  size,
                  alloclabel->str,
                  alloc_size,
                  gnome_vfs_mime_get_description(bbret->mime_type));
      g_string_free(modlabel,TRUE);
      g_string_free(ownlabel,TRUE);
      g_string_free(fullabel,TRUE);
      g_string_free(alloclabel,TRUE);
      g_free(basename);
      g_free(path);
      g_free(size);
      g_free(alloc_size);

}


gchar*
get_owner(uid_t own_id)
{
      GString * owner;
      struct passwd * pw;
      pw = getpwuid(own_id);
      if (pw==NULL) {
            owner = g_string_new(_("Unknown"));
            }
      else {
            owner = g_string_new(pw->pw_name);
      }

      return g_string_free(owner,FALSE);
}

gchar*
get_last_mod(time_t timeacc)
{
      
      GString * time;
      gchar snum[21];
      struct tm * lt;
      
      lt = localtime(&timeacc);     
      strftime(snum,sizeof(snum),"%Y-%m-%d %R:%S",lt);
      time=g_string_new(snum);
      
      
      return g_string_free(time,FALSE);
}

/* pre-fills model during scanning
*/
void
prefill_model (struct chan_data * data)
{
      GString * cdir;
      char * basename;
      GtkTreeIter iter, iterparent;
      GtkTreePath *path;

      cdir=g_string_new ("");
      
      if (currentdepth ==-1) {
            gtk_tree_store_append(baobab.model,&iter,NULL);
            firstiter=iter;
      }
      else if(data->depth==1) {
            gtk_tree_store_append(baobab.model,&iter,&firstiter);
            path = gtk_tree_model_get_path(GTK_TREE_MODEL(baobab.model),&firstiter);
            gtk_tree_view_expand_row ((GtkTreeView*)baobab.tree_view,path,FALSE);
            gtk_tree_path_free(path);
      }
      else if(data->depth > currentdepth) {
            gtk_tree_store_append(baobab.model,&iter,&currentiter);     
      }
      else if (data->depth==currentdepth) {
            gtk_tree_model_iter_parent ((GtkTreeModel*)baobab.model,&iterparent,&currentiter);
            gtk_tree_store_append(baobab.model,&iter,&iterparent);
      }
      else if(data->depth < currentdepth) {
            GtkTreeIter tempiter;
            gint i;
            iter = currentiter;
            for (i=0;i<=(currentdepth-data->depth);i++) {
                  gtk_tree_model_iter_parent ((GtkTreeModel*)baobab.model,&tempiter,&iter);
                  iter = tempiter;
            }
            gtk_tree_store_append(baobab.model,&iter,&tempiter);
      }
      currentdepth=data->depth;
      push_iter_in_stack(&iter);
      currentiter=iter;

      basename = g_filename_display_basename(data->dir);
      g_string_assign(cdir, basename);
      g_free(basename);
      
      /* check UTF-8 and locale */
      check_UTF(cdir);

      g_string_append(cdir," &lt;== ");
      g_string_append(cdir,_("scanning..."));
      gtk_tree_store_set(baobab.model,&iter,COL_DIR_NAME,cdir->str,COL_H_FULLPATH, "",
                                          COL_H_ELEMENTS,-1,-1);
      while (gtk_events_pending()) { gtk_main_iteration(); }
      g_string_free(cdir,TRUE);

            
}

/* set filesystem first row
*/
void
first_row(void)
{
      char *size;
      gchar textperc[10];
      
      gtk_tree_store_append(baobab.model,&firstiter,NULL);
      size = gnome_vfs_format_file_size_for_display (g_fs.used);
      g_sprintf(textperc," %.1f %%",((gfloat)g_fs.used*100)/(gfloat)g_fs.total);
      
      gtk_tree_store_set(baobab.model,&firstiter,
                  COL_DIR_NAME, _("<i>Total filesystem usage:</i>"),    
                  COL_H_FULLPATH, "", 
                  COL_BAR, set_bar((g_fs.used*100)/g_fs.total),
                  COL_H_PERC, (gfloat)((g_fs.used*100)/g_fs.total),
                  COL_DIR_SIZE, size,     
                  COL_PERC,textperc,
                  COL_H_SIZE, g_fs.used,
                  COL_H_ALLOCSIZE, g_fs.used,
                  COL_H_ELEMENTS,-1,
                  
                  -1);
      
      g_free (size);
}


/* fills model during scanning
*  model:
*
*           0, $dir,                               1, $fullpath,
*           2, set_bar($perc),                           3, $perc,
*           4, calc($size),                              5, $size,
*           6, sprintf("% 4s",$elements)." "._('elements'),    7, $elements,
*           8, text showing hardlink size,                     9, $HLsize
*/
void
fill_model (struct chan_data * data)
{
      GtkTreeIter iter;
      GString *hardlinks;
      GString * basename;
      GString *elementi;
      char *size;
      char *alloc_size;
      char * basename_cstr;
      
      if (data->elements ==-1) {
                  prefill_model(data);
                  return;
                  }
      basename= g_string_new ("");
      basename_cstr = g_filename_display_basename(data->dir);
      g_string_assign(basename, basename_cstr);
      g_free(basename_cstr);
      
      check_UTF(basename);
      g_string_prepend(basename,"<b>");
      g_string_append(basename,"</b>");
                        
      iter=pop_iter_from_stack();
      
      hardlinks=g_string_new ("");
      if (data->tempHLsize > 0) {
            size = gnome_vfs_format_file_size_for_display(data->tempHLsize);
            g_string_assign(hardlinks,"<i>(");
            g_string_append(hardlinks,_("contains hardlinks for:"));
            g_string_append(hardlinks," ");
            g_string_append(hardlinks,size);
            g_string_append(hardlinks,")</i>");
            g_free(size);
      }           

      elementi=g_string_new ("");
      g_string_printf(elementi,
                  ngettext("% 5d object", "% 5d objects", data->elements),
                  data->elements);
      
      size = gnome_vfs_format_file_size_for_display(data->size);

      alloc_size = gnome_vfs_format_file_size_for_display(data->alloc_size);
      
      gtk_tree_store_set(baobab.model,&iter,
                  COL_DIR_NAME, basename->str, COL_H_FULLPATH, data->dir,
                  COL_H_PERC, 0.0,
                  COL_DIR_SIZE, baobab.show_allocated ? alloc_size : size,                
                  COL_H_SIZE, data->size,
                  COL_ELEMENTS, elementi->str, COL_H_ELEMENTS, data->elements,
                  COL_HARDLINK, hardlinks->str, COL_H_HARDLINK, data->tempHLsize,
                  COL_H_ALLOCSIZE,data->alloc_size,
                  -1);
      
      while (gtk_events_pending()) { gtk_main_iteration(); }
      g_string_free(hardlinks,TRUE);
      g_string_free(basename,TRUE);
      g_string_free(elementi,TRUE);
      g_free(size);
      g_free(alloc_size);
            
}



void 
push_iter_in_stack (GtkTreeIter *iter)
{

      g_queue_push_head (iterstack,iter->user_data3);
      g_queue_push_head (iterstack,iter->user_data2);
      g_queue_push_head (iterstack,iter->user_data);
      g_queue_push_head (iterstack,GINT_TO_POINTER(iter->stamp));
}


GtkTreeIter
pop_iter_from_stack (void)
{
      GtkTreeIter iter;
      
      iter.stamp      =  GPOINTER_TO_INT(g_queue_pop_head(iterstack));
      iter.user_data  =  g_queue_pop_head(iterstack);
      iter.user_data2 =  g_queue_pop_head(iterstack);
      iter.user_data3 =  g_queue_pop_head(iterstack);
      return iter;
}


void
check_UTF(GString * name)
{
      char * str;
      char * escaped_str;

      str = g_filename_to_utf8(name->str, -1, NULL, NULL, NULL);

      if (!str) {
            str = g_locale_to_utf8(name->str, -1, NULL, NULL, NULL);

            if (!str) {
                  str = g_strjoin("<i>",
                              _("Invalid UTF-8 characters"),
                              "</i>",
                              NULL);
            }
      }

      g_assert(str);

      escaped_str = g_markup_escape_text(str, strlen(str));

      g_string_assign(name, escaped_str);

      g_free(str);
      g_free(escaped_str);
}


gint 
list_find  (gconstpointer a, gconstpointer b)
{
      gchar * str_a, * str_b;
      gint ret;
      
      str_a = gnome_vfs_format_uri_for_display(a);
      str_b = gnome_vfs_format_uri_for_display(b);
      
      ret = (strcmp(str_a,str_b));

      g_free(str_a);
      g_free(str_b);
      return ret;
      
}


static void
baobab_init(void)
{
      GConfClient * gc_client;
      GnomeVFSResult result;
      GnomeVFSVolumeMonitor* volmonitor;
      
      /* Load Glade */
      baobab.glade_path = g_build_path(G_DIR_SEPARATOR_S,
                      GLADE_DIR,
                      "baobab.glade",
                      NULL);
      baobab.main_xml = glade_xml_new(baobab.glade_path,"baobab_window",NULL);
      glade_xml_signal_autoconnect (baobab.main_xml);
      

      /* Misc */
      baobab.label_scan = NULL;
      baobab.label_search = NULL;
      baobab.last_scan_command = g_string_new("/");
      baobab.CONTENTS_CHANGED_DELAYED=FALSE;
      baobab.STOP_SCANNING= TRUE;
      baobab.show_allocated=TRUE;
      baobab.is_local=TRUE;

      /* GConf */
      gc_client = gconf_client_get_default();
      gconf_client_add_dir(gc_client,BAOBAB_KEY, GCONF_CLIENT_PRELOAD_NONE,NULL);
      gconf_client_notify_add(gc_client,PROPS_SCAN_KEY,props_notify,NULL,NULL,NULL);
      baobab.bbExcludedDirs = gconf_client_get_list(gc_client,PROPS_SCAN_KEY,GCONF_VALUE_STRING,NULL);
      baobab.bbEnableHomeMonitor = gconf_client_get_bool(gc_client,PROPS_ENABLE_HOME_MONITOR,NULL);
      
      /* initialize bbSearchOpt variables */
      bbSearchOpt.filename = g_string_new("");
      bbSearchOpt.dir = g_string_new(g_get_home_dir());
      bbSearchOpt.mod_date=NONE;
      bbSearchOpt.size_limit=NONE;
      bbSearchOpt.exact=TRUE;
      bbSearchOpt.search_whole=FALSE;
      bbSearchOpt.dont_recurse_dir=FALSE;
      
      /* start VFS monitoring */
      handle_home=NULL; 

      volmonitor = gnome_vfs_get_volume_monitor();
      g_signal_connect (volmonitor, "volume_mounted",
                G_CALLBACK (volume_changed), NULL);
      g_signal_connect (volmonitor, "volume_unmounted",
                G_CALLBACK (volume_changed), NULL);
      
      result = gnome_vfs_monitor_add(&handle_home,g_get_home_dir(),
                              GNOME_VFS_MONITOR_DIRECTORY,
                              contents_changed_cb,NULL);
      
      if (result != GNOME_VFS_OK) {
            message(_("Cannot initialize GNOME VFS monitoring\n"
                          "Some real-time auto-detect function will not be available!"),NULL);
                  g_print("homedir:%s\n",gnome_vfs_result_to_string (result));

      }

}

static void
baobab_close(void)
{
            g_free(baobab.label_scan);
            g_free(baobab.label_search);
            g_string_free(baobab.last_scan_command,TRUE);
            g_string_free(bbSearchOpt.filename,TRUE);
            g_string_free(bbSearchOpt.dir,TRUE);
            g_free(baobab.glade_path);
      
      if (handle_mtab) {
            gnome_vfs_monitor_cancel(handle_mtab);
      }
      if (handle_home) {
            gnome_vfs_monitor_cancel(handle_home);
      }

      g_free(baobab.selected_path);

      g_slist_foreach(baobab.bbExcludedDirs,(GFunc)g_free,NULL);
      g_slist_free(baobab.bbExcludedDirs);
      glibtop_close();
      gnome_vfs_shutdown();
}



int
main (int argc, char *argv[])
{
      GdkPixbuf * window_icon;

      bindtextdomain (GETTEXT_PACKAGE, BAOBAB_LOCALE_DIR);
      bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
      textdomain (GETTEXT_PACKAGE);

      gnome_program_init(PACKAGE, VERSION, LIBGNOMEUI_MODULE,
                     argc, argv,
                     GNOME_PARAM_APP_DATADIR, BAOBAB_DATA_DIR, NULL);

      g_assert(gnome_vfs_init());
      gnome_authentication_manager_init ();
      glibtop_init();

      baobab_init();
      
      baobab_get_filesystem(&g_fs);
      set_label_scan(&g_fs);
      
      baobab.window = glade_xml_get_widget(baobab.main_xml,"baobab_window");
      gtk_window_set_position(GTK_WINDOW(baobab.window),GTK_WIN_POS_CENTER);
      window_icon = baobab_get_icon();
      gtk_window_set_icon(GTK_WINDOW(baobab.window),window_icon); 
      gtk_window_set_default_icon(window_icon);
      
      /* set global pixbufs */
      baobab.yellow_bar=baobab_load_pixbuf("yellow.png");
      baobab.red_bar=baobab_load_pixbuf("red.png");
      baobab.green_bar=baobab_load_pixbuf("green.png");
      
      baobab.tree_view = create_directorytreeview();
      baobab.tree_search = create_tree_filesearch();
      set_label_search(0,0);
      
      switch_view(VIEW_SEARCH);
      switch_view(VIEW_TREE);
      show_label(VIEW_TREE);
      change_icon("done.png");
            
      /* set allocated space checkbox */
      gtk_toggle_button_set_active((GtkToggleButton*)glade_xml_get_widget(baobab.main_xml,"ck_allocated"),
                                                baobab.show_allocated);
                                                
      gtk_widget_show (baobab.window);

      first_row();
      set_statusbar(_("Ready"));

      /* commandline */ 
      if (argc > 1){
            gchar *uri_shell;
            uri_shell = gnome_vfs_make_uri_from_shell_arg(argv[1]);
            start_proc_on_dir(uri_shell);
            g_free(uri_shell);
            }
            
                  
      gtk_main ();
      
      baobab_close();

return 0;
}

Generated by  Doxygen 1.6.0   Back to index