multiping.c 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857
  1. /*____________________________________________________________________________
  2. gkrellm multiping plugin
  3. Copyright (C) 2010 Jindrich Makovicka
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, Write to the Free Software
  14. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  15. ____________________________________________________________________________*/
  16. #include <stdio.h>
  17. #include <string.h>
  18. #include <gkrellm2/gkrellm.h>
  19. #include <sys/types.h>
  20. #include <sys/wait.h>
  21. #include "decal_multiping_status.xpm"
  22. #define CONFIG_NAME "Multiping"
  23. #define STYLE_NAME "multiping"
  24. #define COMMAND HELPERDIR"/pinger"
  25. static GkrellmMonitor *monitor;
  26. static GkrellmPanel *panel;
  27. static gint style_id;
  28. static FILE *pinger_pipe = NULL;
  29. static pid_t pinger_pid;
  30. static gboolean delete_list;
  31. static gboolean list_modified;
  32. static GtkWidget *plugin_vbox;
  33. static GtkWidget *label_entry;
  34. static GtkWidget *url_entry;
  35. static GtkWidget *updatefreq_spin;
  36. static GtkWidget *show_trip_checkbutton;
  37. static GtkWidget *dynamic_checkbutton;
  38. static GtkTreeView *multiping_treeview;
  39. static GtkTreeRowReference *row_reference;
  40. static GtkTreeSelection *selection;
  41. static GkrellmPiximage *decal_status_image;
  42. static GdkPixmap *status_pixmap;
  43. static GdkBitmap *status_mask;
  44. static gint vspacing, hspacing, time_xoffset;
  45. static gint helper_err = 0;
  46. typedef struct _host_data {
  47. GString *name, *ip, *percentage, *sent_str, *recv_str, *msg, *shortmsg;
  48. gint updatefreq;
  49. GkrellmDecal *name_text, *msg_text, *decal_pix;
  50. gboolean show_trip, dynamic;
  51. } host_data;
  52. static GList *hosts;
  53. enum {
  54. LABEL_COLUMN,
  55. HOST_COLUMN,
  56. TRIP_COLUMN,
  57. DYNAMIC_COLUMN,
  58. INTERVAL_COLUMN,
  59. DUMMY_COLUMN,
  60. N_COLUMNS
  61. };
  62. static host_data *host_malloc()
  63. {
  64. host_data *h = (host_data *) g_malloc(sizeof(host_data));
  65. h->name_text = NULL;
  66. h->msg_text = NULL;
  67. h->decal_pix = NULL;
  68. h->name = g_string_new(NULL);
  69. h->ip = g_string_new(NULL);
  70. h->percentage = g_string_new(NULL);
  71. h->sent_str = g_string_new(NULL);
  72. h->recv_str = g_string_new(NULL);
  73. h->msg = g_string_new(NULL);
  74. h->shortmsg = g_string_new("wait");
  75. h->updatefreq = 60;
  76. h->show_trip = 0;
  77. h->dynamic = 0;
  78. return h;
  79. }
  80. static void host_free(host_data * h)
  81. {
  82. if (h->name_text) {
  83. gkrellm_destroy_decal(h->name_text);
  84. }
  85. if (h->msg_text) {
  86. gkrellm_destroy_decal(h->msg_text);
  87. }
  88. if (h->decal_pix) {
  89. gkrellm_destroy_decal(h->decal_pix);
  90. }
  91. g_string_free(h->name, TRUE);
  92. g_string_free(h->ip, TRUE);
  93. g_string_free(h->percentage, TRUE);
  94. g_string_free(h->sent_str, TRUE);
  95. g_string_free(h->recv_str, TRUE);
  96. g_string_free(h->msg, TRUE);
  97. g_string_free(h->shortmsg, TRUE);
  98. g_free(h);
  99. }
  100. static void strip_nl(gchar *buf)
  101. {
  102. if (buf[strlen(buf) - 1] == '\n')
  103. buf[strlen(buf) - 1] = 0;
  104. }
  105. static void host_read_pipe(host_data * h)
  106. {
  107. gchar buf[512];
  108. char* res = fgets(buf, 512, pinger_pipe);
  109. if (res == 0) {
  110. helper_err = 1;
  111. return;
  112. }
  113. strip_nl(buf);
  114. g_string_assign(h->percentage, buf);
  115. fgets(buf, 512, pinger_pipe);
  116. strip_nl(buf);
  117. g_string_assign(h->sent_str, buf);
  118. fgets(buf, 512, pinger_pipe);
  119. strip_nl(buf);
  120. g_string_assign(h->recv_str, buf);
  121. fgets(buf, 512, pinger_pipe);
  122. strip_nl(buf);
  123. g_string_assign(h->msg, buf);
  124. fgets(buf, 512, pinger_pipe);
  125. strip_nl(buf);
  126. g_string_assign(h->shortmsg, buf);
  127. }
  128. static void kill_pinger()
  129. {
  130. if (pinger_pipe) {
  131. kill(pinger_pid, SIGTERM);
  132. waitpid(pinger_pid, NULL, 0);
  133. fclose(pinger_pipe);
  134. pinger_pipe = NULL;
  135. }
  136. }
  137. static void launch_pipe()
  138. {
  139. GString *s = g_string_new(COMMAND);
  140. gint i;
  141. GList *list;
  142. host_data *h;
  143. pid_t pid;
  144. gint mypipe[2];
  145. for (i = 0, list = hosts; list; list = list->next, i++) {
  146. char freq[5];
  147. h = (host_data *) list->data;
  148. g_string_append(s, " ");
  149. g_string_append(s, h->ip->str);
  150. g_string_append(s, " ");
  151. sprintf(freq, "%3d", h->updatefreq);
  152. g_string_append(s, freq);
  153. g_string_append(s, " ");
  154. g_string_append(s, h->dynamic ? "1" : "0");
  155. }
  156. if (pipe(mypipe)) {
  157. fprintf(stderr, "Pipe failed.\n");
  158. return;
  159. }
  160. pid = fork();
  161. if (pid == 0) {
  162. /* This is the child process. Execute the shell command. */
  163. close(mypipe[0]);
  164. dup2(mypipe[1], 1);
  165. execl("/bin/sh", "/bin/sh", "-c", s->str, NULL);
  166. _exit(EXIT_FAILURE);
  167. } else if (pid < 0) {
  168. /* The fork failed. Report failure. */
  169. fprintf(stderr, "failed to fork\n");
  170. } else {
  171. /* This is the parent process. Prepare the pipe stream. */
  172. close(mypipe[1]);
  173. pinger_pipe = fdopen(mypipe[0], "r");
  174. pinger_pid = pid;
  175. }
  176. g_string_free(s, TRUE);
  177. }
  178. /*
  179. static void
  180. host_append_info(host_data *h, GString *str)
  181. {
  182. GString *s = g_string_new(NULL);
  183. g_string_sprintf(s, "%s: %s, %s\n",
  184. h->name->str, h->percentage->str, h->msg->str);
  185. g_string_append(str, s->str);
  186. g_string_free(s, TRUE);
  187. }
  188. */
  189. static void host_draw_name(host_data * h)
  190. {
  191. gkrellm_draw_decal_text(panel, h->name_text, h->name->str, -1);
  192. }
  193. static void host_draw_msg(host_data * h)
  194. {
  195. gint n, p;
  196. if (h->show_trip) {
  197. gkrellm_draw_decal_text(panel, h->msg_text, h->shortmsg->str, -1);
  198. }
  199. n = sscanf(h->percentage->str, "%d", &p);
  200. if (n != 1 || p == 0) {
  201. gkrellm_draw_decal_pixmap(panel, h->decal_pix, 0);
  202. } else if (p < 100) {
  203. gkrellm_draw_decal_pixmap(panel, h->decal_pix, 2);
  204. } else {
  205. gkrellm_draw_decal_pixmap(panel, h->decal_pix, 1);
  206. }
  207. }
  208. static GList *append_host(GList * list, gchar * name, gchar * ip, gboolean show_trip, gboolean dynamic, gint updatefreq)
  209. {
  210. host_data *h = host_malloc();
  211. g_string_assign(h->name, name);
  212. g_string_assign(h->ip, ip);
  213. h->show_trip = show_trip;
  214. h->dynamic = dynamic;
  215. h->updatefreq = updatefreq;
  216. return g_list_append(list, h);
  217. }
  218. static gint
  219. display_host(host_data * h, GkrellmStyle * style, GkrellmTextstyle * ts,
  220. GkrellmTextstyle * ts_alt, gint y)
  221. {
  222. if (h->show_trip) {
  223. h->msg_text =
  224. gkrellm_create_decal_text(panel, "999", ts_alt, style, 0, y, 0);
  225. h->msg_text->x = gkrellm_chart_width() - h->msg_text->w + time_xoffset;
  226. }
  227. h->decal_pix =
  228. gkrellm_create_decal_pixmap(panel, status_pixmap, status_mask, 3,
  229. style, -1, y);
  230. h->name_text =
  231. gkrellm_create_decal_text(panel, "Ay", ts, style,
  232. h->decal_pix->x+h->decal_pix->w+hspacing, y, -1);
  233. if (h->name_text->h < h->decal_pix->h) {
  234. h->name_text->y += (h->decal_pix->h-h->name_text->h)/2;
  235. if (h->show_trip) {
  236. h->msg_text->y = h->name_text->y;
  237. }
  238. return h->decal_pix->y + h->decal_pix->h + vspacing;
  239. } else {
  240. h->decal_pix->y += (h->name_text->h-h->decal_pix->h)/2;
  241. return h->name_text->y + h->name_text->h + vspacing;
  242. }
  243. }
  244. static gint panel_click_event(GtkWidget * widget, GdkEventButton * ev)
  245. {
  246. if (ev->button == 3)
  247. gkrellm_open_config_window(monitor);
  248. return 1;
  249. }
  250. static gint panel_expose_event(GtkWidget * widget, GdkEventExpose * ev)
  251. {
  252. gdk_draw_pixmap(widget->window,
  253. widget->style->fg_gc[GTK_WIDGET_STATE(widget)],
  254. panel->pixmap, ev->area.x, ev->area.y, ev->area.x,
  255. ev->area.y, ev->area.width, ev->area.height);
  256. return FALSE;
  257. }
  258. static void update_plugin()
  259. {
  260. fd_set fds;
  261. struct timeval tv;
  262. gint ret;
  263. GString *str = g_string_new(NULL);
  264. FD_ZERO(&fds);
  265. FD_SET(fileno(pinger_pipe), &fds);
  266. tv.tv_sec = 0;
  267. tv.tv_usec = 0;
  268. ret = select(fileno(pinger_pipe) + 1, &fds, 0, 0, &tv);
  269. if (ret) {
  270. g_list_foreach(hosts, (GFunc) host_read_pipe, NULL);
  271. g_list_foreach(hosts, (GFunc) host_draw_msg, NULL);
  272. gkrellm_draw_panel_layers(panel);
  273. }
  274. if (helper_err) {
  275. kill_pinger();
  276. launch_pipe();
  277. helper_err = 0;
  278. }
  279. /*
  280. if (GK.minute_tick && tooltip) {
  281. // if (tooltip->tip_window == NULL || !GTK_WIDGET_VISIBLE(tooltip->tip_window)) {
  282. g_list_foreach(hosts, (GFunc)host_append_info, str);
  283. gtk_tooltips_set_tip(tooltip, panel->drawing_area, str->str, NULL);
  284. gtk_tooltips_set_delay(tooltip, 750);
  285. gtk_tooltips_enable(tooltip);
  286. // }
  287. }
  288. */
  289. g_string_free(str, TRUE);
  290. }
  291. static void
  292. setup_display(gboolean first_create)
  293. {
  294. gshort i;
  295. gint y;
  296. GkrellmStyle *style;
  297. GkrellmTextstyle *ts, *ts_alt;
  298. GList *list;
  299. host_data *h;
  300. if (first_create) {
  301. panel = gkrellm_panel_new0();
  302. }
  303. style = gkrellm_panel_style(style_id);
  304. ts = gkrellm_meter_textstyle(style_id);
  305. ts_alt = gkrellm_meter_alt_textstyle(style_id);
  306. y = 3;
  307. // y = style->top_margin;
  308. for (i = 0, list = hosts; list; list = list->next, i++) {
  309. h = (host_data *) list->data;
  310. y = display_host(h, style, ts, ts_alt, y);
  311. }
  312. gkrellm_panel_configure(panel, NULL, style);
  313. gkrellm_panel_create(plugin_vbox, monitor, panel);
  314. if (first_create) {
  315. g_signal_connect(GTK_OBJECT(panel->drawing_area), "expose_event",
  316. (GtkSignalFunc) panel_expose_event, NULL);
  317. g_signal_connect(GTK_OBJECT(panel->drawing_area),
  318. "button_release_event",
  319. (GtkSignalFunc) panel_click_event, NULL);
  320. }
  321. g_list_foreach(hosts, (GFunc) host_draw_name, NULL);
  322. g_list_foreach(hosts, (GFunc) host_draw_msg, NULL);
  323. gkrellm_draw_panel_layers(panel);
  324. }
  325. static void
  326. create_plugin(GtkWidget * vbox, gint first_create)
  327. {
  328. plugin_vbox = vbox;
  329. gkrellm_load_piximage("decal_multiping_status", decal_multiping_status_xpm,
  330. &decal_status_image, STYLE_NAME);
  331. gkrellm_scale_piximage_to_pixmap(decal_status_image, &status_pixmap,
  332. &status_mask, 0, 0);
  333. if (!gkrellm_get_gkrellmrc_integer("multiping_vspacing", &vspacing))
  334. vspacing = 2;
  335. if (!gkrellm_get_gkrellmrc_integer("multiping_hspacing", &hspacing))
  336. hspacing = 2;
  337. if (!gkrellm_get_gkrellmrc_integer("multiping_time_xoffset", &time_xoffset))
  338. time_xoffset = 0;
  339. kill_pinger();
  340. launch_pipe();
  341. setup_display(first_create);
  342. }
  343. static void
  344. change_row_reference(GtkTreeModel *model, GtkTreePath *path)
  345. {
  346. gtk_tree_row_reference_free(row_reference);
  347. if (model && path)
  348. row_reference = gtk_tree_row_reference_new(model, path);
  349. else
  350. row_reference = NULL;
  351. }
  352. static void
  353. reset_entries()
  354. {
  355. gtk_entry_set_text(GTK_ENTRY(label_entry), "");
  356. gtk_entry_set_text(GTK_ENTRY(url_entry), "");
  357. gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(show_trip_checkbutton), TRUE);
  358. gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dynamic_checkbutton), FALSE);
  359. gtk_spin_button_set_value(GTK_SPIN_BUTTON(updatefreq_spin),60);
  360. change_row_reference(NULL, NULL);
  361. gtk_tree_selection_unselect_all(selection);
  362. return;
  363. }
  364. static host_data *
  365. host_new_from_model(GtkTreeModel *model, GtkTreeIter *iter)
  366. {
  367. gchar *label;
  368. gchar *host;
  369. host_data *h;
  370. h = host_malloc();
  371. gtk_tree_model_get(model, iter,
  372. LABEL_COLUMN, &label,
  373. HOST_COLUMN, &host,
  374. TRIP_COLUMN, &h->show_trip,
  375. DYNAMIC_COLUMN, &h->dynamic,
  376. INTERVAL_COLUMN, &h->updatefreq,
  377. -1);
  378. h->name = g_string_new(label);
  379. h->ip = g_string_new(host);
  380. return h;
  381. }
  382. static void
  383. set_list_store_model_data(GtkListStore *store, GtkTreeIter *iter, host_data *h)
  384. {
  385. gtk_list_store_set(store, iter,
  386. LABEL_COLUMN, h->name->str,
  387. HOST_COLUMN, h->ip->str,
  388. TRIP_COLUMN, h->show_trip,
  389. DYNAMIC_COLUMN, h->dynamic,
  390. INTERVAL_COLUMN, h->updatefreq,
  391. DUMMY_COLUMN, "",
  392. -1);
  393. }
  394. static GtkTreeModel *
  395. create_model(void)
  396. {
  397. GtkListStore *store;
  398. GtkTreeIter iter;
  399. GList *list;
  400. host_data *h;
  401. store = gtk_list_store_new(N_COLUMNS,
  402. G_TYPE_STRING, G_TYPE_STRING, G_TYPE_BOOLEAN, G_TYPE_BOOLEAN,
  403. G_TYPE_INT, G_TYPE_STRING);
  404. for (list = hosts; list; list = list->next) {
  405. h = (host_data *) list->data;
  406. gtk_list_store_append(store, &iter);
  407. set_list_store_model_data(store, &iter, h);
  408. }
  409. return GTK_TREE_MODEL(store);
  410. }
  411. static void
  412. cb_selected(GtkWidget * clist, gint row, gint column,
  413. GdkEventButton * bevent, gpointer data)
  414. {
  415. GtkTreeIter iter;
  416. GtkTreeModel *model;
  417. GtkTreePath *path;
  418. host_data *h;
  419. if (!gtk_tree_selection_get_selected(selection, &model, &iter))
  420. {
  421. reset_entries();
  422. return;
  423. }
  424. path = gtk_tree_model_get_path(model, &iter);
  425. change_row_reference(model, path);
  426. gtk_tree_path_free(path);
  427. h = host_new_from_model(model, &iter);
  428. gtk_entry_set_text(GTK_ENTRY(label_entry), h->name->str);
  429. gtk_entry_set_text(GTK_ENTRY(url_entry), h->ip->str);
  430. gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(show_trip_checkbutton), h->show_trip);
  431. gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dynamic_checkbutton), h->dynamic);
  432. gtk_spin_button_set_value(GTK_SPIN_BUTTON(updatefreq_spin), h->updatefreq);
  433. host_free(h);
  434. return;
  435. }
  436. static void
  437. cb_enter(GtkWidget * widget, gpointer data)
  438. {
  439. GtkTreeModel *model;
  440. GtkTreePath *path = NULL;
  441. GtkTreeIter iter;
  442. host_data *h;
  443. gchar *buf[3];
  444. h = host_malloc();
  445. buf[0] = gkrellm_gtk_entry_get_text(&label_entry);
  446. buf[1] = gkrellm_gtk_entry_get_text(&url_entry);
  447. h->show_trip = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(show_trip_checkbutton));
  448. h->dynamic = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dynamic_checkbutton));
  449. buf[2] = gkrellm_gtk_entry_get_text(&updatefreq_spin);
  450. if ((strlen(buf[0]) == 0) || (strlen(buf[1]) == 0)) {
  451. host_free(h);
  452. return;
  453. }
  454. h->name = g_string_new(buf[0]);
  455. h->ip = g_string_new(buf[1]);
  456. h->updatefreq = atoi(buf[2]);
  457. model = gtk_tree_view_get_model(multiping_treeview);
  458. if (row_reference)
  459. {
  460. path = gtk_tree_row_reference_get_path(row_reference);
  461. gtk_tree_model_get_iter(model, &iter, path);
  462. }
  463. else
  464. {
  465. gtk_list_store_append(GTK_LIST_STORE(model), &iter);
  466. }
  467. set_list_store_model_data(GTK_LIST_STORE(model), &iter, h);
  468. host_free(h);
  469. reset_entries();
  470. list_modified = TRUE;
  471. }
  472. static void
  473. cb_delete(GtkWidget * widget, gpointer data)
  474. {
  475. GtkTreeModel *model;
  476. GtkTreePath *path;
  477. GtkTreeIter iter;
  478. if (!row_reference)
  479. return;
  480. model = gtk_tree_view_get_model(multiping_treeview);
  481. path = gtk_tree_row_reference_get_path(row_reference);
  482. gtk_tree_model_get_iter(model, &iter, path);
  483. gtk_list_store_remove(GTK_LIST_STORE(model), &iter);
  484. reset_entries();
  485. list_modified = TRUE;
  486. }
  487. static gboolean
  488. cb_drag_end(GtkWidget *widget, GdkDragContext *context, gpointer data)
  489. {
  490. reset_entries();
  491. list_modified = TRUE;
  492. return FALSE;
  493. }
  494. static gchar plugin_about_text[] =
  495. "GKrellM Multiping version " VERSION "\n\n\n"
  496. "Copyright (C) 2010 Jindrich Makovicka\n"
  497. "makovick@gmail.com\n"
  498. "Released under the GPL.\n";
  499. static void create_plugin_config(GtkWidget * tab_vbox)
  500. {
  501. GtkWidget *tabs;
  502. GtkWidget *vbox;
  503. GtkWidget *hbox;
  504. GtkWidget *label;
  505. GtkWidget *scrolled;
  506. GtkWidget *button;
  507. GtkAdjustment *spin_adjust;
  508. GtkWidget *info_label;
  509. GtkTreeModel *model;
  510. GtkCellRenderer *renderer;
  511. row_reference = NULL;
  512. list_modified = FALSE;
  513. /* Make a couple of tabs */
  514. tabs = gtk_notebook_new();
  515. gtk_notebook_set_tab_pos(GTK_NOTEBOOK(tabs), GTK_POS_TOP);
  516. gtk_box_pack_start(GTK_BOX(tab_vbox), tabs, TRUE, TRUE, 0);
  517. /* Sources tab */
  518. vbox = gkrellm_gtk_framed_notebook_page(tabs, "Hosts");
  519. hbox = gtk_hbox_new(FALSE, 0);
  520. gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, TRUE, 2);
  521. label = gtk_label_new("Label:");
  522. gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
  523. gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, TRUE, 2);
  524. label_entry = gtk_entry_new();
  525. gtk_entry_set_max_length(GTK_ENTRY(label_entry), 25);
  526. gtk_widget_set_size_request(label_entry, 180, -1);
  527. gtk_box_pack_start(GTK_BOX(hbox), label_entry, FALSE, TRUE, 0);
  528. label = gtk_label_new("Hostname / IP:");
  529. gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
  530. gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, TRUE, 2);
  531. url_entry = gtk_entry_new();
  532. gtk_entry_set_max_length(GTK_ENTRY(url_entry), 75);
  533. gtk_box_pack_start(GTK_BOX(hbox), url_entry, TRUE, TRUE, 2);
  534. hbox = gtk_hbox_new(FALSE, 0);
  535. gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, TRUE, 5);
  536. label = gtk_label_new("Ping interval:");
  537. gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
  538. gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, TRUE, 2);
  539. spin_adjust = (GtkAdjustment *) gtk_adjustment_new(0,10,3600,1.0,0,0);
  540. updatefreq_spin = gtk_spin_button_new(spin_adjust,1.0,0);
  541. gtk_spin_button_set_value(GTK_SPIN_BUTTON(updatefreq_spin),60);
  542. gtk_box_pack_start(GTK_BOX(hbox), updatefreq_spin, FALSE, TRUE, 0);
  543. label = gtk_label_new("seconds");
  544. gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, TRUE, 2);
  545. show_trip_checkbutton = gtk_check_button_new_with_label("Display trip time");
  546. gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(show_trip_checkbutton),TRUE);
  547. gtk_box_pack_start(GTK_BOX(hbox), show_trip_checkbutton, FALSE, TRUE, 0);
  548. dynamic_checkbutton = gtk_check_button_new_with_label("Dynamic DNS");
  549. gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dynamic_checkbutton),FALSE);
  550. gtk_box_pack_start(GTK_BOX(hbox), dynamic_checkbutton, FALSE, TRUE, 0);
  551. button = gtk_button_new_from_stock(GTK_STOCK_DELETE);
  552. g_signal_connect(GTK_OBJECT(button), "clicked",
  553. (GtkSignalFunc) cb_delete, NULL);
  554. gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, TRUE, 0);
  555. button = gtk_button_new_from_stock(GTK_STOCK_ADD);;
  556. g_signal_connect(GTK_OBJECT(button), "clicked",
  557. (GtkSignalFunc) cb_enter, NULL);
  558. gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, TRUE, 0);
  559. scrolled = gtk_scrolled_window_new(NULL, NULL);
  560. gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled),
  561. GTK_POLICY_AUTOMATIC,
  562. GTK_POLICY_AUTOMATIC);
  563. gtk_box_pack_start(GTK_BOX(vbox), scrolled, TRUE, TRUE, 0);
  564. /* Treeview */
  565. model = create_model();
  566. multiping_treeview = GTK_TREE_VIEW(gtk_tree_view_new_with_model(model));
  567. gtk_tree_view_set_rules_hint(multiping_treeview, TRUE);
  568. gtk_tree_view_set_reorderable(multiping_treeview, TRUE);
  569. g_signal_connect(G_OBJECT(multiping_treeview), "drag_end",
  570. G_CALLBACK(cb_drag_end), NULL);
  571. renderer = gtk_cell_renderer_text_new();
  572. gtk_tree_view_insert_column_with_attributes(multiping_treeview, -1, "Label",
  573. renderer,
  574. "text", LABEL_COLUMN, NULL);
  575. renderer = gtk_cell_renderer_text_new();
  576. gtk_tree_view_insert_column_with_attributes(multiping_treeview, -1, "Hostname / IP Address",
  577. renderer,
  578. "text", HOST_COLUMN, NULL);
  579. renderer = gtk_cell_renderer_toggle_new();
  580. gtk_tree_view_insert_column_with_attributes(multiping_treeview, -1, "Trip",
  581. renderer,
  582. "active", TRIP_COLUMN, NULL);
  583. renderer = gtk_cell_renderer_toggle_new();
  584. gtk_tree_view_insert_column_with_attributes(multiping_treeview, -1, "Dynamic",
  585. renderer,
  586. "active", DYNAMIC_COLUMN, NULL);
  587. renderer = gtk_cell_renderer_text_new();
  588. gtk_tree_view_insert_column_with_attributes(multiping_treeview, -1, "Ping int.",
  589. renderer,
  590. "text", INTERVAL_COLUMN, NULL);
  591. renderer = gtk_cell_renderer_text_new();
  592. gtk_tree_view_insert_column_with_attributes(multiping_treeview, -1, " ",
  593. renderer,
  594. "text", DUMMY_COLUMN, NULL);
  595. gtk_container_add(GTK_CONTAINER(scrolled), GTK_WIDGET(multiping_treeview));
  596. selection = gtk_tree_view_get_selection(multiping_treeview);
  597. gtk_tree_selection_set_mode(selection, GTK_SELECTION_SINGLE);
  598. g_signal_connect(G_OBJECT(selection), "changed",
  599. G_CALLBACK(cb_selected), NULL);
  600. /* About tab */
  601. info_label = gtk_label_new(plugin_about_text);
  602. label = gtk_label_new("About");
  603. gtk_notebook_append_page(GTK_NOTEBOOK(tabs), info_label, label);
  604. }
  605. static void apply_plugin_config()
  606. {
  607. if (list_modified) {
  608. GList *new_hosts;
  609. GtkTreeModel *model;
  610. GtkTreeIter iter;
  611. kill_pinger();
  612. new_hosts = NULL;
  613. model = gtk_tree_view_get_model(multiping_treeview);
  614. if (gtk_tree_model_get_iter_first(model, &iter)) {
  615. do {
  616. host_data *h;
  617. h = host_new_from_model(model, &iter);
  618. new_hosts = g_list_append(new_hosts, h);
  619. }
  620. while (gtk_tree_model_iter_next(model, &iter));
  621. }
  622. g_list_foreach(hosts, (GFunc) host_free, NULL);
  623. g_list_free(hosts);
  624. gkrellm_panel_destroy(panel);
  625. panel = gkrellm_panel_new0();
  626. hosts = new_hosts;
  627. setup_display(1);
  628. list_modified = FALSE;
  629. launch_pipe();
  630. }
  631. }
  632. static void save_plugin_config(FILE * f)
  633. {
  634. gchar *label;
  635. gchar *pt;
  636. GList *list;
  637. host_data *h;
  638. for (list = hosts; list; list = list->next) {
  639. h = (host_data *) list->data;
  640. //when saving, we convert spaces in labels to underscores
  641. label = g_strdup(h->name->str);
  642. for (pt = label; *pt; pt++)
  643. if (*pt == ' ')
  644. *pt = '_';
  645. fprintf(f, "multiping host %s %s %d %d %d\n", label, h->ip->str, h->show_trip,
  646. h->updatefreq, h->dynamic);
  647. g_free(label);
  648. }
  649. }
  650. static void load_plugin_config(gchar * arg)
  651. {
  652. gchar plugin_config[64];
  653. gchar item[256];
  654. gchar label[26];
  655. gchar ip[76];
  656. gint updatefreq;
  657. gchar *pt;
  658. gshort n;
  659. gboolean show_trip;
  660. gboolean dynamic;
  661. n = sscanf(arg, "%s %[^\n]", plugin_config, item);
  662. if (n == 2) {
  663. if (!strcmp(plugin_config, "host")) {
  664. if (delete_list) {
  665. g_list_foreach(hosts, (GFunc) host_free, NULL);
  666. g_list_free(hosts);
  667. delete_list = FALSE;
  668. }
  669. label[0] = '\0';
  670. ip[0] = '\0';
  671. show_trip = TRUE;
  672. dynamic = FALSE;
  673. sscanf(item, "%25s %75s %d %d %d", label, ip, &show_trip, &updatefreq, &dynamic);
  674. //when loading, we convert underscores in labels to spaces
  675. for (pt = label; *pt; pt++)
  676. if (*pt == '_')
  677. *pt = ' ';
  678. hosts = append_host(hosts, label, ip, show_trip, dynamic, updatefreq);
  679. }
  680. }
  681. }
  682. /* The monitor structure tells GKrellM how to call the plugin routines.
  683. */
  684. static GkrellmMonitor plugin_mon = {
  685. CONFIG_NAME, /* Name, for config tab. */
  686. 0, /* Id, 0 if a plugin */
  687. create_plugin, /* The create function */
  688. update_plugin, /* The update function */
  689. create_plugin_config, /* The config tab create function */
  690. apply_plugin_config, /* Apply the config function */
  691. save_plugin_config, /* Save user config */
  692. load_plugin_config, /* Load user config */
  693. "multiping", /* config keyword */
  694. NULL, /* Undefined 2 */
  695. NULL, /* Undefined 1 */
  696. NULL, /* private */
  697. MON_MAIL, /* Insert plugin before this monitor */
  698. NULL, /* Handle if a plugin, filled in by GKrellM */
  699. NULL /* path if a plugin, filled in by GKrellM */
  700. };
  701. GkrellmMonitor *gkrellm_init_plugin()
  702. {
  703. list_modified = FALSE;
  704. delete_list = TRUE;
  705. style_id = gkrellm_add_meter_style(&plugin_mon, STYLE_NAME);
  706. monitor = &plugin_mon;
  707. return &plugin_mon;
  708. }