Bug Summary

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