Bug Summary

File:ctk/ctkfilechooserbutton.c
Warning:line 1308, column 7
This statement is never executed

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 ctkfilechooserbutton.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/ctk -resource-dir /usr/lib/llvm-16/lib/clang/16 -D HAVE_CONFIG_H -I . -I .. -D G_LOG_DOMAIN="Ctk" -D G_LOG_USE_STRUCTURED=1 -D CTK_VERSION="3.25.5" -D CTK_BINARY_VERSION="3.0.0" -D CTK_COMPILATION -D CTK_PRINT_BACKEND_ENABLE_UNSUPPORTED -D CTK_LIBDIR="/usr/lib" -D CTK_LOCALEDIR="/usr/share/locale" -D CTK_DATADIR="/usr/share" -D CTK_DATA_PREFIX="/usr" -D CTK_SYSCONFDIR="/usr/etc" -D CTK_HOST="x86_64-pc-linux-gnu" -D CTK_PRINT_BACKENDS="file,cups" -D X11_DATA_PREFIX="/usr" -D ISO_CODES_PREFIX="" -I .. -I ../ctk -I .. -I ../cdk -I /usr/include/glib-2.0 -I /usr/lib/x86_64-linux-gnu/glib-2.0/include -I /usr/include/sysprof-6 -D G_ENABLE_DEBUG -D G_ENABLE_CONSISTENCY_CHECKS -D GLIB_MIN_REQUIRED_VERSION=GLIB_VERSION_2_66 -D GLIB_MAX_ALLOWED_VERSION=GLIB_VERSION_2_66 -I /usr/include/pango-1.0 -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/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/atk-1.0 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/x86_64-linux-gnu -I /usr/include/webp -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/gio-unix-2.0 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -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/pango-1.0 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/cairo -I /usr/include/pixman-1 -D PIC -internal-isystem /usr/lib/llvm-16/lib/clang/16/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../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/ctk -ferror-limit 19 -fvisibility=hidden -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-09-19-172131-43638-1 -x c ctkfilechooserbutton.c
1/* -*- Mode: C; c-file-style: "gnu"; tab-width: 8 -*- */
2
3/* CTK+: ctkfilechooserbutton.c
4 *
5 * Copyright (c) 2004 James M. Cape <jcape@ignore-your.tv>
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Library General Public License for more details.
16 *
17 * You should have received a copy of the GNU Library General Public
18 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
19 */
20
21#include "config.h"
22
23#include <sys/types.h>
24#include <sys/stat.h>
25#ifdef HAVE_UNISTD_H1
26#include <unistd.h>
27#endif
28
29#include <string.h>
30
31#include "ctkintl.h"
32#include "ctkbutton.h"
33#include "ctkcelllayout.h"
34#include "ctkcellrenderertext.h"
35#include "ctkcellrendererpixbuf.h"
36#include "ctkcombobox.h"
37#include "ctkcssiconthemevalueprivate.h"
38#include "ctkdnd.h"
39#include "ctkdragdest.h"
40#include "ctkicontheme.h"
41#include "ctkiconfactory.h"
42#include "ctkimage.h"
43#include "ctklabel.h"
44#include "ctkliststore.h"
45#include "ctkstock.h"
46#include "ctktreemodelfilter.h"
47#include "ctkseparator.h"
48#include "ctkfilechooserdialog.h"
49#include "ctkfilechoosernative.h"
50#include "ctkfilechooserprivate.h"
51#include "ctkfilechooserutils.h"
52#include "ctkmarshalers.h"
53
54#include "ctkfilechooserbutton.h"
55
56#include "ctkorientable.h"
57
58#include "ctktypebuiltins.h"
59#include "ctkprivate.h"
60#include "ctksettings.h"
61#include "ctkstylecontextprivate.h"
62#include "ctkbitmaskprivate.h"
63
64/**
65 * SECTION:ctkfilechooserbutton
66 * @Short_description: A button to launch a file selection dialog
67 * @Title: CtkFileChooserButton
68 * @See_also:#CtkFileChooserDialog
69 *
70 * The #CtkFileChooserButton is a widget that lets the user select a
71 * file. It implements the #CtkFileChooser interface. Visually, it is a
72 * file name with a button to bring up a #CtkFileChooserDialog.
73 * The user can then use that dialog to change the file associated with
74 * that button. This widget does not support setting the
75 * #CtkFileChooser:select-multiple property to %TRUE.
76 *
77 * ## Create a button to let the user select a file in /etc
78 *
79 * |[<!-- language="C" -->
80 * {
81 * CtkWidget *button;
82 *
83 * button = ctk_file_chooser_button_new (_("Select a file"),
84 * CTK_FILE_CHOOSER_ACTION_OPEN);
85 * ctk_file_chooser_set_current_folder (CTK_FILE_CHOOSER (button),
86 * "/etc");
87 * }
88 * ]|
89 *
90 * The #CtkFileChooserButton supports the #CtkFileChooserActions
91 * %CTK_FILE_CHOOSER_ACTION_OPEN and %CTK_FILE_CHOOSER_ACTION_SELECT_FOLDER.
92 *
93 * > The #CtkFileChooserButton will ellipsize the label, and will thus
94 * > request little horizontal space. To give the button more space,
95 * > you should call ctk_widget_get_preferred_size(),
96 * > ctk_file_chooser_button_set_width_chars(), or pack the button in
97 * > such a way that other interface elements give space to the
98 * > widget.
99 *
100 * # CSS nodes
101 *
102 * CtkFileChooserButton has a CSS node with name “filechooserbutton”, containing
103 * a subnode for the internal button with name “button” and style class “.file”.
104 */
105
106
107/* **************** *
108 * Private Macros *
109 * **************** */
110
111#define FALLBACK_ICON_SIZE16 16
112#define DEFAULT_TITLE("Select a File") N_("Select a File")("Select a File")
113#define DESKTOP_DISPLAY_NAME("Desktop") N_("Desktop")("Desktop")
114#define FALLBACK_DISPLAY_NAME("(None)") N_("(None)")("(None)") /* this string is used in ctk+/ctk/tests/filechooser.c - change it there if you change it here */
115
116
117/* ********************** *
118 * Private Enumerations *
119 * ********************** */
120
121/* Property IDs */
122enum
123{
124 PROP_0,
125
126 PROP_DIALOG,
127 PROP_TITLE,
128 PROP_WIDTH_CHARS
129};
130
131/* Signals */
132enum
133{
134 FILE_SET,
135 LAST_SIGNAL
136};
137
138/* TreeModel Columns
139 *
140 * keep in line with the store defined in ctkfilechooserbutton.ui
141 */
142enum
143{
144 ICON_COLUMN,
145 DISPLAY_NAME_COLUMN,
146 TYPE_COLUMN,
147 DATA_COLUMN,
148 IS_FOLDER_COLUMN,
149 CANCELLABLE_COLUMN,
150 NUM_COLUMNS
151};
152
153/* TreeModel Row Types */
154typedef enum
155{
156 ROW_TYPE_SPECIAL,
157 ROW_TYPE_VOLUME,
158 ROW_TYPE_SHORTCUT,
159 ROW_TYPE_BOOKMARK_SEPARATOR,
160 ROW_TYPE_BOOKMARK,
161 ROW_TYPE_CURRENT_FOLDER_SEPARATOR,
162 ROW_TYPE_CURRENT_FOLDER,
163 ROW_TYPE_OTHER_SEPARATOR,
164 ROW_TYPE_OTHER,
165 ROW_TYPE_EMPTY_SELECTION,
166
167 ROW_TYPE_INVALID = -1
168}
169RowType;
170
171
172/* ******************** *
173 * Private Structures *
174 * ******************** */
175
176struct _CtkFileChooserButtonPrivate
177{
178 CtkFileChooser *chooser; /* Points to either dialog or native, depending on which is set */
179 CtkWidget *dialog; /* Set if you explicitly enable */
180 CtkFileChooserNative *native; /* Otherwise this is set */
181 CtkWidget *button;
182 CtkWidget *image;
183 CtkWidget *label;
184 CtkWidget *combo_box;
185 CtkCellRenderer *icon_cell;
186 CtkCellRenderer *name_cell;
187
188 CtkTreeModel *model;
189 CtkTreeModel *filter_model;
190
191 CtkFileSystem *fs;
192 GFile *selection_while_inactive;
193 GFile *current_folder_while_inactive;
194
195 gulong fs_volumes_changed_id;
196
197 GCancellable *dnd_select_folder_cancellable;
198 GCancellable *update_button_cancellable;
199 GSList *change_icon_theme_cancellables;
200
201 CtkBookmarksManager *bookmarks_manager;
202
203 gint icon_size;
204
205 guint8 n_special;
206 guint8 n_volumes;
207 guint8 n_shortcuts;
208 guint8 n_bookmarks;
209 guint has_bookmark_separator : 1;
210 guint has_current_folder_separator : 1;
211 guint has_current_folder : 1;
212 guint has_other_separator : 1;
213
214 /* Used for hiding/showing the dialog when the button is hidden */
215 guint active : 1;
216
217 /* Whether the next async callback from GIO should emit the "selection-changed" signal */
218 guint is_changing_selection : 1;
219};
220
221
222/* ************* *
223 * DnD Support *
224 * ************* */
225
226enum
227{
228 TEXT_PLAIN,
229 TEXT_URI_LIST
230};
231
232
233/* ********************* *
234 * Function Prototypes *
235 * ********************* */
236
237/* CtkFileChooserIface Functions */
238static void ctk_file_chooser_button_file_chooser_iface_init (CtkFileChooserIface *iface);
239static gboolean ctk_file_chooser_button_set_current_folder (CtkFileChooser *chooser,
240 GFile *file,
241 GError **error);
242static GFile *ctk_file_chooser_button_get_current_folder (CtkFileChooser *chooser);
243static gboolean ctk_file_chooser_button_select_file (CtkFileChooser *chooser,
244 GFile *file,
245 GError **error);
246static void ctk_file_chooser_button_unselect_file (CtkFileChooser *chooser,
247 GFile *file);
248static void ctk_file_chooser_button_unselect_all (CtkFileChooser *chooser);
249static GSList *ctk_file_chooser_button_get_files (CtkFileChooser *chooser);
250static gboolean ctk_file_chooser_button_add_shortcut_folder (CtkFileChooser *chooser,
251 GFile *file,
252 GError **error);
253static gboolean ctk_file_chooser_button_remove_shortcut_folder (CtkFileChooser *chooser,
254 GFile *file,
255 GError **error);
256
257/* GObject Functions */
258static void ctk_file_chooser_button_constructed (GObject *object);
259static void ctk_file_chooser_button_set_property (GObject *object,
260 guint param_id,
261 const GValue *value,
262 GParamSpec *pspec);
263static void ctk_file_chooser_button_get_property (GObject *object,
264 guint param_id,
265 GValue *value,
266 GParamSpec *pspec);
267static void ctk_file_chooser_button_finalize (GObject *object);
268
269/* CtkWidget Functions */
270static void ctk_file_chooser_button_destroy (CtkWidget *widget);
271static void ctk_file_chooser_button_drag_data_received (CtkWidget *widget,
272 CdkDragContext *context,
273 gint x,
274 gint y,
275 CtkSelectionData *data,
276 guint type,
277 guint drag_time);
278static void ctk_file_chooser_button_show_all (CtkWidget *widget);
279static void ctk_file_chooser_button_show (CtkWidget *widget);
280static void ctk_file_chooser_button_hide (CtkWidget *widget);
281static void ctk_file_chooser_button_map (CtkWidget *widget);
282static gboolean ctk_file_chooser_button_mnemonic_activate (CtkWidget *widget,
283 gboolean group_cycling);
284static void ctk_file_chooser_button_style_updated (CtkWidget *widget);
285static void ctk_file_chooser_button_screen_changed (CtkWidget *widget,
286 CdkScreen *old_screen);
287static void ctk_file_chooser_button_state_flags_changed (CtkWidget *widget,
288 CtkStateFlags previous_state);
289
290/* Utility Functions */
291static CtkIconTheme *get_icon_theme (CtkWidget *widget);
292static void set_info_for_file_at_iter (CtkFileChooserButton *fs,
293 GFile *file,
294 CtkTreeIter *iter);
295
296static gint model_get_type_position (CtkFileChooserButton *button,
297 RowType row_type);
298static void model_free_row_data (CtkFileChooserButton *button,
299 CtkTreeIter *iter);
300static void model_add_special (CtkFileChooserButton *button);
301static void model_add_other (CtkFileChooserButton *button);
302static void model_add_empty_selection (CtkFileChooserButton *button);
303static void model_add_volumes (CtkFileChooserButton *button,
304 GSList *volumes);
305static void model_add_bookmarks (CtkFileChooserButton *button,
306 GSList *bookmarks);
307static void model_update_current_folder (CtkFileChooserButton *button,
308 GFile *file);
309static void model_remove_rows (CtkFileChooserButton *button,
310 gint pos,
311 gint n_rows);
312
313static gboolean filter_model_visible_func (CtkTreeModel *model,
314 CtkTreeIter *iter,
315 gpointer user_data);
316
317static gboolean combo_box_row_separator_func (CtkTreeModel *model,
318 CtkTreeIter *iter,
319 gpointer user_data);
320static void name_cell_data_func (CtkCellLayout *layout,
321 CtkCellRenderer *cell,
322 CtkTreeModel *model,
323 CtkTreeIter *iter,
324 gpointer user_data);
325static void open_dialog (CtkFileChooserButton *button);
326static void update_combo_box (CtkFileChooserButton *button);
327static void update_label_and_image (CtkFileChooserButton *button);
328
329/* Child Object Callbacks */
330static void fs_volumes_changed_cb (CtkFileSystem *fs,
331 gpointer user_data);
332static void bookmarks_changed_cb (gpointer user_data);
333
334static void combo_box_changed_cb (CtkComboBox *combo_box,
335 gpointer user_data);
336static void combo_box_notify_popup_shown_cb (GObject *object,
337 GParamSpec *pspec,
338 gpointer user_data);
339
340static void button_clicked_cb (CtkButton *real_button,
341 gpointer user_data);
342
343static void chooser_update_preview_cb (CtkFileChooser *dialog,
344 gpointer user_data);
345static void chooser_notify_cb (GObject *dialog,
346 GParamSpec *pspec,
347 gpointer user_data);
348static gboolean dialog_delete_event_cb (CtkWidget *dialog,
349 CdkEvent *event,
350 gpointer user_data);
351static void dialog_response_cb (CtkDialog *dialog,
352 gint response,
353 gpointer user_data);
354static void native_response_cb (CtkFileChooserNative *native,
355 gint response,
356 gpointer user_data);
357
358static guint file_chooser_button_signals[LAST_SIGNAL] = { 0 };
359
360/* ******************* *
361 * GType Declaration *
362 * ******************* */
363
364G_DEFINE_TYPE_WITH_CODE (CtkFileChooserButton, ctk_file_chooser_button, CTK_TYPE_BOX,static void ctk_file_chooser_button_init (CtkFileChooserButton
*self); static void ctk_file_chooser_button_class_init (CtkFileChooserButtonClass
*klass); static GType ctk_file_chooser_button_get_type_once (
void); static gpointer ctk_file_chooser_button_parent_class =
((void*)0); static gint CtkFileChooserButton_private_offset;
static void ctk_file_chooser_button_class_intern_init (gpointer
klass) { ctk_file_chooser_button_parent_class = g_type_class_peek_parent
(klass); if (CtkFileChooserButton_private_offset != 0) g_type_class_adjust_private_offset
(klass, &CtkFileChooserButton_private_offset); ctk_file_chooser_button_class_init
((CtkFileChooserButtonClass*) klass); } __attribute__ ((__unused__
)) static inline gpointer ctk_file_chooser_button_get_instance_private
(CtkFileChooserButton *self) { return (((gpointer) ((guint8*
) (self) + (glong) (CtkFileChooserButton_private_offset)))); }
GType ctk_file_chooser_button_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
= ctk_file_chooser_button_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 ctk_file_chooser_button_get_type_once
(void) { GType g_define_type_id = g_type_register_static_simple
((ctk_box_get_type ()), g_intern_static_string ("CtkFileChooserButton"
), sizeof (CtkFileChooserButtonClass), (GClassInitFunc)(void (
*)(void)) ctk_file_chooser_button_class_intern_init, sizeof (
CtkFileChooserButton), (GInstanceInitFunc)(void (*)(void)) ctk_file_chooser_button_init
, (GTypeFlags) 0); { {{ CtkFileChooserButton_private_offset =
g_type_add_instance_private (g_define_type_id, sizeof (CtkFileChooserButtonPrivate
)); } { const GInterfaceInfo g_implement_interface_info = { (
GInterfaceInitFunc)(void (*)(void)) ctk_file_chooser_button_file_chooser_iface_init
, ((void*)0), ((void*)0) }; g_type_add_interface_static (g_define_type_id
, (ctk_file_chooser_get_type ()), &g_implement_interface_info
); };} } return g_define_type_id; }
365 G_ADD_PRIVATE (CtkFileChooserButton)static void ctk_file_chooser_button_init (CtkFileChooserButton
*self); static void ctk_file_chooser_button_class_init (CtkFileChooserButtonClass
*klass); static GType ctk_file_chooser_button_get_type_once (
void); static gpointer ctk_file_chooser_button_parent_class =
((void*)0); static gint CtkFileChooserButton_private_offset;
static void ctk_file_chooser_button_class_intern_init (gpointer
klass) { ctk_file_chooser_button_parent_class = g_type_class_peek_parent
(klass); if (CtkFileChooserButton_private_offset != 0) g_type_class_adjust_private_offset
(klass, &CtkFileChooserButton_private_offset); ctk_file_chooser_button_class_init
((CtkFileChooserButtonClass*) klass); } __attribute__ ((__unused__
)) static inline gpointer ctk_file_chooser_button_get_instance_private
(CtkFileChooserButton *self) { return (((gpointer) ((guint8*
) (self) + (glong) (CtkFileChooserButton_private_offset)))); }
GType ctk_file_chooser_button_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
= ctk_file_chooser_button_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 ctk_file_chooser_button_get_type_once
(void) { GType g_define_type_id = g_type_register_static_simple
((ctk_box_get_type ()), g_intern_static_string ("CtkFileChooserButton"
), sizeof (CtkFileChooserButtonClass), (GClassInitFunc)(void (
*)(void)) ctk_file_chooser_button_class_intern_init, sizeof (
CtkFileChooserButton), (GInstanceInitFunc)(void (*)(void)) ctk_file_chooser_button_init
, (GTypeFlags) 0); { {{ CtkFileChooserButton_private_offset =
g_type_add_instance_private (g_define_type_id, sizeof (CtkFileChooserButtonPrivate
)); } { const GInterfaceInfo g_implement_interface_info = { (
GInterfaceInitFunc)(void (*)(void)) ctk_file_chooser_button_file_chooser_iface_init
, ((void*)0), ((void*)0) }; g_type_add_interface_static (g_define_type_id
, (ctk_file_chooser_get_type ()), &g_implement_interface_info
); };} } return g_define_type_id; }
366 G_IMPLEMENT_INTERFACE (CTK_TYPE_FILE_CHOOSER,static void ctk_file_chooser_button_init (CtkFileChooserButton
*self); static void ctk_file_chooser_button_class_init (CtkFileChooserButtonClass
*klass); static GType ctk_file_chooser_button_get_type_once (
void); static gpointer ctk_file_chooser_button_parent_class =
((void*)0); static gint CtkFileChooserButton_private_offset;
static void ctk_file_chooser_button_class_intern_init (gpointer
klass) { ctk_file_chooser_button_parent_class = g_type_class_peek_parent
(klass); if (CtkFileChooserButton_private_offset != 0) g_type_class_adjust_private_offset
(klass, &CtkFileChooserButton_private_offset); ctk_file_chooser_button_class_init
((CtkFileChooserButtonClass*) klass); } __attribute__ ((__unused__
)) static inline gpointer ctk_file_chooser_button_get_instance_private
(CtkFileChooserButton *self) { return (((gpointer) ((guint8*
) (self) + (glong) (CtkFileChooserButton_private_offset)))); }
GType ctk_file_chooser_button_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
= ctk_file_chooser_button_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 ctk_file_chooser_button_get_type_once
(void) { GType g_define_type_id = g_type_register_static_simple
((ctk_box_get_type ()), g_intern_static_string ("CtkFileChooserButton"
), sizeof (CtkFileChooserButtonClass), (GClassInitFunc)(void (
*)(void)) ctk_file_chooser_button_class_intern_init, sizeof (
CtkFileChooserButton), (GInstanceInitFunc)(void (*)(void)) ctk_file_chooser_button_init
, (GTypeFlags) 0); { {{ CtkFileChooserButton_private_offset =
g_type_add_instance_private (g_define_type_id, sizeof (CtkFileChooserButtonPrivate
)); } { const GInterfaceInfo g_implement_interface_info = { (
GInterfaceInitFunc)(void (*)(void)) ctk_file_chooser_button_file_chooser_iface_init
, ((void*)0), ((void*)0) }; g_type_add_interface_static (g_define_type_id
, (ctk_file_chooser_get_type ()), &g_implement_interface_info
); };} } return g_define_type_id; }
367 ctk_file_chooser_button_file_chooser_iface_init))static void ctk_file_chooser_button_init (CtkFileChooserButton
*self); static void ctk_file_chooser_button_class_init (CtkFileChooserButtonClass
*klass); static GType ctk_file_chooser_button_get_type_once (
void); static gpointer ctk_file_chooser_button_parent_class =
((void*)0); static gint CtkFileChooserButton_private_offset;
static void ctk_file_chooser_button_class_intern_init (gpointer
klass) { ctk_file_chooser_button_parent_class = g_type_class_peek_parent
(klass); if (CtkFileChooserButton_private_offset != 0) g_type_class_adjust_private_offset
(klass, &CtkFileChooserButton_private_offset); ctk_file_chooser_button_class_init
((CtkFileChooserButtonClass*) klass); } __attribute__ ((__unused__
)) static inline gpointer ctk_file_chooser_button_get_instance_private
(CtkFileChooserButton *self) { return (((gpointer) ((guint8*
) (self) + (glong) (CtkFileChooserButton_private_offset)))); }
GType ctk_file_chooser_button_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
= ctk_file_chooser_button_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 ctk_file_chooser_button_get_type_once
(void) { GType g_define_type_id = g_type_register_static_simple
((ctk_box_get_type ()), g_intern_static_string ("CtkFileChooserButton"
), sizeof (CtkFileChooserButtonClass), (GClassInitFunc)(void (
*)(void)) ctk_file_chooser_button_class_intern_init, sizeof (
CtkFileChooserButton), (GInstanceInitFunc)(void (*)(void)) ctk_file_chooser_button_init
, (GTypeFlags) 0); { {{ CtkFileChooserButton_private_offset =
g_type_add_instance_private (g_define_type_id, sizeof (CtkFileChooserButtonPrivate
)); } { const GInterfaceInfo g_implement_interface_info = { (
GInterfaceInitFunc)(void (*)(void)) ctk_file_chooser_button_file_chooser_iface_init
, ((void*)0), ((void*)0) }; g_type_add_interface_static (g_define_type_id
, (ctk_file_chooser_get_type ()), &g_implement_interface_info
); };} } return g_define_type_id; }
368
369
370/* ***************** *
371 * GType Functions *
372 * ***************** */
373
374static void
375ctk_file_chooser_button_class_init (CtkFileChooserButtonClass * class)
376{
377 GObjectClass *gobject_class;
378 CtkWidgetClass *widget_class;
379
380 gobject_class = G_OBJECT_CLASS (class)((((GObjectClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((class)), (((GType) ((20) << (2))))))))
;
381 widget_class = CTK_WIDGET_CLASS (class)((((CtkWidgetClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((class)), ((ctk_widget_get_type ()))))))
;
382
383 gobject_class->constructed = ctk_file_chooser_button_constructed;
384 gobject_class->set_property = ctk_file_chooser_button_set_property;
385 gobject_class->get_property = ctk_file_chooser_button_get_property;
386 gobject_class->finalize = ctk_file_chooser_button_finalize;
387
388 widget_class->destroy = ctk_file_chooser_button_destroy;
389 widget_class->drag_data_received = ctk_file_chooser_button_drag_data_received;
390 widget_class->show_all = ctk_file_chooser_button_show_all;
391 widget_class->show = ctk_file_chooser_button_show;
392 widget_class->hide = ctk_file_chooser_button_hide;
393 widget_class->map = ctk_file_chooser_button_map;
394 widget_class->style_updated = ctk_file_chooser_button_style_updated;
395 widget_class->screen_changed = ctk_file_chooser_button_screen_changed;
396 widget_class->mnemonic_activate = ctk_file_chooser_button_mnemonic_activate;
397 widget_class->state_flags_changed = ctk_file_chooser_button_state_flags_changed;
398
399 /**
400 * CtkFileChooserButton::file-set:
401 * @widget: the object which received the signal.
402 *
403 * The ::file-set signal is emitted when the user selects a file.
404 *
405 * Note that this signal is only emitted when the user
406 * changes the file.
407 *
408 * Since: 2.12
409 */
410 file_chooser_button_signals[FILE_SET] =
411 g_signal_new (I_("file-set")g_intern_static_string ("file-set"),
412 G_TYPE_FROM_CLASS (gobject_class)(((GTypeClass*) (gobject_class))->g_type),
413 G_SIGNAL_RUN_FIRST,
414 G_STRUCT_OFFSET (CtkFileChooserButtonClass, file_set)((glong) __builtin_offsetof(CtkFileChooserButtonClass, file_set
))
,
415 NULL((void*)0), NULL((void*)0),
416 NULL((void*)0),
417 G_TYPE_NONE((GType) ((1) << (2))), 0);
418
419 /**
420 * CtkFileChooserButton:dialog:
421 *
422 * Instance of the #CtkFileChooserDialog associated with the button.
423 *
424 * Since: 2.6
425 */
426 g_object_class_install_property (gobject_class, PROP_DIALOG,
427 g_param_spec_object ("dialog",
428 P_("Dialog")g_dgettext("ctk30" "-properties","Dialog"),
429 P_("The file chooser dialog to use.")g_dgettext("ctk30" "-properties","The file chooser dialog to use."
)
,
430 CTK_TYPE_FILE_CHOOSER(ctk_file_chooser_get_type ()),
431 (CTK_PARAM_WRITABLEG_PARAM_WRITABLE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB |
432 G_PARAM_CONSTRUCT_ONLY)));
433
434 /**
435 * CtkFileChooserButton:title:
436 *
437 * Title to put on the #CtkFileChooserDialog associated with the button.
438 *
439 * Since: 2.6
440 */
441 g_object_class_install_property (gobject_class, PROP_TITLE,
442 g_param_spec_string ("title",
443 P_("Title")g_dgettext("ctk30" "-properties","Title"),
444 P_("The title of the file chooser dialog.")g_dgettext("ctk30" "-properties","The title of the file chooser dialog."
)
,
445 _(DEFAULT_TITLE)((char *) g_dgettext ("ctk30", ("Select a File"))),
446 CTK_PARAM_READWRITEG_PARAM_READWRITE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB));
447
448 /**
449 * CtkFileChooserButton:width-chars:
450 *
451 * The width of the entry and label inside the button, in characters.
452 *
453 * Since: 2.6
454 */
455 g_object_class_install_property (gobject_class, PROP_WIDTH_CHARS,
456 g_param_spec_int ("width-chars",
457 P_("Width In Characters")g_dgettext("ctk30" "-properties","Width In Characters"),
458 P_("The desired width of the button widget, in characters.")g_dgettext("ctk30" "-properties","The desired width of the button widget, in characters."
)
,
459 -1, G_MAXINT2147483647, -1,
460 CTK_PARAM_READWRITEG_PARAM_READWRITE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB));
461
462 _ctk_file_chooser_install_properties (gobject_class);
463
464 /* Bind class to template
465 */
466 ctk_widget_class_set_template_from_resource (widget_class,
467 "/org/ctk/libctk/ui/ctkfilechooserbutton.ui");
468
469 ctk_widget_class_bind_template_child_private (widget_class, CtkFileChooserButton, model)ctk_widget_class_bind_template_child_full (widget_class, "model"
, (0), (CtkFileChooserButton_private_offset + (((glong) __builtin_offsetof
(CtkFileChooserButtonPrivate, model)))))
;
470 ctk_widget_class_bind_template_child_private (widget_class, CtkFileChooserButton, button)ctk_widget_class_bind_template_child_full (widget_class, "button"
, (0), (CtkFileChooserButton_private_offset + (((glong) __builtin_offsetof
(CtkFileChooserButtonPrivate, button)))))
;
471 ctk_widget_class_bind_template_child_private (widget_class, CtkFileChooserButton, image)ctk_widget_class_bind_template_child_full (widget_class, "image"
, (0), (CtkFileChooserButton_private_offset + (((glong) __builtin_offsetof
(CtkFileChooserButtonPrivate, image)))))
;
472 ctk_widget_class_bind_template_child_private (widget_class, CtkFileChooserButton, label)ctk_widget_class_bind_template_child_full (widget_class, "label"
, (0), (CtkFileChooserButton_private_offset + (((glong) __builtin_offsetof
(CtkFileChooserButtonPrivate, label)))))
;
473 ctk_widget_class_bind_template_child_private (widget_class, CtkFileChooserButton, combo_box)ctk_widget_class_bind_template_child_full (widget_class, "combo_box"
, (0), (CtkFileChooserButton_private_offset + (((glong) __builtin_offsetof
(CtkFileChooserButtonPrivate, combo_box)))))
;
474 ctk_widget_class_bind_template_child_private (widget_class, CtkFileChooserButton, icon_cell)ctk_widget_class_bind_template_child_full (widget_class, "icon_cell"
, (0), (CtkFileChooserButton_private_offset + (((glong) __builtin_offsetof
(CtkFileChooserButtonPrivate, icon_cell)))))
;
475 ctk_widget_class_bind_template_child_private (widget_class, CtkFileChooserButton, name_cell)ctk_widget_class_bind_template_child_full (widget_class, "name_cell"
, (0), (CtkFileChooserButton_private_offset + (((glong) __builtin_offsetof
(CtkFileChooserButtonPrivate, name_cell)))))
;
476
477 ctk_widget_class_bind_template_callback (widget_class, button_clicked_cb)ctk_widget_class_bind_template_callback_full (((((CtkWidgetClass
*) (void *) g_type_check_class_cast ((GTypeClass*) ((widget_class
)), ((ctk_widget_get_type ())))))), "button_clicked_cb", ((GCallback
) (button_clicked_cb)))
;
478 ctk_widget_class_bind_template_callback (widget_class, combo_box_changed_cb)ctk_widget_class_bind_template_callback_full (((((CtkWidgetClass
*) (void *) g_type_check_class_cast ((GTypeClass*) ((widget_class
)), ((ctk_widget_get_type ())))))), "combo_box_changed_cb", (
(GCallback) (combo_box_changed_cb)))
;
479 ctk_widget_class_bind_template_callback (widget_class, combo_box_notify_popup_shown_cb)ctk_widget_class_bind_template_callback_full (((((CtkWidgetClass
*) (void *) g_type_check_class_cast ((GTypeClass*) ((widget_class
)), ((ctk_widget_get_type ())))))), "combo_box_notify_popup_shown_cb"
, ((GCallback) (combo_box_notify_popup_shown_cb)))
;
480
481 ctk_widget_class_set_css_name (widget_class, "filechooserbutton");
482}
483
484static void
485ctk_file_chooser_button_init (CtkFileChooserButton *button)
486{
487 CtkFileChooserButtonPrivate *priv;
488 CtkTargetList *target_list;
489
490 priv = button->priv = ctk_file_chooser_button_get_instance_private (button);
491
492 priv->icon_size = FALLBACK_ICON_SIZE16;
493
494 ctk_widget_init_template (CTK_WIDGET (button)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((button)), ((ctk_widget_get_type ()))))))
);
495
496 /* Bookmarks manager */
497 priv->bookmarks_manager = _ctk_bookmarks_manager_new (bookmarks_changed_cb, button);
498 ctk_cell_layout_set_cell_data_func (CTK_CELL_LAYOUT (priv->combo_box)((((CtkCellLayout*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((priv->combo_box)), ((ctk_cell_layout_get_type ())))))
)
,
499 priv->name_cell, name_cell_data_func,
500 NULL((void*)0), NULL((void*)0));
501
502 /* DnD */
503 ctk_drag_dest_set (CTK_WIDGET (button)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((button)), ((ctk_widget_get_type ()))))))
,
504 (CTK_DEST_DEFAULT_ALL),
505 NULL((void*)0), 0,
506 CDK_ACTION_COPY);
507 target_list = ctk_target_list_new (NULL((void*)0), 0);
508 ctk_target_list_add_uri_targets (target_list, TEXT_URI_LIST);
509 ctk_target_list_add_text_targets (target_list, TEXT_PLAIN);
510 ctk_drag_dest_set_target_list (CTK_WIDGET (button)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((button)), ((ctk_widget_get_type ()))))))
, target_list);
511 ctk_target_list_unref (target_list);
512}
513
514
515/* ******************************* *
516 * CtkFileChooserIface Functions *
517 * ******************************* */
518static void
519ctk_file_chooser_button_file_chooser_iface_init (CtkFileChooserIface *iface)
520{
521 _ctk_file_chooser_delegate_iface_init (iface);
522
523 iface->set_current_folder = ctk_file_chooser_button_set_current_folder;
524 iface->get_current_folder = ctk_file_chooser_button_get_current_folder;
525 iface->select_file = ctk_file_chooser_button_select_file;
526 iface->unselect_file = ctk_file_chooser_button_unselect_file;
527 iface->unselect_all = ctk_file_chooser_button_unselect_all;
528 iface->get_files = ctk_file_chooser_button_get_files;
529 iface->add_shortcut_folder = ctk_file_chooser_button_add_shortcut_folder;
530 iface->remove_shortcut_folder = ctk_file_chooser_button_remove_shortcut_folder;
531}
532
533static void
534emit_selection_changed_if_changing_selection (CtkFileChooserButton *button)
535{
536 CtkFileChooserButtonPrivate *priv = button->priv;
537
538 if (priv->is_changing_selection)
539 {
540 priv->is_changing_selection = FALSE(0);
541 g_signal_emit_by_name (button, "selection-changed");
542 }
543}
544
545static gboolean
546ctk_file_chooser_button_set_current_folder (CtkFileChooser *chooser,
547 GFile *file,
548 GError **error G_GNUC_UNUSED__attribute__ ((__unused__)))
549{
550 CtkFileChooserButton *button = CTK_FILE_CHOOSER_BUTTON (chooser)((((CtkFileChooserButton*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((chooser)), ((ctk_file_chooser_button_get_type
()))))))
;
551 CtkFileChooserButtonPrivate *priv = button->priv;
552
553 if (priv->current_folder_while_inactive)
554 g_object_unref (priv->current_folder_while_inactive);
555
556 priv->current_folder_while_inactive = g_object_ref (file)((__typeof__ (file)) (g_object_ref) (file));
557
558 update_combo_box (button);
559
560 g_signal_emit_by_name (button, "current-folder-changed");
561
562 if (priv->active)
563 ctk_file_chooser_set_current_folder_file (CTK_FILE_CHOOSER (priv->chooser)((((CtkFileChooser*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((priv->chooser)), ((ctk_file_chooser_get_type ()))))))
, file, NULL((void*)0));
564
565 return TRUE(!(0));
566}
567
568static GFile *
569ctk_file_chooser_button_get_current_folder (CtkFileChooser *chooser)
570{
571 CtkFileChooserButton *button = CTK_FILE_CHOOSER_BUTTON (chooser)((((CtkFileChooserButton*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((chooser)), ((ctk_file_chooser_button_get_type
()))))))
;
572 CtkFileChooserButtonPrivate *priv = button->priv;
573
574 if (priv->current_folder_while_inactive)
575 return g_object_ref (priv->current_folder_while_inactive)((__typeof__ (priv->current_folder_while_inactive)) (g_object_ref
) (priv->current_folder_while_inactive))
;
576 else
577 return NULL((void*)0);
578}
579
580static gboolean
581ctk_file_chooser_button_select_file (CtkFileChooser *chooser,
582 GFile *file,
583 GError **error G_GNUC_UNUSED__attribute__ ((__unused__)))
584{
585 CtkFileChooserButton *button = CTK_FILE_CHOOSER_BUTTON (chooser)((((CtkFileChooserButton*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((chooser)), ((ctk_file_chooser_button_get_type
()))))))
;
586 CtkFileChooserButtonPrivate *priv = button->priv;
587
588 if (priv->selection_while_inactive)
589 g_object_unref (priv->selection_while_inactive);
590
591 priv->selection_while_inactive = g_object_ref (file)((__typeof__ (file)) (g_object_ref) (file));
592
593 priv->is_changing_selection = TRUE(!(0));
594
595 update_label_and_image (button);
596 update_combo_box (button);
597
598 if (priv->active)
599 ctk_file_chooser_select_file (CTK_FILE_CHOOSER (priv->chooser)((((CtkFileChooser*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((priv->chooser)), ((ctk_file_chooser_get_type ()))))))
, file, NULL((void*)0));
600
601 return TRUE(!(0));
602}
603
604static void
605unselect_current_file (CtkFileChooserButton *button)
606{
607 CtkFileChooserButtonPrivate *priv = button->priv;
608
609 if (priv->selection_while_inactive)
610 {
611 g_object_unref (priv->selection_while_inactive);
612 priv->selection_while_inactive = NULL((void*)0);
613 priv->is_changing_selection = TRUE(!(0));
614 }
615
616 update_label_and_image (button);
617 update_combo_box (button);
618}
619
620static void
621ctk_file_chooser_button_unselect_file (CtkFileChooser *chooser,
622 GFile *file)
623{
624 CtkFileChooserButton *button = CTK_FILE_CHOOSER_BUTTON (chooser)((((CtkFileChooserButton*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((chooser)), ((ctk_file_chooser_button_get_type
()))))))
;
625 CtkFileChooserButtonPrivate *priv = button->priv;
626
627 if (g_file_equal (priv->selection_while_inactive, file))
628 unselect_current_file (button);
629
630 if (priv->active)
631 ctk_file_chooser_unselect_file (CTK_FILE_CHOOSER (priv->chooser)((((CtkFileChooser*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((priv->chooser)), ((ctk_file_chooser_get_type ()))))))
, file);
632}
633
634static void
635ctk_file_chooser_button_unselect_all (CtkFileChooser *chooser)
636{
637 CtkFileChooserButton *button = CTK_FILE_CHOOSER_BUTTON (chooser)((((CtkFileChooserButton*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((chooser)), ((ctk_file_chooser_button_get_type
()))))))
;
638 CtkFileChooserButtonPrivate *priv = button->priv;
639
640 unselect_current_file (button);
641
642 if (priv->active)
643 ctk_file_chooser_unselect_all (CTK_FILE_CHOOSER (priv->chooser)((((CtkFileChooser*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((priv->chooser)), ((ctk_file_chooser_get_type ()))))))
);
644}
645
646static GFile *
647get_selected_file (CtkFileChooserButton *button)
648{
649 CtkFileChooserButtonPrivate *priv = button->priv;
650 GFile *retval;
651
652 retval = NULL((void*)0);
653
654 if (priv->selection_while_inactive)
655 retval = priv->selection_while_inactive;
656 else if (priv->chooser && ctk_file_chooser_get_action (priv->chooser) == CTK_FILE_CHOOSER_ACTION_SELECT_FOLDER)
657 {
658 /* If there is no "real" selection in SELECT_FOLDER mode, then we'll just return
659 * the current folder, since that is what CtkFileChooserWidget would do.
660 */
661 if (priv->current_folder_while_inactive)
662 retval = priv->current_folder_while_inactive;
663 }
664
665 if (retval)
666 return g_object_ref (retval)((__typeof__ (retval)) (g_object_ref) (retval));
667 else
668 return NULL((void*)0);
669}
670
671static GSList *
672ctk_file_chooser_button_get_files (CtkFileChooser *chooser)
673{
674 CtkFileChooserButton *button = CTK_FILE_CHOOSER_BUTTON (chooser)((((CtkFileChooserButton*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((chooser)), ((ctk_file_chooser_button_get_type
()))))))
;
675 GFile *file;
676
677 file = get_selected_file (button);
678 if (file)
679 return g_slist_prepend (NULL((void*)0), file);
680 else
681 return NULL((void*)0);
682}
683
684static gboolean
685ctk_file_chooser_button_add_shortcut_folder (CtkFileChooser *chooser,
686 GFile *file,
687 GError **error)
688{
689 CtkFileChooser *delegate;
690 gboolean retval;
691
692 delegate = g_object_get_qdata (G_OBJECT (chooser)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((chooser)), (((GType) ((20) << (2))))))))
,
693 CTK_FILE_CHOOSER_DELEGATE_QUARK(_ctk_file_chooser_delegate_get_quark ()));
694 retval = _ctk_file_chooser_add_shortcut_folder (delegate, file, error);
695
696 if (retval)
697 {
698 CtkFileChooserButton *button = CTK_FILE_CHOOSER_BUTTON (chooser)((((CtkFileChooserButton*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((chooser)), ((ctk_file_chooser_button_get_type
()))))))
;
699 CtkFileChooserButtonPrivate *priv = button->priv;
700 CtkTreeIter iter;
701 gint pos;
702
703 pos = model_get_type_position (button, ROW_TYPE_SHORTCUT);
704 pos += priv->n_shortcuts;
705
706 ctk_list_store_insert (CTK_LIST_STORE (priv->model)((((CtkListStore*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((priv->model)), ((ctk_list_store_get_type ()))))))
, &iter, pos);
707 ctk_list_store_set (CTK_LIST_STORE (priv->model)((((CtkListStore*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((priv->model)), ((ctk_list_store_get_type ()))))))
, &iter,
708 ICON_COLUMN, NULL((void*)0),
709 DISPLAY_NAME_COLUMN, _(FALLBACK_DISPLAY_NAME)((char *) g_dgettext ("ctk30", ("(None)"))),
710 TYPE_COLUMN, ROW_TYPE_SHORTCUT,
711 DATA_COLUMN, g_object_ref (file)((__typeof__ (file)) (g_object_ref) (file)),
712 IS_FOLDER_COLUMN, FALSE(0),
713 -1);
714 set_info_for_file_at_iter (button, file, &iter);
715 priv->n_shortcuts++;
716
717 ctk_tree_model_filter_refilter (CTK_TREE_MODEL_FILTER (priv->filter_model)((((CtkTreeModelFilter*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((priv->filter_model)), ((ctk_tree_model_filter_get_type
()))))))
);
718 }
719
720 return retval;
721}
722
723static gboolean
724ctk_file_chooser_button_remove_shortcut_folder (CtkFileChooser *chooser,
725 GFile *file,
726 GError **error)
727{
728 CtkFileChooser *delegate;
729 gboolean retval;
730
731 delegate = g_object_get_qdata (G_OBJECT (chooser)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((chooser)), (((GType) ((20) << (2))))))))
,
732 CTK_FILE_CHOOSER_DELEGATE_QUARK(_ctk_file_chooser_delegate_get_quark ()));
733
734 retval = _ctk_file_chooser_remove_shortcut_folder (delegate, file, error);
735
736 if (retval)
737 {
738 CtkFileChooserButton *button = CTK_FILE_CHOOSER_BUTTON (chooser)((((CtkFileChooserButton*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((chooser)), ((ctk_file_chooser_button_get_type
()))))))
;
739 CtkFileChooserButtonPrivate *priv = button->priv;
740 CtkTreeIter iter;
741 gint pos;
742 gchar type;
743
744 pos = model_get_type_position (button, ROW_TYPE_SHORTCUT);
745 ctk_tree_model_iter_nth_child (priv->model, &iter, NULL((void*)0), pos);
746
747 do
748 {
749 gpointer data;
750
751 ctk_tree_model_get (priv->model, &iter,
752 TYPE_COLUMN, &type,
753 DATA_COLUMN, &data,
754 -1);
755
756 if (type == ROW_TYPE_SHORTCUT &&
757 data && g_file_equal (data, file))
758 {
759 model_free_row_data (CTK_FILE_CHOOSER_BUTTON (chooser)((((CtkFileChooserButton*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((chooser)), ((ctk_file_chooser_button_get_type
()))))))
, &iter);
760 ctk_list_store_remove (CTK_LIST_STORE (priv->model)((((CtkListStore*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((priv->model)), ((ctk_list_store_get_type ()))))))
, &iter);
761 priv->n_shortcuts--;
762 ctk_tree_model_filter_refilter (CTK_TREE_MODEL_FILTER (priv->filter_model)((((CtkTreeModelFilter*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((priv->filter_model)), ((ctk_tree_model_filter_get_type
()))))))
);
763 update_combo_box (CTK_FILE_CHOOSER_BUTTON (chooser)((((CtkFileChooserButton*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((chooser)), ((ctk_file_chooser_button_get_type
()))))))
);
764 break;
765 }
766 }
767 while (type == ROW_TYPE_SHORTCUT &&
768 ctk_tree_model_iter_next (priv->model, &iter));
769 }
770
771 return retval;
772}
773
774
775/* ******************* *
776 * GObject Functions *
777 * ******************* */
778
779static void
780ctk_file_chooser_button_constructed (GObject *object)
781{
782 CtkFileChooserButton *button = CTK_FILE_CHOOSER_BUTTON (object)((((CtkFileChooserButton*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((object)), ((ctk_file_chooser_button_get_type
()))))))
;
783 CtkFileChooserButtonPrivate *priv = button->priv;
784 GSList *list;
785
786 G_OBJECT_CLASS (ctk_file_chooser_button_parent_class)((((GObjectClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((ctk_file_chooser_button_parent_class)), (((GType) ((20) <<
(2))))))))
->constructed (object);
787
788 if (!priv->dialog)
789 {
790 priv->native = ctk_file_chooser_native_new (NULL((void*)0),
791 NULL((void*)0),
792 CTK_FILE_CHOOSER_ACTION_OPEN,
793 NULL((void*)0),
794 NULL((void*)0));
795 priv->chooser = CTK_FILE_CHOOSER (priv->native)((((CtkFileChooser*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((priv->native)), ((ctk_file_chooser_get_type ()))))))
;
796 ctk_file_chooser_button_set_title (button, _(DEFAULT_TITLE)((char *) g_dgettext ("ctk30", ("Select a File"))));
797
798 g_signal_connect (priv->native, "response",g_signal_connect_data ((priv->native), ("response"), (((GCallback
) (native_response_cb))), (object), ((void*)0), (GConnectFlags
) 0)
799 G_CALLBACK (native_response_cb), object)g_signal_connect_data ((priv->native), ("response"), (((GCallback
) (native_response_cb))), (object), ((void*)0), (GConnectFlags
) 0)
;
800 }
801 else /* dialog set */
802 {
803 priv->chooser = CTK_FILE_CHOOSER (priv->dialog)((((CtkFileChooser*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((priv->dialog)), ((ctk_file_chooser_get_type ()))))))
;
804
805 if (!ctk_window_get_title (CTK_WINDOW (priv->dialog)((((CtkWindow*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((priv->dialog)), ((ctk_window_get_type ()))))))
))
806 ctk_file_chooser_button_set_title (button, _(DEFAULT_TITLE)((char *) g_dgettext ("ctk30", ("Select a File"))));
807
808 g_signal_connect (priv->dialog, "delete-event",g_signal_connect_data ((priv->dialog), ("delete-event"), (
((GCallback) (dialog_delete_event_cb))), (object), ((void*)0)
, (GConnectFlags) 0)
809 G_CALLBACK (dialog_delete_event_cb), object)g_signal_connect_data ((priv->dialog), ("delete-event"), (
((GCallback) (dialog_delete_event_cb))), (object), ((void*)0)
, (GConnectFlags) 0)
;
810 g_signal_connect (priv->dialog, "response",g_signal_connect_data ((priv->dialog), ("response"), (((GCallback
) (dialog_response_cb))), (object), ((void*)0), (GConnectFlags
) 0)
811 G_CALLBACK (dialog_response_cb), object)g_signal_connect_data ((priv->dialog), ("response"), (((GCallback
) (dialog_response_cb))), (object), ((void*)0), (GConnectFlags
) 0)
;
812
813 g_object_add_weak_pointer (G_OBJECT (priv->dialog)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((priv->dialog)), (((GType) ((20) << (2))))))))
,
814 (gpointer) (&priv->dialog));
815 }
816
817 g_signal_connect (priv->chooser, "notify",g_signal_connect_data ((priv->chooser), ("notify"), (((GCallback
) (chooser_notify_cb))), (object), ((void*)0), (GConnectFlags
) 0)
818 G_CALLBACK (chooser_notify_cb), object)g_signal_connect_data ((priv->chooser), ("notify"), (((GCallback
) (chooser_notify_cb))), (object), ((void*)0), (GConnectFlags
) 0)
;
819
820 /* This is used, instead of the standard delegate, to ensure that signals are only
821 * delegated when the OK button is pressed. */
822 g_object_set_qdata (object, CTK_FILE_CHOOSER_DELEGATE_QUARK(_ctk_file_chooser_delegate_get_quark ()), priv->chooser);
823
824 priv->fs =
825 g_object_ref (_ctk_file_chooser_get_file_system (priv->chooser))((__typeof__ (_ctk_file_chooser_get_file_system (priv->chooser
))) (g_object_ref) (_ctk_file_chooser_get_file_system (priv->
chooser)))
;
826
827 model_add_special (button);
828
829 list = _ctk_file_system_list_volumes (priv->fs);
830 model_add_volumes (button, list);
831 g_slist_free (list);
832
833 list = _ctk_bookmarks_manager_list_bookmarks (priv->bookmarks_manager);
834 model_add_bookmarks (button, list);
835 g_slist_free_full (list, g_object_unref);
836
837 model_add_other (button);
838
839 model_add_empty_selection (button);
840
841 priv->filter_model = ctk_tree_model_filter_new (priv->model, NULL((void*)0));
842 ctk_tree_model_filter_set_visible_func (CTK_TREE_MODEL_FILTER (priv->filter_model)((((CtkTreeModelFilter*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((priv->filter_model)), ((ctk_tree_model_filter_get_type
()))))))
,
843 filter_model_visible_func,
844 object, NULL((void*)0));
845
846 ctk_combo_box_set_model (CTK_COMBO_BOX (priv->combo_box)((((CtkComboBox*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((priv->combo_box)), ((ctk_combo_box_get_type ()))))))
, priv->filter_model);
847 ctk_combo_box_set_row_separator_func (CTK_COMBO_BOX (priv->combo_box)((((CtkComboBox*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((priv->combo_box)), ((ctk_combo_box_get_type ()))))))
,
848 combo_box_row_separator_func,
849 NULL((void*)0), NULL((void*)0));
850
851 /* set up the action for a user-provided dialog, this also updates
852 * the label, image and combobox
853 */
854 g_object_set (object,
855 "action", ctk_file_chooser_get_action (CTK_FILE_CHOOSER (priv->chooser)((((CtkFileChooser*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((priv->chooser)), ((ctk_file_chooser_get_type ()))))))
),
856 NULL((void*)0));
857
858 priv->fs_volumes_changed_id =
859 g_signal_connect (priv->fs, "volumes-changed",g_signal_connect_data ((priv->fs), ("volumes-changed"), ((
(GCallback) (fs_volumes_changed_cb))), (object), ((void*)0), (
GConnectFlags) 0)
860 G_CALLBACK (fs_volumes_changed_cb), object)g_signal_connect_data ((priv->fs), ("volumes-changed"), ((
(GCallback) (fs_volumes_changed_cb))), (object), ((void*)0), (
GConnectFlags) 0)
;
861
862 update_label_and_image (button);
863 update_combo_box (button);
864}
865
866static void
867ctk_file_chooser_button_set_property (GObject *object,
868 guint param_id,
869 const GValue *value,
870 GParamSpec *pspec)
871{
872 CtkFileChooserButton *button = CTK_FILE_CHOOSER_BUTTON (object)((((CtkFileChooserButton*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((object)), ((ctk_file_chooser_button_get_type
()))))))
;
873 CtkFileChooserButtonPrivate *priv = button->priv;
874
875 switch (param_id)
876 {
877 case PROP_DIALOG:
878 /* Construct-only */
879 priv->dialog = g_value_get_object (value);
880 break;
881 case PROP_WIDTH_CHARS:
882 ctk_file_chooser_button_set_width_chars (CTK_FILE_CHOOSER_BUTTON (object)((((CtkFileChooserButton*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((object)), ((ctk_file_chooser_button_get_type
()))))))
,
883 g_value_get_int (value));
884 break;
885 case CTK_FILE_CHOOSER_PROP_ACTION:
886 switch (g_value_get_enum (value))
887 {
888 case CTK_FILE_CHOOSER_ACTION_CREATE_FOLDER:
889 case CTK_FILE_CHOOSER_ACTION_SAVE:
890 {
891 GEnumClass *eclass;
892 GEnumValue *eval;
893
894 eclass = g_type_class_peek (CTK_TYPE_FILE_CHOOSER_ACTION(ctk_file_chooser_action_get_type ()));
895 eval = g_enum_get_value (eclass, g_value_get_enum (value));
896 g_warning ("%s: Choosers of type '%s' do not support '%s'.",
897 G_STRFUNC((const char*) (__func__)), G_OBJECT_TYPE_NAME (object)(g_type_name ((((((GTypeClass*) (((GTypeInstance*) (object))->
g_class))->g_type)))))
, eval->value_name);
898
899 g_value_set_enum ((GValue *) value, CTK_FILE_CHOOSER_ACTION_OPEN);
900 }
901 break;
902 }
903
904 g_object_set_property (G_OBJECT (priv->chooser)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((priv->chooser)), (((GType) ((20) << (2))))))))
, pspec->name, value);
905 update_label_and_image (CTK_FILE_CHOOSER_BUTTON (object)((((CtkFileChooserButton*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((object)), ((ctk_file_chooser_button_get_type
()))))))
);
906 update_combo_box (CTK_FILE_CHOOSER_BUTTON (object)((((CtkFileChooserButton*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((object)), ((ctk_file_chooser_button_get_type
()))))))
);
907
908 switch (g_value_get_enum (value))
909 {
910 case CTK_FILE_CHOOSER_ACTION_OPEN:
911 ctk_widget_hide (priv->combo_box);
912 ctk_widget_show (priv->button);
913 break;
914 case CTK_FILE_CHOOSER_ACTION_SELECT_FOLDER:
915 ctk_widget_hide (priv->button);
916 ctk_widget_show (priv->combo_box);
917 break;
918 default:
919 g_assert_not_reached ()do { g_assertion_message_expr ("Ctk", "ctkfilechooserbutton.c"
, 919, ((const char*) (__func__)), ((void*)0)); } while (0)
;
920 break;
921 }
922 break;
923
924 case PROP_TITLE:
925 case CTK_FILE_CHOOSER_PROP_FILTER:
926 case CTK_FILE_CHOOSER_PROP_PREVIEW_WIDGET:
927 case CTK_FILE_CHOOSER_PROP_PREVIEW_WIDGET_ACTIVE:
928 case CTK_FILE_CHOOSER_PROP_USE_PREVIEW_LABEL:
929 case CTK_FILE_CHOOSER_PROP_EXTRA_WIDGET:
930 case CTK_FILE_CHOOSER_PROP_SHOW_HIDDEN:
931 case CTK_FILE_CHOOSER_PROP_DO_OVERWRITE_CONFIRMATION:
932 case CTK_FILE_CHOOSER_PROP_CREATE_FOLDERS:
933 g_object_set_property (G_OBJECT (priv->chooser)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((priv->chooser)), (((GType) ((20) << (2))))))))
, pspec->name, value);
934 break;
935
936 case CTK_FILE_CHOOSER_PROP_LOCAL_ONLY:
937 g_object_set_property (G_OBJECT (priv->chooser)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((priv->chooser)), (((GType) ((20) << (2))))))))
, pspec->name, value);
938 fs_volumes_changed_cb (priv->fs, button);
939 bookmarks_changed_cb (button);
940 break;
941
942 case CTK_FILE_CHOOSER_PROP_SELECT_MULTIPLE:
943 g_warning ("%s: Choosers of type '%s' do not support selecting multiple files.",
944 G_STRFUNC((const char*) (__func__)), G_OBJECT_TYPE_NAME (object)(g_type_name ((((((GTypeClass*) (((GTypeInstance*) (object))->
g_class))->g_type)))))
);
945 break;
946 default:
947 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec)do { GObject *_glib__object = (GObject*) ((object)); GParamSpec
*_glib__pspec = (GParamSpec*) ((pspec)); guint _glib__property_id
= ((param_id)); g_warning ("%s:%d: invalid %s id %u for \"%s\" of type '%s' in '%s'"
, "ctkfilechooserbutton.c", 947, ("property"), _glib__property_id
, _glib__pspec->name, g_type_name ((((((GTypeClass*) (((GTypeInstance
*) (_glib__pspec))->g_class))->g_type)))), (g_type_name
((((((GTypeClass*) (((GTypeInstance*) (_glib__object))->g_class
))->g_type)))))); } while (0)
;
948 break;
949 }
950}
951
952static void
953ctk_file_chooser_button_get_property (GObject *object,
954 guint param_id,
955 GValue *value,
956 GParamSpec *pspec)
957{
958 CtkFileChooserButton *button = CTK_FILE_CHOOSER_BUTTON (object)((((CtkFileChooserButton*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((object)), ((ctk_file_chooser_button_get_type
()))))))
;
959 CtkFileChooserButtonPrivate *priv = button->priv;
960
961 switch (param_id)
962 {
963 case PROP_WIDTH_CHARS:
964 g_value_set_int (value,
965 ctk_label_get_width_chars (CTK_LABEL (priv->label)((((CtkLabel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((priv->label)), ((ctk_label_get_type ()))))))
));
966 break;
967
968 case PROP_TITLE:
969 case CTK_FILE_CHOOSER_PROP_ACTION:
970 case CTK_FILE_CHOOSER_PROP_FILTER:
971 case CTK_FILE_CHOOSER_PROP_LOCAL_ONLY:
972 case CTK_FILE_CHOOSER_PROP_PREVIEW_WIDGET:
973 case CTK_FILE_CHOOSER_PROP_PREVIEW_WIDGET_ACTIVE:
974 case CTK_FILE_CHOOSER_PROP_USE_PREVIEW_LABEL:
975 case CTK_FILE_CHOOSER_PROP_EXTRA_WIDGET:
976 case CTK_FILE_CHOOSER_PROP_SELECT_MULTIPLE:
977 case CTK_FILE_CHOOSER_PROP_SHOW_HIDDEN:
978 case CTK_FILE_CHOOSER_PROP_DO_OVERWRITE_CONFIRMATION:
979 case CTK_FILE_CHOOSER_PROP_CREATE_FOLDERS:
980 g_object_get_property (G_OBJECT (priv->chooser)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((priv->chooser)), (((GType) ((20) << (2))))))))
, pspec->name, value);
981 break;
982
983 default:
984 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec)do { GObject *_glib__object = (GObject*) ((object)); GParamSpec
*_glib__pspec = (GParamSpec*) ((pspec)); guint _glib__property_id
= ((param_id)); g_warning ("%s:%d: invalid %s id %u for \"%s\" of type '%s' in '%s'"
, "ctkfilechooserbutton.c", 984, ("property"), _glib__property_id
, _glib__pspec->name, g_type_name ((((((GTypeClass*) (((GTypeInstance
*) (_glib__pspec))->g_class))->g_type)))), (g_type_name
((((((GTypeClass*) (((GTypeInstance*) (_glib__object))->g_class
))->g_type)))))); } while (0)
;
985 break;
986 }
987}
988
989static void
990ctk_file_chooser_button_finalize (GObject *object)
991{
992 CtkFileChooserButton *button = CTK_FILE_CHOOSER_BUTTON (object)((((CtkFileChooserButton*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((object)), ((ctk_file_chooser_button_get_type
()))))))
;
993 CtkFileChooserButtonPrivate *priv = button->priv;
994
995 if (priv->selection_while_inactive)
996 g_object_unref (priv->selection_while_inactive);
997
998 if (priv->current_folder_while_inactive)
999 g_object_unref (priv->current_folder_while_inactive);
1000
1001 if (priv->model)
1002 {
1003 model_remove_rows (button, 0, ctk_tree_model_iter_n_children (priv->model, NULL((void*)0)));
1004 g_object_unref (priv->model);
1005 }
1006
1007 G_OBJECT_CLASS (ctk_file_chooser_button_parent_class)((((GObjectClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((ctk_file_chooser_button_parent_class)), (((GType) ((20) <<
(2))))))))
->finalize (object);
1008}
1009
1010/* ********************* *
1011 * CtkWidget Functions *
1012 * ********************* */
1013
1014static void
1015ctk_file_chooser_button_state_flags_changed (CtkWidget *widget,
1016 CtkStateFlags previous_state)
1017{
1018 CtkFileChooserButton *button = CTK_FILE_CHOOSER_BUTTON (widget)((((CtkFileChooserButton*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((widget)), ((ctk_file_chooser_button_get_type
()))))))
;
1019 CtkFileChooserButtonPrivate *priv = button->priv;
1020 CtkWidget *child;
1021
1022 if (ctk_widget_get_visible (priv->button))
1023 child = priv->button;
1024 else
1025 child = priv->combo_box;
1026
1027 if (ctk_widget_get_state_flags (widget) & CTK_STATE_FLAG_DROP_ACTIVE)
1028 ctk_widget_set_state_flags (child, CTK_STATE_FLAG_DROP_ACTIVE, FALSE(0));
1029 else
1030 ctk_widget_unset_state_flags (child, CTK_STATE_FLAG_DROP_ACTIVE);
1031
1032 CTK_WIDGET_CLASS (ctk_file_chooser_button_parent_class)((((CtkWidgetClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((ctk_file_chooser_button_parent_class)), ((ctk_widget_get_type
()))))))
->state_flags_changed (widget, previous_state);
1033}
1034
1035static void
1036ctk_file_chooser_button_destroy (CtkWidget *widget)
1037{
1038 CtkFileChooserButton *button = CTK_FILE_CHOOSER_BUTTON (widget)((((CtkFileChooserButton*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((widget)), ((ctk_file_chooser_button_get_type
()))))))
;
1039 CtkFileChooserButtonPrivate *priv = button->priv;
1040 CtkTreeIter iter;
1041 GSList *l;
1042
1043 if (priv->dialog != NULL((void*)0))
1044 {
1045 ctk_widget_destroy (priv->dialog);
1046 priv->dialog = NULL((void*)0);
1047 }
1048
1049 if (priv->native)
1050 {
1051 ctk_native_dialog_destroy (CTK_NATIVE_DIALOG (priv->native));
1052 g_clear_object (&priv->native)do { _Static_assert (sizeof *((&priv->native)) == sizeof
(gpointer), "Expression evaluates to false"); __typeof__ (((
&priv->native))) _pp = ((&priv->native)); __typeof__
(*((&priv->native))) _ptr = *_pp; *_pp = ((void*)0); if
(_ptr) (g_object_unref) (_ptr); } while (0)
;
1053 }
1054
1055 priv->chooser = NULL((void*)0);
1056
1057 if (priv->model && ctk_tree_model_get_iter_first (priv->model, &iter))
1058 {
1059 do
1060 model_free_row_data (button, &iter);
1061 while (ctk_tree_model_iter_next (priv->model, &iter));
1062 }
1063
1064 if (priv->dnd_select_folder_cancellable)
1065 {
1066 g_cancellable_cancel (priv->dnd_select_folder_cancellable);
1067 priv->dnd_select_folder_cancellable = NULL((void*)0);
1068 }
1069
1070 if (priv->update_button_cancellable)
1071 {
1072 g_cancellable_cancel (priv->update_button_cancellable);
1073 priv->update_button_cancellable = NULL((void*)0);
1074 }
1075
1076 if (priv->change_icon_theme_cancellables)
1077 {
1078 for (l = priv->change_icon_theme_cancellables; l; l = l->next)
1079 {
1080 GCancellable *cancellable = G_CANCELLABLE (l->data)((((GCancellable*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((l->data)), ((g_cancellable_get_type ()))))))
;
1081 g_cancellable_cancel (cancellable);
1082 }
1083 g_slist_free (priv->change_icon_theme_cancellables);
1084 priv->change_icon_theme_cancellables = NULL((void*)0);
1085 }
1086
1087 if (priv->filter_model)
1088 {
1089 g_object_unref (priv->filter_model);
1090 priv->filter_model = NULL((void*)0);
1091 }
1092
1093 if (priv->fs)
1094 {
1095 g_signal_handler_disconnect (priv->fs, priv->fs_volumes_changed_id);
1096 g_object_unref (priv->fs);
1097 priv->fs = NULL((void*)0);
1098 }
1099
1100 if (priv->bookmarks_manager)
1101 {
1102 _ctk_bookmarks_manager_free (priv->bookmarks_manager);
1103 priv->bookmarks_manager = NULL((void*)0);
1104 }
1105
1106 CTK_WIDGET_CLASS (ctk_file_chooser_button_parent_class)((((CtkWidgetClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((ctk_file_chooser_button_parent_class)), ((ctk_widget_get_type
()))))))
->destroy (widget);
1107}
1108
1109struct DndSelectFolderData
1110{
1111 CtkFileSystem *file_system;
1112 CtkFileChooserButton *button;
1113 CtkFileChooserAction action;
1114 GFile *file;
1115 gchar **uris;
1116 guint i;
1117 gboolean selected;
1118};
1119
1120static void
1121dnd_select_folder_get_info_cb (GCancellable *cancellable,
1122 GFileInfo *info,
1123 const GError *error,
1124 gpointer user_data)
1125{
1126 gboolean cancelled = g_cancellable_is_cancelled (cancellable);
1127 struct DndSelectFolderData *data = user_data;
1128
1129 if (cancellable != data->button->priv->dnd_select_folder_cancellable)
1130 {
1131 g_object_unref (data->button);
1132 g_object_unref (data->file);
1133 g_strfreev (data->uris);
1134 g_free (data);
1135
1136 g_object_unref (cancellable);
1137 return;
1138 }
1139
1140 data->button->priv->dnd_select_folder_cancellable = NULL((void*)0);
1141
1142 if (!cancelled && !error && info != NULL((void*)0))
1143 {
1144 gboolean is_folder;
1145
1146 is_folder = _ctk_file_info_consider_as_directory (info);
1147
1148 data->selected =
1149 (((data->action == CTK_FILE_CHOOSER_ACTION_SELECT_FOLDER && is_folder) ||
1150 (data->action == CTK_FILE_CHOOSER_ACTION_OPEN && !is_folder)) &&
1151 ctk_file_chooser_select_file (CTK_FILE_CHOOSER (data->button)((((CtkFileChooser*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((data->button)), ((ctk_file_chooser_get_type ()))))))
, data->file, NULL((void*)0)));
1152 }
1153 else
1154 data->selected = FALSE(0);
1155
1156 if (data->selected || data->uris[++data->i] == NULL((void*)0))
1157 {
1158 g_signal_emit (data->button, file_chooser_button_signals[FILE_SET], 0);
1159
1160 g_object_unref (data->button);
1161 g_object_unref (data->file);
1162 g_strfreev (data->uris);
1163 g_free (data);
1164
1165 g_object_unref (cancellable);
1166 return;
1167 }
1168
1169 if (data->file)
1170 g_object_unref (data->file);
1171
1172 data->file = g_file_new_for_uri (data->uris[data->i]);
1173
1174 data->button->priv->dnd_select_folder_cancellable =
1175 _ctk_file_system_get_info (data->file_system, data->file,
1176 "standard::type",
1177 dnd_select_folder_get_info_cb, user_data);
1178
1179 g_object_unref (cancellable);
1180}
1181
1182static void
1183ctk_file_chooser_button_drag_data_received (CtkWidget *widget,
1184 CdkDragContext *context,
1185 gint x,
1186 gint y,
1187 CtkSelectionData *data,
1188 guint type,
1189 guint drag_time)
1190{
1191 CtkFileChooserButton *button = CTK_FILE_CHOOSER_BUTTON (widget)((((CtkFileChooserButton*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((widget)), ((ctk_file_chooser_button_get_type
()))))))
;
1192 CtkFileChooserButtonPrivate *priv = button->priv;
1193 GFile *file;
1194 gchar *text;
1195
1196 if (CTK_WIDGET_CLASS (ctk_file_chooser_button_parent_class)((((CtkWidgetClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((ctk_file_chooser_button_parent_class)), ((ctk_widget_get_type
()))))))
->drag_data_received != NULL((void*)0))
1197 CTK_WIDGET_CLASS (ctk_file_chooser_button_parent_class)((((CtkWidgetClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((ctk_file_chooser_button_parent_class)), ((ctk_widget_get_type
()))))))
->drag_data_received (widget,
1198 context,
1199 x, y,
1200 data, type,
1201 drag_time);
1202
1203 if (widget == NULL((void*)0) || context == NULL((void*)0) || data == NULL((void*)0) || ctk_selection_data_get_length (data) < 0)
1204 return;
1205
1206 switch (type)
1207 {
1208 case TEXT_URI_LIST:
1209 {
1210 gchar **uris;
1211 struct DndSelectFolderData *info;
1212
1213 uris = ctk_selection_data_get_uris (data);
1214
1215 if (uris == NULL((void*)0))
1216 break;
1217
1218 info = g_new0 (struct DndSelectFolderData, 1)((struct DndSelectFolderData *) g_malloc0_n ((1), sizeof (struct
DndSelectFolderData)))
;
1219 info->button = g_object_ref (button)((__typeof__ (button)) (g_object_ref) (button));
1220 info->i = 0;
1221 info->uris = uris;
1222 info->selected = FALSE(0);
1223 info->file_system = priv->fs;
1224 g_object_get (priv->chooser, "action", &info->action, NULL((void*)0));
1225
1226 info->file = g_file_new_for_uri (info->uris[info->i]);
1227
1228 if (priv->dnd_select_folder_cancellable)
1229 g_cancellable_cancel (priv->dnd_select_folder_cancellable);
1230
1231 priv->dnd_select_folder_cancellable =
1232 _ctk_file_system_get_info (priv->fs, info->file,
1233 "standard::type",
1234 dnd_select_folder_get_info_cb, info);
1235 }
1236 break;
1237
1238 case TEXT_PLAIN:
1239 text = (char*) ctk_selection_data_get_text (data);
1240 file = g_file_new_for_uri (text);
1241 ctk_file_chooser_select_file (CTK_FILE_CHOOSER (priv->chooser)((((CtkFileChooser*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((priv->chooser)), ((ctk_file_chooser_get_type ()))))))
, file, NULL((void*)0));
1242 g_object_unref (file);
1243 g_free (text);
1244 g_signal_emit (button, file_chooser_button_signals[FILE_SET], 0);
1245 break;
1246
1247 default:
1248 break;
1249 }
1250
1251 ctk_drag_finish (context, TRUE(!(0)), FALSE(0), drag_time);
1252}
1253
1254static void
1255ctk_file_chooser_button_show_all (CtkWidget *widget)
1256{
1257 ctk_widget_show (widget);
1258}
1259
1260static void
1261ctk_file_chooser_button_show (CtkWidget *widget)
1262{
1263 CtkFileChooserButton *button = CTK_FILE_CHOOSER_BUTTON (widget)((((CtkFileChooserButton*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((widget)), ((ctk_file_chooser_button_get_type
()))))))
;
1264 CtkFileChooserButtonPrivate *priv = button->priv;
1265
1266 if (CTK_WIDGET_CLASS (ctk_file_chooser_button_parent_class)((((CtkWidgetClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((ctk_file_chooser_button_parent_class)), ((ctk_widget_get_type
()))))))
->show)
1267 CTK_WIDGET_CLASS (ctk_file_chooser_button_parent_class)((((CtkWidgetClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((ctk_file_chooser_button_parent_class)), ((ctk_widget_get_type
()))))))
->show (widget);
1268
1269 if (priv->active)
1270 open_dialog (CTK_FILE_CHOOSER_BUTTON (widget)((((CtkFileChooserButton*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((widget)), ((ctk_file_chooser_button_get_type
()))))))
);
1271}
1272
1273static void
1274ctk_file_chooser_button_hide (CtkWidget *widget)
1275{
1276 CtkFileChooserButton *button = CTK_FILE_CHOOSER_BUTTON (widget)((((CtkFileChooserButton*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((widget)), ((ctk_file_chooser_button_get_type
()))))))
;
1277 CtkFileChooserButtonPrivate *priv = button->priv;
1278
1279 if (priv->dialog)
1280 ctk_widget_hide (priv->dialog);
1281 else
1282 ctk_native_dialog_hide (CTK_NATIVE_DIALOG (priv->native));
1283
1284 if (CTK_WIDGET_CLASS (ctk_file_chooser_button_parent_class)((((CtkWidgetClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((ctk_file_chooser_button_parent_class)), ((ctk_widget_get_type
()))))))
->hide)
1285 CTK_WIDGET_CLASS (ctk_file_chooser_button_parent_class)((((CtkWidgetClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((ctk_file_chooser_button_parent_class)), ((ctk_widget_get_type
()))))))
->hide (widget);
1286}
1287
1288static void
1289ctk_file_chooser_button_map (CtkWidget *widget)
1290{
1291 CTK_WIDGET_CLASS (ctk_file_chooser_button_parent_class)((((CtkWidgetClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((ctk_file_chooser_button_parent_class)), ((ctk_widget_get_type
()))))))
->map (widget);
1292}
1293
1294static gboolean
1295ctk_file_chooser_button_mnemonic_activate (CtkWidget *widget,
1296 gboolean group_cycling)
1297{
1298 CtkFileChooserButton *button = CTK_FILE_CHOOSER_BUTTON (widget)((((CtkFileChooserButton*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((widget)), ((ctk_file_chooser_button_get_type
()))))))
;
1299 CtkFileChooserButtonPrivate *priv = button->priv;
1300
1301 switch (ctk_file_chooser_get_action (CTK_FILE_CHOOSER (priv->chooser)((((CtkFileChooser*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((priv->chooser)), ((ctk_file_chooser_get_type ()))))))
))
1302 {
1303 case CTK_FILE_CHOOSER_ACTION_OPEN:
1304 ctk_widget_grab_focus (priv->button);
1305 break;
1306 case CTK_FILE_CHOOSER_ACTION_SELECT_FOLDER:
1307 return ctk_widget_mnemonic_activate (priv->combo_box, group_cycling);
1308 break;
This statement is never executed
1309 default:
1310 g_assert_not_reached ()do { g_assertion_message_expr ("Ctk", "ctkfilechooserbutton.c"
, 1310, ((const char*) (__func__)), ((void*)0)); } while (0)
;
1311 break;
1312 }
1313
1314 return TRUE(!(0));
1315}
1316
1317/* Changes the icons wherever it is needed */
1318struct ChangeIconThemeData
1319{
1320 CtkFileChooserButton *button;
1321 CtkTreeRowReference *row_ref;
1322};
1323
1324static void
1325change_icon_theme_get_info_cb (GCancellable *cancellable,
1326 GFileInfo *info,
1327 const GError *error,
1328 gpointer user_data)
1329{
1330 gboolean cancelled = g_cancellable_is_cancelled (cancellable);
1331 cairo_surface_t *surface;
1332 struct ChangeIconThemeData *data = user_data;
1333
1334 if (!g_slist_find (data->button->priv->change_icon_theme_cancellables, cancellable))
1335 goto out;
1336
1337 data->button->priv->change_icon_theme_cancellables =
1338 g_slist_remove (data->button->priv->change_icon_theme_cancellables, cancellable);
1339
1340 if (cancelled || error)
1341 goto out;
1342
1343 surface = _ctk_file_info_render_icon (info, CTK_WIDGET (data->button)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((data->button)), ((ctk_widget_get_type ()))))))
, data->button->priv->icon_size);
1344
1345 if (surface)
1346 {
1347 gint width = 0;
1348 CtkTreeIter iter;
1349 CtkTreePath *path;
1350
1351 width = MAX (width, data->button->priv->icon_size)(((width) > (data->button->priv->icon_size)) ? (width
) : (data->button->priv->icon_size))
;
1352
1353 path = ctk_tree_row_reference_get_path (data->row_ref);
1354 if (path)
1355 {
1356 ctk_tree_model_get_iter (data->button->priv->model, &iter, path);
1357 ctk_tree_path_free (path);
1358
1359 ctk_list_store_set (CTK_LIST_STORE (data->button->priv->model)((((CtkListStore*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((data->button->priv->model)), ((ctk_list_store_get_type
()))))))
, &iter,
1360 ICON_COLUMN, surface,
1361 -1);
1362
1363 g_object_set (data->button->priv->icon_cell,
1364 "width", width,
1365 NULL((void*)0));
1366 }
1367 cairo_surface_destroy (surface);
1368 }
1369
1370out:
1371 g_object_unref (data->button);
1372 ctk_tree_row_reference_free (data->row_ref);
1373 g_free (data);
1374
1375 g_object_unref (cancellable);
1376}
1377
1378static void
1379change_icon_theme (CtkFileChooserButton *button)
1380{
1381 CtkFileChooserButtonPrivate *priv = button->priv;
1382 CtkIconTheme *theme;
1383 CtkTreeIter iter;
1384 GSList *l;
1385 gint width = 0, height = 0;
1386
1387 for (l = button->priv->change_icon_theme_cancellables; l; l = l->next)
1388 {
1389 GCancellable *cancellable = G_CANCELLABLE (l->data)((((GCancellable*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((l->data)), ((g_cancellable_get_type ()))))))
;
1390 g_cancellable_cancel (cancellable);
1391 }
1392 g_slist_free (button->priv->change_icon_theme_cancellables);
1393 button->priv->change_icon_theme_cancellables = NULL((void*)0);
1394
1395 if (ctk_icon_size_lookup (CTK_ICON_SIZE_MENU, &width, &height))
1396 priv->icon_size = MAX (width, height)(((width) > (height)) ? (width) : (height));
1397 else
1398 priv->icon_size = FALLBACK_ICON_SIZE16;
1399
1400 update_label_and_image (button);
1401
1402 ctk_tree_model_get_iter_first (priv->model, &iter);
1403
1404 theme = get_icon_theme (CTK_WIDGET (button)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((button)), ((ctk_widget_get_type ()))))))
);
1405
1406 do
1407 {
1408 cairo_surface_t *surface = NULL((void*)0);
1409 gchar type;
1410 gpointer data;
1411
1412 type = ROW_TYPE_INVALID;
1413 ctk_tree_model_get (priv->model, &iter,
1414 TYPE_COLUMN, &type,
1415 DATA_COLUMN, &data,
1416 -1);
1417
1418 switch (type)
1419 {
1420 case ROW_TYPE_SPECIAL:
1421 case ROW_TYPE_SHORTCUT:
1422 case ROW_TYPE_BOOKMARK:
1423 case ROW_TYPE_CURRENT_FOLDER:
1424 if (data)
1425 {
1426 if (g_file_is_native (G_FILE (data)((((GFile*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((data)), ((g_file_get_type ()))))))
))
1427 {
1428 CtkTreePath *path;
1429 GCancellable *cancellable;
1430 struct ChangeIconThemeData *info;
1431
1432 info = g_new0 (struct ChangeIconThemeData, 1)((struct ChangeIconThemeData *) g_malloc0_n ((1), sizeof (struct
ChangeIconThemeData)))
;
1433 info->button = g_object_ref (button)((__typeof__ (button)) (g_object_ref) (button));
1434 path = ctk_tree_model_get_path (priv->model, &iter);
1435 info->row_ref = ctk_tree_row_reference_new (priv->model, path);
1436 ctk_tree_path_free (path);
1437
1438 cancellable =
1439 _ctk_file_system_get_info (priv->fs, data,
1440 "standard::icon",
1441 change_icon_theme_get_info_cb,
1442 info);
1443 button->priv->change_icon_theme_cancellables =
1444 g_slist_append (button->priv->change_icon_theme_cancellables, cancellable);
1445 surface = NULL((void*)0);
1446 }
1447 else
1448 {
1449 /* Don't call get_info for remote paths to avoid latency and
1450 * auth dialogs.
1451 * If we switch to a better bookmarks file format (XBEL), we
1452 * should use mime info to get a better icon.
1453 */
1454 surface = ctk_icon_theme_load_surface (theme, "folder-remote",
1455 priv->icon_size,
1456 ctk_widget_get_scale_factor (CTK_WIDGET (button)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((button)), ((ctk_widget_get_type ()))))))
),
1457 ctk_widget_get_window (CTK_WIDGET (button)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((button)), ((ctk_widget_get_type ()))))))
),
1458 0, NULL((void*)0));
1459 }
1460 }
1461 break;
1462 case ROW_TYPE_VOLUME:
1463 if (data)
1464 {
1465 surface = _ctk_file_system_volume_render_icon (data,
1466 CTK_WIDGET (button)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((button)), ((ctk_widget_get_type ()))))))
,
1467 priv->icon_size,
1468 NULL((void*)0));
1469 }
1470
1471 break;
1472 default:
1473 continue;
1474 break;
1475 }
1476
1477 if (surface)
1478 width = MAX (width, priv->icon_size)(((width) > (priv->icon_size)) ? (width) : (priv->icon_size
))
;
1479
1480 ctk_list_store_set (CTK_LIST_STORE (priv->model)((((CtkListStore*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((priv->model)), ((ctk_list_store_get_type ()))))))
, &iter,
1481 ICON_COLUMN, surface,
1482 -1);
1483
1484 if (surface)
1485 cairo_surface_destroy (surface);
1486 }
1487 while (ctk_tree_model_iter_next (priv->model, &iter));
1488
1489 g_object_set (button->priv->icon_cell,
1490 "width", width,
1491 NULL((void*)0));
1492}
1493
1494static void
1495ctk_file_chooser_button_style_updated (CtkWidget *widget)
1496{
1497 CTK_WIDGET_CLASS (ctk_file_chooser_button_parent_class)((((CtkWidgetClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((ctk_file_chooser_button_parent_class)), ((ctk_widget_get_type
()))))))
->style_updated (widget);
1498
1499 if (ctk_widget_has_screen (widget))
1500 {
1501 /* We need to update the icon surface, but only in case
1502 * the icon theme really changed. */
1503 CtkStyleContext *context = ctk_widget_get_style_context (widget);
1504 CtkCssStyleChange *change = ctk_style_context_get_change (context);
1505 if (!change || ctk_css_style_change_changes_property (change, CTK_CSS_PROPERTY_ICON_THEME))
1506 change_icon_theme (CTK_FILE_CHOOSER_BUTTON (widget)((((CtkFileChooserButton*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((widget)), ((ctk_file_chooser_button_get_type
()))))))
);
1507 }
1508}
1509
1510static void
1511ctk_file_chooser_button_screen_changed (CtkWidget *widget,
1512 CdkScreen *old_screen)
1513{
1514 if (CTK_WIDGET_CLASS (ctk_file_chooser_button_parent_class)((((CtkWidgetClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((ctk_file_chooser_button_parent_class)), ((ctk_widget_get_type
()))))))
->screen_changed)
1515 CTK_WIDGET_CLASS (ctk_file_chooser_button_parent_class)((((CtkWidgetClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((ctk_file_chooser_button_parent_class)), ((ctk_widget_get_type
()))))))
->screen_changed (widget,
1516 old_screen);
1517
1518 change_icon_theme (CTK_FILE_CHOOSER_BUTTON (widget)((((CtkFileChooserButton*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((widget)), ((ctk_file_chooser_button_get_type
()))))))
);
1519}
1520
1521
1522/* ******************* *
1523 * Utility Functions *
1524 * ******************* */
1525
1526/* General */
1527static CtkIconTheme *
1528get_icon_theme (CtkWidget *widget)
1529{
1530 return ctk_css_icon_theme_value_get_icon_theme
1531 (_ctk_style_context_peek_property (ctk_widget_get_style_context (widget), CTK_CSS_PROPERTY_ICON_THEME));
1532}
1533
1534
1535struct SetDisplayNameData
1536{
1537 CtkFileChooserButton *button;
1538 char *label;
1539 CtkTreeRowReference *row_ref;
1540};
1541
1542static void
1543set_info_get_info_cb (GCancellable *cancellable,
1544 GFileInfo *info,
1545 const GError *error,
1546 gpointer callback_data)
1547{
1548 gboolean cancelled = g_cancellable_is_cancelled (cancellable);
1549 cairo_surface_t *surface;
1550 CtkTreePath *path;
1551 CtkTreeIter iter;
1552 GCancellable *model_cancellable = NULL((void*)0);
1553 struct SetDisplayNameData *data = callback_data;
1554 gboolean is_folder;
1555
1556 if (!data->button->priv->model)
1557 /* button got destroyed */
1558 goto out;
1559
1560 path = ctk_tree_row_reference_get_path (data->row_ref);
1561 if (!path)
1562 /* Cancellable doesn't exist anymore in the model */
1563 goto out;
1564
1565 ctk_tree_model_get_iter (data->button->priv->model, &iter, path);
1566 ctk_tree_path_free (path);
1567
1568 /* Validate the cancellable */
1569 ctk_tree_model_get (data->button->priv->model, &iter,
1570 CANCELLABLE_COLUMN, &model_cancellable,
1571 -1);
1572 if (cancellable != model_cancellable)
1573 goto out;
1574
1575 ctk_list_store_set (CTK_LIST_STORE (data->button->priv->model)((((CtkListStore*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((data->button->priv->model)), ((ctk_list_store_get_type
()))))))
, &iter,
1576 CANCELLABLE_COLUMN, NULL((void*)0),
1577 -1);
1578
1579 if (cancelled || error)
1580 /* There was an error, leave the fallback name in there */
1581 goto out;
1582
1583 surface = _ctk_file_info_render_icon (info, CTK_WIDGET (data->button)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((data->button)), ((ctk_widget_get_type ()))))))
, data->button->priv->icon_size);
1584
1585 if (!data->label)
1586 data->label = g_strdup (g_file_info_get_display_name (info))g_strdup_inline (g_file_info_get_display_name (info));
1587
1588 is_folder = _ctk_file_info_consider_as_directory (info);
1589
1590 ctk_list_store_set (CTK_LIST_STORE (data->button->priv->model)((((CtkListStore*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((data->button->priv->model)), ((ctk_list_store_get_type
()))))))
, &iter,
1591 ICON_COLUMN, surface,
1592 DISPLAY_NAME_COLUMN, data->label,
1593 IS_FOLDER_COLUMN, is_folder,
1594 -1);
1595
1596 if (surface)
1597 cairo_surface_destroy (surface);
1598
1599out:
1600 g_object_unref (data->button);
1601 g_free (data->label);
1602 ctk_tree_row_reference_free (data->row_ref);
1603 g_free (data);
1604
1605 g_object_unref (cancellable);
1606}
1607
1608static void
1609set_info_for_file_at_iter (CtkFileChooserButton *button,
1610 GFile *file,
1611 CtkTreeIter *iter)
1612{
1613 struct SetDisplayNameData *data;
1614 CtkTreePath *tree_path;
1615 GCancellable *cancellable;
1616
1617 data = g_new0 (struct SetDisplayNameData, 1)((struct SetDisplayNameData *) g_malloc0_n ((1), sizeof (struct
SetDisplayNameData)))
;
1618 data->button = g_object_ref (button)((__typeof__ (button)) (g_object_ref) (button));
1619 data->label = _ctk_bookmarks_manager_get_bookmark_label (button->priv->bookmarks_manager, file);
1620
1621 tree_path = ctk_tree_model_get_path (button->priv->model, iter);
1622 data->row_ref = ctk_tree_row_reference_new (button->priv->model, tree_path);
1623 ctk_tree_path_free (tree_path);
1624
1625 cancellable = _ctk_file_system_get_info (button->priv->fs, file,
1626 "standard::type,standard::icon,standard::display-name",
1627 set_info_get_info_cb, data);
1628
1629 ctk_list_store_set (CTK_LIST_STORE (button->priv->model)((((CtkListStore*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((button->priv->model)), ((ctk_list_store_get_type (
)))))))
, iter,
1630 CANCELLABLE_COLUMN, cancellable,
1631 -1);
1632}
1633
1634/* Shortcuts Model */
1635static gint
1636model_get_type_position (CtkFileChooserButton *button,
1637 RowType row_type)
1638{
1639 gint retval = 0;
1640
1641 if (row_type == ROW_TYPE_SPECIAL)
1642 return retval;
1643
1644 retval += button->priv->n_special;
1645
1646 if (row_type == ROW_TYPE_VOLUME)
1647 return retval;
1648
1649 retval += button->priv->n_volumes;
1650
1651 if (row_type == ROW_TYPE_SHORTCUT)
1652 return retval;
1653
1654 retval += button->priv->n_shortcuts;
1655
1656 if (row_type == ROW_TYPE_BOOKMARK_SEPARATOR)
1657 return retval;
1658
1659 retval += button->priv->has_bookmark_separator;
1660
1661 if (row_type == ROW_TYPE_BOOKMARK)
1662 return retval;
1663
1664 retval += button->priv->n_bookmarks;
1665
1666 if (row_type == ROW_TYPE_CURRENT_FOLDER_SEPARATOR)
1667 return retval;
1668
1669 retval += button->priv->has_current_folder_separator;
1670
1671 if (row_type == ROW_TYPE_CURRENT_FOLDER)
1672 return retval;
1673
1674 retval += button->priv->has_current_folder;
1675
1676 if (row_type == ROW_TYPE_OTHER_SEPARATOR)
1677 return retval;
1678
1679 retval += button->priv->has_other_separator;
1680
1681 if (row_type == ROW_TYPE_OTHER)
1682 return retval;
1683
1684 retval++;
1685
1686 if (row_type == ROW_TYPE_EMPTY_SELECTION)
1687 return retval;
1688
1689 g_assert_not_reached ()do { g_assertion_message_expr ("Ctk", "ctkfilechooserbutton.c"
, 1689, ((const char*) (__func__)), ((void*)0)); } while (0)
;
1690 return -1;
1691}
1692
1693static void
1694model_free_row_data (CtkFileChooserButton *button,
1695 CtkTreeIter *iter)
1696{
1697 gchar type;
1698 gpointer data;
1699 GCancellable *cancellable;
1700
1701 ctk_tree_model_get (button->priv->model, iter,
1702 TYPE_COLUMN, &type,
1703 DATA_COLUMN, &data,
1704 CANCELLABLE_COLUMN, &cancellable,
1705 -1);
1706
1707 if (cancellable)
1708 g_cancellable_cancel (cancellable);
1709
1710 switch (type)
1711 {
1712 case ROW_TYPE_SPECIAL:
1713 case ROW_TYPE_SHORTCUT:
1714 case ROW_TYPE_BOOKMARK:
1715 case ROW_TYPE_CURRENT_FOLDER:
1716 g_object_unref (data);
1717 break;
1718 case ROW_TYPE_VOLUME:
1719 _ctk_file_system_volume_unref (data);
1720 break;
1721 default:
1722 break;
1723 }
1724}
1725
1726static void
1727model_add_special_get_info_cb (GCancellable *cancellable,
1728 GFileInfo *info,
1729 const GError *error,
1730 gpointer user_data)
1731{
1732 gboolean cancelled = g_cancellable_is_cancelled (cancellable);
1733 CtkTreeIter iter;
1734 CtkTreePath *path;
1735 cairo_surface_t *surface;
1736 GCancellable *model_cancellable = NULL((void*)0);
1737 struct ChangeIconThemeData *data = user_data;
1738 gchar *name;
1739
1740 if (!data->button->priv->model)
1741 /* button got destroyed */
1742 goto out;
1743
1744 path = ctk_tree_row_reference_get_path (data->row_ref);
1745 if (!path)
1746 /* Cancellable doesn't exist anymore in the model */
1747 goto out;
1748
1749 ctk_tree_model_get_iter (data->button->priv->model, &iter, path);
1750 ctk_tree_path_free (path);
1751
1752 ctk_tree_model_get (data->button->priv->model, &iter,
1753 CANCELLABLE_COLUMN, &model_cancellable,
1754 -1);
1755 if (cancellable != model_cancellable)
1756 goto out;
1757
1758 ctk_list_store_set (CTK_LIST_STORE (data->button->priv->model)((((CtkListStore*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((data->button->priv->model)), ((ctk_list_store_get_type
()))))))
, &iter,
1759 CANCELLABLE_COLUMN, NULL((void*)0),
1760 -1);
1761
1762 if (cancelled || error)
1763 goto out;
1764
1765 surface = _ctk_file_info_render_icon (info, CTK_WIDGET (data->button)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((data->button)), ((ctk_widget_get_type ()))))))
, data->button->priv->icon_size);
1766 if (surface)
1767 {
1768 ctk_list_store_set (CTK_LIST_STORE (data->button->priv->model)((((CtkListStore*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((data->button->priv->model)), ((ctk_list_store_get_type
()))))))
, &iter,
1769 ICON_COLUMN, surface,
1770 -1);
1771 cairo_surface_destroy (surface);
1772 }
1773
1774 ctk_tree_model_get (data->button->priv->model, &iter,
1775 DISPLAY_NAME_COLUMN, &name,
1776 -1);
1777 if (!name)
1778 ctk_list_store_set (CTK_LIST_STORE (data->button->priv->model)((((CtkListStore*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((data->button->priv->model)), ((ctk_list_store_get_type
()))))))
, &iter,
1779 DISPLAY_NAME_COLUMN, g_file_info_get_display_name (info),
1780 -1);
1781 g_free (name);
1782
1783out:
1784 g_object_unref (data->button);
1785 ctk_tree_row_reference_free (data->row_ref);
1786 g_free (data);
1787
1788 g_object_unref (cancellable);
1789}
1790
1791static void
1792model_add_special (CtkFileChooserButton *button)
1793{
1794 const gchar *homedir;
1795 const gchar *desktopdir;
1796 CtkListStore *store;
1797 CtkTreeIter iter;
1798 GFile *file;
1799 gint pos;
1800
1801 store = CTK_LIST_STORE (button->priv->model)((((CtkListStore*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((button->priv->model)), ((ctk_list_store_get_type (
)))))))
;
1802 pos = model_get_type_position (button, ROW_TYPE_SPECIAL);
1803
1804 homedir = g_get_home_dir ();
1805
1806 if (homedir)
1807 {
1808 CtkTreePath *tree_path;
1809 GCancellable *cancellable;
1810 struct ChangeIconThemeData *info;
1811
1812 file = g_file_new_for_path (homedir);
1813 ctk_list_store_insert (store, &iter, pos);
1814 pos++;
1815
1816 info = g_new0 (struct ChangeIconThemeData, 1)((struct ChangeIconThemeData *) g_malloc0_n ((1), sizeof (struct
ChangeIconThemeData)))
;
1817 info->button = g_object_ref (button)((__typeof__ (button)) (g_object_ref) (button));
1818 tree_path = ctk_tree_model_get_path (CTK_TREE_MODEL (store)((((CtkTreeModel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((store)), ((ctk_tree_model_get_type ()))))))
, &iter);
1819 info->row_ref = ctk_tree_row_reference_new (CTK_TREE_MODEL (store)((((CtkTreeModel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((store)), ((ctk_tree_model_get_type ()))))))
,
1820 tree_path);
1821 ctk_tree_path_free (tree_path);
1822
1823 cancellable = _ctk_file_system_get_info (button->priv->fs, file,
1824 "standard::icon,standard::display-name",
1825 model_add_special_get_info_cb, info);
1826
1827 ctk_list_store_set (store, &iter,
1828 ICON_COLUMN, NULL((void*)0),
1829 DISPLAY_NAME_COLUMN, NULL((void*)0),
1830 TYPE_COLUMN, ROW_TYPE_SPECIAL,
1831 DATA_COLUMN, file,
1832 IS_FOLDER_COLUMN, TRUE(!(0)),
1833 CANCELLABLE_COLUMN, cancellable,
1834 -1);
1835
1836 button->priv->n_special++;
1837 }
1838
1839 desktopdir = g_get_user_special_dir (G_USER_DIRECTORY_DESKTOP);
1840
1841 /* "To disable a directory, point it to the homedir."
1842 * See http://freedesktop.org/wiki/Software/xdg-user-dirs
1843 */
1844 if (g_strcmp0 (desktopdir, g_get_home_dir ()) != 0)
1845 {
1846 CtkTreePath *tree_path;
1847 GCancellable *cancellable;
1848 struct ChangeIconThemeData *info;
1849
1850 file = g_file_new_for_path (desktopdir);
1851 ctk_list_store_insert (store, &iter, pos);
1852 pos++;
1853
1854 info = g_new0 (struct ChangeIconThemeData, 1)((struct ChangeIconThemeData *) g_malloc0_n ((1), sizeof (struct
ChangeIconThemeData)))
;
1855 info->button = g_object_ref (button)((__typeof__ (button)) (g_object_ref) (button));
1856 tree_path = ctk_tree_model_get_path (CTK_TREE_MODEL (store)((((CtkTreeModel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((store)), ((ctk_tree_model_get_type ()))))))
, &iter);
1857 info->row_ref = ctk_tree_row_reference_new (CTK_TREE_MODEL (store)((((CtkTreeModel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((store)), ((ctk_tree_model_get_type ()))))))
,
1858 tree_path);
1859 ctk_tree_path_free (tree_path);
1860
1861 cancellable = _ctk_file_system_get_info (button->priv->fs, file,
1862 "standard::icon,standard::display-name",
1863 model_add_special_get_info_cb, info);
1864
1865 ctk_list_store_set (store, &iter,
1866 TYPE_COLUMN, ROW_TYPE_SPECIAL,
1867 ICON_COLUMN, NULL((void*)0),
1868 DISPLAY_NAME_COLUMN, _(DESKTOP_DISPLAY_NAME)((char *) g_dgettext ("ctk30", ("Desktop"))),
1869 DATA_COLUMN, file,
1870 IS_FOLDER_COLUMN, TRUE(!(0)),
1871 CANCELLABLE_COLUMN, cancellable,
1872 -1);
1873
1874 button->priv->n_special++;
1875 }
1876}
1877
1878static void
1879model_add_volumes (CtkFileChooserButton *button,
1880 GSList *volumes)
1881{
1882 CtkListStore *store;
1883 gint pos;
1884 gboolean local_only;
1885 GSList *l;
1886
1887 if (!volumes)
1888 return;
1889
1890 store = CTK_LIST_STORE (button->priv->model)((((CtkListStore*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((button->priv->model)), ((ctk_list_store_get_type (
)))))))
;
1891 pos = model_get_type_position (button, ROW_TYPE_VOLUME);
1892 local_only = ctk_file_chooser_get_local_only (CTK_FILE_CHOOSER (button->priv->chooser)((((CtkFileChooser*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((button->priv->chooser)), ((ctk_file_chooser_get_type
()))))))
);
1893
1894 for (l = volumes; l; l = l->next)
1895 {
1896 CtkFileSystemVolume *volume;
1897 CtkTreeIter iter;
1898 cairo_surface_t *surface;
1899 gchar *display_name;
1900
1901 volume = l->data;
1902
1903 if (local_only)
1904 {
1905 if (_ctk_file_system_volume_is_mounted (volume))
1906 {
1907 GFile *base_file;
1908
1909 base_file = _ctk_file_system_volume_get_root (volume);
1910 if (base_file != NULL((void*)0))
1911 {
1912 if (!_ctk_file_has_native_path (base_file))
1913 {
1914 g_object_unref (base_file);
1915 continue;
1916 }
1917 else
1918 g_object_unref (base_file);
1919 }
1920 }
1921 }
1922
1923 surface = _ctk_file_system_volume_render_icon (volume,
1924 CTK_WIDGET (button)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((button)), ((ctk_widget_get_type ()))))))
,
1925 button->priv->icon_size,
1926 NULL((void*)0));
1927 display_name = _ctk_file_system_volume_get_display_name (volume);
1928
1929 ctk_list_store_insert (store, &iter, pos);
1930 ctk_list_store_set (store, &iter,
1931 ICON_COLUMN, surface,
1932 DISPLAY_NAME_COLUMN, display_name,
1933 TYPE_COLUMN, ROW_TYPE_VOLUME,
1934 DATA_COLUMN, _ctk_file_system_volume_ref (volume),
1935 IS_FOLDER_COLUMN, TRUE(!(0)),
1936 -1);
1937
1938 if (surface)
1939 cairo_surface_destroy (surface);
1940 g_free (display_name);
1941
1942 button->priv->n_volumes++;
1943 pos++;
1944 }
1945}
1946
1947extern gchar * _ctk_file_chooser_label_for_file (GFile *file);
1948
1949static void
1950model_add_bookmarks (CtkFileChooserButton *button,
1951 GSList *bookmarks)
1952{
1953 CtkListStore *store;
1954 CtkTreeIter iter;
1955 gint pos;
1956 gboolean local_only;
1957 GSList *l;
1958
1959 if (!bookmarks)
1960 return;
1961
1962 store = CTK_LIST_STORE (button->priv->model)((((CtkListStore*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((button->priv->model)), ((ctk_list_store_get_type (
)))))))
;
1963 pos = model_get_type_position (button, ROW_TYPE_BOOKMARK);
1964 local_only = ctk_file_chooser_get_local_only (CTK_FILE_CHOOSER (button->priv->chooser)((((CtkFileChooser*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((button->priv->chooser)), ((ctk_file_chooser_get_type
()))))))
);
1965
1966 for (l = bookmarks; l; l = l->next)
1967 {
1968 GFile *file;
1969
1970 file = l->data;
1971
1972 if (_ctk_file_has_native_path (file))
1973 {
1974 ctk_list_store_insert (store, &iter, pos);
1975 ctk_list_store_set (store, &iter,
1976 ICON_COLUMN, NULL((void*)0),
1977 DISPLAY_NAME_COLUMN, _(FALLBACK_DISPLAY_NAME)((char *) g_dgettext ("ctk30", ("(None)"))),
1978 TYPE_COLUMN, ROW_TYPE_BOOKMARK,
1979 DATA_COLUMN, g_object_ref (file)((__typeof__ (file)) (g_object_ref) (file)),
1980 IS_FOLDER_COLUMN, FALSE(0),
1981 -1);
1982 set_info_for_file_at_iter (button, file, &iter);
1983 }
1984 else
1985 {
1986 gchar *label;
1987 CtkIconTheme *icon_theme;
1988 cairo_surface_t *surface = NULL((void*)0);
1989
1990 if (local_only)
1991 continue;
1992
1993 /* Don't call get_info for remote paths to avoid latency and
1994 * auth dialogs.
1995 * If we switch to a better bookmarks file format (XBEL), we
1996 * should use mime info to get a better icon.
1997 */
1998 label = _ctk_bookmarks_manager_get_bookmark_label (button->priv->bookmarks_manager, file);
1999 if (!label)
2000 label = _ctk_file_chooser_label_for_file (file);
2001
2002 icon_theme = get_icon_theme (CTK_WIDGET (button)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((button)), ((ctk_widget_get_type ()))))))
);
2003 surface = ctk_icon_theme_load_surface (icon_theme, "folder-remote",
2004 button->priv->icon_size,
2005 ctk_widget_get_scale_factor (CTK_WIDGET (button)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((button)), ((ctk_widget_get_type ()))))))
),
2006 ctk_widget_get_window (CTK_WIDGET (button)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((button)), ((ctk_widget_get_type ()))))))
),
2007 0, NULL((void*)0));
2008
2009 ctk_list_store_insert (store, &iter, pos);
2010 ctk_list_store_set (store, &iter,
2011 ICON_COLUMN, surface,
2012 DISPLAY_NAME_COLUMN, label,
2013 TYPE_COLUMN, ROW_TYPE_BOOKMARK,
2014 DATA_COLUMN, g_object_ref (file)((__typeof__ (file)) (g_object_ref) (file)),
2015 IS_FOLDER_COLUMN, TRUE(!(0)),
2016 -1);
2017
2018 g_free (label);
2019 if (surface)
2020 cairo_surface_destroy (surface);
2021 }
2022
2023 button->priv->n_bookmarks++;
2024 pos++;
2025 }
2026
2027 if (button->priv->n_bookmarks > 0 &&
2028 !button->priv->has_bookmark_separator)
2029 {
2030 pos = model_get_type_position (button, ROW_TYPE_BOOKMARK_SEPARATOR);
2031
2032 ctk_list_store_insert (store, &iter, pos);
2033 ctk_list_store_set (store, &iter,
2034 ICON_COLUMN, NULL((void*)0),
2035 DISPLAY_NAME_COLUMN, NULL((void*)0),
2036 TYPE_COLUMN, ROW_TYPE_BOOKMARK_SEPARATOR,
2037 DATA_COLUMN, NULL((void*)0),
2038 IS_FOLDER_COLUMN, FALSE(0),
2039 -1);
2040 button->priv->has_bookmark_separator = TRUE(!(0));
2041 }
2042}
2043
2044static void
2045model_update_current_folder (CtkFileChooserButton *button,
2046 GFile *file)
2047{
2048 CtkListStore *store;
2049 CtkTreeIter iter;
2050 gint pos;
2051
2052 if (!file)
2053 return;
2054
2055 store = CTK_LIST_STORE (button->priv->model)((((CtkListStore*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((button->priv->model)), ((ctk_list_store_get_type (
)))))))
;
2056
2057 if (!button->priv->has_current_folder_separator)
2058 {
2059 pos = model_get_type_position (button, ROW_TYPE_CURRENT_FOLDER_SEPARATOR);
2060 ctk_list_store_insert (store, &iter, pos);
2061 ctk_list_store_set (store, &iter,
2062 ICON_COLUMN, NULL((void*)0),
2063 DISPLAY_NAME_COLUMN, NULL((void*)0),
2064 TYPE_COLUMN, ROW_TYPE_CURRENT_FOLDER_SEPARATOR,
2065 DATA_COLUMN, NULL((void*)0),
2066 IS_FOLDER_COLUMN, FALSE(0),
2067 -1);
2068 button->priv->has_current_folder_separator = TRUE(!(0));
2069 }
2070
2071 pos = model_get_type_position (button, ROW_TYPE_CURRENT_FOLDER);
2072 if (!button->priv->has_current_folder)
2073 {
2074 ctk_list_store_insert (store, &iter, pos);
2075 button->priv->has_current_folder = TRUE(!(0));
2076 }
2077 else
2078 {
2079 ctk_tree_model_iter_nth_child (button->priv->model, &iter, NULL((void*)0), pos);
2080 model_free_row_data (button, &iter);
2081 }
2082
2083 if (g_file_is_native (file))
2084 {
2085 ctk_list_store_set (store, &iter,
2086 ICON_COLUMN, NULL((void*)0),
2087 DISPLAY_NAME_COLUMN, _(FALLBACK_DISPLAY_NAME)((char *) g_dgettext ("ctk30", ("(None)"))),
2088 TYPE_COLUMN, ROW_TYPE_CURRENT_FOLDER,
2089 DATA_COLUMN, g_object_ref (file)((__typeof__ (file)) (g_object_ref) (file)),
2090 IS_FOLDER_COLUMN, FALSE(0),
2091 -1);
2092 set_info_for_file_at_iter (button, file, &iter);
2093 }
2094 else
2095 {
2096 gchar *label;
2097 CtkIconTheme *icon_theme;
2098 cairo_surface_t *surface;
2099
2100 /* Don't call get_info for remote paths to avoid latency and
2101 * auth dialogs.
2102 * If we switch to a better bookmarks file format (XBEL), we
2103 * should use mime info to get a better icon.
2104 */
2105 label = _ctk_bookmarks_manager_get_bookmark_label (button->priv->bookmarks_manager, file);
2106 if (!label)
2107 label = _ctk_file_chooser_label_for_file (file);
2108
2109 icon_theme = get_icon_theme (CTK_WIDGET (button)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((button)), ((ctk_widget_get_type ()))))))
);
2110
2111 if (g_file_is_native (file))
2112 surface = ctk_icon_theme_load_surface (icon_theme, "folder",
2113 button->priv->icon_size,
2114 ctk_widget_get_scale_factor (CTK_WIDGET (button)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((button)), ((ctk_widget_get_type ()))))))
),
2115 ctk_widget_get_window (CTK_WIDGET (button)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((button)), ((ctk_widget_get_type ()))))))
),
2116 0, NULL((void*)0));
2117 else
2118 surface = ctk_icon_theme_load_surface (icon_theme, "folder-remote",
2119 button->priv->icon_size,
2120 ctk_widget_get_scale_factor (CTK_WIDGET (button)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((button)), ((ctk_widget_get_type ()))))))
),
2121 ctk_widget_get_window (CTK_WIDGET (button)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((button)), ((ctk_widget_get_type ()))))))
),
2122 0, NULL((void*)0));
2123
2124 ctk_list_store_set (store, &iter,
2125 ICON_COLUMN, surface,
2126 DISPLAY_NAME_COLUMN, label,
2127 TYPE_COLUMN, ROW_TYPE_CURRENT_FOLDER,
2128 DATA_COLUMN, g_object_ref (file)((__typeof__ (file)) (g_object_ref) (file)),
2129 IS_FOLDER_COLUMN, TRUE(!(0)),
2130 -1);
2131
2132 g_free (label);
2133 if (surface)
2134 cairo_surface_destroy (surface);
2135 }
2136}
2137
2138static void
2139model_add_other (CtkFileChooserButton *button)
2140{
2141 CtkListStore *store;
2142 CtkTreeIter iter;
2143 gint pos;
2144
2145 store = CTK_LIST_STORE (button->priv->model)((((CtkListStore*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((button->priv->model)), ((ctk_list_store_get_type (
)))))))
;
2146 pos = model_get_type_position (button, ROW_TYPE_OTHER_SEPARATOR);
2147
2148 ctk_list_store_insert (store, &iter, pos);
2149 ctk_list_store_set (store, &iter,
2150 ICON_COLUMN, NULL((void*)0),
2151 DISPLAY_NAME_COLUMN, NULL((void*)0),
2152 TYPE_COLUMN, ROW_TYPE_OTHER_SEPARATOR,
2153 DATA_COLUMN, NULL((void*)0),
2154 IS_FOLDER_COLUMN, FALSE(0),
2155 -1);
2156 button->priv->has_other_separator = TRUE(!(0));
2157 pos++;
2158
2159 ctk_list_store_insert (store, &iter, pos);
2160 ctk_list_store_set (store, &iter,
2161 ICON_COLUMN, NULL((void*)0),
2162 DISPLAY_NAME_COLUMN, _("Other…")((char *) g_dgettext ("ctk30", "Other…")),
2163 TYPE_COLUMN, ROW_TYPE_OTHER,
2164 DATA_COLUMN, NULL((void*)0),
2165 IS_FOLDER_COLUMN, FALSE(0),
2166 -1);
2167}
2168
2169static void
2170model_add_empty_selection (CtkFileChooserButton *button)
2171{
2172 CtkListStore *store;
2173 CtkTreeIter iter;
2174 gint pos;
2175
2176 store = CTK_LIST_STORE (button->priv->model)((((CtkListStore*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((button->priv->model)), ((ctk_list_store_get_type (
)))))))
;
2177 pos = model_get_type_position (button, ROW_TYPE_EMPTY_SELECTION);
2178
2179 ctk_list_store_insert (store, &iter, pos);
2180 ctk_list_store_set (store, &iter,
2181 ICON_COLUMN, NULL((void*)0),
2182 DISPLAY_NAME_COLUMN, _(FALLBACK_DISPLAY_NAME)((char *) g_dgettext ("ctk30", ("(None)"))),
2183 TYPE_COLUMN, ROW_TYPE_EMPTY_SELECTION,
2184 DATA_COLUMN, NULL((void*)0),
2185 IS_FOLDER_COLUMN, FALSE(0),
2186 -1);
2187}
2188
2189static void
2190model_remove_rows (CtkFileChooserButton *button,
2191 gint pos,
2192 gint n_rows)
2193{
2194 CtkListStore *store;
2195
2196 if (!n_rows)
2197 return;
2198
2199 store = CTK_LIST_STORE (button->priv->model)((((CtkListStore*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((button->priv->model)), ((ctk_list_store_get_type (
)))))))
;
2200
2201 do
2202 {
2203 CtkTreeIter iter;
2204
2205 if (!ctk_tree_model_iter_nth_child (button->priv->model, &iter, NULL((void*)0), pos))
2206 g_assert_not_reached ()do { g_assertion_message_expr ("Ctk", "ctkfilechooserbutton.c"
, 2206, ((const char*) (__func__)), ((void*)0)); } while (0)
;
2207
2208 model_free_row_data (button, &iter);
2209 ctk_list_store_remove (store, &iter);
2210 n_rows--;
2211 }
2212 while (n_rows);
2213}
2214
2215/* Filter Model */
2216static gboolean
2217test_if_file_is_visible (CtkFileSystem *fs G_GNUC_UNUSED__attribute__ ((__unused__)),
2218 GFile *file,
2219 gboolean local_only,
2220 gboolean is_folder)
2221{
2222 if (!file)
2223 return FALSE(0);
2224
2225 if (local_only && !_ctk_file_has_native_path (file))
2226 return FALSE(0);
2227
2228 if (!is_folder)
2229 return FALSE(0);
2230
2231 return TRUE(!(0));
2232}
2233
2234static gboolean
2235filter_model_visible_func (CtkTreeModel *model,
2236 CtkTreeIter *iter,
2237 gpointer user_data)
2238{
2239 CtkFileChooserButton *button = CTK_FILE_CHOOSER_BUTTON (user_data)((((CtkFileChooserButton*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((user_data)), ((ctk_file_chooser_button_get_type
()))))))
;
2240 CtkFileChooserButtonPrivate *priv = button->priv;
2241 gchar type;
2242 gpointer data;
2243 gboolean local_only, retval, is_folder;
2244
2245 type = ROW_TYPE_INVALID;
2246 data = NULL((void*)0);
2247 local_only = ctk_file_chooser_get_local_only (CTK_FILE_CHOOSER (priv->chooser)((((CtkFileChooser*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((priv->chooser)), ((ctk_file_chooser_get_type ()))))))
);
2248
2249 ctk_tree_model_get (model, iter,
2250 TYPE_COLUMN, &type,
2251 DATA_COLUMN, &data,
2252 IS_FOLDER_COLUMN, &is_folder,
2253 -1);
2254
2255 switch (type)
2256 {
2257 case ROW_TYPE_CURRENT_FOLDER:
2258 retval = TRUE(!(0));
2259 break;
2260 case ROW_TYPE_SPECIAL:
2261 case ROW_TYPE_SHORTCUT:
2262 case ROW_TYPE_BOOKMARK:
2263 retval = test_if_file_is_visible (priv->fs, data, local_only, is_folder);
2264 break;
2265 case ROW_TYPE_VOLUME:
2266 {
2267 retval = TRUE(!(0));
2268 if (local_only)
2269 {
2270 if (_ctk_file_system_volume_is_mounted (data))
2271 {
2272 GFile *base_file;
2273
2274 base_file = _ctk_file_system_volume_get_root (data);
2275
2276 if (base_file)
2277 {
2278 if (!_ctk_file_has_native_path (base_file))
2279 retval = FALSE(0);
2280 g_object_unref (base_file);
2281 }
2282 else
2283 retval = FALSE(0);
2284 }
2285 }
2286 }
2287 break;
2288 case ROW_TYPE_EMPTY_SELECTION:
2289 {
2290 gboolean popup_shown;
2291
2292 g_object_get (priv->combo_box,
2293 "popup-shown", &popup_shown,
2294 NULL((void*)0));
2295
2296 if (popup_shown)
2297 retval = FALSE(0);
2298 else
2299 {
2300 GFile *selected;
2301
2302 /* When the combo box is not popped up... */
2303
2304 selected = get_selected_file (button);
2305 if (selected)
2306 retval = FALSE(0); /* ... nonempty selection means the ROW_TYPE_EMPTY_SELECTION is *not* visible... */
2307 else
2308 retval = TRUE(!(0)); /* ... and empty selection means the ROW_TYPE_EMPTY_SELECTION *is* visible */
2309
2310 if (selected)
2311 g_object_unref (selected);
2312 }
2313
2314 break;
2315 }
2316 default:
2317 retval = TRUE(!(0));
2318 break;
2319 }
2320
2321 return retval;
2322}
2323
2324/* Combo Box */
2325static void
2326name_cell_data_func (CtkCellLayout *layout G_GNUC_UNUSED__attribute__ ((__unused__)),
2327 CtkCellRenderer *cell,
2328 CtkTreeModel *model,
2329 CtkTreeIter *iter,
2330 gpointer user_data G_GNUC_UNUSED__attribute__ ((__unused__)))
2331{
2332 gchar type;
2333
2334 type = 0;
2335 ctk_tree_model_get (model, iter,
2336 TYPE_COLUMN, &type,
2337 -1);
2338
2339 if (type == ROW_TYPE_CURRENT_FOLDER)
2340 g_object_set (cell, "ellipsize", PANGO_ELLIPSIZE_END, NULL((void*)0));
2341 else if (type == ROW_TYPE_BOOKMARK || type == ROW_TYPE_SHORTCUT)
2342 g_object_set (cell, "ellipsize", PANGO_ELLIPSIZE_MIDDLE, NULL((void*)0));
2343 else
2344 g_object_set (cell, "ellipsize", PANGO_ELLIPSIZE_NONE, NULL((void*)0));
2345}
2346
2347static gboolean
2348combo_box_row_separator_func (CtkTreeModel *model,
2349 CtkTreeIter *iter,
2350 gpointer user_data G_GNUC_UNUSED__attribute__ ((__unused__)))
2351{
2352 gchar type = ROW_TYPE_INVALID;
2353
2354 ctk_tree_model_get (model, iter, TYPE_COLUMN, &type, -1);
2355
2356 return (type == ROW_TYPE_BOOKMARK_SEPARATOR ||
2357 type == ROW_TYPE_CURRENT_FOLDER_SEPARATOR ||
2358 type == ROW_TYPE_OTHER_SEPARATOR);
2359}
2360
2361static void
2362select_combo_box_row_no_notify (CtkFileChooserButton *button, int pos)
2363{
2364 CtkFileChooserButtonPrivate *priv = button->priv;
2365 CtkTreeIter iter, filter_iter;
2366
2367 ctk_tree_model_iter_nth_child (priv->model, &iter, NULL((void*)0), pos);
2368 ctk_tree_model_filter_convert_child_iter_to_iter (CTK_TREE_MODEL_FILTER (priv->filter_model)((((CtkTreeModelFilter*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((priv->filter_model)), ((ctk_tree_model_filter_get_type
()))))))
,
2369 &filter_iter, &iter);
2370
2371 g_signal_handlers_block_by_func (priv->combo_box, combo_box_changed_cb, button)g_signal_handlers_block_matched ((priv->combo_box), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (combo_box_changed_cb), (button))
;
2372 ctk_combo_box_set_active_iter (CTK_COMBO_BOX (priv->combo_box)((((CtkComboBox*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((priv->combo_box)), ((ctk_combo_box_get_type ()))))))
, &filter_iter);
2373 g_signal_handlers_unblock_by_func (priv->combo_box, combo_box_changed_cb, button)g_signal_handlers_unblock_matched ((priv->combo_box), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (combo_box_changed_cb), (button))
;
2374}
2375
2376static void
2377update_combo_box (CtkFileChooserButton *button)
2378{
2379 CtkFileChooserButtonPrivate *priv = button->priv;
2380 GFile *file;
2381 CtkTreeIter iter;
2382 gboolean row_found;
2383
2384 file = get_selected_file (button);
2385
2386 row_found = FALSE(0);
2387
2388 ctk_tree_model_get_iter_first (priv->filter_model, &iter);
2389
2390 do
2391 {
2392 gchar type;
2393 gpointer data;
2394
2395 type = ROW_TYPE_INVALID;
2396 data = NULL((void*)0);
2397
2398 ctk_tree_model_get (priv->filter_model, &iter,
2399 TYPE_COLUMN, &type,
2400 DATA_COLUMN, &data,
2401 -1);
2402
2403 switch (type)
2404 {
2405 case ROW_TYPE_SPECIAL:
2406 case ROW_TYPE_SHORTCUT:
2407 case ROW_TYPE_BOOKMARK:
2408 case ROW_TYPE_CURRENT_FOLDER:
2409 row_found = (file && g_file_equal (data, file));
2410 break;
2411 case ROW_TYPE_VOLUME:
2412 {
2413 GFile *base_file;
2414
2415 base_file = _ctk_file_system_volume_get_root (data);
2416 if (base_file)
2417 {
2418 row_found = (file && g_file_equal (base_file, file));
2419 g_object_unref (base_file);
2420 }
2421 }
2422 break;
2423 default:
2424 row_found = FALSE(0);
2425 break;
2426 }
2427
2428 if (row_found)
2429 {
2430 g_signal_handlers_block_by_func (priv->combo_box, combo_box_changed_cb, button)g_signal_handlers_block_matched ((priv->combo_box), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (combo_box_changed_cb), (button))
;
2431 ctk_combo_box_set_active_iter (CTK_COMBO_BOX (priv->combo_box)((((CtkComboBox*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((priv->combo_box)), ((ctk_combo_box_get_type ()))))))
,
2432 &iter);
2433 g_signal_handlers_unblock_by_func (priv->combo_box, combo_box_changed_cb, button)g_signal_handlers_unblock_matched ((priv->combo_box), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (combo_box_changed_cb), (button))
;
2434 }
2435 }
2436 while (!row_found && ctk_tree_model_iter_next (priv->filter_model, &iter));
2437
2438 if (!row_found)
2439 {
2440 gint pos;
2441
2442 /* If it hasn't been found already, update & select the current-folder row. */
2443 if (file)
2444 {
2445 model_update_current_folder (button, file);
2446 pos = model_get_type_position (button, ROW_TYPE_CURRENT_FOLDER);
2447 }
2448 else
2449 {
2450 /* No selection; switch to that row */
2451
2452 pos = model_get_type_position (button, ROW_TYPE_EMPTY_SELECTION);
2453 }
2454
2455 ctk_tree_model_filter_refilter (CTK_TREE_MODEL_FILTER (priv->filter_model)((((CtkTreeModelFilter*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((priv->filter_model)), ((ctk_tree_model_filter_get_type
()))))))
);
2456
2457 select_combo_box_row_no_notify (button, pos);
2458 }
2459
2460 if (file)
2461 g_object_unref (file);
2462}
2463
2464/* Button */
2465static void
2466update_label_get_info_cb (GCancellable *cancellable,
2467 GFileInfo *info,
2468 const GError *error,
2469 gpointer data)
2470{
2471 gboolean cancelled = g_cancellable_is_cancelled (cancellable);
2472 cairo_surface_t *surface;
2473 CtkFileChooserButton *button = data;
2474 CtkFileChooserButtonPrivate *priv = button->priv;
2475
2476 if (cancellable != priv->update_button_cancellable)
2477 goto out;
2478
2479 priv->update_button_cancellable = NULL((void*)0);
2480
2481 if (cancelled || error)
2482 goto out;
2483
2484 ctk_label_set_text (CTK_LABEL (priv->label)((((CtkLabel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((priv->label)), ((ctk_label_get_type ()))))))
, g_file_info_get_display_name (info));
2485
2486 surface = _ctk_file_info_render_icon (info, CTK_WIDGET (priv->image)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((priv->image)), ((ctk_widget_get_type ()))))))
, priv->icon_size);
2487 ctk_image_set_from_surface (CTK_IMAGE (priv->image)((((CtkImage*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((priv->image)), ((ctk_image_get_type ()))))))
, surface);
2488 if (surface)
2489 cairo_surface_destroy (surface);
2490
2491out:
2492 emit_selection_changed_if_changing_selection (button);
2493
2494 g_object_unref (button);
2495 g_object_unref (cancellable);
2496}
2497
2498static void
2499update_label_and_image (CtkFileChooserButton *button)
2500{
2501 CtkFileChooserButtonPrivate *priv = button->priv;
2502 gchar *label_text;
2503 GFile *file;
2504 gboolean done_changing_selection;
2505
2506 file = get_selected_file (button);
2507
2508 label_text = NULL((void*)0);
2509 done_changing_selection = FALSE(0);
2510
2511 if (priv->update_button_cancellable)
2512 {
2513 g_cancellable_cancel (priv->update_button_cancellable);
2514 priv->update_button_cancellable = NULL((void*)0);
2515 }
2516
2517 if (file)
2518 {
2519 CtkFileSystemVolume *volume = NULL((void*)0);
2520
2521 volume = _ctk_file_system_get_volume_for_file (priv->fs, file);
2522 if (volume)
2523 {
2524 GFile *base_file;
2525
2526 base_file = _ctk_file_system_volume_get_root (volume);
2527 if (base_file && g_file_equal (base_file, file))
2528 {
2529 cairo_surface_t *surface;
2530
2531 label_text = _ctk_file_system_volume_get_display_name (volume);
2532 surface = _ctk_file_system_volume_render_icon (volume,
2533 CTK_WIDGET (button)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((button)), ((ctk_widget_get_type ()))))))
,
2534 priv->icon_size,
2535 NULL((void*)0));
2536 ctk_image_set_from_surface (CTK_IMAGE (priv->image)((((CtkImage*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((priv->image)), ((ctk_image_get_type ()))))))
, surface);
2537 if (surface)
2538 cairo_surface_destroy (surface);
2539 }
2540
2541 if (base_file)
2542 g_object_unref (base_file);
2543
2544 _ctk_file_system_volume_unref (volume);
2545
2546 if (label_text)
2547 {
2548 done_changing_selection = TRUE(!(0));
2549 goto out;
2550 }
2551 }
2552
2553 if (g_file_is_native (file))
2554 {
2555 priv->update_button_cancellable =
2556 _ctk_file_system_get_info (priv->fs, file,
2557 "standard::icon,standard::display-name",
2558 update_label_get_info_cb,
2559 g_object_ref (button)((__typeof__ (button)) (g_object_ref) (button)));
2560 }
2561 else
2562 {
2563 cairo_surface_t *surface;
2564
2565 label_text = _ctk_bookmarks_manager_get_bookmark_label (button->priv->bookmarks_manager, file);
2566 surface = ctk_icon_theme_load_surface (get_icon_theme (CTK_WIDGET (priv->image)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((priv->image)), ((ctk_widget_get_type ()))))))
),
2567 "text-x-generic",
2568 priv->icon_size,
2569 ctk_widget_get_scale_factor (CTK_WIDGET (button)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((button)), ((ctk_widget_get_type ()))))))
),
2570 ctk_widget_get_window (CTK_WIDGET (button)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((button)), ((ctk_widget_get_type ()))))))
),
2571 0, NULL((void*)0));
2572 ctk_image_set_from_surface (CTK_IMAGE (priv->image)((((CtkImage*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((priv->image)), ((ctk_image_get_type ()))))))
, surface);
2573 if (surface)
2574 cairo_surface_destroy (surface);
2575
2576 done_changing_selection = TRUE(!(0));
2577 }
2578 }
2579 else
2580 {
2581 /* We know the selection is empty */
2582 done_changing_selection = TRUE(!(0));
2583 }
2584
2585out:
2586
2587 if (file)
2588 g_object_unref (file);
2589
2590 if (label_text)
2591 {
2592 ctk_label_set_text (CTK_LABEL (priv->label)((((CtkLabel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((priv->label)), ((ctk_label_get_type ()))))))
, label_text);
2593 g_free (label_text);
2594 }
2595 else
2596 {
2597 ctk_label_set_text (CTK_LABEL (priv->label)((((CtkLabel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((priv->label)), ((ctk_label_get_type ()))))))
, _(FALLBACK_DISPLAY_NAME)((char *) g_dgettext ("ctk30", ("(None)"))));
2598 ctk_image_set_from_surface (CTK_IMAGE (priv->image)((((CtkImage*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((priv->image)), ((ctk_image_get_type ()))))))
, NULL((void*)0));
2599 }
2600
2601 if (done_changing_selection)
2602 emit_selection_changed_if_changing_selection (button);
2603}
2604
2605
2606/* ************************ *
2607 * Child Object Callbacks *
2608 * ************************ */
2609
2610/* File System */
2611static void
2612fs_volumes_changed_cb (CtkFileSystem *fs,
2613 gpointer user_data)
2614{
2615 CtkFileChooserButton *button = CTK_FILE_CHOOSER_BUTTON (user_data)((((CtkFileChooserButton*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((user_data)), ((ctk_file_chooser_button_get_type
()))))))
;
2616 CtkFileChooserButtonPrivate *priv = button->priv;
2617 GSList *volumes;
2618
2619 model_remove_rows (user_data,
2620 model_get_type_position (user_data, ROW_TYPE_VOLUME),
2621 priv->n_volumes);
2622
2623 priv->n_volumes = 0;
2624
2625 volumes = _ctk_file_system_list_volumes (fs);
2626 model_add_volumes (user_data, volumes);
2627 g_slist_free (volumes);
2628
2629 ctk_tree_model_filter_refilter (CTK_TREE_MODEL_FILTER (priv->filter_model)((((CtkTreeModelFilter*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((priv->filter_model)), ((ctk_tree_model_filter_get_type
()))))))
);
2630
2631 update_label_and_image (user_data);
2632 update_combo_box (user_data);
2633}
2634
2635static void
2636bookmarks_changed_cb (gpointer user_data)
2637{
2638 CtkFileChooserButton *button = CTK_FILE_CHOOSER_BUTTON (user_data)((((CtkFileChooserButton*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((user_data)), ((ctk_file_chooser_button_get_type
()))))))
;
2639 CtkFileChooserButtonPrivate *priv = button->priv;
2640 GSList *bookmarks;
2641
2642 bookmarks = _ctk_bookmarks_manager_list_bookmarks (priv->bookmarks_manager);
2643 model_remove_rows (user_data,
2644 model_get_type_position (user_data, ROW_TYPE_BOOKMARK_SEPARATOR),
2645 priv->n_bookmarks + priv->has_bookmark_separator);
2646 priv->has_bookmark_separator = FALSE(0);
2647 priv->n_bookmarks = 0;
2648 model_add_bookmarks (user_data, bookmarks);
2649 g_slist_free_full (bookmarks, g_object_unref);
2650
2651 ctk_tree_model_filter_refilter (CTK_TREE_MODEL_FILTER (priv->filter_model)((((CtkTreeModelFilter*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((priv->filter_model)), ((ctk_tree_model_filter_get_type
()))))))
);
2652
2653 update_label_and_image (user_data);
2654 update_combo_box (user_data);
2655}
2656
2657static void
2658save_inactive_state (CtkFileChooserButton *button)
2659{
2660 CtkFileChooserButtonPrivate *priv = button->priv;
2661
2662 if (priv->current_folder_while_inactive)
2663 g_object_unref (priv->current_folder_while_inactive);
2664
2665 if (priv->selection_while_inactive)
2666 g_object_unref (priv->selection_while_inactive);
2667
2668 priv->current_folder_while_inactive = ctk_file_chooser_get_current_folder_file (CTK_FILE_CHOOSER (priv->chooser)((((CtkFileChooser*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((priv->chooser)), ((ctk_file_chooser_get_type ()))))))
);
2669 priv->selection_while_inactive = ctk_file_chooser_get_file (CTK_FILE_CHOOSER (priv->chooser)((((CtkFileChooser*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((priv->chooser)), ((ctk_file_chooser_get_type ()))))))
);
2670}
2671
2672static void
2673restore_inactive_state (CtkFileChooserButton *button)
2674{
2675 CtkFileChooserButtonPrivate *priv = button->priv;
2676
2677 if (priv->current_folder_while_inactive)
2678 ctk_file_chooser_set_current_folder_file (CTK_FILE_CHOOSER (priv->chooser)((((CtkFileChooser*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((priv->chooser)), ((ctk_file_chooser_get_type ()))))))
, priv->current_folder_while_inactive, NULL((void*)0));
2679
2680 if (priv->selection_while_inactive)
2681 ctk_file_chooser_select_file (CTK_FILE_CHOOSER (priv->chooser)((((CtkFileChooser*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((priv->chooser)), ((ctk_file_chooser_get_type ()))))))
, priv->selection_while_inactive, NULL((void*)0));
2682 else
2683 ctk_file_chooser_unselect_all (CTK_FILE_CHOOSER (priv->chooser)((((CtkFileChooser*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((priv->chooser)), ((ctk_file_chooser_get_type ()))))))
);
2684}
2685
2686/* Dialog */
2687static void
2688open_dialog (CtkFileChooserButton *button)
2689{
2690 CtkFileChooserButtonPrivate *priv = button->priv;
2691 CtkWidget *toplevel;
2692
2693 toplevel = ctk_widget_get_toplevel (CTK_WIDGET (button)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((button)), ((ctk_widget_get_type ()))))))
);
2694
2695 /* Setup the dialog parent to be chooser button's toplevel, and be modal
2696 as needed. */
2697 if (priv->dialog != NULL((void*)0))
2698 {
2699 if (!ctk_widget_get_visible (priv->dialog))
2700 {
2701 if (ctk_widget_is_toplevel (toplevel) && CTK_IS_WINDOW (toplevel)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(toplevel)); GType __t = ((ctk_window_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; }))))
)
2702 {
2703 if (CTK_WINDOW (toplevel)((((CtkWindow*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((toplevel)), ((ctk_window_get_type ()))))))
!= ctk_window_get_transient_for (CTK_WINDOW (priv->dialog)((((CtkWindow*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((priv->dialog)), ((ctk_window_get_type ()))))))
))
2704 ctk_window_set_transient_for (CTK_WINDOW (priv->dialog)((((CtkWindow*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((priv->dialog)), ((ctk_window_get_type ()))))))
,
2705 CTK_WINDOW (toplevel)((((CtkWindow*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((toplevel)), ((ctk_window_get_type ()))))))
);
2706
2707 ctk_window_set_modal (CTK_WINDOW (priv->dialog)((((CtkWindow*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((priv->dialog)), ((ctk_window_get_type ()))))))
,
2708 ctk_window_get_modal (CTK_WINDOW (toplevel)((((CtkWindow*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((toplevel)), ((ctk_window_get_type ()))))))
));
2709 }
2710 }
2711 }
2712 else
2713 {
2714 if (!ctk_native_dialog_get_visible (CTK_NATIVE_DIALOG (priv->native)))
2715 {
2716 if (ctk_widget_is_toplevel (toplevel) && CTK_IS_WINDOW (toplevel)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(toplevel)); GType __t = ((ctk_window_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; }))))
)
2717 {
2718 if (CTK_WINDOW (toplevel)((((CtkWindow*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((toplevel)), ((ctk_window_get_type ()))))))
!= ctk_native_dialog_get_transient_for (CTK_NATIVE_DIALOG (priv->native)))
2719 ctk_native_dialog_set_transient_for (CTK_NATIVE_DIALOG (priv->native),
2720 CTK_WINDOW (toplevel)((((CtkWindow*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((toplevel)), ((ctk_window_get_type ()))))))
);
2721
2722 ctk_native_dialog_set_modal (CTK_NATIVE_DIALOG (priv->native),
2723 ctk_window_get_modal (CTK_WINDOW (toplevel)((((CtkWindow*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((toplevel)), ((ctk_window_get_type ()))))))
));
2724 }
2725 }
2726 }
2727
2728 if (!priv->active)
2729 {
2730 restore_inactive_state (button);
2731 priv->active = TRUE(!(0));
2732
2733 /* Only handle update-preview handler if it is handled on the button */
2734 if (g_signal_has_handler_pending (button,
2735 g_signal_lookup ("update-preview", CTK_TYPE_FILE_CHOOSER(ctk_file_chooser_get_type ())),
2736 0, TRUE(!(0))))
2737 {
2738 g_signal_connect (priv->chooser, "update-preview",g_signal_connect_data ((priv->chooser), ("update-preview")
, (((GCallback) (chooser_update_preview_cb))), (button), ((void
*)0), (GConnectFlags) 0)
2739 G_CALLBACK (chooser_update_preview_cb), button)g_signal_connect_data ((priv->chooser), ("update-preview")
, (((GCallback) (chooser_update_preview_cb))), (button), ((void
*)0), (GConnectFlags) 0)
;
2740 }
2741 }
2742
2743 ctk_widget_set_sensitive (priv->combo_box, FALSE(0));
2744 if (priv->dialog)
2745 {
2746 ctk_window_present (CTK_WINDOW (priv->dialog)((((CtkWindow*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((priv->dialog)), ((ctk_window_get_type ()))))))
);
2747 }
2748 else
2749 ctk_native_dialog_show (CTK_NATIVE_DIALOG (priv->native));
2750}
2751
2752/* Combo Box */
2753static void
2754combo_box_changed_cb (CtkComboBox *combo_box,
2755 gpointer user_data)
2756{
2757 CtkFileChooserButton *button = CTK_FILE_CHOOSER_BUTTON (user_data)((((CtkFileChooserButton*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((user_data)), ((ctk_file_chooser_button_get_type
()))))))
;
2758 CtkFileChooserButtonPrivate *priv = button->priv;
2759 CtkTreeIter iter;
2760 gboolean file_was_set;
2761
2762 file_was_set = FALSE(0);
2763
2764 if (ctk_combo_box_get_active_iter (combo_box, &iter))
2765 {
2766 gchar type;
2767 gpointer data;
2768
2769 type = ROW_TYPE_INVALID;
2770 data = NULL((void*)0);
2771
2772 ctk_tree_model_get (priv->filter_model, &iter,
2773 TYPE_COLUMN, &type,
2774 DATA_COLUMN, &data,
2775 -1);
2776
2777 switch (type)
2778 {
2779 case ROW_TYPE_SPECIAL:
2780 case ROW_TYPE_SHORTCUT:
2781 case ROW_TYPE_BOOKMARK:
2782 case ROW_TYPE_CURRENT_FOLDER:
2783 if (data)
2784 {
2785 ctk_file_chooser_button_select_file (CTK_FILE_CHOOSER (button)((((CtkFileChooser*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((button)), ((ctk_file_chooser_get_type ()))))))
, data, NULL((void*)0));
2786 file_was_set = TRUE(!(0));
2787 }
2788 break;
2789 case ROW_TYPE_VOLUME:
2790 {
2791 GFile *base_file;
2792
2793 base_file = _ctk_file_system_volume_get_root (data);
2794 if (base_file)
2795 {
2796 ctk_file_chooser_button_select_file (CTK_FILE_CHOOSER (button)((((CtkFileChooser*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((button)), ((ctk_file_chooser_get_type ()))))))
, base_file, NULL((void*)0));
2797 file_was_set = TRUE(!(0));
2798 g_object_unref (base_file);
2799 }
2800 }
2801 break;
2802 case ROW_TYPE_OTHER:
2803 open_dialog (user_data);
2804 break;
2805 default:
2806 break;
2807 }
2808 }
2809
2810 if (file_was_set)
2811 g_signal_emit (button, file_chooser_button_signals[FILE_SET], 0);
2812}
2813
2814/* Calback for the "notify::popup-shown" signal on the combo box.
2815 * When the combo is popped up, we don’t want the ROW_TYPE_EMPTY_SELECTION to be visible
2816 * at all; otherwise we would be showing a “(None)” item in the combo box’s popup.
2817 *
2818 * However, when the combo box is *not* popped up, we want the empty-selection row
2819 * to be visible depending on the selection.
2820 *
2821 * Since all that is done through the filter_model_visible_func(), this means
2822 * that we need to refilter the model when the combo box pops up - hence the
2823 * present signal handler.
2824 */
2825static void
2826combo_box_notify_popup_shown_cb (GObject *object G_GNUC_UNUSED__attribute__ ((__unused__)),
2827 GParamSpec *pspec G_GNUC_UNUSED__attribute__ ((__unused__)),
2828 gpointer user_data)
2829{
2830 CtkFileChooserButton *button = CTK_FILE_CHOOSER_BUTTON (user_data)((((CtkFileChooserButton*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((user_data)), ((ctk_file_chooser_button_get_type
()))))))
;
2831 CtkFileChooserButtonPrivate *priv = button->priv;
2832 gboolean popup_shown;
2833
2834 g_object_get (priv->combo_box,
2835 "popup-shown", &popup_shown,
2836 NULL((void*)0));
2837
2838 /* Indicate that the ROW_TYPE_EMPTY_SELECTION will change visibility... */
2839 ctk_tree_model_filter_refilter (CTK_TREE_MODEL_FILTER (priv->filter_model)((((CtkTreeModelFilter*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((priv->filter_model)), ((ctk_tree_model_filter_get_type
()))))))
);
2840
2841 /* If the combo box popup got dismissed, go back to showing the ROW_TYPE_EMPTY_SELECTION if needed */
2842 if (!popup_shown)
2843
2844 {
2845 GFile *selected = get_selected_file (button);
2846
2847 if (!selected)
2848 {
2849 int pos;
2850
2851 pos = model_get_type_position (button, ROW_TYPE_EMPTY_SELECTION);
2852 select_combo_box_row_no_notify (button, pos);
2853 }
2854 else
2855 g_object_unref (selected);
2856 }
2857}
2858
2859/* Button */
2860static void
2861button_clicked_cb (CtkButton *real_button G_GNUC_UNUSED__attribute__ ((__unused__)),
2862 gpointer user_data)
2863{
2864 open_dialog (user_data);
2865}
2866
2867/* Dialog */
2868
2869static void
2870chooser_update_preview_cb (CtkFileChooser *dialog G_GNUC_UNUSED__attribute__ ((__unused__)),
2871 gpointer user_data)
2872{
2873 g_signal_emit_by_name (user_data, "update-preview");
2874}
2875
2876static void
2877chooser_notify_cb (GObject *dialog,
2878 GParamSpec *pspec,
2879 gpointer user_data)
2880{
2881 gpointer iface;
2882
2883 iface = g_type_interface_peek (g_type_class_peek (G_OBJECT_TYPE (dialog)(((((GTypeClass*) (((GTypeInstance*) (dialog))->g_class))->
g_type)))
),
2884 CTK_TYPE_FILE_CHOOSER(ctk_file_chooser_get_type ()));
2885 if (g_object_interface_find_property (iface, pspec->name))
2886 g_object_notify (user_data, pspec->name);
2887
2888 if (g_ascii_strcasecmp (pspec->name, "local-only") == 0)
2889 {
2890 CtkFileChooserButton *button = CTK_FILE_CHOOSER_BUTTON (user_data)((((CtkFileChooserButton*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((user_data)), ((ctk_file_chooser_button_get_type
()))))))
;
2891 CtkFileChooserButtonPrivate *priv = button->priv;
2892
2893 if (priv->has_current_folder)
2894 {
2895 CtkTreeIter iter;
2896 gint pos;
2897 gpointer data;
2898
2899 pos = model_get_type_position (user_data,
2900 ROW_TYPE_CURRENT_FOLDER);
2901 ctk_tree_model_iter_nth_child (priv->model, &iter, NULL((void*)0), pos);
2902
2903 data = NULL((void*)0);
2904 ctk_tree_model_get (priv->model, &iter, DATA_COLUMN, &data, -1);
2905
2906 /* If the path isn't local but we're in local-only mode now, remove
2907 * the custom-folder row */
2908 if (data && _ctk_file_has_native_path (G_FILE (data)((((GFile*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((data)), ((g_file_get_type ()))))))
) &&
2909 ctk_file_chooser_get_local_only (CTK_FILE_CHOOSER (priv->chooser)((((CtkFileChooser*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((priv->chooser)), ((ctk_file_chooser_get_type ()))))))
))
2910 {
2911 pos--;
2912 model_remove_rows (user_data, pos, 2);
2913 }
2914 }
2915
2916 ctk_tree_model_filter_refilter (CTK_TREE_MODEL_FILTER (priv->filter_model)((((CtkTreeModelFilter*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((priv->filter_model)), ((ctk_tree_model_filter_get_type
()))))))
);
2917 update_combo_box (user_data);
2918 }
2919}
2920
2921static gboolean
2922dialog_delete_event_cb (CtkWidget *dialog,
2923 CdkEvent *event G_GNUC_UNUSED__attribute__ ((__unused__)),
2924 gpointer user_data G_GNUC_UNUSED__attribute__ ((__unused__)))
2925{
2926 g_signal_emit_by_name (dialog, "response", CTK_RESPONSE_DELETE_EVENT);
2927
2928 return TRUE(!(0));
2929}
2930
2931static void
2932common_response_cb (CtkFileChooserButton *button,
2933 gint response)
2934{
2935 CtkFileChooserButtonPrivate *priv = button->priv;
2936
2937 if (response == CTK_RESPONSE_ACCEPT ||
2938 response == CTK_RESPONSE_OK)
2939 {
2940 save_inactive_state (button);
2941
2942 g_signal_emit_by_name (button, "current-folder-changed");
2943 g_signal_emit_by_name (button, "selection-changed");
2944 }
2945 else
2946 {
2947 restore_inactive_state (button);
2948 }
2949
2950 if (priv->active)
2951 {
2952 priv->active = FALSE(0);
2953
2954 g_signal_handlers_disconnect_by_func (priv->chooser, chooser_update_preview_cb, button)g_signal_handlers_disconnect_matched ((priv->chooser), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (chooser_update_preview_cb), (button))
;
2955 }
2956
2957 update_label_and_image (button);
2958 update_combo_box (button);
2959
2960 ctk_widget_set_sensitive (priv->combo_box, TRUE(!(0)));
2961}
2962
2963
2964static void
2965dialog_response_cb (CtkDialog *dialog G_GNUC_UNUSED__attribute__ ((__unused__)),
2966 gint response,
2967 gpointer user_data)
2968{
2969 CtkFileChooserButton *button = CTK_FILE_CHOOSER_BUTTON (user_data)((((CtkFileChooserButton*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((user_data)), ((ctk_file_chooser_button_get_type
()))))))
;
2970 CtkFileChooserButtonPrivate *priv = button->priv;
2971
2972 common_response_cb (button, response);
2973
2974 ctk_widget_hide (priv->dialog);
2975
2976 if (response == CTK_RESPONSE_ACCEPT ||
2977 response == CTK_RESPONSE_OK)
2978 g_signal_emit (button, file_chooser_button_signals[FILE_SET], 0);
2979}
2980
2981static void
2982native_response_cb (CtkFileChooserNative *native G_GNUC_UNUSED__attribute__ ((__unused__)),
2983 gint response,
2984 gpointer user_data)
2985{
2986 CtkFileChooserButton *button = CTK_FILE_CHOOSER_BUTTON (user_data)((((CtkFileChooserButton*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((user_data)), ((ctk_file_chooser_button_get_type
()))))))
;
2987
2988 common_response_cb (button, response);
2989
2990 /* dialog already hidden */
2991
2992 if (response == CTK_RESPONSE_ACCEPT ||
2993 response == CTK_RESPONSE_OK)
2994 g_signal_emit (button, file_chooser_button_signals[FILE_SET], 0);
2995}
2996
2997
2998/* ************************************************************************** *
2999 * Public API *
3000 * ************************************************************************** */
3001
3002/**
3003 * ctk_file_chooser_button_new:
3004 * @title: the title of the browse dialog.
3005 * @action: the open mode for the widget.
3006 *
3007 * Creates a new file-selecting button widget.
3008 *
3009 * Returns: a new button widget.
3010 *
3011 * Since: 2.6
3012 */
3013CtkWidget *
3014ctk_file_chooser_button_new (const gchar *title,
3015 CtkFileChooserAction action)
3016{
3017 g_return_val_if_fail (action == CTK_FILE_CHOOSER_ACTION_OPEN ||do { if ((action == CTK_FILE_CHOOSER_ACTION_OPEN || action ==
CTK_FILE_CHOOSER_ACTION_SELECT_FOLDER)) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "action == CTK_FILE_CHOOSER_ACTION_OPEN || action == CTK_FILE_CHOOSER_ACTION_SELECT_FOLDER"
); return (((void*)0)); } } while (0)
3018 action == CTK_FILE_CHOOSER_ACTION_SELECT_FOLDER, NULL)do { if ((action == CTK_FILE_CHOOSER_ACTION_OPEN || action ==
CTK_FILE_CHOOSER_ACTION_SELECT_FOLDER)) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "action == CTK_FILE_CHOOSER_ACTION_OPEN || action == CTK_FILE_CHOOSER_ACTION_SELECT_FOLDER"
); return (((void*)0)); } } while (0)
;
3019
3020 return g_object_new (CTK_TYPE_FILE_CHOOSER_BUTTON(ctk_file_chooser_button_get_type ()),
3021 "action", action,
3022 "title", (title ? title : _(DEFAULT_TITLE)((char *) g_dgettext ("ctk30", ("Select a File")))),
3023 NULL((void*)0));
3024}
3025
3026/**
3027 * ctk_file_chooser_button_new_with_dialog:
3028 * @dialog: (type Ctk.Dialog): the widget to use as dialog
3029 *
3030 * Creates a #CtkFileChooserButton widget which uses @dialog as its
3031 * file-picking window.
3032 *
3033 * Note that @dialog must be a #CtkDialog (or subclass) which
3034 * implements the #CtkFileChooser interface and must not have
3035 * %CTK_DIALOG_DESTROY_WITH_PARENT set.
3036 *
3037 * Also note that the dialog needs to have its confirmative button
3038 * added with response %CTK_RESPONSE_ACCEPT or %CTK_RESPONSE_OK in
3039 * order for the button to take over the file selected in the dialog.
3040 *
3041 * Returns: a new button widget.
3042 *
3043 * Since: 2.6
3044 */
3045CtkWidget *
3046ctk_file_chooser_button_new_with_dialog (CtkWidget *dialog)
3047{
3048 g_return_val_if_fail (CTK_IS_FILE_CHOOSER (dialog) && CTK_IS_DIALOG (dialog), NULL)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((dialog)); GType __t = ((ctk_file_chooser_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; })))) &&
(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*)
((dialog)); GType __t = ((ctk_dialog_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 ("Ctk", ((const char*) (__func__
)), "CTK_IS_FILE_CHOOSER (dialog) && CTK_IS_DIALOG (dialog)"
); return (((void*)0)); } } while (0)
;
3049
3050 return g_object_new (CTK_TYPE_FILE_CHOOSER_BUTTON(ctk_file_chooser_button_get_type ()),
3051 "dialog", dialog,
3052 NULL((void*)0));
3053}
3054
3055/**
3056 * ctk_file_chooser_button_set_title:
3057 * @button: the button widget to modify.
3058 * @title: the new browse dialog title.
3059 *
3060 * Modifies the @title of the browse dialog used by @button.
3061 *
3062 * Since: 2.6
3063 */
3064void
3065ctk_file_chooser_button_set_title (CtkFileChooserButton *button,
3066 const gchar *title)
3067{
3068 g_return_if_fail (CTK_IS_FILE_CHOOSER_BUTTON (button))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((button)); GType __t = ((ctk_file_chooser_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 ("Ctk", ((const
char*) (__func__)), "CTK_IS_FILE_CHOOSER_BUTTON (button)"); return
; } } while (0)
;
3069
3070 if (button->priv->dialog)
3071 ctk_window_set_title (CTK_WINDOW (button->priv->dialog)((((CtkWindow*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((button->priv->dialog)), ((ctk_window_get_type ()))
))))
, title);
3072 else
3073 ctk_native_dialog_set_title (CTK_NATIVE_DIALOG (button->priv->native), title);
3074 g_object_notify (G_OBJECT (button)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((button)), (((GType) ((20) << (2))))))))
, "title");
3075}
3076
3077/**
3078 * ctk_file_chooser_button_get_title:
3079 * @button: the button widget to examine.
3080 *
3081 * Retrieves the title of the browse dialog used by @button. The returned value
3082 * should not be modified or freed.
3083 *
3084 * Returns: a pointer to the browse dialog’s title.
3085 *
3086 * Since: 2.6
3087 */
3088const gchar *
3089ctk_file_chooser_button_get_title (CtkFileChooserButton *button)
3090{
3091 g_return_val_if_fail (CTK_IS_FILE_CHOOSER_BUTTON (button), NULL)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((button)); GType __t = ((ctk_file_chooser_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 ("Ctk", ((const
char*) (__func__)), "CTK_IS_FILE_CHOOSER_BUTTON (button)"); return
(((void*)0)); } } while (0)
;
3092
3093 if (button->priv->dialog)
3094 return ctk_window_get_title (CTK_WINDOW (button->priv->dialog)((((CtkWindow*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((button->priv->dialog)), ((ctk_window_get_type ()))
))))
);
3095 else
3096 return ctk_native_dialog_get_title (CTK_NATIVE_DIALOG (button->priv->native));
3097}
3098
3099/**
3100 * ctk_file_chooser_button_get_width_chars:
3101 * @button: the button widget to examine.
3102 *
3103 * Retrieves the width in characters of the @button widget’s entry and/or label.
3104 *
3105 * Returns: an integer width (in characters) that the button will use to size itself.
3106 *
3107 * Since: 2.6
3108 */
3109gint
3110ctk_file_chooser_button_get_width_chars (CtkFileChooserButton *button)
3111{
3112 g_return_val_if_fail (CTK_IS_FILE_CHOOSER_BUTTON (button), -1)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((button)); GType __t = ((ctk_file_chooser_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 ("Ctk", ((const
char*) (__func__)), "CTK_IS_FILE_CHOOSER_BUTTON (button)"); return
(-1); } } while (0)
;
3113
3114 return ctk_label_get_width_chars (CTK_LABEL (button->priv->label)((((CtkLabel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((button->priv->label)), ((ctk_label_get_type ()))))
))
);
3115}
3116
3117/**
3118 * ctk_file_chooser_button_set_width_chars:
3119 * @button: the button widget to examine.
3120 * @n_chars: the new width, in characters.
3121 *
3122 * Sets the width (in characters) that @button will use to @n_chars.
3123 *
3124 * Since: 2.6
3125 */
3126void
3127ctk_file_chooser_button_set_width_chars (CtkFileChooserButton *button,
3128 gint n_chars)
3129{
3130 g_return_if_fail (CTK_IS_FILE_CHOOSER_BUTTON (button))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((button)); GType __t = ((ctk_file_chooser_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 ("Ctk", ((const
char*) (__func__)), "CTK_IS_FILE_CHOOSER_BUTTON (button)"); return
; } } while (0)
;
3131
3132 ctk_label_set_width_chars (CTK_LABEL (button->priv->label)((((CtkLabel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((button->priv->label)), ((ctk_label_get_type ()))))
))
, n_chars);
3133 g_object_notify (G_OBJECT (button)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((button)), (((GType) ((20) << (2))))))))
, "width-chars");
3134}
3135
3136/**
3137 * ctk_file_chooser_button_set_focus_on_click:
3138 * @button: a #CtkFileChooserButton
3139 * @focus_on_click: whether the button grabs focus when clicked with the mouse
3140 *
3141 * Sets whether the button will grab focus when it is clicked with the mouse.
3142 * Making mouse clicks not grab focus is useful in places like toolbars where
3143 * you don’t want the keyboard focus removed from the main area of the
3144 * application.
3145 *
3146 * Since: 2.10
3147 *
3148 * Deprecated: 3.20: Use ctk_widget_set_focus_on_click() instead
3149 */
3150void
3151ctk_file_chooser_button_set_focus_on_click (CtkFileChooserButton *button,
3152 gboolean focus_on_click)
3153{
3154 g_return_if_fail (CTK_IS_FILE_CHOOSER_BUTTON (button))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((button)); GType __t = ((ctk_file_chooser_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 ("Ctk", ((const
char*) (__func__)), "CTK_IS_FILE_CHOOSER_BUTTON (button)"); return
; } } while (0)
;
3155
3156 ctk_widget_set_focus_on_click (CTK_WIDGET (button)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((button)), ((ctk_widget_get_type ()))))))
, focus_on_click);
3157}
3158
3159/**
3160 * ctk_file_chooser_button_get_focus_on_click:
3161 * @button: a #CtkFileChooserButton
3162 *
3163 * Returns whether the button grabs focus when it is clicked with the mouse.
3164 * See ctk_file_chooser_button_set_focus_on_click().
3165 *
3166 * Returns: %TRUE if the button grabs focus when it is clicked with
3167 * the mouse.
3168 *
3169 * Since: 2.10
3170 *
3171 * Deprecated: 3.20: Use ctk_widget_get_focus_on_click() instead
3172 */
3173gboolean
3174ctk_file_chooser_button_get_focus_on_click (CtkFileChooserButton *button)
3175{
3176 g_return_val_if_fail (CTK_IS_FILE_CHOOSER_BUTTON (button), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((button)); GType __t = ((ctk_file_chooser_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 ("Ctk", ((const
char*) (__func__)), "CTK_IS_FILE_CHOOSER_BUTTON (button)"); return
((0)); } } while (0)
;
3177
3178 return ctk_widget_get_focus_on_click (CTK_WIDGET (button)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((button)), ((ctk_widget_get_type ()))))))
);
3179}