Bug Summary

File:src/file-manager/fm-properties-window.c
Warning:line 4524, column 2
Value stored to 'w' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name fm-properties-window.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/rootdir/src/file-manager -fcoverage-compilation-dir=/rootdir/src/file-manager -resource-dir /usr/lib/llvm-19/lib/clang/19 -D HAVE_CONFIG_H -I . -I ../.. -I ../.. -I /usr/include/glib-2.0 -I /usr/lib/x86_64-linux-gnu/glib-2.0/include -I /usr/include/sysprof-6 -I /usr/include/cafe-desktop-2.0 -I /usr/include/ctk-3.0 -I /usr/include/pango-1.0 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/x86_64-linux-gnu -I /usr/include/webp -I /usr/include/gio-unix-2.0 -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/at-spi-2.0 -I /usr/include/dbus-1.0 -I /usr/lib/x86_64-linux-gnu/dbus-1.0/include -I /usr/include/startup-notification-1.0 -I /usr/include/dconf -I /usr/include/cail-3.0 -I /usr/include/libxml2 -D BAUL_DATADIR="/usr/share/baul" -D DATADIR="/usr/share" -D G_DISABLE_DEPRECATED -D GDK_PIXBUF_DISABLE_DEPRECATED -D PIC -internal-isystem /usr/lib/llvm-19/lib/clang/19/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -ferror-limit 19 -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2025-01-24-094037-27604-1 -x c fm-properties-window.c
1/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
2
3/* fm-properties-window.c - window that lets user modify file properties
4
5 Copyright (C) 2000 Eazel, Inc.
6
7 The Cafe Library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Library General Public License as
9 published by the Free Software Foundation; either version 2 of the
10 License, or (at your option) any later version.
11
12 The Cafe Library is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Library General Public License for more details.
16
17 You should have received a copy of the GNU Library General Public
18 License along with the Cafe Library; see the file COPYING.LIB. If not,
19 write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
20 Boston, MA 02110-1301, USA.
21
22 Authors: Darin Adler <darin@bentspoon.com>
23*/
24
25#include <config.h>
26#include <string.h>
27#include <cairo.h>
28
29#include <ctk/ctk.h>
30#include <cdk/cdkkeysyms.h>
31#include <glib/gi18n.h>
32#include <sys/stat.h>
33
34#include <eel/eel-accessibility.h>
35#include <eel/eel-gdk-pixbuf-extensions.h>
36#include <eel/eel-glib-extensions.h>
37#include <eel/eel-cafe-extensions.h>
38#include <eel/eel-ctk-extensions.h>
39#include <eel/eel-labeled-image.h>
40#include <eel/eel-stock-dialogs.h>
41#include <eel/eel-vfs-extensions.h>
42#include <eel/eel-wrap-table.h>
43
44#include <libbaul-extension/baul-property-page-provider.h>
45
46#include <libbaul-private/baul-mime-application-chooser.h>
47#include <libbaul-private/baul-entry.h>
48#include <libbaul-private/baul-extensions.h>
49#include <libbaul-private/baul-file-attributes.h>
50#include <libbaul-private/baul-file-operations.h>
51#include <libbaul-private/baul-desktop-icon-file.h>
52#include <libbaul-private/baul-global-preferences.h>
53#include <libbaul-private/baul-emblem-utils.h>
54#include <libbaul-private/baul-link.h>
55#include <libbaul-private/baul-metadata.h>
56#include <libbaul-private/baul-module.h>
57#include <libbaul-private/baul-mime-actions.h>
58
59#include "fm-properties-window.h"
60#include "fm-ditem-page.h"
61#include "fm-error-reporting.h"
62
63#if HAVE_SYS_VFS_H1
64#include <sys/vfs.h>
65#elif HAVE_SYS_MOUNT_H1
66#if HAVE_SYS_PARAM_H1
67#include <sys/param.h>
68#endif
69#include <sys/mount.h>
70#endif
71
72#define USED_FILL_R0.988235294 0.988235294
73#define USED_FILL_G0.91372549 0.91372549
74#define USED_FILL_B0.309803922 0.309803922
75
76#define FREE_FILL_R0.447058824 0.447058824
77#define FREE_FILL_G0.623529412 0.623529412
78#define FREE_FILL_B0.811764706 0.811764706
79
80#define PREVIEW_IMAGE_WIDTH96 96
81
82#define ROW_PAD6 6
83
84static GHashTable *windows;
85static GHashTable *pending_lists;
86
87struct _FMPropertiesWindowPrivate {
88 GList *original_files;
89 GList *target_files;
90
91 CtkNotebook *notebook;
92
93 CtkGrid *basic_grid;
94
95 CtkWidget *icon_button;
96 CtkWidget *icon_image;
97 CtkWidget *icon_chooser;
98
99 CtkLabel *name_label;
100 CtkWidget *name_field;
101 unsigned int name_row;
102 char *pending_name;
103
104 CtkLabel *directory_contents_title_field;
105 CtkLabel *directory_contents_value_field;
106 guint update_directory_contents_timeout_id;
107 guint update_files_timeout_id;
108
109 GList *emblem_buttons;
110 GHashTable *initial_emblems;
111
112 BaulFile *group_change_file;
113 char *group_change_group;
114 unsigned int group_change_timeout;
115 BaulFile *owner_change_file;
116 char *owner_change_owner;
117 unsigned int owner_change_timeout;
118
119 GList *permission_buttons;
120 GList *permission_combos;
121 GHashTable *initial_permissions;
122 gboolean has_recursive_apply;
123
124 GList *value_fields;
125
126 GList *mime_list;
127
128 gboolean deep_count_finished;
129
130 guint total_count;
131 goffset total_size;
132 goffset total_size_on_disk;
133
134 guint long_operation_underway;
135
136 GList *changed_files;
137
138 guint64 volume_capacity;
139 guint64 volume_free;
140
141 CdkRGBA used_color;
142 CdkRGBA free_color;
143 CdkRGBA used_stroke_color;
144 CdkRGBA free_stroke_color;
145};
146
147typedef enum {
148 PERMISSIONS_CHECKBOXES_READ,
149 PERMISSIONS_CHECKBOXES_WRITE,
150 PERMISSIONS_CHECKBOXES_EXECUTE
151} CheckboxType;
152
153enum {
154 TITLE_COLUMN,
155 VALUE_COLUMN,
156 COLUMN_COUNT
157};
158
159typedef struct {
160 GList *original_files;
161 GList *target_files;
162 CtkWidget *parent_widget;
163 char *pending_key;
164 GHashTable *pending_files;
165} StartupData;
166
167/* drag and drop definitions */
168
169enum {
170 TARGET_URI_LIST,
171 TARGET_CAFE_URI_LIST,
172 TARGET_RESET_BACKGROUND
173};
174
175static const CtkTargetEntry target_table[] = {
176 { "text/uri-list", 0, TARGET_URI_LIST },
177 { "x-special/cafe-icon-list", 0, TARGET_CAFE_URI_LIST },
178 { "x-special/cafe-reset-background", 0, TARGET_RESET_BACKGROUND }
179};
180
181#define DIRECTORY_CONTENTS_UPDATE_INTERVAL200 200 /* milliseconds */
182#define FILES_UPDATE_INTERVAL200 200 /* milliseconds */
183#define STANDARD_EMBLEM_HEIGHT52 52
184#define EMBLEM_LABEL_SPACING2 2
185
186/*
187 * A timeout before changes through the user/group combo box will be applied.
188 * When quickly changing owner/groups (i.e. by keyboard or scroll wheel),
189 * this ensures that the GUI doesn't end up unresponsive.
190 *
191 * Both combos react on changes by scheduling a new change and unscheduling
192 * or cancelling old pending changes.
193 */
194#define CHOWN_CHGRP_TIMEOUT300 300 /* milliseconds */
195
196static void directory_contents_value_field_update (FMPropertiesWindow *window);
197static void file_changed_callback (BaulFile *file,
198 gpointer user_data);
199static void permission_button_update (FMPropertiesWindow *window,
200 CtkToggleButton *button);
201static void permission_combo_update (FMPropertiesWindow *window,
202 CtkComboBox *combo);
203static void value_field_update (FMPropertiesWindow *window,
204 CtkLabel *field);
205static void properties_window_update (FMPropertiesWindow *window,
206 GList *files);
207static void is_directory_ready_callback (BaulFile *file,
208 gpointer data);
209static void cancel_group_change_callback (FMPropertiesWindow *window);
210static void cancel_owner_change_callback (FMPropertiesWindow *window);
211static void parent_widget_destroyed_callback (CtkWidget *widget,
212 gpointer callback_data);
213static void select_image_button_callback (CtkWidget *widget,
214 FMPropertiesWindow *properties_window);
215static void set_icon (const char *icon_path,
216 FMPropertiesWindow *properties_window);
217static void remove_pending (StartupData *data,
218 gboolean cancel_call_when_ready,
219 gboolean cancel_timed_wait,
220 gboolean cancel_destroy_handler);
221static void append_extension_pages (FMPropertiesWindow *window);
222
223static gboolean name_field_focus_out (BaulEntry *name_field,
224 CdkEventFocus *event,
225 gpointer callback_data);
226static void name_field_activate (BaulEntry *name_field,
227 gpointer callback_data);
228static CtkLabel *attach_ellipsizing_value_label (CtkGrid *grid,
229 CtkWidget *sibling,
230
231 const char *initial_text);
232
233static CtkWidget* create_pie_widget (FMPropertiesWindow *window);
234
235G_DEFINE_TYPE_WITH_PRIVATE (FMPropertiesWindow, fm_properties_window, CTK_TYPE_DIALOG)static void fm_properties_window_init (FMPropertiesWindow *self
); static void fm_properties_window_class_init (FMPropertiesWindowClass
*klass); static GType fm_properties_window_get_type_once (void
); static gpointer fm_properties_window_parent_class = ((void
*)0); static gint FMPropertiesWindow_private_offset; static void
fm_properties_window_class_intern_init (gpointer klass) { fm_properties_window_parent_class
= g_type_class_peek_parent (klass); if (FMPropertiesWindow_private_offset
!= 0) g_type_class_adjust_private_offset (klass, &FMPropertiesWindow_private_offset
); fm_properties_window_class_init ((FMPropertiesWindowClass*
) klass); } __attribute__ ((__unused__)) static inline gpointer
fm_properties_window_get_instance_private (FMPropertiesWindow
*self) { return (((gpointer) ((guint8*) (self) + (glong) (FMPropertiesWindow_private_offset
)))); } GType fm_properties_window_get_type (void) { static GType
static_g_define_type_id = 0; if ((__extension__ ({ _Static_assert
(sizeof *(&static_g_define_type_id) == sizeof (gpointer)
, "Expression evaluates to false"); (void) (0 ? (gpointer) * (
&static_g_define_type_id) : ((void*)0)); (!(__extension__
({ _Static_assert (sizeof *(&static_g_define_type_id) ==
sizeof (gpointer), "Expression evaluates to false"); __typeof__
(*(&static_g_define_type_id)) gapg_temp_newval; __typeof__
((&static_g_define_type_id)) gapg_temp_atomic = (&static_g_define_type_id
); __atomic_load (gapg_temp_atomic, &gapg_temp_newval, 5)
; gapg_temp_newval; })) && g_once_init_enter_pointer (
&static_g_define_type_id)); })) ) { GType g_define_type_id
= fm_properties_window_get_type_once (); (__extension__ ({ _Static_assert
(sizeof *(&static_g_define_type_id) == sizeof (gpointer)
, "Expression evaluates to false"); 0 ? (void) (*(&static_g_define_type_id
) = (g_define_type_id)) : (void) 0; g_once_init_leave_pointer
((&static_g_define_type_id), (gpointer) (guintptr) (g_define_type_id
)); })) ; } return static_g_define_type_id; } __attribute__ (
(__noinline__)) static GType fm_properties_window_get_type_once
(void) { GType g_define_type_id = g_type_register_static_simple
((ctk_dialog_get_type ()), g_intern_static_string ("FMPropertiesWindow"
), sizeof (FMPropertiesWindowClass), (GClassInitFunc)(void (*
)(void)) fm_properties_window_class_intern_init, sizeof (FMPropertiesWindow
), (GInstanceInitFunc)(void (*)(void)) fm_properties_window_init
, (GTypeFlags) 0); { {{ FMPropertiesWindow_private_offset = g_type_add_instance_private
(g_define_type_id, sizeof (FMPropertiesWindowPrivate)); };} }
return g_define_type_id; }
;
236
237static gboolean
238is_multi_file_window (FMPropertiesWindow *window)
239{
240 GList *l;
241 int count;
242
243 count = 0;
244
245 for (l = window->details->original_files; l != NULL((void*)0); l = l->next) {
246 if (!baul_file_is_gone (BAUL_FILE (l->data)((((BaulFile*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((l->data)), (baul_file_get_type())))))
)) {
247 count++;
248 if (count > 1) {
249 return TRUE(!(0));
250 }
251 }
252 }
253
254 return FALSE(0);
255}
256
257static int
258get_not_gone_original_file_count (FMPropertiesWindow *window)
259{
260 GList *l;
261 int count;
262
263 count = 0;
264
265 for (l = window->details->original_files; l != NULL((void*)0); l = l->next) {
266 if (!baul_file_is_gone (BAUL_FILE (l->data)((((BaulFile*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((l->data)), (baul_file_get_type())))))
)) {
267 count++;
268 }
269 }
270
271 return count;
272}
273
274static BaulFile *
275get_original_file (FMPropertiesWindow *window)
276{
277 g_return_val_if_fail (!is_multi_file_window (window), NULL)do { if ((!is_multi_file_window (window))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "!is_multi_file_window (window)"
); return (((void*)0)); } } while (0)
;
278
279 if (window->details->original_files == NULL((void*)0)) {
280 return NULL((void*)0);
281 }
282
283 return BAUL_FILE (window->details->original_files->data)((((BaulFile*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((window->details->original_files->data)), (baul_file_get_type
())))))
;
284}
285
286static BaulFile *
287get_target_file_for_original_file (BaulFile *file)
288{
289 BaulFile *target_file;
290
291 target_file = NULL((void*)0);
292 if (BAUL_IS_DESKTOP_ICON_FILE (file)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(file)); GType __t = (baul_desktop_icon_file_get_type()); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; }))))
) {
293 BaulDesktopLink *link;
294
295 link = baul_desktop_icon_file_get_link (BAUL_DESKTOP_ICON_FILE (file)((((BaulDesktopIconFile*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((file)), (baul_desktop_icon_file_get_type
())))))
);
296
297 if (link != NULL((void*)0)) {
298 GFile *location;
299
300 /* map to linked URI for these types of links */
301 location = baul_desktop_link_get_activation_location (link);
302
303 if (location) {
304 target_file = baul_file_get (location);
305 g_object_unref (location);
306 }
307
308 g_object_unref (link);
309 }
310 } else {
311 char *uri_to_display;
312
313 uri_to_display = baul_file_get_activation_uri (file);
314
315 if (uri_to_display != NULL((void*)0)) {
316 target_file = baul_file_get_by_uri (uri_to_display);
317 g_free (uri_to_display);
318 }
319 }
320
321 if (target_file != NULL((void*)0)) {
322 return target_file;
323 }
324
325 /* Ref passed-in file here since we've decided to use it. */
326 baul_file_ref (file);
327 return file;
328}
329
330static BaulFile *
331get_target_file (FMPropertiesWindow *window)
332{
333 return BAUL_FILE (window->details->target_files->data)((((BaulFile*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((window->details->target_files->data)), (baul_file_get_type
())))))
;
334}
335
336static void
337add_prompt (CtkWidget *vbox, const char *prompt_text, gboolean pack_at_start)
338{
339 CtkWidget *prompt;
340
341 prompt = ctk_label_new (prompt_text);
342 ctk_label_set_justify (CTK_LABEL (prompt)((((CtkLabel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((prompt)), ((ctk_label_get_type ()))))))
, CTK_JUSTIFY_LEFT);
343 ctk_label_set_line_wrap (CTK_LABEL (prompt)((((CtkLabel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((prompt)), ((ctk_label_get_type ()))))))
, TRUE(!(0)));
344 ctk_widget_show (prompt);
345 if (pack_at_start) {
346 ctk_box_pack_start (CTK_BOX (vbox)((((CtkBox*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((vbox)), ((ctk_box_get_type ()))))))
, prompt, FALSE(0), FALSE(0), 0);
347 } else {
348 ctk_box_pack_end (CTK_BOX (vbox)((((CtkBox*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((vbox)), ((ctk_box_get_type ()))))))
, prompt, FALSE(0), FALSE(0), 0);
349 }
350}
351
352static void
353add_prompt_and_separator (CtkWidget *vbox, const char *prompt_text)
354{
355 CtkWidget *separator_line;
356
357 add_prompt (vbox, prompt_text, FALSE(0));
358
359 separator_line = ctk_separator_new (CTK_ORIENTATION_HORIZONTAL);
360
361 ctk_widget_show (separator_line);
362 ctk_box_pack_end (CTK_BOX (vbox)((((CtkBox*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((vbox)), ((ctk_box_get_type ()))))))
, separator_line, TRUE(!(0)), TRUE(!(0)), 2*ROW_PAD6);
363}
364
365static void
366get_image_for_properties_window (FMPropertiesWindow *window,
367 char **icon_name,
368 GdkPixbuf **icon_pixbuf)
369{
370 BaulIconInfo *icon, *new_icon;
371 GList *l;
372 gint icon_scale;
373
374 icon = NULL((void*)0);
375 icon_scale = ctk_widget_get_scale_factor (CTK_WIDGET (window->details->notebook)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((window->details->notebook)), ((ctk_widget_get_type
()))))))
);
376
377 for (l = window->details->original_files; l != NULL((void*)0); l = l->next) {
378 BaulFile *file;
379
380 file = BAUL_FILE (l->data)((((BaulFile*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((l->data)), (baul_file_get_type())))))
;
381
382 if (!icon) {
383 icon = baul_file_get_icon (file, BAUL_ICON_SIZE_STANDARD48, icon_scale,
384 BAUL_FILE_ICON_FLAGS_USE_THUMBNAILS |
385 BAUL_FILE_ICON_FLAGS_IGNORE_VISITING);
386 } else {
387 new_icon = baul_file_get_icon (file, BAUL_ICON_SIZE_STANDARD48, icon_scale,
388 BAUL_FILE_ICON_FLAGS_USE_THUMBNAILS |
389 BAUL_FILE_ICON_FLAGS_IGNORE_VISITING);
390 if (!new_icon || new_icon != icon) {
391 g_object_unref (icon);
392 g_object_unref (new_icon);
393 icon = NULL((void*)0);
394 break;
395 }
396 g_object_unref (new_icon);
397 }
398 }
399
400 if (!icon) {
401 icon = baul_icon_info_lookup_from_name ("text-x-generic",
402 BAUL_ICON_SIZE_STANDARD48,
403 icon_scale);
404 }
405
406 if (icon_name != NULL((void*)0)) {
407 *icon_name = g_strdup (baul_icon_info_get_used_name (icon))g_strdup_inline (baul_icon_info_get_used_name (icon));
408 }
409
410 if (icon_pixbuf != NULL((void*)0)) {
411 *icon_pixbuf = baul_icon_info_get_pixbuf_at_size (icon, BAUL_ICON_SIZE_STANDARD48);
412 }
413
414 g_object_unref (icon);
415}
416
417
418static void
419update_properties_window_icon (FMPropertiesWindow *window)
420{
421 GdkPixbuf *pixbuf;
422 cairo_surface_t *surface;
423 char *name;
424
425 get_image_for_properties_window (window, &name, &pixbuf);
426
427 if (name != NULL((void*)0)) {
428 ctk_window_set_icon_name (CTK_WINDOW (window)((((CtkWindow*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((window)), ((ctk_window_get_type ()))))))
, name);
429 } else {
430 ctk_window_set_icon (CTK_WINDOW (window)((((CtkWindow*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((window)), ((ctk_window_get_type ()))))))
, pixbuf);
431 }
432
433 surface = cdk_cairo_surface_create_from_pixbuf (pixbuf, ctk_widget_get_scale_factor (CTK_WIDGET (window)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((window)), ((ctk_widget_get_type ()))))))
),
434 ctk_widget_get_window (CTK_WIDGET (window)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((window)), ((ctk_widget_get_type ()))))))
));
435 ctk_image_set_from_surface (CTK_IMAGE (window->details->icon_image)((((CtkImage*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((window->details->icon_image)), ((ctk_image_get_type
()))))))
, surface);
436
437 g_free (name);
438 g_object_unref (pixbuf);
439 cairo_surface_destroy (surface);
440}
441
442/* utility to test if a uri refers to a local image */
443static gboolean
444uri_is_local_image (const char *uri)
445{
446 GdkPixbuf *pixbuf;
447 char *image_path;
448
449 image_path = g_filename_from_uri (uri, NULL((void*)0), NULL((void*)0));
450 if (image_path == NULL((void*)0)) {
451 return FALSE(0);
452 }
453
454 pixbuf = gdk_pixbuf_new_from_file (image_path, NULL((void*)0));
455 g_free (image_path);
456
457 if (pixbuf == NULL((void*)0)) {
458 return FALSE(0);
459 }
460 g_object_unref (pixbuf);
461 return TRUE(!(0));
462}
463
464
465static void
466reset_icon (FMPropertiesWindow *properties_window)
467{
468 GList *l;
469
470 for (l = properties_window->details->original_files; l != NULL((void*)0); l = l->next) {
471 BaulFile *file;
472
473 file = BAUL_FILE (l->data)((((BaulFile*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((l->data)), (baul_file_get_type())))))
;
474
475 baul_file_set_metadata (file,
476 BAUL_METADATA_KEY_ICON_SCALE"icon-scale",
477 NULL((void*)0), NULL((void*)0));
478 baul_file_set_metadata (file,
479 BAUL_METADATA_KEY_CUSTOM_ICON"custom-icon",
480 NULL((void*)0), NULL((void*)0));
481 }
482}
483
484
485static void
486fm_properties_window_drag_data_received (CtkWidget *widget,
487 CdkDragContext *context G_GNUC_UNUSED__attribute__ ((__unused__)),
488 int x G_GNUC_UNUSED__attribute__ ((__unused__)),
489 int y G_GNUC_UNUSED__attribute__ ((__unused__)),
490 CtkSelectionData *selection_data,
491 guint info,
492 guint time G_GNUC_UNUSED__attribute__ ((__unused__)))
493{
494 char **uris;
495 gboolean exactly_one;
496 CtkImage *image;
497 CtkWindow *window;
498
499 image = CTK_IMAGE (widget)((((CtkImage*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_image_get_type ()))))))
;
500 window = CTK_WINDOW (ctk_widget_get_toplevel (CTK_WIDGET (image)))((((CtkWindow*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((ctk_widget_get_toplevel (((((CtkWidget*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((image)), ((ctk_widget_get_type ())))))))
)), ((ctk_window_get_type ()))))))
;
501
502 if (info == TARGET_RESET_BACKGROUND) {
503 reset_icon (FM_PROPERTIES_WINDOW (window)((((FMPropertiesWindow*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((window)), (fm_properties_window_get_type()
)))))
);
504
505 return;
506 }
507
508 uris = g_strsplit (ctk_selection_data_get_data (selection_data), "\r\n", 0);
509 exactly_one = uris[0] != NULL((void*)0) && (uris[1] == NULL((void*)0) || uris[1][0] == '\0');
510
511
512 if (!exactly_one) {
513 eel_show_error_dialog
514 (_("You cannot assign more than one custom icon at a time!")gettext ("You cannot assign more than one custom icon at a time!"
)
,
515 _("Please drag just one image to set a custom icon.")gettext ("Please drag just one image to set a custom icon."),
516 window);
517 } else {
518 if (uri_is_local_image (uris[0])) {
519 set_icon (uris[0], FM_PROPERTIES_WINDOW (window)((((FMPropertiesWindow*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((window)), (fm_properties_window_get_type()
)))))
);
520 } else {
521 GFile *f;
522
523 f = g_file_new_for_uri (uris[0]);
524 if (!g_file_is_native (f)) {
525 eel_show_error_dialog
526 (_("The file that you dropped is not local.")gettext ("The file that you dropped is not local."),
527 _("You can only use local images as custom icons.")gettext ("You can only use local images as custom icons."),
528 window);
529
530 } else {
531 eel_show_error_dialog
532 (_("The file that you dropped is not an image.")gettext ("The file that you dropped is not an image."),
533 _("You can only use local images as custom icons.")gettext ("You can only use local images as custom icons."),
534 window);
535 }
536 g_object_unref (f);
537 }
538 }
539 g_strfreev (uris);
540}
541
542static CtkWidget *
543create_image_widget (FMPropertiesWindow *window,
544 gboolean is_customizable)
545{
546 CtkWidget *button;
547 CtkWidget *image;
548
549 image = ctk_image_new ();
550 window->details->icon_image = image;
551
552 update_properties_window_icon (window);
553 ctk_widget_show (image);
554
555 button = NULL((void*)0);
556 if (is_customizable) {
557 button = ctk_button_new ();
558 ctk_container_add (CTK_CONTAINER (button)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((button)), ((ctk_container_get_type ()))))))
, image);
559
560 /* prepare the image to receive dropped objects to assign custom images */
561 ctk_drag_dest_set (CTK_WIDGET (image)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((image)), ((ctk_widget_get_type ()))))))
,
562 CTK_DEST_DEFAULT_MOTION | CTK_DEST_DEFAULT_HIGHLIGHT | CTK_DEST_DEFAULT_DROP,
563 target_table, G_N_ELEMENTS (target_table)(sizeof (target_table) / sizeof ((target_table)[0])),
564 CDK_ACTION_COPY | CDK_ACTION_MOVE);
565
566 g_signal_connect (image, "drag_data_received",g_signal_connect_data ((image), ("drag_data_received"), (((GCallback
) (fm_properties_window_drag_data_received))), (((void*)0)), (
(void*)0), (GConnectFlags) 0)
567 G_CALLBACK (fm_properties_window_drag_data_received), NULL)g_signal_connect_data ((image), ("drag_data_received"), (((GCallback
) (fm_properties_window_drag_data_received))), (((void*)0)), (
(void*)0), (GConnectFlags) 0)
;
568 g_signal_connect (button, "clicked",g_signal_connect_data ((button), ("clicked"), (((GCallback) (
select_image_button_callback))), (window), ((void*)0), (GConnectFlags
) 0)
569 G_CALLBACK (select_image_button_callback), window)g_signal_connect_data ((button), ("clicked"), (((GCallback) (
select_image_button_callback))), (window), ((void*)0), (GConnectFlags
) 0)
;
570 }
571
572 window->details->icon_button = button;
573
574 return button != NULL((void*)0) ? button : image;
575}
576
577static void
578set_name_field (FMPropertiesWindow *window,
579 const gchar *original_name,
580 const gchar *name)
581{
582 gboolean new_widget;
583 gboolean use_label;
584
585 /* There are four cases here:
586 * 1) Changing the text of a label
587 * 2) Changing the text of an entry
588 * 3) Creating label (potentially replacing entry)
589 * 4) Creating entry (potentially replacing label)
590 */
591 use_label = is_multi_file_window (window) || !baul_file_can_rename (get_original_file (window));
592 new_widget = !window->details->name_field || (use_label ? BAUL_IS_ENTRY (window->details->name_field)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(window->details->name_field)); GType __t = (baul_entry_get_type
()); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))
: CTK_IS_LABEL (window->details->name_field)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(window->details->name_field)); GType __t = ((ctk_label_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))
);
593
594 if (new_widget) {
595 if (window->details->name_field) {
596 ctk_widget_destroy (window->details->name_field);
597 }
598
599 if (use_label) {
600 window->details->name_field = CTK_WIDGET((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((attach_ellipsizing_value_label (window->details->basic_grid
, ((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((window->details->name_label)), ((ctk_widget_get_type
())))))), name))), ((ctk_widget_get_type ()))))))
601 (attach_ellipsizing_value_label (window->details->basic_grid,((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((attach_ellipsizing_value_label (window->details->basic_grid
, ((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((window->details->name_label)), ((ctk_widget_get_type
())))))), name))), ((ctk_widget_get_type ()))))))
602 CTK_WIDGET (window->details->name_label),((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((attach_ellipsizing_value_label (window->details->basic_grid
, ((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((window->details->name_label)), ((ctk_widget_get_type
())))))), name))), ((ctk_widget_get_type ()))))))
603 name))((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((attach_ellipsizing_value_label (window->details->basic_grid
, ((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((window->details->name_label)), ((ctk_widget_get_type
())))))), name))), ((ctk_widget_get_type ()))))))
;
604
605 } else {
606 window->details->name_field = baul_entry_new ();
607 ctk_entry_set_text (CTK_ENTRY (window->details->name_field)((((CtkEntry*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((window->details->name_field)), ((ctk_entry_get_type
()))))))
, name);
608 ctk_widget_show (window->details->name_field);
609 ctk_grid_attach_next_to (window->details->basic_grid, window->details->name_field,
610 CTK_WIDGET (window->details->name_label)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((window->details->name_label)), ((ctk_widget_get_type
()))))))
,
611 CTK_POS_RIGHT, 1, 1);
612
613 ctk_label_set_mnemonic_widget (CTK_LABEL (window->details->name_label)((((CtkLabel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((window->details->name_label)), ((ctk_label_get_type
()))))))
, window->details->name_field);
614
615 g_signal_connect_object (window->details->name_field, "focus_out_event",
616 G_CALLBACK (name_field_focus_out)((GCallback) (name_field_focus_out)), window, 0);
617 g_signal_connect_object (window->details->name_field, "activate",
618 G_CALLBACK (name_field_activate)((GCallback) (name_field_activate)), window, 0);
619 }
620
621 ctk_widget_show (window->details->name_field);
622 }
623 /* Only replace text if the file's name has changed. */
624 else if (original_name == NULL((void*)0) || strcmp (original_name, name) != 0) {
625
626 if (use_label) {
627 ctk_label_set_text (CTK_LABEL (window->details->name_field)((((CtkLabel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((window->details->name_field)), ((ctk_label_get_type
()))))))
, name);
628 } else {
629 /* Only reset the text if it's different from what is
630 * currently showing. This causes minimal ripples (e.g.
631 * selection change).
632 */
633 gchar *displayed_name = ctk_editable_get_chars (CTK_EDITABLE (window->details->name_field)((((CtkEditable*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((window->details->name_field)), ((ctk_editable_get_type
()))))))
, 0, -1);
634 if (strcmp (displayed_name, name) != 0) {
635 ctk_entry_set_text (CTK_ENTRY (window->details->name_field)((((CtkEntry*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((window->details->name_field)), ((ctk_entry_get_type
()))))))
, name);
636 }
637 g_free (displayed_name);
638 }
639 }
640}
641
642static void
643update_name_field (FMPropertiesWindow *window)
644{
645 BaulFile *file;
646
647 ctk_label_set_text_with_mnemonic (window->details->name_label,
648 ngettext ("_Name:", "_Names:",
649 get_not_gone_original_file_count (window)));
650
651 if (is_multi_file_window (window)) {
652 /* Multifile property dialog, show all names */
653 GString *str;
654 char *name;
655 gboolean first;
656 GList *l;
657
658 str = g_string_new ("");
659
660 first = TRUE(!(0));
661
662 for (l = window->details->target_files; l != NULL((void*)0); l = l->next) {
663 file = BAUL_FILE (l->data)((((BaulFile*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((l->data)), (baul_file_get_type())))))
;
664
665 if (!baul_file_is_gone (file)) {
666 if (!first) {
667 g_string_append (str, ", ")(__builtin_constant_p (", ") ? __extension__ ({ const char * const
__val = (", "); g_string_append_len_inline (str, __val, (__val
!= ((void*)0)) ? (gssize) strlen (((__val) + !(__val))) : (gssize
) -1); }) : g_string_append_len_inline (str, ", ", (gssize) -
1))
;
668 }
669 first = FALSE(0);
670
671 name = baul_file_get_display_name (file);
672 g_string_append (str, name)(__builtin_constant_p (name) ? __extension__ ({ const char * const
__val = (name); g_string_append_len_inline (str, __val, (__val
!= ((void*)0)) ? (gssize) strlen (((__val) + !(__val))) : (gssize
) -1); }) : g_string_append_len_inline (str, name, (gssize) -
1))
;
673 g_free (name);
674 }
675 }
676 set_name_field (window, NULL((void*)0), str->str);
677 g_string_free (str, TRUE)(__builtin_constant_p ((!(0))) ? (((!(0))) ? (g_string_free) (
(str), ((!(0)))) : g_string_free_and_steal (str)) : (g_string_free
) ((str), ((!(0)))))
;
678 } else {
679 const char *original_name = NULL((void*)0);
680 char *current_name;
681
682 file = get_original_file (window);
683
684 if (file == NULL((void*)0) || baul_file_is_gone (file)) {
685 current_name = g_strdup ("")g_strdup_inline ("");
686 } else {
687 current_name = baul_file_get_display_name (file);
688 }
689
690 /* If the file name has changed since the original name was stored,
691 * update the text in the text field, possibly (deliberately) clobbering
692 * an edit in progress. If the name hasn't changed (but some other
693 * aspect of the file might have), then don't clobber changes.
694 */
695 if (window->details->name_field) {
696 original_name = (const char *) g_object_get_data (G_OBJECT (window->details->name_field)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((window->details->name_field)), (((GType) ((20) <<
(2))))))))
, "original_name");
697 }
698
699 set_name_field (window, original_name, current_name);
700
701 if (original_name == NULL((void*)0) ||
702 g_strcmp0 (original_name, current_name) != 0) {
703 g_object_set_data_full (G_OBJECT (window->details->name_field)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((window->details->name_field)), (((GType) ((20) <<
(2))))))))
,
704 "original_name",
705 current_name,
706 g_free);
707 } else {
708 g_free (current_name);
709 }
710 }
711}
712
713static void
714name_field_restore_original_name (BaulEntry *name_field)
715{
716 const char *original_name;
717 char *displayed_name;
718
719 original_name = (const char *) g_object_get_data (G_OBJECT (name_field)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((name_field)), (((GType) ((20) << (2))))))))
,
720 "original_name");
721
722 if (!original_name) {
723 return;
724 }
725
726 displayed_name = ctk_editable_get_chars (CTK_EDITABLE (name_field)((((CtkEditable*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((name_field)), ((ctk_editable_get_type ()))))))
, 0, -1);
727
728 if (strcmp (original_name, displayed_name) != 0) {
729 ctk_entry_set_text (CTK_ENTRY (name_field)((((CtkEntry*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((name_field)), ((ctk_entry_get_type ()))))))
, original_name);
730 }
731 baul_entry_select_all (name_field);
732
733 g_free (displayed_name);
734}
735
736static void
737rename_callback (BaulFile *file,
738 GFile *res_loc G_GNUC_UNUSED__attribute__ ((__unused__)),
739 GError *error,
740 gpointer callback_data)
741{
742 FMPropertiesWindow *window;
743
744 window = FM_PROPERTIES_WINDOW (callback_data)((((FMPropertiesWindow*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((callback_data)), (fm_properties_window_get_type
())))))
;
745
746 /* Complain to user if rename failed. */
747 if (error != NULL((void*)0)) {
748 fm_report_error_renaming_file (file,
749 window->details->pending_name,
750 error,
751 CTK_WINDOW (window)((((CtkWindow*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((window)), ((ctk_window_get_type ()))))))
);
752 if (window->details->name_field != NULL((void*)0)) {
753 name_field_restore_original_name (BAUL_ENTRY (window->details->name_field)((((BaulEntry*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((window->details->name_field)), (baul_entry_get_type
())))))
);
754 }
755 }
756
757 g_object_unref (window);
758}
759
760static void
761set_pending_name (FMPropertiesWindow *window, const char *name)
762{
763 g_free (window->details->pending_name);
764 window->details->pending_name = g_strdup (name)g_strdup_inline (name);
765}
766
767static void
768name_field_done_editing (BaulEntry *name_field, FMPropertiesWindow *window)
769{
770 BaulFile *file;
771 char *new_name;
772
773 g_return_if_fail (BAUL_IS_ENTRY (name_field))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((name_field)); GType __t = (baul_entry_get_type()); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning (((gchar*) 0), ((const char*
) (__func__)), "BAUL_IS_ENTRY (name_field)"); return; } } while
(0)
;
774
775 /* Don't apply if the dialog has more than one file */
776 if (is_multi_file_window (window)) {
777 return;
778 }
779
780 file = get_original_file (window);
781
782 /* This gets called when the window is closed, which might be
783 * caused by the file having been deleted.
784 */
785 if (file == NULL((void*)0) || baul_file_is_gone (file)) {
786 return;
787 }
788
789 new_name = ctk_editable_get_chars (CTK_EDITABLE (name_field)((((CtkEditable*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((name_field)), ((ctk_editable_get_type ()))))))
, 0, -1);
790
791 /* Special case: silently revert text if new text is empty. */
792 if (strlen (new_name) == 0) {
793 name_field_restore_original_name (BAUL_ENTRY (name_field)((((BaulEntry*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((name_field)), (baul_entry_get_type())))))
);
794 } else {
795 const char *original_name;
796
797 original_name = (const char *) g_object_get_data (G_OBJECT (window->details->name_field)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((window->details->name_field)), (((GType) ((20) <<
(2))))))))
,
798 "original_name");
799 /* Don't rename if not changed since we read the display name.
800 This is needed so that we don't save the display name to the
801 file when nothing is changed */
802 if (strcmp (new_name, original_name) != 0) {
803 set_pending_name (window, new_name);
804 g_object_ref (window)((__typeof__ (window)) (g_object_ref) (window));
805 baul_file_rename (file, new_name,
806 rename_callback, window);
807 }
808 }
809
810 g_free (new_name);
811}
812
813static gboolean
814name_field_focus_out (BaulEntry *name_field,
815 CdkEventFocus *event G_GNUC_UNUSED__attribute__ ((__unused__)),
816 gpointer callback_data)
817{
818 g_assert (FM_IS_PROPERTIES_WINDOW (callback_data))do { if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((callback_data)); GType __t = (fm_properties_window_get_type
()); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 818, ((const char*) (__func__)), "FM_IS_PROPERTIES_WINDOW (callback_data)"
); } while (0)
;
819
820 if (ctk_widget_get_sensitive (CTK_WIDGET (name_field)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((name_field)), ((ctk_widget_get_type ()))))))
)) {
821 name_field_done_editing (name_field, FM_PROPERTIES_WINDOW (callback_data)((((FMPropertiesWindow*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((callback_data)), (fm_properties_window_get_type
())))))
);
822 }
823
824 return FALSE(0);
825}
826
827static void
828name_field_activate (BaulEntry *name_field, gpointer callback_data)
829{
830 g_assert (BAUL_IS_ENTRY (name_field))do { if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((name_field)); GType __t = (baul_entry_get_type()); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; }))))) ; else
g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 830, ((const char*) (__func__)), "BAUL_IS_ENTRY (name_field)"
); } while (0)
;
831 g_assert (FM_IS_PROPERTIES_WINDOW (callback_data))do { if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((callback_data)); GType __t = (fm_properties_window_get_type
()); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 831, ((const char*) (__func__)), "FM_IS_PROPERTIES_WINDOW (callback_data)"
); } while (0)
;
832
833 /* Accept changes. */
834 name_field_done_editing (name_field, FM_PROPERTIES_WINDOW (callback_data)((((FMPropertiesWindow*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((callback_data)), (fm_properties_window_get_type
())))))
);
835
836 baul_entry_select_all_at_idle (name_field);
837}
838
839static gboolean
840file_has_keyword (BaulFile *file, const char *keyword)
841{
842 GList *keywords, *word;
843
844 keywords = baul_file_get_keywords (file);
845 word = g_list_find_custom (keywords, keyword, (GCompareFunc) strcmp);
846 g_list_free_full (keywords, g_free);
847
848 return (word != NULL((void*)0));
849}
850
851static void
852get_initial_emblem_state (FMPropertiesWindow *window,
853 const char *name,
854 GList **on,
855 GList **off)
856{
857 GList *l;
858
859 *on = NULL((void*)0);
860 *off = NULL((void*)0);
861
862 for (l = window->details->original_files; l != NULL((void*)0); l = l->next) {
863 GList *initial_emblems;
864
865 initial_emblems = g_hash_table_lookup (window->details->initial_emblems,
866 l->data);
867
868 if (g_list_find_custom (initial_emblems, name, (GCompareFunc) strcmp)) {
869 *on = g_list_prepend (*on, l->data);
870 } else {
871 *off = g_list_prepend (*off, l->data);
872 }
873 }
874}
875
876static void
877emblem_button_toggled (CtkToggleButton *button,
878 FMPropertiesWindow *window)
879{
880 GList *l;
881 GList *keywords;
882 GList *word;
883 char *name;
884 GList *files_on;
885 GList *files_off;
886
887 name = g_object_get_data (G_OBJECT (button)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((button)), (((GType) ((20) << (2))))))))
, "baul_emblem_name");
888
889 files_on = NULL((void*)0);
890 files_off = NULL((void*)0);
891 if (ctk_toggle_button_get_active (button)
892 && !ctk_toggle_button_get_inconsistent (button)) {
893 /* Go to the initial state unless the initial state was
894 consistent */
895 get_initial_emblem_state (window, name,
896 &files_on, &files_off);
897
898 if (!(files_on && files_off)) {
899 g_list_free (files_on);
900 g_list_free (files_off);
901 files_on = g_list_copy (window->details->original_files);
902 files_off = NULL((void*)0);
903 }
904 } else if (ctk_toggle_button_get_inconsistent (button)
905 && !ctk_toggle_button_get_active (button)) {
906 files_on = g_list_copy (window->details->original_files);
907 files_off = NULL((void*)0);
908 } else {
909 files_off = g_list_copy (window->details->original_files);
910 files_on = NULL((void*)0);
911 }
912
913 g_signal_handlers_block_by_func (G_OBJECT (button),g_signal_handlers_block_matched ((((((GObject*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((button)), (((GType) ((20) << (2)))
)))))), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (((GCallback) (emblem_button_toggled))),
(window))
914 G_CALLBACK (emblem_button_toggled),g_signal_handlers_block_matched ((((((GObject*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((button)), (((GType) ((20) << (2)))
)))))), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (((GCallback) (emblem_button_toggled))),
(window))
915 window)g_signal_handlers_block_matched ((((((GObject*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((button)), (((GType) ((20) << (2)))
)))))), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (((GCallback) (emblem_button_toggled))),
(window))
;
916
917 ctk_toggle_button_set_active (button, files_on != NULL((void*)0));
918 ctk_toggle_button_set_inconsistent (button, files_on && files_off);
919
920 g_signal_handlers_unblock_by_func (G_OBJECT (button),g_signal_handlers_unblock_matched ((((((GObject*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((button)), (((GType) ((20) << (2)))
)))))), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (((GCallback) (emblem_button_toggled))),
(window))
921 G_CALLBACK (emblem_button_toggled),g_signal_handlers_unblock_matched ((((((GObject*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((button)), (((GType) ((20) << (2)))
)))))), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (((GCallback) (emblem_button_toggled))),
(window))
922 window)g_signal_handlers_unblock_matched ((((((GObject*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((button)), (((GType) ((20) << (2)))
)))))), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (((GCallback) (emblem_button_toggled))),
(window))
;
923
924 for (l = files_on; l != NULL((void*)0); l = l->next) {
925 BaulFile *file;
926
927 file = BAUL_FILE (l->data)((((BaulFile*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((l->data)), (baul_file_get_type())))))
;
928
929 keywords = baul_file_get_keywords (file);
930
931 word = g_list_find_custom (keywords, name, (GCompareFunc)strcmp);
932 if (!word) {
933 keywords = g_list_prepend (keywords, g_strdup (name)g_strdup_inline (name));
934 }
935 baul_file_set_keywords (file, keywords);
936 g_list_free_full (keywords, g_free);
937 }
938
939 for (l = files_off; l != NULL((void*)0); l = l->next) {
940 BaulFile *file;
941
942 file = BAUL_FILE (l->data)((((BaulFile*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((l->data)), (baul_file_get_type())))))
;
943
944 keywords = baul_file_get_keywords (file);
945
946 word = g_list_find_custom (keywords, name, (GCompareFunc)strcmp);
947 if (word) {
948 keywords = g_list_remove_link (keywords, word);
949 g_list_free_full (word, g_free);
950 }
951 baul_file_set_keywords (file, keywords);
952 g_list_free_full (keywords, g_free);
953 }
954
955 g_list_free (files_on);
956 g_list_free (files_off);
957}
958
959static void
960emblem_button_update (FMPropertiesWindow *window,
961 CtkToggleButton *button)
962{
963 GList *l;
964 char *name;
965 gboolean all_set;
966 gboolean all_unset;
967
968 name = g_object_get_data (G_OBJECT (button)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((button)), (((GType) ((20) << (2))))))))
, "baul_emblem_name");
969
970 all_set = TRUE(!(0));
971 all_unset = TRUE(!(0));
972 for (l = window->details->original_files; l != NULL((void*)0); l = l->next) {
973 gboolean has_keyword;
974 BaulFile *file;
975
976 file = BAUL_FILE (l->data)((((BaulFile*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((l->data)), (baul_file_get_type())))))
;
977
978 has_keyword = file_has_keyword (file, name);
979
980 if (has_keyword) {
981 all_unset = FALSE(0);
982 } else {
983 all_set = FALSE(0);
984 }
985 }
986
987 g_signal_handlers_block_by_func (G_OBJECT (button),g_signal_handlers_block_matched ((((((GObject*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((button)), (((GType) ((20) << (2)))
)))))), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (((GCallback) (emblem_button_toggled))),
(window))
988 G_CALLBACK (emblem_button_toggled),g_signal_handlers_block_matched ((((((GObject*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((button)), (((GType) ((20) << (2)))
)))))), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (((GCallback) (emblem_button_toggled))),
(window))
989 window)g_signal_handlers_block_matched ((((((GObject*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((button)), (((GType) ((20) << (2)))
)))))), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (((GCallback) (emblem_button_toggled))),
(window))
;
990
991 ctk_toggle_button_set_active (button, !all_unset);
992 ctk_toggle_button_set_inconsistent (button, !all_unset && !all_set);
993
994 g_signal_handlers_unblock_by_func (G_OBJECT (button),g_signal_handlers_unblock_matched ((((((GObject*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((button)), (((GType) ((20) << (2)))
)))))), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (((GCallback) (emblem_button_toggled))),
(window))
995 G_CALLBACK (emblem_button_toggled),g_signal_handlers_unblock_matched ((((((GObject*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((button)), (((GType) ((20) << (2)))
)))))), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (((GCallback) (emblem_button_toggled))),
(window))
996 window)g_signal_handlers_unblock_matched ((((((GObject*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((button)), (((GType) ((20) << (2)))
)))))), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (((GCallback) (emblem_button_toggled))),
(window))
;
997
998}
999
1000static void
1001update_properties_window_title (FMPropertiesWindow *window)
1002{
1003 char *title;
1004
1005 g_return_if_fail (CTK_IS_WINDOW (window))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = ((ctk_window_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning (((gchar*) 0), ((const char*
) (__func__)), "CTK_IS_WINDOW (window)"); return; } } while (
0)
;
1006
1007 title = g_strdup_printf (_("Properties")gettext ("Properties"));
1008
1009 if (!is_multi_file_window (window)) {
1010 BaulFile *file;
1011
1012 file = get_original_file (window);
1013
1014 if (file != NULL((void*)0)) {
1015 char *name;
1016
1017 g_free (title);
1018 name = baul_file_get_display_name (file);
1019 title = g_strdup_printf (_("%s Properties")gettext ("%s Properties"), name);
1020 g_free (name);
1021 }
1022 }
1023
1024 ctk_window_set_title (CTK_WINDOW (window)((((CtkWindow*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((window)), ((ctk_window_get_type ()))))))
, title);
1025
1026 g_free (title);
1027}
1028
1029static void
1030clear_extension_pages (FMPropertiesWindow *window)
1031{
1032 int i;
1033 int num_pages;
1034 CtkWidget *page = NULL((void*)0);
1035
1036 num_pages = ctk_notebook_get_n_pages
1037 (CTK_NOTEBOOK (window->details->notebook)((((CtkNotebook*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((window->details->notebook)), ((ctk_notebook_get_type
()))))))
);
1038
1039 for (i = 0; i < num_pages; i++) {
1040 page = ctk_notebook_get_nth_page
1041 (CTK_NOTEBOOK (window->details->notebook)((((CtkNotebook*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((window->details->notebook)), ((ctk_notebook_get_type
()))))))
, i);
1042
1043 if (g_object_get_data (G_OBJECT (page)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((page)), (((GType) ((20) << (2))))))))
, "is-extension-page")) {
1044 ctk_notebook_remove_page
1045 (CTK_NOTEBOOK (window->details->notebook)((((CtkNotebook*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((window->details->notebook)), ((ctk_notebook_get_type
()))))))
, i);
1046 num_pages--;
1047 i--;
1048 }
1049 }
1050}
1051
1052static void
1053refresh_extension_pages (FMPropertiesWindow *window)
1054{
1055 clear_extension_pages (window);
1056 append_extension_pages (window);
1057}
1058
1059static void
1060remove_from_dialog (FMPropertiesWindow *window,
1061 BaulFile *file)
1062{
1063 int index;
1064 GList *original_link;
1065 GList *target_link;
1066 BaulFile *original_file;
1067 BaulFile *target_file;
1068
1069 index = g_list_index (window->details->target_files, file);
1070 if (index == -1) {
1071 index = g_list_index (window->details->original_files, file);
1072 g_return_if_fail (index != -1)do { if ((index != -1)) { } else { g_return_if_fail_warning (
((gchar*) 0), ((const char*) (__func__)), "index != -1"); return
; } } while (0)
;
1073 }
1074
1075 original_link = g_list_nth (window->details->original_files, index);
1076 target_link = g_list_nth (window->details->target_files, index);
1077
1078 g_return_if_fail (original_link && target_link)do { if ((original_link && target_link)) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "original_link && target_link"
); return; } } while (0)
;
1079
1080 original_file = BAUL_FILE (original_link->data)((((BaulFile*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((original_link->data)), (baul_file_get_type())))))
;
1081 target_file = BAUL_FILE (target_link->data)((((BaulFile*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((target_link->data)), (baul_file_get_type())))))
;
1082
1083 window->details->original_files = g_list_remove_link (window->details->original_files, original_link);
1084 g_list_free (original_link);
1085
1086 window->details->target_files = g_list_remove_link (window->details->target_files, target_link);
1087 g_list_free (target_link);
1088
1089 g_hash_table_remove (window->details->initial_emblems, original_file);
1090 g_hash_table_remove (window->details->initial_permissions, target_file);
1091
1092 g_signal_handlers_disconnect_by_func (original_file,g_signal_handlers_disconnect_matched ((original_file), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (((GCallback) (file_changed_callback))), (window))
1093 G_CALLBACK (file_changed_callback),g_signal_handlers_disconnect_matched ((original_file), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (((GCallback) (file_changed_callback))), (window))
1094 window)g_signal_handlers_disconnect_matched ((original_file), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (((GCallback) (file_changed_callback))), (window))
;
1095 g_signal_handlers_disconnect_by_func (target_file,g_signal_handlers_disconnect_matched ((target_file), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (((GCallback) (file_changed_callback))), (window))
1096 G_CALLBACK (file_changed_callback),g_signal_handlers_disconnect_matched ((target_file), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (((GCallback) (file_changed_callback))), (window))
1097 window)g_signal_handlers_disconnect_matched ((target_file), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (((GCallback) (file_changed_callback))), (window))
;
1098
1099 baul_file_monitor_remove (original_file, &window->details->original_files);
1100 baul_file_monitor_remove (target_file, &window->details->target_files);
1101
1102 baul_file_unref (original_file);
1103 baul_file_unref (target_file);
1104
1105}
1106
1107static gboolean
1108mime_list_equal (GList *a, GList *b)
1109{
1110 while (a && b) {
1111 if (strcmp (a->data, b->data)) {
1112 return FALSE(0);
1113 }
1114 a = a->next;
1115 b = b->next;
1116 }
1117
1118 return (a == b);
1119}
1120
1121static GList *
1122get_mime_list (FMPropertiesWindow *window)
1123{
1124 GList *ret;
1125 GList *l;
1126
1127 ret = NULL((void*)0);
1128 for (l = window->details->target_files; l != NULL((void*)0); l = l->next) {
1129 ret = g_list_append (ret, baul_file_get_mime_type (BAUL_FILE (l->data)((((BaulFile*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((l->data)), (baul_file_get_type())))))
));
1130 }
1131 ret = g_list_reverse (ret);
1132 return ret;
1133}
1134
1135static void
1136properties_window_update (FMPropertiesWindow *window,
1137 GList *files)
1138{
1139 GList *l;
1140 GList *mime_list;
1141 GList *tmp;
1142 BaulFile *changed_file = NULL((void*)0);
1143 gboolean dirty_original = FALSE(0);
1144 gboolean dirty_target = FALSE(0);
1145
1146 if (files == NULL((void*)0)) {
1147 dirty_original = TRUE(!(0));
1148 dirty_target = TRUE(!(0));
1149 }
1150
1151 for (tmp = files; tmp != NULL((void*)0); tmp = tmp->next) {
1152 changed_file = BAUL_FILE (tmp->data)((((BaulFile*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tmp->data)), (baul_file_get_type())))))
;
1153
1154 if (changed_file && baul_file_is_gone (changed_file)) {
1155 /* Remove the file from the property dialog */
1156 remove_from_dialog (window, changed_file);
1157 changed_file = NULL((void*)0);
1158
1159 if (window->details->original_files == NULL((void*)0)) {
1160 return;
1161 }
1162 }
1163 if (changed_file == NULL((void*)0) ||
1164 g_list_find (window->details->original_files, changed_file)) {
1165 dirty_original = TRUE(!(0));
1166 }
1167 if (changed_file == NULL((void*)0) ||
1168 g_list_find (window->details->target_files, changed_file)) {
1169 dirty_target = TRUE(!(0));
1170 }
1171
1172 }
1173
1174 if (dirty_original) {
1175 update_properties_window_title (window);
1176 update_properties_window_icon (window);
1177 update_name_field (window);
1178
1179 for (l = window->details->emblem_buttons; l != NULL((void*)0); l = l->next) {
1180 emblem_button_update (window, CTK_TOGGLE_BUTTON (l->data)((((CtkToggleButton*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((l->data)), ((ctk_toggle_button_get_type ()))))))
);
1181 }
1182
1183 /* If any of the value fields start to depend on the original
1184 * value, value_field_updates should be added here */
1185 }
1186
1187 if (dirty_target) {
1188 for (l = window->details->permission_buttons; l != NULL((void*)0); l = l->next) {
1189 permission_button_update (window, CTK_TOGGLE_BUTTON (l->data)((((CtkToggleButton*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((l->data)), ((ctk_toggle_button_get_type ()))))))
);
1190 }
1191
1192 for (l = window->details->permission_combos; l != NULL((void*)0); l = l->next) {
1193 permission_combo_update (window, CTK_COMBO_BOX (l->data)((((CtkComboBox*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((l->data)), ((ctk_combo_box_get_type ()))))))
);
1194 }
1195
1196 for (l = window->details->value_fields; l != NULL((void*)0); l = l->next) {
1197 value_field_update (window, CTK_LABEL (l->data)((((CtkLabel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((l->data)), ((ctk_label_get_type ()))))))
);
1198 }
1199 }
1200
1201 mime_list = get_mime_list (window);
1202
1203 if (!window->details->mime_list) {
1204 window->details->mime_list = mime_list;
1205 } else {
1206 if (!mime_list_equal (window->details->mime_list, mime_list)) {
1207 refresh_extension_pages (window);
1208 }
1209
1210 g_list_free_full (window->details->mime_list, g_free);
1211 window->details->mime_list = mime_list;
1212 }
1213}
1214
1215static gboolean
1216update_files_callback (gpointer data)
1217{
1218 FMPropertiesWindow *window;
1219
1220 window = FM_PROPERTIES_WINDOW (data)((((FMPropertiesWindow*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((data)), (fm_properties_window_get_type()))
)))
;
1221
1222 window->details->update_files_timeout_id = 0;
1223
1224 properties_window_update (window, window->details->changed_files);
1225
1226 if (window->details->original_files == NULL((void*)0)) {
1227 /* Close the window if no files are left */
1228 ctk_widget_destroy (CTK_WIDGET (window)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((window)), ((ctk_widget_get_type ()))))))
);
1229 } else {
1230 baul_file_list_free (window->details->changed_files);
1231 window->details->changed_files = NULL((void*)0);
1232 }
1233
1234 return FALSE(0);
1235 }
1236
1237static void
1238schedule_files_update (FMPropertiesWindow *window)
1239 {
1240 g_assert (FM_IS_PROPERTIES_WINDOW (window))do { if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = (fm_properties_window_get_type());
gboolean __r; if (!__inst) __r = (0); else if (__inst->g_class
&& __inst->g_class->g_type == __t) __r = (!(0)
); else __r = g_type_check_instance_is_a (__inst, __t); __r; }
))))) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 1240, ((const char*) (__func__)), "FM_IS_PROPERTIES_WINDOW (window)"
); } while (0)
;
1241
1242 if (window->details->update_files_timeout_id == 0) {
1243 window->details->update_files_timeout_id
1244 = g_timeout_add (FILES_UPDATE_INTERVAL200,
1245 update_files_callback,
1246 window);
1247 }
1248 }
1249
1250static gboolean
1251file_list_attributes_identical (GList *file_list, const char *attribute_name)
1252{
1253 gboolean identical;
1254 char *first_attr;
1255 GList *l;
1256
1257 first_attr = NULL((void*)0);
1258 identical = TRUE(!(0));
1259
1260 for (l = file_list; l != NULL((void*)0); l = l->next) {
1261 BaulFile *file;
1262
1263 file = BAUL_FILE (l->data)((((BaulFile*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((l->data)), (baul_file_get_type())))))
;
1264
1265 if (baul_file_is_gone (file)) {
1266 continue;
1267 }
1268
1269 if (first_attr == NULL((void*)0)) {
1270 first_attr = baul_file_get_string_attribute_with_default (file, attribute_name);
1271 } else {
1272 char *attr;
1273 attr = baul_file_get_string_attribute_with_default (file, attribute_name);
1274 if (strcmp (attr, first_attr)) {
1275 identical = FALSE(0);
1276 g_free (attr);
1277 break;
1278 }
1279 g_free (attr);
1280 }
1281 }
1282
1283 g_free (first_attr);
1284 return identical;
1285}
1286
1287static char *
1288file_list_get_string_attribute (GList *file_list,
1289 const char *attribute_name,
1290 const char *inconsistent_value)
1291{
1292 if (file_list_attributes_identical (file_list, attribute_name)) {
1293 GList *l;
1294
1295 for (l = file_list; l != NULL((void*)0); l = l->next) {
1296 BaulFile *file;
1297
1298 file = BAUL_FILE (l->data)((((BaulFile*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((l->data)), (baul_file_get_type())))))
;
1299 if (!baul_file_is_gone (file)) {
1300 return baul_file_get_string_attribute_with_default
1301 (file,
1302 attribute_name);
1303 }
1304 }
1305 return g_strdup (_("unknown"))g_strdup_inline (gettext ("unknown"));
1306 } else {
1307 return g_strdup (inconsistent_value)g_strdup_inline (inconsistent_value);
1308 }
1309}
1310
1311
1312static gboolean
1313file_list_all_directories (GList *file_list)
1314{
1315 GList *l;
1316 for (l = file_list; l != NULL((void*)0); l = l->next) {
1317 if (!baul_file_is_directory (BAUL_FILE (l->data)((((BaulFile*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((l->data)), (baul_file_get_type())))))
)) {
1318 return FALSE(0);
1319 }
1320 }
1321 return TRUE(!(0));
1322}
1323
1324static void
1325value_field_update_internal (CtkLabel *label,
1326 GList *file_list)
1327{
1328 const char *attribute_name;
1329 char *attribute_value;
1330 char *inconsistent_string;
1331
1332 g_assert (CTK_IS_LABEL (label))do { if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((label)); GType __t = ((ctk_label_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; }))))) ; else
g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 1332, ((const char*) (__func__)), "CTK_IS_LABEL (label)"); }
while (0)
;
1333
1334 attribute_name = g_object_get_data (G_OBJECT (label)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((label)), (((GType) ((20) << (2))))))))
, "file_attribute");
1335 inconsistent_string = g_object_get_data (G_OBJECT (label)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((label)), (((GType) ((20) << (2))))))))
, "inconsistent_string");
1336 attribute_value = file_list_get_string_attribute (file_list,
1337 attribute_name,
1338 inconsistent_string);
1339 if (!strcmp (attribute_name, "type") && strcmp (attribute_value, inconsistent_string)) {
1340 char *mime_type;
1341
1342 mime_type = file_list_get_string_attribute (file_list,
1343 "mime_type",
1344 inconsistent_string);
1345 if (strcmp (mime_type, inconsistent_string)) {
1346 char *tmp;
1347
1348 tmp = attribute_value;
1349 attribute_value = g_strdup_printf (C_("MIME type description (MIME type)", "%s (%s)")g_dpgettext (((void*)0), "MIME type description (MIME type)" "\004"
"%s (%s)", strlen ("MIME type description (MIME type)") + 1)
, attribute_value, mime_type);
1350 g_free (tmp);
1351 }
1352 g_free (mime_type);
1353 }
1354
1355 ctk_label_set_text (label, attribute_value);
1356 g_free (attribute_value);
1357}
1358
1359static void
1360value_field_update (FMPropertiesWindow *window, CtkLabel *label)
1361{
1362 gboolean use_original;
1363
1364 use_original = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (label), "show_original"))((gint) (glong) (g_object_get_data (((((GObject*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((label)), (((GType) ((20) << (2))))
)))), "show_original")))
;
1365
1366 value_field_update_internal (label,
1367 (use_original ?
1368 window->details->original_files :
1369 window->details->target_files));
1370}
1371
1372static CtkLabel *
1373attach_label (CtkGrid *grid,
1374 CtkWidget *sibling,
1375 const char *initial_text,
1376 gboolean ellipsize_text,
1377 gboolean selectable,
1378 gboolean mnemonic)
1379{
1380 CtkWidget *label_field;
1381
1382 if (ellipsize_text) {
1383 label_field = ctk_label_new (initial_text);
1384 ctk_label_set_ellipsize (CTK_LABEL (label_field)((((CtkLabel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((label_field)), ((ctk_label_get_type ()))))))
,
1385 PANGO_ELLIPSIZE_END);
1386 } else if (mnemonic) {
1387 label_field = ctk_label_new_with_mnemonic (initial_text);
1388 } else {
1389 label_field = ctk_label_new (initial_text);
1390 }
1391
1392 if (selectable) {
1393 ctk_label_set_selectable (CTK_LABEL (label_field)((((CtkLabel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((label_field)), ((ctk_label_get_type ()))))))
, TRUE(!(0)));
1394 }
1395
1396 ctk_label_set_xalign (CTK_LABEL (label_field)((((CtkLabel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((label_field)), ((ctk_label_get_type ()))))))
, 0);
1397 ctk_widget_show (label_field);
1398 if (ellipsize_text) {
1399 ctk_widget_set_hexpand (label_field, TRUE(!(0)));
1400 ctk_label_set_max_width_chars (CTK_LABEL (label_field)((((CtkLabel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((label_field)), ((ctk_label_get_type ()))))))
, 24);
1401 }
1402
1403 if (sibling != NULL((void*)0)) {
1404 ctk_grid_attach_next_to (grid, label_field, sibling,
1405 CTK_POS_RIGHT, 1, 1);
1406 } else {
1407 ctk_container_add (CTK_CONTAINER (grid)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((grid)), ((ctk_container_get_type ()))))))
, label_field);
1408 }
1409
1410 return CTK_LABEL (label_field)((((CtkLabel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((label_field)), ((ctk_label_get_type ()))))))
;
1411}
1412
1413static CtkLabel *
1414attach_value_label (CtkGrid *grid,
1415 CtkWidget *sibling,
1416 const char *initial_text)
1417{
1418 return attach_label (grid, sibling, initial_text, FALSE(0), TRUE(!(0)), FALSE(0));
1419}
1420
1421static CtkLabel *
1422attach_ellipsizing_value_label (CtkGrid *grid,
1423 CtkWidget *sibling,
1424 const char *initial_text)
1425{
1426 return attach_label (grid, sibling, initial_text, TRUE(!(0)), TRUE(!(0)), FALSE(0));
1427}
1428
1429static CtkWidget*
1430attach_value_field_internal (FMPropertiesWindow *window,
1431 CtkGrid *grid,
1432 CtkWidget *sibling,
1433 const char *file_attribute_name,
1434 const char *inconsistent_string,
1435 gboolean show_original,
1436 gboolean ellipsize_text)
1437{
1438 CtkLabel *value_field;
1439
1440 if (ellipsize_text) {
1441 value_field = attach_ellipsizing_value_label (grid, sibling, "");
1442 } else {
1443 value_field = attach_value_label (grid, sibling, "");
1444 }
1445
1446 /* Stash a copy of the file attribute name in this field for the callback's sake. */
1447 g_object_set_data_full (G_OBJECT (value_field)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((value_field)), (((GType) ((20) << (2))))))))
, "file_attribute",
1448 g_strdup (file_attribute_name)g_strdup_inline (file_attribute_name), g_free);
1449
1450 g_object_set_data_full (G_OBJECT (value_field)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((value_field)), (((GType) ((20) << (2))))))))
, "inconsistent_string",
1451 g_strdup (inconsistent_string)g_strdup_inline (inconsistent_string), g_free);
1452
1453 g_object_set_data (G_OBJECT (value_field)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((value_field)), (((GType) ((20) << (2))))))))
, "show_original", GINT_TO_POINTER (show_original)((gpointer) (glong) (show_original)));
1454
1455 window->details->value_fields = g_list_prepend (window->details->value_fields,
1456 value_field);
1457 return CTK_WIDGET(value_field)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((value_field)), ((ctk_widget_get_type ()))))))
;
1458}
1459
1460static CtkWidget*
1461attach_value_field (FMPropertiesWindow *window,
1462 CtkGrid *grid,
1463 CtkWidget *sibling,
1464 const char *file_attribute_name,
1465 const char *inconsistent_string,
1466 gboolean show_original)
1467{
1468 return attach_value_field_internal (window,
1469 grid, sibling,
1470 file_attribute_name,
1471 inconsistent_string,
1472 show_original,
1473 FALSE(0));
1474}
1475
1476static CtkWidget*
1477attach_ellipsizing_value_field (FMPropertiesWindow *window,
1478 CtkGrid *grid,
1479 CtkWidget *sibling,
1480 const char *file_attribute_name,
1481 const char *inconsistent_string,
1482 gboolean show_original)
1483{
1484 return attach_value_field_internal (window,
1485 grid, sibling,
1486 file_attribute_name,
1487 inconsistent_string,
1488 show_original,
1489 TRUE(!(0)));
1490}
1491
1492static void
1493group_change_callback (BaulFile *file,
1494 GFile *res_loc G_GNUC_UNUSED__attribute__ ((__unused__)),
1495 GError *error,
1496 FMPropertiesWindow *window)
1497{
1498 char *group;
1499
1500 g_assert (FM_IS_PROPERTIES_WINDOW (window))do { if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = (fm_properties_window_get_type());
gboolean __r; if (!__inst) __r = (0); else if (__inst->g_class
&& __inst->g_class->g_type == __t) __r = (!(0)
); else __r = g_type_check_instance_is_a (__inst, __t); __r; }
))))) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 1500, ((const char*) (__func__)), "FM_IS_PROPERTIES_WINDOW (window)"
); } while (0)
;
1501 g_assert (window->details->group_change_file == file)do { if (window->details->group_change_file == file) ; else
g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 1501, ((const char*) (__func__)), "window->details->group_change_file == file"
); } while (0)
;
1502
1503 group = window->details->group_change_group;
1504 g_assert (group != NULL)do { if (group != ((void*)0)) ; else g_assertion_message_expr
(((gchar*) 0), "fm-properties-window.c", 1504, ((const char*
) (__func__)), "group != NULL"); } while (0)
;
1505
1506 /* Report the error if it's an error. */
1507 eel_timed_wait_stop ((EelCancelCallback) cancel_group_change_callback, window);
1508 fm_report_error_setting_group (file, error, CTK_WINDOW (window)((((CtkWindow*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((window)), ((ctk_window_get_type ()))))))
);
1509
1510 baul_file_unref (file);
1511 g_free (group);
1512
1513 window->details->group_change_file = NULL((void*)0);
1514 window->details->group_change_group = NULL((void*)0);
1515 g_object_unref (G_OBJECT (window)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((window)), (((GType) ((20) << (2))))))))
);
1516}
1517
1518static void
1519cancel_group_change_callback (FMPropertiesWindow *window)
1520{
1521 BaulFile *file;
1522 char *group;
1523
1524 file = window->details->group_change_file;
1525 g_assert (BAUL_IS_FILE (file))do { if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (baul_file_get_type()); gboolean __r
; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; }))))) ; else
g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 1525, ((const char*) (__func__)), "BAUL_IS_FILE (file)"); }
while (0)
;
1526
1527 group = window->details->group_change_group;
1528 g_assert (group != NULL)do { if (group != ((void*)0)) ; else g_assertion_message_expr
(((gchar*) 0), "fm-properties-window.c", 1528, ((const char*
) (__func__)), "group != NULL"); } while (0)
;
1529
1530 baul_file_cancel (file, (BaulFileOperationCallback) group_change_callback, window);
1531
1532 g_free (group);
1533 baul_file_unref (file);
1534
1535 window->details->group_change_file = NULL((void*)0);
1536 window->details->group_change_group = NULL((void*)0);
1537 g_object_unref (window);
1538}
1539
1540static gboolean
1541schedule_group_change_timeout (FMPropertiesWindow *window)
1542{
1543 BaulFile *file;
1544 char *group;
1545
1546 g_assert (FM_IS_PROPERTIES_WINDOW (window))do { if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = (fm_properties_window_get_type());
gboolean __r; if (!__inst) __r = (0); else if (__inst->g_class
&& __inst->g_class->g_type == __t) __r = (!(0)
); else __r = g_type_check_instance_is_a (__inst, __t); __r; }
))))) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 1546, ((const char*) (__func__)), "FM_IS_PROPERTIES_WINDOW (window)"
); } while (0)
;
1547
1548 file = window->details->group_change_file;
1549 g_assert (BAUL_IS_FILE (file))do { if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (baul_file_get_type()); gboolean __r
; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; }))))) ; else
g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 1549, ((const char*) (__func__)), "BAUL_IS_FILE (file)"); }
while (0)
;
1550
1551 group = window->details->group_change_group;
1552 g_assert (group != NULL)do { if (group != ((void*)0)) ; else g_assertion_message_expr
(((gchar*) 0), "fm-properties-window.c", 1552, ((const char*
) (__func__)), "group != NULL"); } while (0)
;
1553
1554 eel_timed_wait_start
1555 ((EelCancelCallback) cancel_group_change_callback,
1556 window,
1557 _("Cancel Group Change?")gettext ("Cancel Group Change?"),
1558 CTK_WINDOW (window)((((CtkWindow*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((window)), ((ctk_window_get_type ()))))))
);
1559
1560 baul_file_set_group
1561 (file, group,
1562 (BaulFileOperationCallback) group_change_callback, window);
1563
1564 window->details->group_change_timeout = 0;
1565 return FALSE(0);
1566}
1567
1568static void
1569schedule_group_change (FMPropertiesWindow *window,
1570 BaulFile *file,
1571 const char *group)
1572{
1573 g_assert (FM_IS_PROPERTIES_WINDOW (window))do { if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = (fm_properties_window_get_type());
gboolean __r; if (!__inst) __r = (0); else if (__inst->g_class
&& __inst->g_class->g_type == __t) __r = (!(0)
); else __r = g_type_check_instance_is_a (__inst, __t); __r; }
))))) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 1573, ((const char*) (__func__)), "FM_IS_PROPERTIES_WINDOW (window)"
); } while (0)
;
1574 g_assert (window->details->group_change_group == NULL)do { if (window->details->group_change_group == ((void*
)0)) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 1574, ((const char*) (__func__)), "window->details->group_change_group == NULL"
); } while (0)
;
1575 g_assert (window->details->group_change_file == NULL)do { if (window->details->group_change_file == ((void*)
0)) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 1575, ((const char*) (__func__)), "window->details->group_change_file == NULL"
); } while (0)
;
1576 g_assert (BAUL_IS_FILE (file))do { if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (baul_file_get_type()); gboolean __r
; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; }))))) ; else
g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 1576, ((const char*) (__func__)), "BAUL_IS_FILE (file)"); }
while (0)
;
1577
1578 window->details->group_change_file = baul_file_ref (file);
1579 window->details->group_change_group = g_strdup (group)g_strdup_inline (group);
1580 g_object_ref (G_OBJECT (window))((__typeof__ (((((GObject*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((window)), (((GType) ((20) << (2)))
))))))) (g_object_ref) (((((GObject*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((window)), (((GType) ((20) << (2)))
)))))))
;
1581 window->details->group_change_timeout =
1582 g_timeout_add (CHOWN_CHGRP_TIMEOUT300,
1583 (GSourceFunc) schedule_group_change_timeout,
1584 window);
1585}
1586
1587static void
1588unschedule_or_cancel_group_change (FMPropertiesWindow *window)
1589{
1590 BaulFile *file;
1591 char *group;
1592
1593 g_assert (FM_IS_PROPERTIES_WINDOW (window))do { if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = (fm_properties_window_get_type());
gboolean __r; if (!__inst) __r = (0); else if (__inst->g_class
&& __inst->g_class->g_type == __t) __r = (!(0)
); else __r = g_type_check_instance_is_a (__inst, __t); __r; }
))))) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 1593, ((const char*) (__func__)), "FM_IS_PROPERTIES_WINDOW (window)"
); } while (0)
;
1594
1595 file = window->details->group_change_file;
1596 group = window->details->group_change_group;
1597
1598 g_assert ((file == NULL && group == NULL) ||do { if ((file == ((void*)0) && group == ((void*)0)) ||
(file != ((void*)0) && group != ((void*)0))) ; else g_assertion_message_expr
(((gchar*) 0), "fm-properties-window.c", 1599, ((const char*
) (__func__)), "(file == NULL && group == NULL) || (file != NULL && group != NULL)"
); } while (0)
1599 (file != NULL && group != NULL))do { if ((file == ((void*)0) && group == ((void*)0)) ||
(file != ((void*)0) && group != ((void*)0))) ; else g_assertion_message_expr
(((gchar*) 0), "fm-properties-window.c", 1599, ((const char*
) (__func__)), "(file == NULL && group == NULL) || (file != NULL && group != NULL)"
); } while (0)
;
1600
1601 if (file != NULL((void*)0)) {
1602 g_assert (BAUL_IS_FILE (file))do { if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (baul_file_get_type()); gboolean __r
; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; }))))) ; else
g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 1602, ((const char*) (__func__)), "BAUL_IS_FILE (file)"); }
while (0)
;
1603
1604 if (window->details->group_change_timeout == 0) {
1605 baul_file_cancel (file,
1606 (BaulFileOperationCallback) group_change_callback, window);
1607 eel_timed_wait_stop ((EelCancelCallback) cancel_group_change_callback, window);
1608 }
1609
1610 baul_file_unref (file);
1611 g_free (group);
1612
1613 window->details->group_change_file = NULL((void*)0);
1614 window->details->group_change_group = NULL((void*)0);
1615 g_object_unref (G_OBJECT (window)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((window)), (((GType) ((20) << (2))))))))
);
1616 }
1617
1618 if (window->details->group_change_timeout > 0) {
1619 g_assert (file != NULL)do { if (file != ((void*)0)) ; else g_assertion_message_expr (
((gchar*) 0), "fm-properties-window.c", 1619, ((const char*) (
__func__)), "file != NULL"); } while (0)
;
1620 g_source_remove (window->details->group_change_timeout);
1621 window->details->group_change_timeout = 0;
1622 }
1623}
1624
1625static void
1626changed_group_callback (CtkComboBox *combo_box, BaulFile *file)
1627{
1628 char *group;
1629 char *cur_group;
1630
1631 g_assert (CTK_IS_COMBO_BOX (combo_box))do { if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((combo_box)); GType __t = ((ctk_combo_box_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; }))))) ; else
g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 1631, ((const char*) (__func__)), "CTK_IS_COMBO_BOX (combo_box)"
); } while (0)
;
1632 g_assert (BAUL_IS_FILE (file))do { if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (baul_file_get_type()); gboolean __r
; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; }))))) ; else
g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 1632, ((const char*) (__func__)), "BAUL_IS_FILE (file)"); }
while (0)
;
1633
1634 group = ctk_combo_box_text_get_active_text (CTK_COMBO_BOX_TEXT (combo_box)((((CtkComboBoxText*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((combo_box)), ((ctk_combo_box_text_get_type ()))))))
);
1635 cur_group = baul_file_get_group_name (file);
1636
1637 if (group != NULL((void*)0) && strcmp (group, cur_group) != 0) {
1638 FMPropertiesWindow *window;
1639
1640 /* Try to change file group. If this fails, complain to user. */
1641 window = FM_PROPERTIES_WINDOW (ctk_widget_get_ancestor (CTK_WIDGET (combo_box), CTK_TYPE_WINDOW))((((FMPropertiesWindow*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((ctk_widget_get_ancestor (((((CtkWidget*) (
void *) g_type_check_instance_cast ((GTypeInstance*) ((combo_box
)), ((ctk_widget_get_type ())))))), (ctk_window_get_type ()))
)), (fm_properties_window_get_type())))))
;
1642
1643 unschedule_or_cancel_group_change (window);
1644 schedule_group_change (window, file, group);
1645 }
1646 g_free (group);
1647 g_free (cur_group);
1648}
1649
1650/* checks whether the given column at the first level
1651 * of model has the specified entries in the given order. */
1652static gboolean
1653tree_model_entries_equal (CtkTreeModel *model,
1654 unsigned int column,
1655 GList *entries)
1656{
1657 CtkTreeIter iter;
1658 gboolean empty_model;
1659
1660 g_assert (CTK_IS_TREE_MODEL (model))do { if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((model)); GType __t = ((ctk_tree_model_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; }))))) ; else
g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 1660, ((const char*) (__func__)), "CTK_IS_TREE_MODEL (model)"
); } while (0)
;
1661 g_assert (ctk_tree_model_get_column_type (model, column) == G_TYPE_STRING)do { if (ctk_tree_model_get_column_type (model, column) == ((
GType) ((16) << (2)))) ; else g_assertion_message_expr (
((gchar*) 0), "fm-properties-window.c", 1661, ((const char*) (
__func__)), "ctk_tree_model_get_column_type (model, column) == G_TYPE_STRING"
); } while (0)
;
1662
1663 empty_model = !ctk_tree_model_get_iter_first (model, &iter);
1664
1665 if (!empty_model && entries != NULL((void*)0)) {
1666 GList *l;
1667
1668 l = entries;
1669
1670 do {
1671 char *val;
1672
1673 ctk_tree_model_get (model, &iter,
1674 column, &val,
1675 -1);
1676 if ((val == NULL((void*)0) && l->data != NULL((void*)0)) ||
1677 (val != NULL((void*)0) && l->data == NULL((void*)0)) ||
1678 (val != NULL((void*)0) && strcmp (val, l->data))) {
1679 g_free (val);
1680 return FALSE(0);
1681 }
1682
1683 g_free (val);
1684 l = l->next;
1685 } while (ctk_tree_model_iter_next (model, &iter));
1686
1687 return l == NULL((void*)0);
1688 } else {
1689 return (empty_model && entries == NULL((void*)0)) ||
1690 (!empty_model && entries != NULL((void*)0));
1691 }
1692}
1693
1694static char *
1695combo_box_get_active_entry (CtkComboBox *combo_box,
1696 unsigned int column)
1697{
1698 CtkTreeIter iter;
1699 char *val;
1700
1701 g_assert (CTK_IS_COMBO_BOX (combo_box))do { if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((combo_box)); GType __t = ((ctk_combo_box_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; }))))) ; else
g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 1701, ((const char*) (__func__)), "CTK_IS_COMBO_BOX (combo_box)"
); } while (0)
;
1702
1703 if (ctk_combo_box_get_active_iter (CTK_COMBO_BOX (combo_box)((((CtkComboBox*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((combo_box)), ((ctk_combo_box_get_type ()))))))
, &iter)) {
1704 CtkTreeModel *model;
1705
1706 model = ctk_combo_box_get_model (combo_box);
1707 g_assert (CTK_IS_TREE_MODEL (model))do { if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((model)); GType __t = ((ctk_tree_model_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; }))))) ; else
g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 1707, ((const char*) (__func__)), "CTK_IS_TREE_MODEL (model)"
); } while (0)
;
1708
1709 ctk_tree_model_get (model, &iter,
1710 column, &val,
1711 -1);
1712 return val;
1713 }
1714
1715 return NULL((void*)0);
1716}
1717
1718/* returns the index of the given entry in the the given column
1719 * at the first level of model. Returns -1 if entry can't be found
1720 * or entry is NULL.
1721 * */
1722static int
1723tree_model_get_entry_index (CtkTreeModel *model,
1724 unsigned int column,
1725 const char *entry)
1726{
1727 CtkTreeIter iter;
1728 gboolean empty_model;
1729
1730 g_assert (CTK_IS_TREE_MODEL (model))do { if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((model)); GType __t = ((ctk_tree_model_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; }))))) ; else
g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 1730, ((const char*) (__func__)), "CTK_IS_TREE_MODEL (model)"
); } while (0)
;
1731 g_assert (ctk_tree_model_get_column_type (model, column) == G_TYPE_STRING)do { if (ctk_tree_model_get_column_type (model, column) == ((
GType) ((16) << (2)))) ; else g_assertion_message_expr (
((gchar*) 0), "fm-properties-window.c", 1731, ((const char*) (
__func__)), "ctk_tree_model_get_column_type (model, column) == G_TYPE_STRING"
); } while (0)
;
1732
1733 empty_model = !ctk_tree_model_get_iter_first (model, &iter);
1734 if (!empty_model && entry != NULL((void*)0)) {
1735 int index;
1736
1737 index = 0;
1738
1739 do {
1740 char *val;
1741
1742 ctk_tree_model_get (model, &iter,
1743 column, &val,
1744 -1);
1745 if (val != NULL((void*)0) && !strcmp (val, entry)) {
1746 g_free (val);
1747 return index;
1748 }
1749
1750 g_free (val);
1751 index++;
1752 } while (ctk_tree_model_iter_next (model, &iter));
1753 }
1754
1755 return -1;
1756}
1757
1758
1759static void
1760synch_groups_combo_box (CtkComboBox *combo_box, BaulFile *file)
1761{
1762 GList *groups;
1763 GList *node;
1764 CtkTreeModel *model;
1765 CtkListStore *store;
1766 char *current_group_name;
1767 int current_group_index;
1768
1769 g_assert (CTK_IS_COMBO_BOX (combo_box))do { if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((combo_box)); GType __t = ((ctk_combo_box_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; }))))) ; else
g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 1769, ((const char*) (__func__)), "CTK_IS_COMBO_BOX (combo_box)"
); } while (0)
;
1770 g_assert (BAUL_IS_FILE (file))do { if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (baul_file_get_type()); gboolean __r
; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; }))))) ; else
g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 1770, ((const char*) (__func__)), "BAUL_IS_FILE (file)"); }
while (0)
;
1771
1772 if (baul_file_is_gone (file)) {
1773 return;
1774 }
1775
1776 groups = baul_file_get_settable_group_names (file);
1777
1778 model = ctk_combo_box_get_model (combo_box);
1779 store = CTK_LIST_STORE (model)((((CtkListStore*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((model)), ((ctk_list_store_get_type ()))))))
;
1780 g_assert (CTK_IS_LIST_STORE (model))do { if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((model)); GType __t = ((ctk_list_store_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; }))))) ; else
g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 1780, ((const char*) (__func__)), "CTK_IS_LIST_STORE (model)"
); } while (0)
;
1781
1782 if (!tree_model_entries_equal (model, 0, groups)) {
1783 int group_index;
1784
1785 /* Clear the contents of ComboBox in a wacky way because there
1786 * is no function to clear all items and also no function to obtain
1787 * the number of items in a combobox.
1788 */
1789 ctk_list_store_clear (store);
1790
1791 for (node = groups, group_index = 0; node != NULL((void*)0); node = node->next, ++group_index) {
1792 const char *group_name;
1793
1794 group_name = (const char *)node->data;
1795 ctk_combo_box_text_append_text (CTK_COMBO_BOX_TEXT (combo_box)((((CtkComboBoxText*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((combo_box)), ((ctk_combo_box_text_get_type ()))))))
, group_name);
1796 }
1797 }
1798
1799 current_group_name = baul_file_get_group_name (file);
1800 current_group_index = tree_model_get_entry_index (model, 0, current_group_name);
1801
1802 /* If current group wasn't in list, we prepend it (with a separator).
1803 * This can happen if the current group is an id with no matching
1804 * group in the groups file.
1805 */
1806 if (current_group_index < 0 && current_group_name != NULL((void*)0)) {
1807 if (groups != NULL((void*)0)) {
1808 /* add separator */
1809 ctk_combo_box_text_prepend_text (CTK_COMBO_BOX_TEXT (combo_box)((((CtkComboBoxText*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((combo_box)), ((ctk_combo_box_text_get_type ()))))))
, "-");
1810 }
1811
1812 ctk_combo_box_text_prepend_text (CTK_COMBO_BOX_TEXT (combo_box)((((CtkComboBoxText*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((combo_box)), ((ctk_combo_box_text_get_type ()))))))
, current_group_name);
1813 current_group_index = 0;
1814 }
1815 ctk_combo_box_set_active (combo_box, current_group_index);
1816
1817 g_free (current_group_name);
1818 g_list_free_full (groups, g_free);
1819}
1820
1821static gboolean
1822combo_box_row_separator_func (CtkTreeModel *model,
1823 CtkTreeIter *iter,
1824 gpointer data G_GNUC_UNUSED__attribute__ ((__unused__)))
1825{
1826 gchar *text;
1827 gboolean ret;
1828
1829 ctk_tree_model_get (model, iter, 0, &text, -1);
1830
1831 if (text == NULL((void*)0)) {
1832 return FALSE(0);
1833 }
1834
1835 if (strcmp (text, "-") == 0) {
1836 ret = TRUE(!(0));
1837 } else {
1838 ret = FALSE(0);
1839 }
1840
1841 g_free (text);
1842 return ret;
1843}
1844
1845static CtkComboBox *
1846attach_combo_box (CtkGrid *grid,
1847 CtkWidget *sibling,
1848 gboolean two_columns)
1849{
1850 CtkWidget *combo_box;
1851
1852 if (!two_columns) {
1853 combo_box = ctk_combo_box_text_new ();
1854 } else {
1855 CtkTreeModel *model;
1856 CtkCellRenderer *renderer;
1857
1858 model = CTK_TREE_MODEL (ctk_list_store_new (2, G_TYPE_STRING, G_TYPE_STRING))((((CtkTreeModel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((ctk_list_store_new (2, ((GType) ((16) << (2))), ((
GType) ((16) << (2)))))), ((ctk_tree_model_get_type ())
)))))
;
1859 combo_box = ctk_combo_box_new_with_model (model);
1860 g_object_unref (G_OBJECT (model)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((model)), (((GType) ((20) << (2))))))))
);
1861
1862 renderer = ctk_cell_renderer_text_new ();
1863 ctk_cell_layout_pack_start (CTK_CELL_LAYOUT (combo_box)((((CtkCellLayout*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((combo_box)), ((ctk_cell_layout_get_type ()))))))
, renderer, TRUE(!(0)));
1864 ctk_cell_layout_add_attribute (CTK_CELL_LAYOUT (combo_box)((((CtkCellLayout*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((combo_box)), ((ctk_cell_layout_get_type ()))))))
, renderer,
1865 "text", 0);
1866
1867 }
1868
1869 ctk_widget_set_halign (combo_box, CTK_ALIGN_START);
1870
1871 ctk_widget_show (combo_box);
1872
1873 ctk_combo_box_set_row_separator_func (CTK_COMBO_BOX (combo_box)((((CtkComboBox*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((combo_box)), ((ctk_combo_box_get_type ()))))))
,
1874 combo_box_row_separator_func,
1875 NULL((void*)0),
1876 NULL((void*)0));
1877
1878 ctk_grid_attach_next_to (grid, combo_box, sibling,
1879 CTK_POS_RIGHT, 1, 1);
1880
1881 return CTK_COMBO_BOX (combo_box)((((CtkComboBox*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((combo_box)), ((ctk_combo_box_get_type ()))))))
;
1882}
1883
1884static CtkComboBox*
1885attach_group_combo_box (CtkGrid *grid,
1886 CtkWidget *sibling,
1887 BaulFile *file)
1888{
1889 CtkComboBox *combo_box;
1890
1891 combo_box = attach_combo_box (grid, sibling, FALSE(0));
1892
1893 synch_groups_combo_box (combo_box, file);
1894
1895 /* Connect to signal to update menu when file changes. */
1896 g_signal_connect_object (file, "changed",
1897 G_CALLBACK (synch_groups_combo_box)((GCallback) (synch_groups_combo_box)),
1898 combo_box, G_CONNECT_SWAPPED);
1899 g_signal_connect_data (combo_box, "changed",
1900 G_CALLBACK (changed_group_callback)((GCallback) (changed_group_callback)),
1901 baul_file_ref (file),
1902 (GClosureNotify)baul_file_unref, 0);
1903
1904 return combo_box;
1905}
1906
1907static void
1908owner_change_callback (BaulFile *file,
1909 GFile *result_location G_GNUC_UNUSED__attribute__ ((__unused__)),
1910 GError *error,
1911 FMPropertiesWindow *window)
1912{
1913 char *owner;
1914
1915 g_assert (FM_IS_PROPERTIES_WINDOW (window))do { if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = (fm_properties_window_get_type());
gboolean __r; if (!__inst) __r = (0); else if (__inst->g_class
&& __inst->g_class->g_type == __t) __r = (!(0)
); else __r = g_type_check_instance_is_a (__inst, __t); __r; }
))))) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 1915, ((const char*) (__func__)), "FM_IS_PROPERTIES_WINDOW (window)"
); } while (0)
;
1916 g_assert (window->details->owner_change_file == file)do { if (window->details->owner_change_file == file) ; else
g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 1916, ((const char*) (__func__)), "window->details->owner_change_file == file"
); } while (0)
;
1917
1918 owner = window->details->owner_change_owner;
1919 g_assert (owner != NULL)do { if (owner != ((void*)0)) ; else g_assertion_message_expr
(((gchar*) 0), "fm-properties-window.c", 1919, ((const char*
) (__func__)), "owner != NULL"); } while (0)
;
1920
1921 /* Report the error if it's an error. */
1922 eel_timed_wait_stop ((EelCancelCallback) cancel_owner_change_callback, window);
1923 fm_report_error_setting_owner (file, error, CTK_WINDOW (window)((((CtkWindow*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((window)), ((ctk_window_get_type ()))))))
);
1924
1925 baul_file_unref (file);
1926 g_free (owner);
1927
1928 window->details->owner_change_file = NULL((void*)0);
1929 window->details->owner_change_owner = NULL((void*)0);
1930 g_object_unref (G_OBJECT (window)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((window)), (((GType) ((20) << (2))))))))
);
1931}
1932
1933static void
1934cancel_owner_change_callback (FMPropertiesWindow *window)
1935{
1936 BaulFile *file;
1937 char *owner;
1938
1939 file = window->details->owner_change_file;
1940 g_assert (BAUL_IS_FILE (file))do { if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (baul_file_get_type()); gboolean __r
; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; }))))) ; else
g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 1940, ((const char*) (__func__)), "BAUL_IS_FILE (file)"); }
while (0)
;
1941
1942 owner = window->details->owner_change_owner;
1943 g_assert (owner != NULL)do { if (owner != ((void*)0)) ; else g_assertion_message_expr
(((gchar*) 0), "fm-properties-window.c", 1943, ((const char*
) (__func__)), "owner != NULL"); } while (0)
;
1944
1945 baul_file_cancel (file, (BaulFileOperationCallback) owner_change_callback, window);
1946
1947 baul_file_unref (file);
1948 g_free (owner);
1949
1950 window->details->owner_change_file = NULL((void*)0);
1951 window->details->owner_change_owner = NULL((void*)0);
1952 g_object_unref (window);
1953}
1954
1955static gboolean
1956schedule_owner_change_timeout (FMPropertiesWindow *window)
1957{
1958 BaulFile *file;
1959 char *owner;
1960
1961 g_assert (FM_IS_PROPERTIES_WINDOW (window))do { if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = (fm_properties_window_get_type());
gboolean __r; if (!__inst) __r = (0); else if (__inst->g_class
&& __inst->g_class->g_type == __t) __r = (!(0)
); else __r = g_type_check_instance_is_a (__inst, __t); __r; }
))))) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 1961, ((const char*) (__func__)), "FM_IS_PROPERTIES_WINDOW (window)"
); } while (0)
;
1962
1963 file = window->details->owner_change_file;
1964 g_assert (BAUL_IS_FILE (file))do { if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (baul_file_get_type()); gboolean __r
; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; }))))) ; else
g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 1964, ((const char*) (__func__)), "BAUL_IS_FILE (file)"); }
while (0)
;
1965
1966 owner = window->details->owner_change_owner;
1967 g_assert (owner != NULL)do { if (owner != ((void*)0)) ; else g_assertion_message_expr
(((gchar*) 0), "fm-properties-window.c", 1967, ((const char*
) (__func__)), "owner != NULL"); } while (0)
;
1968
1969 eel_timed_wait_start
1970 ((EelCancelCallback) cancel_owner_change_callback,
1971 window,
1972 _("Cancel Owner Change?")gettext ("Cancel Owner Change?"),
1973 CTK_WINDOW (window)((((CtkWindow*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((window)), ((ctk_window_get_type ()))))))
);
1974
1975 baul_file_set_owner
1976 (file, owner,
1977 (BaulFileOperationCallback) owner_change_callback, window);
1978
1979 window->details->owner_change_timeout = 0;
1980 return FALSE(0);
1981}
1982
1983static void
1984schedule_owner_change (FMPropertiesWindow *window,
1985 BaulFile *file,
1986 const char *owner)
1987{
1988 g_assert (FM_IS_PROPERTIES_WINDOW (window))do { if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = (fm_properties_window_get_type());
gboolean __r; if (!__inst) __r = (0); else if (__inst->g_class
&& __inst->g_class->g_type == __t) __r = (!(0)
); else __r = g_type_check_instance_is_a (__inst, __t); __r; }
))))) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 1988, ((const char*) (__func__)), "FM_IS_PROPERTIES_WINDOW (window)"
); } while (0)
;
1989 g_assert (window->details->owner_change_owner == NULL)do { if (window->details->owner_change_owner == ((void*
)0)) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 1989, ((const char*) (__func__)), "window->details->owner_change_owner == NULL"
); } while (0)
;
1990 g_assert (window->details->owner_change_file == NULL)do { if (window->details->owner_change_file == ((void*)
0)) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 1990, ((const char*) (__func__)), "window->details->owner_change_file == NULL"
); } while (0)
;
1991 g_assert (BAUL_IS_FILE (file))do { if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (baul_file_get_type()); gboolean __r
; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; }))))) ; else
g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 1991, ((const char*) (__func__)), "BAUL_IS_FILE (file)"); }
while (0)
;
1992
1993 window->details->owner_change_file = baul_file_ref (file);
1994 window->details->owner_change_owner = g_strdup (owner)g_strdup_inline (owner);
1995 g_object_ref (G_OBJECT (window))((__typeof__ (((((GObject*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((window)), (((GType) ((20) << (2)))
))))))) (g_object_ref) (((((GObject*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((window)), (((GType) ((20) << (2)))
)))))))
;
1996 window->details->owner_change_timeout =
1997 g_timeout_add (CHOWN_CHGRP_TIMEOUT300,
1998 (GSourceFunc) schedule_owner_change_timeout,
1999 window);
2000}
2001
2002static void
2003unschedule_or_cancel_owner_change (FMPropertiesWindow *window)
2004{
2005 BaulFile *file;
2006 char *owner;
2007
2008 g_assert (FM_IS_PROPERTIES_WINDOW (window))do { if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = (fm_properties_window_get_type());
gboolean __r; if (!__inst) __r = (0); else if (__inst->g_class
&& __inst->g_class->g_type == __t) __r = (!(0)
); else __r = g_type_check_instance_is_a (__inst, __t); __r; }
))))) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 2008, ((const char*) (__func__)), "FM_IS_PROPERTIES_WINDOW (window)"
); } while (0)
;
2009
2010 file = window->details->owner_change_file;
2011 owner = window->details->owner_change_owner;
2012
2013 g_assert ((file == NULL && owner == NULL) ||do { if ((file == ((void*)0) && owner == ((void*)0)) ||
(file != ((void*)0) && owner != ((void*)0))) ; else g_assertion_message_expr
(((gchar*) 0), "fm-properties-window.c", 2014, ((const char*
) (__func__)), "(file == NULL && owner == NULL) || (file != NULL && owner != NULL)"
); } while (0)
2014 (file != NULL && owner != NULL))do { if ((file == ((void*)0) && owner == ((void*)0)) ||
(file != ((void*)0) && owner != ((void*)0))) ; else g_assertion_message_expr
(((gchar*) 0), "fm-properties-window.c", 2014, ((const char*
) (__func__)), "(file == NULL && owner == NULL) || (file != NULL && owner != NULL)"
); } while (0)
;
2015
2016 if (file != NULL((void*)0)) {
2017 g_assert (BAUL_IS_FILE (file))do { if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (baul_file_get_type()); gboolean __r
; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; }))))) ; else
g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 2017, ((const char*) (__func__)), "BAUL_IS_FILE (file)"); }
while (0)
;
2018
2019 if (window->details->owner_change_timeout == 0) {
2020 baul_file_cancel (file,
2021 (BaulFileOperationCallback) owner_change_callback, window);
2022 eel_timed_wait_stop ((EelCancelCallback) cancel_owner_change_callback, window);
2023 }
2024
2025 baul_file_unref (file);
2026 g_free (owner);
2027
2028 window->details->owner_change_file = NULL((void*)0);
2029 window->details->owner_change_owner = NULL((void*)0);
2030 g_object_unref (G_OBJECT (window)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((window)), (((GType) ((20) << (2))))))))
);
2031 }
2032
2033 if (window->details->owner_change_timeout > 0) {
2034 g_assert (file != NULL)do { if (file != ((void*)0)) ; else g_assertion_message_expr (
((gchar*) 0), "fm-properties-window.c", 2034, ((const char*) (
__func__)), "file != NULL"); } while (0)
;
2035 g_source_remove (window->details->owner_change_timeout);
2036 window->details->owner_change_timeout = 0;
2037 }
2038}
2039
2040static void
2041changed_owner_callback (CtkComboBox *combo_box, BaulFile* file)
2042{
2043 char *owner_text;
2044 char **name_array;
2045 char *new_owner;
2046 char *cur_owner;
2047
2048 g_assert (CTK_IS_COMBO_BOX (combo_box))do { if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((combo_box)); GType __t = ((ctk_combo_box_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; }))))) ; else
g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 2048, ((const char*) (__func__)), "CTK_IS_COMBO_BOX (combo_box)"
); } while (0)
;
2049 g_assert (BAUL_IS_FILE (file))do { if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (baul_file_get_type()); gboolean __r
; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; }))))) ; else
g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 2049, ((const char*) (__func__)), "BAUL_IS_FILE (file)"); }
while (0)
;
2050
2051 owner_text = combo_box_get_active_entry (combo_box, 0);
2052 if (! owner_text)
2053 return;
2054 name_array = g_strsplit (owner_text, " - ", 2);
2055 new_owner = name_array[0];
2056 g_free (owner_text);
2057 cur_owner = baul_file_get_owner_name (file);
2058
2059 if (strcmp (new_owner, cur_owner) != 0) {
2060 FMPropertiesWindow *window;
2061
2062 /* Try to change file owner. If this fails, complain to user. */
2063 window = FM_PROPERTIES_WINDOW (ctk_widget_get_ancestor (CTK_WIDGET (combo_box), CTK_TYPE_WINDOW))((((FMPropertiesWindow*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((ctk_widget_get_ancestor (((((CtkWidget*) (
void *) g_type_check_instance_cast ((GTypeInstance*) ((combo_box
)), ((ctk_widget_get_type ())))))), (ctk_window_get_type ()))
)), (fm_properties_window_get_type())))))
;
2064
2065 unschedule_or_cancel_owner_change (window);
2066 schedule_owner_change (window, file, new_owner);
2067 }
2068 g_strfreev (name_array);
2069 g_free (cur_owner);
2070}
2071
2072static void
2073synch_user_menu (CtkComboBox *combo_box, BaulFile *file)
2074{
2075 GList *users;
2076 GList *node;
2077 CtkTreeModel *model;
2078 CtkListStore *store;
2079 CtkTreeIter iter;
2080 char *user_name;
2081 char *owner_name;
2082 int owner_index;
2083 char **name_array;
2084
2085 g_assert (CTK_IS_COMBO_BOX (combo_box))do { if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((combo_box)); GType __t = ((ctk_combo_box_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; }))))) ; else
g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 2085, ((const char*) (__func__)), "CTK_IS_COMBO_BOX (combo_box)"
); } while (0)
;
2086 g_assert (BAUL_IS_FILE (file))do { if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = (baul_file_get_type()); gboolean __r
; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; }))))) ; else
g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 2086, ((const char*) (__func__)), "BAUL_IS_FILE (file)"); }
while (0)
;
2087
2088 if (baul_file_is_gone (file)) {
2089 return;
2090 }
2091
2092 users = baul_get_user_names ();
2093
2094 model = ctk_combo_box_get_model (combo_box);
2095 store = CTK_LIST_STORE (model)((((CtkListStore*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((model)), ((ctk_list_store_get_type ()))))))
;
2096 g_assert (CTK_IS_LIST_STORE (model))do { if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((model)); GType __t = ((ctk_list_store_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; }))))) ; else
g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 2096, ((const char*) (__func__)), "CTK_IS_LIST_STORE (model)"
); } while (0)
;
2097
2098 if (!tree_model_entries_equal (model, 1, users)) {
2099 int user_index;
2100
2101 /* Clear the contents of ComboBox in a wacky way because there
2102 * is no function to clear all items and also no function to obtain
2103 * the number of items in a combobox.
2104 */
2105 ctk_list_store_clear (store);
2106
2107 for (node = users, user_index = 0; node != NULL((void*)0); node = node->next, ++user_index) {
2108 char *combo_text;
2109
2110 user_name = (char *)node->data;
2111
2112 name_array = g_strsplit (user_name, "\n", 2);
2113 if (name_array[1] != NULL((void*)0)) {
2114 combo_text = g_strdup_printf ("%s - %s", name_array[0], name_array[1]);
2115 } else {
2116 combo_text = g_strdup (name_array[0])g_strdup_inline (name_array[0]);
2117 }
2118
2119 ctk_list_store_append (store, &iter);
2120 ctk_list_store_set (store, &iter,
2121 0, combo_text,
2122 1, user_name,
2123 -1);
2124
2125 g_strfreev (name_array);
2126 g_free (combo_text);
2127 }
2128 }
2129
2130 owner_name = baul_file_get_string_attribute (file, "owner");
2131 owner_index = tree_model_get_entry_index (model, 0, owner_name);
2132
2133 /* If owner wasn't in list, we prepend it (with a separator).
2134 * This can happen if the owner is an id with no matching
2135 * identifier in the passwords file.
2136 */
2137 if (owner_index < 0 && owner_name != NULL((void*)0)) {
2138 if (users != NULL((void*)0)) {
2139 /* add separator */
2140 ctk_list_store_prepend (store, &iter);
2141 ctk_list_store_set (store, &iter,
2142 0, "-",
2143 1, NULL((void*)0),
2144 -1);
2145 }
2146
2147 name_array = g_strsplit (owner_name, " - ", 2);
2148 if (name_array[1] != NULL((void*)0)) {
2149 user_name = g_strdup_printf ("%s\n%s", name_array[0], name_array[1]);
2150 } else {
2151 user_name = g_strdup (name_array[0])g_strdup_inline (name_array[0]);
2152 }
2153 owner_index = 0;
2154
2155 ctk_list_store_prepend (store, &iter);
2156 ctk_list_store_set (store, &iter,
2157 0, owner_name,
2158 1, user_name,
2159 -1);
2160
2161 g_free (user_name);
2162 g_strfreev (name_array);
2163 }
2164
2165 ctk_combo_box_set_active (combo_box, owner_index);
2166
2167 g_free (owner_name);
2168 g_list_free_full (users, g_free);
2169}
2170
2171static CtkComboBox*
2172attach_owner_combo_box (CtkGrid *grid,
2173 CtkWidget *sibling,
2174 BaulFile *file)
2175{
2176 CtkComboBox *combo_box;
2177
2178 combo_box = attach_combo_box (grid, sibling, TRUE(!(0)));
2179
2180 synch_user_menu (combo_box, file);
2181
2182 /* Connect to signal to update menu when file changes. */
2183 g_signal_connect_object (file, "changed",
2184 G_CALLBACK (synch_user_menu)((GCallback) (synch_user_menu)),
2185 combo_box, G_CONNECT_SWAPPED);
2186 g_signal_connect_data (combo_box, "changed",
2187 G_CALLBACK (changed_owner_callback)((GCallback) (changed_owner_callback)),
2188 baul_file_ref (file),
2189 (GClosureNotify)baul_file_unref, 0);
2190
2191 return combo_box;
2192}
2193
2194static gboolean
2195file_has_prefix (BaulFile *file,
2196 GList *prefix_candidates)
2197{
2198 GList *p;
2199 GFile *location, *candidate_location;
2200
2201 location = baul_file_get_location (file);
2202
2203 for (p = prefix_candidates; p != NULL((void*)0); p = p->next) {
2204 if (file == p->data) {
2205 continue;
2206 }
2207
2208 candidate_location = baul_file_get_location (BAUL_FILE (p->data)((((BaulFile*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((p->data)), (baul_file_get_type())))))
);
2209 if (g_file_has_prefix (location, candidate_location)) {
2210 g_object_unref (location);
2211 g_object_unref (candidate_location);
2212 return TRUE(!(0));
2213 }
2214 g_object_unref (candidate_location);
2215 }
2216
2217 g_object_unref (location);
2218
2219 return FALSE(0);
2220}
2221
2222static void
2223directory_contents_value_field_update (FMPropertiesWindow *window)
2224{
2225 BaulRequestStatus file_status, status;
2226 char *text, *temp;
2227 guint directory_count;
2228 guint file_count;
2229 guint total_count;
2230 guint unreadable_directory_count;
2231 goffset total_size;
2232 goffset total_size_on_disk;
2233 gboolean used_two_lines;
2234 GList *l;
2235 guint file_unreadable;
2236 goffset file_size;
2237 goffset file_size_on_disk;
2238 BaulFile *file = NULL((void*)0);
2239
2240 g_assert (FM_IS_PROPERTIES_WINDOW (window))do { if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = (fm_properties_window_get_type());
gboolean __r; if (!__inst) __r = (0); else if (__inst->g_class
&& __inst->g_class->g_type == __t) __r = (!(0)
); else __r = g_type_check_instance_is_a (__inst, __t); __r; }
))))) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 2240, ((const char*) (__func__)), "FM_IS_PROPERTIES_WINDOW (window)"
); } while (0)
;
2241
2242 status = BAUL_REQUEST_DONE;
2243 file_status = BAUL_REQUEST_NOT_STARTED;
2244 total_count = window->details->total_count;
2245 total_size = window->details->total_size;
2246 total_size_on_disk = window->details->total_size_on_disk;
2247 unreadable_directory_count = FALSE(0);
2248
2249 for (l = window->details->target_files; l; l = l->next) {
2250 file = BAUL_FILE (l->data)((((BaulFile*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((l->data)), (baul_file_get_type())))))
;
2251
2252 if (file_has_prefix (file, window->details->target_files)) {
2253 /* don't count nested files twice */
2254 continue;
2255 }
2256
2257 if (baul_file_is_directory (file)) {
2258 file_status = baul_file_get_deep_counts (file,
2259 &directory_count,
2260 &file_count,
2261 &file_unreadable,
2262 &file_size,
2263 &file_size_on_disk,
2264 TRUE(!(0)));
2265 total_count += (file_count + directory_count);
2266 total_size += file_size;
2267 total_size_on_disk += file_size_on_disk;
2268
2269 if (file_unreadable) {
2270 unreadable_directory_count = TRUE(!(0));
2271 }
2272
2273 if (file_status != BAUL_REQUEST_DONE) {
2274 status = file_status;
2275 }
2276 } else {
2277 ++total_count;
2278 total_size += baul_file_get_size (file);
2279 total_size_on_disk += baul_file_get_size_on_disk (file);
2280 }
2281 }
2282
2283 /* If we've already displayed the total once, don't do another visible
2284 * count-up if the deep_count happens to get invalidated.
2285 * But still display the new total, since it might have changed.
2286 */
2287 if (window->details->deep_count_finished &&
2288 status != BAUL_REQUEST_DONE) {
2289 return;
2290 }
2291
2292 text = NULL((void*)0);
2293 used_two_lines = FALSE(0);
2294
2295 if (total_count == 0) {
2296 switch (status) {
2297 case BAUL_REQUEST_DONE:
2298 if (unreadable_directory_count == 0) {
2299 text = g_strdup (_("nothing"))g_strdup_inline (gettext ("nothing"));
2300 } else {
2301 text = g_strdup (_("unreadable"))g_strdup_inline (gettext ("unreadable"));
2302 }
2303
2304 break;
2305 default:
2306 text = g_strdup ("...")g_strdup_inline ("...");
2307 }
2308 } else {
2309 char *size_str;
2310 char *size_on_disk_str;
2311
2312 if (g_settings_get_boolean (baul_preferences, BAUL_PREFERENCES_USE_IEC_UNITS"use-iec-units")) {
2313 size_str = g_format_size_full (total_size, G_FORMAT_SIZE_IEC_UNITS);
2314 size_on_disk_str = g_format_size_full (total_size_on_disk, G_FORMAT_SIZE_IEC_UNITS);
2315 } else {
2316 size_str = g_format_size (total_size);
2317 size_on_disk_str = g_format_size (total_size_on_disk);
2318 }
2319
2320 text = g_strdup_printf (ngettext("%'d item, with size %s (%s on disk)",
2321 "%'d items, totalling %s (%s on disk)",
2322 total_count),
2323 total_count, size_str, size_on_disk_str);
2324 g_free (size_str);
2325 g_free (size_on_disk_str);
2326
2327 if (unreadable_directory_count != 0) {
2328 temp = text;
2329 text = g_strconcat (temp, "\n",
2330 _("(some contents unreadable)")gettext ("(some contents unreadable)"),
2331 NULL((void*)0));
2332 g_free (temp);
2333 used_two_lines = TRUE(!(0));
2334 }
2335 }
2336
2337 ctk_label_set_text (window->details->directory_contents_value_field,
2338 text);
2339 g_free (text);
2340
2341 /* Also set the title field here, with a trailing carriage return &
2342 * space if the value field has two lines. This is a hack to get the
2343 * "Contents:" title to line up with the first line of the
2344 * 2-line value. Maybe there's a better way to do this, but I
2345 * couldn't think of one.
2346 */
2347 text = g_strdup (_("Contents:"))g_strdup_inline (gettext ("Contents:"));
2348 if (used_two_lines) {
2349 temp = text;
2350 text = g_strconcat (temp, "\n ", NULL((void*)0));
2351 g_free (temp);
2352 }
2353 ctk_label_set_text (window->details->directory_contents_title_field,
2354 text);
2355 g_free (text);
2356
2357 if (status == BAUL_REQUEST_DONE) {
2358 window->details->deep_count_finished = TRUE(!(0));
2359 }
2360}
2361
2362static gboolean
2363update_directory_contents_callback (gpointer data)
2364{
2365 FMPropertiesWindow *window;
2366
2367 window = FM_PROPERTIES_WINDOW (data)((((FMPropertiesWindow*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((data)), (fm_properties_window_get_type()))
)))
;
2368
2369 window->details->update_directory_contents_timeout_id = 0;
2370 directory_contents_value_field_update (window);
2371
2372 return FALSE(0);
2373}
2374
2375static void
2376schedule_directory_contents_update (FMPropertiesWindow *window)
2377{
2378 g_assert (FM_IS_PROPERTIES_WINDOW (window))do { if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = (fm_properties_window_get_type());
gboolean __r; if (!__inst) __r = (0); else if (__inst->g_class
&& __inst->g_class->g_type == __t) __r = (!(0)
); else __r = g_type_check_instance_is_a (__inst, __t); __r; }
))))) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 2378, ((const char*) (__func__)), "FM_IS_PROPERTIES_WINDOW (window)"
); } while (0)
;
2379
2380 if (window->details->update_directory_contents_timeout_id == 0) {
2381 window->details->update_directory_contents_timeout_id
2382 = g_timeout_add (DIRECTORY_CONTENTS_UPDATE_INTERVAL200,
2383 update_directory_contents_callback,
2384 window);
2385 }
2386}
2387
2388static CtkLabel *
2389attach_directory_contents_value_field (FMPropertiesWindow *window,
2390 CtkGrid *grid,
2391 CtkWidget *sibling)
2392{
2393 CtkLabel *value_field;
2394 GList *l;
2395 BaulFile *file = NULL((void*)0);
2396
2397 value_field = attach_value_label (grid, sibling, "");
2398
2399 g_assert (window->details->directory_contents_value_field == NULL)do { if (window->details->directory_contents_value_field
== ((void*)0)) ; else g_assertion_message_expr (((gchar*) 0)
, "fm-properties-window.c", 2399, ((const char*) (__func__)),
"window->details->directory_contents_value_field == NULL"
); } while (0)
;
2400 window->details->directory_contents_value_field = value_field;
2401
2402 ctk_label_set_line_wrap (value_field, TRUE(!(0)));
2403
2404 /* Fill in the initial value. */
2405 directory_contents_value_field_update (window);
2406
2407 for (l = window->details->target_files; l; l = l->next) {
2408 file = BAUL_FILE (l->data)((((BaulFile*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((l->data)), (baul_file_get_type())))))
;
2409 baul_file_recompute_deep_counts (file);
2410
2411 g_signal_connect_object (file,
2412 "updated_deep_count_in_progress",
2413 G_CALLBACK (schedule_directory_contents_update)((GCallback) (schedule_directory_contents_update)),
2414 window, G_CONNECT_SWAPPED);
2415 }
2416
2417 return value_field;
2418}
2419
2420static CtkLabel *
2421attach_title_field (CtkGrid *grid,
2422 const char *title)
2423{
2424 return attach_label (grid, NULL((void*)0), title, FALSE(0), FALSE(0), TRUE(!(0)));
2425}
2426
2427
2428
2429#define INCONSISTENT_STATE_STRING"\xE2\x80\x92" \
2430 "\xE2\x80\x92"
2431
2432static void
2433append_title_value_pair (FMPropertiesWindow *window,
2434 CtkGrid *grid,
2435 const char *title,
2436 const char *file_attribute_name,
2437 const char *inconsistent_state,
2438 gboolean show_original)
2439{
2440 CtkLabel *title_label;
2441 CtkWidget *value;
2442
2443 title_label = attach_title_field (grid, title);
2444 value = attach_value_field (window, grid, CTK_WIDGET (title_label)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((title_label)), ((ctk_widget_get_type ()))))))
,
2445 file_attribute_name,
2446 inconsistent_state,
2447 show_original);
2448 ctk_label_set_mnemonic_widget (title_label, value);
2449}
2450
2451static void
2452append_title_and_ellipsizing_value (FMPropertiesWindow *window,
2453 CtkGrid *grid,
2454 const char *title,
2455 const char *file_attribute_name,
2456 const char *inconsistent_state,
2457 gboolean show_original)
2458{
2459 CtkLabel *title_label;
2460 CtkWidget *value;
2461
2462 title_label = attach_title_field (grid, title);
2463 value = attach_ellipsizing_value_field (window, grid,
2464 CTK_WIDGET (title_label)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((title_label)), ((ctk_widget_get_type ()))))))
,
2465 file_attribute_name,
2466 inconsistent_state,
2467 show_original);
2468 ctk_label_set_mnemonic_widget (title_label, value);
2469}
2470
2471static void
2472append_directory_contents_fields (FMPropertiesWindow *window,
2473 CtkGrid *grid)
2474{
2475 CtkLabel *title_field, *value_field;
2476 title_field = attach_title_field (grid, "");
2477 window->details->directory_contents_title_field = title_field;
2478 ctk_label_set_line_wrap (title_field, TRUE(!(0)));
2479
2480 value_field = attach_directory_contents_value_field
2481 (window, grid, CTK_WIDGET (title_field)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((title_field)), ((ctk_widget_get_type ()))))))
);
2482
2483 ctk_label_set_mnemonic_widget (title_field, CTK_WIDGET(value_field)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((value_field)), ((ctk_widget_get_type ()))))))
);
2484}
2485
2486static CtkWidget *
2487create_page_with_hbox (CtkNotebook *notebook,
2488 const char *title)
2489{
2490 CtkWidget *hbox;
2491
2492 g_assert (CTK_IS_NOTEBOOK (notebook))do { if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((notebook)); GType __t = ((ctk_notebook_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; }))))) ; else
g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 2492, ((const char*) (__func__)), "CTK_IS_NOTEBOOK (notebook)"
); } while (0)
;
2493 g_assert (title != NULL)do { if (title != ((void*)0)) ; else g_assertion_message_expr
(((gchar*) 0), "fm-properties-window.c", 2493, ((const char*
) (__func__)), "title != NULL"); } while (0)
;
2494
2495 hbox = ctk_box_new (CTK_ORIENTATION_HORIZONTAL, 0);
2496 ctk_widget_show (hbox);
2497 ctk_container_set_border_width (CTK_CONTAINER (hbox)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((hbox)), ((ctk_container_get_type ()))))))
, 12);
2498 ctk_box_set_spacing (CTK_BOX (hbox)((((CtkBox*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((hbox)), ((ctk_box_get_type ()))))))
, 12);
2499 ctk_notebook_append_page (notebook, hbox, ctk_label_new (title));
2500
2501 return hbox;
2502}
2503
2504static CtkWidget *
2505create_page_with_vbox (CtkNotebook *notebook,
2506 const char *title)
2507{
2508 CtkWidget *vbox;
2509
2510 g_assert (CTK_IS_NOTEBOOK (notebook))do { if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((notebook)); GType __t = ((ctk_notebook_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; }))))) ; else
g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 2510, ((const char*) (__func__)), "CTK_IS_NOTEBOOK (notebook)"
); } while (0)
;
2511 g_assert (title != NULL)do { if (title != ((void*)0)) ; else g_assertion_message_expr
(((gchar*) 0), "fm-properties-window.c", 2511, ((const char*
) (__func__)), "title != NULL"); } while (0)
;
2512
2513 vbox = ctk_box_new (CTK_ORIENTATION_VERTICAL, 0);
2514 ctk_widget_show (vbox);
2515
2516 ctk_container_set_border_width (CTK_CONTAINER (vbox)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((vbox)), ((ctk_container_get_type ()))))))
, 12);
2517 ctk_notebook_append_page (notebook, vbox, ctk_label_new (title));
2518
2519 return vbox;
2520}
2521
2522static CtkWidget *
2523append_blank_row (CtkGrid *grid)
2524{
2525 return CTK_WIDGET (attach_title_field (grid, ""))((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((attach_title_field (grid, ""))), ((ctk_widget_get_type (
)))))))
;
2526}
2527
2528static void
2529append_blank_slim_row (CtkGrid *grid)
2530{
2531 CtkWidget *w;
2532 PangoAttribute *attribute;
2533 PangoAttrList *attr_list;
2534
2535 attr_list = pango_attr_list_new ();
2536 attribute = pango_attr_scale_new (0.30);
2537 pango_attr_list_insert (attr_list, attribute);
2538
2539 w = ctk_label_new (NULL((void*)0));
2540 ctk_label_set_attributes (CTK_LABEL (w)((((CtkLabel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((w)), ((ctk_label_get_type ()))))))
, attr_list);
2541 ctk_widget_show (w);
2542
2543 pango_attr_list_unref (attr_list);
2544
2545 ctk_container_add (CTK_CONTAINER (grid)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((grid)), ((ctk_container_get_type ()))))))
, w);
2546}
2547
2548static CtkWidget *
2549create_grid_with_standard_properties (void)
2550{
2551 CtkWidget *grid;
2552
2553 grid = ctk_grid_new ();
2554 ctk_container_set_border_width (CTK_CONTAINER (grid)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((grid)), ((ctk_container_get_type ()))))))
, 6);
2555 ctk_grid_set_row_spacing (CTK_GRID (grid)((((CtkGrid*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((grid)), ((ctk_grid_get_type ()))))))
, ROW_PAD6);
2556 ctk_grid_set_column_spacing (CTK_GRID (grid)((((CtkGrid*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((grid)), ((ctk_grid_get_type ()))))))
, 12);
2557 ctk_orientable_set_orientation (CTK_ORIENTABLE (grid)((((CtkOrientable*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((grid)), ((ctk_orientable_get_type ()))))))
, CTK_ORIENTATION_VERTICAL);
2558 ctk_widget_show (grid);
2559
2560 return grid;
2561}
2562
2563static gboolean
2564is_merged_trash_directory (BaulFile *file)
2565{
2566 char *file_uri;
2567 gboolean result;
2568
2569 file_uri = baul_file_get_uri (file);
2570 result = strcmp (file_uri, "trash:///") == 0;
2571 g_free (file_uri);
2572
2573 return result;
2574}
2575
2576static gboolean
2577is_computer_directory (BaulFile *file)
2578{
2579 char *file_uri;
2580 gboolean result;
2581
2582 file_uri = baul_file_get_uri (file);
2583 result = strcmp (file_uri, "computer:///") == 0;
2584 g_free (file_uri);
2585
2586 return result;
2587}
2588
2589static gboolean
2590is_network_directory (BaulFile *file)
2591{
2592 char *file_uri;
2593 gboolean result;
2594
2595 file_uri = baul_file_get_uri (file);
2596 result = strcmp (file_uri, "network:///") == 0;
2597 g_free (file_uri);
2598
2599 return result;
2600}
2601
2602static gboolean
2603is_burn_directory (BaulFile *file)
2604{
2605 char *file_uri;
2606 gboolean result;
2607
2608 file_uri = baul_file_get_uri (file);
2609 result = strcmp (file_uri, "burn:///") == 0;
2610 g_free (file_uri);
2611
2612 return result;
2613}
2614
2615static gboolean
2616should_show_custom_icon_buttons (FMPropertiesWindow *window)
2617{
2618 if (is_multi_file_window (window)) {
2619 return FALSE(0);
2620 }
2621
2622 return TRUE(!(0));
2623}
2624
2625static gboolean
2626should_show_file_type (FMPropertiesWindow *window)
2627{
2628 if (!is_multi_file_window (window)
2629 && (is_merged_trash_directory (get_target_file (window)) ||
2630 is_computer_directory (get_target_file (window)) ||
2631 is_network_directory (get_target_file (window)) ||
2632 is_burn_directory (get_target_file (window)))) {
2633 return FALSE(0);
2634 }
2635
2636
2637 return TRUE(!(0));
2638}
2639
2640static gboolean
2641should_show_location_info (FMPropertiesWindow *window)
2642{
2643 if (!is_multi_file_window (window)
2644 && (is_merged_trash_directory (get_target_file (window)) ||
2645 is_computer_directory (get_target_file (window)) ||
2646 is_network_directory (get_target_file (window)) ||
2647 is_burn_directory (get_target_file (window)))) {
2648 return FALSE(0);
2649 }
2650
2651 return TRUE(!(0));
2652}
2653
2654static gboolean
2655should_show_accessed_date (FMPropertiesWindow *window)
2656{
2657 /* Accessed date for directory seems useless. If we some
2658 * day decide that it is useful, we should separately
2659 * consider whether it's useful for "trash:".
2660 */
2661 if (file_list_all_directories (window->details->target_files)) {
2662 return FALSE(0);
2663 }
2664
2665 return TRUE(!(0));
2666}
2667
2668static gboolean
2669should_show_link_target (FMPropertiesWindow *window)
2670{
2671 if (!is_multi_file_window (window)
2672 && baul_file_is_symbolic_link (get_target_file (window))) {
2673 return TRUE(!(0));
2674 }
2675
2676 return FALSE(0);
2677}
2678
2679static gboolean
2680should_show_free_space (FMPropertiesWindow *window)
2681{
2682
2683 if (!is_multi_file_window (window)
2684 && (is_merged_trash_directory (get_target_file (window)) ||
2685 is_computer_directory (get_target_file (window)) ||
2686 is_network_directory (get_target_file (window)) ||
2687 is_burn_directory (get_target_file (window)))) {
2688 return FALSE(0);
2689 }
2690
2691 if (file_list_all_directories (window->details->target_files)) {
2692 return TRUE(!(0));
2693 }
2694
2695 return FALSE(0);
2696}
2697
2698static gboolean
2699should_show_volume_usage (FMPropertiesWindow *window)
2700{
2701 BaulFile *file;
2702 gboolean success = FALSE(0);
2703
2704 if (is_multi_file_window (window)) {
2705 return FALSE(0);
2706 }
2707
2708 file = get_original_file (window);
2709
2710 if (file == NULL((void*)0)) {
2711 return FALSE(0);
2712 }
2713
2714 if (baul_file_can_unmount (file)) {
2715 return TRUE(!(0));
2716 }
2717
2718#ifdef TODO_GIO
2719 /* Look at is_mountpoint for activation uri */
2720#endif
2721 return success;
2722}
2723
2724static void
2725paint_used_legend (CtkWidget *widget,
2726 cairo_t *cr,
2727 gpointer data)
2728{
2729 FMPropertiesWindow *window;
2730 gint width, height;
2731 CtkAllocation allocation;
2732
2733 ctk_widget_get_allocation (widget, &allocation);
2734
2735 width = allocation.width;
2736 height = allocation.height;
2737
2738 window = FM_PROPERTIES_WINDOW (data)((((FMPropertiesWindow*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((data)), (fm_properties_window_get_type()))
)))
;
2739
2740 cairo_rectangle (cr,
2741 2,
2742 2,
2743 width - 4,
2744 height - 4);
2745
2746 cdk_cairo_set_source_rgba (cr, &window->details->used_color);
2747 cairo_fill_preserve (cr);
2748
2749 cdk_cairo_set_source_rgba (cr, &window->details->used_stroke_color);
2750 cairo_stroke (cr);
2751}
2752
2753static void
2754paint_free_legend (CtkWidget *widget,
2755 cairo_t *cr, gpointer data)
2756{
2757 FMPropertiesWindow *window;
2758 gint width, height;
2759 CtkAllocation allocation;
2760
2761 window = FM_PROPERTIES_WINDOW (data)((((FMPropertiesWindow*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((data)), (fm_properties_window_get_type()))
)))
;
2762 ctk_widget_get_allocation (widget, &allocation);
2763
2764 width = allocation.width;
2765 height = allocation.height;
2766
2767 cairo_rectangle (cr,
2768 2,
2769 2,
2770 width - 4,
2771 height - 4);
2772
2773 cdk_cairo_set_source_rgba (cr, &window->details->free_color);
2774 cairo_fill_preserve(cr);
2775
2776 cdk_cairo_set_source_rgba (cr, &window->details->free_stroke_color);
2777 cairo_stroke (cr);
2778}
2779
2780static void
2781paint_pie_chart (CtkWidget *widget,
2782 cairo_t *cr,
2783 gpointer data)
2784{
2785
2786 FMPropertiesWindow *window;
2787 gint width, height;
2788 double free, used;
2789 double angle1, angle2, split, xc, yc, radius;
2790 CtkAllocation allocation;
2791
2792 window = FM_PROPERTIES_WINDOW (data)((((FMPropertiesWindow*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((data)), (fm_properties_window_get_type()))
)))
;
2793 ctk_widget_get_allocation (widget, &allocation);
2794
2795 width = allocation.width;
2796 height = allocation.height;
2797
2798
2799 free = (double)window->details->volume_free / (double)window->details->volume_capacity;
2800 used = 1.0 - free;
2801
2802 angle1 = free * 2 * G_PI3.1415926535897932384626433832795028841971693993751;
2803 angle2 = used * 2 * G_PI3.1415926535897932384626433832795028841971693993751;
2804 split = (2 * G_PI3.1415926535897932384626433832795028841971693993751 - angle1) * .5;
2805 xc = width / 2;
2806 yc = height / 2;
2807
2808 if (width < height) {
2809 radius = width / 2 - 8;
2810 } else {
2811 radius = height / 2 - 8;
2812 }
2813
2814 if (angle1 != 2 * G_PI3.1415926535897932384626433832795028841971693993751 && angle1 != 0) {
2815 angle1 = angle1 + split;
2816 }
2817
2818 if (angle2 != 2 * G_PI3.1415926535897932384626433832795028841971693993751 && angle2 != 0) {
2819 angle2 = angle2 - split;
2820 }
2821
2822 if (used > 0) {
2823 if (free != 0) {
2824 cairo_move_to (cr,xc,yc);
2825 }
2826
2827 cairo_arc (cr, xc, yc, radius, angle1, angle2);
2828
2829 if (free != 0) {
2830 cairo_line_to (cr,xc,yc);
2831 }
2832
2833 cdk_cairo_set_source_rgba (cr, &window->details->used_color);
2834 cairo_fill_preserve (cr);
2835
2836 cdk_cairo_set_source_rgba (cr, &window->details->used_stroke_color);
2837
2838 cairo_stroke (cr);
2839 }
2840
2841 if (free > 0) {
2842 if (used != 0) {
2843 cairo_move_to (cr,xc,yc);
2844 }
2845
2846 cairo_arc_negative (cr, xc, yc, radius, angle1, angle2);
2847
2848 if (used != 0) {
2849 cairo_line_to (cr,xc,yc);
2850 }
2851
2852
2853 cdk_cairo_set_source_rgba (cr, &window->details->free_color);
2854 cairo_fill_preserve(cr);
2855
2856 cdk_cairo_set_source_rgba (cr, &window->details->free_stroke_color);
2857
2858 cairo_stroke (cr);
2859 }
2860}
2861
2862
2863/* Copied from ctk/ctkstyle.c */
2864
2865static void
2866rgb_to_hls (gdouble *r,
2867 gdouble *g,
2868 gdouble *b)
2869{
2870 gdouble min;
2871 gdouble max;
2872 gdouble red;
2873 gdouble green;
2874 gdouble blue;
2875 gdouble h, l, s;
2876 gdouble delta;
2877
2878 red = *r;
2879 green = *g;
2880 blue = *b;
2881
2882 if (red > green)
2883 {
2884 if (red > blue)
2885 max = red;
2886 else
2887 max = blue;
2888
2889 if (green < blue)
2890 min = green;
2891 else
2892 min = blue;
2893 }
2894 else
2895 {
2896 if (green > blue)
2897 max = green;
2898 else
2899 max = blue;
2900
2901 if (red < blue)
2902 min = red;
2903 else
2904 min = blue;
2905 }
2906
2907 l = (max + min) / 2;
2908 s = 0;
2909 h = 0;
2910
2911 if (max != min)
2912 {
2913 if (l <= 0.5)
2914 s = (max - min) / (max + min);
2915 else
2916 s = (max - min) / (2 - max - min);
2917
2918 delta = max -min;
2919 if (red == max)
2920 h = (green - blue) / delta;
2921 else if (green == max)
2922 h = 2 + (blue - red) / delta;
2923 else if (blue == max)
2924 h = 4 + (red - green) / delta;
2925
2926 h *= 60;
2927 if (h < 0.0)
2928 h += 360;
2929 }
2930
2931 *r = h;
2932 *g = l;
2933 *b = s;
2934}
2935
2936static void
2937hls_to_rgb (gdouble *h,
2938 gdouble *l,
2939 gdouble *s)
2940{
2941 gdouble hue;
2942 gdouble lightness;
2943 gdouble saturation;
2944 gdouble m1, m2;
2945 gdouble r, g, b;
2946
2947 lightness = *l;
2948 saturation = *s;
2949
2950 if (lightness <= 0.5)
2951 m2 = lightness * (1 + saturation);
2952 else
2953 m2 = lightness + saturation - lightness * saturation;
2954 m1 = 2 * lightness - m2;
2955
2956 if (saturation == 0)
2957 {
2958 *h = lightness;
2959 *l = lightness;
2960 *s = lightness;
2961 }
2962 else
2963 {
2964 hue = *h + 120;
2965 while (hue > 360)
2966 hue -= 360;
2967 while (hue < 0)
2968 hue += 360;
2969
2970 if (hue < 60)
2971 r = m1 + (m2 - m1) * hue / 60;
2972 else if (hue < 180)
2973 r = m2;
2974 else if (hue < 240)
2975 r = m1 + (m2 - m1) * (240 - hue) / 60;
2976 else
2977 r = m1;
2978
2979 hue = *h;
2980 while (hue > 360)
2981 hue -= 360;
2982 while (hue < 0)
2983 hue += 360;
2984
2985 if (hue < 60)
2986 g = m1 + (m2 - m1) * hue / 60;
2987 else if (hue < 180)
2988 g = m2;
2989 else if (hue < 240)
2990 g = m1 + (m2 - m1) * (240 - hue) / 60;
2991 else
2992 g = m1;
2993
2994 hue = *h - 120;
2995 while (hue > 360)
2996 hue -= 360;
2997 while (hue < 0)
2998 hue += 360;
2999
3000 if (hue < 60)
3001 b = m1 + (m2 - m1) * hue / 60;
3002 else if (hue < 180)
3003 b = m2;
3004 else if (hue < 240)
3005 b = m1 + (m2 - m1) * (240 - hue) / 60;
3006 else
3007 b = m1;
3008
3009 *h = r;
3010 *l = g;
3011 *s = b;
3012 }
3013}
3014static void
3015_pie_style_shade (CdkRGBA *a,
3016 CdkRGBA *b,
3017 gdouble k)
3018{
3019 gdouble red;
3020 gdouble green;
3021 gdouble blue;
3022
3023 red = a->red;
3024 green = a->green;
3025 blue = a->blue;
3026
3027 rgb_to_hls (&red, &green, &blue);
3028
3029 green *= k;
3030 if (green > 1.0)
3031 green = 1.0;
3032 else if (green < 0.0)
3033 green = 0.0;
3034
3035 blue *= k;
3036 if (blue > 1.0)
3037 blue = 1.0;
3038 else if (blue < 0.0)
3039 blue = 0.0;
3040
3041 hls_to_rgb (&red, &green, &blue);
3042
3043 b->red = red;
3044 b->green = green;
3045 b->blue = blue;
3046 b->alpha = a->alpha;
3047}
3048
3049
3050static CtkWidget*
3051create_pie_widget (FMPropertiesWindow *window)
3052{
3053 BaulFile *file;
3054 CtkGrid *grid;
3055 CtkStyleContext *style;
3056
3057 CtkWidget *pie_canvas;
3058 CtkWidget *used_canvas;
3059 CtkWidget *used_label;
3060 CtkWidget *free_canvas;
3061 CtkWidget *free_label;
3062 CtkWidget *capacity_label;
3063 CtkWidget *fstype_label;
3064 gchar *capacity;
3065 gchar *used;
3066 gchar *free;
3067 gchar *uri;
3068 gchar *concat;
3069 GFile *location;
3070 GFileInfo *info;
3071
3072 if (g_settings_get_boolean (baul_preferences, BAUL_PREFERENCES_USE_IEC_UNITS"use-iec-units")) {
3073 capacity = g_format_size_full(window->details->volume_capacity, G_FORMAT_SIZE_IEC_UNITS);
3074 free = g_format_size_full(window->details->volume_free, G_FORMAT_SIZE_IEC_UNITS);
3075 used = g_format_size_full(window->details->volume_capacity - window->details->volume_free, G_FORMAT_SIZE_IEC_UNITS);
3076 }
3077 else {
3078 capacity = g_format_size(window->details->volume_capacity);
3079 free = g_format_size(window->details->volume_free);
3080 used = g_format_size(window->details->volume_capacity - window->details->volume_free);
3081 }
3082
3083 file = get_original_file (window);
3084
3085 uri = baul_file_get_activation_uri (file);
3086
3087 grid = CTK_GRID (ctk_grid_new ())((((CtkGrid*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((ctk_grid_new ())), ((ctk_grid_get_type ()))))))
;
3088 ctk_container_set_border_width (CTK_CONTAINER (grid)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((grid)), ((ctk_container_get_type ()))))))
, 5);
3089 ctk_grid_set_column_spacing (CTK_GRID (grid)((((CtkGrid*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((grid)), ((ctk_grid_get_type ()))))))
, 5);
3090 style = ctk_widget_get_style_context (CTK_WIDGET (grid)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((grid)), ((ctk_widget_get_type ()))))))
);
3091
3092 if (!ctk_style_context_lookup_color (style, "chart_rgba_1", &window->details->used_color)) {
3093
3094 window->details->used_color.red = USED_FILL_R0.988235294;
3095 window->details->used_color.green = USED_FILL_G0.91372549;
3096 window->details->used_color.blue = USED_FILL_B0.309803922;
3097 window->details->used_color.alpha = 1;
3098
3099 }
3100
3101
3102 if (!ctk_style_context_lookup_color (style, "chart_rgba_2", &window->details->free_color)) {
3103 window->details->free_color.red = FREE_FILL_R0.447058824;
3104 window->details->free_color.green = FREE_FILL_G0.623529412;
3105 window->details->free_color.blue = FREE_FILL_B0.811764706;
3106 window->details->free_color.alpha = 1;
3107
3108 }
3109
3110 _pie_style_shade (&window->details->used_color, &window->details->used_stroke_color, 0.7);
3111 _pie_style_shade (&window->details->free_color, &window->details->free_stroke_color, 0.7);
3112
3113 pie_canvas = ctk_drawing_area_new ();
3114 ctk_widget_set_size_request (pie_canvas, 200, 200);
3115
3116 used_canvas = ctk_drawing_area_new ();
3117
3118 ctk_widget_set_valign (used_canvas, CTK_ALIGN_CENTER);
3119 ctk_widget_set_halign (used_canvas, CTK_ALIGN_CENTER);
3120
3121 ctk_widget_set_size_request (used_canvas, 20, 20);
3122 /* Translators: "used" refers to the capacity of the filesystem */
3123 concat = g_strconcat (used, " ", _("used")gettext ("used"), NULL((void*)0));
3124 used_label = ctk_label_new (concat);
3125 g_free (concat);
3126
3127 free_canvas = ctk_drawing_area_new ();
3128
3129 ctk_widget_set_valign (free_canvas, CTK_ALIGN_CENTER);
3130 ctk_widget_set_halign (free_canvas, CTK_ALIGN_CENTER);
3131
3132 ctk_widget_set_size_request (free_canvas, 20, 20);
3133 /* Translators: "free" refers to the capacity of the filesystem */
3134 concat = g_strconcat (free, " ", _("free")gettext ("free"), NULL((void*)0));
3135 free_label = ctk_label_new (concat);
3136 g_free (concat);
3137
3138 concat = g_strconcat (_("Total capacity:")gettext ("Total capacity:"), " ", capacity, NULL((void*)0));
3139 capacity_label = ctk_label_new (concat);
3140 g_free (concat);
3141 fstype_label = ctk_label_new (NULL((void*)0));
3142
3143 location = g_file_new_for_uri (uri);
3144 info = g_file_query_filesystem_info (location, G_FILE_ATTRIBUTE_FILESYSTEM_TYPE"filesystem::type",
3145 NULL((void*)0), NULL((void*)0));
3146 if (info) {
3147 const char *fs_type;
3148
3149 fs_type = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_FILESYSTEM_TYPE"filesystem::type");
3150
3151 if (fs_type != NULL((void*)0)) {
3152 concat = g_strconcat (_("Filesystem type:")gettext ("Filesystem type:"), " ", fs_type, NULL((void*)0));
3153 ctk_label_set_text (CTK_LABEL (fstype_label)((((CtkLabel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((fstype_label)), ((ctk_label_get_type ()))))))
, concat);
3154 g_free (concat);
3155 }
3156
3157 g_object_unref (info);
3158 }
3159 g_object_unref (location);
3160
3161 g_free (uri);
3162 g_free (capacity);
3163 g_free (used);
3164 g_free (free);
3165
3166 ctk_container_add_with_properties (CTK_CONTAINER (grid)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((grid)), ((ctk_container_get_type ()))))))
, pie_canvas,
3167 "height", 4,
3168 NULL((void*)0));
3169 ctk_grid_attach_next_to (grid, used_canvas, pie_canvas,
3170 CTK_POS_RIGHT, 1, 1);
3171 ctk_grid_attach_next_to (grid, used_label, used_canvas,
3172 CTK_POS_RIGHT, 1, 1);
3173
3174 ctk_grid_attach_next_to (grid, free_canvas, used_canvas,
3175 CTK_POS_BOTTOM, 1, 1);
3176 ctk_grid_attach_next_to (grid, free_label, free_canvas,
3177 CTK_POS_RIGHT, 1, 1);
3178
3179 ctk_grid_attach_next_to (grid, capacity_label, free_canvas,
3180 CTK_POS_BOTTOM, 2, 1);
3181 ctk_grid_attach_next_to (grid, fstype_label, capacity_label,
3182 CTK_POS_BOTTOM, 2, 1);
3183
3184 g_signal_connect (pie_canvas, "draw",g_signal_connect_data ((pie_canvas), ("draw"), (((GCallback) (
paint_pie_chart))), (window), ((void*)0), (GConnectFlags) 0)
3185 G_CALLBACK (paint_pie_chart), window)g_signal_connect_data ((pie_canvas), ("draw"), (((GCallback) (
paint_pie_chart))), (window), ((void*)0), (GConnectFlags) 0)
;
3186 g_signal_connect (used_canvas, "draw",g_signal_connect_data ((used_canvas), ("draw"), (((GCallback)
(paint_used_legend))), (window), ((void*)0), (GConnectFlags)
0)
3187 G_CALLBACK (paint_used_legend), window)g_signal_connect_data ((used_canvas), ("draw"), (((GCallback)
(paint_used_legend))), (window), ((void*)0), (GConnectFlags)
0)
;
3188 g_signal_connect (free_canvas, "draw",g_signal_connect_data ((free_canvas), ("draw"), (((GCallback)
(paint_free_legend))), (window), ((void*)0), (GConnectFlags)
0)
3189 G_CALLBACK (paint_free_legend), window)g_signal_connect_data ((free_canvas), ("draw"), (((GCallback)
(paint_free_legend))), (window), ((void*)0), (GConnectFlags)
0)
;
3190
3191 return CTK_WIDGET (grid)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((grid)), ((ctk_widget_get_type ()))))))
;
3192
3193}
3194
3195static CtkWidget*
3196create_volume_usage_widget (FMPropertiesWindow *window)
3197{
3198 CtkWidget *piewidget;
3199 gchar *uri;
3200 BaulFile *file;
3201 GFile *location;
3202 GFileInfo *info;
3203
3204 file = get_original_file (window);
3205
3206 uri = baul_file_get_activation_uri (file);
3207
3208 location = g_file_new_for_uri (uri);
3209 info = g_file_query_filesystem_info (location, "filesystem::*", NULL((void*)0), NULL((void*)0));
3210
3211 if (info) {
3212 window->details->volume_capacity = g_file_info_get_attribute_uint64 (info, G_FILE_ATTRIBUTE_FILESYSTEM_SIZE"filesystem::size");
3213 window->details->volume_free = g_file_info_get_attribute_uint64 (info, G_FILE_ATTRIBUTE_FILESYSTEM_FREE"filesystem::free");
3214
3215 g_object_unref (info);
3216 } else {
3217 window->details->volume_capacity = 0;
3218 window->details->volume_free = 0;
3219 }
3220
3221 g_object_unref (location);
3222
3223 piewidget = create_pie_widget (window);
3224
3225 ctk_widget_show_all (piewidget);
3226
3227 return piewidget;
3228}
3229
3230static void
3231create_basic_page (FMPropertiesWindow *window)
3232{
3233 CtkGrid *grid;
3234 CtkWidget *icon_pixmap_widget;
3235 CtkWidget *hbox, *vbox;
3236
3237 hbox = create_page_with_hbox (window->details->notebook, _("Basic")gettext ("Basic"));
3238
3239 /* Icon pixmap */
3240
3241 icon_pixmap_widget = create_image_widget (
3242 window, should_show_custom_icon_buttons (window));
3243
3244 ctk_widget_set_halign (icon_pixmap_widget, CTK_ALIGN_END);
3245 ctk_widget_set_valign (icon_pixmap_widget, CTK_ALIGN_START);
3246 ctk_widget_show (icon_pixmap_widget);
3247
3248 ctk_box_pack_start (CTK_BOX (hbox)((((CtkBox*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((hbox)), ((ctk_box_get_type ()))))))
, icon_pixmap_widget, FALSE(0), FALSE(0), 0);
3249
3250 window->details->icon_chooser = NULL((void*)0);
3251
3252 vbox = ctk_box_new (CTK_ORIENTATION_VERTICAL, 0);
3253
3254 ctk_widget_show (vbox);
3255 ctk_container_add (CTK_CONTAINER (hbox)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((hbox)), ((ctk_container_get_type ()))))))
, vbox);
3256
3257 grid = CTK_GRID (create_grid_with_standard_properties ())((((CtkGrid*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((create_grid_with_standard_properties ())), ((ctk_grid_get_type
()))))))
;
3258 ctk_box_pack_start (CTK_BOX (vbox)((((CtkBox*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((vbox)), ((ctk_box_get_type ()))))))
, CTK_WIDGET (grid)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((grid)), ((ctk_widget_get_type ()))))))
, FALSE(0), FALSE(0), 0);
3259 window->details->basic_grid = grid;
3260
3261 /* Name label. The text will be determined in update_name_field */
3262 window->details->name_label = attach_title_field (grid, NULL((void*)0));
3263
3264 /* Name field */
3265 window->details->name_field = NULL((void*)0);
3266 update_name_field (window);
3267
3268 /* Start with name field selected, if it's an entry. */
3269 if (BAUL_IS_ENTRY (window->details->name_field)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(window->details->name_field)); GType __t = (baul_entry_get_type
()); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))
) {
3270 baul_entry_select_all (BAUL_ENTRY (window->details->name_field)((((BaulEntry*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((window->details->name_field)), (baul_entry_get_type
())))))
);
3271 ctk_widget_grab_focus (CTK_WIDGET (window->details->name_field)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((window->details->name_field)), ((ctk_widget_get_type
()))))))
);
3272 }
3273
3274 if (fm_ditem_page_should_show (window->details->target_files)) {
3275 CtkSizeGroup *label_size_group;
3276 CtkWidget *box;
3277
3278 label_size_group = ctk_size_group_new (CTK_SIZE_GROUP_HORIZONTAL);
3279 ctk_size_group_add_widget (label_size_group,
3280 CTK_WIDGET (window->details->name_label)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((window->details->name_label)), ((ctk_widget_get_type
()))))))
);
3281 box = fm_ditem_page_make_box (label_size_group,
3282 window->details->target_files);
3283
3284 ctk_grid_attach_next_to (window->details->basic_grid, box,
3285 CTK_WIDGET (window->details->name_label)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((window->details->name_label)), ((ctk_widget_get_type
()))))))
,
3286 CTK_POS_BOTTOM, 2, 1);
3287 }
3288
3289 if (should_show_file_type (window)) {
3290 append_title_value_pair (window,
3291 grid, _("Type:")gettext ("Type:"),
3292 "type",
3293 INCONSISTENT_STATE_STRING"\xE2\x80\x92",
3294 FALSE(0));
3295 }
3296
3297 if (should_show_link_target (window)) {
3298 append_title_and_ellipsizing_value (window, grid,
3299 _("Link target:")gettext ("Link target:"),
3300 "link_target",
3301 INCONSISTENT_STATE_STRING"\xE2\x80\x92",
3302 FALSE(0));
3303 }
3304
3305 if (is_multi_file_window (window) ||
3306 baul_file_is_directory (get_target_file (window))) {
3307 append_directory_contents_fields (window, grid);
3308 } else {
3309 append_title_value_pair (window, grid, _("Size:")gettext ("Size:"),
3310 "size_detail",
3311 INCONSISTENT_STATE_STRING"\xE2\x80\x92",
3312 FALSE(0));
3313 append_title_value_pair (window, grid, _("Size on Disk:")gettext ("Size on Disk:"),
3314 "size_on_disk_detail",
3315 INCONSISTENT_STATE_STRING"\xE2\x80\x92",
3316 FALSE(0));
3317 }
3318
3319 append_blank_row (grid);
3320
3321 if (should_show_location_info (window)) {
3322 append_title_and_ellipsizing_value (window, grid, _("Location:")gettext ("Location:"),
3323 "where",
3324 INCONSISTENT_STATE_STRING"\xE2\x80\x92",
3325 TRUE(!(0)));
3326
3327 append_title_and_ellipsizing_value (window, grid,
3328 _("Volume:")gettext ("Volume:"),
3329 "volume",
3330 INCONSISTENT_STATE_STRING"\xE2\x80\x92",
3331 FALSE(0));
3332 }
3333
3334 if (should_show_accessed_date (window)) {
3335 append_blank_row (grid);
3336
3337 append_title_value_pair (window, grid, _("Accessed:")gettext ("Accessed:"),
3338 "date_accessed",
3339 INCONSISTENT_STATE_STRING"\xE2\x80\x92",
3340 FALSE(0));
3341 append_title_value_pair (window, grid, _("Modified:")gettext ("Modified:"),
3342 "date_modified",
3343 INCONSISTENT_STATE_STRING"\xE2\x80\x92",
3344 FALSE(0));
3345 }
3346
3347 if (should_show_free_space (window)) {
3348 append_blank_row (grid);
3349
3350 append_title_value_pair (window, grid, _("Free space:")gettext ("Free space:"),
3351 "free_space",
3352 INCONSISTENT_STATE_STRING"\xE2\x80\x92",
3353 FALSE(0));
3354 }
3355
3356 if (should_show_volume_usage (window)) {
3357 CtkWidget *volume_usage;
3358
3359 volume_usage = create_volume_usage_widget (window);
3360 ctk_container_add_with_properties (CTK_CONTAINER (grid)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((grid)), ((ctk_container_get_type ()))))))
, volume_usage,
3361 "width", 2,
3362 NULL((void*)0));
3363 }
3364}
3365
3366static GHashTable *
3367get_initial_emblems (GList *files)
3368{
3369 GHashTable *ret;
3370 GList *l;
3371
3372 ret = g_hash_table_new_full (g_direct_hash,
3373 g_direct_equal,
3374 NULL((void*)0),
3375 (GDestroyNotify) eel_g_list_free_deep);
3376
3377 for (l = files; l != NULL((void*)0); l = l->next) {
3378 BaulFile *file;
3379 GList *keywords;
3380
3381 file = BAUL_FILE (l->data)((((BaulFile*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((l->data)), (baul_file_get_type())))))
;
3382
3383 keywords = baul_file_get_keywords (file);
3384 g_hash_table_insert (ret, file, keywords);
3385 }
3386
3387 return ret;
3388}
3389
3390static gboolean
3391files_has_directory (FMPropertiesWindow *window)
3392{
3393 GList *l;
3394
3395 for (l = window->details->target_files; l != NULL((void*)0); l = l->next) {
3396 BaulFile *file;
3397 file = BAUL_FILE (l->data)((((BaulFile*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((l->data)), (baul_file_get_type())))))
;
3398 if (baul_file_is_directory (file)) {
3399 return TRUE(!(0));
3400 }
3401
3402 }
3403
3404 return FALSE(0);
3405}
3406
3407static gboolean
3408files_has_changable_permissions_directory (FMPropertiesWindow *window)
3409{
3410 GList *l;
3411
3412 for (l = window->details->target_files; l != NULL((void*)0); l = l->next) {
3413 BaulFile *file;
3414 file = BAUL_FILE (l->data)((((BaulFile*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((l->data)), (baul_file_get_type())))))
;
3415 if (baul_file_is_directory (file) &&
3416 baul_file_can_get_permissions (file) &&
3417 baul_file_can_set_permissions (file)) {
3418 return TRUE(!(0));
3419 }
3420
3421 }
3422
3423 return FALSE(0);
3424}
3425
3426
3427static gboolean
3428files_has_file (FMPropertiesWindow *window)
3429{
3430 GList *l;
3431
3432 for (l = window->details->target_files; l != NULL((void*)0); l = l->next) {
3433 BaulFile *file;
3434 file = BAUL_FILE (l->data)((((BaulFile*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((l->data)), (baul_file_get_type())))))
;
3435 if (!baul_file_is_directory (file)) {
3436 return TRUE(!(0));
3437 }
3438
3439 }
3440
3441 return FALSE(0);
3442}
3443
3444
3445static void
3446create_emblems_page (FMPropertiesWindow *window)
3447{
3448 CtkWidget *emblems_table, *button, *scroller;
3449 GdkPixbuf *pixbuf;
3450 char *label;
3451 GList *icons, *l;
3452 BaulIconInfo *info;
3453 gint scale;
3454
3455 /* The emblems wrapped table */
3456 scroller = eel_scrolled_wrap_table_new (TRUE(!(0)), CTK_SHADOW_NONE, &emblems_table);
3457
3458 ctk_container_set_border_width (CTK_CONTAINER (emblems_table)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((emblems_table)), ((ctk_container_get_type ()))))))
, 12);
3459
3460 /* stop CTK 3.22 builds from ballooning the properties dialog to full screen height */
3461 ctk_scrolled_window_set_max_content_height (CTK_SCROLLED_WINDOW (scroller)((((CtkScrolledWindow*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((scroller)), ((ctk_scrolled_window_get_type
()))))))
, 300);
3462
3463 ctk_widget_show (scroller);
3464
3465 ctk_notebook_append_page (window->details->notebook,
3466 scroller, ctk_label_new (_("Emblems")gettext ("Emblems")));
3467
3468 icons = baul_emblem_list_available ();
3469 scale = ctk_widget_get_scale_factor (scroller);
3470
3471 window->details->initial_emblems = get_initial_emblems (window->details->original_files);
3472
3473 l = icons;
3474 while (l != NULL((void*)0)) {
3475 char *emblem_name;
3476
3477 emblem_name = l->data;
3478 l = l->next;
3479
3480 if (!baul_emblem_should_show_in_list (emblem_name)) {
3481 continue;
3482 }
3483
3484 info = baul_icon_info_lookup_from_name (emblem_name, BAUL_ICON_SIZE_SMALL32, scale);
3485 pixbuf = baul_icon_info_get_pixbuf_nodefault_at_size (info, BAUL_ICON_SIZE_SMALL32);
3486
3487 if (pixbuf == NULL((void*)0)) {
3488 continue;
3489 }
3490
3491 g_object_unref (info);
3492
3493 label = baul_emblem_get_keyword_from_icon_name (emblem_name);
3494
3495 button = eel_labeled_image_check_button_new (label, pixbuf);
3496 eel_labeled_image_set_fixed_image_height (EEL_LABELED_IMAGE (ctk_bin_get_child (CTK_BIN (button)))((((EelLabeledImage*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((ctk_bin_get_child (((((CtkBin*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((button)), ((ctk_bin_get_type ())))))))))
, (eel_labeled_image_get_type())))))
, STANDARD_EMBLEM_HEIGHT52 * scale);
3497 eel_labeled_image_set_spacing (EEL_LABELED_IMAGE (ctk_bin_get_child (CTK_BIN (button)))((((EelLabeledImage*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((ctk_bin_get_child (((((CtkBin*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((button)), ((ctk_bin_get_type ())))))))))
, (eel_labeled_image_get_type())))))
, EMBLEM_LABEL_SPACING2 * scale);
3498
3499 g_free (label);
3500 g_object_unref (pixbuf);
3501
3502 /* Attach parameters and signal handler. */
3503 g_object_set_data_full (G_OBJECT (button)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((button)), (((GType) ((20) << (2))))))))
, "baul_emblem_name",
3504 baul_emblem_get_keyword_from_icon_name (emblem_name), g_free);
3505
3506 window->details->emblem_buttons =
3507 g_list_append (window->details->emblem_buttons,
3508 button);
3509
3510 g_signal_connect_object (button, "toggled",
3511 G_CALLBACK (emblem_button_toggled)((GCallback) (emblem_button_toggled)),
3512 G_OBJECT (window)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((window)), (((GType) ((20) << (2))))))))
,
3513 0);
3514
3515 ctk_container_add (CTK_CONTAINER (emblems_table)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((emblems_table)), ((ctk_container_get_type ()))))))
, button);
3516 }
3517 g_list_free_full (icons, g_free);
3518 ctk_widget_show_all (emblems_table);
3519}
3520
3521static void
3522start_long_operation (FMPropertiesWindow *window)
3523{
3524 if (window->details->long_operation_underway == 0) {
3525 /* start long operation */
3526 CdkDisplay *display;
3527 CdkCursor * cursor;
3528
3529 display = ctk_widget_get_display (CTK_WIDGET (window)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((window)), ((ctk_widget_get_type ()))))))
);
3530 cursor = cdk_cursor_new_for_display (display, CDK_WATCH);
3531 cdk_window_set_cursor (ctk_widget_get_window (CTK_WIDGET (window)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((window)), ((ctk_widget_get_type ()))))))
), cursor);
3532 g_object_unref (cursor);
3533 }
3534 window->details->long_operation_underway ++;
3535}
3536
3537static void
3538end_long_operation (FMPropertiesWindow *window)
3539{
3540 if (ctk_widget_get_window (CTK_WIDGET (window)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((window)), ((ctk_widget_get_type ()))))))
) != NULL((void*)0) &&
3541 window->details->long_operation_underway == 1) {
3542 /* finished !! */
3543 cdk_window_set_cursor (ctk_widget_get_window (CTK_WIDGET (window)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((window)), ((ctk_widget_get_type ()))))))
), NULL((void*)0));
3544 }
3545 window->details->long_operation_underway--;
3546}
3547
3548static void
3549permission_change_callback (BaulFile *file,
3550 GFile *res_loc G_GNUC_UNUSED__attribute__ ((__unused__)),
3551 GError *error,
3552 gpointer callback_data)
3553{
3554 FMPropertiesWindow *window;
3555 g_assert (callback_data != NULL)do { if (callback_data != ((void*)0)) ; else g_assertion_message_expr
(((gchar*) 0), "fm-properties-window.c", 3555, ((const char*
) (__func__)), "callback_data != NULL"); } while (0)
;
3556
3557 window = FM_PROPERTIES_WINDOW (callback_data)((((FMPropertiesWindow*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((callback_data)), (fm_properties_window_get_type
())))))
;
3558 end_long_operation (window);
3559
3560 /* Report the error if it's an error. */
3561 fm_report_error_setting_permissions (file, error, NULL((void*)0));
3562
3563 g_object_unref (window);
3564}
3565
3566static void
3567update_permissions (FMPropertiesWindow *window,
3568 guint32 vfs_new_perm,
3569 guint32 vfs_mask,
3570 gboolean is_folder,
3571 gboolean apply_to_both_folder_and_dir,
3572 gboolean use_original)
3573{
3574 GList *l;
3575
3576 for (l = window->details->target_files; l != NULL((void*)0); l = l->next) {
3577 BaulFile *file;
3578 guint32 permissions;
3579
3580 file = BAUL_FILE (l->data)((((BaulFile*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((l->data)), (baul_file_get_type())))))
;
3581
3582 if (!baul_file_can_get_permissions (file)) {
3583 continue;
3584 }
3585
3586 if (!apply_to_both_folder_and_dir &&
3587 ((baul_file_is_directory (file) && !is_folder) ||
3588 (!baul_file_is_directory (file) && is_folder))) {
3589 continue;
3590 }
3591
3592 permissions = baul_file_get_permissions (file);
3593 if (use_original) {
3594 gpointer ptr;
3595 if (g_hash_table_lookup_extended (window->details->initial_permissions,
3596 file, NULL((void*)0), &ptr)) {
3597 permissions = (permissions & ~vfs_mask) | (GPOINTER_TO_INT (ptr)((gint) (glong) (ptr)) & vfs_mask);
3598 }
3599 } else {
3600 permissions = (permissions & ~vfs_mask) | vfs_new_perm;
3601 }
3602
3603 start_long_operation (window);
3604 g_object_ref (window)((__typeof__ (window)) (g_object_ref) (window));
3605 baul_file_set_permissions
3606 (file, permissions,
3607 permission_change_callback,
3608 window);
3609 }
3610}
3611
3612static gboolean
3613initial_permission_state_consistent (FMPropertiesWindow *window,
3614 guint32 mask,
3615 gboolean is_folder,
3616 gboolean both_folder_and_dir)
3617{
3618 GList *l;
3619 gboolean first;
3620 guint32 first_permissions;
3621
3622 first = TRUE(!(0));
3623 first_permissions = 0;
3624 for (l = window->details->target_files; l != NULL((void*)0); l = l->next) {
3625 BaulFile *file;
3626 guint32 permissions;
3627
3628 file = l->data;
3629
3630 if (!both_folder_and_dir &&
3631 ((baul_file_is_directory (file) && !is_folder) ||
3632 (!baul_file_is_directory (file) && is_folder))) {
3633 continue;
3634 }
3635
3636 permissions = GPOINTER_TO_INT (g_hash_table_lookup (window->details->initial_permissions,((gint) (glong) (g_hash_table_lookup (window->details->
initial_permissions, file)))
3637 file))((gint) (glong) (g_hash_table_lookup (window->details->
initial_permissions, file)))
;
3638
3639 if (first) {
3640 if ((permissions & mask) != mask &&
3641 (permissions & mask) != 0) {
3642 /* Not fully on or off -> inconsistent */
3643 return FALSE(0);
3644 }
3645
3646 first_permissions = permissions;
3647 first = FALSE(0);
3648
3649 } else if ((permissions & mask) != (first_permissions & mask)) {
3650 /* Not same permissions as first -> inconsistent */
3651 return FALSE(0);
3652 }
3653 }
3654 return TRUE(!(0));
3655}
3656
3657static void
3658permission_button_toggled (CtkToggleButton *button,
3659 FMPropertiesWindow *window)
3660{
3661 gboolean is_folder, is_special;
3662 guint32 permission_mask;
3663 gboolean inconsistent;
3664 gboolean on;
3665
3666 permission_mask = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (button),((gint) (glong) (g_object_get_data (((((GObject*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((button)), (((GType) ((20) << (2)))
))))), "permission")))
3667 "permission"))((gint) (glong) (g_object_get_data (((((GObject*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((button)), (((GType) ((20) << (2)))
))))), "permission")))
;
3668 is_folder = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (button),((gint) (glong) (g_object_get_data (((((GObject*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((button)), (((GType) ((20) << (2)))
))))), "is-folder")))
3669 "is-folder"))((gint) (glong) (g_object_get_data (((((GObject*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((button)), (((GType) ((20) << (2)))
))))), "is-folder")))
;
3670 is_special = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (button),((gint) (glong) (g_object_get_data (((((GObject*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((button)), (((GType) ((20) << (2)))
))))), "is-special")))
3671 "is-special"))((gint) (glong) (g_object_get_data (((((GObject*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((button)), (((GType) ((20) << (2)))
))))), "is-special")))
;
3672
3673 if (ctk_toggle_button_get_active (button)
3674 && !ctk_toggle_button_get_inconsistent (button)) {
3675 /* Go to the initial state unless the initial state was
3676 consistent, or we support recursive apply */
3677 inconsistent = TRUE(!(0));
3678 on = TRUE(!(0));
3679
3680 if (!window->details->has_recursive_apply &&
3681 initial_permission_state_consistent (window, permission_mask, is_folder, is_special)) {
3682 inconsistent = FALSE(0);
3683 on = TRUE(!(0));
3684 }
3685 } else if (ctk_toggle_button_get_inconsistent (button)
3686 && !ctk_toggle_button_get_active (button)) {
3687 inconsistent = FALSE(0);
3688 on = TRUE(!(0));
3689 } else {
3690 inconsistent = FALSE(0);
3691 on = FALSE(0);
3692 }
3693
3694 g_signal_handlers_block_by_func (G_OBJECT (button),g_signal_handlers_block_matched ((((((GObject*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((button)), (((GType) ((20) << (2)))
)))))), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (((GCallback) (permission_button_toggled
))), (window))
3695 G_CALLBACK (permission_button_toggled),g_signal_handlers_block_matched ((((((GObject*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((button)), (((GType) ((20) << (2)))
)))))), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (((GCallback) (permission_button_toggled
))), (window))
3696 window)g_signal_handlers_block_matched ((((((GObject*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((button)), (((GType) ((20) << (2)))
)))))), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (((GCallback) (permission_button_toggled
))), (window))
;
3697
3698 ctk_toggle_button_set_active (button, on);
3699 ctk_toggle_button_set_inconsistent (button, inconsistent);
3700
3701 g_signal_handlers_unblock_by_func (G_OBJECT (button),g_signal_handlers_unblock_matched ((((((GObject*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((button)), (((GType) ((20) << (2)))
)))))), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (((GCallback) (permission_button_toggled
))), (window))
3702 G_CALLBACK (permission_button_toggled),g_signal_handlers_unblock_matched ((((((GObject*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((button)), (((GType) ((20) << (2)))
)))))), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (((GCallback) (permission_button_toggled
))), (window))
3703 window)g_signal_handlers_unblock_matched ((((((GObject*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((button)), (((GType) ((20) << (2)))
)))))), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (((GCallback) (permission_button_toggled
))), (window))
;
3704
3705 update_permissions (window,
3706 on?permission_mask:0,
3707 permission_mask,
3708 is_folder,
3709 is_special,
3710 inconsistent);
3711}
3712
3713static void
3714permission_button_update (FMPropertiesWindow *window,
3715 CtkToggleButton *button)
3716{
3717 GList *l;
3718 gboolean all_set;
3719 gboolean all_unset;
3720 gboolean all_cannot_set;
3721 gboolean is_folder, is_special;
3722 gboolean no_match;
3723 gboolean sensitive;
3724 guint32 button_permission;
3725
3726 if (ctk_toggle_button_get_inconsistent (button) &&
3727 window->details->has_recursive_apply) {
3728 /* Never change from an inconsistent state if we have dirs, even
3729 * if the current state is now consistent, because its a useful
3730 * state for recursive apply.
3731 */
3732 return;
3733 }
3734
3735 button_permission = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (button),((gint) (glong) (g_object_get_data (((((GObject*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((button)), (((GType) ((20) << (2)))
))))), "permission")))
3736 "permission"))((gint) (glong) (g_object_get_data (((((GObject*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((button)), (((GType) ((20) << (2)))
))))), "permission")))
;
3737 is_folder = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (button),((gint) (glong) (g_object_get_data (((((GObject*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((button)), (((GType) ((20) << (2)))
))))), "is-folder")))
3738 "is-folder"))((gint) (glong) (g_object_get_data (((((GObject*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((button)), (((GType) ((20) << (2)))
))))), "is-folder")))
;
3739 is_special = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (button),((gint) (glong) (g_object_get_data (((((GObject*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((button)), (((GType) ((20) << (2)))
))))), "is-special")))
3740 "is-special"))((gint) (glong) (g_object_get_data (((((GObject*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((button)), (((GType) ((20) << (2)))
))))), "is-special")))
;
3741
3742 all_set = TRUE(!(0));
3743 all_unset = TRUE(!(0));
3744 all_cannot_set = TRUE(!(0));
3745 no_match = TRUE(!(0));
3746 for (l = window->details->target_files; l != NULL((void*)0); l = l->next) {
3747 BaulFile *file;
3748 guint32 file_permissions;
3749
3750 file = BAUL_FILE (l->data)((((BaulFile*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((l->data)), (baul_file_get_type())))))
;
3751
3752 if (!baul_file_can_get_permissions (file)) {
3753 continue;
3754 }
3755
3756 if (!is_special &&
3757 ((baul_file_is_directory (file) && !is_folder) ||
3758 (!baul_file_is_directory (file) && is_folder))) {
3759 continue;
3760 }
3761
3762 no_match = FALSE(0);
3763
3764 file_permissions = baul_file_get_permissions (file);
3765
3766 if ((file_permissions & button_permission) == button_permission) {
3767 all_unset = FALSE(0);
3768 } else if ((file_permissions & button_permission) == 0) {
3769 all_set = FALSE(0);
3770 } else {
3771 all_unset = FALSE(0);
3772 all_set = FALSE(0);
3773 }
3774
3775 if (baul_file_can_set_permissions (file)) {
3776 all_cannot_set = FALSE(0);
3777 }
3778 }
3779
3780 sensitive = !all_cannot_set;
3781 if (!is_folder) {
3782 /* Don't insitive files when we have recursive apply */
3783 sensitive |= window->details->has_recursive_apply;
3784 }
3785
3786
3787 g_signal_handlers_block_by_func (G_OBJECT (button),g_signal_handlers_block_matched ((((((GObject*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((button)), (((GType) ((20) << (2)))
)))))), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (((GCallback) (permission_button_toggled
))), (window))
3788 G_CALLBACK (permission_button_toggled),g_signal_handlers_block_matched ((((((GObject*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((button)), (((GType) ((20) << (2)))
)))))), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (((GCallback) (permission_button_toggled
))), (window))
3789 window)g_signal_handlers_block_matched ((((((GObject*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((button)), (((GType) ((20) << (2)))
)))))), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (((GCallback) (permission_button_toggled
))), (window))
;
3790
3791 ctk_toggle_button_set_active (button, !all_unset);
3792 /* if actually inconsistent, or default value for file buttons
3793 if no files are selected. (useful for recursive apply) */
3794 ctk_toggle_button_set_inconsistent (button,
3795 (!all_unset && !all_set) ||
3796 (!is_folder && no_match));
3797 ctk_widget_set_sensitive (CTK_WIDGET (button)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((button)), ((ctk_widget_get_type ()))))))
, sensitive);
3798
3799 g_signal_handlers_unblock_by_func (G_OBJECT (button),g_signal_handlers_unblock_matched ((((((GObject*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((button)), (((GType) ((20) << (2)))
)))))), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (((GCallback) (permission_button_toggled
))), (window))
3800 G_CALLBACK (permission_button_toggled),g_signal_handlers_unblock_matched ((((((GObject*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((button)), (((GType) ((20) << (2)))
)))))), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (((GCallback) (permission_button_toggled
))), (window))
3801 window)g_signal_handlers_unblock_matched ((((((GObject*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((button)), (((GType) ((20) << (2)))
)))))), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (((GCallback) (permission_button_toggled
))), (window))
;
3802}
3803
3804static void
3805set_up_permissions_checkbox (FMPropertiesWindow *window,
3806 CtkWidget *check_button,
3807 guint32 permission,
3808 gboolean is_folder)
3809{
3810 /* Load up the check_button with data we'll need when updating its state. */
3811 g_object_set_data (G_OBJECT (check_button)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((check_button)), (((GType) ((20) << (2))))))))
, "permission",
3812 GINT_TO_POINTER (permission)((gpointer) (glong) (permission)));
3813 g_object_set_data (G_OBJECT (check_button)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((check_button)), (((GType) ((20) << (2))))))))
, "properties_window",
3814 window);
3815 g_object_set_data (G_OBJECT (check_button)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((check_button)), (((GType) ((20) << (2))))))))
, "is-folder",
3816 GINT_TO_POINTER (is_folder)((gpointer) (glong) (is_folder)));
3817
3818 window->details->permission_buttons =
3819 g_list_prepend (window->details->permission_buttons,
3820 check_button);
3821
3822 g_signal_connect_object (check_button, "toggled",
3823 G_CALLBACK (permission_button_toggled)((GCallback) (permission_button_toggled)),
3824 window,
3825 0);
3826}
3827
3828static CtkWidget *
3829add_permissions_checkbox_with_label (FMPropertiesWindow *window,
3830 CtkGrid *grid,
3831 CtkWidget *sibling,
3832 const char *label,
3833 guint32 permission_to_check,
3834 CtkLabel *label_for,
3835 gboolean is_folder)
3836{
3837 CtkWidget *check_button;
3838 gboolean a11y_enabled;
3839
3840 check_button = ctk_check_button_new_with_mnemonic (label);
3841 ctk_widget_show (check_button);
3842 if (sibling) {
3843 ctk_grid_attach_next_to (grid, check_button, sibling,
3844 CTK_POS_RIGHT, 1, 1);
3845 } else {
3846 ctk_container_add (CTK_CONTAINER (grid)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((grid)), ((ctk_container_get_type ()))))))
, check_button);
3847 }
3848
3849 set_up_permissions_checkbox (window,
3850 check_button,
3851 permission_to_check,
3852 is_folder);
3853
3854 a11y_enabled = CTK_IS_ACCESSIBLE (ctk_widget_get_accessible (check_button))(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(ctk_widget_get_accessible (check_button))); GType __t = ((ctk_accessible_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))
;
3855 if (a11y_enabled && label_for != NULL((void*)0)) {
3856 eel_accessibility_set_up_label_widget_relation (CTK_WIDGET (label_for)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((label_for)), ((ctk_widget_get_type ()))))))
,
3857 check_button);
3858 }
3859
3860 return check_button;
3861}
3862
3863static CtkWidget *
3864add_permissions_checkbox (FMPropertiesWindow *window,
3865 CtkGrid *grid,
3866 CtkWidget *sibling,
3867 CheckboxType type,
3868 guint32 permission_to_check,
3869 CtkLabel *label_for,
3870 gboolean is_folder)
3871{
3872 const gchar *label;
3873
3874 if (type == PERMISSIONS_CHECKBOXES_READ) {
3875 label = _("_Read")gettext ("_Read");
3876 } else if (type == PERMISSIONS_CHECKBOXES_WRITE) {
3877 label = _("_Write")gettext ("_Write");
3878 } else {
3879 label = _("E_xecute")gettext ("E_xecute");
3880 }
3881
3882 return add_permissions_checkbox_with_label (window, grid,
3883 sibling,
3884 label,
3885 permission_to_check,
3886 label_for,
3887 is_folder);
3888}
3889
3890enum {
3891 UNIX_PERM_SUID = S_ISUID04000,
3892 UNIX_PERM_SGID = S_ISGID02000,
3893 UNIX_PERM_STICKY = 01000, /* S_ISVTX not defined on all systems */
3894 UNIX_PERM_USER_READ = S_IRUSR0400,
3895 UNIX_PERM_USER_WRITE = S_IWUSR0200,
3896 UNIX_PERM_USER_EXEC = S_IXUSR0100,
3897 UNIX_PERM_USER_ALL = S_IRUSR0400 | S_IWUSR0200 | S_IXUSR0100,
3898 UNIX_PERM_GROUP_READ = S_IRGRP(0400 >> 3),
3899 UNIX_PERM_GROUP_WRITE = S_IWGRP(0200 >> 3),
3900 UNIX_PERM_GROUP_EXEC = S_IXGRP(0100 >> 3),
3901 UNIX_PERM_GROUP_ALL = S_IRGRP(0400 >> 3) | S_IWGRP(0200 >> 3) | S_IXGRP(0100 >> 3),
3902 UNIX_PERM_OTHER_READ = S_IROTH((0400 >> 3) >> 3),
3903 UNIX_PERM_OTHER_WRITE = S_IWOTH((0200 >> 3) >> 3),
3904 UNIX_PERM_OTHER_EXEC = S_IXOTH((0100 >> 3) >> 3),
3905 UNIX_PERM_OTHER_ALL = S_IROTH((0400 >> 3) >> 3) | S_IWOTH((0200 >> 3) >> 3) | S_IXOTH((0100 >> 3) >> 3)
3906};
3907
3908typedef enum {
3909 PERMISSION_READ = (1<<0),
3910 PERMISSION_WRITE = (1<<1),
3911 PERMISSION_EXEC = (1<<2)
3912} PermissionValue;
3913
3914typedef enum {
3915 PERMISSION_USER,
3916 PERMISSION_GROUP,
3917 PERMISSION_OTHER
3918} PermissionType;
3919
3920static guint32 vfs_perms[3][3] = {
3921 {UNIX_PERM_USER_READ, UNIX_PERM_USER_WRITE, UNIX_PERM_USER_EXEC},
3922 {UNIX_PERM_GROUP_READ, UNIX_PERM_GROUP_WRITE, UNIX_PERM_GROUP_EXEC},
3923 {UNIX_PERM_OTHER_READ, UNIX_PERM_OTHER_WRITE, UNIX_PERM_OTHER_EXEC},
3924};
3925
3926static guint32
3927permission_to_vfs (PermissionType type, PermissionValue perm)
3928{
3929 guint32 vfs_perm;
3930 g_assert (type >= 0 && type < 3)do { if (type >= 0 && type < 3) ; else g_assertion_message_expr
(((gchar*) 0), "fm-properties-window.c", 3930, ((const char*
) (__func__)), "type >= 0 && type < 3"); } while
(0)
;
3931
3932 vfs_perm = 0;
3933 if (perm & PERMISSION_READ) {
3934 vfs_perm |= vfs_perms[type][0];
3935 }
3936 if (perm & PERMISSION_WRITE) {
3937 vfs_perm |= vfs_perms[type][1];
3938 }
3939 if (perm & PERMISSION_EXEC) {
3940 vfs_perm |= vfs_perms[type][2];
3941 }
3942
3943 return vfs_perm;
3944}
3945
3946
3947static PermissionValue
3948permission_from_vfs (PermissionType type, guint32 vfs_perm)
3949{
3950 PermissionValue perm;
3951 g_assert (type >= 0 && type < 3)do { if (type >= 0 && type < 3) ; else g_assertion_message_expr
(((gchar*) 0), "fm-properties-window.c", 3951, ((const char*
) (__func__)), "type >= 0 && type < 3"); } while
(0)
;
3952
3953 perm = 0;
3954 if (vfs_perm & vfs_perms[type][0]) {
3955 perm |= PERMISSION_READ;
3956 }
3957 if (vfs_perm & vfs_perms[type][1]) {
3958 perm |= PERMISSION_WRITE;
3959 }
3960 if (vfs_perm & vfs_perms[type][2]) {
3961 perm |= PERMISSION_EXEC;
3962 }
3963
3964 return perm;
3965}
3966
3967static void
3968permission_combo_changed (CtkWidget *combo, FMPropertiesWindow *window)
3969{
3970 CtkTreeIter iter;
3971 CtkTreeModel *model;
3972 gboolean is_folder, use_original;
3973 PermissionType type;
3974 int new_perm, mask;
3975 guint32 vfs_new_perm, vfs_mask;
3976
3977 is_folder = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (combo), "is-folder"))((gint) (glong) (g_object_get_data (((((GObject*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((combo)), (((GType) ((20) << (2))))
)))), "is-folder")))
;
3978 type = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (combo), "permission-type"))((gint) (glong) (g_object_get_data (((((GObject*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((combo)), (((GType) ((20) << (2))))
)))), "permission-type")))
;
3979
3980 if (is_folder) {
3981 mask = PERMISSION_READ|PERMISSION_WRITE|PERMISSION_EXEC;
3982 } else {
3983 mask = PERMISSION_READ|PERMISSION_WRITE;
3984 }
3985
3986 vfs_mask = permission_to_vfs (type, mask);
3987
3988 model = ctk_combo_box_get_model (CTK_COMBO_BOX (combo)((((CtkComboBox*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((combo)), ((ctk_combo_box_get_type ()))))))
);
3989
3990 if (!ctk_combo_box_get_active_iter (CTK_COMBO_BOX (combo)((((CtkComboBox*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((combo)), ((ctk_combo_box_get_type ()))))))
, &iter)) {
3991 return;
3992 }
3993 ctk_tree_model_get (model, &iter, 1, &new_perm, 2, &use_original, -1);
3994 vfs_new_perm = permission_to_vfs (type, new_perm);
3995
3996 update_permissions (window, vfs_new_perm, vfs_mask,
3997 is_folder, FALSE(0), use_original);
3998}
3999
4000static void
4001permission_combo_add_multiple_choice (CtkComboBox *combo, CtkTreeIter *iter)
4002{
4003 CtkTreeModel *model;
4004 CtkListStore *store;
4005 gboolean found;
4006
4007 model = ctk_combo_box_get_model (combo);
4008 store = CTK_LIST_STORE (model)((((CtkListStore*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((model)), ((ctk_list_store_get_type ()))))))
;
4009
4010 found = FALSE(0);
4011 ctk_tree_model_get_iter_first (model, iter);
4012 do {
4013 gboolean multi;
4014 ctk_tree_model_get (model, iter, 2, &multi, -1);
4015
4016 if (multi) {
4017 found = TRUE(!(0));
4018 break;
4019 }
4020 } while (ctk_tree_model_iter_next (model, iter));
4021
4022 if (!found) {
4023 ctk_list_store_append (store, iter);
4024 ctk_list_store_set (store, iter, 0, "---", 1, 0, 2, TRUE(!(0)), -1);
4025 }
4026}
4027
4028static void
4029permission_combo_update (FMPropertiesWindow *window,
4030 CtkComboBox *combo)
4031{
4032 PermissionType type;
4033 PermissionValue perm, all_dir_perm, all_file_perm, all_perm;
4034 gboolean is_folder, no_files, no_dirs, all_file_same, all_dir_same, all_same;
4035 gboolean all_dir_cannot_set, all_file_cannot_set, sensitive;
4036 CtkTreeIter iter;
4037 int mask;
4038 CtkTreeModel *model;
4039 CtkListStore *store;
4040 GList *l;
4041 gboolean is_multi;
4042
4043 model = ctk_combo_box_get_model (combo);
4044
4045 is_folder = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (combo), "is-folder"))((gint) (glong) (g_object_get_data (((((GObject*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((combo)), (((GType) ((20) << (2))))
)))), "is-folder")))
;
4046 type = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (combo), "permission-type"))((gint) (glong) (g_object_get_data (((((GObject*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((combo)), (((GType) ((20) << (2))))
)))), "permission-type")))
;
4047
4048 is_multi = FALSE(0);
4049 if (ctk_combo_box_get_active_iter (CTK_COMBO_BOX (combo)((((CtkComboBox*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((combo)), ((ctk_combo_box_get_type ()))))))
, &iter)) {
4050 ctk_tree_model_get (model, &iter, 2, &is_multi, -1);
4051 }
4052
4053 if (is_multi && window->details->has_recursive_apply) {
4054 /* Never change from an inconsistent state if we have dirs, even
4055 * if the current state is now consistent, because its a useful
4056 * state for recursive apply.
4057 */
4058 return;
4059 }
4060
4061 no_files = TRUE(!(0));
4062 no_dirs = TRUE(!(0));
4063 all_dir_same = TRUE(!(0));
4064 all_file_same = TRUE(!(0));
4065 all_dir_perm = 0;
4066 all_file_perm = 0;
4067 all_dir_cannot_set = TRUE(!(0));
4068 all_file_cannot_set = TRUE(!(0));
4069
4070 for (l = window->details->target_files; l != NULL((void*)0); l = l->next) {
4071 BaulFile *file;
4072 guint32 file_permissions;
4073
4074 file = BAUL_FILE (l->data)((((BaulFile*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((l->data)), (baul_file_get_type())))))
;
4075
4076 if (!baul_file_can_get_permissions (file)) {
4077 continue;
4078 }
4079
4080 if (baul_file_is_directory (file)) {
4081 mask = PERMISSION_READ|PERMISSION_WRITE|PERMISSION_EXEC;
4082 } else {
4083 mask = PERMISSION_READ|PERMISSION_WRITE;
4084 }
4085
4086 file_permissions = baul_file_get_permissions (file);
4087
4088 perm = permission_from_vfs (type, file_permissions) & mask;
4089
4090 if (baul_file_is_directory (file)) {
4091 if (no_dirs) {
4092 all_dir_perm = perm;
4093 no_dirs = FALSE(0);
4094 } else if (perm != all_dir_perm) {
4095 all_dir_same = FALSE(0);
4096 }
4097
4098 if (baul_file_can_set_permissions (file)) {
4099 all_dir_cannot_set = FALSE(0);
4100 }
4101 } else {
4102 if (no_files) {
4103 all_file_perm = perm;
4104 no_files = FALSE(0);
4105 } else if (perm != all_file_perm) {
4106 all_file_same = FALSE(0);
4107 }
4108
4109 if (baul_file_can_set_permissions (file)) {
4110 all_file_cannot_set = FALSE(0);
4111 }
4112 }
4113 }
4114
4115 if (is_folder) {
4116 all_same = all_dir_same;
4117 all_perm = all_dir_perm;
4118 } else {
4119 all_same = all_file_same && !no_files;
4120 all_perm = all_file_perm;
4121 }
4122
4123 store = CTK_LIST_STORE (model)((((CtkListStore*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((model)), ((ctk_list_store_get_type ()))))))
;
4124 if (all_same) {
4125 gboolean found;
4126
4127 found = FALSE(0);
4128 ctk_tree_model_get_iter_first (model, &iter);
4129 do {
4130 int current_perm;
4131 ctk_tree_model_get (model, &iter, 1, &current_perm, -1);
4132
4133 if (current_perm == all_perm) {
4134 found = TRUE(!(0));
4135 break;
4136 }
4137 } while (ctk_tree_model_iter_next (model, &iter));
4138
4139 if (!found) {
4140 GString *str;
4141 str = g_string_new ("");
4142
4143 if (!(all_perm & PERMISSION_READ)) {
4144 /* Translators: this gets concatenated to "no read",
4145 * "no access", etc. (see following strings)
4146 */
4147 g_string_append (str, _("no "))(__builtin_constant_p (gettext ("no ")) ? __extension__ ({ const
char * const __val = (gettext ("no ")); g_string_append_len_inline
(str, __val, (__val != ((void*)0)) ? (gssize) strlen (((__val
) + !(__val))) : (gssize) -1); }) : g_string_append_len_inline
(str, gettext ("no "), (gssize) -1))
;
4148 }
4149 if (is_folder) {
4150 g_string_append (str, _("list"))(__builtin_constant_p (gettext ("list")) ? __extension__ ({ const
char * const __val = (gettext ("list")); g_string_append_len_inline
(str, __val, (__val != ((void*)0)) ? (gssize) strlen (((__val
) + !(__val))) : (gssize) -1); }) : g_string_append_len_inline
(str, gettext ("list"), (gssize) -1))
;
4151 } else {
4152 g_string_append (str, _("read"))(__builtin_constant_p (gettext ("read")) ? __extension__ ({ const
char * const __val = (gettext ("read")); g_string_append_len_inline
(str, __val, (__val != ((void*)0)) ? (gssize) strlen (((__val
) + !(__val))) : (gssize) -1); }) : g_string_append_len_inline
(str, gettext ("read"), (gssize) -1))
;
4153 }
4154
4155 g_string_append (str, ", ")(__builtin_constant_p (", ") ? __extension__ ({ const char * const
__val = (", "); g_string_append_len_inline (str, __val, (__val
!= ((void*)0)) ? (gssize) strlen (((__val) + !(__val))) : (gssize
) -1); }) : g_string_append_len_inline (str, ", ", (gssize) -
1))
;
4156
4157 if (!(all_perm & PERMISSION_WRITE)) {
4158 g_string_append (str, _("no "))(__builtin_constant_p (gettext ("no ")) ? __extension__ ({ const
char * const __val = (gettext ("no ")); g_string_append_len_inline
(str, __val, (__val != ((void*)0)) ? (gssize) strlen (((__val
) + !(__val))) : (gssize) -1); }) : g_string_append_len_inline
(str, gettext ("no "), (gssize) -1))
;
4159 }
4160 if (is_folder) {
4161 g_string_append (str, _("create/delete"))(__builtin_constant_p (gettext ("create/delete")) ? __extension__
({ const char * const __val = (gettext ("create/delete")); g_string_append_len_inline
(str, __val, (__val != ((void*)0)) ? (gssize) strlen (((__val
) + !(__val))) : (gssize) -1); }) : g_string_append_len_inline
(str, gettext ("create/delete"), (gssize) -1))
;
4162 } else {
4163 g_string_append (str, _("write"))(__builtin_constant_p (gettext ("write")) ? __extension__ ({ const
char * const __val = (gettext ("write")); g_string_append_len_inline
(str, __val, (__val != ((void*)0)) ? (gssize) strlen (((__val
) + !(__val))) : (gssize) -1); }) : g_string_append_len_inline
(str, gettext ("write"), (gssize) -1))
;
4164 }
4165
4166 if (is_folder) {
4167 g_string_append (str, ", ")(__builtin_constant_p (", ") ? __extension__ ({ const char * const
__val = (", "); g_string_append_len_inline (str, __val, (__val
!= ((void*)0)) ? (gssize) strlen (((__val) + !(__val))) : (gssize
) -1); }) : g_string_append_len_inline (str, ", ", (gssize) -
1))
;
4168
4169 if (!(all_perm & PERMISSION_EXEC)) {
4170 g_string_append (str, _("no "))(__builtin_constant_p (gettext ("no ")) ? __extension__ ({ const
char * const __val = (gettext ("no ")); g_string_append_len_inline
(str, __val, (__val != ((void*)0)) ? (gssize) strlen (((__val
) + !(__val))) : (gssize) -1); }) : g_string_append_len_inline
(str, gettext ("no "), (gssize) -1))
;
4171 }
4172 g_string_append (str, _("access"))(__builtin_constant_p (gettext ("access")) ? __extension__ ({
const char * const __val = (gettext ("access")); g_string_append_len_inline
(str, __val, (__val != ((void*)0)) ? (gssize) strlen (((__val
) + !(__val))) : (gssize) -1); }) : g_string_append_len_inline
(str, gettext ("access"), (gssize) -1))
;
4173 }
4174
4175 ctk_list_store_append (store, &iter);
4176 ctk_list_store_set (store, &iter,
4177 0, str->str,
4178 1, all_perm, -1);
4179
4180 g_string_free (str, TRUE)(__builtin_constant_p ((!(0))) ? (((!(0))) ? (g_string_free) (
(str), ((!(0)))) : g_string_free_and_steal (str)) : (g_string_free
) ((str), ((!(0)))))
;
4181 }
4182 } else {
4183 permission_combo_add_multiple_choice (combo, &iter);
4184 }
4185
4186 g_signal_handlers_block_by_func (G_OBJECT (combo),g_signal_handlers_block_matched ((((((GObject*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((combo)), (((GType) ((20) << (2))))
))))), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (((GCallback) (permission_combo_changed)
)), (window))
4187 G_CALLBACK (permission_combo_changed),g_signal_handlers_block_matched ((((((GObject*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((combo)), (((GType) ((20) << (2))))
))))), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (((GCallback) (permission_combo_changed)
)), (window))
4188 window)g_signal_handlers_block_matched ((((((GObject*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((combo)), (((GType) ((20) << (2))))
))))), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (((GCallback) (permission_combo_changed)
)), (window))
;
4189
4190 ctk_combo_box_set_active_iter (combo, &iter);
4191
4192 /* Also enable if no files found (for recursive
4193 file changes when only selecting folders) */
4194 if (is_folder) {
4195 sensitive = !all_dir_cannot_set;
4196 } else {
4197 sensitive = !all_file_cannot_set ||
4198 window->details->has_recursive_apply;
4199 }
4200 ctk_widget_set_sensitive (CTK_WIDGET (combo)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((combo)), ((ctk_widget_get_type ()))))))
, sensitive);
4201
4202 g_signal_handlers_unblock_by_func (G_OBJECT (combo),g_signal_handlers_unblock_matched ((((((GObject*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((combo)), (((GType) ((20) << (2))))
))))), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (((GCallback) (permission_combo_changed)
)), (window))
4203 G_CALLBACK (permission_combo_changed),g_signal_handlers_unblock_matched ((((((GObject*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((combo)), (((GType) ((20) << (2))))
))))), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (((GCallback) (permission_combo_changed)
)), (window))
4204 window)g_signal_handlers_unblock_matched ((((((GObject*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((combo)), (((GType) ((20) << (2))))
))))), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (((GCallback) (permission_combo_changed)
)), (window))
;
4205
4206}
4207
4208static void
4209add_permissions_combo_box (FMPropertiesWindow *window, CtkGrid *grid,
4210 PermissionType type, gboolean is_folder,
4211 gboolean short_label)
4212{
4213 CtkWidget *combo;
4214 CtkLabel *label;
4215 CtkListStore *store;
4216 CtkCellRenderer *cell;
4217 CtkTreeIter iter;
4218
4219 if (short_label) {
4220 label = attach_title_field (grid, _("Access:")gettext ("Access:"));
4221 } else if (is_folder) {
4222 label = attach_title_field (grid, _("Folder access:")gettext ("Folder access:"));
4223 } else {
4224 label = attach_title_field (grid, _("File access:")gettext ("File access:"));
4225 }
4226
4227 store = ctk_list_store_new (3, G_TYPE_STRING((GType) ((16) << (2))), G_TYPE_INT((GType) ((6) << (2))), G_TYPE_BOOLEAN((GType) ((5) << (2))));
4228 combo = ctk_combo_box_new_with_model (CTK_TREE_MODEL (store)((((CtkTreeModel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((store)), ((ctk_tree_model_get_type ()))))))
);
4229
4230 g_object_set_data (G_OBJECT (combo)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((combo)), (((GType) ((20) << (2))))))))
, "is-folder", GINT_TO_POINTER (is_folder)((gpointer) (glong) (is_folder)));
4231 g_object_set_data (G_OBJECT (combo)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((combo)), (((GType) ((20) << (2))))))))
, "permission-type", GINT_TO_POINTER (type)((gpointer) (glong) (type)));
4232
4233 if (is_folder) {
4234 if (type != PERMISSION_USER) {
4235 ctk_list_store_append (store, &iter);
4236 /* Translators: this is referred to the permissions
4237 * the user has in a directory.
4238 */
4239 ctk_list_store_set (store, &iter, 0, _("None")gettext ("None"), 1, 0, -1);
4240 }
4241 ctk_list_store_append (store, &iter);
4242 ctk_list_store_set (store, &iter, 0, _("List files only")gettext ("List files only"), 1, PERMISSION_READ, -1);
4243 ctk_list_store_append (store, &iter);
4244 ctk_list_store_set (store, &iter, 0, _("Access files")gettext ("Access files"), 1, PERMISSION_READ|PERMISSION_EXEC, -1);
4245 ctk_list_store_append (store, &iter);
4246 ctk_list_store_set (store, &iter, 0, _("Create and delete files")gettext ("Create and delete files"), 1, PERMISSION_READ|PERMISSION_EXEC|PERMISSION_WRITE, -1);
4247 } else {
4248 if (type != PERMISSION_USER) {
4249 ctk_list_store_append (store, &iter);
4250 ctk_list_store_set (store, &iter, 0, _("None")gettext ("None"), 1, 0, -1);
4251 }
4252 ctk_list_store_append (store, &iter);
4253 ctk_list_store_set (store, &iter, 0, _("Read-only")gettext ("Read-only"), 1, PERMISSION_READ, -1);
4254 ctk_list_store_append (store, &iter);
4255 ctk_list_store_set (store, &iter, 0, _("Read and write")gettext ("Read and write"), 1, PERMISSION_READ|PERMISSION_WRITE, -1);
4256 }
4257 if (window->details->has_recursive_apply) {
4258 permission_combo_add_multiple_choice (CTK_COMBO_BOX (combo)((((CtkComboBox*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((combo)), ((ctk_combo_box_get_type ()))))))
, &iter);
4259 }
4260
4261 g_object_unref (store);
4262
4263 window->details->permission_combos =
4264 g_list_prepend (window->details->permission_combos,
4265 combo);
4266
4267 g_signal_connect (combo, "changed", G_CALLBACK (permission_combo_changed), window)g_signal_connect_data ((combo), ("changed"), (((GCallback) (permission_combo_changed
))), (window), ((void*)0), (GConnectFlags) 0)
;
4268
4269 cell = ctk_cell_renderer_text_new ();
4270 ctk_cell_layout_pack_start (CTK_CELL_LAYOUT (combo)((((CtkCellLayout*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((combo)), ((ctk_cell_layout_get_type ()))))))
, cell, TRUE(!(0)));
4271 ctk_cell_layout_set_attributes (CTK_CELL_LAYOUT (combo)((((CtkCellLayout*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((combo)), ((ctk_cell_layout_get_type ()))))))
, cell,
4272 "text", 0,
4273 NULL((void*)0));
4274
4275 ctk_label_set_mnemonic_widget (label, combo);
4276 ctk_widget_show (combo);
4277
4278 ctk_grid_attach_next_to (grid, combo, CTK_WIDGET (label)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((label)), ((ctk_widget_get_type ()))))))
,
4279 CTK_POS_RIGHT, 1, 1);
4280}
4281
4282
4283static CtkWidget *
4284append_special_execution_checkbox (FMPropertiesWindow *window,
4285 CtkGrid *grid,
4286 CtkWidget *sibling,
4287 const char *label_text,
4288 guint32 permission_to_check)
4289{
4290 CtkWidget *check_button;
4291
4292 check_button = ctk_check_button_new_with_mnemonic (label_text);
4293 ctk_widget_show (check_button);
4294
4295 if (sibling != NULL((void*)0)) {
4296 ctk_grid_attach_next_to (grid, check_button, sibling,
4297 CTK_POS_RIGHT, 1, 1);
4298 } else {
4299 ctk_container_add_with_properties (CTK_CONTAINER (grid)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((grid)), ((ctk_container_get_type ()))))))
, check_button,
4300 "left-attach", 1,
4301 NULL((void*)0));
4302 }
4303
4304 set_up_permissions_checkbox (window,
4305 check_button,
4306 permission_to_check,
4307 FALSE(0));
4308 g_object_set_data (G_OBJECT (check_button)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((check_button)), (((GType) ((20) << (2))))))))
, "is-special",
4309 GINT_TO_POINTER (TRUE)((gpointer) (glong) ((!(0)))));
4310
4311 return check_button;
4312}
4313
4314static void
4315append_special_execution_flags (FMPropertiesWindow *window, CtkGrid *grid)
4316{
4317 CtkWidget *title;
4318
4319 append_blank_slim_row (grid);
4320 title = CTK_WIDGET (attach_title_field (grid, _("Special flags:")))((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((attach_title_field (grid, gettext ("Special flags:")))),
((ctk_widget_get_type ()))))))
;
4321
4322 append_special_execution_checkbox (window, grid, title, _("Set _user ID")gettext ("Set _user ID"), UNIX_PERM_SUID);
4323 append_special_execution_checkbox (window, grid, NULL((void*)0), _("Set gro_up ID")gettext ("Set gro_up ID"), UNIX_PERM_SGID);
4324 append_special_execution_checkbox (window, grid, NULL((void*)0), _("_Sticky")gettext ("_Sticky"), UNIX_PERM_STICKY);
4325}
4326
4327static gboolean
4328all_can_get_permissions (GList *file_list)
4329{
4330 GList *l;
4331 for (l = file_list; l != NULL((void*)0); l = l->next) {
4332 BaulFile *file;
4333
4334 file = BAUL_FILE (l->data)((((BaulFile*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((l->data)), (baul_file_get_type())))))
;
4335
4336 if (!baul_file_can_get_permissions (file)) {
4337 return FALSE(0);
4338 }
4339 }
4340
4341 return TRUE(!(0));
4342}
4343
4344static gboolean
4345all_can_set_permissions (GList *file_list)
4346{
4347 GList *l;
4348 for (l = file_list; l != NULL((void*)0); l = l->next) {
4349 BaulFile *file;
4350
4351 file = BAUL_FILE (l->data)((((BaulFile*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((l->data)), (baul_file_get_type())))))
;
4352
4353 if (!baul_file_can_set_permissions (file)) {
4354 return FALSE(0);
4355 }
4356 }
4357
4358 return TRUE(!(0));
4359}
4360
4361static GHashTable *
4362get_initial_permissions (GList *file_list)
4363{
4364 GHashTable *ret;
4365 GList *l;
4366
4367 ret = g_hash_table_new (g_direct_hash,
4368 g_direct_equal);
4369
4370 for (l = file_list; l != NULL((void*)0); l = l->next) {
4371 guint32 permissions;
4372 BaulFile *file;
4373
4374 file = BAUL_FILE (l->data)((((BaulFile*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((l->data)), (baul_file_get_type())))))
;
4375
4376 permissions = baul_file_get_permissions (file);
4377 g_hash_table_insert (ret, file,
4378 GINT_TO_POINTER (permissions)((gpointer) (glong) (permissions)));
4379 }
4380
4381 return ret;
4382}
4383
4384static void
4385create_simple_permissions (FMPropertiesWindow *window, CtkGrid *page_grid)
4386{
4387 gboolean has_file, has_directory;
4388 CtkLabel *group_label;
4389 CtkLabel *owner_label;
4390 CtkLabel *execute_label;
4391 CtkWidget *value;
4392
4393 has_file = files_has_file (window);
4394 has_directory = files_has_directory (window);
4395
4396 if (!is_multi_file_window (window) && baul_file_can_set_owner (get_target_file (window))) {
4397 CtkComboBox *owner_combo_box;
4398
4399 owner_label = attach_title_field (page_grid, _("_Owner:")gettext ("_Owner:"));
4400 /* Combo box in this case. */
4401 owner_combo_box = attach_owner_combo_box (page_grid,
4402 CTK_WIDGET (owner_label)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((owner_label)), ((ctk_widget_get_type ()))))))
,
4403 get_target_file (window));
4404 ctk_label_set_mnemonic_widget (owner_label,
4405 CTK_WIDGET (owner_combo_box)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((owner_combo_box)), ((ctk_widget_get_type ()))))))
);
4406 } else {
4407 owner_label = attach_title_field (page_grid, _("Owner:")gettext ("Owner:"));
4408 /* Static text in this case. */
4409 value = attach_value_field (window,
4410 page_grid, CTK_WIDGET (owner_label)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((owner_label)), ((ctk_widget_get_type ()))))))
,
4411 "owner",
4412 INCONSISTENT_STATE_STRING"\xE2\x80\x92",
4413 FALSE(0));
4414 ctk_label_set_mnemonic_widget (owner_label, value);
4415 }
4416
4417 if (has_directory) {
4418 add_permissions_combo_box (window, page_grid,
4419 PERMISSION_USER, TRUE(!(0)), FALSE(0));
4420 }
4421 if (has_file || window->details->has_recursive_apply) {
4422 add_permissions_combo_box (window, page_grid,
4423 PERMISSION_USER, FALSE(0), !has_directory);
4424 }
4425
4426 append_blank_slim_row (page_grid);
4427
4428 if (!is_multi_file_window (window) && baul_file_can_set_group (get_target_file (window))) {
4429 CtkComboBox *group_combo_box;
4430
4431 group_label = attach_title_field (page_grid, _("_Group:")gettext ("_Group:"));
4432
4433 /* Combo box in this case. */
4434 group_combo_box = attach_group_combo_box (page_grid, CTK_WIDGET (group_label)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((group_label)), ((ctk_widget_get_type ()))))))
,
4435 get_target_file (window));
4436 ctk_label_set_mnemonic_widget (group_label,
4437 CTK_WIDGET (group_combo_box)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((group_combo_box)), ((ctk_widget_get_type ()))))))
);
4438 } else {
4439 group_label = attach_title_field (page_grid, _("Group:")gettext ("Group:"));
4440
4441 /* Static text in this case. */
4442 value = attach_value_field (window, page_grid,
4443 CTK_WIDGET (group_label)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((group_label)), ((ctk_widget_get_type ()))))))
,
4444 "group",
4445 INCONSISTENT_STATE_STRING"\xE2\x80\x92",
4446 FALSE(0));
4447 ctk_label_set_mnemonic_widget (group_label, value);
4448 }
4449
4450 if (has_directory) {
4451 add_permissions_combo_box (window, page_grid,
4452 PERMISSION_GROUP, TRUE(!(0)),
4453 FALSE(0));
4454 }
4455 if (has_file || window->details->has_recursive_apply) {
4456 add_permissions_combo_box (window, page_grid,
4457 PERMISSION_GROUP, FALSE(0),
4458 !has_directory);
4459 }
4460
4461 append_blank_slim_row (page_grid);
4462
4463 group_label = attach_title_field (page_grid, _("Others")gettext ("Others"));
4464
4465 if (has_directory) {
4466 add_permissions_combo_box (window, page_grid,
4467 PERMISSION_OTHER, TRUE(!(0)),
4468 FALSE(0));
4469 }
4470 if (has_file || window->details->has_recursive_apply) {
4471 add_permissions_combo_box (window, page_grid,
4472 PERMISSION_OTHER, FALSE(0),
4473 !has_directory);
4474 }
4475
4476 append_blank_slim_row (page_grid);
4477
4478 execute_label = attach_title_field (page_grid, _("Execute:")gettext ("Execute:"));
4479 add_permissions_checkbox_with_label (window, page_grid,
4480 CTK_WIDGET (execute_label)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((execute_label)), ((ctk_widget_get_type ()))))))
,
4481 _("Allow _executing file as program")gettext ("Allow _executing file as program"),
4482 UNIX_PERM_USER_EXEC|UNIX_PERM_GROUP_EXEC|UNIX_PERM_OTHER_EXEC,
4483 execute_label, FALSE(0));
4484}
4485
4486static void
4487create_permission_checkboxes (FMPropertiesWindow *window,
4488 CtkGrid *page_grid,
4489 gboolean is_folder)
4490{
4491 CtkLabel *owner_perm_label;
4492 CtkLabel *group_perm_label;
4493 CtkLabel *other_perm_label;
4494 CtkGrid *check_button_grid;
4495 CtkWidget *w;
4496
4497 owner_perm_label = attach_title_field (page_grid, _("Owner:")gettext ("Owner:"));
4498 group_perm_label = attach_title_field (page_grid, _("Group:")gettext ("Group:"));
4499 other_perm_label = attach_title_field (page_grid, _("Others:")gettext ("Others:"));
4500
4501 check_button_grid = CTK_GRID (create_grid_with_standard_properties ())((((CtkGrid*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((create_grid_with_standard_properties ())), ((ctk_grid_get_type
()))))))
;
4502 ctk_widget_show (CTK_WIDGET (check_button_grid)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((check_button_grid)), ((ctk_widget_get_type ()))))))
);
4503
4504 ctk_grid_attach_next_to (page_grid, CTK_WIDGET (check_button_grid)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((check_button_grid)), ((ctk_widget_get_type ()))))))
,
4505 CTK_WIDGET (owner_perm_label)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((owner_perm_label)), ((ctk_widget_get_type ()))))))
,
4506 CTK_POS_RIGHT, 1, 3);
4507
4508 w = add_permissions_checkbox (window,
4509 check_button_grid,
4510 NULL((void*)0),
4511 PERMISSIONS_CHECKBOXES_READ,
4512 UNIX_PERM_USER_READ,
4513 owner_perm_label,
4514 is_folder);
4515
4516 w = add_permissions_checkbox (window,
4517 check_button_grid,
4518 w,
4519 PERMISSIONS_CHECKBOXES_WRITE,
4520 UNIX_PERM_USER_WRITE,
4521 owner_perm_label,
4522 is_folder);
4523
4524 w = add_permissions_checkbox (window,
Value stored to 'w' is never read
4525 check_button_grid,
4526 w,
4527 PERMISSIONS_CHECKBOXES_EXECUTE,
4528 UNIX_PERM_USER_EXEC,
4529 owner_perm_label,
4530 is_folder);
4531
4532 w = add_permissions_checkbox (window,
4533 check_button_grid,
4534 NULL((void*)0),
4535 PERMISSIONS_CHECKBOXES_READ,
4536 UNIX_PERM_GROUP_READ,
4537 group_perm_label,
4538 is_folder);
4539
4540 w = add_permissions_checkbox (window,
4541 check_button_grid,
4542 w,
4543 PERMISSIONS_CHECKBOXES_WRITE,
4544 UNIX_PERM_GROUP_WRITE,
4545 group_perm_label,
4546 is_folder);
4547
4548 w = add_permissions_checkbox (window,
4549 check_button_grid,
4550 w,
4551 PERMISSIONS_CHECKBOXES_EXECUTE,
4552 UNIX_PERM_GROUP_EXEC,
4553 group_perm_label,
4554 is_folder);
4555
4556 w = add_permissions_checkbox (window,
4557 check_button_grid,
4558 NULL((void*)0),
4559 PERMISSIONS_CHECKBOXES_READ,
4560 UNIX_PERM_OTHER_READ,
4561 other_perm_label,
4562 is_folder);
4563
4564 w = add_permissions_checkbox (window,
4565 check_button_grid,
4566 w,
4567 PERMISSIONS_CHECKBOXES_WRITE,
4568 UNIX_PERM_OTHER_WRITE,
4569 other_perm_label,
4570 is_folder);
4571
4572 add_permissions_checkbox (window,
4573 check_button_grid,
4574 w,
4575 PERMISSIONS_CHECKBOXES_EXECUTE,
4576 UNIX_PERM_OTHER_EXEC,
4577 other_perm_label,
4578 is_folder);
4579}
4580
4581static void
4582create_advanced_permissions (FMPropertiesWindow *window, CtkGrid *page_grid)
4583{
4584 CtkLabel *group_label;
4585 CtkLabel *owner_label;
4586 gboolean has_directory, has_file;
4587
4588 if (!is_multi_file_window (window) && baul_file_can_set_owner (get_target_file (window))) {
4589 CtkComboBox *owner_combo_box;
4590
4591 owner_label = attach_title_field (page_grid, _("_Owner:")gettext ("_Owner:"));
4592 /* Combo box in this case. */
4593 owner_combo_box = attach_owner_combo_box (page_grid,
4594 CTK_WIDGET (owner_label)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((owner_label)), ((ctk_widget_get_type ()))))))
,
4595 get_target_file (window));
4596 ctk_label_set_mnemonic_widget (owner_label,
4597 CTK_WIDGET (owner_combo_box)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((owner_combo_box)), ((ctk_widget_get_type ()))))))
);
4598 } else {
4599 CtkWidget *value;
4600 owner_label = attach_title_field (page_grid, _("Owner:")gettext ("Owner:"));
4601
4602 /* Static text in this case. */
4603 value = attach_value_field (window,
4604 page_grid,
4605 CTK_WIDGET (owner_label)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((owner_label)), ((ctk_widget_get_type ()))))))
,
4606 "owner",
4607 INCONSISTENT_STATE_STRING"\xE2\x80\x92",
4608 FALSE(0));
4609 ctk_label_set_mnemonic_widget (owner_label, value);
4610 }
4611
4612 if (!is_multi_file_window (window) && baul_file_can_set_group (get_target_file (window))) {
4613 CtkComboBox *group_combo_box;
4614
4615 group_label = attach_title_field (page_grid, _("_Group:")gettext ("_Group:"));
4616
4617 /* Combo box in this case. */
4618 group_combo_box = attach_group_combo_box (page_grid, CTK_WIDGET (group_label)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((group_label)), ((ctk_widget_get_type ()))))))
,
4619 get_target_file (window));
4620 ctk_label_set_mnemonic_widget (group_label,
4621 CTK_WIDGET (group_combo_box)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((group_combo_box)), ((ctk_widget_get_type ()))))))
);
4622 } else {
4623 group_label = attach_title_field (page_grid, _("Group:")gettext ("Group:"));
4624
4625 /* Static text in this case. */
4626 attach_value_field (window, page_grid, CTK_WIDGET (group_label)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((group_label)), ((ctk_widget_get_type ()))))))
,
4627 "group",
4628 INCONSISTENT_STATE_STRING"\xE2\x80\x92",
4629 FALSE(0));
4630 }
4631
4632 append_blank_slim_row (page_grid);
4633
4634 has_directory = files_has_directory (window);
4635 has_file = files_has_file (window);
4636
4637 if (has_directory) {
4638 if (has_file || window->details->has_recursive_apply) {
4639 attach_title_field (page_grid, _("Folder Permissions:")gettext ("Folder Permissions:"));
4640 }
4641 create_permission_checkboxes (window, page_grid, TRUE(!(0)));
4642 }
4643
4644 if (has_file || window->details->has_recursive_apply) {
4645 if (has_directory) {
4646 attach_title_field (page_grid, _("File Permissions:")gettext ("File Permissions:"));
4647 }
4648 create_permission_checkboxes (window, page_grid, FALSE(0));
4649 }
4650
4651 append_blank_slim_row (page_grid);
4652 append_special_execution_flags (window, page_grid);
4653
4654 append_title_value_pair
4655 (window, page_grid, _("Text view:")gettext ("Text view:"),
4656 "permissions", INCONSISTENT_STATE_STRING"\xE2\x80\x92",
4657 FALSE(0));
4658}
4659
4660static void
4661set_recursive_permissions_done (gpointer callback_data)
4662{
4663 FMPropertiesWindow *window;
4664
4665 window = FM_PROPERTIES_WINDOW (callback_data)((((FMPropertiesWindow*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((callback_data)), (fm_properties_window_get_type
())))))
;
4666 end_long_operation (window);
4667
4668 g_object_unref (window);
4669}
4670
4671
4672static void
4673apply_recursive_clicked (CtkWidget *recursive_button G_GNUC_UNUSED__attribute__ ((__unused__)),
4674 FMPropertiesWindow *window)
4675{
4676 guint32 file_permission, file_permission_mask;
4677 guint32 dir_permission, dir_permission_mask;
4678 guint32 vfs_mask, vfs_new_perm, p;
4679 gboolean active, is_folder, is_special, use_original;
4680 GList *l;
4681 CtkTreeModel *model;
4682 CtkTreeIter iter;
4683 PermissionType type;
4684 int new_perm, mask;
4685 CtkWidget *button = NULL((void*)0);
4686 CtkWidget *combo = NULL((void*)0);
4687
4688 file_permission = 0;
4689 file_permission_mask = 0;
4690 dir_permission = 0;
4691 dir_permission_mask = 0;
4692
4693 /* Advanced mode and execute checkbox: */
4694 for (l = window->details->permission_buttons; l != NULL((void*)0); l = l->next) {
4695 button = l->data;
4696
4697 if (ctk_toggle_button_get_inconsistent (CTK_TOGGLE_BUTTON (button)((((CtkToggleButton*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((button)), ((ctk_toggle_button_get_type ()))))))
)) {
4698 continue;
4699 }
4700
4701 active = ctk_toggle_button_get_active (CTK_TOGGLE_BUTTON (button)((((CtkToggleButton*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((button)), ((ctk_toggle_button_get_type ()))))))
);
4702 p = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (button),((gint) (glong) (g_object_get_data (((((GObject*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((button)), (((GType) ((20) << (2)))
))))), "permission")))
4703 "permission"))((gint) (glong) (g_object_get_data (((((GObject*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((button)), (((GType) ((20) << (2)))
))))), "permission")))
;
4704 is_folder = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (button),((gint) (glong) (g_object_get_data (((((GObject*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((button)), (((GType) ((20) << (2)))
))))), "is-folder")))
4705 "is-folder"))((gint) (glong) (g_object_get_data (((((GObject*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((button)), (((GType) ((20) << (2)))
))))), "is-folder")))
;
4706 is_special = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (button),((gint) (glong) (g_object_get_data (((((GObject*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((button)), (((GType) ((20) << (2)))
))))), "is-special")))
4707 "is-special"))((gint) (glong) (g_object_get_data (((((GObject*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((button)), (((GType) ((20) << (2)))
))))), "is-special")))
;
4708
4709 if (is_folder || is_special) {
4710 dir_permission_mask |= p;
4711 if (active) {
4712 dir_permission |= p;
4713 }
4714 }
4715 if (!is_folder || is_special) {
4716 file_permission_mask |= p;
4717 if (active) {
4718 file_permission |= p;
4719 }
4720 }
4721 }
4722 /* Simple mode, minus exec checkbox */
4723 for (l = window->details->permission_combos; l != NULL((void*)0); l = l->next) {
4724 combo = l->data;
4725
4726 if (!ctk_combo_box_get_active_iter (CTK_COMBO_BOX (combo)((((CtkComboBox*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((combo)), ((ctk_combo_box_get_type ()))))))
, &iter)) {
4727 continue;
4728 }
4729
4730 type = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (combo), "permission-type"))((gint) (glong) (g_object_get_data (((((GObject*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((combo)), (((GType) ((20) << (2))))
)))), "permission-type")))
;
4731 is_folder = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (combo),((gint) (glong) (g_object_get_data (((((GObject*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((combo)), (((GType) ((20) << (2))))
)))), "is-folder")))
4732 "is-folder"))((gint) (glong) (g_object_get_data (((((GObject*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((combo)), (((GType) ((20) << (2))))
)))), "is-folder")))
;
4733
4734 model = ctk_combo_box_get_model (CTK_COMBO_BOX (combo)((((CtkComboBox*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((combo)), ((ctk_combo_box_get_type ()))))))
);
4735 ctk_tree_model_get (model, &iter, 1, &new_perm, 2, &use_original, -1);
4736 if (use_original) {
4737 continue;
4738 }
4739 vfs_new_perm = permission_to_vfs (type, new_perm);
4740
4741 if (is_folder) {
4742 mask = PERMISSION_READ|PERMISSION_WRITE|PERMISSION_EXEC;
4743 } else {
4744 mask = PERMISSION_READ|PERMISSION_WRITE;
4745 }
4746 vfs_mask = permission_to_vfs (type, mask);
4747
4748 if (is_folder) {
4749 dir_permission_mask |= vfs_mask;
4750 dir_permission |= vfs_new_perm;
4751 } else {
4752 file_permission_mask |= vfs_mask;
4753 file_permission |= vfs_new_perm;
4754 }
4755 }
4756
4757 for (l = window->details->target_files; l != NULL((void*)0); l = l->next) {
4758 BaulFile *file;
4759
4760 file = BAUL_FILE (l->data)((((BaulFile*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((l->data)), (baul_file_get_type())))))
;
4761
4762 if (baul_file_is_directory (file) &&
4763 baul_file_can_set_permissions (file)) {
4764 char *uri;
4765
4766 uri = baul_file_get_uri (file);
4767 start_long_operation (window);
4768 g_object_ref (window)((__typeof__ (window)) (g_object_ref) (window));
4769 baul_file_set_permissions_recursive (uri,
4770 file_permission,
4771 file_permission_mask,
4772 dir_permission,
4773 dir_permission_mask,
4774 set_recursive_permissions_done,
4775 window);
4776 g_free (uri);
4777 }
4778 }
4779}
4780
4781static void
4782create_permissions_page (FMPropertiesWindow *window)
4783{
4784 CtkWidget *vbox;
4785 GList *file_list;
4786
4787 vbox = create_page_with_vbox (window->details->notebook,
4788 _("Permissions")gettext ("Permissions"));
4789
4790 file_list = window->details->original_files;
4791
4792 window->details->initial_permissions = NULL((void*)0);
4793
4794 if (all_can_get_permissions (file_list) && all_can_get_permissions (window->details->target_files)) {
4795 CtkGrid *page_grid;
4796
4797 window->details->initial_permissions = get_initial_permissions (window->details->target_files);
4798 window->details->has_recursive_apply = files_has_changable_permissions_directory (window);
4799
4800 if (!all_can_set_permissions (file_list)) {
4801 add_prompt_and_separator (
4802 vbox,
4803 _("You are not the owner, so you cannot change these permissions.")gettext ("You are not the owner, so you cannot change these permissions."
)
);
4804 }
4805
4806 page_grid = CTK_GRID (create_grid_with_standard_properties ())((((CtkGrid*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((create_grid_with_standard_properties ())), ((ctk_grid_get_type
()))))))
;
4807
4808 ctk_widget_show (CTK_WIDGET (page_grid)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((page_grid)), ((ctk_widget_get_type ()))))))
);
4809 ctk_box_pack_start (CTK_BOX (vbox)((((CtkBox*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((vbox)), ((ctk_box_get_type ()))))))
,
4810 CTK_WIDGET (page_grid)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((page_grid)), ((ctk_widget_get_type ()))))))
,
4811 TRUE(!(0)), TRUE(!(0)), 0);
4812
4813 if (g_settings_get_boolean (baul_preferences, BAUL_PREFERENCES_SHOW_ADVANCED_PERMISSIONS"show-advanced-permissions")) {
4814 create_advanced_permissions (window, page_grid);
4815 } else {
4816 create_simple_permissions (window, page_grid);
4817 }
4818
4819 append_blank_slim_row (page_grid);
4820
4821#ifdef HAVE_SELINUX1
4822 append_title_value_pair
4823 (window, page_grid, _("SELinux context:")gettext ("SELinux context:"),
4824 "selinux_context", INCONSISTENT_STATE_STRING"\xE2\x80\x92",
4825 FALSE(0));
4826#endif
4827 append_title_value_pair
4828 (window, page_grid, _("Last changed:")gettext ("Last changed:"),
4829 "date_permissions", INCONSISTENT_STATE_STRING"\xE2\x80\x92",
4830 FALSE(0));
4831
4832 if (window->details->has_recursive_apply) {
4833 CtkWidget *button, *hbox;
4834
4835 hbox = ctk_box_new (CTK_ORIENTATION_HORIZONTAL, 0);
4836 ctk_widget_show (hbox);
4837 ctk_container_add_with_properties (CTK_CONTAINER (page_grid)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((page_grid)), ((ctk_container_get_type ()))))))
, hbox,
4838 "width", 2,
4839 NULL((void*)0));
4840
4841 button = ctk_button_new_with_mnemonic (_("Apply Permissions to Enclosed Files")gettext ("Apply Permissions to Enclosed Files"));
4842 ctk_widget_show (button);
4843 ctk_box_pack_start (CTK_BOX (hbox)((((CtkBox*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((hbox)), ((ctk_box_get_type ()))))))
, button, FALSE(0), FALSE(0), 0);
4844 g_signal_connect (button, "clicked",g_signal_connect_data ((button), ("clicked"), (((GCallback) (
apply_recursive_clicked))), (window), ((void*)0), (GConnectFlags
) 0)
4845 G_CALLBACK (apply_recursive_clicked),g_signal_connect_data ((button), ("clicked"), (((GCallback) (
apply_recursive_clicked))), (window), ((void*)0), (GConnectFlags
) 0)
4846 window)g_signal_connect_data ((button), ("clicked"), (((GCallback) (
apply_recursive_clicked))), (window), ((void*)0), (GConnectFlags
) 0)
;
4847 }
4848 } else {
4849 char *prompt_text;
4850
4851 if (!is_multi_file_window (window)) {
4852 char *file_name;
4853
4854 file_name = baul_file_get_display_name (get_target_file (window));
4855 prompt_text = g_strdup_printf (_("The permissions of \"%s\" could not be determined.")gettext ("The permissions of \"%s\" could not be determined."
)
, file_name);
4856 g_free (file_name);
4857 } else {
4858 prompt_text = g_strdup (_("The permissions of the selected file could not be determined."))g_strdup_inline (gettext ("The permissions of the selected file could not be determined."
))
;
4859 }
4860
4861 add_prompt (vbox, prompt_text, TRUE(!(0)));
4862 g_free (prompt_text);
4863 }
4864}
4865
4866static void
4867append_extension_pages (FMPropertiesWindow *window)
4868{
4869 GList *providers;
4870 GList *module_providers;
4871 GList *p;
4872
4873 providers = baul_extensions_get_for_type (BAUL_TYPE_PROPERTY_PAGE_PROVIDER(baul_property_page_provider_get_type ()));
4874
4875 /* FIXME: we also need the property pages from two old modules that
4876 * are not registered as proper extensions. This is going to work
4877 * this way until some generic solution is introduced.
4878 */
4879 module_providers = baul_module_get_extensions_for_type (BAUL_TYPE_PROPERTY_PAGE_PROVIDER(baul_property_page_provider_get_type ()));
4880 for (p = module_providers; p != NULL((void*)0); p = p->next) {
4881 const gchar *type_name = G_OBJECT_TYPE_NAME (G_OBJECT (p->data))(g_type_name ((((((GTypeClass*) (((GTypeInstance*) (((((GObject
*) (void *) g_type_check_instance_cast ((GTypeInstance*) ((p->
data)), (((GType) ((20) << (2))))))))))->g_class))->
g_type)))))
;
4882 if (g_strcmp0 (type_name, "BaulNotesViewerProvider") == 0 ||
4883 g_strcmp0 (type_name, "BaulImagePropertiesPageProvider") == 0) {
4884 providers = g_list_prepend (providers, p->data);
4885 }
4886 }
4887
4888 for (p = providers; p != NULL((void*)0); p = p->next) {
4889 BaulPropertyPageProvider *provider;
4890 GList *pages;
4891 GList *l;
4892
4893 provider = BAUL_PROPERTY_PAGE_PROVIDER (p->data)((((BaulPropertyPageProvider*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((p->data)), ((baul_property_page_provider_get_type
()))))))
;
4894
4895 pages = baul_property_page_provider_get_pages
4896 (provider, window->details->original_files);
4897
4898 for (l = pages; l != NULL((void*)0); l = l->next) {
4899 BaulPropertyPage *page;
4900 CtkWidget *page_widget;
4901 CtkWidget *label;
4902
4903 page = BAUL_PROPERTY_PAGE (l->data)((((BaulPropertyPage*) (void *) g_type_check_instance_cast ((
GTypeInstance*) ((l->data)), ((baul_property_page_get_type
()))))))
;
4904
4905 g_object_get (G_OBJECT (page)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((page)), (((GType) ((20) << (2))))))))
,
4906 "page", &page_widget, "label", &label,
4907 NULL((void*)0));
4908
4909 ctk_notebook_append_page (window->details->notebook,
4910 page_widget, label);
4911
4912 g_object_set_data (G_OBJECT (page_widget)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((page_widget)), (((GType) ((20) << (2))))))))
,
4913 "is-extension-page",
4914 page);
4915
4916 g_object_unref (page_widget);
4917 g_object_unref (label);
4918
4919 g_object_unref (page);
4920 }
4921
4922 g_list_free (pages);
4923 }
4924
4925 baul_module_extension_list_free (providers);
4926}
4927
4928static gboolean
4929should_show_emblems (FMPropertiesWindow *window)
4930{
4931 /* FIXME bugzilla.gnome.org 45643:
4932 * Emblems aren't displayed on the the desktop Trash icon, so
4933 * we shouldn't pretend that they work by showing them here.
4934 * When bug 5643 is fixed we can remove this case.
4935 */
4936 if (!is_multi_file_window (window)
4937 && is_merged_trash_directory (get_target_file (window))) {
4938 return FALSE(0);
4939 }
4940
4941 return TRUE(!(0));
4942}
4943
4944static gboolean
4945should_show_permissions (FMPropertiesWindow *window)
4946{
4947 BaulFile *file;
4948
4949 file = get_target_file (window);
4950
4951 /* Don't show permissions for Trash and Computer since they're not
4952 * really file system objects.
4953 */
4954 if (!is_multi_file_window (window)
4955 && (is_merged_trash_directory (file) ||
4956 is_computer_directory (file))) {
4957 return FALSE(0);
4958 }
4959
4960 return TRUE(!(0));
4961}
4962
4963static char *
4964get_pending_key (GList *file_list)
4965{
4966 GList *l;
4967 GList *uris;
4968 GString *key;
4969 char *ret;
4970
4971 uris = NULL((void*)0);
4972 for (l = file_list; l != NULL((void*)0); l = l->next) {
4973 uris = g_list_prepend (uris, baul_file_get_uri (BAUL_FILE (l->data)((((BaulFile*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((l->data)), (baul_file_get_type())))))
));
4974 }
4975 uris = g_list_sort (uris, (GCompareFunc)strcmp);
4976
4977 key = g_string_new ("");
4978 for (l = uris; l != NULL((void*)0); l = l->next) {
4979 g_string_append (key, l->data)(__builtin_constant_p (l->data) ? __extension__ ({ const char
* const __val = (l->data); g_string_append_len_inline (key
, __val, (__val != ((void*)0)) ? (gssize) strlen (((__val) + !
(__val))) : (gssize) -1); }) : g_string_append_len_inline (key
, l->data, (gssize) -1))
;
4980 g_string_append (key, ";")(__builtin_constant_p (";") ? __extension__ ({ const char * const
__val = (";"); g_string_append_len_inline (key, __val, (__val
!= ((void*)0)) ? (gssize) strlen (((__val) + !(__val))) : (gssize
) -1); }) : g_string_append_len_inline (key, ";", (gssize) -1
))
;
4981 }
4982
4983 g_list_free_full (uris, g_free);
4984
4985 ret = key->str;
4986 g_string_free (key, FALSE)(__builtin_constant_p ((0)) ? (((0)) ? (g_string_free) ((key)
, ((0))) : g_string_free_and_steal (key)) : (g_string_free) (
(key), ((0))))
;
4987
4988 return ret;
4989}
4990
4991static StartupData *
4992startup_data_new (GList *original_files,
4993 GList *target_files,
4994 const char *pending_key,
4995 CtkWidget *parent_widget)
4996{
4997 StartupData *data;
4998 GList *l;
4999
5000 data = g_new0 (StartupData, 1)((StartupData *) g_malloc0_n ((1), sizeof (StartupData)));
5001 data->original_files = baul_file_list_copy (original_files);
5002 data->target_files = baul_file_list_copy (target_files);
5003 data->parent_widget = parent_widget;
5004 data->pending_key = g_strdup (pending_key)g_strdup_inline (pending_key);
5005 data->pending_files = g_hash_table_new (g_direct_hash,
5006 g_direct_equal);
5007
5008 for (l = data->target_files; l != NULL((void*)0); l = l->next) {
5009 g_hash_table_insert (data->pending_files, l->data, l->data);
5010 }
5011
5012 return data;
5013}
5014
5015static void
5016startup_data_free (StartupData *data)
5017{
5018 baul_file_list_free (data->original_files);
5019 baul_file_list_free (data->target_files);
5020 g_hash_table_destroy (data->pending_files);
5021 g_free (data->pending_key);
5022 g_free (data);
5023}
5024
5025static void
5026file_changed_callback (BaulFile *file, gpointer user_data)
5027{
5028 FMPropertiesWindow *window = FM_PROPERTIES_WINDOW (user_data)((((FMPropertiesWindow*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((user_data)), (fm_properties_window_get_type
())))))
;
5029
5030 if (!g_list_find (window->details->changed_files, file)) {
5031 baul_file_ref (file);
5032 window->details->changed_files = g_list_prepend (window->details->changed_files, file);
5033
5034 schedule_files_update (window);
5035 }
5036}
5037
5038static gboolean
5039is_a_special_file (BaulFile *file)
5040{
5041 if (file == NULL((void*)0) ||
5042 BAUL_IS_DESKTOP_ICON_FILE (file)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(file)); GType __t = (baul_desktop_icon_file_get_type()); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; }))))
||
5043 is_merged_trash_directory (file) ||
5044 is_computer_directory (file)) {
5045 return TRUE(!(0));
5046 }
5047 return FALSE(0);
5048}
5049
5050static gboolean
5051should_show_open_with (FMPropertiesWindow *window)
5052{
5053 BaulFile *file;
5054
5055 /* Don't show open with tab for desktop special icons (trash, etc)
5056 * We don't get the open-with menu for these anyway.
5057 *
5058 * Also don't show it for folders. Changing the default app for folders
5059 * leads to all sort of hard to understand errors.
5060 */
5061
5062 if (is_multi_file_window (window)) {
5063 if (!file_list_attributes_identical (window->details->original_files,
5064 "mime_type")) {
5065 return FALSE(0);
5066 } else {
5067
5068 GList *l;
5069
5070 for (l = window->details->original_files; l; l = l->next) {
5071 file = BAUL_FILE (l->data)((((BaulFile*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((l->data)), (baul_file_get_type())))))
;
5072 if (baul_file_is_directory (file) ||
5073 is_a_special_file (file)) {
5074 return FALSE(0);
5075 }
5076 }
5077 }
5078 } else {
5079 file = get_original_file (window);
5080 if (baul_file_is_directory (file) ||
5081 is_a_special_file (file)) {
5082 return FALSE(0);
5083 }
5084 }
5085 return TRUE(!(0));
5086}
5087
5088static void
5089create_open_with_page (FMPropertiesWindow *window)
5090{
5091 CtkWidget *vbox;
5092 char *mime_type;
5093
5094 mime_type = baul_file_get_mime_type (get_target_file (window));
5095
5096 if (!is_multi_file_window (window)) {
5097 char *uri;
5098
5099 uri = baul_file_get_uri (get_target_file (window));
5100
5101 if (uri == NULL((void*)0)) {
5102 return;
5103 }
5104
5105 vbox = baul_mime_application_chooser_new (uri, mime_type);
5106
5107 g_free (uri);
5108 } else {
5109 GList *uris;
5110
5111 uris = window->details->original_files;
5112 if (uris == NULL((void*)0)) {
5113 return;
5114 }
5115 vbox = baul_mime_application_chooser_new_for_multiple_files (uris, mime_type);
5116 }
5117
5118 ctk_widget_show (vbox);
5119 g_free (mime_type);
5120
5121 ctk_notebook_append_page (window->details->notebook,
5122 vbox, ctk_label_new (_("Open With")gettext ("Open With")));
5123}
5124
5125
5126static FMPropertiesWindow *
5127create_properties_window (StartupData *startup_data)
5128{
5129 FMPropertiesWindow *window;
5130 GList *l;
5131 CtkWidget *action_area;
5132
5133 window = FM_PROPERTIES_WINDOW (ctk_widget_new (fm_properties_window_get_type (), NULL))((((FMPropertiesWindow*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((ctk_widget_new (fm_properties_window_get_type
(), ((void*)0)))), (fm_properties_window_get_type())))))
;
5134
5135 window->details->original_files = baul_file_list_copy (startup_data->original_files);
5136
5137 window->details->target_files = baul_file_list_copy (startup_data->target_files);
5138
5139 ctk_window_set_screen (CTK_WINDOW (window)((((CtkWindow*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((window)), ((ctk_window_get_type ()))))))
,
5140 ctk_widget_get_screen (startup_data->parent_widget));
5141
5142 ctk_window_set_type_hint (CTK_WINDOW (window)((((CtkWindow*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((window)), ((ctk_window_get_type ()))))))
, CDK_WINDOW_TYPE_HINT_DIALOG);
5143
5144 /* Set initial window title */
5145 update_properties_window_title (window);
5146
5147 /* Start monitoring the file attributes we display. Note that some
5148 * of the attributes are for the original file, and some for the
5149 * target files.
5150 */
5151
5152 for (l = window->details->original_files; l != NULL((void*)0); l = l->next) {
5153 BaulFile *file;
5154 BaulFileAttributes attributes;
5155
5156 file = BAUL_FILE (l->data)((((BaulFile*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((l->data)), (baul_file_get_type())))))
;
5157
5158 attributes =
5159 BAUL_FILE_ATTRIBUTES_FOR_ICON(BAUL_FILE_ATTRIBUTE_INFO | BAUL_FILE_ATTRIBUTE_LINK_INFO | BAUL_FILE_ATTRIBUTE_THUMBNAIL
)
|
5160 BAUL_FILE_ATTRIBUTE_INFO |
5161 BAUL_FILE_ATTRIBUTE_LINK_INFO;
5162
5163 baul_file_monitor_add (file,
5164 &window->details->original_files,
5165 attributes);
5166 }
5167
5168 for (l = window->details->target_files; l != NULL((void*)0); l = l->next) {
5169 BaulFile *file;
5170 BaulFileAttributes attributes;
5171
5172 file = BAUL_FILE (l->data)((((BaulFile*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((l->data)), (baul_file_get_type())))))
;
5173
5174 attributes = 0;
5175 if (baul_file_is_directory (file)) {
5176 attributes |= BAUL_FILE_ATTRIBUTE_DEEP_COUNTS;
5177 }
5178
5179 attributes |= BAUL_FILE_ATTRIBUTE_INFO;
5180 baul_file_monitor_add (file, &window->details->target_files, attributes);
5181 }
5182
5183 for (l = window->details->target_files; l != NULL((void*)0); l = l->next) {
5184 g_signal_connect_object (BAUL_FILE (l->data)((((BaulFile*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((l->data)), (baul_file_get_type())))))
,
5185 "changed",
5186 G_CALLBACK (file_changed_callback)((GCallback) (file_changed_callback)),
5187 G_OBJECT (window)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((window)), (((GType) ((20) << (2))))))))
,
5188 0);
5189 }
5190
5191 for (l = window->details->original_files; l != NULL((void*)0); l = l->next) {
5192 g_signal_connect_object (BAUL_FILE (l->data)((((BaulFile*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((l->data)), (baul_file_get_type())))))
,
5193 "changed",
5194 G_CALLBACK (file_changed_callback)((GCallback) (file_changed_callback)),
5195 G_OBJECT (window)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((window)), (((GType) ((20) << (2))))))))
,
5196 0);
5197 }
5198
5199 /* Create the notebook tabs. */
5200 window->details->notebook = CTK_NOTEBOOK (ctk_notebook_new ())((((CtkNotebook*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((ctk_notebook_new ())), ((ctk_notebook_get_type ()))))))
;
5201
5202 ctk_notebook_set_scrollable (CTK_NOTEBOOK (window->details->notebook)((((CtkNotebook*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((window->details->notebook)), ((ctk_notebook_get_type
()))))))
, TRUE(!(0)));
5203 ctk_widget_add_events (CTK_WIDGET (window->details->notebook)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((window->details->notebook)), ((ctk_widget_get_type
()))))))
, CDK_SCROLL_MASK);
5204 g_signal_connect (window->details->notebook,g_signal_connect_data ((window->details->notebook), ("scroll-event"
), (((GCallback) (eel_dialog_page_scroll_event_callback))), (
window), ((void*)0), (GConnectFlags) 0)
5205 "scroll-event",g_signal_connect_data ((window->details->notebook), ("scroll-event"
), (((GCallback) (eel_dialog_page_scroll_event_callback))), (
window), ((void*)0), (GConnectFlags) 0)
5206 G_CALLBACK (eel_dialog_page_scroll_event_callback),g_signal_connect_data ((window->details->notebook), ("scroll-event"
), (((GCallback) (eel_dialog_page_scroll_event_callback))), (
window), ((void*)0), (GConnectFlags) 0)
5207 window)g_signal_connect_data ((window->details->notebook), ("scroll-event"
), (((GCallback) (eel_dialog_page_scroll_event_callback))), (
window), ((void*)0), (GConnectFlags) 0)
;
5208
5209 ctk_widget_show (CTK_WIDGET (window->details->notebook)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((window->details->notebook)), ((ctk_widget_get_type
()))))))
);
5210 ctk_box_pack_start (CTK_BOX (ctk_dialog_get_content_area (CTK_DIALOG (window)))((((CtkBox*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((ctk_dialog_get_content_area (((((CtkDialog*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((window)), ((ctk_dialog_get_type ()))))))
))), ((ctk_box_get_type ()))))))
,
5211 CTK_WIDGET (window->details->notebook)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((window->details->notebook)), ((ctk_widget_get_type
()))))))
,
5212 TRUE(!(0)), TRUE(!(0)), 0);
5213
5214 /* Create the pages. */
5215 create_basic_page (window);
5216
5217 if (should_show_emblems (window)) {
5218 create_emblems_page (window);
5219 }
5220
5221 if (should_show_permissions (window)) {
5222 create_permissions_page (window);
5223 }
5224
5225 if (should_show_open_with (window)) {
5226 create_open_with_page (window);
5227 }
5228
5229 /* append pages from available views */
5230 append_extension_pages (window);
5231
5232 eel_dialog_add_button (CTK_DIALOG (window)((((CtkDialog*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((window)), ((ctk_dialog_get_type ()))))))
,
5233 _("_Help")gettext ("_Help"),
5234 "help-browser",
5235 CTK_RESPONSE_HELP);
5236
5237 action_area = ctk_widget_get_parent (eel_dialog_add_button (CTK_DIALOG (window)((((CtkDialog*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((window)), ((ctk_dialog_get_type ()))))))
,
5238 _("_Close")gettext ("_Close"),
5239 "window-close",
5240 CTK_RESPONSE_CLOSE));
5241
5242 /* FIXME - HIGificiation, should be done inside CTK+ */
5243 ctk_container_set_border_width (CTK_CONTAINER (ctk_dialog_get_content_area (CTK_DIALOG (window)))((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((ctk_dialog_get_content_area (((((CtkDialog*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((window)), ((ctk_dialog_get_type ()))))))
))), ((ctk_container_get_type ()))))))
, 12);
5244 ctk_container_set_border_width (CTK_CONTAINER (action_area)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((action_area)), ((ctk_container_get_type ()))))))
, 0);
5245 ctk_box_set_spacing (CTK_BOX (ctk_dialog_get_content_area (CTK_DIALOG (window)))((((CtkBox*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((ctk_dialog_get_content_area (((((CtkDialog*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((window)), ((ctk_dialog_get_type ()))))))
))), ((ctk_box_get_type ()))))))
, 12);
5246
5247 /* Update from initial state */
5248 properties_window_update (window, NULL((void*)0));
5249
5250 return window;
5251}
5252
5253static GList *
5254get_target_file_list (GList *original_files)
5255{
5256 GList *ret;
5257 GList *l;
5258
5259 ret = NULL((void*)0);
5260
5261 for (l = original_files; l != NULL((void*)0); l = l->next) {
5262 BaulFile *target;
5263
5264 target = get_target_file_for_original_file (BAUL_FILE (l->data)((((BaulFile*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((l->data)), (baul_file_get_type())))))
);
5265
5266 ret = g_list_prepend (ret, target);
5267 }
5268
5269 ret = g_list_reverse (ret);
5270
5271 return ret;
5272}
5273
5274static void
5275add_window (FMPropertiesWindow *window)
5276{
5277 if (!is_multi_file_window (window)) {
5278 g_hash_table_insert (windows,
5279 get_original_file (window),
5280 window);
5281 g_object_set_data (G_OBJECT (window)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((window)), (((GType) ((20) << (2))))))))
, "window_key",
5282 get_original_file (window));
5283 }
5284}
5285
5286static void
5287remove_window (FMPropertiesWindow *window)
5288{
5289 gpointer key;
5290
5291 key = g_object_get_data (G_OBJECT (window)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((window)), (((GType) ((20) << (2))))))))
, "window_key");
5292 if (key) {
5293 g_hash_table_remove (windows, key);
5294 }
5295}
5296
5297static CtkWindow *
5298get_existing_window (GList *file_list)
5299{
5300 if (!file_list->next) {
5301 return g_hash_table_lookup (windows, file_list->data);
5302 }
5303
5304 return NULL((void*)0);
5305}
5306
5307static void
5308cancel_create_properties_window_callback (gpointer callback_data)
5309{
5310 remove_pending ((StartupData *)callback_data, TRUE(!(0)), FALSE(0), TRUE(!(0)));
5311}
5312
5313static void
5314parent_widget_destroyed_callback (CtkWidget *widget, gpointer callback_data)
5315{
5316 g_assert (widget == ((StartupData *)callback_data)->parent_widget)do { if (widget == ((StartupData *)callback_data)->parent_widget
) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 5316, ((const char*) (__func__)), "widget == ((StartupData *)callback_data)->parent_widget"
); } while (0)
;
5317
5318 remove_pending ((StartupData *)callback_data, TRUE(!(0)), TRUE(!(0)), FALSE(0));
5319}
5320
5321static void
5322cancel_call_when_ready_callback (gpointer key,
5323 gpointer value G_GNUC_UNUSED__attribute__ ((__unused__)),
5324 gpointer user_data)
5325{
5326 baul_file_cancel_call_when_ready
5327 (BAUL_FILE (key)((((BaulFile*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((key)), (baul_file_get_type())))))
,
5328 is_directory_ready_callback,
5329 user_data);
5330}
5331
5332static void
5333remove_pending (StartupData *startup_data,
5334 gboolean cancel_call_when_ready,
5335 gboolean cancel_timed_wait,
5336 gboolean cancel_destroy_handler)
5337{
5338 if (cancel_call_when_ready) {
5339 g_hash_table_foreach (startup_data->pending_files,
5340 cancel_call_when_ready_callback,
5341 startup_data);
5342
5343 }
5344 if (cancel_timed_wait) {
5345 eel_timed_wait_stop
5346 (cancel_create_properties_window_callback, startup_data);
5347 }
5348 if (cancel_destroy_handler) {
5349 g_signal_handlers_disconnect_by_func (startup_data->parent_widget,g_signal_handlers_disconnect_matched ((startup_data->parent_widget
), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (((GCallback) (parent_widget_destroyed_callback
))), (startup_data))
5350 G_CALLBACK (parent_widget_destroyed_callback),g_signal_handlers_disconnect_matched ((startup_data->parent_widget
), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (((GCallback) (parent_widget_destroyed_callback
))), (startup_data))
5351 startup_data)g_signal_handlers_disconnect_matched ((startup_data->parent_widget
), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (((GCallback) (parent_widget_destroyed_callback
))), (startup_data))
;
5352 }
5353
5354 g_hash_table_remove (pending_lists, startup_data->pending_key);
5355
5356 startup_data_free (startup_data);
5357}
5358
5359static void
5360is_directory_ready_callback (BaulFile *file,
5361 gpointer data)
5362{
5363 StartupData *startup_data;
5364
5365 startup_data = data;
5366
5367 g_hash_table_remove (startup_data->pending_files, file);
5368
5369 if (g_hash_table_size (startup_data->pending_files) == 0) {
5370 FMPropertiesWindow *new_window;
5371
5372 new_window = create_properties_window (startup_data);
5373
5374 add_window (new_window);
5375
5376 remove_pending (startup_data, FALSE(0), TRUE(!(0)), TRUE(!(0)));
5377
5378 ctk_window_present (CTK_WINDOW (new_window)((((CtkWindow*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((new_window)), ((ctk_window_get_type ()))))))
);
5379 }
5380}
5381
5382
5383void
5384fm_properties_window_present (GList *original_files,
5385 CtkWidget *parent_widget)
5386{
5387 GList *l, *next;
5388 CtkWidget *parent_window;
5389 StartupData *startup_data;
5390 GList *target_files;
5391 CtkWindow *existing_window;
5392 char *pending_key;
5393
5394 g_return_if_fail (original_files != NULL)do { if ((original_files != ((void*)0))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "original_files != NULL"
); return; } } while (0)
;
5395 g_return_if_fail (CTK_IS_WIDGET (parent_widget))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((parent_widget)); GType __t = ((ctk_widget_get_type ()));
gboolean __r; if (!__inst) __r = (0); else if (__inst->g_class
&& __inst->g_class->g_type == __t) __r = (!(0)
); else __r = g_type_check_instance_is_a (__inst, __t); __r; }
)))))) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "CTK_IS_WIDGET (parent_widget)"); return
; } } while (0)
;
5396
5397 /* Create the hash tables first time through. */
5398 if (windows == NULL((void*)0)) {
5399 windows = eel_g_hash_table_new_free_at_exit
5400 (NULL((void*)0), NULL((void*)0), "property windows");
5401 }
5402
5403 if (pending_lists == NULL((void*)0)) {
5404 pending_lists = eel_g_hash_table_new_free_at_exit
5405 (g_str_hash, g_str_equal, "pending property window files");
5406 }
5407
5408 /* Look to see if there's already a window for this file. */
5409 existing_window = get_existing_window (original_files);
5410 if (existing_window != NULL((void*)0)) {
5411 ctk_window_set_screen (existing_window,
5412 ctk_widget_get_screen (parent_widget));
5413 ctk_window_present (existing_window);
5414 return;
5415 }
5416
5417
5418 pending_key = get_pending_key (original_files);
5419
5420 /* Look to see if we're already waiting for a window for this file. */
5421 if (g_hash_table_lookup (pending_lists, pending_key) != NULL((void*)0)) {
5422 return;
5423 }
5424
5425 target_files = get_target_file_list (original_files);
5426
5427 startup_data = startup_data_new (original_files,
5428 target_files,
5429 pending_key,
5430 parent_widget);
5431
5432 baul_file_list_free (target_files);
5433 g_free(pending_key);
5434
5435 /* Wait until we can tell whether it's a directory before showing, since
5436 * some one-time layout decisions depend on that info.
5437 */
5438
5439 g_hash_table_insert (pending_lists, startup_data->pending_key, startup_data->pending_key);
5440 g_signal_connect (parent_widget, "destroy",g_signal_connect_data ((parent_widget), ("destroy"), (((GCallback
) (parent_widget_destroyed_callback))), (startup_data), ((void
*)0), (GConnectFlags) 0)
5441 G_CALLBACK (parent_widget_destroyed_callback), startup_data)g_signal_connect_data ((parent_widget), ("destroy"), (((GCallback
) (parent_widget_destroyed_callback))), (startup_data), ((void
*)0), (GConnectFlags) 0)
;
5442
5443 parent_window = ctk_widget_get_ancestor (parent_widget, CTK_TYPE_WINDOW(ctk_window_get_type ()));
5444
5445 eel_timed_wait_start
5446 (cancel_create_properties_window_callback,
5447 startup_data,
5448 _("Creating Properties window.")gettext ("Creating Properties window."),
5449 parent_window == NULL((void*)0) ? NULL((void*)0) : CTK_WINDOW (parent_window)((((CtkWindow*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((parent_window)), ((ctk_window_get_type ()))))))
);
5450
5451
5452 for (l = startup_data->target_files; l != NULL((void*)0); l = next) {
5453 next = l->next;
5454 baul_file_call_when_ready
5455 (BAUL_FILE (l->data)((((BaulFile*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((l->data)), (baul_file_get_type())))))
,
5456 BAUL_FILE_ATTRIBUTE_INFO,
5457 is_directory_ready_callback,
5458 startup_data);
5459 }
5460}
5461
5462static void
5463real_response (CtkDialog *dialog,
5464 int response)
5465{
5466 GError *error = NULL((void*)0);
5467
5468 switch (response) {
5469 case CTK_RESPONSE_HELP:
5470 ctk_show_uri_on_window (CTK_WINDOW (dialog)((((CtkWindow*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((dialog)), ((ctk_window_get_type ()))))))
,
5471 "help:cafe-user-guide/gosbaul-51",
5472 ctk_get_current_event_time (),
5473 &error);
5474 if (error != NULL((void*)0)) {
5475 eel_show_error_dialog (_("There was an error displaying help.")gettext ("There was an error displaying help."), error->message,
5476 CTK_WINDOW (dialog)((((CtkWindow*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((dialog)), ((ctk_window_get_type ()))))))
);
5477 g_error_free (error);
5478 }
5479 break;
5480
5481 case CTK_RESPONSE_NONE:
5482 case CTK_RESPONSE_CLOSE:
5483 case CTK_RESPONSE_DELETE_EVENT:
5484 ctk_widget_destroy (CTK_WIDGET (dialog)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((dialog)), ((ctk_widget_get_type ()))))))
);
5485 break;
5486
5487 default:
5488 g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 5488, ((const char*) (__func__)), ((void*)0)); } while (0)
;
5489 break;
5490 }
5491}
5492
5493static void
5494real_destroy (CtkWidget *object)
5495{
5496 FMPropertiesWindow *window;
5497 GList *l;
5498
5499 window = FM_PROPERTIES_WINDOW (object)((((FMPropertiesWindow*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((object)), (fm_properties_window_get_type()
)))))
;
5500
5501 remove_window (window);
5502
5503 for (l = window->details->original_files; l != NULL((void*)0); l = l->next) {
5504 baul_file_monitor_remove (BAUL_FILE (l->data)((((BaulFile*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((l->data)), (baul_file_get_type())))))
, &window->details->original_files);
5505 }
5506 baul_file_list_free (window->details->original_files);
5507 window->details->original_files = NULL((void*)0);
5508
5509 for (l = window->details->target_files; l != NULL((void*)0); l = l->next) {
5510 baul_file_monitor_remove (BAUL_FILE (l->data)((((BaulFile*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((l->data)), (baul_file_get_type())))))
, &window->details->target_files);
5511 }
5512 baul_file_list_free (window->details->target_files);
5513 window->details->target_files = NULL((void*)0);
5514
5515 baul_file_list_free (window->details->changed_files);
5516 window->details->changed_files = NULL((void*)0);
5517
5518 window->details->name_field = NULL((void*)0);
5519
5520 g_list_free (window->details->emblem_buttons);
5521 window->details->emblem_buttons = NULL((void*)0);
5522
5523 if (window->details->initial_emblems) {
5524 g_hash_table_destroy (window->details->initial_emblems);
5525 window->details->initial_emblems = NULL((void*)0);
5526 }
5527
5528 g_list_free (window->details->permission_buttons);
5529 window->details->permission_buttons = NULL((void*)0);
5530
5531 g_list_free (window->details->permission_combos);
5532 window->details->permission_combos = NULL((void*)0);
5533
5534 if (window->details->initial_permissions) {
5535 g_hash_table_destroy (window->details->initial_permissions);
5536 window->details->initial_permissions = NULL((void*)0);
5537 }
5538
5539 g_list_free (window->details->value_fields);
5540 window->details->value_fields = NULL((void*)0);
5541
5542 if (window->details->update_directory_contents_timeout_id != 0) {
5543 g_source_remove (window->details->update_directory_contents_timeout_id);
5544 window->details->update_directory_contents_timeout_id = 0;
5545 }
5546
5547 if (window->details->update_files_timeout_id != 0) {
5548 g_source_remove (window->details->update_files_timeout_id);
5549 window->details->update_files_timeout_id = 0;
5550 }
5551
5552 CTK_WIDGET_CLASS (fm_properties_window_parent_class)((((CtkWidgetClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((fm_properties_window_parent_class)), ((ctk_widget_get_type
()))))))
->destroy (object);
5553}
5554
5555static void
5556real_finalize (GObject *object)
5557{
5558 FMPropertiesWindow *window;
5559
5560 window = FM_PROPERTIES_WINDOW (object)((((FMPropertiesWindow*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((object)), (fm_properties_window_get_type()
)))))
;
5561
5562 g_list_free_full (window->details->mime_list, g_free);
5563
5564 g_free (window->details->pending_name);
5565
5566 G_OBJECT_CLASS (fm_properties_window_parent_class)((((GObjectClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((fm_properties_window_parent_class)), (((GType) ((20) <<
(2))))))))
->finalize (object);
5567}
5568
5569/* converts
5570 * file://foo/foobar/foofoo/bar
5571 * to
5572 * foofoo/bar
5573 * if
5574 * file://foo/foobar
5575 * is the parent
5576 *
5577 * It does not resolve any symlinks.
5578 * */
5579static char *
5580make_relative_uri_from_full (const char *uri,
5581 const char *base_uri)
5582{
5583 g_assert (uri != NULL)do { if (uri != ((void*)0)) ; else g_assertion_message_expr (
((gchar*) 0), "fm-properties-window.c", 5583, ((const char*) (
__func__)), "uri != NULL"); } while (0)
;
5584 g_assert (base_uri != NULL)do { if (base_uri != ((void*)0)) ; else g_assertion_message_expr
(((gchar*) 0), "fm-properties-window.c", 5584, ((const char*
) (__func__)), "base_uri != NULL"); } while (0)
;
5585
5586 if (g_str_has_prefix (uri, base_uri)(__builtin_constant_p (base_uri)? __extension__ ({ const char
* const __str = (uri); const char * const __prefix = (base_uri
); gboolean __result = (0); if (__str == ((void*)0) || __prefix
== ((void*)0)) __result = (g_str_has_prefix) (__str, __prefix
); else { const size_t __str_len = strlen (((__str) + !(__str
))); const size_t __prefix_len = strlen (((__prefix) + !(__prefix
))); if (__str_len >= __prefix_len) __result = memcmp (((__str
) + !(__str)), ((__prefix) + !(__prefix)), __prefix_len) == 0
; } __result; }) : (g_str_has_prefix) (uri, base_uri) )
) {
5587 uri += strlen (base_uri);
5588 if (*uri != '/') {
5589 return NULL((void*)0);
5590 }
5591
5592 while (*uri == '/') {
5593 uri++;
5594 }
5595
5596 if (*uri != '\0') {
5597 return g_strdup (uri)g_strdup_inline (uri);
5598 }
5599 }
5600
5601 return NULL((void*)0);
5602}
5603
5604/* icon selection callback to set the image of the file object to the selected file */
5605static void
5606set_icon (const char* icon_uri, FMPropertiesWindow *properties_window)
5607{
5608 char *icon_path;
5609
5610 g_assert (icon_uri != NULL)do { if (icon_uri != ((void*)0)) ; else g_assertion_message_expr
(((gchar*) 0), "fm-properties-window.c", 5610, ((const char*
) (__func__)), "icon_uri != NULL"); } while (0)
;
5611 g_assert (FM_IS_PROPERTIES_WINDOW (properties_window))do { if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((properties_window)); GType __t = (fm_properties_window_get_type
()); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 5611, ((const char*) (__func__)), "FM_IS_PROPERTIES_WINDOW (properties_window)"
); } while (0)
;
5612
5613 icon_path = g_filename_from_uri (icon_uri, NULL((void*)0), NULL((void*)0));
5614 /* we don't allow remote URIs */
5615 if (icon_path != NULL((void*)0)) {
5616 GList *l;
5617 BaulFile *file = NULL((void*)0);
5618
5619 for (l = properties_window->details->original_files; l != NULL((void*)0); l = l->next) {
5620 char *file_uri;
5621
5622 file = BAUL_FILE (l->data)((((BaulFile*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((l->data)), (baul_file_get_type())))))
;
5623
5624 file_uri = baul_file_get_uri (file);
5625
5626 if (baul_file_is_mime_type (file, "application/x-desktop")) {
5627 if (baul_link_local_set_icon (file_uri, icon_path)) {
5628 baul_file_invalidate_attributes (file,
5629 BAUL_FILE_ATTRIBUTE_INFO |
5630 BAUL_FILE_ATTRIBUTE_LINK_INFO);
5631 }
5632 } else {
5633 char *real_icon_uri;
5634
5635 real_icon_uri = make_relative_uri_from_full (icon_uri, file_uri);
5636
5637 if (real_icon_uri == NULL((void*)0)) {
5638 real_icon_uri = g_strdup (icon_uri)g_strdup_inline (icon_uri);
5639 }
5640
5641 baul_file_set_metadata (file, BAUL_METADATA_KEY_CUSTOM_ICON"custom-icon", NULL((void*)0), real_icon_uri);
5642 baul_file_set_metadata (file, BAUL_METADATA_KEY_ICON_SCALE"icon-scale", NULL((void*)0), NULL((void*)0));
5643
5644 g_free (real_icon_uri);
5645 }
5646
5647 g_free (file_uri);
5648 }
5649
5650 g_free (icon_path);
5651 }
5652}
5653
5654static void
5655update_preview_callback (CtkFileChooser *icon_chooser,
5656 FMPropertiesWindow *window G_GNUC_UNUSED__attribute__ ((__unused__)))
5657{
5658 GdkPixbuf *pixbuf, *scaled_pixbuf;
5659 char *filename;
5660
5661 pixbuf = NULL((void*)0);
5662
5663 filename = ctk_file_chooser_get_filename (icon_chooser);
5664 if (filename != NULL((void*)0)) {
5665 pixbuf = gdk_pixbuf_new_from_file (filename, NULL((void*)0));
5666 }
5667
5668 if (pixbuf != NULL((void*)0)) {
5669 CtkWidget *preview_widget;
5670
5671 preview_widget = ctk_file_chooser_get_preview_widget (icon_chooser);
5672 ctk_file_chooser_set_preview_widget_active (icon_chooser, TRUE(!(0)));
5673
5674 if (gdk_pixbuf_get_width (pixbuf) > PREVIEW_IMAGE_WIDTH96) {
5675 double scale;
5676
5677 scale = (double)gdk_pixbuf_get_height (pixbuf) /
5678 gdk_pixbuf_get_width (pixbuf);
5679
5680 scaled_pixbuf = gdk_pixbuf_scale_simple
5681 (pixbuf,
5682 PREVIEW_IMAGE_WIDTH96,
5683 scale * PREVIEW_IMAGE_WIDTH96,
5684 GDK_INTERP_HYPER);
5685 g_object_unref (pixbuf);
5686 pixbuf = scaled_pixbuf;
5687 }
5688
5689 ctk_image_set_from_pixbuf (CTK_IMAGE (preview_widget)((((CtkImage*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((preview_widget)), ((ctk_image_get_type ()))))))
, pixbuf);
5690 } else {
5691 ctk_file_chooser_set_preview_widget_active (icon_chooser, FALSE(0));
5692 }
5693
5694 g_free (filename);
5695
5696 if (pixbuf != NULL((void*)0)) {
5697 g_object_unref (pixbuf);
5698 }
5699}
5700
5701static void
5702custom_icon_file_chooser_response_cb (CtkDialog *dialog,
5703 gint response,
5704 FMPropertiesWindow *window)
5705{
5706 char *uri;
5707
5708 switch (response) {
5709 case CTK_RESPONSE_NO:
5710 reset_icon (window);
5711 break;
5712
5713 case CTK_RESPONSE_OK:
5714 uri = ctk_file_chooser_get_uri (CTK_FILE_CHOOSER (dialog)((((CtkFileChooser*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((dialog)), ((ctk_file_chooser_get_type ()))))))
);
5715 set_icon (uri, window);
5716 g_free (uri);
5717 break;
5718
5719 default:
5720 break;
5721 }
5722
5723 ctk_widget_hide (CTK_WIDGET (dialog)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((dialog)), ((ctk_widget_get_type ()))))))
);
5724}
5725
5726static void
5727select_image_button_callback (CtkWidget *widget G_GNUC_UNUSED__attribute__ ((__unused__)),
5728 FMPropertiesWindow *window)
5729{
5730 CtkWidget *dialog;
5731 GList *l;
5732 BaulFile *file;
5733 char *image_path;
5734 gboolean revert_is_sensitive;
5735
5736 g_assert (FM_IS_PROPERTIES_WINDOW (window))do { if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = (fm_properties_window_get_type());
gboolean __r; if (!__inst) __r = (0); else if (__inst->g_class
&& __inst->g_class->g_type == __t) __r = (!(0)
); else __r = g_type_check_instance_is_a (__inst, __t); __r; }
))))) ; else g_assertion_message_expr (((gchar*) 0), "fm-properties-window.c"
, 5736, ((const char*) (__func__)), "FM_IS_PROPERTIES_WINDOW (window)"
); } while (0)
;
5737
5738 dialog = window->details->icon_chooser;
5739
5740 if (dialog == NULL((void*)0)) {
5741 CtkWidget *preview;
5742 CtkFileFilter *filter;
5743
5744 dialog = eel_file_chooser_dialog_new (_("Select Custom Icon")gettext ("Select Custom Icon"), CTK_WINDOW (window)((((CtkWindow*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((window)), ((ctk_window_get_type ()))))))
,
5745 CTK_FILE_CHOOSER_ACTION_OPEN,
5746 "document-revert", CTK_RESPONSE_NO,
5747 "process-stop", CTK_RESPONSE_CANCEL,
5748 "document-open", CTK_RESPONSE_OK,
5749 NULL((void*)0));
5750 ctk_file_chooser_add_shortcut_folder (CTK_FILE_CHOOSER (dialog)((((CtkFileChooser*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((dialog)), ((ctk_file_chooser_get_type ()))))))
, "/usr/share/icons", NULL((void*)0));
5751 ctk_file_chooser_add_shortcut_folder (CTK_FILE_CHOOSER (dialog)((((CtkFileChooser*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((dialog)), ((ctk_file_chooser_get_type ()))))))
, "/usr/share/pixmaps", NULL((void*)0));
5752 ctk_window_set_destroy_with_parent (CTK_WINDOW (dialog)((((CtkWindow*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((dialog)), ((ctk_window_get_type ()))))))
, TRUE(!(0)));
5753
5754 filter = ctk_file_filter_new ();
5755 ctk_file_filter_add_pixbuf_formats (filter);
5756 ctk_file_chooser_set_filter (CTK_FILE_CHOOSER (dialog)((((CtkFileChooser*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((dialog)), ((ctk_file_chooser_get_type ()))))))
, filter);
5757
5758 preview = ctk_image_new ();
5759 ctk_widget_set_size_request (preview, PREVIEW_IMAGE_WIDTH96, -1);
5760 ctk_file_chooser_set_preview_widget (CTK_FILE_CHOOSER (dialog)((((CtkFileChooser*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((dialog)), ((ctk_file_chooser_get_type ()))))))
, preview);
5761 ctk_file_chooser_set_use_preview_label (CTK_FILE_CHOOSER (dialog)((((CtkFileChooser*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((dialog)), ((ctk_file_chooser_get_type ()))))))
, FALSE(0));
5762 ctk_file_chooser_set_preview_widget_active (CTK_FILE_CHOOSER (dialog)((((CtkFileChooser*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((dialog)), ((ctk_file_chooser_get_type ()))))))
, FALSE(0));
5763
5764 g_signal_connect (dialog, "update-preview",g_signal_connect_data ((dialog), ("update-preview"), (((GCallback
) (update_preview_callback))), (window), ((void*)0), (GConnectFlags
) 0)
5765 G_CALLBACK (update_preview_callback), window)g_signal_connect_data ((dialog), ("update-preview"), (((GCallback
) (update_preview_callback))), (window), ((void*)0), (GConnectFlags
) 0)
;
5766
5767 window->details->icon_chooser = dialog;
5768
5769 g_object_add_weak_pointer (G_OBJECT (dialog)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((dialog)), (((GType) ((20) << (2))))))))
,
5770 (gpointer *) &window->details->icon_chooser);
5771 }
5772
5773 /* it's likely that the user wants to pick an icon that is inside a local directory */
5774 if (g_list_length (window->details->original_files) == 1) {
5775 file = BAUL_FILE (window->details->original_files->data)((((BaulFile*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((window->details->original_files->data)), (baul_file_get_type
())))))
;
5776
5777 if (baul_file_is_directory (file)) {
5778 char *uri;
5779
5780 uri = baul_file_get_uri (file);
5781
5782 image_path = g_filename_from_uri (uri, NULL((void*)0), NULL((void*)0));
5783 if (image_path != NULL((void*)0)) {
5784 ctk_file_chooser_set_current_folder (CTK_FILE_CHOOSER (dialog)((((CtkFileChooser*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((dialog)), ((ctk_file_chooser_get_type ()))))))
, image_path);
5785 g_free (image_path);
5786 }
5787
5788 g_free (uri);
5789 }
5790 }
5791
5792 revert_is_sensitive = FALSE(0);
5793 for (l = window->details->original_files; l != NULL((void*)0); l = l->next) {
5794 file = BAUL_FILE (l->data)((((BaulFile*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((l->data)), (baul_file_get_type())))))
;
5795 image_path = baul_file_get_metadata (file, BAUL_METADATA_KEY_CUSTOM_ICON"custom-icon", NULL((void*)0));
5796 revert_is_sensitive = (image_path != NULL((void*)0));
5797 g_free (image_path);
5798
5799 if (revert_is_sensitive) {
5800 break;
5801 }
5802 }
5803 ctk_dialog_set_response_sensitive (CTK_DIALOG (dialog)((((CtkDialog*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((dialog)), ((ctk_dialog_get_type ()))))))
, CTK_RESPONSE_NO, revert_is_sensitive);
5804
5805 g_signal_connect (dialog, "response",g_signal_connect_data ((dialog), ("response"), (((GCallback) (
custom_icon_file_chooser_response_cb))), (window), ((void*)0)
, (GConnectFlags) 0)
5806 G_CALLBACK (custom_icon_file_chooser_response_cb), window)g_signal_connect_data ((dialog), ("response"), (((GCallback) (
custom_icon_file_chooser_response_cb))), (window), ((void*)0)
, (GConnectFlags) 0)
;
5807 ctk_widget_show (dialog);
5808}
5809
5810static void
5811fm_properties_window_class_init (FMPropertiesWindowClass *class)
5812{
5813 CtkBindingSet *binding_set;
5814
5815 G_OBJECT_CLASS (class)((((GObjectClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((class)), (((GType) ((20) << (2))))))))
->finalize = real_finalize;
5816
5817 CTK_WIDGET_CLASS (class)((((CtkWidgetClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((class)), ((ctk_widget_get_type ()))))))
->destroy = real_destroy;
5818
5819 CTK_DIALOG_CLASS (class)((((CtkDialogClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((class)), ((ctk_dialog_get_type ()))))))
->response = real_response;
5820
5821 binding_set = ctk_binding_set_by_class (class);
5822 ctk_binding_entry_add_signal (binding_set, CDK_KEY_Escape0xff1b, 0,
5823 "close", 0);
5824}
5825
5826static void
5827fm_properties_window_init (FMPropertiesWindow *window)
5828{
5829 window->details = fm_properties_window_get_instance_private (window);
5830}