diff --git a/src/BinGrok.pro b/src/BinGrok.pro index 8824b00..cf169eb 100644 --- a/src/BinGrok.pro +++ b/src/BinGrok.pro @@ -19,8 +19,10 @@ SOURCES += \ txtdisplaywidget.cc \ structeditor.cc \ syntaxhighlighter.cc \ + datahighlighter.cc \ structtypes.cc \ - rd_parser.cc + rd_parser.cc \ + datavisualizer.cc HEADERS += \ bingrokwindow.h \ @@ -31,10 +33,13 @@ HEADERS += \ txtdisplaywidget.h \ structeditor.h \ syntaxhighlighter.h \ + datahighlighter.h \ structtypes.h \ - rd_parser.h + rd_parser.h \ + datavisualizer.h FORMS += \ bingrokwindow.ui \ preferences.ui \ - structeditor.ui + structeditor.ui \ + datavisualizer.ui diff --git a/src/bingrokwindow.cc b/src/bingrokwindow.cc index 2d938e6..2d057d5 100644 --- a/src/bingrokwindow.cc +++ b/src/bingrokwindow.cc @@ -78,7 +78,7 @@ void BinGrokWindow::read_settings() s.beginGroup("window"); resize(s.value("size", QSize(400,400)).toSize()); move(s.value("position", QPoint(200,200)).toPoint()); - max_recently_open = s.value("max_recently_open", 8).toInt(); + max_recently_open = static_cast(s.value("max_recently_open", 8).toUInt()); recently_open = s.value("recently_open").toStringList(); @@ -88,19 +88,20 @@ void BinGrokWindow::read_settings() void BinGrokWindow::open() { QString filename = QFileDialog::getOpenFileName(this); - if (!filename.isEmpty()) - hexwidget->open(filename); + if (!filename.isEmpty()) + open_file(filename); } void BinGrokWindow::open_file(const QString &f) { + has_open_file = true; hexwidget->open(f); } void BinGrokWindow::open_recent() { QAction *a = qobject_cast(sender()); - if (a) hexwidget->open(a->data().toString()); + if (a) open_file(a->data().toString()); } void BinGrokWindow::new_file() @@ -115,7 +116,7 @@ void BinGrokWindow::save() qDebug("save() called"); #endif /* - if bghexwidget contents is empty: + if bghexwidget contents is empty:test return saveAs(); else return save_file(current file); @@ -167,10 +168,18 @@ void BinGrokWindow::show_preferences() void BinGrokWindow::show_struct_editor() { - if (structeditor_ui == NULL) { - structeditor_ui = new StructEditor(this); + if (!has_open_file) { + if (error_window == nullptr) + error_window = new QMessageBox(); + error_window->setWindowTitle("Error"); + error_window->setText("Can't edit datastructure when there is no file open!"); + error_window->show(); + } else { + if (structeditor_ui == NULL) { + structeditor_ui = new StructEditor(this); + } + structeditor_ui->show(); } - structeditor_ui->show(); } void BinGrokWindow::save_preferences() diff --git a/src/bingrokwindow.h b/src/bingrokwindow.h index 522b274..bbe9861 100644 --- a/src/bingrokwindow.h +++ b/src/bingrokwindow.h @@ -3,6 +3,7 @@ #include #include +#include #include "hexwidget.h" class QString; @@ -39,6 +40,8 @@ class BinGrokWindow : public QMainWindow QHBoxLayout *layout; quint8 max_recently_open; QStringList recently_open; + bool has_open_file = false; + QMessageBox *error_window = nullptr; void read_settings(); bool save_file(const QString & filename); diff --git a/src/datahighlighter.cc b/src/datahighlighter.cc new file mode 100644 index 0000000..0b25723 --- /dev/null +++ b/src/datahighlighter.cc @@ -0,0 +1,53 @@ +#include "datahighlighter.h" + +#include +#include +#include +#include + +#define BOUNDARY(s) ("\\b" s "\\b") + +DataHighlighter::DataHighlighter(QTextDocument *parent) : + QSyntaxHighlighter (parent) +{ + + QTextCharFormat string_format, ident_format, integer_format; + + string_format.setForeground(Qt::darkBlue); + + highlighting_rules.append({ + QRegExp("\".*\";"), + string_format + }); + + ident_format.setForeground(Qt::blue); + ident_format.setFontItalic(true); + + highlighting_rules.append({ + QRegExp(".+(?=:)"), + ident_format + }); + + integer_format.setForeground(Qt::black); + integer_format.setFontWeight(QFont::Bold); + highlighting_rules.append({ + QRegExp("\\d+"), + integer_format + }); + +} + +void DataHighlighter::highlightBlock(const QString &text) +{ + foreach (const HighlightingRule &rule, highlighting_rules) { + QRegExp expression(rule.pattern); + int index = expression.indexIn(text); + while (index >= 0) { + int length = expression.matchedLength(); + setFormat(index, length, rule.format); + index = expression.indexIn(text, index + length); + } + } + + setCurrentBlockState(0); +} diff --git a/src/datahighlighter.h b/src/datahighlighter.h new file mode 100644 index 0000000..87a496b --- /dev/null +++ b/src/datahighlighter.h @@ -0,0 +1,32 @@ +#ifndef DATAHIGHLIGHTER_H +#define DATAHIGHLIGHTER_H + +#include +#include +#include +#include +#include +#include + + +class DataHighlighter : public QSyntaxHighlighter +{ + Q_OBJECT + +public: + DataHighlighter(QTextDocument *parent=0); + +protected: + void highlightBlock(const QString &text) Q_DECL_OVERRIDE; + +private: + struct HighlightingRule + { + QRegExp pattern; + QTextCharFormat format; + }; + + QVector highlighting_rules; +}; + +#endif // DATAHIGHLIGHTER_H diff --git a/src/datavisualizer.cc b/src/datavisualizer.cc new file mode 100644 index 0000000..89b6254 --- /dev/null +++ b/src/datavisualizer.cc @@ -0,0 +1,25 @@ +#include "datavisualizer.h" +#include "ui_datavisualizer.h" + +DataVisualizer::DataVisualizer(QWidget *parent) : + QDialog(parent), + ui(new Ui::DataVisualizer) +{ + ui->setupUi(this); + ui->status_panel->setPlainText("test"); + highlighter = new DataHighlighter(ui->text_display->document()); + connect(ui->buttonBox, SIGNAL(accepted()), this, SLOT(close())); +} + +DataVisualizer::~DataVisualizer() +{ + delete ui; +} + +void DataVisualizer::visualize(Struct *s) +{ + if (current_data != nullptr) + delete current_data; + current_data = s; + ui->text_display->setText(s->to_string()); +} diff --git a/src/datavisualizer.h b/src/datavisualizer.h new file mode 100644 index 0000000..4fca909 --- /dev/null +++ b/src/datavisualizer.h @@ -0,0 +1,27 @@ +#ifndef DATAVISUALIZER_H +#define DATAVISUALIZER_H + +#include +#include "structtypes.h" +#include "datahighlighter.h" + +namespace Ui { +class DataVisualizer; +} + +class DataVisualizer : public QDialog +{ + Q_OBJECT + +public: + explicit DataVisualizer(QWidget *parent = 0); + ~DataVisualizer(); + void visualize(Struct *s); + +private: + Ui::DataVisualizer *ui; + Struct *current_data = nullptr; + DataHighlighter *highlighter; +}; + +#endif // DATAVISUALIZER_H diff --git a/src/datavisualizer.ui b/src/datavisualizer.ui new file mode 100644 index 0000000..a0cd9ef --- /dev/null +++ b/src/datavisualizer.ui @@ -0,0 +1,84 @@ + + + DataVisualizer + + + + 0 + 0 + 584 + 372 + + + + BinGrok :: Data Visualizer + + + + + + + 3 + 0 + + + + + + + + + 1 + 0 + + + + + + + Qt::Vertical + + + QDialogButtonBox::Ok + + + + + + + + 0 + 1 + + + + + 0 + 0 + + + + Qt::NoFocus + + + Qt::NoContextMenu + + + false + + + false + + + Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse + + + + + + + + + + + diff --git a/src/hexwidget.cc b/src/hexwidget.cc index 9ca9e49..1b5f964 100644 --- a/src/hexwidget.cc +++ b/src/hexwidget.cc @@ -22,7 +22,7 @@ HexWidget::HexWidget(QWidget *parent) : QWidget(parent),file(NULL),seek_to(0), - columns(20),rows(20),sel(NULL), + columns(20),rows(20),sel(new Selection(0, 0)), grokked(new Selection(0, 0)), txtdisplay(NULL), mouse_down(false) { scroll_timer = new QTimer(this); @@ -85,7 +85,14 @@ bool HexWidget::open(const QString & filename) emit file_opened(file); trigger_resizeEvent(); + + sel->resize(columns, file->size()); + grokked->resize(columns, file->size()); + txtdisplay->set_selection(sel); + txtdisplay->set_grokked(grokked); + update(); + return true; } @@ -241,13 +248,9 @@ void HexWidget::selection(QMouseEvent *e, bool new_selection=false) return; if (new_selection) { - if (sel != NULL) { - delete sel; - sel = NULL; - txtdisplay->set_selection(NULL); - } - sel = new Selection(columns, file->size()); - txtdisplay->set_selection(sel); + if (sel->is_active()) + sel->reset(); + sel->start(xy_to_grid(e), seek_to); } else { sel->end(xy_to_grid(e), seek_to); @@ -273,6 +276,18 @@ void HexWidget::drag_scroll() } } +void HexWidget::highlight(quint64 start_tell,quint64 end_tell) +{ + grokked->select(start_tell, end_tell); + update(); +} + +void HexWidget::reset_highlight() +{ + grokked->reset(); + update(); +} + /****************************************************************************** * * Overrides @@ -285,7 +300,6 @@ void HexWidget::paintEvent(QPaintEvent *e) painter.setFont(font()); QPalette palette = QApplication::palette(this); - painter.setPen(palette.foreground().color()); painter.setBackgroundMode(Qt::OpaqueMode); quint32 i = 0; @@ -294,19 +308,20 @@ void HexWidget::paintEvent(QPaintEvent *e) QString word = get_dataword(i); i += bytes_per_column; - if (sel != NULL) { - if (sel->in_range(c, r, seek_to)) { - painter.setBackground(palette.link()); - painter.setPen(palette.brightText().color()); - } else { - painter.setBackground(palette.base()); - painter.setPen(palette.foreground().color()); - } - } + // put selection first so that you can "see" it over the grokked bytes + if (sel->is_active() && sel->in_range(c, r, seek_to)) { + painter.setBackground(palette.link()); + painter.setPen(palette.brightText().color()); + } else if (grokked->is_active() && grokked->in_range(c, r, seek_to)) { + painter.setBackground(palette.highlight()); + painter.setPen(palette.brightText().color()); + } else { + painter.setBackground(palette.base()); + painter.setPen(palette.foreground().color()); + } painter.drawText(c*col_width, r*row_height, col_width, row_height, Qt::AlignLeft, - word - ); + word); } } } @@ -328,6 +343,8 @@ void HexWidget::resizeEvent(QResizeEvent *e) bytes_per_page = bytes_per_line() * rows; scroll_lines = ((file->size() - bytes_per_page) / bytes_per_line()) + 1; scrollbar->setRange(0, scroll_lines); + sel->resize(columns); + grokked->resize(columns); } } @@ -344,10 +361,8 @@ void HexWidget::wheelEvent(QWheelEvent *e) void HexWidget::mousePressEvent(QMouseEvent *e) { if (e->button() == Qt::LeftButton) { - if (sel != NULL) { - delete sel; - sel = NULL; - txtdisplay->set_selection(NULL); + if (sel->is_active()) { + sel->reset(); update(); } mouse_down = true; @@ -359,7 +374,7 @@ void HexWidget::mouseReleaseEvent(QMouseEvent *e) { if (e->button() == Qt::LeftButton) { mouse_down = false; - if (sel != NULL) { + if (sel->is_active()) { selection(e, false); scroll_timer->stop(); update(); @@ -370,11 +385,10 @@ void HexWidget::mouseReleaseEvent(QMouseEvent *e) void HexWidget::mouseMoveEvent(QMouseEvent *e) { - if (sel == NULL && mouse_down) { + if (!sel->is_active() && mouse_down) { selection(e, true); - } else if (sel != NULL && mouse_down) { - sel->end(xy_to_grid(e), seek_to); - update(); + } else if (sel->is_active() && mouse_down) { + selection(e, false); e->accept(); /* if moved below or above widget bounds diff --git a/src/hexwidget.h b/src/hexwidget.h index 00a8c5c..0ca2e39 100644 --- a/src/hexwidget.h +++ b/src/hexwidget.h @@ -55,6 +55,7 @@ class HexWidget : public QWidget QByteArray viewport_data; TrTable trtable; Selection *sel; + Selection *grokked; QPoint mouse_position; QTimer *scroll_timer; QScrollBar *scrollbar; @@ -86,7 +87,8 @@ public slots: void scroll_changed(int i); void drag_scroll(); void update(); - + void highlight(quint64 start_tell, quint64 end_tell); + void reset_highlight(); }; #endif // BGHEXWIDGET_H diff --git a/src/selection.cc b/src/selection.cc index b9cfb62..5b2c498 100644 --- a/src/selection.cc +++ b/src/selection.cc @@ -9,11 +9,13 @@ void Selection::start(int x, int y, quint64 tell) { start_offset = xy_to_offset(x, y, tell); end_offset = start_offset; + active = true; } void Selection::end(int x, int y, quint64 tell) { end_offset = xy_to_offset(x, y, tell); + active = true; } quint64 Selection::xy_to_offset(int x, int y, quint64 tell) @@ -39,3 +41,22 @@ bool Selection::in_range(int x, int y, quint64 tell) if (test >= s && test <= e) return true; return false; } + +bool Selection::in_range(quint64 tell) +{ + quint64 s = start_offset; + quint64 e = end_offset; + + if (tell >= size) return false; // can't select outside of file size + + /* user was selecting 'up' instead of 'down' */ + if (e < s) { + quint64 tmp = s; + s = e; + e = tmp; + } + + if (tell >= s && tell <= e) return true; + return false; + +} diff --git a/src/selection.h b/src/selection.h index 7621656..4d788d4 100644 --- a/src/selection.h +++ b/src/selection.h @@ -6,19 +6,30 @@ class Selection { public: - Selection(uint columns, quint64 size) : columns(columns),size(size) {} + Selection(uint columns, quint64 size) : columns(columns),size(size) { reset(); } + + void resize(uint c) { columns = c; } + void resize(uint c, quint64 s) { size = s; resize(c); } + void reset() { start_offset = end_offset = 0; active = false;} void start(int x, int y, quint64 tell); void start(QPoint p, quint64 tell) { start(p.x(), p.y(), tell); } + void start(quint64 tell) { start_offset = tell; active = true; } void end(int x, int y, quint64 tell); void end(QPoint p, quint64 tell) { end(p.x(), p.y(), tell); } + void end(quint64 tell) { end_offset = tell; active = true;} + + void select(quint64 s, quint64 e) { start(s); end(e); active=true; } bool in_range(int x, int y, quint64 tell); + bool in_range(quint64 tell); + bool is_active() { return active; } private: uint columns; quint64 start_offset, end_offset, size; + bool active = false; quint64 xy_to_offset(int x, int y, quint64 tell); }; diff --git a/src/structeditor.cc b/src/structeditor.cc index e55fb1b..3f0dcff 100644 --- a/src/structeditor.cc +++ b/src/structeditor.cc @@ -4,6 +4,8 @@ #include "bingrokwindow.h" #include "rd_parser.h" #include "structtypes.h" +#include "datavisualizer.h" +#include "hexwidget.h" #include #include @@ -21,12 +23,14 @@ StructEditor::StructEditor(QWidget *parent) : { ui->setupUi(this); highlighter = new SyntaxHighlighter(ui->struct_textedit->document()); + hex_display = static_cast(parent)->get_hexwidget(); QPushButton *apply_button = ui->buttonBox->button(QDialogButtonBox::Apply); connect(apply_button, SIGNAL(clicked()), this, SLOT(apply_struct())); connect(ui->buttonBox, SIGNAL(accepted()), this, SLOT(close_and_apply())); connect(ui->buttonBox, SIGNAL(rejected()), this, SLOT(close())); + connect(this, &StructEditor::struct_applied, hex_display, &HexWidget::highlight); } StructEditor::~StructEditor() @@ -35,6 +39,15 @@ StructEditor::~StructEditor() delete error_window; } +void StructEditor::show_datavisualizer(Struct *s) +{ + if (dv == nullptr) + dv = new DataVisualizer(this); + + dv->visualize(s); + dv->show(); +} + void StructEditor::close_and_apply() { apply_struct(); @@ -45,12 +58,16 @@ void StructEditor::apply_struct() { QString data = ui->struct_textedit->document()->toPlainText(); RDParser r; - Struct *s; + Struct *s = nullptr; + quint64 start_offset = ui->start_at->text().toLong(); + const char *d = nullptr; + try { s = r.parse(data); - - const char *d = static_cast(parent())->get_hexwidget()->read_bytes(ui->start_at->text().toLong(), s->record_length()); + d = hex_display->read_bytes(start_offset, s->record_length()); s->populate(d); + show_datavisualizer(s); + emit struct_applied(start_offset, s->record_length()); } catch (RDParser::ParserException &e) { error_window->setWindowTitle("Parse Error"); error_window->setWindowFlags(Qt::WindowStaysOnTopHint); diff --git a/src/structeditor.h b/src/structeditor.h index 6981183..cfe088b 100644 --- a/src/structeditor.h +++ b/src/structeditor.h @@ -4,7 +4,9 @@ #include #include #include +#include "hexwidget.h" #include "syntaxhighlighter.h" +#include "datavisualizer.h" #include "structtypes.h" namespace Ui { @@ -22,13 +24,20 @@ class StructEditor : public QDialog private: Ui::StructEditor *ui; SyntaxHighlighter *highlighter; + DataVisualizer *dv = nullptr; QList structs; QMessageBox *error_window; + HexWidget *hex_display; + + void show_datavisualizer(Struct *s); public slots: void apply_struct(); void close_and_apply(); //void close(); + +signals: + void struct_applied(quint64 start, quint64 end); }; #endif // STRUCTEDITOR_H diff --git a/src/structtypes.cc b/src/structtypes.cc index 4d56d7b..339f881 100644 --- a/src/structtypes.cc +++ b/src/structtypes.cc @@ -1,10 +1,11 @@ +#include +#include #include "structtypes.h" -QString StructStatement::get_name() -{ - return name; -} +/******************************************* + * StructStatement + * *****************************************/ void StructStatement::alloc() { data = new char[record_length()](); @@ -17,6 +18,24 @@ void StructStatement::set_data(const char *d) std::memcpy(data, d, record_length()); } +/******************************************* + * Struct + * *****************************************/ +QString Struct::to_string(int indent_level) +{ + QString out; + QString indent(indent_level, ' '); + QTextStream writer(&out); + + writer << indent << name << " {" << endl; + + for (auto it = statements.begin(); it != statements.end(); it++) { + writer << indent << (*it)->to_string(indent_level+1); + } + writer << indent << "};" << endl; + return out; +} + void Struct::populate(const char * const d) { char *ptr = const_cast(d); @@ -32,19 +51,31 @@ void Struct::populate(const char * const d) } } - -QString NumericStatement::get_name() +/******************************************* + * NumericStatement + * *****************************************/ +QString NumericStatement::to_string(int indent_level) { - return name; -} + QString out; + QString indent(indent_level, ' '); + QTextStream writer(&out); + QString formatted_data(QByteArray(data, record_length())); -QString StringStatement::get_name() -{ - return name; + writer << indent << name << ": " << formatted_data << ";" << endl; + return out; } -QString Struct::get_name() +/******************************************* + * StringStatement + * *****************************************/ +QString StringStatement::to_string(int indent_level) { - return name; + QString out; + QString indent(indent_level, ' '); + QTextStream writer(&out); + QString formatted_data(QByteArray(data, record_length())); + + writer << indent << name << ": \"" << formatted_data << "\";" << endl; + return out; } diff --git a/src/structtypes.h b/src/structtypes.h index 7630f99..cf21b70 100644 --- a/src/structtypes.h +++ b/src/structtypes.h @@ -13,11 +13,11 @@ class StructStatement StructStatement() {} StructStatement(QString n, QString t) : name(n), type(t) {} - virtual ~StructStatement() {} - virtual QString get_name(); + virtual ~StructStatement() { if (data != nullptr) delete data;} unsigned int virtual record_length() { return 0; } void alloc(); - void set_data(const char *d); + virtual void set_data(const char *d); + virtual QString to_string(int indent_level=0) { return ""; } }; class NumericStatement : public StructStatement @@ -28,7 +28,7 @@ class NumericStatement : public StructStatement NumericStatement() : StructStatement() {} NumericStatement(QString n, QString t) : StructStatement(n, t) { } - virtual QString get_name(); + virtual QString to_string(int indent_level=0); unsigned int record_length() { return precision; } }; @@ -40,7 +40,7 @@ class StringStatement : public StructStatement StringStatement() : StructStatement() {} StringStatement(QString n, QString t) : StructStatement(n, t) { } - virtual QString get_name(); + virtual QString to_string(int indent_level=0); unsigned int record_length() { return (length_bytes); } }; @@ -52,7 +52,7 @@ class Struct : public StructStatement Struct() : StructStatement() {} Struct(QString n, QString t) : StructStatement(n, t) { } virtual ~Struct() { for (auto it = statements.begin(); it != statements.end(); it++) delete *it; } - virtual QString get_name(); + virtual QString to_string(int indent_level=0); void populate(const char *d); unsigned int record_length() { unsigned int s = 0; for (auto it = statements.begin(); it != statements.end(); it++) s += (*it)->record_length(); return s;} }; diff --git a/src/syntaxhighlighter.cc b/src/syntaxhighlighter.cc index 203c8d5..7a4c2fc 100644 --- a/src/syntaxhighlighter.cc +++ b/src/syntaxhighlighter.cc @@ -5,7 +5,7 @@ #include #include -#define RE_B(s) ("\\b" s "\\b") +#define BOUNDARY(s) ("\\b" s "\\b") SyntaxHighlighter::SyntaxHighlighter(QTextDocument *parent) : QSyntaxHighlighter (parent) @@ -16,8 +16,7 @@ SyntaxHighlighter::SyntaxHighlighter(QTextDocument *parent) : keyword_format.setFontWeight(QFont::Bold); QStringList keyword_patterns; - keyword_patterns << RE_B("int") << RE_B("uint") << RE_B("struct") - << RE_B("array") << RE_B("string") << RE_B("float"); + keyword_patterns << BOUNDARY("int") << BOUNDARY("uint") << BOUNDARY("struct") << BOUNDARY("array") << BOUNDARY("string"); foreach (const QString &pattern, keyword_patterns) { rule.pattern = QRegExp(pattern); @@ -25,12 +24,13 @@ SyntaxHighlighter::SyntaxHighlighter(QTextDocument *parent) : highlighting_rules.append(rule); } - integer_format.setForeground(Qt::cyan); + integer_format.setForeground(Qt::black); + integer_format.setFontWeight(QFont::Bold); rule.pattern = QRegExp("[0-9]+"); rule.format = integer_format; highlighting_rules.append(rule); - single_line_comment_format.setForeground(Qt::red); + single_line_comment_format.setForeground(Qt::gray); rule.pattern = QRegExp("//[^\n]*"); rule.format = single_line_comment_format; highlighting_rules.append(rule); diff --git a/src/txtdisplaywidget.cc b/src/txtdisplaywidget.cc index 63ba280..c07c5cc 100644 --- a/src/txtdisplaywidget.cc +++ b/src/txtdisplaywidget.cc @@ -56,6 +56,11 @@ void TxtDisplayWidget::set_selection(Selection *s) sel = s; } +void TxtDisplayWidget::set_grokked(Selection *s) +{ + grokked = s; +} + void TxtDisplayWidget::set_seek_to(qint64 *st) { seek_to = st; @@ -124,14 +129,15 @@ void TxtDisplayWidget::paintEvent(QPaintEvent *e) for (int c = 0; c < columns; c++) { QString word = get_dataword(i++); - if (sel != NULL) { - if (sel->in_range(c, r, *seek_to)) { - painter.setBackground(palette.link()); - painter.setPen(palette.brightText().color()); - } else { - painter.setBackground(palette.base()); - painter.setPen(palette.foreground().color()); - } + if (sel != nullptr && sel->is_active() && sel->in_range(c, r, *seek_to)) { + painter.setBackground(palette.link()); + painter.setPen(palette.brightText().color()); + } else if (grokked != nullptr && grokked->is_active() && grokked->in_range(c, r, *seek_to)) { + painter.setBackground(palette.highlight()); + painter.setPen(palette.brightText().color()); + } else { + painter.setBackground(palette.base()); + painter.setPen(palette.foreground().color()); } painter.drawText(c*col_width, r*row_height, col_width, row_height, Qt::AlignLeft, word); diff --git a/src/txtdisplaywidget.h b/src/txtdisplaywidget.h index 09adc8c..056c7c9 100644 --- a/src/txtdisplaywidget.h +++ b/src/txtdisplaywidget.h @@ -24,8 +24,9 @@ class TxtDisplayWidget : public QWidget int col_width; int row_height; TrTable *trtable; - Selection *sel; - qint64 *seek_to; + Selection *sel = nullptr; + Selection *grokked = nullptr; + qint64 *seek_to; void trigger_resizeEvent(); void update_grid_sizes(); @@ -34,6 +35,7 @@ class TxtDisplayWidget : public QWidget void set_viewport_data(QByteArray *v); void set_trtable(TrTable *t); void set_selection(Selection *s); + void set_grokked(Selection *s); void set_seek_to(qint64 *st); void read_settings();