/** * Fetch data from the selection of a clist. Returns a GSList containing * the user_data pointers from the selected rows. If allow_null is TRUE, * the returned list may contain NULL pointers. If cfn != NULL, it will * be used to determine whether two entries are equal and drop all duplicate * items from the result list. Using cfn will significantly increase runtime. */ GSList * clist_collect_data(GtkCList *clist, gboolean allow_null, GCompareFunc cfn) { GSList *result_list = NULL; GList *l; GSList *sl; GSList *to_unselect = NULL; g_assert(clist != NULL); /* * Collect the data of the selected rows. */ for (l = clist->selection; l != NULL; l = g_list_next(l)) { gpointer data; gint row; row = GPOINTER_TO_INT(l->data); data = gtk_clist_get_row_data(clist, row); if ((data != NULL) || allow_null) { if (cfn != NULL) { if (g_slist_find_custom(result_list, data, cfn) != NULL) { if (GUI_PROPERTY(gui_debug) >= 3) { const gchar *name = gtk_widget_get_name(GTK_WIDGET(clist)); printf("%s has duplicate data: %p\n", (name != NULL) ? name : "<UNKNOWN>", data); } to_unselect = g_slist_prepend(to_unselect, GINT_TO_POINTER(row)); continue; } } result_list = g_slist_prepend(result_list, data); to_unselect = g_slist_prepend(to_unselect, GINT_TO_POINTER(row)); } else { if (GUI_PROPERTY(gui_debug) >= 3) { const gchar *name = gtk_widget_get_name(GTK_WIDGET(clist)); printf("%s contains NULL data in row %d\n", (name != NULL) ? name : "<UNKNOWN>", row); } } } /* * Unselect the rows from which data has been sucessfully gathered. */ for (sl = to_unselect; sl != NULL; sl = g_slist_next(sl)) gtk_clist_unselect_row(clist, GPOINTER_TO_INT(sl->data), 0); g_slist_free(to_unselect); return result_list; }
/** * Callback: called when a node is removed from the backend. * * Removes all references to the node from the frontend. */ static void nodes_gui_node_removed(const struct nid *node_id) { if (GUI_PROPERTY(gui_debug) >= 5) g_debug("%s(%s)", G_STRFUNC, nid_to_string(node_id)); nodes_gui_remove_node(node_id); }
static inline int search_gui_cmp_strings(const char *a, const char *b) { if (a && b) { return a == b ? 0 : GUI_PROPERTY(search_sort_casesense) ? strcmp(a, b) : ascii_strcasecmp(a, b); } else { return a ? 1 : (b ? -1 : 0); } }
static void search_stats_gui_timer(time_t now) { static time_t last_update; time_delta_t interval = GUI_PROPERTY(search_stats_update_interval); if (!last_update || delta_time(now, last_update) > interval) { last_update = now; search_stats_gui_update_display(); } }
/** * Callback: called when a node is added from the backend. * * Adds the node to the gui. */ static void nodes_gui_node_added(const struct nid *node_id) { gnet_node_info_t info; if (GUI_PROPERTY(gui_debug) >= 5) g_debug("%s(%s)", G_STRFUNC, nid_to_string(node_id)); guc_node_fill_info(node_id, &info); nodes_gui_add_node(&info); guc_node_clear_info(&info); }
/** * helper func for stats_display - * does two things: * * - clears out aged / infrequent search terms * - sticks the rest of the search terms in clist_search_stats * */ static gboolean stats_hash_to_clist(gpointer key, gpointer value, gpointer unused_udata) { gchar *text[3]; gchar period_tmp[32]; gchar total_tmp[32]; struct term_counts *val = value; (void) unused_udata; /* update counts */ if (!val->period_cnt) val->periods++; else val->periods = 0; val->total_cnt += val->period_cnt; /* try to keep the number of infrequent terms down */ if ( (1.0 * val->total_cnt / (val->periods + 2.0)) * 100 < GUI_PROPERTY(search_stats_delcoef) ) { G_FREE_NULL(key); G_FREE_NULL(val); return TRUE; } stat_count++; /* update the display */ /* FIXME: make %8.8d %d and set up custom sort function */ gm_snprintf(period_tmp, sizeof period_tmp, "%8.8d", (int) val->period_cnt); gm_snprintf(total_tmp, sizeof total_tmp, "%8.8d", (int) val->total_cnt); text[0] = key; text[1] = period_tmp; text[2] = total_tmp; { GtkWidget *clist_search_stats = gui_main_window_lookup("clist_search_stats"); gtk_clist_insert(GTK_CLIST(clist_search_stats), 0, text); } /* new period begins */ val->period_cnt = 0; return FALSE; }
/** * Callback: called when a node is added from the backend. * * Adds the node to the gui. */ static void nodes_gui_node_added(const struct nid *node_id) { gnet_node_info_t *info; if (GUI_PROPERTY(gui_debug) >= 5) g_debug("nodes_gui_node_added(%s)\n", nid_to_string(node_id)); info = guc_node_get_info(node_id); if (info) { nodes_gui_add_node(info); guc_node_free_info(info); } }
/** * Helper func for stats_display - * does two things: * * - clears out aged / infrequent search terms * - sticks the rest of the search terms in treeview_search_stats */ static bool stats_hash_to_treeview(const void *key, void *value, void *unused_udata) { struct term_counts *val = value; GtkTreeIter iter; char *s; (void) unused_udata; /* update counts */ val->periods = val->period_cnt ? 0 : (val->periods + 1); val->total_cnt += val->period_cnt; /* try to keep the number of infrequent terms down */ if ( (1.0 * val->total_cnt / (val->periods + 2.0)) * 100 < GUI_PROPERTY(search_stats_delcoef) ) { free_hash_entry(key, value, NULL); return TRUE; } stat_count++; /* update the display */ s = key ? unknown_to_utf8_normalized(key, UNI_NORM_GUI, NULL) : NULL; gtk_list_store_append(store_search_stats, &iter); gtk_list_store_set(store_search_stats, &iter, 0, s, 1, (gulong) val->period_cnt, 2, (gulong) val->total_cnt, (-1)); if (key != s) { G_FREE_NULL(s); } /* new period begins */ val->period_cnt = 0; return FALSE; }
/** * Process all pending gtk events (id est draw now!). * * @returns TRUE if gtk_main_quit has been called * for the innermost mainloop. Aborts flush if * gtk_main_quit has been called. */ gint gtk_main_flush(void) { gint val = FALSE; gint i = 0; while (gtk_events_pending() && i++ < GTK_ITERATION_MAX) { val = gtk_main_iteration_do(FALSE); if (val) break; } if (i > GTK_ITERATION_MAX && !val) { if (GUI_PROPERTY(gui_debug)) { g_warning("gtk_main_flush: too much work"); } } return val; }
/** * Fetch data from the selection of a treeview. Returns a GSList containing * the user_data pointers from the selected rows. If cfn != NULL, it will * be used to determine whether two entries are equal and drop all duplicate * items from the result list. Using cfn will significantly increase runtime. */ GSList * tree_selection_collect_data(GtkTreeSelection *selection, tree_selection_get_data_func gdf, GCompareFunc cfn) { collect_data_struct_t cdata; g_assert(NULL != selection); cdata.results = NULL; cdata.to_unselect = NULL; cdata.cfn = cfn; cdata.gdf = gdf; cdata.tv = gtk_tree_selection_get_tree_view(selection); if (GUI_PROPERTY(gui_debug) >= 3) { cdata.name = gtk_widget_get_name( GTK_WIDGET(gtk_tree_selection_get_tree_view(selection))); if (NULL == cdata.name) cdata.name = "<UNKNOWN>"; } else cdata.name = NULL; /* * Browse selected rows and gather data. */ gtk_tree_selection_selected_foreach(selection, tree_selection_collect_data_helper, &cdata); /* * Now unselect the rows from which we got data. */ g_slist_foreach(cdata.to_unselect, tree_selection_unselect_helper, selection); /* * Cleanup before exit. */ gm_slist_free_null(&cdata.to_unselect); return cdata.results; }
static inline void tree_selection_collect_data_record(GtkTreeModel *model, GtkTreeIter *iter, collect_data_struct_t *cdata, gboolean unselect) { gpointer data; g_assert(NULL != cdata); g_assert(NULL != iter); data = cdata->gdf(model, iter); if (unselect) { cdata->to_unselect = g_slist_prepend(cdata->to_unselect, w_tree_iter_copy(iter)); } if (NULL != cdata->cfn && NULL != g_slist_find_custom(cdata->results, data, cdata->cfn)) { if (GUI_PROPERTY(gui_debug) >= 3) g_warning("%s has duplicate data: %p", cdata->name, data); return; } cdata->results = g_slist_prepend(cdata->results, data); }
/** * Compute info string for node. * * @return pointer to static data. */ const gchar * nodes_gui_common_status_str(const gnet_node_status_t *n) { static gchar gui_tmp[4096]; const gchar *a; switch (n->status) { case GTA_NODE_CONNECTING: a = _("Connecting..."); break; case GTA_NODE_HELLO_SENT: a = _("Hello sent"); break; case GTA_NODE_WELCOME_SENT: a = _("Welcome sent"); break; case GTA_NODE_CONNECTED: if (n->sent || n->received) { size_t slen = 0; if (!GUI_PROPERTY(node_show_detailed_info)) { str_bprintf(gui_tmp, sizeof(gui_tmp), "TX=%u RX=%u Q=%u,%u%% %s", n->sent, n->received, n->mqueue_count, n->mqueue_percent_used, n->in_tx_swift_control ? " [SW]" : n->in_tx_flow_control ? " [FC]" : ""); a = gui_tmp; break; } if (n->tx_compressed && GUI_PROPERTY(show_gnet_info_txc)) slen += str_bprintf(gui_tmp, sizeof(gui_tmp), "TXc=%u,%d%%", n->sent, (int) (n->tx_compression_ratio * 100.0)); else slen += str_bprintf(gui_tmp, sizeof(gui_tmp), "TX=%u", n->sent); if ( GUI_PROPERTY(show_gnet_info_tx_speed) || GUI_PROPERTY(show_gnet_info_tx_wire) ) { gboolean is_first = TRUE; slen += str_bprintf(&gui_tmp[slen], sizeof(gui_tmp)-slen, " (" /* ')' */); if (GUI_PROPERTY(show_gnet_info_tx_wire)) { slen += str_bprintf(&gui_tmp[slen], sizeof(gui_tmp)-slen, "%s", compact_size(n->tx_written, show_metric_units())); is_first = FALSE; } if (GUI_PROPERTY(show_gnet_info_tx_speed)) slen += str_bprintf(&gui_tmp[slen], sizeof(gui_tmp)-slen, "%s%s", is_first ? "" : ", ", compact_rate(n->tx_bps, show_metric_units())); slen += str_bprintf(&gui_tmp[slen], sizeof(gui_tmp)-slen, /* '(' */ ")"); } if (n->rx_compressed && GUI_PROPERTY(show_gnet_info_rxc)) slen += str_bprintf(&gui_tmp[slen], sizeof(gui_tmp)-slen, " RXc=%u,%d%%", n->received, (int) (n->rx_compression_ratio * 100.0)); else slen += str_bprintf(&gui_tmp[slen], sizeof(gui_tmp)-slen, " RX=%u", n->received); if ( GUI_PROPERTY(show_gnet_info_rx_speed) || GUI_PROPERTY(show_gnet_info_rx_wire) ) { gboolean is_first = TRUE; slen += str_bprintf(&gui_tmp[slen], sizeof(gui_tmp)-slen, " (" /* ')' */); if (GUI_PROPERTY(show_gnet_info_rx_wire)) { slen += str_bprintf(&gui_tmp[slen], sizeof(gui_tmp)-slen, "%s", compact_size(n->rx_given, show_metric_units())); is_first = FALSE; } if (GUI_PROPERTY(show_gnet_info_rx_speed)) slen += str_bprintf(&gui_tmp[slen], sizeof(gui_tmp)-slen, "%s%s", is_first ? "" : ", ", compact_rate(n->rx_bps, show_metric_units())); slen += str_bprintf(&gui_tmp[slen], sizeof(gui_tmp)-slen, /* '(' */ ")"); } if ( GUI_PROPERTY(show_gnet_info_tx_queries) || GUI_PROPERTY(show_gnet_info_rx_queries) || GUI_PROPERTY(show_gnet_info_gen_queries) || GUI_PROPERTY(show_gnet_info_sq_queries) ) { gboolean is_first = TRUE; slen += str_bprintf(&gui_tmp[slen], sizeof(gui_tmp)-slen, " Query(" /* ')' */); if (GUI_PROPERTY(show_gnet_info_gen_queries)) { slen += str_bprintf(&gui_tmp[slen], sizeof(gui_tmp)-slen, "Gen=%u", n->squeue_sent); is_first = FALSE; } if (GUI_PROPERTY(show_gnet_info_sq_queries)) { slen += str_bprintf(&gui_tmp[slen], sizeof(gui_tmp)-slen, "%sQ=%u", is_first ? "" : ", ", n->squeue_count); is_first = FALSE; } if (GUI_PROPERTY(show_gnet_info_tx_queries)) { slen += str_bprintf(&gui_tmp[slen], sizeof(gui_tmp)-slen, "%sTX=%u", is_first ? "" : ", ", n->tx_queries); is_first = FALSE; } if (GUI_PROPERTY(show_gnet_info_rx_queries)) slen += str_bprintf(&gui_tmp[slen], sizeof(gui_tmp)-slen, "%sRX=%u", is_first ? "" : ", ", n->rx_queries); slen += str_bprintf(&gui_tmp[slen], sizeof(gui_tmp)-slen, /* '(' */ ")"); } if ( GUI_PROPERTY(show_gnet_info_tx_hits) || GUI_PROPERTY(show_gnet_info_rx_hits) ) { gboolean is_first = TRUE; slen += str_bprintf(&gui_tmp[slen], sizeof(gui_tmp)-slen, " QHit(" /* ')' */); if (GUI_PROPERTY(show_gnet_info_tx_hits)) { slen += str_bprintf(&gui_tmp[slen], sizeof(gui_tmp)-slen, "TX=%u", n->tx_qhits); is_first = FALSE; } if (GUI_PROPERTY(show_gnet_info_rx_hits)) slen += str_bprintf(&gui_tmp[slen], sizeof(gui_tmp)-slen, "%sRX=%u", is_first ? "" : ", ", n->rx_qhits); slen += str_bprintf(&gui_tmp[slen], sizeof(gui_tmp)-slen, /* '(' */ ")"); } if ( GUI_PROPERTY(show_gnet_info_tx_dropped) || GUI_PROPERTY(show_gnet_info_rx_dropped) ) { gboolean is_first = TRUE; slen += str_bprintf(&gui_tmp[slen], sizeof(gui_tmp)-slen, " Drop(" /* ')' */); if (GUI_PROPERTY(show_gnet_info_tx_dropped)) { slen += str_bprintf(&gui_tmp[slen], sizeof(gui_tmp)-slen, "TX=%u", n->tx_dropped); is_first = FALSE; } if (GUI_PROPERTY(show_gnet_info_rx_dropped)) slen += str_bprintf(&gui_tmp[slen], sizeof(gui_tmp)-slen, "%sRX=%u", is_first ? "" : ", ", n->rx_dropped); slen += str_bprintf(&gui_tmp[slen], sizeof(gui_tmp)-slen, /* '(' */ ")"); } if ( GUI_PROPERTY(show_gnet_info_shared_size) || GUI_PROPERTY(show_gnet_info_shared_files) ) { gboolean is_first = TRUE; slen += str_bprintf(&gui_tmp[slen], sizeof(gui_tmp)-slen, " Lib(" /* ')' */); if ( GUI_PROPERTY(show_gnet_info_shared_size) && n->gnet_info_known ) { slen += str_bprintf(&gui_tmp[slen], sizeof(gui_tmp)-slen, "%s", compact_kb_size(n->gnet_files_count ? n->gnet_kbytes_count : 0, show_metric_units())); is_first = FALSE; } if ( GUI_PROPERTY(show_gnet_info_shared_files) && n->gnet_info_known ) { slen += str_bprintf(&gui_tmp[slen], sizeof(gui_tmp)-slen, "%s#=%u", is_first ? "" : ", ", n->gnet_files_count); } slen += str_bprintf(&gui_tmp[slen], sizeof(gui_tmp)-slen, /* '(' */ "%s)", n->gnet_info_known ? "" : "?"); } if (GUI_PROPERTY(show_gnet_info_qrp_stats)) { if (n->has_qrp) slen += str_bprintf(&gui_tmp[slen], sizeof(gui_tmp)-slen, " QRP=%u%%", (guint) (n->qrp_efficiency * 100.0)); if (n->qrt_slots != 0) slen += str_bprintf(&gui_tmp[slen], sizeof(gui_tmp)-slen, " QRT(%s, g=%u, f=%u%%, t=%u%%, e=%u%%)", compact_size(n->qrt_slots, show_metric_units()), n->qrt_generation, n->qrt_fill_ratio, n->qrt_pass_throw, (guint) (n->qrp_efficiency * 100.0)); } if (GUI_PROPERTY(show_gnet_info_dbw)) slen += str_bprintf(&gui_tmp[slen], sizeof(gui_tmp)-slen, " Dup=%u Bad=%u W=%u H=%u S=%u E=%u", n->n_dups, n->n_bad, n->n_weird, n->n_hostile, n->n_spam, n->n_evil); if (GUI_PROPERTY(show_gnet_info_rt)) { slen += str_bprintf(&gui_tmp[slen], sizeof(gui_tmp)-slen, " RT(avg=%u, last=%u", n->rt_avg, n->rt_last); /* ) */ if (n->tcp_rtt) slen += str_bprintf(&gui_tmp[slen], sizeof(gui_tmp)-slen, ", tcp=%u", n->tcp_rtt); if (n->udp_rtt) slen += str_bprintf(&gui_tmp[slen], sizeof(gui_tmp)-slen, ", udp=%u", n->udp_rtt); slen += str_bprintf(&gui_tmp[slen], sizeof(gui_tmp)-slen, /* ( */ ")"); } slen += str_bprintf(&gui_tmp[slen], sizeof(gui_tmp)-slen, " Q=%u,%u%% %s", n->mqueue_count, n->mqueue_percent_used, n->in_tx_swift_control ? " [SW]" : n->in_tx_flow_control ? " [FC]" : ""); a = gui_tmp; } else if (n->is_pseudo) { a = _("No UDP traffic yet"); } else { a = _("Connected"); } break; case GTA_NODE_SHUTDOWN: { str_bprintf(gui_tmp, sizeof(gui_tmp), _("Closing: %s [Stop in %us] RX=%u Q=%u,%u%%"), n->message, n->shutdown_remain, n->received, n->mqueue_count, n->mqueue_percent_used); a = gui_tmp; } break; case GTA_NODE_REMOVING: a = *n->message ? n->message : _("Removing"); break; case GTA_NODE_RECEIVING_HELLO: a = _("Receiving hello"); break; default: a = _("UNKNOWN STATUS"); } return a; }