File: | ctk/ctkfilesystemmodel.c |
Warning: | line 1719, column 10 Casting a non-structure type to a structure type and accessing a field can lead to memory access errors or data corruption |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
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 | |
130 | typedef struct _FileModelNode FileModelNode; |
131 | typedef struct _CtkFileSystemModelClass CtkFileSystemModelClass; |
132 | |
133 | struct _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 | |
149 | struct _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 | |
198 | struct _CtkFileSystemModelClass |
199 | { |
200 | GObjectClass parent_class; |
201 | |
202 | /* Signals */ |
203 | |
204 | void (*finished_loading) (CtkFileSystemModel *model, GError *error); |
205 | }; |
206 | |
207 | static void freeze_updates (CtkFileSystemModel *model); |
208 | static void thaw_updates (CtkFileSystemModel *model); |
209 | |
210 | static guint node_get_for_file (CtkFileSystemModel *model, |
211 | GFile *file); |
212 | |
213 | static void add_file (CtkFileSystemModel *model, |
214 | GFile *file, |
215 | GFileInfo *info); |
216 | static 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 | */ |
249 | static void |
250 | node_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)); |
268 | if (node->visible) |
269 | row++; |
270 | node->row = row; |
271 | i++; |
272 | } |
273 | model->n_nodes_valid = i; |
274 | } |
275 | |
276 | static guint |
277 | node_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 | |
285 | static void |
286 | node_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 | |
291 | static CtkTreePath * |
292 | tree_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 | |
301 | static void |
302 | emit_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 | |
313 | static void |
314 | emit_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 | |
325 | static void |
326 | emit_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 | |
335 | static void |
336 | node_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 | |
374 | static gboolean |
375 | node_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 | |
444 | static gboolean |
445 | node_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 | |
476 | static void |
477 | node_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 | |
490 | static CtkTreeModelFlags |
491 | ctk_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 | |
497 | static gint |
498 | ctk_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 | |
505 | static GType |
506 | ctk_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 | |
516 | static int |
517 | compare_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 | |
524 | static gboolean |
525 | ctk_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 | |
580 | static gboolean |
581 | ctk_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 | |
596 | static CtkTreePath * |
597 | ctk_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 | |
607 | static void |
608 | ctk_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 | |
629 | static gboolean |
630 | ctk_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 | |
652 | static gboolean |
653 | ctk_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 | |
660 | static gboolean |
661 | ctk_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 | |
667 | static gint |
668 | ctk_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 | |
679 | static gboolean |
680 | ctk_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 | |
687 | static void |
688 | ctk_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 | |
694 | static void |
695 | ctk_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 | |
701 | static void |
702 | ctk_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 | |
722 | typedef struct _SortData SortData; |
723 | struct _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 */ |
731 | static gboolean |
732 | sort_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 | |
763 | static int |
764 | compare_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 | |
774 | static void |
775 | ctk_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 | |
835 | static void |
836 | ctk_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 | |
843 | static gboolean |
844 | ctk_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 | |
862 | static void |
863 | ctk_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 | |
901 | static void |
902 | ctk_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 | |
918 | static void |
919 | ctk_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 | |
942 | static gboolean |
943 | ctk_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 | |
950 | static void |
951 | ctk_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 | |
962 | static gboolean |
963 | drag_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 | |
975 | static gboolean |
976 | drag_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 | |
1000 | static void |
1001 | drag_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 */ |
1011 | enum { |
1012 | FINISHED_LOADING, |
1013 | LAST_SIGNAL |
1014 | }; |
1015 | |
1016 | static guint file_system_model_signals[LAST_SIGNAL] = { 0 }; |
1017 | |
1018 | |
1019 | |
1020 | G_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 | |
1028 | static void |
1029 | ctk_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 | |
1047 | static void |
1048 | ctk_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 | |
1088 | static 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 | |
1106 | static 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 | |
1122 | static void |
1123 | ctk_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 | |
1130 | static gboolean |
1131 | thaw_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 | |
1141 | static void |
1142 | ctk_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 */ |
1222 | static void |
1223 | query_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 | |
1250 | static void |
1251 | ctk_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 | |
1262 | static void |
1263 | ctk_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 | |
1298 | static void |
1299 | ctk_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 | |
1339 | static void |
1340 | ctk_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 | |
1374 | static void |
1375 | ctk_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 | |
1394 | static 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 | **/ |
1424 | CtkFileSystemModel * |
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 | **/ |
1461 | CtkFileSystemModel * |
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 | |
1485 | static void |
1486 | ctk_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 | **/ |
1514 | void |
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 | **/ |
1537 | void |
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 | **/ |
1561 | void |
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 | **/ |
1585 | void |
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 | **/ |
1611 | GCancellable * |
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 | **/ |
1632 | gboolean |
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 | **/ |
1658 | gboolean |
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 | **/ |
1685 | GFileInfo * |
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 | **/ |
1711 | GFile * |
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)); |
Casting a non-structure type to a structure type and accessing a field can lead to memory access errors or data corruption | |
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 | **/ |
1740 | const 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 | |
1770 | static guint |
1771 | node_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 | **/ |
1815 | gboolean |
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 | */ |
1841 | static void |
1842 | adjust_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 | **/ |
1871 | static void |
1872 | add_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 | **/ |
1906 | static void |
1907 | remove_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 | **/ |
1953 | void |
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 | |
1990 | void |
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 | **/ |
2016 | void |
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 | **/ |
2046 | static void |
2047 | freeze_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 | **/ |
2060 | static void |
2061 | thaw_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 | **/ |
2105 | void |
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 | **/ |
2157 | void |
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 | |
2175 | static void |
2176 | ctk_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 | |
2183 | void |
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 | |
2209 | GFile * |
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 |