File: | ctk/ctkfilechooserbutton.c |
Warning: | line 1308, column 7 This statement is never executed |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
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 */ |
122 | enum |
123 | { |
124 | PROP_0, |
125 | |
126 | PROP_DIALOG, |
127 | PROP_TITLE, |
128 | PROP_WIDTH_CHARS |
129 | }; |
130 | |
131 | /* Signals */ |
132 | enum |
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 | */ |
142 | enum |
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 */ |
154 | typedef 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 | } |
169 | RowType; |
170 | |
171 | |
172 | /* ******************** * |
173 | * Private Structures * |
174 | * ******************** */ |
175 | |
176 | struct _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 | |
226 | enum |
227 | { |
228 | TEXT_PLAIN, |
229 | TEXT_URI_LIST |
230 | }; |
231 | |
232 | |
233 | /* ********************* * |
234 | * Function Prototypes * |
235 | * ********************* */ |
236 | |
237 | /* CtkFileChooserIface Functions */ |
238 | static void ctk_file_chooser_button_file_chooser_iface_init (CtkFileChooserIface *iface); |
239 | static gboolean ctk_file_chooser_button_set_current_folder (CtkFileChooser *chooser, |
240 | GFile *file, |
241 | GError **error); |
242 | static GFile *ctk_file_chooser_button_get_current_folder (CtkFileChooser *chooser); |
243 | static gboolean ctk_file_chooser_button_select_file (CtkFileChooser *chooser, |
244 | GFile *file, |
245 | GError **error); |
246 | static void ctk_file_chooser_button_unselect_file (CtkFileChooser *chooser, |
247 | GFile *file); |
248 | static void ctk_file_chooser_button_unselect_all (CtkFileChooser *chooser); |
249 | static GSList *ctk_file_chooser_button_get_files (CtkFileChooser *chooser); |
250 | static gboolean ctk_file_chooser_button_add_shortcut_folder (CtkFileChooser *chooser, |
251 | GFile *file, |
252 | GError **error); |
253 | static gboolean ctk_file_chooser_button_remove_shortcut_folder (CtkFileChooser *chooser, |
254 | GFile *file, |
255 | GError **error); |
256 | |
257 | /* GObject Functions */ |
258 | static void ctk_file_chooser_button_constructed (GObject *object); |
259 | static void ctk_file_chooser_button_set_property (GObject *object, |
260 | guint param_id, |
261 | const GValue *value, |
262 | GParamSpec *pspec); |
263 | static void ctk_file_chooser_button_get_property (GObject *object, |
264 | guint param_id, |
265 | GValue *value, |
266 | GParamSpec *pspec); |
267 | static void ctk_file_chooser_button_finalize (GObject *object); |
268 | |
269 | /* CtkWidget Functions */ |
270 | static void ctk_file_chooser_button_destroy (CtkWidget *widget); |
271 | static 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); |
278 | static void ctk_file_chooser_button_show_all (CtkWidget *widget); |
279 | static void ctk_file_chooser_button_show (CtkWidget *widget); |
280 | static void ctk_file_chooser_button_hide (CtkWidget *widget); |
281 | static void ctk_file_chooser_button_map (CtkWidget *widget); |
282 | static gboolean ctk_file_chooser_button_mnemonic_activate (CtkWidget *widget, |
283 | gboolean group_cycling); |
284 | static void ctk_file_chooser_button_style_updated (CtkWidget *widget); |
285 | static void ctk_file_chooser_button_screen_changed (CtkWidget *widget, |
286 | CdkScreen *old_screen); |
287 | static void ctk_file_chooser_button_state_flags_changed (CtkWidget *widget, |
288 | CtkStateFlags previous_state); |
289 | |
290 | /* Utility Functions */ |
291 | static CtkIconTheme *get_icon_theme (CtkWidget *widget); |
292 | static void set_info_for_file_at_iter (CtkFileChooserButton *fs, |
293 | GFile *file, |
294 | CtkTreeIter *iter); |
295 | |
296 | static gint model_get_type_position (CtkFileChooserButton *button, |
297 | RowType row_type); |
298 | static void model_free_row_data (CtkFileChooserButton *button, |
299 | CtkTreeIter *iter); |
300 | static void model_add_special (CtkFileChooserButton *button); |
301 | static void model_add_other (CtkFileChooserButton *button); |
302 | static void model_add_empty_selection (CtkFileChooserButton *button); |
303 | static void model_add_volumes (CtkFileChooserButton *button, |
304 | GSList *volumes); |
305 | static void model_add_bookmarks (CtkFileChooserButton *button, |
306 | GSList *bookmarks); |
307 | static void model_update_current_folder (CtkFileChooserButton *button, |
308 | GFile *file); |
309 | static void model_remove_rows (CtkFileChooserButton *button, |
310 | gint pos, |
311 | gint n_rows); |
312 | |
313 | static gboolean filter_model_visible_func (CtkTreeModel *model, |
314 | CtkTreeIter *iter, |
315 | gpointer user_data); |
316 | |
317 | static gboolean combo_box_row_separator_func (CtkTreeModel *model, |
318 | CtkTreeIter *iter, |
319 | gpointer user_data); |
320 | static void name_cell_data_func (CtkCellLayout *layout, |
321 | CtkCellRenderer *cell, |
322 | CtkTreeModel *model, |
323 | CtkTreeIter *iter, |
324 | gpointer user_data); |
325 | static void open_dialog (CtkFileChooserButton *button); |
326 | static void update_combo_box (CtkFileChooserButton *button); |
327 | static void update_label_and_image (CtkFileChooserButton *button); |
328 | |
329 | /* Child Object Callbacks */ |
330 | static void fs_volumes_changed_cb (CtkFileSystem *fs, |
331 | gpointer user_data); |
332 | static void bookmarks_changed_cb (gpointer user_data); |
333 | |
334 | static void combo_box_changed_cb (CtkComboBox *combo_box, |
335 | gpointer user_data); |
336 | static void combo_box_notify_popup_shown_cb (GObject *object, |
337 | GParamSpec *pspec, |
338 | gpointer user_data); |
339 | |
340 | static void button_clicked_cb (CtkButton *real_button, |
341 | gpointer user_data); |
342 | |
343 | static void chooser_update_preview_cb (CtkFileChooser *dialog, |
344 | gpointer user_data); |
345 | static void chooser_notify_cb (GObject *dialog, |
346 | GParamSpec *pspec, |
347 | gpointer user_data); |
348 | static gboolean dialog_delete_event_cb (CtkWidget *dialog, |
349 | CdkEvent *event, |
350 | gpointer user_data); |
351 | static void dialog_response_cb (CtkDialog *dialog, |
352 | gint response, |
353 | gpointer user_data); |
354 | static void native_response_cb (CtkFileChooserNative *native, |
355 | gint response, |
356 | gpointer user_data); |
357 | |
358 | static guint file_chooser_button_signals[LAST_SIGNAL] = { 0 }; |
359 | |
360 | /* ******************* * |
361 | * GType Declaration * |
362 | * ******************* */ |
363 | |
364 | G_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 | |
374 | static void |
375 | ctk_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 | |
484 | static void |
485 | ctk_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 | * ******************************* */ |
518 | static void |
519 | ctk_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 | |
533 | static void |
534 | emit_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 | |
545 | static gboolean |
546 | ctk_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 | |
568 | static GFile * |
569 | ctk_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 | |
580 | static gboolean |
581 | ctk_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 | |
604 | static void |
605 | unselect_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 | |
620 | static void |
621 | ctk_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 | |
634 | static void |
635 | ctk_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 | |
646 | static GFile * |
647 | get_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 | |
671 | static GSList * |
672 | ctk_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 | |
684 | static gboolean |
685 | ctk_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 | |
723 | static gboolean |
724 | ctk_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 | |
779 | static void |
780 | ctk_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 | |
866 | static void |
867 | ctk_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 | |
952 | static void |
953 | ctk_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 | |
989 | static void |
990 | ctk_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 | |
1014 | static void |
1015 | ctk_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 | |
1035 | static void |
1036 | ctk_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 | |
1109 | struct 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 | |
1120 | static void |
1121 | dnd_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 | |
1182 | static void |
1183 | ctk_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 | |
1254 | static void |
1255 | ctk_file_chooser_button_show_all (CtkWidget *widget) |
1256 | { |
1257 | ctk_widget_show (widget); |
1258 | } |
1259 | |
1260 | static void |
1261 | ctk_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 | |
1273 | static void |
1274 | ctk_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 | |
1288 | static void |
1289 | ctk_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 | |
1294 | static gboolean |
1295 | ctk_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 */ |
1318 | struct ChangeIconThemeData |
1319 | { |
1320 | CtkFileChooserButton *button; |
1321 | CtkTreeRowReference *row_ref; |
1322 | }; |
1323 | |
1324 | static void |
1325 | change_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 | |
1370 | out: |
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 | |
1378 | static void |
1379 | change_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 | |
1494 | static void |
1495 | ctk_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 | |
1510 | static void |
1511 | ctk_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 */ |
1527 | static CtkIconTheme * |
1528 | get_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 | |
1535 | struct SetDisplayNameData |
1536 | { |
1537 | CtkFileChooserButton *button; |
1538 | char *label; |
1539 | CtkTreeRowReference *row_ref; |
1540 | }; |
1541 | |
1542 | static void |
1543 | set_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 | |
1599 | out: |
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 | |
1608 | static void |
1609 | set_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 */ |
1635 | static gint |
1636 | model_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 | |
1693 | static void |
1694 | model_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 | |
1726 | static void |
1727 | model_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 | |
1783 | out: |
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 | |
1791 | static void |
1792 | model_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 | |
1878 | static void |
1879 | model_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 | |
1947 | extern gchar * _ctk_file_chooser_label_for_file (GFile *file); |
1948 | |
1949 | static void |
1950 | model_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 | |
2044 | static void |
2045 | model_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 | |
2138 | static void |
2139 | model_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 | |
2169 | static void |
2170 | model_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 | |
2189 | static void |
2190 | model_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 */ |
2216 | static gboolean |
2217 | test_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 | |
2234 | static gboolean |
2235 | filter_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 */ |
2325 | static void |
2326 | name_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 | |
2347 | static gboolean |
2348 | combo_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 | |
2361 | static void |
2362 | select_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 | |
2376 | static void |
2377 | update_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 */ |
2465 | static void |
2466 | update_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 | |
2491 | out: |
2492 | emit_selection_changed_if_changing_selection (button); |
2493 | |
2494 | g_object_unref (button); |
2495 | g_object_unref (cancellable); |
2496 | } |
2497 | |
2498 | static void |
2499 | update_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 | |
2585 | out: |
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 */ |
2611 | static void |
2612 | fs_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 | |
2635 | static void |
2636 | bookmarks_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 | |
2657 | static void |
2658 | save_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 | |
2672 | static void |
2673 | restore_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 */ |
2687 | static void |
2688 | open_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 */ |
2753 | static void |
2754 | combo_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 | */ |
2825 | static void |
2826 | combo_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 */ |
2860 | static void |
2861 | button_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 | |
2869 | static void |
2870 | chooser_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 | |
2876 | static void |
2877 | chooser_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 | |
2921 | static gboolean |
2922 | dialog_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 | |
2931 | static void |
2932 | common_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 | |
2964 | static void |
2965 | dialog_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 | |
2981 | static void |
2982 | native_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 | */ |
3013 | CtkWidget * |
3014 | ctk_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 | */ |
3045 | CtkWidget * |
3046 | ctk_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 | */ |
3064 | void |
3065 | ctk_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 | */ |
3088 | const gchar * |
3089 | ctk_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 | */ |
3109 | gint |
3110 | ctk_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 | */ |
3126 | void |
3127 | ctk_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 | */ |
3150 | void |
3151 | ctk_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 | */ |
3173 | gboolean |
3174 | ctk_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 | } |