| File: | ctk/ctkfilesystemmodel.c |
| Warning: | line 2072, column 17 Casting a non-structure type to a structure type and accessing a field can lead to memory access errors or data corruption |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
| 1 | /* CTK - The GIMP Toolkit |
| 2 | * ctkfilesystemmodel.c: CtkTreeModel wrapping a CtkFileSystem |
| 3 | * Copyright (C) 2003, Red Hat, Inc. |
| 4 | * |
| 5 | * This library is free software; you can redistribute it and/or |
| 6 | * modify it under the terms of the GNU Lesser General Public |
| 7 | * License as published by the Free Software Foundation; either |
| 8 | * version 2 of the License, or (at your option) any later version. |
| 9 | * |
| 10 | * This library is distributed in the hope that it will be useful, |
| 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| 13 | * Lesser General Public License for more details. |
| 14 | * |
| 15 | * You should have received a copy of the GNU Lesser General Public |
| 16 | * License along with this library. If not, see <http://www.gnu.org/licenses/>. |
| 17 | */ |
| 18 | |
| 19 | #include "config.h" |
| 20 | |
| 21 | #include "ctkfilesystemmodel.h" |
| 22 | |
| 23 | #include <stdlib.h> |
| 24 | #include <string.h> |
| 25 | |
| 26 | #include "ctkfilesystem.h" |
| 27 | #include "ctkintl.h" |
| 28 | #include "ctkmarshalers.h" |
| 29 | #include "ctktreedatalist.h" |
| 30 | #include "ctktreednd.h" |
| 31 | #include "ctktreemodel.h" |
| 32 | |
| 33 | /*** Structure: how CtkFileSystemModel works |
| 34 | * |
| 35 | * This is a custom CtkTreeModel used to hold a collection of files for CtkFileChooser. There are two use cases: |
| 36 | * |
| 37 | * 1. The model populates itself from a folder, using the GIO file enumerator API. This happens if you use |
| 38 | * _ctk_file_system_model_new_for_directory(). This is the normal usage for showing the contents of a folder. |
| 39 | * |
| 40 | * 2. The caller populates the model by hand, with files not necessarily in the same folder. This happens |
| 41 | * if you use _ctk_file_system_model_new() and then _ctk_file_system_model_add_and_query_file(). This is |
| 42 | * the special kind of usage for “search” and “recent-files”, where the file chooser gives the model the |
| 43 | * files to be displayed. |
| 44 | * |
| 45 | * Internal data structure |
| 46 | * ----------------------- |
| 47 | * |
| 48 | * Each file is kept in a FileModelNode structure. Each FileModelNode holds a GFile* and other data. All the |
| 49 | * node structures have the same size, determined at runtime, depending on the number of columns that were passed |
| 50 | * to _ctk_file_system_model_new() or _ctk_file_system_model_new_for_directory() (that is, the size of a node is |
| 51 | * not sizeof (FileModelNode), but rather model->node_size). The last field in the FileModelNode structure, |
| 52 | * node->values[], is an array of GValue, used to hold the data for those columns. |
| 53 | * |
| 54 | * The model stores an array of FileModelNode structures in model->files. This is a GArray where each element is |
| 55 | * model->node_size bytes in size (the model computes that node size when initializing itself). There are |
| 56 | * convenience macros, get_node() and node_index(), to access that array based on an array index or a pointer to |
| 57 | * a node inside the array. |
| 58 | * |
| 59 | * The model accesses files through two of its fields: |
| 60 | * |
| 61 | * model->files - GArray of FileModelNode structures. |
| 62 | * |
| 63 | * model->file_lookup - hash table that maps a GFile* to an index inside the model->files array. |
| 64 | * |
| 65 | * The model->file_lookup hash table is populated lazily. It is both accessed and populated with the |
| 66 | * node_get_for_file() function. The invariant is that the files in model->files[n] for n < g_hash_table_size |
| 67 | * (model->file_lookup) are already added to the hash table. The hash table will get cleared when we re-sort the |
| 68 | * files, as the array will be in a different order and the indexes need to be rebuilt. |
| 69 | * |
| 70 | * Each FileModelNode has a node->visible field, which indicates whether the node is visible in the CtkTreeView. |
| 71 | * A node may be invisible if, for example, it corresponds to a hidden file and the file chooser is not showing |
| 72 | * hidden files. Also, a file filter may be explicitly set onto the model, for example, to only show files that |
| 73 | * match “*.jpg”. In this case, node->filtered_out says whether the node failed the filter. The ultimate |
| 74 | * decision on whether a node is visible or not in the treeview is distilled into the node->visible field. |
| 75 | * The reason for having a separate node->filtered_out field is so that the file chooser can query whether |
| 76 | * a (filtered-out) folder should be made sensitive in the GUI. |
| 77 | * |
| 78 | * Visible rows vs. possibly-invisible nodes |
| 79 | * ----------------------------------------- |
| 80 | * |
| 81 | * Since not all nodes in the model->files array may be visible, we need a way to map visible row indexes from |
| 82 | * the treeview to array indexes in our array of files. And thus we introduce a bit of terminology: |
| 83 | * |
| 84 | * index - An index in the model->files array. All variables/fields that represent indexes are either called |
| 85 | * “index” or “i_*”, or simply “i” for things like loop counters. |
| 86 | * |
| 87 | * row - An index in the CtkTreeView, i.e. the index of a row within the outward-facing API of the |
| 88 | * CtkFileSystemModel. However, note that our rows are 1-based, not 0-based, for the reason explained in the |
| 89 | * following paragraph. Variables/fields that represent visible rows are called “row”, or “r_*”, or simply |
| 90 | * “r”. |
| 91 | * |
| 92 | * Each FileModelNode has a node->row field which is the number of visible rows in the treeview, *before and |
| 93 | * including* that node. This means that node->row is 1-based, instead of 0-based --- this makes some code |
| 94 | * simpler, believe it or not :) This also means that when the calling CtkTreeView gives us a CtkTreePath, we |
| 95 | * turn the 0-based treepath into a 1-based row for our purposes. If a node is not visible, it will have the |
| 96 | * same row number as its closest preceding visible node. |
| 97 | * |
| 98 | * We try to compute the node->row fields lazily. A node is said to be “valid” if its node->row is accurate. |
| 99 | * For this, the model keeps a model->n_nodes_valid field which is the count of valid nodes starting from the |
| 100 | * beginning of the model->files array. When a node changes its information, or when a node gets deleted, that |
| 101 | * node and the following ones get invalidated by simply setting model->n_nodes_valid to the array index of the |
| 102 | * node. If the model happens to need a node’s row number and that node is in the model->files array after |
| 103 | * model->n_nodes_valid, then the nodes get re-validated up to the sought node. See node_validate_rows() for |
| 104 | * this logic. |
| 105 | * |
| 106 | * You never access a node->row directly. Instead, call node_get_tree_row(). That function will validate the nodes |
| 107 | * up to the sought one if the node is not valid yet, and it will return a proper 0-based row. |
| 108 | * |
| 109 | * Sorting |
| 110 | * ------- |
| 111 | * |
| 112 | * The model implements the CtkTreeSortable interface. To avoid re-sorting |
| 113 | * every time a node gets added (which would lead to O(n^2) performance during |
| 114 | * the initial population of the model), the model can freeze itself (with |
| 115 | * freeze_updates()) during the intial population process. When the model is |
| 116 | * frozen, sorting will not happen. The model will sort itself when the freeze |
| 117 | * count goes back to zero, via corresponding calls to thaw_updates(). |
| 118 | */ |
| 119 | |
| 120 | /*** DEFINES ***/ |
| 121 | |
| 122 | /* priority used for all async callbacks in the main loop |
| 123 | * This should be higher than redraw priorities so multiple callbacks |
| 124 | * firing can be handled without intermediate redraws */ |
| 125 | #define IO_PRIORITY0 G_PRIORITY_DEFAULT0 |
| 126 | |
| 127 | /* random number that everyone else seems to use, too */ |
| 128 | #define FILES_PER_QUERY100 100 |
| 129 | |
| 130 | typedef struct _FileModelNode FileModelNode; |
| 131 | typedef struct _CtkFileSystemModelClass CtkFileSystemModelClass; |
| 132 | |
| 133 | struct _FileModelNode |
| 134 | { |
| 135 | GFile * file; /* file represented by this node or NULL for editable */ |
| 136 | GFileInfo * info; /* info for this file or NULL if unknown */ |
| 137 | |
| 138 | guint row; /* if valid (see model->n_valid_indexes), visible nodes before and including |
| 139 | * this one - see the "Structure" comment above. |
| 140 | */ |
| 141 | |
| 142 | guint visible :1; /* if the file is currently visible */ |
| 143 | guint filtered_out :1;/* if the file is currently filtered out (i.e. it didn't pass the filters) */ |
| 144 | guint frozen_add :1; /* true if the model was frozen and the entry has not been added yet */ |
| 145 | |
| 146 | GValue values[1]; /* actually n_columns values */ |
| 147 | }; |
| 148 | |
| 149 | struct _CtkFileSystemModel |
| 150 | { |
| 151 | GObject parent_instance; |
| 152 | |
| 153 | GFile * dir; /* directory that's displayed */ |
| 154 | guint dir_thaw_source;/* GSource id for unfreezing the model */ |
| 155 | char * attributes; /* attributes the file info must contain, or NULL for all attributes */ |
| 156 | GFileMonitor * dir_monitor; /* directory that is monitored, or NULL if monitoring was not supported */ |
| 157 | |
| 158 | GCancellable * cancellable; /* cancellable in use for all operations - cancelled on dispose */ |
| 159 | GArray * files; /* array of FileModelNode containing all our files */ |
| 160 | gsize node_size; /* Size of a FileModelNode structure once its ->values field has n_columns */ |
| 161 | guint n_nodes_valid; /* count of valid nodes (i.e. those whose node->row is accurate) */ |
| 162 | GHashTable * file_lookup; /* mapping of GFile => array index in model->files |
| 163 | * This hash table doesn't always have the same number of entries as the files array; |
| 164 | * it can get cleared completely when we resort. |
| 165 | * The hash table gets re-populated in node_get_for_file() if this mismatch is |
| 166 | * detected. |
| 167 | */ |
| 168 | |
| 169 | guint n_columns; /* number of columns */ |
| 170 | GType * column_types; /* types of each column */ |
| 171 | CtkFileSystemModelGetValue get_func; /* function to call to fill in values in columns */ |
| 172 | gpointer get_data; /* data to pass to get_func */ |
| 173 | |
| 174 | CtkFileFilter * filter; /* filter to use for deciding which nodes are visible */ |
| 175 | |
| 176 | int sort_column_id; /* current sorting column */ |
| 177 | CtkSortType sort_order; /* current sorting order */ |
| 178 | GList * sort_list; /* list of sorting functions */ |
| 179 | CtkTreeIterCompareFunc default_sort_func; /* default sort function */ |
| 180 | gpointer default_sort_data; /* data to pass to default sort func */ |
| 181 | GDestroyNotify default_sort_destroy; /* function to call to destroy default_sort_data */ |
| 182 | |
| 183 | guint frozen; /* number of times we're frozen */ |
| 184 | |
| 185 | gboolean filter_on_thaw :1;/* set when filtering needs to happen upon thawing */ |
| 186 | gboolean sort_on_thaw :1;/* set when sorting needs to happen upon thawing */ |
| 187 | |
| 188 | guint show_hidden :1; /* whether to show hidden files */ |
| 189 | guint show_folders :1;/* whether to show folders */ |
| 190 | guint show_files :1; /* whether to show files */ |
| 191 | guint filter_folders :1;/* whether filter applies to folders */ |
| 192 | }; |
| 193 | |
| 194 | #define CTK_FILE_SYSTEM_MODEL_CLASS(klass)((((CtkFileSystemModelClass*) (void *) g_type_check_class_cast ((GTypeClass*) ((klass)), ((_ctk_file_system_model_get_type ( ))))))) (G_TYPE_CHECK_CLASS_CAST ((klass), CTK_TYPE_FILE_SYSTEM_MODEL, CtkFileSystemModelClass)(((CtkFileSystemModelClass*) (void *) g_type_check_class_cast ((GTypeClass*) ((klass)), ((_ctk_file_system_model_get_type ( ))))))) |
| 195 | #define CTK_IS_FILE_SYSTEM_MODEL_CLASS(klass)(((__extension__ ({ GTypeClass *__class = (GTypeClass*) ((klass )); GType __t = ((_ctk_file_system_model_get_type ())); gboolean __r; if (!__class) __r = (0); else if (__class->g_type == __t) __r = (!(0)); else __r = g_type_check_class_is_a (__class , __t); __r; })))) (G_TYPE_CHECK_CLASS_TYPE ((klass), CTK_TYPE_FILE_SYSTEM_MODEL)((__extension__ ({ GTypeClass *__class = (GTypeClass*) ((klass )); GType __t = ((_ctk_file_system_model_get_type ())); gboolean __r; if (!__class) __r = (0); else if (__class->g_type == __t) __r = (!(0)); else __r = g_type_check_class_is_a (__class , __t); __r; })))) |
| 196 | #define CTK_FILE_SYSTEM_MODEL_GET_CLASS(obj)((((CtkFileSystemModelClass*) (((GTypeInstance*) ((obj)))-> g_class)))) (G_TYPE_INSTANCE_GET_CLASS ((obj), CTK_TYPE_FILE_SYSTEM_MODEL, CtkFileSystemModelClass)(((CtkFileSystemModelClass*) (((GTypeInstance*) ((obj)))-> g_class)))) |
| 197 | |
| 198 | struct _CtkFileSystemModelClass |
| 199 | { |
| 200 | GObjectClass parent_class; |
| 201 | |
| 202 | /* Signals */ |
| 203 | |
| 204 | void (*finished_loading) (CtkFileSystemModel *model, GError *error); |
| 205 | }; |
| 206 | |
| 207 | static void freeze_updates (CtkFileSystemModel *model); |
| 208 | static void thaw_updates (CtkFileSystemModel *model); |
| 209 | |
| 210 | static guint node_get_for_file (CtkFileSystemModel *model, |
| 211 | GFile *file); |
| 212 | |
| 213 | static void add_file (CtkFileSystemModel *model, |
| 214 | GFile *file, |
| 215 | GFileInfo *info); |
| 216 | static void remove_file (CtkFileSystemModel *model, |
| 217 | GFile *file); |
| 218 | |
| 219 | /* iter setup: |
| 220 | * @user_data: the model |
| 221 | * @user_data2: GUINT_TO_POINTER of array index of current entry |
| 222 | * |
| 223 | * All other fields are unused. Note that the array index does not corrspond |
| 224 | * 1:1 with the path index as entries might not be visible. |
| 225 | */ |
| 226 | #define ITER_INDEX(iter)((guint) (gulong) ((iter)->user_data2)) GPOINTER_TO_UINT((iter)->user_data2)((guint) (gulong) ((iter)->user_data2)) |
| 227 | #define ITER_IS_VALID(model, iter)((model) == (iter)->user_data) ((model) == (iter)->user_data) |
| 228 | #define ITER_INIT_FROM_INDEX(model, _iter, _index)do { do { if (_index < (model)->files->len) ; else g_assertion_message_expr ("Ctk", "ctkfilesystemmodel.c", 228, ((const char*) (__func__ )), "_index < (model)->files->len"); } while (0); (_iter )->user_data = (model); (_iter)->user_data2 = ((gpointer ) (gulong) (_index)); }while (0) G_STMT_STARTdo {\ |
| 229 | g_assert (_index < (model)->files->len)do { if (_index < (model)->files->len) ; else g_assertion_message_expr ("Ctk", "ctkfilesystemmodel.c", 229, ((const char*) (__func__ )), "_index < (model)->files->len"); } while (0); \ |
| 230 | (_iter)->user_data = (model); \ |
| 231 | (_iter)->user_data2 = GUINT_TO_POINTER (_index)((gpointer) (gulong) (_index)); \ |
| 232 | }G_STMT_ENDwhile (0) |
| 233 | |
| 234 | /*** FileModelNode ***/ |
| 235 | |
| 236 | /* Get a FileModelNode structure given an index in the model->files array of nodes */ |
| 237 | #define get_node(_model, _index)((FileModelNode *) ((_model)->files->data + (_index) * ( _model)->node_size)) ((FileModelNode *) ((_model)->files->data + (_index) * (_model)->node_size)) |
| 238 | |
| 239 | /* Get an index within the model->files array of nodes, given a FileModelNode* */ |
| 240 | #define node_index(_model, _node)(((gchar *) (_node) - (_model)->files->data) / (_model) ->node_size) (((gchar *) (_node) - (_model)->files->data) / (_model)->node_size) |
| 241 | |
| 242 | /* @up_to_index: smallest model->files array index that will be valid after this call |
| 243 | * @up_to_row: smallest node->row that will be valid after this call |
| 244 | * |
| 245 | * If you want to validate up to an index or up to a row, specify the index or |
| 246 | * the row you want and specify G_MAXUINT for the other argument. Pass |
| 247 | * G_MAXUINT for both arguments for “validate everything”. |
| 248 | */ |
| 249 | static void |
| 250 | node_validate_rows (CtkFileSystemModel *model, guint up_to_index, guint up_to_row) |
| 251 | { |
| 252 | guint i, row; |
| 253 | |
| 254 | if (model->files->len == 0) |
| 255 | return; |
| 256 | |
| 257 | up_to_index = MIN (up_to_index, model->files->len - 1)(((up_to_index) < (model->files->len - 1)) ? (up_to_index ) : (model->files->len - 1)); |
| 258 | |
| 259 | i = model->n_nodes_valid; |
| 260 | if (i != 0) |
| 261 | row = get_node (model, i - 1)((FileModelNode *) ((model)->files->data + (i - 1) * (model )->node_size))->row; |
| 262 | else |
| 263 | row = 0; |
| 264 | |
| 265 | while (i <= up_to_index && row <= up_to_row) |
| 266 | { |
| 267 | FileModelNode *node = get_node (model, i)((FileModelNode *) ((model)->files->data + (i) * (model )->node_size)); |
| 268 | if (node->visible) |
| 269 | row++; |
| 270 | node->row = row; |
| 271 | i++; |
| 272 | } |
| 273 | model->n_nodes_valid = i; |
| 274 | } |
| 275 | |
| 276 | static guint |
| 277 | node_get_tree_row (CtkFileSystemModel *model, guint index) |
| 278 | { |
| 279 | if (model->n_nodes_valid <= index) |
| 280 | node_validate_rows (model, index, G_MAXUINT(2147483647 *2U +1U)); |
| 281 | |
| 282 | return get_node (model, index)((FileModelNode *) ((model)->files->data + (index) * (model )->node_size))->row - 1; |
| 283 | } |
| 284 | |
| 285 | static void |
| 286 | node_invalidate_index (CtkFileSystemModel *model, guint id) |
| 287 | { |
| 288 | model->n_nodes_valid = MIN (model->n_nodes_valid, id)(((model->n_nodes_valid) < (id)) ? (model->n_nodes_valid ) : (id)); |
| 289 | } |
| 290 | |
| 291 | static CtkTreePath * |
| 292 | tree_path_new_from_node (CtkFileSystemModel *model, guint id) |
| 293 | { |
| 294 | guint r = node_get_tree_row (model, id); |
| 295 | |
| 296 | g_assert (r < model->files->len)do { if (r < model->files->len) ; else g_assertion_message_expr ("Ctk", "ctkfilesystemmodel.c", 296, ((const char*) (__func__ )), "r < model->files->len"); } while (0); |
| 297 | |
| 298 | return ctk_tree_path_new_from_indices (r, -1); |
| 299 | } |
| 300 | |
| 301 | static void |
| 302 | emit_row_inserted_for_node (CtkFileSystemModel *model, guint id) |
| 303 | { |
| 304 | CtkTreePath *path; |
| 305 | CtkTreeIter iter; |
| 306 | |
| 307 | path = tree_path_new_from_node (model, id); |
| 308 | ITER_INIT_FROM_INDEX (model, &iter, id)do { do { if (id < (model)->files->len) ; else g_assertion_message_expr ("Ctk", "ctkfilesystemmodel.c", 308, ((const char*) (__func__ )), "id < (model)->files->len"); } while (0); (& iter)->user_data = (model); (&iter)->user_data2 = ( (gpointer) (gulong) (id)); }while (0); |
| 309 | ctk_tree_model_row_inserted (CTK_TREE_MODEL (model)((((CtkTreeModel*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((model)), ((ctk_tree_model_get_type ())))))), path, &iter); |
| 310 | ctk_tree_path_free (path); |
| 311 | } |
| 312 | |
| 313 | static void |
| 314 | emit_row_changed_for_node (CtkFileSystemModel *model, guint id) |
| 315 | { |
| 316 | CtkTreePath *path; |
| 317 | CtkTreeIter iter; |
| 318 | |
| 319 | path = tree_path_new_from_node (model, id); |
| 320 | ITER_INIT_FROM_INDEX (model, &iter, id)do { do { if (id < (model)->files->len) ; else g_assertion_message_expr ("Ctk", "ctkfilesystemmodel.c", 320, ((const char*) (__func__ )), "id < (model)->files->len"); } while (0); (& iter)->user_data = (model); (&iter)->user_data2 = ( (gpointer) (gulong) (id)); }while (0); |
| 321 | ctk_tree_model_row_changed (CTK_TREE_MODEL (model)((((CtkTreeModel*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((model)), ((ctk_tree_model_get_type ())))))), path, &iter); |
| 322 | ctk_tree_path_free (path); |
| 323 | } |
| 324 | |
| 325 | static void |
| 326 | emit_row_deleted_for_row (CtkFileSystemModel *model, guint row) |
| 327 | { |
| 328 | CtkTreePath *path; |
| 329 | |
| 330 | path = ctk_tree_path_new_from_indices (row, -1); |
| 331 | ctk_tree_model_row_deleted (CTK_TREE_MODEL (model)((((CtkTreeModel*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((model)), ((ctk_tree_model_get_type ())))))), path); |
| 332 | ctk_tree_path_free (path); |
| 333 | } |
| 334 | |
| 335 | static void |
| 336 | node_set_visible_and_filtered_out (CtkFileSystemModel *model, guint id, gboolean visible, gboolean filtered_out) |
| 337 | { |
| 338 | FileModelNode *node = get_node (model, id)((FileModelNode *) ((model)->files->data + (id) * (model )->node_size)); |
| 339 | |
| 340 | /* Filteredness */ |
| 341 | |
| 342 | if (node->filtered_out != filtered_out) |
| 343 | { |
| 344 | node->filtered_out = filtered_out; |
| 345 | if (node->visible && visible) |
| 346 | emit_row_changed_for_node (model, id); |
| 347 | } |
| 348 | |
| 349 | /* Visibility */ |
| 350 | |
| 351 | if (node->visible == visible || |
| 352 | node->frozen_add) |
| 353 | return; |
| 354 | |
| 355 | if (visible) |
| 356 | { |
| 357 | node->visible = TRUE(!(0)); |
| 358 | node_invalidate_index (model, id); |
| 359 | emit_row_inserted_for_node (model, id); |
| 360 | } |
| 361 | else |
| 362 | { |
| 363 | guint row; |
| 364 | |
| 365 | row = node_get_tree_row (model, id); |
| 366 | g_assert (row < model->files->len)do { if (row < model->files->len) ; else g_assertion_message_expr ("Ctk", "ctkfilesystemmodel.c", 366, ((const char*) (__func__ )), "row < model->files->len"); } while (0); |
| 367 | |
| 368 | node->visible = FALSE(0); |
| 369 | node_invalidate_index (model, id); |
| 370 | emit_row_deleted_for_row (model, row); |
| 371 | } |
| 372 | } |
| 373 | |
| 374 | static gboolean |
| 375 | node_should_be_filtered_out (CtkFileSystemModel *model, guint id) |
| 376 | { |
| 377 | FileModelNode *node = get_node (model, id)((FileModelNode *) ((model)->files->data + (id) * (model )->node_size)); |
| 378 | CtkFileFilterInfo filter_info = { 0, }; |
| 379 | CtkFileFilterFlags required; |
| 380 | gboolean result; |
| 381 | char *mime_type = NULL((void*)0); |
| 382 | char *filename = NULL((void*)0); |
| 383 | char *uri = NULL((void*)0); |
| 384 | |
| 385 | if (node->info == NULL((void*)0)) |
| 386 | return TRUE(!(0)); |
| 387 | |
| 388 | if (model->filter == NULL((void*)0)) |
| 389 | return FALSE(0); |
| 390 | |
| 391 | /* fill info */ |
| 392 | required = ctk_file_filter_get_needed (model->filter); |
| 393 | |
| 394 | filter_info.contains = CTK_FILE_FILTER_DISPLAY_NAME; |
| 395 | filter_info.display_name = g_file_info_get_display_name (node->info); |
| 396 | |
| 397 | if (required & CTK_FILE_FILTER_MIME_TYPE) |
| 398 | { |
| 399 | const char *s = g_file_info_get_content_type (node->info); |
| 400 | |
| 401 | if (!s) |
| 402 | s = g_file_info_get_attribute_string (node->info, G_FILE_ATTRIBUTE_STANDARD_FAST_CONTENT_TYPE"standard::fast-content-type"); |
| 403 | |
| 404 | if (s) |
| 405 | { |
| 406 | mime_type = g_content_type_get_mime_type (s); |
| 407 | if (mime_type) |
| 408 | { |
| 409 | filter_info.mime_type = mime_type; |
| 410 | filter_info.contains |= CTK_FILE_FILTER_MIME_TYPE; |
| 411 | } |
| 412 | } |
| 413 | } |
| 414 | |
| 415 | if (required & CTK_FILE_FILTER_FILENAME) |
| 416 | { |
| 417 | filename = g_file_get_path (node->file); |
| 418 | if (filename) |
| 419 | { |
| 420 | filter_info.filename = filename; |
| 421 | filter_info.contains |= CTK_FILE_FILTER_FILENAME; |
| 422 | } |
| 423 | } |
| 424 | |
| 425 | if (required & CTK_FILE_FILTER_URI) |
| 426 | { |
| 427 | uri = g_file_get_uri (node->file); |
| 428 | if (uri) |
| 429 | { |
| 430 | filter_info.uri = uri; |
| 431 | filter_info.contains |= CTK_FILE_FILTER_URI; |
| 432 | } |
| 433 | } |
| 434 | |
| 435 | result = !ctk_file_filter_filter (model->filter, &filter_info); |
| 436 | |
| 437 | g_free (mime_type); |
| 438 | g_free (filename); |
| 439 | g_free (uri); |
| 440 | |
| 441 | return result; |
| 442 | } |
| 443 | |
| 444 | static gboolean |
| 445 | node_should_be_visible (CtkFileSystemModel *model, guint id, gboolean filtered_out) |
| 446 | { |
| 447 | FileModelNode *node = get_node (model, id)((FileModelNode *) ((model)->files->data + (id) * (model )->node_size)); |
| 448 | gboolean result; |
| 449 | |
| 450 | if (node->info == NULL((void*)0)) |
| 451 | return FALSE(0); |
| 452 | |
| 453 | if (!model->show_hidden && |
| 454 | (g_file_info_get_is_hidden (node->info) || g_file_info_get_is_backup (node->info))) |
| 455 | return FALSE(0); |
| 456 | |
| 457 | if (_ctk_file_info_consider_as_directory (node->info)) |
| 458 | { |
| 459 | if (!model->show_folders) |
| 460 | return FALSE(0); |
| 461 | |
| 462 | if (!model->filter_folders) |
| 463 | return TRUE(!(0)); |
| 464 | } |
| 465 | else |
| 466 | { |
| 467 | if (!model->show_files) |
| 468 | return FALSE(0); |
| 469 | } |
| 470 | |
| 471 | result = !filtered_out; |
| 472 | |
| 473 | return result; |
| 474 | } |
| 475 | |
| 476 | static void |
| 477 | node_compute_visibility_and_filters (CtkFileSystemModel *model, guint id) |
| 478 | { |
| 479 | gboolean filtered_out; |
| 480 | gboolean visible; |
| 481 | |
| 482 | filtered_out = node_should_be_filtered_out (model, id); |
| 483 | visible = node_should_be_visible (model, id, filtered_out); |
| 484 | |
| 485 | node_set_visible_and_filtered_out (model, id, visible, filtered_out); |
| 486 | } |
| 487 | |
| 488 | /*** CtkTreeModel ***/ |
| 489 | |
| 490 | static CtkTreeModelFlags |
| 491 | ctk_file_system_model_get_flags (CtkTreeModel *tree_model G_GNUC_UNUSED__attribute__ ((__unused__))) |
| 492 | { |
| 493 | /* CTK_TREE_MODEL_ITERS_PERSIST doesn't work with arrays :( */ |
| 494 | return CTK_TREE_MODEL_LIST_ONLY; |
| 495 | } |
| 496 | |
| 497 | static gint |
| 498 | ctk_file_system_model_get_n_columns (CtkTreeModel *tree_model) |
| 499 | { |
| 500 | CtkFileSystemModel *model = CTK_FILE_SYSTEM_MODEL (tree_model)((((CtkFileSystemModel*) (void *) g_type_check_instance_cast ( (GTypeInstance*) ((tree_model)), ((_ctk_file_system_model_get_type ())))))); |
| 501 | |
| 502 | return model->n_columns; |
| 503 | } |
| 504 | |
| 505 | static GType |
| 506 | ctk_file_system_model_get_column_type (CtkTreeModel *tree_model, |
| 507 | gint i) |
| 508 | { |
| 509 | CtkFileSystemModel *model = CTK_FILE_SYSTEM_MODEL (tree_model)((((CtkFileSystemModel*) (void *) g_type_check_instance_cast ( (GTypeInstance*) ((tree_model)), ((_ctk_file_system_model_get_type ())))))); |
| 510 | |
| 511 | g_return_val_if_fail (i >= 0 && (guint) i < model->n_columns, G_TYPE_NONE)do { if ((i >= 0 && (guint) i < model->n_columns )) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "i >= 0 && (guint) i < model->n_columns" ); return (((GType) ((1) << (2)))); } } while (0); |
| 512 | |
| 513 | return model->column_types[i]; |
| 514 | } |
| 515 | |
| 516 | static int |
| 517 | compare_indices (gconstpointer key, gconstpointer _node) |
| 518 | { |
| 519 | const FileModelNode *node = _node; |
| 520 | |
| 521 | return GPOINTER_TO_UINT (key)((guint) (gulong) (key)) - node->row; |
| 522 | } |
| 523 | |
| 524 | static gboolean |
| 525 | ctk_file_system_model_iter_nth_child (CtkTreeModel *tree_model, |
| 526 | CtkTreeIter *iter, |
| 527 | CtkTreeIter *parent, |
| 528 | gint n) |
| 529 | { |
| 530 | CtkFileSystemModel *model = CTK_FILE_SYSTEM_MODEL (tree_model)((((CtkFileSystemModel*) (void *) g_type_check_instance_cast ( (GTypeInstance*) ((tree_model)), ((_ctk_file_system_model_get_type ())))))); |
| 531 | guint id; |
| 532 | guint row_to_find; |
| 533 | |
| 534 | g_return_val_if_fail (n >= 0, FALSE)do { if ((n >= 0)) { } else { g_return_if_fail_warning ("Ctk" , ((const char*) (__func__)), "n >= 0"); return ((0)); } } while (0); |
| 535 | |
| 536 | if (parent != NULL((void*)0)) |
| 537 | return FALSE(0); |
| 538 | |
| 539 | row_to_find = n + 1; /* plus one as our node->row numbers are 1-based; see the "Structure" comment at the beginning */ |
| 540 | |
| 541 | if (model->n_nodes_valid > 0 && |
| 542 | get_node (model, model->n_nodes_valid - 1)((FileModelNode *) ((model)->files->data + (model->n_nodes_valid - 1) * (model)->node_size))->row >= row_to_find) |
| 543 | { |
| 544 | char *node; |
| 545 | |
| 546 | /* Fast path - the nodes are valid up to the sought one. |
| 547 | * |
| 548 | * First, find a node with the sought row number...*/ |
| 549 | |
| 550 | node = bsearch (GUINT_TO_POINTER (row_to_find)((gpointer) (gulong) (row_to_find)), |
| 551 | model->files->data, |
| 552 | model->n_nodes_valid, |
| 553 | model->node_size, |
| 554 | compare_indices); |
| 555 | if (node == NULL((void*)0)) |
| 556 | return FALSE(0); |
| 557 | |
| 558 | /* ... Second, back up until we find the first visible node with that row number */ |
| 559 | |
| 560 | id = node_index (model, node)(((gchar *) (node) - (model)->files->data) / (model)-> node_size); |
| 561 | while (!get_node (model, id)((FileModelNode *) ((model)->files->data + (id) * (model )->node_size))->visible) |
| 562 | id--; |
| 563 | |
| 564 | g_assert (get_node (model, id)->row == row_to_find)do { if (((FileModelNode *) ((model)->files->data + (id ) * (model)->node_size))->row == row_to_find) ; else g_assertion_message_expr ("Ctk", "ctkfilesystemmodel.c", 564, ((const char*) (__func__ )), "get_node (model, id)->row == row_to_find"); } while ( 0); |
| 565 | } |
| 566 | else |
| 567 | { |
| 568 | /* Slow path - the nodes need to be validated up to the sought one */ |
| 569 | |
| 570 | node_validate_rows (model, G_MAXUINT(2147483647 *2U +1U), n); /* note that this is really "n", not row_to_find - see node_validate_rows() */ |
| 571 | id = model->n_nodes_valid - 1; |
| 572 | if (model->n_nodes_valid == 0 || get_node (model, id)((FileModelNode *) ((model)->files->data + (id) * (model )->node_size))->row != row_to_find) |
| 573 | return FALSE(0); |
| 574 | } |
| 575 | |
| 576 | ITER_INIT_FROM_INDEX (model, iter, id)do { do { if (id < (model)->files->len) ; else g_assertion_message_expr ("Ctk", "ctkfilesystemmodel.c", 576, ((const char*) (__func__ )), "id < (model)->files->len"); } while (0); (iter) ->user_data = (model); (iter)->user_data2 = ((gpointer) (gulong) (id)); }while (0); |
| 577 | return TRUE(!(0)); |
| 578 | } |
| 579 | |
| 580 | static gboolean |
| 581 | ctk_file_system_model_get_iter (CtkTreeModel *tree_model, |
| 582 | CtkTreeIter *iter, |
| 583 | CtkTreePath *path) |
| 584 | { |
| 585 | g_return_val_if_fail (ctk_tree_path_get_depth (path) > 0, FALSE)do { if ((ctk_tree_path_get_depth (path) > 0)) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "ctk_tree_path_get_depth (path) > 0" ); return ((0)); } } while (0); |
| 586 | |
| 587 | if (ctk_tree_path_get_depth (path) > 1) |
| 588 | return FALSE(0); |
| 589 | |
| 590 | return ctk_file_system_model_iter_nth_child (tree_model, |
| 591 | iter, |
| 592 | NULL((void*)0), |
| 593 | ctk_tree_path_get_indices (path)[0]); |
| 594 | } |
| 595 | |
| 596 | static CtkTreePath * |
| 597 | ctk_file_system_model_get_path (CtkTreeModel *tree_model, |
| 598 | CtkTreeIter *iter) |
| 599 | { |
| 600 | CtkFileSystemModel *model = CTK_FILE_SYSTEM_MODEL (tree_model)((((CtkFileSystemModel*) (void *) g_type_check_instance_cast ( (GTypeInstance*) ((tree_model)), ((_ctk_file_system_model_get_type ())))))); |
| 601 | |
| 602 | g_return_val_if_fail (ITER_IS_VALID (model, iter), NULL)do { if ((((model) == (iter)->user_data))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "ITER_IS_VALID (model, iter)" ); return (((void*)0)); } } while (0); |
| 603 | |
| 604 | return tree_path_new_from_node (model, ITER_INDEX (iter)((guint) (gulong) ((iter)->user_data2))); |
| 605 | } |
| 606 | |
| 607 | static void |
| 608 | ctk_file_system_model_get_value (CtkTreeModel *tree_model, |
| 609 | CtkTreeIter *iter, |
| 610 | gint column, |
| 611 | GValue *value) |
| 612 | { |
| 613 | CtkFileSystemModel *model = CTK_FILE_SYSTEM_MODEL (tree_model)((((CtkFileSystemModel*) (void *) g_type_check_instance_cast ( (GTypeInstance*) ((tree_model)), ((_ctk_file_system_model_get_type ())))))); |
| 614 | const GValue *original; |
| 615 | |
| 616 | g_return_if_fail ((guint) column < model->n_columns)do { if (((guint) column < model->n_columns)) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "(guint) column < model->n_columns"); return; } } while (0); |
| 617 | g_return_if_fail (ITER_IS_VALID (model, iter))do { if ((((model) == (iter)->user_data))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "ITER_IS_VALID (model, iter)" ); return; } } while (0); |
| 618 | |
| 619 | original = _ctk_file_system_model_get_value (model, iter, column); |
| 620 | if (original) |
| 621 | { |
| 622 | g_value_init (value, G_VALUE_TYPE (original)(((GValue*) (original))->g_type)); |
| 623 | g_value_copy (original, value); |
| 624 | } |
| 625 | else |
| 626 | g_value_init (value, model->column_types[column]); |
| 627 | } |
| 628 | |
| 629 | static gboolean |
| 630 | ctk_file_system_model_iter_next (CtkTreeModel *tree_model, |
| 631 | CtkTreeIter *iter) |
| 632 | { |
| 633 | CtkFileSystemModel *model = CTK_FILE_SYSTEM_MODEL (tree_model)((((CtkFileSystemModel*) (void *) g_type_check_instance_cast ( (GTypeInstance*) ((tree_model)), ((_ctk_file_system_model_get_type ())))))); |
| 634 | guint i; |
| 635 | |
| 636 | g_return_val_if_fail (ITER_IS_VALID (model, iter), FALSE)do { if ((((model) == (iter)->user_data))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "ITER_IS_VALID (model, iter)" ); return ((0)); } } while (0); |
| 637 | |
| 638 | for (i = ITER_INDEX (iter)((guint) (gulong) ((iter)->user_data2)) + 1; i < model->files->len; i++) |
| 639 | { |
| 640 | FileModelNode *node = get_node (model, i)((FileModelNode *) ((model)->files->data + (i) * (model )->node_size)); |
| 641 | |
| 642 | if (node->visible) |
| 643 | { |
| 644 | ITER_INIT_FROM_INDEX (model, iter, i)do { do { if (i < (model)->files->len) ; else g_assertion_message_expr ("Ctk", "ctkfilesystemmodel.c", 644, ((const char*) (__func__ )), "i < (model)->files->len"); } while (0); (iter)-> user_data = (model); (iter)->user_data2 = ((gpointer) (gulong ) (i)); }while (0); |
| 645 | return TRUE(!(0)); |
| 646 | } |
| 647 | } |
| 648 | |
| 649 | return FALSE(0); |
| 650 | } |
| 651 | |
| 652 | static gboolean |
| 653 | ctk_file_system_model_iter_children (CtkTreeModel *tree_model G_GNUC_UNUSED__attribute__ ((__unused__)), |
| 654 | CtkTreeIter *iter G_GNUC_UNUSED__attribute__ ((__unused__)), |
| 655 | CtkTreeIter *parent G_GNUC_UNUSED__attribute__ ((__unused__))) |
| 656 | { |
| 657 | return FALSE(0); |
| 658 | } |
| 659 | |
| 660 | static gboolean |
| 661 | ctk_file_system_model_iter_has_child (CtkTreeModel *tree_model G_GNUC_UNUSED__attribute__ ((__unused__)), |
| 662 | CtkTreeIter *iter G_GNUC_UNUSED__attribute__ ((__unused__))) |
| 663 | { |
| 664 | return FALSE(0); |
| 665 | } |
| 666 | |
| 667 | static gint |
| 668 | ctk_file_system_model_iter_n_children (CtkTreeModel *tree_model, |
| 669 | CtkTreeIter *iter) |
| 670 | { |
| 671 | CtkFileSystemModel *model = CTK_FILE_SYSTEM_MODEL (tree_model)((((CtkFileSystemModel*) (void *) g_type_check_instance_cast ( (GTypeInstance*) ((tree_model)), ((_ctk_file_system_model_get_type ())))))); |
| 672 | |
| 673 | if (iter) |
| 674 | return 0; |
| 675 | |
| 676 | return node_get_tree_row (model, model->files->len - 1) + 1; |
| 677 | } |
| 678 | |
| 679 | static gboolean |
| 680 | ctk_file_system_model_iter_parent (CtkTreeModel *tree_model G_GNUC_UNUSED__attribute__ ((__unused__)), |
| 681 | CtkTreeIter *iter G_GNUC_UNUSED__attribute__ ((__unused__)), |
| 682 | CtkTreeIter *child G_GNUC_UNUSED__attribute__ ((__unused__))) |
| 683 | { |
| 684 | return FALSE(0); |
| 685 | } |
| 686 | |
| 687 | static void |
| 688 | ctk_file_system_model_ref_node (CtkTreeModel *tree_model G_GNUC_UNUSED__attribute__ ((__unused__)), |
| 689 | CtkTreeIter *iter G_GNUC_UNUSED__attribute__ ((__unused__))) |
| 690 | { |
| 691 | /* nothing to do */ |
| 692 | } |
| 693 | |
| 694 | static void |
| 695 | ctk_file_system_model_unref_node (CtkTreeModel *tree_model G_GNUC_UNUSED__attribute__ ((__unused__)), |
| 696 | CtkTreeIter *iter G_GNUC_UNUSED__attribute__ ((__unused__))) |
| 697 | { |
| 698 | /* nothing to do */ |
| 699 | } |
| 700 | |
| 701 | static void |
| 702 | ctk_file_system_model_iface_init (CtkTreeModelIface *iface) |
| 703 | { |
| 704 | iface->get_flags = ctk_file_system_model_get_flags; |
| 705 | iface->get_n_columns = ctk_file_system_model_get_n_columns; |
| 706 | iface->get_column_type = ctk_file_system_model_get_column_type; |
| 707 | iface->get_iter = ctk_file_system_model_get_iter; |
| 708 | iface->get_path = ctk_file_system_model_get_path; |
| 709 | iface->get_value = ctk_file_system_model_get_value; |
| 710 | iface->iter_next = ctk_file_system_model_iter_next; |
| 711 | iface->iter_children = ctk_file_system_model_iter_children; |
| 712 | iface->iter_has_child = ctk_file_system_model_iter_has_child; |
| 713 | iface->iter_n_children = ctk_file_system_model_iter_n_children; |
| 714 | iface->iter_nth_child = ctk_file_system_model_iter_nth_child; |
| 715 | iface->iter_parent = ctk_file_system_model_iter_parent; |
| 716 | iface->ref_node = ctk_file_system_model_ref_node; |
| 717 | iface->unref_node = ctk_file_system_model_unref_node; |
| 718 | } |
| 719 | |
| 720 | /*** CtkTreeSortable ***/ |
| 721 | |
| 722 | typedef struct _SortData SortData; |
| 723 | struct _SortData { |
| 724 | CtkFileSystemModel * model; |
| 725 | CtkTreeIterCompareFunc func; |
| 726 | gpointer data; |
| 727 | int order; /* -1 to invert sort order or 1 to keep it */ |
| 728 | }; |
| 729 | |
| 730 | /* returns FALSE if no sort necessary */ |
| 731 | static gboolean |
| 732 | sort_data_init (SortData *data, CtkFileSystemModel *model) |
| 733 | { |
| 734 | CtkTreeDataSortHeader *header; |
| 735 | |
| 736 | if (model->files->len <= 2) |
| 737 | return FALSE(0); |
| 738 | |
| 739 | switch (model->sort_column_id) |
| 740 | { |
| 741 | case CTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID(-1): |
| 742 | if (!model->default_sort_func) |
| 743 | return FALSE(0); |
| 744 | data->func = model->default_sort_func; |
| 745 | data->data = model->default_sort_data; |
| 746 | break; |
| 747 | case CTK_TREE_SORTABLE_UNSORTED_SORT_COLUMN_ID(-2): |
| 748 | return FALSE(0); |
| 749 | default: |
| 750 | header = _ctk_tree_data_list_get_header (model->sort_list, model->sort_column_id); |
| 751 | if (header == NULL((void*)0)) |
| 752 | return FALSE(0); |
| 753 | data->func = header->func; |
| 754 | data->data = header->data; |
| 755 | break; |
| 756 | } |
| 757 | |
| 758 | data->order = model->sort_order == CTK_SORT_DESCENDING ? -1 : 1; |
| 759 | data->model = model; |
| 760 | return TRUE(!(0)); |
| 761 | } |
| 762 | |
| 763 | static int |
| 764 | compare_array_element (gconstpointer a, gconstpointer b, gpointer user_data) |
| 765 | { |
| 766 | SortData *data = user_data; |
| 767 | CtkTreeIter itera, iterb; |
| 768 | |
| 769 | ITER_INIT_FROM_INDEX (data->model, &itera, node_index (data->model, a))do { do { if ((((gchar *) (a) - (data->model)->files-> data) / (data->model)->node_size) < (data->model) ->files->len) ; else g_assertion_message_expr ("Ctk", "ctkfilesystemmodel.c" , 769, ((const char*) (__func__)), "(((gchar *) (a) - (data->model)->files->data) / (data->model)->node_size) < (data->model)->files->len" ); } while (0); (&itera)->user_data = (data->model) ; (&itera)->user_data2 = ((gpointer) (gulong) ((((gchar *) (a) - (data->model)->files->data) / (data->model )->node_size))); }while (0); |
| 770 | ITER_INIT_FROM_INDEX (data->model, &iterb, node_index (data->model, b))do { do { if ((((gchar *) (b) - (data->model)->files-> data) / (data->model)->node_size) < (data->model) ->files->len) ; else g_assertion_message_expr ("Ctk", "ctkfilesystemmodel.c" , 770, ((const char*) (__func__)), "(((gchar *) (b) - (data->model)->files->data) / (data->model)->node_size) < (data->model)->files->len" ); } while (0); (&iterb)->user_data = (data->model) ; (&iterb)->user_data2 = ((gpointer) (gulong) ((((gchar *) (b) - (data->model)->files->data) / (data->model )->node_size))); }while (0); |
| 771 | return data->func (CTK_TREE_MODEL (data->model)((((CtkTreeModel*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((data->model)), ((ctk_tree_model_get_type ())))))), &itera, &iterb, data->data) * data->order; |
| 772 | } |
| 773 | |
| 774 | static void |
| 775 | ctk_file_system_model_sort (CtkFileSystemModel *model) |
| 776 | { |
| 777 | SortData data; |
| 778 | |
| 779 | if (model->frozen) |
| 780 | { |
| 781 | model->sort_on_thaw = TRUE(!(0)); |
| 782 | return; |
| 783 | } |
| 784 | |
| 785 | if (sort_data_init (&data, model)) |
| 786 | { |
| 787 | guint i; |
| 788 | guint r, n_visible_rows; |
| 789 | |
| 790 | node_validate_rows (model, G_MAXUINT(2147483647 *2U +1U), G_MAXUINT(2147483647 *2U +1U)); |
| 791 | n_visible_rows = node_get_tree_row (model, model->files->len - 1) + 1; |
| 792 | model->n_nodes_valid = 0; |
| 793 | g_hash_table_remove_all (model->file_lookup); |
| 794 | g_sort_array (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; |
Casting a non-structure type to a structure type and accessing a field can lead to memory access errors or data corruption | |
| 2073 | |
| 2074 | if (model->filter_on_thaw) |
| 2075 | ctk_file_system_model_refilter_all (model); |
| 2076 | if (model->sort_on_thaw) |
| 2077 | ctk_file_system_model_sort (model); |
| 2078 | if (stuff_added) |
| 2079 | { |
| 2080 | guint i; |
| 2081 | |
| 2082 | for (i = 0; i < model->files->len; i++) |
| 2083 | { |
| 2084 | FileModelNode *node = get_node (model, i)((FileModelNode *) ((model)->files->data + (i) * (model )->node_size)); |
| 2085 | |
| 2086 | if (!node->frozen_add) |
| 2087 | continue; |
| 2088 | node->frozen_add = FALSE(0); |
| 2089 | node_compute_visibility_and_filters (model, i); |
| 2090 | } |
| 2091 | } |
| 2092 | } |
| 2093 | |
| 2094 | /** |
| 2095 | * _ctk_file_system_model_clear_cache: |
| 2096 | * @model: a #CtkFileSystemModel |
| 2097 | * @column: the column to clear or -1 for all columns |
| 2098 | * |
| 2099 | * Clears the cached values in the model for the given @column. Use |
| 2100 | * this function whenever your get_value function would return different |
| 2101 | * values for a column. |
| 2102 | * The file chooser uses this for example when the icon theme changes to |
| 2103 | * invalidate the cached pixbufs. |
| 2104 | **/ |
| 2105 | void |
| 2106 | _ctk_file_system_model_clear_cache (CtkFileSystemModel *model, |
| 2107 | int column) |
| 2108 | { |
| 2109 | guint i; |
| 2110 | int start, end; |
| 2111 | gboolean changed; |
| 2112 | |
| 2113 | g_return_if_fail (CTK_IS_FILE_SYSTEM_MODEL (model))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance *) ((model)); GType __t = ((_ctk_file_system_model_get_type ( ))); gboolean __r; if (!__inst) __r = (0); else if (__inst-> g_class && __inst->g_class->g_type == __t) __r = (!(0)); else __r = g_type_check_instance_is_a (__inst, __t); __r; })))))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "CTK_IS_FILE_SYSTEM_MODEL (model)"); return ; } } while (0); |
| 2114 | g_return_if_fail (column >= -1 && (guint) column < model->n_columns)do { if ((column >= -1 && (guint) column < model ->n_columns)) { } else { g_return_if_fail_warning ("Ctk", ( (const char*) (__func__)), "column >= -1 && (guint) column < model->n_columns" ); return; } } while (0); |
| 2115 | |
| 2116 | if (column > -1) |
| 2117 | { |
| 2118 | start = column; |
| 2119 | end = column + 1; |
| 2120 | } |
| 2121 | else |
| 2122 | { |
| 2123 | start = 0; |
| 2124 | end = model->n_columns; |
| 2125 | } |
| 2126 | |
| 2127 | for (i = 0; i < model->files->len; i++) |
| 2128 | { |
| 2129 | FileModelNode *node = get_node (model, i)((FileModelNode *) ((model)->files->data + (i) * (model )->node_size)); |
| 2130 | changed = FALSE(0); |
| 2131 | for (column = start; column < end; column++) |
| 2132 | { |
| 2133 | if (!G_VALUE_TYPE (&node->values[column])(((GValue*) (&node->values[column]))->g_type)) |
| 2134 | continue; |
| 2135 | |
| 2136 | g_value_unset (&node->values[column]); |
| 2137 | changed = TRUE(!(0)); |
| 2138 | } |
| 2139 | |
| 2140 | if (changed && node->visible) |
| 2141 | emit_row_changed_for_node (model, i); |
| 2142 | } |
| 2143 | |
| 2144 | /* FIXME: resort? */ |
| 2145 | } |
| 2146 | |
| 2147 | /** |
| 2148 | * _ctk_file_system_model_add_and_query_file: |
| 2149 | * @model: a #CtkFileSystemModel |
| 2150 | * @file: the file to add |
| 2151 | * @attributes: attributes to query before adding the file |
| 2152 | * |
| 2153 | * This is a conenience function that calls g_file_query_info_async() on |
| 2154 | * the given file, and when successful, adds it to the model. |
| 2155 | * Upon failure, the @file is discarded. |
| 2156 | **/ |
| 2157 | void |
| 2158 | _ctk_file_system_model_add_and_query_file (CtkFileSystemModel *model, |
| 2159 | GFile * file, |
| 2160 | const char * attributes) |
| 2161 | { |
| 2162 | g_return_if_fail (CTK_IS_FILE_SYSTEM_MODEL (model))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance *) ((model)); GType __t = ((_ctk_file_system_model_get_type ( ))); gboolean __r; if (!__inst) __r = (0); else if (__inst-> g_class && __inst->g_class->g_type == __t) __r = (!(0)); else __r = g_type_check_instance_is_a (__inst, __t); __r; })))))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "CTK_IS_FILE_SYSTEM_MODEL (model)"); return ; } } while (0); |
| 2163 | g_return_if_fail (G_IS_FILE (file))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance *) ((file)); GType __t = ((g_file_get_type ())); gboolean __r ; if (!__inst) __r = (0); else if (__inst->g_class && __inst->g_class->g_type == __t) __r = (!(0)); else __r = g_type_check_instance_is_a (__inst, __t); __r; })))))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__ )), "G_IS_FILE (file)"); return; } } while (0); |
| 2164 | g_return_if_fail (attributes != NULL)do { if ((attributes != ((void*)0))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "attributes != NULL"); return ; } } while (0); |
| 2165 | |
| 2166 | g_file_query_info_async (file, |
| 2167 | attributes, |
| 2168 | G_FILE_QUERY_INFO_NONE, |
| 2169 | IO_PRIORITY0, |
| 2170 | model->cancellable, |
| 2171 | ctk_file_system_model_query_done, |
| 2172 | model); |
| 2173 | } |
| 2174 | |
| 2175 | static void |
| 2176 | ctk_file_system_model_one_query_done (GObject * object, |
| 2177 | GAsyncResult *res, |
| 2178 | gpointer data) |
| 2179 | { |
| 2180 | query_done_helper (object, res, data, TRUE(!(0))); |
| 2181 | } |
| 2182 | |
| 2183 | void |
| 2184 | _ctk_file_system_model_add_and_query_files (CtkFileSystemModel *model, |
| 2185 | GList *list, |
| 2186 | const char *attributes) |
| 2187 | { |
| 2188 | GList *l; |
| 2189 | |
| 2190 | g_return_if_fail (CTK_IS_FILE_SYSTEM_MODEL (model))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance *) ((model)); GType __t = ((_ctk_file_system_model_get_type ( ))); gboolean __r; if (!__inst) __r = (0); else if (__inst-> g_class && __inst->g_class->g_type == __t) __r = (!(0)); else __r = g_type_check_instance_is_a (__inst, __t); __r; })))))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "CTK_IS_FILE_SYSTEM_MODEL (model)"); return ; } } while (0); |
| 2191 | g_return_if_fail (attributes != NULL)do { if ((attributes != ((void*)0))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "attributes != NULL"); return ; } } while (0); |
| 2192 | |
| 2193 | for (l = list; l; l = l->next) |
| 2194 | { |
| 2195 | GFile *file; |
| 2196 | |
| 2197 | file = (GFile *)l->data; |
| 2198 | freeze_updates (model); |
| 2199 | g_file_query_info_async (file, |
| 2200 | attributes, |
| 2201 | G_FILE_QUERY_INFO_NONE, |
| 2202 | IO_PRIORITY0, |
| 2203 | model->cancellable, |
| 2204 | ctk_file_system_model_one_query_done, |
| 2205 | model); |
| 2206 | } |
| 2207 | } |
| 2208 | |
| 2209 | GFile * |
| 2210 | _ctk_file_system_model_get_directory (CtkFileSystemModel *model) |
| 2211 | { |
| 2212 | g_return_val_if_fail (CTK_IS_FILE_SYSTEM_MODEL (model), NULL)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance *) ((model)); GType __t = ((_ctk_file_system_model_get_type ( ))); gboolean __r; if (!__inst) __r = (0); else if (__inst-> g_class && __inst->g_class->g_type == __t) __r = (!(0)); else __r = g_type_check_instance_is_a (__inst, __t); __r; })))))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "CTK_IS_FILE_SYSTEM_MODEL (model)"); return (((void*)0)); } } while (0); |
| 2213 | |
| 2214 | return model->dir; |
| 2215 | } |
| 2216 |