2008-01-14 16:40:23 +00:00
/* profile_dlg.c
* Dialog box for profiles editing
2008-10-29 07:31:45 +00:00
* Stig Bjorlykke < stig @ bjorlykke . org > , 2008
2008-01-14 16:40:23 +00:00
*
* $ 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 <string.h>
# include <gtk/gtk.h>
2008-01-14 21:43:10 +00:00
# include <gdk/gdkkeysyms.h>
2008-01-14 16:40:23 +00:00
# include <epan/filesystem.h>
2008-04-13 03:32:24 +00:00
# include <epan/prefs.h>
# include "../simple_dialog.h"
2008-05-22 15:46:27 +00:00
# include <wsutil/file_util.h>
2008-01-14 16:40:23 +00:00
# include "gtk/main.h"
2008-04-13 03:32:24 +00:00
# include "gtk/profile_dlg.h"
# include "gtk/dlg_utils.h"
# include "gtk/gui_utils.h"
# include "gtk/gtkglobals.h"
# include "gtk/help_dlg.h"
2008-01-14 16:40:23 +00:00
# define E_PROF_PROFILE_L_KEY "profile_profile_l"
# define E_PROF_DEL_BT_KEY "profile_del_bt"
# define E_PROF_NAME_TE_KEY "profile_name_te"
static GtkWidget * global_profile_w = NULL ;
static GList * current_profiles = NULL ;
static GList * edited_profiles = NULL ;
# define PROF_STAT_DEFAULT 1
# define PROF_STAT_EXISTS 2
# define PROF_STAT_NEW 3
# define PROF_STAT_CHANGED 4
# define PROF_STAT_COPY 5
typedef struct {
char * name ; /* profile name */
char * reference ; /* profile reference */
int status ;
} profile_def ;
static GList *
add_profile_entry ( GList * fl , const char * profilename , const char * reference , int status )
{
profile_def * profile ;
profile = ( profile_def * ) g_malloc ( sizeof ( profile_def ) ) ;
profile - > name = g_strdup ( profilename ) ;
profile - > reference = g_strdup ( reference ) ;
profile - > status = status ;
return g_list_append ( fl , profile ) ;
}
static GList *
remove_profile_entry ( GList * fl , GList * fl_entry )
{
profile_def * profile ;
profile = ( profile_def * ) fl_entry - > data ;
g_free ( profile - > name ) ;
g_free ( profile - > reference ) ;
g_free ( profile ) ;
return g_list_remove_link ( fl , fl_entry ) ;
}
2009-12-21 12:32:31 +00:00
static const gchar *
get_profile_parent ( const gchar * profilename )
{
GList * fl_entry = g_list_first ( edited_profiles ) ;
guint no_edited = g_list_length ( edited_profiles ) ;
profile_def * profile ;
guint i ;
if ( fl_entry ) {
/* We have edited profiles, find parent */
for ( i = 0 ; i < no_edited ; i + + ) {
while ( fl_entry ) {
profile = ( profile_def * ) fl_entry - > data ;
if ( strcmp ( profile - > name , profilename ) = = 0 ) {
if ( ( profile - > status = = PROF_STAT_NEW ) | |
( profile - > reference = = NULL ) ) {
/* Copy from a new profile */
return NULL ;
} else {
/* Found a parent, use this */
profilename = profile - > reference ;
}
}
fl_entry = g_list_next ( fl_entry ) ;
}
fl_entry = g_list_first ( edited_profiles ) ;
}
}
return profilename ;
}
2008-01-14 16:40:23 +00:00
static GList *
add_to_profile_list ( const char * name , const char * expression , int status )
{
edited_profiles = add_profile_entry ( edited_profiles , name , expression , status ) ;
return g_list_last ( edited_profiles ) ;
}
static void
remove_from_profile_list ( GList * fl_entry )
{
edited_profiles = remove_profile_entry ( edited_profiles , fl_entry ) ;
}
static void
empty_profile_list ( gboolean edit_list )
{
GList * * flpp ;
if ( edit_list ) {
flpp = & edited_profiles ;
while ( * flpp ) {
* flpp = remove_profile_entry ( * flpp , g_list_first ( * flpp ) ) ;
}
2008-05-22 15:46:27 +00:00
2008-01-14 16:40:23 +00:00
g_assert ( g_list_length ( * flpp ) = = 0 ) ;
2008-05-22 15:46:27 +00:00
}
2008-01-14 16:40:23 +00:00
flpp = & current_profiles ;
while ( * flpp ) {
* flpp = remove_profile_entry ( * flpp , g_list_first ( * flpp ) ) ;
}
2008-05-22 15:46:27 +00:00
2008-01-14 16:40:23 +00:00
g_assert ( g_list_length ( * flpp ) = = 0 ) ;
}
static void
copy_profile_list ( void )
{
GList * flp_src ;
profile_def * profile ;
flp_src = edited_profiles ;
/* throw away the "old" destination list - a NULL list is ok here */
empty_profile_list ( FALSE ) ;
/* copy the list entries */
while ( flp_src ) {
profile = ( flp_src ) - > data ;
2008-05-22 15:46:27 +00:00
current_profiles = add_profile_entry ( current_profiles , profile - > name ,
2008-01-14 16:40:23 +00:00
profile - > reference , profile - > status ) ;
flp_src = g_list_next ( flp_src ) ;
}
}
static GtkTreeIter *
fill_list ( GtkWidget * main_w )
{
2008-10-27 04:47:57 +00:00
WS_DIR * dir ; /* scanned directory */
WS_DIRENT * file ; /* current file */
2008-01-14 16:40:23 +00:00
GList * fl_entry ;
profile_def * profile ;
GtkTreeView * profile_l ;
GtkListStore * store ;
GtkTreeIter iter , * l_select = NULL ;
const gchar * profile_name = get_profile_name ( ) ;
const gchar * profiles_dir , * name ;
gchar * filename ;
2008-05-22 15:46:27 +00:00
2008-04-11 16:44:31 +00:00
profile_l = GTK_TREE_VIEW ( g_object_get_data ( G_OBJECT ( main_w ) , E_PROF_PROFILE_L_KEY ) ) ;
2008-01-14 16:40:23 +00:00
store = GTK_LIST_STORE ( gtk_tree_view_get_model ( profile_l ) ) ;
2008-05-22 15:46:27 +00:00
2008-01-14 16:40:23 +00:00
fl_entry = add_to_profile_list ( DEFAULT_PROFILE , DEFAULT_PROFILE , PROF_STAT_DEFAULT ) ;
gtk_list_store_append ( store , & iter ) ;
gtk_list_store_set ( store , & iter , 0 , DEFAULT_PROFILE , 1 , fl_entry , - 1 ) ;
2008-01-24 17:06:22 +00:00
if ( strcmp ( profile_name , DEFAULT_PROFILE ) = = 0 ) {
2008-01-14 16:40:23 +00:00
l_select = g_memdup ( & iter , sizeof ( iter ) ) ;
}
2008-05-22 15:46:27 +00:00
2008-01-14 16:40:23 +00:00
/* fill in data */
profiles_dir = get_profiles_dir ( ) ;
2008-05-22 15:46:27 +00:00
if ( ( dir = ws_dir_open ( profiles_dir , 0 , NULL ) ) ! = NULL ) {
while ( ( file = ws_dir_read_name ( dir ) ) ! = NULL ) {
name = ws_dir_get_name ( file ) ;
2008-01-14 16:40:23 +00:00
filename = g_strdup_printf ( " %s%s%s " , profiles_dir , G_DIR_SEPARATOR_S , name ) ;
if ( test_for_directory ( filename ) = = EISDIR ) {
fl_entry = add_to_profile_list ( name , name , PROF_STAT_EXISTS ) ;
profile = ( profile_def * ) fl_entry - > data ;
gtk_list_store_append ( store , & iter ) ;
gtk_list_store_set ( store , & iter , 0 , profile - > name , 1 , fl_entry , - 1 ) ;
2008-05-22 15:46:27 +00:00
2008-01-24 17:06:22 +00:00
if ( profile - > name ) {
2008-01-14 16:40:23 +00:00
if ( strcmp ( profile_name , profile - > name ) = = 0 ) {
/*
* XXX - We ' re assuming that we can just copy a GtkTreeIter
* and use it later without any crashes . This may not be a
* valid assumption .
*/
l_select = g_memdup ( & iter , sizeof ( iter ) ) ;
}
}
}
g_free ( filename ) ;
}
2008-05-22 15:46:27 +00:00
ws_dir_close ( dir ) ;
2008-01-14 16:40:23 +00:00
}
2009-04-08 13:41:30 +00:00
/* Make the current list and the edited list equal */
2008-01-14 16:40:23 +00:00
copy_profile_list ( ) ;
2008-05-22 15:46:27 +00:00
2008-01-14 16:40:23 +00:00
return l_select ;
}
2008-02-04 15:50:17 +00:00
static gboolean
profile_is_invalid_name ( gchar * name )
{
gchar * message = NULL ;
# ifdef _WIN32
char * invalid_dir_char = " \\ /:*? \" <>| " ;
gboolean invalid = FALSE ;
int i ;
for ( i = 0 ; i < 9 ; i + + ) {
if ( strchr ( name , invalid_dir_char [ i ] ) ) {
/* Invalid character in directory */
invalid = TRUE ;
}
}
if ( name [ 0 ] = = ' . ' | | name [ strlen ( name ) - 1 ] = = ' . ' ) {
/* Profile name cannot start or end with period */
invalid = TRUE ;
}
if ( invalid ) {
message = g_strdup_printf ( " start or end with period (.), or contain any of the following characters: \n "
" \\ / : * ? \" < > | " ) ;
}
# else
if ( strchr ( name , ' / ' ) ) {
/* Invalid character in directory */
message = g_strdup_printf ( " contain the '/' character. " ) ;
}
# endif
if ( message ) {
simple_dialog ( ESD_TYPE_ERROR , ESD_BTN_OK , " A profile name cannot %s \n Profiles unchanged. " , message ) ;
g_free ( message ) ;
return TRUE ;
}
return FALSE ;
}
2008-01-14 16:40:23 +00:00
static void
profile_select ( GtkWidget * main_w , GtkTreeView * profile_l , gboolean destroy )
{
GList * fl_entry ;
profile_def * profile ;
GtkTreeSelection * sel ;
GtkTreeModel * model ;
GtkTreeIter iter ;
sel = gtk_tree_view_get_selection ( GTK_TREE_VIEW ( profile_l ) ) ;
if ( gtk_tree_selection_get_selected ( sel , & model , & iter ) ) {
gtk_tree_model_get ( model , & iter , 1 , & fl_entry , - 1 ) ;
if ( fl_entry ) {
profile = ( profile_def * ) fl_entry - > data ;
2008-01-27 14:45:31 +00:00
if ( profile_exists ( profile - > name ) ) {
/* The new profile exists, change */
2008-01-14 16:40:23 +00:00
change_configuration_profile ( profile - > name ) ;
2008-01-27 14:45:31 +00:00
} else if ( ! profile_exists ( get_profile_name ( ) ) ) {
2008-05-22 15:46:27 +00:00
/* The new profile does not exist, and the previous profile has
2008-01-27 14:45:31 +00:00
been deleted . Change to the default profile */
2008-01-14 16:40:23 +00:00
change_configuration_profile ( NULL ) ;
}
}
}
if ( destroy ) {
/*
* Destroy the profile dialog box .
*/
empty_profile_list ( TRUE ) ;
window_destroy ( main_w ) ;
}
}
static void
2008-01-19 01:18:35 +00:00
profile_apply ( GtkWidget * main_w , GtkTreeView * profile_l , gboolean destroy )
2008-01-14 16:40:23 +00:00
{
2009-12-21 12:32:31 +00:00
char * pf_dir_path , * pf_dir_path2 , * pf_filename ;
2008-01-14 16:40:23 +00:00
GList * fl1 , * fl2 ;
profile_def * profile1 , * profile2 ;
gboolean found ;
2008-02-04 15:50:17 +00:00
/* First validate all profile names */
fl1 = g_list_first ( edited_profiles ) ;
while ( fl1 ) {
profile1 = ( profile_def * ) fl1 - > data ;
g_strstrip ( profile1 - > name ) ;
if ( profile_is_invalid_name ( profile1 - > name ) ) {
return ;
}
fl1 = g_list_next ( fl1 ) ;
}
2009-12-21 12:32:31 +00:00
/* Then do all copy profiles */
fl1 = g_list_first ( edited_profiles ) ;
while ( fl1 ) {
profile1 = ( profile_def * ) fl1 - > data ;
g_strstrip ( profile1 - > name ) ;
if ( profile1 - > status = = PROF_STAT_COPY ) {
if ( create_persconffile_profile ( profile1 - > name , & pf_dir_path ) = = - 1 ) {
simple_dialog ( ESD_TYPE_ERROR , ESD_BTN_OK ,
" Can't create directory \n \" %s \" : \n %s. " ,
pf_dir_path , strerror ( errno ) ) ;
g_free ( pf_dir_path ) ;
}
profile1 - > status = PROF_STAT_EXISTS ;
if ( profile1 - > reference ) {
if ( copy_persconffile_profile ( profile1 - > name , profile1 - > reference , & pf_filename ,
& pf_dir_path , & pf_dir_path2 ) = = - 1 ) {
simple_dialog ( ESD_TYPE_ERROR , ESD_BTN_OK ,
" Can't copy file \" %s \" in directory \n \" %s \" to \n \" %s \" : \n %s. " ,
pf_filename , pf_dir_path2 , pf_dir_path , strerror ( errno ) ) ;
g_free ( pf_filename ) ;
g_free ( pf_dir_path ) ;
g_free ( pf_dir_path2 ) ;
}
}
g_free ( profile1 - > reference ) ;
profile1 - > reference = g_strdup ( profile1 - > name ) ;
}
fl1 = g_list_next ( fl1 ) ;
}
2008-02-04 15:50:17 +00:00
/* Then create new and rename changed */
2008-01-14 16:40:23 +00:00
fl1 = g_list_first ( edited_profiles ) ;
while ( fl1 ) {
profile1 = ( profile_def * ) fl1 - > data ;
2008-02-01 18:42:59 +00:00
g_strstrip ( profile1 - > name ) ;
2008-01-14 16:40:23 +00:00
if ( profile1 - > status = = PROF_STAT_NEW ) {
/* We do not create a directory for the default profile */
if ( strcmp ( profile1 - > name , DEFAULT_PROFILE ) ! = 0 ) {
if ( create_persconffile_profile ( profile1 - > name , & pf_dir_path ) = = - 1 ) {
simple_dialog ( ESD_TYPE_ERROR , ESD_BTN_OK ,
" Can't create directory \n \" %s \" : \n %s. " ,
pf_dir_path , strerror ( errno ) ) ;
2008-05-22 15:46:27 +00:00
2008-01-14 16:40:23 +00:00
g_free ( pf_dir_path ) ;
}
profile1 - > status = PROF_STAT_EXISTS ;
2009-03-13 22:06:48 +00:00
g_free ( profile1 - > reference ) ;
2008-02-01 16:49:34 +00:00
profile1 - > reference = g_strdup ( profile1 - > name ) ;
2008-01-14 16:40:23 +00:00
}
} else if ( profile1 - > status = = PROF_STAT_CHANGED ) {
if ( strcmp ( profile1 - > reference , profile1 - > name ) ! = 0 ) {
/* Rename old profile directory to new */
if ( rename_persconffile_profile ( profile1 - > reference , profile1 - > name ,
& pf_dir_path , & pf_dir_path2 ) = = - 1 ) {
simple_dialog ( ESD_TYPE_ERROR , ESD_BTN_OK ,
" Can't rename directory \n \" %s \" to \n \" %s \" : \n %s. " ,
pf_dir_path , pf_dir_path2 , strerror ( errno ) ) ;
2008-05-22 15:46:27 +00:00
2008-01-14 16:40:23 +00:00
g_free ( pf_dir_path ) ;
2009-12-21 12:32:31 +00:00
g_free ( pf_dir_path2 ) ;
2008-01-14 16:40:23 +00:00
}
profile1 - > status = PROF_STAT_EXISTS ;
2008-02-01 16:49:34 +00:00
g_free ( profile1 - > reference ) ;
profile1 - > reference = g_strdup ( profile1 - > name ) ;
2008-01-14 16:40:23 +00:00
}
}
fl1 = g_list_next ( fl1 ) ;
}
2008-02-04 15:50:17 +00:00
/* Last remove deleted */
2008-01-14 16:40:23 +00:00
fl1 = g_list_first ( current_profiles ) ;
while ( fl1 ) {
found = FALSE ;
profile1 = ( profile_def * ) fl1 - > data ;
fl2 = g_list_first ( edited_profiles ) ;
while ( fl2 ) {
profile2 = ( profile_def * ) fl2 - > data ;
if ( strcmp ( profile1 - > name , profile2 - > name ) = = 0 ) {
/* Profile exists in both lists */
found = TRUE ;
} else if ( strcmp ( profile1 - > name , profile2 - > reference ) = = 0 ) {
/* Profile has been renamed */
found = TRUE ;
}
fl2 = fl2 - > next ;
}
if ( ! found ) {
/* Exists in existing list and not in edited, this is a deleted profile */
if ( delete_persconffile_profile ( profile1 - > name , & pf_dir_path ) = = - 1 ) {
simple_dialog ( ESD_TYPE_ERROR , ESD_BTN_OK ,
" Can't delete profile directory \n \" %s \" : \n %s. " ,
pf_dir_path , strerror ( errno ) ) ;
g_free ( pf_dir_path ) ;
}
}
fl1 = g_list_next ( fl1 ) ;
}
copy_profile_list ( ) ;
2008-01-14 21:58:45 +00:00
profile_select ( main_w , profile_l , destroy ) ;
}
static void
profile_dlg_ok_cb ( GtkWidget * ok_bt , gpointer data _U_ )
{
2008-01-19 01:18:35 +00:00
GtkWidget * main_w = gtk_widget_get_toplevel ( ok_bt ) ;
2008-04-11 16:44:31 +00:00
GtkTreeView * profile_l = GTK_TREE_VIEW ( g_object_get_data ( G_OBJECT ( main_w ) , E_PROF_PROFILE_L_KEY ) ) ;
2008-05-22 15:46:27 +00:00
2008-01-14 16:40:23 +00:00
/*
2008-01-14 21:58:45 +00:00
* Apply the profile and destroy the dialog box .
2008-01-14 16:40:23 +00:00
*/
2008-01-19 01:18:35 +00:00
profile_apply ( main_w , profile_l , TRUE ) ;
2008-01-14 16:40:23 +00:00
}
static void
profile_dlg_apply_cb ( GtkWidget * apply_bt , gpointer data _U_ )
{
2008-04-11 16:44:31 +00:00
GtkWidget * main_w = gtk_widget_get_toplevel ( apply_bt ) ;
GtkTreeView * profile_l = GTK_TREE_VIEW ( g_object_get_data ( G_OBJECT ( main_w ) , E_PROF_PROFILE_L_KEY ) ) ;
2008-01-19 01:18:35 +00:00
2008-01-14 16:40:23 +00:00
/*
* Apply the profile , but don ' t destroy the dialog box .
*/
2008-01-19 01:18:35 +00:00
profile_apply ( main_w , profile_l , FALSE ) ;
2008-01-14 16:40:23 +00:00
}
/* cancel button pressed, revert changes and exit dialog */
static void
profile_dlg_cancel_cb ( GtkWidget * cancel_bt , gpointer data _U_ )
{
GtkWidget * main_w = gtk_widget_get_toplevel ( cancel_bt ) ;
empty_profile_list ( TRUE ) ;
window_destroy ( GTK_WIDGET ( main_w ) ) ;
}
/* Treat this as a cancel, by calling "profile_dlg_cancel_cb()" */
static gboolean
profile_dlg_delete_event_cb ( GtkWidget * main_w , GdkEvent * event _U_ ,
gpointer data )
{
profile_dlg_cancel_cb ( main_w , data ) ;
return FALSE ;
}
static void
profile_dlg_destroy_cb ( GtkWidget * w _U_ , gpointer data _U_ )
{
global_profile_w = NULL ;
}
static gint
2008-01-19 01:18:35 +00:00
profile_button_press_cb ( GtkWidget * list , GdkEventButton * event , gpointer data _U_ )
2008-01-14 16:40:23 +00:00
{
if ( event - > type = = GDK_2BUTTON_PRESS ) {
2008-01-19 01:18:35 +00:00
GtkWidget * main_w = gtk_widget_get_toplevel ( list ) ;
2008-01-14 16:40:23 +00:00
2008-01-19 01:18:35 +00:00
profile_apply ( main_w , GTK_TREE_VIEW ( list ) , TRUE ) ;
2008-01-14 16:40:23 +00:00
}
return FALSE ;
}
2008-01-14 21:43:10 +00:00
static gint
profile_key_release_cb ( GtkWidget * list , GdkEventKey * event , gpointer data _U_ )
{
if ( event - > keyval = = GDK_Return | | event - > keyval = = GDK_KP_Enter ) {
2008-01-19 01:18:35 +00:00
GtkWidget * main_w = gtk_widget_get_toplevel ( list ) ;
2008-01-14 21:43:10 +00:00
2008-01-19 01:18:35 +00:00
profile_apply ( main_w , GTK_TREE_VIEW ( list ) , TRUE ) ;
2008-01-14 21:43:10 +00:00
}
return FALSE ;
}
2008-01-14 16:40:23 +00:00
static void
profile_sel_list_cb ( GtkTreeSelection * sel , gpointer data _U_ )
{
2008-04-11 16:44:31 +00:00
GtkWidget * profile_l = GTK_WIDGET ( gtk_tree_selection_get_tree_view ( sel ) ) ;
GtkWidget * main_w = gtk_widget_get_toplevel ( profile_l ) ;
2008-01-14 16:40:23 +00:00
GtkTreeModel * model ;
GtkTreeIter iter ;
2008-04-11 16:44:31 +00:00
GtkWidget * name_te = g_object_get_data ( G_OBJECT ( main_w ) , E_PROF_NAME_TE_KEY ) ;
GtkWidget * del_bt = g_object_get_data ( G_OBJECT ( main_w ) , E_PROF_DEL_BT_KEY ) ;
2008-01-14 16:40:23 +00:00
profile_def * profile ;
2008-04-11 16:44:31 +00:00
gchar * name = NULL ;
2008-01-14 16:40:23 +00:00
GList * fl_entry ;
gint sensitivity = FALSE ;
if ( gtk_tree_selection_get_selected ( sel , & model , & iter ) ) {
gtk_tree_model_get ( model , & iter , 1 , & fl_entry , - 1 ) ;
if ( fl_entry ) {
profile = ( profile_def * ) fl_entry - > data ;
name = g_strdup ( profile - > name ) ;
if ( profile - > status ! = PROF_STAT_DEFAULT ) {
sensitivity = TRUE ;
}
}
}
/*
* Did you know that this function is called when the window is destroyed ?
* Funny , that .
* This means that we have to :
*
* attach to the top - level window data items containing pointers to
* the widgets we affect here ;
*
* give each of those widgets their own destroy callbacks ;
*
* clear that pointer when the widget is destroyed ;
*
* don ' t do anything to the widget if the pointer we get back is
* null ;
*
* so that if we ' re called after any of the widgets we ' d affect are
* destroyed , we know that we shouldn ' t do anything to those widgets .
*/
if ( name_te ! = NULL ) {
gtk_entry_set_text ( GTK_ENTRY ( name_te ) , name ? name : " " ) ;
gtk_widget_set_sensitive ( name_te , sensitivity ) ;
}
if ( del_bt ! = NULL )
gtk_widget_set_sensitive ( del_bt , sensitivity ) ;
2009-03-13 22:06:48 +00:00
g_free ( name ) ;
2008-01-14 16:40:23 +00:00
}
static void
profile_new_bt_clicked_cb ( GtkWidget * w , gpointer data _U_ )
{
GtkWidget * main_w = gtk_widget_get_toplevel ( w ) ;
2008-04-11 16:44:31 +00:00
GtkWidget * name_te = g_object_get_data ( G_OBJECT ( main_w ) , E_PROF_NAME_TE_KEY ) ;
GtkTreeView * profile_l = GTK_TREE_VIEW ( g_object_get_data ( G_OBJECT ( main_w ) , E_PROF_PROFILE_L_KEY ) ) ;
2008-01-14 16:40:23 +00:00
GtkListStore * store ;
GtkTreeIter iter ;
GList * fl_entry ;
const gchar * name = " New profile " ;
/* Add a new entry to the profile list. */
fl_entry = add_to_profile_list ( name , " " , PROF_STAT_NEW ) ;
store = GTK_LIST_STORE ( gtk_tree_view_get_model ( profile_l ) ) ;
gtk_list_store_append ( store , & iter ) ;
gtk_list_store_set ( store , & iter , 0 , name , 1 , fl_entry , - 1 ) ;
/* Select the item. */
gtk_tree_selection_select_iter ( gtk_tree_view_get_selection ( profile_l ) , & iter ) ;
2008-01-14 21:43:10 +00:00
gtk_editable_select_region ( GTK_EDITABLE ( name_te ) , 0 , - 1 ) ;
gtk_widget_grab_focus ( name_te ) ;
2008-01-14 16:40:23 +00:00
}
static void
profile_copy_bt_clicked_cb ( GtkWidget * w , gpointer data _U_ )
{
GtkWidget * main_w = gtk_widget_get_toplevel ( w ) ;
2008-04-11 16:44:31 +00:00
GtkWidget * name_te = g_object_get_data ( G_OBJECT ( main_w ) , E_PROF_NAME_TE_KEY ) ;
GtkTreeView * profile_l = GTK_TREE_VIEW ( g_object_get_data ( G_OBJECT ( main_w ) , E_PROF_PROFILE_L_KEY ) ) ;
2008-01-14 16:40:23 +00:00
GtkListStore * store ;
GtkTreeIter iter ;
GList * fl_entry ;
const gchar * name = gtk_entry_get_text ( GTK_ENTRY ( name_te ) ) ;
gchar * new_name ;
new_name = g_strdup_printf ( " %s (copy) " , name ) ;
/* Add a new entry to the profile list. */
2009-12-21 12:32:31 +00:00
fl_entry = add_to_profile_list ( new_name , get_profile_parent ( name ) , PROF_STAT_COPY ) ;
2008-01-14 16:40:23 +00:00
store = GTK_LIST_STORE ( gtk_tree_view_get_model ( profile_l ) ) ;
gtk_list_store_append ( store , & iter ) ;
gtk_list_store_set ( store , & iter , 0 , new_name , 1 , fl_entry , - 1 ) ;
/* Select the item. */
gtk_tree_selection_select_iter ( gtk_tree_view_get_selection ( profile_l ) , & iter ) ;
2008-01-14 21:43:10 +00:00
gtk_editable_select_region ( GTK_EDITABLE ( name_te ) , 0 , - 1 ) ;
gtk_widget_grab_focus ( name_te ) ;
2008-01-14 16:40:23 +00:00
g_free ( new_name ) ;
}
static void
profile_name_te_changed_cb ( GtkWidget * w , gpointer data _U_ )
{
GtkWidget * main_w = gtk_widget_get_toplevel ( w ) ;
2008-04-11 16:44:31 +00:00
GtkWidget * name_te = g_object_get_data ( G_OBJECT ( main_w ) , E_PROF_NAME_TE_KEY ) ;
GtkWidget * profile_l = g_object_get_data ( G_OBJECT ( main_w ) , E_PROF_PROFILE_L_KEY ) ;
2008-01-14 16:40:23 +00:00
profile_def * profile ;
GList * fl_entry ;
const gchar * name = " " ;
GtkTreeSelection * sel ;
GtkTreeModel * model ;
GtkTreeIter iter ;
sel = gtk_tree_view_get_selection ( GTK_TREE_VIEW ( profile_l ) ) ;
name = gtk_entry_get_text ( GTK_ENTRY ( name_te ) ) ;
/* if something was selected */
if ( gtk_tree_selection_get_selected ( sel , & model , & iter ) ) {
gtk_tree_model_get ( model , & iter , 1 , & fl_entry , - 1 ) ;
if ( fl_entry ! = NULL ) {
profile = ( profile_def * ) fl_entry - > data ;
2008-05-22 15:46:27 +00:00
2008-01-14 16:40:23 +00:00
if ( strlen ( name ) > 0 & & profile ) {
if ( profile - > status ! = PROF_STAT_DEFAULT ) {
2008-02-04 15:50:17 +00:00
g_free ( profile - > name ) ;
profile - > name = g_strdup ( name ) ;
2009-12-21 12:32:31 +00:00
if ( ( profile - > status ! = PROF_STAT_NEW ) & &
( profile - > status ! = PROF_STAT_COPY ) ) {
2008-02-04 15:50:17 +00:00
profile - > status = PROF_STAT_CHANGED ;
2008-01-14 16:40:23 +00:00
}
2008-02-04 15:50:17 +00:00
gtk_list_store_set ( GTK_LIST_STORE ( model ) , & iter , 0 , name , - 1 ) ;
2008-01-14 16:40:23 +00:00
}
}
}
}
}
static void
profile_del_bt_clicked_cb ( GtkWidget * w , gpointer data _U_ )
{
GtkWidget * main_w = gtk_widget_get_toplevel ( w ) ;
2008-04-11 16:44:31 +00:00
GtkWidget * profile_l = g_object_get_data ( G_OBJECT ( main_w ) , E_PROF_PROFILE_L_KEY ) ;
2008-01-14 16:40:23 +00:00
GList * fl_entry ;
GtkTreeSelection * sel ;
GtkTreeModel * model ;
GtkTreeIter iter ;
sel = gtk_tree_view_get_selection ( GTK_TREE_VIEW ( profile_l ) ) ;
/* If something was selected */
if ( gtk_tree_selection_get_selected ( sel , & model , & iter ) ) {
gtk_tree_model_get ( model , & iter , 1 , & fl_entry , - 1 ) ;
if ( fl_entry ! = NULL ) {
remove_from_profile_list ( fl_entry ) ;
gtk_list_store_remove ( GTK_LIST_STORE ( model ) , & iter ) ;
}
}
if ( gtk_tree_model_get_iter_first ( model , & iter ) ) {
gtk_tree_selection_select_iter ( sel , & iter ) ;
}
}
static GtkWidget *
profile_dialog_new ( void )
{
GtkWidget * main_w , /* main window */
* main_vb , /* main container */
* bbox , /* button container */
* ok_bt , /* "OK" button */
* apply_bt , /* "Apply" button */
* cancel_bt , /* "Cancel" button */
* help_bt ; /* "Help" button */
GtkWidget * profile_vb , /* profile settings box */
* props_vb ;
GtkWidget * top_hb ,
* list_bb ,
* new_bt ,
* copy_bt ,
* del_bt ,
* profile_sc ,
* profile_l ,
* middle_hb ,
* name_lb ,
* name_te ,
* profile_fr ,
* edit_fr ,
* props_fr ;
GtkTooltips * tooltips ;
GtkListStore * store ;
GtkCellRenderer * renderer ;
GtkTreeViewColumn * column ;
GtkTreeSelection * sel ;
GtkTreeIter * l_select ;
2008-05-22 15:46:27 +00:00
2008-01-14 16:40:23 +00:00
/* Get a pointer to a static variable holding the type of profile on
which we ' re working , so we can pass that pointer to callback
routines . */
2008-05-22 15:46:27 +00:00
2008-01-14 16:40:23 +00:00
tooltips = gtk_tooltips_new ( ) ;
2008-05-22 15:46:27 +00:00
2008-04-14 15:01:34 +00:00
main_w = dlg_conf_window_new ( " Wireshark: Configuration Profiles " ) ;
2008-01-14 16:40:23 +00:00
gtk_window_set_default_size ( GTK_WINDOW ( main_w ) , 400 , 400 ) ;
2008-05-22 15:46:27 +00:00
2008-01-14 16:40:23 +00:00
main_vb = gtk_vbox_new ( FALSE , 0 ) ;
2008-06-29 15:51:43 +00:00
gtk_container_set_border_width ( GTK_CONTAINER ( main_vb ) , 5 ) ;
2008-01-14 16:40:23 +00:00
gtk_container_add ( GTK_CONTAINER ( main_w ) , main_vb ) ;
gtk_widget_show ( main_vb ) ;
/* Container for each row of widgets */
profile_vb = gtk_vbox_new ( FALSE , 0 ) ;
2008-06-29 15:51:43 +00:00
gtk_container_set_border_width ( GTK_CONTAINER ( profile_vb ) , 0 ) ;
2008-01-14 16:40:23 +00:00
gtk_container_add ( GTK_CONTAINER ( main_vb ) , profile_vb ) ;
gtk_widget_show ( profile_vb ) ;
/* Top row: Buttons and profile list */
top_hb = gtk_hbox_new ( FALSE , 0 ) ;
gtk_container_add ( GTK_CONTAINER ( profile_vb ) , top_hb ) ;
gtk_widget_show ( top_hb ) ;
edit_fr = gtk_frame_new ( " Edit " ) ;
gtk_box_pack_start ( GTK_BOX ( top_hb ) , edit_fr , FALSE , FALSE , 0 ) ;
gtk_widget_show ( edit_fr ) ;
list_bb = gtk_vbox_new ( TRUE , 0 ) ;
2008-06-29 15:51:43 +00:00
gtk_container_set_border_width ( GTK_CONTAINER ( list_bb ) , 5 ) ;
2008-01-14 16:40:23 +00:00
gtk_container_add ( GTK_CONTAINER ( edit_fr ) , list_bb ) ;
gtk_widget_show ( list_bb ) ;
2008-04-11 18:58:19 +00:00
new_bt = gtk_button_new_from_stock ( GTK_STOCK_NEW ) ;
2008-04-11 23:16:06 +00:00
g_signal_connect ( new_bt , " clicked " , G_CALLBACK ( profile_new_bt_clicked_cb ) , NULL ) ;
2008-01-14 16:40:23 +00:00
gtk_widget_show ( new_bt ) ;
gtk_box_pack_start ( GTK_BOX ( list_bb ) , new_bt , FALSE , FALSE , 0 ) ;
gtk_tooltips_set_tip ( tooltips , new_bt ,
" Create a new profile (with default properties) " , NULL ) ;
2008-04-11 18:58:19 +00:00
copy_bt = gtk_button_new_from_stock ( GTK_STOCK_COPY ) ;
2008-04-11 23:16:06 +00:00
g_signal_connect ( copy_bt , " clicked " , G_CALLBACK ( profile_copy_bt_clicked_cb ) , NULL ) ;
2008-01-14 16:40:23 +00:00
gtk_widget_show ( copy_bt ) ;
gtk_box_pack_start ( GTK_BOX ( list_bb ) , copy_bt , FALSE , FALSE , 0 ) ;
gtk_tooltips_set_tip ( tooltips , copy_bt ,
" Copy the selected profile " , NULL ) ;
2008-04-11 18:58:19 +00:00
del_bt = gtk_button_new_from_stock ( GTK_STOCK_DELETE ) ;
2008-01-14 16:40:23 +00:00
gtk_widget_set_sensitive ( del_bt , FALSE ) ;
2008-04-11 23:16:06 +00:00
g_signal_connect ( del_bt , " clicked " , G_CALLBACK ( profile_del_bt_clicked_cb ) , NULL ) ;
2008-04-11 16:44:31 +00:00
g_object_set_data ( G_OBJECT ( main_w ) , E_PROF_DEL_BT_KEY , del_bt ) ;
2008-01-14 16:40:23 +00:00
gtk_widget_show ( del_bt ) ;
gtk_box_pack_start ( GTK_BOX ( list_bb ) , del_bt , FALSE , FALSE , 0 ) ;
gtk_tooltips_set_tip ( tooltips , del_bt , " Delete the selected profile " , NULL ) ;
profile_fr = gtk_frame_new ( " Configuration Profiles " ) ;
gtk_box_pack_start ( GTK_BOX ( top_hb ) , profile_fr , TRUE , TRUE , 0 ) ;
gtk_widget_show ( profile_fr ) ;
profile_sc = scrolled_window_new ( NULL , NULL ) ;
gtk_scrolled_window_set_shadow_type ( GTK_SCROLLED_WINDOW ( profile_sc ) ,
GTK_SHADOW_IN ) ;
gtk_container_set_border_width ( GTK_CONTAINER ( profile_sc ) , 5 ) ;
gtk_container_add ( GTK_CONTAINER ( profile_fr ) , profile_sc ) ;
gtk_widget_show ( profile_sc ) ;
store = gtk_list_store_new ( 2 , G_TYPE_STRING , G_TYPE_POINTER ) ;
profile_l = tree_view_new ( GTK_TREE_MODEL ( store ) ) ;
gtk_tree_view_set_headers_visible ( GTK_TREE_VIEW ( profile_l ) , FALSE ) ;
renderer = gtk_cell_renderer_text_new ( ) ;
column = gtk_tree_view_column_new_with_attributes ( " " , renderer , " text " , 0 , NULL ) ;
gtk_tree_view_column_set_sort_column_id ( column , 0 ) ;
gtk_tree_view_append_column ( GTK_TREE_VIEW ( profile_l ) , column ) ;
sel = gtk_tree_view_get_selection ( GTK_TREE_VIEW ( profile_l ) ) ;
gtk_tree_selection_set_mode ( sel , GTK_SELECTION_SINGLE ) ;
2008-04-11 23:16:06 +00:00
g_signal_connect ( sel , " changed " , G_CALLBACK ( profile_sel_list_cb ) , profile_vb ) ;
g_signal_connect ( profile_l , " button_press_event " , G_CALLBACK ( profile_button_press_cb ) , NULL ) ;
g_signal_connect ( profile_l , " key_release_event " , G_CALLBACK ( profile_key_release_cb ) , NULL ) ;
2008-04-11 16:44:31 +00:00
g_object_set_data ( G_OBJECT ( main_w ) , E_PROF_PROFILE_L_KEY , profile_l ) ;
2008-01-14 16:40:23 +00:00
gtk_container_add ( GTK_CONTAINER ( profile_sc ) , profile_l ) ;
gtk_widget_show ( profile_l ) ;
/* fill in data */
l_select = fill_list ( main_w ) ;
g_object_unref ( G_OBJECT ( store ) ) ;
props_fr = gtk_frame_new ( " Properties " ) ;
gtk_box_pack_start ( GTK_BOX ( profile_vb ) , props_fr , FALSE , FALSE , 0 ) ;
gtk_widget_show ( props_fr ) ;
props_vb = gtk_vbox_new ( FALSE , 3 ) ;
2008-06-29 15:51:43 +00:00
gtk_container_set_border_width ( GTK_CONTAINER ( props_vb ) , 5 ) ;
2008-01-14 16:40:23 +00:00
gtk_container_add ( GTK_CONTAINER ( props_fr ) , props_vb ) ;
gtk_widget_show ( props_vb ) ;
/* row: Profile name entry */
middle_hb = gtk_hbox_new ( FALSE , 3 ) ;
gtk_container_add ( GTK_CONTAINER ( props_vb ) , middle_hb ) ;
gtk_widget_show ( middle_hb ) ;
name_lb = gtk_label_new ( " Profile name: " ) ;
gtk_box_pack_start ( GTK_BOX ( middle_hb ) , name_lb , FALSE , FALSE , 0 ) ;
gtk_widget_show ( name_lb ) ;
name_te = gtk_entry_new ( ) ;
gtk_box_pack_start ( GTK_BOX ( middle_hb ) , name_te , TRUE , TRUE , 0 ) ;
2008-04-11 16:44:31 +00:00
g_object_set_data ( G_OBJECT ( main_w ) , E_PROF_NAME_TE_KEY , name_te ) ;
2008-04-11 23:16:06 +00:00
g_signal_connect ( name_te , " changed " , G_CALLBACK ( profile_name_te_changed_cb ) , NULL ) ;
2008-02-01 16:49:34 +00:00
# ifdef _WIN32
2008-02-04 15:50:17 +00:00
gtk_tooltips_set_tip ( tooltips , name_te , " A profile name cannot start or end with a period (.), and cannot contain any of the following characters: \n \\ / : * ? \" < > | " , NULL ) ;
2008-02-01 16:49:34 +00:00
# else
2008-02-04 15:50:17 +00:00
gtk_tooltips_set_tip ( tooltips , name_te , " A profile name cannot contain the '/' character " , NULL ) ;
2008-02-01 16:49:34 +00:00
# endif
2008-01-14 16:40:23 +00:00
gtk_widget_show ( name_te ) ;
/* button row (create all possible buttons and hide the unrequired later - it's a lot easier) */
bbox = dlg_button_row_new ( GTK_STOCK_OK , GTK_STOCK_APPLY , GTK_STOCK_CANCEL , GTK_STOCK_HELP , NULL ) ;
gtk_box_pack_start ( GTK_BOX ( main_vb ) , bbox , FALSE , FALSE , 5 ) ;
gtk_widget_show ( bbox ) ;
2008-04-11 16:44:31 +00:00
ok_bt = g_object_get_data ( G_OBJECT ( bbox ) , GTK_STOCK_OK ) ;
2008-04-11 23:16:06 +00:00
g_signal_connect ( ok_bt , " clicked " , G_CALLBACK ( profile_dlg_ok_cb ) , NULL ) ;
2008-01-14 16:40:23 +00:00
gtk_tooltips_set_tip ( tooltips , ok_bt , " Apply the profiles and close this dialog " , NULL ) ;
/* Catch the "activate" signal on the profile name and profile
list entries , so that if the user types Return
there , we act as if the " OK " button had been selected , as
happens if Return is typed if some widget that * doesn ' t *
handle the Return key has the input focus . */
dlg_set_activate ( name_te , ok_bt ) ;
2008-04-11 16:44:31 +00:00
apply_bt = g_object_get_data ( G_OBJECT ( bbox ) , GTK_STOCK_APPLY ) ;
2008-04-11 23:16:06 +00:00
g_signal_connect ( apply_bt , " clicked " , G_CALLBACK ( profile_dlg_apply_cb ) , NULL ) ;
2008-01-14 16:40:23 +00:00
gtk_tooltips_set_tip ( tooltips , apply_bt , " Apply the profiles and keep this dialog open " , NULL ) ;
2008-04-11 16:44:31 +00:00
cancel_bt = g_object_get_data ( G_OBJECT ( bbox ) , GTK_STOCK_CANCEL ) ;
2008-01-14 16:40:23 +00:00
gtk_tooltips_set_tip ( tooltips , cancel_bt , " Cancel the changes " , NULL ) ;
2008-04-11 23:16:06 +00:00
g_signal_connect ( cancel_bt , " clicked " , G_CALLBACK ( profile_dlg_cancel_cb ) , NULL ) ;
2008-01-14 16:40:23 +00:00
window_set_cancel_button ( main_w , cancel_bt , NULL ) ;
2008-04-11 16:44:31 +00:00
help_bt = g_object_get_data ( G_OBJECT ( bbox ) , GTK_STOCK_HELP ) ;
2008-04-11 23:16:06 +00:00
g_signal_connect ( help_bt , " clicked " , G_CALLBACK ( topic_cb ) , ( gpointer ) HELP_CONFIG_PROFILES_DIALOG ) ;
2008-01-14 16:40:23 +00:00
gtk_tooltips_set_tip ( tooltips , help_bt , " Show topic specific help " , NULL ) ;
if ( ok_bt ) {
gtk_widget_grab_default ( ok_bt ) ;
}
/* DO SELECTION THINGS *AFTER* SHOWING THE DIALOG! */
/* otherwise the updatings can get confused */
if ( l_select ) {
gtk_tree_selection_select_iter ( sel , l_select ) ;
g_free ( l_select ) ;
}
2008-01-14 21:43:10 +00:00
if ( profile_l ) {
gtk_widget_grab_focus ( profile_l ) ;
}
2008-04-11 23:16:06 +00:00
g_signal_connect ( main_w , " delete_event " , G_CALLBACK ( profile_dlg_delete_event_cb ) , NULL ) ;
g_signal_connect ( main_w , " destroy " , G_CALLBACK ( profile_dlg_destroy_cb ) , NULL ) ;
2008-01-14 16:40:23 +00:00
gtk_widget_show ( main_w ) ;
window_present ( main_w ) ;
return main_w ;
}
2008-10-27 04:47:57 +00:00
static void
2008-06-17 19:50:22 +00:00
select_profile_cb ( GtkWidget * w _U_ , gpointer data )
{
const gchar * current_profile = get_profile_name ( ) ;
gchar * selected_profile = ( gchar * ) data ;
if ( strcmp ( selected_profile , current_profile ) ! = 0 ) {
change_configuration_profile ( selected_profile ) ;
}
}
gboolean
profile_show_popup_cb ( GtkWidget * w _U_ , GdkEvent * event )
{
GdkEventButton * bevent = ( GdkEventButton * ) event ;
const gchar * profile_name = get_profile_name ( ) ;
const gchar * profiles_dir , * name ;
2008-10-27 04:47:57 +00:00
WS_DIR * dir ; /* scanned directory */
WS_DIRENT * file ; /* current file */
2008-06-17 19:50:22 +00:00
GtkWidget * menu ;
GtkWidget * menu_item ;
menu = gtk_menu_new ( ) ;
/* Add a menu item for the Default profile */
menu_item = gtk_check_menu_item_new_with_label ( DEFAULT_PROFILE ) ;
if ( strcmp ( profile_name , DEFAULT_PROFILE ) = = 0 ) {
/* Check current profile */
gtk_check_menu_item_set_active ( GTK_CHECK_MENU_ITEM ( menu_item ) , TRUE ) ;
}
2008-06-18 15:57:12 +00:00
g_object_set ( G_OBJECT ( menu_item ) , " draw-as-radio " , TRUE , NULL ) ;
2008-06-17 19:50:22 +00:00
g_signal_connect ( menu_item , " activate " , G_CALLBACK ( select_profile_cb ) , g_strdup ( DEFAULT_PROFILE ) ) ;
2009-02-26 21:41:07 +00:00
gtk_menu_shell_append ( GTK_MENU_SHELL ( menu ) , menu_item ) ;
2008-06-17 19:50:22 +00:00
gtk_widget_show ( menu_item ) ;
profiles_dir = get_profiles_dir ( ) ;
if ( ( dir = ws_dir_open ( profiles_dir , 0 , NULL ) ) ! = NULL ) {
while ( ( file = ws_dir_read_name ( dir ) ) ! = NULL ) {
name = ws_dir_get_name ( file ) ;
if ( profile_exists ( name ) ) {
menu_item = gtk_check_menu_item_new_with_label ( name ) ;
if ( strcmp ( name , profile_name ) = = 0 ) {
/* Check current profile */
gtk_check_menu_item_set_active ( GTK_CHECK_MENU_ITEM ( menu_item ) , TRUE ) ;
}
2008-06-18 15:57:12 +00:00
g_object_set ( G_OBJECT ( menu_item ) , " draw-as-radio " , TRUE , NULL ) ;
2008-06-17 19:50:22 +00:00
g_signal_connect ( menu_item , " activate " , G_CALLBACK ( select_profile_cb ) , g_strdup ( name ) ) ;
2009-02-26 21:41:07 +00:00
gtk_menu_shell_append ( GTK_MENU_SHELL ( menu ) , menu_item ) ;
2008-06-17 19:50:22 +00:00
gtk_widget_show ( menu_item ) ;
}
}
}
gtk_menu_popup ( GTK_MENU ( menu ) , NULL , NULL , NULL , NULL ,
bevent - > button , bevent - > time ) ;
2008-10-27 04:47:57 +00:00
2008-06-17 19:50:22 +00:00
return TRUE ;
}
2008-01-14 16:40:23 +00:00
/* Create a profile dialog for editing display profiles; this is to be used
as a callback for menu items , toolbars , etc . . */
void
profile_dialog_cb ( GtkWidget * w _U_ )
{
/* Has a profiles dialog box already been opened */
if ( global_profile_w ! = NULL ) {
/* Yes. Just reactivate it. */
reactivate_window ( global_profile_w ) ;
} else {
global_profile_w = profile_dialog_new ( ) ;
}
}