Qt: Add a timeline indicator to conversations.
Add a timeline indicator to the Start and Duration columns in the Conversations dialog. Add tooltips to the columns that explain what's going on. Round the timeline rect corners and do the same for Prototocol Hierarchy Statistics. This should hopefully differentiate the graph bars from a text selection and IMHO it looks better. Update the PHS and Conversations images in the User's Guide. Change-Id: I61d6c25843be522cc444e01ba77cb5b1e991fa36 Reviewed-on: https://code.wireshark.org/review/17396 Reviewed-by: Gerald Combs <gerald@wireshark.org> Petri-Dish: Gerald Combs <gerald@wireshark.org> Tested-by: Petri Dish Buildbot <buildbot-no-reply@wireshark.org> Reviewed-by: Anders Broman <a.broman58@gmail.com>
This commit is contained in:
parent
2ddb46dbee
commit
893e0e9608
Binary file not shown.
Before Width: | Height: | Size: 102 KiB After Width: | Height: | Size: 245 KiB |
Binary file not shown.
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 177 KiB |
|
@ -35,7 +35,6 @@ These statistics range from general information about the loaded capture file
|
|||
|
||||
- Various other protocol specific statistics.
|
||||
|
||||
|
||||
[NOTE]
|
||||
====
|
||||
The protocol specific statistics require detailed knowledge about the specific
|
||||
|
@ -45,11 +44,11 @@ be pretty hard to understand.
|
|||
|
||||
[[ChStatSummary]]
|
||||
|
||||
=== The _Summary_ window
|
||||
=== The ``Summary'' window
|
||||
|
||||
General statistics about the current capture file.
|
||||
|
||||
.The "Summary" window
|
||||
.The ``Summary'' window
|
||||
image::wsug_graphics/ws-stats-summary.png[]
|
||||
|
||||
* __File__: general information about the capture file.
|
||||
|
@ -73,12 +72,12 @@ image::wsug_graphics/ws-stats-summary.png[]
|
|||
|
||||
[[ChStatHierarchy]]
|
||||
|
||||
=== The "Protocol Hierarchy" window
|
||||
=== The ``Protocol Hierarchy'' window
|
||||
|
||||
The protocol hierarchy of the captured packets.
|
||||
|
||||
.The "Protocol Hierarchy" window
|
||||
image::wsug_graphics/ws-stats-hierarchy.png[]
|
||||
.The ``Protocol Hierarchy'' window
|
||||
image::wsug_graphics/ws-stats-hierarchy.png[scaledwidth="100%"]
|
||||
|
||||
This is a tree of all the protocols in the capture. Each row contains the
|
||||
statistical values of one protocol. Two of the columns (_Percent Packets_ and
|
||||
|
@ -143,10 +142,11 @@ The conversations window is similar to the endpoint Window. See
|
|||
<<ChStatEndpointsWindow>> for a description of their common features. Along with
|
||||
addresses, packet counters, and byte counters the conversation window adds four
|
||||
columns: the time in seconds between the start of the capture and the start of
|
||||
the conversation ("Rel Start"), the duration of the conversation in seconds, and
|
||||
the average bits (not bytes) per second in each direction.
|
||||
the conversation (``Rel Start''), the duration of the conversation in seconds, and
|
||||
the average bits (not bytes) per second in each direction. A timeline graph is
|
||||
also drawn across the ``Rel Start'' and ``Duration'' columns.
|
||||
|
||||
.The "Conversations" window
|
||||
.The ``Conversations'' window
|
||||
image::wsug_graphics/ws-stats-conversations.png[scaledwidth="100%"]
|
||||
|
||||
Each row in the list shows the statistical values for exactly one conversation.
|
||||
|
@ -241,7 +241,7 @@ will be received by some or all of the listed unicast endpoints.
|
|||
|
||||
[[ChStatEndpointsWindow]]
|
||||
|
||||
==== The "Endpoints" window
|
||||
==== The ``Endpoints'' window
|
||||
|
||||
This window shows statistics about the endpoints captured.
|
||||
|
||||
|
@ -281,13 +281,13 @@ it before (or while) you are doing a live capture.
|
|||
|
||||
[[ChStatIOGraphs]]
|
||||
|
||||
=== The "IO Graphs" window
|
||||
=== The ``IO Graphs'' window
|
||||
|
||||
User configurable graph of the captured network packets.
|
||||
|
||||
You can define up to five differently colored graphs.
|
||||
|
||||
.The "IO Graphs" window
|
||||
.The ``IO Graphs'' window
|
||||
image::wsug_graphics/ws-stats-iographs.png[]
|
||||
|
||||
The user can configure the following things:
|
||||
|
|
|
@ -146,6 +146,7 @@ set(WIRESHARK_QT_HEADERS
|
|||
tap_parameter_dialog.h
|
||||
tcp_stream_dialog.h
|
||||
time_shift_dialog.h
|
||||
timeline_delegate.h
|
||||
traffic_table_dialog.h
|
||||
uat_dialog.h
|
||||
voip_calls_dialog.h
|
||||
|
@ -301,6 +302,7 @@ set(WIRESHARK_QT_SRC
|
|||
tap_parameter_dialog.cpp
|
||||
tcp_stream_dialog.cpp
|
||||
time_shift_dialog.cpp
|
||||
timeline_delegate.cpp
|
||||
traffic_table_dialog.cpp
|
||||
uat_dialog.cpp
|
||||
voip_calls_dialog.cpp
|
||||
|
|
|
@ -278,6 +278,7 @@ MOC_HDRS = \
|
|||
tap_parameter_dialog.h \
|
||||
tcp_stream_dialog.h \
|
||||
time_shift_dialog.h \
|
||||
timeline_delegate.h \
|
||||
traffic_table_dialog.h \
|
||||
uat_dialog.h \
|
||||
voip_calls_dialog.h \
|
||||
|
@ -545,6 +546,7 @@ WIRESHARK_QT_SRC = \
|
|||
tap_parameter_dialog.cpp \
|
||||
tcp_stream_dialog.cpp \
|
||||
time_shift_dialog.cpp \
|
||||
timeline_delegate.cpp \
|
||||
traffic_table_dialog.cpp \
|
||||
uat_dialog.cpp \
|
||||
voip_calls_dialog.cpp \
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#include "wsutil/str_util.h"
|
||||
|
||||
#include "qt_ui_utils.h"
|
||||
#include "timeline_delegate.h"
|
||||
#include "wireshark_application.h"
|
||||
|
||||
#include <QCheckBox>
|
||||
|
@ -153,6 +154,9 @@ bool ConversationDialog::addTrafficTable(register_ct_t* table)
|
|||
|
||||
trafficTableTabWidget()->addTab(conv_tree, table_name);
|
||||
|
||||
conv_tree->setItemDelegateForColumn(CONV_COLUMN_START, new TimelineDelegate(conv_tree));
|
||||
conv_tree->setItemDelegateForColumn(CONV_COLUMN_DURATION, new TimelineDelegate(conv_tree));
|
||||
|
||||
connect(conv_tree, SIGNAL(titleChanged(QWidget*,QString)),
|
||||
this, SLOT(setTabText(QWidget*,QString)));
|
||||
connect(conv_tree, SIGNAL(filterAction(QString,FilterAction::Action,FilterAction::ActionType)),
|
||||
|
@ -325,14 +329,20 @@ public:
|
|||
conv_array_(conv_array),
|
||||
conv_idx_(conv_idx),
|
||||
resolve_names_ptr_(resolve_names_ptr)
|
||||
{}
|
||||
{
|
||||
QString timeline_tt = QObject::tr("Bars show the relative timeline for each conversation.");
|
||||
setToolTip(CONV_COLUMN_START, timeline_tt);
|
||||
setToolTip(CONV_COLUMN_DURATION, timeline_tt);
|
||||
}
|
||||
|
||||
conv_item_t *convItem() {
|
||||
return &g_array_index(conv_array_, conv_item_t, conv_idx_);
|
||||
}
|
||||
|
||||
virtual QVariant data(int column, int role) const {
|
||||
if (role == Qt::DisplayRole) {
|
||||
switch (role) {
|
||||
case Qt::DisplayRole:
|
||||
{
|
||||
// Column text cooked representation.
|
||||
conv_item_t *conv_item = &g_array_index(conv_array_, conv_item_t, conv_idx_);
|
||||
|
||||
|
@ -371,6 +381,37 @@ public:
|
|||
default:
|
||||
return colData(column, resolve_names).toString();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Qt::UserRole:
|
||||
{
|
||||
if (column != CONV_COLUMN_START && column != CONV_COLUMN_DURATION) break;
|
||||
|
||||
ConversationTreeWidget *ctw = qobject_cast<ConversationTreeWidget *>(treeWidget());
|
||||
if (!ctw) break;
|
||||
|
||||
conv_item_t *conv_item = &g_array_index(conv_array_, conv_item_t, conv_idx_);
|
||||
double start_time = nstime_to_sec(&conv_item->start_time);
|
||||
double stop_time = nstime_to_sec(&conv_item->stop_time);
|
||||
|
||||
double span_s = ctw->maxRelStopTime() - ctw->minRelStartTime();
|
||||
if (span_s <= 0) break;
|
||||
int start_px = ctw->columnWidth(CONV_COLUMN_START);
|
||||
int column_px = start_px + ctw->columnWidth(CONV_COLUMN_DURATION);
|
||||
|
||||
struct timeline_span span_px;
|
||||
span_px.start = ((start_time - ctw->minRelStartTime()) * column_px) / span_s;
|
||||
span_px.width = ((stop_time - start_time) * column_px) / span_s;
|
||||
|
||||
if (column == CONV_COLUMN_DURATION) {
|
||||
span_px.start -= start_px;
|
||||
}
|
||||
return qVariantFromValue(span_px);
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return QTreeWidgetItem::data(column, role);
|
||||
}
|
||||
|
@ -498,7 +539,9 @@ private:
|
|||
// TrafficTableTreeWidget / QTreeWidget subclass that allows tapping
|
||||
|
||||
ConversationTreeWidget::ConversationTreeWidget(QWidget *parent, register_ct_t* table) :
|
||||
TrafficTableTreeWidget(parent, table)
|
||||
TrafficTableTreeWidget(parent, table),
|
||||
min_rel_start_time_(0),
|
||||
max_rel_stop_time_(0)
|
||||
{
|
||||
setColumnCount(CONV_NUM_COLUMNS);
|
||||
setUniformRowHeights(true);
|
||||
|
@ -609,6 +652,8 @@ void ConversationTreeWidget::tapReset(void *conv_hash_ptr)
|
|||
|
||||
conv_tree->clear();
|
||||
reset_conversation_table_data(&conv_tree->hash_);
|
||||
conv_tree->min_rel_start_time_ = 0;
|
||||
conv_tree->max_rel_stop_time_ = 0;
|
||||
}
|
||||
|
||||
void ConversationTreeWidget::tapDraw(void *conv_hash_ptr)
|
||||
|
@ -659,6 +704,11 @@ void ConversationTreeWidget::updateItems() {
|
|||
ConversationTreeWidgetItem *ctwi = new ConversationTreeWidgetItem(hash_.conv_array, i, &resolve_names_);
|
||||
new_items << ctwi;
|
||||
|
||||
if (i == 0) {
|
||||
min_rel_start_time_ = nstime_to_sec(&(ctwi->convItem()->start_time));
|
||||
max_rel_stop_time_ = nstime_to_sec(&(ctwi->convItem()->stop_time));
|
||||
}
|
||||
|
||||
for (int col = 0; col < columnCount(); col++) {
|
||||
switch (col) {
|
||||
case CONV_COLUMN_SRC_ADDR:
|
||||
|
@ -672,6 +722,20 @@ void ConversationTreeWidget::updateItems() {
|
|||
}
|
||||
addTopLevelItems(new_items);
|
||||
|
||||
for (int i = 0; i < topLevelItemCount(); i++) {
|
||||
ConversationTreeWidgetItem *ctwi = dynamic_cast<ConversationTreeWidgetItem *>(topLevelItem(i));
|
||||
|
||||
double item_rel_start = nstime_to_sec(&(ctwi->convItem()->start_time));
|
||||
if (item_rel_start < min_rel_start_time_) {
|
||||
min_rel_start_time_ = item_rel_start;
|
||||
}
|
||||
|
||||
double item_rel_stop = nstime_to_sec(&(ctwi->convItem()->stop_time));
|
||||
if (item_rel_stop > max_rel_stop_time_) {
|
||||
max_rel_stop_time_ = item_rel_stop;
|
||||
}
|
||||
}
|
||||
|
||||
setSortingEnabled(true);
|
||||
|
||||
if (resize) {
|
||||
|
|
|
@ -35,10 +35,14 @@ public:
|
|||
|
||||
static void tapReset(void *conv_hash_ptr);
|
||||
static void tapDraw(void *conv_hash_ptr);
|
||||
double minRelStartTime() { return min_rel_start_time_; }
|
||||
double maxRelStopTime() { return max_rel_stop_time_; }
|
||||
|
||||
private:
|
||||
void initDirectionMap();
|
||||
void updateItems();
|
||||
double min_rel_start_time_; // seconds
|
||||
double max_rel_stop_time_; // seconds
|
||||
|
||||
private slots:
|
||||
void filterActionTriggered();
|
||||
|
|
|
@ -35,7 +35,9 @@ void PercentBarDelegate::paint(QPainter *painter, const QStyleOptionViewItem &op
|
|||
QStyleOptionViewItem option_vi = option;
|
||||
QStyledItemDelegate::initStyleOption(&option_vi, index);
|
||||
|
||||
QStyledItemDelegate::paint(painter, option, index);
|
||||
// Paint our rect with no text using the current style, then draw our
|
||||
// bar and text over it.
|
||||
QStyledItemDelegate::paint(painter, option, QModelIndex());
|
||||
|
||||
bool ok = false;
|
||||
double value = index.data(Qt::UserRole).toDouble(&ok);
|
||||
|
@ -45,8 +47,6 @@ void PercentBarDelegate::paint(QPainter *painter, const QStyleOptionViewItem &op
|
|||
return;
|
||||
}
|
||||
|
||||
painter->save();
|
||||
|
||||
if (QApplication::style()->objectName().contains("vista")) {
|
||||
// QWindowsVistaStyle::drawControl does this internally. Unfortunately there
|
||||
// doesn't appear to be a more general way to do this.
|
||||
|
@ -54,29 +54,35 @@ void PercentBarDelegate::paint(QPainter *painter, const QStyleOptionViewItem &op
|
|||
option_vi.palette.color(QPalette::Active, QPalette::Text));
|
||||
}
|
||||
|
||||
QColor bar_color = ColorUtils::alphaBlend(option_vi.palette.windowText(),
|
||||
option_vi.palette.window(), bar_blend_);
|
||||
QPalette::ColorGroup cg = option_vi.state & QStyle::State_Enabled
|
||||
? QPalette::Normal : QPalette::Disabled;
|
||||
QColor text_color = option_vi.palette.color(cg, QPalette::Text);
|
||||
QColor bar_color = ColorUtils::alphaBlend(option_vi.palette.windowText(),
|
||||
option_vi.palette.window(), bar_blend_);
|
||||
|
||||
if (cg == QPalette::Normal && !(option_vi.state & QStyle::State_Active))
|
||||
cg = QPalette::Inactive;
|
||||
if (option_vi.state & QStyle::State_Selected) {
|
||||
painter->setPen(option_vi.palette.color(cg, QPalette::HighlightedText));
|
||||
text_color = option_vi.palette.color(cg, QPalette::HighlightedText);
|
||||
bar_color = ColorUtils::alphaBlend(option_vi.palette.color(cg, QPalette::Window),
|
||||
option_vi.palette.color(cg, QPalette::Highlight),
|
||||
bar_blend_);
|
||||
} else {
|
||||
painter->setPen(option_vi.palette.color(cg, QPalette::Text));
|
||||
}
|
||||
|
||||
painter->save();
|
||||
int border_radius = 3; // We use 3 px elsewhere, e.g. filter combos.
|
||||
QRect pct_rect = option.rect;
|
||||
pct_rect.adjust(1, 1, -1, -1);
|
||||
pct_rect.setWidth(((pct_rect.width() * value) / 100.0) + 0.5);
|
||||
painter->fillRect(pct_rect, bar_color);
|
||||
painter->setPen(Qt::NoPen);
|
||||
painter->setBrush(bar_color);
|
||||
painter->drawRoundedRect(pct_rect, border_radius, border_radius);
|
||||
painter->restore();
|
||||
|
||||
painter->save();
|
||||
QString pct_str = QString::number(value, 'f', 1);
|
||||
painter->setPen(text_color);
|
||||
painter->drawText(option.rect, Qt::AlignCenter, pct_str);
|
||||
|
||||
painter->restore();
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,103 @@
|
|||
/* timeline_delegate.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 "timeline_delegate.h"
|
||||
|
||||
#include "color_utils.h"
|
||||
|
||||
#include <QApplication>
|
||||
#include <QPainter>
|
||||
|
||||
// XXX We might want to move this to conversation_dialog.cpp.
|
||||
|
||||
// PercentBarDelegate uses a stronger blend value, but its bars are also
|
||||
// more of a prominent feature. Make the blend weaker here so that we don't
|
||||
// obscure our text.
|
||||
static const double bar_blend_ = 0.08;
|
||||
|
||||
TimelineDelegate::TimelineDelegate(QWidget *parent) :
|
||||
QStyledItemDelegate(parent)
|
||||
{}
|
||||
|
||||
void TimelineDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option,
|
||||
const QModelIndex &index) const
|
||||
{
|
||||
QStyleOptionViewItem option_vi = option;
|
||||
QStyledItemDelegate::initStyleOption(&option_vi, index);
|
||||
|
||||
|
||||
struct timeline_span span_px = index.data(Qt::UserRole).value<struct timeline_span>();
|
||||
|
||||
// Paint our rect with no text using the current style, then draw our
|
||||
// bar and text over it.
|
||||
QStyledItemDelegate::paint(painter, option, QModelIndex());
|
||||
|
||||
if (QApplication::style()->objectName().contains("vista")) {
|
||||
// QWindowsVistaStyle::drawControl does this internally. Unfortunately there
|
||||
// doesn't appear to be a more general way to do this.
|
||||
option_vi.palette.setColor(QPalette::All, QPalette::HighlightedText,
|
||||
option_vi.palette.color(QPalette::Active, QPalette::Text));
|
||||
}
|
||||
|
||||
QPalette::ColorGroup cg = option_vi.state & QStyle::State_Enabled
|
||||
? QPalette::Normal : QPalette::Disabled;
|
||||
QColor text_color = option_vi.palette.color(cg, QPalette::Text);
|
||||
QColor bar_color = ColorUtils::alphaBlend(option_vi.palette.windowText(),
|
||||
option_vi.palette.window(), bar_blend_);
|
||||
|
||||
if (cg == QPalette::Normal && !(option_vi.state & QStyle::State_Active))
|
||||
cg = QPalette::Inactive;
|
||||
if (option_vi.state & QStyle::State_Selected) {
|
||||
text_color = option_vi.palette.color(cg, QPalette::HighlightedText);
|
||||
bar_color = ColorUtils::alphaBlend(option_vi.palette.color(cg, QPalette::Window),
|
||||
option_vi.palette.color(cg, QPalette::Highlight),
|
||||
bar_blend_);
|
||||
}
|
||||
|
||||
painter->save();
|
||||
int border_radius = 3; // We use 3 px elsewhere, e.g. filter combos.
|
||||
QRect timeline_rect = option.rect;
|
||||
timeline_rect.adjust(span_px.start, 1, 0, -1);
|
||||
timeline_rect.setWidth(span_px.width);
|
||||
painter->setClipRect(option.rect);
|
||||
painter->setPen(Qt::NoPen);
|
||||
painter->setBrush(bar_color);
|
||||
painter->drawRoundedRect(timeline_rect, border_radius, border_radius);
|
||||
painter->restore();
|
||||
|
||||
painter->save();
|
||||
painter->setPen(text_color);
|
||||
painter->drawText(option.rect, Qt::AlignCenter, index.data(Qt::DisplayRole).toString());
|
||||
painter->restore();
|
||||
}
|
||||
|
||||
/*
|
||||
* 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:
|
||||
*/
|
|
@ -0,0 +1,80 @@
|
|||
/* timeline_delegate.h
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef TIMELINE_DELEGATE_H
|
||||
#define TIMELINE_DELEGATE_H
|
||||
|
||||
/*
|
||||
* @file Timeline delegate.
|
||||
*
|
||||
* QStyledItemDelegate subclass that will draw a timeline indicator for
|
||||
* the specified value.
|
||||
*
|
||||
* This is intended to be used in QTreeWidgets to show timelines, e.g. for
|
||||
* conversations.
|
||||
* To use it, first call setItemDelegate:
|
||||
*
|
||||
* myTreeWidget()->setItemDelegateForColumn(col_time_start_, new TimelineDelegate());
|
||||
*
|
||||
* Then, for each QTreeWidgetItem, set or return a timeline_span for the start and end
|
||||
* of the timeline in pixels relative to the column width.
|
||||
*
|
||||
* setData(col_start_, Qt::UserRole, start_span);
|
||||
* setData(col_end_, Qt::UserRole, end_span);
|
||||
*
|
||||
*/
|
||||
|
||||
#include <QStyledItemDelegate>
|
||||
|
||||
// Pixels are relative to item rect and will be clipped.
|
||||
struct timeline_span {
|
||||
int start;
|
||||
int width;
|
||||
};
|
||||
|
||||
Q_DECLARE_METATYPE(timeline_span)
|
||||
|
||||
class TimelineDelegate : public QStyledItemDelegate
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
TimelineDelegate(QWidget *parent = 0);
|
||||
protected:
|
||||
void paint(QPainter *painter, const QStyleOptionViewItem &option,
|
||||
const QModelIndex &index) const;
|
||||
private:
|
||||
};
|
||||
|
||||
#endif // TIMELINE_DELEGATE_H
|
||||
|
||||
/*
|
||||
* 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:
|
||||
*/
|
Loading…
Reference in New Issue