void nemo_list_model_file_changed (NemoListModel *model, NemoFile *file, NemoDirectory *directory) { FileEntry *parent_file_entry; GtkTreeIter iter; GtkTreePath *path, *parent_path; GSequenceIter *ptr; int pos_before, pos_after, length, i, old; int *new_order; gboolean has_iter; GSequence *files; ptr = lookup_file (model, file, directory); if (!ptr) { return; } pos_before = g_sequence_iter_get_position (ptr); g_sequence_sort_changed (ptr, nemo_list_model_file_entry_compare_func, model); pos_after = g_sequence_iter_get_position (ptr); if (pos_before != pos_after) { /* The file moved, we need to send rows_reordered */ parent_file_entry = ((FileEntry *)g_sequence_get (ptr))->parent; if (parent_file_entry == NULL) { has_iter = FALSE; parent_path = gtk_tree_path_new (); files = model->details->files; } else { has_iter = TRUE; nemo_list_model_ptr_to_iter (model, parent_file_entry->ptr, &iter); parent_path = gtk_tree_model_get_path (GTK_TREE_MODEL (model), &iter); files = parent_file_entry->files; } length = g_sequence_get_length (files); new_order = g_new (int, length); /* Note: new_order[newpos] = oldpos */ for (i = 0, old = 0; i < length; ++i) { if (i == pos_after) { new_order[i] = pos_before; } else { if (old == pos_before) old++; new_order[i] = old++; } } gtk_tree_model_rows_reordered (GTK_TREE_MODEL (model), parent_path, has_iter ? &iter : NULL, new_order); gtk_tree_path_free (parent_path); g_free (new_order); }
// Called from the hub tab when something changes to the user list. void uit_userlist_userchange(ui_tab_t *tab, int change, hub_user_t *user) { tab_t *t = (tab_t *)tab; if(change == UIHUB_UC_JOIN) { user->iter = g_sequence_insert_sorted(t->list->list, user, sort_func, t); ui_listing_inserted(t->list); } else if(change == UIHUB_UC_QUIT) { g_return_if_fail(g_sequence_get(user->iter) == (gpointer)user); ui_listing_remove(t->list, user->iter); g_sequence_remove(user->iter); } else { g_sequence_sort_changed(user->iter, sort_func, t); ui_listing_sorted(t->list); } }
static gboolean g_file_monitor_source_set_pending_change_dirty (GFileMonitorSource *fms, GSequenceIter *iter) { PendingChange *change; change = g_sequence_get (iter); /* if it was already dirty then this change is 'uninteresting' */ if (change->dirty) return FALSE; change->dirty = TRUE; g_sequence_sort_changed (iter, pending_change_compare_ready_time, fms); return TRUE; }
static void on_pattern_name_changed (BtPattern * pattern, GParamSpec * arg, gpointer user_data) { BtPatternListModel *model = BT_PATTERN_LIST_MODEL (user_data); GSequence *seq = model->priv->seq; GtkTreePath *path; GtkTreeIter iter; gint pos1, pos2 = -1, len; // find the item by pattern (cannot use model_item_cmp, as id has changed) iter.stamp = model->priv->stamp; len = g_sequence_get_length (seq); for (pos1 = 0; pos1 < len; pos1++) { iter.user_data = g_sequence_get_iter_at_pos (seq, pos1); if (g_sequence_get (iter.user_data) == pattern) { g_sequence_sort_changed (iter.user_data, model_item_cmp, NULL); pos2 = g_sequence_iter_get_position (iter.user_data); break; } } if (G_UNLIKELY (pos2 == -1)) return; GST_DEBUG ("pos %d -> %d", pos1, pos2); // signal updates if (pos1 != pos2) { path = gtk_tree_path_new (); gtk_tree_path_append_index (path, pos1); gtk_tree_model_row_deleted (GTK_TREE_MODEL (model), path); gtk_tree_path_free (path); path = gtk_tree_path_new (); gtk_tree_path_append_index (path, pos2); gtk_tree_model_row_inserted (GTK_TREE_MODEL (model), path, &iter); gtk_tree_path_free (path); } else { path = gtk_tree_path_new (); gtk_tree_path_append_index (path, pos2); gtk_tree_model_row_changed (GTK_TREE_MODEL (model), path, &iter); gtk_tree_path_free (path); } }
static gboolean g_file_monitor_source_dispatch (GSource *source, GSourceFunc callback, gpointer user_data) { GFileMonitorSource *fms = (GFileMonitorSource *) source; QueuedEvent *event; GQueue event_queue; gint64 now; /* make sure the monitor still exists */ if (!fms->instance) return FALSE; now = g_source_get_time (source); /* Acquire the lock once and grab all events in one go, handling the * queued events first. This avoids strange possibilities in cases of * long delays, such as CHANGED events coming before CREATED events. * * We do this by converting the applicable pending changes into queued * events (after the ones already queued) and then stealing the entire * event queue in one go. */ g_mutex_lock (&fms->lock); /* Create events for any pending changes that are due to fire */ while (!g_sequence_is_empty (fms->pending_changes)) { GSequenceIter *iter = g_sequence_get_begin_iter (fms->pending_changes); PendingChange *pending = g_sequence_get (iter); /* We've gotten to a pending change that's not ready. Stop. */ if (pending_change_get_ready_time (pending, fms) > now) break; if (pending->dirty) { /* It's time to send another CHANGED and update the record */ g_file_monitor_source_queue_event (fms, G_FILE_MONITOR_EVENT_CHANGED, pending->child, NULL); pending->last_emission = now; pending->dirty = FALSE; g_sequence_sort_changed (iter, pending_change_compare_ready_time, fms); } else { /* It's time to send CHANGES_DONE and remove the pending record */ g_file_monitor_source_queue_event (fms, G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT, pending->child, NULL); g_file_monitor_source_remove_pending_change (fms, iter, pending->child); } } /* Steal the queue */ memcpy (&event_queue, &fms->event_queue, sizeof event_queue); memset (&fms->event_queue, 0, sizeof fms->event_queue); g_file_monitor_source_update_ready_time (fms); g_mutex_unlock (&fms->lock); /* We now have our list of events to deliver */ while ((event = g_queue_pop_head (&event_queue))) { /* an event handler could destroy 'instance', so check each time */ if (fms->instance) g_file_monitor_emit_event (fms->instance, event->child, event->other, event->event_type); queued_event_free (event); } return TRUE; }