Codepage messages related translated & other stuff...
[midnight-commander.git] / gnome / gnome-file-property-dialog.c
blob60dccf4ceab8fe87a24f99b0bd1858d68c80a99b
1 /* gnome-file-property-dialog.c
2 * Copyright (C) 1999 Free Software Foundation
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
19 #include <config.h>
20 #include "dir.h"
21 #include "util.h"
22 #include <gnome.h>
23 #include <time.h>
24 #include <string.h>
25 #include "gnome-file-property-dialog.h"
26 #include "gdesktop.h"
27 #include <pwd.h>
28 #include <grp.h>
29 #include <sys/types.h>
30 #include <sys/stat.h>
31 #include "fileopctx.h"
32 #include "file.h"
33 #include "../vfs/vfs.h"
34 #include "gicon.h"
35 #include "dialog.h"
36 #include "gmain.h"
38 static void gnome_file_property_dialog_init (GnomeFilePropertyDialog *file_property_dialog);
39 static void gnome_file_property_dialog_class_init (GnomeFilePropertyDialogClass *klass);
40 static void gnome_file_property_dialog_finalize (GtkObject *object);
42 static GnomeDialogClass *parent_class = NULL;
45 GtkType
46 gnome_file_property_dialog_get_type (void)
48 static GtkType file_property_dialog_type = 0;
50 if (!file_property_dialog_type)
52 static const GtkTypeInfo file_property_dialog_info =
54 "GnomeFilePropertyDialog",
55 sizeof (GnomeFilePropertyDialog),
56 sizeof (GnomeFilePropertyDialogClass),
57 (GtkClassInitFunc) gnome_file_property_dialog_class_init,
58 (GtkObjectInitFunc) gnome_file_property_dialog_init,
59 /* reserved_1 */ NULL,
60 /* reserved_2 */ NULL,
63 file_property_dialog_type = gtk_type_unique (gnome_dialog_get_type (), &file_property_dialog_info);
66 return file_property_dialog_type;
69 static void
70 gnome_file_property_dialog_class_init (GnomeFilePropertyDialogClass *klass)
72 GtkObjectClass *object_class;
74 object_class = (GtkObjectClass*) klass;
76 parent_class = gtk_type_class (gnome_dialog_get_type ());
77 object_class->finalize = gnome_file_property_dialog_finalize;
82 static void
83 gnome_file_property_dialog_init (GnomeFilePropertyDialog *file_property_dialog)
85 gnome_dialog_close_hides (GNOME_DIALOG (file_property_dialog), TRUE);
87 file_property_dialog->file_name = NULL;
88 file_property_dialog->file_entry = NULL;
89 file_property_dialog->group_name = NULL;
90 file_property_dialog->modifyable = TRUE;
91 file_property_dialog->user_name = NULL;
92 file_property_dialog->prop1_label = NULL;
93 file_property_dialog->prop2_label = NULL;
94 file_property_dialog->prop1_entry = NULL;
95 file_property_dialog->prop2_entry = NULL;
96 file_property_dialog->prop1_cbox = NULL;
97 file_property_dialog->prop2_cbox = NULL;
98 file_property_dialog->fm_open = NULL;
99 file_property_dialog->fm_view = NULL;
100 file_property_dialog->edit = NULL;
101 file_property_dialog->drop_target = NULL;
102 file_property_dialog->im = NULL;
105 static void
106 gnome_file_property_dialog_finalize (GtkObject *object)
108 GnomeFilePropertyDialog *gfpd;
110 g_return_if_fail (object != NULL);
111 g_return_if_fail (GNOME_IS_FILE_PROPERTY_DIALOG (object));
113 gfpd = GNOME_FILE_PROPERTY_DIALOG (object);
115 if (gfpd->file_name)
116 g_free (gfpd->file_name);
117 if (gfpd->fm_open)
118 g_free (gfpd->fm_open);
119 if (gfpd->fm_view)
120 g_free (gfpd->fm_view);
121 if (gfpd->edit)
122 g_free (gfpd->edit);
123 if (gfpd->drop_target)
124 g_free (gfpd->drop_target);
125 if (gfpd->icon_filename)
126 g_free (gfpd->icon_filename);
127 if (gfpd->desktop_url)
128 g_free (gfpd->desktop_url);
129 if (gfpd->caption)
130 g_free (gfpd->caption);
132 if (gfpd->mode_name)
133 g_free (gfpd->mode_name);
135 (* GTK_OBJECT_CLASS (parent_class)->finalize) (object);
138 /* Create the pane */
140 static GtkWidget *
141 create_general_properties (GnomeFilePropertyDialog *fp_dlg)
143 GtkWidget *vbox;
144 GtkWidget *hbox;
145 GtkWidget *label;
146 GtkWidget *align;
147 gchar *direc;
148 gchar *gen_string;
149 gchar buf[MC_MAXPATHLEN];
150 gchar buf2[MC_MAXPATHLEN];
151 file_entry *fe;
152 GtkWidget *icon;
153 struct tm *time;
154 GtkWidget *table;
155 int n;
157 vbox = gtk_vbox_new (FALSE, GNOME_PAD_SMALL);
158 gtk_container_set_border_width (GTK_CONTAINER (vbox), GNOME_PAD);
160 /* first, we set the icon */
161 direc = g_strdup (fp_dlg->file_name);
162 strrchr (direc, '/')[0] = '\0';
163 fe = file_entry_from_file (fp_dlg->file_name);
164 fp_dlg->im = gicon_get_icon_for_file (direc, fe, FALSE);
165 file_entry_free (fe);
166 g_free (direc);
167 icon = gnome_pixmap_new_from_imlib (fp_dlg->im);
168 gtk_box_pack_start (GTK_BOX (vbox), icon, FALSE, FALSE, 0);
170 /* we set the file part */
171 gen_string = g_strconcat (_("Full Name: "), fp_dlg->file_name, NULL);
172 label = gtk_label_new (gen_string);
173 gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
174 g_free (gen_string);
175 gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
176 /* if it's a symlink */
177 align = gtk_alignment_new (0.0, 0.5, 1.0, 1.0);
178 hbox = gtk_hbox_new (FALSE, 2);
179 label = gtk_label_new (_("File Name"));
180 gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
181 fp_dlg->file_entry = gtk_entry_new ();
182 gen_string = strrchr (fp_dlg->file_name, '/');
183 if (gen_string)
184 gtk_entry_set_text (GTK_ENTRY (fp_dlg->file_entry), gen_string + 1);
185 else
186 /* I don't think this should happen anymore, but it can't hurt in
187 * case this ever gets used outside gmc */
188 gtk_entry_set_text (GTK_ENTRY (fp_dlg->file_entry), fp_dlg->file_name);
189 /* We want to prevent editing of the file if
190 * the thing is a BLK, CHAR, or we don't own it */
191 /* FIXME: We can actually edit it if we're in the same grp of the file. */
192 if (fp_dlg->modifyable == FALSE)
193 gtk_widget_set_sensitive (fp_dlg->file_entry, FALSE);
194 gtk_box_pack_start (GTK_BOX (hbox), fp_dlg->file_entry, FALSE, FALSE, 0);
195 gtk_container_add (GTK_CONTAINER (align), hbox);
196 gtk_box_pack_start (GTK_BOX (vbox), align, FALSE, FALSE, 0);
197 gtk_box_pack_start (GTK_BOX (vbox), gtk_hseparator_new (), FALSE, FALSE, 8);
199 /* File statistics */
200 /* File type first */
201 if (S_ISREG (fp_dlg->st.st_mode)) {
202 if (use_magic)
204 gen_string = g_strconcat (_("File Type: "),
205 gnome_mime_type_or_default_of_file (fp_dlg->file_name, "text/plain"),
206 NULL);
208 else
210 gen_string = g_strconcat (_("File Type: "),
211 gnome_mime_type (fp_dlg->file_name),
212 NULL);
214 label = gtk_label_new (gen_string);
215 g_free (gen_string);
216 } else if (S_ISLNK (fp_dlg->st.st_mode)) {
217 label = gtk_label_new (_("File Type: Symbolic Link"));
218 gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
219 gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
220 n = mc_readlink (fp_dlg->file_name, buf, MC_MAXPATHLEN);
221 if (n < 0)
222 label = gtk_label_new (_("Target Name: INVALID LINK"));
223 else {
224 buf [n] = 0;
225 gen_string = g_strconcat (_("Target Name: "), buf, NULL);
226 label = gtk_label_new (gen_string);
227 g_free (gen_string);
229 }else if (S_ISDIR (fp_dlg->st.st_mode))
230 label = gtk_label_new (_("File Type: Directory"));
231 else if (S_ISCHR (fp_dlg->st.st_mode))
232 label = gtk_label_new (_("File Type: Character Device"));
233 else if (S_ISBLK (fp_dlg->st.st_mode))
234 label = gtk_label_new (_("File Type: Block Device"));
235 else if (S_ISSOCK (fp_dlg->st.st_mode))
236 label = gtk_label_new (_("File Type: Socket"));
237 else if (S_ISFIFO (fp_dlg->st.st_mode))
238 label = gtk_label_new (_("File Type: FIFO"));
239 gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
240 gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
242 /* Now file size */
243 if (S_ISDIR (fp_dlg->st.st_mode)
244 || S_ISREG (fp_dlg->st.st_mode)
245 || S_ISLNK (fp_dlg->st.st_mode)) {
246 if ((gint)fp_dlg->st.st_size < 1024) {
247 snprintf (buf, MC_MAXPATHLEN, "%d", (gint) fp_dlg->st.st_size);
248 gen_string = g_strconcat (_("File Size: "), buf, _(" bytes"), NULL);
249 } else if ((gint)fp_dlg->st.st_size < 1024 * 1024) {
250 snprintf (buf, MC_MAXPATHLEN, "%.1f", (gfloat) fp_dlg->st.st_size / 1024.0);
251 snprintf (buf2, MC_MAXPATHLEN, "%d", (gint) fp_dlg->st.st_size);
252 gen_string = g_strconcat (_("File Size: "), buf, _(" KBytes ("),
253 buf2, _(" bytes)"), NULL);
254 } else {
255 snprintf (buf, MC_MAXPATHLEN, "%.1f",
256 (gfloat) fp_dlg->st.st_size / (1024.0 * 1024.0));
257 snprintf (buf2, MC_MAXPATHLEN, "%d", (gint) fp_dlg->st.st_size);
258 gen_string = g_strconcat (_("File Size: "), buf, _(" MBytes ("),
259 buf2, _(" bytes)"), NULL);
261 label = gtk_label_new (gen_string);
262 g_free (gen_string);
263 gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
264 gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
265 } else {
266 label = gtk_label_new (_("File Size: N/A"));
267 gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
268 gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
271 gtk_box_pack_start (GTK_BOX (vbox), gtk_hseparator_new (), FALSE, FALSE, 8);
273 /* Time Fields */
274 table = gtk_table_new (3, 2, FALSE);
275 gtk_table_set_row_spacings (GTK_TABLE (table), 2);
276 gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, FALSE, 0);
277 label = gtk_label_new (_("File Created on: "));
278 gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
279 gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 1, 0, 1);
280 time = localtime (&(fp_dlg->st.st_ctime));
281 strftime (buf, MC_MAXPATHLEN, _("%a, %b %d %Y, %I:%M:%S %p"), time);
282 label = gtk_label_new (buf);
283 gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
284 gtk_table_attach_defaults (GTK_TABLE (table), label, 1, 2, 0, 1);
286 label = gtk_label_new (_("Last Modified on: "));
287 gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
288 gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 1, 1, 2);
289 time = localtime (&(fp_dlg->st.st_mtime));
290 strftime (buf, MC_MAXPATHLEN, _("%a, %b %d %Y, %I:%M:%S %p"), time);
291 label = gtk_label_new (buf);
292 gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
293 gtk_table_attach_defaults (GTK_TABLE (table), label, 1, 2, 1, 2);
295 label = gtk_label_new (_("Last Accessed on: "));
296 gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
297 gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 1, 2, 3);
298 time = localtime (&(fp_dlg->st.st_atime));
299 strftime (buf, MC_MAXPATHLEN, _("%a, %b %d %Y, %I:%M:%S %p"), time);
300 label = gtk_label_new (buf);
301 gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
302 gtk_table_attach_defaults (GTK_TABLE (table), label, 1, 2, 2, 3);
303 return vbox;
306 static GtkWidget *
307 create_url_properties (GnomeFilePropertyDialog *fp_dlg)
309 GtkWidget *table, *label;
311 table = gtk_table_new (0, 0, 0);
313 label = gtk_label_new (_("URL:"));
314 gtk_table_attach (GTK_TABLE (table), label,
315 1, 2, 1, 2, 0, 0, GNOME_PAD, GNOME_PAD);
316 fp_dlg->desktop_entry = gtk_entry_new ();
317 gtk_table_attach (GTK_TABLE (table), fp_dlg->desktop_entry,
318 2, 3, 1, 2, GTK_FILL | GTK_EXPAND, 0, GNOME_PAD, GNOME_PAD);
320 label = gtk_label_new (_("Caption:"));
321 gtk_table_attach (GTK_TABLE (table), label,
322 1, 2, 2, 3, 0, 0, GNOME_PAD, GNOME_PAD);
323 fp_dlg->caption_entry = gtk_entry_new ();
324 gtk_table_attach (GTK_TABLE (table), fp_dlg->caption_entry,
325 2, 3, 2, 3, GTK_FILL | GTK_EXPAND, 0, GNOME_PAD, GNOME_PAD);
327 gtk_widget_show_all (table);
328 return table;
331 /* Settings Pane */
332 static void
333 metadata_toggled (GtkWidget *cbox, GnomeFilePropertyDialog *fp_dlg)
335 if (fp_dlg->changing)
336 return;
337 if (cbox == fp_dlg->open_cbox) {
338 if (GTK_TOGGLE_BUTTON (cbox)->active) {
339 gtk_widget_set_sensitive (fp_dlg->open_entry, FALSE);
340 if (fp_dlg->mime_fm_open)
341 gtk_entry_set_text (GTK_ENTRY (fp_dlg->open_entry), fp_dlg->mime_fm_open);
342 } else {
343 gtk_widget_set_sensitive (fp_dlg->open_entry, TRUE);
344 if (fp_dlg->fm_open) {
345 gtk_entry_set_text (GTK_ENTRY (fp_dlg->open_entry), fp_dlg->fm_open);
348 } else if (cbox == fp_dlg->prop1_cbox) {
349 if (GTK_TOGGLE_BUTTON (cbox)->active) {
350 gtk_widget_set_sensitive (fp_dlg->prop1_entry, FALSE);
351 if (fp_dlg->executable && fp_dlg->mime_drop_target) {
352 gtk_entry_set_text (GTK_ENTRY (fp_dlg->prop1_entry), fp_dlg->mime_drop_target);
353 } else if (!fp_dlg->executable && fp_dlg->mime_fm_view) {
354 gtk_entry_set_text (GTK_ENTRY (fp_dlg->prop1_entry), fp_dlg->mime_fm_view);
355 } else {
356 gtk_entry_set_text (GTK_ENTRY (fp_dlg->prop1_entry), "");
358 } else {
359 gtk_widget_set_sensitive (fp_dlg->prop1_entry, TRUE);
360 if (fp_dlg->executable && fp_dlg->drop_target) {
361 gtk_entry_set_text (GTK_ENTRY (fp_dlg->prop1_entry), fp_dlg->drop_target);
362 } else if (!fp_dlg->executable && fp_dlg->fm_view) {
363 gtk_entry_set_text (GTK_ENTRY (fp_dlg->prop1_entry), fp_dlg->fm_view);
366 } else {
367 if (GTK_TOGGLE_BUTTON (cbox)->active) {
368 gtk_widget_set_sensitive (fp_dlg->prop2_entry, FALSE);
369 if (fp_dlg->mime_edit) {
370 gtk_entry_set_text (GTK_ENTRY (fp_dlg->prop2_entry), fp_dlg->mime_edit);
371 } else {
372 gtk_entry_set_text (GTK_ENTRY (fp_dlg->prop2_entry), "");
374 } else {
375 gtk_widget_set_sensitive (fp_dlg->prop2_entry, TRUE);
376 if (fp_dlg->edit) {
377 gtk_entry_set_text (GTK_ENTRY (fp_dlg->prop2_entry), fp_dlg->edit);
383 static void
384 switch_metadata_box (GnomeFilePropertyDialog *fp_dlg)
386 if (NULL == fp_dlg->prop1_label)
387 return;
388 fp_dlg->changing = TRUE;
390 if (fp_dlg->desktop_url){
391 gtk_entry_set_text (GTK_ENTRY (fp_dlg->desktop_entry), fp_dlg->desktop_url);
393 gtk_entry_set_text (GTK_ENTRY (fp_dlg->caption_entry), fp_dlg->caption);
396 if (fp_dlg->executable) {
397 gtk_label_set_text (GTK_LABEL (fp_dlg->prop1_label), _("Drop Action"));
398 gtk_label_set_text (GTK_LABEL (GTK_BIN (fp_dlg->prop1_cbox)->child), _("Use default Drop Action options"));
399 if (fp_dlg->drop_target) {
400 gtk_toggle_button_set_active ( GTK_TOGGLE_BUTTON (fp_dlg->prop1_cbox), FALSE);
401 gtk_entry_set_text (GTK_ENTRY (fp_dlg->prop1_entry), fp_dlg->drop_target);
402 gtk_widget_set_sensitive (fp_dlg->prop1_entry, TRUE);
403 } else if (fp_dlg->mime_drop_target) {
404 gtk_entry_set_text (GTK_ENTRY (fp_dlg->prop1_entry), fp_dlg->mime_drop_target);
405 gtk_toggle_button_set_active ( GTK_TOGGLE_BUTTON (fp_dlg->prop1_cbox), TRUE);
406 gtk_widget_set_sensitive (fp_dlg->prop1_entry, FALSE);
407 } else {
408 gtk_entry_set_text (GTK_ENTRY (fp_dlg->prop1_entry), "");
409 gtk_toggle_button_set_active ( GTK_TOGGLE_BUTTON (fp_dlg->prop1_cbox), TRUE);
410 gtk_widget_set_sensitive (fp_dlg->prop1_entry, FALSE);
412 } else {
413 gtk_label_set_text (GTK_LABEL (fp_dlg->prop1_label), _("View"));
414 gtk_label_set_text (GTK_LABEL (GTK_BIN (fp_dlg->prop1_cbox)->child), _("Use default View options"));
415 if (fp_dlg->fm_view) {
416 gtk_entry_set_text (GTK_ENTRY (fp_dlg->prop1_entry), fp_dlg->fm_view);
417 gtk_toggle_button_set_active ( GTK_TOGGLE_BUTTON (fp_dlg->prop1_cbox), FALSE);
418 gtk_widget_set_sensitive (fp_dlg->prop1_entry, TRUE);
419 } else if (fp_dlg->mime_fm_view) {
420 gtk_entry_set_text (GTK_ENTRY (fp_dlg->prop1_entry), fp_dlg->mime_fm_view);
421 gtk_toggle_button_set_active ( GTK_TOGGLE_BUTTON (fp_dlg->prop1_cbox), TRUE);
422 gtk_widget_set_sensitive (fp_dlg->prop1_entry, FALSE);
423 } else {
424 gtk_entry_set_text (GTK_ENTRY (fp_dlg->prop1_entry), "");
425 gtk_toggle_button_set_active ( GTK_TOGGLE_BUTTON (fp_dlg->prop1_cbox), TRUE);
426 gtk_widget_set_sensitive (fp_dlg->prop1_entry, FALSE);
429 if (fp_dlg->executable) {
430 gtk_widget_hide (fp_dlg->prop2_label);
431 gtk_widget_hide (fp_dlg->prop2_entry);
432 gtk_widget_hide (fp_dlg->prop2_cbox);
433 gtk_widget_hide (fp_dlg->prop2_hline);
434 } else {
435 gtk_widget_show (fp_dlg->prop2_label);
436 gtk_widget_show (fp_dlg->prop2_entry);
437 gtk_widget_show (fp_dlg->prop2_cbox);
438 gtk_widget_show (fp_dlg->prop2_hline);
440 fp_dlg->changing = FALSE;
443 static GtkWidget *
444 generate_icon_sel (GnomeFilePropertyDialog *fp_dlg)
446 GtkWidget *retval;
447 gchar *icon;
449 retval = gnome_icon_entry_new ("gmc_file_icon", _("Select an Icon"));
450 icon = g_strdup (gicon_get_filename_for_icon (fp_dlg->im));
452 if (icon == NULL)
453 return retval;
454 gnome_icon_entry_set_icon (GNOME_ICON_ENTRY (retval), icon);
455 fp_dlg->icon_filename = icon;
456 return retval;
459 static GtkWidget *
460 generate_actions_box (GnomeFilePropertyDialog *fp_dlg)
462 GtkWidget *vbox;
463 GtkWidget *table;
465 /* Here's the Logic: */
466 /* All tops of files (other then folders) should let us edit "open" */
467 /* If we are a file, and an executable, we want to edit our "drop-action" */
468 /* Metadata, as it is meaningful to us. */
469 /* If we are non-executable, we want to edit our "edit" and "view" fields. */
470 /* Sym links want to have the same options as above, but use their Target's */
471 /* Executable/set bit in order to determine which one. */
472 /* Note, symlinks can set their own metadata, independent from their */
473 /* targets. */
475 table = gtk_table_new (8, 2, FALSE);
476 gtk_container_set_border_width (GTK_CONTAINER (table), GNOME_PAD_SMALL);
478 /* we do open first */
479 fp_dlg->open_label = gtk_label_new (_("Open"));
480 gtk_misc_set_alignment (GTK_MISC (fp_dlg->open_label), 0.0, 0.5);
481 gtk_misc_set_padding (GTK_MISC (fp_dlg->open_label), 2, 0);
482 gtk_table_attach_defaults (GTK_TABLE (table),
483 fp_dlg->open_label,
484 0, 1, 0, 1);
485 fp_dlg->open_entry = gtk_entry_new ();
486 gtk_table_attach_defaults (GTK_TABLE (table),
487 fp_dlg->open_entry,
488 1, 2, 0, 1);
489 fp_dlg->open_cbox = gtk_check_button_new_with_label (_("Use default Open action"));
490 gtk_signal_connect (GTK_OBJECT (fp_dlg->open_cbox), "toggled", metadata_toggled, fp_dlg);
491 gtk_table_attach_defaults (GTK_TABLE (table), fp_dlg->open_cbox, 0, 2, 1, 2);
494 vbox = gtk_vbox_new (FALSE, 0);
495 gtk_box_pack_start (GTK_BOX (vbox), gtk_hseparator_new (), FALSE, FALSE, GNOME_PAD_SMALL);
496 gtk_table_attach_defaults (GTK_TABLE (table), vbox, 0, 2, 2, 3);
498 if (fp_dlg->executable)
499 fp_dlg->prop1_label = gtk_label_new (_("Drop Action"));
500 else
501 fp_dlg->prop1_label = gtk_label_new (_("View"));
502 gtk_misc_set_alignment (GTK_MISC (fp_dlg->prop1_label), 0.0, 0.5);
503 gtk_misc_set_padding (GTK_MISC (fp_dlg->prop1_label), 2, 0);
504 gtk_table_attach_defaults (GTK_TABLE (table),
505 fp_dlg->prop1_label,
506 0, 1, 3, 4);
507 fp_dlg->prop1_entry = gtk_entry_new ();
508 gtk_table_attach_defaults (GTK_TABLE (table),
509 fp_dlg->prop1_entry,
510 1, 2, 3, 4);
511 if (fp_dlg->executable)
512 fp_dlg->prop1_cbox = gtk_check_button_new_with_label (_("Use default Drop action"));
513 else
514 fp_dlg->prop1_cbox = gtk_check_button_new_with_label (_("Use default View action"));
515 gtk_signal_connect (GTK_OBJECT (fp_dlg->prop1_cbox), "toggled", metadata_toggled, fp_dlg);
516 gtk_table_attach_defaults (GTK_TABLE (table), fp_dlg->prop1_cbox, 0, 2, 4, 5);
518 vbox = gtk_vbox_new (FALSE, 0);
519 fp_dlg->prop2_hline = gtk_hseparator_new ();
520 gtk_box_pack_start (GTK_BOX (vbox), fp_dlg->prop2_hline, FALSE, FALSE, GNOME_PAD_SMALL);
521 gtk_table_attach_defaults (GTK_TABLE (table), vbox, 0, 2, 5, 6);
523 fp_dlg->prop2_label = gtk_label_new (_("Edit"));
524 gtk_misc_set_alignment (GTK_MISC (fp_dlg->prop2_label), 0.0, 0.5);
525 gtk_misc_set_padding (GTK_MISC (fp_dlg->prop2_label), 2, 0);
526 gtk_table_attach_defaults (GTK_TABLE (table),
527 fp_dlg->prop2_label,
528 0, 1, 6, 7);
529 fp_dlg->prop2_entry = gtk_entry_new ();
530 gtk_table_attach_defaults (GTK_TABLE (table),
531 fp_dlg->prop2_entry,
532 1, 2, 6, 7);
533 fp_dlg->prop2_cbox = gtk_check_button_new_with_label (_("Use default Edit action"));
534 gtk_signal_connect (GTK_OBJECT (fp_dlg->prop2_cbox), "toggled", metadata_toggled, fp_dlg);
535 gtk_table_attach_defaults (GTK_TABLE (table), fp_dlg->prop2_cbox, 0, 2, 7, 8);
537 /* we set the open field */
538 fp_dlg->changing = TRUE;
539 if (fp_dlg->fm_open) {
540 gtk_entry_set_text (GTK_ENTRY (fp_dlg->open_entry), fp_dlg->fm_open);
541 gtk_toggle_button_set_active ( GTK_TOGGLE_BUTTON (fp_dlg->open_cbox), FALSE);
542 gtk_widget_set_sensitive (fp_dlg->open_entry, TRUE);
543 } else if (fp_dlg->mime_fm_open) {
544 gtk_entry_set_text (GTK_ENTRY (fp_dlg->open_entry), fp_dlg->mime_fm_open);
545 gtk_toggle_button_set_active ( GTK_TOGGLE_BUTTON (fp_dlg->open_cbox), TRUE);
546 gtk_widget_set_sensitive (fp_dlg->open_entry, FALSE);
547 } else {
548 gtk_entry_set_text (GTK_ENTRY (fp_dlg->open_entry), "");
549 gtk_toggle_button_set_active ( GTK_TOGGLE_BUTTON (fp_dlg->open_cbox), TRUE);
550 gtk_widget_set_sensitive (fp_dlg->open_entry, FALSE);
552 if (fp_dlg->edit) {
553 gtk_toggle_button_set_active ( GTK_TOGGLE_BUTTON (fp_dlg->prop2_cbox), FALSE);
554 gtk_entry_set_text (GTK_ENTRY (fp_dlg->prop2_entry), fp_dlg->edit);
555 gtk_widget_set_sensitive (fp_dlg->prop2_entry, TRUE);
556 } else if (fp_dlg->mime_edit) {
557 gtk_entry_set_text (GTK_ENTRY (fp_dlg->prop2_entry), fp_dlg->mime_edit);
558 gtk_toggle_button_set_active ( GTK_TOGGLE_BUTTON (fp_dlg->prop2_cbox), TRUE);
559 gtk_widget_set_sensitive (fp_dlg->prop2_entry, FALSE);
560 } else {
561 gtk_entry_set_text (GTK_ENTRY (fp_dlg->prop2_entry), "");
562 gtk_toggle_button_set_active ( GTK_TOGGLE_BUTTON (fp_dlg->prop2_cbox), TRUE);
563 gtk_widget_set_sensitive (fp_dlg->prop2_entry, FALSE);
565 fp_dlg->changing = FALSE;
567 return table;
570 static GtkWidget *
571 create_settings_pane (GnomeFilePropertyDialog *fp_dlg)
573 GtkWidget *vbox = NULL;
574 GtkWidget *hbox;
575 GtkWidget *vbox2;
576 GtkWidget *frame;
577 GtkWidget *align;
578 GtkWidget *table;
579 struct stat linkstat;
580 int finish;
582 vbox = gtk_vbox_new (FALSE, GNOME_PAD_SMALL);
583 gtk_container_set_border_width (GTK_CONTAINER (vbox), GNOME_PAD);
585 if (fp_dlg->can_set_icon) {
587 frame = gtk_frame_new (_("Icon"));
588 vbox2 = gtk_vbox_new (FALSE, 0);
589 hbox = gtk_hbox_new (FALSE, 0);
590 align = gtk_alignment_new (0.5, 0.5, 1.0, 1.0);
591 gtk_box_pack_start (GTK_BOX (vbox), frame, TRUE, TRUE, 0);
592 fp_dlg->button = generate_icon_sel (fp_dlg);
593 gtk_container_add (GTK_CONTAINER (frame), vbox2);
594 gtk_container_set_border_width (GTK_CONTAINER (vbox2), GNOME_PAD_SMALL);
595 gtk_box_pack_start (GTK_BOX (vbox2), hbox, TRUE, FALSE, 0);
596 gtk_box_pack_start (GTK_BOX (hbox), align, TRUE, FALSE, 0);
597 gtk_container_add (GTK_CONTAINER (align), fp_dlg->button);
599 /* Are we a directory or device? If so, we do nothing else. */
600 if (S_ISLNK (fp_dlg->st.st_mode))
601 mc_stat (fp_dlg->file_name, &linkstat);
603 finish = 0;
604 if (!S_ISREG (fp_dlg->st.st_mode)){
605 if (S_ISLNK (fp_dlg->st.st_mode)){
606 if (!S_ISREG (linkstat.st_mode))
607 finish = 1;
608 } else
609 finish = 1;
612 if (finish){
613 if (!fp_dlg->can_set_icon) {
614 gtk_widget_unref (vbox);
615 vbox = NULL;
617 return vbox;
620 /* We must be a file or a link to a file. */
621 frame = gtk_frame_new (_("File Actions"));
622 gtk_box_pack_start (GTK_BOX (vbox), frame, TRUE, TRUE, 0);
623 table = generate_actions_box (fp_dlg);
624 gtk_container_add (GTK_CONTAINER (frame), table);
626 frame = gtk_frame_new (_("Open action"));
627 fp_dlg->needs_terminal_check = gtk_check_button_new_with_label (_("Needs terminal to run"));
628 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fp_dlg->needs_terminal_check),
629 fp_dlg->needs_terminal);
630 gtk_container_add (GTK_CONTAINER (frame), fp_dlg->needs_terminal_check);
632 gtk_box_pack_start (GTK_BOX (vbox), frame, TRUE, TRUE, 0);
633 return vbox;
636 /* Permissions Pane */
638 static GtkWidget *
639 align_label_new (char *text, double xalign, double yalign)
641 GtkWidget *label;
643 label = gtk_label_new (text);
644 gtk_misc_set_alignment (GTK_MISC (label), xalign, yalign);
645 gtk_widget_show (label);
647 return label;
650 static mode_t
651 perm_get_umode (GnomeFilePropertyDialog *fp_dlg)
653 mode_t umode;
655 #define SETBIT(widget, flag) umode |= GTK_TOGGLE_BUTTON (widget)->active ? flag : 0
657 umode = 0;
659 SETBIT (fp_dlg->suid, S_ISUID);
660 SETBIT (fp_dlg->sgid, S_ISGID);
661 SETBIT (fp_dlg->svtx, S_ISVTX);
663 SETBIT (fp_dlg->rusr, S_IRUSR);
664 SETBIT (fp_dlg->wusr, S_IWUSR);
665 SETBIT (fp_dlg->xusr, S_IXUSR);
667 SETBIT (fp_dlg->rgrp, S_IRGRP);
668 SETBIT (fp_dlg->wgrp, S_IWGRP);
669 SETBIT (fp_dlg->xgrp, S_IXGRP);
671 SETBIT (fp_dlg->roth, S_IROTH);
672 SETBIT (fp_dlg->woth, S_IWOTH);
673 SETBIT (fp_dlg->xoth, S_IXOTH);
675 return umode;
677 #undef SETBIT
680 static void
681 perm_set_mode_label (GtkWidget *widget, gpointer data)
683 GnomeFilePropertyDialog *fp_dlg;
684 mode_t umode;
685 char s_mode[5];
687 fp_dlg = GNOME_FILE_PROPERTY_DIALOG (data);
688 umode = perm_get_umode (fp_dlg);
689 if (!fp_dlg->executable && (umode & (S_IXUSR | S_IXGRP | S_IXOTH))) {
690 fp_dlg->executable = TRUE;
691 switch_metadata_box (fp_dlg);
692 } else if (fp_dlg->executable && !(umode & (S_IXUSR | S_IXGRP | S_IXOTH))) {
693 fp_dlg->executable = FALSE;
694 switch_metadata_box (fp_dlg);
697 s_mode[0] = '0' + ((umode & (S_ISUID | S_ISGID | S_ISVTX)) >> 9);
698 s_mode[1] = '0' + ((umode & (S_IRUSR | S_IWUSR | S_IXUSR)) >> 6);
699 s_mode[2] = '0' + ((umode & (S_IRGRP | S_IWGRP | S_IXGRP)) >> 3);
700 s_mode[3] = '0' + ((umode & (S_IROTH | S_IWOTH | S_IXOTH)) >> 0);
701 s_mode[4] = 0;
702 gtk_label_set_text (GTK_LABEL (fp_dlg->mode_label), s_mode);
705 static GtkWidget *
706 perm_check_new (char *text, int state, GnomeFilePropertyDialog *fp_dlg)
708 GtkWidget *check;
710 if (text)
711 check = gtk_check_button_new_with_label (text);
712 else
713 check = gtk_check_button_new ();
715 gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (check), FALSE);
716 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check), state ? TRUE : FALSE);
718 gtk_signal_connect (GTK_OBJECT (check), "toggled",
719 (GtkSignalFunc) perm_set_mode_label,
720 fp_dlg);
722 gtk_widget_show (check);
723 return check;
726 #define ATTACH(table, widget, left, right, top, bottom) \
727 gtk_table_attach (GTK_TABLE (table), widget, \
728 left, right, top, bottom, \
729 GTK_FILL | GTK_SHRINK, \
730 GTK_FILL | GTK_SHRINK, \
731 0, 0);
733 #define PERMSET(name, r, w, x, rmask, wmask, xmask, y) do { \
734 r = perm_check_new (NULL, fp_dlg->st.st_mode & rmask, fp_dlg); \
735 w = perm_check_new (NULL, fp_dlg->st.st_mode & wmask, fp_dlg); \
736 x = perm_check_new (NULL, fp_dlg->st.st_mode & xmask, fp_dlg); \
738 ATTACH (table, align_label_new (name, 0.0, 0.5), 0, 1, y, y + 1); \
739 ATTACH (table, r, 1, 2, y, y + 1); \
740 ATTACH (table, w, 2, 3, y, y + 1); \
741 ATTACH (table, x, 3, 4, y, y + 1); \
742 } while (0);
744 static GtkWidget *
745 perm_mode_new (GnomeFilePropertyDialog *fp_dlg)
747 GtkWidget *frame;
748 GtkWidget *vbox;
749 GtkWidget *hbox;
750 GtkWidget *table;
751 gchar *mode;
753 frame = gtk_frame_new (_("File Permissions"));
755 vbox = gtk_vbox_new (FALSE, GNOME_PAD_SMALL);
756 gtk_container_set_border_width (GTK_CONTAINER (vbox), 6);
757 gtk_container_add (GTK_CONTAINER (frame), vbox);
758 gtk_widget_show (vbox);
760 hbox = gtk_hbox_new (FALSE, 0);
761 gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
762 gtk_widget_show (hbox);
764 gtk_box_pack_start (GTK_BOX (hbox), align_label_new (_("Current mode: "), 0.0, 0.5),
765 FALSE, FALSE, 0);
767 fp_dlg->mode_label = align_label_new ("0000", 0.0, 0.5);
768 gtk_box_pack_start (GTK_BOX (hbox), fp_dlg->mode_label, FALSE, FALSE, 0);
770 table = gtk_table_new (4, 5, FALSE);
771 if (!fp_dlg->modifyable || S_ISLNK (fp_dlg->st.st_mode))
772 gtk_widget_set_sensitive (table, FALSE);
773 gtk_table_set_col_spacings (GTK_TABLE (table), 4);
774 gtk_table_set_row_spacings (GTK_TABLE (table), 6);
775 gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, FALSE, 0);
776 gtk_widget_show (table);
778 /* Headings */
780 ATTACH (table, align_label_new (_("Read"), 0.0, 0.5), 1, 2, 0, 1);
781 ATTACH (table, align_label_new (_("Write"), 0.0, 0.5), 2, 3, 0, 1);
782 ATTACH (table, align_label_new (_("Exec"), 0.0, 0.5), 3, 4, 0, 1);
783 ATTACH (table, align_label_new (_("Special"), 0.0, 0.5), 4, 5, 0, 1);
785 /* Permissions */
787 PERMSET (_("User"), fp_dlg->rusr, fp_dlg->wusr, fp_dlg->xusr, S_IRUSR, S_IWUSR, S_IXUSR, 1);
788 PERMSET (_("Group"), fp_dlg->rgrp, fp_dlg->wgrp, fp_dlg->xgrp, S_IRGRP, S_IWGRP, S_IXGRP, 2);
789 PERMSET (_("Other"), fp_dlg->roth, fp_dlg->woth, fp_dlg->xoth, S_IROTH, S_IWOTH, S_IXOTH, 3);
791 /* Special */
793 fp_dlg->suid = perm_check_new (_("Set UID"), fp_dlg->st.st_mode & S_ISUID, fp_dlg);
794 fp_dlg->sgid = perm_check_new (_("Set GID"), fp_dlg->st.st_mode & S_ISGID, fp_dlg);
795 fp_dlg->svtx = perm_check_new (_("Sticky"), fp_dlg->st.st_mode & S_ISVTX, fp_dlg);
797 ATTACH (table, fp_dlg->suid, 4, 5, 1, 2);
798 ATTACH (table, fp_dlg->sgid, 4, 5, 2, 3);
799 ATTACH (table, fp_dlg->svtx, 4, 5, 3, 4);
801 perm_set_mode_label (NULL, fp_dlg);
802 gtk_label_get (GTK_LABEL (fp_dlg->mode_label), &mode);
803 fp_dlg->mode_name = g_strdup (mode);
804 return frame;
807 #undef ATTACH
808 #undef PERMSET
810 static GtkWidget *
811 perm_owner_new (GnomeFilePropertyDialog *fp_dlg)
813 GtkWidget *gentry;
814 struct passwd *passwd;
816 gentry = gtk_entry_new ();
818 if (fp_dlg->euid != 0)
819 gtk_widget_set_sensitive (gentry, FALSE);
820 passwd = getpwuid (fp_dlg->st.st_uid);
821 if (passwd) {
822 fp_dlg->user_name = passwd->pw_name;
823 gtk_entry_set_text (GTK_ENTRY (gentry), passwd->pw_name);
824 } else {
825 char buf[100];
827 g_snprintf (buf, sizeof (buf), "%d", (int) fp_dlg->st.st_uid);
828 gtk_entry_set_text (GTK_ENTRY (gentry), buf);
831 return gentry;
834 static GtkWidget *
835 perm_group_new (GnomeFilePropertyDialog *fp_dlg)
837 GtkWidget *gentry;
838 struct group *grp;
839 gboolean grp_flag = FALSE;
840 gchar *grpname = NULL;
841 GList *templist;
842 GList *list = NULL;
844 /* Are we root? Do we own the file? */
845 /* In this case we can change it. */
846 /* A little bit of this was swiped from kfm. */
848 if ((fp_dlg->euid == 0) || (fp_dlg->st.st_uid == fp_dlg->euid)) {
849 gentry = gtk_combo_new ();
850 grp = getgrgid (fp_dlg->st.st_gid);
851 if (grp){
852 if (grp->gr_name)
853 fp_dlg->group_name = g_strdup (grp->gr_name);
854 else {
855 fp_dlg->group_name = g_strdup_printf ("%d", (int) grp->gr_gid);
857 } else {
858 fp_dlg->group_name = g_strdup_printf ("%d", (int) fp_dlg->st.st_gid);
861 /* we change this, b/c we are able to set the egid, if we aren't in the group already */
862 grp = getgrgid (getegid());
863 if (grp) {
864 if (grp->gr_name)
865 grpname = g_strdup (grp->gr_name);
866 else
867 grpname = g_strdup_printf ("%d", (int) grp->gr_gid);
868 } else
869 grpname = g_strdup_printf ("%d", (int) fp_dlg->st.st_gid);
871 if (fp_dlg->euid != 0)
872 gtk_editable_set_editable (GTK_EDITABLE (GTK_COMBO (gentry)->entry), FALSE);
873 for (setgrent (); (grp = getgrent ()) != NULL;) {
874 if (!grp_flag && grpname && !strcmp (grp->gr_name, grpname)) {
875 list = g_list_insert_sorted (list, g_strdup (grp->gr_name), (GCompareFunc)strcmp);
876 grp_flag = TRUE;
877 continue;
879 if (fp_dlg->euid == 0) {
880 list = g_list_insert_sorted (list, g_strdup (grp->gr_name), (GCompareFunc)strcmp);
881 } else {
882 gchar **members = grp->gr_mem;
883 gchar *member;
884 while ((member = *members) != 0L) {
885 if (!strcmp (member, fp_dlg->user_name)) {
886 list = g_list_insert_sorted (list, g_strdup (grp->gr_name), (GCompareFunc)strcmp);
887 break;
889 ++members;
893 endgrent ();
895 /* we also might want to add the egid to the list. */
896 if (!grp_flag)
897 list = g_list_insert_sorted (list, g_strdup (grpname), (GCompareFunc)strcmp);
899 /* Now we have a list. We should make our option menu. */
900 gtk_combo_set_popdown_strings (GTK_COMBO (gentry), list);
901 for (templist = list; templist; templist = templist->next) {
902 g_free (templist->data);
904 gtk_entry_set_text (GTK_ENTRY (GTK_COMBO (gentry)->entry), fp_dlg->group_name);
905 g_list_free (list);
906 } else {
907 /* we're neither so we just put an entry down */
908 gentry = gtk_entry_new ();
909 gtk_widget_set_sensitive (gentry, FALSE);
911 grp = getgrgid (fp_dlg->st.st_gid);
912 if (grp)
913 gtk_entry_set_text (GTK_ENTRY (gentry), grp->gr_name);
914 else {
915 char buf[100];
917 g_snprintf (buf, sizeof (buf), _("<Unknown> (%d)"), fp_dlg->st.st_gid);
918 gtk_entry_set_text (GTK_ENTRY (gentry), buf);
921 g_free (grpname);
922 return gentry;
925 static GtkWidget *
926 perm_ownership_new (GnomeFilePropertyDialog *fp_dlg)
928 GtkWidget *frame;
929 GtkWidget *table;
931 frame = gtk_frame_new (_("File ownership"));
933 table = gtk_table_new (2, 2, FALSE);
934 gtk_container_set_border_width (GTK_CONTAINER (table), 6);
935 gtk_table_set_col_spacings (GTK_TABLE (table), 6);
936 gtk_table_set_row_spacings (GTK_TABLE (table), 4);
937 gtk_container_add (GTK_CONTAINER (frame), table);
938 gtk_widget_show (table);
940 /* Owner */
942 gtk_table_attach (GTK_TABLE (table), align_label_new (_("Owner"), 0.0, 0.5),
943 0, 1, 0, 1,
944 GTK_FILL | GTK_SHRINK, GTK_FILL | GTK_SHRINK,
945 0, 0);
947 fp_dlg->owner_entry = perm_owner_new (fp_dlg);
948 gtk_table_attach (GTK_TABLE (table), fp_dlg->owner_entry,
949 1, 2, 0, 1,
950 GTK_EXPAND | GTK_FILL | GTK_SHRINK,
951 GTK_FILL | GTK_SHRINK,
952 0, 0);
953 gtk_widget_show (fp_dlg->owner_entry);
955 /* Group */
957 gtk_table_attach (GTK_TABLE (table), align_label_new (_("Group"), 0.0, 0.5),
958 0, 1, 1, 2,
959 GTK_FILL | GTK_SHRINK, GTK_FILL | GTK_SHRINK,
960 0, 0);
962 fp_dlg->group_entry = perm_group_new (fp_dlg);
963 gtk_table_attach (GTK_TABLE (table), fp_dlg->group_entry,
964 1, 2, 1, 2,
965 GTK_EXPAND | GTK_FILL | GTK_SHRINK,
966 GTK_FILL | GTK_SHRINK,
967 0, 0);
968 gtk_widget_show (fp_dlg->group_entry);
969 return frame;
972 static GtkWidget *
973 create_perm_properties (GnomeFilePropertyDialog *fp_dlg)
975 GtkWidget *vbox;
977 vbox = gtk_vbox_new (FALSE, GNOME_PAD_SMALL);
978 gtk_container_set_border_width (GTK_CONTAINER (vbox), GNOME_PAD);
979 gtk_box_pack_start (GTK_BOX (vbox), perm_mode_new (fp_dlg), FALSE, FALSE, 0);
980 gtk_box_pack_start (GTK_BOX (vbox), perm_ownership_new (fp_dlg), TRUE, TRUE, 0);
981 return vbox;
984 /* finally the new dialog */
985 static void
986 init_metadata (GnomeFilePropertyDialog *fp_dlg)
988 gint size;
989 char *mime_type, *str;
990 gchar link_name[MC_MAXPATHLEN];
991 gint n;
992 gchar *file_name, *desktop_url;
994 if (gnome_metadata_get (fp_dlg->file_name, "fm-open", &size, &fp_dlg->fm_open) != 0)
995 gnome_metadata_get (fp_dlg->file_name, "open", &size, &fp_dlg->fm_open);
996 if (gnome_metadata_get (fp_dlg->file_name, "fm-view", &size, &fp_dlg->fm_view) != 0)
997 gnome_metadata_get (fp_dlg->file_name, "view", &size, &fp_dlg->fm_view);
998 gnome_metadata_get (fp_dlg->file_name, "edit", &size, &fp_dlg->edit);
999 gnome_metadata_get (fp_dlg->file_name, "drop-action", &size, &fp_dlg->drop_target);
1002 * Fetch the needs-terminal setting
1004 if (gnome_metadata_get (fp_dlg->file_name, "flags", &size, &str) == 0){
1005 fp_dlg->needs_terminal = strstr (str, "needsterminal") != 0;
1006 g_free (str);
1007 } else
1008 fp_dlg->needs_terminal = 0;
1010 /* Mime stuff */
1011 file_name = fp_dlg->file_name;
1012 if (S_ISLNK (fp_dlg->st.st_mode)) {
1013 n = mc_readlink (fp_dlg->file_name, link_name, MC_MAXPATHLEN);
1014 if (n > 0){
1015 link_name [n] = 0;
1016 file_name = link_name;
1020 if (gnome_metadata_get (fp_dlg->file_name, "desktop-url", &size, &desktop_url) == 0)
1021 fp_dlg->desktop_url = desktop_url;
1022 else
1023 fp_dlg->desktop_url = NULL;
1025 if (gnome_metadata_get (fp_dlg->file_name, "icon-caption", &size, &fp_dlg->caption))
1026 fp_dlg->caption = g_strdup (desktop_url);
1029 * Mime type.
1031 if (use_magic)
1033 mime_type = (char *) gnome_mime_type_or_default_of_file (file_name, NULL);
1035 else
1036 mime_type = (char *) gnome_mime_type_or_default (file_name, NULL);
1038 if (!mime_type)
1039 return;
1040 fp_dlg->mime_fm_open = gnome_mime_get_value (mime_type, "fm-open");
1041 if (!fp_dlg->mime_fm_open)
1042 fp_dlg->mime_fm_open = gnome_mime_get_value (mime_type, "open");
1043 fp_dlg->mime_fm_view = gnome_mime_get_value (mime_type, "fm-view");
1044 if (!fp_dlg->mime_fm_view)
1045 fp_dlg->mime_fm_view = gnome_mime_get_value (mime_type, "view");
1046 fp_dlg->mime_edit = gnome_mime_get_value (mime_type, "edit");
1047 fp_dlg->mime_drop_target = gnome_mime_get_value (mime_type, "drop-action");
1050 GtkWidget *
1051 gnome_file_property_dialog_new (gchar *file_name, gboolean can_set_icon)
1053 GnomeFilePropertyDialog *fp_dlg;
1054 GtkWidget *notebook;
1055 GtkWidget *new_page;
1056 gchar *title_string;
1057 mode_t mode;
1059 g_return_val_if_fail (file_name != NULL, NULL);
1060 fp_dlg = gtk_type_new (gnome_file_property_dialog_get_type ());
1062 /* We set non-gui specific things first */
1063 if (mc_lstat (file_name, &fp_dlg->st) == -1) {
1064 /* Bad things man, bad things */
1065 gtk_object_unref (GTK_OBJECT (fp_dlg));
1066 return NULL;
1069 mode = fp_dlg->st.st_mode;
1070 if (S_ISLNK (mode)){
1071 struct stat s;
1073 if (mc_stat (file_name, &s) != -1)
1074 mode = s.st_mode;
1077 if (fp_dlg->st.st_mode & (S_IXUSR | S_IXGRP |S_IXOTH)) {
1078 fp_dlg->executable = TRUE;
1079 } else {
1080 fp_dlg->executable = FALSE;
1083 fp_dlg->file_name = g_strdup (file_name);
1084 fp_dlg->euid = geteuid ();
1085 fp_dlg->can_set_icon = can_set_icon;
1086 if (S_ISCHR (fp_dlg->st.st_mode) || S_ISBLK (fp_dlg->st.st_mode)
1087 || ((fp_dlg->euid != fp_dlg->st.st_uid) && (fp_dlg->euid != 0)))
1088 fp_dlg->modifyable = FALSE;
1089 init_metadata (fp_dlg);
1091 /* and now, we set up the gui. */
1092 notebook = gtk_notebook_new ();
1094 if (fp_dlg->desktop_url)
1095 gtk_notebook_append_page (GTK_NOTEBOOK (notebook),
1096 create_url_properties (fp_dlg),
1097 gtk_label_new (_("URL")));
1098 gtk_notebook_append_page (GTK_NOTEBOOK (notebook),
1099 create_general_properties (fp_dlg),
1100 gtk_label_new (_("Statistics")));
1102 new_page = create_settings_pane (fp_dlg);
1103 if (new_page)
1104 gtk_notebook_append_page (GTK_NOTEBOOK (notebook),
1105 new_page,
1106 gtk_label_new (_("Options")));
1107 gtk_notebook_append_page (GTK_NOTEBOOK (notebook),
1108 create_perm_properties (fp_dlg),
1109 gtk_label_new (_("Permissions")));
1110 gtk_box_pack_start (GTK_BOX (GNOME_DIALOG (fp_dlg)->vbox),
1111 notebook, TRUE, TRUE, 0);
1112 title_string = g_strconcat (strrchr (file_name, '/') + 1, _(" Properties"), NULL);
1113 gtk_window_set_title (GTK_WINDOW (fp_dlg), title_string);
1114 g_free (title_string);
1116 gnome_dialog_append_button ( GNOME_DIALOG(fp_dlg),
1117 GNOME_STOCK_BUTTON_OK);
1118 gnome_dialog_append_button ( GNOME_DIALOG(fp_dlg),
1119 GNOME_STOCK_BUTTON_CANCEL);
1120 gtk_widget_show_all (GNOME_DIALOG (fp_dlg)->vbox);
1122 /* It's okay to do this now... */
1123 /* and set the rest of the fields */
1124 switch_metadata_box (fp_dlg);
1126 return GTK_WIDGET (fp_dlg);
1129 static gint
1130 apply_mode_change (GnomeFilePropertyDialog *fpd)
1132 gchar *new_mode;
1133 gtk_label_get (GTK_LABEL (fpd->mode_label), &new_mode);
1134 if (strcmp (new_mode, fpd->mode_name)) {
1135 mc_chmod (fpd->file_name, (mode_t) strtol(new_mode, (char **)NULL, 8));
1136 return 1;
1138 return 0;
1141 static gint
1142 apply_uid_group_change (GnomeFilePropertyDialog *fpd)
1144 uid_t uid;
1145 gid_t gid;
1146 struct passwd *p;
1147 struct group *g;
1148 gchar *new_user_name = NULL;
1149 gchar *new_group_name = NULL;
1151 uid = fpd->st.st_uid;
1152 gid = fpd->st.st_gid;
1154 /* we only check if our euid == 0 */
1155 if (fpd->euid == 0) {
1156 new_user_name = gtk_entry_get_text (GTK_ENTRY (fpd->owner_entry));
1158 if (fpd->user_name && new_user_name && strcmp (fpd->user_name, new_user_name)) {
1159 /* now we need to get the new uid */
1160 p = getpwnam (new_user_name);
1161 if (!p) {
1162 uid = atoi (new_user_name);
1163 if (uid == 0) {
1164 message (1, "Error", _("You entered an invalid username"));
1165 uid = fpd->st.st_uid;
1167 } else
1168 uid = p->pw_uid;
1169 } else {
1170 if (new_user_name){
1171 p = getpwnam (new_user_name);
1172 if (!p) {
1173 uid = atoi (new_user_name);
1174 if (uid == 0) {
1175 message (1, "Error", _("You entered an invalid username"));
1176 uid = fpd->st.st_uid;
1178 } else
1179 uid = p->pw_uid;
1184 /* now we check the group */
1185 /* We are only a combo if we are sensitive, and we only want to check if we are
1186 * sensitive. */
1187 if (GTK_WIDGET_IS_SENSITIVE (fpd->group_entry))
1188 new_group_name = gtk_entry_get_text (GTK_ENTRY (GTK_COMBO (fpd->group_entry)->entry));
1190 if (fpd->group_name && new_group_name && strcmp (fpd->group_name, new_group_name)) {
1191 g = getgrnam (new_group_name);
1192 if (!g) {
1193 gid = atoi (new_group_name);
1194 if (gid == 0) {
1195 message (1, "Error", "You entered an invalid group name");
1196 gid = fpd->st.st_gid;
1198 } else
1199 gid = g->gr_gid;
1201 if ((uid != fpd->st.st_uid) || (gid != fpd->st.st_gid)) {
1202 mc_chown (fpd->file_name, uid, gid);
1203 return 1;
1205 return 0;
1208 static gint
1209 apply_name_change (GnomeFilePropertyDialog *fpd)
1211 char *new_name;
1212 char *base_name;
1213 char *full_target;
1214 FileOpContext *ctx;
1215 long count = 0;
1216 double bytes = 0;
1218 new_name = gtk_entry_get_text (GTK_ENTRY (fpd->file_entry));
1219 if (!*new_name) {
1220 message (1, "Error", _("You must rename your file to something"));
1221 return 0;
1223 /* has it changed? */
1224 if (strcmp (strrchr(fpd->file_name, '/') + 1, new_name)) {
1225 if (strchr (new_name, '/')) {
1226 message (1, "Error", _("You cannot rename a file to something containing a '/' character"));
1227 return 0;
1228 } else {
1229 char *p;
1230 int s;
1232 /* create the files. */
1233 base_name = g_strdup (fpd->file_name);
1235 p = strrchr (base_name, '/');
1237 if (p)
1238 *p = '\0';
1240 full_target = concat_dir_and_file (base_name, new_name);
1242 ctx = file_op_context_new ();
1243 file_op_context_create_ui (ctx, OP_MOVE, FALSE);
1244 s = move_file_file (ctx, fpd->file_name, full_target, &count, &bytes);
1245 file_op_context_destroy (ctx);
1247 if (s == FILE_CONT){
1248 g_free (fpd->file_name);
1249 fpd->file_name = full_target;
1250 } else
1251 g_free (full_target);
1254 return 1;
1257 static gint
1258 apply_metadata_change (GnomeFilePropertyDialog *fpd)
1260 gchar *text;
1262 /* If we don't have an open_cbox, that means we have no metadata
1263 * to set.
1265 if (fpd->open_cbox != NULL) {
1266 if (!GTK_TOGGLE_BUTTON (fpd->open_cbox)->active) {
1267 text = gtk_entry_get_text (GTK_ENTRY (fpd->open_entry));
1268 if (text && text[0])
1269 gnome_metadata_set (fpd->file_name,
1270 "fm-open",
1271 strlen (text) + 1,
1272 text);
1273 else
1274 gnome_metadata_remove (fpd->file_name,
1275 "fm-open");
1276 } else {
1277 if (fpd->fm_open)
1278 gnome_metadata_remove (fpd->file_name,
1279 "fm-open");
1281 if (fpd->executable) {
1282 if (!GTK_TOGGLE_BUTTON (fpd->prop1_cbox)->active) {
1283 text = gtk_entry_get_text (GTK_ENTRY (fpd->prop1_entry));
1284 if (text && text[0])
1285 gnome_metadata_set (fpd->file_name,
1286 "drop-action",
1287 strlen (text) + 1,
1288 text);
1289 else
1290 gnome_metadata_remove (fpd->file_name,
1291 "drop-action");
1292 } else {
1293 if (fpd->drop_target)
1294 gnome_metadata_remove (fpd->file_name,
1295 "drop-action");
1297 } else {
1298 if (!GTK_TOGGLE_BUTTON (fpd->prop1_cbox)->active) {
1299 text = gtk_entry_get_text (GTK_ENTRY (fpd->prop1_entry));
1300 if (text && text[0])
1301 gnome_metadata_set (fpd->file_name,
1302 "fm-view",
1303 strlen (text) + 1,
1304 text);
1305 else
1306 gnome_metadata_remove (fpd->file_name,
1307 "fm-view");
1308 } else {
1309 if (fpd->fm_view)
1310 gnome_metadata_remove (fpd->file_name,
1311 "fm-view");
1313 if (!GTK_TOGGLE_BUTTON (fpd->prop2_cbox)->active) {
1314 text = gtk_entry_get_text (GTK_ENTRY (fpd->prop2_entry));
1315 if (text && text[0])
1316 gnome_metadata_set (fpd->file_name,
1317 "edit",
1318 strlen (text) + 1,
1319 text);
1320 else
1321 gnome_metadata_remove (fpd->file_name,
1322 "edit");
1323 } else {
1324 if (fpd->edit)
1325 gnome_metadata_remove (fpd->file_name,
1326 "edit");
1331 if (fpd->desktop_url){
1332 char *new_desktop_url = gtk_entry_get_text (GTK_ENTRY (fpd->desktop_entry));
1333 char *new_caption = gtk_entry_get_text (GTK_ENTRY (fpd->caption_entry));
1335 gnome_metadata_set (fpd->file_name, "desktop-url",
1336 strlen (new_desktop_url)+1, new_desktop_url);
1337 gnome_metadata_set (fpd->file_name, "icon-caption",
1338 strlen (new_caption)+1, new_caption);
1342 * "Needs terminal" check button
1344 * This piece of code is more complex than it should, as the "flags"
1345 * metadata value is actually a list of comma separated flags. So
1346 * we need to edit this list when removing the "needsterminal" flag.
1348 if (fpd->needs_terminal_check)
1350 int toggled = 0 != GTK_TOGGLE_BUTTON (fpd->needs_terminal_check)->active;
1351 int size;
1352 char *buf;
1354 if (gnome_metadata_get (fpd->file_name, "flags", &size, &buf) == 0){
1355 char *p;
1357 p = strstr (buf, "needsterminal");
1358 if (toggled){
1359 if (!p){
1360 p = g_strconcat (buf, ",needsterminal", NULL);
1361 gnome_metadata_set (fpd->file_name, "flags", strlen (p)+1, p);
1362 g_free (p);
1364 } else {
1365 if (p){
1366 char *p1, *p2;
1368 if (p != buf){
1369 p1 = g_malloc (p - buf + 1);
1370 strncpy (p1, buf, p - buf);
1371 p1 [p - buf ] = 0;
1372 } else
1373 p1 = g_strdup ("");
1375 p += strlen ("needsterminal");
1377 p2 = g_strconcat (p1, p, NULL);
1378 if (strcmp (p2, ",") == 0)
1379 gnome_metadata_remove (fpd->file_name, "flags");
1380 else
1381 gnome_metadata_set (fpd->file_name, "flags",
1382 strlen (p2)+1, p2);
1383 g_free (p2);
1384 g_free (p1);
1388 } else {
1389 if (toggled){
1390 gnome_metadata_set (fpd->file_name, "flags",
1391 sizeof ("needsterminal"), "needsterminal");
1396 if (!fpd->can_set_icon)
1397 return 1;
1398 /* And finally, we set the metadata on the icon filename */
1399 text = gnome_icon_entry_get_filename (GNOME_ICON_ENTRY (fpd->button));
1400 /*gtk_entry_get_text (GTK_ENTRY (gnome_icon_entry_gtk_entry (GNOME_ICON_ENTRY (fpd->button))));*/
1402 if (text) {
1403 if (fpd->icon_filename == NULL || strcmp (fpd->icon_filename, text) != 0)
1404 gnome_metadata_set (fpd->file_name, "icon-filename", strlen (text) + 1, text);
1405 g_free (text);
1407 /* I suppose we should only do this if we know there's been a change -- I'll try to figure it
1408 * out later if it turns out to be important. */
1409 return 1;
1412 /* This function will apply what changes it can do. It is meant to be used in conjunction
1413 * with a gnome_dialog_run_and_hide. Please note that doing a gnome_dialog_run
1414 * will (obviously) cause greivious bogoness. */
1416 gint
1417 gnome_file_property_dialog_make_changes (GnomeFilePropertyDialog *file_property_dialog)
1419 gint retval = 0;
1421 g_return_val_if_fail (file_property_dialog != NULL, 1);
1422 g_return_val_if_fail (GNOME_IS_FILE_PROPERTY_DIALOG (file_property_dialog), 1);
1424 retval += apply_mode_change (file_property_dialog);
1425 retval += apply_uid_group_change (file_property_dialog);
1426 retval += apply_name_change (file_property_dialog);
1427 retval += apply_metadata_change (file_property_dialog);
1429 return retval;