mc/gnome/gnome-open-dialog.c
Miguel de Icaza ca1437548b 1999-03-10 Federico Mena Quintero <federico@nuclecu.unam.mx>
This is a semi-big slew of changes to integrate the DESKTOP_BRANCH
	into the main trunk.  Now the gdesktop code creates a temprary
	WPanel structure and passes it on to the core file management
	functions.  Also, the menu code is improved (we now use gpopup2;
	gpopup should go away shortly and gpopup2 should replace it).
	This makes the desktop act consistently with the file panels.
	Thanks to Jonathan for his help with this branch.

	* gdnd.c (perform_action): Use mc_lstat(), not mc_stat().

	* glayout.c (update_panels): Do not update the panels that are
	desktop panels.

	* gdesktop.c (icon_is_in_area): An icon is not considered to be in
	a 0x0 area.

	* gpopup2.c (handle_open): Fetch the desktop icon from the
	filename and call desktop_icon_info_open().

	* gdesktop.c (desktop_icon_info_get_by_filename): New function to
	look up a desktop icon by its filename.

	* glayout.c (create_new_menu_from): Test for the ".desktop" suffix
	correctly.

	* gpopup2.c (handle_properties): If the file comes from a desktop
	panel, always allow edition of the icon image.

1999-03-10  Federico Mena Quintero  <federico@nuclecu.unam.mx>

	* file.c (erase_dir): Erase metadata for directories as well.
	(erase_dir_iff_empty): Likewise.
	(copy_file_file): Delete/copy the metadata even for
	char/block/sock/fifo files.  Same thing for when copying symlinks.
	(copy_dir_dir): Delete/copy the metadata.
	(move_dir_dir): Delete/move the metadata.
	(recursive_erase): Delete the metadata.
1999-03-11 02:40:53 +00:00

333 lines
12 KiB
C

/* gnome-open-dialog.c
* Copyright (C) 1999 Red Hat Software. Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#include <gnome.h>
#include "gnome-open-dialog.h"
#include <sys/types.h>
#include <dirent.h>
#include <sys/stat.h>
#include <unistd.h>
static void gnome_open_dialog_init (GnomeOpenDialog *open_dialog);
static void gnome_open_dialog_class_init (GnomeOpenDialogClass *klass);
static void gnome_open_dialog_destroy (GtkObject *object);
static void gnome_open_dialog_generate_tree_helper (GtkCTree *ctree, GtkCTreeNode *parent, GNode *node);
static void gnome_open_dialog_destroy_func (GtkCTree *ctree, GtkCTreeNode *node, gpointer data);
static GnomeDialogClass *parent_class = NULL;
#define SMALL_ICON_SIZE 20
GtkType
gnome_open_dialog_get_type (void)
{
static GtkType open_dialog_type = 0;
if (!open_dialog_type)
{
static const GtkTypeInfo open_dialog_info =
{
"GnomeOpenDialog",
sizeof (GnomeOpenDialog),
sizeof (GnomeOpenDialogClass),
(GtkClassInitFunc) gnome_open_dialog_class_init,
(GtkObjectInitFunc) gnome_open_dialog_init,
/* reserved_1 */ NULL,
/* reserved_2 */ NULL,
(GtkClassInitFunc) NULL,
};
open_dialog_type = gtk_type_unique (gnome_dialog_get_type (), &open_dialog_info);
}
return open_dialog_type;
}
static void
gnome_open_dialog_class_init (GnomeOpenDialogClass *klass)
{
GtkObjectClass *object_class;
object_class = (GtkObjectClass*) klass;
parent_class = gtk_type_class (gnome_dialog_get_type ());
object_class->destroy = gnome_open_dialog_destroy;
}
static void
gnome_open_dialog_destroy_func (GtkCTree *ctree,
GtkCTreeNode *node,
gpointer data)
{
GnomeDesktopEntry *gde;
if (ctree == NULL || node == NULL)
return;
gde = (GnomeDesktopEntry *)gtk_ctree_node_get_row_data (GTK_CTREE (ctree),node);
if (gde)
gnome_desktop_entry_free (gde);
}
static void
gnome_open_dialog_destroy (GtkObject *object)
{
g_return_if_fail (object != NULL);
g_return_if_fail (GNOME_IS_OPEN_DIALOG (object));
g_free (GNOME_OPEN_DIALOG (object)->file_name);
gtk_ctree_post_recursive (GTK_CTREE (GNOME_OPEN_DIALOG (object)->ctree),
NULL,
gnome_open_dialog_destroy_func,
NULL);
gtk_widget_unref (GNOME_OPEN_DIALOG (object)->ctree);
gtk_widget_unref (GNOME_OPEN_DIALOG (object)->entry);
(* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
}
static void
gnome_open_dialog_init (GnomeOpenDialog *open_dialog)
{
}
/* Private internal functions */
/* Stolen from gnomecc:tree.c */
static GNode *
read_directory (gchar *directory)
{
DIR *parent_dir;
struct dirent *child_dir;
struct stat filedata;
GNode *retval = g_node_new(NULL);
parent_dir = opendir (directory);
if (parent_dir == NULL)
return NULL;
while ((child_dir = readdir (parent_dir)) != NULL) {
if (child_dir->d_name[0] != '.') {
/* we check to see if it is interesting. */
GString *name = g_string_new (directory);
g_string_append (name, "/");
g_string_append (name, child_dir->d_name);
if (stat (name->str, &filedata) != -1) {
gchar* test;
if (S_ISDIR (filedata.st_mode)) {
/* it might be interesting... */
GNode *next_dir = read_directory (name->str);
if (next_dir)
/* it is interesting!!! */
g_node_prepend (retval, next_dir);
}
test = rindex(child_dir->d_name, '.');
if (test && !strcmp (".desktop", test)) {
/* it's a .desktop file -- it's interesting for sure! */
GNode *new_node = g_node_new (gnome_desktop_entry_load (name->str));
g_node_prepend (retval, new_node);
}
}
g_string_free (name, TRUE);
}
else if (!strcmp (child_dir->d_name, ".directory")) {
GString *name = g_string_new (directory);
g_string_append (name, "/.directory");
retval->data = gnome_desktop_entry_load (name->str);
g_string_free (name, TRUE);
}
}
#if 0
if (!retval->data) {
/* no .directory file. Well, I guess we abort. */
/* FIXME: i guess we should free memory now... */
return NULL;
}
#endif
if (retval->children == NULL) {
if (retval->data)
gnome_desktop_entry_free (retval->data);
return NULL;
}
return retval;
}
static void
gnome_open_dialog_generate_tree_helper (GtkCTree *ctree, GtkCTreeNode *parent, GNode *node)
{
GNode *i;
GtkCTreeNode *child = NULL;
static char *text[2];
GnomePixmap *icon_gpixmap;
gchar *icon;
GdkPixmap *icon_pixmap, *icon_mask;
text[0] = NULL;
text[1] = NULL;
for (i = node;i;i = i->next) {
icon_pixmap=NULL;
icon_mask=NULL;
icon=NULL;
icon_gpixmap = NULL;
if (i->data && ((GnomeDesktopEntry *)i->data)->name) {
text[0] = ((GnomeDesktopEntry *)i->data)->name;
} else
text[0] = NULL;
if ((i->data) && ((GnomeDesktopEntry *)i->data)->icon)
icon = ((GnomeDesktopEntry *)i->data)->icon;
if (icon && g_file_exists (icon))
icon_gpixmap = (GnomePixmap *)gnome_pixmap_new_from_file_at_size(icon,
SMALL_ICON_SIZE,
SMALL_ICON_SIZE);
if (icon_gpixmap) {
icon_pixmap = icon_gpixmap->pixmap;
icon_mask = icon_gpixmap->mask;
}
if (i->data && text[0]) {
if (((GnomeDesktopEntry *)i->data)->type && !strcmp(((GnomeDesktopEntry *)i->data)->type,"Directory"))
child = gtk_ctree_insert_node (ctree,parent,NULL, text, 3, icon_pixmap, icon_mask, icon_pixmap, icon_mask,FALSE,FALSE);
else
child = gtk_ctree_insert_node (ctree,parent,NULL, text, 3, icon_pixmap, icon_mask, icon_pixmap, icon_mask,TRUE,FALSE);
gtk_ctree_node_set_row_data (ctree, child, i->data);
} else
gnome_desktop_entry_free (i->data);
if (i->children)
gnome_open_dialog_generate_tree_helper (ctree, child, i->children);
/*
if (parent == NULL)
gtk_ctree_expand_recursive (ctree, child);
*/
}
}
static void
gnome_open_dialog_selected_row_callback (GtkWidget *widget, GtkCTreeNode *node, gint column, gpointer *data)
{
GnomeDesktopEntry *gde = NULL;
GnomeOpenDialog *dialog = NULL;
GtkWidget *entry;
if (column < 0)
return;
dialog = GNOME_OPEN_DIALOG (data);
gde = (GnomeDesktopEntry *)gtk_ctree_node_get_row_data (GTK_CTREE (widget),node);
g_return_if_fail (dialog != NULL);
g_return_if_fail (gde != NULL);
if (gde->exec) {
entry = gnome_file_entry_gtk_entry (GNOME_FILE_ENTRY (dialog->entry));
gtk_entry_set_text (GTK_ENTRY (entry), gde->exec[0]);
}
}
GtkWidget *
gnome_open_dialog_get_tree (GnomeOpenDialog *dialog)
{
GtkWidget *retval;
gchar *prefix;
GNode *node;
/* widget stuff */
retval = gtk_ctree_new (1, 0);
gtk_clist_set_row_height(GTK_CLIST (retval),20);
gtk_ctree_set_line_style (GTK_CTREE (retval), GTK_CTREE_LINES_DOTTED);
gtk_ctree_set_expander_style (GTK_CTREE (retval), GTK_CTREE_EXPANDER_SQUARE);
gtk_clist_set_column_width(GTK_CLIST (retval), 0, 150);
gtk_signal_connect( GTK_OBJECT (retval),
"tree_select_row",
GTK_SIGNAL_FUNC (gnome_open_dialog_selected_row_callback),
dialog);
gtk_ctree_set_indent (GTK_CTREE (retval), 15);
gtk_clist_set_column_auto_resize (GTK_CLIST (retval), 0, TRUE);
/* set up the apps */
prefix = gnome_unconditional_datadir_file ("gnome/apps");
node = read_directory (prefix);
gnome_open_dialog_generate_tree_helper (GTK_CTREE (retval), NULL, node);
g_node_destroy (node);
g_free (prefix);
return retval;
}
/* Public functions */
GtkWidget *
gnome_open_dialog_new (gchar *file_name)
{
GnomeOpenDialog *dialog;
GtkWidget *label;
GtkWidget *frame;
GtkWidget *sw;
gchar *label_string;
g_return_val_if_fail (file_name != NULL, NULL);
dialog = gtk_type_new (gnome_open_dialog_get_type ());
/* the first label */
label_string = g_strconcat (_("Select an application to open \""),
file_name, "\" with.", NULL);
label = gtk_label_new (label_string);
gtk_widget_set_usize (label, 300, -1);
gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT);
g_free (label_string);
gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
/* The entry */
dialog->file_name = g_strdup (file_name);
dialog->entry = gnome_file_entry_new ("GNOME_OPEN_DIALOG",
_("Select a file to run with"));
gtk_widget_ref (dialog->entry);
/* Watch me do something evil... (-: */
label_string = gnome_unconditional_libdir_file ("");
strcpy (label_string + strlen (label_string) - 4, "bin");
g_print ("%s\n", label_string);
gnome_file_entry_set_default_path (GNOME_FILE_ENTRY (dialog->entry),
label_string);
g_free (label_string);
/* the file tree */
frame = gtk_frame_new (_("Applications"));
dialog->ctree = gnome_open_dialog_get_tree (dialog);
gtk_widget_ref (dialog->ctree);
sw = gtk_scrolled_window_new (GTK_CLIST (dialog->ctree)->hadjustment,
GTK_CLIST (dialog->ctree)->vadjustment);
gtk_widget_set_usize (sw, 300, 170);
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
gtk_container_set_border_width (GTK_CONTAINER (sw), GNOME_PAD_SMALL);
gtk_container_add (GTK_CONTAINER (sw), dialog->ctree);
gtk_container_add (GTK_CONTAINER (frame), sw);
gtk_box_pack_start (GTK_BOX (GNOME_DIALOG (dialog)->vbox),
label, FALSE, FALSE, 0);
gtk_box_pack_start (GTK_BOX (GNOME_DIALOG (dialog)->vbox),
frame, FALSE, FALSE, 0);
frame = gtk_frame_new (_("Program to run"));
gtk_container_set_border_width (GTK_CONTAINER (dialog->entry), GNOME_PAD_SMALL);
gtk_container_add (GTK_CONTAINER (frame), dialog->entry);
gtk_box_pack_start (GTK_BOX (GNOME_DIALOG (dialog)->vbox),
frame, FALSE, FALSE, 0);
gnome_dialog_append_button (GNOME_DIALOG(dialog),
GNOME_STOCK_BUTTON_OK);
gnome_dialog_append_button (GNOME_DIALOG(dialog),
GNOME_STOCK_BUTTON_CANCEL);
gtk_widget_show_all (GNOME_DIALOG (dialog)->vbox);
return GTK_WIDGET (dialog);
}