summaryrefslogtreecommitdiffstats
path: root/ui/qt/models/manuf_table_model.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'ui/qt/models/manuf_table_model.cpp')
-rw-r--r--ui/qt/models/manuf_table_model.cpp220
1 files changed, 220 insertions, 0 deletions
diff --git a/ui/qt/models/manuf_table_model.cpp b/ui/qt/models/manuf_table_model.cpp
new file mode 100644
index 0000000..3579227
--- /dev/null
+++ b/ui/qt/models/manuf_table_model.cpp
@@ -0,0 +1,220 @@
+/*
+ * manuf_table_model.h
+ *
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald@wireshark.org>
+ * Copyright 1998 Gerald Combs
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "manuf_table_model.h"
+
+ManufTableItem::ManufTableItem(struct ws_manuf *ptr) :
+ short_name_(QString::fromUtf8(ptr->short_name)),
+ long_name_(QString::fromUtf8(ptr->long_name))
+{
+ qsizetype size;
+ switch (ptr->mask) {
+ case 24:
+ size = 3;
+ break;
+ case 28:
+ size = 4;
+ break;
+ case 36:
+ size = 5;
+ break;
+ default:
+ ws_assert_not_reached();
+ }
+ // Note: since 'ptr' is not stable, a deep copy is needed.
+#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
+ block_bytes_ = QByteArray(reinterpret_cast<const char *>(ptr->block), size);
+#else
+ block_bytes_ = QByteArray(reinterpret_cast<const char *>(ptr->block), static_cast<int>(size));
+#endif
+
+ char buf[64];
+ block_name_ = QString::fromUtf8(ws_manuf_block_str(buf, sizeof(buf), ptr));
+}
+
+ManufTableItem::~ManufTableItem()
+{
+}
+
+ManufTableModel::ManufTableModel(QObject *parent) : QAbstractTableModel(parent)
+{
+ ws_manuf_iter_t iter;
+ struct ws_manuf item;
+
+ ws_manuf_iter_init(&iter);
+ while (ws_manuf_iter_next(&iter, &item)) {
+ rows_.append(new ManufTableItem(&item));
+ }
+}
+
+ManufTableModel::~ManufTableModel()
+{
+ clear();
+}
+
+int ManufTableModel::rowCount(const QModelIndex &) const
+{
+ return static_cast<int>(rows_.count());
+}
+
+int ManufTableModel::columnCount(const QModelIndex &) const
+{
+ return NUM_COLS;
+}
+
+QVariant ManufTableModel::data(const QModelIndex &index, int role) const
+{
+ if (!index.isValid())
+ return QVariant();
+
+ if (index.row() >= rows_.size())
+ return QVariant();
+
+ ManufTableItem *item = rows_.at(index.row());
+ if (index.column() >= NUM_COLS)
+ return QVariant();
+
+ if (role == Qt::DisplayRole) {
+ switch (index.column()) {
+ case COL_MAC_PREFIX:
+ return item->block_name_;
+ case COL_SHORT_NAME:
+ return item->short_name_;
+ case COL_VENDOR_NAME:
+ return item->long_name_;
+ default:
+ return QVariant();
+ }
+ }
+
+ if (role == Qt::UserRole) {
+ switch (index.column()) {
+ case COL_MAC_PREFIX:
+ return item->block_bytes_;
+ case COL_SHORT_NAME:
+ return item->short_name_;
+ case COL_VENDOR_NAME:
+ return item->long_name_;
+ default:
+ return QVariant();
+ }
+ }
+
+ return QVariant();
+}
+
+void ManufTableModel::addRecord(struct ws_manuf *ptr)
+{
+ emit beginInsertRows(QModelIndex(), rowCount(), rowCount());
+ ManufTableItem *item = new ManufTableItem(ptr);
+ rows_.append(item);
+ emit endInsertRows();
+}
+
+void ManufTableModel::clear()
+{
+ if (!rows_.isEmpty()) {
+ emit beginRemoveRows(QModelIndex(), 0, rowCount() - 1);
+ qDeleteAll(rows_.begin(), rows_.end());
+ rows_.clear();
+ emit endRemoveRows();
+ }
+}
+
+QVariant ManufTableModel::headerData(int section, Qt::Orientation orientation, int role) const
+{
+ if (role != Qt::DisplayRole)
+ return QVariant();
+
+ if (orientation == Qt::Horizontal) {
+ switch (section) {
+ case COL_MAC_PREFIX:
+ return QString(tr("Address Block"));
+ case COL_SHORT_NAME:
+ return QString(tr("Short Name"));
+ case COL_VENDOR_NAME:
+ return QString(tr("Vendor Name"));
+ }
+ }
+
+ return QVariant();
+}
+
+
+ManufSortFilterProxyModel::ManufSortFilterProxyModel(QObject* parent) :
+ QSortFilterProxyModel(parent),
+ filter_type_(FilterEmpty)
+{
+}
+
+void ManufSortFilterProxyModel::clearFilter()
+{
+ if (filter_type_ == FilterEmpty)
+ return;
+ filter_type_ = FilterEmpty;
+ invalidateFilter();
+}
+
+void ManufSortFilterProxyModel::setFilterAddress(const QByteArray &bytes)
+{
+ filter_type_ = FilterByAddress;
+ filter_bytes_ = bytes;
+ invalidateFilter();
+}
+
+void ManufSortFilterProxyModel::setFilterName(QRegularExpression &name)
+{
+ filter_type_ = FilterByName;
+ filter_name_ = name;
+ invalidateFilter();
+}
+
+static bool match_filter(const QByteArray &bytes, const QByteArray &mac_block)
+{
+ if (bytes.size() < mac_block.size())
+ return mac_block.startsWith(bytes);
+
+#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
+ QByteArray prefix = bytes.first(mac_block.size());
+#else
+ QByteArray prefix = bytes.left(mac_block.size());
+#endif
+ // Blocks are 3, 4 or 5 bytes wide
+ if (mac_block.size() > 3) {
+ // Mask out the last nibble of the bytes for 28 and 36 bit block lengths
+ // (but not 24 bit OUIs)
+ prefix[prefix.size() - 1] = prefix[prefix.size() - 1] & 0xF0;
+ }
+ return prefix == mac_block;
+}
+
+bool ManufSortFilterProxyModel::filterAddressAcceptsRow(int source_row, const QModelIndex& source_parent) const
+{
+ QModelIndex chkIdx = sourceModel()->index(source_row, ManufTableModel::COL_MAC_PREFIX, source_parent);
+ QByteArray mac_block = chkIdx.data(Qt::UserRole).toByteArray();
+ return match_filter(filter_bytes_, mac_block);
+}
+
+bool ManufSortFilterProxyModel::filterNameAcceptsRow(int source_row, const QModelIndex& source_parent) const
+{
+ QModelIndex chkIdx = sourceModel()->index(source_row, ManufTableModel::COL_VENDOR_NAME, source_parent);
+ QString vendor_name = chkIdx.data(Qt::UserRole).toString();
+ return filter_name_.match(vendor_name).hasMatch();
+}
+
+bool ManufSortFilterProxyModel::filterAcceptsRow(int source_row, const QModelIndex& source_parent) const
+{
+ switch (filter_type_) {
+ case FilterEmpty: return true;
+ case FilterByAddress: return filterAddressAcceptsRow(source_row, source_parent);
+ case FilterByName: return filterNameAcceptsRow(source_row, source_parent);
+ }
+ ws_error("unknown filter type %d", filter_type_);
+}