在GList中交换两个项目(GLib)

时间:2014-08-01 10:00:20

标签: c glib

我很难弄清楚如何在一个怪物中交换两个项目。我需要交换列表中的两个项目,以便在渲染时更改其顺序。我怎么能这样做?

我该怎么做才能向上移动并向下移动列表中的项目。

例如,我想在gtktreeview中使用向上或向下移动项目的功能。我试着向上移动:

    typedef struct Settings settings;
    struct Settings
    {
        GList *l;
    };

    typedef struct Preset preset;
    struct Preset
    {
        char* title;
        float freq;
    };

    settings sts;

    void move_up_button(GtkWidget *widget, gpointer(data))
    {
        preset *ps;
        int *row, pos;
        .....................................

        row = gtk_tree_path_get_indices(path);

        ps = g_list_nth_data(sts.l, *row);
        g_assert(ps);

        pos = g_list_index(sts.l, (gpointer)ps);
        pos--;

        sts.l = g_list_remove(sts.l, (gpointer)ps);
        sts.l = g_list_insert(sts.l, (gpointer)ps, pos);

        .......................................
    }

如何在不使用删除和插入Glist函数的情况下简化此操作?

由于

1 个答案:

答案 0 :(得分:1)

我假设你在谈论列表中的连续元素。

在这种情况下,让A和B代表您希望交换的两个元素(按此顺序)。然后你需要确保

  • 指向A的元素(即它之前的元素)指向B代替;
  • 指向元素B当前指向的点;和
  • B指向A.

试试这个:

GList *element_a, *element_b;

...

/* Swap elements A and B */
element_a->prev->next = element_b;
element_b->prev = element_a->prev;

element_a->next = element_b->next;
element_b->next->prev = element_a;

element_b->next = element_a;
element_a->prev = element_b;

修改:鉴于您已添加到问题中的代码,请尝试使用此代码来操作列表元素'指针而非使用g_list_removeg_list_insert

GList *button_element, *preceding_element;

....

row = gtk_tree_path_get_indices(path);

button_element = g_list_nth(sts.l, *row);
g_assert(button_element->data);

/* Swap the button with its preceding element, if there is one */
preceding_element = button_element->prev;
if(preceding_element) {
  if(preceding_element->prev) {
    preceding_element->prev->next = button_element;
    button_element->prev = preceding_element->prev;
  }
  else {
    /* The preceding element is the head of the list, which we must update */
    sts.l = button_element;
    button_element->prev = NULL;
  }

  preceding_element->next = button_element->next;
  if(button_element->next) {
    button_element->next->prev = preceding_element;
  }

  button_element->next = preceding_element;
  preceding_element->prev = button_element;
}