2 * Routines for the file set dialog
6 * Wireshark - Network traffic analyzer
7 * By Gerald Combs <gerald@wireshark.org>
8 * Copyright 1998 Gerald Combs
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version 2
13 * of the License, or (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
36 #include <epan/filesystem.h>
38 #include "../fileset.h"
40 #include "ui/gtk/gui_utils.h"
41 #include "ui/gtk/dlg_utils.h"
42 #include "ui/gtk/main.h"
43 #include "ui/gtk/menus.h"
44 #include "ui/gtk/help_dlg.h"
45 #include "ui/gtk/fileset_dlg.h"
50 * Keep a static pointer to the current "File Set" window, if
51 * any, so that if somebody tries to do "File Set" while there's
52 * already a "File Set" window up, we just pop up the existing
53 * one, rather than creating a new one.
55 static GtkWidget
*fs_w
;
59 /* various widget related global data */
61 static GtkWidget
*fs_grid
;
62 static GtkWidget
*fs_sw
;
63 static GtkWidget
*fs_dir_lb
;
64 static GtkWidget
*fs_first_rb
;
65 static GtkWidget
*fs_grid_vb
;
69 /* open the file corresponding to the given fileset entry */
71 fs_open_entry(fileset_entry
*entry
)
77 /* make a copy of the filename (cf_close will indirectly destroy it right now) */
78 fname
= g_strdup(entry
->fullname
);
80 /* close the old and open the new file */
82 if (cf_open(&cfile
, fname
, FALSE
, &err
) == CF_OK
) {
83 cf_read(&cfile
, FALSE
);
90 /* radio button was pressed/released */
92 fs_rb_cb(GtkWidget
*open_bt
, gpointer fs_data
)
94 fileset_entry
*entry
= (fileset_entry
*)fs_data
;
96 /* button release should have no effect */
97 if (!gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(open_bt
) )) {
101 fs_open_entry(entry
);
105 /* the window was closed, cleanup things */
107 fs_destroy_cb(GtkWidget
*win _U_
, gpointer user_data _U_
)
109 /* Note that we no longer have a "File Set" dialog box. */
114 /* get creation date (converted from filename) */
117 fileset_dlg_name2date_dup(const char * name
) {
123 /* just to be sure ... */
124 if (!fileset_filename_match_pattern(name
)) {
128 /* find char position behind the last underscore */
129 pfx
= strrchr(name
, '_');
133 /* Start conversion behind that underscore */
134 /* http://en.wikipedia.org/wiki/ISO_8601 */
135 filename
= g_strdup_printf("%c%c%c%c-%c%c-%c%c %c%c:%c%c:%c%c",
136 /* year */ name
[pos
] , name
[pos
+1], name
[pos
+2], name
[pos
+3],
137 /* month */ name
[pos
+4], name
[pos
+5],
138 /* day */ name
[pos
+6], name
[pos
+7],
139 /* hour */ name
[pos
+8], name
[pos
+9],
140 /* min */ name
[pos
+10], name
[pos
+11],
141 /* second */ name
[pos
+12], name
[pos
+13]);
147 /* this file is a part of the current file set, add it to the dialog */
149 fileset_dlg_add_file(fileset_entry
*entry
, void *window _U_
) {
163 created
= fileset_dlg_name2date_dup(entry
->name
);
165 /* if this file doesn't follow the file set pattern, */
166 /* use the creation time of that file */
167 local
= localtime(&entry
->ctime
);
168 created
= g_strdup_printf("%04u-%02u-%02u %02u:%02u:%02u",
169 local
->tm_year
+1900, local
->tm_mon
+1, local
->tm_mday
,
170 local
->tm_hour
, local
->tm_min
, local
->tm_sec
);
173 local
= localtime(&entry
->mtime
);
174 modified
= g_strdup_printf("%04u-%02u-%02u %02u:%02u:%02u",
175 local
->tm_year
+1900, local
->tm_mon
+1, local
->tm_mday
,
176 local
->tm_hour
, local
->tm_min
, local
->tm_sec
);
177 size
= g_strdup_printf("%" G_GINT64_MODIFIER
"d Bytes", entry
->size
);
179 fs_rb
= gtk_radio_button_new_with_label_from_widget(
180 fs_first_rb
? GTK_RADIO_BUTTON(fs_first_rb
) : NULL
, entry
->name
);
184 if (entry
->current
) {
185 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON (fs_rb
), entry
->current
);
187 gtk_widget_set_tooltip_text(fs_rb
, "Open this capture file");
188 ws_gtk_grid_attach_extended(GTK_GRID(fs_grid
), fs_rb
, 0, row
, 1, 1, (GtkAttachOptions
)(GTK_EXPAND
|GTK_FILL
), (GtkAttachOptions
)0, 0, 0);
189 g_signal_connect(fs_rb
, "toggled", G_CALLBACK(fs_rb_cb
), entry
);
190 gtk_widget_show(fs_rb
);
192 fs_lb
= gtk_label_new(created
);
193 ws_gtk_grid_attach_extended(GTK_GRID(fs_grid
), fs_lb
, 1, row
, 1, 1, (GtkAttachOptions
)(GTK_EXPAND
|GTK_FILL
), (GtkAttachOptions
)0, 0, 0);
194 gtk_widget_set_sensitive(fs_lb
, entry
->current
);
195 gtk_widget_show(fs_lb
);
197 fs_lb
= gtk_label_new(modified
);
198 ws_gtk_grid_attach_extended(GTK_GRID(fs_grid
), fs_lb
, 2, row
, 1, 1, (GtkAttachOptions
)(GTK_EXPAND
|GTK_FILL
), (GtkAttachOptions
)0, 0, 0);
199 gtk_widget_set_sensitive(fs_lb
, entry
->current
);
200 gtk_widget_show(fs_lb
);
202 fs_lb
= gtk_label_new(size
);
203 ws_gtk_grid_attach_extended(GTK_GRID(fs_grid
), fs_lb
, 3, row
, 1, 1, (GtkAttachOptions
)(GTK_EXPAND
|GTK_FILL
), (GtkAttachOptions
)0, 0, 0);
204 gtk_widget_set_sensitive(fs_lb
, entry
->current
);
205 gtk_widget_show(fs_lb
);
207 title
= g_strdup_printf("Wireshark: %u File%s in Set", row
, plurality(row
, "", "s"));
208 gtk_window_set_title(GTK_WINDOW(fs_w
), title
);
211 title
= g_strdup_printf("... in directory: %s", fileset_get_dirname());
212 gtk_label_set_text(GTK_LABEL(fs_dir_lb
), title
);
215 gtk_widget_show_all(fs_grid
);
217 /* resize the table until we use 18 rows (fits well into 800*600), if it's bigger use a scrollbar */
218 /* XXX - I didn't found a way to automatically shrink the table size again */
220 GtkRequisition requisition
;
222 #if GTK_CHECK_VERSION(3,0,0)
223 gtk_widget_get_preferred_size(fs_grid
, &requisition
, NULL
);
225 gtk_widget_size_request(fs_grid
, &requisition
);
227 /* XXX use gtk_window_set_default_size()? */
228 gtk_widget_set_size_request(fs_sw
, -1, requisition
.height
);
229 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(fs_sw
), GTK_POLICY_NEVER
, GTK_POLICY_NEVER
);
233 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(fs_sw
), GTK_POLICY_NEVER
, GTK_POLICY_AUTOMATIC
);
244 /* init the fileset table */
246 fileset_init_table(GtkWidget
*parent_vb
)
250 fs_grid
= ws_gtk_grid_new();
251 ws_gtk_grid_set_row_spacing(GTK_GRID(fs_grid
), 1);
252 ws_gtk_grid_set_column_spacing(GTK_GRID(fs_grid
), 12);
253 gtk_box_pack_start(GTK_BOX(parent_vb
), fs_grid
, FALSE
, FALSE
, 0);
258 fs_lb
= gtk_label_new("Filename");
259 ws_gtk_grid_attach_extended(GTK_GRID(fs_grid
), fs_lb
, 0, row
, 1, 1, (GtkAttachOptions
)(GTK_EXPAND
|GTK_FILL
), (GtkAttachOptions
)0, 0, 0);
261 fs_lb
= gtk_label_new("Created");
262 ws_gtk_grid_attach_extended(GTK_GRID(fs_grid
), fs_lb
, 1, row
, 1, 1, (GtkAttachOptions
)(GTK_EXPAND
|GTK_FILL
), (GtkAttachOptions
)0, 0, 0);
264 fs_lb
= gtk_label_new("Last Modified");
265 ws_gtk_grid_attach_extended(GTK_GRID(fs_grid
), fs_lb
, 2, row
, 1, 1, (GtkAttachOptions
)(GTK_EXPAND
|GTK_FILL
), (GtkAttachOptions
)0, 0, 0);
267 fs_lb
= gtk_label_new("Size");
268 ws_gtk_grid_attach_extended(GTK_GRID(fs_grid
), fs_lb
, 3, row
, 1, 1, (GtkAttachOptions
)(GTK_EXPAND
|GTK_FILL
), (GtkAttachOptions
)0, 0, 0);
270 gtk_widget_hide(fs_grid
);
272 gtk_window_set_title(GTK_WINDOW(fs_w
), "Wireshark: 0 Files in Set");
274 gtk_label_set_text(GTK_LABEL(fs_dir_lb
), "No capture file loaded.");
280 /* open the fileset dialog */
282 fileset_cb(GtkWidget
*w _U_
, gpointer d _U_
)
284 GtkWidget
*main_vb
, *bbox
, *close_bt
, *help_bt
;
288 /* There's already a "File Set" dialog box; reactivate it. */
289 reactivate_window(fs_w
);
293 fs_w
= dlg_window_new(""); /* transient_for top_level */
294 gtk_window_set_destroy_with_parent (GTK_WINDOW(fs_w
), TRUE
);
296 main_vb
= ws_gtk_box_new(GTK_ORIENTATION_VERTICAL
, 5, FALSE
);
297 gtk_container_set_border_width(GTK_CONTAINER(main_vb
), 5);
298 gtk_container_add(GTK_CONTAINER(fs_w
), main_vb
);
300 fs_sw
= gtk_scrolled_window_new(NULL
, NULL
);
301 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(fs_sw
), GTK_POLICY_NEVER
, GTK_POLICY_NEVER
);
302 gtk_box_pack_start(GTK_BOX(main_vb
), fs_sw
, TRUE
, TRUE
, 0);
304 /* add a dummy container, so we can replace the table later */
305 fs_grid_vb
= ws_gtk_box_new(GTK_ORIENTATION_VERTICAL
, 0, FALSE
);
306 #if ! GTK_CHECK_VERSION(3,8,0)
307 gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(fs_sw
), fs_grid_vb
);
309 gtk_container_add(GTK_CONTAINER(fs_sw
), fs_grid_vb
);
312 fs_dir_lb
= gtk_label_new("");
313 gtk_box_pack_start(GTK_BOX(main_vb
), fs_dir_lb
, FALSE
, FALSE
, 0);
315 fileset_init_table(fs_grid_vb
);
317 /* Button row: close and help button */
318 bbox
= dlg_button_row_new(GTK_STOCK_CLOSE
, GTK_STOCK_HELP
, NULL
);
319 gtk_box_pack_start(GTK_BOX(main_vb
), bbox
, FALSE
, FALSE
, 5);
321 close_bt
= (GtkWidget
*)g_object_get_data(G_OBJECT(bbox
), GTK_STOCK_CLOSE
);
322 window_set_cancel_button(fs_w
, close_bt
, window_cancel_button_cb
);
323 gtk_widget_set_tooltip_text(close_bt
, "Close this window.");
325 help_bt
= (GtkWidget
*)g_object_get_data(G_OBJECT(bbox
), GTK_STOCK_HELP
);
326 g_signal_connect(help_bt
, "clicked", G_CALLBACK(topic_cb
), (gpointer
)HELP_FILESET_DIALOG
);
328 gtk_widget_grab_default(close_bt
);
330 g_signal_connect(fs_w
, "delete_event", G_CALLBACK(window_delete_event_cb
), NULL
);
331 g_signal_connect(fs_w
, "destroy", G_CALLBACK(fs_destroy_cb
), NULL
);
333 /* init the dialog content */
334 fileset_update_dlg(NULL
);
336 gtk_widget_show_all(fs_w
);
337 window_present(fs_w
);
341 /* open the next file in the file set, or do nothing if already the last file */
343 fileset_next_cb(GtkWidget
*w _U_
, gpointer d _U_
)
345 fileset_entry
*entry
;
347 entry
= fileset_get_next();
350 fs_open_entry(entry
);
355 /* open the previous file in the file set, or do nothing if already the first file */
357 fileset_previous_cb(GtkWidget
*w _U_
, gpointer d _U_
)
359 fileset_entry
*entry
;
361 entry
= fileset_get_previous();
364 fs_open_entry(entry
);
369 /* a new capture file was opened, browse the dir and look for files matching the given file set */
371 fileset_file_opened(const capture_file
*cf
) {
372 fileset_add_dir(cf
->filename
, NULL
);
374 window_present(fs_w
);
377 /* update the menu */
378 set_menus_for_file_set(TRUE
/* file_set */,
379 fileset_get_previous() != NULL
, fileset_get_next() != NULL
);
383 /* the capture file was closed */
385 fileset_file_closed(void)
388 /* reinit the table, title and alike */
389 g_object_ref(G_OBJECT(fs_grid_vb
));
390 gtk_widget_destroy(fs_grid
);
392 fileset_init_table(fs_grid_vb
);
393 window_present(fs_w
);
398 /* update the menu */
399 set_menus_for_file_set(FALSE
/* file_set */,
400 fileset_get_previous() != NULL
,
401 fileset_get_next() != NULL
);