From 4d6454e18027a7265138e16ef95b52000825aa47 Mon Sep 17 00:00:00 2001 From: Roland Knall Date: Tue, 7 Nov 2017 15:51:43 +0000 Subject: Qt: Drag n Drop Filter expression from Packet Tree Drag and Drop a field from the packet tree to the displayfilteredit or the toolbar and drop it there to either apply the filter (or prepare it by holding down the Shift key) or create a new toolbar button Change-Id: I42645a02223c71315e91e0d58eb1b54ebab4fd58 Reviewed-on: https://code.wireshark.org/review/24280 Petri-Dish: Anders Broman Reviewed-by: Roland Knall --- ui/qt/CMakeLists.txt | 4 ++ ui/qt/Makefile.am | 4 ++ ui/qt/main_window.cpp | 4 ++ ui/qt/main_window.h | 1 + ui/qt/main_window_slots.cpp | 15 +++++++ ui/qt/proto_tree.cpp | 74 ++++++++++++++++++++++++++++++++++- ui/qt/proto_tree.h | 11 ++++++ ui/qt/utils/wireshark_mime_data.cpp | 53 +++++++++++++++++++++++++ ui/qt/utils/wireshark_mime_data.h | 57 +++++++++++++++++++++++++++ ui/qt/widgets/display_filter_edit.cpp | 67 +++++++++++++++++++++++++++++-- ui/qt/widgets/display_filter_edit.h | 6 +++ ui/qt/widgets/drag_drop_toolbar.cpp | 32 +++++++++++++++ ui/qt/widgets/drag_drop_toolbar.h | 2 + ui/qt/widgets/drag_label.cpp | 53 +++++++++++++++++++++++++ ui/qt/widgets/drag_label.h | 52 ++++++++++++++++++++++++ 15 files changed, 431 insertions(+), 4 deletions(-) create mode 100644 ui/qt/utils/wireshark_mime_data.cpp create mode 100644 ui/qt/utils/wireshark_mime_data.h create mode 100644 ui/qt/widgets/drag_label.cpp create mode 100644 ui/qt/widgets/drag_label.h diff --git a/ui/qt/CMakeLists.txt b/ui/qt/CMakeLists.txt index 565fa0bee5..d6a0045ddf 100644 --- a/ui/qt/CMakeLists.txt +++ b/ui/qt/CMakeLists.txt @@ -30,6 +30,7 @@ set(WIRESHARK_WIDGET_HEADERS widgets/display_filter_combo.h widgets/display_filter_edit.h widgets/drag_drop_toolbar.h + widgets/drag_label.h widgets/editor_color_dialog.h widgets/editor_file_dialog.h widgets/elided_label.h @@ -50,6 +51,7 @@ set(WIRESHARK_UTILS_HEADERS utils/stock_icon.h utils/qt_ui_utils.h utils/tango_colors.h + utils/wireshark_mime_data.h utils/variant_pointer.h ) @@ -230,6 +232,7 @@ set(WIRESHARK_WIDGET_SRCS widgets/display_filter_combo.cpp widgets/display_filter_edit.cpp widgets/drag_drop_toolbar.cpp + widgets/drag_label.cpp widgets/editor_color_dialog.cpp widgets/editor_file_dialog.cpp widgets/elided_label.cpp @@ -248,6 +251,7 @@ set(WIRESHARK_WIDGET_SRCS set(WIRESHARK_UTILS_SRCS utils/color_utils.cpp utils/stock_icon.cpp + utils/wireshark_mime_data.cpp utils/qt_ui_utils.cpp ) diff --git a/ui/qt/Makefile.am b/ui/qt/Makefile.am index 51da3107f9..735c849a55 100644 --- a/ui/qt/Makefile.am +++ b/ui/qt/Makefile.am @@ -172,6 +172,7 @@ MOC_WIDGET_HDRS = \ widgets/stock_icon_tool_button.h \ widgets/tabnav_tree_view.h \ widgets/drag_drop_toolbar.h \ + widgets/drag_label.h \ widgets/qcustomplot.h # Files that are utility classes with multi-purpose, but no widgets @@ -179,6 +180,7 @@ MOC_UTILS_HDRS = \ utils/color_utils.h \ utils/stock_icon.h \ utils/qt_ui_utils.h \ + utils/wireshark_mime_data.h \ utils/variant_pointer.h # Files for delegates and models @@ -486,11 +488,13 @@ WIRESHARK_QT_WIDGET_SRC = \ widgets/syntax_line_edit.cpp \ widgets/tabnav_tree_view.cpp \ widgets/drag_drop_toolbar.cpp \ + widgets/drag_label.cpp \ widgets/qcustomplot.cpp WIRESHARK_QT_UTILS_SRC = \ utils/color_utils.cpp \ utils/stock_icon.cpp \ + utils/wireshark_mime_data.cpp \ utils/qt_ui_utils.cpp WIRESHARK_QT_MODELS_SRCS = \ diff --git a/ui/qt/main_window.cpp b/ui/qt/main_window.cpp index bbaced0077..9e06490ed9 100644 --- a/ui/qt/main_window.cpp +++ b/ui/qt/main_window.cpp @@ -420,6 +420,8 @@ MainWindow::MainWindow(QWidget *parent) : this, SLOT(filterToolbarCustomMenuHandler(QPoint))); connect(filter_expression_toolbar_, SIGNAL(actionMoved(QAction*, int, int)), this, SLOT(filterToolbarActionMoved(QAction*, int, int))); + connect(filter_expression_toolbar_, SIGNAL(newFilterDropped(QString, QString)), + this, SLOT(filterDropped(QString, QString))); main_ui_->displayFilterToolBar->addWidget(filter_expression_toolbar_); @@ -652,6 +654,8 @@ MainWindow::MainWindow(QWidget *parent) : main_ui_->statusBar, SLOT(setCaptureFile(capture_file*))); connect(this, SIGNAL(setCaptureFile(capture_file*)), packet_list_, SLOT(setCaptureFile(capture_file*))); + connect(this, SIGNAL(setCaptureFile(capture_file*)), + proto_tree_, SLOT(setCaptureFile(capture_file*))); connect(this, SIGNAL(setCaptureFile(capture_file*)), byte_view_tab_, SLOT(setCaptureFile(capture_file*))); diff --git a/ui/qt/main_window.h b/ui/qt/main_window.h index 74f95da95f..1f92b00a13 100644 --- a/ui/qt/main_window.h +++ b/ui/qt/main_window.h @@ -367,6 +367,7 @@ private slots: void filterToolbarDisableFilter(); void filterToolbarRemoveFilter(); void filterToolbarActionMoved(QAction * action, int oldPos, int newPos); + void filterDropped(QString description, QString filter); void startInterfaceCapture(bool valid, const QString capture_filter); diff --git a/ui/qt/main_window_slots.cpp b/ui/qt/main_window_slots.cpp index 2cced5b4c3..ee25e61e58 100644 --- a/ui/qt/main_window_slots.cpp +++ b/ui/qt/main_window_slots.cpp @@ -4074,6 +4074,21 @@ void MainWindow::filterToolbarEditFilter() delete uatModel; } +void MainWindow::filterDropped(QString description, QString filter) +{ + gchar* err = NULL; + if ( filter.length() == 0 ) + return; + + filter_expression_new(description.toUtf8().constData(), + filter.toUtf8().constData(), description.toUtf8().constData(), TRUE); + + uat_save(uat_get_table_by_name("Display expressions"), &err); + g_free(err); + + filterExpressionsChanged(); +} + void MainWindow::filterToolbarDisableFilter() { gchar* err = NULL; diff --git a/ui/qt/proto_tree.cpp b/ui/qt/proto_tree.cpp index 32c104a724..f64ac911e7 100644 --- a/ui/qt/proto_tree.cpp +++ b/ui/qt/proto_tree.cpp @@ -27,8 +27,9 @@ #include #include - #include +#include +#include #include #include @@ -38,6 +39,11 @@ #include #include +#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0) +#include +#endif + + // To do: // - Fix "apply as filter" behavior. @@ -286,6 +292,8 @@ ProtoTree::ProtoTree(QWidget *parent) : // have scrolled to an area with a different width at this point. connect(verticalScrollBar(), SIGNAL(sliderReleased()), this, SLOT(updateContentWidth())); + + viewport()->installEventFilter(this); } void ProtoTree::closeContextMenu() @@ -690,6 +698,70 @@ void ProtoTree::restoreSelectedField() } } +void ProtoTree::setCaptureFile(capture_file *cf) +{ + cap_file_ = cf; +} + +bool ProtoTree::eventFilter(QObject * obj, QEvent * event) +{ + if ( cap_file_ && event->type() != QEvent::MouseButtonPress && event->type() != QEvent::MouseMove ) + return QTreeWidget::eventFilter(obj, event); + + QMouseEvent * ev = (QMouseEvent *)event; + + if ( event->type() == QEvent::MouseButtonPress ) + { + if ( ev->buttons() & Qt::LeftButton ) + { + dragStartPosition = ev->pos(); + } + } + else if ( event->type() == QEvent::MouseMove ) + { + if ( ( ev->buttons() & Qt::LeftButton ) && (ev->pos() - dragStartPosition).manhattanLength() + > QApplication::startDragDistance()) + { + QTreeWidgetItem * item = itemAt(dragStartPosition); + if ( item ) + { + field_info * fi = VariantPointer::asPtr(item->data(0, Qt::UserRole)); + if ( fi ) + { + QString description = QString(fi->hfinfo->name); + QString filter = QString(proto_construct_match_selected_string(fi, cap_file_->edt)); + + if ( filter.length() > 0 ) + { + QDrag * drag = new QDrag(this); + drag->setMimeData(new DisplayFilterMimeData(description, filter)); + + QString cmt = QString("%1 - ( %2 )").arg(description, filter); + DragLabel * content = new DragLabel(cmt, this); + + #if QT_VERSION >= QT_VERSION_CHECK(5, 1, 0) + qreal dpr = window()->windowHandle()->devicePixelRatio(); + QPixmap pixmap(content->size() * dpr); + pixmap.setDevicePixelRatio(dpr); + #else + QPixmap pixmap(content->size()); + #endif + content->render(&pixmap); + drag->setPixmap(pixmap); + + drag->exec(Qt::CopyAction); + + return true; + } + } + } + } + } + + return QTreeWidget::eventFilter(obj, event); +} + + /* * Editor modelines * diff --git a/ui/qt/proto_tree.h b/ui/qt/proto_tree.h index a27aab5faa..cf9c85369a 100644 --- a/ui/qt/proto_tree.h +++ b/ui/qt/proto_tree.h @@ -26,6 +26,8 @@ #include +#include "cfile.h" + #include "protocol_preferences_menu.h" #include @@ -51,6 +53,8 @@ protected: virtual void timerEvent(QTimerEvent *event); virtual void keyReleaseEvent(QKeyEvent *event); + virtual bool eventFilter(QObject * obj, QEvent * ev); + private: QMenu ctx_menu_; QMenu conv_menu_; @@ -62,6 +66,10 @@ private: int column_resize_timer_; QList selected_field_path_; + QPoint dragStartPosition; + + capture_file *cap_file_; + signals: void protoItemSelected(const QString &); void protoItemSelected(field_info *); @@ -72,6 +80,9 @@ signals: void editProtocolPreference(struct preference *pref, struct pref_module *module); public slots: + + /* Set the capture file */ + void setCaptureFile(capture_file *cf); void setMonospaceFont(const QFont &mono_font); void updateSelectionStatus(QTreeWidgetItem*); void expand(const QModelIndex & index); diff --git a/ui/qt/utils/wireshark_mime_data.cpp b/ui/qt/utils/wireshark_mime_data.cpp new file mode 100644 index 0000000000..7844ee3fd2 --- /dev/null +++ b/ui/qt/utils/wireshark_mime_data.cpp @@ -0,0 +1,53 @@ +/* wireshark_mime_data.cpp + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include + +DisplayFilterMimeData::DisplayFilterMimeData(QString description, QString filter) : +QMimeData(), +description_(description), +filter_(filter) +{ +} + +QString DisplayFilterMimeData::description() const +{ + return description_; +} + +QString DisplayFilterMimeData::filter() const +{ + return filter_; +} + +/* + * Editor modelines + * + * Local Variables: + * c-basic-offset: 4 + * tab-width: 8 + * indent-tabs-mode: nil + * End: + * + * ex: set shiftwidth=4 tabstop=8 expandtab: + * :indentSize=4:tabSize=8:noTabs=true: + */ + diff --git a/ui/qt/utils/wireshark_mime_data.h b/ui/qt/utils/wireshark_mime_data.h new file mode 100644 index 0000000000..d2b4c79e82 --- /dev/null +++ b/ui/qt/utils/wireshark_mime_data.h @@ -0,0 +1,57 @@ +/* wireshark_mime_data.h + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef UI_QT_UTILS_WIRESHARK_MIME_DATA_H_ +#define UI_QT_UTILS_WIRESHARK_MIME_DATA_H_ + +#include + +class DisplayFilterMimeData: public QMimeData { + Q_OBJECT +public: + + DisplayFilterMimeData(QString description, QString filter); + + QString description() const; + QString filter() const; + +private: + + QString description_; + QString filter_; + +}; + +#endif /* UI_QT_UTILS_WIRESHARK_MIME_DATA_H_ */ + +/* + * Editor modelines + * + * Local Variables: + * c-basic-offset: 4 + * tab-width: 8 + * indent-tabs-mode: nil + * End: + * + * ex: set shiftwidth=4 tabstop=8 expandtab: + * :indentSize=4:tabSize=8:noTabs=true: + */ + diff --git a/ui/qt/widgets/display_filter_edit.cpp b/ui/qt/widgets/display_filter_edit.cpp index 47abe3fefe..df5d1b0709 100644 --- a/ui/qt/widgets/display_filter_edit.cpp +++ b/ui/qt/widgets/display_filter_edit.cpp @@ -33,18 +33,21 @@ #include "filter_dialog.h" #include #include +#include #include #include #include #include -#include #include #include #include #include - -#include +#include +#include +#include +#include +#include // To do: // - Get rid of shortcuts and replace them with "n most recently applied filters"? @@ -164,6 +167,7 @@ DisplayFilterEdit::DisplayFilterEdit(QWidget *parent, DisplayFilterEditType type connect(wsApp, SIGNAL(appInitialized()), this, SLOT(updateBookmarkMenu())); connect(wsApp, SIGNAL(displayFilterListChanged()), this, SLOT(updateBookmarkMenu())); + } void DisplayFilterEdit::setDefaultPlaceholderText() @@ -531,6 +535,63 @@ void DisplayFilterEdit::applyOrPrepareFilter() } } +void DisplayFilterEdit::dragEnterEvent(QDragEnterEvent *event) +{ + if (event && qobject_cast(event->mimeData())) { + if ( event->source() != this ) + { + event->setDropAction(Qt::CopyAction); + event->accept(); + } else { + event->acceptProposedAction(); + } + } else { + event->ignore(); + } +} + +void DisplayFilterEdit::dragMoveEvent(QDragMoveEvent *event) +{ + if (event && qobject_cast(event->mimeData())) { + if ( event->source() != this ) + { + event->setDropAction(Qt::CopyAction); + event->accept(); + } else { + event->acceptProposedAction(); + } + } else { + event->ignore(); + } +} + +void DisplayFilterEdit::dropEvent(QDropEvent *event) +{ + /* Moving items around */ + if (event && qobject_cast(event->mimeData())) { + const DisplayFilterMimeData * data = qobject_cast(event->mimeData()); + + if ( event->source() != this ) + { + event->setDropAction(Qt::CopyAction); + event->accept(); + + setText(data->filter()); + + // Holding down the Shift key will only prepare filter. + if (!(QApplication::keyboardModifiers() & Qt::ShiftModifier)) { + applyDisplayFilter(); + } + + } else { + event->acceptProposedAction(); + } + + } else { + event->ignore(); + } +} + /* * Editor modelines * diff --git a/ui/qt/widgets/display_filter_edit.h b/ui/qt/widgets/display_filter_edit.h index a7e57107d5..84c6307fd4 100644 --- a/ui/qt/widgets/display_filter_edit.h +++ b/ui/qt/widgets/display_filter_edit.h @@ -22,6 +22,8 @@ #ifndef DISPLAYFILTEREDIT_H #define DISPLAYFILTEREDIT_H +#include + #include #include @@ -47,6 +49,10 @@ protected: void focusInEvent(QFocusEvent *event) { completionFocusInEvent(event); } void focusOutEvent(QFocusEvent *event); + virtual void dragEnterEvent(QDragEnterEvent *event); + virtual void dragMoveEvent(QDragMoveEvent *event); + virtual void dropEvent(QDropEvent *event); + public slots: bool checkFilter(); void updateBookmarkMenu(); diff --git a/ui/qt/widgets/drag_drop_toolbar.cpp b/ui/qt/widgets/drag_drop_toolbar.cpp index 3ebfbcecc5..aa2f0f9aeb 100644 --- a/ui/qt/widgets/drag_drop_toolbar.cpp +++ b/ui/qt/widgets/drag_drop_toolbar.cpp @@ -20,6 +20,7 @@ */ #include +#include #include #include @@ -141,6 +142,14 @@ void DragDropToolBar::dragEnterEvent(QDragEnterEvent *event) } else { event->acceptProposedAction(); } + } else if (qobject_cast(event->mimeData())) { + if ( event->source() != this ) + { + event->setDropAction(Qt::CopyAction); + event->accept(); + } else { + event->acceptProposedAction(); + } } else { event->ignore(); } @@ -167,6 +176,14 @@ void DragDropToolBar::dragMoveEvent(QDragMoveEvent *event) widgetForAction(action)->setStyleSheet("QWidget { border: 2px dotted grey; };"); } } + } else if (qobject_cast(event->mimeData())) { + if ( event->source() != this ) + { + event->setDropAction(Qt::CopyAction); + event->accept(); + } else { + event->acceptProposedAction(); + } } else { event->ignore(); } @@ -174,6 +191,7 @@ void DragDropToolBar::dragMoveEvent(QDragMoveEvent *event) void DragDropToolBar::dropEvent(QDropEvent *event) { + /* Moving items around */ if (event->mimeData()->hasFormat("application/x-wireshark-toolbar-entry")) { int oldPos = event->mimeData()->data("application/x-wireshark-toolbar-entry").toInt(); @@ -194,6 +212,20 @@ void DragDropToolBar::dropEvent(QDropEvent *event) event->acceptProposedAction(); } + } else if (qobject_cast(event->mimeData())) { + const DisplayFilterMimeData * data = qobject_cast(event->mimeData()); + + if ( event->source() != this ) + { + event->setDropAction(Qt::CopyAction); + event->accept(); + + emit newFilterDropped(data->description(), data->filter()); + + } else { + event->acceptProposedAction(); + } + } else { event->ignore(); } diff --git a/ui/qt/widgets/drag_drop_toolbar.h b/ui/qt/widgets/drag_drop_toolbar.h index 73e93384a1..3958a0ca33 100644 --- a/ui/qt/widgets/drag_drop_toolbar.h +++ b/ui/qt/widgets/drag_drop_toolbar.h @@ -37,6 +37,8 @@ public: Q_SIGNALS: void actionMoved(QAction * action, int oldPos, int newPos); + void newFilterDropped(QString description, QString filter); + protected: virtual void childEvent(QChildEvent * event); diff --git a/ui/qt/widgets/drag_label.cpp b/ui/qt/widgets/drag_label.cpp new file mode 100644 index 0000000000..1665995692 --- /dev/null +++ b/ui/qt/widgets/drag_label.cpp @@ -0,0 +1,53 @@ +/* drag_label.cpp + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include + +#include + +DragLabel::DragLabel(QString txt, QWidget * parent) +: QLabel(txt, parent) +{ + setAutoFillBackground(true); + setFrameShape(QFrame::Panel); + setFrameShadow(QFrame::Raised); + setAttribute(Qt::WA_DeleteOnClose); + setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding); + + adjustSize(); +} + +DragLabel::~DragLabel() { + // TODO Auto-generated destructor stub +} + +/* + * Editor modelines + * + * Local Variables: + * c-basic-offset: 4 + * tab-width: 8 + * indent-tabs-mode: nil + * End: + * + * ex: set shiftwidth=4 tabstop=8 expandtab: + * :indentSize=4:tabSize=8:noTabs=true: + */ diff --git a/ui/qt/widgets/drag_label.h b/ui/qt/widgets/drag_label.h new file mode 100644 index 0000000000..50618f1579 --- /dev/null +++ b/ui/qt/widgets/drag_label.h @@ -0,0 +1,52 @@ +/* drag_label.h + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef UI_QT_WIDGETS_DRAG_LABEL_H_ +#define UI_QT_WIDGETS_DRAG_LABEL_H_ + +#include +#include +#include +#include + +class DragLabel: public QLabel +{ + Q_OBJECT + +public: + explicit DragLabel(QString text, QWidget * parent = 0); + virtual ~DragLabel(); +}; + +#endif /* UI_QT_WIDGETS_DRAG_LABEL_H_ */ + +/* + * Editor modelines + * + * Local Variables: + * c-basic-offset: 4 + * tab-width: 8 + * indent-tabs-mode: nil + * End: + * + * ex: set shiftwidth=4 tabstop=8 expandtab: + * :indentSize=4:tabSize=8:noTabs=true: + */ -- cgit v1.2.3