gboolean keyword_exists(GtkTreeModel *keyword_tree, GtkTreeIter *parent_ptr, GtkTreeIter *sibling, const gchar *name, gboolean exclude_sibling, GtkTreeIter *result) { GtkTreeIter parent; GtkTreeIter iter; gboolean toplevel = FALSE; gboolean ret; gchar *casefold; if (parent_ptr) { parent = *parent_ptr; } else if (sibling) { toplevel = !gtk_tree_model_iter_parent(keyword_tree, &parent, sibling); } else { toplevel = TRUE; } if (!gtk_tree_model_iter_children(GTK_TREE_MODEL(keyword_tree), &iter, toplevel ? NULL : &parent)) return FALSE; casefold = g_utf8_casefold(name, -1); ret = FALSE; while (TRUE) { if (!(exclude_sibling && sibling && keyword_compare(keyword_tree, &iter, sibling) == 0)) { if (options->metadata.keywords_case_sensitive) { gchar *iter_name = keyword_get_name(keyword_tree, &iter); ret = strcmp(name, iter_name) == 0; g_free(iter_name); } else { gchar *iter_casefold = keyword_get_casefold(keyword_tree, &iter); ret = strcmp(casefold, iter_casefold) == 0; g_free(iter_casefold); } // if (options->metadata.tags_cas... } if (ret) { if (result) *result = iter; break; } if (!gtk_tree_model_iter_next(keyword_tree, &iter)) break; } g_free(casefold); return ret; }
gboolean keyword_same_parent(GtkTreeModel *keyword_tree, GtkTreeIter *a, GtkTreeIter *b) { GtkTreeIter parent_a; GtkTreeIter parent_b; gboolean valid_pa = gtk_tree_model_iter_parent(keyword_tree, &parent_a, a); gboolean valid_pb = gtk_tree_model_iter_parent(keyword_tree, &parent_b, b); if (valid_pa && valid_pb) { return keyword_compare(keyword_tree, &parent_a, &parent_b) == 0; } else { return (!valid_pa && !valid_pb); /* both are toplevel */ } }
void meta_data_connect_mark_with_keyword(GtkTreeModel *keyword_tree, GtkTreeIter *kw_iter, gint mark) { FileDataGetMarkFunc get_mark_func; FileDataSetMarkFunc set_mark_func; gpointer mark_func_data; gint i; for (i = 0; i < FILEDATA_MARKS_SIZE; i++) { file_data_get_registered_mark_func(i, &get_mark_func, &set_mark_func, &mark_func_data); if (get_mark_func == meta_data_get_keyword_mark) { GtkTreeIter old_kw_iter; GList *old_path = mark_func_data; if (keyword_tree_get_iter(keyword_tree, &old_kw_iter, old_path) && (i == mark || /* release any previous connection of given mark */ keyword_compare(keyword_tree, &old_kw_iter, kw_iter) == 0)) /* or given keyword */ { file_data_register_mark_func(i, NULL, NULL, NULL, NULL); gtk_tree_store_set(GTK_TREE_STORE(keyword_tree), &old_kw_iter, KEYWORD_COLUMN_MARK, "", -1); } } } if (mark >= 0 && mark < FILEDATA_MARKS_SIZE) { GList *path; gchar *mark_str; path = keyword_tree_get_path(keyword_tree, kw_iter); file_data_register_mark_func(mark, meta_data_get_keyword_mark, meta_data_set_keyword_mark, path, (GDestroyNotify)string_list_free); mark_str = g_strdup_printf("%d", (mark < 9 ? mark : -1) + 1); gtk_tree_store_set(GTK_TREE_STORE(keyword_tree), kw_iter, KEYWORD_COLUMN_MARK, mark_str, -1); g_free(mark_str); } }
static void bar_pane_keywords_dnd_receive(GtkWidget *tree_view, GdkDragContext *context, gint x, gint y, GtkSelectionData *selection_data, guint info, guint time, gpointer data) { PaneKeywordsData *pkd = data; GtkTreePath *tpath = NULL; GtkTreeViewDropPosition pos; GtkTreeModel *model; GtkTreeModel *keyword_tree; gboolean src_valid = FALSE; GList *new_keywords = NULL; GList *work; /* iterators for keyword_tree */ GtkTreeIter src_kw_iter; GtkTreeIter dest_kw_iter; GtkTreeIter new_kw_iter; g_signal_stop_emission_by_name(tree_view, "drag_data_received"); model = gtk_tree_view_get_model(GTK_TREE_VIEW(tree_view)); keyword_tree = gtk_tree_model_filter_get_model(GTK_TREE_MODEL_FILTER(model)); gtk_tree_view_get_dest_row_at_pos(GTK_TREE_VIEW(tree_view), x, y, &tpath, &pos); gtk_tree_view_set_drag_dest_row(GTK_TREE_VIEW(tree_view), NULL, pos); switch (info) { case TARGET_APP_KEYWORD_PATH: { GList *path = *(gpointer *)gtk_selection_data_get_data(selection_data); src_valid = keyword_tree_get_iter(keyword_tree, &src_kw_iter, path); string_list_free(path); break; } default: new_keywords = string_to_keywords_list((gchar *)gtk_selection_data_get_data(selection_data)); break; } if (tpath) { GtkTreeIter dest_iter; gtk_tree_model_get_iter(model, &dest_iter, tpath); gtk_tree_path_free(tpath); gtk_tree_model_filter_convert_iter_to_child_iter(GTK_TREE_MODEL_FILTER(model), &dest_kw_iter, &dest_iter); if (src_valid && gtk_tree_store_is_ancestor(GTK_TREE_STORE(keyword_tree), &src_kw_iter, &dest_kw_iter)) { /* can't move to it's own child */ return; } if (src_valid && keyword_compare(keyword_tree, &src_kw_iter, &dest_kw_iter) == 0) { /* can't move to itself */ return; } if ((pos == GTK_TREE_VIEW_DROP_INTO_OR_BEFORE || pos == GTK_TREE_VIEW_DROP_INTO_OR_AFTER) && !gtk_tree_model_iter_has_child(keyword_tree, &dest_kw_iter)) { /* the node has no children, all keywords can be added */ gtk_tree_store_append(GTK_TREE_STORE(keyword_tree), &new_kw_iter, &dest_kw_iter); } else { if (src_valid && !bar_pane_keywords_dnd_can_move(keyword_tree, &src_kw_iter, &dest_kw_iter)) { /* the keyword can't be moved if the same name already exist */ return; } if (new_keywords && !bar_pane_keywords_dnd_skip_existing(keyword_tree, &dest_kw_iter, &new_keywords)) { /* the keywords can't be added if the same name already exist */ return; } switch (pos) { case GTK_TREE_VIEW_DROP_INTO_OR_BEFORE: case GTK_TREE_VIEW_DROP_BEFORE: gtk_tree_store_insert_before(GTK_TREE_STORE(keyword_tree), &new_kw_iter, NULL, &dest_kw_iter); break; case GTK_TREE_VIEW_DROP_INTO_OR_AFTER: case GTK_TREE_VIEW_DROP_AFTER: gtk_tree_store_insert_after(GTK_TREE_STORE(keyword_tree), &new_kw_iter, NULL, &dest_kw_iter); break; } } } else { if (src_valid && !bar_pane_keywords_dnd_can_move(keyword_tree, &src_kw_iter, NULL)) { /* the keyword can't be moved if the same name already exist */ return; } if (new_keywords && !bar_pane_keywords_dnd_skip_existing(keyword_tree, NULL, &new_keywords)) { /* the keywords can't be added if the same name already exist */ return; } gtk_tree_store_append(GTK_TREE_STORE(keyword_tree), &new_kw_iter, NULL); } if (src_valid) { keyword_move_recursive(GTK_TREE_STORE(keyword_tree), &new_kw_iter, &src_kw_iter); } work = new_keywords; while (work) { gchar *keyword = work->data; keyword_set(GTK_TREE_STORE(keyword_tree), &new_kw_iter, keyword, TRUE); work = work->next; if (work) { GtkTreeIter add; gtk_tree_store_insert_after(GTK_TREE_STORE(keyword_tree), &add, NULL, &new_kw_iter); new_kw_iter = add; } } string_list_free(new_keywords); bar_keyword_tree_sync(pkd); }