Jase
Jase

Reputation: 33

GtkProgressBar with CSS for progress colour not functioning

I am not able to change the colour of the progress element in the GtkProgressBar using CSS. I have tried different combinations to reference this progress bar such as the below but to no avail. I have attached a minimum example C program, Glade file and CSS file where CSS attempt 4 is currently active to demonstrate that all elements are affected except this progress bar.

/* attempt 1 */
#gtkprogressbar1 {
    color: rgba(83,165,198,255);
    background-color: rgba(83,165,198,255);
}
/* attempt 2 */
#progressbar * {
    color: rgba(83,165,198,255);
    background-color: rgba(83,165,198,255);
}
/* attempt 3 */
GtkProgressBar * {
    color: rgba(83,165,198,255);
    background-color: rgba(83,165,198,255);
}
/* attempt 4 */
* {
    color: rgba(83,165,198,255);
    background-color: rgba(83,165,198,255);
}

C Program: Save as progressbar.c

/* Compile as follows: 
* gcc -o PROGRESS progressbar.c -g `pkg-config --cflags --libs gtk+-3.0 gmodule-2.0` -pthread `pkg-config --cflags --libs gtk+-3.0 gmodule-2.0` -export-dynamic
*/
#include <gio/gio.h>
#include <gtk/gtk.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

typedef struct {
    GtkWidget *button_on;
    GtkWidget *progressbar1;
    time_t time_start;
    time_t time_finish;
} app_gui;

void set_progress_bar (app_gui *gui);

void adding_timer (app_gui *gui);

void set_css (void);

int main (int argc, char *argv[]) {

    GtkBuilder *builder = g_slice_new (GtkBuilder);
    GtkWidget *window;
    GError *gtk_error = NULL;

    app_gui *gui = g_slice_new (app_gui);

    gui->time_start = time (NULL);
    gui->time_finish = gui->time_start + 60; // 60 seconds progress bar
    printf("%s%lu\n", "button click: Time start at button click is ", gui->time_start);
    printf("%s%lu\n", "button click: Time finish at button click is ", gui->time_finish);

    gtk_init (&argc, &argv);

    set_css ();

    builder = gtk_builder_new ();
    if (!gtk_builder_add_from_file (builder, "progressbar_main.glade", NULL)) {
        fprintf (stdout, "%s%s\n", "Error loading file with the reason: ", gtk_error->message);
        g_free (gtk_error);
        exit (EXIT_FAILURE);
    }

    window = GTK_WIDGET (gtk_builder_get_object (builder, "window_main"));
    gui->button_on = GTK_WIDGET (gtk_builder_get_object (builder, "button_on"));
    gui->progressbar1 = GTK_WIDGET (gtk_builder_get_object (builder, "progressbar1"));

    gtk_builder_connect_signals (builder, gui);

    g_object_unref (builder);

    g_timeout_add_seconds_full (G_PRIORITY_DEFAULT_IDLE, 1, (GSourceFunc)set_progress_bar, 
        gui, (GDestroyNotify)adding_timer);

    gtk_widget_show (window);
    gtk_main ();

    g_slice_free (app_gui, gui);
    return 0;

}

void set_css (void) {

    GtkCssProvider *css_provider;
    GdkDisplay *display;
    GdkScreen *screen;
    const char *css_file = "style.css";
    GError *error = NULL;

    css_provider = gtk_css_provider_new ();
    display = gdk_display_get_default ();
    screen = gdk_display_get_default_screen (display);
    gtk_style_context_add_provider_for_screen (screen, GTK_STYLE_PROVIDER (css_provider), 
        GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);


    gtk_css_provider_load_from_file(css_provider, g_file_new_for_path (css_file), &error);
    g_object_unref (css_provider);  
}

void adding_timer (app_gui *gui) {

    g_timeout_add_seconds_full (G_PRIORITY_DEFAULT_IDLE, 1, (GSourceFunc)set_progress_bar, 
    gui, (GDestroyNotify)adding_timer);

}

void set_progress_bar (app_gui *gui) {

    time_t time_now = time (NULL);

    double progress = 1.00 - (((gui->time_finish * 1.0) - time_now)/60.0);

    printf("%s%f\n", "set progress: Progress is ", progress);
    if (progress >= 1.00) {
        EXIT_SUCCESS;
    }
    gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (gui->progressbar1), progress); 

}

void on_window_main_destroy () {

    gtk_main_quit ();
}

Glade File: Save as progressbar_main.glade

<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.18.3 -->
<interface>
  <requires lib="gtk+" version="3.12"/>
  <object class="GtkWindow" id="window_main">
    <property name="can_focus">False</property>
    <signal name="destroy" handler="on_window_main_destroy" swapped="no"/>
    <child>
      <object class="GtkFixed" id="fixed1">
        <property name="visible">True</property>
        <property name="can_focus">False</property>
        <child>
          <object class="GtkButton" id="button_on">
            <property name="label" translatable="yes">ON</property>
            <property name="width_request">100</property>
            <property name="height_request">80</property>
            <property name="visible">True</property>
            <property name="can_focus">True</property>
            <property name="receives_default">True</property>
          </object>
          <packing>
            <property name="x">48</property>
            <property name="y">75</property>
          </packing>
        </child>
        <child>
          <object class="GtkViewport" id="viewport1">
            <property name="width_request">200</property>
            <property name="height_request">80</property>
            <property name="visible">True</property>
            <property name="can_focus">False</property>
            <child>
              <object class="GtkTextView" id="textview1">
                <property name="visible">True</property>
                <property name="can_focus">True</property>
              </object>
            </child>
          </object>
          <packing>
            <property name="x">201</property>
            <property name="y">75</property>
          </packing>
        </child>
        <child>
          <object class="GtkProgressBar" id="progressbar1">
            <property name="width_request">200</property>
            <property name="height_request">-1</property>
            <property name="visible">True</property>
            <property name="can_focus">False</property>
          </object>
          <packing>
            <property name="x">53</property>
            <property name="y">31</property>
          </packing>
        </child>
      </object>
    </child>
  </object>
</interface>

CSS File: Save as style.css

* {
    color: rgba(83,165,198,255);
    background-color: rgba(83,165,198,255);
}

Thank you for any assistance offered.

Upvotes: 1

Views: 2106

Answers (1)

underscore_d
underscore_d

Reputation: 6792

All of your attempts to select the ProgressBar widget are wrong:

  • In your UI file, progressbar1 is the id, not the name, and it's Glade's name that gets used as the CSS ID. Confusing, right? Anyway, it's not gtkprogressbar1, so that wouldn't work regardless.
  • An ID like #widgetclass, e.g. #progressbar, is never used by GTK+ as the CSS ID is per-element, not per-class, and only one widget per process should have the same CSS name, but all GtkProgressBars would in this hypothetical.
  • GtkProgressBar style names are the old style, pre 3.18ish, and I presume you're not using so old a version (but you can try substituting it if you are).

The CSS node name, as of now, is progressbar, not GtkProgressBar. The same pattern applies to other widgets: all nodes named GtkWhatever are now named whatever generally, with a few minor exceptions (e.g. GtkListBox is list).

So that's one problem. Your second is that your attempts to change the colour are not using specific enough selectors and therefore are being overridden by whatever theme you're using applying more specific selectors than * - which is to say: all of them.

Even if your colour would take effect this way, it would have to apply to the whole widget, which is obviously wrong.

Read the documentation to learn the proper CSS node names and hierarchies, and select on something more specific, e.g.:

progressbar > trough > progress

is the most specific variant.

That said, if you prefer brevity, I just ran gtk3-widget-factory and found this to be sufficient to style the progress fill node:

progressbar progress {
    background-color: rgba(83, 165, 198, 255);
}

So, yes: just selecting on progressbar alone produces wrong results because you're not being specific enough. That's why we need separate CSS nodes and why the node hierarchy is documented!

Upvotes: 1

Related Questions