File: | ctk/ctkfilesystemmodel.c |
Warning: | line 320, column 3 Using a fixed address is not portable because that address will probably not be valid in all environments or platforms |
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)); | ||||
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
| ||||
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
| ||||
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 |