|
Packit |
b802ec |
/*
|
|
Packit |
b802ec |
mtr -- a network diagnostic tool
|
|
Packit |
b802ec |
Copyright (C) 1997,1998 Matt Kimball
|
|
Packit |
b802ec |
Changes/additions Copyright (C) 1998 R.E.Wolff@BitWizard.nl
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
This program is free software; you can redistribute it and/or modify
|
|
Packit |
b802ec |
it under the terms of the GNU General Public License version 2 as
|
|
Packit |
b802ec |
published by the Free Software Foundation.
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
This program is distributed in the hope that it will be useful,
|
|
Packit |
b802ec |
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
b802ec |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
Packit |
b802ec |
GNU General Public License for more details.
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
You should have received a copy of the GNU General Public License
|
|
Packit |
b802ec |
along with this program; if not, write to the Free Software
|
|
Packit |
b802ec |
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
Packit |
b802ec |
*/
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
#include "config.h"
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
#include <stdio.h>
|
|
Packit |
b802ec |
#include <stdlib.h>
|
|
Packit |
b802ec |
#include <unistd.h>
|
|
Packit |
b802ec |
#include <sys/time.h>
|
|
Packit |
b802ec |
#include <sys/types.h>
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
#ifdef HAVE_GTK
|
|
Packit |
b802ec |
#include <string.h>
|
|
Packit |
b802ec |
#include <sys/types.h>
|
|
Packit |
b802ec |
#include <gtk/gtk.h>
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
#include "mtr.h"
|
|
Packit |
b802ec |
#include "net.h"
|
|
Packit |
b802ec |
#include "dns.h"
|
|
Packit |
b802ec |
#include "asn.h"
|
|
Packit |
b802ec |
#include "mtr-gtk.h"
|
|
Packit |
b802ec |
#include "utils.h"
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
#include "img/mtr_icon.xpm"
|
|
Packit |
b802ec |
#endif
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
static gint gtk_ping(
|
|
Packit |
b802ec |
gpointer data);
|
|
Packit |
b802ec |
static gint Copy_activate(
|
|
Packit |
b802ec |
GtkWidget * widget,
|
|
Packit |
b802ec |
gpointer data);
|
|
Packit |
b802ec |
static gint NewDestination_activate(
|
|
Packit |
b802ec |
GtkWidget * widget,
|
|
Packit |
b802ec |
gpointer data);
|
|
Packit |
b802ec |
static gboolean ReportTreeView_clicked(
|
|
Packit |
b802ec |
GtkWidget * Tree,
|
|
Packit |
b802ec |
GdkEventButton * event,
|
|
Packit |
b802ec |
gpointer data);
|
|
Packit |
b802ec |
static gchar *getSelectedHost(
|
|
Packit |
b802ec |
GtkTreePath * path);
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
static int ping_timeout_timer;
|
|
Packit |
b802ec |
static GtkWidget *Pause_Button;
|
|
Packit |
b802ec |
static GtkWidget *Entry;
|
|
Packit |
b802ec |
static GtkWidget *main_window;
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
static void gtk_add_ping_timeout(
|
|
Packit |
b802ec |
struct mtr_ctl *ctl)
|
|
Packit |
b802ec |
{
|
|
Packit |
b802ec |
int dt;
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
if (gtk_toggle_button_get_active((GtkToggleButton *) Pause_Button)) {
|
|
Packit |
b802ec |
return;
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
dt = calc_deltatime(ctl->WaitTime);
|
|
Packit |
b802ec |
gtk_redraw(ctl);
|
|
Packit |
b802ec |
ping_timeout_timer = g_timeout_add(dt / 1000, gtk_ping, ctl);
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
static void gtk_do_init(
|
|
Packit |
b802ec |
int *argc,
|
|
Packit |
b802ec |
char ***argv)
|
|
Packit |
b802ec |
{
|
|
Packit |
b802ec |
static int done = 0;
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
if (!done) {
|
|
Packit |
b802ec |
gtk_init(argc, argv);
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
done = 1;
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
int gtk_detect(
|
|
Packit |
b802ec |
ATTRIBUTE_UNUSED int *argc,
|
|
Packit |
b802ec |
ATTRIBUTE_UNUSED char ***argv)
|
|
Packit |
b802ec |
{
|
|
Packit |
b802ec |
if (getenv("DISPLAY") != NULL) {
|
|
Packit |
b802ec |
/* If we do this here, gtk_init exits on an error. This happens
|
|
Packit |
b802ec |
BEFORE the user has had a chance to tell us not to use the
|
|
Packit |
b802ec |
display... */
|
|
Packit |
b802ec |
return TRUE;
|
|
Packit |
b802ec |
} else {
|
|
Packit |
b802ec |
return FALSE;
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
static gint Window_destroy(
|
|
Packit |
b802ec |
ATTRIBUTE_UNUSED GtkWidget * Window,
|
|
Packit |
b802ec |
ATTRIBUTE_UNUSED gpointer data)
|
|
Packit |
b802ec |
{
|
|
Packit |
b802ec |
gtk_main_quit();
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
return FALSE;
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
static gint Restart_clicked(
|
|
Packit |
b802ec |
ATTRIBUTE_UNUSED GtkWidget * Button,
|
|
Packit |
b802ec |
gpointer data)
|
|
Packit |
b802ec |
{
|
|
Packit |
b802ec |
struct mtr_ctl *ctl = (struct mtr_ctl *) data;
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
net_reset(ctl);
|
|
Packit |
b802ec |
gtk_redraw(ctl);
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
return FALSE;
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
static gint Pause_clicked(
|
|
Packit |
b802ec |
ATTRIBUTE_UNUSED GtkWidget * Button,
|
|
Packit |
b802ec |
gpointer data)
|
|
Packit |
b802ec |
{
|
|
Packit |
b802ec |
struct mtr_ctl *ctl = (struct mtr_ctl *) data;
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
static int paused = 0;
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
if (paused) {
|
|
Packit |
b802ec |
gtk_add_ping_timeout(ctl);
|
|
Packit |
b802ec |
} else {
|
|
Packit |
b802ec |
g_source_remove(ping_timeout_timer);
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
paused = !paused;
|
|
Packit |
b802ec |
gtk_redraw(ctl);
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
return FALSE;
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
static gint About_clicked(
|
|
Packit |
b802ec |
ATTRIBUTE_UNUSED GtkWidget * Button,
|
|
Packit |
b802ec |
ATTRIBUTE_UNUSED gpointer data)
|
|
Packit |
b802ec |
{
|
|
Packit |
b802ec |
static const gchar *authors[] = {
|
|
Packit |
b802ec |
"Matt Kimball <matt.kimball@gmail.com>",
|
|
Packit |
b802ec |
"Roger Wolff <R.E.Wolff@BitWizard.nl>",
|
|
Packit |
b802ec |
"Bohdan Vlasyuk <bohdan@cec.vstu.vinnica.ua>",
|
|
Packit |
b802ec |
"Evgeniy Tretyak <evtr@ukr.net>",
|
|
Packit |
b802ec |
"John Thacker <thacker@math.cornell.edu>",
|
|
Packit |
b802ec |
"Juha Takala",
|
|
Packit |
b802ec |
"David Sward <sward@clark.net>",
|
|
Packit |
b802ec |
"David Stone <stone@AsIf.com>",
|
|
Packit |
b802ec |
"Andrew Stesin",
|
|
Packit |
b802ec |
"Greg Stark <gsstark@mit.edu>",
|
|
Packit |
b802ec |
"Robert Sparks <rjsparks@nostrum.com>",
|
|
Packit |
b802ec |
"Mike Simons <msimons@moria.simons-clan.com>",
|
|
Packit |
b802ec |
"Aaron Scarisbrick,",
|
|
Packit |
b802ec |
"Craig Milo Rogers <Rogers@ISI.EDU>",
|
|
Packit |
b802ec |
"Antonio Querubin <tony@lavanauts.org>",
|
|
Packit |
b802ec |
"Russell Nelson <rn-mtr@crynwr.com>",
|
|
Packit |
b802ec |
"Davin Milun <milun@acm.org>",
|
|
Packit |
b802ec |
"Josh Martin <jmartin@columbiaservices.net>",
|
|
Packit |
b802ec |
"Alexander V. Lukyanov <lav@yars.free.net>",
|
|
Packit |
b802ec |
"Charles Levert <charles@comm.polymtl.ca> ",
|
|
Packit |
b802ec |
"Bertrand Leconte <B.Leconte@mail.dotcom.fr>",
|
|
Packit |
b802ec |
"Anand Kumria",
|
|
Packit |
b802ec |
"Olav Kvittem <Olav.Kvittem@uninett.no>",
|
|
Packit |
b802ec |
"Adam Kramer <l3zqc@qcunix1.acc.qc.edu> ",
|
|
Packit |
b802ec |
"Philip Kizer <pckizer@nostrum.com>",
|
|
Packit |
b802ec |
"Simon Kirby",
|
|
Packit |
b802ec |
"Sami Kerola <kerolasa@iki.fi>",
|
|
Packit |
b802ec |
"Christophe Kalt",
|
|
Packit |
b802ec |
"Steve Kann <stevek@spheara.horizonlive.com>",
|
|
Packit |
b802ec |
"Brett Johnson <brett@jdacareers.com>",
|
|
Packit |
b802ec |
"Roland Illig <roland.illig@gmx.de>",
|
|
Packit |
b802ec |
"Damian Gryski <dgryski@uwaterloo.ca>",
|
|
Packit |
b802ec |
"Rob Foehl <rwf@loonybin.net>",
|
|
Packit |
b802ec |
"Mircea Damian",
|
|
Packit |
b802ec |
"Cougar <cougar@random.ee>",
|
|
Packit |
b802ec |
"Travis Cross <tc@traviscross.com>",
|
|
Packit |
b802ec |
"Brian Casey",
|
|
Packit |
b802ec |
"Andrew Brown <atatat@atatdot.net>",
|
|
Packit |
b802ec |
"Bill Bogstad <bogstad@pobox.com> ",
|
|
Packit |
b802ec |
"Marc Bejarano <marc.bejarano@openwave.com>",
|
|
Packit |
b802ec |
"Moritz Barsnick <barsnick@gmx.net>",
|
|
Packit |
b802ec |
"Thomas Klausner <wiz@NetBSD.org>",
|
|
Packit |
b802ec |
NULL
|
|
Packit |
b802ec |
};
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
gtk_show_about_dialog(GTK_WINDOW(main_window)
|
|
Packit |
b802ec |
, "version", PACKAGE_VERSION, "copyright",
|
|
Packit |
b802ec |
"Copyright \xc2\xa9 1997,1998 Matt Kimball",
|
|
Packit |
b802ec |
"website", "http://www.bitwizard.nl/mtr/",
|
|
Packit |
b802ec |
"authors", authors, "comments",
|
|
Packit |
b802ec |
"The 'traceroute' and 'ping' programs in a single network diagnostic tool.",
|
|
Packit |
b802ec |
"license",
|
|
Packit |
b802ec |
"This program is free software; you can redistribute it and/or modify\n"
|
|
Packit |
b802ec |
"it under the terms of the GNU General Public License version 2 as\n"
|
|
Packit |
b802ec |
"published by the Free Software Foundation.\n"
|
|
Packit |
b802ec |
"\n"
|
|
Packit |
b802ec |
"This program is distributed in the hope that it will be useful,\n"
|
|
Packit |
b802ec |
"but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
|
|
Packit |
b802ec |
"MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
|
|
Packit |
b802ec |
"GNU General Public License for more details.",
|
|
Packit |
b802ec |
NULL);
|
|
Packit |
b802ec |
return TRUE;
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
/*
|
|
Packit |
b802ec |
* There is a small problem with the following code:
|
|
Packit |
b802ec |
* The timeout is canceled and removed in order to ensure that
|
|
Packit |
b802ec |
* it takes effect (consider what happens if you set the timeout to 999,
|
|
Packit |
b802ec |
* then try to undo the change); is a better approach possible?
|
|
Packit |
b802ec |
*
|
|
Packit |
b802ec |
* What's the problem with this? (-> "I don't think so)
|
|
Packit |
b802ec |
*/
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
static gint WaitTime_changed(
|
|
Packit |
b802ec |
ATTRIBUTE_UNUSED GtkAdjustment * Adj,
|
|
Packit |
b802ec |
GtkWidget * data)
|
|
Packit |
b802ec |
{
|
|
Packit |
b802ec |
struct mtr_ctl *ctl = (struct mtr_ctl *) data;
|
|
Packit |
b802ec |
GtkWidget *Button = (GtkWidget *) ctl->gtk_data;
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
ctl->WaitTime = gtk_spin_button_get_value(GTK_SPIN_BUTTON(Button));
|
|
Packit |
b802ec |
g_source_remove(ping_timeout_timer);
|
|
Packit |
b802ec |
gtk_add_ping_timeout(ctl);
|
|
Packit |
b802ec |
gtk_redraw(ctl);
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
return FALSE;
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
static gint Host_activate(
|
|
Packit |
b802ec |
GtkWidget * entry,
|
|
Packit |
b802ec |
gpointer data)
|
|
Packit |
b802ec |
{
|
|
Packit |
b802ec |
struct mtr_ctl *ctl = (struct mtr_ctl *) data;
|
|
Packit |
b802ec |
struct hostent *addr;
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
addr = dns_forward(gtk_entry_get_text(GTK_ENTRY(entry)));
|
|
Packit |
b802ec |
if (addr) {
|
|
Packit |
b802ec |
net_reopen(ctl, addr);
|
|
Packit |
b802ec |
/* If we are "Paused" at this point it is usually because someone
|
|
Packit |
b802ec |
entered a non-existing host. Therefore do the go-ahead... */
|
|
Packit |
b802ec |
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(Pause_Button), 0);
|
|
Packit |
b802ec |
} else {
|
|
Packit |
b802ec |
int pos = strlen(gtk_entry_get_text(GTK_ENTRY(entry)));
|
|
Packit |
b802ec |
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(Pause_Button), 1);
|
|
Packit |
b802ec |
gtk_editable_insert_text(GTK_EDITABLE(entry), ": not found", -1,
|
|
Packit |
b802ec |
&pos;;
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
return FALSE;
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
static void Toolbar_fill(
|
|
Packit |
b802ec |
struct mtr_ctl *ctl,
|
|
Packit |
b802ec |
GtkWidget * Toolbar)
|
|
Packit |
b802ec |
{
|
|
Packit |
b802ec |
GtkWidget *Button;
|
|
Packit |
b802ec |
GtkWidget *Label;
|
|
Packit |
b802ec |
GtkAdjustment *Adjustment;
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
Button = gtk_button_new_from_stock(GTK_STOCK_QUIT);
|
|
Packit |
b802ec |
gtk_box_pack_end(GTK_BOX(Toolbar), Button, FALSE, FALSE, 0);
|
|
Packit |
b802ec |
g_signal_connect(GTK_OBJECT(Button), "clicked",
|
|
Packit |
b802ec |
GTK_SIGNAL_FUNC(Window_destroy), NULL);
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
Button = gtk_button_new_from_stock(GTK_STOCK_ABOUT);
|
|
Packit |
b802ec |
gtk_box_pack_end(GTK_BOX(Toolbar), Button, FALSE, FALSE, 0);
|
|
Packit |
b802ec |
g_signal_connect(GTK_OBJECT(Button), "clicked",
|
|
Packit |
b802ec |
GTK_SIGNAL_FUNC(About_clicked), NULL);
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
Button = gtk_button_new_with_mnemonic("_Restart");
|
|
Packit |
b802ec |
gtk_box_pack_end(GTK_BOX(Toolbar), Button, FALSE, FALSE, 0);
|
|
Packit |
b802ec |
g_signal_connect(GTK_OBJECT(Button), "clicked",
|
|
Packit |
b802ec |
GTK_SIGNAL_FUNC(Restart_clicked), ctl);
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
Pause_Button = gtk_toggle_button_new_with_mnemonic("_Pause");
|
|
Packit |
b802ec |
gtk_box_pack_end(GTK_BOX(Toolbar), Pause_Button, FALSE, FALSE, 0);
|
|
Packit |
b802ec |
g_signal_connect(GTK_OBJECT(Pause_Button), "clicked",
|
|
Packit |
b802ec |
GTK_SIGNAL_FUNC(Pause_clicked), ctl);
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
/* allow root only to set zero delay */
|
|
Packit |
b802ec |
Adjustment = (GtkAdjustment *) gtk_adjustment_new(ctl->WaitTime,
|
|
Packit |
b802ec |
getuid() ==
|
|
Packit |
b802ec |
0 ? 0.01 : 1.00,
|
|
Packit |
b802ec |
999.99, 1.0, 10.0,
|
|
Packit |
b802ec |
0.0);
|
|
Packit |
b802ec |
Button = gtk_spin_button_new(Adjustment, 0.5, 2);
|
|
Packit |
b802ec |
gtk_spin_button_set_numeric(GTK_SPIN_BUTTON(Button), TRUE);
|
|
Packit |
b802ec |
gtk_box_pack_end(GTK_BOX(Toolbar), Button, FALSE, FALSE, 0);
|
|
Packit |
b802ec |
ctl->gtk_data = Button;
|
|
Packit |
b802ec |
g_signal_connect(GTK_OBJECT(Adjustment), "value_changed",
|
|
Packit |
b802ec |
GTK_SIGNAL_FUNC(WaitTime_changed), ctl);
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
Label = gtk_label_new_with_mnemonic("_Hostname:");
|
|
Packit |
b802ec |
gtk_box_pack_start(GTK_BOX(Toolbar), Label, FALSE, FALSE, 0);
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
Entry = gtk_entry_new();
|
|
Packit |
b802ec |
gtk_entry_set_text(GTK_ENTRY(Entry), ctl->Hostname);
|
|
Packit |
b802ec |
g_signal_connect(GTK_OBJECT(Entry), "activate",
|
|
Packit |
b802ec |
GTK_SIGNAL_FUNC(Host_activate), ctl);
|
|
Packit |
b802ec |
gtk_box_pack_start(GTK_BOX(Toolbar), Entry, TRUE, TRUE, 0);
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
gtk_label_set_mnemonic_widget(GTK_LABEL(Label), Entry);
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
static GtkWidget *ReportTreeView;
|
|
Packit |
b802ec |
static GtkListStore *ReportStore;
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
enum {
|
|
Packit |
b802ec |
#ifdef HAVE_IPINFO
|
|
Packit |
b802ec |
COL_ASN,
|
|
Packit |
b802ec |
#endif
|
|
Packit |
b802ec |
COL_HOSTNAME,
|
|
Packit |
b802ec |
COL_LOSS,
|
|
Packit |
b802ec |
COL_RCV,
|
|
Packit |
b802ec |
COL_SNT,
|
|
Packit |
b802ec |
COL_LAST,
|
|
Packit |
b802ec |
COL_BEST,
|
|
Packit |
b802ec |
COL_AVG,
|
|
Packit |
b802ec |
COL_WORST,
|
|
Packit |
b802ec |
COL_STDEV,
|
|
Packit |
b802ec |
COL_COLOR,
|
|
Packit |
b802ec |
N_COLS
|
|
Packit |
b802ec |
};
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
/* Trick to cast a pointer to integer. We are mis-using a pointer as a
|
|
Packit |
b802ec |
single integer. On 64-bit architectures, the pointer is 64 bits and the
|
|
Packit |
b802ec |
integer only 32. The compiler warns us of loss of precision. However we
|
|
Packit |
b802ec |
know we casted a normal 32-bit integer into this pointer a few
|
|
Packit |
b802ec |
microseconds earlier, so it is ok. Nothing to worry about. */
|
|
Packit |
b802ec |
#define POINTER_TO_INT(p) ((int)(long)(p))
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
static void float_formatter(
|
|
Packit |
b802ec |
GtkTreeViewColumn * tree_column ATTRIBUTE_UNUSED,
|
|
Packit |
b802ec |
GtkCellRenderer * cell,
|
|
Packit |
b802ec |
GtkTreeModel * tree_model,
|
|
Packit |
b802ec |
GtkTreeIter * iter,
|
|
Packit |
b802ec |
gpointer data)
|
|
Packit |
b802ec |
{
|
|
Packit |
b802ec |
gfloat f;
|
|
Packit |
b802ec |
gchar text[64];
|
|
Packit |
b802ec |
gtk_tree_model_get(tree_model, iter, POINTER_TO_INT(data), &f, -1);
|
|
Packit |
b802ec |
sprintf(text, "%.2f", f);
|
|
Packit |
b802ec |
g_object_set(cell, "text", text, NULL);
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
static void percent_formatter(
|
|
Packit |
b802ec |
GtkTreeViewColumn * tree_column ATTRIBUTE_UNUSED,
|
|
Packit |
b802ec |
GtkCellRenderer * cell,
|
|
Packit |
b802ec |
GtkTreeModel * tree_model,
|
|
Packit |
b802ec |
GtkTreeIter * iter,
|
|
Packit |
b802ec |
gpointer data)
|
|
Packit |
b802ec |
{
|
|
Packit |
b802ec |
gfloat f;
|
|
Packit |
b802ec |
gchar text[64];
|
|
Packit |
b802ec |
gtk_tree_model_get(tree_model, iter, POINTER_TO_INT(data), &f, -1);
|
|
Packit |
b802ec |
sprintf(text, "%.1f%%", f);
|
|
Packit |
b802ec |
g_object_set(cell, "text", text, NULL);
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
static void TreeViewCreate(
|
|
Packit |
b802ec |
struct mtr_ctl *ctl)
|
|
Packit |
b802ec |
{
|
|
Packit |
b802ec |
GtkCellRenderer *renderer;
|
|
Packit |
b802ec |
GtkTreeViewColumn *column;
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
ReportStore = gtk_list_store_new(N_COLS,
|
|
Packit |
b802ec |
#ifdef HAVE_IPINFO
|
|
Packit |
b802ec |
G_TYPE_STRING,
|
|
Packit |
b802ec |
#endif
|
|
Packit |
b802ec |
G_TYPE_STRING,
|
|
Packit |
b802ec |
G_TYPE_FLOAT,
|
|
Packit |
b802ec |
G_TYPE_INT,
|
|
Packit |
b802ec |
G_TYPE_INT,
|
|
Packit |
b802ec |
G_TYPE_INT,
|
|
Packit |
b802ec |
G_TYPE_INT,
|
|
Packit |
b802ec |
G_TYPE_INT,
|
|
Packit |
b802ec |
G_TYPE_INT,
|
|
Packit |
b802ec |
G_TYPE_FLOAT, G_TYPE_STRING);
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
ReportTreeView =
|
|
Packit |
b802ec |
gtk_tree_view_new_with_model(GTK_TREE_MODEL(ReportStore));
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
g_signal_connect(GTK_OBJECT(ReportTreeView), "button_press_event",
|
|
Packit |
b802ec |
G_CALLBACK(ReportTreeView_clicked), ctl);
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
#ifdef HAVE_IPINFO
|
|
Packit |
b802ec |
if (is_printii(ctl)) {
|
|
Packit |
b802ec |
renderer = gtk_cell_renderer_text_new();
|
|
Packit |
b802ec |
column = gtk_tree_view_column_new_with_attributes("ASN",
|
|
Packit |
b802ec |
renderer,
|
|
Packit |
b802ec |
"text", COL_ASN,
|
|
Packit |
b802ec |
"foreground",
|
|
Packit |
b802ec |
COL_COLOR, NULL);
|
|
Packit |
b802ec |
gtk_tree_view_column_set_resizable(column, TRUE);
|
|
Packit |
b802ec |
gtk_tree_view_append_column(GTK_TREE_VIEW(ReportTreeView), column);
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
#endif
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
renderer = gtk_cell_renderer_text_new();
|
|
Packit |
b802ec |
column = gtk_tree_view_column_new_with_attributes("Hostname",
|
|
Packit |
b802ec |
renderer,
|
|
Packit |
b802ec |
"text", COL_HOSTNAME,
|
|
Packit |
b802ec |
"foreground",
|
|
Packit |
b802ec |
COL_COLOR, NULL);
|
|
Packit |
b802ec |
gtk_tree_view_column_set_expand(column, TRUE);
|
|
Packit |
b802ec |
gtk_tree_view_column_set_resizable(column, TRUE);
|
|
Packit |
b802ec |
gtk_tree_view_append_column(GTK_TREE_VIEW(ReportTreeView), column);
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
renderer = gtk_cell_renderer_text_new();
|
|
Packit |
b802ec |
g_object_set(G_OBJECT(renderer), "xalign", 1.0, NULL);
|
|
Packit |
b802ec |
column = gtk_tree_view_column_new_with_attributes("Loss",
|
|
Packit |
b802ec |
renderer,
|
|
Packit |
b802ec |
"text", COL_LOSS,
|
|
Packit |
b802ec |
"foreground",
|
|
Packit |
b802ec |
COL_COLOR, NULL);
|
|
Packit |
b802ec |
gtk_tree_view_column_set_resizable(column, TRUE);
|
|
Packit |
b802ec |
gtk_tree_view_column_set_cell_data_func(column, renderer,
|
|
Packit |
b802ec |
percent_formatter,
|
|
Packit |
b802ec |
(void *) COL_LOSS, NULL);
|
|
Packit |
b802ec |
gtk_tree_view_append_column(GTK_TREE_VIEW(ReportTreeView), column);
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
renderer = gtk_cell_renderer_text_new();
|
|
Packit |
b802ec |
g_object_set(G_OBJECT(renderer), "xalign", 1.0, NULL);
|
|
Packit |
b802ec |
column = gtk_tree_view_column_new_with_attributes("Snt",
|
|
Packit |
b802ec |
renderer,
|
|
Packit |
b802ec |
"text", COL_SNT,
|
|
Packit |
b802ec |
"foreground",
|
|
Packit |
b802ec |
COL_COLOR, NULL);
|
|
Packit |
b802ec |
gtk_tree_view_column_set_resizable(column, TRUE);
|
|
Packit |
b802ec |
gtk_tree_view_append_column(GTK_TREE_VIEW(ReportTreeView), column);
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
renderer = gtk_cell_renderer_text_new();
|
|
Packit |
b802ec |
g_object_set(G_OBJECT(renderer), "xalign", 1.0, NULL);
|
|
Packit |
b802ec |
column = gtk_tree_view_column_new_with_attributes("Last",
|
|
Packit |
b802ec |
renderer,
|
|
Packit |
b802ec |
"text", COL_LAST,
|
|
Packit |
b802ec |
"foreground",
|
|
Packit |
b802ec |
COL_COLOR, NULL);
|
|
Packit |
b802ec |
gtk_tree_view_column_set_resizable(column, TRUE);
|
|
Packit |
b802ec |
gtk_tree_view_append_column(GTK_TREE_VIEW(ReportTreeView), column);
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
renderer = gtk_cell_renderer_text_new();
|
|
Packit |
b802ec |
g_object_set(G_OBJECT(renderer), "xalign", 1.0, NULL);
|
|
Packit |
b802ec |
column = gtk_tree_view_column_new_with_attributes("Avg",
|
|
Packit |
b802ec |
renderer,
|
|
Packit |
b802ec |
"text", COL_AVG,
|
|
Packit |
b802ec |
"foreground",
|
|
Packit |
b802ec |
COL_COLOR, NULL);
|
|
Packit |
b802ec |
gtk_tree_view_column_set_resizable(column, TRUE);
|
|
Packit |
b802ec |
gtk_tree_view_append_column(GTK_TREE_VIEW(ReportTreeView), column);
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
renderer = gtk_cell_renderer_text_new();
|
|
Packit |
b802ec |
g_object_set(G_OBJECT(renderer), "xalign", 1.0, NULL);
|
|
Packit |
b802ec |
column = gtk_tree_view_column_new_with_attributes("Best",
|
|
Packit |
b802ec |
renderer,
|
|
Packit |
b802ec |
"text", COL_BEST,
|
|
Packit |
b802ec |
"foreground",
|
|
Packit |
b802ec |
COL_COLOR, NULL);
|
|
Packit |
b802ec |
gtk_tree_view_column_set_resizable(column, TRUE);
|
|
Packit |
b802ec |
gtk_tree_view_append_column(GTK_TREE_VIEW(ReportTreeView), column);
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
renderer = gtk_cell_renderer_text_new();
|
|
Packit |
b802ec |
g_object_set(G_OBJECT(renderer), "xalign", 1.0, NULL);
|
|
Packit |
b802ec |
column = gtk_tree_view_column_new_with_attributes("Worst",
|
|
Packit |
b802ec |
renderer,
|
|
Packit |
b802ec |
"text", COL_WORST,
|
|
Packit |
b802ec |
"foreground",
|
|
Packit |
b802ec |
COL_COLOR, NULL);
|
|
Packit |
b802ec |
gtk_tree_view_column_set_resizable(column, TRUE);
|
|
Packit |
b802ec |
gtk_tree_view_append_column(GTK_TREE_VIEW(ReportTreeView), column);
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
renderer = gtk_cell_renderer_text_new();
|
|
Packit |
b802ec |
g_object_set(G_OBJECT(renderer), "xalign", 1.0, NULL);
|
|
Packit |
b802ec |
column = gtk_tree_view_column_new_with_attributes("StDev",
|
|
Packit |
b802ec |
renderer,
|
|
Packit |
b802ec |
"text", COL_STDEV,
|
|
Packit |
b802ec |
"foreground",
|
|
Packit |
b802ec |
COL_COLOR, NULL);
|
|
Packit |
b802ec |
gtk_tree_view_column_set_resizable(column, TRUE);
|
|
Packit |
b802ec |
gtk_tree_view_column_set_cell_data_func(column, renderer,
|
|
Packit |
b802ec |
float_formatter,
|
|
Packit |
b802ec |
(void *) COL_STDEV, NULL);
|
|
Packit |
b802ec |
gtk_tree_view_append_column(GTK_TREE_VIEW(ReportTreeView), column);
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
static void update_tree_row(
|
|
Packit |
b802ec |
struct mtr_ctl *ctl,
|
|
Packit |
b802ec |
int row,
|
|
Packit |
b802ec |
GtkTreeIter * iter)
|
|
Packit |
b802ec |
{
|
|
Packit |
b802ec |
ip_t *addr;
|
|
Packit |
b802ec |
char str[256] = "???", *name = str;
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
addr = net_addr(row);
|
|
Packit |
b802ec |
if (addrcmp((void *) addr, (void *) &ctl->unspec_addr, ctl->af)) {
|
|
Packit |
b802ec |
if ((name = dns_lookup(ctl, addr))) {
|
|
Packit |
b802ec |
if (ctl->show_ips) {
|
|
Packit |
b802ec |
snprintf(str, sizeof(str), "%s (%s)", name,
|
|
Packit |
b802ec |
strlongip(ctl, addr));
|
|
Packit |
b802ec |
name = str;
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
} else
|
|
Packit |
b802ec |
name = strlongip(ctl, addr);
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
gtk_list_store_set(ReportStore, iter,
|
|
Packit |
b802ec |
COL_HOSTNAME, name,
|
|
Packit |
b802ec |
COL_LOSS, (float) (net_loss(row) / 1000.0),
|
|
Packit |
b802ec |
COL_RCV, net_returned(row),
|
|
Packit |
b802ec |
COL_SNT, net_xmit(row),
|
|
Packit |
b802ec |
COL_LAST, net_last(row) / 1000,
|
|
Packit |
b802ec |
COL_BEST, net_best(row) / 1000,
|
|
Packit |
b802ec |
COL_AVG, net_avg(row) / 1000,
|
|
Packit |
b802ec |
COL_WORST, net_worst(row) / 1000,
|
|
Packit |
b802ec |
COL_STDEV, (float) (net_stdev(row) / 1000.0),
|
|
Packit |
b802ec |
COL_COLOR, net_up(row) ? NULL : "red", -1);
|
|
Packit |
b802ec |
#ifdef HAVE_IPINFO
|
|
Packit |
b802ec |
if (is_printii(ctl))
|
|
Packit |
b802ec |
gtk_list_store_set(ReportStore, iter, COL_ASN,
|
|
Packit |
b802ec |
fmt_ipinfo(ctl, addr), -1);
|
|
Packit |
b802ec |
#endif
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
void gtk_redraw(
|
|
Packit |
b802ec |
struct mtr_ctl *ctl)
|
|
Packit |
b802ec |
{
|
|
Packit |
b802ec |
int max = net_max(ctl);
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
GtkTreeIter iter;
|
|
Packit |
b802ec |
int row = net_min(ctl);
|
|
Packit |
b802ec |
gboolean valid;
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
valid =
|
|
Packit |
b802ec |
gtk_tree_model_get_iter_first(GTK_TREE_MODEL(ReportStore), &iter);
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
while (valid) {
|
|
Packit |
b802ec |
if (row < max) {
|
|
Packit |
b802ec |
update_tree_row(ctl, row++, &iter);
|
|
Packit |
b802ec |
valid =
|
|
Packit |
b802ec |
gtk_tree_model_iter_next(GTK_TREE_MODEL(ReportStore),
|
|
Packit |
b802ec |
&iter);
|
|
Packit |
b802ec |
} else {
|
|
Packit |
b802ec |
valid = gtk_list_store_remove(ReportStore, &iter);
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
while (row < max) {
|
|
Packit |
b802ec |
gtk_list_store_append(ReportStore, &iter);
|
|
Packit |
b802ec |
update_tree_row(ctl, row++, &iter);
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
static void Window_fill(
|
|
Packit |
b802ec |
struct mtr_ctl *ctl,
|
|
Packit |
b802ec |
GtkWidget * Window)
|
|
Packit |
b802ec |
{
|
|
Packit |
b802ec |
GtkWidget *VBox;
|
|
Packit |
b802ec |
GtkWidget *Toolbar;
|
|
Packit |
b802ec |
GtkWidget *scroll;
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
gtk_window_set_title(GTK_WINDOW(Window), "My traceroute");
|
|
Packit |
b802ec |
gtk_window_set_default_size(GTK_WINDOW(Window), 650, 400);
|
|
Packit |
b802ec |
gtk_container_set_border_width(GTK_CONTAINER(Window), 10);
|
|
Packit |
b802ec |
VBox = gtk_vbox_new(FALSE, 10);
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
Toolbar = gtk_hbox_new(FALSE, 10);
|
|
Packit |
b802ec |
Toolbar_fill(ctl, Toolbar);
|
|
Packit |
b802ec |
gtk_box_pack_start(GTK_BOX(VBox), Toolbar, FALSE, FALSE, 0);
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
TreeViewCreate(ctl);
|
|
Packit |
b802ec |
scroll = gtk_scrolled_window_new(NULL, NULL);
|
|
Packit |
b802ec |
gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll),
|
|
Packit |
b802ec |
GTK_POLICY_AUTOMATIC,
|
|
Packit |
b802ec |
GTK_POLICY_AUTOMATIC);
|
|
Packit |
b802ec |
gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scroll),
|
|
Packit |
b802ec |
GTK_SHADOW_IN);
|
|
Packit |
b802ec |
gtk_container_add(GTK_CONTAINER(scroll), ReportTreeView);
|
|
Packit |
b802ec |
gtk_box_pack_start(GTK_BOX(VBox), scroll, TRUE, TRUE, 0);
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
gtk_container_add(GTK_CONTAINER(Window), VBox);
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
void gtk_open(
|
|
Packit |
b802ec |
struct mtr_ctl *ctl)
|
|
Packit |
b802ec |
{
|
|
Packit |
b802ec |
GdkPixbuf *icon;
|
|
Packit |
b802ec |
int argc = 1;
|
|
Packit |
b802ec |
char *args[2];
|
|
Packit |
b802ec |
char **argv;
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
argv = args;
|
|
Packit |
b802ec |
argv[0] = xstrdup("");
|
|
Packit |
b802ec |
argv[1] = NULL;
|
|
Packit |
b802ec |
gtk_do_init(&argc, &argv);
|
|
Packit |
b802ec |
free(argv[0]);
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
icon = gdk_pixbuf_new_from_xpm_data((const char **) mtr_icon);
|
|
Packit |
b802ec |
gtk_window_set_default_icon(icon);
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
main_window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
g_set_application_name("My traceroute");
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
Window_fill(ctl, main_window);
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
g_signal_connect(GTK_OBJECT(main_window), "delete_event",
|
|
Packit |
b802ec |
GTK_SIGNAL_FUNC(Window_destroy), NULL);
|
|
Packit |
b802ec |
g_signal_connect(GTK_OBJECT(main_window), "destroy",
|
|
Packit |
b802ec |
GTK_SIGNAL_FUNC(Window_destroy), NULL);
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
gtk_widget_show_all(main_window);
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
void gtk_close(
|
|
Packit |
b802ec |
void)
|
|
Packit |
b802ec |
{
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
int gtk_keyaction(
|
|
Packit |
b802ec |
void)
|
|
Packit |
b802ec |
{
|
|
Packit |
b802ec |
return 0;
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
static gint gtk_ping(
|
|
Packit |
b802ec |
gpointer data)
|
|
Packit |
b802ec |
{
|
|
Packit |
b802ec |
struct mtr_ctl *ctl = (struct mtr_ctl *) data;
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
gtk_redraw(ctl);
|
|
Packit |
b802ec |
net_send_batch(ctl);
|
|
Packit |
b802ec |
net_harvest_fds(ctl);
|
|
Packit |
b802ec |
g_source_remove(ping_timeout_timer);
|
|
Packit |
b802ec |
gtk_add_ping_timeout(ctl);
|
|
Packit |
b802ec |
return TRUE;
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
static gboolean gtk_net_data(
|
|
Packit |
b802ec |
ATTRIBUTE_UNUSED GIOChannel * channel,
|
|
Packit |
b802ec |
ATTRIBUTE_UNUSED GIOCondition cond,
|
|
Packit |
b802ec |
gpointer data)
|
|
Packit |
b802ec |
{
|
|
Packit |
b802ec |
struct mtr_ctl *ctl = (struct mtr_ctl *) data;
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
net_process_return(ctl);
|
|
Packit |
b802ec |
return TRUE;
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
static gboolean gtk_dns_data(
|
|
Packit |
b802ec |
ATTRIBUTE_UNUSED GIOChannel * channel,
|
|
Packit |
b802ec |
ATTRIBUTE_UNUSED GIOCondition cond,
|
|
Packit |
b802ec |
gpointer data)
|
|
Packit |
b802ec |
{
|
|
Packit |
b802ec |
struct mtr_ctl *ctl = (struct mtr_ctl *) data;
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
dns_ack(ctl);
|
|
Packit |
b802ec |
gtk_redraw(ctl);
|
|
Packit |
b802ec |
return TRUE;
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
#ifdef ENABLE_IPV6
|
|
Packit |
b802ec |
static gboolean gtk_dns_data6(
|
|
Packit |
b802ec |
ATTRIBUTE_UNUSED GIOChannel * channel,
|
|
Packit |
b802ec |
ATTRIBUTE_UNUSED GIOCondition cond,
|
|
Packit |
b802ec |
gpointer data)
|
|
Packit |
b802ec |
{
|
|
Packit |
b802ec |
struct mtr_ctl *ctl = (struct mtr_ctl *) data;
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
dns_ack6();
|
|
Packit |
b802ec |
gtk_redraw(ctl);
|
|
Packit |
b802ec |
return TRUE;
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
#endif
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
void gtk_loop(
|
|
Packit |
b802ec |
struct mtr_ctl *ctl)
|
|
Packit |
b802ec |
{
|
|
Packit |
b802ec |
GIOChannel *net_iochannel, *dns_iochannel;
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
gtk_add_ping_timeout(ctl);
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
net_iochannel = g_io_channel_unix_new(net_waitfd());
|
|
Packit |
b802ec |
g_io_add_watch(net_iochannel, G_IO_IN, gtk_net_data, ctl);
|
|
Packit |
b802ec |
#ifdef ENABLE_IPV6
|
|
Packit |
b802ec |
if (dns_waitfd6() > 0) {
|
|
Packit |
b802ec |
dns_iochannel = g_io_channel_unix_new(dns_waitfd6());
|
|
Packit |
b802ec |
g_io_add_watch(dns_iochannel, G_IO_IN, gtk_dns_data6, ctl);
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
#endif
|
|
Packit |
b802ec |
dns_iochannel = g_io_channel_unix_new(dns_waitfd());
|
|
Packit |
b802ec |
g_io_add_watch(dns_iochannel, G_IO_IN, gtk_dns_data, ctl);
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
gtk_main();
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
static gboolean NewDestination_activate(
|
|
Packit |
b802ec |
GtkWidget * widget ATTRIBUTE_UNUSED,
|
|
Packit |
b802ec |
gpointer data)
|
|
Packit |
b802ec |
{
|
|
Packit |
b802ec |
gchar *hostname;
|
|
Packit |
b802ec |
struct mtr_ctl *ctl = (struct mtr_ctl *) data;
|
|
Packit |
b802ec |
GtkTreePath *path = (GtkTreePath *) ctl->gtk_data;
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
hostname = getSelectedHost(path);
|
|
Packit |
b802ec |
if (hostname) {
|
|
Packit |
b802ec |
ctl->gtk_data = hostname;
|
|
Packit |
b802ec |
gtk_entry_set_text(GTK_ENTRY(Entry), hostname);
|
|
Packit |
b802ec |
Host_activate(Entry, ctl);
|
|
Packit |
b802ec |
g_free(hostname);
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
return TRUE;
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
static gboolean Copy_activate(
|
|
Packit |
b802ec |
GtkWidget * widget ATTRIBUTE_UNUSED,
|
|
Packit |
b802ec |
gpointer data)
|
|
Packit |
b802ec |
{
|
|
Packit |
b802ec |
gchar *hostname;
|
|
Packit |
b802ec |
GtkTreePath *path = (GtkTreePath *) data;
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
hostname = getSelectedHost(path);
|
|
Packit |
b802ec |
if (hostname != NULL) {
|
|
Packit |
b802ec |
GtkClipboard *clipboard;
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
clipboard = gtk_clipboard_get(GDK_SELECTION_CLIPBOARD);
|
|
Packit |
b802ec |
gtk_clipboard_set_text(clipboard, hostname, -1);
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
clipboard = gtk_clipboard_get(GDK_SELECTION_PRIMARY);
|
|
Packit |
b802ec |
gtk_clipboard_set_text(clipboard, hostname, -1);
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
g_free(hostname);
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
return TRUE;
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
static gchar *getSelectedHost(
|
|
Packit |
b802ec |
GtkTreePath * path)
|
|
Packit |
b802ec |
{
|
|
Packit |
b802ec |
GtkTreeIter iter;
|
|
Packit |
b802ec |
gchar *name = NULL;
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
if (gtk_tree_model_get_iter(GTK_TREE_MODEL(ReportStore), &iter, path)) {
|
|
Packit |
b802ec |
gtk_tree_model_get(GTK_TREE_MODEL(ReportStore), &iter,
|
|
Packit |
b802ec |
COL_HOSTNAME, &name, -1);
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
gtk_tree_path_free(path);
|
|
Packit |
b802ec |
return name;
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
static gboolean ReportTreeView_clicked(
|
|
Packit |
b802ec |
GtkWidget * Tree ATTRIBUTE_UNUSED,
|
|
Packit |
b802ec |
GdkEventButton * event,
|
|
Packit |
b802ec |
gpointer data)
|
|
Packit |
b802ec |
{
|
|
Packit |
b802ec |
GtkWidget *popup_menu;
|
|
Packit |
b802ec |
GtkWidget *copy_item;
|
|
Packit |
b802ec |
GtkWidget *newdestination_item;
|
|
Packit |
b802ec |
GtkTreePath *path;
|
|
Packit |
b802ec |
struct mtr_ctl *ctl = (struct mtr_ctl *) data;
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
if (event->type != GDK_BUTTON_PRESS || event->button != 3)
|
|
Packit |
b802ec |
return FALSE;
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
if (!gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(ReportTreeView),
|
|
Packit |
b802ec |
event->x, event->y, &path, NULL,
|
|
Packit |
b802ec |
NULL, NULL))
|
|
Packit |
b802ec |
return FALSE;
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
gtk_tree_view_set_cursor(GTK_TREE_VIEW(ReportTreeView), path, NULL,
|
|
Packit |
b802ec |
FALSE);
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
/* Single right click: prepare and show the popup menu */
|
|
Packit |
b802ec |
popup_menu = gtk_menu_new();
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
copy_item = gtk_menu_item_new_with_label("Copy to clipboard");
|
|
Packit |
b802ec |
newdestination_item =
|
|
Packit |
b802ec |
gtk_menu_item_new_with_label("Set as new destination");
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
gtk_menu_append(GTK_MENU(popup_menu), copy_item);
|
|
Packit |
b802ec |
gtk_menu_append(GTK_MENU(popup_menu), newdestination_item);
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
g_signal_connect(GTK_OBJECT(copy_item), "activate",
|
|
Packit |
b802ec |
GTK_SIGNAL_FUNC(Copy_activate), path);
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
ctl->gtk_data = path;
|
|
Packit |
b802ec |
g_signal_connect(GTK_OBJECT(newdestination_item), "activate",
|
|
Packit |
b802ec |
GTK_SIGNAL_FUNC(NewDestination_activate), ctl);
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
gtk_widget_show(copy_item);
|
|
Packit |
b802ec |
gtk_widget_show(newdestination_item);
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
gtk_menu_popup(GTK_MENU(popup_menu), NULL, NULL, NULL, NULL,
|
|
Packit |
b802ec |
0, event->time);
|
|
Packit |
b802ec |
return TRUE;
|
|
Packit |
b802ec |
}
|