Blame src/gtk-helpers/event_config_dialog.c

Packit 4f15d5
/*
Packit 4f15d5
    Copyright (C) 2011  ABRT Team
Packit 4f15d5
    Copyright (C) 2011  RedHat inc.
Packit 4f15d5
Packit 4f15d5
    This program is free software; you can redistribute it and/or modify
Packit 4f15d5
    it under the terms of the GNU General Public License as published by
Packit 4f15d5
    the Free Software Foundation; either version 2 of the License, or
Packit 4f15d5
    (at your option) any later version.
Packit 4f15d5
Packit 4f15d5
    This program is distributed in the hope that it will be useful,
Packit 4f15d5
    but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 4f15d5
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit 4f15d5
    GNU General Public License for more details.
Packit 4f15d5
Packit 4f15d5
    You should have received a copy of the GNU General Public License along
Packit 4f15d5
    with this program; if not, write to the Free Software Foundation, Inc.,
Packit 4f15d5
    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Packit 4f15d5
*/
Packit 4f15d5
#include <gtk/gtk.h>
Packit 4f15d5
#include "internal_libreport_gtk.h"
Packit 4f15d5
Packit 4f15d5
static GtkWindow *g_event_list_window;
Packit 4f15d5
static GList *g_option_list = NULL;
Packit 4f15d5
Packit 4f15d5
static bool has_password_option;
Packit 4f15d5
Packit 4f15d5
enum
Packit 4f15d5
{
Packit 4f15d5
    COLUMN_EVENT_UINAME,
Packit 4f15d5
    COLUMN_EVENT_NAME,
Packit 4f15d5
    NUM_COLUMNS
Packit 4f15d5
};
Packit 4f15d5
Packit 4f15d5
static GtkWidget *gtk_label_new_justify_left(const gchar *label_str)
Packit 4f15d5
{
Packit 4f15d5
    GtkWidget *label = gtk_label_new(label_str);
Packit 4f15d5
    gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_LEFT);
Packit 4f15d5
Packit 4f15d5
    gtk_widget_set_halign (label, GTK_ALIGN_START);
Packit 4f15d5
    /* Make some space between label and input field to the right of it: */
Packit 4f15d5
    gtk_widget_set_margin_start(label, 5);
Packit 4f15d5
    gtk_widget_set_margin_end(label, 5);
Packit 4f15d5
Packit 4f15d5
    return label;
Packit 4f15d5
}
Packit 4f15d5
Packit 4f15d5
GList *add_option_widget(GList *options, GtkWidget *widget, event_option_t *option)
Packit 4f15d5
{
Packit 4f15d5
    option_widget_t *ow = (option_widget_t *)xmalloc(sizeof(*ow));
Packit 4f15d5
    ow->widget = widget;
Packit 4f15d5
    ow->option = option;
Packit 4f15d5
    options = g_list_prepend(options, ow);
Packit 4f15d5
Packit 4f15d5
    return options;
Packit 4f15d5
}
Packit 4f15d5
Packit 4f15d5
static void on_show_pass_cb(GtkToggleButton *tb, gpointer user_data)
Packit 4f15d5
{
Packit 4f15d5
    GtkEntry *entry = (GtkEntry *)user_data;
Packit 4f15d5
    gtk_entry_set_visibility(entry, gtk_toggle_button_get_active(tb));
Packit 4f15d5
}
Packit 4f15d5
Packit 4f15d5
static void on_show_pass_store_cb(GtkToggleButton *tb, gpointer user_data)
Packit 4f15d5
{
Packit 4f15d5
    set_user_setting("store_passwords", gtk_toggle_button_get_active(tb) ? "no" : "yes");
Packit 4f15d5
}
Packit 4f15d5
Packit 4f15d5
static unsigned add_one_row_to_grid(GtkGrid *table)
Packit 4f15d5
{
Packit 4f15d5
    gulong rows = (gulong)g_object_get_data(G_OBJECT(table), "n-rows");
Packit 4f15d5
    gtk_grid_insert_row(table, rows);
Packit 4f15d5
    g_object_set_data(G_OBJECT(table), "n-rows", (gpointer)(rows + 1));
Packit 4f15d5
    return rows;
Packit 4f15d5
}
Packit 4f15d5
Packit 4f15d5
void save_data_from_event_config_dialog(GList *widgets, event_config_t *ec)
Packit 4f15d5
{
Packit 4f15d5
    dehydrate_config_dialog(widgets);
Packit 4f15d5
    const char *const store_passwords_s = get_user_setting("store_passwords");
Packit 4f15d5
    save_event_config_data_to_user_storage(ec_get_name(ec),
Packit 4f15d5
                                           ec,
Packit 4f15d5
                                           !(store_passwords_s && !strcmp(store_passwords_s, "no")));
Packit 4f15d5
}
Packit 4f15d5
Packit 4f15d5
static void save_data_from_event_dialog_name(GList *widgets, const char *name)
Packit 4f15d5
{
Packit 4f15d5
    event_config_t *ec = get_event_config(name);
Packit 4f15d5
Packit 4f15d5
    save_data_from_event_config_dialog(widgets, ec);
Packit 4f15d5
}
Packit 4f15d5
Packit 4f15d5
Packit 4f15d5
static void add_option_to_table(gpointer data, gpointer user_data)
Packit 4f15d5
{
Packit 4f15d5
    event_option_t *option = data;
Packit 4f15d5
    GtkGrid *option_table = user_data;
Packit 4f15d5
    if (option->is_advanced)
Packit 4f15d5
        option_table = GTK_GRID(g_object_get_data(G_OBJECT(option_table), "advanced-options"));
Packit 4f15d5
Packit 4f15d5
    GtkWidget *label;
Packit 4f15d5
    GtkWidget *option_input;
Packit 4f15d5
    unsigned last_row;
Packit 4f15d5
Packit 4f15d5
    char *option_label;
Packit 4f15d5
    if (option->eo_label != NULL)
Packit 4f15d5
        option_label = xstrdup(option->eo_label);
Packit 4f15d5
    else
Packit 4f15d5
    {
Packit 4f15d5
        option_label = xstrdup(option->eo_name ? option->eo_name : "");
Packit 4f15d5
        /* Replace '_' with ' ' */
Packit 4f15d5
        char *p = option_label - 1;
Packit 4f15d5
        while (*++p)
Packit 4f15d5
            if (*p == '_')
Packit 4f15d5
                *p = ' ';
Packit 4f15d5
    }
Packit 4f15d5
Packit 4f15d5
    switch (option->eo_type)
Packit 4f15d5
    {
Packit 4f15d5
        case OPTION_TYPE_TEXT:
Packit 4f15d5
        case OPTION_TYPE_NUMBER:
Packit 4f15d5
        case OPTION_TYPE_PASSWORD:
Packit 4f15d5
            last_row = add_one_row_to_grid(option_table);
Packit 4f15d5
            label = gtk_label_new_justify_left(option_label);
Packit 4f15d5
            gtk_grid_attach(option_table, label,
Packit 4f15d5
                             /*left,top:*/ 0, last_row,
Packit 4f15d5
                             /*width,height:*/ 1, 1);
Packit 4f15d5
            option_input = gtk_entry_new();
Packit 4f15d5
            gtk_entry_set_activates_default(GTK_ENTRY(option_input), TRUE);
Packit 4f15d5
            gtk_widget_set_hexpand(option_input, TRUE);
Packit 4f15d5
            if (option->eo_value != NULL)
Packit 4f15d5
                gtk_entry_set_text(GTK_ENTRY(option_input), option->eo_value);
Packit 4f15d5
            gtk_grid_attach(option_table, option_input,
Packit 4f15d5
                             /*left,top:*/ 1, last_row,
Packit 4f15d5
                             /*width,height:*/ 1, 1);
Packit 4f15d5
            g_option_list = add_option_widget(g_option_list, option_input, option);
Packit 4f15d5
            if (option->eo_type == OPTION_TYPE_PASSWORD)
Packit 4f15d5
            {
Packit 4f15d5
                gtk_entry_set_visibility(GTK_ENTRY(option_input), 0);
Packit 4f15d5
                last_row = add_one_row_to_grid(option_table);
Packit 4f15d5
                GtkWidget *pass_cb = gtk_check_button_new_with_label(_("Show password"));
Packit 4f15d5
                gtk_grid_attach(option_table, pass_cb,
Packit 4f15d5
                             /*left,top:*/ 1, last_row,
Packit 4f15d5
                             /*width,height:*/ 1, 1);
Packit 4f15d5
                g_signal_connect(pass_cb, "toggled", G_CALLBACK(on_show_pass_cb), option_input);
Packit 4f15d5
                has_password_option = true;
Packit 4f15d5
            }
Packit 4f15d5
            break;
Packit 4f15d5
Packit 4f15d5
        case OPTION_TYPE_HINT_HTML:
Packit 4f15d5
            label = gtk_label_new(option_label);
Packit 4f15d5
            gtk_label_set_use_markup(GTK_LABEL(label), TRUE);
Packit 4f15d5
Packit 4f15d5
            gtk_widget_set_halign(label, GTK_ALIGN_START);
Packit 4f15d5
            gtk_widget_set_valign(label, GTK_ALIGN_START);
Packit 4f15d5
Packit 4f15d5
            make_label_autowrap_on_resize(GTK_LABEL(label));
Packit 4f15d5
Packit 4f15d5
            last_row = add_one_row_to_grid(option_table);
Packit 4f15d5
            gtk_grid_attach(option_table, label,
Packit 4f15d5
                             /*left,top:*/ 0, last_row,
Packit 4f15d5
                             /*width,height:*/ 2, 1);
Packit 4f15d5
            break;
Packit 4f15d5
Packit 4f15d5
        case OPTION_TYPE_BOOL:
Packit 4f15d5
            last_row = add_one_row_to_grid(option_table);
Packit 4f15d5
            option_input = gtk_check_button_new_with_label(option_label);
Packit 4f15d5
            gtk_grid_attach(option_table, option_input,
Packit 4f15d5
                             /*left,top:*/ 0, last_row,
Packit 4f15d5
                             /*width,height:*/ 2, 1);
Packit 4f15d5
            if (option->eo_value != NULL)
Packit 4f15d5
                gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(option_input),
Packit 4f15d5
                                    string_to_bool(option->eo_value));
Packit 4f15d5
            g_option_list = add_option_widget(g_option_list, option_input, option);
Packit 4f15d5
            break;
Packit 4f15d5
Packit 4f15d5
        default:
Packit 4f15d5
            //option_input = gtk_label_new_justify_left("WTF?");
Packit 4f15d5
            log_warning("unsupported option type");
Packit 4f15d5
            free(option_label);
Packit 4f15d5
            return;
Packit 4f15d5
    }
Packit 4f15d5
Packit 4f15d5
    if (option->eo_note_html)
Packit 4f15d5
    {
Packit 4f15d5
        label = gtk_label_new(option->eo_note_html);
Packit 4f15d5
        gtk_label_set_use_markup(GTK_LABEL(label), TRUE);
Packit 4f15d5
Packit 4f15d5
        gtk_widget_set_halign(label, GTK_ALIGN_START);
Packit 4f15d5
        gtk_widget_set_valign(label, GTK_ALIGN_START);
Packit 4f15d5
Packit 4f15d5
        make_label_autowrap_on_resize(GTK_LABEL(label));
Packit 4f15d5
Packit 4f15d5
        last_row = add_one_row_to_grid(option_table);
Packit 4f15d5
        gtk_grid_attach(option_table, label,
Packit 4f15d5
                             /*left,top:*/ 1, last_row,
Packit 4f15d5
                             /*top,heigh:*/ 1, 1);
Packit 4f15d5
    }
Packit 4f15d5
Packit 4f15d5
    free(option_label);
Packit 4f15d5
}
Packit 4f15d5
Packit 4f15d5
static GtkWidget *create_event_config_grid()
Packit 4f15d5
{
Packit 4f15d5
    GtkWidget *option_table = gtk_grid_new();
Packit 4f15d5
Packit 4f15d5
    gtk_widget_set_margin_start(option_table, 5);
Packit 4f15d5
    gtk_widget_set_margin_end(option_table, 5);
Packit 4f15d5
Packit 4f15d5
    gtk_widget_set_margin_top(option_table, 5);
Packit 4f15d5
    gtk_widget_set_margin_bottom(option_table, 5);
Packit 4f15d5
Packit 4f15d5
    gtk_grid_set_row_homogeneous(GTK_GRID(option_table), FALSE);
Packit 4f15d5
    gtk_grid_set_column_homogeneous(GTK_GRID(option_table), FALSE);
Packit 4f15d5
    gtk_grid_set_row_spacing(GTK_GRID(option_table), 10);
Packit 4f15d5
    g_object_set_data(G_OBJECT(option_table), "n-rows", (gpointer)-1);
Packit 4f15d5
Packit 4f15d5
    gtk_widget_set_hexpand(option_table, TRUE);
Packit 4f15d5
    gtk_widget_set_vexpand(option_table, TRUE);
Packit 4f15d5
    gtk_widget_set_halign(option_table, GTK_ALIGN_FILL);
Packit 4f15d5
    gtk_widget_set_valign(option_table, GTK_ALIGN_FILL);
Packit 4f15d5
Packit 4f15d5
    return option_table;
Packit 4f15d5
}
Packit 4f15d5
Packit 4f15d5
config_dialog_t *create_event_config_dialog_content(event_config_t *event, GtkWidget *content)
Packit 4f15d5
{
Packit 4f15d5
    INITIALIZE_LIBREPORT();
Packit 4f15d5
Packit 4f15d5
    if (content == NULL)
Packit 4f15d5
        content = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
Packit 4f15d5
Packit 4f15d5
    //event_config_t *event = get_event_config(event_name);
Packit 4f15d5
    GtkWidget *notebook_layout = gtk_notebook_new();
Packit 4f15d5
    gtk_box_pack_start(GTK_BOX(content), notebook_layout, TRUE, TRUE, 0);
Packit 4f15d5
Packit 4f15d5
    GtkWidget *option_table = create_event_config_grid();
Packit 4f15d5
Packit 4f15d5
    /* table to hold advanced options
Packit 4f15d5
     * hidden in expander which is visible only if there's at least
Packit 4f15d5
     * one advanced option
Packit 4f15d5
    */
Packit 4f15d5
    GtkWidget *adv_option_table = create_event_config_grid();
Packit 4f15d5
Packit 4f15d5
    g_object_set_data(G_OBJECT(option_table), "advanced-options", adv_option_table);
Packit 4f15d5
Packit 4f15d5
    has_password_option = false;
Packit 4f15d5
    /* it's already stored in config_dialog_t from the previous call
Packit 4f15d5
     * we need to set it to null so we create a new list for the actual
Packit 4f15d5
     * event_config
Packit 4f15d5
     * note: say *NO* to the global variables!
Packit 4f15d5
    */
Packit 4f15d5
    g_option_list = NULL;
Packit 4f15d5
    /* this fills the g_option_list, so we can use it for new_config_dialog */
Packit 4f15d5
    g_list_foreach(event->options, &add_option_to_table, option_table);
Packit 4f15d5
Packit 4f15d5
    /* if there is at least one password option, add checkbox to disable storing passwords */
Packit 4f15d5
    /* if the user storage is not available nothing is to be stored, so it is not necessary
Packit 4f15d5
     * to bother with an extra checkbox about storing passwords */
Packit 4f15d5
    if (is_event_config_user_storage_available()
Packit 4f15d5
            && has_password_option)
Packit 4f15d5
    {
Packit 4f15d5
        unsigned last_row = add_one_row_to_grid(GTK_GRID(option_table));
Packit 4f15d5
        GtkWidget *pass_store_cb = gtk_check_button_new_with_label(_("Don't store passwords"));
Packit 4f15d5
        gtk_grid_attach(GTK_GRID(option_table), pass_store_cb,
Packit 4f15d5
                /*left,top:*/ 0, last_row,
Packit 4f15d5
                /*width,height:*/ 1, 1);
Packit 4f15d5
        const char *store_passwords = get_user_setting("store_passwords");
Packit 4f15d5
        if (store_passwords && !strcmp(store_passwords, "no"))
Packit 4f15d5
            gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(pass_store_cb), 1);
Packit 4f15d5
        g_signal_connect(pass_store_cb, "toggled", G_CALLBACK(on_show_pass_store_cb), NULL);
Packit 4f15d5
    }
Packit 4f15d5
Packit 4f15d5
    GtkWidget *option_table_lbl = gtk_label_new_with_mnemonic(_("Basic"));
Packit 4f15d5
    GtkWidget *option_table_scrl = gtk_scrolled_window_new(NULL, NULL);
Packit 4f15d5
    gtk_container_add(GTK_CONTAINER(option_table_scrl), option_table);
Packit 4f15d5
    gtk_notebook_append_page(GTK_NOTEBOOK(notebook_layout), option_table_scrl, option_table_lbl);
Packit 4f15d5
Packit 4f15d5
    /* add the adv_option_table to the dialog only if there is some adv option */
Packit 4f15d5
    if (g_list_length(gtk_container_get_children(GTK_CONTAINER(adv_option_table))) > 0)
Packit 4f15d5
    {
Packit 4f15d5
        GtkWidget *adv_option_table_lbl = gtk_label_new_with_mnemonic(_("Advanced"));
Packit 4f15d5
        GtkWidget *adv_option_table_scrl = gtk_scrolled_window_new(NULL, NULL);
Packit 4f15d5
        gtk_container_add(GTK_CONTAINER(adv_option_table_scrl), adv_option_table);
Packit 4f15d5
        gtk_notebook_append_page(GTK_NOTEBOOK(notebook_layout), adv_option_table_scrl, adv_option_table_lbl);
Packit 4f15d5
    }
Packit 4f15d5
    else
Packit 4f15d5
        /* Do not show single tab 'Basic' */
Packit 4f15d5
        gtk_notebook_set_show_tabs(GTK_NOTEBOOK(notebook_layout), FALSE);
Packit 4f15d5
Packit 4f15d5
    /* add warning if secrets service is not available showing the nagging dialog
Packit 4f15d5
     * is considered "too heavy UI" be designers
Packit 4f15d5
     */
Packit 4f15d5
    if (!is_event_config_user_storage_available())
Packit 4f15d5
    {
Packit 4f15d5
        GtkWidget *keyring_warn_lbl =
Packit 4f15d5
        gtk_label_new(
Packit 4f15d5
          _("Secret Service is not available, your settings won't be saved!"));
Packit 4f15d5
        gtk_widget_set_name(keyring_warn_lbl, "keyring_warn_lbl");
Packit 4f15d5
Packit 4f15d5
        GtkCssProvider *g_provider = gtk_css_provider_new();
Packit 4f15d5
        gtk_style_context_add_provider_for_screen(gdk_screen_get_default(),
Packit 4f15d5
                                                  GTK_STYLE_PROVIDER(g_provider),
Packit 4f15d5
                                                  GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
Packit 4f15d5
        const gchar *data = "#keyring_warn_lbl {color: rgba(100%, 0%, 0%, 1);}";
Packit 4f15d5
        gtk_css_provider_load_from_data(g_provider, data, -1, NULL);
Packit 4f15d5
        g_object_unref (g_provider);
Packit 4f15d5
Packit 4f15d5
        gtk_box_pack_start(GTK_BOX(content), keyring_warn_lbl, false, false, 0);
Packit 4f15d5
    }
Packit 4f15d5
Packit 4f15d5
    gtk_widget_show_all(content); //make it all visible
Packit 4f15d5
Packit 4f15d5
    //g_option_list is filled on
Packit 4f15d5
    config_dialog_t *cdialog = new_config_dialog(NULL,
Packit 4f15d5
                                    g_option_list,
Packit 4f15d5
                                    (config_save_fun_t)save_data_from_event_dialog_name
Packit 4f15d5
                                    );
Packit 4f15d5
Packit 4f15d5
    return cdialog;
Packit 4f15d5
}
Packit 4f15d5
Packit 4f15d5
config_dialog_t *create_event_config_dialog(const char *event_name, GtkWindow *parent)
Packit 4f15d5
{
Packit 4f15d5
    INITIALIZE_LIBREPORT();
Packit 4f15d5
Packit 4f15d5
    event_config_t *event = get_event_config(event_name);
Packit 4f15d5
Packit 4f15d5
    if(!ec_is_configurable(event))
Packit 4f15d5
        return NULL;
Packit 4f15d5
Packit 4f15d5
    GtkWindow *parent_window = parent ? parent : g_event_list_window;
Packit 4f15d5
Packit 4f15d5
    char *window_title = xasprintf("%s - Reporting Configuration",
Packit 4f15d5
            ec_get_screen_name(event) ? ec_get_screen_name(event) : event_name);
Packit 4f15d5
Packit 4f15d5
    GtkWidget *dialog = gtk_dialog_new_with_buttons(
Packit 4f15d5
                        window_title,
Packit 4f15d5
                        parent_window,
Packit 4f15d5
                        GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
Packit 4f15d5
                        _("_Cancel"),
Packit 4f15d5
                        GTK_RESPONSE_CANCEL,
Packit 4f15d5
                        _("_OK"),
Packit 4f15d5
                        GTK_RESPONSE_APPLY,
Packit 4f15d5
                        NULL);
Packit 4f15d5
Packit 4f15d5
    free(window_title);
Packit 4f15d5
Packit 4f15d5
    gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_APPLY);
Packit 4f15d5
Packit 4f15d5
    /* Allow resize?
Packit 4f15d5
     * W/o resize, e.g. upload configuration hint looks awfully
Packit 4f15d5
     * line wrapped.
Packit 4f15d5
     */
Packit 4f15d5
    gtk_window_set_resizable(GTK_WINDOW(dialog), true);
Packit 4f15d5
    gtk_window_set_default_size(GTK_WINDOW(dialog), 450, 310);
Packit 4f15d5
Packit 4f15d5
    if (parent_window != NULL)
Packit 4f15d5
    {
Packit 4f15d5
        gtk_window_set_icon_name(GTK_WINDOW(dialog),
Packit 4f15d5
                                 gtk_window_get_icon_name(parent_window));
Packit 4f15d5
    }
Packit 4f15d5
Packit 4f15d5
    GtkWidget *content = gtk_dialog_get_content_area(GTK_DIALOG(dialog));
Packit 4f15d5
    config_dialog_t *cdialog = create_event_config_dialog_content(event, content);
Packit 4f15d5
    cdialog_set_widget(cdialog, dialog);
Packit 4f15d5
Packit 4f15d5
    return cdialog;
Packit 4f15d5
}
Packit 4f15d5
Packit 4f15d5
static void add_event_to_liststore(gpointer key, gpointer value, gpointer list_store)
Packit 4f15d5
{
Packit 4f15d5
    config_item_info_t *info = ec_get_config_info((event_config_t *)value);
Packit 4f15d5
    config_dialog_t *cdialog = create_event_config_dialog(key, NULL);
Packit 4f15d5
Packit 4f15d5
    add_item_to_config_liststore(cdialog, info, list_store);
Packit 4f15d5
}
Packit 4f15d5
Packit 4f15d5
GtkListStore *add_events_to_liststore(GHashTable *events)
Packit 4f15d5
{
Packit 4f15d5
    GtkListStore *list_store = new_conf_liststore();
Packit 4f15d5
    g_hash_table_foreach(events, (GHFunc)add_event_to_liststore, list_store);
Packit 4f15d5
Packit 4f15d5
    return list_store;
Packit 4f15d5
}
Packit 4f15d5
Packit 4f15d5
int show_event_config_dialog(const char *event_name, GtkWindow *parent)
Packit 4f15d5
{
Packit 4f15d5
    INITIALIZE_LIBREPORT();
Packit 4f15d5
Packit 4f15d5
    config_dialog_t *dialog = create_event_config_dialog(event_name, parent);
Packit 4f15d5
    const int result = cdialog_run(dialog, event_name);
Packit 4f15d5
    free(dialog);
Packit 4f15d5
Packit 4f15d5
    return result;
Packit 4f15d5
}
Packit 4f15d5