Skip to content

Commit

Permalink
do not allow to add keywords with the same name as siblings
Browse files Browse the repository at this point in the history
  • Loading branch information
nadvornik committed Mar 13, 2009
1 parent c278646 commit 83a3127
Show file tree
Hide file tree
Showing 3 changed files with 142 additions and 2 deletions.
82 changes: 80 additions & 2 deletions src/bar_keywords.c
Original file line number Diff line number Diff line change
Expand Up @@ -514,6 +514,53 @@ static void bar_pane_keywords_dnd_end(GtkWidget *widget, GdkDragContext *context
{
}


static gboolean bar_pane_keywords_dnd_can_move(GtkTreeModel *keyword_tree, GtkTreeIter *src_kw_iter, GtkTreeIter *dest_kw_iter)
{
gchar *src_name;
GtkTreeIter parent;

if (dest_kw_iter && keyword_same_parent(keyword_tree, src_kw_iter, dest_kw_iter))
{
return TRUE; /* reordering of siblings is ok */
}
if (!dest_kw_iter && !gtk_tree_model_iter_parent(keyword_tree, &parent, src_kw_iter))
{
return TRUE; /* reordering of top-level siblings is ok */
}

src_name = keyword_get_name(keyword_tree, src_kw_iter);
if (keyword_exists(keyword_tree, NULL, dest_kw_iter, src_name, FALSE))
{
g_free(src_name);
return FALSE;
}
g_free(src_name);
return TRUE;
}

static gboolean bar_pane_keywords_dnd_skip_existing(GtkTreeModel *keyword_tree, GtkTreeIter *dest_kw_iter, GList **keywords)
{
/* we have to find at least one keyword that does not already exist as a sibling of dest_kw_iter */
GList *work = *keywords;
while (work)
{
gchar *keyword = work->data;
if (keyword_exists(keyword_tree, NULL, dest_kw_iter, keyword, FALSE))
{
GList *next = work->next;
g_free(keyword);
*keywords = g_list_delete_link(*keywords, work);
work = next;
}
else
{
work = work->next;
}
}
return !!*keywords;
}

static void bar_pane_keywords_dnd_receive(GtkWidget *tree_view, GdkDragContext *context,
gint x, gint y,
GtkSelectionData *selection_data, guint info,
Expand Down Expand Up @@ -580,10 +627,22 @@ static void bar_pane_keywords_dnd_receive(GtkWidget *tree_view, GdkDragContext *
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:
Expand All @@ -596,9 +655,20 @@ static void bar_pane_keywords_dnd_receive(GtkWidget *tree_view, GdkDragContext *
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);
}

Expand All @@ -611,8 +681,10 @@ static void bar_pane_keywords_dnd_receive(GtkWidget *tree_view, GdkDragContext *
work = new_keywords;
while (work)
{
keyword_set(GTK_TREE_STORE(keyword_tree), &new_kw_iter, work->data, TRUE);
gchar *keyword = work->data;
keyword_set(GTK_TREE_STORE(keyword_tree), &new_kw_iter, keyword, TRUE);
work = work->next;

if (work)
{
GtkTreeIter add;
Expand Down Expand Up @@ -705,7 +777,8 @@ static void bar_pane_keywords_edit_ok_cb(GenericDialog *gd, gpointer data)

if (cdd->edit_existing)
{
if (keywords && keywords->data) /* there should be one keyword */
if (keywords && keywords->data && /* there should be one keyword */
!keyword_exists(keyword_tree, NULL, &kw_iter, keywords->data, TRUE))
{
keyword_set(GTK_TREE_STORE(keyword_tree), &kw_iter, keywords->data, cdd->is_keyword);
}
Expand All @@ -717,6 +790,11 @@ static void bar_pane_keywords_edit_ok_cb(GenericDialog *gd, gpointer data)
while (work)
{
GtkTreeIter add;
if (keyword_exists(keyword_tree, NULL, have_dest ? &kw_iter : NULL, work->data, FALSE))
{
work = work->next;
continue;
}
if (have_dest)
{
gtk_tree_store_insert_after(GTK_TREE_STORE(keyword_tree), &add, NULL, &kw_iter);
Expand Down
60 changes: 60 additions & 0 deletions src/metadata.c
Original file line number Diff line number Diff line change
Expand Up @@ -765,6 +765,66 @@ gboolean keyword_compare(GtkTreeModel *keyword_tree, GtkTreeIter *a, GtkTreeIter
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 */
}
}

gboolean keyword_exists(GtkTreeModel *keyword_tree, GtkTreeIter *parent_ptr, GtkTreeIter *sibling, const gchar *name, gboolean exclude_sibling)
{
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))
{
gchar *iter_casefold = keyword_get_casefold(keyword_tree, &iter);
ret = strcmp(casefold, iter_casefold) == 0;
g_free(iter_casefold);
}
if (ret) break;
if (!gtk_tree_model_iter_next(keyword_tree, &iter)) break;
}
g_free(casefold);
return ret;
}


void keyword_copy(GtkTreeStore *keyword_tree, GtkTreeIter *to, GtkTreeIter *from)
{

Expand Down
2 changes: 2 additions & 0 deletions src/metadata.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ gchar *keyword_get_casefold(GtkTreeModel *keyword_tree, GtkTreeIter *iter);
gboolean keyword_get_is_keyword(GtkTreeModel *keyword_tree, GtkTreeIter *iter);

gboolean keyword_compare(GtkTreeModel *keyword_tree, GtkTreeIter *a, GtkTreeIter *b);
gboolean keyword_same_parent(GtkTreeModel *keyword_tree, GtkTreeIter *a, GtkTreeIter *b);
gboolean keyword_exists(GtkTreeModel *keyword_tree, GtkTreeIter *parent_ptr, GtkTreeIter *sibling, const gchar *name, gboolean exclude_sibling);

void keyword_copy(GtkTreeStore *keyword_tree, GtkTreeIter *to, GtkTreeIter *from);
void keyword_copy_recursive(GtkTreeStore *keyword_tree, GtkTreeIter *to, GtkTreeIter *from);
Expand Down

0 comments on commit 83a3127

Please sign in to comment.