diff options
author | Peter Wu <peter@lekensteyn.nl> | 2017-03-17 00:51:08 +0100 |
---|---|---|
committer | Peter Wu <peter@lekensteyn.nl> | 2017-03-24 23:02:43 +0000 |
commit | 370f3b358cd9ee7dcd2b7274f7ee6c90d5906c7a (patch) | |
tree | f71b56580079e13f017bda7e6c504e30eaa61be8 /ui/qt/cache_proxy_model.cpp | |
parent | b4bc6c72c79fa121753cf94ae179ea73f1e911dd (diff) | |
download | wireshark-370f3b358cd9ee7dcd2b7274f7ee6c90d5906c7a.tar.gz |
Qt: add cache proxy model for Voip Calls dialog
When a capture file is reloaded, the information stored in
VoipCallsInfoModel is invalidated. Add another cache layer to fix this:
VoipCallsInfoModel wraps around raw data (invalid on close)
CacheProxyModel NEW: use prev. data or cache on close
VoipCallsInfoSortedModel provided sorting, etc.
VoipCallsDialog actual user of model (callTreeView)
This also fixes a UAF after a file was closed, and when a call is
selected (that got worse with the last model/view patch and is "fixed"
in this patch with the caching layer. Note that the Flow sequence and
Play Streams dialog are not that useful when the file is closed).
Change-Id: Ib4daff9dc01a54863fe1d943bdbdb876418924ee
Reviewed-on: https://code.wireshark.org/review/20574
Petri-Dish: Peter Wu <peter@lekensteyn.nl>
Tested-by: Petri Dish Buildbot <buildbot-no-reply@wireshark.org>
Reviewed-by: Peter Wu <peter@lekensteyn.nl>
Diffstat (limited to 'ui/qt/cache_proxy_model.cpp')
-rw-r--r-- | ui/qt/cache_proxy_model.cpp | 112 |
1 files changed, 112 insertions, 0 deletions
diff --git a/ui/qt/cache_proxy_model.cpp b/ui/qt/cache_proxy_model.cpp new file mode 100644 index 0000000000..63b1aac70c --- /dev/null +++ b/ui/qt/cache_proxy_model.cpp @@ -0,0 +1,112 @@ +/* cache_proxy_model.cpp + * + * Wireshark - Network traffic analyzer + * By Gerald Combs <gerald@wireshark.org> + * 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 "cache_proxy_model.h" + +CacheProxyModel::CacheProxyModel(QObject *parent) : QIdentityProxyModel(parent) +{ +} + +QVariant CacheProxyModel::data(const QModelIndex &index, int role) const +{ + QModelIndex dataIndex = cache.index(index.row(), index.column()); + if (!dataIndex.isValid()) { + // index is possibly outside columnCount or rowCount + return QVariant(); + } + + if (hasModel()) { + QVariant value = QIdentityProxyModel::data(index, role); + cache.setData(dataIndex, value, role); + return value; + } else { + return cache.data(dataIndex, role); + } +} + +Qt::ItemFlags CacheProxyModel::flags(const QModelIndex &index) const +{ + if (hasModel()) { + return QIdentityProxyModel::flags(index); + } else { + // Override default to prevent editing. + return Qt::ItemIsSelectable | Qt::ItemIsEnabled; + } +} + +QVariant CacheProxyModel::headerData(int section, Qt::Orientation orientation, + int role) const +{ + if (hasModel()) { + QVariant value = QIdentityProxyModel::headerData(section, orientation, role); + cache.setHeaderData(section, orientation, value, role); + return value; + } else { + return cache.headerData(section, orientation, role); + } +} + +int CacheProxyModel::rowCount(const QModelIndex &parent) const +{ + if (hasModel()) { + int count = QIdentityProxyModel::rowCount(parent); + cache.setRowCount(count); + return count; + } else { + return cache.rowCount(parent); + } +} + +int CacheProxyModel::columnCount(const QModelIndex &parent) const +{ + if (hasModel()) { + int count = QIdentityProxyModel::columnCount(parent); + cache.setColumnCount(count); + return count; + } else { + return cache.columnCount(parent); + } +} + +/** + * Sets the source model from which data must be pulled. If newSourceModel is + * NULL, then the cache will be used. + */ +void CacheProxyModel::setSourceModel(QAbstractItemModel *newSourceModel) +{ + if (newSourceModel) { + cache.clear(); + QIdentityProxyModel::setSourceModel(newSourceModel); + connect(newSourceModel, SIGNAL(modelReset()), + this, SLOT(resetCacheModel())); + } else { + if (sourceModel()) { + // Prevent further updates to source model from invalidating cache. + disconnect(sourceModel(), SIGNAL(modelReset()), + this, SLOT(resetCacheModel())); + } + QIdentityProxyModel::setSourceModel(&cache); + } +} + +void CacheProxyModel::resetCacheModel() { + cache.clear(); +} |