Add Search and Documentation for trkConvert (#646)

* Add Export of variable list to file.

* Create DocWindow:formattedSave, and implement saveAsCSV etc in terms of it.

* Minor spacing changes

* Add text text UI parts to DocWindow.

* Add foreward and reverse search by pattern.

* Document and configuration for Mac.
This commit is contained in:
jmpenn 2018-07-13 13:43:03 -05:00 committed by GitHub
parent 8a4c8e3dd9
commit b0b0cdf21b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 223 additions and 67 deletions

View File

@ -3,6 +3,7 @@
#include <QMenuBar>
#include <QPushButton>
#include <QVBoxLayout>
#include <QLineEdit>
#include <QWidget>
#include <iostream>
@ -11,52 +12,89 @@
#include "DocWindow.h"
#include "VarTableWidget.h"
#include "CSV_Formatter.hh"
#include "Varlist_Formatter.hh"
// Notes:
// Need to be able to search for a variable by pattern.
// Use a QLineEdit widget for the text box.
DocWindow::DocWindow(const QString &name)
: QMainWindow( 0, 0) {
trkFileName = name;
QTextStream out(stdout);
// Build the Menus
QAction * fileLoadAction = new QAction( "&Open File...", this );
fileLoadAction->setShortcut(tr("CTRL+O"));
connect( fileLoadAction, &QAction::triggered , this, &DocWindow::load );
foundItemIndex = 0;
QAction * fileSaveAction = new QAction( "&Export as CSV...", this );
connect( fileSaveAction, &QAction::triggered, this, &DocWindow::saveAsCSV );
trkFileName = name;
QMenu *fileMenu = menuBar()->addMenu("&File");
// Build the Menus
QAction * fileLoadAction = new QAction( "&Open File...", this );
fileLoadAction->setShortcut(tr("CTRL+O"));
connect( fileLoadAction, &QAction::triggered , this, &DocWindow::load );
fileMenu->addAction(fileLoadAction);
fileMenu->addSeparator();
fileMenu->addAction(fileSaveAction);
QAction * csvSaveAction = new QAction( "&Export as CSV...", this );
connect( csvSaveAction, &QAction::triggered, this, &DocWindow::saveAsCSV );
QAction * editSelectAction = new QAction( "&Select All", this );
editSelectAction->setShortcut(tr("CTRL+A"));
connect( editSelectAction, &QAction::triggered, this, &DocWindow::checkAll );
QAction * varListSaveAction = new QAction( "&Export as Variable List...", this );
connect( varListSaveAction, &QAction::triggered, this, &DocWindow::saveAsVarList );
QAction * editClearAction = new QAction( "&Clear All", this );
connect( editClearAction, &QAction::triggered, this, &DocWindow::unCheckAll );
QMenu *fileMenu = menuBar()->addMenu("&File");
QMenu *editMenu = menuBar()->addMenu("&Edit");
editMenu->addAction(editSelectAction);
editMenu->addAction(editClearAction);
fileMenu->addAction(fileLoadAction);
fileMenu->addSeparator();
fileMenu->addAction(csvSaveAction);
fileMenu->addAction(varListSaveAction);
// Build the Table Widget that displays the variable names, types, and units.
varTable = new VarTableWidget(this);
QAction * editSelectAction = new QAction( "&Select All", this );
editSelectAction->setShortcut(tr("CTRL+A"));
connect( editSelectAction, &QAction::triggered, this, &DocWindow::checkAll );
datalog = new TRK_DataLog( trkFileName.toStdString().c_str() );
int recordCount = datalog->parameterCount();
for (int ii = 0; ii < recordCount; ii++) {
varTable->addRecord( Qt::Checked,
datalog->parameterName(ii),
datalog->parameterType(ii),
datalog->parameterUnits(ii));
}
QAction * editClearAction = new QAction( "&Clear All", this );
connect( editClearAction, &QAction::triggered, this, &DocWindow::unCheckAll );
setCentralWidget(varTable);
QMenu *editMenu = menuBar()->addMenu("&Edit");
editMenu->addAction(editSelectAction);
editMenu->addAction(editClearAction);
QHBoxLayout *hbox = new QHBoxLayout();
QPushButton *backward = new QPushButton(QChar(0x25C0), this);
connect( backward, &QPushButton::released, this, &DocWindow::findAgainBackward);
QPushButton *forward = new QPushButton(QChar(0x25B6), this);
connect( forward, &QPushButton::released, this, &DocWindow::findAgainForward);
searchLineEdit = new QLineEdit;
searchLineEdit->setPlaceholderText("Search Pattern");
connect(searchLineEdit, SIGNAL(returnPressed()), this, SLOT(find()));
hbox->addWidget(backward);
hbox->addWidget(forward);
hbox->addWidget(searchLineEdit);
QVBoxLayout *vbox = new QVBoxLayout();
// Build the Table Widget that displays the variable names, types, and units.
varTable = new VarTableWidget(this);
datalog = new TRK_DataLog( trkFileName.toStdString().c_str() );
int recordCount = datalog->parameterCount();
for (int ii = 0; ii < recordCount; ii++) {
varTable->addRecord( Qt::Checked,
datalog->parameterName(ii),
datalog->parameterType(ii),
datalog->parameterUnits(ii));
}
vbox->addWidget(varTable);
vbox->addLayout(hbox);
QWidget *window = new QWidget;
window->setLayout(vbox);
setCentralWidget(window);
}
void DocWindow::load() {
@ -74,32 +112,41 @@ void DocWindow::load() {
}
}
void DocWindow::saveAsCSV() {
void DocWindow::formattedSave(LogFormatter &formatter) {
QTextStream out(stdout);
CSV_Formatter csv_formatter;
QFileInfo trkFileInfo( trkFileName);
QString csvFileName = trkFileInfo.canonicalPath();
csvFileName += "/";
csvFileName += trkFileInfo.completeBaseName();
csvFileName += csv_formatter.extension();
out << "csvFileName = \"" << csvFileName << "\"" << endl;
QString outFileName = trkFileInfo.canonicalPath();
outFileName += "/";
outFileName += trkFileInfo.completeBaseName();
outFileName += formatter.extension();
QTextStream out(stdout);
out << "outFileName = \"" << outFileName << "\"" << endl;
int count = varTable->recordCount();
for (int index=0 ; index<count ; index++) {
if (varTable->isChecked(index)) {
datalog->selectParameter(index);
}
} else {
datalog->deselectParameter(index);
}
}
FILE *fp;
if (( fp = fopen(csvFileName.toStdString().c_str(), "w") ) != NULL) {
datalog->formattedWrite(fp, &csv_formatter);
if (( fp = fopen(outFileName.toStdString().c_str(), "w") ) != NULL) {
datalog->formattedWrite(fp, &formatter);
}
}
void DocWindow::saveAsCSV() {
CSV_Formatter csv_formatter;
formattedSave(csv_formatter);
}
void DocWindow::saveAsVarList() {
Varlist_Formatter varlist_formatter;
formattedSave(varlist_formatter);
}
void DocWindow::checkAll() {
@ -109,3 +156,50 @@ void DocWindow::checkAll() {
void DocWindow::unCheckAll() {
varTable->unCheckAll();
}
void DocWindow::findAgain(int direction) {
if (foundItemIndex >= 0) {
varTable->unHighLightRecord(foundItemIndex);
int count = varTable->recordCount();
int startIndex = (count + foundItemIndex + direction) % count;
if ((foundItemIndex = textSearch(searchPattern, startIndex, direction)) >= 0) {
varTable->scrollToRecord(foundItemIndex);
varTable->highLightRecord(foundItemIndex);
}
}
}
void DocWindow::findAgainForward() {
findAgain(1);
}
void DocWindow::findAgainBackward() {
findAgain(-1);
}
void DocWindow::find() {
searchPattern = searchLineEdit->text();
if (foundItemIndex >= 0) {
varTable->unHighLightRecord(foundItemIndex);
}
if ((foundItemIndex = textSearch(searchPattern, 0, 1)) >= 0) {
varTable->scrollToRecord(foundItemIndex);
varTable->highLightRecord(foundItemIndex);
}
}
int DocWindow::textSearch(QString pattern, int startIndex, int direction) {
QRegExp rx(pattern);
int count = varTable->recordCount();
int foundIx = -1;
for (int i=0 ; i<count ; i++) {
int index = (count + startIndex + direction * i) % count;
if ((rx.indexIn(datalog->parameterName(index),0)) >= 0) {
foundIx = index;
break;
}
}
return foundIx;
}

View File

@ -13,14 +13,27 @@ class DocWindow : public QMainWindow {
DocWindow(const QString &name);
~DocWindow(){};
void formattedSave(LogFormatter &formatter);
void textSearch();
int textSearch(QString searchText, int startIndex, int direction);
void findAgain(int direction);
private slots:
void load();
void saveAsCSV();
void saveAsVarList();
void checkAll();
void unCheckAll();
void find();
void findAgainForward();
void findAgainBackward();
private:
QString searchPattern;
int foundItemIndex;
QString trkFileName;
QLineEdit* searchLineEdit;
VarTableWidget* varTable;
TRK_DataLog* datalog;
};

View File

@ -0,0 +1,49 @@
# trkConvert
Convert selected sets of variables in Trick binary data recording files (.trk) to comma separated values (.csv). In the future, more formats may be added as needed.
## Building trkConvert
trkConvert requires the [Qt Application Framework](https://www.qt.io).
When Qt is installed, building the application is as simple as:
```
% qmake
% make
% cp trkConvert $TRICK_HOME/bin/trkConvert
```
## Running trkConvert
**% trkConvert [name.trk] &**
```
% trkConvert &
```
![fileSelectDialog](images/fileSelectDialog.png)
```
% trkConvert log_helios.trk &
```
The resulting window displays the names, data types and units of the variables recorded in the .trk file. The check marks, to the left indicate which variables would be recorded in an exported format.
![x](images/DocWindow.png)
The check boxes can be individually selected and cleared with a mouse-click.
They can be collectively selected and cleared from the Edit menu.
![x](images/DocWindow2.png)
## Variable Search
Python-like regular expressions
A search pattern is Python-like regular expression that matches any part of a variable name. To search, type the pattern, and press **Return** or **Enter**.
Subsequent searches for the pattern can be performed using the arrow buttons.
* Right arror searches forward
* Left arrow searches backward.
## Exporting Selected Values
Export selected values to CSV, or other format from the **File** menu.

View File

@ -66,6 +66,20 @@ void VarTableWidget::addRecord( Qt::CheckState checkState,
}
void VarTableWidget::highLightRecord(int index) {
QBrush brush(Qt::yellow);
item(index, 1)->setBackground(brush);
}
void VarTableWidget::unHighLightRecord(int index) {
QBrush brush(Qt::white);
item(index, 1)->setBackground(brush);
}
void VarTableWidget::scrollToRecord(int index) {
scrollToItem(item(index, 0));
}
bool VarTableWidget::isChecked(int index) {
return (item(index, 0)->checkState() == Qt::Checked) ? true : false;
}

View File

@ -14,6 +14,9 @@ class VarTableWidget : public QTableWidget {
void addRecord( Qt::CheckState checkState, std::string name, std::string type, std::string units );
bool isChecked(int index);
int recordCount();
void scrollToRecord(int index);
void highLightRecord(int index);
void unHighLightRecord(int index);
public slots:
void checkAll();

Binary file not shown.

After

Width:  |  Height:  |  Size: 157 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 149 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 101 KiB

View File

@ -13,14 +13,9 @@ static const char *usage_doc[] = {
" trkConvert - ",
" ",
" USAGE: trkConvert -help ",
" trkConvert [-csv|-varlist] [-o <outfile>] <trk_file_name> ",
" trkConvert <trk_file_name> ",
" Options: ",
" -help Print this message and exit. ",
" -csv (the default) Generates a comma-separated value (CSV) file from ",
" a Trick binary data file. CSV files are a common ",
" means of sharing data between applications. ",
" -varlist Generates a list of the names of the variables ",
" the are recorded in the Trick binary data file. ",
" -help Print this message and exit. ",
"----------------------------------------------------------------------------"};
#define N_USAGE_LINES (sizeof(usage_doc)/sizeof(usage_doc[0]))
@ -56,20 +51,6 @@ int main(int argc, char *argv[]) {
(QString::compare(arg, "--help") == 0) ) {
usage();
exit(0);
} else if ((QString::compare(arg, "-csv") == 0)) {
out << "CSV selected." << endl;
} else if ((QString::compare(arg, "-varlist") == 0)) {
out << "Varlist selected." << endl;
} else if ((QString::compare(arg, "-o") == 0)) {
i++;
if (i < argc) {
arg = args.at(i);
outputName = arg;
} else {
out << programName << ": -o option requires a filename." << endl;
usage();
exit(1);
}
} else if ((QString::compare(arg.right(4), ".trk") == 0)) {
trkFilePath = arg;
} else {
@ -80,7 +61,6 @@ int main(int argc, char *argv[]) {
i++;
}
// If a .trk file has been specified
if (trkFilePath.isEmpty()) {
trkFilePath = QFileDialog::getOpenFileName(0, "Open Data File", ".", "Data Files (*.trk)");
}
@ -94,6 +74,5 @@ int main(int argc, char *argv[]) {
w1->show();
return app.exec();
}
}

View File

@ -32,4 +32,8 @@ SOURCES += CSV_Formatter.cpp \
TRK_DataLog.cpp \
Varlist_Formatter.cpp \
VarTableWidget.cpp
QT += widgets
# Inhibit creation of an Mac OS X App bundle.
CONFIG -= app_bundle