Bug Summary

File:src/baul-pathbar.c
Warning:line 844, column 17
Access to field 'next' results in a dereference of a null pointer (loaded from variable 'first_button')

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 baul-pathbar.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 -pic-is-pie -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 -resource-dir /usr/lib/llvm-16/lib/clang/16 -D HAVE_CONFIG_H -I . -I .. -I .. -I ../libbaul-private -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 -I /usr/include/exempi-2.0 -D DATADIR="/usr/share" -D LIBDIR="/usr/lib" -D BAUL_DATADIR="/usr/share/baul" -D CAFELOCALEDIR="/usr/share/locale" -D UIDIR="/usr/share/baul/ui" -D BAUL_PIXMAPDIR="/usr/share/pixmaps/baul" -D PREFIX="/usr" -D SYSCONFDIR="/usr/etc" -D VERSION="1.25.0" -D G_DISABLE_DEPRECATED -D GDK_PIXBUF_DISABLE_DEPRECATED -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 -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-08-06-114458-28316-1 -x c baul-pathbar.c
1/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
2/* baul-pathbar.c
3 * Copyright (C) 2004 Red Hat, Inc., Jonathan Blandford <jrb@gnome.org>
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
14 *
15 * You should have received a copy of the GNU Library General Public
16 * License along with this library; if not, write to the
17 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
18 * Boston, MA 02110-1301, USA.
19 */
20
21#include <config.h>
22#include <string.h>
23
24#include <ctk/ctk.h>
25#include <glib/gi18n.h>
26#include <gio/gio.h>
27
28#include <libbaul-private/baul-file.h>
29#include <libbaul-private/baul-file-utilities.h>
30#include <libbaul-private/baul-global-preferences.h>
31#include <libbaul-private/baul-icon-names.h>
32#include <libbaul-private/baul-trash-monitor.h>
33#include <libbaul-private/baul-dnd.h>
34#include <libbaul-private/baul-icon-dnd.h>
35
36#include "baul-pathbar.h"
37
38enum
39{
40 PATH_CLICKED,
41 PATH_EVENT,
42 LAST_SIGNAL
43};
44
45typedef enum
46{
47 NORMAL_BUTTON,
48 ROOT_BUTTON,
49 HOME_BUTTON,
50 DESKTOP_BUTTON,
51 MOUNT_BUTTON,
52 DEFAULT_LOCATION_BUTTON,
53} ButtonType;
54
55#define BUTTON_DATA(x)((ButtonData *)(x)) ((ButtonData *)(x))
56
57#define SCROLL_TIMEOUT150 150
58#define INITIAL_SCROLL_TIMEOUT300 300
59
60static guint path_bar_signals [LAST_SIGNAL] = { 0 };
61
62static gboolean desktop_is_home;
63
64#define BAUL_PATH_BAR_ICON_SIZE16 16
65
66typedef struct _ButtonData ButtonData;
67
68struct _ButtonData
69{
70 CtkWidget *button;
71 ButtonType type;
72 char *dir_name;
73 GFile *path;
74 BaulFile *file;
75 unsigned int file_changed_signal_id;
76
77 /* custom icon */
78 cairo_surface_t *custom_icon;
79
80 /* flag to indicate its the base folder in the URI */
81 gboolean is_base_dir;
82
83 CtkWidget *image;
84 CtkWidget *label;
85 guint ignore_changes : 1;
86 guint file_is_hidden : 1;
87 guint fake_root : 1;
88
89 BaulDragSlotProxyInfo drag_info;
90};
91
92G_DEFINE_TYPE (BaulPathBar,static void baul_path_bar_init (BaulPathBar *self); static void
baul_path_bar_class_init (BaulPathBarClass *klass); static GType
baul_path_bar_get_type_once (void); static gpointer baul_path_bar_parent_class
= ((void*)0); static gint BaulPathBar_private_offset; static
void baul_path_bar_class_intern_init (gpointer klass) { baul_path_bar_parent_class
= g_type_class_peek_parent (klass); if (BaulPathBar_private_offset
!= 0) g_type_class_adjust_private_offset (klass, &BaulPathBar_private_offset
); baul_path_bar_class_init ((BaulPathBarClass*) klass); } __attribute__
((__unused__)) static inline gpointer baul_path_bar_get_instance_private
(BaulPathBar *self) { return (((gpointer) ((guint8*) (self) +
(glong) (BaulPathBar_private_offset)))); } GType baul_path_bar_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
= baul_path_bar_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 baul_path_bar_get_type_once (void
) { GType g_define_type_id = g_type_register_static_simple ((
ctk_container_get_type ()), g_intern_static_string ("BaulPathBar"
), sizeof (BaulPathBarClass), (GClassInitFunc)(void (*)(void)
) baul_path_bar_class_intern_init, sizeof (BaulPathBar), (GInstanceInitFunc
)(void (*)(void)) baul_path_bar_init, (GTypeFlags) 0); { {{};
} } return g_define_type_id; }
93 baul_path_bar,static void baul_path_bar_init (BaulPathBar *self); static void
baul_path_bar_class_init (BaulPathBarClass *klass); static GType
baul_path_bar_get_type_once (void); static gpointer baul_path_bar_parent_class
= ((void*)0); static gint BaulPathBar_private_offset; static
void baul_path_bar_class_intern_init (gpointer klass) { baul_path_bar_parent_class
= g_type_class_peek_parent (klass); if (BaulPathBar_private_offset
!= 0) g_type_class_adjust_private_offset (klass, &BaulPathBar_private_offset
); baul_path_bar_class_init ((BaulPathBarClass*) klass); } __attribute__
((__unused__)) static inline gpointer baul_path_bar_get_instance_private
(BaulPathBar *self) { return (((gpointer) ((guint8*) (self) +
(glong) (BaulPathBar_private_offset)))); } GType baul_path_bar_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
= baul_path_bar_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 baul_path_bar_get_type_once (void
) { GType g_define_type_id = g_type_register_static_simple ((
ctk_container_get_type ()), g_intern_static_string ("BaulPathBar"
), sizeof (BaulPathBarClass), (GClassInitFunc)(void (*)(void)
) baul_path_bar_class_intern_init, sizeof (BaulPathBar), (GInstanceInitFunc
)(void (*)(void)) baul_path_bar_init, (GTypeFlags) 0); { {{};
} } return g_define_type_id; }
94 CTK_TYPE_CONTAINER)static void baul_path_bar_init (BaulPathBar *self); static void
baul_path_bar_class_init (BaulPathBarClass *klass); static GType
baul_path_bar_get_type_once (void); static gpointer baul_path_bar_parent_class
= ((void*)0); static gint BaulPathBar_private_offset; static
void baul_path_bar_class_intern_init (gpointer klass) { baul_path_bar_parent_class
= g_type_class_peek_parent (klass); if (BaulPathBar_private_offset
!= 0) g_type_class_adjust_private_offset (klass, &BaulPathBar_private_offset
); baul_path_bar_class_init ((BaulPathBarClass*) klass); } __attribute__
((__unused__)) static inline gpointer baul_path_bar_get_instance_private
(BaulPathBar *self) { return (((gpointer) ((guint8*) (self) +
(glong) (BaulPathBar_private_offset)))); } GType baul_path_bar_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
= baul_path_bar_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 baul_path_bar_get_type_once (void
) { GType g_define_type_id = g_type_register_static_simple ((
ctk_container_get_type ()), g_intern_static_string ("BaulPathBar"
), sizeof (BaulPathBarClass), (GClassInitFunc)(void (*)(void)
) baul_path_bar_class_intern_init, sizeof (BaulPathBar), (GInstanceInitFunc
)(void (*)(void)) baul_path_bar_init, (GTypeFlags) 0); { {{};
} } return g_define_type_id; }
;
95
96static void baul_path_bar_finalize (GObject *object);
97static void baul_path_bar_dispose (GObject *object);
98
99static void baul_path_bar_get_preferred_width (CtkWidget *widget,
100 gint *minimum,
101 gint *natural);
102static void baul_path_bar_get_preferred_height (CtkWidget *widget,
103 gint *minimum,
104 gint *natural);
105
106static void baul_path_bar_unmap (CtkWidget *widget);
107static void baul_path_bar_size_allocate (CtkWidget *widget,
108 CtkAllocation *allocation);
109static void baul_path_bar_add (CtkContainer *container,
110 CtkWidget *widget);
111static void baul_path_bar_remove (CtkContainer *container,
112 CtkWidget *widget);
113static void baul_path_bar_forall (CtkContainer *container,
114 gboolean include_internals,
115 CtkCallback callback,
116 gpointer callback_data);
117static void baul_path_bar_scroll_up (BaulPathBar *path_bar);
118static void baul_path_bar_scroll_down (BaulPathBar *path_bar);
119static gboolean baul_path_bar_scroll (CtkWidget *path_bar,
120 CdkEventScroll *scroll);
121static void baul_path_bar_stop_scrolling (BaulPathBar *path_bar);
122static gboolean baul_path_bar_slider_button_press (CtkWidget *widget,
123 CdkEventButton *event,
124 BaulPathBar *path_bar);
125static gboolean baul_path_bar_slider_button_release (CtkWidget *widget,
126 CdkEventButton *event,
127 BaulPathBar *path_bar);
128static void baul_path_bar_grab_notify (CtkWidget *widget,
129 gboolean was_grabbed);
130static void baul_path_bar_state_changed (CtkWidget *widget,
131 CtkStateType previous_state);
132
133static void baul_path_bar_style_updated (CtkWidget *widget);
134
135static void baul_path_bar_screen_changed (CtkWidget *widget,
136 CdkScreen *previous_screen);
137static void baul_path_bar_check_icon_theme (BaulPathBar *path_bar);
138static void baul_path_bar_update_button_appearance (ButtonData *button_data);
139static void baul_path_bar_update_button_state (ButtonData *button_data,
140 gboolean current_dir);
141static gboolean baul_path_bar_update_path (BaulPathBar *path_bar,
142 GFile *file_path,
143 gboolean emit_signal);
144
145
146static CtkWidget *
147get_slider_button (BaulPathBar *path_bar,
148 const gchar *arrow_type)
149{
150 CtkWidget *button;
151
152 button = ctk_button_new ();
153 ctk_widget_set_focus_on_click (button, FALSE(0));
154 ctk_widget_add_events (button, CDK_SCROLL_MASK);
155 ctk_container_add (CTK_CONTAINER (button)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((button)), ((ctk_container_get_type ()))))))
,
156 ctk_image_new_from_icon_name (arrow_type, CTK_ICON_SIZE_MENU));
157 ctk_container_add (CTK_CONTAINER (path_bar)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((path_bar)), ((ctk_container_get_type ()))))))
, button);
158 ctk_widget_show_all (button);
159
160 return button;
161}
162
163static void
164update_button_types (BaulPathBar *path_bar)
165{
166 GList *list;
167 GFile *path = NULL((void*)0);
168
169 for (list = path_bar->button_list; list; list = list->next)
170 {
171 ButtonData *button_data;
172 button_data = BUTTON_DATA (list->data)((ButtonData *)(list->data));
173 if (ctk_toggle_button_get_active (CTK_TOGGLE_BUTTON (button_data->button)((((CtkToggleButton*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((button_data->button)), ((ctk_toggle_button_get_type (
)))))))
))
174 {
175 /*Increase the reference count on path so it does not get cleared
176 *by baul_path_bar_clear_buttons during baul_path_bar_update_path
177 */
178 path = g_object_ref (button_data->path)((__typeof__ (button_data->path)) (g_object_ref) (button_data
->path))
;
179 break;
180 }
181 }
182 if (path != NULL((void*)0))
183 {
184 baul_path_bar_update_path (path_bar, path, TRUE(!(0)));
185 g_object_unref (path);
186 }
187}
188
189
190static void
191desktop_location_changed_callback (gpointer user_data)
192{
193 BaulPathBar *path_bar;
194
195 path_bar = BAUL_PATH_BAR (user_data)((((BaulPathBar*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((user_data)), ((baul_path_bar_get_type ()))))))
;
196
197 g_object_unref (path_bar->desktop_path);
198 g_object_unref (path_bar->home_path);
199 path_bar->desktop_path = baul_get_desktop_location ();
200 path_bar->home_path = g_file_new_for_path (g_get_home_dir ());
201 desktop_is_home = g_file_equal (path_bar->home_path, path_bar->desktop_path);
202
203 update_button_types (path_bar);
204}
205
206static void
207trash_state_changed_cb (BaulTrashMonitor *monitor,
208 gboolean state,
209 BaulPathBar *path_bar)
210{
211 GFile *file;
212 GList *list;
213 gint scale;
214
215 file = g_file_new_for_uri ("trash:///");
216 scale = ctk_widget_get_scale_factor (CTK_WIDGET (path_bar)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((path_bar)), ((ctk_widget_get_type ()))))))
);
217 for (list = path_bar->button_list; list; list = list->next)
218 {
219 ButtonData *button_data;
220 button_data = BUTTON_DATA (list->data)((ButtonData *)(list->data));
221 if (g_file_equal (file, button_data->path))
222 {
223 GIcon *icon;
224 BaulIconInfo *icon_info;
225 cairo_surface_t *surface;
226
227 icon = baul_trash_monitor_get_icon ();
228 icon_info = baul_icon_info_lookup (icon, BAUL_PATH_BAR_ICON_SIZE16, scale);
229 surface = baul_icon_info_get_surface_at_size (icon_info, BAUL_PATH_BAR_ICON_SIZE16);
230 ctk_image_set_from_surface (CTK_IMAGE (button_data->image)((((CtkImage*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((button_data->image)), ((ctk_image_get_type ()))))))
, surface);
231 }
232 }
233 g_object_unref (file);
234}
235
236static gboolean
237slider_timeout (gpointer user_data)
238{
239 BaulPathBar *path_bar;
240
241 path_bar = BAUL_PATH_BAR (user_data)((((BaulPathBar*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((user_data)), ((baul_path_bar_get_type ()))))))
;
242
243 path_bar->drag_slider_timeout = 0;
244
245 if (ctk_widget_get_visible (CTK_WIDGET (path_bar)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((path_bar)), ((ctk_widget_get_type ()))))))
))
246 {
247 if (path_bar->drag_slider_timeout_for_up_button)
248 {
249 baul_path_bar_scroll_up (path_bar);
250 }
251 else
252 {
253 baul_path_bar_scroll_down (path_bar);
254 }
255 }
256
257 return FALSE(0);
258}
259
260static void
261baul_path_bar_slider_drag_motion (CtkWidget *widget,
262 CdkDragContext *context,
263 int x,
264 int y,
265 unsigned int time,
266 gpointer user_data)
267{
268 BaulPathBar *path_bar;
269 unsigned int timeout;
270
271 path_bar = BAUL_PATH_BAR (user_data)((((BaulPathBar*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((user_data)), ((baul_path_bar_get_type ()))))))
;
272
273 if (path_bar->drag_slider_timeout == 0)
274 {
275 CtkSettings *settings;
276
277 settings = ctk_widget_get_settings (widget);
278
279 g_object_get (settings, "ctk-timeout-expand", &timeout, NULL((void*)0));
280 path_bar->drag_slider_timeout =
281 g_timeout_add (timeout,
282 slider_timeout,
283 path_bar);
284
285 path_bar->drag_slider_timeout_for_up_button =
286 widget == path_bar->up_slider_button;
287 }
288}
289
290static void
291baul_path_bar_slider_drag_leave (CtkWidget *widget,
292 CdkDragContext *context,
293 unsigned int time,
294 gpointer user_data)
295{
296 BaulPathBar *path_bar;
297
298 path_bar = BAUL_PATH_BAR (user_data)((((BaulPathBar*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((user_data)), ((baul_path_bar_get_type ()))))))
;
299
300 if (path_bar->drag_slider_timeout != 0)
301 {
302 g_source_remove (path_bar->drag_slider_timeout);
303 path_bar->drag_slider_timeout = 0;
304 }
305}
306
307static void
308baul_path_bar_init (BaulPathBar *path_bar)
309{
310 char *p;
311 CtkStyleContext *context;
312
313 context = ctk_widget_get_style_context (CTK_WIDGET (path_bar)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((path_bar)), ((ctk_widget_get_type ()))))))
);
314 ctk_style_context_add_class (context, "baul-pathbar");
315
316 ctk_widget_set_has_window (CTK_WIDGET (path_bar)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((path_bar)), ((ctk_widget_get_type ()))))))
, FALSE(0));
317 ctk_widget_set_redraw_on_allocate (CTK_WIDGET (path_bar)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((path_bar)), ((ctk_widget_get_type ()))))))
, FALSE(0));
318
319 path_bar->spacing = 3;
320 path_bar->up_slider_button = get_slider_button (path_bar, "pan-start-symbolic");
321 path_bar->down_slider_button = get_slider_button (path_bar, "pan-end-symbolic");
322 ctk_style_context_add_class (ctk_widget_get_style_context (CTK_WIDGET (path_bar->up_slider_button)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((path_bar->up_slider_button)), ((ctk_widget_get_type (
)))))))
),
323 "slider-button");
324 ctk_style_context_add_class (ctk_widget_get_style_context (CTK_WIDGET (path_bar->down_slider_button)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((path_bar->down_slider_button)), ((ctk_widget_get_type
()))))))
),
325 "slider-button");
326
327 path_bar->icon_size = BAUL_PATH_BAR_ICON_SIZE16;
328
329 p = baul_get_desktop_directory ();
330 path_bar->desktop_path = g_file_new_for_path (p);
331 g_free (p);
332 path_bar->home_path = g_file_new_for_path (g_get_home_dir ());
333 path_bar->root_path = g_file_new_for_path ("/");
334 path_bar->current_path = NULL((void*)0);
335 path_bar->current_button_data = NULL((void*)0);
336
337 desktop_is_home = g_file_equal (path_bar->home_path, path_bar->desktop_path);
338
339 g_signal_connect_swapped (baul_preferences, "changed::" BAUL_PREFERENCES_DESKTOP_IS_HOME_DIR,g_signal_connect_data ((baul_preferences), ("changed::" "desktop-is-home-dir"
), (((GCallback) (desktop_location_changed_callback))), (path_bar
), ((void*)0), G_CONNECT_SWAPPED)
340 G_CALLBACK(desktop_location_changed_callback),g_signal_connect_data ((baul_preferences), ("changed::" "desktop-is-home-dir"
), (((GCallback) (desktop_location_changed_callback))), (path_bar
), ((void*)0), G_CONNECT_SWAPPED)
341 path_bar)g_signal_connect_data ((baul_preferences), ("changed::" "desktop-is-home-dir"
), (((GCallback) (desktop_location_changed_callback))), (path_bar
), ((void*)0), G_CONNECT_SWAPPED)
;
342
343 g_signal_connect_swapped (path_bar->up_slider_button, "clicked", G_CALLBACK (baul_path_bar_scroll_up), path_bar)g_signal_connect_data ((path_bar->up_slider_button), ("clicked"
), (((GCallback) (baul_path_bar_scroll_up))), (path_bar), ((void
*)0), G_CONNECT_SWAPPED)
;
344 g_signal_connect_swapped (path_bar->down_slider_button, "clicked", G_CALLBACK (baul_path_bar_scroll_down), path_bar)g_signal_connect_data ((path_bar->down_slider_button), ("clicked"
), (((GCallback) (baul_path_bar_scroll_down))), (path_bar), (
(void*)0), G_CONNECT_SWAPPED)
;
345
346 g_signal_connect (path_bar->up_slider_button, "button_press_event", G_CALLBACK (baul_path_bar_slider_button_press), path_bar)g_signal_connect_data ((path_bar->up_slider_button), ("button_press_event"
), (((GCallback) (baul_path_bar_slider_button_press))), (path_bar
), ((void*)0), (GConnectFlags) 0)
;
347 g_signal_connect (path_bar->up_slider_button, "button_release_event", G_CALLBACK (baul_path_bar_slider_button_release), path_bar)g_signal_connect_data ((path_bar->up_slider_button), ("button_release_event"
), (((GCallback) (baul_path_bar_slider_button_release))), (path_bar
), ((void*)0), (GConnectFlags) 0)
;
348 g_signal_connect (path_bar->down_slider_button, "button_press_event", G_CALLBACK (baul_path_bar_slider_button_press), path_bar)g_signal_connect_data ((path_bar->down_slider_button), ("button_press_event"
), (((GCallback) (baul_path_bar_slider_button_press))), (path_bar
), ((void*)0), (GConnectFlags) 0)
;
349 g_signal_connect (path_bar->down_slider_button, "button_release_event", G_CALLBACK (baul_path_bar_slider_button_release), path_bar)g_signal_connect_data ((path_bar->down_slider_button), ("button_release_event"
), (((GCallback) (baul_path_bar_slider_button_release))), (path_bar
), ((void*)0), (GConnectFlags) 0)
;
350
351 ctk_drag_dest_set (CTK_WIDGET (path_bar->up_slider_button)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((path_bar->up_slider_button)), ((ctk_widget_get_type (
)))))))
,
352 0, NULL((void*)0), 0, 0);
353 ctk_drag_dest_set_track_motion (CTK_WIDGET (path_bar->up_slider_button)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((path_bar->up_slider_button)), ((ctk_widget_get_type (
)))))))
, TRUE(!(0)));
354 g_signal_connect (path_bar->up_slider_button,g_signal_connect_data ((path_bar->up_slider_button), ("drag-motion"
), (((GCallback) (baul_path_bar_slider_drag_motion))), (path_bar
), ((void*)0), (GConnectFlags) 0)
355 "drag-motion",g_signal_connect_data ((path_bar->up_slider_button), ("drag-motion"
), (((GCallback) (baul_path_bar_slider_drag_motion))), (path_bar
), ((void*)0), (GConnectFlags) 0)
356 G_CALLBACK (baul_path_bar_slider_drag_motion),g_signal_connect_data ((path_bar->up_slider_button), ("drag-motion"
), (((GCallback) (baul_path_bar_slider_drag_motion))), (path_bar
), ((void*)0), (GConnectFlags) 0)
357 path_bar)g_signal_connect_data ((path_bar->up_slider_button), ("drag-motion"
), (((GCallback) (baul_path_bar_slider_drag_motion))), (path_bar
), ((void*)0), (GConnectFlags) 0)
;
358 g_signal_connect (path_bar->up_slider_button,g_signal_connect_data ((path_bar->up_slider_button), ("drag-leave"
), (((GCallback) (baul_path_bar_slider_drag_leave))), (path_bar
), ((void*)0), (GConnectFlags) 0)
359 "drag-leave",g_signal_connect_data ((path_bar->up_slider_button), ("drag-leave"
), (((GCallback) (baul_path_bar_slider_drag_leave))), (path_bar
), ((void*)0), (GConnectFlags) 0)
360 G_CALLBACK (baul_path_bar_slider_drag_leave),g_signal_connect_data ((path_bar->up_slider_button), ("drag-leave"
), (((GCallback) (baul_path_bar_slider_drag_leave))), (path_bar
), ((void*)0), (GConnectFlags) 0)
361 path_bar)g_signal_connect_data ((path_bar->up_slider_button), ("drag-leave"
), (((GCallback) (baul_path_bar_slider_drag_leave))), (path_bar
), ((void*)0), (GConnectFlags) 0)
;
362
363 ctk_drag_dest_set (CTK_WIDGET (path_bar->down_slider_button)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((path_bar->down_slider_button)), ((ctk_widget_get_type
()))))))
,
364 0, NULL((void*)0), 0, 0);
365 ctk_drag_dest_set_track_motion (CTK_WIDGET (path_bar->up_slider_button)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((path_bar->up_slider_button)), ((ctk_widget_get_type (
)))))))
, TRUE(!(0)));
366 g_signal_connect (path_bar->down_slider_button,g_signal_connect_data ((path_bar->down_slider_button), ("drag-motion"
), (((GCallback) (baul_path_bar_slider_drag_motion))), (path_bar
), ((void*)0), (GConnectFlags) 0)
367 "drag-motion",g_signal_connect_data ((path_bar->down_slider_button), ("drag-motion"
), (((GCallback) (baul_path_bar_slider_drag_motion))), (path_bar
), ((void*)0), (GConnectFlags) 0)
368 G_CALLBACK (baul_path_bar_slider_drag_motion),g_signal_connect_data ((path_bar->down_slider_button), ("drag-motion"
), (((GCallback) (baul_path_bar_slider_drag_motion))), (path_bar
), ((void*)0), (GConnectFlags) 0)
369 path_bar)g_signal_connect_data ((path_bar->down_slider_button), ("drag-motion"
), (((GCallback) (baul_path_bar_slider_drag_motion))), (path_bar
), ((void*)0), (GConnectFlags) 0)
;
370 g_signal_connect (path_bar->down_slider_button,g_signal_connect_data ((path_bar->down_slider_button), ("drag-leave"
), (((GCallback) (baul_path_bar_slider_drag_leave))), (path_bar
), ((void*)0), (GConnectFlags) 0)
371 "drag-leave",g_signal_connect_data ((path_bar->down_slider_button), ("drag-leave"
), (((GCallback) (baul_path_bar_slider_drag_leave))), (path_bar
), ((void*)0), (GConnectFlags) 0)
372 G_CALLBACK (baul_path_bar_slider_drag_leave),g_signal_connect_data ((path_bar->down_slider_button), ("drag-leave"
), (((GCallback) (baul_path_bar_slider_drag_leave))), (path_bar
), ((void*)0), (GConnectFlags) 0)
373 path_bar)g_signal_connect_data ((path_bar->down_slider_button), ("drag-leave"
), (((GCallback) (baul_path_bar_slider_drag_leave))), (path_bar
), ((void*)0), (GConnectFlags) 0)
;
374
375 g_signal_connect (baul_trash_monitor_get (),g_signal_connect_data ((baul_trash_monitor_get ()), ("trash_state_changed"
), (((GCallback) (trash_state_changed_cb))), (path_bar), ((void
*)0), (GConnectFlags) 0)
376 "trash_state_changed",g_signal_connect_data ((baul_trash_monitor_get ()), ("trash_state_changed"
), (((GCallback) (trash_state_changed_cb))), (path_bar), ((void
*)0), (GConnectFlags) 0)
377 G_CALLBACK (trash_state_changed_cb),g_signal_connect_data ((baul_trash_monitor_get ()), ("trash_state_changed"
), (((GCallback) (trash_state_changed_cb))), (path_bar), ((void
*)0), (GConnectFlags) 0)
378 path_bar)g_signal_connect_data ((baul_trash_monitor_get ()), ("trash_state_changed"
), (((GCallback) (trash_state_changed_cb))), (path_bar), ((void
*)0), (GConnectFlags) 0)
;
379}
380
381static void
382baul_path_bar_class_init (BaulPathBarClass *path_bar_class)
383{
384 GObjectClass *gobject_class;
385 CtkWidgetClass *widget_class;
386 CtkContainerClass *container_class;
387
388 gobject_class = (GObjectClass *) path_bar_class;
389 widget_class = (CtkWidgetClass *) path_bar_class;
390 container_class = (CtkContainerClass *) path_bar_class;
391
392 gobject_class->finalize = baul_path_bar_finalize;
393 gobject_class->dispose = baul_path_bar_dispose;
394
395 widget_class->get_preferred_height = baul_path_bar_get_preferred_height;
396 widget_class->get_preferred_width = baul_path_bar_get_preferred_width;
397
398 widget_class->unmap = baul_path_bar_unmap;
399 widget_class->size_allocate = baul_path_bar_size_allocate;
400 widget_class->style_updated = baul_path_bar_style_updated;
401
402 widget_class->screen_changed = baul_path_bar_screen_changed;
403 widget_class->grab_notify = baul_path_bar_grab_notify;
404 widget_class->state_changed = baul_path_bar_state_changed;
405 widget_class->scroll_event = baul_path_bar_scroll;
406
407 container_class->add = baul_path_bar_add;
408 container_class->forall = baul_path_bar_forall;
409 container_class->remove = baul_path_bar_remove;
410
411 path_bar_signals [PATH_CLICKED] =
412 g_signal_new ("path-clicked",
413 G_OBJECT_CLASS_TYPE (path_bar_class)((((GTypeClass*) (path_bar_class))->g_type)),
414 G_SIGNAL_RUN_FIRST,
415 G_STRUCT_OFFSET (BaulPathBarClass, path_clicked)((glong) __builtin_offsetof(BaulPathBarClass, path_clicked)),
416 NULL((void*)0), NULL((void*)0),
417 g_cclosure_marshal_VOID__OBJECT,
418 G_TYPE_NONE((GType) ((1) << (2))), 1,
419 G_TYPE_FILE(g_file_get_type ()));
420
421 path_bar_signals [PATH_EVENT] =
422 g_signal_new ("path-event",
423 G_OBJECT_CLASS_TYPE (path_bar_class)((((GTypeClass*) (path_bar_class))->g_type)),
424 G_SIGNAL_RUN_FIRST | G_SIGNAL_RUN_LAST,
425 G_STRUCT_OFFSET (BaulPathBarClass, path_event)((glong) __builtin_offsetof(BaulPathBarClass, path_event)),
426 NULL((void*)0), NULL((void*)0), NULL((void*)0),
427 G_TYPE_BOOLEAN((GType) ((5) << (2))), 2,
428 G_TYPE_FILE(g_file_get_type ()),
429 CDK_TYPE_EVENT(cdk_event_get_type ()));
430
431 ctk_container_class_handle_border_width (container_class);
432}
433
434
435static void
436baul_path_bar_finalize (GObject *object)
437{
438 BaulPathBar *path_bar;
439
440 path_bar = BAUL_PATH_BAR (object)((((BaulPathBar*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((object)), ((baul_path_bar_get_type ()))))))
;
441
442 baul_path_bar_stop_scrolling (path_bar);
443
444 if (path_bar->drag_slider_timeout != 0)
445 {
446 g_source_remove (path_bar->drag_slider_timeout);
447 path_bar->drag_slider_timeout = 0;
448 }
449
450 g_list_free (path_bar->button_list);
451 if (path_bar->root_path)
452 {
453 g_object_unref (path_bar->root_path);
454 path_bar->root_path = NULL((void*)0);
455 }
456 if (path_bar->home_path)
457 {
458 g_object_unref (path_bar->home_path);
459 path_bar->home_path = NULL((void*)0);
460 }
461 if (path_bar->desktop_path)
462 {
463 g_object_unref (path_bar->desktop_path);
464 path_bar->desktop_path = NULL((void*)0);
465 }
466
467 g_signal_handlers_disconnect_by_func (baul_trash_monitor_get (),g_signal_handlers_disconnect_matched ((baul_trash_monitor_get
()), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (trash_state_changed_cb), (path_bar))
468 trash_state_changed_cb, path_bar)g_signal_handlers_disconnect_matched ((baul_trash_monitor_get
()), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (trash_state_changed_cb), (path_bar))
;
469 g_signal_handlers_disconnect_by_func (baul_preferences,g_signal_handlers_disconnect_matched ((baul_preferences), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (desktop_location_changed_callback), (path_bar))
470 desktop_location_changed_callback,g_signal_handlers_disconnect_matched ((baul_preferences), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (desktop_location_changed_callback), (path_bar))
471 path_bar)g_signal_handlers_disconnect_matched ((baul_preferences), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (desktop_location_changed_callback), (path_bar))
;
472
473 G_OBJECT_CLASS (baul_path_bar_parent_class)((((GObjectClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((baul_path_bar_parent_class)), (((GType) ((20) << (
2))))))))
->finalize (object);
474}
475
476/* Removes the settings signal handler. It's safe to call multiple times */
477static void
478remove_settings_signal (BaulPathBar *path_bar,
479 CdkScreen *screen)
480{
481 if (path_bar->settings_signal_id)
482 {
483 CtkSettings *settings;
484
485 settings = ctk_settings_get_for_screen (screen);
486 g_signal_handler_disconnect (settings,
487 path_bar->settings_signal_id);
488 path_bar->settings_signal_id = 0;
489 }
490}
491
492static void
493baul_path_bar_dispose (GObject *object)
494{
495 remove_settings_signal (BAUL_PATH_BAR (object)((((BaulPathBar*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((object)), ((baul_path_bar_get_type ()))))))
, ctk_widget_get_screen (CTK_WIDGET (object)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((object)), ((ctk_widget_get_type ()))))))
));
496
497 G_OBJECT_CLASS (baul_path_bar_parent_class)((((GObjectClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((baul_path_bar_parent_class)), (((GType) ((20) << (
2))))))))
->dispose (object);
498}
499
500/* Size requisition:
501 *
502 * Ideally, our size is determined by another widget, and we are just filling
503 * available space.
504 */
505
506static void
507baul_path_bar_get_preferred_width (CtkWidget *widget,
508 gint *minimum,
509 gint *natural)
510{
511 BaulPathBar *path_bar;
512 GList *list;
513 gint child_height;
514 gint height;
515 gint child_min, child_nat;
516 gint slider_width;
517 ButtonData *button_data = NULL((void*)0);
518
519 path_bar = BAUL_PATH_BAR (widget)((((BaulPathBar*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((baul_path_bar_get_type ()))))))
;
520
521 *minimum = *natural = 0;
522 height = 0;
523
524 for (list = path_bar->button_list; list; list = list->next) {
525 button_data = BUTTON_DATA (list->data)((ButtonData *)(list->data));
526 ctk_widget_get_preferred_width (button_data->button, &child_min, &child_nat);
527 ctk_widget_get_preferred_height (button_data->button, &child_height, NULL((void*)0));
528 height = MAX (height, child_height)(((height) > (child_height)) ? (height) : (child_height));
529
530 if (button_data->type == NORMAL_BUTTON) {
531 /* Use 2*Height as button width because of ellipsized label. */
532 child_min = MAX (child_min, child_height * 2)(((child_min) > (child_height * 2)) ? (child_min) : (child_height
* 2))
;
533 child_nat = MAX (child_min, child_height * 2)(((child_min) > (child_height * 2)) ? (child_min) : (child_height
* 2))
;
534 }
535
536 *minimum = MAX (*minimum, child_min)(((*minimum) > (child_min)) ? (*minimum) : (child_min));
537 *natural = MAX (*natural, child_nat)(((*natural) > (child_nat)) ? (*natural) : (child_nat));
538 }
539
540 /* Add space for slider, if we have more than one path */
541 /* Theoretically, the slider could be bigger than the other button. But we're
542 * not going to worry about that now.
543 */
544 ctk_widget_get_preferred_width (path_bar->down_slider_button,
545 &slider_width,
546 NULL((void*)0));
547 ctk_widget_get_preferred_width (path_bar->up_slider_button,
548 &slider_width,
549 NULL((void*)0));
550
551
552 if (path_bar->button_list) {
553 *minimum += (path_bar->spacing + slider_width) * 2;
554 *natural += (path_bar->spacing + slider_width) * 2;
555 }
556 /*Let's keep the rest of this as it was */
557 path_bar->slider_width = slider_width;
558}
559
560static void
561baul_path_bar_get_preferred_height (CtkWidget *widget,
562 gint *minimum,
563 gint *natural)
564{
565 BaulPathBar *path_bar;
566 GList *list;
567 gint child_min, child_nat;
568 ButtonData *button_data = NULL((void*)0);
569
570 path_bar = BAUL_PATH_BAR (widget)((((BaulPathBar*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((baul_path_bar_get_type ()))))))
;
571
572 *minimum = *natural = 0;
573
574 for (list = path_bar->button_list; list; list = list->next) {
575 button_data = BUTTON_DATA (list->data)((ButtonData *)(list->data));
576 ctk_widget_get_preferred_height (button_data->button, &child_min, &child_nat);
577
578 *minimum = MAX (*minimum, child_min)(((*minimum) > (child_min)) ? (*minimum) : (child_min));
579 *natural = MAX (*natural, child_nat)(((*natural) > (child_nat)) ? (*natural) : (child_nat));
580 }
581}
582
583static void
584baul_path_bar_update_slider_buttons (BaulPathBar *path_bar)
585{
586 if (path_bar->button_list)
587 {
588
589 CtkWidget *button;
590
591 button = BUTTON_DATA (path_bar->button_list->data)((ButtonData *)(path_bar->button_list->data))->button;
592 if (ctk_widget_get_child_visible (button))
593 {
594 ctk_widget_set_sensitive (path_bar->down_slider_button, FALSE(0));
595 }
596 else
597 {
598 ctk_widget_set_sensitive (path_bar->down_slider_button, TRUE(!(0)));
599 }
600 button = BUTTON_DATA (g_list_last (path_bar->button_list)->data)((ButtonData *)(g_list_last (path_bar->button_list)->data
))
->button;
601 if (ctk_widget_get_child_visible (button))
602 {
603 ctk_widget_set_sensitive (path_bar->up_slider_button, FALSE(0));
604 }
605 else
606 {
607 ctk_widget_set_sensitive (path_bar->up_slider_button, TRUE(!(0)));
608 }
609 }
610}
611
612static void
613baul_path_bar_unmap (CtkWidget *widget)
614{
615 baul_path_bar_stop_scrolling (BAUL_PATH_BAR (widget)((((BaulPathBar*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((baul_path_bar_get_type ()))))))
);
616
617 CTK_WIDGET_CLASS (baul_path_bar_parent_class)((((CtkWidgetClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((baul_path_bar_parent_class)), ((ctk_widget_get_type ()))
))))
->unmap (widget);
618}
619
620/* This is a tad complicated */
621static void
622baul_path_bar_size_allocate (CtkWidget *widget,
623 CtkAllocation *allocation)
624{
625 CtkWidget *child;
626 BaulPathBar *path_bar;
627 CtkTextDirection direction;
628 CtkAllocation child_allocation;
629 GList *list, *first_button;
630 gint width;
631 gint allocation_width;
632 gboolean need_sliders;
633 gint up_slider_offset;
634 gint down_slider_offset;
635 CtkRequisition child_requisition;
636 CtkAllocation widget_allocation;
637
638 need_sliders = TRUE(!(0));
639 up_slider_offset = 0;
640 down_slider_offset = 0;
641 path_bar = BAUL_PATH_BAR (widget)((((BaulPathBar*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((baul_path_bar_get_type ()))))))
;
642
643 ctk_widget_set_allocation (widget, allocation);
644
645 /* No path is set so we don't have to allocate anything. */
646 if (path_bar->button_list == NULL((void*)0))
1
Assuming field 'button_list' is not equal to NULL
2
Taking false branch
647 {
648 return;
649 }
650 direction = ctk_widget_get_direction (widget);
651
652 allocation_width = allocation->width;
653
654 /* First, we check to see if we need the scrollbars. */
655 if (path_bar->fake_root)
3
Assuming field 'fake_root' is null
4
Taking false branch
656 {
657 width = path_bar->spacing + path_bar->slider_width;
658 }
659 else
660 {
661 width = 0;
662 }
663
664 ctk_widget_get_preferred_size (BUTTON_DATA (path_bar->button_list->data)((ButtonData *)(path_bar->button_list->data))->button,
665 &child_requisition, NULL((void*)0));
666 width += child_requisition.width;
667
668 for (list = path_bar->button_list->next; list; list = list->next)
5
Loop condition is false. Execution continues on line 680
669 {
670 child = BUTTON_DATA (list->data)((ButtonData *)(list->data))->button;
671 ctk_widget_get_preferred_size (child, &child_requisition, NULL((void*)0));
672 width += child_requisition.width + path_bar->spacing;
673
674 if (list == path_bar->fake_root)
675 {
676 break;
677 }
678 }
679
680 if (width <= allocation_width)
6
Assuming 'width' is <= 'allocation_width'
7
Taking true branch
681 {
682 if (path_bar->fake_root
7.1
Field 'fake_root' is null
)
8
Taking false branch
683 {
684 first_button = path_bar->fake_root;
685 }
686 else
687 {
688 first_button = g_list_last (path_bar->button_list);
9
Value assigned to 'first_button'
689 }
690 }
691 else
692 {
693 gboolean reached_end;
694 gint slider_space;
695 reached_end = FALSE(0);
696 slider_space = 2 * (path_bar->spacing + path_bar->slider_width);
697
698 if (path_bar->first_scrolled_button)
699 {
700 first_button = path_bar->first_scrolled_button;
701 }
702 else
703 {
704 first_button = path_bar->button_list;
705 }
706
707 need_sliders = TRUE(!(0));
708 /* To see how much space we have, and how many buttons we can display.
709 * We start at the first button, count forward until hit the new
710 * button, then count backwards.
711 */
712 /* Count down the path chain towards the end. */
713 ctk_widget_get_preferred_size (BUTTON_DATA (first_button->data)((ButtonData *)(first_button->data))->button,
714 &child_requisition, NULL((void*)0));
715 width = child_requisition.width;
716 list = first_button->prev;
717 while (list && !reached_end)
718 {
719 child = BUTTON_DATA (list->data)((ButtonData *)(list->data))->button;
720 ctk_widget_get_preferred_size (child, &child_requisition, NULL((void*)0));
721
722 if (width + child_requisition.width + path_bar->spacing + slider_space > allocation_width)
723 {
724 reached_end = TRUE(!(0));
725 }
726 else
727 {
728 if (list == path_bar->fake_root)
729 {
730 break;
731 }
732 else
733 {
734 width += child_requisition.width + path_bar->spacing;
735 }
736 }
737
738 list = list->prev;
739 }
740
741 /* Finally, we walk up, seeing how many of the previous buttons we can add*/
742
743 while (first_button->next && ! reached_end)
744 {
745 child = BUTTON_DATA (first_button->next->data)((ButtonData *)(first_button->next->data))->button;
746 ctk_widget_get_preferred_size (child, &child_requisition, NULL((void*)0));
747
748 if (width + child_requisition.width + path_bar->spacing + slider_space > allocation_width)
749 {
750 reached_end = TRUE(!(0));
751 }
752 else
753 {
754 width += child_requisition.width + path_bar->spacing;
755 if (first_button == path_bar->fake_root)
756 {
757 break;
758 }
759 first_button = first_button->next;
760 }
761 }
762 }
763
764 /* Now, we allocate space to the buttons */
765 child_allocation.y = allocation->y;
766 child_allocation.height = allocation->height;
767
768 if (direction == CTK_TEXT_DIR_RTL)
10
Assuming 'direction' is not equal to CTK_TEXT_DIR_RTL
11
Taking false branch
769 {
770 child_allocation.x = allocation->x + allocation->width;
771
772 if (need_sliders || path_bar->fake_root)
773 {
774 child_allocation.x -= (path_bar->spacing + path_bar->slider_width);
775 up_slider_offset = allocation->width - path_bar->slider_width;
776
777 }
778 }
779 else
780 {
781 child_allocation.x = allocation->x;
782
783 if (need_sliders
11.1
'need_sliders' is 1
|| path_bar->fake_root)
784 {
785 up_slider_offset = 0;
786 child_allocation.x += (path_bar->spacing + path_bar->slider_width);
787 }
788 }
789
790 for (list = first_button; list; list = list->prev)
12
Assuming pointer value is null
13
Loop condition is false. Execution continues on line 839
791 {
792 child = BUTTON_DATA (list->data)((ButtonData *)(list->data))->button;
793 ctk_widget_get_preferred_size (child, &child_requisition, NULL((void*)0));
794
795 ctk_widget_get_allocation (widget, &widget_allocation);
796
797 child_allocation.width = child_requisition.width;
798 if (direction == CTK_TEXT_DIR_RTL)
799 {
800 child_allocation.x -= child_allocation.width;
801 }
802 /* Check to see if we've don't have any more space to allocate buttons */
803 if (need_sliders && direction == CTK_TEXT_DIR_RTL)
804 {
805 if (child_allocation.x - path_bar->spacing - path_bar->slider_width < widget_allocation.x)
806 {
807 break;
808 }
809 }
810 else
811 {
812 if (need_sliders && direction == CTK_TEXT_DIR_LTR)
813 {
814 if (child_allocation.x + child_allocation.width + path_bar->spacing + path_bar->slider_width > widget_allocation.x + allocation_width)
815
816 {
817 break;
818 }
819 }
820 }
821
822 ctk_widget_set_child_visible (BUTTON_DATA (list->data)((ButtonData *)(list->data))->button, TRUE(!(0)));
823 ctk_widget_size_allocate (child, &child_allocation);
824
825 if (direction == CTK_TEXT_DIR_RTL)
826 {
827 child_allocation.x -= path_bar->spacing;
828 down_slider_offset = child_allocation.x - allocation->x - path_bar->slider_width;
829 }
830 else
831 {
832 down_slider_offset = child_allocation.x - widget_allocation.x;
833 down_slider_offset += child_allocation.width + path_bar->spacing;
834
835 child_allocation.x += child_allocation.width + path_bar->spacing;
836 }
837 }
838 /* Now we go hide all the widgets that don't fit */
839 while (list)
14
Loop condition is false. Execution continues on line 844
840 {
841 ctk_widget_set_child_visible (BUTTON_DATA (list->data)((ButtonData *)(list->data))->button, FALSE(0));
842 list = list->prev;
843 }
844 for (list = first_button->next; list; list = list->next)
15
Access to field 'next' results in a dereference of a null pointer (loaded from variable 'first_button')
845 {
846 ctk_widget_set_child_visible (BUTTON_DATA (list->data)((ButtonData *)(list->data))->button, FALSE(0));
847 }
848
849 if (need_sliders || path_bar->fake_root)
850 {
851 child_allocation.width = path_bar->slider_width;
852 child_allocation.x = up_slider_offset + allocation->x;
853 ctk_widget_size_allocate (path_bar->up_slider_button, &child_allocation);
854
855 ctk_widget_set_child_visible (path_bar->up_slider_button, TRUE(!(0)));
856 ctk_widget_show_all (path_bar->up_slider_button);
857 }
858 else
859 {
860 ctk_widget_set_child_visible (path_bar->up_slider_button, FALSE(0));
861 }
862
863 if (need_sliders)
864 {
865 child_allocation.width = path_bar->slider_width;
866 child_allocation.x = down_slider_offset + allocation->x;
867 ctk_widget_size_allocate (path_bar->down_slider_button, &child_allocation);
868
869 ctk_widget_set_child_visible (path_bar->down_slider_button, TRUE(!(0)));
870 ctk_widget_show_all (path_bar->down_slider_button);
871 baul_path_bar_update_slider_buttons (path_bar);
872 }
873 else
874 {
875 ctk_widget_set_child_visible (path_bar->down_slider_button, FALSE(0));
876 }
877}
878
879static void
880baul_path_bar_style_updated (CtkWidget *widget)
881{
882 if (CTK_WIDGET_CLASS (baul_path_bar_parent_class)((((CtkWidgetClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((baul_path_bar_parent_class)), ((ctk_widget_get_type ()))
))))
->style_updated)
883 {
884 CTK_WIDGET_CLASS (baul_path_bar_parent_class)((((CtkWidgetClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((baul_path_bar_parent_class)), ((ctk_widget_get_type ()))
))))
->style_updated (widget);
885 }
886
887 baul_path_bar_check_icon_theme (BAUL_PATH_BAR (widget)((((BaulPathBar*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((baul_path_bar_get_type ()))))))
);
888}
889
890static void
891baul_path_bar_screen_changed (CtkWidget *widget,
892 CdkScreen *previous_screen)
893{
894 if (CTK_WIDGET_CLASS (baul_path_bar_parent_class)((((CtkWidgetClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((baul_path_bar_parent_class)), ((ctk_widget_get_type ()))
))))
->screen_changed)
895 {
896 CTK_WIDGET_CLASS (baul_path_bar_parent_class)((((CtkWidgetClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((baul_path_bar_parent_class)), ((ctk_widget_get_type ()))
))))
->screen_changed (widget, previous_screen);
897 }
898 /* We might nave a new settings, so we remove the old one */
899 if (previous_screen)
900 {
901 remove_settings_signal (BAUL_PATH_BAR (widget)((((BaulPathBar*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((baul_path_bar_get_type ()))))))
, previous_screen);
902 }
903 baul_path_bar_check_icon_theme (BAUL_PATH_BAR (widget)((((BaulPathBar*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((baul_path_bar_get_type ()))))))
);
904}
905
906static gboolean
907baul_path_bar_scroll (CtkWidget *widget,
908 CdkEventScroll *event)
909{
910 BaulPathBar *path_bar;
911
912 path_bar = BAUL_PATH_BAR (widget)((((BaulPathBar*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((baul_path_bar_get_type ()))))))
;
913
914 switch (event->direction)
915 {
916 case CDK_SCROLL_RIGHT:
917 case CDK_SCROLL_DOWN:
918 baul_path_bar_scroll_down (path_bar);
919 return TRUE(!(0));
920
921 case CDK_SCROLL_LEFT:
922 case CDK_SCROLL_UP:
923 baul_path_bar_scroll_up (path_bar);
924 return TRUE(!(0));
925
926 case CDK_SCROLL_SMOOTH:
927 break;
928 }
929
930 return FALSE(0);
931}
932
933
934static void
935baul_path_bar_add (CtkContainer *container,
936 CtkWidget *widget)
937{
938 ctk_widget_set_parent (widget, CTK_WIDGET (container)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((container)), ((ctk_widget_get_type ()))))))
);
939}
940
941static void
942baul_path_bar_remove_1 (CtkContainer *container,
943 CtkWidget *widget)
944{
945 gboolean was_visible = ctk_widget_get_visible (widget);
946 ctk_widget_unparent (widget);
947 if (was_visible)
948 {
949 ctk_widget_queue_resize (CTK_WIDGET (container)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((container)), ((ctk_widget_get_type ()))))))
);
950 }
951}
952
953static void
954baul_path_bar_remove (CtkContainer *container,
955 CtkWidget *widget)
956{
957 BaulPathBar *path_bar;
958 GList *children;
959
960 path_bar = BAUL_PATH_BAR (container)((((BaulPathBar*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((container)), ((baul_path_bar_get_type ()))))))
;
961
962 if (widget == path_bar->up_slider_button)
963 {
964 baul_path_bar_remove_1 (container, widget);
965 path_bar->up_slider_button = NULL((void*)0);
966 return;
967 }
968
969 if (widget == path_bar->down_slider_button)
970 {
971 baul_path_bar_remove_1 (container, widget);
972 path_bar->down_slider_button = NULL((void*)0);
973 return;
974 }
975
976 children = path_bar->button_list;
977 while (children)
978 {
979 if (widget == BUTTON_DATA (children->data)((ButtonData *)(children->data))->button)
980 {
981 baul_path_bar_remove_1 (container, widget);
982 path_bar->button_list = g_list_remove_link (path_bar->button_list, children);
983 g_list_free_1 (children);
984 return;
985 }
986 children = children->next;
987 }
988}
989
990static void
991baul_path_bar_forall (CtkContainer *container,
992 gboolean include_internals,
993 CtkCallback callback,
994 gpointer callback_data)
995{
996 BaulPathBar *path_bar;
997 GList *children;
998
999 g_return_if_fail (callback != NULL)do { if ((callback != ((void*)0))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "callback != NULL"
); return; } } while (0)
;
1000 path_bar = BAUL_PATH_BAR (container)((((BaulPathBar*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((container)), ((baul_path_bar_get_type ()))))))
;
1001
1002 children = path_bar->button_list;
1003 while (children)
1004 {
1005 CtkWidget *child;
1006 child = BUTTON_DATA (children->data)((ButtonData *)(children->data))->button;
1007 children = children->next;
1008 (* callback) (child, callback_data);
1009 }
1010
1011 if (path_bar->up_slider_button)
1012 {
1013 (* callback) (path_bar->up_slider_button, callback_data);
1014 }
1015
1016 if (path_bar->down_slider_button)
1017 {
1018 (* callback) (path_bar->down_slider_button, callback_data);
1019 }
1020}
1021
1022static void
1023baul_path_bar_scroll_down (BaulPathBar *path_bar)
1024{
1025 GList *list;
1026 GList *down_button;
1027 GList *up_button;
1028 gint space_available;
1029 gint space_needed;
1030 CtkTextDirection direction;
1031 CtkAllocation allocation, button_allocation, slider_allocation;
1032
1033 down_button = NULL((void*)0);
1034 up_button = NULL((void*)0);
1035
1036 if (path_bar->ignore_click)
1037 {
1038 path_bar->ignore_click = FALSE(0);
1039 return;
1040 }
1041
1042 ctk_widget_queue_resize (CTK_WIDGET (path_bar)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((path_bar)), ((ctk_widget_get_type ()))))))
);
1043
1044 direction = ctk_widget_get_direction (CTK_WIDGET (path_bar)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((path_bar)), ((ctk_widget_get_type ()))))))
);
1045
1046 /* We find the button at the 'down' end that we have to make */
1047 /* visible */
1048 for (list = path_bar->button_list; list; list = list->next)
1049 {
1050 if (list->next && ctk_widget_get_child_visible (BUTTON_DATA (list->next->data)((ButtonData *)(list->next->data))->button))
1051 {
1052 down_button = list;
1053 break;
1054 }
1055 }
1056
1057 if (down_button == NULL((void*)0))
1058 {
1059 return;
1060 }
1061
1062 /* Find the last visible button on the 'up' end */
1063 for (list = g_list_last (path_bar->button_list); list; list = list->prev)
1064 {
1065 if (ctk_widget_get_child_visible (BUTTON_DATA (list->data)((ButtonData *)(list->data))->button))
1066 {
1067 up_button = list;
1068 break;
1069 }
1070 }
1071
1072 ctk_widget_get_allocation (BUTTON_DATA (down_button->data)((ButtonData *)(down_button->data))->button, &button_allocation);
1073 ctk_widget_get_allocation (CTK_WIDGET (path_bar)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((path_bar)), ((ctk_widget_get_type ()))))))
, &allocation);
1074 ctk_widget_get_allocation (path_bar->down_slider_button, &slider_allocation);
1075
1076 space_needed = button_allocation.width + path_bar->spacing;
1077 if (direction == CTK_TEXT_DIR_RTL)
1078 {
1079 space_available = slider_allocation.x - allocation.x;
1080 }
1081 else
1082 {
1083 space_available = (allocation.x + allocation.width) -
1084 (slider_allocation.x + slider_allocation.width);
1085 }
1086
1087 /* We have space_available extra space that's not being used. We
1088 * need space_needed space to make the button fit. So we walk down
1089 * from the end, removing buttons until we get all the space we
1090 * need. */
1091 ctk_widget_get_allocation (BUTTON_DATA (up_button->data)((ButtonData *)(up_button->data))->button, &button_allocation);
1092 while (space_available < space_needed && up_button)
1093 {
1094 space_available += button_allocation.width + path_bar->spacing;
1095 up_button = up_button->prev;
1096 path_bar->first_scrolled_button = up_button;
1097 }
1098}
1099
1100static void
1101baul_path_bar_scroll_up (BaulPathBar *path_bar)
1102{
1103 GList *list;
1104
1105 if (path_bar->ignore_click)
1106 {
1107 path_bar->ignore_click = FALSE(0);
1108 return;
1109 }
1110
1111 ctk_widget_queue_resize (CTK_WIDGET (path_bar)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((path_bar)), ((ctk_widget_get_type ()))))))
);
1112
1113 for (list = g_list_last (path_bar->button_list); list; list = list->prev)
1114 {
1115 if (list->prev && ctk_widget_get_child_visible (BUTTON_DATA (list->prev->data)((ButtonData *)(list->prev->data))->button))
1116 {
1117 if (list->prev == path_bar->fake_root)
1118 {
1119 path_bar->fake_root = NULL((void*)0);
1120 }
1121 path_bar->first_scrolled_button = list;
1122 return;
1123 }
1124 }
1125}
1126
1127static gboolean
1128baul_path_bar_scroll_timeout (BaulPathBar *path_bar)
1129{
1130 gboolean retval = FALSE(0);
1131
1132 if (path_bar->timer)
1133 {
1134 if (ctk_widget_has_focus (path_bar->up_slider_button))
1135 {
1136 baul_path_bar_scroll_up (path_bar);
1137 }
1138 else
1139 {
1140 if (ctk_widget_has_focus (path_bar->down_slider_button))
1141 {
1142 baul_path_bar_scroll_down (path_bar);
1143 }
1144 }
1145 if (path_bar->need_timer)
1146 {
1147 path_bar->need_timer = FALSE(0);
1148
1149 path_bar->timer = g_timeout_add (SCROLL_TIMEOUT150,
1150 (GSourceFunc)baul_path_bar_scroll_timeout,
1151 path_bar);
1152
1153 }
1154 else
1155 {
1156 retval = TRUE(!(0));
1157 }
1158 }
1159
1160 return retval;
1161}
1162
1163static void
1164baul_path_bar_stop_scrolling (BaulPathBar *path_bar)
1165{
1166 if (path_bar->timer)
1167 {
1168 g_source_remove (path_bar->timer);
1169 path_bar->timer = 0;
1170 path_bar->need_timer = FALSE(0);
1171 }
1172}
1173
1174static gboolean
1175baul_path_bar_slider_button_press (CtkWidget *widget,
1176 CdkEventButton *event,
1177 BaulPathBar *path_bar)
1178{
1179 if (!ctk_widget_has_focus (widget))
1180 {
1181 ctk_widget_grab_focus (widget);
1182 }
1183
1184 if (event->type != CDK_BUTTON_PRESS || event->button != 1)
1185 {
1186 return FALSE(0);
1187 }
1188
1189 path_bar->ignore_click = FALSE(0);
1190
1191 if (widget == path_bar->up_slider_button)
1192 {
1193 baul_path_bar_scroll_up (path_bar);
1194 }
1195 else
1196 {
1197 if (widget == path_bar->down_slider_button)
1198 {
1199 baul_path_bar_scroll_down (path_bar);
1200 }
1201 }
1202
1203 if (!path_bar->timer)
1204 {
1205 path_bar->need_timer = TRUE(!(0));
1206 path_bar->timer = g_timeout_add (INITIAL_SCROLL_TIMEOUT300,
1207 (GSourceFunc)baul_path_bar_scroll_timeout,
1208 path_bar);
1209 }
1210
1211 return FALSE(0);
1212}
1213
1214static gboolean
1215baul_path_bar_slider_button_release (CtkWidget *widget,
1216 CdkEventButton *event,
1217 BaulPathBar *path_bar)
1218{
1219 if (event->type != CDK_BUTTON_RELEASE)
1220 {
1221 return FALSE(0);
1222 }
1223
1224 path_bar->ignore_click = TRUE(!(0));
1225 baul_path_bar_stop_scrolling (path_bar);
1226
1227 return FALSE(0);
1228}
1229
1230static void
1231baul_path_bar_grab_notify (CtkWidget *widget,
1232 gboolean was_grabbed)
1233{
1234 if (!was_grabbed)
1235 {
1236 baul_path_bar_stop_scrolling (BAUL_PATH_BAR (widget)((((BaulPathBar*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((baul_path_bar_get_type ()))))))
);
1237 }
1238}
1239
1240static void
1241baul_path_bar_state_changed (CtkWidget *widget,
1242 CtkStateType previous_state)
1243{
1244 if (!ctk_widget_get_sensitive (widget))
1245 {
1246 baul_path_bar_stop_scrolling (BAUL_PATH_BAR (widget)((((BaulPathBar*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((baul_path_bar_get_type ()))))))
);
1247 }
1248}
1249
1250
1251
1252/* Changes the icons wherever it is needed */
1253static void
1254reload_icons (BaulPathBar *path_bar)
1255{
1256 GList *list;
1257
1258 for (list = path_bar->button_list; list; list = list->next)
1259 {
1260 ButtonData *button_data;
1261
1262 button_data = BUTTON_DATA (list->data)((ButtonData *)(list->data));
1263 if (button_data->type != NORMAL_BUTTON || button_data->is_base_dir)
1264 {
1265 baul_path_bar_update_button_appearance (button_data);
1266 }
1267
1268 }
1269}
1270
1271static void
1272change_icon_theme (BaulPathBar *path_bar)
1273{
1274 path_bar->icon_size = BAUL_PATH_BAR_ICON_SIZE16;
1275 reload_icons (path_bar);
1276}
1277
1278/* Callback used when a CtkSettings value changes */
1279static void
1280settings_notify_cb (GObject *object,
1281 GParamSpec *pspec,
1282 BaulPathBar *path_bar)
1283{
1284 const char *name;
1285
1286 name = g_param_spec_get_name (pspec);
1287
1288 if (! strcmp (name, "ctk-icon-theme-name") || ! strcmp (name, "ctk-icon-sizes"))
1289 {
1290 change_icon_theme (path_bar);
1291 }
1292}
1293
1294static void
1295baul_path_bar_check_icon_theme (BaulPathBar *path_bar)
1296{
1297 CtkSettings *settings;
1298
1299 if (path_bar->settings_signal_id)
1300 {
1301 return;
1302 }
1303
1304 settings = ctk_settings_get_for_screen (ctk_widget_get_screen (CTK_WIDGET (path_bar)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((path_bar)), ((ctk_widget_get_type ()))))))
));
1305 path_bar->settings_signal_id = g_signal_connect (settings, "notify", G_CALLBACK (settings_notify_cb), path_bar)g_signal_connect_data ((settings), ("notify"), (((GCallback) (
settings_notify_cb))), (path_bar), ((void*)0), (GConnectFlags
) 0)
;
1306
1307 change_icon_theme (path_bar);
1308}
1309
1310/* Public functions and their helpers */
1311void
1312baul_path_bar_clear_buttons (BaulPathBar *path_bar)
1313{
1314 while (path_bar->button_list != NULL((void*)0))
1315 {
1316 ctk_container_remove (CTK_CONTAINER (path_bar)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((path_bar)), ((ctk_container_get_type ()))))))
, BUTTON_DATA (path_bar->button_list->data)((ButtonData *)(path_bar->button_list->data))->button);
1317 }
1318 path_bar->first_scrolled_button = NULL((void*)0);
1319 path_bar->fake_root = NULL((void*)0);
1320}
1321
1322static void
1323button_clicked_cb (CtkWidget *button,
1324 gpointer data)
1325{
1326 ButtonData *button_data;
1327 BaulPathBar *path_bar;
1328 GList *button_list;
1329
1330 button_data = BUTTON_DATA (data)((ButtonData *)(data));
1331 if (button_data->ignore_changes)
1332 {
1333 return;
1334 }
1335
1336 path_bar = BAUL_PATH_BAR (ctk_widget_get_parent (button))((((BaulPathBar*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((ctk_widget_get_parent (button))), ((baul_path_bar_get_type
()))))))
;
1337
1338 button_list = g_list_find (path_bar->button_list, button_data);
1339 g_assert (button_list != NULL)do { if (button_list != ((void*)0)) ; else g_assertion_message_expr
(((gchar*) 0), "baul-pathbar.c", 1339, ((const char*) (__func__
)), "button_list != NULL"); } while (0)
;
1340
1341 ctk_toggle_button_set_active (CTK_TOGGLE_BUTTON (button)((((CtkToggleButton*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((button)), ((ctk_toggle_button_get_type ()))))))
, TRUE(!(0)));
1342
1343 g_signal_emit (path_bar, path_bar_signals [PATH_CLICKED], 0, button_data->path);
1344}
1345
1346static gboolean
1347button_event_cb (CtkWidget *button,
1348 CdkEventButton *event,
1349 gpointer data)
1350{
1351 ButtonData *button_data;
1352 BaulPathBar *path_bar;
1353 GList *button_list;
1354 gboolean retval;
1355
1356 button_data = BUTTON_DATA (data)((ButtonData *)(data));
1357 path_bar = BAUL_PATH_BAR (ctk_widget_get_parent (button))((((BaulPathBar*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((ctk_widget_get_parent (button))), ((baul_path_bar_get_type
()))))))
;
1358
1359 if (event->type == CDK_BUTTON_PRESS) {
1360 g_object_set_data (G_OBJECT (button)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((button)), (((GType) ((20) << (2))))))))
, "handle-button-release",
1361 GINT_TO_POINTER (TRUE)((gpointer) (glong) ((!(0)))));
1362 }
1363
1364 if (event->type == CDK_BUTTON_RELEASE &&
1365 !GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (button),((guint) (gulong) (g_object_get_data (((((GObject*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((button)), (((GType) ((20) << (2)))
))))), "handle-button-release")))
1366 "handle-button-release"))((guint) (gulong) (g_object_get_data (((((GObject*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((button)), (((GType) ((20) << (2)))
))))), "handle-button-release")))
) {
1367 return FALSE(0);
1368 }
1369
1370 button_list = g_list_find (path_bar->button_list, button_data);
1371 g_assert (button_list != NULL)do { if (button_list != ((void*)0)) ; else g_assertion_message_expr
(((gchar*) 0), "baul-pathbar.c", 1371, ((const char*) (__func__
)), "button_list != NULL"); } while (0)
;
1372
1373 g_signal_emit (path_bar, path_bar_signals [PATH_EVENT], 0, button_data->path, event, &retval);
1374
1375 return retval;
1376}
1377
1378static void
1379button_drag_begin_cb (CtkWidget *widget,
1380 CdkDragContext *drag_context,
1381 gpointer user_data)
1382{
1383 g_object_set_data (G_OBJECT (widget)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), (((GType) ((20) << (2))))))))
, "handle-button-release",
1384 GINT_TO_POINTER (FALSE)((gpointer) (glong) ((0))));
1385}
1386
1387
1388static BaulIconInfo *
1389get_type_icon_info (ButtonData *button_data)
1390{
1391 gint icon_scale = ctk_widget_get_scale_factor (CTK_WIDGET (button_data->button)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((button_data->button)), ((ctk_widget_get_type ()))))))
);
1392
1393 switch (button_data->type)
1394 {
1395 case ROOT_BUTTON:
1396 return baul_icon_info_lookup_from_name (BAUL_ICON_FILESYSTEM"drive-harddisk",
1397 BAUL_PATH_BAR_ICON_SIZE16,
1398 icon_scale);
1399
1400 case HOME_BUTTON:
1401 return baul_icon_info_lookup_from_name (BAUL_ICON_HOME"user-home",
1402 BAUL_PATH_BAR_ICON_SIZE16,
1403 icon_scale);
1404
1405 case DESKTOP_BUTTON:
1406 return baul_icon_info_lookup_from_name (BAUL_ICON_DESKTOP"user-desktop",
1407 BAUL_PATH_BAR_ICON_SIZE16,
1408 icon_scale);
1409
1410 case NORMAL_BUTTON:
1411 if (button_data->is_base_dir)
1412 {
1413 return baul_file_get_icon (button_data->file,
1414 BAUL_PATH_BAR_ICON_SIZE16, icon_scale,
1415 BAUL_FILE_ICON_FLAGS_NONE);
1416 }
1417
1418 default:
1419 return NULL((void*)0);
1420 }
1421
1422 return NULL((void*)0);
1423}
1424
1425static void
1426button_data_free (ButtonData *button_data)
1427{
1428 g_object_unref (button_data->path);
1429 g_free (button_data->dir_name);
1430 if (button_data->custom_icon)
1431 {
1432 cairo_surface_destroy (button_data->custom_icon);
1433 }
1434 if (button_data->file != NULL((void*)0))
1435 {
1436 g_signal_handler_disconnect (button_data->file,
1437 button_data->file_changed_signal_id);
1438 baul_file_monitor_remove (button_data->file, button_data);
1439 baul_file_unref (button_data->file);
1440 }
1441
1442 g_object_unref (button_data->drag_info.target_location);
1443 button_data->drag_info.target_location = NULL((void*)0);
1444
1445 g_free (button_data);
1446}
1447
1448static const char *
1449get_dir_name (ButtonData *button_data)
1450{
1451 if (button_data->type == DESKTOP_BUTTON)
1452 {
1453 return _("Desktop")gettext ("Desktop");
1454 }
1455 else
1456 {
1457 return button_data->dir_name;
1458 }
1459}
1460
1461/* We always want to request the same size for the label, whether
1462 * or not the contents are bold
1463 */
1464static void
1465set_label_padding_size (ButtonData *button_data)
1466{
1467 const gchar *dir_name = get_dir_name (button_data);
1468 PangoLayout *layout;
1469 gint width, height, bold_width, bold_height;
1470 gint pad_left, pad_right;
1471 gchar *markup;
1472
1473 layout = ctk_widget_create_pango_layout (button_data->label, dir_name);
1474 pango_layout_get_pixel_size (layout, &width, &height);
1475
1476 markup = g_markup_printf_escaped ("<b>%s</b>", dir_name);
1477 pango_layout_set_markup (layout, markup, -1);
1478 g_free (markup);
1479
1480 pango_layout_get_pixel_size (layout, &bold_width, &bold_height);
1481
1482 pad_left = (bold_width - width) / 2;
1483 pad_right = (bold_width + 1 - width) / 2; /* this ensures rounding up - the
1484 pixel size difference between bold and normal fonts is not always even and
1485 will give an off-by-one error when dividing by 2 */
1486
1487 ctk_widget_set_margin_start (CTK_WIDGET (button_data->label)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((button_data->label)), ((ctk_widget_get_type ()))))))
, pad_left);
1488 ctk_widget_set_margin_end (CTK_WIDGET (button_data->label)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((button_data->label)), ((ctk_widget_get_type ()))))))
, pad_right);
1489
1490 g_object_unref (layout);
1491}
1492
1493static void
1494baul_path_bar_update_button_appearance (ButtonData *button_data)
1495{
1496 const gchar *dir_name = get_dir_name (button_data);
1497
1498 if (button_data->label != NULL((void*)0))
1499 {
1500 if (ctk_label_get_use_markup (CTK_LABEL (button_data->label)((((CtkLabel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((button_data->label)), ((ctk_label_get_type ()))))))
))
1501 {
1502 char *markup;
1503
1504 markup = g_markup_printf_escaped ("<b>%s</b>", dir_name);
1505 ctk_label_set_markup (CTK_LABEL (button_data->label)((((CtkLabel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((button_data->label)), ((ctk_label_get_type ()))))))
, markup);
1506
1507 ctk_widget_set_margin_end (CTK_WIDGET (button_data->label)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((button_data->label)), ((ctk_widget_get_type ()))))))
, 0);
1508 ctk_widget_set_margin_start (CTK_WIDGET (button_data->label)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((button_data->label)), ((ctk_widget_get_type ()))))))
, 0);
1509 g_free(markup);
1510 }
1511 else
1512 {
1513 ctk_label_set_text (CTK_LABEL (button_data->label)((((CtkLabel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((button_data->label)), ((ctk_label_get_type ()))))))
, dir_name);
1514 set_label_padding_size (button_data);
1515 }
1516 }
1517
1518 if (button_data->image != NULL((void*)0))
1519 {
1520 if (button_data->custom_icon)
1521 {
1522 ctk_image_set_from_surface (CTK_IMAGE (button_data->image)((((CtkImage*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((button_data->image)), ((ctk_image_get_type ()))))))
, button_data->custom_icon);
1523 ctk_widget_show (CTK_WIDGET (button_data->image)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((button_data->image)), ((ctk_widget_get_type ()))))))
);
1524 }
1525 else
1526 {
1527 BaulIconInfo *icon_info;
1528 cairo_surface_t *surface;
1529
1530 icon_info = get_type_icon_info (button_data);
1531 surface = NULL((void*)0);
1532
1533 if (icon_info != NULL((void*)0))
1534 {
1535 surface = baul_icon_info_get_surface_at_size (icon_info, BAUL_PATH_BAR_ICON_SIZE16);
1536 g_object_unref (icon_info);
1537 }
1538
1539 if (surface != NULL((void*)0))
1540 {
1541 ctk_image_set_from_surface (CTK_IMAGE (button_data->image)((((CtkImage*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((button_data->image)), ((ctk_image_get_type ()))))))
, surface);
1542 ctk_style_context_add_class (ctk_widget_get_style_context (button_data->button),
1543 "image-button");
1544 ctk_widget_show (CTK_WIDGET (button_data->image)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((button_data->image)), ((ctk_widget_get_type ()))))))
);
1545 cairo_surface_destroy (surface);
1546 }
1547 else
1548 {
1549 ctk_widget_hide (CTK_WIDGET (button_data->image)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((button_data->image)), ((ctk_widget_get_type ()))))))
);
1550 ctk_style_context_remove_class (ctk_widget_get_style_context (button_data->button),
1551 "image-button");
1552 }
1553 }
1554 }
1555
1556}
1557
1558static void
1559baul_path_bar_update_button_state (ButtonData *button_data,
1560 gboolean current_dir)
1561{
1562 if (button_data->label != NULL((void*)0))
1563 {
1564 g_object_set (button_data->label, "use-markup", current_dir, NULL((void*)0));
1565 }
1566
1567 baul_path_bar_update_button_appearance (button_data);
1568
1569 if (ctk_toggle_button_get_active (CTK_TOGGLE_BUTTON (button_data->button)((((CtkToggleButton*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((button_data->button)), ((ctk_toggle_button_get_type (
)))))))
) != current_dir)
1570 {
1571 button_data->ignore_changes = TRUE(!(0));
1572 ctk_toggle_button_set_active (CTK_TOGGLE_BUTTON (button_data->button)((((CtkToggleButton*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((button_data->button)), ((ctk_toggle_button_get_type (
)))))))
, current_dir);
1573 button_data->ignore_changes = FALSE(0);
1574 }
1575}
1576
1577static gboolean
1578setup_file_path_mounted_mount (GFile *location, ButtonData *button_data)
1579{
1580 GVolumeMonitor *volume_monitor;
1581 GList *mounts, *l;
1582 gboolean result;
1583 GIcon *icon;
1584 BaulIconInfo *info;
1585 GFile *root, *default_location;
1586 gint scale;
1587 GMount *mount = NULL((void*)0);
1588
1589 /* Return false if button has not been set up yet or has been destroyed*/
1590 if (!button_data->button)
1591 return FALSE(0);
1592 result = FALSE(0);
1593 volume_monitor = g_volume_monitor_get ();
1594 mounts = g_volume_monitor_get_mounts (volume_monitor);
1595
1596 scale = ctk_widget_get_scale_factor (CTK_WIDGET (button_data->button)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((button_data->button)), ((ctk_widget_get_type ()))))))
);
1597 for (l = mounts; l != NULL((void*)0); l = l->next)
1598 {
1599 mount = l->data;
1600 if (g_mount_is_shadowed (mount))
1601 {
1602 continue;
1603 }
1604 if (result)
1605 {
1606 continue;
1607 }
1608 root = g_mount_get_root (mount);
1609 if (g_file_equal (location, root))
1610 {
1611 result = TRUE(!(0));
1612 /* set mount specific details in button_data */
1613 if (button_data)
1614 {
1615 icon = g_mount_get_icon (mount);
1616 if (icon == NULL((void*)0))
1617 {
1618 icon = g_themed_icon_new (BAUL_ICON_FOLDER"folder");
1619 }
1620 info = baul_icon_info_lookup (icon, BAUL_PATH_BAR_ICON_SIZE16, scale);
1621 g_object_unref (icon);
1622 button_data->custom_icon = baul_icon_info_get_surface_at_size (info, BAUL_PATH_BAR_ICON_SIZE16);
1623 g_object_unref (info);
1624 button_data->dir_name = g_mount_get_name (mount);
1625 button_data->type = MOUNT_BUTTON;
1626 button_data->fake_root = TRUE(!(0));
1627 }
1628 g_object_unref (root);
1629 break;
1630 }
1631 default_location = g_mount_get_default_location (mount);
1632 if (!g_file_equal (default_location, root) &&
1633 g_file_equal (location, default_location))
1634 {
1635 result = TRUE(!(0));
1636 /* set mount specific details in button_data */
1637 if (button_data)
1638 {
1639 icon = g_mount_get_icon (mount);
1640 if (icon == NULL((void*)0))
1641 {
1642 icon = g_themed_icon_new (BAUL_ICON_FOLDER"folder");
1643 }
1644 info = baul_icon_info_lookup (icon, BAUL_PATH_BAR_ICON_SIZE16, scale);
1645 g_object_unref (icon);
1646 button_data->custom_icon = baul_icon_info_get_surface_at_size (info, BAUL_PATH_BAR_ICON_SIZE16);
1647 g_object_unref (info);
1648 button_data->type = DEFAULT_LOCATION_BUTTON;
1649 button_data->fake_root = TRUE(!(0));
1650 }
1651 g_object_unref (default_location);
1652 g_object_unref (root);
1653 break;
1654 }
1655 g_object_unref (default_location);
1656 g_object_unref (root);
1657 }
1658 g_list_free_full (mounts, g_object_unref);
1659 return result;
1660}
1661
1662static void
1663setup_button_type (ButtonData *button_data,
1664 BaulPathBar *path_bar,
1665 GFile *location)
1666{
1667 if (path_bar->root_path != NULL((void*)0) && g_file_equal (location, path_bar->root_path))
1668 {
1669 button_data->type = ROOT_BUTTON;
1670 }
1671 else if (path_bar->home_path != NULL((void*)0) && g_file_equal (location, path_bar->home_path))
1672 {
1673 button_data->type = HOME_BUTTON;
1674 button_data->fake_root = TRUE(!(0));
1675 }
1676 else if (path_bar->desktop_path != NULL((void*)0) && g_file_equal (location, path_bar->desktop_path))
1677 {
1678 if (!desktop_is_home)
1679 {
1680 button_data->type = DESKTOP_BUTTON;
1681 }
1682 else
1683 {
1684 button_data->type = NORMAL_BUTTON;
1685 }
1686 }
1687 else if (setup_file_path_mounted_mount (location, button_data))
1688 {
1689 /* already setup */
1690 }
1691 else
1692 {
1693 button_data->type = NORMAL_BUTTON;
1694 }
1695}
1696
1697static void
1698button_drag_data_get_cb (CtkWidget *widget,
1699 CdkDragContext *context,
1700 CtkSelectionData *selection_data,
1701 guint info,
1702 guint time_,
1703 gpointer user_data)
1704{
1705 ButtonData *button_data;
1706 char *uri_list[2];
1707
1708 button_data = user_data;
1709
1710 uri_list[0] = g_file_get_uri (button_data->path);
1711 uri_list[1] = NULL((void*)0);
1712
1713 if (info == BAUL_ICON_DND_CAFE_ICON_LIST)
1714 {
1715 char *tmp;
1716
1717 tmp = g_strdup_printf ("%s\r\n", uri_list[0]);
1718 ctk_selection_data_set (selection_data, ctk_selection_data_get_target (selection_data),
1719 8, tmp, strlen (tmp));
1720 g_free (tmp);
1721 }
1722 else if (info == BAUL_ICON_DND_URI_LIST)
1723 {
1724 ctk_selection_data_set_uris (selection_data, uri_list);
1725 }
1726
1727 g_free (uri_list[0]);
1728}
1729
1730static void
1731setup_button_drag_source (ButtonData *button_data)
1732{
1733 CtkTargetList *target_list;
1734 const CtkTargetEntry targets[] =
1735 {
1736 { BAUL_ICON_DND_CAFE_ICON_LIST_TYPE"x-special/cafe-icon-list", 0, BAUL_ICON_DND_CAFE_ICON_LIST }
1737 };
1738
1739 ctk_drag_source_set (button_data->button,
1740 CDK_BUTTON1_MASK |
1741 CDK_BUTTON2_MASK,
1742 NULL((void*)0), 0,
1743 CDK_ACTION_MOVE |
1744 CDK_ACTION_COPY |
1745 CDK_ACTION_LINK |
1746 CDK_ACTION_ASK);
1747
1748 target_list = ctk_target_list_new (targets, G_N_ELEMENTS (targets)(sizeof (targets) / sizeof ((targets)[0])));
1749 ctk_target_list_add_uri_targets (target_list, BAUL_ICON_DND_URI_LIST);
1750 ctk_drag_source_set_target_list (button_data->button, target_list);
1751 ctk_target_list_unref (target_list);
1752
1753 g_signal_connect (button_data->button, "drag-data-get",g_signal_connect_data ((button_data->button), ("drag-data-get"
), (((GCallback) (button_drag_data_get_cb))), (button_data), (
(void*)0), (GConnectFlags) 0)
1754 G_CALLBACK (button_drag_data_get_cb),g_signal_connect_data ((button_data->button), ("drag-data-get"
), (((GCallback) (button_drag_data_get_cb))), (button_data), (
(void*)0), (GConnectFlags) 0)
1755 button_data)g_signal_connect_data ((button_data->button), ("drag-data-get"
), (((GCallback) (button_drag_data_get_cb))), (button_data), (
(void*)0), (GConnectFlags) 0)
;
1756}
1757
1758static void
1759button_data_file_changed (BaulFile *file,
1760 ButtonData *button_data)
1761{
1762 GFile *location, *current_location;
1763 ButtonData *current_button_data;
1764 BaulPathBar *path_bar;
1765 gboolean renamed, child;
1766
1767 path_bar = (BaulPathBar *) ctk_widget_get_ancestor (button_data->button,
1768 BAUL_TYPE_PATH_BAR(baul_path_bar_get_type ()));
1769 if (path_bar == NULL((void*)0))
1770 {
1771 return;
1772 }
1773
1774 g_return_if_fail (path_bar->current_path != NULL)do { if ((path_bar->current_path != ((void*)0))) { } else {
g_return_if_fail_warning (((gchar*) 0), ((const char*) (__func__
)), "path_bar->current_path != NULL"); return; } } while (
0)
;
1775 g_return_if_fail (path_bar->current_button_data != NULL)do { if ((path_bar->current_button_data != ((void*)0))) { }
else { g_return_if_fail_warning (((gchar*) 0), ((const char*
) (__func__)), "path_bar->current_button_data != NULL"); return
; } } while (0)
;
1776
1777 current_button_data = path_bar->current_button_data;
1778
1779 location = baul_file_get_location (file);
1780 if (!g_file_equal (button_data->path, location))
1781 {
1782 GFile *parent, *button_parent;
1783
1784 parent = g_file_get_parent (location);
1785 button_parent = g_file_get_parent (button_data->path);
1786
1787 renamed = (parent != NULL((void*)0) && button_parent != NULL((void*)0)) &&
1788 g_file_equal (parent, button_parent);
1789
1790 if (parent != NULL((void*)0))
1791 {
1792 g_object_unref (parent);
1793 }
1794 if (button_parent != NULL((void*)0))
1795 {
1796 g_object_unref (button_parent);
1797 }
1798
1799 if (renamed)
1800 {
1801 button_data->path = g_object_ref (location)((__typeof__ (location)) (g_object_ref) (location));
1802 }
1803 else
1804 {
1805 /* the file has been moved.
1806 * If it was below the currently displayed location, remove it.
1807 * If it was not below the currently displayed location, update the path bar
1808 */
1809 child = g_file_has_prefix (button_data->path,
1810 path_bar->current_path);
1811
1812 if (child)
1813 {
1814 /* moved file inside current path hierarchy */
1815 g_object_unref (location);
1816 location = g_file_get_parent (button_data->path);
1817 current_location = g_object_ref (path_bar->current_path)((__typeof__ (path_bar->current_path)) (g_object_ref) (path_bar
->current_path))
;
1818 }
1819 else
1820 {
1821 /* moved current path, or file outside current path hierarchy.
1822 * Update path bar to new locations.
1823 */
1824 current_location = baul_file_get_location (current_button_data->file);
1825 }
1826
1827 baul_path_bar_update_path (path_bar, location, FALSE(0));
1828 baul_path_bar_set_path (path_bar, current_location);
1829 g_object_unref (location);
1830 g_object_unref (current_location);
1831 return;
1832 }
1833 }
1834 else if (baul_file_is_gone (file))
1835 {
1836 gint idx, position;
1837
1838 /* if the current or a parent location are gone, don't do anything, as the view
1839 * will get the event too and call us back.
1840 */
1841 current_location = baul_file_get_location (current_button_data->file);
1842
1843 if (g_file_has_prefix (location, current_location))
1844 {
1845 /* remove this and the following buttons */
1846 position = g_list_position (path_bar->button_list,
1847 g_list_find (path_bar->button_list, button_data));
1848
1849 if (position != -1)
1850 {
1851 for (idx = 0; idx <= position; idx++)
1852 {
1853 ctk_container_remove (CTK_CONTAINER (path_bar)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((path_bar)), ((ctk_container_get_type ()))))))
,
1854 BUTTON_DATA (path_bar->button_list->data)((ButtonData *)(path_bar->button_list->data))->button);
1855 }
1856 }
1857 }
1858
1859 g_object_unref (current_location);
1860 g_object_unref (location);
1861 return;
1862 }
1863 g_object_unref (location);
1864
1865 /* MOUNTs use the GMount as the name, so don't update for those */
1866 if (button_data->type != MOUNT_BUTTON)
1867 {
1868 char *display_name;
1869
1870 display_name = baul_file_get_display_name (file);
1871 if (g_strcmp0 (display_name, button_data->dir_name) != 0)
1872 {
1873 g_free (button_data->dir_name);
1874 button_data->dir_name = g_strdup (display_name)g_strdup_inline (display_name);
1875 }
1876
1877 g_free (display_name);
1878 }
1879 baul_path_bar_update_button_appearance (button_data);
1880}
1881
1882static ButtonData *
1883make_directory_button (BaulPathBar *path_bar,
1884 BaulFile *file,
1885 gboolean current_dir,
1886 gboolean base_dir,
1887 gboolean file_is_hidden)
1888{
1889 GFile *path;
1890 CtkWidget *child;
1891 ButtonData *button_data;
1892
1893 path = baul_file_get_location (file);
1894
1895 child = NULL((void*)0);
1896
1897 file_is_hidden = !! file_is_hidden;
1898 /* Is it a special button? */
1899 button_data = g_new0 (ButtonData, 1)((ButtonData *) g_malloc0_n ((1), sizeof (ButtonData)));
1900
1901 setup_button_type (button_data, path_bar, path);
1902 button_data->button = ctk_toggle_button_new ();
1903 ctk_style_context_add_class (ctk_widget_get_style_context (button_data->button),
1904 "text-button");
1905 ctk_widget_set_focus_on_click (button_data->button, FALSE(0));
1906 ctk_widget_add_events (button_data->button, CDK_SCROLL_MASK);
1907 /* TODO update button type when xdg directories change */
1908
1909 button_data->drag_info.target_location = g_object_ref (path)((__typeof__ (path)) (g_object_ref) (path));
1910
1911 button_data->image = ctk_image_new ();
1912
1913 switch (button_data->type)
1914 {
1915 case ROOT_BUTTON:
1916 /* Fall through */
1917 case HOME_BUTTON:
1918 /* Fall through */
1919 case DESKTOP_BUTTON:
1920 /* Fall through */
1921 case MOUNT_BUTTON:
1922 /* Fall through */
1923 case DEFAULT_LOCATION_BUTTON:
1924 button_data->label = ctk_label_new (NULL((void*)0));
1925 child = ctk_box_new (CTK_ORIENTATION_HORIZONTAL, 2);
1926 ctk_box_pack_start (CTK_BOX (child)((((CtkBox*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((child)), ((ctk_box_get_type ()))))))
, button_data->image, FALSE(0), FALSE(0), 0);
1927 ctk_box_pack_start (CTK_BOX (child)((((CtkBox*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((child)), ((ctk_box_get_type ()))))))
, button_data->label, FALSE(0), FALSE(0), 0);
1928
1929 break;
1930 case NORMAL_BUTTON:
1931 default:
1932 button_data->label = ctk_label_new (NULL((void*)0));
1933 child = ctk_box_new (CTK_ORIENTATION_HORIZONTAL, 2);
1934 ctk_box_pack_start (CTK_BOX (child)((((CtkBox*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((child)), ((ctk_box_get_type ()))))))
, button_data->image, FALSE(0), FALSE(0), 0);
1935 ctk_box_pack_start (CTK_BOX (child)((((CtkBox*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((child)), ((ctk_box_get_type ()))))))
, button_data->label, FALSE(0), FALSE(0), 0);
1936 button_data->is_base_dir = base_dir;
1937 }
1938
1939 if (button_data->path == NULL((void*)0))
1940 {
1941 button_data->path = g_object_ref (path)((__typeof__ (path)) (g_object_ref) (path));
1942 }
1943 if (button_data->dir_name == NULL((void*)0))
1944 {
1945 button_data->dir_name = baul_file_get_display_name (file);
1946 }
1947 if (button_data->file == NULL((void*)0))
1948 {
1949 button_data->file = baul_file_ref (file);
1950 baul_file_monitor_add (button_data->file, button_data,
1951 BAUL_FILE_ATTRIBUTES_FOR_ICON(BAUL_FILE_ATTRIBUTE_INFO | BAUL_FILE_ATTRIBUTE_LINK_INFO | BAUL_FILE_ATTRIBUTE_THUMBNAIL
)
);
1952 button_data->file_changed_signal_id =
1953 g_signal_connect (button_data->file, "changed",g_signal_connect_data ((button_data->file), ("changed"), (
((GCallback) (button_data_file_changed))), (button_data), ((void
*)0), (GConnectFlags) 0)
1954 G_CALLBACK (button_data_file_changed),g_signal_connect_data ((button_data->file), ("changed"), (
((GCallback) (button_data_file_changed))), (button_data), ((void
*)0), (GConnectFlags) 0)
1955 button_data)g_signal_connect_data ((button_data->file), ("changed"), (
((GCallback) (button_data_file_changed))), (button_data), ((void
*)0), (GConnectFlags) 0)
;
1956 }
1957
1958 button_data->file_is_hidden = file_is_hidden;
1959
1960 ctk_container_add (CTK_CONTAINER (button_data->button)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((button_data->button)), ((ctk_container_get_type ())))
)))
, child);
1961 ctk_widget_show_all (button_data->button);
1962
1963 baul_path_bar_update_button_state (button_data, current_dir);
1964
1965 g_signal_connect (button_data->button, "clicked", G_CALLBACK (button_clicked_cb), button_data)g_signal_connect_data ((button_data->button), ("clicked"),
(((GCallback) (button_clicked_cb))), (button_data), ((void*)
0), (GConnectFlags) 0)
;
1966 g_signal_connect (button_data->button, "button-press-event", G_CALLBACK (button_event_cb), button_data)g_signal_connect_data ((button_data->button), ("button-press-event"
), (((GCallback) (button_event_cb))), (button_data), ((void*)
0), (GConnectFlags) 0)
;
1967 g_signal_connect (button_data->button, "button-release-event", G_CALLBACK (button_event_cb), button_data)g_signal_connect_data ((button_data->button), ("button-release-event"
), (((GCallback) (button_event_cb))), (button_data), ((void*)
0), (GConnectFlags) 0)
;
1968 g_signal_connect (button_data->button, "drag-begin", G_CALLBACK (button_drag_begin_cb), button_data)g_signal_connect_data ((button_data->button), ("drag-begin"
), (((GCallback) (button_drag_begin_cb))), (button_data), ((void
*)0), (GConnectFlags) 0)
;
1969 g_object_weak_ref (G_OBJECT (button_data->button)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((button_data->button)), (((GType) ((20) << (2)))
)))))
, (GWeakNotify) button_data_free, button_data);
1970
1971 setup_button_drag_source (button_data);
1972
1973 baul_drag_slot_proxy_init (button_data->button,
1974 &(button_data->drag_info));
1975
1976 g_object_unref (path);
1977
1978 return button_data;
1979}
1980
1981static gboolean
1982baul_path_bar_check_parent_path (BaulPathBar *path_bar,
1983 GFile *location,
1984 ButtonData **current_button_data)
1985{
1986 GList *list;
1987 GList *current_path;
1988 gboolean need_new_fake_root;
1989
1990 current_path = NULL((void*)0);
1991 need_new_fake_root = FALSE(0);
1992
1993 if (current_button_data)
1994 {
1995 *current_button_data = NULL((void*)0);
1996 }
1997
1998 for (list = path_bar->button_list; list; list = list->next)
1999 {
2000 ButtonData *button_data;
2001
2002 button_data = list->data;
2003 if (g_file_equal (location, button_data->path))
2004 {
2005 current_path = list;
2006
2007 if (current_button_data)
2008 {
2009 *current_button_data = button_data;
2010 }
2011 break;
2012 }
2013 if (list == path_bar->fake_root)
2014 {
2015 need_new_fake_root = TRUE(!(0));
2016 }
2017 }
2018
2019 if (current_path)
2020 {
2021
2022 if (need_new_fake_root)
2023 {
2024 path_bar->fake_root = NULL((void*)0);
2025 for (list = current_path; list; list = list->next)
2026 {
2027 ButtonData *button_data;
2028
2029 button_data = list->data;
2030 if (list->prev != NULL((void*)0) &&
2031 button_data->fake_root)
2032 {
2033 path_bar->fake_root = list;
2034 break;
2035 }
2036 }
2037 }
2038
2039 for (list = path_bar->button_list; list; list = list->next)
2040 {
2041
2042 baul_path_bar_update_button_state (BUTTON_DATA (list->data)((ButtonData *)(list->data)),
2043 (list == current_path) ? TRUE(!(0)) : FALSE(0));
2044 }
2045
2046 if (!ctk_widget_get_child_visible (BUTTON_DATA (current_path->data)((ButtonData *)(current_path->data))->button))
2047 {
2048 path_bar->first_scrolled_button = current_path;
2049 ctk_widget_queue_resize (CTK_WIDGET (path_bar)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((path_bar)), ((ctk_widget_get_type ()))))))
);
2050 }
2051 return TRUE(!(0));
2052 }
2053 return FALSE(0);
2054}
2055
2056static gboolean
2057baul_path_bar_update_path (BaulPathBar *path_bar,
2058 GFile *file_path,
2059 gboolean emit_signal)
2060{
2061 BaulFile *file, *parent_file;
2062 gboolean first_directory, last_directory;
2063 gboolean result;
2064 GList *new_buttons, *l, *fake_root;
2065 ButtonData *button_data, *current_button_data;
2066
2067 g_return_val_if_fail (BAUL_IS_PATH_BAR (path_bar), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((path_bar)); GType __t = ((baul_path_bar_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_PATH_BAR (path_bar)"); return ((0)); }
} while (0)
;
2068 g_return_val_if_fail (file_path != NULL, FALSE)do { if ((file_path != ((void*)0))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "file_path != NULL"
); return ((0)); } } while (0)
;
2069
2070 fake_root = NULL((void*)0);
2071 result = TRUE(!(0));
2072 first_directory = TRUE(!(0));
2073 new_buttons = NULL((void*)0);
2074 current_button_data = NULL((void*)0);
2075
2076 file = baul_file_get (file_path);
2077
2078 while (file != NULL((void*)0))
2079 {
2080 parent_file = baul_file_get_parent (file);
2081 last_directory = !parent_file;
2082 button_data = make_directory_button (path_bar, file, first_directory, last_directory, FALSE(0));
2083 baul_file_unref (file);
2084
2085 if (first_directory)
2086 {
2087 current_button_data = button_data;
2088 }
2089
2090 new_buttons = g_list_prepend (new_buttons, button_data);
2091
2092 if (parent_file != NULL((void*)0) &&
2093 button_data->fake_root)
2094 {
2095 fake_root = new_buttons;
2096 }
2097
2098 file = parent_file;
2099 first_directory = FALSE(0);
2100 }
2101
2102 baul_path_bar_clear_buttons (path_bar);
2103 path_bar->button_list = g_list_reverse (new_buttons);
2104 path_bar->fake_root = fake_root;
2105
2106 for (l = path_bar->button_list; l; l = l->next)
2107 {
2108 CtkWidget *button;
2109 button = BUTTON_DATA (l->data)((ButtonData *)(l->data))->button;
2110 ctk_container_add (CTK_CONTAINER (path_bar)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((path_bar)), ((ctk_container_get_type ()))))))
, button);
2111 }
2112
2113 if (path_bar->current_path != NULL((void*)0))
2114 {
2115 g_object_unref (path_bar->current_path);
2116 }
2117
2118 path_bar->current_path = g_object_ref (file_path)((__typeof__ (file_path)) (g_object_ref) (file_path));
2119
2120 path_bar->current_button_data = current_button_data;
2121
2122 return result;
2123}
2124
2125gboolean
2126baul_path_bar_set_path (BaulPathBar *path_bar, GFile *file_path)
2127{
2128 ButtonData *button_data;
2129
2130 g_return_val_if_fail (BAUL_IS_PATH_BAR (path_bar), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((path_bar)); GType __t = ((baul_path_bar_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_PATH_BAR (path_bar)"); return ((0)); }
} while (0)
;
2131 g_return_val_if_fail (file_path != NULL, FALSE)do { if ((file_path != ((void*)0))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "file_path != NULL"
); return ((0)); } } while (0)
;
2132
2133 /* Check whether the new path is already present in the pathbar as buttons.
2134 * This could be a parent directory or a previous selected subdirectory. */
2135 if (baul_path_bar_check_parent_path (path_bar, file_path, &button_data))
2136 {
2137 if (path_bar->current_path != NULL((void*)0))
2138 {
2139 g_object_unref (path_bar->current_path);
2140 }
2141
2142 path_bar->current_path = g_object_ref (file_path)((__typeof__ (file_path)) (g_object_ref) (file_path));
2143 path_bar->current_button_data = button_data;
2144
2145 return TRUE(!(0));
2146 }
2147
2148 return baul_path_bar_update_path (path_bar, file_path, TRUE(!(0)));
2149}
2150
2151GFile *
2152baul_path_bar_get_path_for_button (BaulPathBar *path_bar,
2153 CtkWidget *button)
2154{
2155 GList *list;
2156
2157 g_return_val_if_fail (BAUL_IS_PATH_BAR (path_bar), NULL)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((path_bar)); GType __t = ((baul_path_bar_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_PATH_BAR (path_bar)"); return (((void
*)0)); } } while (0)
;
2158 g_return_val_if_fail (CTK_IS_BUTTON (button), NULL)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((button)); GType __t = ((ctk_button_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_BUTTON (button)"); return (((void*)0))
; } } while (0)
;
2159
2160 for (list = path_bar->button_list; list; list = list->next)
2161 {
2162 ButtonData *button_data;
2163 button_data = BUTTON_DATA (list->data)((ButtonData *)(list->data));
2164 if (button_data->button == button)
2165 {
2166 return g_object_ref (button_data->path)((__typeof__ (button_data->path)) (g_object_ref) (button_data
->path))
;
2167 }
2168 }
2169
2170 return NULL((void*)0);
2171}
2172
2173CtkWidget *
2174baul_path_bar_get_button_from_button_list_entry (gpointer entry)
2175{
2176 return BUTTON_DATA(entry)((ButtonData *)(entry))->button;
2177}