Fix enhancement bug #1337: Export IO Graphs

This new code adds a save button to the Statistics IO Graphs window and
is also reusable by any other code that uses GDK Pixmaps to draw graphs.
The Gdk-pixbuf library included in GTK is used for this save function.


svn path=/trunk/; revision=22166
This commit is contained in:
Stephen Fisher 2007-06-22 22:22:10 +00:00
parent 35f3ff0246
commit 0ba44094e6
7 changed files with 241 additions and 2 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 27 KiB

After

Width:  |  Height:  |  Size: 56 KiB

View File

@ -427,7 +427,13 @@
</para>
</listitem>
</itemizedlist>
</itemizedlist>
The save button will save the currently displayed portion of
the graph as one of various file formats. The save feature is
only available when using GTK version 2.4 or higher (the
latest Windows versions comply with this requirement) and
Wireshark version 0.99.7 or higher.
XXX - describe the Advanced feature.
</para>
</section>

View File

@ -91,6 +91,7 @@ noinst_HEADERS = \
packet_history.h \
packet_list.h \
packet_win.h \
pixmap_save.h \
plugins_dlg.h \
prefs_dlg.h \
print_prefs.h \

View File

@ -88,6 +88,7 @@ WIRESHARK_GTK_SRC = \
packet_history.c \
packet_list.c \
packet_win.c \
pixmap_save.c \
plugins_dlg.c \
prefs_dlg.c \
print_dlg.c \

View File

@ -55,6 +55,7 @@
#include "dlg_utils.h"
#include "filter_dlg.h"
#include "help_dlg.h"
#include "pixmap_save.h"
void protect_thread_critical_region(void);
void unprotect_thread_critical_region(void);
@ -1143,6 +1144,9 @@ configure_event(GtkWidget *widget, GdkEventConfigure *event _U_)
{
int i;
io_stat_t *io;
#if GTK_CHECK_VERSION(2,4,0)
GtkWidget *save_bt;
#endif
io=(io_stat_t *)OBJECT_GET_DATA(widget, "io_stat_t");
if(!io){
@ -1161,6 +1165,12 @@ configure_event(GtkWidget *widget, GdkEventConfigure *event _U_)
io->pixmap_width=widget->allocation.width;
io->pixmap_height=widget->allocation.height;
#if GTK_CHECK_VERSION(2,4,0)
save_bt = OBJECT_GET_DATA(io->window, "save_bt");
SIGNAL_CONNECT(save_bt, "clicked", pixmap_save_cb, io->pixmap);
gtk_widget_set_sensitive(save_bt, TRUE);
#endif
gdk_draw_rectangle(io->pixmap,
widget->style->white_gc,
TRUE,
@ -1871,7 +1881,10 @@ init_io_stat_window(io_stat_t *io)
GtkWidget *vbox;
GtkWidget *hbox;
GtkWidget *bbox;
GtkWidget *close_bt, *help_bt;
GtkWidget *close_bt, *help_bt;
#if GTK_CHECK_VERSION(2,4,0)
GtkWidget *save_bt;
#endif
/* create the main window */
io->window=window_new(GTK_WINDOW_TOPLEVEL, "I/O Graphs");
@ -1894,9 +1907,18 @@ init_io_stat_window(io_stat_t *io)
io_stat_set_title(io);
if(topic_available(HELP_STATS_IO_GRAPH_DIALOG)) {
#if GTK_CHECK_VERSION(2,4,0)
bbox = dlg_button_row_new(GTK_STOCK_CLOSE, GTK_STOCK_SAVE,
GTK_STOCK_HELP, NULL);
#else
bbox = dlg_button_row_new(GTK_STOCK_CLOSE, GTK_STOCK_HELP, NULL);
#endif
} else {
#if GTK_CHECK_VERSION(2,4,0)
bbox = dlg_button_row_new(GTK_STOCK_CLOSE, GTK_STOCK_SAVE, NULL);
#else
bbox = dlg_button_row_new(GTK_STOCK_CLOSE, NULL);
#endif
}
gtk_box_pack_start(GTK_BOX(vbox), bbox, FALSE, FALSE, 0);
gtk_widget_show(bbox);
@ -1904,6 +1926,12 @@ init_io_stat_window(io_stat_t *io)
close_bt = OBJECT_GET_DATA(bbox, GTK_STOCK_CLOSE);
window_set_cancel_button(io->window, close_bt, window_cancel_button_cb);
#if GTK_CHECK_VERSION(2,4,0)
save_bt = OBJECT_GET_DATA(bbox, GTK_STOCK_SAVE);
gtk_widget_set_sensitive(save_bt, FALSE);
OBJECT_SET_DATA(io->window, "save_bt", save_bt);
#endif
if(topic_available(HELP_STATS_IO_GRAPH_DIALOG)) {
help_bt = OBJECT_GET_DATA(bbox, GTK_STOCK_HELP);
SIGNAL_CONNECT(help_bt, "clicked", topic_cb, HELP_STATS_IO_GRAPH_DIALOG);

170
gtk/pixmap_save.c Normal file
View File

@ -0,0 +1,170 @@
/* pixmap_save.c
* Routines for saving pixmaps using the Gdk-Pixmap library
* Copyright 2007, Stephen Fisher <stephentfisher@yahoo.com>
*
* $Id$
*
* Wireshark - Network traffic analyzer
* By Gerald Combs <gerald@wireshark.org>
* Copyright 1998 Gerald Combs
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <glib.h>
#include <gtk/gtk.h>
/* This feature is not available in GTK1 and includes some functions that
* are only available in GTK2.4+ */
#if GTK_CHECK_VERSION(2,4,0)
#include "pixmap_save.h"
#include "simple_dialog.h"
#include "gui_utils.h"
#include "file_dlg.h"
#include "compat_macros.h"
#include <errno.h>
#include <epan/filesystem.h>
static GtkWidget *save_as_w;
static void
pixbuf_save_destroy_cb(GtkWidget *window _U_, gpointer data _U_)
{
/* We no longer have a save as dialog */
save_as_w = NULL;
}
static void
pixbuf_save_button_cb(GtkWidget *save_as_w, GdkPixbuf *pixbuf)
{
gchar *filename, *file_type;
GtkWidget *type_cm, *simple_w;
GError *error = NULL;
gboolean ret;
filename = g_strdup(gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(save_as_w)));
type_cm = OBJECT_GET_DATA(save_as_w, "type_cm");
file_type = gtk_combo_box_get_active_text(GTK_COMBO_BOX(type_cm));
/* Perhaps the user specified a directory instead of a file.
Check whether they did. */
if(test_for_directory(filename) == EISDIR) {
/* It's a directory - set the file selection box to display that
directory, and leave the selection box displayed. */
set_last_open_dir(filename);
g_free(filename);
file_selection_set_current_folder(save_as_w,
get_last_open_dir());
return;
}
ret = gdk_pixbuf_save(pixbuf, filename, file_type, &error, NULL);
if(!ret) {
simple_w = simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
"%s%s%s",
simple_dialog_primary_start(),
error->message,
simple_dialog_primary_end());
gtk_window_set_transient_for(GTK_WINDOW(simple_w),
GTK_WINDOW(save_as_w));
}
}
void
pixmap_save_cb(GtkWidget *w, gpointer pixmap_ptr)
{
GdkPixmap *pixmap = pixmap_ptr;
GdkPixbuf *pixbuf;
GdkPixbufFormat *pixbuf_format;
GtkWidget *main_vb, *save_as_type_hb, *type_lb, *type_cm;
GSList *file_formats;
GdkWindow *parent;
pixbuf = gdk_pixbuf_get_from_drawable(NULL, GDK_DRAWABLE(pixmap), NULL,
0, 0, 0, 0, -1, -1);
if(!pixbuf) {
simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
"%sCould not get image from graph%s",
simple_dialog_primary_start(),
simple_dialog_primary_end());
return;
}
if(save_as_w != NULL) {
/* If this save as window is already open, re-open it */
reactivate_window(save_as_w);
return;
}
save_as_w = file_selection_new("Wireshark: Save Graph As ...",
FILE_SELECTION_SAVE);
/* Container for each row of widgets */
main_vb = gtk_vbox_new(FALSE, 0);
file_selection_set_extra_widget(save_as_w, main_vb);
gtk_widget_show(main_vb);
save_as_type_hb = gtk_hbox_new(FALSE, 0);
gtk_box_pack_start(GTK_BOX(main_vb), save_as_type_hb, FALSE, FALSE, 0);
gtk_widget_show(save_as_type_hb);
type_lb = gtk_label_new("File type: ");
gtk_box_pack_start(GTK_BOX(save_as_type_hb), type_lb, FALSE, FALSE, 0);
gtk_widget_show(type_lb);
type_cm = gtk_combo_box_new_text();
gtk_box_pack_start(GTK_BOX(save_as_type_hb), type_cm, FALSE, FALSE, 0);
/* List all of the file formats the gdk-pixbuf library supports */
file_formats = gdk_pixbuf_get_formats();
while(file_formats) {
if (gdk_pixbuf_format_is_writable(file_formats->data)) {
pixbuf_format = file_formats->data;
gtk_combo_box_append_text(GTK_COMBO_BOX(type_cm),
gdk_pixbuf_format_get_name(pixbuf_format));
}
file_formats = file_formats->next;
}
g_slist_free(file_formats);
gtk_combo_box_set_active(GTK_COMBO_BOX(type_cm), 0);
OBJECT_SET_DATA(save_as_w, "type_cm", type_cm);
gtk_widget_show(type_cm);
SIGNAL_CONNECT(save_as_w, "destroy", pixbuf_save_destroy_cb, NULL);
gtk_widget_show(save_as_w);
window_present(save_as_w);
parent = gtk_widget_get_parent_window(w);
gdk_window_set_transient_for(save_as_w->window, parent);
if(gtk_dialog_run(GTK_DIALOG(save_as_w)) == GTK_RESPONSE_ACCEPT)
pixbuf_save_button_cb(save_as_w, pixbuf);
window_destroy(save_as_w);
}
#endif /* GTK_CHECK_VERSION(2,4,0) */

33
gtk/pixmap_save.h Normal file
View File

@ -0,0 +1,33 @@
/* pixmap_save.h
* Routines for saving pixmaps using the Gdk-Pixmap library
* Copyright 2007, Stephen Fisher <stephentfisher@yahoo.com>
*
* $Id$
*
* Wireshark - Network traffic analyzer
* By Gerald Combs <gerald@wireshark.org>
* Copyright 1998 Gerald Combs
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __PIXMAP_SAVE_H__
#define __PIXMAP_SAVE_H__
/* Callback to be tied to a save button. This function will pop-up a dialog
* asking for options to save the graph with (such as file type). */
void pixmap_save_cb(GtkWidget *w, gpointer pixmap_ptr);
#endif /* __PIXMAP_SAVE_H__ */