Blame src/gtk-helpers/config_dialog.c

Packit Service 779887
/*
Packit Service 779887
    Copyright (C) 2011  ABRT Team
Packit Service 779887
    Copyright (C) 2011  RedHat inc.
Packit Service 779887
Packit Service 779887
    This program is free software; you can redistribute it and/or modify
Packit Service 779887
    it under the terms of the GNU General Public License as published by
Packit Service 779887
    the Free Software Foundation; either version 2 of the License, or
Packit Service 779887
    (at your option) any later version.
Packit Service 779887
Packit Service 779887
    This program is distributed in the hope that it will be useful,
Packit Service 779887
    but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 779887
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit Service 779887
    GNU General Public License for more details.
Packit Service 779887
Packit Service 779887
    You should have received a copy of the GNU General Public License along
Packit Service 779887
    with this program; if not, write to the Free Software Foundation, Inc.,
Packit Service 779887
    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Packit Service 779887
*/
Packit Service 779887
Packit Service 779887
#include <gtk/gtk.h>
Packit Service 779887
#include <gdk/gdk.h>
Packit Service 779887
#include "internal_libreport_gtk.h"
Packit Service 779887
Packit Service 779887
enum
Packit Service 779887
{
Packit Service 779887
    COLUMN_UINAME,
Packit Service 779887
    COLUMN_NAME,
Packit Service 779887
    CONFIG_DIALOG,
Packit Service 779887
    NUM_COLUMNS
Packit Service 779887
};
Packit Service 779887
Packit Service 779887
enum
Packit Service 779887
{
Packit Service 779887
    TYPE_STR,
Packit Service 779887
    TYPE_POINTER
Packit Service 779887
};
Packit Service 779887
Packit Service 779887
struct config_dialog
Packit Service 779887
{
Packit Service 779887
    GtkWidget *dialog;
Packit Service 779887
    gpointer *data;
Packit Service 779887
    config_save_fun_t save_data;
Packit Service 779887
};
Packit Service 779887
Packit Service 779887
GtkListStore *new_conf_liststore(void)
Packit Service 779887
{
Packit Service 779887
    /* Create data store for the list and attach it
Packit Service 779887
     * COLUMN_UINAME -> name+description
Packit Service 779887
     * COLUMN_NAME -> config name so we can retrieve it from the row
Packit Service 779887
     */
Packit Service 779887
    return gtk_list_store_new(NUM_COLUMNS,
Packit Service 779887
                              G_TYPE_STRING, /* Event name + description */
Packit Service 779887
                              G_TYPE_STRING,  /* event name */
Packit Service 779887
                              G_TYPE_POINTER, /* dialog */
Packit Service 779887
                              G_TYPE_POINTER /* option_list */
Packit Service 779887
                            );
Packit Service 779887
}
Packit Service 779887
Packit Service 779887
Packit Service 779887
config_dialog_t *new_config_dialog(GtkWidget *dialog,
Packit Service 779887
                                   gpointer config_data,
Packit Service 779887
                                   config_save_fun_t save_fun)
Packit Service 779887
{
Packit Service 779887
    config_dialog_t *cdialog = (config_dialog_t *)xmalloc(sizeof(*cdialog));
Packit Service 779887
    cdialog->dialog = dialog;
Packit Service 779887
    cdialog->data = config_data;
Packit Service 779887
    cdialog->save_data = save_fun;
Packit Service 779887
    return cdialog;
Packit Service 779887
}
Packit Service 779887
Packit Service 779887
void cdialog_set_widget(config_dialog_t *cdialog, GtkWidget *widget)
Packit Service 779887
{
Packit Service 779887
    //TODO destroy(cdialog-dialog) ??
Packit Service 779887
    cdialog->dialog = widget;
Packit Service 779887
}
Packit Service 779887
Packit Service 779887
GtkWidget *cdialog_get_widget(config_dialog_t *cdialog)
Packit Service 779887
{
Packit Service 779887
    return cdialog->dialog;
Packit Service 779887
}
Packit Service 779887
Packit Service 779887
gpointer cdialog_get_data(config_dialog_t *cdialog)
Packit Service 779887
{
Packit Service 779887
    return cdialog->data;
Packit Service 779887
}
Packit Service 779887
Packit Service 779887
int cdialog_run(config_dialog_t *cdialog, const char *name)
Packit Service 779887
{
Packit Service 779887
    if (cdialog == NULL || cdialog->dialog == NULL)
Packit Service 779887
    {
Packit Service 779887
        log_warning("There is no configurable option for: '%s'", name);
Packit Service 779887
        return GTK_RESPONSE_REJECT;
Packit Service 779887
    }
Packit Service 779887
Packit Service 779887
    const int result = gtk_dialog_run(GTK_DIALOG(cdialog->dialog));
Packit Service 779887
    if (result == GTK_RESPONSE_APPLY)
Packit Service 779887
    {
Packit Service 779887
        if (cdialog->save_data)
Packit Service 779887
            cdialog->save_data(cdialog->data, name);
Packit Service 779887
    }
Packit Service 779887
    else if (result == GTK_RESPONSE_CANCEL)
Packit Service 779887
        log_notice("Cancelling on user request");
Packit Service 779887
Packit Service 779887
    gtk_widget_hide(GTK_WIDGET(cdialog->dialog));
Packit Service 779887
Packit Service 779887
    return result;
Packit Service 779887
}
Packit Service 779887
Packit Service 779887
static const void *get_column_value_from_row(GtkTreeView *treeview, int column, int type)
Packit Service 779887
{
Packit Service 779887
    GtkTreeSelection *selection = gtk_tree_view_get_selection(treeview);
Packit Service 779887
    const void *retval = NULL;
Packit Service 779887
    if (selection)
Packit Service 779887
    {
Packit Service 779887
        GtkTreeIter iter;
Packit Service 779887
        GtkTreeModel *store = gtk_tree_view_get_model(treeview);
Packit Service 779887
        if (gtk_tree_selection_get_selected(selection, &store, &iter) == TRUE)
Packit Service 779887
        {
Packit Service 779887
            GValue value = { 0 };
Packit Service 779887
            gtk_tree_model_get_value(store, &iter, column, &value);
Packit Service 779887
            switch(type){
Packit Service 779887
                case TYPE_STR:
Packit Service 779887
                    retval = g_value_get_string(&value);
Packit Service 779887
                    break;
Packit Service 779887
                case TYPE_POINTER:
Packit Service 779887
                    retval = g_value_get_pointer(&value);
Packit Service 779887
            }
Packit Service 779887
        }
Packit Service 779887
    }
Packit Service 779887
    return retval;
Packit Service 779887
}
Packit Service 779887
Packit Service 779887
static void save_value_from_widget(gpointer data, gpointer user_data)
Packit Service 779887
{
Packit Service 779887
    option_widget_t *ow = (option_widget_t *)data;
Packit Service 779887
Packit Service 779887
    const char *val = NULL;
Packit Service 779887
    switch (ow->option->eo_type)
Packit Service 779887
    {
Packit Service 779887
        case OPTION_TYPE_TEXT:
Packit Service 779887
        case OPTION_TYPE_NUMBER:
Packit Service 779887
        case OPTION_TYPE_PASSWORD:
Packit Service 779887
            val = (char *)gtk_entry_get_text(GTK_ENTRY(ow->widget));
Packit Service 779887
            break;
Packit Service 779887
        case OPTION_TYPE_BOOL:
Packit Service 779887
            val = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ow->widget)) ? "yes" : "no";
Packit Service 779887
            break;
Packit Service 779887
        default:
Packit Service 779887
            log_warning("unsupported option type");
Packit Service 779887
    }
Packit Service 779887
Packit Service 779887
    /* gtk_entry_get_text() returns empty string for empty text value */
Packit Service 779887
    /* so if value is empty and the old value is NULL then nothing has */
Packit Service 779887
    /* changed and we must not set option's value */
Packit Service 779887
    if (val && (val[0] != '\0' || ow->option->eo_value != NULL))
Packit Service 779887
    {
Packit Service 779887
        free(ow->option->eo_value);
Packit Service 779887
        ow->option->eo_value = xstrdup(val);
Packit Service 779887
        log_notice("saved: %s:%s", ow->option->eo_name, ow->option->eo_value);
Packit Service 779887
    }
Packit Service 779887
}
Packit Service 779887
Packit Service 779887
void dehydrate_config_dialog(GList *option_widgets)
Packit Service 779887
{
Packit Service 779887
    if (option_widgets != NULL)
Packit Service 779887
        g_list_foreach(option_widgets, &save_value_from_widget, NULL);
Packit Service 779887
}
Packit Service 779887
Packit Service 779887
void add_item_to_config_liststore(gpointer cdialog, gpointer inf, gpointer user_data)
Packit Service 779887
{
Packit Service 779887
    INITIALIZE_LIBREPORT();
Packit Service 779887
Packit Service 779887
    GtkListStore *list_store = (GtkListStore *)user_data;
Packit Service 779887
    config_item_info_t *info = (config_item_info_t *)inf;
Packit Service 779887
Packit Service 779887
    log_notice("adding '%s' to workflow list\n", ci_get_screen_name(info));
Packit Service 779887
    char *label;
Packit Service 779887
    if (ci_get_screen_name(info) != NULL && ci_get_description(info) != NULL)
Packit Service 779887
        label = xasprintf("%s\n%s",ci_get_screen_name(info), ci_get_description(info));
Packit Service 779887
    else
Packit Service 779887
        //if event has no xml description
Packit Service 779887
        label = xasprintf("%s\n%s", _("No description available"), ci_get_name(info));
Packit Service 779887
Packit Service 779887
    GtkTreeIter iter;
Packit Service 779887
    gtk_list_store_append(list_store, &iter);
Packit Service 779887
    gtk_list_store_set(list_store, &iter,
Packit Service 779887
                      COLUMN_UINAME, label,
Packit Service 779887
                      COLUMN_NAME, ci_get_name(info),
Packit Service 779887
                      CONFIG_DIALOG, cdialog,
Packit Service 779887
                      -1);
Packit Service 779887
    free(label);
Packit Service 779887
}
Packit Service 779887
Packit Service 779887
//filters configuration - show only those with configurable options trac#881
Packit Service 779887
static gboolean config_filter_func(GtkTreeModel *model,
Packit Service 779887
                                   GtkTreeIter  *iter,
Packit Service 779887
                                   gpointer      data)
Packit Service 779887
{
Packit Service 779887
  gboolean visible = FALSE;
Packit Service 779887
  gpointer cdialog;
Packit Service 779887
Packit Service 779887
  GValue value = { 0 };
Packit Service 779887
  gtk_tree_model_get_value(model, iter, CONFIG_DIALOG, &value);
Packit Service 779887
  cdialog = g_value_get_pointer(&value);
Packit Service 779887
  visible = (cdialog != NULL);
Packit Service 779887
Packit Service 779887
  return visible;
Packit Service 779887
}
Packit Service 779887
Packit Service 779887
static void open_config_for_selected_row(GtkTreeView *tv)
Packit Service 779887
{
Packit Service 779887
    config_dialog_t *cdialog = (config_dialog_t *)get_column_value_from_row(tv, CONFIG_DIALOG, TYPE_POINTER);
Packit Service 779887
    const char *name = (const char *)get_column_value_from_row(tv, COLUMN_NAME, TYPE_STR);
Packit Service 779887
Packit Service 779887
    cdialog_run(cdialog, name);
Packit Service 779887
}
Packit Service 779887
Packit Service 779887
static gboolean on_key_press_event_cb(GtkWidget *btn, GdkEvent *event, gpointer user_data)
Packit Service 779887
{
Packit Service 779887
    GdkEventKey *ek = (GdkEventKey *)event;
Packit Service 779887
Packit Service 779887
    if (ek->keyval == GDK_KEY_Return)
Packit Service 779887
    {
Packit Service 779887
        GtkTreeView *tv = (GtkTreeView *)user_data;
Packit Service 779887
        open_config_for_selected_row(tv);
Packit Service 779887
    }
Packit Service 779887
Packit Service 779887
    return FALSE;
Packit Service 779887
}
Packit Service 779887
Packit Service 779887
static gboolean on_button_press_event_cb(GtkWidget *btn, GdkEvent *event, gpointer user_data)
Packit Service 779887
{
Packit Service 779887
    GdkEventButton *eb = (GdkEventButton *)event;
Packit Service 779887
Packit Service 779887
    if (eb->type == GDK_2BUTTON_PRESS)
Packit Service 779887
    {
Packit Service 779887
        GtkTreeView *tv = (GtkTreeView *)user_data;
Packit Service 779887
        open_config_for_selected_row(tv);
Packit Service 779887
    }
Packit Service 779887
Packit Service 779887
    return FALSE;
Packit Service 779887
}
Packit Service 779887
Packit Service 779887
GtkWidget *create_config_tab_content(const char *column_label,
Packit Service 779887
                                      GtkListStore *store)
Packit Service 779887
{
Packit Service 779887
    GtkWidget *main_vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
Packit Service 779887
    GtkWidget *scroll = gtk_scrolled_window_new(NULL, NULL);
Packit Service 779887
    gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll),
Packit Service 779887
                                    GTK_POLICY_NEVER,
Packit Service 779887
                                    GTK_POLICY_AUTOMATIC);
Packit Service 779887
    /* workflow list treeview */
Packit Service 779887
    GtkWidget *tv = gtk_tree_view_new();
Packit Service 779887
    g_signal_connect(tv, "key-press-event", G_CALLBACK(on_key_press_event_cb), tv);
Packit Service 779887
    g_signal_connect(tv, "button-press-event", G_CALLBACK(on_button_press_event_cb), tv);
Packit Service 779887
Packit Service 779887
    /* column with workflow name and description */
Packit Service 779887
    GtkCellRenderer *renderer;
Packit Service 779887
    GtkTreeViewColumn *column;
Packit Service 779887
Packit Service 779887
    /* add column to tree view */
Packit Service 779887
    renderer = gtk_cell_renderer_text_new();
Packit Service 779887
    column = gtk_tree_view_column_new_with_attributes(column_label,
Packit Service 779887
                                                 renderer,
Packit Service 779887
                                                 "markup",
Packit Service 779887
                                                 COLUMN_UINAME,
Packit Service 779887
                                                 NULL);
Packit Service 779887
    gtk_tree_view_column_set_resizable(column, TRUE);
Packit Service 779887
    g_object_set(G_OBJECT(renderer), "wrap-mode", PANGO_WRAP_WORD, NULL);
Packit Service 779887
    g_object_set(G_OBJECT(renderer), "wrap-width", 440, NULL);
Packit Service 779887
    gtk_tree_view_column_set_sort_column_id(column, COLUMN_NAME);
Packit Service 779887
    gtk_tree_view_append_column(GTK_TREE_VIEW(tv), column);
Packit Service 779887
Packit Service 779887
    // TODO: gtk_tree_view_set_headers_visible(FALSE)? We have only one column anyway...
Packit Service 779887
    GtkTreeModel *model = gtk_tree_model_filter_new(GTK_TREE_MODEL(store), NULL);
Packit Service 779887
    gtk_tree_model_filter_set_visible_func(GTK_TREE_MODEL_FILTER(model), config_filter_func, NULL, NULL);
Packit Service 779887
Packit Service 779887
    gtk_tree_view_set_model(GTK_TREE_VIEW(tv), GTK_TREE_MODEL(model));
Packit Service 779887
Packit Service 779887
    {   /* Selected the first row, so we do not need to call gtk_tree_view_scroll_to_cell() */
Packit Service 779887
        GtkTreeIter iter;
Packit Service 779887
        gtk_tree_model_get_iter_first(model, &iter);
Packit Service 779887
        GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(tv));
Packit Service 779887
        gtk_tree_selection_select_iter(selection, &iter);
Packit Service 779887
    }
Packit Service 779887
Packit Service 779887
    gtk_container_add(GTK_CONTAINER(scroll), tv);
Packit Service 779887
Packit Service 779887
    gtk_box_pack_start(GTK_BOX(main_vbox), scroll, true, true, 10);
Packit Service 779887
    return main_vbox;
Packit Service 779887
}
Packit Service 779887
Packit Service 779887
static void add_config_tabs(const char *name, GtkListStore *store, gpointer nb)
Packit Service 779887
{
Packit Service 779887
    GtkNotebook *ntb = (GtkNotebook *)nb;
Packit Service 779887
Packit Service 779887
    GtkWidget *config_list_vbox = create_config_tab_content(
Packit Service 779887
                                        name,
Packit Service 779887
                                        store);
Packit Service 779887
Packit Service 779887
    gtk_notebook_append_page(ntb, config_list_vbox, gtk_label_new(name));
Packit Service 779887
}
Packit Service 779887
Packit Service 779887
static void on_configure_cb(GtkWidget *btn, gpointer user_data)
Packit Service 779887
{
Packit Service 779887
    GtkNotebook *nb = (GtkNotebook *)user_data;
Packit Service 779887
Packit Service 779887
    guint current_page_n = gtk_notebook_get_current_page(nb);
Packit Service 779887
    GtkWidget *vbox = gtk_notebook_get_nth_page(nb, current_page_n);
Packit Service 779887
    GList *children = gtk_container_get_children(GTK_CONTAINER(vbox));
Packit Service 779887
    GtkScrolledWindow *sw = (GtkScrolledWindow *)children->data;
Packit Service 779887
Packit Service 779887
    open_config_for_selected_row((GtkTreeView *)gtk_bin_get_child(GTK_BIN(sw)));
Packit Service 779887
}
Packit Service 779887
Packit Service 779887
static void on_close_cb(GtkWidget *btn, gpointer config_list_w)
Packit Service 779887
{
Packit Service 779887
    GtkWidget *w = (GtkWidget *)config_list_w;
Packit Service 779887
    gtk_widget_hide(w);
Packit Service 779887
}
Packit Service 779887
Packit Service 779887
GtkWindow *create_config_list_window(GHashTable *configs, GtkWindow *parent)
Packit Service 779887
{
Packit Service 779887
    INITIALIZE_LIBREPORT();
Packit Service 779887
Packit Service 779887
    // config window
Packit Service 779887
    GtkWidget *window = NULL;
Packit Service 779887
    if (parent != NULL)
Packit Service 779887
    {
Packit Service 779887
        window = gtk_dialog_new();
Packit Service 779887
        gtk_window_set_icon_name(GTK_WINDOW(window), gtk_window_get_icon_name(parent));
Packit Service 779887
        gtk_window_set_modal(GTK_WINDOW(window), TRUE);
Packit Service 779887
        gtk_window_set_transient_for(GTK_WINDOW(window), parent);
Packit Service 779887
    }
Packit Service 779887
    else
Packit Service 779887
        window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
Packit Service 779887
Packit Service 779887
    gtk_container_set_border_width(GTK_CONTAINER(window), 5);
Packit Service 779887
    gtk_window_set_title(GTK_WINDOW(window), _("Configuration"));
Packit Service 779887
    gtk_window_set_default_size(GTK_WINDOW(window), 450, 400);
Packit Service 779887
    gtk_window_set_position(GTK_WINDOW(window), parent
Packit Service 779887
                            ? GTK_WIN_POS_CENTER_ON_PARENT
Packit Service 779887
                            : GTK_WIN_POS_CENTER);
Packit Service 779887
Packit Service 779887
Packit Service 779887
    //g_signal_connect(window, "destroy", G_CALLBACK (gtk_main_quit), NULL);
Packit Service 779887
Packit Service 779887
    GtkWidget *main_vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 5);
Packit Service 779887
    GtkWidget *config_nb = gtk_notebook_new();
Packit Service 779887
    gtk_box_pack_start(GTK_BOX(main_vbox), config_nb, 1, 1, 0);
Packit Service 779887
Packit Service 779887
    /* we can't use this, because we want the workflows first and hashtable
Packit Service 779887
     * doesn't return the items in the order they were added
Packit Service 779887
     */
Packit Service 779887
    //g_hash_table_foreach(configs, (GHFunc)add_config_tabs, config_nb);
Packit Service 779887
Packit Service 779887
    gpointer config = g_hash_table_lookup(configs, _("Workflows"));
Packit Service 779887
    if (config != NULL)
Packit Service 779887
        add_config_tabs(_("Workflows"), config, config_nb);
Packit Service 779887
Packit Service 779887
    config = g_hash_table_lookup(configs, _("Events"));
Packit Service 779887
    if (config != NULL)
Packit Service 779887
        add_config_tabs(_("Events"), config, config_nb);
Packit Service 779887
Packit Service 779887
    //buttons
Packit Service 779887
    GtkWidget *btn_box = gtk_box_new(GTK_ORIENTATION_HORIZONTAL,5);
Packit Service 779887
    GtkWidget *configure_btn = gtk_button_new_with_mnemonic(_("C_onfigure"));
Packit Service 779887
Packit Service 779887
    GtkWidget *close_btn = gtk_button_new_with_mnemonic(_("_Close"));
Packit Service 779887
    GtkSizeGroup *sg = gtk_size_group_new(GTK_SIZE_GROUP_BOTH);
Packit Service 779887
    //force apply and close to have the same size
Packit Service 779887
    gtk_size_group_add_widget(sg, close_btn);
Packit Service 779887
    gtk_size_group_add_widget(sg, configure_btn);
Packit Service 779887
Packit Service 779887
    g_signal_connect(configure_btn, "clicked", (GCallback)on_configure_cb, config_nb);
Packit Service 779887
    g_signal_connect(close_btn, "clicked", (GCallback)on_close_cb, window);
Packit Service 779887
Packit Service 779887
    gtk_box_pack_start(GTK_BOX(btn_box), close_btn, 0, 0, 5);
Packit Service 779887
    gtk_box_pack_end(GTK_BOX(btn_box), configure_btn, 0, 0, 5);
Packit Service 779887
Packit Service 779887
Packit Service 779887
    gtk_box_pack_start(GTK_BOX(main_vbox), btn_box, 0, 0, 0);
Packit Service 779887
    if (parent != NULL)
Packit Service 779887
    {
Packit Service 779887
        GtkWidget *content = gtk_dialog_get_content_area(GTK_DIALOG(window));
Packit Service 779887
        gtk_box_pack_start(GTK_BOX(content), main_vbox, /*expand*/TRUE, /*fill*/TRUE, /*padding*/0);
Packit Service 779887
        gtk_widget_show_all(content);
Packit Service 779887
    }
Packit Service 779887
    else
Packit Service 779887
        gtk_container_add(GTK_CONTAINER(window), main_vbox);
Packit Service 779887
Packit Service 779887
    //gtk_widget_show_all(window);
Packit Service 779887
    return GTK_WINDOW(window);
Packit Service 779887
}
Packit Service 779887
Packit Service 779887
/*  Name | vbox with the gtk_Tree
Packit Service 779887
 * <String name, GtkWidget *vbox>
Packit Service 779887
*/
Packit Service 779887
Packit Service 779887
void show_config_list_dialog(GtkWindow *parent)
Packit Service 779887
{
Packit Service 779887
    INITIALIZE_LIBREPORT();
Packit Service 779887
Packit Service 779887
    GHashTable *confs = g_hash_table_new_full(
Packit Service 779887
            /*hash_func*/ g_str_hash,
Packit Service 779887
            /*key_equal_func:*/ g_str_equal,
Packit Service 779887
            /*key_destroy_func:*/ g_free,
Packit Service 779887
            /*value_destroy_func:*/ NULL);
Packit Service 779887
Packit Service 779887
Packit Service 779887
    //TODO: free the hashtables somewhere!!
Packit Service 779887
    GHashTable *events = load_event_config_data();
Packit Service 779887
    load_event_config_data_from_user_storage(events);
Packit Service 779887
Packit Service 779887
    GHashTable *workflows = load_workflow_config_data(WORKFLOWS_DIR);
Packit Service 779887
    load_workflow_config_data_from_user_storage(workflows);
Packit Service 779887
    GtkListStore *workflows_store = add_workflows_to_liststore(workflows);
Packit Service 779887
    g_hash_table_insert(confs, _("Workflows"), workflows_store);
Packit Service 779887
Packit Service 779887
    GtkListStore *events_store = add_events_to_liststore(events);
Packit Service 779887
    g_hash_table_insert(confs, _("Events"), events_store);
Packit Service 779887
Packit Service 779887
    GtkWindow *window = create_config_list_window(confs, parent);
Packit Service 779887
    gtk_widget_show_all(GTK_WIDGET(window));
Packit Service 779887
}