1998-03-19 07:51:17 +03:00
|
|
|
/* GNU Midnight Commander -- GNOME edition
|
|
|
|
*
|
1998-03-20 05:00:09 +03:00
|
|
|
* Properties dialog for files and desktop icons.
|
1998-03-19 07:51:17 +03:00
|
|
|
*
|
|
|
|
* Copyright (C) 1997 The Free Software Foundation
|
|
|
|
*
|
|
|
|
* Authors: Miguel de Icaza
|
|
|
|
* Federico Mena
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <config.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <stdlib.h> /* atoi */
|
|
|
|
#include <pwd.h>
|
|
|
|
#include <grp.h>
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include "fs.h"
|
|
|
|
#include "x.h"
|
|
|
|
#include "gprop.h"
|
|
|
|
#include "util.h"
|
1998-03-20 05:00:09 +03:00
|
|
|
#include "dialog.h"
|
1998-03-19 07:51:17 +03:00
|
|
|
#include "file.h"
|
1998-03-20 05:00:09 +03:00
|
|
|
#include "../vfs/vfs.h"
|
1998-03-19 07:51:17 +03:00
|
|
|
#include "gpageprop.h"
|
|
|
|
|
|
|
|
static int prop_dialog_result;
|
|
|
|
|
|
|
|
static GtkWidget *
|
|
|
|
c_spacing (GtkWidget *widget)
|
|
|
|
{
|
1998-12-01 08:13:40 +03:00
|
|
|
gtk_container_set_border_width (GTK_CONTAINER (widget), 6);
|
1998-03-19 07:51:17 +03:00
|
|
|
return widget;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
properties_button_click (GtkWidget *widget, gpointer value)
|
|
|
|
{
|
|
|
|
prop_dialog_result = (int) value;
|
|
|
|
gtk_main_quit ();
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
kill_toplevel ()
|
|
|
|
{
|
|
|
|
gtk_main_quit ();
|
|
|
|
}
|
|
|
|
|
1998-03-20 05:00:09 +03:00
|
|
|
int
|
|
|
|
item_properties (GtkWidget *parent, char *fname, desktop_icon_t *di)
|
1998-03-19 07:51:17 +03:00
|
|
|
{
|
1998-03-21 02:38:43 +03:00
|
|
|
GtkWidget *parent_window;
|
1998-05-21 02:10:06 +04:00
|
|
|
GdkCursor *cursor;
|
1998-03-21 02:38:43 +03:00
|
|
|
GtkWidget *notebook, *ok, *cancel;
|
|
|
|
GtkWidget *vbox;
|
|
|
|
GpropFilename *name;
|
|
|
|
GpropPerm *perm;
|
|
|
|
GpropGeneral *gene;
|
1998-05-20 09:49:16 +04:00
|
|
|
GpropExec *exec;
|
1998-03-21 02:38:43 +03:00
|
|
|
GtkDialog *toplevel;
|
|
|
|
|
|
|
|
umode_t new_mode;
|
|
|
|
char *new_group;
|
|
|
|
char *new_owner;
|
|
|
|
char *new_title;
|
|
|
|
char *new_icon;
|
|
|
|
char *new_name;
|
|
|
|
char *base;
|
1998-03-20 05:00:09 +03:00
|
|
|
|
1998-03-19 07:51:17 +03:00
|
|
|
struct stat s;
|
1998-03-20 05:00:09 +03:00
|
|
|
int retval = 0;
|
|
|
|
|
|
|
|
/* Set a clock cursor while we create stuff and read users/groups */
|
|
|
|
|
|
|
|
parent_window = gtk_widget_get_toplevel (parent);
|
1998-05-21 02:10:06 +04:00
|
|
|
cursor = gdk_cursor_new (GDK_WATCH);
|
|
|
|
gdk_window_set_cursor (parent_window->window, cursor);
|
|
|
|
gdk_cursor_destroy (cursor);
|
1998-03-20 05:00:09 +03:00
|
|
|
|
1998-03-19 07:51:17 +03:00
|
|
|
toplevel = GTK_DIALOG (gtk_dialog_new ());
|
|
|
|
notebook = gtk_notebook_new ();
|
|
|
|
gtk_box_pack_start_defaults (GTK_BOX (toplevel->vbox), notebook);
|
|
|
|
gtk_window_set_title (GTK_WINDOW (toplevel), fname);
|
|
|
|
|
|
|
|
/* Create the property widgets */
|
|
|
|
mc_stat (fname, &s);
|
|
|
|
base = x_basename (fname);
|
1998-03-20 05:00:09 +03:00
|
|
|
|
|
|
|
vbox = gtk_vbox_new (FALSE, 6);
|
1998-03-19 07:51:17 +03:00
|
|
|
|
1998-03-20 05:00:09 +03:00
|
|
|
if (di && di->dentry) {
|
1998-03-21 02:38:43 +03:00
|
|
|
gene = gprop_general_new (di->dentry->name, di->dentry->icon);
|
|
|
|
gtk_box_pack_start (GTK_BOX (vbox), gene->top, FALSE, FALSE, 0);
|
1998-05-20 09:49:16 +04:00
|
|
|
|
|
|
|
exec = gprop_exec_new (di->dentry);
|
|
|
|
gtk_box_pack_start (GTK_BOX (vbox), exec->top, FALSE, FALSE, 0);
|
|
|
|
} else {
|
|
|
|
name = gprop_filename_new (fname, base);
|
|
|
|
gtk_box_pack_start (GTK_BOX (vbox), name->top, FALSE, FALSE, 0);
|
1998-03-20 05:00:09 +03:00
|
|
|
}
|
1998-05-20 09:49:16 +04:00
|
|
|
|
1998-03-21 02:38:43 +03:00
|
|
|
perm = gprop_perm_new (s.st_mode, get_owner (s.st_uid), get_group (s.st_gid));
|
|
|
|
|
1998-03-19 07:51:17 +03:00
|
|
|
/* Pack them into nice notebook */
|
1998-03-20 05:00:09 +03:00
|
|
|
gtk_notebook_append_page (GTK_NOTEBOOK (notebook), c_spacing (vbox), gtk_label_new ("General"));
|
1998-03-19 07:51:17 +03:00
|
|
|
gtk_notebook_append_page (GTK_NOTEBOOK (notebook), c_spacing (perm->top), gtk_label_new ("Permissions"));
|
|
|
|
|
|
|
|
/* Ok, Cancel */
|
|
|
|
ok = gnome_stock_button (GNOME_STOCK_BUTTON_OK);
|
|
|
|
GTK_WIDGET_SET_FLAGS (ok, GTK_CAN_DEFAULT);
|
1998-03-20 05:00:09 +03:00
|
|
|
|
1998-03-19 07:51:17 +03:00
|
|
|
cancel = gnome_stock_button (GNOME_STOCK_BUTTON_CANCEL);
|
1998-03-20 05:00:09 +03:00
|
|
|
GTK_WIDGET_SET_FLAGS (cancel, GTK_CAN_DEFAULT);
|
1998-03-19 07:51:17 +03:00
|
|
|
|
|
|
|
gtk_box_pack_start (GTK_BOX (toplevel->action_area), ok, 0, 0, 0);
|
|
|
|
gtk_box_pack_start (GTK_BOX (toplevel->action_area), cancel, 0, 0, 0);
|
1998-03-20 05:00:09 +03:00
|
|
|
|
1998-03-19 07:51:17 +03:00
|
|
|
gtk_signal_connect (GTK_OBJECT (ok), "clicked", GTK_SIGNAL_FUNC (properties_button_click), (gpointer) 0);
|
|
|
|
gtk_signal_connect (GTK_OBJECT (cancel), "clicked", GTK_SIGNAL_FUNC (properties_button_click), (gpointer) 1);
|
|
|
|
gtk_signal_connect (GTK_OBJECT (toplevel), "delete_event", GTK_SIGNAL_FUNC (kill_toplevel), toplevel);
|
1998-03-20 05:00:09 +03:00
|
|
|
|
1998-03-19 07:51:17 +03:00
|
|
|
/* Start the dialog box */
|
|
|
|
prop_dialog_result = -1;
|
1998-03-20 05:00:09 +03:00
|
|
|
|
|
|
|
gtk_widget_grab_default (ok);
|
1998-03-19 07:51:17 +03:00
|
|
|
gtk_widget_show_all (GTK_WIDGET (toplevel));
|
1998-03-20 05:00:09 +03:00
|
|
|
|
1998-05-21 02:10:06 +04:00
|
|
|
/* Restore the arrow cursor and run the dialog */
|
|
|
|
|
|
|
|
cursor = gdk_cursor_new (GDK_TOP_LEFT_ARROW);
|
|
|
|
gdk_window_set_cursor (parent_window->window, cursor);
|
|
|
|
gdk_cursor_destroy (cursor);
|
|
|
|
|
1998-03-19 07:51:17 +03:00
|
|
|
gtk_grab_add (GTK_WIDGET (toplevel));
|
|
|
|
gtk_main ();
|
|
|
|
gtk_grab_remove (GTK_WIDGET (toplevel));
|
|
|
|
|
1998-03-20 05:00:09 +03:00
|
|
|
if (prop_dialog_result != 0) {
|
1998-03-19 07:51:17 +03:00
|
|
|
gtk_widget_destroy (GTK_WIDGET (toplevel));
|
1998-03-20 05:00:09 +03:00
|
|
|
return 0; /* nothing changed */
|
1998-03-19 07:51:17 +03:00
|
|
|
}
|
|
|
|
|
1998-03-20 05:00:09 +03:00
|
|
|
/* Check and change permissions */
|
|
|
|
|
1998-03-19 07:51:17 +03:00
|
|
|
gprop_perm_get_data (perm, &new_mode, &new_owner, &new_group);
|
|
|
|
|
1998-03-20 05:00:09 +03:00
|
|
|
if (new_mode != s.st_mode) {
|
1998-03-19 07:51:17 +03:00
|
|
|
mc_chmod (fname, new_mode);
|
1998-03-20 05:00:09 +03:00
|
|
|
retval |= GPROP_MODE;
|
|
|
|
}
|
|
|
|
|
1998-03-19 07:51:17 +03:00
|
|
|
if ((strcmp (new_owner, get_owner (s.st_uid)) != 0) ||
|
1998-03-20 05:00:09 +03:00
|
|
|
(strcmp (new_group, get_group (s.st_gid)) != 0)) {
|
1998-03-19 07:51:17 +03:00
|
|
|
struct passwd *p;
|
|
|
|
struct group *g;
|
|
|
|
uid_t uid;
|
|
|
|
gid_t gid;
|
|
|
|
|
|
|
|
/* Get uid */
|
|
|
|
p = getpwnam (new_owner);
|
1998-03-20 05:00:09 +03:00
|
|
|
if (!p) {
|
1998-03-19 07:51:17 +03:00
|
|
|
uid = atoi (new_owner);
|
1998-03-20 05:00:09 +03:00
|
|
|
if (uid == 0) {
|
1998-03-19 07:51:17 +03:00
|
|
|
int v;
|
|
|
|
v = query_dialog ("Warning",
|
|
|
|
"You entered an invalid user name, should I use `root'?",
|
|
|
|
0, 2, "Yes", "No");
|
|
|
|
if (v != 0)
|
|
|
|
goto ciao;
|
|
|
|
}
|
|
|
|
} else
|
|
|
|
uid = p->pw_uid;
|
|
|
|
|
|
|
|
/* get gid */
|
|
|
|
g = getgrnam (new_group);
|
1998-03-20 05:00:09 +03:00
|
|
|
if (!g) {
|
1998-03-19 07:51:17 +03:00
|
|
|
gid = atoi (new_group);
|
1998-03-20 05:00:09 +03:00
|
|
|
if (gid == 0) {
|
1998-03-19 07:51:17 +03:00
|
|
|
message (1, "Error", "You entered an invalid group name");
|
|
|
|
goto ciao2;
|
|
|
|
}
|
|
|
|
} else
|
|
|
|
gid = g->gr_gid;
|
1998-03-20 05:00:09 +03:00
|
|
|
|
1998-03-19 07:51:17 +03:00
|
|
|
mc_chown (fname, uid, gid);
|
1998-03-20 05:00:09 +03:00
|
|
|
retval |= GPROP_UID | GPROP_GID;
|
|
|
|
|
1998-03-19 07:51:17 +03:00
|
|
|
ciao2:
|
|
|
|
endgrent ();
|
|
|
|
ciao:
|
|
|
|
endpwent ();
|
|
|
|
}
|
|
|
|
|
1998-03-20 05:00:09 +03:00
|
|
|
/* Check and change filename */
|
|
|
|
|
1998-05-20 09:49:16 +04:00
|
|
|
if (di && di->dentry){
|
|
|
|
gprop_exec_get_data (exec, di->dentry);
|
|
|
|
} else {
|
|
|
|
gprop_filename_get_data (name, &new_name);
|
|
|
|
|
|
|
|
if (strchr (new_name, '/'))
|
|
|
|
message (1, "Error", "The new name includes the `/' character");
|
|
|
|
else if (strcmp (new_name, base) != 0) {
|
1998-12-05 02:39:41 +03:00
|
|
|
char *base = x_basename (fname);
|
|
|
|
char save = *base;
|
|
|
|
char *full_target;
|
|
|
|
long count = 0;
|
|
|
|
double bytes = 0;
|
1998-05-20 09:49:16 +04:00
|
|
|
|
|
|
|
*base = 0;
|
|
|
|
full_target = concat_dir_and_file (fname, new_name);
|
|
|
|
*base = save;
|
|
|
|
|
|
|
|
create_op_win (OP_MOVE, 0);
|
|
|
|
file_mask_defaults ();
|
1998-12-05 02:39:41 +03:00
|
|
|
move_file_file (fname, full_target, &count, &bytes);
|
1998-05-20 09:49:16 +04:00
|
|
|
destroy_op_win ();
|
|
|
|
|
|
|
|
if (di) {
|
|
|
|
free (di->pathname);
|
|
|
|
di->pathname = full_target;
|
|
|
|
} else
|
|
|
|
free (full_target);
|
|
|
|
|
|
|
|
retval |= GPROP_FILENAME;
|
|
|
|
}
|
1998-03-20 05:00:09 +03:00
|
|
|
}
|
1998-05-20 09:49:16 +04:00
|
|
|
|
1998-03-21 02:38:43 +03:00
|
|
|
/* Check and change title and icon -- change is handled by caller */
|
1998-03-20 05:00:09 +03:00
|
|
|
|
|
|
|
if (di && di->dentry) {
|
1998-03-21 02:38:43 +03:00
|
|
|
gprop_general_get_data (gene, &new_title, &new_icon);
|
|
|
|
|
|
|
|
if (strcmp (new_title, di->dentry->name) != 0) {
|
|
|
|
g_free (di->dentry->name);
|
|
|
|
|
|
|
|
di->dentry->name = new_title;
|
|
|
|
retval |= GPROP_TITLE;
|
|
|
|
}
|
1998-03-20 05:00:09 +03:00
|
|
|
|
|
|
|
if (strcmp (new_icon, di->dentry->icon) != 0) {
|
|
|
|
g_free (di->dentry->icon);
|
|
|
|
|
|
|
|
di->dentry->icon = new_icon;
|
|
|
|
retval |= GPROP_ICON;
|
|
|
|
}
|
1998-03-19 07:51:17 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
gtk_widget_destroy (GTK_WIDGET (toplevel));
|
1998-03-20 05:00:09 +03:00
|
|
|
return retval;
|
1998-03-19 07:51:17 +03:00
|
|
|
}
|