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

directory_menu.c

/*
 * Danpei -- a GTK+ based Image Viewer
 * Copyright (C) 2001-2003 Shinji Moiino
 *
 * 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.
 */
/* directory_menu.c */

#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <gdk/gdkx.h>

#include "config.h"
#include "dialog.h"
#include "intl.h"
#include "directory_menu.h"
#include "dirtree.h"
#include "version.h"

/* Static function declarations. */
static void   directory_menu_cb_ok              (GtkWidget*   ,
                                                 gpointer       );

static void   directory_menu_cb_cancel          (GtkWidget*   ,
                                                 gpointer       );

static gchar* directory_menu_cerate_name_dialog (TopLevel*      );

static void   directory_menu_insert_new_node    (TopLevel*    ,
                                                 GtkCTreeNode*,
                                                 gchar*       ,
                                                 gchar*         );
/* Function definitions. */
/*
 * @directory_menu_cb_new
 *
 *  Create a new directory.
 *
 */
void directory_menu_cb_new(GtkWidget *widget,
                           gpointer  data   ,
                           guint     action   ) {
  TopLevel     *tp;
  NodeInfo     *nodeinfo;
  GtkCTreeNode *node;
  gchar        *name1, *name2, *name3;

  /* Initialize the local variables. */
  tp       = (TopLevel*)data;
  nodeinfo = NULL;
  name1    = name2 = name3 = NULL;

  /* Get the information of the row focused. */
  node = gtk_ctree_node_nth(GTK_CTREE(tp->dir_tree.ctree), 
                            GTK_CLIST(tp->dir_tree.ctree)->focus_row);
  if (node == NULL) { return; }

  nodeinfo = gtk_ctree_node_get_row_data(GTK_CTREE(tp->dir_tree.ctree), 
                                         node);
  if (nodeinfo == NULL) { return; }

  name1 = directory_menu_cerate_name_dialog(tp);

  if (name1 != NULL) {
    name2 = name1;
    while(*name2 == '/') { name2++; }
    name3 = strchr(name2, '/');
    if (name3 != NULL) { *name3 = '\0'; }
    name3 = (gchar*)malloc(sizeof(gchar) *
                           (strlen(nodeinfo->path) +
                            strlen("/")            +
                            strlen(name2)          + 1));
    if (name3 == NULL) {
      /* Out of memory. */
      fprintf(stderr, "danpei: Out of memory.\n");
      fprintf(stderr, "        directory_menu.c: error -- 01.\n");
      gtk_exit(-1);
    }
    else {
      strcpy(name3, nodeinfo->path);
      strcat(name3, "/");
      strcat(name3, name2);
    }

    if (mkdir(name3, 0755) == 0) {
      directory_menu_insert_new_node(tp, node, name2, name3);
    }
    else {
      switch(errno) {
        case ENOENT:
          dialog_error_dialog_create(FILE_NOT_EXISTS,
                                     name3, GTK_WINDOW(tp->window));
          break;
        case EPERM:
        case EACCES:
          dialog_error_dialog_create(PERMISSION_DENIED,
                                     name3, GTK_WINDOW(tp->window));
          break;
        case EEXIST:
          dialog_error_dialog_create(DIRECTORY_ALREADY_EXISTS,
                                     name3, GTK_WINDOW(tp->window));
          break;
        case EROFS:
          dialog_error_dialog_create(READ_ONLY_FS,
                                     name3, GTK_WINDOW(tp->window));
          break;
        case ENOSPC:
          dialog_error_dialog_create(NO_SPACE_LEFT,
                                     name3, GTK_WINDOW(tp->window));
          break;
        case ENAMETOOLONG:
          dialog_error_dialog_create(TOO_LONG_FILE_NAME,
                                     name3, GTK_WINDOW(tp->window));
        default:
          dialog_error_dialog_create(MKDIR_ERROR,
                                     name3, GTK_WINDOW(tp->window));
          break;
      }
    }
  }

  free(name1); free(name3);

  return;
}

/*
 * @directory_menu_cb_remove
 *
 *  Remove a directory.
 *  This function is neary equal to the 'rmdir' command on bash.
 *  If the directory includes other files or directory, this function
 *  will return an error.
 *
 */
void directory_menu_cb_remove(GtkWidget *widget,
                              gpointer  data   ,
                              guint     action   ) {
  TopLevel     *tp;
  NodeInfo     *nodeinfo;
  GtkCTreeNode *node;
  gboolean     ret;

  /* Initialize the local variables. */
  tp       = (TopLevel*)data;
  nodeinfo = NULL;
  node     = NULL;

  /* Get the information of the row focused. */
  node = gtk_ctree_node_nth(GTK_CTREE(tp->dir_tree.ctree), 
                            GTK_CLIST(tp->dir_tree.ctree)->focus_row);
  if (node == NULL) { return; }

  nodeinfo = gtk_ctree_node_get_row_data(GTK_CTREE(tp->dir_tree.ctree), 
                                         node);
  if (nodeinfo == NULL) { return; }

  if (tp->app_option.dialog.dir_remove == TRUE) {
    ret = dialog_message_dialog_create(DIRECTORY_REMOVED, NULL,
                                       APP_OK_CANCEL_DIALOG,
                                       APP_OK_BUTTON   ,
                                       GTK_WINDOW(tp->window));
    if (ret != APP_RET_OK) { return; }
  }

  if (rmdir(nodeinfo->path) == 0) {
    gtk_ctree_remove_node(GTK_CTREE(tp->dir_tree.ctree), node);
  }
  else {
    switch(errno) {
      case ENOENT:
        dialog_error_dialog_create(FILE_NOT_EXISTS,
                                   nodeinfo->path, GTK_WINDOW(tp->window));
        dirtree_refresh(tp);
        break;
      case EPERM:
      case EACCES:
        dialog_error_dialog_create(PERMISSION_DENIED,
                                   nodeinfo->path, GTK_WINDOW(tp->window));
        break;
      case EROFS:
        dialog_error_dialog_create(READ_ONLY_FS,
                                   nodeinfo->path, GTK_WINDOW(tp->window));
        break;
      case ENOSPC:
        dialog_error_dialog_create(NO_SPACE_LEFT,
                                   nodeinfo->path, GTK_WINDOW(tp->window));
        break;
      case ENAMETOOLONG:
        dialog_error_dialog_create(TOO_LONG_FILE_NAME,
                                   nodeinfo->path, GTK_WINDOW(tp->window));
        break;
      case ENOTEMPTY:
        dialog_error_dialog_create(DIRECTORY_NOT_EMPTY,
                                   nodeinfo->path, GTK_WINDOW(tp->window));
        break;
      default:
        dialog_error_dialog_create(RMDIR_ERROR,
                                   nodeinfo->path, GTK_WINDOW(tp->window));
        break;
    }
  }

  return;
}

/*
 * @directory_menu_cb_refresh
 *
 *  Refresh the directory tree.
 *
 */
void directory_menu_cb_refresh(GtkWidget *widget,
                               gpointer  data   ,
                               guint     action   ) {
  TopLevel *tp;

  /* Initialize the local variables. */
  tp = (TopLevel*)data;

  dirtree_refresh(tp);

  return;
}

/*
 * @directory_menu_cb_dotfile
 *
 */
void directory_menu_cb_dotfile(GtkWidget *widget,
                               gpointer  data   ,
                               guint     action   ) {
  TopLevel *tp;

  tp = (TopLevel*)data;

  if (tp->dot_file_on == TRUE) {
    tp->dot_file_on = FALSE;
    dirtree_refresh(tp);
  }
  else {
    tp->dot_file_on = TRUE;
    dirtree_refresh(tp);
  }

  return;
}

/* Static functions declaration. */
/*
 * @directory_menu_cb_ok
 *
 *
 */
static void directory_menu_cb_ok(GtkWidget *widget,
                                 gpointer  data     ) {
  ManageDialog *md;

  md = (ManageDialog*)data;

  md->is_ok = TRUE;

  gtk_main_quit();

  return;
}

/*
 * @directory_menu_cb_cancel
 *
 *
 */
static void directory_menu_cb_cancel(GtkWidget *widget,
                                     gpointer  data     ) {
  ManageDialog *md;

  md = (ManageDialog*)data;

  md->is_ok = FALSE;

  gtk_main_quit();

  return;
}

/*
 * @directory_menu_cerate_name_dialog
 *
 *  Create a dialog to input a new directory name.
 *  -- return value, type gchar*, must be freed.
 *
 */
static gchar* directory_menu_cerate_name_dialog(TopLevel *tp) {
  ManageDialog md;
  GtkWidget    *frame;
  GtkWidget    *entry;
  GtkWidget    *hbox;
  GtkWidget    *button;
  gchar        *name;

  /* Initilaize th local variables. */
  name     = NULL;
  md.is_ok = FALSE;

  /* Create a dialog to input a new directory name. */
  md.dialog = gtk_dialog_new();
  gtk_window_set_title(GTK_WINDOW(md.dialog), _("New Directory"));
  gtk_window_set_policy(GTK_WINDOW(md.dialog), FALSE, FALSE, FALSE);
  gtk_window_set_position(GTK_WINDOW(md.dialog), GTK_WIN_POS_CENTER);
  gtk_window_set_transient_for(GTK_WINDOW(md.dialog), GTK_WINDOW(tp->window));
  gtk_signal_connect(GTK_OBJECT(md.dialog), 
                     "delete-event",
                     GTK_SIGNAL_FUNC(directory_menu_cb_cancel), &md);

  frame = gtk_frame_new(NULL);
  gtk_container_border_width(GTK_CONTAINER(frame), 8);
  gtk_box_pack_start(GTK_BOX(GTK_DIALOG(md.dialog)->vbox), frame, 
                     TRUE, TRUE, 0);
  gtk_widget_show(frame);

  hbox = gtk_hbox_new(FALSE, 2);
  gtk_container_add(GTK_CONTAINER(frame), hbox);
  gtk_widget_show(hbox);

  entry = gtk_entry_new();
  gtk_signal_connect(GTK_OBJECT(entry), 
                     "activate",
                     GTK_SIGNAL_FUNC(directory_menu_cb_ok), &md);
  gtk_widget_set_usize(entry, 200, 20);
  gtk_box_pack_start(GTK_BOX(hbox), entry, TRUE, FALSE, 0);
  gtk_widget_show(entry);

  button = gtk_button_new_with_label(_("  OK  "));
  gtk_box_pack_start(GTK_BOX(GTK_DIALOG(md.dialog)->action_area), button,
                     FALSE, FALSE, 0);
  gtk_signal_connect(GTK_OBJECT(button), 
                     "clicked",
                     GTK_SIGNAL_FUNC(directory_menu_cb_ok), &md);
  GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
  gtk_widget_grab_default(button);
  gtk_widget_show(button);

  button = gtk_button_new_with_label(_("  Cancel  "));
  gtk_box_pack_start(GTK_BOX(GTK_DIALOG(md.dialog)->action_area), button,
                     FALSE, FALSE, 0);
  gtk_signal_connect(GTK_OBJECT(button), 
                     "clicked",
                     GTK_SIGNAL_FUNC(directory_menu_cb_cancel), &md);
  GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
  gtk_widget_show(button);

  gtk_widget_grab_focus(GTK_WIDGET(entry));

  gtk_widget_show(md.dialog);

  gtk_window_set_modal(GTK_WINDOW(md.dialog), TRUE);

  gtk_main();

  gtk_window_set_modal(GTK_WINDOW(md.dialog), FALSE);

  if (md.is_ok == TRUE) {
    name = strdup(gtk_entry_get_text(GTK_ENTRY(entry)));
    if (name == NULL) {
      /* Out of memory. */
      fprintf(stderr, "danpei: Out of memory.\n");
      fprintf(stderr, "        directory_menu.c: error -- 02.\n");
      gtk_exit(-1);
    }
    if (strcmp(name, "") == 0) {
      free(name);
      name = NULL;
    }
  }
  else {
    name = NULL;
  }

  gtk_widget_destroy(md.dialog);

  return name;
}

/*
 * @directory_menu_insert_new_node
 *
 *  Insert a new node to the directory tree.
 *  -- this function will be called after directory_menu_cb_new().
 *
 */
static void directory_menu_insert_new_node (TopLevel     *tp         ,
                                            GtkCTreeNode *parent_node,
                                            gchar        *new_name   ,
                                            gchar        *full_path    ) {
  GtkCTreeNode *wk_node, *dummy_node;
  NodeInfo     *parent_nodeinfo, *nodeinfo;
  gchar        *dummy_node_str = "dummy";
  gboolean     is_leaf, is_expanded;

  /* Get parent node information. */
  parent_nodeinfo = 
         gtk_ctree_node_get_row_data(GTK_CTREE(tp->dir_tree.ctree),
                                     GTK_CTREE_NODE(parent_node)    );
  gtk_ctree_get_node_info(GTK_CTREE(tp->dir_tree.ctree),
                          GTK_CTREE_NODE(parent_node),
                          NULL, NULL, NULL, NULL, NULL, NULL,
                          &is_leaf, &is_expanded);

  if (parent_nodeinfo->is_scan == FALSE) {
    wk_node = gtk_ctree_find_by_row_data(GTK_CTREE(tp->dir_tree.ctree),
                                         GTK_CTREE_NODE(parent_node) , NULL);
    if(wk_node == NULL) {
      dummy_node = gtk_ctree_insert_node(GTK_CTREE(tp->dir_tree.ctree),
                                         parent_node     , NULL,
                                         &dummy_node_str , 4   ,
                                         NULL, NULL, NULL, NULL,
                                         FALSE, FALSE           );
      gtk_ctree_node_set_row_data(GTK_CTREE(tp->dir_tree.ctree), 
                                  GTK_CTREE_NODE(dummy_node)   , NULL);
    }
  }
  else {
    gtk_clist_freeze(GTK_CLIST(tp->dir_tree.ctree));

    wk_node = gtk_ctree_insert_node(GTK_CTREE(tp->dir_tree.ctree),
                                    GTK_CTREE_NODE(parent_node),
                                    NULL, &new_name, 4,
                                    tp->closed_folder_pixmap, 
                                    tp->closed_folder_mask  ,
                                    tp->opened_folder_pixmap,
                                    tp->opened_folder_mask  ,
                                    FALSE, FALSE              );
    
    nodeinfo = (NodeInfo*)malloc(sizeof(NodeInfo));
    if(nodeinfo == NULL) {
      /* Out of memory. */
      fprintf(stderr, "danpei: Out of memory.\n");
      fprintf(stderr, "        directory_menu.c: error -- 03.\n");
      gtk_exit(-1);
    }
    nodeinfo->is_scan = FALSE;
    nodeinfo->next    = NULL;
    (tp->dir_tree.last_nodeinfo)->next = nodeinfo;
    (tp->dir_tree).last_nodeinfo       = nodeinfo;
    if ((nodeinfo->path = strdup(full_path)) == NULL) {
      /* Out of memory. */
      fprintf(stderr, "danpei: Out of memory.\n");
      fprintf(stderr, "        directory_menu.c: error -- 04.\n");
      gtk_exit(-1);
    }
    gtk_ctree_node_set_row_data(GTK_CTREE(tp->dir_tree.ctree), 
                                GTK_CTREE_NODE(wk_node), nodeinfo);

    gtk_clist_thaw(GTK_CLIST(tp->dir_tree.ctree));
  }

  if (is_expanded == FALSE) {
    gtk_ctree_expand(GTK_CTREE(tp->dir_tree.ctree), parent_node);
  }

  return;
}




Generated by  Doxygen 1.6.0   Back to index