Add packet information and selection to the Follow Stream dialog.

Collect packet numbers when following streams so that we can correlate
text positions with packets. Add a FollowStreamText class so that we can
track mouse events. Add a hint label that shows the packet under the
cursor along with packet counts and the number of "turns".

Add the packet number to the C array dump. Note that dumping to YAML
might be useful for Scapy users.

svn path=/trunk/; revision=53314
This commit is contained in:
Gerald Combs 2013-11-14 17:37:40 +00:00
parent 2809240ead
commit 190bdc32de
15 changed files with 306 additions and 50 deletions

View File

@ -4632,7 +4632,8 @@ dissect_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
&pinfo->net_src,
&pinfo->net_dst,
pinfo->srcport,
pinfo->destport);
pinfo->destport,
pinfo->fd->num);
}
}

View File

@ -231,7 +231,7 @@ void
reassemble_tcp( guint32 tcp_stream, guint32 sequence, guint32 acknowledgement,
guint32 length, const char* data, guint32 data_length,
int synflag, address *net_src, address *net_dst,
guint srcport, guint dstport) {
guint srcport, guint dstport, guint32 packet_num) {
guint8 srcx[MAX_IPADDR_LEN], dstx[MAX_IPADDR_LEN];
int src_index, j, first = 0, len;
guint32 newseq;
@ -325,8 +325,9 @@ reassemble_tcp( guint32 tcp_stream, guint32 sequence, guint32 acknowledgement,
/* Initialize our stream chunk. This data gets written to disk. */
memcpy(sc.src_addr, srcx, len);
sc.src_port = srcport;
sc.dlen = data_length;
sc.src_port = srcport;
sc.dlen = data_length;
sc.packet_num = packet_num;
/* now that we have filed away the srcs, lets get the sequence number stuff
figured out */

View File

@ -44,6 +44,7 @@ typedef struct _tcp_stream_chunk {
guint8 src_addr[MAX_IPADDR_LEN];
guint16 src_port;
guint32 dlen;
guint32 packet_num;
} tcp_stream_chunk;
/** Build a follow filter based on the current packet's conversation.
@ -84,7 +85,7 @@ WS_DLL_PUBLIC
guint32 get_follow_tcp_index(void);
void reassemble_tcp( guint32, guint32, guint32, guint32, const char*, guint32,
int, address *, address *, guint, guint );
int, address *, address *, guint, guint, guint32 );
WS_DLL_PUBLIC
void reset_tcp_reassembly( void );

View File

@ -38,6 +38,7 @@ extern "C" {
typedef struct {
gboolean is_from_server;
guint32 packet_num;
StringInfo data;
} SslDecryptedRecord;
@ -73,6 +74,7 @@ typedef enum {
typedef struct {
gboolean is_server;
guint32 packet_num;
GByteArray *data;
} follow_record_t;

View File

@ -45,6 +45,7 @@ set(QTSHARK_H_SRC
file_set_dialog.h
filter_expressions_preferences_frame.h
follow_stream_dialog.h
follow_stream_text.h
font_color_preferences_frame.h
import_text_dialog.h
interface_tree.h
@ -108,6 +109,7 @@ set(CLEAN_FILES
file_set_dialog.cpp
filter_expressions_preferences_frame.cpp
follow_stream_dialog.cpp
follow_stream_text.cpp
font_color_preferences_frame.cpp
import_text_dialog.cpp
interface_tree.cpp

View File

@ -247,6 +247,7 @@ WIRESHARK_QT_SRC = \
file_set_dialog.cpp \
filter_expressions_preferences_frame.cpp \
follow_stream_dialog.cpp \
follow_stream_text.cpp \
font_color_preferences_frame.cpp \
import_text_dialog.cpp \
interface_tree.cpp \

View File

@ -238,6 +238,7 @@ HEADERS += $$HEADERS_WS_C \
export_object_dialog.h \
filter_expressions_preferences_frame.h \
follow_stream_dialog.h \
follow_stream_text.h \
font_color_preferences_frame.h \
layout_preferences_frame.h \
main_window_preferences_frame.h \
@ -532,6 +533,7 @@ SOURCES += \
file_set_dialog.cpp \
filter_expressions_preferences_frame.cpp \
follow_stream_dialog.cpp \
follow_stream_text.cpp \
font_color_preferences_frame.cpp \
import_text_dialog.cpp \
interface_tree.cpp \

View File

@ -81,7 +81,10 @@ FollowStreamDialog::FollowStreamDialog(QWidget *parent, follow_type_t type, capt
ui->teStreamContent->installEventFilter(this);
connect(ui->buttonBox, SIGNAL(helpRequested()), this, SLOT(helpButton()));
// XXX Use recent settings instead
if (parent) {
resize(parent->width() * 2 / 3, parent->height());
}
b_filter_out_ = ui->buttonBox->addButton(tr("Hide this stream"), QDialogButtonBox::ActionRole);
connect(b_filter_out_, SIGNAL(clicked()), this, SLOT(filterOut()));
@ -92,6 +95,13 @@ FollowStreamDialog::FollowStreamDialog(QWidget *parent, follow_type_t type, capt
b_save_ = ui->buttonBox->addButton(tr("Save as..."), QDialogButtonBox::ActionRole);
connect(b_save_, SIGNAL(clicked()), this, SLOT(saveAs()));
connect(ui->buttonBox, SIGNAL(helpRequested()), this, SLOT(helpButton()));
connect(ui->teStreamContent, SIGNAL(mouseMovedToTextCursorPosition(int)),
this, SLOT(fillHintLabel(int)));
connect(ui->teStreamContent, SIGNAL(mouseClickedOnTextCursorPosition(int)),
this, SLOT(goToPacketForTextPos(int)));
fillHintLabel(-1);
}
FollowStreamDialog::~FollowStreamDialog()
@ -110,6 +120,50 @@ void FollowStreamDialog::printStream()
#endif
}
void FollowStreamDialog::fillHintLabel(int text_pos)
{
QString hint;
int pkt = -1;
if (text_pos >= 0) {
QMap<int, guint32>::iterator it = text_pos_to_packet_.upperBound(text_pos);
if (it != text_pos_to_packet_.end()) {
pkt = it.value();
}
}
if (pkt > 0) {
hint = QString("Packet %1. ").arg(pkt);
}
hint.append(QString("%1 client pkts, %2 server pkts, %3 turns.")
.arg(client_packet_count_).arg(server_packet_count_).arg(turns_));
if (pkt > 0) {
hint.append(QString(" Click to select."));
}
hint.prepend("<small><i>");
hint.append("</i></small>");
ui->hintLabel->setText(hint);
}
void FollowStreamDialog::goToPacketForTextPos(int text_pos)
{
int pkt = -1;
if (text_pos >= 0) {
QMap<int, guint32>::iterator it = text_pos_to_packet_.upperBound(text_pos);
if (it != text_pos_to_packet_.end()) {
pkt = it.value();
}
}
if (pkt > 0) {
emit goToPacket(pkt);
}
}
void FollowStreamDialog::findText(bool go_back)
{
if (ui->leFind->text().isEmpty()) return;
@ -245,6 +299,7 @@ void FollowStreamDialog::resetStream()
GList *cur;
filter_out_filter_.clear();
text_pos_to_packet_.clear();
if (!data_out_filename_.isEmpty()) ws_unlink(data_out_filename_.toUtf8().constData());
for (cur = follow_info_.payload; cur; cur = g_list_next(cur)) {
g_free(cur->data);
@ -253,11 +308,19 @@ void FollowStreamDialog::resetStream()
follow_info_.payload = NULL;
}
// XXX We end up calling this twice when we open the dialog.
frs_return_t
FollowStreamDialog::follow_read_stream()
{
ui->teStreamContent->clear();
client_buffer_count_ = 0;
server_buffer_count_ = 0;
client_packet_count_ = 0;
server_packet_count_ = 0;
last_packet_ = 0;
turns_ = 0;
switch(follow_type_) {
case FOLLOW_TCP :
@ -292,6 +355,7 @@ udp_queue_packet_data(void *tapdata, packet_info *pinfo,
follow_record->data = g_byte_array_append(follow_record->data,
tvb_get_ptr(next_tvb, 0, -1),
tvb_length(next_tvb));
follow_record->packet_num = pinfo->fd->num;
if (follow_info->client_port == 0) {
follow_info->client_port = pinfo->srcport;
@ -360,6 +424,7 @@ ssl_queue_packet_data(void *tapdata, packet_info *pinfo, epan_dissect_t *edt, co
view does by starting a new array declaration. */
rec = (SslDecryptedRecord*) g_malloc(sizeof(SslDecryptedRecord) + appl_data->plain_data.data_len);
rec->is_from_server = from == FROM_SERVER;
rec->packet_num = pinfo->fd->num;
rec->data.data = (guchar*) (rec + 1);
rec->data.data_len = appl_data->plain_data.data_len;
memcpy(rec->data.data, appl_data->plain_data.data, appl_data->plain_data.data_len);
@ -372,7 +437,6 @@ ssl_queue_packet_data(void *tapdata, packet_info *pinfo, epan_dissect_t *edt, co
return 0;
}
/*
* XXX - the routine pointed to by "print_line_fcn_p" doesn't get handed lines,
* it gets handed bufferfuls. That's fine for "follow_write_raw()"
@ -394,8 +458,6 @@ frs_return_t
FollowStreamDialog::follow_read_ssl_stream()
{
guint32 global_client_pos = 0, global_server_pos = 0;
guint32 server_packet_count = 0;
guint32 client_packet_count = 0;
guint32 * global_pos;
GList * cur;
frs_return_t frs_return;
@ -419,8 +481,7 @@ FollowStreamDialog::follow_read_ssl_stream()
gchar *buffer = (gchar *)g_memdup(rec->data.data, (guint) nchars);
frs_return = follow_show(buffer, nchars,
rec->is_from_server, global_pos,
&server_packet_count, &client_packet_count);
rec->is_from_server, rec->packet_num, global_pos);
g_free(buffer);
if (frs_return == FRS_PRINT_ERROR)
return frs_return;
@ -450,7 +511,7 @@ FollowStreamDialog::follow_stream()
void FollowStreamDialog::add_text(char *buffer, size_t nchars, gboolean is_from_server)
void FollowStreamDialog::add_text(char *buffer, size_t nchars, gboolean is_from_server, guint32 packet_num)
{
size_t i;
QString buf;
@ -504,6 +565,8 @@ void FollowStreamDialog::add_text(char *buffer, size_t nchars, gboolean is_from_
ui->teStreamContent->setTextBackgroundColor(tagclient_bg);
ui->teStreamContent->insertPlainText(buf);
}
ui->teStreamContent->moveCursor(QTextCursor::End);
text_pos_to_packet_[ui->teStreamContent->textCursor().anchor()] = packet_num;
}
void FollowStreamDialog::setCaptureFile(capture_file *cf)
@ -560,9 +623,8 @@ void FollowStreamDialog::keyPressEvent(QKeyEvent *event)
}
frs_return_t
FollowStreamDialog::follow_show(char *buffer, size_t nchars, gboolean is_from_server,
guint32 *global_pos, guint32 *server_packet_count,
guint32 *client_packet_count)
FollowStreamDialog::follow_show(char *buffer, size_t nchars, gboolean is_from_server, guint32 packet_num,
guint32 *global_pos)
{
gchar initbuf[256];
guint32 current_pos;
@ -573,21 +635,21 @@ FollowStreamDialog::follow_show(char *buffer, size_t nchars, gboolean is_from_se
case SHOW_EBCDIC:
/* If our native arch is ASCII, call: */
EBCDIC_to_ASCII((guint8*)buffer, (guint) nchars);
add_text(buffer, nchars, is_from_server);
add_text(buffer, nchars, is_from_server, packet_num);
break;
case SHOW_ASCII:
/* If our native arch is EBCDIC, call:
* ASCII_TO_EBCDIC(buffer, nchars);
*/
add_text(buffer, nchars, is_from_server);
add_text(buffer, nchars, is_from_server, packet_num);
break;
case SHOW_RAW:
/* Don't translate, no matter what the native arch
* is.
*/
add_text(buffer, nchars, is_from_server);
add_text(buffer, nchars, is_from_server, packet_num);
break;
case SHOW_HEXDUMP:
@ -634,16 +696,18 @@ FollowStreamDialog::follow_show(char *buffer, size_t nchars, gboolean is_from_se
*cur++ = '\n';
*cur = 0;
add_text(hexbuf, strlen(hexbuf), is_from_server);
add_text(hexbuf, strlen(hexbuf), is_from_server, packet_num);
}
break;
// We might want to add Python-compatible output (e.g. YAML) for the Scapy folks.
case SHOW_CARRAY:
current_pos = 0;
g_snprintf(initbuf, sizeof(initbuf), "char peer%d_%d[] = {\n",
g_snprintf(initbuf, sizeof(initbuf), "char peer%d_%d[] = { /* Packet %u */\n",
is_from_server ? 1 : 0,
is_from_server ? (*server_packet_count)++ : (*client_packet_count)++);
add_text(initbuf, strlen(initbuf), is_from_server);
is_from_server ? server_buffer_count_++ : client_buffer_count_++,
packet_num);
add_text(initbuf, strlen(initbuf), is_from_server, packet_num);
while (current_pos < nchars) {
gchar hexbuf[256];
@ -676,11 +740,28 @@ FollowStreamDialog::follow_show(char *buffer, size_t nchars, gboolean is_from_se
(*global_pos) += i;
hexbuf[cur++] = '\n';
hexbuf[cur] = 0;
add_text(hexbuf, strlen(hexbuf), is_from_server);
add_text(hexbuf, strlen(hexbuf), is_from_server, packet_num);
}
break;
}
if (last_packet_ == 0) {
last_from_server_ = is_from_server;
}
if (packet_num != last_packet_) {
last_packet_ = packet_num;
if (is_from_server) {
server_packet_count_++;
} else {
client_packet_count_++;
}
if (last_from_server_ != is_from_server) {
last_from_server_ = is_from_server;
turns_++;
}
}
return FRS_OK;
}
@ -1048,6 +1129,7 @@ bool FollowStreamDialog::follow(QString previous_filter, bool use_tcp_index)
follow_stream();
fillHintLabel(-1);
data_out_file = NULL;
@ -1086,8 +1168,6 @@ FollowStreamDialog::follow_read_tcp_stream()
guint16 client_port = 0;
gboolean is_server;
guint32 global_client_pos = 0, global_server_pos = 0;
guint32 server_packet_count = 0;
guint32 client_packet_count = 0;
guint32 *global_pos;
gboolean skip;
char buffer[FLT_BUF_SIZE+1]; /* +1 to fix ws bug 1043 */
@ -1100,7 +1180,6 @@ FollowStreamDialog::follow_read_tcp_stream()
int ret;
#endif
iplen = (follow_info_.is_ipv6) ? 16 : 4;
data_out_fp = ws_fopen(data_out_filename_.toUtf8().constData(), "rb");
@ -1134,8 +1213,7 @@ FollowStreamDialog::follow_read_tcp_stream()
if (follow_info_.show_stream == FROM_SERVER) {
skip = TRUE;
}
}
else {
} else {
is_server = TRUE;
global_pos = &global_server_pos;
if (follow_info_.show_stream == FROM_CLIENT) {
@ -1162,8 +1240,7 @@ FollowStreamDialog::follow_read_tcp_stream()
if (gunzip) {
/* show header (which is not gzipped)*/
frs_return = follow_show(buffer,
header_len, is_server, global_pos,
&server_packet_count, &client_packet_count);
header_len, is_server, sc.packet_num, global_pos);
if (frs_return == FRS_PRINT_ERROR) {
fclose(data_out_fp);
data_out_fp = NULL;
@ -1210,9 +1287,8 @@ FollowStreamDialog::follow_read_tcp_stream()
frs_return = follow_show(outbuffer,
FLT_BUF_SIZE-strm.avail_out, is_server,
global_pos,
&server_packet_count,
&client_packet_count);
sc.packet_num,
global_pos);
if(frs_return == FRS_PRINT_ERROR) {
inflateEnd(&strm);
fclose(data_out_fp);
@ -1226,9 +1302,7 @@ FollowStreamDialog::follow_read_tcp_stream()
if (!skip)
{
frs_return = follow_show(buffer,
nchars, is_server, global_pos,
&server_packet_count,
&client_packet_count);
nchars, is_server, sc.packet_num, global_pos);
if(frs_return == FRS_PRINT_ERROR) {
fclose(data_out_fp);
data_out_fp = NULL;
@ -1252,9 +1326,6 @@ FollowStreamDialog::follow_read_tcp_stream()
return FRS_OK;
}
/*
* XXX - the routine pointed to by "print_line_fcn_p" doesn't get handed lines,
* it gets handed bufferfuls. That's fine for "follow_write_raw()"
@ -1276,8 +1347,6 @@ frs_return_t
FollowStreamDialog::follow_read_udp_stream()
{
guint32 global_client_pos = 0, global_server_pos = 0;
guint32 server_packet_count = 0;
guint32 client_packet_count = 0;
guint32 *global_pos;
gboolean skip;
GList* cur;
@ -1285,7 +1354,6 @@ FollowStreamDialog::follow_read_udp_stream()
follow_record_t *follow_record;
char *buffer;
for (cur = follow_info_.payload; cur; cur = g_list_next(cur)) {
follow_record = (follow_record_t *)cur->data;
skip = FALSE;
@ -1309,9 +1377,8 @@ FollowStreamDialog::follow_read_udp_stream()
buffer,
follow_record->data->len,
follow_record->is_server,
global_pos,
&server_packet_count,
&client_packet_count);
follow_record->packet_num,
global_pos);
g_free(buffer);
if(frs_return == FRS_PRINT_ERROR)
return frs_return;

View File

@ -40,6 +40,7 @@
#include <QDialog>
#include <QFile>
#include <QMap>
#include <QPushButton>
extern "C" {
@ -89,6 +90,8 @@ private slots:
void findText(bool go_back = true);
void saveAs();
void printStream();
void fillHintLabel(int text_pos);
void goToPacketForTextPos(int text_pos);
void on_streamNumberSpinBox_valueChanged(int stream_num);
@ -96,14 +99,14 @@ private slots:
signals:
void updateFilter(QString &filter, bool force);
void goToPacket(int packet_num);
private:
void removeStreamControls();
void resetStream(void);
frs_return_t
follow_show(char *buffer, size_t nchars, gboolean is_from_server,
guint32 *global_pos, guint32 *server_packet_count,
guint32 *client_packet_count);
guint32 packet_num, guint32 *global_pos);
frs_return_t follow_read_stream();
frs_return_t follow_read_tcp_stream();
@ -112,7 +115,7 @@ private:
void follow_stream();
void add_text(char *buffer, size_t nchars, gboolean is_from_server);
void add_text(char *buffer, size_t nchars, gboolean is_from_server, guint32 packet_num);
Ui::FollowStreamDialog *ui;
@ -126,6 +129,14 @@ private:
follow_info_t follow_info_;
QString data_out_filename_;
QString filter_out_filter_;
int client_buffer_count_;
int server_buffer_count_;
int client_packet_count_;
int server_packet_count_;
guint32 last_packet_;
bool last_from_server_;
int turns_;
QMap<int,guint32> text_pos_to_packet_;
bool save_as_;
QFile file_;

View File

@ -6,7 +6,7 @@
<rect>
<x>0</x>
<y>0</y>
<width>750</width>
<width>594</width>
<height>620</height>
</rect>
</property>
@ -24,12 +24,19 @@
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QTextEdit" name="teStreamContent">
<widget class="FollowStreamText" name="teStreamContent">
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="hintLabel">
<property name="text">
<string>Hint.</string>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout" stretch="0,0,0,0,1,0,0">
<item>
@ -142,6 +149,13 @@
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>FollowStreamText</class>
<extends>QTextEdit</extends>
<header>follow_stream_text.h</header>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>

View File

@ -0,0 +1,64 @@
/* follow_stream_text.cpp
*
* $Id$
*
* 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 "follow_stream_text.h"
#include <QMouseEvent>
#include <QTextCursor>
FollowStreamText::FollowStreamText(QWidget *parent) :
QTextEdit(parent)
{
setMouseTracking(true);
}
void FollowStreamText::mouseMoveEvent(QMouseEvent *event)
{
emit mouseMovedToTextCursorPosition(cursorForPosition(event->pos()).position());
QTextEdit::mouseMoveEvent(event);
}
void FollowStreamText::mousePressEvent(QMouseEvent *event)
{
emit mouseClickedOnTextCursorPosition(cursorForPosition(event->pos()).position());
QTextEdit::mousePressEvent(event);
}
void FollowStreamText::leaveEvent(QEvent *event)
{
emit mouseMovedToTextCursorPosition(-1);
QTextEdit::leaveEvent(event);
}
/*
* 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:
*/

View File

@ -0,0 +1,62 @@
/* follow_stream_text.h
*
* $Id$
*
* 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 FOLLOW_STREAM_TEXT_H
#define FOLLOW_STREAM_TEXT_H
#include <QTextEdit>
class FollowStreamText : public QTextEdit
{
Q_OBJECT
public:
explicit FollowStreamText(QWidget *parent = 0);
protected:
void mouseMoveEvent(QMouseEvent *event);
void mousePressEvent(QMouseEvent *event);
void leaveEvent(QEvent *event);
signals:
// Perhaps this is not descriptive enough. We should add more words.
void mouseMovedToTextCursorPosition(int);
void mouseClickedOnTextCursorPosition(int);
public slots:
};
#endif // FOLLOW_STREAM_TEXT_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:
*/

View File

@ -1705,6 +1705,7 @@ void MainWindow::on_actionAnalyzePAFOrNotSelected_triggered()
void MainWindow::openFollowStreamDialog(follow_type_t type) {
FollowStreamDialog *fsd = new FollowStreamDialog(this, type, cap_file_);
connect(fsd, SIGNAL(updateFilter(QString&, bool)), this, SLOT(filterPackets(QString&, bool)));
connect(fsd, SIGNAL(goToPacket(int)), packet_list_, SLOT(goToPacket(int)));
fsd->follow(getFilter());
fsd->show();

View File

@ -127,6 +127,7 @@ SequenceDialog::SequenceDialog(QWidget *parent, capture_file *cf, SequenceType t
QPushButton *save_bt = ui->buttonBox->button(QDialogButtonBox::Save);
save_bt->setText(tr("Save As..."));
// XXX Use recent settings instead
if (parent) {
resize(parent->width(), parent->height() * 4 / 5);
}
@ -496,3 +497,16 @@ void SequenceDialog::on_actionMoveDown1_triggered()
{
panAxes(0, 1);
}
/*
* 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:
*/

View File

@ -106,3 +106,16 @@ private:
};
#endif // SEQUENCE_DIALOG_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:
*/