root/gui/world_tree.c @ 866d24baaf48377077b4d8bac26343c7e5e201fc

Revision 866d24baaf48377077b4d8bac26343c7e5e201fc, 19.6 KB (checked in by Nedko Arnaudov <nedko@…>, 3 years ago)

gui: display run menu item of view in world tree only if app supervisor is available

  • Property mode set to 100644
Line 
1/* -*- Mode: C ; c-basic-offset: 2 -*- */
2/*
3 * LADI Session Handler (ladish)
4 *
5 * Copyright (C) 2008, 2009, 2010 Nedko Arnaudov <nedko@arnaudov.name>
6 *
7 **************************************************************************
8 * This file contains implementation of the project_list class
9 **************************************************************************
10 *
11 * LADI Session Handler is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * LADI Session Handler is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with LADI Session Handler. If not, see <http://www.gnu.org/licenses/>
23 * or write to the Free Software Foundation, Inc.,
24 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
25 */
26
27#include "common.h"
28#include "world_tree.h"
29#include "gtk_builder.h"
30#include "../catdup.h"
31#include "menu.h"
32
33enum entry_type
34{
35  entry_type_view,
36  entry_type_app
37};
38
39enum
40{
41  COL_TYPE = 0,
42  COL_NAME,
43  COL_VIEW,
44  COL_ID,
45  COL_RUNNING,
46  COL_TERMINAL,
47  COL_LEVEL,
48  NUM_COLS
49};
50
51GtkWidget * g_world_tree_widget;
52GtkTreeStore * g_treestore;
53
54static
55gboolean
56on_select(
57  GtkTreeSelection * selection,
58  GtkTreeModel * model,
59  GtkTreePath * path,
60  gboolean path_currently_selected,
61  gpointer data)
62{
63  GtkTreeIter iter;
64  graph_view_handle view;
65  gint type;
66
67  if (gtk_tree_model_get_iter(model, &iter, path))
68  {
69    gtk_tree_model_get(model, &iter, COL_TYPE, &type, COL_VIEW, &view, -1);
70    if (type == entry_type_view)
71    {
72      //log_info("%s is going to be %s.", get_view_name(view), path_currently_selected ? "unselected" : "selected");
73      if (!path_currently_selected)
74      {
75        activate_view(view);
76      }
77    }
78  }
79
80  return TRUE;
81}
82
83bool get_selected_app_id(graph_view_handle * view_ptr, uint64_t * id_ptr)
84{
85  GtkTreeSelection * selection;
86  GtkTreeIter app_iter;
87  GtkTreeIter view_iter;
88  gint type;
89  uint64_t id;
90  graph_view_handle view;
91
92  selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(g_world_tree_widget));
93  if (!gtk_tree_selection_get_selected(selection, NULL, &app_iter))
94  {
95    return false;
96  }
97
98  gtk_tree_model_get(
99    GTK_TREE_MODEL(g_treestore),
100    &app_iter,
101    COL_TYPE, &type,
102    COL_ID, &id,
103    -1);
104  if (type != entry_type_app)
105  {
106    return false;
107  }
108
109  if (!gtk_tree_model_iter_parent(GTK_TREE_MODEL(g_treestore), &view_iter, &app_iter))
110  {
111    ASSERT_NO_PASS;
112    return false;
113  }
114
115  gtk_tree_model_get(
116    GTK_TREE_MODEL(g_treestore),
117    &view_iter,
118    COL_TYPE, &type,
119    COL_VIEW, &view,
120    -1);
121  if (type != entry_type_view)
122  {
123    ASSERT_NO_PASS;
124    return false;
125  }
126
127  *view_ptr = view;
128  *id_ptr = id;
129
130  return true;
131}
132
133void on_popup_menu_action_app_start(GtkWidget * menuitem, gpointer userdata)
134{
135  uint64_t id;
136  ladish_app_supervisor_proxy_handle proxy;
137  graph_view_handle view;
138
139  if (!get_selected_app_id(&view, &id))
140  {
141    return;
142  }
143
144  log_info("start app %"PRIu64, id);
145
146  proxy = graph_view_get_app_supervisor(view);
147  ladish_app_supervisor_proxy_start_app(proxy, id);
148}
149
150void on_popup_menu_action_app_stop(GtkWidget * menuitem, gpointer userdata)
151{
152  uint64_t id;
153  ladish_app_supervisor_proxy_handle proxy;
154  graph_view_handle view;
155
156  if (!get_selected_app_id(&view, &id))
157  {
158    return;
159  }
160
161  log_info("stop app %"PRIu64, id);
162
163  proxy = graph_view_get_app_supervisor(view);
164  ladish_app_supervisor_proxy_stop_app(proxy, id);
165}
166
167void on_popup_menu_action_app_kill(GtkWidget * menuitem, gpointer userdata)
168{
169  uint64_t id;
170  ladish_app_supervisor_proxy_handle proxy;
171  graph_view_handle view;
172
173  if (!get_selected_app_id(&view, &id))
174  {
175    return;
176  }
177
178  log_info("kill app %"PRIu64, id);
179
180  proxy = graph_view_get_app_supervisor(view);
181  ladish_app_supervisor_proxy_kill_app(proxy, id);
182}
183
184void on_popup_menu_action_app_remove(GtkWidget * menuitem, gpointer userdata)
185{
186  uint64_t id;
187  ladish_app_supervisor_proxy_handle proxy;
188  graph_view_handle view;
189
190  if (!get_selected_app_id(&view, &id))
191  {
192    return;
193  }
194
195  log_info("remove app %"PRIu64, id);
196
197  proxy = graph_view_get_app_supervisor(view);
198  ladish_app_supervisor_proxy_remove_app(proxy, id);
199}
200
201void on_popup_menu_action_app_properties(GtkWidget * menuitem, gpointer userdata)
202{
203  uint64_t id;
204  ladish_app_supervisor_proxy_handle proxy;
205  graph_view_handle view;
206  char * name;
207  char * command;
208  bool running;
209  bool terminal;
210  uint8_t level;
211  guint result;
212  GtkEntry * command_entry = GTK_ENTRY(get_gtk_builder_widget("app_command_entry"));
213  GtkEntry * name_entry = GTK_ENTRY(get_gtk_builder_widget("app_name_entry"));
214  GtkToggleButton * terminal_button = GTK_TOGGLE_BUTTON(get_gtk_builder_widget("app_terminal_check_button"));
215  GtkToggleButton * level0_button = GTK_TOGGLE_BUTTON(get_gtk_builder_widget("app_level0"));
216  GtkToggleButton * level1_button = GTK_TOGGLE_BUTTON(get_gtk_builder_widget("app_level1"));
217  GtkToggleButton * level2_button = GTK_TOGGLE_BUTTON(get_gtk_builder_widget("app_level2"));
218  GtkToggleButton * level3_button = GTK_TOGGLE_BUTTON(get_gtk_builder_widget("app_level3"));
219
220  if (!get_selected_app_id(&view, &id))
221  {
222    return;
223  }
224
225  log_info("app %"PRIu64" properties", id);
226
227  proxy = graph_view_get_app_supervisor(view);
228
229  if (!ladish_app_supervisor_get_app_properties(proxy, id, &name, &command, &running, &terminal, &level))
230  {
231    error_message_box("Cannot get app properties");
232    return;
233  }
234
235  log_info("'%s':'%s' %s level %"PRIu8, name, command, terminal ? "terminal" : "shell", level);
236
237  gtk_entry_set_text(name_entry, name);
238  gtk_entry_set_text(command_entry, command);
239  gtk_toggle_button_set_active(terminal_button, terminal);
240
241  gtk_widget_set_sensitive(GTK_WIDGET(command_entry), !running);
242  gtk_widget_set_sensitive(GTK_WIDGET(terminal_button), !running);
243  gtk_widget_set_sensitive(GTK_WIDGET(level0_button), !running);
244  gtk_widget_set_sensitive(GTK_WIDGET(level1_button), !running);
245
246  switch (level)
247  {
248  case 0:
249    gtk_toggle_button_set_active(level0_button, TRUE);
250    break;
251  case 1:
252    gtk_toggle_button_set_active(level1_button, TRUE);
253    break;
254  case 2:
255    gtk_toggle_button_set_active(level2_button, TRUE);
256    break;
257  case 3:
258    gtk_toggle_button_set_active(level3_button, TRUE);
259    break;
260  default:
261    log_error("unknown level");
262    ASSERT_NO_PASS;
263    gtk_toggle_button_set_active(level0_button, TRUE);
264  }
265
266  free(name);
267  free(command);
268
269  gtk_window_set_focus(GTK_WINDOW(g_app_dialog), running ? GTK_WIDGET(name_entry) : GTK_WIDGET(command_entry));
270  gtk_window_set_title(GTK_WINDOW(g_app_dialog), "App properties");
271
272  gtk_widget_show(g_app_dialog);
273
274  result = gtk_dialog_run(GTK_DIALOG(g_app_dialog));
275  if (result == 2)
276  {
277    if (gtk_toggle_button_get_active(level0_button))
278    {
279      level = 0;
280    }
281    else if (gtk_toggle_button_get_active(level1_button))
282    {
283      level = 1;
284    }
285    else if (gtk_toggle_button_get_active(level2_button))
286    {
287      level = 2;
288    }
289    else if (gtk_toggle_button_get_active(level3_button))
290    {
291      level = 3;
292    }
293    else
294    {
295      log_error("unknown level");
296      ASSERT_NO_PASS;
297      level = 0;
298    }
299
300    log_info("'%s':'%s' %s level %"PRIu8, gtk_entry_get_text(name_entry), gtk_entry_get_text(command_entry), gtk_toggle_button_get_active(terminal_button) ? "terminal" : "shell", level);
301    if (!ladish_app_supervisor_set_app_properties(proxy, id, gtk_entry_get_text(name_entry), gtk_entry_get_text(command_entry), gtk_toggle_button_get_active(terminal_button), level))
302    {
303      error_message_box("Cannot set app properties.");
304    }
305  }
306
307  gtk_widget_hide(g_app_dialog);
308}
309
310void on_popup_menu_action_start_app(GtkWidget * menuitem, gpointer userdata)
311{
312  menu_request_start_app();
313}
314
315void on_popup_menu_action_create_room(GtkWidget * menuitem, gpointer userdata)
316{
317  menu_request_create_room();
318}
319
320void on_popup_menu_action_destroy_room(GtkWidget * menuitem, gpointer userdata)
321{
322  menu_request_destroy_room();
323}
324
325void popup_menu(GtkWidget * treeview, GdkEventButton * event)
326{
327  GtkTreeSelection * selection;
328  GtkTreeIter iter;
329  GtkWidget * menu;
330  GtkWidget * menuitem;
331  gint type;
332  graph_view_handle view;
333  uint64_t id;
334  gboolean running;
335  gboolean terminal;
336  uint8_t level;
337
338  selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(g_world_tree_widget));
339  if (!gtk_tree_selection_get_selected(selection, NULL, &iter))
340  {
341    return;
342  }
343
344  gtk_tree_model_get(
345    GTK_TREE_MODEL(g_treestore),
346    &iter,
347    COL_TYPE, &type,
348    COL_VIEW, &view,
349    COL_ID, &id,
350    COL_RUNNING, &running,
351    COL_TERMINAL, &terminal,
352    COL_LEVEL, &level,
353    -1);
354
355  menu = gtk_menu_new();
356
357  if (type == entry_type_app)
358  {
359    if (running)
360    {
361      menuitem = gtk_menu_item_new_with_label("Stop");
362      g_signal_connect(menuitem, "activate", (GCallback)on_popup_menu_action_app_stop, NULL);
363      gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
364    }
365    else
366    {
367      menuitem = gtk_menu_item_new_with_label("Start");
368      g_signal_connect(menuitem, "activate", (GCallback)on_popup_menu_action_app_start, NULL);
369      gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
370    }
371
372    menuitem = gtk_menu_item_new_with_label("Remove");
373    g_signal_connect(menuitem, "activate", (GCallback)on_popup_menu_action_app_remove, NULL);
374    gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
375
376    if (running)
377    {
378      menuitem = gtk_menu_item_new_with_label("Kill");
379      g_signal_connect(menuitem, "activate", (GCallback)on_popup_menu_action_app_kill, NULL);
380      gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
381    }
382
383    menuitem = gtk_menu_item_new_with_label("Properties");
384    g_signal_connect(menuitem, "activate", (GCallback)on_popup_menu_action_app_properties, NULL);
385    gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
386  }
387  else if (type == entry_type_view)
388  {
389    if (graph_view_get_app_supervisor(view) != NULL)
390    {
391      menuitem = gtk_menu_item_new_with_label("Run...");
392      g_signal_connect(menuitem, "activate", (GCallback)on_popup_menu_action_start_app, NULL);
393      gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
394    }
395
396    if (is_room_view(view))
397    {
398      menuitem = gtk_menu_item_new_with_label("Destroy Room");
399      g_signal_connect(menuitem, "activate", (GCallback)on_popup_menu_action_destroy_room, NULL);
400      gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
401    }
402    else
403    {
404      menuitem = gtk_menu_item_new_with_label("Create Room...");
405      g_signal_connect(menuitem, "activate", (GCallback)on_popup_menu_action_create_room, NULL);
406      gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
407    }
408  }
409  else
410  {
411    g_object_ref(menu);
412    g_object_unref(menu);
413    return;
414  }
415
416  gtk_widget_show_all(menu);
417
418  /* Note: event can be NULL here when called from view_onPopupMenu;
419   *  gdk_event_get_time() accepts a NULL argument */
420  gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, (event != NULL) ? event->button : 0, gdk_event_get_time((GdkEvent *)event));
421}
422
423gboolean on_button_pressed(GtkWidget * treeview, GdkEventButton * event, gpointer userdata)
424{
425  /* single click with the right mouse button? */
426  if (event->type == GDK_BUTTON_PRESS && event->button == 3)
427  {
428    /* select row if no row is selected or only one other row is selected */
429    {
430      GtkTreeSelection *selection;
431
432      selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(treeview));
433
434      /* Note: gtk_tree_selection_count_selected_rows() does not exist in gtk+-2.0, only in gtk+ >= v2.2 ! */
435      if (gtk_tree_selection_count_selected_rows(selection) <= 1)
436      {
437        GtkTreePath *path;
438
439        /* Get tree path for row that was clicked */
440        if (gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(treeview), (gint)event->x, (gint)event->y, &path, NULL, NULL, NULL))
441        {
442          gtk_tree_selection_unselect_all(selection);
443          gtk_tree_selection_select_path(selection, path);
444          gtk_tree_path_free(path);
445        }
446      }
447    }
448
449    popup_menu(treeview, event);
450
451    return TRUE; /* we handled this */
452  }
453
454  return FALSE; /* we did not handle this */
455}
456
457gboolean on_popup_menu(GtkWidget * treeview, gpointer userdata)
458{
459  popup_menu(treeview, NULL);
460  return TRUE; /* we handled this */
461}
462
463void world_tree_init(void)
464{
465  GtkTreeViewColumn * col;
466  GtkCellRenderer * renderer;
467  GtkTreeSelection * selection;
468
469  g_world_tree_widget = get_gtk_builder_widget("world_tree");
470  gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(g_world_tree_widget), FALSE);
471
472  col = gtk_tree_view_column_new();
473  gtk_tree_view_column_set_title(col, "Name");
474  gtk_tree_view_append_column(GTK_TREE_VIEW(g_world_tree_widget), col);
475  renderer = gtk_cell_renderer_text_new();
476  gtk_tree_view_column_pack_start(col, renderer, TRUE);
477  gtk_tree_view_column_add_attribute(col, renderer, "text", COL_NAME);
478
479  g_treestore = gtk_tree_store_new(
480    NUM_COLS,
481    G_TYPE_INT,
482    G_TYPE_STRING,
483    G_TYPE_POINTER,
484    G_TYPE_UINT64,
485    G_TYPE_BOOLEAN,
486    G_TYPE_BOOLEAN,
487    G_TYPE_CHAR);
488  gtk_tree_view_set_model(GTK_TREE_VIEW(g_world_tree_widget), GTK_TREE_MODEL(g_treestore));
489
490  selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(g_world_tree_widget));
491  gtk_tree_selection_set_select_function(selection, on_select, NULL, NULL);
492
493  g_signal_connect(g_world_tree_widget, "button-press-event", (GCallback)on_button_pressed, NULL);
494  g_signal_connect(g_world_tree_widget, "popup-menu", (GCallback)on_popup_menu, NULL);
495}
496
497void world_tree_add(graph_view_handle view, bool force_activate)
498{
499  GtkTreeIter iter;
500
501  gtk_tree_store_append(g_treestore, &iter, NULL);
502  gtk_tree_store_set(g_treestore, &iter, COL_TYPE, entry_type_view, COL_VIEW, view, COL_NAME, get_view_name(view), -1);
503
504  /* select the first top level item */
505  if (force_activate || gtk_tree_model_iter_n_children(GTK_TREE_MODEL(g_treestore), NULL) == 1)
506  {
507    gtk_tree_selection_select_iter(gtk_tree_view_get_selection(GTK_TREE_VIEW(g_world_tree_widget)), &iter);
508  }
509}
510
511graph_view_handle world_tree_find_by_opath(const char * opath)
512{
513  gint type;
514  graph_view_handle view;
515  GtkTreeIter iter;
516
517  if (gtk_tree_model_get_iter_first(GTK_TREE_MODEL(g_treestore), &iter))
518  {
519    do
520    {
521      gtk_tree_model_get(GTK_TREE_MODEL(g_treestore), &iter, COL_TYPE, &type, COL_VIEW, &view, -1);
522      if (type == entry_type_view)
523      {
524        if (strcmp(get_view_opath(view), opath) == 0)
525        {
526          return view;
527        }
528      }
529    }
530    while (gtk_tree_model_iter_next(GTK_TREE_MODEL(g_treestore), &iter));
531  }
532
533  return NULL;
534}
535
536static bool find_view(graph_view_handle view, GtkTreeIter * iter_ptr)
537{
538  gint type;
539  graph_view_handle view2;
540
541  if (gtk_tree_model_get_iter_first(GTK_TREE_MODEL(g_treestore), iter_ptr))
542  {
543    do
544    {
545      gtk_tree_model_get(GTK_TREE_MODEL(g_treestore), iter_ptr, COL_TYPE, &type, COL_VIEW, &view2, -1);
546      if (type == entry_type_view && view == view2)
547      {
548        return true;
549      }
550    }
551    while (gtk_tree_model_iter_next(GTK_TREE_MODEL(g_treestore), iter_ptr));
552  }
553
554  return false;
555}
556
557static bool find_app(graph_view_handle view, uint64_t id, GtkTreeIter * view_iter_ptr, GtkTreeIter * app_iter_ptr)
558{
559  gint type;
560  uint64_t id2;
561
562  if (!find_view(view, view_iter_ptr))
563  {
564    return false;
565  }
566
567  if (!gtk_tree_model_iter_children(GTK_TREE_MODEL(g_treestore), app_iter_ptr, view_iter_ptr))
568  {
569    return false;
570  }
571
572  do
573  {
574    gtk_tree_model_get(GTK_TREE_MODEL(g_treestore), app_iter_ptr, COL_TYPE, &type, COL_ID, &id2, -1);
575    if (type == entry_type_app && id == id2)
576    {
577      return true;
578    }
579  }
580  while (gtk_tree_model_iter_next(GTK_TREE_MODEL(g_treestore), app_iter_ptr));
581
582  return false;
583}
584
585void world_tree_remove(graph_view_handle view)
586{
587  GtkTreeIter iter;
588
589  if (find_view(view, &iter))
590  {
591    gtk_tree_store_remove(g_treestore, &iter);
592  }
593}
594
595void world_tree_activate(graph_view_handle view)
596{
597  GtkTreeIter iter;
598
599  if (find_view(view, &iter))
600  {
601    gtk_tree_selection_select_iter(gtk_tree_view_get_selection(GTK_TREE_VIEW(g_world_tree_widget)), &iter);
602  }
603}
604
605void world_tree_name_changed(graph_view_handle view)
606{
607  GtkTreeIter iter;
608
609  if (find_view(view, &iter))
610  {
611    gtk_tree_store_set(g_treestore, &iter, COL_NAME, get_view_name(view), -1);
612  }
613}
614
615static char * get_app_name_string(const char * app_name, bool running, bool terminal, uint8_t level)
616{
617  char * app_name_with_status;
618  const char * level_string;
619
620  switch (level)
621  {
622  case 0:
623    level_string = "[L0]";
624    break;
625  case 1:
626    level_string = "[L1]";
627    break;
628  default:
629    level_string = "[L?]";
630  }
631
632  app_name_with_status = catdup3(level_string, running ? " " : " (inactive) ", app_name);
633  if (app_name_with_status == NULL)
634  {
635    log_error("catdup failed for app name");
636    return NULL;
637  }
638
639  return app_name_with_status;
640}
641
642void world_tree_add_app(graph_view_handle view, uint64_t id, const char * app_name, bool running, bool terminal, uint8_t level)
643{
644  GtkTreeIter iter;
645  const char * view_name;
646  GtkTreeIter child;
647  GtkTreePath * path;
648  char * app_name_with_status;
649
650  if (!find_view(view, &iter))
651  {
652    ASSERT_NO_PASS;
653    return;
654  }
655
656  path = gtk_tree_model_get_path(GTK_TREE_MODEL(g_treestore), &iter);
657
658  gtk_tree_model_get(GTK_TREE_MODEL(g_treestore), &iter, COL_NAME, &view_name, -1);
659
660  log_info("adding app '%s' to '%s'", app_name, view_name);
661
662  app_name_with_status = get_app_name_string(app_name, running, terminal, level);
663  if (app_name_with_status == NULL)
664  {
665    goto free_path;
666  }
667
668  gtk_tree_store_append(g_treestore, &child, &iter);
669  gtk_tree_store_set(
670    g_treestore,
671    &child,
672    COL_TYPE, entry_type_app,
673    COL_NAME, app_name_with_status,
674    COL_ID, id,
675    COL_RUNNING, running,
676    COL_TERMINAL, terminal,
677    COL_LEVEL, level,
678    -1);
679  gtk_tree_view_expand_row(GTK_TREE_VIEW(g_world_tree_widget), path, false);
680
681  free(app_name_with_status);
682free_path:
683  gtk_tree_path_free(path);
684}
685
686void world_tree_app_state_changed(graph_view_handle view, uint64_t id, const char * app_name, bool running, bool terminal, uint8_t level)
687{
688  GtkTreeIter view_iter;
689  GtkTreeIter app_iter;
690  const char * view_name;
691  GtkTreePath * path;
692  char * app_name_with_status;
693
694  if (!find_app(view, id, &view_iter, &app_iter))
695  {
696    log_error("removed app not found");
697    return;
698  }
699
700  path = gtk_tree_model_get_path(GTK_TREE_MODEL(g_treestore), &view_iter);
701
702  gtk_tree_model_get(GTK_TREE_MODEL(g_treestore), &view_iter, COL_NAME, &view_name, -1);
703
704  log_info("changing app state '%s':'%s'", view_name, app_name);
705
706  app_name_with_status = get_app_name_string(app_name, running, terminal, level);
707  if (app_name_with_status == NULL)
708  {
709    goto free_path;
710  }
711
712  gtk_tree_view_expand_row(GTK_TREE_VIEW(g_world_tree_widget), path, false);
713  gtk_tree_store_set(
714    g_treestore,
715    &app_iter,
716    COL_NAME, app_name_with_status,
717    COL_RUNNING, running,
718    COL_TERMINAL, terminal,
719    COL_LEVEL, level,
720    -1);
721
722  free(app_name_with_status);
723free_path:
724  gtk_tree_path_free(path);
725}
726
727void world_tree_remove_app(graph_view_handle view, uint64_t id)
728{
729  GtkTreeIter view_iter;
730  GtkTreeIter app_iter;
731  const char * view_name;
732  const char * app_name;
733  GtkTreePath * path;
734
735  if (!find_app(view, id, &view_iter, &app_iter))
736  {
737    log_error("removed app not found");
738    return;
739  }
740
741  path = gtk_tree_model_get_path(GTK_TREE_MODEL(g_treestore), &view_iter);
742
743  gtk_tree_model_get(GTK_TREE_MODEL(g_treestore), &view_iter, COL_NAME, &view_name, -1);
744  gtk_tree_model_get(GTK_TREE_MODEL(g_treestore), &app_iter, COL_NAME, &app_name, -1);
745
746  log_info("removing app '%s' from '%s'", app_name, view_name);
747
748  gtk_tree_view_expand_row(GTK_TREE_VIEW(g_world_tree_widget), path, false);
749  gtk_tree_store_remove(g_treestore, &app_iter);
750
751  gtk_tree_path_free(path);
752}
Note: See TracBrowser for help on using the browser.