/* ====================================================================
 * FTD4Linux Software License, Version 1.0
 *
 * Copyright (c) 2000-2004 The FTD4Linux Development Team.  All rights
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. The end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:
 *       "This product includes software developed by the
 *        FTD4Linux Development Team (http://www.ftd4linux.2y.net/)."
 *    Alternately, this acknowledgment may appear in the software itself,
 *    if and wherever such third-party acknowledgments normally appear.
 *
 * 4. The names "FTD" and "FTD4Linux" must
 *    not be used to endorse or promote products derived from this
 *    software without prior written permission. For written
 *    permission, please contact alguno@ftd4linux.2y.net.
 *
 * 5. Products derived from this software may not be called "FTD4Linux",
 *    nor may "FTD4Linux" appear in their name, without prior written
 *    permission of the FTD4Linux Development Team.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE FTD4LINUX DEVELOPMENT TEAM OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

#include "ftd4linux.h"
#include "ftd_gui_config.h"

#define _(x) x

FtdGuiConfigCatFilters *catfilters = NULL;

static void
add_filter_func(gpointer data, gpointer user_data)
{
    FtdFilter *filter = (FtdFilter *) data;
    int cat = GPOINTER_TO_INT(user_data);
    GtkListStore *store = NULL;
    GtkTreeIter iter;

    switch(cat) {
        case 0:
            store = catfilters->lststoreCat0Filters;
            break;
        case 1:
            store = catfilters->lststoreCat1Filters;
            break;
        case 2:
            store = catfilters->lststoreCat2Filters;
            break;
        case 3:
            store = catfilters->lststoreCat3Filters;
            break;
    }

    if (filter->cat == cat) {
        gtk_list_store_append(store, &iter);
        gtk_list_store_set(store, &iter, 0, ftd_string_value( filter->filterNaam ), -1);
    }
}

void
duplicate_func(gpointer data, gpointer user_data)
{
    FtdFilter *filter = (FtdFilter *) data;

    // Maak een volledige in-depth werk-copy van de filterlijst in het geheugen
    // Alle attributen worden gekopieerd, hoewel sommige momenteel niet in de
    // statische lijst gebruikt worden. Dit met het oog op eventuele toekomstige
    // implementaties hiervan.
    catfilters->filters = ftd_list_append(catfilters->filters, ftd_filter_duplicate(filter));
}

void
ftd_gui_config_catfilters_new(FtdGuiConfig *config)
{
    GtkWidget *tmp;
    GtkWidget *hbox1;
    GtkWidget *hbox2;
    GtkWidget *vbox1;
    GtkWidget *vbox2;
    GtkWidget *tabs;
    GtkWidget *tabs2;
    GtkWidget *label;
    GtkWidget *window;
    GtkCellRenderer *renderer;
    GtkTreeViewColumn *column;
    FtdList *list;
    GtkTreeSelection *select;
    FTDFilterlist *filterlist;

    filterlist = ftd_filterlist_get();

    g_assert( config );

    // Create widgets
    catfilters = g_malloc0(sizeof(FtdGuiConfigCatFilters ));
    config->catfilters = catfilters;
    catfilters->changed_anything = FALSE;

    tabs = gtk_notebook_new( );

    //catfilters->widget = gtk_vbox_new( FALSE, 10 );
    //gtk_widget_show( catfilters->widget );
    catfilters->widget = tabs;
    gtk_container_set_border_width (GTK_CONTAINER (catfilters->widget), 5);

    // *** Beeld-tab
    hbox1 = gtk_hbox_new( FALSE, 10 );

    catfilters->lststoreCat0Filters = gtk_list_store_new( 1, G_TYPE_STRING );
    catfilters->lstCat0Filters = gtk_tree_view_new_with_model( GTK_TREE_MODEL(catfilters->lststoreCat0Filters) );
    renderer = gtk_cell_renderer_text_new();
    column = gtk_tree_view_column_new_with_attributes( "Filter", renderer, "text", 0, NULL );
    gtk_tree_view_append_column( GTK_TREE_VIEW( catfilters->lstCat0Filters ), column );
    // Lijst vullen met filters

    ftd_filterlist_foreach(filterlist, TRUE, add_filter_func, GINT_TO_POINTER(0));

    gtk_widget_show( catfilters->lstCat0Filters );
    gtk_box_pack_start( GTK_BOX( hbox1 ), catfilters->lstCat0Filters, FALSE, FALSE, 0 );

    vbox1 = gtk_vbox_new( TRUE, 10 );

    catfilters->btnCat0FilterUp = gtk_button_new( );
    tmp = gtk_arrow_new( GTK_ARROW_UP, GTK_SHADOW_OUT );
    gtk_container_add( GTK_CONTAINER( catfilters->btnCat0FilterUp ), tmp );
    gtk_widget_show( tmp );
    gtk_widget_show( catfilters->btnCat0FilterUp );
    gtk_box_pack_start( GTK_BOX( vbox1 ), catfilters->btnCat0FilterUp, FALSE, FALSE, 0 );

    catfilters->btnCat0FilterDown = gtk_button_new( );
    tmp = gtk_arrow_new( GTK_ARROW_DOWN, GTK_SHADOW_OUT );
    gtk_container_add( GTK_CONTAINER( catfilters->btnCat0FilterDown ), tmp );
    gtk_widget_show( tmp );
    gtk_widget_show( catfilters->btnCat0FilterDown );
    gtk_box_pack_start( GTK_BOX( vbox1 ), catfilters->btnCat0FilterDown, FALSE, FALSE, 0 );

    gtk_widget_show( vbox1 );
    gtk_box_pack_start( GTK_BOX( hbox1 ), vbox1, FALSE, FALSE, 0 );

    vbox1 = gtk_vbox_new( FALSE, 10 );

    hbox2 = gtk_hbox_new( FALSE, 10 );

    label = gtk_label_new( "Naam:" );
    gtk_widget_show( label );
    gtk_box_pack_start( GTK_BOX( hbox2 ), label, FALSE, FALSE, 0 );

    catfilters->txtCat0Name = gtk_entry_new( );
    gtk_widget_show( catfilters->txtCat0Name );
    gtk_box_pack_start( GTK_BOX( hbox2 ), catfilters->txtCat0Name, TRUE, TRUE, 0 );

    gtk_widget_show( hbox2 );
    gtk_box_pack_start( GTK_BOX( vbox1 ), hbox2, FALSE, FALSE, 0 );

    hbox2 = gtk_hbox_new( TRUE, 10 );

    catfilters->btnCat0Save = gtk_button_new_with_label( "Toevoegen" );
    gtk_widget_show( catfilters->btnCat0Save );
    gtk_box_pack_start( GTK_BOX( hbox2 ), catfilters->btnCat0Save, TRUE, TRUE, 0 );

    catfilters->btnCat0Delete = gtk_button_new_with_label( "Verwijderen" );
    gtk_widget_show( catfilters->btnCat0Delete );
    gtk_box_pack_start( GTK_BOX( hbox2 ), catfilters->btnCat0Delete, TRUE, TRUE, 0 );

    gtk_widget_show( hbox2 );
    gtk_box_pack_start( GTK_BOX( vbox1 ), hbox2, FALSE, FALSE, 0 );

    tabs2 = gtk_notebook_new( );

    // Tags A
    vbox2 = gtk_vbox_new( FALSE, 0 );

    list = ftd_get_tags( );
    catfilters->cat0TagsA = NULL;
    while( list ) {
        FtdTag *tag = ftd_list_value( list );
        if( tag->parent != NULL && tag->parent->cat == 0 && ftd_string_value( tag->code )[0] == 'a' ) {
            tmp = gtk_check_button_new_with_label( ftd_string_value( tag->name ) );
            g_object_set_data( G_OBJECT( tmp ), "ftd_tag_code", tag->code );
            gtk_widget_show( tmp );
            gtk_box_pack_start( GTK_BOX( vbox2 ), tmp, FALSE, FALSE, 0 );
            catfilters->cat0TagsA = ftd_list_append( catfilters->cat0TagsA, tmp );
        }
        list = ftd_list_next( list );
    }

    gtk_widget_show( vbox2 );
    gtk_notebook_append_page( GTK_NOTEBOOK(tabs2), vbox2, gtk_label_new( "Formaat" ) );

    // Tags B
    vbox2 = gtk_vbox_new( FALSE, 0 );

    list = ftd_get_tags( );
    catfilters->cat0TagsB = NULL;
    while( list ) {
        FtdTag *tag = ftd_list_value( list );
        if( tag->parent != NULL && tag->parent->cat == 0 && ftd_string_value( tag->code )[0] == 'b' ) {
            tmp = gtk_check_button_new_with_label( ftd_string_value( tag->name ) );
            g_object_set_data( G_OBJECT( tmp ), "ftd_tag_code", tag->code );
            gtk_widget_show( tmp );
            gtk_box_pack_start( GTK_BOX( vbox2 ), tmp, FALSE, FALSE, 0 );
            catfilters->cat0TagsB = ftd_list_append( catfilters->cat0TagsB, tmp );
        }
        list = ftd_list_next( list );
    }

    gtk_widget_show( vbox2 );
    gtk_notebook_append_page( GTK_NOTEBOOK(tabs2), vbox2, gtk_label_new( "Bron" ) );

    // Tags C
    vbox2 = gtk_vbox_new( FALSE, 0 );

    list = ftd_get_tags( );
    catfilters->cat0TagsC = NULL;
    while( list ) {
        FtdTag *tag = ftd_list_value( list );
        if( tag->parent != NULL && tag->parent->cat == 0 && ftd_string_value( tag->code )[0] == 'c' ) {
            tmp = gtk_check_button_new_with_label( ftd_string_value( tag->name ) );
            g_object_set_data( G_OBJECT( tmp ), "ftd_tag_code", tag->code );
            gtk_widget_show( tmp );
            gtk_box_pack_start( GTK_BOX( vbox2 ), tmp, FALSE, FALSE, 0 );
            catfilters->cat0TagsC = ftd_list_append( catfilters->cat0TagsC, tmp );
        }
        list = ftd_list_next( list );
    }

    gtk_widget_show( vbox2 );
    gtk_notebook_append_page( GTK_NOTEBOOK(tabs2), vbox2, gtk_label_new( "Ondertitels" ) );

    // Tags D
    window = gtk_scrolled_window_new( NULL, NULL );
    gtk_scrolled_window_set_policy( GTK_SCROLLED_WINDOW( window ), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC );

    vbox2 = gtk_vbox_new( FALSE, 0 );

    list = ftd_get_tags( );
    catfilters->cat0TagsD = NULL;
    while( list ) {
        FtdTag *tag = ftd_list_value( list );
        if( tag->parent != NULL && tag->parent->cat == 0 && ftd_string_value( tag->code )[0] == 'd' ) {
            tmp = gtk_check_button_new_with_label( ftd_string_value( tag->name ) );
            g_object_set_data( G_OBJECT( tmp ), "ftd_tag_code", tag->code );
            gtk_widget_show( tmp );
            gtk_box_pack_start( GTK_BOX( vbox2 ), tmp, FALSE, FALSE, 0 );
            catfilters->cat0TagsD = ftd_list_append( catfilters->cat0TagsD, tmp );
        }
        list = ftd_list_next( list );
    }

    gtk_widget_show( vbox2 );
    gtk_scrolled_window_add_with_viewport( GTK_SCROLLED_WINDOW( window ), vbox2 );

    gtk_widget_show( window );
    gtk_notebook_append_page( GTK_NOTEBOOK(tabs2), window, gtk_label_new( "Genre" ) );

    gtk_widget_show( tabs2 );
    gtk_box_pack_start( GTK_BOX( vbox1 ), tabs2, TRUE, TRUE, 0 );

    hbox2 = gtk_hbox_new( FALSE, 10 );

    label = gtk_label_new( "Tag:" );
    gtk_widget_show( label );
    gtk_box_pack_start( GTK_BOX( hbox2 ), label, FALSE, FALSE, 0 );

    catfilters->txtCat0ExtraTag = gtk_entry_new( );
    gtk_widget_show( catfilters->txtCat0ExtraTag );
    gtk_box_pack_start( GTK_BOX( hbox2 ), catfilters->txtCat0ExtraTag, TRUE, TRUE, 0 );

    gtk_widget_show( hbox2 );
    gtk_box_pack_start( GTK_BOX( vbox1 ), hbox2, FALSE, FALSE, 0 );

    gtk_widget_show( vbox1 );
    gtk_box_pack_start( GTK_BOX( hbox1 ), vbox1, TRUE, TRUE,  0 );

    gtk_widget_show( hbox1 );
    gtk_notebook_append_page( GTK_NOTEBOOK(tabs), hbox1, gtk_label_new( "Beeld" ) );

    g_signal_connect( G_OBJECT( catfilters->btnCat0FilterUp ), "clicked", G_CALLBACK( ftd_gui_config_catfilters_callback_filter_up ), GINT_TO_POINTER(0) );
    g_signal_connect( G_OBJECT( catfilters->btnCat0FilterDown ), "clicked", G_CALLBACK( ftd_gui_config_catfilters_callback_filter_down ), GINT_TO_POINTER(0) );
    select = gtk_tree_view_get_selection( GTK_TREE_VIEW( catfilters->lstCat0Filters ) );
    g_signal_connect( G_OBJECT( select ), "changed", G_CALLBACK( ftd_gui_config_catfilters_callback_selection_changed ), GINT_TO_POINTER(0) );
    g_signal_connect( G_OBJECT( catfilters->txtCat0Name ), "key-release-event", G_CALLBACK( ftd_gui_config_catfilters_callback_name_changed ),  GINT_TO_POINTER(0) );
    g_signal_connect( G_OBJECT( catfilters->btnCat0Save ), "clicked", G_CALLBACK( ftd_gui_config_catfilters_callback_save ), GINT_TO_POINTER(0) );
    g_signal_connect( G_OBJECT( catfilters->btnCat0Delete ), "clicked", G_CALLBACK( ftd_gui_config_catfilters_callback_delete), GINT_TO_POINTER(0) );

    // *** Geluid-tab
    hbox1 = gtk_hbox_new( FALSE, 10 );

    catfilters->lststoreCat1Filters = gtk_list_store_new( 1, G_TYPE_STRING );
    catfilters->lstCat1Filters = gtk_tree_view_new_with_model( GTK_TREE_MODEL(catfilters->lststoreCat1Filters) );
    renderer = gtk_cell_renderer_text_new();
    column = gtk_tree_view_column_new_with_attributes( "Filter", renderer, "text", 0, NULL );
    gtk_tree_view_append_column( GTK_TREE_VIEW( catfilters->lstCat1Filters ), column );
    // Lijst vullen met filters

    ftd_filterlist_foreach(filterlist, TRUE, add_filter_func, GINT_TO_POINTER(1));

    gtk_widget_show( catfilters->lstCat1Filters );
    gtk_box_pack_start( GTK_BOX( hbox1 ), catfilters->lstCat1Filters, FALSE, FALSE, 0 );

    vbox1 = gtk_vbox_new( TRUE, 10 );

    catfilters->btnCat1FilterUp = gtk_button_new( );
    tmp = gtk_arrow_new( GTK_ARROW_UP, GTK_SHADOW_OUT );
    gtk_container_add( GTK_CONTAINER( catfilters->btnCat1FilterUp ), tmp );
    gtk_widget_show( tmp );
    gtk_widget_show( catfilters->btnCat1FilterUp );
    gtk_box_pack_start( GTK_BOX( vbox1 ), catfilters->btnCat1FilterUp, FALSE, FALSE, 0 );

    catfilters->btnCat1FilterDown = gtk_button_new( );
    tmp = gtk_arrow_new( GTK_ARROW_DOWN, GTK_SHADOW_OUT );
    gtk_container_add( GTK_CONTAINER( catfilters->btnCat1FilterDown ), tmp );
    gtk_widget_show( tmp );
    gtk_widget_show( catfilters->btnCat1FilterDown );
    gtk_box_pack_start( GTK_BOX( vbox1 ), catfilters->btnCat1FilterDown, FALSE, FALSE, 0 );

    gtk_widget_show( vbox1 );
    gtk_box_pack_start( GTK_BOX( hbox1 ), vbox1, FALSE, FALSE, 0 );

    vbox1 = gtk_vbox_new( FALSE, 10 );

    hbox2 = gtk_hbox_new( FALSE, 10 );

    label = gtk_label_new( "Naam:" );
    gtk_widget_show( label );
    gtk_box_pack_start( GTK_BOX( hbox2 ), label, FALSE, FALSE, 0 );

    catfilters->txtCat1Name = gtk_entry_new( );
    gtk_widget_show( catfilters->txtCat1Name );
    gtk_box_pack_start( GTK_BOX( hbox2 ), catfilters->txtCat1Name, TRUE, TRUE, 0 );

    gtk_widget_show( hbox2 );
    gtk_box_pack_start( GTK_BOX( vbox1 ), hbox2, FALSE, FALSE, 0 );

    hbox2 = gtk_hbox_new( TRUE, 10 );

    catfilters->btnCat1Save = gtk_button_new_with_label( "Toevoegen" );
    gtk_widget_show( catfilters->btnCat1Save );
    gtk_box_pack_start( GTK_BOX( hbox2 ), catfilters->btnCat1Save, TRUE, TRUE, 0 );

    catfilters->btnCat1Delete = gtk_button_new_with_label( "Verwijderen" );
    gtk_widget_show( catfilters->btnCat1Delete );
    gtk_box_pack_start( GTK_BOX( hbox2 ), catfilters->btnCat1Delete, TRUE, TRUE, 0 );

    gtk_widget_show( hbox2 );
    gtk_box_pack_start( GTK_BOX( vbox1 ), hbox2, FALSE, FALSE, 0 );

    tabs2 = gtk_notebook_new( );

    // Tags A
    vbox2 = gtk_vbox_new( FALSE, 0 );

    list = ftd_get_tags( );
    catfilters->cat1TagsA = NULL;
    while( list ) {
        FtdTag *tag = ftd_list_value( list );
        if( tag->parent != NULL && tag->parent->cat == 1 && ftd_string_value( tag->code )[0] == 'a' ) {
            tmp = gtk_check_button_new_with_label( ftd_string_value( tag->name ) );
            g_object_set_data( G_OBJECT( tmp ), "ftd_tag_code", tag->code );
            gtk_widget_show( tmp );
            gtk_box_pack_start( GTK_BOX( vbox2 ), tmp, FALSE, FALSE, 0 );
            catfilters->cat1TagsA = ftd_list_append( catfilters->cat1TagsA, tmp );
        }
        list = ftd_list_next( list );
    }

    gtk_widget_show( vbox2 );
    gtk_notebook_append_page( GTK_NOTEBOOK(tabs2), vbox2, gtk_label_new( "Formaat" ) );

    // Tags B
    vbox2 = gtk_vbox_new( FALSE, 0 );

    list = ftd_get_tags( );
    catfilters->cat1TagsB = NULL;
    while( list ) {
        FtdTag *tag = ftd_list_value( list );
        if( tag->parent != NULL && tag->parent->cat == 1 && ftd_string_value( tag->code )[0] == 'b' ) {
            tmp = gtk_check_button_new_with_label( ftd_string_value( tag->name ) );
            g_object_set_data( G_OBJECT( tmp ), "ftd_tag_code", tag->code );
            gtk_widget_show( tmp );
            gtk_box_pack_start( GTK_BOX( vbox2 ), tmp, FALSE, FALSE, 0 );
            catfilters->cat1TagsB = ftd_list_append( catfilters->cat1TagsB, tmp );
        }
        list = ftd_list_next( list );
    }

    gtk_widget_show( vbox2 );
    gtk_notebook_append_page( GTK_NOTEBOOK(tabs2), vbox2, gtk_label_new( "Bron" ) );

    // Tags C
    vbox2 = gtk_vbox_new( FALSE, 0 );

    list = ftd_get_tags( );
    catfilters->cat1TagsC = NULL;
    while( list ) {
        FtdTag *tag = ftd_list_value( list );
        if( tag->parent != NULL && tag->parent->cat == 1 && ftd_string_value( tag->code )[0] == 'c' ) {
            tmp = gtk_check_button_new_with_label( ftd_string_value( tag->name ) );
            g_object_set_data( G_OBJECT( tmp ), "ftd_tag_code", tag->code );
            gtk_widget_show( tmp );
            gtk_box_pack_start( GTK_BOX( vbox2 ), tmp, FALSE, FALSE, 0 );
            catfilters->cat1TagsC = ftd_list_append( catfilters->cat1TagsC, tmp );
        }
        list = ftd_list_next( list );
    }

    gtk_widget_show( vbox2 );
    gtk_notebook_append_page( GTK_NOTEBOOK(tabs2), vbox2, gtk_label_new( "Bitrate" ) );

    // Tags D
    window = gtk_scrolled_window_new( NULL, NULL );
    gtk_scrolled_window_set_policy( GTK_SCROLLED_WINDOW( window ), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC );

    vbox2 = gtk_vbox_new( FALSE, 0 );

    list = ftd_get_tags( );
    catfilters->cat1TagsD = NULL;
    while( list ) {
        FtdTag *tag = ftd_list_value( list );
        if( tag->parent != NULL && tag->parent->cat == 1 && ftd_string_value( tag->code )[0] == 'd' ) {
            tmp = gtk_check_button_new_with_label( ftd_string_value( tag->name ) );
            g_object_set_data( G_OBJECT( tmp ), "ftd_tag_code", tag->code );
            gtk_widget_show( tmp );
            gtk_box_pack_start( GTK_BOX( vbox2 ), tmp, FALSE, FALSE, 0 );
            catfilters->cat1TagsD = ftd_list_append( catfilters->cat1TagsD, tmp );
        }
        list = ftd_list_next( list );
    }

    gtk_widget_show( vbox2 );
    gtk_scrolled_window_add_with_viewport( GTK_SCROLLED_WINDOW( window ), vbox2 );

    gtk_widget_show( window );
    gtk_notebook_append_page( GTK_NOTEBOOK(tabs2), window, gtk_label_new( "Genre" ) );

    gtk_widget_show( tabs2 );
    gtk_box_pack_start( GTK_BOX( vbox1 ), tabs2, TRUE, TRUE, 0 );

    hbox2 = gtk_hbox_new( FALSE, 10 );

    label = gtk_label_new( "Tag:" );
    gtk_widget_show( label );
    gtk_box_pack_start( GTK_BOX( hbox2 ), label, FALSE, FALSE, 0 );

    catfilters->txtCat1ExtraTag = gtk_entry_new( );
    gtk_widget_show( catfilters->txtCat1ExtraTag );
    gtk_box_pack_start( GTK_BOX( hbox2 ), catfilters->txtCat1ExtraTag, TRUE, TRUE, 0 );

    gtk_widget_show( hbox2 );
    gtk_box_pack_start( GTK_BOX( vbox1 ), hbox2, FALSE, FALSE, 0 );

    gtk_widget_show( vbox1 );
    gtk_box_pack_start( GTK_BOX( hbox1 ), vbox1, TRUE, TRUE,  0 );

    gtk_widget_show( hbox1 );
    gtk_notebook_append_page( GTK_NOTEBOOK(tabs), hbox1, gtk_label_new( "Geluid" ) );

    g_signal_connect( G_OBJECT( catfilters->btnCat1FilterUp ), "clicked", G_CALLBACK( ftd_gui_config_catfilters_callback_filter_up ), GINT_TO_POINTER(1) );
    g_signal_connect( G_OBJECT( catfilters->btnCat1FilterDown ), "clicked", G_CALLBACK( ftd_gui_config_catfilters_callback_filter_down ), GINT_TO_POINTER(1) );
    select = gtk_tree_view_get_selection( GTK_TREE_VIEW( catfilters->lstCat1Filters ) );
    g_signal_connect( G_OBJECT( select ), "changed", G_CALLBACK( ftd_gui_config_catfilters_callback_selection_changed ), GINT_TO_POINTER(1) );
    g_signal_connect( G_OBJECT( catfilters->txtCat1Name ), "key-release-event", G_CALLBACK( ftd_gui_config_catfilters_callback_name_changed ),  GINT_TO_POINTER(1) );
    g_signal_connect( G_OBJECT( catfilters->btnCat1Save ), "clicked", G_CALLBACK( ftd_gui_config_catfilters_callback_save ), GINT_TO_POINTER(1) );
    g_signal_connect( G_OBJECT( catfilters->btnCat1Delete ), "clicked", G_CALLBACK( ftd_gui_config_catfilters_callback_delete), GINT_TO_POINTER(1) );

    gtk_widget_show( tabs );

    // *** Spelletjes-tab
    hbox1 = gtk_hbox_new( FALSE, 10 );

    catfilters->lststoreCat2Filters = gtk_list_store_new( 1, G_TYPE_STRING );
    catfilters->lstCat2Filters = gtk_tree_view_new_with_model( GTK_TREE_MODEL(catfilters->lststoreCat2Filters) );
    renderer = gtk_cell_renderer_text_new();
    column = gtk_tree_view_column_new_with_attributes( "Filter", renderer, "text", 0, NULL );
    gtk_tree_view_append_column( GTK_TREE_VIEW( catfilters->lstCat2Filters ), column );
    // Lijst vullen met filters

    ftd_filterlist_foreach(filterlist, TRUE, add_filter_func, GINT_TO_POINTER(2));

    gtk_widget_show( catfilters->lstCat2Filters );
    gtk_box_pack_start( GTK_BOX( hbox1 ), catfilters->lstCat2Filters, FALSE, FALSE, 0 );

    vbox1 = gtk_vbox_new( TRUE, 10 );

    catfilters->btnCat2FilterUp = gtk_button_new( );
    tmp = gtk_arrow_new( GTK_ARROW_UP, GTK_SHADOW_OUT );
    gtk_container_add( GTK_CONTAINER( catfilters->btnCat2FilterUp ), tmp );
    gtk_widget_show( tmp );
    gtk_widget_show( catfilters->btnCat2FilterUp );
    gtk_box_pack_start( GTK_BOX( vbox1 ), catfilters->btnCat2FilterUp, FALSE, FALSE, 0 );

    catfilters->btnCat2FilterDown = gtk_button_new( );
    tmp = gtk_arrow_new( GTK_ARROW_DOWN, GTK_SHADOW_OUT );
    gtk_container_add( GTK_CONTAINER( catfilters->btnCat2FilterDown ), tmp );
    gtk_widget_show( tmp );
    gtk_widget_show( catfilters->btnCat2FilterDown );
    gtk_box_pack_start( GTK_BOX( vbox1 ), catfilters->btnCat2FilterDown, FALSE, FALSE, 0 );

    gtk_widget_show( vbox1 );
    gtk_box_pack_start( GTK_BOX( hbox1 ), vbox1, FALSE, FALSE, 0 );

    vbox1 = gtk_vbox_new( FALSE, 10 );

    hbox2 = gtk_hbox_new( FALSE, 10 );

    label = gtk_label_new( "Naam:" );
    gtk_widget_show( label );
    gtk_box_pack_start( GTK_BOX( hbox2 ), label, FALSE, FALSE, 0 );

    catfilters->txtCat2Name = gtk_entry_new( );
    gtk_widget_show( catfilters->txtCat2Name );
    gtk_box_pack_start( GTK_BOX( hbox2 ), catfilters->txtCat2Name, TRUE, TRUE, 0 );

    gtk_widget_show( hbox2 );
    gtk_box_pack_start( GTK_BOX( vbox1 ), hbox2, FALSE, FALSE, 0 );

    hbox2 = gtk_hbox_new( TRUE, 10 );

    catfilters->btnCat2Save = gtk_button_new_with_label( "Toevoegen" );
    gtk_widget_show( catfilters->btnCat2Save );
    gtk_box_pack_start( GTK_BOX( hbox2 ), catfilters->btnCat2Save, TRUE, TRUE, 0 );

    catfilters->btnCat2Delete = gtk_button_new_with_label( "Verwijderen" );
    gtk_widget_show( catfilters->btnCat2Delete );
    gtk_box_pack_start( GTK_BOX( hbox2 ), catfilters->btnCat2Delete, TRUE, TRUE, 0 );

    gtk_widget_show( hbox2 );
    gtk_box_pack_start( GTK_BOX( vbox1 ), hbox2, FALSE, FALSE, 0 );

    tabs2 = gtk_notebook_new( );

    // Tags A
    vbox2 = gtk_vbox_new( FALSE, 0 );

    list = ftd_get_tags( );
    catfilters->cat2TagsA = NULL;
    while( list ) {
        FtdTag *tag = ftd_list_value( list );
        if( tag->parent != NULL && tag->parent->cat == 2 && ftd_string_value( tag->code )[0] == 'a' ) {
            tmp = gtk_check_button_new_with_label( ftd_string_value( tag->name ) );
            g_object_set_data( G_OBJECT( tmp ), "ftd_tag_code", tag->code );
            gtk_widget_show( tmp );
            gtk_box_pack_start( GTK_BOX( vbox2 ), tmp, FALSE, FALSE, 0 );
            catfilters->cat2TagsA = ftd_list_append( catfilters->cat2TagsA, tmp );
        }
        list = ftd_list_next( list );
    }

    gtk_widget_show( vbox2 );
    gtk_notebook_append_page( GTK_NOTEBOOK(tabs2), vbox2, gtk_label_new( "Platform" ) );

    // Tags B
    vbox2 = gtk_vbox_new( FALSE, 0 );

    list = ftd_get_tags( );
    catfilters->cat2TagsB = NULL;
    while( list ) {
        FtdTag *tag = ftd_list_value( list );
        if( tag->parent != NULL && tag->parent->cat == 2 && ftd_string_value( tag->code )[0] == 'b' ) {
            tmp = gtk_check_button_new_with_label( ftd_string_value( tag->name ) );
            g_object_set_data( G_OBJECT( tmp ), "ftd_tag_code", tag->code );
            gtk_widget_show( tmp );
            gtk_box_pack_start( GTK_BOX( vbox2 ), tmp, FALSE, FALSE, 0 );
            catfilters->cat2TagsB = ftd_list_append( catfilters->cat2TagsB, tmp );
        }
        list = ftd_list_next( list );
    }

    gtk_widget_show( vbox2 );
    gtk_notebook_append_page( GTK_NOTEBOOK(tabs2), vbox2, gtk_label_new( "Formaat" ) );

    // Tags C
    window = gtk_scrolled_window_new( NULL, NULL );
    gtk_scrolled_window_set_policy( GTK_SCROLLED_WINDOW( window ), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC );

    vbox2 = gtk_vbox_new( FALSE, 0 );

    list = ftd_get_tags( );
    catfilters->cat2TagsC = NULL;
    while( list ) {
        FtdTag *tag = ftd_list_value( list );
        if( tag->parent != NULL && tag->parent->cat == 2 && ftd_string_value( tag->code )[0] == 'c' ) {
            tmp = gtk_check_button_new_with_label( ftd_string_value( tag->name ) );
            g_object_set_data( G_OBJECT( tmp ), "ftd_tag_code", tag->code );
            gtk_widget_show( tmp );
            gtk_box_pack_start( GTK_BOX( vbox2 ), tmp, FALSE, FALSE, 0 );
            catfilters->cat2TagsC = ftd_list_append( catfilters->cat2TagsC, tmp );
        }
        list = ftd_list_next( list );
    }

    gtk_widget_show( vbox2 );
    gtk_scrolled_window_add_with_viewport( GTK_SCROLLED_WINDOW( window ), vbox2 );

    gtk_widget_show( window );
    gtk_notebook_append_page( GTK_NOTEBOOK(tabs2), window, gtk_label_new( "Genre" ) );

    gtk_widget_show( tabs2 );
    gtk_box_pack_start( GTK_BOX( vbox1 ), tabs2, TRUE, TRUE, 0 );

    hbox2 = gtk_hbox_new( FALSE, 10 );

    label = gtk_label_new( "Tag:" );
    gtk_widget_show( label );
    gtk_box_pack_start( GTK_BOX( hbox2 ), label, FALSE, FALSE, 0 );

    catfilters->txtCat2ExtraTag = gtk_entry_new( );
    gtk_widget_show( catfilters->txtCat2ExtraTag );
    gtk_box_pack_start( GTK_BOX( hbox2 ), catfilters->txtCat2ExtraTag, TRUE, TRUE, 0 );

    gtk_widget_show( hbox2 );
    gtk_box_pack_start( GTK_BOX( vbox1 ), hbox2, FALSE, FALSE, 0 );

    gtk_widget_show( vbox1 );
    gtk_box_pack_start( GTK_BOX( hbox1 ), vbox1, TRUE, TRUE,  0 );

    gtk_widget_show( hbox1 );
    gtk_notebook_append_page( GTK_NOTEBOOK(tabs), hbox1, gtk_label_new( "Spelletjes" ) );

    g_signal_connect( G_OBJECT( catfilters->btnCat2FilterUp ), "clicked", G_CALLBACK( ftd_gui_config_catfilters_callback_filter_up ), GINT_TO_POINTER(2) );
    g_signal_connect( G_OBJECT( catfilters->btnCat2FilterDown ), "clicked", G_CALLBACK( ftd_gui_config_catfilters_callback_filter_down ), GINT_TO_POINTER(2) );
    select = gtk_tree_view_get_selection( GTK_TREE_VIEW( catfilters->lstCat2Filters ) );
    g_signal_connect( G_OBJECT( select ), "changed", G_CALLBACK( ftd_gui_config_catfilters_callback_selection_changed ), GINT_TO_POINTER(2) );
    g_signal_connect( G_OBJECT( catfilters->txtCat2Name ), "key-release-event", G_CALLBACK( ftd_gui_config_catfilters_callback_name_changed ),  GINT_TO_POINTER(2) );
    g_signal_connect( G_OBJECT( catfilters->btnCat2Save ), "clicked", G_CALLBACK( ftd_gui_config_catfilters_callback_save ), GINT_TO_POINTER(2) );
    g_signal_connect( G_OBJECT( catfilters->btnCat2Delete ), "clicked", G_CALLBACK( ftd_gui_config_catfilters_callback_delete), GINT_TO_POINTER(2) );

    // *** Applicaties-tab
    hbox1 = gtk_hbox_new( FALSE, 10 );

    catfilters->lststoreCat3Filters = gtk_list_store_new( 1, G_TYPE_STRING );
    catfilters->lstCat3Filters = gtk_tree_view_new_with_model( GTK_TREE_MODEL(catfilters->lststoreCat3Filters) );
    renderer = gtk_cell_renderer_text_new();
    column = gtk_tree_view_column_new_with_attributes( "Filter", renderer, "text", 0, NULL );
    gtk_tree_view_append_column( GTK_TREE_VIEW( catfilters->lstCat3Filters ), column );
    // Lijst vullen met filters

    ftd_filterlist_foreach(filterlist, TRUE, add_filter_func, GINT_TO_POINTER(3));

    gtk_widget_show( catfilters->lstCat3Filters );
    gtk_box_pack_start( GTK_BOX( hbox1 ), catfilters->lstCat3Filters, FALSE, FALSE, 0 );

    vbox1 = gtk_vbox_new( TRUE, 10 );

    catfilters->btnCat3FilterUp = gtk_button_new( );
    tmp = gtk_arrow_new( GTK_ARROW_UP, GTK_SHADOW_OUT );
    gtk_container_add( GTK_CONTAINER( catfilters->btnCat3FilterUp ), tmp );
    gtk_widget_show( tmp );
    gtk_widget_show( catfilters->btnCat3FilterUp );
    gtk_box_pack_start( GTK_BOX( vbox1 ), catfilters->btnCat3FilterUp, FALSE, FALSE, 0 );

    catfilters->btnCat3FilterDown = gtk_button_new( );
    tmp = gtk_arrow_new( GTK_ARROW_DOWN, GTK_SHADOW_OUT );
    gtk_container_add( GTK_CONTAINER( catfilters->btnCat3FilterDown ), tmp );
    gtk_widget_show( tmp );
    gtk_widget_show( catfilters->btnCat3FilterDown );
    gtk_box_pack_start( GTK_BOX( vbox1 ), catfilters->btnCat3FilterDown, FALSE, FALSE, 0 );

    gtk_widget_show( vbox1 );
    gtk_box_pack_start( GTK_BOX( hbox1 ), vbox1, FALSE, FALSE, 0 );

    vbox1 = gtk_vbox_new( FALSE, 10 );

    hbox2 = gtk_hbox_new( FALSE, 10 );

    label = gtk_label_new( "Naam:" );
    gtk_widget_show( label );
    gtk_box_pack_start( GTK_BOX( hbox2 ), label, FALSE, FALSE, 0 );

    catfilters->txtCat3Name = gtk_entry_new( );
    gtk_widget_show( catfilters->txtCat3Name );
    gtk_box_pack_start( GTK_BOX( hbox2 ), catfilters->txtCat3Name, TRUE, TRUE, 0 );

    gtk_widget_show( hbox2 );
    gtk_box_pack_start( GTK_BOX( vbox1 ), hbox2, FALSE, FALSE, 0 );

    hbox2 = gtk_hbox_new( TRUE, 10 );

    catfilters->btnCat3Save = gtk_button_new_with_label( "Toevoegen" );
    gtk_widget_show( catfilters->btnCat3Save );
    gtk_box_pack_start( GTK_BOX( hbox2 ), catfilters->btnCat3Save, TRUE, TRUE, 0 );

    catfilters->btnCat3Delete = gtk_button_new_with_label( "Verwijderen" );
    gtk_widget_show( catfilters->btnCat3Delete );
    gtk_box_pack_start( GTK_BOX( hbox2 ), catfilters->btnCat3Delete, TRUE, TRUE, 0 );

    gtk_widget_show( hbox2 );
    gtk_box_pack_start( GTK_BOX( vbox1 ), hbox2, FALSE, FALSE, 0 );

    tabs2 = gtk_notebook_new( );

    // Tags A
    vbox2 = gtk_vbox_new( FALSE, 0 );

    list = ftd_get_tags( );
    catfilters->cat3TagsA = NULL;
    while( list ) {
        FtdTag *tag = ftd_list_value( list );
        if( tag->parent != NULL && tag->parent->cat == 3 && ftd_string_value( tag->code )[0] == 'a' ) {
            tmp = gtk_check_button_new_with_label( ftd_string_value( tag->name ) );
            g_object_set_data( G_OBJECT( tmp ), "ftd_tag_code", tag->code );
            gtk_widget_show( tmp );
            gtk_box_pack_start( GTK_BOX( vbox2 ), tmp, FALSE, FALSE, 0 );
            catfilters->cat3TagsA = ftd_list_append( catfilters->cat3TagsA, tmp );
        }
        list = ftd_list_next( list );
    }

    gtk_widget_show( vbox2 );
    gtk_notebook_append_page( GTK_NOTEBOOK(tabs2), vbox2, gtk_label_new( "Platform" ) );

    // Tags B
    window = gtk_scrolled_window_new( NULL, NULL );
    gtk_scrolled_window_set_policy( GTK_SCROLLED_WINDOW( window ), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC );

    vbox2 = gtk_vbox_new( FALSE, 0 );

    list = ftd_get_tags( );
    catfilters->cat3TagsB = NULL;
    while( list ) {
        FtdTag *tag = ftd_list_value( list );
        if( tag->parent != NULL && tag->parent->cat == 3 && ftd_string_value( tag->code )[0] == 'b' ) {
            tmp = gtk_check_button_new_with_label( ftd_string_value( tag->name ) );
            g_object_set_data( G_OBJECT( tmp ), "ftd_tag_code", tag->code );
            gtk_widget_show( tmp );
            gtk_box_pack_start( GTK_BOX( vbox2 ), tmp, FALSE, FALSE, 0 );
            catfilters->cat3TagsB = ftd_list_append( catfilters->cat3TagsB, tmp );
        }
        list = ftd_list_next( list );
    }

    gtk_widget_show( vbox2 );
    gtk_scrolled_window_add_with_viewport( GTK_SCROLLED_WINDOW( window ), vbox2 );

    gtk_widget_show( window );
    gtk_notebook_append_page( GTK_NOTEBOOK(tabs2), window, gtk_label_new( "Genre" ) );

    gtk_widget_show( tabs2 );
    gtk_box_pack_start( GTK_BOX( vbox1 ), tabs2, TRUE, TRUE, 0 );

    hbox2 = gtk_hbox_new( FALSE, 10 );

    label = gtk_label_new( "Tag:" );
    gtk_widget_show( label );
    gtk_box_pack_start( GTK_BOX( hbox2 ), label, FALSE, FALSE, 0 );

    catfilters->txtCat3ExtraTag = gtk_entry_new( );
    gtk_widget_show( catfilters->txtCat3ExtraTag );
    gtk_box_pack_start( GTK_BOX( hbox2 ), catfilters->txtCat3ExtraTag, TRUE, TRUE, 0 );

    gtk_widget_show( hbox2 );
    gtk_box_pack_start( GTK_BOX( vbox1 ), hbox2, FALSE, FALSE, 0 );

    gtk_widget_show( vbox1 );
    gtk_box_pack_start( GTK_BOX( hbox1 ), vbox1, TRUE, TRUE,  0 );

    gtk_widget_show( hbox1 );
    gtk_notebook_append_page( GTK_NOTEBOOK(tabs), hbox1, gtk_label_new( "Applicaties" ) );

    g_signal_connect( G_OBJECT( catfilters->btnCat3FilterUp ), "clicked", G_CALLBACK( ftd_gui_config_catfilters_callback_filter_up ), GINT_TO_POINTER(3) );
    g_signal_connect( G_OBJECT( catfilters->btnCat3FilterDown ), "clicked", G_CALLBACK( ftd_gui_config_catfilters_callback_filter_down ), GINT_TO_POINTER(3) );
    select = gtk_tree_view_get_selection( GTK_TREE_VIEW( catfilters->lstCat3Filters ) );
    g_signal_connect( G_OBJECT( select ), "changed", G_CALLBACK( ftd_gui_config_catfilters_callback_selection_changed ), GINT_TO_POINTER(3) );
    g_signal_connect( G_OBJECT( catfilters->txtCat3Name ), "key-release-event", G_CALLBACK( ftd_gui_config_catfilters_callback_name_changed ),  GINT_TO_POINTER(3) );
    g_signal_connect( G_OBJECT( catfilters->btnCat3Save ), "clicked", G_CALLBACK( ftd_gui_config_catfilters_callback_save ), GINT_TO_POINTER(3));
    g_signal_connect( G_OBJECT( catfilters->btnCat3Delete ), "clicked", G_CALLBACK( ftd_gui_config_catfilters_callback_delete), GINT_TO_POINTER(3) );


    ftd_filterlist_foreach(filterlist, TRUE, duplicate_func, NULL);

    g_object_unref(filterlist);
}

void
ftd_gui_config_catfilters_callback_delete( GtkButton * btn, gpointer data )
{
    int cat = GPOINTER_TO_INT(data);
    gboolean exists = FALSE;
    const gchar * name;
    FtdFilter *filter;
    FtdList *list = catfilters->filters;
    GtkWidget *tree;
    GtkTreeIter iter;
    GtkTreeModel *store;
    GtkWidget *txtName;
    gchar *value;
    gboolean found = FALSE;
    GtkWidget *btnSave;

    catfilters->changed_anything = TRUE;

    switch( cat ) {
        case 0 :
            tree = catfilters->lstCat0Filters;
            txtName = catfilters->txtCat0Name;
            btnSave = catfilters->btnCat0Save;
            break;
        case 1 :
            tree = catfilters->lstCat1Filters;
            txtName = catfilters->txtCat1Name;
            btnSave = catfilters->btnCat1Save;
            break;
        case 2 :
            tree = catfilters->lstCat2Filters;
            txtName = catfilters->txtCat2Name;
            btnSave = catfilters->btnCat2Save;
            break;
        case 3 :
            tree = catfilters->lstCat3Filters;
            txtName = catfilters->txtCat3Name;
            btnSave = catfilters->btnCat3Save;
            break;
        default :
            g_warning( "A filter was to be saved, but the data was illegal." );
            return;
    }
    name = gtk_entry_get_text( GTK_ENTRY( txtName ) );
    if( !strlen( name ) ) {
        // lege naam is ongeldig
        return;
    }
    // Eerst opzoeken
    while( list ) {
        FtdFilter *filter1 = ftd_list_value( list );
        if( filter1->cat == cat ) {
            if( !strcmp( ftd_string_value( filter1->filterNaam ), name ) ) {
                exists = TRUE;
                filter = filter1;
                break;
            }
        }
        list = ftd_list_next( list );
    }
    if( !exists ) {
        // Kan niet verwijderen als het niet is
        return;
    }
    // Uit de filter-lijst verwijderen
    catfilters->filters = ftd_list_remove( catfilters->filters, filter );
    // Uit de tree verwijderen op het scherm
    store = gtk_tree_view_get_model( GTK_TREE_VIEW(tree) );
    if( !store ) {
        g_warning( "Kon de filter niet uit de zichtbare lijst halen." );
        return;
    }
    if( gtk_tree_model_get_iter_first( store, &iter ) ) {
        gtk_tree_model_get( store, &iter, 0, &value, -1 );
        if( strcmp( value, name ) ) {
            g_free( value );
            while( gtk_tree_model_iter_next( store, &iter ) ) {
                gtk_tree_model_get( store, &iter, 0, &value, -1 );
                if( !strcmp( value, name ) ) {
                    found = TRUE;
                    break;
                }
                g_free( value );
            }
        }
        else {
            found = TRUE;
        }
    }
    if( found ) {
        gtk_list_store_remove( GTK_LIST_STORE( store ), &iter );
    }
    gtk_button_set_label( GTK_BUTTON( btnSave ), "Toevoegen" );
    // Weggooien
    ftd_filter_free_filter( filter );
}

void
ftd_gui_config_catfilters_callback_save( GtkButton * btn, gpointer data ) {
    int cat = GPOINTER_TO_INT(data);
    gboolean exists = FALSE;
    const gchar * name;
    FtdFilter *filter;
    FtdList *list = catfilters->filters;
    FtdList *tagsA = NULL;
    FtdList *tagsB = NULL;
    FtdList *tagsC = NULL;
    FtdList *tagsD = NULL;
    FtdList *tags;
    GtkWidget *tree;
    GtkTreeIter iter;
    GtkTreeModel *store;
    GtkWidget *txtName;
    GtkWidget *txtExtraTag;

    catfilters->changed_anything = TRUE;

    switch( cat ) {
        case 0 :
            tree = catfilters->lstCat0Filters;
            txtName = catfilters->txtCat0Name;
            txtExtraTag = catfilters->txtCat0ExtraTag;
            tagsA = catfilters->cat0TagsA;
            tagsB = catfilters->cat0TagsB;
            tagsC = catfilters->cat0TagsC;
            tagsD = catfilters->cat0TagsD;
            break;
        case 1 :
            tree = catfilters->lstCat1Filters;
            txtName = catfilters->txtCat1Name;
            txtExtraTag = catfilters->txtCat1ExtraTag;
            tagsA = catfilters->cat1TagsA;
            tagsB = catfilters->cat1TagsB;
            tagsC = catfilters->cat1TagsC;
            tagsD = catfilters->cat1TagsD;
            break;
        case 2 :
            tree = catfilters->lstCat2Filters;
            txtName = catfilters->txtCat2Name;
            txtExtraTag = catfilters->txtCat2ExtraTag;
            tagsA = catfilters->cat2TagsA;
            tagsB = catfilters->cat2TagsB;
            tagsC = catfilters->cat2TagsC;
            break;
        case 3 :
            tree = catfilters->lstCat3Filters;
            txtName = catfilters->txtCat3Name;
            txtExtraTag = catfilters->txtCat3ExtraTag;
            tagsA = catfilters->cat3TagsA;
            tagsB = catfilters->cat3TagsB;
            break;
        default :
            g_warning( "A filter was to be saved, but the data was illegal." );
            return;
    }

    name = gtk_entry_get_text( GTK_ENTRY( txtName ) );
    if( !strlen( name ) ) {
        // lege naam is ongeldig
        return;
    }

    while( list ) {
        FtdFilter *filter1 = ftd_list_value( list );
        if( filter1->cat == cat ) {
            if( !strcmp( ftd_string_value( filter1->filterNaam ), name ) ) {
                exists = TRUE;
                filter = filter1;
                break;
            }
        }
        list = ftd_list_next( list );
    }
    if( !exists ) {
        filter = ftd_filter_new_filter( );
        filter->filterNaam = ftd_string_new( name );
        filter->cat = cat;
        catfilters->filters = ftd_list_append( catfilters->filters, filter );
        store = gtk_tree_view_get_model( GTK_TREE_VIEW(tree) );
        gtk_list_store_append( GTK_LIST_STORE( store ), &iter );
        gtk_list_store_set( GTK_LIST_STORE( store ), &iter, 0, name, -1 );
        gtk_button_set_label( btn, "Opslaan" );
    }
    else {
        tags = filter->tags;
        while( tags ) {
            FtdString *tag = ftd_list_value( tags );
            g_assert( tag );
            ftd_string_free( tag );
            tags = ftd_list_next( tags );
        }
        filter->tags = NULL;
        if( filter->extra_tag ) {
            ftd_string_free( filter->extra_tag );
        }
        filter->extra_tag = NULL;
    }

    tags = tagsA;
    while( tags ) {
        GtkWidget *chkTag = ftd_list_value( tags );
        if( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( chkTag ) ) ) {
            filter->tags = ftd_list_append( filter->tags, ftd_string_new( ftd_string_value( g_object_get_data( G_OBJECT( chkTag ), "ftd_tag_code" ) ) ) );
        }
        tags = ftd_list_next( tags );
    }
    tags = tagsB;
    while( tags ) {
        GtkWidget *chkTag = ftd_list_value( tags );
        if( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( chkTag ) ) ) {
            filter->tags = ftd_list_append( filter->tags, ftd_string_new( ftd_string_value( g_object_get_data( G_OBJECT( chkTag ), "ftd_tag_code" ) ) ) );
        }
        tags = ftd_list_next( tags );
    }
    tags = tagsC;
    while( tags ) {
        GtkWidget *chkTag = ftd_list_value( tags );
        if( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( chkTag ) ) ) {
            filter->tags = ftd_list_append( filter->tags, ftd_string_new( ftd_string_value( g_object_get_data( G_OBJECT( chkTag ), "ftd_tag_code" ) ) ) );
        }
        tags = ftd_list_next( tags );
    }
    tags = tagsD;
    while( tags ) {
        GtkWidget *chkTag = ftd_list_value( tags );
        if( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( chkTag ) ) ) {
            filter->tags = ftd_list_append( filter->tags, ftd_string_new( ftd_string_value( g_object_get_data( G_OBJECT( chkTag ), "ftd_tag_code" ) ) ) );
        }
        tags = ftd_list_next( tags );
    }
    if( strlen( gtk_entry_get_text( GTK_ENTRY( txtExtraTag ) ) ) ) {
        filter->extra_tag = ftd_string_new( gtk_entry_get_text( GTK_ENTRY( txtExtraTag ) ) );
    }
}

void
ftd_gui_config_catfilters_callback_name_changed( GtkWidget * widget, GdkEventKey * event, gpointer data )
{
    int cat = GPOINTER_TO_INT(data);
    gboolean exists = FALSE;
    const gchar * text = gtk_entry_get_text( GTK_ENTRY( widget ) );
    FtdList *list = catfilters->filters;
    GtkWidget *btnSave;

    catfilters->changed_anything = TRUE;

    while( list ) {
        FtdFilter *filter = ftd_list_value( list );
        if( filter->cat == cat && !strcmp( ftd_string_value( filter->filterNaam ), text ) ) {
            exists = TRUE;
            break;
        }
        list = ftd_list_next( list );
    }
    switch( cat ) {
        case 0 :
            btnSave = catfilters->btnCat0Save;
            break;
        case 1 :
            btnSave = catfilters->btnCat1Save;
            break;
        case 2 :
            btnSave = catfilters->btnCat2Save;
            break;
        case 3 :
            btnSave = catfilters->btnCat3Save;
            break;
        default :
            g_warning( "A name was changed, but the data was not valid." );
            return;
    }
    if( exists ) {
        if( strcmp( gtk_button_get_label( GTK_BUTTON( btnSave ) ), "Opslaan" ) ) {
            gtk_button_set_label( GTK_BUTTON( btnSave ), "Opslaan" );
        }
    }
    else {
        if( strcmp( gtk_button_get_label( GTK_BUTTON( btnSave ) ), "Toevoegen" ) ) {
            gtk_button_set_label( GTK_BUTTON( btnSave ), "Toevoegen" );
        }
    }
}

void
ftd_gui_config_catfilters_callback_selection_changed( GtkTreeSelection * select, gpointer data )
{
    int cat = GPOINTER_TO_INT(data);
    GtkTreeModel *store;
    GtkWidget *list;
    GtkTreeIter iter;
    FtdFilter *filter = NULL;
    FtdList *filterlist;
    gchar *value;
    GtkWidget *txtName;
    GtkWidget *btnSave;
    GtkWidget *txtExtraTag;
    FtdList *tagsA = NULL;
    FtdList *tagsB = NULL;
    FtdList *tagsC = NULL;
    FtdList *tagsD = NULL;
    FtdList *taglist;
    FtdList *tags;

    switch( cat ) {
        case 0 :
            list = catfilters->lstCat0Filters;
            txtName = catfilters->txtCat0Name;
            btnSave = catfilters->btnCat0Save;
            txtExtraTag = catfilters->txtCat0ExtraTag;
            tagsA = catfilters->cat0TagsA;
            tagsB = catfilters->cat0TagsB;
            tagsC = catfilters->cat0TagsC;
            tagsD = catfilters->cat0TagsD;
            break;
        case 1 :
            list = catfilters->lstCat1Filters;
            txtName = catfilters->txtCat1Name;
            btnSave = catfilters->btnCat1Save;
            txtExtraTag = catfilters->txtCat1ExtraTag;
            tagsA = catfilters->cat1TagsA;
            tagsB = catfilters->cat1TagsB;
            tagsC = catfilters->cat1TagsC;
            tagsD = catfilters->cat1TagsD;
            break;
        case 2 :
            list = catfilters->lstCat2Filters;
            txtName = catfilters->txtCat2Name;
            btnSave = catfilters->btnCat2Save;
            txtExtraTag = catfilters->txtCat2ExtraTag;
            tagsA = catfilters->cat2TagsA;
            tagsB = catfilters->cat2TagsB;
            tagsC = catfilters->cat2TagsC;
            break;
        case 3 :
            list = catfilters->lstCat3Filters;
            txtName = catfilters->txtCat3Name;
            btnSave = catfilters->btnCat3Save;
            txtExtraTag = catfilters->txtCat3ExtraTag;
            tagsA = catfilters->cat3TagsA;
            tagsB = catfilters->cat3TagsB;
            break;
        default :
            g_warning( "A filter was to be moved up, but the data was illegal." );
            return;
    }

    // Selectie opzoeken
    select = gtk_tree_view_get_selection( GTK_TREE_VIEW(list) );
    if( !gtk_tree_selection_get_selected( select, &store, &iter ) ) {
        // Geen selectie om mee te werken
        return;
    }
    gtk_tree_model_get( store, &iter, 0, &value, -1 );

    // Bijbehorend filter opzoeken
    filterlist = catfilters->filters;
    while( filterlist ) {
        FtdFilter *filtertmp = ftd_list_value( filterlist );
        if( filtertmp->cat == cat ) {
            if( !strcmp( value, ftd_string_value( filtertmp->filterNaam ) ) ) {
                filter = filtertmp;
            }
        }
        filterlist = ftd_list_next( filterlist );
    }

    if( filter == NULL ) {
        g_warning( "Het bijbehorend filter is niet gevonden. Dit mag niet gebeuren." );
        g_free( value );
        return;
    }

    // Informatie in het veld vullen
    gtk_entry_set_text( GTK_ENTRY( txtName ), value );
    gtk_button_set_label( GTK_BUTTON( btnSave ), "Opslaan" );
    if( filter->extra_tag == NULL ) {
        gtk_entry_set_text( GTK_ENTRY( txtExtraTag ), "" );
    } else {
        gtk_entry_set_text( GTK_ENTRY( txtExtraTag ), ftd_string_value( filter->extra_tag ) );
    }
    tags = tagsA;
    while( tags ) {
        GtkWidget *chkTag = ftd_list_value( tags );
        gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( chkTag ), FALSE );
        tags = ftd_list_next( tags );
    }
    tags = tagsB;
    while( tags ) {
        GtkWidget *chkTag = ftd_list_value( tags );
        gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( chkTag ), FALSE );
        tags = ftd_list_next( tags );
    }
    tags = tagsC;
    while( tags ) {
        GtkWidget *chkTag = ftd_list_value( tags );
        gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( chkTag ), FALSE );
        tags = ftd_list_next( tags );
    }
    tags = tagsD;
    while( tags ) {
        GtkWidget *chkTag = ftd_list_value( tags );
        gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( chkTag ), FALSE );
        tags = ftd_list_next( tags );
    }
    taglist = filter->tags;
    while( taglist ) {
        FtdString *tag = ftd_list_value( taglist );
        switch( ftd_string_value( tag )[0] ) {
            case 'a' :
                tags = tagsA;
                break;
            case 'b' :
                tags = tagsB;
                break;
            case 'c' :
                tags = tagsC;
                break;
            case 'd' :
                tags = tagsD;
                break;
            default :
                g_warning( "Unknown tag" );
                taglist = ftd_list_next( taglist );
                continue;
        }
        if( tags == NULL ) {
            g_warning( "Unknown tag" );
            taglist = ftd_list_next( taglist );
            continue;
        }
        while( tags ) {
            GtkWidget *chkTag = ftd_list_value( tags );
            if( !strcmp( ftd_string_value( g_object_get_data( G_OBJECT( chkTag ), "ftd_tag_code" ) ), ftd_string_value( tag ) ) ) {
                gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( chkTag ), TRUE );
                break;
            }
            tags = ftd_list_next( tags );
        }
        taglist = ftd_list_next( taglist );
    }
    g_free( value );
}

void
ftd_gui_config_catfilters_callback_filter_up( GtkButton * btn, gpointer data )
{
    int cat = GPOINTER_TO_INT(data);
    GtkTreeModel *store;
    GtkWidget *list;
    GtkTreeSelection *selection;
    GtkTreeIter iter;
    GtkTreeIter iter2;
    GtkTreeIter iter3;
    gchar* value;
    gchar* value2;
    gboolean found = FALSE;
    FtdFilter **filter1 = NULL;
    FtdFilter **filter2 = NULL;
    FtdFilter *filter3;
    FtdList *filterlist;

    catfilters->changed_anything = TRUE;

    switch( cat ) {
        case 0 :
            list = catfilters->lstCat0Filters;
            break;
        case 1 :
            list = catfilters->lstCat1Filters;
            break;
        case 2 :
            list = catfilters->lstCat2Filters;
            break;
        case 3 :
            list = catfilters->lstCat3Filters;
            break;
        default :
            g_warning( "A filter was to be moved up, but the data was illegal." );
            return;
    }

    // Selectie opzoeken
    selection = gtk_tree_view_get_selection( GTK_TREE_VIEW(list) );
    if( !gtk_tree_selection_get_selected( selection, &store, &iter ) ) {
        // Geen selectie om mee te werken
        return;
    }
    gtk_tree_model_get( store, &iter, 0, &value, -1 );

    // De vorige opzoeken
    if( !gtk_tree_model_get_iter_first( store, &iter2 ) ) {
        // Lege lijst? Goedbeschouwd kunnen we hier niet komen...
        g_free( value );
        return;
    }

    gtk_tree_model_get( store, &iter2, 0, &value2, -1 );
    if( !strcmp( value, value2 ) ) {
        // De eerste geselecteerd
        g_free( value );
        g_free( value2 );
        return;
    }
    g_free( value2 );
    iter3 = iter2;
    while( gtk_tree_model_iter_next( store, &iter2 ) ) {
        gtk_tree_model_get( store, &iter2, 0, &value2, -1 );
        if( !strcmp( value, value2 ) ) {
            iter2 = iter3;
            g_free( value2 );
            found = TRUE;
            break;
        }
        g_free( value2 );
        iter3 = iter2;
    }

    if( !found ) {
        g_free( value );
        g_warning( "Vorige niet gevonden. Dit zou niet moeten kunnen!" );
        return;
    }

    gtk_tree_model_get( store, &iter2, 0, &value2, -1 );

    // Bijbehorende filters opzoeken
    filterlist = catfilters->filters;
    while( filterlist ) {
        FtdFilter *filter = ftd_list_value( filterlist );
        if( filter->cat == cat ) {
            if( !strcmp( value, ftd_string_value( filter->filterNaam ) ) ) {
                filter1 = (FtdFilter **) &(filterlist->data);
            }
            if( !strcmp( value2, ftd_string_value( filter->filterNaam ) ) ) {
                filter2 = (FtdFilter **) &(filterlist->data);
            }
        }
        filterlist = ftd_list_next( filterlist );
    }

    if( filter1 == NULL || filter2 == NULL ) {
        g_warning( "De bijbehorende filters zijn niet gevonden. Dit mag niet gebeuren." );
        g_free( value );
        g_free( value2 );
        return;
    }

    // Swap
    filter3 = (*filter1);
    (*filter1) = (*filter2);
    (*filter2) = filter3;

    // In de lijst aanpassen
    gtk_list_store_set( GTK_LIST_STORE( store ), &iter, 0, value2, -1 );
    gtk_list_store_set( GTK_LIST_STORE( store ), &iter2, 0, value, -1 );

    gtk_tree_selection_unselect_iter( selection, &iter );
    gtk_tree_selection_select_iter( selection, &iter2 );

    g_free( value );
    g_free( value2 );
}

void
ftd_gui_config_catfilters_callback_filter_down( GtkButton * btn, gpointer data )
{
    int cat = GPOINTER_TO_INT(data);
    GtkTreeModel *store;
    GtkWidget *list;
    GtkTreeSelection *selection;
    GtkTreeIter iter;
    GtkTreeIter iter2;
    gchar* value;
    gchar* value2;
    FtdFilter **filter1 = NULL;
    FtdFilter **filter2 = NULL;
    FtdFilter *filter3;
    FtdList *filterlist;

    catfilters->changed_anything = TRUE;

    switch( cat ) {
        case 0 :
            list = catfilters->lstCat0Filters;
            break;
        case 1 :
            list = catfilters->lstCat1Filters;
            break;
        case 2 :
            list = catfilters->lstCat2Filters;
            break;
        case 3 :
            list = catfilters->lstCat3Filters;
            break;
        default :
            g_warning( "A filter was to be moved down, but the data was illegal." );
            return;
    }

    // Selectie opzoeken
    selection = gtk_tree_view_get_selection( GTK_TREE_VIEW(list) );
    if( !gtk_tree_selection_get_selected( selection, &store, &iter ) ) {
        // Geen selectie om mee te werken
        return;
    }
    gtk_tree_model_get( store, &iter, 0, &value, -1 );

    // De volgende opzoeken
    iter2 = iter;
    if( !gtk_tree_model_iter_next( store, &iter2 ) ) {
        // Einde lijst
        g_free( value );
        return;
    }

    gtk_tree_model_get( store, &iter2, 0, &value2, -1 );

    // Bijbehorende filters opzoeken
    filterlist = catfilters->filters;
    while( filterlist ) {
        FtdFilter *filter = ftd_list_value( filterlist );
        if( filter->cat == cat ) {
            if( !strcmp( value, ftd_string_value( filter->filterNaam ) ) ) {
                filter1 = (FtdFilter **) &(filterlist->data);
            }
            if( !strcmp( value2, ftd_string_value( filter->filterNaam ) ) ) {
                filter2 = (FtdFilter **) &(filterlist->data);
            }
        }
        filterlist = ftd_list_next( filterlist );
    }

    if( filter1 == NULL || filter2 == NULL ) {
        g_warning( "De bijbehorende filters zijn niet gevonden. Dit mag niet gebeuren." );
        g_free( value );
        g_free( value2 );
        return;
    }

    // Swap
    filter3 = (*filter1);
    (*filter1) = (*filter2);
    (*filter2) = filter3;

    // In de lijst aanpassen
    gtk_list_store_set( GTK_LIST_STORE( store ), &iter, 0, value2, -1 );
    gtk_list_store_set( GTK_LIST_STORE( store ), &iter2, 0, value, -1 );

    gtk_tree_selection_unselect_iter( selection, &iter );
    gtk_tree_selection_select_iter( selection, &iter2 );

    g_free( value );
    g_free( value2 );
}

void
ftd_gui_config_catfilters_free(FtdGuiConfig *config)
{
    FtdList *filters;

    g_assert( config );
    g_assert( config->catfilters );

    filters = catfilters->filters;
    while( filters ) {
        FtdFilter *filter = ftd_list_value( filters );
        ftd_filter_free_filter( filter );
        filters = ftd_list_next( filters );
    }
    g_free( config->catfilters );
    config->catfilters = NULL;
}
