bc221b133e015f8566b41636845fc82a0bf4cd93
[metze/wireshark/wip.git] / ui / qt / main_window_slots.cpp
1 /* main_window.cpp
2  *
3  * $Id$
4  *
5  * Wireshark - Network traffic analyzer
6  * By Gerald Combs <gerald@wireshark.org>
7  * Copyright 1998 Gerald Combs
8  *
9  * This program is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU General Public License
11  * as published by the Free Software Foundation; either version 2
12  * of the License, or (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22  */
23
24 #include <config.h>
25
26 #ifdef HAVE_FCNTL_H
27 #include <fcntl.h>
28 #endif
29
30 #ifdef HAVE_UNISTD_H
31 #include <unistd.h>
32 #endif
33
34 #include "main_window.h"
35 #include "ui_main_window.h"
36
37 #include "globals.h"
38
39 #include <epan/filesystem.h>
40 #include <epan/prefs.h>
41
42 #ifdef _WIN32
43 #include <windows.h>
44 #include <io.h>
45 #endif
46
47 #ifdef HAVE_LIBPCAP
48 #include "capture.h"
49 #include "capture-pcap-util.h"
50 #include "capture_ui_utils.h"
51 #endif
52
53 #include "wsutil/file_util.h"
54
55 #include "ui/alert_box.h"
56 #include "ui/capture_globals.h"
57 #include "ui/help_url.h"
58 #include "ui/main_statusbar.h"
59 #include "ui/ssl_key_export.h"
60
61 #include "wireshark_application.h"
62 #include "capture_file_dialog.h"
63 #include "export_object_dialog.h"
64 #include "print_dialog.h"
65
66 #include <QMessageBox>
67 #include <QClipboard>
68
69 #include <QDebug>
70
71 //
72 // Public slots
73 //
74
75 void MainWindow::openCaptureFile(QString &cf_path, QString &display_filter)
76 {
77     QString file_name = "";
78     dfilter_t *rfcode = NULL;
79     int err;
80
81     testCaptureFileClose(false);
82
83     for (;;) {
84
85         if (cf_path.isEmpty()) {
86             CaptureFileDialog open_dlg(this, cap_file_, display_filter);
87
88             switch (prefs.gui_fileopen_style) {
89
90             case FO_STYLE_LAST_OPENED:
91                 /* The user has specified that we should start out in the last directory
92                    we looked in.  If we've already opened a file, use its containing
93                    directory, if we could determine it, as the directory, otherwise
94                    use the "last opened" directory saved in the preferences file if
95                    there was one. */
96                 /* This is now the default behaviour in file_selection_new() */
97                 break;
98
99             case FO_STYLE_SPECIFIED:
100                 /* The user has specified that we should always start out in a
101                    specified directory; if they've specified that directory,
102                    start out by showing the files in that dir. */
103                 if (prefs.gui_fileopen_dir[0] != '\0')
104                     open_dlg.setDirectory(prefs.gui_fileopen_dir);
105                 break;
106             }
107
108             if (open_dlg.open(file_name)) {
109                 if (dfilter_compile(display_filter.toUtf8().constData(), &rfcode)) {
110                     cf_set_rfcode(&cfile, rfcode);
111                 } else {
112                     /* Not valid.  Tell the user, and go back and run the file
113                        selection box again once they dismiss the alert. */
114                     //bad_dfilter_alert_box(top_level, display_filter->str);
115                     QMessageBox::warning(this, tr("Invalid Display Filter"),
116                                          QString("The filter expression ") +
117                                          display_filter +
118                                          QString(" isn't a valid display filter. (") +
119                                          dfilter_error_msg + QString(")."),
120                                          QMessageBox::Ok);
121                     continue;
122                 }
123                 cf_path = file_name;
124             } else {
125                 return;
126             }
127         }
128
129         /* Try to open the capture file. */
130         cfile.window = this;
131         if (cf_open(&cfile, cf_path.toUtf8().constData(), FALSE, &err) != CF_OK) {
132             /* We couldn't open it; don't dismiss the open dialog box,
133                just leave it around so that the user can, after they
134                dismiss the alert box popped up for the open error,
135                try again. */
136             cfile.window = NULL;
137             if (rfcode != NULL)
138                 dfilter_free(rfcode);
139             cf_path.clear();
140             continue;
141         }
142
143         switch (cf_read(&cfile, FALSE)) {
144
145         case CF_READ_OK:
146         case CF_READ_ERROR:
147             /* Just because we got an error, that doesn't mean we were unable
148                to read any of the file; we handle what we could get from the
149                file. */
150             break;
151
152         case CF_READ_ABORTED:
153             /* The user bailed out of re-reading the capture file; the
154                capture file has been closed - just free the capture file name
155                string and return (without changing the last containing
156                directory). */
157             cap_file_ = NULL;
158             return;
159         }
160         break;
161     }
162     // get_dirname overwrites its path. Hopefully this isn't a problem.
163     wsApp->setLastOpenDir(get_dirname(cf_path.toUtf8().data()));
164     df_combo_box_->setEditText(display_filter);
165
166     main_ui_->statusBar->showExpert();
167 }
168
169 void MainWindow::filterPackets(QString& new_filter, bool force)
170 {
171     cf_status_t cf_status;
172
173     cf_status = cf_filter_packets(&cfile, new_filter.toUtf8().data(), force);
174
175     if (cf_status == CF_OK) {
176         emit displayFilterSuccess(true);
177         if (new_filter.length() > 0) {
178             if (df_combo_box_->findText(new_filter) < 0) {
179                 df_combo_box_->insertItem(0, new_filter);
180             }
181         }
182     } else {
183         emit displayFilterSuccess(false);
184     }
185 }
186
187 // Capture callbacks
188
189 #ifdef HAVE_LIBPCAP
190 void MainWindow::captureCapturePrepared(capture_options *capture_opts) {
191     qDebug() << "FIX captureCapturePrepared";
192 //    main_capture_set_main_window_title(capture_opts);
193
194 //    if(icon_list == NULL) {
195 //        icon_list = icon_list_create(wsiconcap16_xpm, wsiconcap32_xpm, wsiconcap48_xpm, NULL);
196 //    }
197 //    gtk_window_set_icon_list(GTK_WINDOW(top_level), icon_list);
198
199     /* Disable menu items that make no sense if you're currently running
200        a capture. */
201     setForCaptureInProgress(true);
202 //    set_capture_if_dialog_for_capture_in_progress(TRUE);
203
204 //    /* Don't set up main window for a capture file. */
205 //    main_set_for_capture_file(FALSE);
206     main_ui_->mainStack->setCurrentWidget(packet_splitter_);
207     cap_file_ = (capture_file *) capture_opts->cf;
208 }
209 void MainWindow::captureCaptureUpdateStarted(capture_options *capture_opts) {
210     Q_UNUSED(capture_opts);
211
212     setForCaptureInProgress(true);
213     setForCapturedPackets(true);
214 }
215 void MainWindow::captureCaptureUpdateFinished(capture_options *capture_opts) {
216     Q_UNUSED(capture_opts);
217
218     /* The capture isn't stopping any more - it's stopped. */
219     capture_stopping_ = false;
220
221     /* Update the main window as appropriate */
222     updateForUnsavedChanges();
223
224     /* Enable menu items that make sense if you're not currently running
225      a capture. */
226     setForCaptureInProgress(false);
227
228 }
229 void MainWindow::captureCaptureFixedStarted(capture_options *capture_opts) {
230     Q_UNUSED(capture_opts);
231     qDebug() << "captureCaptureFixedStarted";
232 }
233 void MainWindow::captureCaptureFixedFinished(capture_options *capture_opts) {
234     Q_UNUSED(capture_opts);
235     qDebug() << "captureCaptureFixedFinished";
236
237     /* The capture isn't stopping any more - it's stopped. */
238     capture_stopping_ = false;
239
240     /* Enable menu items that make sense if you're not currently running
241      a capture. */
242     setForCaptureInProgress(false);
243
244 }
245 void MainWindow::captureCaptureStopping(capture_options *capture_opts) {
246     Q_UNUSED(capture_opts);
247
248     capture_stopping_ = true;
249     setMenusForCaptureStopping();
250 }
251 void MainWindow::captureCaptureFailed(capture_options *capture_opts) {
252     Q_UNUSED(capture_opts);
253     qDebug() << "captureCaptureFailed";
254     /* Capture isn't stopping any more. */
255     capture_stopping_ = false;
256
257     setForCaptureInProgress(false);
258 }
259 #endif // HAVE_LIBPCAP
260
261
262 // Callbacks from cfile.c via WiresharkApplication::captureFileCallback
263
264 void MainWindow::captureFileOpened(const capture_file *cf) {
265     if (cf->window != this) return;
266     cap_file_ = (capture_file *) cf;
267
268     file_set_dialog_.fileOpened(cf);
269     setMenusForFileSet(true);
270     emit setCaptureFile(cap_file_);
271 }
272
273 void MainWindow::captureFileReadStarted(const capture_file *cf) {
274     if (cf != cap_file_) return;
275 //    tap_param_dlg_update();
276
277     /* Set up main window for a capture file. */
278 //    main_set_for_capture_file(TRUE);
279
280     main_ui_->statusBar->popFileStatus();
281     QString msg = QString(tr("Loading: %1")).arg(get_basename(cf->filename));
282     main_ui_->statusBar->pushFileStatus(msg);
283     main_ui_->mainStack->setCurrentWidget(packet_splitter_);
284     WiresharkApplication::processEvents();
285 }
286
287 void MainWindow::captureFileReadFinished(const capture_file *cf) {
288     if (cf != cap_file_) return;
289
290 //    gchar *dir_path;
291
292 //    if (!cf->is_tempfile && cf->filename) {
293 //        /* Add this filename to the list of recent files in the "Recent Files" submenu */
294 //        add_menu_recent_capture_file(cf->filename);
295
296 //        /* Remember folder for next Open dialog and save it in recent */
297 //      dir_path = get_dirname(g_strdup(cf->filename));
298 //        wsApp->setLastOpenDir(dir_path);
299 //        g_free(dir_path);
300 //    }
301 //    set_display_filename(cf);
302
303     /* Update the appropriate parts of the main window. */
304     updateForUnsavedChanges();
305
306 //    /* Enable menu items that make sense if you have some captured packets. */
307     setForCapturedPackets(true);
308
309     main_ui_->statusBar->popFileStatus();
310     QString msg = QString().sprintf("%s", get_basename(cf->filename));
311     main_ui_->statusBar->pushFileStatus(msg);
312 }
313
314 void MainWindow::captureFileClosing(const capture_file *cf) {
315     if (cf != cap_file_) return;
316
317     setMenusForCaptureFile(true);
318     setForCapturedPackets(false);
319     setForCaptureInProgress(false);
320
321     // Reset expert info indicator
322     main_ui_->statusBar->hideExpert();
323 //    gtk_widget_show(expert_info_none);
324     emit setCaptureFile(NULL);
325 }
326
327 void MainWindow::captureFileClosed(const capture_file *cf) {
328     if (cf != cap_file_) return;
329     packets_bar_update();
330
331     file_set_dialog_.fileClosed();
332     setMenusForFileSet(false);
333
334     // Reset expert info indicator
335     main_ui_->statusBar->hideExpert();
336
337     main_ui_->statusBar->popFileStatus();
338     cap_file_ = NULL;
339
340     setMenusForSelectedTreeRow();
341 }
342
343 //
344 // Private slots
345 //
346
347 // ui/gtk/capture_dlg.c:start_capture_confirmed
348
349 void MainWindow::startCapture() {
350     interface_options interface_opts;
351     guint i;
352
353     /* did the user ever select a capture interface before? */
354     if(global_capture_opts.num_selected == 0) {
355         QString msg = QString("No interface selected");
356         main_ui_->statusBar->pushTemporaryStatus(msg);
357         return;
358     }
359
360     /* XXX - we might need to init other pref data as well... */
361 //    main_auto_scroll_live_changed(auto_scroll_live);
362
363     /* XXX - can this ever happen? */
364     if (global_capture_opts.state != CAPTURE_STOPPED)
365       return;
366
367     /* close the currently loaded capture file */
368     cf_close((capture_file *) global_capture_opts.cf);
369
370     /* Copy the selected interfaces to the set of interfaces to use for
371        this capture. */
372     collect_ifaces(&global_capture_opts);
373
374     cfile.window = this;
375     if (capture_start(&global_capture_opts)) {
376         /* The capture succeeded, which means the capture filter syntax is
377          valid; add this capture filter to the recent capture filter list. */
378         for (i = 0; i < global_capture_opts.ifaces->len; i++) {
379             interface_opts = g_array_index(global_capture_opts.ifaces, interface_options, i);
380             if (interface_opts.cfilter) {
381 //              cfilter_combo_add_recent(interface_opts.cfilter);
382             }
383         }
384     } else {
385         cfile.window = NULL;
386     }
387 }
388
389 // Copied from ui/gtk/gui_utils.c
390 void MainWindow::pipeTimeout() {
391 #ifdef _WIN32
392     HANDLE handle;
393     DWORD avail = 0;
394     gboolean result, result1;
395     DWORD childstatus;
396     gint iterations = 0;
397
398
399     /* try to read data from the pipe only 5 times, to avoid blocking */
400     while(iterations < 5) {
401         /*g_log(NULL, G_LOG_LEVEL_DEBUG, "pipe_timer_cb: new iteration");*/
402
403         /* Oddly enough although Named pipes don't work on win9x,
404            PeekNamedPipe does !!! */
405         handle = (HANDLE) _get_osfhandle (pipe_source_);
406         result = PeekNamedPipe(handle, NULL, 0, NULL, &avail, NULL);
407
408         /* Get the child process exit status */
409         result1 = GetExitCodeProcess((HANDLE)*(pipe_child_process_),
410                                      &childstatus);
411
412         /* If the Peek returned an error, or there are bytes to be read
413            or the childwatcher thread has terminated then call the normal
414            callback */
415         if (!result || avail > 0 || childstatus != STILL_ACTIVE) {
416
417             /*g_log(NULL, G_LOG_LEVEL_DEBUG, "pipe_timer_cb: data avail");*/
418
419             /* And call the real handler */
420             if (!pipe_input_cb_(pipe_source_, pipe_user_data_)) {
421                 g_log(NULL, G_LOG_LEVEL_DEBUG, "pipe_timer_cb: input pipe closed, iterations: %u", iterations);
422                 /* pipe closed, return false so that the old timer is not run again */
423                 delete pipe_timer_;
424                 return;
425             }
426         }
427         else {
428             /*g_log(NULL, G_LOG_LEVEL_DEBUG, "pipe_timer_cb: no data avail");*/
429             /* No data, stop now */
430             break;
431         }
432
433         iterations++;
434     }
435 #endif // _WIN32
436 }
437
438 void MainWindow::pipeActivated(int source) {
439 #ifdef _WIN32
440     Q_UNUSED(source);
441 #else
442     g_assert(source == pipe_source_);
443
444     pipe_notifier_->setEnabled(false);
445     if (pipe_input_cb_(pipe_source_, pipe_user_data_)) {
446         pipe_notifier_->setEnabled(true);
447     } else {
448         delete pipe_notifier_;
449     }
450 #endif // _WIN32
451 }
452
453 void MainWindow::pipeNotifierDestroyed() {
454 #ifdef _WIN32
455     pipe_timer_ = NULL;
456 #else
457     pipe_notifier_ = NULL;
458 #endif // _WIN32
459 }
460
461 void MainWindow::stopCapture() {
462 //#ifdef HAVE_AIRPCAP
463 //  if (airpcap_if_active)
464 //    airpcap_set_toolbar_stop_capture(airpcap_if_active);
465 //#endif
466
467     capture_stop(&global_capture_opts);
468 }
469
470 // XXX - Copied from ui/gtk/menus.c
471
472 /**
473  * Add the capture filename (with an absolute path) to the "Recent Files" menu.
474  *
475  * @param cf_name Absolute path to the file.
476  * @param first Prepend the filename if true, otherwise append it. Default is false (append).
477  */
478 // XXX - We should probably create a RecentFile class.
479 void MainWindow::updateRecentFiles() {
480     QAction *ra;
481     QMenu *recentMenu = main_ui_->menuOpenRecentCaptureFile;
482     QString action_cf_name;
483
484     if (!recentMenu) {
485         return;
486     }
487
488     recentMenu->clear();
489
490     /* Iterate through the actions in menuOpenRecentCaptureFile,
491      * removing special items, a maybe duplicate entry and every item above count_max */
492     int shortcut = Qt::Key_0;
493     foreach (recent_item_status *ri, wsApp->recentItems()) {
494         // Add the new item
495         ra = new QAction(recentMenu);
496         ra->setData(ri->filename);
497         // XXX - Needs get_recent_item_status or equivalent
498         ra->setEnabled(ri->accessible);
499         recentMenu->insertAction(NULL, ra);
500         action_cf_name = ra->data().toString();
501         if (shortcut <= Qt::Key_9) {
502             ra->setShortcut(Qt::META | shortcut);
503             shortcut++;
504         }
505         ra->setText(action_cf_name);
506         connect(ra, SIGNAL(triggered()), this, SLOT(recentActionTriggered()));
507     }
508
509     if (recentMenu->actions().count() > 0) {
510         // Separator + "Clear"
511         // XXX - Do we really need this?
512         ra = new QAction(recentMenu);
513         ra->setSeparator(true);
514         recentMenu->insertAction(NULL, ra);
515
516         ra = new QAction(recentMenu);
517         ra->setText(tr("Clear Menu"));
518         recentMenu->insertAction(NULL, ra);
519         connect(ra, SIGNAL(triggered()), wsApp, SLOT(clearRecentItems()));
520     } else {
521         if (main_ui_->actionDummyNoFilesFound) {
522             recentMenu->addAction(main_ui_->actionDummyNoFilesFound);
523         }
524     }
525 }
526
527 void MainWindow::recentActionTriggered() {
528     QAction *ra = qobject_cast<QAction*>(sender());
529
530     if (ra) {
531         QString cfPath = ra->data().toString();
532         openCaptureFile(cfPath);
533     }
534 }
535
536 void MainWindow::setMenusForSelectedTreeRow(field_info *fi) {
537     //gboolean properties;
538     //gint id;
539
540     // XXX Add commented items below
541
542     if (cap_file_) {
543         cap_file_->finfo_selected = fi;
544     }
545
546     if (cap_file_ != NULL && fi != NULL) {
547         /*
548         header_field_info *hfinfo = fi->hfinfo;
549         const char *abbrev;
550         char *prev_abbrev;
551
552         if (hfinfo->parent == -1) {
553             abbrev = hfinfo->abbrev;
554             id = (hfinfo->type == FT_PROTOCOL) ? proto_get_id((protocol_t *)hfinfo->strings) : -1;
555         } else {
556             abbrev = proto_registrar_get_abbrev(hfinfo->parent);
557             id = hfinfo->parent;
558         }
559         properties = prefs_is_registered_protocol(abbrev);
560         */
561         bool can_match_selected = proto_can_match_selected(cap_file_->finfo_selected, cap_file_->edt);
562 //        set_menu_sensitivity(ui_manager_tree_view_menu,
563 //                             "/TreeViewPopup/GotoCorrespondingPacket", hfinfo->type == FT_FRAMENUM);
564 //        set_menu_sensitivity(ui_manager_tree_view_menu, "/TreeViewPopup/Copy",
565 //                             TRUE);
566
567 //        set_menu_sensitivity(ui_manager_tree_view_menu, "/TreeViewPopup/ApplyasColumn",
568 //                             hfinfo->type != FT_NONE);
569 //        set_menu_sensitivity(ui_manager_tree_view_menu, "/TreeViewPopup/ColorizewithFilter",
570 //                             proto_can_match_selected(cf->finfo_selected, cf->edt));
571 //        set_menu_sensitivity(ui_manager_tree_view_menu, "/TreeViewPopup/ProtocolPreferences",
572 //                             properties);
573 //        set_menu_sensitivity(ui_manager_tree_view_menu, "/TreeViewPopup/DisableProtocol",
574 //                             (id == -1) ? FALSE : proto_can_toggle_protocol(id));
575 //        set_menu_sensitivity(ui_manager_tree_view_menu, "/TreeViewPopup/ExpandSubtrees",
576 //                             cf->finfo_selected->tree_type != -1);
577 //        set_menu_sensitivity(ui_manager_tree_view_menu, "/TreeViewPopup/WikiProtocolPage",
578 //                             (id == -1) ? FALSE : TRUE);
579 //        set_menu_sensitivity(ui_manager_tree_view_menu, "/TreeViewPopup/FilterFieldReference",
580 //                             (id == -1) ? FALSE : TRUE);
581 //        set_menu_sensitivity(ui_manager_main_menubar,
582         main_ui_->actionFileExportPacketBytes->setEnabled(true);
583
584 //        set_menu_sensitivity(ui_manager_main_menubar,
585 //                             "/Menubar/GoMenu/GotoCorrespondingPacket", hfinfo->type == FT_FRAMENUM);
586
587         main_ui_->actionEditCopyDescription->setEnabled(can_match_selected);
588         main_ui_->actionEditCopyFieldName->setEnabled(can_match_selected);
589         main_ui_->actionEditCopyValue->setEnabled(can_match_selected);
590         main_ui_->actionEditCopyAsFilter->setEnabled(can_match_selected);
591 //        set_menu_sensitivity(ui_manager_main_menubar, "/Menubar/EditMenu/Copy/Description",
592 //                             proto_can_match_selected(cf->finfo_selected, cf->edt));
593 //        set_menu_sensitivity(ui_manager_main_menubar, "/Menubar/EditMenu/Copy/Fieldname",
594 //                             proto_can_match_selected(cf->finfo_selected, cf->edt));
595 //        set_menu_sensitivity(ui_manager_main_menubar, "/Menubar/EditMenu/Copy/Value",
596 //                             proto_can_match_selected(cf->finfo_selected, cf->edt));
597 //        set_menu_sensitivity(ui_manager_main_menubar, "/Menubar/EditMenu/Copy/AsFilter",
598 //                             proto_can_match_selected(cf->finfo_selected, cf->edt));
599
600 //        set_menu_sensitivity(ui_manager_main_menubar, "/Menubar/AnalyzeMenu/ApplyasColumn",
601 //                             hfinfo->type != FT_NONE);
602         main_ui_->actionAnalyzeAAFSelected->setEnabled(can_match_selected);
603         main_ui_->actionAnalyzeAAFNotSelected->setEnabled(can_match_selected);
604         main_ui_->actionAnalyzeAAFAndSelected->setEnabled(can_match_selected);
605         main_ui_->actionAnalyzeAAFOrSelected->setEnabled(can_match_selected);
606         main_ui_->actionAnalyzeAAFAndNotSelected->setEnabled(can_match_selected);
607         main_ui_->actionAnalyzeAAFOrNotSelected->setEnabled(can_match_selected);
608
609         main_ui_->actionAnalyzePAFSelected->setEnabled(can_match_selected);
610         main_ui_->actionAnalyzePAFNotSelected->setEnabled(can_match_selected);
611         main_ui_->actionAnalyzePAFAndSelected->setEnabled(can_match_selected);
612         main_ui_->actionAnalyzePAFOrSelected->setEnabled(can_match_selected);
613         main_ui_->actionAnalyzePAFAndNotSelected->setEnabled(can_match_selected);
614         main_ui_->actionAnalyzePAFOrNotSelected->setEnabled(can_match_selected);
615
616         main_ui_->actionViewExpandSubtrees->setEnabled(cap_file_->finfo_selected->tree_type != -1);
617 //        prev_abbrev = g_object_get_data(G_OBJECT(ui_manager_tree_view_menu), "menu_abbrev");
618 //        if (!prev_abbrev || (strcmp (prev_abbrev, abbrev) != 0)) {
619 //            /* No previous protocol or protocol changed - update Protocol Preferences menu */
620 //            module_t *prefs_module_p = prefs_find_module(abbrev);
621 //            rebuild_protocol_prefs_menu (prefs_module_p, properties);
622
623 //            g_object_set_data(G_OBJECT(ui_manager_tree_view_menu), "menu_abbrev", g_strdup(abbrev));
624 //            g_free (prev_abbrev);
625 //        }
626     } else {
627 //        set_menu_sensitivity(ui_manager_tree_view_menu,
628 //                             "/TreeViewPopup/GotoCorrespondingPacket", FALSE);
629 //        set_menu_sensitivity(ui_manager_tree_view_menu, "/TreeViewPopup/Copy", FALSE);
630 //        set_menu_sensitivity(ui_manager_tree_view_menu, "/TreeViewPopup/ApplyasColumn", FALSE);
631 //        set_menu_sensitivity(ui_manager_tree_view_menu, "/TreeViewPopup/ApplyAsFilter", FALSE);
632 //        set_menu_sensitivity(ui_manager_tree_view_menu, "/TreeViewPopup/PrepareaFilter", FALSE);
633 //        set_menu_sensitivity(ui_manager_tree_view_menu, "/TreeViewPopup/ColorizewithFilter", FALSE);
634 //        set_menu_sensitivity(ui_manager_tree_view_menu, "/TreeViewPopup/ProtocolPreferences",
635 //                             FALSE);
636 //        set_menu_sensitivity(ui_manager_tree_view_menu, "/TreeViewPopup/DisableProtocol", FALSE);
637 //        set_menu_sensitivity(ui_manager_tree_view_menu, "/TreeViewPopup/ExpandSubtrees", FALSE);
638 //        set_menu_sensitivity(ui_manager_tree_view_menu, "/TreeViewPopup/WikiProtocolPage",
639 //                             FALSE);
640 //        set_menu_sensitivity(ui_manager_tree_view_menu, "/TreeViewPopup/FilterFieldReference",
641 //                             FALSE);
642         main_ui_->actionFileExportPacketBytes->setEnabled(false);
643 //        set_menu_sensitivity(ui_manager_main_menubar,
644 //                             "/Menubar/GoMenu/GotoCorrespondingPacket", FALSE);
645         main_ui_->actionEditCopyDescription->setEnabled(false);
646         main_ui_->actionEditCopyFieldName->setEnabled(false);
647         main_ui_->actionEditCopyValue->setEnabled(false);
648         main_ui_->actionEditCopyAsFilter->setEnabled(false);
649 //        set_menu_sensitivity(ui_manager_main_menubar, "/Menubar/AnalyzeMenu/ApplyasColumn", FALSE);
650
651         main_ui_->actionAnalyzeAAFSelected->setEnabled(false);
652         main_ui_->actionAnalyzeAAFNotSelected->setEnabled(false);
653         main_ui_->actionAnalyzeAAFAndSelected->setEnabled(false);
654         main_ui_->actionAnalyzeAAFOrSelected->setEnabled(false);
655         main_ui_->actionAnalyzeAAFAndNotSelected->setEnabled(false);
656         main_ui_->actionAnalyzeAAFOrNotSelected->setEnabled(false);
657
658         main_ui_->actionAnalyzePAFSelected->setEnabled(false);
659         main_ui_->actionAnalyzePAFNotSelected->setEnabled(false);
660         main_ui_->actionAnalyzePAFAndSelected->setEnabled(false);
661         main_ui_->actionAnalyzePAFOrSelected->setEnabled(false);
662         main_ui_->actionAnalyzePAFAndNotSelected->setEnabled(false);
663         main_ui_->actionAnalyzePAFOrNotSelected->setEnabled(false);
664
665         main_ui_->actionViewExpandSubtrees->setEnabled(false);
666     }
667 }
668
669 void MainWindow::interfaceSelectionChanged()
670 {
671     if (global_capture_opts.num_selected > 0) {
672         main_ui_->actionStartCapture->setEnabled(true);
673     } else {
674         main_ui_->actionStartCapture->setEnabled(false);
675     }
676 }
677
678
679 // File Menu
680
681 void MainWindow::on_actionFileOpen_triggered()
682 {
683     openCaptureFile();
684 }
685
686 void MainWindow::on_actionFileMerge_triggered()
687 {
688     mergeCaptureFile();
689 }
690
691 void MainWindow::on_actionFileImport_triggered()
692 {
693     importCaptureFile();
694 }
695
696 void MainWindow::on_actionFileClose_triggered() {
697     if (testCaptureFileClose())
698         main_ui_->mainStack->setCurrentWidget(main_welcome_);
699 }
700
701 void MainWindow::on_actionFileSave_triggered()
702 {
703     saveCaptureFile(cap_file_, FALSE);
704 }
705
706 void MainWindow::on_actionFileSaveAs_triggered()
707 {
708     saveAsCaptureFile(cap_file_, FALSE, TRUE);
709 }
710
711 void MainWindow::on_actionFileSetListFiles_triggered()
712 {
713     file_set_dialog_.exec();
714 }
715
716 void MainWindow::on_actionFileSetNextFile_triggered()
717 {
718     fileset_entry *entry = fileset_get_next();
719
720     if (entry) {
721         QString new_cf_path = entry->fullname;
722         openCaptureFile(new_cf_path);
723     }
724 }
725
726 void MainWindow::on_actionFileSetPreviousFile_triggered()
727 {
728     fileset_entry *entry = fileset_get_previous();
729
730     if (entry) {
731         QString new_cf_path = entry->fullname;
732         openCaptureFile(new_cf_path);
733     }
734 }
735
736 void MainWindow::on_actionFileExportPackets_triggered()
737 {
738     exportSelectedPackets();
739 }
740
741 void MainWindow::on_actionFileExportAsPlainText_triggered()
742 {
743     exportDissections(export_type_text);
744 }
745
746 void MainWindow::on_actionFileExportAsCSV_triggered()
747 {
748     exportDissections(export_type_csv);
749 }
750
751 void MainWindow::on_actionFileExportAsCArrays_triggered()
752 {
753     exportDissections(export_type_carrays);
754 }
755
756 void MainWindow::on_actionFileExportAsPSML_triggered()
757 {
758     exportDissections(export_type_psml);
759 }
760
761 void MainWindow::on_actionFileExportAsPDML_triggered()
762 {
763     exportDissections(export_type_pdml);
764 }
765
766 void MainWindow::on_actionFileExportPacketBytes_triggered()
767 {
768     QString file_name;
769
770     if (!cap_file_ || !cap_file_->finfo_selected) return;
771
772     file_name = QFileDialog::getSaveFileName(this,
773                                              tr("Wireshark: Export Selected Packet Bytes"),
774                                              wsApp->lastOpenDir().canonicalPath(),
775                                              tr("Raw data (*.bin *.dat *.raw);;Any File (*.*)")
776                                              );
777
778     if (file_name.length() > 0) {
779         const guint8 *data_p;
780         int fd;
781
782         data_p = tvb_get_ptr(cap_file_->finfo_selected->ds_tvb, 0, -1) +
783                 cap_file_->finfo_selected->start;
784         fd = ws_open(file_name.toUtf8().constData(), O_WRONLY|O_CREAT|O_TRUNC|O_BINARY, 0666);
785         if (fd == -1) {
786             open_failure_alert_box(file_name.toUtf8().constData(), errno, TRUE);
787             return;
788         }
789         if (write(fd, data_p, cfile.finfo_selected->length) < 0) {
790             write_failure_alert_box(file_name.toUtf8().constData(), errno);
791             ::close(fd);
792             return;
793         }
794         if (::close(fd) < 0) {
795             write_failure_alert_box(file_name.toUtf8().constData(), errno);
796             return;
797         }
798
799         /* Save the directory name for future file dialogs. */
800         wsApp->setLastOpenDir(&file_name);
801     }
802 }
803
804 void MainWindow::on_actionFileExportSSLSessionKeys_triggered()
805 {
806     QString file_name;
807     QString save_title;
808     int keylist_len;
809
810     keylist_len = ssl_session_key_count();
811     /* don't show up the dialog, if no data has to be saved */
812     if (keylist_len < 1) {
813         /* shouldn't happen as the menu item should have been greyed out */
814         QMessageBox::warning(
815                     this,
816                     tr("No Keys"),
817                     tr("There are no SSL Session Keys to save."),
818                     QMessageBox::Ok
819                     );
820         return;
821     }
822
823     save_title.append("Wireshark: Export SSL Session Keys (%1 key%2").
824             arg(keylist_len).arg(plurality(keylist_len, "", "s"));
825     file_name = QFileDialog::getSaveFileName(this,
826                                              save_title,
827                                              wsApp->lastOpenDir().canonicalPath(),
828                                              tr("SSL Session Keys (*.keys *.txt);;Any File (*.*)")
829                                              );
830     if (file_name.length() > 0) {
831         gchar *keylist;
832         int fd;
833
834         keylist = ssl_export_sessions();
835         fd = ws_open(file_name.toUtf8().constData(), O_WRONLY|O_CREAT|O_TRUNC|O_BINARY, 0666);
836         if (fd == -1) {
837             open_failure_alert_box(file_name.toUtf8().constData(), errno, TRUE);
838             g_free(keylist);
839             return;
840         }
841         /*
842          * Thanks, Microsoft, for not using size_t for the third argument to
843          * _write().  Presumably this string will be <= 4GiB long....
844          */
845         if (ws_write(fd, keylist, (unsigned int)strlen(keylist)) < 0) {
846             write_failure_alert_box(file_name.toUtf8().constData(), errno);
847             ::close(fd);
848             g_free(keylist);
849             return;
850         }
851         if (::close(fd) < 0) {
852             write_failure_alert_box(file_name.toUtf8().constData(), errno);
853             g_free(keylist);
854             return;
855         }
856
857         /* Save the directory name for future file dialogs. */
858         wsApp->setLastOpenDir(&file_name);
859         g_free(keylist);
860     }
861 }
862
863 void MainWindow::on_actionFileExportObjectsDICOM_triggered()
864 {
865     new ExportObjectDialog(this, cap_file_, ExportObjectDialog::Dicom);
866 }
867
868 void MainWindow::on_actionFileExportObjectsHTTP_triggered()
869 {
870     new ExportObjectDialog(this, cap_file_, ExportObjectDialog::Http);
871 }
872
873 void MainWindow::on_actionFileExportObjectsSMB_triggered()
874 {
875     new ExportObjectDialog(this, cap_file_, ExportObjectDialog::Smb);
876 }
877
878 void MainWindow::on_actionFilePrint_triggered()
879 {
880     PrintDialog pdlg(this, cap_file_);
881
882     pdlg.exec();
883 }
884
885 // Edit Menu
886
887 // XXX This should probably be somewhere else.
888 void MainWindow::actionEditCopyTriggered(MainWindow::CopySelected selection_type)
889 {
890     char label_str[ITEM_LABEL_LENGTH];
891     QString clip;
892
893     if (!cap_file_) return;
894
895     switch(selection_type) {
896     case CopySelectedDescription:
897         if (cap_file_->finfo_selected->rep &&
898                 strlen (cap_file_->finfo_selected->rep->representation) > 0) {
899             clip.append(cap_file_->finfo_selected->rep->representation);
900         }
901         break;
902     case CopySelectedFieldName:
903         if (cap_file_->finfo_selected->hfinfo->abbrev != 0) {
904             clip.append(cap_file_->finfo_selected->hfinfo->abbrev);
905         }
906         break;
907     case CopySelectedValue:
908         if (cap_file_->edt != 0) {
909             clip.append(get_node_field_value(cap_file_->finfo_selected, cap_file_->edt));
910         }
911         break;
912     }
913
914     if (clip.length() == 0) {
915         /* If no representation then... Try to read the value */
916         proto_item_fill_label(cap_file_->finfo_selected, label_str);
917         clip.append(label_str);
918     }
919
920     if (clip.length()) {
921         wsApp->clipboard()->setText(clip);
922     } else {
923         QString err = tr("Couldn't copy text. Try another item.");
924         main_ui_->statusBar->pushTemporaryStatus(err);
925     }
926 }
927
928 void MainWindow::on_actionEditCopyDescription_triggered()
929 {
930     actionEditCopyTriggered(CopySelectedDescription);
931 }
932
933 void MainWindow::on_actionEditCopyFieldName_triggered()
934 {
935     actionEditCopyTriggered(CopySelectedFieldName);
936 }
937
938 void MainWindow::on_actionEditCopyValue_triggered()
939 {
940     actionEditCopyTriggered(CopySelectedValue);
941 }
942
943 void MainWindow::on_actionEditCopyAsFilter_triggered()
944 {
945     matchSelectedFilter(MatchSelectedReplace, false, true);
946 }
947
948 // View Menu
949
950 // Expand / collapse slots in proto_tree
951
952 // Go Menu
953
954 // Analyze Menu
955
956 // XXX This should probably be somewhere else.
957 void MainWindow::matchSelectedFilter(MainWindow::MatchSelected filter_type, bool apply, bool copy_only)
958 {
959     QString field_filter;
960     QString cur_filter;
961     QString new_filter;
962
963     if (packet_list_->contextMenuActive()) {
964         field_filter = packet_list_->getFilterFromRowAndColumn();
965     } else if (cap_file_ && cap_file_->finfo_selected) {
966         field_filter = proto_construct_match_selected_string(cap_file_->finfo_selected,
967                                                        cap_file_->edt);
968     } else {
969         return;
970     }
971
972     if (field_filter.isEmpty()) {
973         QString err = tr("No filter available. Try another ");
974         err.append(packet_list_->contextMenuActive() ? "column" : "item");
975         err.append(".");
976         main_ui_->statusBar->pushTemporaryStatus(err);
977         return;
978     }
979
980     if (!df_combo_box_) return;
981
982     cur_filter = df_combo_box_->lineEdit()->text();
983
984     switch (filter_type) {
985     case MatchSelectedReplace:
986         new_filter = field_filter;
987         break;
988     case MatchSelectedAnd:
989         if (cur_filter.length()) {
990             new_filter = "(" + cur_filter + ") && (" + field_filter + ")";
991         } else {
992             new_filter = field_filter;
993         }
994         break;
995     case MatchSelectedOr:
996         if (cur_filter.length()) {
997             new_filter = "(" + cur_filter + ") || (" + field_filter + ")";
998         } else {
999             new_filter = field_filter;
1000         }
1001         break;
1002     case MatchSelectedNot:
1003         new_filter = "!(" + field_filter + ")";
1004         break;
1005     case MatchSelectedAndNot:
1006         if (cur_filter.length()) {
1007             new_filter = "(" + cur_filter + ") && !(" + field_filter + ")";
1008         } else {
1009             new_filter = "!(" + field_filter + ")";
1010         }
1011         break;
1012     case MatchSelectedOrNot:
1013         if (cur_filter.length()) {
1014             new_filter = "(" + cur_filter + ") || !(" + field_filter + ")";
1015         } else {
1016             new_filter = "!(" + field_filter + ")";
1017         }
1018         break;
1019     default:
1020         g_assert_not_reached();
1021         break;
1022     }
1023
1024     if (copy_only) {
1025         wsApp->clipboard()->setText(new_filter);
1026     } else {
1027         df_combo_box_->lineEdit()->setText(new_filter);
1028         if (apply) {
1029             df_combo_box_->applyDisplayFilter();
1030         } else {
1031             df_combo_box_->lineEdit()->setFocus();
1032         }
1033     }
1034
1035 }
1036
1037 void MainWindow::on_actionAnalyzeAAFSelected_triggered()
1038 {
1039     matchSelectedFilter(MatchSelectedReplace, true, false);
1040 }
1041
1042 void MainWindow::on_actionAnalyzeAAFNotSelected_triggered()
1043 {
1044     matchSelectedFilter(MatchSelectedNot, true, false);
1045 }
1046
1047 void MainWindow::on_actionAnalyzeAAFAndSelected_triggered()
1048 {
1049     matchSelectedFilter(MatchSelectedAnd, true, false);
1050 }
1051
1052 void MainWindow::on_actionAnalyzeAAFOrSelected_triggered()
1053 {
1054     matchSelectedFilter(MatchSelectedOr, true, false);
1055 }
1056
1057 void MainWindow::on_actionAnalyzeAAFAndNotSelected_triggered()
1058 {
1059     matchSelectedFilter(MatchSelectedAndNot, true, false);
1060 }
1061
1062 void MainWindow::on_actionAnalyzeAAFOrNotSelected_triggered()
1063 {
1064     matchSelectedFilter(MatchSelectedOrNot, true, false);
1065 }
1066
1067 void MainWindow::on_actionAnalyzePAFSelected_triggered()
1068 {
1069     matchSelectedFilter(MatchSelectedReplace, false, false);
1070 }
1071
1072 void MainWindow::on_actionAnalyzePAFNotSelected_triggered()
1073 {
1074     matchSelectedFilter(MatchSelectedNot, false, false);
1075 }
1076
1077 void MainWindow::on_actionAnalyzePAFAndSelected_triggered()
1078 {
1079     matchSelectedFilter(MatchSelectedAnd, false, false);
1080 }
1081
1082 void MainWindow::on_actionAnalyzePAFOrSelected_triggered()
1083 {
1084     matchSelectedFilter(MatchSelectedOr, false, false);
1085 }
1086
1087 void MainWindow::on_actionAnalyzePAFAndNotSelected_triggered()
1088 {
1089     matchSelectedFilter(MatchSelectedAndNot, false, false);
1090 }
1091
1092 void MainWindow::on_actionAnalyzePAFOrNotSelected_triggered()
1093 {
1094     matchSelectedFilter(MatchSelectedOrNot, false, false);
1095 }
1096
1097
1098 // Next / previous / first / last slots in packet_list
1099
1100 // Help Menu
1101 void MainWindow::on_actionHelpContents_triggered() {
1102
1103     wsApp->helpTopicAction(HELP_CONTENT);
1104 }
1105
1106 void MainWindow::on_actionHelpMPWireshark_triggered() {
1107
1108     wsApp->helpTopicAction(LOCALPAGE_MAN_WIRESHARK);
1109 }
1110 void MainWindow::on_actionHelpMPWireshark_Filter_triggered() {
1111
1112     wsApp->helpTopicAction(LOCALPAGE_MAN_WIRESHARK_FILTER);
1113 }
1114 void MainWindow::on_actionHelpMPTShark_triggered() {
1115
1116     wsApp->helpTopicAction(LOCALPAGE_MAN_TSHARK);
1117 }
1118 void MainWindow::on_actionHelpMPRawShark_triggered() {
1119
1120     wsApp->helpTopicAction(LOCALPAGE_MAN_RAWSHARK);
1121 }
1122 void MainWindow::on_actionHelpMPDumpcap_triggered() {
1123
1124     wsApp->helpTopicAction(LOCALPAGE_MAN_DUMPCAP);
1125 }
1126 void MainWindow::on_actionHelpMPMergecap_triggered() {
1127
1128     wsApp->helpTopicAction(LOCALPAGE_MAN_MERGECAP);
1129 }
1130 void MainWindow::on_actionHelpMPEditcap_triggered() {
1131
1132     wsApp->helpTopicAction(LOCALPAGE_MAN_EDITCAP);
1133 }
1134 void MainWindow::on_actionHelpMPText2cap_triggered() {
1135
1136     wsApp->helpTopicAction(LOCALPAGE_MAN_TEXT2PCAP);
1137 }
1138
1139 void MainWindow::on_actionHelpWebsite_triggered() {
1140
1141     wsApp->helpTopicAction(ONLINEPAGE_HOME);
1142 }
1143
1144 void MainWindow::on_actionHelpFAQ_triggered() {
1145
1146     wsApp->helpTopicAction(ONLINEPAGE_FAQ);
1147 }
1148
1149 void MainWindow::on_actionHelpAsk_triggered() {
1150
1151     wsApp->helpTopicAction(ONLINEPAGE_ASK);
1152 }
1153
1154 void MainWindow::on_actionHelpDownloads_triggered() {
1155
1156     wsApp->helpTopicAction(ONLINEPAGE_DOWNLOAD);
1157 }
1158
1159 void MainWindow::on_actionHelpWiki_triggered() {
1160
1161     wsApp->helpTopicAction(ONLINEPAGE_WIKI);
1162 }
1163
1164 void MainWindow::on_actionHelpSampleCaptures_triggered() {
1165
1166     wsApp->helpTopicAction(ONLINEPAGE_SAMPLE_FILES);
1167 }
1168
1169 void MainWindow::on_actionGoGoToPacket_triggered() {
1170     if (packet_list_->model()->rowCount() < 1) {
1171         return;
1172     }
1173     previous_focus_ = wsApp->focusWidget();
1174     connect(previous_focus_, SIGNAL(destroyed()), this, SLOT(resetPreviousFocus()));
1175     main_ui_->goToFrame->show();
1176     main_ui_->goToLineEdit->setFocus();
1177 }
1178
1179 void MainWindow::resetPreviousFocus() {
1180     previous_focus_ = NULL;
1181 }
1182
1183 void MainWindow::on_goToCancel_clicked()
1184 {
1185     main_ui_->goToFrame->hide();
1186     if (previous_focus_) {
1187         disconnect(previous_focus_, SIGNAL(destroyed()), this, SLOT(resetPreviousFocus()));
1188         previous_focus_->setFocus();
1189         resetPreviousFocus();
1190     }
1191 }
1192
1193 void MainWindow::on_goToGo_clicked()
1194 {
1195     int packet_num = main_ui_->goToLineEdit->text().toInt();
1196
1197     if (packet_num > 0) {
1198         packet_list_->goToPacket(packet_num);
1199     }
1200     on_goToCancel_clicked();
1201 }
1202
1203 void MainWindow::on_goToLineEdit_returnPressed()
1204 {
1205     on_goToGo_clicked();
1206 }
1207
1208 void MainWindow::on_actionStartCapture_triggered()
1209 {
1210 //#ifdef HAVE_AIRPCAP
1211 //  airpcap_if_active = airpcap_if_selected;
1212 //  if (airpcap_if_active)
1213 //    airpcap_set_toolbar_start_capture(airpcap_if_active);
1214 //#endif
1215
1216 //  if (cap_open_w) {
1217 //    /*
1218 //     * There's an options dialog; get the values from it and close it.
1219 //     */
1220 //    gboolean success;
1221
1222 //    /* Determine if "capture start" while building of the "capture options" window */
1223 //    /*  is in progress. If so, ignore the "capture start.                          */
1224 //    /* XXX: Would it be better/cleaner for the "capture options" window code to    */
1225 //    /*      disable the capture start button temporarily ?                         */
1226 //    if (cap_open_complete == FALSE) {
1227 //      return;  /* Building options window: ignore "capture start" */
1228 //    }
1229 //    success = capture_dlg_prep(cap_open_w);
1230 //    window_destroy(GTK_WIDGET(cap_open_w));
1231 //    if (!success)
1232 //      return;   /* error in options dialog */
1233 //  }
1234
1235     main_ui_->mainStack->setCurrentWidget(packet_splitter_);
1236
1237     if (global_capture_opts.num_selected == 0) {
1238         QString err_msg = tr("No Interface Selected");
1239         main_ui_->statusBar->pushTemporaryStatus(err_msg);
1240         return;
1241     }
1242
1243     /* XXX - will closing this remove a temporary file? */
1244     if (testCaptureFileClose(FALSE, *new QString(" before starting a new capture")))
1245         startCapture();
1246 }
1247
1248 void MainWindow::on_actionStopCapture_triggered()
1249 {
1250     stopCapture();
1251 }
1252
1253 /*
1254  * Editor modelines
1255  *
1256  * Local Variables:
1257  * c-basic-offset: 4
1258  * tab-width: 8
1259  * indent-tabs-mode: nil
1260  * End:
1261  *
1262  * ex: set shiftwidth=4 tabstop=8 expandtab:
1263  * :indentSize=4:tabSize=8:noTabs=true:
1264  */