ui_tree_view.c 22.9 KB
Newer Older
1 2 3 4 5
/*
 * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The OpenAirInterface Software Alliance licenses this file to You under
6
 * the OAI Public License, Version 1.1  (the "License"); you may not use this file
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
 * except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.openairinterface.org/?page_id=698
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *-------------------------------------------------------------------------------
 * For more information about the OpenAirInterface (OAI) Software Alliance:
 *      contact@openairinterface.org
 */

Cedric Roux's avatar
 
Cedric Roux committed
22 23 24
#include <stdlib.h>
#include <stdint.h>

25 26
#define G_LOG_DOMAIN ("UI_TREE")

Cedric Roux's avatar
 
Cedric Roux committed
27 28
#include <gtk/gtk.h>

29
#include "logs.h"
30
#include "rc.h"
Cedric Roux's avatar
 
Cedric Roux committed
31

Cedric Roux's avatar
Cedric Roux committed
32 33
#include "buffers.h"

Cedric Roux's avatar
 
Cedric Roux committed
34 35 36
#include "ui_main_screen.h"
#include "ui_tree_view.h"
#include "ui_callbacks.h"
37
#include "ui_filters.h"
Cedric Roux's avatar
 
Cedric Roux committed
38 39 40

#include "ui_signal_dissect_view.h"

41 42 43 44
typedef struct
{
    GtkListStore *store;
    GtkTreeModelFilter *filtered;
winckel's avatar
winckel committed
45 46
    uint32_t filtered_last_msg;
    uint32_t filtered_msg_number;
winckel's avatar
winckel committed
47
    uint32_t instance_number;
48 49 50 51
} ui_store_t;

static ui_store_t ui_store;

52 53 54
GtkWidget *ui_tree_view_menu;
ui_tree_view_menu_enable_t ui_tree_view_menu_enable[NUM_MENU_TYPE];

winckel's avatar
winckel committed
55 56
GdkEventButton *ui_tree_view_last_event;

57 58
static gboolean ui_tree_filter_messages(GtkTreeModel *model, GtkTreeIter *iter, ui_store_t *store)
{
winckel's avatar
winckel committed
59
    uint32_t msg_number;
60 61 62
    uint32_t message_id;
    uint32_t origin_task_id;
    uint32_t destination_task_id;
winckel's avatar
winckel committed
63 64
    uint32_t instance;

65
    gboolean enabled = TRUE;
66

67
    if (ui_filters.filters_enabled)
68
    {
69
        gtk_tree_model_get (model, iter, COL_MSG_NUM, &msg_number, COL_MESSAGE_ID, &message_id, COL_FROM_TASK_ID,
70
                            &origin_task_id, COL_TO_TASK_ID, &destination_task_id, COL_INSTANCE_ID, &instance, -1);
71
        if (msg_number != 0)
72
        {
73
            enabled = ui_filters_message_enabled (message_id, origin_task_id, destination_task_id, instance);
74

75 76 77 78 79 80
            if ((enabled) && (store->filtered_last_msg < msg_number))
            {
                store->filtered_last_msg = msg_number;
                store->filtered_msg_number++;
            }
            g_debug("ui_tree_filter_messages: %p %p %d m:%d o:%d d:%d i:%d %d %d", model, iter, msg_number, message_id, origin_task_id, destination_task_id, instance, enabled, store->filtered_msg_number);
81 82
        }
    }
83 84 85 86

    return enabled;
}

winckel's avatar
winckel committed
87 88
static gboolean onButtonPressed(GtkWidget *treeview, GdkEventButton *event, gpointer userdata)
{
89
    g_info("onButtonPressed %p %p %p %d %d", treeview, event, userdata, event->type, event->button);
winckel's avatar
winckel committed
90 91 92 93 94 95
    ui_tree_view_last_event = event;

    return FALSE;
}

/*
96 97
 static gboolean onButtonRelease(GtkWidget *treeview, GdkEventButton *event, gpointer userdata)
 {
98
 g_info("onButtonRelease %p %p %p %d %d", treeview, event, userdata, event->type, event->button);
99
 // last_event = event;
winckel's avatar
winckel committed
100

101 102 103
 return FALSE;
 }
 */
winckel's avatar
winckel committed
104

105
static void ui_tree_view_init_list(GtkWidget *list)
Cedric Roux's avatar
 
Cedric Roux committed
106
{
107 108
    GtkCellRenderer *renderer_left;
    GtkCellRenderer *renderer_right;
Cedric Roux's avatar
 
Cedric Roux committed
109 110
    GtkTreeViewColumn *column;

111
    renderer_left = gtk_cell_renderer_text_new ();
112
    gtk_cell_renderer_set_padding (renderer_left, 5, 0);
113

114
    renderer_right = gtk_cell_renderer_text_new ();
115 116
    gtk_cell_renderer_set_alignment (renderer_right, 1, 0.5);
    gtk_cell_renderer_set_padding (renderer_right, 5, 0);
117

118 119
    column = gtk_tree_view_column_new_with_attributes ("MN", renderer_right, "text", COL_MSG_NUM, "foreground",
                                                       COL_FOREGROUND, "background", COL_BACKGROUND, NULL);
120
    gtk_tree_view_column_set_resizable (column, TRUE);
121
    gtk_tree_view_column_set_alignment (column, 0.5);
122
    gtk_tree_view_append_column (GTK_TREE_VIEW(list), column);
123

124
    column = gtk_tree_view_column_new_with_attributes ("LTE Time", renderer_right, "text", COL_LTE_TIME, NULL);
125
    gtk_tree_view_column_set_resizable (column, TRUE);
126
    gtk_tree_view_column_set_alignment (column, 0.5);
127
    gtk_tree_view_append_column (GTK_TREE_VIEW(list), column);
Cedric Roux's avatar
 
Cedric Roux committed
128

129
    column = gtk_tree_view_column_new_with_attributes ("Message", renderer_left, "text", COL_MESSAGE, "foreground",
130
                                                       COL_FOREGROUND, "background", COL_BACKGROUND, "strikethrough",
winckel's avatar
winckel committed
131
                                                       COL_STRIKETHROUGH, "style", COL_STYLE, "weight", COL_WEIGHT, "underline", COL_UNDERLINE, NULL);
132
    gtk_tree_view_column_set_resizable (column, TRUE);
133
    gtk_tree_view_column_set_alignment (column, 0.5);
134 135 136
    gtk_tree_view_append_column (GTK_TREE_VIEW(list), column);
    g_signal_connect(G_OBJECT(column), "clicked", G_CALLBACK(ui_callback_on_tree_column_header_click),
                     (gpointer) COL_MESSAGE);
Cedric Roux's avatar
 
Cedric Roux committed
137

138
    column = gtk_tree_view_column_new_with_attributes ("From", renderer_left, "text", COL_FROM_TASK, NULL);
139
    gtk_tree_view_column_set_alignment (column, 0.5);
140
    gtk_tree_view_column_set_resizable (column, TRUE);
141 142 143
    gtk_tree_view_append_column (GTK_TREE_VIEW(list), column);
    g_signal_connect(G_OBJECT(column), "clicked", G_CALLBACK(ui_callback_on_tree_column_header_click),
                     (gpointer) COL_FROM_TASK);
Cedric Roux's avatar
Cedric Roux committed
144

145
    column = gtk_tree_view_column_new_with_attributes ("To", renderer_left, "text", COL_TO_TASK, NULL);
146
    gtk_tree_view_column_set_alignment (column, 0.5);
147
    gtk_tree_view_column_set_resizable (column, TRUE);
148 149 150
    gtk_tree_view_append_column (GTK_TREE_VIEW(list), column);
    g_signal_connect(G_OBJECT(column), "clicked", G_CALLBACK(ui_callback_on_tree_column_header_click),
                     (gpointer) COL_TO_TASK);
Cedric Roux's avatar
Cedric Roux committed
151

152
    column = gtk_tree_view_column_new_with_attributes ("Ins", renderer_right, "text", COL_INSTANCE, NULL);
153
    gtk_tree_view_column_set_alignment (column, 0.5);
154 155 156 157 158 159 160 161 162 163 164
    gtk_tree_view_append_column (GTK_TREE_VIEW(list), column);
    g_signal_connect(G_OBJECT(column), "clicked", G_CALLBACK(ui_callback_on_tree_column_header_click),
                     (gpointer) COL_INSTANCE);

    ui_store.store = gtk_list_store_new (NUM_COLS, // Number of columns
            // Displayed columns
            G_TYPE_UINT, // COL_MSG_NUM
            G_TYPE_STRING, // COL_LTE_TIME
            G_TYPE_STRING, // COL_MESSAGE
            G_TYPE_STRING, // COL_FROM_TASK
            G_TYPE_STRING, // COL_TO_TASK
165
            G_TYPE_STRING, // COL_INSTANCE
166 167 168 169 170
            // Not displayed columns
            // Id of some message fields to speed-up filtering
            G_TYPE_UINT, // COL_MESSAGE_ID
            G_TYPE_UINT, // COL_FROM_TASK_ID
            G_TYPE_UINT, // COL_TO_TASK_ID
171
            G_TYPE_UINT, // COL_INSTANCE_ID
172
            G_TYPE_STRING, // COL_FOREGROUND
173
            G_TYPE_STRING, // COL_BACKGROUND
174
            G_TYPE_BOOLEAN, // COL_STRIKETHROUGH
winckel's avatar
winckel committed
175 176 177
            G_TYPE_UINT,
            G_TYPE_UINT,
            G_TYPE_UINT,
178 179 180 181
            // Reference to the buffer here to avoid maintaining multiple lists.
            G_TYPE_POINTER);

    if (ui_store.store == NULL)
winckel's avatar
winckel committed
182 183 184 185
    {
        g_error("gtk_list_store_new failed");
    }

186
    ui_store.filtered = GTK_TREE_MODEL_FILTER (gtk_tree_model_filter_new (GTK_TREE_MODEL (ui_store.store), NULL));
187
    gtk_tree_model_filter_set_visible_func (ui_store.filtered, (GtkTreeModelFilterVisibleFunc) ui_tree_filter_messages,
188
                                            &ui_store, NULL);
Cedric Roux's avatar
 
Cedric Roux committed
189

190
    gtk_tree_view_set_model (GTK_TREE_VIEW(list), GTK_TREE_MODEL(ui_store.filtered));
191

192
    gtk_tree_view_columns_autosize (GTK_TREE_VIEW(list));
Cedric Roux's avatar
 
Cedric Roux committed
193 194
}

195 196
static void ui_tree_view_add_to_list(GtkWidget *list, const gchar *lte_time, const uint32_t message_number,
                                     const uint32_t message_id, const gchar *signal_name, const uint32_t origin_task_id,
197 198
                                     const char *origin_task_name, const uint32_t destination_task_id,
                                     const char *destination_task_name, uint32_t instance_id, const char *instance_name, gpointer buffer)
Cedric Roux's avatar
 
Cedric Roux committed
199
{
winckel's avatar
winckel committed
200 201
    static int counter = 0;

Cedric Roux's avatar
 
Cedric Roux committed
202
    GtkTreeIter iter;
203
    gboolean enabled;
204
    int message_index;
205

206 207 208 209 210 211
    g_info("ui_tree_view_add_to_list: %d %d %d %d %d", message_number, message_id, origin_task_id, destination_task_id, instance_id);

    enabled = ui_filters_message_enabled (message_id, origin_task_id, destination_task_id, instance_id);
    message_index = ui_filters_search_id (&ui_filters.messages, message_id);

    g_info("ui_tree_view_add_to_list: %d %d", enabled, message_index);
Cedric Roux's avatar
 
Cedric Roux committed
212

213 214
    gtk_list_store_append (ui_store.store, &iter);
    gtk_list_store_set (ui_store.store, &iter,
215 216
    /* Columns */
    COL_MSG_NUM,
217 218 219 220
                        message_number, COL_LTE_TIME, lte_time, COL_MESSAGE, signal_name, COL_FROM_TASK, origin_task_name,
                        COL_TO_TASK, destination_task_name, COL_INSTANCE, instance_name, COL_MESSAGE_ID, message_id,
                        COL_FROM_TASK_ID, origin_task_id, COL_TO_TASK_ID, destination_task_id, COL_INSTANCE_ID, instance_id,
                        COL_BUFFER, buffer, COL_FOREGROUND, ui_filters.messages.items[message_index].foreground, COL_BACKGROUND,
221
                        ui_filters.messages.items[message_index].background, COL_STRIKETHROUGH, !enabled,
winckel's avatar
winckel committed
222 223 224 225 226 227
//                        COL_STYLE, (counter % 2) == 0 ? PANGO_STYLE_ITALIC : PANGO_STYLE_NORMAL,
//                        COL_WEIGHT, ((counter + 2) % 4) < 2 ? PANGO_WEIGHT_BOLD : PANGO_WEIGHT_NORMAL,
//                        COL_UNDERLINE, ((counter + 4) % 8) < 4 ?PANGO_UNDERLINE_SINGLE : PANGO_UNDERLINE_NONE,
                        COL_STYLE, PANGO_STYLE_NORMAL,
                        COL_WEIGHT, PANGO_WEIGHT_NORMAL,
                        COL_UNDERLINE, PANGO_UNDERLINE_NONE,
228 229
                        /* End of columns */
                        -1);
winckel's avatar
winckel committed
230
    counter++;
Cedric Roux's avatar
 
Cedric Roux committed
231 232 233 234 235 236
}

void ui_tree_view_destroy_list(GtkWidget *list)
{
    g_assert(list != NULL);

237
    gtk_list_store_clear (ui_store.store);
238 239
    ui_store.filtered_last_msg = 0;
    ui_store.filtered_msg_number = 0;
winckel's avatar
winckel committed
240
    ui_store.instance_number = 0;
241 242 243

    /* Reset number of messages */
    ui_main_data.nb_message_received = 0;
winckel's avatar
winckel committed
244 245 246
}

/* Search for the message with its message number equal to the given value or the previous one */
247 248
static gboolean ui_tree_view_search(GtkTreeModel *model, gint column, const gchar *key, GtkTreeIter *iter,
                                    gpointer search_data)
winckel's avatar
winckel committed
249 250
{
    uint32_t msg_number;
251
    uint32_t key_value = atoi (key);
winckel's avatar
winckel committed
252 253 254

    gtk_tree_model_get (model, iter, column, &msg_number, -1);

255
    g_debug("ui_tree_view_search %d %d", key_value, msg_number);
winckel's avatar
winckel committed
256 257 258 259 260 261 262 263 264 265

    if (key_value == msg_number)
    {
        /* Value found, use this message */
        return 0;
    }

    {
        GtkTreeIter iter_next = *iter;

266
        if (gtk_tree_model_iter_next (model, &iter_next))
winckel's avatar
winckel committed
267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282
        {
            gtk_tree_model_get (model, &iter_next, column, &msg_number, -1);

            if (key_value < msg_number)
            {
                /* Next value will be greater, use this message */
                return 0;
            }
        }
        else
        {
            /* Last value, use this message */
            return 0;
        }
    }
    return 1;
Cedric Roux's avatar
 
Cedric Roux committed
283 284
}

285 286 287 288
static void ui_tree_view_create_menu(GtkWidget **menu)
{
    GtkWidget *menu_items;

289
    *menu = gtk_menu_new ();
290 291 292 293

    /* Create the "Message enable" menu-item */
    {
        /* Create a new menu-item */
294
        menu_items = gtk_check_menu_item_new ();
295 296 297
        ui_tree_view_menu_enable[MENU_MESSAGE].menu_enable = menu_items;

        /* Add it to the menu. */
298 299 300
        gtk_menu_shell_append (GTK_MENU_SHELL(*menu), menu_items);
        g_signal_connect(G_OBJECT(menu_items), "activate", G_CALLBACK(ui_callback_on_menu_enable),
                         &ui_tree_view_menu_enable[MENU_MESSAGE]);
301 302

        /* Show the widget */
303
        gtk_widget_show (menu_items);
304 305 306 307 308
    }

    /* Create the "Destination task enable" menu-item */
    {
        /* Create a new menu-item */
309
        menu_items = gtk_check_menu_item_new ();
310 311 312
        ui_tree_view_menu_enable[MENU_FROM_TASK].menu_enable = menu_items;

        /* Add it to the menu. */
313 314 315
        gtk_menu_shell_append (GTK_MENU_SHELL(*menu), menu_items);
        g_signal_connect(G_OBJECT(menu_items), "activate", G_CALLBACK(ui_callback_on_menu_enable),
                         &ui_tree_view_menu_enable[MENU_FROM_TASK]);
316 317

        /* Show the widget */
318
        gtk_widget_show (menu_items);
319 320 321 322 323
    }

    /* Create the "Origin task enable" menu-item */
    {
        /* Create a new menu-item */
324
        menu_items = gtk_check_menu_item_new ();
325 326 327
        ui_tree_view_menu_enable[MENU_TO_TASK].menu_enable = menu_items;

        /* Add it to the menu. */
328 329 330
        gtk_menu_shell_append (GTK_MENU_SHELL(*menu), menu_items);
        g_signal_connect(G_OBJECT(menu_items), "activate", G_CALLBACK(ui_callback_on_menu_enable),
                         &ui_tree_view_menu_enable[MENU_TO_TASK]);
331 332

        /* Show the widget */
333
        gtk_widget_show (menu_items);
334 335 336 337 338
    }

    /* Create the "Instance enable" menu-item */
    {
        /* Create a new menu-item */
339
        menu_items = gtk_check_menu_item_new ();
340 341 342
        ui_tree_view_menu_enable[MENU_INSTANCE].menu_enable = menu_items;

        /* Add it to the menu. */
343 344 345
        gtk_menu_shell_append (GTK_MENU_SHELL(*menu), menu_items);
        g_signal_connect(G_OBJECT(menu_items), "activate", G_CALLBACK(ui_callback_on_menu_enable),
                         &ui_tree_view_menu_enable[MENU_INSTANCE]);
346 347

        /* Show the widget */
348
        gtk_widget_show (menu_items);
349 350
    }

351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368
    /* Create the "Foreground color" menu-item */
    {
        static ui_tree_view_menu_color_t menu_color_foreground =
            {TRUE, &ui_tree_view_menu_enable[MENU_MESSAGE]};

        /* Create a new menu-item with a name */
        menu_items = gtk_menu_item_new_with_label ("Select message foreground color");

        /* Add it to the menu. */
        gtk_menu_shell_append (GTK_MENU_SHELL(*menu), menu_items);
        g_signal_connect(G_OBJECT(menu_items), "activate", G_CALLBACK(ui_callback_on_menu_color),
                         &menu_color_foreground);

        /* Show the widget */
        gtk_widget_show (menu_items);
    }

    /* Create the "Background color" menu-item */
369
    {
370 371 372
        static ui_tree_view_menu_color_t menu_color_background =
            {FALSE, &ui_tree_view_menu_enable[MENU_MESSAGE]};

373
        /* Create a new menu-item with a name */
374
        menu_items = gtk_menu_item_new_with_label ("Select message background color");
375 376

        /* Add it to the menu. */
377 378
        gtk_menu_shell_append (GTK_MENU_SHELL(*menu), menu_items);
        g_signal_connect(G_OBJECT(menu_items), "activate", G_CALLBACK(ui_callback_on_menu_color),
379
                         &menu_color_background);
380 381

        /* Show the widget */
382
        gtk_widget_show (menu_items);
383 384 385
    }
}

Cedric Roux's avatar
 
Cedric Roux committed
386 387 388 389 390 391
int ui_tree_view_create(GtkWidget *window, GtkWidget *vbox)
{
    GtkWidget *hbox;
    GtkTreeSelection *selection;
    GtkWidget *scrolled_window;

392
    scrolled_window = gtk_scrolled_window_new (NULL, NULL);
Cedric Roux's avatar
 
Cedric Roux committed
393

394
    gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW(scrolled_window), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
Cedric Roux's avatar
 
Cedric Roux committed
395

396 397
    ui_main_data.messages_list = gtk_tree_view_new ();
    gtk_tree_view_set_headers_visible (GTK_TREE_VIEW(ui_main_data.messages_list), TRUE);
398
    gtk_tree_view_set_search_equal_func (GTK_TREE_VIEW(ui_main_data.messages_list), ui_tree_view_search, NULL, NULL);
399 400
    gtk_tree_view_set_search_entry (GTK_TREE_VIEW(ui_main_data.messages_list),
                                    GTK_ENTRY(ui_main_data.signals_go_to_entry));
Cedric Roux's avatar
 
Cedric Roux committed
401 402

    /* Disable multiple selection */
403 404
    selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(ui_main_data.messages_list));
    gtk_tree_selection_set_mode (selection, GTK_SELECTION_BROWSE);
Cedric Roux's avatar
 
Cedric Roux committed
405

406
    hbox = gtk_paned_new (GTK_ORIENTATION_HORIZONTAL);
Cedric Roux's avatar
 
Cedric Roux committed
407

408
    gtk_container_add (GTK_CONTAINER(scrolled_window), ui_main_data.messages_list);
Cedric Roux's avatar
 
Cedric Roux committed
409

410 411
    ui_tree_view_init_list (ui_main_data.messages_list);
    gtk_tree_view_set_headers_clickable (GTK_TREE_VIEW(ui_main_data.messages_list), TRUE);
Cedric Roux's avatar
 
Cedric Roux committed
412

413
    gtk_scrolled_window_set_min_content_width (GTK_SCROLLED_WINDOW(scrolled_window), 680);
414
    gtk_paned_pack1 (GTK_PANED (hbox), scrolled_window, FALSE, TRUE);
415
    ui_main_data.text_view = ui_signal_dissect_new (hbox);
Cedric Roux's avatar
 
Cedric Roux committed
416

417
    gtk_box_pack_start (GTK_BOX(vbox), hbox, TRUE, TRUE, 5);
Cedric Roux's avatar
 
Cedric Roux committed
418

419
    g_signal_connect(G_OBJECT(ui_main_data.messages_list), "button-press-event", G_CALLBACK (onButtonPressed), NULL);
winckel's avatar
winckel committed
420 421
    // g_signal_connect(G_OBJECT(ui_main_data.signalslist), "button-release-event", G_CALLBACK (onButtonRelease), NULL);

Cedric Roux's avatar
 
Cedric Roux committed
422
    /* Connect callback on row selection */
423
    gtk_tree_selection_set_select_function (selection, ui_callback_on_select_signal, ui_main_data.text_view, NULL);
Cedric Roux's avatar
 
Cedric Roux committed
424

winckel's avatar
winckel committed
425 426 427 428
    ui_store.filtered_last_msg = 0;
    ui_store.filtered_msg_number = 0;
    ui_store.instance_number = 0;

429 430
    ui_main_data.selection = selection;

431 432
    ui_tree_view_create_menu (&ui_tree_view_menu);

Cedric Roux's avatar
 
Cedric Roux committed
433 434 435
    return 0;
}

436
int ui_tree_view_new_signal_ind(const uint32_t message_number, const gchar *lte_time, const uint32_t message_id,
437 438
                                const char *message_name, const uint32_t origin_task_id, const char *origin_task_name,
                                const uint32_t destination_task_id, const char *destination_task_name, uint32_t instance_id,
439
                                gpointer buffer)
Cedric Roux's avatar
 
Cedric Roux committed
440
{
441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462
    char *instance_name = NULL;
    char instance_name_buffer[10];

    if (((instance_t) instance_id) < INSTANCE_DEFAULT)
    {
        if (ui_store.instance_number < (instance_id + 1))
        {
            int i;

            for (i = ui_store.instance_number; i <= instance_id; i++)
            {
                sprintf (instance_name_buffer, "%d", i);
                ui_filters_add (FILTER_INSTANCES, i, instance_name_buffer, ENTRY_ENABLED_TRUE, NULL, NULL);
            }
            ui_store.instance_number = (instance_id + 1);
            ui_destroy_filter_menu (FILTER_INSTANCES);
        }

        sprintf (instance_name_buffer, "%d", instance_id);
        instance_name = instance_name_buffer;
    }
    else
winckel's avatar
winckel committed
463
    {
464 465 466 467 468 469 470 471 472 473 474 475 476
        switch ((instance_t) instance_id)
        {
            case INSTANCE_DEFAULT:
                instance_name = "DEF";
                break;

            case INSTANCE_ALL:
                instance_name = "ALL";
                break;

            default:
                break;
        }
winckel's avatar
winckel committed
477

478
        if ((instance_name != NULL) && (ui_filters_search_id (&ui_filters.instances, instance_id) < 0))
winckel's avatar
winckel committed
479
        {
480
            ui_filters_add (FILTER_INSTANCES, instance_id, instance_name, ENTRY_ENABLED_TRUE, NULL, NULL);
winckel's avatar
winckel committed
481 482 483
        }
    }

484
    ui_tree_view_add_to_list (ui_main_data.messages_list, lte_time, message_number, message_id, message_name,
485
                              origin_task_id, origin_task_name, destination_task_id, destination_task_name, instance_id, instance_name,
486
                              buffer);
Cedric Roux's avatar
 
Cedric Roux committed
487 488 489

    return RC_OK;
}
490

winckel's avatar
winckel committed
491
void ui_tree_view_select_row(gint row)
492
{
493
    GtkTreePath *path_row;
494

495
    if (row >= 0)
496
    {
497 498 499 500
        path_row = gtk_tree_path_new_from_indices (row, -1);

        if ((ui_main_data.messages_list != NULL) && (path_row != NULL))
        {
501
            g_info("Select row %d", row);
502 503 504 505 506 507

            /* Select the message in requested row */
            gtk_tree_view_set_cursor (GTK_TREE_VIEW(ui_main_data.messages_list), path_row, NULL, FALSE);
            /* Center the message in the middle of the list if possible */
            gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW(ui_main_data.messages_list), path_row, NULL, TRUE, 0.5, 0.0);
        }
508
    }
509
}
510

511
static gboolean updateColors(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
512 513 514 515 516 517 518
{
    uint32_t message_id;
    uint32_t origin_task_id;
    uint32_t destination_task_id;
    uint32_t instance;

    gboolean enabled = FALSE;
519
    int message_index;
520

521
    gtk_tree_model_get (model, iter, COL_MESSAGE_ID, &message_id, COL_FROM_TASK_ID, &origin_task_id, COL_TO_TASK_ID,
522
                        &destination_task_id, COL_INSTANCE_ID, &instance, -1);
523
    enabled = ui_filters_message_enabled (message_id, origin_task_id, destination_task_id, instance);
524
    message_index = ui_filters_search_id (&ui_filters.messages, message_id);
525

526 527 528
    gtk_list_store_set (GTK_LIST_STORE(model), iter, COL_FOREGROUND,
                        ui_filters.messages.items[message_index].foreground, COL_BACKGROUND,
                        ui_filters.messages.items[message_index].background, COL_STRIKETHROUGH, !enabled, -1);
529 530 531 532

    return FALSE;
}

533
void ui_tree_view_refilter()
534
{
535 536
    ui_store.filtered_last_msg = 0;
    ui_store.filtered_msg_number = 0;
537 538 539

    /* Update foreground color of messages, this will also update filtered model */
    if (ui_store.store != NULL)
540
    {
541
        gtk_tree_model_foreach (GTK_TREE_MODEL(ui_store.store), updateColors, NULL);
542 543 544 545 546 547 548 549 550 551 552 553 554 555 556

        if (ui_main_data.messages_list != NULL)
        {
            GtkTreePath *path_row;

            /* Get the currently selected message */
            gtk_tree_view_get_cursor (GTK_TREE_VIEW(ui_main_data.messages_list), &path_row, NULL);
            if (path_row != NULL)
            {
                /* Center the message in the middle of the list if possible */
                gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW(ui_main_data.messages_list), path_row, NULL, TRUE, 0.5,
                                              0.0);
                g_info("ui_tree_view_refilter: center on message");
            }
        }
557
    }
558

559
    g_info("ui_tree_view_refilter: last message %d, %d messages displayed", ui_store.filtered_last_msg, ui_store.filtered_msg_number);
560 561
}

562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606
typedef struct foreach_message_params_s
{
    message_write_callback_t   callback;
    gboolean                    filter;
} foreach_message_params_t;

static gboolean foreach_message(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
{
    foreach_message_params_t *params = (foreach_message_params_t *) data;
    const gchar *signal_name;
    uint32_t message_id;
    uint32_t origin_task_id;
    uint32_t destination_task_id;
    uint32_t instance;
    gpointer buffer = NULL;

    gtk_tree_model_get (model, iter, COL_MESSAGE, &signal_name, COL_MESSAGE_ID, &message_id, COL_FROM_TASK_ID, &origin_task_id, COL_TO_TASK_ID,
                        &destination_task_id, COL_INSTANCE_ID, &instance, COL_BUFFER, &buffer, -1);

    if (params->filter == TRUE)
    {
        gboolean enabled = FALSE;

        enabled = ui_filters_message_enabled (message_id, origin_task_id, destination_task_id, instance);
        if (enabled == FALSE)
        {
            buffer = NULL;
        }
    }

    if (buffer != NULL)
    {
        params->callback(buffer, signal_name);
    }

    return FALSE;
}

void ui_tree_view_foreach_message(message_write_callback_t callback, gboolean filter)
{
    foreach_message_params_t params = {callback, filter};

    gtk_tree_model_foreach (GTK_TREE_MODEL(ui_store.store), foreach_message, (void *) &params);
}

607 608 609
guint ui_tree_view_get_filtered_number(void)
{
    return ui_store.filtered_msg_number;
610
}