update epan/dissectors/pidl/drsuapi/drsuapi.idl from samba
[wireshark-sm.git] / ui / qt / bluetooth_att_server_attributes_dialog.cpp
blobf8f20a9243dabcde5ccd35491740d3d0a78b11ed
1 /* bluetooth_att_server_attributes_dialog.cpp
3 * Wireshark - Network traffic analyzer
4 * By Gerald Combs <gerald@wireshark.org>
5 * Copyright 1998 Gerald Combs
7 * SPDX-License-Identifier: GPL-2.0-or-later
8 */
10 #include "bluetooth_att_server_attributes_dialog.h"
11 #include <ui_bluetooth_att_server_attributes_dialog.h>
13 #include <ui/qt/utils/color_utils.h>
15 #include "epan/epan.h"
16 #include "epan/to_str.h"
17 #include "epan/epan_dissect.h"
18 #include "epan/prefs.h"
19 #include "epan/dissectors/packet-bluetooth.h"
20 #include "epan/dissectors/packet-btatt.h"
22 #include "ui/simple_dialog.h"
24 #include "ui/qt/widgets/wireshark_file_dialog.h"
26 #include <QClipboard>
27 #include <QContextMenuEvent>
28 #include <QPushButton>
29 #include <QTreeWidget>
31 static const int column_number_handle = 0;
32 static const int column_number_uuid = 1;
33 static const int column_number_uuid_name = 2;
35 static tap_packet_status
36 btatt_handle_tap_packet(void *tapinfo_ptr, packet_info *pinfo, epan_dissect_t *edt, const void* data, tap_flags_t flags)
38 tapinfo_t *tapinfo = (tapinfo_t *) tapinfo_ptr;
40 if (tapinfo->tap_packet)
41 tapinfo->tap_packet(tapinfo, pinfo, edt, data, flags);
43 return TAP_PACKET_REDRAW;
46 static void
47 btatt_handle_tap_reset(void *tapinfo_ptr)
49 tapinfo_t *tapinfo = (tapinfo_t *) tapinfo_ptr;
51 if (tapinfo->tap_reset)
52 tapinfo->tap_reset(tapinfo);
55 static QTreeWidgetItem *
56 item_with_handle_get(QTreeWidget *tableTree, uint16_t handle)
58 QTreeWidgetItemIterator i_item(tableTree);
60 while (*i_item) {
61 QTreeWidgetItem *item = static_cast<QTreeWidgetItem*>(*i_item);
63 if (item->data(1, Qt::UserRole).value<uint32_t>() == handle) {
64 return item;
67 ++i_item;
70 return NULL;
73 BluetoothAttServerAttributesDialog::BluetoothAttServerAttributesDialog(QWidget &parent, CaptureFile &cf) :
74 WiresharkDialog(parent, cf),
75 ui(new Ui::BluetoothAttServerAttributesDialog)
77 ui->setupUi(this);
78 loadGeometry(parent.width() * 4 / 5, parent.height() * 2 / 3);
80 connect(ui->tableTreeWidget, &QTreeWidget::customContextMenuRequested, this, &BluetoothAttServerAttributesDialog::tableContextMenu);
81 connect(ui->interfaceComboBox, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, &BluetoothAttServerAttributesDialog::interfaceCurrentIndexChanged);
82 connect(ui->deviceComboBox, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, &BluetoothAttServerAttributesDialog::deviceCurrentIndexChanged);
83 #if QT_VERSION >= QT_VERSION_CHECK(6, 7, 0)
84 connect(ui->removeDuplicatesCheckBox, &QCheckBox::checkStateChanged, this, &BluetoothAttServerAttributesDialog::removeDuplicatesStateChanged);
85 #else
86 connect(ui->removeDuplicatesCheckBox, &QCheckBox::stateChanged, this, &BluetoothAttServerAttributesDialog::removeDuplicatesStateChanged);
87 #endif
89 ui->tableTreeWidget->sortByColumn(column_number_handle, Qt::AscendingOrder);
91 ui->tableTreeWidget->setStyleSheet("QTreeView::item:hover{background-color:lightyellow; color:black;}");
93 context_menu_.addActions(QList<QAction *>() << ui->actionMark_Unmark_Cell);
94 context_menu_.addActions(QList<QAction *>() << ui->actionMark_Unmark_Row);
95 context_menu_.addActions(QList<QAction *>() << ui->actionCopy_Cell);
96 context_menu_.addActions(QList<QAction *>() << ui->actionCopy_Rows);
97 context_menu_.addActions(QList<QAction *>() << ui->actionCopy_All);
98 context_menu_.addActions(QList<QAction *>() << ui->actionSave_as_image);
100 tapinfo_.tap_packet = tapPacket;
101 tapinfo_.tap_reset = tapReset;
102 tapinfo_.ui = this;
104 registerTapListener("btatt.handles", &tapinfo_, NULL,
106 btatt_handle_tap_reset,
107 btatt_handle_tap_packet,
108 NULL
111 cap_file_.retapPackets();
115 BluetoothAttServerAttributesDialog::~BluetoothAttServerAttributesDialog()
117 delete ui;
121 void BluetoothAttServerAttributesDialog::captureFileClosed()
123 ui->interfaceComboBox->setEnabled(false);
124 ui->deviceComboBox->setEnabled(false);
125 ui->removeDuplicatesCheckBox->setEnabled(false);
127 WiresharkDialog::captureFileClosed();
131 void BluetoothAttServerAttributesDialog::changeEvent(QEvent *event)
133 if (0 != event)
135 switch (event->type())
137 case QEvent::LanguageChange:
138 ui->retranslateUi(this);
139 break;
140 default:
141 break;
144 QDialog::changeEvent(event);
148 void BluetoothAttServerAttributesDialog::keyPressEvent(QKeyEvent *event)
150 /* NOTE: Do nothing*, but in real it "takes focus" from button_box so allow user
151 * to use Enter button to jump to frame from tree widget */
152 /* * - reimplement shortcuts from contex menu */
154 if (event->modifiers() & Qt::ControlModifier && event->key()== Qt::Key_M)
155 on_actionMark_Unmark_Row_triggered();
159 void BluetoothAttServerAttributesDialog::tableContextMenu(const QPoint &pos)
161 context_menu_.popup(ui->tableTreeWidget->viewport()->mapToGlobal(pos));
165 void BluetoothAttServerAttributesDialog::on_actionMark_Unmark_Cell_triggered()
167 QTreeWidgetItem *current_item = ui->tableTreeWidget->currentItem();
168 if (!current_item)
169 return;
171 QBrush fg;
172 QBrush bg;
174 if (current_item->background(ui->tableTreeWidget->currentColumn()) == QBrush(ColorUtils::fromColorT(&prefs.gui_marked_bg))) {
175 fg = QBrush();
176 bg = QBrush();
177 } else {
178 fg = QBrush(ColorUtils::fromColorT(&prefs.gui_marked_fg));
179 bg = QBrush(ColorUtils::fromColorT(&prefs.gui_marked_bg));
182 current_item->setForeground(ui->tableTreeWidget->currentColumn(), fg);
183 current_item->setBackground(ui->tableTreeWidget->currentColumn(), bg);
187 void BluetoothAttServerAttributesDialog::on_actionMark_Unmark_Row_triggered()
189 QTreeWidgetItem *current_item = ui->tableTreeWidget->currentItem();
190 if (!current_item)
191 return;
193 QBrush fg;
194 QBrush bg;
195 bool is_marked = true;
197 for (int i = 0; i < ui->tableTreeWidget->columnCount(); i += 1) {
198 if (current_item->background(i) != QBrush(ColorUtils::fromColorT(&prefs.gui_marked_bg)))
199 is_marked = false;
202 if (is_marked) {
203 fg = QBrush();
204 bg = QBrush();
205 } else {
206 fg = QBrush(ColorUtils::fromColorT(&prefs.gui_marked_fg));
207 bg = QBrush(ColorUtils::fromColorT(&prefs.gui_marked_bg));
210 for (int i = 0; i < ui->tableTreeWidget->columnCount(); i += 1) {
211 current_item->setForeground(i, fg);
212 current_item->setBackground(i, bg);
217 void BluetoothAttServerAttributesDialog::on_actionCopy_Cell_triggered()
219 QTreeWidgetItem *current_item = ui->tableTreeWidget->currentItem();
220 if (!current_item)
221 return;
223 QClipboard *clipboard = QApplication::clipboard();
224 QString copy;
226 copy = QString(current_item->text(ui->tableTreeWidget->currentColumn()));
228 clipboard->setText(copy);
232 void BluetoothAttServerAttributesDialog::on_actionCopy_Rows_triggered()
234 QClipboard *clipboard = QApplication::clipboard();
235 QString copy;
236 QList<QTreeWidgetItem *> items;
237 QList<QTreeWidgetItem *>::iterator i_item;
239 items = ui->tableTreeWidget->selectedItems();
241 for (i_item = items.begin(); i_item != items.end(); ++i_item) {
242 copy += QStringLiteral("%1 %2 %3\n")
243 .arg((*i_item)->text(column_number_handle), -6)
244 .arg((*i_item)->text(column_number_uuid), -32)
245 .arg((*i_item)->text(column_number_uuid_name));
249 clipboard->setText(copy);
252 void BluetoothAttServerAttributesDialog::tapReset(void *tapinfo_ptr)
254 tapinfo_t *tapinfo = (tapinfo_t *) tapinfo_ptr;
255 BluetoothAttServerAttributesDialog *bluetooth_att_server_attributes_dialog = static_cast<BluetoothAttServerAttributesDialog *>(tapinfo->ui);
258 bluetooth_att_server_attributes_dialog->ui->tableTreeWidget->clear();
262 tap_packet_status BluetoothAttServerAttributesDialog::tapPacket(void *tapinfo_ptr, packet_info *pinfo, epan_dissect_t *, const void *data, tap_flags_t)
264 tapinfo_t *tapinfo = static_cast<tapinfo_t *>(tapinfo_ptr);
265 BluetoothAttServerAttributesDialog *dialog = static_cast<BluetoothAttServerAttributesDialog *>(tapinfo->ui);
266 tap_handles_t *tap_handles = static_cast<tap_handles_t *>(const_cast<void *>(data));
267 QString handle;
268 QString uuid;
269 QString uuid_name;
270 char *addr = NULL;
272 if (dialog->file_closed_)
273 return TAP_PACKET_DONT_REDRAW;
275 if (pinfo->rec->rec_type != REC_TYPE_PACKET)
276 return TAP_PACKET_DONT_REDRAW;
278 if (pinfo->rec->presence_flags & WTAP_HAS_INTERFACE_ID) {
279 char *interface;
280 const char *interface_name;
282 unsigned section_number = pinfo->rec->presence_flags & WTAP_HAS_SECTION_NUMBER ? pinfo->rec->section_number : 0;
283 interface_name = epan_get_interface_name(pinfo->epan, pinfo->rec->rec_header.packet_header.interface_id, section_number);
284 interface = wmem_strdup_printf(pinfo->pool, "%u: %s", pinfo->rec->rec_header.packet_header.interface_id, interface_name);
286 if (dialog->ui->interfaceComboBox->findText(interface) == -1)
287 dialog->ui->interfaceComboBox->addItem(interface);
289 if (interface && dialog->ui->interfaceComboBox->currentIndex() > 0) {
290 if (dialog->ui->interfaceComboBox->currentText() != interface)
291 return TAP_PACKET_REDRAW;
295 if (pinfo->p2p_dir == P2P_DIR_SENT || pinfo->p2p_dir == P2P_DIR_RECV)
296 addr = address_to_str(pinfo->pool, &pinfo->src);
298 if (addr && dialog->ui->deviceComboBox->findText(addr) == -1) {
299 dialog->ui->deviceComboBox->addItem(addr);
302 if (addr && dialog->ui->deviceComboBox->currentIndex() > 0) {
303 if (dialog->ui->deviceComboBox->currentText() != addr)
304 return TAP_PACKET_REDRAW;
307 handle = QStringLiteral("0x%1").arg(tap_handles->handle, 4, 16, QChar('0'));
308 uuid = QString(print_numeric_bluetooth_uuid(pinfo->pool, &tap_handles->uuid));
309 uuid_name = QString(print_bluetooth_uuid(pinfo->pool, &tap_handles->uuid));
311 if (dialog->ui->removeDuplicatesCheckBox->checkState() == Qt::Checked) {
312 QTreeWidgetItem *item = item_with_handle_get(dialog->ui->tableTreeWidget,
313 tap_handles->handle);
315 if (item) {
316 if (item->text(column_number_handle) == handle &&
317 item->text(column_number_uuid) == uuid &&
318 item->text(column_number_uuid_name) == uuid_name)
319 return TAP_PACKET_REDRAW;
323 QTreeWidgetItem *parent = NULL;
325 if (tap_handles->attribute_type == ATTRIBUTE_TYPE_SERVICE) {
326 /* Service declarations are the top level items */
327 parent = dialog->ui->tableTreeWidget->invisibleRootItem();
328 } else if ((tap_handles->uuid.bt_uuid == UUID_GATT_INCLUDE_DECLARATION) ||
329 (tap_handles->uuid.bt_uuid == UUID_GATT_CHARACTERISTIC_DECLARATION)) {
330 /* Characteristic and include declarations are part of services. */
331 parent = item_with_handle_get(dialog->ui->tableTreeWidget,
332 tap_handles->service_handle);
333 } else {
334 /* Each characteristic may have several attributes. */
335 parent = item_with_handle_get(dialog->ui->tableTreeWidget,
336 tap_handles->char_decl_handle);
339 if (parent) {
340 QTreeWidgetItem *item = new QTreeWidgetItem(parent);
342 item->setText(column_number_handle, handle);
343 item->setText(column_number_uuid, uuid);
344 item->setText(column_number_uuid_name, uuid_name);
345 item->setData(0, Qt::UserRole, QVariant::fromValue(pinfo->num));
346 item->setData(1, Qt::UserRole, QVariant::fromValue(tap_handles->handle));
348 parent->setExpanded(true);
349 } else {
350 /* Do not insert items without a known parent into the tree.
351 * The parent will likely be found later.
355 for (int i = 0; i < dialog->ui->tableTreeWidget->columnCount(); i++) {
356 dialog->ui->tableTreeWidget->resizeColumnToContents(i);
359 return TAP_PACKET_REDRAW;
362 void BluetoothAttServerAttributesDialog::interfaceCurrentIndexChanged(int)
364 cap_file_.retapPackets();
368 void BluetoothAttServerAttributesDialog::deviceCurrentIndexChanged(int)
370 cap_file_.retapPackets();
373 #if QT_VERSION >= QT_VERSION_CHECK(6, 7, 0)
374 void BluetoothAttServerAttributesDialog::removeDuplicatesStateChanged(Qt::CheckState)
375 #else
376 void BluetoothAttServerAttributesDialog::removeDuplicatesStateChanged(int)
377 #endif
379 cap_file_.retapPackets();
384 void BluetoothAttServerAttributesDialog::on_tableTreeWidget_itemActivated(QTreeWidgetItem *item, int)
386 if (file_closed_)
387 return;
389 uint32_t frame_number = item->data(0, Qt::UserRole).value<uint32_t>();
391 emit goToPacket(frame_number);
395 void BluetoothAttServerAttributesDialog::on_actionCopy_All_triggered()
397 QClipboard *clipboard = QApplication::clipboard();
398 QString copy;
399 QTreeWidgetItemIterator i_item(ui->tableTreeWidget);
401 copy = QStringLiteral("%1 %2 %3\n")
402 .arg(ui->tableTreeWidget->headerItem()->text(column_number_handle), -6)
403 .arg(ui->tableTreeWidget->headerItem()->text(column_number_uuid), -32)
404 .arg(ui->tableTreeWidget->headerItem()->text(column_number_uuid_name));
406 while (*i_item) {
407 QTreeWidgetItem *item = static_cast<QTreeWidgetItem*>(*i_item);
408 copy += QStringLiteral("%1 %2 %3\n")
409 .arg(item->text(column_number_handle), -6)
410 .arg(item->text(column_number_uuid), -32)
411 .arg(item->text(column_number_uuid_name));
412 ++i_item;
415 clipboard->setText(copy);
418 void BluetoothAttServerAttributesDialog::on_actionSave_as_image_triggered()
420 QPixmap image;
422 QString fileName = WiresharkFileDialog::getSaveFileName(this, tr("Save Table Image"),
423 "att_server_attributes_table.png",
424 tr("PNG Image (*.png)"));
426 if (fileName.isEmpty()) return;
428 image = ui->tableTreeWidget->grab();
429 image.save(fileName, "PNG");
432 void BluetoothAttServerAttributesDialog::on_buttonBox_clicked(QAbstractButton *)
434 /* if (button == foo_button_) */