void nemo_directory_notify_files_added_by_uri (GList *uris) { GList *files; files = nemo_file_list_from_uris (uris); nemo_directory_notify_files_added (files); g_list_free_full (files, g_object_unref); }
gboolean nemo_link_local_create (const char *directory_uri, const char *base_name, const char *display_name, const char *image, const char *target_uri, const GdkPoint *point, int screen, gboolean unique_filename) { char *real_directory_uri; char *uri, *contents; GFile *file; GList dummy_list; NemoFileChangesQueuePosition item; g_return_val_if_fail (directory_uri != NULL, FALSE); g_return_val_if_fail (base_name != NULL, FALSE); g_return_val_if_fail (display_name != NULL, FALSE); g_return_val_if_fail (target_uri != NULL, FALSE); if (eel_uri_is_trash (directory_uri) || eel_uri_is_search (directory_uri)) { return FALSE; } if (eel_uri_is_desktop (directory_uri)) { real_directory_uri = nemo_get_desktop_directory_uri (); } else { real_directory_uri = g_strdup (directory_uri); } if (unique_filename) { uri = nemo_ensure_unique_file_name (real_directory_uri, base_name, ".desktop"); if (uri == NULL) { g_free (real_directory_uri); return FALSE; } file = g_file_new_for_uri (uri); g_free (uri); } else { char *link_name; GFile *dir; link_name = g_strdup_printf ("%s.desktop", base_name); /* replace '/' with '-', just in case */ g_strdelimit (link_name, "/", '-'); dir = g_file_new_for_uri (directory_uri); file = g_file_get_child (dir, link_name); g_free (link_name); g_object_unref (dir); } g_free (real_directory_uri); contents = g_strdup_printf ("[Desktop Entry]\n" "Encoding=UTF-8\n" "Name=%s\n" "Type=Link\n" "URL=%s\n" "%s%s\n", display_name, target_uri, image != NULL ? "Icon=" : "", image != NULL ? image : ""); if (!g_file_replace_contents (file, contents, strlen (contents), NULL, FALSE, G_FILE_CREATE_NONE, NULL, NULL, NULL)) { g_free (contents); g_object_unref (file); return FALSE; } g_free (contents); dummy_list.data = file; dummy_list.next = NULL; dummy_list.prev = NULL; nemo_directory_notify_files_added (&dummy_list); if (point != NULL) { item.location = file; item.set = TRUE; item.point.x = point->x; item.point.y = point->y; item.screen = screen; dummy_list.data = &item; dummy_list.next = NULL; dummy_list.prev = NULL; nemo_directory_schedule_position_set (&dummy_list); } g_object_unref (file); return TRUE; }
/* go through changes in the change queue, send ones with the same kind * in a list to the different nemo_directory_notify calls */ void nemo_file_changes_consume_changes (gboolean consume_all) { NemoFileChange *change; GList *additions, *changes, *deletions, *moves; GList *position_set_requests; GFilePair *pair; NemoFileChangesQueuePosition *position_set; guint chunk_count; NemoFileChangesQueue *queue; gboolean flush_needed; additions = NULL; changes = NULL; deletions = NULL; moves = NULL; position_set_requests = NULL; queue = nemo_file_changes_queue_get(); /* Consume changes from the queue, stuffing them into one of three lists, * keep doing it while the changes are of the same kind, then send them off. * This is to ensure that the changes get sent off in the same order that they * arrived. */ for (chunk_count = 0; ; chunk_count++) { change = nemo_file_changes_queue_get_change (queue); /* figure out if we need to flush the pending changes that we collected sofar */ if (change == NULL) { flush_needed = TRUE; /* no changes left, flush everything */ } else { flush_needed = additions != NULL && change->kind != CHANGE_FILE_ADDED && change->kind != CHANGE_POSITION_SET && change->kind != CHANGE_POSITION_REMOVE; flush_needed |= changes != NULL && change->kind != CHANGE_FILE_CHANGED; flush_needed |= moves != NULL && change->kind != CHANGE_FILE_MOVED && change->kind != CHANGE_POSITION_SET && change->kind != CHANGE_POSITION_REMOVE; flush_needed |= deletions != NULL && change->kind != CHANGE_FILE_REMOVED; flush_needed |= position_set_requests != NULL && change->kind != CHANGE_POSITION_SET && change->kind != CHANGE_POSITION_REMOVE && change->kind != CHANGE_FILE_ADDED && change->kind != CHANGE_FILE_MOVED; flush_needed |= !consume_all && chunk_count >= CONSUME_CHANGES_MAX_CHUNK; /* we have reached the chunk maximum */ } if (flush_needed) { /* Send changes we collected off. * At one time we may only have one of the lists * contain changes. */ if (deletions != NULL) { deletions = g_list_reverse (deletions); nemo_directory_notify_files_removed (deletions); g_list_free_full (deletions, g_object_unref); deletions = NULL; } if (moves != NULL) { moves = g_list_reverse (moves); nemo_directory_notify_files_moved (moves); pairs_list_free (moves); moves = NULL; } if (additions != NULL) { additions = g_list_reverse (additions); nemo_directory_notify_files_added (additions); g_list_free_full (additions, g_object_unref); additions = NULL; } if (changes != NULL) { changes = g_list_reverse (changes); nemo_directory_notify_files_changed (changes); g_list_free_full (changes, g_object_unref); changes = NULL; } if (position_set_requests != NULL) { position_set_requests = g_list_reverse (position_set_requests); nemo_directory_schedule_position_set (position_set_requests); position_set_list_free (position_set_requests); position_set_requests = NULL; } } if (change == NULL) { /* we are done */ return; } /* add the new change to the list */ switch (change->kind) { case CHANGE_FILE_ADDED: additions = g_list_prepend (additions, change->from); break; case CHANGE_FILE_CHANGED: changes = g_list_prepend (changes, change->from); break; case CHANGE_FILE_REMOVED: deletions = g_list_prepend (deletions, change->from); break; case CHANGE_FILE_MOVED: pair = g_new (GFilePair, 1); pair->from = change->from; pair->to = change->to; moves = g_list_prepend (moves, pair); break; case CHANGE_POSITION_SET: position_set = g_new (NemoFileChangesQueuePosition, 1); position_set->location = change->from; position_set->set = TRUE; position_set->point = change->point; position_set->screen = change->screen; position_set_requests = g_list_prepend (position_set_requests, position_set); break; case CHANGE_POSITION_REMOVE: position_set = g_new (NemoFileChangesQueuePosition, 1); position_set->location = change->from; position_set->set = FALSE; position_set_requests = g_list_prepend (position_set_requests, position_set); break; default: g_assert_not_reached (); break; } g_free (change); } }
void nemo_directory_notify_files_moved (GList *file_pairs) { GList *p, *affected_files, *node; GFilePair *pair; NemoFile *file; NemoDirectory *old_directory, *new_directory; GHashTable *parent_directories; GList *new_files_list, *unref_list; GHashTable *added_lists, *changed_lists; char *name; NemoFileAttributes cancel_attributes; GFile *to_location, *from_location; /* Make a list of added and changed files in each directory. */ new_files_list = NULL; added_lists = g_hash_table_new (NULL, NULL); changed_lists = g_hash_table_new (NULL, NULL); unref_list = NULL; /* Make a list of parent directories that will need their counts updated. */ parent_directories = g_hash_table_new (NULL, NULL); cancel_attributes = nemo_file_get_all_attributes (); for (p = file_pairs; p != NULL; p = p->next) { pair = p->data; from_location = pair->from; to_location = pair->to; /* Handle overwriting a file. */ file = nemo_file_get_existing (to_location); if (file != NULL) { /* Mark it gone and prepare to send the changed signal. */ nemo_file_mark_gone (file); new_directory = file->details->directory; hash_table_list_prepend (changed_lists, new_directory, file); collect_parent_directories (parent_directories, new_directory); } /* Update any directory objects that are affected. */ affected_files = nemo_directory_moved_internal (from_location, to_location); for (node = affected_files; node != NULL; node = node->next) { file = NEMO_FILE (node->data); hash_table_list_prepend (changed_lists, file->details->directory, file); } unref_list = g_list_concat (unref_list, affected_files); /* Move an existing file. */ file = nemo_file_get_existing (from_location); if (file == NULL) { /* Handle this as if it was a new file. */ new_files_list = g_list_prepend (new_files_list, to_location); } else { /* Handle notification in the old directory. */ old_directory = file->details->directory; collect_parent_directories (parent_directories, old_directory); /* Cancel loading of attributes in the old directory */ nemo_directory_cancel_loading_file_attributes (old_directory, file, cancel_attributes); /* Locate the new directory. */ new_directory = get_parent_directory (to_location); collect_parent_directories (parent_directories, new_directory); /* We can unref now -- new_directory is in the * parent directories list so it will be * around until the end of this function * anyway. */ nemo_directory_unref (new_directory); /* Update the file's name and directory. */ name = g_file_get_basename (to_location); nemo_file_update_name_and_directory (file, name, new_directory); g_free (name); /* Update file attributes */ nemo_file_invalidate_attributes (file, NEMO_FILE_ATTRIBUTE_INFO); hash_table_list_prepend (changed_lists, old_directory, file); if (old_directory != new_directory) { hash_table_list_prepend (added_lists, new_directory, file); } /* Unref each file once to balance out nemo_file_get_by_uri. */ unref_list = g_list_prepend (unref_list, file); } } /* Now send out the changed and added signals for existing file objects. */ g_hash_table_foreach (changed_lists, call_files_changed_free_list, NULL); g_hash_table_destroy (changed_lists); g_hash_table_foreach (added_lists, call_files_added_free_list, NULL); g_hash_table_destroy (added_lists); /* Let the file objects go. */ nemo_file_list_free (unref_list); /* Invalidate count for each parent directory. */ g_hash_table_foreach (parent_directories, invalidate_count_and_unref, NULL); g_hash_table_destroy (parent_directories); /* Separate handling for brand new file objects. */ nemo_directory_notify_files_added (new_files_list); g_list_free (new_files_list); }