mirror of
https://github.com/nasa/trick.git
synced 2025-02-21 01:31:25 +00:00
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:
parent
8a4c8e3dd9
commit
b0b0cdf21b
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
};
|
||||
|
49
trick_source/data_products/Apps/trkConvert/README.md
Normal file
49
trick_source/data_products/Apps/trkConvert/README.md
Normal 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 &
|
||||
```
|
||||
|
||||

|
||||
|
||||
```
|
||||
% 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.
|
||||
|
||||

|
||||
The check boxes can be individually selected and cleared with a mouse-click.
|
||||
They can be collectively selected and cleared from the Edit menu.
|
||||
|
||||

|
||||
|
||||
## 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.
|
@ -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;
|
||||
}
|
||||
|
@ -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();
|
||||
|
BIN
trick_source/data_products/Apps/trkConvert/images/DocWindow.png
Normal file
BIN
trick_source/data_products/Apps/trkConvert/images/DocWindow.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 157 KiB |
BIN
trick_source/data_products/Apps/trkConvert/images/DocWindow2.png
Normal file
BIN
trick_source/data_products/Apps/trkConvert/images/DocWindow2.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 149 KiB |
Binary file not shown.
After Width: | Height: | Size: 101 KiB |
@ -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();
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user