GTK TreeViewColumn Titles Disappear - c

I have a program that parses text files into distinct words and displays them plus their counts via GTK 3 in a tree view. One column is "Word" and the other is "Count".
For some reason, when a file has more than 1638 distinct "Words", the tree view no longer shows the column names, even though the parsing and word display proceeds normally. See the screenshots.
The words are stored in a struct:
typedef struct Word{
char * _origWord;
char * _word;
int _number;
struct Word * _left;
struct Word * _right;
Line * _line;
} Word;
"Line" is another struct for noting the lines the words appear on.
Here is the code where each "Word" is added to the GtkTreeStore:
static void store_words_counts(Word *w, GtkTreeStore *store, GtkTreeIter iter){
if (w->_word == NULL) return;
store_words_counts(w->_left, store, iter);
if (strlen(w->_origWord) > 0 && strAlpha(w->_origWord)){
gtk_tree_store_append (store, &iter, NULL);
int length = snprintf( NULL, 0, "%d", w->_number);
char * number = malloc(length + 1);
snprintf(number, length + 1, "%d", w->_number);
gtk_tree_store_set(store, &iter,
0, w->_origWord,
1, number,
-1);
free(number);
}
store_words_counts(w->_right, store, iter);
}
And here is the code where the columns are created:
GtkTreeStore * store = gtk_tree_store_new(2, G_TYPE_STRING, G_TYPE_STRING);
/* Load the data - call to parser */
load_tree_store(store, contents);
GtkWidget * tree = gtk_tree_view_new_with_model (GTK_TREE_MODEL (store));
GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(tree));
gtk_tree_selection_set_mode(selection, GTK_SELECTION_NONE);
g_object_unref (G_OBJECT (store));
GtkCellRendere *renderer = gtk_cell_renderer_text_new();
GtkTreeViewColumn *column = gtk_tree_view_column_new ();
gtk_tree_view_column_set_title (column, "Word");
gtk_tree_view_column_pack_start (column, renderer, TRUE);
gtk_tree_view_column_set_attributes(column, renderer, "text", 0, NULL);
printf("title is: %s\n", gtk_tree_view_column_get_title(column));
//column = gtk_tree_view_column_new_with_attributes ("Word", renderer,
// "text", 0,
// NULL);
I am not using an enum for column numbers so that I could make sure the columns were being created correctly. I also commented out a quicker way of creating the columns and did it step by step. When I check the titles of the columns after creating and loading them, the titles print correctly to stdout.
Any idea why they are not rendering past a certain number of data being loaded? Thanks.

Related

Revealer hiding another revealer when active (gtk_tree_store) - GTK3 , C

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.

Simulate backspace button press gtk in C

I am writing an app on raspberry in gtk+3/C which requires a virtual numpad (e.g 0-9, backspace and enter). I will use it with a touch screen, so no keyboard or mouse available (just like a kiosk).
I am adopting this code which allows me to use button press to emulate the number and display to an entry, however I am stuck at giving it the backspace function (go back and delete one previous char) and enter function (e.g when I'm done with input, press that button will help me to get back to the main screen).
/*
gcc -Wall keyboard1.c -o keyboard1 `pkg-config --cflags --libs gtk+-3.0`
Tested with GTK3.22 and GTK3.22 on Ubuntu18.04
*/
#include<gtk/gtk.h>
struct key{
gint id;
GtkWidget *button;
};
static const gchar letters[18]="QWERTYASDFGHZXCVBN";
//Need single chars as strings.
static gchar single_char[2]={'A', '\0'};
static void button_clicked(GtkWidget *button, gpointer *user_data)
{
gpointer *button_index=g_hash_table_lookup((GHashTable*)user_data[0], button);
g_print("Button index %i\n", (gint)(*button_index));
gint index=(gint)(*button_index);
single_char[0]=letters[index];
gchar *string=g_strdup_printf("%s%s", gtk_entry_get_text(GTK_ENTRY(user_data[1])), single_char);
gtk_entry_set_text(GTK_ENTRY(user_data[1]), string);
g_free(string);
}
int main(int argc, char *argv[])
{
gtk_init (&argc, &argv);
gint i=0;
gint j=0;
GtkWidget *window=gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_title(GTK_WINDOW(window), "Keyboard");
gtk_window_set_default_size(GTK_WINDOW(window), 400, 200);
gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL);
GtkWidget *entry=gtk_entry_new();
gtk_widget_set_hexpand(entry, TRUE);
//Save buttons in an array.
struct key k1;
GArray *keyboard=g_array_new(FALSE, FALSE, sizeof(struct key));
for(i=0;i<18;i++)
{
single_char[0]=letters[i];
k1.id=i;
k1.button=gtk_button_new_with_label(single_char);
g_array_append_val(keyboard, k1);
}
//A hash table to look up array index values.
struct key *p1=NULL;
GHashTable *hash_table=g_hash_table_new(NULL, NULL);
for(i=0;i<18;i++)
{
p1=&g_array_index(keyboard, struct key, i);
g_hash_table_insert(hash_table, p1->button, &(p1->id));
}
gpointer user_data[2]={hash_table, entry};
GtkWidget *grid1=gtk_grid_new();
for(i=0;i<3;i++)
{
for(j=0;j<6;j++)
{
p1=&g_array_index(keyboard, struct key, i*6+j);
gtk_grid_attach(GTK_GRID(grid1), p1->button, j, i, 1, 1);
g_signal_connect(p1->button, "clicked", G_CALLBACK(button_clicked), user_data);
}
}
GtkWidget *scroll=gtk_scrolled_window_new(NULL, NULL);
gtk_widget_set_vexpand(scroll, TRUE);
gtk_widget_set_hexpand(scroll, TRUE);
gtk_container_add(GTK_CONTAINER(scroll), grid1);
GtkWidget *expander=gtk_expander_new("Keyboard");
gtk_widget_set_vexpand(expander, TRUE);
gtk_widget_set_hexpand(expander, TRUE);
gtk_container_add(GTK_CONTAINER(expander), scroll);
GtkWidget *grid2=gtk_grid_new();
gtk_grid_attach(GTK_GRID(grid2), expander, 0, 0, 1, 1);
gtk_grid_attach(GTK_GRID(grid2), entry, 0, 1, 1, 1);
gtk_container_add(GTK_CONTAINER(window), grid2);
gtk_widget_show_all(window);
gtk_main();
g_hash_table_destroy(hash_table);
g_array_free(keyboard, TRUE);
return 0;
}
Here is the link to the post.
I have tried to replace a char in the gchar letters[18]="QWERTYASDFGHZXCVBN"; with \b, \n and \t as to replace backspace, newline and tab, but only \t works. \b gave me a strange symbol:
Could you give me suggestions on how to do it. Thank you very much!
You seem to confuse two things: gtk_entry_set_text sets the caption of a GTK element to a string of characters. It does not interpret it's characters.
That's why gtk_entry_set_text works well with non-control characters but stuck at \b. You had to send a GtkEvent using gtk_propagate_event to handle this properly (see here and here). \n is not a control character is this manner: It's possible that the GTK element your writing to just doesn't support newlines and Return would be interpreted as confirmation.

Ncurses text inside box flickering on refresh

I am trying to draw a box around some text that will be updated. In the place holder the text is static, but flickering is still observed. My code is below
/*
* #file main.cc
* #author Tom Eaton
* #date 09 Jan 2018
* #brief Command line interface to show Hawkcell PCB data.
*/
#include <iostream>
#include <string>
#include <cstring>
#include <ncurses.h>
using namespace std;
/*
* Prints string in the horizontal center of row specified.
* #param row - Row that text should be printed on
* #param mesg - Pointer to char array containing message
*/
void printHorizCenter(int row, char* mesg) {
mvprintw(row, ((COLS - strlen(mesg))/2)-1, mesg);
}
/*
* Reads version of PCB and updates char array with version
* #param outVersion - Pointer to char array where version should be stored.
* #param port - Reference to serial port
*/
void printHorizBlock(int row, int startCol, int endCol) {
for(int i = startCol; i<=endCol; i++) {
mvaddch(row, i, ACS_BLOCK);
}
}
int main(int argc, char** argv) {
//Initialise curses
initscr();
cbreak();
echo();
keypad(stdscr, 1);
//Make character capture non blocking
nodelay(stdscr, 1);
//Define char arrays for each cell
char cellOne[2] = {'1', '\n'};
char cellTwo[2] = {'2', '\n'};
char cellThree[2] = {'3', '\n'};
char cellFour[2] = {'4', '\n'};
//Setup curses colour schemes
start_color();
use_default_colors();
curs_set(0);
//Setup curses colour pairs
init_pair(1, COLOR_RED, -1);
init_pair(2, COLOR_WHITE, COLOR_RED);
WINDOW *win = newwin(10, 20, 1, 0);
//Main loop
while (1) {
if(getch() == 12) {
endwin();
cerr << "You pressed left and exited" << endl;
exit(1);
}
//Print top title bar
attron(COLOR_PAIR(1));
printHorizBlock(0, 0, (COLS/2) - (strlen("HawkCell")/2));
attroff(COLOR_PAIR(1));
attron(COLOR_PAIR(2));
printHorizCenter(0, (char *)"HawkCell");
attroff(COLOR_PAIR(2));
attron(COLOR_PAIR(1));
printHorizBlock(0, (COLS/2) + (strlen("HawkCell")/2) - 1, COLS);
attroff(COLOR_PAIR(1));
//Print voltage data
mvprintw(3, 1, "Cell 1: %.3fV\n", 4.0f);
mvprintw(4, 1, "Cell 2: %.3fV\n", 4.0f);
mvprintw(5, 1, "Cell 3: %.3fV\n", 4.0f);
mvprintw(6, 1, "Cell 4: %.3fV\n", 4.0f);
mvprintw(7, 1, "Total: %.3fV\n", 4.0f);
//Print bottom info bar
attron(COLOR_PAIR(1));
printHorizBlock(LINES-1, 0, COLS);
attroff(COLOR_PAIR(1));
attron(COLOR_PAIR(2));
printHorizCenter(LINES-1, (char *)"ctrl+c: Exit, ctrl+l: Toggle logging ");
attroff(COLOR_PAIR(2));
//Call curses refresh function to update screen
box(win, 0, 0);
//touchwin(win);
wrefresh(win);
wrefresh(stdscr);
}
getch();
endwin();
return 0;
}
The problem is that there is flickering when the screen is redrawn, shown in the gif below (Photo sensitivity warning)Gif showing problem. As you can see it only happens on the lines containing text, which makes me think that the whole line is being drawn when writing the text, not just the specific characters.
I have tried using a various combination of wrefresh(), touchwin(), erase() and refresh() but I couldn't find any that did not produce flickering.
How do I stop this flickering?
The problem is that your updates to stdscr and win alternate in updating the current screen (curscr), and since they write in the same area, they are doing a lot of repainting.
You could improve this by making a subwindow of win, and using that window for writing the text.
Something like
WINDOW *txt = derwin(win, 8, 18, 1, 1);
... modify all of the calls using stdscr:
mvwprintw(txt, 7, 1, "Total: %.3fV\n", 4.0f);
//Print bottom info bar
wattron(txt, COLOR_PAIR(1));
and using wgetch(txt) rather than getch() to get characters. The box only needs to be refreshed once (before the loop), and the wgetch() refreshes the window anyway: remove the last wrefresh and move the other right after creating win and calling box:
WINDOW *win = newwin(10, 20, 1, 0);
box(win, 0, 0);
wrefresh(win);

How to get the number of rows of gtk.ListStore

How to get the number of items / rows / length / count of gtk.ListStore in C
Here is my sample code:
store = gtk_list_store_new (NUM_COLS, G_TYPE_STRING, G_TYPE_UINT);
/* Append a row and fill in some data */
gtk_list_store_append (store, &iter);
gtk_list_store_set (store, &iter,
COL_NAME, "Heinz El-Mann",
COL_AGE, 51,
-1);
/* .
.
.
*/
/* get the length of gtk_list_store*/
Use gtk_tree_model_iter_n_children to obtain the number of rows in the list store.
In your case
number_of_rows = gtk_tree_model_iter_n_children(GTK_TREE_MODEL(store), NULL);
gtk_tree_model_iter_n_children reference

Optimise queries file information and attributes inside of function called at regular intervals

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

Resources