GTK3 GtkCssProvider not working - gtk3

Configuration is Ubunutu Server 18.04 LTS / Xorg / openbox / GTK3
I have been struggling to figure out why I can't get GtkCssProvider to work on even the most basic item. If have been working with different examples but here is one similar to another post.
Here is the app code that will display the label.
#include <gtk/gtk.h>
int main(int argc, char *argv[])
{
gtk_init(&argc, &argv);
GtkWidget * window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
GtkWidget * label = gtk_label_new("Label 0123456789");
GtkCssProvider * cssProvider = gtk_css_provider_new();
g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL);
if( gtk_css_provider_load_from_path(cssProvider, "csstest.css", NULL) )
{
gtk_style_context_add_provider(gtk_widget_get_style_context(label),
GTK_STYLE_PROVIDER(cssProvider),
GTK_STYLE_PROVIDER_PRIORITY_USER);
gtk_container_add(GTK_CONTAINER(window), label);
gtk_widget_show_all(window);
gtk_main();
}
return 0;
}
The .CSS file is simple:
GtkLabel {
color: green;
}
The one post indicated that the gtk_style_context_add_provider() should be replaced with the gtk_style_context_add_provider_for_screen() call. Neither seems to have any effect. The label is appearing in the default style black on gray. So what is the trick to getting the Css style to be applied to the widget.
My requirement is to have different styles I can set to different widgets. I assume I can create some type of class construct in the Css that will allow me to apply different themes to the same widget via the gtk_style_context_add_provider() call. However I have not been able to figure that out either. I see how I can set a style in the Css for a specific named widget (via ID) but this appears to be only a predefined statc definition. Any suggestions on this would be helpful.

The CSS selector for a label is label, not GtkLabel:
label {
color: green;
}
See the GtkLabel API reference which lists the valid selectors.
You should also use the GTK Inspector to test CSS fragments.
You may also want to read the API reference for CSS handling in GTK, as well as the GtkStyleContext documentation.

Thanks ebassi for the clarification on the change to css. I shouldn't have started with an older example. Here was the completed example working in GTK 3.22 I ended up with to demonstrate the dynamic change in appearance using CSS styles:
#include <gtk/gtk.h>
GtkWidget * label1;
GtkWidget * label2;
GtkWidget * label3;
// Handler to change the appearance of the widgets from their original
void button_clicked (GtkButton * button, gpointer user_data)
{
// names are defined in the .CSS
gtk_widget_set_name( GTK_WIDGET(label1) , "" );
gtk_widget_set_name( GTK_WIDGET(label2) , "white-widget" );
gtk_widget_set_name( GTK_WIDGET(label3) , "red-widget" );
}
// Set the style provider for the widgets
static void apply_css_provider (GtkWidget * widget, GtkCssProvider * cssstyleProvider)
{
gtk_style_context_add_provider ( gtk_widget_get_style_context(widget), GTK_STYLE_PROVIDER(cssstyleProvider) , GTK_STYLE_PROVIDER_PRIORITY_USER );
// For container widgets, apply to every child widget on the container
if (GTK_IS_CONTAINER (widget))
{
gtk_container_forall( GTK_CONTAINER (widget), (GtkCallback)apply_css_provider , cssstyleProvider);
}
}
int main(int argc, char *argv[])
{
gtk_init(&argc, &argv);
GtkWidget * window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
GtkCssProvider * cssProvider = gtk_css_provider_new();
GtkWidget * fixed = gtk_fixed_new();
GtkWidget * button = gtk_button_new_with_label ("Change");
//create the labels for this test
label1 = gtk_label_new("Label 0001");
label2 = gtk_label_new("Label 23456789");
label3 = gtk_label_new("Label 3");
//setup container and add widgets
gtk_container_add (GTK_CONTAINER (window), fixed);
gtk_fixed_put( GTK_FIXED(fixed), label1 , 30 , 30 );
gtk_fixed_put( GTK_FIXED(fixed), label2 , 30 , 50 );
gtk_fixed_put( GTK_FIXED(fixed), label3 , 30 , 70 );
gtk_fixed_put( GTK_FIXED(fixed), button , 30 , 110 );
//register the handlers
g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL);
g_signal_connect(button, "clicked", G_CALLBACK(button_clicked), NULL );
if( gtk_css_provider_load_from_path(cssProvider, "csstest.css", NULL) )
{
apply_css_provider( window , cssProvider );
// set a default style - name is defined in .CSS file
gtk_widget_set_name( GTK_WIDGET(label1) , "red-widget" );
gtk_widget_show_all(window);
gtk_main();
}
return 0;
}
csstest.css:
/* default coloring of widgets */
* {
background-color: #00ee00;
}
#red-widget {
color: white;
background-color: red;
}
#white-widget {
color: red;
background-color: white;
}
button {
border-bottom-left-radius: 0;
border-bottom-right-radius: 0;
border-top-left-radius: 0;
border-top-right-radius: 0;
background-image: none;
}

Related

Customize leaflet routing error (options)

I am using Leaflet-routing-machine,
I added the error control to my map like this :
L.Routing.errorControl(this.control).addTo(map);
for style I used this :
.leaflet-routing-error {
width: 320px;
background-color: rgb(238, 153, 164);
padding-top: 4px;
transition: all 0.2s ease;
box-sizing: border-box;
}
this is what I got :
Ididn't find a lot of explanations about. Have anyone know how to customise this more, change language, hide/show... ?
After reading this source code
you can redefine the header and the fromat message function
L.Routing.errorControl(control, {
header: 'Routing error',
formatMessage(error) {
if (error.status < 0) {
return 'Calculating the route caused an error. Technical description follows: <code><pre>' +
error.message + '</pre></code';
} else {
return 'The route could not be calculated. ' +
error.message;
}
}
}).addTo(map);
I believe that in your control you can redefine this two options
also you may be able to use the leaflet element with classes leaflet-bar leaflet-routing-error and inject more html code on it as they do to create the alert
var L = require('leaflet');
onAdd: function() {
var header,
message;
this._element = L.DomUtil.create('div', 'leaflet-bar leaflet-routing-error');
this._element.style.visibility = 'hidden';
header = L.DomUtil.create('h3', null, this._element);
message = L.DomUtil.create('span', null, this._element);
header.innerHTML = this.options.header;
return this._element;
}
so retrieving the div of class or id leaflet-routing-error and injecting on it your desired html component template should be fine

setting gtk textview selection color with css

I have the following code that works fine to set background and foreground colors for a GtkTextview:
static void
setColor(GtkWidget * widget) {
auto style_context = gtk_widget_get_style_context (widget);
gtk_style_context_add_class(style_context, GTK_STYLE_CLASS_VIEW );
auto css_provider = gtk_css_provider_new();
GError *error=NULL;
auto data = g_strdup_printf("\
* {\
background-color: black;\
color: white;\
}\
*:selected {\
background-color: blue;\
color: yellow;\
}\
");
gtk_css_provider_load_from_data (css_provider, data, -1, &error);
g_free(data);
if (error){
ERROR("gtk_css_provider_load_from_data: %s\n", error->message);
g_error_free(error);
return;
}
gtk_style_context_add_provider (style_context,
GTK_STYLE_PROVIDER(css_provider),
GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
}
The result is that both normal and selected text color have black background and white foreground.
Why doesn't the selected text appear in yellow/blue?
Any pointer to an example file would be much appreciated.
Figured it out. The lack of any tutorials or example led me search the gtk source code for answers. A very complete css file is in the Adwaita theme (gtk-contained.css). From looking through that and a bit of experimenting, the following code will set the foreground and background colors for normal and selected text as specified.
auto data = g_strdup_printf("\
textview text {\
background-color: black;\
color: white;\
}\
.view text selection {\
background-color: blue;\
color: yellow;\
}\
");
The main problem was using the "*". In that same file there is a comment which reads "Wildcards ar bad and troublesome, use them with car, or better, just don't. Everytime a wildcard is used a kitten dies, painfully."

How to create the GtkListview by Glade3?

I'm using glade3 to develop a simple app on windows. The official reference manual seems out of date, so I use the gtk-function to create the Listview and put the MySQL-Query result under the field rows. Need help about create the listview by glade3 not by the codes.
Thanks anymore!
My code:
#include <gtk/gtk.h>
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <string.h>
#include "mysql.h"
#define HOST "localhost"
#define USERNAME "root"
#define PASSWORD ""
#define DATABASE "student"
enum ListCols
{
LIST_NUM,
LIST_NAME,
LIST_CHECKED,
LIST_CNT
};
int main (int argc, char *argv[])
{
GtkWidget* win;
GtkWidget* vbox ;
GtkWidget* statusbar ;
GtkTreeView* tree;
GtkTreeView* list;
GtkTreeStore* tree_store;
GtkListStore* list_store;
GtkTreeIter iter;
GtkTreeIter iter_child;
GtkCellRenderer* renderer;
GtkTreeViewColumn* column;
GtkTreeSelection* select;
MYSQL my_connection;
MYSQL_RES *res_ptr;
MYSQL_FIELD *field;
MYSQL_ROW result_row;
int res;
int row, col;
int i, j;
char * sql = "select * from person;";
gtk_init (&argc, &argv);
win = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_title (GTK_WINDOW (win), "QueryData");
gtk_window_set_position (GTK_WINDOW (win), GTK_WIN_POS_CENTER);
gtk_widget_set_size_request(win, 480, 480);
vbox = gtk_vbox_new (FALSE, 2);
gtk_container_add (GTK_CONTAINER (win), vbox);
list = gtk_tree_view_new();
list_store = gtk_list_store_new(LIST_CNT,
G_TYPE_STRING,
G_TYPE_STRING,
G_TYPE_BOOLEAN);
mysql_init(&my_connection);
if (mysql_real_connect(&my_connection, HOST, USERNAME, PASSWORD,DATABASE, 0, NULL, CLIENT_FOUND_ROWS))
{
printf("Query data successfully!\n");
mysql_query(&my_connection, "set names utf8");
res = mysql_query(&my_connection, sql);
if (res)
{
printf("Error: mysql_query !\n");
mysql_close(&my_connection);
}
else
{
res_ptr = mysql_store_result(&my_connection);
if (res_ptr)
{
col = mysql_num_fields(res_ptr);
row = mysql_num_rows(res_ptr) + 1;
printf("%d lines queried\n", row);
for (i = 0; field = mysql_fetch_field(res_ptr); i++)
printf("%s ", field->name);
printf("\n");
for (i = 1; i < row; i++)
{
result_row = mysql_fetch_row(res_ptr);
gtk_list_store_append(list_store, &iter);
gtk_list_store_set(list_store, &iter,
LIST_NUM, result_row[0],
LIST_NAME, result_row[2],
LIST_CHECKED, FALSE, -1);
}
}
mysql_close(&my_connection);
}
}
else
printf("Fail to query data!\n");
for (int k = 0; k < 3; k++)
gtk_tree_view_set_model(list, list_store);
g_object_unref(list_store);
renderer = gtk_cell_renderer_text_new();
column = gtk_tree_view_column_new_with_attributes("Name", renderer,
"text", LIST_NUM, NULL);
column = gtk_tree_view_append_column(list, column);
renderer = gtk_cell_renderer_text_new();
column = gtk_tree_view_column_new_with_attributes("Age", renderer,
"text", LIST_NAME, NULL);
column = gtk_tree_view_append_column(list, column);
renderer = gtk_cell_renderer_toggle_new();
column = gtk_tree_view_column_new_with_attributes("PersonInfo", renderer,
"active", LIST_CHECKED, NULL);
column = gtk_tree_view_append_column(list, column);
gtk_box_pack_start(vbox, list, TRUE, TRUE, 1);
g_signal_connect (win, "destroy", gtk_main_quit, NULL);
gtk_widget_show_all (win);
gtk_main ();
return 0;
}
First of all you have to create a container to hold the treeview. If your using a grid, you can use a ScrolledWindow for example. In this example I just put it directly in the window container. Drag the TreeView on the window container:
Then a dialog asks you for the corresponding treestore:
Press on the pen and paper icon to open another dialog. Then press on "new".
This will get you back to the first dialog, with the newly created TreeStore already filled into the field. You can just press "Create":
Then you can start creating columns for the TreeStore. I created on for the Name (gchararray) and one for the Age (gint):
After that you can add data to the TreeStore:
Finally you still have to add columns to the TreeView. That is done by clicking on the TreeView --> click edit --> go to Hierarchy tab --> Add as many columns as you need.
Don't forget to also load the liststore from the Glade file, otherwise your data will not be present, when you run the program from the code.
Let's say you already have a container and you want to add a tree view into it.
To do that, you look at the "Control and Display" category of widgets, and locate "tree view". If you can't find it, or can't identify the icon, try hovering each icon until you find it.
Click on the icon, then click on the container that you wish to add it to. This will immediately cause a dialog box to occur, asking you to link it with a tree model. You can click the pencil icon, then click "New" to create a list store.
Alternatively, you can create a list store or tree store first. In the widget selection side panel, look under "Miscellaneous". (Between "Composite Widgets" and "Deprecated".) Locate list store or tree store, and click on it to create it. Now if you create the tree view (using the method above), you can choose this tree store / list store as your model.

How to create a Gtk combobox with the interface new_with_area?

According to the gtk documentation you can create a combobox with:
GtkWidget * gtk_combo_box_new ()
GtkWidget * gtk_combo_box_new_with_entry ()
GtkWidget * gtk_combo_box_new_with_model ()
GtkWidget * gtk_combo_box_new_with_model_and_entry ()
GtkWidget * gtk_combo_box_new_with_area ()
GtkWidget * gtk_combo_box_new_with_area_and_entry ()
I have found a lot of examples for the gtk_combo_box_new_with_model but I can't find anything related to the use of gtk_combo_box_new_with_area .
The langage used doesn't matter.
something like (pygobject):
from gi.repository import Gtk
area = Gtk.CellAreaBox()
combo = Gtk.ComboBox.new_with_area(area=area)
cell = Gtk.CellRendererText()
area.pack_start(cell, True, True, True)
you can add more CellRenderers to the box (which is a Gtk.Box) and do whatever you need to do with those.

Can't set CSS to specified widget in GTK+

I'm using Vala with GTK+ and now I'm trying to add custom CSS to specified widget.
I can add fe. backgroudn to GtkWidget but not for #sidebar
#sidebar { //It doesn't work
color: white;
}
GtkWindow { // It works
background-color: red;
}
I'm adding class to widget like that:
sidebar = new Gtk.Label("Hello");
sidebar.set_name("sidebar");
And it's changes color to GtkWindow, but not for this label.
Any ideas?
I haven't programmed in Vala, but you should add class to StyleContext.
This is in C
sidebar = gtk_label_new ("Hello');
gtk_style_context_add_class ( gtk_widget_get_style_context ("mysidebar"), sidebar);
Also, style "sidebar", is already defined in GtkStyle. You should change the "sidebar" in CSS into something else (sidebar is used by views, toolbar etc)
But if you persist, the syntax should be:
.mysidebar {
#anything
}