wireshark/ui/qt/models/column_list_model.cpp
Roland Knall f8ec872017 Qt: Reset all changes in the column preferences
Allow the user to reset the changes done. This can be done
at any time, as long as the dialog has not been closed

Change-Id: I0d72a7972b4ea94b53fbed4c84ea952fd6f71b01
Reviewed-on: https://code.wireshark.org/review/34825
Petri-Dish: Roland Knall <rknall@gmail.com>
Tested-by: Petri Dish Buildbot
Reviewed-by: Roland Knall <rknall@gmail.com>
2019-10-21 21:40:57 +00:00

490 lines
13 KiB
C++

/* column_list_models.cpp
*
* Wireshark - Network traffic analyzer
* By Gerald Combs <gerald@wireshark.org>
* Copyright 1998 Gerald Combs
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#include <ui/qt/models/column_list_model.h>
#include <ui/qt/utils/qt_ui_utils.h>
#include <ui/qt/widgets/field_filter_edit.h>
#include <ui/qt/widgets/syntax_line_edit.h>
#include <glib.h>
#include <epan/column-info.h>
#include <epan/column.h>
#include <epan/prefs.h>
#include <epan/proto.h>
#include <ui/preference_utils.h>
#include <QLineEdit>
#include <QStringList>
#include <QComboBox>
struct ListElement
{
QString title;
QString customFields;
int nr;
int type;
int originalType;
int occurrence;
bool displayed;
bool changed;
};
static QList<ListElement> store_;
ColumnProxyModel::ColumnProxyModel(QObject * parent) :
QSortFilterProxyModel(parent),
showDisplayedOnly_(false)
{}
bool ColumnProxyModel::filterAcceptsRow(int source_row, const QModelIndex &/*source_parent*/) const
{
bool displayed = false;
if ( sourceModel() &&
sourceModel()->index(source_row, ColumnListModel::COL_DISPLAYED).data(ColumnListModel::DisplayedState).toBool() )
displayed = true;
if ( showDisplayedOnly_ && ! displayed )
return false;
return true;
}
void ColumnProxyModel::setShowDisplayedOnly(bool set)
{
showDisplayedOnly_ = set;
invalidateFilter();
}
ColumnTypeDelegate::ColumnTypeDelegate(QObject * parent) :
QStyledItemDelegate(parent)
{}
QWidget *ColumnTypeDelegate::createEditor(QWidget *parent,
const QStyleOptionViewItem &option,
const QModelIndex &index) const
{
if ( index.column() == ColumnListModel::COL_TYPE )
{
QComboBox *editor = new QComboBox(parent);
for (int i = 0; i < NUM_COL_FMTS; i++)
{
editor->addItem(col_format_desc(i), QVariant(i));
if ( i == index.data().toInt() )
editor->setCurrentIndex(i);
}
editor->setFrame(false);
return editor;
}
else if ( index.column() == ColumnListModel::COL_FIELDS )
{
FieldFilterEdit * editor = new FieldFilterEdit(parent);
editor->setText(index.data().toString());
return editor;
}
else if ( index.column() == ColumnListModel::COL_OCCURRENCE )
{
SyntaxLineEdit * editor = new SyntaxLineEdit(parent);
connect(editor, &SyntaxLineEdit::textChanged, editor, &SyntaxLineEdit::checkInteger);
editor->setText(index.data().toString());
return editor;
}
return QStyledItemDelegate::createEditor(parent, option, index);
}
void ColumnTypeDelegate::setEditorData(QWidget *editor,
const QModelIndex &index) const
{
QVariant data = index.model()->data(index);
if ( index.column() == ColumnListModel::COL_TYPE )
{
QComboBox *comboBox = static_cast<QComboBox*>(editor);
comboBox->setCurrentText(data.toString());
}
else if ( index.column() == ColumnListModel::COL_FIELDS )
{
if ( qobject_cast<FieldFilterEdit *>(editor) )
qobject_cast<FieldFilterEdit *>(editor)->setText(data.toString());
}
else if ( index.column() == ColumnListModel::COL_OCCURRENCE )
{
if ( qobject_cast<SyntaxLineEdit *>(editor) )
qobject_cast<SyntaxLineEdit *>(editor)->setText(data.toString());
}
else
{
if ( qobject_cast<QLineEdit *>(editor) )
qobject_cast<QLineEdit *>(editor)->setText(data.toString());
}
}
void ColumnTypeDelegate::setModelData(QWidget *editor, QAbstractItemModel *model,
const QModelIndex &index) const
{
if ( index.column() == ColumnListModel::COL_TYPE )
{
QComboBox *comboBox = static_cast<QComboBox*>(editor);
bool ok = false;
int value = comboBox->currentData().toInt(&ok);
if ( ok )
model->setData(index, value, Qt::EditRole);
}
else if ( index.column() == ColumnListModel::COL_FIELDS )
{
FieldFilterEdit * ffe = qobject_cast<FieldFilterEdit *>(editor);
if ( ffe && ffe->checkFilter() )
{
QModelIndex typeIndex = index.sibling(index.row(), ColumnListModel::COL_TYPE);
model->setData(typeIndex, COL_CUSTOM, Qt::EditRole);
model->setData(index, ffe->text(), Qt::EditRole);
}
else
ffe->setText(index.data().toString());
if ( index.data().toString().length() == 0 )
{
QModelIndex typeIndex = index.sibling(index.row(), ColumnListModel::COL_TYPE);
model->setData(typeIndex, index.data(ColumnListModel::OriginalType).toInt(), Qt::EditRole);
}
}
else if ( index.column() == ColumnListModel::COL_OCCURRENCE )
{
SyntaxLineEdit * sle = qobject_cast<SyntaxLineEdit *>(editor);
bool ok = false;
if ( sle )
{
sle->checkInteger(index.data().toString());
if ( sle->syntaxState() == SyntaxLineEdit::Valid )
ok = true;
}
if ( ok )
{
QModelIndex typeIndex = index.sibling(index.row(), ColumnListModel::COL_TYPE);
model->setData(typeIndex, COL_CUSTOM, Qt::EditRole);
model->setData(index, sle->text(), Qt::EditRole);
}
else
sle->setText(index.data().toString());
if ( index.data().toString().length() == 0 )
{
QModelIndex typeIndex = index.sibling(index.row(), ColumnListModel::COL_TYPE);
model->setData(typeIndex, index.data(ColumnListModel::OriginalType).toInt(), Qt::EditRole);
}
}
else
QStyledItemDelegate::setModelData(editor, model, index);
}
void ColumnTypeDelegate::updateEditorGeometry(QWidget *editor,
const QStyleOptionViewItem &option,
const QModelIndex &/* index */) const
{
editor->setGeometry(option.rect);
}
ColumnListModel::ColumnListModel(QObject * parent):
QAbstractTableModel(parent)
{
populate();
}
QVariant ColumnListModel::headerData(int section, Qt::Orientation orientation, int role) const
{
if ( section > ColumnListModel::COL_OCCURRENCE || orientation != Qt::Horizontal ||
role != Qt::DisplayRole )
return QVariant();
return headerTitle(section);
}
int ColumnListModel::rowCount(const QModelIndex &/*parent*/) const
{
return store_.count();
}
int ColumnListModel::columnCount(const QModelIndex &/*parent*/) const
{
return ColumnListModel::COL_OCCURRENCE + 1;
}
QString ColumnListModel::headerTitle(int section) const
{
switch ( section )
{
case ColumnListModel::COL_DISPLAYED:
return tr("Displayed");
case ColumnListModel::COL_TITLE:
return tr("Title");
case ColumnListModel::COL_TYPE:
return tr("Type");
case ColumnListModel::COL_FIELDS:
return tr("Fields");
case ColumnListModel::COL_OCCURRENCE:
return tr("Field Occurence");
}
return QString();
}
void ColumnListModel::populate()
{
store_.clear();
int nr = 0;
for (GList *cur = g_list_first(prefs.col_list); cur != NULL && cur->data != NULL; cur = cur->next) {
fmt_data *cfmt = (fmt_data *) cur->data;
ListElement ne;
ne.nr = nr;
ne.displayed = cfmt->visible;
ne.title = cfmt->title;
ne.type = ne.originalType = cfmt->fmt;
ne.customFields = cfmt->custom_fields;
ne.occurrence = cfmt->custom_occurrence;
nr++;
store_ << ne;
}
}
QVariant ColumnListModel::data(const QModelIndex &index, int role) const
{
if ( ! index.isValid() || index.column() >= store_.count() )
return QVariant();
ListElement ne = store_.at(index.row());
if ( role == Qt::DisplayRole )
{
switch (index.column())
{
case COL_DISPLAYED:
return QVariant();
case ColumnListModel::COL_TITLE:
return ne.title;
case ColumnListModel::COL_TYPE:
return col_format_desc(ne.type);
case ColumnListModel::COL_FIELDS:
return ne.customFields;
case ColumnListModel::COL_OCCURRENCE:
return ne.customFields.length() > 0 ? qVariantFromValue(ne.occurrence) : QVariant();
}
}
else if ( role == Qt::CheckStateRole )
{
if ( index.column() == COL_DISPLAYED )
{
return ne.displayed ? Qt::Checked : Qt::Unchecked;
}
}
else if ( role == OriginalType )
return qVariantFromValue(ne.originalType);
else if ( role == DisplayedState )
return qVariantFromValue(ne.displayed);
return QVariant();
}
Qt::ItemFlags ColumnListModel::flags(const QModelIndex &index) const
{
Qt::ItemFlags defaultFlags = QAbstractTableModel::flags(index);
if ( index.isValid() && index.row() < store_.count() )
{
ListElement ne = store_.at(index.row());
Qt::ItemFlags flags = Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled | defaultFlags;
if ( index.column() == COL_DISPLAYED )
flags |= Qt::ItemIsUserCheckable;
flags |= Qt::ItemIsEditable;
return flags;
}
else
return Qt::ItemIsDropEnabled | defaultFlags;
}
QMimeData *ColumnListModel::mimeData(const QModelIndexList &indexes) const
{
QMimeData *mimeData = new QMimeData;
int row = -1;
if ( indexes.count() > 0 )
row = indexes.at(0).row();
mimeData->setText(QString::number(row));
return mimeData;
}
bool ColumnListModel::canDropMimeData(const QMimeData *data,
Qt::DropAction /* action */, int /* row */, int /* column */, const QModelIndex &parent) const
{
if (parent.isValid() || data->text().isEmpty() )
return false;
return true;
}
bool ColumnListModel::dropMimeData(const QMimeData *data,
Qt::DropAction action, int row, int column, const QModelIndex &parent)
{
int moveTo;
if (!canDropMimeData(data, action, row, column, parent))
return false;
if (action == Qt::IgnoreAction || parent.isValid() )
return true;
if (row != -1)
moveTo = row;
else
moveTo = rowCount(QModelIndex());
bool ok = false;
int moveFrom = data->text().toInt(&ok);
if ( ! ok )
return false;
if ( moveFrom < moveTo )
moveTo = moveTo - 1;
if ( moveTo >= store_.count() )
moveTo = store_.count() - 1;
emit beginResetModel();
store_.move(moveFrom, moveTo);
emit endResetModel();
return true;
}
Qt::DropActions ColumnListModel::supportedDropActions() const
{
return Qt::MoveAction;
}
bool ColumnListModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
if ( !index.isValid() || ! value.isValid() )
return false;
bool change = false;
if ( role == Qt::CheckStateRole && index.column() == ColumnListModel::COL_DISPLAYED )
{
store_[index.row()].displayed = value.toInt() == Qt::Checked ? true : false;
change = true;
}
else if ( index.column() == ColumnListModel::COL_TYPE )
{
bool ok = false;
int val = value.toInt(&ok);
if ( ok )
store_[index.row()].type = val;
}
else if ( index.column() == ColumnListModel::COL_TITLE )
{
store_[index.row()].title = value.toString();
}
else if ( index.column() == ColumnListModel::COL_FIELDS )
{
store_[index.row()].customFields = value.toString();
}
else if ( index.column() == ColumnListModel::COL_OCCURRENCE )
{
bool ok = false;
int val = value.toInt(&ok);
if ( ok )
store_[index.row()].occurrence = val;
}
if ( change )
emit dataChanged(index, index);
return change;
}
void ColumnListModel::saveColumns()
{
GList *new_col_list = Q_NULLPTR;
for ( int row = 0; row < store_.count(); row++ )
{
fmt_data * cfmt = new fmt_data();
ListElement elem = store_.at(row);
cfmt->title = qstring_strdup(elem.title);
cfmt->visible = elem.displayed;
cfmt->fmt = elem.type;
cfmt->resolved = TRUE;
if ( cfmt->fmt == COL_CUSTOM )
{
cfmt->custom_fields = qstring_strdup(elem.customFields);
cfmt->custom_occurrence = elem.occurrence;
}
new_col_list = g_list_append(new_col_list, cfmt);
}
while (prefs.col_list)
column_prefs_remove_link(prefs.col_list);
prefs.col_list = new_col_list;
}
void ColumnListModel::addEntry()
{
emit beginInsertRows(QModelIndex(), rowCount(), rowCount());
ListElement elem;
elem.nr = rowCount();
elem.title = tr("New Column");
elem.displayed = true;
elem.type = elem.originalType = COL_NUMBER;
elem.occurrence = 0;
elem.customFields = QString();
store_ << elem;
emit endInsertRows();
}
void ColumnListModel::deleteEntry(int row)
{
emit beginRemoveRows(QModelIndex(), row, row);
store_.removeAt(row);
emit endRemoveRows();
}
void ColumnListModel::reset()
{
emit beginResetModel();
populate();
emit endResetModel();
}
/*
* 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:
*/