I've been playing around with Xfce 4.12, which uses GTK2, and I would like to make taskbar buttons to have semi-transparent text when their respective windows are minimized. Here's the original code:
xfce_tasklist_button_name_changed (WnckWindow *window, XfceTasklistChild *child)
{
const gchar *name;
gchar *label = NULL;
panel_return_if_fail (window == NULL || child->window == window);
panel_return_if_fail (WNCK_IS_WINDOW (child->window));
panel_return_if_fail (XFCE_IS_TASKLIST (child->tasklist));
name = wnck_window_get_name (child->window);
gtk_widget_set_tooltip_text (GTK_WIDGET (child->button), name);
if (!child->tasklist->only_minimized && wnck_window_is_minimized (child->window))
name = label = g_strdup_printf ("[%s]", name);
else if (wnck_window_is_shaded (child->window))
name = label = g_strdup_printf ("=%s=", name);
gtk_label_set_text (GTK_LABEL (child->label), name);
g_free (label);
if (window != NULL)
xfce_tasklist_sort (child->tasklist);
}
I tried countless things, but I failed to find a way to apply alpha to the text in the widget.
Interesting to notice that the icons next to the text have alpha using pixbuf, which I guess doesn't work for text in widgets:
XfceTasklist *tasklist = child->tasklist;
GdkPixbuf *pixbuf = wnck_window_get_icon (window);
GdkPixbuf *lucent = lucent = exo_gdk_pixbuf_lucent (pixbuf, tasklist->minimized_icon_lucency);
if (G_UNLIKELY (lucent != NULL))
pixbuf = lucent;
xfce_panel_image_set_from_pixbuf (XFCE_PANEL_IMAGE (child->icon), pixbuf);
Background
This is part of an exercise, in which I am creating a small network packet analyzer "as Wireshark".
Aim
I'm trying to store the Data of packets in a gtk_tree_store which can be revealed:
Code
structures used:
packet's data is stored in a trame.
typedef struct trame_{
unsigned int *tab;
int id;
int nb_ligne_erreur;
int nb_octet_erreur;
//couche ethernet
char *mac_dest;
char *mac_source;
char *ip_type;
//couche ip
char *version;
char *header_length;
int *total_length;
int *identification;
int *flags_frag_offset;
int TTL;
int protocol;
int *header_checksum;
int *ip_source;
int *ip_dest;
//couche tcp
int source_port;
int destination_port;
int stream_index;
int tcp_seg_len;
char* sequence_number;
int sequence_number_raw;
char *next_sequence_number;
char *acknowledgment_number;
int acknowledgment_number_raw;
char *tcp_header_length;
}trame;
chained list of trames with buttons (upper window, arbre (revealers on the lower window)
typedef struct cell_{
trame *obj;
GtkWidget *arbre;
GtkWidget *bouton;
struct cell_ *suiv;
int status_bouton_ip;
}cell;
this function create a new gtk_store_tree with all the data collected in a packet
void remplir_arbre(GtkWidget *pWidget, gpointer pData){
cell *tmp_cell=(cell *)pData;
GtkTreeStore *arbre=gtk_tree_store_new(2, G_TYPE_STRING, G_TYPE_STRING);
GtkTreeIter header_ethernet;
GtkTreeIter contenu_ethernet;
GtkTreeIter header_IP;
GtkTreeIter contenu_IP;
gtk_tree_store_insert (arbre,&header_ethernet,NULL,-1);
gtk_tree_store_set(arbre, &header_ethernet,0,"Ethernet II",1,NULL, -1);
gtk_tree_store_insert (arbre,&contenu_ethernet,&header_ethernet,-1);
gtk_tree_store_set(arbre,&contenu_ethernet, 0, "Source:",1,tmp_cell->obj->mac_source, -1);
gtk_tree_store_insert (arbre,&contenu_ethernet,&header_ethernet,-1);
gtk_tree_store_set(arbre,&contenu_ethernet, 0, "Destination:",1,tmp_cell->obj->mac_dest, -1);
gtk_tree_store_insert (arbre,&contenu_ethernet,&header_ethernet,-1);
gtk_tree_store_set(arbre,&contenu_ethernet, 0, "type:",1,tmp_cell->obj->ip_type, -1);
gtk_tree_store_insert(arbre,&header_IP,NULL,-1);
gtk_tree_store_set(arbre,&header_IP,0,"Internet Protocol",1,"", -1);
gtk_tree_store_insert(arbre,&contenu_IP,&header_IP,-1);
gtk_tree_store_set(arbre,&contenu_IP,0,"IP Version:",1,tmp_cell->obj->version, -1);
gtk_tree_store_insert(arbre,&contenu_IP,&header_IP,-1);
gtk_tree_store_set(arbre,&contenu_IP,0,"IP Version:",1,tmp_cell->obj->version, -1);
gtk_tree_store_insert(arbre,&contenu_IP,&header_IP,-1);
gtk_tree_store_set(arbre,&contenu_IP,0,"IP Version:",1,tmp_cell->obj->version, -1);
tmp_cell->arbre = gtk_tree_view_new_with_model(GTK_TREE_MODEL(arbre));
GtkCellRenderer *renderer_col1;
GtkCellRenderer *renderer_col2;
GtkTreeViewColumn *column;
GtkTreeViewColumn *column_2;
char label[20];
sprintf(label,"trame n°%d",tmp_cell->obj->id);
renderer_col1 = gtk_cell_renderer_text_new();
renderer_col2 = gtk_cell_renderer_text_new();
column = gtk_tree_view_column_new_with_attributes(label, renderer_col1, "text", 0, NULL);
column_2 = gtk_tree_view_column_new_with_attributes(NULL, renderer_col2, "text",1, NULL);
gtk_tree_view_append_column(GTK_TREE_VIEW(tmp_cell->arbre), column);
gtk_tree_view_append_column(GTK_TREE_VIEW(tmp_cell->arbre), column_2);
return;
}
this Function call remplir_arbre() and create and new revealer which is going to be stacked in the lower window
void ajout_liste(cell **liste,trame *elem,GtkWidget* box_haut, GtkWidget* box_bas){
char label[80];
sprintf(label,"%d\t%d:%d:%d:%d\t%d:%d:%d:%d",elem->id,(elem->ip_source)[0],(elem->ip_source)[1],(elem->ip_source)[2],(elem->ip_source)[3],(elem->ip_dest)[0],(elem->ip_dest)[1],(elem->ip_dest)[2],(elem->ip_dest)[3]);
GtkWidget* tmp_bouton=gtk_toggle_button_new_with_label(label);
if (elem->nb_ligne_erreur==-1){
gtk_widget_set_name(tmp_bouton,"button_dark_mode");
}else {
gtk_widget_set_name(tmp_bouton,"button_dark_mode_erreur");
}
cell *new_cell=(cell *) malloc(sizeof(cell));
GtkWidget *revealer = gtk_revealer_new();
new_cell->obj=elem;
new_cell->arbre=NULL;
new_cell->bouton=tmp_bouton;
new_cell->suiv=(*liste);
new_cell->status_bouton_ip=0;
*liste=new_cell;
remplir_arbre(NULL, new_cell);
gtk_widget_set_name(new_cell->arbre,"tree_dark_mode");
gtk_container_add(GTK_CONTAINER(revealer), new_cell->arbre);
gtk_revealer_set_reveal_child(GTK_REVEALER(revealer), FALSE);
gtk_box_pack_start(GTK_BOX(box_haut),tmp_bouton, FALSE,TRUE, 0);
gtk_box_pack_start(GTK_BOX(box_bas),revealer, FALSE, FALSE, 0); #box_bas is a gtk_box were all revealers are stacked ( the lower box on the screen)
gtk_widget_show (tmp_bouton);
gtk_widget_show_all(box_bas);
g_signal_connect(G_OBJECT(tmp_bouton), "clicked", G_CALLBACK(action_bouton_ip),new_cell);
g_object_bind_property(tmp_bouton, "active", revealer, "reveal-child", 1);
}
problem
Revealers don't show all of the rows of their child until all of the revealers are not activated:
all revealers activated
activated revealers hide non-activated other ones:
a revealer hiding another one
-all revealers non-activated
I was wondering if it was because i was using a gtk_box to stack revealers but it does not seems to be it.
Edit
I removed the revealer to see if i could at first , try to see all of the tree's childs and then find a solution to hide them.
i noticed some things :
i can always see all the childs of the second child of the tree ( Internet Protocol)
sometimes i can see all of the first child (Ethernet II ) rows without activating the second child ( Internet Protocol )
Solved
Finally i found another structure provided by GTK which fits to my needs.
Instead of using gtk_trees , i'm using some gtk_expanders combined with gtk_box to stack widgets into.
https://developer.gnome.org/gtk3/stable/GtkExpander.html
here is how it looks:
void remplir_ethernet(GtkWidget *box_ethernet,cell *tmp_cell){
char label[80];
GtkWidget *tmp_label=NULL;
sprintf(label,"\tSource\t\t: %s\n",(tmp_cell->obj->mac_source));
tmp_label=gtk_label_new(label);
gtk_label_set_xalign (GTK_LABEL(tmp_label),0);
gtk_box_pack_start(GTK_BOX(box_ethernet),tmp_label, FALSE, FALSE, 0);
sprintf(label,"\tDestination\t: %s\n",(tmp_cell->obj->mac_dest));
tmp_label=gtk_label_new(label);
gtk_label_set_xalign (GTK_LABEL(tmp_label),0);
gtk_box_pack_start(GTK_BOX(box_ethernet),tmp_label, FALSE, FALSE, 0);
sprintf(label,"\ttype\t\t: %s\n",(tmp_cell->obj->ip_type));
tmp_label=gtk_label_new(label);
gtk_label_set_xalign (GTK_LABEL(tmp_label),0);
gtk_box_pack_start(GTK_BOX(box_ethernet),tmp_label, FALSE, FALSE, 0);
}
void remplir_ip(GtkWidget *box_ip,cell *tmp_cell){
char label[80];
GtkWidget *tmp_label=NULL;
sprintf(label,"\tVersion\t\t: %s\n",(tmp_cell->obj->version));
tmp_label=gtk_label_new(label);
gtk_label_set_xalign (GTK_LABEL(tmp_label),0);
gtk_box_pack_start(GTK_BOX(box_ip),tmp_label, FALSE, FALSE, 0);
}
void remplir_arbre(GtkWidget *new_box, gpointer pData){
cell *tmp_cell=(cell *)pData;
GtkWidget *ethernet=gtk_expander_new ("Ethernet II");
gtk_expander_set_resize_toplevel (GTK_EXPANDER(ethernet),FALSE);
gtk_box_pack_start (GTK_BOX(new_box),ethernet,FALSE,FALSE,0);
GtkWidget *box_ethernet=gtk_box_new(FALSE,0);
gtk_orientable_set_orientation (GTK_ORIENTABLE (box_ethernet),GTK_ORIENTATION_VERTICAL);
gtk_container_add(GTK_CONTAINER(ethernet),box_ethernet);
remplir_ethernet(box_ethernet,tmp_cell);
GtkWidget *IP=gtk_expander_new ("Internet Protocol");
gtk_expander_set_resize_toplevel (GTK_EXPANDER(IP),FALSE);
gtk_box_pack_start (GTK_BOX(new_box),IP,FALSE,FALSE,0);
GtkWidget *box_ip=gtk_box_new(FALSE,0);
gtk_orientable_set_orientation (GTK_ORIENTABLE (box_ip),GTK_ORIENTATION_VERTICAL);
gtk_container_add(GTK_CONTAINER(IP),box_ip);
remplir_ip(box_ip,tmp_cell);
return;
}
I still don't know why gtk_tree did not work.
I'm trying to create a diaporama in c using gtk. I have a button "previous", which show the previous image. So I connect my button to a function and I pass it to a structure. But when I try to print an element of my array I have weird characters, and I don't know why. Plus, I got this warning for my gtk image :
GLib-GObject-WARNING **: 19:12:16.442: invalid uninstantiatable type '(null)' in cast to 'GtkImage'
Gtk-CRITICAL **: 19:12:16.442: IA__gtk_image_set_from_file: assertion 'GTK_IS_IMAGE (image)' failed
Here's my structure :
struct ButtonsArg {
GtkWidget *image;
char *img[];
};
Here's my code for the initialisation of my structure in the main :
GtkWidget *image = gtk_image_new();
char *images[nbImages];
//I get the name of all my image in this function
getImageList(images);
//This print work fine
printf("%s\n", images[0]);
struct ButtonsArg * arg;
arg = malloc(sizeof(struct ButtonsArg) + nbImages*sizeof(char*));
for(int i = 0; i < nbImages; i++) {
arg->img[i] = malloc(strlen(images[i])+1);
strcpy(arg->img[i], images[i]);
}
arg->image = image;
g_signal_connect(precedent, "clicked", G_CALLBACK(event_precedent), &arg);
Here's the function where the problems occur:
static void event_previous(GtkWidget *widget, gpointer data) {
g_print ("previous\n");
struct ButtonsArg *arg = data;
//Print weird charac
for(int i = 0; i < nbImages; i++) {
printf("%s\n", arg->img[i]);
}
GtkWidget *image = arg->image;
if(currentImage == 0) {
currentImage = nbImages - 1;
gtk_image_set_from_file (GTK_IMAGE (arg->image), arg->img[1]);
} else {
currentImage--;
gtk_image_set_from_file (GTK_IMAGE (arg->image), arg->img[2]);
}
}
If you have any advice, help or link that could help, thanks for sharing it with me.
Can you show the part of code where you try to change GtkImage variable? Seems like program was trying to set the null-value to GtkImage-type variable. In this cause any expression with this variable (like image->value) can raise segementation fault.
UPD: Ok. I see it. You should be check the arg-structure. I think, some attribute of this structure can have null-value.
Could anyone help me? I have programming skills in C and I'm trying to program gui's using gtk. I wish, from firing an action (a callback function) from a widget (eg a button), I can change any condition or characteristic belonging to any other widget. Ie something like allow full visibility from within the callback function as if all variables in all gui widgets (say a single main application window) were global. How can I address the closest way to accomplish this? So far, the steps I tried to discover underlying concepts in programming with gtk were frustrating me, when I try to make something more complex than simple Hello World tutorial.I also tried using:
/* out of main */
struct data_widgets
{
struct data_widgets * myp;
gchar **loc ; // LOCAL name
gchar **rem ; // REMOTE name
gchar **pmte ; // Plain message to encrypt filename
gchar **lem ; // Local encrypted message filename
gchar **emr ; // Encrypted message received filename
gchar **pmr ; // Plain message received filename
gchar **lopk ; // Local owner public key filename
gchar **crpk ; // Current remote public key filename
};
int main(int argc, char *argv[])
{
gchar loc_str[100] = "*"; /* LOCAL name for filechoose filter */
gchar rem_str[100] = "*"; /* REMOTE name idem */
gchar pmte_str[100]= "plainmsgtoencrypt"; /* Plain message to encrypt filename */
gchar lem_str[100] = "localencmsg"; /* Local encrypted message filename */
gchar emr_str[100] = "encmsgreceiv"; /* Encrypted message received filename */
gchar pmr_str[100] = "plainreceiv"; /* Plain message received filename */
gchar lopk_str[100]= "locownpubkey"; /* Local owner public key filename */
gchar crpk_str[100]= "remotpubkey"; /* Current remote public key filename */
struct data_widgets mydata;
mydata.loc = &loc_str;
mydata.rem = &rem_str;
mydata.pmte = &pmte_str;
mydata.lem = &lem_str;
mydata.emr = &emr_str;
mydata.pmr = &pmr_str;
mydata.lopk = &lopk_str;
mydata.crpk = &crpk_str;
mydata.myp = &mydata;
/* in main */
....
/* in my callback */
struct data_widgets *pp = (struct data_widgets *) data;
/*passing gpointer data as &mydata.myp, and doing (*pp)->(any pointer) this try fail*/
From what I understood you want to access widgets from within the callback without having to carry around a bunch of globals. You have some option.
You can pack data and widgets inside a single struct and pass it as user_data to the callback.
struct snapshot {
struct data_widgets data;
GtkWidget *entry;
GtkWidget *box;
GtkWidget *label;
GtkWidget *whatever;
};
/* Now fill and use the above struct as user_data */
The GtkWidget fields should be initialized in the code you use to create the UI stuff.
You can also set a name for each relevant widget with gtk_widget_set_name() (Glade automatically sets a name on every element). Once you need a widget, just get it with gtk_widget_get_name().
static void a_callback(GtkWidget *widget, gpointer user_data)
GtkWidget *an_entry = NULL;
GtkWidget *toplevel = gtk_widget_get_toplevel(widget);
if (gtk_widget_is_toplevel(toplevel))
an_entry = gtk_widget_get_name(toplevel, "name of the entry");
g_return_if_fail(an_entry != NULL);
/* ... do something with an_entry ... */
}
You can also traverse the widget hierarchy as if it was a DOM or directly bind your data to the widgets with g_object_set_data() or any valid mixture of the above.
Addendum
With g_object_set_data() you can attach arbitrary data to any GObject instance, e.g.:
gchar *text;
/* Bind some data to widget */
g_object_set_data(G_OBJECT(widget), "pmte", "plainmsgtoencrypt");
g_object_set_data(G_OBJECT(widget), "lem", "localencmsg");
text = g_object_get_data(G_OBJECT(widget), "pmte");
g_print("%s\n", text); /* Print "plainmsgtoencrypt" */
g_free(text);
text = g_object_get_data(G_OBJECT(widget), "lme");
g_print("%s\n", text); /* Print "localencmsg" */
g_free(text);
Code cleanup
Your code is messy in many ways: I suggest you forget what you learnt for C and restart from zero. Your data has one level of indirection more than what it is needed, myp is bogus, you are specifying size of arrays and initializing it.
Answering your comment: the following code is self-contained and does not throw the error you see.
#include <gtk/gtk.h>
struct data_widgets {
gchar **crpk;
};
void callback(GtkWidget *widget, gpointer user_data) {
struct data_widgets *data = user_data;
g_print("%s\n", data->crpk); /* Prints remotpubkey */
}
int main(int argc, char *argv[]) {
gchar crpk_str[100] = "remotpubkey";
struct data_widgets mydata;
mydata.crpk = &crpk_str;
callback(NULL, &mydata);
return 0;
}
The same code, cleaned up in a sane way:
#include <gtk/gtk.h>
typedef struct {
gchar *crpk;
} data_t;
void callback(GtkWidget *widget, gpointer user_data) {
data_t *data = user_data;
g_print("%s\n", data->crpk); /* Prints remotpubkey */
}
int main() {
data_t mydata;
mydata.crpk = "remotpubkey";
callback(NULL, &mydata);
return 0;
}
I'm developing an application that records audio files with GStreamer.
One feature of this app is to display a GTK dialog with a label
that contains information about the file recording process (name, type and size).
code:
static int timeout_id = -1;
static GtkWidget *file_label, *type_label, *size_label;
static gboolean timeout_cb(gpointer data)
{
GFile *session_file;
GFileInfo *info;
session_file = g_file_new_for_path (path);
info = g_file_query_info (session_file,
G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME ","
G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE ","
G_FILE_ATTRIBUTE_STANDARD_SIZE,
G_FILE_QUERY_INFO_NONE,
NULL,
NULL);
if (info != NULL) {
/* name */
const gchar *display_name = g_file_info_get_attribute_string (info,
G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME);
gtk_label_set_text (GTK_LABEL (file_label), display_name);
/* type */
const gchar *type = g_file_info_get_attribute_string (info,
G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE);
gtk_label_set_text (GTK_LABEL (type_label), type);
/* size */
guint64 size = g_file_info_get_attribute_uint64 (info,
G_FILE_ATTRIBUTE_STANDARD_SIZE);
gchar *tmp = g_format_size_full (size, G_FORMAT_SIZE_LONG_FORMAT);
gtk_label_set_text (GTK_LABEL (size_label), tmp);
g_free (tmp);
g_object_unref (info);
}
g_object_unref (file);
return TRUE;
}
void run_status_window(Record *record)
{
timeout_id = g_timeout_add(500, (GSourceFunc) timeout_cb, record);
}
I'm use queries for file information and attributes and calling this at 500 ms intervals.
My question is how can optimise this feature because the name and type aren't likely to change during the recording process.
Thanks