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(uint64_t * id_ptr
)
84 GtkTreeSelection
* selection
;
89 selection
= gtk_tree_view_get_selection(GTK_TREE_VIEW(g_world_tree_widget
));
90 if (!gtk_tree_selection_get_selected(selection
, NULL
, &iter
))
96 GTK_TREE_MODEL(g_treestore
),
101 if (type
!= entry_type_app
)
111 void on_popup_menu_action_app_start(GtkWidget
* menuitem
, gpointer userdata
)
115 if (!get_selected_app_id(&id
))
120 log_info("start app %"PRIu64
, id
);
123 void on_popup_menu_action_app_stop(GtkWidget
* menuitem
, gpointer userdata
)
127 if (!get_selected_app_id(&id
))
132 log_info("stop app %"PRIu64
, id
);
135 void on_popup_menu_action_app_remove(GtkWidget
* menuitem
, gpointer userdata
)
139 if (!get_selected_app_id(&id
))
144 log_info("remove app %"PRIu64
, id
);
147 void popup_menu(GtkWidget
* treeview
, GdkEventButton
* event
)
149 GtkTreeSelection
* selection
;
152 GtkWidget
* menuitem
;
154 graph_view_handle view
;
160 selection
= gtk_tree_view_get_selection(GTK_TREE_VIEW(g_world_tree_widget
));
161 if (!gtk_tree_selection_get_selected(selection
, NULL
, &iter
))
167 GTK_TREE_MODEL(g_treestore
),
172 COL_RUNNING
, &running
,
173 COL_TERMINAL
, &terminal
,
176 if (type
!= entry_type_app
)
181 menu
= gtk_menu_new();
185 menuitem
= gtk_menu_item_new_with_label("Stop");
186 g_signal_connect(menuitem
, "activate", (GCallback
)on_popup_menu_action_app_stop
, NULL
);
187 gtk_menu_shell_append(GTK_MENU_SHELL(menu
), menuitem
);
191 menuitem
= gtk_menu_item_new_with_label("Start");
192 g_signal_connect(menuitem
, "activate", (GCallback
)on_popup_menu_action_app_start
, NULL
);
193 gtk_menu_shell_append(GTK_MENU_SHELL(menu
), menuitem
);
196 menuitem
= gtk_menu_item_new_with_label("Remove");
197 g_signal_connect(menuitem
, "activate", (GCallback
)on_popup_menu_action_app_remove
, NULL
);
198 gtk_menu_shell_append(GTK_MENU_SHELL(menu
), menuitem
);
200 gtk_widget_show_all(menu
);
202 /* Note: event can be NULL here when called from view_onPopupMenu;
203 * gdk_event_get_time() accepts a NULL argument */
204 gtk_menu_popup(GTK_MENU(menu
), NULL
, NULL
, NULL
, NULL
, (event
!= NULL
) ? event
->button
: 0, gdk_event_get_time((GdkEvent
*)event
));
207 gboolean
on_button_pressed(GtkWidget
* treeview
, GdkEventButton
* event
, gpointer userdata
)
209 /* single click with the right mouse button? */
210 if (event
->type
== GDK_BUTTON_PRESS
&& event
->button
== 3)
212 /* select row if no row is selected or only one other row is selected */
214 GtkTreeSelection
*selection
;
216 selection
= gtk_tree_view_get_selection(GTK_TREE_VIEW(treeview
));
218 /* Note: gtk_tree_selection_count_selected_rows() does not exist in gtk+-2.0, only in gtk+ >= v2.2 ! */
219 if (gtk_tree_selection_count_selected_rows(selection
) <= 1)
223 /* Get tree path for row that was clicked */
224 if (gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(treeview
), (gint
)event
->x
, (gint
)event
->y
, &path
, NULL
, NULL
, NULL
))
226 gtk_tree_selection_unselect_all(selection
);
227 gtk_tree_selection_select_path(selection
, path
);
228 gtk_tree_path_free(path
);
233 popup_menu(treeview
, event
);
235 return TRUE
; /* we handled this */
238 return FALSE
; /* we did not handle this */
241 gboolean
on_popup_menu(GtkWidget
* treeview
, gpointer userdata
)
243 popup_menu(treeview
, NULL
);
244 return TRUE
; /* we handled this */
247 void world_tree_init(void)
249 GtkTreeViewColumn
* col
;
250 GtkCellRenderer
* renderer
;
251 GtkTreeSelection
* selection
;
253 g_world_tree_widget
= get_glade_widget("world_tree");
254 gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(g_world_tree_widget
), FALSE
);
256 col
= gtk_tree_view_column_new();
257 gtk_tree_view_column_set_title(col
, "Name");
258 gtk_tree_view_append_column(GTK_TREE_VIEW(g_world_tree_widget
), col
);
259 renderer
= gtk_cell_renderer_text_new();
260 gtk_tree_view_column_pack_start(col
, renderer
, TRUE
);
261 gtk_tree_view_column_add_attribute(col
, renderer
, "text", COL_NAME
);
263 g_treestore
= gtk_tree_store_new(
272 gtk_tree_view_set_model(GTK_TREE_VIEW(g_world_tree_widget
), GTK_TREE_MODEL(g_treestore
));
274 selection
= gtk_tree_view_get_selection(GTK_TREE_VIEW(g_world_tree_widget
));
275 gtk_tree_selection_set_select_function(selection
, on_select
, NULL
, NULL
);
277 g_signal_connect(g_world_tree_widget
, "button-press-event", (GCallback
)on_button_pressed
, NULL
);
278 g_signal_connect(g_world_tree_widget
, "popup-menu", (GCallback
)on_popup_menu
, NULL
);
281 void world_tree_add(graph_view_handle view
, bool force_activate
)
285 gtk_tree_store_append(g_treestore
, &iter
, NULL
);
286 gtk_tree_store_set(g_treestore
, &iter
, COL_TYPE
, entry_type_view
, COL_VIEW
, view
, COL_NAME
, get_view_name(view
), -1);
288 /* select the first top level item */
289 if (force_activate
|| gtk_tree_model_iter_n_children(GTK_TREE_MODEL(g_treestore
), NULL
) == 1)
291 gtk_tree_selection_select_iter(gtk_tree_view_get_selection(GTK_TREE_VIEW(g_world_tree_widget
)), &iter
);
295 static bool find_view(graph_view_handle view
, GtkTreeIter
* iter_ptr
)
298 graph_view_handle view2
;
300 if (gtk_tree_model_get_iter_first(GTK_TREE_MODEL(g_treestore
), iter_ptr
))
304 gtk_tree_model_get(GTK_TREE_MODEL(g_treestore
), iter_ptr
, COL_TYPE
, &type
, COL_VIEW
, &view2
, -1);
305 if (type
== entry_type_view
&& view
== view2
)
310 while (gtk_tree_model_iter_next(GTK_TREE_MODEL(g_treestore
), iter_ptr
));
316 static bool find_app(graph_view_handle view
, uint64_t id
, GtkTreeIter
* view_iter_ptr
, GtkTreeIter
* app_iter_ptr
)
321 if (!find_view(view
, view_iter_ptr
))
326 if (!gtk_tree_model_iter_children(GTK_TREE_MODEL(g_treestore
), app_iter_ptr
, view_iter_ptr
))
333 gtk_tree_model_get(GTK_TREE_MODEL(g_treestore
), app_iter_ptr
, COL_TYPE
, &type
, COL_ID
, &id2
, -1);
334 if (type
== entry_type_app
&& id
== id2
)
339 while (gtk_tree_model_iter_next(GTK_TREE_MODEL(g_treestore
), app_iter_ptr
));
344 void world_tree_remove(graph_view_handle view
)
348 if (find_view(view
, &iter
))
350 gtk_tree_store_remove(g_treestore
, &iter
);
354 void world_tree_activate(graph_view_handle view
)
358 if (find_view(view
, &iter
))
360 gtk_tree_selection_select_iter(gtk_tree_view_get_selection(GTK_TREE_VIEW(g_world_tree_widget
)), &iter
);
364 void world_tree_name_changed(graph_view_handle view
)
368 if (find_view(view
, &iter
))
370 gtk_tree_store_set(g_treestore
, &iter
, COL_NAME
, get_view_name(view
), -1);
374 static char * get_app_name_string(const char * app_name
, bool running
, bool terminal
, uint8_t level
)
376 char * app_name_with_status
;
378 app_name_with_status
= catdup(running
? "" : "(inactive) ", app_name
);
379 if (app_name_with_status
== NULL
)
381 log_error("catdup failed for app name");
385 return app_name_with_status
;
388 void world_tree_add_app(graph_view_handle view
, uint64_t id
, const char * app_name
, bool running
, bool terminal
, uint8_t level
)
391 const char * view_name
;
394 char * app_name_with_status
;
396 if (!find_view(view
, &iter
))
402 path
= gtk_tree_model_get_path(GTK_TREE_MODEL(g_treestore
), &iter
);
404 gtk_tree_model_get(GTK_TREE_MODEL(g_treestore
), &iter
, COL_NAME
, &view_name
, -1);
406 log_info("adding app '%s' to '%s'", app_name
, view_name
);
408 app_name_with_status
= get_app_name_string(app_name
, running
, terminal
, level
);
409 if (app_name_with_status
== NULL
)
414 gtk_tree_store_append(g_treestore
, &child
, &iter
);
418 COL_TYPE
, entry_type_app
,
419 COL_NAME
, app_name_with_status
,
421 COL_RUNNING
, running
,
422 COL_TERMINAL
, terminal
,
425 gtk_tree_view_expand_row(GTK_TREE_VIEW(g_world_tree_widget
), path
, false);
427 free(app_name_with_status
);
429 gtk_tree_path_free(path
);
432 void world_tree_app_state_changed(graph_view_handle view
, uint64_t id
, const char * name
, bool running
, bool terminal
, uint8_t level
)
434 GtkTreeIter view_iter
;
435 GtkTreeIter app_iter
;
436 const char * view_name
;
437 const char * app_name
;
439 char * app_name_with_status
;
441 if (!find_app(view
, id
, &view_iter
, &app_iter
))
443 log_error("removed app not found");
447 path
= gtk_tree_model_get_path(GTK_TREE_MODEL(g_treestore
), &view_iter
);
449 gtk_tree_model_get(GTK_TREE_MODEL(g_treestore
), &view_iter
, COL_NAME
, &view_name
, -1);
450 gtk_tree_model_get(GTK_TREE_MODEL(g_treestore
), &app_iter
, COL_NAME
, &app_name
, -1);
452 log_info("changing app state '%s':'%s'", view_name
, app_name
);
454 app_name_with_status
= get_app_name_string(app_name
, running
, terminal
, level
);
455 if (app_name_with_status
== NULL
)
460 gtk_tree_view_expand_row(GTK_TREE_VIEW(g_world_tree_widget
), path
, false);
464 COL_NAME
, app_name_with_status
,
465 COL_RUNNING
, running
,
466 COL_TERMINAL
, terminal
,
470 free(app_name_with_status
);
472 gtk_tree_path_free(path
);
475 void world_tree_remove_app(graph_view_handle view
, uint64_t id
)
477 GtkTreeIter view_iter
;
478 GtkTreeIter app_iter
;
479 const char * view_name
;
480 const char * app_name
;
483 if (!find_app(view
, id
, &view_iter
, &app_iter
))
485 log_error("removed app not found");
489 path
= gtk_tree_model_get_path(GTK_TREE_MODEL(g_treestore
), &view_iter
);
491 gtk_tree_model_get(GTK_TREE_MODEL(g_treestore
), &view_iter
, COL_NAME
, &view_name
, -1);
492 gtk_tree_model_get(GTK_TREE_MODEL(g_treestore
), &app_iter
, COL_NAME
, &app_name
, -1);
494 log_info("removing app '%s' from '%s'", app_name
, view_name
);
496 gtk_tree_view_expand_row(GTK_TREE_VIEW(g_world_tree_widget
), path
, false);
497 gtk_tree_store_remove(g_treestore
, &app_iter
);
499 gtk_tree_path_free(path
);