setItemsExpandable(false);
setRootIsDecorated(false);
setSortingEnabled(true);
+ setUniformRowHeights(true);
setAccessibleName("Packet list");
setItemDelegateForColumn(0, &related_packet_delegate_);
g_assert(gbl_cur_packet_list == NULL);
gbl_cur_packet_list = this;
- connect(packet_list_model_, SIGNAL(rowHeightsVary()), this, SLOT(rowHeightsVary()));
connect(packet_list_model_, SIGNAL(goToPacket(int)), this, SLOT(goToPacket(int)));
+ connect(packet_list_model_, SIGNAL(itemHeightChanged(const QModelIndex&)), this, SLOT(updateRowHeights(const QModelIndex&)));
connect(wsApp, SIGNAL(addressResolutionChanged()), this, SLOT(redrawVisiblePackets()));
header()->setContextMenuPolicy(Qt::CustomContextMenu);
// on OS X and Linux. We might want to add Q_OS_... #ifdefs accordingly.
size_hint = itemDelegateForColumn(column)->sizeHint(viewOptions(), QModelIndex()).width();
}
- packet_list_model_->setSizeHintEnabled(false);
size_hint += QTreeView::sizeHintForColumn(column); // Decoration padding
- packet_list_model_->setSizeHintEnabled(true);
return size_hint;
}
create_near_overlay_ = true;
create_far_overlay_ = true;
- setUniformRowHeights(true);
setColumnVisibility();
}
{
setFont(mono_font);
header()->setFont(wsApp->font());
-
- // qtreeview.cpp does something similar in Qt 5 so this *should* be
- // safe...
- int row_height = itemDelegate()->sizeHint(viewOptions(), QModelIndex()).height();
- packet_list_model_->setMonospaceFont(mono_font, row_height);
- redrawVisiblePackets();
}
void PacketList::goNextPacket(void) {
wsApp->emitAppSignal(WiresharkApplication::ColumnsChanged);
}
-void PacketList::rowHeightsVary()
+void PacketList::updateRowHeights(const QModelIndex &ih_index)
{
- // This impairs performance considerably for large numbers of packets.
- // We should probably move a bunch of the code in ::data to
- // RelatedPacketDelegate and make it the delegate for everything.
- setUniformRowHeights(false);
+ QStyleOptionViewItem option = viewOptions();
+ int max_height = 0;
+
+ // One of our columns increased the maximum row height. Find out which one.
+ for (int col = 0; col < packet_list_model_->columnCount(); col++) {
+ QSize size_hint = itemDelegate()->sizeHint(option, packet_list_model_->index(ih_index.row(), col));
+ max_height = qMax(max_height, size_hint.height());
+ }
+
+ if (max_height > 0) {
+ packet_list_model_->setMaximiumRowHeight(max_height);
+ }
}
void PacketList::copySummary()
void columnVisibilityTriggered();
void sectionResized(int col, int, int new_width);
void sectionMoved(int, int, int);
- void rowHeightsVary();
+ void updateRowHeights(const QModelIndex &ih_index);
void copySummary();
void vScrollBarActionTriggered(int);
void drawFarOverlay();
PacketListModel::PacketListModel(QObject *parent, capture_file *cf) :
QAbstractItemModel(parent),
- uniform_row_heights_(true),
- row_height_(-1),
- line_spacing_(0),
+ max_row_height_(0),
+ max_line_count_(1),
idle_dissection_row_(0)
{
setCaptureFile(cf);
PacketListRecord::clearStringPool();
- connect(this, SIGNAL(itemHeightChanged(QModelIndex)),
+ connect(this, SIGNAL(maxLineCountChanged(QModelIndex)),
this, SLOT(emitItemHeightChanged(QModelIndex)),
Qt::QueuedConnection);
idle_dissection_timer_ = new QElapsedTimer();
}
}
endInsertRows();
- return visible_rows_.count();
idle_dissection_row_ = 0;
+ return visible_rows_.count();
}
void PacketListModel::clear() {
number_to_row_.clear();
PacketListRecord::clearStringPool();
endResetModel();
- uniform_row_heights_ = true;
+ max_row_height_ = 0;
+ max_line_count_ = 1;
idle_dissection_row_ = 0;
}
dataChanged(index(0, 0), index(rowCount() - 1, columnCount() - 1));
}
-void PacketListModel::setMonospaceFont(const QFont &mono_font, int row_height)
+void PacketListModel::setMaximiumRowHeight(int height)
{
- QFontMetrics fm(mono_font_);
- mono_font_ = mono_font;
- row_height_ = row_height;
- line_spacing_ = fm.lineSpacing();
+ max_row_height_ = height;
+ // As the QTreeView uniformRowHeights documentation says,
+ // "The height is obtained from the first item in the view. It is
+ // updated when the data changes on that item."
+ dataChanged(index(0, 0), index(0, columnCount() - 1));
}
+//void PacketListModel::setMonospaceFont(const QFont &mono_font, int row_height)
+//{
+// QFontMetrics fm(mono_font_);
+// mono_font_ = mono_font;
+// row_height_ = row_height;
+// line_spacing_ = fm.lineSpacing();
+//}
+
// The Qt MVC documentation suggests using QSortFilterProxyModel for sorting
// and filtering. That seems like overkill but it might be something we want
// to do in the future.
// ::data is const so we have to make changes here.
void PacketListModel::emitItemHeightChanged(const QModelIndex &ih_index)
{
- if (uniform_row_heights_) {
- uniform_row_heights_ = false;
- emit rowHeightsVary();
+ if (!ih_index.isValid()) return;
+
+ PacketListRecord *record = static_cast<PacketListRecord*>(ih_index.internalPointer());
+ if (!record) return;
+
+ if (record->lineCount() > max_line_count_) {
+ max_line_count_ = record->lineCount();
+ emit itemHeightChanged(ih_index);
}
- emit dataChanged(ih_index, ih_index);
}
int PacketListModel::rowCount(const QModelIndex &parent) const
return QVariant();
switch (role) {
- case Qt::FontRole:
- return mono_font_;
case Qt::TextAlignmentRole:
switch(recent_get_column_xalign(d_index.column())) {
case COLUMN_XALIGN_RIGHT:
// Assume each line count is 1. If the line count changes, emit
// itemHeightChanged which triggers another redraw (including a
// fetch of SizeHintRole and DisplayRole) in the next event loop.
- if (column == 0 && record->lineCountChanged()) {
- emit itemHeightChanged(d_index);
+ if (column == 0 && record->lineCountChanged() && record->lineCount() > max_line_count_) {
+ emit maxLineCountChanged(d_index);
}
return column_string;
}
case Qt::SizeHintRole:
{
- // We assume that inter-line spacing is 0.
- QSize size = QSize(-1, row_height_ + ((record->lineCount() - 1) * line_spacing_));
- return size;
+ // If this is the first row and column, return the maximum row height...
+ if (d_index.row() < 1 && d_index.column() < 1 && max_row_height_ > 0) {
+ QSize size = QSize(-1, max_row_height_);
+ return size;
+ }
+ // ...otherwise punt so that the item delegate can correctly calculate the item width.
+ return QVariant();
}
default:
return QVariant();
void setDisplayedFrameIgnore(gboolean set);
void toggleFrameRefTime(const QModelIndex &rt_index);
void unsetAllFrameRefTime();
- void setSizeHintEnabled(bool enable) { uniform_row_heights_ = enable; }
+
+ void setMaximiumRowHeight(int height);
signals:
void goToPacket(int);
- void itemHeightChanged(const QModelIndex &ih_index) const;
- void rowHeightsVary();
+ void maxLineCountChanged(const QModelIndex &ih_index) const;
+ void itemHeightChanged(const QModelIndex &ih_index);
void pushBusyStatus(const QString &status);
void popBusyStatus();
void popProgressStatus();
public slots:
- void setMonospaceFont(const QFont &mono_font, int row_height);
void sort(int column, Qt::SortOrder order = Qt::AscendingOrder);
void flushVisibleRows();
void dissectIdle(bool reset = false);
private:
capture_file *cap_file_;
- QFont mono_font_;
QList<QString> col_names_;
QVector<PacketListRecord *> physical_rows_;
QVector<PacketListRecord *> visible_rows_;
QVector<PacketListRecord *> new_visible_rows_;
QMap<int, int> number_to_row_;
- bool uniform_row_heights_;
- int row_height_;
- int line_spacing_;
+ int max_row_height_; // px
+ int max_line_count_;
static int sort_column_;
static int text_sort_column_;
// Related packet indicator. Rightward arrow for requests, leftward
// arrow for responses, circle for others.
+ // XXX These are comically oversized when we have multi-line rows.
if (related_frames_.contains(fd->num)) {
painter->setBrush(fg);
switch (related_frames_[fd->num]) {