From 0dc0d19a2fb0e2432308e988524d7610f93d11a5 Mon Sep 17 00:00:00 2001
From: Danny Auble <da@llnl.gov>
Date: Fri, 9 Oct 2009 21:49:58 +0000
Subject: [PATCH] a lot more eye candy, looks much better

---
 src/sview/block_info.c  |  34 ++++++++---
 src/sview/common.c      | 129 ++++++++++++++++++++++++++++------------
 src/sview/grid.c        |  67 +++++++++------------
 src/sview/job_info.c    |  30 +++++++---
 src/sview/node_info.c   | 121 ++++++++++++++++++++++++++++++-------
 src/sview/part_info.c   |  29 ++++++---
 src/sview/resv_info.c   |  30 +++++++---
 src/sview/submit_info.c |   7 ++-
 src/sview/sview.c       |  14 ++++-
 src/sview/sview.h       |  61 ++++++++++++-------
 10 files changed, 367 insertions(+), 155 deletions(-)

diff --git a/src/sview/block_info.c b/src/sview/block_info.c
index 042dad60e0c..56f044c1672 100644
--- a/src/sview/block_info.c
+++ b/src/sview/block_info.c
@@ -140,10 +140,10 @@ static display_data_t options_data_block[] = {
 	{G_TYPE_STRING, BLOCK_PAGE, "Put block in free state",
 	 TRUE, ADMIN_PAGE},
 	{G_TYPE_STRING, JOB_PAGE, "Jobs", TRUE, BLOCK_PAGE},
-	{G_TYPE_STRING, PART_PAGE, "Partition", TRUE, BLOCK_PAGE},
+	{G_TYPE_STRING, PART_PAGE, "Partitions", TRUE, BLOCK_PAGE},
 	{G_TYPE_STRING, NODE_PAGE, "Base Partitions", TRUE, BLOCK_PAGE},
 	//{G_TYPE_STRING, SUBMIT_PAGE, "Job Submit", FALSE, BLOCK_PAGE},
-	{G_TYPE_STRING, RESV_PAGE, "Reservation", TRUE, BLOCK_PAGE},
+	{G_TYPE_STRING, RESV_PAGE, "Reservations", TRUE, BLOCK_PAGE},
 	{G_TYPE_NONE, -1, NULL, FALSE, EDIT_NONE}
 };
 
@@ -934,7 +934,8 @@ display_it:
 		display_widget = NULL;
 	}
 	if(!display_widget) {
-		tree_view = create_treeview(local_display_data);
+		tree_view = create_treeview(local_display_data,
+					    &grid_button_list);
 		display_widget = gtk_widget_ref(GTK_WIDGET(tree_view));
 		gtk_table_attach_defaults(table, 
 					  GTK_WIDGET(tree_view),
@@ -1042,7 +1043,8 @@ display_it:
 		spec_info->display_widget = NULL;
 	}
 	if(spec_info->type != INFO_PAGE && !spec_info->display_widget) {
-		tree_view = create_treeview(local_display_data);
+		tree_view = create_treeview(local_display_data,
+					    &popup_win->grid_button_list);
 		spec_info->display_widget = 
 			gtk_widget_ref(GTK_WIDGET(tree_view));
 		gtk_table_attach_defaults(popup_win->table, 
@@ -1162,22 +1164,36 @@ end_it:
 	return;
 }
 
-extern void set_menus_block(void *arg, GtkTreePath *path, 
-			    GtkMenu *menu, int type)
+extern void set_menus_block(void *arg, void *arg2, GtkTreePath *path, int type)
 {
 	GtkTreeView *tree_view = (GtkTreeView *)arg;
 	popup_info_t *popup_win = (popup_info_t *)arg;
+	GtkMenu *menu = (GtkMenu *)arg2;
+	List button_list = (List)arg2;
+
 	switch(type) {
 	case TAB_CLICKED:
 		make_fields_menu(NULL, menu, display_data_block, SORTID_CNT);
 		break;
 	case ROW_CLICKED:
 		make_options_menu(tree_view, path, menu, options_data_block);
-		/* don't break, need to highlight */
+		break;
 	case ROW_LEFT_CLICKED:
-		highlight_grid(tree_view, path, 
-			       SORTID_NODE_INX, grid_button_list);
+		highlight_grid(tree_view, path, SORTID_NODE_INX, button_list);
 		break;
+	case FULL_CLICKED:
+	{
+		GtkTreeModel *model = gtk_tree_view_get_model(tree_view);
+		GtkTreeIter iter;
+		if (!gtk_tree_model_get_iter(model, &iter, path)) {
+			g_error("error getting iter from model\n");
+			break;
+		}		
+	
+		popup_all_block(model, &iter, INFO_PAGE);
+
+		break;
+	}
 	case POPUP_CLICKED:
 		make_fields_menu(popup_win, menu,
 				 popup_win->display_data, SORTID_CNT);
diff --git a/src/sview/common.c b/src/sview/common.c
index f872e487254..c1362a1e2be 100644
--- a/src/sview/common.c
+++ b/src/sview/common.c
@@ -624,15 +624,23 @@ extern void create_page(GtkNotebook *notebook, display_data_t *display_data)
 
 }
 
-extern GtkTreeView *create_treeview(display_data_t *local)
+extern GtkTreeView *create_treeview(display_data_t *local, List *button_list)
 {
+	signal_params_t *signal_params = xmalloc(sizeof(signal_params));
 	GtkTreeView *tree_view = GTK_TREE_VIEW(gtk_tree_view_new());
 	local->user_data = NULL;
+
+	signal_params->display_data = local;
+	signal_params->button_list = button_list;
+	
 	g_signal_connect(G_OBJECT(tree_view), "button-press-event",
 			 G_CALLBACK(row_clicked),
-			 local);
+			 signal_params);
+	g_signal_connect(G_OBJECT(tree_view), "row-activated",
+			 G_CALLBACK(row_activated),
+			 signal_params);
 	gtk_widget_show(GTK_WIDGET(tree_view));
-	
+	list_push(signal_params_list, signal_params);
 	return tree_view;
 
 }
@@ -769,59 +777,95 @@ extern GtkTreeStore *create_treestore(GtkTreeView *tree_view,
 	return treestore;
 }
 
-extern void right_button_pressed(GtkTreeView *tree_view, 
-				 GtkTreePath *path,
-				 GdkEventButton *event, 
-				 const display_data_t *display_data,
-				 int type)
+extern gboolean right_button_pressed(GtkTreeView *tree_view, 
+				     GtkTreePath *path,
+				     GdkEventButton *event, 
+				     const signal_params_t *signal_params,
+				     int type)
 {
-	if(event->button == 3) {
-		GtkMenu *menu = GTK_MENU(gtk_menu_new());
+	GtkMenu *menu = GTK_MENU(gtk_menu_new());
+	display_data_t *display_data = signal_params->display_data;
 	
-		(display_data->set_menu)(tree_view, path, menu, type);
-				
-		gtk_widget_show_all(GTK_WIDGET(menu));
-		gtk_menu_popup(menu, NULL, NULL, NULL, NULL,
-			       (event != NULL) ? event->button : 0,
-			       gdk_event_get_time((GdkEvent*)event));
-	}
+	/* These next 2 functions are there to keep the keyboard in
+	   sync */
+	gtk_tree_view_set_cursor(tree_view, path, NULL, false);
+	gtk_widget_grab_focus(GTK_WIDGET(tree_view));
+
+	/* highlight the nodes from this row */
+	(display_data->set_menu)(tree_view, *signal_params->button_list,
+				 path, ROW_LEFT_CLICKED);
+
+	(display_data->set_menu)(tree_view, menu, path, type);
+	
+	gtk_widget_show_all(GTK_WIDGET(menu));
+	gtk_menu_popup(menu, NULL, NULL, NULL, NULL,
+		       (event != NULL) ? event->button : 0,
+		       gdk_event_get_time((GdkEvent*)event));
+	return true;
 }
 
 extern gboolean left_button_pressed(GtkTreeView *tree_view, 
 				    GtkTreePath *path,
-				    GdkEventButton *event, 
-				    const display_data_t *display_data,
-				    int type)
+				    const signal_params_t *signal_params)
 {
 	static time_t last_time = 0;
 	time_t now = time(NULL);
 	gboolean rc = false;
-
-	if(event->button != 1)
-		return false;
-
-	if(!(now-last_time)) {
+	GtkTreeIter iter;
+	GtkTreeModel *model = gtk_tree_view_get_model(tree_view);
+	display_data_t *display_data = signal_params->display_data;
+	static gpointer *last_user_data = NULL;
+	
+	/* These next 2 functions are there to keep the keyboard in
+	   sync */
+	gtk_tree_view_set_cursor(tree_view, path, NULL, false);
+	gtk_widget_grab_focus(GTK_WIDGET(tree_view));
+
+	/* highlight the nodes from this row */
+	(display_data->set_menu)(tree_view, *signal_params->button_list,
+				 path, ROW_LEFT_CLICKED);
+	
+	/* make sure it was a double click */
+	if (!gtk_tree_model_get_iter(model, &iter, path)) {
+		g_error("error getting iter from model\n");
+		return rc;
+	}		
+	if(!(now-last_time) 
+	   && (!last_user_data || (iter.user_data == last_user_data))) {
 		/* double click */
-		rc = true;
-	} else if(event->button == 1) {
-		/* highlight the nodes from this row */
-		(display_data->set_menu)(tree_view, path, 
-					 NULL, ROW_LEFT_CLICKED);
-		if(!admin_mode)
-			rc = true;
+		(display_data->set_menu)(tree_view, NULL, path, FULL_CLICKED); 
 	}
+	last_user_data = iter.user_data;
+
+	if(!admin_mode)
+		rc = true;
 
 	last_time = now;
 
 	return rc;
 }
 
+extern gboolean row_activated(GtkTreeView *tree_view, GtkTreePath *path,
+			      GtkTreeViewColumn *column,
+			      const signal_params_t *signal_params)
+{
+	display_data_t *display_data = signal_params->display_data;
+	/* highlight the nodes from this row */
+	(display_data->set_menu)(tree_view, *signal_params->button_list,
+				 path, ROW_LEFT_CLICKED);
+	/* display the full info */
+	(display_data->set_menu)(tree_view, NULL, path, FULL_CLICKED);
+		
+	return false;
+}
+
 extern gboolean row_clicked(GtkTreeView *tree_view, GdkEventButton *event, 
-			    const display_data_t *display_data)
+			    const signal_params_t *signal_params)
 {
 	GtkTreePath *path = NULL;
 	GtkTreeSelection *selection = NULL;
 	gboolean did_something = FALSE;
+
 	if(!gtk_tree_view_get_path_at_pos(tree_view,
 					  (gint) event->x, 
 					  (gint) event->y,
@@ -843,12 +887,12 @@ extern gboolean row_clicked(GtkTreeView *tree_view, GdkEventButton *event,
 		did_something = FALSE;
 	} else if(event->button == 1) {
 		/*  left click */
-		did_something = left_button_pressed(tree_view, path, event, 
-						    display_data, ROW_CLICKED);
+		did_something = left_button_pressed(
+			tree_view, path, signal_params);
 	} else if(event->button == 3) {
 		/*  right click */
 		right_button_pressed(tree_view, path, event, 
-				     display_data, ROW_CLICKED);
+				     signal_params, ROW_CLICKED);
 		did_something = TRUE;
 	} else if(!admin_mode)
 		did_something = TRUE;
@@ -974,9 +1018,9 @@ extern void redo_popup(GtkWidget *widget, GdkEventButton *event,
 	if(event->button == 3) {
 		GtkMenu *menu = GTK_MENU(gtk_menu_new());
 		
-		(popup_win->display_data->set_menu)(popup_win, 
+		(popup_win->display_data->set_menu)(popup_win, menu, 
 						    NULL, 
-						    menu, POPUP_CLICKED);
+						    POPUP_CLICKED);
 		
 		gtk_widget_show_all(GTK_WIDGET(menu));
 		gtk_menu_popup(menu, NULL, NULL, NULL, NULL,
@@ -1053,6 +1097,15 @@ extern void destroy_popup_info(void *arg)
 	
 }
 
+extern void destroy_signal_params(void *arg)
+{
+	signal_params_t *signal_params = (signal_params_t *)arg;
+	
+	if(signal_params) {
+		xfree(signal_params);
+	}
+}
+
 extern gboolean delete_popup(GtkWidget *widget, GtkWidget *event, char *title)
 {
 	ListIterator itr = list_iterator_create(popup_list);
diff --git a/src/sview/grid.c b/src/sview/grid.c
index b239d416308..dea38b24ab5 100644
--- a/src/sview/grid.c
+++ b/src/sview/grid.c
@@ -102,40 +102,13 @@ static gboolean _mouseoff_node(GtkWidget *widget, GdkEventButton *event,
 static gboolean _open_node(GtkWidget *widget, GdkEventButton *event, 
 			   grid_button_t *grid_button)
 {
-	GError *error = NULL;
-	char title[100];
-	ListIterator itr = NULL;
-	popup_info_t *popup_win = NULL;
-
-#ifdef HAVE_BG
-	snprintf(title, 100, 
-		 "Info about base partition %s", grid_button->node_name);
-#else
-	snprintf(title, 100, "Info about node %s", grid_button->node_name);
-#endif
-	itr = list_iterator_create(popup_list);
-	while((popup_win = list_next(itr))) {
-		if(popup_win->spec_info)
-			if(!strcmp(popup_win->spec_info->title, title)) {
-				break;
-			} 
+	if(event->button == 1) {
+		popup_all_node_name(grid_button->node_name, INFO_PAGE);
+	} else if(event->button == 3) {
+		/* right click */
+		admin_menu_node_name(grid_button->node_name, event);
 	}
-	list_iterator_destroy(itr);
 
-	if(!popup_win) {
-		popup_win = create_popup_info(INFO_PAGE, NODE_PAGE, title);
-		popup_win->spec_info->search_info->gchar_data =
-			g_strdup(grid_button->node_name);
-		if (!g_thread_create((gpointer)popup_thr, popup_win,
-				     FALSE, &error))
-		{
-			g_printerr ("Failed to create grid popup thread: "
-				    "%s\n", 
-				    error->message);
-			return false;
-		}	
-	} else
-		gtk_window_present(GTK_WINDOW(popup_win->popup));
 	return false;
 }
 
@@ -519,6 +492,7 @@ extern void highlight_grid(GtkTreeView *tree_view, GtkTreePath *path,
 	GtkTreeModel *model = gtk_tree_view_get_model(tree_view);
 	GtkTreeIter iter;
 	int *node_inx = NULL;
+/* 	static int *last_node_inx = NULL; */
 	int j=0;	       
 				
 	if(!button_list)
@@ -535,21 +509,32 @@ extern void highlight_grid(GtkTreeView *tree_view, GtkTreePath *path,
 
 	itr = list_iterator_create(button_list);
 	while((grid_button = list_next(itr))) {
-		/* clear everyone else */
-		gtk_widget_set_state(grid_button->button, GTK_STATE_NORMAL);
-		
 		if((node_inx[j] < 0) 
 		   || (grid_button->inx < node_inx[j])
-		   || (grid_button->inx > node_inx[j+1]))
+		   || (grid_button->inx > node_inx[j+1])) {
+			/* clear everyone else */
+			if((GTK_WIDGET_STATE(grid_button->button)
+			    != GTK_STATE_NORMAL))
+				gtk_widget_set_state(grid_button->button,
+						     GTK_STATE_NORMAL);
 			continue;
-		/* highlight this one */
+		}
+		/* highlight this one, if it is already hightlighted,
+		 * put it back to normal */
 		//g_print("highlighting %d\n", grid_button->inx);
-		gtk_widget_set_state(grid_button->button, GTK_STATE_PRELIGHT);
+		if((GTK_WIDGET_STATE(grid_button->button)
+		    != GTK_STATE_PRELIGHT))
+			gtk_widget_set_state(grid_button->button,
+					     GTK_STATE_PRELIGHT);
+/* 		else if(last_node_inx && (last_node_inx == node_inx)) */
+/* 			gtk_widget_set_state(grid_button->button, */
+/* 					     GTK_STATE_NORMAL); */
+			
 		if(grid_button->inx == node_inx[j+1])
 			j+=2;
 	}
 	list_iterator_destroy(itr);
-
+//	last_node_inx = node_inx;
 	return;
 }
 
@@ -608,6 +593,7 @@ extern void get_button_list_from_main(List *button_list, int start, int end,
 		send_grid_button = create_grid_button_from_another(
 			grid_button, grid_button->node_name, color_inx);
 		if(send_grid_button) {
+			send_grid_button->button_list = *button_list;
 			_add_button_signals(send_grid_button);
 			list_append(*button_list, send_grid_button);
 		}
@@ -628,6 +614,7 @@ extern List copy_main_button_list(int initial_color)
 		send_grid_button = create_grid_button_from_another(
 			grid_button, grid_button->node_name, initial_color);
 		if(send_grid_button) {
+			send_grid_button->button_list = button_list;
 			_add_button_signals(send_grid_button);
 			send_grid_button->used = false;
 			list_append(button_list, send_grid_button);
@@ -707,6 +694,7 @@ extern void add_extra_bluegene_buttons(List *button_list, int inx,
 			grid_button, nodes, *color_inx);
 		grid_button->state = orig_state;
 		if(send_grid_button) {
+			send_grid_button->button_list = *button_list;
 			send_grid_button->table_x = 0;
 			send_grid_button->table_y = coord_y++;
 			//_add_button_signals(send_grid_button);
@@ -732,6 +720,7 @@ extern void add_extra_bluegene_buttons(List *button_list, int inx,
 		send_grid_button = create_grid_button_from_another(
 			grid_button, grid_button->node_name, *color_inx);
 		if(send_grid_button) {
+			send_grid_button->button_list = *button_list;
 			send_grid_button->table_x = 0;
 			send_grid_button->table_y = coord_y++;
 			_add_button_signals(send_grid_button);
diff --git a/src/sview/job_info.c b/src/sview/job_info.c
index e5a6524f28b..b7c53742047 100644
--- a/src/sview/job_info.c
+++ b/src/sview/job_info.c
@@ -2793,7 +2793,8 @@ display_it:
 		display_widget = NULL;
 	}
 	if(!display_widget) {
-		tree_view = create_treeview(local_display_data);
+		tree_view = create_treeview(local_display_data,
+					    &grid_button_list);
 				
 		display_widget = gtk_widget_ref(GTK_WIDGET(tree_view));
 		gtk_table_attach_defaults(GTK_TABLE(table), 
@@ -2903,7 +2904,8 @@ display_it:
 	}
 	
 	if(spec_info->type != INFO_PAGE && !spec_info->display_widget) {
-		tree_view = create_treeview(local_display_data);
+		tree_view = create_treeview(local_display_data,
+					    &popup_win->grid_button_list);
 				
 		spec_info->display_widget = 
 			gtk_widget_ref(GTK_WIDGET(tree_view));
@@ -3045,22 +3047,36 @@ end_it:
 	return;
 }
 
-extern void set_menus_job(void *arg, GtkTreePath *path, 
-			  GtkMenu *menu, int type)
+extern void set_menus_job(void *arg, void *arg2, GtkTreePath *path, int type)
 {
 	GtkTreeView *tree_view = (GtkTreeView *)arg;
 	popup_info_t *popup_win = (popup_info_t *)arg;
+	GtkMenu *menu = (GtkMenu *)arg2;
+	List button_list = (List)arg2;
+
 	switch(type) {
 	case TAB_CLICKED:
 		make_fields_menu(NULL, menu, display_data_job, SORTID_CNT);
 		break;
 	case ROW_CLICKED:
 		make_options_menu(tree_view, path, menu, options_data_job);
-		/* don't break, need to highlight */
+		break;
 	case ROW_LEFT_CLICKED:
-		highlight_grid(tree_view, path, 
-			       SORTID_NODE_INX, grid_button_list);
+		highlight_grid(tree_view, path, SORTID_NODE_INX, button_list);
 		break;
+	case FULL_CLICKED:
+	{
+		GtkTreeModel *model = gtk_tree_view_get_model(tree_view);
+		GtkTreeIter iter;
+		if (!gtk_tree_model_get_iter(model, &iter, path)) {
+			g_error("error getting iter from model\n");
+			break;
+		}		
+	
+		popup_all_job(model, &iter, INFO_PAGE);
+
+		break;
+	}
 	case POPUP_CLICKED:
 		make_fields_menu(popup_win, menu,
 				 popup_win->display_data, SORTID_CNT);
diff --git a/src/sview/node_info.c b/src/sview/node_info.c
index 58328f29079..145238059eb 100644
--- a/src/sview/node_info.c
+++ b/src/sview/node_info.c
@@ -116,8 +116,8 @@ static display_data_t options_data_node[] = {
 #ifdef HAVE_BG
 	{G_TYPE_STRING, BLOCK_PAGE, "Blocks", TRUE, NODE_PAGE},
 #endif
-	{G_TYPE_STRING, PART_PAGE, "Partition", TRUE, NODE_PAGE},
-	{G_TYPE_STRING, RESV_PAGE, "Reservation", TRUE, NODE_PAGE},
+	{G_TYPE_STRING, PART_PAGE, "Partitions", TRUE, NODE_PAGE},
+	{G_TYPE_STRING, RESV_PAGE, "Reservations", TRUE, NODE_PAGE},
 	//{G_TYPE_STRING, SUBMIT_PAGE, "Job Submit", FALSE, NODE_PAGE},
 	{G_TYPE_NONE, -1, NULL, FALSE, EDIT_NONE}
 };
@@ -1002,7 +1002,8 @@ display_it:
 		display_widget = NULL;
 	}
 	if(!display_widget) {
-		tree_view = create_treeview(local_display_data);
+		tree_view = create_treeview(local_display_data,
+					    &grid_button_list);
 		
 		display_widget = gtk_widget_ref(GTK_WIDGET(tree_view));
 		gtk_table_attach_defaults(GTK_TABLE(table),
@@ -1086,7 +1087,8 @@ display_it:
 		spec_info->display_widget = NULL;
 	}
 	if(spec_info->type != INFO_PAGE && !spec_info->display_widget) {
-		tree_view = create_treeview(local_display_data);
+		tree_view = create_treeview(local_display_data,
+					    &popup_win->grid_button_list);
 		
 		spec_info->display_widget = 
 			gtk_widget_ref(GTK_WIDGET(tree_view));
@@ -1224,22 +1226,36 @@ end_it:
 	
 }
 
-extern void set_menus_node(void *arg, GtkTreePath *path, 
-			   GtkMenu *menu, int type)
+extern void set_menus_node(void *arg, void *arg2, GtkTreePath *path, int type)
 {
 	GtkTreeView *tree_view = (GtkTreeView *)arg;
 	popup_info_t *popup_win = (popup_info_t *)arg;
+	GtkMenu *menu = (GtkMenu *)arg2;
+/* 	List button_list = (List)arg2; */
+
 	switch(type) {
 	case TAB_CLICKED:
 		make_fields_menu(NULL, menu, display_data_node, SORTID_CNT);
 		break;
 	case ROW_CLICKED:
 		make_options_menu(tree_view, path, menu, options_data_node);
-		/* don't break, need to highlight */
+		break;
 	case ROW_LEFT_CLICKED:
-		/* highlight_grid(tree_view, path,  */
-/* 			       SORTID_NODE_INX, grid_button_list); */
+		//highlight_grid(tree_view, path, SORTID_NODE_INX, button_list);
 		break;
+	case FULL_CLICKED:
+	{
+		GtkTreeModel *model = gtk_tree_view_get_model(tree_view);
+		GtkTreeIter iter;
+		if (!gtk_tree_model_get_iter(model, &iter, path)) {
+			g_error("error getting iter from model\n");
+			break;
+		}		
+	
+		popup_all_node(model, &iter, INFO_PAGE);
+
+		break;
+	}
 	case POPUP_CLICKED:
 		make_fields_menu(popup_win, menu,
 				 popup_win->display_data, SORTID_CNT);
@@ -1252,6 +1268,15 @@ extern void set_menus_node(void *arg, GtkTreePath *path,
 extern void popup_all_node(GtkTreeModel *model, GtkTreeIter *iter, int id)
 {
 	char *name = NULL;
+
+	gtk_tree_model_get(model, iter, SORTID_NAME, &name, -1);
+	popup_all_node_name(name, id);
+	/* this name gets g_strdup'ed in the previous function */
+	g_free(name);
+}
+
+extern void popup_all_node_name(char *name, int id)
+{
 	char title[100];
 	ListIterator itr = NULL;
 	popup_info_t *popup_win = NULL;
@@ -1262,10 +1287,9 @@ extern void popup_all_node(GtkTreeModel *model, GtkTreeIter *iter, int id)
 #else
 	char *node = "node";
 #endif
-	gtk_tree_model_get(model, iter, SORTID_NAME, &name, -1);
 	switch(id) {
 	case JOB_PAGE:
-		snprintf(title, 100, "Jobs(s) with %s %s", node, name);
+		snprintf(title, 100, "Job(s) with %s %s", node, name);
 		break;
 	case PART_PAGE:
 		snprintf(title, 100, "Partition(s) with %s %s", node, name);
@@ -1300,7 +1324,7 @@ extern void popup_all_node(GtkTreeModel *model, GtkTreeIter *iter, int id)
 			popup_win = create_popup_info(id, NODE_PAGE, title);
 		else
 			popup_win = create_popup_info(NODE_PAGE, id, title);
-		popup_win->spec_info->search_info->gchar_data = name;
+		popup_win->spec_info->search_info->gchar_data = g_strdup(name);
 		if (!g_thread_create((gpointer)popup_thr, popup_win, 
 				     FALSE, &error))
 		{
@@ -1309,15 +1333,75 @@ extern void popup_all_node(GtkTreeModel *model, GtkTreeIter *iter, int id)
 				    error->message);
 			return;
 		}
-	} else {
-		g_free(name);
+	} else 
 		gtk_window_present(GTK_WINDOW(popup_win->popup));
+}
+
+static void _selected_page(GtkMenuItem *menuitem, 
+			   display_data_t *display_data)
+{
+	switch(display_data->extra) {
+	case NODE_PAGE:
+		popup_all_node_name(display_data->user_data, display_data->id);
+		break;
+	case ADMIN_PAGE:
+		admin_node_name(display_data->user_data,
+				NULL, display_data->name);
+		break;
+	default:
+		g_print("node got %d %d\n", display_data->extra,
+			display_data->id);
+	}
+
+}
+
+extern void admin_menu_node_name(char *name, GdkEventButton *event)
+{
+	GtkMenu *menu = GTK_MENU(gtk_menu_new());
+	display_data_t *display_data = options_data_node;
+	GtkWidget *menuitem;
+
+	while(display_data++) {
+		if(display_data->id == -1)
+			break;
+		if(!display_data->name)
+			continue;
+		
+		display_data->user_data = name;
+		menuitem = gtk_menu_item_new_with_label(display_data->name); 
+		g_signal_connect(menuitem, "activate",
+				 G_CALLBACK(_selected_page), 
+				 display_data);
+		gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
 	}
+	gtk_widget_show_all(GTK_WIDGET(menu));
+	gtk_menu_popup(menu, NULL, NULL, NULL, NULL,
+		       (event != NULL) ? event->button : 0,
+		       gdk_event_get_time((GdkEvent*)event));
 }
 
 extern void admin_node(GtkTreeModel *model, GtkTreeIter *iter, char *type)
 {
 	char *name = NULL;
+	char *old_features = NULL;
+
+	gtk_tree_model_get(model, iter, SORTID_NAME, &name, -1);
+	if(!strcasecmp("Update Features", type))  /* get old features */
+		gtk_tree_model_get(model, iter, SORTID_FEATURES,
+				   &old_features, -1);
+		
+	admin_node_name(name, old_features, type);
+
+	if(name)
+		g_free(name);
+	if(old_features)
+		g_free(old_features);	
+
+	return;
+}
+
+extern void admin_node_name(char *name, char *old_features, char *type)
+{
 	GtkWidget *popup = gtk_dialog_new_with_buttons(
 		type,
 		GTK_WINDOW(main_window),
@@ -1325,18 +1409,11 @@ extern void admin_node(GtkTreeModel *model, GtkTreeIter *iter, char *type)
 		NULL);
 	gtk_window_set_transient_for(GTK_WINDOW(popup), NULL);
 
-	gtk_tree_model_get(model, iter, SORTID_NAME, &name, -1);
-		
 	if(!strcasecmp("Update Features", type)) { /* update features */
-		char *old_features = NULL;
-		gtk_tree_model_get(model, iter, SORTID_FEATURES,
-				   &old_features, -1);
 		update_features_node(GTK_DIALOG(popup), name, old_features);
-		g_free(old_features);
-
 	} else /* something that has to deal with a node state change */
 		update_state_node(GTK_DIALOG(popup), name, type);
-	g_free(name);
+
 	gtk_widget_destroy(popup);
 		
 	return;
diff --git a/src/sview/part_info.c b/src/sview/part_info.c
index 78d852877ba..423d3934796 100644
--- a/src/sview/part_info.c
+++ b/src/sview/part_info.c
@@ -1880,7 +1880,8 @@ display_it:
 		display_widget = NULL;
 	}
 	if(!display_widget) {
-		tree_view = create_treeview(local_display_data);
+		tree_view = create_treeview(local_display_data,
+					    &grid_button_list);
 
 		display_widget = gtk_widget_ref(GTK_WIDGET(tree_view));
 		gtk_table_attach_defaults(table,
@@ -2009,7 +2010,8 @@ display_it:
 	}
 	
 	if(spec_info->type != INFO_PAGE && !spec_info->display_widget) {
-		tree_view = create_treeview(local_display_data);
+		tree_view = create_treeview(local_display_data,
+					    &popup_win->grid_button_list);
 		
 		spec_info->display_widget = 
 			gtk_widget_ref(GTK_WIDGET(tree_view));
@@ -2092,11 +2094,12 @@ end_it:
 	return;
 }
 
-extern void set_menus_part(void *arg, GtkTreePath *path, 
-			   GtkMenu *menu, int type)
+extern void set_menus_part(void *arg, void *arg2, GtkTreePath *path, int type)
 {
 	GtkTreeView *tree_view = (GtkTreeView *)arg;
 	popup_info_t *popup_win = (popup_info_t *)arg;
+	GtkMenu *menu = (GtkMenu *)arg2;
+	List button_list = (List)arg2;
 
 	switch(type) {
 	case TAB_CLICKED:
@@ -2104,11 +2107,23 @@ extern void set_menus_part(void *arg, GtkTreePath *path,
 		break;
 	case ROW_CLICKED:
 		make_options_menu(tree_view, path, menu, options_data_part);
-		/* don't break, need to highlight */
+		break;
 	case ROW_LEFT_CLICKED:
-		highlight_grid(tree_view, path, 
-			       SORTID_NODE_INX, grid_button_list);
+		highlight_grid(tree_view, path, SORTID_NODE_INX, button_list);
+		break;
+	case FULL_CLICKED:
+	{
+		GtkTreeModel *model = gtk_tree_view_get_model(tree_view);
+		GtkTreeIter iter;
+		if (!gtk_tree_model_get_iter(model, &iter, path)) {
+			g_error("error getting iter from model\n");
+			break;
+		}		
+	
+		popup_all_part(model, &iter, INFO_PAGE);
+
 		break;
+	}
 	case POPUP_CLICKED:
 		make_fields_menu(popup_win, menu,
 				 popup_win->display_data, SORTID_CNT);
diff --git a/src/sview/resv_info.c b/src/sview/resv_info.c
index 56b68288a06..3f3f59ea780 100644
--- a/src/sview/resv_info.c
+++ b/src/sview/resv_info.c
@@ -996,7 +996,8 @@ display_it:
 		display_widget = NULL;
 	}
 	if(!display_widget) {
-		tree_view = create_treeview(local_display_data);
+		tree_view = create_treeview(local_display_data,
+					    &grid_button_list);
 
 		display_widget = gtk_widget_ref(GTK_WIDGET(tree_view));
 		gtk_table_attach_defaults(table,
@@ -1080,7 +1081,8 @@ display_it:
 		spec_info->display_widget = NULL;
 	}
 	if(spec_info->type != INFO_PAGE && !spec_info->display_widget) {
-		tree_view = create_treeview(local_display_data);
+		tree_view = create_treeview(local_display_data,
+					    &popup_win->grid_button_list);
 		spec_info->display_widget = 
 			gtk_widget_ref(GTK_WIDGET(tree_view));
 		gtk_table_attach_defaults(popup_win->table, 
@@ -1172,22 +1174,36 @@ end_it:
 	return;
 }
 
-extern void set_menus_resv(void *arg, GtkTreePath *path, 
-			   GtkMenu *menu, int type)
+extern void set_menus_resv(void *arg, void *arg2, GtkTreePath *path, int type)
 {
 	GtkTreeView *tree_view = (GtkTreeView *)arg;
 	popup_info_t *popup_win = (popup_info_t *)arg;
+	GtkMenu *menu = (GtkMenu *)arg2;
+	List button_list = (List)arg2;
+
 	switch(type) {
 	case TAB_CLICKED:
 		make_fields_menu(NULL, menu, display_data_resv, SORTID_CNT);
 		break;
 	case ROW_CLICKED:
 		make_options_menu(tree_view, path, menu, options_data_resv);
-		/* don't break, need to highlight */
+		break;
 	case ROW_LEFT_CLICKED:
-		highlight_grid(tree_view, path, 
-			       SORTID_NODE_INX, grid_button_list);
+		highlight_grid(tree_view, path, SORTID_NODE_INX, button_list);
 		break;
+	case FULL_CLICKED:
+	{
+		GtkTreeModel *model = gtk_tree_view_get_model(tree_view);
+		GtkTreeIter iter;
+		if (!gtk_tree_model_get_iter(model, &iter, path)) {
+			g_error("error getting iter from model\n");
+			break;
+		}		
+	
+		popup_all_resv(model, &iter, INFO_PAGE);
+
+		break;
+	}
 	case POPUP_CLICKED:
 		make_fields_menu(popup_win, menu,
 				 popup_win->display_data, SORTID_CNT);
diff --git a/src/sview/submit_info.c b/src/sview/submit_info.c
index d016ab12938..7495a18c761 100644
--- a/src/sview/submit_info.c
+++ b/src/sview/submit_info.c
@@ -70,11 +70,14 @@ extern void get_info_submit(GtkTable *table, display_data_t *display_data)
 }
 
 
-extern void set_menus_submit(void *arg, GtkTreePath *path, 
-			     GtkMenu *menu, int type)
+extern void set_menus_submit(void *arg, void *arg2,
+			     GtkTreePath *path, int type)
 {
 	GtkTreeView *tree_view = (GtkTreeView *)arg;
 	popup_info_t *popup_win = (popup_info_t *)arg;
+	GtkMenu *menu = (GtkMenu *)arg2;
+	/* List button_list = (List)arg2; */
+
 	switch(type) {
 	case TAB_CLICKED:
 		make_fields_menu(NULL, menu, display_data_submit, SORTID_CNT);
diff --git a/src/sview/sview.c b/src/sview/sview.c
index 6720607bf07..8b36c55c948 100644
--- a/src/sview/sview.c
+++ b/src/sview/sview.c
@@ -53,7 +53,8 @@ int fini = 0;
 int grid_init = 0;
 bool toggled = FALSE;
 bool force_refresh = FALSE;
-List popup_list;
+List popup_list = NULL;
+List signal_params_list = NULL;
 int page_running[PAGE_CNT];
 int global_sleep_time = 5;
 bool admin_mode = FALSE;
@@ -360,6 +361,8 @@ static gboolean _delete(GtkWidget *widget,
 		list_destroy(popup_list);
 	if(grid_button_list)
 		list_destroy(grid_button_list);
+	if(signal_params_list)
+		list_destroy(signal_params_list);
 	return FALSE;
 }
 
@@ -572,14 +575,18 @@ extern void refresh_main(GtkAction *action, gpointer user_data)
 }
 
 extern void tab_pressed(GtkWidget *widget, GdkEventButton *event, 
-			const display_data_t *display_data)
+			display_data_t *display_data)
 {
+	signal_params_t signal_params;
+	signal_params.display_data = display_data;
+	signal_params.button_list = &grid_button_list;
+
 	/* single click with the right mouse button? */
 	gtk_notebook_set_current_page(GTK_NOTEBOOK(main_notebook),
 				      display_data->extra);
 	if(event->button == 3) {
 		right_button_pressed(NULL, NULL, event, 
-				     display_data, TAB_CLICKED);
+				     &signal_params, TAB_CLICKED);
 	} 
 }
 
@@ -673,6 +680,7 @@ int main(int argc, char *argv[])
 	/* tell signal we are done adding */
 	adding = 0;
 	popup_list = list_create(destroy_popup_info);
+	signal_params_list = list_create(destroy_signal_params);
 	gtk_widget_show_all(main_window);
 
 	/* Finished! */
diff --git a/src/sview/sview.h b/src/sview/sview.h
index 4ef1debface..227dcf424aa 100644
--- a/src/sview/sview.h
+++ b/src/sview/sview.h
@@ -106,6 +106,7 @@ enum { JOB_PAGE,
 enum { TAB_CLICKED,
        ROW_LEFT_CLICKED,
        ROW_CLICKED,
+       FULL_CLICKED,
        POPUP_CLICKED
 };
 
@@ -185,9 +186,10 @@ struct display_data {
 			     gpointer data);
 	void (*get_info)    (GtkTable *table, display_data_t *display_data);
 	void (*specific)    (popup_info_t *popup_win);
-	void (*set_menu)    (void *arg, GtkTreePath *path,
-			     GtkMenu *menu, int type);
+	void (*set_menu)    (void *arg, void *arg2,
+			     GtkTreePath *path, int type);
 	gpointer user_data;
+	gpointer button_list;
 };
 
 typedef struct {
@@ -228,6 +230,9 @@ struct popup_info {
 
 typedef struct {
 	GtkWidget *button;
+	List button_list; /*list this grid_button exists in does not
+			   * need to be freed, should only be a
+			   * pointer to an existing list */
 	char *color;
 	int color_inx;
 	int inx;
@@ -248,6 +253,12 @@ typedef struct {
 	char *color;
 } sview_node_info_t;
 
+typedef struct {
+	display_data_t *display_data;
+	List *button_list;
+} signal_params_t;
+
+
 extern sview_parameters_t params;
 extern int text_line_cnt;
 
@@ -260,6 +271,7 @@ extern bool toggled;
 extern bool force_refresh;
 extern List popup_list;
 extern List grid_button_list;
+extern List signal_params_list;
 extern int global_sleep_time;
 extern bool admin_mode;
 extern GtkWidget *main_statusbar;
@@ -283,7 +295,7 @@ extern void print_date();
 //sview.c
 extern void refresh_main(GtkAction *action, gpointer user_data);
 extern void tab_pressed(GtkWidget *widget, GdkEventButton *event, 
-			const display_data_t *display_data);
+			display_data_t *display_data);
 
 //popups.c
 extern void create_config_popup(GtkAction *action, gpointer user_data);
@@ -329,8 +341,7 @@ extern void admin_edit_part(GtkCellRendererText *cell,
 extern int get_new_info_part(partition_info_msg_t **part_ptr, int force);
 extern void get_info_part(GtkTable *table, display_data_t *display_data);
 extern void specific_info_part(popup_info_t *popup_win);
-extern void set_menus_part(void *arg, GtkTreePath *path, 
-			   GtkMenu *menu, int type);
+extern void set_menus_part(void *arg, void *arg2, GtkTreePath *path, int type);
 extern void popup_all_part(GtkTreeModel *model, GtkTreeIter *iter, int id);
 extern void admin_part(GtkTreeModel *model, GtkTreeIter *iter, char *type);
 
@@ -346,8 +357,7 @@ extern void admin_edit_block(GtkCellRendererText *cell,
 extern int get_new_info_block(block_info_msg_t **block_ptr, int force);
 extern void get_info_block(GtkTable *table, display_data_t *display_data);
 extern void specific_info_block(popup_info_t *popup_win);
-extern void set_menus_block(void *arg, GtkTreePath *path, 
-			    GtkMenu *menu, int type);
+extern void set_menus_block(void *arg, void *arg2, GtkTreePath *path, int type);
 extern void popup_all_block(GtkTreeModel *model, GtkTreeIter *iter, int id);
 extern void admin_block(GtkTreeModel *model, GtkTreeIter *iter, char *type);
 
@@ -363,8 +373,7 @@ extern int get_new_info_job_step(job_step_info_response_msg_t **info_ptr,
 				 int force);
 extern void get_info_job(GtkTable *table, display_data_t *display_data);
 extern void specific_info_job(popup_info_t *popup_win);
-extern void set_menus_job(void *arg, GtkTreePath *path, 
-			  GtkMenu *menu, int type);
+extern void set_menus_job(void *arg, void *arg2, GtkTreePath *path, int type);
 extern void popup_all_job(GtkTreeModel *model, GtkTreeIter *iter, int id);
 extern void admin_job(GtkTreeModel *model, GtkTreeIter *iter, char *type);
 
@@ -384,10 +393,12 @@ extern void admin_edit_node(GtkCellRendererText *cell,
 extern int get_new_info_node(node_info_msg_t **info_ptr, int force);
 extern void get_info_node(GtkTable *table, display_data_t *display_data);
 extern void specific_info_node(popup_info_t *popup_win);
-extern void set_menus_node(void *arg, GtkTreePath *path, 
-			   GtkMenu *menu, int type);
+extern void set_menus_node(void *arg, void *arg2, GtkTreePath *path, int type);
 extern void popup_all_node(GtkTreeModel *model, GtkTreeIter *iter, int id);
+extern void popup_all_node_name(char *name, int id);
+extern void admin_menu_node_name(char *name, GdkEventButton *event);
 extern void admin_node(GtkTreeModel *model, GtkTreeIter *iter, char *type);
+extern void admin_node_name(char *name, char *old_features, char *type);
 
 // resv_info.c
 extern void refresh_resv(GtkAction *action, gpointer user_data);
@@ -399,16 +410,15 @@ extern void admin_edit_resv(GtkCellRendererText *cell,
 extern int get_new_info_resv(reserve_info_msg_t **info_ptr, int force);
 extern void get_info_resv(GtkTable *table, display_data_t *display_data);
 extern void specific_info_resv(popup_info_t *popup_win);
-extern void set_menus_resv(void *arg, GtkTreePath *path, 
-			   GtkMenu *menu, int type);
+extern void set_menus_resv(void *arg, void *arg2, GtkTreePath *path, int type);
 extern void popup_all_resv(GtkTreeModel *model, GtkTreeIter *iter, int id);
 extern void admin_resv(GtkTreeModel *model, GtkTreeIter *iter, char *type);
 
 
 // submit_info.c
 extern void get_info_submit(GtkTable *table, display_data_t *display_data);
-extern void set_menus_submit(void *arg, GtkTreePath *path, 
-			     GtkMenu *menu, int type);
+extern void set_menus_submit(void *arg, void *arg2,
+			     GtkTreePath *path, int type);
 // common.c
 extern int get_row_number(GtkTreeView *tree_view, GtkTreePath *path);
 extern int find_col(display_data_t *display_data, int type);
@@ -421,28 +431,37 @@ extern void make_options_menu(GtkTreeView *tree_view, GtkTreePath *path,
 extern GtkScrolledWindow *create_scrolled_window();
 extern GtkWidget *create_entry();
 extern void create_page(GtkNotebook *notebook, display_data_t *display_data);
-extern GtkTreeView *create_treeview(display_data_t *local);
+extern GtkTreeView *create_treeview(display_data_t *local, List *button_list);
 extern GtkTreeView *create_treeview_2cols_attach_to_table(GtkTable *table);
 extern GtkTreeStore *create_treestore(GtkTreeView *tree_view, 
 				      display_data_t *display_data,
 				      int count, int sort_column,
 				      int color_column);
 
-extern void right_button_pressed(GtkTreeView *tree_view, GtkTreePath *path, 
-				 GdkEventButton *event, 
-				 const display_data_t *display_data,
-				 int type);
+extern gboolean right_button_pressed(GtkTreeView *tree_view, GtkTreePath *path, 
+				     GdkEventButton *event, 
+				     const signal_params_t *signal_params,
+				     int type);
+extern gboolean left_button_pressed(GtkTreeView *tree_view, 
+				    GtkTreePath *path,
+				    const signal_params_t *signal_params);
+extern gboolean row_activated(GtkTreeView *tree_view, GtkTreePath *path,
+			      GtkTreeViewColumn *column,
+			      const signal_params_t *signal_params);
 extern gboolean row_clicked(GtkTreeView *tree_view, GdkEventButton *event, 
-			    const display_data_t *display_data);
+			    const signal_params_t *signal_params);
 extern popup_info_t *create_popup_info(int type, int dest_type, char *title);
 extern void setup_popup_info(popup_info_t *popup_win, 
 			     display_data_t *display_data, 
 			     int cnt);
 extern void redo_popup(GtkWidget *widget, GdkEventButton *event, 
 		       popup_info_t *popup_win);
+
 extern void destroy_search_info(void *arg);
 extern void destroy_specific_info(void *arg);
 extern void destroy_popup_info(void *arg);
+extern void destroy_signal_params(void *arg);
+
 extern gboolean delete_popup(GtkWidget *widget, GtkWidget *event, char *title);
 extern void *popup_thr(popup_info_t *popup_win);
 extern void remove_old(GtkTreeModel *model, int updated);
-- 
GitLab