Bug Summary

File:ctk/ctkfilesystemmodel.c
Warning:line 267, column 29
Casting a non-structure type to a structure type and accessing a field can lead to memory access errors or data corruption

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name ctkfilesystemmodel.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/ctk -resource-dir /usr/lib/llvm-16/lib/clang/16 -D HAVE_CONFIG_H -I . -I .. -D G_LOG_DOMAIN="Ctk" -D G_LOG_USE_STRUCTURED=1 -D CTK_VERSION="3.25.5" -D CTK_BINARY_VERSION="3.0.0" -D CTK_COMPILATION -D CTK_PRINT_BACKEND_ENABLE_UNSUPPORTED -D CTK_LIBDIR="/usr/lib" -D CTK_LOCALEDIR="/usr/share/locale" -D CTK_DATADIR="/usr/share" -D CTK_DATA_PREFIX="/usr" -D CTK_SYSCONFDIR="/usr/etc" -D CTK_HOST="x86_64-pc-linux-gnu" -D CTK_PRINT_BACKENDS="file,cups" -D X11_DATA_PREFIX="/usr" -D ISO_CODES_PREFIX="" -I .. -I ../ctk -I .. -I ../cdk -I /usr/include/glib-2.0 -I /usr/lib/x86_64-linux-gnu/glib-2.0/include -I /usr/include/sysprof-6 -D G_ENABLE_DEBUG -D G_ENABLE_CONSISTENCY_CHECKS -D GLIB_MIN_REQUIRED_VERSION=GLIB_VERSION_2_66 -D GLIB_MAX_ALLOWED_VERSION=GLIB_VERSION_2_66 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib/x86_64-linux-gnu/glib-2.0/include -I /usr/include/sysprof-6 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/atk-1.0 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/x86_64-linux-gnu -I /usr/include/webp -I /usr/include/at-spi2-atk/2.0 -I /usr/include/at-spi-2.0 -I /usr/include/dbus-1.0 -I /usr/lib/x86_64-linux-gnu/dbus-1.0/include -I /usr/include/gio-unix-2.0 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/glib-2.0 -I /usr/lib/x86_64-linux-gnu/glib-2.0/include -I /usr/include/sysprof-6 -I /usr/include/pango-1.0 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/cairo -I /usr/include/pixman-1 -D PIC -internal-isystem /usr/lib/llvm-16/lib/clang/16/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -fdebug-compilation-dir=/rootdir/ctk -ferror-limit 19 -fvisibility=hidden -fgnuc-version=4.2.1 -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2024-09-19-173409-43638-1 -x c ctkfilesystemmodel.c
1/* CTK - The GIMP Toolkit
2 * ctkfilesystemmodel.c: CtkTreeModel wrapping a CtkFileSystem
3 * Copyright (C) 2003, Red Hat, Inc.
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19#include "config.h"
20
21#include "ctkfilesystemmodel.h"
22
23#include <stdlib.h>
24#include <string.h>
25
26#include "ctkfilesystem.h"
27#include "ctkintl.h"
28#include "ctkmarshalers.h"
29#include "ctktreedatalist.h"
30#include "ctktreednd.h"
31#include "ctktreemodel.h"
32
33/*** Structure: how CtkFileSystemModel works
34 *
35 * This is a custom CtkTreeModel used to hold a collection of files for CtkFileChooser. There are two use cases:
36 *
37 * 1. The model populates itself from a folder, using the GIO file enumerator API. This happens if you use
38 * _ctk_file_system_model_new_for_directory(). This is the normal usage for showing the contents of a folder.
39 *
40 * 2. The caller populates the model by hand, with files not necessarily in the same folder. This happens
41 * if you use _ctk_file_system_model_new() and then _ctk_file_system_model_add_and_query_file(). This is
42 * the special kind of usage for “search” and “recent-files”, where the file chooser gives the model the
43 * files to be displayed.
44 *
45 * Internal data structure
46 * -----------------------
47 *
48 * Each file is kept in a FileModelNode structure. Each FileModelNode holds a GFile* and other data. All the
49 * node structures have the same size, determined at runtime, depending on the number of columns that were passed
50 * to _ctk_file_system_model_new() or _ctk_file_system_model_new_for_directory() (that is, the size of a node is
51 * not sizeof (FileModelNode), but rather model->node_size). The last field in the FileModelNode structure,
52 * node->values[], is an array of GValue, used to hold the data for those columns.
53 *
54 * The model stores an array of FileModelNode structures in model->files. This is a GArray where each element is
55 * model->node_size bytes in size (the model computes that node size when initializing itself). There are
56 * convenience macros, get_node() and node_index(), to access that array based on an array index or a pointer to
57 * a node inside the array.
58 *
59 * The model accesses files through two of its fields:
60 *
61 * model->files - GArray of FileModelNode structures.
62 *
63 * model->file_lookup - hash table that maps a GFile* to an index inside the model->files array.
64 *
65 * The model->file_lookup hash table is populated lazily. It is both accessed and populated with the
66 * node_get_for_file() function. The invariant is that the files in model->files[n] for n < g_hash_table_size
67 * (model->file_lookup) are already added to the hash table. The hash table will get cleared when we re-sort the
68 * files, as the array will be in a different order and the indexes need to be rebuilt.
69 *
70 * Each FileModelNode has a node->visible field, which indicates whether the node is visible in the CtkTreeView.
71 * A node may be invisible if, for example, it corresponds to a hidden file and the file chooser is not showing
72 * hidden files. Also, a file filter may be explicitly set onto the model, for example, to only show files that
73 * match “*.jpg”. In this case, node->filtered_out says whether the node failed the filter. The ultimate
74 * decision on whether a node is visible or not in the treeview is distilled into the node->visible field.
75 * The reason for having a separate node->filtered_out field is so that the file chooser can query whether
76 * a (filtered-out) folder should be made sensitive in the GUI.
77 *
78 * Visible rows vs. possibly-invisible nodes
79 * -----------------------------------------
80 *
81 * Since not all nodes in the model->files array may be visible, we need a way to map visible row indexes from
82 * the treeview to array indexes in our array of files. And thus we introduce a bit of terminology:
83 *
84 * index - An index in the model->files array. All variables/fields that represent indexes are either called
85 * “index” or “i_*”, or simply “i” for things like loop counters.
86 *
87 * row - An index in the CtkTreeView, i.e. the index of a row within the outward-facing API of the
88 * CtkFileSystemModel. However, note that our rows are 1-based, not 0-based, for the reason explained in the
89 * following paragraph. Variables/fields that represent visible rows are called “row”, or “r_*”, or simply
90 * “r”.
91 *
92 * Each FileModelNode has a node->row field which is the number of visible rows in the treeview, *before and
93 * including* that node. This means that node->row is 1-based, instead of 0-based --- this makes some code
94 * simpler, believe it or not :) This also means that when the calling CtkTreeView gives us a CtkTreePath, we
95 * turn the 0-based treepath into a 1-based row for our purposes. If a node is not visible, it will have the
96 * same row number as its closest preceding visible node.
97 *
98 * We try to compute the node->row fields lazily. A node is said to be “valid” if its node->row is accurate.
99 * For this, the model keeps a model->n_nodes_valid field which is the count of valid nodes starting from the
100 * beginning of the model->files array. When a node changes its information, or when a node gets deleted, that
101 * node and the following ones get invalidated by simply setting model->n_nodes_valid to the array index of the
102 * node. If the model happens to need a node’s row number and that node is in the model->files array after
103 * model->n_nodes_valid, then the nodes get re-validated up to the sought node. See node_validate_rows() for
104 * this logic.
105 *
106 * You never access a node->row directly. Instead, call node_get_tree_row(). That function will validate the nodes
107 * up to the sought one if the node is not valid yet, and it will return a proper 0-based row.
108 *
109 * Sorting
110 * -------
111 *
112 * The model implements the CtkTreeSortable interface. To avoid re-sorting
113 * every time a node gets added (which would lead to O(n^2) performance during
114 * the initial population of the model), the model can freeze itself (with
115 * freeze_updates()) during the intial population process. When the model is
116 * frozen, sorting will not happen. The model will sort itself when the freeze
117 * count goes back to zero, via corresponding calls to thaw_updates().
118 */
119
120/*** DEFINES ***/
121
122/* priority used for all async callbacks in the main loop
123 * This should be higher than redraw priorities so multiple callbacks
124 * firing can be handled without intermediate redraws */
125#define IO_PRIORITY0 G_PRIORITY_DEFAULT0
126
127/* random number that everyone else seems to use, too */
128#define FILES_PER_QUERY100 100
129
130typedef struct _FileModelNode FileModelNode;
131typedef struct _CtkFileSystemModelClass CtkFileSystemModelClass;
132
133struct _FileModelNode
134{
135 GFile * file; /* file represented by this node or NULL for editable */
136 GFileInfo * info; /* info for this file or NULL if unknown */
137
138 guint row; /* if valid (see model->n_valid_indexes), visible nodes before and including
139 * this one - see the "Structure" comment above.
140 */
141
142 guint visible :1; /* if the file is currently visible */
143 guint filtered_out :1;/* if the file is currently filtered out (i.e. it didn't pass the filters) */
144 guint frozen_add :1; /* true if the model was frozen and the entry has not been added yet */
145
146 GValue values[1]; /* actually n_columns values */
147};
148
149struct _CtkFileSystemModel
150{
151 GObject parent_instance;
152
153 GFile * dir; /* directory that's displayed */
154 guint dir_thaw_source;/* GSource id for unfreezing the model */
155 char * attributes; /* attributes the file info must contain, or NULL for all attributes */
156 GFileMonitor * dir_monitor; /* directory that is monitored, or NULL if monitoring was not supported */
157
158 GCancellable * cancellable; /* cancellable in use for all operations - cancelled on dispose */
159 GArray * files; /* array of FileModelNode containing all our files */
160 gsize node_size; /* Size of a FileModelNode structure once its ->values field has n_columns */
161 guint n_nodes_valid; /* count of valid nodes (i.e. those whose node->row is accurate) */
162 GHashTable * file_lookup; /* mapping of GFile => array index in model->files
163 * This hash table doesn't always have the same number of entries as the files array;
164 * it can get cleared completely when we resort.
165 * The hash table gets re-populated in node_get_for_file() if this mismatch is
166 * detected.
167 */
168
169 guint n_columns; /* number of columns */
170 GType * column_types; /* types of each column */
171 CtkFileSystemModelGetValue get_func; /* function to call to fill in values in columns */
172 gpointer get_data; /* data to pass to get_func */
173
174 CtkFileFilter * filter; /* filter to use for deciding which nodes are visible */
175
176 int sort_column_id; /* current sorting column */
177 CtkSortType sort_order; /* current sorting order */
178 GList * sort_list; /* list of sorting functions */
179 CtkTreeIterCompareFunc default_sort_func; /* default sort function */
180 gpointer default_sort_data; /* data to pass to default sort func */
181 GDestroyNotify default_sort_destroy; /* function to call to destroy default_sort_data */
182
183 guint frozen; /* number of times we're frozen */
184
185 gboolean filter_on_thaw :1;/* set when filtering needs to happen upon thawing */
186 gboolean sort_on_thaw :1;/* set when sorting needs to happen upon thawing */
187
188 guint show_hidden :1; /* whether to show hidden files */
189 guint show_folders :1;/* whether to show folders */
190 guint show_files :1; /* whether to show files */
191 guint filter_folders :1;/* whether filter applies to folders */
192};
193
194#define CTK_FILE_SYSTEM_MODEL_CLASS(klass)((((CtkFileSystemModelClass*) (void *) g_type_check_class_cast
((GTypeClass*) ((klass)), ((_ctk_file_system_model_get_type (
)))))))
(G_TYPE_CHECK_CLASS_CAST ((klass), CTK_TYPE_FILE_SYSTEM_MODEL, CtkFileSystemModelClass)(((CtkFileSystemModelClass*) (void *) g_type_check_class_cast
((GTypeClass*) ((klass)), ((_ctk_file_system_model_get_type (
))))))
)
195#define CTK_IS_FILE_SYSTEM_MODEL_CLASS(klass)(((__extension__ ({ GTypeClass *__class = (GTypeClass*) ((klass
)); GType __t = ((_ctk_file_system_model_get_type ())); gboolean
__r; if (!__class) __r = (0); else if (__class->g_type ==
__t) __r = (!(0)); else __r = g_type_check_class_is_a (__class
, __t); __r; }))))
(G_TYPE_CHECK_CLASS_TYPE ((klass), CTK_TYPE_FILE_SYSTEM_MODEL)((__extension__ ({ GTypeClass *__class = (GTypeClass*) ((klass
)); GType __t = ((_ctk_file_system_model_get_type ())); gboolean
__r; if (!__class) __r = (0); else if (__class->g_type ==
__t) __r = (!(0)); else __r = g_type_check_class_is_a (__class
, __t); __r; })))
)
196#define CTK_FILE_SYSTEM_MODEL_GET_CLASS(obj)((((CtkFileSystemModelClass*) (((GTypeInstance*) ((obj)))->
g_class))))
(G_TYPE_INSTANCE_GET_CLASS ((obj), CTK_TYPE_FILE_SYSTEM_MODEL, CtkFileSystemModelClass)(((CtkFileSystemModelClass*) (((GTypeInstance*) ((obj)))->
g_class)))
)
197
198struct _CtkFileSystemModelClass
199{
200 GObjectClass parent_class;
201
202 /* Signals */
203
204 void (*finished_loading) (CtkFileSystemModel *model, GError *error);
205};
206
207static void freeze_updates (CtkFileSystemModel *model);
208static void thaw_updates (CtkFileSystemModel *model);
209
210static guint node_get_for_file (CtkFileSystemModel *model,
211 GFile *file);
212
213static void add_file (CtkFileSystemModel *model,
214 GFile *file,
215 GFileInfo *info);
216static void remove_file (CtkFileSystemModel *model,
217 GFile *file);
218
219/* iter setup:
220 * @user_data: the model
221 * @user_data2: GUINT_TO_POINTER of array index of current entry
222 *
223 * All other fields are unused. Note that the array index does not corrspond
224 * 1:1 with the path index as entries might not be visible.
225 */
226#define ITER_INDEX(iter)((guint) (gulong) ((iter)->user_data2)) GPOINTER_TO_UINT((iter)->user_data2)((guint) (gulong) ((iter)->user_data2))
227#define ITER_IS_VALID(model, iter)((model) == (iter)->user_data) ((model) == (iter)->user_data)
228#define ITER_INIT_FROM_INDEX(model, _iter, _index)do { do { if (_index < (model)->files->len) ; else g_assertion_message_expr
("Ctk", "ctkfilesystemmodel.c", 228, ((const char*) (__func__
)), "_index < (model)->files->len"); } while (0); (_iter
)->user_data = (model); (_iter)->user_data2 = ((gpointer
) (gulong) (_index)); }while (0)
G_STMT_STARTdo {\
229 g_assert (_index < (model)->files->len)do { if (_index < (model)->files->len) ; else g_assertion_message_expr
("Ctk", "ctkfilesystemmodel.c", 229, ((const char*) (__func__
)), "_index < (model)->files->len"); } while (0)
; \
230 (_iter)->user_data = (model); \
231 (_iter)->user_data2 = GUINT_TO_POINTER (_index)((gpointer) (gulong) (_index)); \
232}G_STMT_ENDwhile (0)
233
234/*** FileModelNode ***/
235
236/* Get a FileModelNode structure given an index in the model->files array of nodes */
237#define get_node(_model, _index)((FileModelNode *) ((_model)->files->data + (_index) * (
_model)->node_size))
((FileModelNode *) ((_model)->files->data + (_index) * (_model)->node_size))
238
239/* Get an index within the model->files array of nodes, given a FileModelNode* */
240#define node_index(_model, _node)(((gchar *) (_node) - (_model)->files->data) / (_model)
->node_size)
(((gchar *) (_node) - (_model)->files->data) / (_model)->node_size)
241
242/* @up_to_index: smallest model->files array index that will be valid after this call
243 * @up_to_row: smallest node->row that will be valid after this call
244 *
245 * If you want to validate up to an index or up to a row, specify the index or
246 * the row you want and specify G_MAXUINT for the other argument. Pass
247 * G_MAXUINT for both arguments for “validate everything”.
248 */
249static void
250node_validate_rows (CtkFileSystemModel *model, guint up_to_index, guint up_to_row)
251{
252 guint i, row;
253
254 if (model->files->len == 0)
255 return;
256
257 up_to_index = MIN (up_to_index, model->files->len - 1)(((up_to_index) < (model->files->len - 1)) ? (up_to_index
) : (model->files->len - 1))
;
258
259 i = model->n_nodes_valid;
260 if (i != 0)
261 row = get_node (model, i - 1)((FileModelNode *) ((model)->files->data + (i - 1) * (model
)->node_size))
->row;
262 else
263 row = 0;
264
265 while (i <= up_to_index && row <= up_to_row)
266 {
267 FileModelNode *node = get_node (model, i)((FileModelNode *) ((model)->files->data + (i) * (model
)->node_size))
;
Casting a non-structure type to a structure type and accessing a field can lead to memory access errors or data corruption
268 if (node->visible)
269 row++;
270 node->row = row;
271 i++;
272 }
273 model->n_nodes_valid = i;
274}
275
276static guint
277node_get_tree_row (CtkFileSystemModel *model, guint index)
278{
279 if (model->n_nodes_valid <= index)
280 node_validate_rows (model, index, G_MAXUINT(2147483647 *2U +1U));
281
282 return get_node (model, index)((FileModelNode *) ((model)->files->data + (index) * (model
)->node_size))
->row - 1;
283}
284
285static void
286node_invalidate_index (CtkFileSystemModel *model, guint id)
287{
288 model->n_nodes_valid = MIN (model->n_nodes_valid, id)(((model->n_nodes_valid) < (id)) ? (model->n_nodes_valid
) : (id))
;
289}
290
291static CtkTreePath *
292tree_path_new_from_node (CtkFileSystemModel *model, guint id)
293{
294 guint r = node_get_tree_row (model, id);
295
296 g_assert (r < model->files->len)do { if (r < model->files->len) ; else g_assertion_message_expr
("Ctk", "ctkfilesystemmodel.c", 296, ((const char*) (__func__
)), "r < model->files->len"); } while (0)
;
297
298 return ctk_tree_path_new_from_indices (r, -1);
299}
300
301static void
302emit_row_inserted_for_node (CtkFileSystemModel *model, guint id)
303{
304 CtkTreePath *path;
305 CtkTreeIter iter;
306
307 path = tree_path_new_from_node (model, id);
308 ITER_INIT_FROM_INDEX (model, &iter, id)do { do { if (id < (model)->files->len) ; else g_assertion_message_expr
("Ctk", "ctkfilesystemmodel.c", 308, ((const char*) (__func__
)), "id < (model)->files->len"); } while (0); (&
iter)->user_data = (model); (&iter)->user_data2 = (
(gpointer) (gulong) (id)); }while (0)
;
309 ctk_tree_model_row_inserted (CTK_TREE_MODEL (model)((((CtkTreeModel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((model)), ((ctk_tree_model_get_type ()))))))
, path, &iter);
310 ctk_tree_path_free (path);
311}
312
313static void
314emit_row_changed_for_node (CtkFileSystemModel *model, guint id)
315{
316 CtkTreePath *path;
317 CtkTreeIter iter;
318
319 path = tree_path_new_from_node (model, id);
320 ITER_INIT_FROM_INDEX (model, &iter, id)do { do { if (id < (model)->files->len) ; else g_assertion_message_expr
("Ctk", "ctkfilesystemmodel.c", 320, ((const char*) (__func__
)), "id < (model)->files->len"); } while (0); (&
iter)->user_data = (model); (&iter)->user_data2 = (
(gpointer) (gulong) (id)); }while (0)
;
321 ctk_tree_model_row_changed (CTK_TREE_MODEL (model)((((CtkTreeModel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((model)), ((ctk_tree_model_get_type ()))))))
, path, &iter);
322 ctk_tree_path_free (path);
323}
324
325static void
326emit_row_deleted_for_row (CtkFileSystemModel *model, guint row)
327{
328 CtkTreePath *path;
329
330 path = ctk_tree_path_new_from_indices (row, -1);
331 ctk_tree_model_row_deleted (CTK_TREE_MODEL (model)((((CtkTreeModel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((model)), ((ctk_tree_model_get_type ()))))))
, path);
332 ctk_tree_path_free (path);
333}
334
335static void
336node_set_visible_and_filtered_out (CtkFileSystemModel *model, guint id, gboolean visible, gboolean filtered_out)
337{
338 FileModelNode *node = get_node (model, id)((FileModelNode *) ((model)->files->data + (id) * (model
)->node_size))
;
339
340 /* Filteredness */
341
342 if (node->filtered_out != filtered_out)
343 {
344 node->filtered_out = filtered_out;
345 if (node->visible && visible)
346 emit_row_changed_for_node (model, id);
347 }
348
349 /* Visibility */
350
351 if (node->visible == visible ||
352 node->frozen_add)
353 return;
354
355 if (visible)
356 {
357 node->visible = TRUE(!(0));
358 node_invalidate_index (model, id);
359 emit_row_inserted_for_node (model, id);
360 }
361 else
362 {
363 guint row;
364
365 row = node_get_tree_row (model, id);
366 g_assert (row < model->files->len)do { if (row < model->files->len) ; else g_assertion_message_expr
("Ctk", "ctkfilesystemmodel.c", 366, ((const char*) (__func__
)), "row < model->files->len"); } while (0)
;
367
368 node->visible = FALSE(0);
369 node_invalidate_index (model, id);
370 emit_row_deleted_for_row (model, row);
371 }
372}
373
374static gboolean
375node_should_be_filtered_out (CtkFileSystemModel *model, guint id)
376{
377 FileModelNode *node = get_node (model, id)((FileModelNode *) ((model)->files->data + (id) * (model
)->node_size))
;
378 CtkFileFilterInfo filter_info = { 0, };
379 CtkFileFilterFlags required;
380 gboolean result;
381 char *mime_type = NULL((void*)0);
382 char *filename = NULL((void*)0);
383 char *uri = NULL((void*)0);
384
385 if (node->info == NULL((void*)0))
386 return TRUE(!(0));
387
388 if (model->filter == NULL((void*)0))
389 return FALSE(0);
390
391 /* fill info */
392 required = ctk_file_filter_get_needed (model->filter);
393
394 filter_info.contains = CTK_FILE_FILTER_DISPLAY_NAME;
395 filter_info.display_name = g_file_info_get_display_name (node->info);
396
397 if (required & CTK_FILE_FILTER_MIME_TYPE)
398 {
399 const char *s = g_file_info_get_content_type (node->info);
400
401 if (!s)
402 s = g_file_info_get_attribute_string (node->info, G_FILE_ATTRIBUTE_STANDARD_FAST_CONTENT_TYPE"standard::fast-content-type");
403
404 if (s)
405 {
406 mime_type = g_content_type_get_mime_type (s);
407 if (mime_type)
408 {
409 filter_info.mime_type = mime_type;
410 filter_info.contains |= CTK_FILE_FILTER_MIME_TYPE;
411 }
412 }
413 }
414
415 if (required & CTK_FILE_FILTER_FILENAME)
416 {
417 filename = g_file_get_path (node->file);
418 if (filename)
419 {
420 filter_info.filename = filename;
421 filter_info.contains |= CTK_FILE_FILTER_FILENAME;
422 }
423 }
424
425 if (required & CTK_FILE_FILTER_URI)
426 {
427 uri = g_file_get_uri (node->file);
428 if (uri)
429 {
430 filter_info.uri = uri;
431 filter_info.contains |= CTK_FILE_FILTER_URI;
432 }
433 }
434
435 result = !ctk_file_filter_filter (model->filter, &filter_info);
436
437 g_free (mime_type);
438 g_free (filename);
439 g_free (uri);
440
441 return result;
442}
443
444static gboolean
445node_should_be_visible (CtkFileSystemModel *model, guint id, gboolean filtered_out)
446{
447 FileModelNode *node = get_node (model, id)((FileModelNode *) ((model)->files->data + (id) * (model
)->node_size))
;
448 gboolean result;
449
450 if (node->info == NULL((void*)0))
451 return FALSE(0);
452
453 if (!model->show_hidden &&
454 (g_file_info_get_is_hidden (node->info) || g_file_info_get_is_backup (node->info)))
455 return FALSE(0);
456
457 if (_ctk_file_info_consider_as_directory (node->info))
458 {
459 if (!model->show_folders)
460 return FALSE(0);
461
462 if (!model->filter_folders)
463 return TRUE(!(0));
464 }
465 else
466 {
467 if (!model->show_files)
468 return FALSE(0);
469 }
470
471 result = !filtered_out;
472
473 return result;
474}
475
476static void
477node_compute_visibility_and_filters (CtkFileSystemModel *model, guint id)
478{
479 gboolean filtered_out;
480 gboolean visible;
481
482 filtered_out = node_should_be_filtered_out (model, id);
483 visible = node_should_be_visible (model, id, filtered_out);
484
485 node_set_visible_and_filtered_out (model, id, visible, filtered_out);
486}
487
488/*** CtkTreeModel ***/
489
490static CtkTreeModelFlags
491ctk_file_system_model_get_flags (CtkTreeModel *tree_model G_GNUC_UNUSED__attribute__ ((__unused__)))
492{
493 /* CTK_TREE_MODEL_ITERS_PERSIST doesn't work with arrays :( */
494 return CTK_TREE_MODEL_LIST_ONLY;
495}
496
497static gint
498ctk_file_system_model_get_n_columns (CtkTreeModel *tree_model)
499{
500 CtkFileSystemModel *model = CTK_FILE_SYSTEM_MODEL (tree_model)((((CtkFileSystemModel*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((tree_model)), ((_ctk_file_system_model_get_type
()))))))
;
501
502 return model->n_columns;
503}
504
505static GType
506ctk_file_system_model_get_column_type (CtkTreeModel *tree_model,
507 gint i)
508{
509 CtkFileSystemModel *model = CTK_FILE_SYSTEM_MODEL (tree_model)((((CtkFileSystemModel*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((tree_model)), ((_ctk_file_system_model_get_type
()))))))
;
510
511 g_return_val_if_fail (i >= 0 && (guint) i < model->n_columns, G_TYPE_NONE)do { if ((i >= 0 && (guint) i < model->n_columns
)) { } else { g_return_if_fail_warning ("Ctk", ((const char*)
(__func__)), "i >= 0 && (guint) i < model->n_columns"
); return (((GType) ((1) << (2)))); } } while (0)
;
512
513 return model->column_types[i];
514}
515
516static int
517compare_indices (gconstpointer key, gconstpointer _node)
518{
519 const FileModelNode *node = _node;
520
521 return GPOINTER_TO_UINT (key)((guint) (gulong) (key)) - node->row;
522}
523
524static gboolean
525ctk_file_system_model_iter_nth_child (CtkTreeModel *tree_model,
526 CtkTreeIter *iter,
527 CtkTreeIter *parent,
528 gint n)
529{
530 CtkFileSystemModel *model = CTK_FILE_SYSTEM_MODEL (tree_model)((((CtkFileSystemModel*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((tree_model)), ((_ctk_file_system_model_get_type
()))))))
;
531 guint id;
532 guint row_to_find;
533
534 g_return_val_if_fail (n >= 0, FALSE)do { if ((n >= 0)) { } else { g_return_if_fail_warning ("Ctk"
, ((const char*) (__func__)), "n >= 0"); return ((0)); } }
while (0)
;
535
536 if (parent != NULL((void*)0))
537 return FALSE(0);
538
539 row_to_find = n + 1; /* plus one as our node->row numbers are 1-based; see the "Structure" comment at the beginning */
540
541 if (model->n_nodes_valid > 0 &&
542 get_node (model, model->n_nodes_valid - 1)((FileModelNode *) ((model)->files->data + (model->n_nodes_valid
- 1) * (model)->node_size))
->row >= row_to_find)
543 {
544 char *node;
545
546 /* Fast path - the nodes are valid up to the sought one.
547 *
548 * First, find a node with the sought row number...*/
549
550 node = bsearch (GUINT_TO_POINTER (row_to_find)((gpointer) (gulong) (row_to_find)),
551 model->files->data,
552 model->n_nodes_valid,
553 model->node_size,
554 compare_indices);
555 if (node == NULL((void*)0))
556 return FALSE(0);
557
558 /* ... Second, back up until we find the first visible node with that row number */
559
560 id = node_index (model, node)(((gchar *) (node) - (model)->files->data) / (model)->
node_size)
;
561 while (!get_node (model, id)((FileModelNode *) ((model)->files->data + (id) * (model
)->node_size))
->visible)
562 id--;
563
564 g_assert (get_node (model, id)->row == row_to_find)do { if (((FileModelNode *) ((model)->files->data + (id
) * (model)->node_size))->row == row_to_find) ; else g_assertion_message_expr
("Ctk", "ctkfilesystemmodel.c", 564, ((const char*) (__func__
)), "get_node (model, id)->row == row_to_find"); } while (
0)
;
565 }
566 else
567 {
568 /* Slow path - the nodes need to be validated up to the sought one */
569
570 node_validate_rows (model, G_MAXUINT(2147483647 *2U +1U), n); /* note that this is really "n", not row_to_find - see node_validate_rows() */
571 id = model->n_nodes_valid - 1;
572 if (model->n_nodes_valid == 0 || get_node (model, id)((FileModelNode *) ((model)->files->data + (id) * (model
)->node_size))
->row != row_to_find)
573 return FALSE(0);
574 }
575
576 ITER_INIT_FROM_INDEX (model, iter, id)do { do { if (id < (model)->files->len) ; else g_assertion_message_expr
("Ctk", "ctkfilesystemmodel.c", 576, ((const char*) (__func__
)), "id < (model)->files->len"); } while (0); (iter)
->user_data = (model); (iter)->user_data2 = ((gpointer)
(gulong) (id)); }while (0)
;
577 return TRUE(!(0));
578}
579
580static gboolean
581ctk_file_system_model_get_iter (CtkTreeModel *tree_model,
582 CtkTreeIter *iter,
583 CtkTreePath *path)
584{
585 g_return_val_if_fail (ctk_tree_path_get_depth (path) > 0, FALSE)do { if ((ctk_tree_path_get_depth (path) > 0)) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "ctk_tree_path_get_depth (path) > 0"
); return ((0)); } } while (0)
;
586
587 if (ctk_tree_path_get_depth (path) > 1)
588 return FALSE(0);
589
590 return ctk_file_system_model_iter_nth_child (tree_model,
591 iter,
592 NULL((void*)0),
593 ctk_tree_path_get_indices (path)[0]);
594}
595
596static CtkTreePath *
597ctk_file_system_model_get_path (CtkTreeModel *tree_model,
598 CtkTreeIter *iter)
599{
600 CtkFileSystemModel *model = CTK_FILE_SYSTEM_MODEL (tree_model)((((CtkFileSystemModel*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((tree_model)), ((_ctk_file_system_model_get_type
()))))))
;
601
602 g_return_val_if_fail (ITER_IS_VALID (model, iter), NULL)do { if ((((model) == (iter)->user_data))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "ITER_IS_VALID (model, iter)"
); return (((void*)0)); } } while (0)
;
603
604 return tree_path_new_from_node (model, ITER_INDEX (iter)((guint) (gulong) ((iter)->user_data2)));
605}
606
607static void
608ctk_file_system_model_get_value (CtkTreeModel *tree_model,
609 CtkTreeIter *iter,
610 gint column,
611 GValue *value)
612{
613 CtkFileSystemModel *model = CTK_FILE_SYSTEM_MODEL (tree_model)((((CtkFileSystemModel*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((tree_model)), ((_ctk_file_system_model_get_type
()))))))
;
614 const GValue *original;
615
616 g_return_if_fail ((guint) column < model->n_columns)do { if (((guint) column < model->n_columns)) { } else {
g_return_if_fail_warning ("Ctk", ((const char*) (__func__)),
"(guint) column < model->n_columns"); return; } } while
(0)
;
617 g_return_if_fail (ITER_IS_VALID (model, iter))do { if ((((model) == (iter)->user_data))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "ITER_IS_VALID (model, iter)"
); return; } } while (0)
;
618
619 original = _ctk_file_system_model_get_value (model, iter, column);
620 if (original)
621 {
622 g_value_init (value, G_VALUE_TYPE (original)(((GValue*) (original))->g_type));
623 g_value_copy (original, value);
624 }
625 else
626 g_value_init (value, model->column_types[column]);
627}
628
629static gboolean
630ctk_file_system_model_iter_next (CtkTreeModel *tree_model,
631 CtkTreeIter *iter)
632{
633 CtkFileSystemModel *model = CTK_FILE_SYSTEM_MODEL (tree_model)((((CtkFileSystemModel*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((tree_model)), ((_ctk_file_system_model_get_type
()))))))
;
634 guint i;
635
636 g_return_val_if_fail (ITER_IS_VALID (model, iter), FALSE)do { if ((((model) == (iter)->user_data))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "ITER_IS_VALID (model, iter)"
); return ((0)); } } while (0)
;
637
638 for (i = ITER_INDEX (iter)((guint) (gulong) ((iter)->user_data2)) + 1; i < model->files->len; i++)
639 {
640 FileModelNode *node = get_node (model, i)((FileModelNode *) ((model)->files->data + (i) * (model
)->node_size))
;
641
642 if (node->visible)
643 {
644 ITER_INIT_FROM_INDEX (model, iter, i)do { do { if (i < (model)->files->len) ; else g_assertion_message_expr
("Ctk", "ctkfilesystemmodel.c", 644, ((const char*) (__func__
)), "i < (model)->files->len"); } while (0); (iter)->
user_data = (model); (iter)->user_data2 = ((gpointer) (gulong
) (i)); }while (0)
;
645 return TRUE(!(0));
646 }
647 }
648
649 return FALSE(0);
650}
651
652static gboolean
653ctk_file_system_model_iter_children (CtkTreeModel *tree_model G_GNUC_UNUSED__attribute__ ((__unused__)),
654 CtkTreeIter *iter G_GNUC_UNUSED__attribute__ ((__unused__)),
655 CtkTreeIter *parent G_GNUC_UNUSED__attribute__ ((__unused__)))
656{
657 return FALSE(0);
658}
659
660static gboolean
661ctk_file_system_model_iter_has_child (CtkTreeModel *tree_model G_GNUC_UNUSED__attribute__ ((__unused__)),
662 CtkTreeIter *iter G_GNUC_UNUSED__attribute__ ((__unused__)))
663{
664 return FALSE(0);
665}
666
667static gint
668ctk_file_system_model_iter_n_children (CtkTreeModel *tree_model,
669 CtkTreeIter *iter)
670{
671 CtkFileSystemModel *model = CTK_FILE_SYSTEM_MODEL (tree_model)((((CtkFileSystemModel*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((tree_model)), ((_ctk_file_system_model_get_type
()))))))
;
672
673 if (iter)
674 return 0;
675
676 return node_get_tree_row (model, model->files->len - 1) + 1;
677}
678
679static gboolean
680ctk_file_system_model_iter_parent (CtkTreeModel *tree_model G_GNUC_UNUSED__attribute__ ((__unused__)),
681 CtkTreeIter *iter G_GNUC_UNUSED__attribute__ ((__unused__)),
682 CtkTreeIter *child G_GNUC_UNUSED__attribute__ ((__unused__)))
683{
684 return FALSE(0);
685}
686
687static void
688ctk_file_system_model_ref_node (CtkTreeModel *tree_model G_GNUC_UNUSED__attribute__ ((__unused__)),
689 CtkTreeIter *iter G_GNUC_UNUSED__attribute__ ((__unused__)))
690{
691 /* nothing to do */
692}
693
694static void
695ctk_file_system_model_unref_node (CtkTreeModel *tree_model G_GNUC_UNUSED__attribute__ ((__unused__)),
696 CtkTreeIter *iter G_GNUC_UNUSED__attribute__ ((__unused__)))
697{
698 /* nothing to do */
699}
700
701static void
702ctk_file_system_model_iface_init (CtkTreeModelIface *iface)
703{
704 iface->get_flags = ctk_file_system_model_get_flags;
705 iface->get_n_columns = ctk_file_system_model_get_n_columns;
706 iface->get_column_type = ctk_file_system_model_get_column_type;
707 iface->get_iter = ctk_file_system_model_get_iter;
708 iface->get_path = ctk_file_system_model_get_path;
709 iface->get_value = ctk_file_system_model_get_value;
710 iface->iter_next = ctk_file_system_model_iter_next;
711 iface->iter_children = ctk_file_system_model_iter_children;
712 iface->iter_has_child = ctk_file_system_model_iter_has_child;
713 iface->iter_n_children = ctk_file_system_model_iter_n_children;
714 iface->iter_nth_child = ctk_file_system_model_iter_nth_child;
715 iface->iter_parent = ctk_file_system_model_iter_parent;
716 iface->ref_node = ctk_file_system_model_ref_node;
717 iface->unref_node = ctk_file_system_model_unref_node;
718}
719
720/*** CtkTreeSortable ***/
721
722typedef struct _SortData SortData;
723struct _SortData {
724 CtkFileSystemModel * model;
725 CtkTreeIterCompareFunc func;
726 gpointer data;
727 int order; /* -1 to invert sort order or 1 to keep it */
728};
729
730/* returns FALSE if no sort necessary */
731static gboolean
732sort_data_init (SortData *data, CtkFileSystemModel *model)
733{
734 CtkTreeDataSortHeader *header;
735
736 if (model->files->len <= 2)
737 return FALSE(0);
738
739 switch (model->sort_column_id)
740 {
741 case CTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID(-1):
742 if (!model->default_sort_func)
743 return FALSE(0);
744 data->func = model->default_sort_func;
745 data->data = model->default_sort_data;
746 break;
747 case CTK_TREE_SORTABLE_UNSORTED_SORT_COLUMN_ID(-2):
748 return FALSE(0);
749 default:
750 header = _ctk_tree_data_list_get_header (model->sort_list, model->sort_column_id);
751 if (header == NULL((void*)0))
752 return FALSE(0);
753 data->func = header->func;
754 data->data = header->data;
755 break;
756 }
757
758 data->order = model->sort_order == CTK_SORT_DESCENDING ? -1 : 1;
759 data->model = model;
760 return TRUE(!(0));
761}
762
763static int
764compare_array_element (gconstpointer a, gconstpointer b, gpointer user_data)
765{
766 SortData *data = user_data;
767 CtkTreeIter itera, iterb;
768
769 ITER_INIT_FROM_INDEX (data->model, &itera, node_index (data->model, a))do { do { if ((((gchar *) (a) - (data->model)->files->
data) / (data->model)->node_size) < (data->model)
->files->len) ; else g_assertion_message_expr ("Ctk", "ctkfilesystemmodel.c"
, 769, ((const char*) (__func__)), "(((gchar *) (a) - (data->model)->files->data) / (data->model)->node_size) < (data->model)->files->len"
); } while (0); (&itera)->user_data = (data->model)
; (&itera)->user_data2 = ((gpointer) (gulong) ((((gchar
*) (a) - (data->model)->files->data) / (data->model
)->node_size))); }while (0)
;
770 ITER_INIT_FROM_INDEX (data->model, &iterb, node_index (data->model, b))do { do { if ((((gchar *) (b) - (data->model)->files->
data) / (data->model)->node_size) < (data->model)
->files->len) ; else g_assertion_message_expr ("Ctk", "ctkfilesystemmodel.c"
, 770, ((const char*) (__func__)), "(((gchar *) (b) - (data->model)->files->data) / (data->model)->node_size) < (data->model)->files->len"
); } while (0); (&iterb)->user_data = (data->model)
; (&iterb)->user_data2 = ((gpointer) (gulong) ((((gchar
*) (b) - (data->model)->files->data) / (data->model
)->node_size))); }while (0)
;
771 return data->func (CTK_TREE_MODEL (data->model)((((CtkTreeModel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((data->model)), ((ctk_tree_model_get_type ()))))))
, &itera, &iterb, data->data) * data->order;
772}
773
774static void
775ctk_file_system_model_sort (CtkFileSystemModel *model)
776{
777 SortData data;
778
779 if (model->frozen)
780 {
781 model->sort_on_thaw = TRUE(!(0));
782 return;
783 }
784
785 if (sort_data_init (&data, model))
786 {
787 guint i;
788 guint r, n_visible_rows;
789
790 node_validate_rows (model, G_MAXUINT(2147483647 *2U +1U), G_MAXUINT(2147483647 *2U +1U));
791 n_visible_rows = node_get_tree_row (model, model->files->len - 1) + 1;
792 model->n_nodes_valid = 0;
793 g_hash_table_remove_all (model->file_lookup);
794 g_qsort_with_data (get_node (model, 1)((FileModelNode *) ((model)->files->data + (1) * (model
)->node_size))
, /* start at index 1; don't sort the editable row */
795 model->files->len - 1,
796 model->node_size,
797 compare_array_element,
798 &data);
799 g_assert (model->n_nodes_valid == 0)do { if (model->n_nodes_valid == 0) ; else g_assertion_message_expr
("Ctk", "ctkfilesystemmodel.c", 799, ((const char*) (__func__
)), "model->n_nodes_valid == 0"); } while (0)
;
800 g_assert (g_hash_table_size (model->file_lookup) == 0)do { if (g_hash_table_size (model->file_lookup) == 0) ; else
g_assertion_message_expr ("Ctk", "ctkfilesystemmodel.c", 800
, ((const char*) (__func__)), "g_hash_table_size (model->file_lookup) == 0"
); } while (0)
;
801 if (n_visible_rows)
802 {
803 CtkTreePath *path;
804
805 int *new_order = g_new (int, n_visible_rows)((int *) g_malloc_n ((n_visible_rows), sizeof (int)));
806
807 r = 0;
808 for (i = 0; i < model->files->len; i++)
809 {
810 FileModelNode *node = get_node (model, i)((FileModelNode *) ((model)->files->data + (i) * (model
)->node_size))
;
811 if (!node->visible)
812 {
813 node->row = r;
814 continue;
815 }
816
817 new_order[r] = node->row - 1;
818 r++;
819 node->row = r;
820 }
821 g_assert (r == n_visible_rows)do { if (r == n_visible_rows) ; else g_assertion_message_expr
("Ctk", "ctkfilesystemmodel.c", 821, ((const char*) (__func__
)), "r == n_visible_rows"); } while (0)
;
822 path = ctk_tree_path_new ();
823 ctk_tree_model_rows_reordered (CTK_TREE_MODEL (model)((((CtkTreeModel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((model)), ((ctk_tree_model_get_type ()))))))
,
824 path,
825 NULL((void*)0),
826 new_order);
827 ctk_tree_path_free (path);
828 g_free (new_order);
829 }
830 }
831
832 model->sort_on_thaw = FALSE(0);
833}
834
835static void
836ctk_file_system_model_sort_node (CtkFileSystemModel *model,
837 guint node G_GNUC_UNUSED__attribute__ ((__unused__)))
838{
839 /* FIXME: improve */
840 ctk_file_system_model_sort (model);
841}
842
843static gboolean
844ctk_file_system_model_get_sort_column_id (CtkTreeSortable *sortable,
845 gint *sort_column_id,
846 CtkSortType *order)
847{
848 CtkFileSystemModel *model = CTK_FILE_SYSTEM_MODEL (sortable)((((CtkFileSystemModel*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((sortable)), ((_ctk_file_system_model_get_type
()))))))
;
849
850 if (sort_column_id)
851 *sort_column_id = model->sort_column_id;
852 if (order)
853 *order = model->sort_order;
854
855 if (model->sort_column_id == CTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID(-1) ||
856 model->sort_column_id == CTK_TREE_SORTABLE_UNSORTED_SORT_COLUMN_ID(-2))
857 return FALSE(0);
858
859 return TRUE(!(0));
860}
861
862static void
863ctk_file_system_model_set_sort_column_id (CtkTreeSortable *sortable,
864 gint sort_column_id,
865 CtkSortType order)
866{
867 CtkFileSystemModel *model = CTK_FILE_SYSTEM_MODEL (sortable)((((CtkFileSystemModel*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((sortable)), ((_ctk_file_system_model_get_type
()))))))
;
868
869 if ((model->sort_column_id == sort_column_id) &&
870 (model->sort_order == order))
871 return;
872
873 if (sort_column_id != CTK_TREE_SORTABLE_UNSORTED_SORT_COLUMN_ID(-2))
874 {
875 if (sort_column_id != CTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID(-1))
876 {
877 CtkTreeDataSortHeader *header = NULL((void*)0);
878
879 header = _ctk_tree_data_list_get_header (model->sort_list,
880 sort_column_id);
881
882 /* We want to make sure that we have a function */
883 g_return_if_fail (header != NULL)do { if ((header != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "header != NULL"); return
; } } while (0)
;
884 g_return_if_fail (header->func != NULL)do { if ((header->func != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "header->func != NULL"
); return; } } while (0)
;
885 }
886 else
887 {
888 g_return_if_fail (model->default_sort_func != NULL)do { if ((model->default_sort_func != ((void*)0))) { } else
{ g_return_if_fail_warning ("Ctk", ((const char*) (__func__)
), "model->default_sort_func != NULL"); return; } } while (
0)
;
889 }
890 }
891
892
893 model->sort_column_id = sort_column_id;
894 model->sort_order = order;
895
896 ctk_tree_sortable_sort_column_changed (sortable);
897
898 ctk_file_system_model_sort (model);
899}
900
901static void
902ctk_file_system_model_set_sort_func (CtkTreeSortable *sortable,
903 gint sort_column_id,
904 CtkTreeIterCompareFunc func,
905 gpointer data,
906 GDestroyNotify destroy)
907{
908 CtkFileSystemModel *model = CTK_FILE_SYSTEM_MODEL (sortable)((((CtkFileSystemModel*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((sortable)), ((_ctk_file_system_model_get_type
()))))))
;
909
910 model->sort_list = _ctk_tree_data_list_set_header (model->sort_list,
911 sort_column_id,
912 func, data, destroy);
913
914 if (model->sort_column_id == sort_column_id)
915 ctk_file_system_model_sort (model);
916}
917
918static void
919ctk_file_system_model_set_default_sort_func (CtkTreeSortable *sortable,
920 CtkTreeIterCompareFunc func,
921 gpointer data,
922 GDestroyNotify destroy)
923{
924 CtkFileSystemModel *model = CTK_FILE_SYSTEM_MODEL (sortable)((((CtkFileSystemModel*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((sortable)), ((_ctk_file_system_model_get_type
()))))))
;
925
926 if (model->default_sort_destroy)
927 {
928 GDestroyNotify d = model->default_sort_destroy;
929
930 model->default_sort_destroy = NULL((void*)0);
931 d (model->default_sort_data);
932 }
933
934 model->default_sort_func = func;
935 model->default_sort_data = data;
936 model->default_sort_destroy = destroy;
937
938 if (model->sort_column_id == CTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID(-1))
939 ctk_file_system_model_sort (model);
940}
941
942static gboolean
943ctk_file_system_model_has_default_sort_func (CtkTreeSortable *sortable)
944{
945 CtkFileSystemModel *model = CTK_FILE_SYSTEM_MODEL (sortable)((((CtkFileSystemModel*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((sortable)), ((_ctk_file_system_model_get_type
()))))))
;
946
947 return (model->default_sort_func != NULL((void*)0));
948}
949
950static void
951ctk_file_system_model_sortable_init (CtkTreeSortableIface *iface)
952{
953 iface->get_sort_column_id = ctk_file_system_model_get_sort_column_id;
954 iface->set_sort_column_id = ctk_file_system_model_set_sort_column_id;
955 iface->set_sort_func = ctk_file_system_model_set_sort_func;
956 iface->set_default_sort_func = ctk_file_system_model_set_default_sort_func;
957 iface->has_default_sort_func = ctk_file_system_model_has_default_sort_func;
958}
959
960/*** CtkTreeDragSource ***/
961
962static gboolean
963drag_source_row_draggable (CtkTreeDragSource *drag_source,
964 CtkTreePath *path)
965{
966 CtkFileSystemModel *model = CTK_FILE_SYSTEM_MODEL (drag_source)((((CtkFileSystemModel*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((drag_source)), ((_ctk_file_system_model_get_type
()))))))
;
967 CtkTreeIter iter;
968
969 if (!ctk_file_system_model_get_iter (CTK_TREE_MODEL (model)((((CtkTreeModel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((model)), ((ctk_tree_model_get_type ()))))))
, &iter, path))
970 return FALSE(0);
971
972 return ITER_INDEX (&iter)((guint) (gulong) ((&iter)->user_data2)) != 0;
973}
974
975static gboolean
976drag_source_drag_data_get (CtkTreeDragSource *drag_source,
977 CtkTreePath *path,
978 CtkSelectionData *selection_data)
979{
980 CtkFileSystemModel *model = CTK_FILE_SYSTEM_MODEL (drag_source)((((CtkFileSystemModel*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((drag_source)), ((_ctk_file_system_model_get_type
()))))))
;
981 FileModelNode *node;
982 CtkTreeIter iter;
983 char *uris[2];
984
985 if (!ctk_file_system_model_get_iter (CTK_TREE_MODEL (model)((((CtkTreeModel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((model)), ((ctk_tree_model_get_type ()))))))
, &iter, path))
986 return FALSE(0);
987
988 node = get_node (model, ITER_INDEX (&iter))((FileModelNode *) ((model)->files->data + (((guint) (gulong
) ((&iter)->user_data2))) * (model)->node_size))
;
989 if (node->file == NULL((void*)0))
990 return FALSE(0);
991
992 uris[0] = g_file_get_uri (node->file);
993 uris[1] = NULL((void*)0);
994 ctk_selection_data_set_uris (selection_data, uris);
995 g_free (uris[0]);
996
997 return TRUE(!(0));
998}
999
1000static void
1001drag_source_iface_init (CtkTreeDragSourceIface *iface)
1002{
1003 iface->row_draggable = drag_source_row_draggable;
1004 iface->drag_data_get = drag_source_drag_data_get;
1005 iface->drag_data_delete = NULL((void*)0);
1006}
1007
1008/*** CtkFileSystemModel ***/
1009
1010/* Signal IDs */
1011enum {
1012 FINISHED_LOADING,
1013 LAST_SIGNAL
1014};
1015
1016static guint file_system_model_signals[LAST_SIGNAL] = { 0 };
1017
1018
1019
1020G_DEFINE_TYPE_WITH_CODE (CtkFileSystemModel, _ctk_file_system_model, G_TYPE_OBJECT,static void _ctk_file_system_model_init (CtkFileSystemModel *
self); static void _ctk_file_system_model_class_init (CtkFileSystemModelClass
*klass); static GType _ctk_file_system_model_get_type_once (
void); static gpointer _ctk_file_system_model_parent_class = (
(void*)0); static gint CtkFileSystemModel_private_offset; static
void _ctk_file_system_model_class_intern_init (gpointer klass
) { _ctk_file_system_model_parent_class = g_type_class_peek_parent
(klass); if (CtkFileSystemModel_private_offset != 0) g_type_class_adjust_private_offset
(klass, &CtkFileSystemModel_private_offset); _ctk_file_system_model_class_init
((CtkFileSystemModelClass*) klass); } __attribute__ ((__unused__
)) static inline gpointer _ctk_file_system_model_get_instance_private
(CtkFileSystemModel *self) { return (((gpointer) ((guint8*) (
self) + (glong) (CtkFileSystemModel_private_offset)))); } GType
_ctk_file_system_model_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_system_model_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_system_model_get_type_once
(void) { GType g_define_type_id = g_type_register_static_simple
(((GType) ((20) << (2))), g_intern_static_string ("CtkFileSystemModel"
), sizeof (CtkFileSystemModelClass), (GClassInitFunc)(void (*
)(void)) _ctk_file_system_model_class_intern_init, sizeof (CtkFileSystemModel
), (GInstanceInitFunc)(void (*)(void)) _ctk_file_system_model_init
, (GTypeFlags) 0); { {{ const GInterfaceInfo g_implement_interface_info
= { (GInterfaceInitFunc)(void (*)(void)) ctk_file_system_model_iface_init
, ((void*)0), ((void*)0) }; g_type_add_interface_static (g_define_type_id
, (ctk_tree_model_get_type ()), &g_implement_interface_info
); } { const GInterfaceInfo g_implement_interface_info = { (GInterfaceInitFunc
)(void (*)(void)) ctk_file_system_model_sortable_init, ((void
*)0), ((void*)0) }; g_type_add_interface_static (g_define_type_id
, (ctk_tree_sortable_get_type ()), &g_implement_interface_info
); } { const GInterfaceInfo g_implement_interface_info = { (GInterfaceInitFunc
)(void (*)(void)) drag_source_iface_init, ((void*)0), ((void*
)0) }; g_type_add_interface_static (g_define_type_id, (ctk_tree_drag_source_get_type
()), &g_implement_interface_info); };} } return g_define_type_id
; }
1021 G_IMPLEMENT_INTERFACE (CTK_TYPE_TREE_MODEL,static void _ctk_file_system_model_init (CtkFileSystemModel *
self); static void _ctk_file_system_model_class_init (CtkFileSystemModelClass
*klass); static GType _ctk_file_system_model_get_type_once (
void); static gpointer _ctk_file_system_model_parent_class = (
(void*)0); static gint CtkFileSystemModel_private_offset; static
void _ctk_file_system_model_class_intern_init (gpointer klass
) { _ctk_file_system_model_parent_class = g_type_class_peek_parent
(klass); if (CtkFileSystemModel_private_offset != 0) g_type_class_adjust_private_offset
(klass, &CtkFileSystemModel_private_offset); _ctk_file_system_model_class_init
((CtkFileSystemModelClass*) klass); } __attribute__ ((__unused__
)) static inline gpointer _ctk_file_system_model_get_instance_private
(CtkFileSystemModel *self) { return (((gpointer) ((guint8*) (
self) + (glong) (CtkFileSystemModel_private_offset)))); } GType
_ctk_file_system_model_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_system_model_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_system_model_get_type_once
(void) { GType g_define_type_id = g_type_register_static_simple
(((GType) ((20) << (2))), g_intern_static_string ("CtkFileSystemModel"
), sizeof (CtkFileSystemModelClass), (GClassInitFunc)(void (*
)(void)) _ctk_file_system_model_class_intern_init, sizeof (CtkFileSystemModel
), (GInstanceInitFunc)(void (*)(void)) _ctk_file_system_model_init
, (GTypeFlags) 0); { {{ const GInterfaceInfo g_implement_interface_info
= { (GInterfaceInitFunc)(void (*)(void)) ctk_file_system_model_iface_init
, ((void*)0), ((void*)0) }; g_type_add_interface_static (g_define_type_id
, (ctk_tree_model_get_type ()), &g_implement_interface_info
); } { const GInterfaceInfo g_implement_interface_info = { (GInterfaceInitFunc
)(void (*)(void)) ctk_file_system_model_sortable_init, ((void
*)0), ((void*)0) }; g_type_add_interface_static (g_define_type_id
, (ctk_tree_sortable_get_type ()), &g_implement_interface_info
); } { const GInterfaceInfo g_implement_interface_info = { (GInterfaceInitFunc
)(void (*)(void)) drag_source_iface_init, ((void*)0), ((void*
)0) }; g_type_add_interface_static (g_define_type_id, (ctk_tree_drag_source_get_type
()), &g_implement_interface_info); };} } return g_define_type_id
; }
1022 ctk_file_system_model_iface_init)static void _ctk_file_system_model_init (CtkFileSystemModel *
self); static void _ctk_file_system_model_class_init (CtkFileSystemModelClass
*klass); static GType _ctk_file_system_model_get_type_once (
void); static gpointer _ctk_file_system_model_parent_class = (
(void*)0); static gint CtkFileSystemModel_private_offset; static
void _ctk_file_system_model_class_intern_init (gpointer klass
) { _ctk_file_system_model_parent_class = g_type_class_peek_parent
(klass); if (CtkFileSystemModel_private_offset != 0) g_type_class_adjust_private_offset
(klass, &CtkFileSystemModel_private_offset); _ctk_file_system_model_class_init
((CtkFileSystemModelClass*) klass); } __attribute__ ((__unused__
)) static inline gpointer _ctk_file_system_model_get_instance_private
(CtkFileSystemModel *self) { return (((gpointer) ((guint8*) (
self) + (glong) (CtkFileSystemModel_private_offset)))); } GType
_ctk_file_system_model_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_system_model_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_system_model_get_type_once
(void) { GType g_define_type_id = g_type_register_static_simple
(((GType) ((20) << (2))), g_intern_static_string ("CtkFileSystemModel"
), sizeof (CtkFileSystemModelClass), (GClassInitFunc)(void (*
)(void)) _ctk_file_system_model_class_intern_init, sizeof (CtkFileSystemModel
), (GInstanceInitFunc)(void (*)(void)) _ctk_file_system_model_init
, (GTypeFlags) 0); { {{ const GInterfaceInfo g_implement_interface_info
= { (GInterfaceInitFunc)(void (*)(void)) ctk_file_system_model_iface_init
, ((void*)0), ((void*)0) }; g_type_add_interface_static (g_define_type_id
, (ctk_tree_model_get_type ()), &g_implement_interface_info
); } { const GInterfaceInfo g_implement_interface_info = { (GInterfaceInitFunc
)(void (*)(void)) ctk_file_system_model_sortable_init, ((void
*)0), ((void*)0) }; g_type_add_interface_static (g_define_type_id
, (ctk_tree_sortable_get_type ()), &g_implement_interface_info
); } { const GInterfaceInfo g_implement_interface_info = { (GInterfaceInitFunc
)(void (*)(void)) drag_source_iface_init, ((void*)0), ((void*
)0) }; g_type_add_interface_static (g_define_type_id, (ctk_tree_drag_source_get_type
()), &g_implement_interface_info); };} } return g_define_type_id
; }
1023 G_IMPLEMENT_INTERFACE (CTK_TYPE_TREE_SORTABLE,static void _ctk_file_system_model_init (CtkFileSystemModel *
self); static void _ctk_file_system_model_class_init (CtkFileSystemModelClass
*klass); static GType _ctk_file_system_model_get_type_once (
void); static gpointer _ctk_file_system_model_parent_class = (
(void*)0); static gint CtkFileSystemModel_private_offset; static
void _ctk_file_system_model_class_intern_init (gpointer klass
) { _ctk_file_system_model_parent_class = g_type_class_peek_parent
(klass); if (CtkFileSystemModel_private_offset != 0) g_type_class_adjust_private_offset
(klass, &CtkFileSystemModel_private_offset); _ctk_file_system_model_class_init
((CtkFileSystemModelClass*) klass); } __attribute__ ((__unused__
)) static inline gpointer _ctk_file_system_model_get_instance_private
(CtkFileSystemModel *self) { return (((gpointer) ((guint8*) (
self) + (glong) (CtkFileSystemModel_private_offset)))); } GType
_ctk_file_system_model_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_system_model_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_system_model_get_type_once
(void) { GType g_define_type_id = g_type_register_static_simple
(((GType) ((20) << (2))), g_intern_static_string ("CtkFileSystemModel"
), sizeof (CtkFileSystemModelClass), (GClassInitFunc)(void (*
)(void)) _ctk_file_system_model_class_intern_init, sizeof (CtkFileSystemModel
), (GInstanceInitFunc)(void (*)(void)) _ctk_file_system_model_init
, (GTypeFlags) 0); { {{ const GInterfaceInfo g_implement_interface_info
= { (GInterfaceInitFunc)(void (*)(void)) ctk_file_system_model_iface_init
, ((void*)0), ((void*)0) }; g_type_add_interface_static (g_define_type_id
, (ctk_tree_model_get_type ()), &g_implement_interface_info
); } { const GInterfaceInfo g_implement_interface_info = { (GInterfaceInitFunc
)(void (*)(void)) ctk_file_system_model_sortable_init, ((void
*)0), ((void*)0) }; g_type_add_interface_static (g_define_type_id
, (ctk_tree_sortable_get_type ()), &g_implement_interface_info
); } { const GInterfaceInfo g_implement_interface_info = { (GInterfaceInitFunc
)(void (*)(void)) drag_source_iface_init, ((void*)0), ((void*
)0) }; g_type_add_interface_static (g_define_type_id, (ctk_tree_drag_source_get_type
()), &g_implement_interface_info); };} } return g_define_type_id
; }
1024 ctk_file_system_model_sortable_init)static void _ctk_file_system_model_init (CtkFileSystemModel *
self); static void _ctk_file_system_model_class_init (CtkFileSystemModelClass
*klass); static GType _ctk_file_system_model_get_type_once (
void); static gpointer _ctk_file_system_model_parent_class = (
(void*)0); static gint CtkFileSystemModel_private_offset; static
void _ctk_file_system_model_class_intern_init (gpointer klass
) { _ctk_file_system_model_parent_class = g_type_class_peek_parent
(klass); if (CtkFileSystemModel_private_offset != 0) g_type_class_adjust_private_offset
(klass, &CtkFileSystemModel_private_offset); _ctk_file_system_model_class_init
((CtkFileSystemModelClass*) klass); } __attribute__ ((__unused__
)) static inline gpointer _ctk_file_system_model_get_instance_private
(CtkFileSystemModel *self) { return (((gpointer) ((guint8*) (
self) + (glong) (CtkFileSystemModel_private_offset)))); } GType
_ctk_file_system_model_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_system_model_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_system_model_get_type_once
(void) { GType g_define_type_id = g_type_register_static_simple
(((GType) ((20) << (2))), g_intern_static_string ("CtkFileSystemModel"
), sizeof (CtkFileSystemModelClass), (GClassInitFunc)(void (*
)(void)) _ctk_file_system_model_class_intern_init, sizeof (CtkFileSystemModel
), (GInstanceInitFunc)(void (*)(void)) _ctk_file_system_model_init
, (GTypeFlags) 0); { {{ const GInterfaceInfo g_implement_interface_info
= { (GInterfaceInitFunc)(void (*)(void)) ctk_file_system_model_iface_init
, ((void*)0), ((void*)0) }; g_type_add_interface_static (g_define_type_id
, (ctk_tree_model_get_type ()), &g_implement_interface_info
); } { const GInterfaceInfo g_implement_interface_info = { (GInterfaceInitFunc
)(void (*)(void)) ctk_file_system_model_sortable_init, ((void
*)0), ((void*)0) }; g_type_add_interface_static (g_define_type_id
, (ctk_tree_sortable_get_type ()), &g_implement_interface_info
); } { const GInterfaceInfo g_implement_interface_info = { (GInterfaceInitFunc
)(void (*)(void)) drag_source_iface_init, ((void*)0), ((void*
)0) }; g_type_add_interface_static (g_define_type_id, (ctk_tree_drag_source_get_type
()), &g_implement_interface_info); };} } return g_define_type_id
; }
1025 G_IMPLEMENT_INTERFACE (CTK_TYPE_TREE_DRAG_SOURCE,static void _ctk_file_system_model_init (CtkFileSystemModel *
self); static void _ctk_file_system_model_class_init (CtkFileSystemModelClass
*klass); static GType _ctk_file_system_model_get_type_once (
void); static gpointer _ctk_file_system_model_parent_class = (
(void*)0); static gint CtkFileSystemModel_private_offset; static
void _ctk_file_system_model_class_intern_init (gpointer klass
) { _ctk_file_system_model_parent_class = g_type_class_peek_parent
(klass); if (CtkFileSystemModel_private_offset != 0) g_type_class_adjust_private_offset
(klass, &CtkFileSystemModel_private_offset); _ctk_file_system_model_class_init
((CtkFileSystemModelClass*) klass); } __attribute__ ((__unused__
)) static inline gpointer _ctk_file_system_model_get_instance_private
(CtkFileSystemModel *self) { return (((gpointer) ((guint8*) (
self) + (glong) (CtkFileSystemModel_private_offset)))); } GType
_ctk_file_system_model_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_system_model_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_system_model_get_type_once
(void) { GType g_define_type_id = g_type_register_static_simple
(((GType) ((20) << (2))), g_intern_static_string ("CtkFileSystemModel"
), sizeof (CtkFileSystemModelClass), (GClassInitFunc)(void (*
)(void)) _ctk_file_system_model_class_intern_init, sizeof (CtkFileSystemModel
), (GInstanceInitFunc)(void (*)(void)) _ctk_file_system_model_init
, (GTypeFlags) 0); { {{ const GInterfaceInfo g_implement_interface_info
= { (GInterfaceInitFunc)(void (*)(void)) ctk_file_system_model_iface_init
, ((void*)0), ((void*)0) }; g_type_add_interface_static (g_define_type_id
, (ctk_tree_model_get_type ()), &g_implement_interface_info
); } { const GInterfaceInfo g_implement_interface_info = { (GInterfaceInitFunc
)(void (*)(void)) ctk_file_system_model_sortable_init, ((void
*)0), ((void*)0) }; g_type_add_interface_static (g_define_type_id
, (ctk_tree_sortable_get_type ()), &g_implement_interface_info
); } { const GInterfaceInfo g_implement_interface_info = { (GInterfaceInitFunc
)(void (*)(void)) drag_source_iface_init, ((void*)0), ((void*
)0) }; g_type_add_interface_static (g_define_type_id, (ctk_tree_drag_source_get_type
()), &g_implement_interface_info); };} } return g_define_type_id
; }
1026 drag_source_iface_init))static void _ctk_file_system_model_init (CtkFileSystemModel *
self); static void _ctk_file_system_model_class_init (CtkFileSystemModelClass
*klass); static GType _ctk_file_system_model_get_type_once (
void); static gpointer _ctk_file_system_model_parent_class = (
(void*)0); static gint CtkFileSystemModel_private_offset; static
void _ctk_file_system_model_class_intern_init (gpointer klass
) { _ctk_file_system_model_parent_class = g_type_class_peek_parent
(klass); if (CtkFileSystemModel_private_offset != 0) g_type_class_adjust_private_offset
(klass, &CtkFileSystemModel_private_offset); _ctk_file_system_model_class_init
((CtkFileSystemModelClass*) klass); } __attribute__ ((__unused__
)) static inline gpointer _ctk_file_system_model_get_instance_private
(CtkFileSystemModel *self) { return (((gpointer) ((guint8*) (
self) + (glong) (CtkFileSystemModel_private_offset)))); } GType
_ctk_file_system_model_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_system_model_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_system_model_get_type_once
(void) { GType g_define_type_id = g_type_register_static_simple
(((GType) ((20) << (2))), g_intern_static_string ("CtkFileSystemModel"
), sizeof (CtkFileSystemModelClass), (GClassInitFunc)(void (*
)(void)) _ctk_file_system_model_class_intern_init, sizeof (CtkFileSystemModel
), (GInstanceInitFunc)(void (*)(void)) _ctk_file_system_model_init
, (GTypeFlags) 0); { {{ const GInterfaceInfo g_implement_interface_info
= { (GInterfaceInitFunc)(void (*)(void)) ctk_file_system_model_iface_init
, ((void*)0), ((void*)0) }; g_type_add_interface_static (g_define_type_id
, (ctk_tree_model_get_type ()), &g_implement_interface_info
); } { const GInterfaceInfo g_implement_interface_info = { (GInterfaceInitFunc
)(void (*)(void)) ctk_file_system_model_sortable_init, ((void
*)0), ((void*)0) }; g_type_add_interface_static (g_define_type_id
, (ctk_tree_sortable_get_type ()), &g_implement_interface_info
); } { const GInterfaceInfo g_implement_interface_info = { (GInterfaceInitFunc
)(void (*)(void)) drag_source_iface_init, ((void*)0), ((void*
)0) }; g_type_add_interface_static (g_define_type_id, (ctk_tree_drag_source_get_type
()), &g_implement_interface_info); };} } return g_define_type_id
; }
1027
1028static void
1029ctk_file_system_model_dispose (GObject *object)
1030{
1031 CtkFileSystemModel *model = CTK_FILE_SYSTEM_MODEL (object)((((CtkFileSystemModel*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((object)), ((_ctk_file_system_model_get_type
()))))))
;
1032
1033 if (model->dir_thaw_source)
1034 {
1035 g_source_remove (model->dir_thaw_source);
1036 model->dir_thaw_source = 0;
1037 }
1038
1039 g_cancellable_cancel (model->cancellable);
1040 if (model->dir_monitor)
1041 g_file_monitor_cancel (model->dir_monitor);
1042
1043 G_OBJECT_CLASS (_ctk_file_system_model_parent_class)((((GObjectClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((_ctk_file_system_model_parent_class)), (((GType) ((20) <<
(2))))))))
->dispose (object);
1044}
1045
1046
1047static void
1048ctk_file_system_model_finalize (GObject *object)
1049{
1050 CtkFileSystemModel *model = CTK_FILE_SYSTEM_MODEL (object)((((CtkFileSystemModel*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((object)), ((_ctk_file_system_model_get_type
()))))))
;
1051 guint i;
1052
1053 for (i = 0; i < model->files->len; i++)
1054 {
1055 int v;
1056
1057 FileModelNode *node = get_node (model, i)((FileModelNode *) ((model)->files->data + (i) * (model
)->node_size))
;
1058 if (node->file)
1059 g_object_unref (node->file);
1060 if (node->info)
1061 g_object_unref (node->info);
1062
1063 for (v = 0; v < model->n_columns; v++)
1064 if (G_VALUE_TYPE (&node->values[v])(((GValue*) (&node->values[v]))->g_type) != G_TYPE_INVALID((GType) ((0) << (2))))
1065 g_value_unset (&node->values[v]);
1066 }
1067 g_array_free (model->files, TRUE(!(0)));
1068
1069 g_object_unref (model->cancellable);
1070 g_free (model->attributes);
1071 if (model->dir)
1072 g_object_unref (model->dir);
1073 if (model->dir_monitor)
1074 g_object_unref (model->dir_monitor);
1075 g_hash_table_destroy (model->file_lookup);
1076 if (model->filter)
1077 g_object_unref (model->filter);
1078
1079 g_slice_free1 (sizeof (GType) * model->n_columns, model->column_types);
1080
1081 _ctk_tree_data_list_header_free (model->sort_list);
1082 if (model->default_sort_destroy)
1083 model->default_sort_destroy (model->default_sort_data);
1084
1085 G_OBJECT_CLASS (_ctk_file_system_model_parent_class)((((GObjectClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((_ctk_file_system_model_parent_class)), (((GType) ((20) <<
(2))))))))
->finalize (object);
1086}
1087
1088static void
1089_ctk_file_system_model_class_init (CtkFileSystemModelClass *class)
1090{
1091 GObjectClass *gobject_class = G_OBJECT_CLASS (class)((((GObjectClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((class)), (((GType) ((20) << (2))))))))
;
1092
1093 gobject_class->finalize = ctk_file_system_model_finalize;
1094 gobject_class->dispose = ctk_file_system_model_dispose;
1095
1096 file_system_model_signals[FINISHED_LOADING] =
1097 g_signal_new (I_("finished-loading")g_intern_static_string ("finished-loading"),
1098 G_OBJECT_CLASS_TYPE (gobject_class)((((GTypeClass*) (gobject_class))->g_type)),
1099 G_SIGNAL_RUN_LAST,
1100 G_STRUCT_OFFSET (CtkFileSystemModelClass, finished_loading)((glong) __builtin_offsetof(CtkFileSystemModelClass, finished_loading
))
,
1101 NULL((void*)0), NULL((void*)0),
1102 NULL((void*)0),
1103 G_TYPE_NONE((GType) ((1) << (2))), 1, G_TYPE_POINTER((GType) ((17) << (2))));
1104}
1105
1106static void
1107_ctk_file_system_model_init (CtkFileSystemModel *model)
1108{
1109 model->show_files = TRUE(!(0));
1110 model->show_folders = TRUE(!(0));
1111 model->show_hidden = FALSE(0);
1112 model->filter_folders = FALSE(0);
1113
1114 model->sort_column_id = CTK_TREE_SORTABLE_UNSORTED_SORT_COLUMN_ID(-2);
1115
1116 model->file_lookup = g_hash_table_new (g_file_hash, (GEqualFunc) g_file_equal);
1117 model->cancellable = g_cancellable_new ();
1118}
1119
1120/*** API ***/
1121
1122static void
1123ctk_file_system_model_closed_enumerator (GObject *object,
1124 GAsyncResult *res,
1125 gpointer data G_GNUC_UNUSED__attribute__ ((__unused__)))
1126{
1127 g_file_enumerator_close_finish (G_FILE_ENUMERATOR (object)((((GFileEnumerator*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((object)), ((g_file_enumerator_get_type ()))))))
, res, NULL((void*)0));
1128}
1129
1130static gboolean
1131thaw_func (gpointer data)
1132{
1133 CtkFileSystemModel *model = data;
1134
1135 thaw_updates (model);
1136 model->dir_thaw_source = 0;
1137
1138 return FALSE(0);
1139}
1140
1141static void
1142ctk_file_system_model_got_files (GObject *object, GAsyncResult *res, gpointer data)
1143{
1144 GFileEnumerator *enumerator = G_FILE_ENUMERATOR (object)((((GFileEnumerator*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((object)), ((g_file_enumerator_get_type ()))))))
;
1145 CtkFileSystemModel *model = data;
1146 GList *walk, *files;
1147 GError *error = NULL((void*)0);
1148
1149 cdk_threads_enter ();
1150
1151 files = g_file_enumerator_next_files_finish (enumerator, res, &error);
1152
1153 if (files)
1154 {
1155 if (model->dir_thaw_source == 0)
1156 {
1157 freeze_updates (model);
1158 model->dir_thaw_source = cdk_threads_add_timeout_full (IO_PRIORITY0 + 1,
1159 50,
1160 thaw_func,
1161 model,
1162 NULL((void*)0));
1163 g_source_set_name_by_id (model->dir_thaw_source, "[ctk+] thaw_func");
1164 }
1165
1166 for (walk = files; walk; walk = walk->next)
1167 {
1168 const char *name;
1169 GFileInfo *info;
1170 GFile *file;
1171
1172 info = walk->data;
1173 name = g_file_info_get_name (info);
1174 if (name == NULL((void*)0))
1175 {
1176 /* Shouldn't happen, but the APIs allow it */
1177 g_object_unref (info);
1178 continue;
1179 }
1180 file = g_file_get_child (model->dir, name);
1181 add_file (model, file, info);
1182 g_object_unref (file);
1183 g_object_unref (info);
1184 }
1185 g_list_free (files);
1186
1187 g_file_enumerator_next_files_async (enumerator,
1188 g_file_is_native (model->dir) ? 50 * FILES_PER_QUERY100 : FILES_PER_QUERY100,
1189 IO_PRIORITY0,
1190 model->cancellable,
1191 ctk_file_system_model_got_files,
1192 model);
1193 }
1194 else
1195 {
1196 if (!g_error_matches (error, G_IO_ERRORg_io_error_quark(), G_IO_ERROR_CANCELLED))
1197 {
1198 g_file_enumerator_close_async (enumerator,
1199 IO_PRIORITY0,
1200 model->cancellable,
1201 ctk_file_system_model_closed_enumerator,
1202 NULL((void*)0));
1203 if (model->dir_thaw_source != 0)
1204 {
1205 g_source_remove (model->dir_thaw_source);
1206 model->dir_thaw_source = 0;
1207 thaw_updates (model);
1208 }
1209
1210 g_signal_emit (model, file_system_model_signals[FINISHED_LOADING], 0, error);
1211 }
1212
1213 if (error)
1214 g_error_free (error);
1215 }
1216
1217 cdk_threads_leave ();
1218}
1219
1220/* Helper for ctk_file_system_model_query_done and
1221 * ctk_file_system_model_one_query_done */
1222static void
1223query_done_helper (GObject * object,
1224 GAsyncResult *res,
1225 gpointer data,
1226 gboolean do_thaw_updates)
1227{
1228 CtkFileSystemModel *model;
1229 GFile *file = G_FILE (object)((((GFile*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((object)), ((g_file_get_type ()))))))
;
1230 GFileInfo *info;
1231 guint id;
1232
1233 info = g_file_query_info_finish (file, res, NULL((void*)0));
1234 if (info == NULL((void*)0))
1235 return;
1236
1237 model = CTK_FILE_SYSTEM_MODEL (data)((((CtkFileSystemModel*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((data)), ((_ctk_file_system_model_get_type (
)))))))
;
1238
1239 _ctk_file_system_model_update_file (model, file, info);
1240
1241 id = node_get_for_file (model, file);
1242 ctk_file_system_model_sort_node (model, id);
1243
1244 if (do_thaw_updates)
1245 thaw_updates (model);
1246
1247 g_object_unref (info);
1248}
1249
1250static void
1251ctk_file_system_model_query_done (GObject * object,
1252 GAsyncResult *res,
1253 gpointer data)
1254{
1255 cdk_threads_enter ();
1256
1257 query_done_helper (object, res, data, FALSE(0));
1258
1259 cdk_threads_leave ();
1260}
1261
1262static void
1263ctk_file_system_model_monitor_change (GFileMonitor * monitor G_GNUC_UNUSED__attribute__ ((__unused__)),
1264 GFile * file,
1265 GFile * other_file G_GNUC_UNUSED__attribute__ ((__unused__)),
1266 GFileMonitorEvent type,
1267 CtkFileSystemModel *model)
1268{
1269 switch (type)
1270 {
1271 case G_FILE_MONITOR_EVENT_CREATED:
1272 case G_FILE_MONITOR_EVENT_CHANGED:
1273 case G_FILE_MONITOR_EVENT_ATTRIBUTE_CHANGED:
1274 /* We can treat all of these the same way */
1275 g_file_query_info_async (file,
1276 model->attributes,
1277 G_FILE_QUERY_INFO_NONE,
1278 IO_PRIORITY0,
1279 model->cancellable,
1280 ctk_file_system_model_query_done,
1281 model);
1282 break;
1283 case G_FILE_MONITOR_EVENT_DELETED:
1284 cdk_threads_enter ();
1285 remove_file (model, file);
1286 cdk_threads_leave ();
1287 break;
1288 case G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT:
1289 /* FIXME: use freeze/thaw with this somehow? */
1290 case G_FILE_MONITOR_EVENT_PRE_UNMOUNT:
1291 case G_FILE_MONITOR_EVENT_UNMOUNTED:
1292 default:
1293 /* ignore these */
1294 break;
1295 }
1296}
1297
1298static void
1299ctk_file_system_model_got_enumerator (GObject *dir, GAsyncResult *res, gpointer data)
1300{
1301 CtkFileSystemModel *model = data;
1302 GFileEnumerator *enumerator;
1303 GError *error = NULL((void*)0);
1304
1305 cdk_threads_enter ();
1306
1307 enumerator = g_file_enumerate_children_finish (G_FILE (dir)((((GFile*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((dir)), ((g_file_get_type ()))))))
, res, &error);
1308 if (enumerator == NULL((void*)0))
1309 {
1310 if (!g_error_matches (error, G_IO_ERRORg_io_error_quark(), G_IO_ERROR_CANCELLED))
1311 {
1312 g_signal_emit (model, file_system_model_signals[FINISHED_LOADING], 0, error);
1313 g_error_free (error);
1314 }
1315 }
1316 else
1317 {
1318 g_file_enumerator_next_files_async (enumerator,
1319 g_file_is_native (model->dir) ? 50 * FILES_PER_QUERY100 : FILES_PER_QUERY100,
1320 IO_PRIORITY0,
1321 model->cancellable,
1322 ctk_file_system_model_got_files,
1323 model);
1324 g_object_unref (enumerator);
1325 model->dir_monitor = g_file_monitor_directory (model->dir,
1326 G_FILE_MONITOR_NONE,
1327 model->cancellable,
1328 NULL((void*)0)); /* we don't mind if directory monitoring isn't supported, so the GError is NULL here */
1329 if (model->dir_monitor)
1330 g_signal_connect (model->dir_monitor,g_signal_connect_data ((model->dir_monitor), ("changed"), (
((GCallback) (ctk_file_system_model_monitor_change))), (model
), ((void*)0), (GConnectFlags) 0)
1331 "changed",g_signal_connect_data ((model->dir_monitor), ("changed"), (
((GCallback) (ctk_file_system_model_monitor_change))), (model
), ((void*)0), (GConnectFlags) 0)
1332 G_CALLBACK (ctk_file_system_model_monitor_change),g_signal_connect_data ((model->dir_monitor), ("changed"), (
((GCallback) (ctk_file_system_model_monitor_change))), (model
), ((void*)0), (GConnectFlags) 0)
1333 model)g_signal_connect_data ((model->dir_monitor), ("changed"), (
((GCallback) (ctk_file_system_model_monitor_change))), (model
), ((void*)0), (GConnectFlags) 0)
;
1334 }
1335
1336 cdk_threads_leave ();
1337}
1338
1339static void
1340ctk_file_system_model_set_n_columns (CtkFileSystemModel *model,
1341 gint n_columns,
1342 va_list args)
1343{
1344 guint i;
1345
1346 g_assert (model->files == NULL)do { if (model->files == ((void*)0)) ; else g_assertion_message_expr
("Ctk", "ctkfilesystemmodel.c", 1346, ((const char*) (__func__
)), "model->files == NULL"); } while (0)
;
1347 g_assert (n_columns > 0)do { if (n_columns > 0) ; else g_assertion_message_expr ("Ctk"
, "ctkfilesystemmodel.c", 1347, ((const char*) (__func__)), "n_columns > 0"
); } while (0)
;
1348
1349 model->n_columns = n_columns;
1350 model->column_types = g_slice_alloc (sizeof (GType) * n_columns);
1351
1352 model->node_size = sizeof (FileModelNode) + sizeof (GValue) * (n_columns - 1); /* minus 1 because FileModelNode.values[] has a default size of 1 */
1353
1354 for (i = 0; i < (guint) n_columns; i++)
1355 {
1356 GType type = va_arg (args, GType)__builtin_va_arg(args, GType);
1357 if (! _ctk_tree_data_list_check_type (type))
1358 {
1359 g_error ("%s: type %s cannot be a column type for CtkFileSystemModel\n", G_STRLOC"ctkfilesystemmodel.c" ":" "1359", g_type_name (type));
1360 return; /* not reached */
1361 }
1362
1363 model->column_types[i] = type;
1364 }
1365
1366 model->sort_list = _ctk_tree_data_list_header_new (n_columns, model->column_types);
1367
1368 model->files = g_array_sized_new (FALSE(0), FALSE(0), model->node_size, FILES_PER_QUERY100);
1369 /* add editable node at start */
1370 g_array_set_size (model->files, 1);
1371 memset (get_node (model, 0)((FileModelNode *) ((model)->files->data + (0) * (model
)->node_size))
, 0, model->node_size);
1372}
1373
1374static void
1375ctk_file_system_model_set_directory (CtkFileSystemModel *model,
1376 GFile * dir,
1377 const gchar * attributes)
1378{
1379 g_assert (G_IS_FILE (dir))do { if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((dir)); GType __t = ((g_file_get_type ())); gboolean __r;
if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; }))))) ; else
g_assertion_message_expr ("Ctk", "ctkfilesystemmodel.c", 1379
, ((const char*) (__func__)), "G_IS_FILE (dir)"); } while (0)
;
1380
1381 model->dir = g_object_ref (dir)((__typeof__ (dir)) (g_object_ref) (dir));
1382 model->attributes = g_strdup (attributes)g_strdup_inline (attributes);
1383
1384 g_file_enumerate_children_async (model->dir,
1385 attributes,
1386 G_FILE_QUERY_INFO_NONE,
1387 IO_PRIORITY0,
1388 model->cancellable,
1389 ctk_file_system_model_got_enumerator,
1390 model);
1391
1392}
1393
1394static CtkFileSystemModel *
1395_ctk_file_system_model_new_valist (CtkFileSystemModelGetValue get_func,
1396 gpointer get_data,
1397 guint n_columns,
1398 va_list args)
1399{
1400 CtkFileSystemModel *model;
1401
1402 model = g_object_new (CTK_TYPE_FILE_SYSTEM_MODEL(_ctk_file_system_model_get_type ()), NULL((void*)0));
1403 model->get_func = get_func;
1404 model->get_data = get_data;
1405
1406 ctk_file_system_model_set_n_columns (model, n_columns, args);
1407
1408 return model;
1409}
1410
1411/**
1412 * _ctk_file_system_model_new:
1413 * @get_func: function to call for getting a value
1414 * @get_data: user data argument passed to @get_func
1415 * @n_columns: number of columns
1416 * @...: @n_columns #GType types for the columns
1417 *
1418 * Creates a new #CtkFileSystemModel object. You need to add files
1419 * to the list using _ctk_file_system_model_add_and_query_file()
1420 * or _ctk_file_system_model_update_file().
1421 *
1422 * Returns: the newly created #CtkFileSystemModel
1423 **/
1424CtkFileSystemModel *
1425_ctk_file_system_model_new (CtkFileSystemModelGetValue get_func,
1426 gpointer get_data,
1427 guint n_columns,
1428 ...)
1429{
1430 CtkFileSystemModel *model;
1431 va_list args;
1432
1433 g_return_val_if_fail (get_func != NULL, NULL)do { if ((get_func != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "get_func != NULL"); return
(((void*)0)); } } while (0)
;
1434 g_return_val_if_fail (n_columns > 0, NULL)do { if ((n_columns > 0)) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "n_columns > 0"); return
(((void*)0)); } } while (0)
;
1435
1436 va_start (args, n_columns)__builtin_va_start(args, n_columns);
1437 model = _ctk_file_system_model_new_valist (get_func, get_data, n_columns, args);
1438 va_end (args)__builtin_va_end(args);
1439
1440 return model;
1441}
1442
1443/**
1444 * _ctk_file_system_model_new_for_directory:
1445 * @directory: the directory to show.
1446 * @attributes: (allow-none): attributes to immediately load or %NULL for all
1447 * @get_func: function that the model should call to query data about a file
1448 * @get_data: user data to pass to the @get_func
1449 * @n_columns: number of columns
1450 * @...: @n_columns #GType types for the columns
1451 *
1452 * Creates a new #CtkFileSystemModel object. The #CtkFileSystemModel
1453 * object wraps the given @directory as a #CtkTreeModel.
1454 * The model will query the given directory with the given @attributes
1455 * and add all files inside the directory automatically. If supported,
1456 * it will also monitor the drectory and update the model's
1457 * contents to reflect changes, if the @directory supports monitoring.
1458 *
1459 * Returns: the newly created #CtkFileSystemModel
1460 **/
1461CtkFileSystemModel *
1462_ctk_file_system_model_new_for_directory (GFile * dir,
1463 const gchar * attributes,
1464 CtkFileSystemModelGetValue get_func,
1465 gpointer get_data,
1466 guint n_columns,
1467 ...)
1468{
1469 CtkFileSystemModel *model;
1470 va_list args;
1471
1472 g_return_val_if_fail (G_IS_FILE (dir), NULL)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((dir)); GType __t = ((g_file_get_type ())); gboolean __r;
if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "G_IS_FILE (dir)"); return (((void*)0)); } } while (0)
;
1473 g_return_val_if_fail (get_func != NULL, NULL)do { if ((get_func != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "get_func != NULL"); return
(((void*)0)); } } while (0)
;
1474 g_return_val_if_fail (n_columns > 0, NULL)do { if ((n_columns > 0)) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "n_columns > 0"); return
(((void*)0)); } } while (0)
;
1475
1476 va_start (args, n_columns)__builtin_va_start(args, n_columns);
1477 model = _ctk_file_system_model_new_valist (get_func, get_data, n_columns, args);
1478 va_end (args)__builtin_va_end(args);
1479
1480 ctk_file_system_model_set_directory (model, dir, attributes);
1481
1482 return model;
1483}
1484
1485static void
1486ctk_file_system_model_refilter_all (CtkFileSystemModel *model)
1487{
1488 guint i;
1489
1490 if (model->frozen)
1491 {
1492 model->filter_on_thaw = TRUE(!(0));
1493 return;
1494 }
1495
1496 freeze_updates (model);
1497
1498 /* start at index 1, don't change the editable */
1499 for (i = 1; i < model->files->len; i++)
1500 node_compute_visibility_and_filters (model, i);
1501
1502 model->filter_on_thaw = FALSE(0);
1503 thaw_updates (model);
1504}
1505
1506/**
1507 * _ctk_file_system_model_set_show_hidden:
1508 * @model: a #CtkFileSystemModel
1509 * @show_hidden: whether hidden files should be displayed
1510 *
1511 * Sets whether hidden files should be included in the #CtkTreeModel
1512 * for display.
1513 **/
1514void
1515_ctk_file_system_model_set_show_hidden (CtkFileSystemModel *model,
1516 gboolean show_hidden)
1517{
1518 g_return_if_fail (CTK_IS_FILE_SYSTEM_MODEL (model))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((model)); GType __t = ((_ctk_file_system_model_get_type (
))); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; })))))) { } else { g_return_if_fail_warning ("Ctk", ((const
char*) (__func__)), "CTK_IS_FILE_SYSTEM_MODEL (model)"); return
; } } while (0)
;
1519
1520 show_hidden = show_hidden != FALSE(0);
1521
1522 if (show_hidden != model->show_hidden)
1523 {
1524 model->show_hidden = show_hidden;
1525 ctk_file_system_model_refilter_all (model);
1526 }
1527}
1528
1529/**
1530 * _ctk_file_system_model_set_show_folders:
1531 * @model: a #CtkFileSystemModel
1532 * @show_folders: whether folders should be displayed
1533 *
1534 * Sets whether folders should be included in the #CtkTreeModel for
1535 * display.
1536 **/
1537void
1538_ctk_file_system_model_set_show_folders (CtkFileSystemModel *model,
1539 gboolean show_folders)
1540{
1541 g_return_if_fail (CTK_IS_FILE_SYSTEM_MODEL (model))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((model)); GType __t = ((_ctk_file_system_model_get_type (
))); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; })))))) { } else { g_return_if_fail_warning ("Ctk", ((const
char*) (__func__)), "CTK_IS_FILE_SYSTEM_MODEL (model)"); return
; } } while (0)
;
1542
1543 show_folders = show_folders != FALSE(0);
1544
1545 if (show_folders != model->show_folders)
1546 {
1547 model->show_folders = show_folders;
1548 ctk_file_system_model_refilter_all (model);
1549 }
1550}
1551
1552/**
1553 * _ctk_file_system_model_set_show_files:
1554 * @model: a #CtkFileSystemModel
1555 * @show_files: whether files (as opposed to folders) should
1556 * be displayed.
1557 *
1558 * Sets whether files (as opposed to folders) should be included
1559 * in the #CtkTreeModel for display.
1560 **/
1561void
1562_ctk_file_system_model_set_show_files (CtkFileSystemModel *model,
1563 gboolean show_files)
1564{
1565 g_return_if_fail (CTK_IS_FILE_SYSTEM_MODEL (model))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((model)); GType __t = ((_ctk_file_system_model_get_type (
))); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; })))))) { } else { g_return_if_fail_warning ("Ctk", ((const
char*) (__func__)), "CTK_IS_FILE_SYSTEM_MODEL (model)"); return
; } } while (0)
;
1566
1567 show_files = show_files != FALSE(0);
1568
1569 if (show_files != model->show_files)
1570 {
1571 model->show_files = show_files;
1572 ctk_file_system_model_refilter_all (model);
1573 }
1574}
1575
1576/**
1577 * _ctk_file_system_model_set_filter_folders:
1578 * @model: a #CtkFileSystemModel
1579 * @filter_folders: whether the filter applies to folders
1580 *
1581 * Sets whether the filter set by _ctk_file_system_model_set_filter()
1582 * applies to folders. By default, it does not and folders are always
1583 * visible.
1584 **/
1585void
1586_ctk_file_system_model_set_filter_folders (CtkFileSystemModel *model,
1587 gboolean filter_folders)
1588{
1589 g_return_if_fail (CTK_IS_FILE_SYSTEM_MODEL (model))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((model)); GType __t = ((_ctk_file_system_model_get_type (
))); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; })))))) { } else { g_return_if_fail_warning ("Ctk", ((const
char*) (__func__)), "CTK_IS_FILE_SYSTEM_MODEL (model)"); return
; } } while (0)
;
1590
1591 filter_folders = filter_folders != FALSE(0);
1592
1593 if (filter_folders != model->filter_folders)
1594 {
1595 model->filter_folders = filter_folders;
1596 ctk_file_system_model_refilter_all (model);
1597 }
1598}
1599
1600/**
1601 * _ctk_file_system_model_get_cancellable:
1602 * @model: the model
1603 *
1604 * Gets the cancellable used by the @model. This is the cancellable used
1605 * internally by the @model that will be cancelled when @model is
1606 * disposed. So you can use it for operations that should be cancelled
1607 * when the model goes away.
1608 *
1609 * Returns: The cancellable used by @model
1610 **/
1611GCancellable *
1612_ctk_file_system_model_get_cancellable (CtkFileSystemModel *model)
1613{
1614 g_return_val_if_fail (CTK_IS_FILE_SYSTEM_MODEL (model), NULL)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((model)); GType __t = ((_ctk_file_system_model_get_type (
))); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; })))))) { } else { g_return_if_fail_warning ("Ctk", ((const
char*) (__func__)), "CTK_IS_FILE_SYSTEM_MODEL (model)"); return
(((void*)0)); } } while (0)
;
1615
1616 return model->cancellable;
1617}
1618
1619/**
1620 * _ctk_file_system_model_iter_is_visible:
1621 * @model: the model
1622 * @iter: a valid iterator
1623 *
1624 * Checks if the iterator is visible. A visible iterator references
1625 * a row that is currently exposed using the #CtkTreeModel API. If
1626 * the iterator is invisible, it references a file that is not shown
1627 * for some reason, such as being filtered out by the current filter or
1628 * being a hidden file.
1629 *
1630 * Returns: %TRUE if the iterator is visible
1631 **/
1632gboolean
1633_ctk_file_system_model_iter_is_visible (CtkFileSystemModel *model,
1634 CtkTreeIter *iter)
1635{
1636 FileModelNode *node;
1637
1638 g_return_val_if_fail (CTK_IS_FILE_SYSTEM_MODEL (model), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((model)); GType __t = ((_ctk_file_system_model_get_type (
))); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; })))))) { } else { g_return_if_fail_warning ("Ctk", ((const
char*) (__func__)), "CTK_IS_FILE_SYSTEM_MODEL (model)"); return
((0)); } } while (0)
;
1639 g_return_val_if_fail (iter != NULL, FALSE)do { if ((iter != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "iter != NULL"); return (
(0)); } } while (0)
;
1640
1641 node = get_node (model, ITER_INDEX (iter))((FileModelNode *) ((model)->files->data + (((guint) (gulong
) ((iter)->user_data2))) * (model)->node_size))
;
1642 return node->visible;
1643}
1644
1645/**
1646 * _ctk_file_system_model_iter_is_filtered_out:
1647 * @model: the model
1648 * @iter: a valid iterator
1649 *
1650 * Checks if the iterator is filtered out. This is only useful for rows
1651 * that refer to folders, as those are always visible regardless
1652 * of what the current filter says. This function lets you see
1653 * the results of the filter.
1654 *
1655 * Returns: %TRUE if the iterator passed the current filter; %FALSE if the
1656 * filter would not have let the row pass.
1657 **/
1658gboolean
1659_ctk_file_system_model_iter_is_filtered_out (CtkFileSystemModel *model,
1660 CtkTreeIter *iter)
1661{
1662 FileModelNode *node;
1663
1664 g_return_val_if_fail (CTK_IS_FILE_SYSTEM_MODEL (model), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((model)); GType __t = ((_ctk_file_system_model_get_type (
))); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; })))))) { } else { g_return_if_fail_warning ("Ctk", ((const
char*) (__func__)), "CTK_IS_FILE_SYSTEM_MODEL (model)"); return
((0)); } } while (0)
;
1665 g_return_val_if_fail (iter != NULL, FALSE)do { if ((iter != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "iter != NULL"); return (
(0)); } } while (0)
;
1666
1667 node = get_node (model, ITER_INDEX (iter))((FileModelNode *) ((model)->files->data + (((guint) (gulong
) ((iter)->user_data2))) * (model)->node_size))
;
1668 return node->filtered_out;
1669}
1670
1671/**
1672 * _ctk_file_system_model_get_info:
1673 * @model: a #CtkFileSystemModel
1674 * @iter: a #CtkTreeIter pointing to a row of @model
1675 *
1676 * Gets the #GFileInfo-struct for a particular row
1677 * of @model.
1678 *
1679 * Returns: a #GFileInfo-struct. This value
1680 * is owned by @model and must not be modified or freed.
1681 * If you want to keep the information for later use,
1682 * you must take a reference, since the #GFileInfo-struct may be
1683 * freed on later changes to the file system.
1684 **/
1685GFileInfo *
1686_ctk_file_system_model_get_info (CtkFileSystemModel *model,
1687 CtkTreeIter *iter)
1688{
1689 FileModelNode *node;
1690
1691 g_return_val_if_fail (CTK_IS_FILE_SYSTEM_MODEL (model), NULL)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((model)); GType __t = ((_ctk_file_system_model_get_type (
))); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; })))))) { } else { g_return_if_fail_warning ("Ctk", ((const
char*) (__func__)), "CTK_IS_FILE_SYSTEM_MODEL (model)"); return
(((void*)0)); } } while (0)
;
1692 g_return_val_if_fail (iter != NULL, NULL)do { if ((iter != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "iter != NULL"); return (
((void*)0)); } } while (0)
;
1693
1694 node = get_node (model, ITER_INDEX (iter))((FileModelNode *) ((model)->files->data + (((guint) (gulong
) ((iter)->user_data2))) * (model)->node_size))
;
1695 g_assert (node->info == NULL || G_IS_FILE_INFO (node->info))do { if (node->info == ((void*)0) || (((__extension__ ({ GTypeInstance
*__inst = (GTypeInstance*) ((node->info)); GType __t = ((
g_file_info_get_type ())); gboolean __r; if (!__inst) __r = (
0); else if (__inst->g_class && __inst->g_class
->g_type == __t) __r = (!(0)); else __r = g_type_check_instance_is_a
(__inst, __t); __r; }))))) ; else g_assertion_message_expr (
"Ctk", "ctkfilesystemmodel.c", 1695, ((const char*) (__func__
)), "node->info == NULL || G_IS_FILE_INFO (node->info)"
); } while (0)
;
1696 return node->info;
1697}
1698
1699/**
1700 * _ctk_file_system_model_get_file:
1701 * @model: a #CtkFileSystemModel
1702 * @iter: a #CtkTreeIter pointing to a row of @model
1703 *
1704 * Gets the file for a particular row in @model.
1705 *
1706 * Returns: the file. This object is owned by @model and
1707 * or freed. If you want to save the path for later use,
1708 * you must take a ref, since the object may be freed
1709 * on later changes to the file system.
1710 **/
1711GFile *
1712_ctk_file_system_model_get_file (CtkFileSystemModel *model,
1713 CtkTreeIter *iter)
1714{
1715 FileModelNode *node;
1716
1717 g_return_val_if_fail (CTK_IS_FILE_SYSTEM_MODEL (model), NULL)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((model)); GType __t = ((_ctk_file_system_model_get_type (
))); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; })))))) { } else { g_return_if_fail_warning ("Ctk", ((const
char*) (__func__)), "CTK_IS_FILE_SYSTEM_MODEL (model)"); return
(((void*)0)); } } while (0)
;
1718
1719 node = get_node (model, ITER_INDEX (iter))((FileModelNode *) ((model)->files->data + (((guint) (gulong
) ((iter)->user_data2))) * (model)->node_size))
;
1720 return node->file;
1721}
1722
1723/**
1724 * _ctk_file_system_model_get_value:
1725 * @model: a #CtkFileSystemModel
1726 * @iter: a #CtkTreeIter pointing to a row of @model
1727 * @column: the column to get the value for
1728 *
1729 * Gets the value associated with the given row @iter and @column.
1730 * If no value is available yet and the default value should be used,
1731 * %NULL is returned.
1732 * This is a performance optimization for the calls
1733 * ctk_tree_model_get() or ctk_tree_model_get_value(), which copy
1734 * the value and spend a considerable amount of time in iterator
1735 * lookups. Both of which are slow.
1736 *
1737 * Returns: a pointer to the actual value as stored in @model or %NULL
1738 * if no value available yet.
1739 **/
1740const GValue *
1741_ctk_file_system_model_get_value (CtkFileSystemModel *model,
1742 CtkTreeIter * iter,
1743 int column)
1744{
1745 FileModelNode *node;
1746
1747 g_return_val_if_fail (CTK_IS_FILE_SYSTEM_MODEL (model), NULL)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((model)); GType __t = ((_ctk_file_system_model_get_type (
))); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; })))))) { } else { g_return_if_fail_warning ("Ctk", ((const
char*) (__func__)), "CTK_IS_FILE_SYSTEM_MODEL (model)"); return
(((void*)0)); } } while (0)
;
1748 g_return_val_if_fail (column >= 0 && (guint) column < model->n_columns, NULL)do { if ((column >= 0 && (guint) column < model
->n_columns)) { } else { g_return_if_fail_warning ("Ctk", (
(const char*) (__func__)), "column >= 0 && (guint) column < model->n_columns"
); return (((void*)0)); } } while (0)
;
1749
1750 node = get_node (model, ITER_INDEX (iter))((FileModelNode *) ((model)->files->data + (((guint) (gulong
) ((iter)->user_data2))) * (model)->node_size))
;
1751
1752 if (!G_VALUE_TYPE (&node->values[column])(((GValue*) (&node->values[column]))->g_type))
1753 {
1754 g_value_init (&node->values[column], model->column_types[column]);
1755 if (!model->get_func (model,
1756 node->file,
1757 node->info,
1758 column,
1759 &node->values[column],
1760 model->get_data))
1761 {
1762 g_value_unset (&node->values[column]);
1763 return NULL((void*)0);
1764 }
1765 }
1766
1767 return &node->values[column];
1768}
1769
1770static guint
1771node_get_for_file (CtkFileSystemModel *model,
1772 GFile * file)
1773{
1774 guint i;
1775
1776 i = GPOINTER_TO_UINT (g_hash_table_lookup (model->file_lookup, file))((guint) (gulong) (g_hash_table_lookup (model->file_lookup
, file)))
;
1777 if (i != 0)
1778 return i;
1779
1780 /* Node 0 is the editable row and has no associated file or entry in the table, so we start counting from 1.
1781 *
1782 * The invariant here is that the files in model->files[n] for n < g_hash_table_size (model->file_lookup)
1783 * are already added to the hash table. The table can get cleared when we re-sort; this loop merely rebuilds
1784 * our (file -> index) mapping on demand.
1785 *
1786 * If we exit the loop, the next pending batch of mappings will be resolved when this function gets called again
1787 * with another file that is not yet in the mapping.
1788 */
1789 for (i = g_hash_table_size (model->file_lookup) + 1; i < model->files->len; i++)
1790 {
1791 FileModelNode *node = get_node (model, i)((FileModelNode *) ((model)->files->data + (i) * (model
)->node_size))
;
1792
1793 g_hash_table_insert (model->file_lookup, node->file, GUINT_TO_POINTER (i)((gpointer) (gulong) (i)));
1794 if (g_file_equal (node->file, file))
1795 return i;
1796 }
1797
1798 return 0;
1799}
1800
1801/**
1802 * _ctk_file_system_model_get_iter_for_file:
1803 * @model: the model
1804 * @iter: the iterator to be initialized
1805 * @file: the file to look up
1806 *
1807 * Initializes @iter to point to the row used for @file, if @file is part
1808 * of the model. Note that upon successful return, @iter may point to an
1809 * invisible row in the @model. Use
1810 * _ctk_file_system_model_iter_is_visible() to make sure it is visible to
1811 * the tree view.
1812 *
1813 * Returns: %TRUE if file is part of the model and @iter was initialized
1814 **/
1815gboolean
1816_ctk_file_system_model_get_iter_for_file (CtkFileSystemModel *model,
1817 CtkTreeIter *iter,
1818 GFile * file)
1819{
1820 guint i;
1821
1822 g_return_val_if_fail (CTK_IS_FILE_SYSTEM_MODEL (model), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((model)); GType __t = ((_ctk_file_system_model_get_type (
))); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; })))))) { } else { g_return_if_fail_warning ("Ctk", ((const
char*) (__func__)), "CTK_IS_FILE_SYSTEM_MODEL (model)"); return
((0)); } } while (0)
;
1823 g_return_val_if_fail (iter != NULL, FALSE)do { if ((iter != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "iter != NULL"); return (
(0)); } } while (0)
;
1824 g_return_val_if_fail (G_IS_FILE (file), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = ((g_file_get_type ())); gboolean __r
; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "G_IS_FILE (file)"); return ((0)); } } while (0)
;
1825
1826 i = node_get_for_file (model, file);
1827
1828 if (i == 0)
1829 return FALSE(0);
1830
1831 ITER_INIT_FROM_INDEX (model, iter, i)do { do { if (i < (model)->files->len) ; else g_assertion_message_expr
("Ctk", "ctkfilesystemmodel.c", 1831, ((const char*) (__func__
)), "i < (model)->files->len"); } while (0); (iter)->
user_data = (model); (iter)->user_data2 = ((gpointer) (gulong
) (i)); }while (0)
;
1832 return TRUE(!(0));
1833}
1834
1835/* When an element is added or removed to the model->files array, we need to
1836 * update the model->file_lookup mappings of (node, index), as the indexes
1837 * change. This function adds the specified increment to the index in that pair
1838 * if the index is equal or after the specified id. We use this to slide the
1839 * mappings up or down when a node is added or removed, respectively.
1840 */
1841static void
1842adjust_file_lookup (CtkFileSystemModel *model, guint id, int increment)
1843{
1844 GHashTableIter iter;
1845 gpointer key;
1846 gpointer value;
1847
1848 g_hash_table_iter_init (&iter, model->file_lookup);
1849
1850 while (g_hash_table_iter_next (&iter, &key, &value))
1851 {
1852 guint index = GPOINTER_TO_UINT (value)((guint) (gulong) (value));
1853
1854 if (index >= id)
1855 {
1856 index += increment;
1857 g_hash_table_iter_replace (&iter, GUINT_TO_POINTER (index)((gpointer) (gulong) (index)));
1858 }
1859 }
1860}
1861
1862/**
1863 * add_file:
1864 * @model: the model
1865 * @file: the file to add
1866 * @info: the information to associate with the file
1867 *
1868 * Adds the given @file with its associated @info to the @model.
1869 * If the model is frozen, the file will only show up after it is thawn.
1870 **/
1871static void
1872add_file (CtkFileSystemModel *model,
1873 GFile *file,
1874 GFileInfo *info)
1875{
1876 FileModelNode *node;
1877
1878 g_return_if_fail (CTK_IS_FILE_SYSTEM_MODEL (model))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((model)); GType __t = ((_ctk_file_system_model_get_type (
))); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; })))))) { } else { g_return_if_fail_warning ("Ctk", ((const
char*) (__func__)), "CTK_IS_FILE_SYSTEM_MODEL (model)"); return
; } } while (0)
;
1879 g_return_if_fail (G_IS_FILE (file))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = ((g_file_get_type ())); gboolean __r
; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "G_IS_FILE (file)"); return; } } while (0)
;
1880 g_return_if_fail (G_IS_FILE_INFO (info))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((info)); GType __t = ((g_file_info_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__
)), "G_IS_FILE_INFO (info)"); return; } } while (0)
;
1881
1882 node = g_slice_alloc0 (model->node_size);
1883 node->file = g_object_ref (file)((__typeof__ (file)) (g_object_ref) (file));
1884 if (info)
1885 node->info = g_object_ref (info)((__typeof__ (info)) (g_object_ref) (info));
1886 node->frozen_add = model->frozen ? TRUE(!(0)) : FALSE(0);
1887
1888 g_array_append_vals (model->files, node, 1);
1889 g_slice_free1 (model->node_size, node);
1890
1891 if (!model->frozen)
1892 node_compute_visibility_and_filters (model, model->files->len -1);
1893
1894 ctk_file_system_model_sort_node (model, model->files->len -1);
1895}
1896
1897/**
1898 * remove_file:
1899 * @model: the model
1900 * @file: file to remove from the model. The file must have been
1901 * added to the model previously
1902 *
1903 * Removes the given file from the model. If the file is not part of
1904 * @model, this function does nothing.
1905 **/
1906static void
1907remove_file (CtkFileSystemModel *model,
1908 GFile *file)
1909{
1910 FileModelNode *node;
1911 gboolean was_visible;
1912 guint id;
1913 guint row;
1914
1915 g_return_if_fail (CTK_IS_FILE_SYSTEM_MODEL (model))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((model)); GType __t = ((_ctk_file_system_model_get_type (
))); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; })))))) { } else { g_return_if_fail_warning ("Ctk", ((const
char*) (__func__)), "CTK_IS_FILE_SYSTEM_MODEL (model)"); return
; } } while (0)
;
1916 g_return_if_fail (G_IS_FILE (file))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = ((g_file_get_type ())); gboolean __r
; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "G_IS_FILE (file)"); return; } } while (0)
;
1917
1918 id = node_get_for_file (model, file);
1919 if (id == 0)
1920 return;
1921
1922 node = get_node (model, id)((FileModelNode *) ((model)->files->data + (id) * (model
)->node_size))
;
1923 was_visible = node->visible;
1924 row = node_get_tree_row (model, id);
1925
1926 node_invalidate_index (model, id);
1927
1928 g_hash_table_remove (model->file_lookup, file);
1929 g_object_unref (node->file);
1930 adjust_file_lookup (model, id, -1);
1931
1932 if (node->info)
1933 g_object_unref (node->info);
1934
1935 g_array_remove_index (model->files, id);
1936
1937 /* We don't need to resort, as removing a row doesn't change the sorting order of the other rows */
1938
1939 if (was_visible)
1940 emit_row_deleted_for_row (model, row);
1941}
1942
1943/**
1944 * _ctk_file_system_model_update_file:
1945 * @model: the model
1946 * @file: the file
1947 * @info: the new file info
1948 *
1949 * Tells the file system model that the file changed and that the
1950 * new @info should be used for it now. If the file is not part of
1951 * @model, it will get added automatically.
1952 **/
1953void
1954_ctk_file_system_model_update_file (CtkFileSystemModel *model,
1955 GFile *file,
1956 GFileInfo *info)
1957{
1958 FileModelNode *node;
1959 guint i, id;
1960 GFileInfo *old_info;
1961
1962 g_return_if_fail (CTK_IS_FILE_SYSTEM_MODEL (model))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((model)); GType __t = ((_ctk_file_system_model_get_type (
))); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; })))))) { } else { g_return_if_fail_warning ("Ctk", ((const
char*) (__func__)), "CTK_IS_FILE_SYSTEM_MODEL (model)"); return
; } } while (0)
;
1963 g_return_if_fail (G_IS_FILE (file))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = ((g_file_get_type ())); gboolean __r
; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "G_IS_FILE (file)"); return; } } while (0)
;
1964 g_return_if_fail (G_IS_FILE_INFO (info))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((info)); GType __t = ((g_file_info_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__
)), "G_IS_FILE_INFO (info)"); return; } } while (0)
;
1965
1966 id = node_get_for_file (model, file);
1967 if (id == 0)
1968 {
1969 add_file (model, file, info);
1970 id = node_get_for_file (model, file);
1971 }
1972
1973 node = get_node (model, id)((FileModelNode *) ((model)->files->data + (id) * (model
)->node_size))
;
1974
1975 old_info = node->info;
1976 node->info = g_object_ref (info)((__typeof__ (info)) (g_object_ref) (info));
1977 if (old_info)
1978 g_object_unref (old_info);
1979
1980 for (i = 0; i < model->n_columns; i++)
1981 {
1982 if (G_VALUE_TYPE (&node->values[i])(((GValue*) (&node->values[i]))->g_type))
1983 g_value_unset (&node->values[i]);
1984 }
1985
1986 if (node->visible)
1987 emit_row_changed_for_node (model, id);
1988}
1989
1990void
1991_ctk_file_system_model_update_files (CtkFileSystemModel *model,
1992 GList *files,
1993 GList *infos)
1994{
1995 GList *l, *i;
1996
1997 g_return_if_fail (CTK_IS_FILE_SYSTEM_MODEL (model))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((model)); GType __t = ((_ctk_file_system_model_get_type (
))); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; })))))) { } else { g_return_if_fail_warning ("Ctk", ((const
char*) (__func__)), "CTK_IS_FILE_SYSTEM_MODEL (model)"); return
; } } while (0)
;
1998
1999 freeze_updates (model);
2000
2001 for (l = files, i = infos; l; l = l->next, i = i->next)
2002 _ctk_file_system_model_update_file (model, (GFile *)l->data, (GFileInfo *)i->data);
2003
2004 thaw_updates (model);
2005}
2006
2007/**
2008 * _ctk_file_system_model_set_filter:
2009 * @mode: a #CtkFileSystemModel
2010 * @filter: (allow-none): %NULL or filter to use
2011 *
2012 * Sets a filter to be used for deciding if a row should be visible or not.
2013 * Whether this filter applies to directories can be toggled with
2014 * _ctk_file_system_model_set_filter_folders().
2015 **/
2016void
2017_ctk_file_system_model_set_filter (CtkFileSystemModel *model,
2018 CtkFileFilter * filter)
2019{
2020 CtkFileFilter *old_filter;
2021
2022 g_return_if_fail (CTK_IS_FILE_SYSTEM_MODEL (model))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((model)); GType __t = ((_ctk_file_system_model_get_type (
))); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; })))))) { } else { g_return_if_fail_warning ("Ctk", ((const
char*) (__func__)), "CTK_IS_FILE_SYSTEM_MODEL (model)"); return
; } } while (0)
;
2023 g_return_if_fail (filter == NULL || CTK_IS_FILE_FILTER (filter))do { if ((filter == ((void*)0) || (((__extension__ ({ GTypeInstance
*__inst = (GTypeInstance*) ((filter)); GType __t = ((ctk_file_filter_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__)), "filter == NULL || CTK_IS_FILE_FILTER (filter)"
); return; } } while (0)
;
2024
2025 if (filter)
2026 g_object_ref (filter)((__typeof__ (filter)) (g_object_ref) (filter));
2027
2028 old_filter = model->filter;
2029 model->filter = filter;
2030
2031 if (old_filter)
2032 g_object_unref (old_filter);
2033
2034 ctk_file_system_model_refilter_all (model);
2035}
2036
2037/**
2038 * freeze_updates:
2039 * @model: a #CtkFileSystemModel
2040 *
2041 * Freezes most updates on the model, so that performing multiple operations on
2042 * the files in the model do not cause any events. Use thaw_updates() to resume
2043 * proper operations. It is fine to call this function multiple times as long as
2044 * freeze and thaw calls are balanced.
2045 **/
2046static void
2047freeze_updates (CtkFileSystemModel *model)
2048{
2049 g_return_if_fail (CTK_IS_FILE_SYSTEM_MODEL (model))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((model)); GType __t = ((_ctk_file_system_model_get_type (
))); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; })))))) { } else { g_return_if_fail_warning ("Ctk", ((const
char*) (__func__)), "CTK_IS_FILE_SYSTEM_MODEL (model)"); return
; } } while (0)
;
2050
2051 model->frozen++;
2052}
2053
2054/**
2055 * thaw_updates:
2056 * @model: a #CtkFileSystemModel
2057 *
2058 * Undoes the effect of a previous call to freeze_updates()
2059 **/
2060static void
2061thaw_updates (CtkFileSystemModel *model)
2062{
2063 gboolean stuff_added;
2064
2065 g_return_if_fail (CTK_IS_FILE_SYSTEM_MODEL (model))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((model)); GType __t = ((_ctk_file_system_model_get_type (
))); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; })))))) { } else { g_return_if_fail_warning ("Ctk", ((const
char*) (__func__)), "CTK_IS_FILE_SYSTEM_MODEL (model)"); return
; } } while (0)
;
2066 g_return_if_fail (model->frozen > 0)do { if ((model->frozen > 0)) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "model->frozen > 0"
); return; } } while (0)
;
2067
2068 model->frozen--;
2069 if (model->frozen > 0)
2070 return;
2071
2072 stuff_added = get_node (model, model->files->len - 1)((FileModelNode *) ((model)->files->data + (model->files
->len - 1) * (model)->node_size))
->frozen_add;
2073
2074 if (model->filter_on_thaw)
2075 ctk_file_system_model_refilter_all (model);
2076 if (model->sort_on_thaw)
2077 ctk_file_system_model_sort (model);
2078 if (stuff_added)
2079 {
2080 guint i;
2081
2082 for (i = 0; i < model->files->len; i++)
2083 {
2084 FileModelNode *node = get_node (model, i)((FileModelNode *) ((model)->files->data + (i) * (model
)->node_size))
;
2085
2086 if (!node->frozen_add)
2087 continue;
2088 node->frozen_add = FALSE(0);
2089 node_compute_visibility_and_filters (model, i);
2090 }
2091 }
2092}
2093
2094/**
2095 * _ctk_file_system_model_clear_cache:
2096 * @model: a #CtkFileSystemModel
2097 * @column: the column to clear or -1 for all columns
2098 *
2099 * Clears the cached values in the model for the given @column. Use
2100 * this function whenever your get_value function would return different
2101 * values for a column.
2102 * The file chooser uses this for example when the icon theme changes to
2103 * invalidate the cached pixbufs.
2104 **/
2105void
2106_ctk_file_system_model_clear_cache (CtkFileSystemModel *model,
2107 int column)
2108{
2109 guint i;
2110 int start, end;
2111 gboolean changed;
2112
2113 g_return_if_fail (CTK_IS_FILE_SYSTEM_MODEL (model))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((model)); GType __t = ((_ctk_file_system_model_get_type (
))); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; })))))) { } else { g_return_if_fail_warning ("Ctk", ((const
char*) (__func__)), "CTK_IS_FILE_SYSTEM_MODEL (model)"); return
; } } while (0)
;
2114 g_return_if_fail (column >= -1 && (guint) column < model->n_columns)do { if ((column >= -1 && (guint) column < model
->n_columns)) { } else { g_return_if_fail_warning ("Ctk", (
(const char*) (__func__)), "column >= -1 && (guint) column < model->n_columns"
); return; } } while (0)
;
2115
2116 if (column > -1)
2117 {
2118 start = column;
2119 end = column + 1;
2120 }
2121 else
2122 {
2123 start = 0;
2124 end = model->n_columns;
2125 }
2126
2127 for (i = 0; i < model->files->len; i++)
2128 {
2129 FileModelNode *node = get_node (model, i)((FileModelNode *) ((model)->files->data + (i) * (model
)->node_size))
;
2130 changed = FALSE(0);
2131 for (column = start; column < end; column++)
2132 {
2133 if (!G_VALUE_TYPE (&node->values[column])(((GValue*) (&node->values[column]))->g_type))
2134 continue;
2135
2136 g_value_unset (&node->values[column]);
2137 changed = TRUE(!(0));
2138 }
2139
2140 if (changed && node->visible)
2141 emit_row_changed_for_node (model, i);
2142 }
2143
2144 /* FIXME: resort? */
2145}
2146
2147/**
2148 * _ctk_file_system_model_add_and_query_file:
2149 * @model: a #CtkFileSystemModel
2150 * @file: the file to add
2151 * @attributes: attributes to query before adding the file
2152 *
2153 * This is a conenience function that calls g_file_query_info_async() on
2154 * the given file, and when successful, adds it to the model.
2155 * Upon failure, the @file is discarded.
2156 **/
2157void
2158_ctk_file_system_model_add_and_query_file (CtkFileSystemModel *model,
2159 GFile * file,
2160 const char * attributes)
2161{
2162 g_return_if_fail (CTK_IS_FILE_SYSTEM_MODEL (model))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((model)); GType __t = ((_ctk_file_system_model_get_type (
))); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; })))))) { } else { g_return_if_fail_warning ("Ctk", ((const
char*) (__func__)), "CTK_IS_FILE_SYSTEM_MODEL (model)"); return
; } } while (0)
;
2163 g_return_if_fail (G_IS_FILE (file))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((file)); GType __t = ((g_file_get_type ())); gboolean __r
; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "G_IS_FILE (file)"); return; } } while (0)
;
2164 g_return_if_fail (attributes != NULL)do { if ((attributes != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "attributes != NULL"); return
; } } while (0)
;
2165
2166 g_file_query_info_async (file,
2167 attributes,
2168 G_FILE_QUERY_INFO_NONE,
2169 IO_PRIORITY0,
2170 model->cancellable,
2171 ctk_file_system_model_query_done,
2172 model);
2173}
2174
2175static void
2176ctk_file_system_model_one_query_done (GObject * object,
2177 GAsyncResult *res,
2178 gpointer data)
2179{
2180 query_done_helper (object, res, data, TRUE(!(0)));
2181}
2182
2183void
2184_ctk_file_system_model_add_and_query_files (CtkFileSystemModel *model,
2185 GList *list,
2186 const char *attributes)
2187{
2188 GList *l;
2189
2190 g_return_if_fail (CTK_IS_FILE_SYSTEM_MODEL (model))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((model)); GType __t = ((_ctk_file_system_model_get_type (
))); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; })))))) { } else { g_return_if_fail_warning ("Ctk", ((const
char*) (__func__)), "CTK_IS_FILE_SYSTEM_MODEL (model)"); return
; } } while (0)
;
2191 g_return_if_fail (attributes != NULL)do { if ((attributes != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "attributes != NULL"); return
; } } while (0)
;
2192
2193 for (l = list; l; l = l->next)
2194 {
2195 GFile *file;
2196
2197 file = (GFile *)l->data;
2198 freeze_updates (model);
2199 g_file_query_info_async (file,
2200 attributes,
2201 G_FILE_QUERY_INFO_NONE,
2202 IO_PRIORITY0,
2203 model->cancellable,
2204 ctk_file_system_model_one_query_done,
2205 model);
2206 }
2207}
2208
2209GFile *
2210_ctk_file_system_model_get_directory (CtkFileSystemModel *model)
2211{
2212 g_return_val_if_fail (CTK_IS_FILE_SYSTEM_MODEL (model), NULL)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((model)); GType __t = ((_ctk_file_system_model_get_type (
))); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; })))))) { } else { g_return_if_fail_warning ("Ctk", ((const
char*) (__func__)), "CTK_IS_FILE_SYSTEM_MODEL (model)"); return
(((void*)0)); } } while (0)
;
2213
2214 return model->dir;
2215}
2216