1 /* -*- Mode: C ; c-basic-offset: 2 -*- */
3 * LADI Session Handler (ladish)
5 * Copyright (C) 2008, 2009 Nedko Arnaudov <nedko@arnaudov.name>
7 **************************************************************************
8 * This file contains implementation of the project_list class
9 **************************************************************************
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.
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.
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.
28 #include "world_tree.h"
30 #include "../catdup.h"
50 GtkWidget
* g_world_tree_widget
;
51 GtkTreeStore
* g_treestore
;
56 GtkTreeSelection
* selection
,
59 gboolean path_currently_selected
,
63 graph_view_handle view
;
66 if (gtk_tree_model_get_iter(model
, &iter
, path
))
68 gtk_tree_model_get(model
, &iter
, COL_TYPE
, &type
, COL_VIEW
, &view
, -1);
69 if (type
== entry_type_view
)
71 //log_info("%s is going to be %s.", get_view_name(view), path_currently_selected ? "unselected" : "selected");
72 if (!path_currently_selected
)
82 bool get_selected_app_id(graph_view_handle
* view_ptr
, uint64_t * id_ptr
)
84 GtkTreeSelection
* selection
;
86 GtkTreeIter view_iter
;
89 graph_view_handle view
;
91 selection
= gtk_tree_view_get_selection(GTK_TREE_VIEW(g_world_tree_widget
));
92 if (!gtk_tree_selection_get_selected(selection
, NULL
, &app_iter
))
98 GTK_TREE_MODEL(g_treestore
),
103 if (type
!= entry_type_app
)
108 if (!gtk_tree_model_iter_parent(GTK_TREE_MODEL(g_treestore
), &view_iter
, &app_iter
))
115 GTK_TREE_MODEL(g_treestore
),
120 if (type
!= entry_type_view
)
132 void on_popup_menu_action_app_start(GtkWidget
* menuitem
, gpointer userdata
)
135 ladish_app_supervisor_proxy_handle proxy
;
136 graph_view_handle view
;
138 if (!get_selected_app_id(&view
, &id
))
143 log_info("start app %"PRIu64
, id
);
145 proxy
= graph_view_get_app_supervisor(view
);
146 ladish_app_supervisor_proxy_start_app(proxy
, id
);
149 void on_popup_menu_action_app_stop(GtkWidget
* menuitem
, gpointer userdata
)
152 ladish_app_supervisor_proxy_handle proxy
;
153 graph_view_handle view
;
155 if (!get_selected_app_id(&view
, &id
))
160 log_info("stop app %"PRIu64
, id
);
162 proxy
= graph_view_get_app_supervisor(view
);
163 ladish_app_supervisor_proxy_stop_app(proxy
, id
);
166 void on_popup_menu_action_app_kill(GtkWidget
* menuitem
, gpointer userdata
)
169 ladish_app_supervisor_proxy_handle proxy
;
170 graph_view_handle view
;
172 if (!get_selected_app_id(&view
, &id
))
177 log_info("kill app %"PRIu64
, id
);
179 proxy
= graph_view_get_app_supervisor(view
);
180 ladish_app_supervisor_proxy_kill_app(proxy
, id
);
183 void on_popup_menu_action_app_remove(GtkWidget
* menuitem
, gpointer userdata
)
186 ladish_app_supervisor_proxy_handle proxy
;
187 graph_view_handle view
;
189 if (!get_selected_app_id(&view
, &id
))
194 log_info("remove app %"PRIu64
, id
);
196 proxy
= graph_view_get_app_supervisor(view
);
197 ladish_app_supervisor_proxy_remove_app(proxy
, id
);
200 void popup_menu(GtkWidget
* treeview
, GdkEventButton
* event
)
202 GtkTreeSelection
* selection
;
205 GtkWidget
* menuitem
;
207 graph_view_handle view
;
213 selection
= gtk_tree_view_get_selection(GTK_TREE_VIEW(g_world_tree_widget
));
214 if (!gtk_tree_selection_get_selected(selection
, NULL
, &iter
))
220 GTK_TREE_MODEL(g_treestore
),
225 COL_RUNNING
, &running
,
226 COL_TERMINAL
, &terminal
,
229 if (type
!= entry_type_app
)
234 menu
= gtk_menu_new();
238 menuitem
= gtk_menu_item_new_with_label("Stop");
239 g_signal_connect(menuitem
, "activate", (GCallback
)on_popup_menu_action_app_stop
, NULL
);
240 gtk_menu_shell_append(GTK_MENU_SHELL(menu
), menuitem
);
244 menuitem
= gtk_menu_item_new_with_label("Start");
245 g_signal_connect(menuitem
, "activate", (GCallback
)on_popup_menu_action_app_start
, NULL
);
246 gtk_menu_shell_append(GTK_MENU_SHELL(menu
), menuitem
);
249 menuitem
= gtk_menu_item_new_with_label("Remove");
250 g_signal_connect(menuitem
, "activate", (GCallback
)on_popup_menu_action_app_remove
, NULL
);
251 gtk_menu_shell_append(GTK_MENU_SHELL(menu
), menuitem
);
255 menuitem
= gtk_menu_item_new_with_label("Kill");
256 g_signal_connect(menuitem
, "activate", (GCallback
)on_popup_menu_action_app_kill
, NULL
);
257 gtk_menu_shell_append(GTK_MENU_SHELL(menu
), menuitem
);
260 gtk_widget_show_all(menu
);
262 /* Note: event can be NULL here when called from view_onPopupMenu;
263 * gdk_event_get_time() accepts a NULL argument */
264 gtk_menu_popup(GTK_MENU(menu
), NULL
, NULL
, NULL
, NULL
, (event
!= NULL
) ? event
->button
: 0, gdk_event_get_time((GdkEvent
*)event
));
267 gboolean
on_button_pressed(GtkWidget
* treeview
, GdkEventButton
* event
, gpointer userdata
)
269 /* single click with the right mouse button? */
270 if (event
->type
== GDK_BUTTON_PRESS
&& event
->button
== 3)
272 /* select row if no row is selected or only one other row is selected */
274 GtkTreeSelection
*selection
;
276 selection
= gtk_tree_view_get_selection(GTK_TREE_VIEW(treeview
));
278 /* Note: gtk_tree_selection_count_selected_rows() does not exist in gtk+-2.0, only in gtk+ >= v2.2 ! */
279 if (gtk_tree_selection_count_selected_rows(selection
) <= 1)
283 /* Get tree path for row that was clicked */
284 if (gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(treeview
), (gint
)event
->x
, (gint
)event
->y
, &path
, NULL
, NULL
, NULL
))
286 gtk_tree_selection_unselect_all(selection
);
287 gtk_tree_selection_select_path(selection
, path
);
288 gtk_tree_path_free(path
);
293 popup_menu(treeview
, event
);
295 return TRUE
; /* we handled this */
298 return FALSE
; /* we did not handle this */
301 gboolean
on_popup_menu(GtkWidget
* treeview
, gpointer userdata
)
303 popup_menu(treeview
, NULL
);
304 return TRUE
; /* we handled this */
307 void world_tree_init(void)
309 GtkTreeViewColumn
* col
;
310 GtkCellRenderer
* renderer
;
311 GtkTreeSelection
* selection
;
313 g_world_tree_widget
= get_glade_widget("world_tree");
314 gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(g_world_tree_widget
), FALSE
);
316 col
= gtk_tree_view_column_new();
317 gtk_tree_view_column_set_title(col
, "Name");
318 gtk_tree_view_append_column(GTK_TREE_VIEW(g_world_tree_widget
), col
);
319 renderer
= gtk_cell_renderer_text_new();
320 gtk_tree_view_column_pack_start(col
, renderer
, TRUE
);
321 gtk_tree_view_column_add_attribute(col
, renderer
, "text", COL_NAME
);
323 g_treestore
= gtk_tree_store_new(
332 gtk_tree_view_set_model(GTK_TREE_VIEW(g_world_tree_widget
), GTK_TREE_MODEL(g_treestore
));
334 selection
= gtk_tree_view_get_selection(GTK_TREE_VIEW(g_world_tree_widget
));
335 gtk_tree_selection_set_select_function(selection
, on_select
, NULL
, NULL
);
337 g_signal_connect(g_world_tree_widget
, "button-press-event", (GCallback
)on_button_pressed
, NULL
);
338 g_signal_connect(g_world_tree_widget
, "popup-menu", (GCallback
)on_popup_menu
, NULL
);
341 void world_tree_add(graph_view_handle view
, bool force_activate
)
345 gtk_tree_store_append(g_treestore
, &iter
, NULL
);
346 gtk_tree_store_set(g_treestore
, &iter
, COL_TYPE
, entry_type_view
, COL_VIEW
, view
, COL_NAME
, get_view_name(view
), -1);
348 /* select the first top level item */
349 if (force_activate
|| gtk_tree_model_iter_n_children(GTK_TREE_MODEL(g_treestore
), NULL
) == 1)
351 gtk_tree_selection_select_iter(gtk_tree_view_get_selection(GTK_TREE_VIEW(g_world_tree_widget
)), &iter
);
355 static bool find_view(graph_view_handle view
, GtkTreeIter
* iter_ptr
)
358 graph_view_handle view2
;
360 if (gtk_tree_model_get_iter_first(GTK_TREE_MODEL(g_treestore
), iter_ptr
))
364 gtk_tree_model_get(GTK_TREE_MODEL(g_treestore
), iter_ptr
, COL_TYPE
, &type
, COL_VIEW
, &view2
, -1);
365 if (type
== entry_type_view
&& view
== view2
)
370 while (gtk_tree_model_iter_next(GTK_TREE_MODEL(g_treestore
), iter_ptr
));
376 static bool find_app(graph_view_handle view
, uint64_t id
, GtkTreeIter
* view_iter_ptr
, GtkTreeIter
* app_iter_ptr
)
381 if (!find_view(view
, view_iter_ptr
))
386 if (!gtk_tree_model_iter_children(GTK_TREE_MODEL(g_treestore
), app_iter_ptr
, view_iter_ptr
))
393 gtk_tree_model_get(GTK_TREE_MODEL(g_treestore
), app_iter_ptr
, COL_TYPE
, &type
, COL_ID
, &id2
, -1);
394 if (type
== entry_type_app
&& id
== id2
)
399 while (gtk_tree_model_iter_next(GTK_TREE_MODEL(g_treestore
), app_iter_ptr
));
404 void world_tree_remove(graph_view_handle view
)
408 if (find_view(view
, &iter
))
410 gtk_tree_store_remove(g_treestore
, &iter
);
414 void world_tree_activate(graph_view_handle view
)
418 if (find_view(view
, &iter
))
420 gtk_tree_selection_select_iter(gtk_tree_view_get_selection(GTK_TREE_VIEW(g_world_tree_widget
)), &iter
);
424 void world_tree_name_changed(graph_view_handle view
)
428 if (find_view(view
, &iter
))
430 gtk_tree_store_set(g_treestore
, &iter
, COL_NAME
, get_view_name(view
), -1);
434 static char * get_app_name_string(const char * app_name
, bool running
, bool terminal
, uint8_t level
)
436 char * app_name_with_status
;
438 app_name_with_status
= catdup(running
? "" : "(inactive) ", app_name
);
439 if (app_name_with_status
== NULL
)
441 log_error("catdup failed for app name");
445 return app_name_with_status
;
448 void world_tree_add_app(graph_view_handle view
, uint64_t id
, const char * app_name
, bool running
, bool terminal
, uint8_t level
)
451 const char * view_name
;
454 char * app_name_with_status
;
456 if (!find_view(view
, &iter
))
462 path
= gtk_tree_model_get_path(GTK_TREE_MODEL(g_treestore
), &iter
);
464 gtk_tree_model_get(GTK_TREE_MODEL(g_treestore
), &iter
, COL_NAME
, &view_name
, -1);
466 log_info("adding app '%s' to '%s'", app_name
, view_name
);
468 app_name_with_status
= get_app_name_string(app_name
, running
, terminal
, level
);
469 if (app_name_with_status
== NULL
)
474 gtk_tree_store_append(g_treestore
, &child
, &iter
);
478 COL_TYPE
, entry_type_app
,
479 COL_NAME
, app_name_with_status
,
481 COL_RUNNING
, running
,
482 COL_TERMINAL
, terminal
,
485 gtk_tree_view_expand_row(GTK_TREE_VIEW(g_world_tree_widget
), path
, false);
487 free(app_name_with_status
);
489 gtk_tree_path_free(path
);
492 void world_tree_app_state_changed(graph_view_handle view
, uint64_t id
, const char * app_name
, bool running
, bool terminal
, uint8_t level
)
494 GtkTreeIter view_iter
;
495 GtkTreeIter app_iter
;
496 const char * view_name
;
498 char * app_name_with_status
;
500 if (!find_app(view
, id
, &view_iter
, &app_iter
))
502 log_error("removed app not found");
506 path
= gtk_tree_model_get_path(GTK_TREE_MODEL(g_treestore
), &view_iter
);
508 gtk_tree_model_get(GTK_TREE_MODEL(g_treestore
), &view_iter
, COL_NAME
, &view_name
, -1);
510 log_info("changing app state '%s':'%s'", view_name
, app_name
);
512 app_name_with_status
= get_app_name_string(app_name
, running
, terminal
, level
);
513 if (app_name_with_status
== NULL
)
518 gtk_tree_view_expand_row(GTK_TREE_VIEW(g_world_tree_widget
), path
, false);
522 COL_NAME
, app_name_with_status
,
523 COL_RUNNING
, running
,
524 COL_TERMINAL
, terminal
,
528 free(app_name_with_status
);
530 gtk_tree_path_free(path
);
533 void world_tree_remove_app(graph_view_handle view
, uint64_t id
)
535 GtkTreeIter view_iter
;
536 GtkTreeIter app_iter
;
537 const char * view_name
;
538 const char * app_name
;
541 if (!find_app(view
, id
, &view_iter
, &app_iter
))
543 log_error("removed app not found");
547 path
= gtk_tree_model_get_path(GTK_TREE_MODEL(g_treestore
), &view_iter
);
549 gtk_tree_model_get(GTK_TREE_MODEL(g_treestore
), &view_iter
, COL_NAME
, &view_name
, -1);
550 gtk_tree_model_get(GTK_TREE_MODEL(g_treestore
), &app_iter
, COL_NAME
, &app_name
, -1);
552 log_info("removing app '%s' from '%s'", app_name
, view_name
);
554 gtk_tree_view_expand_row(GTK_TREE_VIEW(g_world_tree_widget
), path
, false);
555 gtk_tree_store_remove(g_treestore
, &app_iter
);
557 gtk_tree_path_free(path
);