1 /*****************************************************************************\
2  *  common.c - common functions used by tabs in sview
3  *****************************************************************************
4  *  Copyright (C) 2004-2007 The Regents of the University of California.
5  *  Copyright (C) 2008-2009 Lawrence Livermore National Security.
6  *  Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER).
7  *  Written by Danny Auble <da@llnl.gov>
8  *
9  *  CODE-OCEC-09-009. All rights reserved.
10  *
11  *  This file is part of Slurm, a resource management program.
12  *  For details, see <https://slurm.schedmd.com/>.
13  *  Please also read the included file: DISCLAIMER.
14  *
15  *  Slurm is free software; you can redistribute it and/or modify it under
16  *  the terms of the GNU General Public License as published by the Free
17  *  Software Foundation; either version 2 of the License, or (at your option)
18  *  any later version.
19  *
20  *  Slurm is distributed in the hope that it will be useful, but WITHOUT ANY
21  *  WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
22  *  FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
23  *  details.
24  *
25  *  You should have received a copy of the GNU General Public License along
26  *  with Slurm; if not, write to the Free Software Foundation, Inc.,
27  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA.
28 \*****************************************************************************/
29 
30 #include "config.h"
31 
32 #include "src/sview/sview.h"
33 #include "src/common/parse_time.h"
34 #include <gdk/gdkkeysyms.h>
35 
36 #define TOPO_DEBUG 0
37 #define _DEBUG 0
38 static bool menu_right_pressed = false;
39 
40 typedef struct {
41 	display_data_t *display_data;
42 	void (*pfunc)(GtkTreeModel*, GtkTreeIter*, int);
43 	GtkTreeView  *tree_view;
44 } each_t;
45 
46 typedef struct {
47 	GtkTreeIter iter;
48 	GtkTreeModel *model;
49 	GtkTreeView  *treeview;
50 } treedata_t;
51 
52 static gboolean control_key_in_effect = false;
53 static gboolean enter_key_in_effect = false;
54 
_find_node_inx(char * name)55 static int _find_node_inx (char *name)
56 {
57 	int i;
58 
59 	if ((name == NULL) || (name[0] == '\0')) {
60 		info("_find_node_inx passed NULL name");
61 		return -1;
62 	}
63 
64 
65 	for (i = 0; i < g_node_info_ptr->record_count; i++) {
66 		if (g_node_info_ptr->node_array[i].name == NULL)
67 			continue;	/* Future node or other anomaly */
68 		if (!xstrcmp(name, g_node_info_ptr->node_array[i].name))
69 			return i;
70 	}
71 
72 	return -1;
73 }
74 
_display_topology(void)75 static void _display_topology(void)
76 {
77 	int i, one_liner = 1;
78 
79 	if (TOPO_DEBUG) {
80 		g_print("_display_topology,  record_count = %d\n",
81 			g_topo_info_msg_ptr->record_count);
82 	}
83 
84 	for (i = 0; i < g_topo_info_msg_ptr->record_count; i++) {
85 		slurm_print_topo_record(stdout,
86 					&g_topo_info_msg_ptr->topo_array[i],
87 					one_liner);
88 	}
89 }
90 
_foreach_popup_all(GtkTreeModel * model,GtkTreePath * path,GtkTreeIter * iter,gpointer userdata)91 static void _foreach_popup_all(GtkTreeModel  *model,
92 			       GtkTreePath   *path,
93 			       GtkTreeIter   *iter,
94 			       gpointer       userdata)
95 {
96 
97 	each_t *each = userdata;
98 	each->pfunc(model, iter, each->display_data->id);
99 }
100 
_foreach_full_info(GtkTreeModel * model,GtkTreePath * path,GtkTreeIter * iter,gpointer userdata)101 static void _foreach_full_info(GtkTreeModel  *model,
102 			       GtkTreePath   *path,
103 			       GtkTreeIter   *iter,
104 			       gpointer       userdata)
105 {
106 
107 	each_t *each = userdata;
108 	(each->display_data->set_menu)(each->tree_view, NULL, path,
109 				       FULL_CLICKED);
110 	popup_pos.x = popup_pos.slider + popup_pos.cntr * 10;
111 	popup_pos.y = popup_pos.cntr * 22;
112 	popup_pos.cntr++;
113 	if (popup_pos.cntr > 10) {
114 		popup_pos.cntr = 1;
115 		popup_pos.slider += 100;
116 	}
117 }
118 
119 /* These next 2 functions are here to make it so we don't magically
120  * click on something before we really want to in a menu.
121  */
_menu_button_pressed(GtkWidget * widget,GdkEventButton * event,gpointer extra)122 static gboolean _menu_button_pressed(GtkWidget *widget, GdkEventButton *event,
123 				     gpointer extra)
124 {
125 	if (event->button == 3) {
126 		menu_right_pressed = true;
127 		return true;
128 	}
129 	return false;
130 }
131 
_menu_button_released(GtkWidget * widget,GdkEventButton * event,gpointer extra)132 static gboolean _menu_button_released(GtkWidget *widget, GdkEventButton *event,
133 				      gpointer extra)
134 {
135 	if (event->button == 3 && !menu_right_pressed)
136 		return true;
137 	menu_right_pressed = false;
138 	return false;
139 }
140 
_frame_callback(GtkWindow * window,GdkEvent * event,gpointer data)141 static gboolean _frame_callback(GtkWindow *window,
142 				GdkEvent *event, gpointer data)
143 {
144 
145 	if (event->expose.send_event == 0) {
146 		default_sview_config.fi_popup_width = event->configure.width;
147 		default_sview_config.fi_popup_height = event->configure.height;
148 		working_sview_config.fi_popup_width = event->configure.width;
149 		working_sview_config.fi_popup_height = event->configure.height;
150 
151 		ListIterator itr = list_iterator_create(popup_list);
152 		popup_info_t *popup_win = NULL;
153 
154 		while ((popup_win = list_next(itr))) {
155 			gtk_window_resize(GTK_WINDOW(popup_win->popup),
156 					  working_sview_config.fi_popup_width,
157 					  working_sview_config.fi_popup_height);
158 		}
159 		list_iterator_destroy(itr);
160 	}
161 
162 
163 	return false;
164 }
165 
_handle_response(GtkDialog * dialog,gint response_id,popup_info_t * popup_win)166 static void _handle_response(GtkDialog *dialog, gint response_id,
167 			     popup_info_t *popup_win)
168 {
169 
170 	switch(response_id) {
171 	case GTK_RESPONSE_OK: //refresh
172 		(popup_win->display_data->refresh)(NULL, popup_win);
173 		break;
174 	case GTK_RESPONSE_DELETE_EVENT: // exit
175 	case GTK_RESPONSE_CLOSE: // close
176 		delete_popup(NULL, NULL, popup_win->spec_info->title);
177 		break;
178 	case GTK_RESPONSE_CANCEL: // cancel
179 		delete_popups();
180 		break;
181 	default:
182 		g_print("handle unknown response %d\n", response_id);
183 		break;
184 	}
185 	return;
186 }
187 
_sort_iter_compare_func_char(GtkTreeModel * model,GtkTreeIter * a,GtkTreeIter * b,gpointer userdata)188 static int _sort_iter_compare_func_char(GtkTreeModel *model,
189 					GtkTreeIter  *a,
190 					GtkTreeIter  *b,
191 					gpointer      userdata)
192 {
193 	int sortcol = GPOINTER_TO_INT(userdata);
194 	int ret = 0;
195 	int len1 = 0, len2 = 0;
196 	gchar *name1 = NULL, *name2 = NULL;
197 
198 	gtk_tree_model_get(model, a, sortcol, &name1, -1);
199 	gtk_tree_model_get(model, b, sortcol, &name2, -1);
200 
201 	if (!name1 && !name2)
202 		goto cleanup; /* both equal => ret = 0 */
203 	else if (!name1 || !name2) {
204 		ret = (name1 == NULL) ? -1 : 1;
205 	} else {
206 		/* sort like a human would
207 		   meaning snowflake2 would be greater than
208 		   snowflake12 */
209 		len1 = strlen(name1);
210 		len2 = strlen(name2);
211 		while ((ret < len1) && (!g_ascii_isdigit(name1[ret])))
212 			ret++;
213 		if (ret < len1) {
214 			if (!g_ascii_strncasecmp(name1, name2, ret)) {
215 				if (len1 > len2)
216 					ret = 1;
217 				else if (len1 < len2)
218 					ret = -1;
219 				else
220 					ret = g_ascii_strcasecmp(name1, name2);
221 			} else
222 				ret = g_ascii_strcasecmp(name1, name2);
223 		} else
224 			ret = g_ascii_strcasecmp(name1, name2);
225 	}
226 cleanup:
227 	g_free(name1);
228 	g_free(name2);
229 
230 	return ret;
231 }
232 
_sort_iter_compare_func_int(GtkTreeModel * model,GtkTreeIter * a,GtkTreeIter * b,gpointer userdata)233 static int _sort_iter_compare_func_int(GtkTreeModel *model,
234 				       GtkTreeIter  *a,
235 				       GtkTreeIter  *b,
236 				       gpointer      userdata)
237 {
238 	int sortcol = GPOINTER_TO_INT(userdata);
239 	int ret = 0;
240 	gint int1, int2;
241 
242 	gtk_tree_model_get(model, a, sortcol, &int1, -1);
243 	gtk_tree_model_get(model, b, sortcol, &int2, -1);
244 
245 	if (int1 != int2)
246 		ret = (int1 > int2) ? 1 : -1;
247 
248 	return ret;
249 }
250 
_sort_iter_compare_func_nodes(GtkTreeModel * model,GtkTreeIter * a,GtkTreeIter * b,gpointer userdata)251 static int _sort_iter_compare_func_nodes(GtkTreeModel *model,
252 					 GtkTreeIter  *a,
253 					 GtkTreeIter  *b,
254 					 gpointer      userdata)
255 {
256 	int sortcol = GPOINTER_TO_INT(userdata);
257 	int ret = 0;
258 	gchar *name1 = NULL, *name2 = NULL;
259 
260 	gtk_tree_model_get(model, a, sortcol, &name1, -1);
261 	gtk_tree_model_get(model, b, sortcol, &name2, -1);
262 
263 	if (!name1 && !name2)
264 		goto cleanup; /* both equal => ret = 0 */
265 	else if (!name1 || !name2)
266 		ret = (name1 == NULL) ? -1 : 1;
267 	else {
268 		uint64_t int1=0, int2=0, tmp_int;
269 		int spot=0;
270 		/* If this is in a mixed state we need to get them all */
271 		while (name1[spot]) {
272 			while (name1[spot]
273 			       && !g_ascii_isdigit(name1[spot])) {
274 				spot++;
275 			}
276 			if (!name1[spot])
277 				break;
278 			tmp_int = atoi(name1+spot);
279 			while (name1[spot] && g_ascii_isdigit(name1[spot])) {
280 				spot++;
281 			}
282 
283 			if (!name1[spot]) {
284 			} else if (name1[spot] == 'K')
285 				tmp_int *= 1024;
286 			else if (name1[spot] == 'M')
287 				tmp_int *= 1048576;
288 			else if (name1[spot] == 'G')
289 				tmp_int *= 1073741824;
290 
291 			int1 += tmp_int;
292 		}
293 
294 		spot=0;
295 		while (name2[spot]) {
296 			while (name2[spot]
297 			       && !g_ascii_isdigit(name2[spot])) {
298 				spot++;
299 			}
300 			if (!name2[spot])
301 				break;
302 			tmp_int = atoi(name2+spot);
303 			while (name2[spot] && g_ascii_isdigit(name2[spot])) {
304 				spot++;
305 			}
306 			if (!name2[spot]) {
307 			} else if (name2[spot] == 'K')
308 				tmp_int *= 1024;
309 			else if (name2[spot] == 'M')
310 				tmp_int *= 1048576;
311 			else if (name2[spot] == 'G')
312 				tmp_int *= 1073741824;
313 
314 			int2 += tmp_int;
315 		}
316 
317 		if (int1 != int2)
318 			ret = (int1 > int2) ? 1 : -1;
319 	}
320 cleanup:
321 	g_free(name1);
322 	g_free(name2);
323 
324 	return ret;
325 }
326 
_editing_started(GtkCellRenderer * cell,GtkCellEditable * editable,const gchar * path,gpointer data)327 static void _editing_started(GtkCellRenderer *cell,
328 			     GtkCellEditable *editable,
329 			     const gchar     *path,
330 			     gpointer         data)
331 {
332 	gdk_threads_leave();
333 	g_mutex_lock(sview_mutex);
334 }
335 
_editing_canceled(GtkCellRenderer * cell,gpointer data)336 static void _editing_canceled(GtkCellRenderer *cell,
337 			      gpointer         data)
338 {
339 	g_mutex_unlock(sview_mutex);
340 }
341 
_editing_thr(gpointer arg)342 static void *_editing_thr(gpointer arg)
343 {
344 	int msg_id = 0;
345 	sleep(5);
346 	gdk_threads_enter();
347 	msg_id = GPOINTER_TO_INT(arg);
348 	gtk_statusbar_remove(GTK_STATUSBAR(main_statusbar),
349 			     STATUS_ADMIN_EDIT, msg_id);
350 	//gdk_flush();
351 	gdk_threads_leave();
352 	return NULL;
353 }
354 
_cell_data_func(GtkTreeViewColumn * col,GtkCellRenderer * renderer,GtkTreeModel * model,GtkTreeIter * iter,gpointer data)355 static void _cell_data_func(GtkTreeViewColumn *col,
356 			    GtkCellRenderer *renderer,
357 			    GtkTreeModel *model,
358 			    GtkTreeIter *iter,
359 			    gpointer data)
360 {
361 	GdkPixbuf *pixbuf = NULL;
362 	char *color_char, *color_char2;
363 	uint32_t color;
364 
365 	g_object_get(renderer, "pixbuf", &pixbuf, NULL);
366 	if (!pixbuf)
367 		return;
368 
369 	gtk_tree_model_get(model, iter,
370 			   GPOINTER_TO_INT(g_object_get_data(G_OBJECT(renderer),
371 							     "column")),
372 			   &color_char, -1);
373 	if (!color_char)
374 		return;
375 
376 	color_char2 = color_char+1;
377 	color = strtoul(color_char2, (char **)&color_char2, 16);
378 	g_free(color_char);
379 
380 	/* we need to shift over 2 spots for the alpha */
381 	gdk_pixbuf_fill(pixbuf, color << 8);
382 	/* This only has to be done once, but I can't find any way to
383 	 * set something to only make it happen once.  It only takes
384 	 * 3-5 usecs to do it so I didn't worry about it doing it
385 	 * multiple times.  If you can figure out how to make this
386 	 * happen only once please fix, but the pointers for the col,
387 	 * renderer, and pixbuf are all the same.  You could put in
388 	 * some think in the tree_model, but that seemed a bit more
389 	 * cumbersome. - da
390 	 */
391 }
392 
_add_col_to_treeview(GtkTreeView * tree_view,display_data_t * display_data,int color_column)393 static void _add_col_to_treeview(GtkTreeView *tree_view,
394 				 display_data_t *display_data, int color_column)
395 {
396 	GtkTreeViewColumn *col;
397 	GtkListStore *model;
398 	GtkCellRenderer *renderer = NULL;
399 
400 	/* Since some systems have different default columns (some
401 	 * which aren't displayed on all types of clusters only add a
402 	 * column if there is a name for it. */
403 	if (!display_data->name && (display_data->extra != EDIT_COLOR))
404 		return;
405 
406 	col = gtk_tree_view_column_new();
407 	model = (display_data->create_model)(display_data->id);
408 
409 	if (model && display_data->extra != EDIT_NONE) {
410 		renderer = gtk_cell_renderer_combo_new();
411 		g_object_set(renderer,
412 			     "model", model,
413 			     "text-column", 0,
414 			     "has-entry", 1,
415 			     "editable", true,
416 			     NULL);
417 	} else if (display_data->extra == EDIT_TEXTBOX) {
418 		renderer = gtk_cell_renderer_text_new();
419 		g_object_set(renderer,
420 			     "editable", true,
421 			     NULL);
422 	} else if (display_data->extra == EDIT_COLOR) {
423 		GdkPixbuf *pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, false,
424 						   8, 10, 20);
425 		renderer = gtk_cell_renderer_pixbuf_new();
426 		g_object_set(renderer, "pixbuf", pixbuf, NULL);
427 		g_object_unref(pixbuf);
428 	} else
429 		renderer = gtk_cell_renderer_text_new();
430 
431 	if (model)
432 		g_object_unref(model);
433 
434 	gtk_tree_view_column_pack_start(col, renderer, true);
435 
436 	g_object_set_data(G_OBJECT(renderer), "column",
437 			  GINT_TO_POINTER(display_data->id));
438 
439 	if (display_data->extra == EDIT_COLOR) {
440 		gtk_tree_view_column_set_cell_data_func(
441 			col, renderer, _cell_data_func,
442 			NULL, NULL);
443 	} else {
444 		g_signal_connect(renderer, "editing-started",
445 				 G_CALLBACK(_editing_started), NULL);
446 		g_signal_connect(renderer, "editing-canceled",
447 				 G_CALLBACK(_editing_canceled), NULL);
448 		g_signal_connect(renderer, "edited",
449 				 G_CALLBACK(display_data->admin_edit),
450 				 gtk_tree_view_get_model(tree_view));
451 
452 		gtk_tree_view_column_add_attribute(col, renderer,
453 						   "text", display_data->id);
454 		gtk_tree_view_column_set_expand(col, true);
455 		gtk_tree_view_column_set_reorderable(col, true);
456 		gtk_tree_view_column_set_resizable(col, true);
457 		gtk_tree_view_column_set_sort_column_id(col, display_data->id);
458 		gtk_tree_view_column_set_title(col, display_data->name);
459 	}
460 
461 	gtk_tree_view_append_column(tree_view, col);
462 }
463 
_toggle_state_changed(GtkCheckMenuItem * menuitem,display_data_t * display_data)464 static void _toggle_state_changed(GtkCheckMenuItem *menuitem,
465 				  display_data_t *display_data)
466 {
467 	if (display_data->show)
468 		display_data->show = false;
469 	else
470 		display_data->show = true;
471 	toggled = true;
472 	refresh_main(NULL, NULL);
473 }
474 
_popup_state_changed(GtkCheckMenuItem * menuitem,display_data_t * display_data)475 static void _popup_state_changed(GtkCheckMenuItem *menuitem,
476 				 display_data_t *display_data)
477 {
478 	popup_info_t *popup_win = (popup_info_t *) display_data->user_data;
479 	if (display_data->show)
480 		display_data->show = false;
481 	else
482 		display_data->show = true;
483 	popup_win->toggled = 1;
484 	(display_data->refresh)(NULL, display_data->user_data);
485 }
486 
_selected_page(GtkMenuItem * menuitem,display_data_t * display_data)487 static void _selected_page(GtkMenuItem *menuitem, display_data_t *display_data)
488 {
489 	treedata_t *treedata = (treedata_t *)display_data->user_data;
490 	each_t each;
491 	memset(&each, 0, sizeof(each_t));
492 	each.tree_view = treedata->treeview;
493 	each.display_data = display_data;
494 	global_row_count = gtk_tree_selection_count_selected_rows(
495 		gtk_tree_view_get_selection(treedata->treeview));
496 	switch(display_data->extra & EXTRA_BASE) {
497 	case PART_PAGE:
498 		each.pfunc = &popup_all_part;
499 		break;
500 	case JOB_PAGE:
501 		each.pfunc = &popup_all_job;
502 		break;
503 	case NODE_PAGE:
504 		each.pfunc = &popup_all_node;
505 		break;
506 	case RESV_PAGE:
507 		each.pfunc = &popup_all_resv;
508 		break;
509 	case BB_PAGE:
510 		each.pfunc = &popup_all_bb;
511 		break;
512 	case FRONT_END_PAGE:
513 		each.pfunc = &popup_all_front_end;
514 		break;
515 	case ADMIN_PAGE:
516 		switch(display_data->id) {
517 		case JOB_PAGE:
518 			admin_job(treedata->model, &treedata->iter,
519 				  display_data->name,treedata->treeview);
520 			break;
521 		case PART_PAGE:
522 			select_admin_partitions(treedata->model,
523 						&treedata->iter,
524 						display_data,
525 						treedata->treeview);
526 			break;
527 		case FRONT_END_PAGE:
528 			select_admin_front_end(treedata->model,
529 					       &treedata->iter,
530 					       display_data,
531 					       treedata->treeview);
532 			break;
533 		case RESV_PAGE:
534 			select_admin_resv(treedata->model, &treedata->iter,
535 					  display_data, treedata->treeview);
536 			break;
537 		case NODE_PAGE:
538 			select_admin_nodes(treedata->model, &treedata->iter,
539 					   display_data, NO_VAL,
540 					   treedata->treeview);
541 			break;
542 		case BB_PAGE:
543 			select_admin_bb(treedata->model, &treedata->iter,
544 					   display_data, treedata->treeview);
545 			break;
546 		default:
547 			g_print("common admin got %d %d\n",
548 				display_data->extra,
549 				display_data->id);
550 		}
551 		break;
552 	default:
553 		g_print("common got %d %d\n", display_data->extra,
554 			display_data->id);
555 	}
556 	if (each.pfunc)
557 		gtk_tree_selection_selected_foreach(
558 			gtk_tree_view_get_selection(treedata->treeview),
559 			_foreach_popup_all, &each);
560 	xfree(treedata);
561 }
562 
replspace(char * str)563 extern char * replspace (char *str)
564 {
565 	int pntr = 0;
566 	while (str[pntr]) {
567 		if (str[pntr] == ' ')
568 			str[pntr] = '_';
569 		pntr++;
570 	}
571 	return str;
572 }
573 
replus(char * str)574 extern char * replus (char *str)
575 {
576 	int pntr = 0;
577 	while (str[pntr]) {
578 		if (str[pntr] == '_')
579 			str[pntr] = ' ';
580 		pntr++;
581 	}
582 	return str;
583 }
584 
free_switch_nodes_maps(switch_record_bitmaps_t * sw_nodes_bitmaps_ptr)585 extern void free_switch_nodes_maps(
586 	switch_record_bitmaps_t *sw_nodes_bitmaps_ptr)
587 {
588 	while (sw_nodes_bitmaps_ptr++) {
589 		if (!sw_nodes_bitmaps_ptr->node_bitmap)
590 			break;
591 		bit_free(sw_nodes_bitmaps_ptr->node_bitmap);
592 		if (sw_nodes_bitmaps_ptr->node_bitmap)
593 			xfree(sw_nodes_bitmaps_ptr->nodes);
594 	}
595 	g_switch_nodes_maps = NULL;
596 }
597 
build_nodes_bitmap(char * node_names,bitstr_t ** bitmap)598 extern int build_nodes_bitmap(char *node_names, bitstr_t **bitmap)
599 
600 {
601 	char *this_node_name;
602 	bitstr_t *my_bitmap;
603 	hostlist_t host_list;
604 	int node_inx = -1;
605 
606 	if (TOPO_DEBUG)
607 		g_print("...............build_nodes_bitmap............%s\n",
608 			node_names);
609 	my_bitmap = (bitstr_t *) bit_alloc(g_node_info_ptr->record_count);
610 	*bitmap = my_bitmap;
611 
612 	if (!node_names) {
613 		error("build_nodes_bitmap: node_names is NULL");
614 		return EINVAL;
615 	}
616 
617 	if (!(host_list = hostlist_create(node_names))) {
618 		error("build_nodes_bitmap: hostlist_create(%s) error",
619 		      node_names);
620 		return EINVAL;
621 	}
622 
623 	/*spin hostlist and map nodes into a bitmap*/
624 	while ((this_node_name = hostlist_shift(host_list))) {
625 		node_inx = _find_node_inx(this_node_name);
626 		free(this_node_name);
627 
628 		if (node_inx == -1)
629 			continue;
630 
631 		bit_set(my_bitmap, (bitoff_t)node_inx);
632 	}
633 	hostlist_destroy(host_list);
634 
635 	return SLURM_SUCCESS;
636 }
637 
get_topo_conf(void)638 extern int get_topo_conf(void)
639 {
640 	int i;
641 	switch_record_bitmaps_t sw_nodes_bitmaps;
642 	switch_record_bitmaps_t *sw_nodes_bitmaps_ptr;
643 
644 	if (TOPO_DEBUG)
645 		g_print("get_topo_conf\n");
646 
647 	if (!g_topo_info_msg_ptr && slurm_load_topo(&g_topo_info_msg_ptr)) {
648 		slurm_perror ("slurm_load_topo error");
649 		if (TOPO_DEBUG)
650 			g_print("get_topo_conf error !!\n");
651 		return SLURM_ERROR;
652 	}
653 
654 	if (g_topo_info_msg_ptr->record_count == 0) {
655 		slurm_free_topo_info_msg(g_topo_info_msg_ptr);
656 		g_topo_info_msg_ptr = NULL;
657 		return SLURM_ERROR;
658 	}
659 
660 	if (g_switch_nodes_maps)
661 		free_switch_nodes_maps(g_switch_nodes_maps);
662 
663 	g_switch_nodes_maps = xmalloc(sizeof(sw_nodes_bitmaps)
664 				      * g_topo_info_msg_ptr->record_count);
665 	sw_nodes_bitmaps_ptr = g_switch_nodes_maps;
666 
667 	if (TOPO_DEBUG)
668 		g_print("_display_topology,  record_count = %d\n",
669 			g_topo_info_msg_ptr->record_count);
670 	for (i = 0; i < g_topo_info_msg_ptr->record_count;
671 	     i++, sw_nodes_bitmaps_ptr++) {
672 		if (!g_topo_info_msg_ptr->topo_array[i].nodes)
673 			continue;
674 		if (TOPO_DEBUG)  {
675 			g_print("ptr->nodes =  %s \n",
676 				g_topo_info_msg_ptr->topo_array[i].nodes);
677 		}
678 		if (build_nodes_bitmap(
679 			    g_topo_info_msg_ptr->topo_array[i].nodes,
680 			    &sw_nodes_bitmaps_ptr->node_bitmap)) {
681 			g_print("Invalid node name (%s) in switch %s\n",
682 				g_topo_info_msg_ptr->topo_array[i].nodes,
683 				g_topo_info_msg_ptr->topo_array[i].name);
684 		}
685 	}
686 
687 	if (TOPO_DEBUG)
688 		_display_topology();
689 
690 	return SLURM_SUCCESS;
691 }
692 
get_row_number(GtkTreeView * tree_view,GtkTreePath * path)693 extern int get_row_number(GtkTreeView *tree_view, GtkTreePath *path)
694 {
695 	GtkTreeModel *model = gtk_tree_view_get_model(tree_view);
696 	GtkTreeIter iter;
697 	int line = 0;
698 
699 	if (!model) {
700 		g_error("error getting the model from the tree_view");
701 		return -1;
702 	}
703 
704 	if (!gtk_tree_model_get_iter(model, &iter, path)) {
705 		g_error("get row, error getting iter from model");
706 		return -1;
707 	}
708 	gtk_tree_model_get(model, &iter, POS_LOC, &line, -1);
709 	return line;
710 }
711 
find_col(display_data_t * display_data,int type)712 extern int find_col(display_data_t *display_data, int type)
713 {
714 	int i = 0;
715 
716 	while (display_data++) {
717 		if (display_data->id == -1)
718 			break;
719 		if (display_data->id == type)
720 			return i;
721 		i++;
722 	}
723 	return -1;
724 }
725 
find_col_name(display_data_t * display_data,int type)726 extern const char *find_col_name(display_data_t *display_data, int type)
727 {
728 	while (display_data++) {
729 		if (display_data->id == -1)
730 			break;
731 		if (display_data->id == type)
732 			return display_data->name;
733 	}
734 	return NULL;
735 }
736 
get_pointer(GtkTreeView * tree_view,GtkTreePath * path,int loc)737 extern void *get_pointer(GtkTreeView *tree_view, GtkTreePath *path, int loc)
738 {
739 	GtkTreeModel *model = gtk_tree_view_get_model(tree_view);
740 	GtkTreeIter iter;
741 	void *ptr = NULL;
742 
743 	if (!model) {
744 		g_error("error getting the model from the tree_view");
745 		return ptr;
746 	}
747 
748 	if (!gtk_tree_model_get_iter(model, &iter, path)) {
749 		g_error("get pointer, error getting iter from model");
750 		return ptr;
751 	}
752 	gtk_tree_model_get(model, &iter, loc, &ptr, -1);
753 	return ptr;
754 }
755 
make_fields_menu(popup_info_t * popup_win,GtkMenu * menu,display_data_t * display_data,int count)756 extern void make_fields_menu(popup_info_t *popup_win, GtkMenu *menu,
757 			     display_data_t *display_data, int count)
758 {
759 	GtkWidget *menuitem = NULL;
760 	display_data_t *first_display_data = display_data;
761 	int i = 0;
762 
763 	/* we don't want to display anything on the full info page */
764 	if (popup_win && popup_win->spec_info->type == INFO_PAGE)
765 		return;
766 
767 	g_signal_connect(G_OBJECT(menu), "button-press-event",
768 			 G_CALLBACK(_menu_button_pressed),
769 			 NULL);
770 	g_signal_connect(G_OBJECT(menu), "button-release-event",
771 			 G_CALLBACK(_menu_button_released),
772 			 NULL);
773 
774 	for(i=0; i<count; i++) {
775 		while (display_data++) {
776 			if (display_data->id == -1)
777 				break;
778 			if (!display_data->name)
779 				continue;
780 			if (display_data->id != i)
781 				continue;
782 
783 			menuitem = gtk_check_menu_item_new_with_label(
784 				display_data->name);
785 
786 			gtk_check_menu_item_set_active(
787 				GTK_CHECK_MENU_ITEM(menuitem),
788 				display_data->show);
789 			if (popup_win) {
790 				display_data->user_data = popup_win;
791 				g_signal_connect(
792 					menuitem, "toggled",
793 					G_CALLBACK(_popup_state_changed),
794 					display_data);
795 			} else {
796 				g_signal_connect(
797 					menuitem, "toggled",
798 					G_CALLBACK(_toggle_state_changed),
799 					display_data);
800 			}
801 			gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
802 			break;
803 		}
804 		display_data = first_display_data;
805 	}
806 }
807 
set_page_opts(int page,display_data_t * display_data,int count,char * initial_opts)808 extern void set_page_opts(int page, display_data_t *display_data,
809 			  int count, char* initial_opts)
810 {
811 	page_opts_t *page_opts;
812 	ListIterator itr = NULL;
813 	char *col_name = NULL;
814 
815 	xassert(page < PAGE_CNT);
816 
817 	page_opts = &working_sview_config.page_opts[page];
818 	if (!page_opts->col_list) {
819 		page_opts->def_col_list = 1;
820 		page_opts->col_list = list_create(xfree_ptr);
821 		slurm_addto_char_list(page_opts->col_list, initial_opts);
822 	}
823 
824 	page_opts->display_data = display_data;
825 
826 	itr = list_iterator_create(page_opts->col_list);
827 	while ((col_name = list_next(itr))) {
828 		replus(col_name);
829 		while (display_data++) {
830 			if (display_data->id == -1)
831 				break;
832 			if (!display_data->name)
833 				continue;
834 			if (!xstrncasecmp(col_name, display_data->name,
835 					  strlen(col_name))) {
836 				display_data->show = true;
837 				break;
838 			}
839 		}
840 		display_data = page_opts->display_data;
841 	}
842 	list_iterator_destroy(itr);
843 }
844 
make_options_menu(GtkTreeView * tree_view,GtkTreePath * path,GtkMenu * menu,display_data_t * display_data)845 extern void make_options_menu(GtkTreeView *tree_view, GtkTreePath *path,
846 			      GtkMenu *menu, display_data_t *display_data)
847 {
848 	GtkWidget *menuitem = NULL;
849 	treedata_t *treedata = xmalloc(sizeof(treedata_t));
850 	treedata->model = gtk_tree_view_get_model(tree_view);
851 	treedata->treeview = tree_view;
852 
853 	g_signal_connect(G_OBJECT(menu), "button-press-event",
854 			 G_CALLBACK(_menu_button_pressed),
855 			 NULL);
856 	g_signal_connect(G_OBJECT(menu), "button-release-event",
857 			 G_CALLBACK(_menu_button_released),
858 			 NULL);
859 
860 	if (!gtk_tree_model_get_iter(treedata->model, &treedata->iter, path)) {
861 		g_error("make menus error getting iter from model\n");
862 		return;
863 	}
864 
865 	/* check selection list */
866 	global_row_count = gtk_tree_selection_count_selected_rows(
867 		gtk_tree_view_get_selection(tree_view));
868 
869 	if (display_data->user_data)
870 		xfree(display_data->user_data);
871 
872 	while (display_data++) {
873 		if (display_data->id == -1) {
874 			break;
875 		}
876 
877 		if (!display_data->name)
878 			continue;
879 		display_data->user_data = treedata;
880 		menuitem = gtk_menu_item_new_with_label(display_data->name);
881 
882 		g_signal_connect(menuitem, "activate",
883 				 G_CALLBACK(_selected_page),
884 				 display_data);
885 		gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
886 
887 	}
888 }
889 
create_scrolled_window(void)890 extern GtkScrolledWindow *create_scrolled_window(void)
891 {
892 	GtkScrolledWindow *scrolled_window = NULL;
893 	GtkWidget *table = NULL;
894 	table = gtk_table_new(1, 1, false);
895 
896 	gtk_container_set_border_width(GTK_CONTAINER(table), 10);
897 
898 	scrolled_window = GTK_SCROLLED_WINDOW(gtk_scrolled_window_new(
899 						      NULL, NULL));
900 	gtk_container_set_border_width(GTK_CONTAINER(scrolled_window), 10);
901 
902 	gtk_scrolled_window_set_policy(scrolled_window,
903 				       GTK_POLICY_AUTOMATIC,
904 				       GTK_POLICY_AUTOMATIC);
905 
906 	gtk_scrolled_window_add_with_viewport(scrolled_window, table);
907 
908 	return scrolled_window;
909 }
910 
create_entry(void)911 extern GtkWidget *create_entry(void)
912 {
913 	GtkWidget *entry = gtk_entry_new();
914 
915 	gtk_entry_set_activates_default(GTK_ENTRY(entry), true);
916 
917 	return entry;
918 }
919 
create_page(GtkNotebook * notebook,display_data_t * display_data)920 extern void create_page(GtkNotebook *notebook, display_data_t *display_data)
921 {
922 	GtkScrolledWindow *scrolled_window = create_scrolled_window();
923 	GtkWidget *event_box = gtk_event_box_new();
924 	GtkWidget *label = gtk_label_new(display_data->name);
925 	GtkWidget *close_button = gtk_event_box_new();
926 	GtkWidget *table;
927 	GtkWidget *image = NULL;
928 	int err;
929 
930 	if (display_data->id == TAB_PAGE) {
931 		table = gtk_table_new(PAGE_CNT, 3, false);
932 		image = gtk_image_new_from_stock(
933 			GTK_STOCK_ADD, GTK_ICON_SIZE_SMALL_TOOLBAR);
934 	} else {
935 		table = gtk_table_new(1, 3, false);
936 		image = gtk_image_new_from_stock(
937 			GTK_STOCK_DIALOG_ERROR, GTK_ICON_SIZE_SMALL_TOOLBAR);
938 		g_signal_connect(G_OBJECT(close_button), "button-press-event",
939 				 G_CALLBACK(close_tab),
940 				 display_data);
941 	}
942 
943 	gtk_container_add(GTK_CONTAINER(close_button), image);
944 	gtk_widget_set_size_request(close_button, 10, 10);
945 
946 	//gtk_event_box_set_above_child(GTK_EVENT_BOX(close_button), false);
947 
948 	gtk_container_add(GTK_CONTAINER(event_box), label);
949 	gtk_event_box_set_above_child(GTK_EVENT_BOX(event_box), false);
950 	g_signal_connect(G_OBJECT(event_box), "button-press-event",
951 			 G_CALLBACK(tab_pressed),
952 			 display_data);
953 
954 	gtk_table_set_homogeneous(GTK_TABLE(table), false);
955 	gtk_table_set_col_spacings(GTK_TABLE(table), 5);
956 	gtk_container_set_border_width(GTK_CONTAINER(table), 1);
957 
958 	gtk_table_attach_defaults(GTK_TABLE(table), event_box, 0, 1, 0, 1);
959 	gtk_table_attach_defaults(GTK_TABLE(table), close_button, 2, 3, 0, 1);
960 	gtk_container_set_focus_child(GTK_CONTAINER(table), label);
961 
962 	gtk_widget_show_all(table);
963 	//(display_data->set_fields)(GTK_MENU(menu));
964 	if ((err = gtk_notebook_append_page(GTK_NOTEBOOK(notebook),
965 					    GTK_WIDGET(scrolled_window),
966 					    table)) == -1) {
967 		g_error("Couldn't add page to notebook\n");
968 	}
969 
970 	display_data->extra = err;
971 
972 }
973 
create_treeview(display_data_t * local,List * button_list)974 extern GtkTreeView *create_treeview(display_data_t *local, List *button_list)
975 {
976 	signal_params_t *signal_params = xmalloc(sizeof(signal_params_t));
977 	GtkTreeView *tree_view = GTK_TREE_VIEW(gtk_tree_view_new());
978 	local->user_data = NULL;
979 
980 	signal_params->display_data = local;
981 	signal_params->button_list = button_list;
982 	if (working_sview_config.ruled_treeview)
983 		gtk_tree_view_set_rules_hint (tree_view, true);
984 
985 	g_signal_connect(G_OBJECT(tree_view), "button-press-event",
986 			 G_CALLBACK(row_clicked),
987 			 signal_params);
988 	g_signal_connect(G_OBJECT(tree_view), "key_release_event",
989 			 G_CALLBACK(key_released),
990 			 signal_params);
991 	g_signal_connect(G_OBJECT(tree_view), "key_press_event",
992 			 G_CALLBACK(key_pressed),
993 			 signal_params);
994 	g_signal_connect(G_OBJECT(tree_view), "row-activated",
995 			 G_CALLBACK(row_activated),
996 			 signal_params);
997 	gtk_widget_show(GTK_WIDGET(tree_view));
998 	list_push(signal_params_list, signal_params);
999 	return tree_view;
1000 
1001 }
1002 
create_treeview_2cols_attach_to_table(GtkTable * table)1003 extern GtkTreeView *create_treeview_2cols_attach_to_table(GtkTable *table)
1004 {
1005 	GtkTreeView *tree_view = GTK_TREE_VIEW(gtk_tree_view_new());
1006 	GtkTreeStore *treestore =
1007 		gtk_tree_store_new(3, G_TYPE_STRING,
1008 				   G_TYPE_STRING, G_TYPE_STRING);
1009 	GtkTreeViewColumn *col = gtk_tree_view_column_new();
1010 	GtkCellRenderer *renderer = gtk_cell_renderer_text_new();
1011 
1012 	if (working_sview_config.ruled_treeview)
1013 		gtk_tree_view_set_rules_hint (tree_view, true);
1014 
1015 	gtk_table_attach_defaults(table,
1016 				  GTK_WIDGET(tree_view),
1017 				  0, 1, 0, 1);
1018 
1019 	gtk_tree_view_set_model(tree_view, GTK_TREE_MODEL(treestore));
1020 
1021 	gtk_tree_view_column_pack_start(col, renderer, true);
1022 	gtk_tree_view_column_add_attribute(col, renderer,
1023 					   "text", DISPLAY_NAME);
1024 	gtk_tree_view_column_add_attribute(col, renderer,
1025 					   "font", DISPLAY_FONT);
1026 	gtk_tree_view_column_set_title(col, "Name");
1027 	gtk_tree_view_column_set_resizable(col, true);
1028 	gtk_tree_view_column_set_expand(col, true);
1029 	gtk_tree_view_append_column(tree_view, col);
1030 
1031 	col = gtk_tree_view_column_new();
1032 	renderer = gtk_cell_renderer_text_new();
1033 	gtk_tree_view_column_pack_start(col, renderer, true);
1034 	gtk_tree_view_column_add_attribute(col, renderer,
1035 					   "text", DISPLAY_VALUE);
1036 	gtk_tree_view_column_add_attribute(col, renderer,
1037 					   "font", DISPLAY_FONT);
1038 	gtk_tree_view_column_set_title(col, "Value");
1039 	gtk_tree_view_column_set_resizable(col, true);
1040 	gtk_tree_view_column_set_expand(col, true);
1041 	gtk_tree_view_append_column(tree_view, col);
1042 
1043 	col = gtk_tree_view_column_new();
1044 	renderer = gtk_cell_renderer_text_new();
1045 	gtk_tree_view_column_pack_start(col, renderer, true);
1046 	gtk_tree_view_column_set_visible(col, false);
1047 	gtk_tree_view_column_add_attribute(col, renderer,
1048 					   "text", DISPLAY_FONT);
1049 	gtk_tree_view_append_column(tree_view, col);
1050 
1051 	g_object_unref(treestore);
1052 	return tree_view;
1053 }
1054 
create_treestore(GtkTreeView * tree_view,display_data_t * display_data,int count,int sort_column,int color_column)1055 extern GtkTreeStore *create_treestore(GtkTreeView *tree_view,
1056 				      display_data_t *display_data,
1057 				      int count, int sort_column,
1058 				      int color_column)
1059 {
1060 	GtkTreeStore *treestore = NULL;
1061 	GType types[count];
1062 	int i=0;
1063 
1064 	/*set up the types defined in the display_data_t */
1065 	for(i=0; i<count; i++) {
1066 		types[display_data[i].id] = display_data[i].type;
1067 	}
1068 
1069 	treestore = gtk_tree_store_newv(count, types);
1070 	if (!treestore) {
1071 		g_print("Can't create treestore.\n");
1072 		return NULL;
1073 	}
1074 
1075 	gtk_tree_view_set_model(tree_view, GTK_TREE_MODEL(treestore));
1076 
1077 	for(i=1; i<count; i++) {
1078 		if (!display_data[i].show)
1079 			continue;
1080 
1081 		_add_col_to_treeview(tree_view, &display_data[i], color_column);
1082 		if (!display_data[i].name)
1083 			continue;
1084 
1085 		switch(display_data[i].type) {
1086 		case G_TYPE_INT:
1087 			gtk_tree_sortable_set_sort_func(
1088 				GTK_TREE_SORTABLE(treestore),
1089 				display_data[i].id,
1090 				_sort_iter_compare_func_int,
1091 				GINT_TO_POINTER(display_data[i].id),
1092 				NULL);
1093 
1094 			break;
1095 		case G_TYPE_STRING:
1096 			if (!xstrcasecmp(display_data[i].name, "Node Count")
1097 			    || !xstrcasecmp(display_data[i].name, "CPU Count")
1098 			    || !xstrcasecmp(display_data[i].name, "Real Memory")
1099 			    || !xstrcasecmp(display_data[i].name, "Port")
1100 			    || !xstrcasecmp(display_data[i].name, "Tmp Disk")) {
1101 				gtk_tree_sortable_set_sort_func(
1102 					GTK_TREE_SORTABLE(treestore),
1103 					display_data[i].id,
1104 					_sort_iter_compare_func_nodes,
1105 					GINT_TO_POINTER(display_data[i].id),
1106 					NULL);
1107 				break;
1108 			} else {
1109 				gtk_tree_sortable_set_sort_func(
1110 					GTK_TREE_SORTABLE(treestore),
1111 					display_data[i].id,
1112 					_sort_iter_compare_func_char,
1113 					GINT_TO_POINTER(display_data[i].id),
1114 					NULL);
1115 				break;
1116 			}
1117 		default:
1118 			g_print("unknown type %d",
1119 				(int)display_data[i].type);
1120 		}
1121 	}
1122 
1123 	if (sort_column >= 0) {
1124 		gtk_tree_sortable_set_sort_column_id(
1125 					GTK_TREE_SORTABLE(treestore),
1126 					sort_column,
1127 					GTK_SORT_ASCENDING);
1128 	}
1129 
1130 	g_object_unref(treestore);
1131 
1132 	return treestore;
1133 }
1134 
right_button_pressed(GtkTreeView * tree_view,GtkTreePath * path,GdkEventButton * event,const signal_params_t * signal_params,int type)1135 extern gboolean right_button_pressed(GtkTreeView *tree_view,
1136 				     GtkTreePath *path,
1137 				     GdkEventButton *event,
1138 				     const signal_params_t *signal_params,
1139 				     int type)
1140 {
1141 	GtkMenu *menu = GTK_MENU(gtk_menu_new());
1142 	display_data_t *display_data = signal_params->display_data;
1143 
1144 	if (type == ROW_CLICKED) {
1145 		if (_DEBUG)
1146 			g_print("right_button_pressed:global_row_count : %d\n",
1147 				global_row_count);
1148 
1149 		/* These next 2 functions are there to keep the keyboard in
1150 		   sync */
1151 		if (!(event->state & GDK_CONTROL_MASK)
1152 		    && (!(global_row_count > 0)))
1153 			gtk_tree_view_set_cursor(tree_view, path, NULL, false);
1154 
1155 		gtk_widget_grab_focus(GTK_WIDGET(tree_view));
1156 
1157 		/* highlight the nodes from this row */
1158 		(display_data->set_menu)(tree_view, *signal_params->button_list,
1159 					 path, ROW_LEFT_CLICKED);
1160 	}
1161 
1162 	(display_data->set_menu)(tree_view, menu, path, type);
1163 	gtk_widget_show_all(GTK_WIDGET(menu));
1164 	gtk_menu_popup(menu, NULL, NULL, NULL, NULL,
1165 		       event ? event->button : 0,
1166 		       gdk_event_get_time((GdkEvent*)event));
1167 	return true;
1168 }
1169 
left_button_pressed(GtkTreeView * tree_view,GtkTreePath * path,const signal_params_t * signal_params,GdkEventButton * event)1170 extern gboolean left_button_pressed(GtkTreeView *tree_view,
1171 				    GtkTreePath *path,
1172 				    const signal_params_t *signal_params,
1173 				    GdkEventButton *event)
1174 {
1175 	static time_t last_time = 0;
1176 	time_t now = time(NULL);
1177 	gboolean rc = false;
1178 	GtkTreeIter iter;
1179 	GtkTreeModel *model = gtk_tree_view_get_model(tree_view);
1180 	display_data_t *display_data = signal_params->display_data;
1181 	static gpointer *last_user_data = NULL;
1182 
1183 	/* These next 2 functions are there to keep the keyboard in
1184 	   sync */
1185 	if (!((event->state & GDK_CONTROL_MASK)
1186 	      || (event->state & GDK_SHIFT_MASK)))
1187 		gtk_tree_view_set_cursor(tree_view, path, NULL, false);
1188 
1189 	gtk_widget_grab_focus(GTK_WIDGET(tree_view)); /*give keyboard focus*/
1190 
1191 	if (signal_params->button_list) {
1192 		(display_data->set_menu)(tree_view, *signal_params->button_list,
1193 					 path, ROW_LEFT_CLICKED);
1194 	} else
1195 		(display_data->set_menu)(tree_view, NULL, path, FULL_CLICKED);
1196 
1197 	/* make sure it was a double click */
1198 	if (!gtk_tree_model_get_iter(model, &iter, path)) {
1199 		g_error("left pressed, error getting iter from model\n");
1200 		return rc;
1201 	}
1202 	if (!(now-last_time)
1203 	    && (!last_user_data || (iter.user_data == last_user_data))) {
1204 		/* double click */
1205 		(display_data->set_menu)(tree_view, NULL, path, FULL_CLICKED);
1206 	}
1207 	last_user_data = iter.user_data;
1208 
1209 	if (!working_sview_config.admin_mode)
1210 		rc = true;
1211 
1212 	last_time = now;
1213 
1214 	return rc;
1215 }
1216 
row_activated(GtkTreeView * tree_view,GtkTreePath * path,GtkTreeViewColumn * column,const signal_params_t * signal_params)1217 extern gboolean row_activated(GtkTreeView *tree_view, GtkTreePath *path,
1218 			      GtkTreeViewColumn *column,
1219 			      const signal_params_t *signal_params)
1220 {
1221 	display_data_t *display_data = signal_params->display_data;
1222 	/* highlight the nodes from this row */
1223 	(display_data->set_menu)(tree_view, *signal_params->button_list,
1224 				 path, ROW_LEFT_CLICKED);
1225 	/* display the full info */
1226 	if (!enter_key_in_effect)
1227 		(display_data->set_menu)(tree_view, NULL, path, FULL_CLICKED);
1228 	enter_key_in_effect = false;
1229 
1230 	return false;
1231 }
1232 
key_pressed(GtkTreeView * tree_view,GdkEventKey * event,const signal_params_t * signal_params)1233 extern gboolean key_pressed(GtkTreeView *tree_view,
1234 			    GdkEventKey *event,
1235 			    const signal_params_t *signal_params)
1236 {
1237 	control_key_in_effect = false;
1238 	enter_key_in_effect = false;
1239 
1240 	if ((event->keyval == GDK_Control_L) ||
1241 	    (event->keyval == GDK_Control_R))
1242 		control_key_in_effect = true;
1243 	else if (event->keyval == GDK_Return) {
1244 		each_t each;
1245 		GtkTreeSelection *selection = NULL;
1246 
1247 		selection = gtk_tree_view_get_selection(tree_view);
1248 		memset(&each, 0, sizeof(each_t));
1249 		each.tree_view = tree_view;
1250 		each.display_data = signal_params->display_data;
1251 		global_row_count =
1252 			gtk_tree_selection_count_selected_rows(selection);
1253 		popup_pos.x = 10;
1254 		popup_pos.x = 10;
1255 		popup_pos.cntr = 1;
1256 		popup_pos.slider = 0;
1257 		gtk_tree_selection_selected_foreach(
1258 			selection, _foreach_full_info, &each);
1259 		/*prevent row_activation from
1260 		 * performing a redundant 'full info'*/
1261 		enter_key_in_effect = true;
1262 
1263 	}
1264 
1265 	return false;
1266 }/*key_pressed ^^^*/
1267 
1268 
key_released(GtkTreeView * tree_view,GdkEventKey * event,const signal_params_t * signal_params)1269 extern gboolean key_released(GtkTreeView *tree_view,
1270 			     GdkEventKey *event,
1271 			     const signal_params_t *signal_params)
1272 {
1273 
1274 	GtkTreePath *path = NULL;
1275 	GtkTreeViewColumn *column;
1276 	GtkTreeSelection *selection = NULL;
1277 
1278 	if ((event->keyval != GDK_Up) &&
1279 	    (event->keyval != GDK_Down) &&
1280 	    (event->keyval != GDK_Return))
1281 		return true;
1282 
1283 	gtk_tree_view_get_cursor(GTK_TREE_VIEW(tree_view), &path, &column);
1284 	if (path) {
1285 		selection = gtk_tree_view_get_selection(tree_view);
1286 		gtk_tree_selection_select_path(selection, path);
1287 		gtk_tree_path_free(path);
1288 	}
1289 	return true;
1290 
1291 
1292 }/*key_released ^^^*/
1293 
row_clicked(GtkTreeView * tree_view,GdkEventButton * event,const signal_params_t * signal_params)1294 extern gboolean row_clicked(GtkTreeView *tree_view, GdkEventButton *event,
1295 			    const signal_params_t *signal_params)
1296 {
1297 	GtkTreePath *path = NULL;
1298 	GtkTreePath *last_path = NULL;
1299 	GtkTreeSelection *selection = NULL;
1300 	gboolean did_something = false;
1301 	gboolean selected_in_current_mix = false;
1302 
1303 	if (!gtk_tree_view_get_path_at_pos(tree_view,
1304 					   (gint) event->x,
1305 					   (gint) event->y,
1306 					   &path, NULL, NULL, NULL)) {
1307 		selection = gtk_tree_view_get_selection(tree_view);
1308 
1309 		/* If there is a selection AND we are not under
1310 		 * multi-selection processing via the ctrl key clear
1311 		 * it up by doing a refresh.  If there wasn't a
1312 		 * selection before OR we are stacking selections via
1313 		 * the ctrl key do nothing here. */
1314 		if (gtk_tree_selection_count_selected_rows(selection)){
1315 			if (!(event->state & GDK_CONTROL_MASK))
1316 				gtk_tree_selection_unselect_all(selection);
1317 			refresh_main(NULL, NULL);
1318 			return true;
1319 		}
1320 		return false;
1321 	}
1322 
1323 	/* make the selection (highlight) here */
1324 	selection = gtk_tree_view_get_selection(tree_view);
1325 	global_row_count =
1326 		gtk_tree_selection_count_selected_rows(selection);
1327 
1328 	/*flag this for rightclick to unselect on*/
1329 	selected_in_current_mix =
1330 		gtk_tree_selection_path_is_selected(selection, path);
1331 
1332 	if (event->button != 3) {
1333 		/*if Lshift is down then pull a range out*/
1334 		if ((event->state & GDK_SHIFT_MASK)) {
1335 			if (last_event_x != 0) {
1336 				if (gtk_tree_view_get_path_at_pos(
1337 					    tree_view,
1338 					    (gint) last_event_x,
1339 					    (gint) last_event_y,
1340 					    &last_path, NULL, NULL, NULL)) {
1341 					if (last_path) {
1342 						gtk_tree_selection_select_range(
1343 							selection, last_path,
1344 							path);
1345 						gtk_tree_path_free(last_path);
1346 					}
1347 				}
1348 			} else if (path) {
1349 				/*ignore shift and pull single row anyway*/
1350 				gtk_tree_selection_select_path(selection,
1351 							       path);
1352 			}
1353 		} /*shift down^^*/
1354 	}
1355 	last_event_x = event->x; /*save THIS x*/
1356 	last_event_y = event->y; /*save THIS y*/
1357 
1358 	if (event->x <= 28) {
1359 		/* When you try to resize a column this event happens
1360 		   for some reason.  Resizing always happens in the
1361 		   first 2 of x so if that happens just return and
1362 		   continue. Also if we want to expand/collapse a
1363 		   column, that happens in the first 28 (The default
1364 		   expander size is 14, and as of writing this we
1365 		   could expand 2 levels, so just skip
1366 		   that also.  If anyone in the future can figure out
1367 		   a way to know for sure the expander was clicked
1368 		   and not the actual column please fix this :).
1369 		*/
1370 		did_something = false;
1371 	} else if (event->button == 1) {
1372 		/*  left click */
1373 		if (!(event->state & GDK_CONTROL_MASK)
1374 		    && !(event->state & GDK_SHIFT_MASK)) {
1375 			/* unselect current on naked left clicks..*/
1376 			gtk_tree_selection_unselect_all(selection);
1377 		}
1378 		did_something = left_button_pressed(
1379 			tree_view, path, signal_params, event);
1380 	} else if (event->button == 3) {
1381 		/*  right click */
1382 		if (!selected_in_current_mix) {
1383 			if (!(event->state & GDK_CONTROL_MASK)){
1384 				gtk_tree_selection_unselect_all(selection);
1385 			} else if (path)
1386 				gtk_tree_selection_select_path(selection, path);
1387 		}
1388 		global_row_count =
1389 			gtk_tree_selection_count_selected_rows(selection);
1390 		if (_DEBUG)
1391 			g_print("row_clicked:global_row_count2 : %d \n",
1392 				global_row_count);
1393 		/*prevent rc processing if under contol/shift*/
1394 		if (!(event->state & GDK_CONTROL_MASK)
1395 		    && !(event->state & GDK_SHIFT_MASK))
1396 			right_button_pressed(tree_view, path, event,
1397 					     signal_params, ROW_CLICKED);
1398 		did_something = true;
1399 	} else if (!working_sview_config.admin_mode)
1400 		did_something = true;
1401 	gtk_tree_path_free(path);
1402 
1403 	/* If control key held refresh main (which does the grid and
1404 	   exit with false to reset the treeview.  This has to happen
1405 	   after left_button_pressed to get other things correct. */
1406 	if (event->state & GDK_CONTROL_MASK) {
1407 		refresh_main(NULL, NULL);
1408 		return false; /*propagate event*/
1409 	}
1410 	return did_something;
1411 }
1412 
create_popup_info(int type,int dest_type,char * title)1413 extern popup_info_t *create_popup_info(int type, int dest_type, char *title)
1414 {
1415 	GtkScrolledWindow *window = NULL, *grid_window = NULL;
1416 	GtkBin *bin = NULL;
1417 	GtkViewport *view = NULL;
1418 	GtkWidget *label = NULL;
1419 	GtkWidget *table = NULL;
1420 	GtkWidget *close_btn = NULL;
1421 	popup_info_t *popup_win = xmalloc(sizeof(popup_info_t));
1422 //	int i=0;
1423 
1424 	list_push(popup_list, popup_win);
1425 
1426 	popup_win->spec_info = xmalloc(sizeof(specific_info_t));
1427 	popup_win->spec_info->search_info =
1428 		xmalloc(sizeof(sview_search_info_t));
1429 	popup_win->spec_info->search_info->search_type = 0;
1430 	popup_win->spec_info->search_info->gchar_data = NULL;
1431 	popup_win->spec_info->search_info->int_data = NO_VAL;
1432 	popup_win->spec_info->search_info->int_data2 = NO_VAL;
1433 
1434 	popup_win->spec_info->type = type;
1435 	popup_win->spec_info->title = xstrdup(title);
1436 	popup_win->popup = gtk_dialog_new_with_buttons(
1437 		title,
1438 		GTK_WINDOW(main_window),
1439 		GTK_DIALOG_DESTROY_WITH_PARENT,
1440 		GTK_STOCK_REFRESH,
1441 		GTK_RESPONSE_OK,
1442 		NULL);
1443 	close_btn = gtk_dialog_add_button(GTK_DIALOG(popup_win->popup),
1444 					  GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE);
1445 	gtk_window_set_type_hint(GTK_WINDOW(popup_win->popup),
1446 				 GDK_WINDOW_TYPE_HINT_NORMAL);
1447 	gtk_window_set_focus(GTK_WINDOW(popup_win->popup), close_btn);
1448 	gtk_dialog_add_button(GTK_DIALOG(popup_win->popup),
1449 			      "Close All Popups", GTK_RESPONSE_CANCEL);
1450 
1451 
1452 	popup_win->show_grid = 1;
1453 	popup_win->toggled = 0;
1454 	popup_win->force_refresh = 0;
1455 	popup_win->type = dest_type;
1456 	popup_win->not_found = false;
1457 	/*
1458 	  for(i=0;; i++) {
1459 	  if (main_popup_positioner[i].width == -1)
1460 	  break;
1461 	  if (strstr(title,main_popup_positioner[i].name)) {
1462 	  width = main_popup_positioner[i].width;
1463 	  height = main_popup_positioner[i].height;
1464 	  break;
1465 	  }
1466 	  }
1467 	*/
1468 	gtk_window_set_default_size(GTK_WINDOW(popup_win->popup),
1469 				    working_sview_config.fi_popup_width,
1470 				    working_sview_config.fi_popup_height);
1471 	gtk_window_set_transient_for(GTK_WINDOW(popup_win->popup), NULL);
1472 
1473 	popup_win->event_box = gtk_event_box_new();
1474 	label = gtk_label_new(popup_win->spec_info->title);
1475 	gtk_container_add(GTK_CONTAINER(popup_win->event_box), label);
1476 
1477 	g_signal_connect(G_OBJECT(popup_win->event_box),
1478 			 "button-press-event",
1479 			 G_CALLBACK(redo_popup),
1480 			 popup_win);
1481 
1482 	gtk_event_box_set_above_child(
1483 		GTK_EVENT_BOX(popup_win->event_box),
1484 		false);
1485 
1486 	gtk_box_pack_start(GTK_BOX(GTK_DIALOG(popup_win->popup)->vbox),
1487 			   popup_win->event_box, false, false, 0);
1488 
1489 	grid_window = create_scrolled_window();
1490 	gtk_scrolled_window_set_policy(grid_window,
1491 				       GTK_POLICY_NEVER,
1492 				       GTK_POLICY_AUTOMATIC);
1493 	bin = GTK_BIN(&grid_window->container);
1494 	view = GTK_VIEWPORT(bin->child);
1495 	bin = GTK_BIN(&view->bin);
1496 	popup_win->grid_table = GTK_TABLE(bin->child);
1497 	popup_win->grid_button_list = NULL;
1498 
1499 	table = gtk_table_new(1, 2, false);
1500 
1501 	gtk_table_attach(GTK_TABLE(table), GTK_WIDGET(grid_window), 0, 1, 0, 1,
1502 			 GTK_SHRINK, GTK_EXPAND | GTK_FILL,
1503 			 0, 0);
1504 
1505 	window = create_scrolled_window();
1506 	bin = GTK_BIN(&window->container);
1507 	view = GTK_VIEWPORT(bin->child);
1508 	bin = GTK_BIN(&view->bin);
1509 	popup_win->table = GTK_TABLE(bin->child);
1510 
1511 	gtk_table_attach_defaults(GTK_TABLE(table), GTK_WIDGET(window),
1512 				  1, 2, 0, 1);
1513 
1514 	gtk_box_pack_start(GTK_BOX(GTK_DIALOG(popup_win->popup)->vbox),
1515 			   table, true, true, 0);
1516 
1517 	g_signal_connect(G_OBJECT(popup_win->popup), "delete_event",
1518 			 G_CALLBACK(delete_popup),
1519 			 popup_win->spec_info->title);
1520 	g_signal_connect(G_OBJECT(popup_win->popup), "response",
1521 			 G_CALLBACK(_handle_response),
1522 			 popup_win);
1523 	g_signal_connect(G_OBJECT(popup_win->popup), "configure-event",
1524 			 G_CALLBACK(_frame_callback),
1525 			 popup_win);
1526 	gtk_window_move(GTK_WINDOW(popup_win->popup),
1527 			popup_pos.x, popup_pos.y);
1528 	gtk_widget_show_all(popup_win->popup);
1529 
1530 	if (cluster_flags & CLUSTER_FLAG_FED)
1531 		gtk_widget_hide(GTK_WIDGET(grid_window));
1532 
1533 	return popup_win;
1534 }
1535 
setup_popup_info(popup_info_t * popup_win,display_data_t * display_data,int cnt)1536 extern void setup_popup_info(popup_info_t *popup_win,
1537 			     display_data_t *display_data,
1538 			     int cnt)
1539 {
1540 	int i = 0;
1541 
1542 	popup_win->display_data = xmalloc(sizeof(display_data_t)*(cnt+2));
1543 	for(i=0; i<cnt+1; i++) {
1544 		memcpy(&popup_win->display_data[i],
1545 		       &display_data[i],
1546 		       sizeof(display_data_t));
1547 	}
1548 }
1549 
redo_popup(GtkWidget * widget,GdkEventButton * event,popup_info_t * popup_win)1550 extern void redo_popup(GtkWidget *widget, GdkEventButton *event,
1551 		       popup_info_t *popup_win)
1552 {
1553 	if (event && (event->button == 3)) {
1554 		GtkMenu *menu = GTK_MENU(gtk_menu_new());
1555 
1556 		(popup_win->display_data->set_menu)(popup_win, menu,
1557 						    NULL,
1558 						    POPUP_CLICKED);
1559 
1560 		gtk_widget_show_all(GTK_WIDGET(menu));
1561 		gtk_menu_popup(menu, NULL, NULL, NULL, NULL, event->button,
1562 			       gdk_event_get_time((GdkEvent*)event));
1563 	}
1564 }
1565 
destroy_search_info(void * arg)1566 extern void destroy_search_info(void *arg)
1567 {
1568 	sview_search_info_t *search_info = (sview_search_info_t *)arg;
1569 	if (search_info) {
1570 		g_free(search_info->cluster_name);
1571 		if (search_info->gchar_data)
1572 			g_free(search_info->gchar_data);
1573 		search_info->gchar_data = NULL;
1574 		xfree(search_info);
1575 		search_info = NULL;
1576 	}
1577 }
1578 
destroy_specific_info(void * arg)1579 extern void destroy_specific_info(void *arg)
1580 {
1581 	specific_info_t *spec_info = (specific_info_t *)arg;
1582 	if (spec_info) {
1583 		xfree(spec_info->title);
1584 
1585 		destroy_search_info(spec_info->search_info);
1586 
1587 		if (spec_info->display_widget) {
1588 			gtk_widget_destroy(spec_info->display_widget);
1589 			spec_info->display_widget = NULL;
1590 		}
1591 		xfree(spec_info);
1592 	}
1593 }
1594 
destroy_popup_info(void * arg)1595 extern void destroy_popup_info(void *arg)
1596 {
1597 	popup_info_t *popup_win = (popup_info_t *)arg;
1598 
1599 	if (popup_win) {
1600 		*popup_win->running = 0;
1601 		g_mutex_lock(sview_mutex);
1602 		/* these are all children of each other so must
1603 		   be freed in this order */
1604 		FREE_NULL_LIST(popup_win->grid_button_list);
1605 		if (popup_win->table) {
1606 			gtk_widget_destroy(GTK_WIDGET(popup_win->table));
1607 			popup_win->table = NULL;
1608 		}
1609 		if (popup_win->grid_table) {
1610 			gtk_widget_destroy(GTK_WIDGET(popup_win->grid_table));
1611 			popup_win->grid_table = NULL;
1612 		}
1613 		if (popup_win->event_box) {
1614 			gtk_widget_destroy(popup_win->event_box);
1615 			popup_win->event_box = NULL;
1616 		}
1617 		if (popup_win->popup) {
1618 			gtk_widget_destroy(popup_win->popup);
1619 			popup_win->popup = NULL;
1620 		}
1621 
1622 		destroy_specific_info(popup_win->spec_info);
1623 		xfree(popup_win->display_data);
1624 		xfree(popup_win);
1625 		g_mutex_unlock(sview_mutex);
1626 	}
1627 
1628 }
1629 
destroy_signal_params(void * arg)1630 extern void destroy_signal_params(void *arg)
1631 {
1632 	signal_params_t *signal_params = (signal_params_t *)arg;
1633 
1634 	if (signal_params) {
1635 		xfree(signal_params);
1636 	}
1637 }
1638 
delete_popup(GtkWidget * widget,GtkWidget * event,char * title)1639 extern gboolean delete_popup(GtkWidget *widget, GtkWidget *event, char *title)
1640 {
1641 	ListIterator itr = list_iterator_create(popup_list);
1642 	popup_info_t *popup_win = NULL;
1643 
1644 	while ((popup_win = list_next(itr))) {
1645 		if (popup_win->spec_info) {
1646 			if (!xstrcmp(popup_win->spec_info->title, title)) {
1647 				//g_print("removing %s\n", title);
1648 				list_remove(itr);
1649 				destroy_popup_info(popup_win);
1650 				break;
1651 			}
1652 		}
1653 	}
1654 	list_iterator_destroy(itr);
1655 
1656 
1657 	return false;
1658 }
1659 
delete_popups(void)1660 extern gboolean delete_popups(void)
1661 {
1662 	ListIterator itr = list_iterator_create(popup_list);
1663 	popup_info_t *popup_win = NULL;
1664 
1665 	while ((popup_win = list_next(itr))) {
1666 		list_remove(itr);
1667 		destroy_popup_info(popup_win);
1668 	}
1669 	list_iterator_destroy(itr);
1670 
1671 	return false;
1672 }
1673 
popup_thr(popup_info_t * popup_win)1674 extern void *popup_thr(popup_info_t *popup_win)
1675 {
1676 	void (*specifc_info) (popup_info_t *popup_win) = NULL;
1677 	int running = 1;
1678 	if (_DEBUG)
1679 		g_print("popup_thr:global_row_count = %d \n",
1680 			global_row_count);
1681 	switch(popup_win->type) {
1682 	case PART_PAGE:
1683 		specifc_info = specific_info_part;
1684 		break;
1685 	case JOB_PAGE:
1686 		specifc_info = specific_info_job;
1687 		break;
1688 	case NODE_PAGE:
1689 		specifc_info = specific_info_node;
1690 		break;
1691 	case RESV_PAGE:
1692 		specifc_info = specific_info_resv;
1693 		break;
1694 	case FRONT_END_PAGE:
1695 		specifc_info = specific_info_front_end;
1696 		break;
1697 	case BB_PAGE:
1698 		specifc_info = specific_info_bb;
1699 		break;
1700 	case SUBMIT_PAGE:
1701 	default:
1702 		g_print("thread got unknown type %d\n", popup_win->type);
1703 		return NULL;
1704 	}
1705 	/* this will switch to 0 when popup is closed. */
1706 	popup_win->running = &running;
1707 	/* when popup is killed running will be set to 0 */
1708 	while (running) {
1709 		gdk_threads_enter();
1710 		(specifc_info)(popup_win);
1711 		gdk_threads_leave();
1712 		sleep(working_sview_config.refresh_delay);
1713 	}
1714 	return NULL;
1715 }
1716 
set_for_update(GtkTreeModel * model,int updated)1717 extern void set_for_update(GtkTreeModel *model, int updated)
1718 {
1719 	GtkTreePath *path = gtk_tree_path_new_first();
1720 	GtkTreeIter iter;
1721 
1722 	/* mark all current rows as in need of an update. */
1723 	if (path && gtk_tree_model_get_iter(model, &iter, path)) {
1724 		/* This process will make sure all iter's in the
1725 		 * tree_store will be mark as needing to be updated.
1726 		 * If it is still 0 after the update then it is old
1727 		 * data and will be removed with remove_old()
1728 		 */
1729 		while (1) {
1730 			gtk_tree_store_set(GTK_TREE_STORE(model), &iter,
1731 					   updated, 0, -1);
1732 			if (!gtk_tree_model_iter_next(model, &iter)) {
1733 				break;
1734 			}
1735 		}
1736 	}
1737 
1738 	if (path)
1739 		gtk_tree_path_free(path);
1740 }
1741 
remove_old(GtkTreeModel * model,int updated)1742 extern void remove_old(GtkTreeModel *model, int updated)
1743 {
1744 	GtkTreePath *path = gtk_tree_path_new_first();
1745 	GtkTreeIter iter;
1746 	int i;
1747 
1748 	/* remove all old objects */
1749 	if (gtk_tree_model_get_iter(model, &iter, path)) {
1750 		while (1) {
1751 			gtk_tree_model_get(model, &iter, updated, &i, -1);
1752 			if (!i) {
1753 				if (!gtk_tree_store_remove(
1754 					    GTK_TREE_STORE(model),
1755 					    &iter))
1756 					break;
1757 				else
1758 					continue;
1759 			}
1760 			if (!gtk_tree_model_iter_next(model, &iter)) {
1761 				break;
1762 			}
1763 		}
1764 	}
1765 	gtk_tree_path_free(path);
1766 }
1767 
create_pulldown_combo(display_data_t * display_data)1768 extern GtkWidget *create_pulldown_combo(display_data_t *display_data)
1769 {
1770 	GtkListStore *store = NULL;
1771 	GtkWidget *combo = NULL;
1772 	GtkTreeIter iter;
1773 	GtkCellRenderer *renderer = NULL;
1774 	int i=0;
1775 
1776 	store = gtk_list_store_new(2, G_TYPE_INT, G_TYPE_STRING);
1777 	while (display_data[i].id != -1) {
1778 		gtk_list_store_append(store, &iter);
1779 		gtk_list_store_set(store, &iter, 0, display_data[i].id,
1780 				   1, display_data[i].name, -1);
1781 		i++;
1782 	}
1783 	combo = gtk_combo_box_new_with_model(GTK_TREE_MODEL(store));
1784 
1785 	g_object_unref(store);
1786 	renderer = gtk_cell_renderer_text_new();
1787 	gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(combo), renderer, true);
1788 	gtk_cell_layout_add_attribute(GTK_CELL_LAYOUT(combo), renderer,
1789 				      "text", 1);
1790 
1791 	gtk_combo_box_set_active (GTK_COMBO_BOX (combo), 0);
1792 	return combo;
1793 }
1794 
1795 /*
1796  * str_tolower - convert string to all lower case
1797  * upper_str IN - upper case input string
1798  * RET - lower case version of upper_str, caller must be xfree
1799  */
str_tolower(char * upper_str)1800 extern char *str_tolower(char *upper_str)
1801 {
1802 	int i = strlen(upper_str) + 1;
1803 	char *lower_str = xmalloc(i);
1804 
1805 	for (i=0; upper_str[i]; i++)
1806 		lower_str[i] = tolower((int) upper_str[i]);
1807 
1808 	return lower_str;
1809 }
1810 
get_reason(void)1811 extern char *get_reason(void)
1812 {
1813 	char *reason_str = NULL;
1814 	int len = 0;
1815 	GtkWidget *table = gtk_table_new(1, 2, false);
1816 	GtkWidget *label = gtk_label_new("Reason ");
1817 	GtkWidget *entry = gtk_entry_new();
1818 	GtkWidget *popup = gtk_dialog_new_with_buttons(
1819 		"State change reason",
1820 		GTK_WINDOW(main_window),
1821 		GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
1822 		GTK_STOCK_OK,
1823 		GTK_RESPONSE_OK,
1824 		GTK_STOCK_CANCEL,
1825 		GTK_RESPONSE_CANCEL,
1826 		NULL);
1827 	int response = 0;
1828 	char *user_name = NULL;
1829 	char time_str[32];
1830 	time_t now = time(NULL);
1831 
1832 	gtk_window_set_type_hint(GTK_WINDOW(popup),
1833 				 GDK_WINDOW_TYPE_HINT_NORMAL);
1834 
1835 	gtk_container_set_border_width(GTK_CONTAINER(table), 10);
1836 
1837 	gtk_box_pack_start(GTK_BOX(GTK_DIALOG(popup)->vbox),
1838 			   table, false, false, 0);
1839 
1840 	gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 0, 1);
1841 	gtk_table_attach_defaults(GTK_TABLE(table), entry, 1, 2, 0, 1);
1842 
1843 	gtk_widget_show_all(popup);
1844 	response = gtk_dialog_run (GTK_DIALOG(popup));
1845 
1846 	if (response == GTK_RESPONSE_OK)
1847 	{
1848 		reason_str = xstrdup(gtk_entry_get_text(GTK_ENTRY(entry)));
1849 		len = strlen(reason_str) - 1;
1850 		if (len == -1) {
1851 			xfree(reason_str);
1852 			reason_str = NULL;
1853 			goto end_it;
1854 		}
1855 		/* Append user, date and time */
1856 		xstrcat(reason_str, " [");
1857 		user_name = getlogin();
1858 		if (user_name)
1859 			xstrcat(reason_str, user_name);
1860 		else
1861 			xstrfmtcat(reason_str, "%d", getuid());
1862 		slurm_make_time_str(&now, time_str, sizeof(time_str));
1863 		xstrfmtcat(reason_str, "@%s]", time_str);
1864 	} else
1865 		reason_str = xstrdup("cancelled");
1866 end_it:
1867 	gtk_widget_destroy(popup);
1868 
1869 	return reason_str;
1870 }
1871 
display_admin_edit(GtkTable * table,void * type_msg,int * row,GtkTreeModel * model,GtkTreeIter * iter,display_data_t * display_data,GCallback changed_callback,GCallback focus_callback,void (* set_active)(GtkComboBox * combo,GtkTreeModel * model,GtkTreeIter * iter,int type))1872 extern void display_admin_edit(GtkTable *table, void *type_msg, int *row,
1873 			       GtkTreeModel *model, GtkTreeIter *iter,
1874 			       display_data_t *display_data,
1875 			       GCallback changed_callback,
1876 			       GCallback focus_callback,
1877 			       void (*set_active)(
1878 				       GtkComboBox *combo,
1879 				       GtkTreeModel *model, GtkTreeIter *iter,
1880 				       int type))
1881 {
1882 	GtkWidget *label = NULL;
1883 	GtkWidget *entry = NULL;
1884 
1885 	if (display_data->extra == EDIT_MODEL) {
1886 		/* edittable items that can only be known
1887 		   values */
1888 		GtkCellRenderer *renderer = NULL;
1889 		GtkTreeModel *model2 = GTK_TREE_MODEL(
1890 			(display_data->create_model)(display_data->id));
1891 		if (!model2) {
1892 			g_print("no model set up for %d(%s)\n",
1893 				display_data->id,
1894 				display_data->name);
1895 			return;
1896 		}
1897 		entry = gtk_combo_box_new_with_model(model2);
1898 		g_object_unref(model2);
1899 
1900 /*		(callback)_set_active_combo_part(GTK_COMBO_BOX(entry), model, */
1901 /*				       iter, display_data->id); */
1902 		(set_active)(GTK_COMBO_BOX(entry), model,
1903 			     iter, display_data->id);
1904 
1905 		g_signal_connect(entry, "changed",
1906 				 changed_callback,
1907 				 type_msg);
1908 
1909 		renderer = gtk_cell_renderer_text_new();
1910 		gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(entry),
1911 					   renderer, true);
1912 		gtk_cell_layout_add_attribute(GTK_CELL_LAYOUT(entry),
1913 					      renderer, "text", 0);
1914 	} else if (display_data->extra == EDIT_TEXTBOX) {
1915 		char *temp_char = NULL;
1916 		/* other edittable items that are unknown */
1917 		entry = create_entry();
1918 		if (model) {
1919 			gtk_tree_model_get(model, iter,
1920 					   display_data->id,
1921 					   &temp_char, -1);
1922 		}
1923 		gtk_entry_set_max_length(GTK_ENTRY(entry),
1924 					 (DEFAULT_ENTRY_LENGTH +
1925 					  display_data->id));
1926 
1927 		if (temp_char) {
1928 			gtk_entry_set_text(GTK_ENTRY(entry),
1929 					   temp_char);
1930 			g_free(temp_char);
1931 		}
1932 		g_signal_connect(entry, "focus-out-event",
1933 				 focus_callback,
1934 				 type_msg);
1935 
1936 		/* set global variable so we know something changed */
1937 		g_signal_connect(entry, "changed",
1938 				 G_CALLBACK(entry_changed),
1939 				 NULL);
1940 	} else /* others can't be altered by the user */
1941 		return;
1942 	label = gtk_label_new(display_data->name);
1943 	/* left justify */
1944 	gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
1945 	gtk_table_attach(table, label, 0, 1, *row, (*row)+1,
1946 			 GTK_FILL | GTK_EXPAND, GTK_SHRINK,
1947 			 0, 0);
1948 	gtk_table_attach(table, entry, 1, 2, *row, (*row)+1,
1949 			 GTK_FILL, GTK_SHRINK,
1950 			 0, 0);
1951 	(*row)++;
1952 }
1953 
display_edit_note(char * edit_note)1954 extern void display_edit_note(char *edit_note)
1955 {
1956 	GError *error = NULL;
1957 	int msg_id = 0;
1958 
1959 	if (!edit_note)
1960 		return;
1961 
1962 	gtk_statusbar_pop(GTK_STATUSBAR(main_statusbar), STATUS_ADMIN_EDIT);
1963 	msg_id = gtk_statusbar_push(GTK_STATUSBAR(main_statusbar),
1964 				    STATUS_ADMIN_EDIT,
1965 				    edit_note);
1966 	if (!sview_thread_new(_editing_thr, GINT_TO_POINTER(msg_id),
1967 			      false, &error))
1968 		g_printerr("Failed to create edit thread: %s\n",
1969 			   error->message);
1970 
1971 	return;
1972 }
1973 
add_display_treestore_line(int update,GtkTreeStore * treestore,GtkTreeIter * iter,const char * name,const char * value)1974 extern void add_display_treestore_line(int update,
1975 				       GtkTreeStore *treestore,
1976 				       GtkTreeIter *iter,
1977 				       const char *name,
1978 				       const char *value)
1979 {
1980 	if (!name) {
1981 /*		g_print("error, name = %s and value = %s\n", */
1982 /*			name, value); */
1983 		return;
1984 	}
1985 	if (update) {
1986 		char *display_name = NULL;
1987 		GtkTreePath *path = gtk_tree_path_new_first();
1988 		gtk_tree_model_get_iter(GTK_TREE_MODEL(treestore), iter, path);
1989 
1990 		while (1) {
1991 			/* search for the jobid and check to see if
1992 			   it is in the list */
1993 			gtk_tree_model_get(GTK_TREE_MODEL(treestore), iter,
1994 					   DISPLAY_NAME,
1995 					   &display_name, -1);
1996 			if (!xstrcmp(display_name, name)) {
1997 				/* update with new info */
1998 				g_free(display_name);
1999 				goto found;
2000 			}
2001 			g_free(display_name);
2002 
2003 			if (!gtk_tree_model_iter_next(GTK_TREE_MODEL(treestore),
2004 						      iter)) {
2005 				return;
2006 			}
2007 		}
2008 
2009 	} else {
2010 		gtk_tree_store_append(treestore, iter, NULL);
2011 	}
2012 found:
2013 	gtk_tree_store_set(treestore, iter,
2014 			   DISPLAY_NAME,  name,
2015 			   DISPLAY_VALUE, value,
2016 			   -1);
2017 
2018 	return;
2019 }
2020 
add_display_treestore_line_with_font(int update,GtkTreeStore * treestore,GtkTreeIter * iter,const char * name,char * value,char * font)2021 extern void add_display_treestore_line_with_font(
2022 	int update,
2023 	GtkTreeStore *treestore,
2024 	GtkTreeIter *iter,
2025 	const char *name, char *value,
2026 	char *font)
2027 {
2028 	if (!name) {
2029 /*		g_print("error, name = %s and value = %s\n", */
2030 /*			name, value); */
2031 		return;
2032 	}
2033 	if (update) {
2034 		char *display_name = NULL;
2035 		GtkTreePath *path = gtk_tree_path_new_first();
2036 		gtk_tree_model_get_iter(GTK_TREE_MODEL(treestore), iter, path);
2037 
2038 		while (1) {
2039 			/* search for the jobid and check to see if
2040 			   it is in the list */
2041 			gtk_tree_model_get(GTK_TREE_MODEL(treestore), iter,
2042 					   DISPLAY_NAME,
2043 					   &display_name, -1);
2044 			if (!xstrcmp(display_name, name)) {
2045 				/* update with new info */
2046 				g_free(display_name);
2047 				goto found;
2048 			}
2049 			g_free(display_name);
2050 
2051 			if (!gtk_tree_model_iter_next(GTK_TREE_MODEL(treestore),
2052 						      iter)) {
2053 				return;
2054 			}
2055 		}
2056 
2057 	} else {
2058 		gtk_tree_store_append(treestore, iter, NULL);
2059 	}
2060 found:
2061 	gtk_tree_store_set(treestore, iter,
2062 			   DISPLAY_NAME,  name,
2063 			   DISPLAY_VALUE, value,
2064 			   DISPLAY_FONT,  font,
2065 			   -1);
2066 
2067 	return;
2068 }
2069 
sview_widget_modify_bg(GtkWidget * widget,GtkStateType state,const GdkColor color)2070 extern void sview_widget_modify_bg(GtkWidget *widget, GtkStateType state,
2071 				   const GdkColor color)
2072 {
2073 	gtk_widget_modify_bg(widget, state, &color);
2074 }
2075 
sview_radio_action_set_current_value(GtkRadioAction * action,gint current_value)2076 extern void sview_radio_action_set_current_value(GtkRadioAction *action,
2077 						 gint current_value)
2078 {
2079 #ifdef GTK2_USE_RADIO_SET
2080 	gtk_radio_action_set_current_value(action, current_value);
2081 #else
2082 	GSList *slist, *group;
2083 	int i=0;
2084 	/* gtk_radio_action_set_current_value wasn't added to
2085 	   GTK until 2.10, it turns out this is what is required to
2086 	   set the correct value.
2087 	*/
2088 	g_return_if_fail(GTK_IS_RADIO_ACTION(action));
2089 
2090 	if ((group = gtk_radio_action_get_group(action))) {
2091 		/* for some reason groups are set backwards like a
2092 		   stack, g_slist_reverse will fix this but takes twice
2093 		   as long so just figure out the length, they add 1
2094 		   to it sense 0 isn't a number and then subtract the
2095 		   value to get the augmented in the stack.
2096 		*/
2097 		current_value = g_slist_length(group) - 1 - current_value;
2098 		if (current_value < 0) {
2099 			g_warning("Radio group does not contain an action "
2100 				  "with value '%d'\n", current_value);
2101 			return;
2102 		}
2103 
2104 		for (slist = group; slist; slist = slist->next) {
2105 			if (i == current_value) {
2106 				gtk_toggle_action_set_active(
2107 					GTK_TOGGLE_ACTION(slist->data), true);
2108 				return;
2109 			}
2110 			i++;
2111 		}
2112 	}
2113 #endif
2114 }
2115 
page_to_str(int page)2116 extern char *page_to_str(int page)
2117 {
2118 	switch (page) {
2119 	case JOB_PAGE:
2120 		return "Job";
2121 	case PART_PAGE:
2122 		return "Partition";
2123 	case RESV_PAGE:
2124 		return "Reservation";
2125 	case BB_PAGE:
2126 		return "BurstBuffer";
2127 	case NODE_PAGE:
2128 		return "Node";
2129 	case FRONT_END_PAGE:
2130 		return "Frontend";
2131 	default:
2132 		return NULL;
2133 	}
2134 }
2135 
tab_pos_to_str(int pos)2136 extern char *tab_pos_to_str(int pos)
2137 {
2138 	switch (pos) {
2139 	case GTK_POS_TOP:
2140 		return "Top";
2141 	case GTK_POS_BOTTOM:
2142 		return "Bottom";
2143 	case GTK_POS_LEFT:
2144 		return "Left";
2145 	case GTK_POS_RIGHT:
2146 		return "Right";
2147 	default:
2148 		return "Unknown";
2149 	}
2150 }
2151 
visible_to_str(sview_config_t * sview_config)2152 extern char *visible_to_str(sview_config_t *sview_config)
2153 {
2154 	char *ret = NULL;
2155 	int i;
2156 
2157 	for (i = 0; i < PAGE_CNT; i++) {
2158 		if (sview_config->page_visible[i] && (i != TAB_PAGE)) {
2159 			if (ret)
2160 				xstrcat(ret, ",");
2161 			xstrcat(ret, page_to_str(i));
2162 		}
2163 	}
2164 
2165 	return ret;
2166 }
2167 
entry_changed(GtkWidget * widget,void * msg)2168 extern gboolean entry_changed(GtkWidget *widget, void *msg)
2169 {
2170 	global_entry_changed = 1;
2171 	return false;
2172 }
2173 
select_admin_common(GtkTreeModel * model,GtkTreeIter * iter,display_data_t * display_data,GtkTreeView * treeview,uint32_t node_col,void (* process_each)(GtkTreeModel * model,GtkTreePath * path,GtkTreeIter * iter,gpointer userdata))2174 extern void select_admin_common(GtkTreeModel *model, GtkTreeIter *iter,
2175 				display_data_t *display_data,
2176 				GtkTreeView *treeview,
2177 				uint32_t node_col,
2178 				void (*process_each)(GtkTreeModel *model,
2179 						     GtkTreePath *path,
2180 						     GtkTreeIter *iter,
2181 						     gpointer userdata))
2182 {
2183 	GtkTreePath *path;
2184 	GtkTreeRowReference *ref;
2185 	GtkTreeSelection *selection;
2186 	GList *list = NULL, *selected_rows = NULL;
2187 
2188 	if (!treeview)
2189 		return;
2190 
2191 	if (display_data->extra & EXTRA_NODES) {
2192 		select_admin_nodes(model, iter, display_data,
2193 				   node_col, treeview);
2194 		return;
2195 	}
2196 
2197 	global_multi_error = false;
2198 
2199 	selection = gtk_tree_view_get_selection(treeview);
2200 	selected_rows =	gtk_tree_selection_get_selected_rows(selection, &model);
2201 
2202 	for (list = selected_rows; list; list = g_list_next(list)) {
2203 		ref = gtk_tree_row_reference_new(model, list->data);
2204 		path = gtk_tree_row_reference_get_path(ref);
2205 		(*(process_each))(model, path, iter, display_data->name);
2206 		gtk_tree_path_free(path);
2207 		gtk_tree_row_reference_free(ref);
2208 	}
2209 
2210 	g_list_foreach(selected_rows, (GFunc)gtk_tree_path_free, NULL);
2211 	g_list_free(selected_rows);
2212 
2213 	return;
2214 }
2215