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